diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c99f8c8b1ead6ed4dda21dd48859c82613eecaee Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index de8476d682d75cd8b5c92330bb3e92ac972c0da9..ece31c4873293323d80f7147d4548ac84cca9b47 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,20 @@ -# CodeChina +# CODEChina 欢迎使用CodeChina代码托管平台,本产品基于 Gitlab CE 版本 (13.2 stable) 开发并,目前版本提供了代码仓库管理、组织管理等基本功能,欢迎体验使用。 -体验使用过程中如果遇到任何问题,请联系我们。% +体验使用过程中如果遇到任何问题,请与我们联系。 + + +### 联系方式 + +- [点此向 CODEChina 产品提交 issue](https://codechina.csdn.net/codechina/beta/~/issues) + +- CODEChina微信群(1) + +- CODEChina微信群(2) + +- CODEChina观察员(1) Wechat / QQ + +- CODEChina观察员(2) Wechat / QQ \ No newline at end of file diff --git a/SUMMARY.md b/SUMMARY.md index 263112fe674f1783192fddec97e12681184558a8..c6d352208c0ee468e8a41f158f0b8bea57ad3f44 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,4 +1,5 @@ # Summary * [Introduction](README.md) +* [概览](docs/002.md) diff --git a/_book/docs/002.html b/_book/docs/002.html new file mode 100644 index 0000000000000000000000000000000000000000..0980c3c4e74895bb5607b4b0d3c89ccc7387d201 --- /dev/null +++ b/_book/docs/002.html @@ -0,0 +1,666 @@ + + + + + + + 概览 · GitBook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + +
+ +
+
文档目录
+ + + + + +
+ + +
+
在这篇文章中:
+
+ +
+
+ +
+ +
+ + + + + + + + +
+
+ +
+
+ +
+ +

帮助文档

+

访问codechina.csdn.net/docs,以获得优化的导航,可发现性和可读性.

+

概览

+

欢迎您使用CODEChina,如果您是 Github 或 GitLab 的初级用户,我们建议您从查看本文档开始学习如何使用 CODEChina。如果您熟悉以上两个产品中的一个或多个,您可以直接开始 CODEChina 产品,在产品中我们也会为您设置帮助提示,您可以随时回来查看我们的产品文档。

+ + + + + + + + + + + + + + + + + + + + + +
基础入门基本入门
用户文件熟悉CODEChina 中的功能和概念.管理员文件管理员入门.
为 CODEChina 做贡献为CODEChina开源贡献力量!是 Git 和 GitLab/GitHub 的新手吗?我们有资源可以帮助您入门.
从另一个平台进入 CODEChina?请查阅我们的便捷指南. 
+

热门话题

+

以下是我们推荐的一些主题:

+

计划

+

无论您使用 Waterfall,敏捷还是会话开发,CODEChina 均可简化您的协作工作流程.

+

使用 CODEChina 灵活的项目管理工具可视化,确定优先级,协调和跟踪进度.

+

以下文档与 DevOps 计划阶段有关:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
计划主题描述
Burndown Charts在特定的里程碑中观察项目的进度.
讨论问题,提交和合并请求中的线程,注释和可解决线程.
截止日期]跟踪发行期限.
Epics跟踪共享主题的问题组.
问题 ,包括机密问题发布和合并请求模板 ,和移动的问题项目问题并限制对问题的访问,并创建用于提交新问题和合并请求的模板. 此外,在项目之间转移问题.
标签分类问题或使用描述性标签合并请求.
里程碑设置发布问题和合并请求的里程碑,并带有可选的截止日期.
看板在 Scrum 或看板上显示问题.
快捷方式针对问题或合并请求的常见操作的快捷方式,而无需单击按钮或在WEB界面中使用下拉菜单.
关联 Issue在问题之间建立关系.
Roadmap可视化史诗般的时间表.
时间跟踪跟踪花费在问题和合并请求上的时间.
代办事项通过在简单仪表板上显示的时间顺序列表,跟踪需要注意的工作.
+

返回概览

+

新建

+

将源代码整合到一个易于管理和控制的分布式版本控制系统中 ,而不会中断您的工作流程.

+

CODEChina 存储库随附分支工具和访问控制,可为项目和代码的协作提供可扩展的单一事实来源.

+

以下文档与 DevOps 新建阶段有关:

+

项目和组织

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
创建主题-项目和组描述
全局搜索利用 Elasticsearch 在整个 CODEChina 实例上进行更快,更高级的代码搜索.
语法检索使用高级查询获得更具针对性的搜索结果.
Contribution analytics请参阅小组贡献者的详细统计信息.
创建fork项目,以及导入项目 实例之间创建,复制和移动项目.
锁定文件锁定文件以避免合并冲突.
组织 and 子组织分组组织您的项目.
Issue 分析检查每月创建了多少个问题.
项目 ,包括项目访问设置托管源代码,并控制项目的可见性和设置配置.
Search through CODEChina搜索问题,合并请求,项目,组和待办事项.
Web IDE在 WebIDE 中编辑文件.
Wikis使用内置的 Wiki 来管理您的文档.
+

返回概览

+

代码仓库

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
创建主题-代码仓库描述
分支默认分支如何在 CODEChina 中使用分支.
提交 and 署名提交处理提交,并使用 GPG 对您的提交进行签名.
创建分支创建上传文件,并创建目录创建分支,创建和上传文件以及创建目录.
删除已合并的分支合并更改后的批量删除分支.
文件模板通用文件的文件模板.
文件文件管理.
Jupyter Notebook 文件.ipynb文件的支持.
保护分支使用受保护的分支.
推送规则对项目推送的附加控制.
代码仓库在网页中管理源代码仓库.
镜像代码仓库推入或拉出外部的代码仓库
处理合并请求在提交时启动合并请求.
+

返回概览

+

合并请求

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
创建主题-合并请求描述
在本地处理合并请求在本地处理合并请求的提示.
Cherry-pick对更改进行 Cherry Pick.
Merge request thread resolution解析线程,将合并请求中的线程移至问题,并且仅在解决所有线程后才允许合并请求.
合并请求合并请求管理.
草稿合并请求防止合并草稿合并请求.
+

返回概览

+

刚开始使用Git/CODEChina/GitLab/Github?

+

使用新系统可能让您觉得难以入手,我们有以下文档可快速提升您的相关知识:

+ + + + + + + + + + + + + + + + + + + + + +
主题描述
Basics guides开始在命令行和 CODEChina 上工作.
Workflow overview利用最佳的工作流程增强您的工作流程.
Markdown高级格式化系统(Markdown)
+

返回概览

+

账户管理

+

了解有关帐户管理的更多信息:

+ + + + + + + + + + + + + + + + + + + + + +
主题描述
用户账号管理您的帐户.
账号验证具有两因素身份验证的帐户安全性,设置您的 SSH 密钥,并部署密钥以安全地访问您的项目.
用户权限了解项目中的每个角色可以做什么.
+

返回概览

+

Git 和 CODEChina

+

了解有关使用 Git 以及将 Git 与 CODEChina 结合使用的更多信息:

+ + + + + + + + + + + + + + + + + + + + + +
主题描述
GitGit 入门,分支策略,Git LFS 和高级用法.
Git cheat sheet下载描述最常用的 Git 操作的 PDF.
Work Flow使用 Work Flow 策略探索 Git 的精华.
+

返回概览

+

从另一个平台进入 CODEChina?

+

如果您是从另一个平台进入 CODEChina,您会发现以下有用信息:

+ + + + + + + + + + + + + + + + + +
主题描述
导入项目从 GitHub,Bitbucket,GitLab.com,FogBugz 和 SVN 导入项目.
从SVN迁移将 SVN 存储库转换为 Git 和 CODEChina.
+

返回概览

+

为CODEChina开源做贡献

+

CODEChina 是开源的,您可以通过以下方式为我们的开源社区做出贡献:

+ + + + + + + + + + + + + + + + + + + + + +
主题描述
开发如何在开发上做贡献.
协议贡献者许可协议.
文档如何在文档上做贡献.
+

返回概览

+ + + +
+ +
+
+
+ +

results matching ""

+
    + +
    +
    + +

    No results matching ""

    + +
    +
    +
    + +
    +
    + +
    + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/docs/003.md b/_book/docs/003.md new file mode 100644 index 0000000000000000000000000000000000000000..1ff4afc6e9be8753b25555b544d10175642d4abd --- /dev/null +++ b/_book/docs/003.md @@ -0,0 +1,76 @@ +# Installation + +> 原文:[https://docs.gitlab.com/ee/install/README.html](https://docs.gitlab.com/ee/install/README.html) + +* [Requirements](#requirements) +* [Installing GitLab using the Omnibus GitLab package (recommended)](#installing-gitlab-using-the-omnibus-gitlab-package-recommended) +* [Installing GitLab on Kubernetes via the GitLab Helm charts](#installing-gitlab-on-kubernetes-via-the-gitlab-helm-charts) +* [Installing GitLab with Docker](#installing-gitlab-with-docker) +* [Installing GitLab from source](#installing-gitlab-from-source) +* [Installing GitLab on cloud providers](#installing-gitlab-on-cloud-providers) +* [Securing your GitLab installation](#securing-your-gitlab-installation) + +# Installation[](#installation-core-only "Permalink") + +GitLab 可以安装在大多数 GNU / Linux 发行版以及许多云提供商中. 为了从 GitLab 获得最佳体验,您需要在性能,可靠性,易于管理(备份,升级和故障排除)以及托管成本之间取得平衡. + +根据平台的不同,可以通过多种方式安装 GitLab: + +1. **Omnibus GitLab** :官方的 deb / rpm 软件包,包含捆绑的 GitLab 及其依赖的各种组件,例如 PostgreSQL,Redis,Sidekiq 等. +2. **GitLab Helm 图表** :用于在 Kubernetes 上安装 GitLab 及其所有组件的云原生 Helm 图表. +3. **码头**工人:Omnibus GitLab 软件包码头化. +4. **来源** :从头开始安装 GitLab 及其所有组件. + +**如有疑问,请选择 Omnibus:** Omnibus GitLab 软件包已经成熟, [可扩展,](../administration/reference_architectures/index.html)并且已在 GitLab.com 上使用. 建议向熟悉 Kubernetes 的人使用 Helm 图表. + +## Requirements[](#requirements "Permalink") + +在安装 GitLab 之前,查看系统[要求](requirements.html)至关重要. 系统要求包括有关最低硬件,软件,数据库以及支持 GitLab 的其他要求的详细信息. + +## Installing GitLab using the Omnibus GitLab package (recommended)[](#installing-gitlab-using-the-omnibus-gitlab-package-recommended "Permalink") + +Omnibus GitLab 软件包使用我们的官方 deb / rpm 存储库. 建议大多数用户使用. + +如果您需要更多的灵活性和弹性,我们建议按照[参考架构文档](../administration/reference_architectures/index.html)中的[说明](../administration/reference_architectures/index.html)部署 GitLab. + +[**> Install GitLab using the Omnibus GitLab package.**](https://about.gitlab.com/install/) + +## Installing GitLab on Kubernetes via the GitLab Helm charts[](#installing-gitlab-on-kubernetes-via-the-gitlab-helm-charts "Permalink") + +**需要 Kubernetes 经验:**我们建议您先熟悉 Kubernetes,然后再使用 Kubernetes 在生产中部署 GitLab. 管理,可观察性和某些概念的方法与传统部署不同. + +在 Kubernetes 上安装 GitLab 时,需要注意一些折衷: + +* 管理和故障排除需要 Kubernetes 知识. +* 对于较小的安装,它可能会更昂贵. 默认安装比单节点 Omnibus 部署需要更多的资源,因为大多数服务都是以冗余方式部署的. +* 有一些功能[限制需要注意](https://docs.gitlab.com/charts/) . + +[**> Install GitLab on Kubernetes using the GitLab Helm charts.**](https://docs.gitlab.com/charts/) + +## Installing GitLab with Docker[](#installing-gitlab-with-docker "Permalink") + +GitLab 基于 Omnibus GitLab 软件包维护一组正式的 Docker 映像. + +[**> Install GitLab using the official GitLab Docker images.**](docker.html) + +## Installing GitLab from source[](#installing-gitlab-from-source "Permalink") + +如果您的发行版中没有 Omnibus GitLab 软件包,则可以从源代码安装 GitLab:对于* BSD 等不受支持的系统很有用. 有关目录结构的概述,请阅读[结构文档](structure.html) . + +[**> Install GitLab from source.**](installation.html) + +## Installing GitLab on cloud providers[](#installing-gitlab-on-cloud-providers "Permalink") + +只要有云提供商支持,就可以使用上述任何一种方法将 GitLab 安装在各种云提供商上. + +* [在 AWS 上](aws/index.html)安装:使用 GitLab 提供的社区 AMI 在 AWS [上](aws/index.html)安装 Omnibus GitLab. +* [在 Google Cloud Platform 上安装 GitLab](google_cloud_platform/index.html) :在 GCP 中的 VM 上安装 Omnibus GitLab. +* [在 Azure 上](azure/index.html)安装 GitLab:从 Azure 市场安装 Omnibus GitLab. +* [在 OpenShift 上](https://docs.gitlab.com/charts/installation/cloud/openshift.html)安装 GitLab:通过使用 GitLab 的 Helm 图表在 OpenShift [上](https://docs.gitlab.com/charts/installation/cloud/openshift.html)安装 GitLab. +* [在 DC / OS 上](https://d2iq.com/blog/gitlab-dcos)安装 GitLab:通过[GitLab-Mesosphere 集成](https://about.gitlab.com/blog/2016/09/16/announcing-gitlab-and-mesosphere/)在 Mesosphere DC / OS 上安装 GitLab. +* [在 DigitalOcean 上安装 GitLab:在 DigitalOcean 上](https://about.gitlab.com/blog/2016/04/27/getting-started-with-gitlab-and-digitalocean/)安装 Omnibus GitLab. +* *仅测试!* [DigitalOcean 和 Docker Machine](digitaloceandocker.html) :使用 Docker Machine 在 DigitalOcean 上快速测试任何版本的 GitLab. + +## Securing your GitLab installation[](#securing-your-gitlab-installation "Permalink") + +完成安装后,请查看我们[建议的做法以保护您的 GitLab 实例](../security/README.html#securing-your-gitlab-installation) . \ No newline at end of file diff --git a/_book/docs/004.md b/_book/docs/004.md new file mode 100644 index 0000000000000000000000000000000000000000..195670cc6a4867e74e3110db9019017296083cef --- /dev/null +++ b/_book/docs/004.md @@ -0,0 +1,245 @@ +# Requirements + +> 原文:[https://docs.gitlab.com/ee/install/requirements.html](https://docs.gitlab.com/ee/install/requirements.html) + +* [Operating Systems](#operating-systems) + * [Supported Linux distributions](#supported-linux-distributions) + * [Unsupported Linux distributions and Unix-like operating systems](#unsupported-linux-distributions-and-unix-like-operating-systems) + * [Microsoft Windows](#microsoft-windows) +* [Software requirements](#software-requirements) + * [Ruby versions](#ruby-versions) + * [Go versions](#go-versions) + * [Git versions](#git-versions) + * [Node.js versions](#nodejs-versions) +* [Redis versions](#redis-versions) +* [Hardware requirements](#hardware-requirements) + * [Storage](#storage) + * [CPU](#cpu) + * [Memory](#memory) +* [Database](#database) + * [PostgreSQL Requirements](#postgresql-requirements) + * [Additional requirements for GitLab Geo](#additional-requirements-for-gitlab-geo) +* [Puma settings](#puma-settings) + * [Puma workers](#puma-workers) + * [Puma threads](#puma-threads) +* [Unicorn Workers](#unicorn-workers) +* [Redis and Sidekiq](#redis-and-sidekiq) +* [Prometheus and its exporters](#prometheus-and-its-exporters) +* [GitLab Runner](#gitlab-runner) +* [Supported web browsers](#supported-web-browsers) + +# Requirements[](#requirements "Permalink") + +该页面包含有关受支持的操作系统以及安装和使用 GitLab 所需的硬件要求的有用信息. + +## Operating Systems[](#operating-systems "Permalink") + +### Supported Linux distributions[](#supported-linux-distributions "Permalink") + +* Ubuntu(16.04 / 18.04) +* Debian(8/9/10) +* CentOS 的(6/7/8) +* openSUSE(Leap 15.1 / Enterprise Server 12.2) +* 红帽企业版 Linux(请使用 CentOS 软件包和说明) +* 科学版 Linux(请使用 CentOS 软件包和说明) +* Oracle Linux(请使用 CentOS 软件包和说明) + +有关安装选项,请参见[主要安装页面](README.html) . + +### Unsupported Linux distributions and Unix-like operating systems[](#unsupported-linux-distributions-and-unix-like-operating-systems "Permalink") + +* Arch Linux +* Fedora +* FreeBSD +* Gentoo +* macOS + +可以在这些操作系统上安装 GitLab,但不支持. 请参阅[源安装指南](installation.html)和[安装指南](https://about.gitlab.com/install/)以获取更多信息. + +### Microsoft Windows[](#microsoft-windows "Permalink") + +GitLab 是针对基于 Linux 的操作系统开发的. 它**不能**在 Microsoft Windows 上运行,并且我们没有计划在不久的将来支持它. 有关最新的开发状态,请查看此[问题](https://gitlab.com/gitlab-org/gitlab/-/issues/22337) . 请考虑使用虚拟机运行 GitLab. + +## Software requirements[](#software-requirements "Permalink") + +### Ruby versions[](#ruby-versions "Permalink") + +GitLab 需要 Ruby(MRI)2.6\. 从 GitLab 12.2 开始,我们不再支持 Ruby 2.5 及更低版本. + +您必须使用 Ruby 的标准 MRI 实现. 我们喜欢[JRuby](https://www.jruby.org/)和[Rubinius](https://github.com/rubinius/rubinius#the-rubinius-language-platform) ,但是 GitLab 需要几个具有本机扩展的 Gems. + +### Go versions[](#go-versions "Permalink") + +所需的最低 Go 版本为 1.13. + +### Git versions[](#git-versions "Permalink") + +从 GitLab 13.1: + +* 需要 Git 2.25.x 及更高版本. +* [建议使用](https://gitlab.com/gitlab-org/gitaly/-/issues/2829) Git 2.27.x 及更高版本. + +### Node.js versions[](#nodejs-versions "Permalink") + +从 GitLab 12.9 开始,我们仅支持 node.js 10.13.0 或更高版本,并且我们放弃了对 node.js 8 的支持.(在 GitLab 11.8 中取消了对 node.js 6 的支持). + +我们建议使用 Node 12.x,因为它速度更快. + +GitLab 使用[Webpack](https://webpack.js.org/)编译前端资产,这需要最低版本的 Node.js 10.13.0. + +您可以使用`node -v`检查您正在运行哪个版本. 如果您运行的版本低于`v10.13.0` ,则需要将其更新为较新的版本. 您可以在[Node.js 网站上](https://s0nodejs0org.icopy.site/en/download/)找到从社区维护的软件包安装或从源代码进行编译的[说明](https://s0nodejs0org.icopy.site/en/download/) . + +## Redis versions[](#redis-versions "Permalink") + +GitLab 需要 Redis 5.0+. 从 GitLab 13.0 开始,不支持较低版本. + +## Hardware requirements[](#hardware-requirements "Permalink") + +### Storage[](#storage "Permalink") + +所需的硬盘空间在很大程度上取决于要存储在 GitLab 中的存储库的大小,但是根据*经验,*您应该至少具有与所有存储库加起来一样大的可用空间. + +如果您将来想灵活地增加硬盘驱动器空间,请考虑使用[逻辑卷管理(LVM)进行](https://en.wikipedia.org/wiki/Logical_volume_management)安装,以便在需要时可以添加更多硬盘驱动器. + +除本地硬盘驱动器外,您还可以安装支持网络文件系统(NFS)协议的卷. 该卷可能位于文件服务器,网络连接存储(NAS)设备,存储区域网络(SAN)或 Amazon Web Services(AWS)弹性块存储(EBS)卷上. + +如果您有足够的 RAM 和最新的 CPU,则 GitLab 的速度主要受硬盘搜索时间限制. 具有快速驱动器(7200 RPM 及更高版本)或固态驱动器(SSD)将提高 GitLab 的响应速度. + +**注意:**由于文件系统性能可能会影响 GitLab 的整体性能,因此[我们不建议使用 AWS EFS 进行存储](../administration/high_availability/nfs.html#avoid-using-awss-elastic-file-system-efs) . + +### CPU[](#cpu "Permalink") + +CPU 需求取决于用户数量和预期的工作量. 您的确切需求可能更多,具体取决于您的工作量. 您的工作负载受以下因素影响,这些因素包括但不限于:用户的活跃程度,使用的自动化程度,镜像和回购/更改大小. + +以下是一些示例 GitLab 用户库大小的建议最低 CPU 硬件指南. + +* **4 芯**是核心的**推荐**最小数目和多达 500 个用户支持 +* 8 个内核最多支持 1000 个用户 +* 更多用户? 查阅[参考架构页面](../administration/reference_architectures/index.html) + +### Memory[](#memory "Permalink") + +内存需求取决于用户数量和预期的工作量. 您的确切需求可能更多,具体取决于您的工作量. 您的工作负载受以下因素影响,这些因素包括但不限于:用户的活跃程度,使用的自动化程度,镜像和回购/更改大小. + +以下是一些示例 GitLab 用户库大小的建议最低内存硬件指南. + +* **4GB RAM**是**必需的**最小内存大小,最多可支持 500 个用户 + * 我们的[内存团队](https://about.gitlab.com/handbook/engineering/development/enablement/memory/)正在努力减少内存需求. +* 8GB RAM 最多支持 1000 个用户 +* 更多用户? 查阅[参考架构页面](../administration/reference_architectures/index.html) + +除上述之外,即使您当前有足够的可用 RAM,我们通常也建议在服务器上至少有 2GB 的交换空间. 如果您的可用内存发生更改,那么进行交换将有助于减少发生错误的机会. 我们还建议将内核的 swappiness 设置配置为较低的值(例如`10`以充分利用您的 RAM,同时在需要时仍可使用交换功能. + +## Database[](#database "Permalink") + +PostgreSQL 是唯一受支持的数据库,与 Omnibus GitLab 软件包捆绑在一起. 您也可以使用[外部 PostgreSQL 数据库](https://docs.gitlab.com/omnibus/settings/database.html) . 在 GitLab 12.1 中删除了对 MySQL 的支持. 建议在 MySQL / MariaDB 上使用 GitLab 的现有用户在升级之前[迁移到 PostgreSQL](../update/mysql_to_postgresql.html) . + +### PostgreSQL Requirements[](#postgresql-requirements "Permalink") + +运行 PostgreSQL 的服务器应*至少有* 5-10 GB 的可用存储空间,尽管确切的要求[取决于用户数量](../administration/reference_architectures/index.html) . + +我们强烈建议用户使用下面指定的最低 PostgreSQL 版本,因为这些是用于开发和测试的版本. + +| GitLab 版本 | 最低 PostgreSQL 版本 | +| --- | --- | +| 10.0 | 9.6 | +| 12.10 | 11 | +| 13.0 | 11 | + +您还必须确保将`pg_trgm`扩展加载到每个 GitLab 数据库中. [可以](https://s0www0postgresql0org.icopy.site/docs/11/sql-createextension.html)使用 PostgreSQL 超级用户[启用](https://s0www0postgresql0org.icopy.site/docs/11/sql-createextension.html)此扩展. + +在某些系统上,您可能需要安装一个附加软件包(例如`postgresql-contrib` ),此扩展才可以使用. + +**注意:** [在 GitLab 13.0 中已删除了](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#postgresql-11-is-now-the-minimum-required-version-to-install-gitlab)对[PostgreSQL 9.6 和 10 的](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#postgresql-11-is-now-the-minimum-required-version-to-install-gitlab)支持,因此 GitLab 可以从 PostgreSQL 11 的改进(例如分区)中受益. 有关过渡到 PostgreSQL 12 的时间表,请参阅[相关的 epic](https://gitlab.com/groups/gitlab-org/-/epics/2184) . + +#### Additional requirements for GitLab Geo[](#additional-requirements-for-gitlab-geo "Permalink") + +如果您使用的是[GitLab Geo](../administration/geo/replication/index.html) : + +* 我们强烈建议您在积极开发和测试的情况下运行由 Omnibus 管理的实例. 我们的目标是与大多数外部数据库(不由 Omnibus 管理)兼容(例如, [AWS Relational Database Service(RDS)](https://aws.amazon.com/rds/) ),但我们不保证兼容性. +* 您还必须确保将`postgres_fdw`扩展加载到每个 GitLab 数据库中. [可以](https://s0www0postgresql0org.icopy.site/docs/11/sql-createextension.html)使用 PostgreSQL 超级用户[启用](https://s0www0postgresql0org.icopy.site/docs/11/sql-createextension.html)此扩展. + +## Puma settings[](#puma-settings "Permalink") + +建议的 Puma 设置取决于运行它的基础结构. Omnibus GitLab 默认为建议的 Puma 设置. 无论安装方法如何,都可以调整 Puma 设置. + +如果您使用的是 Omnibus GitLab,请参阅[Puma 设置](https://docs.gitlab.com/omnibus/settings/puma.html)以获取有关更改 Puma 设置的说明. 如果您使用的是 GitLab Helm 图表,请参阅[Webservice 图表](https://docs.gitlab.com/charts/charts/gitlab/webservice/index.html) . + +### Puma workers[](#puma-workers "Permalink") + +推荐的工人人数是根据以下最高者计算得出的: + +* `2` +* CPU 核心数-1 + +例如,一个具有 4 个核心的节点应配置 3 个 Puma Worker. + +如果可以提供足够的 CPU 和内存容量,则可以增加 Puma worker 的数量. 数量更多的 Puma 工作人员通常将有助于减少应用程序的响应时间并提高处理并行请求的能力. 您必须执行测试以验证基础架构的最佳设置. + +### Puma threads[](#puma-threads "Permalink") + +推荐的线程数取决于几个因素,包括总内存和[传统 Rugged 代码的使用](../development/gitaly.html#legacy-rugged-code) . + +* 如果操作系统最多具有 2 GB 的内存,则建议的线程数为`1` . 较高的值将导致过多的交换,并降低性能. +* If legacy Rugged code is in use, the recommended number of threads is `1`. +* 在所有其他情况下,建议的线程数为`4` . 由于[Ruby MRI 多线程的](https://en.wikipedia.org/wiki/Global_interpreter_lock)工作方式,我们不建议设置更高的值. + +## Unicorn Workers[](#unicorn-workers "Permalink") + +对于大多数情况,我们建议使用:(CPU 内核* 1.5)+ 1 = Unicorn worker. 例如,一个具有 4 个核心的节点将有 7 个 Unicorn worker. + +对于所有 2GB 以上的计算机,我们建议至少三名 Unicorn 工人. 如果您有一台 1GB 的计算机,我们建议仅配置两个 Unicorn worker,以防止过度交换. + +只要您有足够的可用 CPU 和内存容量,就可以增加 Unicorn worker 的数量,这通常将有助于减少应用程序的响应时间并提高处理并行请求的能力. + +要在拥有 Omnibus 软件包(默认为上述建议)时更改 Unicorn worker,请参阅[Omnibus GitLab 文档中的 Unicorn 设置](https://docs.gitlab.com/omnibus/settings/unicorn.html) . + +## Redis and Sidekiq[](#redis-and-sidekiq "Permalink") + +Redis 存储所有用户会话和后台任务队列. Redis 的存储要求极低,每个用户大约 25kB. Sidekiq 使用多线程进程来处理后台作业. 此过程从整个 Rails 堆栈(200MB +)开始,但是由于内存泄漏,它可能随着时间的推移而增长. 在非常活跃的服务器(10,000 个活跃用户)上,Sidekiq 进程可以使用 1GB +的内存. + +## Prometheus and its exporters[](#prometheus-and-its-exporters "Permalink") + +从 Omnibus GitLab 9.0 起,默认启用[Prometheus](https://s0prometheus0io.icopy.site)及其相关出口商,以实现对 GitLab 的轻松和深度监控. 使用默认设置,这些进程将消耗大约 200MB 的内存. + +如果您想禁用 Prometheus 及其出口商或阅读有关它的更多信息,请查阅[Prometheus 文档](../administration/monitoring/prometheus/index.html) . + +## GitLab Runner[](#gitlab-runner "Permalink") + +强烈建议不要在打算安装 GitLab 的同一台计算机上安装 GitLab Runner. 根据您决定配置 GitLab Runner 的方式以及用于在 CI 环境中运行应用程序的工具的不同,GitLab Runner 会消耗大量可用内存. + +如果您决定在同一台计算机上运行 GitLab Runner 和 GitLab Rails 应用程序,则上面提供的内存消耗计算将无效. + +由于[安全原因](https://docs.gitlab.com/runner/security/) ,将所有内容都安装在一台机器上也不安全,尤其是当您计划将 Shell executor 与 GitLab Runner 一起使用时. + +如果您打算使用 CI 功能,我们建议为每个 GitLab Runner 使用单独的机器. GitLab Runner 服务器要求取决于: + +* 您在 GitLab Runner 上配置的[执行程序](https://docs.gitlab.com/runner/executors/)的类型. +* 运行构建作业所需的资源. +* 作业并发设置. + +由于作业的性质因每个用例而异,因此您将需要通过调整作业并发来进行实验以获得最佳设置. + +作为参考,对 GitLab.com 的[自动缩放共享](../user/gitlab_com/index.html#shared-runners)运行器进行了配置,以便**单个作业**将在**单个实例中**运行,并具有: + +* 1vCPU. +* 3.75GB 的 RAM. + +## Supported web browsers[](#supported-web-browsers "Permalink") + +**警告:**在 GitLab 13.0(2020 年 5 月)中,我们删除了对 Internet Explorer 11 的官方支持.在 GitLab 13.4 发行版(2020 年 9 月)中,我们将删除了所有支持 Internet Explorer 11 的代码.您可以提供[有关此问题的](https://gitlab.com/gitlab-org/gitlab/-/issues/197987)反馈[,](https://gitlab.com/gitlab-org/gitlab/-/issues/197987)也可以通过通常的支持渠道. + +GitLab supports the following web browsers: + +* [Mozilla Firefox](https://www.mozilla.org/en-US/firefox/new/) +* [Google Chrome](https://www.google.com/chrome/) +* [Chromium](https://www.chromium.org/getting-involved/dev-channel) +* [Apple Safari](https://www.apple.com/safari/) +* [Microsoft Edge](https://www.microsoft.com/en-us/edge) + +对于列出的 Web 浏览器,GitLab 支持: + +* 当前和以前的主要浏览器版本(Internet Explorer 除外). +* 受支持的主要版本的当前次要版本. + +**注意:**我们不支持在浏览器中禁用 JavaScript 的情况下运行 GitLab,并且将来也没有支持该计划的计划,因为我们具有诸如 Issue Boards 之类的功能,这些功能广泛需要 JavaScript. \ No newline at end of file diff --git a/_book/docs/005.md b/_book/docs/005.md new file mode 100644 index 0000000000000000000000000000000000000000..0b8423e6516d336a1fee5bc0b1837fdb766a6dc5 --- /dev/null +++ b/_book/docs/005.md @@ -0,0 +1 @@ +> 原文:[https://about.gitlab.com/install/](https://about.gitlab.com/install/) \ No newline at end of file diff --git a/_book/docs/006.md b/_book/docs/006.md new file mode 100644 index 0000000000000000000000000000000000000000..f9d6aa3fc2263d2d747eeecfbbe0b4d004d4ed61 --- /dev/null +++ b/_book/docs/006.md @@ -0,0 +1,181 @@ +# GitLab cloud native Helm Chart + +> 原文:[https://docs.gitlab.com/charts/](https://docs.gitlab.com/charts/) + +* [Introduction](#introduction) +* [Limitations](#limitations) +* [GitLab Helm chart quick start guide](#gitlab-helm-chart-quick-start-guide) +* [Troubleshooting](#troubleshooting) +* [Installation](#installation) + * [Global settings](#global-settings) + * [Complete properties list](#complete-properties-list) +* [Upgrading](#upgrading) +* [Uninstall](#uninstall) +* [Advanced](#advanced) + * [Advanced Configuration](#advanced-configuration) + * [Migrate from Omnibus GitLab to Kubernetes](#migrate-from-omnibus-gitlab-to-kubernetes) +* [Architecture](#architecture) +* [Development](#development) + * [GitLab version mappings](#gitlab-version-mappings) + * [Contributing](#contributing) + +# GitLab cloud native Helm Chart[](#gitlab-cloud-native-helm-chart "Permalink") + +这是在云本机环境上安装 GitLab 的官方,推荐和受支持的方法. + +**注意:**不必在 Kubernetes 上安装 GitLab 即可使用[GitLab Kubernetes 集成](https://docs.gitlab.com/ee/user/project/clusters/) . + +## Introduction[](#introduction "Permalink") + +The `gitlab/gitlab` chart is the best way to operate GitLab on Kubernetes. This chart contains all the required components to get started, and can scale to large deployments. + +该图表包括完整的体验所需的所有组件,但是每个部分都可以单独安装. + +* GitLab 核心组件: + * [NGINX 入口](charts/nginx/index.html) + * [登记处](charts/registry/index.html) + * [亚搏体育 app](charts/gitlab/gitaly/index.html) / [Gitaly](charts/gitlab/gitaly/index.html) + * GitLab / [GitLab 出口商](charts/gitlab/gitlab-exporter/index.html) + * GitLab / [GitLab Grafana](charts/gitlab/gitlab-grafana/index.html) + * GitLab / [GitLab 外壳](charts/gitlab/gitlab-shell/index.html) + * GitLab / [迁移](charts/gitlab/migrations/index.html) + * [亚搏体育 app](charts/gitlab/sidekiq/index.html) / [Sidekiq](charts/gitlab/sidekiq/index.html) + * GitLab / [web 服务](charts/gitlab/webservice/index.html) +* 可选依赖项: + * [PostgreSQL 的](https://hub.helm.sh/charts/bitnami/postgresql) + * [雷迪斯](https://hub.helm.sh/charts/bitnami/redis) + * [MinIO](charts/minio/index.html) +* 可选的补充: + * [普罗米修斯](https://hub.helm.sh/charts/stable/prometheus) + * [格拉法纳](https://hub.helm.sh/charts/stable/grafana) + * 使用 Kubernetes 执行器的[*非特权*](https://docs.gitlab.com/runner/install/kubernetes.html) [GitLab Runner](https://docs.gitlab.com/runner/) + * 使用[Jetstack](https://www.jetstack.io/)的[cert-manager](https://cert-manager.io/docs/)通过[Let's Encrypt](https://letsencrypt.org/)自动提供 SSL + +## Limitations[](#limitations "Permalink") + +使用 Helm 图表当前无法使用 GitLab 的某些功能: + +* [GitLab Pages](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/37) +* [Smartcard authentication](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/988) + +数据库限制: + +* GitLab Geo 功能[需要使用外部数据库服务](installation/deployment.html#postgresql) . + +## GitLab Helm chart quick start guide[](#gitlab-helm-chart-quick-start-guide "Permalink") + +对于那些希望在*非生产*用例中尽快建立并运行这些图表的人,我们提供了概念验证(PoC)部署[快速入门指南](quickstart/index.html) . + +本指南将通过部署这些图表使用默认值和功能引导用户,但*不*符合生产做好准备的要求. 如果希望在持续负载下将这些图表部署到生产中,则应遵循以下完整的[安装指南](#installation) . + +## Troubleshooting[](#troubleshooting "Permalink") + +我们已尽力使这些图表尽可能地无缝,但偶尔也会出现无法控制的问题. 我们已收集了一些常见问题的疑难解答技巧. 在提出[问题](https://gitlab.com/gitlab-org/charts/gitlab/-/issues)之前,请先检查这些内容,并通过提出[合并请求](https://gitlab.com/gitlab-org/charts/gitlab/-/merge_requests)随意添加它们! + +See [Troubleshooting](troubleshooting/index.html). + +## Installation[](#installation "Permalink") + +`gitlab/gitlab`图表包含所有必需的依赖项. 在生产中,您可能需要启用可选功能或[高级配置](#advanced-configuration) . 本指南深入介绍了这些图表的所有选项和功能. + +如果您只是想部署概念验证进行测试,我们强烈建议您遵循我们的[快速入门](#gitlab-helm-chart-quick-start-guide)进行第一次迭代. + +1. [Preparation](installation/index.html) +2. [Deployment](installation/deployment.html) + +### Global settings[](#global-settings "Permalink") + +这些图表的复杂性使其可以使用全局属性. 有许多通用全局设置适用于多个图表. 有关不同的全局配置值及其应用程序的详细信息,请参见[Globals 文档](charts/globals.html) . + +### Complete properties list[](#complete-properties-list "Permalink") + +经常要求我们将所有可能的属性表直接放入此索引. 这些图表是规模*庞大* ,并作为属性的这种数量超过背景的量,我们在这里很舒服配售. 请参阅我们(几乎) [全面的属性和默认值列表](installation/command-line-options.html) . + +## Upgrading[](#upgrading "Permalink") + +安装了 GitLab 图表后,应使用`helm upgrade`完成配置更改和图表更新: + +``` +helm repo add gitlab https://charts.gitlab.io/ +helm repo update +helm get values gitlab > gitlab.yaml +helm upgrade gitlab gitlab/gitlab -f gitlab.yaml +``` + +有关更多详细信息,请参阅[升级](installation/upgrade.html) . + +## Uninstall[](#uninstall "Permalink") + +要卸载 GitLab Chart,请运行以下命令: + +``` +helm uninstall gitlab +``` + +**注意:**在 Helm v2 中,您需要使用`helm delete --purge gitlab`命令. + +为了连续起见,这些图表具有一些在执行`helm uninstall`时不会删除的 Kubernetes 对象. 这些是我们要求您有*意识地*删除的项目,因为它们会影响您应选择的重新部署. + +* 用于状态数据的 PVC,必须*自觉*删除 + * Gitaly:这是您的存储库数据. + * PostgreSQL(如果内部):这是您的元数据. + * Redis(如果内部):这是缓存和作业队列,可以安全地将其删除. +* 机密(如果由我们的共享机密工作生成). 这些图表旨在避免直接通过 Helm 生成 Kubernetes 秘密. 因此,Helm 无法删除它们. 它们包含密码,加密机密等.它们不应被恶意破坏. +* ConfigMaps + * `ingress-controller-leader-RELEASE-nginx` :这是由 NGINX Ingress 控制器本身生成的,不在我们图表的控制范围内. 可以安全地将其删除. + +PVC 和秘密将设置`release`标签,因此您可以通过以下方式找到它们: + +``` +kubectl get pvc,secret -lrelease=gitlab +``` + +## Advanced[](#advanced "Permalink") + +除了在云本机环境中进行 GitLab 的基本部署以外,还可以进行更复杂的配置. 本节为需要进一步计划的任务提供指导,例如大规模部署或从 Omnibus GitLab 迁移. + +### Advanced Configuration[](#advanced-configuration "Permalink") + +高级和大规模部署具有利用外部服务,扩展功能和备用提供程序的能力. + +高级配置示例: + +* 亚搏体育 app Geo +* 外部对象存储提供者 +* 外部 PostgreSQL,Redis,Gitaly +* 外部入口提供商 + +See [Advanced Configuration](advanced/index.html). + +### Migrate from Omnibus GitLab to Kubernetes[](#migrate-from-omnibus-gitlab-to-kubernetes "Permalink") + +可以从[Omnibus GitLab](https://docs.gitlab.com/omnibus/)迁移到这些图表. 这样做通常需要将现有数据迁移到对象存储,因此是[高级配置](advanced/index.html) . + +要将现有的 Omnibus GitLab 实例迁移到这些图表,请遵循[迁移文档](installation/migration/index.html) . + +## Architecture[](#architecture "Permalink") + +这些图表非常复杂,因为它们可以协调整个应用程序套件的部署. 我们提供有关目标,结构,设计决策和资源消耗的[文档](architecture/index.html) . + +## Development[](#development "Permalink") + +对于那些有兴趣为这些图表做出贡献的人,我们提供了涵盖该项目工作范围的开发指南. 它们可以在[开发中](development/index.html) . + +### GitLab version mappings[](#gitlab-version-mappings "Permalink") + +GitLab 图表与 GitLab 本身的版本号不同. 预计可能需要在图表中引入一些重大更改,这些更改可能会导致重大版本颠簸,而对这些更改的要求可能会完全阻止这些图表上的其他开发,直到完成为止. + +要快速查看它们映射到的`gitlab`图表版本和 GitLab 版本的完整列表,请对[Helm](installation/tools.html#helm)发出以下命令: + +``` +helm repo add gitlab https://charts.gitlab.io/ +helm search repo -l gitlab/gitlab +``` + +**注意**对于 Helm v2,搜索命令将为`helm search -l gitlab/gitlab` + +有关更多信息,请访问[版本映射 docs](installation/version_mappings.html) . + +### Contributing[](#contributing "Permalink") + +除了我们的[贡献准则](https://gitlab.com/gitlab-org/charts/gitlab/tree/master/CONTRIBUTING.md)之外,请参阅[开发者文档](development/index.html)以了解如何对 GitLab 图表[做出贡献](https://gitlab.com/gitlab-org/charts/gitlab/tree/master/CONTRIBUTING.md) . \ No newline at end of file diff --git a/_book/docs/007.md b/_book/docs/007.md new file mode 100644 index 0000000000000000000000000000000000000000..1465da9585ee471ca3bd3eaed42a06e3ea53ff7d --- /dev/null +++ b/_book/docs/007.md @@ -0,0 +1,26 @@ +# Install GitLab with Docker + +> 原文:[https://docs.gitlab.com/ee/install/docker.html](https://docs.gitlab.com/ee/install/docker.html) + +* [Omnibus GitLab based images](#omnibus-gitlab-based-images) +* [Cloud native images](#cloud-native-images) + +# Install GitLab with Docker[](#install-gitlab-with-docker "Permalink") + +在过去的几年中, [Docker](https://www.docker.com)和容器技术一直在改变软件世界. 它们将本地执行的性能和效率与虚拟化的抽象性,安全性和不变性结合在一起. + +GitLab 提供了官方的 Docker 映像,使您可以在操作 GitLab 实例时轻松利用容器化的优势. + +## Omnibus GitLab based images[](#omnibus-gitlab-based-images "Permalink") + +GitLab 基于我们的[Omnibus GitLab 软件包](https://docs.gitlab.com/omnibus/README.html)维护了一组[正式的 Docker 映像](https://hub.docker.com/u/gitlab) . 这些图像包括: + +* [GitLab Community Edition](https://hub.docker.com/r/gitlab/gitlab-ce/) +* [GitLab Enterprise Edition](https://hub.docker.com/r/gitlab/gitlab-ee/) +* [GitLab Runner](https://hub.docker.com/r/gitlab/gitlab-runner/) + +提供了有关这些映像的[完整用法指南](https://docs.gitlab.com/omnibus/docker/) ,以及[用于构建映像](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/docker)的[Dockerfile](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/docker) . + +## Cloud native images[](#cloud-native-images "Permalink") + +manbetx 客户端打不开也正在努力向[容器](https://docs.gitlab.com/charts/)的[云本机集,](https://docs.gitlab.com/charts/)每个组件服务具有单个映像. 我们打算将这些图像最终替换为[基于 Omnibus GitLab 的图像](#omnibus-gitlab-based-images) . \ No newline at end of file diff --git a/_book/docs/008.md b/_book/docs/008.md new file mode 100644 index 0000000000000000000000000000000000000000..6d91a29ea7ca76107f3c10e1534839edf4189a68 --- /dev/null +++ b/_book/docs/008.md @@ -0,0 +1,1010 @@ +# Installation from source + +> 原文:[https://docs.gitlab.com/ee/install/installation.html](https://docs.gitlab.com/ee/install/installation.html) + +* [Consider the Omnibus package installation](#consider-the-omnibus-package-installation) +* [Select a version to install](#select-a-version-to-install) +* [GitLab directory structure](#gitlab-directory-structure) +* [Overview](#overview) +* [1\. Packages and dependencies](#1-packages-and-dependencies) +* [2\. Ruby](#2-ruby) +* [3\. Go](#3-go) +* [4\. Node](#4-node) +* [5\. System users](#5-system-users) +* [6\. Database](#6-database) +* [7\. Redis](#7-redis) +* [8\. GitLab](#8-gitlab) + * [Clone the Source](#clone-the-source) + * [Configure It](#configure-it) + * [Configure GitLab DB Settings](#configure-gitlab-db-settings) + * [Install Gems](#install-gems) + * [Install GitLab Shell](#install-gitlab-shell) + * [Install GitLab Workhorse](#install-gitlab-workhorse) + * [Install GitLab-Elasticsearch-indexer on Enterprise Edition](#install-gitlab-elasticsearch-indexer-on-enterprise-edition) + * [Install GitLab Pages](#install-gitlab-pages) + * [Install Gitaly](#install-gitaly) + * [Start Gitaly](#start-gitaly) + * [Initialize Database and Activate Advanced Features](#initialize-database-and-activate-advanced-features) + * [Secure secrets.yml](#secure-secretsyml) + * [Install Init Script](#install-init-script) + * [Set up Logrotate](#set-up-logrotate) + * [Check Application Status](#check-application-status) + * [Compile GetText PO files](#compile-gettext-po-files) + * [Compile Assets](#compile-assets) + * [Start Your GitLab Instance](#start-your-gitlab-instance) +* [9\. NGINX](#9-nginx) + * [Installation](#installation) + * [Site Configuration](#site-configuration) + * [Test Configuration](#test-configuration) + * [Restart](#restart) +* [Post-install](#post-install) + * [Double-check Application Status](#double-check-application-status) + * [Initial Login](#initial-login) +* [Advanced Setup Tips](#advanced-setup-tips) + * [Relative URL support](#relative-url-support) + * [Using HTTPS](#using-https) + * [Enable Reply by email](#enable-reply-by-email) + * [LDAP Authentication](#ldap-authentication) + * [Using Custom OmniAuth Providers](#using-custom-omniauth-providers) + * [Build your projects](#build-your-projects) + * [Adding your Trusted Proxies](#adding-your-trusted-proxies) + * [Custom Redis Connection](#custom-redis-connection) + * [Custom SSH Connection](#custom-ssh-connection) + * [Additional Markup Styles](#additional-markup-styles) + * [Using Unicorn](#using-unicorn) + * [Using Sidekiq instead of Sidekiq Cluster](#using-sidekiq-instead-of-sidekiq-cluster) +* [Troubleshooting](#troubleshooting) + * [“You appear to have cloned an empty repository.”](#you-appear-to-have-cloned-an-empty-repository) + * [`google-protobuf` “LoadError: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14’ not found”](#google-protobuf-loaderror-libx86_64-linux-gnulibcso6-version-glibc_214-not-found) + +# Installation from source[](#installation-from-source "Permalink") + +这是使用源文件设置生产 GitLab 服务器的官方安装指南. 要设置**开发安装**或许多其他安装选项,请参见[主要安装页面](README.html) . 它是为**Debian / Ubuntu**操作系统创建并经过测试的. 有关硬件和操作系统[要求](requirements.html) ,请阅读 requirements.md. 如果要在 RHEL / CentOS 上安装,我们建议使用[Omnibus 软件包](https://about.gitlab.com/install/) . + +本指南之所以冗长,是因为它涵盖了许多情况,并且包括您需要的所有命令,这是[实际上可以立即使用的少数安装脚本之一](https://twitter.com/robinvdvleuten/status/424163226532986880) . 已知以下步骤有效. **偏离**本指南**时请多加注意** . 确保您没有违反任何有关 GitLab 对其环境的假设. 例如,许多人遇到权限问题,因为他们更改了目录的位置或以错误的用户身份运行服务. + +如果您在本指南中发现错误/错误, **请**按照[提供帮助的指南](https://gitlab.com/gitlab-org/gitlab/blob/master/CONTRIBUTING.md) **提交合并请求** . + +## Consider the Omnibus package installation[](#consider-the-omnibus-package-installation "Permalink") + +由于从源头进行安装需要大量工作并且容易出错,因此我们强烈建议您快速,可靠地[安装 Omnibus 软件包](https://about.gitlab.com/install/) (deb / rpm). + +Omnibus 软件包更可靠的原因之一是它使用 runit 来重新启动任何 GitLab 进程,以防万一崩溃. 在频繁使用的 GitLab 实例上,Sidekiq 后台工作程序的内存使用量会随着时间增长. + +Omnibus 软件包通过[使 Sidekiq](../administration/operations/sidekiq_memory_killer.html)在使用过多内存的情况下[正常终止来](../administration/operations/sidekiq_memory_killer.html)解决此问题. 在此终止后,runit 将检测到 Sidekiq 没有运行并启动它. 由于从源头进行的安装不使用 runit 进行过程监视,因此 Sidekiq 无法终止,并且其内存使用量会随着时间的推移而增长. + +## Select a version to install[](#select-a-version-to-install "Permalink") + +确保从您要安装的 GitLab 的分支(版本)中查看[此安装指南](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/install/installation.md) (例如`11-7-stable` ). 您可以在 GitLab 左上角的版本下拉菜单中选择分支(位于菜单栏下方). + +如果不清楚最高数目的稳定分支,请查看[GitLab 博客](https://about.gitlab.com/blog/)以获取版本信息. + +## GitLab directory structure[](#gitlab-directory-structure "Permalink") + +这是主要的目录结构,您将按照此页面的说明进行操作: + +``` +|-- home +| |-- git +| |-- .ssh +| |-- gitlab +| |-- gitlab-shell +| |-- repositories +``` + +* `/home/git/.ssh`包含 OpenSSH 设置. 具体来说,由 GitLab Shell 管理的`authorized_keys`文件. +* `/home/git/gitlab` -GitLab 核心软件. +* `/home/git/gitlab-shell` -GitLab 的核心附加组件. 维护 SSH 克隆和其他功能. +* `/home/git/repositories`按名称空间组织的所有项目的裸存储库. 这是为所有项目维护推/拉的 Git 存储库的地方. **该区域包含项目的关键数据.** **[保持备份](../raketasks/backup_restore.html) .** + +**注意:**可以在 GitLab 的`config/gitlab.yml`和 GitLab Shell 的`config.yml`中`config/gitlab.yml`存储库的默认位置. + +有关更深入的概述,请参阅[GitLab 体系结构文档](../development/architecture.html) . + +## Overview[](#overview "Permalink") + +GitLab 安装包括设置以下组件: + +1. [Packages and dependencies](#1-packages-and-dependencies). +2. [Ruby](#2-ruby). +3. [Go](#3-go). +4. [Node](#4-node). +5. [System users](#5-system-users). +6. [Database](#6-database). +7. [Redis](#7-redis). +8. [GitLab](#8-gitlab). +9. [NGINX](#9-nginx). + +## 1\. Packages and dependencies[](#1-packages-and-dependencies "Permalink") + +默认情况下,Debian 上未安装`sudo` . 确保您的系统是最新的并安装. + +``` +# run as root! +apt-get update -y +apt-get upgrade -y +apt-get install sudo -y +``` + +**注意:**在此安装过程中,将需要手动编辑某些文件. 如果您熟悉 vim,请使用以下命令将其设置为默认编辑器. 如果您不熟悉 vim,请跳过此步骤并继续使用默认编辑器. + +``` +# Install vim and set as default editor +sudo apt-get install -y vim +sudo update-alternatives --set editor /usr/bin/vim.basic +``` + +安装所需的软件包(需要编译 Ruby 和 Ruby gem 的本机扩展): + +``` +sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libre2-dev \ + libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev \ + libxslt-dev libcurl4-openssl-dev libicu-dev logrotate rsync python-docutils pkg-config cmake \ + runit +``` + +Ubuntu 14.04(Trusty `libre2-dev` )没有可用的`libre2-dev`软件包,但您可以[手动安装 re2](https://github.com/google/re2/wiki/Install) . + +如果要使用 Kerberos 进行用户身份验证,请安装`libkrb5-dev` : + +``` +sudo apt-get install libkrb5-dev +``` + +**注意:**如果您不知道 Kerberos 是什么,则可以假定您不需要它. + +确保您安装了正确的 Git 版本: + +``` +# Install Git +sudo apt-get install -y git-core + +# Make sure Git is version 2.27.0 or higher (minimal supported version is 2.25.0) +git --version +``` + +从 GitLab 12.0 开始,需要使用`libpcre2`编译 Git. 找出是否是这种情况: + +``` +ldd $(command -v git) | grep pcre2 +``` + +输出应包含`libpcre2-8.so.0` . + +系统打包的 Git 是否过旧,或者未使用 pcre2 编译? 去掉它: + +``` +sudo apt-get remove git-core +``` + +在 Ubuntu 上, [从其官方 PPA](https://git-scm.com/download/linux)安装 Git: + +``` +# run as root! +add-apt-repository ppa:git-core/ppa +apt update +apt install git +# repeat libpcre2 check as above +``` + +在 Debian 上,使用以下编译说明: + +``` +# Install dependencies +sudo apt-get install -y libcurl4-openssl-dev libexpat1-dev gettext libz-dev libssl-dev build-essential + +# Download and compile pcre2 from source +curl --silent --show-error --location https://ftp.pcre.org/pub/pcre/pcre2-10.33.tar.gz --output pcre2.tar.gz +tar -xzf pcre2.tar.gz +cd pcre2-10.33 +chmod +x configure +./configure --prefix=/usr --enable-jit +make +sudo make install + +# Download and compile from source +cd /tmp +curl --remote-name --location --progress https://www.kernel.org/pub/software/scm/git/git-2.27.0.tar.gz +echo '77ded85cbe42b1ffdc2578b460a1ef5d23bcbc6683eabcafbb0d394dffe2e787 git-2.27.0.tar.gz' | shasum -a256 -c - && tar -xzf git-2.27.0.tar.gz +cd git-2.27.0/ +./configure --with-libpcre +make prefix=/usr/local all + +# Install into /usr/local/bin +sudo make prefix=/usr/local install + +# When editing config/gitlab.yml later, change the git -> bin_path to /usr/local/bin/git +``` + +为了使[自定义图标](../user/admin_area/appearance.html#favicon)能够正常工作,需要安装 GraphicsMagick. + +``` +sudo apt-get install -y graphicsmagick +``` + +**注意:**为了接收邮件通知,请确保安装邮件服务器. 默认情况下,Debian 随 exim4 一起提供,但这[会带来问题,](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/12754)而 Ubuntu 则没有. 推荐的邮件服务器是 postfix,您可以使用以下命令进行安装: + +``` +sudo apt-get install -y postfix +``` + +然后选择" Internet Site",然后按 Enter 确认主机名. + +[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse#dependencies)需要使用`exiftool`才能从上传的图像中删除 EXIF 数据. + +``` +sudo apt-get install -y libimage-exiftool-perl +``` + +## 2\. Ruby[](#2-ruby "Permalink") + +运行 GitLab 需要使用 Ruby 解释器. + +**注意:**当前支持的 Ruby(MRI)版本是 2.6.x. GitLab 12.2 放弃了对 Ruby 2.5.x 的支持. + +在生产环境[中将](https://github.com/rbenv/rbenv) Ruby 版本管理器(如[RVM](https://rvm.io/) , [rbenv](https://github.com/rbenv/rbenv)或[chruby)](https://github.com/postmodern/chruby)与 GitLab [一起](https://github.com/postmodern/chruby)使用通常会导致难以诊断问题. 不支持版本管理器,我们强烈建议所有人按照以下说明使用系统 Ruby. + +Linux 发行版通常提供较旧版本的 Ruby,因此这些说明旨在从官方源代码安装 Ruby. + +删除旧的 Ruby 1.8(如果存在): + +``` +sudo apt-get remove ruby1.8 +``` + +下载 Ruby 并进行编译: + +``` +mkdir /tmp/ruby && cd /tmp/ruby +curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.6.tar.gz +echo '2d78048e293817f38d4ede4ebc7873013e97bb0b ruby-2.6.6.tar.gz' | shasum -c - && tar xzf ruby-2.6.6.tar.gz +cd ruby-2.6.6 + +./configure --disable-install-rdoc +make +sudo make install +``` + +然后安装 Bundler gem(低于 2.x 的版本): + +``` +sudo gem install bundler --no-document --version '< 2' +``` + +## 3\. Go[](#3-go "Permalink") + +从 GitLab 8.0 开始,GitLab 有几个用 Go 编写的守护程序. 要安装 GitLab,我们需要一个 Go 编译器. 以下说明假定您使用 64 位 Linux. 您可以在[Go 下载页面上](https://s0golang0org.icopy.site/dl)找到其他平台的[下载](https://s0golang0org.icopy.site/dl) . + +``` +# Remove former Go installation folder +sudo rm -rf /usr/local/go + +curl --remote-name --progress https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz +echo '512103d7ad296467814a6e3f635631bd35574cab3369a97a323c9a585ccaa569 go1.13.5.linux-amd64.tar.gz' | shasum -a256 -c - && \ + sudo tar -C /usr/local -xzf go1.13.5.linux-amd64.tar.gz +sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/ +rm go1.13.5.linux-amd64.tar.gz +``` + +## 4\. Node[](#4-node "Permalink") + +从 GitLab 8.17 开始,GitLab 需要使用 Node 来编译 JavaScript 资产,并使用 Yarn 来管理 JavaScript 依赖项. 当前的最低要求是: + +* `node` > = v10.13.0\. (我们建议使用节点 12.x,因为它速度更快) +* `yarn` > = v1.10.0. + +在许多发行版中,官方软件包存储库提供的版本已经过时,因此我们需要通过以下命令进行安装: + +``` +# install node v12.x +curl --location https://deb.nodesource.com/setup_12.x | sudo bash - +sudo apt-get install -y nodejs + +curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list +sudo apt-get update +sudo apt-get install yarn +``` + +如果您对这些步骤有任何疑问,请访问[node](https://s0nodejs0org.icopy.site/en/download/package-manager/)和[yarn](https://classic.yarnpkg.com/en/docs/install/)的官方网站. + +## 5\. System users[](#5-system-users "Permalink") + +为 GitLab 创建一个`git`用户: + +``` +sudo adduser --disabled-login --gecos 'GitLab' git +``` + +## 6\. Database[](#6-database "Permalink") + +**注意:**从 GitLab 12.1 开始,仅支持 PostgreSQL. 从 GitLab 13.0 开始,我们需要 PostgreSQL 11+. + +1. 安装数据库软件包: + + ``` + sudo apt-get install -y postgresql postgresql-client libpq-dev postgresql-contrib + ``` + +2. 启动 PostgreSQL 服务并确认该服务正在运行: + + ``` + sudo service postgresql start + sudo service postgresql status + ``` + +3. 为 GitLab 创建数据库用户: + + ``` + sudo -u postgres psql -d template1 -c "CREATE USER git CREATEDB;" + ``` + +4. 创建`pg_trgm`扩展(GitLab 8.6+必需): + + ``` + sudo -u postgres psql -d template1 -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;" + ``` + +5. 创建 GitLab 生产数据库并授予该数据库的所有特权: + + ``` + sudo -u postgres psql -d template1 -c "CREATE DATABASE gitlabhq_production OWNER git;" + ``` + +6. 尝试使用新用户连接到新数据库: + + ``` + sudo -u git -H psql -d gitlabhq_production + ``` + +7. 检查是否启用了`pg_trgm`扩展名: + + ``` + SELECT true AS enabled + FROM pg_available_extensions + WHERE name = 'pg_trgm' + AND installed_version IS NOT NULL; + ``` + + 如果启用了扩展名,将产生以下输出: + + ``` + enabled + --------- + t + (1 row) + ``` + +8. 退出数据库会话: + + ``` + gitlabhq_production> \q + ``` + +## 7\. Redis[](#7-redis "Permalink") + +GitLab 至少需要 Redis 5.0. + +如果您使用的是 Debian 10 或 Ubuntu 20.04 及更高版本,则可以使用以下命令安装 Redis 5.0: + +``` +sudo apt-get install redis-server +``` + +完成后,您可以配置 Redis: + +``` +# Configure redis to use sockets +sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.orig + +# Disable Redis listening on TCP by setting 'port' to 0 +sudo sed 's/^port .*/port 0/' /etc/redis/redis.conf.orig | sudo tee /etc/redis/redis.conf + +# Enable Redis socket for default Debian / Ubuntu path +echo 'unixsocket /var/run/redis/redis.sock' | sudo tee -a /etc/redis/redis.conf + +# Grant permission to the socket to all members of the redis group +echo 'unixsocketperm 770' | sudo tee -a /etc/redis/redis.conf + +# Create the directory which contains the socket +sudo mkdir -p /var/run/redis +sudo chown redis:redis /var/run/redis +sudo chmod 755 /var/run/redis + +# Persist the directory which contains the socket, if applicable +if [ -d /etc/tmpfiles.d ]; then echo 'd /var/run/redis 0755 redis redis 10d -' | sudo tee -a /etc/tmpfiles.d/redis.conf +fi + +# Activate the changes to redis.conf +sudo service redis-server restart + +# Add git to the redis group +sudo usermod -aG redis git +``` + +## 8\. GitLab[](#8-gitlab "Permalink") + +``` +# We'll install GitLab into the home directory of the user "git" +cd /home/git +``` + +### Clone the Source[](#clone-the-source "Permalink") + +克隆社区版: + +``` +# Clone GitLab repository +sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-foss.git -b X-Y-stable gitlab +``` + +克隆企业版: + +``` +# Clone GitLab repository +sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ee.git -b X-Y-stable gitlab +``` + +确保用与要安装的版本匹配的稳定分支替换`XY-stable` . 例如,如果要安装 11.8,则可以使用分支名称`11-8-stable` . + +**注意:**您可以更改`XY-stable` ,以`master` ,如果你想最*前沿*的版本,但从来没有安装`master`在生产服务器上! + +### Configure It[](#configure-it "Permalink") + +``` +# Go to GitLab installation folder +cd /home/git/gitlab + +# Copy the example GitLab config +sudo -u git -H cp config/gitlab.yml.example config/gitlab.yml + +# Update GitLab config file, follow the directions at top of the file +sudo -u git -H editor config/gitlab.yml + +# Copy the example secrets file +sudo -u git -H cp config/secrets.yml.example config/secrets.yml +sudo -u git -H chmod 0600 config/secrets.yml + +# Make sure GitLab can write to the log/ and tmp/ directories +sudo chown -R git log/ +sudo chown -R git tmp/ +sudo chmod -R u+rwX,go-w log/ +sudo chmod -R u+rwX tmp/ + +# Make sure GitLab can write to the tmp/pids/ and tmp/sockets/ directories +sudo chmod -R u+rwX tmp/pids/ +sudo chmod -R u+rwX tmp/sockets/ + +# Create the public/uploads/ directory +sudo -u git -H mkdir -p public/uploads/ + +# Make sure only the GitLab user has access to the public/uploads/ directory +# now that files in public/uploads are served by gitlab-workhorse +sudo chmod 0700 public/uploads + +# Change the permissions of the directory where CI job logs are stored +sudo chmod -R u+rwX builds/ + +# Change the permissions of the directory where CI artifacts are stored +sudo chmod -R u+rwX shared/artifacts/ + +# Change the permissions of the directory where GitLab Pages are stored +sudo chmod -R ug+rwX shared/pages/ + +# Copy the example Puma config +sudo -u git -H cp config/puma.rb.example config/puma.rb + +# Refer to https://github.com/puma/puma#configuration for more information. +# You should scale Puma workers and threads based on the number of CPU +# cores you have available. You can get that number via the `nproc` command. +sudo -u git -H editor config/puma.rb + +# Copy the example Rack attack config +sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb + +# Configure Git global settings for git user +# 'autocrlf' is needed for the web editor +sudo -u git -H git config --global core.autocrlf input + +# Disable 'git gc --auto' because GitLab already runs 'git gc' when needed +sudo -u git -H git config --global gc.auto 0 + +# Enable packfile bitmaps +sudo -u git -H git config --global repack.writeBitmaps true + +# Enable push options +sudo -u git -H git config --global receive.advertisePushOptions true + +# Enable fsyncObjectFiles to reduce risk of repository corruption if the server crashes +sudo -u git -H git config --global core.fsyncObjectFiles true + +# Configure Redis connection settings +sudo -u git -H cp config/resque.yml.example config/resque.yml + +# Change the Redis socket path if you are not using the default Debian / Ubuntu configuration +sudo -u git -H editor config/resque.yml +``` + +**注意:**请确保同时编辑`gitlab.yml`和`puma.rb`以匹配您的设置. 如果要使用 Unicorn Web 服务器,请参阅" [使用 Unicorn"](#using-unicorn)以了解其他步骤.**注意:**如果要使用 HTTPS,请参阅" [使用 HTTPS"](#using-https)以了解其他步骤. + +### Configure GitLab DB Settings[](#configure-gitlab-db-settings "Permalink") + +``` +sudo -u git cp config/database.yml.postgresql config/database.yml + +# Remove host, username, and password lines from config/database.yml. +# Once modified, the `production` settings will be as follows: +# +# production: +# adapter: postgresql +# encoding: unicode +# database: gitlabhq_production +# pool: 10 +# +sudo -u git -H editor config/database.yml + +# Remote PostgreSQL only: +# Update username/password in config/database.yml. +# You only need to adapt the production settings (first part). +# If you followed the database guide then please do as follows: +# Change 'secure password' with the value you have given to $password +# You can keep the double quotes around the password +sudo -u git -H editor config/database.yml + +# Make config/database.yml readable to git only +sudo -u git -H chmod o-rwx config/database.yml +``` + +### Install Gems[](#install-gems "Permalink") + +**注意:**从 Bundler 1.5.2 开始,您可以调用`bundle install -jN` (其中`N`是您的处理器内核数)并享受并行 gem 的安装,其完成时间有可衡量的差异(快 60%). 使用`nproc`检查您的内核数. 有关更多信息,请参见这篇[文章](https://thoughtbot.com/blog/parallel-gem-installing-using-bundler) . + +确保您有`bundle` (运行`bundle -v` ): + +* `>= 1.5.2` ,因为某些[问题](https://devcenter.heroku.com/changelog-items/411)已在 1.5.2 中[修复](https://github.com/rubygems/bundler/pull/2817) . +* `< 2.x`. + +``` +sudo -u git -H bundle install --deployment --without development test mysql aws kerberos +``` + +**注意:**如果要使用 Kerberos 进行用户身份验证,请在上面的`--without`选项中省略`kerberos` . + +### Install GitLab Shell[](#install-gitlab-shell "Permalink") + +GitLab Shell 是专门为 GitLab 开发的 SSH 访问和存储库管理软件. + +``` +# Run the installation task for gitlab-shell: +sudo -u git -H bundle exec rake gitlab:shell:install RAILS_ENV=production + +# By default, the gitlab-shell config is generated from your main GitLab config. +# You can review (and modify) the gitlab-shell config as follows: +sudo -u git -H editor /home/git/gitlab-shell/config.yml +``` + +**注意:**如果要使用 HTTPS,请参阅" [使用 HTTPS"](#using-https)以了解其他步骤.**注意:**确保您的主机名可以通过正确的 DNS 记录或`/etc/hosts`的其他行(" 127.0.0.1 主机名")在计算机上解析. 例如,如果您在反向代理后面设置了 GitLab,则可能有必要. 如果无法解析主机名,则最终安装检查将失败,并具有`Check GitLab API access: FAILED. code: 401` `Check GitLab API access: FAILED. code: 401`和推送提交将通过`[remote rejected] master -> master (hook declined)` . + +### Install GitLab Workhorse[](#install-gitlab-workhorse "Permalink") + +GitLab-Workhorse 使用[GNU Make](https://www.gnu.org/software/make/) . 以下命令行将在建议的位置`/home/git/gitlab-workhorse`安装 GitLab-Workhorse. + +``` +sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production +``` + +您可以通过提供其他参数来指定其他 Git 存储库: + +``` +sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse,https://example.com/gitlab-workhorse.git]" RAILS_ENV=production +``` + +### Install GitLab-Elasticsearch-indexer on Enterprise Edition[](#install-gitlab-elasticsearch-indexer-on-enterprise-edition "Permalink") + +GitLab-Elasticsearch-Indexer 使用[GNU Make](https://www.gnu.org/software/make/) . 以下命令行将在推荐位置`/home/git/gitlab-elasticsearch-indexer`中安装 GitLab-Elasticsearch-Indexer. + +``` +sudo -u git -H bundle exec rake "gitlab:indexer:install[/home/git/gitlab-elasticsearch-indexer]" RAILS_ENV=production +``` + +您可以通过提供其他参数来指定其他 Git 存储库: + +``` +sudo -u git -H bundle exec rake "gitlab:indexer:install[/home/git/gitlab-elasticsearch-indexer,https://example.com/gitlab-elasticsearch-indexer.git]" RAILS_ENV=production +``` + +首先将源代码提取到第一个参数指定的路径. 然后,将在其`bin`目录下构建一个二进制文件. 然后,您将需要更新`gitlab.yml`的`production -> elasticsearch -> indexer_path`设置以指向该二进制文件. + +**注意:** Elasticsearch 是 GitLab 企业版的一项功能,不包含在 GitLab 社区版中. + +### Install GitLab Pages[](#install-gitlab-pages "Permalink") + +GitLab Pages 使用[GNU Make](https://www.gnu.org/software/make/) . 此步骤是可选的,仅当您希望在 GitLab 中托管静态站点时才需要. 以下命令将在`/home/git/gitlab-pages`安装 GitLab `/home/git/gitlab-pages` . 有关其他设置步骤,请查阅适用于您的 GitLab 版本的[管理指南](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/pages/source.md) ,因为 GitLab Pages 守护程序可以通过几种不同的方式运行. + +``` +cd /home/git +sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-pages.git +cd gitlab-pages +sudo -u git -H git checkout v$(> $gitlab_path/log/gitaly.log 2>&1 &" +``` + +### Initialize Database and Activate Advanced Features[](#initialize-database-and-activate-advanced-features "Permalink") + +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production +# Type 'yes' to create the database tables. + +# or you can skip the question by adding force=yes +sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production force=yes + +# When done, you see 'Administrator account created:' +``` + +**注意:**您可以通过分别在环境变量`GITLAB_ROOT_PASSWORD`和`GITLAB_ROOT_EMAIL`提供管理员/ root 密码和电子邮件来设置它们,如下所示. 如果您未设置密码(并且密码已设置为默认密码),请等待 GitLab 暴露在公共互联网上,直到安装完成并且您已首次登录服务器. 首次登录时,将被迫更改默认密码. 通过在`GITLAB_LICENSE_FILE`环境变量中提供完整路径,此时也可以安装 Enterprise Edition 许可证. + +``` +sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=yourpassword GITLAB_ROOT_EMAIL=youremail GITLAB_LICENSE_FILE="/path/to/license" +``` + +### Secure secrets.yml[](#secure-secretsyml "Permalink") + +`secrets.yml`文件存储会话和安全变量的加密密钥. 备份`secrets.yml`安全保存,但是请不要将其与数据库备份存储在同一位置. 否则,如果其中一个备份遭到破坏,您的秘密就会暴露出来. + +### Install Init Script[](#install-init-script "Permalink") + +下载初始化脚本(将为`/etc/init.d/gitlab` ): + +``` +sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab +``` + +而且,如果要使用非默认文件夹或用户安装,请复制并编辑默认文件: + +``` +sudo cp lib/support/init.d/gitlab.default.example /etc/default/gitlab +``` + +如果将 GitLab 安装在其他目录中或以默认用户以外的用户身份安装,则应在`/etc/default/gitlab`更改这些设置. 不要编辑`/etc/init.d/gitlab`因为它将在升级时更改. + +使 GitLab 在启动时启动: + +``` +sudo update-rc.d gitlab defaults 21 +``` + +### Set up Logrotate[](#set-up-logrotate "Permalink") + +``` +sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab +``` + +### Check Application Status[](#check-application-status "Permalink") + +检查 GitLab 及其环境是否配置正确: + +``` +sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production +``` + +### Compile GetText PO files[](#compile-gettext-po-files "Permalink") + +``` +sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production +``` + +### Compile Assets[](#compile-assets "Permalink") + +``` +sudo -u git -H yarn install --production --pure-lockfile +sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production +``` + +如果`rake`因`JavaScript heap out of memory`不足错误而失败,请尝试按如下所示设置`NODE_OPTIONS`来运行它. + +``` +sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production NODE_OPTIONS="--max_old_space_size=4096" +``` + +### Start Your GitLab Instance[](#start-your-gitlab-instance "Permalink") + +``` +sudo service gitlab start +# or +sudo /etc/init.d/gitlab restart +``` + +## 9\. NGINX[](#9-nginx "Permalink") + +**注意:** NGINX 是 GitLab 官方支持的 Web 服务器. 如果您不能或不想将 NGINX 用作 Web 服务器,请参阅[GitLab 配方](https://gitlab.com/gitlab-org/gitlab-recipes/) . + +### Installation[](#installation "Permalink") + +``` +sudo apt-get install -y nginx +``` + +### Site Configuration[](#site-configuration "Permalink") + +复制示例站点配置: + +``` +sudo cp lib/support/nginx/gitlab /etc/nginx/sites-available/gitlab +sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab +``` + +确保编辑配置文件以匹配您的设置. 另外,请确保您与 GitLab 的路径匹配,尤其是在为`git`用户以外的用户安装时: + +``` +# Change YOUR_SERVER_FQDN to the fully-qualified +# domain name of your host serving GitLab. +# +# Remember to match your paths to GitLab, especially +# if installing for a user other than 'git'. +# +# If using Ubuntu default nginx install: +# either remove the default_server from the listen line +# or else sudo rm -f /etc/nginx/sites-enabled/default +sudo editor /etc/nginx/sites-available/gitlab +``` + +如果您打算启用 GitLab 页面,则需要使用一个单独的 NGINX 配置. 在[GitLab 页面管理指南中](../administration/pages/index.html)阅读有关所需配置的所有信息. + +**注意:**如果要使用 HTTPS,请将`gitlab` NGINX 配置替换为`gitlab-ssl` . 有关 HTTPS 配置的详细信息,请参见[使用 HTTPS](#using-https) . + +### Test Configuration[](#test-configuration "Permalink") + +使用以下命令验证`gitlab`或`gitlab-ssl` NGINX 配置文件: + +``` +sudo nginx -t +``` + +您应该会收到`syntax is okay`并且`test is successful`消息. 如果收到错误,请按照给出的错误消息中的说明检查`gitlab`或`gitlab-ssl` NGINX 配置文件是否有错别字等. + +**注意:**通过运行`nginx -v`验证安装的版本是否大于 1.12.1\. 如果它较低,您可能会收到以下错误: `nginx: [emerg] unknown "start$temp=[filtered]$rest" variable nginx: configuration file /etc/nginx/nginx.conf test failed` + +### Restart[](#restart "Permalink") + +``` +sudo service nginx restart +``` + +## Post-install[](#post-install "Permalink") + +### Double-check Application Status[](#double-check-application-status "Permalink") + +为了确保您不会错过任何东西,请使用以下命令进行更彻底的检查: + +``` +sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production +``` + +如果所有项目均为绿色,则恭喜您成功安装了 GitLab! + +向`gitlab:check`提供`SANITIZE=true`环境变量,以从 check 命令的输出中省略项目名称. + +### Initial Login[](#initial-login "Permalink") + +在您的 Web 浏览器中访问 YOUR_SERVER 进行首次 GitLab 登录. + +如果[在设置过程中](#initialize-database-and-activate-advanced-features)未[提供 root 密码,](#initialize-database-and-activate-advanced-features)则将重定向到密码重置屏幕,以提供初始管理员帐户的密码. 输入所需的密码,您将被重定向回登录屏幕. + +默认帐户的用户名是**root** . 提供您先前创建的密码并登录. 登录后,您可以根据需要更改用户名. + +**Enjoy!** + +You can use `sudo service gitlab start` and `sudo service gitlab stop` to start and stop GitLab. + +## Advanced Setup Tips[](#advanced-setup-tips "Permalink") + +### Relative URL support[](#relative-url-support "Permalink") + +有关如何使用相对 URL 配置 GitLab 的更多信息,请参见[相对 URL 文档](relative_url.html) . + +### Using HTTPS[](#using-https "Permalink") + +要将 GitLab 与 HTTPS 一起使用: + +1. In `gitlab.yml`: + 1. 将第 1 节中的`port`选项设置为`443` . + 2. 将第 1 节中的`https`选项设置为`true` . +2. 在 GitLab Shell 的`config.yml`中: + 1. 将`gitlab_url`选项设置为 GitLab 的 HTTPS 端点(例如`https://git.example.com` ). + 2. 使用`ca_file`或`ca_path`选项设置证书. +3. 使用`gitlab-ssl` NGINX 示例配置,而不是`gitlab`配置. + 1. 更新`YOUR_SERVER_FQDN` . + 2. 更新`ssl_certificate`和`ssl_certificate_key` . + 3. 查看配置文件,并考虑应用其他安全性和性能增强功能. + +不鼓励使用自签名证书,但如果必须使用它,请遵循正常说明. 然后: + +1. 生成自签名 SSL 证书: + + ``` + mkdir -p /etc/nginx/ssl/ + cd /etc/nginx/ssl/ + sudo openssl req -newkey rsa:2048 -x509 -nodes -days 3560 -out gitlab.crt -keyout gitlab.key + sudo chmod o-r gitlab.key + ``` + +2. 在 GitLab Shell 的`config.yml` ,将`self_signed_cert`设置为`true` . + +### Enable Reply by email[](#enable-reply-by-email "Permalink") + +有关如何进行此设置的更多信息,请参见["通过电子邮件答复"文档](../administration/reply_by_email.html) . + +### LDAP Authentication[](#ldap-authentication "Permalink") + +您可以在`config/gitlab.yml`配置 LDAP 身份验证. 编辑此文件后,重新启动 GitLab. + +### Using Custom OmniAuth Providers[](#using-custom-omniauth-providers "Permalink") + +请参阅[OmniAuth 集成文档](../integration/omniauth.html) . + +### Build your projects[](#build-your-projects "Permalink") + +GitLab 可以构建您的项目. 要启用该功能,您需要 GitLab Runners 为您执行此操作. 请参阅[GitLab Runner 部分](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/#gitlab-runner)进行安装. + +### Adding your Trusted Proxies[](#adding-your-trusted-proxies "Permalink") + +如果要在单独的计算机上使用反向代理,则可能要将代理添加到"受信任的代理"列表中. 否则,用户将显示为从代理的 IP 地址登录. + +您可以通过自定义第 1 节中的`trusted_proxies`选项在`config/gitlab.yml`添加受信任的代理.保存文件并[重新配置 GitLab,](../administration/restart_gitlab.html)以使更改生效. + +### Custom Redis Connection[](#custom-redis-connection "Permalink") + +如果您想通过非标准端口或其他主机连接到 Redis 服务器,则可以通过`config/resque.yml`文件配置其连接字符串. + +``` +# example +production: + url: redis://redis.example.tld:6379 +``` + +如果要通过套接字连接 Redis 服务器,请使用" unix:" URL 方案以及`config/resque.yml`文件中 Redis 套接字文件的路径. + +``` +# example +production: + url: unix:/path/to/redis/socket +``` + +另外,您可以在`config/resque.yml`文件中使用环境变量: + +``` +# example +production: + url: <%= ENV.fetch('GITLAB_REDIS_URL') %> +``` + +### Custom SSH Connection[](#custom-ssh-connection "Permalink") + +如果您在非标准端口上运行 SSH,则必须更改 GitLab 用户的 SSH 配置. + +``` +# Add to /home/git/.ssh/config +host localhost # Give your setup a name (here: override localhost) + user git # Your remote git user + port 2222 # Your port number + hostname 127.0.0.1; # Your server name or IP +``` + +您还需要在`config\gitlab.yml`文件中更改相应的选项(例如`ssh_user` , `ssh_host` , `admin_uri` ). + +### Additional Markup Styles[](#additional-markup-styles "Permalink") + +除了始终支持的 Markdown 样式外,GitLab 还可以显示其他富文本文件. 但是您可能必须安装依赖项才能这样做. 有关更多信息,请参见[`github-markup` gem 自述文件](https://github.com/gitlabhq/markup#markups) . + +### Using Unicorn[](#using-unicorn "Permalink") + +从 GitLab 12.9 开始, [Puma](https://github.com/puma/puma)已取代 Unicorn 成为默认源安装 Web 服务器. 如果要切换回独角兽,请按照下列步骤操作: + +1. 完成 GitLab 设置,以使其启动并运行. +2. 将提供的示例 Unicorn 配置文件复制到位: + + ``` + cd /home/git/gitlab + + # Copy config file for the web server + sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb + ``` + +3. 编辑系统`init.d`脚本并设置`USE_WEB_SERVER="unicorn"` . 如果您有`/etc/default/gitlab` ,那么您应该对其进行编辑. +4. Restart GitLab. + +### Using Sidekiq instead of Sidekiq Cluster[](#using-sidekiq-instead-of-sidekiq-cluster "Permalink") + +从 GitLab 12.10 开始,Source 安装使用`bin/sidekiq-cluster`来管理 Sidekiq 进程. 在 14.0 之前,仍支持直接使用 Sidekiq. 因此,如果您遇到问题,请: + +1. 编辑系统`init.d`脚本以删除`SIDEKIQ_WORKERS`标志. 如果您有`/etc/default/gitlab` ,那么您应该对其进行编辑. +2. 重新启动 GitLab. +3. [创建一个](https://gitlab.com/gitlab-org/gitlab/-/issues/-/new)描述问题的问题. + +## Troubleshooting[](#troubleshooting "Permalink") + +### “You appear to have cloned an empty repository.”[](#you-appear-to-have-cloned-an-empty-repository "Permalink") + +如果在尝试克隆由 GitLab 托管的存储库时看到此消息,则可能是由于 NGINX 或 Apache 配置过时,或者缺少或配置了错误的 GitLab Workhorse 实例. 仔细检查您是否已[安装 Go](#3-go) , [已安装 GitLab Workhorse](#install-gitlab-workhorse)并已正确[配置 NGINX](#site-configuration) . + +### `google-protobuf` “LoadError: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14’ not found”[](#google-protobuf-loaderror-libx86_64-linux-gnulibcso6-version-glibc_214-not-found "Permalink") + +对于某些版本的`google-protobuf` gem,这可能会在某些平台上发生. 解决方法是安装此 gem 的仅源版本. + +首先,您必须找到 GitLab 安装所需的`google-protobuf`确切版本: + +``` +cd /home/git/gitlab + +# Only one of the following two commands will print something. It +# will look like: * google-protobuf (3.2.0) +bundle list | grep google-protobuf +bundle check | grep google-protobuf +``` + +下面以`3.2.0`为例. 将其替换为您在上面找到的版本号: + +``` +cd /home/git/gitlab +sudo -u git -H gem install google-protobuf --version 3.2.0 --platform ruby +``` + +最后,您可以测试`google-protobuf`是否正确加载. 以下应打印"确定". + +``` +sudo -u git -H bundle exec ruby -rgoogle/protobuf -e 'puts :OK' +``` + +如果`gem install`命令失败,则可能需要安装操作系统的开发人员工具. + +在 Debian / Ubuntu 上: + +``` +sudo apt-get install build-essential libgmp-dev +``` + +在 RedHat / CentOS 上: + +``` +sudo yum groupinstall 'Development Tools' +``` \ No newline at end of file diff --git a/_book/docs/009.md b/_book/docs/009.md new file mode 100644 index 0000000000000000000000000000000000000000..9d598f33ac273490e9dbaa468678d3d7e6b46394 --- /dev/null +++ b/_book/docs/009.md @@ -0,0 +1,345 @@ +# Install GitLab on Microsoft Azure + +> 原文:[https://docs.gitlab.com/ee/install/azure/](https://docs.gitlab.com/ee/install/azure/) + +* [Getting started](#getting-started) +* [Working with Azure](#working-with-azure) +* [Create New VM](#create-new-vm) +* [Basics](#basics) +* [Size](#size) +* [Settings](#settings) +* [Purchase](#purchase) +* [Deployment](#deployment) +* [Set up a domain name](#set-up-a-domain-name) +* [Let’s open some ports](#lets-open-some-ports) + * [Which ports to open?](#which-ports-to-open) + * [Open HTTP on Port 80](#open-http-on-port-80) + * [Open SSH on Port 22](#open-ssh-on-port-22) +* [Connecting to GitLab](#connecting-to-gitlab) + * [Success?](#success) +* [Creating your first GitLab project](#creating-your-first-gitlab-project) +* [Maintaining your GitLab instance](#maintaining-your-gitlab-instance) + * [Checking our current version](#checking-our-current-version) + * [Connect via SSH](#connect-via-ssh) + * [SSH from the command-line](#ssh-from-the-command-line) + * [SSH from Windows (PuTTY)](#ssh-from-windows-putty) + * [Updating GitLab](#updating-gitlab) + * [Check out your updated GitLab](#check-out-your-updated-gitlab) +* [Conclusion](#conclusion) +* [Where to next?](#where-to-next) + * [Useful links](#useful-links) + +# Install GitLab on Microsoft Azure[](#install-gitlab-on-microsoft-azure "Permalink") + +Azure 是 Microsoft 的业务云,GitLab 是 Azure 市场上的预配置产品. 希望您不会惊讶地听到 Microsoft 和 Azure 接受了开源软件,例如 Ubuntu,Red Hat Enterprise Linux,当然还有 GitLab! 这意味着您可以启动预配置的 GitLab VM,并在 30 分钟左右启动并运行自己的私有 GitLab. 让我们开始吧. + +## Getting started[](#getting-started "Permalink") + +首先,您需要在 Azure 上拥有一个帐户. 有三种方法可以做到这一点: + +* 如果您的公司(或您)已经有一个帐户,那么您就可以开始了! +* 您还可以免费打开自己的 Azure 帐户. *在撰写本文时* ,您将获得 200 美元的信用额度,可用于 30 天的 Azure 服务支出. 您可以使用此信用额度试用付费的 Azure 服务,免费浏览 Microsoft 的云. 即使在开始的 30 天之后,您也无需支付任何费用,除非您决定转换为使用"按需付费" Azure 订阅的付费服务. 这是试用 Azure 和云计算的好方法,您可以[在其全面的 FAQ 中阅读更多内容](https://azure.microsoft.com/en-us/free/free-account-faq/) . +* 如果您具有 MSDN 订阅,则可以激活 Azure 订阅者权益. 您的 MSDN 订阅每月为您提供经常性的 Azure 信用,那么为什么不立即使用这些信用并尝试 GitLab 呢? + +## Working with Azure[](#working-with-azure "Permalink") + +Once you have an Azure account, you can get started. [Log in to Azure](https://portal.azure.com) and the first thing you will see is the Dashboard: + +[![Azure Dashboard](img/27f5db1ffe5c715ccd311bccf93665f2.png)](img/azure-dashboard.png) + +仪表板为您提供了 Azure 资源的快速概述,从这里您可以构建 VM,创建 SQL 数据库,创建网站以及执行许多其他云任务. + +## Create New VM[](#create-new-vm "Permalink") + +[Azure 市场](https://azuremarketplace.microsoft.com/en-us/marketplace/)是一个在线商店,用于存储预配置的应用程序和服务,这些软件和服务已由 GitLab 等软件供应商针对云进行了优化,可以在 Azure 市场上作为预配置的解决方案使用. 在本教程中,我们将安装 GitLab 社区版,但是对于 GitLab 企业版,您可以遵循相同的过程. + +要开始创建新的 GitLab VM,请单击**+新建**图标,在搜索框中键入" GitLab",然后单击**" GitLab Community Edition"**搜索结果: + +[![Azure - New - Search for 'GitLab'](img/3e0f74f35030a15b593a12090d5c0daf.png)](img/azure-new-search-gitlab.png) + +将会弹出一个新的"刀片"窗口,您可以在其中阅读有关 MIT Expat 许可免费提供的**" GitLab 社区版"**产品的更多信息: + +[![Azure - New - Select 'GitLab Community Edition'](img/0290c1013dba1b07f226f1548c8b6fd2.png)](img/azure-new-gitlab-ce.png) + +单击**"创建"** ,将显示"创建虚拟机"刀片: + +[![Azure - Create Virtual Machine - Basics](img/e4581843d51522e972a6bb6716aa4b05.png)](img/azure-create-virtual-machine-basics.png) + +## Basics[](#basics "Permalink") + +我们需要配置的第一项是基础虚拟机的基本设置: + +1. 输入虚拟机的`Name` -例如**" GitLab-CE"** +2. 选择一个`VM disk type` -无论是***HDD(**慢,成本更低)*或***SSD(**更快,更高成本)* +3. 输入`User name` -例如`gitlab-admin` +4. 选择一种`Authentication type` , **SSH 公钥**或**密码** : + + > **注意:**如果不确定要使用哪种身份验证类型,请选择**密码** + + 1. 如果您选择**SSH 公钥** -在提供的字段中输入`SSH public key` *(请阅读[SSH 文档,](../../ssh/README.html)以了解有关如何设置 SSH 公钥的更多信息)* + 2. 如果选择了**密码** -输入要使用*的密码(这是本教程后面将用于[SSH](https://en.wikipedia.org/wiki/Secure_Shell)到 VM 的密码,因此请确保它是一个强密码/密码)* +5. 为您的 Azure 帐户选择适当的`Subscription`层 +6. 选择一个现有的`Resource Group`或创建一个新的`Resource Group` -例如**" GitLab-CE-Azure"** + + > **注意:** "资源组"是一种将相关资源分组在一起以简化管理的方法. 我们选择了" GitLab-CE-Azure",但是您的资源组可以与 VM 具有相同的名称. + +7. 选择一个`Location` -如果不确定,请选择默认位置 + +这是我们使用的设置: + +[![Azure - Create Virtual Machine - Basics Completed](img/defc257dc0219b95ed3f3065afcaff94.png)](img/azure-create-virtual-machine-basics-password.png) + +检查您输入的设置,然后在准备好继续时单击**"确定"** . + +## Size[](#size "Permalink") + +接下来,您需要选择 VM 的大小-选择功能,例如 CPU 内核数,RAM 数量,存储大小(及其速度)等. + +> **注意:**与其他云供应商一样,Azure 运行资源/使用定价模型,即,VM 消耗的资源越多,运行成本就越高,因此请谨慎选择. 您会看到,Azure 提供了每个 VM 大小以下的*估计*每月费用,以帮助指导选择. + +默认大小-成本最低的**" DS1_V2 标准" VM-**满足运行测试和评估目的小型 GitLab 环境的最低系统要求,因此我们将继续选择该大小,但请选择大小最能满足您的要求: + +[![Azure - Create Virtual Machine - Size](img/f7bf9b7c134eb4ee2629082be8992d5a.png)](img/azure-create-virtual-machine-size.png) + +> **注意:请**注意,当您的 VM 处于活动状态(称为"已分配")时,将产生"计算费用",最终将向您收费. 因此,即使您使用的是免费试用版信用,您也可能想学习[如何正确关闭 Azure VM 以节省资金](https://build5nines.com/properly-shutdown-azure-vm-to-save-money/) . + +继续并单击您选择的大小,然后在准备进行下一步时单击**"选择"** . + +## Settings[](#settings "Permalink") + +在下一个刀片服务器上,要求您配置存储,网络和扩展设置. 我们保留了默认设置,因为它们足以进行 GitLab 的测试驾驶,但是请选择最能满足您自己要求的设置: + +[![Azure - Create Virtual Machine - Settings](img/e470cb0eb6198f35d2db011704471fce.png)](img/azure-create-virtual-machine-settings.png) + +检查设置,然后在准备好进行最后一步时单击**"确定"** . + +## Purchase[](#purchase "Permalink") + +"购买"页面是最后一步,在这里将为您显示新 VM 的每小时价格. 您只需要为 VM 本身付费(例如" Standard DS1 v2"),因为**" GitLab 社区版"**市场解决方案可以以 0 美元/小时的价格免费使用: + +[![Azure - Create Virtual Machine - Purchase](img/ed70f998a438f30a2762829a3cc5b5b6.png)](img/azure-create-virtual-machine-purchase.png) + +> **注意:**在此阶段,您可以查看和修改在之前所有步骤中所做的任何设置,只需单击四个步骤中的任何一个即可重新打开它们. + +阅读并同意使用条款并准备进行时,请单击**"购买"** . + +## Deployment[](#deployment "Permalink") + +此时,Azure 将开始部署您的新 VM. 部署过程将需要几分钟才能完成,进度显示在**"部署"**刀片上: + +[![Azure - Create Virtual Machine - Deployment](img/c9fb44f57074dc166ca07353bd7d31c7.png)](img/azure-create-virtual-machine-deployment.png) + +部署过程完成后,新的 VM 及其相关资源将显示在 Azure 仪表板上(您可能需要刷新页面): + +[![Azure - Dashboard - All resources](img/12208c7d040cd738d51605b7fcb55237.png)](img/azure-dashboard-running-resources.png) + +也可以通过单击 Azure Portal 侧栏导航菜单中的" `All resources`或" `Virtual machines`图标来访问新 VM. + +## Set up a domain name[](#set-up-a-domain-name "Permalink") + +该虚拟机将具有一个公共 IP 地址(默认情况下为静态),但是 Azure 允许我们为该虚拟机分配一个友好的 DNS 名称,所以让我们继续吧. + +在控制面板中,单击**" GitLab-CE"**图块以打开新 VM 的管理刀片. VM 使用的公共 IP 地址在"基本"部分中显示: + +[![Azure - VM - Management - Public IP Address](img/f08e838598cbf1f61321a510bb24c6a1.png)](img/azure-vm-management-public-ip.png) + +单击公共 IP 地址-这将打开**"公共 IP 地址-配置"**刀片,然后单击**"配置"** (在"设置"下). 现在,在" `DNS name label`字段中为您的实例输入一个友好的 DNS 名称: + +[![Azure - VM - Domain Name](img/bccfe6e36a18f67a038a8d90f2a6499f.png)](img/azure-vm-domain-name.png) + +In the screenshot above, you’ll see that we’ve set the `DNS name label` to `gitlab-ce-test`. This will make our VM accessible at `gitlab-ce-test.centralus.cloudapp.azure.com` *(当然,您自己的 VM 的完整域名将有所不同)*. + +单击**"保存"**以使更改生效. + +> **注意:**如果要使用自己的域名,则需要在域注册商处添加 DNS `A`记录, `A`记录指向 Azure VM 的公共 IP 地址. 如果这样做,则需要确保将 VM 配置为使用*静态的*公共 IP 地址(即不是*动态的* IP 地址),否则每次 Azure 重新为 VM 分配新的公共 IP 时,都必须重新配置 DNS `A`记录.地址. 阅读[公共 IP 地址](https://docs.microsoft.com/en-us/azure/virtual-network/public-ip-addresses)以了解更多信息. + +## Let’s open some ports[](#lets-open-some-ports "Permalink") + +在此阶段,您应该拥有一个正在运行且完全可运行的 VM. 但是,在您打开必要的端口以启用对这些服务的访问之前,将无法通过 Internet 公开访问 VM 上的任何服务(例如 GitLab). + +通过将*安全规则*添加到已分配了我们的 VM 的**"网络安全组"** (NSG),可以打开端口. 如果按照上述过程进行操作,则 Azure 将自动创建一个名为`GitLab-CE-nsg`的 NSG 并将`GitLab-CE` VM 分配给它. + +> **注意:**如果给虚拟机命名不同,则 Azure 自动创建的 NSG 也将具有不同的名称-您拥有虚拟机的名称,并附加`-nsg` . + +您可以通过 Azure 门户中的许多不同路径导航到 NSG 设置,但是最简单的方法之一是转到 Azure 仪表板,然后单击**"所有资源"**图块中列出的 Network Security 组: + +[![Azure - Dashboard - All resources - Network security group](img/c380b8ddd78f1d3281d0eeea7f19971c.png)](img/azure-dashboard-highlight-nsg.png) + +在打开**"网络安全组"**刀片的情况下,单击**"设置"**下的**"** **入站安全规则** **"** : + +[![Azure - Network security group - Inbound security rules](img/3b13f587681dd3391c82eb9b650ff6cf.png)](img/azure-nsg-inbound-sec-rules-highlight.png) + +接下来,点击**"添加"** : + +[![Azure - Network security group - Inbound security rules - Add](img/f6e26efd0e5206a2e9d1bf43865b9f4a.png)](img/azure-nsg-inbound-sec-rules-add-highlight.png) + +### Which ports to open?[](#which-ports-to-open "Permalink") + +像所有服务器一样,我们的 VM 将运行许多服务. 但是,我们要打开正确的端口,以使公共互联网特别能够访问两种服务: + +1. **HTTP** (端口 80)-打开端口 80 将使我们的 VM 能够响应 HTTP 请求,从而允许公众访问在我们的 VM 上运行的 GitLab 实例. +2. **SSH** (端口 22)-打开端口 22 将使我们的 VM 能够响应 SSH 连接请求,允许对远程终端会话进行公共访问(带有身份验证) *(您将[在本教程的后面部分](#maintaining-your-gitlab-instance)看到为什么我们需要对 VM 进行[SSH](https://en.wikipedia.org/wiki/Secure_Shell)访问)* + +### Open HTTP on Port 80[](#open-http-on-port-80 "Permalink") + +在**"添加入站安全规则"**刀片中,让我们打开端口 80,以便我们的 VM 可以接受 HTTP 连接: + +[![Azure - Add inbound security rules - HTTP](img/7d05273dffbd24f67285426b02a19ddc.png)](img/azure-add-inbound-sec-rule-http.png) + +1. 在`Name`字段中输入**" HTTP"** +2. 从`Service`下拉列表中的选项中选择**HTTP** +3. 确保将`Action`设置为**允许** +4. Click **“OK”** + +### Open SSH on Port 22[](#open-ssh-on-port-22 "Permalink") + +重复上述过程,添加第二个入站安全规则以打开端口 22,使我们的 VM 能够接受[SSH](https://en.wikipedia.org/wiki/Secure_Shell)连接: + +[![Azure - Add inbound security rules - SSH](img/fb8ded1bb07112b49dc42dff02fe01f7.png)](img/azure-add-inbound-sec-rule-ssh.png) + +1. 在" `Name`字段中输入**" SSH"** +2. 从`Service`下拉列表中的选项中选择**SSH** +3. 确保将`Action`设置为**允许** +4. Click **“OK”** + +Azure 将花一点时间来添加每个新的入站安全规则(您可能需要单击**"入站安全规则"**以刷新列表),但是一旦完成,您应该在列表中看到两个新规则: + +[![Azure - Inbound security rules - List](img/72431eb6b6fe2dd27e2f6f9be7d91672.png)](img/azure-inbound-sec-rules-list.png) + +## Connecting to GitLab[](#connecting-to-gitlab "Permalink") + +使用您先前设置的域名(或公共 IP 地址)在浏览器中访问新的 GitLab 实例. 如果一切都按计划进行,则应显示以下页面,要求您为 GitLab 自动创建的管理员帐户设置*新*密码: + +[![GitLab - Change Password](img/b786322ea49fe7840203db128b72a5e0.png)](img/gitlab-change-password.png) + +在两个表单字段中输入您的*新*密码,然后单击**"更改密码"** . + +更改密码后,您将被重定向到 GitLab 登录页面. 使用`root`作为用户名,输入在上一步中设置的新密码,然后单击**"登录"** : + +[![GitLab - Login](img/56b25600afa13ee05e76062ab09ee470.png)](img/gitlab-login.png) + +### Success?[](#success "Permalink") + +成功登录后,您应该看到 GitLab 项目页面显示**"欢迎使用 GitLab!".** 信息: + +[![GitLab - Projects Page](img/96c6ce839dca0e2ef2d69b8fbc0cff56.png)](img/gitlab-home.png) + +如果是这样,您现在可以在自己的私有 Azure VM 上拥有一个正常的 GitLab 实例. **恭喜你!** + +## Creating your first GitLab project[](#creating-your-first-gitlab-project "Permalink") + +如果您熟悉 Git 和 GitLab,则可以跳过本节. 否则,让我们创建第一个项目. 在"欢迎"页面上,单击**"新建项目"** . + +让我们给项目命名和描述,然后接受其他所有内容的默认值: + +1. 在`Project path`项目名称字段中输入**" demo"** +2. 输入`description` ,例如**"我的真棒演示项目!"** +3. Click **"创建项目"** + +[![GitLab - New Project](img/c7562ae46b8ec150661af0c88f1a5aad.png)](img/gitlab-new-project.png) + +一旦创建了新项目(只需要一点时间),您将被重定向到该项目的主页: + +[![GitLab - Empty Project](img/669c2de32e70a30ad93c28d4afd41491.png)](img/gitlab-project-home-empty.png) + +If you scroll further down the project’s home page, you’ll see some basic instructions on how to set up a local clone of your new repository and push and pull from it: + +[![GitLab - Empty Project - Basic Instructions](img/3281ef5fea53e2f0a57bb3c648aa7fa4.png)](img/gitlab-project-home-instructions.png) + +**而已! 现在,您已经在云中安装并运行了自己的私有 GitLab 环境!** + +## Maintaining your GitLab instance[](#maintaining-your-gitlab-instance "Permalink") + +保持最新的 GitLab 环境非常重要. GitLab 团队会不断进行增强,出于安全原因,有时您可能需要进行更新. 因此,让我们回顾一下如何更新 GitLab. + +### Checking our current version[](#checking-our-current-version "Permalink") + +要检查我们当前正在运行的 GitLab 版本,请单击"管理区域"链接-它是显示在搜索框旁边的右上角的扳手图标. + +在以下屏幕截图中,您可以在右上角看到**"尽快更新"**通知消息. 此特定消息表明存在可用的较新版本的 GitLab,其中包含一个或多个安全修复程序: + +[![GitLab - update asap](img/8465cc4b8bf68fad2a64c9fc838c7939.png)](img/gitlab-admin-area.png) + +在**"组件"**部分下,我们可以看到我们的 VM 当前正在运行 GitLab 的`8.6.5`版本. 这是 GitLab 的版本,包含在 Azure 市场**" GitLab 社区版"中,该**产品在编写本教程时曾用来构建 VM. + +> **注意:**您自己的 VM 实例中的 GitLab 版本可能会有所不同,但是更新过程仍然相同. + +### Connect via SSH[](#connect-via-ssh "Permalink") + +要执行更新,我们需要直接连接到我们的 Azure VM 实例并从终端运行一些命令. 我们的 Azure VM 实际上是运行 Linux(Ubuntu)的服务器,因此我们需要使用 SSH( [Secure Shell](https://en.wikipedia.org/wiki/Secure_Shell) )连接到它. + +如果您正在运行 Windows,则需要使用[PuTTY](https://www.putty.org)或等效的 Windows SSH 客户端进行连接. 如果您正在运行 Linux 或 macOS,则说明您已经安装了 SSH 客户端. + +> **Note:** +> +> * 请记住,您将需要使用[创建](#basics) Azure VM [时](#basics)指定的用户名和密码登录 +> * 如果需要重置虚拟机密码,请阅读[如何为 Azure VM 上的用户重置 SSH 凭据](https://docs.microsoft.com/en-us/azure/virtual-machines/troubleshooting/troubleshoot-ssh-connection) . + +#### SSH from the command-line[](#ssh-from-the-command-line "Permalink") + +如果您从命令行(终端)运行[SSH](https://en.wikipedia.org/wiki/Secure_Shell) ,则键入以下命令以连接到您的 VM,用`username`和`your-azure-domain-name.com`替换正确的值. + +再次提醒您,您的 Azure VM 域名将是您[先前在本教程中设置的](#set-up-a-domain-name)域名. 如果未为 VM 设置域名,则可以在以下命令中使用其 IP 地址: + +``` +ssh username@your-azure-domain-name.com +``` + +在提示时提供密码以进行身份​​验证. + +#### SSH from Windows (PuTTY)[](#ssh-from-windows-putty "Permalink") + +如果您将 Windows 中的[PuTTY](https://www.putty.org)用作[SSH](https://en.wikipedia.org/wiki/Secure_Shell)客户端,那么您可能想快速阅读[Windows 中的 PuTTY](https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty-) . + +### Updating GitLab[](#updating-gitlab "Permalink") + +通过 SSH 登录后,输入以下命令将 GitLab 更新到最新版本: + +``` +sudo apt-get update && sudo apt-get install gitlab-ce +``` + +此命令会将 GitLab 及其关联的组件更新为最新版本,因此需要一些时间才能完成. 您将在 SSH 终端窗口中看到各种更新任务正在完成: + +[![GitLab updating](img/dbae11f07630ae759b8156031d0c496d.png)](img/gitlab-ssh-update-in-progress.png) + +更新过程完成后,您将看到以下消息: + +``` +Upgrade complete! If your GitLab server is misbehaving try running + + sudo gitlab-ctl restart + +before anything else. +``` + +#### Check out your updated GitLab[](#check-out-your-updated-gitlab "Permalink") + +在浏览器中刷新您的 GitLab 实例,然后导航到"管理区域". 您现在应该具有最新的 GitLab 实例. + +在编写本教程时,我们的 Azure VM GitLab 实例在撰写本文时已更新为最新版本( `9.4.0` ). 您可以看到以前显示**" update asap"**的消息现在显示为**"最新"** : + +[![GitLab up to date](img/80a9fe0374f84134fa2b40172431604d.png)](img/gitlab-admin-area-9.4.0.png) + +## Conclusion[](#conclusion "Permalink") + +自然地,我们认为 GitLab 是一个很棒的 Git 存储库工具. 但是,GitLab 的功能远不止于此. GitLab 将问题,代码审查,CI 和 CD 统一到一个 UI 中,可帮助您从构思到生产更快地迁移,并且在本教程中,我们向您展示了在 Azure 上设置和运行自己的 GitLab 实例是多么快速和容易. ,微软的云服务. + +Azure 是尝试 GitLab 的好方法,如果您决定(如我们所愿)GitLab 适合您,则可以继续使用 Azure 作为您的安全,可扩展的云提供商,当然也可以在您选择的任何云服务上运行 GitLab. + +## Where to next?[](#where-to-next "Permalink") + +查看其他[技术文章](../../articles/index.html)或浏览[GitLab 文档](../../README.html)以了解有关 GitLab 的更多信息. + +### Useful links[](#useful-links "Permalink") + +* [GitLab Community Edition](https://about.gitlab.com/features/) +* [GitLab Enterprise Edition](https://about.gitlab.com/features/#ee-starter) +* [Microsoft Azure](https://azure.microsoft.com/en-us/) + * [Azure - Free Account FAQ](https://azure.microsoft.com/en-us/free/free-account-faq/) + * [Azure - Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/) + * [Azure Portal](https://portal.azure.com) + * [Azure - Pricing Calculator](https://azure.microsoft.com/en-us/pricing/calculator/) + * [Azure - Troubleshoot SSH Connections to an Azure Linux VM](https://docs.microsoft.com/en-us/azure/virtual-machines/troubleshooting/troubleshoot-ssh-connection) + * [Azure - Properly Shutdown an Azure VM](https://build5nines.com/properly-shutdown-azure-vm-to-save-money/) +* [SSH](https://en.wikipedia.org/wiki/Secure_Shell), [PuTTY](https://www.putty.org) and [Using SSH in PuTTY](https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty-) \ No newline at end of file diff --git a/_book/docs/010.md b/_book/docs/010.md new file mode 100644 index 0000000000000000000000000000000000000000..f3fad8a66bd72e139804011598deb4618d1a8a71 --- /dev/null +++ b/_book/docs/010.md @@ -0,0 +1,122 @@ +# Installing GitLab on Google Cloud Platform + +> 原文:[https://docs.gitlab.com/ee/install/google_cloud_platform/](https://docs.gitlab.com/ee/install/google_cloud_platform/) + +* [Prerequisites](#prerequisites) +* [Creating the VM](#creating-the-vm) +* [Installing GitLab](#installing-gitlab) +* [Next steps](#next-steps) + * [Assigning a static IP](#assigning-a-static-ip) + * [Using a domain name](#using-a-domain-name) + * [Configuring HTTPS with the domain name](#configuring-https-with-the-domain-name) + * [Configuring the email SMTP settings](#configuring-the-email-smtp-settings) +* [Further reading](#further-reading) + +# Installing GitLab on Google Cloud Platform[](#installing-gitlab-on-google-cloud-platform "Permalink") + +本指南将帮助您在[Google Cloud Platform(GCP)](https://cloud.google.com/)实例上安装 GitLab. + +**替代安装方法:** Google 提供了一份白皮书,用于[在 Google Kubernetes Engine 上部署可投入生产的 GitLab](https://cloud.google.com/solutions/deploying-production-ready-gitlab-on-gke) ,包括所有步骤和外部资源配置. 这些是使用 GCP VM 的替代方法,并使用[Cloud native GitLab Helm chart](https://docs.gitlab.com/charts/) . + +## Prerequisites[](#prerequisites "Permalink") + +在 GCP 上安装 GitLab 的前提条件只有两个: + +1. 您需要有一个 Google 帐户. +2. 您需要注册 GCP 计划. 如果您是第一次,Google 会为您提供[$ 300 的信用额,](https://console.cloud.google.com/freetrial)可在 60 天内[免费](https://console.cloud.google.com/freetrial)使用. + +完成这两个步骤后,就可以[创建 VM 了](#creating-the-vm) . + +## Creating the VM[](#creating-the-vm "Permalink") + +要在 GCP 上部署 GitLab,您首先需要创建一个虚拟机: + +1. 转到[https://console.cloud.google.com/compute/instances](https://console.cloud.google.com/compute/instances)并使用您的 Google 凭据登录. +2. 点击**创建** + + [![Search for GitLab](img/9f6f0b27f8e7df6c95a3262de502b39f.png)](img/launch_vm.png) + +3. On the next page, you can select the type of VM as well as the estimated costs. Provide the name of the instance, desired datacenter, and machine type. Note our [hardware requirements for different user base sizes](../requirements.html#hardware-requirements). + + [![Launch on Compute Engine](img/d345ea7938f401127d9471442b27eb27.png)](img/vm_details.png) + +4. 要选择大小,类型和所需的[操作系统](../requirements.html#supported-linux-distributions) ,请在" `Boot disk` **"**下单击" **更改** ". 完成后单击" **选择"** . + +5. 最后,允许 HTTP 和 HTTPS 通信,然后点击**创建** . 该过程将在几秒钟内完成. + +## Installing GitLab[](#installing-gitlab "Permalink") + +几秒钟后,实例将被创建并可以登录.下一步是将 GitLab 安装到实例上. + +[![Deploy settings](img/ad33446e7ba7897d31835424ce5e1feb.png)](img/vm_created.png) + +1. 记下实例的 IP 地址,因为在后续步骤中将需要使用该 IP 地址. +2. 单击 SSH 按钮以连接到实例. +3. 登录到实例后,将出现一个新窗口. + + [![GitLab first sign in](img/e2a52ca7a089fcbd9b17f94875cba0ca.png)](img/ssh_terminal.png) + +4. 接下来,在[https://about.gitlab.com/install/上](https://about.gitlab.com/install/)按照说明为您选择的操作系统安装 GitLab. 您可以将上述步骤中的 IP 地址用作主机名. + +5. 恭喜你! GitLab 现在已安装,您可以通过浏览器访问它. 要完成安装,请在浏览器中打开 URL 并提供初始管理员密码. 该帐户的用户名是`root` . + + [![GitLab first sign in](img/279650b9e9c3ec26a7d6f0493bd5af7c.png)](img/first_signin.png) + +## Next steps[](#next-steps "Permalink") + +这些是首次安装 GitLab 之后要执行的最重要的后续步骤. + +### Assigning a static IP[](#assigning-a-static-ip "Permalink") + +默认情况下,Google 会为您的实例分配一个临时 IP. 如果您要在生产中使用 GitLab 并使用域名,则强烈建议分配一个静态 IP,如下所示. + +阅读 Google 有关如何[提升临时 IP 地址](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address#promote_ephemeral_ip)的文档. + +### Using a domain name[](#using-a-domain-name "Permalink") + +假设您拥有一个域名,并且已正确设置 DNS 以指向在上一步中配置的静态 IP,则可以通过以下方法配置 GitLab 以了解更改: + +1. SSH 进入虚拟机. 您可以轻松使用 Google 控制台中的**SSH**按钮,然后会弹出一个新窗口. + + [![SSH button](img/ad33446e7ba7897d31835424ce5e1feb.png)](img/vm_created.png) + + 将来,您可能想设置[使用 SSH 密钥的连接](https://cloud.google.com/compute/docs/instances/connecting-to-instance) . + +2. 使用您喜欢的文本编辑器编辑 Omnibus GitLab 的配置文件: + + ``` + sudo vim /etc/gitlab/gitlab.rb + ``` + +3. 将`external_url`值设置为您希望 GitLab 在**不使用** `https` **情况下**拥有的域名: + + ``` + external_url 'http://gitlab.example.com' + ``` + + 我们将在下一步中设置 HTTPS,而现在无需这样做. + +4. 重新配置 GitLab,以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +5. 您现在可以使用域名访问 GitLab. + +### Configuring HTTPS with the domain name[](#configuring-https-with-the-domain-name "Permalink") + +尽管不需要,但强烈建议使用 TLS 证书保护 GitLab. 请遵循[Omnibus 文档中](https://docs.gitlab.com/omnibus/settings/nginx.html)的步骤. + +### Configuring the email SMTP settings[](#configuring-the-email-smtp-settings "Permalink") + +您需要正确配置电子邮件 SMTP 设置,否则 GitLab 将无法发送通知电子邮件,例如注释和密码更改. 检查[Omnibus 文档的](https://docs.gitlab.com/omnibus/settings/smtp.html)操作方法. + +## Further reading[](#further-reading "Permalink") + +可以将 GitLab 配置为与其他 OAuth 提供程序,LDAP,SAML,Kerberos 等进行身份验证.以下是您可能感兴趣阅读的一些文档: + +* [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/) +* [Integration documentation](../../integration/README.html) +* [GitLab Pages configuration](../../administration/pages/index.html) +* [GitLab Container Registry configuration](../../administration/packages/container_registry.html) \ No newline at end of file diff --git a/_book/docs/011.md b/_book/docs/011.md new file mode 100644 index 0000000000000000000000000000000000000000..97920a2c475f285239d9eb4f496cf2ab0b5256cc --- /dev/null +++ b/_book/docs/011.md @@ -0,0 +1,754 @@ +# Installing GitLab on Amazon Web Services (AWS) + +> 原文:[https://docs.gitlab.com/ee/install/aws/](https://docs.gitlab.com/ee/install/aws/) + +* [Introduction](#introduction) +* [Requirements](#requirements) +* [Architecture](#architecture) +* [AWS costs](#aws-costs) +* [Create an IAM EC2 instance role and profile](#create-an-iam-ec2-instance-role-and-profile) + * [Create an IAM Policy](#create-an-iam-policy) + * [Create an IAM Role](#create-an-iam-role) +* [Configuring the network](#configuring-the-network) + * [Creating the Virtual Private Cloud (VPC)](#creating-the-virtual-private-cloud-vpc) + * [Subnets](#subnets) + * [Internet Gateway](#internet-gateway) + * [Create NAT Gateways](#create-nat-gateways) + * [Route Tables](#route-tables) + * [Public Route Table](#public-route-table) + * [Private Route Tables](#private-route-tables) +* [Load Balancer](#load-balancer) + * [Configure DNS for Load Balancer](#configure-dns-for-load-balancer) +* [PostgreSQL with RDS](#postgresql-with-rds) + * [RDS Security Group](#rds-security-group) + * [RDS Subnet Group](#rds-subnet-group) + * [Create the database](#create-the-database) +* [Redis with ElastiCache](#redis-with-elasticache) + * [Create a Redis Security Group](#create-a-redis-security-group) + * [Redis Subnet Group](#redis-subnet-group) + * [Create the Redis Cluster](#create-the-redis-cluster) +* [Setting up Bastion Hosts](#setting-up-bastion-hosts) + * [Create Bastion Host A](#create-bastion-host-a) + * [Create Bastion Host B](#create-bastion-host-b) + * [Use SSH Agent Forwarding](#use-ssh-agent-forwarding) +* [Install GitLab and create custom AMI](#install-gitlab-and-create-custom-ami) + * [Install GitLab](#install-gitlab) + * [Add custom configuration](#add-custom-configuration) + * [Disable Let’s Encrypt](#disable-lets-encrypt) + * [Install the `pg_trgm` extension for PostgreSQL](#install-the-pg_trgm-extension-for-postgresql) + * [Configure GitLab to connect to PostgreSQL and Redis](#configure-gitlab-to-connect-to-postgresql-and-redis) + * [Set up Gitaly](#set-up-gitaly) + * [Add Support for Proxied SSL](#add-support-for-proxied-ssl) + * [Fast lookup of authorized SSH keys](#fast-lookup-of-authorized-ssh-keys) + * [Configure host keys](#configure-host-keys) + * [Amazon S3 object storage](#amazon-s3-object-storage) + * [Create custom AMI](#create-custom-ami) +* [Deploy GitLab inside an auto scaling group](#deploy-gitlab-inside-an-auto-scaling-group) + * [Create a launch configuration](#create-a-launch-configuration) + * [Create an auto scaling group](#create-an-auto-scaling-group) + * [Log in for the first time](#log-in-for-the-first-time) +* [Health check and monitoring with Prometheus](#health-check-and-monitoring-with-prometheus) +* [GitLab Runners](#gitlab-runners) +* [Backup and restore](#backup-and-restore) + * [Backing up GitLab](#backing-up-gitlab) + * [Restoring GitLab from a backup](#restoring-gitlab-from-a-backup) +* [Updating GitLab](#updating-gitlab) +* [Conclusion](#conclusion) +* [Troubleshooting](#troubleshooting) + * [Instances are failing health checks](#instances-are-failing-health-checks) + * [“The change you requested was rejected (422)”](#the-change-you-requested-was-rejected-422) + +# Installing GitLab on Amazon Web Services (AWS)[](#installing-gitlab-on-amazon-web-services-aws "Permalink") + +该页面提供了 AWS 上 GitLab 通用配置的演练. 您应该对其进行自定义以满足您的需求. + +**注意:**对于拥有 1,000 个或更少用户的组织,建议的 AWS 安装方法是启动 EC2 单框[Omnibus 安装](https://about.gitlab.com/install/)并实施快照策略以备份数据. 有关更多信息,请参见[1,000 个用户参考体系结构](../../administration/reference_architectures/1k_users.html) . + +## Introduction[](#introduction "Permalink") + +在大多数情况下,我们将在我们的设置中使用 Omnibus GitLab,但我们还将利用本机 AWS 服务. 代替使用 Omnibus 捆绑的 PostgreSQL 和 Redis,我们将使用 AWS RDS 和 ElastiCache. + +在本指南中,我们将进行多节点设置,首先将配置虚拟私有云和子网,以稍后集成服务(例如用于数据库服务器的 RDS 和作为 Redis 集群的 ElastiCache)以最终在一个具有自定义缩放策略的自动缩放组. + +## Requirements[](#requirements "Permalink") + +除了基本了解[AWS](https://docs.aws.amazon.com/)和[Amazon EC2 之外](https://docs.aws.amazon.com/ec2/) ,您还需要: + +* [An AWS account](https://console.aws.amazon.com/console/home) +* [To create or upload an SSH key](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) to connect to the instance via SSH +* GitLab 实例的域名 +* SSL / TLS 证书以保护您的域. 如果您还不拥有该证书,则可以通过[AWS Certificate Manager](https://aws.amazon.com/certificate-manager/) (ACM)设置免费的公共 SSL / TLS 证书,以与我们将创建的[Elastic Load Balancer](#load-balancer)一起使用. + +**注意:**验证通过 ACM 设置的证书可能需要几个小时. 为避免以后出现延迟,请尽快申请您的证书. + +## Architecture[](#architecture "Permalink") + +下面是推荐架构的示意图. + +[![AWS architecture diagram](img/20bba5f798131b98df30aaa9202ccfd5.png)](img/aws_ha_architecture_diagram.png) + +## AWS costs[](#aws-costs "Permalink") + +以下是我们将使用的 AWS 服务的列表,以及指向定价信息的链接: + +* **EC2** :GitLab 将部署在共享硬件上,这意味着将[按需定价](https://aws.amazon.com/ec2/pricing/on-demand/) . 如果要在专用或保留实例上运行它,请参阅[EC2 定价页面](https://aws.amazon.com/ec2/pricing/)以获取有关费用的更多信息. +* **S3** :我们将使用 S3 来存储备份,工件,LFS 对象等.请参阅[Amazon S3 定价](https://aws.amazon.com/s3/pricing/) . +* **ELB** :经典负载均衡器将用于将请求路由到 GitLab 实例. 请参阅[Amazon ELB 定价](https://aws.amazon.com/elasticloadbalancing/pricing/) . +* **RDS** :将使用使用 PostgreSQL 的 Amazon Relational Database Service. 请参阅[Amazon RDS 定价](https://aws.amazon.com/rds/postgresql/pricing/) . +* **ElastiCache** :内存缓存环境将用于提供 Redis 配置. 请参阅[Amazon ElastiCache 定价](https://aws.amazon.com/elasticache/pricing/) . + +## Create an IAM EC2 instance role and profile[](#create-an-iam-ec2-instance-role-and-profile "Permalink") + +由于我们将使用[Amazon S3 对象存储](#amazon-s3-object-storage) ,因此我们的 EC2 实例需要具有对 S3 存储桶的读取,写入和列出权限. 为了避免将 AWS Key 嵌入我们的 GitLab 配置中,我们将利用[IAM 角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)允许 GitLab 实例具有此访问权限. 我们需要创建一个 IAM 策略以附加到我们的 IAM 角色: + +### Create an IAM Policy[](#create-an-iam-policy "Permalink") + +1. 导航到 IAM 仪表板,然后单击左侧菜单中的" **策略** ". +2. 单击**创建策略** ,选择`JSON`选项卡,然后添加策略. 我们希望[遵循安全最佳实践并授予*最少的特权*](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege) ,仅向我们的角色授予执行所需操作所需的权限. + 1. 假设如图所示,在 S3 存储桶名称前添加`gl-`作为前缀,请添加以下策略: + +``` +{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:AbortMultipartUpload", "s3:CompleteMultipartUpload", "s3:ListBucket", "s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:PutObjectAcl" ], "Resource": [ "arn:aws:s3:::gl-*/*" ] } ] } +``` + +1. 点击**审核政策** ,为您的政策命名(我们将使用`gl-s3-policy` ),然后点击**创建政策** . + +### Create an IAM Role[](#create-an-iam-role "Permalink") + +1. 仍在 IAM 仪表板上,单击左侧菜单中的**角色** ,然后单击**创建角色** . +2. 通过选择**AWS 服务> EC2**来创建新角色,然后单击**下一步:权限** . +3. 在策略过滤器中,搜索我们在上面创建的`gl-s3-policy` ,选择它,然后点击**标签** . +4. 根据需要添加标签,然后单击" **查看"** . +5. 为角色命名(我们将使用`GitLabS3Access` ),然后点击**创建角色** . + +稍后[创建启动配置](#create-a-launch-configuration)时,将使用此角色. + +## Configuring the network[](#configuring-the-network "Permalink") + +我们将从为 GitLab 云基础架构创建 VPC 开始,然后我们可以创建子网以在至少两个[可用区(AZ)中](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html)具有公共实例和私有实例. 公共子网将需要保留路由表和关联的 Internet 网关. + +### Creating the Virtual Private Cloud (VPC)[](#creating-the-virtual-private-cloud-vpc "Permalink") + +现在,我们将创建一个 VPC,一个您可以控制的虚拟网络环境: + +1. 导航至[https://console.aws.amazon.com/vpc/home](https://console.aws.amazon.com/vpc/home) . +2. 从左侧菜单中选择**您的 VPC** ,然后单击**创建 VPC** . 在"名称标签"中输入`gitlab-vpc` ,在" IPv4 CIDR 块"中输入`10.0.0.0/16` . 如果不需要专用硬件,则可以将" Tenancy"保留为默认设置. 单击**是,**准备好后**创建** . + + [![Create VPC](img/7cfe14b5f606095866af7260c844d4e2.png)](img/create_vpc.png) + +3. 选择 VPC,单击" **操作"** ,单击" **编辑 DNS 解析"** ,然后启用 DNS 解析. 完成后点击**保存** . + +### Subnets[](#subnets "Permalink") + +现在,让我们在不同的可用区中创建一些子网. 确保每个子网都与我们刚刚创建的 VPC 相关联,并且 CIDR 块不会重叠. 这也将使我们能够启用多可用区以实现冗余. + +我们还将创建专用和公用子网以匹配负载均衡器和 RDS 实例: + +1. 从左侧菜单中选择**子网** . +2. 单击**创建子网** . 给它一个基于 IP 的描述性名称标签,例如`gitlab-public-10.0.0.0` ,选择我们之前创建的 VPC,选择一个可用区(我们将使用`us-west-2a` ),并在 IPv4 CIDR 块上让我们给它一个 24 个子网`10.0.0.0/24` : + + [![Create subnet](img/48482b1410caf250f0257d772e55c544.png)](img/create_subnet.png) + +3. 请按照相同的步骤创建所有子网: + + | 名称标签 | Type | 可用区 | CIDR 块 | + | --- | --- | --- | --- | + | `gitlab-public-10.0.0.0` | public | `us-west-2a` | `10.0.0.0/24` | + | `gitlab-private-10.0.1.0` | private | `us-west-2a` | `10.0.1.0/24` | + | `gitlab-public-10.0.2.0` | public | `us-west-2b` | `10.0.2.0/24` | + | `gitlab-private-10.0.3.0` | private | `us-west-2b` | `10.0.3.0/24` | + +4. 创建所有子网后,请为两个公共子网启用**自动分配 IPv4** : + 1. 依次选择每个公共子网,单击" **操作"** ,然后单击" **修改自动分配 IP 设置"** . 启用该选项并保存. + +### Internet Gateway[](#internet-gateway "Permalink") + +现在,仍然在同一仪表板上,转到 Internet 网关并创建一个新的网关: + +1. 从左侧菜单中选择" **Internet 网关** ". +2. 单击**创建互联网网关** ,为其命名为`gitlab-gateway` ,然后单击**创建** . +3. 从表中选择它,然后在" **操作"**下拉菜单下选择"附加到 VPC". + + [![Create gateway](img/104374dd85800b346ef75734f6fd0b38.png)](img/create_gateway.png) + +4. 从列表中选择`gitlab-vpc` ,然后点击**Attach** . + +### Create NAT Gateways[](#create-nat-gateways "Permalink") + +部署在我们专用子网中的实例需要连接到 Internet 进行更新,但不能从公共 Internet 到达. 为此,我们将利用部署在每个公共子网中的[NAT 网关](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html) : + +1. 导航到 VPC 仪表板,然后单击左侧菜单栏中的**NAT 网关** . +2. 单击**创建 NAT 网关,**然后完成以下操作: + 1. **子网** :从下拉列表中选择`gitlab-public-10.0.0.0` . + 2. **弹性 IP 分配 ID** :输入现有的弹性 IP 或单击**分配弹性 IP 地址,**以将新 IP 分配给您的 NAT 网关. + 3. 如果需要,添加标签. + 4. 单击**创建 NAT 网关** . + +创建第二个 NAT 网关,但这一次将其放置在第二个公共子网`gitlab-public-10.0.2.0` . + +### Route Tables[](#route-tables "Permalink") + +#### Public Route Table[](#public-route-table "Permalink") + +我们需要为公共子网创建路由表,以通过上一步中创建的 Internet 网关访问 Internet. + +在 VPC 仪表板上: + +1. 从左侧菜单中选择**路由表** . +2. Click **创建路由表**. +3. 在"名称标签"中,输入`gitlab-public` , `gitlab-vpc`在" VPC"下选择`gitlab-vpc` . +4. Click **Create**. + +现在,我们需要将我们的 Internet 网关添加为新目标,并使其接收来自任何目的地的流量. + +1. 从左侧菜单中选择" **路由表"** ,然后选择`gitlab-public`路由以在底部显示选项. +2. 选择" **路线"**选项卡,单击" **编辑路线">"添加路线",**然后将`0.0.0.0/0`设置为目的地. 在目标列中,选择我们之前创建的`gitlab-gateway` . 完成后,点击**保存路线** . + +接下来,我们必须将**公共**子网关联到路由表: + +1. Select the **子网关联** tab and click **编辑子网关联**. +2. 仅检查公共子网,然后单击" **保存"** . + +#### Private Route Tables[](#private-route-tables "Permalink") + +我们还需要创建两个私有路由表,以便每个私有子网中的实例都可以通过同一可用性区域中相应公共子网中的 NAT 网关到达 Internet. + +1. 请按照与上述相同的步骤创建两个专用路由表. 将它们`gitlab-private-a`命名为`gitlab-private-a`和`gitlab-private-b` . +2. Next, add a new route to each of the private route tables where the destination is `0.0.0.0/0` and the target is one of the NAT gateways we created earlier. + 1. 将我们在`gitlab-public-10.0.0.0`创建的 NAT 网关添加为`gitlab-private-a`路由表中新路由的目标. + 2. 同样,在`gitlab-public-10.0.2.0`添加 NAT 网关作为`gitlab-private-b`新路由的目标. +3. 最后,将每个专用子网与专用路由表相关联. + 1. 将`gitlab-private-10.0.1.0` `gitlab-private-a`与`gitlab-private-a` . + 2. 将`gitlab-private-10.0.3.0`与`gitlab-private-b` . + +## Load Balancer[](#load-balancer "Permalink") + +我们将创建一个负载平衡器,以在我们的 GitLab 应用程序服务器之间平均分配端口`80`和`443`上的入站流量. 根据我们稍后将创建的[扩展策略](#create-an-auto-scaling-group) ,实例将根据需要添加到负载均衡器中或从负载均衡器中删除. 此外,负载平衡将对我们的实例执行运行状况检查. + +在 EC2 仪表板上,在左侧导航栏中查找 Load Balancer: + +1. 单击**创建负载均衡器**按钮. + 1. 选择**经典负载均衡器** . + 2. 给它`gitlab-loadbalancer` (我们将使用`gitlab-loadbalancer` ),并在**Create LB Inside**选项中,从下拉菜单中选择`gitlab-vpc` . + 3. 在" **侦听器"**部分中,设置以下侦听器: + * 负载均衡器和实例协议以及端口的 HTTP 端口 80 + * 负载均衡器和实例协议以及端口的 TCP 端口 22 + * HTTPS 端口 443(用于负载均衡器协议和端口),转发到实例上的 HTTP 端口 80(我们将[在指南](#add-support-for-proxied-ssl)中将 GitLab 配置为侦听端口 80) + 4. 在" **选择子网"**部分中,从列表中选择两个公共子网,以便负载均衡器可以将流量路由到两个可用区域. +2. 我们将为负载均衡器添加一个安全组,以充当防火墙来控制允许通过的流量. 单击**分配安全组,**然后选择**创建新的安全组** ,为其命名(我们将使用`gitlab-loadbalancer-sec-group` )和说明,并允许来自任何地方的 HTTP 和 HTTPS 通信( `0.0.0.0/0, ::/0` ). 还允许 SSH 流量,选择自定义来源,并以 CIDR 表示法添加单个受信任的 IP 地址或 IP 地址范围. 这将允许用户通过 SSH 执行 Git 操作. +3. 单击**配置安全设置,**然后进行以下设置: + 1. 从 ACM 中选择一个 SSL / TLS 证书或将一个证书上传到 IAM. + 2. 在" **选择密码"下** ,从下拉列表中选择预定义的安全策略. 您可以在 AWS 文档中[查看 Classic Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html)的[预定义 SSL 安全策略](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html)明细. 检查 GitLab 代码库以获取[受支持的 SSL 密码和协议](https://gitlab.com/gitlab-org/gitlab/-/blob/9ee7ad433269b37251e0dd5b5e00a0f00d8126b4/lib/support/nginx/gitlab-ssl#L97-99)的列表. +4. 单击" **配置**运行状况检查",然后为您的 EC2 实例设置运行状况检查. + 1. 对于" **Ping 协议"** ,选择" HTTP". + 2. 对于**Ping 端口** ,输入 80\. + 3. 对于**Ping Path** ,输入`/users/sign_in` . (我们使用`/users/sign_in`因为它是不需要授权的公共端点.) + 4. 保留默认的" **高级详细信息"**或根据需要进行调整. +5. 单击**添加 EC2 实例** -不要添加任何内容,因为稍后我们将创建一个 Auto Scaling 组来为我们管理实例. +6. 单击**添加标签,**然后添加您需要的任何标签. +7. 单击" **查看并创建"** ,查看所有设置,如果满意,请单击" **创建"** . + +在负载均衡器启动并运行后,您可以重新访问安全组以仅通过 ELB 和您可能具有的任何其他要求来完善访问. + +### Configure DNS for Load Balancer[](#configure-dns-for-load-balancer "Permalink") + +在 Route 53 仪表板上,单击左侧导航栏中的" **托管区域** ": + +1. 选择一个现有的托管区域,或者,如果您的域还没有一个,请单击**创建托管区域** ,输入您的域名,然后单击**创建** . +2. 单击**创建记录集,**并提供以下值: + 1. **名称:**使用域名(默认值)或输入一个子域. + 2. **类型:**选择**A-IPv4 地址** . + 3. **别名:**默认为**No.** 选择**是** . + 4. **别名目标:**找到" **ELB 经典负载均衡器"**部分,然后选择我们之前创建的经典负载均衡器. + 5. **路由策略:**我们将使用" **简单",**但您可以根据用例选择其他策略. + 6. **评估目标健康状况:**我们将其设置为" **否",**但是您可以选择让负载均衡器根据目标健康状况来路由流量. + 7. 点击**创建** . +3. 如果您通过 Route 53 注册了域,那么您就完成了. 如果您使用了其他域名注册商,则需要使用域名注册商更新 DNS 记录. 您需要: + 1. 单击**托管区域,**然后选择您在上面添加的域. + 2. 您将看到`NS`记录列表. 在您的域名注册商的管理面板中,将每一个作为`NS`记录添加到您域的 DNS 记录中. 这些步骤在域注册商之间可能会有所不同. 如果您陷入困境,则 Google **"您的注册商名称"会添加 dns 记录** ,您应该会找到针对您的域名注册商的帮助文章. + +根据您使用的注册商的不同,执行此操作的步骤也有所不同,这超出了本指南的范围. + +## PostgreSQL with RDS[](#postgresql-with-rds "Permalink") + +对于我们的数据库服务器,我们将使用提供多可用区以实现冗余的 Amazon RDS. 首先,我们将创建一个安全组和子网组,然后将创建实际的 RDS 实例. + +### RDS Security Group[](#rds-security-group "Permalink") + +我们需要一个用于数据库的安全组,该安全组将允许稍后将在`gitlab-loadbalancer-sec-group`部署的实例的入站流量: + +1. 在 EC2 仪表板中,从左侧菜单栏中选择" **安全组** ". +2. Click **创建安全组**. +3. 给它起一个名字(我们将使用`gitlab-rds-sec-group` ),一个描述,并从**VPC**下拉列表中选择`gitlab-vpc` . +4. 在" **入站规则"**部分中,单击" **添加规则"**并进行以下设置: + 1. **键入:**搜索并选择**PostgreSQL**规则. + 2. **来源类型:**设置为"自定义". + 3. **来源:**选择我们之前创建的`gitlab-loadbalancer-sec-group` . +5. 完成后,点击**创建安全组** . + +### RDS Subnet Group[](#rds-subnet-group "Permalink") + +1. 导航到 RDS 仪表板,然后从左侧菜单中选择" **子网组** ". +2. 单击**创建数据库子网组** . +3. 在" **子网组详细信息"下** ,输入名称(我们将使用`gitlab-rds-group` ),描述,然后从 VPC 下拉列表中选择`gitlab-vpc` . +4. 从" **可用区"**下拉列表中,选择包括您已配置的子网的可用区. 在本例中,我们将添加`eu-west-2a`和`eu-west-2b` . +5. 从**子网**下拉列表中,选择两个专用子网( `10.0.1.0/24`和`10.0.3.0/24` ,因为我们在定义它们) [的子网部分](#subnets) . +6. 准备好后,单击**创建** . + +### Create the database[](#create-the-database "Permalink") + +**危险:**避免对数据库使用易爆实例(t 类实例),因为由于 CPU 信用在持续的高负载期间用尽而可能导致性能问题. + +现在,该创建数据库了: + +1. 导航到 RDS 仪表板,从左侧菜单中选择" **数据库** ",然后单击" **创建数据库"** . +2. 选择**标准创建**作为数据库创建方法. +3. 选择**PostgreSQL**作为数据库引擎,然后选择在[数据库要求中](../../install/requirements.html#postgresql-requirements)为您的 GitLab 版本定义的最低 PostgreSQL 版本. +4. 由于这是生产服务器,因此我们从" **模板"**部分中选择" **生产** ". +5. 在**"设置"下** ,设置数据库实例标识符,主用户名和主密码. 我们将分别使用`gitlab-db-ha` , `gitlab`和一个非常安全的密码. 记下这些内容,稍后我们将需要它们. +6. 对于数据库实例大小,请选择" **标准类",**然后从下拉菜单中选择一个满足您要求的实例大小. 我们将使用`db.m4.large`实例. +7. 在" **存储"下** ,配置以下内容: + 1. 从存储类型下拉菜单中选择" **Provisioned IOPS(SSD)** ". 预置 IOPS(SSD)存储最适合此用途(尽管您可以选择 General Purpose(SSD)来降低成本). 在[Amazon RDS 的存储中](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html)阅读有关它的更多信息. + 2. 分配存储并设置预配置的 IOPS. 我们将分别使用最小值`100`和`1000` . + 3. 启用存储自动缩放(可选)并设置最大存储阈值. +8. 在" **可用性和持久性"下** ,选择" **创建备用实例"**以在另一个可用[区中](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html)配置备用 RDS 实例. +9. 在" **连接性"下** ,配置以下内容: + 1. 从**虚拟私有云(VPC)**下拉菜单中选择我们之前创建的 VPC( `gitlab-vpc` ). + 2. 展开**其他连接配置**部分,然后选择我们之前创建的子网组( `gitlab-rds-group` ). + 3. 设置公众了解**没有** . + 4. 在**VPC 安全组下** ,选择**选择现有,**然后从下拉列表中选择我们在上面创建的`gitlab-rds-sec-group` . + 5. 将数据库端口保留为默认值`5432` . +10. 对于**数据库身份验证** ,选择**密码身份验证** . +11. 展开**其他配置**部分,并完成以下操作: + 1. 初始数据库名称. 我们将使用`gitlabhq_production` . + 2. 配置您的首选备份设置. + 3. 我们将在此处进行的唯一其他更改是禁用" **维护"**下的自动次要版本更新. + 4. 保留所有其他设置不变或根据需要进行调整. + 5. 满意后,点击**创建数据库** . + +现在已经创建了数据库,让我们继续使用 ElastiCache 设置 Redis. + +## Redis with ElastiCache[](#redis-with-elasticache "Permalink") + +ElastiCache 是​​一个内存托管的缓存解决方案. Redis 保持其自身的持久性,并用于为 GitLab 应用程序存储会话数据,临时缓存信息和后台作业队列. + +### Create a Redis Security Group[](#create-a-redis-security-group "Permalink") + +1. 导航到 EC2 仪表板. +2. 从左侧菜单中选择" **安全组** ". +3. 单击**创建安全组,**然后填写详细信息. 给它`gitlab-redis-sec-group` (我们将使用`gitlab-redis-sec-group` ),添加描述,然后选择我们之前创建的 VPC +4. 在" **入站规则"**部分中,单击" **添加规则"**并添加一个" **自定义 TCP"**规则,设置端口`6379` ,并将"自定义"源设置为我们之前创建的`gitlab-loadbalancer-sec-group` . +5. 完成后,点击**创建安全组** . + +### Redis Subnet Group[](#redis-subnet-group "Permalink") + +1. 从您的 AWS 控制台导航到 ElastiCache 仪表板. +2. 转到左侧菜单中的" **子网组** ",然后创建一个新的子网组(我们将其命名为`gitlab-redis-group` ). 确保选择我们的 VPC 及其[专用子网](#subnets) . 准备好后,单击**创建** . + + [![ElastiCache subnet](img/98f7e80b6f738f9886082aeec3955fd5.png)](img/ec_subnet.png) + +### Create the Redis Cluster[](#create-the-redis-cluster "Permalink") + +1. 导航回到 ElastiCache 仪表板. +2. 在左侧菜单上选择**Redis** ,然后单击**创建**以创建新的 Redis 集群. 不要启用**集群模式,**因为它[不受支持](../../administration/redis/replication_and_failover_external.html#requirements) . 即使没有启用群集模式,您仍然有机会在多个可用性区域中部署 Redis. +3. 在设置部分: + 1. 为集群命名( `gitlab-redis` )和描述. + 2. 对于版本,选择最新的`5.0`系列(例如`5.0.6` ). + 3. 将端口保留为`6379`因为这是我们在上面的 Redis 安全组中使用的端口. + 4. 选择节点类型(至少为`cache.t3.medium` ,但根据需要进行调整)和副本数. +4. 在高级设置部分: + 1. 选择多可用区自动故障转移选项. + 2. 选择我们之前创建的子网组. + 3. 手动选择首选的可用区域,然后在"副本 2"下选择与其他两个区域不同的区域. + + [![Redis 可用区](img/38ef5bf427869fe9b1050db6eacd2972.png)](img/ec_az.png) + +5. 在安全设置中,编辑安全组,然后选择我们之前创建的`gitlab-redis-sec-group` . +6. 将其余设置保留为默认值,或根据自己的喜好进行编辑. +7. 完成后,点击**创建** . + +## Setting up Bastion Hosts[](#setting-up-bastion-hosts "Permalink") + +由于我们的 GitLab 实例将位于专用子网中,因此我们需要一种通过 SSH 连接到这些实例以进行配置更改,执行升级等的方法.一种方法是通过[堡垒主机](https://en.wikipedia.org/wiki/Bastion_host) ,有时也称为跳转框. + +**提示:**如果您不想维护堡垒主机,则可以设置[AWS Systems Manager Session Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html)来访问实例. 这超出了本文档的范围. + +### Create Bastion Host A[](#create-bastion-host-a "Permalink") + +1. 导航到 EC2 仪表板,然后单击**Launch instance** . +2. 选择**Ubuntu Server 18.04 LTS(HVM)** AMI. +3. 选择一个实例类型. 我们将使用`t2.micro`因为我们仅使用堡垒主机将 SSH SSH 到我们的其他实例中. +4. Click **配置实例详细信息**. + 1. 在" **网络"下** ,从下拉菜单中选择`gitlab-vpc` . + 2. 在" **子网"下** ,选择我们之前创建的公共子网( `gitlab-public-10.0.0.0` ). + 3. 仔细检查是否在" **自动分配公用 IP"下**选择了" **使用子网设置"("启用")** . + 4. 将其他所有内容保留为默认值,然后单击" **添加存储"** . +5. 对于存储,我们将所有内容保留为默认设置,仅添加 8GB 根卷. 我们不会在此实例上存储任何内容. +6. 单击**添加标签** ,然后在下一个屏幕上单击**添加标签** . + 1. 我们只设置`Key: Name`和`Value: Bastion Host A` +7. Click **配置安全组**. + 1. 选择**创建新的安全组** ,输入**安全组名称** (我们将使用`bastion-sec-group` ),然后添加描述. + 2. 我们将从任何地方( `0.0.0.0/0` )启用 SSH 访问. 如果需要更严格的安全性,请以 CIDR 表示法指定单个 IP 地址或 IP 地址范围. + 3. Click **审查并启动** +8. Review all your settings and, if you’re happy, click **Launch**. +9. 确认您有权访问现有的密钥对或创建一个新的密钥对. 单击**启动实例** . + +确认您可以通过 SSH 进入实例: + +1. 在 EC2 仪表板上,单击左侧菜单中的**Instances** . +2. 从实例列表中选择**Bastion HostA** . +3. 单击**连接,**然后按照连接说明进行操作. +4. 如果能够成功连接,让我们继续设置第二个堡垒主机以实现冗余. + +### Create Bastion Host B[](#create-bastion-host-b "Permalink") + +1. 按照与上述相同的步骤创建 EC2 实例,并进行以下更改: + 1. 对于**Subnet** ,选择我们之前创建的第二个公共子网( `gitlab-public-10.0.2.0` ). + 2. 在" **添加标签"**部分下,我们将设置" `Key: Name`和`Value: Bastion Host B`以便我们可以轻松识别两个实例. + 3. 对于安全组,选择我们上面创建的现有`bastion-sec-group` . + +### Use SSH Agent Forwarding[](#use-ssh-agent-forwarding "Permalink") + +运行 Linux 的 EC2 实例使用私钥文件进行 SSH 身份验证. 您将使用 SSH 客户端和存储在客户端上的私钥文件连接到堡垒主机. 由于私有密钥文件不存在于堡垒主机上,因此您将无法连接到私有子网中的实例. + +在堡垒主机上存储私钥文件是一个坏主意. 要解决此问题,请在客户端上使用 SSH 代理转发. 有关如何使用 SSH 代理转发的分步指南,请参阅[安全连接到在私有 Amazon VPC 中运行的 Linux 实例](https://aws.amazon.com/blogs/security/securely-connect-to-linux-instances-running-in-a-private-amazon-vpc/) . + +## Install GitLab and create custom AMI[](#install-gitlab-and-create-custom-ami "Permalink") + +我们将需要预先配置的自定义 GitLab AMI,以便稍后在我们的启动配置中使用. 首先,我们将使用官方的 GitLab AMI 创建 GitLab 实例. 然后,我们将为 PostgreSQL,Redis 和 Gitaly 添加自定义配置. 如果愿意,您也可以使用自己选择的 EC2 实例启动并[手动安装 GitLab](https://about.gitlab.com/install/) ,而不是使用官方的 GitLab AMI. + +### Install GitLab[](#install-gitlab "Permalink") + +从 EC2 仪表板: + +1. 单击**启动实例,**然后从左侧菜单中选择**社区 AMI** . +2. 在搜索栏中,搜索`GitLab EE ` ,其中``是[发行页面](https://about.gitlab.com/releases/)上显示的最新版本. 选择最新的补丁程序版本,例如`GitLab EE 12.9.2` . +3. 根据您的工作量选择一个实例类型. 请查阅[硬件要求,](../../install/requirements.html#hardware-requirements)以选择适合您需求的[硬件](../../install/requirements.html#hardware-requirements) (至少`c5.xlarge` ,足以容纳 100 位用户). +4. Click **配置实例详细信息**: + 1. 在" **网络"**下拉列表中,选择`gitlab-vpc` ,这是我们之前创建的 VPC. + 2. 在" **子网"**下拉列表中,从我们先前创建的**子网**列表中选择`gitlab-private-10.0.1.0` . + 3. 仔细检查是否将" **自动分配公用 IP"**设置为" `Use subnet setting (Disable)` . + 4. Click **添加存储**. + 5. 默认情况下,根卷为 8GiB,并且在我们不会在其中存储任何数据的情况下,根卷应该足够. +5. 单击**添加标签,**然后添加您可能需要的任何标签. 在本例中,我们将仅设置`Key: Name`和`Value: GitLab` . +6. 单击**配置安全组** . 选中**选择现有安全组,**然后选择我们之前创建的`gitlab-loadbalancer-sec-group` . +7. 如果对设置满意,请单击**查看并启动,**然后单击**启动** . +8. 最后,确认您有权访问所选的私钥文件或创建一个新的私钥文件. 单击**启动实例** . + +### Add custom configuration[](#add-custom-configuration "Permalink") + +使用[SSH 代理转发](#use-ssh-agent-forwarding)通过**Bastion Host A**连接到您的 GitLab 实例. 连接后,添加以下自定义配置: + +#### Disable Let’s Encrypt[](#disable-lets-encrypt "Permalink") + +由于我们要在负载均衡器中添加 SSL 证书,因此我们不需要 GitLab 对 Let's Encrypt 的内置支持. 自 GitLab 10.7 起,使用`https`域时[,默认情况下启用](https://docs.gitlab.com/omnibus/settings/ssl.html)加密[功能](https://docs.gitlab.com/omnibus/settings/ssl.html) ,因此我们需要显式禁用它: + +1. 打开`/etc/gitlab/gitlab.rb`并禁用它: + + ``` + letsencrypt['enable'] = false + ``` + +2. 保存文件并重新配置以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +#### Install the `pg_trgm` extension for PostgreSQL[](#install-the-pg_trgm-extension-for-postgresql "Permalink") + +在您的 GitLab 实例中,连接到 RDS 实例以验证访问权限并安装所需的`pg_trgm`扩展. + +要查找主机或终端节点,请导航至**Amazon RDS>数据库** ,然后单击您之前创建的数据库. 在" **连接性和安全性"**选项卡下查找端点. + +不要包括冒号和端口号: + +``` +sudo /opt/gitlab/embedded/bin/psql -U gitlab -h -d gitlabhq_production +``` + +在`psql`提示符下,创建扩展,然后退出会话: + +``` +psql (10.9) +Type "help" for help. + +gitlab=# CREATE EXTENSION pg_trgm; +gitlab=# \q +``` + +#### Configure GitLab to connect to PostgreSQL and Redis[](#configure-gitlab-to-connect-to-postgresql-and-redis "Permalink") + +1. 编辑`/etc/gitlab/gitlab.rb` ,找到`external_url 'http://'`选项并将其更改为您将使用的`https`域. + +2. 查找 GitLab 数据库设置,并根据需要取消注释. 在当前情况下,我们将指定数据库适配器,编码,主机,名称,用户名和密码: + + ``` + # Disable the built-in Postgres + postgresql['enable'] = false + + # Fill in the connection details + gitlab_rails['db_adapter'] = "postgresql" + gitlab_rails['db_encoding'] = "unicode" + gitlab_rails['db_database'] = "gitlabhq_production" + gitlab_rails['db_username'] = "gitlab" + gitlab_rails['db_password'] = "mypassword" + gitlab_rails['db_host'] = "" + ``` + +3. 接下来,我们需要通过添加主机并取消注释端口来配置 Redis 部分: + + ``` + # Disable the built-in Redis + redis['enable'] = false + + # Fill in the connection details + gitlab_rails['redis_host'] = "" + gitlab_rails['redis_port'] = 6379 + ``` + +4. 最后,重新配置 GitLab 以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +5. 您可能还会发现运行检查和服务状态以确保一切均已正确设置很有用: + + ``` + sudo gitlab-rake gitlab:check + sudo gitlab-ctl status + ``` + +#### Set up Gitaly[](#set-up-gitaly "Permalink") + +**注意:**在这种体系结构中,只有一台 Gitaly 服务器会造成单点故障. 使用[Gitaly Cluster](../../administration/gitaly/praefect.html)可以消除此限制. + +Gitaly 是一项服务,它提供对 Git 存储库的高级 RPC 访问. 应该在我们之前配置的[专用子网](#subnets)之一中的单独 EC2 实例上启用和配置它. + +让我们创建一个安装 Gitaly 的 EC2 实例: + +1. 在 EC2 仪表板中,单击**启动实例** . +2. 选择一个 AMI. 在此示例中,我们将选择**Ubuntu Server 18.04 LTS(HVM),SSD Volume Type** . +3. Choose an instance type. We’ll pick a **c5.xlarge**. +4. Click **配置实例详细信息**. + 1. 在" **网络"**下拉列表中,选择`gitlab-vpc` ,这是我们之前创建的 VPC. + 2. 在" **子网"**下拉列表中,从我们先前创建的**子网**列表中选择`gitlab-private-10.0.1.0` . + 3. 仔细检查是否将" **自动分配公用 IP"**设置为" `Use subnet setting (Disable)` . + 4. Click **添加存储**. +5. 将根卷大小增加到`20 GiB` ,并将**卷类型**更改为`Provisoned IOPS SSD (io1)` . (这是一个任意大小.创建一个足以满足您的存储库存储需求的卷.) + 1. 对于**IOPS**设置`1000` (20 GiB x 50 IOPS). 每个 GiB 最多可以配置 50 IOPS. 如果选择更大的音量,请相应地增加 IOPS. 以串行方式写入许多小文件的工作负载(如`git` )需要高性能的存储,因此选择`Provisoned IOPS SSD (io1)` . +6. 单击**添加标签**并添加您的标签. 在本例中,我们将仅设置`Key: Name`和`Value: Gitaly` . +7. 单击" **配置安全组",**然后**创建一个新的安全组** . + 1. 给您的安全组一个名称和描述. 我们将同时使用`gitlab-gitaly-sec-group` . + 2. 创建一个**自定义 TCP**规则,并将端口`8075`添加到" **端口范围"中** . 对于**Source** ,选择`gitlab-loadbalancer-sec-group` . + 3. 还要从`bastion-sec-group`添加 SSH 的入站规则,以便我们可以使用来自堡垒主机的[SSH 代理转发](#use-ssh-agent-forwarding)进行连接. +8. 如果对设置满意,请单击**查看并启动,**然后单击**启动** . +9. 最后,确认您有权访问所选的私钥文件或创建一个新的私钥文件. 单击**启动实例** . + +**注意:**除了将配置*和*存储库数据存储在根卷上之外,您还可以选择添加其他 EBS 卷用于存储库存储. 请遵循上述相同的指导. 请参阅[Amazon EBS 定价](https://aws.amazon.com/ebs/pricing/) . 我们不建议使用 EFS,因为它可能会对 GitLab 的性能产生负面影响. 您可以查看[相关文档](../../administration/high_availability/nfs.html#avoid-using-awss-elastic-file-system-efs)以了解更多详细信息. + +现在我们已经准备好我们的 EC2 实例,请按照[文档安装 GitLab 并在其自己的服务器上设置 Gitaly](../../administration/gitaly/index.html#run-gitaly-on-its-own-server) . 在[我们](#install-gitlab)上面[创建](#install-gitlab)的[GitLab 实例](#install-gitlab)上,从该文档执行客户端设置步骤. + +#### Add Support for Proxied SSL[](#add-support-for-proxied-ssl "Permalink") + +当我们在[负载均衡器](#load-balancer)处终止 SSL 时,请按照[支持代理的 SSL 中](https://docs.gitlab.com/omnibus/settings/nginx.html)的步骤在`/etc/gitlab/gitlab.rb`进行配置. + +将更改保存到`gitlab.rb`文件后,切记要运行`sudo gitlab-ctl reconfigure` . + +#### Fast lookup of authorized SSH keys[](#fast-lookup-of-authorized-ssh-keys "Permalink") + +允许访问 GitLab 的用户的公共 SSH 密钥存储在`/var/opt/gitlab/.ssh/authorized_keys` . 通常,我们会使用共享存储,以便当用户通过 SSH 执行 Git 操作时,所有实例都能够访问该文件. 由于我们的设置中没有共享存储,因此我们将更新配置,以通过 GitLab 数据库中的索引查找来授权 SSH 用户. + +按照[通过 GitLab Shell 设置快速查找中](../../administration/operations/fast_ssh_key_lookup.html#setting-up-fast-lookup-via-gitlab-shell)的说明,从使用`authorized_keys`文件切换到数据库. + +如果不配置快速查找,则通过 SSH 进行的 Git 操作将导致以下错误: + +``` +Permission denied (publickey). +fatal: Could not read from remote repository. + +Please make sure you have the correct access rights +and the repository exists. +``` + +#### Configure host keys[](#configure-host-keys "Permalink") + +通常,我们将手动将主应用程序服务器上`/etc/ssh/`的内容(主密钥和公共密钥)复制到所有辅助服务器上的`/etc/ssh` . 这样可以防止在访问负载均衡器后面的群集中的服务器时出现虚假的中间人攻击警报. + +我们将通过创建静态主机密钥作为自定义 AMI 的一部分来自动执行此操作. 由于每次 EC2 实例启动时也会旋转这些主机密钥,因此将它们"硬编码"到我们的自定义 AMI 中是一种方便的解决方法. + +在您的 GitLab 实例上运行以下命令: + +``` +sudo mkdir /etc/ssh_static +sudo cp -R /etc/ssh/* /etc/ssh_static +``` + +在`/etc/ssh/sshd_config`更新以下内容: + +``` +# HostKeys for protocol version 2 +HostKey /etc/ssh_static/ssh_host_rsa_key +HostKey /etc/ssh_static/ssh_host_dsa_key +HostKey /etc/ssh_static/ssh_host_ecdsa_key +HostKey /etc/ssh_static/ssh_host_ed25519_key +``` + +#### Amazon S3 object storage[](#amazon-s3-object-storage "Permalink") + +由于我们不使用 NFS 进行共享存储,因此我们将使用[Amazon S3](https://aws.amazon.com/s3/)存储桶来存储备份,工件,LFS 对象,上传,合并请求差异,容器注册表映像等等. 我们的文档包括[有关如何](../../administration/object_storage.html)为每种数据类型[配置对象存储的说明](../../administration/object_storage.html) ,以及有关在 GitLab 中使用对象存储的其他信息. + +**注意:**由于我们使用的是之前创建的[AWS IAM 配置文件](#create-an-iam-role) ,因此在配置对象存储时,请确保省略 AWS 访问密钥和秘密访问密钥/值对. 而是在您的配置中使用`'use_iam_profile' => true` ,如上面链接的对象存储文档中所示. + +将更改保存到`gitlab.rb`文件后,切记要运行`sudo gitlab-ctl reconfigure` . + +**注意:** GitLab 的当前一项功能仍需要共享目录(NFS),即[GitLab Pages](../../user/project/pages/index.html) . 目前[正在进行的工作](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196) ,以消除支持 GitLab 页面需要 NFS. + +* * * + +到此,我们的 GitLab 实例的配置更改结束了. 接下来,我们将基于该实例创建自定义 AMI,以用于我们的启动配置和自动缩放组. + +### Create custom AMI[](#create-custom-ami "Permalink") + +在 EC2 仪表板上: + +1. 选择我们[之前创建](#install-gitlab)的`GitLab`实例. +2. 单击" **操作"** ,向下滚动到" **图像"** ,然后单击" **创建图像"** . +3. 给您的图像起一个名称和描述(我们将同时使用`GitLab-Source` ). +4. 将其他所有内容保留为默认值,然后单击**创建图像** + +现在,我们有了一个定制的 AMI,将用于下一步创建启动配置. + +## Deploy GitLab inside an auto scaling group[](#deploy-gitlab-inside-an-auto-scaling-group "Permalink") + +### Create a launch configuration[](#create-a-launch-configuration "Permalink") + +从 EC2 仪表板: + +1. 从左侧菜单中选择**启动配置** ,然后单击**创建启动配置** . +2. 从左侧菜单中选择**我的 AMI** ,然后选择我们在上面创建的`GitLab`自定义 AMI. +3. 选择最适合您需求的实例类型(至少为`c5.xlarge` ),然后单击**配置详细信息** . +4. 输入启动配置的名称(我们将使用`gitlab-ha-launch-config` ). +5. **不要** check **请求竞价型实例**. +6. 从**IAM 角色**下拉列表中,选择我们[之前创建](#create-an-iam-ec2-instance-role-and-profile)的`GitLabAdmin`实例角色. +7. 将其余的保留为默认值,然后单击" **添加存储"** . +8. 默认情况下,根卷为 8GiB,并且在我们不会在其中存储任何数据的情况下,根卷应该足够. 单击**配置安全组** . +9. 选中**选择和现有安全组,**然后选择我们之前创建的`gitlab-loadbalancer-sec-group` . +10. 点击**查看** ,查看您的更改,然后点击**创建启动配置** . +11. 确认您有权访问私钥或创建一个新私钥. 单击**创建启动配置** . + +### Create an auto scaling group[](#create-an-auto-scaling-group "Permalink") + +1. 创建启动配置后,您将看到一个**使用此启动配置创建 Auto Scaling 组**的选项. 单击以开始创建自动缩放组. +2. 输入一个**组名** (我们将使用`gitlab-auto-scaling-group` ). +3. 对于**Group size** ,输入您要开始的实例数(我们将输入`2` ). +4. 从" **网络"**下拉列表中选择`gitlab-vpc` . +5. 添加[我们先前创建的](#subnets)两个专用[子网](#subnets) . +6. 展开" **高级详细信息"**部分,然后选中" **从一个或多个负载平衡器接收流量"**选项. +7. 从**经典负载均衡器**下拉列表中,选择我们之前创建的负载均衡器. +8. For **健康检查类型**, select **ELB**. +9. 我们将" **健康检查宽限期"**保留为默认的`300`秒. 单击" **配置扩展策略"** . +10. Check **使用扩展策略来调整该组的容量**. +11. 对于该组,我们将在 2 到 4 个实例之间扩展,如果 CPU 利用率大于 60%将添加一个实例,如果 CPU 利用率小于 45%则删除一个实例. + +[![Auto scaling group policies](img/36aa502eb297ed552d82e3b015053e9e.png)](img/policies.png) + +1. 最后,根据需要配置通知和标签,查看更改并创建自动缩放组. + +创建自动伸缩组后,您将在 EC2 仪表板中看到新实例. 您还将看到新实例添加到您的负载均衡器. 一旦实例通过健康检查,它们就准备开始从负载平衡器接收流量. + +由于我们的实例是由自动缩放组创建的,因此请返回您的实例并终止[我们在上面手动创建](#install-gitlab)的[实例](#install-gitlab) . 我们只需要该实例即可创建我们的自定义 AMI. + +### Log in for the first time[](#log-in-for-the-first-time "Permalink") + +现在,使用[为负载均衡器](#configure-dns-for-load-balancer)设置[DNS](#configure-dns-for-load-balancer)时使用的域名,您现在应该能够在浏览器中访问 GitLab. 首次要求您为在 GitLab 实例上具有管理员权限的`root`用户设置密码. + +设置后,使用用户名`root`和新创建的密码登录. + +## Health check and monitoring with Prometheus[](#health-check-and-monitoring-with-prometheus "Permalink") + +除了可以在各种服务上启用的 Amazon Cloudwatch 之外,GitLab 还提供了自己的基于 Prometheus 的集成监控解决方案. 有关如何设置的更多信息,请访问[GitLab Prometheus 文档.](../../administration/monitoring/prometheus/index.html) + +GitLab 还具有各种[运行状况检查端点](../../user/admin_area/monitoring/health_check.html) ,您可以对其进行 ping 操作并获取报告. + +## GitLab Runners[](#gitlab-runners "Permalink") + +如果要利用[GitLab CI / CD](../../ci/README.html) ,则必须至少设置一个[GitLab Runner](https://docs.gitlab.com/runner/) . + +阅读有关[在 AWS](https://docs.gitlab.com/runner/configuration/runner_autoscale_aws/)上配置[自动缩放 GitLab Runner 的](https://docs.gitlab.com/runner/configuration/runner_autoscale_aws/)更多信息. + +## Backup and restore[](#backup-and-restore "Permalink") + +GitLab 提供[了一个备份](../../raketasks/backup_restore.html#back-up-gitlab)和还原其 Git 数据,数据库,附件,LFS 对象等的工具. + +一些重要的事情要知道: + +* 备份/还原工具**不**存储某些配置文件,例如机密. 您需要[自己配置](../../raketasks/backup_restore.html#storing-configuration-files) . +* 默认情况下,备份文件存储在本地,但是您可以[使用 S3 备份 GitLab](../../raketasks/backup_restore.html#using-amazon-s3) . +* 您可以[从备份中排除特定目录](../../raketasks/backup_restore.html#excluding-specific-directories-from-the-backup) . + +### Backing up GitLab[](#backing-up-gitlab "Permalink") + +备份 GitLab: + +1. SSH 进入您的实例. +2. 备份: + + ``` + sudo gitlab-backup create + ``` + +**注意:**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +### Restoring GitLab from a backup[](#restoring-gitlab-from-a-backup "Permalink") + +To restore GitLab, first review the [restore documentation](../../raketasks/backup_restore.html#restore-gitlab), and primarily the restore prerequisites. Then, follow the steps under the [Omnibus installations section](../../raketasks/backup_restore.html#restore-for-omnibus-gitlab-installations). + +## Updating GitLab[](#updating-gitlab "Permalink") + +GitLab 于 22 日每月发布一个新版本. 每当发布新版本时,您都可以更新您的 GitLab 实例: + +1. SSH 进入您的实例 +2. 备份: + + ``` + sudo gitlab-backup create + ``` + +**注意:**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +1. 更新存储库并安装 GitLab: + + ``` + sudo apt update + sudo apt install gitlab-ee + ``` + +几分钟后,新版本应已启动并正在运行. + +## Conclusion[](#conclusion "Permalink") + +在本指南中,我们主要进行了缩放和一些冗余选项,您的里程可能会有所不同. + +请记住,所有解决方案都需要在成本/复杂性和正常运行时间之间进行权衡. 您想要的正常运行时间越长,解决方案就越复杂. 解决方案越复杂,设置和维护该解决方案所涉及的工作就越多. + +通读以下其他资源,并随时[提出问题](https://gitlab.com/gitlab-org/gitlab/-/issues/new)以请求其他材料: + +* [扩展 GitLab](../../administration/reference_architectures/index.html) :GitLab 支持几种不同类型的集群. +* [Geo 复制](../../administration/geo/replication/index.html) :Geo 是面向广泛分布的开发团队的解决方案. +* [Omnibus GitLab-](https://docs.gitlab.com/omnibus/)您需要了解的有关管理 GitLab 实例的所有信息. +* [上载许可证](../../user/admin_area/license.html) : [使用许可证](../../user/admin_area/license.html)激活所有的 GitLab Enterprise Edition 功能. +* [定价](https://about.gitlab.com/pricing/) :不同层级的定价. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Instances are failing health checks[](#instances-are-failing-health-checks "Permalink") + +如果您的实例未通过负载均衡器的运行状况检查,请验证它们是否从我们之前配置的运行状况检查终结点返回状态`200` . 任何其他状态,包括重定向(例如状态`302` ),都会导致运行状况检查失败. + +您可能必须在`root`用户上设置密码,以防止在运行状况检查通过之前在登录端点上进行自动重定向. + +### “The change you requested was rejected (422)”[](#the-change-you-requested-was-rejected-422 "Permalink") + +如果你看到这个页面,试图设置通过网络界面输入密码时,请确保`external_url`在`gitlab.rb`你正在从一个请求域,并运行匹配`sudo gitlab-ctl reconfigure`进行任何更改之后. \ No newline at end of file diff --git a/_book/docs/012.md b/_book/docs/012.md new file mode 100644 index 0000000000000000000000000000000000000000..a2446ee93c4059a4196535aa608014b207485b1b --- /dev/null +++ b/_book/docs/012.md @@ -0,0 +1,40 @@ +# Analytics + +> 原文:[https://docs.gitlab.com/ee/user/analytics/](https://docs.gitlab.com/ee/user/analytics/) + +* [Analytics workspace](#analytics-workspace) +* [Group-level analytics](#group-level-analytics) +* [Project-level analytics](#project-level-analytics) + +# Analytics[](#analytics "Permalink") + +## Analytics workspace[](#analytics-workspace "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12077) . + +通过 Analytics(分析)工作区,可以跨 GitLab 汇总分析,以便用户可以在一个地方查看多个项目和组中的信息. + +要访问 Google Analytics(分析)工作区,请单击顶部导航栏中的**更多>分析** . + +## Group-level analytics[](#group-level-analytics "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/195979) . + +在组级别可以使用以下分析功能: + +* [Contribution](../group/contribution_analytics/index.html). +* [Insights](../group/insights/index.html). +* [Issues](../group/issues_analytics/index.html). +* [生产力](productivity_analytics.html) (通过`productivity_analytics` [功能标记](../../development/feature_flags/development.html#enabling-a-feature-flag-in-development)启用). +* [值流](value_stream_analytics.html) ,通过`cycle_analytics` [功能标记](../../development/feature_flags/development.html#enabling-a-feature-flag-in-development)启用. + +## Project-level analytics[](#project-level-analytics "Permalink") + +在项目级别可以使用以下分析功能: + +* [CI/CD](../../ci/pipelines/index.html#pipeline-success-and-duration-charts). +* [Code Review](code_review_analytics.html). +* [Insights](../group/insights/index.html). +* [Issues](../group/issues_analytics/index.html). +* [Repository](repository_analytics.html). +* [值流](value_stream_analytics.html) ,通过`cycle_analytics` [功能标记](../../development/feature_flags/development.html#enabling-a-feature-flag-in-development)启用. \ No newline at end of file diff --git a/_book/docs/013.md b/_book/docs/013.md new file mode 100644 index 0000000000000000000000000000000000000000..8743ce152e598a049b28436eb559af5e5cd70437 --- /dev/null +++ b/_book/docs/013.md @@ -0,0 +1,49 @@ +# Code Review Analytics + +> 原文:[https://docs.gitlab.com/ee/user/analytics/code_review_analytics.html](https://docs.gitlab.com/ee/user/analytics/code_review_analytics.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Permissions](#permissions) + +# Code Review Analytics[](#code-review-analytics-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38062) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.7. + +通过 Code Review Analytics,可以轻松地查看打开的合并请求中运行时间最长的审查,从而使您可以对单个合并请求采取措施,并缩短总体周期. + +**注意:**最初,不会显示任何数据. 用户在打开的合并请求中发表评论时,将填充数据. + +## Overview[](#overview "Permalink") + +Code Review Analytics 显示一个打开的合并请求表,该请求至少具有一个非作者注释. 审阅时间从提交第一个非作者评论的时间开始计算. 合并请求的代码审阅时间自动标识为自第一个非作者评论以来的时间. + +要访问 Code Review Analytics,请从您项目的菜单中转到 **项目分析>代码审查** . + +[![Code Review Analytics](img/0124687ca256ab68d34dd0918f1e1a8d.png "List of code reviews; oldest review first.")](img/code_review_analytics_v12_8.png) + +* 该表格按评论时长排序,可帮助您快速找到运行时间最长的评论,这可能需要干预或分解成较小的部分. +* 您可以按里程碑和标签过滤 MR 列表. +* 用于显示作者,批准者,评论数和行更改(-/ +)数的列. + +## Use cases[](#use-cases "Permalink") + +此功能专为[开发团队负责](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#delaney-development-team-lead)人和其他想了解广泛的代码审查动态并确定模式以对其进行解释的人员而设计. + +您可以使用 Code Review Analytics 通过代码审查来揭露团队的独特挑战,并确定可能会大大加快开发周期的改进. + +在以下情况下可以使用代码审查分析: + +* 您的团队同意代码审查进度太慢. +* [价值流分析功能](value_stream_analytics.html)表明,审核是您团队最耗时的步骤. + +您可以使用 Code Review Analytics 查看当前运行最慢的工作类型,并分析它们之间的模式和趋势. 例如: + +* 很多评论或承诺? 也许代码太复杂了. +* 涉及特定作者吗? 也许需要更多的培训. +* 评论和批准者很少? 也许您的团队人手不足. + +## Permissions[](#permissions "Permalink") + +* 在[简化版或青铜级](https://about.gitlab.com/pricing/)上. +* 由具有 Reporter 访问权限及以上权限的用户组成. \ No newline at end of file diff --git a/_book/docs/014.md b/_book/docs/014.md new file mode 100644 index 0000000000000000000000000000000000000000..1c80f2ec3f6019d2b886758914547fdc914c5fbd --- /dev/null +++ b/_book/docs/014.md @@ -0,0 +1,91 @@ +# Productivity Analytics + +> 原文:[https://docs.gitlab.com/ee/user/analytics/productivity_analytics.html](https://docs.gitlab.com/ee/user/analytics/productivity_analytics.html) + +* [Supported features](#supported-features) +* [Accessing metrics and visualizations](#accessing-metrics-and-visualizations) +* [Date ranges](#date-ranges) +* [Permissions](#permissions) +* [Enabling and disabling using feature flags](#enabling-and-disabling-using-feature-flags) + +# Productivity Analytics[](#productivity-analytics-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12079) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3. + +使用 Productivity Analytics 追踪发展速度. + +For many companies, the development cycle is a black box and getting an estimate of how long, on average, it takes to deliver features is an enormous endeavor. + +虽然[价值流分析](../project/cycle_analytics.html)专注于整个软件开发生命周期(SDLC)流程,但生产力分析为工程管理提供了一种以系统的方式向下钻取的方法,以揭示在个人,项目或团队级别上的模式以及成败的原因. + +生产力降低的原因很多,从降低代码库到快速成长的团队. 为了进行调查,部门或团队负责人可以从可视化合并请求所花费的时间开始. + +## Supported features[](#supported-features "Permalink") + +生产力分析允许 GitLab 用户执行以下操作: + +* 可视化典型的合并请求(MR)生存期和统计信息. 使用直方图显示创建和合并合并请求之间经过的时间分布. +* 深入研究最耗时的合并请求,选择一些异常值,然后筛选所有后续图表以调查潜在原因. +* 按组,项目,作者,标签,里程碑或特定日期范围过滤. 例如,在里程碑或特定日期范围内,筛选出组或项目中特定作者的合并请求. +* 测量随时间变化的速度. 随时间推移可视化以上图表中每个指标的趋势,以观察进度. 如果发现异常值,请放大特定的日期范围. + +## Accessing metrics and visualizations[](#accessing-metrics-and-visualizations "Permalink") + +要访问该图表,请导航至组的侧边栏,然后选择**Analytics(分析)> Productivity Analytics(生产力分析)** . + +以下度量标准和可视化在项目或组级别可用-当前仅涵盖**合并的**合并请求: + +* 直方图,显示创建后经过指定天数进行合并的合并请求数. 选择一个特定的列以筛选后续的图表. +* 直方图显示了合并合并请求所花费的时间(以小时为单位)的细目. 可以使用以下间隔: + * 从第一次提交到第一次评论的时间. + * 从第一次评论到最后一次提交的时间. + * 从上次提交到合并的时间. +* 使用以下内容显示合并请求的大小或复杂度的直方图: + * 每个合并请求的提交数. + * 每次提交的代码行数. + * 触摸的文件数. +* 散点图显示所有 MR 在特定日期合并,以及完成操作所需的天数和 30 天的滚动中位数. +* 该表显示了合并请求的列表及其各自的持续时间指标. + * 用户可以按上述任何指标进行排序. + +## Date ranges[](#date-ranges "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13188) . + +GitLab 能够根据日期范围过滤分析. 要过滤结果: + +1. 选择一个组. +2. (可选)选择一个项目. +3. 使用可用的日期选择器选择日期范围. + +## Permissions[](#permissions "Permalink") + +只能访问**Productivity Analytics**仪表板: + +* 在[高级或银级](https://about.gitlab.com/pricing/)以上. +* 由具有[Reporter 访问权限](../permissions.html)及以上[权限的](../permissions.html)用户组成. + +## Enabling and disabling using feature flags[](#enabling-and-disabling-using-feature-flags "Permalink") + +生产力分析是: + +* [默认情况下](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18754)从 GitLab 12.4 [启用](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18754) ,但可以使用以下功能标志禁用: + * `productivity_analytics` . + * `productivity_analytics_scatterplot_enabled` . +* 在 GitLab 12.3 中默认为禁用,但可以使用以下功能标志启用: + * `productivity_analytics` . + +GitLab 管理员可以: + +* 通过在 Rails 控制台中运行以下命令,从 GitLab 12.4 禁用此功能: + + ``` + Feature.disable(:productivity_analytics) + Feature.disable(:productivity_analytics_scatterplot_enabled) + ``` + +* 通过在 Rails 控制台中运行以下命令,在 GitLab 12.3 中启用此功能: + + ``` + Feature.enable(:productivity_analytics) + ``` \ No newline at end of file diff --git a/_book/docs/015.md b/_book/docs/015.md new file mode 100644 index 0000000000000000000000000000000000000000..571c1984e5848d74a125a4302a5f3284f97814bd --- /dev/null +++ b/_book/docs/015.md @@ -0,0 +1,298 @@ +# Value Stream Analytics + +> 原文:[https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html](https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html) + +* [Overview](#overview) +* [Date ranges](#date-ranges) +* [How Time metrics are measured](#how-time-metrics-are-measured) +* [How the stages are measured](#how-the-stages-are-measured) +* [Example workflow](#example-workflow) +* [Customizable Value Stream Analytics](#customizable-value-stream-analytics) + * [Stage path](#stage-path) + * [Adding a stage](#adding-a-stage) + * [Re-ordering stages](#re-ordering-stages) + * [Label based stages](#label-based-stages) + * [Hiding unused stages](#hiding-unused-stages) +* [Days to completion chart](#days-to-completion-chart) + * [Chart median line](#chart-median-line) + * [Disabling chart](#disabling-chart) + * [Disabling chart median line](#disabling-chart-median-line) +* [Type of work - Tasks by type chart](#type-of-work---tasks-by-type-chart) +* [Permissions](#permissions) +* [More resources](#more-resources) + +# Value Stream Analytics[](#value-stream-analytics "Permalink") + +版本历史 + +* 在项目级别在 GitLab 12.3 之前作为 Cycle Analytics 引入. +* 在小组级别的[GitLab Premium](https://about.gitlab.com/pricing/) 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12077) . +* 在 GitLab 12.8 中从 Cycle Analytics [重命名](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23427)为 Value Stream Analytics. + +Value Stream Analytics measures the time spent to go from an [idea to production](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab) (also known as cycle time) for each of your projects. Value Stream Analytics displays the median time spent in each stage defined in the process. + +有关如何为 Value Stream Analytics 的发展做出贡献的信息,请参阅我们的[贡献者文档](../../development/value_stream_analytics.html) . + +值流分析有助于快速确定给定项目的速度. 它指出了开发过程中的瓶颈,从而使管理层能够发现,分类和识别软件开发生命周期中速度下降的根本原因. + +Value Stream Analytics 与[GitLab 流程](../../topics/gitlab_flow.html)紧密结合,并为每个阶段计算单独的中位数. + +## Overview[](#overview "Permalink") + +价值流分析可用: + +* 在 GitLab 12.9 中,通过**组>分析>值流**在组级别. +* 在项目级别,通过" **项目">"分析">"价值流"** . + +作为"价值流分析"计算的一部分,将跟踪七个阶段. + +* **Issue** (Tracker) + * 安排问题的时间(按里程碑或通过将其添加到问题板) +* **Plan** (Board) + * 第一次提交的时间 +* **Code** (IDE) + * 是时候创建合并请求了 +* **Test** (CI) + * GitLab CI / CD 测试代码所需的时间 +* **审核** (合并请求/ MR) + * 花在代码审查上的时间 +* **暂存** (连续部署) + * 合并和部署到生产之间的时间 +* **Total** (Total) + * 总生命周期时间. 也就是说,项目或团队的速度. [以前称为](https://gitlab.com/gitlab-org/gitlab/-/issues/38317) **Production** . + +## Date ranges[](#date-ranges "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13216) . + +GitLab 提供了根据日期范围过滤分析的功能. 要过滤结果: + +1. 选择一个组. +2. (可选)选择一个项目. +3. 使用可用的日期选择器选择日期范围. + +## How Time metrics are measured[](#how-time-metrics-are-measured "Permalink") + +页面顶部附近的"时间"指标的测量方法如下: + +* **提前期** :从创建问题到关闭问题的平均时间. +* **周期时间** :从第一次提交到发布完成的中值时间. + +注意:通过在提交消息中进行[交联](../project/issues/crosslinking_issues.html)或通过手动链接包含提交的合并请求,将提交与问题相关[联](../project/issues/crosslinking_issues.html) . + +[![Value stream analytics time metrics](img/f7050ce0aa3559c639befc2fe3d7aacb.png "Time metrics for value stream analytics")](img/vsa_time_metrics_v13_0.png) + +## How the stages are measured[](#how-the-stages-are-measured "Permalink") + +Value Stream Analytics 根据项目问题记录阶段时间和数据,但阶段和总阶段除外,在阶段和总阶段中,仅测量部署到生产中的数据. + +具体而言,如果未设置 CI 且尚未定义`production`或`production/*` [环境](../../ci/yaml/README.html#environment) ,则此阶段将没有任何数据. + +下表进一步描述了价值流分析的每个阶段. + +| **Stage** | **Description** | +| --- | --- | +| Issue | 通过标记问题或将其添加到里程碑中,以先发生的为准,来衡量从创建问题到采取行动解决问题之间的平均时间. 仅在标签已经为其创建了[发行委员会列表的](../project/issue_board.html)情况下,才会跟踪该标签. | +| Plan | 测量您在上一阶段采取的操作与将第一次提交推入分支之间的平均时间. 分支的第一个提交是触发**计划**和**代码**之间分离的提交,并且分支中的至少一个提交需要包含相关的发行编号(例如`#42` ). 如果分支中的所有提交都未提及相关的发行号,则不会考虑该阶段的度量时间. | +| Code | 测量推入第一个提交(上一阶段)与创建与该提交相关的合并请求(MR)之间的平均时间. 保持流程跟踪的关键是在合并请求的描述中包括[问题关闭模式](../project/issues/managing_issues.html#closing-issues-automatically) (例如, `Closes #xxx` ,其中`xxx`是与此合并请求相关的问题编号). 如果合并请求描述中不存在问题结束模式,则不会将 MR 视为平台的测量时间. | +| Test | 测量运行该项目的整个管道的中值时间. 这与 GitLab CI / CD 为推送到上一阶段中定义的合并请求的提交运行每个作业所花费的时间有关. 基本上,这是所有管道的开始->完成时间. | +| Review | 测量从创建到合并之间,审核具有结束问题模式的合并请求所需的平均时间. | +| Staging | 测量从合并合并请求到结束发布模式到首次部署到生产之间的平均时间. 在您的 GitLab CI / CD 配置中,通过设置为`production`或匹配`production/*` (区分大小写, `Production`将不起作用)的环境进行跟踪. 如果没有生产环境,则不会进行跟踪. | +| Total | 从问题创建到将代码部署到生产中,运行整个过程所需的所有时间(中位数)之和. [以前称为](https://gitlab.com/gitlab-org/gitlab/-/issues/38317) **Production** . | + +幕后工作原理: + +1. 问题和合并请求成对地分组在一起,这样对于每个``对,合并请求都具有对应问题的[问题关闭模式](../project/issues/managing_issues.html#closing-issues-automatically) . **不**考虑所有其他问题和合并请求. +2. 然后,在最近的 XX 天(由 UI 指定-默认为 90 天)中过滤出``对. 因此,它禁止考虑这些对. +3. 对于其余的``对,我们检查阶段所需的信息,例如发行日期,合并请求合并时间等. + +综上所述,不会跟踪任何未遵循[GitLab 流程的](../../workflow/gitlab_flow.html)内容,并且 Value Stream Analytics 仪表板将不会显示以下任何数据: + +* 合并不会解决问题的请求. +* 未在发行委员会中贴有标签的问题或未分配里程碑的问题. +* 如果项目没有`production`或`production/*`环境,则为阶段和生产阶段. + +## Example workflow[](#example-workflow "Permalink") + +以下是一个简单的虚拟周期工作流,它在一天中经历了所有七个阶段后,才发生. 请注意,如果一个阶段没有开始和结束标记,则不会对其进行测量,因此不会在中位时间中进行计算. 假定已创建里程碑并配置了用于测试和设置环境的 CI. + +1. 在 09:00( **发行**阶段开始)创建**发行** . +2. 在 11:00( **发行**阶段停止/ **计划**阶段开始)将发行添加到里程碑. +3. 开始解决此问题,在本地创建一个分支,并在 12:00 提交一次. +4. 对分支进行第二次提交,该分支在 12.30( **计划**阶段的停止/ **代码**阶段的开始)中提及发行号. +5. 推送分支并创建一个合并请求,该请求的描述在 14:00( **代码**阶段停止/ **测试**和**复审**阶段开始)中包含[问题关闭模式](../project/issues/managing_issues.html#closing-issues-automatically) . +6. CI 将开始运行您在[`.gitlab-ci.yml`](../../ci/yaml/README.html)定义的脚本,并需要 5 分钟( **测试**阶段停止). +7. 查看合并请求,确保一切正常,然后在 19:00 合并合并请求. ( **复习**阶段的停止/启动**分期**阶段). +8. 现在,合并请求合并,部署到`production`环境中开始和结束日 19:30( **分期**阶段停止). +9. 循环完成,并且先前阶段的中位数时间总和记录到" **总计"**阶段. 这是从创建问题到将其相关合并请求部署到生产之间的时间. + +从上面的示例中,您可以得出每个阶段完成所需的时间,只要达到其总时间即可: + +* **问题** :2 小时(11:00-09:00) +* **计划** :1 小时(12:00-11:00) +* **编码** :2h(14:00-12:00) +* **测试时间** :5 分钟 +* **评论** :5 小时(19:00-14:00) +* **演出时间** :30 分钟(19:30-19:00) +* **总计** :由于此阶段测量的是之前所有阶段的中位时间之和,因此如果我们不知道之前各阶段的状态,则无法计算. 如果这是项目中运行的第一个周期,则**总**时间为 10h 30min(19:30-09:00) + +一些注意事项: + +* 在上面的示例中,我们演示了您的第一次提交没有提到发行号也没关系,您可以稍后在正在处理的分支的任何提交中进行此操作. +* 您可以看到,由于未将" **测试"**阶段计算为整个周期的时间,因此" **检查"**阶段已包含在" **审查"**过程中(应测试每个 MR). +* 上面的示例只是七个阶段中的**一个循环** . 添加多个周期,计算它们的中值时间,结果就是 Value Stream Analytics 仪表板显示的内容. + +## Customizable Value Stream Analytics[](#customizable-value-stream-analytics "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12196) . + +默认阶段旨在直接使用,但是可能并不适合所有团队. 不同的团队使用不同的方法来构建软件,因此一些团队可能想要自定义其 Value Stream Analytics. + +GitLab 允许用户隐藏默认阶段并创建自定义阶段,使其更适合其开发工作流程. + +**注意:**自定义性[仅适用于组级别的](https://gitlab.com/gitlab-org/gitlab/-/issues/35823#note_272558950)价值流分析. + +### Stage path[](#stage-path "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/210315) . + +从视觉上将阶段描绘为水平过程流. 选择一个阶段将更新值流下方的内容. + +默认情况下禁用. 如果您具有自我管理的实例,则管理员可以[打开 Rails 控制台](../../administration/troubleshooting/navigating_gitlab_via_rails_console.html)并使用以下命令启用它: + +``` +Feature.enable(:value_stream_analytics_path_navigation) +``` + +### Adding a stage[](#adding-a-stage "Permalink") + +在下面的示例中,我们将创建一个新阶段,该阶段可以衡量和跟踪从创建到关闭的所有问题. + +1. 导航到您组的" **分析">"价值流"** . +2. 单击**添加阶段**按钮. +3. 填写新的舞台表格: + * 名称:问题开始完成. + * 开始事件:已创建问题. + * 结束事件:问题已关闭. +4. 单击**添加阶段**按钮. + +[![New Value Stream Analytics Stage](img/d1c47110b6092ce9cec04ff22addfaa4.png "Form for creating a new stage")](img/new_vsm_stage_v12_9.png) + +新阶段将保持不变,并将始终显示在您组的"价值流分析"页面上. + +如果要更改或删除阶段,可以通过以下方法轻松地针对自定义阶段进行操作: + +1. Hovering over the stage. +2. 单击垂直省略号( )出现的按钮. + +[![Value Stream Analytics Stages](img/d277485e75207494ed3529dfcc7a6395.png)](img/vsm_stage_list_v12_9.png) + +创建自定义阶段需要指定两个事件: + +* 开始. +* 结束. + +请小心选择*在*结束事件*之前*发生的开始事件. 例如,考虑一个阶段: + +* 在将问题添加到板上时开始. +* 创建问题时结束. + +此阶段将不起作用,因为开始事件发生时,结束事件已经发生. 为防止此类无效阶段,UI 禁止出现不兼容的开始和结束事件. 选择开始事件后,停止事件下拉列表将仅列出兼容事件. + +### Re-ordering stages[](#re-ordering-stages "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/196698) . + +添加自定义阶段后,您可以"拖放"阶段以重新排列其顺序. 这些更改将自动保存到系统中. + +### Label based stages[](#label-based-stages "Permalink") + +预定义的开始和结束事件可以涵盖涉及问题和合并请求的许多用例. + +为了支持更复杂的工作流程,请使用基于组标签的阶段. 这些事件基于添加或删除的标签. 特别是, [范围标签](../project/labels.html#scoped-labels-premium)对于复杂的工作流程很有用. + +在此示例中,我们希望测量更准确的代码检查时间. 工作流程如下: + +* 代码审阅开始时,审阅者将`workflow::code_review_start`标签添加到合并请求中. +* 代码检查完成后,检查者将`workflow::code_review_complete`标签添加到合并请求中. + +创建一个称为"代码审查"的新阶段: + +[![New Label Based Value Stream Analytics Stage](img/ea01744c06eb8853392bfd840dc1517d.png "Creating a label based Value Stream Analytics Stage")](img/label_based_stage_vsm_v12_9.png) + +### Hiding unused stages[](#hiding-unused-stages "Permalink") + +有时某些默认阶段与团队无关. 在这种情况下,您可以轻松隐藏阶段,使它们不再出现在列表中. 隐藏阶段: + +1. 添加定制阶段以激活可定制性. +2. 将鼠标悬停在要隐藏的默认阶段上. +3. 单击垂直省略号( )按钮出现,然后选择" **隐藏舞台"** . + +要恢复以前隐藏的默认阶段: + +1. Click **添加一个阶段** button. +2. 在右上角打开" **恢复隐藏的阶段"**下拉列表. +3. 选择一个阶段. + +## Days to completion chart[](#days-to-completion-chart "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21631) . + +该图表直观地描述了完成周期所需的总天数. + +该图表使用全局页面过滤器来基于选定的组,项目和时间范围显示数据. 此外,可以从图表本身内选择特定阶段. + +### Chart median line[](#chart-median-line "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36675) . + +图表上的中间线显示的数据偏移了所选的天数. 例如,如果选择了 30 天的数据(例如 2019-12-16 至 2020-01-15),则中线将代表前 30 天的数据(2019-11-16 至 2019-12 -16)作为要比较的指标. + +### Disabling chart[](#disabling-chart "Permalink") + +This chart is enabled by default. If you have a self-managed instance, an administrator can open a Rails console and disable it with the following command: + +``` +Feature.disable(:cycle_analytics_scatterplot_enabled) +``` + +### Disabling chart median line[](#disabling-chart-median-line "Permalink") + +默认情况下,此图表的中线是启用的. 如果您具有自我管理的实例,则管理员可以打开 Rails 控制台并使用以下命令将其禁用: + +``` +Feature.disable(:cycle_analytics_scatterplot_median_enabled) +``` + +## Type of work - Tasks by type chart[](#type-of-work---tasks-by-type-chart "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32421) . + +此图表显示每天的问题和合并请求的累积计数. + +该图表使用全局页面过滤器来基于选定的组,项目和时间范围显示数据. 该图表默认为显示问题计数,但可以切换为显示合并请求数据,并进一步细化为特定的组级标签. + +默认情况下,预先选择了最高的组级别标签(最多 10 个),最多可以选择 15 个标签. + +## Permissions[](#permissions "Permalink") + +Project Value Stream Analytics 仪表板上的当前权限为: + +* 公共项目-任何人都可以访问. +* 内部项目-任何经过身份验证的用户都可以访问. +* 私人项目-访客及以上的任何成员都可以访问. + +您通常可以[阅读有关权限的更多信息](../../ci/yaml/README.html) . + +对于 GitLab 12.3 和更高版本中引入的 Value Stream Analytics 功能: + +* 用户必须具有 Reporter 或更高权限. +* 仅在[Premium 或 Silver 等级](https://about.gitlab.com/pricing/)及更高[级别](https://about.gitlab.com/pricing/)上可用. + +## More resources[](#more-resources "Permalink") + +Learn more about Value Stream Analytics in the following resources: + +* [Value Stream Analytics feature page](https://about.gitlab.com/stages-devops-lifecycle/value-stream-analytics/). +* [Value Stream Analytics feature preview](https://about.gitlab.com/blog/2016/09/16/feature-preview-introducing-cycle-analytics/). +* [Value Stream Analytics feature highlight](https://about.gitlab.com/blog/2016/09/21/cycle-analytics-feature-highlight/). \ No newline at end of file diff --git a/_book/docs/016.md b/_book/docs/016.md new file mode 100644 index 0000000000000000000000000000000000000000..4ce588b0d0e27519d83261314aa935773d7e0fea --- /dev/null +++ b/_book/docs/016.md @@ -0,0 +1,309 @@ +# Kubernetes clusters + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/](https://docs.gitlab.com/ee/user/project/clusters/) + +* [Overview](#overview) +* [Setting up](#setting-up) + * [Supported cluster versions](#supported-cluster-versions) + * [Adding and removing clusters](#adding-and-removing-clusters) + * [Multiple Kubernetes clusters](#multiple-kubernetes-clusters) + * [Setting the environment scope](#setting-the-environment-scope-premium) +* [Configuring your Kubernetes cluster](#configuring-your-kubernetes-cluster) + * [Security implications](#security-implications) + * [GitLab-managed clusters](#gitlab-managed-clusters) + * [Important notes](#important-notes) + * [Clearing the cluster cache](#clearing-the-cluster-cache) + * [Base domain](#base-domain) +* [Installing applications](#installing-applications) +* [Auto DevOps](#auto-devops) +* [Deploying to a Kubernetes cluster](#deploying-to-a-kubernetes-cluster) + * [Deployment variables](#deployment-variables) + * [Custom namespace](#custom-namespace) + * [Integrations](#integrations) + * [Canary Deployments](#canary-deployments-premium) + * [Deploy Boards](#deploy-boards-premium) + * [Viewing pod logs](#viewing-pod-logs) + * [Web terminals](#web-terminals) + * [Troubleshooting](#troubleshooting) +* [Monitoring your Kubernetes cluster](#monitoring-your-kubernetes-cluster) + * [Visualizing cluster health](#visualizing-cluster-health) + +# Kubernetes clusters[](#kubernetes-clusters "Permalink") + +版本历史 + +* 在项目的 GitLab 10.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35954) . +* 在 GitLab 11.6 中针对[组](../../group/clusters/index.html) [引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34758) . +* 在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39840)了[实例](../../instance/clusters/index.html) . + +## Overview[](#overview "Permalink") + +使用 GitLab 项目 Kubernetes 集成,您可以: + +* Use [Review Apps](../../../ci/review_apps/index.html). +* Run [pipelines](../../../ci/pipelines/index.html). +* [部署](#deploying-to-a-kubernetes-cluster)您的应用程序. +* 检测和[监控 Kubernetes](#monitoring-your-kubernetes-cluster) . +* 与[Auto DevOps](#auto-devops)一起使用. +* Use [Web terminals](#web-terminals). +* Use [Deploy Boards](#deploy-boards-premium). +* Use [Canary Deployments](#canary-deployments-premium). +* View [Logs](#viewing-pod-logs). +* [使用 Knative](serverless/index.html)在[Kubernetes 上](serverless/index.html)运行无服务器工作负载. + +除了在项目级别进行集成之外,Kubernetes 集群还可以在[组级别](../../group/clusters/index.html)或[GitLab 实例级别](../../instance/clusters/index.html)进行集成. + +## Setting up[](#setting-up "Permalink") + +### Supported cluster versions[](#supported-cluster-versions "Permalink") + +GitLab 承诺在任何给定时间至少支持两个生产就绪的 Kubernetes 次要版本. 我们会定期审查我们支持的版本,并提供四个月的弃用期,然后再删除特定版本的支持. 支持的版本范围基于以下方面的评估: + +* 我们自己的需求. +* 主要托管 Kubernetes 提供商支持的版本. +* [Kubernetes 社区支持](https://kubernetes.io/docs/setup/release/version-skew-policy/#supported-versions)的版本. + +当前,GitLab 支持以下 Kubernetes 版本: + +* 1.16 +* 1.15 +* 1.14 +* 1.13(不建议使用,支持终止于 2020 年 11 月 22 日) +* 1.12(不建议使用,支持终止于 2020 年 9 月 22 日) + +**注意:**某些 GitLab 功能可能支持此处提供的范围之外的版本. + +### Adding and removing clusters[](#adding-and-removing-clusters "Permalink") + +有关如何执行以下操作的详细信息,请参见[添加和删​​除 Kubernetes 集群](add_remove_clusters.html) : + +* 使用 GitLab 的 UI 在 Google Cloud Platform(GCP)或 Amazon Elastic Kubernetes Service(EKS)中创建集群. +* 从任何 Kubernetes 平台向现有集群添加集成. + +### Multiple Kubernetes clusters[](#multiple-kubernetes-clusters "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 10.3 中引入 +* 在 13.2 中[移至](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094) GitLab 核心. + +您可以将多个 Kubernetes 集群关联到您的项目. 这样,您可以为不同的环境(例如开发,登台,生产等)使用不同的集群. + +就像您第一次一样,只需添加另一个集群,并确保[设置一个环境范围即可](#setting-the-environment-scope-premium)将新集群与其他集群区分开. + +#### Setting the environment scope[](#setting-the-environment-scope-premium "Permalink") + +将多个 Kubernetes 集群添加到您的项目时,您需要通过环境范围来区分它们. 环境范围将群集与[环境](../../../ci/environments/index.html)相关联,类似于[特定](../../../ci/variables/README.html#limit-the-environment-scopes-of-environment-variables)于[环境的变量的](../../../ci/variables/README.html#limit-the-environment-scopes-of-environment-variables)工作方式. + +默认环境范围是`*` ,这意味着所有作业,无论其环境如何,都将使用该群集. 每个作用域只能由项目中的单个群集使用,否则将发生验证错误. 另外,没有设置环境关键字的作业将无法访问任何群集. + +例如,假设项目中存在以下 Kubernetes 集群: + +| Cluster | 环境范围 | +| --- | --- | +| Development | `*` | +| Production | `production` | + +[`.gitlab-ci.yml`](../../../ci/yaml/README.html)中设置了以下环境: + +``` +stages: + - test + - deploy + +test: + stage: test + script: sh test + +deploy to staging: + stage: deploy + script: make deploy + environment: + name: staging + url: https://staging.example.com/ + +deploy to production: + stage: deploy + script: make deploy + environment: + name: production + url: https://example.com/ +``` + +结果将是: + +* The Development cluster details will be available in the `deploy to staging` job. +* 生产集群详细信息将在`deploy to production`作业中提供. +* `test`作业中没有可用的群集详细信息,因为它没有定义任何环境. + +## Configuring your Kubernetes cluster[](#configuring-your-kubernetes-cluster "Permalink") + +[将 Kubernetes 群集添加](add_remove_clusters.html)到 GitLab 之后,请阅读本节,其中涵盖了使用 GitLab 配置 Kubernetes 群集的重要注意事项. + +### Security implications[](#security-implications "Permalink") + +**Important:** The whole cluster security is based on a model where [developers](../../permissions.html) are trusted, so **仅允许受信任的用户控制您的集群**. + +默认的群集配置授予对成功构建和部署容器化应用程序所需的广泛功能的访问权限. 请记住,群集上运行的所有应用程序都使用相同的凭据. + +### GitLab-managed clusters[](#gitlab-managed-clusters "Permalink") + +版本历史 + +* 在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22011) . +* 在 GitLab 11.11 中成为[可选](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26565) . + +您可以选择允许 GitLab 为您管理集群. 如果您的集群由 GitLab 管理,则将自动创建项目资源. 有关创建哪些资源的详细信息,请参见" [访问控制"](add_remove_clusters.html#access-controls)部分. + +如果选择管理自己的群集,则不会自动创建特定于项目的资源. 如果使用的是[Auto DevOps](../../../topics/autodevops/index.html) ,则需要显式提供部署作业将使用的`KUBE_NAMESPACE` [部署变量](#deployment-variables) ,否则将为您创建一个名称空间. + +#### Important notes[](#important-notes "Permalink") + +在 GitLab 和集群上注意以下几点: + +* 如果您在群集上[安装应用程序](#installing-applications) ,即使您选择管理自己的群集,GitLab 也会创建运行这些资源所需的资源. +* 请注意,手动管理由 GitLab 创建的资源(例如名称空间和服务帐户)可能会导致意外错误. 如果发生这种情况,请尝试[清除集群缓存](#clearing-the-cluster-cache) . + +#### Clearing the cluster cache[](#clearing-the-cluster-cache "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31759) . + +如果您选择允许 GitLab 为您管理集群,则 GitLab 将存储它为项目创建的名称空间和服务帐户的缓存版本. 如果在群集中手动修改这些资源,则此缓存可能与群集不同步,这可能导致部署作业失败. + +清除缓存: + +1. 导航到项目的" **操作">" Kubernetes"**页面,然后选择您的集群. +2. 展开**高级设置**部分. +3. Click **Clear cluster cache**. + +### Base domain[](#base-domain "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24580) . + +**注意:**使用 GitLab Serverless 时,无需在群集设置上指定基本域. 在这种情况下,域将被指定为 Knative 安装的一部分. 请参阅[安装应用程序](#installing-applications) . + +指定基本域将自动将`KUBE_INGRESS_BASE_DOMAIN`设置为环境变量. 如果您使用的是[Auto DevOps](../../../topics/autodevops/index.html) ,则此域将用于不同的阶段. 例如,"自动查看应用程序"和"自动部署". + +该域应将通配符 DNS 配置为入口 IP 地址. 安装 Ingress 之后(请参阅[安装应用程序](#installing-applications) ),您可以: + +* 创建一个指向您的域提供商指向入口 IP 地址的`A`记录. +* 使用 nip.io 或 xip.io 之类的服务输入通配符 DNS 地址. 例如, `192.168.1.1.xip.io` . + +## Installing applications[](#installing-applications "Permalink") + +GitLab 可以在项目级集群中安装和管理一些应用程序,例如 Helm,GitLab Runner,Ingress,Prometheus 等. 有关为项目集群安装,升级,卸载和故障排除应用程序的更多信息,请参阅[GitLab 托管应用程序](../../clusters/applications.html) . + +## Auto DevOps[](#auto-devops "Permalink") + +Auto DevOps 自动检测,构建,测试,部署和监视您的应用程序. + +要充分利用 Auto DevOps(自动部署,自动查看应用程序和自动监控),您需要启用 Kubernetes 项目集成. + +[Read more about Auto DevOps](../../../topics/autodevops/index.html) + +**注意** Kubernetes 群集可以在没有 Auto DevOps 的情况下使用. + +## Deploying to a Kubernetes cluster[](#deploying-to-a-kubernetes-cluster "Permalink") + +Kubernetes 集群可以作为部署作业的目标. 如果 + +* 该集群与 GitLab 集成在一起,特殊的[部署变量](#deployment-variables)可用于您的工作,并且不需要配置. 您可以使用诸如`kubectl`或`helm`工具立即开始从作业中与集群进行交互. +* 您无需使用 GitLab 的集群集成,仍然可以将其部署到集群中. 但是,您需要自己使用[环境变量](../../../ci/variables/README.html#custom-environment-variables)配置 Kubernetes 工具,然后才能通过作业与集群进行交互. + +### Deployment variables[](#deployment-variables "Permalink") + +Kubernetes 集群集成在 GitLab CI / CD 构建环境中公开了以下[部署变量](../../../ci/variables/README.html#deployment-environment-variables) . + +| Variable | Description | +| --- | --- | +| `KUBE_URL` | 等于 API URL. | +| `KUBE_TOKEN` | [环境服务帐户](add_remove_clusters.html#access-controls)的 Kubernetes 令牌. | +| `KUBE_NAMESPACE` | 与项目的部署服务帐户关联的名称空间. 格式为`--` . 对于由 GitLab 管理的集群,GitLab 会在集群中自动创建一个匹配的名称空间. | +| `KUBE_CA_PEM_FILE` | 包含 PEM 数据的文件的路径. 仅当指定了自定义 CA 捆绑包时才存在. | +| `KUBE_CA_PEM` | ( **已弃用** )原始 PEM 数据. 仅当指定了自定义 CA 捆绑包时. | +| `KUBECONFIG` | 包含用于此部署的`kubeconfig`的文件的路径. 如果指定,则将嵌入 CA 捆绑软件. 此配置还嵌入了在`KUBE_TOKEN`定义的相同令牌,因此您可能只需要此变量. 该变量名也会由`kubectl`自动选择,因此,如果使用`kubectl`则实际上不需要显式引用它. | +| `KUBE_INGRESS_BASE_DOMAIN` | 从 GitLab 11.8 开始,此变量可用于为每个群集设置一个域. 有关更多信息,请参见[群集域](#base-domain) . | + +**注意:**在 GitLab 11.5 之前, `KUBE_TOKEN`是集群集成的主要服务帐户的 Kubernetes 令牌.**注意:**如果您的集群是在 GitLab 12.2 之前创建的,则默认`KUBE_NAMESPACE`将设置为`-` . + +### Custom namespace[](#custom-namespace "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) . + +Kubernetes 集成默认为格式为`--`的特定于项目环境的名称空间(请参阅[部署变量](#deployment-variables) ). + +对于**非** GitLab 管理的集群,可以使用`.gitlab-ci.yml` [`environment:kubernetes:namespace`](../../../ci/environments/index.html#configuring-kubernetes-deployments)来定制[`environment:kubernetes:namespace`](../../../ci/environments/index.html#configuring-kubernetes-deployments) . + +**注意:**使用[GitLab 管理的集群时](#gitlab-managed-clusters) ,名称空间是在部署之前自动创建的, [无法自定义](https://gitlab.com/gitlab-org/gitlab/-/issues/38054) . + +### Integrations[](#integrations "Permalink") + +#### Canary Deployments[](#canary-deployments-premium "Permalink") + +利用[Kubernetes 的 Canary 部署,](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments)并在部署板内部可视化您的 Canary 部署,而无需离开 GitLab. + +[Read more about Canary Deployments](../canary_deployments.html) + +#### Deploy Boards[](#deploy-boards-premium "Permalink") + +GitLab 的部署板提供了 Kubernetes 上运行的每个 CI [环境](../../../ci/environments/index.html)的当前运行状况和状态的合并视图,显示了部署中 Pod 的状态. 开发人员和其他团队成员可以在已经使用的工作流程中逐个窗格地查看发布的进度和状态,而无需访问 Kubernetes. + +[Read more about Deploy Boards](../deploy_boards.html) + +#### Viewing pod logs[](#viewing-pod-logs "Permalink") + +使用 GitLab 可以轻松查看连接的 Kubernetes 集群中正在运行的 Pod 的日志. 通过直接在 GitLab 中显示日志,开发人员可以避免管理控制台工具或跳转到其他界面. + +[Read more about Kubernetes logs](kubernetes_pod_logs.html) + +#### Web terminals[](#web-terminals "Permalink") + +在 GitLab 8.15 中引入. + +启用后,Kubernetes 集成将为您的[环境](../../../ci/environments/index.html)添加[Web 终端](../../../ci/environments/index.html#web-terminals)支持. 这基于 Docker 和 Kubernetes 中的`exec`功能,因此您可以在现有容器中获得一个新的 Shell 会话. 要使用此集成,您应该使用上面的部署变量将其部署到 Kubernetes,并确保对所有部署,副本集和 Pod 进行注释: + +* `app.gitlab.com/env: $CI_ENVIRONMENT_SLUG` +* `app.gitlab.com/app: $CI_PROJECT_PATH_SLUG` + +`$CI_ENVIRONMENT_SLUG`和`$CI_PROJECT_PATH_SLUG`是 CI 变量的值. + +您必须是项目所有者或拥有`maintainer`权限才能使用终端. 支持仅限于环境中第一个容器中的第一个容器. + +### Troubleshooting[](#troubleshooting "Permalink") + +在开始部署作业之前,GitLab 将为部署作业专门创建以下内容: + +* 命名空间. +* A service account. + +但是,有时 GitLab 无法创建它们. 在这种情况下,您的工作将失败,并显示以下消息: + +``` +This job failed because the necessary resources were not successfully created. +``` + +要在创建名称空间和服务帐户时查找导致此错误的原因,请检查[日志](../../../administration/logs.html#kuberneteslog) . + +失败的原因包括: + +* 您为 GitLab 提供的令牌没有 GitLab 所需的[`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)特权. +* 缺少`KUBECONFIG`或`KUBE_TOKEN`变量. 要传递给您的工作,他们必须具有匹配的[`environment:name`](../../../ci/environments/index.html#defining-environments) . 如果您的作业没有设置`environment:name` ,则不会通过 Kubernetes 凭据. + +**注意:**从 GitLab 12.0 或更早版本升级的项目级群集可能以导致此错误的方式进行配置. 如果要自己管理名称空间和服务帐户,请确保取消选择由[GitLab 管理的群集](#gitlab-managed-clusters)选项. + +## Monitoring your Kubernetes cluster[](#monitoring-your-kubernetes-cluster "Permalink") + +自动检测和监控 Kubernetes 指标. 还支持[NGINX Ingress 的](../integrations/prometheus_library/nginx.html)自动监视. + +[Read more about Kubernetes monitoring](../integrations/prometheus_library/kubernetes.html) + +### Visualizing cluster health[](#visualizing-cluster-health "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4701) . +* 在 13.2 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/208224) GitLab 核心. + +[部署 Prometheus 后](#installing-applications) ,GitLab 将自动监视群集的运行状况. 在群集设置页面的顶部,显示 CPU 和内存利用率以及可用总量. 如果群集的内存不足,则监视群集资源可能很重要,可能会关闭或无法启动. + +[![Cluster Monitoring](img/0e27f7f7b1dd7b6748365d5ea985238a.png)](img/k8s_cluster_monitoring.png) \ No newline at end of file diff --git a/_book/docs/017.md b/_book/docs/017.md new file mode 100644 index 0000000000000000000000000000000000000000..44149203201a8e84ffd6b29e0d80e99ab486a7da --- /dev/null +++ b/_book/docs/017.md @@ -0,0 +1,256 @@ +# Adding and removing Kubernetes clusters + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/add_remove_clusters.html](https://docs.gitlab.com/ee/user/project/clusters/add_remove_clusters.html) + +* [Before you begin](#before-you-begin) +* [Access controls](#access-controls) + * [Important notes](#important-notes) + * [RBAC cluster resources](#rbac-cluster-resources) + * [ABAC cluster resources](#abac-cluster-resources) + * [Security of GitLab Runners](#security-of-gitlab-runners) +* [Create new cluster](#create-new-cluster) +* [Add existing cluster](#add-existing-cluster) + * [Existing Kubernetes cluster](#existing-kubernetes-cluster) + * [Disable Role-Based Access Control (RBAC) (optional)](#disable-role-based-access-control-rbac-optional) +* [Enabling or disabling integration](#enabling-or-disabling-integration) +* [Removing integration](#removing-integration) +* [Learn more](#learn-more) + +# Adding and removing Kubernetes clusters[](#adding-and-removing-kubernetes-clusters "Permalink") + +GitLab 为以下 Kubernetes 提供者提供了集成的集群创建功能: + +* Google Kubernetes 引擎(GKE). +* Amazon Elastic Kubernetes 服务(EKS). + +GitLab 还可以与本地或托管的任何标准 Kubernetes 提供程序集成. + +**注意:**观看[使用 GitLab 和 Google Cloud Platform 进行](https://about.gitlab.com/webcast/scalable-app-deploy/)的网络广播[可扩展应用程序部署,](https://about.gitlab.com/webcast/scalable-app-deploy/)并了解如何通过单击几下加速由 Google Cloud Platform(GCP)管理的 Kubernetes 集群.**提示:**每个新的 Google Cloud Platform(GCP)帐户[在注册后](https://console.cloud.google.com/freetrial)都会获得[$ 300 的信用额](https://console.cloud.google.com/freetrial) ,并且与 Google 合作,GitLab 能够为新的 GCP 帐户提供额外的$ 200,以开始使用 GitLab 的 Google Kubernetes Engine Integration. 您所要做的就是[点击此链接](https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form)并申请信贷. + +## Before you begin[](#before-you-begin "Permalink") + +在使用 GitLab [添加 Kubernetes 集群](#create-new-cluster)之前,您需要: + +* GitLab 本身. 要么: + * 一个[GitLab.com 帐户](https://about.gitlab.com/pricing/#gitlab-com) . + * 使用 GitLab 12.5 或更高版本的[自我管理安装](https://about.gitlab.com/pricing/#self-managed) . 这将确保 GitLab UI 可用于创建集群. +* 以下 GitLab 访问: + * [维护者](../../permissions.html#project-members-permissions)对项目级集群的项目[访问](../../permissions.html#project-members-permissions) . + * [维护者](../../permissions.html#group-members-permissions)对组级别集群的[访问权限](../../permissions.html#group-members-permissions) . + * 自我管理的实例级别群集的管理[区域访问](../../admin_area/index.html) . + +## Access controls[](#access-controls "Permalink") + +在 GitLab 中创建集群时,系统会询问您是否要创建以下任一集群: + +* A [Role-based access control (RBAC)](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) cluster. +* An [Attribute-based access control (ABAC)](https://kubernetes.io/docs/reference/access-authn-authz/abac/) cluster. + +**注意:**建议使用[RBAC](#rbac-cluster-resources) ,GitLab 为默认值. + +GitLab 创建必要的服务帐户和特权,以安装和运行[GitLab 托管的应用程序](index.html#installing-applications) . 当 GitLab 创建集群时,将在`default`名称空间中创建具有`cluster-admin`特权的`gitlab`服务帐户,以管理新创建的集群. + +**注意:**用于部署的受限服务帐户是在 GitLab 11.5 中[引入的](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51716) . + +The first time you install an application into your cluster, the `tiller` service account is created with `cluster-admin` privileges in the `gitlab-managed-apps` namespace. This service account will be used by Helm to install and run [GitLab managed applications](index.html#installing-applications). + +Helm 还将为每个已安装的应用程序创建其他服务帐户和其他资源. 有关每个应用程序,请查阅 Helm 图表的文档. + +如果要[添加现有的 Kubernetes 集群](add_remove_clusters.html#add-existing-cluster) ,请确保该帐户的令牌具有该集群的管理员特权. + +GitLab 创建的资源取决于集群的类型. + +### Important notes[](#important-notes "Permalink") + +请注意以下有关访问控制的内容: + +* 仅当集群[由 GitLab 管理时,](index.html#gitlab-managed-clusters)才会创建特定于环境的资源. +* 如果您的集群是在 GitLab 12.2 之前创建的,它将为所有项目环境使用单个名称空间. + +### RBAC cluster resources[](#rbac-cluster-resources "Permalink") + +GitLab 为 RBAC 集群创建以下资源. + +| Name | Type | Details | 创建时间 | +| --- | --- | --- | --- | +| `gitlab` | `ServiceAccount` | `default` namespace | 创建一个新集群 | +| `gitlab-admin` | `ClusterRoleBinding` | [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | 创建一个新集群 | +| `gitlab-token` | `Secret` | `gitlab` ServiceAccount 的令牌 | 创建一个新集群 | +| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | 安装舵图 | +| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | 安装舵图 | +| 环境名称空间 | `Namespace` | 包含所有特定于环境的资源 | 部署到集群 | +| 环境名称空间 | `ServiceAccount` | 使用环境的名称空间 | 部署到集群 | +| 环境名称空间 | `Secret` | 环境 ServiceAccount 的令牌 | 部署到集群 | +| 环境名称空间 | `RoleBinding` | [`edit`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | 部署到集群 | + +### ABAC cluster resources[](#abac-cluster-resources "Permalink") + +GitLab 为 ABAC 群集创建以下资源. + +| Name | Type | Details | 创建时间 | +| --- | --- | --- | --- | +| `gitlab` | `ServiceAccount` | `default` namespace | 创建一个新集群 | +| `gitlab-token` | `Secret` | `gitlab` ServiceAccount 的令牌 | 创建一个新集群 | +| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | 安装舵图 | +| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | 安装舵图 | +| 环境名称空间 | `Namespace` | 包含所有特定于环境的资源 | 部署到集群 | +| 环境名称空间 | `ServiceAccount` | 使用环境的名称空间 | 部署到集群 | +| 环境名称空间 | `Secret` | 环境 ServiceAccount 的令牌 | 部署到集群 | + +### Security of GitLab Runners[](#security-of-gitlab-runners "Permalink") + +GitLab Runners 默认情况[下](https://docs.gitlab.com/runner/executors/docker.html)启用了[特权模式](https://docs.gitlab.com/runner/executors/docker.html) ,这使他们可以执行特殊命令并在 Docker 中运行 Docker. 运行某些[Auto DevOps](../../../topics/autodevops/index.html)作业需要此功能. 这意味着容器正在特权模式下运行,因此,您应该注意一些重要的细节. + +特权标志为正在运行的容器提供了所有功能,而容器又可以执行主机可以执行的几乎所有操作. 请注意与对任意映像执行`docker run`操作相关的固有安全风险,因为它们有效地具有 root 用户访问权限. + +如果您不想在特权模式下使用 GitLab Runner,请执行以下任一操作: + +* 在 GitLab.com 上使用共享的跑步者. 他们没有这个安全问题. +* 使用[Shared Runners 中](../../gitlab_com/index.html#shared-runners)描述的配置来设置自己的[Runners](../../gitlab_com/index.html#shared-runners) . 这涉及: + 1. 确保您没有通过[应用程序](index.html#installing-applications)安装它. + 2. [使用`docker+machine`](https://docs.gitlab.com/runner/executors/docker_machine.html)安装 Runner. + +## Create new cluster[](#create-new-cluster "Permalink") + +可以使用 Google Kubernetes Engine(GKE)上的 GitLab 或 Amazon Elastic Kubernetes Service(EKS)在项目,组或实例级别上创建新集群: + +1. 导航到您的: + * 项目的 **操作> Kubernetes**页面,用于项目级集群. + * 组的 **Kubernetes**页面,用于组级别集群. + * **管理区>** **Kubernetes**页面,用于实例级集群. +2. Click **添加 Kubernetes 集群**. +3. 单击**创建新集群**选项卡. +4. 单击**Amazon EKS**或**Google GKE** ,然后按照说明提供所需的服务: + * [亚马逊 EKS](add_eks_clusters.html#new-eks-cluster) . + * [Google GKE](add_gke_clusters.html#creating-the-cluster-on-gke) . + +## Add existing cluster[](#add-existing-cluster "Permalink") + +如果您已有 Kubernetes 集群,则可以将其添加到项目,组或实例中. + +**注意:** arm64 集群不支持 Kubernetes 集成. 有关详细信息,请参阅问题[Helm Tiller 无法在 arm64 群集上安装](https://gitlab.com/gitlab-org/gitlab/-/issues/29838) . + +### Existing Kubernetes cluster[](#existing-kubernetes-cluster "Permalink") + +要将 Kubernetes 集群添加到您的项目,组或实例: + +1. 导航到您的: + 1. 项目的 **操作> Kubernetes**页面,用于项目级集群. + 2. 组的 **Kubernetes**页面,用于组级别集群. + 3. **管理区>** **Kubernetes**页面,用于实例级集群. +2. Click **添加 Kubernetes 集群**. +3. 单击**添加现有集群**选项卡,然后填写详细信息: + 1. **Kubernetes 集群名称** (必填)-您希望为**集群指定**的名称. + 2. **环境范围** (必需)- [与](index.html#setting-the-environment-scope-premium)此集群[相关的环境](index.html#setting-the-environment-scope-premium) . + 3. **API URL** (必填)-这是 GitLab 用于访问 Kubernetes API 的 URL. Kubernetes 公开了几个 API,我们想要所有这些 API 通用的"基本" URL. 例如, `https://kubernetes.example.com`而不是`https://kubernetes.example.com/api/v1` . + + 通过运行以下命令获取 API URL: + + ``` + kubectl cluster-info | grep 'Kubernetes master' | awk '/http/ {print $NF}' + ``` + + 4. **CA 证书** (必需)-需要有效的 Kubernetes 证书才能对集群进行身份验证. 我们将使用默认创建的证书. + 1. 列出带有`kubectl get secrets` ,并且应将其命名类似于`default-token-xxxxx` . 复制该令牌名称以在下面使用. + 2. 通过运行以下命令获取证书: + + ``` + kubectl get secret -o jsonpath = "{['data']['ca \. crt']}" | base64 --decode + ``` + + **注意:**如果命令返回整个证书链,则需要在证书链的底部复制*根 ca*证书. + 5. **令牌** -GitLab 使用服务令牌对 Kubernetes 进行身份验证,服务令牌的作用域是特定的`namespace` . **使用的令牌应属于具有[`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)特权的服务帐户.** 要创建此服务帐户: + 1. 创建一个名为`gitlab-admin-service-account.yaml` ,其内容为: + + ``` + apiVersion : v1 kind : ServiceAccount metadata : name : gitlab-admin namespace : kube-system --- apiVersion : rbac.authorization.k8s.io/v1beta1 kind : ClusterRoleBinding metadata : name : gitlab-admin roleRef : apiGroup : rbac.authorization.k8s.io kind : ClusterRole name : cluster-admin subjects : - kind : ServiceAccount name : gitlab-admin namespace : kube-system + ``` + + 2. 将服务帐户和群集角色绑定应用于您的群集: + + ``` + kubectl apply -f gitlab-admin-service-account.yaml + ``` + + 您将需要`container.clusterRoleBindings.create`权限来创建集群级角色. 如果您没有此权限,则可以选择启用基本身份验证,然后以管理员身份运行`kubectl apply`命令: + + ``` + kubectl apply -f gitlab-admin-service-account.yaml --username = admin --password = + ``` + + **注意:**可以打开基本身份验证,并可以使用 Google Cloud Console 获取密码凭据. + + 输出: + + ``` + serviceaccount "gitlab-admin" created clusterrolebinding "gitlab-admin" created + ``` + + 3. 检索`gitlab-admin`服务帐户的令牌: + + ``` + kubectl -n kube-system describe secret $( kubectl -n kube-system get secret | grep gitlab-admin | awk '{print $1}' ) + ``` + + 从输出中复制``值: + + ``` + Name : gitlab-admin-token-b5zv4 Namespace : kube-system Labels : Annotations : kubernetes.io/service-account.name=gitlab-admin kubernetes.io/service-account.uid=bcfe66ac-39be-11e8-97e8-026dce96b6e8 Type : kubernetes.io/service-account-token Data ==== ca.crt : 1025 bytes namespace : 11 bytes token : + ``` + + **注意:**对于 GKE 群集,您将需要`container.clusterRoleBindings.create`权限来创建群集角色绑定. 您可以按照[Google Cloud 文档](https://cloud.google.com/iam/docs/granting-changing-revoking-access)授予访问权限. + 6. **由 GitLab 管理的群集** -如果要让 GitLab 管理该群集的名称空间和服务帐户,请选中此复选框. 有关更多信息,请参见[托管集群部分](index.html#gitlab-managed-clusters) . + 7. **项目名称空间** (可选)-您不必填写它; 将其保留为空白,GitLab 将为您创建一个. 也: + * 每个项目应具有唯一的名称空间. + * 如果您正在使用具有更广泛权限的机密(例如`default`的机密),则项目名称空间不一定是机密的名称空间. + * 你**不**应该使用`default`为项目命名空间. + * 如果您或某人为项目专门创建了一个秘密(通常具有有限的权限),则该秘密的名称空间和项目名称空间可能是相同的. +4. 最后,单击**创建 Kubernetes 集群**按钮. + +几分钟后,您的集群将准备就绪. 现在,您可以继续安装一些[预定义的应用程序](index.html#installing-applications) . + +#### Disable Role-Based Access Control (RBAC) (optional)[](#disable-role-based-access-control-rbac-optional "Permalink") + +通过 GitLab 集成连接集群时,您可以指定集群是否支持 RBAC. 这将影响 GitLab 如何与集群进行某些操作的交互. 如果您在创建时*未*选中**启用 RBAC 的群集**复选框,则 GitLab 将假定与群集进行交互时禁用了 RBAC. 如果是这样,则必须在群集上禁用 RBAC 才能使集成正常工作. + +[![rbac](img/9d9a196fe723b5afc79e2d7b29fd0f4d.png)](img/rbac_v13_1.png) + +**注意:**禁用 RBAC 意味着群集中运行的任何应用程序或可以向群集进行身份验证的用户都具有完全的 API 访问权限. 这是一个[安全问题](index.html#security-implications) ,可能不是所希望的. + +为了有效地禁用 RBAC,可以应用全局权限来授予完全访问权限: + +``` +kubectl create clusterrolebinding permissive-binding \ + --clusterrole=cluster-admin \ + --user=admin \ + --user=kubelet \ + --group=system:serviceaccounts +``` + +## Enabling or disabling integration[](#enabling-or-disabling-integration "Permalink") + +成功创建新集群或添加现有集群后,即可启用 Kubernetes 集群集成. 要禁用 Kubernetes 集群集成: + +1. 导航到您的: + * 项目的 **操作> Kubernetes**页面,用于项目级集群. + * 组的 **Kubernetes**页面,用于组级别集群. + * **管理区>** **Kubernetes**页面,用于实例级集群. +2. 单击群集的名称. +3. 单击**GitLab 集成**切换. +4. Click **保存更改**. + +## Removing integration[](#removing-integration "Permalink") + +要从您的项目中删除 Kubernetes 集群集成,请首先导航到集群详细信息页面的**Advanced Settings**选项卡,然后执行以下任一操作: + +* 选择**删除集成** ,仅删除 Kubernetes 集成. +* [从 GitLab 12.6 中](https://gitlab.com/gitlab-org/gitlab/-/issues/26815) ,选择**删除集成和资源** ,以在**删除集成时**也删除所有相关的 GitLab 集群资源(例如,名称空间,角色和绑定). + +删除集群集成时,请注意: + +* 您需要具有维护人员及以上[权限](../../permissions.html)才能删除 Kubernetes 集群集成. +* 删除集群时,只删除其与 GitLab 的关系,而不删除集群本身. 要删除集群,可以通过访问 GKE 或 EKS 仪表板或使用`kubectl`来`kubectl` . + +## Learn more[](#learn-more "Permalink") + +要了解有关自动部署应用程序的更多信息,请阅读有关[Auto DevOps](../../../topics/autodevops/index.html) . \ No newline at end of file diff --git a/_book/docs/018.md b/_book/docs/018.md new file mode 100644 index 0000000000000000000000000000000000000000..ed361cb7d4b5f8794d573c41a2c6ff1ffa94548e --- /dev/null +++ b/_book/docs/018.md @@ -0,0 +1,190 @@ +# Adding EKS clusters + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/add_eks_clusters.html](https://docs.gitlab.com/ee/user/project/clusters/add_eks_clusters.html) + +* [EKS requirements](#eks-requirements) + * [Additional requirements for self-managed instances](#additional-requirements-for-self-managed-instances-core-only) +* [New EKS cluster](#new-eks-cluster) + * [Troubleshooting creating a new cluster](#troubleshooting-creating-a-new-cluster) + * [Error: Request failed with status code 422](#error-request-failed-with-status-code-422) + * [Could not load Security Groups for this VPC](#could-not-load-security-groups-for-this-vpc) + * [`ROLLBACK_FAILED` during cluster creation](#rollback_failed-during-cluster-creation) +* [Existing EKS cluster](#existing-eks-cluster) + * [Create a default Storage Class](#create-a-default-storage-class) + * [Deploy the app to EKS](#deploy-the-app-to-eks) + +# Adding EKS clusters[](#adding-eks-clusters "Permalink") + +GitLab 支持添加新的和现有的 EKS 集群. + +## EKS requirements[](#eks-requirements "Permalink") + +在通过 GitLab 集成在 Amazon EKS 上创建第一个集群之前,请确保满足以下要求: + +* 设置了[Amazon Web Services](https://aws.amazon.com/)帐户,您就可以登录. +* 您有权管理 IAM 资源. +* 如果要使用[现有的 EKS 集群](#existing-eks-cluster) : + * 已正确配置工作节点的 Amazon EKS 集群. + * [安装并配置](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html#get-started-kubectl)了`kubectl`以访问 EKS 集群. + +### Additional requirements for self-managed instances[](#additional-requirements-for-self-managed-instances-core-only "Permalink") + +如果您使用自我管理的 GitLab 实例,则必须首先使用一组 Amazon 凭证配置 GitLab. 这些凭证将用于承担创建集群的用户提供的 Amazon IAM 角色. 创建一个 IAM 用户,并确保其有权承担您的用户将用来创建 EKS 群集的角色. + +例如,以下策略文档允许在帐户`123456789012`假设一个角色的名称以`gitlab-eks-` : + +``` +{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::123456789012:role/gitlab-eks-*" } } +``` + +为 IAM 用户生成访问密钥,并使用凭据配置 GitLab: + +1. 导航至**管理区域>设置>集成,**然后展开**Amazon EKS**部分. +2. Check **启用 Amazon EKS 集成**. +3. 在相应的`Account ID` , `Access key ID`和`Secret access key`字段中输入帐户 ID 和访问密钥凭据. +4. Click **保存更改**. + +## New EKS cluster[](#new-eks-cluster "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22392) . + +要创建新的 Kubernetes 集群并将其添加到您的项目,组或实例: + +1. 导航到您的: + * 项目的 **操作> Kubernetes**页面,用于项目级集群. + * 组的 **Kubernetes**页面,用于组级别集群. + * **管理区>** **Kubernetes** ,用于实例级集群. +2. Click **添加 Kubernetes 集群**. +3. 在" **创建新集群"**选项卡下,单击**Amazon EKS** . 将为您提供一个`Account ID`和`External ID` ,供下一步使用. +4. 在[IAM 管理控制台中](https://console.aws.amazon.com/iam/home) ,创建一个 IAM 角色: + 1. 在左侧面板中,选择**角色** . + 2. 单击**创建角色** . + 3. 在`Select type of trusted entity` ,选择**另一个 AWS 账户** . + 4. 在 GitLab 中的`Account ID`字段中输入`Account ID` . + 5. 选中**需要外部 ID** . + 6. 在 GitLab 中将`External ID`输入到`External ID`字段中. + 7. 单击**下一步:权限** . + 8. 点击**创建策略** ,这将打开一个新窗口. + 9. 选择**JSON**标签,然后粘贴以下代码段代替现有内容: + + ``` + { + "Version" : "2012-10-17" , + "Statement" : [ + { + "Effect" : "Allow" , + "Action" : [ + "autoscaling:CreateAutoScalingGroup" , + "autoscaling:DescribeAutoScalingGroups" , + "autoscaling:DescribeScalingActivities" , + "autoscaling:UpdateAutoScalingGroup" , + "autoscaling:CreateLaunchConfiguration" , + "autoscaling:DescribeLaunchConfigurations" , + "cloudformation:CreateStack" , + "cloudformation:DescribeStacks" , + "ec2:AuthorizeSecurityGroupEgress" , + "ec2:AuthorizeSecurityGroupIngress" , + "ec2:RevokeSecurityGroupEgress" , + "ec2:RevokeSecurityGroupIngress" , + "ec2:CreateSecurityGroup" , + "ec2:createTags" , + "ec2:DescribeImages" , + "ec2:DescribeKeyPairs" , + "ec2:DescribeRegions" , + "ec2:DescribeSecurityGroups" , + "ec2:DescribeSubnets" , + "ec2:DescribeVpcs" , + "eks:CreateCluster" , + "eks:DescribeCluster" , + "iam:AddRoleToInstanceProfile" , + "iam:AttachRolePolicy" , + "iam:CreateRole" , + "iam:CreateInstanceProfile" , + "iam:CreateServiceLinkedRole" , + "iam:GetRole" , + "iam:ListRoles" , + "iam:PassRole" , + "ssm:GetParameters" + ], + "Resource" : "*" + } + ] + } + ``` + + **注意:**这些权限使 GitLab 能够创建资源,但不能删除它们. 这意味着,如果在创建过程中遇到错误,更改将不会回滚,您必须手动删除资源. 您可以通过删除相关的[CloudFormation 堆栈](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html)来做到这一点 + 10. 点击**审核政策** . + 11. 为此策略输入合适的名称,然后点击**创建策略** . 您现在可以关闭此窗口. + 12. 切换回"创建角色"窗口,然后选择刚创建的策略. + 13. 单击**下一步:标签** ,并选择输入您希望与此角色关联的任何标签. + 14. 单击**下一步:查看** . + 15. 在提供的字段中输入角色名称和可选描述. + 16. 点击**创建角色** ,新角色名称将显示在顶部. 单击其名称,然后从新创建的角色复制`Role ARN` . +5. 在 GitLab 中,将复制的角色 ARN 输入到`Role ARN`字段中. +6. Click **使用 AWS 进行身份验证**. +7. 选择集群的设置: + * **Kubernetes 集群名称** -您希望赋予集群的名称. + * **环境范围** -该集群的[关联环境](index.html#setting-the-environment-scope-premium) . + * **Kubernetes 版本** -要使用的 Kubernetes 版本. 当前唯一支持的版本是 1.14\. + * **角色名称** -选择[IAM 角色](https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html)以允许 Amazon EKS 和 Kubernetes 控制平面代表您管理 AWS 资源. 此 IAM 角色与上面创建的 IAM 角色是分开的,如果尚不存在,则需要创建它. + * **区域** -将在其中创建群集的[区域](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html) . + * **密钥对名称** -如果需要,选择可用于连接到工作节点的[密钥对](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) . + * **VPC-**选择要用于 EKS 群集资源的[VPC](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html) . + * **子网** -在您的 VPC 中选择运行工作节点的[子网](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html) . 您必须至少选择两个. + * **安全组** -选择[安全组](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html)以应用到在工作节点子网中创建的 EKS 管理的弹性网络接口. + * **实例类型** -工作节点的[实例类型](https://aws.amazon.com/ec2/instance-types/) . + * **节点数** -工作节点数. + * **由 GitLab 管理的群集** -如果要让 GitLab 管理该群集的名称空间和服务帐户,请选中此复选框. 有关更多信息,请参见[托管集群部分](index.html#gitlab-managed-clusters) . +8. 最后,单击**创建 Kubernetes 集群**按钮. + +大约 10 分钟后,您的集群便可以使用了. 现在,您可以继续安装一些[预定义的应用程序](index.html#installing-applications) . + +**注意:**您需要将 AWS 外部 ID 添加到[AWS CLI 中](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html#cli-configure-role-xaccount)的[IAM 角色,](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html#cli-configure-role-xaccount)才能使用`kubectl`管理集群. + +### Troubleshooting creating a new cluster[](#troubleshooting-creating-a-new-cluster "Permalink") + +创建新集群时,通常会遇到以下错误. + +#### Error: Request failed with status code 422[](#error-request-failed-with-status-code-422 "Permalink") + +提交初始身份验证表单时,如果无法确定您提供的角色,则 GitLab 会返回状态码 422 错误. 确保已使用 GitLab 提供的**帐户 ID**和**外部 ID**正确配置了角色. 在 GitLab 中,确保输入正确的**Role ARN** . + +#### Could not load Security Groups for this VPC[](#could-not-load-security-groups-for-this-vpc "Permalink") + +当在配置表单中填充选项时,GitLab 将返回此错误,因为 GitLab 已成功承担了您提供的角色,但是该角色没有足够的权限来检索表单所需的资源. 确保已为角色分配了正确的权限. + +#### `ROLLBACK_FAILED` during cluster creation[](#rollback_failed-during-cluster-creation "Permalink") + +由于 GitLab 在创建一个或多个资源时遇到错误,因此创建过程停止. 您可以检查关联的[CloudFormation 堆栈](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-view-stack-data-resources.html)以查找创建失败的特定资源. + +如果`Cluster`资源因错误`The provided role doesn't have the Amazon EKS Managed Policies associated with it.`失败,则`The provided role doesn't have the Amazon EKS Managed Policies associated with it.` , **角色名称**中指定的**角色**配置不正确. + +**注意:**此角色不应与上面创建的角色相同. 如果您没有现有的[EKS 群集 IAM 角色](https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html) ,则必须创建一个. + +## Existing EKS cluster[](#existing-eks-cluster "Permalink") + +有关添加现有 EKS 群集的信息,请参阅" [现有 Kubernetes 群集"](add_remove_clusters.html#existing-kubernetes-cluster) . + +### Create a default Storage Class[](#create-a-default-storage-class "Permalink") + +Amazon EKS 没有开箱即用的默认存储类,这意味着对持久卷的请求将不会自动满足. 作为 Auto DevOps 的一部分,已部署的 PostgreSQL 实例将请求持久存储,并且如果没有默认存储类,它将无法启动. + +如果默认的存储类尚不存在并且需要使用,请按照 Amazon 的[存储类指南](https://docs.aws.amazon.com/eks/latest/userguide/storage-classes.html)创建一个. + +或者,通过将项目变量[`POSTGRES_ENABLED`](../../../topics/autodevops/customize.html#environment-variables)设置为`false`来禁用 PostgreSQL. + +### Deploy the app to EKS[](#deploy-the-app-to-eks "Permalink") + +在禁用 RBAC 和部署服务的情况下,现在可以利用[Auto DevOps](../../../topics/autodevops/index.html)构建,测试和部署应用程序. + +如果尚未启用,则[启用 Auto DevOps](../../../topics/autodevops/index.html#at-the-project-level) . 如果创建了通配符 DNS 条目以解析到负载均衡器,请在"自动 DevOps"设置下的" `domain`字段中输入它. 否则,已部署的应用程序将无法在群集外部从外部获得. + +[![Deploy Pipeline](img/de608fa9aefa963f38d0d95043413679.png)](img/pipeline.png) + +将自动创建一个新管道,该管道将开始构建,测试和部署该应用程序. + +管道完成后,您的应用将在 EKS 中运行,并可供用户使用. 单击**CI / CD>环境** . + +[![Deployed Environment](img/dc47374cec4da1de3e6476346ecf738e.png)](img/environment.png) + +您将看到环境及其部署状态的列表,以及浏览到应用程序,查看监视指标甚至访问正在运行的 Pod 上的 Shell 的选项. \ No newline at end of file diff --git a/_book/docs/019.md b/_book/docs/019.md new file mode 100644 index 0000000000000000000000000000000000000000..fa763920987d9effd3c7fdadfe55e25f7149dc67 --- /dev/null +++ b/_book/docs/019.md @@ -0,0 +1,65 @@ +# Adding GKE clusters + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/add_gke_clusters.html](https://docs.gitlab.com/ee/user/project/clusters/add_gke_clusters.html) + +* [GKE requirements](#gke-requirements) +* [New GKE cluster](#new-gke-cluster) + * [Creating the cluster on GKE](#creating-the-cluster-on-gke) + * [Cloud Run for Anthos](#cloud-run-for-anthos) +* [Existing GKE cluster](#existing-gke-cluster) + +# Adding GKE clusters[](#adding-gke-clusters "Permalink") + +GitLab 支持添加新的和现有的 GKE 集群. + +## GKE requirements[](#gke-requirements "Permalink") + +在通过 GitLab 集成在 Google GKE 上创建第一个集群之前,请确保满足以下要求: + +* 设置了具有访问权限的[结算帐户](https://cloud.google.com/billing/docs/how-to/manage-billing-account) . +* 启用了 Kubernetes Engine API 和相关服务. 它应该可以立即工作,但是创建项目后最多可能需要 10 分钟. 有关更多信息,请参见[Kubernetes Engine 文档](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin)的["开始之前"部分](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin) . + +## New GKE cluster[](#new-gke-cluster "Permalink") + +从[GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/issues/25925)开始, [GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/25925)提供的所有 GKE 群集均为[VPC 本地的](https://cloud.google.com/kubernetes-engine/docs/how-to/alias-ips) . + +请注意以下几点: + +* 必须在实例级别的 GitLab 中启用[Google 身份验证集成](../../../integration/google.html) . 如果不是这种情况,请要求您的 GitLab 管理员启用它. 在 GitLab.com 上启用了此功能. +* 从[GitLab 12.1](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55902)开始,由[GitLab](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55902)创建的所有 GKE 集群都启用了 RBAC. 请参阅[RBAC 部分](add_remove_clusters.html#rbac-cluster-resources)以获取更多信息. +* 从[GitLab 12.5](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18341)开始,群集的 Pod 地址 IP 范围将设置为/ 16,而不是常规的/ 14\. / 16 是 CIDR 表示法. +* GitLab 要求启用基本身份验证并为集群颁发客户端证书,以设置[初始服务帐户](add_remove_clusters.html#access-controls) . 在[GitLab 11.10 及更高版本中](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/58208) ,集群创建过程明确要求 GKE 创建启用了基本身份验证和客户端证书的集群. + +### Creating the cluster on GKE[](#creating-the-cluster-on-gke "Permalink") + +要创建新的 Kubernetes 集群并将其添加到您的项目,组或实例: + +1. 导航到您的: + * 项目的 **操作> Kubernetes**页面,用于项目级集群. + * 组的 **Kubernetes**页面,用于组级别集群. + * **管理区>** **Kubernetes**页面,用于实例级集群. +2. Click **添加 Kubernetes 集群**. +3. 在[ **建立新丛集]**标签下,按一下[ **Google GKE]** . +4. 如果尚未连接 Google 帐户,请单击" **使用 Google 登录"**按钮. +5. 选择集群的设置: + * **Kubernetes 集群名称** -您希望赋予集群的名称. + * **环境范围** -该集群的[关联环境](index.html#setting-the-environment-scope-premium) . + * **Google Cloud Platform 项目** -选择您在 GCP 控制台中创建的将托管 Kubernetes 集群的项目. 了解有关[Google Cloud Platform 项目的](https://cloud.google.com/resource-manager/docs/creating-managing-projects)更多信息. + * **区域** -选择将在其下创建群集的[区域区域](https://cloud.google.com/compute/docs/regions-zones/) . + * **节点数** -输入希望群集具有的节点数. + * **计算机类型** -群集将基于的虚拟机实例的[计算机类型](https://cloud.google.com/compute/docs/machine-types) . + * **为 Anthos 启用 Cloud Run-**如果要对此集群使用 Cloud Run for Anthos,请选中此复选框. 有关更多信息,请参见[Anthos](#cloud-run-for-anthos)的[Cloud Run 部分](#cloud-run-for-anthos) . + * **由 GitLab 管理的群集** -如果要让 GitLab 管理该群集的名称空间和服务帐户,请选中此复选框. 有关更多信息,请参见[托管集群部分](index.html#gitlab-managed-clusters) . +6. 最后,单击**创建 Kubernetes 集群**按钮. + +几分钟后,您的集群将准备就绪. 现在,您可以继续安装一些[预定义的应用程序](index.html#installing-applications) . + +### Cloud Run for Anthos[](#cloud-run-for-anthos "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16566) . + +创建群集后,可以选择使用 Cloud Run for Anthos 代替分别安装 Knative 和 Istio. 这意味着将在创建时在集群上启用 Cloud Run(Knative),Istio 和 HTTP Load Balancing,并且不能单独[安装或卸载](../../clusters/applications.html) . + +## Existing GKE cluster[](#existing-gke-cluster "Permalink") + +有关添加现有 GKE 群集的信息,请参阅" [现有 Kubernetes 群集"](add_remove_clusters.html#existing-kubernetes-cluster) . \ No newline at end of file diff --git a/_book/docs/020.md b/_book/docs/020.md new file mode 100644 index 0000000000000000000000000000000000000000..e00a05647fd42a90e2515b47ea7136bf641168d0 --- /dev/null +++ b/_book/docs/020.md @@ -0,0 +1,144 @@ +# Group-level Kubernetes clusters + +> 原文:[https://docs.gitlab.com/ee/user/group/clusters/](https://docs.gitlab.com/ee/user/group/clusters/) + +* [Installing applications](#installing-applications) +* [RBAC compatibility](#rbac-compatibility) +* [Cluster precedence](#cluster-precedence) +* [Multiple Kubernetes clusters](#multiple-kubernetes-clusters) +* [GitLab-managed clusters](#gitlab-managed-clusters) + * [Clearing the cluster cache](#clearing-the-cluster-cache) +* [Base domain](#base-domain) +* [Environment scopes](#environment-scopes-premium) +* [Cluster environments](#cluster-environments-premium) +* [Security of Runners](#security-of-runners) +* [More information](#more-information) + +# Group-level Kubernetes clusters[](#group-level-kubernetes-clusters "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34758) . + +与[项目级](../../project/clusters/index.html)和[实例级](../../instance/clusters/index.html) Kubernetes 集群类似,组级 Kubernetes 集群允许您将 Kubernetes 集群连接到您的组,从而使您可以在多个项目中使用同一集群. + +## Installing applications[](#installing-applications "Permalink") + +GitLab 可以在您的组级别集群中安装和管理某些应用程序. 有关为您的组集群安装,升级,卸载和故障排除应用程序的更多信息,请参阅[GitLab 托管应用程序](../../clusters/applications.html) . + +## RBAC compatibility[](#rbac-compatibility "Permalink") + +版本历史 + +* 在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29398) . +* [项目名称空间限制](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51716)是在 GitLab 11.5 中引入的. + +对于具有 Kubernetes 集群的组中的每个项目,GitLab 都会在项目名称空间中创建具有[`edit`权限](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)的受限服务帐户. + +## Cluster precedence[](#cluster-precedence "Permalink") + +如果项目的群集可用且未禁用,则 GitLab 在使用属于包含该项目的组的任何群集之前,先使用项目的群集. 对于子组,如果未禁用该组,则 GitLab 将使用与项目最接近的祖先组的集群. + +## Multiple Kubernetes clusters[](#multiple-kubernetes-clusters "Permalink") + +版本历史 + +* 在 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094)了 GitLab Core. + +您可以将多个 Kubernetes 集群关联到您的组,并为不同的环境(例如开发,登台和生产)维护不同的集群. + +添加另一个群集时,请[设置环境范围](#environment-scopes-premium)以帮助区分新群集和其他群集. + +## GitLab-managed clusters[](#gitlab-managed-clusters "Permalink") + +版本历史 + +* 在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22011) . +* 在 GitLab 11.11 中成为[可选](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26565) . + +You can choose to allow GitLab to manage your cluster for you. If GitLab manages your cluster, resources for your projects will be automatically created. See the [Access controls](../../project/clusters/add_remove_clusters.html#access-controls) section for details on which resources GitLab creates for you. + +对于不受 GitLab 管理的集群,将不会自动创建特定于项目的资源. 如果将[Auto DevOps](../../../topics/autodevops/index.html)用于具有不受 GitLab 管理的群集的部署,则必须确保: + +* 项目的部署服务帐户有权部署到[`KUBE_NAMESPACE`](../../project/clusters/index.html#deployment-variables) . +* `KUBECONFIG`正确反映了对`KUBE_NAMESPACE`任何更改(这[不是自动的](https://gitlab.com/gitlab-org/gitlab/-/issues/31519) ). 不建议直接编辑`KUBE_NAMESPACE` . + +**注意:**如果您在群集上[安装应用程序](#installing-applications) ,即使您选择管理自己的群集,GitLab 也会创建运行它们所需的资源. + +### Clearing the cluster cache[](#clearing-the-cluster-cache "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31759) . + +如果您选择允许 GitLab 为您管理集群,则 GitLab 将存储它为项目创建的名称空间和服务帐户的缓存版本. 如果在群集中手动修改这些资源,则此缓存可能与群集不同步,这可能导致部署作业失败. + +清除缓存: + +1. 导航到您小组的 **Kubernetes**页面,然后选择您的集群. +2. 展开**高级设置**部分. +3. Click **清除集群缓存**. + +## Base domain[](#base-domain "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24580) . + +集群级别的域允许每个[多个 Kubernetes 集群](#multiple-kubernetes-clusters)支持多个域.指定域时,这将在[Auto DevOps](../../../topics/autodevops/index.html)阶段自动设置为环境变量( `KUBE_INGRESS_BASE_DOMAIN` ). + +该域应将通配符 DNS 配置为入口 IP 地址. + +## Environment scopes[](#environment-scopes-premium "Permalink") + +将多个 Kubernetes 集群添加到您的项目时,您需要通过环境范围来区分它们. 环境范围将群集与[环境](../../../ci/environments/index.html)相关联,类似于[特定](../../../ci/variables/README.html#limit-the-environment-scopes-of-environment-variables)于[环境的变量的](../../../ci/variables/README.html#limit-the-environment-scopes-of-environment-variables)工作方式. + +在评估哪个环境与群集的环境范围匹配时, [群集优先级](#cluster-precedence)将生效. 项目级别的集群优先,其次是最接近的祖先组,然后是该组的父级,依此类推. + +例如,如果您的项目具有以下 Kubernetes 集群: + +| Cluster | 环境范围 | Where | +| --- | --- | --- | +| Project | `*` | Project | +| Staging | `staging/*` | Project | +| Production | `production/*` | Project | +| Test | `test` | Group | +| Development | `*` | Group | + +[`.gitlab-ci.yml`](../../../ci/yaml/README.html)中设置了以下环境: + +``` +stages: + - test + - deploy + +test: + stage: test + script: sh test + +deploy to staging: + stage: deploy + script: make deploy + environment: + name: staging/$CI_COMMIT_REF_NAME + url: https://staging.example.com/ + +deploy to production: + stage: deploy + script: make deploy + environment: + name: production/$CI_COMMIT_REF_NAME + url: https://example.com/ +``` + +结果是: + +* 项目集群用于`test`作业. +* 分段群集用于`deploy to staging`作业. +* 生产集群用于`deploy to production`作业. + +## Cluster environments[](#cluster-environments-premium "Permalink") + +有关将哪种 CI [环境](../../../ci/environments/index.html)部署到 Kubernetes 集群的统一视图,请参阅[集群环境](../../clusters/environments.html)文档. + +## Security of Runners[](#security-of-runners "Permalink") + +有关安全配置 GitLab Runners 的重要信息,请参阅项目级集群[的 Runners 安全性](../../project/clusters/add_remove_clusters.html#security-of-gitlab-runners)文档. + +## More information[](#more-information "Permalink") + +For information on integrating GitLab and Kubernetes, see [Kubernetes clusters](../../project/clusters/index.html). \ No newline at end of file diff --git a/_book/docs/021.md b/_book/docs/021.md new file mode 100644 index 0000000000000000000000000000000000000000..a9f066f1278ddb6dc5e8a5cb06ccf07cf17d1858 --- /dev/null +++ b/_book/docs/021.md @@ -0,0 +1,34 @@ +# Instance-level Kubernetes clusters + +> 原文:[https://docs.gitlab.com/ee/user/instance/clusters/](https://docs.gitlab.com/ee/user/instance/clusters/) + +* [Overview](#overview) +* [Cluster precedence](#cluster-precedence) +* [Cluster environments](#cluster-environments-premium) +* [More information](#more-information) + +# Instance-level Kubernetes clusters[](#instance-level-kubernetes-clusters "Permalink") + +在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39840) . + +## Overview[](#overview "Permalink") + +与[项目级](../../project/clusters/index.html)和[组级](../../group/clusters/index.html) Kubernetes 集群类似,实例级 Kubernetes 集群允许您将 Kubernetes 集群连接到 GitLab 实例,这使您可以在多个项目中使用同一集群. + +## Cluster precedence[](#cluster-precedence "Permalink") + +GitLab 将尝试按以下顺序匹配集群: + +* 项目级集群. +* 组级别群集. +* 实例级集群. + +要选择集群,必须启用集群并使其与[环境选择器](../../../ci/environments/index.html#scoping-environments-with-specs)匹配. + +## Cluster environments[](#cluster-environments-premium "Permalink") + +有关将哪种 CI [环境](../../../ci/environments/index.html)部署到 Kubernetes 集群的统一视图,请参阅[集群环境](../../clusters/environments.html)文档. + +## More information[](#more-information "Permalink") + +有关集成 GitLab 和 Kubernetes 的信息,此[Kubernetes 集群](../../project/clusters/index.html) . \ No newline at end of file diff --git a/_book/docs/022.md b/_book/docs/022.md new file mode 100644 index 0000000000000000000000000000000000000000..5a0961c34fd6d09c041f896aa2b37619333e2e79 --- /dev/null +++ b/_book/docs/022.md @@ -0,0 +1,42 @@ +# Canary Deployments + +> 原文:[https://docs.gitlab.com/ee/user/project/canary_deployments.html](https://docs.gitlab.com/ee/user/project/canary_deployments.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Enabling Canary Deployments](#enabling-canary-deployments) + +# Canary Deployments[](#canary-deployments-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1659) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.1. + +一种流行的[持续部署](https://en.wikipedia.org/wiki/Continuous_deployment)策略,其中将一小部分机队更新为应用程序的新版本. + +## Overview[](#overview "Permalink") + +在采用[持续交付时](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) ,公司需要决定要使用哪种部署策略. 最受欢迎的策略之一是金丝雀部署,首先将一小部分机队更新为新版本. 金丝雀的这个子集,然后在煤矿中成为众所周知的[金丝雀](https://en.wiktionary.org/wiki/canary_in_a_coal_mine) . + +如果应用程序的新版本存在问题,则仅会影响一小部分用户,并且可以固定更改或快速还原更改. + +利用[Kubernetes 的 Canary 部署](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments) ,无需离开 GitLab,即可在[Deploy Board](deploy_boards.html)内部可视化您的 Canary 部署. + +## Use cases[](#use-cases "Permalink") + +当您只想向部分 Pod 舰队提供功能并观看其行为时,可以使用 Canary 部署. 如果一切正常,您可以将该功能部署到生产中,因为它不会造成任何问题. + +Canary 部署对于后端重构,性能改进或用户界面不变的其他更改也特别有用,但是您要确保性能保持不变或有所提高. 开发人员在使用面向用户的更改的 Canary 时需要谨慎,因为默认情况下,来自同一用户的请求将随机分布在 Canary 和非 Canary Pod 之间,这可能导致混乱甚至错误. 如果需要,您可能需要考虑[在 Kubernetes 服务定义中将`service.spec.sessionAffinity`设置为`ClientIP`](https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies) ,但这超出了本文档的范围. + +## Enabling Canary Deployments[](#enabling-canary-deployments "Permalink") + +Canary 部署要求您正确配置 Deploy Boards: + +1. 请按照以下步骤[启用 Deploy Boards](deploy_boards.html#enabling-deploy-boards) . +2. 要跟踪 canary 部署,您需要使用`track: canary`标记 Kubernetes 部署和 Pod. 为了快速入门,您可以将[自动部署](../../topics/autodevops/stages.html#auto-deploy)模板用于 GitLab 提供的金丝雀部署. + +根据部署情况,标签应该是`stable`或`canary` . 通常, `stable`且空白或丢失的标签表示同一件事,而`canary`或任何其他轨道表示金丝雀/临时. 这使 GitLab 能够发现部署是稳定的还是金丝雀(临时)的. + +完成以上所有设置并且管道至少运行了一次之后,导航至" **管道">"环境"**下的环境页面. 随着管道的执行,部署委员会将清楚地标记金丝雀荚,从而可以快速,轻松地洞察每种环境和部署的状态. + +Canary deployments are marked with a yellow dot in the Deploy Board so that you can easily notice them. + +[![Canary deployments on Deploy Board](img/9a002df90c6ed1d01c8ae3a9817242df.png)](img/deploy_boards_canary_deployments.png) \ No newline at end of file diff --git a/_book/docs/023.md b/_book/docs/023.md new file mode 100644 index 0000000000000000000000000000000000000000..9a11616616052d0777d2aa9e4218d2ab88ef726d --- /dev/null +++ b/_book/docs/023.md @@ -0,0 +1,42 @@ +# Cluster Environments + +> 原文:[https://docs.gitlab.com/ee/user/clusters/environments.html](https://docs.gitlab.com/ee/user/clusters/environments.html) + +* [Overview](#overview) +* [Usage](#usage) + +# Cluster Environments[](#cluster-environments-premium "Permalink") + +> * 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.3 中针对组级集群[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13392) . +> * 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.4 中针对实例级集群进行了[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/14809) . + +群集环境提供了一个统一的视图,用于说明将哪些 CI [环境](../../ci/environments/index.html)部署到 Kubernetes 群集及其: + +* 显示项目和与部署相关的相关环境. +* 显示该环境的窗格的状态. + +## Overview[](#overview "Permalink") + +使用集群环境,您可以深入了解: + +* 哪些项目已部署到集群. +* 每个项目的环境使用了多少个 Pod. +* 用于部署到该环境的 CI 作业. + +[![Cluster environments page](img/662e9b0c090a4f28c82eb779aabdc9c8.png)](img/cluster_environments_table_v12_3.png) + +仅限集群[维护者和所有者](../permissions.html#group-members-permissions)访问集群环境 + +## Usage[](#usage "Permalink") + +为了: + +* 跟踪集群的环境,您必须成功[部署到 Kubernetes 集群](../project/clusters/index.html#deploying-to-a-kubernetes-cluster) . +* 正确显示容器使用情况,必须[启用 Deploy Boards](../project/deploy_boards.html#enabling-deploy-boards) . + +成功部署到组级或实例级集群后: + +1. 导航到您组的**Kubernetes**页面. +2. 单击**环境**选项卡. + +**注意:**此页面仅包含成功部署到群集的信息. 非群集环境将不包括在内. \ No newline at end of file diff --git a/_book/docs/024.md b/_book/docs/024.md new file mode 100644 index 0000000000000000000000000000000000000000..0fc69a277907a6d55e4970d65c873902713cfdb5 --- /dev/null +++ b/_book/docs/024.md @@ -0,0 +1,113 @@ +# Deploy Boards + +> 原文:[https://docs.gitlab.com/ee/user/project/deploy_boards.html](https://docs.gitlab.com/ee/user/project/deploy_boards.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Enabling Deploy Boards](#enabling-deploy-boards) + * [Example manifest file](#example-manifest-file) +* [Canary Deployments](#canary-deployments) +* [Further reading](#further-reading) + +# Deploy Boards[](#deploy-boards-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1589) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0. + +GitLab 的部署板提供了[Kubernetes](https://kubernetes.io)上运行的每个 CI [环境](../../ci/environments/index.html)的当前运行状况和状态的综合视图,显示了部署中 Pod 的状态. 开发人员和其他团队成员可以在已经使用的工作流程中逐个窗格地查看发布的进度和状态,而无需访问 Kubernetes. + +## Overview[](#overview "Permalink") + +使用部署板,您可以通过以下优势对部署进行更多了解: + +* 从头开始进行部署,而不仅仅是完成之后 +* 监视跨多个服务器的构建的推出 +* 更详细的状态详细信息(成功,正在运行,失败,待处理,未知) +* See [Canary Deployments](canary_deployments.html) + +这是生产环境的部署板的示例. + +[![Deploy Boards landing page](img/4ceccc7ae590a56e8b135fa8baaafabe.png)](img/deploy_boards_landing_page.png) + +正方形表示与给定环境关联的 Kubernetes 集群中的 Pod. 将鼠标悬停在每个方块上方,可以看到部署的状态. 百分比是已更新到最新版本的 Pod 的百分比. + +由于部署板与 Kubernetes 紧密结合,因此需要一些知识. 特别是,您应该熟悉: + +* [Kubernetes pods](https://kubernetes.io/docs/concepts/workloads/pods/pod/) +* [Kubernetes labels](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) +* [Kubernetes namespaces](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) +* [Kubernetes canary deployments](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments) + +**注意:**包含多个部署的应用程序在部署板上显示为重复项. 有关详细信息,请关注[此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/8463) . + +## Use cases[](#use-cases "Permalink") + +由于部署板是针对特定环境的 Kubernetes 吊舱的直观表示,因此存在许多用例. 仅举几例: + +* 您想将分阶段运行的产品推广到生产环境. 您转到环境列表,验证阶段运行的是您认为正在运行的,然后单击[手动操作](../../ci/yaml/README.html#whenmanual)以部署到生产环境. +* 您触发了部署,并且有很多容器需要升级,因此您将花费一段时间(您也限制了部署,一次只能删除 X 个容器). 但是您需要告诉某人何时部署,因此您可以转到环境列表,查看生产环境,以了解每个 Pod 滚动时的实时进度. +* 您会得到一份报告,说明生产中有些异常,因此您可以查看生产环境以查看正在运行什么,以及部署是否正在进行,是否停止或失败. +* 您的 MR 看起来不错,但是您希望在登台上运行它,因为登台是在某种程度上更接近生产环境进行设置的. 您转到环境列表,找到您感兴趣的[Review App](../../ci/review_apps/index.html) ,然后单击手动操作将其部署到登台. + +## Enabling Deploy Boards[](#enabling-deploy-boards "Permalink") + +要显示特定[环境](../../ci/environments/index.html)的部署板,您应该: + +1. 用部署阶段[定义了一个环境](../../ci/environments/index.html#defining-environments) . + +2. 使 Kubernetes 集群启动并运行. + + **在 OpenShift 上运行:**如果使用的是 OpenShift,请确保使用的是`Deployment`资源而不是`DeploymentConfiguration` . 否则,部署板将无法正确渲染. 有关更多信息,请阅读[OpenShift docs](https://docs.openshift.com/container-platform/3.7/dev_guide/deployments/kubernetes_deployments.html#kubernetes-deployments-vs-deployment-configurations)和[GitLab 问题#4584](https://gitlab.com/gitlab-org/gitlab/-/issues/4584) . +3. 使用[Docker](https://docs.gitlab.com/runner/executors/docker.html)或[Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html)执行器[配置 GitLab Runner](../../ci/runners/README.html) . +4. 在您的项目中为集群配置[Kubernetes 集成](clusters/index.html) . 特别注意 Kubernetes 命名空间,因为部署脚本(由`KUBE_NAMESPACE` env 变量公开)将需要它. +5. 确保将 app.gitlab.com/env:$ `app.gitlab.com/env: $CI_ENVIRONMENT_SLUG`和`app.gitlab.com/app: $CI_PROJECT_PATH_SLUG` CI_PROJECT_PATH_SLUG 的 Kubernetes 注释应用于部署,副本集和 Pod,其中`$CI_ENVIRONMENT_SLUG`和`$CI_PROJECT_PATH_SLUG`是 CI 变量的值. 这样一来,我们便可以在可能有多个的群集/命名空间中查找适当的环境. 这些资源应包含在 Kubernetes 服务设置中定义的名称空间中. 您可以使用[Autodeploy](../../topics/autodevops/stages.html#auto-deploy) `.gitlab-ci.yml`模板,该模板具有要使用的预定义阶段和命令,并自动应用注释. 每个项目还需要在 Kubernetes 中具有唯一的名称空间. 下图演示了如何在 Kubernetes 中显示此内容. + + **注意:**在[GitLab 12.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14020)中删除了基于 Kubernetes `app`标签的匹配. 要迁移,请应用所需的注释(请参见上文),然后重新部署您的应用程序. 如果您使用的是 Auto DevOps,这将自动完成,无需采取任何措施. + + [![Deploy Boards Kubernetes Label](img/f5739c1b278ddd91c915c534514b4235.png)](img/deploy_boards_kubernetes_label.png) + +完成以上所有设置并且管道至少运行了一次之后,导航至**Operations> Environments**下的 environment 页面. + +默认情况下,部署板是可见的. 您可以显式单击相应环境名称旁边的三角形以隐藏它们. + +### Example manifest file[](#example-manifest-file "Permalink") + +以下示例是使用两个注释`app.gitlab.com/env`和`app.gitlab.com/app`启用 Kubernetes 清单部署文件的`app.gitlab.com/env` ,以启用**Deploy Boards** : + +``` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: "APPLICATION_NAME" + annotations: + app.gitlab.com/app: ${CI_PROJECT_PATH_SLUG} + app.gitlab.com/env: ${CI_ENVIRONMENT_SLUG} +spec: + replicas: 1 + selector: + matchLabels: + app: "APPLICATION_NAME" + template: + metadata: + labels: + app: "APPLICATION_NAME" + annotations: + app.gitlab.com/app: ${CI_PROJECT_PATH_SLUG} + app.gitlab.com/env: ${CI_ENVIRONMENT_SLUG} +``` + +注释将应用于部署,副本集和 Pod. 通过更改副本数量,例如`kubectl scale --replicas=3 deploy APPLICATION_NAME -n ${KUBE_NAMESPACE}` ,您可以从开发板上跟踪实例的 pod. + +**注意:** YAML 文件是静态的. 如果使用`kubectl apply` ,则必须在`kubectl apply`之前手动提供项目和环境段,或者创建脚本来替换 YAML 中的变量. + +## Canary Deployments[](#canary-deployments "Permalink") + +一种流行的 CI 策略,其中将一小部分车队更新为应用程序的新版本. + +[Read more about Canary Deployments.](canary_deployments.html) + +## Further reading[](#further-reading "Permalink") + +* [GitLab Autodeploy](../../topics/autodevops/stages.html#auto-deploy) +* [GitLab CI/CD environment variables](../../ci/variables/README.html) +* [Environments and deployments](../../ci/environments/index.html) +* [Kubernetes deploy example](https://gitlab.com/gitlab-examples/kubernetes-deploy) \ No newline at end of file diff --git a/_book/docs/025.md b/_book/docs/025.md new file mode 100644 index 0000000000000000000000000000000000000000..ba3543f75b3deba1b090b905b7b9ef53348754cb --- /dev/null +++ b/_book/docs/025.md @@ -0,0 +1,1220 @@ +# GitLab Managed Apps + +> 原文:[https://docs.gitlab.com/ee/user/clusters/applications.html](https://docs.gitlab.com/ee/user/clusters/applications.html) + +* [Installing applications](#installing-applications) + * [Helm](#helm) + * [Enable or disable local Tiller](#enable-or-disable-local-tiller-core-only) + * [cert-manager](#cert-manager) + * [GitLab Runner](#gitlab-runner) + * [Ingress](#ingress) + * [Determining the external endpoint automatically](#determining-the-external-endpoint-automatically) + * [Determining the external endpoint manually](#determining-the-external-endpoint-manually) + * [Using a static IP](#using-a-static-ip) + * [Pointing your DNS at the external endpoint](#pointing-your-dns-at-the-external-endpoint) + * [Web Application Firewall (ModSecurity)](#web-application-firewall-modsecurity) + * [Logging and blocking modes](#logging-and-blocking-modes) + * [WAF version updates](#waf-version-updates) + * [Viewing Web Application Firewall traffic](#viewing-web-application-firewall-traffic) + * [JupyterHub](#jupyterhub) + * [Jupyter Git Integration](#jupyter-git-integration) + * [Knative](#knative) + * [Prometheus](#prometheus) + * [Crossplane](#crossplane) + * [Elastic Stack](#elastic-stack) + * [Optional: deploy Kibana to perform advanced queries](#optional-deploy-kibana-to-perform-advanced-queries) + * [Fluentd](#fluentd) + * [Future apps](#future-apps) +* [Install using GitLab CI/CD (alpha)](#install-using-gitlab-cicd-alpha) + * [Usage](#usage) + * [Important notes](#important-notes) + * [Install Ingress using GitLab CI/CD](#install-ingress-using-gitlab-cicd) + * [Install cert-manager using GitLab CI/CD](#install-cert-manager-using-gitlab-cicd) + * [Install Sentry using GitLab CI/CD](#install-sentry-using-gitlab-cicd) + * [Install PostHog using GitLab CI/CD](#install-posthog-using-gitlab-cicd) + * [Install Prometheus using GitLab CI/CD](#install-prometheus-using-gitlab-cicd) + * [Install GitLab Runner using GitLab CI/CD](#install-gitlab-runner-using-gitlab-cicd) + * [Install Cilium using GitLab CI/CD](#install-cilium-using-gitlab-cicd) + * [Install Falco using GitLab CI/CD](#install-falco-using-gitlab-cicd) + * [Install Vault using GitLab CI/CD](#install-vault-using-gitlab-cicd) + * [Install JupyterHub using GitLab CI/CD](#install-jupyterhub-using-gitlab-cicd) + * [Install Elastic Stack using GitLab CI/CD](#install-elastic-stack-using-gitlab-cicd) + * [Install Crossplane using GitLab CI/CD](#install-crossplane-using-gitlab-cicd) + * [Install Fluentd using GitLab CI/CD](#install-fluentd-using-gitlab-cicd) + * [Install Knative using GitLab CI/CD](#install-knative-using-gitlab-cicd) + * [Knative Metrics](#knative-metrics) + * [Uninstall Knative](#uninstall-knative) + * [Install AppArmor using GitLab CI/CD](#install-apparmor-using-gitlab-cicd) + * [Using AppArmor profiles in your deployments](#using-apparmor-profiles-in-your-deployments) +* [Upgrading applications](#upgrading-applications) +* [Uninstalling applications](#uninstalling-applications) +* [Troubleshooting applications](#troubleshooting-applications) + * [Error installing managed apps on EKS cluster](#error-installing-managed-apps-on-eks-cluster) + * [Unable to install Prometheus](#unable-to-install-prometheus) + +# GitLab Managed Apps[](#gitlab-managed-apps "Permalink") + +GitLab 提供**GitLab 托管应用程序** ,一键安装各种应用程序,可以直接将其添加到配置的集群中. + +使用[Auto DevOps](../../topics/autodevops/index.html)时, [Review Apps](../../ci/review_apps/index.html)和[部署](../../ci/environments/index.html)需要这些应用程序. + +您可以在[创建集群](../project/clusters/add_remove_clusters.html)后安装它们. + +## Installing applications[](#installing-applications "Permalink") + +由 GitLab `gitlab-managed-apps`将安装到`gitlab-managed-apps`命名空间中. + +该名称空间: + +* 与用于项目部署的名称空间不同. +* 创建一次. +* 具有不可配置的名称. + +查看可用安装的应用程序列表. 为一个: + +* [项目级集群](../project/clusters/index.html) ,导航到项目的 **运营> Kubernetes** . +* [小组级别的集群](../group/clusters/index.html) ,导航到您小组的 **Kubernetes**页面. + +**注意:**从 GitLab 11.6 开始,Helm 将在安装任何应用程序之前升级到 GitLab 支持的最新版本. + +可以安装以下应用程序: + +* [Helm](#helm) +* [Ingress](#ingress) +* [cert-manager](#cert-manager) +* [Prometheus](#prometheus) +* [GitLab Runner](#gitlab-runner) +* [JupyterHub](#jupyterhub) +* [Knative](#knative) +* [Crossplane](#crossplane) +* [Elastic Stack](#elastic-stack) +* [Fluentd](#fluentd) + +除 Knative 外,这些应用程序将安装在名为`gitlab-managed-apps`的专用命名空间中. + +**注意:**某些应用程序仅可用于项目级集群安装. 计划在将来的发行版中支持在组级群集中安装这些应用程序. 有关更新,请参阅[问题跟踪进度](https://gitlab.com/gitlab-org/gitlab/-/issues/24411) .**注意:**如果您现有的 Kubernetes 集群已安装 Helm,则应谨慎使用,因为 GitLab 无法检测到它. 在这种情况下,通过应用程序安装 Helm 将导致集群对其进行两次配置,这可能导致部署期间的混乱. + +### Helm[](#helm "Permalink") + +版本历史 + +* 在 GitLab 10.2 中针对项目级集群引入. +* 在 GitLab 11.6 中针对组级集群引入. +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/209736)了本地 Tiller 选项,该选项在功能标记后(默认情况下启用). +* 在 GitLab.com 上启用了本地 Tiller 的功能标志. + +[Helm](https://helm.sh/docs/)是 Kubernetes 的软件包管理器,用于安装 GitLab 管理的应用程序. GitLab 在集群内`gitlab-managed-apps`命名空间内的 pod 中运行每个`helm`命令. + +从 GitLab 13.2 开始,集成默认使用本地[Tiller](https://v2.helm.sh/docs/glossary/#tiller) . 使用本地 Tiller 时,不需要安装 Helm 应用程序,也不会显示在应用程序列表中. + +**注意:** GitLab 的 Helm 集成不支持在代理后面安装应用程序,但是可以使用一种[解决方法](../../topics/autodevops/index.html#install-applications-behind-a-proxy) . + +### Enable or disable local Tiller[](#enable-or-disable-local-tiller-core-only "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/209736) +* [计划](https://gitlab.com/gitlab-org/gitlab/-/issues/209736)在 GitLab 13.3 中[删除](https://gitlab.com/gitlab-org/gitlab/-/issues/209736)禁用本地 Tiller 的选项 + +本地分 iller 正在开发中,但已准备好用于生产. 它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../administration/feature_flags.html)可以为您的实例启用它. + +要启用它: + +``` +# Instance-wide +Feature.enable(:managed_apps_local_tiller) +``` + +禁用它: + +``` +# Instance-wide +Feature.disable(:managed_apps_local_tiller) +``` + +### cert-manager[](#cert-manager "Permalink") + +在 GitLab 11.6 中针对项目级和组级集群引入. + +[cert-manager](https://cert-manager.io/docs/)是本地 Kubernetes 证书管理控制器,可帮助颁发证书. 在群集上安装 cert-manager 将通过[Let's Encrypt](https://letsencrypt.org/)颁发证书,并确保证书有效和最新. + +用于安装此应用程序的图表取决于所使用的 GitLab 版本. 在: + +* 在 GitLab 12.3 及更高版本中, [jetstack / cert-manager](https://github.com/jetstack/cert-manager)图表与[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/cert_manager/values.yaml)文件一起使用. +* 在 GitLab 12.2 和更早版本中,使用了[稳定/证书管理器](https://github.com/helm/charts/tree/master/stable/cert-manager)图表. + +如果您在 GitLab 12.3 之前安装了 cert-manager,那么我们加密将[阻止来自较早版本 cert-manager 的请求](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) . + +要解决此问题: + +1. 卸载 cert-manager(考虑[备份任何其他配置](https://cert-manager.io/docs/tutorials/backup/) ). +2. 再次安装 cert-manager. + +### GitLab Runner[](#gitlab-runner "Permalink") + +版本历史 + +* 在 GitLab 10.6 中针对项目级集群引入. +* 在 GitLab 11.10 中针对组级集群引入. + +[GitLab Runner](https://docs.gitlab.com/runner/)是一个开源项目,用于运行您的作业并将结果发送回 GitLab. 它与[GitLab CI / CD](../../ci/README.html)结合使用, [GitLab CI / CD](../../ci/README.html)是 GitLab 随附的用于协调作业的开源持续集成服务. + +如果该项目在 GitLab.com 上,则可以使用共享的 Runners(前 2000 分钟是免费的,以后您可以[购买更多](../../subscriptions/index.html#purchasing-additional-ci-minutes) ),并且如果它们足以满足您的需求,则不必部署它. 如果需要特定于项目的运行器,或者没有共享的运行器,则部署它很容易. + +请注意,已部署的 Runner 将设置为**privileged** ,这意味着它实际上将具有对基础计算机的 root 访问权限. 这是构建 Docker 映像所必需的,因此它是默认设置. 在部署前,请确保已阅读[安全隐患](../project/clusters/index.html#security-implications) . + +**注意:** [`runner/gitlab-runner`](https://gitlab.com/gitlab-org/charts/gitlab-runner)图表用于使用[预先配置的`values.yaml`](https://gitlab.com/gitlab-org/charts/gitlab-runner/-/blob/master/values.yaml)文件安装此应用程序. 不支持通过修改此文件来自定义安装. + +### Ingress[](#ingress "Permalink") + +版本历史 + +* 在 GitLab 10.2 中针对项目级集群引入. +* 在 GitLab 11.6 中针对组级集群引入. + +[Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)提供开箱即用的负载平衡,SSL 终止和基于名称的虚拟主机. 它充当应用程序的 Web 代理,如果要使用[Auto DevOps](../../topics/autodevops/index.html)或部署自己的 Web 应用程序,则很有用. + +安装的 Ingress Controller 是[Ingress-NGINX](https://kubernetes.io/docs/concepts/services-networking/ingress/) ,由 Kubernetes 社区支持. + +**注意:**通过以下过程,必须在群集中安装负载均衡器才能获取端点. 如果使用 Knative,则可以使用 Ingress 或 Knative 自己的负载平衡器( [Istio](https://istio.io) ). + +In order to publish your web application, you first need to find the endpoint which will be either an IP address or a hostname associated with your load balancer. + +要安装它,请点击 Ingress 的**安装**按钮. GitLab 将尝试确定外部端点,并且它应在几分钟之内可用. + +#### Determining the external endpoint automatically[](#determining-the-external-endpoint-automatically "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17052) . + +安装 Ingress 之后,外部端点应在几分钟之内可用. + +**提示:**可以使用`KUBE_INGRESS_BASE_DOMAIN`环境变量将此端点用于[Auto DevOps 基础域](../../topics/autodevops/index.html#auto-devops-base-domain) . + +如果没有出现端点,并且您的集群在 Google Kubernetes Engine 上运行: + +1. [在 Google Kubernetes Engine 上](https://console.cloud.google.com/kubernetes)检查您的[Kubernetes 集群,](https://console.cloud.google.com/kubernetes)以确保其节点上没有错误. +2. 确保您在 Google Kubernetes Engine 上有足够的[配额](https://console.cloud.google.com/iam-admin/quotas) . 有关更多信息,请参见[资源配额](https://cloud.google.com/compute/quotas) . +3. 检查[Google Cloud 的状态,](https://status.cloud.google.com/)以确保它们没有任何中断. + +安装后,您可能会看到一个`?` 取决于云提供商的"入口 IP 地址". 特别是对于 EKS,这是因为 ELB 是使用 DNS 名称而不是 IP 地址创建的. 如果 GitLab 仍然无法确定您的 Ingress 或 Knative 应用程序的端点,则可以[手动确定它](#determining-the-external-endpoint-manually) . + +**注意:** [`stable/nginx-ingress`](https://github.com/helm/charts/tree/master/stable/nginx-ingress)图表用于通过[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/ingress/values.yaml)文件安装此应用程序. + +#### Determining the external endpoint manually[](#determining-the-external-endpoint-manually "Permalink") + +如果群集位于 GKE 上,请单击" **高级设置"中**的**Google Kubernetes Engine**链接,或直接转到[Google Kubernetes Engine 仪表板,](https://console.cloud.google.com/kubernetes/)然后选择适当的项目和群集. 然后单击" **连接"** ,然后在本地终端或使用**Cloud Shell**执行`gcloud`命令. + +如果集群不在 GKE 上,请按照 Kubernetes 提供程序的特定说明使用正确的凭据配置`kubectl` . 以下示例的输出将显示集群的外部端点. 然后,可以使用此信息来设置 DNS 条目和转发规则,以允许外部访问已部署的应用程序. + +If you installed Ingress via the **Applications**, run the following command: + +``` +kubectl get service --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}' +``` + +有些 Kubernetes 集群会返回主机名,例如[Amazon EKS](https://aws.amazon.com/eks/) . 对于这些平台,运行: + +``` +kubectl get service --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' +``` + +对于 Istio / Knative,命令将有所不同: + +``` +kubectl get svc --namespace=istio-system istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} ' +``` + +否则,您可以列出所有负载均衡器的 IP 地址: + +``` +kubectl get svc --all-namespaces -o jsonpath='{range.items[?(@.status.loadBalancer.ingress)]}{.status.loadBalancer.ingress[*].ip} ' +``` + +**注意:**如果使用 EKS,还将创建一个[Elastic Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/) ,这将产生额外的 AWS 成本.**注意:**在某些 Kubernetes 版本上,您可能会看到尾随`%` , **但不要包括它** . + +入口现在在此地址可用,并将基于请求中的 DNS 名称将传入请求路由到适当的服务. 为此,应为所需的域名创建通配符 DNS CNAME 记录. 例如, `*.myekscluster.com`将指向之前获得的 Ingress 主机名. + +#### Using a static IP[](#using-a-static-ip "Permalink") + +默认情况下,临时外部 IP 地址与群集的负载平衡器关联. 如果您将临时 IP 与 DNS 关联,并且 IP 更改,则将无法访问您的应用程序,因此您必须再次更改 DNS 记录. 为了避免这种情况,您应该将其更改为静态保留的 IP. + +阅读如何[在 GKE 中提升临时外部 IP 地址](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address#promote_ephemeral_ip) . + +#### Pointing your DNS at the external endpoint[](#pointing-your-dns-at-the-external-endpoint "Permalink") + +设置外部终结点后,应将其与[通配符 DNS 记录(](https://en.wikipedia.org/wiki/Wildcard_DNS_record)例如`*.example.com.`相关联`*.example.com.` 为了能够访问您的应用. 如果您的外部端点是 IP 地址,请使用 A 记录. 如果您的外部端点是主机名,请使用 CNAME 记录. + +#### Web Application Firewall (ModSecurity)[](#web-application-firewall-modsecurity "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21966) . + +Web 应用程序防火墙(WAF)可以检查正在发送或接收的流量,并可以在恶意流量到达您的应用程序之前对其进行阻止. WAF 的好处是: + +* 实时监控您的应用程序 +* 将所有 HTTP 通信记录到应用程序 +* 您的应用程序的访问控制 +* 高度可配置的日志记录和阻止规则 + +开箱即用,GitLab 为您提供了一个称为[`ModSecurity`](https://www.modsecurity.org/)的 WAF. + +ModSecurity 是用于实时 Web 应用程序监视,日志记录和访问控制的工具包. 借助 GitLab 的产品,将自动应用[OWASP 的 Core Rule Set](https://www.modsecurity.org/CRS/Documentation/) (提供通用的攻击检测功能). + +此功能: + +* 除非另有配置,否则以"仅检测模式"运行. +* 通过检查您的 Ingress 控制器的`modsec`日志中是否有违反规则可以查看. 例如: + + ``` + kubectl logs -n gitlab-managed-apps $(kubectl get pod -n gitlab-managed-apps -l app=nginx-ingress,component=controller --no-headers=true -o custom-columns=:metadata.name) modsecurity-log -f + ``` + +要启用 WAF,请在安装或更新[Ingress 应用程序](#ingress)时将其相应的切换开关切换到启用位置. + +如果这是您首次使用 GitLab 的 WAF,我们建议您遵循[快速入门指南](../../topics/web_application_firewall/quick_start_guide.html) . + +通过启用 ModSecurity,性能开销很小. 如果这对于您的应用程序而言很重要,则可以通过以下任何一种方式为已部署的应用程序禁用 ModSecurity 的规则引擎: + +1. Setting [the deployment variable](../../topics/autodevops/index.html) `AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE` to `Off`. This will prevent ModSecurity from processing any requests for the given application or environment. + +2. 将其各自的切换开关切换到禁用位置,然后通过" **保存更改"**按钮应用更改. 这将使用最新更改重新安装 Ingress. + +[![Disabling WAF](img/74f87e79779a102e82a644227e50a2e4.png)](../../topics/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png) + +##### Logging and blocking modes[](#logging-and-blocking-modes "Permalink") + +为了帮助您调整 WAF 规则,可以将 WAF 全局设置为" **日志记录"**或" **阻止"**模式: + +* **日志记录模式** -允许符合规则的流量通过并记录事件. +* **阻止模式** -阻止符合规则的流量通过,并记录事件. + +更改 WAF 的模式: + +1. 如果尚未[安装 ModSecurity](../../topics/web_application_firewall/quick_start_guide.html) ,请[安装它](../../topics/web_application_firewall/quick_start_guide.html) . +2. 导航 **运营>州长** . +3. In **Applications**, scroll to **Ingress**. +4. 在" **全局默认值"下** ,选择所需的模式. +5. Click **保存更改**. + +##### WAF version updates[](#waf-version-updates "Permalink") + +由于[Helm 的](https://helm.sh/)限制,在以后的发行版中可能会克服这些问题,因此仅在同一版本的[Ingress 中](#ingress)才允许启用,禁用或更改**ModSecurity**的日志记录模式. + +如果所部署的版本与 GitLab 中可用的版本不同,则将禁用**ModSecurity** UI 控件,而仍可以执行[Ingress](#ingress)级别的操作,例如卸载: + +[![WAF settings disabled](img/27858125d0f3461e373b06413f40e616.png)](../../topics/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png) + +将[Ingress](#ingress)更新到最新版本使您能够利用错误修复,安全修复和性能改进. 要更新[Ingress 应用程序](#ingress) ,您必须首先将其卸载,然后按照[Install ModSecurity 中的说明](../../topics/web_application_firewall/quick_start_guide.html)进行重新[安装](../../topics/web_application_firewall/quick_start_guide.html) . + +##### Viewing Web Application Firewall traffic[](#viewing-web-application-firewall-traffic "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14707) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9. + +您可以通过导航到项目的" **安全性和合规性">"威胁监视"**页面来查看 Web 应用程序防火墙的流量. + +从那里,您可以看到随着时间的推移进行跟踪: + +* 您的应用程序的总流量. +* Web 应用程序防火墙的默认[OWASP 规则集](https://www.modsecurity.org/CRS/Documentation/)认为异常的流量比例. + +如果很大一部分流量是异常的,则应[检查](#web-application-firewall-modsecurity)潜在的威胁,这可以通过[检查 Web 应用程序防火墙日志](#web-application-firewall-modsecurity)来完成. + +[![Threat Monitoring](img/a3964b6d91003c90a72b5ca689b9e0c5.png)](img/threat_monitoring_v12_9.png) + +### JupyterHub[](#jupyterhub "Permalink") + +版本历史 + +* 在 GitLab 11.0 中针对项目级集群引入. +* 在 GitLab 12.3 中针对组和实例级集群引入. + +[JupyterHub](https://jupyterhub.readthedocs.io/en/stable/)是用于在团队中管理笔记本的多用户服务. [Jupyter Notebook](https://jupyter-notebook.readthedocs.io/en/latest/)提供了一个基于 Web 的交互式编程环境,用于数据分析,可视化和机器学习. + +Authentication will be enabled only for [project members](../project/members/index.html) for project-level clusters and group members for group-level clusters with [Developer or higher](../permissions.html) access to the associated project or group. + +我们使用一个[自定义的 Jupyter 映像](https://gitlab.com/gitlab-org/jupyterhub-user-image/blob/master/Dockerfile) ,该[映像](https://gitlab.com/gitlab-org/jupyterhub-user-image/blob/master/Dockerfile)将在基础 Jupyter 之上安装其他有用的软件包. 您还将看到使用 Nurtch 的[Rubix 库](https://github.com/Nurtch/rubix)构建的即用型 DevOps Runbook. + +有关创建可执行运行本的更多信息,请参见[我们的运行本文档](../project/clusters/runbooks/index.html#configure-an-executable-runbook-with-gitlab) . 请注意,必须先安装 Ingress 并分配 IP 地址,然后才能安装 JupyterHub. + +**注意:** [`jupyter/jupyterhub`](https://jupyterhub.github.io/helm-chart/)图表用于通过[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/jupyter/values.yaml)文件安装此应用程序. + +#### Jupyter Git Integration[](#jupyter-git-integration "Permalink") + +版本历史 + +* 在 GitLab 12.0 中针对项目级集群[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28783) . +* 在 GitLab 12.3 中针对组和实例级集群[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/32512) . + +将 JupyterHub 安装到 Kubernetes 集群上时,将使用已验证用户的身份自动配置和配置[JupyterLab 的 Git 扩展](https://github.com/jupyterlab/jupyterlab-git) : + +* Name. +* Email. +* 新创建的访问令牌. + +JupyterLab 的 Git 扩展使您能够对笔记本进行完整版本控制,并在 Jupyter 中发布 Git 命令. Git 命令可以通过左侧面板上的**Git**选项卡或 Jupyter 的命令行提示符发出. + +**注意:** JupyterLab 的 Git 扩展将用户令牌以加密格式存储在 JupyterHub DB 中,并以纯文本形式存储在单个用户 Jupyter 实例中. 这是因为[Git 要求将凭据存储为纯文本](https://git-scm.com/docs/git-credential-store) . 潜在地,如果一个邪恶的用户在单用户 Jupyter 实例中找到一种从文件系统读取的方法,则他们可以检索令牌. + +[![Jupyter's Git Extension](img/993315f2d7b2aa15b2f3faa03d14705c.png)](img/jupyter-git-extension.gif) + +您可以从 Jupyter 的"文件"选项卡中克隆存储库: + +[![Jupyter clone repository](img/bed33522d3ca08c8f5c920ba11fa05d4.png)](img/jupyter-gitclone.png) + +### Knative[](#knative "Permalink") + +版本历史 + +* 在 GitLab 11.5 中针对项目级集群引入. +* 在 GitLab 12.3 中针对组和实例级集群引入. + +[Knative](https://cloud.google.com/knative/)提供了一个平台,用于从 Kubernetes 集群创建,部署和管理无服务器工作负载. 它与[Istio](https://istio.io)结合使用并包括在内, [以为 Knative](https://istio.io)托管的所有程序提供外部 IP 地址. + +系统将提示您输入一个通配符域,您的应用程序将在该域中公开. 配置您的 DNS 服务器以使用该域的外部 IP 地址. 对于创建和安装的任何应用程序,可以通过`..` . 这将要求您的 Kubernetes 群集[启用 RBAC](../project/clusters/add_remove_clusters.html#rbac-cluster-resources) . + +**Note:** The [`knative/knative`](https://storage.googleapis.com/triggermesh-charts) chart is used to install this application. + +### Prometheus[](#prometheus "Permalink") + +版本历史 + +* 在 GitLab 10.4 中针对项目级集群引入. +* 在 GitLab 11.11 中针对组级集群引入. + +[Prometheus](https://s0prometheus0io.icopy.site/docs/introduction/overview/)是一个开源监视和警报系统,可用于监督已部署的应用程序. + +GitLab 能够使用[Prometheus 集成](../project/integrations/prometheus.html)自动监视应用程序. Kubernetes 容器的 CPU 和内存指标将自动收集,响应指标也将从 NGINX Ingress 检索. + +要启用监视,只需使用" **安装"**按钮将 Prometheus 安装到群集中. + +**注意:** [`stable/prometheus`](https://github.com/helm/charts/tree/master/stable/prometheus)图表用于通过[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/prometheus/values.yaml)文件安装此应用程序. + +### Crossplane[](#crossplane "Permalink") + +版本历史 + +* 在 GitLab 12.5 中针对项目级集群[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34702) . + +[Crossplane](https://crossplane.github.io/docs/v0.9/)是一种多云控制平面,可用于跨多个云管理应用程序和基础架构. 它使用以下方法扩展了 Kubernetes API: + +* 自定义资源. +* 监视那些自定义资源的控制器. + +Crossplane 通过抽象特定于云提供商的配置,以统一的方式允许跨云提供商进行基础架构组件的供应和生命周期管理. + +Crossplane GitLab 管理的应用程序: + +* 在连接到项目存储库的 Kubernetes 集群上使用选择的提供程序安装 Crossplane. +* 然后可以用于通过 Auto DevOps 管道来配置基础结构或托管应用程序,例如 PostgreSQL(例如,来自 GCP 的 CloudSQL 或来自 AWS 的 RDS)以及该应用程序所需的其他服务. + +有关配置群集上安装的 Crossplane 的信息,请参阅[Crossplane 配置](crossplane.html) . + +**注意:** [`alpha/crossplane`](https://github.com/crossplane/crossplane/tree/v0.4.1/cluster/charts/crossplane) crossplane 图表 v0.4.1 用于通过[`values.yaml`](https://github.com/crossplane/crossplane/blob/master/cluster/charts/crossplane/values.yaml.tmpl)文件安装 Crossplane. + +### Elastic Stack[](#elastic-stack "Permalink") + +在 GitLab 12.7 中针对项目级和组级集群引入. + +[Elastic Stack](https://www.elastic.co/elastic-stack)是一个完整的端到端日志分析解决方案,可帮助深入搜索,分析和可视化从不同计算机生成的日志. + +GitLab 能够自动从集群中的 Pod 收集日志. Filebeat 将在集群中的每个节点上作为 DaemonSet 运行,并将容器日志发送到 Elasticsearch 进行查询. 然后,GitLab 将连接到 Elasticsearch 以获取日志而不是 Kubernetes API,您将可以使用更高级的查询功能. + +使用[Curator](https://www.elastic.co/guide/en/elasticsearch/client/curator/5.5/about.html)在 30 天后会自动删除日志数据. + +要启用日志传送: + +1. 确保您的集群至少包含 3 个实例类型大于`f1-micro` , `g1-small`或`n1-standard-1`节点. +2. 导航 **运营>州长** . +3. 在**Kubernetes Cluster 中** ,选择一个集群. +4. 在" **应用程序"**部分中,找到" **Elastic Stack"** ,然后单击" **安装"** . + +**注意:** [`gitlab/elastic-stack`](https://gitlab.com/gitlab-org/charts/elastic-stack)图用于通过[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/elastic_stack/values.yaml)文件安装此应用程序.**注意:**该图表部署了 3 个相同的 Elasticsearch Pod,这些 Pod 无法共置,每个 Pod 需要 1 个 CPU 和 2 GB RAM,从而使其与包含少于 3 个节点或由`f1-micro` , `g1-small` , `n1-standard-1`组成的集群不兼容`n1-standard-1`或`*-highcpu-2`实例类型.**注意:** Elastic Stack 群集应用程序旨在用作日志聚合解决方案,并且与我们的[Advanced Global Search](../search/advanced_global_search.html)功能无关,后者使用单独的 Elasticsearch 群集. + +#### Optional: deploy Kibana to perform advanced queries[](#optional-deploy-kibana-to-perform-advanced-queries "Permalink") + +如果您是高级用户,并且可以使用`kubectl`和`helm`直接访问 Kubernetes 集群,则可以手动部署 Kibana. + +下面假设`helm`已经[初始化](https://v2.helm.sh/docs/helm/)与`helm init` . + +将以下内容保存到`kibana.yml` : + +``` +elasticsearch: + enabled: false + +filebeat: + enabled: false + +kibana: + enabled: true + elasticsearchHosts: http://elastic-stack-elasticsearch-master.gitlab-managed-apps.svc.cluster.local:9200 +``` + +然后将其安装在您的集群上: + +``` +helm repo add gitlab https://charts.gitlab.io +helm install --name kibana gitlab/elastic-stack --values kibana.yml +``` + +要访问 Kibana,请将端口转发到本地计算机: + +``` +kubectl port-forward svc/kibana-kibana 5601:5601 +``` + +然后,您可以通过`http://localhost:5601`访问 Kibana. + +### Fluentd[](#fluentd "Permalink") + +在 GitLab 12.10 中针对项目级和组级集群引入. + +[Fluentd](https://www.fluentd.org/)是一个开源数据收集器,它使您能够统一数据收集和使用以更好地使用和理解数据. Fluentd 以 syslog 格式发送日志. + +To enable Fluentd: + +1. 导航 **操作> Kubernetes** ,然后单击**应用程序** . 系统将提示您输入主机,端口和协议,WAF 日志将通过 syslog 发送到该主机,端口和协议. +2. 在**SIEM Hostname 中**提供主机域名或 URL. +3. 在**SIEM Port 中**提供主机端口号. +4. 选择一个**SIEM 协议** . +5. 选择至少一个可用日志(例如 WAF 或 Cilium). +6. Click **保存更改**. + +[![Fluentd input fields](img/f52fe1b4788045a510a1783bfb546b6f.png)](img/fluentd_v13_0.png) + +### Future apps[](#future-apps "Permalink") + +有兴趣贡献一个新的 GitLab 托管应用程序吗? 访问[开发指南页面](../../development/kubernetes.html#gitlab-managed-apps)以开始使用. + +## Install using GitLab CI/CD (alpha)[](#install-using-gitlab-cicd-alpha "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20822) in GitLab 12.6. + +**警告:**这是*Alpha 版*功能,如有更改,恕不另行通知. + +这种替代方法允许用户使用 GitLab CI / CD 安装由 GitLab 管理的应用程序. 它还允许使用 Helm `values.yaml`文件来自定义安装. + +支持的应用程序: + +* [Ingress](#install-ingress-using-gitlab-cicd) +* [cert-manager](#install-cert-manager-using-gitlab-cicd) +* [Sentry](#install-sentry-using-gitlab-cicd) +* [GitLab Runner](#install-gitlab-runner-using-gitlab-cicd) +* [Cilium](#install-cilium-using-gitlab-cicd) +* [Falco](#install-falco-using-gitlab-cicd) +* [Vault](#install-vault-using-gitlab-cicd) +* [JupyterHub](#install-jupyterhub-using-gitlab-cicd) +* [Elastic Stack](#install-elastic-stack-using-gitlab-cicd) +* [Crossplane](#install-crossplane-using-gitlab-cicd) +* [Fluentd](#install-fluentd-using-gitlab-cicd) +* [Knative](#install-knative-using-gitlab-cicd) +* [PostHog](#install-posthog-using-gitlab-cicd) +* [Prometheus](#install-prometheus-using-gitlab-cicd) + +### Usage[](#usage "Permalink") + +您可以在[示例集群应用程序项目中](https://gitlab.com/gitlab-org/cluster-integration/example-cluster-applications/)找到并导入下面引用的所有文件. + +要使用 GitLab CI / CD 安装应用程序: + +1. 将集群连接到[集群管理项目](management_project.html) . +2. 在该项目中,添加具有以下内容的`.gitlab-ci.yml`文件: + + ``` + include: + - template: Managed-Cluster-Applications.gitlab-ci.yml + ``` + + **注意:**此模板提供的作业使用自定义 Docker 映像中提供的工具连接到集群. 它要求您具有在 Docker,Kubernetes 或 Docker Machine 执行器上注册的运行程序. +3. 添加`.gitlab/managed-apps/config.yaml`文件,以定义要安装的应用程序. 将已`installed`密钥定义为`true`以安装应用程序,将`false`为卸载应用程序. 例如,要安装 Ingress: + + ``` + ingress: + installed: true + ``` + +4. (可选)定义`.gitlab/managed-apps//values.yaml`文件,以自定义已安装应用程序的值. + +然后,一个 GitLab CI / CD 管道将在`master`分支上运行,以安装您配置的应用程序. 万一管道发生故障, [Helm Tiller](https://v2.helm.sh/docs/install/#running-tiller-locally)二进制文件的输出将另存为[CI 作业工件](../../ci/pipelines/job_artifacts.html) . + +### Important notes[](#important-notes "Permalink") + +请注意以下几点: + +* 我们建议仅使用集群管理项目来管理集群的部署. 不要将应用程序的源代码添加到此类项目中. +* 当您将`installed`密钥的值`installed`回`false` ,将从群集中取消配置该应用程序. +* 如果使用新值更新`.gitlab/managed-apps//values.yaml` ,则将重新部署该应用程序. + +### Install Ingress using GitLab CI/CD[](#install-ingress-using-gitlab-cicd "Permalink") + +要安装 Ingress,请使用以下命令定义`.gitlab/managed-apps/config.yaml`文件: + +``` +ingress: + installed: true +``` + +然后,Ingress 将安装到集群的`gitlab-managed-apps`命名空间中. + +You can customize the installation of Ingress by defining a `.gitlab/managed-apps/ingress/values.yaml` file in your cluster management project. Refer to the [chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress) for the available configuration options. + +**注意:** GitLab 配置组提供了对安装 Ingress 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并从[Configure 组中](https://about.gitlab.com/handbook/product/categories/#configure-group) ping 通至少 2 个人. + +### Install cert-manager using GitLab CI/CD[](#install-cert-manager-using-gitlab-cicd "Permalink") + +通过在`.gitlab/managed-apps/config.yaml`定义配置,使用 GitLab CI / CD 安装了 cert-manager. + +cert-manager: + +* 已安装到集群的`gitlab-managed-apps`命名空间中. +* Can be installed with or without a default [Let’s Encrypt `ClusterIssuer`](https://cert-manager.io/docs/configuration/acme/), which requires an email address to be specified. The email address is used by Let’s Encrypt to contact you about expiring certificates and issues related to your account. + +使用 GitLab CI / CD 安装证书管理器需要以下配置: + +``` +certManager: + installed: true + letsEncryptClusterIssuer: + installed: true + email: "user@example.com" +``` + +以下使用 GitLab CI / CD 安装 cert-manager,而没有默认的`ClusterIssuer` : + +``` +certManager: + installed: true + letsEncryptClusterIssuer: + installed: false +``` + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/cert-manager/values.yaml`文件来自定义 cert-manager 的安装. 请参阅[图表](https://hub.helm.sh/charts/jetstack/cert-manager)以获取可用的配置选项. + +**注意:** GitLab 配置组提供了对安装 Cert Manager 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并从[Configure 组中](https://about.gitlab.com/handbook/product/categories/#configure-group) ping 通至少 2 个人. + +### Install Sentry using GitLab CI/CD[](#install-sentry-using-gitlab-cicd "Permalink") + +**注意:** Sentry Helm 图表[建议](https://github.com/helm/charts/blob/f6e5784f265dd459c5a77430185d0302ed372665/stable/sentry/values.yaml#L284-L285)至少 3GB 的可用 RAM 用于数据库迁移. + +To install Sentry, define the `.gitlab/managed-apps/config.yaml` file with: + +``` +sentry: + installed: true +``` + +然后,将 Sentry 安装到集群的`gitlab-managed-apps`命名空间中. + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/sentry/values.yaml`文件来自定义 Sentry 的安装. 请参阅[图表](https://github.com/helm/charts/tree/master/stable/sentry)以获取可用的配置选项. + +我们建议您密切注意以下配置选项: + +* `email` . 需要邀请用户加入您的 Sentry 实例并发送错误电子邮件. +* `user` . 您可以在其中设置默认管理员用户的登录凭据. +* `postgresql` . 有关在将来运行更新时可以使用的 PostgreSQL 密码. + +**注意:**升级时,重要的是提供现有的 PostgreSQL 密码(使用`postgresql.postgresqlPassword`密钥提供),否则您将收到认证错误. 有关更多信息,请参见[PostgreSQL 图表文档](https://github.com/helm/charts/tree/master/stable/postgresql#upgrade) . + +这是 Sentry 的示例配置: + +``` +# Admin user to create +user: + # Indicated to create the admin user or not, + # Default is true as the initial installation. + create: true + email: "" + password: "" + +email: + from_address: "" + host: smtp + port: 25 + use_tls: false + user: "" + password: "" + enable_replies: false + +ingress: + enabled: true + hostname: "" + +# Needs to be here between runs. +# See https://github.com/helm/charts/tree/master/stable/postgresql#upgrade for more info +postgresql: + postgresqlPassword: example-postgresql-password +``` + +**注意:** GitLab Health 组为安装 Sentry 托管应用程序提供支持. 如果您遇到未知问题,请[打开一个新的问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并从[健康小组](https://about.gitlab.com/handbook/product/product-categories/#health-group) ping 至少 2 个人. + +### Install PostHog using GitLab CI/CD[](#install-posthog-using-gitlab-cicd "Permalink") + +[PostHog](https://www.posthog.com)是开发人员友好的开源产品分析平台. + +要将 PostHog 安装到群集的`gitlab-managed-apps`命名空间中,请使用以下`.gitlab/managed-apps/config.yaml`定义`.gitlab/managed-apps/config.yaml`文件: + +``` +posthog: + installed: true +``` + +您可以通过在群集管理项目中定义`.gitlab/managed-apps/posthog/values.yaml`来自定义`.gitlab/managed-apps/posthog/values.yaml`的安装. 有关可用的配置选项,请参阅[PostHog 图表的自述文件](https://github.com/PostHog/charts/tree/master/charts/posthog)的" [配置"部分](https://github.com/PostHog/charts/tree/master/charts/posthog) . + +**注意:**您必须在`postgresql.postgresqlPassword`提供 PostgreSQL 密码,否则将收到身份验证错误. 有关更多信息,请参见[PostgreSQL 图表文档](https://github.com/helm/charts/tree/master/stable/postgresql#upgrade) . + +Redis Pod 在升级之间重新启动. 为防止停机,请使用`redis.password`键提供 Redis 密码. 这样可以防止在每次重新启动时生成新密码. + +这是 PostHog 的示例配置: + +``` +ingress: + enabled: true + hostname: "" + +# This will be autogenerated if you skip it. Include if you have 2 or more web replicas +posthogSecret: 'long-secret-key-used-to-sign-cookies' + +# Needs to be here between runs. +# See https://github.com/helm/charts/tree/master/stable/postgresql#upgrade for more info +postgresql: + postgresqlPassword: example-postgresql-password + +# Recommended to set this to a value to redis prevent downtime between upgrades +redis: + password: example-redis-password +``` + +**注意:** PostHog 团队对 PostHog 托管应用程序提供支持. 如果遇到问题,请直接[打开支持凭单](https://github.com/PostHog/posthog/issues/new/choose) . + +### Install Prometheus using GitLab CI/CD[](#install-prometheus-using-gitlab-cicd "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25138) . + +[Prometheus](https://s0prometheus0io.icopy.site/docs/introduction/overview/)是用于监视已部署应用程序的开源监视和警报系统. + +要将 Prometheus 安装到群集的`gitlab-managed-apps`命名空间中,请使用以下`.gitlab/managed-apps/config.yaml`定义`.gitlab/managed-apps/config.yaml`文件: + +``` +prometheus: + installed: true +``` + +您可以通过在群集管理项目中定义`.gitlab/managed-apps/prometheus/values.yaml`来定制 Prometheus 的安装. 有关可用的配置选项,请参阅[Prometheus 图的 README](https://github.com/helm/charts/tree/master/stable/prometheus#configuration)的[Configuration(配置)部分](https://github.com/helm/charts/tree/master/stable/prometheus#configuration) . + +**注意:** GitLab APM 组提供了对安装 Prometheus 托管应用程序的支持. 如果遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping [APM 组中的](https://about.gitlab.com/handbook/product/product-categories/#apm-group)至少 2 个人. + +### Install GitLab Runner using GitLab CI/CD[](#install-gitlab-runner-using-gitlab-cicd "Permalink") + +通过在`.gitlab/managed-apps/config.yaml`定义配置,使用 GitLab CI / CD 安装了 GitLab Runner. + +使用 GitLab CI / CD 安装 GitLab Runner 需要以下配置: + +``` +gitlabRunner: + installed: true +``` + +GitLab Runner 已安装到集群的`gitlab-managed-apps`命名空间中. + +为了使 GitLab Runner 运行, **必须**指定以下内容: + +* `gitlabUrl`用于注册 Runner 的 GitLab 服务器完整 URL(例如, `https://example.gitlab.com` `gitlabUrl` ). +* `runnerRegistrationToken`用于将新的`runnerRegistrationToken`添加到 GitLab 的注册令牌. 这必须[从您的 GitLab 实例中检索](../../ci/runners/README.html) . + +这些值可以使用[CI 变量](../../ci/variables/README.html)指定: + +* `GITLAB_RUNNER_GITLAB_URL`将用于`gitlabUrl` . +* `GITLAB_RUNNER_REGISTRATION_TOKEN`将用于`runnerRegistrationToken` + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/gitlab-runner/values.yaml`文件来自定义 GitLab Runner 的安装. 请参阅[图表](https://gitlab.com/gitlab-org/charts/gitlab-runner)以获取可用的配置选项. + +**注意:** GitLab Runner 组提供了对安装 Runner 管理的应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping [Runner 组中的](https://about.gitlab.com/handbook/product/product-categories/#runner-group)至少 2 个人. + +### Install Cilium using GitLab CI/CD[](#install-cilium-using-gitlab-cicd "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/merge_requests/22) in GitLab 12.8. + +[Cilium](https://cilium.io/)是[Kubernetes](https://cilium.io/)的网络插件,可用于实现对[NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/)资源的支持. 有关更多信息,请参阅[网络策略](../../topics/autodevops/stages.html#network-policy) . + +有关概述,请参见[GitLab 12.8](https://www.youtube.com/watch?v=pgUEdhdhoUI)的[容器网络安全演示](https://www.youtube.com/watch?v=pgUEdhdhoUI) . + +在`.gitlab/managed-apps/config.yaml`文件中启用 Cilium 进行安装: + +``` +# possible values are gke, eks or you can leave it blank +clusterType: gke + +cilium: + installed: true +``` + +`clusterType`变量为相应的群集类型启用建议的 Helm 变量. 默认值为空白. 您可以在官方文档中检查每种群集类型的建议变量: + +* [Google GKE](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-gke/#deploy-cilium) +* [AWS EKS](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-eks/#deploy-cilium) + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/cilium/values.yaml`文件来自定义 Cilium 的 Helm 变量. 有关可用的配置选项,请参阅[Cilium 图表](https://github.com/cilium/cilium/tree/master/install/kubernetes/cilium) . + +**注意:**安装和拆卸纤毛的需要**手动** [重新启动](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-gke/#restart-unmanaged-pods)在所有命名空间所有受影响的吊舱,以确保它们[管理](https://docs.cilium.io/en/stable/troubleshooting/#ensure-pod-is-managed-by-cilium)由正确的网络插件.**注意:**主要升级可能需要其他设置步骤,请查阅官方[升级指南](https://docs.cilium.io/en/stable/install/upgrade/)以获取更多信息. + +默认情况下,Cilium 会在策略部署时丢弃所有不允许的数据包. 但是,在[auditmode](https://docs.cilium.io/en/v1.8/gettingstarted/policy-creation/?highlight=policy-audit#enable-policy-audit-mode)中,Cilium 不会丢弃不允许的数据包. 您可以使用`policy-verdict`日志来观察与策略相关的决策. 您可以通过将以下内容添加到`.gitlab/managed-apps/cilium/values.yaml`来启用审核模式: + +``` +config: + policyAuditMode: true + +agent: + monitor: + eventTypes: ["drop", "policy-verdict"] +``` + +用于流量的 Cilium 监视器日志由`cilium-monitor`边车容器注销. 您可以使用以下命令检查这些日志: + +``` +kubectl -n gitlab-managed-apps logs cilium-XXXX cilium-monitor +``` + +您可以在`.gitlab/managed-apps/cilium/values.yaml`禁用监视器日志: + +``` +agent: + monitor: + enabled: false +``` + +默认情况下,启用了[Hubble](https://github.com/cilium/hubble)监视守护程序,并将其设置为收集每个命名空间流指标. 可在" [威胁监控"](../application_security/threat_monitoring/index.html)仪表板上访问此指标. 您可以通过将以下内容添加到`.gitlab/managed-apps/cilium/values.yaml`来禁用 Hubble: + +``` +global: + hubble: + enabled: false +``` + +您还可以通过`.gitlab/managed-apps/cilium/values.yaml`来为哈勃调整 Helm 值: + +``` +global: + hubble: + enabled: true + metrics: + enabled: + - 'flow:sourceContext=namespace;destinationContext=namespace' +``` + +**注意:** GitLab Container Security 组提供了对安装 Cilium 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping 通至少来自[Container Security 组的](https://about.gitlab.com/handbook/product/product-categories/#container-security-group) 2 个人. + +### Install Falco using GitLab CI/CD[](#install-falco-using-gitlab-cicd "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/merge_requests/91) . + +GitLab 容器主机安全监视使用[Falco](https://falco.org/)作为运行时安全工具,该工具使用 eBPF 侦听 Linux 内核. Falco 实时解析系统调用并针对可配置的规则引擎声明流. 有关更多信息,请参见[Falco 的文档](https://falco.org/docs/) . + +您可以在`.gitlab/managed-apps/config.yaml`文件中启用 Falco: + +``` +falco: + installed: true +``` + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/falco/values.yaml`文件来自定义 Falco 的 Helm 变量. 有关可用的配置选项,请参考[Falco 图表](https://github.com/falcosecurity/charts/tree/master/falco) . + +**警告:**默认情况下,eBPF 支持已启用,Falco 将使用[eBPF 探针](https://falco.org/docs/event-sources/drivers/#using-the-ebpf-probe)将系统调用传递到用户空间. 如果您的群集不支持此功能,则可以通过将以下内容添加到`.gitlab/managed-apps/falco/values.yaml` ,将其配置为使用 Falco 内核模块: + +``` +ebpf: + enabled: false +``` + +在极少数情况下,无法在群集上自动安装探针并且未预编译内核/探针,您可能需要手动准备带有[driverkit](https://github.com/falcosecurity/driverkit#against-a-kubernetes-cluster)的内核模块或 eBPF 探针,并将其安装在每个群集节点上. + +默认情况下,Falco 部署的规则有限. 要添加更多规则,请将以下内容添加到`.gitlab/managed-apps/falco/values.yaml` (您可以从[Cloud Native Security Hub 中](https://securityhub.dev/)获取示例): + +``` +customRules: + file-integrity.yaml: |- + - rule: Detect New File + desc: detect new file created + condition: > + evt.type = chmod or evt.type = fchmod + output: > + File below a known directory opened for writing (user=%user.name + command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2]) + priority: ERROR + tags: [filesystem] + - rule: Detect New Directory + desc: detect new directory created + condition: > + mkdir + output: > + File below a known directory opened for writing (user=%user.name + command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2]) + priority: ERROR + tags: [filesystem] +``` + +默认情况下,Falco 仅将安全事件作为 JSON 对象输出到日志. 要将其设置为输出到[外部 API](https://falco.org/docs/alerts/#https-output-send-alerts-to-an-https-end-point)或[应用程序](https://falco.org/docs/alerts/#program-output) ,请将以下内容添加到`.gitlab/managed-apps/falco/values.yaml` : + +``` +falco: + programOutput: + enabled: true + keepAlive: false + program: mail -s "Falco Notification" someone@example.com + + httpOutput: + enabled: true + url: http://some.url +``` + +您可以使用以下命令检查这些日志: + +``` +kubectl logs -l app=falco -n gitlab-managed-apps +``` + +**注意:** GitLab Container Security 组提供了对安装 Falco 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping 通至少来自[Container Security 组的](https://about.gitlab.com/handbook/product/product-categories/#container-security-group) 2 个人. + +### Install Vault using GitLab CI/CD[](#install-vault-using-gitlab-cicd "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9982) . + +[Hashicorp Vault](https://www.vaultproject.io/)是一个秘密管理解决方案,可用于安全地管理和存储密码,凭据,证书等. 可以利用 Vault 安装为应用程序,GitLab CI / CD 作业等中使用的凭据提供一个安全的数据存储. 它还可以用作向基础结构中的系统和部署提供 SSL / TLS 证书的方式. 通过将 Vault 作为所有这些凭据的单一来源,可以通过对所有敏感凭据和证书具有单一的访问,控制和可审核性来源,从而提高安全性. + +To install Vault, enable it in the `.gitlab/managed-apps/config.yaml` file: + +``` +vault: + installed: true +``` + +默认情况下,您将获得基本的保险柜设置,没有可扩展的存储后端. 这对于简单的测试和小规模部署就足够了,尽管限制了它可以扩展的规模,并且由于它是单实例部署,因此在升级 Vault 应用程序时会遇到停机时间. + +为了在生产环境中最佳地使用 Vault,理想的是充分了解 Vault 的内部结构以及如何配置它. 这可以通过阅读[Vault 文档](https://www.vaultproject.io/docs/internals)以及 Vault Helm 图表[`values.yaml`文件来完成](https://github.com/hashicorp/vault-helm/blob/v0.3.3/values.yaml) . + +至少您可能会设置: + +* 用于对主密钥进行额外加密的[印章](https://www.vaultproject.io/docs/configuration/seal) . +* 适合于环境和存储安全性要求的[存储后端](https://www.vaultproject.io/docs/configuration/storage) . +* [HA Mode](https://www.vaultproject.io/docs/concepts/ha). +* [The Vault UI](https://www.vaultproject.io/docs/configuration/ui). + +以下是一个示例值文件( `.gitlab/managed-apps/vault/values.yaml` ),该文件使用 Google Cloud Storage 后端,启用 Vault UI 并启用具有 3 个 pod 的 HA,将 Google 密钥管理服务配置为自动`.gitlab/managed-apps/vault/values.yaml`副本. 下面的`storage`和`seal`节是示例,应替换为特定于您的环境的设置. + +``` +# Enable the Vault WebUI +ui: + enabled: true +server: + # Disable the built in data storage volume as it's not safe for Hight Availability mode + dataStorage: + enabled: false + # Enable High Availability Mode + ha: + enabled: true + # Configure Vault to listen on port 8200 for normal traffic and port 8201 for inter-cluster traffic + config: | + listener "tcp" { + tls_disable = 1 + address = "[::]:8200" + cluster_address = "[::]:8201" + } + # Configure Vault to store its data in a GCS Bucket backend + storage "gcs" { + path = "gcs://my-vault-storage/vault-bucket" + ha_enabled = "true" + } + # Configure Vault to automatically unseal storage using a GKMS key + seal "gcpckms" { + project = "vault-helm-dev-246514" + region = "global" + key_ring = "vault-helm-unseal-kr" + crypto_key = "vault-helm-unseal-key" + } +``` + +成功安装保险柜后,您将需要[初始化保险柜](https://learn.hashicorp.com/vault/getting-started/deploy#initializing-the-vault)并获取初始根令牌. 为此,您将需要访问已将 Vault 部署到的 Kubernetes 群集. 要初始化 Vault,请在 Kubernetes 内部运行的一个 Vault 容器中安装一个外壳(通常是通过使用`kubectl`命令行工具来完成). 将外壳放入吊舱后,运行`vault operator init`命令: + +``` +kubectl -n gitlab-managed-apps exec -it vault-0 sh +/ $ vault operator init +``` + +这应该为您提供解封密钥和初始根令牌. 确保记下这些内容并保持安全,因为您将需要它们在保险柜的整个生命周期内将其解封. + +**注意:** GitLab 版本管理组提供了对安装 Vault 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并从" [发行管理"组](https://about.gitlab.com/handbook/product/product-categories/#release-management-group) ping 至少 2 个人. + +### Install JupyterHub using GitLab CI/CD[](#install-jupyterhub-using-gitlab-cicd "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/merge_requests/40) . + +通过在`.gitlab/managed-apps/config.yaml`定义配置,使用 GitLab CI / CD 安装`.gitlab/managed-apps/config.yaml` ,如下所示: + +``` +jupyterhub: + installed: true + gitlabProjectIdWhitelist: [] + gitlabGroupWhitelist: [] +``` + +在配置中: + +* `gitlabProjectIdWhitelist`将 GitLab 身份验证限制为仅指定项目的成员. +* `gitlabGroupWhitelist`将 GitLab 身份验证限制为仅指定组的成员. +* 为两者指定一个空数组将允许 GitLab 实例上的任何用户登录. + +JupyterHub 已安装到集群的`gitlab-managed-apps`命名空间中. + +为了使 JupyterHub 正常运行,您必须设置一个[OAuth 应用程序](../../integration/oauth_provider.html) . 组: + +* “Redirect URI” to `http:///hub/oauth_callback`. +* `api read_repository write_repository` "范围". + +此外,必须使用[CI 变量](../../ci/variables/README.html)指定以下[变量](../../ci/variables/README.html) : + +| 可变 CI | Description | +| --- | --- | +| `JUPYTERHUB_PROXY_SECRET_TOKEN` | 用于签名来自集线器的通信的安全字符串. 请参阅[`proxy.secretToken`](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference/reference.html#proxy-secrettoken) . | +| `JUPYTERHUB_COOKIE_SECRET` | 用于签署安全 cookie 的安全字符串. 参见[`hub.cookieSecret`](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference/reference.html#hub-cookiesecret) . | +| `JUPYTERHUB_HOST` | 用于安装的主机名. 例如, `jupyter.gitlab.example.com` . | +| `JUPYTERHUB_GITLAB_HOST` | 用于身份验证的 GitLab 实例的主机名. 例如, `gitlab.example.com` . | +| `JUPYTERHUB_AUTH_CRYPTO_KEY` | 一个 32 字节的加密密钥,用于设置[`auth.state.cryptoKey`](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference/reference.html#auth-state-cryptokey) . | +| `JUPYTERHUB_AUTH_GITLAB_CLIENT_ID` | OAuth 应用程序的"应用程序 ID". | +| `JUPYTERHUB_AUTH_GITLAB_CLIENT_SECRET` | OAuth 应用程序的"秘密". | + +默认情况下,将使用[默认值文件](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/blob/master/src/default-data/jupyterhub/values.yaml.gotmpl)安装 JupyterHub. 您可以通过在群集管理项目中定义`.gitlab/managed-apps/jupyterhub/values.yaml`文件来自定义`.gitlab/managed-apps/jupyterhub/values.yaml`的安装. + +有关可用的配置选项,请参考[图表参考](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference/reference.html) . + +**注意:** GitLab 配置组提供了对安装 JupyterHub 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并从[Configure 组中](https://about.gitlab.com/handbook/product/categories/#configure-group) ping 通至少 2 个人. + +### Install Elastic Stack using GitLab CI/CD[](#install-elastic-stack-using-gitlab-cicd "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25138) . + +通过在`.gitlab/managed-apps/config.yaml`定义配置,使用 GitLab CI / CD 安装 Elastic Stack. + +使用 GitLab CI / CD 安装 Elastic Stack 需要以下配置: + +``` +elasticStack: + installed: true +``` + +Elastic Stack 已安装到集群的`gitlab-managed-apps`命名空间中. + +您可以检查默认[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/vendor/elastic_stack/values.yaml)我们此图表设置. + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/elastic-stack/values.yaml`文件来自定义 Elastic Stack 的安装. 请参阅[图表](https://gitlab.com/gitlab-org/charts/elastic-stack)以获取可用的配置选项. + +**注意:**在通过 CI 安装 Elastic Stack 的 alpha 实现中,不支持通过 Elasticsearch 读取环境日志. 如果[通过 UI 安装,](#elastic-stack)则支持此功能.**注意:** GitLab APM 组提供了对安装 Elastic Stack 托管应用程序的支持. 如果遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping [APM 组中的](https://about.gitlab.com/handbook/product/product-categories/#apm-group)至少 2 个人. + +### Install Crossplane using GitLab CI/CD[](#install-crossplane-using-gitlab-cicd "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/35675) . + +通过在`.gitlab/managed-apps/config.yaml`定义配置,使用 GitLab CI / CD 安装 Crossplane. + +使用 GitLab CI / CD 安装 Crossplane 需要以下配置: + +``` +Crossplane: + installed: true +``` + +Crossplane 已安装到集群的`gitlab-managed-apps`命名空间中. + +您可以检查默认[`values.yaml`](https://github.com/crossplane/crossplane/blob/master/cluster/charts/crossplane/values.yaml.tmpl)我们此图表设置. + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/crossplane/values.yaml`文件来自定义 Crossplane 的安装. 请参阅[图表](https://github.com/crossplane/crossplane/tree/master/cluster/charts/crossplane#configuration)以获取可用的配置选项. 请注意,此链接指向当前开发版本的文档,该文档可能与您安装的版本不同. + +**注意:** Crossplane 团队提供对 Crossplane 托管应用程序的支持. 如果遇到问题,请直接[打开支持凭单](https://github.com/crossplane/crossplane/issues/new/choose) . + +### Install Fluentd using GitLab CI/CD[](#install-fluentd-using-gitlab-cicd "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/merge_requests/76) . + +要使用 GitLab CI / CD 将`gitlab-managed-apps`安装到群集的`gitlab-managed-apps`命名空间中,请在`.gitlab/managed-apps/config.yaml`定义以下配置: + +``` +Fluentd: + installed: true +``` + +您也可以在[`values.yaml`](https://github.com/helm/charts/blob/master/stable/fluentd/values.yaml)文件中查看为此图表设置的默认值. + +您可以通过在群集管理项目中定义`.gitlab/managed-apps/fluentd/values.yaml`文件来自定义`.gitlab/managed-apps/fluentd/values.yaml`的安装. 有关可用的配置选项,请参阅[Fluentd 当前开发版本](https://github.com/helm/charts/tree/master/stable/fluentd#configuration)的[配置表](https://github.com/helm/charts/tree/master/stable/fluentd#configuration) . + +**注意:**配置图表链接指向当前的开发版本,该版本可能与您安装的版本不同. 为了确保兼容性,请切换到您正在使用的特定分支或标签.**注意:** GitLab Container Security 组提供了对安装 Fluentd 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping 通至少来自[Container Security 组的](https://about.gitlab.com/handbook/product/product-categories/#container-security-group) 2 个人. + +### Install Knative using GitLab CI/CD[](#install-knative-using-gitlab-cicd "Permalink") + +要安装 Knative,请使用以下命令定义`.gitlab/managed-apps/config.yaml`文件: + +``` +knative: + installed: true +``` + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/knative/values.yaml`文件来自定义`.gitlab/managed-apps/knative/values.yaml`的安装. 请参阅[图表](https://gitlab.com/gitlab-org/charts/knative)以获取可用的配置选项. + +这是 Knative 的示例配置: + +``` +domain: 'my.wildcard.A.record.dns' +``` + +如果计划使用 GitLab 无服务器功能,请确保在自定义配置上设置 A 记录通配符域. + +**注意:** GitLab 配置组提供了对安装 Knative 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并从[Configure 组中](https://about.gitlab.com/handbook/product/categories/#configure-group) ping 通至少 2 个人. + +#### Knative Metrics[](#knative-metrics "Permalink") + +GitLab 为您的函数提供了[调用指标](../project/clusters/serverless/index.html#invocation-metrics) . 要收集这些指标,您必须具有: + +1. 在群集上安装了 Knative 和 Prometheus 托管的应用程序. +2. 通过运行以下命令在群集上手动应用自定义指标: + + ``` + kubectl apply -f https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/raw/02c8231e30ef5b6725e6ba368bc63863ceb3c07d/src/default-data/knative/istio-metrics.yaml + ``` + +#### Uninstall Knative[](#uninstall-knative "Permalink") + +要卸载 Knative,必须首先通过运行以下命令手动删除已添加的所有自定义指标: + +``` +kubectl delete -f https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/raw/02c8231e30ef5b6725e6ba368bc63863ceb3c07d/src/default-data/knative/istio-metrics.yaml +``` + +### Install AppArmor using GitLab CI/CD[](#install-apparmor-using-gitlab-cicd "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/merge_requests/100) . + +要使用 GitLab CI / CD 将 AppArmor 安装到群集的`gitlab-managed-apps`命名空间中,请在`.gitlab/managed-apps/config.yaml`定义以下配置: + +``` +apparmor: + installed: true +``` + +您可以通过将它们添加到`.gitlab/managed-apps/apparmor/values.yaml`来定义一个或多个 AppArmor 配置文件,如下所示: + +``` +profiles: + profile-one: |- + profile profile-one { + file, + } +``` + +有关此图表的更多信息,请参考[AppArmor](https://gitlab.com/gitlab-org/charts/apparmor)图表. + +#### Using AppArmor profiles in your deployments[](#using-apparmor-profiles-in-your-deployments "Permalink") + +安装 AppAmor 之后,您可以通过添加 Pod 注释来使用配置文件. 如果您使用的是 Auto DevOps,则可以[自定义`auto-deploy-values.yaml`](../../topics/autodevops/customize.html#customize-values-for-helm-chart)来注释您的 Pod. 尽管了解[自定义属性列表](https://gitlab.com/gitlab-org/charts/auto-deploy-app#gitlabs-auto-deploy-helm-chart)会有所帮助,但只需`podAnnotations`如下所示设置`podAnnotations` : + +``` +podAnnotations: + container.apparmor.security.beta.kubernetes.io/auto-deploy-app: localhost/profile-one +``` + +此处唯一要更改的信息是配置文件名称,在本示例中为`profile-one` . 有关如何在 Kubernetes 中集成[AppArmor](https://kubernetes.io/docs/tutorials/clusters/apparmor/#securing-a-pod)的更多信息,请参考[AppArmor 教程](https://kubernetes.io/docs/tutorials/clusters/apparmor/#securing-a-pod) . + +**注意:** GitLab Container Security 组提供了对安装 AppArmor 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping 通至少来自[Container Security 组的](https://about.gitlab.com/handbook/product/product-categories/#container-security-group) 2 个人. + +## Upgrading applications[](#upgrading-applications "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24789) . + +以下应用程序可以升级. + +| Application | GitLab 版本 | +| --- | --- | +| Runner | 11.8+ | + +升级应用程序: + +1. 为一个: + * [在项目级别的集群中](../project/clusters/index.html) ,导航到项目的**Operations> Kubernetes** . + * [组级别集群](../group/clusters/index.html) ,导航到您组的**Kubernetes**页面. +2. 选择您的集群. +3. 如果有升级,将显示" **升级"**按钮. 单击按钮进行升级. + +**注意:**升级会将值重置为`runner`图表中内置的值, [`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/runner/values.yaml)设置的值. + +## Uninstalling applications[](#uninstalling-applications "Permalink") + +在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/60665) . + +可以卸载以下应用程序. + +| Application | GitLab 版本 | Notes | +| --- | --- | --- | +| cert-manager | 12.2+ | 关联的私钥将被删除,并且无法还原. 部署的应用程序将继续使用 HTTPS,但是不会续订证书. 卸载之前,您可能希望[备份配置](https://cert-manager.io/docs/tutorials/backup/)或[吊销证书](https://letsencrypt.org/docs/revoking/) . | +| 亚搏体育 app Runner | 12.2+ | 任何正在运行的管道将被取消. | +| Helm | 12.2+ | 关联的 Tiller 容器, `gitlab-managed-apps`命名空间及其所有资源将被删除,并且无法还原. | +| Ingress | 12.1+ | 关联的负载均衡器和 IP 将被删除,并且无法还原. 此外,仅当未安装 JupyterHub 时才能将其卸载. | +| JupyterHub | 12.1+ | 所有未提交到 GitLab 的数据将被删除,并且无法还原. | +| Knative | 12.1+ | 关联的 IP 将被删除,无法恢复. | +| Prometheus | 11.11+ | 所有数据将被删除,无法还原. | +| Crossplane | 12.5+ | 所有数据将被删除,无法还原. | +| 弹性堆叠 | 12.7+ | 所有数据将被删除,无法还原. | +| Sentry | 12.6+ | PostgreSQL 永久卷将保留,应手动删除以完全卸载. | + +卸载应用程序: + +1. 为一个: + * [在项目级别的集群中](../project/clusters/index.html) ,导航到项目的**Operations> Kubernetes** . + * [组级别集群](../group/clusters/index.html) ,导航到您组的**Kubernetes**页面. +2. 选择您的集群. +3. 单击该应用程序的" **卸载"**按钮. + +支持逐步卸载所有支持的应用程序. 要了解进度,请参阅[相关的史诗](https://gitlab.com/groups/gitlab-org/-/epics/1201) . + +## Troubleshooting applications[](#troubleshooting-applications "Permalink") + +应用程序可能因以下错误而失败: + +``` +Error: remote error: tls: bad certificate +``` + +为避免安装错误: + +* 在开始安装应用程序之前,请确保您的 GitLab 服务器和 Kubernetes 集群之间的时间已同步. +* 确保证书不同步. 在安装应用程序时,GitLab 需要一个没有先前安装的 Helm 的新集群. + + 您可以通过`kubectl`确认证书匹配: + + ``` + kubectl get configmaps/values-content-configuration-ingress -n gitlab-managed-apps -o \ + "jsonpath={.data['cert\.pem']}" | base64 -d > a.pem + kubectl get secrets/tiller-secret -n gitlab-managed-apps -o "jsonpath={.data['ca\.crt']}" | base64 -d > b.pem + diff a.pem b.pem + ``` + +### Error installing managed apps on EKS cluster[](#error-installing-managed-apps-on-eks-cluster "Permalink") + +如果您在 AWS EKS 上使用托管集群,但无法安装某些托管应用程序,请考虑检查日志. + +您可以通过运行以下命令来检查日志: + +``` +kubectl get pods --all-namespaces +kubectl get services --all-namespaces +``` + +如果遇到`Failed to assign an IP address to container`错误,则可能是由于您在 AWS 配置中指定的实例类型. 节点的数量和大小可能没有足够的 IP 地址来运行或安装这些 Pod. + +作为参考,可以[在 GitHub 上的此 AWS 存储库](https://github.com/aws/amazon-vpc-cni-k8s/blob/master/pkg/awsutils/vpc_ip_resource_limit.go)中找到所有 AWS 实例 IP 限制(搜索`InstanceENIsAvailable` ). + +### Unable to install Prometheus[](#unable-to-install-prometheus "Permalink") + +Prometheus 安装失败,出现以下错误: + +``` +# kubectl -n gitlab-managed-apps logs install-prometheus +... +Error: Could not get apiVersions from Kubernetes: unable to retrieve the complete list of server APIs: admission.certmanager.k8s.io/v1beta1: the server is currently unable to handle the request +``` + +这是在 Helm `2.15`中引入并在`3.0.2`修复的错误. 解决方法是,在安装 Prometheus 之前,需要确保已成功安装[`cert-manager`](#cert-manager) . \ No newline at end of file diff --git a/_book/docs/026.md b/_book/docs/026.md new file mode 100644 index 0000000000000000000000000000000000000000..7adc85bef91ade83593af0abc823335be5b3c842 --- /dev/null +++ b/_book/docs/026.md @@ -0,0 +1,264 @@ +# Crossplane configuration + +> 原文:[https://docs.gitlab.com/ee/user/clusters/crossplane.html](https://docs.gitlab.com/ee/user/clusters/crossplane.html) + +* [Configure RBAC permissions](#configure-rbac-permissions) +* [Configure Crossplane with a cloud provider](#configure-crossplane-with-a-cloud-provider) +* [Configure Managed Service Access](#configure-managed-service-access) +* [Setting up Resource classes](#setting-up-resource-classes) +* [Auto DevOps Configuration Options](#auto-devops-configuration-options) +* [Connect to the PostgreSQL instance](#connect-to-the-postgresql-instance) + +# Crossplane configuration[](#crossplane-configuration "Permalink") + +[安装](applications.html#crossplane) Crossplane 后,必须对其进行配置以供使用. 配置 Crossplane 的过程包括: + +1. [Configure RBAC permissions](#configure-rbac-permissions). +2. [Configure Crossplane with a cloud provider](#configure-crossplane-with-a-cloud-provider). +3. [Configure managed service access](#configure-managed-service-access). +4. [Set up Resource classes](#setting-up-resource-classes). +5. Use [Auto DevOps configuration options](#auto-devops-configuration-options). +6. [Connect to the PostgreSQL instance](#connect-to-the-postgresql-instance). + +为了允许 Crossplane 设置诸如 PostgreSQL 之类的云服务,必须使用用户帐户配置云提供商堆栈. 例如: + +* GCP 的服务帐户. +* AWS 的 IAM 用户. + +一些重要的注意事项: + +* 本指南以 GCP 为例,但 AWS 和 Azure 的过程相似. +* Crossplane 要求 Kubernetes 集群是启用了 Alias IP 的 VPC 本机,因此可以在 GCP 网络内路由 Pod 的 IP 地址. + +首先,使用配置声明一些环境变量以供本指南使用: + +``` +export PROJECT_ID=crossplane-playground # the GCP project where all resources reside. +export NETWORK_NAME=default # the GCP network where your GKE is provisioned. +export REGION=us-central1 # the GCP region where the GKE cluster is provisioned. +``` + +## Configure RBAC permissions[](#configure-rbac-permissions "Permalink") + +对于由 GitLab 管理的群集,将自动配置基于角色的访问控制(RBAC). + +对于非 GitLab 管理的群集,请确保提供的令牌的服务帐户可以管理`database.crossplane.io` API 组中的资源: + +1. 将以下 YAML 保存为`crossplane-database-role.yaml` : + + ``` + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + name: crossplane-database-role + labels: + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rules: + - apiGroups: + - database.crossplane.io + resources: + - postgresqlinstances + verbs: + - get + - list + - create + - update + - delete + - patch + - watch + ``` + +2. 将集群角色应用于集群: + + ``` + kubectl apply -f crossplane-database-role.yaml + ``` + +## Configure Crossplane with a cloud provider[](#configure-crossplane-with-a-cloud-provider "Permalink") + +请参阅[配置您的云提供商帐户](https://crossplane.github.io/docs/v0.4/cloud-providers.html)以使用用户帐户配置已安装的云提供商堆栈. + +**注意:必须**将 Secret 和引用该 Secret 的 Provider 资源应用于指南中的`gitlab-managed-apps`命名空间. 请确保在执行该过程时进行更改. + +## Configure Managed Service Access[](#configure-managed-service-access "Permalink") + +接下来,通过以下任一方法配置 PostgreSQL 数据库和 GKE 集群之间的连接: + +* 如下所示使用 Crossplane. +* Directly in the GCP console by [configuring private services access](https://cloud.google.com/vpc/docs/configure-private-services-access). + +1. 运行以下命令,这将创建一个`network.yaml`文件,并配置`GlobalAddress`和连接资源: + + ``` + cat > network.yaml < gcp-postgres-standard.yaml < +Annotations: crossplane.io/propagate-from-name: 108e460e-06c7-11ea-b907-42010a8000bd + crossplane.io/propagate-from-namespace: gitlab-managed-apps + crossplane.io/propagate-from-uid: 10c79605-06c7-11ea-b907-42010a8000bd + +Type: Opaque + +Data +==== +privateIP: 8 bytes +publicIP: 13 bytes +serverCACertificateCert: 1272 bytes +serverCACertificateCertSerialNumber: 1 bytes +serverCACertificateCreateTime: 24 bytes +serverCACertificateExpirationTime: 24 bytes +username: 8 bytes +endpoint: 8 bytes +password: 27 bytes +serverCACertificateCommonName: 98 bytes +serverCACertificateInstance: 41 bytes +serverCACertificateSha1Fingerprint: 40 bytes +``` + +## Connect to the PostgreSQL instance[](#connect-to-the-postgresql-instance "Permalink") + +如果您想连接到 CloudSQL 上新配置的 PostgreSQL 数据库实例,请遵循此[GCP 指南](https://cloud.google.com/sql/docs/postgres/connect-kubernetes-engine) . \ No newline at end of file diff --git a/_book/docs/027.md b/_book/docs/027.md new file mode 100644 index 0000000000000000000000000000000000000000..267cdcd9578a0721596624b7b57e6a1cbe5ca77c --- /dev/null +++ b/_book/docs/027.md @@ -0,0 +1,103 @@ +# Cluster management project (alpha) + +> 原文:[https://docs.gitlab.com/ee/user/clusters/management_project.html](https://docs.gitlab.com/ee/user/clusters/management_project.html) + +* [Permissions](#permissions) +* [Usage](#usage) + * [Selecting a cluster management project](#selecting-a-cluster-management-project) + * [Configuring your pipeline](#configuring-your-pipeline) + * [Setting the environment scope](#setting-the-environment-scope-premium) + +# Cluster management project (alpha)[](#cluster-management-project-alpha "Permalink") + +**警告:**这是*Alpha 版*功能,如有更改,恕不另行通知. + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32810) + +可以将一个项目指定为集群的管理项目. 管理项目可用于以 Kubernetes [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)权限运行部署作业. + +这对以下情况很有用: + +* 创建管道以将群集范围的应用程序安装到群集中,有关详细信息,请参见[使用 GitLab CI / CD(alpha)](applications.html#install-using-gitlab-cicd-alpha)安装. +* 需要`cluster-admin`权限的所有作业. + +## Permissions[](#permissions "Permalink") + +仅管理项目将获得`cluster-admin`权限. 所有其他项目将继续获得[命名空间范围的`edit`级别特权](../project/clusters/add_remove_clusters.html#rbac-cluster-resources) . + +管理项目仅限于以下内容: + +* 对于项目级集群,管理项目必须与集群项目位于相同的名称空间(或子代)中. +* 对于组级集群,管理项目必须与集群的组位于同一组(或子孙)中. +* 对于实例级群集,没有此类限制. + +## Usage[](#usage "Permalink") + +要将群集管理项目用于群集: + +1. 选择项目. +2. 配置管道. +3. 设置环境范围. + +### Selecting a cluster management project[](#selecting-a-cluster-management-project "Permalink") + +选择要使用的集群管理项目: + +1. 导航到适当的配置页面. 为一个: + * [项目级集群](../project/clusters/index.html) ,导航到项目的**Operations> Kubernetes**页面. + * [组级别集群](../group/clusters/index.html) ,导航到您组的**Kubernetes**页面. + * [实例级集群](../instance/clusters/index.html) ,导航到管理区域的**Kubernetes**页面. +2. 在" **高级设置"**部分中的"使用**集群管理项目"字段**中选择项目. + +[![Selecting a cluster management project under Advanced settings](img/838245c530d1afaf54929d9edd3f6a24.png)](img/advanced-settings-cluster-management-project-v12_5.png) + +### Configuring your pipeline[](#configuring-your-pipeline "Permalink") + +将项目指定为集群的管理项目后,在该项目中编写[`.gitlab-ci.yml`](../../ci/yaml/README.html) . 例如: + +``` +configure cluster: + stage: deploy + script: kubectl get namespaces + environment: + name: production +``` + +### Setting the environment scope[](#setting-the-environment-scope-premium "Permalink") + +将多个群集与同一管理项目关联时,可以使用[环境范围](../project/clusters/index.html#setting-the-environment-scope-premium) . + +每个作用域只能由单个群集用于管理项目. + +例如,假设以下 Kubernetes 集群与管理项目相关联: + +| Cluster | 环境范围 | +| --- | --- | +| Development | `*` | +| Staging | `staging` | +| Production | `production` | + +[`.gitlab-ci.yml`](../../ci/yaml/README.html)设置的以下环境将分别部署到 Development,Staging 和 Production 集群. + +``` +stages: + - deploy + +configure development cluster: + stage: deploy + script: kubectl get namespaces + environment: + name: development + +configure staging cluster: + stage: deploy + script: kubectl get namespaces + environment: + name: staging + +configure production cluster: + stage: deploy + script: kubectl get namespaces + environment: + name: production +``` \ No newline at end of file diff --git a/_book/docs/028.md b/_book/docs/028.md new file mode 100644 index 0000000000000000000000000000000000000000..72b89b4e4b654a3acd84f965ee24cc57fbcf96d3 --- /dev/null +++ b/_book/docs/028.md @@ -0,0 +1,100 @@ +# Kubernetes Logs + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/kubernetes_pod_logs.html](https://docs.gitlab.com/ee/user/project/clusters/kubernetes_pod_logs.html) + +* [Overview](#overview) +* [Requirements](#requirements) +* [Usage](#usage) + * [From the project sidebar](#from-the-project-sidebar) + * [From Deploy Boards](#from-deploy-boards) + * [Logs view](#logs-view) + * [Filter by date](#filter-by-date) + * [Full text search](#full-text-search) + +# Kubernetes Logs[](#kubernetes-logs "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4752) . +* [移至](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26383) [GitLab Core](https://about.gitlab.com/pricing/) 12.9\. + +使用 GitLab 可以轻松查看[连接的 Kubernetes 集群](index.html)中正在运行的 Pod 的日志. 通过直接在**Log Explorer 的** GitLab 中显示**日志** ,开发人员可以避免管理控制台工具或跳转到其他界面. + +**注意:** [了解有关 Kubernetes + GitLab 的更多信息](https://about.gitlab.com/solutions/kubernetes/) . 大规模构建,测试,部署和运行应用程序所需的一切. + +## Overview[](#overview "Permalink") + +[Kubernetes](https://kubernetes.io)日志可以使用**Log Explorer**在 GitLab 中直接查看. + +[![Pod logs](img/0370f6d6a289b9e8237fcad4c7672e78.png)](img/kubernetes_pod_logs_v12_10.png) + +要了解更多信息,请参阅[APM-Log Explorer](https://www.youtube.com/watch?v=hWclZHA7Dgw) . + +## Requirements[](#requirements "Permalink") + +要使用日志,需要[部署到 Kubernetes 环境](../deploy_boards.html#enabling-deploy-boards) . + +## Usage[](#usage "Permalink") + +要访问日志,您必须具有正确的[权限](../../permissions.html#project-members-permissions) . + +您可以通过两种方式访问​​它们. + +### From the project sidebar[](#from-the-project-sidebar "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22011) . + +去 侧栏菜单上的" **操作">"舱位日志** "以显示" **日志资源管理器"** . + +[![Sidebar menu](img/0050abd936ad2e13e4ad057a58611cc9.png)](img/sidebar_menu_pod_logs_v12_10.png) + +### From Deploy Boards[](#from-deploy-boards "Permalink") + +可以通过单击[Deploy Boards 中](../deploy_boards.html)的特定窗格来显示日志: + +1. 去 **操作>环境,**然后找到包含所需 pod 的环境,例如`production` . +2. 在" **环境"**页面上,您应该通过[Deploy Boards](../deploy_boards.html)看到环境容器的状态. +3. 将鼠标悬停在窗格列表上时,将显示一个工具提示,其中包含确切的窗格名称和状态. [![部署板窗格列表](img/81c888ba61ab652f9505d5b51406ed22.png)](img/pod_logs_deploy_board.png) +4. 单击所需的窗格以显示**Log Explorer** . + +### Logs view[](#logs-view "Permalink") + +**日志浏览**器使您可以通过以下方式过滤日志: + +* Pods. +* [从 GitLab 12.4 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/5769) ,环境. +* [From GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21656), [full text search](#full-text-search). +* [从 GitLab 12.8 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/197879) ,日期. + +从[GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/198050)起可以加载 500 条以上的日志行. + +[在将来的版本中将](https://gitlab.com/gitlab-org/gitlab/-/issues/13404)支持具有多个容器的 Pod. + +[在将来的版本中将](https://gitlab.com/gitlab-org/gitlab/-/issues/196191)支持历史数据. + +### Filter by date[](#filter-by-date "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/197879) . + +在集群上启用[Elastic Stack](../../clusters/applications.html#elastic-stack)时,您可以按日期过滤" **日志浏览**器"中显示的**日志** . + +单击" **日志资源管理器"**中的" **显示最后一个** "以查看可用选项. + +### Full text search[](#full-text-search "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21656) . + +在集群上启用[Elastic Stack](../../clusters/applications.html#elastic-stack)时,可以通过搜索栏搜索日志的内容. + +搜索通过使用[simple_query_string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html) Elasticsearch 函数传递给 Elasticsearch,该函数支持以下运算符: + +| Operator | Description | +| --- | --- | +| `\|` | 或运算. | +| `-` | 取反单个令牌. | +| `+` | AND 运算. | +| `"` | 包装许多标记以表示要搜索的短语. | +| `*` (每学期末) | 前缀查询. | +| `(` and `)` | Precedence. | +| `~N` (一个字之后) | 编辑距离(模糊性). | +| `~N` (在短语之后) | 斜率. | \ No newline at end of file diff --git a/_book/docs/029.md b/_book/docs/029.md new file mode 100644 index 0000000000000000000000000000000000000000..695ccf7100dfe06c457b0f23654abdd5166b0968 --- /dev/null +++ b/_book/docs/029.md @@ -0,0 +1,104 @@ +# Runbooks + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/runbooks/](https://docs.gitlab.com/ee/user/project/clusters/runbooks/) + +* [Executable Runbooks](#executable-runbooks) +* [Requirements](#requirements) +* [Nurtch](#nurtch) +* [Configure an executable runbook with GitLab](#configure-an-executable-runbook-with-gitlab) + +# Runbooks[](#runbooks "Permalink") + +Runbooks 是记录在案的过程的集合,这些过程解释了如何执行特定过程,包括启动,停止,调试特定系统或对特定系统进行故障排除. + +使用[Jupyter Notebook](https://jupyter.org/)和[Rubix 库](https://github.com/Nurtch/rubix) ,用户可以开始编写自己的可执行运行手册. + +从历史上看,运行手册根据情况或系统采用决策树或详细的分步指南的形式. + +现代的实现方式引入了"可执行的运行手册"的概念,其中,操作员可以结合定义良好的流程在给定的环境中执行预写的代码块或数据库查询. + +## Executable Runbooks[](#executable-runbooks "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45912) . + +通过 GitLab 的 Kubernetes 集成提供的 JupyterHub 应用程序现在随 Nurtch 的 Rubix 库一起提供,提供了一种创建 DevOps Runbook 的简单方法. 提供了一个样本运行手册,其中展示了常见的操作. 虽然 Rubix 使创建常见的 Kubernetes 和 AWS 工作流变得简单,但是您也可以不使用 Rubix 手动创建它们. + +观看此[视频](https://www.youtube.com/watch?v=Q_OqHIIUPjE) ,了解如何在 GitLab 中完成此操作! + +## Requirements[](#requirements "Permalink") + +要创建可执行的运行本,您将需要: + +* **Kubernetes-**需要 Kubernetes 集群才能部署其余应用程序. 最简单的入门方法是使用[GitLab 的集成](../add_remove_clusters.html#create-new-cluster)之一添加集群. +* **入口** -入口可以提供负载平衡,SSL 终止和基于名称的虚拟主机. 它充当您的应用程序的 Web 代理. +* **JupyterHub** - [JupyterHub](https://jupyterhub.readthedocs.io/)是用于在团队中管理笔记本的多用户服务. Jupyter Notebook 提供了一个基于 Web 的交互式编程环境,用于数据分析,可视化和机器学习. + +## Nurtch[](#nurtch "Permalink") + +Nurtch 是[Rubix 库](https://github.com/Nurtch/rubix)背后的公司. Rubix 是一个开源 Python 库,可轻松在 Jupyter Notebooks 中执行常见的 DevOps 任务. 绘制 Cloudwatch 指标和滚动 ECS / Kubernetes 应用之类的任务将简化为几行代码. 有关更多信息,请参见[Nurtch 文档](http://docs.nurtch.com/en/latest/) . + +## Configure an executable runbook with GitLab[](#configure-an-executable-runbook-with-gitlab "Permalink") + +遵循此分步指南,使用上述组件和预加载的演示运行本在 GitLab 中配置可执行运行本. + +1. 遵循[创建新集群中](../add_remove_clusters.html#create-new-cluster)概述的步骤,将 Kubernetes 集群添加到您的项目中. + +2. 单击**Ingress**应用程序旁边的" **安装"**按钮以安装 Ingress. + + [![install ingress](img/5a2430ba8091036f8e9e3308aa845de8.png)](img/ingress-install.png) + +3. 成功安装 Ingress 后,单击**JupyterHub**应用程序旁边的" **安装"**按钮. **下一步,**您将需要此处提供的**Jupyter 主机名** . + + [![install JupyterHub](img/00fd9bca0c7bdc64f74a24b691e0adac.png)](img/jupyterhub-install.png) + +4. 成功安装**JupyterHub 后** ,在浏览器中打开**Jupyter 主机名** . 单击" **使用 GitLab 登录"**按钮登录到 JupyterHub 并启动服务器. 使用 OAuth2 为 GitLab 实例的任何用户启用身份验证. 此按钮将您重定向到 GitLab 上的页面,请求 JupyterHub 授权使用您的 GitLab 帐户. + + [![authorize Jupyter](img/9950340e3b641e3f63d70fb29b2b05bb.png)](img/authorize-jupyter.png) + +5. 单击**Authorize** ,您将被重定向到 JupyterHub 应用程序. +6. 单击" **启动我的服务器"** ,服务器将在几秒钟后启动. +7. 要配置 Runbook 对 GitLab 项目的访问,必须在演示 Runbook 的" **设置"**部分中输入您的[GitLab 访问令牌](../../../profile/personal_access_tokens.html)和项目 ID: + + 1. 双击左侧面板上的**DevOps-Runbook-Demo**文件夹. + + [![demo runbook](img/6809ef73be513357f41ebe6d325265d5.png)](img/demo-runbook.png) + + 2. 双击`Nurtch-DevOps-Demo.ipynb` . + + [![sample runbook](img/ae5a500e2333874603b33328b017eb35.png)](img/sample-runbook.png) + + Jupyter 在屏幕右侧显示 Runbook 的内容. **设置**部分显示您的`PRIVATE_TOKEN`和您的`PROJECT_ID` . 输入这些值,并保持单引号如下: + + ``` + PRIVATE_TOKEN = 'n671WNGecHugsdEDPsyo' + PROJECT_ID = '1234567' + ``` + + 3. Update the `VARIABLE_NAME` on the last line of this section to match the name of the variable you’re using for your access token. In this example, our variable name is `PRIVATE_TOKEN`. + + ``` + VARIABLE_VALUE = project.variables.get('PRIVATE_TOKEN').value + ``` + +8. 要配置运行手册的操作,请创建和配置变量: + + **注意:**对于此示例,我们使用示例**运行簿**中的**笔记本中**的**"运行 SQL 查询"**部分来查询 PostgreSQL 数据库. 以下代码块的前四行定义了此查询运行所需的变量: + + ``` + %env DB_USER={project.variables.get('DB_USER').value} + %env DB_PASSWORD={project.variables.get('DB_PASSWORD').value} + %env DB_ENDPOINT={project.variables.get('DB_ENDPOINT').value} + %env DB_NAME={project.variables.get('DB_NAME').value} + ``` + + 1. 导航 **设置»CI / CD»变量**以在项目中创建变量. + + [![GitLab variables](img/15b455cffa86c3a9234ad8c30082a4df.png)](img/gitlab-variables.png) + + 2. Click **保存变量**. + + 3. 在 Jupyter 中,单击**"笔记本"**标题中的**"运行 SQL 查询"** ,然后单击**"运行"** . 结果以内联方式显示如下: + + [![PostgreSQL query](img/1a1b871d7e874d4f8e2ab4905d000509.png)](img/postgres-query.png) + +您可以尝试其他操作,例如运行 Shell 脚本或与 Kubernetes 集群进行交互. 有关更多信息,请访问[Nurtch 文档](http://docs.nurtch.com/) . \ No newline at end of file diff --git a/_book/docs/030.md b/_book/docs/030.md new file mode 100644 index 0000000000000000000000000000000000000000..84e2f128a8540c042191d922cfa21706a323ea2b --- /dev/null +++ b/_book/docs/030.md @@ -0,0 +1,734 @@ +# Serverless + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/serverless/](https://docs.gitlab.com/ee/user/project/clusters/serverless/) + +* [Overview](#overview) +* [Knative](#knative) +* [Prerequisites](#prerequisites) +* [Installing Knative via GitLab’s Kubernetes integration](#installing-knative-via-gitlabs-kubernetes-integration) +* [Using an existing installation of Knative](#using-an-existing-installation-of-knative) +* [Supported runtimes](#supported-runtimes) + * [GitLab-managed runtimes](#gitlab-managed-runtimes) + * [OpenFaaS runtimes](#openfaas-runtimes) +* [Deploying functions](#deploying-functions) + * [`service`](#service) + * [`provider`](#provider) + * [`functions`](#functions) + * [Deployment](#deployment) + * [Runtime aliases](#runtime-aliases) + * [Secrets](#secrets) + * [CLI example](#cli-example) + * [Part of deployment job](#part-of-deployment-job) + * [Running functions locally](#running-functions-locally) +* [Deploying Serverless applications](#deploying-serverless-applications) + * [Deploy the application with Knative](#deploy-the-application-with-knative) + * [Function details](#function-details) + * [Invocation metrics](#invocation-metrics) +* [Configuring logging](#configuring-logging) + * [Prerequisites](#prerequisites-1) + * [Enable request log template](#enable-request-log-template) + * [Enable request logs](#enable-request-logs) + * [Viewing request logs](#viewing-request-logs) +* [Enabling TLS for Knative services](#enabling-tls-for-knative-services) +* [Using an older version of `gitlabktl`](#using-an-older-version-of-gitlabktl) + +# Serverless[](#serverless "Permalink") + +在 GitLab 11.5 中引入. + +**警告:** Serverless 目前处于[alpha 状态](https://about.gitlab.com/handbook/product/#alpha) . + +## Overview[](#overview "Permalink") + +无服务器架构为运营商和开发人员提供了在不配置单个服务器的情况下编写高度可扩展的应用程序的能力. + +GitLab 支持在 Kubernetes 环境和主要的云 FAAS 环境中部署无服务器应用程序的几种方法. + +目前,我们支持: + +* [Knative](#knative) :在 GKE 和 EKS 上使用 Knative 和`gitlabktl`构建 Knative 应用程序. +* [AWS Lambda](aws.html) :通过无服务器框架和 GitLab CI / CD 创建无服务器应用程序. + +## Knative[](#knative "Permalink") + +使用[Knative](https://cloud.google.com/knative/)在 Kubernetes 上运行无服务器工作负载. + +Knative 扩展了 Kubernetes 以提供一组中间件组件,这些组件对于构建现代的,以源为中心的,基于容器的应用程序很有用. Knative 通过其主要组件带来了一些明显的好处: + +* [服务](https://github.com/knative/serving) :请求驱动的计算,可扩展为零. +* [事件](https://github.com/knative/eventing) : [事件的](https://github.com/knative/eventing)管理和交付. + +有关 Knative 的更多信息,请访问[Knative docs 资源库](https://github.com/knative/docs) . + +借助 GitLab Serverless,您可以部署功能即服务(FaaS)和无服务器应用程序. + +## Prerequisites[](#prerequisites "Permalink") + +要在 GitLab 上运行 Knative,您需要: + +1. **现有的 GitLab 项目:**您将需要一个 GitLab 项目来关联所有资源. 最简单的入门方法: + * 如果您打算[部署功能](#deploying-functions) ,请克隆[功能示例项目](https://gitlab.com/knative-examples/functions)以开始使用. + * 如果您打算[部署无服务器应用程序](#deploying-serverless-applications) ,请克隆示例[Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app)以开始使用. +2. **Kubernetes 集群:**部署 Knative 需要启用 RBAC 的 Kubernetes 集群. 最简单的入门方法是使用 GitLab 的[GKE 集成](../add_remove_clusters.html)添加集群. 建议的运行 Knative 的最低建议群集规格为 3 个节点,6 个 vCPU 和 22.50 GB 内存. +3. **GitLab 运行程序:**运行 CI 作业需要运行程序,该作业会将无服务器的应用程序或功能部署到您的集群上. 您可以将 GitLab Runner 安装到现有的 Kubernetes 集群上. 有关更多信息,请参见[安装应用程序](../index.html#installing-applications) . +4. **域名:** Knative 将使用 Istio 提供自己的负载平衡器. 它将为 Knative 服务的所有应用程序提供一个外部 IP 地址或主机名. 系统将提示您输入一个通配符域,将在其中提供您的应用程序. 配置您的 DNS 服务器以使用该域的外部 IP 地址或主机名. +5. **`.gitlab-ci.yml` :** GitLab 使用[Kaniko](https://github.com/GoogleContainerTools/kaniko)来构建应用程序. 我们还使用[GitLab Knative 工具](https://gitlab.com/gitlab-org/gitlabktl) CLI 来简化向 Knative 部署服务和功能. +6. **`serverless.yml`** ( [仅](#deploying-functions)适用于[功能](#deploying-functions) ):使用 lessserver 部署功能时, `serverless.yml`文件将包含存储库中托管的所有功能的信息以及所使用的运行时的引用. +7. **`Dockerfile`** ( [仅](#deploying-serverless-applications)适用于[应用程序](#deploying-serverless-applications) ):Knative 需要`Dockerfile`才能构建您的应用程序. 它应该包含在项目存储库的根目录中,并公开端口`8080` . 如果您打算使用我们的[运行时](https://gitlab.com/gitlab-org/serverless/runtimes)来构建无服务器功能,则不需要`Dockerfile` . +8. **Prometheus** (可选):安装 Prometheus 可使您监视无服务器功能/应用程序的规模和流量. 有关更多信息,请参见[安装应用程序](../index.html#installing-applications) . +9. **日志记录** (可选):配置日志记录可让您查看和搜索无服务器功能/应用程序的请求日志. 有关更多信息,请参见[配置日志记录](#configuring-logging) . + +## Installing Knative via GitLab’s Kubernetes integration[](#installing-knative-via-gitlabs-kubernetes-integration "Permalink") + +**注意:**运行 Knative 的最小建议群集大小是 3 节点,6 vCPU 和 22.50 GB 内存. **必须启用 RBAC.** + +1. [Add a Kubernetes cluster](../add_remove_clusters.html). +2. 选择" **应用程序"**选项卡,然后向下滚动到" Knative 应用程序"部分. 输入要用于您的应用程序/功能的域(例如`example.com` ),然后单击**Install** . + + [![install-knative](img/a93d26d68bbc1f4954a7038e601ba3b6.png)](img/install-knative.png) + +3. Knative 安装完成后,您可以等待 IP 地址或主机名显示在**Knative Endpoint**字段中,或[手动检索 Istio Ingress 端点](../../../clusters/applications.html#determining-the-external-endpoint-manually) . + + **注意:**在集群上运行`kubectl`命令需要首先设置对集群的访问. 对于在 GKE 上创建的集群,请参见[GKE 集群访问](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl) ,对于其他平台,请[安装 kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) . +4. 入口现在在此地址可用,并将基于请求中的 DNS 名称将传入请求路由到适当的服务. 为此,应为所需的域名创建通配符 DNS 记录. 例如,如果您的 Knative 基础域是`knative.info`则需要创建一个 A 记录或 CNAME 记录,其域`*.knative.info`指向 Ingress 的 IP 地址或主机名. + + [![DNS entry](img/e7acd74bc1dc7f0103e1b107aac74f84.png)](img/dns-entry.png) + +**注意:**可以在给定项目上部署[功能](#deploying-functions)或[无服务器应用程序](#deploying-serverless-applications) ,但不能两者都部署. 当前实现利用了的`serverless.yml`文件发信号 FAAS 项目. + +## Using an existing installation of Knative[](#using-an-existing-installation-of-knative "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/58941) in GitLab 12.0. + +**注意:**添加现有的 Knative 安装时,GitLabless server 的"调用"监视功能将不起作用. + +也可以将 GitLab Serverless 与已经安装 Knative 的现有 Kubernetes 集群一起使用. + +您必须执行以下操作: + +1. 按照步骤[添加现有的 Kubernetes 集群](../add_remove_clusters.html#add-existing-cluster) . + +2. 确保 GitLab 可以管理 Knative: + * 对于非 GitLab 托管群集,请确保提供的令牌的服务帐户可以管理`serving.knative.dev` API 组中的资源. + * 对于 GitLab 托管群集,如果您在[GitLab 12.1 或更高版本中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30235)添加了群集,则 GitLab 将已经具有所需的访问权限,您可以继续进行下一步. + + 否则,您需要手动授权 GitLab 的服务帐户具有管理`serving.knative.dev` API 组中资源的能力. 由于每个 GitLab 服务帐户都具有`edit`集群角色,因此最简单的方法是通过将默认规则添加到默认`edit`集群角色的[聚合 ClusterRole](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles) :首先,将以下 YAML 保存为`knative-serving-only-role.yaml` : + + ``` + apiVersion : rbac.authorization.k8s.io/v1 kind : ClusterRole metadata : name : knative-serving-only-role labels : rbac.authorization.k8s.io/aggregate-to-edit : " true" rules : - apiGroups : - serving.knative.dev resources : - configurations - configurationgenerations - routes - revisions - revisionuids - autoscalers - services verbs : - get - list - create - update - delete - patch - watch + ``` + + 然后运行以下命令: + + ``` + kubectl apply -f knative-serving-only-role.yaml + ``` + + 如果您希望基于每个服务帐户授予权限,则可以使用特定于服务帐户和名称空间的`Role`和`RoleBinding`来执行此操作. + +3. 请按照以下步骤将[功能](#deploying-functions)或[无服务器应用程序](#deploying-serverless-applications)部署到群集上. + +## Supported runtimes[](#supported-runtimes "Permalink") + +GitLab 的无服务器功能可以使用以下命令运行: + +* [GitLab-managed](#gitlab-managed-runtimes) runtimes. +* [OpenFaaS](#openfaas-runtimes) runtimes. + +如果所需的编程语言无法使用运行时,请考虑部署[无服务器应用程序](#deploying-serverless-applications) . + +### GitLab-managed runtimes[](#gitlab-managed-runtimes "Permalink") + +当前,以下 GitLab 管理的[运行时](https://gitlab.com/gitlab-org/serverless/runtimes)可用: + +* `go` (概念证明) +* `nodejs` +* `ruby` + +如果未指定运行时,则必须提供一个`Dockerfile`来运行无服务器功能. + +### OpenFaaS runtimes[](#openfaas-runtimes "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/29253) . + +[OpenFaaS 经典运行时](https://github.com/openfaas/templates#templates-in-store)可与 GitLab 无服务器一起使用. + +OpenFaas 运行时可用于以下语言: + +* C# +* Go +* NodeJS +* PHP +* Python +* Ruby + +使用以下模式指定运行时: `openfaas/classic/` . 下面的示例示出了如何定义一个函数`serverless.yml`使用 OpenFaaS 运行时: + +``` +hello: + source: ./hello + runtime: openfaas/classic/ruby + description: "Ruby function using OpenFaaS classic runtime" +``` + +`handler` is not needed for OpenFaaS functions. The location of the handler is defined by the conventions of the runtime. + +有关使用 OpenFaaS 运行时的函数示例,请参见[`ruby-openfaas-function`](https://gitlab.com/knative-examples/ruby-openfaas-function)项目. + +## Deploying functions[](#deploying-functions "Permalink") + +在 GitLab 11.6 中引入. + +您可以在**[功能示例项目中](https://gitlab.com/knative-examples/functions)**找到并导入此文档中引用的所有文件. + +请按照以下步骤将使用 Node.js 运行时的功能部署到您的 Knative 实例(如果您已克隆示例项目,则可以跳过以下步骤): + +1. 创建一个目录来容纳该函数. 在此示例中,我们将在项目的根目录创建一个名为`echo`的目录. + +2. 创建将包含功能代码的文件. 在此示例中,我们的文件名为`echo.js` ,位于`echo`目录中. 如果您的项目是: + * 公开,继续下一步. + * 私有的,您将需要使用`gitlab-deploy-token`作为名称和`read_registry`范围[创建一个 GitLab 部署令牌](../../deploy_tokens/index.html#creating-a-deploy-token) . +3. `.gitlab-ci.yml` :这定义了用于部署功能的管道. 它必须包含在存储库的根目录中: + + ``` + include: + - template: Serverless.gitlab-ci.yml + + functions:build: + extends: .serverless:build:functions + environment: production + + functions:deploy: + extends: .serverless:deploy:functions + environment: production + ``` + + 这个`.gitlab-ci.yml`创建的作业会调用一些预定义的命令来构建功能并将其部署到集群中. + + `Serverless.gitlab-ci.yml` is a template that allows customization. You can either import it with `include` parameter and use `extends` to customize your jobs, or you can inline the entire template by choosing it from **套用范本** dropdown when editing the `.gitlab-ci.yml` file through the user interface. + +4. `serverless.yml` :此文件包含您的功能的元数据,例如名称,运行时和环境. + + 它必须包含在存储库的根目录中. 下面是一个示例`echo`函数,它显示了文件所需的结构. + + 您可以在[功能示例项目中](https://gitlab.com/knative-examples/functions)找到该项目的相关文件. + + ``` + service: functions + description: "GitLab Serverless functions using Knative" + + provider: + name: triggermesh + envs: + FOO: value + secrets: + - my-secrets + + functions: + echo-js: + handler: echo-js + source: ./echo-js + runtime: gitlab/runtimes/nodejs + description: "node.js runtime function" + envs: + MY_FUNCTION: echo-js + secrets: + - my-secrets + ``` + +上面使用的字段的说明: + +### `service`[](#service "Permalink") + +| Parameter | Description | +| --- | --- | +| `service` | 服务该功能的 Knative 服务的名称. | +| `description` | 在的简短描述`service` . | + +### `provider`[](#provider "Permalink") + +| Parameter | Description | +| --- | --- | +| `name` | 指示使用哪个提供程序来执行`serverless.yml`文件. 在这种情况下,使用 TriggerMesh 中间件. | +| `envs` | 包括要在文件中**所有**函数的函数执行过程中传递的环境变量,其中`FOO`是变量名, `BAR`是变量内容. 您可以将其替换为自己的变量. | +| `secrets` | 包含 Kubernetes 机密的内容作为环境变量,可访问该变量作为文件中**所有**函数的函数执行的一部分进行传递. 机密应采用 INI 格式. | + +### `functions`[](#functions "Permalink") + +在上面的`serverless.yml`示例中,函数名称为`echo` ,随后的行包含函数属性. + +| Parameter | Description | +| --- | --- | +| `handler` | 函数的名称. | +| `source` | 具有功能源的目录. | +| `runtime` (optional) | 用于执行功能的运行时. 这可以是运行时别名(请参阅[运行时别名](#runtime-aliases) ),也可以是自定义运行时存储库的完整 URL. 当未指定运行`Dockerfile` ,我们假定`Dockerfile`存在于`source`指定的函数目录中. | +| `description` | 功能的简短描述. | +| `envs` | 仅为特定功能设置环境变量. | +| `secrets` | 将 Kubernetes 机密的内容作为环境变量包含在内,这些变量只能作为特定函数的函数执行的一部分进行传递. 机密应采用 INI 格式. | + +### Deployment[](#deployment "Permalink") + +#### Runtime aliases[](#runtime-aliases "Permalink") + +可选的`runtime`参数可以引用以下运行时别名之一(另请参阅[受支持的运行时](#supported-runtimes) ): + +| 运行时别名 | 维护者 | +| --- | --- | +| `gitlab/runtimes/go` | GitLab | +| `gitlab/runtimes/nodejs` | GitLab | +| `gitlab/runtimes/ruby` | GitLab | +| `openfaas/classic/csharp` | OpenFaaS | +| `openfaas/classic/go` | OpenFaaS | +| `openfaas/classic/node` | OpenFaaS | +| `openfaas/classic/php7` | OpenFaaS | +| `openfaas/classic/python` | OpenFaaS | +| `openfaas/classic/python3` | OpenFaaS | +| `openfaas/classic/ruby` | OpenFaaS | + +经过`gitlab-ci.yml`模板已添加和`serverless.yml`文件被创建,推动提交到您的项目将导致 CI 管道被执行,而部署的每个功能的 Knative 服务. 部署阶段完成后,该功能的其他详细信息将显示在" **操作">"无服务器"下** . + +[![serverless page](img/e8c78799e0967a32ee1efeaea30f6213.png)](img/serverless-page.png) + +该页面包含可用于项目的所有功能,访问功能的描述以及(如果有)功能的运行时信息. 详细信息来自于项目的每个 Kubernetes 集群中的 Knative 安装. 单击每个功能以获得详细的规模和调用数据. + +可以从集群上的 Knative 直接检索函数详细信息: + +``` +kubectl -n "$KUBE_NAMESPACE" get services.serving.knative.dev +``` + +现在可以使用任何简单的`POST`调用从任何 HTTP 客户端触发示例函数: + +1. 使用 curl(将最后一行的 URL 替换为应用程序的 URL): + + ``` + curl \ + --header "Content-Type: application/json" \ + --request POST \ + --data '{"GitLab":"FaaS"}' \ + http://functions-echo.functions-1.functions.example.com/ + ``` + +2. 使用基于 Web 的工具(例如 Postman 或 Restlet) + + [![function execution](img/676537e7ead1101c5c0668a2adbc08d5.png)](img/function-execution.png) + +### Secrets[](#secrets "Permalink") + +要从函数内部访问 Kubernetes 机密,应在无服务器部署的名称空间下创建该机密,并在上述`serverless.yml`文件中指定这些机密. 您可以通过多种方式创建机密. 以下各节显示了一些示例. + +#### CLI example[](#cli-example "Permalink") + +``` +kubectl create secret generic my-secrets -n "$KUBE_NAMESPACE" --from-literal MY_SECRET=imverysecure +``` + +#### Part of deployment job[](#part-of-deployment-job "Permalink") + +您可以扩展`.gitlab-ci.yml`以在部署期间使用安全存储在 GitLab 项目下的[环境变量](../../../../ci/variables/README.html)来创建秘密. + +``` +deploy:function: + stage: deploy + environment: production + extends: .serverless:deploy:functions + before_script: + - kubectl create secret generic my-secret + --from-literal MY_SECRET="$GITLAB_SECRET_VARIABLE" + --namespace "$KUBE_NAMESPACE" + --dry-run -o yaml | kubectl apply -f - +``` + +### Running functions locally[](#running-functions-locally "Permalink") + +在本地运行功能是在开发过程中快速验证行为的好方法. + +在本地运行功能需要: + +* 转到 1.12 或更高版本. +* Docker Engine 已安装并正在运行. +* 使用 Go 软件包管理器安装的`gitlabktl` : + + ``` + GO111MODULE=on go get gitlab.com/gitlab-org/gitlabktl + ``` + +要在本地运行功能: + +1. 导航到您的 GitLab 无服务器项目的根目录. +2. 将功能构建到 Docker 映像中: + + ``` + gitlabktl serverless build + ``` + +3. 在 Docker 中运行您的函数: + + ``` + docker run -itp 8080:8080 + ``` + +4. 调用您的功能: + + ``` + curl http://localhost:8080 + ``` + +## Deploying Serverless applications[](#deploying-serverless-applications "Permalink") + +在 GitLab 11.5 中引入. + +无服务器应用程序是[无服务器功能](#deploying-functions)的替代[方法](#deploying-functions) . 它们在现有运行时不能满足应用程序需求的情况下很有用,例如以一种没有可用运行时的语言编写的应用程序. 请注意,尽管无服务器应用程序应该是无状态的! + +**注意:**您可以参考并导入示例[Knative Ruby 应用程序](https://gitlab.com/knative-examples/knative-ruby-app)以开始使用. + +将以下`.gitlab-ci.yml`添加到存储库的根目录中(如果您先前已经克隆了上述示例[Knative Ruby App,](https://gitlab.com/knative-examples/knative-ruby-app)则可以跳过此步骤): + +``` +include: + - template: Serverless.gitlab-ci.yml + +build: + extends: .serverless:build:image + +deploy: + extends: .serverless:deploy:image +``` + +`Serverless.gitlab-ci.yml`是允许自定义的模板. 您可以使用`include`参数导入它,并使用`extends`来自定义作业,或者可以通过在通过用户界面编辑`.gitlab-ci.yml`文件时从**Apply a template**下拉列表中选择它来内联整个模板. + +部署无服务器应用程序时,不需要`serverless.yml`文件. + +### Deploy the application with Knative[](#deploy-the-application-with-knative "Permalink") + +一切就绪后,下次运行 CI 管道时,将部署 Knative 应用程序. 导航到**CI / CD>管道** ,然后单击最新的管道. + +### Function details[](#function-details "Permalink") + +转到**操作>无服务器**页面以查看功能的最终 URL. + +[![function_details](img/4e0797b4100df465293bf0c8f24a097b.png)](img/function-list_v12_7.png) + +### Invocation metrics[](#invocation-metrics "Permalink") + +On the same page as above, click on one of the function rows to bring up the function details page. + +[![function_details](img/a0ea9fb503066a9bed377bc4dadb0d59.png)](img/function-details-loaded.png) + +容器数将为您提供在给定集群上运行无服务器功能实例的容器数. + +为了显示 Knative 函数调用, [必须安装 Prometheus](../index.html#installing-applications) . + +一旦安装了 Prometheus,可能会出现一条消息,指示度量标准数据*正在加载或当前不可用.* 它会在首次访问该页面时显示,但应在几秒钟后消失. 如果该消息没有消失,则可能是 GitLab 无法连接到集群上运行的 Prometheus 实例. + +## Configuring logging[](#configuring-logging "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33330) . + +### Prerequisites[](#prerequisites-1 "Permalink") + +* 由 GitLab 管理的集群. +* `kubectl`已安装并正在运行. + +在集群上运行`kubectl`命令需要首先设置对集群的访问权限. 对于在以下位置创建的集群: + +* GKE,请参阅[GKE 群集访问](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl) +* 其他平台,请参阅[安装和设置 kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) . + +### Enable request log template[](#enable-request-log-template "Permalink") + +运行以下命令以启用请求日志: + +``` +kubectl edit cm -n knative-serving config-observability +``` + +将`logging.request-log-template`从`data._example`字段复制到层次结构中上一层的数据字段. + +### Enable request logs[](#enable-request-logs "Permalink") + +运行以下命令以将 Elasticsearch,Kibana 和 Filebeat 安装到`kube-logging`命名空间中,并配置所有节点以使用 Filebeat 转发日志: + +``` +kubectl apply -f https://gitlab.com/gitlab-org/serverless/configurations/knative/raw/v0.7.0/kube-logging-filebeat.yaml +kubectl label nodes --all beta.kubernetes.io/filebeat-ready="true" +``` + +### Viewing request logs[](#viewing-request-logs "Permalink") + +要查看请求日志: + +1. Run `kubectl proxy`. +2. 导航到[Kibana UI](http://localhost:8001/api/v1/namespaces/kube-logging/services/kibana/proxy/app/kibana) . + +Or: + +1. 打开[Kibana UI](http://localhost:8001/api/v1/namespaces/kube-logging/services/kibana/proxy/app/kibana) . +2. 单击" **发现"** ,然后从左侧的下拉列表中选择`filebeat-*` . +3. 在搜索框中输入`kubernetes.container.name:"queue-proxy" AND message:/httpRequest/` . + +## Enabling TLS for Knative services[](#enabling-tls-for-knative-services "Permalink") + +默认情况下,将通过`http`提供 GitLab 无服务器部署. 为了通过`https`提供服务,您必须手动获取并安装 TLS 证书. + +完成此操作的最简单方法是使用[Certbot 手动获取 Let's Encrypt 证书](https://knative.dev/docs/serving/using-a-tls-cert/#using-certbot-to-manually-obtain-let-s-encrypt-certificates) . Certbot 是一个免费的开源软件工具,可用于在手动管理的网站上自动使用 Let's Encrypt 证书来启用 HTTPS. + +**注意:**以下说明与在安装了 Python 3 且不能在其他操作系统或其他版本的 Python 上运行的 Linux 服务器上安装和运行 Certbot 有关. + +1. 通过运行[`certbot-auto` wrapper 脚本](https://certbot.eff.org/docs/install.html#certbot-auto)安装 Certbot. 在服务器的命令行上,运行以下命令: + + ``` + wget https://dl.eff.org/certbot-auto + sudo mv certbot-auto /usr/local/bin/certbot-auto + sudo chown root /usr/local/bin/certbot-auto + sudo chmod 0755 /usr/local/bin/certbot-auto + /usr/local/bin/certbot-auto --help + ``` + + 要检查`certbot-auto`脚本的完整性,请运行: + + ``` + wget -N https://dl.eff.org/certbot-auto.asc + gpg2 --keyserver ipv4.pool.sks-keyservers.net --recv-key A2CFB51FA275A7286234E7B24D17C995CD9775F2 + gpg2 --trusted-key 4D17C995CD9775F2 --verify certbot-auto.asc /usr/local/bin/certbot-auto + ``` + + The output of the last command should look something like: + + ``` + gpg: Signature made Mon 10 Jun 2019 06:24:40 PM EDT + gpg: using RSA key A2CFB51FA275A7286234E7B24D17C995CD9775F2 + gpg: key 4D17C995CD9775F2 marked as ultimately trusted + gpg: checking the trustdb + gpg: marginals needed: 3 completes needed: 1 trust model: pgp + gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u + gpg: next trustdb check due at 2027-11-22 + gpg: Good signature from "Let's Encrypt Client Team " [ultimate] + ``` + +2. 运行以下命令以使用 Certbot 在授权过程中使用 DNS 质询来请求证书: + + ``` + /usr/local/bin/certbot-auto certonly --manual --preferred-challenges dns -d '*..example.com' + ``` + + 其中``是 GitLab 为您的无服务器项目创建的名称空间(由`--` ),而`example.com`是用于项目的域. 如果不确定项目的名称空间是什么,请导航至项目的" **操作">"无服务器"**页面,然后检查为功能/应用程序提供的端点. + + [![function_endpoint](img/70c613da170fdfd7665282f16becad56.png)](img/function-endpoint.png) + + 在上图中,项目的名称空间为`node-function-11909507` ,域为`knative.info` ,因此证书申请行如下所示: + + ``` + ./certbot-auto certonly --manual --preferred-challenges dns -d '*.node-function-11909507.knative.info' + ``` + + Certbot 工具将引导您完成通过在这些域中创建 TXT 记录来验证您拥有的每个域的步骤. 此过程完成后,输出应如下所示: + + ``` + IMPORTANT NOTES: + - Congratulations! Your certificate and chain have been saved at: + /etc/letsencrypt/live/namespace.example.com/fullchain.pem + Your key file has been saved at: + /etc/letsencrypt/live/namespace.example/privkey.pem + Your cert will expire on 2019-09-19\. To obtain a new or tweaked + version of this certificate in the future, simply run certbot-auto + again. To non-interactively renew *all* of your certificates, run + "certbot-auto renew" + -----BEGIN PRIVATE KEY----- + - Your account credentials have been saved in your Certbot + configuration directory at /etc/letsencrypt. You should make a + secure backup of this folder now. This configuration directory will + also contain certificates and private keys obtained by Certbot so + making regular backups of this folder is ideal. + ``` + +3. 创建证书和私钥文件. 使用 Certbot 返回的文件的内容,我们将创建两个文件以创建 Kubernetes 机密: + + 运行以下命令以查看`fullchain.pem`的内容: + + ``` + sudo cat /etc/letsencrypt/live/node-function-11909507.knative.info/fullchain.pem + ``` + + 输出应如下所示: + + ``` + -----BEGIN CERTIFICATE----- + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b4ag== + -----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + K2fcb195768c39e9a94cec2c2e30Qg== + -----END CERTIFICATE----- + ``` + + 创建一个名称为`cert.pem`的文件,其中包含整个输出的内容. + + 创建`cert.pem` ,运行以下命令以查看`privkey.pem`的内容: + + ``` + sudo cat /etc/letsencrypt/live/namespace.example/privkey.pem + ``` + + 输出应如下所示: + + ``` + -----BEGIN PRIVATE KEY----- + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + -----BEGIN CERTIFICATE----- + fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 4f294d1eaca42b8692017b4262== + -----END PRIVATE KEY----- + ``` + + 使用整个输出的内容创建一个名称为`cert.pk`的新文件. + +4. 创建一个 Kubernetes 机密以保存您的 TLS 证书`cert.pem`和私钥`cert.pk` : + + **注意:**在集群上运行`kubectl`命令需要首先设置对集群的访问. 对于在 GKE 上创建的集群,请参阅[GKE 集群访问](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl) . 对于其他平台, [请安装`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/) . + + ``` + kubectl create --namespace istio-system secret tls istio-ingressgateway-certs \ + --key cert.pk \ + --cert cert.pem + ``` + + 其中`cert.pem`和`cert.pk`是您的证书和私钥文件. 请注意, `istio-ingressgateway-certs`秘密名称是必需的. + +5. 配置 Knative 以使用为 HTTPS 连接创建的新密码. 运行以下命令以编辑方式打开 Knative 共享`gateway` : + + ``` + kubectl edit gateway knative-ingress-gateway --namespace knative-serving + ``` + + 更新网关以包括以下 tls:部分和配置: + + ``` + tls: + mode: SIMPLE + privateKey: /etc/istio/ingressgateway-certs/tls.key + serverCertificate: /etc/istio/ingressgateway-certs/tls.crt + ``` + + Example: + + ``` + apiVersion: networking.istio.io/v1alpha3 + kind: Gateway + metadata: + # ... skipped ... + spec: + selector: + istio: ingressgateway + servers: + - hosts: + - "*" + port: + name: http + number: 80 + protocol: HTTP + - hosts: + - "*" + port: + name: https + number: 443 + protocol: HTTPS + tls: + mode: SIMPLE + privateKey: /etc/istio/ingressgateway-certs/tls.key + serverCertificate: /etc/istio/ingressgateway-certs/tls.crt + ``` + + After your changes are running on your Knative cluster, you can begin using the HTTPS protocol for secure access your deployed Knative services. In the event a mistake is made during this process and you need to update the cert, you will need to edit the gateway `knative-ingress-gateway` to switch back to `PASSTHROUGH` mode. Once corrections are made, edit the file again so the gateway will use the new certificates. + +## Using an older version of `gitlabktl`[](#using-an-older-version-of-gitlabktl "Permalink") + +在某些情况下,您想运行旧版本的`gitlabktl` . 这需要在`.gitlab-ci.yml`文件中设置较旧版本的`gitlabktl`映像. + +要设置较旧的版本,请将`image:`添加到`functions:deploy`块中. 例如: + +``` +functions:deploy: + extends: .serverless:deploy:functions + environment: production + image: registry.gitlab.com/gitlab-org/gitlabktl:0.5.0 +``` + +通过更改注册表 URL 末尾的版本标签(格式为`registry.gitlab.com/gitlab-org/gitlabktl:`可以使用不同的版本. + +有关可用`gitlabktl`版本的完整清单,请参见`gitlabktl`项目的[容器注册表](https://gitlab.com/gitlab-org/gitlabktl/container_registry) . \ No newline at end of file diff --git a/_book/docs/031.md b/_book/docs/031.md new file mode 100644 index 0000000000000000000000000000000000000000..79a6a450c6dc9236e4416d505f47aa430d2839ab --- /dev/null +++ b/_book/docs/031.md @@ -0,0 +1,488 @@ +# Deploying AWS Lambda function using GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/serverless/aws.html](https://docs.gitlab.com/ee/user/project/clusters/serverless/aws.html) + +* [Serverless Framework](#serverless-framework) + * [Example](#example) + * [Steps](#steps) + * [Creating a Lambda handler function](#creating-a-lambda-handler-function) + * [Creating a `serverless.yml` file](#creating-a-serverlessyml-file) + * [Crafting the `.gitlab-ci.yml` file](#crafting-the-gitlab-ciyml-file) + * [Setting up your AWS credentials with your GitLab account](#setting-up-your-aws-credentials-with-your-gitlab-account) + * [Deploying your function](#deploying-your-function) + * [Manually testing your function](#manually-testing-your-function) + * [How To](#how-to) + * [Running function locally](#running-function-locally) + * [Secret variables](#secret-variables) + * [Setting up CORS](#setting-up-cors) + * [Writing automated tests](#writing-automated-tests) + * [Examples and template](#examples-and-template) +* [AWS Serverless Application Model](#aws-serverless-application-model) + * [Deploying AWS Lambda function using AWS SAM and GitLab CI/CD](#deploying-aws-lambda-function-using-aws-sam-and-gitlab-cicd) + * [Example](#example-1) + * [Steps](#steps-1) + * [Installing SAM CLI](#installing-sam-cli) + * [Creating an AWS SAM application using SAM CLI](#creating-an-aws-sam-application-using-sam-cli) + * [Setting up your AWS credentials with your GitLab account](#setting-up-your-aws-credentials-with-your-gitlab-account-1) + * [Crafting the `.gitlab-ci.yml` file](#crafting-the-gitlab-ciyml-file-1) + * [Deploying your application](#deploying-your-application) + * [Testing the deployed application](#testing-the-deployed-application) + * [Testing Locally](#testing-locally) + +# Deploying AWS Lambda function using GitLab CI/CD[](#deploying-aws-lambda-function-using-gitlab-cicd "Permalink") + +GitLab 允许用户轻松部署 AWS Lambda 函数并创建丰富的无服务器应用程序. + +GitLab 支持使用以下无服务器框架通过 GitLab CI / CD 部署 AWS Lambda 功能: + +* [Serverless Framework with AWS](#serverless-framework) +* [AWS’ Serverless Application Model (SAM)](#aws-serverless-application-model) + +## Serverless Framework[](#serverless-framework "Permalink") + +The [Serverless Framework can deploy to AWS](https://www.serverless.com/framework/docs/providers/aws/). + +我们准备了一个包含分步指南的示例,以创建一个简单功能并将其部署在 AWS 上. + +此外,在"操作方法["部分中](#how-to) ,您可以了解不同的用例,例如: + +* 在本地运行功能. +* 处理秘密. +* 设置 CORS. + +或者,您可以[使用 template](../../../../gitlab-basics/create-project.html#project-templates)快速[创建一个新项目](../../../../gitlab-basics/create-project.html#project-templates) . [`Serverless Framework/JS`模板](https://gitlab.com/gitlab-org/project-templates/serverless-framework/)已经包括下面描述的所有部分. + +### Example[](#example "Permalink") + +在以下示例中,您将: + +1. 创建一个基本的 AWS Lambda Node.js 函数. +2. 将该函数链接到 API Gateway `GET`端点. + +#### Steps[](#steps "Permalink") + +该示例包括以下步骤: + +1. 创建 Lambda 处理函数. +2. 创建一个`serverless.yml`文件. +3. 制作`.gitlab-ci.yml`文件. +4. 使用 GitLab 账户设置 AWS 凭证. +5. 部署您的功能. +6. 测试已部署的功能. + +让我们一步一步来. + +#### Creating a Lambda handler function[](#creating-a-lambda-handler-function "Permalink") + +您的 Lambda 函数将是请求的主要处理程序. 在这种情况下,我们将创建一个非常简单的 Node.js `hello`函数: + +``` +'use strict'; + +module.exports.hello = async event => { + return { + statusCode: 200, + body: JSON.stringify( + { + message: 'Your function executed successfully!' + }, + null, + 2 + ), + }; +}; +``` + +将此代码放在文件`src/handler.js` . + +`src`是无服务器功能的标准位置,但是您可以根据需要进行自定义. + +在我们的例子中, `module.exports.hello`定义了`hello` ,这将在以后的引用处理器`serverless.yml` + +您可以在此处了解有关 AWS Lambda Node.js 函数处理程序及其所有各种选项的更多信息: [https](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html) : [//docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html) + +#### Creating a `serverless.yml` file[](#creating-a-serverlessyml-file "Permalink") + +在项目的根目录中,创建一个`serverless.yml`文件,其中将包含 Serverless Framework 的配置详细信息. + +将以下代码放入文件中: + +``` +service: gitlab-example +provider: + name: aws + runtime: nodejs10.x + +functions: + hello: + handler: src/handler.hello + events: + - http: GET hello +``` + +我们的函数包含一个处理程序和一个事件. + +处理程序定义将使用位于`src/handler.hello`的源代码提供 Lambda 函数. + +`events`声明将创建一个 AWS API Gateway `GET`终端节点,以接收外部请求并将其通过服务集成传递给 Lambda 函数. + +您可以阅读有关无服务器框架的[可用属性和其他配置可能性](https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml/)的更多信息. + +#### Crafting the `.gitlab-ci.yml` file[](#crafting-the-gitlab-ciyml-file "Permalink") + +在项目根目录下的`.gitlab-ci.yml`文件中,放置以下代码: + +``` +image: node:latest + +stages: + - deploy + +production: + stage: deploy + before_script: + - npm config set prefix /usr/local + - npm install -g serverless + script: + - serverless deploy --stage production --verbose + environment: production +``` + +此示例代码执行以下操作: + +1. 对所有 GitLab CI / CD 版本使用`node:latest`映像 +2. The `deploy` stage: + * 安装无服务器框架. + * 使用上面定义的 AWS 凭证将无服务器功能部署到您的 AWS 账户. + +#### Setting up your AWS credentials with your GitLab account[](#setting-up-your-aws-credentials-with-your-gitlab-account "Permalink") + +为了与您的 AWS 账户进行交互,GitLab CI / CD 管道要求在您的 GitLab 设置中的**设置> CI / CD>变量**下定义`AWS_ACCESS_KEY_ID`和`AWS_SECRET_ACCESS_KEY` . 有关更多信息,请参见[在 UI 中创建自定义变量](../../../../ci/variables/README.html#create-a-custom-variable-in-the-ui) . + +**注意:**您提供的 AWS 凭证必须包括 IAM 策略,以提供对 AWS Lambda,API 网关,CloudFormation 和 IAM 资源的正确访问控制. + +#### Deploying your function[](#deploying-your-function "Permalink") + +`git push` the changes to your GitLab repository and the GitLab build pipeline will automatically deploy your function. + +在您的 GitLab 部署阶段日志中,将包含您的 AWS Lambda 端点 URL 的输出. 日志行将类似于以下内容: + +``` +endpoints: + GET - https://u768nzby1j.execute-api.us-east-1.amazonaws.com/production/hello +``` + +#### Manually testing your function[](#manually-testing-your-function "Permalink") + +运行以下`curl`命令将触发您的功能. + +**注意:**您的 URL 应该是从 GitLab 部署阶段日志中检索到的 URL. + +``` +curl https://u768nzby1j.execute-api.us-east-1.amazonaws.com/production/hello +``` + +那应该输出: + +``` +{ "message": "Your function executed successfully!" } +``` + +万岁! 现在,您已经通过 GitLab CI / CD 部署了 AWS Lambda 函数. + +干得好! + +### How To[](#how-to "Permalink") + +在本节中,我们向您展示如何在基本示例上构建以下内容: + +* 在本地运行该功能. +* 设置秘密变量. +* 设置 CORS. + +#### Running function locally[](#running-function-locally "Permalink") + +`serverless-offline`插件允许在本地运行代码. 要在本地运行代码: + +1. 将以下内容添加到您的`serverless.yml` : + + ``` + plugins: + - serverless-offline + ``` + +2. 通过运行以下命令来启动服务: + + ``` + serverless offline + ``` + +运行以下`curl`命令将触发您的功能. + +``` +curl http://localhost:3000/hello +``` + +它应该输出: + +``` +{ "message": "Your function executed successfully!" } +``` + +#### Secret variables[](#secret-variables "Permalink") + +Secrets are injected into your functions using environment variables. + +通过在`serverless.yml`的 provider 部分中定义变量,可以将它们添加到已部署函数的环境中: + +``` +provider: + ... + environment: + A_VARIABLE: ${env:A_VARIABLE} +``` + +从那里,您也可以在函数中引用它们. 请记住,在**设置> CI / CD>**变量下,将`A_VARIABLE`添加到您的 GitLab CI / CD 变量中,它将随您的函数一起被拾取和部署. + +**注意:**有权访问 AWS 环境的任何人都可以查看 lambda 定义中保留的那些变量的值. + +#### Setting up CORS[](#setting-up-cors "Permalink") + +如果您想要建立一个调用函数的网页,就像我们在[模板中](https://gitlab.com/gitlab-org/project-templates/serverless-framework/)所做的那样,则需要处理跨域资源共享(CORS). + +快速的方法来做到这一点是添加`cors: true`标志的 HTTP 端点在你`serverless.yml` : + +``` +functions: + hello: + handler: src/handler.hello + events: + - http: # Rewrite this part to enable CORS + path: hello + method: get + cors: true # <-- CORS here +``` + +您还需要在函数响应中返回 CORS 特定的标头: + +``` +'use strict'; + +module.exports.hello = async event => { + return { + statusCode: 200, + headers: { + // Uncomment the line below if you need access to cookies or authentication + // 'Access-Control-Allow-Credentials': true, + 'Access-Control-Allow-Origin': '*' + }, + body: JSON.stringify( + { + message: 'Your function executed successfully!' + }, + null, + 2 + ), + }; +}; +``` + +有关更多信息,请参阅由无服务器框架团队撰写的《 [您的 CORS 和 API 网关生存指南》](https://www.serverless.com/blog/cors-api-gateway-survival-guide/)博客文章. + +#### Writing automated tests[](#writing-automated-tests "Permalink") + +[无服务器框架](https://gitlab.com/gitlab-org/project-templates/serverless-framework/)示例项目展示了如何使用 Jest,Axios 和`serverless-offline`插件对本地和已部署的无服务器功能进行自动化测试. + +### Examples and template[](#examples-and-template "Permalink") + +示例代码可用: + +* 作为[可克隆的存储库](https://gitlab.com/gitlab-org/serverless/examples/serverless-framework-js) . +* 在带有[测试和秘密变量](https://gitlab.com/gitlab-org/project-templates/serverless-framework/)的版本中. + +您还可以在 GitLab UI 中使用[模板](../../../../gitlab-basics/create-project.html#project-templates) (基于带有测试和秘密变量的版本)(请参阅`Serverless Framework/JS`模板). + +## AWS Serverless Application Model[](#aws-serverless-application-model "Permalink") + +AWS 无服务器应用程序模型是用于构建无服务器应用程序的开源框架. 它使构建和部署无服务器应用程序变得更加容易. 有关更多详细信息,请参阅有关[AWS 无服务器应用程序模型的](https://docs.aws.amazon.com/serverless-application-model/) AWS 文档. + +### Deploying AWS Lambda function using AWS SAM and GitLab CI/CD[](#deploying-aws-lambda-function-using-aws-sam-and-gitlab-cicd "Permalink") + +GitLab 允许开发人员使用以下组合来构建和部署无服务器应用程序: + +* [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/). +* 亚搏体育 app CI / CD. + +### Example[](#example-1 "Permalink") + +在以下示例中,您将: + +* 安装 SAM CLI. +* 创建一个示例 SAM 应用程序,其中包括 Lambda 函数和 API 网关. +* 使用 GitLab CI / CD 将应用程序构建并部署到您的 AWS 账户. + +### Steps[](#steps-1 "Permalink") + +该示例包括以下步骤: + +1. 安装 SAM CLI. +2. 使用 SAM CLI 创建 AWS SAM 应用程序. +3. 制作`.gitlab-ci.yml`文件. +4. 使用 GitLab 账户设置 AWS 凭证. +5. 部署您的应用程序. +6. 测试已部署的功能. + +### Installing SAM CLI[](#installing-sam-cli "Permalink") + +AWS SAM 提供了一个称为 AWS SAM CLI 的 CLI,可简化创建和管理应用程序的过程. + +本文档中的某些步骤使用 SAM CLI. 请按照说明[安装 SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)来安装和配置 SAM CLI. + +如果您将[AWS Cloud9](https://aws.amazon.com/cloud9/)用作集成开发环境(IDE),则会为您安装以下软件: + +* [AWS Command Line Interface](https://docs.aws.amazon.com/en_pv/cli/latest/userguide/cli-chap-install.html) +* [SAM CLI](https://docs.aws.amazon.com/en_pv/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) +* [Docker](https://s0docs0docker0com.icopy.site/install/)和必要的 Docker 映像 + +### Creating an AWS SAM application using SAM CLI[](#creating-an-aws-sam-application-using-sam-cli "Permalink") + +要创建新的 AWS SAM 应用程序: + +1. 创建一个新的 GitLab 项目. +2. `git clone`将项目`git clone`到您的本地环境中. +3. 更改为新克隆的项目,并使用以下命令创建新的 SAM 应用程序: + + ``` + sam init -r python3.8 -n gitlabpoc --app-template "hello-world" + ``` + +4. `git push`应用程序`git push`回到 GitLab 项目. + +这将使用默认配置创建一个名为`gitlabpoc`的 SAM 应用程序,该配置是[Amazon API Gateway](https://aws.amazon.com/api-gateway/)端点调用的单个 Python 3.8 函数. 要查看 SAM 支持的其他运行时以及`sam init`选项,请运行: + +``` +sam init -h +``` + +### Setting up your AWS credentials with your GitLab account[](#setting-up-your-aws-credentials-with-your-gitlab-account-1 "Permalink") + +为了与您的 AWS 账户进行交互,GitLab CI / CD 管道要求在项目的 CI / CD 变量中同时设置`AWS_ACCESS_KEY_ID`和`AWS_SECRET_ACCESS_KEY` . + +设置这些: + +1. 导航到项目的 **设置> CI / CD** . +2. 展开**变量**部分,并为`AWS_ACCESS_KEY_ID`和`AWS_SECRET_ACCESS_KEY`创建条目. +3. 屏蔽凭据,以免使用"已**屏蔽"**切换将其显示在日志中. + +**注意:**您提供的 AWS 凭证必须包括 IAM 策略,以提供对 AWS Lambda,API 网关,CloudFormation 和 IAM 资源的正确访问控制. + +### Crafting the `.gitlab-ci.yml` file[](#crafting-the-gitlab-ciyml-file-1 "Permalink") + +在项目根目录中的[`.gitlab-ci.yml`](../../../../ci/yaml/README.html)文件中,添加以下内容,并将``替换为要在其中存储软件包的 S3 存储桶的名称: + +``` +image: python:latest + +stages: + - deploy + +production: + stage: deploy + before_script: + - pip3 install awscli --upgrade + - pip3 install aws-sam-cli --upgrade + script: + - sam build + - sam package --output-template-file packaged.yaml --s3-bucket + - sam deploy --template-file packaged.yaml --stack-name gitlabpoc --s3-bucket --capabilities CAPABILITY_IAM --region us-east-1 + environment: production +``` + +让我们更仔细地检查配置文件: + +* `image`指定用于此构建的 Docker 映像. 由于示例应用程序是用 Python 编写的,因此这是最新的 Python 图像. +* AWS CLI 和 AWS SAM CLI 安装在`before_script`部分中. +* SAM 构建,打包和部署命令用于构建,打包和部署应用程序. + +### Deploying your application[](#deploying-your-application "Permalink") + +Push changes to your GitLab repository and the GitLab build pipeline will automatically deploy your application. If your: + +* 构建和部署成功, [测试已部署的应用程序](#testing-the-deployed-application) . +* 生成失败,请查看生成日志以查看生成失败的原因. 构建可能会失败的一些常见原因是: + + * 不兼容的软件版本. 例如,Python 运行时版本可能与构建计算机上的 Python 不同. 通过安装所需的软件版本来解决此问题. + * 您可能无法从 GitLab 访问您的 AWS 账户. 检查您使用 AWS 凭证设置的环境变量. + * 您可能没有权限部署无服务器应用程序. 确保提供了部署无服务器应用程序所需的所有权限. + +### Testing the deployed application[](#testing-the-deployed-application "Permalink") + +要测试您部署的应用程序,请转到构建日志,然后执行以下步骤: + +1. 点击右上角的"显示完整的原始数据": + + [![sam-complete-raw](img/fd24d5842b589870b2063edaca149511.png)](img/sam-complete-raw.png) + +2. 查找 HelloWorldApi –与以下所示类似的 API 网关端点: + + [![sam-api-endpoint](img/5dd66b504685d06e7b88c8f8a71d39ba.png)](img/sam-api-endpoint.png) + +3. 使用 curl 测试 API. 例如: + + ``` + curl https://py4rg7qtlg.execute-api.us-east-1.amazonaws.com/Prod/hello/ + ``` + +输出应为: + +``` +{"message": "hello world"} +``` + +### Testing Locally[](#testing-locally "Permalink") + +AWS SAM 提供了在本地测试应用程序的功能. 您必须在本地安装 AWS SAM CLI,才能在本地进行测试. + +首先,测试功能. + +SAM 在`events/event.json`中提供一个默认事件,其中包括以下消息主体: + +``` +{\"message\": \"hello world\"} +``` + +如果您将该事件传递给`HelloWorldFunction` ,则它应该以相同的主体响应. + +通过运行以下命令来调用该函数: + +``` +sam local invoke HelloWorldFunction -e events/event.json +``` + +输出应为: + +``` +{"message": "hello world"} +``` + +确认 Lambda 函数按预期工作后,请按照以下步骤测试 API 网关. + +通过运行以下命令在本地启动 API: + +``` +sam local start-api +``` + +SAM 再次启动 Docker 容器,这一次是在`localhost:3000`上侦听的模拟 Amazon API Gateway. + +通过运行以下命令来调用`hello` API: + +``` +curl http://127.0.0.1:3000/hello +``` + +再次输出应为: + +``` +{"message": "hello world"} +``` \ No newline at end of file diff --git a/_book/docs/032.md b/_book/docs/032.md new file mode 100644 index 0000000000000000000000000000000000000000..172ec4d47766aaccad586bd350b46920483bb91a --- /dev/null +++ b/_book/docs/032.md @@ -0,0 +1,101 @@ +# Securing your deployed applications + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/securing.html](https://docs.gitlab.com/ee/user/project/clusters/securing.html) + +* [Overview](#overview) + * [Requirements](#requirements) + * [Understanding how GitLab Managed Apps are installed](#understanding-how-gitlab-managed-apps-are-installed) +* [Connect the cluster to GitLab](#connect-the-cluster-to-gitlab) +* [Set up a GitLab Runner](#set-up-a-gitlab-runner) +* [Create a Cluster Management Project](#create-a-cluster-management-project) +* [Install GitLab Container Network Policy](#install-gitlab-container-network-policy) +* [Install GitLab Container Host Security](#install-gitlab-container-host-security) + +# Securing your deployed applications[](#securing-your-deployed-applications "Permalink") + +使用 GitLab 可以轻松保护在[连接的 Kubernetes 集群中](index.html)部署的应用程序的安全. 您可以从[Web 应用程序防火墙](../../../topics/web_application_firewall/quick_start_guide.html) , [网络策略](../../../topics/autodevops/stages.html#network-policy)甚至[容器主机安全性](../../clusters/applications.html#install-falco-using-gitlab-cicd)的保护中受益. + +无论您的应用程序是否通过 GitLab CI / CD 进行部署,此页面均包含将群集连接到 GitLab 并安装这些功能的完整的端到端步骤和说明. 如果您使用[Auto DevOps](../../../topics/autodevops/index.html)与 GitLab 一起构建和部署您的应用程序,请参见上面有关[GitLab 托管应用程序](../../clusters/applications.html)的文档. + +## Overview[](#overview "Permalink") + +在较高级别,所需步骤包括以下步骤: + +* 将集群连接到 GitLab. +* 设置一个或多个跑步者. +* 设置集群管理项目. +* 安装 Web 应用程序防火墙,网络策略和/或容器主机安全性. +* 安装 Prometheus,以在[威胁监视](../../application_security/threat_monitoring/)仪表板中获取统计信息和指标. + +### Requirements[](#requirements "Permalink") + +最低要求(取决于您要安装的 GitLab 管理应用程序): + +* 您的群集已连接到 GitLab(ModSecurity,Cilium 和 Falco). +* 至少安装了一个 GitLab Runner(仅限 Cilium 和 Falco). + +### Understanding how GitLab Managed Apps are installed[](#understanding-how-gitlab-managed-apps-are-installed "Permalink") + +**注意:**为简单起见,这些图使用术语*Kubernetes* . 实际上,Sidekiq 连接到在集群中的 Pod 中运行的 Helm Tiller 守护程序. + +您可以通过一键式安装过程从 GitLab Web 界面安装 GitLab 托管应用程序. GitLab 使用 Sidekiq(后台处理服务)来简化此过程. + +sequenceDiagram 自动编号 GitLab->> + Sidekiq:安装 GitLab 托管应用程序 Sidekiq->> + Kubernetes:Helm 安装 Kubernetes->>-Sidekiq:安装完成 Sidekiq->>-GitLab:刷新 UI + +尽管此安装方法比较容易,因为它是用户界面中的"点击"操作,但它不灵活且难以调试. 当出现问题时,您将看不到部署日志. Web 应用程序防火墙功能使用此安装方法. + +但是,下一代的 GitLab 托管应用程序 V2( [基于 CI / CD 的 GitLab 托管应用程序](https://gitlab.com/groups/gitlab-org/-/epics/2103) )不使用 Sidekiq 进行部署. 所有应用程序都使用 GitLab CI / CD 管道以及因此使用的 GitLab Runners 进行部署. + +sequenceDiagram 自动编号 GitLab->> + GitLab:触发管道 GitLab->> + Runner:运行部署作业 Runner->> + Kubernetes:Helm 安装 Kubernetes->>-Runner:安装完成 Runner->>-GitLab:报告工作状态和更新流程 + +调试更容易,因为您可以访问这些作业的原始日志(在失败的情况下,可以将 Helm Tiller 输出作为工件使用),并且灵活性要好得多. 由于这些部署仅在管道正在运行时触发(很可能在集群管理存储库中有新提交时才触发),因此每个操作都具有书面记录,并遵循经典的合并请求工作流程(批准,合并,部署). 网络模型(Cilium)托管的应用程序和容器主机安全性(Falco)都使用此模型进行部署. + +## Connect the cluster to GitLab[](#connect-the-cluster-to-gitlab "Permalink") + +要将 GitLab 托管应用程序部署到群集,必须首先[将群集添加](add_remove_clusters.html)到 GitLab. 然后从项目或组 Kubernetes 页面[安装](../../clusters/applications.html#installing-applications) Web 应用程序防火墙. + +请注意,您的项目不必通过 GitLab 托管或部署. 您可以独立于使用群集的应用程序来管理群集. + +## Set up a GitLab Runner[](#set-up-a-gitlab-runner "Permalink") + +要安装基于 CI / CD 的 GitLab 托管应用程序,必须在 GitLab 中运行使用 GitLab Runner 的管道. 您可以在上一步中添加的 Kubernetes 集群中[安装 GitLab 运行程序](../../clusters/applications.html#gitlab-runner) ,或者如果使用的是 GitLab.com,则可以使用 GitLab 提供的共享运行程序之一. + +将群集连接到 GitLab 并安装好 GitLab Runner 之后,您可以继续执行下一步,并开始安装 Cilium 和 Falco GitLab 托管应用程序以保护托管在此群集上的应用程序. + +## Create a Cluster Management Project[](#create-a-cluster-management-project "Permalink") + +[群集管理项目](../../clusters/management_project.html)是一个 GitLab 项目,其中包含一个`.gitlab-ci.yml`文件,用于将 GitLab 托管应用程序部署到您的群集中. 该项目使用 Kubernetes [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)特权运行所需的图表. + +该项目的创建与其他任何 GitLab 项目一样开始. 使用一个空项目,并在根目录下添加一个`gitlab-ci.yml`文件,其中包含以下模板: + +``` +include: + - template: Managed-Cluster-Applications.gitlab-ci.yml +``` + +要使该项目成为集群管理项目,请遵循以下[说明](../../clusters/management_project.html#selecting-a-cluster-management-project) . 即使您的应用程序未托管在 GitLab 上,也可以这样指定该项目. 在这种情况下,请创建一个新的空项目,您可以在其中选择新创建的集群管理项目. + +## Install GitLab Container Network Policy[](#install-gitlab-container-network-policy "Permalink") + +GitLab 容器网络策略基于[Cilium](https://cilium.io/) . 要安装 Cilium GitLab 托管应用程序,请将`.gitlab/managed-apps/config.yaml`文件添加到群集管理项目中: + +``` +# possible values are gke, eks or you can leave it blank +clusterType: gke + +cilium: + installed: true +``` + +您的应用程序不必由 GitLab 进行管理或部署即可利用此功能. [阅读](../../clusters/applications.html#install-cilium-using-gitlab-cicd)有关配置容器网络策略的[更多](../../clusters/applications.html#install-cilium-using-gitlab-cicd)信息. + +## Install GitLab Container Host Security[](#install-gitlab-container-host-security "Permalink") + +同样,您可以在`.gitlab/managed-apps/config.yaml`基于[Falco](https://falco.org/)安装 Container Host Security: + +``` +falco: + installed: true +``` + +[阅读](../../clusters/applications.html#install-falco-using-gitlab-cicd)有关配置容器主机安全性的[更多](../../clusters/applications.html#install-falco-using-gitlab-cicd)信息. \ No newline at end of file diff --git a/_book/docs/033.md b/_book/docs/033.md new file mode 100644 index 0000000000000000000000000000000000000000..1d21fad79812ce8e6179ba1acb3cd4a78abd23e3 --- /dev/null +++ b/_book/docs/033.md @@ -0,0 +1,687 @@ +# Groups + +> 原文:[https://docs.gitlab.com/ee/user/group/](https://docs.gitlab.com/ee/user/group/) + +* [Use cases](#use-cases) +* [Namespaces](#namespaces) +* [Issues and merge requests within a group](#issues-and-merge-requests-within-a-group) + * [Bulk editing issues and merge requests](#bulk-editing-issues-and-merge-requests) +* [Create a new group](#create-a-new-group) +* [Add users to a group](#add-users-to-a-group) +* [Request access to a group](#request-access-to-a-group) +* [Changing the owner of a group](#changing-the-owner-of-a-group) +* [Remove a member from the group](#remove-a-member-from-the-group) +* [Changing the default branch protection of a group](#changing-the-default-branch-protection-of-a-group) +* [Add projects to a group](#add-projects-to-a-group) + * [Default project-creation level](#default-project-creation-level) +* [View group details](#view-group-details) + * [Group activity analytics overview](#group-activity-analytics-overview) +* [View group activity](#view-group-activity) +* [Transfer projects into groups](#transfer-projects-into-groups) +* [Sharing a project with a group](#sharing-a-project-with-a-group) +* [Sharing a group with another group](#sharing-a-group-with-another-group) +* [Manage group memberships via LDAP](#manage-group-memberships-via-ldap) + * [Creating group links via CN](#creating-group-links-via-cn-starter-only) + * [Creating group links via filter](#creating-group-links-via-filter-premium-only) + * [Overriding user permissions](#overriding-user-permissions-starter-only) +* [Epics](#epics-ultimate) +* [Group Security Dashboard](#group-security-dashboard-ultimate) +* [Insights](#insights-ultimate) +* [Transferring groups](#transferring-groups) +* [Group settings](#group-settings) + * [General settings](#general-settings) + * [Changing a group’s path](#changing-a-groups-path) + * [Remove a group](#remove-a-group) + * [Restore a group](#restore-a-group-premium) + * [Enforce 2FA to group members](#enforce-2fa-to-group-members) + * [Share with group lock](#share-with-group-lock) + * [Member Lock](#member-lock-starter) + * [IP access restriction](#ip-access-restriction-premium) + * [Allowed domain restriction](#allowed-domain-restriction-premium) + * [Group file templates](#group-file-templates-premium) + * [Group-level project templates](#group-level-project-templates-premium) + * [Disabling email notifications](#disabling-email-notifications) + * [Disabling group mentions](#disabling-group-mentions) + * [Enabling delayed Project removal](#enabling-delayed-project-removal-premium) + * [Advanced settings](#advanced-settings) + * [Storage usage quota](#storage-usage-quota-starter) + * [Group push rules](#group-push-rules-starter) + * [Enabling the feature](#enabling-the-feature) + * [Maximum artifacts size](#maximum-artifacts-size-core-only) +* [User contribution analysis](#user-contribution-analysis-starter) +* [Issues analytics](#issues-analytics-premium) +* [Dependency Proxy](#dependency-proxy-premium) + +# Groups[](#groups "Permalink") + +使用 GitLab 组,您可以: + +* 将相关项目组装在一起. +* 授予成员一次访问多个项目的权限. + +有关 GitLab 组的视频介绍,请参见[GitLab 大学:存储库,项目和组](https://www.youtube.com/watch?v=4TWfh1aKHHw) . + +组也可以嵌套在[子组中](subgroups/index.html) . + +通过单击顶部导航中的**组>您的组**来找到您的组. + +[![GitLab Groups](img/53bcd8c2d2c69aceb7db6677802be6b1.png)](img/groups.png) + +[GitLab 11.1](https://about.gitlab.com/releases/2018/07/22/gitlab-11-1-released/#groups-dropdown-in-navigation)中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36234)了顶部导航中的" **组"**下拉列表. + +" **组"**页面显示: + +* 选择**您的组**后, **您将**是**您**所属的所有组. +* 选中" **浏览公共组"**时的公共组列表. + +" **组"**页面上的每个组都列出了: + +* 它有多少个子组. +* 它包含多少个项目. +* 该组有多少个成员,不包括从父组继承的成员. +* 小组的知名度. +* 如果您具有足够的权限,则指向组设置的链接. +* 如果您是成员,则退出该组的链接. + +## Use cases[](#use-cases "Permalink") + +您可以出于多种原因创建组. 列举几个: + +* 通过在同一[名称空间](#namespaces)下组织相关项目并将成员添加到顶级组,可以以较少的步骤授予对多个项目和多个团队成员的访问权限. +* 通过创建小组并包括适当的成员,可以轻松地`@mention`所有团队中的问题并合并请求. + +例如,您可以为公司成员创建一个[组](subgroups/index.html) ,并为每个单独的团队创建一个[子](subgroups/index.html)组. 假设您创建了一个名为`company-team` ,并且在该组中为各个团队`backend-team` , `frontend-team`和`production-team`创建了子组. + +* 从问题开始新的实现时,请添加评论: *" `@company-team` ,让我们开始吧!* *`@company-team/backend-team`您很高兴!"* +* 当您的后端团队需要前端提供帮助时,他们会添加一条评论: *" `@company-team/frontend-team`您能在这里帮助我们吗?"* +* 前端团队完成实施后,他们会评论: *" `@company-team/backend-team` ,它已经完成!* *让我们将其运送到`@company-team/production-team` !* + +## Namespaces[](#namespaces "Permalink") + +在 GitLab 中,名称空间是用作用户名,组名或子组名的唯一名称. + +* `http://gitlab.example.com/username` +* `http://gitlab.example.com/groupname` +* `http://gitlab.example.com/groupname/subgroup_name` + +例如,考虑一个名为 Alex 的用户: + +1. Alex 在 GitLab.com 上使用用户名`alex`创建了一个帐户; 他们的个人资料将在`https://gitlab.example.com/alex`下访问 +2. Alex 为他们的团队创建了一个小组,小组名称为`alex-team` ; 该小组及其项目将在`https://gitlab.example.com/alex-team`下访问 +3. 亚历克斯(Alex)创建了一个亚历克斯小组( `alex-team`子`alex-team` ,其子小组名称为`marketing` ; 该子小组及其项目将在`https://gitlab.example.com/alex-team/marketing`下访问 + +通过这样做: + +* 任何团队成员都使用`@alex`提及 Alex +* 亚历克斯通过`@alex-team`提及了团队中的每个人 +* 亚历克斯只提及`@alex-team/marketing` + +## Issues and merge requests within a group[](#issues-and-merge-requests-within-a-group "Permalink") + +问题和合并请求是项目的一部分. 对于给定的组,您可以在单个列表视图中查看所有[问题](../project/issues/index.html#issues-list)并将该组中所有项目的[请求合并](../project/merge_requests/reviewing_and_managing_merge_requests.html#view-merge-requests-for-all-projects-in-a-group)在一起. + +### Bulk editing issues and merge requests[](#bulk-editing-issues-and-merge-requests "Permalink") + +有关详细信息,请参阅[批量编辑问题和合并请求](../group/bulk_editing/index.html) . + +## Create a new group[](#create-a-new-group "Permalink") + +> 有关不允许用作组名的单词列表,请参见[保留名称](../reserved_names.html) . + +要创建新组,请执行以下任一操作: + +* 在顶部菜单中,依次单击" **组"**和" **您的组"** ,然后单击绿色按钮" **新建组"** . + + [![new group from groups page](img/7e5039b0d8fb74c5ea813e354f23493e.png)](img/new_group_from_groups.png) + +* 或者,在顶部菜单中,展开`plus`号并选择**新建组** . + + [![new group from elsewhere](img/ee8ead7652026dd03a75e2551122350f.png)](img/new_group_from_other_pages.png) + +添加以下信息: + +[![new group information](img/ad2cdacdd36348cddf7d5c19d8940d5b.png)](img/create_new_group_info.png) + +1. **组名将**自动填充 URL. (可选)您可以更改它. 这是在组视图中显示的名称. 该名称只能包含: + * 字母数字字符 + * 下划线 + * 划线和点 + * 空间 +2. **组 URL**是将托管项目的名称空间. 该网址只能包含: + * 字母数字字符 + * 下划线 + * 破折号和点(不能以破折号开头或以点结尾) +3. (可选)您可以添加简短说明,以告诉其他人该组的内容. +4. (可选)为您的群组选择一个头像. +5. Choose the [visibility level](../../public_access/public_access.html). + +有关创建组的更多详细信息,请观看视频[GitLab 命名空间(用户,组和子组)](https://youtu.be/r0sJgjR2f5A) . + +## Add users to a group[](#add-users-to-a-group "Permalink") + +将多个项目放在一个组中的好处是,您可以通过一个操作就授予用户访问该组中所有项目的权限. + +通过导航到组的仪表板并单击**Members**将成员添加到组. + +[![add members to group](img/ece990045e1a7ae1237b5f2912a2df3e.png)](img/add_new_members.png) + +选择[权限级别](../permissions.html#permissions) ,然后添加新成员. 您还可以设置该用户的到期日期. 这是他们将不再有权访问您的网上论坛的日期. + +考虑一个有两个项目的小组: + +* 现在,在" **组成员"**页面上,可以将新用户添加到组中. +* 现在,由于该用户是该组的**开发人员**成员,因此他们自动获得**开发人员**对该组内**所有项目的**访问权限. + +要提高特定项目的现有用户的访问级别,请将其作为新成员再次添加到具有所需权限级别的项目中. + +## Request access to a group[](#request-access-to-a-group "Permalink") + +作为论坛所有者,您可以启用或禁用非会员请求访问您论坛的功能. 转到组设置,然后单击**允许用户请求访问权限** . + +作为用户,如果启用了该设置,则可以请求成为组的成员. 转到您要加入的组,然后单击屏幕右侧的" **请求访问**权"按钮. + +[![Request access button](img/aa2dd1694d7e1573bbd49200ed1ccb04.png)](img/request_access_button.png) + +请求访问后: + +* 通过电子邮件将多达十个群组所有者的通知通知您. 电子邮件将发送给最近活动的组所有者. +* 任何论坛所有者都可以在会员页面上批准或拒绝您的请求. + +[![Manage access requests](img/fd0991d7941fed77c4d82bd219ec713b.png)](img/access_requests_management.png) + +如果您在批准请求之前改变主意,只需单击" **撤回访问请求"**按钮. + +[![Withdraw access request button](img/a6d5e94df0d5d50038a0909603d69933.png)](img/withdraw_access_request_button.png) + +## Changing the owner of a group[](#changing-the-owner-of-a-group "Permalink") + +Ownership of a group means at least one of its members has [Owner permission](../permissions.html#group-members-permissions). Groups must have at least one owner. + +可以只更改一个所有者的组所有者. 更改组的唯一所有者: + +* 作为管理员: + 1. 前往小组的 **成员**选项卡. + 2. 赋予其他成员**所有者**权限. + 3. 刷新页面. 现在,您可以从原始所有者中删除**所有者**权限. +* 作为当前组的所有者: + 1. 前往小组的 **成员**选项卡. + 2. 赋予其他成员**所有者**权限. + 3. 让新的所有者登录并从您中删除**所有者**权限. + +## Remove a member from the group[](#remove-a-member-from-the-group "Permalink") + +只有[拥有所有者](../permissions.html#group-members-permissions)权限的[用户](../permissions.html#group-members-permissions)才能管理组成员. + +如果给定成员在该组中具有直接成员资格,则可以从该组中删除该成员. 如果成员资格是从父组继承的,则该成员只能从父组本身中删除. + +删除成员时,您可以决定是从所有问题中取消分配用户,还是合并当前已分配的请求,还是保留分配. + +* 当用户离开私人组并且您希望撤消他们对所有问题的访问并分配他们的合并请求时,从所有问题和合并请求中**取消分配已删除的成员**可能会有所帮助. +* **保留问题和合并请求的分配**可能对于接受公共贡献的组很有帮助,在这些组中,用户不必是成员就可以为问题和合并请求做出贡献. + +要从组中删除成员: + +1. 在一个小组中,转到 **成员们** . +2. 点击**删除** 要删除的群组成员旁边的按钮. 出现" **删除成员"**模态. +3. (可选)选中" **也从相关问题中取消分配此用户并合并请求"**复选框. +4. Click **删除会员**. + +## Changing the default branch protection of a group[](#changing-the-default-branch-protection-of-a-group "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7583) . + +默认情况下,每个组都继承全局级别的分支保护集. + +要为特定组更改此设置: + +1. 前往小组的 **设置>常规**页面. +2. 展开" **权限,LFS,2FA"**部分. +3. 在" **默认分支保护"**下拉列表中选择所需的选项. +4. Click **保存更改**. + +要全局更改此设置,请参阅[默认分支保护](../admin_area/settings/visibility_and_access_controls.html#default-branch-protection) . + +**注意:**在[GitLab Premium 或更高版本中](https://about.gitlab.com/pricing/) ,GitLab 管理员可以选择[禁止组所有者更新默认的分支保护](../admin_area/settings/visibility_and_access_controls.html#disable-group-owners-from-updating-default-branch-protection-premium-only) . + +## Add projects to a group[](#add-projects-to-a-group "Permalink") + +有两种方法可以将新项目添加到组中: + +* 选择一个组,然后单击" **新建项目"** . 然后,您可以继续[创建您的项目](../../gitlab-basics/create-project.html) . + + [![New project](img/ef67d77909a856277f9f2821fa0c18ea.png)](img/create_new_project_from_group.png) + +* 在创建项目时,请从下拉菜单中选择已经创建的组名称空间. + + [![Select group](img/674c1579957cca4a644bc90fb8fbb2f3.png)](img/select_group_dropdown.png) + +### Default project-creation level[](#default-project-creation-level "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/2534) . +* 在 10.7 中带到[GitLab Starter](https://about.gitlab.com/pricing/) . +* 在 11.10 中[移至](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25975) [GitLab Core](https://about.gitlab.com/pricing/) . + +默认情况下, [开发人员和维护人员](../permissions.html#group-members-permissions)可以在一个组下创建项目. + +要为特定组更改此设置: + +1. 转到论坛的**设置>常规**页面. +2. 展开" **权限,LFS,2FA"**部分. +3. 在" **允许创建项目"**下拉列表中选择所需的选项. +4. Click **保存更改**. + +要全局更改此设置,请参阅[默认项目创建保护](../admin_area/settings/visibility_and_access_controls.html#default-project-creation-protection) . + +## View group details[](#view-group-details "Permalink") + +组的" **详细信息"**页面包含以下选项卡: + +* 小组和项目. +* 共享的项目. +* 存档的项目. + +### Group activity analytics overview[](#group-activity-analytics-overview "Permalink") + +版本历史 + +* 在 GitLab [Starter](https://about.gitlab.com/pricing/) 12.10 中作为[测试版功能](https://about.gitlab.com/handbook/product/#beta) [引入](https://gitlab.com/gitlab-org/gitlab/-/issues/207164) + +组详细信息视图还显示最近 90 天内创建的以下项目数: + +* 合并请求. +* Issues. +* Members. + +可以使用`group_activity_analytics` [功能标记](../../development/feature_flags/development.html#enabling-a-feature-flag-in-development)启用这些组活动分析. + +[![Recent Group Activity](img/645965e7ebb61697ff42cc06214ca5af.png)](img/group_activity_analytics_v12_10.png) + +有关详细信息,请参阅有关如何[查看组活动的部分](#view-group-activity) . + +## View group activity[](#view-group-activity "Permalink") + +群组的" **活动"**页面显示群组中最近执行的操作,包括: + +* **推送事件** :最近推送到分支. +* **合并事件** :最近合并. +* **发行事件** :已发行或已关闭的发行. +* **史诗般的事件** :史诗集开启或关闭. +* **评论** :评论已打开或关闭. +* **小组** :已加入或离开小组的小组成员. +* **Wiki** :创建,删除或更新的 Wiki. + +单击**RSS**图标,还可以 Atom 格式获得整个活动供稿. + +要查看论坛的" **活动"**页面,请执行以下操作: + +1. 转到论坛的页面. +2. 在左侧导航菜单中,转到" **组概述",**然后选择" **活动"** . + +## Transfer projects into groups[](#transfer-projects-into-groups "Permalink") + +了解如何[将项目转移到小组中](../project/settings/index.html#transferring-an-existing-project-into-another-namespace) . + +## Sharing a project with a group[](#sharing-a-project-with-a-group "Permalink") + +您可以[与一个小组共享您的项目,](../project/members/share_project_with_groups.html)并向所有小组成员立即授予对该项目的访问权限. + +或者,您可以[锁定共享与组功能](#share-with-group-lock) . + +## Sharing a group with another group[](#sharing-a-group-with-another-group "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/18328) . + +与[与组共享项目](#sharing-a-project-with-a-group)类似,您可以与另一个组共享一个组,以使直接的组成员可以访问共享的组. 这对于继承的成员无效. + +要将给定的组(例如"前端")与另一个组(例如"工程")共享: + +1. 导航到"前端"群组页面,然后使用左侧的导航菜单转到群组" **成员"** . +2. Select the **邀请小组** tab. +3. 以您选择的最大访问权限级别添加"工程". +4. Click **Invite**. + +"工程"组的所有成员将被添加到"前端". + +## Manage group memberships via LDAP[](#manage-group-memberships-via-ldap "Permalink") + +组同步允许将 LDAP 组映射到 GitLab 组. 这样可以更好地控制每组用户的管理. 要配置组同步,请编辑`group_base` **DN** ( `'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org'` ). 该**OU**包含将与 GitLab 组关联的所有组. + +可以使用 CN 或过滤器创建组链接. 这些组链接在**组设置-> LDAP 同步**页面上创建. 配置链接后,用户可能需要一个多小时才能与 GitLab 组进行同步. + +有关 LDAP 和组同步管理的更多信息,请参阅[LDAP 主文档](../../administration/auth/ldap/index.html#group-sync-starter-only) . + +**注意:**如果在添加 LDAP 同步时 LDAP 用户是组成员,并且它们不属于 LDAP 组,则将从该组中将其删除. + +### Creating group links via CN[](#creating-group-links-via-cn-starter-only "Permalink") + +通过 CN 创建群组链接: + +1. 选择**LDAP 服务器**作为链接. +2. 选择`LDAP Group cn`作为**同步方法** . +3. 在" **LDAP 组 cn"**文本输入框中,开始输入组的 CN. 在配置的`group_base`中将有一个带有匹配 CN 的下拉菜单. 从此列表中选择您的 CN. +4. 在" **LDAP 访问"**部分中,选择在该组中同步的用户的[权限级别](../permissions.html) . +5. 单击`Add Synchronization`按钮以保存该组链接. + +[![Creating group links via CN](img/5d200a6bcc883fcfa57dac51301bc2e3.png)](img/ldap_sync_cn_v13_1.png) + +### Creating group links via filter[](#creating-group-links-via-filter-premium-only "Permalink") + +通过过滤器创建组链接: + +1. 选择**LDAP 服务器**作为链接. +2. 选择`LDAP user filter`作为**Sync 方法** . +3. 在" **LDAP 用户"过滤器**框中输入过滤**器** . 请遵循[有关用户过滤器](../../administration/auth/ldap/index.html#set-up-ldap-user-filter-core-only)的[文档](../../administration/auth/ldap/index.html#set-up-ldap-user-filter-core-only) . +4. 在" **LDAP 访问"**部分中,选择在该组中同步的用户的[权限级别](../permissions.html) . +5. 单击`Add Synchronization`按钮以保存该组链接. + +[![Creating group links via filter](img/5b8558c08a5996468dcd0d1a119ac76b.png)](img/ldap_sync_filter_v13_1.png) + +### Overriding user permissions[](#overriding-user-permissions-starter-only "Permalink") + +从 GitLab [v8.15 开始,](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/822) LDAP 用户权限现在可以由管理员用户手动覆盖. 覆盖用户的权限: + +1. 转到您小组的" **成员"**页面. +2. 在您要编辑的用户的行中选择铅笔图标. +3. 选择橙色的`Change permissions`按钮. + +[![Setting manual permissions](img/c6273de0eb8e4c8e7750113a7a66e7d6.png)](img/manual_permissions_v13_1.png) + +现在,您将能够从" **成员"**页面编辑用户的权限. + +## Epics[](#epics-ultimate "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.2 中引入. + +Epics 通过跟踪跨项目和里程碑共享主题的问题组,使您可以更有效,更轻松地管理项目组合. + +[Learn more about Epics.](epics/index.html) + +## Group Security Dashboard[](#group-security-dashboard-ultimate "Permalink") + +概述组及其子组中所有项目的漏洞. + +[Learn more about the Group Security Dashboard.](security_dashboard/index.html) + +## Insights[](#insights-ultimate "Permalink") + +[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. + +配置对您的组或项目重要的见解,使用户可以浏览以下数据: + +* 分诊卫生 +* 在给定期间内创建/关闭的问题 +* 合并请求的平均合并时间 +* 多得多 + +[Learn more about Insights](insights/index.html). + +## Transferring groups[](#transferring-groups "Permalink") + +在 GitLab 10.5 中,您可以通过以下方式转移组: + +* 将子组转移到新的父组. +* 通过将顶级组转移到所需的组,将其转换为子组. +* Convert a subgroup into a top-level group by transferring it out of its current group. + +转移群组时,请注意: + +* 更改组的父母可能会产生意想不到的副作用. 请参阅[更改存储库路径时的重定向](../project/index.html#redirects-when-changing-repository-paths) . +* 您只能将群组转移到您管理的群组中. +* 您必须更新本地存储库以指向新位置. +* If the immediate parent group’s visibility is lower than the group’s current visibility, visibility levels for subgroups and projects will change to match the new parent group’s visibility. +* 仅传输显式组成员身份,不继承继承成员身份. 如果组的所有者仅继承了成员身份,则该组将没有所有者. 在这种情况下,转移组的用户将成为该组的所有者. + +## Group settings[](#group-settings "Permalink") + +创建群组后,您可以导航至该群组的信息中心,然后点击**设置**来管理其设置. + +[![group settings](img/b98f1bb6205ce5c692946b81e8c78003.png)](img/group_settings.png) + +### General settings[](#general-settings "Permalink") + +除了编辑您在[创建组](#create-a-new-group)时先前设置的任何设置之外,您还可以访问[该组的](#create-a-new-group)其他配置. + +#### Changing a group’s path[](#changing-a-groups-path "Permalink") + +更改组的路径可能会有意想不到的副作用. 在继续之前,请阅读[重定向的行为](../project/index.html#redirects-when-changing-repository-paths) . + +如果您要腾出路径,以便其他组或用户可以声明该路径,则由于名称和路径都必须是唯一的,因此您可能也需要重命名该组. + +更改组路径: + +1. 导航到论坛的**"设置">"常规"**页面. +2. 展开**路径,传输,删除**部分. +3. 在" **更改组路径"**下输入新名称. +4. Click **变更群组路径**. + +**注意:**如果命名空间包含带有[Container Registry](../packages/container_registry/index.html)标记的项目,则当前无法重命名该命名空间,因为该项目无法移动.**提示:**如果要保留对原始名称空间的所有权并保护 URL 重定向,则可以更改一个组并向其传输项目,而无需更改组的路径或重命名用户名. + +### Remove a group[](#remove-a-group "Permalink") + +删除组及其内容: + +1. 导航到您小组的 **设置>常规**页面. +2. 展开**路径,传输,删除**部分. +3. 在"删除组"部分中,单击" **删除组"**按钮. +4. 根据要求确认操作. + +此操作要么: + +* 删除组,并且将后台作业排队以删除该组中的所有项目. +* 从[GitLab 12.8 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/33257) ,在[Premium 或 Silver](https://about.gitlab.com/pricing/premium/)或更高级别上,将一个组标记为删除. 默认情况下,删除将在 7 天后进行,但是可以在[实例设置中](../admin_area/settings/visibility_and_access_controls.html#default-deletion-adjourned-period-premium-only)进行更改. + +### Restore a group[](#restore-a-group-premium "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33257) . + +要还原标记为删除的组: + +1. 导航到您小组的 **设置>常规**页面. +2. 展开**路径,传输,删除**部分. +3. 在"还原组"部分中,单击" **还原组"**按钮. + +#### Enforce 2FA to group members[](#enforce-2fa-to-group-members "Permalink") + +通过对所有组成员[强制执行两因素身份验证(2FA)](../../security/two_factor_authentication.html#enforcing-2fa-for-all-users-in-a-group) ,将安全层添加到您的组中. + +#### Share with group lock[](#share-with-group-lock "Permalink") + +防止一个组中[的项目与另一个组共享项目,](../project/members/share_project_with_groups.html)以便对项目访问进行更严格的控制. + +例如,假设您有两个不同的团队(A 组和 B 组)在一个项目中一起工作,并且要继承该组成员身份,您可以在 A 组和 B 组之间共享项目. **使用组锁共享**可以防止其中的任何项目该群组不会与其他群组共享,从而确保只有合适的群组成员才能访问这些项目. + +要启用此功能,请导航至组设置页面. 选择" **使用组锁定共享"**并**保存组** . + +[![Checkbox for share with group lock](img/788efc08015bf62f608d47f16b49b4d7.png)](img/share_with_group_lock.png) + +#### Member Lock[](#member-lock-starter "Permalink") + +成员锁定使组所有者可以阻止组中所有项目的任何新项目成员资格,从而可以更严格地控​​制项目成员资格. + +例如,如果要为" [审核事件"](../../administration/audit_events.html)锁定组,请启用"成员锁定"以确保在该审核期间不能修改项目成员身份. + +要启用此功能: + +1. 导航到组的**"设置">"常规"**页面. +2. 展开" **权限,LFS,2FA"**部分,然后选择" **成员锁"** . +3. Click **保存更改**. + +[![Checkbox for membership lock](img/5460742929164e737a1b4c1990b75fc3.png)](img/member_lock.png) + +这将对以前有权操作项目成员资格的所有用户禁用该选项,因此无法添加新用户. 此外,将无法通过 API 向项目添加新用户的任何请求. + +#### IP access restriction[](#ip-access-restriction-premium "Permalink") + +版本历史 + +* 在[GitLab Ultimate 和 Gold](https://about.gitlab.com/pricing/) 12.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/1985) . +* 在 13.1 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/215410) [GitLab Premium 和 Silver](https://about.gitlab.com/pricing/) . + +为了确保只有组织内的人员可以访问特定资源,您可以选择通过 IP 地址限制对组及其基础项目,问题等的访问. 这可以帮助确保特定内容不会离开场所,同时又不会阻止对整个实例的访问. + +使用 CIDR 表示法将一个或多个允许的 IP 子网添加到组设置中,并且来自其他 IP 地址的任何人将无法访问受限制的内容. + +目前限制适用于: + +* UI. +* [从 GitLab 12.3 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/12874) ,可以访问 API. +* [从 GitLab 12.4 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/32113) ,Git 通过 SSH 进行操作. + +为了避免意外锁定,管理员和组所有者可以访问组,而不受 IP 限制. + +要启用此功能: + +1. 导航到组的**"设置">"常规"**页面. +2. 展开" **权限,LFS,2FA"**部分,然后在" **允许访问以下 IP 地址"**字段中输入 IP 地址范围. +3. Click **保存更改**. + +#### Allowed domain restriction[](#allowed-domain-restriction-premium "Permalink") + +版本历史 + +* 在[GitLab Premium 和 Silver](https://about.gitlab.com/pricing/) 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7297) . +* 支持指定 GitLab 13.1 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/33143)多个电子邮件域 + +通过仅将具有特定域中电子邮件地址的用户添加到组中,可以限制对组的访问. + +添加您要允许的电子邮件域,并且不允许来自不同域的电子邮件用户添加到该组. + +某些域不能被限制. 这些是最受欢迎的公共电子邮件域,例如: + +* `gmail.com` +* `yahoo.com` +* `hotmail.com` +* `aol.com` +* `msn.com` +* `hotmail.co.uk` +* `hotmail.fr` +* `live.com` +* `outlook.com` +* `icloud.com` + +要启用此功能: + +1. 导航到组的**"设置">"常规"**页面. +2. 展开" **权限,LFS,2FA"**部分,然后在" **通过电子邮件限制成员身份"**字段中输入域名. +3. Click **保存更改**. + +此后,将对所有添加到组中的新用户启用域检查. + +#### Group file templates[](#group-file-templates-premium "Permalink") + +组文件模板使您可以与组中的每个项目共享一组通用文件类型的模板. 它类似于[实例模板存储库](../admin_area/settings/instance_template_repository.html)功能,所选项目应遵循该页面上记录的相同命名约定. + +您只能在组中选择项目作为模板源. 这包括与该组共享的项目,但**不包括**正在配置的组的子组或父组中的项目. + +您可以为子组和直接父组配置此功能. 子组中的项目将有权访问该子组以及任何直接父组的模板. + +[![Group file template dropdown](img/6c431eb1e4bc729eceb4a6a36f0ea6b0.png)](img/group_file_template_dropdown.png) + +要启用此功能,请导航至组设置页面,展开" **模板"**部分,选择一个项目作为模板存储库,然后选择" **保存组"** . + +[![Group file template settings](img/09e1824644c088dfbd0f2f9710fc7d77.png)](img/group_file_template_settings.png) + +#### Group-level project templates[](#group-level-project-templates-premium "Permalink") + +通过将组设置为模板源,在组级别定义项目模板. [了解有关组级项目模板的更多信息](custom_project_templates.html) . + +#### Disabling email notifications[](#disabling-email-notifications "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/23585) . + +您可以禁用与该组相关的所有电子邮件通知,其中包括其子组和项目. + +要启用此功能: + +1. 导航到组的**"设置">"常规"**页面. +2. 展开**权限,LFS,2FA**部分,然后选择**禁用电子邮件通知** . +3. Click **保存更改**. + +#### Disabling group mentions[](#disabling-group-mentions "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/21301) . + +您可以防止将用户添加到对话中,并且在任何人提及这些用户所属的组时通知他们. + +自动完成下拉列表中会相应地显示提及被禁用的组. + +这对于具有大量用户的组特别有用. + +要启用此功能: + +1. 导航到组的**"设置">"常规"**页面. +2. 展开" **权限"," LFS,2FA"**部分,然后选择" **禁用组提及"** . +3. Click **保存更改**. + +#### Enabling delayed Project removal[](#enabling-delayed-project-removal-premium "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) . + +默认情况下,组中的项目会立即删除. (可选)在[Premium 或 Silver](https://about.gitlab.com/pricing/)或更高级别上,您可以将组内的项目配置为在延迟间隔后删除. + +在此间隔期间,项目将处于只读状态,并且可以根据需要还原. 间隔时间默认为 7 天,可以由管理员在[实例设置中](../admin_area/settings/visibility_and_access_controls.html#default-deletion-adjourned-period-premium-only)进行修改. + +要启用延迟删除项目: + +1. 导航到组的**"设置">"常规"**页面. +2. 展开" **权限"," LFS,2FA"**部分,然后选中" **启用延迟的项目删除"** . +3. Click **保存更改**. + +### Advanced settings[](#advanced-settings "Permalink") + +* **项目** :查看该组中的所有项目,将成员添加到每个项目,访问每个项目的设置,以及删除任何项目,所有操作均在同一屏幕上进行. +* **Webhooks** :为您的组配置[webhooks](../project/integrations/webhooks.html) . +* **Kubernetes 集群集成** :将您的 GitLab 组与[Kubernetes 集群连接](clusters/index.html) . +* **审核事件** :查看该组的[审核事件](../../administration/audit_events.html) . +* **管道配额** :跟踪组的[管道配额](../admin_area/settings/continuous_integration.html) . + +#### Storage usage quota[](#storage-usage-quota-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/13294) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.0. + +组所有者可以在组页面设置列表可用的" **使用配额"**页面的" **存储"**选项卡中,查看一个组(包括子组)中所有项目的聚合存储使用情况. + +[![Group storage usage quota](img/7042e9f430cefb3a9c62194cec839692.png)](img/group_storage_usage_quota.png) + +如果触发了任何会影响其值的相关事件(例如,提交推送),则将更新存储的总使用量. 出于性能原因,我们可能会将更新延迟最多 1 小时 30 分钟. + +如果您的名称空间显示`N/A`作为总存储使用量,则可以通过将提交推送到该名称空间中的任何项目来触发重新计算. + +#### Group push rules[](#group-push-rules-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34370) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.8. + +组推送规则允许组维护者为特定组内的新创建项目设置[推送规则](../../push_rules/push_rules.html) . + +要为组配置推送规则,请导航至 在小组的侧边栏上. + +设置后,新的子组将根据以下任一条件为其设置推送规则: + +* 定义了推送规则的最接近的父组. +* 如果没有父组定义推送规则,则在实例级别设置推送规则. + +##### Enabling the feature[](#enabling-the-feature "Permalink") + +默认情况下,此功能带有`:group_push_rules`功能标记. 可以使用功能标记[API 端点](../../api/features.html#set-or-create-a-feature)或通过具有 Rails 控制台访问权限的 GitLab 管理员为特定组启用它,方法是运行: + +``` +Feature.enable(:group_push_rules) +``` + +### Maximum artifacts size[](#maximum-artifacts-size-core-only "Permalink") + +有关为组设置最大工件大小的信息,请参见[最大工件大小](../admin_area/settings/continuous_integration.html#maximum-artifacts-size-core-only) . + +## User contribution analysis[](#user-contribution-analysis-starter "Permalink") + +使用[GitLab Contribution Analytics](contribution_analytics/index.html) ,您可以概述组成员执行的贡献(推送,合并请求和问题). + +## Issues analytics[](#issues-analytics-premium "Permalink") + +使用[GitLab Issues Analytics](issues_analytics/index.html) ,您可以查看组中每个月创建的问题数量的条形图. + +## Dependency Proxy[](#dependency-proxy-premium "Permalink") + +使用 GitLab 作为上游 Docker 映像的[依赖项代理](../packages/dependency_proxy/index.html) . \ No newline at end of file diff --git a/_book/docs/034.md b/_book/docs/034.md new file mode 100644 index 0000000000000000000000000000000000000000..0bb10091cf5f191ca38b2c13b3f3f49fce74681f --- /dev/null +++ b/_book/docs/034.md @@ -0,0 +1,69 @@ +# Contribution Analytics + +> 原文:[https://docs.gitlab.com/ee/user/group/contribution_analytics/](https://docs.gitlab.com/ee/user/group/contribution_analytics/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Using Contribution Analytics](#using-contribution-analytics) +* [Changing the period time](#changing-the-period-time) +* [Sorting by different factors](#sorting-by-different-factors) + +# Contribution Analytics[](#contribution-analytics-starter "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 8.3 中引入. +* 在 GitLab 12.2 中针对子组进行了[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/3090) . + +## Overview[](#overview "Permalink") + +借助 Contribution Analytics,您可以大致了解小组中的以下活动: + +* Issues +* 合并要求 +* 推送事件 + +要查看贡献分析,请转至小组的" **分析">"贡献分析"**页面. + +## Use cases[](#use-cases "Permalink") + +* 分析您的团队在一段时间内的贡献,并为杰出贡献者提供奖金. +* 与可以从其他支持中受益的小组成员一起确定改进的机会. + +## Using Contribution Analytics[](#using-contribution-analytics "Permalink") + +以下是三个主要的条形图,它们说明了每个组成员的贡献数量: + +* 推送事件 +* 合并要求 +* 已解决的问题 + +将鼠标悬停在每个栏上可以显示特定组成员的事件数. + +[![Contribution analytics bar graphs](img/52f1314a06269a0dc317f758c8e8cdab.png)](img/group_stats_graph.png) + +## Changing the period time[](#changing-the-period-time "Permalink") + +您可以从以下三个期间中选择: + +* 上周(默认) +* 上个月 +* 最近三个月 + +从日历下拉列表中选择所需的时间段. + +[![Contribution analytics choose period](img/0bc8de7b7d20af897fb8b38bb48663e8.png)](img/group_stats_cal.png) + +## Sorting by different factors[](#sorting-by-different-factors "Permalink") + +每个小组成员的贡献也以表格形式显示. 单击列标题以按该列对表进行排序: + +* 成员名字 +* 推送事件数 +* 未解决的问题数 +* 已解决的问题数 +* 已打开的 MR 数 +* 合并的 MR 数 +* 总捐款数 + +[![Contribution analytics contributions table](img/0a64287e1feef55413a5a906d02ec8ea.png)](img/group_stats_table.png) \ No newline at end of file diff --git a/_book/docs/035.md b/_book/docs/035.md new file mode 100644 index 0000000000000000000000000000000000000000..ea71ab10dc35940dbd6e790781ba94b2503d8aa6 --- /dev/null +++ b/_book/docs/035.md @@ -0,0 +1,21 @@ +# Custom group-level project templates + +> 原文:[https://docs.gitlab.com/ee/user/group/custom_project_templates.html](https://docs.gitlab.com/ee/user/group/custom_project_templates.html) + +# Custom group-level project templates[](#custom-group-level-project-templates-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6861) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.6. + +创建新[项目时](../project/index.html) ,基于自定义项目模板创建它是一个方便的选择. + +用户可以在组的**"设置">"常规">"自定义项目模板"**下配置一个用作模板源的 GitLab 组. + +**注意:** GitLab 管理员可以[为整个 GitLab 实例设置项目模板](../admin_area/custom_project_templates.html) . + +在本部分中,您可以配置所有自定义项目模板的来源组. 如果用户有权访问组命名空间下的每个项目,则它们将对用户可用. 例如,组中的每个公共项目将对每个登录用户可用. + +但是,仅当用户是项目成员时,私人项目才可用. + +**注意:**只能将直接子组设置为模板源. 不能使用所选模板源的嵌套子组项目. + +复制到每个新项目的存储库和数据库信息与使用[GitLab 的项目导入/导出导出](../project/settings/import_export.html)的数据相同. \ No newline at end of file diff --git a/_book/docs/036.md b/_book/docs/036.md new file mode 100644 index 0000000000000000000000000000000000000000..c23acbabf862fe7d9ff5be19018a5e785959b379 --- /dev/null +++ b/_book/docs/036.md @@ -0,0 +1,170 @@ +# Epics + +> 原文:[https://docs.gitlab.com/ee/user/group/epics/](https://docs.gitlab.com/ee/user/group/epics/) + +* [Use cases](#use-cases) +* [Manage epics](#manage-epics) +* [Relationships between epics and issues](#relationships-between-epics-and-issues) +* [Issue health status in Epic tree](#issue-health-status-in-epic-tree-ultimate) + * [Disable Issue health status in Epic tree](#disable-issue-health-status-in-epic-tree) +* [Multi-level child epics](#multi-level-child-epics-ultimate) +* [Start date and due date](#start-date-and-due-date) + * [From milestones](#from-milestones) + * [Inherited](#inherited) +* [Roadmap in epics](#roadmap-in-epics) +* [Permissions](#permissions) +* [Thread](#thread) +* [Comment or start a thread](#comment-or-start-a-thread) + * [Activity sort order](#activity-sort-order) +* [Award emoji](#award-emoji) +* [Notifications](#notifications) + +# Epics[](#epics-premium "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.2 中引入. +* 单级史诗在 12.8 [中移至](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) [GitLab Premium](https://about.gitlab.com/pricing/) . + +Epics 通过跟踪跨项目和里程碑共享主题的问题组,使您可以更有效,更轻松地管理项目组合. + +[![epics list view](img/bad7cd1d32a4bbf53fc1d27dcb3dd211.png)](img/epics_list_view_v12.5.png) + +## Use cases[](#use-cases "Permalink") + +* 假设您的团队正在研究一项大型功能,其中涉及在一个[小组](../index.html)内不同项目中创建的不同问题的多个讨论. 借助 Epics,您可以跟踪所有有助于该单一功能的相关活动. +* 跟踪何时针对该组问题开始工作,以及何时结束目标工作. +* 深入讨论和协作功能思想和范围. + +## Manage epics[](#manage-epics "Permalink") + +要了解您可以使用史诗功能,请参阅[管理史诗](manage_epics.html) . 可能的动作包括: + +* [Create an epic](manage_epics.html#create-an-epic) +* [Bulk-edit epics](../bulk_editing/index.html#bulk-edit-epics) +* [Delete an epic](manage_epics.html#delete-an-epic) +* [Close an epic](manage_epics.html#close-an-epic) +* [Reopen a closed epic](manage_epics.html#reopen-a-closed-epic) +* [Go to an epic from an issue](manage_epics.html#go-to-an-epic-from-an-issue) +* [Search for an epic from epics list page](manage_epics.html#search-for-an-epic-from-epics-list-page) +* [Make an epic confidential](manage_epics.html#make-an-epic-confidential) +* [Manage issues assigned to an epic](manage_epics.html#manage-issues-assigned-to-an-epic) +* [Manage multi-level child epics](manage_epics.html#manage-multi-level-child-epics-ultimate) + +## Relationships between epics and issues[](#relationships-between-epics-and-issues "Permalink") + +史诗与问题之间的可能关系是: + +* 史诗是一个或多个问题的父代. +* 史诗是一个或多个子史诗的父代. 有关详细信息,请参见[多级子史诗](#multi-level-child-epics-ultimate) . + +图 TD Parent_epic-> Issue1 Parent_epic-> Child_epic Child_epic-> Issue2 + +请参阅[管理分配给史诗](manage_epics.html#manage-issues-assigned-to-an-epic)的问题以获取将事件添加到史诗,重新排序问题,在史诗之间移动问题或将问题升级到史诗的步骤. + +## Issue health status in Epic tree[](#issue-health-status-in-epic-tree-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199184) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. + +您可以通过在问题上设置红色,琥珀色或绿色的[健康状态](../../project/issues/index.html#health-status-ultimate)来报告并快速响应单个问题和史诗的[健康](../../project/issues/index.html#health-status-ultimate) ,该状态将显示在史诗树上. + +### Disable Issue health status in Epic tree[](#disable-issue-health-status-in-epic-tree "Permalink") + +此功能带有默认情况下启用的功能标志. 有关禁用它的步骤,请参阅[禁用问题运行状况](../../project/issues/index.html#disable-issue-health-status) . + +## Multi-level child epics[](#multi-level-child-epics-ultimate "Permalink") + +在 GitLab Ultimate 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/8333) . + +属于父史诗组的一个组或子组的任何史诗都可以添加. 新的儿童史诗出现在" **史诗和问题"**选项卡中史诗列表的顶部. + +当您添加已链接到父级史诗的史诗时,到其当前父级的链接将被删除. + +An epic can have multiple child epics up to the maximum depth of five. + +请参阅[管理多级子级史诗](manage_epics.html#manage-multi-level-child-epics-ultimate) ,以了解创建,移动,重新排序或删除子[级史诗](manage_epics.html#manage-multi-level-child-epics-ultimate)的步骤. + +## Start date and due date[](#start-date-and-due-date "Permalink") + +要设置史诗的**开始日期**和**截止日期** ,请选择以下选项之一: + +* **固定** :输入固定值. +* **从里程碑** :从当前分配给史诗问题的里程碑继承动态值. 请注意,GitLab 12.5 用**Inherited**替换了此选项. +* **继承** :从史诗的问题,子史诗和里程碑继承动态值(在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7332) ,以代替**From 里程碑** ). + +### From milestones[](#from-milestones "Permalink") + +> 在 GitLab 12.5 中由**Inherited** [取代](https://gitlab.com/gitlab-org/gitlab/-/issues/7332) . + +如果您选择" **从里程碑**开始"作为开始日期,则 GitLab 会自动将日期设置为当前分配给添加到史诗中的问题的所有里程碑中最早的开始日期. 同样,如果您选择" **从里程碑** "作为截止日期,则 GitLab 会将其设置为当前分配给这些问题的所有里程碑中的最新截止日期. + +这些是动态日期,如果发生以下任何情况,将重新计算这些日期: + +* 将里程碑重新分配给这些问题. +* 里程碑日期更改. +* 从史诗中添加或删除问题. + +### Inherited[](#inherited "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7332)以替换**From 里程碑** . + +如果选择: + +* GitLab **继承**了开始日期,它将扫描所有子史诗和分配给该史诗的问题,并将开始日期设置为与找到的最早开始日期或里程碑相匹配. +* GitLab **继承**了截止日期,它将设置截止日期以匹配在其子史诗和问题中发现的最新截止日期或里程碑. + +这些是动态日期,如果发生以下任何情况,则重新计算: + +* 儿童史诗的日期发生了变化. +* 将里程碑重新分配给问题. +* 里程碑的日期会更改. +* 问题被添加到史诗中或从史诗中删除. + +由于史诗的日期可以从其子级继承日期,因此开始日期和到期日期从底部传播到顶部. 如果最低级别的子级史诗的开始日期发生更改(成为其父级史诗最早的开始日期),则父级史诗的开始日期将反映该更改,并将向上传播到顶部的史诗级. + +## Roadmap in epics[](#roadmap-in-epics "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7327) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.10. + +如果你的史诗包含一个或多个[孩子史诗](#multi-level-child-epics-ultimate)其中有一个[开始或到期日](#start-date-and-due-date) ,一个[路线图,](../roadmap/index.html)孩子史诗的观点是父史诗中列出. + +[![Child epics roadmap](img/35e89eba4dfc37f409cb295b0c8b13d1.png)](img/epic_view_roadmap_v12_9.png) + +## Permissions[](#permissions "Permalink") + +如果您有权查看史诗,并且有权查看已添加到该史诗的问题,则可以在史诗问题列表中查看该问题. + +如果您有权编辑史诗并且有权编辑问题,则可以将问题添加到史诗中或从史诗中删除. + +请注意,对于给定的组,所有项目的可见性必须与该组相同,或限制较少. 这意味着,如果您有权访问某个小组的史诗,那么您已经可以访问该小组的项目. + +您也可以查阅[组权限表](../../permissions.html#group-members-permissions) . + +## Thread[](#thread "Permalink") + +* 评论:通过在该史诗中的评论中发布评论来协作. 这些文本字段也完全支持[GitLab Flavored Markdown](../../markdown.html#gitlab-flavored-markdown-gfm) . + +## Comment or start a thread[](#comment-or-start-a-thread "Permalink") + +写下评论后,您可以: + +* 点击**评论** ,您的评论将被发布. +* 单击" **开始主题"** ,您将在该史诗般的讨论中开始一个主题. + +### Activity sort order[](#activity-sort-order "Permalink") + +[Introduced](https://https://gitlab.com/gitlab-org/gitlab/-/issues/214364) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + +您可以颠倒默认顺序,并与按顶部的最新项目排序的活动供稿进行交互. 您的首选项通过本地存储保存,并自动应用于您查看的每个问题. + +要更改活动排序顺序,请单击**最旧的第一个**下拉菜单,然后选择最旧或最新的项目以首先显示. + +[![Issue activity sort order dropdown button](img/806d03909b4b194f095b4c69e175868d.png)](img/epic_activity_sort_order_v13_2.png) + +## Award emoji[](#award-emoji "Permalink") + +您可以为该史诗或其评论[授予表情符号](../../award_emojis.html) . + +## Notifications[](#notifications "Permalink") + +您可以[打开通知](../../profile/notifications.html)以[通知](../../profile/notifications.html)史诗事件. \ No newline at end of file diff --git a/_book/docs/037.md b/_book/docs/037.md new file mode 100644 index 0000000000000000000000000000000000000000..d6a4bfbea536ececb2f63abc6e375043efda76cf --- /dev/null +++ b/_book/docs/037.md @@ -0,0 +1,313 @@ +# Manage epics + +> 原文:[https://docs.gitlab.com/ee/user/group/epics/manage_epics.html](https://docs.gitlab.com/ee/user/group/epics/manage_epics.html) + +* [Create an epic](#create-an-epic) + * [Create an epic from the epic list](#create-an-epic-from-the-epic-list) + * [Access the New Epic form](#access-the-new-epic-form) + * [Elements of the New Epic form](#elements-of-the-new-epic-form) +* [Edit an epic](#edit-an-epic) +* [Bulk-edit epics](#bulk-edit-epics) +* [Delete an epic](#delete-an-epic) +* [Close an epic](#close-an-epic) +* [Reopen a closed epic](#reopen-a-closed-epic) +* [Go to an epic from an issue](#go-to-an-epic-from-an-issue) +* [Search for an epic from epics list page](#search-for-an-epic-from-epics-list-page) +* [Make an epic confidential](#make-an-epic-confidential) + * [Disable confidential epics](#disable-confidential-epics-premium-only) +* [Manage issues assigned to an epic](#manage-issues-assigned-to-an-epic) + * [Add an issue to an epic](#add-an-issue-to-an-epic) + * [Add an existing issue to an epic](#add-an-existing-issue-to-an-epic) + * [Create an issue from an epic](#create-an-issue-from-an-epic) + * [Remove an issue from an epic](#remove-an-issue-from-an-epic) + * [Reorder issues assigned to an epic](#reorder-issues-assigned-to-an-epic) + * [Move issues between epics](#move-issues-between-epics-ultimate) + * [Promote an issue to an epic](#promote-an-issue-to-an-epic) +* [Manage multi-level child epics](#manage-multi-level-child-epics-ultimate) + * [Add a child epic to an epic](#add-a-child-epic-to-an-epic) + * [Move child epics between epics](#move-child-epics-between-epics) + * [Reorder child epics assigned to an epic](#reorder-child-epics-assigned-to-an-epic) + * [Remove a child epic from a parent epic](#remove-a-child-epic-from-a-parent-epic) + +# Manage epics[](#manage-epics-premium "Permalink") + +该页面收集了有关[史诗](index.html)或与[史诗](index.html)有关的所有操作的说明. + +## Create an epic[](#create-an-epic "Permalink") + +每个组中都有史诗的分页列表,您可以从中创建新的史诗. 史诗列表还包括所选组中所有子组的史诗. 在您的论坛页面中: + +### Create an epic from the epic list[](#create-an-epic-from-the-epic-list "Permalink") + +要从史诗列表中创建史诗,请分组: + +1. 去 **史诗** . +2. Click **新史诗**. +3. 输入描述性标题. +4. Click **创造史诗**. + +### Access the New Epic form[](#access-the-new-epic-form "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211533) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + +有两种方法可以进入"新史诗"表格并在您所在的小组中创建史诗: + +* 在您小组的史诗中,点击**新建史诗** . +* 在任何地方的顶部菜单中,单击**加号** ( ) **>新史诗** . + + [![New epic from an open epic](img/4c0cef07da8190af4f517bd8d336cb5b.png)](img/new_epic_from_groups_v13.2.png) + +### Elements of the New Epic form[](#elements-of-the-new-epic-form "Permalink") + +在创建新的史诗时,您可以填写以下字段: + +* Title +* Description +* 保密性复选框 +* Labels +* 开始日期 +* 截止日期 + +[![New epic form](img/a48fc7b7ef95b54bd7ec66c17cad7dbb.png)](img/new_epic_form_v13.2.png) + +## Edit an epic[](#edit-an-epic "Permalink") + +创建史诗之后,可以编辑更改以下详细信息: + +* Title +* Description +* 开始日期 +* 截止日期 +* Labels + +编辑史诗的标题或说明: + +1. 点击**修改标题和说明** 按钮. +2. 进行更改. +3. Click **保存更改**. + +要编辑史诗的开始日期,截止日期或标签,请执行以下操作: + +1. 单击史诗侧边栏中每个部分旁边的" **编辑"** . +2. 选择日期或标签为您的史诗. + +## Bulk-edit epics[](#bulk-edit-epics "Permalink") + +您可以一次编辑多个史诗. 要了解操作方法,请访问[批量编辑问题,史诗和在组级别合并请求](../bulk_editing/index.html#bulk-edit-epics) . + +## Delete an epic[](#delete-an-epic "Permalink") + +**注意:**要删除史诗,您需要成为组/子组的[所有者](../../permissions.html#group-members-permissions) . + +编辑史诗的描述时,单击" **删除"**按钮以删除史诗. 出现一个模态来确认您的动作. + +删除史诗会从系统中与其关联的史诗中释放所有现有问题. + +## Close an epic[](#close-an-epic "Permalink") + +每当您决定不再需要该史诗时,请通过以下方法关闭该史诗: + +* 单击**关闭史诗**按钮. + + [![close epic - button](img/dce9a8c36e06896553bd80f313c3a756.png)](img/button_close_epic.png) + +* 使用[快速动作](../../project/quick_actions.html) . + +## Reopen a closed epic[](#reopen-a-closed-epic "Permalink") + +您可以重新打开因以下原因而关闭的史诗: + +* 单击**重新打开史诗**按钮. + + [![reopen epic - button](img/ed7d654fa8271709dfa6c567b48c5de6.png)](img/button_reopen_epic.png) + +* 使用[快速动作](../../project/quick_actions.html) . + +## Go to an epic from an issue[](#go-to-an-epic-from-an-issue "Permalink") + +如果问题属于史诗,则可以使用问题侧栏中的链接导航到包含该史诗. + +[![containing epic](img/8edd1cbf476ddc76f3df25fdeff8b55c.png)](img/containing_epic.png) + +## Search for an epic from epics list page[](#search-for-an-epic-from-epics-list-page "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.5 中引入. +* [已移至](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) GitLab 12.8 中的[Premium](https://about.gitlab.com/pricing/)层. + +您可以根据以下参数,使用过滤的搜索栏(类似于"问题和合并请求"的搜索栏)从史诗列表中搜索史诗: + +* 标题或说明 +* 作者名称/用户名 +* Labels + +[![epics search](img/c77b45147112088b7940cb4ebcc5f4a6.png)](img/epics_search.png) + +要进行搜索,请转到史诗列表,然后单击" **搜索或过滤结果** "字段. 它将显示一个下拉菜单,您可以从中添加一个作者. 您也可以输入纯文本以按史诗标题或描述进行搜索. 完成后,按键盘上的`Enter`键过滤列表. + +您还可以按以下方式对史诗列表进行排序: + +* 创建日期 +* 最近更新时间 +* 开始日期 +* 截止日期 + +每个选项都包含一个按钮,可以在**升序**和**降序**之间切换顺序. 无论您浏览史诗,包括" [路线图"](../roadmap/index.html) ,都可以保存和使用排序选项和顺序. + +[![epics sort](img/57b0d20488fb6cdd9ed2e8f573fcb7bb.png)](img/epics_sort.png) + +## Make an epic confidential[](#make-an-epic-confidential "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 13.0 中在功能标志后面[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/213068) ,默认情况下禁用. +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 13.2 中[默认启用](https://gitlab.com/gitlab-org/gitlab/-/issues/224513) . + +创建史诗时,可以选中**"将此史诗设为机密"**复选框,使其成为机密文件. + +### Disable confidential epics[](#disable-confidential-epics-premium-only "Permalink") + +机密史诗功能部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以为您的自我管理实例禁用它. + +禁用它: + +``` +Feature.disable(:confidential_epics) +``` + +## Manage issues assigned to an epic[](#manage-issues-assigned-to-an-epic "Permalink") + +### Add an issue to an epic[](#add-an-issue-to-an-epic "Permalink") + +您可以将现有问题添加到史诗中,也可以创建一个自动添加到史诗中的新问题. + +#### Add an existing issue to an epic[](#add-an-existing-issue-to-an-epic "Permalink") + +属于史诗组或史诗子组中任何项目的现有问题都可以添加到史诗中. 新添加的问题显示在" **史诗和问题"**选项卡中问题列表的顶部. + +史诗包含一个问题列表,一个问题最多可以与一个史诗相关联. 当您添加已链接到史诗的问题时,该问题会自动与其当前父级取消链接. + +要将问题添加到史诗中: + +1. 点击**添加**下拉按钮. +2. Click **添加问题**. +3. 使用以下两种方法之一确定要添加的问题: + * 粘贴问题的链接. + * 通过输入问题标题的一部分来搜索所需的问题,然后选择所需的匹配项(在[GitLab 12.5 中](https://gitlab.com/gitlab-org/gitlab/-/issues/9126)引入). + + 如果要添加多个问题,请按`空格键` ,然后重复此步骤. + +4. Click **Add**. + +#### Create an issue from an epic[](#create-an-issue-from-an-epic "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/5419) . + +从史诗中创建问题使您可以将注意力集中在史诗的更广泛的上下文上,同时将工作划分成较小的部分. + +要从史诗中创建问题: + +1. 在史诗页面上的" **史诗和问题"下** ,点击**添加**下拉按钮,然后选择**创建新问题** . +2. 在**标题下** ,输入新期刊的标题. +3. 从**项目**下拉列表中,选择应在其中创建问题的项目. +4. Click **创建问题**. + +### Remove an issue from an epic[](#remove-an-issue-from-an-epic "Permalink") + +在史诗的详细信息页面上时,可以从史诗中删除问题. 从史诗中删除问题后,该问题将不再与此史诗相关联. + +要从史诗中删除问题: + +1. 点击**删除** ( )按钮旁边要删除的问题. 出现**删除问题**警告. +2. Click **Remove**. + +[![List of issues assigned to an epic](img/8c47dc71d95554edf7da34adb5acc575.png)](img/issue_list_v13_1.png) + +### Reorder issues assigned to an epic[](#reorder-issues-assigned-to-an-epic "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9367) . + +新问题出现在" **史诗和问题"**选项卡中的列表顶部. 您可以通过拖动来重新排列问题列表. + +要重新分配分配给史诗的问题: + +1. 转到" **史诗和问题"**标签. +2. 将问题拖到所需的顺序. + +### Move issues between epics[](#move-issues-between-epics-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0. + +新问题出现在" **史诗和问题"**选项卡中的列表顶部. 您可以将问题从一部史诗转移到另一部史诗. + +要将问题移至另一个史诗: + +1. 转到" **史诗和问题"**标签. +2. 将问题拖到所需的父级史诗中. + +### Promote an issue to an epic[](#promote-an-issue-to-an-epic "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/3777) . +* 在 12.8 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) [GitLab Premium](https://about.gitlab.com/pricing/) . + +如果您具有关闭问题并在直接父组中创建史诗的必要[权限](../../permissions.html) ,则可以使用`/promote` [快速操作](../../project/quick_actions.html#quick-actions-for-issues-merge-requests-and-epics)将问题升级为史诗. 仅可以促进小组项目中的问题. 尝试提出机密问题时,将显示警告. 向史诗宣传机密问题将使与该问题相关的所有信息公开,因为史诗对小组成员是公开的. + +执行快速操作时: + +* 在与问题项目所在的组中创建一个史诗. +* 通知该问题的订户该史诗已创建. + +以下问题元数据将被复制到史诗中: + +* 标题,描述,活动/评论主题. +* Upvotes/downvotes. +* Participants. +* Group labels that the issue already has. + +## Manage multi-level child epics[](#manage-multi-level-child-epics-ultimate "Permalink") + +### Add a child epic to an epic[](#add-a-child-epic-to-an-epic "Permalink") + +要将儿童史诗添加到史诗中: + +1. 点击**添加**下拉按钮. +2. Click **添加史诗**. +3. 使用以下两种方法之一确定要添加的史诗: + * 粘贴史诗的链接. + * 通过输入史诗标题的一部分来搜索所需的问题,然后选择所需的匹配项(在[GitLab 12.5 中](https://gitlab.com/gitlab-org/gitlab/-/issues/9126)引入). + + 如果要添加多个史诗,请按`空格键`并重复此步骤. + +4. Click **Add**. + +### Move child epics between epics[](#move-child-epics-between-epics "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0. + +新的儿童史诗出现在" **史诗和问题"**选项卡中的列表顶部. 您可以将儿童史诗从一个史诗转移到另一个史诗. 当您添加已链接到父级史诗的史诗时,到其当前父级的链接将被删除. 问题和儿童史诗不能混在一起. + +要将儿童史诗移至另一史诗: + +1. 转到" **史诗和问题"**标签. +2. 将史诗拖到所需的父史诗中. + +### Reorder child epics assigned to an epic[](#reorder-child-epics-assigned-to-an-epic "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9367) . + +新的儿童史诗出现在" **史诗和问题"**选项卡中的列表顶部. 您可以对子史诗列表进行重新排序. + +要重新分配分配给史诗的子史诗: + +1. 转到" **史诗和问题"**标签. +2. 将史诗拖到所需的顺序. + +### Remove a child epic from a parent epic[](#remove-a-child-epic-from-a-parent-epic "Permalink") + +要从父级史诗中删除子级史诗: + +1. 单击父级史诗列表中的`x`按钮. +2. 在**删除史诗**警告消息,请单击**删除** . \ No newline at end of file diff --git a/_book/docs/038.md b/_book/docs/038.md new file mode 100644 index 0000000000000000000000000000000000000000..7fc538ab6cd4eacdc8ec641882de0be71e51269b --- /dev/null +++ b/_book/docs/038.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/user/group/dependency_proxy/](https://docs.gitlab.com/ee/user/group/dependency_proxy/) \ No newline at end of file diff --git a/_book/docs/039.md b/_book/docs/039.md new file mode 100644 index 0000000000000000000000000000000000000000..06fa17a1ad60a16eb839d12a0c12542bcd4e9fb1 --- /dev/null +++ b/_book/docs/039.md @@ -0,0 +1,126 @@ +# Group Import/Export + +> 原文:[https://docs.gitlab.com/ee/user/group/settings/import_export.html](https://docs.gitlab.com/ee/user/group/settings/import_export.html) + +* [Important Notes](#important-notes) + * [Exported Contents](#exported-contents) +* [Exporting a Group](#exporting-a-group) + * [Between CE and EE](#between-ce-and-ee) +* [Importing the group](#importing-the-group) +* [Version history](#version-history) +* [Rate Limits](#rate-limits) + +# Group Import/Export[](#group-importexport "Permalink") + +版本历史 + +* 在 GitLab 13.0 中作为实验功能[引入](https://gitlab.com/groups/gitlab-org/-/epics/2888) . 在将来的版本中可能会更改. + +可以将在任何 GitLab 实例或 GitLab.com 上运行的现有组及其所有相关数据导出,并移至新的 GitLab 实例. + +如果启用了组导入选项,则会显示**GitLab 导入/导出**按钮. + +也可以看看: + +* [Group Import/Export API](../../../api/group_import_export.html) +* [Project Import/Export](../../project/settings/import_export.html) +* [Project Import/Export API](../../../api/project_import_export.html) + +要启用 GitLab 导入/导出: + +1. 导航 **管理区>** **设置>可见性和访问控制** . +2. 滚动到**导入源** +3. 启用所需的**导入源** + +## Important Notes[](#important-notes "Permalink") + +请注意以下几点: + +* 导出存储在一个临时[共享目录中](../../../development/shared_files.html) ,并由特定工作人员每 24 小时删除一次. +* 要保留导入项目中的组级关系,请首先运行"组导入/导出",以允许将项目导入所需的组结构中. +* 除非导入到父组,否则将为导入的组提供`private`可见性级别. +* 如果导入父组,则除非另有限制,否则子组将继承相同级别的可见性. +* 若要保留成员列表及其对导入组的各自权限,请查看这些组中的用户. 在导入所需的组之前,请确保这些用户存在. + +### Exported Contents[](#exported-contents "Permalink") + +将导出以下项目: + +* Milestones +* Labels +* 董事会和董事会名单 +* Badges +* 子组(包括所有上述数据) +* Epics +* Events + +以下项目将不会导出: + +* Projects +* 跑步者令牌 +* SAML 发现令牌 + +**注意:**有关在组导出中[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/import_export/group/import_export.yml)的特定数据的更多详细信息,请参阅[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/import_export/group/import_export.yml)文件. + +## Exporting a Group[](#exporting-a-group "Permalink") + +1. 导航到您的论坛的主页. + +2. 请点击 侧栏中的**设置** . + +3. 在" **高级"**部分中,单击" **导出组"**按钮. + + [![Export group panel](img/222aa4a1e09c2312446d0aa324c6f193.png)](img/export_panel_v13_0.png) + +4. 生成导出后,您应该会收到一封电子邮件,其中包含指向压缩的 tar 存档中[导出内容](#exported-contents)的链接,其中的内容为 JSON 格式. + +5. 或者,您可以返回项目设置,然后点击**下载导出**从那里下载文件,或者点击**重新**生成导出来生成一个新文件. + +**注意:**可以由管理员设置最大导入文件大小,默认为 50MB. 作为管理员,您可以修改最大导入文件大小. 为此,请在" [应用程序设置" API](../../../api/settings.html#change-application-settings)或" [管理界面"中](../../admin_area/settings/account_and_limit_settings.html)使用`max_import_size`选项. + +### Between CE and EE[](#between-ce-and-ee "Permalink") + +您可以将组从[Community Edition](https://about.gitlab.com/install/ce-or-ee/)导出[到 Enterprise Edition](https://about.gitlab.com/install/ce-or-ee/) ,反之亦然. + +如果要将组从企业版导出到社区版,则可能会丢失仅保留在企业版中的数据. 有关更多信息,请参阅[从 EE 降级为 CE](../../../README.html) . + +## Importing the group[](#importing-the-group "Permalink") + +1. 通过顶部导航栏中的`+`按钮或现有组页面上的" **新建子组"**按钮导航到" **新建**组"页面. + + [![Navigation paths to create a new group](img/fad2df1fa4371b39b3ea1032a8ad236c.png)](img/new_group_navigation_v13_1.png) + +2. 在"新建组"页面上,选择" **导入组"**选项卡. + + [![Fill in group details](img/d15d948fc7d1b6e5c8dabacbe7c2fcc9.png)](img/import_panel_v13_1.png) + +3. 输入您的群组名称. + +4. 接受或修改关联的组 URL. + +5. Click **选择文件** + +6. 在" [导出组"](#exporting-a-group)部分中选择您导出的文件. + +7. 单击**导入组**开始导入. 您新导入的组页面将很快出现. + +## Version history[](#version-history "Permalink") + +GitLab 可以导入从其他 GitLab 部署导出的捆绑软件. 此功能仅限于之前的两个 GitLab [次要](../../../policy/maintenance.html#versioning)发行版,这与我们的[安全发布](../../../policy/maintenance.html#security-releases)流程类似. + +例如: + +| 当前版本 | 可以导入从 | +| --- | --- | +| 13.0 | 13.0, 12.10, 12.9 | +| 13.1 | 13.1, 13.0, 12.10 | + +## Rate Limits[](#rate-limits "Permalink") + +为了避免滥用,用户的速率仅限于: + +| 请求类型 | Limit | +| --- | --- | +| Export | 每 5 分钟 30 个小组 | +| 下载导出 | 每 10 分钟每组 10 次下载 | +| Import | 每 5 分钟 30 个小组 | \ No newline at end of file diff --git a/_book/docs/040.md b/_book/docs/040.md new file mode 100644 index 0000000000000000000000000000000000000000..54e39bd604217296cb2057b060bb627611933db5 --- /dev/null +++ b/_book/docs/040.md @@ -0,0 +1,39 @@ +# Insights + +> 原文:[https://docs.gitlab.com/ee/user/group/insights/](https://docs.gitlab.com/ee/user/group/insights/) + +* [View your group’s Insights](#view-your-groups-insights) +* [Configure your Insights](#configure-your-insights) +* [Permissions](#permissions) + +# Insights[](#insights-ultimate "Permalink") + +[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. + +配置对您的团队重要的洞察力,以探索数据,例如分类诊断,在给定时间段内创建/关闭的问题,合并请求的平均时间等. + +[![Insights example stacked bar chart](img/9f4a21c247f193621ddd2f709c4536d7.png)](img/insights_example_stacked_bar_chart.png) + +## View your group’s Insights[](#view-your-groups-insights "Permalink") + +您可以通过点击左侧边栏中的**Analytics(分析)> Insights**链接来访问组的 Insights: + +[![Insights sidebar link](img/098a5864447e44da06b72051af59b294.png)](img/insights_sidebar_link_v12_8.png) + +## Configure your Insights[](#configure-your-insights "Permalink") + +导航到组的**"设置">"常规"** ,展开" **Insights"** ,然后选择包含`.gitlab/insights.yml`配置文件的项目: + +[![group insights configuration](img/6e3e1e9c7013cd330bcb6380ef19ddf9.png)](img/insights_group_configuration.png) + +如果未设置任何配置,将使用[默认配置文件](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/fixtures/insights/default.yml) . + +有关`.gitlab/insights.yml`配置文件的更多详细信息,请参见[Project 的 Insights 文档](../../project/insights/index.html) . + +## Permissions[](#permissions "Permalink") + +如果您有权查看组,则可以查看其见解. + +**注意:**您无法访问的问题或合并请求(因为您无法访问它们所属的项目,或者因为它们是机密的)会从 Insights 图表中过滤掉. + +您也可以查阅[组权限表](../../permissions.html#group-members-permissions) . \ No newline at end of file diff --git a/_book/docs/041.md b/_book/docs/041.md new file mode 100644 index 0000000000000000000000000000000000000000..584bc07c7d4c6615f2e6a02c184267c558919e5a --- /dev/null +++ b/_book/docs/041.md @@ -0,0 +1,41 @@ +# Issues Analytics + +> 原文:[https://docs.gitlab.com/ee/user/group/issues_analytics/](https://docs.gitlab.com/ee/user/group/issues_analytics/) + +* [Drill into the information](#drill-into-the-information) + +# Issues Analytics[](#issues-analytics-premium "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7478) . +* 在项目级别的[GitLab Premium](https://about.gitlab.com/pricing/) 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/196561) . + +问题分析是一个条形图,用于说明每月创建的问题数. 默认时间跨度为 13 个月,其中包括当月以及之前的 12 个月. + +要访问图表,请导航至您的组或项目侧边栏,然后选择 **分析>问题分析** . + +将鼠标悬停在每个栏上可以查看总数. + +要缩小图中包含的问题的范围,请在" **搜索或过滤结果..."**字段中输入您的条件. 可以在以下列表中输入条件或从菜单中选择条件: + +* Author +* Assignee +* Milestone +* Label +* 我的反应 +* Weight + +您可以通过设置 URL 参数来更改显示的总月数. 例如, `https://gitlab.com/groups/gitlab-org/-/issues_analytics?months_back=15` //gitlab.com/groups/gitlab-org/-/issues_analytics?months_back `https://gitlab.com/groups/gitlab-org/-/issues_analytics?months_back=15` 15 显示 GitLab.org 组中图表的总计 15 个月. + +[![Issues created per month](img/7a1046341466c144b96bc573f0a16114.png)](img/issues_created_per_month_v12_8.png) + +## Drill into the information[](#drill-into-the-information "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/196547) . + +您可以通过浏览图表下方的表格来检查各个问题的详细信息. + +该图表显示基于全局页面筛选器的前 100 个问题. + +[![Issues table](img/c07889c4060a55eccd0e5dde9cb54f74.png)](img/issues_table_v13_1.png) \ No newline at end of file diff --git a/_book/docs/042.md b/_book/docs/042.md new file mode 100644 index 0000000000000000000000000000000000000000..97e3436b195b83a46bcb0e498eeb8881f14a7933 --- /dev/null +++ b/_book/docs/042.md @@ -0,0 +1,80 @@ +# Iterations + +> 原文:[https://docs.gitlab.com/ee/user/group/iterations/](https://docs.gitlab.com/ee/user/group/iterations/) + +* [View the iterations list](#view-the-iterations-list) +* [Create an iteration](#create-an-iteration) +* [Edit an iteration](#edit-an-iteration) +* [Enable Iterations](#enable-iterations-core-only) + +# Iterations[](#iterations-starter "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214713) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上已禁用. +* 可以按组启用或禁用 +* 不建议将其用于生产. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-iterations-core-only) . + +迭代是跟踪一段时间内问题的一种方法. 这使团队可以跟踪速度和波动性指标. 迭代可与[里程碑](../../project/milestones/index.html)一起使用,以在不同时间段内进行跟踪. + +例如,您可以使用: + +* 计划递增的里程碑,跨越 8 到 12 周. +* Sprint 的迭代,历时 2 周. + +在 GitLab 中,迭代类似于里程碑,但有一些区别: + +* 迭代仅适用于组. +* 一组一次只能有一个活动的迭代. +* 迭代需要开始日期和结束日期. +* 迭代日期范围不能重叠. + +## View the iterations list[](#view-the-iterations-list "Permalink") + +要查看迭代列表,请分组访问 **问题>迭代** . 从那里您可以创建一个新的迭代或单击一个迭代以获得更详细的视图. + +## Create an iteration[](#create-an-iteration "Permalink") + +**注意:**您需要具有开发人员[权限](../../permissions.html)或更高[权限](../../permissions.html)才能创建迭代. + +要创建迭代: + +1. 在一个小组中,转到 **问题>迭代** . +2. Click **新迭代**. +3. 输入标题,描述(可选),开始日期和截止日期. +4. 单击**创建迭代** . 将打开"迭代详细信息"页面. + +## Edit an iteration[](#edit-an-iteration "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/218277) . + +**注意:**您需要开发者[权限](../../permissions.html)或更高[权限](../../permissions.html)才能编辑迭代. + +要编辑迭代,请点击三点菜单( )> **编辑迭代** . + +## Enable Iterations[](#enable-iterations-core-only "Permalink") + +GitLab 迭代功能正在开发中,尚未准备好用于生产. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以为您的实例启用它. `:group_iterations`可以按组启用或禁用. + +要启用它: + +``` +# Instance-wide +Feature.enable(:group_iterations) +# or by group +Feature.enable(:group_iterations, Group.find()) +``` + +禁用它: + +``` +# Instance-wide +Feature.disable(:group_iterations) +# or by group +Feature.disable(:group_iterations, Group.find()) +``` \ No newline at end of file diff --git a/_book/docs/043.md b/_book/docs/043.md new file mode 100644 index 0000000000000000000000000000000000000000..96a59ace35118b558e42f468376c894322c387bf --- /dev/null +++ b/_book/docs/043.md @@ -0,0 +1,89 @@ +# Public access + +> 原文:[https://docs.gitlab.com/ee/public_access/public_access.html](https://docs.gitlab.com/ee/public_access/public_access.html) + +* [Visibility of projects](#visibility-of-projects) + * [Public projects](#public-projects) + * [Internal projects](#internal-projects) + * [Private projects](#private-projects) + * [How to change project visibility](#how-to-change-project-visibility) +* [Visibility of groups](#visibility-of-groups) +* [Visibility of users](#visibility-of-users) +* [Visibility of pages](#visibility-of-pages) +* [Restricting the use of public or internal projects](#restricting-the-use-of-public-or-internal-projects) +* [Reducing visibility](#reducing-visibility) + +# Public access[](#public-access "Permalink") + +GitLab 允许[所有者](../user/permissions.html)将项目的可见性设置为**public** , **internal**或**private** . 这些可见性级别会影响谁可以在公共访问目录(GitLab 实例下的`/public` )中查看项目,例如[https://gitlab.com/public](https://gitlab.com/public) + +## Visibility of projects[](#visibility-of-projects "Permalink") + +### Public projects[](#public-projects "Permalink") + +可以克隆公共项目, **而无需**通过 HTTPS **进行任何**身份验证. + +它们将在所有用户的公共访问目录( `/public` )中列出. + +**任何登录的用户**都将对存储库具有[来宾权限](../user/permissions.html) . + +### Internal projects[](#internal-projects "Permalink") + +任何登录用户都可以克隆内部项目. + +它们也将列在公共访问目录( `/public` )中,但仅适用于登录用户. + +任何登录的用户都将对存储库具有[来宾权限](../user/permissions.html) . + +**注意:**从 2019 年 7 月开始,GitLab.com 上的新项目,组和摘要的`` `Internal`可见性''设置被禁用. 使用" `Internal`可见性"设置的现有项目,组和摘录保留此设置. 您可以在[相关问题中](https://gitlab.com/gitlab-org/gitlab/-/issues/12388)阅读有关更改的更多信息. + +### Private projects[](#private-projects "Permalink") + +私人项目只能由项目成员(来宾除外)克隆和查看. + +它们将仅出现在项目成员的公共访问目录( `/public` )中. + +### How to change project visibility[](#how-to-change-project-visibility "Permalink") + +1. 转到项目的**"设置"** . +2. 将**可见性级别**更改为公共,内部或私有. + +## Visibility of groups[](#visibility-of-groups "Permalink") + +**注意:** [从](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3323) GitLab 8.6 [开始](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3323) ,组的可见性已更改,并且可以与项目相同的方式进行配置. 在以前的版本中,组页面始终对所有用户可见. + +与项目一样,可以设置组的可见性来决定匿名用户,所有登录用户还是仅显式组成员可以查看它. 应用程序设置级别对可见性级别的限制也适用于组,因此,如果将其设置为内部,则匿名用户的浏览页面将为空. 现在,组页面上有一个可见性级别图标. + +管理员用户不能创建具有比直接父组更高的可见性级别的子组或项目. + +## Visibility of users[](#visibility-of-users "Permalink") + +无论您是否登录,位于`/username`的用户公共页面始终可见. + +当访问用户的公共页面时,您只能看到您有权访问的项目. + +如果公共级别受到限制,则用户配置文件仅对登录用户可见. + +## Visibility of pages[](#visibility-of-pages "Permalink") + +默认情况下,以下目录对未经身份验证的用户可见: + +* 公共访问( `/public` ). +* 探索( `/explore` ). +* 帮助( `/help` ). + +但是,如果`/public`目录的访问级别受到限制,则这些目录仅对登录用户可见. + +## Restricting the use of public or internal projects[](#restricting-the-use-of-public-or-internal-projects "Permalink") + +您可以限制用户在创建项目或代码段时对可见性级别的使用. 这有助于防止用户意外公开其存储库. 受限的可见性设置不适用于管理员用户. + +有关详细信息,请参阅[受限可见性级别](../user/admin_area/settings/visibility_and_access_controls.html#restricted-visibility-levels) . + +## Reducing visibility[](#reducing-visibility "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33358) . + +降低项目的可见性级别将删除该项目与任何分叉项目之间的派生关系. 这是一种潜在的破坏性操作,需要先确认才能保存. + +[![Project visibility change confirmation](img/17abb300a15db5073a41bf8a13e53bc7.png)](img/project_visibility_confirmation_v12_6.png) \ No newline at end of file diff --git a/_book/docs/044.md b/_book/docs/044.md new file mode 100644 index 0000000000000000000000000000000000000000..9c2048ad575dc9ae3be87b64b9860c7fe77f04f3 --- /dev/null +++ b/_book/docs/044.md @@ -0,0 +1,403 @@ +# SAML SSO for GitLab.com groups + +> 原文:[https://docs.gitlab.com/ee/user/group/saml_sso/](https://docs.gitlab.com/ee/user/group/saml_sso/) + +* [Configuring your Identity Provider](#configuring-your-identity-provider) + * [NameID](#nameid) + * [NameID Format](#nameid-format) + * [Metadata configuration](#metadata-configuration) +* [Configuring GitLab](#configuring-gitlab) + * [SSO enforcement](#sso-enforcement) +* [Providers](#providers) + * [Azure setup notes](#azure-setup-notes) + * [Okta setup notes](#okta-setup-notes) + * [OneLogin setup notes](#onelogin-setup-notes) + * [Additional providers and setup options](#additional-providers-and-setup-options) +* [User access and management](#user-access-and-management) + * [Linking SAML to your existing GitLab.com account](#linking-saml-to-your-existing-gitlabcom-account) + * [Signing in to GitLab.com with SAML](#signing-in-to-gitlabcom-with-saml) + * [Role](#role) + * [Blocking access](#blocking-access) + * [Unlinking accounts](#unlinking-accounts) +* [Glossary](#glossary) +* [Configuring on a self-managed GitLab instance](#configuring-on-a-self-managed-gitlab-instance-premium-only) + * [Limitations](#limitations) + * [Omnibus installations](#omnibus-installations) + * [Source installations](#source-installations) +* [Troubleshooting](#troubleshooting) + * [SAML debugging tools](#saml-debugging-tools) + * [Verifying configuration](#verifying-configuration) + * [Verifying NameID](#verifying-nameid) + * [Message: “SAML authentication failed: Extern uid has already been taken”](#message-saml-authentication-failed-extern-uid-has-already-been-taken) + * [Message: “SAML authentication failed: User has already been taken”](#message-saml-authentication-failed-user-has-already-been-taken) + * [Message: “SAML authentication failed: Email has already been taken”](#message-saml-authentication-failed-email-has-already-been-taken) + * [Message: “SAML authentication failed: Extern uid has already been taken, User has already been taken”](#message-saml-authentication-failed-extern-uid-has-already-been-taken-user-has-already-been-taken) + * [Message: “Request to link SAML account must be authorized”](#message-request-to-link-saml-account-must-be-authorized) + * [Stuck in a login “loop”](#stuck-in-a-login-loop) + * [The NameID has changed](#the-nameid-has-changed) + * [I need to change my SAML app](#i-need-to-change-my-saml-app) + * [I need additional information to configure my identity provider](#i-need-additional-information-to-configure-my-identity-provider) + +# SAML SSO for GitLab.com groups[](#saml-sso-for-gitlabcom-groups-premium "Permalink") + +在 GitLab 11.0 中引入. + +此页面描述了组的 SAML. 有关自我管理的 GitLab 实例上的实例范围内的 SAML,请参阅[SAML OmniAuth Provider](../../../integration/saml.html) . + +GitLab.com 上的 SAML 允许用户通过其 SAML 身份提供商进行登录. 如果用户还不是成员,则登录过程会自动将用户添加到适当的组. + +如果您遵循我们的指导以使用[SCIM](scim_setup.html)或[组管理的帐户](group_managed_accounts.html)自动执行用户配置,则无需手动创建此类帐户. + +通过[SCIM](scim_setup.html)支持 SAML SSO 组的用户同步. SCIM 支持在 GitLab 组中添加和删除用户. 例如,如果您从 SCIM 应用程序中删除用户,则 SCIM 将从 GitLab 组中删除该用户. + +## Configuring your Identity Provider[](#configuring-your-identity-provider "Permalink") + +1. 导航到该组,然后单击**设置> SAML SSO** . +2. 使用**Assertion 使用者服务 URL** , **Identifier**和**GitLab 单一登录** **URL**来配置 SAML 服务器. 另外,GitLab 还提供[元数据 XML 配置](#metadata-configuration) . 有关更多详细信息,请参见[特定的身份提供者文档](#providers) . +3. 配置 SAML 响应以包括唯一标识每个用户的 NameID. +4. 如果使用[组托管帐户,请](group_managed_accounts.html)配置[必需的断言](group_managed_accounts.html#assertions) . +5. 设置身份提供者后,继续[配置 GitLab](#configuring-gitlab) . + +[![Issuer and callback for configuring SAML identity provider with GitLab.com](img/ebc54b5fdcb529ff40d6d097098188ae.png)](img/group_saml_configuration_information.png) + +### NameID[](#nameid "Permalink") + +GitLab.com 使用 SAML NameID 来识别用户. NameID 元素: + +* 是 SAML 响应中的必填字段. +* 每个用户必须唯一. +* 必须是永久不变的值,例如随机生成的唯一用户 ID. +* 区分大小写. NameID 必须在随后的登录尝试中完全匹配,因此不应依赖可能在大小写之间变化的用户输入. +* 不应是电子邮件地址或用户名. 我们强烈建议您反对这些,因为很难保证它们永远不会改变,例如当一个人的名字改变时. 电子邮件地址也不区分大小写,这可能导致用户无法登录. + +支持的提供程序的相关字段名称和建议值在[提供程序特定的注释中](#providers) . 适当的相应字段. + +**警告:**用户使用 SSO SAML 设置登录到 GitLab 后,更改`NameID`将破坏配置,并有可能将用户锁定在 GitLab 组之外. + +#### NameID Format[](#nameid-format "Permalink") + +我们建议将 NameID 格式设置为`Persistent`除非使用要求其他格式的字段(例如电子邮件). + +### Metadata configuration[](#metadata-configuration "Permalink") + +GitLab 提供了可用于配置身份提供者的元数据 XML. + +1. 导航到该组,然后单击**设置> SAML SSO** . +2. 复制提供的**GitLab 元数据 URL** . +3. 请遵循身份提供者的文档,并在请求时粘贴元数据 URL. + +## Configuring GitLab[](#configuring-gitlab "Permalink") + +设置好身份提供程序以与 GitLab 一起使用后,您需要配置 GitLab 以使用它进行身份验证: + +1. 导航到组的**"设置">" SAML SSO"** . +2. 从您的身份提供者中找到 SSO URL,然后在**身份提供者单点登录 URL**字段中输入 SSO URL. +3. 在" **证书"**字段中找到并输入 SAML 令牌签名证书的指纹. +4. 单击" **为此组启用 SAML 身份验证"**切换开关. +5. 点击**保存更改**按钮. + +[![Group SAML Settings for GitLab.com](img/6ea99225391da160a92dd9fd1fb01cd7.png)](img/group_saml_settings.png) + +**注意:**请注意,证书[指纹算法](#additional-providers-and-setup-options)必须在 SHA1 中. 配置身份提供者时,请使用安全签名算法. + +### SSO enforcement[](#sso-enforcement "Permalink") + +* 在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/5291) . +* 在 GitLab 11.11 中进行了[改进](https://gitlab.com/gitlab-org/gitlab/-/issues/9255) ,并在 GitLab UI 中不断实施. + +启用此选项后,用户必须浏览您组的 GitLab 单一登录 URL. 如果已配置,也可以通过 SCIM 添加它们. 无法手动添加用户,只能通过 UI 通过 SSO URL 登录来访问项目/组资源. + +但是,每次访问时都不会提示用户通过 SSO 登录. GitLab 将检查用户是否已通过 SSO 进行身份验证,并且仅在会话过期时提示用户通过 SSO 登录. + +我们打算为[Git 和 API 活动](https://gitlab.com/gitlab-org/gitlab/-/issues/9152)添加类似的 SSO 要求. + +为组启用 SSO 强制后,即使分叉了项目,用户也无法在顶级组之外的组中共享项目. + +要禁止用户在顶级组之外进行贡献,请参阅" [组管理帐户"](group_managed_accounts.html) . + +## Providers[](#providers "Permalink") + +**注意:** GitLab 无法为未在此处列出的 IdP 提供支持. + +| Provider | Documentation | +| --- | --- | +| ADFS(Active Directory 联合身份验证服务) | [Create a Relying Party Trust](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust) | +| Azure | [Configuring single sign-on to applications](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/configure-single-sign-on-non-gallery-applications) | +| Okta | [Setting up a SAML application in Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/) | +| OneLogin | [Use the OneLogin SAML Test Connector](https://onelogin.service-now.com/support?id=kb_article&sys_id=93f95543db109700d5505eea4b96198f) | + +在[配置标识提供程序时](#configuring-your-identity-provider) ,请考虑以下有关特定提供程序的注意事项,以帮助避免常见问题,并作为所用术语的指南. + +### Azure setup notes[](#azure-setup-notes "Permalink") + +有关包括 SCIM 在内的 Azure SAML 设置的演示,请参阅《 [使用针对组的 SAML SSO 的 Azure 上的 SCIM 置备》演示](https://youtu.be/24-ZxmTeEBU) . + +| 亚搏体育 app 设置 | 蔚蓝领域 | +| --- | --- | +| Identifier | 标识符(实体 ID) | +| 断言消费者服务 URL | 回复 URL(断言消费者服务 URL) | +| GitLab 单一登录 URL | 登录 URL | +| 身份提供者单点登录 URL | 登录网址 | +| 证书指纹 | Thumbprint | + +我们推荐: + +* **唯一用户标识符(名称标识符)**设置为`user.objectID` . +* **nameid-format**设置为持久. + +### Okta setup notes[](#okta-setup-notes "Permalink") + +有关 Okta SAML 设置(包括 SCIM)的[演示](https://youtu.be/0ES9HsZq0AQ) ,请参见[演示:Okta Group SAML 和 SCIM 设置](https://youtu.be/0ES9HsZq0AQ) . + +| 亚搏体育 app 设置 | Okta 场 | +| --- | --- | +| Identifier | 目标对象 URI | +| 断言消费者服务 URL | 单一登录网址 | +| GitLab 单一登录 URL | 登录页面 URL(在" **应用程序登录页面"**设置下) | +| 身份提供者单点登录 URL | 身份提供者单一登录 URL | + +在 Okta 的" **单一登录 URL"**字段下,选中" **将此用于收件人 URL 和目标 URL** "选项. + +我们推荐: + +* **应用程序用户名** (NameID)设置为**Custom** `user.getInternalProperty("id")` . +* **名称 ID 格式**设置为**Persistent** . + +### OneLogin setup notes[](#onelogin-setup-notes "Permalink") + +OneLogin 应用目录中列出的 GitLab 应用适用于自我管理的 GitLab 实例. 对于 GitLab.com,请使用通用 SAML 测试连接器,例如 SAML 测试连接器(高级). + +| 亚搏体育 app 设置 | OneLogin Field | +| --- | --- | +| Identifier | Audience | +| 断言消费者服务 URL | Recipient | +| 断言消费者服务 URL | ACS(消费者)网址 | +| 断言消费者服务 URL(转义版本) | ACS(消费者)URL 验证器 | +| GitLab 单一登录 URL | 登录网址 | +| 身份提供者单点登录 URL | SAML 2.0 端点 | + +Recommended `NameID` value: `OneLogin ID`. + +### Additional providers and setup options[](#additional-providers-and-setup-options "Permalink") + +SAML 标准意味着广泛的身份提供者将与 GitLab 一起使用. 不幸的是,我们尚未验证与所有 SAML 提供程序的连接. 有关更多信息,请参见[关于提供程序](#providers)的[讨论](#providers) . + +您的身份提供者可能具有相关的文档. 它可能是通用的 SAML 文档,也可能是专门针对 GitLab 的. 例子: + +* [Auth0](https://auth0.com/docs/protocols/saml/saml-idp-generic) +* [G Suite](https://support.google.com/a/answer/6087519?hl=en) +* [JumpCloud](https://support.jumpcloud.com/support/s/article/single-sign-on-sso-with-gitlab-2019-08-21-10-36-47) +* [PingOne by Ping Identity](https://docs.pingidentity.com/bundle/pingone/page/xsh1564020480660-1.html) + +您的身份提供商可能需要其他配置,例如: + +| Field | Value | Notes | +| --- | --- | --- | +| SAML 配置文件 | Web 浏览器 SSO 配置文件 | GitLab 使用 SAML 通过用户的浏览器登录. 我们不会直接向身份提供者发出请求. | +| SAML 请求绑定 | HTTP 重定向 | GitLab(服务提供商)使用 base64 编码的`SAMLRequest` HTTP 参数将用户重定向到您的身份提供商. | +| SAML 响应绑定 | HTTP POST | 您的身份提供者使用 HTTP 表单(包括`SAMLResponse`响应用户,该表单由用户的浏览器提交回 GitLab. | +| 签署 SAML 回应 | Yes | 我们要求这样做以防止篡改. | +| X.509 证书作为回应 | Yes | 这用于签署响应并对照提供的指纹进行检查. | +| 指纹算法 | SHA-1 | 我们需要用于签名 SAML 响应的证书的 SHA-1 哈希. | +| 签名算法 | SHA-1/SHA-256/SHA-384/SHA-512 | 也称为摘要方法,可以在 SAML 响应中指定此方法. 它确定响应的签名方式. | +| 加密 SAML 断言 | No | 在您的身份提供者,用户的浏览器和 GitLab 之间使用 TLS. | +| 签署 SAML 声明 | Optional | 我们不需要签署声明. 我们要求签署完整的回复以验证其完整性. | +| 检查 SAML 请求签名 | No | GitLab 不会对 SAML 请求进行签名,但是会检查 SAML 响应上的签名. | +| 默认 RelayState | Optional | 通过身份提供者上的按钮登录后,URL 用户应最终打开. | +| NameID 格式 | `Persistent` | See [details above](#nameid-format). | +| 其他网址 |   | 您可能需要在某些提供程序的其他字段中使用" `Identifier`或" `Assertion consumer service URL` . | +| 单一登出网址 |   | 不支持 | + +如果上面没有列出您需要的信息,则不妨查看[下面](#i-need-additional-information-to-configure-my-identity-provider)的[故障排除文档](#i-need-additional-information-to-configure-my-identity-provider) . + +## User access and management[](#user-access-and-management "Permalink") + +一旦配置并启用了 Group SSO,用户就可以通过身份提供商的仪表板访问 GitLab.com 组. 如果配置了[SCIM](scim_setup.html) ,请参阅[SCIM 页面上的](scim_setup.html#user-access-and-linking-setup) " [用户访问和链接设置"部分](scim_setup.html#user-access-and-linking-setup) . + +当用户尝试使用 Group SSO 登录时,他们将需要一个配置了以下内容之一的帐户: + +* [SCIM](scim_setup.html). +* [Group-managed accounts](group_managed_accounts.html). +* 一个 GitLab.com 帐户. + +### Linking SAML to your existing GitLab.com account[](#linking-saml-to-your-existing-gitlabcom-account "Permalink") + +要将 SAML 链接到您现有的 GitLab.com 帐户: + +1. 登录到您的 GitLab.com 帐户. +2. 找到并访问您要登录的组的**GitLab 单一登录 URL** . 群组管理员可以在群组的**"设置">" SAML SSO"**页面上找到此内容. 如果配置了登录 URL,则用户可以从身份提供者连接到 GitLab 应用. +3. Click **Authorize**. +4. 如果出现提示,请在身份提供者上输入您的凭据. +5. 您将被重定向回 GitLab.com,现在应该可以访问该组了. 将来,您可以使用 SAML 登录到 GitLab.com. + +在随后的访问中,您应该能够[使用 SAML](#signing-in-to-gitlabcom-with-saml)或直接访问链接来[登录 GitLab.com](#signing-in-to-gitlabcom-with-saml) . 如果**强制 SSO**选项已打开,您将被重定向到通过身份提供者登录. + +### Signing in to GitLab.com with SAML[](#signing-in-to-gitlabcom-with-saml "Permalink") + +1. 登录到您的身份提供商. +2. 从应用程序列表中,单击" GitLab.com"应用程序(名称由身份提供者的管理员设置). +3. 您将登录到 GitLab.com,并重定向到该组. + +### Role[](#role "Permalink") + +首次登录时,GitLab 会将您添加到具有 Guest 角色的顶级父组中. 具有适当特权的现有成员可以提升该新用户. + +如果用户已经是组的成员,则链接 SAML 身份不会更改其角色. + +### Blocking access[](#blocking-access "Permalink") + +要取消对该组的访问,请按顺序执行以下步骤: + +1. 从身份提供者上的用户数据存储中删除用户,或从特定应用程序上的用户列表中删除用户. +2. 从 GitLab.com 组中删除用户. + +### Unlinking accounts[](#unlinking-accounts "Permalink") + +用户可以从其个人资料页面取消链接组的 SAML. 在以下情况下这可能会有所帮助: + +* 您不再希望某个群组能够登录 GitLab.com. +* 您的 SAML NameID 已更改,因此 GitLab 无法再找到您的用户. + +例如,要取消链接`MyOrg`帐户,以下" **断开连接"**按钮将在" **配置文件">"帐户"**下可用: + +[![Unlink Group SAML](img/b203ae7a973815c03ea680032d1e75eb.png)](img/unlink_group_saml.png) + +## Glossary[](#glossary "Permalink") + +| Term | Description | +| --- | --- | +| 身份提供者 | 管理您的用户身份的服务,例如 ADFS,Okta,Onelogin 或 Ping 身份. | +| 服务提供者 | SAML 认为 GitLab 是服务提供商. | +| Assertion | 有关用户身份的一条信息,例如他们的姓名或角色. 也称为声明或属性. | +| SSO | 单一登录. | +| 断言消费者服务 URL | 在 GitLab 上的回调,在通过身份提供商成功进行身份验证后,将重定向用户. | +| Issuer | manbetx 客户端打不开如何向身份提供商识别自己. 也称为"信赖方信任标识符". | +| 证书指纹 | 用于通过检查服务器是否使用正确的证书对通信进行签名来确认通过 SAML 进行的通信是否安全. 也称为证书指纹. | + +## Configuring on a self-managed GitLab instance[](#configuring-on-a-self-managed-gitlab-instance-premium-only "Permalink") + +对于自我管理的 GitLab 实例,我们强烈建议改用[实例范围的 SAML OmniAuth Provider](../../../integration/saml.html) . + +如果您需要允许通过多个 SAML 身份提供者进行访问,Group SAML SSO 可以提供帮助,但是作为多租户解决方案,它不太适合您管理自己的 GitLab 实例的情况. + +要改为继续配置 Group SAML SSO,您需要启用`group_saml` OmniAuth 提供程序. 这可以通过以下方式完成: + +* `gitlab.rb`用于 GitLab [Omnibus 安装](#omnibus-installations) . +* `gitlab/config/gitlab.yml` for [source installations](#source-installations). + +### Limitations[](#limitations "Permalink") + +与建议的[实例范围的 SAML](../../../integration/saml.html)相比,自管理实例上的组 SAML 受到限制. 推荐的解决方案使您可以利用: + +* [LDAP compatibility](../../../administration/auth/ldap/index.html). +* [LDAP Group Sync](../index.html#manage-group-memberships-via-ldap). +* [Required groups](../../../integration/saml.html#required-groups-starter-only). +* [Admin groups](../../../integration/saml.html#admin-groups-starter-only). +* [Auditor groups](../../../integration/saml.html#auditor-groups-starter-only). + +### Omnibus installations[](#omnibus-installations "Permalink") + +1. 确保为 GitLab [配置了 HTTPS](../../../install/installation.html#using-https) . +2. 启用 OmniAuth 和`group_saml`在提供`gitlab.rb` : + + ``` + gitlab_rails['omniauth_enabled'] = true + gitlab_rails['omniauth_providers'] = [{ name: 'group_saml' }] + ``` + +### Source installations[](#source-installations "Permalink") + +1. 确保为 GitLab [配置了 HTTPS](../../../install/installation.html#using-https) . +2. 在`gitlab/config/gitlab.yml`启用 OmniAuth 和`group_saml`提供程序: + + ``` + omniauth: + enabled: true + providers: + - { name: 'group_saml' } + ``` + +## Troubleshooting[](#troubleshooting "Permalink") + +本节包含可能遇到的问题的可能解决方案. + +### SAML debugging tools[](#saml-debugging-tools "Permalink") + +SAML 响应是 base64 编码的,因此我们建议使用以下浏览器插件即时对其进行解码: + +* [SAML tracer for Firefox](https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/) +* [Chrome SAML Panel](https://chrome.google.com/webstore/detail/saml-chrome-panel/paijfdbeoenhembfhkhllainmocckace?hl=en) + +应特别注意: + +* [NameID](#nameid) (我们用来标识正在登录的用户).如果该用户先前已登录,则该[ID 必须与我们存储的值匹配](#verifying-nameid) . +* `X509Certificate`的存在,我们需要使用它来验证响应签名. +* `SubjectConfirmation`和`Conditions` ,如果配置错误,可能会导致错误. + +### Verifying configuration[](#verifying-configuration "Permalink") + +For convenience, we’ve included some [example resources](../../../administration/troubleshooting/group_saml_scim.html) used by our Support Team. While they may help you verify the SAML app configuration, they are not guaranteed to reflect the current state of third-party products. + +### Verifying NameID[](#verifying-nameid "Permalink") + +在对组 SAML 设置进行故障排除时,任何经过身份验证的用户都可以通过访问[https://gitlab.com/api/v4/user](https://gitlab.com/api/v4/user)并检查身份下的`extern_uid`来使用 API​​来验证 NameID GitLab 是否已链接到该用户. + +同样,具有适当权限的角色的组成员可以使用[成员 API](../../../api/members.html)来查看该组成员的组 SAML 身份信息. + +然后可以通过使用[SAML 调试工具](#saml-debugging-tools)解码消息,将其与身份提供者发送的[NameID](#nameid)进行比较. 我们要求这些匹配项以识别用户. + +### Message: “SAML authentication failed: Extern uid has already been taken”[](#message-saml-authentication-failed-extern-uid-has-already-been-taken "Permalink") + +此错误表明您已以 GitLab 用户身份登录,但已将 SAML 身份链接到其他 GitLab 用户. 退出,然后尝试使用 SSO SAML 链接再次登录,该链接应使用链接的用户帐户将您登录到 GitLab. + +如果您不希望通过 SAML 登录使用该 GitLab 用户,则可以[取消 GitLab 帐户与该组的 SAML 的链接](#unlinking-accounts) . + +### Message: “SAML authentication failed: User has already been taken”[](#message-saml-authentication-failed-user-has-already-been-taken "Permalink") + +与您登录的用户已经将 SAML 链接到另一个身份. 以下是可能的原因和解决方案: + +| Cause | Solution | +| --- | --- | +| You’ve tried to link multiple SAML identities to the same user, for a given Identity Provider. | 更改用于登录的身份. 为此,请先从此 GitLab 帐户[取消链接先前的 SAML 身份](#unlinking-accounts) ,然后再尝试登录. | + +### Message: “SAML authentication failed: Email has already been taken”[](#message-saml-authentication-failed-email-has-already-been-taken "Permalink") + +| Cause | Solution | +| --- | --- | +| 当具有电子邮件地址的用户帐户已经存在于 GitLab 中时,但该用户没有绑定到其帐户的 SAML 身份. | 用户将需要[链接他们的帐户](#user-access-and-management) . | + +### Message: “SAML authentication failed: Extern uid has already been taken, User has already been taken”[](#message-saml-authentication-failed-extern-uid-has-already-been-taken-user-has-already-been-taken "Permalink") + +同时获得这两个错误表明,身份提供者提供的 NameID 大写字母与该用户的先前值不完全匹配. + +可以通过配置[NameID](#nameid)返回一致的值来防止这种情况. 为单个用户解决此问题涉及[取消 GitLab 帐户中的 SAML 链接](#unlinking-accounts) ,尽管这将导致组成员身份和 Todos 丢失. + +### Message: “Request to link SAML account must be authorized”[](#message-request-to-link-saml-account-must-be-authorized "Permalink") + +确保尝试链接其 GitLab 帐户的用户已添加为身份提供者的 SAML 应用中的用户. + +### Stuck in a login “loop”[](#stuck-in-a-login-loop "Permalink") + +确保在身份提供者的 SAML 应用中将**GitLab 单一登录 URL**配置为"登录 URL"(或类似命名的字段). + +另外,当用户需要[将 SAML 链接到其现有的 GitLab.com 帐户时](#linking-saml-to-your-existing-gitlabcom-account) ,请提供**GitLab 单一登录 URL,**并指示用户不要在首次登录时使用 SAML 应用. + +### The NameID has changed[](#the-nameid-has-changed "Permalink") + +| Cause | Solution | +| --- | --- | +| 如[NameID](#nameid)部分所述,如果 NameID 对于任何用户都发生了更改,则可以将用户锁定. 当电子邮件地址用作标识符时,这是一个常见问题. | 请按照[" SAML 身份验证失败:用户已被使用"](#message-saml-authentication-failed-user-has-already-been-taken)部分中概述的步骤进行操作. 如果许多用户受到影响,建议您使用适当的 API. | + +### I need to change my SAML app[](#i-need-to-change-my-saml-app "Permalink") + +用户将需要[取消链接当前的 SAML 身份](#unlinking-accounts) , [并将其身份链接](#user-access-and-management)到新的 SAML 应用. + +### I need additional information to configure my identity provider[](#i-need-additional-information-to-configure-my-identity-provider "Permalink") + +提供商之间的许多 SAML 术语可能会有所不同. 您正在查找的信息可能以其他名称列出. + +有关更多信息,请从您的身份提供商的文档开始. 查找他们的选项和示例,以了解他们如何配置 SAML. 这可以提供有关配置 GitLab 以便与这些提供程序一起使用所需的提示. + +它也有助于查看我们[有关自管理 GitLab 的更详细的文档](../../../integration/saml.html) . GitLab.com 的 SAML 配置与自我管理实例的 SAML 配置基本相同. 但是,自我管理的 GitLab 实例使用支持更多选项的配置文件,如外部[OmniAuth SAML 文档中所述](https://github.com/omniauth/omniauth-saml/) . 在内部使用[`ruby-saml`库](https://github.com/onelogin/ruby-saml) ,因此我们有时在此处检查以验证不常用选项的低级详细信息. + +它还可以帮助将提供商的 XML 响应与我们[用于内部测试的 XML 示例进行比较](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/spec/fixtures/saml/response.xml) . \ No newline at end of file diff --git a/_book/docs/045.md b/_book/docs/045.md new file mode 100644 index 0000000000000000000000000000000000000000..0217c80a46763c70f823cf0eb5d2a6d850aefc25 --- /dev/null +++ b/_book/docs/045.md @@ -0,0 +1,254 @@ +# SCIM provisioning using SAML SSO for GitLab.com groups + +> 原文:[https://docs.gitlab.com/ee/user/group/saml_sso/scim_setup.html](https://docs.gitlab.com/ee/user/group/saml_sso/scim_setup.html) + +* [Features](#features) +* [Requirements](#requirements) +* [GitLab configuration](#gitlab-configuration) +* [Identity Provider configuration](#identity-provider-configuration) + * [Azure configuration steps](#azure-configuration-steps) + * [Configure attribute mapping](#configure-attribute-mapping) + * [Okta configuration steps](#okta-configuration-steps) + * [Okta Known Issues](#okta-known-issues) +* [User access and linking setup](#user-access-and-linking-setup) + * [Blocking access](#blocking-access) +* [Troubleshooting](#troubleshooting) + * [Azure](#azure) + * [How do I verify my SCIM configuration is correct?](#how-do-i-verify-my-scim-configuration-is-correct) + * [Testing Azure connection: invalid credentials](#testing-azure-connection-invalid-credentials) + * [Azure: (Field) can’t be blank sync error](#azure-field-cant-be-blank-sync-error) + * [How do I diagnose why a user is unable to sign in](#how-do-i-diagnose-why-a-user-is-unable-to-sign-in) + * [How do I verify user’s SAML NameId matches the SCIM externalId](#how-do-i-verify-users-saml-nameid-matches-the-scim-externalid) + * [Update or fix mismatched SCIM externalId and SAML NameId](#update-or-fix-mismatched-scim-externalid-and-saml-nameid) + * [I need to change my SCIM app](#i-need-to-change-my-scim-app) + +# SCIM provisioning using SAML SSO for GitLab.com groups[](#scim-provisioning-using-saml-sso-for-gitlabcom-groups-silver-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in [GitLab.com Silver](https://about.gitlab.com/pricing/) 11.10. + +跨域身份管理系统(SCIM)是一种开放标准,可实现用户自动配置. 当为 GitLab 组配置 SCIM 时,该组的成员资格将在 GitLab 和身份提供者之间同步. + +GitLab 的[SCIM API](../../../api/scim.html)实现[了 RFC7644 协议的](https://tools.ietf.org/html/rfc7644)一部分. + +## Features[](#features "Permalink") + +当前,可以执行以下操作: + +* 建立使用者 +* 更新用户(仅限 Azure) +* 停用用户 + +支持以下身份提供者: + +* Azure +* Okta + +## Requirements[](#requirements "Permalink") + +* 必须配置[组单一登录](index.html) . + +## GitLab configuration[](#gitlab-configuration "Permalink") + +配置[组单一登录后](index.html) ,我们可以: + +1. 导航到该组,然后单击**管理> SAML SSO** . +2. 单击**生成 SCIM 令牌**按钮. +3. 保存令牌和 URL,以便可以在下一步中使用它们. + +[![SCIM token configuration](img/c187de65e481b5598b110fee5310776c.png)](img/scim_token.png) + +## Identity Provider configuration[](#identity-provider-configuration "Permalink") + +* [Azure](#azure-configuration-steps) +* [Okta](#okta-configuration-steps) + +### Azure configuration steps[](#azure-configuration-steps "Permalink") + +现在需要为 SCIM 设置在[Azure 的](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/configure-single-sign-on-non-gallery-applications) [单点登录](index.html)安装过程中创建的 SAML 应用程序. + +1. 检查您的 GitLab SAML 应用程序的配置,并确保**名称标识符值** (NameID)指向`user.objectid`或另一个唯一标识符. 这将与 GitLab 上使用的`extern_uid`匹配. + + [![Name identifier value mapping](img/fe827d4bc97b90c3a250af05fd988fc4.png)](img/scim_name_identifier_mapping.png) + +2. 通过遵循针对 Azure [支持](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#provisioning-users-and-groups-to-applications-that-support-scim)的 SCIM 安装文档[中支持 SCIM 的应用程序](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#provisioning-users-and-groups-to-applications-that-support-scim)的[供应用户和组,来](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#provisioning-users-and-groups-to-applications-that-support-scim)设置自动供应和管理凭据. + +During this configuration, note the following: + +* `Tenant URL`和`secret token`是在[上一步中](#gitlab-configuration)检索到的. +* 如果 GitLab 的可用性有任何问题或类似错误,则通知电子邮件集将获得这些信息. +* 建议设置通知电子邮件并选中**发生故障时发送电子邮件通知**复选框. +* 对于映射,我们将仅启用"将`Synchronize Azure Active Directory Users to AppName`启用状态. + +然后,您可以通过单击" **测试连接"**来**测试连接** . 如果连接成功,请确保在继续操作之前保存配置. 请参阅下面的[疑难解答](#troubleshooting) . + +#### Configure attribute mapping[](#configure-attribute-mapping "Permalink") + +1. 单击"将`Synchronize Azure Active Directory Users to AppName`以配置属性映射. +2. 单击`mail`映射旁边的**删除** . +3. 将`userPrincipalName`映射到`emails[type eq "work"].value`并将其**Matching 优先级**更改为`2` . +4. Map `mailNickname` to `userName`. +5. 确定 GitLab 如何唯一标识用户. + + * 除非用户已经为您的组链接了 SAML,否则请使用`objectId` . + * 如果已经有链接 SAML 的用户,则使用[SAML 配置中](#azure)的" `Name ID`值. 使用其他值可能会导致用户重复并阻止用户访问 GitLab 组. +6. 创建一个新的映射: + 1. 单击**添加新映射** . + 2. 组: + * 上面确定的唯一标识符的**Source 属性** ,通常是`objectId` . + * **目标属性**为`externalId` . + * **使用此属性**将**对象匹配**为`Yes` . + * **匹配优先级**为`1` . +7. 单击`userPrincipalName`映射,然后**使用此属性**将**Match 对象**更改为`No` + +8. 保存您的更改. 作为参考,您可以[在故障排除参考中](../../../administration/troubleshooting/group_saml_scim.html#azure-active-directory)查看[示例配置](../../../administration/troubleshooting/group_saml_scim.html#azure-active-directory) . + + **注意:**如果您使用**除** `objectId` **之外**的唯一标识符,请确保将其映射到`externalId` . +9. 在映射列表下,单击**显示高级选项>编辑 AppName 的属性列表** . + +10. 确保`id`是主要字段和必填字段,并且还需要`externalId` . + + **注意:** `username`既不是主要`username`也不是必需的,因为我们尚不支持 GitLab SCIM 上的该字段. +11. 保存所有屏幕,然后在**Provisioning**步骤中将`Provisioning Status`设置为`On` . + + [![Provisioning status toggle switch](img/4c6172d095020a91bcf8d48c85ee4d1d.png)](img/scim_provisioning_status.png) + + **注意:**您可以通过选择`Scope`来控制实际同步的内容. 例如, `Sync only assigned users and groups`将仅同步分配给应用程序的`Users and groups` ( `Users and groups` ),否则,它将同步整个 Active Directory. + +一旦启用,同步细节的任何错误都出现在**供应**屏幕的底部,有一个链接到审计日志在一起. + +**警告:**同步后,将映射到`id`和`externalId`的字段更改可能会导致配置错误,用户重复,并阻止现有用户访问 GitLab 组. + +### Okta configuration steps[](#okta-configuration-steps "Permalink") + +现在需要为 SCIM 设置在[Okta 的](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/) [单点登录](index.html#okta-setup-notes)安装过程中创建的 SAML 应用程序. 在继续之前,请确保完成[GitLab 配置](#gitlab-configuration)过程. + +1. 登录到 Okta. +2. 如果您在右上角看到一个**管理**按钮,请单击该按钮. 这将确保您位于"管理"区域. + + **提示:**如果您在使用开发者控制台,点击**开发者控制台**顶部栏并选择**经典的 UI.** 否则,您可能看不到以下步骤中描述的按钮: +3. 在" **应用程序"**选项卡中,单击" **添加应用程序"** . +4. Search for **GitLab**, find and click on the ‘GitLab’ application. +5. 在 GitLab 应用程序概述页面上,单击**添加** . +6. 在" **应用程序可见性"下,**选中两个复选框. 当前,GitLab 应用程序不支持 SAML 身份验证,因此不应向用户显示该图标. +7. 单击**"完成"**以完成添加应用程序. +8. 在**供应**标签中,点击**配置 API 集成** . +9. Select **启用 API 集成**. + * 对于**基本 URL,**输入从 GitLab SCIM 配置页面获得的 URL. + * 对于**API 令牌,**输入从 GitLab SCIM 配置页面获得的 SCIM 令牌. +10. 点击"测试 API 凭据"以验证配置. +11. 单击**保存**以应用设置. +12. After saving the API integration details, new settings tabs will appear on the left. Choose **到应用**. +13. Click **Edit**. +14. 选中"为**创建用户**和**停用用户** **启用** "复选框. +15. Click **Save**. +16. 在" **分配"**选项卡中分配用户. 分配的用户将在您的 GitLab 组中创建和管理. + +#### Okta Known Issues[](#okta-known-issues "Permalink") + +Okta GitLab 应用程序当前仅支持 SCIM. 继续使用单独的 Okta [SAML SSO](index.html)配置以及上述新的 SCIM 应用程序. + +## User access and linking setup[](#user-access-and-linking-setup "Permalink") + +只要已经配置了[Group SAML](index.html) ,就可以在启用同步之前,在激活同步之前,现有的 GitLab.com 用户可以通过以下方式之一链接到其帐户: + +* 通过更新其 GitLab.com 用户帐户中的*主要*电子邮件地址以匹配其身份提供商的用户个人资料电子邮件地址. +* 通过执行以下步骤: + + 1. 如果需要,登录到 GitLab.com. + 2. 在身份提供商的仪表板上单击 GitLab 应用程序,或访问**GitLab 单一登录 URL** . + 3. 单击**授权**按钮. + +后续访问中的新用户和现有用户可以通过身份提供商的仪表板或直接访问链接来访问组. + +有关角色信息,请参阅[组 SAML 页面](index.html#user-access-and-management) + +### Blocking access[](#blocking-access "Permalink") + +要取消对该组的访问,我们建议从身份提供商或特定应用程序的用户列表中删除该用户. + +在下一次同步时,将取消提供该用户,这意味着该用户将从组中删除. 除非使用[组托管帐户,](group_managed_accounts.html)否则不会删除该用户帐户. + +## Troubleshooting[](#troubleshooting "Permalink") + +本节包含可能遇到的问题的可能解决方案. + +### Azure[](#azure "Permalink") + +#### How do I verify my SCIM configuration is correct?[](#how-do-i-verify-my-scim-configuration-is-correct "Permalink") + +查看以下内容: + +* 确保`id`的 SCIM 值与`NameId`的 SAML 值匹配. +* 确保`externalId`的 SCIM 值与`NameId`的 SAML 值匹配. + +查看以下 SCIM 参数以获取合理的值: + +* `userName` +* `displayName` +* `emails[type eq "work"].value` + +#### Testing Azure connection: invalid credentials[](#testing-azure-connection-invalid-credentials "Permalink") + +测试连接时,您可能会遇到错误: **您似乎输入了无效的凭据.** **请确认您使用的管理帐户信息正确** . 如果`Tenant URL`和`secret token`正确,请检查您的组路径中是否包含可能被视为无效 JSON 原语的字符(例如`.` ). 从组路径中删除此类字符通常可以解决该错误. + +#### Azure: (Field) can’t be blank sync error[](#azure-field-cant-be-blank-sync-error "Permalink") + +在检查供应的审核日志时,有时您会看到错误`Namespace can't be blank, Name can't be blank, and User can't be blank.` + +这可能是由于没有为所有要映射的用户提供所有必填字段(例如名字和姓氏). + +作为解决方法,请尝试其他映射: + +1. 请按照上面的 Azure 映射说明进行操作. +2. 删除`name.formatted`目标属性条目. +3. 将`displayName`源属性更改为具有`name.formatted`目标属性. + +#### How do I diagnose why a user is unable to sign in[](#how-do-i-diagnose-why-a-user-is-unable-to-sign-in "Permalink") + +每当`id`或`externalId`更改时,SCIM 都会更新 GitLab 存储的**Identity** ( `extern_uid` )值. 除非 GitLab 标识( `extern_uid` )值与 SAML 发送的`NameId`匹配,否则用户将无法登录. + +SCIM 还将使用此值来匹配`id`上的用户,并且只要`id`或`externalId`值发生更改,SCIM 就会更新此值. + +将此 SCIM `id`和 SCIM `externalId`配置为与 SAML `NameId`相同的值很重要. 可以使用[调试工具](./index.html#saml-debugging-tools)跟踪 SAML 响应,并且可以根据我们的[SAML 故障排除文档](./index.html#troubleshooting)检查任何错误. + +#### How do I verify user’s SAML NameId matches the SCIM externalId[](#how-do-i-verify-users-saml-nameid-matches-the-scim-externalid "Permalink") + +组所有者可以在组 SAML SSO 设置页面中查看用户列表和为每个用户存储的`externalId` . + +另外,在[SCIM API](../../../api/scim.html#get-a-list-of-saml-users)可用于手动检索`externalId` ,我们已经存储了用户,也被称为`external_uid`或`NameId` . + +例如: + +``` +curl 'https://example.gitlab.com/api/scim/v2/groups/GROUP_NAME/Users?startIndex=1"' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +要查看它与作为 SAML NameId 返回的值的比较,可以让用户使用[SAML Tracer](index.html#saml-debugging-tools) . + +#### Update or fix mismatched SCIM externalId and SAML NameId[](#update-or-fix-mismatched-scim-externalid-and-saml-nameid "Permalink") + +无论是更改值还是需要映射到其他字段,请确保`id` , `externalId`和`NameId`都映射到同一字段. + +如果 GitLab 的`externalId`与 SAML NameId 不匹配,则需要对其进行更新才能使用户登录.理想情况下,将身份标识提供者配置为进行此类更新,但是在某些情况下,它可能无法这样做. ,例如在查找用户时由于 ID 更改而失败. + +如果您修改 SCIM 身份提供程序使用的字段,请务必谨慎,通常为`id`和`externalId` . 我们使用这些 ID 查找用户. 如果身份提供者不知道这些字段的当前值,则该提供者可以创建重复的用户. + +如果用户的`externalId`不正确,并且也与 SAML NameID 不匹配,则可以通过以下方式解决该问题: + +* 您可以根据[" SAML 身份验证失败:用户已被使用"](./index.html#message-saml-authentication-failed-user-has-already-been-taken)部分,使用户取消链接并重新链接自己. +* 通过在启用预配置的同时从 SAML 应用中删除所有用户,可以同时取消所有用户的链接. +* 您可以使用[SCIM API](../../../api/scim.html#update-a-single-saml-user)手动更正为用户存储的`externalId`以匹配 SAML `NameId` . 要查找用户,您需要知道与`NameId`以及当前`externalId`匹配的`NameId` . + +然后可以发出手动 SCIM#update 请求,例如: + +``` +curl --verbose --request PATCH 'https://gitlab.com/api/scim/v2/groups/YOUR_GROUP/Users/OLD_EXTERNAL_UID' --data '{ "Operations": [{"op":"Replace","path":"externalId","value":"NEW_EXTERNAL_UID"}] }' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +重要的是不要将这些值更新为不正确的值,因为这将导致用户无法登录.也不要将值分配给错误的用户,这也很重要,因为这将导致用户登录到错误的帐户. + +#### I need to change my SCIM app[](#i-need-to-change-my-scim-app "Permalink") + +各个用户可以按照[" SAML 身份验证失败:用户已被使用"](./index.html#i-need-to-change-my-saml-app)部分中的说明进行操作. + +或者,可以从 SCIM 应用程序中删除用户,这将取消所有已删除用户的链接. 然后可以为新的 SCIM 应用打开同步,以[链接现有用户](#user-access-and-linking-setup) . \ No newline at end of file diff --git a/_book/docs/046.md b/_book/docs/046.md new file mode 100644 index 0000000000000000000000000000000000000000..31e89420729d95a6f9dc4be60ce3c7ac7886901f --- /dev/null +++ b/_book/docs/046.md @@ -0,0 +1,149 @@ +# Subgroups + +> 原文:[https://docs.gitlab.com/ee/user/group/subgroups/](https://docs.gitlab.com/ee/user/group/subgroups/) + +* [Overview](#overview) +* [Creating a subgroup](#creating-a-subgroup) +* [Membership](#membership) + * [Overriding the ancestor group membership](#overriding-the-ancestor-group-membership) +* [Mentioning subgroups](#mentioning-subgroups) +* [Limitations](#limitations) + +# Subgroups[](#subgroups "Permalink") + +在 GitLab 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/2772) . + +GitLab 支持多达 20 个级别的子组,也称为嵌套组或层次结构组. 组的级别. + +通过使用子组,您可以执行以下操作: + +* **独立的内部/外部组织.** 由于每个组都有自己的可见性级别,因此您可以在同一保护范围内为不同目的托管组. +* **组织大型项目.** 对于大型项目,子组可能会更容易分隔部分源代码的权限. +* **使管理人员和控制可见性变得更加容易.** 根据人们的组[成员身份,](#membership)赋予他们不同的[权限](../../permissions.html#group-members-permissions) . + +有关组和项目中允许的权限的更多信息,请参见[可见性级别](../../../development/permissions.html#general-permissions) . + +## Overview[](#overview "Permalink") + +一个组中可以有许多子组,而同一组中只能有一个直接父组. 它类似于目录行为或嵌套项目列表: + +* 第一组 + * 1.1 组 + * 1.2 组 + * 1.2.1 组 + * 1.2.2 组 + * 组 1.2.2.1 + +在一个真实的示例中,设想维护一个 GNU / Linux 发行版,其中第一个组是发行版的名称,随后的组按如下所示拆分: + +* Organization Group - GNU/Linux distro + * 类别子组-包 + * (项目)配套 01 + * (项目)配套 02 + * 类别子组-软件 + * (项目)核心 + * (项目)CLI + * (项目)Android 应用 + * (项目)iOS 应用 + * 类别子组-红外线工具 + * (项目)Ansible 剧本 + +Another example of GitLab as a company would be the following: + +* 组织组-GitLab + * 类别子组-市场营销 + * (项目)设计 + * (项目)一般 + * 类别子组-软件 + * (项目)GitLab CE + * (项目)GitLab EE + * (项目)Omnibus GitLab + * (项目)GitLab Runner + * (项目)GitLab Pages 守护程序 + * 类别子组-红外线工具 + * (项目)厨师食谱 + * 类别子组-执行团队 + +* * * + +当执行诸如在子组之间转移或导入项目的操作时,其行为与在`group/project`级别执行这些操作时的行为相同. + +## Creating a subgroup[](#creating-a-subgroup "Permalink") + +要创建子组,您必须是该组的所有者或维护者,具体取决于该组的设置. + +默认情况下,在以下位置创建的组: + +* GitLab 12.2 或更高版本允许所有者和维护者创建子组. +* GitLab 12.1 或更早版本仅允许所有者创建子组. + +此设置可以是所有者或管理员的任何组. + +有关更多信息,请检查[权限表](../../permissions.html#group-members-permissions) . 有关不允许用作组名的单词列表,请参见[保留名称](../../reserved_names.html) . + +如果将子组明确地作为所有者(或维护者,如果启用了此设置)添加到直接父组,则用户始终可以创建子组,即使管理员在其设置中禁用了组创建也是如此. + +要创建一个子组: + +1. 在组的仪表板中,展开" **新建项目**拆分"按钮,选择" **新建子组"** ,然后单击" **新建子组"**按钮. + + [![Subgroups page](img/c3c27ff673c33bcd50004c2adb617d5f.png)](img/create_subgroup_button.png) + +2. 像平常一样创建一个新组. 请注意,直接父组名称空间在" **组路径"**下是固定的. 可见性级别可以与直接父组不同. + + [![Subgroups page](img/7fb24fed9f39dcdabb530523bcb8dc08.png)](img/create_new_group.png) + +3. 单击**创建组**按钮,您将被带到新组的仪表板页面. + +按照相同的过程创建任何后续组. + +## Membership[](#membership "Permalink") + +将成员添加到子组时,它们将从父组继承成员资格和权限级别. 如果您是其父级成员之一,则该模型允许访问嵌套组. + +在亚组可以用乔布斯的管道[运动员](../../../ci/runners/README.html)注册到父组(S). 这意味着为父组配置的机密可用于子组作业. + +此外,属于子组的项目的维护者可以查看注册到父组的 Runner 的详细信息. + +成员的组权限只能由所有者更改,并且只能在添加成员的组的" **成员"**页面上进行. + +您可以通过查看组的" **成员"**页面来确定成员是否从父组继承了权限. + +[![Group members page](img/e18ff80d06980688066f9ec9404bd2da.png)](img/group_members.png) + +从上图可以得出以下几点: + +* 有 5 位成员可以访问第`four`组. +* User0 是一个 Reporter,已从组`four`的层次结构上方的组`one`继承了其权限. +* 用户 1 是一个开发并已继承组他们的权限`one/two`其是组的层级以上`four` . +* 用户 2 是一个开发并已继承组他们的权限`one/two/three`这是组的层级以上`four` . +* 对于 User3,没有任何父组的指示,因此它们属于`four`组,即我们正在检查的组. +* 管理员是**所有**子组的所有者和成员,因此,与 User3 一样,没有任何祖先组的迹象. + +[在](https://gitlab.com/gitlab-org/gitlab/-/issues/21727) GitLab 12.6 中,您可以使用右侧的下拉列表过滤此列表: + +[![Group members filter](img/8215c374294289cd2bd24399439403fd.png)](img/group_members_filter_v12_6.png) + +* **仅显示直接成员**仅显示 Administrator 和 User3,因为这是属于`four`组的唯一用户,这是我们正在检查的用户. +* **仅显示继承的成员将**显示 User0,User1 和 User2,无论层次结构上方的哪个组都是继承权限的来源. + +### Overriding the ancestor group membership[](#overriding-the-ancestor-group-membership "Permalink") + +**注意:**您必须是网上论坛的所有者,才能向其中添加成员.**注意:**子组中的用户权限不能低于其任何祖先组中的权限. 因此,您不能针对子组的祖先组减少用户的权限. + +要覆盖用户的祖先组(他们被添加到的第一个组)的成员资格,请将该用户再次以更高的权限集添加到新的子组中. + +例如,如果首先使用具有开发者权限将 User0 添加到组`group-1/group-1-1` ,则它们将在组`group-1/group-1-1`每个其他子`group-1/group-1-1`继承这些权限. 要为他们提供维护者访问`group-1/group-1-1/group1-1-1` ,您可以将他们再次添加为该维护者. 从该组中删除它们,权限将回退到祖先组的权限. + +## Mentioning subgroups[](#mentioning-subgroups "Permalink") + +在问题,提交和合并请求中提及组( `@group` )将通知该组的所有成员. 现在有了子组,如果您想拆分组的结构,将有更精细的支持. 提及方式与以前一样,您可以选择要通知的人群. + +[![Mentioning subgroups](img/0d1089161431c5f21751458027d84535.png)](img/mention_subgroups.png) + +## Limitations[](#limitations "Permalink") + +以下是您无法对子组进行操作的列表: + +* [GitLab 页面](../../project/pages/index.html)支持在一个子组下托管的项目,但不支持子组网站下的项目. 这意味着,尽管您可以在子组下拥有项目网站,但是只有最高级别的组才支持[组网站](../../project/pages/getting_started_part_one.html#gitlab-pages-default-domain-names) . +* 不能与作为该项目所属组的祖先的组共享项目.这意味着您只能在沿层次结构走时共享. 例如, `group/subgroup01/project` **不能**与`group`共享,但是可以与`group/subgroup02`或`group/subgroup01/subgroup03`共享. \ No newline at end of file diff --git a/_book/docs/047.md b/_book/docs/047.md new file mode 100644 index 0000000000000000000000000000000000000000..ddb56143267ac8aa9a4343d63d0877122cee9dff --- /dev/null +++ b/_book/docs/047.md @@ -0,0 +1,81 @@ +# Roadmap + +> 原文:[https://docs.gitlab.com/ee/user/group/roadmap/](https://docs.gitlab.com/ee/user/group/roadmap/) + +* [Timeline duration](#timeline-duration) + * [Quarters](#quarters) + * [Months](#months) + * [Weeks](#weeks) +* [Roadmap timeline bar](#roadmap-timeline-bar) + +# Roadmap[](#roadmap-premium "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.5 中引入. +* 在[GitLab 12.9 中](https://gitlab.com/gitlab-org/gitlab/-/issues/198062) ,路线图已移至高级层. +* 在[GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/5164)及更高版本中,史诗条显示史诗的标题,进度和完成的重量百分比. +* 里程碑出现在[GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/issues/6802)及更高版本的路线图中. +* 在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29641)删除的路线图中可见的里程碑的功能标志. +* 在[GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/214375)和更高版本中,该路线图还显示了组中项目的里程碑. +* 在[GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/212494)和更高版本中,里程碑栏可以折叠和展开. + +可以以时间轴(即甘特图)的形式显示包含开始日期或截止日期的组中的史诗和里程碑. "路线图"页面显示了一个组,一个子组或一个组中的一个项目的史诗和里程碑. + +在史诗栏上,您可以看到每个史诗的标题,进度和完成的重量百分比. 当您将鼠标悬停在史诗栏上时,将显示一个弹出框,其中包含史诗的标题,开始日期,到期日和完成的权重. + +您可以展开包含子级史诗的史诗,以在路线图中显示其子级史诗. 您可以单击人字形( )旁边的史诗标题,以展开和折叠子史诗. + +在里程碑栏的顶部,您可以看到其标题. 当您将鼠标悬停在里程碑栏或标题上时,将显示一个带有其标题,开始日期和截止日期的弹出窗口. 您也可以点击 V 形符号( )旁边的" **里程碑"**标题以切换里程碑栏的列表. + +[![roadmap view](img/b44c56313892b2d78da86b3f64519a98.png)](img/roadmap_view_v13_2.png) + +下拉菜单允许您仅显示打开或关闭的史诗. 默认情况下,显示所有史诗. + +[![epics state dropdown](img/9fa8173be554c09a1397ae7e064f24e5.png)](img/epics_state_dropdown_v12_10.png) + +您可以通过以下方式在"路线图"视图中对史诗进行排序: + +* 创建日期 +* 最近更新时间 +* 开始日期 +* 截止日期 + +每个选项都包含一个按钮,可在**升序**和**降序**之间切换排序顺序. 浏览史诗(包括[史诗列表视图)](../epics/index.html)时,排序选项和顺序仍然存在. + +路线图也可以[在史诗内部可视化](../epics/index.html#roadmap-in-epics) . + +## Timeline duration[](#timeline-duration "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0 中引入. +* 在[GitLab 12.9 中](https://gitlab.com/gitlab-org/gitlab/-/issues/198062) ,时间轴已移至高级层. + +路线图支持以下日期范围: + +* Quarters +* 月(默认) +* Weeks + +### Quarters[](#quarters "Permalink") + +[![roadmap date range in quarters](img/ecb561241f5fcf0f0695ee4e29069b11.png)](img/roadmap_timeline_quarters.png) + +在" **季度"**预设中,路线图显示史诗和里程碑,其开始或到期日期**在**过去的季度,当前季度和接下来的四个季度**之内**或**经过**过去的季度,当前季度和接下来的四个季度,其中**今天**由时间轴中的垂直红线显示. 时间轴标题上季度名称下方的子标题代表季度的月份. + +### Months[](#months "Permalink") + +[![roadmap date range in months](img/e255c03f63cd814a974b54b2a9eb6b02.png)](img/roadmap_timeline_months.png) + +在" **月份"**预设中,路线图显示史诗和里程碑,这些史诗和里程碑的开始或到期日期**在**过去一个月,当前月份以及接下来的五个月**之内**或**经历**过去或六个月,其中**今天**由时间轴中的垂直红线显示. 时间轴标题上月份名称下方的子标题表示一周中开始日期(星期日)的日期. 默认情况下选择此预设. + +### Weeks[](#weeks "Permalink") + +[![roadmap date range in weeks](img/26b5d3ef6b515c199d6c860ac62a4671.png)](img/roadmap_timeline_weeks.png) + +在" **周"**预设中,路线图显示史诗和里程碑,这些史诗和里程碑的开始日期或到期日期**在**过去一周,当前星期和接下来的四个星期**之内**或**经过**过去一周,当前星期和接下来的四个星期,其中**今天**由时间轴中的垂直红线显示. 时间轴标题上星期名称下方的子标题代表星期几. + +## Roadmap timeline bar[](#roadmap-timeline-bar "Permalink") + +时间线栏根据史诗或里程碑的开始日期和到期日期指示其大概位置. \ No newline at end of file diff --git a/_book/docs/048.md b/_book/docs/048.md new file mode 100644 index 0000000000000000000000000000000000000000..57fe3d28ad1e2ae70050f99a243562be01a85960 --- /dev/null +++ b/_book/docs/048.md @@ -0,0 +1,303 @@ +# Projects + +> 原文:[https://docs.gitlab.com/ee/user/project/](https://docs.gitlab.com/ee/user/project/) + +* [Project features](#project-features) + * [Project integrations](#project-integrations) +* [New project](#new-project) + * [Fork a project](#fork-a-project) + * [Star a project](#star-a-project) + * [Explore projects](#explore-projects) +* [Project settings](#project-settings) +* [Import or export a project](#import-or-export-a-project) +* [Remove a project](#remove-a-project) + * [Delayed removal](#delayed-removal-premium) +* [CI/CD for external repositories](#cicd-for-external-repositories-premium) +* [Project members](#project-members) +* [Project activity](#project-activity) + * [Leave a project](#leave-a-project) +* [Project’s landing page](#projects-landing-page) +* [Redirects when changing repository paths](#redirects-when-changing-repository-paths) +* [Use your project as a Go package](#use-your-project-as-a-go-package) + * [Disable Go module features for private projects](#disable-go-module-features-for-private-projects) + * [Authenticate Go requests](#authenticate-go-requests) + * [Authenticate Git fetches](#authenticate-git-fetches) +* [Access project page with project ID](#access-project-page-with-project-id) +* [Project aliases](#project-aliases-premium-only) +* [Project APIs](#project-apis) + +# Projects[](#projects "Permalink") + +在 GitLab 中,您可以创建用于托管代码库的项目,将其用作问题跟踪器,在代码上进行协作,并使用内置的 GitLab CI / CD 持续构建,测试和部署应用程序. + +您可以[选择](../../public_access/public_access.html)公开,内部或私有[使用](../../public_access/public_access.html)您的项目. GitLab 不限制您创建的私人项目的数量. + +## Project features[](#project-features "Permalink") + +在 GitLab 中创建项目时,您将可以使用大量[功能](https://about.gitlab.com/features/) : + +**Repositories:** + +* [问题跟踪器](issues/index.html) :与您的团队讨论问题内的实现 + * [发行板](issue_board.html) :组织工作流程并确定其优先级 + * [多个发行板](issue_board.html#multiple-issue-boards) :允许您的团队为同一项目创建自己的工作流(发行板) +* [存储库](repository/index.html) :将代码托管在完全集成的平台中 + * [分支](repository/branches/index.html) :使用 Git 分支策略在代码上进行协作 + * [受保护的分支机构](protected_branches.html) :防止协作者弄乱历史记录或在未经审查的情况下推送代码 + * [受保护的标签](protected_tags.html) :控制谁有权创建标签,并防止意外更新或删除 + * [储存库镜​​像](repository/repository_mirroring.html) + * [签署提交](gpg_signed_commits/index.html) :使用 GPG 签署您的提交 + * [部署令牌](deploy_tokens/index.html) :管理基于项目的部署令牌,这些令牌允许永久访问存储库和 Container Registry. +* [Web IDE](web_ide/index.html) + +**发出和合并请求:** + +* [问题跟踪器](issues/index.html) :与您的团队讨论问题内的实现 + * [发行板](issue_board.html) :组织工作流程并确定其优先级 + * [多个发行板](issue_board.html#multiple-issue-boards) :允许您的团队为同一项目创建自己的工作流(发行板) +* [合并请求](merge_requests/index.html) :应用您的分支策略并获得团队的审查 + * [合并请求批准](merge_requests/merge_request_approvals.html) :实施更改之前[请求批准](merge_requests/merge_request_approvals.html) + * [修复 UI 中的合并冲突](merge_requests/resolve_conflicts.html) :直接从 GitLab UI 中使用 Git diff 工具 + * [审查应用程序](../../ci/review_apps/index.html) :按分支实时预览合并请求中建议的更改结果 +* [标签](labels.html) :按标签整理问题并合并请求 +* [时间跟踪](time_tracking.html) :跟踪估计在完成问题或合并请求上花费的时间和时间 +* [里程碑](milestones/index.html) :朝着目标日期迈进 +* [描述模板](description_templates.html) :为项目定义特定于上下文的模板,并为您的项目合并请求描述字段 +* [斜杠命令(快速操作)](quick_actions.html) :针对问题或合并请求的常见操作的文本快捷方式 +* [自动完成字符](autocomplete_characters.html) :自动完成对用户,组,问题,合并请求和其他 GitLab 元素的引用. +* [Web IDE](web_ide/index.html) + +**亚搏体育 app CI / CD:** + +* [GitLab CI / CD](../../ci/README.html) :GitLab 内置的[持续集成,交付和部署](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/)工具 + * [容器注册表](../packages/container_registry/index.html) :开箱即用地构建和推送 Docker 映像 + * [自动部署](../../topics/autodevops/stages.html#auto-deploy) :配置 GitLab CI / CD 以自动设置应用程序的部署 + * [启用和禁用 GitLab CI / CD](../../ci/enable_or_disable_ci.html) + * [管道](../../ci/pipelines/index.html) :从 UI 配置和可视化 GitLab CI / CD 管道 + * [计划的管道](../../ci/pipelines/schedules.html) :计划管道以在选定的时间开始 + * [管道图](../../ci/pipelines/index.html#visualize-pipelines) :通过 UI 查看整个管道 + * [作业工件](../../ci/pipelines/job_artifacts.html) :定义,浏览和下载作业工件 + * [管道设置](../../ci/pipelines/settings.html) :设置 Git 策略(选择从作业中的 GitLab 提取存储库的默认方式),超时(定义可以运行作业的最长时间(以分钟为`.gitlab-ci.yml` )) `.gitlab-ci.yml`自定义路径,测试覆盖率分析,管道的可见性等 + * [Kubernetes 集群集成](clusters/index.html) :将您的 GitLab 项目与 Kubernetes 集群连接 + * [功能标志](../../operations/feature_flags.html) :功能标志允许您通过动态切换某些功能来以不同的方式发布项目 +* [GitLab Pages](pages/index.html) :使用[GitLab Pages](pages/index.html)构建,测试和部署您的静态网站 + +**其他特性:** + +* [Wiki](wiki/index.html) :在集成的 Wiki 中记录您的 GitLab 项目. +* [片段](../snippets.html) :存储,共享和协作代码片段. +* [价值流分析](cycle_analytics.html) :查看您的开发生命周期. +* [见解](insights/index.html) :配置对您的项目至关重要的见解. +* [安全仪表板](security_dashboard.html) :安全仪表板. +* [语法突出显示](highlighting.html) :一种自定义代码块的替代方法,它替代了 GitLab 的默认语言选择. +* [徽章](badges.html) :项目概述的徽章. +* [发行版](releases/index.html) :一种跟踪项目中可交付成果的方式,可作为源,构建输出,其他元数据和与代码的发行版本相关的其他工件的快照. +* [Conan 软件包](../packages/conan_repository/index.html) :您在 GitLab 中的私人 Conan 存储库. +* [Maven 软件包](../packages/maven_repository/index.html) :您在 GitLab 中的私有 Maven 存储库. +* [NPM 软件包](../packages/npm_registry/index.html) :您在 GitLab 中的私有 NPM 软件包注册表. +* [代码所有者](code_owners.html) :为某些文件指定代码所有者 +* [许可证合规性](../compliance/license_compliance/index.html) :批准和拒绝项目的许可证. +* [依赖项列表](../application_security/dependency_list/index.html) :查看项目依赖项. +* [要求](requirements/index.html) :要求使您可以创建标准来检查产品. +* [静态站点编辑器](static_site_editor/index.html) :无需事先了解代码库或 Git 命令,即可在静态网站上快速编辑内容. +* [代码智能](code_intelligence.html) :代码导航功能. + +### Project integrations[](#project-integrations "Permalink") + +[将您的项目](integrations/index.html)与 Jira,Mattermost,Kubernetes,Slack 等进行[集成](integrations/index.html) . + +## New project[](#new-project "Permalink") + +了解如何在 GitLab 中[创建一个新项目](../../gitlab-basics/create-project.html) . + +### Fork a project[](#fork-a-project "Permalink") + +您可以[派生一个项目](repository/forking_workflow.html) ,以便: + +* 通过分叉项目并创建从分支到上游项目的合并请求来进行代码协作 +* 分叉一个示例项目以在其顶部工作 + +### Star a project[](#star-a-project "Permalink") + +您可以为项目加注星标,以使其更容易找到您经常使用的项目. 项目拥有的明星数量可以表明其受欢迎程度. + +为项目加注星标: + +1. 转到要加注星标的项目的主页. +2. 在页面的右上角,点击**星标** . + +要查看已加星标的项目,请执行以下操作: + +1. 单击导航栏中的**项目** . +2. Click **已加星标的项目**. +3. GitLab 显示有关已加星标项目的信息,包括: + + * 项目描述,包括名称,描述和图标 + * 已为该项目加注星标的次数 + * Number of times this project has been forked + * 打开的合并请求数 + * 未解决问题的数量 + +### Explore projects[](#explore-projects "Permalink") + +您可以探索 GitLab 上可用的其他流行项目. 探索项目: + +1. 单击导航栏中的**项目** . +2. Click **探索项目**. + +GitLab 显示一个项目列表,按上次更新日期排序. 要查看具有最多[星星的](#star-a-project)项目,请单击" **最多星星"** . 要查看过去一个月中评论数量最多的项目,请点击**趋势** . + +## Project settings[](#project-settings "Permalink") + +将项目的可见性级别和访问级别设置为各个页面,并执行诸如归档,重命名或传输项目的操作. + +通读有关[项目设置](settings/index.html)的文档. + +## Import or export a project[](#import-or-export-a-project "Permalink") + +* [Import a project](import/index.html) from: + * [GitHub to GitLab](import/github.html) + * [Bitbucket to GitLab](import/bitbucket.html) + * [Gitea to GitLab](import/gitea.html) + * [FogBugz to GitLab](import/fogbugz.html) +* [Export a project from GitLab](settings/import_export.html#exporting-a-project-and-its-data) +* [Importing and exporting projects between GitLab instances](settings/import_export.html) + +## Remove a project[](#remove-a-project "Permalink") + +要删除项目,请首先导航到该项目的主页. + +1. 导航至**设置>常规** . +2. 展开**高级**部分. +3. 向下滚动到" **删除项目"**部分. +4. Click **移除专案** +5. 通过输入所需的文本来确认此操作. + +### Delayed removal[](#delayed-removal-premium "Permalink") + +默认情况下,单击以删除项目后会延迟 7 天. 管理员可以在这段时间内恢复项目. [管理员可以更改](../admin_area/settings/visibility_and_access_controls.html#default-deletion-adjourned-period-premium-only)此延迟. + +管理员可以查看所有待删除项目. 如果您是管理员,请转到顶部导航栏,单击" **项目">"您的项目"** ,然后选择"已**删除的项目"**选项卡. 管理员可以从此选项卡还原任何项目. + +## CI/CD for external repositories[](#cicd-for-external-repositories-premium "Permalink") + +您可以将存储库作为 CI / CD 项目连接,而不是将存储库直接导入到 GitLab. + +通读[CI / CD 上有关外部存储库](../../ci/ci_cd_for_external_repos/index.html)的文档. + +## Project members[](#project-members "Permalink") + +了解如何[将成员添加到您的项目中](members/index.html) . + +## Project activity[](#project-activity "Permalink") + +要查看项目的活动,请导航至**项目概述>活动** . 在此处,您可以单击选项卡以查看**所有**活动,或查看按**Push 事件** , **Merge 事件** , **Issue 事件** , **Comment** , **Team**和**Wiki**过滤的**活动** . + +### Leave a project[](#leave-a-project "Permalink") + +当项目属于组时(在[组命名空间下](../group/index.html#namespaces) ), **离开项目**将仅显示在项目的仪表板上. 如果您选择退出项目,那么您将不再是项目成员,因此无法参与. + +## Project’s landing page[](#projects-landing-page "Permalink") + +项目的登录页面根据项目的可见性设置和用户权限显示不同的信息. + +对于公共项目以及[有权查看该项目代码](../permissions.html#project-members-permissions)的内部和私有项目的成员: + +* 显示[`README`文件或索引文件的](repository/#repository-readme-and-index-files)内容(如果有),然后显示项目存储库中的目录列表. +* 如果项目不包含这些文件中的任何一个,则访问者将看到存储库的文件和目录列表. + +对于没有权限查看项目代码的用户: + +* 显示维基主页(如果有). +* 显示项目中的问题列表. + +## Redirects when changing repository paths[](#redirects-when-changing-repository-paths "Permalink") + +当存储库路径更改时,从旧位置平稳过渡到新位置至关重要. GitLab 提供两种重定向:Web UI 和 Git 推/拉重定向. + +根据情况,可能会有所不同. + +When [renaming a user](../profile/index.html#changing-your-username), [changing a group path](../group/index.html#changing-a-groups-path) or [renaming a repository](settings/index.html#renaming-a-repository): + +* 名称空间及其下的任何内容(例如项目)的现有 Web URL 将重定向到新 URL. +* 从 GitLab 10.3 开始,命名空间下项目的现有 Git 远程 URL 将重定向到新的远程 URL. 每次将其推/拉到更改位置的存储库时,都会显示一条警告消息,提示您更新遥控器,而不是拒绝操作. 这意味着在重命名后,任何自动化脚本或 Git 客户端将继续工作,从而使任何过渡都更加顺畅. +* The redirects will be available as long as the original path is not claimed by another group, user or project. + +## Use your project as a Go package[](#use-your-project-as-a-go-package "Permalink") + +任何项目都可以用作 Go 包. GitLab 会正确响应`go get`和`godoc.org`发现请求,包括[`go-import`](https://s0golang0org.icopy.site/cmd/go/)和[`go-source`](https://github.com/golang/gddo/wiki/Source-Code-Links)元标记. + +私有项目(包括子组中的项目)可以用作 Go 包,但可能需要进行配置才能正常工作. 无论身份验证或授权如何,GitLab 都会正确响应以`go get` *不在*子组中的项目的发现请求. 要使用子组中的私有项目作为 Go 包,必须进行[身份验证](#authenticate-go-requests) . 否则,GitLab 会将子组中私有项目的路径截断到前两个段,从而导致`go get`失败. + +GitLab 实现了自己的 Go 代理. 此功能必须由管理员启用,并且需要其他配置. 请参阅[GitLab Go 代理](../packages/go_proxy/index.html) . + +### Disable Go module features for private projects[](#disable-go-module-features-for-private-projects "Permalink") + +In Go 1.12 and later, Go queries module proxies and checksum databases in the process of [fetching a module](../../development/go_guide/dependencies.html#fetching). This can be selectively disabled with `GOPRIVATE` (disable both), [`GONOPROXY`](../../development/go_guide/dependencies.html#proxies) (disable proxy queries), and [`GONOSUMDB`](../../development/go_guide/dependencies.html#fetching) (disable checksum queries). + +`GOPRIVATE` , `GONOPROXY`和`GONOSUMDB`是 Go 模块和 Go 模块前缀的逗号分隔列表. 例如, `GOPRIVATE=gitlab.example.com/my/private/project`将禁用对该项目的查询,而`GOPRIVATE=gitlab.example.com`将禁用`GOPRIVATE=gitlab.example.com` *所有*项目的查询. 如果模块名称或其前缀出现在`GOPRIVATE`或`GONOPROXY` ,则 Go 不会查询模块代理. 如果模块名称或其前缀出现在`GONOPRIVATE`或`GONOSUMDB` ,则 Go 不会查询校验和数据库. + +### Authenticate Go requests[](#authenticate-go-requests "Permalink") + +要验证对 Go 私有项目的请求,请在密码字段中使用[`.netrc`文件](https://ec.haxx.se/usingcurl-netrc.html)和[个人访问令牌](../profile/personal_access_tokens.html) . **仅当可以通过 HTTPS 访问您的 GitLab 实例时,此方法才有效.** `go`命令不会通过不安全的连接传输凭据. 这将验证 Go 直接发出的所有 HTTPS 请求,但不会验证通过 Git 发出的请求. + +例如: + +``` +machine example.gitlab.com +login +password +``` + +**注意:**在 Windows 上,Go 读取`~/_netrc`而不是`~/.netrc` . + +### Authenticate Git fetches[](#authenticate-git-fetches "Permalink") + +如果无法从代理中获取模块,Go 将退回到使用 Git(对于 GitLab 项目). Git 将使用`.netrc`来认证请求. 另外,可以将 Git 配置为在请求 URL 中嵌入特定的凭据,或者使用 SSH 代替 HTTPS(因为 Go 始终使用 HTTPS 来获取 Git 存储库): + +``` +# embed credentials in any request to GitLab.com: +git config --global url."https://${user}:${personal_access_token}@gitlab.example.com".insteadOf "https://gitlab.example.com" + +# use SSH instead of HTTPS: +git config --global url."git@gitlab.example.com".insteadOf "https://gitlab.example.com" +``` + +## Access project page with project ID[](#access-project-page-with-project-id "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53671) . + +要使用项目 ID 从 GitLab UI 快速访问项目,请在浏览器或其他访问项目的工具中访问`/projects/:id` URL. + +## Project aliases[](#project-aliases-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3264) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.1. + +将存储库迁移到 GitLab 并被其他系统访问时,能够使用相同的名称访问它们非常有用,尤其是当它们很多时. 它降低了在大量系统中更改大量 Git URL 的风险. + +manbetx 客户端打不开提供了功能来帮助这一点. 在 GitLab 中,通常使用名称空间和项目名称访问存储库. 也可以通过项目别名访问它们. 此功能仅在通过 SSH 的 Git 上可用. + +项目别名只能通过 API 创建,并且只能由 GitLab 管理员创建. 有关更多详细信息,请遵循[Project Aliases API 文档](../../api/project_aliases.html) . + +一旦为项目创建了别名(例如,项目`https://gitlab.com/gitlab-org/gitlab`的别名`gitlab` ),就可以使用别名(例如`git clone git@gitlab.com:gitlab.git` )来克隆存储库. `git clone git@gitlab.com:gitlab.git`而不是`git clone git@gitlab.com:gitlab-org/gitlab.git` ). + +## Project APIs[](#project-apis "Permalink") + +您的项目可以使用许多[API](../../api/README.html) : + +* [Badges](../../api/project_badges.html) +* [Clusters](../../api/project_clusters.html) +* [Threads](../../api/discussions.html) +* [General](../../api/projects.html) +* [Import/export](../../api/project_import_export.html) +* [Issue Board](../../api/boards.html) +* [Labels](../../api/labels.html) +* [Markdown](../../api/markdown.html) +* [Merge Requests](../../api/merge_requests.html) +* [Milestones](../../api/milestones.html) +* [Services](../../api/services.html) +* [Snippets](../../api/project_snippets.html) +* [Templates](../../api/project_templates.html) +* [Traffic](../../api/project_statistics.html) +* [Variables](../../api/project_level_variables.html) +* [Aliases](../../api/project_aliases.html) \ No newline at end of file diff --git a/_book/docs/049.md b/_book/docs/049.md new file mode 100644 index 0000000000000000000000000000000000000000..cfa11449866c3285a60461d5c1efcfb3d511dca6 --- /dev/null +++ b/_book/docs/049.md @@ -0,0 +1,459 @@ +# GitLab Secure + +> 原文:[https://docs.gitlab.com/ee/user/application_security/](https://docs.gitlab.com/ee/user/application_security/) + +* [Quick start](#quick-start) + * [Override the default registry base address](#override-the-default-registry-base-address) +* [Security scanning tools](#security-scanning-tools) +* [Security Scanning with Auto DevOps](#security-scanning-with-auto-devops) +* [Maintenance and update of the vulnerabilities database](#maintenance-and-update-of-the-vulnerabilities-database) +* [Interacting with the vulnerabilities](#interacting-with-the-vulnerabilities) + * [View details of a DAST vulnerability](#view-details-of-a-dast-vulnerability) + * [Hide sensitive information in headers](#hide-sensitive-information-in-headers) + * [Dismissing a vulnerability](#dismissing-a-vulnerability) + * [Adding a dismissal reason](#adding-a-dismissal-reason) + * [Dismissing multiple vulnerabilities](#dismissing-multiple-vulnerabilities) + * [Creating an issue for a vulnerability](#creating-an-issue-for-a-vulnerability) + * [Solutions for vulnerabilities (auto-remediation)](#solutions-for-vulnerabilities-auto-remediation) + * [Manually applying the suggested patch](#manually-applying-the-suggested-patch) + * [Creating a merge request from a vulnerability](#creating-a-merge-request-from-a-vulnerability) +* [Security approvals in merge requests](#security-approvals-in-merge-requests) + * [Enabling Security Approvals within a project](#enabling-security-approvals-within-a-project) +* [Enabling License Approvals within a project](#enabling-license-approvals-within-a-project) +* [Working in an offline environment](#working-in-an-offline-environment) +* [Using private Maven repos](#using-private-maven-repos) +* [Outdated security reports](#outdated-security-reports) + * [Source branch is behind the target branch](#source-branch-is-behind-the-target-branch) + * [Target branch security report is out of date](#target-branch-security-report-is-out-of-date) +* [Troubleshooting](#troubleshooting) + * [Getting error message `sast job: stage parameter should be [some stage name here]`](#getting-error-message-sast-job-stage-parameter-should-be-some-stage-name-here) + * [Getting error message `sast job: config key may not be used with 'rules': only/except`](#getting-error-message-sast-job-config-key-may-not-be-used-with-rules-onlyexcept) + * [Transitioning your `only/except` syntax to `rules`](#transitioning-your-onlyexcept-syntax-to-rules) + * [Pin your templates to the deprecated versions](#pin-your-templates-to-the-deprecated-versions) + +# GitLab Secure[](#gitlab-secure-ultimate "Permalink") + +GitLab 可以检查您的应用程序是否存在安全漏洞,这些漏洞可能导致未经授权的访问,数据泄漏,服务拒绝等. GitLab 在合并请求中报告漏洞,因此您可以在合并之前修复它们. [安全仪表板](security_dashboard/index.html)提供了在项目,管道和组中检测到的漏洞的高级视图. " [威胁监视"](threat_monitoring/index.html)页面提供了应用程序环境的运行时安全性度量. 使用提供的信息,您可以立即开始风险分析和补救. + +有关 GitLab 的应用程序安全性的概述,请参阅[Security Deep Dive](https://www.youtube.com/watch?v=k4vEJnGYy84) . + +## Quick start[](#quick-start "Permalink") + +通过将以下内容添加到`.gitlab-ci.yml` ,可以快速开始进行依赖项扫描,许可证扫描,静态应用程序安全测试(SAST)和秘密检测. + +``` +include: + - template: Dependency-Scanning.gitlab-ci.yml + - template: License-Scanning.gitlab-ci.yml + - template: SAST.gitlab-ci.yml + - template: Secret-Detection.gitlab-ci.yml +``` + +要添加动态应用程序安全测试(DAST)扫描,请将以下内容添加到`.gitlab-ci.yml` ,并将`https://staging.example.com`替换为登台服务器的网址: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_WEBSITE: https://staging.example.com +``` + +为确保 DAST 扫描程序*在*将应用程序部署到登台服务器*之后*运行,请查阅[DAST 完整文档](dast/index.html) . + +要添加容器扫描,请遵循[容器扫描文档中](container_scanning/index.html#requirements)列出的步骤. + +要进一步配置任何其他扫描仪,请参阅每个扫描仪的文档. + +### Override the default registry base address[](#override-the-default-registry-base-address "Permalink") + +默认情况下,GitLab 安全扫描程序使用`registry.gitlab.com/gitlab-org/security-products/analyzers`作为 Docker 映像的基址. 您可以通过将变量`SECURE_ANALYZERS_PREFIX`设置到另一个位置来全局覆盖此位置. 请注意,这会同时影响所有扫描仪. + +## Security scanning tools[](#security-scanning-tools "Permalink") + +GitLab 使用以下工具来扫描和报告项目中发现的已知漏洞. + +| 安全扫描工具 | Description | +| --- | --- | +| [Container Scanning](container_scanning/index.html) | 扫描 Docker 容器中的已知漏洞. | +| [Dependency List](dependency_list/index.html) | 查看项目的依存关系及其已知漏洞. | +| [Dependency Scanning](dependency_scanning/index.html) | 分析您的依赖项是否存在已知漏洞. | +| [Dynamic Application Security Testing (DAST)](dast/index.html) | 分析运行中的 Web 应用程序是否存在已知漏洞. | +| [Secret Detection](secret_detection/index.html) | 分析 Git 历史记录以了解泄露的机密. | +| [Security Dashboard](security_dashboard/index.html) | 查看所有项目和组中的漏洞. | +| [Static Application Security Testing (SAST)](sast/index.html) | Analyze source code for known vulnerabilities. | + +## Security Scanning with Auto DevOps[](#security-scanning-with-auto-devops "Permalink") + +启用[自动 DevOps 时](../../topics/autodevops/) ,将使用默认设置配置所有 GitLab 安全扫描工具. + +* [Auto SAST](../../topics/autodevops/stages.html#auto-sast-ultimate) +* [Auto Secret Detection](../../topics/autodevops/stages.html#auto-secret-detection-ultimate) +* [Auto DAST](../../topics/autodevops/stages.html#auto-dast-ultimate) +* [Auto Dependency Scanning](../../topics/autodevops/stages.html#auto-dependency-scanning-ultimate) +* [Auto License Compliance](../../topics/autodevops/stages.html#auto-license-compliance-ultimate) +* [Auto Container Scanning](../../topics/autodevops/stages.html#auto-container-scanning-ultimate) + +虽然您无法直接自定义 Auto DevOps,但可以[在项目的`.gitlab-ci.yml`文件中包括 Auto DevOps 模板](../../topics/autodevops/customize.html#customizing-gitlab-ciyml) . + +## Maintenance and update of the vulnerabilities database[](#maintenance-and-update-of-the-vulnerabilities-database "Permalink") + +扫描工具和漏洞数据库会定期更新. + +| 安全扫描工具 | 漏洞数据库更新 | +| --- | --- | +| [Container Scanning](container_scanning/index.html) | 使用`clair` . 通过运行[`latest` Docker image 标签](https://gitlab.com/gitlab-org/gitlab/blob/438a0a56dc0882f22bdd82e700554525f552d91b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L37) ,每个作业都使用最新的`clair-db`版本. [根据作者的说法,](https://github.com/arminc/clair-local-scan#clair-server-or-local) `clair-db`数据库[每天进行更新](https://github.com/arminc/clair-local-scan#clair-server-or-local) . | +| [Dependency Scanning](dependency_scanning/index.html) | 依赖于`bundler-audit` (对于 Ruby gems), `retire.js` (对于 NPM 软件包)和`gemnasium` (GitLab 自己的所有库工具). `bundler-audit`和`retire.js`从 GitHub 存储库中获取漏洞数据,因此添加到`ruby-advisory-db`和`retire.js`立即可用. 如果有新版本,工具本身每月更新一次. [Gemnasium 数据库](https://gitlab.com/gitlab-org/security-products/gemnasium-db)至少每周更新一次. 请参阅我们[当前从发布 CVE 到更新我们产品的时间度量](https://about.gitlab.com/handbook/engineering/development/performance-indicators/#cve-issue-to-update) . | +| [Dynamic Application Security Testing (DAST)](dast/index.html) | 扫描引擎会定期更新. 请参阅[基础工具`zaproxy`](https://gitlab.com/gitlab-org/security-products/dast/blob/master/Dockerfile#L1)的[版本](https://gitlab.com/gitlab-org/security-products/dast/blob/master/Dockerfile#L1) . 扫描规则在扫描运行时下载. | +| [Static Application Security Testing (SAST)](sast/index.html) | Relies exclusively on [the tools GitLab wraps](sast/index.html#supported-languages-and-frameworks). The underlying analyzers are updated at least once per month if a relevant update is available. The vulnerabilities database is updated by the upstream tools. | + +当前,您不必更新 GitLab 即可从最新的漏洞定义中受益. 安全工具作为 Docker 映像发布. 供应商的职位定义使他们能够使用根据[语义版本控制的](https://semver.org/)主要发行标签. 工具的每个新版本都会覆盖这些标签. Docker 映像已更新为与以前的 GitLab 版本匹配,因此用户无需执行任何操作即可自动获取最新版本的扫描工具. 但是,这种方法存在一些已知问题,并且有[解决这些问题](https://gitlab.com/gitlab-org/gitlab/-/issues/9725)的[计划](https://gitlab.com/gitlab-org/gitlab/-/issues/9725) . + +## Interacting with the vulnerabilities[](#interacting-with-the-vulnerabilities "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.8 中引入. + +合并请求报告或" [安全仪表板"](security_dashboard/index.html)中的每个安全漏洞都是可操作的. 单击一个条目以查看具有多个选项的详细信息: + +* 消除[漏洞](#dismissing-a-vulnerability) :消除漏洞可在删除线中设置样式. +* [创建问题](#creating-an-issue-for-a-vulnerability) :创建一个新问题,其标题和说明已预先填充了漏洞报告中的信息. 默认情况下,此类问题是[机密的](../project/issues/confidential_issues.html) . +* [解决方案](#solutions-for-vulnerabilities-auto-remediation) :对于某些漏洞,提供了有关如何修复该漏洞的解决方案. + +[![Interacting with security reports](img/079efbfe641967c936be8ed9b033bca6.png)](img/interacting_with_vulnerability_v13_0.png) + +### View details of a DAST vulnerability[](#view-details-of-a-dast-vulnerability "Permalink") + +DAST 检测到的漏洞在实时 Web 应用程序中发生. 纠正这些类型的漏洞需要特定的信息. DAST 提供了调查和纠正根本原因所需的信息. + +要查看 DAST 漏洞的详细信息,请执行以下操作: + +1. 要查看检测到的所有漏洞: + + * 在一个项目中,转到该项目的 **安全和合规性**页面. + * 仅在合并请求中,转到合并请求的" **安全性"**选项卡. +2. 单击漏洞的描述. 提供以下详细信息: + + | Field | Description | + | --- | --- | + | Description | Description of the vulnerability. | + | Project | 检测到漏洞的名称空间和项目. | + | Method | 用于检测漏洞的 HTTP 方法. | + | URL | 检测到漏洞的 URL. | + | 请求标题 | 请求的标题. | + | 回应状态 | 从应用程序收到的响应状态. | + | 响应标题 | 从应用程序收到的响应的标头. | + | Evidence | 数据证据证明该漏洞. 通常是请求或响应的摘要,可以用来帮助验证发现是否为漏洞. | + | Identifiers | 漏洞的标识符. | + | Severity | 漏洞的严重性. | + | 扫描仪类型 | 漏洞报告的类型. | + | Links | 链接到检测到的漏洞的更多详细信息. | + | Solution | 推荐的漏洞解决方案的详细信息(可选). | + +#### Hide sensitive information in headers[](#hide-sensitive-information-in-headers "Permalink") + +HTTP 请求和响应标头可能包含敏感信息,包括 cookie 和授权凭证. 默认情况下,特定标头的内容在 DAST 漏洞报告中被屏蔽. 您可以指定要屏蔽的所有标题的列表. 有关详细信息,请参阅[隐藏敏感信息](dast/index.html#hide-sensitive-information) . + +### Dismissing a vulnerability[](#dismissing-a-vulnerability "Permalink") + +要消除漏洞,必须将其状态设置为"消除". 请按照以下步骤操作: + +1. 在"安全仪表板"中选择漏洞. +2. 从右上方的**状态**选择器菜单中选择"已**关闭"** . + +您可以通过从同一菜单中选择其他状态来撤消此操作. + +#### Adding a dismissal reason[](#adding-a-dismissal-reason "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0 中引入. + +消除漏洞时,提供这样做的理由通常很有帮助. 将漏洞的状态设置为"已撤消"后,将出现一个文本框,供您添加有关撤消的评论. 添加后,您可以对其进行编辑或删除. 随着时间的推移,这使您可以添加和更新漏洞的上下文. + +[![Dismissed vulnerability comment](img/cb3829e4d0ca25082e0f52f135a9d1de.png)](img/adding_a_dismissal_reason_v13_0.png) + +#### Dismissing multiple vulnerabilities[](#dismissing-multiple-vulnerabilities "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9 中引入. + +您可以提供多个可选原因,一次消除多个漏洞. 选中列表中每个漏洞旁边的复选框,将选择该单个漏洞. 或者,您可以通过选择表标题中的复选框来选择列表中的所有漏洞. 取消选中标题中的复选框将取消选择列表中的所有漏洞. 选择了某些漏洞后,表格顶部会显示一个菜单,您可以通过该菜单选择解雇原因. 按下"关闭选定的漏洞"按钮将立即消除所有选定的漏洞,并说明您选择的原因. + +[![Multiple vulnerability dismissal](img/fef11068ab5cc264b208a4bd3addb7fa.png)](img/multi_select_v12_9.png) + +### Creating an issue for a vulnerability[](#creating-an-issue-for-a-vulnerability "Permalink") + +您可以通过从漏洞模式中选择" **创建问题"**按钮,或使用组安全性仪表板中漏洞行右侧的"操作"按钮来创建漏洞问题. + +这在漏洞来自的项目中创建了一个[机密问题](../project/issues/confidential_issues.html) ,并使用从漏洞报告中获取的一些有用信息对其进行了预填充. 创建问题后,您将重定向到该问题,以便您可以对其进行编辑,分配或评论. + +返回组安全性仪表板后,该漏洞现在在名称旁边具有一个关联的问题. + +[![Linked issue in the group security dashboard](img/557f2cc00416c6f64286e93532f50121.png)](img/issue.png) + +### Solutions for vulnerabilities (auto-remediation)[](#solutions-for-vulnerabilities-auto-remediation "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5656) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.7. + +可以通过应用 GitLab 自动生成的解决方案来修复某些漏洞. 支持以下扫描仪: + +* [依赖项扫描](dependency_scanning/index.html) :自动补丁创建仅适用于使用`yarn`管理的 Node.js 项目. +* [Container Scanning](container_scanning/index.html) + +#### Manually applying the suggested patch[](#manually-applying-the-suggested-patch "Permalink") + +可以通过应用由 GitLab 自动生成的补丁来修复某些漏洞. 要应用此修复程序: + +1. 单击漏洞. +2. 下载并查看补丁文件`remediation.patch` . +3. 确保本地项目的签出提交与生成补丁的提交相同. +4. Run `git apply remediation.patch`. +5. 验证并将更改提交到您的分支. + +[![Apply patch for dependency scanning](img/2e2c36f66667fc52b3fb3681533dcef7.png)](img/vulnerability_solution.png) + +#### Creating a merge request from a vulnerability[](#creating-a-merge-request-from-a-vulnerability "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9224) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9. + +在某些情况下,GitLab 允许您创建一个合并请求以自动修复漏洞. 具有[解决方案的](#solutions-for-vulnerabilities-auto-remediation)任何漏洞都可以创建合并请求以自动解决问题. + +如果可以使用此操作,则漏洞模式将包含" **创建合并请求"**按钮. 单击此按钮创建合并请求,以将解决方案应用于源分支. + +[![Create merge request from vulnerability](img/6dffd31bb67148d85ebfccbfc20abfd8.png)](img/create_issue_with_list_hover.png) + +## Security approvals in merge requests[](#security-approvals-in-merge-requests "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9928) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.2. + +可以将合并请求批准配置为在合并请求引入以下安全问题之一时,需要安全团队成员的批准: + +* 一个安全漏洞 +* 违反软件许可证规定 + +安全漏洞阈值定义为`high` , `critical`或`unknown`严重性. `Vulnerability-Check`批准者组必须批准包含漏洞的合并请求. + +当 GitLab 可以评估漏洞的严重性时,等级可以是以下之一: + +* `unknown` +* `low` +* `medium` +* `high` +* `critical` + +`unknown`等级表明基础扫描仪不包含或没有提供严重等级. + +### Enabling Security Approvals within a project[](#enabling-security-approvals-within-a-project "Permalink") + +要启用安全批准,必须使用区分大小写的名称`Vulnerability-Check`创建[项目批准规则](../project/merge_requests/merge_request_approvals.html#adding--editing-a-default-approval-rule) . 该批准组必须设置为所需的批准数量大于零. 您必须具有维护者或所有者[权限](../permissions.html#project-members-permissions)才能管理批准规则. + +1. 导航到您项目的 **设置>常规,**然后展开**合并请求批准** . +2. 单击**添加批准规则** ,或单击**编辑** . + * 将**规则名称**添加或更改为`Vulnerability-Check` (区分大小写). + +[![Vulnerability Check Approver Rule](img/2c7964b63403cf1f03ea9bdbfeee96cf.png)](img/vulnerability-check_v13_0.png) + +将这个组添加到您的项目后,将为所有合并请求启用批准规则. + +任何代码更改都会导致重置所需的批准. + +当安全报告: + +* 包含`high` , `critical`或`unknown`严重性的新漏洞,无论被解雇如何. +* 在管道执行期间未生成. + +在安全报告中,批准是可选的: + +* 不包含任何新漏洞. +* 仅包含严重程度`low`或`medium`新漏洞. + +## Enabling License Approvals within a project[](#enabling-license-approvals-within-a-project "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13067) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.3. + +`License-Check`是一个批准规则,您可以启用它来允许个人或组批准包含`denied`许可证的合并请求. + +您可以启用`License-Check`的两种方式之一: + +* 使用区分大小写的名称`License-Check`创建[项目批准规则](../project/merge_requests/merge_request_approvals.html#multiple-approval-rules-premium) . +* 在[项目策略部分中为许可合规](../compliance/license_compliance/index.html#policies)创建批准组. 您必须将此批准组的所需批准数量设置为大于零. 在项目中启用该组后,将为所有合并请求启用批准规则. + +任何代码更改都会导致重置所需的批准. + +许可证报告如下时,需要批准: + +* 包含包含被`denied`的软件许可证的依赖项. +* 在管道执行期间未生成. + +许可证报告如下时,批准是可选的: + +* 不包含任何违反软件许可证的行为. +* 仅包含`allowed`或未知的新许可证. + +## Working in an offline environment[](#working-in-an-offline-environment "Permalink") + +当未连接到 Internet 时,有时会在脱机,受限连接,局域网(LAN),Intranet 或"气隙"环境中运行大多数 GitLab 安全扫描程序. + +阅读如何[在离线环境中操作安全扫描仪](offline_deployments/index.html) . + +## Using private Maven repos[](#using-private-maven-repos "Permalink") + +如果您有需要登录凭据的私有 Apache Maven 存储库,则可以使用`MAVEN_CLI_OPTS`环境变量来传递用户名和密码. 您可以在项目的设置下进行设置,以免凭据在`.gitlab-ci.yml` . + +如果用户名是`myuser`并且密码非常`verysecret`则可以在项目的设置下[设置以下变量](../../ci/variables/README.html#create-a-custom-variable-in-the-ui) : + +| Type | Key | Value | +| --- | --- | --- | +| Variable | `MAVEN_CLI_OPTS` | `--settings mysettings.xml -Drepository.password=verysecret -Drepository.user=myuser` | + +``` + + + ... + + + private_server + ${private.username} + ${private.password} + + + +``` + +## Outdated security reports[](#outdated-security-reports "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4913) . + +当为合并请求生成的安全报告过时时,合并请求会在安全小部件中显示警告消息,并提示您采取适当的措施. + +这可能在两种情况下发生: + +1. Your [source branch is behind the target branch](#source-branch-is-behind-the-target-branch). +2. The [target branch security report is out of date](#target-branch-security-report-is-out-of-date). + +### Source branch is behind the target branch[](#source-branch-is-behind-the-target-branch "Permalink") + +这意味着目标分支和源分支之间的最新公共祖先提交不是目标分支上的最新提交. 到目前为止,这是最常见的情况. + +在这种情况下,您必须重新设置基础或合并以合并来自目标分支的更改. + +[![Incorporate target branch changes](img/6564cc179b8bafb5577b9762c905010c.png)](img/outdated_report_branch_v12_9.png) + +### Target branch security report is out of date[](#target-branch-security-report-is-out-of-date "Permalink") + +发生这种情况的原因有很多,包括工作失败或新的咨询. 当合并请求显示安全报告已过期时,必须在目标分支上运行新管道. 您可以按照提供的超链接运行新管道来快速完成此操作. + +[![Run a new pipeline](img/66a70133eaa2327dce4cd61c485afcdb.png)](img/outdated_report_pipeline_v12_9.png) + +## Troubleshooting[](#troubleshooting "Permalink") + +### Getting error message `sast job: stage parameter should be [some stage name here]`[](#getting-error-message-sast-job-stage-parameter-should-be-some-stage-name-here "Permalink") + +当[包括](../../ci/yaml/README.html#includetemplate)诸如[`SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml)的`.gitlab-ci.yml`模板时,根据您的 GitLab CI / CD 配置,可能会发生以下错误: + +``` +Found errors in your .gitlab-ci.yml: + +* sast job: stage parameter should be unit-tests +``` + +如果未在`.gitlab-ci.yml`声明包含作业的阶段(名为`test` ),则会出现此错误. 要解决此问题,您可以: + +* 在`.gitlab-ci.yml`添加一个`test`阶段. +* 更改包含的安全作业的默认阶段. 例如,使用 SpotBugs(SAST): + + ``` + include: + template: SAST.gitlab-ci.yml + + spotbugs-sast: + stage: unit-tests + ``` + +[了解有关覆盖 SAST 作业的更多信息](sast/index.html#overriding-sast-jobs) . 所有安全扫描工具都定义了它们的阶段,因此,所有这些工具都可能发生此错误. + +### Getting error message `sast job: config key may not be used with 'rules': only/except`[](#getting-error-message-sast-job-config-key-may-not-be-used-with-rules-onlyexcept "Permalink") + +当[包括](../../ci/yaml/README.html#includetemplate)诸如[`SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml)的`.gitlab-ci.yml`模板时,根据您的 GitLab CI / CD 配置,可能会发生以下错误: + +``` +Found errors in your .gitlab-ci.yml: + + jobs:sast config key may not be used with `rules`: only/except +``` + +当[`only`使用已弃用的或`except`语法`except`](../../ci/yaml/README.html#onlyexcept-basic) [覆盖](sast/index.html#overriding-sast-jobs)了包含作业的`rules`配置时,将出现此错误[.](../../ci/yaml/README.html#onlyexcept-basic) 若要解决此问题,您必须: + +* [Transition your `only/except` syntax to `rules`](#transitioning-your-onlyexcept-syntax-to-rules). +* (Temporarily) [Pin your templates to the deprecated versions](#pin-your-templates-to-the-deprecated-versions) + +[Learn more on overriding SAST jobs](sast/index.html#overriding-sast-jobs). + +#### Transitioning your `only/except` syntax to `rules`[](#transitioning-your-onlyexcept-syntax-to-rules "Permalink") + +覆盖模板以控制作业执行时, [`only`或`except`](../../ci/yaml/README.html#onlyexcept-basic)先前实例不再兼容,必须转换为[`rules`语法](../../ci/yaml/README.html#rules) . + +如果您的替代旨在将作业限制为仅在`master`运行,则先前的语法类似于: + +``` +include: + - template: SAST.gitlab-ci.yml + +# Ensure that the scanning is only executed on master or merge requests +spotbugs-sast: + only: + refs: + - master + - merge_requests +``` + +要将上面的配置转换为新的`rules`语法,重写将如下编写: + +``` +include: + - template: SAST.gitlab-ci.yml + +# Ensure that the scanning is only executed on master or merge requests +spotbugs-sast: + rules: + - if: $CI_COMMIT_BRANCH == "master" + - if: $CI_MERGE_REQUEST_ID +``` + +如果您的覆盖旨在限制作业仅在分支而不是标签上运行,则其外观类似于: + +``` +include: + - template: SAST.gitlab-ci.yml + +# Ensure that the scanning is not executed on tags +spotbugs-sast: + except: + - tags +``` + +为了过渡到新的`rules`语法,重写将被重写为: + +``` +include: + - template: SAST.gitlab-ci.yml + +# Ensure that the scanning is not executed on tags +spotbugs-sast: + rules: + - if: $CI_COMMIT_TAG == null +``` + +[Learn more on the usage of `rules`](../../ci/yaml/README.html#rules). + +#### Pin your templates to the deprecated versions[](#pin-your-templates-to-the-deprecated-versions "Permalink") + +为了确保获得最新支持,我们**强烈**建议您迁移到[`rules`](../../ci/yaml/README.html#rules) . + +如果您无法立即更新 CI 配置,则有几种解决方法,其中涉及固定到以前的模板版本,例如: + +``` + include: + remote: 'https://gitlab.com/gitlab-org/gitlab/-/raw/12-10-stable-ee/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml' +``` + +此外,我们提供了一个专用项目,其中包含版本控制的旧版模板. 这对于脱机设置或希望使用[Auto DevOps 的](../../topics/autodevops/index.html)任何人很有用. + +[旧版模板项目](https://gitlab.com/gitlab-org/auto-devops-v12-10)中提供了说明. \ No newline at end of file diff --git a/_book/docs/050.md b/_book/docs/050.md new file mode 100644 index 0000000000000000000000000000000000000000..0afab18f910a62a81685fdc8e6f150ca065e560f --- /dev/null +++ b/_book/docs/050.md @@ -0,0 +1,26 @@ +# Security Configuration + +> 原文:[https://docs.gitlab.com/ee/user/application_security/configuration/](https://docs.gitlab.com/ee/user/application_security/configuration/) + +* [Overview](#overview) +* [Limitations](#limitations) + +# Security Configuration[](#security-configuration-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20711) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6. + +## Overview[](#overview "Permalink") + +安全配置页面显示每个安全功能的配置状态,可以通过项目的侧边栏导航来访问. + +[![Screenshot of security configuration page](img/c5fbd1d44b70c599ae2cc8751ccfca14.png)](../img/security_configuration_page_v13_2.png) + +该页面使用项目的最新默认分支[CI 管道](../../../ci/pipelines/index.html)来确定每个功能部件的配置状态. 如果管道中存在具有预期安全报告工件的作业,则认为该功能已配置. + +**注意:**如果最新的管道使用了[Auto DevOps](../../../topics/autodevops/index.html) ,则默认情况下将配置所有安全功能. + +## Limitations[](#limitations "Permalink") + +尚无法使用配置页启用或禁用大多数功能. 但是,可以通过该页面上每个功能旁边的链接找到有关如何启用或禁用功能的说明. + +如果项目没有现有的 CI 配置,则可以通过单击"管理"列下的"启用合并请求"按钮来启用 SAST 功能. 将来的工作会将其扩展到编辑*现有* CI 配置以及其他安全功能. \ No newline at end of file diff --git a/_book/docs/051.md b/_book/docs/051.md new file mode 100644 index 0000000000000000000000000000000000000000..13125b0ab37d72d3c70c14c3c4f4b3f669f5e7b5 --- /dev/null +++ b/_book/docs/051.md @@ -0,0 +1,321 @@ +# Container Scanning + +> 原文:[https://docs.gitlab.com/ee/user/application_security/container_scanning/](https://docs.gitlab.com/ee/user/application_security/container_scanning/) + +* [Overview](#overview) +* [Requirements](#requirements) +* [Configuration](#configuration) + * [Customizing the Container Scanning settings](#customizing-the-container-scanning-settings) + * [Available variables](#available-variables) + * [Overriding the Container Scanning template](#overriding-the-container-scanning-template) + * [Vulnerability allowlisting](#vulnerability-allowlisting) + * [Running Container Scanning in an offline environment](#running-container-scanning-in-an-offline-environment) + * [Requirements for offline Container Scanning](#requirements-for-offline-container-scanning) + * [Make GitLab Container Scanning analyzer images available inside your Docker registry](#make-gitlab-container-scanning-analyzer-images-available-inside-your-docker-registry) + * [Set Container Scanning CI job variables to use local Container Scanner analyzers](#set-container-scanning-ci-job-variables-to-use-local-container-scanner-analyzers) + * [Automating Container Scanning vulnerability database updates with a pipeline](#automating-container-scanning-vulnerability-database-updates-with-a-pipeline) +* [Running the standalone Container Scanning Tool](#running-the-standalone-container-scanning-tool) +* [Reports JSON format](#reports-json-format) +* [Security Dashboard](#security-dashboard) +* [Vulnerabilities database update](#vulnerabilities-database-update) +* [Interacting with the vulnerabilities](#interacting-with-the-vulnerabilities) +* [Solutions for vulnerabilities (auto-remediation)](#solutions-for-vulnerabilities-auto-remediation) +* [Troubleshooting](#troubleshooting) + * [`docker: Error response from daemon: failed to copy xattrs`](#docker-error-response-from-daemon-failed-to-copy-xattrs) + +# Container Scanning[](#container-scanning-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4. + +## Overview[](#overview "Permalink") + +应用程序的 Docker 映像本身可能基于包含已知漏洞的 Docker 映像. 通过在管道中包含一个额外的作业来扫描这些漏洞并将其显示在合并请求中,您可以使用 GitLab 来审核基于 Docker 的应用程序. 默认情况下,GitLab 中的容器扫描基于[Clair](https://github.com/quay/clair)和[Klar](https://github.com/optiopay/klar) ,这是用于对容器中的漏洞进行静态分析的开源工具. [GitLab 的 Klar 分析仪](https://gitlab.com/gitlab-org/security-products/analyzers/klar/)扫描容器并用作 Clair 的包装纸. + +**注意:**要将除 Clair 和 Klar 以外的其他[安全扫描器集成](../../../development/integrations/secure.html)到 GitLab 中,请参阅" [安全扫描器集成"](../../../development/integrations/secure.html) . + +您可以通过执行以下任一操作来启用容器扫描: + +* 在现有的`.gitlab-ci.yml`文件中[包括 CI 作业](#configuration) . +* 隐式使用[Auto DevOps](../../../topics/autodevops/index.html)提供的[自动](../../../topics/autodevops/index.html) [容器扫描](../../../topics/autodevops/stages.html#auto-container-scanning-ultimate) . + +GitLab 比较发现的源分支与目标分支之间的漏洞,并在合并请求中直接显示信息. + +[![Container Scanning Widget](img/81b83780f68abcbb32edb1eb48002a4d.png)](img/container_scanning_v13_2.png) + +## Requirements[](#requirements "Permalink") + +要在管道中启用容器扫描,您需要以下内容: + +* 带有[Docker](https://docs.gitlab.com/runner/executors/docker.html)或[Kubernetes](https://docs.gitlab.com/runner/install/kubernetes.html)执行器的[GitLab Runner](https://docs.gitlab.com/runner/) . +* Docker `18.09.03`或更高版本与 Runner 安装在同一台计算机上. 如果您在 GitLab.com 上使用共享的 Runners,那么情况已经如此. +* [构建](../../packages/container_registry/index.html#container-registry-examples-with-gitlab-cicd) Docker 镜像[并将其推](../../packages/container_registry/index.html#container-registry-examples-with-gitlab-cicd)送到项目的容器注册表中. Docker 映像的名称应使用以下[预定义的环境变量](../../../ci/variables/predefined_variables.html) : + + ``` + $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA + ``` + + 您可以在`.gitlab-ci.yml`文件中直接使用它们: + + ``` + build: + image: docker:19.03.12 + stage: build + services: + - docker:19.03.12-dind + variables: + IMAGE_TAG: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA + script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker build -t $IMAGE_TAG . + - docker push $IMAGE_TAG + ``` + +## Configuration[](#configuration "Permalink") + +启用容器扫描的方式取决于您的 GitLab 版本: + +* GitLab 11.9 及更高版本: [包括](../../../ci/yaml/README.html#includetemplate) GitLab 安装随附的[`Container-Scanning.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml) . +* 11.9 之前的 GitLab 版本:从[`Container-Scanning.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml)复制并使用作业. + +要包括`Container-Scanning.gitlab-ci.yml`模板(GitLab 11.9 及更高版本),请将以下内容添加到您的`.gitlab-ci.yml`文件中: + +``` +include: + - template: Container-Scanning.gitlab-ci.yml +``` + +包含的模板: + +* 在 CI / CD 管道中创建`container_scanning`作业. +* 从项目的[Container Registry 中](../../packages/container_registry/index.html)拉出已构建的 Docker 映像(请参阅[要求](#requirements) ),并扫描其可能的漏洞. + +GitLab 将结果保存为" [容器扫描"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportscontainer_scanning-ultimate) ,您可以稍后下载和分析. 下载时,您始终会收到最新的工件. + +以下是一个示例`.gitlab-ci.yml` ,用于构建您的 Docker 映像,将其推送到 Container Registry 并扫描容器: + +``` +variables: + DOCKER_DRIVER: overlay2 + +stages: + - build + - test + +build: + image: docker:stable + stage: build + services: + - docker:19.03.12-dind + variables: + IMAGE: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA + script: + - docker info + - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY + - docker build -t $IMAGE . + - docker push $IMAGE + +include: + - template: Container-Scanning.gitlab-ci.yml +``` + +### Customizing the Container Scanning settings[](#customizing-the-container-scanning-settings "Permalink") + +There may be cases where you want to customize how GitLab scans your containers. For example, you may want to enable more verbose output from Clair or Klar, access a Docker registry that requires authentication, and more. To change such settings, use the [`variables`](../../../ci/yaml/README.html#variables) parameter in your `.gitlab-ci.yml` to set [environment variables](#available-variables). The environment variables you set in your `.gitlab-ci.yml` overwrite those in `Container-Scanning.gitlab-ci.yml`. + +此示例[包括](../../../ci/yaml/README.html#include)容器扫描模板,并通过将`CLAIR_OUTPUT`环境变量设置为`High`来启用 Clair 的详细输出: + +``` +include: + - template: Container-Scanning.gitlab-ci.yml + +variables: + CLAIR_OUTPUT: High +``` + +#### Available variables[](#available-variables "Permalink") + +可以使用环境变量[配置](#customizing-the-container-scanning-settings)容器扫描. + +| 环境变量 | Description | Default | +| --- | --- | --- | +| `SECURE_ANALYZERS_PREFIX` | 设置用于下载分析器的 Docker 注册表基地址. | `"registry.gitlab.com/gitlab-org/security-products/analyzers"` | +| `KLAR_TRACE` | 设置为 true 可启用 klar 的更多详细输出. | `"false"` | +| `CLAIR_TRACE` | 设置为 true 可启用 clair 服务器进程的更多详细输出. | `"false"` | +| `DOCKER_USER` | 用于访问需要身份验证的 Docker 注册表的用户名. | `$CI_REGISTRY_USER` | +| `DOCKER_PASSWORD` | 访问需要身份验证的 Docker 注册表的密码. | `$CI_REGISTRY_PASSWORD` | +| `CLAIR_OUTPUT` | 严重级别阈值. 严重级别高于或等于此阈值的漏洞将被输出. 支持的级别为`Unknown` , `Negligible` , `Low` , `Medium` , `High` , `Critical`和`Defcon1` . | `Unknown` | +| `REGISTRY_INSECURE` | 允许[Klar](https://github.com/optiopay/klar)访问不安全的注册表(仅 HTTP). 仅应在本地测试图像时设置为`true` . | `"false"` | +| `DOCKER_INSECURE` | 允许[Klar](https://github.com/optiopay/klar)使用带有错误(或自签名)SSL 证书的 HTTPS 访问安全的 Docker 注册表. | `"false"` | +| `CLAIR_VULNERABILITIES_DB_URL` | (不推荐**使用-改为使用`CLAIR_DB_CONNECTION_STRING`** )此变量在`Container-Scanning.gitlab-ci.yml`文件的[services 部分](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23)中显式设置,并且默认为`Container-Scanning.gitlab-ci.yml` `clair-vulnerabilities-db` . 该值表示[托管漏洞定义](https://hub.docker.com/r/arminc/clair-db)的[PostgreSQL 服务器](https://hub.docker.com/r/arminc/clair-db)正在运行的地址,除非您按照" [运行独立容器扫描工具"](#running-the-standalone-container-scanning-tool)部分中的说明在本地运行映像,否则**不应更改**该地址. | `clair-vulnerabilities-db` | +| `CLAIR_DB_CONNECTION_STRING` | 该变量表示[托管漏洞定义](https://hub.docker.com/r/arminc/clair-db)数据库的[PostgreSQL 服务器](https://hub.docker.com/r/arminc/clair-db)的[连接字符串](https://s0www0postgresql0org.icopy.site/docs/9.3/libpq-connect.html) ,除非您按照" [运行独立容器扫描工具"](#running-the-standalone-container-scanning-tool)部分中的说明在本地运行映像,否则**不应更改**该变量. 连接字符串的主机值必须与`Container-Scanning.gitlab-ci.yml`模板文件的[别名](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23)值匹配,该[别名](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23)默认为`clair-vulnerabilities-db` . | `postgresql://postgres:password@clair-vulnerabilities-db:5432/postgres?sslmode=disable&statement_timeout=60000` | +| `CI_APPLICATION_REPOSITORY` | Docker repository URL for the image to be scanned. | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` | +| `CI_APPLICATION_TAG` | 待扫描图像的 Docker 存储库标签. | `$CI_COMMIT_SHA` | +| `CLAIR_DB_IMAGE` | [托管漏洞定义](https://hub.docker.com/r/arminc/clair-db)的[PostgreSQL 服务器](https://hub.docker.com/r/arminc/clair-db)的 Docker 映像名称和标记. 使用特定版本覆盖此值可能很有用,例如,为了进行集成测试而提供一致的漏洞集,或在本地进行脱机安装时引用本地托管的漏洞数据库. | `arminc/clair-db:latest` | +| `CLAIR_DB_IMAGE_TAG` | (不推荐**使用-改为使用`CLAIR_DB_IMAGE`** ) [托管漏洞定义](https://hub.docker.com/r/arminc/clair-db)的[PostgreSQL 服务器](https://hub.docker.com/r/arminc/clair-db)的 Docker 映像标记. 可以使用特定版本覆盖此值,例如,为集成测试目的提供一致的漏洞集很有用. | `latest` | +| `DOCKERFILE_PATH` | 用于生成补救的`Dockerfile`的路径. 默认情况下,扫描程序将在项目的根目录中查找名为`Dockerfile`的文件,因此仅当您的`Dockerfile`位于非标准位置(例如子目录)时,才应配置此变量. 有关更多详细信息,请参见[漏洞解决方案](#solutions-for-vulnerabilities-auto-remediation) . | `Dockerfile` | +| `ADDITIONAL_CA_CERT_BUNDLE` | 您要信任的 CA 证书捆绑包. | ”” | +| `SECURE_LOG_LEVEL` | 可用的日志级别为: `fatal` , `error` , `warn` , `info` , `debug` | `info` | + +### Overriding the Container Scanning template[](#overriding-the-container-scanning-template "Permalink") + +如果要覆盖作业定义(例如,更改诸如`variables`属性),则必须在`container_scanning`模板之后声明一个`container_scanning`作业,然后指定任何其他键. 例如: + +``` +include: + - template: Container-Scanning.gitlab-ci.yml + +container_scanning: + variables: + GIT_STRATEGY: fetch +``` + +**Deprecated:** GitLab 13.0 and later doesn’t support [`only` and `except`](../../../ci/yaml/README.html#onlyexcept-basic). When overriding the template, you must use [`rules`](../../../ci/yaml/README.html#rules) instead. + +### Vulnerability allowlisting[](#vulnerability-allowlisting "Permalink") + +要允许列表特定漏洞,请按照下列步骤操作: + +1. 设置`GIT_STRATEGY: fetch`按照[覆盖容器扫描模板中](#overriding-the-container-scanning-template)的说明, `GIT_STRATEGY: fetch` `.gitlab-ci.yml`文件. +2. 在名为`vulnerability-allowlist.yml`的 YAML 文件中定义允许列出的漏洞. 这必须使用[许可清单示例文件中](https://gitlab.com/gitlab-org/security-products/analyzers/klar/-/raw/master/testdata/vulnerability-allowlist.yml)描述的格式. +3. 将`vulnerability-allowlist.yml`文件添加到项目的 Git 存储库中. + +### Running Container Scanning in an offline environment[](#running-container-scanning-in-an-offline-environment "Permalink") + +对于在通过互联网有限,受限或间歇性访问外部资源的环境中进行自我管理的 GitLab 实例,需要进行一些调整才能使容器扫描作业成功运行. 有关更多信息,请参阅[脱机环境](../offline_deployments/index.html) . + +#### Requirements for offline Container Scanning[](#requirements-for-offline-container-scanning "Permalink") + +要在脱机环境中使用容器扫描,您需要: + +* GitLab 亚军与[`docker`或`kubernetes`执行](#requirements) . +* 要使用 Container Scanning [分析器](https://gitlab.com/gitlab-org/security-products/analyzers/klar)映像的副本配置本地 Docker Container Registry,请在[Container Scanning 容器注册表中找到](https://gitlab.com/gitlab-org/security-products/analyzers/klar/container_registry) . + +**注意:** GitLab Runner 的[默认`pull policy`为`always`](https://docs.gitlab.com/runner/executors/docker.html) ,这意味着即使本地副本可用,Runner 也会尝试从 GitLab 容器注册表中拉取 Docker 映像. 如果您只喜欢使用本地可用的 Docker 映像,则可以在离线环境[`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html) GitLab Runner 的[`pull_policy`设置为`if-not-present`](https://docs.gitlab.com/runner/executors/docker.html) . 但是,如果不在离线环境中,我们建议将拉取策略设置保持为`always` ,因为这样可以在 CI / CD 管道中使用更新的扫描仪. + +#### Make GitLab Container Scanning analyzer images available inside your Docker registry[](#make-gitlab-container-scanning-analyzer-images-available-inside-your-docker-registry "Permalink") + +对于容器扫描,将以下默认图像从`registry.gitlab.com`导入[本地 Docker 容器注册表](../../packages/container_registry/index.html) : + +``` +registry.gitlab.com/gitlab-org/security-products/analyzers/klar +https://hub.docker.com/r/arminc/clair-db +``` + +将 Docker 映像导入本地脱机 Docker 注册表的过程取决于**您的网络安全策略** . 请咨询您的 IT 员工,以找到可以导入或临时访问外部资源的已接受和批准的流程. 请注意,这些扫描程序会[定期](../index.html#maintenance-and-update-of-the-vulnerabilities-database)使用新定义进行[更新](../index.html#maintenance-and-update-of-the-vulnerabilities-database) ,因此请考虑您是否能够自己进行定期更新. + +有关更多信息,请参见[有关如何使用管道更新映像的特定步骤](#automating-container-scanning-vulnerability-database-updates-with-a-pipeline) . + +有关将 Docker 映像保存和传输为文件的详细信息,请参阅 Docker 有关[`docker save`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/save/) , [`docker load`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/load/) , [`docker export`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/export/)和[`docker import`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/import/)的文档. + +#### Set Container Scanning CI job variables to use local Container Scanner analyzers[](#set-container-scanning-ci-job-variables-to-use-local-container-scanner-analyzers "Permalink") + +1. [覆盖](#overriding-the-container-scanning-template) `.gitlab-ci.yml`文件中[的容器扫描模板](#overriding-the-container-scanning-template) ,以引用本地 Docker 容器注册表中托管的 Docker 映像: + + ``` + include: + - template: Container-Scanning.gitlab-ci.yml + + container_scanning: + image: $CI_REGISTRY/namespace/gitlab-klar-analyzer + variables: + CLAIR_DB_IMAGE: $CI_REGISTRY/namespace/clair-vulnerabilities-db + ``` + +2. 如果您的本地 Docker 容器注册表正在通过`HTTPS`安全运行,但是您使用的是自签名证书,则必须在`.gitlab-ci.yml`的上述`container_scanning`部分中将`DOCKER_INSECURE: "true"`设置为. + +#### Automating Container Scanning vulnerability database updates with a pipeline[](#automating-container-scanning-vulnerability-database-updates-with-a-pipeline "Permalink") + +设置[计划的管道](../../../ci/pipelines/schedules.html)以按照预设的计划自动构建漏洞数据库的新版本可能是值得的. 使用管道自动执行此操作意味着您不必每次都手动进行操作. 您可以使用以下`.gitlab-yml.ci`作为模板: + +``` +image: docker:stable + +stages: + - build + +build_latest_vulnerabilities: + stage: build + services: + - docker:19.03.12-dind + script: + - docker pull arminc/clair-db:latest + - docker tag arminc/clair-db:latest $CI_REGISTRY/namespace/clair-vulnerabilities-db + - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY + - docker push $CI_REGISTRY/namespace/clair-vulnerabilities-db +``` + +上面的模板适用于在本地安装上运行的 GitLab Docker 注册表,但是,如果您使用的是非 GitLab Docker 注册表,则需要更改`$CI_REGISTRY`值和 Docker `docker login`凭据以匹配以下内容:您的本地注册表. + +## Running the standalone Container Scanning Tool[](#running-the-standalone-container-scanning-tool "Permalink") + +可以对 Docker 容器运行[GitLab 容器扫描工具](https://gitlab.com/gitlab-org/security-products/analyzers/klar) ,而无需在 CI 作业的上下文中运行它. 要直接扫描图像,请按照下列步骤操作: + +1. Run [Docker Desktop](https://www.docker.com/products/docker-desktop) or [Docker Machine](https://github.com/docker/machine). +2. 运行最新的[预填充漏洞数据库](https://hub.docker.com/repository/docker/arminc/clair-db) Docker 映像: + + ``` + docker run -p 5432:5432 -d --name clair-db arminc/clair-db:latest + ``` + +3. Configure an environment variable to point to your local machine’s IP address (or insert your IP address instead of the `LOCAL_MACHINE_IP_ADDRESS` variable in the `CLAIR_DB_CONNECTION_STRING` in the next step): + + ``` + export LOCAL_MACHINE_IP_ADDRESS=your.local.ip.address + ``` + +4. 运行分析器的 Docker 映像,并在`CI_APPLICATION_REPOSITORY`和`CI_APPLICATION_TAG`环境变量中传递要分析的映像和标签: + + ``` + docker run \ + --interactive --rm \ + --volume "$PWD":/tmp/app \ + -e CI_PROJECT_DIR=/tmp/app \ + -e CLAIR_DB_CONNECTION_STRING="postgresql://postgres:password@${LOCAL_MACHINE_IP_ADDRESS}:5432/postgres?sslmode=disable&statement_timeout=60000" \ + -e CI_APPLICATION_REPOSITORY=registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256 \ + -e CI_APPLICATION_TAG=bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e \ + registry.gitlab.com/gitlab-org/security-products/analyzers/klar + ``` + +结果存储在`gl-container-scanning-report.json` . + +## Reports JSON format[](#reports-json-format "Permalink") + +容器扫描工具会发出 JSON 报告文件. 有关更多信息,请参见此[报告](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json)的[架构](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json) . + +这是示例容器扫描报告: + +``` +{ "version": "2.3", "vulnerabilities": [ { "id": "ac0997ad-1006-4c81-81fb-ee2bbe6e78e3", "category": "container_scanning", "message": "CVE-2019-3462 in apt", "description": "Incorrect sanitation of the 302 redirect field in HTTP transport method of apt versions 1.4.8 and earlier can lead to content injection by a MITM attacker, potentially leading to remote code execution on the target machine.", "severity": "High", "confidence": "Unknown", "solution": "Upgrade apt from 1.4.8 to 1.4.9", "scanner": { "id": "klar", "name": "klar" }, "location": { "dependency": { "package": { "name": "apt" }, "version": "1.4.8" }, "operating_system": "debian:9", "image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e" }, "identifiers": [ { "type": "cve", "name": "CVE-2019-3462", "value": "CVE-2019-3462", "url": "https://security-tracker.debian.org/tracker/CVE-2019-3462" } ], "links": [ { "url": "https://security-tracker.debian.org/tracker/CVE-2019-3462" } ] } ], "remediations": [ { "fixes": [ { "id": "c0997ad-1006-4c81-81fb-ee2bbe6e78e3" } ], "summary": "Upgrade apt from 1.4.8 to 1.4.9", "diff": "YXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCB1cGdyYWRlIC15IGFwdA==" } ] } +``` + +## Security Dashboard[](#security-dashboard "Permalink") + +[安全仪表板](../security_dashboard/index.html)向您显示组,项目和管道中所有安全漏洞的概述. + +## Vulnerabilities database update[](#vulnerabilities-database-update "Permalink") + +有关漏洞数据库更新的更多信息,请查看[维护表](../index.html#maintenance-and-update-of-the-vulnerabilities-database) . + +## Interacting with the vulnerabilities[](#interacting-with-the-vulnerabilities "Permalink") + +一旦发现漏洞,便可以[与其进行交互](../index.html#interacting-with-the-vulnerabilities) . + +## Solutions for vulnerabilities (auto-remediation)[](#solutions-for-vulnerabilities-auto-remediation "Permalink") + +可以通过应用 GitLab 自动生成的解决方案来修复某些漏洞. + +为了使整治的支持,对扫描工具*必须*能够访问`Dockerfile`指定由[`DOCKERFILE_PATH`](#available-variables)环境变量. 为确保扫描工具可以访问此文件,有必要设置[`GIT_STRATEGY: fetch`](../../../ci/yaml/README.html#git-strategy)按照本文档中" [覆盖容器扫描模板"](#overriding-the-container-scanning-template)部分中介绍的说明,在`.gitlab-ci.yml`文件中进行[`GIT_STRATEGY: fetch`](../../../ci/yaml/README.html#git-strategy) . + +阅读有关[漏洞解决方案的](../index.html#solutions-for-vulnerabilities-auto-remediation)更多信息. + +## Troubleshooting[](#troubleshooting "Permalink") + +### `docker: Error response from daemon: failed to copy xattrs`[](#docker-error-response-from-daemon-failed-to-copy-xattrs "Permalink") + +当 GitLab Runner 使用 Docker 执行程序并使用 NFS 时(例如, `/var/lib/docker`在 NFS 挂载上),容器扫描可能会失败,并显示以下错误: + +``` +docker: Error response from daemon: failed to copy xattrs: failed to set xattr "security.selinux" on /path/to/file: operation not supported. +``` + +这是由于 Docker 中的一个错误而导致的,该错误现已[修复](https://github.com/containerd/continuity/pull/138 "fs:添加 WithAllowXAttrErrors CopyOpt") . 为避免该错误,请确保 Runner 使用的 Docker 版本为`18.09.03`或更高. 有关更多信息,请参见[问题#10241](https://gitlab.com/gitlab-org/gitlab/-/issues/10241 "调查为什么容器扫描不适用于 NFS 挂载") . \ No newline at end of file diff --git a/_book/docs/052.md b/_book/docs/052.md new file mode 100644 index 0000000000000000000000000000000000000000..4c8515bb49211c2eb62332dba94676452a06748f --- /dev/null +++ b/_book/docs/052.md @@ -0,0 +1,370 @@ +# Dependency Scanning + +> 原文:[https://docs.gitlab.com/ee/user/application_security/dependency_scanning/](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) + +* [Overview](#overview) +* [Requirements](#requirements) +* [Supported languages and package managers](#supported-languages-and-package-managers) +* [Contribute your scanner](#contribute-your-scanner) +* [Configuration](#configuration) + * [Customizing the Dependency Scanning settings](#customizing-the-dependency-scanning-settings) + * [Overriding Dependency Scanning jobs](#overriding-dependency-scanning-jobs) + * [Available variables](#available-variables) + * [Configuring Dependency Scanning](#configuring-dependency-scanning) + * [Configuring Docker-in-Docker orchestrator](#configuring-docker-in-docker-orchestrator) + * [Configuring specific analyzers used by Dependency Scanning](#configuring-specific-analyzers-used-by-dependency-scanning) + * [Using private Maven repos](#using-private-maven-repos) + * [Enabling Docker-in-Docker](#enabling-docker-in-docker) +* [Interacting with the vulnerabilities](#interacting-with-the-vulnerabilities) +* [Solutions for vulnerabilities (auto-remediation)](#solutions-for-vulnerabilities-auto-remediation) +* [Security Dashboard](#security-dashboard) +* [Vulnerabilities database update](#vulnerabilities-database-update) +* [Dependency List](#dependency-list) +* [Reports JSON format](#reports-json-format) +* [Versioning and release process](#versioning-and-release-process) +* [Contributing to the vulnerability database](#contributing-to-the-vulnerability-database) +* [Running Dependency Scanning in an offline environment](#running-dependency-scanning-in-an-offline-environment) + * [Requirements for offline Dependency Scanning](#requirements-for-offline-dependency-scanning) + * [Make GitLab Dependency Scanning analyzer images available inside your Docker registry](#make-gitlab-dependency-scanning-analyzer-images-available-inside-your-docker-registry) + * [Set Dependency Scanning CI job variables to use local Dependency Scanning analyzers](#set-dependency-scanning-ci-job-variables-to-use-local-dependency-scanning-analyzers) + * [Specific settings for languages and package managers](#specific-settings-for-languages-and-package-managers) + * [JavaScript (npm and yarn) projects](#javascript-npm-and-yarn-projects) + * [Ruby (gem) projects](#ruby-gem-projects) + * [Python (setuptools)](#python-setuptools) +* [Limitations](#limitations) + * [Referencing local dependencies using a path in JavaScript projects](#referencing-local-dependencies-using-a-path-in-javascript-projects) +* [Troubleshooting](#troubleshooting) + * [`Error response from daemon: error processing tar file: docker-tar: relocation error`](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) + +# Dependency Scanning[](#dependency-scanning-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5105) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.7. + +在开发和测试应用程序时,例如当应用程序使用已知的易受攻击的外部(开源)库时,"依赖关系扫描"有助于自动在依赖项中查找安全漏洞. + +## Overview[](#overview "Permalink") + +如果您使用的是[GitLab CI / CD](../../../ci/README.html) ,则可以使用"依赖关系扫描"来分析依赖关系中的已知漏洞. 扫描所有依赖项,包括传递性依赖项(也称为嵌套依赖项). 您可以通过在现有`.gitlab-ci.yml`文件中[包括依赖扫描模板](#configuration) ,或通过隐式使用[Auto DevOps](../../../topics/autodevops/index.html)提供的[自动依赖扫描](../../../topics/autodevops/stages.html#auto-dependency-scanning-ultimate)来利用[依赖扫描](../../../topics/autodevops/stages.html#auto-dependency-scanning-ultimate) . + +GitLab 检查"依赖性扫描"报告,比较发现的源分支和目标分支之间的漏洞,并显示有关合并请求的信息. + +[![Dependency Scanning Widget](img/6d49650d7eab0173612011fa6d81dc4e.png)](img/dependency_scanning_v13_2.png) + +结果按漏洞的严重性排序: + +1. Critical +2. High +3. Medium +4. Low +5. Unknown +6. 其他一切 + +## Requirements[](#requirements "Permalink") + +要运行依赖扫描作业,默认情况下,你需要 GitLab 亚军与[`docker`](https://docs.gitlab.com/runner/executors/docker.html)或[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html)执行. 如果您在 GitLab.com 上使用共享的 Runners,则默认启用该功能. + +**注意:**如果使用自己的 Runners,请确保已安装的 Docker 版本**不是** `19.03.0` . 有关详细[信息](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) ,请参见[故障排除信息](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) . + +从 GitLab 13.0 开始,仅当您已[启用 Docker-in-Docker 进行依赖项扫描](#enabling-docker-in-docker)时,才需要 Docker 特权模式. + +## Supported languages and package managers[](#supported-languages-and-package-managers "Permalink") + +GitLab 依赖于[`rules`](../../../ci/yaml/README.html#rules)来启动相关分析器,具体取决于存储库中检测到的语言. 当前的检测逻辑将最大搜索深度限制为两个级别. 例如,如果存储库包含`Gemfile`或`api/Gemfile`文件,则启用`gemnasium-dependency_scanning`作业,但如果唯一受支持的依赖性文件是`api/client/Gemfile` . + +支持以下语言和依赖项管理器: + +| 语言(程序包管理器) | 支援的档案 | 扫描工具 | +| --- | --- | --- | +| Java ([Gradle](https://s0gradle0org.icopy.site/), [Maven](https://maven.apache.org/)) | `build.gradle`, `build.gradle.kts`, `pom.xml` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | +| JavaScript( [npm](https://s0www0npmjs0com.icopy.site/) , [yarn](https://classic.yarnpkg.com/en/) ) | `package-lock.json`, `npm-shrinkwrap.json`, `yarn.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium), [Retire.js](https://retirejs.github.io/retire.js/) | +| 去( [Golang](https://s0golang0org.icopy.site/) ) | `go.sum` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | +| PHP( [作曲家](https://s0getcomposer0org.icopy.site/) ) | `composer.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | +| Python( [setuptools](https://setuptools.readthedocs.io/en/latest/) , [pip](https://pip.pypa.io/en/stable/) , [Pipenv](https://pipenv.pypa.io/en/latest/) ) | `setup.py`, `requirements.txt`, `requirements.pip`, `requires.txt`, `Pipfile` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | +| 红宝石( [Bundler](https://bundler.io/) ) | `Gemfile.lock`, `gems.locked` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium), [bundler-audit](https://github.com/rubysec/bundler-audit) | +| Scala( [sbt](https://www.scala-sbt.org/) ) | `build.sbt` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | + +正在制定支持以下语言,依赖性管理器和依赖性文件的计划. 有关详细信息,请参见每个的问题链接. + +| 语言(程序包管理器) | 支援的档案 | 扫描工具 | Issue | +| --- | --- | --- | --- | +| Python( [诗歌](https://python-poetry.org/) ) | `poetry.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#7006](https://gitlab.com/gitlab-org/gitlab/-/issues/7006) | +| Python( [Pipenv](https://pipenv.pypa.io/en/latest/) ) | `Pipfile.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#11756](https://gitlab.com/gitlab-org/gitlab/-/issues/11756) | + +## Contribute your scanner[](#contribute-your-scanner "Permalink") + +[安全扫描程序集成](../../../development/integrations/secure.html)文档说明了如何将其他安全扫描[程序集成](../../../development/integrations/secure.html)到 GitLab 中. + +## Configuration[](#configuration "Permalink") + +To enable Dependency Scanning for GitLab 11.9 and later, you must [include](../../../ci/yaml/README.html#includetemplate) the [`Dependency-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml) that’s provided as a part of your GitLab installation. For GitLab versions earlier than 11.9, you can copy and use the job as defined that template. + +将以下内容添加到您的`.gitlab-ci.yml`文件中: + +``` +include: + - template: Dependency-Scanning.gitlab-ci.yml +``` + +随附的模板将在 CI / CD 管道中创建"依赖关系扫描"作业,并扫描项目的源代码以查找可能的漏洞. 结果将保存为" [依赖关系扫描"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsdependency_scanning-ultimate) ,您以后可以下载和分析该[工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsdependency_scanning-ultimate) . 由于实施限制,我们始终采用最新的"依赖关系扫描"工件. + +### Customizing the Dependency Scanning settings[](#customizing-the-dependency-scanning-settings "Permalink") + +可以使用`.gitlab-ci.yml`的[`variables`](../../../ci/yaml/README.html#variables)参数通过[环境变量](#available-variables)来更改"依赖项扫描"设置. 例如: + +``` +include: + - template: Dependency-Scanning.gitlab-ci.yml + +variables: + DS_PYTHON_VERSION: 2 +``` + +因为模板是[在](../../../ci/yaml/README.html#include)管道配置[之前评估](../../../ci/yaml/README.html#include)的,所以最后提到的变量将具有优先权. + +### Overriding Dependency Scanning jobs[](#overriding-dependency-scanning-jobs "Permalink") + +**弃用:**从 GitLab 13.0 开始,不再支持[`only`和`except`](../../../ci/yaml/README.html#onlyexcept-basic)的使用. 覆盖模板时,必须使用[`rules`](../../../ci/yaml/README.html#rules) . + +要覆盖作业定义(例如,更改诸如`variables`或`dependencies`类的属性),请声明一个与要覆盖的作业同名的新作业. 将此新作业放置在包含模板之后,并在其下指定其他任何键. 例如,这将禁用`DS_REMEDIATE`为`gemnasium`分析器: + +``` +include: + - template: Dependency-Scanning.gitlab-ci.yml + +gemnasium-dependency_scanning: + variables: + DS_REMEDIATE: "false" +``` + +### Available variables[](#available-variables "Permalink") + +可以使用环境变量[配置](#customizing-the-dependency-scanning-settings)依赖性扫描. + +#### Configuring Dependency Scanning[](#configuring-dependency-scanning "Permalink") + +以下变量允许配置全局依赖项扫描设置. + +| 环境变量 | Description | +| --- | --- | +| `SECURE_ANALYZERS_PREFIX` | 覆盖提供正式默认映像(代理)的 Docker 注册表名称. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `DS_DEFAULT_ANALYZERS` | 覆盖正式默认图像的名称. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `DS_DISABLE_DIND` | 禁用 Docker-in-Docker 并[单独](#enabling-docker-in-docker)运行分析器. 默认情况下,此变量为`true` . | +| `ADDITIONAL_CA_CERT_BUNDLE` | 捆绑的 CA 证书可信任. | +| `DS_EXCLUDED_PATHS` | 根据路径从输出中排除漏洞. 以逗号分隔的模式列表. 模式可以是全局变量,也可以是文件或文件夹路径(例如`doc,spec` ). 父目录也匹配模式. 默认值: `"spec, test, tests, tmp"` | +| `SECURE_LOG_LEVEL` | 默认日志级别为`info` ,您可以将其设置为以下任意字符串: `fatal` , `error` , `warn` , `info` , `debug` . | + +#### Configuring Docker-in-Docker orchestrator[](#configuring-docker-in-docker-orchestrator "Permalink") + +以下变量配置 Docker-in-Docker 协调器,因此仅在[启用](#enabling-docker-in-docker) Docker-in-Docker 模式时才使用. + +| 环境变量 | Default | Description | +| --- | --- | --- | +| `DS_ANALYZER_IMAGES` |   | 以逗号分隔的自定义图像列表. 官方默认图像仍处于启用状态. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `DS_ANALYZER_IMAGE_TAG` |   | 覆盖官方默认映像的 Docker 标签. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `DS_PULL_ANALYZER_IMAGES` |   | 从 Docker 注册表中提取映像(设置为`0`以禁用). | +| `DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT` | 2m | Docker 客户端协商的时间限制. 使用 Go 的[`ParseDuration`](https://s0golang0org.icopy.site/pkg/time/)解析超时. 有效时间单位为`ns` , `us` (或`µs` ), `ms` , `s` , `m`或`h` . 例如`300ms` , `1.5h`或`2h45m` . | +| `DS_PULL_ANALYZER_IMAGE_TIMEOUT` | 5m | 拉取分析仪图像的时间限制. 使用 Go 的[`ParseDuration`](https://s0golang0org.icopy.site/pkg/time/)解析超时. 有效时间单位为`ns` , `us` (或`µs` ), `ms` , `s` , `m`或`h` . 例如`300ms` , `1.5h`或`2h45m` . | +| `DS_RUN_ANALYZER_TIMEOUT` | 20m | 运行分析仪的时间限制. 使用 Go 的[`ParseDuration`](https://s0golang0org.icopy.site/pkg/time/)解析超时. 有效时间单位为`ns` , `us` (或`µs` ), `ms` , `s` , `m`或`h` . 例如`300ms` , `1.5h`或`2h45m` . | + +#### Configuring specific analyzers used by Dependency Scanning[](#configuring-specific-analyzers-used-by-dependency-scanning "Permalink") + +以下变量用于配置特定的分析器(用于特定的语言/框架). + +| Environment variable | Analyzer | Default | Description | +| --- | --- | --- | --- | +| `GEMNASIUM_DB_LOCAL_PATH` | `gemnasium` | `/gemnasium-db` | 本地 Gemnasium 数据库的路径. | +| `GEMNASIUM_DB_REMOTE_URL` | `gemnasium` | `https://gitlab.com/gitlab-org/security-products/gemnasium-db.git` | 用于获取 Gemnasium 数据库的存储库 URL. | +| `GEMNASIUM_DB_REF_NAME` | `gemnasium` | `master` | 远程存储库数据库的分支名称. 需要`GEMNASIUM_DB_REMOTE_URL` . | +| `DS_REMEDIATE` | `gemnasium` | `"true"` | 启用对弱势依赖项的自动修复. | +| `PIP_INDEX_URL` | `gemnasium-python` | `https://pypi.org/simple` | Python 软件包索引的基本 URL. | +| `PIP_EXTRA_INDEX_URL` | `gemnasium-python` |   | 除`PIP_INDEX_URL`之外, `PIP_INDEX_URL`使用包索引的其他[URL](https://pip.pypa.io/en/stable/reference/pip_install/#cmdoption-extra-index-url)数组. 以逗号分隔. | +| `PIP_REQUIREMENTS_FILE` | `gemnasium-python` |   | 要扫描的点子要求文件. | +| `DS_PIP_VERSION` | `gemnasium-python` |   | 强制安装特定的 pip 版本(例如: `"19.3"` ),否则将使用 Docker 映像中安装的 pip. (在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12811) ) | +| `DS_PIP_DEPENDENCY_PATH` | `gemnasium-python` |   | 从中加载 Python pip 依赖项的路径. (在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12412) ) | +| `DS_PYTHON_VERSION` | `retire.js` |   | Python 版本. 如果设置为 2,则将使用 Python 2.7 而非 Python 3.6 安装依赖项. (在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12296) ) | +| `DS_JAVA_VERSION` | `gemnasium-maven` | `11` | Java 版本. 可用版本: `8` , `11` , `13` , `14` . Maven 和 Gradle 将使用此值指定的 Java 版本. | +| `MAVEN_CLI_OPTS` | `gemnasium-maven` | `"-DskipTests --batch-mode"` | 分析器将传递给`maven`的命令行参数列表. 请参阅[使用私有存储库](../index.html#using-private-maven-repos)的示例. | +| `GRADLE_CLI_OPTS` | `gemnasium-maven` |   | 分析器将传递给`gradle`的命令行参数列表. | +| `SBT_CLI_OPTS` | `gemnasium-maven` |   | 分析器将传递给`sbt`的命令行参数列表. | +| `BUNDLER_AUDIT_UPDATE_DISABLED` | `bundler-audit` | `"false"` | 禁用`bundler-audit`分析器的自动更新. 如果您在脱机的空白环境中运行"依赖性扫描",则很有用. | +| `BUNDLER_AUDIT_ADVISORY_DB_URL` | `bundler-audit` | `https://github.com/rubysec/ruby-advisory-db` | bundler-audit 使用的咨询数据库的 URL. | +| `BUNDLER_AUDIT_ADVISORY_DB_REF_NAME` | `bundler-audit` | `master` | `BUNDLER_AUDIT_ADVISORY_DB_URL`指定的咨询数据库的 Git ref. | +| `RETIREJS_JS_ADVISORY_DB` | `retire.js` | `https://raw.githubusercontent.com/RetireJS/retire.js/master/repository/jsrepository.json` | `retire.js` JS 漏洞数据文件的路径或 URL. 请注意,如果托管数据文件的 URL 使用自定义 SSL 证书(例如在脱机安装中),则可以在`ADDITIONAL_CA_CERT_BUNDLE`环境变量中传递证书. | +| `RETIREJS_NODE_ADVISORY_DB` | `retire.js` | `https://raw.githubusercontent.com/RetireJS/retire.js/master/repository/npmrepository.json` | `retire.js`节点漏洞数据文件的路径或 URL. 请注意,如果托管数据文件的 URL 使用自定义 SSL 证书(例如在脱机安装中),则可以在`ADDITIONAL_CA_CERT_BUNDLE`环境变量中传递证书. | +| `RETIREJS_ADVISORY_DB_INSECURE` | `retire.js` | `false` | 启用使用不安全或自签名 SSL(TLS)证书从主机获取远程 JS 和 Node 漏洞数据文件(由`RETIREJS_JS_ADVISORY_DB`和`RETIREJS_NODE_ADVISORY_DB`变量定义)的功能. | + +### Using private Maven repos[](#using-private-maven-repos "Permalink") + +如果您的私有 Maven 存储库需要登录凭据,则可以使用`MAVEN_CLI_OPTS`环境变量. + +阅读有关[如何使用私有 Maven 存储库的](../index.html#using-private-maven-repos)更多[信息](../index.html#using-private-maven-repos) . + +### Enabling Docker-in-Docker[](#enabling-docker-in-docker "Permalink") + +在 GitLab Ultimate 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12487) . + +如果需要,可以启用 Docker-in-Docker 来还原 GitLab 13.0 之前存在的 Dependency Scanning 行为. 请按照以下步骤操作: + +1. 在[特权模式下](https://docs.gitlab.com/runner/executors/docker.html)使用 Docker-in-Docker 配置 GitLab Runner. +2. Set the `DS_DISABLE_DIND` variable to `false`: + + ``` + include: + - template: Dependency-Scanning.gitlab-ci.yml + + variables: + DS_DISABLE_DIND: "false" + ``` + +这将在您的 CI / CD 管道中创建一个`dependency_scanning`作业,而不是多个`-dependency_scanning`作业. + +## Interacting with the vulnerabilities[](#interacting-with-the-vulnerabilities "Permalink") + +一旦发现漏洞,便可以与其进行交互. 阅读有关如何[与漏洞](../index.html#interacting-with-the-vulnerabilities)进行[交互的](../index.html#interacting-with-the-vulnerabilities)更多信息. + +## Solutions for vulnerabilities (auto-remediation)[](#solutions-for-vulnerabilities-auto-remediation "Permalink") + +可以通过应用 GitLab 自动生成的解决方案来修复某些漏洞. 阅读有关[漏洞解决方案的](../index.html#solutions-for-vulnerabilities-auto-remediation)更多信息. + +## Security Dashboard[](#security-dashboard "Permalink") + +在"安全仪表板"中,您可以概览您的组,项目和管道中的所有安全漏洞. 阅读有关[安全仪表板的](../security_dashboard/index.html)更多[信息](../security_dashboard/index.html) . + +## Vulnerabilities database update[](#vulnerabilities-database-update "Permalink") + +有关漏洞数据库更新的更多信息,请查看[维护表](../index.html#maintenance-and-update-of-the-vulnerabilities-database) . + +## Dependency List[](#dependency-list "Permalink") + +依赖项扫描的另一个好处是能够查看项目的依赖项及其已知漏洞. 阅读有关[依赖列表的](../dependency_list/index.html)更多信息. + +## Reports JSON format[](#reports-json-format "Permalink") + +依赖关系扫描工具将发出 JSON 报告文件. 有关更多信息,请参见此[报告](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/dependency-scanning-report-format.json)的[架构](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/dependency-scanning-report-format.json) . + +这是一个示例依赖性扫描报告: + +``` +{ "version": "2.0", "vulnerabilities": [ { "id": "51e83874-0ff6-4677-a4c5-249060554eae", "category": "dependency_scanning", "name": "Regular Expression Denial of Service", "message": "Regular Expression Denial of Service in debug", "description": "The debug module is vulnerable to regular expression denial of service when untrusted user input is passed into the `o` formatter. It takes around 50k characters to block for 2 seconds making this a low severity issue.", "severity": "Unknown", "solution": "Upgrade to latest versions.", "scanner": { "id": "gemnasium", "name": "Gemnasium" }, "location": { "file": "yarn.lock", "dependency": { "package": { "name": "debug" }, "version": "1.0.5" } }, "identifiers": [ { "type": "gemnasium", "name": "Gemnasium-37283ed4-0380-40d7-ada7-2d994afcc62a", "value": "37283ed4-0380-40d7-ada7-2d994afcc62a", "url": "https://deps.sec.gitlab.com/packages/npm/debug/versions/1.0.5/advisories" } ], "links": [ { "url": "https://nodesecurity.io/advisories/534" }, { "url": "https://github.com/visionmedia/debug/issues/501" }, { "url": "https://github.com/visionmedia/debug/pull/504" } ] }, { "id": "5d681b13-e8fa-4668-957e-8d88f932ddc7", "category": "dependency_scanning", "name": "Authentication bypass via incorrect DOM traversal and canonicalization", "message": "Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js", "description": "Some XML DOM traversal and canonicalization APIs may be inconsistent in handling of comments within XML nodes. Incorrect use of these APIs by some SAML libraries results in incorrect parsing of the inner text of XML nodes such that any inner text after the comment is lost prior to cryptographically signing the SAML message. Text after the comment therefore has no impact on the signature on the SAML message.\r\n\r\nA remote attacker can modify SAML content for a SAML service provider without invalidating the cryptographic signature, which may allow attackers to bypass primary authentication for the affected SAML service provider.", "severity": "Unknown", "solution": "Upgrade to fixed version.\r\n", "scanner": { "id": "gemnasium", "name": "Gemnasium" }, "location": { "file": "yarn.lock", "dependency": { "package": { "name": "saml2-js" }, "version": "1.5.0" } }, "identifiers": [ { "type": "gemnasium", "name": "Gemnasium-9952e574-7b5b-46fa-a270-aeb694198a98", "value": "9952e574-7b5b-46fa-a270-aeb694198a98", "url": "https://deps.sec.gitlab.com/packages/npm/saml2-js/versions/1.5.0/advisories" }, { "type": "cve", "name": "CVE-2017-11429", "value": "CVE-2017-11429", "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429" } ], "links": [ { "url": "https://github.com/Clever/saml2/commit/3546cb61fd541f219abda364c5b919633609ef3d#diff-af730f9f738de1c9ad87596df3f6de84R279" }, { "url": "https://github.com/Clever/saml2/issues/127" }, { "url": "https://www.kb.cert.org/vuls/id/475445" } ] } ], "remediations": [ { "fixes": [ { "id": "5d681b13-e8fa-4668-957e-8d88f932ddc7", } ], "summary": "Upgrade saml2-js", "diff": "ZGlmZiAtLWdpdCBhL...OR0d1ZUc2THh3UT09Cg==" // some content is omitted for brevity } ] } +``` + +## Versioning and release process[](#versioning-and-release-process "Permalink") + +请检查[发布过程文档](https://gitlab.com/gitlab-org/security-products/release/blob/master/docs/release_process.md) . + +## Contributing to the vulnerability database[](#contributing-to-the-vulnerability-database "Permalink") + +您可以搜索[gemnasium-db](https://gitlab.com/gitlab-org/security-products/gemnasium-db)项目,以在 Gemnasium 数据库中找到漏洞. 您还可以[提交新漏洞](https://gitlab.com/gitlab-org/security-products/gemnasium-db/blob/master/CONTRIBUTING.md) . + +## Running Dependency Scanning in an offline environment[](#running-dependency-scanning-in-an-offline-environment "Permalink") + +对于在通过 Internet 限制,限制或间歇性访问外部资源的环境中进行自我管理的 GitLab 实例,需要进行一些调整才能使"依赖关系扫描"作业成功运行. 有关更多信息,请参阅[脱机环境](../offline_deployments/index.html) . + +### Requirements for offline Dependency Scanning[](#requirements-for-offline-dependency-scanning "Permalink") + +以下是在脱机环境中使用依赖关系扫描的要求: + +* Keep Docker-In-Docker disabled (default). +* GitLab 亚军与[`docker`或`kubernetes`执行](#requirements) . +* Docker 容器注册表以及 Dependency Scanning [分析器](https://gitlab.com/gitlab-org/security-products/analyzers)映像的本地可用副本. +* 托管[gemnasium-db 咨询数据库](https://gitlab.com/gitlab-org/security-products/gemnasium-db/)的脱机 Git 副本 +* *仅在扫描 Ruby 项目时* :托管[咨询数据库](https://github.com/rubysec/ruby-advisory-db)的脱机 Git 副本. +* *仅在扫描 npm / yarn 项目时* :托管[retire.js](https://github.com/RetireJS/retire.js/) [节点](https://github.com/RetireJS/retire.js/blob/master/repository/npmrepository.json)和[js](https://github.com/RetireJS/retire.js/blob/master/repository/jsrepository.json)咨询数据库的脱机副本. + +**注意:** GitLab Runner 的[默认`pull policy`为`always`](https://docs.gitlab.com/runner/executors/docker.html) ,这意味着即使本地副本可用,Runner 也会尝试从 GitLab 容器注册表中拉取 Docker 映像. 如果您只喜欢使用本地可用的 Docker 映像,则可以在离线环境[`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html) GitLab Runner 的[`pull_policy`设置为`if-not-present`](https://docs.gitlab.com/runner/executors/docker.html) . 但是,如果不在离线环境中,我们建议将拉取策略设置保持为`always` ,因为这样可以在 CI / CD 管道中使用更新的扫描仪. + +### Make GitLab Dependency Scanning analyzer images available inside your Docker registry[](#make-gitlab-dependency-scanning-analyzer-images-available-inside-your-docker-registry "Permalink") + +对于具有所有[受支持的语言和框架的](#supported-languages-and-package-managers)依赖关系扫描,请将以下默认的依赖关系扫描分析器映像从`registry.gitlab.com`导入[本地 Docker 容器注册表](../../packages/container_registry/index.html) : + +``` +registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/retire.js:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/bundler-audit:2 +``` + +将 Docker 映像导入本地脱机 Docker 注册表的过程取决于**您的网络安全策略** . 请咨询您的 IT 员工,以找到可以导入或临时访问外部资源的已接受和批准的流程. 请注意,这些扫描程序会[定期](../index.html#maintenance-and-update-of-the-vulnerabilities-database)使用新定义进行[更新](../index.html#maintenance-and-update-of-the-vulnerabilities-database) ,因此请考虑是否可以自己进行定期更新. + +有关将 Docker 映像保存和传输为文件的详细信息,请参阅 Docker 有关[`docker save`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/save/) , [`docker load`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/load/) , [`docker export`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/export/)和[`docker import`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/import/)的文档. + +### Set Dependency Scanning CI job variables to use local Dependency Scanning analyzers[](#set-dependency-scanning-ci-job-variables-to-use-local-dependency-scanning-analyzers "Permalink") + +将以下配置添加到您的`.gitlab-ci.yml`文件. 您必须替换`SECURE_ANALYZERS_PREFIX`才能引用本地 Docker 容器注册表: + +``` +include: + - template: Dependency-Scanning.gitlab-ci.yml + +variables: + SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers" + GEMNASIUM_DB_REMOTE_URL: "gitlab.example.com/gemnasium-db.git" + GIT_SSL_NO_VERIFY: "true" +``` + +请参阅[配置部分中](#configuration)以上变量的说明. + +### Specific settings for languages and package managers[](#specific-settings-for-languages-and-package-managers "Permalink") + +请参阅以下各节,以配置特定的语言和程序包管理器. + +#### JavaScript (npm and yarn) projects[](#javascript-npm-and-yarn-projects "Permalink") + +将以下内容添加到`.gitlab-ci.yml`的变量部分: + +``` +RETIREJS_JS_ADVISORY_DB: "example.com/jsrepository.json" +RETIREJS_NODE_ADVISORY_DB: "example.com/npmrepository.json" +``` + +#### Ruby (gem) projects[](#ruby-gem-projects "Permalink") + +将以下内容添加到`.gitlab-ci.yml`的变量部分: + +``` +BUNDLER_AUDIT_ADVISORY_DB_REF_NAME: "master" +BUNDLER_AUDIT_ADVISORY_DB_URL: "gitlab.example.com/ruby-advisory-db.git" +``` + +#### Python (setuptools)[](#python-setuptools "Permalink") + +当为私有 PyPi 存储库使用自签名证书时,不需要额外的作业配置(除了上面的模板`.gitlab-ci.yml` ). 但是,您必须更新`setup.py`以确保它可以到达您的私有存储库. 这是一个示例配置: + +1. 更新`setup.py` ,以为`install_requires`列表中的每个依赖项创建一个指向您的私有存储库的`dependency_links`属性: + + ``` + install_requires=['pyparsing>=2.0.3'], + dependency_links=['https://pypi.example.com/simple/pyparsing'], + ``` + +2. 从存储库 URL 中获取证书并将其添加到项目中: + + ``` + echo -n | openssl s_client -connect pypi.example.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > internal.crt + ``` + +3. 将`setup.py`指向新下载的证书: + + ``` + import setuptools.ssl_support + setuptools.ssl_support.cert_paths = ['internal.crt'] + ``` + +## Limitations[](#limitations "Permalink") + +### Referencing local dependencies using a path in JavaScript projects[](#referencing-local-dependencies-using-a-path-in-javascript-projects "Permalink") + +[Retire.js](https://gitlab.com/gitlab-org/security-products/analyzers/retire.js)分析器不支持使用 JavaScript 项目的`package.json`的[本地路径](https://s0docs0npmjs0com.icopy.site/files/package.json)进行的依赖项引用. 依赖项扫描针对此类引用输出以下错误: + +``` +ERROR: Could not find dependencies: . You may need to run npm install +``` + +解决方法是,从[DS_DEFAULT_ANALYZERS](#configuring-dependency-scanning)删除[`retire.js`](analyzers.html#selecting-specific-analyzers)分析器. + +## Troubleshooting[](#troubleshooting "Permalink") + +### `Error response from daemon: error processing tar file: docker-tar: relocation error`[](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error "Permalink") + +当运行 Dependency Scanning 作业的 Docker 版本为`19.03.00`时,会发生此错误. 考虑更新到 Docker `19.03.1`或更高版本. 旧版本不受影响. 阅读[本期的](https://gitlab.com/gitlab-org/gitlab/-/issues/13830#note_211354992 "当前的 SAST 容器失败")更多内容. \ No newline at end of file diff --git a/_book/docs/053.md b/_book/docs/053.md new file mode 100644 index 0000000000000000000000000000000000000000..fc4e34c7e2fc3426ca8445f8fe42444707e02d2a --- /dev/null +++ b/_book/docs/053.md @@ -0,0 +1,49 @@ +# Dependency List + +> 原文:[https://docs.gitlab.com/ee/user/application_security/dependency_list/](https://docs.gitlab.com/ee/user/application_security/dependency_list/) + +* [Requirements](#requirements) +* [Viewing dependencies](#viewing-dependencies) + * [Vulnerabilities](#vulnerabilities) +* [Licenses](#licenses) +* [Downloading the Dependency List](#downloading-the-dependency-list) + +# Dependency List[](#dependency-list-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10075) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. + +"依赖关系"列表使您可以查看项目的依赖关系以及有关它们的关键详细信息,包括已知漏洞. 要查看它,请导航至项目侧栏中的" **安全性和合规性">"依赖项列表"** . 该信息有时被称为软件物料清单或 SBoM / BOM. + +## Requirements[](#requirements "Permalink") + +1. 必须为您的项目配置" [依赖项扫描](../dependency_scanning/index.html) CI"作业. +2. 您的项目至少使用 Gemnasium 支持的一种[语言和包管理器](../dependency_scanning/index.html#supported-languages-and-package-managers) . + +## Viewing dependencies[](#viewing-dependencies "Permalink") + +[![Dependency List](img/e4fa52f4d522392d049bf73b1bb065a5.png)](img/dependency_list_v12_10.png) + +依存关系显示以下信息: + +| Field | Description | +| --- | --- | +| Component | 依赖项的名称和版本 | +| Packager | 打包程序用于安装依赖项 | +| Location | 指向项目中特定于包装程序的锁定文件的链接,该文件声明了依赖性 | +| License | 链接到依赖项的软件许可证 | + +最初显示的依赖项是按其已知漏洞的严重性(如果有)进行排序的. 也可以按名称或安装它们的打包程序对它们进行排序. + +### Vulnerabilities[](#vulnerabilities "Permalink") + +如果依赖项具有已知漏洞,则可以通过单击依赖项名称旁边的箭头或指示存在多少已知漏洞的标志来查看它们. 对于每个漏洞,其严重性和描述将显示在其下方. + +## Licenses[](#licenses "Permalink") + +在 GitLab Ultimate 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/10536) . + +如果配置了" [许可证合规性](../../compliance/license_compliance/index.html) CI"作业,则[发现的许可证](../../compliance/license_compliance/index.html#supported-languages-and-package-managers)将显示在此页面上. + +## Downloading the Dependency List[](#downloading-the-dependency-list "Permalink") + +您可以通过单击下载按钮以`JSON`格式下载项目的依赖关系及其详细信息的完整列表. \ No newline at end of file diff --git a/_book/docs/054.md b/_book/docs/054.md new file mode 100644 index 0000000000000000000000000000000000000000..8c1123b479f7b99a402ff21fcfa7fccaa2dd5b68 --- /dev/null +++ b/_book/docs/054.md @@ -0,0 +1,437 @@ +# Static Application Security Testing (SAST) + +> 原文:[https://docs.gitlab.com/ee/user/application_security/sast/](https://docs.gitlab.com/ee/user/application_security/sast/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Requirements](#requirements) +* [Supported languages and frameworks](#supported-languages-and-frameworks) + * [Making SAST analyzers available to all GitLab tiers](#making-sast-analyzers-available-to-all-gitlab-tiers) + * [Summary of features per tier](#summary-of-features-per-tier) +* [Contribute your scanner](#contribute-your-scanner) +* [Configuration](#configuration) + * [Customizing the SAST settings](#customizing-the-sast-settings) + * [Overriding SAST jobs](#overriding-sast-jobs) + * [Using environment variables to pass credentials for private repositories](#using-environment-variables-to-pass-credentials-for-private-repositories) + * [Using a variable to pass username and password to a private Maven repository](#using-a-variable-to-pass-username-and-password-to-a-private-maven-repository) + * [Enabling Docker-in-Docker](#enabling-docker-in-docker) + * [Enabling Kubesec analyzer](#enabling-kubesec-analyzer) + * [Pre-compilation](#pre-compilation) + * [Available variables](#available-variables) + * [Logging Level](#logging-level) + * [Custom Certificate Authority](#custom-certificate-authority) + * [Docker images](#docker-images) + * [Vulnerability filters](#vulnerability-filters) + * [Docker-in-Docker orchestrator](#docker-in-docker-orchestrator) + * [Analyzer settings](#analyzer-settings) + * [Custom environment variables](#custom-environment-variables) +* [Reports JSON format](#reports-json-format) +* [Secret detection](#secret-detection) +* [Security Dashboard](#security-dashboard) +* [Interacting with the vulnerabilities](#interacting-with-the-vulnerabilities) +* [Vulnerabilities database](#vulnerabilities-database) + * [Vulnerabilities database update](#vulnerabilities-database-update) +* [Running SAST in an offline environment](#running-sast-in-an-offline-environment) + * [Requirements for offline SAST](#requirements-for-offline-sast) + * [Make GitLab SAST analyzer images available inside your Docker registry](#make-gitlab-sast-analyzer-images-available-inside-your-docker-registry) + * [Set SAST CI job variables to use local SAST analyzers](#set-sast-ci-job-variables-to-use-local-sast-analyzers) +* [Troubleshooting](#troubleshooting) + * [`Error response from daemon: error processing tar file: docker-tar: relocation error`](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) + +# Static Application Security Testing (SAST)[](#static-application-security-testing-sast-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3775) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.3. + +**注意:**白皮书["应用程序安全性发生](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)了[地震变化"](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)说明**了前 6 种攻击中有 4 种是基于应用程序的** . 下载它以了解如何保护您的组织. + +## Overview[](#overview "Permalink") + +如果您使用的是[GitLab CI / CD](../../../ci/README.html) ,则可以使用静态应用程序安全性测试(SAST)分析源代码中的已知漏洞. + +您可以通过执行以下任一操作来利用 SAST: + +* 在现有的`.gitlab-ci.yml`文件中[包括 SAST 模板](#configuration) . +* 隐式使用[Auto DevOps](../../../topics/autodevops/stages.html#auto-sast-ultimate)提供的[Auto](../../../topics/autodevops/index.html) [SAST](../../../topics/autodevops/stages.html#auto-sast-ultimate) . + +GitLab 检查 SAST 报告,比较发现的源分支和目标分支之间的漏洞,并在合并请求中显示信息. + +[![SAST Widget](img/5e9b34b344fc5f08d74d5156c419f471.png)](img/sast_v13_2.png) + +结果按漏洞的优先级排序: + +1. Critical +2. High +3. Medium +4. Low +5. Unknown +6. 其他一切 + +**注意:**管道包含多个作业,包括 SAST 和 DAST 扫描. 如果任何作业由于任何原因未能完成,则安全信息中心将不会显示 SAST 扫描仪输出. 例如,如果 SAST 作业完成但 DAST 作业失败,则安全性仪表板将不会显示 SAST 结果. 分析器将在失败时输出[退出代码](../../../development/integrations/secure.html#exit-code) . + +## Use cases[](#use-cases "Permalink") + +* 您的代码在类中具有潜在的危险属性,或者不安全的代码可能导致意外的代码执行. +* 您的应用程序容易受到跨站点脚本(XSS)攻击的攻击,这些攻击可用于未经授权访问会话数据. + +## Requirements[](#requirements "Permalink") + +要运行 SAST 工作,默认情况下,你需要 GitLab 亚军与[`docker`](https://docs.gitlab.com/runner/executors/docker.html)或[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html)执行. 如果您在 GitLab.com 上使用共享的 Runners,则默认启用该功能. + +从 GitLab 13.0 开始,仅当您已[为 SAST 启用 Docker-in-Docker 时,才](#enabling-docker-in-docker)需要 Docker 特权模式. + +**警告:**目前,我们的 SAST 作业需要 Linux 容器类型. Windows 容器尚不支持.**注意:**如果使用自己的 Runners,请确保安装的 Docker 版本**不是** `19.03.0` . 有关详细[信息](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) ,请参见[故障排除信息](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) . + +## Supported languages and frameworks[](#supported-languages-and-frameworks "Permalink") + +下表显示了支持的语言,程序包管理器和框架以及使用了哪些工具. + +| 语言(包管理器)/框架 | 扫描工具 | 在 GitLab 版本中引入 | +| --- | --- | --- | +| .NET Core | [Security Code Scan](https://security-code-scan.github.io) | 11.0 | +| .NET Framework | [Security Code Scan](https://security-code-scan.github.io) | 13.0 | +| Any | [Gitleaks](https://github.com/zricethezav/gitleaks) and [TruffleHog](https://github.com/dxa4481/truffleHog) | 11.9 | +| Apex(Salesforce) | [PMD](https://pmd.github.io/pmd/index.html) | 12.1 | +| C/C++ | [Flawfinder](https://github.com/david-a-wheeler/flawfinder) | 10.7 | +| 长生不老药(凤凰城) | [Sobelow](https://github.com/nccgroup/sobelow) | 11.10 | +| Go | [Gosec](https://github.com/securego/gosec) | 10.7 | +| Groovy( [Ant](https://ant.apache.org/) , [Gradle](https://s0gradle0org.icopy.site/) , [Maven](https://maven.apache.org/)和[SBT](https://www.scala-sbt.org/) ) | 带有[find-sec-bugs](https://find-sec-bugs.github.io/)插件的[SpotBugs](https://spotbugs.github.io/) | 11.3(Gradle)和 11.9(Ant,Maven,SBT) | +| 头盔图 | [Kubesec](https://github.com/controlplaneio/kubesec) | 13.1 | +| Java( [Ant](https://ant.apache.org/) , [Gradle](https://s0gradle0org.icopy.site/) , [Maven](https://maven.apache.org/)和[SBT](https://www.scala-sbt.org/) ) | 带有[find-sec-bugs](https://find-sec-bugs.github.io/)插件的[SpotBugs](https://spotbugs.github.io/) | 10.6(Maven),10.8(Grade)和 11.9(Ant,SBT) | +| JavaScript | [ESLint security plugin](https://github.com/nodesecurity/eslint-plugin-security) | 11.8,在 13.2 中移至[GitLab Core](https://about.gitlab.com/pricing/) | +| 州长宣言 | [Kubesec](https://github.com/controlplaneio/kubesec) | 12.6 | +| Node.js | [NodeJsScan](https://github.com/ajinabraham/NodeJsScan) | 11.1 | +| PHP | [phpcs-security-audit](https://github.com/FloeDesignTechnologies/phpcs-security-audit) | 10.8 | +| Python( [点子](https://pip.pypa.io/en/stable/) ) | [bandit](https://github.com/PyCQA/bandit) | 10.3 | +| React | [ESLint react plugin](https://github.com/yannickcr/eslint-plugin-react) | 12.5 | +| Ruby on Rails | [brakeman](https://brakemanscanner.org) | 10.3,于 13.1 中移至[GitLab Core](https://about.gitlab.com/pricing/) | +| Scala( [Ant](https://ant.apache.org/) , [Gradle](https://s0gradle0org.icopy.site/) , [Maven](https://maven.apache.org/)和[SBT](https://www.scala-sbt.org/) ) | 带有[find-sec-bugs](https://find-sec-bugs.github.io/)插件的[SpotBugs](https://spotbugs.github.io/) | 11.0(SBT)和 11.9(Ant,Gradle,Maven) | +| TypeScript | [ESLint security plugin](https://github.com/nodesecurity/eslint-plugin-security) | 11.9,在 13.2 中与 ESLint 合并 | + +**注意:** Java 分析器还可以用于[Gradle 包装器](https://s0docs0gradle0org.icopy.site/current/userguide/gradle_wrapper.html) , [Grails](https://grails.org/)和[Maven 包装器](https://github.com/takari/maven-wrapper)等变体. + +### Making SAST analyzers available to all GitLab tiers[](#making-sast-analyzers-available-to-all-gitlab-tiers "Permalink") + +所有开放源代码(OSS)分析器都正在接受审核,并有可能移至 GitLab 核心层. 可以在相应的[史诗中](https://gitlab.com/groups/gitlab-org/-/epics/2098)跟踪进度. + +请注意,对[Docker-in-Docker 的](#enabling-docker-in-docker)支持不会扩展到 GitLab 核心层. + +#### Summary of features per tier[](#summary-of-features-per-tier "Permalink") + +下表列出了在不同的[GitLab 层](https://about.gitlab.com/pricing/)中可用的不同功能: + +| Capability | 在核心 | 终极 | +| --- | --- | --- | +| [Configure SAST Scanners](#configuration) | | | +| [Customize SAST Settings](#customizing-the-sast-settings) | | | +| View [JSON Report](#reports-json-format) | | | +| [Presentation of JSON Report in Merge Request](#overview) | | | +| [Interaction with Vulnerabilities](#interacting-with-the-vulnerabilities) | | | +| [Access to Security Dashboard](#security-dashboard) | | | + +## Contribute your scanner[](#contribute-your-scanner "Permalink") + +[安全扫描程序集成](../../../development/integrations/secure.html)文档说明了如何将其他安全扫描[程序集成](../../../development/integrations/secure.html)到 GitLab 中. + +## Configuration[](#configuration "Permalink") + +**注意:**如果您使用的是[Auto DevOps](../../../topics/autodevops/index.html)提供的[Auto](../../../topics/autodevops/index.html) [SAST,则不必](../../../topics/autodevops/stages.html#auto-sast-ultimate)按照本节中的说明手动配置 SAST. + +对于 GitLab 11.9 和更高版本,要启用 SAST,您必须[包括](../../../ci/yaml/README.html#includetemplate)作为 GitLab 安装的一部分提供的[`SAST.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml) . 对于 11.9 之前的 GitLab 版本,您可以复制和使用该模板中定义的作业. + +将以下内容添加到您的`.gitlab-ci.yml`文件中: + +``` +include: + - template: SAST.gitlab-ci.yml +``` + +随附的模板将在 CI / CD 管道中创建 SAST 作业,并扫描项目的源代码以查找可能的漏洞. + +结果将保存为[SAST 报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportssast-ultimate) ,您可以稍后下载和分析. 由于实施限制,我们始终采用最新的 SAST 工件. + +### Customizing the SAST settings[](#customizing-the-sast-settings "Permalink") + +可以使用`.gitlab-ci.yml`的[`variables`](../../../ci/yaml/README.html#variables)参数通过[环境变量](#available-variables)更改 SAST 设置. 在下面的示例中,我们包括 SAST 模板,同时将`SAST_GOSEC_LEVEL`变量设置为`2` : + +``` +include: + - template: SAST.gitlab-ci.yml + +variables: + SAST_GOSEC_LEVEL: 2 +``` + +因为模板是[在](../../../ci/yaml/README.html#include)管道配置[之前进行评估](../../../ci/yaml/README.html#include)的,所以最后提到的变量优先. + +### Overriding SAST jobs[](#overriding-sast-jobs "Permalink") + +**弃用:**从 GitLab 13.0 开始,不再支持[`only`和`except`](../../../ci/yaml/README.html#onlyexcept-basic)的使用. 覆盖模板时,必须使用[`rules`](../../../ci/yaml/README.html#rules) . + +要覆盖作业定义(例如,更改`variables`或`dependencies`类的属性),请声明与要覆盖的 SAST 作业同名的作业. 将此新作业放置在包含模板之后,并在其下指定其他任何键. 例如,这使得能够`FAIL_NEVER`为`spotbugs`分析器: + +``` +include: + - template: SAST.gitlab-ci.yml + +spotbugs-sast: + variables: + FAIL_NEVER: 1 +``` + +### Using environment variables to pass credentials for private repositories[](#using-environment-variables-to-pass-credentials-for-private-repositories "Permalink") + +一些分析器需要下载项目的依赖项才能执行分析. 反过来,此类依赖项可能存在于私有 Git 存储库中,因此需要诸如用户名和密码之类的凭据才能下载它们. 根据分析器的不同,可以通过[自定义环境变量](#custom-environment-variables)向其提供此类凭据. + +#### Using a variable to pass username and password to a private Maven repository[](#using-a-variable-to-pass-username-and-password-to-a-private-maven-repository "Permalink") + +如果您的私有 Maven 存储库需要登录凭据,则可以使用`MAVEN_CLI_OPTS`环境变量. + +阅读有关[如何使用私有 Maven 存储库的](../index.html#using-private-maven-repos)更多[信息](../index.html#using-private-maven-repos) . + +### Enabling Docker-in-Docker[](#enabling-docker-in-docker "Permalink") + +如果需要,您可以启用 Docker-in-Docker 来还原 GitLab 13.0 之前存在的 SAST 行为. 请按照以下步骤操作: + +1. 在[特权模式下](https://docs.gitlab.com/runner/executors/docker.html)使用 Docker-inDocker 配置 GitLab Runner. +2. 将变量`SAST_DISABLE_DIND`设置为`false` : + + ``` + include: + - template: SAST.gitlab-ci.yml + + variables: + SAST_DISABLE_DIND: "false" + ``` + +这将创建一个单一的`sast`在你的 CI / CD 管道,而不是多个作业`-sast`工作. + +#### Enabling Kubesec analyzer[](#enabling-kubesec-analyzer "Permalink") + +在 GitLab Ultimate 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12752) . + +您需要将`SCAN_KUBERNETES_MANIFESTS`设置为`"true"`才能启用 Kubesec 分析器. 在`.gitlab-ci.yml` ,定义: + +``` +include: + - template: SAST.gitlab-ci.yml + +variables: + SCAN_KUBERNETES_MANIFESTS: "true" +``` + +#### Pre-compilation[](#pre-compilation "Permalink") + +如果您的项目需要自定义构建配置,则最好避免在 SAST 执行期间进行编译,而应将管道中较早阶段的所有作业工件传递出去. 当需要执行`before_script`来准备扫描作业时,这是当前的策略. + +要将项目的依赖项作为工件传递,这些依赖项必须包含在项目的工作目录中,并使用`artifacts:path`配置进行指定. 如果存在所有依赖项,则可以将`COMPILE=false`变量提供给分析器,并且将跳过编译: + +``` +image: maven:3.6-jdk-8-alpine + +stages: + - build + - test + +include: + - template: SAST.gitlab-ci.yml + +build: + stage: build + script: + - mvn package -Dmaven.repo.local=./.m2/repository + artifacts: + paths: + - .m2/ + - target/ + +spotbugs-sast: + dependencies: + - build + variables: + MAVEN_REPO_PATH: ./.m2/repository + COMPILE: false + artifacts: + reports: + sast: gl-sast-report.json +``` + +**注意:**必须显式指定供应商目录的路径,以允许分析器识别已编译的工件. 每个分析器的配置可能有所不同,但在上述 Java 的情况下,可以使用`MAVEN_REPO_PATH` . 有关可用选项的完整列表,请参见[分析器设置](#analyzer-settings) . + +### Available variables[](#available-variables "Permalink") + +可以使用环境变量[配置](#customizing-the-sast-settings) SAST. + +#### Logging Level[](#logging-level "Permalink") + +您可以通过设置`SECURE_LOG_LEVEL` env var 来控制日志的详细程度. 默认设置为`info` ,您可以将其设置为以下任意级别: + +* `fatal` +* `error` +* `warn` +* `info` +* `debug` + +#### Custom Certificate Authority[](#custom-certificate-authority "Permalink") + +要信任自定义证书颁发机构,请将`ADDITIONAL_CA_CERT_BUNDLE`变量设置为要在 SAST 环境中信任的 CA 证书包. + +#### Docker images[](#docker-images "Permalink") + +以下是与 Docker 映像相关的变量. + +| Environment variable | Description | +| --- | --- | +| `SECURE_ANALYZERS_PREFIX` | 覆盖提供默认映像(代理)的 Docker 注册表名称. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `SAST_ANALYZER_IMAGE_TAG` | **已弃用:**覆盖默认映像的 Docker 标签. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `SAST_DEFAULT_ANALYZERS` | 覆盖默认图像的名称. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `SAST_DISABLE_DIND` | 禁用 Docker-in-Docker 并[单独](#enabling-docker-in-docker)运行分析器. 默认情况下,此变量为`true` . | + +#### Vulnerability filters[](#vulnerability-filters "Permalink") + +一些分析器可以过滤掉给定阈值以下的漏洞. + +| 环境变量 | 默认值 | Description | +| --- | --- | --- | +| `SAST_EXCLUDED_PATHS` | `spec, test, tests, tmp` | 根据路径从输出中排除漏洞. 这是逗号分隔的模式列表. 模式可以是全局变量,也可以是文件或文件夹路径(例如`doc,spec` ). 父目录也将匹配模式. | +| `SAST_BANDIT_EXCLUDED_PATHS` |   | 逗号分隔的路径列表,可从扫描中排除. 使用 Python 的[`fnmatch`语法](https://s0docs0python0org.icopy.site/2/library/fnmatch.html) ; 例如: `'*/tests/*, */venv/*'` | +| `SAST_BRAKEMAN_LEVEL` | 1 | 在给定的置信度下忽略 Brakeman 漏洞. 整数,1 =低 3 =高. | +| `SAST_DISABLE_BABEL` | `false` | 禁用 NodeJsScan 扫描仪的 Babel 处理. 设置为`true`将禁用 Babel 处理. 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33065) . | +| `SAST_FLAWFINDER_LEVEL` | 1 | 在给定风险级别下忽略 Flawfinder 漏洞. 整数,0 =无风险,5 =高风险. | +| `SAST_GITLEAKS_ENTROPY_LEVEL` | 8.0 | 秘密检测的最小熵. 浮动,0.0 =低,8.0 =高. | +| `SAST_GOSEC_LEVEL` | 0 | 在给定的置信度下忽略 Gosec 漏洞. 整数,0 =未定义,1 =低,2 =中,3 =高. | +| `SAST_GITLEAKS_COMMIT_FROM` |   | 提交 Gitleaks 扫描始于. | +| `SAST_GITLEAKS_COMMIT_TO` |   | Gitleaks 扫描的提交结束于. | +| `SAST_GITLEAKS_HISTORIC_SCAN` | `false` | 标记以启用历史性的 Gitleaks 扫描. | + +#### Docker-in-Docker orchestrator[](#docker-in-docker-orchestrator "Permalink") + +以下变量配置 Docker-in-Docker 协调器,因此仅在[启用](#enabling-docker-in-docker) Docker-in-Docker 模式时才使用. + +| 环境变量 | 默认值 | Description | +| --- | --- | --- | +| `SAST_ANALYZER_IMAGES` |   | 以逗号分隔的自定义图像列表. 默认图像仍处于启用状态. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `SAST_PULL_ANALYZER_IMAGES` | 1 | 从 Docker 注册表中提取映像(设置为 0 以禁用). 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `SAST_DOCKER_CLIENT_NEGOTIATION_TIMEOUT` | 2m | Docker 客户端协商的时间限制. 使用 Go 的[`ParseDuration`](https://s0golang0org.icopy.site/pkg/time/)解析超时. 有效时间单位为`ns` , `us` (或`µs` ), `ms` , `s` , `m` , `h` . 例如`300ms` , `1.5h`或`2h45m` . | +| `SAST_PULL_ANALYZER_IMAGE_TIMEOUT` | 5m | Time limit when pulling the image of an analyzer. Timeouts are parsed using Go’s [`ParseDuration`](https://s0golang0org.icopy.site/pkg/time/). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. For example, `300ms`, `1.5h` or `2h45m`. | +| `SAST_RUN_ANALYZER_TIMEOUT` | 20m | 运行分析仪的时间限制. 使用 Go 的[`ParseDuration`](https://s0golang0org.icopy.site/pkg/time/)解析超时. 有效时间单位为`ns` , `us` (或`µs` ), `ms` , `s` , `m` , `h` . 例如`300ms` , `1.5h`或`2h45m` . | + +#### Analyzer settings[](#analyzer-settings "Permalink") + +某些分析仪可以使用环境变量进行自定义. + +| Environment variable | Analyzer | Description | +| --- | --- | --- | +| `SCAN_KUBERNETES_MANIFESTS` | Kubesec | 设置为`"true"`以扫描 Kubernetes 清单. | +| `KUBESEC_HELM_CHARTS_PATH` | Kubesec | `helm`将用于生成`kubesec`将扫描的 Kubernetes 清单的舵图的可选路径. 如果定义了`helm dependency build`则应在`before_script`运行`helm dependency build`以获取必要的依赖关系. | +| `KUBESEC_HELM_OPTIONS` | Kubesec | `helm`可执行文件的其他参数. | +| `COMPILE` | SpotBugs | 设置为`false`可禁用项目编译和依赖项获取. 在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/195252) . | +| `ANT_HOME` | SpotBugs | `ANT_HOME`环境变量. | +| `ANT_PATH` | SpotBugs | `ant`可执行文件的路径. | +| `GRADLE_PATH` | SpotBugs | `gradle`可执行文件的路径. | +| `JAVA_OPTS` | SpotBugs | `java`可执行文件的附加参数. | +| `JAVA_PATH` | SpotBugs | `java`可执行文件的路径. | +| `SAST_JAVA_VERSION` | SpotBugs | 使用哪个 Java 版本. 支持的版本是`8`和`11` . 默认为`8` . | +| `MAVEN_CLI_OPTS` | SpotBugs | `mvn`或`mvnw`可执行文件的其他参数. | +| `MAVEN_PATH` | SpotBugs | `mvn`可执行文件的路径. | +| `MAVEN_REPO_PATH` | SpotBugs | Maven 本地存储库的路径( `maven.repo.local`属性的快捷方式). | +| `SBT_PATH` | SpotBugs | `sbt`可执行文件的路径. | +| `FAIL_NEVER` | SpotBugs | 设置为`1`可忽略编译失败. | +| `SAST_GOSEC_CONFIG` | Gosec | Gosec 的配置路径(可选). | +| `PHPCS_SECURITY_AUDIT_PHP_EXTENSIONS` | phpcs-security-audit | 以逗号分隔的其他 PHP 扩展列表. | +| `SEARCH_MAX_DEPTH` | any | 搜索源代码文件时遍历的最大目录数. 默认值: `4` . | + +#### Custom environment variables[](#custom-environment-variables "Permalink") + +在 GitLab Ultimate 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18193) . + +除上述 SAST 配置变量外,如果[使用 SAST 供应商模板](#configuration) ,则所有[自定义环境变量](../../../ci/variables/README.html#custom-environment-variables)都将传播到基础 SAST 分析器映像. + +**警告:**名称以这些前缀开头的变量将**不会**传播到 SAST Docker 容器和/或分析器容器: `DOCKER_` , `CI` , `GITLAB_` , `FF_` , `HOME` , `PWD` , `OLDPWD` , `PATH` , `SHLVL` , `HOSTNAME` . + +## Reports JSON format[](#reports-json-format "Permalink") + +SAST 工具会发出 JSON 报告文件. 有关更多信息,请参见此[报告](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/sast-report-format.json)的[架构](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/sast-report-format.json) . + +这是一个示例 SAST 报告: + +``` +{ "version": "2.0", "vulnerabilities": [ { "id": "9e96e0ab-23da-4d7d-a09e-0acbaa5e83ca", "category": "sast", "name": "Predictable pseudorandom number generator", "message": "Predictable pseudorandom number generator", "description": "The use of java.util.Random is predictable", "severity": "Medium", "confidence": "Medium", "scanner": { "id": "find_sec_bugs", "name": "Find Security Bugs" }, "location": { "file": "groovy/src/main/groovy/com/gitlab/security_products/tests/App.groovy", "start_line": 47, "end_line": 47, "class": "com.gitlab.security_products.tests.App", "method": "generateSecretToken2", "dependency": { "package": {} } }, "identifiers": [ { "type": "find_sec_bugs_type", "name": "Find Security Bugs-PREDICTABLE_RANDOM", "value": "PREDICTABLE_RANDOM", "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM" }, { "type": "cwe", "name": "CWE-330", "value": "330", "url": "https://cwe.mitre.org/data/definitions/330.html" } ] }, { "id": "e6dbf91f-4c07-46f7-a365-0169489c27d1", "category": "sast", "message": "Probable insecure usage of temp file/directory.", "severity": "Medium", "confidence": "Medium", "scanner": { "id": "bandit", "name": "Bandit" }, "location": { "file": "python/hardcoded/hardcoded-tmp.py", "start_line": 10, "end_line": 10, "dependency": { "package": {} } }, "identifiers": [ { "type": "bandit_test_id", "name": "Bandit Test ID B108", "value": "B108", "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html" } ] }, ], "remediations": [] } +``` + +## Secret detection[](#secret-detection "Permalink") + +了解有关[秘密检测的](../secret_detection)更多信息. + +## Security Dashboard[](#security-dashboard "Permalink") + +在"安全仪表板"中,您可以概览您的组,项目和管道中的所有安全漏洞. 阅读有关[安全仪表板的](../security_dashboard/index.html)更多[信息](../security_dashboard/index.html) . + +## Interacting with the vulnerabilities[](#interacting-with-the-vulnerabilities "Permalink") + +一旦发现漏洞,便可以与其进行交互. 阅读有关如何[与漏洞](../index.html#interacting-with-the-vulnerabilities)进行[交互的](../index.html#interacting-with-the-vulnerabilities)更多信息. + +## Vulnerabilities database[](#vulnerabilities-database "Permalink") + +Vulnerabilities contained within the vulnerability database can be searched and viewed at the [GitLab vulnerability advisory database](https://advisories.gitlab.com). + +### Vulnerabilities database update[](#vulnerabilities-database-update "Permalink") + +有关漏洞数据库更新的更多信息,请查看[维护表](../index.html#maintenance-and-update-of-the-vulnerabilities-database) . + +## Running SAST in an offline environment[](#running-sast-in-an-offline-environment "Permalink") + +对于在通过 Internet 限制,限制或间歇性访问外部资源的环境中进行自我管理的 GitLab 实例,需要进行一些调整才能使 SAST 作业成功运行. 有关更多信息,请参阅[脱机环境](../offline_deployments/index.html) . + +### Requirements for offline SAST[](#requirements-for-offline-sast "Permalink") + +要在离线环境中使用 SAST,您需要: + +* 保持 Docker-In-Docker 禁用(默认). +* GitLab 亚军与[`docker`或`kubernetes`执行](#requirements) . +* Docker Container Registry,带有本地可用的 SAST [分析器](https://gitlab.com/gitlab-org/security-products/analyzers)映像副本. + +**注意:** GitLab Runner 的[默认`pull policy`为`always`](https://docs.gitlab.com/runner/executors/docker.html) ,这意味着即使本地副本可用,Runner 也会尝试从 GitLab 容器注册表中拉取 Docker 映像. 如果您只喜欢使用本地可用的 Docker 映像,则可以在离线环境[`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html) GitLab Runner 的[`pull_policy`设置为`if-not-present`](https://docs.gitlab.com/runner/executors/docker.html) . 但是,如果不在离线环境中,我们建议将拉取策略设置保持为`always` ,因为这样可以在 CI / CD 管道中使用更新的扫描仪. + +### Make GitLab SAST analyzer images available inside your Docker registry[](#make-gitlab-sast-analyzer-images-available-inside-your-docker-registry "Permalink") + +对于具有所有[受支持的语言和框架的](#supported-languages-and-frameworks) SAST,请将以下默认 SAST 分析器图像从`registry.gitlab.com`导入[本地 Docker 容器注册表](../../packages/container_registry/index.html) : + +``` +registry.gitlab.com/gitlab-org/security-products/analyzers/bandit:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/brakeman:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/eslint:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/flawfinder:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/gosec:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/kubesec:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/nodejs-scan:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/pmd-apex:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/secrets:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/security-code-scan:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/sobelow:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/spotbugs:2 +``` + +将 Docker 映像导入本地脱机 Docker 注册表的过程取决于**您的网络安全策略** . 请咨询您的 IT 员工,以找到可以导入或临时访问外部资源的已接受和批准的流程. 请注意,这些扫描程序会[定期](../index.html#maintenance-and-update-of-the-vulnerabilities-database)使用新定义进行[更新](../index.html#maintenance-and-update-of-the-vulnerabilities-database) ,因此请考虑您是否能够自己进行定期更新. + +有关将 Docker 映像保存和传输为文件的详细信息,请参阅 Docker 有关[`docker save`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/save/) , [`docker load`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/load/) , [`docker export`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/export/)和[`docker import`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/import/)的文档. + +### Set SAST CI job variables to use local SAST analyzers[](#set-sast-ci-job-variables-to-use-local-sast-analyzers "Permalink") + +将以下配置添加到您的`.gitlab-ci.yml`文件. 您必须替换`SECURE_ANALYZERS_PREFIX`才能引用本地 Docker 容器注册表: + +``` +include: + - template: SAST.gitlab-ci.yml + +variables: + SECURE_ANALYZERS_PREFIX: "localhost:5000/analyzers" +``` + +现在,SAST 作业应使用 SAST 分析器的本地副本来扫描您的代码并生成安全报告,而无需访问 Internet. + +## Troubleshooting[](#troubleshooting "Permalink") + +### `Error response from daemon: error processing tar file: docker-tar: relocation error`[](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error "Permalink") + +当运行 SAST 作业的码头工人的版本是出现此错误`19.03.0` . 考虑更新到 Docker `19.03.1`或更高版本. 旧版本不受影响. 阅读[本期的](https://gitlab.com/gitlab-org/gitlab/-/issues/13830#note_211354992 "当前的 SAST 容器失败")更多内容. \ No newline at end of file diff --git a/_book/docs/055.md b/_book/docs/055.md new file mode 100644 index 0000000000000000000000000000000000000000..5ea01fbd0812b161c686ba62e853c9c82b6fe34f --- /dev/null +++ b/_book/docs/055.md @@ -0,0 +1,128 @@ +# Secret Detection + +> 原文:[https://docs.gitlab.com/ee/user/application_security/secret_detection/](https://docs.gitlab.com/ee/user/application_security/secret_detection/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Requirements](#requirements) +* [Configuration](#configuration) + * [Using the SAST Template](#using-the-sast-template) + * [Customizing settings](#customizing-settings) + * [Available variables](#available-variables) + * [Logging Level](#logging-level) +* [Full History Secret Scan](#full-history-secret-scan) + +# Secret Detection[](#secret-detection-ultimate "Permalink") + +[Introduced](https://about.gitlab.com/releases/2019/03/22/gitlab-11-9-released/#detect-secrets-and-credentials-in-the-repository) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9. + +## Overview[](#overview "Permalink") + +开发应用程序时经常出现的问题是,开发人员可能会无意间将秘密和凭据提交到其远程存储库. 如果其他人可以访问源,或者项目是公开的,则敏感信息将被公开,恶意用户可以利用这些信息来访问诸如部署环境之类的资源. + +GitLab 11.9 包含一个称为"秘密检测"的新检查. 它扫描存储库的内容以查找 API 密钥和其他不应存在的信息. + +manbetx 客户端打不开显示识别的秘密作为 SAST 报告的一部分在几个地方: + +* [Security Dashboard](../security_dashboard/) +* Pipelines’ **Security** tab +* 合并请求小部件中的报告 + +[![Secret Detection in merge request widget](img/56321b27a391110651e26fae3d93064e.png)](img/secret_detection_v13_2.png) + +## Use cases[](#use-cases "Permalink") + +* 检测密钥,密码和 API 令牌等机密信息的意外提交. +* 对存储库的完整历史记录执行一次或重复扫描以查找机密信息. + +## Requirements[](#requirements "Permalink") + +要运行检测的秘密工作,默认情况下,你需要 GitLab 亚军与[`docker`](https://docs.gitlab.com/runner/executors/docker.html)或[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html)执行. 如果您在 GitLab.com 上使用共享的 Runners,则默认启用该功能. + +**注意:**目前我们的秘密检测作业需要 Linux 容器类型. Windows 容器尚不支持.**注意:**如果使用自己的 Runners,请确保安装的 Docker 版本**不是** `19.03.0` . 有关详细[信息](../sast#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) ,请参见[故障排除信息](../sast#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) . + +## Configuration[](#configuration "Permalink") + +**注意:**在 GitLab 13.1 中,秘密检测被拆分为自己的 CI / CD 模板. + +秘密检测是在`secret-detection`作业期间由[特定的分析器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml)执行的. 无论您的应用程序使用哪种编程语言,它都可以运行. + +秘密检测分析器包括[Gitleaks](https://github.com/zricethezav/gitleaks)和[TruffleHog](https://github.com/dxa4481/truffleHog)检查. + +***Note:** The Secret Detection analyzer will ignore "Password in URL" vulnerabilities if the password begins with a dollar sign ( `$` ) as this likely indicates the password being used is an environment variable. **注意:**如果密码以美元符号( `$` )开头,则秘密检测分析器将忽略" URL 中的密码"漏洞,因为这很可能表明所使用的密码是环境变量. For example, `https://username:$password@example.com/path/to/repo` won't be detected, whereas `https://username:password@example.com/path/to/repo` would be detected. 例如,将不会检测到`https://username:$password@example.com/path/to/repo` ,而将检测到`https://username:password@example.com/path/to/repo` .***注意:**如果您使用的是[Auto DevOps](../../../topics/autodevops/index.html)提供的[自动](../../../topics/autodevops/index.html) [秘密检测,](../../../topics/autodevops/stages.html#auto-secret-detection-ultimate)则不必按照本节中的说明手动配置秘密检测. + +要为 GitLab 13.1 和更高版本启用 Secret Detection,您必须包括`Secret-Detection.gitlab-ci.yml`模板,该模板作为 GitLab 安装的一部分提供. 对于 11.9 之前的 GitLab 版本,您可以复制和使用该模板中定义的作业. + +将以下内容添加到您的`.gitlab-ci.yml`文件中: + +``` +include: + - template: Secret-Detection.gitlab-ci.yml +``` + +包含的模板在 CI / CD 管道中创建"秘密检测"作业,并扫描项目的源代码中的秘密. + +结果将保存为" [秘密检测"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportssecret_detection-ultimate) ,您以后可以下载和分析该[工件](../../../ci/pipelines/job_artifacts.html#artifactsreportssecret_detection-ultimate) . 由于实施限制,我们始终采用最新的秘密检测工件. + +### Using the SAST Template[](#using-the-sast-template "Permalink") + +在 GitLab 13.1 之前,秘密检测是[SAST 配置的](../sast#configuration)一部分. 如果您已经在 GitLab 13.1 之前为您的应用配置了启用 SAST,则无需手动配置它. + +**计划的弃用:**在以后的 GitLab 版本中,将不建议使用 SAST 模板配置秘密检测. 请开始使用`Secret-Detection.gitlab-ci.yml`以防止将来出现问题. 我们制作了一个[视频,指导您完成过渡](https://www.youtube.com/watch?v=W2tjcQreDwQ)到此新模板的过程.观看视频: [历史秘密扫描演练](https://www.youtube.com/watch?v=W2tjcQreDwQ) . + +
    + +使用 SAST 模板时,秘密检测由[特定分析器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml#L180)在`sast`作业期间执行. 它的运行与应用程序的编程语言无关,并且您无需更改 CI / CD 配置文件即可启用它. 结果可在 SAST 报告中获得. + +### Customizing settings[](#customizing-settings "Permalink") + +可以使用`.gitlab-ci.yml`的[`variables`](../../../ci/yaml/README.html#variables)参数通过[环境变量](#available-variables)更改秘密检测扫描设置. + +要覆盖作业定义(例如,更改`variables`或`dependencies`类的属性),请声明与要覆盖的 SAST 作业同名的作业. 将此新作业放置在包含模板之后,并在其下指定其他任何键. + +在下面的示例中,我们包括"秘密检测"模板,同时使用`SECRET_DETECTION_HISTORIC_SCAN`变量将`secret_detection`作业覆盖为`true` : + +``` +include: + - template: Secret-Detection.gitlab-ci.yml + +secret_detection: + variables: + SECRET_DETECTION_HISTORIC_SCAN: "true" +``` + +因为模板是[在](../../../ci/yaml/README.html#include)管道配置[之前进行评估](../../../ci/yaml/README.html#include)的,所以最后提到的变量优先. + +**弃用:**从 GitLab 13.0 开始,不再支持[`only`和`except`](../../../ci/yaml/README.html#onlyexcept-basic)的使用. 覆盖模板时,必须使用[`rules`](../../../ci/yaml/README.html#rules) . + +#### Available variables[](#available-variables "Permalink") + +可以通过定义可用变量来自定义秘密检测: + +| 环境变量 | 默认值 | Description | +| --- | --- | --- | +| `SECRET_DETECTION_COMMIT_FROM` | - | 提交 Gitleaks 扫描始于. | +| `SECRET_DETECTION_COMMIT_TO` | - | Gitleaks 扫描的提交结束于. | +| `SECRET_DETECTION_HISTORIC_SCAN` | false | 标记以启用历史性的 Gitleaks 扫描. | + +### Logging Level[](#logging-level "Permalink") + +您可以通过设置`SECURE_LOG_LEVEL` env var 来控制日志的详细程度. 默认设置为`info` ,您可以将其设置为以下任意级别: + +* `fatal` +* `error` +* `warn` +* `info` +* `debug` + +## Full History Secret Scan[](#full-history-secret-scan "Permalink") + +GitLab 12.11 引入了对扫描存储库完整历史记录的支持. 当您首次在存储库中启用秘密检测并且想要执行完整的秘密扫描时,此新功能特别有用. 对整个历史记录进行秘密扫描可能会花费很长时间,尤其是对于 Git 历史记录较长的大型存储库. 我们建议不要将此变量设置为常规作业定义的一部分. + +可以设置一个新的配置变量( [`SECRET_DETECTION_HISTORIC_SCAN`](../sast/#vulnerability-filters) )来更改 GitLab 秘密检测扫描的行为,使其在存储库的整个 Git 历史记录上运行. + +我们创建了一个[简短的视频演练,](https://youtu.be/wDtc_K00Y0A)展示了如何执行完整的历史秘密扫描. + +观看视频: [历史秘密扫描演练](https://www.youtube.com/watch?v=wDtc_K00Y0A) . + +
    \ No newline at end of file diff --git a/_book/docs/056.md b/_book/docs/056.md new file mode 100644 index 0000000000000000000000000000000000000000..3fb2e6ef22124f03b88408a143ea11bdfd8da58c --- /dev/null +++ b/_book/docs/056.md @@ -0,0 +1,642 @@ +# Dynamic Application Security Testing (DAST) + +> 原文:[https://docs.gitlab.com/ee/user/application_security/dast/](https://docs.gitlab.com/ee/user/application_security/dast/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Requirements](#requirements) +* [Configuration](#configuration) + * [When DAST scans run](#when-dast-scans-run) + * [Hide sensitive information](#hide-sensitive-information) + * [Authentication](#authentication) + * [Full scan](#full-scan) + * [Domain validation](#domain-validation) + * [Ruby on Rails](#ruby-on-rails) + * [Django](#django) + * [Node (with Express)](#node-with-express) + * [Domain validation header via a proxy](#domain-validation-header-via-a-proxy) + * [API scan](#api-scan) + * [Specification format](#specification-format) + * [Import API specification from a URL](#import-api-specification-from-a-url) + * [Import API specification from a file](#import-api-specification-from-a-file) + * [Full scan](#full-scan-1) + * [Host override](#host-override) + * [Authentication using headers](#authentication-using-headers) + * [Customizing the DAST settings](#customizing-the-dast-settings) + * [Available variables](#available-variables) + * [DAST command-line options](#dast-command-line-options) + * [Custom ZAProxy configuration](#custom-zaproxy-configuration) + * [Cloning the project’s repository](#cloning-the-projects-repository) + * [Debugging DAST jobs](#debugging-dast-jobs) +* [Running DAST in an offline environment](#running-dast-in-an-offline-environment) + * [Requirements for offline DAST support](#requirements-for-offline-dast-support) + * [Make GitLab DAST analyzer images available inside your Docker registry](#make-gitlab-dast-analyzer-images-available-inside-your-docker-registry) + * [Set DAST CI job variables to use local DAST analyzers](#set-dast-ci-job-variables-to-use-local-dast-analyzers) +* [On-Demand Scans](#on-demand-scans) + * [Enable or disable On-Demand Scans](#enable-or-disable-on-demand-scans) +* [Reports](#reports) + * [List of URLs scanned](#list-of-urls-scanned) + * [JSON](#json) + * [Other formats](#other-formats) +* [Security Dashboard](#security-dashboard) +* [Bleeding-edge vulnerability definitions](#bleeding-edge-vulnerability-definitions) +* [Interacting with the vulnerabilities](#interacting-with-the-vulnerabilities) +* [Vulnerabilities database update](#vulnerabilities-database-update) +* [Optimizing DAST](#optimizing-dast) +* [Troubleshooting](#troubleshooting) + * [Running out of memory](#running-out-of-memory) + +# Dynamic Application Security Testing (DAST)[](#dynamic-application-security-testing-dast-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4348) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4. + +**注意:**白皮书["应用程序安全性发生](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)了[地震变化"](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)说明**了前 6 种攻击中有 4 种是基于应用程序的** . 下载它以了解如何保护您的组织. + +对代码运行[静态检查](../sast/index.html)是检测可能使代码安全性受到威胁的漏洞的第一步. 但是,一旦部署,您的应用程序将面临一类新的可能的攻击,例如跨站点脚本或损坏的身份验证缺陷. 这是动态应用程序安全性测试(DAST)实施的地方. + +## Overview[](#overview "Permalink") + +如果您使用的是[GitLab CI / CD](../../../ci/README.html) ,则可以使用动态应用程序安全性测试(DAST)分析运行中的 Web 应用程序是否存在已知漏洞. 您可以通过在现有`.gitlab-ci.yml`文件中[包含 CI 作业](#configuration) ,或通过隐式使用[Auto DevOps](../../../topics/autodevops/index.html)提供的[Auto](../../../topics/autodevops/index.html) [DAST](../../../topics/autodevops/stages.html#auto-dast-ultimate)来利用[DAST](../../../topics/autodevops/stages.html#auto-dast-ultimate) . + +GitLab 检查 DAST 报告,比较发现的源分支和目标分支之间的漏洞,并显示有关合并请求的信息. + +**注意:**此比较逻辑仅使用针对目标分支的基本提交执行的最新管道. 在任何其他提交上运行管道对合并请求没有影响. + +[![DAST Widget](img/ae9e67c8841e45007cf186891963198f.png)](img/dast_v13_2.png) + +通过单击检测到的链接漏洞之一,您可以查看详细信息和受影响的 URL. + +[![DAST Widget Clicked](img/7a612dcc3c18a6e6433eb5a57a99368d.png)](img/dast_single_v13_0.png) + +[动态应用程序安全测试(DAST)](https://en.wikipedia.org/wiki/Dynamic_Application_Security_Testing)使用流行的开源工具[OWASP Zed Attack Proxy](https://www.zaproxy.org/)对运行中的 Web 应用程序执行分析. + +默认情况下,DAST 执行[ZAP 基准扫描](https://www.zaproxy.org/docs/docker/baseline-scan/)并仅执行被动扫描. 它不会主动攻击您的应用程序. 但是,可以将 DAST [配置](#full-scan)为还执行*主动扫描* :攻击您的应用程序并生成更广泛的安全报告. 与[Review Apps](../../../ci/review_apps/index.html)结合使用可能非常有用. + +**注意:**管道可能包含多个作业,包括 SAST 和 DAST 扫描. 如果任何作业由于任何原因未能完成,则安全信息中心将不会显示 DAST 扫描仪输出. 例如,如果 DAST 作业完成但 SAST 作业失败,则安全性仪表板将不会显示 DAST 结果. 分析器将在失败时输出[退出代码](../../../development/integrations/secure.html#exit-code) . + +## Use cases[](#use-cases "Permalink") + +它可以帮助您在开发和测试应用程序时自动查找正在运行的 Web 应用程序中的安全漏洞. + +## Requirements[](#requirements "Permalink") + +要运行 DAST 作业,您需要具有[`docker` executor 的](https://docs.gitlab.com/runner/executors/docker.html) GitLab Runner. + +## Configuration[](#configuration "Permalink") + +对于 GitLab 11.9 和更高版本,要启用 DAST,您必须[包含](../../../ci/yaml/README.html#includetemplate) [`DAST.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml) ,该[模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml)作为 GitLab 安装的一部分提供. 对于 11.9 之前的 GitLab 版本,您可以复制和使用该模板中定义的作业. + +将以下内容添加到您的`.gitlab-ci.yml`文件中: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_WEBSITE: https://example.com +``` + +有两种方法来定义要由 DAST 扫描的 URL: + +1. 设置`DAST_WEBSITE` [变量](../../../ci/yaml/README.html#variables) . + +2. 将其添加到项目根目录的`environment_url.txt`文件中. 这非常适合在动态环境中进行测试. 为了针对在 GitLab CI / CD 管道中动态创建的应用程序运行 DAST,请让该应用程序将其域保留在`environment_url.txt`文件中,然后 DAST 自动解析该文件以找到其扫描目标. 您可以在我们的 Auto DevOps CI YAML 中看到一个[示例](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml) . + +如果同时设置了两个值,则`DAST_WEBSITE`值优先. + +随附的模板会在 CI / CD 管道中创建`dast`工作,并扫描项目的源代码中可能存在的漏洞. + +结果将保存为[DAST 报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsdast-ultimate) ,您可以稍后下载和分析. 由于实施限制,我们始终采用最新的 DAST 工件. 在后台, [GitLab DAST Docker 映像](https://gitlab.com/gitlab-org/security-products/dast)用于在指定的 URL 上运行测试并扫描它是否存在漏洞. + +默认情况下,DAST 模板将使用 DAST Docker 映像的最新主版本. 使用`DAST_VERSION`变量,您可以选择 DAST 更新的方式: + +* 通过固定到主要版本(例如`1` )自动更新具有新功能和修复程序的 DAST. +* 仅通过固定到次要版本(例如`1.6` )来更新修补程序. +* 通过固定到特定版本(例如`1.6.4` )来防止所有更新. + +在" [发行"](https://gitlab.com/gitlab-org/security-products/dast/-/releases)页面上找到最新的 DAST 版本. + +### When DAST scans run[](#when-dast-scans-run "Permalink") + +使用`DAST.gitlab-ci.yml`模板时, `dast`作业最后运行,如下例所示. 为确保 DAST 正在扫描最新代码,您的 CI 管道应在`dast`作业之前的`dast`作业`dast`更改部署到 Web 服务器. + +``` +stages: + - build + - test + - deploy + - dast +``` + +请注意,如果您将管道配置为在每次运行中都部署到同一 Web 服务器,则在另一个管道仍在运行时运行管道可能会导致争用情况,其中一个管道会覆盖另一个管道的代码. 在 DAST 扫描期间,应从更改中排除要扫描的站点. 对该站点的唯一更改应来自 DAST 扫描仪. 请注意,在扫描过程中,用户,计划任务,数据库更改,代码更改,其他管道或其他扫描程序对站点所做的任何更改都可能导致结果不准确. + +### Hide sensitive information[](#hide-sensitive-information "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36332) . + +HTTP 请求和响应标头可能包含敏感信息,包括 cookie 和授权凭证. 默认情况下,以下标头被屏蔽: + +* `Authorization`. +* `Proxy-Authorization`. +* `Set-Cookie` (仅值). +* `Cookie` (values only). + +使用[`DAST_MASK_HTTP_HEADERS`变量](#available-variables) ,可以列出要屏蔽其值的标头. 有关如何屏蔽标题的详细信息,请参阅" [自定义 DAST 设置"](#customizing-the-dast-settings) . + +### Authentication[](#authentication "Permalink") + +在执行 DAST 检查之前,还可以对用户进行身份验证. + +创建掩码变量以传递 DAST 将使用的凭据. 要为用户名和密码创建掩码变量,请参阅[在 UI 中创建自定义变量](../../../ci/variables/README.html#create-a-custom-variable-in-the-ui) . 请注意,username 变量的密钥必须为`DAST_USERNAME` ,而 password 变量的密钥必须为`DAST_PASSWORD` . + +与认证扫描相关的其他变量是: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_WEBSITE: https://example.com + DAST_AUTH_URL: https://example.com/sign-in + DAST_USERNAME_FIELD: session[user] # the name of username field at the sign-in HTML form + DAST_PASSWORD_FIELD: session[password] # the name of password field at the sign-in HTML form + DAST_AUTH_EXCLUDE_URLS: http://example.com/sign-out,http://example.com/sign-out-2 # optional, URLs to skip during the authenticated scan; comma-separated, no spaces in between +``` + +结果将保存为[DAST 报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsdast-ultimate) ,您以后可以下载和分析. 由于实施限制,我们始终采用最新的 DAST 工件. + +**危险:** **切勿**对生产服务器运行经过身份验证的扫描. 运行经过身份验证的扫描时,它可以执行经过身份验证的用户可以执行的*任何*功能. 这包括修改和删除数据,提交表单以及跟随链接之类的操作. 仅对测试服务器运行经过身份验证的扫描. + +### Full scan[](#full-scan "Permalink") + +可以将 DAST 配置为执行[ZAP 全面扫描](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) ,其中包括针对同一目标网站的被动扫描和主动扫描: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_FULL_SCAN_ENABLED: "true" +``` + +#### Domain validation[](#domain-validation "Permalink") + +DAST 作业可以在任何地方运行,这意味着您可能会意外击中实时 Web 服务器并可能损坏它们. 您甚至可以减少生产环境. 因此,您应该使用域验证. + +默认情况下,不需要域验证. 通过将[环境变量](#available-variables) `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED`设置为`"true"`可能需要它. + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_FULL_SCAN_ENABLED: "true" + DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED: "true" +``` + +由于 ZAP 全面扫描会主动攻击目标应用程序,因此 DAST 会事先向目标(通常在`DAST_WEBSITE`或`environment_url.txt`定义)发送 ping 命令. + +* 如果`DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED`为`false`或未设置,则将继续进行扫描,除非对 ping 的响应包含值为`deny`的`Gitlab-DAST-Permission`标头. +* 如果`DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED`是`true` ,则扫描将退出除非对 ping 响应包括一个`Gitlab-DAST-Permission`用的头值`allow` . + +以下是在 Rails,Django 和 Node(使用 Express)中向响应添加`Gitlab-DAST-Permission`标头的一些示例. + +##### Ruby on Rails[](#ruby-on-rails "Permalink") + +这是[在 Ruby on Rails 中](https://guides.rubyonrails.org/action_controller_overview.html#setting-custom-headers)添加[自定义标头的方法](https://guides.rubyonrails.org/action_controller_overview.html#setting-custom-headers) : + +``` +class DastWebsiteTargetController < ActionController::Base + def dast_website_target + response.headers['Gitlab-DAST-Permission'] = 'allow' + + head :ok + end +end +``` + +##### Django[](#django "Permalink") + +Here’s how you would add a [custom header in Django](https://docs.djangoproject.com/en/2.2/ref/request-response/#setting-header-fields): + +``` +class DastWebsiteTargetView(View): + def head(self, *args, **kwargs): + response = HttpResponse() + response['Gitlab-Dast-Permission'] = 'allow' + + return response +``` + +##### Node (with Express)[](#node-with-express "Permalink") + +这是[在 Node(使用 Express)中](http://expressjs0com.icopy.site/en/5x/api.html)添加[自定义标头的方法](http://expressjs0com.icopy.site/en/5x/api.html) : + +``` +app.get('/dast-website-target', function(req, res) { + res.append('Gitlab-DAST-Permission', 'allow') + res.send('Respond to DAST ping') +}) +``` + +##### Domain validation header via a proxy[](#domain-validation-header-via-a-proxy "Permalink") + +也可以通过代理添加`Gitlab-DAST-Permission`标头. + +###### NGINX[](#nginx "Permalink") + +以下配置允许 NGINX 充当反向代理并添加`Gitlab-DAST-Permission` [标头](http://nginx0org.icopy.site/en/docs/http/ngx_http_headers_module.html) : + +``` +# default.conf +server { + listen 80; + server_name localhost; + + location / { + proxy_pass http://test-application; + add_header Gitlab-DAST-Permission allow; + } +} +``` + +###### Apache[](#apache "Permalink") + +Apache 还可以用作[反向代理,](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html)以添加`Gitlab-DAST-Permission` [标头](https://httpd.apache.org/docs/current/mod/mod_headers.html) . + +为此, `httpd.conf`添加到`httpd.conf` : + +``` +# httpd.conf +LoadModule proxy_module modules/mod_proxy.so +LoadModule proxy_connect_module modules/mod_proxy_connect.so +LoadModule proxy_http_module modules/mod_proxy_http.so + + + ProxyPass "/" "http://test-application.com/" + ProxyPassReverse "/" "http://test-application.com/" + Header set Gitlab-DAST-Permission "allow" + +``` + +[此代码段](https://gitlab.com/gitlab-org/security-products/dast/snippets/1894732)包含完整的`httpd.conf`文件,该文件配置为充当远程代理并添加`Gitlab-DAST-Permission`标头. + +### API scan[](#api-scan "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10928) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. + +使用 API​​规范作为扫描目标是一种为 URL 注入用于扫描 API 的有用方法. API 扫描中的漏洞规则与普通网站扫描中的漏洞规则不同. + +#### Specification format[](#specification-format "Permalink") + +API 扫描支持 OpenAPI V2 和 OpenAPI V3 规范. 您可以使用`JSON`或`YAML`定义这些规范. + +#### Import API specification from a URL[](#import-api-specification-from-a-url "Permalink") + +如果可以通过 URL 访问 API 规范,则可以直接将该 URL 作为目标传递. 该规范不必与要测试的 API 托管在同一主机上. + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_API_SPECIFICATION: http://my.api/api-specification.yml +``` + +#### Import API specification from a file[](#import-api-specification-from-a-file "Permalink") + +如果您的存储库中有 API 规范,则可以直接提供规范的文件名作为目标. 规范文件应位于`/zap/wrk`目录中. + +``` +dast: + script: + - mkdir -p /zap/wrk + - cp api-specification.yml /zap/wrk/api-specification.yml + - /analyze -t $DAST_WEBSITE + variables: + GIT_STRATEGY: fetch + DAST_API_SPECIFICATION: api-specification.yml +``` + +#### Full scan[](#full-scan-1 "Permalink") + +API 扫描支持完全扫描,可以使用`DAST_FULL_SCAN_ENABLED`环境变量来启用它. 完整的 API 扫描不支持域验证. + +#### Host override[](#host-override "Permalink") + +规范通常定义一个主机,其中包含一个域名和一个端口. 引用的主机可能与 API 的审阅实例的主机不同. 这可能导致导入不正确的 URL,或对不正确的主机进行扫描. 使用`DAST_API_HOST_OVERRIDE`环境变量来覆盖这些值. + +例如,对于包含以下内容的 OpenAPI V3 规范: + +``` +servers: + - url: https://api.host.com +``` + +如果 API 的测试版本在`https://api-test.host.com`上运行,则可以使用以下 DAST 配置: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_API_SPECIFICATION: http://api-test.host.com/api-specification.yml + DAST_API_HOST_OVERRIDE: api-test.host.com +``` + +请注意, `DAST_API_HOST_OVERRIDE`仅适用于 URL 导入的规范. + +#### Authentication using headers[](#authentication-using-headers "Permalink") + +请求标头中的令牌通常用作验证 API 请求的方式. 您可以通过使用`DAST_REQUEST_HEADERS`环境变量来实现. 标头适用于 DAST 提出的每个请求. + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_API_SPECIFICATION: http://api-test.api.com/api-specification.yml + DAST_REQUEST_HEADERS: "Authorization: Bearer my.token" +``` + +### Customizing the DAST settings[](#customizing-the-dast-settings "Permalink") + +**弃用:**从 GitLab 13.0 开始,不再支持[`only`和`except`](../../../ci/yaml/README.html#onlyexcept-basic)的使用. 覆盖模板时,必须使用[`rules`](../../../ci/yaml/README.html#rules) . + +可以使用`.gitlab-ci.yml`的[`variables`](../../../ci/yaml/README.html#variables)参数通过环境变量更改 DAST 设置. 这些变量记录在[可用变量中](#available-variables) . + +例如: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_WEBSITE: https://example.com + DAST_SPIDER_MINS: 120 +``` + +因为模板是[在](../../../ci/yaml/README.html#include)管道配置[之前评估](../../../ci/yaml/README.html#include)的,所以最后提到的变量将具有优先权. + +### Available variables[](#available-variables "Permalink") + +可以使用环境变量[配置](#customizing-the-dast-settings) DAST. + +| 环境变量 | Type | Description | +| --- | --- | --- | +| `SECURE_ANALYZERS_PREFIX` | URL | 设置用于下载分析器的 Docker 注册表基地址. | +| `DAST_WEBSITE` | URL | 要扫描的网站的 URL. 如果省略,则必须指定`DAST_API_SPECIFICATION` . | +| `DAST_API_SPECIFICATION` | 网址或字符串 | 要导入的 API 规范. 该规范可以托管在 URL 或`/zap/wrk`目录中存在的文件的名称中. 如果省略,则必须指定`DAST_WEBSITE` . | +| `DAST_AUTH_URL` | URL | 目标网站上包含登录 HTML 表单的页面的 URL. `DAST_USERNAME`和`DAST_PASSWORD`将与登录表单一起提交,以创建经过身份验证的扫描. API 扫描不支持. | +| `DAST_USERNAME` | string | 网站中要验证的用户名. | +| `DAST_PASSWORD` | string | 网站中要验证的密码. | +| `DAST_USERNAME_FIELD` | string | 登录 HTML 表单中的用户名字段名称. | +| `DAST_PASSWORD_FIELD` | string | 登录 HTML 表单中的密码字段名称. | +| `DAST_MASK_HTTP_HEADERS` | string | 要屏蔽的请求和响应头的逗号分隔列表(在 GitLab 13.1 中引入). 必须包含**所有**要屏蔽的标头. 请参阅[默认情况下被屏蔽的标题列表](#hide-sensitive-information) . | +| `DAST_AUTH_EXCLUDE_URLS` | URLs | 经过身份验证的扫描期间要跳过的 URL; 以逗号分隔,中间没有空格. API 扫描不支持. | +| `DAST_FULL_SCAN_ENABLED` | boolean | 设置为`true`可以运行[ZAP 全面扫描](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan)而不是[ZAP 基线扫描](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan) . 默认值: `false` | +| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | boolean | 设置为`true`以在运行 DAST 全面扫描时要求[域验证](#domain-validation) . API 扫描不支持. 默认值: `false` | +| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP 附件固定在 DAST Docker 映像中的特定版本. 设置为`true`以在扫描开始时下载最新版本. 默认值: `false` | +| `DAST_API_HOST_OVERRIDE` | string | 用于覆盖 API 规范文件中定义的域. 范例: `example.com:8080` : `example.com:8080` | +| `DAST_EXCLUDE_RULES` | string | 设置为以逗号分隔的漏洞规则 ID 列表,以将其排除在扫描过程之外. 规则 ID 是数字,可以从 DAST 日志或[ZAP 项目中找到](https://github.com/zaproxy/zaproxy/blob/develop/docs/scanners.md) . 例如, `HTTP Parameter Override`的规则 ID 为`10026` . **注意:**在早期版本的 GitLab 中,已执行排除的规则,但禁止生成它们的警报. 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) . | +| `DAST_REQUEST_HEADERS` | string | 设置为请求标题名称和值的逗号分隔列表. 标头将添加到 DAST 提出的每个请求中. 例如, `Cache-control: no-cache,User-Agent: DAST/1.0` | +| `DAST_DEBUG` | boolean | 启用调试消息输出. 默认值: `false` | +| `DAST_SPIDER_MINS` | number | 蜘蛛扫描的最大持续时间(以分钟为单位). 设置为`0`表示无限制. 默认值:一分钟,如果扫描为完全扫描,则为无限. | +| `DAST_HTML_REPORT` | string | 扫描结束时编写的 HTML 报告的文件名. | +| `DAST_MARKDOWN_REPORT` | string | 扫描结束时写入的 Markdown 报告的文件名. | +| `DAST_XML_REPORT` | string | 扫描结束时写入的 XML 报告的文件名. | +| `DAST_INCLUDE_ALPHA_VULNERABILITIES` | boolean | 设置为`true`以包括 alpha 被动和主动扫描规则. 默认值: `false` | +| `DAST_USE_AJAX_SPIDER` | boolean | 设置为`true`可以除传统蜘蛛外还使用 AJAX 蜘蛛,对爬网需要 JavaScript 的站点很有用. 默认值: `false` | +| `DAST_ZAP_CLI_OPTIONS` | string | ZAP 服务器命令行选项. 例如, `-Xmx3072m`将设置 Java 最大内存分配池大小. | +| `DAST_ZAP_LOG_CONFIGURATION` | string | 设置为 ZAP 服务器的其他 log4j 属性的分号分隔列表. 例如, `log4j.logger.org.parosproxy.paros.network.HttpSender=DEBUG;log4j.logger.com.crawljax=DEBUG` | + +### DAST command-line options[](#dast-command-line-options "Permalink") + +并非所有 DAST 配置都可以通过环境变量获得. 要找出所有可能的选项,请运行以下配置. 可用的命令行选项将被打印到作业日志中: + +``` +include: + template: DAST.gitlab-ci.yml + +dast: + script: + - /analyze --help +``` + +然后,您必须覆盖`script`命令以传递适当的参数. 例如,可以使用选项`-D`延迟被动扫描. 以下配置将被动扫描延迟了五分钟: + +``` +include: + template: DAST.gitlab-ci.yml + +dast: + script: + - export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)} + - /analyze -D 300 -t $DAST_WEBSITE +``` + +### Custom ZAProxy configuration[](#custom-zaproxy-configuration "Permalink") + +ZAProxy 服务器包含许多[有用的可配置值](https://gitlab.com/gitlab-org/gitlab/-/issues/36437#note_245801885) . `-config`许多键/值仍未记录,但是有未测试的[可能键](https://gitlab.com/gitlab-org/gitlab/-/issues/36437#note_244981023)列表. 请注意,DAST 不支持这些选项,并且在使用时可能会中断 DAST 扫描. 下面是一个如何使用`TOKEN`重写 Authorization 标头值的示例: + +``` +include: + template: DAST.gitlab-ci.yml + +variables: + DAST_ZAP_CLI_OPTIONS: "-config replacer.full_list(0).description=auth -config replacer.full_list(0).enabled=true -config replacer.full_list(0).matchtype=REQ_HEADER -config replacer.full_list(0).matchstr=Authorization -config replacer.full_list(0).regex=false -config replacer.full_list(0).replacement=TOKEN" +``` + +### Cloning the project’s repository[](#cloning-the-projects-repository "Permalink") + +DAST 作业在运行时不需要存在项目的存储库,因此默认情况下[`GIT_STRATEGY`](../../../ci/yaml/README.html#git-strategy)设置为`none` . + +### Debugging DAST jobs[](#debugging-dast-jobs "Permalink") + +A DAST job has two executing processes: + +* ZAP 服务器. +* 启动,控制和停止 ZAP 服务器的一系列脚本. + +可以使用`DAST_DEBUG`环境变量来启用脚本的调试模式. 这在对作业进行故障排除时会有所帮助,并且将输出指示扫描完成百分比的语句. 有关使用变量的详细信息,请参见[覆盖 DAST 模板](#customizing-the-dast-settings) . + +可以使用`DAST_ZAP_LOG_CONFIGURATION`环境变量启用 ZAP 服务器的调试模式. 下表概述了可以设置的值的示例,以及它们对记录的输出的影响. 可以指定多个值,以分号分隔. + +| 日志配置值 | Effect | +| --- | --- | +| `log4j.rootLogger=DEBUG` | 启用所有调试日志记录语句. | +| `log4j.logger.org.apache.commons.httpclient=DEBUG` | 记录 ZAP 服务器所做的每个 HTTP 请求和响应. | +| `log4j.logger.org.zaproxy.zap.spider.SpiderController=DEBUG` | 在目标的蜘蛛扫描期间找到的日志 URL. | +| `log4j.logger.com.crawljax=DEBUG` | 启用 Ajax Crawler 调试日志记录语句. | +| `log4j.logger.org.parosproxy.paros=DEBUG` | 启用 ZAP 服务器代理调试日志记录语句. | +| `log4j.logger.org.zaproxy.zap=DEBUG` | 启用常规 ZAP 服务器代码的调试日志记录语句. | + +## Running DAST in an offline environment[](#running-dast-in-an-offline-environment "Permalink") + +对于在通过互联网有限,受限或间歇性访问外部资源的环境中进行自我管理的 GitLab 实例,需要进行一些调整才能成功运行 DAST 作业. 有关更多信息,请参阅[脱机环境](../offline_deployments/index.html) . + +### Requirements for offline DAST support[](#requirements-for-offline-dast-support "Permalink") + +要在离线环境中使用 DAST,您需要: + +* GitLab 亚军与[`docker`或`kubernetes`执行](#requirements) . +* 带有 DAST [容器映像](https://gitlab.com/gitlab-org/security-products/dast)的本地可用副本的 Docker 容器注册表,可在[DAST 容器注册表中找到](https://gitlab.com/gitlab-org/security-products/dast/container_registry) . + +**Note:** GitLab Runner has a [default `pull policy` of `always`](https://docs.gitlab.com/runner/executors/docker.html), meaning the Runner tries to pull Docker images from the GitLab container registry even if a local copy is available. GitLab Runner’s [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html) in an offline environment if you prefer using only locally available Docker images. However, we recommend keeping the pull policy setting to `always` if not in an offline environment, as this enables the use of updated scanners in your CI/CD pipelines. + +### Make GitLab DAST analyzer images available inside your Docker registry[](#make-gitlab-dast-analyzer-images-available-inside-your-docker-registry "Permalink") + +对于 DAST,将以下默认 DAST 分析器映像从`registry.gitlab.com`导入到[本地 Docker 容器注册表](../../packages/container_registry/index.html) : + +* `registry.gitlab.com/gitlab-org/security-products/dast:latest` + +The process for importing Docker images into a local offline Docker registry depends on **您的网络安全政策**. Please consult your IT staff to find an accepted and approved process by which external resources can be imported or temporarily accessed. Note that these scanners are [updated periodically](../index.html#maintenance-and-update-of-the-vulnerabilities-database) with new definitions, so consider if you’re able to make periodic updates yourself. + +有关将 Docker 映像保存和传输为文件的详细信息,请参阅 Docker 有关[`docker save`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/save/) , [`docker load`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/load/) , [`docker export`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/export/)和[`docker import`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/import/)的文档. + +### Set DAST CI job variables to use local DAST analyzers[](#set-dast-ci-job-variables-to-use-local-dast-analyzers "Permalink") + +将以下配置添加到您的`.gitlab-ci.yml`文件. 您必须替换`image`以引用本地 Docker 容器注册表中托管的 DAST Docker 映像: + +``` +include: + - template: DAST.gitlab-ci.yml +dast: + image: registry.example.com/namespace/dast:latest +``` + +DAST 作业现在应该使用 DAST 分析器的本地副本来扫描您的代码并生成安全报告,而无需访问 Internet. + +或者,您可以使用变量`SECURE_ANALYZERS_PREFIX`覆盖`dast`映像的基本注册表地址. + +## On-Demand Scans[](#on-demand-scans "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上已禁用. +* 每个项目都可以启用或禁用它. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-on-demand-scans) . + +在 DevOps 生命周期之外,可以根据需要针对目标网站运行被动 DAST 扫描. 这些扫描将始终与项目的默认分支或`master`分支关联,并且结果可以在项目仪表板中看到. + +[![DAST On-Demand Scan](img/49588b733704d134418744f910f7809b.png)](img/dast_on_demand_v13_2.png) + +### Enable or disable On-Demand Scans[](#enable-or-disable-on-demand-scans "Permalink") + +按需扫描正在开发中,尚未准备好用于生产. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以为您的实例启用它. 可以按项目启用或禁用按需扫描 + +要启用它: + +``` +# Instance-wide +Feature.enable(:security_on_demand_scans_feature_flag) +# or by project +Feature.enable(:security_on_demand_scans_feature_flag, Project.find()) +``` + +To disable it: + +``` +# Instance-wide +Feature.disable(:security_on_demand_scans_feature_flag) +# or by project +Feature.disable(:security_on_demand_scans_feature_flag, Project.find()) +``` + +## Reports[](#reports "Permalink") + +默认情况下,DAST 工具以 JSON 格式输出报告文件. 但是,此工具还可以生成 Markdown,HTML 和 XML 的报告. 有关更多信息,请参阅[DAST 报告](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/dast-report-format.json)的[架构](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/dast-report-format.json) . + +### List of URLs scanned[](#list-of-urls-scanned "Permalink") + +当 DAST 完成扫描时,合并请求页面将说明扫描的 URL 数量. 单击**查看详细信息**以查看 Web 控制台输出,其中包括扫描的 URL 列表. + +[![DAST Widget](img/81cb03504811f2ae5f008de13366a1db.png)](img/dast_urls_scanned_v12_10.png) + +### JSON[](#json "Permalink") + +**警告:** JSON 报表工件不是 DAST 的公共 API,并且其格式预计会在将来更改. + +DAST 工具始终会发出一个名为`gl-dast-report.json`的 JSON 报告文件,并且可以在[DAST 存储库中](https://gitlab.com/gitlab-org/security-products/dast/-/tree/master/test/end-to-end/expect)找到示例报告. + +JSON 报表中有两种数据格式可以并排使用: + +* 专有的 ZAP 格式将最终弃用. +* 一种通用格式,将来会成为默认格式. + +### Other formats[](#other-formats "Permalink") + +还可以用 Markdown,HTML 和 XML 生成报告. 这些可以使用以下配置作为工件发布: + +``` +include: + template: DAST.gitlab-ci.yml + +dast: + variables: + DAST_HTML_REPORT: report.html + DAST_MARKDOWN_REPORT: report.md + DAST_XML_REPORT: report.xml + artifacts: + paths: + - $DAST_HTML_REPORT + - $DAST_MARKDOWN_REPORT + - $DAST_XML_REPORT + - gl-dast-report.json +``` + +## Security Dashboard[](#security-dashboard "Permalink") + +在"安全仪表板"中,您可以概览您的组,项目和管道中的所有安全漏洞. 阅读有关[安全仪表板的](../security_dashboard/index.html)更多[信息](../security_dashboard/index.html) . + +## Bleeding-edge vulnerability definitions[](#bleeding-edge-vulnerability-definitions "Permalink") + +ZAP 首先在`alpha`类中创建规则. 经过与社区的测试期后,他们被提升为`beta` . 默认情况下,DAST 使用`beta`定义. 要请求`alpha`定义,请使用`DAST_INCLUDE_ALPHA_VULNERABILITIES`环境变量,如以下配置所示: + +``` +include: + template: DAST.gitlab-ci.yml + +variables: + DAST_INCLUDE_ALPHA_VULNERABILITIES: true +``` + +## Interacting with the vulnerabilities[](#interacting-with-the-vulnerabilities "Permalink") + +一旦发现漏洞,便可以与其进行交互. 阅读有关如何[与漏洞](../index.html#interacting-with-the-vulnerabilities)进行[交互的](../index.html#interacting-with-the-vulnerabilities)更多信息. + +## Vulnerabilities database update[](#vulnerabilities-database-update "Permalink") + +有关漏洞数据库更新的更多信息,请查看[维护表](../index.html#maintenance-and-update-of-the-vulnerabilities-database) . + +## Optimizing DAST[](#optimizing-dast "Permalink") + +默认情况下,DAST 将下载管道中先前作业定义的所有工件. 如果您的 DAST 作业不依赖`environment_url.txt`来定义被测 URL 或以前的作业中创建的任何其他文件,我们建议您不要下载工件. 为了避免下载工件,请将以下内容添加到您的`gitlab-ci.yml`文件中: + +``` +dast: dependencies: [] +``` + +## Troubleshooting[](#troubleshooting "Permalink") + +### Running out of memory[](#running-out-of-memory "Permalink") + +默认情况下,DAST 依赖的 ZAProxy 被分配的内存总计为主机上总内存的 25%. 由于它在扫描期间将大部分信息保留在内存中,因此 DAST 在扫描大型应用程序时可能会用尽内存. 这将导致以下错误: + +``` +[zap.out] java.lang.OutOfMemoryError: Java heap space +``` + +幸运的是,通过使用`DAST_ZAP_CLI_OPTIONS`环境变量可以直接增加 DAST 可用的内存量: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_ZAP_CLI_OPTIONS: "-Xmx3072m" +``` + +在此,DAST 被分配了 3072 MB. 将`-Xmx`之后的数字更改为所需的存储量. \ No newline at end of file diff --git a/_book/docs/057.md b/_book/docs/057.md new file mode 100644 index 0000000000000000000000000000000000000000..8b2a1b850199a90fe39bef322541e1d64f6c9398 --- /dev/null +++ b/_book/docs/057.md @@ -0,0 +1,160 @@ +# GitLab Security Dashboard + +> 原文:[https://docs.gitlab.com/ee/user/application_security/security_dashboard/](https://docs.gitlab.com/ee/user/application_security/security_dashboard/) + +* [Supported reports](#supported-reports) +* [Requirements](#requirements) +* [Pipeline Security](#pipeline-security) +* [Project Security Dashboard](#project-security-dashboard) +* [Group Security Dashboard](#group-security-dashboard) +* [Instance Security Dashboard](#instance-security-dashboard) + * [Adding projects to the dashboard](#adding-projects-to-the-dashboard) +* [Export vulnerabilities](#export-vulnerabilities) +* [Keeping the dashboards up to date](#keeping-the-dashboards-up-to-date) +* [Security scans using Auto DevOps](#security-scans-using-auto-devops) +* [Vulnerability list](#vulnerability-list) + +# GitLab Security Dashboard[](#gitlab-security-dashboard-ultimate "Permalink") + +在"安全仪表板"中,您可以概览您的组,项目和管道中的所有安全漏洞. + +您还可以深入研究漏洞并获得更多信息,查看其来源,项目所在的文件以及各种元数据,以帮助您分析风险. 您也可以通过为漏洞创建问题或消除漏洞来对漏洞采取措施. + +要从"安全仪表板"中受益,您必须首先配置其中一份[安全报告](../index.html) . + +## Supported reports[](#supported-reports "Permalink") + +安全仪表板支持以下报告: + +* [Container Scanning](../container_scanning/index.html) +* [Dynamic Application Security Testing](../dast/index.html) +* [Dependency Scanning](../dependency_scanning/index.html) +* [Static Application Security Testing](../sast/index.html) + +## Requirements[](#requirements "Permalink") + +要使用实例,组,项目或管道安全性仪表板,请执行以下操作: + +1. 组中的至少一个项目必须配置有至少一个[受支持的报告](#supported-reports) . +2. 配置的作业必须使用[新的`reports`语法](../../../ci/pipelines/job_artifacts.html#artifactsreports) . +3. 必须使用[GitLab Runner](https://docs.gitlab.com/runner/) 11.5 或更高版本. 如果您在 GitLab.com 上使用共享的 Runners,那么情况已经如此. + +## Pipeline Security[](#pipeline-security "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13496) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.3. + +在管道级别,"安全性"部分显示了运行管道所针对的项目分支中存在的漏洞. + +访问页面以查看运行了任何[受支持报告的](#supported-reports)任何管道. 单击**安全性**选项卡以查看安全性发现. + +[![Pipeline Security Dashboard](img/f0d8585fb8235b36b1464ed1d142a4c0.png)](img/pipeline_security_dashboard_v13_2.png) + +**注意:**管道包含多个作业,包括 SAST 和 DAST 扫描. 如果任何作业由于任何原因无法完成,则安全信息中心将不会显示 SAST 扫描仪输出. 例如,如果 SAST 作业完成但 DAST 作业失败,则安全性仪表板将不会显示 SAST 结果. 分析器将在失败时输出[退出代码](../../../development/integrations/secure.html#exit-code) . + +## Project Security Dashboard[](#project-security-dashboard "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6165) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.1. + +在项目级别,安全性仪表板显示合并到项目的[默认分支中](../../project/repository/branches/index.html#default-branch)的漏洞. 通过导航到" **安全与合规性">"安全仪表板"**来访问它. + +安全仪表板首先按严重性显示漏洞的总数(例如,严重,高,中,低). 在此下方,有一个表显示每个漏洞的状态,严重性和描述. 单击漏洞会将您带到其" [漏洞详细信息"](../vulnerabilities)页面,以查看有关该漏洞的更多信息. + +您可以通过以下方式过滤漏洞: + +* Status +* Severity +* 报告类型 + +您还可以消除表中的漏洞: + +1. 选择要消除的每个漏洞的复选框. +2. 在出现的菜单中,选择**退出**的原因,然后点击**取消选中** . + +[![Project Security Dashboard](img/2066156f84e498acec96cdfb63d2d2a4.png)](img/project_security_dashboard_v13_2.png) + +## Group Security Dashboard[](#group-security-dashboard "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6709) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5. + +组安全仪表板概述了组及其子组中项目的默认分支中的漏洞. 通过导航至组的" **安全性">"安全性仪表板"**来访问它. + +**注意:** "安全仪表板"仅显示在组中启用了[安全报告的](#supported-reports)项目. + +[![Dashboard with action buttons and metrics](img/7b7c08f411e1307c05a834071bccb610.png)](img/group_security_dashboard_v13_2_noNav.png) + +您可以通过以下方式过滤安全仪表板显示的漏洞: + +* Status +* Severity +* 报告类型 +* Project + +表格列出了漏洞,并按严重性排序. 该表显示了每个漏洞的状态,严重性和描述. 单击漏洞会将您带到其" [漏洞详细信息"](../vulnerabilities)页面,以查看有关该漏洞的更多信息. + +列表旁边是时间线图,该图显示了您的项目在不同时间点有多少个未解决的漏洞. 您可以在 30 天,60 天和 90 天之间进行过滤,默认值为 90 天.将鼠标悬停在图表上可获得有关特定时间未解决漏洞的更多详细信息. + +时间线图表下方是项目列表,按发现的漏洞的严重程度进行分组和排序: + +* F:1 个或更多"关键" +* D:1 个或多个"高"或"未知" +* C: 1 or more “medium” +* B:1 个或多个"低" +* 答:0 个漏洞 + +未配置漏洞测试的项目不会出现在列表中. 此外,也不包含已消除的漏洞. + +阅读有关如何[与漏洞](../index.html#interacting-with-the-vulnerabilities)进行[交互的](../index.html#interacting-with-the-vulnerabilities)更多信息. + +## Instance Security Dashboard[](#instance-security-dashboard "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6953) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.8. + +在实例级别,安全仪表板显示您配置为显示在仪表板上的所有项目的默认分支中存在的漏洞. 它包括[组"安全仪表板"的](#group-security-dashboard)所有功能. + +您可以从页面顶部的菜单栏中访问 Instance Security 仪表板. 在" **更多"下** ,选择" **安全性"** . + +[![Instance Security Dashboard navigation link](img/25892ec4aa99429a91c30ac3395379e0.png)](img/instance_security_dashboard_link_v12_4.png) + +### Adding projects to the dashboard[](#adding-projects-to-the-dashboard "Permalink") + +要将项目添加到仪表板: + +1. 单击"实例安全性仪表板"页面上的**编辑仪表板**按钮. +2. 使用" **搜索您的项目"**字段搜索并添加一个或多个项目. +3. 单击**添加项目**按钮. + +添加后,安全仪表板将显示在所选项目的默认分支中发现的漏洞. + +[![Instance Security Dashboard with projects](img/5653420f4acd0e8a49be80d5d413bd10.png)](img/instance_security_dashboard_with_projects_v13_2_sm.png) + +## Export vulnerabilities[](#export-vulnerabilities "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213014) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. + +您可以通过以下方式将所有漏洞导出为 CSV 格式: 位于**安全仪表板**右上方的" **导出"**按钮. 生成报告后,CSV 报告将下载到本地计算机. 该报告包含" **安全性仪表板"中**定义的项目的所有漏洞,因为过滤器不适用于导出功能. + +**注意:**如果您的项目包含成千上万个漏洞,下载可能需要几分钟的时间才能开始. 下载完成之前,请不要关闭页面. + +## Keeping the dashboards up to date[](#keeping-the-dashboards-up-to-date "Permalink") + +安全仪表板在[默认分支](../../project/repository/branches/index.html#default-branch)上显示来自最新安全扫描结果的信息,这意味着每次更新分支时都会执行安全扫描. + +如果不经常更新默认分支,则不经常运行扫描,并且随着发现新漏洞,安全仪表板上的信息可能会过时. + +为确保安全仪表板上的信息得到定期更新,请[配置计划的管道](../../../ci/pipelines/schedules.html)以运行每日安全扫描. 不管默认分支的更新频率如何,这都会更新"安全性"仪表板上显示的信息. + +这样,即使没有代码更改也不会创建报告. + +## Security scans using Auto DevOps[](#security-scans-using-auto-devops "Permalink") + +使用[Auto DevOps 时](../../../topics/autodevops/index.html) ,请使用[特殊的环境变量](../../../topics/autodevops/customize.html#environment-variables)来配置每日安全扫描. + +## Vulnerability list[](#vulnerability-list "Permalink") + +Each dashboard’s vulnerability list contains vulnerabilities from the latest scans that were merged into the default branch. Click any vulnerability in the table to see more information on that vulnerability. To create an issue associated with the vulnerability, click the **创建问题** button. + +[![Create an issue for the vulnerability](img/a9880855e171e225a4b6c73ae1790538.png)](img/standalone_vulnerability_page_v13_1.png) + +创建问题后,漏洞列表将包含该问题的链接和一个图标,其颜色指示该问题的状态(绿色代表未解决的问题,蓝色代表未解决的问题). + +[![Display attached issues](img/f1e26381a4d60fa929a9285e04721656.png)](img/vulnerability_list_table_v13_1.png) \ No newline at end of file diff --git a/_book/docs/058.md b/_book/docs/058.md new file mode 100644 index 0000000000000000000000000000000000000000..faf96043e9c08bee7dd5787f3dc133eb297eff32 --- /dev/null +++ b/_book/docs/058.md @@ -0,0 +1,64 @@ +# Offline environments + +> 原文:[https://docs.gitlab.com/ee/user/application_security/offline_deployments/](https://docs.gitlab.com/ee/user/application_security/offline_deployments/) + +* [Defining offline environments](#defining-offline-environments) +* [Overview](#overview) + * [Container registries and package repositories](#container-registries-and-package-repositories) + * [Interacting with the vulnerabilities](#interacting-with-the-vulnerabilities) + * [Suggested Solutions for vulnerabilities](#suggested-solutions-for-vulnerabilities) + * [Scanner signature and rule updates](#scanner-signature-and-rule-updates) +* [Specific scanner instructions](#specific-scanner-instructions) + +# Offline environments[](#offline-environments "Permalink") + +未连接到互联网时,可以运行大多数的 GitLab 安全扫描程序. + +本文档介绍了如何在脱机环境中操作安全类别(即扫描仪类型). 这些说明还适用于受保护,具有安全策略(例如,防火墙策略)或受其他限制而无法访问整个 Internet 的自我管理安装. GitLab 将这些环境称为*脱机环境* . 其他常用名称包括: + +* 气隙环境 +* 受限的连接环境 +* 局域网(LAN)环境 +* 内联网环境 + +这些环境具有阻止或限制 Internet 访问的物理障碍或安全策略(例如,防火墙). 这些说明是为物理上断开连接的网络而设计的,但在其他用例中也可以遵循这些说明. + +## Defining offline environments[](#defining-offline-environments "Permalink") + +在离线环境中,GitLab 实例可以是一个或多个服务器和服务,它们可以在本地网络上进行通信,但是对 Internet 的访问没有限制或受到非常严格的限制. 假设可以通过本地网络连接访问 GitLab 实例和支持基础结构(例如,私有 Maven 存储库)中的任何内容. 假定来自 Internet 的任何文件都必须通过物理媒体(USB 驱动器,硬盘驱动器,可写 DVD 等)进入. + +## Overview[](#overview "Permalink") + +GitLab 扫描仪通常会连接到互联网,以下载最新的签名,规则和补丁集. 通过使用本地网络上可用的资源,需要一些额外的步骤来配置工具以使其正常运行. + +### Container registries and package repositories[](#container-registries-and-package-repositories "Permalink") + +在较高级别,安全分析器以 Docker 映像的形式提供,并且可以利用各种软件包存储库. 当您在联网的 GitLab 安装上运行作业时,GitLab 会检查 GitLab.com 托管的容器注册表,以检查您是否具有这些 Docker 映像的最新版本,并可能连接到软件包存储库以安装必要的依赖项. + +在离线环境中,必须禁用这些检查,以便不查询 GitLab.com. 由于 GitLab.com 注册表和存储库不可用,因此您必须更新每个扫描仪以引用不同的内部托管注册表,或提供对单个扫描仪图像的访问. + +您还必须确保您的应用可以访问不在 GitLab.com 上托管的常见软件包存储库,例如 npm,yarn 或 Ruby gems. 可以通过临时连接到网络或通过镜像自己的脱机网络中的软件包来获取这些存储库中的软件包. + +### Interacting with the vulnerabilities[](#interacting-with-the-vulnerabilities "Permalink") + +一旦发现漏洞,便可以与其进行交互. 阅读有关如何[与漏洞](../index.html#interacting-with-the-vulnerabilities)进行[交互的](../index.html#interacting-with-the-vulnerabilities)更多信息. + +请注意,在某些情况下,所报告的漏洞提供的元数据可能包含 UI 中公开的外部链接. 在脱机环境中可能无法访问这些链接. + +### Suggested Solutions for vulnerabilities[](#suggested-solutions-for-vulnerabilities "Permalink") + +[建议的解决方案](../index.html#solutions-for-vulnerabilities-auto-remediation)功能(自动修复)可用于"依赖关系扫描"和"容器扫描",但可能无法运行,具体取决于实例的配置. 当我们能够访问托管该依赖项或映像的最新版本的最新注册表服务时,我们只能建议解决方案,这些解决方案通常是已修补的最新版本. + +### Scanner signature and rule updates[](#scanner-signature-and-rule-updates "Permalink") + +连接到 Internet 时,某些扫描仪会参考公共数据库以获取最新的签名集和要检查的规则. 没有连接,这是不可能的. 因此,根据扫描仪的不同,您必须禁用这些自动更新检查,并使用它们随附的数据库并手动更新这些数据库,或者提供对网络中托管的自己的副本的访问权限. + +## Specific scanner instructions[](#specific-scanner-instructions "Permalink") + +每个单独的扫描仪可能与上述步骤略有不同. 您可以在以下每个页面上找到更多信息: + +* [Container scanning offline directions](../container_scanning/index.html#running-container-scanning-in-an-offline-environment) +* [SAST offline directions](../sast/index.html#running-sast-in-an-offline-environment) +* [DAST offline directions](../dast/index.html#running-dast-in-an-offline-environment) +* [License Compliance offline directions](../../compliance/license_compliance/index.html#running-license-compliance-in-an-offline-environment) +* [Dependency Scanning offline directions](../dependency_scanning/index.html#running-dependency-scanning-in-an-offline-environment) \ No newline at end of file diff --git a/_book/docs/059.md b/_book/docs/059.md new file mode 100644 index 0000000000000000000000000000000000000000..1db0f5ce12927d172a21f88e5ec4a140f4b7bf0b --- /dev/null +++ b/_book/docs/059.md @@ -0,0 +1,62 @@ +# Standalone Vulnerability pages + +> 原文:[https://docs.gitlab.com/ee/user/application_security/vulnerabilities/](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/) + +* [Changing vulnerability status](#changing-vulnerability-status) +* [Creating an issue for a vulnerability](#creating-an-issue-for-a-vulnerability) +* [Automatic remediation solutions for vulnerabilities](#automatic-remediation-solutions-for-vulnerabilities) + * [Manually applying a suggested patch](#manually-applying-a-suggested-patch) + +# Standalone Vulnerability pages[](#standalone-vulnerability-pages "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13561) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0. + +[安全仪表板](../security_dashboard/index.html#project-security-dashboard)中的每个安全漏洞都有其自己的独立页面. + +[![Standalone vulnerability page](img/62d2b5c8435d31dff0a7fc689c288e8c.png)](img/standalone_vulnerability_page_v13_1.png) + +在独立漏洞页面上,您可以通过几种不同方式与漏洞进行交互: + +* [变化的脆弱性状态](#changing-vulnerability-status) -您可以将漏洞的状态更改为**检测** , **确认** , **驳回**或**解决** . +* [创建问题](#creating-an-issue-for-a-vulnerability) -创建一个新问题,其标题和说明已预先填充了漏洞报告中的信息. 默认情况下,此类问题是[机密的](../../project/issues/confidential_issues.html) . +* [解决方案](#automatic-remediation-solutions-for-vulnerabilities) -对于某些漏洞,提供了有关如何修复该漏洞的解决方案. + +## Changing vulnerability status[](#changing-vulnerability-status "Permalink") + +您可以使用" **状态"**下拉列表将漏洞的**状态**切换为以下值之一: + +| Status | Description | +| --- | --- | +| Detected | 新发现漏洞的默认状态 | +| Confirmed | 用户已经看到此漏洞并确认它是真实的 | +| Dismissed | 用户已经看到此漏洞并将其消除 | +| Resolved | 该漏洞已修复,不再存在于代码库中 | + +## Creating an issue for a vulnerability[](#creating-an-issue-for-a-vulnerability "Permalink") + +您可以通过选择**创建问题**按钮来**创建**漏洞**问题** . + +这会在漏洞来自的项目中创建一个[机密问题](../../project/issues/confidential_issues.html) ,并使用漏洞报告中的有用信息对其进行预填充. 创建问题后,GitLab 会将您重定向到问题页面,以便您可以编辑,分配或评论问题. + +## Automatic remediation solutions for vulnerabilities[](#automatic-remediation-solutions-for-vulnerabilities "Permalink") + +您可以通过应用 GitLab 为您自动生成的解决方案来修复某些漏洞. GitLab 支持以下扫描仪: + +* [依赖项扫描](../dependency_scanning/index.html) :自动补丁创建仅适用于使用`yarn`管理的 Node.js 项目. +* [Container Scanning](../container_scanning/index.html). + +When an automatic solution is available, the button in the header will show “Resolve with merge request”: + +[![Resolve with Merge Request button](img/e661a6c6931c39f12f5b6833566b8947.png)](img/standalone_vulnerability_page_merge_request_button_v13_1.png) + +选择该按钮将创建带有自动解决方案的合并请求. + +### Manually applying a suggested patch[](#manually-applying-a-suggested-patch "Permalink") + +要手动应用由 GitLab 生成的漏洞补丁,请选择"使用合并请求解决"按钮上的下拉箭头,然后选择"下载要解决的补丁"选项: + +[![Resolve with Merge Request button dropdown](img/2310ec0a03905adc0774d21079604b57.png)](img/standalone_vulnerability_page_merge_request_button_dropdown_v13_1.png) + +这会将按钮文本更改为"下载修补程序以解决". 单击它下载补丁: + +[![Download patch button](img/4e980984ef171e4c624f56ebeb3277c7.png)](img/standalone_vulnerability_page_download_patch_button_v13_1.png) \ No newline at end of file diff --git a/_book/docs/060.md b/_book/docs/060.md new file mode 100644 index 0000000000000000000000000000000000000000..82a0adcc96879fefb2a014f0f771f34ff2cf9ed8 --- /dev/null +++ b/_book/docs/060.md @@ -0,0 +1,388 @@ +# Security scanner integration + +> 原文:[https://docs.gitlab.com/ee/development/integrations/secure.html](https://docs.gitlab.com/ee/development/integrations/secure.html) + +* [Job definition](#job-definition) + * [Name](#name) + * [Image](#image) + * [Script](#script) + * [Stage](#stage) + * [Fail-safe](#fail-safe) + * [Artifacts](#artifacts) + * [Policies](#policies) + * [Policy checking example](#policy-checking-example) +* [Docker image](#docker-image) + * [Image size](#image-size) + * [Image tag](#image-tag) +* [Command line](#command-line) + * [Variables](#variables) + * [SAST and Dependency Scanning](#sast-and-dependency-scanning) + * [Container Scanning](#container-scanning) + * [Configuration files](#configuration-files) + * [Output file](#output-file) + * [Exit code](#exit-code) + * [Logging](#logging) + * [Logging level](#logging-level) + * [common logutil package](#common-logutil-package) +* [Report](#report) + * [Version](#version) + * [Vulnerabilities](#vulnerabilities) + * [ID](#id) + * [Category](#category) + * [Scanner](#scanner) + * [Name, message, and description](#name-message-and-description) + * [Solution](#solution) + * [Identifiers](#identifiers) + * [Location](#location) + * [Dependency Scanning](#dependency-scanning) + * [Container Scanning](#container-scanning-1) + * [SAST](#sast) + * [Tracking and merging vulnerabilities](#tracking-and-merging-vulnerabilities) + * [Severity and confidence](#severity-and-confidence) + * [Remediations](#remediations) + * [Summary](#summary) + * [Fixed vulnerabilities](#fixed-vulnerabilities) + * [Diff](#diff) +* [Limitations](#limitations) + * [Container Scanning](#container-scanning-2) + +# Security scanner integration[](#security-scanner-integration "Permalink") + +将安全扫描程序集成到 GitLab 包括为最终用户提供[CI 作业定义,](../../ci/yaml/README.html#introduction)他们可以将其添加到 CI 配置文件中以扫描其 GitLab 项目. 然后,此 CI 作业应以 GitLab 指定的格式输出其结果. 然后,这些结果将自动显示在 GitLab 中的各个位置,例如管道视图,合并请求小部件和安全仪表板. + +扫描作业通常基于[Docker 映像](https://s0docs0docker0com.icopy.site/) ,该[映像](https://s0docs0docker0com.icopy.site/)包含扫描程序及其在独立环境中的所有依赖性. + +该页面记录了编写实现安全扫描程序的 CI 作业的要求和准则,以及 Docker 映像的要求和准则. + +## Job definition[](#job-definition "Permalink") + +本节描述了要添加到安全扫描器的作业定义文件中的几个重要字段. 有关这些以及其他可用字段的完整文档,请参阅[CI 文档](../../ci/yaml/README.html#image) . + +### Name[](#name "Permalink") + +为了保持一致性,扫描作业应以扫描仪的名字命名(小写). 作业名称是扫描的类型之后后缀: `_dependency_scanning` , `_container_scanning` , `_dast`和`_sast` . 例如,基于" MySec"扫描程序的依赖项扫描作业将被命名为`mysec_dependency_scanning` . + +### Image[](#image "Permalink") + +[`image`](../../ci/yaml/README.html#image)关键字用于指定包含安全扫描器的[Docker 映像](../../ci/docker/using_docker_images.html#what-is-an-image) . + +### Script[](#script "Permalink") + +[`script`](../../ci/yaml/README.html#script)关键字用于指定运行扫描仪的命令. 由于`script`条目不能为空,因此必须将其设置为执行扫描的命令. 无法依靠 Docker 映像的预定义`ENTRYPOINT`和`CMD`来自动执行扫描,而无需传递任何命令. + +在作业定义中不应使用[`before_script`](../../ci/yaml/README.html#before_script-and-after_script) ,因为用户可以在执行扫描之前依靠它来准备其项目. 例如,通常的做法是在执行 SAST 或依赖项扫描之前,使用`before_script`安装特定项目所需的系统库. + +同样,在作业定义中不应使用[`after_script`](../../ci/yaml/README.html#before_script-and-after_script) ,因为它可能会被用户覆盖. + +### Stage[](#stage "Permalink") + +为了保持一致性,扫描作业应尽可能属于`test`阶段. 可以省略[`stage`](../../ci/yaml/README.html#stage)关键字,因为`test`是默认值. + +### Fail-safe[](#fail-safe "Permalink") + +为了与[GitLab Security 范例](https://about.gitlab.com/direction/secure/#security-paradigm)保持一致,扫描作业在失败时不应阻塞管道,因此[`allow_failure`](../../ci/yaml/README.html#allow_failure)参数设置为`true` . + +### Artifacts[](#artifacts "Permalink") + +扫描作业必须使用[`artifacts:reports`](../../ci/pipelines/job_artifacts.html#artifactsreports)关键字声明与其执行的扫描类型相对应的[`artifacts:reports`](../../ci/pipelines/job_artifacts.html#artifactsreports) . 有效报告为: `dependency_scanning` , `container_scanning` , `dast`和`sast` . + +例如,以下是 SAST 作业的定义,该作业生成一个名为`gl-sast-report.json`的文件,并将其作为 SAST 报告上载: + +``` +mysec_sast: + image: registry.gitlab.com/secure/mysec + artifacts: + reports: + sast: gl-sast-report.json +``` + +请注意, `gl-sast-report.json`是示例文件路径,但可以使用任何其他文件名. 有关更多详细信息,请参见["输出文件"部分](#output-file) . 之所以将其作为 SAST 报告处理是因为它是在作业定义中的`reports:sast`键下声明的,而不是因为文件名. + +### Policies[](#policies "Permalink") + +某些 GitLab 工作流程(例如[AutoDevOps](../../topics/autodevops/customize.html#disable-jobs) )定义了变量,以指示应禁用给定的扫描. 您可以通过查找诸如`DEPENDENCY_SCANNING_DISABLED` , `CONTAINER_SCANNING_DISABLED` , `SAST_DISABLED`和`DAST_DISABLED`变量来进行检查. 根据扫描仪类型,如果合适,则应禁用运行自定义扫描仪. + +GitLab 还定义了一个`CI_PROJECT_REPOSITORY_LANGUAGES`变量,该变量提供了存储库中的语言列表. 根据此值,扫描仪可能会做或可能不会做不同的事情. 目前,语言检测依赖于[`linguist`](https://github.com/github/linguist) Ruby gem. 请参阅[GitLab CI / CD 预定义变量](../../ci/variables/predefined_variables.html) . + +#### Policy checking example[](#policy-checking-example "Permalink") + +此示例显示如何跳过自定义的依赖项扫描作业`mysec_dependency_scanning` ,除非项目存储库包含 Java 源代码并且启用了`dependency_scanning`功能: + +``` +mysec_dependency_scanning: + rules: + - if: $DEPENDENCY_SCANNING_DISABLED + when: never + - if: $GITLAB_FEATURES =~ /\bdependency_scanning\b/ + exists: + - '**/*.java' +``` + +任何其他作业策略仅应由用户根据其需求进行配置. 例如,预定义策略不应触发特定分支或特定文件集更改时的扫描作业. + +## Docker image[](#docker-image "Permalink") + +Docker 映像是一个自包含的环境,将扫描仪与其依赖的所有库和工具结合在一起. 将扫描程序打包到 Docker 映像中,无论扫描程序在哪台计算机上运行,​​其依赖关系和配置始终存在. + +### Image size[](#image-size "Permalink") + +根据 CI 基础架构,CI 可能必须在每次作业运行时都获取 Docker 映像. 为了使扫描作业快速运行并避免浪费带宽,Docker 映像应尽可能小. 您的目标应该是 50MB 或更小. 如果无法做到这一点,请尝试使其保持在 1.46 GB 以下,即 CD-ROM 的大小. + +If the scanner requires a fully functional Linux environment, it is recommended to use a [Debian](https://www.debian.org/intro/about) “slim” distribution or [Alpine Linux](https://www.alpinelinux.org/). If possible, it is recommended to build the image from scratch, using the `FROM scratch` instruction, and to compile the scanner with all the libraries it needs. [Multi-stage builds](https://s0docs0docker0com.icopy.site/develop/develop-images/multistage-build/) might also help with keeping the image small. + +为了保持较小的图像大小,请考虑使用[Dive](https://github.com/wagoodman/dive#dive)分析 Docker 图像中的图层,以识别可能来自其他地方的膨胀. + +In some cases, it might be difficult to remove files from an image. When this occurs, consider using [Zstandard](https://github.com/facebook/zstd) to compress files or large directories. Zstandard offers many different compression levels that can decrease the size of your image with very little impact to decompression speed. It may be helpful to automatically decompress any compressed directories as soon as an image launches. You can accomplish this by adding a step to the Docker image’s `/etc/bashrc` or to a specific user’s `$HOME/.bashrc`. Remember to change the entry point to launch a bash login shell if you chose the latter option. + +以下是一些入门的示例: + +* [https://gitlab.com/gitlab-org/security-products/license-management/-/blob/0b976fcffe0a9b8e80587adb076bcdf279c9331c/config/install.sh#L168-170](https://gitlab.com/gitlab-org/security-products/license-management/-/blob/0b976fcffe0a9b8e80587adb076bcdf279c9331c/config/install.sh#L168-170) +* [https://gitlab.com/gitlab-org/security-products/license-management/-/blob/0b976fcffe0a9b8e80587adb076bcdf279c9331c/config/.bashrc#L49](https://gitlab.com/gitlab-org/security-products/license-management/-/blob/0b976fcffe0a9b8e80587adb076bcdf279c9331c/config/.bashrc#L49) + +### Image tag[](#image-tag "Permalink") + +如[Docker Official Images](https://github.com/docker-library/official-images#tags-and-aliases)项目中所述,强烈建议给版本号标签起别名,这使用户可以轻松地引用特定系列的"最新"版本. 另请参阅[Docker 标记:标记和版本化 Docker 映像的最佳实践](https://docs.microsoft.com/en-us/archive/blogs/stevelasker/docker-tagging-best-practices-for-tagging-and-versioning-docker-images) . + +## Command line[](#command-line "Permalink") + +扫描程序是一种命令行工具,它将环境变量作为输入,并生成一个文件,该文件作为报告上载(基于作业定义). 它还会在标准输出和标准错误流上生成文本输出,并以状态码退出. + +### Variables[](#variables "Permalink") + +所有 CI 变量都作为环境变量传递到扫描仪. 扫描的项目由[预定义的 CI 变量](../../ci/variables/README.html)描述. + +#### SAST and Dependency Scanning[](#sast-and-dependency-scanning "Permalink") + +SAST 和依赖项扫描扫描程序必须扫描项目目录中由`CI_PROJECT_DIR`变量指定的文件. + +#### Container Scanning[](#container-scanning "Permalink") + +为了与 GitLab 的官方 Container Scanning 一致,扫描程序必须扫描 Docker 映像,其名称和标记分别由`CI_APPLICATION_REPOSITORY`和`CI_APPLICATION_TAG`给出. + +如果未提供, `CI_APPLICATION_REPOSITORY`应该默认为`$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` ,这是预定义的 CI 变量的组合. `CI_APPLICATION_TAG`应该默认为`CI_COMMIT_SHA` . + +扫描程序应使用变量`DOCKER_USER`和`DOCKER_PASSWORD`登录 Docker 注册表. 如果未定义它们,则扫描程序应使用`CI_REGISTRY_USER`和`CI_REGISTRY_PASSWORD`作为默认值. + +#### Configuration files[](#configuration-files "Permalink") + +尽管扫描程序可以使用`CI_PROJECT_DIR`加载特定的配置文件,但建议将配置公开为环境变量,而不是文件. + +### Output file[](#output-file "Permalink") + +与上载到 GitLab CI / CD 的任何工件一样,由扫描仪生成的安全报告必须写入项目目录中,该目录由`CI_PROJECT_DIR`环境变量指定. + +建议以扫描类型命名输出文件,并使用`gl-`作为前缀. 由于所有安全报告都是 JSON 文件,因此建议使用`.json`作为文件扩展名. 例如,"依赖关系扫描"报告的建议文件名是`gl-dependency-scanning.json` . + +作业定义的[`artifacts:reports`](../../ci/pipelines/job_artifacts.html#artifactsreports)关键字必须与编写"安全性"报告的文件路径一致. 例如,如果 Dependency Scanning 分析器将其报告写入 CI 项目目录,并且此报告文件名为`depscan.json` ,则必须将`artifacts:reports:dependency_scanning`设置为`depscan.json` . + +### Exit code[](#exit-code "Permalink") + +遵循 POSIX 退出代码标准,扫描仪将以 0 表示成功退出,以 1 到 255 之间的任何数字表示退出. 成功还包括发现漏洞的情况. + +使用[Docker-in-Docker 特权模式](../../user/application_security/sast/index.html#requirements)执行扫描作业时,我们保留以下标准退出代码. + +| 协调器退出代码 | Description | +| --- | --- | +| 3 | 没有匹配项,没有兼容的分析仪 | +| 4 | 项目目录为空 | +| 5 | 没有兼容的 Docker 映像 | + +### Logging[](#logging "Permalink") + +扫描程序应记录错误消息和警告,以便用户可以通过查看 CI 扫描作业的日志轻松调查配置错误和集成问题. + +扫描程序可以使用[ANSI 转义码](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors)来着色它们写入 Unix 标准输出和标准错误流的消息的颜色. 我们建议您使用红色报告错误,黄色使用警告,绿色使用通知. 此外,我们建议在错误消息前添加`[ERRO]` ,在警告前添加`[WARN]` ,在通知中添加`[INFO]` . + +#### Logging level[](#logging-level "Permalink") + +如果扫描程序的日志级别低于`SECURE_LOG_LEVEL`变量中设置的级别,则扫描器应筛选出一条日志消息. 例如,当`SECURE_LOG_LEVEL`设置为`error`时,应跳过`info`和`warn`消息. 可接受的值如下,从最高到最低列出: + +* `fatal` +* `error` +* `warn` +* `info` +* `debug` + +建议将`debug`级别用于详细日志记录,这在调试时可能会很有用. `SECURE_LOG_LEVEL`的默认值应设置为`info` . + +#### common logutil package[](#common-logutil-package "Permalink") + +如果您使用[go](https://s0golang0org.icopy.site/)和[common](https://gitlab.com/gitlab-org/security-products/analyzers/common) ,那么建议您使用[logrus](https://github.com/Sirupsen/logrus)和[common 的 logutil 软件包](https://gitlab.com/gitlab-org/security-products/analyzers/common/-/tree/master/logutil)为[logrus](https://github.com/Sirupsen/logrus)配置格式化[程序](https://github.com/Sirupsen/logrus) . 请参阅[logutil README.md](https://gitlab.com/gitlab-org/security-products/analyzers/common/-/tree/master/logutil/README.md) + +## Report[](#report "Permalink") + +该报告是 JSON 文档,其中结合了漏洞和可能的补救措施. + +本文档概述了报告 JSON 格式,以及帮助集成商设置其字段的建议和示例. 该格式在[SAST](../../user/application_security/sast/index.html#reports-json-format) , [依赖项扫描](../../user/application_security/dependency_scanning/index.html#reports-json-format)和[容器扫描](../../user/application_security/container_scanning/index.html#reports-json-format)的文档中进行了广泛描述. + +目前未记录报告 JSON 格式的 DAST 变体. + +### Version[](#version "Permalink") + +This field specifies the version of the report schema you are using. Please reference individual scanner pages for the specific versions to use. + +### Vulnerabilities[](#vulnerabilities "Permalink") + +报告的`vulnerabilities`字段是漏洞对象的数组. + +#### ID[](#id "Permalink") + +`id`字段是漏洞的唯一标识符. 它用于从[修复对象中](#remediations)引用固定的漏洞. 我们建议您生成一个 UUID 并将其用作`id`字段的值. + +#### Category[](#category "Permalink") + +`category`字段的值与报告类型匹配: `dependency_scanning` , `container_scanning` , `sast`和`dast` . + +#### Scanner[](#scanner "Permalink") + +`scanner`字段是一个嵌入人类可读`name`和技术`id` . 该`id`不应与其他集成商提供的其他扫描仪冲突. + +#### Name, message, and description[](#name-message-and-description "Permalink") + +`name`和`message`字段包含该漏洞的简短描述. `description`字段提供更多详细信息. + +`name`字段不受上下文限制,并且不包含有关在何处发现漏洞的`message` ,而`message`可能会重复该位置. + +作为一个直观的示例,此屏幕快照突出显示了在将漏洞作为管道视图的一部分查看时使用这些字段的位置. + +[![Example Vulnerability](img/c7126ad3e897b95ff53bc9300bce4d43.png)](example_vuln.png) + +For instance, a `message` for a vulnerability reported by Dependency Scanning gives information on the vulnerable dependency, which is redundant with the `location` field of the vulnerability. The `name` field is preferred but the `message` field is used when the context/location cannot be removed from the title of the vulnerability. + +为了说明这一点,这是一个由"依赖关系扫描"扫描器报告的示例漏洞对象,并且该`message`重复了`location`字段: + +``` +{ "location": { "dependency": { "package": { "name": "debug" } } }, "name": "Regular Expression Denial of Service", "message": "Regular Expression Denial of Service in debug", "description": "The debug module is vulnerable to regular expression denial of service + when untrusted user input is passed into the `o` formatter. + It takes around 50k characters to block for 2 seconds making this a low severity issue." } +``` + +该`description`可能会解释漏洞的工作方式或提供有关漏洞利用的上下文. 它不应重复漏洞对象的其他字段. 特别是,该`description`不应重复`location` (受影响的对象)或`solution` (如何减轻风险). + +#### Solution[](#solution "Permalink") + +您可以使用`solution`字段来指导用户如何解决已识别的漏洞或减轻风险. 最终用户与此字段进行交互,而 GitLab 会自动处理`remediations`对象. + +#### Identifiers[](#identifiers "Permalink") + +`identifiers`数组描述了检测到的漏洞. 标识符对象的`type`和`value`字段用于判断两个标识符是否相同. 用户界面使用对象的`name`和`url`字段显示标识符. + +建议重新使用 GitLab 扫描仪已经定义的标识符: + +| Identifier | Type | 示例值 | +| --- | --- | --- | +| [CVE](https://cve.mitre.org/cve/) | `cve` | CVE-2019-10086 | +| [CWE](https://cwe.mitre.org/data/index.html) | `cwe` | CWE-1026 | +| [OSVD](https://cve.mitre.org/data/refs/refmap/source-OSVDB.html) | `osvdb` | OSVDB-113928 | +| [USN](https://usn.ubuntu.com/) | `usn` | USN-4234-1 | +| [WASC](http://projects.webappsec.org/Threat-Classification-Reference-Grid) | `wasc` | WASC-19 | +| [RHSA](https://access.redhat.com/errata/#/) | `rhsa` | RHSA-2020:0111 | +| [ELSA](https://linux.oracle.com/security/) | `elsa` | ELSA-2020-0085 | + +上面列出的通用标识符在[公共库](https://gitlab.com/gitlab-org/security-products/analyzers/common)中定义,由 GitLab 维护的分析器共享. 如果需要,您可以[贡献](https://gitlab.com/gitlab-org/security-products/analyzers/common/blob/master/issue/identifier.go)新的通用标识符. 分析人员还可以生成特定于供应商或产品的标识符,这些标识符不属于[公共库](https://gitlab.com/gitlab-org/security-products/analyzers/common) . + +`identifiers`数组的第一项称为主要标识符. 主标识符特别重要,因为当新提交被推送到存储库时,它用于[跟踪漏洞](#tracking-and-merging-vulnerabilities) . 标识符还用于[合并](#tracking-and-merging-vulnerabilities)针对同一提交报告的[重复漏洞](#tracking-and-merging-vulnerabilities) ,但`CWE`和`WASC`除外. + +### Location[](#location "Permalink") + +该`location`指示检测到漏洞的`location` . 位置的格式取决于扫描的类型. + +在内部,GitLab 提取`location`一些属性以生成**位置指纹** ,该**指纹**用于在将新的提交推送到存储库时跟踪漏洞. 用于生成位置指纹的属性还取决于扫描的类型. + +#### Dependency Scanning[](#dependency-scanning "Permalink") + +该`location`依赖关系扫描漏洞是由的`dependency`和`file` . `dependency`对象描述了受影响的`package`和依赖项`version` . `package`嵌入受影响的库/模块的`name` . `file`是声明受影响的依赖项的依赖项文件的路径. + +例如,这是一个影响 npm 软件包[`handlebars`](https://s0www0npmjs0com.icopy.site/package/handlebars)版本`4.0.11`的漏洞的`location`对象: + +``` +{ "file": "client/package.json", "dependency": { "package": { "name": "handlebars" }, "version": "4.0.11" } } +``` + +受影响的依赖项列在`client/package.json` ,该文件由 npm 或 yarn 处理. + +The location fingerprint of a Dependency Scanning vulnerability combines the `file` and the package `name`, so these attributes are mandatory. All other attributes are optional. + +#### Container Scanning[](#container-scanning-1 "Permalink") + +与依赖性扫描相似,容器扫描漏洞的`location`具有`dependency`和`file` . 它还具有一个`operating_system`字段. + +例如,这是一个漏洞对象的`location`对象,该漏洞影响 Debian 软件包`glib2.0`版本`2.50.3-2+deb9u1` `glib2.0` : + +``` +{ "dependency": { "package": { "name": "glib2.0" }, }, "version": "2.50.3-2+deb9u1", "operating_system": "debian:9", "image": "registry.gitlab.com/example/app:latest" } +``` + +在扫描 Docker 镜像`registry.gitlab.com/example/app:latest`时找到受影响的软件包. Docker 映像基于`debian:9` (Debian Stretch). + +容器扫描漏洞的位置指纹结合了`operating_system`和程序包`name` ,因此这些属性是必需的. 该`image`也是必需的. 所有其他属性都是可选的. + +#### SAST[](#sast "Permalink") + +SAST 漏洞的`location`必须具有一个`file`和一个`start_line`字段,分别提供受影响文件的路径和受影响的行号. 它还可能有一个`end_line` ,一个`class`和一个`method` . + +例如,此处是`location`为一个安全漏洞对象发现在线路`41`的`src/main/java/com/gitlab/example/App.java` ,在`generateSecretToken`所述的方法`com.gitlab.security_products.tests.App` Java 类: + +``` +{ "file": "src/main/java/com/gitlab/example/App.java", "start_line": 41, "end_line": 41, "class": "com.gitlab.security_products.tests.App", "method": "generateSecretToken1" } +``` + +SAST 漏洞的位置指纹结合了`file` , `start_line`和`end_line` ,因此这些属性是必需的. 所有其他属性都是可选的. + +### Tracking and merging vulnerabilities[](#tracking-and-merging-vulnerabilities "Permalink") + +用户可以提供有关漏洞的反馈: + +* 如果该漏洞不适用于他们的项目,他们可能会忽略该漏洞 +* 如果存在潜在威胁,他们可能会导致漏洞问题 + +GitLab 跟踪漏洞,以便在将新的 Git 提交推送到存储库时不会丢失用户反馈. 使用以下三个属性的组合来跟踪漏洞: + +* [Report type](#category) +* [Location fingerprint](#location) +* [Primary identifier](#identifiers) + +目前,如果推送新 Git 提交时其位置发生变化,则 GitLab 无法跟踪漏洞,这会导致用户反馈丢失. 例如,如果重命名受影响的文件或受影响的行向下移动,则会丢失用户对 SAST 漏洞的反馈. [问题#7586 中](https://gitlab.com/gitlab-org/gitlab/-/issues/7586)已解决. + +在某些情况下,在同一 CI 管道中执行的多次扫描会导致重复生成,这些重复使用漏洞位置和标识符自动合并. 如果两个漏洞共享相同的[位置指纹](#location)和至少一个[标识符,](#identifiers)则认为这两个漏洞是相同的. 如果两个标识符共享相同的`type`和`id`则它们是相同的. 不考虑使用 CWE 和 WASC 标识符,因为它们描述了漏洞缺陷的类别,但没有描述特定的安全缺陷. + +#### Severity and confidence[](#severity-and-confidence "Permalink") + +`severity`字段描述了漏洞对软件的影响`severity` ,而`confidence`字段描述了漏洞评估的可靠性. 严重性用于对安全性仪表板中的漏洞进行排序. + +严重性的范围从" `Info`到" `Critical` ,但也可以是" `Unknown` . 有效值为: `Unknown` , `Info` , `Low` , `Medium` , `High`或`Critical` + +置信度范围从`Low`到`Confirmed` ,但是如果要忽略此漏洞,也可以是`Unknown` , `Experimental`甚至`Ignore` . 有效值为: `Ignore` , `Unknown` , `Experimental` , `Low` , `Medium` , `High`或`Confirmed` + +`Unknown`值意味着无法获得数据来确定其实际值. 因此,它可能是`high` , `medium`或`low` ,需要进行调查. 我们[提供了](../../user/application_security/sast/analyzers.html#analyzers-data)可用的 SAST 分析仪以及当前可用的数据[的图表](../../user/application_security/sast/analyzers.html#analyzers-data) . + +### Remediations[](#remediations "Permalink") + +报告的" `remediations`字段是补救对象的数组. 每个补救措施都描述了一个补丁,可将其应用来[自动修复](../../user/application_security/#solutions-for-vulnerabilities-auto-remediation)一组漏洞. + +这是包含补救措施的报告示例. + +``` +{ "vulnerabilities": [ { "category": "dependency_scanning", "name": "Regular Expression Denial of Service", "id": "123e4567-e89b-12d3-a456-426655440000", "solution": "Upgrade to new versions.", "scanner": { "id": "gemnasium", "name": "Gemnasium" }, "identifiers": [ { "type": "gemnasium", "name": "Gemnasium-642735a5-1425-428d-8d4e-3c854885a3c9", "value": "642735a5-1425-428d-8d4e-3c854885a3c9" } ] } ], "remediations": [ { "fixes": [ { "id": "123e4567-e89b-12d3-a456-426655440000" } ], "summary": "Upgrade to new version", "diff": "ZGlmZiAtLWdpdCBhL3lhcm4ubG9jayBiL3lhcm4ubG9jawppbmRleCAwZWNjOTJmLi43ZmE0NTU0IDEwMDY0NAotLS0gYS95Y==" } ] } +``` + +#### Summary[](#summary "Permalink") + +`summary`字段概述了如何修复漏洞. 这是必填栏. + +#### Fixed vulnerabilities[](#fixed-vulnerabilities "Permalink") + +`fixes`字段是一组对象,这些对象引用了补救措施所修复的漏洞. `fixes[].id`包含一个固定漏洞的[唯一标识符](#id) . 这是必填栏. + +#### Diff[](#diff "Permalink") + +`diff`字段是 base64 编码的补救代码 diff,与[`git apply`](https://git-scm.com/docs/git-format-patch#_discussion)兼容. 这是必填栏. + +## Limitations[](#limitations "Permalink") + +### Container Scanning[](#container-scanning-2 "Permalink") + +容器扫描当前具有以下限制: + +* 尽管"安全仪表板"可以显示来自多个图像的扫描结果,但是,如果多个漏洞具有相同的指纹,则仅显示该漏洞的第一个实例. 我们正在努力消除这一限制. 您可以关注我们的问题[更改容器扫描的位置指纹](https://gitlab.com/gitlab-org/gitlab/-/issues/215466)问题的进展. +* 不同的扫描程序可能各自报告相同的漏洞,从而导致重复的发现. \ No newline at end of file diff --git a/_book/docs/061.md b/_book/docs/061.md new file mode 100644 index 0000000000000000000000000000000000000000..b22dd5c5f6a7a9c6231cff698010980351dfca8e --- /dev/null +++ b/_book/docs/061.md @@ -0,0 +1,59 @@ +# Badges + +> 原文:[https://docs.gitlab.com/ee/user/project/badges.html](https://docs.gitlab.com/ee/user/project/badges.html) + +* [Project badges](#project-badges) +* [Group badges](#group-badges) +* [Placeholders](#placeholders) +* [API](#api) + +# Badges[](#badges "Permalink") + +在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41174) . + +徽章是呈现有关您的项目的简要信息的统一方法. 它们由一个小图像以及该图像指向的 URL 组成. 徽章的示例可以是[管道状态](../../ci/pipelines/settings.html#pipeline-status-badge) , [测试范围](../../ci/pipelines/settings.html#test-coverage-report-badge)或与项目维护者联系的方式. + +[![Badges on Project overview page](img/0e0e78d03e98ec2ac04952defaba83ff.png)](img/project_overview_badges.png) + +## Project badges[](#project-badges "Permalink") + +维护者或所有者可以将徽章添加到项目中,然后在项目的概述页面上可见. 如果发现必须将相同的徽标添加到多个项目,则可能需要在[组级别](#group-badges)添加它们. + +要将新徽章添加到项目: + +1. 导航到项目的**设置>常规>徽章** . +2. 在"链接"下,输入徽章应指向的 URL,在"徽章图像 URL"下输入应显示的图像的 URL. +3. 通过单击**添加徽章**按钮来提交**徽章** . + +将徽章添加到项目后,您可以在表单下方的列表中看到它. 您可以通过单击旁边的笔图标进行编辑,也可以通过单击垃圾箱图标将其删除. + +与组关联的徽章只能在[组级别](#group-badges)上进行编辑或删除. + +## Group badges[](#group-badges "Permalink") + +可以将徽章添加到组中,然后将在该组下的每个项目的概述页面上看到它们. 在这种情况下,无法在项目级别上对其进行编辑或删除. 如果每个项目需要单独的徽章,请考虑将其添加到[项目级别](#project-badges)或使用[占位符](#placeholders) . + +要将新徽章添加到组: + +1. 导航到组的**"设置">"常规">"徽章"** . +2. 在"链接"下,输入徽章应指向的 URL,在"徽章图像 URL"下输入应显示的图像的 URL. +3. 通过单击**添加徽章**按钮来提交**徽章** . + +将徽章添加到组后,您可以在表格下方的列表中看到它. 您可以通过单击徽章旁边的笔图标来编辑徽章,也可以通过单击垃圾箱图标来删除徽章. + +与项目直接关联的徽章可以在[项目级别](#project-badges)上配置. + +## Placeholders[](#placeholders "Permalink") + +徽章指向的 URL 以及图像 URL 可以包含占位符,在显示徽章时将对其进行评估. 可以使用以下占位符: + +* `%{project_path}` :包含父组的项目的路径 +* `%{project_id}` :与项目关联的数据库 ID +* `%{default_branch}` :为项目存储库配置的默认分支名称 +* `%{commit_sha}` :对项目存储库的默认分支的最新提交的 ID + +**Note:** Placeholders allow badges to expose otherwise-private information, such as the default branch or commit SHA when the project is configured to have a private repository. This is by design, as badges are intended to be used publicly. Avoid using these placeholders if the information is sensitive. + +## API[](#api "Permalink") + +您还可以通过 GitLab API 配置徽章. 与设置一样,在[项目级别](../../api/project_badges.html)和[组级别的](../../api/group_badges.html)徽章端点之间也有所区别. \ No newline at end of file diff --git a/_book/docs/062.md b/_book/docs/062.md new file mode 100644 index 0000000000000000000000000000000000000000..26d06c4d2c86bce8aab8ad72d0d005a8082717fe --- /dev/null +++ b/_book/docs/062.md @@ -0,0 +1,56 @@ +# Bulk editing issues and merge requests at the project level + +> 原文:[https://docs.gitlab.com/ee/user/project/bulk_editing.html](https://docs.gitlab.com/ee/user/project/bulk_editing.html) + +* [Bulk edit issues at the project level](#bulk-edit-issues-at-the-project-level) +* [Bulk edit merge requests at the project level](#bulk-edit-merge-requests-at-the-project-level) + +# Bulk editing issues and merge requests at the project level[](#bulk-editing-issues-and-merge-requests-at-the-project-level "Permalink") + +**注意:**批量编辑问题,史诗和合并请求在**组级别**也可用. 有关更多详细信息,请参阅[在组级别批量编辑问题,史诗和合并请求](../group/bulk_editing/index.html) . + +如果要跨多个问题更新属性或合并请求,则可以通过批量编辑它们,即一起编辑它们来完成. + +[![Bulk editing](img/5b2694c5d35f9fdb42b43bb1f38ec29c.png)](img/bulk-editing_v13_2.png) + +## Bulk edit issues at the project level[](#bulk-edit-issues-at-the-project-level "Permalink") + +**注意:**您需要具有[Reporter 或更高](../permissions.html)级别的权限才能管理问题. + +When bulk editing issues in a project, you can edit the following attributes: + +* 状态(打开/关闭) +* Assignee +* Epic(在[GitLab Premium](https://about.gitlab.com/pricing/) 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/210470) ) +* Milestone +* Labels +* 健康状况(在[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/218395) ) +* Subscriptions + +要同时更新多个项目问题: + +1. 在一个项目中,转到 **问题>列表** . +2. 点击**编辑问题** . 屏幕右侧的侧边栏显示,其中包含可编辑的字段. +3. 选中要编辑的每个问题旁边的复选框. +4. 从边栏中选择适当的字段及其值. +5. Click **全部更新**. + +## Bulk edit merge requests at the project level[](#bulk-edit-merge-requests-at-the-project-level "Permalink") + +**注意:**您需要[开发人员或更高](../permissions.html)级别的权限才能管理合并请求. + +在项目中批量编辑合并请求时,可以编辑以下属性: + +* 状态(打开/关闭) +* Assignee +* Milestone +* Labels +* Subscriptions + +要同时更新多个项目合并请求: + +1. 在一个项目中,转到 **合并请求** . +2. 单击**编辑合并请求** . 屏幕右侧的侧边栏显示,其中包含可编辑的字段. +3. 选中要编辑的每个合并请求旁边的复选框. +4. 从边栏中选择适当的字段及其值. +5. Click **全部更新**. \ No newline at end of file diff --git a/_book/docs/063.md b/_book/docs/063.md new file mode 100644 index 0000000000000000000000000000000000000000..5ddfd6a64ae9534904341b0597a3e3a27b45f3b9 --- /dev/null +++ b/_book/docs/063.md @@ -0,0 +1,151 @@ +# Code Owners + +> 原文:[https://docs.gitlab.com/ee/user/project/code_owners.html](https://docs.gitlab.com/ee/user/project/code_owners.html) + +* [Introduction](#introduction) +* [Why is this useful?](#why-is-this-useful) +* [How to set up Code Owners](#how-to-set-up-code-owners) +* [Approvals by Code Owners](#approvals-by-code-owners) +* [The syntax of Code Owners files](#the-syntax-of-code-owners-files) + +# Code Owners[](#code-owners-starter "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6916) . +* [支持](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53182)在 GitLab Starter 12.1 中添加的[组名称空间](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53182) . +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4418)了用于合并请求批准的代码所有者. + +## Introduction[](#introduction "Permalink") + +在为项目做贡献时,通常很难找出谁应该审查或批准合并请求. 此外,如果您对特定文件或代码块有疑问,可能很难知道从谁那里找到答案. + +GitLab 代码所有者是一项功能,用于定义谁拥有存储库中的特定文件或路径,从而允许其他用户了解谁对每个文件或路径负责. + +## Why is this useful?[](#why-is-this-useful "Permalink") + +代码所有者允许使用版本控制的单个真实文件源,该文件概述了拥有存储库中某些文件或路径的确切 GitLab 用户或组. 可以在合并请求批准过程中利用代码所有者,该过程可以简化为给定合并请求找到合适的审阅者和批准者的过程. + +在大型组织或流行的开源项目中,如果您遇到的问题可能与代码审查或合并请求批准无关,则代码所有者还可以帮助您了解与谁联系. + +## How to set up Code Owners[](#how-to-set-up-code-owners "Permalink") + +您可以使用`CODEOWNERS`文件来指定负责存储库中某些文件的用户或[共享组](members/share_project_with_groups.html) . + +您可以在三个位置选择并添加`CODEOWNERS`文件: + +* 到存储库的根目录 +* 在`.gitlab/`目录中 +* 在`docs/`目录中 + +The `CODEOWNERS` file is scoped to a branch, which means that with the introduction of new files, the person adding the new content can specify themselves as a code owner, all before the new changes get merged to the default branch. + +当一个文件与`CODEOWNERS`文件中的多个条目匹配时,与该文件匹配的上一个模式的用户将显示在给定文件的 Blob 页面上. 例如,您具有以下`CODEOWNERS`文件: + +``` +README.md @user1 + +# This line would also match the file README.md +*.md @user2 +``` + +将显示`README.md`的用户为`@user2` . + +## Approvals by Code Owners[](#approvals-by-code-owners "Permalink") + +将"代码所有者"设置为项目后,可以将其配置为用于合并请求批准: + +* As [merge request eligible approvers](merge_requests/merge_request_approvals.html#code-owners-as-eligible-approvers). +* 根据需要批准[分支机构](protected_branches.html#protected-branches-approval-by-code-owners-premium) . + +**注意** :为了批准合并请求,需要开发人员或更高[权限](../permissions.html) . + +设置后,"代码所有者"将显示在合并请求小部件中: + +[![MR widget - Code Owners](img/6deba2d9890a294d17564cce39fcbaef.png)](img/code_owners_mr_widget_v12_4.png) + +尽管`CODEOWNERS`文件除了可以用于合并请求[批准规则之外](merge_requests/merge_request_approvals.html#approval-rules) ,还可以用作合并请求批准的唯一驱动程序(不使用[批准规则](merge_requests/merge_request_approvals.html#approval-rules) ). 为此,请在上面指定的三个位置之一中创建文件,并将代码所有者设置为[受保护分支的](protected_branches.html#protected-branches-approval-by-code-owners-premium)必需批准者. 使用[代码所有者文件的语法](code_owners.html#the-syntax-of-code-owners-files)来指定实际所有者和精细权限. + +结合使用"代码所有者"和" [受保护的分支机构批准",](protected_branches.html#protected-branches-approval-by-code-owners-premium)将防止在`CODEOWNERS`文件中未指定的任何用户推送对指定文件/路径的更改,即使其角色包含在" **允许推送"**列中. 这允许采用更具包容性的推送策略,因为管理员不必限制开发人员直接将其推送到受保护的分支,而可以将推送限制到某些需要代码所有者审查的文件. + +## The syntax of Code Owners files[](#the-syntax-of-code-owners-files "Permalink") + +可以使用与`.gitignore`文件中使用的相同类型的模式来指定文件,然后使用一个或多个用户的`@username`或电子邮件或应作为文件所有者的一个或多个组的`@name`进行指定. 必须将组添加为[项目的成员](members/index.html) ,否则它们将被忽略. + +从[GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/32432)开始,您现在可以将项目组层次结构中的组或子组指定为潜在的代码所有者. + +例如,考虑给定项目的以下层次结构: + +``` +group >> sub-group >> sub-subgroup >> myproject >> file.md +``` + +以下任何组都可以被指定为代码所有者: + +* `@group` +* `@group/sub-group` +* `@group/sub-group/sub-subgroup` + +此外,使用" **成员"**工具邀请到项目的任何组也将被视为合格的代码所有者. + +定义路径的顺序很重要:与给定路径匹配的最后一个模式将用于查找代码所有者. + +以`#`开头的行表示注释. 需要使用`\#`对其进行转义,以寻址其名称以`#`开头的文件. + +Example `CODEOWNERS` file: + +``` +# This is an example of a code owners file +# lines starting with a `#` will be ignored. + +# app/ @commented-rule + +# We can specify a default match using wildcards: +* @default-codeowner + +# We can also specify "multiple tab or space" separated codeowners: +* @multiple @code @owners + +# Rules defined later in the file take precedence over the rules +# defined before. +# This will match all files for which the file name ends in `.rb` +*.rb @ruby-owner + +# Files with a `#` can still be accessed by escaping the pound sign +\#file_with_pound.rb @owner-file-with-pound + +# Multiple codeowners can be specified, separated by spaces or tabs +# In the following case the CODEOWNERS file from the root of the repo +# has 3 code owners (@multiple @code @owners) +CODEOWNERS @multiple @code @owners + +# Both usernames or email addresses can be used to match +# users. Everything else will be ignored. For example this will +# specify `@legal` and a user with email `janedoe@gitlab.com` as the +# owner for the LICENSE file +LICENSE @legal this_does_not_match janedoe@gitlab.com + +# Group names can be used to match groups and nested groups to specify +# them as owners for a file +README @group @group/with-nested/subgroup + +# Ending a path in a `/` will specify the code owners for every file +# nested in that directory, on any level +/docs/ @all-docs + +# Ending a path in `/*` will specify code owners for every file in +# that directory, but not nested deeper. This will match +# `docs/index.md` but not `docs/projects/index.md` +/docs/* @root-docs + +# This will make a `lib` directory nested anywhere in the repository +# match +lib/ @lib-owner + +# This will only match a `config` directory in the root of the +# repository +/config/ @config-owner + +# If the path contains spaces, these need to be escaped like this: +path\ with\ spaces/ @space-owner +``` \ No newline at end of file diff --git a/_book/docs/064.md b/_book/docs/064.md new file mode 100644 index 0000000000000000000000000000000000000000..737b1641fca87e2c818edd9817b1195b844bc7ea --- /dev/null +++ b/_book/docs/064.md @@ -0,0 +1,10 @@ +# Compliance + +> 原文:[https://docs.gitlab.com/ee/user/compliance/](https://docs.gitlab.com/ee/user/compliance/) + +# Compliance[](#compliance-ultimate "Permalink") + +GitLab 提供的合规性工具可让您随时关注项目的各个方面. 可以使用以下合规工具: + +* [Compliance Dashboard](compliance_dashboard/index.html) :查看组中所有项目的最近合并请求活动. 这使您可以查看合并请求是否被批准以及由谁批准. +* [许可证合规性](license_compliance/index.html) :在项目的依存关系中搜索其许可证. 这样,您可以确定项目依赖项的许可证是否与项目的许可证兼容. \ No newline at end of file diff --git a/_book/docs/065.md b/_book/docs/065.md new file mode 100644 index 0000000000000000000000000000000000000000..2de665c3fec4d8fea1c0d9e65896fe772a34d3d7 --- /dev/null +++ b/_book/docs/065.md @@ -0,0 +1,639 @@ +# License Compliance + +> 原文:[https://docs.gitlab.com/ee/user/compliance/license_compliance/](https://docs.gitlab.com/ee/user/compliance/license_compliance/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Supported languages and package managers](#supported-languages-and-package-managers) + * [Experimental support](#experimental-support) +* [Requirements](#requirements) +* [Configuration](#configuration) + * [Available variables](#available-variables) + * [Installing custom dependencies](#installing-custom-dependencies) + * [Overriding the template](#overriding-the-template) + * [Configuring Maven projects](#configuring-maven-projects) + * [Using private Maven repos](#using-private-maven-repos) + * [Selecting the version of Python](#selecting-the-version-of-python) + * [Custom root certificates for Python](#custom-root-certificates-for-python) + * [Using private Python repos](#using-private-python-repos) + * [Configuring NPM projects](#configuring-npm-projects) + * [Using private NPM registries](#using-private-npm-registries) + * [Custom root certificates for NPM](#custom-root-certificates-for-npm) + * [Configuring Yarn projects](#configuring-yarn-projects) + * [Using private Yarn registries](#using-private-yarn-registries) + * [Custom root certificates for Yarn](#custom-root-certificates-for-yarn) + * [Configuring Bower projects](#configuring-bower-projects) + * [Using private Bower registries](#using-private-bower-registries) + * [Custom root certificates for Bower](#custom-root-certificates-for-bower) + * [Using private Bundler registries](#using-private-bundler-registries) + * [Custom root certificates for Bundler](#custom-root-certificates-for-bundler) + * [Configuring Conan projects](#configuring-conan-projects) + * [Using private Conan registries](#using-private-conan-registries) + * [Custom root certificates for Conan](#custom-root-certificates-for-conan) + * [Configuring Go projects](#configuring-go-projects) + * [Using private Go registries](#using-private-go-registries) + * [Custom root certificates for Go](#custom-root-certificates-for-go) + * [Using private NuGet registries](#using-private-nuget-registries) + * [Custom root certificates for NuGet](#custom-root-certificates-for-nuget) + * [Migration from `license_management` to `license_scanning`](#migration-from-license_management-to-license_scanning) +* [Running License Compliance in an offline environment](#running-license-compliance-in-an-offline-environment) + * [Requirements for offline License Compliance](#requirements-for-offline-license-compliance) + * [Make GitLab License Compliance analyzer images available inside your Docker registry](#make-gitlab-license-compliance-analyzer-images-available-inside-your-docker-registry) + * [Set License Compliance CI job variables to use local License Compliance analyzers](#set-license-compliance-ci-job-variables-to-use-local-license-compliance-analyzers) +* [License list](#license-list) +* [Policies](#policies) + * [Enabling License Approvals within a project](#enabling-license-approvals-within-a-project) +* [Troubleshooting](#troubleshooting) + * [`ERROR -- : asdf: No preset version installed for command`](#error-----asdf-no-preset-version-installed-for-command) + +# License Compliance[](#license-compliance-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5483) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0. + +## Overview[](#overview "Permalink") + +如果您使用的是[GitLab CI / CD](../../../ci/README.html) ,则可以使用许可证合规性在项目依赖项中搜索其许可证. + +您可以通过[将作业包括](#configuration)在现有的`.gitlab-ci.yml`文件中,或者隐式使用[Auto DevOps](../../../topics/autodevops/index.html)提供的[自动](../../../topics/autodevops/index.html) [许可证合规性](../../../topics/autodevops/stages.html#auto-license-compliance-ultimate)来利用[许可证合规性](../../../topics/autodevops/stages.html#auto-license-compliance-ultimate) . + +GitLab 检查"许可证合规性"报告,比较源分支机构和目标分支机构之间的许可证,并在合并请求中显示信息. 拒绝许可证将有清晰可见的`x`红色图标旁边还有哪些需要从你决定新的许可证. 此外,您可以在项目的许可证合规性政策部分中[手动允许或拒绝](#policies)许可证. + +**注意:**如果许可证合规性报告没有可比较的内容,则合并请求区域中将不会显示任何信息. 第一次在`.gitlab-ci.yml`添加`license_scanning`作业时就是这种情况. 连续的合并请求将具有可比性,并且许可证合规性报告将正确显示. + +[![License Compliance Widget](img/89c2a0a388333182ff39563629933a87.png)](img/license_compliance_v13_0.png) + +如果您是项目或组维护者,则可以单击许可证以选择允许或拒绝. + +[![License approval decision](img/28ec7a2f016b77873dfadd5ab59c447b.png)](img/license_compliance_decision_v13_0.png) + +当 GitLab 检测到**拒绝的**许可证时,您可以在[许可证列表中](#license-list)查看它. + +[![License List](img/dc75662feab34ea9fa5cb187a2d77739.png)](img/license_list_v13_0.png) + +您可以从" [策略"](#policies)选项卡查看和修改现有策略. + +[![Edit Policy](img/e545dd77cf453f5a97873da4f0083ebb.png)](img/policies_maintainer_edit_v13_2.png) + +## Use cases[](#use-cases "Permalink") + +It helps you find what licenses your project uses in its dependencies, and decide for each of then whether to allow it or forbid it. For example, your application is using an external (open source) library whose license is incompatible with yours. + +## Supported languages and package managers[](#supported-languages-and-package-managers "Permalink") + +支持以下语言和程序包管理器. + +| Language | 包装经理 | 扫描工具 | +| --- | --- | --- | +| JavaScript | [Bower](https://bower.io/), [npm](https://s0www0npmjs0com.icopy.site/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Go | [Godep](https://github.com/tools/godep), [go mod](https://github.com/golang/go/wiki/Modules) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Java | [Gradle](https://s0gradle0org.icopy.site/), [Maven](https://maven.apache.org/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| .NET | [Nuget](https://www.nuget.org/) (.NET Framework 通过[mono 项目](https://www.mono-project.com/)支持.目前不支持 Windows 特定的依赖项.) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Python | [pip](https://pip.pypa.io/en/stable/) (通过[requirements.txt](https://pip.pypa.io/en/stable/user_guide/#requirements-files)和[Pipfile.lock](https://github.com/pypa/pipfile#pipfilelock)支持 Python.) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Ruby | [gem](https://rubygems.org/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| 的 Objective-C,斯威夫特 | [Carthage](https://github.com/Carthage/Carthage) | [License Finder](https://github.com/pivotal/LicenseFinder) | + +**Note:** + +不支持 Java 8 和 Gradle 1.x 项目. + +### Experimental support[](#experimental-support "Permalink") + +[实验性支持](https://github.com/pivotal/LicenseFinder#experimental-project-types)以下语言和程序包管理器,这意味着报告的许可证可能不完整或不准确. + +| Language | 包装经理 | 扫描工具 | +| --- | --- | --- | +| JavaScript | [yarn](https://yarnpkg.com/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Go | 去获取,gvt,滑行,部门,垃圾,govendor | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Erlang | [rebar](https://www.rebar3.org/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| 的 Objective-C,斯威夫特 | [CocoaPods](https://cocoapods.org/) v0.39 及以下 | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Elixir | [mix](https://s0elixir-lang0org.icopy.site/getting-started/mix-otp/introduction-to-mix.html) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| C++/C | [conan](https://conan.io/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Scala | [sbt](https://www.scala-sbt.org/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Rust | [cargo](https://crates.io) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| PHP | [composer](https://s0getcomposer0org.icopy.site/) | [License Finder](https://github.com/pivotal/LicenseFinder) | + +## Requirements[](#requirements "Permalink") + +要运行许可证合规性扫描作业,您需要具有[`docker` executor 的](https://docs.gitlab.com/runner/executors/docker.html) GitLab Runner. + +## Configuration[](#configuration "Permalink") + +对于 GitLab 12.8 及更高版本,要启用许可证合规性,您必须[包括](../../../ci/yaml/README.html#includetemplate)在 GitLab 安装过程中提供的[`License-Scanning.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml) . 对于从 11.9 到 12.7 的较旧版本的 GitLab,您必须[包括](../../../ci/yaml/README.html#includetemplate) [`License-Management.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml) . 对于 11.9 之前的 GitLab 版本,您可以复制和使用该模板中定义的作业. + +**注意:** GitLab 13.0 删除了`License-Management.gitlab-ci.yml`模板. 请改用`License-Scanning.gitlab-ci.yml` . + +将以下内容添加到您的`.gitlab-ci.yml`文件中: + +``` +include: + - template: License-Scanning.gitlab-ci.yml +``` + +The included template will create a `license_scanning` job in your CI/CD pipeline and scan your dependencies to find their licenses. + +**注意:**在 GitLab 12.8 之前, `license_scanning`作业名为`license_management` . GitLab 13.0 删除了`license_management`作业,因此建议您迁移到`license_scanning`作业,并使用新的`License-Scanning.gitlab-ci.yml`模板. + +结果将保存为" [许可证合规性"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportslicense_scanning-ultimate) ,您以后可以下载和分析该[工件](../../../ci/pipelines/job_artifacts.html#artifactsreportslicense_scanning-ultimate) . 由于实施限制,我们始终采用最新的许可证合规性工件. 在后台, [GitLab 许可证合规性 Docker 映像](https://gitlab.com/gitlab-org/security-products/license-management)用于检测语言/框架,进而分析许可证. + +可以使用`.gitlab-ci.yml`的[`variables`](../../../ci/yaml/README.html#variables)参数通过[环境变量](#available-variables)来更改许可合规性设置. + +### Available variables[](#available-variables "Permalink") + +可以使用环境变量来配置许可证合规性. + +| 环境变量 | Required | Description | +| --- | --- | --- | +| `ADDITIONAL_CA_CERT_BUNDLE` | no | 捆绑的可信 CA 证书(当前在 Pip,Pipenv,Maven,Gradle,Yarn 和 NPM 项目中受支持). | +| `ASDF_JAVA_VERSION` | no | 用于扫描的 Java 版本. | +| `ASDF_NODEJS_VERSION` | no | 用于扫描的 Node.js 版本. | +| `ASDF_PYTHON_VERSION` | no | 用于扫描的 Python 版本. | +| `ASDF_RUBY_VERSION` | no | 用于扫描的 Ruby 版本. | +| `GRADLE_CLI_OPTS` | no | gradle 可执行文件的其他参数. 如果未提供,则默认为`--exclude-task=test` . | +| `LICENSE_FINDER_CLI_OPTS` | no | `license_finder`可执行文件的其他参数. 例如,如果您的项目同时在不同的目录中存储了 Golang 和 Ruby 代码,并且您只想扫描 Ruby 代码,则可以更新`.gitlab-ci-yml`模板以指定要扫描的项目目录,例如`LICENSE_FINDER_CLI_OPTS: '--debug --aggregate-paths=. ruby'` `LICENSE_FINDER_CLI_OPTS: '--debug --aggregate-paths=. ruby'` . | +| `LM_JAVA_VERSION` | no | Java 版本. 如果设置为`11` ,则 Maven 和 Gradle 使用 Java 11 而不是 Java 8. | +| `LM_PYTHON_VERSION` | no | Python 版本. 如果设置为`3` ,则将使用 Python 3 而非 Python 2.7 安装依赖项. | +| `MAVEN_CLI_OPTS` | no | mvn 可执行文件的附加参数. 如果未提供,则默认为`-DskipTests` . | +| `PIP_INDEX_URL` | no | Python 软件包索引的基本 URL(默认值: `https://pypi.org/simple/` : `https://pypi.org/simple/` ). | +| `SECURE_ANALYZERS_PREFIX` | no | 设置 Docker 注册表基地址以从中下载分析器. | +| `SETUP_CMD` | no | 依赖项安装的自定义设置(实验性). | + +### Installing custom dependencies[](#installing-custom-dependencies "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.4 中引入. + +`license_management`映像已经嵌入了许多自动检测脚本,语言和软件包. 但是,几乎不可能涵盖所有项目的所有案例. 这就是为什么有时需要安装额外的程序包,或在项目自动设置中进行额外步骤的原因,例如证书的下载和安装. 为此,可以将`LICENSE_MANAGEMENT_SETUP_CMD`环境变量与所需的命令一起传递到容器,以在许可证检测之前运行. + +如果存在,则此变量将覆盖安装应用程序所有软件包所必需的设置步骤(例如:对于具有`Gemfile`的项目,设置步骤可以为`bundle install` ). + +例如: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +variables: + LICENSE_MANAGEMENT_SETUP_CMD: sh my-custom-install-script.sh +``` + +在此示例中, `my-custom-install-script.sh`是项目根目录下的 shell 脚本. + +### Overriding the template[](#overriding-the-template "Permalink") + +**弃用:**从 GitLab 13.0 开始,不再支持[`only`和`except`](../../../ci/yaml/README.html#onlyexcept-basic)的使用. 覆盖模板时,必须使用[`rules`](../../../ci/yaml/README.html#rules) . + +如果要覆盖作业定义(例如,更改诸如`variables`或`dependencies`类的属性),则需要在包含模板之后声明一个`license_scanning`作业,并在其下指定任何其他键. 例如: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + CI_DEBUG_TRACE: "true" +``` + +### Configuring Maven projects[](#configuring-maven-projects "Permalink") + +许可证合规性工具提供了一个`MAVEN_CLI_OPTS`环境变量,该变量可以保存命令行参数,以传递给在`MAVEN_CLI_OPTS`执行的`mvn install`命令. 随意使用它来定制 Maven 执行. 例如: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + MAVEN_CLI_OPTS: --debug +``` + +`mvn install`过所有的运行[构建生命周期](http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html)前阶段的`install` ,包括`test` . 出于许可证扫描的目的,运行单元测试不是直接必要的,并且会浪费时间,因此可以通过将`MAVEN_CLI_OPTS`的默认值`MAVEN_CLI_OPTS`为`-DskipTests`跳过它. 如果要提供自定义的`MAVEN_CLI_OPTS`并同时跳过测试,请不要忘记将`-DskipTests`显式添加到您的选项中. 如果在`mvn install`期间仍然需要运行测试,则将`-DskipTests=false`添加到`MAVEN_CLI_OPTS` . + +#### Using private Maven repos[](#using-private-maven-repos "Permalink") + +如果您有需要登录凭据的私有 Maven 存储库,则可以使用`MAVEN_CLI_OPTS`环境变量. + +阅读更多有关[如何使用私有 Maven 仓库的信息](../../application_security/index.html#using-private-maven-repos) . + +您还可以使用`MAVEN_CLI_OPTS`连接到使用自签名或内部受信任证书的受信任 Maven 存储库. 例如: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + MAVEN_CLI_OPTS: -Dmaven.wagon.http.ssl.allowall=true -Dmaven.wagon.http.ssl.ignore.validity.dates=true -Dmaven.wagon.http.ssl.insecure=true +``` + +或者,您可以使用 Java 密钥存储来验证 TLS 连接. 有关如何生成密钥存储文件的说明,请参阅《 [Maven 通过身份验证的 HTTPS 进行远程存储库访问指南》](http://maven.apache.org/guides/mini/guide-repository-ssl.html) . + +### Selecting the version of Python[](#selecting-the-version-of-python "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0 中[引入](https://gitlab.com/gitlab-org/security-products/license-management/-/merge_requests/36) . +* 在[GitLab 12.2 中](https://gitlab.com/gitlab-org/gitlab/-/issues/12032) ,Python 3.5 成为默认设置. +* 在[GitLab 12.7 中](https://gitlab.com/gitlab-org/security-products/license-management/-/merge_requests/101) ,Python 3.8 成为默认设置. + +默认情况下,许可证合规性使用 Python 3.8 和 pip 19.1\. 如果您的项目需要 Python 2,则可以通过将`LM_PYTHON_VERSION`环境变量设置为`2`来切换到 Python 2.7 和 pip 10.0. + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + LM_PYTHON_VERSION: 2 +``` + +### Custom root certificates for Python[](#custom-root-certificates-for-python "Permalink") + +您可以使用`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables)提供自定义根证书来完成 TLS 验证. + +要绕过 TLS 验证,可以使用自定义[`pip.conf`](https://pip.pypa.io/en/stable/user_guide/#config-file)文件来配置受信任的主机. + +以下`gitlab-ci.yml`文件使用[`before_script`](../../../ci/yaml/README.html#before_script-and-after_script)注入自定义[`pip.conf`](https://pip.pypa.io/en/stable/user_guide/#config-file) : + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + PIP_INDEX_URL: 'https://pypi.example.com/simple/' + before_script: + - mkdir -p ~/.config/pip/ + - cp pip.conf ~/.config/pip/pip.conf +``` + +[`pip.conf`](https://pip.pypa.io/en/stable/reference/pip/)允许您指定[受信任主机](https://pip.pypa.io/en/stable/reference/pip/#cmdoption-trusted-host)的列表: + +``` +[global] +trusted-host = pypi.example.com +``` + +#### Using private Python repos[](#using-private-python-repos "Permalink") + +如果您拥有专用的 Python 存储库,则可以使用`PIP_INDEX_URL` [环境变量](#available-variables)来指定其位置. 也可以提供自定义的`pip.conf`进行[其他配置](#custom-root-certificates-for-python) . + +### Configuring NPM projects[](#configuring-npm-projects "Permalink") + +您可以使用[`.npmrc`](https://s0docs0npmjs0com.icopy.site/configuring-npm/npmrc.html)文件配置 NPM 项目. + +#### Using private NPM registries[](#using-private-npm-registries "Permalink") + +如果您有私有 NPM 注册表,则可以使用[`registry`](https://s0docs0npmjs0com.icopy.site/using-npm/config)设置来指定其位置. + +例如: + +``` +registry = https://npm.example.com +``` + +#### Custom root certificates for NPM[](#custom-root-certificates-for-npm "Permalink") + +您可以使用`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables)提供自定义根证书来完成 TLS 验证. + +要禁用 TLS 验证,您可以提供[`strict-ssl`](https://s0docs0npmjs0com.icopy.site/using-npm/config)设置. + +例如: + +``` +strict-ssl = false +``` + +### Configuring Yarn projects[](#configuring-yarn-projects "Permalink") + +您可以使用[`.yarnrc.yml`](https://yarnpkg.com/configuration/yarnrc)文件配置 Yarn 项目. + +#### Using private Yarn registries[](#using-private-yarn-registries "Permalink") + +如果您有专用的 Yarn 注册表,则可以使用[`npmRegistryServer`](https://yarnpkg.com/configuration/yarnrc#npmRegistryServer)设置来指定其位置. + +例如: + +``` +npmRegistryServer: "https://npm.example.com" +``` + +#### Custom root certificates for Yarn[](#custom-root-certificates-for-yarn "Permalink") + +您可以使用`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables)提供自定义根证书来完成 TLS 验证. + +### Configuring Bower projects[](#configuring-bower-projects "Permalink") + +您可以使用[`.bowerrc`](https://bower.io/docs/config/#bowerrc-specification)文件配置 Bower 项目. + +#### Using private Bower registries[](#using-private-bower-registries "Permalink") + +如果您有专用的 Bower 注册表,则可以使用[`registry`](https://bower.io/docs/config/#bowerrc-specification)设置来指定其位置. + +例如: + +``` +{ + "registry": "https://registry.bower.io" +} +``` + +#### Custom root certificates for Bower[](#custom-root-certificates-for-bower "Permalink") + +您可以使用`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables)或在[`.bowerrc`](https://bower.io/docs/config/#bowerrc-specification)文件中指定`ca`设置来提供自定义根证书来完成 TLS 验证. + +#### Using private Bundler registries[](#using-private-bundler-registries "Permalink") + +如果您有私人的 Bundler 注册表,则可以使用[`source`](https://bundler.io/man/gemfile.5.html#GLOBAL-SOURCES)设置来指定其位置. + +例如: + +``` +source "https://gems.example.com" +``` + +#### Custom root certificates for Bundler[](#custom-root-certificates-for-bundler "Permalink") + +您可以使用`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables)或在作业定义中指定[`BUNDLE_SSL_CA_CERT`](https://bundler.io/v2.0/man/bundle-config.1.html) [环境变量](../../../ci/variables/README.html#custom-environment-variables)来提供自定义根证书来完成 TLS 验证. + +### Configuring Conan projects[](#configuring-conan-projects "Permalink") + +您可以通过将`.conan`目录添加到项目根目录来配置[Conan](https://conan.io/)项目. 项目根用作[`CONAN_USER_HOME`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-user-home) . + +Consult the [Conan](https://docs.conan.io/en/latest/reference/config_files/conan.conf.html#conan-conf) documentation for a list of settings that you can apply. + +`license_scanning`作业在[Debian 10](https://www.debian.org/releases/buster/) Docker 映像中运行. 提供的映像附带了一些构建工具,例如[CMake](https://cmake.org/)和[GCC](https://gcc.gnu.org/) . 但是,默认情况下不支持所有项目类型. 要安装编译依赖关系所需的其他工具,请使用[`before_script`](../../../ci/yaml/README.html#before_script-and-after_script)使用[`apt`](https://wiki.debian.org/PackageManagementTools)软件包管理器安装必要的构建工具. 有关完整列表,请参阅[柯南文档](https://docs.conan.io/en/latest/introduction.html#all-platforms-all-build-systems-and-compilers) . + +默认的[柯南](https://conan.io/)配置将[`CONAN_LOGIN_USERNAME`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-login-username-conan-login-username-remote-name)设置为`ci_user` ,并将[`CONAN_PASSWORD`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-password-conan-password-remote-name)绑定到[`CI_JOB_TOKEN`](../../../ci/variables/predefined_variables.html)以用于正在运行的作业. 如果在`.conan/remotes.json`文件中指定了 GitLab 遥控器,则这允许 Conan 项目从[GitLab 科南存储库中](../../packages/conan_repository/#fetching-conan-package-information-from-the-gitlab-package-registry)获取软件包. + +要覆盖默认凭据,请指定一个[`CONAN_LOGIN_USERNAME_{REMOTE_NAME}`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-login-username-conan-login-username-remote-name)与`.conan/remotes.json`文件中指定的远程名称匹配. + +**注意:**不支持[MSBuild](https://github.com/mono/msbuild#microsoftbuild-msbuild)项目. `license_scanning`映像随[Mono](https://www.mono-project.com/)和[MSBuild 一起提供](https://github.com/mono/msbuild#microsoftbuild-msbuild) . 可能需要其他设置才能生成此项目配置的软件包. + +#### Using private Conan registries[](#using-private-conan-registries "Permalink") + +默认情况下, [柯南](https://conan.io/)使用[柯南](https://conan.io/) `conan-center`遥控器. 例如: + +``` +{ "remotes": [ { "name": "conan-center", "url": "https://conan.bintray.com", "verify_ssl": true } ] } +``` + +要从备用远程获取依赖项,请在`.conan/remotes.json`指定该远程. 例如: + +``` +{ "remotes": [ { "name": "gitlab", "url": "https://gitlab.com/api/v4/packages/conan", "verify_ssl": true } ] } +``` + +如果需要使用凭据进行身份验证,则可以按照[`CONAN_LOGIN_USERNAME`文档中](https://docs.conan.io/en/latest/reference/env_vars.html#conan-login-username-conan-login-username-remote-name)描述的命名约定配置[受保护的变量](../../../ci/variables/README.html#protect-a-custom-variable) . + +#### Custom root certificates for Conan[](#custom-root-certificates-for-conan "Permalink") + +您可以通过将`.conan/cacert.pem`文件添加到项目根目录并将[`CA_CERT_PATH`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-cacert-path)设置为`.conan/cacert.pem`来提供自定义证书. + +如果您指定`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables) ,则此变量的 X.509 证书将安装在 Docker 映像的默认信任库中,并且 Conan 配置为将其用作默认`CA_CERT_PATH` . + +### Configuring Go projects[](#configuring-go-projects "Permalink") + +要配置基于[Go 模块](https://github.com/golang/go/wiki/Modules)的项目,请在`.gitlab-ci.yml`的`license_scanning`作业的[变量](#available-variables)部分中指定[环境变量](https://s0golang0org.icopy.site/pkg/cmd/go/) . + +如果项目已[供应了](https://s0golang0org.icopy.site/pkg/cmd/go/)其模块,则使用`vendor`目录和`mod.sum`文件的组合来检测与 Go 模块依赖关系相关的软件许可证. + +#### Using private Go registries[](#using-private-go-registries "Permalink") + +您可以使用[`GOPRIVATE`](https://s0golang0org.icopy.site/pkg/cmd/go/)和[`GOPROXY`](https://s0golang0org.icopy.site/pkg/cmd/go/)环境变量来控制模块的来源. 另外,您可以使用[`go mod vendor`](https://s0golang0org.icopy.site/ref/mod)来供应项目的模块. + +#### Custom root certificates for Go[](#custom-root-certificates-for-go "Permalink") + +您可以通过导出[`GOFLAGS`](https://s0golang0org.icopy.site/cmd/go/)环境变量来指定[`-insecure`](https://s0golang0org.icopy.site/pkg/cmd/go/internal/get/)标志. 例如: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + GOFLAGS: '-insecure' +``` + +#### Using private NuGet registries[](#using-private-nuget-registries "Permalink") + +如果您拥有私有的 NuGet 注册表,则可以通过将其添加到[`nuget.config`](https://docs.microsoft.com/en-us/nuget/reference/nuget-config-file)文件的[`packageSources`](https://docs.microsoft.com/en-us/nuget/reference/nuget-config-file#package-source-sections)部分中来将其添加为源. + +例如: + +``` + + + + + + + +``` + +#### Custom root certificates for NuGet[](#custom-root-certificates-for-nuget "Permalink") + +您可以使用`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables)提供自定义根证书来完成 TLS 验证. + +### Migration from `license_management` to `license_scanning`[](#migration-from-license_management-to-license_scanning "Permalink") + +在 GitLab 12.8 中,引入了`license_management`作业的新名称. 进行此更改是为了提高扫描目的的清晰度,即扫描并收集项目依赖项中存在的许可证类型. GitLab 13.0 放弃了对`license_management`支持. 如果您使用自定义设置来实现"许可证合规性",则需要相应地更新 CI 配置: + +1. 将 CI 模板更改为`License-Scanning.gitlab-ci.yml` . +2. 将作业名称更改为`license_scanning` (如果在`.gitlab-ci.yml`提到了该`.gitlab-ci.yml` ). +3. 将工件名称更改为`license_scanning` ,并将文件名称更改为`gl-license-scanning-report.json` (如果在`.gitlab-ci.yml`中`.gitlab-ci.yml` ). + +例如,以下`.gitlab-ci.yml` : + +``` +include: + - template: License-Management.gitlab-ci.yml + +license_management: + artifacts: + reports: + license_management: gl-license-management-report.json +``` + +应更改为: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + artifacts: + reports: + license_scanning: gl-license-scanning-report.json +``` + +如果您在 GitLab 13.0 或更高版本中使用`license_management`工件,则"许可证合规性"作业将产生以下错误: + +``` +WARNING: Uploading artifacts to coordinator... failed id=:id responseStatus=400 Bad Request status=400 Bad Request token=:sha + +FATAL: invalid_argument +``` + +如果遇到此错误,请按照本节中的说明进行操作. + +## Running License Compliance in an offline environment[](#running-license-compliance-in-an-offline-environment "Permalink") + +对于在通过互联网有限,受限或间歇性访问外部资源的环境中进行自我管理的 GitLab 实例,需要进行一些调整才能成功运行许可合规性工作. 有关更多信息,请参阅[脱机环境](../../application_security/offline_deployments/index.html) . + +### Requirements for offline License Compliance[](#requirements-for-offline-license-compliance "Permalink") + +要在离线环境中使用许可证合规性,您需要: + +* GitLab 亚军与[`docker`或`kubernetes`执行](#requirements) . +* Docker 容器注册表,其中包含许可证合规性[分析器](https://gitlab.com/gitlab-org/security-products/analyzers)映像的本地可用副本. + +**注意:** GitLab Runner 的[默认`pull policy`为`always`](https://docs.gitlab.com/runner/executors/docker.html) ,这意味着即使本地副本可用,Runner 也会尝试从 GitLab 容器注册表中拉取 Docker 映像. 如果您只喜欢使用本地可用的 Docker 映像,则可以在离线环境[`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html) GitLab Runner 的[`pull_policy`设置为`if-not-present`](https://docs.gitlab.com/runner/executors/docker.html) . 但是,如果不在离线环境中,我们建议将拉取策略设置保持为`always` ,因为这样可以在 CI / CD 管道中使用更新的扫描仪. + +### Make GitLab License Compliance analyzer images available inside your Docker registry[](#make-gitlab-license-compliance-analyzer-images-available-inside-your-docker-registry "Permalink") + +要使用所有[支持的语言和程序包管理器进行](#supported-languages-and-package-managers)许可证合规性检查,请将以下默认许可证合规性分析器映像从`registry.gitlab.com`导入到您的离线[本地 Docker 容器注册表中](../../packages/container_registry/index.html) : + +``` +registry.gitlab.com/gitlab-org/security-products/license-management:latest +``` + +将 Docker 映像导入本地脱机 Docker 注册表的过程取决于**您的网络安全策略** . 请咨询您的 IT 员工,以找到可以导入或临时访问外部资源的已接受和批准的流程. 请注意,这些扫描程序会[定期](../../application_security/index.html#maintenance-and-update-of-the-vulnerabilities-database)使用新定义进行[更新](../../application_security/index.html#maintenance-and-update-of-the-vulnerabilities-database) ,因此请考虑您是否能够自己进行定期更新. + +有关将 Docker 映像保存和传输为文件的详细信息,请参阅 Docker 有关[`docker save`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/save/) , [`docker load`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/load/) , [`docker export`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/export/)和[`docker import`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/import/)的文档. + +### Set License Compliance CI job variables to use local License Compliance analyzers[](#set-license-compliance-ci-job-variables-to-use-local-license-compliance-analyzers "Permalink") + +将以下配置添加到您的`.gitlab-ci.yml`文件. 您必须替换`image`以引用本地 Docker 容器注册表中托管的 License Compliance Docker 映像: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + image: + name: localhost:5000/analyzers/license-management:latest +``` + +现在,"许可证合规性"作业应使用"许可证合规性"分析器的本地副本来扫描您的代码并生成安全报告,而无需访问 Internet. + +连接到[私有 Bower 注册表](#using-private-bower-registries) , [私有 Bundler 注册表](#using-private-bundler-registries) , [私有 Conan 注册表](#using-private-bower-registries) , [私有 Go 注册表](#using-private-go-registries) , [私有 Maven 仓库](#using-private-maven-repos) , [私有 NPM 注册表](#using-private-npm-registries) , [私有 Python 仓库](#using-private-python-repos)和[私有 Yarn 注册表时](#using-private-yarn-registries) ,可能需要附加配置. + +在脱机环境中运行时, [项目策略](#policies)必须与名称完全匹配( [请参阅相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/212388) ). + +## License list[](#license-list "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13582) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.7. + +许可证列表允许您查看项目的许可证以及有关许可证的关键详细信息. + +为了使许可证出现在许可证列表下,必须满足以下要求: + +1. 必须为您的项目[配置](#configuration)许可证合规性 CI 作业. +2. 您的项目必须至少使用一种[受支持的语言和程序包管理器](#supported-languages-and-package-managers) . + +设置完所有内容后,请在项目的侧边栏中导航至" **安全性和合规性">"许可证合规性"** ,您将看到显示的许可证,其中: + +* **名称:**许可证名称. +* **Component:** The components which have this license. +* **违反政策:**许可证的[许可证政策](#policies)标记为**拒绝** . + +[![License List](img/dc75662feab34ea9fa5cb187a2d77739.png)](img/license_list_v13_0.png) + +## Policies[](#policies "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22465) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9. + +通过" **策略"**选项卡,您可以查看项目的软件许可证策略以及每个策略的关联分类. + +可以由项目的维护者配置策略. + +[![Edit Policy](img/e545dd77cf453f5a97873da4f0083ebb.png)](img/policies_maintainer_edit_v13_2.png) [![Add Policy](img/45974f94466502ace734ecc3473a0d58.png)](img/policies_maintainer_add_v13_2.png) + +项目的开发人员可以查看项目中配置的策略. + +[![View Policies](img/793399d61e9710ebd809bd4c52901d68.png)](img/policies_v13_0.png) + +### Enabling License Approvals within a project[](#enabling-license-approvals-within-a-project "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13067) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.3. + +`License-Check`是一个批准规则,您可以启用它来允许批准人,个人或组批准包含`denied`许可证的合并请求. + +您可以启用`License-Check`的两种方式之一: + +* 使用区分大小写的名称`License-Check`创建[项目批准规则](../../project/merge_requests/merge_request_approvals.html#multiple-approval-rules-premium) . +* 在[项目策略部分中为许可合规](#policies)创建批准组. 您必须将此批准组的所需批准数量设置为大于零. 在项目中启用该组后,将为所有合并请求启用批准规则. + +任何代码更改都会导致重置所需的批准. + +许可证报告如下时,需要批准: + +* 包含包含被`denied`的软件许可证的依赖项. +* 在管道执行期间未生成. + +许可证报告如下时,批准是可选的: + +* 不包含任何违反软件许可证的行为. +* Contains only new licenses that are `allowed` or unknown. + +## Troubleshooting[](#troubleshooting "Permalink") + +### `ERROR -- : asdf: No preset version installed for command`[](#error-----asdf-no-preset-version-installed-for-command "Permalink") + +当项目使用的工具的版本与`license_scanning` Docker 映像中可用的预安装工具的版本不匹配时,会发生此错误. `license_scanning`作业使用[asdf-vm](https://asdf-vm.com/)来激活项目所依赖的工具的适当版本. 例如,如果您的项目依赖于特定版本的[Node.js](https://s0nodejs0org.icopy.site/)或任何其他受支持的工具,则可以通过向项目中添加[`.tool-versions`](https://asdf-vm.com/#/core-configuration?id=tool-versions)文件或使用适当的[`ASDF__VERSION`](https://asdf-vm.com/#/core-configuration?id=environment-variables)环境变量来激活所需的版本,从而指定所需的版本.适当的版本. + +例如,以下`.tool-versions`文件将激活[Node.js 的](https://s0nodejs0org.icopy.site/) `12.16.3`版和[Ruby 的](https://www.ruby-lang.org/) `2.6.6`版. + +``` +nodejs 12.16.3 +ruby 2.6.6 +``` + +下一个示例显示如何通过使用项目的`.gitlab-ci.yml`文件中定义的环境变量来激活上述工具的相同版本. + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + ASDF_NODEJS_VERSION: '12.16.3' + ASDF_RUBY_VERSION: '2.6.6' +``` + +完整的变量列表可以在[环境变量中](#available-variables)找到. + +要了解在`license_scanning` Docker 映像中预安装了哪些工具,请使用以下命令: + +``` +$ docker run --entrypoint='' registry.gitlab.com/gitlab-org/security-products/analyzers/license-finder:3 /bin/bash -lc 'asdf list' +golang + 1.14 +gradle + 6.3 +java + adopt-openjdk-11.0.7+10 + adopt-openjdk-8u242-b08 +maven + 3.6.3 +nodejs + 10.20.1 + 12.16.3 +php + 7.4.5 +python + 2.7.18 + 3.8.2 +ruby + 2.6.6 +sbt + 1.3.8 +``` + +要与`license_scanning`运行时环境进行交互,请使用以下命令: + +``` +$ docker run -it --entrypoint='' registry.gitlab.com/gitlab-org/security-products/analyzers/license-finder:3 /bin/bash -l +root@6abb70e9f193:~# +``` + +**注意:**当前不支持选择[Mono](https://www.mono-project.com/)或[.NET Core](https://dotnet.microsoft.com/download/dotnet-core)的自定义版本. \ No newline at end of file diff --git a/_book/docs/066.md b/_book/docs/066.md new file mode 100644 index 0000000000000000000000000000000000000000..ba96dbeed9900570b2bc8ea15d8d0eecddd58b9d --- /dev/null +++ b/_book/docs/066.md @@ -0,0 +1,35 @@ +# Compliance Dashboard + +> 原文:[https://docs.gitlab.com/ee/user/compliance/compliance_dashboard/](https://docs.gitlab.com/ee/user/compliance/compliance_dashboard/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Permissions](#permissions) + +# Compliance Dashboard[](#compliance-dashboard-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36524) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.8. + +Compliance Dashboard 通过为组中的所有项目提供高级视图,使您能够查看组的"合并请求"活动. 例如,批准用于合并的代码. + +## Overview[](#overview "Permalink") + +要访问组的合规性仪表板,请导航至 组菜单上的" **安全性和合规性">"合规性** ". + +[![Compliance Dashboard](img/da827bb1926cf748cff537fec6ecc954.png)](img/compliance_dashboard_v13_2.png) + +## Use cases[](#use-cases "Permalink") + +此功能适用于关心团队中项目的合规性状态的人员. + +您可以使用仪表板执行以下操作: + +* 概述每个项目的最新合并请求. +* 查看合并请求是否被批准以及由谁批准. +* 请参阅合并请求作者. +* 查看每个合并请求的最新[CI 管道](../../../ci/pipelines/index.html)结果. + +## Permissions[](#permissions "Permalink") + +* On [GitLab Ultimate](https://about.gitlab.com/pricing/) tier. +* By **Administrators** and **集团所有者**. \ No newline at end of file diff --git a/_book/docs/067.md b/_book/docs/067.md new file mode 100644 index 0000000000000000000000000000000000000000..93ac84760bd5107536c6aea7d0486b275430683b --- /dev/null +++ b/_book/docs/067.md @@ -0,0 +1,130 @@ +# Create a project + +> 原文:[https://docs.gitlab.com/ee/gitlab-basics/create-project.html](https://docs.gitlab.com/ee/gitlab-basics/create-project.html) + +* [Create a project in GitLab](#create-a-project-in-gitlab) + * [Blank projects](#blank-projects) + * [Project templates](#project-templates) + * [Built-in templates](#built-in-templates) + * [Enterprise templates](#enterprise-templates-ultimate) + * [Custom project templates](#custom-project-templates-premium) +* [Push to create a new project](#push-to-create-a-new-project) + +# Create a project[](#create-a-project "Permalink") + +GitLab 中的大多数工作都在一个[Project 中](../user/project/index.html)完成. 文件和代码保存在项目中,并且大多数功能都在项目范围内使用. + +## Create a project in GitLab[](#create-a-project-in-gitlab "Permalink") + +要在 GitLab 中创建项目: + +1. 在信息中心中,点击绿色的**新建项目**按钮或使用导航栏中的加号图标. 这将打开" **新项目"**页面. +2. 在" **新建项目"**页面上,选择是否要: + * 创建一个[空白项目](#blank-projects) . + * 使用可用的[项目模板](#project-templates)之一创建一个项目. + * 如果已在您的 GitLab 实例上启用,则从其他存储库[导入项目](../user/project/import/index.html) . 如果不可用,请与您的 GitLab 管理员联系. + * 运行[用于外部存储库的 CI / CD 管道](../ci/ci_cd_for_external_repos/index.html) . + +**注意:**有关不能用作项目名称的单词列表,请参见[保留的项目和组名称](../user/reserved_names.html) . + +### Blank projects[](#blank-projects "Permalink") + +要在" **新建项目"**页面上创建一个新的空白项目,请执行以下操作: + +1. 在" **空白项目"**选项卡上,提供以下信息: + * **项目名称**在**项目名称**字段中. 您不能使用特殊字符,但可以使用空格,连字符,下划线甚至表情符号. 添加名称时, **Project slug**将自动填充. slug 是 GitLab 实例将用作项目的 URL 路径的东西. 如果您要使用其他子弹,请先输入项目名称,然后再更改子弹. + * **Project slug**字段中项目的路径. 这是 GitLab 实例将使用的项目的 URL 路径. 如果**项目名称**为空白,则当您填写**项目 slug**时,它将自动填充. + * 使用" **项目描述"(可选)**字段,您可以为项目的仪表板输入描述,这将帮助其他人了解您的项目的含义. 尽管不是必需的,但这是个好主意. + * 更改" **可见性级别"**会修改用户的项目[查看和访问权限](../public_access/public_access.html) . + * 选择**使用 README 初始化存储库**选项将创建一个 README 文件,以便 Git 存储库被初始化,具有默认分支并可以被克隆. +2. Click **建立专案**. + +### Project templates[](#project-templates "Permalink") + +项目模板可以使用必要的文件预填充新项目,以使您快速入门. + +有两种类型的项目模板: + +* [内置模板](#built-in-templates) ,来自以下组: + * [`project-templates`](https://gitlab.com/gitlab-org/project-templates) + * [`pages`](https://gitlab.com/pages) +* [自定义项目模板](#custom-project-templates-premium) ,用于由 GitLab 管理员和用户配置的自定义模板. + +#### Built-in templates[](#built-in-templates "Permalink") + +内置模板是项目模板,它们是: + +* 在[`project-templates`](https://gitlab.com/gitlab-org/project-templates)和[`pages`](https://gitlab.com/pages)组中开发和维护. +* 与 GitLab 一起发布. + +要在" **新建项目"**页面上使用内置模板,请执行以下操作: + +1. 在" **从模板创建"**选项卡上,选择" **内置"**选项卡. +2. 从可用的内置模板列表中,单击: + * **预览**按钮以查看模板源本身. + * **使用模板**按钮开始创建项目. +3. 通过填写项目的详细信息来完成创建项目. 该过程与创建[空白项目](#blank-projects)相同. + +##### Enterprise templates[](#enterprise-templates-ultimate "Permalink") + +GitLab 正在开发企业模板,以帮助您根据选定的法规标准简化审核管理. 这些模板会自动导入与每个法规要求相对应的问题. + +要使用企业模板创建新项目,请在" **新建项目"**页面上: + +1. 在" **从模板创建"**选项卡上,选择" **内置"**选项卡. +2. 从可用的内置企业模板列表中,单击: + * **预览**按钮以查看模板源本身. + * **使用模板**按钮开始创建项目. +3. 通过填写项目的详细信息来完成创建项目. 该过程与创建[空白项目](#blank-projects)相同. + +可用的企业模板包括: + +* HIPAA 审核协议模板(在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13756) ) + +**提示:**您可以按照[以下步骤](https://gitlab.com/gitlab-org/project-templates/contributing)改进现有的内置模板或在[`project-templates`](https://gitlab.com/gitlab-org/project-templates)和[`pages`](https://gitlab.com/pages)组中添加新的[`project-templates`](https://gitlab.com/gitlab-org/project-templates) . + +#### Custom project templates[](#custom-project-templates-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6860) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2. + +Creating new projects based on custom project templates is a convenient option for quickly starting projects. + +自定义项目可以在[实例级别](../user/admin_area/custom_project_templates.html)从**实例**选项卡,或在[组级别](../user/group/custom_project_templates.html)从**组**选项卡,在**从模板**标签上的**创建** . + +要在" **新建项目"**页面上使用自定义项目模板: + +1. 在" **从模板创建"**选项卡上,选择" **实例"**选项卡或" **组"**选项卡. +2. 从可用的自定义模板列表中,单击: + * **预览**按钮以查看模板源本身. + * **使用模板**按钮开始创建项目. +3. 通过填写项目的详细信息来完成创建项目. 该过程与创建[空白项目](#blank-projects)相同. + +## Push to create a new project[](#push-to-create-a-new-project "Permalink") + +在 GitLab 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26388) . + +当您在本地创建新的存储库时,无需直接在 GitLab 上手动创建一个新项目然后[在](start-using-git.html#clone-a-repository)本地[克隆该](start-using-git.html#clone-a-repository)存储库,而无需将其直接发送到 GitLab 即可创建新项目. 如果您具有关联的名称空间的访问权,则 GitLab 将在该 GitLab 名称空间下自动创建一个新项目,其可见性默认设置为 Private(您以后可以在[项目的设置中](../public_access/public_access.html#how-to-change-project-visibility)对其进行更改). + +这可以通过使用 SSH 或 HTTPS 来完成: + +``` +## Git push using SSH +git push --set-upstream git@gitlab.example.com:namespace/nonexistent-project.git master + +## Git push using HTTPS +git push --set-upstream https://gitlab.example.com/namespace/nonexistent-project.git master +``` + +推送成功完成后,将显示一条远程消息,指示将遥控器和 URL 设置为新项目的命令: + +``` +remote: +remote: The private project namespace/nonexistent-project was created. +remote: +remote: To configure the remote, run: +remote: git remote add origin https://gitlab.example.com/namespace/nonexistent-project.git +remote: +remote: To view the project, visit: +remote: https://gitlab.example.com/namespace/nonexistent-project +remote: +``` \ No newline at end of file diff --git a/_book/docs/068.md b/_book/docs/068.md new file mode 100644 index 0000000000000000000000000000000000000000..ce5174968e003160fe0c9a64553ed873e0b67cc2 --- /dev/null +++ b/_book/docs/068.md @@ -0,0 +1,131 @@ +# Description templates + +> 原文:[https://docs.gitlab.com/ee/user/project/description_templates.html](https://docs.gitlab.com/ee/user/project/description_templates.html) + +* [Overview](#overview) +* [Use-cases](#use-cases) +* [Creating issue templates](#creating-issue-templates) +* [Creating merge request templates](#creating-merge-request-templates) +* [Using the templates](#using-the-templates) +* [Setting a default template for merge requests and issues](#setting-a-default-template-for-merge-requests-and-issues-starter) +* [Description template example](#description-template-example) + +# Description templates[](#description-templates "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4981) . + +我们都知道,项目开发人员更有可能及时解决提交的问题. + +使用描述模板,您可以为问题定义特定于上下文的模板,并为项目合并请求描述字段,并帮助从问题中过滤掉许多不必要的噪音. + +## Overview[](#overview "Permalink") + +通过使用描述模板,创建新发行或合并请求的用户可以选择描述模板,以帮助他们与其他贡献者进行有效沟通. + +每个 GitLab 项目都可以定义自己的一组描述模板,这些模板将被添加到 GitLab 项目存储库的根目录中. + +描述模板必须用[Markdown](../markdown.html)编写,并存储在项目的存储库中的`.gitlab`目录下. 仅考虑默认分支的模板. + +## Use-cases[](#use-cases "Permalink") + +* 添加一个模板,该模板将用于特定项目的每个问题,并提供说明和指南,要求提供特定于该主题的信息. 例如,如果您有一个用于跟踪新博客文章的项目,则可以要求标题,大纲,作者姓名,作者社交媒体信息等等. +* 在前面的示例之后,您可以为随新博客帖子提交的每个 MR 创建模板,要求提供有关帖子日期,前事数据,图像准则,相关问题的链接,审阅者姓名等信息. +* 您还可以为工作流的不同阶段创建问题并合并请求模板,例如功能建议,功能改进或错误报告. + +## Creating issue templates[](#creating-issue-templates "Permalink") + +在存储库的`.gitlab/issue_templates/`目录内创建一个新的 Markdown( `.md` )文件. 提交并推送到您的默认分支. + +To create a Markdown file: + +1. 单击`master`旁边的`+`按钮,然后单击**New file** . +2. 将问题模板的名称添加到`master`旁边的**File name**文本字段中. 确保单词之间用下划线分隔,并且文件的扩展名为`.md` ,例如`feature_request.md` . +3. 提交并推送到您的默认分支. + +如果您的存储库中没有`.gitlab/issue_templates`目录,则需要创建它. + +要创建`.gitlab/issue_templates`目录: + +1. 单击`master`旁边的`+`按钮,然后选择**New directory** . +2. 将此新目录`.gitlab`并提交到默认分支. +3. 再次单击`master`旁边的`+`按钮,然后选择**New directory** .这次,n +4. 将目录`issue_templates`并提交到默认分支. + +要检查它是否正常工作,请[创建一个新问题,](./issues/managing_issues.html#create-a-new-issue)然后查看是否可以选择描述模板. + +## Creating merge request templates[](#creating-merge-request-templates "Permalink") + +与发布模板类似,在存储库的`.gitlab/merge_request_templates/`目录内创建一个新的 Markdown( `.md` )文件. 提交并推送到您的默认分支. + +## Using the templates[](#using-the-templates "Permalink") + +让我们以创建了`.gitlab/issue_templates/Bug.md`文件`.gitlab/issue_templates/Bug.md` . 在创建或编辑问题时,这将启用`Bug`下拉选项. 选择`Bug` , `Bug.md`模板文件中的内容将被复制到问题描述字段. "重置模板"按钮将放弃您在选择模板后所做的任何更改,并将其恢复为初始状态. + +[![Description templates](img/6224c1a367d53cc7bb5c5536af96ec6e.png)](img/description_templates.png) + +## Setting a default template for merge requests and issues[](#setting-a-default-template-for-merge-requests-and-issues-starter "Permalink") + +版本历史 + +* 此功能是在[描述模板](#overview)之前引入的,可在[GitLab Starter 中使用](https://about.gitlab.com/pricing/) . 可以在项目设置中启用它. +* 问题模板在 GitLab EE 8.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28) . +* 在 GitLab EE 6.9 中[引入](https://gitlab.com/gitlab-org/gitlab/commit/7478ece8b48e80782b5465b96c79f85cc91d391b)了合并请求的模板. + +在项目的**"设置" /"可见性","项目功能","权限"**部分中,应将问题和/或合并请求的可见性设置为"每个人都可以访问"或"只有项目成员",否则模板文本区域将不会显示. 这是默认行为,因此在大多数情况下都可以. + +1. 转到项目的**"设置"** . +2. 单击**合并请求**标题下的**展开** . +3. 填写" **合并请求**的**默认描述模板"**文本区域. +4. Click **Expand** under **默认问题模板**. +5. 填写问题的**默认描述模板**文本区域. 由于 GitLab 合并请求和问题支持[Markdown](../markdown.html) ,因此您可以使用它来格式化标题,列表等. + +[![Default merge request description templates](img/c7ee3e55c50a5f7d0e3faceda16e2dc2.png)](img/description_templates_merge_request_settings.png) + +[![Default issue description templates](img/c9d2a45b5906d81d1118b63a832bbcd4.png)](img/description_templates_issue_settings.png) + +添加描述后,点击**保存更改**以使设置生效. 现在,每次创建新的合并请求或问题时,都将使用您在模板中输入的文本预先填充. + +## Description template example[](#description-template-example "Permalink") + +我们在 GitLab 社区版项目中使用问题和合并请求的描述模板. 请参考[`.gitlab`文件夹](https://gitlab.com/gitlab-org/gitlab/tree/master/.gitlab)中的一些示例. + +**提示:**可以在描述模板中使用[快速操作](quick_actions.html)来快速添加标签,受让人和里程碑. 仅当提交问题或合并请求的用户有权执行相关操作时,才执行快速操作. + +这是错误报告模板的示例: + +``` +Summary + +(Summarize the bug encountered concisely) + +Steps to reproduce + +(How one can reproduce the issue - this is very important) + +Example Project + +(If possible, please create an example project here on GitLab.com that exhibits the problematic behaviour, and link to it here in the bug report) + +(If you are using an older version of GitLab, this will also determine whether the bug has been fixed in a more recent version) + +What is the current bug behavior? + +(What actually happens) + +What is the expected correct behavior? + +(What you should see instead) + +Relevant logs and/or screenshots + +(Paste any relevant logs - please use code blocks (```) to format console output, +logs, and code as it's very hard to read otherwise.) + +Possible fixes + +(If you can, link to the line of code that might be responsible for the problem) + +/label ~bug ~reproduced ~needs-investigation +/cc @project-manager +/assign @qa-tester +``` \ No newline at end of file diff --git a/_book/docs/069.md b/_book/docs/069.md new file mode 100644 index 0000000000000000000000000000000000000000..1f83928d6e543dd9b867c6d3caced9884876d4ce --- /dev/null +++ b/_book/docs/069.md @@ -0,0 +1,119 @@ +# Deploy Keys + +> 原文:[https://docs.gitlab.com/ee/user/project/deploy_keys/](https://docs.gitlab.com/ee/user/project/deploy_keys/) + +* [Key details on deploy keys](#key-details-on-deploy-keys) +* [Deploy Keys Permissions](#deploy-keys-permissions) +* [Differences between deploy keys and deploy tokens](#differences-between-deploy-keys-and-deploy-tokens) +* [How to enable Deploy Keys](#how-to-enable-deploy-keys) + * [Project deploy keys](#project-deploy-keys) + * [Public deploy keys](#public-deploy-keys) +* [Troubleshooting](#troubleshooting) + * [Deploy Key cannot push to a protected branch](#deploy-key-cannot-push-to-a-protected-branch) + +# Deploy Keys[](#deploy-keys "Permalink") + +通过将 SSH 公钥导入到 GitLab 实例,部署密钥允许对一个或多个存储库的只读或读写(如果启用)访问. + +这对于将存储库克隆到持续集成(CI)服务器非常有用. 通过使用部署密钥,您不必设置虚拟用户帐户. + +There are two types of deploy keys: + +* [Project deploy keys](#project-deploy-keys) +* [Public deploy keys](#public-deploy-keys) + +## Key details on deploy keys[](#key-details-on-deploy-keys "Permalink") + +部署密钥使远程机器(VM,物理机等)只需几个步骤即可访问 GitLab 存储库. 如果您希望远程计算机以自动化方式与 GitLab 存储库进行交互,这是一个简单的解决方案. + +缺点是,如果远程计算机被黑客入侵,则您的存储库可能会变得脆弱. 在存储库中启用部署密钥之前,应限制对远程计算机的访问. 遵循的好规则是仅访问受信任的用户,并确保允许的用户在 GitLab 项目中具有[维护者权限或更高权限](../../permissions.html) . + +如果您的组织担心这种安全隐患,则可以使用" [部署令牌"](../deploy_tokens/index.html)作为替代方案,但具有更多的安全控制. + +## Deploy Keys Permissions[](#deploy-keys-permissions "Permalink") + +在项目上启用部署密钥时,可以选择其访问级别: + +* `read-only` :部署密钥可以读取存储库. +* `read-write` :部署密钥可以读取存储库并对其进行写入. + +项目维护者和所有者可以激活和停用部署密钥. 他们还可以添加自己的部署密钥并为该项目启用它们. + +当使用`write-access`部署密钥来推送提交时,GitLab 会检查部署密钥的**创建者**是否有权访问资源. 例如: + +* 当使用部署密钥将提交推送到[受保护的分支时](../protected_branches.html) ,部署密钥的**创建者**必须有权访问该分支. +* 当使用部署密钥来推送触发 CI / CD 管道的提交时,部署密钥的**创建者**必须有权访问 CI / CD 资源(例如受保护的环境,机密变量等). +* 如果部署密钥的**创建者**没有读取项目存储库的权限,则部署密钥*可能*在此过程中遇到错误. + +## Differences between deploy keys and deploy tokens[](#differences-between-deploy-keys-and-deploy-tokens "Permalink") + +部署密钥和[部署令牌](../deploy_tokens/index.html#deploy-tokens)都可以帮助您访问存储库,但是它们之间存在一些显着差异: + +* 部署密钥可以在不相关甚至不属于同一组的项目之间共享. 部署令牌属于项目或[组](../deploy_tokens/index.html#group-deploy-token) . +* 部署密钥是您需要在计算机上生成自己的 SSH 密钥. 部署令牌是由您的 GitLab 实例生成的,仅在创建时提供给用户一次. +* 只要已注册并启用部署密钥,该密钥便有效. 部署令牌可能是时间敏感的,因为您可以通过设置令牌的到期日期来控制令牌的有效性. +* 您不能使用部署密钥登录注册表,也不能对其执行读/写操作,但是[使用部署令牌是可以的](../deploy_tokens/index.html#gitlab-deploy-token) . +* 您需要 SSH 密钥对才能使用部署密钥,但不需要部署令牌. + +## How to enable Deploy Keys[](#how-to-enable-deploy-keys "Permalink") + +### Project deploy keys[](#project-deploy-keys "Permalink") + +[项目维护者和所有者](../../permissions.html#project-members-permissions)可以为项目存储库添加或启用部署密钥: + +1. 导航到项目的**"设置">"存储库"**页面. +2. 展开" **部署密钥"**部分. +3. 为新的部署密钥指定标题,然后粘贴您的公共 SSH 密钥. +4. (可选)检查**写访问允许**允许`read-write`访问. 保留它的`read-only`访问权限. + +有三个项目部署密钥列表: + +* 启用的部署密钥 +* Privately accessible deploy keys +* 公共可访问的部署密钥 + +[![Deploy Keys section](img/86738432aa05c0c68fffb68c00788fa4.png)](img/deploy_keys_v13_0.png) + +添加密钥后,默认情况下将为此项目启用该密钥,它将显示在"已**启用的部署密钥"**选项卡中. + +在"私有**可访问的部署密钥"**选项卡中,您可以启用已导入到其他项目中的私有密钥. 如果您有权访问这些密钥,那是因为您具有以下任一能力: + +* 以前,您自己将密钥上传到了另一个项目中. +* 您是导入密钥的另一个项目的维护者或所有者. + +在可**公开访问的部署密钥**选项卡中,您可以启用[对整个 GitLab 实例可用的](#public-deploy-keys)密钥. + +添加密钥后,您可以对其进行编辑以更新其标题,或者在`read-only`和`read-write`访问之间切换. + +**注意:**如果您为项目启用了私有或公共访问或部署密钥,并且随后将该密钥的访问级别从`read-only`更新为`read-write` ,则更改将仅适用于**当前项目** . + +### Public deploy keys[](#public-deploy-keys "Permalink") + +公共部署密钥允许对 GitLab 实例中的任何存储库进行`read-only`或`read-write`访问. 这对于将存储库集成到安全的共享服务(例如 CI / CD)很有用. + +实例管理员可以添加公共部署密钥: + +1. 转到**管理区域** ( ) **>部署密钥** . +2. 单击**新部署密钥** . + + 确保新密钥具有有意义的标题,因为这是项目维护者和所有者识别要添加的正确公共部署密钥的主要方法. 例如,如果密钥允许访问 SaaS CI / CD 实例,请在密钥名称中使用该服务的名称(如果已使用了所有密钥). + +[![Public Deploy Keys section](img/2d13f3059b88ccaf448646ed61f70d47.png)](img/public_deploy_key_v13_0.png) + +添加密钥后,它将对所有共享系统可用. 项目维护者或更高级别的人员可以[授权公共部署密钥](#project-deploy-keys)开始在项目中使用它. + +**注意:**仅在配置了至少一个公共部署密钥的情况下,Project CI / CD 设置中的" **公共可访问部署密钥"**选项卡才会显示. + +与项目部署密钥相比,公共部署密钥可以提供更高的安全性,因为目标集成系统的管理员是唯一需要知道或配置密钥值的管理员. + +创建公共部署密钥时,请确定是否可以针对非常狭窄的用途(例如仅特定服务)定义它,或者是否需要针对更广泛的用途(例如对所有服务进行完全`read-write`访问)进行定义. + +**警告:**添加公共部署密钥不会立即向其公开任何存储库. 公共部署密钥允许从其他系统进行访问,但是只有项目维护者选择使用它之后,才能访问任何项目. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Deploy Key cannot push to a protected branch[](#deploy-key-cannot-push-to-a-protected-branch "Permalink") + +如果此部署密钥的所有者无权访问[受保护的分支](../protected_branches.html) ,则此部署密钥也将无权访问该分支. 除此之外,在["允许推送"部分中](../protected_branches.html#configuring-protected-branches)选择" **否"**值意味着没有用户**和**使用部署密钥的服务都无法推送到该选定分支. + +有关更多信息,请参考[此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/30769) . \ No newline at end of file diff --git a/_book/docs/070.md b/_book/docs/070.md new file mode 100644 index 0000000000000000000000000000000000000000..60ad7ba10cd31ca8c15c2f50c1722061c1b96cef --- /dev/null +++ b/_book/docs/070.md @@ -0,0 +1,169 @@ +# Deploy Tokens + +> 原文:[https://docs.gitlab.com/ee/user/project/deploy_tokens/](https://docs.gitlab.com/ee/user/project/deploy_tokens/) + +* [Creating a Deploy Token](#creating-a-deploy-token) +* [Deploy token expiration](#deploy-token-expiration) +* [Revoking a deploy token](#revoking-a-deploy-token) +* [Limiting scopes of a deploy token](#limiting-scopes-of-a-deploy-token) +* [Deploy token custom username](#deploy-token-custom-username) +* [Usage](#usage) + * [Git clone a repository](#git-clone-a-repository) + * [Read Container Registry images](#read-container-registry-images) + * [Push Container Registry images](#push-container-registry-images) + * [Read or pull packages](#read-or-pull-packages) + * [Push or upload packages](#push-or-upload-packages) + * [Group Deploy Token](#group-deploy-token) + * [GitLab Deploy Token](#gitlab-deploy-token) + +# Deploy Tokens[](#deploy-tokens "Permalink") + +版本历史 + +* 在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17894) . +* 从 GitLab 12.9 中的**设置>存储库** [移动](https://gitlab.com/gitlab-org/gitlab/-/issues/199370) . +* 在 GitLab 12.10 中[添加了`write_registry`范围](https://gitlab.com/gitlab-org/gitlab/-/issues/22743) . +* 从 GitLab 12.10.1.中的**"设置">" CI / CD"** [移动](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29280) . +* 在 GitLab 13.0 中[添加了软件包注册表范围](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) . + +部署令牌使您无需用户和密码即可下载( `git clone` )或推和拉项目的程序包和容器注册表映像. + +部署令牌只能由[维护者](../../permissions.html)管理. + +如果有密钥对,则可能要改用[部署密钥](../../../ssh/README.html#deploy-keys) . + +## Creating a Deploy Token[](#creating-a-deploy-token "Permalink") + +您可以从项目的设置中创建任意数量的部署令牌. 或者,您也可以创建[组范围的部署令牌](#group-deploy-token) . + +1. 登录到您的 GitLab 帐户. +2. 转到要为其创建"部署令牌"的项目(或组). +3. 去 **设置** > **存储库** . +4. 单击" **部署令牌"**部分上的"扩展". +5. 选择令牌的名称,有效期(可选)和用户名(可选). +6. 选择[所需的范围](#limiting-scopes-of-a-deploy-token) . +7. 单击**创建部署令牌** . +8. 将部署令牌保存在安全的地方. 离开或刷新页面后, **您将无法再次访问它** . + +[![Personal access tokens page](img/90bcd1f29936328bfb5d344868b8bb81.png)](img/deploy_tokens.png) + +## Deploy token expiration[](#deploy-token-expiration "Permalink") + +部署令牌在您定义的日期 UTC 午夜到期. + +## Revoking a deploy token[](#revoking-a-deploy-token "Permalink") + +您可以随时单击"活动的部署令牌"区域下的相应" **撤消"**按钮来撤消任何部署令牌. + +## Limiting scopes of a deploy token[](#limiting-scopes-of-a-deploy-token "Permalink") + +可以使用不同的作用域创建部署令牌,这些作用域允许给定令牌可以执行各种操作. 下表介绍了可用的范围以及引入的 GitLab 版本. + +| Scope | Description | 在 GitLab 版本中引入 | +| --- | --- | --- | +| `read_repository` | 允许通过`git clone`对存储库进行读取访问 | 10.7 | +| `read_registry` | 如果项目是私有的并且需要授权,则允许对[容器注册表](../../packages/container_registry/index.html)图像的读取访问. | 10.7 | +| `write_registry` | Allows write-access (push) to [container registry](../../packages/container_registry/index.html). | 12.10 | +| `read_package_registry` | 允许对包注册表进行读取访问. | 13.0 | +| `write_package_registry` | 允许对程序包注册表的写访问. | 13.0 | + +## Deploy token custom username[](#deploy-token-custom-username "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29639) . + +默认的用户名格式为`gitlab+deploy-token-#{n}` . 某些工具或平台可能不支持此格式,在这种情况下,您可以指定在创建部署令牌时要使用的自定义用户名. + +## Usage[](#usage "Permalink") + +### Git clone a repository[](#git-clone-a-repository "Permalink") + +要使用部署令牌下载存储库,您只需要: + +1. 创建一个以`read_repository`为范围的部署令牌. +2. 记下您的`username`和`token` . +3. `git clone`使用 Deploy Token `git clone`项目: + + ``` + git clone https://:@gitlab.example.com/tanuki/awesome_project.git + ``` + +将``和``替换为正确的值. + +### Read Container Registry images[](#read-container-registry-images "Permalink") + +要读取容器注册表图像,您需要: + +1. 使用`read_registry`作为范围创建部署令牌. +2. 记下您的`username`和`token` . +3. 使用部署令牌登录到 GitLab 的 Container Registry: + +``` +docker login -u -p registry.example.com +``` + +只需将``和``替换为适当的值即可. 然后,您可以简单地从 Container Registry 中提取图像. + +### Push Container Registry images[](#push-container-registry-images "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22743) . + +要推送容器注册表映像,您需要: + +1. 创建一个具有`write_registry`作为范围的部署令牌. +2. 记下您的`username`和`token` . +3. 使用部署令牌登录到 GitLab 的 Container Registry: + + ``` + docker login -u -p registry.example.com + ``` + +只需将``和``替换为适当的值即可. 然后,您可以简单地将图像推送到 Container Registry. + +### Read or pull packages[](#read-or-pull-packages "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) . + +要在 GitLab 软件包注册表中提取软件包,您需要: + +1. 使用`read_package_registry`作为范围创建一个部署令牌. +2. 记下您的`username`和`token` . +3. 对于[您选择](./../../packages/index.html)的[软件包类型,请](./../../packages/index.html)遵循有关部署令牌的身份验证说明. + +### Push or upload packages[](#push-or-upload-packages "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) . + +要在 GitLab 软件包注册表中上传软件包,您需要: + +1. 使用`write_package_registry`作为范围创建部署令牌. +2. 记下您的`username`和`token` . +3. 对于[您选择](./../../packages/index.html)的[软件包类型,请](./../../packages/index.html)遵循有关部署令牌的身份验证说明. + +### Group Deploy Token[](#group-deploy-token "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/21765) . + +在组级别创建的部署令牌可在属于特定组或其子组之一的所有项目中使用. + +有关概述,请参阅" [组部署令牌"](https://youtu.be/8kxTJvaD9ks) . + +要使用组部署令牌: + +1. 为组[创建](#creating-a-deploy-token)一个部署令牌. +2. 与[克隆存储库](#git-clone-a-repository)时使用项目部署令牌的方式相同. + +克隆相关项目的存储库时,应用于组部署令牌的范围(例如`read_repository` )将一致地应用. + +### GitLab Deploy Token[](#gitlab-deploy-token "Permalink") + +在 GitLab 10.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18414) . + +部署令牌是一种特殊情况. 如果用户创建了一个名为`gitlab-deploy-token`的名称,则 Deploy Token 的用户名和令牌将自动作为环境变量暴露给 CI / CD 作业: `CI_DEPLOY_USER`和`CI_DEPLOY_PASSWORD` . + +创建令牌后,可以使用以下变量登录到 Container Registry: + +``` +docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY +``` + +**注意:**目前尚未为组部署令牌实现`gitlab-deploy-token`部署令牌的特殊处理. 为了使部署令牌可用于 CI / CD 作业,必须在项目级别创建它. 有关详细信息,请参[见此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/214014) . \ No newline at end of file diff --git a/_book/docs/071.md b/_book/docs/071.md new file mode 100644 index 0000000000000000000000000000000000000000..31641697c1d4b4e0e5e7a2b8113e2bd7805ebd24 --- /dev/null +++ b/_book/docs/071.md @@ -0,0 +1,35 @@ +# File finder + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/file_finder.html](https://docs.gitlab.com/ee/user/project/repository/file_finder.html) + +* [How it works](#how-it-works) + +# File finder[](#file-finder "Permalink") + +在 GitLab 8.4 中[引入](https://github.com/gitlabhq/gitlabhq/pull/9889) . + +文件查找器功能使您可以使用 GitLab UI 在存储库中搜索文件. + +您可以在项目的" **文件"**部分中找到" **查找文件"**按钮. + +[![Find file button](img/264ee345c8d001f9b7cabf52e10f47bf.png)](img/file_finder_find_button_v12_10.png) + +对于那些喜欢用手指触摸键盘的人,还有一个[快捷按钮](../../shortcuts.html) ,您可以从项目中的*任何地方*调用它. + +在**问题** , **合并请求** , **里程碑**甚至项目设置中,按`t`键启动文件搜索功能. + +开始输入您要搜索的内容,然后观察魔术的发生. 使用向上/向下箭头,您可以向上和向下搜索结果,使用`Esc`可以关闭搜索并返回" **文件"** + +## How it works[](#how-it-works "Permalink") + +文件查找器功能由[模糊过滤器](https://github.com/jeancroy/fuzz-aldrin-plus)库提供支持. + +它通过突出显示来实现模糊搜索,并试图通过识别人们在搜索时使用的模式来提供直观的结果. + +例如,考虑[GitLab FOSS 存储库](https://gitlab.com/gitlab-org/gitlab-foss/tree/master) ,并且我们要打开`app/controllers/admin/deploy_keys_controller.rb`文件. + +使用模糊搜索,我们首先输入使我们更接近文件的字母. + +**提示:**要缩小搜索范围,请在搜索词中包含`/` . + +[![Find file button](img/ead8d62e426d9309f25a82da77770f59.png)](img/file_finder_find_file_v12_10.png) \ No newline at end of file diff --git a/_book/docs/072.md b/_book/docs/072.md new file mode 100644 index 0000000000000000000000000000000000000000..b4506a38023b4150ff3e9bb868c683d5a233602a --- /dev/null +++ b/_book/docs/072.md @@ -0,0 +1,22 @@ +# Project integrations + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/](https://docs.gitlab.com/ee/user/project/integrations/) + +* [Integrations](#integrations) +* [Project webhooks](#project-webhooks) + +# Project integrations[](#project-integrations "Permalink") + +您可以在项目的**设置➔集成**页面下找到可用的集成. 您至少需要对该项目具有[维护者权限](../../permissions.html) . + +## Integrations[](#integrations "Permalink") + +集成使您可以将 GitLab 与其他应用程序集成. 它们有点像插件,因为它们为 GitLab 添加功能提供了很大的自由度. + +[Learn more about integrations.](overview.html) + +## Project webhooks[](#project-webhooks "Permalink") + +通过项目 webhooks,您可以在例如推送新代码或创建新问题时触发 URL. 您可以将 webhook 配置为侦听特定事件,例如推送,问题或合并请求. GitLab 会将带有数据的 POST 请求发送到 webhook URL. + +[Learn more about webhooks.](webhooks.html) \ No newline at end of file diff --git a/_book/docs/073.md b/_book/docs/073.md new file mode 100644 index 0000000000000000000000000000000000000000..0f3891169dc625e1ae0ca8354fcec3195bce9c72 --- /dev/null +++ b/_book/docs/073.md @@ -0,0 +1,112 @@ +# Integrations + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/overview.html](https://docs.gitlab.com/ee/user/project/integrations/overview.html) + +* [Accessing integrations](#accessing-integrations) +* [Integrations listing](#integrations-listing) +* [Push hooks limit](#push-hooks-limit) +* [Service templates](#service-templates) +* [Troubleshooting integrations](#troubleshooting-integrations) + * [Uninitialized repositories](#uninitialized-repositories) +* [Contributing to integrations](#contributing-to-integrations) + +# Integrations[](#integrations "Permalink") + +集成使您可以将 GitLab 与其他应用程序集成. 它们有点像插件,因为它们为 GitLab 添加功能提供了很大的自由度. + +## Accessing integrations[](#accessing-integrations "Permalink") + +您可以在项目的**设置➔集成**页面下找到可用的集成. + +有 20 多个要集成的集成. 单击您要配置的一个. + +[![Integrations list](img/da1fdf492cc3f883353bb1997795a4a5.png)](img/project_services.png) + +## Integrations listing[](#integrations-listing "Permalink") + +单击服务链接以查看更多的配置说明和详细信息. + +| Service | Description | 服务挂钩 | +| --- | --- | --- | +| Asana | Asana-无需电子邮件的团队合作 | No | +| Assembla | 项目管理软件(源提交端点) | No | +| [Atlassian Bamboo CI](bamboo.html) | 持续集成和构建服务器 | Yes | +| Buildkite | 持续集成和部署 | Yes | +| [Bugzilla](bugzilla.html) | Bugzilla 问题追踪器 | No | +| Campfire | 基于网络的简单实时群聊 | No | +| [Confluence](../../../api/services.html#confluence-service) | 将指向内部 Wiki 的链接替换为指向 Confluence Cloud Workspace 的链接 | No | +| 自定义问题跟踪器 | 自定义问题跟踪器 | No | +| [Discord Notifications](discord_notifications.html) | 在 Discord 中接收事件通知 | No | +| CI 无人机 | Go 编写的基于 Docker 的持续集成平台 | Yes | +| [Emails on push](emails_on_push.html) | 通过电子邮件将每次推送的提交和差异发送到收件人列表 | No | +| 外部维基 | 将指向内部 Wiki 的链接替换为指向外部 Wiki 的链接 | No | +| Flowdock | Flowdock 是面向技术团队的协作网络应用程序 | No | +| [Generic alerts](generic_alerts.html) | 从任何来源接收有关 GitLab 的警报 | No | +| [GitHub](github.html) | 发送管道通知到 GitHub | No | +| [Hangouts Chat](hangouts_chat.html) | 在 Google 环聊中接收事件通知 | No | +| [HipChat](hipchat.html) | 私人群聊和即时消息 | No | +| [Irker (IRC gateway)](irker.html) | 通过 Irker 网关在更新时将 IRC 消息发送到收件人列表 | No | +| [Jira](jira.html) | 吉拉问题追踪器 | No | +| [Jenkins](../../../integration/jenkins.html) | 可扩展的开源持续集成服务器 | Yes | +| JetBrains TeamCity CI | 持续集成和构建服务器 | Yes | +| [Mattermost slash commands](mattermost_slash_commands.html) | 最重要的聊天和 ChatOps 斜杠命令 | No | +| [Mattermost Notifications](mattermost.html) | 在 Mattermost 接收事件通知 | No | +| [Microsoft teams](microsoft_teams.html) | 使用 Office 365 连接器接收有关在 GitLab 上进入 Microsoft Teams 房间的操作的通知 | No | +| Packagist | 在主要 Composer 存储库 Packagist 上更新项目 | Yes | +| 管道电子邮件 | 通过电子邮件将管道状态发送给收件人列表 | No | +| [Slack Notifications](slack.html) | 将 GitLab 事件(例如,已创建问题)作为通知发送到 Slack | No | +| [Slack slash commands](slack_slash_commands.html) | 在 Slack 中使用斜杠命令控制 GitLab | No | +| [GitLab Slack application](gitlab_slack_application.html) | 使用 Slack 的官方应用程序 | No | +| PivotalTracker | 项目管理软件(源提交端点) | No | +| [Prometheus](prometheus.html) | 监控已部署应用程序的性能 | No | +| Pushover | 通过 Pushover,可以轻松在 Android 设备,iPhone,iPad 和台式机上获取实时通知 | No | +| [Redmine](redmine.html) | Redmine 问题追踪器 | No | +| [Unify Circuit](unify_circuit.html) | 在统一电路中接收事件通知 | No | +| [Webex Teams](webex_teams.html) | 在 Webex Teams 中接收事件通知 | No | +| [YouTrack](youtrack.html) | YouTrack 问题追踪器 | No | + +## Push hooks limit[](#push-hooks-limit "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17874) . + +如果单个推送包含对三个以上分支或标签的更改,则`push_hooks`和`tag_push_hooks`事件支持的服务将不会执行. + +可以通过[`push_event_hooks_limit`应用程序设置](../../../api/settings.html#list-of-settings-that-can-be-accessed-via-api-calls)来更改支持的分支或标记的数量. + +## Service templates[](#service-templates "Permalink") + +服务模板是为实例上所有新项目之间的集成设置预定义值的方法. + +[在本文档中](services_templates.html)阅读有关[服务模板的](services_templates.html)更多信息. + +## Troubleshooting integrations[](#troubleshooting-integrations "Permalink") + +某些集成使用服务挂钩来与外部应用程序集成. 要确认哪些使用服务挂钩,请参见上面[列出](#integrations-listing)的[集成](#integrations-listing) . GitLab 存储最近 2 天内发出的服务挂钩请求的详细信息. 要查看请求的详细信息,请转到该集成的配置页面. + +**最近发送**部分列出了最近 2 天内提出的每个请求的详细信息: + +* HTTP 状态代码(绿色表示 200-299 代码,红色表示其他代码, `internal error`表示传送失败) +* 触发事件 +* 请求发送到的 URL +* 请求经过的时间 +* 提出请求的相对时间 + +要查看有关请求执行的更多信息,请单击相应的**查看详细信息**链接. 在详细信息页面上,您可以看到 GitLab 发送和接收的请求标头和正文. + +要使用相同的数据重复发送,请点击**重新发送请求** . + +[![Recent deliveries](img/78dac22706dcca5ce3855d23987289ea.png)](img/webhook_logs.png) + +### Uninitialized repositories[](#uninitialized-repositories "Permalink") + +某些集成失败,并显示错误" `Test Failed. Save Anyway` 尝试在未初始化的存储库上设置它们时,仍然要`Test Failed. Save Anyway` . 某些集成使用推送数据来构建测试有效负载,并且当项目中尚无推送事件时,就会发生此错误. + +要解决此错误,请通过将测试文件推送到项目来初始化存储库,然后再次设置集成. + +## Contributing to integrations[](#contributing-to-integrations "Permalink") + +因为 GitLab 是开源的,所以我们可以附带所有插件的代码和测试. 这使社区可以使插件保持最新状态,以便它们始终在较新的 GitLab 版本中运行. + +有关可用集成的概述,请参见[project_services 源目录](https://gitlab.com/gitlab-org/gitlab/tree/master/app/models/project_services) . + +欢迎捐款! \ No newline at end of file diff --git a/_book/docs/074.md b/_book/docs/074.md new file mode 100644 index 0000000000000000000000000000000000000000..0d206a7579bb21fd94bdca4c71ed23c46b3d1129 --- /dev/null +++ b/_book/docs/074.md @@ -0,0 +1,50 @@ +# Atlassian Bamboo CI Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/bamboo.html](https://docs.gitlab.com/ee/user/project/integrations/bamboo.html) + +* [Setup](#setup) + * [Complete these steps in Bamboo](#complete-these-steps-in-bamboo) + * [Complete these steps in GitLab](#complete-these-steps-in-gitlab) +* [Troubleshooting](#troubleshooting) + +# Atlassian Bamboo CI Service[](#atlassian-bamboo-ci-service "Permalink") + +GitLab 提供与 Atlassian Bamboo 的集成,以实现持续集成. 配置后,推送到项目将自动触发 Bamboo 的构建. 合并请求还将显示 CI 状态,显示构建是挂起,失败还是成功完成. 它还提供了指向 Bamboo 构建页面的链接,以获取更多信息. + +在接受 Webhook 和提交数据方面,Bamboo 并没有提供与传统构建系统相同的功能. 在 GitLab 集成之前,需要在 Bamboo 构建计划中进行一些配置. + +## Setup[](#setup "Permalink") + +### Complete these steps in Bamboo[](#complete-these-steps-in-bamboo "Permalink") + +1. 导航到 Bamboo 建设计划,然后从"操作"下拉列表中选择"配置计划". +2. 选择"触发器"标签. +3. 点击"添加触发器". +4. 输入描述,例如" GitLab 触发器" +5. 选择"提交更改后,存储库将触发构建" +6. 选中一个或多个存储库复选框 +7. 在"触发 IP 地址"框中输入 GitLab IP 地址. 这是允许触发 Bamboo 生成的 IP 地址的列表. +8. 保存触发器. +9. 在左窗格中,选择一个构建阶段. 如果您有多个构建阶段,则要选择包含 Git 签出任务的最后一个阶段. +10. Select the ‘Miscellaneous’ tab. +11. 在"模式匹配标签"下,将`${bamboo.repository.revision.number}`放在"标签"框中. +12. Save + +Bamboo 现在准备接受来自 GitLab 的触发器. 接下来,在 GitLab 中设置 Bamboo 服务. + +### Complete these steps in GitLab[](#complete-these-steps-in-gitlab "Permalink") + +1. 导航到要配置为触发构建的项目. +2. 导航到" [集成"页面](overview.html#accessing-integrations) +3. 点击" Atlassian Bamboo CI" +4. 确保启用了**活动**切换. +5. 输入 Bamboo 服务器的基本 URL. `https://bamboo.example.com` +6. Enter the build key from your Bamboo build plan. 输入 Bamboo 建造计划中的建造钥匙. Build keys are typically made up from the Project Key and Plan Key that are set on project/plan creation and separated with a dash ( `-` ), for example **PROJ-PLAN** . 构建密钥通常由在项目/计划创建时设置的项目密钥和计划密钥组成,并用破折号( `-` )分隔,例如**PROJ-PLAN** . This is a short, all uppercase identifier that is unique. 这是一个简短的全大写标识符,是唯一的. When viewing a plan within Bamboo, the build key is also shown in the browser URL, for example `https://bamboo.example.com/browse/PROJ-PLAN` . 在 Bamboo 内查看计划时,构建密钥也会显示在浏览器 URL 中,例如`https://bamboo.example.com/browse/PROJ-PLAN` . +7. 如有必要,请输入有权触发构建计划的 Bamboo 用户的用户名和密码. 如果不需要身份验证,请将这些字段留空. +8. 保存或选择单击"测试设置". 请注意,"测试设置"实际上会触发 Bamboo 的构建. + +## Troubleshooting[](#troubleshooting "Permalink") + +如果未触发构建,请确保在 Bamboo 的"触发 IP 地址"下输入了正确的 GitLab IP 地址. 还检查[服务挂钩日志中](overview.html#troubleshooting-integrations)是否存在请求失败. + +**注意:**从 GitLab 8.14.0 开始,构建会在推送事件中触发. \ No newline at end of file diff --git a/_book/docs/075.md b/_book/docs/075.md new file mode 100644 index 0000000000000000000000000000000000000000..eeff9e052870787d8217cd2ba62503b9f048608e --- /dev/null +++ b/_book/docs/075.md @@ -0,0 +1,33 @@ +# Bugzilla Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/bugzilla.html](https://docs.gitlab.com/ee/user/project/integrations/bugzilla.html) + +* [Referencing issues in Bugzilla](#referencing-issues-in-bugzilla) +* [Troubleshooting](#troubleshooting) + +# Bugzilla Service[](#bugzilla-service "Permalink") + +导航到[Integrations 页面](overview.html#accessing-integrations) ,选择**Bugzilla**服务,然后按照下表中的说明填写所需的详细信息. + +| Field | Description | +| --- | --- | +| `project_url` | The URL to the project in Bugzilla which is being linked to this GitLab project. Note that the `project_url` requires PRODUCT_NAME to be updated with the product/project name in Bugzilla. | +| `issues_url` | 链接到此 GitLab 项目的 Bugzilla 项目中问题的 URL. 请注意, `issues_url`在 URL 中需要`:id` . GitLab 使用此 ID 作为占位符来替换问题编号. | +| `new_issue_url` | 这是在 Bugzilla 中为与此 GitLab 项目链接的项目创建新问题的 URL. 请注意,在`new_issue_url`中, `new_issue_url`要求使用产品/项目名称更新 PRODUCT_NAME. | + +配置并启用 Bugzilla 后,您将在 GitLab 项目页面上看到 Bugzilla 链接,该链接将您带到相应的 Bugzilla 项目. + +## Referencing issues in Bugzilla[](#referencing-issues-in-bugzilla "Permalink") + +Bugzilla 中的问题可以通过两种替代方式进行引用: + +* `#` ,其中``是数字(示例`#143` ). +* `-` ,其中``以大写字母开头,然后是大写字母,数字或下划线,并且``是数字(示例`API_32-143` ). + +如果您同时启用了内部和外部问题跟踪器,我们建议使用更长的格式. 如果您使用较短的格式,并且内部问题跟踪器中存在具有相同 ID 的问题,则内部问题将被链接. + +请注意, ``部分将被忽略,链接始终指向`issues_url`指定的地址. + +## Troubleshooting[](#troubleshooting "Permalink") + +要查看最近的服务挂钩交付,请检查[服务挂钩日志](overview.html#troubleshooting-integrations) . \ No newline at end of file diff --git a/_book/docs/076.md b/_book/docs/076.md new file mode 100644 index 0000000000000000000000000000000000000000..484102c4a66a9848401ada02419d0a6609b66191 --- /dev/null +++ b/_book/docs/076.md @@ -0,0 +1,33 @@ +# Custom Issue Tracker service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/custom_issue_tracker.html](https://docs.gitlab.com/ee/user/project/integrations/custom_issue_tracker.html) + +* [Referencing issues](#referencing-issues) + +# Custom Issue Tracker service[](#custom-issue-tracker-service "Permalink") + +To enable the Custom Issue Tracker integration in a project: + +1. 去 **设置>集成** . +2. Click **自定义问题跟踪器** +3. 填写跟踪器的详细信息,例如标题,描述和 URL. 您以后也可以编辑这些字段. + + 这些是一些必填字段: + + | Field | Description | + | --- | --- | + | **项目网址** | 自定义问题跟踪器中项目的 URL. | + | **问题网址** | 问题跟踪器项目中与该 GitLab 项目链接的问题的 URL. 请注意, `issues_url`在 URL 中需要`:id` . GitLab 使用此 ID 作为占位符来替换问题编号. 例如, `https://customissuetracker.com/project-name/:id` . | + | **新发行网址** | 目前未使用. 将在以后的版本中进行更改. | + +4. Click **测试设置并保存更改**. + +配置并启用"自定义问题跟踪器"服务后,您将在 GitLab 项目页面上看到一个链接,该链接将您带至该自定义问题跟踪器. + +## Referencing issues[](#referencing-issues "Permalink") + +用`-` (例如`PROJECT-143` )引用问题,其中``可以是 CAPS 中的任何字符串,而``是自定义集成的目标项目中使用的数字. + +``是一个占位符,用于区分使用`#`引用的 GitLab 问题. 例如,您可以使用项目名称或项目密钥来替换它. + +构建超链接时, ``部分将被忽略,并且链接始终指向`issues_url`指定的地址,因此在上面的示例中, `PROJECT-143`将引用`https://customissuetracker.com/project-name/143` . \ No newline at end of file diff --git a/_book/docs/077.md b/_book/docs/077.md new file mode 100644 index 0000000000000000000000000000000000000000..3537af1bfd6b22996d37c1d2e76c0136809c1121 --- /dev/null +++ b/_book/docs/077.md @@ -0,0 +1,36 @@ +# Discord Notifications service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/discord_notifications.html](https://docs.gitlab.com/ee/user/project/integrations/discord_notifications.html) + +* [Create webhook](#create-webhook) +* [Configure created webhook in GitLab](#configure-created-webhook-in-gitlab) + +# Discord Notifications service[](#discord-notifications-service "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22684) . + +Discord Notifications 服务将事件通知从 GitLab 发送到创建 Webhook 的通道. + +要将 GitLab 事件通知发送到 Discord 频道,请在 Discord 中创建一个 Webhook,然后在 GitLab 中对其进行配置. + +## Create webhook[](#create-webhook "Permalink") + +1. 打开您要接收 GitLab 事件通知的 Discord 频道. +2. 在频道菜单中,选择**编辑频道** . +3. 单击**Webhooks**菜单项. +4. 单击**创建 Webhook**按钮,然后填写将发布消息的机器人的名称. (可选)编辑头像. +5. 记下" **WEBHOOK URL"**字段中的**URL** . +6. 单击**保存**按钮. + +## Configure created webhook in GitLab[](#configure-created-webhook-in-gitlab "Permalink") + +使用在 Discord 频道中创建的 webhook URL,可以在 GitLab 中设置 Discord Notifications 服务. + +1. 导航到项目设置中的" [集成"页面](overview.html#accessing-integrations) . 也就是说, **项目>设置>集成** . +2. 选择" **Discord Notifications"**集成进行配置. +3. 确保启用了**活动**切换. +4. 选中与您要向 Discord 发送通知的 GitLab 事件相对应的复选框. +5. 粘贴您从创建 Discord Webhook 步骤复制的 Webhook URL. +6. 配置其余选项,然后单击" **保存更改"**按钮. + +您创建了 Webhook 的 Discord 频道现在将收到有关已配置的 GitLab 事件的通知. \ No newline at end of file diff --git a/_book/docs/078.md b/_book/docs/078.md new file mode 100644 index 0000000000000000000000000000000000000000..ac0f83415411b8dab1b32f9999d02515a30dedaf --- /dev/null +++ b/_book/docs/078.md @@ -0,0 +1,22 @@ +# Enabling emails on push + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/emails_on_push.html](https://docs.gitlab.com/ee/user/project/integrations/emails_on_push.html) + +# Enabling emails on push[](#enabling-emails-on-push "Permalink") + +通过启用此服务,您将收到有关推送至项目的每个更改的电子邮件通知. + +在" [集成"页面中,](overview.html#accessing-integrations)选择**"推送**服务中的**电子邮件"**以激活和配置它. + +在" *收件人"*区域中,提供用空格或换行符分隔的电子邮件列表. + +提供以下选项: + +* **推送事件** -收到推送事件时将触发电子邮件. +* **标记推送事件** -创建和推送标记时将触发电子邮件. +* **从提交者**发送-如果该域是运行 GitLab 的域的一部分,则从提交者的电子邮件地址发送通知(例如`user@gitlab.com` ). +* **禁用代码差异** -通知正文中不要包含敏感的代码差异. + +| Settings | Notification | +| --- | --- | +| [![Email on push service settings](img/b4a1ffd094e753d655825c1385561991.png)](img/emails_on_push_service.png) | [![Email on push notification](img/906ca69aaf7c7a7f53479eb595f83ec0.png)](img/emails_on_push_email.png) | \ No newline at end of file diff --git a/_book/docs/079.md b/_book/docs/079.md new file mode 100644 index 0000000000000000000000000000000000000000..92999577b276f3f042dc55097214f8b332393e0a --- /dev/null +++ b/_book/docs/079.md @@ -0,0 +1,53 @@ +# GitHub project integration + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/github.html](https://docs.gitlab.com/ee/user/project/integrations/github.html) + +* [Configuration](#configuration) + * [Complete these steps on GitHub](#complete-these-steps-on-github) + * [Complete these steps on GitLab](#complete-these-steps-on-gitlab) + * [Static / dynamic status check names](#static--dynamic-status-check-names) + +# GitHub project integration[](#github-project-integration-premium "Permalink") + +在 GitLab Premium 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/3836) . + +GitLab 提供了一个集成,用于更新 GitHub 上的管道状态. 如果仅将 GitLab 用于 CI / CD,这将特别有用. + +此项目集成与[实例范围的 GitHub 集成](../import/github.html#mirroring-and-pipeline-status-sharing)分开,并且在[GitHub import](../../../integration/github.html)上自动配置. + +[![Pipeline status update on GitHub](img/e3e09b090e6c8612f71f6dbd7244cbb2.png)](img/github_status_check_pipeline_update.png) + +## Configuration[](#configuration "Permalink") + +### Complete these steps on GitHub[](#complete-these-steps-on-github "Permalink") + +此集成需要[GitHub API 令牌,](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token)并授予`repo:status`访问权限: + +1. 转到[https://github.com/settings/tokens 上的](https://github.com/settings/tokens) "个人访问令牌"页面. +2. 点击"生成新令牌" +3. 确保选中`repo:status`并单击" Generate token" +4. 复制生成的令牌以在 GitLab 上使用 + +### Complete these steps on GitLab[](#complete-these-steps-on-gitlab "Permalink") + +1. Navigate to the project you want to configure. +2. 导航到" [集成"页面](overview.html#accessing-integrations) +3. 点击" GitHub". +4. 确保启用了**活动**切换. +5. 粘贴您在 GitHub 上生成的令牌 +6. 输入您在 GitHub 上的项目的路径,例如`https://github.com/username/repository` +7. (可选)取消选中" **静态状态检查名称"**复选框以禁用静态状态检查名称. +8. 保存或选择单击"测试设置". + +配置完集成后,请参阅[外部请求请求的](../../../ci/ci_cd_for_external_repos/#pipelines-for-external-pull-requests)管道,以配置要为打开请求请求运行的管道. + +#### Static / dynamic status check names[](#static--dynamic-status-check-names "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入:使用静态检查名称作为选择加入选项. +* [在 GitLab 12.4 中](https://gitlab.com/gitlab-org/gitlab/-/issues/9931) ,静态状态检查名称是新项目的默认行为. + +This makes it possible to mark these status checks as *Required* on GitHub. 这样就可以在 GitHub 上将这些状态检查标记为" *必需* ". With **Static status check names** enabled on the integration page, your GitLab instance host name is going to be appended to a status check name, whereas in case of dynamic status check names, a branch name is going to be appended. 在集成页面上启用了**静态状态检查名称后** ,您的 GitLab 实例主机名将被附加到状态检查名称中,而在动态状态检查名的情况下将被添加分支名称. + +[![Configure GitHub Project Integration](img/9101937463fa0be989f93d09d9f54d7a.png)](img/github_configuration.png) \ No newline at end of file diff --git a/_book/docs/080.md b/_book/docs/080.md new file mode 100644 index 0000000000000000000000000000000000000000..173779b0aa46c881710c03b55150d8fcaa68ed89 --- /dev/null +++ b/_book/docs/080.md @@ -0,0 +1,36 @@ +# Hangouts Chat service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/hangouts_chat.html](https://docs.gitlab.com/ee/user/project/integrations/hangouts_chat.html) + +* [On Hangouts Chat](#on-hangouts-chat) +* [On GitLab](#on-gitlab) + +# Hangouts Chat service[](#hangouts-chat-service "Permalink") + +在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/43756) . + +环聊聊天服务将通知从 GitLab 发送到创建 Webhook 的房间. + +## On Hangouts Chat[](#on-hangouts-chat "Permalink") + +1. 打开要在其中查看通知的聊天室. +2. 从聊天室菜单中,选择**配置 Webhooks** . +3. 单击**添加网站,**然后填写将发布消息的机器人的名称. (可选)定义头像. +4. 单击" **保存",**然后复制您的**Webhook 的 Webhook URL** . + +另请参阅[环聊聊天文档,以配置传入的 Webhooks](https://developers.google.com/hangouts/chat/how-tos/webhooks) + +## On GitLab[](#on-gitlab "Permalink") + +当您拥有环**聊聊天**室**Webhook 的 Webhook URL 时** ,您可以设置 GitLab 服务. + +1. 导航到项目设置中的" [集成"页面](overview.html#accessing-integrations) ,即" **项目">"设置">"集成"** . +2. 选择**环聊聊天**集成进行配置. +3. 确保启用了**活动**切换. +4. 选中与您要接收的 GitLab 事件相对应的复选框. +5. 粘贴您从环**聊聊天**配置步骤中复制的**Webhook URL** . +6. 配置其余选项,然后单击" `Save changes` . + +您的环聊聊天室现在将开始接收配置的 GitLab 事件通知. + +[![Hangouts Chat configuration](img/5f87ce250e2ea1a803a3aeda446eca15.png)](img/hangouts_chat_configuration.png) \ No newline at end of file diff --git a/_book/docs/081.md b/_book/docs/081.md new file mode 100644 index 0000000000000000000000000000000000000000..05c94c705ab873fb774d4aecb2878e2d85c3a08f --- /dev/null +++ b/_book/docs/081.md @@ -0,0 +1,50 @@ +# Atlassian HipChat + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/hipchat.html](https://docs.gitlab.com/ee/user/project/integrations/hipchat.html) + +* [Setup](#setup) + * [Complete these steps in HipChat](#complete-these-steps-in-hipchat) + * [Complete these steps in GitLab](#complete-these-steps-in-gitlab) +* [Troubleshooting](#troubleshooting) + +# Atlassian HipChat[](#atlassian-hipchat "Permalink") + +GitLab 提供了一种在许多事件(例如,当用户按下代码,创建分支或标签,添加注释以及创建合并请求)时发送 HipChat 通知的方法. + +## Setup[](#setup "Permalink") + +GitLab 要求使用 HipChat v2 API 令牌才能工作. 目前不支持 v1 令牌. 注意 v1 和 v2 令牌之间的区别: + +HipChat v1 API(旧版)在" Group API"菜单中支持" API Auth Tokens". 允许使用 v1 令牌将消息发送到*任何*房间. + +HipChat v2 API 具有可以使用"组"或"房间"管理页面中的"集成"选项卡创建的令牌. 根据设计,这些是轻量级令牌,允许 GitLab 仅将消息发送到*一个*房间. + +### Complete these steps in HipChat[](#complete-these-steps-in-hipchat "Permalink") + +1. 转到: `https://admin.hipchat.com/admin` : `https://admin.hipchat.com/admin` +2. 单击"组管理员"->"集成". +3. 找到"自己动手!" 然后点击"创建". +4. 选择所需的房间,将集成命名为" GitLab",然后单击"创建". +5. 在"通过发布此 URL 将消息发送到此房间"列中,您应该看到以下格式的 URL: + +``` +https://api.hipchat.com/v2/room//notification?auth_token= +``` + +HipChat 现在准备接受来自 GitLab 的消息. 接下来,在 GitLab 中设置 HipChat 服务. + +### Complete these steps in GitLab[](#complete-these-steps-in-gitlab "Permalink") + +1. 导航到您要为通知配置的项目. +2. 导航到" [集成"页面](overview.html#accessing-integrations) +3. 点击" HipChat". +4. 确保启用了**活动**切换. +5. 插入`token`从 URL 字段进入`Token`在 Web 页面上的字段. +6. 插入`room`从 URL 字段进入`Room`在 Web 页面上字段. +7. 保存或选择单击"测试设置". + +## Troubleshooting[](#troubleshooting "Permalink") + +如果没有看到通知,请确保您使用的是 HipChat v2 API 令牌,而不是 v1 令牌. + +请注意,v2 令牌绑定到特定房间. 如果希望能够指定任意房间,则可以在 HipChat 中"帐户设置"和" API 访问"下为特定用户创建 API 令牌. 使用`auth_token=XXX`下的`XXX`值. \ No newline at end of file diff --git a/_book/docs/082.md b/_book/docs/082.md new file mode 100644 index 0000000000000000000000000000000000000000..0c9029f818764e75ca9afb978af4329194e187e2 --- /dev/null +++ b/_book/docs/082.md @@ -0,0 +1,43 @@ +# Irker IRC Gateway + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/irker.html](https://docs.gitlab.com/ee/user/project/integrations/irker.html) + +* [Needed setup](#needed-setup) +* [Complete these steps in GitLab](#complete-these-steps-in-gitlab) +* [Note on Irker recipients](#note-on-irker-recipients) + +# Irker IRC Gateway[](#irker-irc-gateway "Permalink") + +GitLab 提供了一种将更新消息推送到 Irker 服务器的方法. 配置后,推送到项目将触发服务将数据直接发送到 Irker 服务器. + +有关更多信息,请参见项目主页: [https](https://gitlab.com/esr/irker) : [//gitlab.com/esr/irker](https://gitlab.com/esr/irker) + +## Needed setup[](#needed-setup "Permalink") + +您首先需要一个 Irker 守护程序. 您可以从[https://gitlab.com/esr/irker 的](https://gitlab.com/esr/irker)存储库中下载 Irker 代码: + +``` +git clone https://gitlab.com/esr/irker.git +``` + +下载代码后,您可以运行名为`irkerd`的 Python 脚本. 该脚本是网关脚本,它既充当 IRC 客户端(用于显然将消息发送到 IRC 服务器),又充当 TCP 服务器(用于从 GitLab 服务接收消息). + +如果 Irker 服务器在同一台计算机上运行,​​则操作完成. 如果没有,您将需要遵循下一部分的第一步. + +## Complete these steps in GitLab[](#complete-these-steps-in-gitlab "Permalink") + +1. 导航到您要为通知配置的项目. +2. 导航到" [集成"页面](overview.html#accessing-integrations) +3. Click “Irker”. +4. 确保启用了**活动**切换. +5. 在网页的" `Server host`字段中输入`irkerd`运行的服务器主机地址(默认为`localhost` ). +6. 在网页的" `Server port`字段中输入`irkerd`的服务器端口(例如,默认为 6659). +7. 可选:如果设置了`Default IRC URI` ,则其格式必须为`irc[s]://domain.name`并且将`irc[s]://domain.name`在用户提供的每个通道(不是完整 URI)之前. +8. 指定收件人(例如,#channel1,user1 等) +9. 保存或选择单击"测试设置". + +## Note on Irker recipients[](#note-on-irker-recipients "Permalink") + +Irker 接受形式的信道名称`chan`和`#chan`为,既`#chan`通道. 如果要在查询中发送消息,则需要在频道名称后添加`,isnick` ,格式为: `Aorimn,isnick` . 在后一种情况下, `Aorimn`被视为昵称,而不再被视为频道名称. + +Irker 也可以加入受密码保护的频道. 用户需要在 chan 名称后附加`?key=thesecretpassword` . 使用此功能时,请记住**不要**在频道名称前加上`#`号; 否则,irker 会加入一个字面名为`#chan?key=password`的通道,此后将通过`/whois` IRC 命令(取决于 IRC 服务器配置)泄漏该通道密钥. 这是由于长期存在的虫虫. \ No newline at end of file diff --git a/_book/docs/083.md b/_book/docs/083.md new file mode 100644 index 0000000000000000000000000000000000000000..9be472f031b38d690e7bb73d34806e941b2dce2e --- /dev/null +++ b/_book/docs/083.md @@ -0,0 +1,178 @@ +# GitLab Jira integration + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/jira.html](https://docs.gitlab.com/ee/user/project/integrations/jira.html) + +* [Configuration](#configuration) + * [Configuring Jira](#configuring-jira) + * [Jira Server](#jira-server) + * [Jira Cloud](#jira-cloud) + * [Configuring GitLab](#configuring-gitlab) + * [Obtaining a transition ID](#obtaining-a-transition-id) + * [Disabling comments on Jira issues](#disabling-comments-on-jira-issues) +* [Jira issues](#jira-issues) + * [Referencing Jira Issues](#referencing-jira-issues) + * [Closing Jira Issues](#closing-jira-issues) + * [Jira issue closing example](#jira-issue-closing-example) +* [Troubleshooting](#troubleshooting) + * [GitLab is unable to comment on a Jira issue](#gitlab-is-unable-to-comment-on-a-jira-issue) + * [GitLab is unable to close a Jira issue](#gitlab-is-unable-to-close-a-jira-issue) + * [CAPTCHA](#captcha) + +# GitLab Jira integration[](#gitlab-jira-integration "Permalink") + +GitLab 问题是讨论想法,计划和跟踪工作的强大工具. 但是,许多组织已经将 Jira 用于这些目的,并且内置了广泛的数据和业务流程. + +尽管您始终可以将内容和流程从 Jira 迁移到 GitLab Issue,但是您也可以选择继续使用 Jira,并通过我们的集成将其与 GitLab 一起使用. + +有关与 Jira 集成的视频演示,请观看有关[GitLab 工作流程的 Jira 问题和 Jenkins 管道](https://youtu.be/Jn-_fyra7xQ) . + +将 GitLab 项目与 Jira 实例集成后,即可自动检测 GitLab 项目与 Jira 中的任何项目之间的活动并进行交叉引用. 这包括在 GitLab 中完成工作后关闭或转换 Jira 问题的功能. + +在 GitLab 中执行以下操作时,集成的响应方式如下: + +* 在提交消息或 MR(合并请求)中**提及 Jira 问题 ID** . + * GitLab 超链接至 Jira 问题. + * Jira 问题将问题链接添加到 GitLab 中的提交/ MR. + * Jira 问题会添加评论,以反映在 GitLab 中发表的评论,评论作者以及在 GitLab 中指向 commit / MR 的链接,除非[禁用了](#disabling-comments-on-jira-issues)对 Jira 的评论. +* **提及提交或 MR"关闭","解决"或"修复" Jira 问题 ID** . 在项目的默认分支(通常是主分支)上进行提交或将更改合并到默认分支时: + * GitLab 的合并请求页面显示一条注释,指出"已关闭" Jira 问题,并带有指向该问题的链接. (注意:在合并之前,MR 将显示它"关闭"了 Jira 问题.) + * Jira 问题显示活动,并且 Jira 问题已关闭或已转换. + +您还可以直接从 GitLab 使用[Jira 的 Smart](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html) Commit,如文章[如何以及为什么将 GitLab 与 Jira 集成中所述](https://www.programmableweb.com/news/how-and-why-to-integrate-gitlab-jira/how-to/2017/04/25) . + +## Configuration[](#configuration "Permalink") + +每个 GitLab 项目都可以配置为连接到整个 Jira 实例. 这意味着一个 GitLab 项目一旦配置,便可以与该实例中的*所有* Jira 项目进行交互. 因此,您不必将 GitLab 项目与任何单个 Jira 项目显式关联. + +如果您有一个 Jira 实例,则可以使用默认模板预先填充设置页面. 请参阅[服务模板](services_templates.html)文档. + +为了在 GitLab 中启用 Jira 服务,您需要首先在 Jira 中配置项目,然后在 GitLab 中输入正确的值. + +### Configuring Jira[](#configuring-jira "Permalink") + +#### Jira Server[](#jira-server "Permalink") + +**Jira Server**支持基本身份验证. 连接时,需要**用户名和密码** . 请注意,无法通过 CAS 连接到 Jira Server. 首先[在 Jira Server 中设置用户,](jira_server_configuration.html)然后继续[配置 GitLab](#configuring-gitlab) . + +#### Jira Cloud[](#jira-cloud "Permalink") + +**Jira Cloud**支持通过 API 令牌进行身份验证. 连接到**Jira Cloud 时** ,需要**电子邮件和 API 令牌** . 首先[在 Jira Cloud 中设置用户,](jira_cloud_configuration.html)然后继续[配置 GitLab](#configuring-gitlab) . + +### Configuring GitLab[](#configuring-gitlab "Permalink") + +> **Notes:** +> +> * 当前支持的 Jira 版本是`v6.x, v7.x, v8.x` . 需要 GitLab 7.8 或更高版本. +> * GitLab 8.14 引入了一种与 Jira 集成的新方法,该方法大大简化了您必须输入的配置选项. 如果您使用的是旧版本,请[遵循此文档](https://gitlab.com/gitlab-org/gitlab/blob/8-13-stable-ee/doc/project_services/jira.md) . +> * 为了支持 Oracle 的 Access Manager,GitLab 将发送其他 cookie 以启用基本身份验证. 添加到每个请求的 cookie 是`OBBasicAuth` ,其值为`fromDialog` . + +要在项目中启用 Jira 集成,请导航到[Integrations 页面](overview.html#accessing-integrations) ,单击**Jira**服务,然后按照下表中的说明在页面上填写所需的详细信息. + +| Field | Description | +| --- | --- | +| `Web URL` | 链接到此 GitLab 项目的 Jira 实例 Web 界面的基本 URL. 例如, `https://jira.example.com` . | +| `Jira API URL` | The base URL to the Jira instance API. Web URL value will be used if not set. E.g., `https://jira-api.example.com`. Leave this field blank (or use the same value of `Web URL`) if using **吉拉云**. | +| `Username/Email` | 在[配置 Jira step](#configuring-jira)时创建. 将`username`用于**Jira Server**或将`email`用于**Jira Cloud** . | +| `Password/API token` | 在[配置 Jira 步骤中](#configuring-jira)创建. 为**Jira Server**使用`password`或为**Jira Cloud**使用`API token` . | +| `Transition ID` | 这是将问题移至所需状态的过渡的 ID. 它可以插入过渡 IDS 分离通过`,`或`;` 这意味着将按照给定的顺序将问题逐个移至每个州. **如果您未正确设置 ID,则无法通过提交或合并请求来关闭 Jira 问题.** | + +### Obtaining a transition ID[](#obtaining-a-transition-id "Permalink") + +在最新的 Jira 用户界面中,您不再可以在工作流管理 UI 中看到过渡 ID. 您可以通过以下两种方式之一获取所需的 ID: + +1. 通过使用 API​​,并使用诸如处于适当"打开"状态的问题的请求(例如`https://yourcompany.atlassian.net/rest/api/2/issue/ISSUE-123/transitions` +2. 通过将鼠标悬停在所需转换的链接上并在 URL 中查找" action"参数 + +请注意,即使您要更改的状态相同,过渡 ID 在工作流之间也可能有所不同(例如,错误与故事). + +保存配置后,您的 GitLab 项目将能够与 Jira 实例中的所有 Jira 项目进行交互,并且您将在 GitLab 项目页面上看到 Jira 链接,该链接将您带到适当的 Jira 项目. + +[![Jira service page](img/ebaf329b1a5a45f2d451e4574f3d7857.png)](img/jira_service_page_v12_2.png) + +### Disabling comments on Jira issues[](#disabling-comments-on-jira-issues "Permalink") + +当您引用 Jira 问题时,它将始终链接回 GitLab 中的源提交/ MR,但是,您可以控制 GitLab 是否还将交叉发布对 Jira 问题的评论. 默认情况下启用该功能. + +要禁用对 Jira 问题的自动评论: + +1. 打开" [集成"页面,](overview.html#accessing-integrations)然后选择**Jira** . +2. 在" **事件操作"**部分中,取消选中" **注释"** . + +## Jira issues[](#jira-issues "Permalink") + +现在,您应该已经[配置了 Jira](#configuring-jira)并[在 GitLab 中](#configuring-gitlab)启用了[Jira 服务](#configuring-gitlab) . 如果一切设置正确,您应该能够通过在 GitLab 提交和合并请求中提及 ID 来引用和关闭 Jira 问题. + +### Referencing Jira Issues[](#referencing-jira-issues "Permalink") + +当 GitLab 项目配置并启用了 Jira 问题跟踪器时,在 GitLab 中提及 Jira 问题将自动在 Jira 问题中添加评论,并带有返回到 GitLab 的链接. 这意味着在合并请求和提交中引用问题的注释中,例如`PROJECT-7` ,将在 Jira issue 中添加以下格式的注释: + +``` +USER mentioned this issue in RESOURCE_NAME of [PROJECT_NAME|LINK_TO_COMMENT]: +ENTITY_TITLE +``` + +* `USER`提到问题的用户. 这是指向 GitLab 中的用户配置文件的链接. +* `LINK_TO_THE_COMMENT`链接到提及的来源,带有提及吉拉问题的实体的名称. +* `RESOURCE_NAME`引用该问题的`RESOURCE_NAME`种类. 可以是提交或合并请求. +* `PROJECT_NAME` GitLab 项目名称. +* `ENTITY_TITLE`合并请求标题或提交消息的第一行. + +[![example of mentioning or closing the Jira issue](img/bf46825f18b4b1998d719dffeab0c45c.png)](img/jira_issue_reference.png) + +例如,以下提交将引用以`PROJECT-1`作为 ID 的 Jira 问题: + +``` +git commit -m "PROJECT-1 Fix spelling and grammar" +``` + +### Closing Jira Issues[](#closing-jira-issues "Permalink") + +通过在提交和合并请求中使用触发词,可以直接从 GitLab 关闭 Jira 问题. 当推送包含触发词并在提交消息中包含 Jira 问题 ID 的提交时,GitLab 将在提到的 Jira 问题中添加注释,并立即将其关闭(前提是正确设置了转换 ID). + +当前有三个触发词,您可以使用其中一个来实现相同的目标: + +* `Resolves PROJECT-1` +* `Closes PROJECT-1` +* `Fixes PROJECT-1` + +其中`PROJECT-1`是 Jira 问题的 ID. + +> **Notes:** +> +> * 只有提交并合并到项目的默认分支(通常是**master** )才能关闭 Jira 中的问题. 您可以在[项目设置](img/jira_project_settings.png)下更改项目默认分支. +> * 如果有解决方案,那么 Jira 问题将不会过渡. + +### Jira issue closing example[](#jira-issue-closing-example "Permalink") + +让我们考虑以下示例: + +1. 对于 Jira 中名为`PROJECT` ,我们实现了一项新功能,并在 GitLab 中创建了合并请求. +2. This feature was requested in Jira issue `PROJECT-7` and the merge request in GitLab contains the improvement +3. 在合并请求描述中,我们使用问题关闭触发器`Closes PROJECT-7` . +4. 合并请求合并后,Jira 问题将自动关闭,并带有注释和指向解决该问题的提交的关联链接. + +在以下屏幕截图中,您可以看到指向 Jira 问题的链接的外观. + +[![A Git commit that causes the Jira issue to be closed](img/381000c5f5c6ad01300dfcc889f7fb0f.png)](img/jira_merge_request_close.png) + +合并此合并请求后,将通过指向解决该问题的提交的链接自动关闭 Jira 问题. + +[![The GitLab integration closes Jira issue](img/ae54430a80c08d51c51659ac1a4dd8b9.png)](img/jira_service_close_issue.png) + +## Troubleshooting[](#troubleshooting "Permalink") + +如果这些功能不能按预期方式工作,则可能是由于集成设置的配置存在问题. + +### GitLab is unable to comment on a Jira issue[](#gitlab-is-unable-to-comment-on-a-jira-issue "Permalink") + +如果您希望 GitLab 也可以这样做,请确保您为集成设置的 Jira 用户具有正确的访问权限,可以发表有关 Jira 问题的评论并转换问题. 如果禁用了 GitLab 问题跟踪器,则 Jira 问题参考和更新注释将不起作用. + +### GitLab is unable to close a Jira issue[](#gitlab-is-unable-to-close-a-jira-issue "Permalink") + +确保在" Jira"设置中设置的" `Transition ID`与您的项目解决问题所需的`Transition ID`匹配. + +确保尚未将 Jira 问题标记为已解决; 也就是说,未设置" Jira 问题解决"字段. (不应在 Jira 列表中删除它.) + +### CAPTCHA[](#captcha "Permalink") + +在连续几次失败的登录尝试后,可能会触发 CAPTCHA,这可能会在测试 Jira 集成时导致`401 unauthorized`错误. 如果已触发验证码,则您将无法使用 Jira 的 REST API 对 Jira 站点进行身份验证. 您将需要登录到您的 Jira 实例并完成 CAPTCHA. \ No newline at end of file diff --git a/_book/docs/084.md b/_book/docs/084.md new file mode 100644 index 0000000000000000000000000000000000000000..cbe7b6a254b73e7373a167d9661bdd1d8c81e1f1 --- /dev/null +++ b/_book/docs/084.md @@ -0,0 +1,57 @@ +# Mattermost Notifications Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/mattermost.html](https://docs.gitlab.com/ee/user/project/integrations/mattermost.html) + +* [On Mattermost](#on-mattermost) +* [On GitLab](#on-gitlab) + +# Mattermost Notifications Service[](#mattermost-notifications-service "Permalink") + +Mattermost Notifications Service 允许您的 GitLab 项目将事件(例如, `issue created` )作为通知发送到您现有的 Mattermost 团队. 这需要在 Mattermost 和 GitLab 中进行配置. + +您还可以使用 Mattermost 斜杠命令来控制 Mattermost 中的 GitLab. 这是单独配置的[Mattermost 斜杠命令](mattermost_slash_commands.html) . + +## On Mattermost[](#on-mattermost "Permalink") + +要启用 Mattermost 集成,您必须创建传入的 Webhook 集成: + +1. 登录到您的 Mattermost 实例. +2. 访问传入的 Webhooks,类似于: `https://mattermost.example.com/your_team_name/integrations/incoming_webhooks/add` ://mattermost.example.com/your_team_name/integrations/incoming_webhooks/add. +3. 选择显示名称,描述和通道,可以在 GitLab 上覆盖它们. +4. 保存它,复制**Webhook URL** ,稍后我们将在 GitLab 中使用它. + +传入的 Webhooks 可能在您的 Mattermost 实例上被阻止. 要求您的 Mattermost 管理员启用它: + +* **Mattermost** 5.12 及更高版本中的**Mattermost 系统控制台>集成>集成管理** . +* **Mattermost** 5.11 及更低版本中的**Mattermost 系统控制台>集成>自定义集成** . + +默认情况下,不启用显示名称覆盖,您需要让您的管理员在同一部分启用它. + +## On GitLab[](#on-gitlab "Permalink") + +设置 Mattermost 之后,就该设置 GitLab 了. + +导航到" [集成"页面,](overview.html#accessing-integrations)然后选择"最**重要的通知"**服务以对其进行配置. 在那里,您将看到一个带有以下可触发事件的复选框: + +* Push +* Issue +* 机密问题 +* 合并要求 +* Note +* 机密说明 +* 标签推送 +* Pipeline +* 维基页面 +* Deployment + +在每个事件复选框的下方,都有一个输入字段,用于输入您要发送该事件消息的 Mattermost 频道. 输入您首选的频道句柄(井号`#`是可选的). + +最后,填写您最重要的详细信息: + +| Field | Description | +| --- | --- | +| **Webhook** | 您必须在 Mattermost 上设置的传入 Webhook URL,它类似于: `http://mattermost.example/hooks/5xo…` | +| **Username** | 可选的用户名,可以在发送给 Mattermost 的邮件中使用. 如果要更改机器人的用户名,请填写. | +| **仅通知断开的管道** | 如果您选择启用**管道**事件,并且只希望收到有关失败管道的通知. | + +[![Mattermost configuration](img/95c0b87af108caee2a239482aec61675.png)](img/mattermost_configuration.png) \ No newline at end of file diff --git a/_book/docs/085.md b/_book/docs/085.md new file mode 100644 index 0000000000000000000000000000000000000000..005323550152081512b764cb7124cbfc89431dae --- /dev/null +++ b/_book/docs/085.md @@ -0,0 +1,137 @@ +# Mattermost slash commands + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/mattermost_slash_commands.html](https://docs.gitlab.com/ee/user/project/integrations/mattermost_slash_commands.html) + +* [Prerequisites](#prerequisites) +* [Automated configuration](#automated-configuration) +* [Manual configuration](#manual-configuration) + * [Step 1\. Enable custom slash commands in Mattermost](#step-1-enable-custom-slash-commands-in-mattermost) + * [Step 2\. Open the Mattermost slash commands service in GitLab](#step-2-open-the-mattermost-slash-commands-service-in-gitlab) + * [Step 3\. Create a new custom slash command in Mattermost](#step-3-create-a-new-custom-slash-command-in-mattermost) + * [Step 4\. Copy the Mattermost token into the Mattermost slash command service](#step-4-copy-the-mattermost-token-into-the-mattermost-slash-command-service) +* [Authorizing Mattermost to interact with GitLab](#authorizing-mattermost-to-interact-with-gitlab) +* [Available slash commands](#available-slash-commands) +* [Permissions](#permissions) +* [Troubleshooting](#troubleshooting) +* [Further reading](#further-reading) + +# Mattermost slash commands[](#mattermost-slash-commands "Permalink") + +在 GitLab 8.14 中引入 + +Mattermost 命令为用户提供了一个额外的界面,可以在聊天环境中执行常见操作. 例如,这使得一个问题一经在 Mattermost 中讨论后就可以创建. + +GitLab 还可以将事件(例如, `issue created` )作为通知发送到 Mattermost. 这是单独配置的[Mattermost Notifications Service](mattermost.html) . + +## Prerequisites[](#prerequisites "Permalink") + +需要 Mattermost 3.4 及更高版本. + +如果您安装了 Omnibus GitLab 软件包,则其中已包含 Mattermost. 您所要做的就是配置它. 在[Omnibus GitLab Mattermost 文档中](https://docs.gitlab.com/omnibus/gitlab-mattermost/)阅读更多[内容](https://docs.gitlab.com/omnibus/gitlab-mattermost/) . + +## Automated configuration[](#automated-configuration "Permalink") + +如果 Mattermost 与 GitLab 安装在同一服务器上,则 GitLab 可以为您完成配置过程. + +转到项目上的 Mattermost Slash Command 服务,然后单击"添加到 Mattermost"按钮. + +## Manual configuration[](#manual-configuration "Permalink") + +配置由两部分组成. 首先,您需要在 Mattermost 中启用斜杠命令,然后在 GitLab 中启用该服务. + +### Step 1\. Enable custom slash commands in Mattermost[](#step-1-enable-custom-slash-commands-in-mattermost "Permalink") + +仅在使用源代码安装时才需要执行此步骤,Omnibus 安装将使用正确的设置进行预配置. + +在 Mattermost 中要做的第一件事是从管理员控制台启用自定义斜杠命令. + +1. 使用具有管理员权限的帐户登录并导航至系统控制台. + + [![Mattermost go to console](img/e9fe43924bd4226e7b819104bcc8b8c1.png)](img/mattermost_goto_console.png) + +2. 单击" **自定义集成"**并将" **启用自定义斜杠命令"** ," **启用自定义集成以覆盖用户名** "和" **覆盖自定义集成以覆盖个人资料图片图标"设置**为 true. + + [![Mattermost console](img/75ffde23ab0100e58532632d19b84db0.png)](img/mattermost_console_integrations.png) + +3. 点击底部的**保存** ,保存更改. + +### Step 2\. Open the Mattermost slash commands service in GitLab[](#step-2-open-the-mattermost-slash-commands-service-in-gitlab "Permalink") + +1. 打开 GitLab 的新标签,转到项目的" [集成"页面,](overview.html#accessing-integrations)然后选择**Mattermost 命令**服务进行配置. 将出现一个屏幕,其中包含您需要在 Mattermost 中复制的所有值,如下一步所述. 使窗口保持打开状态. + + **注意:** GitLab 将为"最重要的设置"建议一些值. 原样复制粘贴的唯一要求是**请求 URL** ,所有其他都只是建议. + + [![Mattermost setup instructions](img/801adc20d157f18e08adbd379180f3c7.png)](img/mattermost_config_help.png) + +2. 继续下一步,并在 Mattermost 中使用上述值创建斜线命令. + +### Step 3\. Create a new custom slash command in Mattermost[](#step-3-create-a-new-custom-slash-command-in-mattermost "Permalink") + +现在,您已在 Mattermost 中启用了自定义斜杠命令并在 GitLab 中打开了 Mattermost 斜杠命令服务,是时候将这些值复制到新的斜杠命令中了. + +1. 回到 Mattermost,在团队页面设置下,您应该看到**Integrations**选项. + + [![Mattermost team integrations](img/d7b5490ec5cb26ce71f19d5c56f003f3.png)](img/mattermost_team_integrations.png) + +2. 转到**Slash Commands**集成,然后单击**Add Slash Command**按钮添加一个新的. + + [![Mattermost add command](img/3694fc45636610ba5fb4e24d7a9eb3b9.png)](img/mattermost_add_slash_command.png) + +3. 按照[步骤 2 中的说明](#step-2-open-the-mattermost-slash-commands-service-in-gitlab)填写自定义命令的选项. + + **注意:**如果计划连接多个项目,请选择一个与项目相关的斜杠命令触发词,例如`/gitlab-project-name`或什至`/project-name` . 仅在将单个项目连接到 Mattermost 团队时才使用`/gitlab` . + + [![Mattermost add command configuration](img/1fdfdef058a3092e25352089de97fee6.png)](img/mattermost_slash_command_configuration.png) + +4. 设置所有值之后,复制令牌(我们将在下面使用它)并单击**完成** . + + [![Mattermost slash command token](img/41571e3a155c671e6ff9f259f20fdeed.png)](img/mattermost_slash_command_token.png) + +### Step 4\. Copy the Mattermost token into the Mattermost slash command service[](#step-4-copy-the-mattermost-token-into-the-mattermost-slash-command-service "Permalink") + +1. 在 GitLab 中,粘贴您在上一步中复制的最重要的令牌,并确保启用了**活动**切换. + + [![Mattermost copy token to GitLab](img/07c2c84efb64460dfa2373f1f75645ab.png)](img/mattermost_gitlab_token.png) + +2. 单击**保存更改**以使更改生效. + +现在,您已设置为在 Mattermost 中开始使用与您配置的 GitLab 项目对话的斜杠命令. + +## Authorizing Mattermost to interact with GitLab[](#authorizing-mattermost-to-interact-with-gitlab "Permalink") + +用户首次与新创建的斜杠命令进行交互时,Mattermost 将触发授权过程. + +[![Mattermost bot authorize](img/6e17896087b8446f53400a1c8d39c0d6.png)](img/mattermost_bot_auth.png) + +这会将您的 Mattermost 用户与 GitLab 用户连接起来. 您可以在个人资料页面的" **聊天"**下看到所有授权的聊天帐户. + +授权过程完成后,您可以使用 Mattermost 命令开始与 GitLab 进行交互. + +## Available slash commands[](#available-slash-commands "Permalink") + +可用的斜杠命令是: + +| Command | Description | Example | +| --- | --- | --- | +| `/ 发出新的 `⇧Shift` + `↵输入` <description>` | 在与`<trigger>`绑定的项目中创建一个新问题. `<description>`是可选的. | `/gitlab issue new We need to change the homepage` | +| `/<trigger> issue show <issue-number>` | 显示与`<trigger>`绑定的项目中 ID 为`<issue-number>` . | `/gitlab issue show 42` | +| `/ <触发>将<环境>部署到<环境>` | 开始从一个环境部署到另一环境的 CI 作业,例如`staging`到`production` . CI / CD 必须[正确配置](../../../ci/yaml/README.html) . | `/gitlab deploy staging to production` | + +要查看与 GitLab 交互的可用命令列表,请输入触发词,然后输入`help` . 示例: `/gitlab help` + +[![Mattermost bot available commands](img/0c549416181d6e18eb1dd34825b00425.png)](img/mattermost_bot_available_commands.png) + +## Permissions[](#permissions "Permalink") + +运行[可用命令](#available-slash-commands)的[权限](../../permissions.html#project-members-permissions)源自[您对项目](../../permissions.html#project-members-permissions)的[权限](../../permissions.html#project-members-permissions) . + +## Troubleshooting[](#troubleshooting "Permalink") + +如果未触发某个事件,请确认您使用的频道是公开频道,因为 Mattermost Webhooks 无法访问私有频道. + +如果需要专用频道,则可以在 Mattermost 中编辑 Webhook 的频道并选择一个专用频道. 无法将不同的通道用于不同类型的通知-所有事件都将发送到指定的通道. + +## Further reading[](#further-reading "Permalink") + +* [Mattermost slash commands documentation](https://docs.mattermost.com/developer/slash-commands.html) +* [Omnibus GitLab Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/) \ No newline at end of file diff --git a/_book/docs/086.md b/_book/docs/086.md new file mode 100644 index 0000000000000000000000000000000000000000..ebb6d65f6cae4a7377bdf1f89c6ae3aef951ca41 --- /dev/null +++ b/_book/docs/086.md @@ -0,0 +1,38 @@ +# Microsoft Teams service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/microsoft_teams.html](https://docs.gitlab.com/ee/user/project/integrations/microsoft_teams.html) + +* [On Microsoft Teams](#on-microsoft-teams) +* [On GitLab](#on-gitlab) + +# Microsoft Teams service[](#microsoft-teams-service "Permalink") + +## On Microsoft Teams[](#on-microsoft-teams "Permalink") + +要启用 Microsoft Teams 集成,必须按照" [向连接器和 Webhooks 发送消息"中](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using)所述的步骤,在 Microsoft Teams 上创建传入的 Webhook 集成. + +## On GitLab[](#on-gitlab "Permalink") + +设置 Microsoft Teams 之后,就该设置 GitLab 了. + +导航到" [集成"页面,](overview.html#accessing-integrations)然后选择" **Microsoft Teams Notification"**服务进行配置. 在那里,您将看到一个带有以下可触发事件的复选框: + +* Push +* Issue +* 机密问题 +* 合并要求 +* Note +* 标签推送 +* Pipeline +* 维基页面 + +最后,填写您的 Microsoft Teams 详细信息: + +| Field | Description | +| --- | --- | +| **Webhook** | 您必须在 Microsoft Teams 上设置的传入 Webhook URL. | +| **仅通知断开的管道** | 如果您选择启用**管道**事件,并且只希望收到有关失败管道的通知. | + +完成所有操作后,单击" **保存更改"**以使更改生效. + +[![Microsoft Teams configuration](img/114dc1abb6412aca14f3c3b6ad3048dc.png)](img/microsoft_teams_configuration.png) \ No newline at end of file diff --git a/_book/docs/087.md b/_book/docs/087.md new file mode 100644 index 0000000000000000000000000000000000000000..927e6eb42627a0fcec3a01714bc3e81b906f92f3 --- /dev/null +++ b/_book/docs/087.md @@ -0,0 +1,17 @@ +# Mock CI Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/mock_ci.html](https://docs.gitlab.com/ee/user/project/integrations/mock_ci.html) + +# Mock CI Service[](#mock-ci-service "Permalink") + +**注意:仅当您处于开发环境中时,此服务才会列出!** + +要设置模拟 CI 服务服务器,请响应以下端点 + +* `commit_status`: `#{project.namespace.path}/#{project.path}/status/#{sha}.json` + * 让您的服务返回`200 { status: ['failed'|'canceled'|'running'|'pending'|'success'|'success-with-warnings'|'skipped'|'not_found'] }` + * 如果服务返回 404,则将其解释为`pending` +* `build_page`: `#{project.namespace.path}/#{project.path}/status/#{sha}` + * 构建链接到的位置,是否实施无关紧要 + +有关模拟 CI 服务器的示例,请参见[`gitlab-org/gitlab-mock-ci-service`](https://gitlab.com/gitlab-org/gitlab-mock-ci-service) \ No newline at end of file diff --git a/_book/docs/088.md b/_book/docs/088.md new file mode 100644 index 0000000000000000000000000000000000000000..01c2052085572359738fde6af4bb7d1d5bb5f018 --- /dev/null +++ b/_book/docs/088.md @@ -0,0 +1,135 @@ +# Prometheus integration + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html) + +* [Enabling Prometheus Integration](#enabling-prometheus-integration) + * [Managed Prometheus on Kubernetes](#managed-prometheus-on-kubernetes) + * [Requirements](#requirements) + * [Getting started](#getting-started) + * [About managed Prometheus deployments](#about-managed-prometheus-deployments) + * [Manual configuration of Prometheus](#manual-configuration-of-prometheus) + * [Requirements](#requirements-1) + * [Getting started](#getting-started-1) + * [Configuration in GitLab](#configuration-in-gitlab) + * [Thanos configuration in GitLab](#thanos-configuration-in-gitlab) + * [Precedence with multiple Prometheus configurations](#precedence-with-multiple-prometheus-configurations) +* [Determining the performance impact of a merge](#determining-the-performance-impact-of-a-merge) + +# Prometheus integration[](#prometheus-integration "Permalink") + +在 GitLab 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8935) . + +GitLab 提供与[Prometheus 的](https://s0prometheus0io.icopy.site)强大集成,可直接在 GitLab 中监视您的应用程序的关键指标. 从 Prometheus 检索每个环境的度量,然后在 GitLab 界面中显示. + +[![Environment Dashboard](img/45cb073d466ec4a6fcb5a09d7f5f204c.png)](img/prometheus_dashboard.png) + +有两种方法可以设置 Prometheus 集成,具体取决于应用程序的运行位置: + +* 对于在 Kubernetes 上的部署,GitLab 可以自动[部署和管理 Prometheus](#managed-prometheus-on-kubernetes) . +* 对于其他部署目标,只需[指定 Prometheus 服务器](#manual-configuration-of-prometheus) . + +启用后,GitLab 将自动从[度量标准库](prometheus_library/index.html)中的已知服务中检测度量[标准](prometheus_library/index.html) . 您还可以[添加自己的指标](../../../operations/metrics/index.html#adding-custom-metrics)并创建[自定义仪表板](../../../operations/metrics/dashboards/index.html) . + +## Enabling Prometheus Integration[](#enabling-prometheus-integration "Permalink") + +### Managed Prometheus on Kubernetes[](#managed-prometheus-on-kubernetes "Permalink") + +在 GitLab 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28916) . + +GitLab 可以在[连接的 Kubernetes 集群](../clusters/index.html)上无缝部署和管理 Prometheus,从而使对应用程序的监视变得容易. + +#### Requirements[](#requirements "Permalink") + +* A [connected Kubernetes cluster](../clusters/index.html) + +#### Getting started[](#getting-started "Permalink") + +拥有连接的 Kubernetes 集群后,只需单击即可轻松部署托管的 Prometheus. + +1. 转到**操作> Kubernetes**页面以查看已连接的集群 +2. 选择您要部署 Prometheus 的集群 +3. 单击**安装**按钮以将 Prometheus 部署到群集 + +[![Managed Prometheus Deploy](img/a198157b454aaa7b52001592ed46dc03.png)](img/prometheus_deploy.png) + +#### About managed Prometheus deployments[](#about-managed-prometheus-deployments "Permalink") + +使用[官方 Helm 图表](https://github.com/helm/charts/tree/master/stable/prometheus)将 Prometheus 部署到`gitlab-managed-apps`命名空间中. Prometheus 仅可在集群中访问,并且 GitLab 通过[Kubernetes API 进行](https://kubernetes.io/docs/concepts/overview/kubernetes-api/)通信. + +Prometheus 服务器将[自动检测和监视](https://s0prometheus0io.icopy.site/docs/prometheus/latest/configuration/configuration/)节点,吊舱和端点. 要配置 Prometheus 监视的资源,只需设置以下[Kubernetes 批注](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) : + +* `prometheus.io/scrape`为`true`以启用对资源的监视. +* `prometheus.io/port`定义度量标准端点的端口. +* `prometheus.io/path`来定义度量标准端点的路径. 默认为`/metrics` . + +CPU 和内存使用情况受到监视,但是需要使用[命名约定](prometheus_library/kubernetes.html#specifying-the-environment)来确定环境. 如果您使用的是[Auto DevOps](../../../topics/autodevops/index.html) ,则会自动处理. + +由 GitLab 部署到群集的[NGINX Ingress](../clusters/index.html#installing-applications)会自动添加注释,以进行监视,以提供关键的响应指标:延迟,吞吐量和错误率. + +### Manual configuration of Prometheus[](#manual-configuration-of-prometheus "Permalink") + +#### Requirements[](#requirements-1 "Permalink") + +与 Prometheus 集成需要满足以下条件: + +1. GitLab 9.0 或更高版本 +2. 必须将 Prometheus 配置为收集[支持的指标之一](prometheus_library/index.html) +3. Each metric must be have a label to indicate the environment +4. GitLab 必须与 Prometheus 服务器具有网络连接 + +#### Getting started[](#getting-started-1 "Permalink") + +安装和配置 Prometheus 来监视应用程序非常简单. + +1. [Install Prometheus](https://s0prometheus0io.icopy.site/docs/prometheus/latest/installation/) +2. 设置[受支持的监视目标之一](prometheus_library/index.html) +3. 配置 Prometheus 服务器以[收集其指标](https://s0prometheus0io.icopy.site/docs/prometheus/latest/configuration/configuration/) + +#### Configuration in GitLab[](#configuration-in-gitlab "Permalink") + +GitLab 中 Prometheus 集成的实际配置非常简单. 您只需要与您要集成的 Prometheus 服务器的域名或 IP 地址. 如果 Prometheus 资源由 Google 的身份识别代理(IAP)保护,则可以传递其他信息,例如客户端 ID 和服务帐户凭据,GitLab 可以使用这些信息来访问资源. 有关从服务帐户进行身份验证的更多信息,请参见 Google 的" [从服务帐户](https://cloud.google.com/iap/docs/authentication-howto#authenticating_from_a_service_account)进行[身份验证"](https://cloud.google.com/iap/docs/authentication-howto#authenticating_from_a_service_account)文档. + +1. 导航至位于的" [集成"页面](overview.html#accessing-integrations) **设置>集成** . +2. 单击**Prometheus**服务. +3. 对于**API URL** ,请提供服务器的域名或 IP 地址,例如`http://prometheus.example.com/`或`http://192.0.2.1/` . +4. (可选)在**Google IAP Audience Client ID 中** ,提供受 Google IAP 保护的 Prometheus OAuth Client 的 Client ID. +5. (可选)在**Google IAP 服务帐户 JSON 中** ,提供被授权访问 Prometheus 资源的服务帐户凭据文件的内容. +6. Click **保存更改**. + +[![Configure Prometheus Service](img/c154238c63e38411889c5647b2cdf20e.png)](img/prometheus_manual_configuration_v13_2.png) + +#### Thanos configuration in GitLab[](#thanos-configuration-in-gitlab "Permalink") + +您可以使用 GitLab 将[Thanos](https://thanos.io/)配置为 Prometheus 的替代品. 您将需要与之集成的 Thanos 服务器的域名或 IP 地址. + +1. 导航到" [集成"页面](overview.html#accessing-integrations) . +2. 单击**Prometheus**服务. +3. 提供服务器的域名或 IP 地址,例如`http://thanos.example.com/`或`http://192.0.2.1/` . +4. Click **保存更改**. + +### Precedence with multiple Prometheus configurations[](#precedence-with-multiple-prometheus-configurations "Permalink") + +尽管可以同时启用 Prometheus 的[手动配置](#manual-configuration-of-prometheus)和[自动配置](#managed-prometheus-on-kubernetes) ,但仅使用其中之一: + +* 如果您已[在 Kubernetes 上](#managed-prometheus-on-kubernetes)启用了[Prometheus 手动配置](#manual-configuration-of-prometheus)和[托管的 Prometheus](#managed-prometheus-on-kubernetes) ,则手动配置优先,并用于从[仪表板](../../../operations/metrics/dashboards/index.html#defining-custom-dashboards-per-project)和[自定义指标](../../../operations/metrics/index.html#adding-custom-metrics)运行查询. +* 如果您已在**不同**级别(项目,组,实例)的 Kubernetes 集群上安装了托管的 Prometheus 应用程序,则集群的优先级中将描述[优先级的顺序](../../instance/clusters/index.html#cluster-precedence) . +* If you have managed Prometheus applications installed on multiple Kubernetes clusters at the **same** level, the Prometheus application of a cluster with a matching [environment scope](../../../ci/environments/index.html#scoping-environments-with-specs) is used. + +## Determining the performance impact of a merge[](#determining-the-performance-impact-of-a-merge "Permalink") + +版本历史 + +* 在 GitLab 9.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10408) . +* GitLab 9.3 添加了 30 分钟平均值的[数字比较](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/27439) . + +开发人员可以在合并请求工作流程中查看其更改对性能的影响. + +**Note:** Requires [Kubernetes](prometheus_library/kubernetes.html) metrics. + +将源分支部署到环境后,将出现迷你图和平均内存消耗的数值比较. 在迷你图上,圆点指示部署当前更改的时间,前后最多显示 30 分钟的性能数据. 比较结果显示了部署前后 30 分钟平均值之间的差异. 部署每个提交后,将更新此信息. + +合并并重新部署目标分支后,指标将切换为显示此修订版已部署到的新环境. + +性能数据将在 Prometheus 服务器上持久保存的时间内可用. + +[![Merge Request with Performance Impact](img/33cc6d96a283a4f1b3cc5b27da9fd1c4.png)](img/merge_request_performance.png) \ No newline at end of file diff --git a/_book/docs/089.md b/_book/docs/089.md new file mode 100644 index 0000000000000000000000000000000000000000..eed44e89c3c5f96f063a734fc8ccfcb8bcba2b00 --- /dev/null +++ b/_book/docs/089.md @@ -0,0 +1,34 @@ +# Redmine Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/redmine.html](https://docs.gitlab.com/ee/user/project/integrations/redmine.html) + +* [Referencing issues in Redmine](#referencing-issues-in-redmine) + +# Redmine Service[](#redmine-service "Permalink") + +1. 要在项目中启用 Redmine 集成,请导航到[Integrations 页面](overview.html#accessing-integrations) ,单击**Redmine**服务,然后按照下表中的说明在页面上填写所需的详细信息. + + | Field | Description | + | --- | --- | + | `project_url` | Redmine 中与该 GitLab 项目链接的项目的 URL | + | `issues_url` | 链接到该 GitLab 项目的 Redmine 项目中问题的 URL. 请注意, `issues_url`在 URL 中需要`:id` . GitLab 使用此 ID 作为占位符来替换问题编号. | + | `new_issue_url` | 这是在 Redmine 中为与此 GitLab 项目链接的项目创建新发行版的 URL. **当前未使用此功能,并将在以后的版本中将其删除.** | + + 配置并启用 Redmine 后,您将在 GitLab 项目页面上看到 Redmine 链接,该链接将您带到适当的 Redmine 项目. + + 例如,下面是一个名为`gitlab-ci`的项目的配置. + + [![Redmine configuration](img/31f8f986b27020e646540b9595d026cd.png)](img/redmine_configuration.png) + +2. 要禁用项目中的内部问题跟踪系统,请导航至"常规"页面,展开[权限](../settings/index.html#sharing-and-permissions)部分,然后将" **问题"**切换切换为"禁用". + +## Referencing issues in Redmine[](#referencing-issues-in-redmine "Permalink") + +Redmine 中的问题可以通过两种替代方式进行引用: + +* `#<ID>` ,其中`<ID>`是数字(示例`#143` ). +* `<PROJECT>-<ID>` where `<PROJECT>` starts with a capital letter which is then followed by capital letters, numbers or underscores, and `<ID>` is a number (example `API_32-143`). + +如果您同时启用了内部和外部问题跟踪器,我们建议使用更长的格式. 如果您使用较短的格式,并且内部问题跟踪器中存在具有相同 ID 的问题,则内部问题将被链接. + +请注意, `<PROJECT>`部分将被忽略,链接始终指向`issues_url`指定的地址. \ No newline at end of file diff --git a/_book/docs/090.md b/_book/docs/090.md new file mode 100644 index 0000000000000000000000000000000000000000..b28f61eb886877688c4cf637676e7b83d5555107 --- /dev/null +++ b/_book/docs/090.md @@ -0,0 +1,94 @@ +# Slack Notifications Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/slack.html](https://docs.gitlab.com/ee/user/project/integrations/slack.html) + +* [Slack configuration](#slack-configuration) +* [GitLab configuration](#gitlab-configuration) + * [Triggers available for Slack notifications](#triggers-available-for-slack-notifications) +* [Troubleshooting](#troubleshooting) + * [Something went wrong on our end](#something-went-wrong-on-our-end) + * [`certificate verify failed`](#certificate-verify-failed) + +# Slack Notifications Service[](#slack-notifications-service "Permalink") + +Slack Notifications Service 允许您的 GitLab 项目将事件(例如问题创建)作为通知发送到您现有的 Slack 团队. 设置 Slack 通知需要同时更改 Slack 和 GitLab 的配置. + +**注意:**您还可以使用 Slack 斜杠命令在 Slack 中控制 GitLab. 这是单独配置的[Slack 斜杠命令](slack_slash_commands.html) . + +## Slack configuration[](#slack-configuration "Permalink") + +1. 登录到 Slack 团队并[开始新的 Incoming WebHooks 配置](https://my.slack.com/services/new/incoming-webhook) . +2. 选择默认情况下将通知发送到的松弛通道. 单击**添加传入的 WebHooks 集成**按钮以添加配置. +3. 复制**Webhook URL** ,我们将在以后的 GitLab 配置中使用它. + +## GitLab configuration[](#gitlab-configuration "Permalink") + +1. Open your project’s page, and navigate to your project’s [Integrations page](overview.html#accessing-integrations) at **设置>集成**. +2. 选择**Slack Notifications**集成进行配置. +3. Click **启用整合**. +4. 在**Trigger 中** ,选中每种类型的 GitLab 事件的复选框,以将其发送给 Slack 作为通知. 有关完整列表,请参阅[可用于 Slack 通知的触发器](#triggers-available-for-slack-notifications) . 默认情况下,消息将发送到您在[Slack 集成](#slack-configuration)期间配置的通道. +5. (可选)要将消息发送到其他渠道,多个渠道或作为直接消息: + * 要将消息发送到频道,请输入 Slack 频道名称,以逗号分隔. + * 要发送直接消息,请使用在用户的 Slack 个人资料中找到的会员 ID.**注意:**不支持用户名和私人频道. +6. 在**Webhook 中** ,提供您从[Slack 集成](#slack-configuration)步骤复制的**Webhook** URL. +7. (可选)在**Username 中** ,提供发送通知的 Slack 机器人的用户名. +8. 选择**仅通知断开的管道**复选框以仅通知失败. +9. 在**要通知**的**分支中**选择框,选择要为其发送通知的分支类型. +10. Click **测试设置并保存更改**. + +您的 Slack 团队现在将开始按照配置接收 GitLab 事件通知. + +### Triggers available for Slack notifications[](#triggers-available-for-slack-notifications "Permalink") + +以下触发器可用于 Slack 通知: + +* **推送** :由推送到存储库触发. +* **问题** :在创建,更新或关闭问题时触发. +* **机密问题** :创建,更新或关闭机密问题时触发. +* **合并请求** :在创建,更新或合并合并请求时触发. +* **注意** :有人添加评论时触发. +* **机密注释** :当有人添加机密注释时触发. +* **标签推送** :将新标签推送到存储库时触发. +* **管道** :管道状态更改时触发. +* **Wiki 页面** :在创建或更新 Wiki 页面时触发. +* **部署** :在部署完成时触发. +* **警报** :记录新的唯一警报时触发. + +## Troubleshooting[](#troubleshooting "Permalink") + +如果您的 Slack 集成无法正常工作,请通过在[Sidekiq 日志中](../../../administration/logs.html#sidekiqlog)搜索与 Slack 服务相关的错误来开始故障排除. + +### Something went wrong on our end[](#something-went-wrong-on-our-end "Permalink") + +这是 GitLab UI 中显示的一般错误,其本身并没有多大意义. 查看[日志](../../../administration/logs.html#productionlog)以查找错误消息,并从那里继续进行故障排除. + +### `certificate verify failed`[](#certificate-verify-failed "Permalink") + +您可能会在 Sidekiq 日志中看到类似于以下内容的条目: + +``` +2019-01-10_13:22:08.42572 2019-01-10T13:22:08.425Z 6877 TID-abcdefg ProjectServiceWorker JID-3bade5fb3dd47a85db6d78c5 ERROR: {:class=>"ProjectServiceWorker", :service_class=>"SlackService", :message=>"SSL_connect returned=1 errno=0 state=error: certificate verify failed"} +``` + +GitLab 与 Slack 通信或 GitLab 与自身通信可能是一个问题. 前者的可能性较小,因为 Slack 的安全证书*希望*始终受到信任. 我们可以使用下面的 rails 控制台脚本来确定要处理的内容. + +``` +# start a rails console: +sudo gitlab-rails console -e production + +# or for source installs: +bundle exec rails console -e production +``` + +``` +# run this in the Rails console +# replace <SLACK URL> with your actual Slack URL +result = Net::HTTP.get(URI('https://<SLACK URL>'));0 + +# replace <GITLAB URL> with your actual GitLab URL +result = Net::HTTP.get(URI('https://<GITLAB URL>'));0 +``` + +如果 GitLab 不信任自身的 HTTPS 连接,则可能需要[将证书添加到 GitLab 的受信任证书中](https://docs.gitlab.com/omnibus/settings/ssl.html) . + +如果 GitLab 不信任与 Slack 的连接,则 GitLab OpenSSL 信任存储不正确. 一些典型的原因:使用`gitlab_rails['env'] = {"SSL_CERT_FILE" => "/path/to/file.pem"}`覆盖信任库,或不小心修改了默认的 CA 捆绑包`/opt/gitlab/embedded/ssl/certs/cacert.pem` . \ No newline at end of file diff --git a/_book/docs/091.md b/_book/docs/091.md new file mode 100644 index 0000000000000000000000000000000000000000..0ef904b13397d299b71b742336a046d3e995cae3 --- /dev/null +++ b/_book/docs/091.md @@ -0,0 +1,32 @@ +# Slack slash commands + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/slack_slash_commands.html](https://docs.gitlab.com/ee/user/project/integrations/slack_slash_commands.html) + +* [Configuration](#configuration) +* [Usage](#usage) + +# Slack slash commands[](#slack-slash-commands-core-only "Permalink") + +在 GitLab 8.15 中引入. + +使用 Slack 斜杠命令,您可以控制 GitLab 并直接在 Slack 内部查看内容,而不必离开它. 这需要在 Slack 和 GitLab 中进行配置. + +GitLab 还可以将事件(例如, `issue created` )作为通知发送到 Slack. 这是单独配置的[Slack Notifications Service](slack.html) . + +**注意:**对于 GitLab.com,请改用[Slack 应用程序](gitlab_slack_application.html) . + +## Configuration[](#configuration "Permalink") + +1. Slack 斜杠命令的作用域是项目. 导航到项目设置中的" [集成"页面](overview.html#accessing-integrations) ,即" **项目">"设置">"集成"** . +2. 选择**Slack 斜杠命令**集成进行配置. 该页面包含完成 Slack 中配置所需的信息. 将此浏览器选项卡保持打开状态. +3. 打开一个新的浏览器选项卡,然后登录到您的 Slack 团队. [开始新的 Slash Commands 集成](https://my.slack.com/services/new/slash-commands) . +4. 输入触发条件. 我们建议您使用项目名称. 单击**添加斜线命令集成** . +5. 使用来自 GitLab 浏览器选项卡的信息来完成 Slack 配置页面中的其余字段. 特别是,URL 需要复制和粘贴. 单击" **保存集成"**以完成 Slack 中的配置. +6. 仍在 Slack 配置页面上,复制**令牌** . 返回到 GitLab 浏览器选项卡并粘贴**令牌** . +7. 确保启用了**活动**切换,然后单击**保存更改**以完成 GitLab 中的配置. + +[![Slack setup instructions](img/1e1a93a55568355165c7529b5326427b.png)](img/slack_setup.png) + +## Usage[](#usage "Permalink") + +现在,您可以使用[Slack 斜杠命令](../../../integration/slash_commands.html) . \ No newline at end of file diff --git a/_book/docs/092.md b/_book/docs/092.md new file mode 100644 index 0000000000000000000000000000000000000000..a5605351f301bf9db99f9fb8946388c5286094fc --- /dev/null +++ b/_book/docs/092.md @@ -0,0 +1,70 @@ +# GitLab Slack application + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html) + +* [Slack App Directory](#slack-app-directory) +* [Configuration](#configuration) +* [Create a project alias for Slack](#create-a-project-alias-for-slack) +* [Usage](#usage) + +# GitLab Slack application[](#gitlab-slack-application-free-only "Permalink") + +版本历史 + +* 在 GitLab 9.4 中引入. +* 分发到 GitLab 10.2 中的 Slack App Directory. + +**注意:** GitLab Slack 应用程序仅可为 GitLab.com 配置. 它**不适**用于您可以配置[Slack 斜杠命令](slack_slash_commands.html)服务的本地安装. 我们正计划使该配置可用于所有的 GitLab 安装,但是没有 ETA-参见[#28164](https://gitlab.com/gitlab-org/gitlab/-/issues/28164) . + +Slack 提供了一个本机应用程序,您可以通过 GitLab.com 上项目的集成来启用它. + +## Slack App Directory[](#slack-app-directory "Permalink") + +为您的工作区启用 GitLab Slack 应用程序的最简单方法是从[Slack App Directory](https://slack.com/apps)安装[GitLab 应用](https://slack-platform.slack.com/apps/A676ADMV5-gitlab) [程序](https://slack.com/apps) . + +单击安装会将您带到[GitLab Slack 应用程序登录页面](https://gitlab.com/profile/slack/edit) ,您可以在其中选择一个项目来为其启用 GitLab Slack 应用程序. + +[![GitLab Slack application landing page](img/618f6f4ba2a434609a1a9de7a9725e49.png)](img/gitlab_slack_app_landing_page.png) + +## Configuration[](#configuration "Permalink") + +或者,您可以使用项目的集成设置来配置 Slack 应用程序. + +请记住,您需要拥有 Slack 团队的适当权限才能安装新应用程序,请阅读 Slack 文档中有关[将应用程序添加到工作区的更多信息](https://slack.com/help/articles/202035138-Add-an-app-to-your-workspace) . + +为您的 Slack 团队启用 GitLab 的服务: + +1. 转到项目的 **设置>集成> Slack 应用程序** (仅在 GitLab.com 上可见). +2. Click **添加到松弛**. + +就这样! 现在,您可以开始使用 Slack 斜杠命令. + +## Create a project alias for Slack[](#create-a-project-alias-for-slack "Permalink") + +要在 GitLab.com 上为 Slack 集成创建项目别名: + +1. 转到项目的主页. +2. 导航 **设置>集成** (仅在 GitLab.com 上可见) +3. 在" **集成"**页面上,单击**Slack application** . +4. 显示当前的**项目别名** (如果有). 要编辑此值,请点击**编辑** . +5. 输入所需的别名,然后点击**保存更改** . + +一些 Slack 命令需要项目别名,如果项目别名不正确或命令中缺少该别名,则会失败并显示以下错误: + +``` +GitLab error: project or alias not found +``` + +## Usage[](#usage "Permalink") + +确认安装后,您和您的 Slack 团队中的其他所有人都可以使用所有[slash 命令](../../../integration/slash_commands.html) . + +当您执行第一个斜杠命令时,将要求您在 GitLab.com 上授权您的 Slack 用户. + +与[手动配置的 Slack 斜杠命令](slack_slash_commands.html)的唯一区别在于,所有命令均应以`/gitlab`关键字为前缀. 我们正在努力使此配置在将来成为可能. + +例如,要显示`gitlab-org/gitlab`项目下的问题编号`1001` ,您可以执行以下操作: + +``` +/gitlab gitlab-org/gitlab issue show 1001 +``` \ No newline at end of file diff --git a/_book/docs/093.md b/_book/docs/093.md new file mode 100644 index 0000000000000000000000000000000000000000..f1b1c2e60e22e51f7308f294a40be1f4e82bba77 --- /dev/null +++ b/_book/docs/093.md @@ -0,0 +1,366 @@ +# Webhooks + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/webhooks.html](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html) + +* [Overview](#overview) +* [Use-cases](#use-cases) +* [Webhook endpoint tips](#webhook-endpoint-tips) +* [Secret token](#secret-token) +* [SSL verification](#ssl-verification) +* [Branch filtering](#branch-filtering) +* [Events](#events) + * [Push events](#push-events) + * [Tag events](#tag-events) + * [Issue events](#issue-events) + * [Comment events](#comment-events) + * [Comment on commit](#comment-on-commit) + * [Comment on merge request](#comment-on-merge-request) + * [Comment on issue](#comment-on-issue) + * [Comment on code snippet](#comment-on-code-snippet) + * [Merge request events](#merge-request-events) + * [Wiki Page events](#wiki-page-events) + * [Pipeline events](#pipeline-events) + * [Job events](#job-events) +* [Image URL rewriting](#image-url-rewriting) +* [Testing webhooks](#testing-webhooks) +* [Troubleshoot webhooks](#troubleshoot-webhooks) + * [Receiving duplicate or multiple webhook requests triggered by one event](#receiving-duplicate-or-multiple-webhook-requests-triggered-by-one-event) + * [Troubleshooting: “Unable to get local issuer certificate”](#troubleshooting-unable-to-get-local-issuer-certificate) +* [Example webhook receiver](#example-webhook-receiver) + +# Webhooks[](#webhooks "Permalink") + +> **注意:**从 GitLab 8.5 开始: +> +> * 不推荐使用`repository`密钥,而推荐使用`project`密钥 +> * 不推荐使用`project.ssh_url`密钥,而推荐使用`project.git_ssh_url`密钥 +> * 不推荐使用`project.http_url`键,而推荐使用`project.git_http_url`键 +> +> **注意:**从 GitLab 11.1 开始,一个月后会自动删除 Webhooks 的日志. +> +> **注意:**从 GitLab 11.2 开始: +> +> * 重写问题,合并请求,评论和 Wiki 页面的`description`字段,以便简单的 Markdown 图像引用(如`![](/uploads/...)` )将其目标 URL 更改为绝对 URL. 有关更多详细信息,请参见[图像 URL 重写](#image-url-rewriting) . + +通过项目 webhooks,您可以在例如推送新代码或创建新问题时触发 URL. 您可以将 webhook 配置为侦听特定事件,例如推送,问题或合并请求. GitLab 会将带有数据的 POST 请求发送到 webhook URL. + +在大多数情况下,您需要设置自己的[Webhook 接收器](#example-webhook-receiver)以从 GitLab 接收信息,然后根据需要将其发送到另一个应用程序. 我们已经有一个[内置接收器,](slack.html)用于*每个项目*发送[Slack](https://api.slack.com/incoming-webhooks)通知. + +## Overview[](#overview "Permalink") + +[Webhooks](https://en.wikipedia.org/wiki/Webhook)是" *用户定义的 HTTP 回调* ". 它们通常是由某些事件触发的,例如将代码推送到存储库或将评论发布到博客. 发生该事件时,源应用程序向为 Webhook 配置的 URI 发出 HTTP 请求. 采取的措施可能是任何事情. 常见用途是触发具有持续集成系统的构建或通知错误跟踪系统. + +Webhooks 可用于更新外部问题跟踪器,触发 CI 作业,更新备份镜像,甚至部署到您的生产服务器. 他们**每个项目**可以 GitLab 社区版,以及**每个项目和每个组** **GitLab 企业版** . + +通过转到项目的**设置➔Webhooks**导航到 webhooks 页面. + +**注意:**在 GitLab.com 上,每个项目和每个组的[最大 Webhooks 数量](../../../user/gitlab_com/index.html#maximum-number-of-webhooks)是有限的. + +## Use-cases[](#use-cases "Permalink") + +* 您可以在 GitLab 中设置一个 Webhook,以在每次作业失败时向[Slack](https://api.slack.com/incoming-webhooks)发送通知. +* 每当在 GitLab 中为特定项目或组创建问题时,您都可以[与 Twilio 集成以通过 SMS 收到通知](https://www.datadoghq.com/blog/send-alerts-sms-customizable-webhooks-twilio/) +* You can use them to [automatically assign labels to merge requests](https://about.gitlab.com/blog/2016/08/19/applying-gitlab-labels-automatically/). + +## Webhook endpoint tips[](#webhook-endpoint-tips "Permalink") + +如果您正在编写自己的将接收 GitLab webhooks 的端点(Web 服务器),请记住以下几点: + +* 您的端点应尽快发送其 HTTP 响应. 如果等待时间太长,GitLab 可能会确定挂钩失败并重试. +* 您的端点应始终返回有效的 HTTP 响应. 如果您不这样做,则 GitLab 会认为挂钩失败并重试. 大多数 HTTP 库会自动为您处理此问题,但是如果您正在编写低级钩子,记住这一点很重要. +* GitLab 会忽略端点返回的 HTTP 状态代码. + +## Secret token[](#secret-token "Permalink") + +如果您指定一个秘密令牌,它将与挂钩请求一起在`X-Gitlab-Token` HTTP 标头中发送. 您的 webhook 端点可以检查以验证请求是否合法. + +## SSL verification[](#ssl-verification "Permalink") + +默认情况下,将基于证书颁发机构的内部列表来验证 webhook 端点的 SSL 证书,这意味着该证书无法进行自签名. + +您可以在 GitLab 项目的 webhook 设置中将其关闭. + +[![SSL Verification](img/e7d35854d0a726fbc4756cca4de4bf77.png)](img/webhooks_ssl.png) + +## Branch filtering[](#branch-filtering "Permalink") + +在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20338) . + +可以使用分支名称或通配符模式按分支过滤推送事件,以限制将哪些推送事件发送到您的 Webhook 端点. 默认情况下,该字段为空白,导致所有推送事件都发送到您的 Webhook 端点. + +## Events[](#events "Permalink") + +下面介绍了受支持的事件. + +### Push events[](#push-events "Permalink") + +当您推送到存储库时(推送标签时除外)触发. + +**注意:**一次推送超过 20 个提交时,出于性能原因, `commits` webhook 属性将仅包含前 20 个. 加载详细的提交数据非常昂贵. 请注意,尽管`commits`属性中仅存在 20 个提交,但`total_commits_count`属性将包含实际总数. + +另外,如果单个推送包含三个以上分支的更改(默认情况下,取决于[`push_event_hooks_limit`设置](../../../api/settings.html#list-of-settings-that-can-be-accessed-via-api-calls) ),则不会执行此挂钩. + +**请求标头**: + +``` +X-Gitlab-Event: Push Hook +``` + +**要求正文:** + +``` +{ "object_kind": "push", "before": "95790bf891e76fee5e1747ab589903a6a1f80f22", "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "ref": "refs/heads/master", "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "user_id": 4, "user_name": "John Smith", "user_username": "jsmith", "user_email": "john@example.com", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 15, "project":{ "id": 15, "name":"Diaspora", "description":"", "web_url":"http://example.com/mike/diaspora", "avatar_url":null, "git_ssh_url":"git@example.com:mike/diaspora.git", "git_http_url":"http://example.com/mike/diaspora.git", "namespace":"Mike", "visibility_level":0, "path_with_namespace":"mike/diaspora", "default_branch":"master", "homepage":"http://example.com/mike/diaspora", "url":"git@example.com:mike/diaspora.git", "ssh_url":"git@example.com:mike/diaspora.git", "http_url":"http://example.com/mike/diaspora.git" }, "repository":{ "name": "Diaspora", "url": "git@example.com:mike/diaspora.git", "description": "", "homepage": "http://example.com/mike/diaspora", "git_http_url":"http://example.com/mike/diaspora.git", "git_ssh_url":"git@example.com:mike/diaspora.git", "visibility_level":0 }, "commits": [ { "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", "message": "Update Catalan translation to e38cb41.\n\nSee https://gitlab.com/gitlab-org/gitlab for more information", "title": "Update Catalan translation to e38cb41.", "timestamp": "2011-12-12T14:27:31+02:00", "url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", "author": { "name": "Jordi Mallach", "email": "jordi@softcatala.org" }, "added": ["CHANGELOG"], "modified": ["app/controller/application.rb"], "removed": [] }, { "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "message": "fixed readme", "title": "fixed readme", "timestamp": "2012-01-03T23:36:29+02:00", "url": "http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "author": { "name": "GitLab dev user", "email": "gitlabdev@dv6700.(none)" }, "added": ["CHANGELOG"], "modified": ["app/controller/application.rb"], "removed": [] } ], "total_commits_count": 4 } +``` + +### Tag events[](#tag-events "Permalink") + +在创建(或删除)存储库标签时触发. + +**注意:**如果单个推送包含三个以上的更改(默认情况下,取决于[`push_event_hooks_limit`设置](../../../api/settings.html#list-of-settings-that-can-be-accessed-via-api-calls) ),则不会执行此挂钩. + +**请求标头**: + +``` +X-Gitlab-Event: Tag Push Hook +``` + +**要求正文:** + +``` +{ "object_kind": "tag_push", "before": "0000000000000000000000000000000000000000", "after": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7", "ref": "refs/tags/v1.0.0", "checkout_sha": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7", "user_id": 1, "user_name": "John Smith", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 1, "project":{ "id": 1, "name":"Example", "description":"", "web_url":"http://example.com/jsmith/example", "avatar_url":null, "git_ssh_url":"git@example.com:jsmith/example.git", "git_http_url":"http://example.com/jsmith/example.git", "namespace":"Jsmith", "visibility_level":0, "path_with_namespace":"jsmith/example", "default_branch":"master", "homepage":"http://example.com/jsmith/example", "url":"git@example.com:jsmith/example.git", "ssh_url":"git@example.com:jsmith/example.git", "http_url":"http://example.com/jsmith/example.git" }, "repository":{ "name": "Example", "url": "ssh://git@example.com/jsmith/example.git", "description": "", "homepage": "http://example.com/jsmith/example", "git_http_url":"http://example.com/jsmith/example.git", "git_ssh_url":"git@example.com:jsmith/example.git", "visibility_level":0 }, "commits": [], "total_commits_count": 0 } +``` + +### Issue events[](#issue-events "Permalink") + +在创建新问题或更新/关闭/重新打开现有问题时触发. + +**请求标头**: + +``` +X-Gitlab-Event: Issue Hook +``` + +**要求正文:** + +``` +{ "object_kind": "issue", "event_type": "issue", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", "email": "admin@example.com" }, "project": { "id": 1, "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlabhq/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", "git_http_url":"http://example.com/gitlabhq/gitlab-test.git", "namespace":"GitlabHQ", "visibility_level":20, "path_with_namespace":"gitlabhq/gitlab-test", "default_branch":"master", "ci_config_path": null, "homepage":"http://example.com/gitlabhq/gitlab-test", "url":"http://example.com/gitlabhq/gitlab-test.git", "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", "http_url":"http://example.com/gitlabhq/gitlab-test.git" }, "object_attributes": { "id": 301, "title": "New API: create/update/delete file", "assignee_ids": [51], "assignee_id": 51, "author_id": 51, "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "updated_by_id": 1, "last_edited_at": null, "last_edited_by_id": null, "relative_position": 0, "description": "Create new API for manipulations with repository", "milestone_id": null, "state_id": 1, "confidential": false, "discussion_locked": true, "due_date": null, "moved_to_id": null, "duplicated_to_id": null, "time_estimate": 0, "total_time_spent": 0, "human_total_time_spent": null, "human_time_estimate": null, "weight": null, "iid": 23, "url": "http://example.com/diaspora/issues/23", "state": "opened", "action": "open", "labels": [{ "id": 206, "title": "API", "color": "#ffffff", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "API related issues", "type": "ProjectLabel", "group_id": 41 }] }, "repository": { "name": "Gitlab Test", "url": "http://example.com/gitlabhq/gitlab-test.git", "description": "Aut reprehenderit ut est.", "homepage": "http://example.com/gitlabhq/gitlab-test" }, "assignees": [{ "name": "User1", "username": "user1", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }], "assignee": { "name": "User1", "username": "user1", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "labels": [{ "id": 206, "title": "API", "color": "#ffffff", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "API related issues", "type": "ProjectLabel", "group_id": 41 }], "changes": { "updated_by_id": { "previous": null, "current": 1 }, "updated_at": { "previous": "2017-09-15 16:50:55 UTC", "current": "2017-09-15 16:52:00 UTC" }, "labels": { "previous": [{ "id": 206, "title": "API", "color": "#ffffff", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "API related issues", "type": "ProjectLabel", "group_id": 41 }], "current": [{ "id": 205, "title": "Platform", "color": "#123123", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "Platform related issues", "type": "ProjectLabel", "group_id": 41 }] } } } +``` + +> **注意** :不赞成使用`assignee`和`assignee_id`键,现在仅显示第一个受让人. + +### Comment events[](#comment-events "Permalink") + +在对提交,合并请求,问题和代码段进行新注释时触发. 音符数据将被存储在`object_attributes` (如`note` , `noteable_type` ). 有效负载还将包括有关注释目标的信息. 例如,对问题的评论将在`issue`密钥下包括特定的问题信息. 有效的目标类型: + +* `commit` +* `merge_request` +* `issue` +* `snippet` + +#### Comment on commit[](#comment-on-commit "Permalink") + +**Request header**: + +``` +X-Gitlab-Event: Note Hook +``` + +**要求正文:** + +``` +{ "object_kind": "note", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "project_id": 5, "project":{ "id": 5, "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlabhq/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", "git_http_url":"http://example.com/gitlabhq/gitlab-test.git", "namespace":"GitlabHQ", "visibility_level":20, "path_with_namespace":"gitlabhq/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlabhq/gitlab-test", "url":"http://example.com/gitlabhq/gitlab-test.git", "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", "http_url":"http://example.com/gitlabhq/gitlab-test.git" }, "repository":{ "name": "Gitlab Test", "url": "http://example.com/gitlab-org/gitlab-test.git", "description": "Aut reprehenderit ut est.", "homepage": "http://example.com/gitlab-org/gitlab-test" }, "object_attributes": { "id": 1243, "note": "This is a commit comment. How does this work?", "noteable_type": "Commit", "author_id": 1, "created_at": "2015-05-17 18:08:09 UTC", "updated_at": "2015-05-17 18:08:09 UTC", "project_id": 5, "attachment":null, "line_code": "bec9703f7a456cd2b4ab5fb3220ae016e3e394e3_0_1", "commit_id": "cfe32cf61b73a0d5e9f13e774abde7ff789b1660", "noteable_id": null, "system": false, "st_diff": { "diff": "--- /dev/null\n+++ b/six\n@@ -0,0 +1 @@\n+Subproject commit 409f37c4f05865e4fb208c771485f211a22c4c2d\n", "new_path": "six", "old_path": "six", "a_mode": "0", "b_mode": "160000", "new_file": true, "renamed_file": false, "deleted_file": false }, "url": "http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660#note_1243" }, "commit": { "id": "cfe32cf61b73a0d5e9f13e774abde7ff789b1660", "message": "Add submodule\n\nSigned-off-by: Example User \u003cuser@example.com.com\u003e\n", "timestamp": "2014-02-27T10:06:20+02:00", "url": "http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660", "author": { "name": "Example User", "email": "user@example.com" } } } +``` + +#### Comment on merge request[](#comment-on-merge-request "Permalink") + +**请求标头**: + +``` +X-Gitlab-Event: Note Hook +``` + +**要求正文:** + +``` +{ "object_kind": "note", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "project_id": 5, "project":{ "id": 5, "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlab-org/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", "namespace":"Gitlab Org", "visibility_level":10, "path_with_namespace":"gitlab-org/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlab-org/gitlab-test", "url":"http://example.com/gitlab-org/gitlab-test.git", "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "http_url":"http://example.com/gitlab-org/gitlab-test.git" }, "repository":{ "name": "Gitlab Test", "url": "http://localhost/gitlab-org/gitlab-test.git", "description": "Aut reprehenderit ut est.", "homepage": "http://example.com/gitlab-org/gitlab-test" }, "object_attributes": { "id": 1244, "note": "This MR needs work.", "noteable_type": "MergeRequest", "author_id": 1, "created_at": "2015-05-17 18:21:36 UTC", "updated_at": "2015-05-17 18:21:36 UTC", "project_id": 5, "attachment": null, "line_code": null, "commit_id": "", "noteable_id": 7, "system": false, "st_diff": null, "url": "http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244" }, "merge_request": { "id": 7, "target_branch": "markdown", "source_branch": "master", "source_project_id": 5, "author_id": 8, "assignee_id": 28, "title": "Tempora et eos debitis quae laborum et.", "created_at": "2015-03-01 20:12:53 UTC", "updated_at": "2015-03-21 18:27:27 UTC", "milestone_id": 11, "state": "opened", "merge_status": "cannot_be_merged", "target_project_id": 5, "iid": 1, "description": "Et voluptas corrupti assumenda temporibus. Architecto cum animi eveniet amet asperiores. Vitae numquam voluptate est natus sit et ad id.", "position": 0, "source":{ "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlab-org/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", "namespace":"Gitlab Org", "visibility_level":10, "path_with_namespace":"gitlab-org/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlab-org/gitlab-test", "url":"http://example.com/gitlab-org/gitlab-test.git", "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "http_url":"http://example.com/gitlab-org/gitlab-test.git" }, "target": { "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlab-org/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", "namespace":"Gitlab Org", "visibility_level":10, "path_with_namespace":"gitlab-org/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlab-org/gitlab-test", "url":"http://example.com/gitlab-org/gitlab-test.git", "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "http_url":"http://example.com/gitlab-org/gitlab-test.git" }, "last_commit": { "id": "562e173be03b8ff2efb05345d12df18815438a4b", "message": "Merge branch 'another-branch' into 'master'\n\nCheck in this test\n", "timestamp": "2015-04-08T21: 00:25-07:00", "url": "http://example.com/gitlab-org/gitlab-test/commit/562e173be03b8ff2efb05345d12df18815438a4b", "author": { "name": "John Smith", "email": "john@example.com" } }, "work_in_progress": false, "assignee": { "name": "User1", "username": "user1", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" } } } +``` + +#### Comment on issue[](#comment-on-issue "Permalink") + +**请求标头**: + +``` +X-Gitlab-Event: Note Hook +``` + +**要求正文:** + +``` +{ "object_kind": "note", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "project_id": 5, "project":{ "id": 5, "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlab-org/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", "namespace":"Gitlab Org", "visibility_level":10, "path_with_namespace":"gitlab-org/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlab-org/gitlab-test", "url":"http://example.com/gitlab-org/gitlab-test.git", "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "http_url":"http://example.com/gitlab-org/gitlab-test.git" }, "repository":{ "name":"diaspora", "url":"git@example.com:mike/diaspora.git", "description":"", "homepage":"http://example.com/mike/diaspora" }, "object_attributes": { "id": 1241, "note": "Hello world", "noteable_type": "Issue", "author_id": 1, "created_at": "2015-05-17 17:06:40 UTC", "updated_at": "2015-05-17 17:06:40 UTC", "project_id": 5, "attachment": null, "line_code": null, "commit_id": "", "noteable_id": 92, "system": false, "st_diff": null, "url": "http://example.com/gitlab-org/gitlab-test/issues/17#note_1241" }, "issue": { "id": 92, "title": "test", "assignee_ids": [], "assignee_id": null, "author_id": 1, "project_id": 5, "created_at": "2015-04-12 14:53:17 UTC", "updated_at": "2015-04-26 08:28:42 UTC", "position": 0, "branch_name": null, "description": "test", "milestone_id": null, "state": "closed", "iid": 17, "labels": [ { "id": 25, "title": "Afterpod", "color": "#3e8068", "project_id": null, "created_at": "2019-06-05T14:32:20.211Z", "updated_at": "2019-06-05T14:32:20.211Z", "template": false, "description": null, "type": "GroupLabel", "group_id": 4 }, { "id": 86, "title": "Element", "color": "#231afe", "project_id": 4, "created_at": "2019-06-05T14:32:20.637Z", "updated_at": "2019-06-05T14:32:20.637Z", "template": false, "description": null, "type": "ProjectLabel", "group_id": null } ], } } +``` + +> **注意** :不建议使用`assignee_id`字段,现在仅显示第一个受让人. + +#### Comment on code snippet[](#comment-on-code-snippet "Permalink") + +**请求标头**: + +``` +X-Gitlab-Event: Note Hook +``` + +**要求正文:** + +``` +{ "object_kind": "note", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "project_id": 5, "project":{ "id": 5, "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlab-org/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", "namespace":"Gitlab Org", "visibility_level":10, "path_with_namespace":"gitlab-org/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlab-org/gitlab-test", "url":"http://example.com/gitlab-org/gitlab-test.git", "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "http_url":"http://example.com/gitlab-org/gitlab-test.git" }, "repository":{ "name":"Gitlab Test", "url":"http://example.com/gitlab-org/gitlab-test.git", "description":"Aut reprehenderit ut est.", "homepage":"http://example.com/gitlab-org/gitlab-test" }, "object_attributes": { "id": 1245, "note": "Is this snippet doing what it's supposed to be doing?", "noteable_type": "Snippet", "author_id": 1, "created_at": "2015-05-17 18:35:50 UTC", "updated_at": "2015-05-17 18:35:50 UTC", "project_id": 5, "attachment": null, "line_code": null, "commit_id": "", "noteable_id": 53, "system": false, "st_diff": null, "url": "http://example.com/gitlab-org/gitlab-test/snippets/53#note_1245" }, "snippet": { "id": 53, "title": "test", "content": "puts 'Hello world'", "author_id": 1, "project_id": 5, "created_at": "2015-04-09 02:40:38 UTC", "updated_at": "2015-04-09 02:40:38 UTC", "file_name": "test.rb", "expires_at": null, "type": "ProjectSnippet", "visibility_level": 0 } } +``` + +### Merge request events[](#merge-request-events "Permalink") + +在创建新的合并请求,更新/合并/关闭现有合并请求或在源分支中添加提交时触发. + +**请求标头**: + +``` +X-Gitlab-Event: Merge Request Hook +``` + +**要求正文:** + +``` +{ "object_kind": "merge_request", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "project": { "id": 1, "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlabhq/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", "git_http_url":"http://example.com/gitlabhq/gitlab-test.git", "namespace":"GitlabHQ", "visibility_level":20, "path_with_namespace":"gitlabhq/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlabhq/gitlab-test", "url":"http://example.com/gitlabhq/gitlab-test.git", "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", "http_url":"http://example.com/gitlabhq/gitlab-test.git" }, "repository": { "name": "Gitlab Test", "url": "http://example.com/gitlabhq/gitlab-test.git", "description": "Aut reprehenderit ut est.", "homepage": "http://example.com/gitlabhq/gitlab-test" }, "object_attributes": { "id": 99, "target_branch": "master", "source_branch": "ms-viewport", "source_project_id": 14, "author_id": 51, "assignee_id": 6, "title": "MS-Viewport", "created_at": "2013-12-03T17:23:34Z", "updated_at": "2013-12-03T17:23:34Z", "milestone_id": null, "state": "opened", "merge_status": "unchecked", "target_project_id": 14, "iid": 1, "description": "", "source": { "name":"Awesome Project", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/awesome_space/awesome_project", "avatar_url":null, "git_ssh_url":"git@example.com:awesome_space/awesome_project.git", "git_http_url":"http://example.com/awesome_space/awesome_project.git", "namespace":"Awesome Space", "visibility_level":20, "path_with_namespace":"awesome_space/awesome_project", "default_branch":"master", "homepage":"http://example.com/awesome_space/awesome_project", "url":"http://example.com/awesome_space/awesome_project.git", "ssh_url":"git@example.com:awesome_space/awesome_project.git", "http_url":"http://example.com/awesome_space/awesome_project.git" }, "target": { "name":"Awesome Project", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/awesome_space/awesome_project", "avatar_url":null, "git_ssh_url":"git@example.com:awesome_space/awesome_project.git", "git_http_url":"http://example.com/awesome_space/awesome_project.git", "namespace":"Awesome Space", "visibility_level":20, "path_with_namespace":"awesome_space/awesome_project", "default_branch":"master", "homepage":"http://example.com/awesome_space/awesome_project", "url":"http://example.com/awesome_space/awesome_project.git", "ssh_url":"git@example.com:awesome_space/awesome_project.git", "http_url":"http://example.com/awesome_space/awesome_project.git" }, "last_commit": { "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "message": "fixed readme", "timestamp": "2012-01-03T23:36:29+02:00", "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "author": { "name": "GitLab dev user", "email": "gitlabdev@dv6700.(none)" } }, "work_in_progress": false, "url": "http://example.com/diaspora/merge_requests/1", "action": "open", "assignee": { "name": "User1", "username": "user1", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" } }, "labels": [{ "id": 206, "title": "API", "color": "#ffffff", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "API related issues", "type": "ProjectLabel", "group_id": 41 }], "changes": { "updated_by_id": { "previous": null, "current": 1 }, "updated_at": { "previous": "2017-09-15 16:50:55 UTC", "current":"2017-09-15 16:52:00 UTC" }, "labels": { "previous": [{ "id": 206, "title": "API", "color": "#ffffff", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "API related issues", "type": "ProjectLabel", "group_id": 41 }], "current": [{ "id": 205, "title": "Platform", "color": "#123123", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "Platform related issues", "type": "ProjectLabel", "group_id": 41 }] } } } +``` + +### Wiki Page events[](#wiki-page-events "Permalink") + +在创建,更新或删除 Wiki 页面时触发. + +**请求标题**: + +``` +X-Gitlab-Event: Wiki Page Hook +``` + +**请求正文**: + +``` +{ "object_kind": "wiki_page", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon" }, "project": { "id": 1, "name": "awesome-project", "description": "This is awesome", "web_url": "http://example.com/root/awesome-project", "avatar_url": null, "git_ssh_url": "git@example.com:root/awesome-project.git", "git_http_url": "http://example.com/root/awesome-project.git", "namespace": "root", "visibility_level": 0, "path_with_namespace": "root/awesome-project", "default_branch": "master", "homepage": "http://example.com/root/awesome-project", "url": "git@example.com:root/awesome-project.git", "ssh_url": "git@example.com:root/awesome-project.git", "http_url": "http://example.com/root/awesome-project.git" }, "wiki": { "web_url": "http://example.com/root/awesome-project/-/wikis/home", "git_ssh_url": "git@example.com:root/awesome-project.wiki.git", "git_http_url": "http://example.com/root/awesome-project.wiki.git", "path_with_namespace": "root/awesome-project.wiki", "default_branch": "master" }, "object_attributes": { "title": "Awesome", "content": "awesome content goes here", "format": "markdown", "message": "adding an awesome page to the wiki", "slug": "awesome", "url": "http://example.com/root/awesome-project/-/wikis/awesome", "action": "create" } } +``` + +### Pipeline events[](#pipeline-events "Permalink") + +在管道状态更改时触发. + +**请求标题**: + +``` +X-Gitlab-Event: Pipeline Hook +``` + +**请求正文**: + +``` +{ "object_kind": "pipeline", "object_attributes":{ "id": 31, "ref": "master", "tag": false, "sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2", "before_sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2", "source": "merge_request_event", "status": "success", "stages":[ "build", "test", "deploy" ], "created_at": "2016-08-12 15:23:28 UTC", "finished_at": "2016-08-12 15:26:29 UTC", "duration": 63, "variables": [ { "key": "NESTOR_PROD_ENVIRONMENT", "value": "us-west-1" } ] }, "merge_request": { "id": 1, "iid": 1, "title": "Test", "source_branch": "test", "source_project_id": 1, "target_branch": "master", "target_project_id": 1, "state": "opened", "merge_status": "can_be_merged", "url": "http://192.168.64.1:3005/gitlab-org/gitlab-test/merge_requests/1" }, "user":{ "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", "email": "user_email@gitlab.com" }, "project":{ "id": 1, "name": "Gitlab Test", "description": "Atque in sunt eos similique dolores voluptatem.", "web_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test", "avatar_url": null, "git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git", "git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git", "namespace": "Gitlab Org", "visibility_level": 20, "path_with_namespace": "gitlab-org/gitlab-test", "default_branch": "master" }, "commit":{ "id": "bcbb5ec396a2c0f828686f14fac9b80b780504f2", "message": "test\n", "timestamp": "2016-08-12T17:23:21+02:00", "url": "http://example.com/gitlab-org/gitlab-test/commit/bcbb5ec396a2c0f828686f14fac9b80b780504f2", "author":{ "name": "User", "email": "user@gitlab.com" } }, "builds":[ { "id": 380, "stage": "deploy", "name": "production", "status": "skipped", "created_at": "2016-08-12 15:23:28 UTC", "started_at": null, "finished_at": null, "when": "manual", "manual": true, "allow_failure": false, "user":{ "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" }, "runner": null, "artifacts_file":{ "filename": null, "size": null } }, { "id": 377, "stage": "test", "name": "test-image", "status": "success", "created_at": "2016-08-12 15:23:28 UTC", "started_at": "2016-08-12 15:26:12 UTC", "finished_at": null, "when": "on_success", "manual": false, "allow_failure": false, "user":{ "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" }, "runner": { "id":380987, "description":"shared-runners-manager-6.gitlab.com", "active":true, "is_shared":true }, "artifacts_file":{ "filename": null, "size": null } }, { "id": 378, "stage": "test", "name": "test-build", "status": "success", "created_at": "2016-08-12 15:23:28 UTC", "started_at": "2016-08-12 15:26:12 UTC", "finished_at": "2016-08-12 15:26:29 UTC", "when": "on_success", "manual": false, "allow_failure": false, "user":{ "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" }, "runner": { "id":380987, "description":"shared-runners-manager-6.gitlab.com", "active":true, "is_shared":true }, "artifacts_file":{ "filename": null, "size": null } }, { "id": 376, "stage": "build", "name": "build-image", "status": "success", "created_at": "2016-08-12 15:23:28 UTC", "started_at": "2016-08-12 15:24:56 UTC", "finished_at": "2016-08-12 15:25:26 UTC", "when": "on_success", "manual": false, "allow_failure": false, "user":{ "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" }, "runner": { "id":380987, "description":"shared-runners-manager-6.gitlab.com", "active":true, "is_shared":true }, "artifacts_file":{ "filename": null, "size": null } }, { "id": 379, "stage": "deploy", "name": "staging", "status": "created", "created_at": "2016-08-12 15:23:28 UTC", "started_at": null, "finished_at": null, "when": "on_success", "manual": false, "allow_failure": false, "user":{ "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" }, "runner": null, "artifacts_file":{ "filename": null, "size": null } } ] } +``` + +### Job events[](#job-events "Permalink") + +在工作状态更改时触发. + +**请求标题**: + +``` +X-Gitlab-Event: Job Hook +``` + +**请求正文**: + +``` +{ "object_kind": "build", "ref": "gitlab-script-trigger", "tag": false, "before_sha": "2293ada6b400935a1378653304eaf6221e0fdb8f", "sha": "2293ada6b400935a1378653304eaf6221e0fdb8f", "build_id": 1977, "build_name": "test", "build_stage": "test", "build_status": "created", "build_started_at": null, "build_finished_at": null, "build_duration": null, "build_allow_failure": false, "build_failure_reason": "script_failure", "pipeline_id": 2366, "project_id": 380, "project_name": "gitlab-org/gitlab-test", "user": { "id": 3, "name": "User", "email": "user@gitlab.com", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" }, "commit": { "id": 2366, "sha": "2293ada6b400935a1378653304eaf6221e0fdb8f", "message": "test\n", "author_name": "User", "author_email": "user@gitlab.com", "status": "created", "duration": null, "started_at": null, "finished_at": null }, "repository": { "name": "gitlab_test", "description": "Atque in sunt eos similique dolores voluptatem.", "homepage": "http://192.168.64.1:3005/gitlab-org/gitlab-test", "git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git", "git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git", "visibility_level": 20 }, "runner": { "active": true, "is_shared": false, "id": 380987, "description": "shared-runners-manager-6.gitlab.com" } } +``` + +请注意, `commit.id`是管道的 ID,而不是提交的 ID. + +## Image URL rewriting[](#image-url-rewriting "Permalink") + +从 GitLab 11.2 开始,简单的图像引用被重写为在 webhooks 中使用绝对 URL. 因此,如果图像,合并请求,评论或维基页面的描述中包含以下内容: + +``` +![image](/uploads/$sha/image.png) +``` + +它将显示在 webhook 主体中,如下所示(假设 GitLab 安装在`gitlab.example.com` ,并且该项目位于`example-group/example-project` ): + +``` +![image](https://gitlab.example.com/example-group/example-project/uploads/$sha/image.png) +``` + +这不会重写已经指向 HTTP,HTTPS 或协议相对 URL 的 URL. 它还不会使用链接标记之类的高级 Markdown 功能重写图像 URL. + +## Testing webhooks[](#testing-webhooks "Permalink") + +您可以手动触发 Webhook. 将使用项目中的样本数据. >例如:要触发" `Push Events`您的项目应至少提交一次. + +[![Webhook testing](img/cee9b8bcba36170c0ae5df4747bb8c44.png)](img/webhook_testing.png) + +## Troubleshoot webhooks[](#troubleshoot-webhooks "Permalink") + +manbetx 客户端打不开存储 webhook 的每个执行. 您可以在每个 Webhook 的编辑页面上的"最近发送"部分中找到最近 2 天的记录. + +[![Recent deliveries](img/78dac22706dcca5ce3855d23987289ea.png)](img/webhook_logs.png) + +在本部分中,您可以看到 HTTP 状态代码(绿色表示 200-299 代码,红色表示其他代码,传递失败的`internal error` ),触发的事件,事件被调用的时间,请求的经过时间. + +如果需要有关执行的更多信息,可以单击`View details`链接. 在此页面上,您可以查看 GitLab 发送的数据(请求标头和正文)和收到的数据(响应标头和正文). + +在此页面上,您可以通过单击" `Resend Request`按钮以相同的数据重复`Resend Request` . + +> **注意:**如果已更新 Webhook 的 URL 或秘密令牌,则数据将被传递到新地址. + +### Receiving duplicate or multiple webhook requests triggered by one event[](#receiving-duplicate-or-multiple-webhook-requests-triggered-by-one-event "Permalink") + +当 GitLab 发送一个 Webhook 时,它期望在 10 秒内响应(设置默认值). 如果没有收到,它将重试网络挂钩. 如果端点在这 10 秒钟内未发送 HTTP 响应,则 GitLab 可能会确定挂钩失败并重试. + +如果接收到多个请求,可以通过取消注释或将以下设置添加到`/etc/gitlab/gitlab.rb`来尝试增加发送`/etc/gitlab/gitlab.rb`之后的默认值,以等待 HTTP 响应: + +``` +gitlab_rails['webhook_timeout'] = 10 +``` + +### Troubleshooting: “Unable to get local issuer certificate”[](#troubleshooting-unable-to-get-local-issuer-certificate "Permalink") + +启用 S​​SL 验证后,此错误表明 GitLab 无法验证 Webhook 端点的 SSL 证书. 通常,这是因为根证书不是由[CAcert.org](http://www.cacert.org/)确定的受信任的证书颁发机构[颁发的](http://www.cacert.org/) . + +如果不是这种情况,请考虑使用[SSL Checker](https://www.sslshopper.com/ssl-checker.html)来识别故障. 缺少中间证书是验证失败的常见原因. + +## Example webhook receiver[](#example-webhook-receiver "Permalink") + +如果您希望通过测试了解 GitLab 的 webhooks,可以使用在控制台会话中运行的简单回显脚本. 为了使以下脚本正常工作,您需要安装 Ruby. + +将以下文件另存为`print_http_body.rb` : + +``` +require 'webrick' + +server = WEBrick::HTTPServer.new(:Port => ARGV.first) +server.mount_proc '/' do |req, res| + puts req.body +end + +trap 'INT' do + server.shutdown +end +server.start +``` + +选择一个未使用的端口(例如 8000)并启动脚本: `ruby print_http_body.rb 8000` . 然后,将您的服务器作为 Webhook 接收器添加到 GitLab 中,作为`http://my.host:8000/` . + +在 GitLab 中按"测试"时,您应该在控制台中看到以下内容: + +``` +{"before":"077a85dd266e6f3573ef7e9ef8ce3343ad659c4e","after":"95cd4a99e93bc4bbabacfa2cd10e6725b1403c60",<SNIP>} +example.com - - [14/May/2014:07:45:26 EDT] "POST / HTTP/1.1" 200 0 +- -> / +``` + +**注意:**您可能需要[允许向本地网络](../../../security/webhooks.html)发送[请求,](../../../security/webhooks.html)以便添加此接收器. \ No newline at end of file diff --git a/_book/docs/094.md b/_book/docs/094.md new file mode 100644 index 0000000000000000000000000000000000000000..2497f9a1a3f3094c1a9104708e705136317b28da --- /dev/null +++ b/_book/docs/094.md @@ -0,0 +1,42 @@ +# YouTrack Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/youtrack.html](https://docs.gitlab.com/ee/user/project/integrations/youtrack.html) + +* [Enable the YouTrack integration](#enable-the-youtrack-integration) +* [Disable the internal issue tracker](#disable-the-internal-issue-tracker) +* [Referencing YouTrack issues in GitLab](#referencing-youtrack-issues-in-gitlab) + +# YouTrack Service[](#youtrack-service "Permalink") + +JetBrains [YouTrack](https://www.jetbrains.com/help/youtrack/standalone/YouTrack-Documentation.html)是一个基于 Web 的问题跟踪和项目管理平台. + +您可以在 GitLab 中将 YouTrack 配置为[外部问题跟踪器](../../../integration/external-issue-tracker.html) . + +## Enable the YouTrack integration[](#enable-the-youtrack-integration "Permalink") + +要在项目中启用 YouTrack 集成,请执行以下操作: + +1. 导航到项目的**"设置">" [集成"](overview.html#accessing-integrations)**页面. +2. 单击**YouTrack**服务,确保其处于活动状态,然后按照下表中的说明在页面上输入所需的详细信息. + + | Field | Description | + | --- | --- | + | **Project URL** | 链接到该 GitLab 项目的 YouTrack 中项目的 URL. | + | **问题网址** | 链接到该 GitLab 项目的 YouTrack 项目中问题的 URL. 请注意, **问题 URL**需要**URL 中的** `:id` . GitLab 使用此 ID 作为占位符来替换问题编号. | + +3. 点击**保存更改**按钮. + +一旦配置并启用了 YouTrack,您将在 GitLab 项目页面上看到 YouTrack 链接,该链接将您带到适当的 YouTrack 项目. + +## Disable the internal issue tracker[](#disable-the-internal-issue-tracker "Permalink") + +要在项目中禁用内部问题跟踪器: + +1. 导航到项目的**"设置">"常规"**页面. +2. 展开[权限部分](../settings/index.html#sharing-and-permissions) ,然后将**问题**切换为禁用. + +## Referencing YouTrack issues in GitLab[](#referencing-youtrack-issues-in-gitlab "Permalink") + +YouTrack 中的问题可以称为`<PROJECT>-<ID>` . `<PROJECT>`必须以字母开头,后跟字母,数字或下划线. `<ID>`是一个数字. 参考示例是`YT-101` , `Api_32-143`或`gl-030` . + +合并请求,提交或注释中对`<PROJECT>-<ID>`引用将自动链接到 YouTrack 问题 URL. 有关更多信息,请参阅[外部问题跟踪器](../../../integration/external-issue-tracker.html)文档. \ No newline at end of file diff --git a/_book/docs/095.md b/_book/docs/095.md new file mode 100644 index 0000000000000000000000000000000000000000..930e3be10f6008d4874d390d6268fcc30d2f281a --- /dev/null +++ b/_book/docs/095.md @@ -0,0 +1,384 @@ +# Insights + +> 原文:[https://docs.gitlab.com/ee/user/project/insights/](https://docs.gitlab.com/ee/user/project/insights/) + +* [View your project’s Insights](#view-your-projects-insights) +* [Configure your Insights](#configure-your-insights) +* [Permissions](#permissions) +* [Writing your `.gitlab/insights.yml`](#writing-your-gitlabinsightsyml) +* [Configuration parameters](#configuration-parameters) +* [Parameter details](#parameter-details) + * [`title`](#title) + * [`description`](#description) + * [`type`](#type) + * [`query`](#query) + * [`query.issuable_type`](#queryissuable_type) + * [`query.issuable_state`](#queryissuable_state) + * [`query.filter_labels`](#queryfilter_labels) + * [`query.collection_labels`](#querycollection_labels) + * [`query.group_by`](#querygroup_by) + * [`query.period_limit`](#queryperiod_limit) + * [`query.period_field`](#queryperiod_field) + * [`projects`](#projects) + * [`projects.only`](#projectsonly) +* [Complete example](#complete-example) + +# Insights[](#insights-ultimate "Permalink") + +[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. + +配置对您的项目至关重要的见解,以探索数据,例如分类诊断,在给定期间内创建/关闭的问题,合并请求的平均合并时间等等. + +[![Insights example bar chart](img/911c6aa51b9202fc3dc3bdc143b30f82.png)](img/project_insights.png) + +**注意:**此功能[在组级别也可用](../../group/insights/index.html) . + +## View your project’s Insights[](#view-your-projects-insights "Permalink") + +您可以通过点击左侧栏中的**Analytics(分析)> Insights**链接来访问项目的 Insights: + +[![Insights sidebar link](img/24ea9a3635dc27668b899d6785917b1b.png)](img/insights_sidebar_link_v12_8.png) + +## Configure your Insights[](#configure-your-insights "Permalink") + +使用项目中名为`.gitlab/insights.yml`的 YAML 文件配置`.gitlab/insights.yml` . 该文件将在项目的"见解"页面中使用. + +有关此文件内容的详细信息,请参见下面的[编写`.gitlab/insights.yml`](#writing-your-gitlabinsightsyml) . + +**注意:**一旦创建了配置文件,您也可以[将其用于项目的 group](../../group/insights/index.html#configure-your-insights) .**注意:**如果项目没有任何配置文件,则将尽可能尝试使用组配置. 如果该组没有任何配置,将使用默认配置. + +## Permissions[](#permissions "Permalink") + +如果您有权查看项目,则可以查看其见解. + +**注意:**您无法访问的问题或合并请求(因为您无法访问它们所属的项目,或者因为它们是机密的)会从 Insights 图表中过滤掉. + +您也可以查阅[组权限表](../../permissions.html#group-members-permissions) . + +## Writing your `.gitlab/insights.yml`[](#writing-your-gitlabinsightsyml "Permalink") + +`.gitlab/insights.yml`文件定义了将在项目或组的每个 Insights 页面中显示的 Insights 图表的结构和顺序. + +每个页面都有一个唯一的键以及一组要获取和显示的图表. + +例如,这是 Insights 的单个定义,它将显示一个带有一个图表的页面: + +``` +bugsCharts: + title: "Charts for bugs" + charts: + - title: "Monthly bugs created" + description: "Open bugs created per month" + type: bar + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + group_by: month + period_limit: 24 +``` + +每个图表定义均由键值对组成的哈希组成. + +例如,这是单个图表定义: + +``` +- title: "Monthly bugs created" + description: "Open bugs created per month" + type: bar + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + group_by: month + period_limit: 24 +``` + +## Configuration parameters[](#configuration-parameters "Permalink") + +图表被定义为定义图表行为的参数列表. + +下表列出了图表的可用参数: + +| Keyword | Description | +| --- | --- | +| [`title`](#title) | 图表标题. 这将显示在"见解"页面上. | +| [`description`](#description) | 单个图表的描述. 这将显示在相关图表上方. | +| [`type`](#type) | 图表类型: `bar` , `line`或`stacked-bar` . | +| [`query`](#query) | 散列,用于定义要成为图表一部分的问题/合并请求的条件. | + +## Parameter details[](#parameter-details "Permalink") + +以下是用于配置 Insights 图表的参数的详细说明. + +### `title`[](#title "Permalink") + +`title`是图表的标题,它将显示在 Insights 页面上. 例如: + +``` +monthlyBugsCreated: + title: "Monthly bugs created" +``` + +### `description`[](#description "Permalink") + +`description`文字显示在图表上方,但标题下方. 它用于提供有关图表的更多详细信息,例如: + +``` +monthlyBugsCreated: + title: "Monthly bugs created" + description: "Open bugs created per month" +``` + +### `type`[](#type "Permalink") + +`type`是图表类型. + +例如: + +``` +monthlyBugsCreated: + title: "Monthly bugs created" + type: bar +``` + +Supported values are: + +| Name | Example | +| --- | --- | +| `bar` | [![Insights example bar chart](img/441419241245b159818b469c6508f227.png)](img/insights_example_bar_chart.png) | +| `bar` (time series, i.e. when `group_by` is used) | [![Insights example bar time series chart](img/6cad1c326921f33ce6d53e7f2ebd1158.png)](img/insights_example_bar_time_series_chart.png) | +| `line` | [![Insights example stacked bar chart](img/e75b1239d806589f91c4a40aba7fdc05.png)](img/insights_example_line_chart.png) | +| `stacked-bar` | [![Insights example stacked bar chart](img/da13575f699b92fa864c2d3fae1fae9e.png)](img/insights_example_stacked_bar_chart.png) | + +### `query`[](#query "Permalink") + +`query`允许定义条件/合并请求成为图表的一部分. + +Example: + +``` +monthlyBugsCreated: + title: "Monthly bugs created" + description: "Open bugs created per month" + type: bar + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + collection_labels: + - S1 + - S2 + - S3 + - S4 + group_by: week + period_limit: 104 +``` + +#### `query.issuable_type`[](#queryissuable_type "Permalink") + +定义要为其创建图表的"可发行"的类型. + +支持的值为: + +* `issue` :图表将显示问题的数据. +* `merge_request` :图表将显示合并请求的数据. + +#### `query.issuable_state`[](#queryissuable_state "Permalink") + +按查询的"可发行"状态过滤. + +默认情况下,将使用`opened`状态过滤器. + +支持的值为: + +* `opened` :未解决问题/合并请求. +* `closed` :已关闭未解决的问题/合并请求. +* `locked` :已锁定讨论的问题/合并请求. +* `merged` :合并的合并请求. +* `all` :在所有状态下发出/合并请求 + +#### `query.filter_labels`[](#queryfilter_labels "Permalink") + +按应用于查询的"可发行"的标签过滤. + +默认情况下,不应用标签过滤器. 必须将所有定义的标签应用于"可发行",才能对其进行选择. + +Example: + +``` +monthlyBugsCreated: + title: "Monthly regressions created" + type: bar + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + - regression +``` + +#### `query.collection_labels`[](#querycollection_labels "Permalink") + +通过配置的标签将"可发行"分组. + +默认情况下,不会进行分组. 使用此关键字时,需要将`type`设置为`line`或`stacked-bar` . + +Example: + +``` +weeklyBugsBySeverity: + title: "Weekly bugs by severity" + type: stacked-bar + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + collection_labels: + - S1 + - S2 + - S3 + - S4 +``` + +#### `query.group_by`[](#querygroup_by "Permalink") + +定义图表的 X 轴. + +支持的值为: + +* `day` : `day`组数据. +* `week` : `week`组数据. +* `month` : `month`组数据. + +#### `query.period_limit`[](#queryperiod_limit "Permalink") + +定义过去查询"可耗材"的距离. + +该单位与您定义的`query.group_by`有关. 例如,如果您定义了`query.group_by: 'day'`则`query.period_limit: 365`意思是"收集并显示最近 365 天的数据". + +默认情况下,将根据您定义的`query.group_by`应用默认值. + +| `query.group_by` | 默认值 | +| --- | --- | +| `day` | 30 | +| `week` | 4 | +| `month` | 12 | + +#### `query.period_field`[](#queryperiod_field "Permalink") + +定义用于将"可耗材"分组的时间戳字段. + +支持的值为: + +* `created_at` (默认):使用`created_at`字段对数据进行分组. +* `closed_at` :使用`closed_at`字段对数据进行`closed_at` (仅针对问题). +* `merged_at` :使用`merged_at`字段对数据进行`merged_at` (仅适用于合并请求). + +`period_field`自动设置为: + +* `closed_at` if `query.issuable_state` is `closed` +* `merged_at` if `query.issuable_state` is `merged` +* `created_at` otherwise + +**注意:**在解决[此错误](https://gitlab.com/gitlab-org/gitlab/-/issues/26911)之前,您可能会看到`created_at`代替`merged_at` . 将使用`created_at`代替. + +### `projects`[](#projects "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10904) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.4. + +您可以限制从以下位置查询"可耗材"的位置: + +* 如果`.gitlab/insights.yml`用于一[组的见解](../../group/insights/index.html#configure-your-insights) ,有`projects` ,你可以限制要查询的项目. 默认情况下,将使用该组下的所有项目. +* 如果将`.gitlab/insights.yml`用于项目的见解,则指定任何其他项目均不会产生任何结果. 默认情况下,将使用项目本身. + +#### `projects.only`[](#projectsonly "Permalink") + +`projects.only`选项指定应从中查询"可发行物品"的项目. + +在以下情况下,此处列出的项目将被忽略: + +* 它们不存在. +* 当前用户没有足够的权限来读取它们. +* 他们不在小组中. + +在以下`insights.yml`示例中,我们指定将在其中使用查询的项目. 设置小组的见解时,此示例非常有用: + +``` +monthlyBugsCreated: + title: "Monthly bugs created" + description: "Open bugs created per month" + type: bar + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + projects: + only: + - 3 # You can use the project ID + - groupA/projectA # Or full project path + - groupA/subgroupB/projectC # Projects in subgroups can be included + - groupB/project # Projects outside the group will be ignored +``` + +## Complete example[](#complete-example "Permalink") + +``` +.projectsOnly: &projectsOnly + projects: + only: + - 3 + - groupA/projectA + - groupA/subgroupB/projectC + +bugsCharts: + title: "Charts for bugs" + charts: + - title: "Monthly bugs created" + description: "Open bugs created per month" + type: bar + <<: *projectsOnly + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + group_by: month + period_limit: 24 + + - title: "Weekly bugs by severity" + type: stacked-bar + <<: *projectsOnly + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + collection_labels: + - S1 + - S2 + - S3 + - S4 + group_by: week + period_limit: 104 + + - title: "Monthly bugs by team" + type: line + <<: *projectsOnly + query: + issuable_type: merge_request + issuable_state: opened + filter_labels: + - bug + collection_labels: + - Manage + - Plan + - Create + group_by: month + period_limit: 24 +``` \ No newline at end of file diff --git a/_book/docs/096.md b/_book/docs/096.md new file mode 100644 index 0000000000000000000000000000000000000000..5ea5c06ea60f6e17b4b7da8f517eb71a6df480e7 --- /dev/null +++ b/_book/docs/096.md @@ -0,0 +1,174 @@ +# Issues + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/](https://docs.gitlab.com/ee/user/project/issues/) + +* [Overview](#overview) +* [Parts of an issue](#parts-of-an-issue) +* [Viewing and managing issues](#viewing-and-managing-issues) + * [Issue page](#issue-page) + * [Issues list](#issues-list) + * [Issue boards](#issue-boards) + * [Design Management](#design-management) + * [Epics](#epics-premium) + * [Related issues](#related-issues-starter) + * [Crosslinking issues](#crosslinking-issues) + * [Similar issues](#similar-issues) + * [Health status](#health-status-ultimate) + * [Disable issue health status](#disable-issue-health-status) +* [Other Issue actions](#other-issue-actions) + +# Issues[](#issues "Permalink") + +问题是在 GitLab 中就想法和计划工作进行协作的基本介质. + +## Overview[](#overview "Permalink") + +GitLab 问题跟踪器是用于协作开发想法,解决问题和计划工作的高级工具. + +通过问题,可以在以下各项之间,在实施之前和期间共享和讨论提案: + +* 您和您的团队. +* 外部合作者. + +它们还可以用于各种其他目的,根据您的需求和工作流程进行定制. + +问题始终与特定项目相关联,但是如果您在一个小组中有多个项目,则还可以在小组级别集体查看所有问题. + +**常见的用例包括:** + +* 讨论新想法的实施 +* 跟踪任务和工作状态 +* 接受功能建议,问题,支持请求或错误报告 +* 详细说明新的代码实现 + +另请参见[始终从问题开始讨论](https://about.gitlab.com/blog/2016/03/03/start-with-an-issue/) . + +要了解 GitLab 战略营销部门如何将 GitLab 问题与[标签](../labels.html)和[问题板一起使用](../issue_board.html) ,请参阅有关[管理问题的承诺](https://www.youtube.com/watch?v=cuIHNintg1o&t=3)的视频. + +## Parts of an issue[](#parts-of-an-issue "Permalink") + +问题包含各种内容和元数据,从而在使用方式上具有很大的灵活性. 每个问题可以包含以下属性,尽管并非必须设置所有项目. + +| + +* Content + * Title + * 描述和任务 + * 评论和其他活动 +* People + * Author + * Assignee(s) +* State + * 状态(打开或关闭) + * 健康状况(正常,需要注意或有危险) + * Confidentiality + * 任务(完成与未完成) + + | + +* 规划和跟踪 + * 里程碑 + * 截止日期 + * 重量 + * 时间跟踪 + * 标签 + * 投票数 + * 反应表情 + * 关联问题 + * 分配史诗 + * 唯一的发行号和 URL + + | + +## Viewing and managing issues[](#viewing-and-managing-issues "Permalink") + +虽然您可以在[问题页面](#issue-page)上查看和管理问题的全部详细信息,但也可以一次使用" [问题列表"](#issues-list) ," [问题板"](#issue-boards) ,"问题参考"和" [Epic"](#epics-premium)处理多个问题 . + +针对问题的关键操作包括: + +* [Creating issues](managing_issues.html#create-a-new-issue) +* [Moving issues](managing_issues.html#moving-issues) +* [Closing issues](managing_issues.html#closing-issues) +* [Deleting issues](managing_issues.html#deleting-issues) + +### Issue page[](#issue-page "Permalink") + +[![Issue view](img/a15f0b2964d7094b019c5c33425ba75b.png)](img/issues_main_view.png) + +在问题的页面上,您可以查看问题的[所有方面,](issue_data_and_actions.html)如果有必要的[权限](../../permissions.html) ,可以对其进行修改. + +### Issues list[](#issues-list "Permalink") + +[![Project issues list view](img/854d722d9976d5b36956ddbe41ceae48.png)](img/project_issues_list_view.png) + +在"问题列表"上,可以从更高级别的组上下文中打开"问题列表",从而可以查看当前项目中的所有问题,也可以查看多个项目中的所有问题. 使用[搜索查询](../../search/index.html#filtering-issue-and-merge-request-lists)过滤问题列表,包括特定的元数据,例如标签,受让人,状态等. 从此视图,您还可以对显示的问题[进行批量](../bulk_editing.html)更改. + +有关更多信息,请参见[问题数据和操作](issue_data_and_actions.html)页面,以了解问题中所有字段和信息的摘要. + +您可以通过多种方式对问题列表进行排序,例如,通过问题创建日期,里程碑到期日期. 有关更多信息,请参见" [排序和排序问题列表"](sorting_issue_lists.html)页面. + +### Issue boards[](#issue-boards "Permalink") + +[![Issue board](img/fd79e7dae86040d6e1249793ae0b1502.png)](img/issue_board.png) + +[发行板](../issue_board.html)是看板,其栏目根据其标签或他们的受让人显示问题 . 它们提供了使用高度可定制的工作流来管理问题的灵活性. + +您可以在栏中重新排序问题. 如果将发行卡拖到另一列,则其关联的标签或受让人将更改以匹配新列的标签或受让人. 整个董事会也可以被筛选为仅包括某个里程碑或总体标签中的问题. + +### Design Management[](#design-management "Permalink") + +使用[Design Management](design_management.html) ,您可以将设计资产上载到问题并一起查看它们,以轻松地与团队共享和协作. + +### Epics[](#epics-premium "Permalink") + +[Epics](../../group/epics/index.html)通过跟踪跨项目和里程碑共享主题的问题组,使您可以更有效,更[轻松地](../../group/epics/index.html)管理项目组合. + +### Related issues[](#related-issues-starter "Permalink") + +您可以将两个问题标记为"相关",以便在查看一个问题时,另一个[问题](related_issues.html)始终列在" [相关问题"](related_issues.html)部分中. 这可以帮助显示重要的上下文,例如过去的工作,依赖项或重复项. + +### Crosslinking issues[](#crosslinking-issues "Permalink") + +您可以通过引用另一个问题中的问题来[交叉链接问题](crosslinking_issues.html) ,也可以通过包括其 URL 或 ID 来合并请求. 参考的问题在活动流中显示有关参考的消息,并带有指向其他问题或 MR 的链接. + +### Similar issues[](#similar-issues "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22866) . + +为了防止同一主题重复出现问题,GitLab 在创建新问题时会搜索相似的问题. + +在" **新问题"**页面中键入标题时,GitLab 会搜索用户在当前项目中有权访问的所有问题的标题和描述. 标题框下方最多显示五个类似问题(按最新更新排序). 请注意,此功能需要启用[GraphQL](../../../api/graphql/index.html) . + +[![Similar issues](img/95882a4976be6b95971ad0011fcd7617.png)](img/similar_issues.png) + +### Health status[](#health-status-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36427) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. + +为了帮助您跟踪问题的状态,您可以为每个问题分配一个状态,以标记按计划进行或需要注意以按时进行的工作: + +* **步入正轨** (green) +* **需要注意** (amber) +* **有一定风险** (red) + +[!["On track" health status on an issue](img/8308fbab7a41e24cad0bf6c358863ae3.png)](img/issue_health_status_dropdown_v12_10.png) + +然后,您可以在[Epic 树上](../../group/epics/index.html#issue-health-status-in-epic-tree-ultimate)查看问题状态. + +#### Disable issue health status[](#disable-issue-health-status "Permalink") + +此功能默认启用`:save_issuable_health_status`功能标志. 但是,在某些情况下,此功能与旧配置不兼容. 要在迁移配置时关闭该功能,请要求具有 Rails 控制台访问权限的 GitLab 管理员运行以下命令: + +``` +Feature.disable(:save_issuable_health_status) +``` + +## Other Issue actions[](#other-issue-actions "Permalink") + +* [Create an issue from a template](../../project/description_templates.html#using-the-templates) +* [Set a due date](due_dates.html) +* [批量编辑问题](../bulk_editing.html) -从问题列表中选择多个问题,以批量更改其状态,受让人,里程碑或标签. +* [Import issues](csv_import.html) +* [Export issues](csv_export.html) +* [Issues API](../../../api/issues.html) +* 配置[外部问题跟踪器,](../../../integration/external-issue-tracker.html)例如 Jira,Redmine 或 Bugzilla. \ No newline at end of file diff --git a/_book/docs/097.md b/_book/docs/097.md new file mode 100644 index 0000000000000000000000000000000000000000..e11a4f4b443c24c87cc66eaa2fdc8a87809f60c2 --- /dev/null +++ b/_book/docs/097.md @@ -0,0 +1,49 @@ +# Crosslinking Issues + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/crosslinking_issues.html](https://docs.gitlab.com/ee/user/project/issues/crosslinking_issues.html) + +* [From Commit Messages](#from-commit-messages) +* [From Related Issues](#from-related-issues) +* [From Merge Requests](#from-merge-requests) + +# Crosslinking Issues[](#crosslinking-issues "Permalink") + +请通读[GitLab 问题文档](index.html)以获取有关 GitLab 问题的概述. + +## From Commit Messages[](#from-commit-messages "Permalink") + +每次在提交消息中提及问题时,您都在开发工作流的两个阶段之间建立一种关系:问题本身以及与该问题相关的第一次提交. + +如果问题和您要提交的代码都在同一项目中,则只需在提交消息中添加`#xxx` ,其中`xxx`是问题编号. 如果它们不在同一项目中,则可以将完整的 URL 添加到问题中( `https://gitlab.com/<username>/<projectname>/issues/<xxx>` ). + +``` +git commit -m "this is my commit message. Ref #xxx" +``` + +or + +``` +git commit -m "this is my commit message. Related to https://gitlab.com/<username>/<projectname>/issues/<xxx>" +``` + +当然,您可以使用自己的 GitLab 实例的 URL 替换`gitlab.com` . + +**注意:**将您的第一次提交与您的问题相关联,对于通过[GitLab Cycle Analytics](https://about.gitlab.com/stages-devops-lifecycle/value-stream-analytics/)跟踪您的过程将非常重要. 它将测量计划该问题的实施所花费的时间,即从创建问题到进行第一次提交之间的时间. + +## From Related Issues[](#from-related-issues "Permalink") + +在合并请求中提及相关问题以及其他问题对于您的团队成员和协作者了解有关同一主题的未解决问题很有用. + +如上所述,当您[从提交消息中提到问题](#from-commit-messages)时,您可以执行此操作. + +当在问题`#222`提到问题`#111`时,问题`#111`还将在其跟踪器中显示一条通知. 也就是说,您只需提及一次关系即可在两个问题中均显示该关系. 在[合并请求中](#from-merge-requests)提及问题时,也是如此. + +[![issue mentioned in issue](img/b962444c71ad27ba05dfc6bfc69269f4.png)](img/mention_in_issue.png) + +## From Merge Requests[](#from-merge-requests "Permalink") + +Mentioning issues in merge request comments works exactly the same way as they do for [related issues](#from-related-issues). + +当您在合并请求说明中提到问题时,它将仅[将问题和合并请求链接在一起](#from-related-issues) . 此外,您还可以[将问题设置](managing_issues.html#closing-issues-automatically)为在合并请求合并后立即[自动关闭](managing_issues.html#closing-issues-automatically) . + +[![issue mentioned in MR](img/f36631c8d1fd9cb42fb7c58a495c24be.png)](img/mention_in_merge_request.png) \ No newline at end of file diff --git a/_book/docs/098.md b/_book/docs/098.md new file mode 100644 index 0000000000000000000000000000000000000000..0fb51b91772938fcc7a4fcd654ac29686f1082ce --- /dev/null +++ b/_book/docs/098.md @@ -0,0 +1,251 @@ +# Design Management + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/design_management.html](https://docs.gitlab.com/ee/user/project/issues/design_management.html) + +* [Overview](#overview) +* [Requirements](#requirements) +* [Supported files](#supported-files) +* [Limitations](#limitations) +* [GitLab-Figma plugin](#gitlab-figma-plugin) +* [The Design Management section](#the-design-management-section) + * [Enable or disable displaying Designs on the issue description](#enable-or-disable-displaying-designs-on-the-issue-description-core-only) +* [Adding designs](#adding-designs) + * [Skipped designs](#skipped-designs) +* [Viewing designs](#viewing-designs) + * [Exploring designs by zooming](#exploring-designs-by-zooming) +* [Deleting designs](#deleting-designs) +* [Starting discussions on designs](#starting-discussions-on-designs) +* [Resolve Design threads](#resolve-design-threads) +* [Referring to designs in Markdown](#referring-to-designs-in-markdown) + * [Enable or disable design references](#enable-or-disable-design-references-core-only) +* [Design activity records](#design-activity-records) + +# Design Management[](#design-management "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.2 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/660) . +* 在 13.0 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) GitLab Core. + +## Overview[](#overview "Permalink") + +Design Management 允许您将设计资产(线框,模型等)上载到 GitLab 问题,并将它们存储在一个位置,由问题中的 Design Management 页面访问,从而为产品设计师,产品经理和工程师提供了一种方法在单一事实来源上进行设计合作. + +您可以轻松地与团队共享设计的模型,也可以轻松查看和解决视觉回归问题. + +有关概述,请参见视频[设计管理(GitLab 12.2)](https://www.youtube.com/watch?v=CCMtCqdK_aM) . + +## Requirements[](#requirements "Permalink") + +设计管理需要启用[大文件存储(LFS)](../../../topics/git/lfs/index.html) : + +* 对于 GitLab.com,已启用 LFS. +* 对于自我管理的实例,GitLab 管理员必须[全局启用 LFS](../../../administration/lfs/index.html) . +* 对于 GitLab.com 和自我管理实例:必须为项目本身启用 LFS. 如果全局启用,则默认情况下将对所有项目启用 LFS. 要在项目级别启用 LFS,请导航至项目的**"设置">"常规"** ,展开" **可见性",项目功能,权限**并启用" **Git Large File Storage"** . + +设计管理还要求项目使用[哈希存储](../../../administration/raketasks/storage.html#migrate-to-hashed-storage) . 从 GitLab 10.0 开始,默认情况下,新创建的项目使用哈希存储. GitLab 管理员可以通过导航到" **管理区域">"项目"** ,然后选择有问题的项目来验证项目的存储类型. 如果项目的*Gitaly 相对路径*包含`@hashed`则可以将其标识为散列存储. + +如果不满足要求,则" **设计"**选项卡会向用户显示一条消息. + +## Supported files[](#supported-files "Permalink") + +上传的文件的文件扩展名必须为`png` , `jpg` , `jpeg` , `gif` , `bmp` , `tiff`或`ico` . + +计划在将来的版本中支持[SVG 文件](https://gitlab.com/gitlab-org/gitlab/-/issues/12771)和[PDF](https://gitlab.com/gitlab-org/gitlab/-/issues/32811) . + +## Limitations[](#limitations "Permalink") + +* 设计上载一次限制为 10 个文件. +* 从 GitLab 13.1 起,设计文件名限制为 255 个字符. +* [销毁项目时,不会删除](https://gitlab.com/gitlab-org/gitlab/-/issues/13429)设计管理数据. +* [移动](https://gitlab.com/gitlab-org/gitlab/-/issues/13426)问题时, [不会移动](https://gitlab.com/gitlab-org/gitlab/-/issues/13426) Design Management 数据; [删除](https://gitlab.com/gitlab-org/gitlab/-/issues/13427)问题时,也不会[删除](https://gitlab.com/gitlab-org/gitlab/-/issues/13427)它. +* 从 GitLab 12.7 起,设计管理数据[可以](../../../administration/geo/replication/datatypes.html#limitations-on-replicationverification)由 Geo [复制](../../../administration/geo/replication/datatypes.html#limitations-on-replicationverification) ,但[不能验证](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) . +* 只能删除设计的最新版本. +* 删除的设计无法恢复,但是您可以在以前的设计版本中看到它们. + +## GitLab-Figma plugin[](#gitlab-figma-plugin "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab-figma-plugin/-/issues/2) . + +通过无缝的工作流程将设计环境与源代码管理连接起来. GitLab-Figma 插件通过将产品设计师的工作从 Figma 直接带到 GitLab Issues 作为上载的 Designs,使在 GitLab 中进行协作变得快捷,容易. + +要使用该插件,请从[Figma 目录中](https://www.figma.com/community/plugin/860845891704482356)安装它,并通过个人访问令牌连接到 GitLab. 有关详细信息,请参见[插件文档](https://gitlab.com/gitlab-org/gitlab-figma-plugin/-/wikis/home) . + +## The Design Management section[](#the-design-management-section "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/223193)设计直接显示在问题描述中,而不是单独的选项卡上. +* 新显示将部署在功能标记后面,默认情况下启用. +* 在 GitLab.com 上启用了它. +* 不能根据项目启用或禁用它. +* 建议用于生产. +* 对于 GitLab 自我管理的实例,GitLab 管理员可以选择[禁用它](#enable-or-disable-displaying-designs-on-the-issue-description-core-only) . 如果禁用,它将"设计"移回" **设计"**选项卡. + +您可以在问题描述的" **设计管理"**部分中找到: + +[![Designs section](img/a9325984eddfbb907563c5bf5003f704.png)](img/design_management_v13_2.png) + +### Enable or disable displaying Designs on the issue description[](#enable-or-disable-displaying-designs-on-the-issue-description-core-only "Permalink") + +正在开发关于问题描述的设计,但已准备好用于生产. 它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以选择为您的实例禁用它. + +禁用它: + +``` +Feature.disable(:design_management_moved) +``` + +要启用它: + +``` +Feature.enable(:design_management_moved) +``` + +通过禁用此功能,设计将显示在" **设计"**选项卡上,而不是直接显示在问题描述上. + +## Adding designs[](#adding-designs "Permalink") + +要上传设计图像,请将文件从计算机上拖放到"设计管理"部分,或单击" **上传"**以从文件浏览器中选择图像: + +[![Designs empty state](img/cbd0470f26aadc25ca385447ade97392.png)](img/design_management_upload_v13.2.png) + +在[GitLab Premium](https://about.gitlab.com/pricing/) 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) ,您可以将设计拖放到专用放置区域以上载它们. + +[![Drag and drop design uploads](img/28e0f270ca5b3b728207d80c19a82d71.png)](img/design_drag_and_drop_uploads_v13_2.png) + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/202634)后,您还可以从文件系统复制图像并将其作为新设计直接粘贴到 GitLab 的"设计"页面上. + +在 macOS 上,您还可以截取屏幕截图,并同时单击`Control` + `Command` + `Shift` + `3` ,将其立即复制到剪贴板,然后将其粘贴为设计. + +复制和粘贴有一些限制: + +* 一次只能粘贴一张图像. 复制/粘贴多个文件时,只会上传第一个文件. +* 所有图像将在引擎盖下转换为`png`格式,因此当您要复制/粘贴`gif`文件时,会导致动画损坏. +* 如果要从剪贴板粘贴屏幕截图,它将被重命名为`design_<timestamp>.png` +* Copy/pasting designs is not supported on Internet Explorer. + +与现有的上载设计具有相同文件名的设计将创建该设计的新版本,并将替换以前的版本. 如果文件名相同,则在[GitLab Premium](https://about.gitlab.com/pricing/) 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34353)后,将设计放到现有的上载设计上也会创建一个新版本. + +如果问题已移动或[讨论被锁定](../../discussions/#lock-discussions) ,则无法添加设计. + +### Skipped designs[](#skipped-designs "Permalink") + +与现有上传的设计具有相同文件名*且*其内容未更改的设计将被跳过. 这意味着将不会创建该设计的新版本. 跳过设计时,将通过关于"问题"的警告消息通知您. + +## Viewing designs[](#viewing-designs "Permalink") + +单击"设计管理"页面上的图像可以将其放大. 您可以通过单击右上角的导航按钮或使用`左` / `右`键盘按钮来浏览设计. + +设计文件名右侧列出了有关设计的讨论数(如果有). 单击此数字可以放大设计,就像单击设计上的其他任何位置一样. 添加或修改设计时,项目上会显示一个图标,以帮助总结版本之间的更改. + +| Indicator | Example | +| --- | --- | +| Discussions | [![Discussions Icon](img/1162f64da937aa1ef37877c6b8930e1e.png)](img/design_comments_v12_3.png) | +| 已修改(在所选版本中) | [![Design Modified](img/3887423740965d20eecf9471bc1b3061.png)](img/design_modified_v12_3.png) | +| 已添加(在所选版本中) | [![Design Added](img/3601605e24186a1976e7aff09112bb7e.png)](img/design_added_v12_3.png) | + +### Exploring designs by zooming[](#exploring-designs-by-zooming "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13217) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7. + +通过放大和缩小图像,可以更详细地探索设计. 使用图像底部的`+`和`-`按钮控制缩放量. 缩放后,您仍然可以在图像上[开始新的讨论](#starting-discussions-on-designs) ,并查看任何现有的讨论. 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/197324) ,放大后,您可以在图像上单击并拖动以在图像中移动. + +[![Design zooming](img/9bf0c7423d5735ccdfbdfe250f9a5452.png)](img/design_zooming_v12_7.png) + +## Deleting designs[](#deleting-designs "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11089) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4. + +有两种删除设计的方法:分别手动删除它们,或选择其中几个立即删除,如下所示. + +要删除单个设计,请单击它以将其放大查看,然后单击右上角的垃圾桶图标,并通过单击模式窗口上的" **删除"**按钮来确认删除: + +[![Confirm design deletion](img/b15b2918f982a43ce2379b4f2ec765a9.png)](img/confirm_design_deletion_v12_4.png) + +要一次删除多个设计,请在设计的列表视图上,首先选择要删除的设计: + +[![Select designs](img/9f6da2599274d0db274d6aa19a27fcfc.png)](img/select_designs_v12_4.png) + +选择后,单击" **删除所选的"**按钮以确认删除: + +[![Delete multiple designs](img/eac2240244a4d3fb9f3d16c19760ea53.png)](img/delete_multiple_designs_v12_4.png) + +**注意:**只能删除设计的最新版本. 删除的设计不会永久丢失; 可以通过浏览以前的版本来查看它们. + +## Starting discussions on designs[](#starting-discussions-on-designs "Permalink") + +上传设计后,您可以通过单击您要关注讨论的确切位置上的图像来开始讨论. 将图钉添加到图像,以标识讨论的位置. + +[![Starting a new discussion on design](img/a272933779dc7642aed4eb4acde12df9.png)](img/adding_note_to_design_1.png) + +在[GitLab Premium](https://about.gitlab.com/pricing/) 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) ,您可以通过在图像周围拖动来调整销的位置. 当您的设计布局在各修订版之间进行了更改时,或者需要移动现有的引脚以在其位置添加新的引脚时,这很有用. + +不同的讨论有不同的引脚号: + +[![Discussions on designs](img/16db6a809ddf03cf101fdbec905d41a2.png)](img/adding_note_to_design_2.png) + +从 GitLab 12.5 起,新的讨论将输出到问题活动中,以便所有相关人员都可以参与讨论. + +## Resolve Design threads[](#resolve-design-threads "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13049) . + +Discussion threads can be resolved on Designs. + +有两种解决/取消解决设计线程的方法: + +1. 您可以通过单击讨论的第一个评论的右上角的" **解决线程"**的复选标记图标,将一个线程标记为已解决或未解决: + +[![Resolve thread icon](img/729f4c6815c7118c098b6925f2375918.png)](img/resolve_design-discussion_icon_v13_1.png) + +1. 还可以通过使用复选框在其线程中解析或不解析设计线程. 回复评论时,您会看到一个复选框,您可以单击该复选框以在发布后解决或取消解决线程: + +[![Resolve checkbox](img/a14ce4f4a816ce9ceea3133c64b5f328.png)](img/resolve_design-discussion_checkbox_v13_1.png) + +请注意,您已解决的注释图钉将从设计中消失,以腾出空间进行新的讨论. 但是,如果您需要重新访问或找到已解决的讨论,则所有已解决的主题将在右侧栏底部的" **已解决的注释"**区域中可用. + +## Referring to designs in Markdown[](#referring-to-designs-in-markdown "Permalink") + +> * [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217160) in **亚搏体育 app 13.1**. +> * 它部署在功能标志后面,默认情况下处于禁用状态. +> * 它在 GitLab.com 上被禁用. +> * 不建议将其用于生产. +> * 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-design-references-core-only) . + +我们支持在[Markdown 中](../../markdown.html)引用设计,在整个应用程序中都可用,包括合并请求和问题描述,讨论和评论以及 Wiki 页面. + +目前,支持完整的 URL 引用. 例如,如果我们使用以下内容引用设计: + +``` +See https://gitlab.com/your-group/your-project/-/issues/123/designs/homescreen.png +``` + +这将呈现为: + +> See [#123[homescreen.png]](https://gitlab.com/your-group/your-project/-/issues/123/designs/homescreen.png) + +### Enable or disable design references[](#enable-or-disable-design-references-core-only "Permalink") + +设计参考解析正在开发中,尚未准备好用于生产. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以为您的实例启用它. + +要启用它: + +``` +Feature.enable(:design_management_reference_filter_gfm_pipeline) +``` + +禁用它: + +``` +Feature.disable(:design_management_reference_filter_gfm_pipeline) +``` + +## Design activity records[](#design-activity-records "Permalink") + +版本历史 + +* 在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33051) . +* 在 GitLab 13.2 中[删除](https://gitlab.com/gitlab-org/gitlab/-/issues/225205)了[功能标志](https://gitlab.com/gitlab-org/gitlab/-/issues/225205) . + +GitLab 跟踪设计上的用户活动事件(创建,删除和更新),并显示在[用户配置文件](../../profile/index.html#user-profile) , [组](../../group/index.html#view-group-activity)和[项目](../index.html#project-activity)活动页面上. \ No newline at end of file diff --git a/_book/docs/099.md b/_book/docs/099.md new file mode 100644 index 0000000000000000000000000000000000000000..00343c63c777baf912d10b2cbdb9ba3e0e3b04a3 --- /dev/null +++ b/_book/docs/099.md @@ -0,0 +1,96 @@ +# Confidential issues + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/confidential_issues.html](https://docs.gitlab.com/ee/user/project/issues/confidential_issues.html) + +* [Making an issue confidential](#making-an-issue-confidential) +* [Modifying issue confidentiality](#modifying-issue-confidentiality) +* [Indications of a confidential issue](#indications-of-a-confidential-issue) +* [Permissions and access to confidential issues](#permissions-and-access-to-confidential-issues) +* [Merge Requests for Confidential Issues](#merge-requests-for-confidential-issues) + * [How it works](#how-it-works) + +# Confidential issues[](#confidential-issues "Permalink") + +在 GitLab 8.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3282) . + +机密性问题是仅对具有[足够权限](#permissions-and-access-to-confidential-issues)的项目成员可见的问题. 开源项目和公司都可以使用机密问题来使安全漏洞不公开或防止意外泄漏. + +## Making an issue confidential[](#making-an-issue-confidential "Permalink") + +您可以在创建问题或编辑现有问题的过程中将其保密. + +创建新问题时,可以在文本区域下方的复选框中将问题标记为机密. 选中该框,然后点击" **提交问题"**按钮以创建问题. 对于现有问题,请对其进行编辑,选中机密复选框,然后点击**保存更改** . + +[![Creating a new confidential issue](img/43a1d5a081bb166e1d43d6e671f250e1.png)](img/confidential_issues_create.png) + +## Modifying issue confidentiality[](#modifying-issue-confidentiality "Permalink") + +有两种方法可以更改问题的机密性. + +第一种方法是编辑问题并标记/取消标记机密复选框. 保存问题后,它将更改问题的机密性. + +第二种方法是在边栏中找到"保密性"部分,然后单击" **编辑"** . 应该会出现一个弹出窗口,并为您提供打开或关闭机密性的选项. + +| 关闭机密性 | Turn on confidentiality | +| --- | --- | +| [![Turn off confidentiality](img/429e9751a8b0336bb8b7e3faab15a373.png)](img/turn_off_confidentiality.png) | [![Turn on confidentiality](img/3252759837ced64a222db48c62becdd3.png)](img/turn_on_confidentiality.png) | + +系统注释在问题注释中指出了从常规到机密(反之亦然)的每项更改. + +[![Confidential issues system notes](img/b66dc4137ac73e81c66e408cf9fcf391.png)](img/confidential_issues_system_notes.png) + +## Indications of a confidential issue[](#indications-of-a-confidential-issue "Permalink") + +> **注意:**如果您没有[足够的权限](#permissions-and-access-to-confidential-issues) ,您将根本看不到机密问题. + +有几件事在视觉上将机密问题与常规问题分开. 在问题索引页面视图中,您可以在标记为机密的问题旁边看到斜线图标. + +[![Confidential issues index page](img/8cebf5d928a8666adcfc25eccfeec89e.png)](img/confidential_issues_index_page.png) + +* * * + +同样,在问题内部,您可以在问题编号旁边看到斜线图标,但在注释区域中也有一个指示符,表明您正在评论的问题是机密的. + +[![Confidential issue page](img/ea665ae1d507d66f5a44d05ff9e32613.png)](img/confidential_issues_issue_page.png) + +侧边栏上还有一个指示保密性的指示器. + +| 机密问题 | 非机密问题 | +| --- | --- | +| [![Sidebar confidential issue](img/813e077e7aa22bb747b5f237984f1b22.png)](img/sidebar_confidential_issue.png) | [![Sidebar not confidential issue](img/6a33d33154553990ed15338a6f9c7b35.png)](img/sidebar_not_confidential_issue.png) | + +## Permissions and access to confidential issues[](#permissions-and-access-to-confidential-issues "Permalink") + +对于机密问题,有两种级别的访问权限. 一般规则是,机密问题仅对具有[Reporter 访问权限](../../permissions.html#project-members-permissions)的项目成员可见. 但是,来宾用户也可以创建机密问题,但只能查看他们自己创建的问题. + +对于非特权用户,机密问题也隐藏在搜索结果中. 例如,这是具有"维护者"和"访客"访问权限的用户分别在项目的搜索结果中看到的内容. + +| 维护者访问 | 来宾访问 | +| --- | --- | +| [![Confidential issues search master](img/30460bec4b16c49e4f5d5ccc7ac92601.png)](img/confidential_issues_search_master.png) | [![Confidential issues search guest](img/2bb7640bbe66bec0d43070f6f4053758.png)](img/confidential_issues_search_guest.png) | + +## Merge Requests for Confidential Issues[](#merge-requests-for-confidential-issues "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/58583) . + +为了帮助防止机密信息在解决机密问题的过程中从公共项目中泄露,可以通过创建私有派生的合并请求来解决机密问题. + +创建的合并请求将针对私有派生的默认分支,而不是公共上游项目的默认分支. 这样可以防止合并请求,分支和提交进入公共存储库,以及过早地泄露机密信息. 当准备好将机密提交公开时,可以通过打开从私有派生到公共上游项目的合并请求来完成. + +**最佳实践:**如果您在原始上游的同一组或子组中创建了一个长期的私有派生,则具有开发者成员身份的公共项目的所有用户在私有项目中也将具有相同的权限. 这样,所有有权查看机密问题的开发人员都将拥有简化的工作流程来解决这些问题. + +### How it works[](#how-it-works "Permalink") + +关于机密问题," **创建机密合并请求"**按钮可用. 单击它会打开一个下拉列表,您可以在其中选择**创建机密合并请求和分支**或**创建分支** : + +| 创建机密合并请求 | 创建分支 | +| --- | --- | +| [![Create Confidential Merge Request Dropdown](img/17d0ef7b105be8069a4258a758bd25bb.png)](img/confidential_mr_dropdown_v12_1.png) | [![Create Confidential Branch Dropdown](img/4f9a7d54cb4f539c606eaef8fd65b8ed.png)](img/confidential_mr_branch_dropdown_v12_1.png) | + +**项目**下拉列表包括用户所属的私有派生列表,至少是开发人员,并且合并请求已启用. + +每当" **分支名称"**和" **源(分支或标记)"**字段更改时,将检查目标或源分支的可用性. 两个分支都应在所选的私有派生中可用. + +通过单击**创建机密合并请求**按钮,GitLab 将在私有分支中创建分支和合并请求. 当选择**Create branch 时** ,GitLab 将仅创建分支. + +在私有分支中创建分支后,开发人员现在可以将代码推送到该分支以解决机密问题. \ No newline at end of file diff --git a/_book/docs/100.md b/_book/docs/100.md new file mode 100644 index 0000000000000000000000000000000000000000..8f5beb3bb0bcffc6d9767e4c59bc3b1902b4fd0b --- /dev/null +++ b/_book/docs/100.md @@ -0,0 +1,47 @@ +# Due dates + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/due_dates.html](https://docs.gitlab.com/ee/user/project/issues/due_dates.html) + +* [Setting a due date](#setting-a-due-date) +* [Making use of due dates](#making-use-of-due-dates) + +# Due dates[](#due-dates "Permalink") + +在 GitLab 8.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3614) . + +请通读[GitLab 问题文档](index.html)以获取有关 GitLab 问题的概述. + +Due dates can be used in issues to keep track of deadlines and make sure features are shipped on time. Users must have at least [Reporter permissions](../../permissions.html) to be able to edit them, but they can be seen by everybody with permission to view the issue. + +## Setting a due date[](#setting-a-due-date "Permalink") + +创建或编辑问题时,您可以单击**截止日期**字段,然后出现一个日历来帮助您选择所需的日期. 要删除日期,请选择日期文本并将其删除. 该日期与服务器的时区有关,而不与设置到期日期的用户的时区有关. + +[![Create a due date](img/36abd47af07b3b82f814e74be4619b4d.png)](img/due_dates_create.png) + +您还可以通过问题侧边栏设置截止日期. 展开边栏,然后单击" **编辑"**以选择截止日期或删除现有的日期. 更改将立即保存. + +[![Edit a due date via the sidebar](img/2dde5152cc249727c2d1016051d52131.png)](img/due_dates_edit_sidebar.png) + +设置截止日期的最后一种方法是直接在问题的描述或注释中使用[快速操作](../quick_actions.html) : + +* `/due <date>` :设置到期日. 有效的`<date>`示例包括`in 2 days` ( `this Friday`和`December 31st` . +* `/remove_due_date` :删除到期日. + +## Making use of due dates[](#making-use-of-due-dates "Permalink") + +具有到期日期的问题可以在问题跟踪器中轻松查看,并在它们旁边显示一个日期. 日期过期的问题将图标和日期标记为红色. 您可以从右侧的下拉菜单中按`Due soon` `Due later`或`Due later` `Due soon`问题对问题进行排序. + +[![Issues with due dates in the issues index page](img/371d1ca1640afbd824acc19b18bc40c9.png)](img/due_dates_issues_index_page.png) + +截止日期也会出现在您的[待办事项清单中](../../todos.html) . + +[![Issues with due dates in the todos](img/9d0b2e21b9be06d263674db132420176.png)](img/due_dates_todos.png) + +未解决问题的前一天,将向该问题的所有参与者发送电子邮件. 与截止日期一样,"截止日期之前的一天"由服务器的时区确定. + +截止日期的问题也可以导出为 iCalendar 供稿. 提要的 URL 可以添加到日历应用程序中. 通过单击以下页面上的**订阅日历**按钮可以访问该提要: + +* 在**分配的问题**页面上,该页面链接在 GitLab 标头的右侧 +* 在" **项目问题"**页面上 +* 在**组问题**页面上 \ No newline at end of file diff --git a/_book/docs/101.md b/_book/docs/101.md new file mode 100644 index 0000000000000000000000000000000000000000..c5a4dc890570892db49f3fb0e5aa59531d8c4a49 --- /dev/null +++ b/_book/docs/101.md @@ -0,0 +1,446 @@ +# Issue Boards + +> 原文:[https://docs.gitlab.com/ee/user/project/issue_board.html](https://docs.gitlab.com/ee/user/project/issue_board.html) + +* [Overview](#overview) + * [Advanced features of issue boards](#advanced-features-of-issue-boards) +* [How it works](#how-it-works) +* [Use cases](#use-cases) + * [Use cases for a single issue board](#use-cases-for-a-single-issue-board) + * [Use cases for multiple issue boards](#use-cases-for-multiple-issue-boards) + * [Scrum team](#scrum-team) + * [Organization of topics](#organization-of-topics) + * [Advanced team handover](#advanced-team-handover) + * [Quick assignments](#quick-assignments) +* [Issue board terminology](#issue-board-terminology) +* [Permissions](#permissions) +* [GitLab Enterprise features for issue boards](#gitlab-enterprise-features-for-issue-boards) + * [Summary of features per tier](#summary-of-features-per-tier) + * [Multiple issue boards](#multiple-issue-boards) + * [Create an issue board](#create-an-issue-board) + * [Delete an issue board](#delete-an-issue-board) + * [Configurable issue boards](#configurable-issue-boards-starter) + * [Focus mode](#focus-mode) + * [Sum of issue weights](#sum-of-issue-weights-starter) + * [Group issue boards](#group-issue-boards-premium) + * [Assignee lists](#assignee-lists-premium) + * [Milestone lists](#milestone-lists-premium) +* [Work In Progress limits](#work-in-progress-limits-starter) +* [Blocked issues](#blocked-issues) +* [Actions you can take on an issue board](#actions-you-can-take-on-an-issue-board) + * [First time using an issue board](#first-time-using-an-issue-board) + * [Create a new list](#create-a-new-list) + * [Delete a list](#delete-a-list) + * [Add issues to a list](#add-issues-to-a-list) + * [Remove an issue from a list](#remove-an-issue-from-a-list) + * [Filter issues](#filter-issues) + * [Create workflows](#create-workflows) + * [Drag issues between lists](#drag-issues-between-lists) + * [Multi-select issue cards](#multi-select-issue-cards) + * [Issue ordering in a list](#issue-ordering-in-a-list) +* [Tips](#tips) + +# Issue Boards[](#issue-boards "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5554) in [GitLab 8.11](https://about.gitlab.com/releases/2016/08/22/gitlab-8-11-released/#issue-board). + +## Overview[](#overview "Permalink") + +GitLab 发行板是一个软件项目管理工具,用于计划,组织和可视化功能或产品发布的工作流程. 它可以用作[看板](https://en.wikipedia.org/wiki/Kanban_(development))或[Scrum](https://en.wikipedia.org/wiki/Scrum_(software_development))板. + +它结合了问题跟踪和项目管理功能,将所有内容保持在同一位置,因此您无需在不同平台之间切换即可组织工作流程. + +使用问题板,您可以将问题组织在与其分配的标签相对应的列表中,从而在这些列表中可视化设计为卡片的问题. + +您定义流程,GitLab 会为您进行组织. 您添加标签,然后创建相应的列表以提取现有问题. 准备就绪后,可以将发行卡从一个步骤拖放到下一个步骤. + +[![GitLab issue board - Core](img/2a62cf1a17a5306e4d6cd91c30149941.png)](img/issue_boards_core.png) + +观看发布板功能的[视频演示](https://youtu.be/UWsJ8tkHAa8) (在 GitLab 8.11 中引入-2016 年 8 月). + +### Advanced features of issue boards[](#advanced-features-of-issue-boards "Permalink") + +* 每个项目创建多个发行板. +* 每个组创建多个发行板. +* 添加[受让人](#assignee-lists-premium)和[里程碑的](#milestone-lists-premium)列表. + +检查[GitLab Enterprise 的](#gitlab-enterprise-features-for-issue-boards)所有[功能是否有发行板](#gitlab-enterprise-features-for-issue-boards) . + +[![GitLab issue boards - Premium](img/e6522f2cefe000bb17275b2a0451bf82.png)](img/issue_boards_premium.png) + +## How it works[](#how-it-works "Permalink") + +发行板功能通过将 GitLab 现有的[发行跟踪功能](issues/index.html#issues-list)和[标签](labels.html)用作 Scrum 板的列表而建立. + +使用问题板,您可以对问题有不同的看法,同时保持在问题跟踪器中看到的相同过滤和排序功能. 发行板基于其项目的标签结构,因此它使用相同的描述性标签来指示在板上的位置,从而在整个开发生命周期中保持一致性. + +问题板向您显示团队正在处理的问题,分配给每个人的问题以及这些问题在工作流中的位置. + +您可以从一个平台创建问题,托管代码,执行审阅,构建,测试和部署. 问题板可帮助您在 GitLab 中可视化和管理整个过程. + +有了[多个发行板](#use-cases-for-multiple-issue-boards) ,您可以走得更远,因为您不仅可以从更广阔的角度组织自己和您的项目,每个项目使用一个发行板,还可以让您的团队成员通过在多个发行板中创建多个发行板来组织自己的工作流程.同一项目. + +## Use cases[](#use-cases "Permalink") + +有多种方法可以使用针对自己喜欢的工作流程量身定制的 GitLab 发行板. 这是发行板的一些常见用例. + +### Use cases for a single issue board[](#use-cases-for-a-single-issue-board "Permalink") + +借助 GitLab 工作流程,您可以讨论问题中的提案,使用标签对其进行分类,然后在其中使用问题委员会进行组织并确定优先级. + +例如,让我们考虑以下简化的开发工作流程: + +1. 您有一个托管应用程序代码库的存储库,而您的团队则在积极贡献代码. +2. 您的**后端**团队将开始新的实施工作,收集反馈和批准,并将其传递给**前端**团队. +3. 前端完成后,新功能将部署到要测试的**登台**环境中. +4. 成功后,它将部署到**生产中** . + +如果您具有标签" **后端** "," **前端** "," **暂存** "和" **生产** ",以及带有每个列表的发行板,则可以: + +* 可视化从开发生命周期开始到部署到生产的整个实现流程. +* 通过垂直移动优先顺序排列列表中的问题. +* 在列表之间移动问题,以根据您设置的标签进行整理. +* 通过选择一个或多个现有问题,将多个问题添加到板中的列表中. + +[![issue card moving](img/a1f2874d536bbec36fba8132d424e066.png)](img/issue_board_move_issue_card_list.png) + +### Use cases for multiple issue boards[](#use-cases-for-multiple-issue-boards "Permalink") + +借助[多个发行委员会](#multiple-issue-boards) ,每个团队可以拥有自己的董事会来单独组织其工作流程. + +#### Scrum team[](#scrum-team "Permalink") + +具有多个发行董事会,每个团队只有一个董事会. 现在,您可以在流程的每个部分中解决问题. 例如: **To Do** , **Doing**和**Done** . + +#### Organization of topics[](#organization-of-topics "Permalink") + +创建列表以按主题对问题进行排序,并快速在主题或组之间(例如**UX** , **Frontend**和**Backend**之间)进行更改. 更改反映在各个方面,因为更改列表会相应更新每个问题的标签. + +#### Advanced team handover[](#advanced-team-handover "Permalink") + +例如,假设我们有一个 UX 小组,其问题板包含: + +* **去做** +* **Doing** +* **Frontend** + +完成操作后,他们将卡移至**Frontend** . 前端团队的董事会看起来像: + +* **Frontend** +* **Doing** +* **Done** + +由 UX 团队**整理的**卡片准备就绪后,会自动显示在" **前端"**列中. + +**注意:**有关更广泛的用例,请参阅博客文章[GitLab 工作流程,概述](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/#gitlab-workflow-use-case-scenario) . 对于一个真实的用例示例,您可以了解为什么[Codepen 决定采用发行版](https://about.gitlab.com/blog/2017/01/27/codepen-welcome-to-gitlab/#project-management-everything-in-one-place)来改善多个[发行版](https://about.gitlab.com/blog/2017/01/27/codepen-welcome-to-gitlab/#project-management-everything-in-one-place)的工作流程. + +#### Quick assignments[](#quick-assignments "Permalink") + +为每个团队成员创建列表,然后将问题快速拖放到每个团队成员的列表中. + +## Issue board terminology[](#issue-board-terminology "Permalink") + +**发行板**代表您的**发行**的独特视图. 它可以有多个列表,每个列表由卡代表的问题组成. + +**列表**是问题板上的一列,显示与某些属性匹配的问题. 除了默认的"打开"和"关闭"列表外,每个其他列表还显示与您选择的标签,受让人或里程碑匹配的问题. 在每个列表的顶部,您可以看到属于该问题的数量. 列表类型包括: + +* **开** (默认):不属于其他列表中的一个所有打开的问题. 始终显示为最左边的列表. +* **已关闭** (默认):所有已关闭的问题. 始终显示为最右边的列表. +* **标签列表** : **标签的**所有未解决问题. +* [**受让人列表**](#assignee-lists-premium) :分配给用户的所有未解决的问题. +* [**里程碑列表**](#milestone-lists-premium) : [**里程碑的**](#milestone-lists-premium)所有未解决的问题. + +**卡**是列表中的一个框,它代表一个问题. 您可以将卡片从一个列表拖动到另一个列表,以更改其标签,受让人或里程碑. 卡上显示的信息包括: + +* 发行标题 +* 相关标签 +* 发行数量 +* Assignee + +## Permissions[](#permissions "Permalink") + +具有[报告者和更高角色的](../permissions.html)用户可以使用发布板功能的所有功能来创建或删除列表,并将问题从一个列表拖动到另一个列表. + +## GitLab Enterprise features for issue boards[](#gitlab-enterprise-features-for-issue-boards "Permalink") + +GitLab 核心和 GitLab.com 免费层上均提供 GitLab 发行板,但某些高级功能仅在[更高层中提供](https://about.gitlab.com/pricing/) . + +### Summary of features per tier[](#summary-of-features-per-tier "Permalink") + +下表列出了在不同的[GitLab 层](https://about.gitlab.com/pricing/)中可用的不同发行板功能: + +| Tier | 项目发行委员会的数量 | Number of Group issue boards | 可配置的发行板 | 受让人名单 | +| --- | --- | --- | --- | --- | +| 核心/免费 | Multiple | 1 | No | No | +| 入门/青铜 | Multiple | 1 | Yes | No | +| 高级/白银 | Multiple | Multiple | Yes | Yes | +| 终极/金 | Multiple | Multiple | Yes | Yes | + +### Multiple issue boards[](#multiple-issue-boards "Permalink") + +版本历史 + +* 在 GitLab 8.13 中[引入](https://about.gitlab.com/releases/2016/10/22/gitlab-8-13-released/) . +* 每个项目有多个发行板[移至](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53811) GitLab 12.1 中的[GitLab Core](https://about.gitlab.com/pricing/) . +* 每套[GitLab Premium 中](https://about.gitlab.com/pricing/)都有多个发行板. + +多个发行板允许给定项目或组使用多个发行板. 对于具有多个团队的大型项目,或者在使用存储库托管多个产品代码的情况下,这非常有用. + +使用菜单顶部的搜索框,您可以过滤列出的板. + +当您有十个或更多的板可用时,菜单中还会显示" **最近"**部分,其中包含最后四个被访问板的快捷方式. + +[![Multiple issue boards](img/dbb80511727781129d638c6d3413a45f.png)](img/issue_boards_multiple.png) + +当您在具有多个板的项目或组中重新访问问题板时,GitLab 会自动加载您上次访问的板. + +#### Create an issue board[](#create-an-issue-board "Permalink") + +要创建新的发行板: + +1. 单击"发行板"页面左上角的具有当前板名称的下拉菜单. +2. Click **创建新板**. +3. 输入新板的名称并选择其范围:里程碑,标签,受让人或权重. + +#### Delete an issue board[](#delete-an-issue-board "Permalink") + +要删除当前活动的发行板: + +1. 单击"发行板"页面左上角的具有当前板名称的下拉菜单. +2. Click **删除板**. +3. 单击**删除**进行确认. + +### Configurable issue boards[](#configurable-issue-boards-starter "Permalink") + +[Introduced](https://about.gitlab.com/releases/2017/11/22/gitlab-10-2-released/#issue-boards-configuration) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2. + +发行板可以与 GitLab [里程碑](milestones/index.html#milestones) , [标签](labels.html) ,受让人和权重关联,它们会根据这些字段自动过滤发行板问题. 这使您可以根据团队的需要创建独特的董事会. + +[![Create scoped board](img/bba7007707d548d73c9b6f0efad3c50b.png)](img/issue_board_creation.png) + +您可以在创建木板时或单击"编辑木板"按钮来定义木板的范围. 将里程碑,受让人或权重分配给发行板后,您将不再能够在搜索栏中进行筛选. 为此,您需要从发行板上删除所需的范围(例如,里程碑,受让人或权重). + +[![Edit board configuration](img/0d59f9135c1fed79a51921909516ef69.png)](img/issue_board_edit_button.png) + +如果您在木板中没有编辑权限,则仍然可以通过点击**查看范围**来**查看**配置. + +[![Viewing board configuration](img/c01efbb34a741e385a7089a6799e9b59.png)](img/issue_board_view_scope.png) + +### Focus mode[](#focus-mode "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 9.1 中[引入]((https://about.gitlab.com/releases/2017/04/22/gitlab-9-1-released/#issue-boards-focus-mode-ees-eep)) . +* [移动](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28597)到 GitLab.com 的自由层在 12.10\. +* 在 13.0 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/212331) GitLab Core. + +单击右上角的按钮可打开和关闭聚焦模式. 在焦点模式下,导航 UI 处于隐藏状态,使您可以集中精力处理板上的问题. + +[![Board focus mode](img/0fdd144a1493e4d21226f1b04a5d336a.png)](img/issue_board_focus_mode.gif) + +* * * + +### Sum of issue weights[](#sum-of-issue-weights-starter "Permalink") + +每个列表的顶部指示属于该列表的问题的问题权重之和. 当使用板进行容量分配时,尤其是与[受让人列表](#assignee-lists-premium)结合使用时,这很有用. + +[![issue board summed weights](img/38c073cc1c78dc88bf317e878e9995cc.png)](img/issue_board_summed_weights.png) + +### Group issue boards[](#group-issue-boards-premium "Permalink") + +[Introduced](https://about.gitlab.com/releases/2017/09/22/gitlab-10-0-released/#group-issue-boards) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.0. + +可以在组导航级别上访问,组问题委员会提供与项目级委员会相同的功能,但是它可以显示该组及其子孙组中所有项目的问题. 同样,您只能按组标签过滤这些板. 通过边栏更新机制更新问题的里程碑和标签时,再次只有组级对象可用. + +**注意:** [GitLab Premium](https://about.gitlab.com/pricing/) 10.0 最初[引入](https://about.gitlab.com/releases/2017/09/22/gitlab-10-0-released/#group-issue-boards)了多个组发行板,而 GitLab Core 10.6 提供了每个组一个组发行板. + +[![Group issue board](img/ce119917ec56b195b909d4371bb994aa.png)](img/group_issue_board.png) + +### Assignee lists[](#assignee-lists-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5784) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.0. + +就像在常规列表中显示带有选定标签的所有问题一样,您可以添加一个受让人列表,该列表显示分配给用户的所有问题. 您可以拥有一个包含标签列表和受让人列表的木板. 添加受让人列表: + +1. Click **新增清单**. +2. 选择" **受理人列表"**选项卡. +3. 搜索并单击要添加为受让人的用户. + +现在已添加了受让人列表,您可以通过[将问题拖到](#drag-issues-between-lists)受让人列表中或从受让人列表中[拖动问题](#drag-issues-between-lists)来向该用户分配或取消分配问题. 要删除受让人列表(与标签列表一样),请单击垃圾桶图标. + +[![Assignee lists](img/baa29e50412ef4acd25e287681ad9e9e.png)](img/issue_board_assignee_lists.png) + +### Milestone lists[](#milestone-lists-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6469) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2. + +You’re also able to create lists of a milestone. These are lists that filter issues by the assigned milestone, giving you more freedom and visibility on the issue board. To add a milestone list: + +1. Click **新增清单**. +2. 选择" **里程碑"**选项卡. +3. 搜索并单击里程碑. + +与受让人列表类似,您现在可以[将问题拖到](#drag-issues-between-lists)里程碑列表中或从里程碑列表中[拖动](#drag-issues-between-lists)出来,以操纵所拖动问题的里程碑. 与其他列表类型一样,单击垃圾桶图标以删除列表. + +[![Milestone lists](img/6261dd255633edf09ab3d7245ccaf2c1.png)](img/issue_board_milestone_lists.png) + +## Work In Progress limits[](#work-in-progress-limits-starter "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/11403) + +您可以为每个问题列表设置进行中(WIP)限制. 设置限制后,列表的标题将显示列表中的问题数和问题的软限制. + +Examples: + +* 您有一个包含四个问题的列表,限制为五个,标题将显示**4/5** . 如果超出限制,则当前的问题数将显示为红色. +* 您有一个包含五个问题的列表,限制为五个. 当您将另一个问题移到该列表时,列表的标题显示**6/5** ,其中六个显示为红色. + +设置列表的在制品限制: + +1. 导航到您所属的项目或小组委员会. +2. 点击设置图标( )放在列表​​标题中. +3. 在"进行中的**工作限制"**旁边,单击" **编辑"** . +4. 输入最大问题数. +5. 按`Enter`保存. + +## Blocked issues[](#blocked-issues "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34723) . + +如果一个问题被另一个问题阻止,则其标题旁边会出现一个图标,指示其阻止状态. + +[![Blocked issues](img/b1edf28a1aa5c59ffa779a574c4fc548.png)](img/issue_boards_blocked_icon_v12_8.png) + +## Actions you can take on an issue board[](#actions-you-can-take-on-an-issue-board "Permalink") + +* [Create a new list](#create-a-new-list). +* [Delete an existing list](#delete-a-list). +* [Add issues to a list](#add-issues-to-a-list). +* [Remove an issue from a list](#remove-an-issue-from-a-list). +* [筛选](#filter-issues)出现在问题板上的问题. +* [Create workflows](#create-workflows). +* [Drag issues between lists](#drag-issues-between-lists). +* [Multi-select issue cards](#multi-select-issue-cards). +* [Re-order issues in lists](#issue-ordering-in-a-list). +* 拖动列表并重新排序. +* 更改问题标签(通过在列表之间拖动问题). +* 解决问题(将其拖动到" **完成"**列表中). + +如果您无法执行上述某些操作,请确保您具有正确的[权限](#permissions) . + +### First time using an issue board[](#first-time-using-an-issue-board "Permalink") + +第一次打开问题面板时,会显示默认列表(" **打开"**和" **关闭"** )以及欢迎消息,其中提供了两个选项. 您可以: + +* 创建一组预定义的标签(默认情况下: **To Do**和**Doing** ),并在发行板上创建其对应的列表. +* 退出并使用自己的列表. + +[![issue board welcome message](img/768ab05f8c35931c200b6da1f8d92352.png)](img/issue_board_welcome_message.png) + +如果选择使用并创建预定义列表,则它们将显示为空,因为与它们关联的标签要到那时才存在,这意味着系统无法自动填充它们. 当然,如果预定义标签还不存在. 如果确实存在,则会创建该列表,并填充具有该标签的问题. + +### Create a new list[](#create-a-new-list "Permalink") + +通过单击发行板右上角的" **添加列表"**按钮来创建新列表. + +[![issue board welcome message](img/604dc2f6326d049dca30995958a84ad2.png)](img/issue_board_add_list.png) + +然后,选择标签或用户以从中创建列表. 新列表将被插入列表的末尾,在**完成**之前. 移动和重新排序列表就像拖动列表一样简单. + +要为尚不存在的标签创建列表,请选择**创建新标签**来**创建标签** . 这将立即创建标签并将其添加到下拉列表中. 现在,您可以选择它来创建列表. + +### Delete a list[](#delete-a-list "Permalink") + +要从发布板上删除列表,请使用列表标题中的小垃圾桶图标. 将出现一个确认对话框供您确认. + +删除列表对问题和标签没有任何影响,只是删除了列表视图. 如果需要,您随时可以将其添加回去. + +### Add issues to a list[](#add-issues-to-a-list "Permalink") + +您可以通过单击**问题**面板右上角的" **添加问题"**按钮将问题添加到列表中. 这将打开一个模式窗口,您可以在其中查看不属于任何列表的所有问题. + +通过单击卡片选择一个或多个问题,然后单击" **添加问题"**以将其添加到所选列表中. 您可以通过按作者,受让人,里程碑和标签筛选来限制要添加到列表中的问题. + +[![Bulk adding issues to lists](img/1d54aa31264e3f3b98ebf2049669f910.png)](img/issue_boards_add_issues_modal.png) + +### Remove an issue from a list[](#remove-an-issue-from-a-list "Permalink") + +从列表中删除问题可以通过单击问题卡,然后单击侧边栏中的**从**面板中**删除**按钮来完成. 相应的标签被删除. + +[![Remove issue from list](img/529405d6cc5cbeb813be69b57b0e45b1.png)](img/issue_boards_remove_issue.png) + +### Filter issues[](#filter-issues "Permalink") + +You should be able to use the filters on top of your issue board to show only the results you want. This is similar to the filtering used in the issue tracker since the metadata from the issues and labels are re-used in the issue board. + +您可以按作者,受让人,里程碑和标签过滤. + +### Create workflows[](#create-workflows "Permalink") + +通过对列表重新排序,可以创建工作流程. 由于发行版中的列表基于标签,因此可以与您现有的发行版一起使用. 因此,如果您已经用"后端"和"前端"标记了事物,则问题在创建它们时会出现在列表中. 此外,这意味着您可以通过更改标签轻松地在列表之间移动某些内容. + +使用发行板的典型工作流程为: + +1. 您已经[创建了](labels.html#label-management)标签并对其进行了[优先排序,](labels.html#label-priority)以便可以轻松地对问题进行分类. +2. 您遇到很多问题(理想情况下是带有标签的). +3. 您访问发行板并开始[创建列表](#create-a-new-list)以创建工作流程. +4. 您可以在列表中四处移动问题,以便您的团队知道谁应该处理什么问题. +5. 当一个团队的工作完成时,可以将问题拖到下一个列表中,以便其他人来接听. +6. 最终解决问题后,该问题将移至" **完成"**列表并自动关闭. + +例如,您可以基于"前端"标签和"后端"标签创建一个列表. 设计师可以通过将问题添加到"前端"列表来开始处理问题. 这样,每个人都知道设计师现在正在研究此问题. 然后,一旦完成,所有要做的就是将其拖到下一个列表"后端",后端开发人员最终可以在该列表中进行选择. 完成后,将其移至**完成** ,以解决问题. + +访问问题时可以清楚地看到此过程,因为每次移动到另一个列表时,标签都会更改,并且不会记录系统. + +[![issue board system notes](img/1be5fea51b824b103e9b5bac12136a90.png)](img/issue_board_system_notes.png) + +### Drag issues between lists[](#drag-issues-between-lists "Permalink") + +在列表之间拖动问题时,根据源列表和目标列表,会发生不同的行为. + +|   | 打开 | 要关闭 | 标记`B`列表 | 分配受让人`Bob`清单 | +| --- | --- | --- | --- | --- | +| 从开放 | - | 问题已结案 | `B` added | `Bob` assigned | +| 从关闭 | 问题重新开放 | - | 问题重新开放 +`B`添加 | 问题重新开放 +`Bob`分配 | +| 从标签`A`列表 | `A` removed | 问题已结案 | `A` removed +`B` added | `Bob` assigned | +| 从受让人`Alice`名单 | `Alice` unassigned | 问题已结案 | `B` added | `Alice` unassigned +`Bob` assigned | + +### Multi-select issue cards[](#multi-select-issue-cards "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/18954) . + +您可以选择多个发行卡,然后将组拖动到列表中的另一个位置或另一个列表中. 这样可以更快地一次重新排序许多问题. + +要选择并移动多张卡片: + +1. 使用`Ctrl`选择每个卡+ `Click`在 Windows 或 Linux,或者`Cmd 的` + `Click`在 MacOS. +2. 将所选卡中的一张拖到另一个位置或列表,所有所选卡都将移动. + +[![Multi-select Issue Cards](img/09b8263a3534de004ff180005a876b4a.png)](img/issue_boards_multi_select_v12_4.png) + +### Issue ordering in a list[](#issue-ordering-in-a-list "Permalink") + +访问董事会时,问题在任何列表中都显示为有序. 您可以通过拖放问题来更改顺序. 更改后的订单将保存到系统中,以便以后访问同一板的任何人都可以看到重新排序,但有一些例外. + +给定问题首次出现在任何面板中(即,用户首次加载包含该问题的面板)时,将根据[优先级顺序](labels.html#label-priority)对该列表中的其他问题进行[排序](labels.html#label-priority) . + +此时,系统会为该问题分配一个相对顺序值,该值代表其相对于列表中其他问题的相对顺序. 每当您拖放该问题的重新排序时,其相对订单值都会相应更改. + +同样,当问题由用户加载时,在任何板上出现的任何时间,都会使用更新的相对订单值进行订购. (这是第一次出现从上述优先顺序中提取问题的问题.)这意味着,如果您的 GitLab 实例内给定板上的任何用户将问题`A`拖放到问题`B`上方的顺序进行了重新排序,每当随后将这两个问题加载到同一实例中的任何板(例如,可以是不同的项目板或不同的组板)中时,都将维持订购. + +此顺序还会影响[问题列表](issues/sorting_issue_lists.html) . 在发行板上更改订单会更改发行列表中的顺序,反之亦然. + +## Tips[](#tips "Permalink") + +需要记住的几件事: + +* 在列表之间移动问题会从其来源列表中删除标签,并从其去往列表中添加标签. +* 如果一个问题有多个标签,则它可以存在于多个列表中. +* 如果标记了问题,则会自动用问题填充列表. +* 单击卡片内的问题标题,将您转到该问题. +* 单击卡内的标签可快速筛选整个问题板,并仅显示所有带有该标签的列表中的问题. +* 出于性能和可见性的原因,每个列表默认显示前 20 个问题. 如果问题超过 20 个,请开始向下滚动,然后出现下 20 个问题. \ No newline at end of file diff --git a/_book/docs/102.md b/_book/docs/102.md new file mode 100644 index 0000000000000000000000000000000000000000..97ae102bcb7effb09ce0adb8cb3ea1b6ca0bf952 --- /dev/null +++ b/_book/docs/102.md @@ -0,0 +1,266 @@ +# Issue Data and Actions + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/issue_data_and_actions.html](https://docs.gitlab.com/ee/user/project/issues/issue_data_and_actions.html) + +* [Parts of an Issue](#parts-of-an-issue) + * [New Issue, close issue (reopen issue, report issue)](#new-issue-close-issue-reopen-issue-report-issue) + * [To Do](#to-do) + * [Assignee](#assignee) + * [Multiple Assignees](#multiple-assignees-starter) + * [Epic](#epic-premium) + * [Milestone](#milestone) + * [Time tracking](#time-tracking) + * [Due date](#due-date) + * [Labels](#labels) + * [Weight](#weight-starter) + * [Confidentiality](#confidentiality) + * [Lock issue](#lock-issue) + * [Participants](#participants) + * [Notifications](#notifications) + * [Reference](#reference) + * [Edit](#edit) + * [Description](#description) + * [Mentions](#mentions) + * [Related Issues](#related-issues-starter) + * [Related Merge Requests](#related-merge-requests) + * [Award emoji](#award-emoji) + * [Show all activity](#show-all-activity) + * [Create Merge Request](#create-merge-request) + * [Issue history](#issue-history) + * [Activity sort order](#activity-sort-order) + * [Comments](#comments) + * [Submit comment, start a thread, or comment and close](#submit-comment-start-a-thread-or-comment-and-close) + * [Zoom meetings](#zoom-meetings) + * [Publish an issue](#publish-an-issue-ultimate) + +# Issue Data and Actions[](#issue-data-and-actions "Permalink") + +请通读[GitLab 问题文档](index.html)以获取有关 GitLab 问题的概述. + +## Parts of an Issue[](#parts-of-an-issue "Permalink") + +下图说明了问题的外观. 请注意,根据使用的 GitLab 版本和查看问题的用户权限,某些部分看起来可能会略有不同或不存在. + +您可以在一个屏幕上找到该问题的所有信息. + +[![Issue view](img/b6662e0dd306cb7949bbfd70db9b384c.png)](img/issues_main_view_numbered.png) + +* **1.** [New Issue, close issue (reopen issue, report issue)](#new-issue-close-issue-reopen-issue-report-issue) +* **2.** [To Do](#to-do) +* **3.** [Assignee](#assignee) + * **3.1.** [Multiple Assignees](#multiple-assignees-starter) +* **4.** [Epic](#epic-premium) +* **5.** [Milestone](#milestone) +* **6.** [Time tracking](#time-tracking) +* **7.** [Due date](#due-date) +* **8.** [Labels](#labels) +* **9.** [Weight](#weight-starter) +* **10.** [Confidentiality](#confidentiality) +* **11.** [Lock issue](#lock-issue) +* **12.** [Participants](#participants) +* **13.** [Notifications](#notifications) +* **14.** [Reference](#reference) +* **15.** [Edit](#edit) +* **16.** [Description](#description) +* **17.** [Mentions](#mentions) +* **18.** [Related Issues](#related-issues-starter) +* **19.** [Related Merge Requests](#related-merge-requests) +* **20.** [Award emoji](#award-emoji) +* **21.** [Show all activity](#show-all-activity) +* **22.** [Create Merge Request](#create-merge-request) +* **23.** [Issue history](#issue-history) + * [Activity sort order](#activity-sort-order) +* **24.** [Comments](#comments) +* **25.** [Submit comment, start a thread, or comment and close](#submit-comment-start-a-thread-or-comment-and-close) +* **26.** [Zoom meetings](#zoom-meetings) + +问题从状态(打开或关闭)开始,然后是作者,并包括许多其他功能,在上图中编号,以逐一解释其含义. + +当问题由其他用户更改时,问题屏幕的许多元素都会自动刷新,例如标题和说明. 注释和系统注释也会根据各种操作和内容更新自动更新. + +### New Issue, close issue (reopen issue, report issue)[](#new-issue-close-issue-reopen-issue-report-issue "Permalink") + +单击" **新问题"**将打开一个新窗口,以在同一项目中创建一个新问题. 单击**关闭问题**将关闭此问题,但不会被删除. 如果问题已经关闭,您仍然可以访问它,并且按钮将显示**Reopen issue** ,如下所示,您可以单击以重新打开问题. 重新开放的问题与其他任何问题都没有不同. + +[![Reopen Issue](img/136df5416c67f2d80606b4849658e289.png)](img/reopen-issue.png) + +如果您无权修改问题,则" **关闭问题"**按钮将替换为" **报告问题"** ,您可以单击该按钮以[提交](../../abuse_reports.html)有关该问题[的滥用情况报告](../../abuse_reports.html) . 如果您有权修改问题,但仅在关闭问题后,它也会显示. + +[![Report Abuse](img/16f0d7c3d19700b0e30aa6c1528acb91.png)](img/report-abuse.png) + +### To Do[](#to-do "Permalink") + +您可以在[GitLab 任务列表中](../../todos.html)添加问题或从中删除问题. + +执行此操作的按钮具有不同的标签,具体取决于问题是否已在"任务列表"中. 如果问题是: + +* 已在您的待办事项清单上:该按钮标有" **标记为已完成"** . 单击按钮以从您的任务列表中删除该问题. +* 不在您的待办事项清单上:该按钮标有**添加待办事项** . 单击按钮将问题添加到您的"任务列表"中. + +### Assignee[](#assignee "Permalink") + +可以将问题分配给: + +* Yourself. +* 另一个人. +* [Many people](#multiple-assignees-starter). + +可以根据需要频繁更改受让人. 想法是,受让人应对该问题负责,直到将其重新分配给其他人以解决该问题为止. 分配给某人后,它将显示在其分配的问题列表中. + +**提示:**如果用户不是该项目的成员,则只有他们自己创建问题后才能将其分配给他们. + +#### Multiple Assignees[](#multiple-assignees-starter "Permalink") + +通常,多个人会共同处理同一问题,而在拥有问题共享所有权的大型团队中,跟踪这些问题尤其困难. + +在[GitLab Starter 中](https://about.gitlab.com/pricing/) ,您可以[将多个人分配](multiple_assignees_for_issues.html)给一个问题. + +### Epic[](#epic-premium "Permalink") + +您可以将问题分配给[Epic](../../group/epics/index.html) ,从而可以更好地管理相关问题组. + +### Milestone[](#milestone "Permalink") + +选择一个[里程碑](../milestones/index.html) ,将问题归因于此. + +### Time tracking[](#time-tracking "Permalink") + +使用[GitLab 快速行动](../quick_actions.html)来[跟踪估计和花费在问题上的时间](../time_tracking.html) . 您可以添加解决问题[所需时间](../time_tracking.html#estimates)的[估计,](../time_tracking.html#estimates)还可以添加解决问题[所花费的时间](../time_tracking.html#time-spent) . + +### Due date[](#due-date "Permalink") + +当您的工作时间很紧时,重要的是要有一种方法来为实现和解决问题设置截止日期. 这可以在[截止日期](due_dates.html)元素中完成. 截止日期可以根据需要进行多次更改. + +### Labels[](#labels "Permalink") + +通过给它们加上[标签](../labels.html)来对问题进行分类. 它们有助于组织工作流程,并使您能够与[GitLab 发行委员会合作](index.html#issue-boards) . + +还可以为组标签分配问题,该组标签允许您对同一组内的所有项目使用相同的标签. 它们的工作原理完全相同,但可立即用于该组中的所有项目. + +**提示:**如果标签尚不存在,可以单击**编辑** ,它会打开一个下拉菜单,从中可以选择**创建新标签** . + +### Weight[](#weight-starter "Permalink") + +为问题[分配权重](issue_weight.html) . 使用较大的值表示完成此问题需要付出更多的努力. 仅允许正值或零. + +### Confidentiality[](#confidentiality "Permalink") + +您可以[将问题设置为机密](confidential_issues.html) . 设置后,未经授权的用户将无法访问该问题,也不会在项目问题委员会或问题列表中看到该问题. + +### Lock issue[](#lock-issue "Permalink") + +您可以[锁定问题中的线程](../../discussions/index.html#lock-discussions) ,以防止添加更多评论. + +### Participants[](#participants "Permalink") + +涉及该问题的所有用户. 他们要么参与了该[线程](../../discussions/index.html) ,要么在描述或线程中被提及. + +### Notifications[](#notifications "Permalink") + +单击该图标以启用/禁用该问题的[通知](../../profile/notifications.html#issue--epics--merge-request-events) . 如果您以任何方式参与该问题,它将自动启用. + +* **Enable**: If you are not a participant in the discussion on that issue, but want to receive notifications on each update, subscribe to it. +* **禁用** :如果您正在接收有关该问题的更新通知,但不再希望接收它们,请取消订阅. + +### Reference[](#reference "Permalink") + +* 快速"复制"按钮,这个问题的参考,它看起来像`foo/bar#xxx` ,其中`foo`是`username`或`groupname` , `bar`是`project-name` ,并且`xxx`是发行数量. + +### Edit[](#edit "Permalink") + +单击此图标可打开要编辑的问题,您将有权访问与创建问题时相同的所有字段. 如果用户没有编辑问题的权限,则不会显示此图标. + +### Description[](#description "Permalink") + +纯文本标题和问题描述位于问题页面的顶部中心. 该描述完全支持[GitLab 风味 Markdown](../../markdown.html#gitlab-flavored-markdown-gfm) ,允许许多格式选项. + +> [自 GitLab 12.6 起](https://gitlab.com/gitlab-org/gitlab/-/issues/10103) , [问题历史记录](#issue-history)中列出了对[问题](#issue-history)描述的更改. + +### Mentions[](#mentions "Permalink") + +您可以使用`@username`或`@groupname`提及您的 GitLab 实例中存在的用户或组,除非他们在配置文件设置中禁用了所有通知,否则它们将通过待办事项和电子邮件得到通知. 这是在[通知设置中](../../profile/notifications.html)控制的. + +自己的提及(当前登录的用户)将以不同的颜色突出显示,使您可以轻松查看涉及到的评论,帮助您快速关注它们. + +**提示:**避免在问题中提及`@all`并合并请求,因为它会向该项目组的所有成员发送电子邮件通知,这可以解释为垃圾邮件. + +### Related Issues[](#related-issues-starter "Permalink") + +这里列出了被称为[相关问题的问题](related_issues.html) . 您也可以单击`+`添加更多相关问题. + +### Related Merge Requests[](#related-merge-requests "Permalink") + +该问题的描述或问题线程中提到的[合并请求](crosslinking_issues.html#from-merge-requests)在此处列为[相关合并请求](crosslinking_issues.html#from-merge-requests) . 另外,如果当前问题在另一个合并请求中被提及是相关的,则该合并请求将在此处列出. + +### Award emoji[](#award-emoji "Permalink") + +您可以为该问题授予表情符号. 有" thumbs_up"和" thumbs_down"的快捷方式,或者您可以单击浅灰色的" face"从可用的[GitLab 风味 Markdown Emoji](../../markdown.html#emoji)下拉列表中选择其他反应. + +**提示:在主题中**张贴" +1"作为评论会对该问题的所有订阅参与者造成垃圾邮件,会使主题混乱,因此不建议这样做. 授予表情符号是一种让他们知道您的反应而不会向其发送垃圾邮件的方法. + +### Show all activity[](#show-all-activity "Permalink") + +您可以通过单击**显示所有活动**并选择以下任一内容来过滤问题历史记录中**显示的内容** : + +* **仅显示评论** ,仅显示主题并隐藏问题的更新. +* **仅显示历史记录** ,它隐藏线程并且仅显示更新. + +Also: + +* 您可以使用`@username`或`@groupname`提及您的 GitLab 实例中存在的用户或组,除非他们已[禁用](#notifications)其配置文件设置中的[所有通知](#notifications) ,否则它们将通过待办事项和电子邮件得到[通知](#notifications) . +* 自己的提及(当前登录的用户)将以不同的颜色突出显示,使您可以轻松查看涉及到的评论,帮助您快速关注它们. + +[![Show all activity](img/6a23362ee367dd144c2c8ea315b8dde0.png)](img/show-all-activity.png) + +### Create Merge Request[](#create-merge-request "Permalink") + +在一个动作中创建一个新的分支和[**草稿**合并请求](../merge_requests/work_in_progress_merge_requests.html) . 默认情况下,该分支将被命名为`issuenumber-title` ,但是您可以选择任何名称,并且 GitLab 会验证该分支尚未被使用. 合并请求将自动继承问题的里程碑和标签,并设置为在合并时关闭问题. + +[![Create MR from issue](img/2a301148b56e04c50113445dc7280c15.png)](img/create_mr_from_issue.png) + +(可选)您可以选择仅创建一个[新分支](../repository/web_editor.html#create-a-new-branch-from-an-issue) ,以该问题命名. + +### Issue history[](#issue-history "Permalink") + +All comments and updates to the issue are tracked and listed here, but this can be filtered, as shown above. + +#### Activity sort order[](#activity-sort-order "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/14588) . + +您可以颠倒默认顺序,并与按顶部的最新项目排序的活动供稿进行交互. 您的首选项通过本地存储保存,并自动应用于您查看的每个问题. + +要更改活动排序顺序,请单击**最旧的第一个**下拉菜单,然后选择最旧或最新的项目以首先显示. + +[![Issue activity sort order dropdown button](img/db92110fba2588fed57b9af6bb2a381c.png)](img/issue_activity_sort_order_v12_10.png) + +### Comments[](#comments "Permalink") + +通过在其主题中发布评论来协作解决问题. 该文本字段还完全支持[GitLab 风味 Markdown](../../markdown.html#gitlab-flavored-markdown-gfm) . + +### Submit comment, start a thread, or comment and close[](#submit-comment-start-a-thread-or-comment-and-close "Permalink") + +撰写评论后,您可以: + +* 单击**评论** ,您的评论将被发布. +* 选择从下拉列表中**启动线程** ,并启动一个新[的线程](../../discussions/index.html#threaded-discussions)这个问题的主线程中讨论具体的点. 这邀请其他参与者直接回复您的主题,并将相关评论分组在一起. + +[![Comment or thread](img/9cb5bb737c82aad68bc28e2a7357e05c.png)](img/comment-or-discussion.png) + +您也可以从此处关闭问题,因此无需滚动到问题页面的顶部. + +### Zoom meetings[](#zoom-meetings "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31103) . + +您可以使用`/zoom`和`/remove_zoom` [快速动作](../quick_actions.html)将[GitLab](../../markdown.html#gitlab-flavored-markdown-gfm) `/remove_zoom` [Markdown](../../markdown.html#gitlab-flavored-markdown-gfm)作为附件添加和删除 Zoom 会议. + +附加问题的[Zoom](https://zoom.us)呼叫会导致问题顶部顶部标题下方的" **加入 Zoom"会议**按钮. + +详细了解如何[添加或删除缩放会议](associate_zoom_meeting.html) . + +### Publish an issue[](#publish-an-issue-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30906) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1. + +If a status page application is associated with the project, you can use the `/publish` [quick action](../quick_actions.html) to publish the issue. Refer to [GitLab Status Page](../status_page/index.html) for more information. \ No newline at end of file diff --git a/_book/docs/103.md b/_book/docs/103.md new file mode 100644 index 0000000000000000000000000000000000000000..dfe90d9a1a796ed97dfce63f0e05f6cc2cc75f60 --- /dev/null +++ b/_book/docs/103.md @@ -0,0 +1,209 @@ +# Labels + +> 原文:[https://docs.gitlab.com/ee/user/project/labels.html](https://docs.gitlab.com/ee/user/project/labels.html) + +* [Overview](#overview) +* [Project labels and group labels](#project-labels-and-group-labels) +* [Assign and unassign labels](#assign-and-unassign-labels) +* [Label management](#label-management) + * [Project labels](#project-labels) + * [Promote a project label to a group label](#promote-a-project-label-to-a-group-label) + * [Group labels](#group-labels) + * [Create group labels from epics](#create-group-labels-from-epics-ultimate) + * [Generate default labels](#generate-default-labels) +* [Scoped labels](#scoped-labels-premium) + * [Workflows with scoped labels](#workflows-with-scoped-labels) + * [Scoped labels with nested scopes](#scoped-labels-with-nested-scopes) +* [Subscribing to labels](#subscribing-to-labels) +* [Label priority](#label-priority) +* [Troubleshooting](#troubleshooting) + * [Some label titles end with `_duplicate<number>`](#some-label-titles-end-with-_duplicatenumber) + +# Labels[](#labels "Permalink") + +## Overview[](#overview "Permalink") + +随着您在 GitLab 中问题,合并请求和史诗数量的增长,跟踪这些项目变得越来越困难. 尤其是随着您的组织从只有几个人发展到成百上千. 标签就是在这里出现的.它们可以帮助您组织和标记工作,以便您可以跟踪和找到您感兴趣的工作项. + +标签是[发行板](issue_board.html)的关键部分. 使用标签,您可以: + +* 使用颜色和描述性标题(例如`bug` , `feature request`或`docs`对史诗,问题和合并请求进行分类. +* 动态过滤和管理史诗,问题和合并请求. +* [搜索问题列表,合并请求和史诗](../search/index.html#issues-and-merge-requests)以及[问题面板](../search/index.html#issue-boards) . + +## Project labels and group labels[](#project-labels-and-group-labels "Permalink") + +GitLab 中有两种类型的标签: + +* **项目标签**只能分配给该项目,并且只能合并该项目中的请求. +* 可以将**组标签**分配给选定组或其子组中的任何项目中的问题并合并请求. + * 也可以将它们分配给所选组或其子组中的史诗. + +## Assign and unassign labels[](#assign-and-unassign-labels "Permalink") + +每个问题,合并请求和史诗都可以分配任意数量的标签. 标签在右侧栏中管理,您可以在其中根据需要分配或取消分配标签. + +要将标签分配给问题,请合并请求或史诗: + +1. 在侧边栏的标签部分,点击**编辑** ,然后: + * 在列表中,单击所需的标签. 每个标签都带有复选标记. + * 通过输入搜索查询并单击搜索来查找标签( ),然后点击它们. 您可以反复搜索并添加更多标签. +2. 单击**X**或标签部分之外的任何位置,然后将应用标签. + +您也可以使用[`/assign @username`快速操作](quick_actions.html)来分配标签. + +## Label management[](#label-management "Permalink") + +具有 Reporter 或更高[权限级别](../permissions.html)的用户可以创建和编辑标签. + +### Project labels[](#project-labels "Permalink") + +通过转到项目并单击**问题>标签**来查看项目标签列表. 该列表包括在项目级别定义的所有标签,以及从直接父组继承的所有标签. 您可以通过在顶部输入搜索查询并点击搜索( ). + +要创建一个新的项目标签: + +1. 导航到项目中的" **问题">"标签** ". +2. 单击**新建标签**按钮. + * 输入标题. + * (可选)输入描述. + * (可选)通过单击可用颜色来选择背景颜色,或输入特定颜色的十六进制颜色值. +3. 单击**创建标签**以创建标签. + +您也可以从发布或合并请求中创建新的项目标签. 在问题或合并请求的右侧栏中的标签部分: + +1. Click **Edit**. +2. Click **创建项目标签**. + * 填写名称字段. 请注意,如果以此方式创建标签,则无法指定描述. 您可以稍后通过编辑标签来添加描述(请参见下文). + * (可选)通过单击可用颜色来选择颜色,或输入特定颜色的十六进制颜色值. +3. Click **Create**. + +创建标签后,您可以通过点击铅笔( ),或通过单击三个点( )旁边的" **订阅"**按钮,然后选择" **删除"** . + +#### Promote a project label to a group label[](#promote-a-project-label-to-a-group-label "Permalink") + +如果您以前创建了项目标签,现在想使其可用于同一组中的其他项目,则可以将其升级为组标签. + +如果同一组中的其他项目具有相同标题的标签,则它们将全部与新的组标签合并. 如果存在具有相同标题的组标签,则它也会被合并. + +所有发行,合并请求,发行板列表,发行板过滤器以及带有旧标签的标签订阅都将分配给新的组标签. + +警告: **警告:**提升标签是永久性的操作,不能撤消. + +要将项目标签提升为组标签: + +1. 导航到项目中的" **问题">"标签** ". +2. 单击三个点( )旁边的**订阅**按钮,然后选择**升级为组标签** . + +### Group labels[](#group-labels "Permalink") + +通过转到组并单击**问题>标签**来查看组标签列表. 该列表包括仅在组级别定义的所有标签. 它没有列出项目中定义的任何标签. 您可以通过在顶部输入搜索查询并点击搜索( ). + +要创建**组标签** ,请导航到**组中的"** **问题">"标签"** ,并按照与[创建项目标签](#project-labels)相同的过程进行操作. + +#### Create group labels from epics[](#create-group-labels-from-epics-ultimate "Permalink") + +您可以从 Epic 侧边栏创建组标签. 您创建的标签将属于该史诗所属的直接组. 该过程与根据[发布或合并请求](#project-labels)创建[项目标签](#project-labels)的过程相同. + +### Generate default labels[](#generate-default-labels "Permalink") + +如果项目或组没有标签,则可以从标签列表页面生成一组默认的项目或组标签. 如果列表为空,该页面将显示一个" **生成默认标签集"**按钮,单击该按钮会将以下默认标签添加到项目中: + +* `bug` +* `confirmed` +* `critical` +* `discussion` +* `documentation` +* `enhancement` +* `suggestion` +* `support` + +## Scoped labels[](#scoped-labels-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9175) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.10. + +范围标签允许团队使用标签功能来注释问题,合并请求和具有互斥标签的史诗. 通过防止某些标签一起使用,可以启用更复杂的工作流程. + +当标签标题中使用特殊的双冒号( `::` :)语法时,该标签将成为作用域,例如: + +[![Sample scoped labels](img/eeadc0bb054ceec8f09d2c44982f4103.png)](img/labels_key_value_v12_1.png) + +issue,merge request 或 epic 不能具有形式为`key::value`且具有相同`key`两个范围标签. 使用相同的`key`添加一个新标签,但是使用不同的`value`将导致以前的`key`标签被新标签替换. + +用例示例: + +1. 一个问题被标识为低优先级,并向其添加了`priority::low`项目标签. +2. 经过更多审查后,问题优先级增加了,并添加了`priority::high`标签. +3. manbetx 客户端打不开会自动删除`priority::low`标签,因为一个问题不应同时具有两个优先级标签. + +### Workflows with scoped labels[](#workflows-with-scoped-labels "Permalink") + +假设您要在问题中创建一个自定义字段,以跟踪功能所针对的操作系统平台,而每个问题只应针对一个平台. 然后,您将创建三个标签`platform::iOS` , `platform::Android` , `platform::Linux` . 在给定的问题上应用这些标签中的任何一个都会自动删除以`platform::`开头的任何其他现有标签. + +可以将相同的模式应用于代表团队的工作流状态. 假设您具有标签以下标签`workflow::development` , `workflow::review`和`workflow::deployed` . 如果一个问题已经应用了标签`workflow::development` ,并且开发人员想要将该问题推进到`workflow::review` ,他们将简单地应用该标签,然后`workflow::development`标签将被自动删除. 当您在整个标签列表中移动的问题这种行为已经存在[问题板](issue_board.html#create-workflows) ,但现在,谁可能无法在一个问题板上工作的团队成员直接将仍然能够推进工作流程中的问题始终国家本身. + +在有关[将范围标签用于自定义字段和工作流](https://www.youtube.com/watch?v=4BCBby6du3c)的视频中演示了此功能. + +### Scoped labels with nested scopes[](#scoped-labels-with-nested-scopes "Permalink") + +创建标签时,可以使用多个双冒号`::`来创建具有嵌套作用域的标签. 在这种情况下,最后一个`::`之前的所有内容都将成为作用域. + +例如, `workflow::backend::review`和`workflow::backend::development`是有效的作用域标签,但是它们**不能同时**存在于同一问题上,因为它们都共享相同的作用域, `workflow::backend` . + +此外, `workflow::backend::review`和`workflow::frontend::review`是有效的范围标签,并且它们**可以同时**存在于同一问题上,因为它们都具有不同的范围, `workflow::frontend`和`workflow::backend` . + +## Subscribing to labels[](#subscribing-to-labels "Permalink") + +在项目标签列表页面和组标签列表页面中,您可以单击任何标签右侧的**订阅**以启用该标签的[通知](../profile/notifications.html) . 只要将标签分配给史诗,发行或合并请求,您就会收到通知. + +如果要从项目内订阅组标签,则可以选择仅订阅项目或整个组的标签通知. + +[![Labels subscriptions](img/074834195e0c24213cffeef5ef08a9e1.png)](img/labels_subscriptions_v12_1.png) + +## Label priority[](#label-priority "Permalink") + +版本历史 + +* 在 GitLab 8.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14189) . +* 优先级排序仅基于最高优先级标签. [讨论中](https://gitlab.com/gitlab-org/gitlab/-/issues/14523)考虑改变这一点. + +标签可以具有相对优先级,在史诗,发布和合并请求列表页面的" **标签优先级"**和" **优先级"**排序顺序中使用. 组标签和项目标签的优先级都在项目级别进行,不能从组标签列表中进行. + +在项目标签列表页面上,在标签上加上星号以表明它具有优先级. + +[![Labels prioritized](img/2fe480e26b1b89b82607729986e5b13a.png)](img/labels_prioritized_v12_1.png) + +在列表中上下拖动已加星标的标签以更改其优先级,列表中的较高表示优先级较高. + +[![Drag to change label priority](img/9e837ca8522bced4f7b219416c893fe4.png)](img/labels_drag_priority_v12_1.gif) + +在史诗般的,合并请求和问题列表页面上(针对组和项目),您可以按`Label priority`或`Priority`进行排序. + +如果您按`Label priority`排序,则 GitLab 将使用以下排序比较顺序: + +1. 具有较高优先级标签的项目. +2. 没有优先标签的项目. + +领带被任意打破. 请注意,只会检查优先级最高的标签,而忽略优先级较低的标签. 有关更多信息,请参见此[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/14523) . + +[![Labels sort label priority](img/3636c78ef6cb3ccc1462dd451c7f3efc.png)](img/labels_sort_label_priority.png) + +如果您按`Priority`排序,则 GitLab 将使用以下排序比较顺序: + +1. 具有里程碑的截止日期的项目,最早分配的[里程碑](milestones/index.html)在此列出. +2. 具有里程碑的项目,没有截止日期. +3. 具有较高优先级标签的项目. +4. 没有优先标签的项目. + +领带被任意打破. + +[![Labels sort priority](img/640bc8c28d8cd3035fbe0c4c1018d2d1.png)](img/labels_sort_priority.png) + +## Troubleshooting[](#troubleshooting "Permalink") + +### Some label titles end with `_duplicate<number>`[](#some-label-titles-end-with-_duplicatenumber "Permalink") + +在特定情况下,可以在同一名称空间中创建具有重复标题的标签. + +为了解决重复问题, [在 GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21384)和更高版本中,某些重复标签的标题后面`_duplicate<number>` . + +如果愿意,可以安全地更改这些标签的标题. 有关原始问题的详细信息,请参见[问题 30390](https://gitlab.com/gitlab-org/gitlab/issues/30390) . \ No newline at end of file diff --git a/_book/docs/104.md b/_book/docs/104.md new file mode 100644 index 0000000000000000000000000000000000000000..ecf246fda9cacbd57737130371e7352c67519dda --- /dev/null +++ b/_book/docs/104.md @@ -0,0 +1,230 @@ +# Managing issues + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/managing_issues.html](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html) + +* [Create a new issue](#create-a-new-issue) + * [Accessing the New Issue form](#accessing-the-new-issue-form) + * [Elements of the New Issue form](#elements-of-the-new-issue-form) + * [New issue from the group-level Issue Tracker](#new-issue-from-the-group-level-issue-tracker) + * [New issue via Service Desk](#new-issue-via-service-desk-starter) + * [New issue via email](#new-issue-via-email) + * [New issue via URL with prefilled fields](#new-issue-via-url-with-prefilled-fields) +* [Moving Issues](#moving-issues) + * [Moving Issues in Bulk](#moving-issues-in-bulk) +* [Closing issues](#closing-issues) + * [Closing issues automatically](#closing-issues-automatically) + * [Default closing pattern](#default-closing-pattern) + * [Disabling automatic issue closing](#disabling-automatic-issue-closing) + * [Customizing the issue closing pattern](#customizing-the-issue-closing-pattern-core-only) +* [Deleting issues](#deleting-issues) + +# Managing issues[](#managing-issues "Permalink") + +[GitLab 问题](index.html)是在[GitLab](index.html)中就想法和计划工作进行协作的基本介质. [创建](#create-a-new-issue) , [移动](#moving-issues) , [关闭](#closing-issues)和[删除](#deleting-issues)是可以解决问题的关键操作. + +## Create a new issue[](#create-a-new-issue "Permalink") + +创建新问题时,系统将提示您填写问题的[数据和字段,](issue_data_and_actions.html)如下所示. 如果知道要分配给问题的值,则可以使用" [快速操作"](../quick_actions.html)功能输入值,而不用从列表中选择它们. + +创建问题时,您可以使用**Epic**下拉列表将其与当前组中的现有史诗相关联. + +### Accessing the New Issue form[](#accessing-the-new-issue-form "Permalink") + +有多种方法可以从项目中获取"新问题"表单: + +* 导航到**项目的仪表板** > **问题** > **新问题** : + + [![New issue from the issue list view](img/ee0396a1cb32367d7ba7c6f4a7262c7f.png)](img/new_issue_from_tracker_list.png) + +* 从项目中未**解决的问题**中,单击**"**新问题"以在同一项目中创建一个新问题: + + [![New issue from an open issue](img/eb851fa4a367081c86d0a2eac3bdca65.png)](img/new_issue_from_open_issue.png) + +* 在**项目的仪表板中** ,单击加号( **+** )以打开带有一些选项的下拉菜单. 选择" **新问题"**以在该项目中创建一个问题: + + [![New issue from a project's dashboard](img/04b61606f38fddf21d194ee3e13abaa3.png)](img/new_issue_from_projects_dashboard.png) + +* 在**发行板中** ,通过单击列表顶部的加号( **+** )创建新发行. 它为该项目打开了一个新问题,并预先标记了各自的列表. + + [![From the issue board](img/7f1a1847005ab07ba8259a9e67005213.png)](img/new_issue_from_issue_board.png) + +### Elements of the New Issue form[](#elements-of-the-new-issue-form "Permalink") + +> 在[GitLab Premium](https://about.gitlab.com/pricing/) 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13847)了将新版本添加到史诗的功能. + +[![New issue from the issues list](img/94be136c7407855701b88eaded7db929.png)](img/new_issue_v13_1.png) + +创建新期刊时,可以填写以下字段: + +* Title +* Description +* 复选框以使问题保密 +* Assignee +* Weight +* Epic +* 截止日期 +* Milestone +* Labels + +### New issue from the group-level Issue Tracker[](#new-issue-from-the-group-level-issue-tracker "Permalink") + +转到"小组"仪表板,然后单击侧边栏中的" **问题** "以访问"小组"中所有项目的问题跟踪器. 使用页面右上方的下拉按钮,选择要添加问题的项目. + +[![Select project to create issue](img/31f0a42465a379e152ef6c0c7a6395e9.png)](img/select_project_from_group_level_issue_tracker.png) + +我们将跟踪您最近选择的项目,并将其用作下次访问的默认项目. 如果您主要是为同一项目创建问题,这应该可以节省大量时间和点击次数. + +[![Create issue from group-level issue tracker](img/75ca9285f50e058d4d85796b4d0b8e69.png)](img/create_issue_from_group_level_issue_tracker.png) + +### New issue via Service Desk[](#new-issue-via-service-desk-starter "Permalink") + +为您的项目启用[Service Desk](../service_desk.html)并提供电子邮件支持. 这样,当您的客户发送新电子邮件时,可以在适当的项目中创建一个新的问题,然后从那里进行后续操作. + +### New issue via email[](#new-issue-via-email "Permalink") + +如果您的 GitLab 实例配置了[传入电子邮件](../../../administration/incoming_email.html) ,则在项目的" **问题列表"**页面的底部会显示**一个"将新问题发送到该项目的电子邮件** "链接. + +[![Bottom of a project issues page](img/fd1e35952a7538923376d54325798b24.png)](img/new_issue_from_email.png) + +当您单击此链接时,将生成并显示一个电子邮件地址,该电子邮件地址**仅供您自己使用** ,以在此项目中创建问题. 您可以将此地址另存为联系人,以方便访问. + +**注意:**这是一个私人电子邮件地址,仅为您生成. **保密** ,因为任何知道它的人都可以创建问题或合并请求,就好像它们是您一样. 如果地址被盗用,或者您出于任何原因希望重新生成该地址,请再次单击"通过**电子邮件将新问题发送到此项目"** ,然后单击"重置"链接. + +向该地址发送电子邮件将以您的名字在此项目中创建一个新问题,其中: + +* The email subject becomes the issue title. +* 电子邮件正文成为问题描述. +* 支持[降价](../../markdown.html)和[快速行动](../quick_actions.html) . + +**注意:**在 GitLab 11.7 中,我们更新了生成的电子邮件地址的格式. 但是,仍支持较旧的格式,从而允许现有别名或联系人继续工作. + +### New issue via URL with prefilled fields[](#new-issue-via-url-with-prefilled-fields "Permalink") + +您可以使用 URL 中的查询字符串参数,使用预填充的字段值直接链接到给定项目的新问题页面. 这对于在外部 HTML 页面中嵌入 URL 以及在某些情况下(希望用户创建带有预填某些字段的问题)很有用. + +标题,描述,描述模板和机密字段可以使用此方法进行预填充. 您不能在同一 URL 中预先填写描述和描述模板字段(因为描述模板也会填充描述字段). + +| Field | URL 参数名称 | Notes | +| --- | --- | --- | +| title | `issue[title]` |   | +| description | `issue[description]` |   | +| 描述模板 | `issuable_template` |   | +| confidential | `issue[confidential]` | 参数值必须为`true`才能设置为机密 | + +请按照以下示例使用预填字段来形成新的问题 URL. + +* 对于 GitLab 社区版项目中的新问题,带有预填充的标题和预填充的描述,URL 为`https://gitlab.com/gitlab-org/gitlab-foss/-/issues/new?issue[title]=Validate new concept&issue[description]=Research idea` +* 对于 GitLab 社区版项目中的新问题,带有预填充的标题和预填充的描述模板,URL 为`https://gitlab.com/gitlab-org/gitlab-foss/-/issues/new?issue[title]=Validate new concept&issuable_template=Research proposal` +* 对于 GitLab 社区版项目中的新问题,其中包含预填充的标题,预填充的描述以及机密标志集,其 URL 为`https://gitlab.com/gitlab-org/gitlab-foss/-/issues/new?issue[title]=Validate new concept&issue[description]=Research idea&issue[confidential]=true` + +## Moving Issues[](#moving-issues "Permalink") + +移动问题会将其复制到新位置(项目),并在旧项目中将其关闭,但不会被删除. 这两个问题上还将添加一个系统注释,以指示它来自何处. + +The “Move issue” button is at the bottom of the right-sidebar when viewing the issue. + +[![move issue - button](img/1bc92f79d9645e6ae51aff10100e5c0d.png)](img/sidebar_move_issue.png) + +### Moving Issues in Bulk[](#moving-issues-in-bulk "Permalink") + +如果您具有高级技术技能,也可以在 Rails 控制台中将所有问题从一个项目批量转移到另一个项目. 下面的脚本会将所有问题从一个项目移至另一个状态尚未**关闭的项目** . + +要访问 rails 控制台,请在 GitLab 服务器上运行`sudo gitlab-rails console`并运行以下脚本. 请确保将**project** , **admin_user**和**target_project**更改为您的值. 我们也建议您在尝试对控制台进行任何更改之前先[创建备份](../../../raketasks/backup_restore.html#back-up-gitlab) . + +``` +project = Project.find_by_full_path('full path of the project where issues are moved from') +issues = project.issues +admin_user = User.find_by_username('username of admin user') # make sure user has permissions to move the issues +target_project = Project.find_by_full_path('full path of target project where issues moved to') + +issues.each do |issue| + if issue.state != "closed" && issue.moved_to.nil? + Issues::MoveService.new(project, admin_user).execute(issue, target_project) + else + puts "issue with id: #{issue.id} and title: #{issue.title} was not moved" + end +end; nil +``` + +## Closing issues[](#closing-issues "Permalink") + +当您确定问题已解决或不再需要时,可以使用"关闭"按钮关闭该问题: + +[![close issue - button](img/4635aba96009dfb3ab93ab6f4b92ee4c.png)](img/button_close_issue.png) + +您还可以通过将发行卡从其发行版列表中拖放到" **已关闭"**列表中来**关闭** [发行板中](../issue_board.html)的发行. + +[![close issue from the Issue Board](img/0f7aab3f307e6b54ebe4d00d94f1da0a.png)](img/close_issue_from_board.gif) + +### Closing issues automatically[](#closing-issues-automatically "Permalink") + +**注意:**由于性能原因,从现有存储库的第一次推送将禁用自动问题关闭. + +当提交或合并请求解决了一个或多个问题时,当提交或合并请求到达项目的默认分支时,可能会自动关闭这些问题. + +如果提交消息或合并请求描述包含与[定义的模式](#default-closing-pattern)匹配的文本,则匹配文本中引用的所有问题均将关闭. 将提交推送到项目的[**默认**分支时](../repository/branches/index.html#default-branch) ,或者将提交或合并请求合并到其中时,就会发生这种情况. + +例如,如果合并请求描述中包含`Closes #4, #6, Related to #5`则合并 MR 时问题`#4`和`#6`将自动关闭,但不会合并`#5` . 将" `Related to` `#5`标记[相关"](related_issues.html)用作[相关问题](related_issues.html) ,但不会自动关闭. + +[![merge request closing issue when merged](img/fee3cc5116f884089066af3908605cbe.png)](img/merge_request_closes_issue.png) + +如果问题与 MR 位于不同的存储库中,请添加问题的完整 URL: + +``` +Closes #4, #6, and https://gitlab.com/<username>/<projectname>/issues/<xxx> +``` + +#### Default closing pattern[](#default-closing-pattern "Permalink") + +如果未指定,将使用如下所示的默认问题关闭模式: + +``` +\b((?:[Cc]los(?:e[sd]?|ing)|\b[Ff]ix(?:e[sd]|ing)?|\b[Rr]esolv(?:e[sd]?|ing)|\b[Ii]mplement(?:s|ed|ing)?)(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?: *,? +and +| *,? *)?)|([A-Z][A-Z0-9_]+-\d+))+) +``` + +这将转换为以下关键字: + +* 关闭,关闭,关闭,关闭,关闭,关闭,关闭,关闭 +* 修正,修正,修正,修正,修正,修正,修正,修正 +* 解决,解决,解决,解决,解决,解决,解决,解决 +* 实施,实施,实施,实施,实施,实施,实施,实施 + +请注意, `%{issue_ref}`是在 GitLab 的源代码中定义的复杂正则表达式,可以匹配对以下内容的引用: + +* 本地问题( `#123` ). +* 跨项目问题( `group/project#123` ). +* 指向问题的链接( `https://gitlab.example.com/group/project/issues/123` ). + +例如以下提交消息: + +``` +Awesome commit message + +Fix #20, Fixes #21 and Closes group/otherproject#22. +This commit is also related to #17 and fixes #18, #19 +and https://gitlab.example.com/group/otherproject/issues/23. +``` + +将在提交被推送到的项目中关闭`#18` , `#19` , `#20`和`#21` ,以及`group/otherproject` `#22`和`#23` . `#17`将不会关闭,因为它与模式不匹配. 当从命令行与`git commit -m`一起使用时,它可以处理多行提交消息以及单行代码. + +#### Disabling automatic issue closing[](#disabling-automatic-issue-closing "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/19754) . + +可以在[项目的存储库设置中](../settings/index.html)针对每个项目禁用自动关闭问题功能. 引用的问题仍将按原样显示,但不会自动关闭. + +[![disable issue auto close - settings](img/a3802569c81d8f8dd179fd218322a4ca.png)](img/disable_issue_auto_close.png) + +这仅适用于受新合并请求或提交影响的问题. 已经解决的问题仍然保持原样. 禁用自动关闭的问题仅影响到项目*中*的合并请求,并不会阻止其他项目从通过跨项目的问题,将其关闭. + +#### Customizing the issue closing pattern[](#customizing-the-issue-closing-pattern-core-only "Permalink") + +为了更改默认的问题关闭模式,GitLab 管理员必须编辑安装的[`gitlab.rb`或`gitlab.yml`文件](../../../administration/issue_closing_pattern.html) . + +## Deleting issues[](#deleting-issues "Permalink") + +在 GitLab 8.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2982) + +具有[项目所有者权限的](../../permissions.html)用户可以通过编辑问题并单击删除按钮来删除问题. + +[![delete issue - button](img/51e7561422b1e74237ea14e916cffc78.png)](img/delete_issue.png) \ No newline at end of file diff --git a/_book/docs/105.md b/_book/docs/105.md new file mode 100644 index 0000000000000000000000000000000000000000..48ed5118637082fc721311d014f11745d4892d11 --- /dev/null +++ b/_book/docs/105.md @@ -0,0 +1,176 @@ +# Milestones + +> 原文:[https://docs.gitlab.com/ee/user/project/milestones/](https://docs.gitlab.com/ee/user/project/milestones/) + +* [Overview](#overview) +* [Milestones as Agile sprints](#milestones-as-agile-sprints) +* [Milestones as releases](#milestones-as-releases) +* [Project milestones and group milestones](#project-milestones-and-group-milestones) +* [Creating milestones](#creating-milestones) + * [New project milestone](#new-project-milestone) + * [New group milestone](#new-group-milestone) +* [Editing milestones](#editing-milestones) + * [Promoting project milestones to group milestones](#promoting-project-milestones-to-group-milestones) +* [Assigning milestones from the sidebar](#assigning-milestones-from-the-sidebar) +* [Filtering issues and merge requests by milestone](#filtering-issues-and-merge-requests-by-milestone) + * [Filtering in list pages](#filtering-in-list-pages) + * [Filtering in issue boards](#filtering-in-issue-boards) + * [Special milestone filters](#special-milestone-filters) +* [Milestone view](#milestone-view) + * [Project Burndown Charts](#project-burndown-charts-starter) + * [Group Burndown Charts](#group-burndown-charts-premium) + * [Milestone sidebar](#milestone-sidebar) + +# Milestones[](#milestones "Permalink") + +## Overview[](#overview "Permalink") + +GitLab 中的里程碑是一种跟踪问题并合并为在一定时期内实现更广泛目标而创建的请求的方法. + +里程碑使您可以组织问题并将请求合并到一个紧密联系的组中,并带有一个可选的开始日期和一个可选的截止日期. + +## Milestones as Agile sprints[](#milestones-as-agile-sprints "Permalink") + +里程碑可用作敏捷冲刺,因此您可以跟踪所有问题并合并与特定冲刺有关的请求. 为此: + +1. 设置里程碑的开始日期和截止日期,以代表敏捷冲刺的开始和结束. +2. 将里程碑标题设置为敏捷 sprint 的名称,例如`November 2018 sprint` . +3. 通过将问题的右侧边栏关联到所需的里程碑,将问题添加到敏捷冲刺中. + +## Milestones as releases[](#milestones-as-releases "Permalink") + +同样,里程碑可以用作发布. 为此: + +1. 设置里程碑到期日期以表示发布的发布日期,并将里程碑开始日期保留为空白. +2. 将里程碑标题设置为您的发行版,例如`Version 9.4` . +3. 通过关联问题右侧的期望里程碑,将问题添加到您的发行中. + +此外,您可以将里程碑与 GitLab 的[Releases 功能](../releases/index.html#associate-milestones-with-a-release)集成. + +## Project milestones and group milestones[](#project-milestones-and-group-milestones "Permalink") + +您可以将**项目里程碑**分配给问题或仅合并该项目中的请求. 要查看项目里程碑列表,请在项目中转到 **问题>里程碑** . + +您可以将**组里程碑**分配给该**组**中任何项目的任何发行或合并请求. 要查看组里程碑列表,请在组中转到 **问题>里程碑** . + +您还可以在仪表板里程碑列表中查看您有权访问的所有里程碑. 要查看您可以访问的项目里程碑和组里程碑,请单击顶部导航栏上的**更多>里程碑** . + +有关项目和组里程碑 API 的信息,请参阅: + +* [Project Milestones API](../../../api/milestones.html) +* [Group Milestones API](../../../api/group_milestones.html) + +**注意:**如果您在一个小组中,然后单击**问题>里程碑** ,您将看到小组里程碑和该小组中的项目里程碑. 如果您在项目中,然后单击" **问题">"里程碑"** ,则只会看到该项目的里程碑. + +## Creating milestones[](#creating-milestones "Permalink") + +**注意:**创建里程碑需要[开发者或更高](../../permissions.html)级别的权限. + +### New project milestone[](#new-project-milestone "Permalink") + +创建**项目里程碑** : + +1. 在一个项目中,转到 **问题>里程碑** . +2. Click **新的里程碑**. +3. 输入标题,可选描述,可选开始日期和可选截止日期. +4. Click **新的里程碑**. + +[![New project milestone](img/9807a6b10b783af2ed7c8703958f017a.png)](img/milestones_new_project_milestone.png) + +### New group milestone[](#new-group-milestone "Permalink") + +创建**组里程碑** : + +1. 在一个小组中,转到 **问题>里程碑** . +2. Click **新的里程碑**. +3. 输入标题,可选描述,可选开始日期和可选截止日期. +4. Click **新的里程碑**. + +[![New group milestone](img/4d2f841f1dee2bdbbdcd14bd5518c000.png)](img/milestones_new_group_milestone.png) + +## Editing milestones[](#editing-milestones "Permalink") + +**注意:**编辑里程碑需要[开发者或更高的](../../permissions.html)权限级别. + +要编辑里程碑: + +1. 在项目或小组中,转到 **问题>里程碑** . +2. 单击里程碑标题. +3. Click **Edit**. + +您可以通过单击" **删除"**按钮来删除里程碑. + +### Promoting project milestones to group milestones[](#promoting-project-milestones-to-group-milestones "Permalink") + +If you are expanding from a few projects to a larger number of projects within the same group, you may want to share the same milestone among multiple projects in the same group. If you previously created a project milestone and now want to make it available for other projects within the same group, you can promote it to a group milestone. + +从项目里程碑列表页面,您可以将项目里程碑升级为组里程碑. 这会将具有相同名称的该组中所有项目中的所有项目里程碑合并为一个组里程碑. 以前已分配给这些项目里程碑之一的所有问题和合并请求现在都将分配给新的组里程碑. 此操作不能撤消,更改是永久的. + +**警告:**从 GitLab 12.4 和更早版本开始,将项目里程碑提升为组里程碑时,某些信息会丢失. 组里程碑视图上并非项目里程碑视图上的所有功能都可用. 如果将项目里程碑升级为组里程碑,则将失去这些功能. 请参阅" [里程碑"视图,](#milestone-view)以查看组里程碑视图中缺少哪些功能. + +[![Promote milestone](img/e14dc9ee9528f343daf09a4dd5340b99.png)](img/milestones_promote_milestone.png) + +## Assigning milestones from the sidebar[](#assigning-milestones-from-the-sidebar "Permalink") + +可以为每个问题和合并请求分配一个里程碑. 里程碑在边栏中的每个问题和合并请求页面上可见. 它们在发行板上也可见. 您可以从边栏中为对象分配或取消分配里程碑. 您也可以在评论中[快速](../quick_actions.html)执行此[操作](../quick_actions.html) . [如前所述](#project-milestones-and-group-milestones) ,对于给定的发布或合并请求,可以选择项目里程碑和组里程碑并将其分配给对象. + +## Filtering issues and merge requests by milestone[](#filtering-issues-and-merge-requests-by-milestone "Permalink") + +### Filtering in list pages[](#filtering-in-list-pages "Permalink") + +在项目发布/合并请求列表页面和组发布/合并请求列表页面中,可以按组里程碑和项目里程碑进行[筛选](../../search/index.html#issues-and-merge-requests) . + +### Filtering in issue boards[](#filtering-in-issue-boards "Permalink") + +* 在[项目发布板上](../issue_board.html) ,您可以在[搜索和过滤器栏中](../../search/index.html#issue-boards)按组里程碑和项目里程碑进行[筛选](../../search/index.html#issue-boards) . +* 在[组发布板上](../issue_board.html#group-issue-boards-premium) ,您只能在[搜索和过滤器栏中](../../search/index.html#issue-boards)按组里程碑进行[过滤](../../search/index.html#issue-boards) . +* 在[项目发行板中](../issue_board.html) ,可以在[发行板配置中](../issue_board.html#configurable-issue-boards-starter)按组里程碑和项目里程碑进行筛选. +* 在[组发行板上,](../issue_board.html#group-issue-boards-premium)您只能按[发行板配置](../issue_board.html#configurable-issue-boards-starter)中的组里程碑进行筛选. + +### Special milestone filters[](#special-milestone-filters "Permalink") + +在按里程碑进行筛选时,除了选择特定的项目里程碑或组里程碑之外,还可以选择特殊的里程碑筛选器. + +* **无** :显示问题或没有分配里程碑的合并请求. +* **任何** :显示问题或合并具有指定里程碑的请求. +* **即将到来的** :显示已分配的公开里程碑的问题或合并请求,该里程碑具有下一个即将到来的到期日(即将来的最近到期日). +* **已开始** :显示具有打开的指定里程碑且开始日期在今天之前的问题或合并请求. + +## Milestone view[](#milestone-view "Permalink") + +里程碑视图显示标题和描述. + +这些标签下面还包含显示以下内容的标签: + +* **问题** :显示分配给里程碑的所有问题. 这些内容显示在名为: + * 未开始的问题(未解决和未分配) + * 进行中的问题(未解决和已分配) + * 已完成的问题(已关闭) +* **合并请求** :显示分配给里程碑的所有合并请求. 这些将显示在名为: + * 进行中的工作(开放且未分配) + * 等待合并(打开和未分配) + * 拒绝(关闭) + * 合并后 +* **参与者** :显示分配给该里程碑的所有问题的受让人. +* **Labels**: Shows all labels that are used in issues assigned to the milestone. + +### Project Burndown Charts[](#project-burndown-charts-starter "Permalink") + +对于[GitLab Starter 中的](https://about.gitlab.com/pricing/)项目里程碑,里程碑视图中有一个[燃尽图](burndown_charts.html) ,显示完成里程碑的进度. + +[![burndown chart](img/eb36e4acf26c49641689d1a05dd8fa8a.png)](img/burndown_chart.png) + +### Group Burndown Charts[](#group-burndown-charts-premium "Permalink") + +对于[GitLab Premium 中的](https://about.gitlab.com/pricing/)组里程碑,里程碑视图中有一个[燃尽图](burndown_charts.html) ,显示完成里程碑的进度. + +### Milestone sidebar[](#milestone-sidebar "Permalink") + +里程碑视图上的里程碑侧栏显示以下内容: + +* 完成百分比,计算方式为已完成的问题数除以问题总数. +* 开始日期和截止日期. +* 在分配给里程碑的所有问题和合并请求上花费的总时间. +* 分配给里程碑的所有问题的总问题权重. + +[![Project milestone page](img/11f64bd49fd604a4644dd54ed7e423e8.png)](img/milestones_project_milestone_page.png) \ No newline at end of file diff --git a/_book/docs/106.md b/_book/docs/106.md new file mode 100644 index 0000000000000000000000000000000000000000..a10dd67a8f28e93895a7e334764f9316b6078c5b --- /dev/null +++ b/_book/docs/106.md @@ -0,0 +1,35 @@ +# Multiple Assignees for Issues + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html](https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [How it works](#how-it-works) + +# Multiple Assignees for Issues[](#multiple-assignees-for-issues-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1904) in [GitLab Starter 9.2](https://about.gitlab.com/releases/2017/05/22/gitlab-9-2-released/#multiple-assignees-for-issues). + +## Overview[](#overview "Permalink") + +在拥有问题共享所有权的大型团队中,可能很难跟踪谁正在处理问题,谁已经完成了贡献,谁还没有开始. + +在[GitLab 企业版中](https://about.gitlab.com/pricing/) ,您还可以选择一个问题的多个受让人,使其更容易跟踪,并更清楚地由谁负责. + +[![multiple assignees for issues](img/d0707d7a1f822105efb120e442c32246.png)](img/multiple_assignees_for_issues.png) + +## Use cases[](#use-cases "Permalink") + +考虑一个由前端开发人员,后端开发人员,UX 设计人员,QA 测试人员和产品经理组成的团队,他们共同努力将创意推向市场. + +多个问题分配者可以使协作更加顺畅,并可以清晰显示共享的职责. 在团队的工作流程中将显示所有受让人,并接收通知(就像作为单个受让人一样),从而简化了沟通和所有权. + +受让人完成工作后,他们将离开自己,成为受让人,这清楚表明他们的角色已经完成. + +## How it works[](#how-it-works "Permalink") + +在未解决的问题中,展开右侧栏,找到受让人条目,然后单击" **编辑"** . 从下拉菜单中,选择要分配问题的用户数. + +[![adding multiple assignees](img/9149638f26311ced385bcc879401a8fd.png)](img/multiple_assignees.gif) + +通过从同一下拉菜单中取消选择受让人可以轻松将其删除. \ No newline at end of file diff --git a/_book/docs/107.md b/_book/docs/107.md new file mode 100644 index 0000000000000000000000000000000000000000..0cba33acb474e76f8419c0fa47c17ba1cde850c5 --- /dev/null +++ b/_book/docs/107.md @@ -0,0 +1,49 @@ +# Related issues + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/related_issues.html](https://docs.gitlab.com/ee/user/project/issues/related_issues.html) + +* [Adding a related issue](#adding-a-related-issue) +* [Removing a related issue](#removing-a-related-issue) + +# Related issues[](#related-issues-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1797) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.4. + +相关问题是任何两个问题之间的双向关系,并出现在问题描述下方的方框中. 问题可能会跨越小组和项目. + +如果用户可以看到两个问题,则该关系仅显示在 UI 中. + +## Adding a related issue[](#adding-a-related-issue "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/2035) . +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 13.0 中进行了[改进](https://gitlab.com/gitlab-org/gitlab/-/issues/34239) . 当您尝试使用打开的阻止程序来解决问题时,您会看到一条警告,您可以将其关闭. + +You can relate one issue to another by clicking the related issues “+” button in the header of the related issue block. Then, input the issue reference number or paste in the full URL of the issue. + +此外,您可以选择当前问题是与输入的问题相关,被阻止还是被阻止. + +[![Adding a related issue](img/8d249dc6a1ff208c520bfc8cad423a4a.png)](img/related_issues_add_v12_8.png) + +同一项目的问题只能通过参考编号指定. 来自其他项目的问题需要其他信息,例如组和项目名称. 例如: + +* 同一项目: `#44` +* 同一组: `project#44` +* 不同的组: `group/project#44` + +有效参考将添加到您可以查看的临时列表中. 添加完所有相关问题后,请单击**添加**以提交. + +完成所有相关问题的添加后,您将能够看到它们的分类,以便可以从视觉上更好地理解它们之间的关系. + +[![Related issue block](img/e3439aafb873fb6b7cdb3a5c6d51c3b9.png)](img/related_issue_block_v12_8.png) + +## Removing a related issue[](#removing-a-related-issue "Permalink") + +在相关问题区域中,单击要删除的每个问题令牌右侧的" x"图标. 由于双向关系,它将不再出现在任何一个问题中. + +[![Removing a related issue](img/9e8d2b5134e62de656bff96c60c04e10.png)](img/related_issues_remove_v12_8.png) + +请访问我们的[权限](../../permissions.html)页面以获取更多信息. + +此外,您还可以通过[我们的 API](../../../api/issue_links.html)管理相关问题. \ No newline at end of file diff --git a/_book/docs/108.md b/_book/docs/108.md new file mode 100644 index 0000000000000000000000000000000000000000..1b6a304839222b8c58b5e8ef7170685d63848d84 --- /dev/null +++ b/_book/docs/108.md @@ -0,0 +1,207 @@ +# Service Desk + +> 原文:[https://docs.gitlab.com/ee/user/project/service_desk.html](https://docs.gitlab.com/ee/user/project/service_desk.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [How it works](#how-it-works) +* [Configuring Service Desk](#configuring-service-desk) + * [Using customized email templates](#using-customized-email-templates) + * [Thank you email](#thank-you-email) + * [New note email](#new-note-email) + * [Using custom email display name](#using-custom-email-display-name) + * [Using custom email address](#using-custom-email-address) + * [Enable custom email address](#enable-custom-email-address) +* [Using Service Desk](#using-service-desk) + * [As an end user (issue creator)](#as-an-end-user-issue-creator) + * [As a responder to the issue](#as-a-responder-to-the-issue) + * [Support Bot user](#support-bot-user) + +# Service Desk[](#service-desk "Permalink") + +Version history + +* [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/149) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.1. +* 在 13.0 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/214839) [GitLab Starter](https://about.gitlab.com/pricing/) . +* 在 13.2 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/215364) [GitLab Core](https://about.gitlab.com/pricing/) . + +## Overview[](#overview "Permalink") + +Service Desk 是一个模块,可让您的团队直接在 GitLab 内部通过电子邮件与任何外部方联系. 无需外部工具. 在构建软件的过程中进行的持续对话可确保用户反馈直接在需要的地方结束,从而帮助您构建正确的功能来解决用户的实际问题. + +借助 Service Desk,您可以为客户提供有效的电子邮件支持,他们现在可以通过电子邮件向您发送错误报告,功能请求或常规反馈,这些问题将作为新问题最终出现在您的 GitLab 项目中. 反过来,您的团队可以直接从项目中做出回应. + +由于 Service Desk 直接内置在 GitLab 中,因此消除了多种工具和外部集成的复杂性和低效率,从而大大缩短了从反馈到软件更新的周期时间. + +有关概述,请查看[GitLab 服务](https://about.gitlab.com/blog/2017/05/09/demo-service-desk/)台上的视频演示. + +## Use cases[](#use-cases "Permalink") + +例如,假设您为 iOS 或 Android 开发游戏. 该代码库托管在您的 GitLab 实例中,并通过 GitLab CI / CD 构建和部署. + +这是 Service Desk 为您工作的方式: + +1. 您向付费客户提供特定于项目的电子邮件地址,他们可以直接从应用程序内向您发送电子邮件. +2. 他们发送的每封电子邮件都会在相应的项目中产生一个问题. +3. 您的团队成员导航到 Service Desk 问题跟踪器,在这里他们可以查看新的支持请求并在内部相关问题中做出响应. +4. 您的团队与客户进行来回沟通以了解请求. +5. 您的团队开始着手实施代码以解决客户的问题. +6. 当您的团队完成实施后,合并请求将合并,问题将自动关闭. +7. 该客户将通过电子邮件成功出席,而无需真正访问您的 GitLab 实例. +8. 您的团队无需离开 GitLab(或设置任何集成)即可跟进客户,从而节省了时间. + +## How it works[](#how-it-works "Permalink") + +GitLab 服务台是一种简单的方法,使人们无需自己的用户帐户即可在您的 GitLab 实例中创建问题. + +它为最终用户提供了一个在项目中创建问题的唯一电子邮件地址,并且可以通过 GitLab 界面或通过电子邮件发送答复. 最终用户将仅通过电子邮件看到该主题. + +## Configuring Service Desk[](#configuring-service-desk "Permalink") + +**注意:**在 GitLab.com 上启用了 Service Desk. 您可以跳过下面的步骤 1; 您只需要为每个项目启用它. + +如果您具有项目维护者访问权限,则可以选择设置服务台. 请按照以下步骤操作: + +1. 为 GitLab 实例[设置传入电子邮件](../../administration/incoming_email.html#set-it-up) . + * 我们建议使用[电子邮件子地址](../../administration/incoming_email.html#email-sub-addressing) ,但在 GitLab 11.7 及更高版本中,您也可以使用[全部接收邮箱](../../administration/incoming_email.html#catch-all-mailbox) . +2. 导航到项目的**"设置">"常规",**然后找到" **服务台"**部分. +3. 启用**激活服务台**切换. 这显示了一个唯一的电子邮件地址,可将问题发送给项目. 这些问题将是[机密的](issues/confidential_issues.html) ,因此它们仅对项目成员可见. 请注意,在 GitLab 11.7 中,我们更新了生成的电子邮件地址的格式. 仍然支持较旧的格式,但是允许现有的别名或联系人继续工作. + + **危险:**任何人都可以使用此电子邮件地址在此项目上创建问题,无论他们是否有权访问您的 GitLab 实例. 我们建议**将其放在别名后面,**以便可以根据需要进行更改,并在您的 GitLab 实例上**[启用 Akismet](../../integration/akismet.html)**来向该服务添加垃圾邮件检查. 畅通无阻的电子邮件垃圾邮件将导致创建许多垃圾邮件问题. + + 如果存储库中有[模板](description_templates.html) ,则可以选择从选择器菜单中选择一个[模板](description_templates.html) ,以将其附加到所有 Service Desk 问题上. + + [![Service Desk enabled](img/d32d8400522e9b5c9dd295fba00e1255.png)](img/service_desk_enabled.png) + +现在已为此项目启用 Service Desk! 您应该能够从项目导航的" **问题"**菜单中访问它. + +[![Service Desk Navigation Item](img/c42e6852cdd2c45b0a814f7a659ee5d2.png)](img/service_desk_nav_item.png) + +### Using customized email templates[](#using-customized-email-templates "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2460) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7. + +当用户使用 Service Desk 提交新问题时,或在 Service Desk 问题上创建新便笺时,将向作者发送电子邮件. + +这些电子邮件的正文可以使用模板进行自定义. 要创建新的自定义模板,请在存储库的`.gitlab/service_desk_templates/`目录内创建一个新的 Markdown( `.md` )文件. 提交并推送到您的默认分支. + +#### Thank you email[](#thank-you-email "Permalink") + +**谢谢电子邮件**是用户提交问题后发送给用户的电子邮件. 模板的文件名必须为`thank_you.md` . 您可以使用`%{ISSUE_ID}`占位符,它将由电子邮件中的问题 IID 替换;而`%{ISSUE_PATH}`占位符,将由项目路径和问题 IID 替换. 由于服务台问题被创建为机密(只有项目成员才能看到),因此回复电子邮件中没有提供问题链接. + +#### New note email[](#new-note-email "Permalink") + +**新笔记电子邮件**是当用户提交的问题有新评论时发送给用户的电子邮件. 模板的文件名必须为`new_note.md` . 您可以使用`%{ISSUE_ID}`占位符(将在电子邮件中替换为问题 IID), `%{ISSUE_PATH}`占位符(将替换为项目路径)以及问题 IID 和`%{NOTE_TEXT}`占位符(将替换为注释文本) . + +### Using custom email display name[](#using-custom-email-display-name "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7529) . + +您可以自定义电子邮件显示名称. 从服务台发送的电子邮件在" `From`标题中将具有此名称. 默认显示名称是`GitLab Support Bot` . + +### Using custom email address[](#using-custom-email-address "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2201) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0. + +**注意:**默认情况下禁用此功能. 有关启用它的步骤,请参阅[启用自定义电子邮件地址](#enable-custom-email-address) . + +如果在配置中启用了`service_desk_email`功能标记,则可以通过将电子邮件发送到自定义 Service Desk 电子邮件地址来创建 Service Desk 问题,该电子邮件地址应采用以下格式: `project_contact+%{key}@example.com` . + +`%{key}`部分用于查找应在其中创建问题的项目. `%{key}`部分组合了项目的路径和可配置的项目名称后缀: `<project_full_path>-<project_name_suffix>` . + +您可以在项目的服务台设置中设置项目名称后缀. 它只能包含小写字母( `az` ),数字( `0-9` )或下划线( `_` ). + +[![Setting custom Service Desk email address](img/210e34a4dbdbe21aba5083c6f7dac9cb.png)](img/service_desk_custom_email_address_v13_0.png) + +您可以将以下代码片段添加到您的配置中. + +从源安装的示例: + +``` +service_desk_email: + enabled: true + address: "project_contact+%{key}@example.com" + user: "project_support@example.com" + password: "[REDACTED]" + host: "imap.gmail.com" + port: 993 + ssl: true + start_tls: false + log_path: "log/mailroom.log" + mailbox: "inbox" + idle_timeout: 60 + expunge_deleted: true +``` + +Omnibus GitLab 安装示例: + +``` +gitlab_rails['service_desk_email_enabled'] = true + +gitlab_rails['service_desk_email_address'] = "project_contact+%{key}@gmail.com" + +gitlab_rails['service_desk_email_email'] = "project_support@gmail.com" + +gitlab_rails['service_desk_email_password'] = "[REDACTED]" + +gitlab_rails['service_desk_email_mailbox_name'] = "inbox" + +gitlab_rails['service_desk_email_idle_timeout'] = 60 + +gitlab_rails['service_desk_email_log_file'] = "/var/log/gitlab/mailroom/mail_room_json.log" + +gitlab_rails['service_desk_email_host'] = "imap.gmail.com" + +gitlab_rails['service_desk_email_port'] = 993 + +gitlab_rails['service_desk_email_ssl'] = true + +gitlab_rails['service_desk_email_start_tls'] = false +``` + +在这种情况下,假设`mygroup/myproject`项目 Service Desk 设置的项目名称后缀设置为`support` ,并且用户将电子邮件发送到`project_contact+mygroup-myproject-support@example.com` . 结果,将在`mygroup/myproject`项目中从此电子邮件中创建一个新的 Service Desk 问题. + +#### Enable custom email address[](#enable-custom-email-address "Permalink") + +默认情况下,此功能附带`service_desk_custom_address`功能标志. 要打开此功能,请要求具有 Rails 控制台访问权限的 GitLab 管理员运行以下命令: + +``` +Feature.enable(:service_desk_custom_address) +``` + +配置选项与配置[传入电子邮件](../../administration/incoming_email.html#set-it-up)相同. + +## Using Service Desk[](#using-service-desk "Permalink") + +### As an end user (issue creator)[](#as-an-end-user-issue-creator "Permalink") + +要创建服务台问题,最终用户无需了解有关 GitLab 实例的任何信息. 他们只是将电子邮件发送到给定的地址,然后收到一封确认回执的电子邮件: + +[![Service Desk enabled](img/3b8b0bcac599d7207d90ed8194bed83e.png)](img/service_desk_confirmation_email.png) + +这也使最终用户可以选择退订. + +如果他们不选择退订,那么添加到该问题的任何新评论都将作为电子邮件发送: + +[![Service Desk reply email](img/85055487485aff8bd5dc0cf97f711d52.png)](img/service_desk_reply.png) + +他们发送的所有回复都将显示在问题本身中. + +### As a responder to the issue[](#as-a-responder-to-the-issue "Permalink") + +For responders to the issue, everything works as usual. They will see a familiar looking issue tracker, where they can see issues created via customer support requests and filter and interact with them just like other GitLab issues. + +[![Service Desk Issue tracker](img/daa9468beb587bb748cbb9ec37bbb43f.png)](img/service_desk_issue_tracker.png) + +来自最终用户的消息将显示为来自特殊的支持机器人用户,但是除此之外,您可以像平常一样阅读和编写评论: + +[![Service Desk issue thread](img/1b69e9fcb692fa835e9b7e06fa856aee.png)](img/service_desk_thread.png) + +注意: + +* 项目的可见性(私有,内部,公共)不会影响 Service Desk. +* 项目的路径,包括其组或名称空间,将显示在电子邮件中. + +### Support Bot user[](#support-bot-user "Permalink") + +在后台,服务台由支持机器人的特殊用户创建问题. 该用户不计入许可证限制数. \ No newline at end of file diff --git a/_book/docs/109.md b/_book/docs/109.md new file mode 100644 index 0000000000000000000000000000000000000000..40ab81a99689f651f1be335babb75caf0f5a1689 --- /dev/null +++ b/_book/docs/109.md @@ -0,0 +1,23 @@ +# Sorting and ordering issue lists + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/sorting_issue_lists.html](https://docs.gitlab.com/ee/user/project/issues/sorting_issue_lists.html) + +* [Manual sorting](#manual-sorting) + +# Sorting and ordering issue lists[](#sorting-and-ordering-issue-lists "Permalink") + +您可以通过多种方式对问题列表进行排序,包括按问题创建日期,里程碑到期日期等进行排序.可用的排序选项可以根据列表的上下文进行更改. 有关按发布优先级排序的信息,请参见[标签优先级](../labels.html#label-priority) . + +在组和项目问题清单中,也可以手动订购问题,类似于[问题委员会](../issue_board.html#issue-ordering-in-a-list) . + +## Manual sorting[](#manual-sorting "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62178) . + +选择" **手动**排序"时,可以通过拖放问题来更改顺序. 更改后的订单将保留. 除了某些例外,访问同一列表的每个人都将看到重新排序的列表. + +每个问题都分配有一个相对顺序值,代表其相对于列表中其他问题的相对顺序. 当您拖放问题的重新排序时,其相对顺序值也会相应更改. + +此外,任何问题出现在手动排序的列表中时,更新的相对订单值将用于订购. 这意味着,如果您的 GitLab 实例内给定列表中的任何用户将问题`A`拖放到问题`B`上方,则随后将这两个问题随后加载到同一实例的任何列表中(可能是不同的)例如项目专案清单或其他群组专案清单),即可维持订购顺序. + +此顺序还会影响[发行板](../issue_board.html#issue-ordering-in-a-list) . 更改问题列表中的顺序会更改问题面板中的顺序,反之亦然. \ No newline at end of file diff --git a/_book/docs/110.md b/_book/docs/110.md new file mode 100644 index 0000000000000000000000000000000000000000..e9eff2c7893784091b9e63d0ed1105f5318cd709 --- /dev/null +++ b/_book/docs/110.md @@ -0,0 +1,17 @@ +# Issue weight + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/issue_weight.html](https://docs.gitlab.com/ee/user/project/issues/issue_weight.html) + +# Issue weight[](#issue-weight-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.3. + +当您遇到很多问题时,可能很难获得概述. 通过为每个问题增加权重,您可以更好地了解给定问题要花费或花费多少时间,价值或复杂性. + +您可以通过简单地更改下拉菜单中的值来设置问题的权重. 您可以将其设置为 0、1、2 等的非负整数值. (数据库存储一个 4 字节的值,因此上限基本上是无限的). 您也可以减轻问题的负担. + +该值将显示在单个问题的右侧栏上,以及在独特的余额比例图标旁边的问题页面中. + +另外,您可以在里程碑页面上查看所有问题的总和. + +[![issue page](img/ff2558c68f4e646052a0c39a7d3f8710.png)](img/issue_weight.png) \ No newline at end of file diff --git a/_book/docs/111.md b/_book/docs/111.md new file mode 100644 index 0000000000000000000000000000000000000000..423ea1162ca56cd2d5ad622d6daab340b7c0369f --- /dev/null +++ b/_book/docs/111.md @@ -0,0 +1,38 @@ +# Associate a Zoom meeting with an issue + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/associate_zoom_meeting.html](https://docs.gitlab.com/ee/user/project/issues/associate_zoom_meeting.html) + +* [Adding a zoom meeting to an issue](#adding-a-zoom-meeting-to-an-issue) +* [Removing an existing Zoom meeting from an issue](#removing-an-existing-zoom-meeting-from-an-issue) + +# Associate a Zoom meeting with an issue[](#associate-a-zoom-meeting-with-an-issue "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16609) . + +为了同步进行事件管理通信,GitLab 允许将 Zoom 会议与问题相关联. 一旦开始进行消防战斗的变焦呼叫,就需要一种将电话会议与问题相关联的方法,以便您的团队成员可以快速加入而无需请求链接. + +## Adding a zoom meeting to an issue[](#adding-a-zoom-meeting-to-an-issue "Permalink") + +要将缩放会议与问题相关联,可以使用 GitLab 的[快速操作](../quick_actions.html#quick-actions-for-issues-merge-requests-and-epics) . + +在一个问题中,使用`/zoom`快速操作和有效的 Zoom 链接发表评论: + +``` +/zoom https://zoom.us/j/123456789 +``` + +如果"缩放会议 URL"有效且您至少具有" [报告者"权限](../../permissions.html) ,则系统警报将通知您会议 URL 添加成功. 该问题的描述将被自动编辑以包含"缩放"链接,并且在该问题的标题下方将出现一个按钮. + +[![Link Zoom Call in Issue](img/2b66844a710706131349b467b399b449.png)](img/zoom-quickaction-button.png) + +您只能将单个 Zoom 会议附加到一个问题. 如果您尝试使用`/zoom`快速操作添加第二个 Zoom 会议,它将无法正常工作,您需要先将其[删除](#removing-an-existing-zoom-meeting-from-an-issue) . + +## Removing an existing Zoom meeting from an issue[](#removing-an-existing-zoom-meeting-from-an-issue "Permalink") + +与添加缩放会议类似,您可以通过快速操作将其删除: + +``` +/remove_zoom +``` + +如果您至少具有[Reporter 权限](../../permissions.html) ,系统警报将通知您会议 URL 已成功删除. \ No newline at end of file diff --git a/_book/docs/112.md b/_book/docs/112.md new file mode 100644 index 0000000000000000000000000000000000000000..51e66d42e4fc1a9ddd75c96c4d449d5b47ffdd94 --- /dev/null +++ b/_book/docs/112.md @@ -0,0 +1,91 @@ +# Merge requests + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/](https://docs.gitlab.com/ee/user/project/merge_requests/) + +* [Use cases](#use-cases) +* [Overview](#overview) +* [Merge request navigation tabs at the top](#merge-request-navigation-tabs-at-the-top) +* [Creating merge requests](#creating-merge-requests) +* [Reviewing and managing merge requests](#reviewing-and-managing-merge-requests) +* [Testing and reports in merge requests](#testing-and-reports-in-merge-requests) +* [Authorization for merge requests](#authorization-for-merge-requests) + +# Merge requests[](#merge-requests "Permalink") + +合并请求使您可以可视化并协作对作为对指定 Git 分支的提交而存在的源代码的建议更改. + +[![Merge request view](img/44dfa1e85103f88c82598a4ef9f8d0ae.png)](img/merge_request.png) + +合并请求( **MR** )是 GitLab 作为代码协作和版本控制平台的基础. 顾名思义,它就是一个*将*一个分支*合并*到另一个分支的*请求* . + +## Use cases[](#use-cases "Permalink") + +答:考虑您是一个团队中的软件开发人员: + +1. 您签出新分支,并通过合并请求提交更改 +2. 您从团队中收集反馈 +3. 您可以使用["代码质量"报告来进行](code_quality.html)优化代码的实现 +4. 您可以在 GitLab CI / CD 中使用[JUnit 测试报告](../../../ci/junit_test_reports.html)来验证您的更改 +5. 通过" [许可证合规性"报告,](../../compliance/license_compliance/index.html)可以避免使用许可证与您的项目不兼容的依赖项 +6. 您要求您的经理[批准](merge_request_approvals.html) +7. 您的经理: + 1. 推动提交并进行最终审查 + 2. [批准合并请求](merge_request_approvals.html) + 3. 将其设置为[在管道成功时合并](merge_when_pipeline_succeeds.html) +8. 您的更改将通过[手动操作](../../../ci/yaml/README.html#whenmanual) GitLab CI / CD 部署到生产中 +9. 您的实施已成功交付给客户 + +B.考虑您是为您公司网站编写网页的 Web 开发人员: + +1. 您签出新分支,并通过合并请求提交新页面 +2. 您从审稿人那里收集反馈 +3. 您的更改将通过[Review Apps](../../../ci/review_apps/index.html)进行预览 +4. 您要求您的网页设计师实施 +5. 您要求您的经理[批准](merge_request_approvals.html) +6. 一旦批准,您的合并请求将被[压缩和合并](squash_and_merge.html) ,并[部署到带有 GitLab 页面的暂存中](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/) +7. 您的生产团队[选择](cherry_pick_changes.html)合并提交到生产中 + +## Overview[](#overview "Permalink") + +合并请求(也称为" MR")显示有关建议的更改的大量信息. MR 的主体包含其描述以及其小部件(显示有关 CI / CD 管道的信息,如果存在的话),然后是与该 MR 合作的人员的讨论线程. + +MR 还包含导航选项卡,从中可以查看线程上正在进行的讨论,提交列表,管道和作业列表,代码更改以及内联代码审阅. + +首先,请阅读[合并请求简介](getting_started.html) . + +## Merge request navigation tabs at the top[](#merge-request-navigation-tabs-at-the-top "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33813) . 此定位是实验性的. + +到目前为止,在合并请求窗口小部件之后,位于合并请求中以显示" **讨论区"** ," **提交"** ," **管道** "和" **更改"**的导航选项卡. + +To facilitate this navigation without having to scroll up and down through the page to find these tabs, based on user feedback, we’re experimenting with a new positioning of these tabs. They are now located at the top of the merge request, with a new **Overview** tab, containing the description of the merge request followed by the widget. Next to **Overview**, you can find **Pipelines**, **Commits**, and **Changes**. + +[![Merge request tab positions](img/9e7b70cdf92b88509713225035e8e964.png)](img/merge_request_tab_position_v12_6.png) + +请注意,此更改当前位于默认情况下启用的功能标志之后. 对于自我管理的实例,GitLab 管理员可以通过 Rails 控制台使用以下命令将其禁用: + +``` +Feature.disable(:mr_tabs_position) +``` + +## Creating merge requests[](#creating-merge-requests "Permalink") + +Learn [how to create a merge request](creating_merge_requests.html). + +## Reviewing and managing merge requests[](#reviewing-and-managing-merge-requests "Permalink") + +查看可使用的功能来[查看和管理合并请求](reviewing_and_managing_merge_requests.html) . + +## Testing and reports in merge requests[](#testing-and-reports-in-merge-requests "Permalink") + +了解有关合并请求中的[测试](testing_and_reports_in_merge_requests.html)选项[和报告](testing_and_reports_in_merge_requests.html)更改的信息. + +## Authorization for merge requests[](#authorization-for-merge-requests "Permalink") + +使用 GitLab 进行合并请求的主要方法有两种: + +1. 在单个存储库中使用[受保护的分支](../protected_branches.html) +2. 使用权威项目的分支 + +[Learn more about the authorization for merge requests.](authorization_for_merge_requests.html) \ No newline at end of file diff --git a/_book/docs/113.md b/_book/docs/113.md new file mode 100644 index 0000000000000000000000000000000000000000..7b1fff144ab4ea316b87b28e7f1a46047c9a4b3e --- /dev/null +++ b/_book/docs/113.md @@ -0,0 +1,61 @@ +# Allow collaboration on merge requests across forks + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/allow_collaboration.html](https://docs.gitlab.com/ee/user/project/merge_requests/allow_collaboration.html) + +* [Enabling commit edits from upstream members](#enabling-commit-edits-from-upstream-members) +* [Pushing to the fork as the upstream member](#pushing-to-the-fork-as-the-upstream-member) + +# Allow collaboration on merge requests across forks[](#allow-collaboration-on-merge-requests-across-forks "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17395) . + +当用户从派生打开合并请求时,将为他们提供允许上游成员在源分支上与其进行协作的选项. 这使上游项目的成员可以在合并之前进行小规模修复或重新分支,从而减少了接受外部贡献的来回过程. + +此功能可用于可公开访问的分支项目之间的合并请求. + +为合并请求启用后,对项目目标分支具有合并访问权限的成员将被授予对合并请求的源分支的写权限. + +## Enabling commit edits from upstream members[](#enabling-commit-edits-from-upstream-members "Permalink") + +只有具有对源项目的推送访问权限的用户才能启用该功能,并且只有在合并请求打开时才能持续使用. 启用后,上游成员也将能够重试合并请求的管道和作业: + +1. 在创建或编辑合并请求时启用贡献. + + [![Enable contribution](img/3794ce06aeeb9528fa1a66915cc69072.png)](img/allow_collaboration.png) + +2. 创建合并请求后,您将看到允许可以合并到目标分支的成员的提交. + + [![Check that contribution is enabled](img/381cb6fd4ceed7b2a8b3642926cb8cf2.png)](img/allow_collaboration_after_save.png) + +## Pushing to the fork as the upstream member[](#pushing-to-the-fork-as-the-upstream-member "Permalink") + +如果合并请求的创建者启用了上游成员的贡献,则可以直接推送到派生存储库的分支. + +假如说: + +* 分叉的项目 URL 为`git@gitlab.com:thedude/awesome-project.git` . +* 合并请求的分支是`update-docs` . + +流程如下所示: + +1. 首先,您需要获取合并请求已引入的更改. 单击" **签出"分支**按钮,其中包含可以运行的一些预填充命令. + + [![Check out branch button](img/e9dbc908a405f57008dbb80d1b8a9a70.png)](img/checkout_button.png) + +2. 使用复制按钮复制第一个命令并将其粘贴到您的终端中: + + ``` + git fetch git@gitlab.com:thedude/awesome-project.git update-docs + git checkout -b thedude-awesome-project-update-docs FETCH_HEAD + ``` + + 这将获取派生项目的分支,然后基于所获取的分支创建本地分支. + +3. Make any changes you want and commit. +4. 推送到分叉的项目: + + ``` + git push git@gitlab.com:thedude/awesome-project.git thedude-awesome-project-update-docs:update-docs + ``` + + 注意冒号( `:`两个分支之间). 上面的命令会将本地分支`thedude-awesome-project-update-docs` `git@gitlab.com:thedude/awesome-project.git`存储库的`update-docs`分支. \ No newline at end of file diff --git a/_book/docs/114.md b/_book/docs/114.md new file mode 100644 index 0000000000000000000000000000000000000000..ac13a596d8ffc0c835e810a721bb5801d3e72219 --- /dev/null +++ b/_book/docs/114.md @@ -0,0 +1,246 @@ +# Merge Request Approvals + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) + +* [Optional Approvals](#optional-approvals-core-only) +* [Required Approvals](#required-approvals-starter) + * [Approval Rules](#approval-rules) + * [Eligible Approvers](#eligible-approvers) + * [Implicit Approvers](#implicit-approvers) + * [Code Owners as eligible approvers](#code-owners-as-eligible-approvers) + * [Adding / editing a default approval rule](#adding--editing-a-default-approval-rule) + * [Editing / overriding approval rules per merge request](#editing--overriding-approval-rules-per-merge-request) + * [Multiple approval rules](#multiple-approval-rules-premium) + * [Scoped to Protected Branch](#scoped-to-protected-branch-premium) + * [Adding or removing an approval](#adding-or-removing-an-approval) + * [Merge request approvals project settings](#merge-request-approvals-project-settings) + * [Prevent overriding default approvals](#prevent-overriding-default-approvals) + * [Resetting approvals on push](#resetting-approvals-on-push) + * [Allowing merge request authors to approve their own merge requests](#allowing-merge-request-authors-to-approve-their-own-merge-requests) + * [Prevent approval of merge requests by their committers](#prevent-approval-of-merge-requests-by-their-committers) + * [Require authentication when approving a merge request](#require-authentication-when-approving-a-merge-request) + * [Security approvals in merge requests](#security-approvals-in-merge-requests-ultimate) + * [Enabling the new approvals interface](#enabling-the-new-approvals-interface) + +# Merge Request Approvals[](#merge-request-approvals "Permalink") + +代码审查是每个成功项目的基本实践,一旦合并请求状态良好,就需要您的批准,这是审查过程的重要组成部分,因为它清楚地传达了合并变更的能力. + +## Optional Approvals[](#optional-approvals-core-only "Permalink") + +在[GitLab Core 13.2 中](https://gitlab.com/gitlab-org/gitlab/-/issues/27426)引入. + +具有开发者[权限](../../permissions.html)或更高[权限的](../../permissions.html)任何用户都可以在 GitLab Core 中批准合并请求. 这为审阅者提供了一种一致的机制来提供批准,并使维护者更容易知道何时可以合并更改. Core 中的批准是可选的,并且在没有批准的情况下不会阻止合并请求的合并. + +## Required Approvals[](#required-approvals-starter "Permalink") + +在[GitLab 企业版 7.12 中](https://about.gitlab.com/releases/2015/06/22/gitlab-7-12-released/#merge-request-approvers-ee-only)引入. + +必需的批准通过要求指定的人在可以合并的合并请求之前批准,可以强制执行代码审查. + +所需的批准可启用多个用例: + +* 强制审查所有合并到存储库中的代码. +* 通过[批准规则](#approval-rules)指定给定提议的代码更改的审核者,以及最少数量的审核者. +* 为所有建议的代码更改指定审阅者的类别,例如后端,前端,质量保证,数据库等. +* 由合并请求中更改的文件确定,自动将[代码所有者](#code-owners-as-eligible-approvers)指定[为合格的批准者](#code-owners-as-eligible-approvers) . +* 在合并可能引入漏洞的代码之前, [需要获得安全团队的批准](#security-approvals-in-merge-requests-ultimate) . + +### Approval Rules[](#approval-rules "Permalink") + +批准规则定义了合并请求在可以合并之前必须获得多少个批准,以及可选地应该由哪些用户进行批准. 可以定义批准: + +* [As project defaults](#adding--editing-a-default-approval-rule). +* [Per merge request](#editing--overriding-approval-rules-per-merge-request). + +如果未定义批准规则,则任何用户都可以批准合并请求,尽管仍可以在[项目设置中为合并请求批准设置](#merge-request-approvals-project-settings)所需批准者的默认最小数量. + +批准规则定义了合并请求在可以合并之前必须获得多少个批准,以及可选地应该由哪些用户进行批准. 可以定义批准: + +* [As project defaults](#adding--editing-a-default-approval-rule). +* [Per merge request](#editing--overriding-approval-rules-per-merge-request). + +如果未定义批准规则,则任何用户都可以批准合并请求,尽管仍可以在[项目设置中为合并请求批准设置](#merge-request-approvals-project-settings)所需批准者的默认最小数量. + +#### Eligible Approvers[](#eligible-approvers "Permalink") + +以下用户可以批准合并请求: + +* 在项目中被添加为批准者的用户,或将请求级别与开发者或更高[权限](../../permissions.html)合并的[用户](../../permissions.html) . +* 由合并请求更改的具有开发人员或更高[权限](../../permissions.html)的文件的[代码所有者](#code-owners-as-eligible-approvers) . + +如果单个用户是以下成员的成员,则可以将其添加为项目的批准者: + +* 该项目. +* 该项目的直接上级组. +* 可以通过[共享](../members/share_project_with_groups.html)访问项目的组. + +也可以将一组用户添加为批准者. 将来,小组批准者可能只[限于对项目具有共享访问权限的小组](https://gitlab.com/gitlab-org/gitlab/-/issues/2048) . + +如果将用户添加为个人批准者,并且也是组批准者的一部分,则该用户仅被计数一次. 如果在项目设置上启用了" [**阻止作者批准"**](#allowing-merge-request-authors-to-approve-their-own-merge-requests) (默认情况下启用)和" [**阻止提交者批准"**](#prevent-approval-of-merge-requests-by-their-committers) (默认情况下禁用),则合并请求作者以及已提交合并请求的用户均不算作合格批准者. + +##### Implicit Approvers[](#implicit-approvers "Permalink") + +如果所需批准的数量大于分配的批准者的数量,则来自其他用户的批准将计入满足要求. 这些将是在项目中具有开发人员[权限](../../permissions.html)或更高[权限的](../../permissions.html)用户,但未在批准规则中明确列出. + +##### Code Owners as eligible approvers[](#code-owners-as-eligible-approvers "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7933) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.5. + +如果将[代码所有者](../code_owners.html)添加到存储库中,则相应文件的所有者将与具有 Developer 或更高[权限的](../../permissions.html)成员一起成为合格的批准者. + +要启用此合并请求批准规则: + +1. 导航到项目的**"设置">"常规",**然后展开" **合并请求批准"** . +2. 找到**任何合格的用户,**然后选择所需的批准数量. + +[![MR approvals by Code Owners](img/6a2d24148988c584ff47ac7c526b48ff.png)](img/mr_approvals_by_code_owners_v12_7.png) + +设置后,合并请求只能在您设置的批准数量批准后才能合并. manbetx 客户端打不开将毫无区别地接受来自具有开发者或更高权限的用户以及代码所有者的批准. + +或者,您可以**要求** [保护所有者的代码所有者批准](../protected_branches.html#protected-branches-approval-by-code-owners-premium) . + +#### Adding / editing a default approval rule[](#adding--editing-a-default-approval-rule "Permalink") + +要添加或编辑默认的合并请求批准规则: + +1. 导航到您项目的 **设置>常规,**然后展开**合并请求批准** . + +2. 单击**添加批准规则** ,或单击**编辑** . + * 添加或更改**规则名称** . + * 设置**所需的批准号**所需的批准数量. 最小值是`0` . + * (可选)搜索有[资格批准](#eligible-approvers)合并请求的用户或组,然后单击" **添加"**按钮将其添加为批准者. 在搜索字段中键入之前,将根据合并请求更改的文件的先前作者来建议批准者. + * (可选)点击 组或用户旁边的" **删除"**按钮可将其从规则中删除. +3. Click **添加批准规则** or **更新批准规则**. + +在更改规则之前创建的任何合并请求都不会更改. 他们将保留原始批准规则,除非手动[覆盖](#editing--overriding-approval-rules-per-merge-request) . + +**注意:**如果合并请求的目标是其他项目,例如从分支到上游项目,则默认批准规则将从目标(上游)项目而不是源(叉子)获取. + +##### Editing / overriding approval rules per merge request[](#editing--overriding-approval-rules-per-merge-request "Permalink") + +在 GitLab 企业版 9.4 中引入. + +默认情况下,MR 作者或具有足够[权限](../../permissions.html)的用户可以编辑每个合并请求(MR)中列出的合并请求批准规则. 可以在[合并请求批准设置中](#prevent-overriding-default-approvals)禁用此功能. + +一种可能的情况是添加比默认设置中定义更多的批准者. + +创建或编辑合并请求时,请找到" **批准规则"**部分,然后按照与[添加/编辑默认批准规则](#adding--editing-a-default-approval-rule)相同的步骤进行操作. + +#### Multiple approval rules[](#multiple-approval-rules-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1979) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.10. + +在 GitLab Premium 中,每个合并请求可以有多个批准规则,每个项目可以有多个默认批准规则. + +添加或编辑多个默认规则与[添加或编辑单个默认批准规则相同](#adding--editing-a-default-approval-rule) ,不同之处在于,即使已经定义了规则," **添加批准规则"**按钮仍可用于添加更多规则. + +同样,每个合并请求中编辑或覆盖多个批准规则与每个合并请求中[编辑或覆盖批准规则](#editing--overriding-approval-rules-per-merge-request)相同,只是即使已定义一个规则," **添加批准规则"**按钮仍可用于添加更多规则. + +当[合格的批准人](#eligible-approvers)批准合并请求时,它将减少批准人所属的所有规则的剩余批准数. + +[![Approvals premium merge request widget](img/b1b6eda7a121cb284375e6c83317263d.png)](img/approvals_premium_mr_widget_v12_7.png) + +#### Scoped to Protected Branch[](#scoped-to-protected-branch-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.8. + +批准规则通常仅与特定分支(例如`master` . 在配置[**默认批准规则时,**](#adding--editing-a-default-approval-rule)可以通过导航到项目的**"设置"** ,展开" **合并请求批准"** ,然后从" **目标"分支**下拉列表中选择" **任何"分支** ,将这些作用域一下子作用于所有受保护的分支. + +或者,您可以从" **目标"分支**下拉列表中选择一个非常特定的受保护分支: + +[![Scoped to Protected Branch](img/439a9c21f68de25b8a16d0d0a28d19be.png)](img/scoped_to_protected_branch_v12_8.png) + +要启用此配置,请参阅[代码所有者对受保护分支的批准](../protected_branches.html#protected-branches-approval-by-code-owners-premium) . + +### Adding or removing an approval[](#adding-or-removing-an-approval "Permalink") + +当[合格的批准者](#eligible-approvers)访问一个开放合并请求时,可能是以下之一: + +* 如果所需的批准数目*尚未*满足,他们可以通过点击批准它显示的**批准**按钮. + + [![Approve](img/45cc34490ebcb0a656d7c57d3dcbbb00.png)](img/approve.png) + +* 如果已经满足所需的批准数量,则他们仍然可以通过单击显示的**"额外批准"**按钮来**批准** . + + [![Add approval](img/a3b1935e9fe6f6222ef3200715c2f595.png)](img/approve_additionally.png) + +* **他们已经批准了此合并请求** :他们可以删除他们的批准. + + [![Remove approval](img/aabf40f234d995e031a5a1a0f66b5905.png)](img/remove_approval.png) + +**注意:**如果在项目设置中启用了" [**阻止作者批准",**](#allowing-merge-request-authors-to-approve-their-own-merge-requests)则不允许合并请求作者批准自己的合并请求. + +满足批准规则后,如果没有其他阻止请求,则可以合并合并请求. 请注意,合并请求仍可能被其他条件阻止,例如合并冲突, [挂起的讨论](../../discussions/index.html#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved)或[失败的 CI / CD 管道](merge_when_pipeline_succeeds.html) . + +### Merge request approvals project settings[](#merge-request-approvals-project-settings "Permalink") + +可以通过以下步骤找到合并请求批准的项目设置: **设置>常规**和扩展**合并请求批准** . + +#### Prevent overriding default approvals[](#prevent-overriding-default-approvals "Permalink") + +默认情况下,用户可以在合并请求中编辑批准规则. 如果禁用,则所有新合并请求的[批准规则](#adding--editing-a-default-approval-rule)将由[默认批准规则](#adding--editing-a-default-approval-rule)确定. 要禁用此功能: + +1. 取消选中**可以覆盖每个合并请求所需的批准人和批准**复选框. +2. Click **保存更改**. + +#### Resetting approvals on push[](#resetting-approvals-on-push "Permalink") + +当新的提交被推送到合并请求的源分支时,您可以强制删除对合并请求的所有批准. 如果禁用,则即使合并请求中添加了更改,批准也将持续. 要启用此功能: + +1. Check the **将新提交推送到其源分支时,删除合并请求中的所有批准** checkbox. +2. Click **保存更改**. + +**注意:**重新定义来自 UI [的合并请求](fast_forward_merge.html)时,批准不会重置. 但是,如果更改了目标分支,则批准将被重置. + +#### Allowing merge request authors to approve their own merge requests[](#allowing-merge-request-authors-to-approve-their-own-merge-requests "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3349) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.3. + +您可以允许合并请求作者自行批准合并请求. 作者也必须包含在批准者列表中,以便能够批准其合并请求. 要启用此功能: + +1. 取消选中" **阻止合并请求作者批准合并请求"**复选框,默认情况下启用此复选框. +2. Click **保存更改**. + +#### Prevent approval of merge requests by their committers[](#prevent-approval-of-merge-requests-by-their-committers "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10441) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.10. + +您可以阻止已提交合并请求的用户批准它. 要启用此功能: + +1. 选中**阻止提交者批准合并请求**复选框. +2. Click **保存更改**. + +#### Require authentication when approving a merge request[](#require-authentication-when-approving-a-merge-request "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5981) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.0. + +**注意:**要在批准合并请求时要求身份验证,必须在[登录限制](../../admin_area/settings/sign_in_restrictions.html#password-authentication-enabled)下**启用为 Web 界面**启用的**密码身份验证** . 在管理区域中. + +您可以强制批准者输入密码以进行身份​​验证,然后再添加批准. 这使电子签名能够获得批准,例如[CFR Part 11](https://www.accessdata.fda.gov/scripts/cdrh/cfdocs/cfcfr/CFRSearch.cfm?CFRPart=11&showFR=1&subpartNode=21:1.0.1.1.8.3)所定义的签名. 要启用此功能: + +1. 选中**需要用户密码批准**复选框. +2. Click **保存更改**. + +### Security approvals in merge requests[](#security-approvals-in-merge-requests-ultimate "Permalink") + +可以将合并请求批准配置为在合并请求引入漏洞时需要安全团队成员的批准. + +有关更多信息,请参见[合并请求中的安全性批准](../../application_security/index.html#security-approvals-in-merge-requests) . + +### Enabling the new approvals interface[](#enabling-the-new-approvals-interface "Permalink") + +从[GitLab v12.0 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/10685) ,默认情况下会提供更新的批准界面. 在 12.0 之前的版本中,除非启用了`approval_rules`功能标志,否则更新的界面不可用,这可由实例管理员从 Rails 控制台中完成. + +使用以下命令来启动 Rails 控制台: + +``` +# Omnibus GitLab +gitlab-rails console + +# Installation from source +cd /home/git/gitlab +sudo -u git -H bin/rails console -e production +``` + +然后运行`Feature.enable(:approval_rules)`以启用更新的界面. \ No newline at end of file diff --git a/_book/docs/115.md b/_book/docs/115.md new file mode 100644 index 0000000000000000000000000000000000000000..f77f4cd3fc99e1506cc2e394e97f03dc2a4eb22b --- /dev/null +++ b/_book/docs/115.md @@ -0,0 +1,203 @@ +# Browser Performance Testing + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html](https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [How browser performance testing works](#how-browser-performance-testing-works) +* [Configuring Browser Performance Testing](#configuring-browser-performance-testing) + * [Configuring degradation threshold](#configuring-degradation-threshold) + * [Performance testing on Review Apps](#performance-testing-on-review-apps) + * [GitLab versions 12.3 and older](#gitlab-versions-123-and-older) + +# Browser Performance Testing[](#browser-performance-testing-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3507) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.3. + +如果您的应用程序提供 Web 界面,并且您正在使用[GitLab CI / CD](../../../ci/README.html) ,则可以快速确定浏览器中待处理代码更改对渲染性能的影响. + +## Overview[](#overview "Permalink") + +GitLab 使用[Sitespeed.io](https://www.sitespeed.io) (一种免费的开源工具)来测量网站的渲染性能. GitLab 构建的[Sitespeed 插件](https://gitlab.com/gitlab-org/gl-performance)在名为`browser-performance.json`的文件中输出所分析的每个页面的性能得分,该数据可以显示在合并请求中. + +## Use cases[](#use-cases "Permalink") + +考虑以下工作流程: + +1. 营销团队的成员正在尝试通过添加新工具来跟踪参与度. +2. 通过浏览器性能指标,他们可以看到他们的更改如何影响最终用户页面的可用性. +3. 指标显示,更改后,页面的性能得分有所下降. +4. 查看详细报告时,他们看到`<head>`包含了新的 JavaScript 库,这会影响加载页面的速度. +5. 他们向前端开发人员寻求帮助,他们将库设置为异步加载. +6. 前端开发人员批准合并请求,并授权将其部署到生产中. + +## How browser performance testing works[](#how-browser-performance-testing-works "Permalink") + +首先,在`.gitlab-ci.yml`文件中定义一个生成[浏览器性能报告工件的作业](../../../ci/pipelines/job_artifacts.html#artifactsreportsperformance-premium) . 然后,GitLab 会检查此报告,比较源分支和目标分支之间每一页的关键性能指标,并在合并请求中显示信息. + +有关性能作业的示例,请参阅" [配置浏览器性能测试"](#configuring-browser-performance-testing) . + +**注意:**如果"浏览器性能"报告没有可比较的数据,例如,当您第一次在`.gitlab-ci.yml`添加"浏览器性能"作业时,"浏览器性能"报告小部件将不会显示. 它必须在目标分支(例如`master` )上至少运行一次,然后才能在针对该分支的合并请求中显示. + +[![Browser Performance Widget](img/c7a5bc700a43a5880572c7f8cc0acdc7.png)](img/browser_performance_testing.png) + +## Configuring Browser Performance Testing[](#configuring-browser-performance-testing "Permalink") + +这个例子显示如何运行[sitespeed.io 容器](https://hub.docker.com/r/sitespeedio/sitespeed.io/)使用 GitLab CI / CD 上的代码和[sitespeed.io](https://www.sitespeed.io)使用泊坞窗功能于泊坞窗. + +1. 首先,使用[Docker-in-Docker 构建](../../../ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor)设置 GitLab Runner. +2. 在`.gitlab-ci.yml`文件中,按如下所示配置默认的浏览器性能测试 CI 作业: + + ``` + include: + template: Verify/Browser-Performance.gitlab-ci.yml + + performance: + variables: + URL: https://example.com + ``` + +**注意:**对于 12.4 之前的版本,请参阅[旧版 GitLab](#gitlab-versions-123-and-older)的信息. 如果您正在使用 Kubernetes 集群,请使用[`template: Jobs/Browser-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml) . + +上面的示例在 CI / CD 管道中创建了一个`performance`作业,并针对您在`URL`定义的网页运行 sitespeed.io 以收集关键指标. + +该示例使用的 CI / CD 模板自 12.4 起已包含在所有 GitLab 安装中,但不适用于 Kubernetes 集群. 如果您使用的是 GitLab 12.3 或更早版本,则必须[手动添加配置](#gitlab-versions-123-and-older) + +该模板将[GitLab 插件用于 sitespeed.io](https://gitlab.com/gitlab-org/gl-performance) ,并将完整的 HTML sitespeed.io 报告保存为" [浏览器性能"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsperformance-premium) ,您可以稍后下载和分析该[工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsperformance-premium) . 此实现始终采用最新的浏览器性能工件. 如果启用了[GitLab Pages,](../pages/index.html)则可以直接在浏览器中查看报告. + +您还可以使用环境变量自定义作业: + +* `SITESPEED_IMAGE` :配置要用于作业的 Docker 映像(默认为`sitespeedio/sitespeed.io` ),而不是映像版本. +* `SITESPEED_VERSION` :配置要用于作业的 Docker 映像的版本(默认`13.3.0` ). +* `SITESPEED_OPTIONS` :根据需要配置任何其他 sitespeed.io 选项(默认为`nil` ). 有关更多详细信息,请参阅[sitespeed.io 文档](https://www.sitespeed.io/documentation/sitespeed.io/configuration/) . + +For example, you can override the number of runs sitespeed.io makes on the given URL, and change the version: + +``` +include: + template: Verify/Browser-Performance.gitlab-ci.yml + +performance: + variables: + URL: https://www.sitespeed.io/ + SITESPEED_VERSION: 13.2.0 + SITESPEED_OPTIONS: -n 5 +``` + +### Configuring degradation threshold[](#configuring-degradation-threshold "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27599) . + +您可以配置降级警报的敏感度,以避免针对度量指标的小幅下降获得警报. 这是通过设置`DEGRADATION_THRESHOLD`变量来完成的. 在以下示例中,仅当" `Total Score`指标下降 5 分或更多时,才会显示警报: + +``` +include: + template: Verify/Browser-Performance.gitlab-ci.yml + +performance: + variables: + URL: https://example.com + DEGRADATION_THRESHOLD: 5 +``` + +`Total Score`指标基于 sitespeed.io 的[教练表现得分](https://www.sitespeed.io/documentation/sitespeed.io/metrics/#performance-score) . 在[教练文档中](https://www.sitespeed.io/documentation/coach/how-to/#what-do-the-coach-do)有更多信息. + +### Performance testing on Review Apps[](#performance-testing-on-review-apps "Permalink") + +上面的 CI YAML 配置非常适合在静态环境下进行测试,并且可以扩展为动态环境,但是还需要一些额外的步骤: + +1. `performance`作业应在动态环境启动后运行. +2. 在`review`工作中: + 1. 生成带有动态 URL 的 URL 列表文件. + 2. 将文件另存为工件,例如,在作业`script`使用`echo $CI_ENVIRONMENT_URL > environment_url.txt` . + 3. 将列表作为 URL 环境变量(可以是 URL 或包含 URL 的文件)传递给`performance`作业. +3. 现在,您可以针对所需的主机名和路径运行 sitespeed.io 容器. + +您的`.gitlab-ci.yml`文件如下所示: + +``` +stages: + - deploy + - performance + +include: + template: Verify/Browser-Performance.gitlab-ci.yml + +review: + stage: deploy + environment: + name: review/$CI_COMMIT_REF_SLUG + url: http://$CI_COMMIT_REF_SLUG.$APPS_DOMAIN + script: + - run_deploy_script + - echo $CI_ENVIRONMENT_URL > environment_url.txt + artifacts: + paths: + - environment_url.txt + only: + - branches + except: + - master + +performance: + dependencies: + - review + variables: + URL: environment_url.txt +``` + +### GitLab versions 12.3 and older[](#gitlab-versions-123-and-older "Permalink") + +自推出以来,浏览器性能测试经历了几处更改. 在本节中,我们将详细介绍这些更改以及如何基于 GitLab 版本运行测试: + +* 在 GitLab 12.4 中提供[了一个工作模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml) . +* 在 13.2 中,使用其他模板变量将该功能从`Performance`重命名为`Browser Performance` . 出于兼容性原因,模板中的作业名称仍然是`performance` ,但可以在以后的迭代中重命名以匹配. +* 对于 11.5 至 12.3,没有可用的模板,必须按以下方式手动定义作业: + +``` +performance: + stage: performance + image: docker:git + variables: + URL: https://example.com + SITESPEED_VERSION: 13.3.0 + SITESPEED_OPTIONS: '' + services: + - docker:stable-dind + script: + - mkdir gitlab-exporter + - wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/master/index.js + - mkdir sitespeed-results + - docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --outputFolder sitespeed-results $URL $SITESPEED_OPTIONS + - mv sitespeed-results/data/performance.json performance.json + artifacts: + paths: + - performance.json + - sitespeed-results/ + reports: + performance: performance.json +``` + +* 对于 11.4 和更早版本,应按以下方式定义作业: + +``` +performance: + stage: performance + image: docker:git + variables: + URL: https://example.com + services: + - docker:stable-dind + script: + - mkdir gitlab-exporter + - wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/master/index.js + - mkdir sitespeed-results + - docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results $URL + - mv sitespeed-results/data/performance.json performance.json + artifacts: + paths: + - performance.json + - sitespeed-results/ +``` + +建议升级到最新版本并使用模板,以确保您收到最新更新,包括对 sitespeed.io 版本的更新. \ No newline at end of file diff --git a/_book/docs/116.md b/_book/docs/116.md new file mode 100644 index 0000000000000000000000000000000000000000..0a97cf1bf023d132266847ae70baecc276a17b9f --- /dev/null +++ b/_book/docs/116.md @@ -0,0 +1,160 @@ +# How to create a merge request + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) + +* [New Merge Request page](#new-merge-request-page) +* [Create Merge Request button](#create-merge-request-button) +* [New merge request by adding, editing, and uploading a file](#new-merge-request-by-adding-editing-and-uploading-a-file) +* [New merge request from a new branch created through the UI](#new-merge-request-from-a-new-branch-created-through-the-ui) +* [New merge request from your local environment](#new-merge-request-from-your-local-environment) +* [New merge request from an issue](#new-merge-request-from-an-issue) +* [New merge request from the Merge Requests page](#new-merge-request-from-the-merge-requests-page) +* [New merge request from a fork](#new-merge-request-from-a-fork) +* [New merge request by email](#new-merge-request-by-email-core-only) + * [Adding patches when creating a merge request via e-mail](#adding-patches-when-creating-a-merge-request-via-e-mail) +* [Reviewing and managing Merge Requests](#reviewing-and-managing-merge-requests) + +# How to create a merge request[](#how-to-create-a-merge-request "Permalink") + +在创建合并请求之前,请通读"合并请求"的[简介,](getting_started.html)以熟悉概念,术语并了解如何使用它们. + +每个合并请求都从创建一个分支开始. 您可以通过[命令行](#new-merge-request-from-your-local-environment) ,Git CLI 应用程序或[GitLab UI](#new-merge-request-from-a-new-branch-created-through-the-ui)在本地进行操作. + +本文档介绍了创建合并请求的几种方法. + +启动新的合并请求时,无论使用哪种方法,都将转到" [**新合并请求"**页面,](#new-merge-request-page)以在其中添加有关合并请求的信息. + +如果将新分支推送到 GitLab,也不管使用哪种方法,都可以单击[**Create Merge Request**](#create-merge-request-button)按钮并从此处启动合并请求. + +## New Merge Request page[](#new-merge-request-page "Permalink") + +在" **新合并请求"**页面上,首先填写**合并请求**的标题和描述. 如果分支上已经有提交,则标题将用第一条提交消息的第一行预填充,描述将用提交消息中的任何其他行预填充. 在所有情况下,标题都是唯一的必填字段. + +在此处,您可以在其中填充信息(标题,描述,受让人,里程碑,标签,批准人),然后点击**创建合并请求** . + +在初始屏幕上,您还可以查看提交合并请求之前推送到分支的所有提交,管道和文件更改. + +[![New Merge Request page](img/9255a795b62eb0bbe1c91eab2f85c149.png)](img/new_merge_request_page_v12_6.png) + +**提示:**您可以在创建合并请求之前将一次或多次推送到 GitLab 中的分支. + +## Create Merge Request button[](#create-merge-request-button "Permalink") + +将新分支推送到 GitLab 后,请访问 GitLab 中的存储库,并在屏幕顶​​部看到一个号召性用语,您可以从中单击**创建合并请求**按钮. + +[![Create Merge Request button](img/2257f7989872604ba6ce6506ba811b15.png)](img/create_merge_request_button_v12_6.png) + +您还可以在以下页面的右上方看到" **创建合并请求"**按钮: + +* **Project** page. +* **资料库>文件** page. +* **合并请求** page. + +In this case, GitLab will use the most recent branch you pushed changes to as the source branch, and the default branch in the current project as the target. + +## New merge request by adding, editing, and uploading a file[](#new-merge-request-by-adding-editing-and-uploading-a-file "Permalink") + +当您选择通过 GitLab UI 编辑,添加或上传文件时,在文件末尾,您会看到以下选项:添加**Commit 消息** ,选择该**提交**的**Target 分支** ,然后选中**Start new**复选框. **具有这些更改的合并请求** . + +同样,如果通过 Web IDE 更改文件,则在左侧边栏中导航到" **提交"**时,将看到这些相同的选项. + +添加,编辑或上传文件后,请执行以下操作: + +1. 在提交消息中描述您的更改. +2. 选择一个现有分支以将您的提交添加到其中,或者,如果您想创建一个新分支,请键入新的分支名称(不带空格,大写字母或特殊字符). +3. 保持选中复选框以立即开始新的合并请求,或者取消选中该复选框以在开始合并请求之前向该分支添加更多更改. +4. Click **提交变更**. + +如果您选择开始合并请求,则将转到" [**新合并请求"**页面](#new-merge-request-page) ,您可以在其中填写信息并提交合并请求. + +合并请求将针对存储库的默认分支. 如果要更改它,可以稍后通过编辑合并请求来进行更改. + +## New merge request from a new branch created through the UI[](#new-merge-request-from-a-new-branch-created-through-the-ui "Permalink") + +要通过 GitLab UI 快速开始处理文件,请导航至项目的" **存储库">"分支"** ,然后单击" **新建分支"** . 将创建一个新分支,您可以开始编辑文件. + +提交并推送后,您可以单击" [**创建合并请求"**](#create-merge-request-button)按钮以打开" [**新合并请求"**页面](#new-merge-request-page) . 将使用当前分支作为源,并使用当前项目中的默认分支作为目标来启动新的合并请求. + +## New merge request from your local environment[](#new-merge-request-from-your-local-environment "Permalink") + +假设您已将存储库克隆到计算机中,并且想要开始处理文件更改,请先创建并签出一个新分支: + +``` +git checkout -b my-new-branch +``` + +处理文件更改,暂存并提交它们: + +``` +git add . +git commit -m "My commit message" +``` + +完成后, [将分支推送到 GitLab](../../../gitlab-basics/start-using-git.html#send-changes-to-gitlabcom) : + +``` +git push origin my-new-branch +``` + +在输出中,GitLab 将提示您一个直接链接来创建合并请求: + +``` +... +remote: To create a merge request for docs-new-merge-request, visit: +remote: https://gitlab-instance.com/my-group/my-project/merge_requests/new?merge_request%5Bsource_branch%5D=my-new-branch +``` + +复制该链接并将其粘贴到浏览器中,将显示" [**新合并请求"页面**](#new-merge-request-page) . + +在[通过命令行推送时](../push_options.html) , [还可以向命令添加](../push_options.html)一些[标志,](../push_options.html)以减少通过 UI 手动编辑合并请求的需要. + +如果您没有通过命令行将分支推送到 GitLab(例如,您使用 Git CLI 应用程序来推送更改),则可以通过单击" [**创建合并请求"**](#create-merge-request-button)按钮通过 GitLab UI [**创建合并请求**](#create-merge-request-button) . + +## New merge request from an issue[](#new-merge-request-from-an-issue "Permalink") + +您也可以[直接从 issue 创建一个新的合并请求](../repository/web_editor.html#create-a-new-branch-from-an-issue) . + +## New merge request from the Merge Requests page[](#new-merge-request-from-the-merge-requests-page "Permalink") + +您可以通过在项目中的" **合并请求"**页面上单击" **新建合并请求"**按钮来开始创建新的合并请求. 然后选择包含更改的源项目和分支,以及要将更改合并到的目标项目和分支. 单击**比较分支,然后继续**转到" [**新合并请求"**页面](#new-merge-request-page)并填写详细信息. + +## New merge request from a fork[](#new-merge-request-from-a-fork "Permalink") + +分叉项目并应用本地更改后,请完成以下步骤,从您的 fork 创建一个合并请求以贡献回主项目: + +1. 转到**项目>您的项目,**然后选择存储库的分支. +2. 在左侧菜单中,转到**合并请求** ,然后点击**新建合并请求** . +3. 在" **源分支"**下拉列表框中,在分支的存储库中选择您的分支作为源分支. +4. 在" **目标分支"**下拉列表框中,从上游存储库中选择分支作为目标分支. +5. 输入凭据后,单击" **比较分支",然后继续**将本地更改与上游存储库进行比较. +6. 分配用户以查看您的更改,然后点击**提交合并请求** . + +合并更改后,您的更改将按照规范添加到上游存储库和分支中. 合并工作后,如果您不想对上游项目做出任何其他贡献,则可以通过[删除分支关系](../settings/index.html#removing-a-fork-relationship) ,在**Settings> Advanced Settings**部分[中将 fork 与](../settings/index.html#removing-a-fork-relationship)上游项目断开链接. + +有关更多详细信息, [请参阅分叉工作流文档](../repository/forking_workflow.html) . + +## New merge request by email[](#new-merge-request-by-email-core-only "Permalink") + +*要使用此功能,需要由 GitLab 管理员配置[传入电子邮件](../../../administration/incoming_email.html)才能使用.* 它在 GitLab.com 中不可用. + +您可以通过将电子邮件发送到特定于用户的电子邮件地址来创建新的合并请求. 通过单击**将新的合并请求**通过**电子邮件发送到该项目**按钮,可以在合并请求页面上获取地址. 该主题将用作新合并请求的源分支名称,而目标分支将是项目的默认分支. 消息正文(如果不为空)将用作合并请求描述. 您需要启用["通过电子邮件回复"](../../../administration/reply_by_email.html)才能使用此功能. 如果您的实例未启用它,则可以要求您的 GitLab 管理员这样做. + +这是一个私人电子邮件地址,仅为您生成. **将其保存在自己**手中,因为拥有它的任何人都可以像您一样创建问题或合并请求. 您可以将此地址添加到您的联系人列表中以便于访问. + +[![Create new merge requests by email](img/4f0a47acf91c1135738d76e1c06eec3a.png)](img/create_from_email.png) + +*在 GitLab 11.7 中,我们更新了生成的电子邮件地址的格式. 但是,仍支持较旧的格式,从而允许现有别名或联系人继续工作.* + +### Adding patches when creating a merge request via e-mail[](#adding-patches-when-creating-a-merge-request-via-e-mail "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22723) . + +您可以通过将补丁添加为电子邮件的附件,将提交添加到正在创建的合并请求中. 文件名以`.patch`结尾的所有附件都将被视为补丁程序,并将按名称顺序对其进行处理. + +补丁的总大小可以是 2MB. + +如果主题的源分支不存在,那么将从存储库的 HEAD 或指定的目标分支创建源分支以应用补丁. 可以使用[`/target_branch`快速操作](../quick_actions.html)指定目标分支. 如果源分支已经存在,则将在其顶部应用补丁. + +## Reviewing and managing Merge Requests[](#reviewing-and-managing-merge-requests "Permalink") + +提交合并请求后,可以通过 GitLab 进行[审查和管理](reviewing_and_managing_merge_requests.html) . \ No newline at end of file diff --git a/_book/docs/117.md b/_book/docs/117.md new file mode 100644 index 0000000000000000000000000000000000000000..685f2f2319df803cbbeae8d1165d335a2925c3aa --- /dev/null +++ b/_book/docs/117.md @@ -0,0 +1,50 @@ +# Cherry-pick changes + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/cherry_pick_changes.html](https://docs.gitlab.com/ee/user/project/merge_requests/cherry_pick_changes.html) + +* [Cherry-picking a merge request](#cherry-picking-a-merge-request) + * [Cherry-pick tracking](#cherry-pick-tracking) +* [Cherry-picking a commit](#cherry-picking-a-commit) + +# Cherry-pick changes[](#cherry-pick-changes "Permalink") + +GitLab 实现了 Git 的强大功能,通过在合并请求和提交详细信息中引入**Cherry-pick**按钮来[挑选任何提交](https://git-scm.com/docs/git-cherry-pick "Git Cherry-Pick 文档") . + +## Cherry-picking a merge request[](#cherry-picking-a-merge-request "Permalink") + +合并请求合并后,将可以使用**Cherry-pick**按钮来选择该合并请求引入的更改. + +[![Cherry-pick Merge Request](img/fe7d77556848be98a93c7b6516b0e6f8.png)](img/cherry_pick_changes_mr.png) + +单击该按钮后,将出现一个模态,显示一个[分支过滤器搜索框](../repository/branches/index.html#branch-filter-search-box) ,您可以在其中选择: + +* 将更改直接选择到所选分支中. +* 使用经过精心挑选的更改创建一个新的合并请求. + +### Cherry-pick tracking[](#cherry-pick-tracking "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2675) . + +当您选择一个合并提交时,GitLab 将向相关的合并请求线程输出系统注释,使新提交与现有合并请求交联. + +[![Cherry-pick tracking in Merge Request timeline](img/e20aec7ab33bbd61bae4825e6c9e35f1.png)](img/cherry_pick_mr_timeline_v12_9.png) + +每个部署的[关联合并请求列表](../../../api/deployments.html#list-of-merge-requests-associated-with-a-deployment)将包括精心挑选的合并提交. + +**注意:**我们仅跟踪从 GitLab(UI 和 API)执行的 cherry-pick. 计划在将来的发行版中支持[通过命令行跟踪精心挑选的提交](https://gitlab.com/gitlab-org/gitlab/-/issues/202215) . + +## Cherry-picking a commit[](#cherry-picking-a-commit "Permalink") + +您可以从提交详细信息页面中挑选一个提交: + +[![Cherry-pick commit](img/b4e821b8b83e29e837f01f4620e557b7.png)](img/cherry_pick_changes_commit.png) + +与选择合并请求类似,您可以选择将更改直接选择到目标分支中,也可以选择创建新的合并请求以选择更改. + +请注意,在进行樱桃挑选合并提交时,主线将始终是第一父级. 如果要使用其他主线,则需要从命令行执行. + +这是一个使用第二个父级作为主线来挑选合并提交的快速示例: + +``` +git cherry-pick -m 2 7a39eb0 +``` \ No newline at end of file diff --git a/_book/docs/118.md b/_book/docs/118.md new file mode 100644 index 0000000000000000000000000000000000000000..70625d490900a60e01c117d82b0140c67e67ddf9 --- /dev/null +++ b/_book/docs/118.md @@ -0,0 +1,275 @@ +# Code Quality + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html) + +* [Use cases](#use-cases) +* [Example configuration](#example-configuration) + * [Previous job definitions](#previous-job-definitions) +* [Configuring jobs using variables](#configuring-jobs-using-variables) +* [Implementing a custom tool](#implementing-a-custom-tool) +* [Code Quality reports](#code-quality-reports) +* [Extending functionality](#extending-functionality) + * [Using Analysis Plugins](#using-analysis-plugins) +* [Troubleshooting](#troubleshooting) + * [Changing the default configuration has no effect](#changing-the-default-configuration-has-no-effect) + * [No Code Quality report is displayed in a Merge Request](#no-code-quality-report-is-displayed-in-a-merge-request) + * [Only a single Code Quality report is displayed, but more are defined](#only-a-single-code-quality-report-is-displayed-but-more-are-defined) + +# Code Quality[](#code-quality-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1984) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.3. + +确保项目的代码保持简单,易读和易于贡献可能会引起问题. 借助[GitLab CI / CD](../../../ci/README.html) ,您可以使用 GitLab 代码质量分析源代码质量. + +代码质量: + +* 使用[Code Climate Engines](https://codeclimate.com) ,它们是免费的开放源代码. 代码质量不需要"代码气候"订阅. +* 使用[默认的 Code Climate 配置](https://gitlab.com/gitlab-org/ci-cd/codequality/-/tree/master/codeclimate_defaults)在[GitLab Code Quality](https://gitlab.com/gitlab-org/ci-cd/codequality)项目中构建的 Docker 映像在[管道中](../../../ci/pipelines/index.html)运行. +* 可以利用[模板](#example-configuration) . +* 可与[Auto DevOps 一起使用](../../../topics/autodevops/stages.html#auto-code-quality-starter) . +* 可以通过[分析插件](https://docs.codeclimate.com/docs/list-of-engines)或[自定义工具](#implementing-a-custom-tool)进行扩展. + +更进一步,GitLab 可以在合并请求小部件区域中显示"代码质量"报告: + +[![Code Quality Widget](img/486761bb835c9408dac03956a04b3a53.png)](img/code_quality.png) + +观看实践中的代码质量快速演练: + +观看视频: [代码质量:快速运行](https://www.youtube.com/watch?v=B32LxtJKo9M) . + +<figure class="video-container"><iframe src="https://www.youtube.com/embed/B32LxtJKo9M" frameborder="0" allowfullscreen=""></iframe></figure> + +**注意:**对于一位客户,审核员发现,在 GitLab CI / CD 中使代码质量,SAST 和容器扫描全部自动化几乎比手动审核要好! [阅读更多](https://about.gitlab.com/customers/bi_worldwide/) . + +另请参阅" [可维护性支持的语言](https://docs.codeclimate.com/docs/supported-languages-for-maintainability)的代码气候列表". + +## Use cases[](#use-cases "Permalink") + +例如,考虑以下工作流程: + +1. 您的后端团队成员将开始新的实施,以更快地使您的应用中的某些功能. +2. 通过代码质量报告,他们可以分析其实施如何影响代码质量. +3. The metrics show that their code degrades the quality by 10 points. +4. 您要求同事来帮助他们进行此修改. +5. 他们都将对更改进行处理,直到"代码质量"报告显示不降级,仅显示改进. +6. 您批准合并请求并授权其部署到暂存. +7. 验证后,其更改将部署到生产中. + +## Example configuration[](#example-configuration "Permalink") + +**注意:** GitLab 11.11 和更高版本支持以下所示的作业定义. 它还需要 GitLab Runner 11.5 或更高版本. 对于早期版本,请使用[先前的作业定义](#previous-job-definitions) . + +本示例说明如何使用 GitLab CI / CD 和 Docker 在代码上运行代码质量. + +首先,您需要配置 GitLab Runner: + +* 对于[Docker-in-Docker 工作流程](../../../ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor) . +* 有足够的磁盘空间来处理生成的代码质量文件. 例如,在[GitLab 项目上](https://gitlab.com/gitlab-org/gitlab) ,文件约为 7 GB. + +设置运行器后,在您的 CI 配置中包括代码质量模板: + +``` +include: + - template: Code-Quality.gitlab-ci.yml +``` + +上面的示例将在 CI / CD 管道中创建一个`code_quality`作业,该作业将扫描源代码以查看代码质量问题. 该报告将另存为["代码质量"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportscodequality-starter) ,您以后可以下载和分析该[工件](../../../ci/pipelines/job_artifacts.html#artifactsreportscodequality-starter) . + +通过设置`CODE_QUALITY_IMAGE`变量,也可以覆盖 URL 到"代码质量"图像. 如果您想锁定特定版本的 Code Quality 或使用其中的一个分支,这将特别有用: + +``` +include: + - template: Code-Quality.gitlab-ci.yml + +code_quality: + variables: + CODE_QUALITY_IMAGE: "registry.example.com/codequality-fork:latest" +``` + +默认情况下,报告工件不可下载. 如果需要在工作详细信息页面上下载它们,则可以将`gl-code-quality-report.json`到工件路径,如下所示: + +``` +include: + - template: Code-Quality.gitlab-ci.yml + +code_quality: + artifacts: + paths: [gl-code-quality-report.json] +``` + +包含的`code_quality`作业正在`test`阶段运行,因此需要将其包含在 CI 配置中,如下所示: + +``` +stages: + - test +``` + +**提示:**该信息将被自动提取并显示在合并请求小部件中.**注意:**在自我管理的实例上,如果恶意行为者破坏了 Code Quality 作业定义,则他们将能够在 Runner 主机上执行特权的 Docker 命令. 拥有适当的访问控制策略,可以通过仅允许访问受信任的参与者来减轻这种攻击. + +### Previous job definitions[](#previous-job-definitions "Permalink") + +**警告:**在 GitLab 11.5 之前,必须专门命名代码质量作业和工件以自动提取报告数据并将其显示在合并请求小部件中. 尽管这些旧的作业定义仍然保留,但它们已被弃用,并且在 GitLab 12.0 或更高版本中不再受支持. 建议您更新`.gitlab-ci.yml`配置以反映该更改. + +对于 GitLab 11.5 及更高版本,该工作应如下所示: + +``` +code_quality: + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + allow_failure: true + services: + - docker:stable-dind + script: + - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') + - docker run + --env SOURCE_CODE="$PWD" + --volume "$PWD":/code + --volume /var/run/docker.sock:/var/run/docker.sock + "registry.gitlab.com/gitlab-org/ci-cd/codequality:$SP_VERSION" /code + artifacts: + reports: + codequality: gl-code-quality-report.json +``` + +在 GitLab 12.6 中,"代码质量"切换到了[新的版本控制方案](https://gitlab.com/gitlab-org/ci-cd/codequality#versioning-and-release-cycle) . 强烈建议包括代码质量模板,如[示例配置](#example-configuration)所示,该模板使用新的版本控制方案. 如果不使用模板,则可以将`SP_VERSION`变量硬编码为使用新的映像版本: + +``` +code_quality: + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + SP_VERSION: 0.85.6 + allow_failure: true + services: + - docker:stable-dind + script: + - docker run + --env SOURCE_CODE="$PWD" + --volume "$PWD":/code + --volume /var/run/docker.sock:/var/run/docker.sock + "registry.gitlab.com/gitlab-org/ci-cd/codequality:$SP_VERSION" /code + artifacts: + reports: + codequality: gl-code-quality-report.json +``` + +对于 GitLab 11.4 和更早版本,该工作应如下所示: + +``` +code_quality: + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + allow_failure: true + services: + - docker:stable-dind + script: + - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') + - docker run + --env SOURCE_CODE="$PWD" + --volume "$PWD":/code + --volume /var/run/docker.sock:/var/run/docker.sock + "registry.gitlab.com/gitlab-org/ci-cd/codequality:$SP_VERSION" /code + artifacts: + paths: [gl-code-quality-report.json] +``` + +或者,作业名称可以是`codeclimate`或`codequality` ,工件名称可以是`codeclimate.json` . 这些名称已在 GitLab 11.0 中弃用,并可能在下一个主要版本 GitLab 12.0 中删除. + +对于 GitLab 10.3 及更早版本,该工作应如下所示: + +``` +codequality: + image: docker:latest + variables: + DOCKER_DRIVER: overlay + services: + - docker:dind + script: + - docker pull codeclimate/codeclimate:0.69.0 + - docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate:0.69.0 init + - docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate:0.69.0 analyze -f json > codeclimate.json || true + artifacts: + paths: [codeclimate.json] +``` + +## Configuring jobs using variables[](#configuring-jobs-using-variables "Permalink") + +代码质量作业支持环境变量,用户可以将其设置为在运行时配置作业执行. + +For a list of available environment variables, see [Environment variables](https://gitlab.com/gitlab-org/ci-cd/codequality#environment-variables). + +## Implementing a custom tool[](#implementing-a-custom-tool "Permalink") + +可以使用自定义工具在 GitLab 中提供代码质量报告. 去做这个: + +1. 在`.gitlab-ci.yml`文件中定义一个生成[代码质量报告工件的作业](../../../ci/pipelines/job_artifacts.html#artifactsreportscodequality-starter) . +2. 配置您的工具以将代码质量报告工件作为 JSON 文件生成,该文件实现了[Code Climate 规范](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#data-types)的子集. + +代码质量报告工件 JSON 文件必须包含具有以下属性的对象数组: + +| Name | Description | +| --- | --- | +| `description` | A description of the code quality violation. | +| `fingerprint` | 用于识别代码质量违规的唯一指纹. 例如,MD5 哈希. | +| `location.path` | 包含代码质量违规的文件的相对路径. | +| `location.lines.begin` | 发生代码质量违规的行. | + +Example: + +``` +[ { "description": "'unused' is assigned a value but never used.", "fingerprint": "7815696ecbf1c96e6894b779456d330e", "location": { "path": "lib/index.js", "lines": { "begin": 42 } } } ] +``` + +**注意:**尽管 Code Climate 规范支持更多属性,但 GitLab 会忽略这些属性. + +## Code Quality reports[](#code-quality-reports "Permalink") + +代码质量工作完成后: + +* 管道生成的违反代码质量的完整列表可在"管道详细信息"页面的"代码质量"选项卡中找到. +* 代码质量的潜在更改直接在合并请求中显示. 合并请求中的"代码质量"窗口小部件比较分支基础和头部的报告,然后列出合并分支时将解决或创建的所有违例. +* 完整的 JSON 报告可作为`code_quality`作业的可[下载工件](../../../ci/pipelines/job_artifacts.html#downloading-artifacts)获得. + +## Extending functionality[](#extending-functionality "Permalink") + +### Using Analysis Plugins[](#using-analysis-plugins "Permalink") + +如果有需要延长的代码质量所提供的默认功能,如在规定[的代码质量](#code-quality-starter) , [分析插件](https://docs.codeclimate.com/docs/list-of-engines)可供选择. + +例如,要使用[SonarJava 分析器](https://docs.codeclimate.com/docs/sonar-java) ,请在存储库的根目录中添加一个名为`.codeclimate.yml`的文件, `.codeclimate.yml`包含插件的[启用代码](https://docs.codeclimate.com/docs/sonar-java#enable-the-plugin) : + +``` +version: "2" +plugins: + sonar-java: + enabled: true +``` + +这会将 SonarJava 添加到项目中[默认`.codeclimate.yml`](https://gitlab.com/gitlab-org/ci-cd/codequality/-/blob/master/codeclimate_defaults/.codeclimate.yml)的`plugins:`部分. + +对`plugins:`部分的更改不会影响 defeault `.codeclimate.yml`的`exclude_patterns`部分. 有关更多详细信息,请参见代码气候文档以[排除文件和文件夹](https://docs.codeclimate.com/docs/excluding-files-and-folders) . + +这是[一个示例项目](https://gitlab.com/jheimbuck_gl/jh_java_example_project) , [该示例项目](https://gitlab.com/jheimbuck_gl/jh_java_example_project)将 Code Quality 与`.codeclimate.yml`文件一起使用. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Changing the default configuration has no effect[](#changing-the-default-configuration-has-no-effect "Permalink") + +一个普遍的问题是`Code Quality` (特定于 GitLab)和`Code Climate` (GitLab 使用的引擎)这两个术语非常相似. 您必须添加**`.codeclimate.yml`**文件来更改默认配置, **而不是** `.codequality.yml`文件. 如果使用错误的文件名,仍将使用[默认的`.codeclimate.yml`](https://gitlab.com/gitlab-org/ci-cd/codequality/-/blob/master/codeclimate_defaults/.codeclimate.yml) . + +### No Code Quality report is displayed in a Merge Request[](#no-code-quality-report-is-displayed-in-a-merge-request "Permalink") + +这可能是由于多种原因: + +* 您刚刚在`.gitlab-ci.yml`添加了代码质量工作. 该报告尚无可比较的内容,因此无法显示任何信息. 将来的合并请求将具有可比性. +* 如果未[检测到降级或错误](https://docs.codeclimate.com/docs/maintainability#section-checks) ,则不会显示任何内容. +* [`artifacts:expire_in`](../../../ci/yaml/README.html#artifactsexpire_in) CI / CD 设置可能导致代码质量构件过期快于所需. +* `codeclimate.json`较大的`codeclimate.json`文件(尤其是> 10 MB)会[阻止报告的显示](https://gitlab.com/gitlab-org/gitlab/-/issues/2737) . 解决方法是,尝试删除[GitLab 忽略的](#implementing-a-custom-tool) [属性](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#data-types) . 您可以: + * 配置代码质量工具以不输出那些类型. + * 在作业完成之前,请在`.gitlab-ci.yml`脚本中使用`sed` , `awk`或类似命令来编辑`codeclimate.json` . + +### Only a single Code Quality report is displayed, but more are defined[](#only-a-single-code-quality-report-is-displayed-but-more-are-defined "Permalink") + +GitLab 仅使用最新创建的作业(具有最大的作业 ID)的代码质量工件. 如果管道中的多个作业生成代码质量工件,则较早作业的那些将被忽略. 为避免混淆,仅配置一个作业即可生成`codeclimate.json` . \ No newline at end of file diff --git a/_book/docs/119.md b/_book/docs/119.md new file mode 100644 index 0000000000000000000000000000000000000000..48ad50b9137038cbda0299b7561d3b8e6cb21244 --- /dev/null +++ b/_book/docs/119.md @@ -0,0 +1,156 @@ +# Load Performance Testing + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/load_performance_testing.html](https://docs.gitlab.com/ee/user/project/merge_requests/load_performance_testing.html) + +* [How Load Performance Testing works](#how-load-performance-testing-works) +* [Configure the Load Performance Testing job](#configure-the-load-performance-testing-job) + * [Determine the test parameters](#determine-the-test-parameters) + * [Test Environment setup](#test-environment-setup) + * [Write the load performance test](#write-the-load-performance-test) + * [Configure the test in GitLab CI/CD](#configure-the-test-in-gitlab-cicd) + * [Load Performance testing in Review Apps](#load-performance-testing-in-review-apps) + +# Load Performance Testing[](#load-performance-testing-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10683) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + +使用负载性能测试,您可以在[GitLab CI / CD 中](../../../ci/README.html)测试任何待处理代码更改对应用程序后端的影响. + +GitLab 使用免费的开源工具[k6](https://k6.io/)来测量负载下应用程序的系统性能. + +Unlike [Browser Performance Testing](browser_performance_testing.html), which is used to measure how web sites perform in client browsers, Load Performance Testing can be used to perform various types of [load tests](https://k6.io/docs/#use-cases) against application endpoints such as APIs, Web Controllers, and so on. This can be used to test how the backend or the server performs at scale. + +例如,您可以使用负载性能测试对应用程序中流行的 API 端点执行许多并发 GET 调用,以查看其性能. + +## How Load Performance Testing works[](#how-load-performance-testing-works "Permalink") + +首先,在您的`.gitlab-ci.yml`文件中定义一个作业,以生成" [负载性能"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsload_performance-premium) . GitLab 会检查此报告,比较源分支和目标分支之间的关键负载性能指标,然后在合并请求小部件中显示信息: + +[![Load Performance Widget](img/1d9bd6ef20c22f103a6d120b8c673b06.png)](img/load_performance_testing.png) + +接下来,您需要配置测试环境并编写 k6 测试. + +测试完成后,合并请求窗口小部件显示的关键性能指标是: + +* 支票:在 k6 测试中配置的[支票的](https://k6.io/docs/using-k6/checks)通过率. +* TTFB P90: The 90th percentile of how long it took to start receiving responses, aka the [Time to First Byte](https://en.wikipedia.org/wiki/Time_to_first_byte) (TTFB). +* TTFB P95:TTFB 的第 95 个百分点. +* RPS:测试能够达到的平均每秒请求数(RPS). + +**注意:**如果"负载性能"报告没有可比较的数据,例如,当您第一次在`.gitlab-ci.yml`添加"负载性能"作业时,"负载性能"报告小部件将不会显示. 它必须在目标分支(例如`master` )上至少运行一次,然后才能在针对该分支的合并请求中显示. + +## Configure the Load Performance Testing job[](#configure-the-load-performance-testing-job "Permalink") + +配置负载性能测试作业可以分为几个不同的部分: + +* 确定测试参数,例如吞吐量,等等. +* 设置目标测试环境以进行负载性能测试. +* 设计并编写 k6 测试. + +### Determine the test parameters[](#determine-the-test-parameters "Permalink") + +您需要做的第一件事是确定要运行[的负载测试](https://k6.io/docs/test-types/introduction)的[类型](https://k6.io/docs/test-types/introduction)以及运行方式(例如,用户数量,吞吐量等). + +请参阅[k6 文档](https://k6.io/docs/) ,尤其是[k6 测试指南](https://k6.io/docs/testing-guides) ,以获取有关上述内容及更多内容的指南. + +### Test Environment setup[](#test-environment-setup "Permalink") + +负载性能测试的大部分工作是为高负载准备目标测试环境. 您应该确保它能够处理将要测试的[吞吐量](https://k6.io/blog/monthly-visits-concurrent-users) . + +通常还需要在目标环境中具有代表性的测试数据,以供负载性能测试使用. + +强烈建议[不要在生产环境中运行这些测试](https://k6.io/our-beliefs#load-test-in-a-pre-production-environment) . + +### Write the load performance test[](#write-the-load-performance-test "Permalink") + +准备好环境后,您可以编写 k6 测试本身. k6 是一种灵活的工具,可用于运行[多种性能测试](https://k6.io/docs/test-types/introduction) . 有关如何编写测试的详细信息,请参阅[k6 文档](https://k6.io/docs/) . + +### Configure the test in GitLab CI/CD[](#configure-the-test-in-gitlab-cicd "Permalink") + +准备好 k6 测试后,下一步就是在 GitLab CI / CD 中配置负载性能测试作业. 最简单的方法是使用 GitLab 随附的[`Verify/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml)模板. + +**注意:**对于大型 k6 测试,您需要确保执行实际测试的 GitLab Runner 实例能够处理运行测试. 有关规格的详细信息,请参阅[k6 的指南](https://k6.io/docs/testing-guides/running-large-tests#hardware-considerations) . [默认的共享 GitLab.com 运行程序](../../gitlab_com/#linux-shared-runners)可能没有足够的规格来处理大多数大型 k6 测试. + +该模板在作业中运行[k6 Docker 容器](https://hub.docker.com/r/loadimpact/k6/) ,并提供了几种自定义作业的方法. + +配置工作流程示例: + +1. 设置一个可以运行 Docker 容器的 GitLab Runner,例如使用[Docker-in-Docker 工作流](../../../ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor)的 Runner. +2. 在`.gitlab-ci.yml`文件中配置默认​​的 Load Performance Testing CI 作业. 您需要包括模板并使用变量进行配置: + + ``` + include: + template: Verify/Load-Performance-Testing.gitlab-ci.yml + + load_performance: + variables: + K6_TEST_FILE: <PATH TO K6 TEST FILE IN PROJECT> + ``` + +上面的示例在运行 k6 测试的 CI / CD 管道中创建了一个`load_performance`作业. + +**注意:**对于 Kubernetes 设置,应使用其他模板: [`Jobs/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml) . + +k6 具有[各种选项](https://k6.io/docs/using-k6/options)来配置它将如何运行测试,例如运行什么吞吐量(RPS),测试应该运行多长时间等等. 几乎所有选项都可以在测试本身中进行配置,但是您也可以通过`K6_OPTIONS`变量传递命令行选项. + +例如,您可以使用 CLI 选项覆盖测试的持续时间: + +``` + include: + template: Verify/Load-Performance-Testing.gitlab-ci.yml + + load_performance: + variables: + K6_TEST_FILE: <PATH TO K6 TEST FILE IN PROJECT> + K6_OPTIONS: '--duration 30s' +``` + +如果 k6 的结果通过[摘要导出](https://k6.io/docs/results-visualization/json#summary-export)保存为" [负载性能"报告工件,则](../../../ci/pipelines/job_artifacts.html#artifactsreportsload_performance-premium) GitLab 仅在 MR 小部件中显示关键性能指标. 始终使用最新的可用负载性能工件. + +如果启用了[GitLab Pages,](../pages/index.html)则可以直接在浏览器中查看报告. + +### Load Performance testing in Review Apps[](#load-performance-testing-in-review-apps "Permalink") + +上面的 CI / CD YAML 配置示例适用于针对静态环境进行测试,但是可以通过一些额外的步骤将其扩展为与[审阅应用程序](../../../ci/review_apps)或[动态环境](../../../ci/environments)一起使用. + +最好的方法是将动态 URL 捕获到一个自定义环境变量中,然后由`load_performance`作业[继承](../../../ci/variables/README.html#inherit-environment-variables)该`load_performance` . 然后应将要运行的 k6 测试脚本配置为使用该环境 URL,例如: `http.get(`${__ENV.ENVIRONMENT_URL`})` . + +例如: + +1. 在`review`工作中: + 1. 捕获动态 URL 并将其保存到`.env`文件,例如`echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env` . + 2. 将`.env`文件设置为[`artifacts:reports:dotenv` report](../../../ci/variables/README.html#inherit-environment-variables) . +2. 将`load_performance`作业设置为依赖于审阅作业,以便它继承环境变量. +3. 配置 k6 测试脚本以在其步骤中使用环境变量. + +您的`.gitlab-ci.yml`文件可能类似于: + +``` +stages: + - deploy + - performance + +include: + template: Verify/Load-Performance-Testing.gitlab-ci.yml + +review: + stage: deploy + environment: + name: review/$CI_COMMIT_REF_NAME + url: http://$CI_ENVIRONMENT_SLUG.example.com + script: + - run_deploy_script + - echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env + artifacts: + reports: + dotenv: + review.env + rules: + - if: '$CI_COMMIT_BRANCH' # Modify to match your pipeline rules, or use `only/except` if needed. + +load_performance: + dependencies: + - review + rules: + - if: '$CI_COMMIT_BRANCH' # Modify to match your pipeline rules, or use `only/except` if needed. +``` \ No newline at end of file diff --git a/_book/docs/120.md b/_book/docs/120.md new file mode 100644 index 0000000000000000000000000000000000000000..0ef4acaba3a6a21fd7f86f75acae9c89b8d60255 --- /dev/null +++ b/_book/docs/120.md @@ -0,0 +1,83 @@ +# Merge Request dependencies + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_dependencies.html](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_dependencies.html) + +* [Use cases](#use-cases) +* [Configuration](#configuration) +* [Limitations](#limitations) + +# Merge Request dependencies[](#merge-request-dependencies-premium "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9688) . +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.4 中从"跨项目依赖项" [重命名](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17291)为"合并请求依赖项". +* [GitLab Premium](https://about.gitlab.com/pricing/) 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16799)了项目内 MR 依赖关系. + +合并请求相关性允许表达合并请求之间的合并所需顺序. 如果合并请求"依赖"另一个请求,则在合并其依赖项之前,不能将其合并. + +**注意:**合并请求依赖项是**PREMIUM**功能,但是此限制仅对依赖合并请求强制执行. **CORE**或**STARTER**项目中的合并请求可以是**PREMIUM**合并请求的依赖项,反之亦然. + +## Use cases[](#use-cases "Permalink") + +* 在更改导入库的项目之前,请确保对库的更改已合并. +* 在实现要记录功能的合并请求之前,防止仅文档合并请求被合并. +* 在合并来自尚未被授予权限的人的合并请求之前,要求合并请求更新要合并的权限矩阵. + +单个逻辑更改通常会跨越多个合并请求,并分散到多个项目中,并且合并的顺序可能很重要. + +例如,给定项目`mycorp/awesome-project`在`myfriend/awesome-lib`处导入了库,在`awesome-project`添加功能可能**还**需要更改`awesome-lib` ,因此需要两个合并请求. 在`awesome-lib`之前合并`awesome-project`合并请求会破坏`master`分支. + +`awesome-project`合并请求可以[标记为**Draft**](work_in_progress_merge_requests.html) ,注释中包含所述草案的原因. 但是,这要求手动跟踪`awesome-lib`合并请求的状态,并且如果`awesome-project`合并请求依赖于对其他**几个**项目的更改,则伸缩性不好. + +通过使`awesome-project`合并请求依赖于`awesome-lib`合并请求,此关系将由 GitLab 自动跟踪,草稿状态可用于在每个单独的合并请求中传达代码的就绪状态. + +## Configuration[](#configuration "Permalink") + +要继续上面的示例,您可以在`awesome-project`创建新的合并请求时配置依赖项(或通过编辑(如果已经存在)). 需要在**依赖**合并请求上配置**依赖** . 表单中有一个" **合并请求依赖项"**部分: + +[![Merge request dependencies form control](img/86c94810add9e77037bd8a135ef2b972.png)](img/dependencies_edit_v12_4.png) + +任何可以编辑合并请求的人都可以更改依赖关系列表. + +可以通过引用或 URL 添加新的依赖项. 要删除依赖项,请按其引用旁边的**X.** + +由于可以在项目之间指定依赖关系,因此其他人可能为您无权访问的项目中的合并请求添加了依赖关系. 这些显示为简单计数: + +[![Merge request dependencies form control with inaccessible merge requests](img/9d8d2ee20801484a30509d79022ce53c.png)](img/dependencies_edit_inaccessible_v12_4.png) + +如有必要,您可以按**X**来删除所有类似的依赖项,就像对单个可见的依赖项一样. + +完成后,请按" **保存更改"**按钮以提交请求,或按" **取消"**以不做任何更改地返回. + +合并请求窗口小部件中显示了已配置依赖项的列表以及每个依赖项的状态: + +[![Dependencies in merge request widget](img/e4b88f4d9d317b9a38522ce9c63f84bc.png)](img/dependencies_view_v12_2.png) + +在所有依赖项本身都被合并之前,对于依赖项合并请求将禁用" **合并"**按钮. 特别要注意的是, **封闭的合并请求**仍会阻止其依赖项被合并-无法自动确定是否已以其他某种方式满足了由封闭的合并请求表示的依赖关系. + +如果已关闭合并请求**,**并且依赖项不再相关,则必须在合并之前按照上述说明将其作为依赖项除去. + +## Limitations[](#limitations "Permalink") + +* API 支持: [问题#12551](https://gitlab.com/gitlab-org/gitlab/-/issues/12551) +* 在项目导出/导入之间未保留依赖项: [问题#12549](https://gitlab.com/gitlab-org/gitlab/-/issues/12549) +* 不支持复杂的合并顺序相关性: [问题#11393](https://gitlab.com/gitlab-org/gitlab/-/issues/11393) + +最后一项值得更多解释. 合并请求之间的依赖关系可以描述为关系图. 最简单的图可能有一个合并请求,该合并请求取决于另一个: + +图 LR; myfriend / awesome-lib!10-> mycorp / awesome-project!100; + +更为复杂(且仍受支持)的图可能具有一个合并请求,该合并请求直接取决于其他几个: + +图 LR; myfriend / awesome-lib!10-> mycorp / awesome-project!100; herfriend / another-lib!1-> mycorp / awesome-project!100; + +几个不同的合并请求也可以直接依赖于同一合并请求: + +图 LR; herfriend / another-lib!1-> myfriend / awesome-lib!10; herfriend / another-lib!1-> mycorp / awesome-project!100; + +**不**支持的是依赖项的"深度"或"嵌套"图. 例如: + +图 LR; herfriend / another-lib!1-> myfriend / awesome-lib!10; myfriend / awesome-lib!10-> mycorp / awesome-project!100; + +在此示例中, `myfriend/awesome-lib!10`取决于`herfriend/another-lib!1` ,它本身是`mycorp/awesome-project!100`的依赖项. 这意味着`myfriend/awesome-lib!10`成为`mycorp/awesome-project!100`的**间接**依赖项,尚不受支持. \ No newline at end of file diff --git a/_book/docs/121.md b/_book/docs/121.md new file mode 100644 index 0000000000000000000000000000000000000000..504bcd33be5f0f166ac75cc9e7d8905429f27e85 --- /dev/null +++ b/_book/docs/121.md @@ -0,0 +1,36 @@ +# Fast-forward merge requests + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/fast_forward_merge.html](https://docs.gitlab.com/ee/user/project/merge_requests/fast_forward_merge.html) + +* [Overview](#overview) +* [Enabling fast-forward merges](#enabling-fast-forward-merges) + +# Fast-forward merge requests[](#fast-forward-merge-requests "Permalink") + +有时,工作流策略可能会强制要求没有合并提交的干净提交历史记录. 在这种情况下,快速合并是理想的选择. + +使用快速转发合并请求,您可以保留线性 Git 历史记录以及一种无需创建合并提交即可接受合并请求的方法. + +## Overview[](#overview "Permalink") + +启用快进合并( [`--ff-only`](https://git-scm.com/docs/git-merge#git-merge---ff-only) )设置时,将不会创建任何合并提交,并且所有合并都将被快速转发,这意味着仅当分支可以被快速转发时才允许合并. + +当无法进行快速合并时,将为用户提供重新设置基准的选项. + +## Enabling fast-forward merges[](#enabling-fast-forward-merges "Permalink") + +1. 导航到项目的**设置,**然后搜索"合并方法" +2. 选择**快速合并**选项 +3. 点击**保存更改**以使更改生效 + +现在,当您访问合并请求页面时, **只有在可能进行快速**合并的情况下,您才能接受它. + +[![Fast forward merge request](img/50ab118d473b61d3d08773d6ea65a8ac.png)](img/ff_merge_mr.png) + +如果无法进行快速合并,但可以进行无冲突的变基,则将提供一个变基按钮. + +[![Fast forward merge request](img/51192310b3785dec5f60b6d59717a7a6.png)](img/ff_merge_rebase.png) + +如果目标分支位于源分支的前面,并且无法进行无冲突的变基,则需要先在本地对源分支进行变基,然后才能进行快速合并. + +[![Fast forward merge rebase locally](img/d241e2868510cfa5755170c1f02c78f3.png)](img/ff_merge_rebase_locally.png) \ No newline at end of file diff --git a/_book/docs/122.md b/_book/docs/122.md new file mode 100644 index 0000000000000000000000000000000000000000..c1d407d8ac952d10c43ede28fbb51365fd7cf905 --- /dev/null +++ b/_book/docs/122.md @@ -0,0 +1,84 @@ +# Merge when pipeline succeeds + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) + +* [How it works](#how-it-works) +* [Only allow merge requests to be merged if the pipeline succeeds](#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds) + * [Limitations](#limitations) + * [Skipped pipelines](#skipped-pipelines) +* [From the command line](#from-the-command-line) + +# Merge when pipeline succeeds[](#merge-when-pipeline-succeeds "Permalink") + +在查看看起来准备合并但仍在运行管道的合并请求时,可以将其设置为在管道成功时自动合并. 这样,您不必等待管道完成,而不必记住手动合并请求. + +[![Enable](img/ac3623994213ad815a95e7826a3cfc3e.png)](img/merge_when_pipeline_succeeds_enable.png) + +## How it works[](#how-it-works "Permalink") + +当您单击"管道成功时合并"时,合并请求的状态将更新以显示即将进行的合并. 如果您不能等待管道成功,则可以**立即**在主按钮右侧的下拉菜单中选择" **合并"** . + +合并请求的作者和具有开发人员权限的项目成员可以在管道完成之前的任何时间取消自动合并. + +[![Status](img/46322215ec68c4896b6b622f9f1ad11e.png)](img/merge_when_pipeline_succeeds_status.png) + +管道成功后,合并请求将自动合并. 当管道失败时,作者有机会重试任何失败的作业,或推送新的提交以修复失败. + +重试作业并第二次尝试成功后,合并请求将自动合并. 当使用新提交更新合并请求时,自动合并将被取消以允许查看新更改. + +## Only allow merge requests to be merged if the pipeline succeeds[](#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds "Permalink") + +如果合并请求的管道未成功或存在要解析的线程,则可以阻止合并请求. 这对两个都适用: + +* GitLab CI / CD 管道 +* 管道从[外部 CI 集成](../integrations/overview.html#integrations-listing)运行 + +因此, [禁用 GitLab CI / CD 管道](../../../ci/enable_or_disable_ci.html)不会禁用此功能,因为可以将外部 CI 提供程序的管道与该功能一起使用. 要启用它,您必须: + +1. 导航到项目的**"设置">"常规"**页面. +2. 展开**合并请求**部分. +3. 在" **合并检查"**小节中,选中" **管道必须成功"**复选框. +4. 按**保存**使更改生效. + +This setting also prevents merge requests from being merged if there is no pipeline. + +### Limitations[](#limitations "Permalink") + +启用此设置后,如果没有管道,将阻止合并请求. 这可能与[`only/except`](../../../ci/yaml/README.html#onlyexcept-advanced)使用[`only/except`](../../../ci/yaml/README.html#onlyexcept-advanced)或[`rules`](../../../ci/yaml/README.html#rules)且不生成任何管道的某些用例相冲突. + +您应该确保[始终有一个管道](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54226)并且该[管道](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54226)是成功的. + +如果为单个合并请求触发了分支管道和合并请求管道,则仅检查*合并请求管道*的成功或失败. 如果合并请求管道配置的工作少于分支管道,则它可能允许失败测试的代码被合并: + +``` +branch-pipeline-job: + rules: + - if: '$CI_PIPELINE_SOURCE == "push"' + script: + - echo "Code testing scripts here, for example." + +merge-request-pipeline-job: + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + script: + - echo "No tests run, but this pipeline always succeeds and enables merge." + - echo true +``` + +您应该避免这样的配置,并尽可能使用分支( `push` )管道或合并请求管道. 有关在单个合并请求中避免使用两个管道的详细信息,请参见[`rules`文档](../../../ci/yaml/README.html#differences-between-rules-and-onlyexcept) . + +### Skipped pipelines[](#skipped-pipelines "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/211482) . + +选中" **管道必须成功"**复选框时, [跳过的管道会](../../../ci/yaml/README.html#skip-pipeline)阻止合并请求被合并. 更改此行为: + +1. 导航到项目的**"设置">"常规"**页面. +2. 展开**合并请求**部分. +3. 在" **合并检查"**小节中,确保已选中" **管道必须成功"** . +4. 在" **合并检查"**小节中,选中" **跳过的管道被视为成功"**复选框. +5. 按**保存**使更改生效. + +## From the command line[](#from-the-command-line "Permalink") + +当从命令行进行[推送](../push_options.html)时,当管道成功请求合并请求时,可以使用" [推送选项"](../push_options.html)启用合并. \ No newline at end of file diff --git a/_book/docs/123.md b/_book/docs/123.md new file mode 100644 index 0000000000000000000000000000000000000000..dc30395d2d3eebc00482b3597bc40177351094f3 --- /dev/null +++ b/_book/docs/123.md @@ -0,0 +1,51 @@ +# Merge request conflict resolution + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/resolve_conflicts.html](https://docs.gitlab.com/ee/user/project/merge_requests/resolve_conflicts.html) + +* [Resolve conflicts: interactive mode](#resolve-conflicts-interactive-mode) +* [Resolve conflicts: inline editor](#resolve-conflicts-inline-editor) +* [Conflicts available for resolution](#conflicts-available-for-resolution) + +# Merge request conflict resolution[](#merge-request-conflict-resolution "Permalink") + +当两个分支具有无法自动合并的不同更改时,将发生合并冲突. + +在大多数情况下,Git 能够自动合并分支之间的更改,但是在某些情况下,Git 需要您的帮助来手动解决冲突. 通常,当人们更改同一文件的相同部分时,这是必需的. + +在解决所有冲突之前,GitLab 将阻止合并请求. 冲突可以在本地解决,也可以在许多情况下在 GitLab 中解决(有关何时可用的信息,请参见可解决的[冲突](#conflicts-available-for-resolution) ). + +[![Merge request widget](img/c3174e54aed82ba15686b58fc97068f1.png)](img/merge_request_widget.png) + +**注意:** GitLab 通过在未自动合并到目标分支的源分支中创建合并提交来解决冲突. 这允许在合并更改之前对合并提交进行检查和测试,从而防止意外更改进入目标分支而无需检查或破坏构建. + +## Resolve conflicts: interactive mode[](#resolve-conflicts-interactive-mode "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5479) . + +单击此按钮将显示有冲突的文件列表,突出显示冲突部分: + +[![Conflict section](img/7a9e6a406ba2eb40638f2b43024b368b.png)](img/conflict_section.png) + +一旦所有冲突都标记为使用"我们的"或"他们的",则可以解决冲突. 这将执行合并请求的目标分支到源分支的合并,使用选择的选项解决冲突. 如果源分支是`feature` ,目标分支是`master` ,则类似于执行`git checkout feature; git merge master` `git checkout feature; git merge master`本地`git checkout feature; git merge master` . + +## Resolve conflicts: inline editor[](#resolve-conflicts-inline-editor "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6374) in GitLab 8.13. + +合并冲突解决编辑器允许更复杂的合并冲突,需要用户手动修改文件以解决冲突,才能从 GitLab 界面中解决. 使用**内联编辑**按钮打开编辑器. 确定更改后,请单击" **提交到源"分支**按钮. + +[![Merge conflict editor](img/7a5996be0f8e75beb29e443470d79ee6.png)](img/merge_conflict_editor.png) + +## Conflicts available for resolution[](#conflicts-available-for-resolution "Permalink") + +GitLab 允许解决以下所有条件均成立的文件中的冲突: + +* 该文件是文本,不是二进制 +* 该文件采用 UTF-8 兼容编码 +* 该文件尚未包含冲突标记 +* 添加了冲突标记的文件大小不超过 200 KB +* 该文件在两个分支中位于相同路径下 + +如果该合并请求中有冲突的任何文件均不满足所有这些条件,则无法在 UI 中解决该合并请求的冲突. + +此外,GitLab 不会在路径之外的重命名中检测到冲突. 例如,这不会造成冲突:在分支`a`执行`git mv file1 file2` ; 在分支`b` ,执行`git mv file1 file3` . 而是,合并请求合并后,两个文件都将出现在分支中. \ No newline at end of file diff --git a/_book/docs/124.md b/_book/docs/124.md new file mode 100644 index 0000000000000000000000000000000000000000..a970a0c4c15102375ae5f41fa6bbbc98b7c48693 --- /dev/null +++ b/_book/docs/124.md @@ -0,0 +1,40 @@ +# Reverting changes + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/revert_changes.html](https://docs.gitlab.com/ee/user/project/merge_requests/revert_changes.html) + +* [Reverting a merge request](#reverting-a-merge-request) +* [Reverting a commit](#reverting-a-commit) + +# Reverting changes[](#reverting-changes "Permalink") + +您可以使用 Git 的强大功能,通过在合并请求和提交详细信息中单击" **还原"**按钮来[还原任何提交](https://git-scm.com/docs/git-revert "Git 恢复文档") . + +## Reverting a merge request[](#reverting-a-merge-request "Permalink") + +**注意:** " **还原"**按钮仅可用于自 GitLab 8.5 起创建的合并请求. 但是,您仍然可以通过从"提交"页面列表中还原合并提交来还原合并请求.**注意:**仅对使用合并方法"合并提交"的项目显示" **还原"**按钮,该方法可以在项目的**"设置">"常规">"合并请求"**下**设置** . 无法通过 MR 视图还原[快进提交](fast_forward_merge.html) . + +合并请求合并后,将有一个**还原**按钮可用于还原该合并请求引入的更改. + +[![Revert Merge Request](img/fe7d77556848be98a93c7b6516b0e6f8.png)](img/cherry_pick_changes_mr.png) + +单击该按钮后,将出现一个模式,您可以在其中选择将更改直接还原到所选分支中,也可以选择使用还原更改创建新的合并请求. + +合并请求恢复后," **恢复"**按钮将不再可用. + +## Reverting a commit[](#reverting-a-commit "Permalink") + +您可以从提交详细信息页面还原提交: + +[![Revert commit](img/b4e821b8b83e29e837f01f4620e557b7.png)](img/cherry_pick_changes_commit.png) + +与还原合并请求类似,您可以选择将更改直接还原到目标分支中,也可以选择创建新的合并请求以还原更改. + +恢复提交后," **恢复"**按钮将不再可用. + +请注意,还原合并提交时,主线将始终是第一父级. 如果要使用其他主线,则需要从命令行执行. + +这是一个使用第二个父级作为主线还原合并提交的快速示例: + +``` +git revert -m 2 7a39eb0 +``` \ No newline at end of file diff --git a/_book/docs/125.md b/_book/docs/125.md new file mode 100644 index 0000000000000000000000000000000000000000..7961872890874955841bb21b7cbee07b6ec8706d --- /dev/null +++ b/_book/docs/125.md @@ -0,0 +1,290 @@ +# Reviewing and managing merge requests + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/reviewing_and_managing_merge_requests.html](https://docs.gitlab.com/ee/user/project/merge_requests/reviewing_and_managing_merge_requests.html) + +* [View project merge requests](#view-project-merge-requests) +* [View merge requests for all projects in a group](#view-merge-requests-for-all-projects-in-a-group) +* [Semi-linear history merge requests](#semi-linear-history-merge-requests) +* [View changes between file versions](#view-changes-between-file-versions) + * [Merge request diff file navigation](#merge-request-diff-file-navigation) + * [File-by-file diff navigation](#file-by-file-diff-navigation) + * [Enable or disable file-by-file diff navigation](#enable-or-disable-file-by-file-diff-navigation-core-only) + * [Merge requests commit navigation](#merge-requests-commit-navigation) + * [Incrementally expand merge request diffs](#incrementally-expand-merge-request-diffs) + * [Ignore whitespace changes in Merge Request diff view](#ignore-whitespace-changes-in-merge-request-diff-view) +* [Perform inline code reviews](#perform-inline-code-reviews) +* [Pipeline status in merge requests widgets](#pipeline-status-in-merge-requests-widgets) + * [Post-merge pipeline status](#post-merge-pipeline-status) + * [Merge when pipeline succeeds (MWPS)](#merge-when-pipeline-succeeds-mwps) + * [Live preview with Review Apps](#live-preview-with-review-apps) +* [Associated features](#associated-features) +* [Troubleshooting](#troubleshooting) + * [Merge request cannot retrieve the pipeline status](#merge-request-cannot-retrieve-the-pipeline-status) + * [Sidekiq](#sidekiq) + * [Bug](#bug) +* [Tips](#tips) + * [Checkout merge requests locally](#checkout-merge-requests-locally) + * [Checkout locally by adding a Git alias](#checkout-locally-by-adding-a-git-alias) + * [Checkout locally by modifying `.git/config` for a given repository](#checkout-locally-by-modifying-gitconfig-for-a-given-repository) + +# Reviewing and managing merge requests[](#reviewing-and-managing-merge-requests "Permalink") + +合并请求是在 GitLab 项目中更改文件的主要方法. 通过[创建并提交合并请求](creating_merge_requests.html)来提出更改,然后将其审核并接受(或拒绝). + +## View project merge requests[](#view-project-merge-requests "Permalink") + +导航到" **项目">"合并请求",**以查看项目中的所有**合并请求** . + +当您访问项目的合并请求时,GitLab 会将它们显示在列表中,并且您可以使用可用的选项卡来快速按打开和关闭进行过滤. 您还可以[搜索和过滤结果](../../search/index.html#filtering-issue-and-merge-request-lists) . + +[![Project merge requests list view](img/252e40c4dc029a21eb939cb40f715d34.png)](img/project_merge_requests_list_view.png) + +## View merge requests for all projects in a group[](#view-merge-requests-for-all-projects-in-a-group "Permalink") + +查看组中所有项目中的合并请求,包括组中所有后代子组的所有项目. 导航到**组>合并请求**以查看这些合并请求. 该视图还具有打开和关闭的合并请求选项卡. + +您可以从此处[搜索和过滤结果](../../search/index.html#filtering-issue-and-merge-request-lists) . + +[![Group Issues list view](img/1c96e8d94988240b7dc68ae02dbea405.png)](img/group_merge_requests_list_view.png) + +## Semi-linear history merge requests[](#semi-linear-history-merge-requests "Permalink") + +将为每个合并创建一个合并提交,但是只有在可能进行快速合并的情况下才合并分支. 这样可以确保如果合并请求构建成功,则合并后目标分支构建也将成功. + +导航到项目的设置,在" **合并请求:合并"方法**下选择" **使用半线性历史** **合并合并"**选项,然后保存更改. + +## View changes between file versions[](#view-changes-between-file-versions "Permalink") + +**更改**选项卡位于主要合并请求详细信息下方,并且在讨论选项卡旁边,显示了分支或提交之间文件的更改. 这种对文件更改的视图也称为**diff** . 默认情况下,差异视图将合并请求分支中的文件与目标分支中的文件进行比较. + +The diff view includes the following: + +* 文件的名称和路径. +* 添加和删​​除的行数. +* 用于以下选项的按钮: + * 切换此文件的注释; 用于内联评论. + * 在合并请求的分支中编辑文件. + * 显示完整文件,以防您要查看上下文中文件其余部分的更改. + * 在当前提交时查看文件. + * 使用[Review Apps](../../../ci/review_apps/index.html)预览更改. +* 已更改的行,突出显示了特定的更改. + +[![Example screenshot of a source code diff](img/1a3f578f317c266ca4b5d61eb91d025b.png)](img/merge_request_diff_v12_2.png) + +### Merge request diff file navigation[](#merge-request-diff-file-navigation "Permalink") + +在" **更改"**选项卡中查看更改时,可以使用文件树或文件列表来浏览差异. 在具有许多更改的大型差异中滚动时,可以使用文件树或文件列表快速跳转到任何更改的文件. + +[![Merge request diff file navigation](img/65770b50cd2119e84c6a852b44cf403d.png)](img/merge_request_diff_file_navigation.png) + +### File-by-file diff navigation[](#file-by-file-diff-navigation "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/222790) . +* 它部署在默认情况下启用的功能标志后面. +* 建议用于生产. +* 在 GitLab.com 上启用了它. +* 对于 GitLab 自我管理的实例,GitLab 管理员可以选择[禁用它](#enable-or-disable-file-by-file-diff-navigation-core-only) . + +对于较大的合并请求,有时一次查看单个文件可能会很有用. 要启用,请从右上角导航栏上的头像,单击**"设置"** ,然后转到左侧边栏上的**"首选项"** . 向下滚动到" **行为"**部分,然后**在合并请求的"更改"标签上**选择**"一次显示一个文件"** . 点击**保存更改**以应用. + +从那里,在查看合并请求的" **更改"**选项卡时,一次只能看到一个文件. 然后,您可以单击按钮上**一个**和**下一个**以查看其他已更改的文件. + +[![File-by-file diff navigation](img/7887f58c141f9c2e749a75158e430ac6.png)](img/file_by_file_v13_2.png) + +#### Enable or disable file-by-file diff navigation[](#enable-or-disable-file-by-file-diff-navigation-core-only "Permalink") + +逐文件差异导航正在开发中,但已准备好用于生产. 它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以选择为您的实例禁用它. + +要启用它: + +``` +# Instance-wide +Feature.enable(:view_diffs_file_by_file) +``` + +禁用它: + +``` +# Instance-wide +Feature.disable(:view_diffs_file_by_file>) +``` + +### Merge requests commit navigation[](#merge-requests-commit-navigation "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18140) in GitLab 13.0. + +要在合并请求中的**提交**之间无缝导航,请从" **提交"**选项卡中,单击其中一个提交以打开单提交视图. 从那里,您可以通过单击页面右上角的**Prev**和**Next**按钮或使用`X`和`C`键盘快捷键在提交之间进行导航. + +### Incrementally expand merge request diffs[](#incrementally-expand-merge-request-diffs "Permalink") + +默认情况下,差异仅显示文件中已更改的部分. 要查看更改上方或下方的更多未更改行,请单击" **向上** **扩展"**或" **向下扩展"**图标. 您也可以单击**显示未更改的行**以展开整个文件. + +[![Incrementally expand merge request diffs](img/da60a36cf66e162640faa1f6cddaacdc.png)](img/incrementally_expand_merge_request_diffs_v12_2.png) + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/205401) ,当查看合并请求的**更改**选项卡时,如果仅重命名了某个文件,则可以通过单击**显示文件内容**展开它以查看全部**内容** . + +### Ignore whitespace changes in Merge Request diff view[](#ignore-whitespace-changes-in-merge-request-diff-view "Permalink") + +如果单击" **隐藏空白更改"**按钮,则可以看到没有空白更改的差异(如果有的话). 在特定的提交页面上,这也可以工作. + +[![MR diff](img/1a097c142decf7d516165322a0f7b880.png)](img/merge_request_diff.png) + +> **提示:**您可以在合并请求的差异页面上附加`?w=1` ,以忽略任何空格更改. + +## Perform inline code reviews[](#perform-inline-code-reviews "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/13950) . + +GitLab 提供了一种在合并请求中更改文件的任何部分中保留注释的方法. 为此,请在"合并请求"差异 UI 的装订线中单击**…**按钮以展开差异行并留下评论,就像更改行一样. + +[![Comment on any diff file line](img/9aa51957855aec8590e352694fe75d5d.png)](img/comment-on-any-diff-line.png) + +## Pipeline status in merge requests widgets[](#pipeline-status-in-merge-requests-widgets "Permalink") + +如果您在项目中设置了[GitLab CI / CD](../../../ci/README.html) ,您将能够看到: + +* 合并前和合并后管道以及环境信息(如果有). +* 正在进行哪些部署. + +如果存在[环境](../../../ci/environments/index.html)并且已将应用程序成功部署到该环境,则还将显示已部署的环境以及指向 Review App 的链接. + +### Post-merge pipeline status[](#post-merge-pipeline-status "Permalink") + +合并请求合并后,可以看到合并请求合并到的分支的合并后管道状态. 例如,当合并请求合并到 master 分支中,然后触发到暂存环境的部署时. + +将显示正在进行的部署,以及环境的部署/部署状态. 如果是第一次部署分支,则该链接将返回`404`错误,直到完成. 在部署期间,停止按钮将被禁用. 如果管道无法部署,则部署信息将被隐藏. + +[![Merge request pipeline](img/1c4eef7cdb82fd840a9facad4ee93d6b.png)](img/merge_request_pipeline.png) + +有关更多信息,请[阅读有关管道](../../../ci/pipelines/index.html) . + +### Merge when pipeline succeeds (MWPS)[](#merge-when-pipeline-succeeds-mwps "Permalink") + +设置一个看起来准备合并的合并请求,以[在 CI 管道成功时自动合并](merge_when_pipeline_succeeds.html) . + +### Live preview with Review Apps[](#live-preview-with-review-apps "Permalink") + +如果为项目配置了[Review Apps](https://about.gitlab.com/stages-devops-lifecycle/review-apps/) ,则可以逐分支预览通过合并请求提交给功能分支的更改. 无需检出分支机构,在本地安装和预览; 带有"评论应用"链接的任何人都可以预览所有更改. + +设置了 GitLab 的" [路线图"后](../../../ci/review_apps/index.html#route-maps) ,合并请求小部件会将您直接带到已更改的页面,从而使预览建议的修改变得更加轻松快捷. + +[Read more about Review Apps](../../../ci/review_apps/index.html). + +## Associated features[](#associated-features "Permalink") + +还有大量与合并请求关联的功能: + +| Feature | Description | +| --- | --- | +| [Bulk editing merge requests](../../project/bulk_editing.html) | 同时更新多个合并请求的属性. | +| [Cherry-pick changes](cherry_pick_changes.html) | 只需在合并的合并请求或提交中单击**Cherry-pick**按钮,即可在 UI 中 Cherry-pick 任何**选择** . | +| [Fast-forward merge requests](fast_forward_merge.html) | 有关线性 Git 历史记录以及接受合并请求而不创建合并提交的方法 | +| [Find the merge request that introduced a change](versions.html) | 当查看提交详细信息页面时,GitLab 将链接到包含该提交的合并请求. | +| [Merge requests versions](versions.html) | 选择并比较合并请求差异的不同版本 | +| [Resolve conflicts](resolve_conflicts.html) | GitLab 可以提供选项来解决 GitLab UI 中的某些合并请求冲突. | +| [Revert changes](revert_changes.html) | 从合并请求中的任何提交还原更改. | + +## Troubleshooting[](#troubleshooting "Permalink") + +有时,合并请求中的操作并没有按预期进行,这是一些故障排除步骤. + +### Merge request cannot retrieve the pipeline status[](#merge-request-cannot-retrieve-the-pipeline-status "Permalink") + +如果 Sidekiq 没有足够快地进行更改,则会发生这种情况. + +#### Sidekiq[](#sidekiq "Permalink") + +Sidekiq 没有足够快地处理 CI 状态更改. 请等待几秒钟,状态将自动更新. + +#### Bug[](#bug "Permalink") + +发生以下情况时,无法检索合并请求管道的状态: + +1. 创建合并请求 +2. 合并请求已关闭 +3. 在项目中进行了更改 +4. 合并请求被重新打开 + +要正确检索管道状态,请再次关闭并重新打开"合并请求". + +## Tips[](#tips "Permalink") + +以下是一些技巧,可帮助您在命令行中更有效地处理合并请求. + +> **注意:**此部分将来可能会在其自己的文档中移动. + +### Checkout merge requests locally[](#checkout-merge-requests-locally "Permalink") + +合并请求包含来自存储库的所有历史记录,以及添加到与合并请求关联的分支的其他提交. 这是一些在本地检出合并请求的技巧. + +请注意,即使源项目是目标项目的分支(甚至是私有分支),也可以在本地签出合并请求. + +#### Checkout locally by adding a Git alias[](#checkout-locally-by-adding-a-git-alias "Permalink") + +将以下别名添加到`~/.gitconfig` : + +``` +[alias] + mr = !sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' - +``` + +现在,您可以从任何存储库和任何远程签出特定的合并请求. 例如,要从`origin`远程服务器签出 ID 为 5 的合并请求(如 GitLab 所示),请执行以下操作: + +``` +git mr origin 5 +``` + +这会将合并请求提取到本地`mr-origin-5`分支中,并检出它. + +#### Checkout locally by modifying `.git/config` for a given repository[](#checkout-locally-by-modifying-gitconfig-for-a-given-repository "Permalink") + +在`.git/config`文件中找到适用于 GitLab 遥控器的部分. 看起来像这样: + +``` +[remote "origin"] + url = https://gitlab.com/gitlab-org/gitlab-foss.git + fetch = +refs/heads/*:refs/remotes/origin/* +``` + +您可以使用以下方式打开文件: + +``` +git config -e +``` + +现在,将以下行添加到上面的部分: + +``` +fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/* +``` + +最后,它应如下所示: + +``` +[remote "origin"] + url = https://gitlab.com/gitlab-org/gitlab-foss.git + fetch = +refs/heads/*:refs/remotes/origin/* + fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/* +``` + +现在,您可以获取所有合并请求: + +``` +git fetch origin + +... +From https://gitlab.com/gitlab-org/gitlab-foss.git + * [new ref] refs/merge-requests/1/head -> origin/merge-requests/1 + * [new ref] refs/merge-requests/2/head -> origin/merge-requests/2 +... +``` + +并检查特定的合并请求: + +``` +git checkout origin/merge-requests/1 +``` + +以上所有操作均可通过[`git-mr`](https://gitlab.com/glensc/git-mr)脚本完成. \ No newline at end of file diff --git a/_book/docs/126.md b/_book/docs/126.md new file mode 100644 index 0000000000000000000000000000000000000000..2caaf125ceb444d3c7f0d457016ec9ac7e92fd56 --- /dev/null +++ b/_book/docs/126.md @@ -0,0 +1,123 @@ +# Squash and merge + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html](https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Enabling squash for a merge request](#enabling-squash-for-a-merge-request) +* [Commit metadata for squashed commits](#commit-metadata-for-squashed-commits) +* [Squash and fast-forward merge](#squash-and-fast-forward-merge) +* [Squash Commits Options](#squash-commits-options) + * [Enable or disable Squash Commit Options](#enable-or-disable-squash-commit-options-core-only) + +# Squash and merge[](#squash-and-merge "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 8.17 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1024) . +* [移植](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18956)到 GitLab Core 11.0\. + +使用 squash 和 merge,您可以将所有合并请求的提交合并为一个并保留干净的历史记录. + +## Overview[](#overview "Permalink") + +通过压接,您可以在接受合并请求时整理分支的提交历史记录. 它将合并请求中的所有更改作为单个提交应用,然后使用为项目设置的合并方法合并该提交. + +换句话说,挤压合并请求会变成一长串提交: + +[![List of commits from a merge request](img/f2d420adddd87cc8087fea62246e7b67.png)](img/squash_mr_commits.png) + +合并为单个提交: + +[![A squashed commit followed by a merge commit](img/e81fe926a5b379f37dfc5af80b8f83f3.png)](img/squash_squashed_commit.png) + +压缩的提交的提交消息将是: + +* 取自合并中的第一条多行提交消息. +* 如果找不到多行提交消息,则合并请求的标题. + +**注意:**仅在至少 2 次提交时,此选项才生效. 由于没有什么可压缩的,因此如果只有 1 次提交,则提交消息不会更改. + +可以在合并合并请求之前对其进行自定义. + +[![A squash commit message editor](img/618ce3d47266d9b45262489065b68cf7.png)](img/squash_mr_message.png) + +**注意:**在此示例中,压缩的提交之后是合并提交,因为此示例存储库的合并方法使用了合并提交. + +压缩也适用于快进合并策略,有关更多详细信息,请参见[压缩和快进合并](#squash-and-fast-forward-merge) . + +## Use cases[](#use-cases "Permalink") + +在功能分支上工作时,有时您想提交当前进度,但实际上并不关心提交消息. 这些"进行中的提交"不一定包含重要的信息,因此,您宁愿不将其包含在目标分支中. + +使用 squash 和 merge,当准备好要合并的合并请求时,您要做的就是在按下 merge 之前将挤压启用,以将合并请求中的提交加入到单个提交中. + +这样,您的基本分支的历史记录将保留有意义的提交消息,并且: + +* 如有必要, [还原](revert_changes.html)更为简单. +* 合并的分支将保留完整的提交历史记录. + +## Enabling squash for a merge request[](#enabling-squash-for-a-merge-request "Permalink") + +可以创建或编辑合并请求的任何人都可以选择将其压缩在合并请求表单上: + +[![Squash commits checkbox on edit form](img/fd54213f0e98a4b2f6482ab98d497410.png)](img/squash_edit_form.png) + +然后可以在接受合并请求时覆盖它: + +[![Squash commits checkbox on accept merge request form](img/3667bc1901823963df25df8a2458047a.png)](img/squash_mr_widget.png) + +## Commit metadata for squashed commits[](#commit-metadata-for-squashed-commits "Permalink") + +压缩的提交具有以下元数据: + +* 消息:壁球提交消息或自定义消息. +* 作者:合并请求的作者. +* 提交者:发起壁球的用户. + +## Squash and fast-forward merge[](#squash-and-fast-forward-merge "Permalink") + +当项目[启用](fast_forward_merge.html#enabling-fast-forward-merges)了[快进合并设置时](fast_forward_merge.html#enabling-fast-forward-merges) ,合并请求必须能够不压缩而进行快速转发以进行压缩. 这是因为压缩仅在接受合并请求时可用,因此即使挤压本身可以被认为等同于重新基准化,也可能需要在压缩之前对合并请求进行重新基准化. + +## Squash Commits Options[](#squash-commits-options "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/17613) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上已禁用. +* 不建议将其用于生产. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-squash-commit-options-core-only) . + +使用 Squash Commits Options,您可以为项目配置 Squash 和 Merge 的行为. 要进行设置,请导航至项目的**设置>常规,**然后展开**合并请求** . 您将找到以下选项可供选择,这将影响提交给您的项目的现有和新合并请求: + +* **不允许** :用户不能在合并之前立即使用 Squash 和 Merge 来压缩所有提交. 启用或禁用它的复选框将被取消选中,并且对用户隐藏. +* **Allow**: users will have the option to enable Squash and Merge on a merge request basis. The checkbox will be unchecked (disabled) by default, but and the user is allowed to enable it. +* **鼓励** :用户可以选择在合并请求的基础上启用 Squash 和 Merge. 默认情况下会选中(启用)该复选框以鼓励使用,但允许用户禁用它. +* **要求** :对所有合并请求都启用了"挤压和合并",因此将始终执行. 启用或禁用它的复选框将被选中并向用户隐藏. + +创建合并请求以及编辑现有请求的描述时,将显示" Squash and Merge"复选框,但" Squash Commit Options"设置为**"不允许"**或" **Require"**时除外. + +**注意:**如果您的项目设置为**"不允许**挤压和合并",则用户仍然可以选择通过命令行在本地挤压提交,并在合并之前强制将其推送到其远程分支. + +### Enable or disable Squash Commit Options[](#enable-or-disable-squash-commit-options-core-only "Permalink") + +壁球提交选项正在开发中,尚未准备好用于生产. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以为您的实例启用它. 可以根据项目启用或禁用壁球提交选项. + +要启用它: + +``` +# Instance-wide +Feature.enable(:squash_options) +# or by project +Feature.enable(:squash_options, Project.find(<project id>)) +``` + +禁用它: + +``` +# Instance-wide +Feature.disable(:squash_options) +# or by project +Feature.disable(:squash_options, Project.find(<project id>)) +``` \ No newline at end of file diff --git a/_book/docs/127.md b/_book/docs/127.md new file mode 100644 index 0000000000000000000000000000000000000000..556beb01657384d332ae1f2cf79b60de108154e1 --- /dev/null +++ b/_book/docs/127.md @@ -0,0 +1,49 @@ +# Merge requests versions + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/versions.html](https://docs.gitlab.com/ee/user/project/merge_requests/versions.html) + +* [Selecting a version](#selecting-a-version) +* [Find the merge request that introduced a change](#find-the-merge-request-that-introduced-a-change) +* [`HEAD` comparison mode for Merge Requests](#head-comparison-mode-for-merge-requests) + +# Merge requests versions[](#merge-requests-versions "Permalink") + +每次您推送到与合并请求绑定的分支时,都会创建新版本的合并请求 diff. 当您访问包含多个推送的合并请求时,可以选择并比较那些合并请求差异的版本. + +[![Merge request versions](img/0d2f752f5d8c7352da5333f4f0d27835.png)](img/versions.png) + +## Selecting a version[](#selecting-a-version "Permalink") + +默认情况下,显示更改的最新版本. 但是,您可以从版本下拉列表中选择一个较旧的版本. + +[![Merge request versions dropdown](img/1864a1996bbb1636d65648dd8b0857df.png)](img/versions_dropdown.png) + +合并请求版本基于推送而不是提交. 因此,如果您单次推送了 5 次提交,那么下拉菜单中的选项就是一个. 如果您按了 5 次,则算上 5 个选项. + +您还可以将合并请求版本与旧版本进行比较,以查看此后发生了什么变化. + +[![Merge request versions compare](img/f0a8b71ac0a74f03724937e45e8782b9.png)](img/versions_compare.png) + +在查看过时的合并版本或与基本版本以外的版本进行比较时,将禁用注释. + +每次将新更改推送到分支时,系统都会显示一个用于比较最后更改的链接. + +[![Merge request versions system note](img/8201105b83669750c4d60036b41f6c6d.png)](img/versions_system_note.png) + +## Find the merge request that introduced a change[](#find-the-merge-request-that-introduced-a-change "Permalink") + +在 GitLab 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/2383) . + +在查看提交详细信息页面时,GitLab 将链接到包含该提交的合并请求(或合并请求,如果存在多个). + +这仅适用于最新版本的合并请求中的提交-如果某个提交位于合并请求中,然后根据该合并请求重新建立基础,则不会链接它们. + +## `HEAD` comparison mode for Merge Requests[](#head-comparison-mode-for-merge-requests "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27008) . + +合并请求(尤其是" **更改"**选项卡)是查看和讨论源代码的地方. 在目标分支被合并到合并请求的源分支的情况下,源分支和目标分支中的更改可以显示为混合在一起,这使得很难理解目标分支中正在添加哪些更改以及已经存在哪些更改. + +在 GitLab 12.10 中,我们添加了一个比较模式,该模式显示了通过模拟合并后的差异计算出的差异-更准确地表示更改,而不是使用两个分支的基础. 通过选择**master(HEAD),**可以从比较目标下拉列表中使用新模式. 将来它将[替换](https://gitlab.com/gitlab-org/gitlab/-/issues/198458)当前的默认比较. + +[![Merge request versions compare HEAD](img/3478cae6da4e529f7c9cf2f4e71dd462.png)](img/versions_compare_head_v12_10.png) \ No newline at end of file diff --git a/_book/docs/128.md b/_book/docs/128.md new file mode 100644 index 0000000000000000000000000000000000000000..f4946df513d05e24390f5c927643b7d39b806b90 --- /dev/null +++ b/_book/docs/128.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/authorization_for_merge_requests.html](https://docs.gitlab.com/ee/user/project/merge_requests/authorization_for_merge_requests.html) \ No newline at end of file diff --git a/_book/docs/129.md b/_book/docs/129.md new file mode 100644 index 0000000000000000000000000000000000000000..414fe2486951773e6a5a0d736b745991bf13dc39 --- /dev/null +++ b/_book/docs/129.md @@ -0,0 +1,38 @@ +# Draft merge requests + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/work_in_progress_merge_requests.html](https://docs.gitlab.com/ee/user/project/merge_requests/work_in_progress_merge_requests.html) + +* [Adding the “Draft” flag to a merge request](#adding-the-draft-flag-to-a-merge-request) +* [Removing the “Draft” flag from a merge request](#removing-the-draft-flag-from-a-merge-request) +* [Including/excluding WIP merge requests when searching](#includingexcluding-wip-merge-requests-when-searching) + +# Draft merge requests[](#draft-merge-requests "Permalink") + +如果合并请求尚未准备好进行合并(可能是由于持续的开发或开放的线程),则可以通过将其标记为**Draft**来阻止在合并之前接受该合并请求. 这将禁用"合并"按钮,从而防止其被合并,并且在删除"草稿"标志之前它将保持禁用状态. + +[![Blocked Merge Button](img/284b72b1bfc8d5679fdaa384932b3b8c.png)](img/draft_blocked_merge_button_v13_2.png) + +## Adding the “Draft” flag to a merge request[](#adding-the-draft-flag-to-a-merge-request "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32692)的在进行中(WIP)合并请求已重命名为**Draft** . 在 GitLab 14.0 中将删除对使用**WIP 的**支持. + +There are several ways to flag a merge request as a Draft: + +* 将`[Draft]` , `Draft:`或`(Draft)`到合并请求标题的开头. 单击标题框下的" **以草稿开始标题:** ",在编辑合并请求的描述时将具有相同的效果. +* **不推荐使用**将`[WIP]`或`WIP:`添加到合并请求标题的开头. **WIP**仍然有效,但不赞成使用**Draft** . 它将在下一个主要版本(GitLab 14.0)中删除. +* 在合并请求的注释中添加`/wip` [快速操作](../quick_actions.html#quick-actions-for-issues-merge-requests-and-epics) . 这是一个切换,可以重复进行以将状态改回. 请注意,注释中的任何其他文本将被丢弃. +* 将`draft:`或`Draft:`添加到针对合并请求的源分支的提交消息的开头. 这不是切换,并且在另一次提交中再次执行将无效. + +## Removing the “Draft” flag from a merge request[](#removing-the-draft-flag-from-a-merge-request "Permalink") + +与上述类似,当准备合并请求时,可以通过以下几种方式删除" `Draft`标志: + +* 从合并请求标题的开头删除`[Draft]` , `Draft:`或`(Draft)` . 在编辑合并请求的描述时,在标题框下单击" **从标题中删除草稿:"前缀** ,将具有相同的效果. +* 在合并请求的注释中添加`/wip` [快速操作](../quick_actions.html#quick-actions-for-issues-merge-requests-and-epics) . 这是一个切换,可以重复进行以将状态改回. 请注意,注释中的任何其他文本将被丢弃. +* 点击靠近合并请求描述底部的**解决草案状态**按钮,旁边的**合并**按钮(见[上面的图片](#draft-merge-requests) ). 必须对该项目至少具有开发人员级别的权限,该按钮才可见. + +## Including/excluding WIP merge requests when searching[](#includingexcluding-wip-merge-requests-when-searching "Permalink") + +查看/搜索合并请求列表时,可以通过在搜索框中添加" WIP"过滤器,然后选择"是"(包括)或"否"(排除)来选择包括或排除 WIP 合并请求. + +[![Filter WIP MRs](img/fa591f90dc1e8840fe7fd692f24dcffe.png)](img/filter_wip_merge_requests.png) \ No newline at end of file diff --git a/_book/docs/130.md b/_book/docs/130.md new file mode 100644 index 0000000000000000000000000000000000000000..da43cee1c9e28178ca2bd77865ebec581bcabb58 --- /dev/null +++ b/_book/docs/130.md @@ -0,0 +1,131 @@ +# Members of a project + +> 原文:[https://docs.gitlab.com/ee/user/project/members/](https://docs.gitlab.com/ee/user/project/members/) + +* [Inherited membership](#inherited-membership) +* [Add a user](#add-a-user) +* [Import users from another project](#import-users-from-another-project) +* [Invite people using their e-mail address](#invite-people-using-their-e-mail-address) +* [Project membership and requesting access](#project-membership-and-requesting-access) +* [Share project with group](#share-project-with-group) +* [Remove a member from the project](#remove-a-member-from-the-project) + +# Members of a project[](#members-of-a-project "Permalink") + +您可以在所有项目中管理组和用户及其访问级别. 您还可以个性化为每个项目赋予每个用户的访问级别. + +您应该具有维护者或所有者[权限,](../../permissions.html)才能将新用户添加或导入到项目中. + +要查看,编辑,添加和删除项目的成员,请转到项目的**成员** . + +## Inherited membership[](#inherited-membership "Permalink") + +当您的项目属于该组时,组成员将从该组继承该项目的成员资格和权限级别. + +[![Project members page](img/3f64ac42c5324a759f292fa0f7e4d991.png)](img/project_members.png) + +从上图可以得出以下几点: + +* 有 3 个成员可以访问该项目. +* User0 是记者,并且已从包含当前项目的组`demo`继承了他们的权限. +* 对于 User1,没有组的指示,因此它们直接属于我们正在检查的项目. +* 管理员是**所有**组的所有者和所有者,因此,有迹象表明祖先组和继承的所有者权限. + +[在 GitLab 12.6 中](https://gitlab.com/gitlab-org/gitlab/-/issues/21727) ,您可以使用右侧的下拉列表过滤此列表: + +[![Project members filter](img/4d5fab6dd3f65351ba798d87517db0bd.png)](img/project_members_filter_v12_6.png) + +* **仅显示直接成员**仅显示 User1. +* **仅显示继承的成员将**显示 User0 和 Administrator. + +## Add a user[](#add-a-user "Permalink") + +旁边的**人** ,开始输入要添加的用户的姓名或用户名. + +[![Search for people](img/5d98850d2ad30c43029645c8c0486059.png)](img/add_user_search_people.png) + +选择用户以及您要赋予该用户的[权限级别](../../permissions.html) . 请注意,您可以选择多个用户. + +[![Give user permissions](img/c736ba09ab7186102250ad9e624d79c1.png)](img/add_user_give_permissions.png) + +完成后,点击**将用户添加到项目中** ,这些**用户**将立即使用您在上面授予他们的权限添加到您的项目中. + +[![List members](img/a94b1f6b20cc665168a8d8359d195f78.png)](img/add_user_list_members.png) + +从那里开始,您可以删除现有用户或更改其对项目的访问级别. + +## Import users from another project[](#import-users-from-another-project "Permalink") + +您可以通过单击" **成员"**菜单右上角的" **导入成员"**按钮,将另一个项目的用户导入您自己的项目中. + +在下拉菜单中,您只能看到维护者所在的项目. + +[![Import members from another project](img/4c34240e5c09caa62a018e3d109c1ba3.png)](img/add_user_import_members_from_another_project.png) + +选择所需的一个,然后单击" **导入项目成员"** . 将会出现一条简短的消息,通知您导入已成功,并且新成员现在位于项目的成员列表中. 请注意,保留了他们对您从中导入的项目的权限. + +[![Members list of new members](img/f9a1ce8fe1042543bc2355950f642a05.png)](img/add_user_imported_members.png) + +## Invite people using their e-mail address[](#invite-people-using-their-e-mail-address "Permalink") + +如果要授予访问权限的用户在您的 GitLab 实例上没有帐户,则可以通过在用户搜索字段中键入其电子邮件地址来邀请他们. + +[![Invite user by mail](img/27d6bf9eb64fd8e4298e7a2a8ae64983.png)](img/add_user_email_search.png) + +可以想象,您可以混合邀请多个人并将现有的 GitLab 用户添加到项目中. + +[![Invite user by mail ready to submit](img/1fa927abbc0d78f64822dcc6c7295cd4.png)](img/add_user_email_ready.png) + +完成后,点击" **将用户添加到项目中",**然后观察到有一个新成员具有我们上面使用的电子邮件地址. 在此之后,您可以重新发送邀请,更改其访问级别,甚至删除它们. + +[![Invite user members list](img/878c3488cf7403499b80fcd402198e32.png)](img/add_user_email_accept.png) + +用户接受邀请后,将提示他们使用邀请发送到的相同电子邮件地址创建一个新的 GitLab 帐户. + +## Project membership and requesting access[](#project-membership-and-requesting-access "Permalink") + +项目所有者可以: + +* 允许非成员请求访问该项目. +* 防止非会员请求访问. + +要进行配置,请转到项目设置,然后单击**允许用户请求访问权限** . + +GitLab 用户可以请求成为项目成员. 转到您要加入的项目,然后单击屏幕右侧的" **请求访问**权"按钮. + +[![Request access button](img/1ff79a3af1496b3e864efbcf5f93307f.png)](img/request_access_button.png) + +请求访问后: + +* 通过电子邮件将最多十个项目维护者通知该请求. 电子邮件被发送给最近活跃的项目维护者. +* 任何项目维护者都可以在成员页面上批准或拒绝该请求. + +**注意:**如果项目没有任何维护者,则将通知发送给该项目组的最近活动的所有者. + +[![Manage access requests](img/083580c1827d40263d500a21f072249f.png)](img/access_requests_management.png) + +如果您在批准请求之前改变主意,只需单击" **撤回访问请求"**按钮. + +[![Withdraw access request button](img/dbb89cfb3c7539310a17d809c65c34a5.png)](img/withdraw_access_request_button.png) + +## Share project with group[](#share-project-with-group "Permalink") + +或者,您可以[与整个组共享一个项目,](share_project_with_groups.html)而不是一个一个地添加用户. + +## Remove a member from the project[](#remove-a-member-from-the-project "Permalink") + +只有[拥有所有者](../../permissions.html#group-members-permissions)权限的[用户](../../permissions.html#group-members-permissions)才能管理项目成员. + +如果给定成员在项目中具有直接成员资格,则可以从项目中删除用户. 如果成员资格是从父组继承的,则该成员只能从父组本身中删除. + +删除成员时,您可以决定是从所有问题中取消分配用户,还是合并当前已分配的请求,还是保留分配. + +* 当用户离开私有项目并且您希望撤消他们对所有问题和已分配的合并请求的访问时,从所有问题和合并请求中**取消分配已删除的成员**可能会有所帮助. +* **保留问题和合并请求的分配**可能对于接受公共贡献的项目很有帮助,在这些项目中,用户不必成为成员就可以为问题和合并请求做出贡献. + +To remove a member from a project: + +1. 在一个项目中,转到 **成员们** . +2. 点击**删除** 要删除的项目成员旁边的按钮. 出现" **删除成员"**模态. +3. (可选)选中" **也从相关问题中取消分配此用户并合并请求"**复选框. +4. Click **删除会员**. \ No newline at end of file diff --git a/_book/docs/131.md b/_book/docs/131.md new file mode 100644 index 0000000000000000000000000000000000000000..2bc50f1276e64767b6c10a4f926ff1730a044786 --- /dev/null +++ b/_book/docs/131.md @@ -0,0 +1,62 @@ +# Migrating projects to a GitLab instance + +> 原文:[https://docs.gitlab.com/ee/user/project/import/](https://docs.gitlab.com/ee/user/project/import/) + +* [Migrating from self-managed GitLab to GitLab.com](#migrating-from-self-managed-gitlab-to-gitlabcom) +* [Migrating from GitLab.com to self-managed GitLab](#migrating-from-gitlabcom-to-self-managed-gitlab) +* [Migrating between two self-managed GitLab instances](#migrating-between-two-self-managed-gitlab-instances) + +# Migrating projects to a GitLab instance[](#migrating-projects-to-a-gitlab-instance "Permalink") + +1. [From Bitbucket Cloud](bitbucket.html) +2. [From Bitbucket Server (also known as Stash)](bitbucket_server.html) +3. [From ClearCase](clearcase.html) +4. [From CVS](cvs.html) +5. [From FogBugz](fogbugz.html) +6. [From GitHub.com or GitHub Enterprise](github.html) +7. [From GitLab.com](gitlab_com.html) +8. [From Gitea](gitea.html) +9. [From Perforce](perforce.html) +10. [From SVN](svn.html) +11. [From TFVC](tfvc.html) +12. [From repo by URL](repo_by_url.html) +13. [By uploading a manifest file (AOSP)](manifest.html) +14. [From Gemnasium](gemnasium.html) +15. [From Phabricator](phabricator.html) +16. [From Jira (issues only)](jira.html) + +除了上述特定的迁移文档之外,您还可以从 New Project 页面通过 HTTP 导入任何 Git 存储库. 请注意,如果存储库太大,则导入可能会超时. + +还可以选择[连接您的外部存储库以获得 CI / CD 好处](../../../ci/ci_cd_for_external_repos/index.html) . + +## Migrating from self-managed GitLab to GitLab.com[](#migrating-from-self-managed-gitlab-to-gitlabcom "Permalink") + +如果只需要迁移 Git 仓库,则可以[通过 URL 导入每个项目](repo_by_url.html) . 问题和合并请求无法导入. + +如果要保留所有元数据(例如问题和合并请求),则可以使用[导入/导出功能](../settings/import_export.html)从自我管理的 GitLab 导出项目,并将这些项目导入 GitLab.com. + +所有的 GitLab 用户关联(例如评论作者)都将更改为导入项目的用户. 有关更多信息,请参阅[导入说明](../settings/import_export.html#important-notes) . + +如果您需要迁移所有数据,则可以利用我们的[API](../../../api/README.html)从自我管理迁移到 GitLab.com. 从自我管理实例迁移到 GitLab.com 的资产顺序如下: + +**注意:**迁移到 GitLab.com 时,除非要使用[SCIM,](../../../user/group/saml_sso/scim_setup.html)否则需要手动创建用户. 使用 API​​创建用户仅限于自我管理的实例,因为它需要管理员访问权限. + +1. [Groups](../../../api/groups.html) +2. [Projects](../../../api/projects.html) +3. [Project variables](../../../api/project_level_variables.html) + +请记住[导入/导出功能](../settings/import_export.html#exported-contents)的局限性. + +您仍然需要通过一系列 Docker 推和推来迁移 Container Registry,并重新运行任何 CI 管道以检索任何构建工件. + +## Migrating from GitLab.com to self-managed GitLab[](#migrating-from-gitlabcom-to-self-managed-gitlab "Permalink") + +该过程与[从自我管理的 GitLab 迁移到 GitLab.com](#migrating-from-self-managed-gitlab-to-gitlabcom)的过程基本相同. 主要区别在于,管理员可以通过 UI 或[用户 API](../../../api/users.html#user-creation)在自助 GitLab 实例上创建[用户](../../../api/users.html#user-creation) . + +## Migrating between two self-managed GitLab instances[](#migrating-between-two-self-managed-gitlab-instances "Permalink") + +The best method for migrating from one GitLab instance to another, perhaps from an old server to a new server for example, is to [back up the instance](../../../raketasks/backup_restore.html), then restore it on the new server. + +如果将两个 GitLab 实例合并在一起(例如,两个实例上都有现有数据,并且不能擦除),请参阅[从自我管理的 GitLab 迁移到 GitLab.com 中的说明](#migrating-from-self-managed-gitlab-to-gitlabcom) . + +此外,您可以将用户[API](../../../api/users.html)与管理员用户一起使用来迁移用户. \ No newline at end of file diff --git a/_book/docs/132.md b/_book/docs/132.md new file mode 100644 index 0000000000000000000000000000000000000000..ca6a25b7e4fa7ba179b1d76e2e82693bb73f9dc3 --- /dev/null +++ b/_book/docs/132.md @@ -0,0 +1,64 @@ +# Import your project from Bitbucket Cloud to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/bitbucket.html](https://docs.gitlab.com/ee/user/project/import/bitbucket.html) + +* [Overview](#overview) +* [Requirements](#requirements) +* [How it works](#how-it-works) +* [Import your Bitbucket repositories](#import-your-bitbucket-repositories) +* [Troubleshooting](#troubleshooting) + +# Import your project from Bitbucket Cloud to GitLab[](#import-your-project-from-bitbucket-cloud-to-gitlab "Permalink") + +**注意:** Bitbucket Cloud 导入程序仅适用于 Bitbucket.org,不适用于 Bitbucket Server(又名 Stash). 如果您尝试从 Bitbucket Server 导入项目,请使用[Bitbucket Server importer](bitbucket_server.html) . + +轻松地将项目从 Bitbucket Cloud 导入到 GitLab. + +## Overview[](#overview "Permalink") + +* 在当前状态下,Bitbucket 导入器可以导入: + * 仓库描述(GitLab 7.7+) + * Git 存储库数据(GitLab 7.7+) + * 问题(GitLab 7.7+) + * 问题评论(GitLab 8.15+) + * 拉取请求(GitLab 8.4+) + * 拉取请求注释(GitLab 8.15+) + * 里程碑(GitLab 8.15+) + * Wiki(GitLab 8.15+) +* 保留对拉取请求和问题的引用(GitLab 8.7+) +* 知识库公共访问权限保留. 如果存储库在 Bitbucket 中是私有的,则它也会在 GitLab 中也创建为私有的. + +## Requirements[](#requirements "Permalink") + +必须首先启用[Bitbucket Cloud 集成](../../../integration/bitbucket.html) ,以便能够从 Bitbucket Cloud 导入项目. 请您的 GitLab 管理员启用该功能(如果尚未启用). + +## How it works[](#how-it-works "Permalink") + +当导入问题/拉取请求时,Bitbucket 导入程序将尝试使用 Bitbucket `nickname`在 GitLab 的数据库中查找 Bitbucket 作者/受让人. 为此,Bitbucket 作者/受让人应事先在 GitLab 中登录并**关联其 Bitbucket 帐户** . 他们的`nickname`也必须与他们的 Bitbucket `username.`匹配`username.` . 如果在 GitLab 的数据库中找不到该用户,则将项目创建者(大多数情况下,当前用户已开始导入过程)设置为作者,但保留有关原始 Bitbucket 作者的问题的参考. + +如果不存在任何新的名称空间(组),或者如果采用了该名称空间,则导入器将创建任何新的名称空间(组),存储库将在启动导入过程的用户名称空间下导入. + +## Import your Bitbucket repositories[](#import-your-bitbucket-repositories "Permalink") + +1. Sign in to GitLab and go to your dashboard. +2. 单击**新建项目** . + +3. 点击" Bitbucket Cloud"按钮. + + [![Bitbucket](img/33da6433c882c8bcc4c699a4e0008b7c.png)](img/import_projects_from_new_project_page.png) + +4. 授予 GitLab 访问您的 Bitbucket 帐户的权限 + + [![Grant access](img/ea804dce7429c547bcf0703446150f59.png)](img/bitbucket_import_grant_access.png) + +5. 点击您要**导入的项目**或**导入所有项目** . 您还可以按名称过滤项目,并选择将在其下导入每个项目的名称空间. + + [![Import projects](img/01df5698e4465e052dcb7bf0ed6a55ae.png)](img/bitbucket_import_select_project_v12_3.png) + +## Troubleshooting[](#troubleshooting "Permalink") + +如果您拥有多个 Bitbucket 帐户,请确保登录正确的帐户. 如果您不小心以错误的帐户启动了导入过程,请按照以下步骤操作: + +1. 撤消对您的 Bitbucket 帐户的 GitLab 访问,实质上是通过以下过程来逆转该过程: [导入 Bitbucket 存储库](#import-your-bitbucket-repositories) . + +2. 退出 Bitbucket 帐户. 请遵循上一步中链接的过程. \ No newline at end of file diff --git a/_book/docs/133.md b/_book/docs/133.md new file mode 100644 index 0000000000000000000000000000000000000000..bb2ceec31706287740f3720587dd5a3410cf6ae4 --- /dev/null +++ b/_book/docs/133.md @@ -0,0 +1,71 @@ +# Import your project from Bitbucket Server to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/bitbucket_server.html](https://docs.gitlab.com/ee/user/project/import/bitbucket_server.html) + +* [Overview](#overview) +* [Limitations](#limitations) +* [How it works](#how-it-works) + * [User assignment](#user-assignment) +* [Importing your Bitbucket repositories](#importing-your-bitbucket-repositories) +* [Troubleshooting](#troubleshooting) + +# Import your project from Bitbucket Server to GitLab[](#import-your-project-from-bitbucket-server-to-gitlab "Permalink") + +在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20164) . + +**注意:** Bitbucket Server 导入程序不适用于[Bitbucket Cloud](https://bitbucket.org) . 为此,请使用[Bitbucket Cloud 导入](bitbucket.html)程序. + +轻松地将项目从 Bitbucket Server 导入到 GitLab. + +## Overview[](#overview "Permalink") + +* 在当前状态下,Bitbucket 导入器可以导入: + * 仓库描述(GitLab 11.2+) + * Git 存储库数据(GitLab 11.2+) + * 拉取请求(GitLab 11.2+) + * 拉取请求注释(GitLab 11.2+) +* 知识库公共访问权限保留. 如果存储库在 Bitbucket 中是私有的,则它也会在 GitLab 中也创建为私有的. + +## Limitations[](#limitations "Permalink") + +1. 目前,GitLab 不允许在任意代码行上添加注释,因此任何超出范围的 Bitbucket 注释都将作为注释插入到合并请求中. +2. Bitbucket Server 允许多个级别的线程. GitLab 导入会将其折叠到一个线程中,并引用原始注释的一部分. +3. 拒绝的拉取请求具有无法到达的提交,这会阻止 GitLab 导入器生成适当的差异. 这些拉取请求将显示为空更改. +4. Markdown 中的附件当前未导入. +5. 任务列表未导入. +6. 表情符号反应未导入 +7. 项目过滤不支持模糊搜索(当前仅支持`starts with`或`full match strings` ) + +## How it works[](#how-it-works "Permalink") + +Bitbucket 服务器导入程序的工作方式如下: + +1. 系统将提示用户输入 URL,用户名和密码(或个人访问令牌)以登录到 Bitbucket. 这些凭据仅在导入程序运行时才保留. +2. 导入程序将尝试列出 Bitbucket 服务器上的所有当前存储库. +3. 选择后,导入程序将克隆存储库并导入拉取请求和注释. + +### User assignment[](#user-assignment "Permalink") + +当导入问题/拉取请求时,Bitbucket 导入器将尝试在 GitLab 用户数据库中查找作者的电子邮件地址以及已确认的电子邮件地址. 如果没有这样的用户可用,则将项目创建者设置为作者. 进口商将在注释中添加注释以标记原始创建者. + +如果不存在任何新的名称空间(组),或者如果采用了该名称空间,则导入器将创建任何新的名称空间(组),存储库将在启动导入过程的用户名称空间下导入. + +## Importing your Bitbucket repositories[](#importing-your-bitbucket-repositories "Permalink") + +1. 登录到 GitLab 并转到您的仪表板. +2. 单击**新建项目** . +3. 点击" Bitbucket 服务器"按钮. 如果该按钮不存在,请在**管理>应用程序设置>可见性和访问控制>导入源中**启用**导入器** . + + [![Bitbucket](img/33da6433c882c8bcc4c699a4e0008b7c.png)](img/import_projects_from_new_project_page.png) + +4. 输入您的 Bitbucket 服务器凭据. + + [![Grant access](img/cca5497f42d0f0512126392deb81fa3e.png)](img/bitbucket_server_import_credentials.png) + +5. 点击您要**导入的项目**或**导入所有项目** . 您还可以按名称过滤项目,并选择将在其下导入每个项目的名称空间. + + [![Import projects](img/c43432893b48081561609f3667b7d497.png)](img/bitbucket_server_import_select_project_v12_3.png) + +## Troubleshooting[](#troubleshooting "Permalink") + +请参阅[Bitbucket](bitbucket.html)的[故障排除](bitbucket.html#troubleshooting)部分. \ No newline at end of file diff --git a/_book/docs/134.md b/_book/docs/134.md new file mode 100644 index 0000000000000000000000000000000000000000..5dfc6f0eab9a1bce8402f5a5c1b8eccdff1b4dd4 --- /dev/null +++ b/_book/docs/134.md @@ -0,0 +1,46 @@ +# Migrating from ClearCase + +> 原文:[https://docs.gitlab.com/ee/user/project/import/clearcase.html](https://docs.gitlab.com/ee/user/project/import/clearcase.html) + +* [Why migrate](#why-migrate) +* [How to migrate](#how-to-migrate) + +# Migrating from ClearCase[](#migrating-from-clearcase "Permalink") + +[ClearCase](https://www.ibm.com/us-en/marketplace/rational-clearcase)是 IBM 开发的一组工具,还包括类似于 Git 的集中式版本控制系统. + +可以在此[StackOverflow 帖子中](https://stackoverflow.com/a/645771/974710)找到有关 ClearCase 基本概念的良好阅读. + +下表说明了 ClearCase 和 Git 之间的主要区别: + +| Aspect | ClearCase | Git | +| --- | --- | --- | +| 仓库模型 | Client-server | Distributed | +| 修订版 ID | 分行号 | 全局字母数字 ID | +| 变更范围 | File | 目录树快照 | +| 并发模型 | Merge | Merge | +| 储存方式 | Deltas | 全部内容 | +| Client | CLI,Eclipse,CC 客户端 | CLI,Eclipse,Git 客户端/ GUI | +| Server | UNIX,Windows 旧式系统 | UNIX,macOS | +| License | Proprietary | GPL | + +*选自 ClearClase 幻灯片[和](https://www.open.collab.net/media/pdfs/ClearCase-and-the-journey-to-Git.pdf) collab.net 提供的[Git 之旅](https://www.open.collab.net/media/pdfs/ClearCase-and-the-journey-to-Git.pdf)* + +## Why migrate[](#why-migrate "Permalink") + +从用户和管理员的角度来看,ClearCase 都可能难以管理. 迁移到 Git / GitLab 有: + +* **没有许可费用** ,Git 是 GPL,而 ClearCase 是专有的. +* **学习曲线更短** ,Git 有一个庞大的社区和大量的入门指南. +* **与现代工具集成** ,迁移到 Git 和 GitLab,您可以拥有一个开源的端到端软件开发平台,该平台具有内置的版本控制,问题跟踪,代码审查,CI / CD 等. + +## How to migrate[](#how-to-migrate "Permalink") + +虽然不存在从 ClearCase 完全迁移到 Git 的工具,但是这里有一些有用的链接可以帮助您入门: + +* [Bridge for Git and ClearCase](https://github.com/charleso/git-cc) +* [Slides “ClearCase and the journey to Git”](https://www.open.collab.net/media/pdfs/ClearCase-and-the-journey-to-Git.pdf) +* [ClearCase to Git](https://therub.org/2013/07/19/clearcase-to-git/) +* [Dual syncing ClearCase to Git](https://therub.org/2013/10/22/dual-syncing-clearcase-and-git/) +* [Moving to Git from ClearCase](https://sateeshkumarb.wordpress.com/2011/01/15/moving-to-git-from-clearcase/) +* [ClearCase to Git webinar](https://www.brighttalk.com/webcast/11817/162473/clearcase-to-git) \ No newline at end of file diff --git a/_book/docs/135.md b/_book/docs/135.md new file mode 100644 index 0000000000000000000000000000000000000000..bed5388f0015a2d74d0616b4ce6b95bd0b6cbf54 --- /dev/null +++ b/_book/docs/135.md @@ -0,0 +1,41 @@ +# Migrating from CVS + +> 原文:[https://docs.gitlab.com/ee/user/project/import/cvs.html](https://docs.gitlab.com/ee/user/project/import/cvs.html) + +* [CVS vs Git](#cvs-vs-git) +* [Why migrate](#why-migrate) +* [How to migrate](#how-to-migrate) + +# Migrating from CVS[](#migrating-from-cvs "Permalink") + +[CVS](https://savannah.nongnu.org/projects/cvs)是类似于[SVN](svn.html)的旧式集中版本控制系统. + +## CVS vs Git[](#cvs-vs-git "Permalink") + +以下列表说明了 CVS 和 Git 之间的主要区别: + +* **Git 已分发.** 另一方面,CVS 使用客户端-服务器体系结构进行集中管理. 这意味着 Git 具有更灵活的工作流程,因为您的工作区是整个存储库的副本. 例如,由于不必与远程服务器进行通信,因此这减少了切换分支或合并时的开销. +* **原子操作.** 在 Git 中,所有操作都是[原子](https://en.wikipedia.org/wiki/Atomic_commit)操作,它们要么全部成功,要么失败而没有任何更改. 在 CVS 中,提交(和其他操作)不是原子的. 如果对存储库的操作在中间中断,则存储库可能处于不一致状态. +* **存放方法.** CVS 中的更改是按文件(更改集)进行的,而在 Git 中,已提交的文件将全部存储(快照). 这意味着在 Git 中还原或撤消整个更改非常容易. +* **修订版 ID.** 在 CVS 中,更改是针对每个文件的,修订 ID 由版本号表示,例如`1.4`反映了给定文件已更改了多少次. 在 Git 中,整个项目的每个版本(每次提交)的唯一名称都由 SHA-1 给出. +* **合并跟踪.** Git 使用一种先合并后提交的方法,而不是像 CVS 那样先合并后提交(或先更新再提交). 如果在准备创建新提交(新修订版)时有人在同一个分支上创建了一个新提交并推送到中央存储库,则 CVS 将强制您首先更新工作目录并解决冲突,然后再允许您提交. Git 并非如此. 您首先提交,将状态保存在版本控制中,然后合并其他开发人员的更改. 您还可以要求其他开发人员进行合并并自己解决任何冲突. +* **签名提交.** Git 支持使用 GPG 对提交进行签名,以提高安全性并验证提交确实来自其原始作者. GitLab 可以[与 GPG 集成,](../repository/gpg_signed_commits/index.html)并显示签名提交是否得到正确验证. + +*上面的一些内容摘自这个很棒的[Stack Overflow 帖子](https://stackoverflow.com/a/824241/974710) . 有关差异的更完整列表,请查阅 Wikipedia 上有关[比较不同版本控制软件的文章](https://en.wikipedia.org/wiki/Comparison_of_version_control_software) .* + +## Why migrate[](#why-migrate "Permalink") + +CVS 较旧,自 2008 年以来没有新版本发布.Git 提供了更多可使用的工具( `git bisect`之一),这使工作流程更加高效. 迁移到 Git / GitLab 有: + +* **学习曲线更短** ,Git 具有庞大的社区和大量的入门指南(请参阅我们的[Git 主题](../../../topics/git/index.html) ). +* **与现代工具集成** ,迁移到 Git 和 GitLab,您可以拥有一个开源的端到端软件开发平台,该平台具有内置的版本控制,问题跟踪,代码审查,CI / CD 等. +* **支持许多网络协议** . Git 支持 SSH,HTTP / HTTPS 和 rsync 等,而 CVS 仅支持 SSH 及其自身的不安全的 pserver 协议,无需用户身份验证. + +## How to migrate[](#how-to-migrate "Permalink") + +以下是一些链接,可帮助您开始进行迁移: + +* [Migrate using the `cvs-fast-export` tool](http://www.catb.org/~esr/reposurgeon/dvcs-migration-guide.html) ([*source code*](https://gitlab.com/esr/cvs-fast-export)) +* [Stack Overflow post on importing the CVS repo](https://stackoverflow.com/a/11490134/974710) +* [Convert a CVS repository to Git](https://www.techrepublic.com/blog/linux-and-open-source/convert-cvs-repositories-to-git/) +* [Man page of the `git-cvsimport` tool](https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-cvsimport.html) \ No newline at end of file diff --git a/_book/docs/136.md b/_book/docs/136.md new file mode 100644 index 0000000000000000000000000000000000000000..c4eb1168aa178c67521d3fbb4acac09fee11a0a7 --- /dev/null +++ b/_book/docs/136.md @@ -0,0 +1,28 @@ +# Import your project from FogBugz to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/fogbugz.html](https://docs.gitlab.com/ee/user/project/import/fogbugz.html) + +# Import your project from FogBugz to GitLab[](#import-your-project-from-fogbugz-to-gitlab "Permalink") + +从 FogBugz 导入项目只需几个简单的步骤. 导入程序将导入您的所有案例和注释以及原始案例编号和时间戳. 您还将有机会将 FogBugz 用户映射到 GitLab 用户. + +1. 在您的 GitLab 仪表板中,单击"新建项目" +2. 点击" FogBugz"按钮 + +[![FogBugz](img/191e4984d9e1aa615a86fec2b6d42dcd.png)](img/fogbugz_import_select_fogbogz.png) + +1. 输入您的 FogBugz URL,电子邮件地址和密码. + +[![Login](img/2b49f82a2ff96781b55685367813e6c9.png)](img/fogbugz_import_login.png) + +1. 创建从 FogBugz 用户到 GitLab 用户的映射. + +[![User Map](img/e71e8b254fc758ab1a18ac4373e14344.png)](img/fogbugz_import_user_map.png) + +1. 通过单击导入按钮选择要导入的项目 + +[![Import Project](img/d677bbf1d2f77fd7394cddab976e6f67.png)](img/fogbugz_import_select_project.png) + +1. 导入完成后,单击链接将您带到项目仪表板. 按照说明推送现有存储库. + +[![Finished](img/1b984d904256e7a325a4cc30bcf71ee1.png)](img/fogbugz_import_finished.png) \ No newline at end of file diff --git a/_book/docs/137.md b/_book/docs/137.md new file mode 100644 index 0000000000000000000000000000000000000000..4672b9c3c4c8e0a664e58c22c747a368c51233f3 --- /dev/null +++ b/_book/docs/137.md @@ -0,0 +1,84 @@ +# Gemnasium + +> 原文:[https://docs.gitlab.com/ee/user/project/import/gemnasium.html](https://docs.gitlab.com/ee/user/project/import/gemnasium.html) + +* [Why is Gemnasium.com closed?](#why-is-gemnasiumcom-closed) +* [What happened to my account?](#what-happened-to-my-account) +* [Will my account/data be transferred to GitLab Inc.?](#will-my-accountdata-be-transferred-to-gitlab-inc) +* [What happened to my badge?](#what-happened-to-my-badge) +* [Migrating to GitLab](#migrating-to-gitlab) + * [If your project is hosted on GitLab (`https://gitlab.com` / self-managed)](#if-your-project-is-hosted-on-gitlab-httpsgitlabcom--self-managed) + * [If your project is hosted on GitHub (`https://github.com` / GitHub Enterprise)](#if-your-project-is-hosted-on-github-httpsgithubcom--github-enterprise) + +# Gemnasium[](#gemnasium-ultimate "Permalink") + +本指南介绍了如何从 Gemnasium.com 迁移到您自己的 GitLab 实例或 GitLab.com. + +## Why is Gemnasium.com closed?[](#why-is-gemnasiumcom-closed "Permalink") + +Gemnasium 在 2018 年 1 月[被 GitLab 收购](https://about.gitlab.com/press/releases/2018-01-30-gemnasium-acquisition.html) .自 2018 年 5 月 15 日起,Gemnasium 提供的服务不再可用. Gemnasium 背后的团队已加入 GitLab,成为新的安全产品团队,并且正在开发[各种工具](../../application_security/index.html) ,包括: + +* [Dependency Scanning](../../application_security/dependency_scanning/index.html) +* [SAST](../../application_security/sast/index.html) +* [DAST](../../application_security/dast/index.html) +* [Container Scanning](../../application_security/container_scanning/index.html) + +如果要继续监视依赖项,请参见下面的" [迁移到 GitLab"](#migrating-to-gitlab)部分. + +## What happened to my account?[](#what-happened-to-my-account "Permalink") + +您的帐户已于 2018 年 5 月 15 日自动关闭.如果您当时有付费订阅,则您的卡将按比例退还. 您可以联系`gemnasium@gitlab.com`了解您的已关闭帐户. + +## Will my account/data be transferred to GitLab Inc.?[](#will-my-accountdata-be-transferred-to-gitlab-inc "Permalink") + +所有帐户和数据已于 2018 年 5 月 15 日被删除.GitLab Inc.对您的私人数据或项目一无所知,因此不知道它们是否容易受到攻击. GitLab Inc.非常重视个人信息. + +## What happened to my badge?[](#what-happened-to-my-badge "Permalink") + +为避免损坏的 404 图像,所有指向 Gemnasium.com 的徽章都将用作占位符,邀请您迁移到 GitLab(并指向此页面). + +## Migrating to GitLab[](#migrating-to-gitlab "Permalink") + +Gemnasium 已被移植并直接集成到 GitLab CI / CD 中. 您仍然可以从我们的依赖项监视功能中受益,并且需要一些步骤来迁移项目. 由于 GitLab 对 Gemnasium.com 上存在的任何项目一无所知,因此没有自动导入. GitLab.com 上托管的公共(开源)项目免费提供安全功能. + +### If your project is hosted on GitLab (`https://gitlab.com` / self-managed)[](#if-your-project-is-hosted-on-gitlab-httpsgitlabcom--self-managed "Permalink") + +您快要准备好了! 如果您已经在使用[Auto DevOps](../../../topics/autodevops/) ,那么您已经了解了. 否则,您必须根据[依赖项扫描页面](../../application_security/dependency_scanning/index.html)配置`.gitlab-ci.yml` . + +### If your project is hosted on GitHub (`https://github.com` / GitHub Enterprise)[](#if-your-project-is-hosted-on-github-httpsgithubcom--github-enterprise "Permalink") + +由于[GitLab 10.6 带有 GitHub 集成](https://about.gitlab.com/solutions/github/) ,因此 GitLab 用户现在可以在 GitLab 中创建一个 CI / CD 项目,该项目连接到外部 GitHub.com 或 GitHub Enterprise 仓库. 每当将代码推送到 GitHub 时,这都会自动提示 GitLab CI / CD 运行,并在完成后将 CI / CD 结果发布回 GitLab 和 GitHub. + +1. 创建一个新项目,然后选择"用于外部仓库的 CI / CD"选项卡: + + [![Create new Project](img/e3489f723615b369a1abec41ebe9dea2.png)](img/gemnasium/create_project.png) + +2. 使用" GitHub"按钮连接存储库. + + [![Connect from GitHub](img/7ebc386f852ada24782fd3b7e5dd226e.png)](img/gemnasium/connect_github.png) + +3. 选择要使用 GitLab CI / CD 设置的项目,然后选择"连接". + + [![Select projects](img/611650a65dd2baf63b32d99fbe8e4a8a.png)](img/gemnasium/select_project.png) + + 配置完成后,您可以在 GitLab 上单击新项目. + + [![click on connected project](img/35b66299a79c8b3212bf8fbb00e9c903.png)](img/gemnasium/project_connected.png) + + 现在,您的项目已镜像到 GitLab,Runners 可以在其中访问您的源代码并运行您的测试. + + 可选步骤:如果您在 GitHub 项目是公共的,则在 GitLab.com 上进行设置,请确保该项目是公共的(在项目设置中),因为该安全功能仅适用于[GitLab Ultimate](https://about.gitlab.com/pricing/) . + +4. 要设置与 Gemnasium 所做的工作相对应的依赖项扫描作业,您必须创建`.gitlab-ci.yml`文件,或根据[依赖项扫描文档](../../application_security/dependency_scanning/index.html)对其进行更新. 默认情况下,镜像是仅拉式的,因此您可以在 GitHub 上创建或更新文件: + + [![Edit gitlab-ci.yml file](img/6427e1b107996a8eb9c401e1aa76bf87.png)](img/gemnasium/edit_gitlab-ci.png) + +5. 提交文件后,如果文件有效,将自动触发新的管道: + + [![pipeline](img/97acbf99c97921ca9e5837c4c70cfa4c.png)](img/gemnasium/pipeline.png) + +6. 作业的结果将直接在管道视图中可见: + + [![Security Dashboard](img/f0d8585fb8235b36b1464ed1d142a4c0.png)](../../application_security/security_dashboard/img/pipeline_security_dashboard_v13_2.png) + +**注意:**如果您不经常提交项目,则可能要使用[计划的管道](../../../ci/pipelines/schedules.html)定期运行作业. \ No newline at end of file diff --git a/_book/docs/138.md b/_book/docs/138.md new file mode 100644 index 0000000000000000000000000000000000000000..7e9b8c9ff825808e950a32335b78a56c64ef731c --- /dev/null +++ b/_book/docs/138.md @@ -0,0 +1,119 @@ +# Import your project from GitHub to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/github.html](https://docs.gitlab.com/ee/user/project/import/github.html) + +* [Overview](#overview) +* [How it works](#how-it-works) +* [Import your GitHub repository into GitLab](#import-your-github-repository-into-gitlab) + * [Using the GitHub integration](#using-the-github-integration) + * [Using a GitHub token](#using-a-github-token) + * [Selecting which repositories to import](#selecting-which-repositories-to-import) +* [Mirroring and pipeline status sharing](#mirroring-and-pipeline-status-sharing) +* [Improving the speed of imports on self-managed instances](#improving-the-speed-of-imports-on-self-managed-instances) + +# Import your project from GitHub to GitLab[](#import-your-project-from-github-to-gitlab "Permalink") + +使用导入器,您可以将 GitHub 存储库导入 GitLab.com 或自管理的 GitLab 实例. + +## Overview[](#overview "Permalink") + +**注意:**这些说明适用于 GitLab.com 上的用户,但是如果您是自助 GitLab 实例的管理员,或者要从 GitHub Enterprise 导入,则必须启用[GitHub 集成](../../../integration/github.html) . GitHub 集成是从 GitHub Enterprise 导入的唯一方法. 如果您使用的是 GitLab.com,则可以使用[个人访问令牌](#using-a-github-token)导入 GitHub 存储库,但不建议使用此方法,因为该方法无法将所有用户活动(例如问题和请求请求)与匹配的 GitLab 用户相关联. 如果您是自我管理的 GitLab 实例的管理员,则还可以使用[GitHub Rake 任务](../../../administration/raketasks/github_import.html)从 GitHub 导入项目,而不受 Sidekiq worker 的限制. + +导入了项目的以下方面: + +* 仓库描述(GitLab.com&7.7+) +* Git 存储库数据(GitLab.com&7.7+) +* 问题(GitLab.com 和 7.7+) +* 拉取请求(GitLab.com&8.4+) +* Wiki 页面(GitLab.com&8.4+) +* 里程碑(GitLab.com&8.7+) +* 标签(GitLab.com 和 8.7+) +* 发行说明说明(GitLab.com 和 8.12+) +* 拉取请求评论评论(GitLab.com&10.2+) +* 定期发布和请求请求注释 + +保留对拉取请求和问题的引用(GitLab.com&8.7+),并且每个导入的存储库都保持可见性级别,除非该[可见性级别受到限制](../../../public_access/public_access.html#restricting-the-use-of-public-or-internal-projects) ,在这种情况下,它默认为默认项目可见性. + +## How it works[](#how-it-works "Permalink") + +导入问题和请求请求时,导入程序会尝试在 GitLab 实例的数据库中查找其 GitHub 作者和受让人(请注意,请求请求在 GitLab 中称为"合并请求"). + +For this association to succeed, each GitHub author and assignee in the repository must meet one of the following conditions prior to the import: + +* 以前使用 GitHub 图标登录到 GitLab 帐户. +* 有一个 GitHub 帐户,其[主要电子邮件地址](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/setting-your-commit-email-address)与其 GitLab 帐户的电子邮件地址匹配. + +如果在 GitLab 的数据库中未找到项目中引用的用户,则将项目创建者(通常是启动导入过程的用户)设置为作者/受让人,但是会添加关于该问题的注释,其中提及原始 GitHub 作者. + +如果不存在任何新的名称空间(组),或者如果采用了名称空间,则导入器会创建存储库,该存储库将在启动导入过程的用户的名称空间下导入. 命名空间/存储库名称也可以使用适当的权限进行编辑. + +进口商还将在与未完成拉取请求相关的项目的分支上导入分支. 这些分支将以类似于`GH-SHA-username/pull-request-number/fork-name/branch`的命名方案导入. 与 GitHub 存储库相比,这可能导致分支中的差异. + +有关更多技术细节,您可以参考[GitHub Importer](../../../development/github_importer.html "使用 GitHub 导入器")开发人员文档. + +有关导入过程的概述,请参阅[从 GitHub 迁移到 GitLab](https://youtu.be/VYOXuOg9tQI)的视频. + +## Import your GitHub repository into GitLab[](#import-your-github-repository-into-gitlab "Permalink") + +### Using the GitHub integration[](#using-the-github-integration "Permalink") + +在开始之前,请确保要映射到 GitLab 用户的所有 GitHub 用户都具有以下任一条件: + +* 使用 GitHub 图标登录的 GitLab 帐户-或- +* 一个 GitLab 帐户,其电子邮件地址与 GitHub 用户的[公共电子邮件地址](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/setting-your-commit-email-address)匹配 + +用户匹配尝试将按该顺序进行,并且如果两种方法均未识别到用户,则该活动将与执行导入的用户帐户相关联. + +**注意:**如果您使用的是自助式 GitLab 实例,或者要从 GitHub Enterprise 导入,则此过程要求您已配置[GitHub 集成](../../../integration/github.html) . + +1. 在顶部导航栏中,单击**+** ,然后选择**新建项目** . +2. 选择**导入项目**选项卡,然后选择**GitHub** . +3. 选择第一个按钮以**列出您的 GitHub 存储库** . 您将被重定向到[GitHub 上](https://github.com)的页面以授权 GitLab 应用程序. +4. 点击**授权 gitlabhq** . 您将被重定向回 GitLab 的 Import 页面,并列出所有 GitHub 存储库. +5. 继续[选择要导入的存储库](#selecting-which-repositories-to-import) . + +### Using a GitHub token[](#using-a-github-token "Permalink") + +**注意:**不建议使用个人访问令牌导入项目. 如果您是 GitLab.com 用户,则可以使用个人访问令牌从 GitHub 导入项目,但是该方法无法将所有用户活动(例如问题和请求请求)与匹配的 GitLab 用户关联. 如果您是自我管理的 GitLab 实例的管理员,或者要从 GitHub Enterprise 导入,则不能使用个人访问令牌. 建议所有用户使用[GitHub 集成方法(上述)](#using-the-github-integration) . 在" [如何工作"](#how-it-works)部分中了解更多信息. + +如果您不使用 GitHub 集成,则仍可以通过 GitHub 执行授权以授予 GitLab 访问您的存储库的权限: + +1. 转到[https://github.com/settings/tokens/new](https://github.com/settings/tokens/new) +2. 输入令牌描述. +3. 选择回购范围​​. +4. Click **生成令牌**. +5. 复制令牌哈希. +6. 返回到 GitLab 并将令牌提供给 GitHub 导入器. +7. 点击**列出您的 GitHub 存储库**按钮,并等待 GitLab 读取您的存储库信息. 完成后,将带您到导入器页面以选择要导入的存储库. + +### Selecting which repositories to import[](#selecting-which-repositories-to-import "Permalink") + +在授权访问 GitHub 存储库后,您将重定向到 GitHub 导入程序页面,并列出 GitHub 存储库. + +1. 默认情况下,建议的存储库名称空间与 GitHub 中存在的名称匹配,但是根据您的权限,您可以选择在继续导入任何名称之前编辑这些名称. +2. 选择任意数量的存储库旁边的**导入**按钮,或选择**导入所有存储库** . 此外,您可以按名称过滤项目. 如果应用了过滤器,则" **导入所有存储库"**仅导入匹配的存储库. +3. " **状态"**列显示每个存储库的导入状态. 您可以选择让页面保持打开状态,它将实时更新,也可以稍后返回. +4. 导入存储库后,单击其 GitLab 路径以打开其 GitLab URL. + +[![Github importer page](img/67f7d8117f3d6bf60fe4d5e03bca7b6e.png)](img/import_projects_from_github_importer_v12_3.png) + +## Mirroring and pipeline status sharing[](#mirroring-and-pipeline-status-sharing "Permalink") + +根据您的 GitLab 层,可以设置[项目镜像](../repository/repository_mirroring.html) ,以使导入的项目与其 GitHub 副本保持同步. + +此外,您可以配置 GitLab 以通过[GitHub Project Integration](../integrations/github.html)将管道状态更新发送回 GitHub. + +如果使用[CI / CD 作为外部存储库](../../../ci/ci_cd_for_external_repos/index.html)导入项目,则会自动配置以上两项. + +## Improving the speed of imports on self-managed instances[](#improving-the-speed-of-imports-on-self-managed-instances "Permalink") + +**注意:**必须具有对 GitLab 服务器的管理员访问权限. + +对于大型项目,可能需要一段时间才能导入所有数据. 为了减少必要的时间,您可以增加处理以下队列的 Sidekiq 工作程序的数量: + +* `github_importer` +* `github_importer_advance_stage` + +For an optimal experience, it’s recommended having at least 4 Sidekiq processes (each running a number of threads equal to the number of CPU cores) that *only* process these queues. It’s also recommended that these processes run on separate servers. For 4 servers with 8 cores this means you can import up to 32 objects (e.g., issues) in parallel. + +减少克隆存储库所花费的时间可以通过增加存储 Git 存储库(适用于您的 GitLab 实例)的磁盘的网络吞吐量,CPU 容量和磁盘性能(例如,使用高性能 SSD)来完成. 增加 Sidekiq 工作人员的数量*不会*减少克隆存储库所花费的时间. \ No newline at end of file diff --git a/_book/docs/139.md b/_book/docs/139.md new file mode 100644 index 0000000000000000000000000000000000000000..0d1bdbae5d497f853f5aec8b491459f05ac3042a --- /dev/null +++ b/_book/docs/139.md @@ -0,0 +1,19 @@ +# Project importing from GitLab.com to your private GitLab instance + +> 原文:[https://docs.gitlab.com/ee/user/project/import/gitlab_com.html](https://docs.gitlab.com/ee/user/project/import/gitlab_com.html) + +# Project importing from GitLab.com to your private GitLab instance[](#project-importing-from-gitlabcom-to-your-private-gitlab-instance "Permalink") + +您可以将现有的 GitLab.com 项目导入到 GitLab 实例中,但请记住,只有在 GitLab 实例上启用了 GitLab.com 集成后,才有可能. [阅读有关 GitLab.com 集成的更多信息,以实现自我管理的 GitLab 实例](../../../integration/gitlab.html) . + +要进入进口商页面,您需要进入"新项目"页面. + +> **注意:**如果您有兴趣将 Wiki 和合并请求数据导入到新实例,则需要按照说明[导出项目](../settings/import_export.html#exporting-a-project-and-its-data) + +[![New project page](img/0d0a16295f0edf554f921ffda49ff421.png)](img/gitlab_new_project_page_v12_2.png) + +转到" **导入项目"**选项卡,然后单击**GitLab.com** ,您将被重定向到 GitLab.com 以获取访问项目的权限. 接受后,您将自动重定向到导入程序. + +[![Importer page](img/e0fb1b28f653637edd64e072798f2385.png)](img/gitlab_importer.png) + +要导入项目,请单击"导入". 导入程序将导入您的存储库和问题. 导入器完成后,将使用导入的数据创建一个新的 GitLab 项目. \ No newline at end of file diff --git a/_book/docs/140.md b/_book/docs/140.md new file mode 100644 index 0000000000000000000000000000000000000000..d5f9fda63ad4d36d57cdaf8d9d6cb08e58c1ba7d --- /dev/null +++ b/_book/docs/140.md @@ -0,0 +1,73 @@ +# Import your project from Gitea to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/gitea.html](https://docs.gitlab.com/ee/user/project/import/gitea.html) + +* [Overview](#overview) +* [How it works](#how-it-works) +* [Importing your Gitea repositories](#importing-your-gitea-repositories) + * [Authorize access to your repositories using a personal access token](#authorize-access-to-your-repositories-using-a-personal-access-token) + * [Select which repositories to import](#select-which-repositories-to-import) + +# Import your project from Gitea to GitLab[](#import-your-project-from-gitea-to-gitlab "Permalink") + +Import your projects from Gitea to GitLab with minimal effort. + +## Overview[](#overview "Permalink") + +> **注意:**这需要 Gitea `v1.0.0`或更高版本. + +* 在当前状态下,Gitea 进口商可以进口: + * 仓库描述(GitLab 8.15+) + * Git 存储库数据(GitLab 8.15+) + * 问题(GitLab 8.15+) + * 拉取请求(GitLab 8.15+) + * 里程碑(GitLab 8.15+) + * 标签(GitLab 8.15+) +* 知识库公共访问权限保留. 如果存储库在 Gitea 中是私有的,则它也将在 GitLab 中创建为私有的. + +## How it works[](#how-it-works "Permalink") + +由于 Gitea 当前不是 OAuth 提供者,因此无法将作者/受让人映射到您的 GitLab 实例中的用户. 这意味着将项目创建者(大多数情况下是当前开始导入过程的当前用户)设置为作者,但是保留了有关原始 Gitea 作者的问题的参考. + +如果不存在任何新的名称空间(组),或者如果采用了该名称空间,则导入器将创建任何新的名称空间(组),存储库将在启动导入过程的用户名称空间下导入. + +## Importing your Gitea repositories[](#importing-your-gitea-repositories "Permalink") + +创建新项目时,将显示导入器页面. + +[![New project page on GitLab](img/33da6433c882c8bcc4c699a4e0008b7c.png)](img/import_projects_from_new_project_page.png) + +单击**Gitea**链接,导入授权过程将开始. + +[![New Gitea project import](img/23b032de89e1f1056b75bd7ad55823ea.png)](img/import_projects_from_gitea_new_import.png) + +### Authorize access to your repositories using a personal access token[](#authorize-access-to-your-repositories-using-a-personal-access-token "Permalink") + +使用这种方法,您将对 Gitea 执行一次性授权,以授权 GitLab 访问您的存储库: + +1. 转到`https://your-gitea-instance/user/settings/applications` (将`your-gitea-instance`替换`your-gitea-instance`的主机). +2. Click **生成新令牌**. +3. 输入令牌描述. +4. Click **生成令牌**. +5. 复制令牌哈希. +6. 返回到 GitLab 并将令牌提供给 Gitea 进口商. +7. 点击**列出您的 Gitea 存储库**按钮,然后等待 GitLab 读取您的存储库信息. 完成后,将带您到导入器页面以选择要导入的存储库. + +### Select which repositories to import[](#select-which-repositories-to-import "Permalink") + +在授权访问 Gitea 存储库后,您将被重定向到 Gitea 导入程序页面. + +从那里,您可以查看 Gitea 存储库的导入状态. + +* 那些正在导入的将显示*开始*状态, +* 那些已经成功导入的将变成绿色,状态为" *完成"* , +* 而尚未导入的表格将在表格的右侧具有" **导入"**按钮. + +您还可以: + +* 点击左上角的" **导入所有项目"** ,一次性导入所有 Gitea 项目. +* 按名称过滤项目. 如果应用了过滤器,则点击**导入所有项目**将仅导入匹配的项目 + +[![Gitea importer page](img/2c8994d4c86769ec5151192ff555b261.png)](img/import_projects_from_gitea_importer_v12_3.png) + +如果您有特权,也可以为项目选择其他名称和名称空间. \ No newline at end of file diff --git a/_book/docs/141.md b/_book/docs/141.md new file mode 100644 index 0000000000000000000000000000000000000000..8509befa96a43bc2cbcb606e6d0ad13413144016 --- /dev/null +++ b/_book/docs/141.md @@ -0,0 +1,67 @@ +# Import your Jira project issues to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/jira.html](https://docs.gitlab.com/ee/user/project/import/jira.html) + +* [Future iterations](#future-iterations) +* [Prerequisites](#prerequisites) + * [Permissions](#permissions) + * [Jira integration](#jira-integration) +* [Import Jira issues to GitLab](#import-jira-issues-to-gitlab) + +# Import your Jira project issues to GitLab[](#import-your-jira-project-issues-to-gitlab "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2766) . + +使用 GitLab Jira 导入器,您可以将 Jira 问题导入到 GitLab.com 或您自己管理的 GitLab 实例. + +Jira 问题导入是 MVC 项目级别的功能,这意味着可以将来自多个 Jira 项目的问题导入到 GitLab 项目中. MVC 版本将问题标题和描述以及一些其他问题元数据作为问题描述的一部分导入. + +## Future iterations[](#future-iterations "Permalink") + +从 GitLab 12.10 开始,Jira 问题导入程序仅提供问题的标题和描述. + +有[史诗般的](https://gitlab.com/groups/gitlab-org/-/epics/2738)跟踪项目的添加,例如问题受让人,标签,评论,用户映射等等. 这些将包含在 GitLab Jira 进口商的未来版本中. + +## Prerequisites[](#prerequisites "Permalink") + +### Permissions[](#permissions "Permalink") + +In order to be able to import issues from a Jira project you need to have read access on Jira issues and a [Maintainer or higher](../../permissions.html#project-members-permissions) role in the GitLab project that you wish to import into. + +### Jira integration[](#jira-integration "Permalink") + +此功能使用现有的 GitLab [Jira 集成](../integrations/jira.html) . + +在尝试导入 Jira 问题之前,请确保已设置集成. + +## Import Jira issues to GitLab[](#import-jira-issues-to-gitlab "Permalink") + +GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/216145)了新的导入表单. + +要将 Jira 问题导入到 GitLab 项目,请执行以下步骤. + +**注意:**导入 Jira 问题是作为异步后台作业完成的,这可能会由于导入队列负载,系统负载或其他因素而导致延迟. 导入大型项目可能需要几分钟,具体取决于导入的大小. + +1. 在 **在问题**页面上,点击**导入问题** ( ) **>从 Jira 导入** . + + [![Import issues from Jira button](img/6b48060a3ef4c055e75a74e6a396ebb9.png)](img/jira/import_issues_from_jira_button_v12_10.png) + + 仅当您具有[正确的权限时,"](#permissions) **从 Jira 导入"**选项才可见. + + 出现以下形式. 如果您先前已经设置了[Jira 集成](../integrations/jira.html) ,现在可以在下拉列表中看到您有权访问的 Jira 项目. + + [![Import issues from Jira form](img/c10c0f19a1d0076044db1057cfb19875.png)](img/jira/import_issues_from_jira_form_v13_2.png) + +2. 单击**导入自**下拉列表,然后选择要从中导入问题的 Jira 项目. + + 在" **Jira-GitLab 用户映射模板"**部分中,该表显示了您的 Jira 用户将映射到哪些 GitLab 用户. 如果无法将 Jira 用户与 GitLab 用户匹配,则该下拉列表默认为执行导入的用户. + +3. 要更改任何建议的映射,请单击**GitLab 用户名列中**的下拉列表,然后选择要映射到每个 Jira 用户的用户. + + 该下拉列表可能不会显示所有用户,因此请使用搜索栏在此 GitLab 项目中查找特定用户. + +4. 点击**继续** . 系统会提示您已开始导入. + + 当导入在后台运行时,您可以从导入状态页面导航到问题页面,并且您会看到新问题出现在问题列表中. + +5. 要检查导入状态,请再次转到" Jira 导入"页面. \ No newline at end of file diff --git a/_book/docs/142.md b/_book/docs/142.md new file mode 100644 index 0000000000000000000000000000000000000000..970fe9a52bdd57087ad8b6f73bf2b0900e352a0e --- /dev/null +++ b/_book/docs/142.md @@ -0,0 +1,40 @@ +# Migrating from Perforce Helix + +> 原文:[https://docs.gitlab.com/ee/user/project/import/perforce.html](https://docs.gitlab.com/ee/user/project/import/perforce.html) + +* [Perforce vs Git](#perforce-vs-git) +* [Why migrate](#why-migrate) +* [How to migrate](#how-to-migrate) + +# Migrating from Perforce Helix[](#migrating-from-perforce-helix "Permalink") + +[Perforce Helix](https://www.perforce.com/)提供了一套工具,其中还包括类似于 Git 的集中式专有版本控制系统. + +## Perforce vs Git[](#perforce-vs-git "Permalink") + +以下列表说明了 Perforce Helix 和 Git 之间的主要区别: + +1. 通常,最大的区别是与 Git 的轻量级分支相比,Perforce 分支是重量级的. 当您在 Perforce 中创建分支时,它会在其专有数据库中为分支中的每个文件创建一个集成记录,无论实际更改了多少. 而 Git 是采用不同的体系结构实现的,因此,单个 SHA 可以充当更改后整个存储库状态的指针,这使得分支非常容易. 这就是功能分支工作流如此容易被 Git 采纳的原因. +2. 而且,在 Git 中,分支之间的上下文切换要容易得多. 如果您的经理说"您需要停止使用该新功能并修复此安全漏洞",那么您可以在 Git 中轻松地做到这一点. +3. 在本地计算机上拥有项目及其历史的完整副本意味着每笔交易都非常快,而 Git 则提供了该副本. 您可以单独进行分支/合并和试验,然后在与所有人共享新的有趣内容之前清理混乱. +4. Git 还使代码审核变得简单,因为您可以共享更改而无需将更改合并到主版本中,而 Perforce 必须在服务器上实现 Shelving 功能,以便其他人可以在合并之前查看更改. + +## Why migrate[](#why-migrate "Permalink") + +从用户和管理员的角度来看,Perforce Helix 可能难以管理. 迁移到 Git / GitLab 有: + +* **没有许可费用** ,Git 是 GPL,而 Perforce Helix 是专有的. +* **学习曲线更短** ,Git 有一个庞大的社区和大量的入门指南. +* **与现代工具集成** ,迁移到 Git 和 GitLab,您可以拥有一个开源的端到端软件开发平台,该平台具有内置的版本控制,问题跟踪,代码审查,CI / CD 等. + +## How to migrate[](#how-to-migrate "Permalink") + +Git 包含一个内置机制( `git p4` ),用于从 Perforce 中提取代码并将其从 Git 提交回 Perforce. + +以下是一些入门指南: + +* [`git-p4` manual page](https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-p4.html) +* [`git-p4` example usage](https://git.wiki.kernel.org/index.php/Git-p4_Usage) +* [Git book migration guide](https://git-scm.com/book/en/v2/Git-and-Other-Systems-Migrating-to-Git#_perforce_import) + +请注意, `git p4`和`git filter-branch`在创建小型高效 Git 包文件方面不是很好. 因此,在第一次将存储库发送到 GitLab 服务器之前,花一些时间和 CPU 适当地重新打包存储库可能是个好主意. 请参阅[此 StackOverflow 问题](https://stackoverflow.com/questions/28720151/git-gc-aggressive-vs-git-repack/) . \ No newline at end of file diff --git a/_book/docs/143.md b/_book/docs/143.md new file mode 100644 index 0000000000000000000000000000000000000000..ee84f539c1f80f32557dbb88e9669a2e1d8bbf56 --- /dev/null +++ b/_book/docs/143.md @@ -0,0 +1,36 @@ +# Import Phabricator tasks into a GitLab project + +> 原文:[https://docs.gitlab.com/ee/user/project/import/phabricator.html](https://docs.gitlab.com/ee/user/project/import/phabricator.html) + +* [Users](#users) +* [Enabling this feature](#enabling-this-feature) + +# Import Phabricator tasks into a GitLab project[](#import-phabricator-tasks-into-a-gitlab-project "Permalink") + +在 GitLab 12.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/60562) . + +GitLab 允许您将所有任务从 Phabricator 实例导入到 GitLab 问题中. 导入将创建一个项目,并禁用存储库. + +当前,仅导入以下基本字段: + +* Title +* Description +* 状态(打开或关闭) +* 创建于 +* 在关闭 + +## Users[](#users "Permalink") + +用户的受让人和作者将从 Task 的所有者和作者中扣除:如果具有相同用户名的用户有权访问要导入到的项目的名称空间,则将链接该用户. + +## Enabling this feature[](#enabling-this-feature "Permalink") + +当此功能不完整时,需要一个功能标志来启用它,以便我们在向所有人发布该功能之前获得早期反馈. 要启用它: + +1. 在 Rails 控制台中运行以下命令: + + ``` + Feature.enable(:phabricator_import) + ``` + +2. 在管理区域中将 Phabricator 用作[导入源](../../admin_area/settings/visibility_and_access_controls.html#import-sources) . \ No newline at end of file diff --git a/_book/docs/144.md b/_book/docs/144.md new file mode 100644 index 0000000000000000000000000000000000000000..6e5f5c5e2891393b4aa59ab915f2434613d3f608 --- /dev/null +++ b/_book/docs/144.md @@ -0,0 +1,55 @@ +# Import multiple repositories by uploading a manifest file + +> 原文:[https://docs.gitlab.com/ee/user/project/import/manifest.html](https://docs.gitlab.com/ee/user/project/import/manifest.html) + +* [Requirements](#requirements) +* [Manifest format](#manifest-format) +* [Importing the repositories](#importing-the-repositories) + +# Import multiple repositories by uploading a manifest file[](#import-multiple-repositories-by-uploading-a-manifest-file "Permalink") + +在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28811) . + +GitLab 允许您基于清单文件(如[Android 存储库](https://android.googlesource.com/platform/manifest/+/2d6f081a3b05d8ef7a2b1b52b0d536b2b74feab4/default.xml)使用的清单文件)导入所有必需的 Git 存储[库](https://android.googlesource.com/platform/manifest/+/2d6f081a3b05d8ef7a2b1b52b0d536b2b74feab4/default.xml) . 当您需要导入具有许多存储库(例如 Android 开放源项目(AOSP))的项目时,此功能非常方便. + +## Requirements[](#requirements "Permalink") + +GitLab 必须为其数据库使用 PostgreSQL,因为清单导入工作需要[子组](../../group/subgroups/index.html) . + +阅读有关[数据库要求的](../../../install/requirements.html#database)更多信息. + +## Manifest format[](#manifest-format "Permalink") + +清单必须是 XML 文件. 必须有一个带有`review`属性的`remote`标签,该`review`属性包含指向 Git 服务器的 URL,并且每个`project`标签都必须具有`name`和`path`属性. 然后,GitLab 将通过将`remote`标记中的 URL 与项目名称组合来构建到存储库的 URL. 路径属性将用于表示 GitLab 中的项目路径. + +以下是清单文件的有效示例: + +``` +<manifest> + <remote review="https://android.googlesource.com/" /> + + <project path="build/make" name="platform/build" /> + <project path="build/blueprint" name="platform/build/blueprint" /> +</manifest> +``` + +结果,将创建以下项目: + +| GitLab | 导入网址 | +| --- | --- | +| `https://gitlab.com/YOUR_GROUP/build/make` | [https://android.googlesource.com/platform/build](https://android.googlesource.com/platform/build) | +| `https://gitlab.com/YOUR_GROUP/build/blueprint` | [https://android.googlesource.com/platform/build/blueprint](https://android.googlesource.com/platform/build/blueprint) | + +## Importing the repositories[](#importing-the-repositories "Permalink") + +You can start the import with: + +1. 在您的 GitLab 仪表板中,单击" **新建项目".** +2. 切换到**导入项目**选项卡 +3. 单击**清单文件**按钮 +4. 为 GitLab 提供清单 xml 文件 +5. 选择要导入的组(如果没有,则需要先创建一个组) +6. 单击**列出可用的存储库** . 此时,您将根据清单文件重定向到带有项目列表的导入状态页面. +7. 检查列表,然后单击" **导入所有存储库"**以开始导入. + + [![Manifest status](img/e5f179b25c2db023892b0a5f559b67d5.png)](img/manifest_status.png) \ No newline at end of file diff --git a/_book/docs/145.md b/_book/docs/145.md new file mode 100644 index 0000000000000000000000000000000000000000..6df03b6d402a1253d067802025a3f6982c0e9879 --- /dev/null +++ b/_book/docs/145.md @@ -0,0 +1,16 @@ +# Import project from repo by URL + +> 原文:[https://docs.gitlab.com/ee/user/project/import/repo_by_url.html](https://docs.gitlab.com/ee/user/project/import/repo_by_url.html) + +# Import project from repo by URL[](#import-project-from-repo-by-url "Permalink") + +您可以通过提供 Git URL 来导入现有存储库: + +1. 在您的 GitLab 仪表板中,单击" **新建项目".** +2. 切换到**导入项目**选项卡 +3. 点击**按 URL 回购**按钮 +4. 填写" Git 存储库 URL"和其余项目字段 +5. 单击**创建项目**开始导入过程 +6. 完成后,您将被重定向到新创建的项目 + +[![Import project by repo URL](img/731943edb4428a3eb27c86d8d454d0e0.png)](img/import_projects_from_repo_url.png) \ No newline at end of file diff --git a/_book/docs/146.md b/_book/docs/146.md new file mode 100644 index 0000000000000000000000000000000000000000..3ebeb7ec335e06ee587887279dd60028422c6dbe --- /dev/null +++ b/_book/docs/146.md @@ -0,0 +1,141 @@ +# Migrating from SVN to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/svn.html](https://docs.gitlab.com/ee/user/project/import/svn.html) + +* [Overview](#overview) +* [Smooth migration with a Git/SVN mirror using SubGit](#smooth-migration-with-a-gitsvn-mirror-using-subgit) + * [SubGit prerequisites](#subgit-prerequisites) + * [SubGit configuration](#subgit-configuration) + * [Initial translation](#initial-translation) + * [SubGit licensing](#subgit-licensing) + * [SubGit support](#subgit-support) +* [Cut over migration with svn2git](#cut-over-migration-with-svn2git) +* [Contribute to this guide](#contribute-to-this-guide) + +# Migrating from SVN to GitLab[](#migrating-from-svn-to-gitlab "Permalink") + +Subversion(SVN)是中央版本控制系统(VCS),而 Git 是分布式版本控制系统. 两者之间有一些主要区别,有关更多信息,请咨询您喜欢的搜索引擎. + +## Overview[](#overview "Permalink") + +SVN 到 Git 迁移的方法有两种: + +1. [Git/SVN Mirror](#smooth-migration-with-a-gitsvn-mirror-using-subgit) which: + * 使 GitLab 存储库镜像 SVN 项目. + * Git 和 SVN 存储库保持同步; 您可以使用任何一个. + * 简化迁移过程并允许管理迁移风险. +2. [Cut over migration](#cut-over-migration-with-svn2git) which: + * 将现有数据和历史记录从 SVN 转换并导入到 Git. + * 是一劳永逸的方法,对较小的团队有用. + +## Smooth migration with a Git/SVN mirror using SubGit[](#smooth-migration-with-a-gitsvn-mirror-using-subgit "Permalink") + +[SubGit](https://subgit.com)是用于平稳,无压力的 SVN 到 Git 迁移的工具. 它创建本地或远程 Subversion 存储库的可写 Git 镜像,并且您可以根据需要同时使用 Subversion 和 Git. 它需要直接在文件系统级别与 Git 存储库通信时访问您的 GitLab 服务器. + +### SubGit prerequisites[](#subgit-prerequisites "Permalink") + +1. 安装 Oracle JRE 1.8 或更高版本. 在基于 Debian 的 Linux 发行版上,您可以阅读[本文](http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html) . +2. 从[https://subgit.com/download](https://subgit.com/download)下载 SubGit. +3. 将下载的 SubGit zip 存档解压缩到`/opt`目录. `subgit`命令将在`/opt/subgit-VERSION/bin/subgit` . + +### SubGit configuration[](#subgit-configuration "Permalink") + +在 GitLab 中镜像 SVN 存储库的第一步是创建一个新的空项目,该项目将用作镜像. 对于 Omnibus 安装,默认情况下,存储库的路径将位于`/var/opt/gitlab/git-data/repositories/USER/REPO.git` . 对于从源安装,默认的存储库目录将是`/home/git/repositories/USER/REPO.git` . 为方便起见,将此路径分配给变量: + +``` +GIT_REPO_PATH=/var/opt/gitlab/git-data/repositories/USER/REPOS.git +``` + +SubGit 将使该存储库与远程 SVN 项目保持同步. 为了方便起见,请将您的远程 SVN 项目 URL 分配给一个变量: + +``` +SVN_PROJECT_URL=http://svn.company.com/repos/project +``` + +接下来,您需要运行 SubGit 来设置 Git / SVN 镜像. 确保代表拥有 GitLab Git 存储库所有权的同一用户运行以下`subgit`命令(默认情况下为`git` ): + +``` +subgit configure --layout auto $SVN_PROJECT_URL $GIT_REPO_PATH +``` + +如有必要,请调整作者和分支机构的映射. 用您喜欢的文本编辑器打开: + +``` +edit $GIT_REPO_PATH/subgit/authors.txt +edit $GIT_REPO_PATH/subgit/config +``` + +有关 SubGit 配置选项的更多信息,请参阅[SubGit 文档](https://subgit.com/documentation/)网站. + +### Initial translation[](#initial-translation "Permalink") + +现在,SubGit 已经配置了 Git / SVN 存储库,运行`subgit`来执行将现有 SVN 修订版初始转换为 Git 存储库的操作: + +``` +subgit install $GIT_REPO_PATH +``` + +初始翻译完成后,Git 存储库和 SVN 项目将通过`subgit`保持同步-新的 Git 提交将转换为 SVN 修订版,而新的 SVN 修订版将转换为 Git 提交. Mirror 透明地工作,不需要任何特殊命令. + +如果您希望使用`subgit`执行一次性迁移,请使用`import`命令而不是`install` : + +``` +subgit import $GIT_REPO_PATH +``` + +### SubGit licensing[](#subgit-licensing "Permalink") + +以镜像模式运行 SubGit 需要[注册](https://subgit.com/pricing) . 开源,学术和启动项目免费注册. + +### SubGit support[](#subgit-support "Permalink") + +对于与 SubGit 的 SVN 到 GitLab 迁移有关的任何问题,您可以直接通过[support@subgit.com](mailto:support@subgit.com)与 SubGit 团队[联系](mailto:support@subgit.com) . + +## Cut over migration with svn2git[](#cut-over-migration-with-svn2git "Permalink") + +如果当前正在使用 SVN 存储库,则可以将该存储库迁移到 Git 和 GitLab. 我们建议您进行一次硬性转换-运行一次迁移命令,然后让所有开发人员立即开始使用新的 GitLab 存储库. 否则,很难保持双向同步更改. 转换过程应在本地工作站上运行. + +安装`svn2git` . 在所有系统上,如果已经安装了 Ruby 和 Git,则可以作为 Ruby gem 安装. + +``` +sudo gem install svn2git +``` + +在基于 Debian 的 Linux 发行版上,您可以安装本机软件包: + +``` +sudo apt-get install git-core git-svn ruby +``` + +(可选)准备一个 authors 文件,以便`svn2git`可以将 SVN 作者映射到 Git 作者. 如果您选择不创建作者文件,则提交将不会归因于正确的 GitLab 用户. 有些用户可能不会认为这是一个大问题,而另一些用户则希望确保他们完成此步骤. 如果选择映射作者,则将需要映射 SVN 信息库中的更改中存在的每个作者. 否则,转换将失败,您将必须相应地更新作者文件. 以下命令将搜索存储库并输出作者列表. + +``` +svn log --quiet | grep -E "r[0-9]+ \| .+ \|" | cut -d'|' -f2 | sed 's/ //g' | sort | uniq +``` + +使用最后一条命令的输出来构造作者文件. 创建一个名为`authors.txt`的文件,并在每行添加一个映射. + +``` +janedoe = Jane Doe <janedoe@example.com> +johndoe = John Doe <johndoe@example.com> +``` + +如果您的 SVN 储存库为标准格式(主干,分支,标签,而非嵌套),则转换很简单. 对于非标准存储库,请参见[svn2git 文档](https://github.com/nirvdrum/svn2git) . 以下命令将检出存储库并在当前工作目录中进行转换. 在运行`svn2git`命令之前,请确保为每个存储库创建一个新目录. 转换过程将需要一些时间. + +``` +svn2git https://svn.example.com/path/to/repo --authors /path/to/authors.txt +``` + +如果您的 SVN 信息库需要用户名和密码,请在上述命令中添加`--username <username>`和`--password <password>`标志. `svn2git`还支持排除某些文件路径,分支,标签等.请参阅[svn2git 文档](https://github.com/nirvdrum/svn2git)或运行`svn2git --help`以获取有关所有可用选项的完整文档. + +创建一个新的 GitLab 项目,您最终将在其中推送转换后的代码. 从项目页面复制 SSH 或 HTTP(S)存储库 URL. 将 GitLab 存储库添加为 Git 远程,并推送所有更改. 这将推送所有提交,分支和标签. + +``` +git remote add origin git@gitlab.com:<group>/<project>.git +git push --all origin +git push --tags origin +``` + +## Contribute to this guide[](#contribute-to-this-guide "Permalink") + +我们欢迎所有将扩展本指南的贡献,其中包括有关如何从 SVN 和其他版本控制系统进行迁移的说明. \ No newline at end of file diff --git a/_book/docs/147.md b/_book/docs/147.md new file mode 100644 index 0000000000000000000000000000000000000000..d0725824ce0de369ed508f874854b212db5b30a1 --- /dev/null +++ b/_book/docs/147.md @@ -0,0 +1,37 @@ +# Migrating from TFVC to Git + +> 原文:[https://docs.gitlab.com/ee/user/project/import/tfvc.html](https://docs.gitlab.com/ee/user/project/import/tfvc.html) + +* [TFVC vs Git](#tfvc-vs-git) +* [Why migrate](#why-migrate) +* [How to migrate](#how-to-migrate) + +# Migrating from TFVC to Git[](#migrating-from-tfvc-to-git "Permalink") + +Team Foundation Server(TFS)在 2019 年重命名为[Azure DevOps Server](https://azure.microsoft.com/en-us/services/devops/server/) ,是 Microsoft 开发的一组工具,还包括[Team Foundation Version Control](https://docs.microsoft.com/en-us/azure/devops/repos/tfvc/what-is-tfvc?view=azure-devops) (TFVC),这是一个类似于 Git 的集中式版本控制系统. + +在本文档中,我们重点介绍从 TFVC 到 Git 的迁移. + +## TFVC vs Git[](#tfvc-vs-git "Permalink") + +TFVC 和 Git 之间的主要区别是: + +* **Git 是分布式的:**虽然 TFVC 使用客户端-服务器体系结构进行集中管理,但 Git 是分布式的. 由于您使用了整个存储库的副本,因此 Git 的工作流程更加灵活. 例如,这使您可以快速切换分支或合并,而无需与远程服务器进行通信. +* **存储:**集中式版本控制系统中的更改是按文件(更改集)进行的,而在 Git 中,已提交的文件将全部存储(快照). 这意味着还原或撤消 Git 的整个更改非常容易. + +有关更多信息,请参见: + +* Microsoft’s [comparison of Git and TFVC](https://docs.microsoft.com/en-us/azure/devops/repos/tfvc/comparison-git-tfvc?view=azure-devops). +* The Wikipedia [comparison of version control software](https://en.wikipedia.org/wiki/Comparison_of_version_control_software). + +## Why migrate[](#why-migrate "Permalink") + +迁移到 Git / GitLab 的优势: + +* **无需许可费用:** Git 是开源的,而 TFVC 是专有的. +* **较短的学习曲线:** Git 拥有一个庞大的社区和大量的入门指南(请参阅我们的[Git 主题](../../../topics/git/index.html) ). +* **与现代工具的集成:**迁移到 Git 和 GitLab 之后,您将拥有一个带有内置版本控制,问题跟踪,代码审查,CI / CD 等的开源,端到端软件开发平台. + +## How to migrate[](#how-to-migrate "Permalink") + +从 TFVC 迁移到 Git 的最佳选择是使用[`git-tfs`](https://github.com/git-tfs/git-tfs)工具. 阅读" [将 TFS 迁移到 Git"](https://github.com/git-tfs/git-tfs/blob/master/doc/usecases/migrate_tfs_to_git.md)指南以获取更多详细信息. \ No newline at end of file diff --git a/_book/docs/148.md b/_book/docs/148.md new file mode 100644 index 0000000000000000000000000000000000000000..eb318a127571726610ba6d2fb6b1e9aabf48c717 --- /dev/null +++ b/_book/docs/148.md @@ -0,0 +1,106 @@ +# Push Options + +> 原文:[https://docs.gitlab.com/ee/user/project/push_options.html](https://docs.gitlab.com/ee/user/project/push_options.html) + +* [Push options for GitLab CI/CD](#push-options-for-gitlab-cicd) +* [Push options for merge requests](#push-options-for-merge-requests) +* [Useful Git aliases](#useful-git-aliases) + * [Merge when pipeline succeeds alias](#merge-when-pipeline-succeeds-alias) + +# Push Options[](#push-options "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15643) . + +GitLab 支持使用客户端[Git 推送选项](https://git-scm.com/docs/git-push#Documentation/git-push.txt--oltoptiongt)在推送更改的同时执行各种操作. 此外, [推送规则](../../push_rules/push_rules.html)提供服务器端控制和实施选项. + +当前,有推送选项可用于: + +* [Skipping CI jobs](#push-options-for-gitlab-cicd) +* [Merge requests](#push-options-for-merge-requests) + +**注意:** Git 推送选项仅在 Git 2.10 或更高版本中可用. + +对于 2.10 至 2.17 版本的 Git,请使用`--push-option` : + +``` +git push --push-option=<push_option> +``` + +对于 2.18 及更高版本,可以使用以上格式,或更短的`-o` : + +``` +git push -o <push_option> +``` + +## Push options for GitLab CI/CD[](#push-options-for-gitlab-cicd "Permalink") + +您可以使用推入选项跳过 CI / CD 管道或传递环境变量. + +| 推送选项 | Description | 版本介绍 | +| --- | --- | --- | +| `ci.skip` | 不要为最新推送创建 CI 管道. | [11.7](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15643) | +| `ci.variable="<name>=<value>"` | 如果由于推送而创建了[环境变量](../../ci/variables/README.html) ,请提供要在 CI 管道中使用的[环境变量](../../ci/variables/README.html) . | [12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/27983) | + +使用`ci.skip`的示例: + +``` +git push -o ci.skip +``` + +An example of passing some environment variables for a pipeline: + +``` +git push -o ci.variable="MAX_RETRIES=10" -o ci.variable="MAX_TIME=600" +``` + +## Push options for merge requests[](#push-options-for-merge-requests "Permalink") + +您可以在推送更改的同时使用 Git 推送选项对合并请求执行某些操作: + +| 推送选项 | Description | 版本介绍 | +| --- | --- | --- | +| `merge_request.create` | 为推送的分支创建一个新的合并请求. | [11.10](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26752) | +| `merge_request.target=<branch_name>` | 将合并请求的目标设置为特定分支. | [11.10](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26752) | +| `merge_request.merge_when_pipeline_succeeds` | 设置合并请求以[在其管道成功时](merge_requests/merge_when_pipeline_succeeds.html)进行[合并](merge_requests/merge_when_pipeline_succeeds.html) . | [11.10](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26752) | +| `merge_request.remove_source_branch` | 设置合并请求以在合并时删除源分支. | [12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64320) | +| `merge_request.title="<title>"` | 设置合并请求的标题. 例如: `git push -o merge_request.title="The title I want"` . | [12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64320) | +| `merge_request.description="<description>"` | 设置合并请求的描述. 例如: `git push -o merge_request.description="The description I want"` . | [12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64320) | +| `merge_request.label="<label>"` | 将标签添加到合并请求. 如果标签不存在,它将被创建. 例如,对于两个标签: `git push -o merge_request.label="label1" -o merge_request.label="label2"` . | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) | +| `merge_request.unlabel="<label>"` | 从合并请求中删除标签. 例如,对于两个标签: `git push -o merge_request.unlabel="label1" -o merge_request.unlabel="label2"` . | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) | + +如果您使用要求文本带有空格的 push 选项,则需要用引号( `"` )括起来.如果没有空格,则可以省略引号.例如: + +``` +git push -o merge_request.label="Label with spaces" +git push -o merge_request.label=Label-with-no-spaces +``` + +您可以通过使用多个`-o` (或`--push-option` )标志来组合推送选项以一次完成多个任务. 例如,如果您要创建一个新的合并请求,并定位一个名为`my-target-branch` : + +``` +git push -o merge_request.create -o merge_request.target=my-target-branch +``` + +此外,如果希望合并请求在管道成功后立即合并,则可以执行以下操作: + +``` +git push -o merge_request.create -o merge_request.target=my-target-branch -o merge_request.merge_when_pipeline_succeeds +``` + +## Useful Git aliases[](#useful-git-aliases "Permalink") + +如上所示,Git 推送选项可能导致 Git 命令增长很长. 如果您经常使用相同的 push 选项,则创建[Git 别名会](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases)很有用. Git 别名是 Git 的命令行快捷方式,可以大大简化长 Git 命令的使用. + +### Merge when pipeline succeeds alias[](#merge-when-pipeline-succeeds-alias "Permalink") + +要[在管道成功执行 Git push 选项时](#push-options-for-merge-requests)为[合并](#push-options-for-merge-requests)设置 Git 别名: + +``` +git config --global alias.mwps "push -o merge_request.create -o merge_request.target=master -o merge_request.merge_when_pipeline_succeeds" +``` + +然后,为了在管道成功时快速推送将针对 master 并合并的本地分支: + +``` +git mwps origin <local-branch-name> +``` \ No newline at end of file diff --git a/_book/docs/149.md b/_book/docs/149.md new file mode 100644 index 0000000000000000000000000000000000000000..cb1f81da37a4a7cf6c26d7528b6dba7acce7ec04 --- /dev/null +++ b/_book/docs/149.md @@ -0,0 +1,341 @@ +# Releases + +> 原文:[https://docs.gitlab.com/ee/user/project/releases/](https://docs.gitlab.com/ee/user/project/releases/) + +* [View releases](#view-releases) +* [Create a release](#create-a-release) + * [Schedule a future release](#schedule-a-future-release) +* [Edit a release](#edit-a-release) +* [Add release notes to Git tags](#add-release-notes-to-git-tags) +* [Associate milestones with a release](#associate-milestones-with-a-release) +* [Get notified when a release is created](#get-notified-when-a-release-is-created) +* [Prevent unintentional releases by setting a deploy freeze](#prevent-unintentional-releases-by-setting-a-deploy-freeze) +* [Release fields](#release-fields) + * [Tag name](#tag-name) + * [Release notes description](#release-notes-description) + * [Release assets](#release-assets) + * [Permanent links to release assets](#permanent-links-to-release-assets) + * [Source code](#source-code) + * [Links](#links) +* [Release evidence](#release-evidence) + * [Collect release evidence](#collect-release-evidence-premium-only) + * [Include report artifacts as release evidence](#include-report-artifacts-as-release-evidence-ultimate-only) + * [Schedule release evidence collection](#schedule-release-evidence-collection) + * [Disable release evidence display](#disable-release-evidence-display-core-only) +* [GitLab Releaser](#gitlab-releaser) + +# Releases[](#releases "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766) . + +要在源代码历史记录中引入检查点,可以在发布时分配[Git 标签](https://git-scm.com/book/en/v2/Git-Basics-Tagging) . 但是,在大多数情况下,您的用户不仅需要原始源代码. 他们需要 CI / CD 系统输出的已编译对象或其他资产. + +GitLab *发行版*是与代码的发行版本相关联的源,构建输出,工件和其他元数据的快照. + +您可以在任何分支上创建一个 GitLab 版本. 创建发行版时: + +* manbetx 客户端打不开自动归档源代码,并将其与版本关联. +* GitLab 会自动创建一个 JSON 文件,其中列出了发行版中的所有内容,因此您可以比较和审核发行版. 该文件称为[发布证据](#release-evidence) . +* 您可以添加发行说明以及与发行版关联的标签的消息. + +创建发行版后,您可以将[里程碑与其关联](#associate-milestones-with-a-release) ,并附加[发行资产](#release-assets) ,例如运行手册或软件包. + +## View releases[](#view-releases "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36667) . + +要查看版本列表: + +* 转到**项目概述>版本** ,或 + +* 在项目的概述页面上,如果存在至少一个版本,请单击版本数. + + [![Number of Releases](img/4b690260474eb340f7b3f6d25b0568d2.png "Incremental counter of Releases")](img/releases_count_v13_2.png) + + * 在公共项目上,此数字对所有用户可见. + * 在私有项目上,具有 Reporter [权限](../../permissions.html#project-members-permissions)或更高[权限的](../../permissions.html#project-members-permissions)用户可以看到此数字. + +## Create a release[](#create-a-release "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32812) . 可以在 GitLab UI 中直接创建发布. + +**注意:**只有具有开发者权限或更高权限的用户才能创建发行版. 阅读有关[释放权限的](../../../user/permissions.html#project-members-permissions)更多信息. + +您可以在用户界面中或使用[Releases API](../../../api/releases/index.html#create-a-release)创建发布. 我们建议使用 API​​添加发行说明,作为 CI / CD 发行流程中的最后步骤之一. + +要通过 GitLab UI 创建新版本: + +1. 导航到**项目概述>发布** ,然后单击**新发布**按钮. +2. 在[**标签名称**](#tag-name)框中,输入一个名称. +3. In the **从创建** list, select the branch or enter a tag or commit SHA. +4. 在" **消息"**框中,输入与标签关联的消息. +5. (可选)在" [**发行说明"**](#release-notes-description)字段中,输入发行说明. 您可以使用 Markdown 并将文件拖放到此字段. + * 如果将此字段留空,则只会创建一个标签. + * 如果您填充它,将同时创建标签和发行版. +6. Click **创建标签**. + +如果创建了发行​​版,则可以在**项目概述>发行版中**对其进行查看. 如果创建了标签,则可以在**存储库>标签中**查看它. + +现在,您可以编辑发布以[添加里程碑](#associate-milestones-with-a-release)和[发布资产](#release-assets) . + +### Schedule a future release[](#schedule-a-future-release "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/38105) . + +您可以使用[Releases API](../../../api/releases/index.html#upcoming-releases)提前创建发行[版](../../../api/releases/index.html#upcoming-releases) . 当您设置将来的`released_at`日期时,将在发布标签旁边显示**即将发布**的发布标志. 经过`released_at`日期和时间后,会自动删除徽章. + +[![An upcoming release](img/7727ed12caef6b761b73e4bd379c7839.png)](img/upcoming_release_v12_7.png) + +## Edit a release[](#edit-a-release "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/26016) . 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9427)了资产链接编辑. + +**注意:**只有具有开发者权限或更高权限的用户才能编辑发行版. 阅读有关[释放权限的](../../../user/permissions.html#project-members-permissions)更多信息. + +要编辑发布的详细信息: + +1. 导航到**项目概述>发布** . +2. 在您要修改的发行版的右上角,单击" **编辑此发行版"** (铅笔图标). +3. 在" **编辑版本"**页面上,更改版本的详细信息. +4. Click **保存更改**. + +您可以编辑发行标题,注释,关联的里程碑和资产链接. 要更改其他发行信息,例如标签或发行日期,请使用[Releases API](../../../api/releases/index.html#update-a-release) . + +## Add release notes to Git tags[](#add-release-notes-to-git-tags "Permalink") + +If you have an existing Git tag, you can add release notes to it. + +您可以在用户界面中或使用[Releases API](../../../api/releases/index.html)来执行此操作. 我们建议使用 API​​添加发行说明,作为 CI / CD 发行流程中的最后步骤之一. + +在界面中,要向新的 Git 标签添加发行说明: + +1. 导航到您项目的**Repository> Tags** . +2. Click **新的一天**. +3. 在**发行说明**字段中,输入发行说明. 您可以使用 Markdown 并将文件拖放到此字段. +4. Click **创建标签**. + +在界面中,要将发行说明添加到现有的 Git 标签: + +1. 导航到您项目的**Repository> Tags** . +2. 单击**编辑发行说明** (铅笔图标). +3. 在**发行说明**字段中,输入发行说明. 您可以在此字段中使用 Markdown,并将文件拖放到该字段中. +4. Click **保存更改**. + +## Associate milestones with a release[](#associate-milestones-with-a-release "Permalink") + +版本历史 + +* 在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/29020) . +* [已更新](https://gitlab.com/gitlab-org/gitlab/-/issues/39467) ,可在 GitLab 13.0 中的 UI 中编辑里程碑. + +您可以将一个版本与一个或多个[项目里程碑](../milestones/index.html#project-milestones-and-group-milestones)相关联. + +您可以在用户界面中执行此操作,也可以在对[Releases API 的](../../../api/releases/index.html#create-a-release)请求中包含一个`milestones`数组. + +在用户界面中,要将里程碑与版本关联: + +1. 导航到**项目概述>发布** . +2. 在您要修改的发行版的右上角,单击" **编辑此发行版"** (铅笔图标). +3. 从" **里程碑"**列表中,选择要关联的每个里程碑. 您可以选择多个里程碑. +4. Click **保存更改**. + +在" **项目概述">"发布"**页面上, **里程碑**列在顶部,以及有关里程碑问题的统计信息. + +[![A Release with one associated milestone](img/21967843cf3a12bcfa5e39a39b1b3f69.png)](img/release_with_milestone_v12_9.png) + +在" **问题">"里程碑"**页面上,以及当您单击此页面上的里程碑时,也可以看到发行版本. + +这是一个里程碑示例,分别没有发布,一个发布和两个发布. + +[![Milestones with and without Release associations](img/e6ef8c883764c13967c9c9fcc5617980.png)](img/milestone_list_with_releases_v12_5.png) + +## Get notified when a release is created[](#get-notified-when-a-release-is-created "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/26001) . + +为您的项目创建新版本时,将通过电子邮件通知您. + +订阅发布通知: + +1. 导航到" **项目概述"** . +2. 单击**通知设置** (响铃图标). +3. 在列表中,点击**自定义** . +4. Select the **新品发布** check box. +5. 关闭对话框进行保存. + +## Prevent unintentional releases by setting a deploy freeze[](#prevent-unintentional-releases-by-setting-a-deploy-freeze "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29382) . + +通过设置[*部署冻结*期,](../../../ci/environments/deployment_safety.html)可以在指定的时间内防止意外的生产发布. 冻结部署有助于减少自动化部署时的不确定性和风险. + +使用" [冻结时间" API](../../../api/freeze_periods.html)设置被定义为[crontab](https://crontab.guru/)条目的`freeze_start`和`freeze_end` . + +如果正在执行的作业处于冻结期,则 GitLab CI / CD 会创建一个名为`$CI_DEPLOY_FREEZE`的环境变量. + +为了防止执行部署作业,请在`gitlab-ci.yaml`创建一个`rules`条目,例如: + +``` +deploy_to_production: + stage: deploy + script: deploy_to_prod.sh + rules: + - if: $CI_DEPLOY_FREEZE == null +``` + +如果项目包含多个冻结期,则所有时期都适用. 如果它们重叠,则冻结将覆盖整个重叠期间. + +有关更多信息,请参阅[部署安全](../../../ci/environments/deployment_safety.html) . + +## Release fields[](#release-fields "Permalink") + +创建或编辑发行版时,以下字段可用. + +### Tag name[](#tag-name "Permalink") + +发行标签名称应包括发行版本. GitLab 在我们的发行版中使用[语义版本控制](https://semver.org/) ,我们建议您也这样做. 使用`(Major).(Minor).(Patch)` ,如[GitLab 版本控制政策](../../../policy/maintenance.html#versioning)中所述. + +例如,对于 GitLab 版本`10.5.7` : + +* `10`代表主要版本. 主要版本是`10.0.0` ,但通常称为`10.0` . +* `5`代表次要版本. 次要版本为`10.5.0` ,但通常称为`10.5` . +* `7`代表补丁号码. + +版本号的任何部分都可以是多个数字,例如`13.10.11` . + +### Release notes description[](#release-notes-description "Permalink") + +每个版本都有说明. 您可以添加任何您喜欢的文本,但是我们建议您添加一个变更日志来描述发行版本的内容. 这可以帮助用户快速扫描您发布的每个版本之间的差异. + +**注意:** [Git 的标记消息](https://git-scm.com/book/en/v2/Git-Basics-Tagging)和发行说明描述无关. 说明支持[Markdown](../../markdown.html) . + +### Release assets[](#release-assets "Permalink") + +当前,您可以将以下类型的资产添加到每个版本: + +* [Source code](#source-code) +* [Links](#links) + +manbetx 客户端打不开将在未来支持更多的资产类型,包括诸如预装包,合规性/安全证据或容器图像之类的对象. + +#### Permanent links to release assets[](#permanent-links-to-release-assets "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27300) . + +与发布相关联的资产可通过永久 URL 访问. GitLab 将始终将此 URL 重定向到实际资产位置,因此,即使资产移动到其他位置,您也可以继续使用相同的 URL. 这是在[链接创建](../../../api/releases/links.html#create-a-link)或[更新](../../../api/releases/links.html#update-a-link)期间定义的. + +每个资产都有一个名称, *实际*资产位置的 URL,以及一个可选的`filepath`参数,如果您指定它,它将创建指向发布的资产的 URL. URL 的格式为: + +``` +https://host/namespace/project/releases/:release/downloads/:filepath +``` + +如果您对资产`v11.9.0-rc2`的发布`gitlab-org`命名空间和`gitlab-runner`项目上`gitlab.com` ,例如: + +``` +{ "name": "linux amd64", "filepath": "/binaries/gitlab-runner-linux-amd64", "url": "https://gitlab-runner-downloads.s3.amazonaws.com/v11.9.0-rc2/binaries/gitlab-runner-linux-amd64" } +``` + +该资产具有以下直接链接: + +``` +https://gitlab.com/gitlab-org/gitlab-runner/releases/v11.9.0-rc2/downloads/binaries/gitlab-runner-linux-amd64 +``` + +资产的物理位置可以随时更改,并且直接链接将保持不变. + +### Source code[](#source-code "Permalink") + +GitLab 会根据给定的 Git 标签自动生成`zip` , `tar.gz` , `tar.bz2`和`tar`归档的源代码. 这些是只读资产. + +### Links[](#links "Permalink") + +A link is any URL which can point to whatever you like: documentation, built binaries, or other related materials. These can be both internal or external links from your GitLab instance. + +链接的四种类型是" Runbook"," Package"," Image"和" Other". + +## Release evidence[](#release-evidence "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/26019) . + +每次创建发行版时,GitLab 都会拍摄与之相关的数据快照. 此数据保存在 JSON 文件中,称为*发布证据* . 它包括链接的里程碑和问题,并且可以促进内部流程,例如外部审核. + +要访问发布证据,请在"发布"页面上,单击" **证据集合"**标题下列出的 JSON 文件的链接. + +您还可以[使用 API](../../../api/releases/index.html#collect-release-evidence-premium-only)生成现有版本的版本证据. 因此,每个版本可以具有多个版本证据快照. 您可以在"发布"页面上查看发布证据及其详细信息. + +**注意:**禁用问题跟踪器后, [将无法下载](https://gitlab.com/gitlab-org/gitlab/-/issues/208397)发布证据. + +这是释放证据对象的示例: + +``` +{ "release": { "id": 5, "tag_name": "v4.0", "name": "New release", "project": { "id": 20, "name": "Project name", "created_at": "2019-04-14T11:12:13.940Z", "description": "Project description" }, "created_at": "2019-06-28 13:23:40 UTC", "description": "Release description", "milestones": [ { "id": 11, "title": "v4.0-rc1", "state": "closed", "due_date": "2019-05-12 12:00:00 UTC", "created_at": "2019-04-17 15:45:12 UTC", "issues": [ { "id": 82, "title": "The top-right popup is broken", "author_name": "John Doe", "author_email": "john@doe.com", "state": "closed", "due_date": "2019-05-10 12:00:00 UTC" }, { "id": 89, "title": "The title of this page is misleading", "author_name": "Jane Smith", "author_email": "jane@smith.com", "state": "closed", "due_date": "nil" } ] }, { "id": 12, "title": "v4.0-rc2", "state": "closed", "due_date": "2019-05-30 18:30:00 UTC", "created_at": "2019-04-17 15:45:12 UTC", "issues": [] } ], "report_artifacts": [ { "url":"https://gitlab.example.com/root/project-name/-/jobs/111/artifacts/download" } ] } } +``` + +### Collect release evidence[](#collect-release-evidence-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199065) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10. + +创建发布后,将自动收集发布证据. 要在其他任何时间启动证据收集,请使用[API 调用](../../../api/releases/index.html#collect-release-evidence-premium-only) . 您可以为一个发布多次收集发布证据. + +在"发布"页面上可以看到证据收集快照,以及收集证据的时间戳. + +### Include report artifacts as release evidence[](#include-report-artifacts-as-release-evidence-ultimate-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32773) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2. + +创建发布时,如果[作业工件](../../../ci/pipelines/job_artifacts.html#artifactsreports)包含在最后运行的管道中,则它们会自动作为发布证据包含在发布中. + +尽管工作工件通常会过期,但发布证据中包含的工件不会过期. + +要启用作业工件收集,您需要同时指定两个: + +1. [`artifacts:paths`](../../../ci/yaml/README.html#artifactspaths) +2. [`artifacts:reports`](../../../ci/pipelines/job_artifacts.html#artifactsreports) + +``` +ruby: + script: + - gem install bundler + - bundle install + - bundle exec rspec --format progress --format RspecJunitFormatter --out rspec.xml + artifacts: + paths: + - rspec.xml + reports: + junit: rspec.xml +``` + +如果管道成功运行,则在创建发布时, `rspec.xml`文件将保存为发布证据. + +**注:**如果您[计划发布证据收集](#schedule-release-evidence-collection) ,则某些[证据](#schedule-release-evidence-collection)可能在证据收集时已经过期. 为了避免这种情况,可以使用[`artifacts:expire_in`](../../../ci/yaml/README.html#artifactsexpire_in)关键字. 了解更多在[这个问题上](https://gitlab.com/gitlab-org/gitlab/-/issues/222351) . + +### Schedule release evidence collection[](#schedule-release-evidence-collection "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23697) . + +在 API 中: + +* 如果您指定未来的`released_at`日期,则该发布将成为**即将发布的发布,**并且将在发布日期收集证据. 在此之前,您无法收集释放证据. +* 如果您使用过去的`released_at`日期,则不会收集任何证据. +* 如果您未指定`released_at`日期,则在创建发布的日期收集发布证据. + +### Disable release evidence display[](#disable-release-evidence-display-core-only "Permalink") + +`:release_evidence_collection`功能标志在 GitLab 自管理实例中默认启用. 要关闭它,请要求具有 Rails 控制台访问权限的 GitLab 管理员运行以下命令: + +``` +Feature.disable(:release_evidence_collection) +``` + +**注意:**无论使用此功能标志如何,都将收集发布证据,该标志仅启用或禁用"发布"页面上的数据显示. + +## GitLab Releaser[](#gitlab-releaser "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab-releaser/-/merge_requests/6) . + +GitLab Releaser 是一个 CLI 工具,用于从命令行或 GitLab 的 CI / CD 配置文件`.gitlab-ci.yml`管理 GitLab 版本. + +有了它,您可以直接通过终端创建,更新,修改和删除发行版. + +有关详细信息,请阅读[GitLab Releaser 文档](https://gitlab.com/gitlab-org/gitlab-releaser/-/tree/master/docs/index.md) . \ No newline at end of file diff --git a/_book/docs/150.md b/_book/docs/150.md new file mode 100644 index 0000000000000000000000000000000000000000..bb9052cbba9b98c5adf1492e58bfeb63c2a662ff --- /dev/null +++ b/_book/docs/150.md @@ -0,0 +1,204 @@ +# Repository + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/](https://docs.gitlab.com/ee/user/project/repository/) + +* [Create a repository](#create-a-repository) +* [Files](#files) + * [Create and edit files](#create-and-edit-files) + * [Find files](#find-files) + * [Supported markup languages and extensions](#supported-markup-languages-and-extensions) + * [Repository README and index files](#repository-readme-and-index-files) + * [Jupyter Notebook files](#jupyter-notebook-files) + * [OpenAPI viewer](#openapi-viewer) +* [Branches](#branches) +* [Commits](#commits) +* [Project and repository size](#project-and-repository-size) +* [Contributors](#contributors) +* [Repository graph](#repository-graph) +* [Repository Languages](#repository-languages) +* [Locked files](#locked-files-premium) +* [Repository’s API](#repositorys-api) +* [Clone in Apple Xcode](#clone-in-apple-xcode) +* [Download Source Code](#download-source-code) + +# Repository[](#repository "Permalink") + +[存储库](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository)是用于将代码库存储在 GitLab 中并通过版本控制对其进行更改的存储库. 存储库是[项目的](../index.html)一部分,它具有许多其他功能. + +## Create a repository[](#create-a-repository "Permalink") + +要创建一个新的存储库,您需要做的就是[创建一个新项目](../../../gitlab-basics/create-project.html)或[创建](../../../gitlab-basics/create-project.html) [一个现有项目](forking_workflow.html) . + +创建新项目后,您可以通过 UI(请参阅以下部分)或通过命令行添加新文件. 要从命令行添加文件,请遵循创建新项目时在屏幕上显示的说明,或在[命令行基础](../../../gitlab-basics/start-using-git.html)文档中通读它们. + +> **重要提示:**出于安全原因,强烈建议您在使用命令行时[通过 SSH 与 GitLab 连接](../../../ssh/README.html) . + +## Files[](#files "Permalink") + +使用存储库将文件存储在 GitLab 中. 在[GitLab 12.10 及更高版本中](https://gitlab.com/gitlab-org/gitlab/-/issues/33806) ,您将在存储库的文件树中根据其扩展名在文件名旁边看到一个图标: + +[![Repository file icons](img/8489a6c45ad75964ea7b4b54b9d9fcaa.png)](img/file_ext_icons_repo_v12_10.png) + +### Create and edit files[](#create-and-edit-files "Permalink") + +通过将文件推送到 GitLab,将代码库托管在 GitLab 存储库中. 您可以使用用户界面(UI),也可以[通过命令行将](../../../gitlab-basics/command-line-commands.html#start-working-on-your-project)本地计算机与 GitLab 连接. + +要配置[GitLab CI / CD](../../../ci/README.html)来构建,测试和部署代码,请在存储库的根目录中添加一个名为[`.gitlab-ci.yml`](../../../ci/quick_start/README.html)的文件. + +**从用户界面:** + +GitLab 的用户界面允许您执行许多 Git 命令,而无需触摸命令行. 即使您定期使用命令行,有时[通过 GitLab UI](web_editor.html)也更容易做到: + +* [Create a file](web_editor.html#create-a-file) +* [Upload a file](web_editor.html#upload-a-file) +* [File templates](web_editor.html#template-dropdowns) +* [Create a directory](web_editor.html#create-a-directory) +* [Start a merge request](web_editor.html#tips) +* [Find file history](git_history.html) +* [Identify changes by line (Git blame)](git_blame.html) + +**在命令行中:** + +要开始使用命令行,请通读[命令行基础文档](../../../gitlab-basics/command-line-commands.html) . + +### Find files[](#find-files "Permalink") + +使用 GitLab 的[文件查找器](file_finder.html)在存储库中搜索文件. + +### Supported markup languages and extensions[](#supported-markup-languages-and-extensions "Permalink") + +GitLab 支持多种标记语言(有时称为[轻量标记语言](https://en.wikipedia.org/wiki/Lightweight_markup_language) ),您可以将其用于存储库中文件的内容. 它们主要用于文档目的. + +只需为文件选择正确的扩展名,GitLab 就会根据标记语言来渲染它们. + +| 标记语言 | Extensions | +| --- | --- | +| 纯文本 | `txt` | +| [Markdown](../../markdown.html) | `mdown`, `mkd`, `mkdn`, `md`, `markdown` | +| [reStructuredText](https://docutils.sourceforge.io/rst.html) | `rst` | +| [AsciiDoc](../../asciidoc.html) | `adoc`, `ad`, `asciidoc` | +| [Textile](https://textile-lang.com/) | `textile` | +| [rdoc](http://rdoc.sourceforge.net/doc/index.html) | `rdoc` | +| [Org mode](https://orgmode.org/) | `org` | +| [creole](http://www.wikicreole.org/) | `creole` | +| [MediaWiki](https://www.mediawiki.org/wiki/MediaWiki) | `wiki`, `mediawiki` | + +### Repository README and index files[](#repository-readme-and-index-files "Permalink") + +当存储库中存在`README`或`index`文件时,它的内容将由 GitLab 自动预渲染,而无需打开它. + +它们可以是纯文本,也可以具有[受支持的标记语言](#supported-markup-languages-and-extensions)的扩展名: + +有关优先级的一些注意事项: + +1. 当`README`文件和`index`文件同时存在时, `README`文件将始终优先. +2. 如果存在多个具有不同扩展名的文件,则按字母顺序排列,但不带扩展名的文件例外,该扩展名始终优先. 例如, `README.adoc`将优先于`README.md` ,而`README.rst`将优先于`README` . + +### Jupyter Notebook files[](#jupyter-notebook-files "Permalink") + +[Jupyter](https://jupyter.org/) Notebook(以前的 IPython Notebook)文件用于许多领域的交互式计算,并且包含用户会话的完整记录,并包括代码,叙述性文本,方程式和丰富的输出. + +[Read how to use Jupyter notebooks with GitLab.](jupyter_notebooks/index.html) + +### OpenAPI viewer[](#openapi-viewer "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/19515) . + +如果文件名包含`openapi`或`swagger`且扩展名为`yaml` , `yml`或`json` ,则 GitLab 可以使用其文件查看器呈现 OpenAPI 规范文件. 以下示例都是正确的: + +* `openapi.yml` +* `openapi.yaml` +* `openapi.json` +* `swagger.yml` +* `swagger.yaml` +* `swagger.json` +* `gitlab_swagger.yml` +* `openapi_gitlab.yml` +* `OpenAPI.YML` +* `openapi.Yaml` +* `openapi.JSON` +* `openapi.gitlab.yml` +* `gitlab.openapi.yml` + +然后,渲染它们: + +1. 在 GitLab 的用户界面中导航至存储库中的 OpenAPI 文件. +2. 单击位于"显示源"和"编辑"按钮之间的"显示 OpenAPI"按钮(找到 OpenAPI 文件后,它将替换"显示渲染的文件"按钮). + +## Branches[](#branches "Permalink") + +有关详细信息,请参见[分支](branches/index.html) . + +## Commits[](#commits "Permalink") + +[提交更改时](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository) ,您会将这些更改引入分支机构. 通过命令行,您可以在提交之前多次提交. + +* **提交消息:**提交消息对于标识正在更改的内容以及更重要的原因至关重要. 在 GitLab 中,您可以将关键字添加到提交消息中,以执行以下操作之一: + * **触发 GitLab CI / CD 管道:**如果您的项目配置有[GitLab CI / CD](../../../ci/README.html) ,则将在每次推送而不是每次提交时触发一个管道. + * **跳过管道:**您可以在提交消息中添加关键字[`[ci skip]`](../../../ci/yaml/README.html#skip-pipeline) ,GitLab CI / CD 将跳过该管道. + * **交叉链接问题和合并请求:** [交叉链接](../issues/crosslinking_issues.html#from-commit-messages)非常适合跟踪工作流程中与之相关的内容. 如果您在提交消息中提到问题或合并请求,它们将显示在各自的线程上. +* **樱桃选择提交:**在 GitLab 中,您可以直接从 UI [樱桃选择提交](../merge_requests/cherry_pick_changes.html#cherry-picking-a-commit) . +* **还原提交:**轻松[将提交](../merge_requests/revert_changes.html#reverting-a-commit)从 UI [还原](../merge_requests/revert_changes.html#reverting-a-commit)到所选分支. +* **签署提交:**使用 GPG [签署您的提交](gpg_signed_commits/index.html) . + +## Project and repository size[](#project-and-repository-size "Permalink") + +在项目的" **详细信息"**页面上报告项目的大小. 报告的大小最多每 15 分钟更新一次,因此可能无法反映最近的活动. 显示的文件大小包括存储库文件,工件和 LFS. + +由于压缩,内务处理和其他因素,每个项目的项目规模可能会略有不同. + +[储存库大小限制](../../admin_area/settings/account_and_limit_settings.html)可以由管理员设置. GitLab.com 的存储库大小限制[由 GitLab 设置](../../gitlab_com/index.html#repository-size-limit) . + +## Contributors[](#contributors "Permalink") + +代码库的所有贡献者都显示在项目的**设置>贡献者下** . + +它们是从协作者中以最少的提交次数排序的,并显示在一个漂亮的图形上: + +[![contributors to code](img/d69ab181c07176aa054b0ceac08b702c.png)](img/contributors_graph.png) + +## Repository graph[](#repository-graph "Permalink") + +存储库图形以可视方式显示存储网络的历史记录,包括分支和合并. 这可以帮助您可视化存储库中使用的 Git 流策略: + +[![repository Git flow](img/a1efb7c23a97e2901852465c9168914f.png)](img/repo_graph.png) + +在您项目的**Repository> Graph**下找到它. + +## Repository Languages[](#repository-languages "Permalink") + +对于每个存储库的默认分支,GitLab 将确定使用了哪种编程语言,并将其显示在项目页面上. 如果缺少此信息,将在更新项目上的默认分支后添加. 此过程最多可能需要 5 分钟. + +[![Repository Languages bar](img/e2e835cd5cd1be1afaa876fde2475fe5.png)](img/repository_languages_v12_2.gif) + +Not all files are detected, among others; documentation, vendored code, and most markup languages are excluded. This behavior can be adjusted by overriding the default. For example, to enable `.proto` files to be detected, add the following to `.gitattributes` in the root of your repository. + +``` +*.proto linguist-detectable=true +``` + +## Locked files[](#locked-files-premium "Permalink") + +使用[文件锁定](../file_lock.html)来锁定文件,以防止发生任何冲突的更改. + +## Repository’s API[](#repositorys-api "Permalink") + +您可以通过[存储库 API](../../../api/repositories.html)访问您的[存储库](../../../api/repositories.html) . + +## Clone in Apple Xcode[](#clone-in-apple-xcode "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45820) in GitLab 11.0 + +现在,可以使用位于用于克隆项目的 Git URL 旁边的新的" **在 Xcode 中打开"**按钮**在 Xcode 中**克隆包含`.xcodeproj`或`.xcworkspace`目录的项目. 该按钮仅在 macOS 上显示. + +## Download Source Code[](#download-source-code "Permalink") + +在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/24704)了对目录下载的支持. + +可以从 UI 下载存储在存储库中的源代码. 单击下载图标,将打开一个下拉列表,其中包含下载以下内容的链接: + +[![Download source code](img/0f88b0e1a49600472f2922218cec1ed7.png)](img/download_source_code.png) + +* **源代码:**允许用户在他们当前正在查看的分支上下载源代码. 可用扩展名: `zip` , `tar` , `tar.gz`和`tar.bz2` . +* **目录:**仅在查看子目录时显示. 这使用户可以下载他们当前正在查看的特定目录. 也可以在`zip` , `tar` , `tar.gz`和`tar.bz2` . +* **工件:**允许用户下载最新 CI 构建的工件. \ No newline at end of file diff --git a/_book/docs/151.md b/_book/docs/151.md new file mode 100644 index 0000000000000000000000000000000000000000..0c2f188d155035132b0d9ceafbb74f591076c762 --- /dev/null +++ b/_book/docs/151.md @@ -0,0 +1,119 @@ +# Branches + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/branches/](https://docs.gitlab.com/ee/user/project/repository/branches/) + +* [Default branch](#default-branch) + * [Custom initial branch name](#custom-initial-branch-name-core-only) + * [Enable or disable custom initial branch name](#enable-or-disable-custom-initial-branch-name-core-only) +* [Compare](#compare) +* [Delete merged branches](#delete-merged-branches) +* [Branch filter search box](#branch-filter-search-box) + +# Branches[](#branches "Permalink") + +分支是项目工作树的版本. 您为所做的每组相关更改创建一个分支. 这样可以使每组更改彼此独立,从而可以并行进行更改,而不会互相影响. + +将更改推送到新分支后,您可以: + +* 创建[合并请求](../../merge_requests/index.html) +* 执行内联代码审查 +* 与团队[讨论](../../../discussions/index.html)实施情况 +* 使用[Review Apps](../../../../ci/review_apps/index.html)预览提交到新分支的更改. + +使用[GitLab Starter](https://about.gitlab.com/pricing/) ,您还可以请求经理的[批准](../../merge_requests/merge_request_approvals.html) . + +有关使用 GitLab UI 管理分支的更多信息,请参见: + +* [Default branches](#default-branch) +* [Create a branch](../web_editor.html#create-a-new-branch) +* [Protected branches](../../protected_branches.html#protected-branches) +* [Delete merged branches](#delete-merged-branches) +* [Branch filter search box](#branch-filter-search-box) + +您也可以使用[命令行](../../../../gitlab-basics/start-using-git.html#create-a-branch)管理分支. + +观看视频[GitLab Flow](https://www.youtube.com/watch?v=InKNIvky2KE) . + +也可以看看: + +* [Branches API](../../../../api/branches.html) ,有关使用 GitLab API 在存储库分支上进行操作的信息. +* [GitLab Flow](../../../../university/training/gitlab_flow.html) documentation. +* [Git](../../../../topics/git/index.html)和 GitLab [入门](../../../../topics/git/index.html) . + +## Default branch[](#default-branch "Permalink") + +创建新[项目时](../../index.html) ,GitLab 会将`master`设置为存储库的默认分支. 您可以在项目的**设置>存储库**下选择另一个分支作为项目的默认分支. + +通过[问题关闭模式](../../issues/managing_issues.html#closing-issues-automatically)直接从合并请求中[关闭问题时](../../issues/managing_issues.html#closing-issues-automatically) ,目标是项目的**默认分支** . + +初始还对默认分支进行了[保护,以](../../protected_branches.html#protected-branches)防止意外删除和强制推送. + +### Custom initial branch name[](#custom-initial-branch-name-core-only "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/221013) . +* 它部署在默认情况下启用的功能标志后面. +* 在 GitLab.com 上启用了它. +* 不能根据项目启用或禁用它. +* 建议用于生产. +* 对于 GitLab 自我管理的实例,GitLab 管理员可以选择[禁用它](#enable-or-disable-custom-initial-branch-name-core-only) . + +默认情况下,当您在 GitLab 中创建新项目时,初始分支称为`master` . 对于自我管理的实例,GitLab 管理员可以将初始分支名称自定义为其他名称. 这样,此后创建的每个新项目都将从自定义分支名称开始,而不是`master` . 为此: + +1. 转到 **在管理区域>设置>存储库中** ,展开**默认初始分支名称** . +2. 将默认的初始分支更改为您选择的自定义名称. +3. **保存更改**. + +#### Enable or disable custom initial branch name[](#enable-or-disable-custom-initial-branch-name-core-only "Permalink") + +正在设置默认的初始分支名称,但已准备好用于生产. 它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../../administration/feature_flags.html)可以选择为您的实例禁用它. + +禁用它: + +``` +Feature.disable(:global_default_branch_name) +``` + +要启用它: + +``` +Feature.enable(:global_default_branch_name) +``` + +## Compare[](#compare "Permalink") + +要比较存储库中的分支: + +1. 导航到项目的存储库. +2. 在边栏中选择**存储库>比较** . +3. 使用[分支过滤器搜索框](#branch-filter-search-box)选择要比较的[分支](#branch-filter-search-box) +4. 单击" **比较** "以内联查看更改: + +[![compare branches](img/b4e4d114d9b2244a7848961617e05a95.png)](img/compare_branches.png) + +## Delete merged branches[](#delete-merged-branches "Permalink") + +在 GitLab 8.14 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6449) . + +[![Delete merged branches](img/6de450be845a1f48a3feae9ce8e7be6e.png)](img/delete_merged_branches.png) + +此功能允许合并的分支被批量删除. 作为此操作的一部分,只有已合并[但未受保护的](../../protected_branches.html)分支才会被删除. + +清理合并请求时未自动删除的旧分支尤其有用. + +## Branch filter search box[](#branch-filter-search-box "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22166) . + +[![Branch filter search box](img/f380fbb3646558d8becf561df5894c38.png)](img/branch_filter_search_box.png) + +此功能使您可以快速搜索和选择分支. 搜索结果按以下顺序显示: + +* 名称与搜索字词完全匹配的分支. +* 名称包含搜索词的其他分支,按字母顺序排序. + +有时,当您有数百个分支时,可能需要更灵活的匹配模式. 在这种情况下,您可以使用以下方法: + +* `^feature`将仅匹配以'feature'开头的分支名称. +* `feature$` will only match branch names that end with ‘feature’. \ No newline at end of file diff --git a/_book/docs/152.md b/_book/docs/152.md new file mode 100644 index 0000000000000000000000000000000000000000..d46ae9f9abea42d8b8c05327e7e7cfe5dd60aa06 --- /dev/null +++ b/_book/docs/152.md @@ -0,0 +1,20 @@ +# Git Attributes + +> 原文:[https://docs.gitlab.com/ee/user/project/git_attributes.html](https://docs.gitlab.com/ee/user/project/git_attributes.html) + +* [Encoding Requirements](#encoding-requirements) +* [Syntax Highlighting](#syntax-highlighting) + +# Git Attributes[](#git-attributes "Permalink") + +GitLab 支持定义自定义[Git 属性,](https://git-scm.com/docs/gitattributes)例如将哪些文件视为二进制文件,以及将哪种语言用于语法突出显示差异. + +要定义这些属性, `.gitattributes`在存储库的根目录中创建一个名为`.gitattributes`的文件,并将其推送到项目的默认分支. + +## Encoding Requirements[](#encoding-requirements "Permalink") + +`.gitattributes`文件*必须*使用 UTF-8 编码,并且*不能*包含字节顺序标记. 如果使用其他编码,则文件的内容将被忽略. + +## Syntax Highlighting[](#syntax-highlighting "Permalink") + +`.gitattributes`文件可用于定义语法高亮显示文件和差异时使用的语言. 有关更多信息,请参见["语法突出显示"](highlighting.html) . \ No newline at end of file diff --git a/_book/docs/153.md b/_book/docs/153.md new file mode 100644 index 0000000000000000000000000000000000000000..6df9d56230e589714f739dfeb61598e2e784f2b7 --- /dev/null +++ b/_book/docs/153.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/administration/lfs/manage_large_binaries_with_git_lfs.html](https://docs.gitlab.com/ee/administration/lfs/manage_large_binaries_with_git_lfs.html) \ No newline at end of file diff --git a/_book/docs/154.md b/_book/docs/154.md new file mode 100644 index 0000000000000000000000000000000000000000..057c070dcfc16d2838975d636faae1f9b5146f89 --- /dev/null +++ b/_book/docs/154.md @@ -0,0 +1,86 @@ +# File Locking + +> 原文:[https://docs.gitlab.com/ee/user/project/file_lock.html](https://docs.gitlab.com/ee/user/project/file_lock.html) + +* [Overview](#overview) +* [Use-cases](#use-cases) +* [Locking a file or a directory](#locking-a-file-or-a-directory) +* [Unlocking a file or a directory](#unlocking-a-file-or-a-directory) +* [Viewing and managing existing locks](#viewing-and-managing-existing-locks) +* [Permissions on file locking](#permissions-on-file-locking) + +# File Locking[](#file-locking-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/440) in [GitLab Premium](https://about.gitlab.com/pricing/) 8.9. + +与多个人一起使用同一文件可能会带来风险. 合并非文本文件时的冲突很难克服,将需要大量的手动工作来解决. 文件锁定可帮助您避免这些合并冲突并更好地管理二进制文件. + +使用文件锁定,您可以锁定任何文件或目录,进行更改,然后将其解锁,以便团队的其他成员可以对其进行编辑. + +## Overview[](#overview "Permalink") + +与多个人一起使用同一文件可能会带来风险. 合并非文本文件时的冲突很难克服,将需要大量的手动工作来解决. 借助 GitLab Premium,文件锁定可防止他人(您除外)修改特定文件或整个目录,从而帮助您避免合并冲突并更好地管理二进制文件. + +## Use-cases[](#use-cases "Permalink") + +在以下情况下,文件锁定功能很有用: + +* 多个人正在同一个文件上,您要避免合并冲突. +* 您的存储库包含二进制文件,在这种情况下,没有简单的方法来告诉您与同事的更改之间的区别. +* 防止设计资产被覆盖. + +Locked directories are locked recursively, which means that everything that lies under them is also locked. + +## Locking a file or a directory[](#locking-a-file-or-a-directory "Permalink") + +**注意:**锁定仅适用于您在项目设置中设置的默认分支(通常是`master` ). + +锁定文件: + +1. 导航到项目的" **存储库">"文件"** . +2. 选择您要锁定的文件. +3. 点击"锁定"按钮. + + [![Locking file](img/2f8e418a69825e31935272d55cceae7f.png)](img/file_lock.png) + +要锁定整个目录,请在"历史记录"旁边查找"锁定"链接. + +锁定文件或目录后,它在存储库视图中将显示为已锁定. + +[![Repository view](img/0574a3e535157d8b9c5744214f19f7c7.png)](img/file_lock_repository_view.png) + +一旦锁定,对默认分支的任何合并请求将无法合并,直到文件被解锁. + +## Unlocking a file or a directory[](#unlocking-a-file-or-a-directory "Permalink") + +要解锁文件或目录,请遵循与锁定文件或目录相同的步骤. 有关每个现有锁的详细视图,请参阅下一节"查看和管理现有锁". + +您可以解锁自己或其他人先前锁定的文件,只要您对该项目具有"维护者"或更高[权限](../permissions.html) . + +## Viewing and managing existing locks[](#viewing-and-managing-existing-locks "Permalink") + +要查看或管理每个现有锁,请导航至" **项目">"存储库">"锁定文件"**区域. 在这里,您可以查看所有现有的锁,并[删除您拥有权限的](#permissions-on-file-locking)锁. + +## Permissions on file locking[](#permissions-on-file-locking "Permalink") + +锁定文件或目录的用户**是唯一**可以编辑并将其更改推回锁定对象所在存储库的用户. + +可以对存储库进行[推送访问](../permissions.html)的任何人都可以创建锁. 即开发人员和更高级别的人员,并且只能由其作者和具有维护者权限及更高权限的任何用户删除. + +如果文件被锁定并且您不是其锁定状态的作者,则在尝试推送时,预接收挂钩将拒绝您的更改. 在以下示例中,对锁定的`.gitignore`文件没有权限的用户将看到以下消息: + +``` +Counting objects: 3, done. +Delta compression using up to 4 threads. +Compressing objects: 100% (3/3), done. +Writing objects: 100% (3/3), 320 bytes | 0 bytes/s, done. +Total 3 (delta 1), reused 0 (delta 0) +remote: GitLab: The path '.gitignore' is locked by Administrator +To https://example.com/gitlab-org/gitlab-foss.git + ! [remote rejected] master -> master (pre-receive hook declined) + error: failed to push some refs to 'https://example.com/gitlab-org/gitlab-foss.git' +``` + +同样,当不是文件锁定状态作者的用户接受合并请求时,将出现一条错误消息,指出文件已锁定. + +[![Merge request error message](img/7a5c28bfcfa2942d75aaace7ccb281ce.png)](img/file_lock_merge_request_error_message.png) \ No newline at end of file diff --git a/_book/docs/155.md b/_book/docs/155.md new file mode 100644 index 0000000000000000000000000000000000000000..e5b6ce4357404ddf2b6ad65d29fe0b0ae810904d --- /dev/null +++ b/_book/docs/155.md @@ -0,0 +1,54 @@ +# Git file blame + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/git_blame.html](https://docs.gitlab.com/ee/user/project/repository/git_blame.html) + +* [Blame previous commit](#blame-previous-commit) +* [Associated `git` command](#associated-git-command) +* [File blame through the API](#file-blame-through-the-api) + +# Git file blame[](#git-file-blame "Permalink") + +在 GitLab 2.5 中[引入](https://git.sphere.ly/staff/publicgitlab/commit/39c657930625ddc3ac8a921f01ffc83acadce68f) + +[Git blame](https://git-scm.com/docs/git-blame)提供有关文件中每一行的更多信息,包括最后修改时间,作者和提交哈希. + +您可以在项目中的每个文件中找到" **责备"**按钮. + +[![File blame button](img/1427a32ce32914c8100f7563817e3d64.png "Blame button")](img/file_blame_button_v12_6.png) + +选择" **责备"**按钮时,您会看到一个带有说明信息的屏幕: + +[![Git blame output](img/4a7c845c8d7b28d90af5923b08fb1e1d.png "Blame button output")](img/file_blame_output_v12_6.png) + +如果将鼠标悬停在 UI 中的提交上,您将看到该提交的确切日期和时间. + +## Blame previous commit[](#blame-previous-commit "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/19299) . + +要查看特定行的早期修订,请**在此更改**之前单击" **查看责备",**直到找到您有兴趣查看的**更改**为止: + +[![Blame previous commit](img/dc12d72310a7e06d2981fd6774b0903d.png "Blame previous commit")](img/file_blame_previous_commit_v12_7.png) + +## Associated `git` command[](#associated-git-command "Permalink") + +如果从命令行运行`git` ,则等效命令为`git blame <filename>` . 例如,如果你想找到`blame`有关信息`README.md`在本地目录中的文件,运行以下命令: + +``` +git blame README.md +``` + +您将看到类似于以下内容的输出,其中包括 UTC 格式的提交时间: + +``` +62e2353a (Achilleas Pipinellis 2019-07-11 14:52:18 +0300 1) [![build status](https://gitlab.com/gitlab-org/gitlab-docs/badges/master/build.svg)](https://gitlab.com/gitlab-com/gitlab-docs/commits/master) +fb0fc7d6 (Achilleas Pipinellis 2016-11-07 22:21:22 +0100 2) +^764ca75 (Connor Shea 2016-10-05 23:40:24 -0600 3) # GitLab Documentation +^764ca75 (Connor Shea 2016-10-05 23:40:24 -0600 4) +0e62ed6d (Mike Jang 2019-11-26 21:44:53 +0000 5) This project hosts the repository used to generate the GitLab +0e62ed6d (Mike Jang 2019-11-26 21:44:53 +0000 6) documentation website and deployed to https://docs.gitlab.com. It uses the +``` + +## File blame through the API[](#file-blame-through-the-api "Permalink") + +您也可以通过[Git 文件指责 REST API](../../../api/repository_files.html#get-file-blame-from-repository)来获取此信息. \ No newline at end of file diff --git a/_book/docs/156.md b/_book/docs/156.md new file mode 100644 index 0000000000000000000000000000000000000000..cd1ef819a7ae4d9b3301da08a4af85cc11c4f22c --- /dev/null +++ b/_book/docs/156.md @@ -0,0 +1,61 @@ +# Git file history + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/git_history.html](https://docs.gitlab.com/ee/user/project/repository/git_history.html) + +* [Associated `git` command](#associated-git-command) + +# Git file history[](#git-file-history "Permalink") + +在 GitLab 0.8.0 中[引入](https://gitlab.com/gitlab-org/gitlab/blob/9ba1224867665844b117fa037e1465bb706b3685/app/controllers/commits_controller.rb) + +Git 文件历史记录提供有关与文件关联的提交历史记录的信息. + +您可以在项目中的每个文件中找到" **历史记录"**按钮. + +[![File history button](img/4b803fd891a7ec7f422522d2ff185864.png "History button")](img/file_history_button_v12_6.png) + +当选择" **历史记录"**按钮时,您将看到一个带有说明信息的屏幕: + +[![Git log output](img/0dad61d266449688c931d1703509bca3.png "History button output")](img/file_history_output_v12_6.png) + +如果将鼠标悬停在 UI 中的提交上,您将看到上次修改提交的确切日期和时间. + +## Associated `git` command[](#associated-git-command "Permalink") + +如果从命令行运行`git` ,则等效命令为`git log <filename>` . 例如,如果要在本地目录中找到有关`README.md`文件的`history`信息,请运行以下命令: + +``` +git log README.md +``` + +您将看到类似于以下内容的输出,其中包括 UTC 格式的提交时间: + +``` +commit 0e62ed6d9f39fa9bedf7efc6edd628b137fa781a +Author: Mike Jang <mjang@gitlab.com> +Date: Tue Nov 26 21:44:53 2019 +0000 + + Deemphasize GDK as a doc build tool + +commit 418879420b1e3a4662067bd07b64bb6988654697 +Author: Marcin Sedlak-Jakubowski <msedlakjakubowski@gitlab.com> +Date: Mon Nov 4 19:58:27 2019 +0100 + + Fix typo + +commit 21cc1fef11349417ed515557748369cfb235fc81 +Author: Jacques Erasmus <jerasmus@gitlab.com> +Date: Mon Oct 14 22:13:40 2019 +0000 + + Add support for modern JS + + Added rollup to the project + +commit 2f5e895aebfa5678e51db303b97de56c51e3cebe +Author: Achilleas Pipinellis <axil@gitlab.com> +Date: Fri Sep 13 14:03:01 2019 +0000 + + Remove gitlab-foss Git URLs as we don't need them anymore + + [ci skip] +``` \ No newline at end of file diff --git a/_book/docs/157.md b/_book/docs/157.md new file mode 100644 index 0000000000000000000000000000000000000000..cd825fadbcb512c640eef9a8781fd8f97848a748 --- /dev/null +++ b/_book/docs/157.md @@ -0,0 +1,429 @@ +# Repository mirroring + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/repository_mirroring.html](https://docs.gitlab.com/ee/user/project/repository/repository_mirroring.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Pushing to a remote repository](#pushing-to-a-remote-repository-core) + * [Configuring push mirrors through the API](#configuring-push-mirrors-through-the-api) + * [Push only protected branches](#push-only-protected-branches-core) + * [Keep divergent refs](#keep-divergent-refs-core) +* [Setting up a push mirror from GitLab to GitHub](#setting-up-a-push-mirror-from-gitlab-to-github-core) +* [Setting up a push mirror to another GitLab instance with 2FA activated](#setting-up-a-push-mirror-to-another-gitlab-instance-with-2fa-activated) +* [Pulling from a remote repository](#pulling-from-a-remote-repository-starter) + * [How it works](#how-it-works) + * [SSH authentication](#ssh-authentication) + * [SSH public key authentication](#ssh-public-key-authentication) + * [Overwrite diverged branches](#overwrite-diverged-branches-starter) + * [Only mirror protected branches](#only-mirror-protected-branches-starter) + * [Hard failure](#hard-failure-starter) + * [Trigger update using API](#trigger-update-using-api-starter) +* [Forcing an update](#forcing-an-update-core) +* [Bidirectional mirroring](#bidirectional-mirroring-starter) + * [Configure a webhook to trigger an immediate pull to GitLab](#configure-a-webhook-to-trigger-an-immediate-pull-to-gitlab) + * [Preventing conflicts using a `pre-receive` hook](#preventing-conflicts-using-a-pre-receive-hook) + * [Mirroring with Perforce Helix via Git Fusion](#mirroring-with-perforce-helix-via-git-fusion-starter) +* [Troubleshooting](#troubleshooting) + * [13:Received RST_STREAM with error code 2 with GitHub](#13received-rst_stream-with-error-code-2-with-github) + +# Repository mirroring[](#repository-mirroring "Permalink") + +存储库镜像允许将存储库镜像到外部源或从外部源镜像. 它可用于镜像存储库之间的分支,标签和提交. + +GitLab 上的存储库镜像将自动更新. 您也可以最多每 5 分钟手动触发一次更新. + +## Overview[](#overview "Permalink") + +当您想在 GitLab 之外使用存储库时,存储库镜像很有用. + +GitLab 支持两种存储库镜像: + +* 推送:用于将 GitLab 存储库镜像到另一个位置. +* Pull: for mirroring a repository from another location to GitLab. + +镜像存储库更新后,所有新的分支,标记和提交将在项目的活动提要中可见. + +至少具有[开发人员访问](../../permissions.html)项目[权限](../../permissions.html)的用户也可以强制立即更新,除非: + +* 镜像已被更新. +* 自上次更新以来,还没有过去 5 分钟. + +出于安全原因,在[GitLab 12.10 和更高版本中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27166) ,原始存储库的 URL 仅显示给对镜像项目具有维护者或所有者权限的用户. + +## Use cases[](#use-cases "Permalink") + +以下是存储库镜像的一些可能的用例: + +* 您迁移到了 GitLab,但仍需要将项目保留在另一个源中. 在这种情况下,您只需将其设置为镜像到 GitLab(拉),所有提交,标签和分支的基本历史记录都将在您的 GitLab 实例中提供. +* 您在另一个源中有旧项目,这些旧项目不再使用,但又不想出于归档目的而删除它们. 在这种情况下,您可以创建一个推送镜像,以便您的活动 GitLab 存储库可以将其更改推送到旧位置. + +## Pushing to a remote repository[](#pushing-to-a-remote-repository-core "Permalink") + +版本历史 + +* 在 GitLab 企业版 8.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/249) . +* 在 10.8 版中[移至 GitLab Core](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18715) . + +对于现有项目,可以按如下所示设置推送镜像: + +1. 导航到项目的**"设置">"存储库",**然后展开" **镜像存储库"**部分. +2. 输入存储库 URL. +3. 从**镜像方向**下拉菜单中选择**推送** . +4. 如有必要,请从" **身份验证方法"**下拉列表中选择一种身份**验证方法** . +5. 如有必要,请选中**仅镜像保护的分支**框. +6. 如果需要, **请**选中" **保持差异引用"**框. +7. 单击**镜像存储库**按钮以保存配置. + +[![Repository mirroring push settings screen](img/d67d5681f30c4769c6d92232eada26e4.png)](img/repository_mirroring_push_settings.png) + +启用推送镜像后,只有推送会直接提交到镜像存储库,以防止镜像发散. 任何时候,所有更改都将最终存储在镜像存储库中: + +* 提交被推送到 GitLab. +* [强制更新](#forcing-an-update-core)已启动. + +推送到存储库中文件的更改至少会自动推送到远程镜像: + +* 收到后五分钟内. +* 如果启用了**仅受镜像保护的分支,**则在一分钟之内. + +如果分支分支不同,您将在" **镜像存储库"**部分看到指示的错误. + +### Configuring push mirrors through the API[](#configuring-push-mirrors-through-the-api "Permalink") + +您还可以通过[远程镜像 API](../../../api/remote_mirrors.html)创建和修改项目推送镜像. + +### Push only protected branches[](#push-only-protected-branches-core "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 10.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3350) . +* 在 10.8 版中[移至 GitLab Core](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18715) . + +您可以选择仅将受保护的分支从 GitLab 推送到远程存储库. + +要使用此选项,请在创建存储库镜像时选中" **仅镜像保护的分支"**框. + +### Keep divergent refs[](#keep-divergent-refs-core "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/208828) . + +默认情况下,如果远程镜像上的任何引用都与本地存储库不同,则*整个推送*将失败,并且不会更新任何内容. + +例如,如果存储库具有已镜像到远程的`master` , `develop`和`stable`分支,然后添加新提交以在镜像上进行`develop` ,则下一次推送尝试将失败,从而使`master`和`stable`不在可用范围内约会尽管没有分歧. 在解决分歧之前,无法反映任何分支上的更改. + +启用" **保持差异引用"**选项后,将跳过`develop`分支,从而可以更新`master`和`stable` . 镜像状态将反映`develop`已偏离并被跳过,并标记为更新失败. + +**注意:**创建镜像后,当前只能通过[API](../../../api/remote_mirrors.html)修改此选项. + +## Setting up a push mirror from GitLab to GitHub[](#setting-up-a-push-mirror-from-gitlab-to-github-core "Permalink") + +要设置从 GitLab 到 GitHub 的镜像,您需要执行以下步骤: + +1. 创建一个[GitHub 个人访问令牌](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) ,并选中`public_repo`框. +2. 使用以下格式填写**Git 存储库 URL**字段: `https://<your_github_username>@github.com/<your_github_group>/<your_github_project>.git` . +3. 使用您的 GitHub 个人访问令牌填写**密码**字段. +4. 单击**镜像存储库**按钮. + +镜像的存储库将被列出. 例如, `https://*****:*****@github.com/<your_github_group>/<your_github_project>.git` . + +该存储库将很快推送. 要强制按下,请单击适当的按钮. + +## Setting up a push mirror to another GitLab instance with 2FA activated[](#setting-up-a-push-mirror-to-another-gitlab-instance-with-2fa-activated "Permalink") + +1. 在目标 GitLab 实例上,创建一个具有`write_repository`范围的[个人访问令牌](../../profile/personal_access_tokens.html) . +2. 在源 GitLab 实例上: + 1. 使用以下格式填写**Git 存储库 URL**字段: `https://oauth2@<destination host>/<your_gitlab_group_or_name>/<your_gitlab_project>.git` . + 2. 在目标 GitLab 实例上创建的 GitLab 个人访问令牌中填写**密码**字段. + 3. 单击**镜像存储库**按钮. + +## Pulling from a remote repository[](#pulling-from-a-remote-repository-starter "Permalink") + +版本历史 + +* 在 GitLab 企业版 8.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51) . +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 11.11 中[添加了 Git LFS 支持](https://gitlab.com/gitlab-org/gitlab/-/issues/10871) . + +您可以将存储库设置为自动从上游存储库更新其分支,标记和提交. + +当您感兴趣的存储库位于其他服务器上并且您希望能够使用熟悉的 GitLab 界面浏览其内容和活动时,此功能很有用. + +要为现有项目配置镜像拉出: + +1. Navigate to your project’s **设置>存储库** and expand the **镜像存储库** section. +2. 输入存储库 URL. +3. 从**镜像方向**下拉菜单中选择**拉** . +4. 如有必要,请从" **身份验证方法"**下拉列表中选择一种身份**验证方法** . +5. 如有必要,请选中以下框: + * **覆盖分散的分支** . + * **触发管道以更新镜像** . + * **仅镜像保护的分支** . +6. 单击**镜像存储库**按钮以保存配置. + +[![Repository mirroring pull settings screen - upper part](img/5881da97228cb042e5934f836edfd06c.png)](img/repository_mirroring_pull_settings_upper.png) + +* * * + +[![Repository mirroring pull settings screen - lower part](img/d5df9e77d389b58908ef235600ccc61c.png)](img/repository_mirroring_pull_settings_lower.png) + +Because GitLab is now set to pull changes from the upstream repository, you should not push commits directly to the repository on GitLab. Instead, any commits should be pushed to the upstream repository. Changes pushed to the upstream repository will be pulled into the GitLab repository, either: + +* 在一定时间内自动. +* 启动[强制更新时](#forcing-an-update-core) . + +**警告:**如果您确实在 GitLab 存储库中更新了分支,则该分支将与上游分叉,并且 GitLab 将不再自动更新该分支以防止丢失任何更改. 另请注意,上游存储库中已删除的分支和标签将不会反映在 GitLab 存储库中. + +### How it works[](#how-it-works "Permalink") + +为存储库启用拉镜像功能后,会将存储库添加到队列中. + +每分钟一次,Sidekiq cron 作业基于以下内容计划存储库镜像的更新: + +* 可用容量. 这由 Sidekiq 设置确定. 对于 GitLab.com,请参阅[GitLab.com Sidekiq 设置](../../gitlab_com/index.html#sidekiq) . +* 队列中已经要更新的存储库镜像数. 到期时间取决于存储库镜像的最后更新时间以及重试次数. + +随着 Sidekiq 可以处理存储库镜像,它们也会更新. 如果更新存储库镜像的过程为: + +* 成功后,至少需要等待 30 分钟,更新才会重新加入队列. +* 失败(例如,分支从上游分支),稍后将再次尝试. 镜像最多可以发生 14 次故障,然后才不会再次进入队列进行更新. + +### SSH authentication[](#ssh-authentication "Permalink") + +> * 在[GitLab Starter](https://about.gitlab.com/pricing/) 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2551)了拉镜像. +> * 在[GitLab Core](https://about.gitlab.com/pricing/) 11.6 中为推送镜像[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22982) + +SSH 身份验证是相互的: + +* 您必须向服务器证明您有权访问存储库. +* 服务器还必须向*您*证明它是谁. + +您提供凭据作为密码或公共密钥. 另一个存储库所在的服务器提供其凭据作为"主机密钥",其指纹需要手动验证. + +如果您通过 SSH 镜像(即使用`ssh://` URL),则可以使用以下方法进行身份验证: + +* 基于密码的身份验证,就像通过 HTTPS 一样. +* 公钥认证. 这通常比密码身份验证更安全,尤其是当其他存储库支持[Deploy Keys 时](../../../ssh/README.html#deploy-keys) . + +开始: + +1. 导航到项目的**"设置">"存储库",**然后展开" **镜像存储库"**部分. +2. 输入`ssh://` URL 进行镜像. + +**注意:**目前不支持 SCP 样式的 URL(即`git@example.com:group/project.git` ). + +输入 URL 在页面上添加两个按钮: + +* **检测主机密钥**. +* **手动输入主机密钥**. + +如果单击: + +* **检测主机密钥**按钮,GitLab 将从服务器获取主机密钥并显示指纹. +* **手动输入主机密钥**按钮,将显示一个字段,您可以在其中粘贴主机密钥. + +假设您使用了前者,那么现在需要验证指纹是否符合您的期望. GitLab.com 和其他代码托管站点公开公开其指纹,供您检查: + +* [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/regions.html#regions-fingerprints) +* [Bitbucket](https://support.atlassian.com/bitbucket-cloud/docs/configure-ssh-and-two-step-verification/) +* [GitHub](https://help.github.com/en/github/authenticating-to-github/githubs-ssh-key-fingerprints) +* [GitLab.com](../../gitlab_com/index.html#ssh-host-keys-fingerprints) +* [Launchpad](https://help.launchpad.net/SSHFingerprints) +* [Savannah](http://savannah.gnu.org/maintenance/SshAccess/) +* [SourceForge](https://sourceforge.net/p/forge/documentation/SSH%20Key%20Fingerprints/) + +其他提供者将有所不同. 如果您正在运行自我管理的 GitLab,或者可以访问其他存储库的服务器,则可以安全地收集密钥指纹: + +``` +$ cat /etc/ssh/ssh_host*pub | ssh-keygen -E md5 -l -f - +256 MD5:f4:28:9f:23:99:15:21:1b:bf:ed:1f:8e:a0:76:b2:9d root@example.com (ECDSA) +256 MD5:e6:eb:45:8a:3c:59:35:5f:e9:5b:80:12:be:7e:22:73 root@example.com (ED25519) +2048 MD5:3f:72:be:3d:62:03:5c:62:83:e8:6e:14:34:3a:85:1d root@example.com (RSA) +``` + +**注意:**对于某些旧版本的 SSH,可能需要排除`-E md5` . + +在镜像存储库时,GitLab 现在将在连接之前检查至少一个存储的主机密钥是否匹配. 这样可以防止将恶意代码注入到您的镜像中,或者防止您的密码被盗. + +### SSH public key authentication[](#ssh-public-key-authentication "Permalink") + +要使用 SSH 公钥身份验证,您还需要从**Authentication method**下拉菜单中选择该选项. 创建镜像后,GitLab 会生成一个 4096 位 RSA 密钥,可以通过单击" **复制 SSH"公共密钥**按钮进行复制. + +[![Repository mirroring copy SSH public key to clipboard button](img/c1e086b58ff99dd5c5684a4571e568e3.png)](img/repository_mirroring_copy_ssh_public_key_button.png) + +然后,您需要将公共 SSH 密钥添加到另一个存储库的配置中: + +* 如果其他存储库托管在 GitLab 上,则应将公共 SSH 密钥添加为[Deploy Key](../../../ssh/README.html#deploy-keys) . +* 如果其他存储库位于其他位置,则可能需要将密钥添加到用户的`authorized_keys`文件中. 将整个公共 SSH 密钥单独粘贴到文件中并保存. + +如果您需要随时更改密钥,则可以删除并重新添加镜像以生成新密钥. 您必须使用新密钥更新另一个存储库,以保持镜像运行. + +**注意:**生成的密钥存储在 GitLab 数据库中,而不存储在文件系统中. 因此,无法在预接收挂钩中使用针对镜像的 SSH 公钥身份验证. + +### Overwrite diverged branches[](#overwrite-diverged-branches-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4559) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. + +您可以选择始终使用远程版本更新本地分支,即使它们与远程分支不同. + +**警告:**对于镜像分支,启用此选项会导致丢失本地更改. + +要使用此选项,请在创建存储库镜像时选中" **覆盖分支分支"**框. + +### Only mirror protected branches[](#only-mirror-protected-branches-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3326) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3. + +您可以选择仅将受保护的分支从远程存储库拉到 GitLab. 未受保护的分支不会被镜像,并且可能会分开. + +要使用此选项,请在创建存储库镜像时选中" **仅镜像保护的分支"**框. + +### Hard failure[](#hard-failure-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3117) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2. + +如果镜像过程连续 14 次失败重试,它将被标记为硬盘失败. 这将在以下任一位置中可见: + +* 项目的主要仪表板. +* 拉镜设置页面. + +当一个项目很难失败时,它将不再需要进行镜像. 用户可以通过[强制更新来](#forcing-an-update-core)再次恢复项目镜像. + +### Trigger update using API[](#trigger-update-using-api-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3453) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3. + +拉镜像使用轮询来检测新添加的分支和提交,通常是在几分钟后. 如果您通过[API](../../../api/projects.html#start-the-pull-mirroring-process-for-a-project-starter)通知 GitLab,更新将立即被拉出. + +有关更多信息,请参阅[启动项目的拉镜像过程](../../../api/projects.html#start-the-pull-mirroring-process-for-a-project-starter) . + +## Forcing an update[](#forcing-an-update-core "Permalink") + +当计划将镜像自动更新时,您始终可以使用" **存储** **库设置"**页面的" **镜像存储库"**部分上的"更新"按钮强制进行更新. + +[![Repository mirroring force update user interface](img/a6e9b62f94c53cd2f37f7300362137a9.png)](img/repository_mirroring_force_update.png) + +## Bidirectional mirroring[](#bidirectional-mirroring-starter "Permalink") + +**注意:**双向镜像可能会导致冲突. + +如果您将 GitLab 存储库配置为从同一远程源中拉出和推送到同一远程源,则不能保证这两个存储库都将正确更新. 如果为双向镜像设置存储库,则应通过确定谁将解决它们以及如何解决它们来为可能的冲突做准备. + +重写任一远程上的任何镜像提交将导致冲突,并且镜像失败. 可以通过以下方法防止此情况: + +* [Pulling only protected branches](#only-mirror-protected-branches-starter). +* [Pushing only protected branches](#push-only-protected-branches-core). + +您应该[保护](../protected_branches.html)希望在两个远程控制器上镜像[的分支](../protected_branches.html) ,以防止由于重写历史记录而引起的冲突. + +双向镜像还会创建竞态条件,在这种竞态条件中,靠近同一分支的提交会引起冲突. 通过使用[Push 事件 Webhook](../integrations/webhooks.html#push-events)触发立即拉到 GitLab,可以通过减少镜像延迟来缓解竞争状况. 当仅推送镜像受保护的分支时,来自 GitLab 的推送镜像的速率限制为每分钟一次. + +### Configure a webhook to trigger an immediate pull to GitLab[](#configure-a-webhook-to-trigger-an-immediate-pull-to-gitlab "Permalink") + +假设您已经在上游 GitLab 实例中配置了[推](#setting-up-a-push-mirror-to-another-gitlab-instance-with-2fa-activated)和[拉](#pulling-from-a-remote-repository-starter)镜像,以触发如上所述的立即提拉,则需要在下游实例中配置一个[推事件 Web 挂钩](../integrations/webhooks.html#push-events) . + +去做这个: + +* 创建具有`API`范围的[个人访问令牌](../../profile/personal_access_tokens.html) . +* 导航到**设置> Webhooks** +* 添加 webhook URL,在这种情况下,它将在存储库更新后使用[Pull Mirror API](../../../api/projects.html#start-the-pull-mirroring-process-for-a-project-starter)请求触发即时提取. + + ``` + https://gitlab.example.com/api/v4/projects/:id/mirror/pull?private_token=<your_access_token> + ``` + +* 确保已选中" **推送事件"**复选框. +* 单击**添加 Webhook**按钮以保存**Webhook** . +* 要测试集成,请单击" **测试"**按钮,并确认 GitLab 不返回任何错误. + +### Preventing conflicts using a `pre-receive` hook[](#preventing-conflicts-using-a-pre-receive-hook "Permalink") + +**警告:**提议的解决方案将对 Git 推送操作的性能产生负面影响,因为它们将被代理到上游 Git 存储库. + +服务器端`pre-receive`挂钩可通过仅在将提交首先推送到上游 Git 存储库之后才接受推送来防止上述竞争情况. 在此配置中,一个 Git 存储库充当权威的上游,另一个充当下游. `pre-receive`挂钩将安装在下游存储库中. + +阅读有关在 GitLab 服务器上[配置服务器挂钩](../../../administration/server_hooks.html)的信息. + +下面提供了一个样品`pre-receive`挂钩. + +``` +#!/usr/bin/env bash + +# --- Assume only one push mirror target +# Push mirroring remotes are named `remote_mirror_<id>`, this finds the first remote and uses that. +TARGET_REPO=$(git remote | grep -m 1 remote_mirror) + +proxy_push() +{ + # --- Arguments + OLDREV=$(git rev-parse $1) + NEWREV=$(git rev-parse $2) + REFNAME="$3" + + # --- Pattern of branches to proxy pushes + allowlist=$(expr "$branch" : "\(master\)") + + case "$refname" in refs/heads/*) + branch=$(expr "$refname" : "refs/heads/\(.*\)") + + if [ "$allowlist" = "$branch" ]; then unset GIT_QUARANTINE_PATH # handle https://git-scm.com/docs/git-receive-pack#_quarantine_environment + error="$(git push --quiet $TARGET_REPO $NEWREV:$REFNAME 2>&1)" + fail=$? + + if [ "$fail" != "0" ]; then echo >&2 "" + echo >&2 " Error: updates were rejected by upstream server" + echo >&2 " This is usually caused by another repository pushing changes" + echo >&2 " to the same ref. You may want to first integrate remote changes" + echo >&2 "" + return + fi + fi + ;; + esac +} + +# Allow dual mode: run from the command line just like the update hook, or +# if no arguments are given then run as a hook script +if [ -n "$1" -a -n "$2" -a -n "$3" ]; then + # Output to the terminal in command line mode - if someone wanted to + # resend an email; they could redirect the output to sendmail + # themselves + PAGER= proxy_push $2 $3 $1 +else + # Push is proxied upstream one ref at a time. Because of this it is possible + # for some refs to succeed, and others to fail. This will result in a failed + # push. + while read oldrev newrev refname + do proxy_push $oldrev $newrev $refname + done +fi +``` + +请注意,此示例有一些限制: + +* 此示例可能无法完全满足您的用例,并且可能需要进行修改. + * 它不考虑镜像的不同类型的身份验证机制. + * 它不适用于强制更新(重写历史记录). + * 仅匹配`allowlist`模式的分支将被代理推送. +* 该脚本规避了 Git 钩子隔离环境,因为`$TARGET_REPO`的更新被视为参考更新,Git 会对此进行抱怨. + +### Mirroring with Perforce Helix via Git Fusion[](#mirroring-with-perforce-helix-via-git-fusion-starter "Permalink") + +**警告:**双向镜像不应用作永久配置. 有关替代的迁移方法,请参阅[从 Perforce Helix](../import/perforce.html)迁移. + +[Git Fusion](https://www.perforce.com/manuals/git-fusion/#Git-Fusion/section_avy_hyc_gl.html)为[Perforce Helix](https://www.perforce.com/products)提供了一个 Git 接口,GitLab 可以使用它来双向镜像 GitLab 项目. 从 Perforce Helix 迁移到 GitLab 的某些情况下,这可能是有用的,因为重叠的 Perforce Helix 工作区无法同时迁移到 GitLab. + +如果将镜像与 Perforce Helix 一起使用,则应仅镜像受保护的分支. Perforce Helix 将拒绝任何重写历史记录的推送. 由于 Git Fusion 的性能限制,只应镜像最少数量的分支. + +通过 Git Fusion 使用 Perforce Helix 配置镜像时,建议使用以下 Git Fusion 设置: + +* `change-pusher`应禁用. 否则,每个提交都将被重写为由镜像帐户提交,而不是映射到现有的 Perforce Helix 用户或`unknown_git`用户. +* 如果 Perforce Helix 中不存在 GitLab 用户,则`unknown_git`用户将用作提交作者. + +[在 Perforce.com 上](https://www.perforce.com/manuals/git-fusion/Content/Git-Fusion/section_vss_bdw_w3.html#section_zdp_zz1_3l)了解有关[Git Fusion 设置的信息](https://www.perforce.com/manuals/git-fusion/Content/Git-Fusion/section_vss_bdw_w3.html#section_zdp_zz1_3l) . + +## Troubleshooting[](#troubleshooting "Permalink") + +如果在推送过程中发生错误,则 GitLab 将在该存储库中显示"错误"突出显示. 然后,将鼠标悬停在突出显示的文本上,即可查看有关错误的详细信息. + +### 13:Received RST_STREAM with error code 2 with GitHub[](#13received-rst_stream-with-error-code-2-with-github "Permalink") + +如果在镜像到 GitHub 存储库时收到"错误代码为 2 的 13:Received RST_STREAM",则您的 GitHub 设置可能被设置为阻止推送,以暴露用于提交的电子邮件地址. 可以将您在 GitHub 上的电子邮件地址设置为公开,或者禁用[公开我的电子邮件](https://github.com/settings/emails)设置的" [阻止"命令行推送](https://github.com/settings/emails) . \ No newline at end of file diff --git a/_book/docs/158.md b/_book/docs/158.md new file mode 100644 index 0000000000000000000000000000000000000000..fe9f35a011c1d8b4d616c961b945564242e9402c --- /dev/null +++ b/_book/docs/158.md @@ -0,0 +1,171 @@ +# Protected branches + +> 原文:[https://docs.gitlab.com/ee/user/project/protected_branches.html](https://docs.gitlab.com/ee/user/project/protected_branches.html) + +* [Overview](#overview) +* [Configuring protected branches](#configuring-protected-branches) +* [Using the Allowed to merge and Allowed to push settings](#using-the-allowed-to-merge-and-allowed-to-push-settings) +* [Restricting push and merge access to certain users](#restricting-push-and-merge-access-to-certain-users-starter) +* [Wildcard protected branches](#wildcard-protected-branches) +* [Creating a protected branch](#creating-a-protected-branch) +* [Deleting a protected branch](#deleting-a-protected-branch) +* [Protected Branches approval by Code Owners](#protected-branches-approval-by-code-owners-premium) +* [Running pipelines on protected branches](#running-pipelines-on-protected-branches) +* [Changelog](#changelog) + +# Protected branches[](#protected-branches "Permalink") + +GitLab 中的[权限](../permissions.html)基本上是围绕对存储库和分支具有读或写权限的想法定义的. 为了对某些分支机构施加进一步的限制,可以对其进行保护. + +## Overview[](#overview "Permalink") + +默认情况下,受保护的分支执行以下四个简单的操作: + +* 它会阻止除具有维护者权限的用户之外的所有用户创建它(如果尚未创建). +* 它可以防止除具有**允许的**权限的用户以外的其他任何人推送. +* 它可以防止**任何人**用力推动分支机构. +* 它可以防止**任何人**删除分支. + +**注意:**允许 GitLab 管理员推送到受保护的分支. + +有关随时间的变化,请参见" [更改日志"](#changelog)部分. + +默认的分支保护级别在[管理区域中](../admin_area/settings/visibility_and_access_controls.html#default-branch-protection)设置. + +## Configuring protected branches[](#configuring-protected-branches "Permalink") + +要保护分支,您需要至少具有维护者权限级别. 请注意,默认情况下`master`分支是受保护的. + +1. 导航到项目的**"设置"➔"存储库"** +2. 滚动查找" **受保护的分支"**部分. +3. 从" **分支"**下拉菜单中,选择要保护的分支,然后单击" **保护"** . 在下面的屏幕截图中,我们选择了`develop`分支. + + [![Protected branches page](img/c29b503c10922622f8ec612bd5168b10.png)](img/protected_branches_page_v12_3.png) + +4. 完成后,受保护的分支将出现在"受保护的分支"列表中. + + [![Protected branches list](img/265f035427185c0998b05886114d104b.png)](img/protected_branches_list_v12_3.png) + +## Using the Allowed to merge and Allowed to push settings[](#using-the-allowed-to-merge-and-allowed-to-push-settings "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5081) . + +从 GitLab 8.11 开始,我们增加了分支保护的另一层,它提供了对受保护分支的更精细的管理. "开发人员可以推送"选项由"允许推送"设置代替,该设置可以设置为允许/禁止维护者和/或开发人员推送到受保护的分支. + +使用"允许推送"和"允许合并"设置,您可以控制不同角色可以在受保护分支中执行的操作. 例如,您可以将"允许推送"设置为"无人",将"允许合并"设置为"开发人员+维护人员",以要求*每个人都*提交合并请求,以请求更改进入受保护分支. 这与[GitLab 工作](../../topics/gitlab_flow.html)流程等[工作流程](../../topics/gitlab_flow.html)兼容. + +但是,有些工作流程不需要这样做,只有防止强行推动和移除分支才有用. 对于这些工作流程,您可以通过将"允许推送"设置为"开发人员+维护人员"来允许具有写访问权的每个人推送到受保护的分支. + +您可以在创建受保护的分支时设置"允许推送"和"允许合并"选项,也可以在之后通过从"已保护"区域的下拉列表中选择所需的选项来设置. + +[![Developers can push](img/eca0c9ec85c6dfc8dbde06c368a9d94d.png)](img/protected_branches_devs_can_push_v12_3.png) + +如果在创建受保护的分支时未选择任何这些选项,则默认情况下会将它们设置为"维护者". + +## Restricting push and merge access to certain users[](#restricting-push-and-merge-access-to-certain-users-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5081) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.11. + +使用 GitLab 企业版,您可以通过选择角色(维护者,开发者)以及某些用户来限制对受保护分支的访问. 从下拉菜单中选择您要合并或推送访问的角色和/或用户. + +[![Select roles and users](img/8fc9989164e038f62ee1015c2f477d84.png)](img/protected_branches_select_roles_and_users.png) + +单击" **保护"** ,该分支将出现在"受保护的分支"列表中. + +[![Roles and users list](img/0387751ed4b8717777ebac2706c2d637.png)](img/protected_branches_select_roles_and_users_list.png) + +## Wildcard protected branches[](#wildcard-protected-branches "Permalink") + +在 GitLab 8.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4665) . + +您可以指定一个通配符保护的分支,该分支将保护所有与通配符匹配的分支. 例如: + +| 通配符保护的分支 | 匹配分支 | +| --- | --- | +| `*-stable` | `production-stable`, `staging-stable` | +| `production/*` | `production/app-server`, `production/load-balancer` | +| `*gitlab*` | `gitlab`, `gitlab/staging`, `master/gitlab/production` | + +受保护的分支设置(如"开发人员可以推送")适用于所有匹配的分支. + +两个不同的通配符可能会匹配同一分支. 例如, `*-stable` `production-stable`和`production-*`都将与`production-stable`分支匹配. 在这种情况下,如果*这些*受保护的分支有这样一个设定"允许推送",然后`production-stable`也将继承这一设置. + +如果单击受保护分支的名称,将显示所有匹配分支的列表: + +[![Protected branch matches](img/09870a42c6e3e94e7553f338a65c0b6d.png)](img/protected_branches_matches.png) + +## Creating a protected branch[](#creating-a-protected-branch "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53361) . + +当受保护的分支或通配符受保护的分支设置为" [**不允许任何人** **推送"时**](#using-the-allowed-to-merge-and-allowed-to-push-settings) ,只要允许开发人员(和具有较高[权限级别的](../permissions.html)用户) [**合并**](#using-the-allowed-to-merge-and-allowed-to-push-settings) ,就可以创建新的受保护分支. 这只能通过 UI 或 API 来完成(为避免意外地从命令行或 Git 客户端应用程序创建受保护的分支). + +通过用户界面创建新分支: + +1. Visit **资料库>分支机构**. +2. Click on **新分支**. +3. 填写分支名称,然后选择一个现有的分支,标记或确认新分支将基于该分支. 仅接受现有的受保护分支和已经在受保护分支中的提交. + +## Deleting a protected branch[](#deleting-a-protected-branch "Permalink") + +在 GitLab 9.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21393) . + +有时可能需要删除或清理受保护的分支. + +具有[维护者权限](../permissions.html)并具有[维护者权限的](../permissions.html)用户可以通过 GitLab 的 Web 界面手动删除受保护的分支: + +1. Visit **资料库>分支机构** +2. 单击您要删除的分支旁边的删除图标 +3. 为了防止意外删除,需要额外的确认 + + [![Delete protected branches](img/4e86bb665dcf8b8997d807441dbd60cd.png)](img/protected_branches_delete.png) + +只能通过 Web 界面而不是 Git 删除受保护的分支. 这意味着您不能从命令行或 Git 客户端应用程序中意外删除受保护的分支. + +## Protected Branches approval by Code Owners[](#protected-branches-approval-by-code-owners-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13251) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4. + +对于合并请求更改的文件,可能需要[代码所有者的](code_owners.html)至少一项批准. 可以在保护新分支时设置"代码所有者"批准,也可以将其设置为已经受保护的分支,如下所述. + +要保护新分支并获得代码所有者的批准: + +1. 导航到项目的**"设置">"存储库",**然后展开" **受保护的分支"** . +2. 向下滚动到**保护一个分支** ,选择**分支**或通配符你想保护,选择谁的**允许合并** **,**并**允许推** ,以及切换**需要从代码的业主**滑块**批准** . +3. Click **Protect**. + +[![Code Owners approval - new protected branch](img/9a996b513114d1fe39fa67c75e54df46.png)](img/code_owners_approval_new_protected_branch_v12_4.png) + +要使代码所有者批准已受保护的分支机构,请执行以下操作: + +1. 导航到项目的**"设置">"存储库",**然后展开" **受保护的分支"** . +2. 向下滚动到" **受保护"分支,**然后切换所选分支的**"代码所有者"批准**滑块. + +[![Code Owners approval - branch already protected](img/7a4195dce33a791e39b721499e4137ad.png)](img/code_owners_approval_protected_branch_v12_4.png) + +启用后,所有针对这些分支的合并请求都将需要代码所有者根据匹配的规则进行批准,然后才能合并. 此外,如果匹配规则,则拒绝直接推送到受保护的分支. + +## Running pipelines on protected branches[](#running-pipelines-on-protected-branches "Permalink") + +合并或推送到受保护分支的权限用于定义用户是否可以运行 CI / CD 管道并在与那些分支相关的作业上执行操作. + +有关管道安全模型的详细信息,请参阅[受保护分支上](../../ci/pipelines/index.html#pipeline-security-on-protected-branches)的安全性. + +## Changelog[](#changelog "Permalink") + +**11.9** + +* [允许](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53361)开发人员(和具有更高权限级别的用户)通过 API 和用户界面[创建受保护的分支](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53361) . + +**9.2** + +* 允许通过 Web 界面删除受保护的分支( [问题#21393](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21393) ). + +**8.11** + +* 允许创建无法推送到的受保护分支( [合并请求!5081](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5081) ). + +**8.10** + +* 允许没有推送访问权限的开发人员合并到受保护的分支中( [合并请求!4892](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4892) ). +* 允许使用通配符指定受保护的分支( [合并请求!4665](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4665) ). \ No newline at end of file diff --git a/_book/docs/159.md b/_book/docs/159.md new file mode 100644 index 0000000000000000000000000000000000000000..3f697d78040addc531af631bbd7e033bdd193bf8 --- /dev/null +++ b/_book/docs/159.md @@ -0,0 +1,56 @@ +# Protected tags + +> 原文:[https://docs.gitlab.com/ee/user/project/protected_tags.html](https://docs.gitlab.com/ee/user/project/protected_tags.html) + +* [Overview](#overview) +* [Configuring protected tags](#configuring-protected-tags) +* [Wildcard protected tags](#wildcard-protected-tags) + +# Protected tags[](#protected-tags "Permalink") + +在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10356) . + +受保护的标签可控制谁有权创建标签,并防止创建后意外更新或删除. 每个规则都允许您匹配单个标签名称,或使用通配符一次控制多个标签. + +此功能从[受保护的分支](protected_branches.html)演变而来 + +## Overview[](#overview "Permalink") + +受保护的标签将阻止任何人更新或删除标签,并且将根据您选择的权限阻止创建匹配的标签. 默认情况下,任何未经维护者许可的人都将无法创建标签. + +## Configuring protected tags[](#configuring-protected-tags "Permalink") + +为了保护标签,您需要至少具有维护者权限级别. + +1. 导航到项目的**"设置">"存储库"** : + + [![Repository Settings](img/bec396562e8fe025cb7009de091ff2aa.png)](img/project_repository_settings.png) + +2. 从**标签**下拉菜单中,选择要保护或输入的标签,然后点击**创建通配符** . 在下面的屏幕截图中,我们选择保护所有与`v*`匹配的标签: + + [![Protected tags page](img/8ab62c2dee9f26abae9b7f794b4f5fae.png)](img/protected_tags_page_v12_3.png) + +3. 从" **允许创建"**下拉列表中,选择谁有权创建匹配的标签,然后单击" **保护"** : + + [![Allowed to create tags dropdown](img/52fecb33c2f168630e9a8f7c95aaf517.png)](img/protected_tags_permissions_dropdown_v12_3.png) + +4. 完成后,受保护的标签将显示在" **受保护的标签"**列表中: + + [![Protected tags list](img/572645049ee5ab43733f62fc45312843.png)](img/protected_tags_list_v12_3.png) + +## Wildcard protected tags[](#wildcard-protected-tags "Permalink") + +您可以指定一个通配符保护的标记,它将保护所有与通配符匹配的标记. 例如: + +| 通配符保护标签 | 匹配标签 | +| --- | --- | +| `v*` | `v1.0.0`, `version-9.1` | +| `*-deploy` | `march-deploy`, `1.0-deploy` | +| `*gitlab*` | `gitlab`, `gitlab/v1` | +| `*` | `v1.0.1rc2`, `accidental-tag` | + +两个不同的通配符可以潜在地匹配同一标签. 例如, `*-stable` `production-stable`和`production-*`都将与`production-stable`标签匹配. 在这种情况下,如果*这些*受保护的标签都像**允许创建**一个设定,然后`production-stable`也将沿用此设置. + +如果单击受保护标签的名称,将显示所有匹配标签的列表: + +[![Protected tag matches](img/cc52a99e48b72695add0c3e8efab158f.png)](img/protected_tag_matches.png) \ No newline at end of file diff --git a/_book/docs/160.md b/_book/docs/160.md new file mode 100644 index 0000000000000000000000000000000000000000..e8c1e32df32c23ca6e3568712e6555611916e058 --- /dev/null +++ b/_book/docs/160.md @@ -0,0 +1,147 @@ +# Push Rules + +> 原文:[https://docs.gitlab.com/ee/push_rules/push_rules.html](https://docs.gitlab.com/ee/push_rules/push_rules.html) + +* [Overview](#overview) +* [Use cases](#use-cases) + * [Commit messages with a specific reference](#commit-messages-with-a-specific-reference) + * [Restrict branch names](#restrict-branch-names) + * [Custom Push Rules](#custom-push-rules-core-only) +* [Enabling push rules](#enabling-push-rules) +* [Prevent pushing secrets to the repository](#prevent-pushing-secrets-to-the-repository) + +# Push Rules[](#push-rules-starter "Permalink") + +通过使用正则表达式拒绝基于提交内容,分支名称或文件详细信息的推送,来获得对哪些内容可以推送或不能推送到存储库的额外控制. + +## Overview[](#overview "Permalink") + +GitLab 已经提供了[受保护的分支](../user/project/protected_branches.html) ,但是在某些情况下,您需要一些特定的规则,例如,防止删除 Git 标签或对提交消息强制采用特殊格式. + +推送规则本质上是[预先接收的 Git 挂钩](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) ,可在用户友好的界面中轻松启用. 如果您是管理员或每个项目,它们是全局定义的,因此您可以根据需要将不同的规则应用于不同的项目. + +## Use cases[](#use-cases "Permalink") + +每个推送规则都可以有自己的用例,但让我们考虑一些示例. + +### Commit messages with a specific reference[](#commit-messages-with-a-specific-reference "Permalink") + +假设您对工作流程有以下要求: + +* 每个提交都应引用 Jira 问题,例如: `Refactored css. Fixes JIRA-123.` `Refactored css. Fixes JIRA-123.` +* 用户应该无法使用`git push`删除 Git 标签 + +您需要做的就是编写一个简单的正则表达式,要求在提交消息中提及一个 Jira 问题,例如`JIRA\-\d+` . + +现在,当用户尝试通过消息`Bugfix`推送提交时,他们的推送将被拒绝. 仅接受`Bugfix according to JIRA-123`推送带有`Bugfix according to JIRA-123`消息的提交. + +### Restrict branch names[](#restrict-branch-names "Permalink") + +假设您公司中有严格的分支机构名称政策,并且您希望分支机构以特定名称开头,因为您有不同的 GitLab CI / CD 作业( `feature` , `hotfix` , `docker` , `android`等)依赖于分支机构名称. + +但是,您的开发人员并不总是记住该策略,因此他们可能会推送到各个分支,并且 CI 管道可能无法按预期工作. 通过在推送规则中全局限制分支名称,可以防止此类错误. 与您的推送规则不匹配的任何分支名称都将被拒绝. + +请注意,不管指定的分支命名正则表达式(regex)如何,始终允许使用默认分支的名称. 通过这种方式配置 GitLab,因为合并通常将默认分支作为目标. 如果您还有其他目标分支,请将其包含在正则表达式中. (请参阅[启用推送规则](#enabling-push-rules) ). + +默认分支还默认为[受保护分支](../user/project/protected_branches.html) ,这已经限制了用户直接推送. + +### Custom Push Rules[](#custom-push-rules-core-only "Permalink") + +通过使用更高级的服务器挂钩,可以创建自定义推送规则,而不是" **管理区域">"推送规则"中**可用的**推送规则** . + +有关更多信息,请参见[服务器挂钩](../administration/server_hooks.html) . + +## Enabling push rules[](#enabling-push-rules "Permalink") + +**注意:** GitLab 管理员可以在" **管理区域">"**所有新项目都将继承的**推送规则"**下全局设置推送规则. 您以后可以在项目的设置中覆盖它们. 也可以在[组级别](../user/group/index.html#group-push-rules-starter)上设置它们. + +1. 导航到项目的**"设置">"存储库",**然后展开" **推送规则"** +2. 设置所需的规则 +3. 单击" **保存推送规则"**以使更改生效 + +以下选项可用. + +| 推送规则 | GitLab 版本 | Description | +| --- | --- | --- | +| 用`git push`删除标签 | **Starter** 7.10 | 禁止用户使用`git push`删除 Git 标签. 仍然可以通过 Web UI 删除标签. | +| 检查作者是否是 GitLab 用户 | **Starter** 7.10 | 限制作者(电子邮件)对现有 GitLab 用户的提交. | +| 提交者限制 | **Premium** 10.2 | GitLab will reject any commit that was not committed by the current authenticated user | +| 检查提交是否通过 GPG 签名 | **Premium** 10.1 | 如果未通过 GPG 签名,则拒绝提交. [使用 GPG](../user/project/repository/gpg_signed_commits/index.html)阅读[签名提交](../user/project/repository/gpg_signed_commits/index.html) . | +| 防止向 Git 提交机密 | **Starter** 8.12 | GitLab 将拒绝任何可能包含机密的文件. 阅读[禁止使用的文件](#prevent-pushing-secrets-to-the-repository) . | +| 通过提交消息限制 | **Starter** 7.10 | 只允许推送与此正则表达式匹配的提交消息. 保留为空以允许任何提交消息. 使用多行模式,可以使用`(?-m)`禁用该模式. | +| 受提交消息限制(负匹配) | **Starter** 11.1 | 只允许提交与此正则表达式不匹配的提交消息. 保留为空以允许任何提交消息. 使用多行模式,可以使用`(?-m)`禁用该模式. | +| 受分支名称限制 | **Starter** 9.3 | 只允许推送与此正则表达式匹配的分支名称. 保留为空以允许使用任何分支名称. | +| 通过提交作者的电子邮件进行限制 | **Starter** 7.10 | 只允许推送与此正则表达式匹配的提交者的电子邮件. 留空以允许任何电子邮件. | +| 禁止的文件名 | **Starter** 7.10 | 与该正则表达式匹配的所有提交的文件名均不允许推送. 保留为空以允许任何文件名. | +| 最大档案大小 | **Starter** 7.12 | 包含超过此文件大小(以 MB 为单位)的添加或更新文件的推送将被拒绝. 设置为 0 允许任何大小的文件. 由 Git LFS 跟踪的文件被豁免. | + +**提示:** GitLab 对推送规则中的正则表达式使用[RE2 语法](https://github.com/google/re2/wiki/Syntax) ,您可以在[GoLang regex tester 上](https://regex-golang.appspot.com/assets/html/index.html)对其进行[测试](https://regex-golang.appspot.com/assets/html/index.html) . + +## Prevent pushing secrets to the repository[](#prevent-pushing-secrets-to-the-repository "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.12. + +诸如凭证文件,SSH 私钥之类的机密以及其他包含机密的文件绝不应提交给源代码控制. GitLab 允许您打开文件的预定义拒绝列表,该列表将不允许被推送到存储库,从而阻止这些提交到达远程存储库. + +通过选中*防止向 Git 提交机密*复选框,当文件与从[`files_denylist.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/gitlab/checks/files_denylist.yml)读取的正则表达式匹配时,GitLab 会阻止将其推送到存储库(在查看此文件时,请确保您处于与 GitLab 版本相同的正确分支). + +**注意:**已经提交的文件将不受此推送规则的限制. + +下面是这些正则表达式将拒绝的内容的示例列表: + +``` +##################### +# AWS CLI credential blobs +##################### +.aws/credentials +aws/credentials +homefolder/aws/credentials + +##################### +# Private RSA SSH keys +##################### +/ssh/id_rsa +/.ssh/personal_rsa +/config/server_rsa +id_rsa +.id_rsa + +##################### +# Private DSA SSH keys +##################### +/ssh/id_dsa +/.ssh/personal_dsa +/config/server_dsa +id_dsa +.id_dsa + +##################### +# Private ed25519 SSH keys +##################### +/ssh/id_ed25519 +/.ssh/personal_ed25519 +/config/server_ed25519 +id_ed25519 +.id_ed25519 + +##################### +# Private ECDSA SSH keys +##################### +/ssh/id_ecdsa +/.ssh/personal_ecdsa +/config/server_ecdsa +id_ecdsa +.id_ecdsa + +##################### +# Any file with .pem or .key extensions +##################### +*.pem +*.key + +##################### +# Any file ending with _history or .history extension +##################### +pry.history +bash_history +``` \ No newline at end of file diff --git a/_book/docs/161.md b/_book/docs/161.md new file mode 100644 index 0000000000000000000000000000000000000000..8d07161c22c78189c5523934fd545fcb56581996 --- /dev/null +++ b/_book/docs/161.md @@ -0,0 +1,211 @@ +# Reduce repository size + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/reducing_the_repo_size_using_git.html](https://docs.gitlab.com/ee/user/project/repository/reducing_the_repo_size_using_git.html) + +* [Purge files from repository history](#purge-files-from-repository-history) +* [Purge files from GitLab storage](#purge-files-from-gitlab-storage) +* [Repository cleanup](#repository-cleanup) +* [Storage limits](#storage-limits) + +# Reduce repository size[](#reduce-repository-size "Permalink") + +随着时间的流逝,Git 存储库变得越来越大. 将大文件添加到 Git 存储库后: + +* 由于每个人都必须下载文件,因此获取存储库的速度变慢. +* 它们占用服务器上的大量存储空间. +* [可以达到](#storage-limits) Git 仓库的存储限制. + +重写存储库可能会删除不需要的历史记录,从而使存储库更小. [`git filter-repo`](https://github.com/newren/git-filter-repo)是用于快速重写 Git 存储库历史记录的工具,建议同时使用以下两种工具: + +* [`git filter-branch`](https://git-scm.com/docs/git-filter-branch). +* [BFG](https://rtyley.github.io/bfg-repo-cleaner/). + +**危险:**重写存储库历史记录是一种破坏性操作. 在开始之前,请确保备份您的存储库. 备份存储库的最佳方法是[导出项目](../settings/import_export.html#exporting-a-project-and-its-data) .**注意:** Git LFS 文件只能由管理员使用[Rake 任务](../../../raketasks/cleanup.html)删除. [计划](https://gitlab.com/gitlab-org/gitlab/-/issues/223621)消除此限制. + +## Purge files from repository history[](#purge-files-from-repository-history "Permalink") + +为了使克隆项目更快,请重写分支和标签以删除不需要的文件. + +1. 使用受支持的程序包管理器或从源代码[安装`git filter-repo`](https://github.com/newren/git-filter-repo/blob/main/INSTALL.md) . + +2. 使用`--bare`克隆存储库的新副本: + + ``` + git clone --bare https://example.gitlab.com/my/project.git + ``` + +3. 使用`git filter-repo` ,从存储库的历史记录中清除所有文件. + + 要清除大文件,可以使用`--strip-blobs-bigger-than`选项: + + ``` + git filter-repo --strip-blobs-bigger-than 10M + ``` + + 要清除使用 Git LFS 存储的大文件,可以使用`--blob--callback`选项. 下面的示例使用回调从 Git LFS 指针读取文件大小,并删除大于 10MB 的文件. + + ``` + git filter-repo --blob-callback ' + if blob.data.startswith(b"version https://git-lfs.github.com/spec/v1"): + size_in_bytes = int.from_bytes(blob.data[124:], byteorder="big") + if size_in_bytes > 10*1000: + blob.skip() + ' + ``` + + 要按路径清除特定的大文件,可以组合使用`--path`和`--invert-paths`选项: + + ``` + git filter-repo --path path/to/big/file.m4v --invert-paths + ``` + + 有关更多示例和完整文档,请参见[`git filter-repo`](https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html#EXAMPLES)文档. + +4. 运行`git filter-repo`会删除所有遥控器. 要为您的项目还原遥控器,请运行: + + ``` + git remote add origin https://example.gitlab.com/<namespace>/<project_name>.git + ``` + +5. 强制推送更改以覆盖 GitLab 上的所有分支: + + ``` + git push origin --force --all + ``` + + [受保护的分支](../protected_branches.html)将导致此操作失败. 要继续,您必须删除分支保护,推送,然后重新启用受保护的分支. + +6. 要从标记的发行版中删除大文件,请强制将更改推送到 GitLab 上的所有标记: + + ``` + git push origin --force --tags + ``` + + [受保护的标签](../protected_tags.html)将导致此操作失败. 要继续,您必须删除标签保护,推送,然后重新启用受保护的标签. + +7. 手动执行[项目整理](../../../administration/housekeeping.html#manual-housekeeping) + +**注意:**为提高性能而缓存了项目统计信息. 您可能需要等待 5 到 10 分钟才能看到存储利用率下降. + +## Purge files from GitLab storage[](#purge-files-from-gitlab-storage "Permalink") + +要减少 GitLab 中存储库的大小,必须删除 GitLab 内部引用以包含大文件的提交. 在完成这些步骤之前,请[从存储库历史记录中清除文件](#purge-files-from-repository-history) . + +除了[分支](branches/index.html)和标签(这是一种 Git 引用)之外,GitLab 还会自动创建其他引用. 这些引用可防止在查看合并请求时死链接到提交或丢失差异. [存储库清理](#repository-cleanup)可用于从 GitLab 中删除它们. + +以下内部参考文献不做广告: + +* `refs/merge-requests/*`用于合并请求. +* `refs/pipelines/*` for [pipelines](../../../ci/pipelines/index.html#troubleshooting-fatal-reference-is-not-a-tree). +* `refs/environments/*`用于环境. + +这意味着在获取时通常不包含它们,这使得获取速度更快. 另外, `refs/keep-around/*`是隐藏的 refs,以防止与讨论相关的提交被删除并且根本无法被获取. + +但是,可以从项目导出内的 Git 捆绑包访问这些引用. + +1. 使用受支持的程序包管理器或从源代码[安装`git filter-repo`](https://github.com/newren/git-filter-repo/blob/main/INSTALL.md) . + +2. [从项目中](../settings/import_export.html#exporting-a-project-and-its-data)生成一个新的[导出](../settings/import_export.html#exporting-a-project-and-its-data)并下载. + +3. 使用`tar`解压缩备份: + + ``` + tar xzf project-backup.tar.gz + ``` + + 这将包含一个由[`git bundle`](https://git-scm.com/docs/git-bundle)创建的`project.bundle`文件. + +4. 从包中克隆存储库的新副本: + + ``` + git clone --bare --mirror /path/to/project.bundle + ``` + +5. 使用`git filter-repo` ,从存储库的历史记录中清除所有文件. 因为我们正在尝试删除内部引用,所以我们将依靠每次运行生成的`commit-map`来告诉我们要删除哪些内部引用. + + **注意:** `git filter-repo`每次运行都会创建一个新的`commit-map`文件,并覆盖前一次运行的`commit-map` . **每次**运行都将需要此文件. 每次运行`git filter-repo`都要执行下一步. + + 要清除所有大文件,可以使用`--strip-blobs-bigger-than`选项: + + ``` + git filter-repo --strip-blobs-bigger-than 10M + ``` + + 要按路径清除特定的大文件,可以组合使用`--path`和`--invert-paths`选项. + + ``` + git filter-repo --path path/to/big/file.m4v --invert-paths + ``` + + 有关更多示例和完整文档,请参见[`git filter-repo`](https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html#EXAMPLES)文档. + +6. 运行[存储库清理](#repository-cleanup) . + +## Repository cleanup[](#repository-cleanup "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/19376) . + +仓库清理允许您上传对象的文本文件,并且 GitLab 将删除对这些对象的内部 Git 引用. 您可以使用[`git filter-repo`](https://github.com/newren/git-filter-repo)生成对象列表(在`commit-map`文件中),该对象列表可与存储库清理一起使用. + +要清理存储库: + +1. 转到存储库的项目. +2. 导航 **设置>存储库** . +3. 上载对象列表. 例如,一个`commit-map`文件. +4. Click **开始清理**. + +这将: + +* 删除所有对旧提交的内部 Git 引用. +* 针对存储库运行`git gc` . + +完成后,您将收到一封电子邮件. + +When using repository cleanup, note: + +* 项目统计信息已缓存. 您可能需要等待 5 到 10 分钟才能看到存储利用率下降. +* 客房部修剪 2 周以上的松散物品. 这意味着在最近 2 周内添加的对象将不会立即删除. 如果您有权访问[Gitaly](../../../administration/gitaly/index.html)服务器,则可以运行`git gc --prune=now`立即修剪所有松散的对象. +* 此过程将从 GitLab 的缓存和数据库中删除一些重写提交的副本,但是覆盖范围仍然存在许多空白,并且某些副本可能会无限期地存在. [清除实例缓存](../../../administration/raketasks/maintenance.html#clear-redis-cache)可能有助于删除其中的一些[实例](../../../administration/raketasks/maintenance.html#clear-redis-cache) ,但出于安全考虑,不应依赖它! + +## Storage limits[](#storage-limits "Permalink") + +储存库大小限制: + +* 可以[由管理员](../../admin_area/settings/account_and_limit_settings.html#repository-size-limit-starter-only)在自我管理实例上设置. +* Are [set for GitLab.com](../../gitlab_com/index.html#repository-size-limit). + +当项目达到其大小限制时,您不能: + +* 推送到项目. +* 创建一个新的合并请求. +* 合并现有的合并请求. +* 上载 LFS 对象. + +您仍然可以: + +* 创造新问题. +* 克隆项目. + +如果超出存储库大小限制,则可以尝试: + +1. 删除一些数据. +2. 进行新的提交. +3. 推回存储库. + +也许您还可以: + +* 将一些斑点移到 LFS. +* 从历史记录中删除一些旧的依赖项更新. + +不幸的是,该工作流程无法正常工作. 实际上,在提交中删除文件并不会减小存储库的大小,因为早期的提交和 Blob 仍然存在. + +您需要做的是重写历史记录. 我们建议使用开源社区维护的工具[`git filter-repo`](https://github.com/newren/git-filter-repo) . + +**注意:**在 GitLab 端运行`git gc`之前,"已删除"的提交和 blob 仍将存在. 您还必须能够将重写的历史记录推送到 GitLab,如果您已经超过最大大小限制,则可能无法实现. + +为了解除这些限制,自我管理的 GitLab 实例的管理员必须增加对超出它的特定项目的限制. 因此,最好始终主动保持在限制之下. 如果您达到了极限,并且无法暂时提高极限,则唯一的选择是: + +1. 在本地修剪所有不需要的东西. +2. 在 GitLab 上创建一个新项目,然后开始使用它. + +**Caution:** This process is not suitable for removing sensitive data like password or keys from your repository. Information about commits, including file content, is cached in the database, and will remain visible even after they have been removed from the repository. \ No newline at end of file diff --git a/_book/docs/162.md b/_book/docs/162.md new file mode 100644 index 0000000000000000000000000000000000000000..c905109ea97aacdcf833cbc88d255c1bff4a63bb --- /dev/null +++ b/_book/docs/162.md @@ -0,0 +1,252 @@ +# Signing commits with GPG + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/gpg_signed_commits/](https://docs.gitlab.com/ee/user/project/repository/gpg_signed_commits/) + +* [How GitLab handles GPG](#how-gitlab-handles-gpg) +* [Generating a GPG key](#generating-a-gpg-key) +* [Adding a GPG key to your account](#adding-a-gpg-key-to-your-account) +* [Associating your GPG key with Git](#associating-your-gpg-key-with-git) +* [Signing commits](#signing-commits) +* [Verifying commits](#verifying-commits) +* [Revoking a GPG key](#revoking-a-gpg-key) +* [Removing a GPG key](#removing-a-gpg-key) +* [Rejecting commits that are not signed](#rejecting-commits-that-are-not-signed-premium) +* [GPG signing API](#gpg-signing-api) +* [Further reading](#further-reading) + +# Signing commits with GPG[](#signing-commits-with-gpg "Permalink") + +版本历史 + +* 在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9546) . +* 在 GitLab 10.1 中添加了子项支持. + +您可以使用 GPG 密钥对在 GitLab 存储库中进行的 Git 提交进行签名. 如果可以验证提交者的身份,则已签名的提交将标记为" **已**验证". 为了验证提交者的身份,GitLab 需要他们的公共 GPG 密钥. + +**注意:**术语 GPG 用于所有与 OpenPGP / PGP / GPG 相关的材料和实现. + +目前尚不支持通过 GPG 验证的标签. + +有关 GPG 的更多详细信息,请参见[进一步阅读](#further-reading)部分. + +## How GitLab handles GPG[](#how-gitlab-handles-gpg "Permalink") + +GitLab 使用其自己的密钥环来验证 GPG 签名. 它不访问任何公钥服务器. + +对于要由 GitLab 验证的提交: + +* 提交者必须具有 GPG 公钥/私钥对. +* 提交者的公钥必须已上传到其 GitLab 帐户. +* GPG 密钥中的一封电子邮件必须与提交者在 GitLab 中使用的**经过验证的**电子邮件地址匹配. +* 提交者的电子邮件地址必须与 GPG 密钥中验证的电子邮件地址匹配. + +## Generating a GPG key[](#generating-a-gpg-key "Permalink") + +如果您还没有 GPG 密钥,则以下步骤将帮助您入门: + +1. 为您的操作系统[安装 GPG](https://www.gnupg.org/download/index.html) . 如果您的操作系统具有`gpg2`安装,更换`gpg`与`gpg2`在下面的命令. +2. 使用以下命令生成私钥/公钥对,这将产生一系列问题: + + ``` + gpg --full-gen-key + ``` + + **注意:**在某些情况下,例如 Windows 和其他 macOS 版本上的 Gpg4win,此处的命令可能是`gpg --gen-key` . +3. 第一个问题是可以使用哪种算法. 选择所需的类型或按`Enter 键`选择默认类型(RSA 和 RSA): + + ``` + Please select what kind of key you want: + (1) RSA and RSA (default) + (2) DSA and Elgamal + (3) DSA (sign only) + (4) RSA (sign only) + Your selection? 1 + ``` + +4. 下一个问题是密钥长度. 我们建议您选择`4096` : + + ``` + RSA keys may be between 1024 and 4096 bits long. + What keysize do you want? (2048) 4096 + Requested keysize is 4096 bits + ``` + +5. 指定密钥的有效期. 这是主观的,您可以使用默认值,该值永远不会过期: + + ``` + Please specify how long the key should be valid. + 0 = key does not expire + <n> = key expires in n days + <n>w = key expires in n weeks + <n>m = key expires in n months + <n>y = key expires in n years + Key is valid for? (0) 0 + Key does not expire at all + ``` + +6. 通过输入`y`确认您给出的答案是正确的: + + ``` + Is this correct? (y/N) y + ``` + +7. 输入您的真实姓名,与此键关联的电子邮件地址(应与您在 GitLab 中使用的经过验证的电子邮件地址匹配)和可选注释(按`Enter`跳过): + + ``` + GnuPG needs to construct a user ID to identify your key. + + Real name: Mr. Robot + Email address: <your_email> + Comment: + You selected this USER-ID: + "Mr. Robot <your_email>" + + Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O + ``` + +8. 在询问时选择一个强密码,然后输入两次以确认. +9. 使用以下命令列出您刚刚创建的私密 GPG 密钥: + + ``` + gpg --list-secret-keys --keyid-format LONG <your_email> + ``` + + 将`<your_email>`替换为您在上面输入的电子邮件地址. + +10. 复制以`sec`开头的 GPG 密钥 ID. 在以下示例中,即`30F2B65B9246B6CA` : + + ``` + sec rsa4096/30F2B65B9246B6CA 2017-08-18 [SC] + D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA + uid [ultimate] Mr. Robot <your_email> + ssb rsa4096/B7ABC0813E4028C0 2017-08-18 [E] + ``` + +11. 导出该 ID 的公共密钥(替换上一步中的密钥 ID): + + ``` + gpg --armor --export 30F2B65B9246B6CA + ``` + +12. 最后,复制公钥并将其[添加到您的个人资料设置中](#adding-a-gpg-key-to-your-account) + +## Adding a GPG key to your account[](#adding-a-gpg-key-to-your-account "Permalink") + +**注意:**添加密钥后,就无法对其进行编辑,只能将其删除. 如果粘贴无效,则必须删除有问题的密钥并重新添加. + +您可以在个人资料的设置中添加 GPG 密钥: + +1. 点击右上角的头像,然后转到**"设置"** . + + [![Settings dropdown](img/5e2e81b44d67af322056491cf32bb8da.png)](../../../profile/img/profile_settings_dropdown.png) + +2. 导航至**GPG 密钥**标签,然后将您的*公共*密钥粘贴到"密钥"框中. + + [![Paste GPG public key](img/d04d999de9102632af46c867821c47c3.png)](img/profile_settings_gpg_keys_paste_pub.png) + +3. 最后,单击**添加键**将其添加到 GitLab. 您将能够看到其指纹,相应的电子邮件地址和创建日期. + + [![GPG key single page](img/8a56e678752a9bd9def98422dee92f3e.png)](img/profile_settings_gpg_keys_single_key.png) + +## Associating your GPG key with Git[](#associating-your-gpg-key-with-git "Permalink") + +[创建 GPG 密钥](#generating-a-gpg-key)并将其[添加到您的帐户之后](#adding-a-gpg-key-to-your-account) ,是时候告诉 Git 使用哪个密钥了. + +1. 使用以下命令列出您刚刚创建的私密 GPG 密钥: + + ``` + gpg --list-secret-keys --keyid-format LONG <your_email> + ``` + + 将`<your_email>`替换为您在上面输入的电子邮件地址. + +2. 复制以`sec`开头的 GPG 密钥 ID. 在以下示例中,即`30F2B65B9246B6CA` : + + ``` + sec rsa4096/30F2B65B9246B6CA 2017-08-18 [SC] + D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA + uid [ultimate] Mr. Robot <your_email> + ssb rsa4096/B7ABC0813E4028C0 2017-08-18 [E] + ``` + +3. 告诉 Git 使用该密钥对提交进行签名: + + ``` + git config --global user.signingkey 30F2B65B9246B6CA + ``` + + 用您的 GPG 密钥 ID 替换`30F2B65B9246B6CA` . + +4. (可选)如果 Git 使用`gpg`并且出现诸如`secret key not available`或`gpg: signing failed: secret key not available` ,请运行以下命令更改为`gpg2` : + + ``` + git config --global gpg.program gpg2 + ``` + +## Signing commits[](#signing-commits "Permalink") + +[创建 GPG 密钥](#generating-a-gpg-key)并将其[添加到您的帐户之后](#adding-a-gpg-key-to-your-account) ,您可以开始对提交进行签名: + +1. 像以前一样提交,唯一的区别是添加了`-S`标志: + + ``` + git commit -S -m "My commit msg" + ``` + +2. 询问时输入 GPG 密钥的密码. +3. 推送至 GitLab 并检查您的提交[是否已通过验证](#verifying-commits) . + +如果您不想在每次提交时都键入`-S`标志,则可以告诉 Git 自动签名您的提交: + +``` +git config --global commit.gpgsign true +``` + +## Verifying commits[](#verifying-commits "Permalink") + +1. 在项目或[合并请求中](../../merge_requests/index.html) ,导航到" **提交"**选项卡. 签名的提交将显示包含" Verified"或" Unverified"的徽章,具体取决于 GPG 签名的验证状态. + + [![Signed and unsigned commits](img/7d08a10bdee492162fdb554fb3033f0d.png)](img/project_signed_and_unsigned_commits.png) + +2. 通过单击 GPG 徽章,将显示签名的详细信息. + + [![Signed commit with verified signature](img/544adf1331ba8dc0c6391bf07ba6df8c.png)](img/project_signed_commit_verified_signature.png) + + [![Signed commit with verified signature](img/cc6935399d2235840119ad00eb778fc9.png)](img/project_signed_commit_unverified_signature.png) + +## Revoking a GPG key[](#revoking-a-gpg-key "Permalink") + +撤消密钥将**取消验证**已签名的提交. 使用此密钥验证的提交将变为未验证状态. 撤销此密钥后,将来的提交也将保持不变. 如果您的密钥已被盗用,则应使用此操作. + +撤销 GPG 密钥: + +1. 点击右上角的头像,然后转到**"设置"** . +2. 导航到**GPG 键**标签. +3. 单击您要删除的 GPG 键**旁边的撤消** . + +## Removing a GPG key[](#removing-a-gpg-key "Permalink") + +删除密钥**不会**取消**验证**已签名的提交. 使用此密钥验证的提交将保持验证状态. 删除此密钥后,只有未按下的提交才会保持未验证状态. 要取消验证已签名的提交,您需要从您的帐户中[撤销关联的 GPG 密钥](#revoking-a-gpg-key) . + +要从您的帐户中删除 GPG 密钥,请执行以下操作: + +1. 点击右上角的头像,然后转到**"设置"** . +2. 导航到**GPG 键**标签. +3. 单击您要删除的 GPG 密钥旁边的垃圾桶图标. + +## Rejecting commits that are not signed[](#rejecting-commits-that-are-not-signed-premium "Permalink") + +您可以将您的项目配置为拒绝不是通过[推送规则进行](../../../../push_rules/push_rules.html) GPG 签名的提交. + +## GPG signing API[](#gpg-signing-api "Permalink") + +了解如何[通过 API 通过提交获取 GPG 签名](../../../../api/commits.html#get-gpg-signature-of-a-commit) . + +## Further reading[](#further-reading "Permalink") + +有关 GPG 的更多详细信息,请参见: + +* [Git Tools - Signing Your Work](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work) +* [Managing OpenPGP Keys](https://riseup.net/en/security/message-security/openpgp/gpg-keys) +* [OpenPGP Best Practices](https://riseup.net/en/security/message-security/openpgp/best-practices) +* [Creating a new GPG key with subkeys](https://www.void.gr/kargig/blog/2013/12/02/creating-a-new-gpg-key-with-subkeys/) (advanced) \ No newline at end of file diff --git a/_book/docs/163.md b/_book/docs/163.md new file mode 100644 index 0000000000000000000000000000000000000000..507059f8a9963d89700c33db31cc1f391375bd15 --- /dev/null +++ b/_book/docs/163.md @@ -0,0 +1,35 @@ +# Syntax Highlighting + +> 原文:[https://docs.gitlab.com/ee/user/project/highlighting.html](https://docs.gitlab.com/ee/user/project/highlighting.html) + +# Syntax Highlighting[](#syntax-highlighting "Permalink") + +GitLab 通过[Rouge](https://rubygems.org/gems/rouge) Ruby gem 在所有文件上提供语法高亮显示. 它将尝试根据文件扩展名猜测要使用哪种语言,大多数时间是足够的. + +**注意:** [Web IDE](web_ide/index.html)和[代码片段](../snippets.html)使用[Monaco Editor](https://microsoft.github.io/monaco-editor/)进行文本编辑,而在内部使用[Monarch](https://microsoft.github.io/monaco-editor/monarch.html)库进行语法突出显示. + +如果 GitLab 在猜测错了,你可以覆盖其选择使用语言的`gitlab-language`的属性`.gitattributes` . 例如,如果您在 Prolog 项目中工作并使用`.pl`文件扩展名(通常以 Perl 突出显示),则可以将以下内容添加到`.gitattributes`文件中: + +``` +*.pl gitlab-language=prolog +``` + +当您签入并进行更改时,项目中的所有`*.pl`文件都将突出显示为 Prolog. + +这里的路径只是 Git 内置的[`.gitattributes`接口](https://git-scm.com/docs/gitattributes) . 因此,如果您要在使用 Ruby 语法的项目根目录下发明一种名为`Nicefile`的文件格式,那么您需要做的就是: + +``` +/Nicefile gitlab-language=ruby +``` + +要完全禁用突出显示,请使用`gitlab-language=text` . 可通过 CGI 选项获得更多有趣的恶作剧,例如: + +``` +# json with erb in it /my-cool-file gitlab-language=erb?parent=json + +# an entire file of highlighting errors! /other-file gitlab-language=text?token=Error +``` + +请注意,这些配置仅在`.gitattributes`文件位于默认分支(通常为`master` )中时才生效. + +**注意:** Web IDE 不支持`.gitattribute`文件,但已[计划在将来的发行版中使用](https://gitlab.com/gitlab-org/gitlab/-/issues/22014) . \ No newline at end of file diff --git a/_book/docs/164.md b/_book/docs/164.md new file mode 100644 index 0000000000000000000000000000000000000000..c2df661079aa443146ba76cf8060267dd4bc1fd2 --- /dev/null +++ b/_book/docs/164.md @@ -0,0 +1,127 @@ +# GitLab Web Editor + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/web_editor.html](https://docs.gitlab.com/ee/user/project/repository/web_editor.html) + +* [Create a file](#create-a-file) + * [Template dropdowns](#template-dropdowns) +* [Upload a file](#upload-a-file) +* [Create a directory](#create-a-directory) +* [Create a new branch](#create-a-new-branch) + * [Create a new branch from an issue](#create-a-new-branch-from-an-issue) + * [Create a new branch from a project’s dashboard](#create-a-new-branch-from-a-projects-dashboard) +* [Create a new tag](#create-a-new-tag) +* [Tips](#tips) + +# GitLab Web Editor[](#gitlab-web-editor "Permalink") + +有时,直接从 GitLab 界面进行快速更改要比克隆项目并使用 Gi​​t 命令行工具容易. 在此功能中,我们重点介绍如何从文件浏览器创建新文件,目录,分支或标记. 所有这些操作都可以通过一个下拉菜单获得. + +## Create a file[](#create-a-file "Permalink") + +在项目的文件页面中,单击分支选择器右侧的" +"按钮. 从下拉列表中选择**新文件** . + +[![New file dropdown menu](img/149fa515778bea7ce86903f0c8d9b31f.png)](img/web_editor_new_file_dropdown.png) + +在" **文件名"**框中输入文件名. 然后,在编辑器区域中添加文件内容. 添加描述性提交消息并选择一个分支. 分支字段将默认为您在文件浏览器中查看的分支. 如果输入新的分支名称,将出现一个复选框,允许您在提交更改后启动新的合并请求. + +当您对新文件感到满意时,请单击底部的" **提交更改** ". + +[![Create file editor](img/07e4663db45be7313a205a17ec342edb.png)](img/web_editor_new_file_editor.png) + +### Template dropdowns[](#template-dropdowns "Permalink") + +启动新项目时,新项目可能也需要一些通用文件. 因此,GitLab 将显示一条消息,以简化您的操作. + +[![First file for your project](img/1e0213e85ced3ac9dcc079f0e1831068.png)](img/web_editor_template_dropdown_first_file.png) + +当单击`LICENSE`或`.gitignore`等时,将显示一个下拉列表,为您提供适合您的项目的模板. + +[![MIT license selected](img/097706015c4d2abaaf34d0782cfac635.png)](img/web_editor_template_dropdown_mit_license.png) + +许可证, `.gitlab-ci.yml`日志,贡献指南或`.gitlab-ci.yml`文件也可以通过项目页面上的按钮添加. 在下面的示例中,许可证已经创建,这将创建指向许可证本身的链接. + +[![New file button](img/adc0d64a6c4c1979d43d8bf1d8d485e8.png)](img/web_editor_template_dropdown_buttons.png) + +> **Note:** The **设置 CI / CD** button will not appear on an empty repository. You have to at least add a file in order for the button to show up. + +## Upload a file[](#upload-a-file "Permalink") + +当内容为文本时,创建文件的能力非常出色. 但是,这不适用于二进制数据,例如图像,PDF 或其他文件类型. 在这种情况下,您需要上传文件. + +在项目的文件页面中,单击分支选择器右侧的" +"按钮. 从下拉菜单中选择上**载文件** . + +[![Upload file dropdown menu](img/671787cdf6cd1dde3e748fae72d46779.png)](img/web_editor_upload_file_dropdown.png) + +弹出上传对话框后,有两种方法可以上传文件. 可以在弹出窗口中拖放文件,也可以使用**点击上传**链接. 选择要上传的文件后,将显示文件预览. + +输入提交消息,选择一个分支,并在准备好后单击"上**载文件"** . + +[![Upload file dialog](img/2ed1719eefb651778ccd248f0bbe577c.png)](img/web_editor_upload_file_dialog.png) + +## Create a directory[](#create-a-directory "Permalink") + +为了使档案库中的文件井井有条,创建一个新目录通常会很有帮助. + +在项目的文件页面中,单击分支选择器右侧的加号按钮( `+` ). 从下拉菜单中选择" **新建目录** ". + +[![New directory dropdown](img/c65afb6da67de7dea9950e2b151cca40.png)](img/web_editor_new_directory_dropdown.png) + +在新目录对话框中,输入目录名称,提交消息并选择目标分支. 单击**创建目录**以完成. + +[![New directory dialog](img/0b804819bf30ce8e657ad538d376ecc5.png)](img/web_editor_new_directory_dialog.png) + +## Create a new branch[](#create-a-new-branch "Permalink") + +有多种方法可从 GitLab 的 Web 界面创建分支. + +### Create a new branch from an issue[](#create-a-new-branch-from-an-issue "Permalink") + +在 GitLab 8.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2808) . + +如果您的开发工作流程要求每个合并请求都存在问题,则可以直接从该问题快速创建分支,以加快流程. 新分支及其以后的合并请求将被标记为与此问题相关. 合并后,MR 将自动关闭问题. 您可以在问题说明下方看到" **创建合并请求"**下拉列表. + +**注意:**如果已经有一个具有相同名称的分支或一个引用的合并请求,或者您的项目具有活动的派生关系,则不会看到" **创建合并请求"**按钮. 如果您想显示此按钮,则可能的解决方法是[删除项目的 fork 关系](../settings/index.html#removing-a-fork-relationship) . 删除后,派生关系将无法恢复,您将不再能够将合并请求发送到源. + +[![Create Button](img/ab48b86f7a0dfe92d4358f705bf938a8.png)](img/web_editor_new_branch_from_issue_create_button_v12_6.png) + +该下拉列表包含选项**创建合并请求和分支**以及**创建分支** . + +[![New Branch Button](img/2f78c411d32ee05e95a1984ef90b2356.png)](img/web_editor_new_branch_from_issue_v_12_6.png) + +选择这些选项之一后,将基于项目的默认分支(默认为`master`创建新的分支或分支与合并请求. 分支名称将基于问题的标题,并作为前缀具有其内部 ID. 因此,上面的示例屏幕快照将创建一个名为`2-make-static-site-auto-deploy-and-serve`的分支. + +当您在一个空的存储库项目中单击**创建分支**按钮时,GitLab 会自动创建一个`master`分支, `README.md`提交一个空白的`README.md`文件,并根据问题标题创建并将您重定向到新分支. 如果您的[项目已经配置了](../integrations/overview.html) Kubernetes 等[部署服务](../integrations/overview.html) ,则 GitLab 会更进一步,并通过帮助您创建`.gitlab-ci.yml`文件来提示您设置[自动部署](../../../topics/autodevops/stages.html#auto-deploy) . + +创建分支后,您可以编辑存储库中的文件以解决此问题. 当基于新创建的分支创建合并请求时,描述字段将自动显示[问题关闭模式](../issues/managing_issues.html#closing-issues-automatically) `Closes #ID` ,其中`ID`为问题的 ID. 一旦合并请求被合并,这将解决问题. + +### Create a new branch from a project’s dashboard[](#create-a-new-branch-from-a-projects-dashboard "Permalink") + +如果要在创建新的合并请求之前对多个文件进行更改,则可以预先创建一个新的分支. 在项目的文件页面上,从下拉列表中选择" **新建分支** ". + +[![New branch dropdown](img/83a4859fc1c1d9fc2ea68819a53eaea8.png)](img/web_editor_new_branch_dropdown.png) + +输入新的**分支名称** . (可选)更改" **创建自"**字段以选择该新分支将来自哪个分支,标记或提交 SHA. 如果您开始键入现有的分支或标签,则此字段将自动完成. 单击**创建分支** ,您将返回到该新分支上的文件浏览器. + +[![New branch page](img/dc5fe88e82dc925a618598e1ac284f39.png)](img/web_editor_new_branch_page.png) + +现在,您可以根据需要更改任何文件. 当您准备好将更改合并回母版时,可以使用屏幕顶部的小部件. 在创建分支或修改文件后,此窗口小部件仅显示一段时间. + +[![New push widget](img/2279c6b38c41208a2726d04b0df15c37.png)](img/web_editor_new_push_widget.png) + +## Create a new tag[](#create-a-new-tag "Permalink") + +标签可用于标记主要的里程碑,例如生产版本,候选版本等等. 您可以从分支或提交 SHA 创建标签. 在项目的文件页面上,从下拉列表中选择" **新建标签** ". + +[![New tag dropdown](img/a8ac57717b491533848b3ebca40aae86.png)](img/web_editor_new_tag_dropdown.png) + +给标签起一个名字,例如`v1.0.0` . 选择您要从中创建此新标签的分支或 SHA. 您可以选择添加一条消息和发行说明. 发行说明部分支持 Markdown 格式,您也可以上传附件. 单击**创建标签** ,您将被带到标签列表页面. + +[![New tag page](img/36d97eaa1e64c3f6d5b78d205d1ce881.png)](img/web_editor_new_tag_page.png) + +## Tips[](#tips "Permalink") + +创建或上载新文件或创建新目录时,可以触发新的合并请求,而不是直接提交给 master. 在**目标分支**字段中输入新的分支名称. 您会注意到出现一个复选框,标**有"通过这些更改启动新的合并请求"** . 提交更改后,您将进入新的合并请求表单. + +[![Start a new merge request with these changes](img/f293e9e73b2cf8c4ef278104fbd068d5.png)](img/web_editor_start_new_merge_request.png) + +如果你*不*希望使用您的主电子邮件地址通过 Web 编辑器创建的提交,您可以选择使用其他的链接的电子邮件地址的从**用户设置>编辑个人资料**页面. \ No newline at end of file diff --git a/_book/docs/165.md b/_book/docs/165.md new file mode 100644 index 0000000000000000000000000000000000000000..1e1dd4b3d89aa6d2a431b6a3a564b5bdc9c079c1 --- /dev/null +++ b/_book/docs/165.md @@ -0,0 +1,285 @@ +# Web IDE + +> 原文:[https://docs.gitlab.com/ee/user/project/web_ide/](https://docs.gitlab.com/ee/user/project/web_ide/) + +* [Open the Web IDE](#open-the-web-ide) +* [File finder](#file-finder) +* [Syntax highlighting](#syntax-highlighting) + * [Themes](#themes) +* [Configure the Web IDE](#configure-the-web-ide) +* [Commit changes](#commit-changes) +* [Reviewing changes](#reviewing-changes) +* [View CI job logs](#view-ci-job-logs) +* [Switching merge requests](#switching-merge-requests) +* [Switching branches](#switching-branches) +* [Markdown editing](#markdown-editing) +* [Live Preview](#live-preview) + * [Enabling Live Preview](#enabling-live-preview) +* [Interactive Web Terminals for the Web IDE](#interactive-web-terminals-for-the-web-ide) + * [Runner configuration](#runner-configuration) + * [Web IDE configuration file](#web-ide-configuration-file) + * [Running interactive terminals in the Web IDE](#running-interactive-terminals-in-the-web-ide) + * [File syncing to web terminal](#file-syncing-to-web-terminal) + * [Limitations](#limitations) + * [Troubleshooting](#troubleshooting) + +# Web IDE[](#web-ide "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4539) . +* 在 10.7 版中[移至](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44157) GitLab Core. + +Web IDE 编辑器通过提供具有提交阶段的高级编辑器,可以更快,更轻松地为项目贡献更改. + +## Open the Web IDE[](#open-the-web-ide "Permalink") + +您可以从存储库文件列表和合并请求中查看文件时打开 Web IDE. + +[![Open Web IDE](img/7a0b5b2ee322d8676753d89561c1d3cb.png)](img/open_web_ide.png) + +## File finder[](#file-finder "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18323) in [GitLab Core](https://about.gitlab.com/pricing/) 10.8. + +通过文件查找器,您可以通过搜索快速打开当前分支中的文件. 使用键盘快捷键`Command-p` , `Control-p`或`t` (当编辑器不在焦点时)启动文件查找器. 输入文件名或文件路径片段以开始查看结果. + +## Syntax highlighting[](#syntax-highlighting "Permalink") + +正如 IDE 所期望的那样,Web IDE 中多种语言的语法突出显示将使您的直接编辑更加容易. + +Web IDE 当前提供: + +* 基本语法着色,适用于各种编程,脚本和标记语言,例如 XML,PHP,C#,C ++,Markdown,Java,VB,Batch,Python,Ruby 和 Objective-C. +* 某些语言的 IntelliSense 和验证支持(显示错误和警告,提供智能补全,格式设置和概述). 例如:TypeScript,JavaScript,CSS,LESS,SCSS,JSON 和 HTML. + +因为 Web IDE 基于[Monaco Editor](https://microsoft.github.io/monaco-editor/) ,所以您可以在[Monaco 语言](https://github.com/Microsoft/monaco-languages)存储库中找到更完整的受支持语言列表. 在幕后,摩纳哥使用[Monarch](https://microsoft.github.io/monaco-editor/monarch.html)库来突出显示语法. + +如果您缺少对任何语言的语法突出显示支持,我们准备了一份简短指南,介绍如何[为缺少的语言语法突出显示添加支持.](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/ide/lib/languages/README.md) + +**注意:**单个文件编辑基于[Ace 编辑器](https://ace.c9.io) . + +### Themes[](#themes "Permalink") + +版本历史 + +* 在 13.0 版的 GitLab 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2389) . +* GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/219228)了完全日光化黑暗主题. + +GitLab 支持的语法突出显示的所有主题都添加到了 Web IDE 的代码编辑器中. 您可以从个人[资料首选项中](../../profile/preferences.html)选择一个主题. + +主题仅在 Web IDE 文件编辑器中可用, [深色主题](https://gitlab.com/gitlab-org/gitlab/-/issues/209808)和[日光化深色主题](https://gitlab.com/gitlab-org/gitlab/-/issues/219228)除外,它们适用于整个 Web IDE 屏幕. + +| 日光灯主题 | 日晒黑暗主题 | 黑暗主题 | +| --- | --- | --- | +| [![Solarized Light Theme](img/d79207e6e4f140448c9dd5e6ebe5e380.png)](img/solarized_light_theme_v13_0.png) | [![Solarized Dark Theme](img/c187176d6b8d40e19db360c4c68ffb46.png)](img/solarized_dark_theme_v13_1.png) | [![Dark Theme](img/30152366655be1543f687603c8d34d96.png)](img/dark_theme_v13_0.png) | + +## Configure the Web IDE[](#configure-the-web-ide "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23352) in [GitLab Core](https://about.gitlab.com/pricing/) 13.1. + +Web IDE 支持使用[`.editorconfig`文件](https://editorconfig.org/)配置某些编辑器设置. 打开文件时,Web IDE 将在当前目录和所有父目录中查找名为`.editorconfig`的文件. 如果找到配置文件并且其设置与文件的路径匹配,则将在打开的文件上强制执行这些设置. + +Web IDE 当前支持以下`.editorconfig`设置: + +* `indent_style` +* `indent_size` +* `end_of_line` +* `trim_trailing_whitespace` +* `tab_width` +* `insert_final_newline` + +## Commit changes[](#commit-changes "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4539) . +* 在 10.7 版中[移至](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44157) GitLab Core. +* 从[GitLab 12.7 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/33441) ,将自动暂存文件. +* 从[GitLab 12.9 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/196609) ,删除了对暂存文件的支持,以防止丢失未暂存的数据. 您当前的所有更改都必须提交或放弃. + +进行更改后,单击左下角的" **提交"**按钮以查看已更改文件的列表. + +完成更改后,可以添加提交消息,提交更改并直接创建合并请求. 如果您没有对所选分支的写访问权,则会看到警告,但仍然可以创建新分支并启动合并请求. + +要放弃特定文件中的更改,请在"更改"选项卡中单击该文件上的" **放弃更改"**按钮. 要放弃所有更改,请单击更改侧栏右上角的垃圾桶图标. + +[![Commit changes](img/bad584bc95c83e26be6c67a2b54b26ae.png)](img/commit_changes_v12_9.png) + +## Reviewing changes[](#reviewing-changes "Permalink") + +提交更改之前,可以通过切换到查看模式或从更改列表中选择文件来将它们与上一次提交进行比较. + +当您打开合并请求时,还可以使用其他查看模式,如果您提交更改,该模式将向您显示合并请求 diff 的预览. + +## View CI job logs[](#view-ci-job-logs "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19279) in [GitLab Core](https://about.gitlab.com/pricing/) 11.0. + +您可以使用 Web IDE 通过在 Web IDE 中打开分支或合并请求并打开失败作业的日志来快速修复失败的测试. 通过单击右上角的" **管道"**按钮,可以访问最新管道的所有作业的状态以及当前提交的作业跟踪. + +管道状态也始终显示在左下方的状态栏中. + +## Switching merge requests[](#switching-merge-requests "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19318) in [GitLab Core](https://about.gitlab.com/pricing/) 11.0. + +要在创作的和分配的合并请求之间切换,请单击侧栏顶部的下拉列表以打开合并请求列表. 在切换到其他合并请求之前,您将需要提交或放弃所有更改. + +## Switching branches[](#switching-branches "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20850) in [GitLab Core](https://about.gitlab.com/pricing/) 11.2. + +To switch between branches of the current project repository, click the dropdown in the top of the sidebar to open a list of branches. You will need to commit or discard all your changes before switching to a different branch. + +## Markdown editing[](#markdown-editing "Permalink") + +版本历史 + +* [GitLab Core](https://about.gitlab.com/pricing/) 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18059)了 Markdown 预览. +* 支持在[GitLab Core](https://about.gitlab.com/pricing/) 13.1 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/22822)粘贴图像. + +在 Web IDE 中编辑 Markdown 文件时,可以通过单击文件编辑器上方的" **预览 Markdown"**选项卡来预览更改. Markdown 预览支持[GitLab 风味 Markdown](../../markdown.html#gitlab-flavored-markdown-gfm) . + +您还可以通过将任何本地图像直接粘贴到 Markdown 文件中来上传它们. 该图像将上传到同一目录,默认情况下命名为`image.png` . 如果已经存在相同名称的另一个文件,则将数字后缀自动添加到文件名. + +## Live Preview[](#live-preview "Permalink") + +版本历史 + +* 在[GitLab Core](https://about.gitlab.com/pricing/) 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19764) . +* 在 GitLab 13.0 中从*客户端评估* [重命名](https://gitlab.com/gitlab-org/gitlab/-/issues/213853)为*实时预览* . + +您可以使用 Web IDE 在浏览器中预览 JavaScript 项目. 此功能使用 CodeSandbox 编译和捆绑用于预览 Web 应用程序的 JavaScript. + +[![Web IDE Live Preview](img/7efae901a0febb2a8e969415dced271a.png)](img/live_preview_v13_0.png) + +Additionally, for public projects an **在 CodeSandbox 中打开** button is available to transfer the contents of the project into a public CodeSandbox project to quickly share your project with others. + +### Enabling Live Preview[](#enabling-live-preview "Permalink") + +需要在 GitLab 实例管理员设置中启用实时预览功能. 在 GitLab.com 上为所有项目启用了实时预览 + +[![Admin Live Preview setting](img/fb0d67715160a5a049ca0b8e7d7af698.png)](img/admin_live_preview_v13_0.png) + +完成此操作后,您可以使用`package.json`文件和 Web IDE 内的`main`入口点预览项目. 下面显示了一个示例`package.json` . + +``` +{ "main": "index.js", "dependencies": { "vue": "latest" } } +``` + +## Interactive Web Terminals for the Web IDE[](#interactive-web-terminals-for-the-web-ide "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/5426) . +* 在 13.1 版中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/211685) GitLab Core. + +**警告:** Web IDE 的交互式 Web 终端当前处于**Beta 中** . 共享运行程序[尚不支持交互式 Web 终端](https://gitlab.com/gitlab-org/gitlab/-/issues/24674) ,因此您需要使用自己的私有运行程序来使用此功能. + +[交互式 Web 终端](../../../ci/interactive_web_terminal/index.html)使项目[维护者](../../permissions.html#project-members-permissions)用户可以直接从 GitLab(包括通过 Web IDE)访问终端以与 Runner 进行交互. + +### Runner configuration[](#runner-configuration "Permalink") + +为了使交互式 Web 终端正常工作,需要在运行程序中配置一些内容: + +* 跑步者需要[正确配置`[session_server]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) . 本部分至少需要一个`session_timeout`值(默认为 1800 秒)和一个`listen_address`值. 如果未定义`advertise_address` ,则使用`listen_address` . +* 如果您对 GitLab 实例使用反向代理,则需要[启用](../../../administration/integration/terminal.html#enabling-and-disabling-terminal-support) Web 终端. + +如果您打开终端并且作业已完成其任务,则终端将在[`[session_server].session_timeout`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)配置的持续时间内阻止作业完成,直到关闭终端窗口. + +**注意:**并非所有执行程序都[受支持](https://docs.gitlab.com/runner/executors/) . [文件同步](#file-syncing-to-web-terminal)功能仅在 Kubernetes 运行程序上受支持. + +### Web IDE configuration file[](#web-ide-configuration-file "Permalink") + +为了启用 Web IDE 终端,您需要在存储库根目录内创建文件`.gitlab/.gitlab-webide.yml` . 该文件与[CI 配置文件的](../../../ci/yaml/README.html)语法非常相似,但有一些限制: + +* 无法定义全局块(即: `before_script`或`after_script` ) +* 只能将一个名为`terminal`作业添加到该文件中. +* 仅允许使用关键字`image` , `services` , `tags` , `before_script` , `script`和`variables`来配置作业. +* 要连接到交互式终端, `terminal`作业必须仍然处于活动状态并且正在运行,否则终端将无法连接到作业的会话. 默认情况下, `script`关键字的值是`sleep 60`以防止作业结束并为 Web IDE 提供足够的连接时间. 这意味着,如果您覆盖默认`script`值,则必须添加一个使作业保持运行`sleep`的命令,例如`sleep` . + +在下面的代码中,有此配置文件的示例: + +``` +terminal: + # This can be any image that has the necessary runtime environment for your project. + image: node:10-alpine + before_script: + - apt-get update + script: sleep 60 + variables: + RAILS_ENV: "test" + NODE_ENV: "test" +``` + +终端启动后,将显示控制台,我们可以访问项目存储库文件. + +**重要的** . 终端作业取决于分支. 这意味着用于触发和配置终端的配置文件将是 Web IDE 所选分支中的配置文件. + +如果分支中没有配置文件,将显示错误消息. + +### Running interactive terminals in the Web IDE[](#running-interactive-terminals-in-the-web-ide "Permalink") + +如果交互式终端可供当前用户使用,则" **终端"**按钮将显示在 Web IDE 的右侧栏中. 单击此按钮可以打开或关闭终端选项卡. + +打开后,该选项卡将显示" **启动 Web 终端"**按钮. 如果环境配置不正确,则可能禁用此按钮. 如果是这样,状态消息将描述问题. 以下是可能会禁用" **启动 Web 终端"的**一些原因: + +* `.gitlab/.gitlab-webide.yml`不存在或设置错误. +* 该项目没有活跃的私人跑步者. + +如果处于活动状态,则单击" **启动 Web 终端"**按钮将加载终端视图并开始连接到跑步者的终端. 任何时候都可以关闭并重新打开**终端**选项卡,并且不会影响终端的状态. + +当终端启动并成功连接到跑步者时,跑步者的外壳提示将出现在终端中. 在这里,您可以输入将在跑步者的环境中执行的命令. 这类似于在本地终端或通过 SSH 运行命令. + +在终端运行时,可以通过单击**Stop Terminal**停止它. 这将断开终端并停止跑步者的终端工作. 在此处,单击" **重新启动终端"**以启动新的终端会话. + +### File syncing to web terminal[](#file-syncing-to-web-terminal "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/5276) . +* 在 13.1 版中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/211686) GitLab Core. + +Web IDE 中的文件更改可以同步到正在运行的 Web 终端. 这使用户能够在预配置的终端环境中测试其代码更改. + +**注意:**仅将 Web IDE 中的文件更改同步到终端. 在终端中所做的更改**不会**同步到 Web IDE. 此功能仅适用于 Kubernetes Runners. + +要使文件同步到 Web 终端, `.gitlab/.gitlab-webide.yml`文件需要配置`webide-file-sync`服务. 这是使用此服务的 Node JS 项目的示例配置: + +``` +terminal: + # This can be any image that has the necessary runtime environment for your project. + image: + name: node:10-alpine + services: + - name: registry.gitlab.com/gitlab-org/webide-file-sync:latest + alias: webide-file-sync + entrypoint: ["/bin/sh"] + command: ["-c", "sleep 5 && ./webide-file-sync -project-dir $CI_PROJECT_DIR"] + ports: + # The `webide-file-sync` executable defaults to port 3000. + - number: 3000 +``` + +* 项目目录可用**后** ,必须启动`webide-file-sync`可执行文件. 这就是为什么我们需要在`command`添加`sleep 5`的原因. 有关更多信息,请参[见此问题](https://gitlab.com/gitlab-org/webide-file-sync/-/issues/7) . +* `$CI_PROJECT_DIR`是 GitLab Runners 的[预定义环境变量](../../../ci/variables/predefined_variables.html) . 这是您项目的存储库所在的位置. + +一旦将 Web 终端配置为用于文件同步,则在启动 Web 终端后,状态栏中将显示**终端**状态. + +[![Web IDE Client Side Evaluation](img/37238acd557de0d61f0c3be198c56e00.png)](img/terminal_status.png) + +在以下情况下,通过 Web IDE 对文件所做的更改将同步到正在运行的终端: + +* 编辑文件时,按`Ctrl` + `S` (在 Mac 上为`Cmd` + `S` ). +* 编辑文件后,将单击文件编辑器之外的所有内容. +* 创建,删除或重命名文件或文件夹. + +### Limitations[](#limitations "Permalink") + +交互式终端处于 beta 阶段,并将在以后的发行版中继续进行改进. 同时,请注意,用户一次只能拥有一个活动终端. + +### Troubleshooting[](#troubleshooting "Permalink") + +* 如果终端的文本为灰色且无响应,则表明终端已停止,无法再使用. 停止的终端可以通过单击**Restart Terminal 重新启动** . +* 如果终端显示**Connection Failure** ,则终端无法连接到流道. 请尝试停止并重新启动终端. 如果问题仍然存在,请仔细检查流道配置. \ No newline at end of file diff --git a/_book/docs/166.md b/_book/docs/166.md new file mode 100644 index 0000000000000000000000000000000000000000..ec97ba4bebc1a48cd7ed042d487875a9dfdb18e4 --- /dev/null +++ b/_book/docs/166.md @@ -0,0 +1,160 @@ +# Requirements Management + +> 原文:[https://docs.gitlab.com/ee/user/project/requirements/](https://docs.gitlab.com/ee/user/project/requirements/) + +* [Create a requirement](#create-a-requirement) +* [Edit a requirement](#edit-a-requirement) +* [Archive a requirement](#archive-a-requirement) +* [Reopen a requirement](#reopen-a-requirement) +* [Search for a requirement](#search-for-a-requirement) +* [Allow requirements to be satisfied from a CI job](#allow-requirements-to-be-satisfied-from-a-ci-job) + * [Add the manual job to CI](#add-the-manual-job-to-ci) + * [Specifying individual requirements](#specifying-individual-requirements) + * [Add the manual job to CI conditionally](#add-the-manual-job-to-ci-conditionally) + +# Requirements Management[](#requirements-management-ultimate "Permalink") + +[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2703) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. + +根据要求,您可以设置标准来检查产品. 它们可以基于用户,涉众,系统,软件或您认为重要的其他任何内容. + +需求是 GitLab 中的工件,用于描述产品的特定行为. 需求是长期存在的,除非手动清除,否则它们不会消失. + +如果行业标准*要求*您的应用程序具有某些功能或行为,则可以[创建一个要求](#create-a-requirement)来反映这一点. 如果不再需要某个功能,则可以[归档相关需求](#archive-a-requirement) . + +有关概述,请参见[GitLab 12.10 引入需求管理](https://www.youtube.com/watch?v=uSS7oUNSEoU) . + +[![requirements list view](img/56d89ff1e02ecf30404a57092adae96d.png)](img/requirements_list_v13_1.png) + +## Create a requirement[](#create-a-requirement "Permalink") + +每个项目都有一个分页的需求清单,您可以在其中创建一个新需求. + +创建需求: + +1. 在您的项目页面上,转到 **要求** . +2. Click **新要求**. +3. 输入描述性标题,然后单击**创建需求** . + +您将在列表顶部看到新创建的需求,因为需求列表按创建日期降序排列. + +## Edit a requirement[](#edit-a-requirement "Permalink") + +您可以从需求列表页面编辑需求(如果您具有必要的特权). + +要编辑需求: + +1. 在需求清单中,按一下[ **编辑** ( ). +2. 在文本输入字段中更新标题. +3. Click **保存更改**. + +## Archive a requirement[](#archive-a-requirement "Permalink") + +在" **打开"**选项卡中时,可以存档一个未完成的需求(如果有必要的特权). + +要存档需求,请点击**存档** ( ). + +需求存档后,它不再出现在" **打开"**选项卡中. + +## Reopen a requirement[](#reopen-a-requirement "Permalink") + +您可以在"已**归档"**选项卡中查看已归档需求的列表. + +[![archived requirements list](img/596a395127f6b3d5c9d1deac3f676680.png)](img/requirements_archived_list_view_v13_1.png) + +要重新打开已归档的需求,请点击**重新打开** . + +重新打开需求后,它不再出现在" **归档"**选项卡中. + +## Search for a requirement[](#search-for-a-requirement "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212543) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1. + +您可以根据以下条件从需求列表页面中搜索需求: + +* 要求标题 +* 作者的用户名 + +要搜索需求: + +1. 在一个项目中,转到 **需求>清单** . +2. 单击**搜索或过滤结果**字段. 出现一个下拉菜单. +3. 从下拉列表中选择需求作者或输入纯文本以按需求标题进行搜索. +4. 在键盘上按`Enter`键以过滤列表. + +您还可以通过以下方式对需求列表进行排序: + +* 创建日期 +* 最近更新时间 + +## Allow requirements to be satisfied from a CI job[](#allow-requirements-to-be-satisfied-from-a-ci-job "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2859) . +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2 中[增加](https://gitlab.com/gitlab-org/gitlab/-/issues/215514)了指定个别要求及其状态的功能. + +GitLab 现在支持[需求测试报告](../../../ci/pipelines/job_artifacts.html#artifactsreportsrequirements-ultimate) . 您可以将作业添加到 CI 管道,该作业在触发时会将所有现有需求标记为"满足". + +### Add the manual job to CI[](#add-the-manual-job-to-ci "Permalink") + +要配置您的 CI 以在触发手动作业时将要求标记为"满足",请将以下代码添加到`.gitlab-ci.yml`文件中. + +``` +requirements_confirmation: + when: manual + allow_failure: false + script: + - mkdir tmp + - echo "{\"*\":\"passed\"}" > tmp/requirements.json + artifacts: + reports: + requirements: tmp/requirements.json +``` + +此定义将手动触发的( `when: manual` )作业添加到 CI 管道. 它阻止了( `allow_failure: false` ),但是由您决定触发 CI 作业的条件是什么. 另外,您可以使用任何现有的 CI 作业将所有需求标记为已满足,前提是 CI 作业生成并上传了`requirements.json`工件. + +当您手动触发此作业时,包含`{"*":"passed"}`的`requirements.json`文件将作为工件上传到服务器. 在服务器端,将检查需求报告中的"所有通过"记录( `{"*":"passed"}` ),并在成功后将所有现有的打开需求标记为"满意". + +#### Specifying individual requirements[](#specifying-individual-requirements "Permalink") + +可以指定个别要求及其状态. + +如果存在以下要求: + +* `REQ-1` (具有 IID `1` ) +* `REQ-2` (具有 IID `2` ) +* `REQ-3` (具有 IID `3` ) + +可以指定第一个要求通过,第二个失败. 有效值为"通过"和"失败". 通过省略需求 IID(在这种情况下为`REQ-3`的 IID `3` ),没有发现结果. + +``` +requirements_confirmation: + when: manual + allow_failure: false + script: + - mkdir tmp + - echo "{\"1\":\"passed\", \"2\":\"failed\"}" > tmp/requirements.json + artifacts: + reports: + requirements: tmp/requirements.json +``` + +### Add the manual job to CI conditionally[](#add-the-manual-job-to-ci-conditionally "Permalink") + +要将 CI 配置为仅在有某些开放要求时才包括手动作业,请添加一条规则以检查`CI_HAS_OPEN_REQUIREMENTS` CI 变量. + +``` +requirements_confirmation: + rules: + - if: "$CI_HAS_OPEN_REQUIREMENTS" == "true" + when: manual + - when: never + allow_failure: false + script: + - mkdir tmp + - echo "{\"*\":\"passed\"}" > tmp/requirements.json + artifacts: + reports: + requirements: tmp/requirements.json +``` \ No newline at end of file diff --git a/_book/docs/167.md b/_book/docs/167.md new file mode 100644 index 0000000000000000000000000000000000000000..da809430dfcae16b64b3db73b630a929108ce1b7 --- /dev/null +++ b/_book/docs/167.md @@ -0,0 +1,244 @@ +# Project settings + +> 原文:[https://docs.gitlab.com/ee/user/project/settings/](https://docs.gitlab.com/ee/user/project/settings/) + +* [General settings](#general-settings) + * [General project settings](#general-project-settings) + * [Compliance framework](#compliance-framework-premium) + * [Sharing and permissions](#sharing-and-permissions) + * [Disabling email notifications](#disabling-email-notifications) + * [Merge request settings](#merge-request-settings) + * [Service Desk](#service-desk-starter) + * [Export project](#export-project) + * [Advanced settings](#advanced-settings) + * [Archiving a project](#archiving-a-project) + * [Unarchiving a project](#unarchiving-a-project) + * [Renaming a repository](#renaming-a-repository) + * [Transferring an existing project into another namespace](#transferring-an-existing-project-into-another-namespace) + * [Remove a project](#remove-a-project) + * [Restore a project](#restore-a-project-premium) + * [Removing a fork relationship](#removing-a-fork-relationship) +* [Operations settings](#operations-settings) + * [Error Tracking](#error-tracking) + * [Jaeger tracing](#jaeger-tracing-ultimate) + * [Status Page](#status-page) + +# Project settings[](#project-settings "Permalink") + +**注意:**只有项目维护者和管理员用户[有权](../../permissions.html#project-members-permissions)访问项目设置. + +您可以通过导航到项目的主页并点击**设置**来调整[项目](../index.html)设置. + +## General settings[](#general-settings "Permalink") + +在项目的常规设置下,您可以找到与项目功能有关的所有内容. + +### General project settings[](#general-project-settings "Permalink") + +调整项目的名称,描述,头像, [默认分支](../repository/branches/index.html#default-branch)和主题: + +[![general project settings](img/743ce9a40d40e900e957589a9024f116.png)](img/general_settings.png) + +项目描述还部分支持[标准 Markdown](../../markdown.html#standard-markdown-and-extensions-in-gitlab) . 您可以使用[强调](../../markdown.html#emphasis) , [链接](../../markdown.html#links)和[换行符](../../markdown.html#line-breaks)为项目描述添加更多上下文. + +#### Compliance framework[](#compliance-framework-premium "Permalink") + +您可以选择一个框架标签来标识您的项目具有某些合规性要求或需要其他监督. 可用的标签包括: + +* GDPR-通用数据保护法规 +* HIPAA-健康保险可移植性和责任法案 +* PCI-DSS-支付卡行业数据安全标准 +* SOC 2-服务组织控制 2 +* SOX-萨班斯-奥克斯利 + +### Sharing and permissions[](#sharing-and-permissions "Permalink") + +对于您的存储库,您可以设置功能,例如公共访问,存储库功能,文档,访问权限等等. 要从您的项目中执行此操作,请转到**"设置"** >" **常规"** ,然后展开" **可见性","项目功能","权限"**部分. + +现在,您可以更改[项目可见性](../../../public_access/public_access.html) . 如果将" **项目可见性"**设置为公开,则可以将某些功能的访问权限限制为" **仅项目成员"** . 此外,您可以选择[允许用户请求访问权限](../members/index.html#project-membership-and-requesting-access)的选项. + +**警告:**如果[降低项目的可见性级别](../../../public_access/public_access.html#reducing-visibility) ,则该操作将取消该项目的所有分支的链接. + +使用开关启用或禁用以下功能: + +| Option | 更多访问限制选项 | Description | +| --- | --- | --- | +| **Issues** | ✓ | 激活 GitLab 问题跟踪器 | +| **Repository** | ✓ | Enables [repository](../repository/) functionality | +| **合并请求** | ✓ | 启用[合并请求](../merge_requests/)功能; 另请参阅[合并请求设置](#merge-request-settings) | +| **Forks** | ✓ | Enables [forking](../index.html#fork-a-project) functionality | +| **Pipelines** | ✓ | Enables [CI/CD](../../../ci/README.html) functionality | +| **集装箱登记处** |   | 为您的 Docker 映像激活[注册表](../../packages/container_registry/) | +| **Git 大文件存储** |   | 允许使用[大文件](../../../topics/git/lfs/index.html#git-large-file-storage-lfs) | +| **Packages** |   | Supports configuration of a [package registry](../../../administration/packages/index.html#gitlab-package-registry-administration-premium-only) functionality | +| **Wiki** | ✓ | 启用单独的[文档](../wiki/)系统 | +| **Snippets** | ✓ | Enables [sharing of code and text](../../snippets.html) | +| **Pages** | ✓ | 允许您[发布静态网站](../pages/) | +| **指标仪表板** | ✓ | 控制对[指标仪表板的](../integrations/prometheus.html)访问 | + +一些功能取决于其他功能: + +* 如果禁用" **问题"**选项,则 GitLab 还将删除以下功能: + * **发行板** + * [**服务台**](#service-desk-starter)**注意:**禁用" **问题"**选项后,您仍然可以从合并请求访问**里程碑** . +* 此外,如果您同时禁用**Issues**和**Merge Requests** ,则将无法再访问: + * **标签** + * **大事记** +* 如果禁用**存储库**功能,GitLab 还将为您的项目禁用以下功能: + * **合并请求** + * **流水线** + * **集装箱登记处** + * **Git 大文件存储** + * **配套** +* 指标仪表板访问要求同时阅读项目环境和部署. 有权访问指标仪表板的用户还可以访问环境和部署. + +#### Disabling email notifications[](#disabling-email-notifications "Permalink") + +项目所有者可以通过选中" **禁用电子邮件通知"**复选框来**禁用**与项目相关的所有[电子邮件通知](../../profile/notifications.html#gitlab-notification-emails) . + +### Merge request settings[](#merge-request-settings "Permalink") + +设置项目的合并请求设置: + +* 设置合并请求方法(合并提交, [快速合并](../merge_requests/fast_forward_merge.html) ). +* 添加合并请求[描述模板](../description_templates.html#description-templates) . +* Enable [merge request approvals](../merge_requests/merge_request_approvals.html). +* Enable [merge only if pipeline succeeds](../merge_requests/merge_when_pipeline_succeeds.html). +* Enable [merge only when all threads are resolved](../../discussions/index.html#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved). +* Enable [`delete source branch after merge` option by default](../merge_requests/getting_started.html#deleting-the-source-branch) +* Configure [suggested changes commit messages](../../discussions/index.html#configure-the-commit-message-for-applied-suggestions) + +[![project's merge request settings](img/813cda0881e353d15eed9ca9417104f1.png)](img/merge_requests_settings.png) + +### Service Desk[](#service-desk-starter "Permalink") + +为您的项目启用[Service Desk](../service_desk.html)以提供客户支持. + +### Export project[](#export-project "Permalink") + +了解如何在 GitLab 中[导出项目](import_export.html#importing-the-project) . + +### Advanced settings[](#advanced-settings "Permalink") + +在这里,您可以运行内部管理,存档,重命名,传输, [删除派生关系](#removing-a-fork-relationship)或删除项目. + +#### Archiving a project[](#archiving-a-project "Permalink") + +归档项目后,所有用户都将其设为只读,并表明该项目已不再处于主动维护状态. 也可以取消归档已归档的项目. 只有项目所有者和管理员用户才[有权](../../permissions.html#project-members-permissions)归档项目. + +归档项目后,存储库,问题,合并请求和所有其他功能均为只读. 归档的项目也隐藏在项目列表中. + +归档项目: + +1. 导航到您项目的 **设置>常规** . +2. 在" **高级"下** ,单击" **展开"** . +3. 在" **存档项目"**部分中,单击" **存档项目"**按钮. +4. 根据要求确认操作. + +#### Unarchiving a project[](#unarchiving-a-project "Permalink") + +取消归档项目会删除对项目的只读限制,并使其在项目列表中可用. 只有项目所有者和管理员用户才[有权](../../permissions.html#project-members-permissions)取消归档项目. + +要查找已归档的项目: + +1. 以具有项目所有者或管理员权限的用户身份登录到 GitLab. +2. 如果你: + * 拥有项目的 URL,在浏览器中打开项目的页面. + * 没有项目的 URL:1.单击**项目>浏览项目** . 1.在" **排序项目"**下拉框中,选择" **显示存档的项目"** . 1.在**按名称过滤**字段中,提供项目的名称. 1.单击指向项目的链接以打开其" **详细信息"**页面. + +接下来,要取消归档项目: + +1. 导航到您项目的 **设置>常规** . +2. Under **Advanced**, click **Expand**. +3. 在" **取消存档项目"**部分中,单击" **取消存档项目"**按钮. +4. 根据要求确认操作. + +#### Renaming a repository[](#renaming-a-repository "Permalink") + +**注意:**只有项目维护者和管理员用户才[有权](../../permissions.html#project-members-permissions)重命名存储库. 不要与项目名称混淆,也可以从[常规项目设置中](#general-project-settings)进行更改. + +项目的存储库名称定义其 URL(您用于通过浏览器访问该项目的 URL)及其在安装 GitLab 的文件磁盘上的位置. + +要重命名存储库: + +1. 导航到您项目的 **设置>常规** . +2. 在" **高级"下** ,单击" **展开"** . +3. 在"重命名存储库"下,根据您的喜好更改"路径". +4. Hit **重命名项目**. + +请记住,这可能会带来意想不到的副作用,因为使用旧网址的每个人都无法推送或拉动. 阅读有关[重命名存储库时重定向](../index.html#redirects-when-changing-repository-paths)发生的更多[信息](../index.html#redirects-when-changing-repository-paths) . + +#### Transferring an existing project into another namespace[](#transferring-an-existing-project-into-another-namespace "Permalink") + +**注意:**只有项目所有者和管理员用户才[有权](../../permissions.html#project-members-permissions)传输项目. + +在以下情况下,您可以将现有项目转移到[组中](../../group/index.html) : + +* 您至少对该组具有**维护者** [权限](../../permissions.html#project-members-permissions) . +* 您至少是要转让的项目的**所有者** . +* 将项目转移到的组必须允许创建新项目. + +转移项目: + +1. 导航到您项目的 **设置>常规** . +2. 在" **高级"下** ,单击" **展开"** . +3. 在"传输项目"下,选择要将项目传输到的名称空间. +4. 按照说明键入项目路径,以确认传输. + +完成后,您将被带到新项目的名称空间. 此时,请阅读[从旧项目到新项目](../index.html#redirects-when-changing-repository-paths)的[重定向](../index.html#redirects-when-changing-repository-paths)发生了什么. + +**注意:**如果需要,GitLab 管理员可以使用管理界面将任何项目移动到任何名称空间. + +#### Remove a project[](#remove-a-project "Permalink") + +**注意:**只有项目所有者和管理员才[有权](../../permissions.html#project-members-permissions)删除项目. + +删除项目: + +1. 导航到您的项目,然后选择 **设置>常规>高级** . +2. 在"删除项目"部分中,单击" **删除项目"**按钮. +3. 根据要求确认操作. + +这个动作: + +* 删除包含所有相关资源(问题,合并请求等)的项目. +* 从[Premium 或 Silver](https://about.gitlab.com/pricing/)或更高级别的[GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) ,组管理员可以[将](../../group/index.html#enabling-delayed-project-removal-premium)组内的项目[配置](../../group/index.html#enabling-delayed-project-removal-premium)为在延迟一段时间后删除. 启用后,实际删除将在[实例设置中](../../admin_area/settings/visibility_and_access_controls.html#default-deletion-adjourned-period-premium-only)指定的天数后发生. + +**Warning:** The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6 was changed to [Immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2. + +#### Restore a project[](#restore-a-project-premium "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) . + +要还原标记为删除的项目: + +1. 导航到您的项目,然后选择 **设置>常规>高级** . +2. 在"还原项目"部分中,单击" **还原项目"**按钮. + +#### Removing a fork relationship[](#removing-a-fork-relationship "Permalink") + +分叉是为您不是会员[的项目](../repository/forking_workflow.html)做[贡献](../repository/forking_workflow.html)的好方法. 如果您想自己使用 fork,而无需将[合并请求](../merge_requests.html)发送到上游项目,则可以安全地删除 fork 关系. + +**注意:**删除后,将无法恢复派生关系. 您将不再能够将合并请求发送到源,并且如果有人分叉了您的项目,他们的分支也将失去关系. + +为此: + +1. 导航到项目的**设置>常规>高级** . +2. 在" **删除分叉关系"下** ,单击同样标记的按钮. +3. 按照说明键入项目的路径,以确认操作. + +**注意:**只有项目所有者[有权](../../permissions.html#project-members-permissions)删除派生关系. + +## Operations settings[](#operations-settings "Permalink") + +### Error Tracking[](#error-tracking "Permalink") + +配置错误跟踪以[在 GitLab 中](../operations/error_tracking.html)发现和查看[Sentry 错误](../operations/error_tracking.html) . + +### Jaeger tracing[](#jaeger-tracing-ultimate "Permalink") + +添加 Jaeger 服务器的 URL,以使您的用户可以[从 GitLab 轻松访问 Jaeger UI](../../../operations/tracing.html) . + +### Status Page[](#status-page "Permalink") + +[添加存储凭据](../status_page/#syncing-incidents-to-the-status-page)以启用将公共问题同步到已[部署状态页面的功能](../status_page/#status-page-project) . \ No newline at end of file diff --git a/_book/docs/168.md b/_book/docs/168.md new file mode 100644 index 0000000000000000000000000000000000000000..78ed81069ad163e008d15142e6cccb4eecb58562 --- /dev/null +++ b/_book/docs/168.md @@ -0,0 +1,172 @@ +# Project import/export + +> 原文:[https://docs.gitlab.com/ee/user/project/settings/import_export.html](https://docs.gitlab.com/ee/user/project/settings/import_export.html) + +* [Important notes](#important-notes) +* [Version history](#version-history) + * [13.0+](#130) + * [12.x](#12x) +* [Between CE and EE](#between-ce-and-ee) +* [Exported contents](#exported-contents) +* [Exporting a project and its data](#exporting-a-project-and-its-data) +* [Importing the project](#importing-the-project) + * [Project import status](#project-import-status) + * [Import large projects](#import-large-projects-core-only) +* [Rate limits](#rate-limits) + +# Project import/export[](#project-importexport "Permalink") + +版本历史 + +* 在 GitLab 8.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3050) . +* 从 GitLab 10.0,管理员可以在 GitLab 实例上禁用项目导出选项. + +可以将在任何 GitLab 实例或 GitLab.com 上运行的现有项目及其所有相关数据导出,并移入新的 GitLab 实例. + +如果启用了项目导入选项,则会显示**GitLab 导入/导出**按钮. + +也可以看看: + +* [Project import/export API](../../../api/project_import_export.html) +* [Project import/export administration Rake tasks](../../../administration/raketasks/project_import_export.html) +* [Group import/export](../../group/settings/import_export.html) +* [Group import/export API](../../../api/group_import_export.html) + +设置项目导入/导出: + +1. 导航 **管理区>** **设置>可见性和访问控制** . +2. 滚动到**导入源** +3. 启用所需的**导入源** + +## Important notes[](#important-notes "Permalink") + +请注意以下几点: + +* 不支持从较新版本的 GitLab 导入. 导入的 GitLab 版本必须大于或等于导出的 GitLab 版本. +* 除非导入和导出 GitLab 实例与[版本历史记录中](#version-history)描述的兼容,否则导入将失败. +* 导出存储在一个临时[共享目录中](../../../development/shared_files.html) ,并由特定工作人员每 24 小时删除一次. +* 只要用户对所导出项目所在的组具有维护者或管理员访问权限,组成员就会作为项目成员导出. +* 具有所有者访问权限的项目成员将被导入为维护者. +* 使用管理员帐户导入将通过电子邮件地址映射用户(仅限自我管理). 否则,将留下补充评论,以提及原始作者和 MR,注释或问题将归进口商所有. +* 如果导入的项目包含源自派生的合并请求,则将在导入/导出期间在项目内创建与此类合并请求关联的新分支. 因此,导出项目中的分支数量可能会大于原始项目中的分支数量. + +## Version history[](#version-history "Permalink") + +### 13.0+[](#130 "Permalink") + +从 GitLab 13.0 开始,GitLab 可以导入从其他 GitLab 部署导出的捆绑软件. 此功能仅限于之前的两个 GitLab [次要](../../../policy/maintenance.html#versioning)发行版,这与我们的[安全发布](../../../policy/maintenance.html#security-releases)流程类似. + +例如: + +| 当前版本 | 可以导入从 | +| --- | --- | +| 13.0 | 13.0, 12.10, 12.9 | +| 13.1 | 13.1, 13.0, 12.10 | + +### 12.x[](#12x "Permalink") + +在 13.0 之前,这是一个已定义的兼容性表: + +| 导出 GitLab 版本 | 导入 GitLab 版本 | +| --- | --- | +| 11.7 至 12.10 | 11.7 至 12.10 | +| 11.1 至 11.6 | 11.1 至 11.6 | +| 10.8 至 11.0 | 10.8 至 11.0 | +| 10.4 至 10.7 | 10.4 至 10.7 | +| 10.3 | 10.3 | +| 10.0 至 10.2 | 10.0 至 10.2 | +| 9.4 至 9.6 | 9.4 至 9.6 | +| 9.2 至 9.3 | 9.2 至 9.3 | +| 8.17 至 9.1 | 8.17 至 9.1 | +| 8.13 至 8.16 | 8.13 至 8.16 | +| 8.12 | 8.12 | +| 8.10.3 至 8.11 | 8.10.3 至 8.11 | +| 8.10.0 至 8.10.2 | 8.10.0 至 8.10.2 | +| 8.9.5 至 8.9.11 | 8.9.5 至 8.9.11 | +| 8.9.0 至 8.9.4 | 8.9.0 至 8.9.4 | + +只能在具有匹配导入/导出版本的 GitLab 版本之间导出和导入项目. + +例如,8.10.3 和 8.11 具有相同的导入/导出版本(0.1.3),它们之间的导出将兼容. + +## Between CE and EE[](#between-ce-and-ee "Permalink") + +您可以将项目从[Community Edition](https://about.gitlab.com/install/ce-or-ee/)导出[到 Enterprise Edition](https://about.gitlab.com/install/ce-or-ee/) ,反之亦然. 假定满足[版本历史记录](#version-history)要求. + +如果要将项目从企业版导出到社区版,则可能会丢失仅保留在企业版中的数据. 有关更多信息,请参阅[从 EE 降级为 CE](../../../README.html) . + +## Exported contents[](#exported-contents "Permalink") + +将导出以下项目: + +* 项目和 Wiki 存储库 +* 项目上传 +* 项目配置,不包括集成 +* 注释问题,带有差异和注释的合并请求,标签,里程碑,摘要,时间跟踪和其他项目实体 +* 设计管理文件和数据 +* LFS 对象 +* 发行板 +* 管道历史 + +以下项目将不会导出: + +* 建立痕迹和工件 +* 容器注册表映像 +* 可变配置项 +* Webhooks +* 任何加密令牌 +* 合并请求批准者 +* 推送规则 +* Awards + +**注意:**有关项目导出中[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/import_export/project/import_export.yml)的特定数据的更多详细信息,请参阅[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/import_export/project/import_export.yml)文件. + +## Exporting a project and its data[](#exporting-a-project-and-its-data "Permalink") + +1. 转到项目的主页. + +2. 请点击 侧栏中的**设置** . + +3. 向下滚动以找到" **导出项目"**按钮: + + [![Export button](img/5f6c85f0240f3ec56519dde74a715dba.png)](img/import_export_export_button.png) + +4. 生成导出后,您应该会收到一封电子邮件,其中包含用于下载文件的链接: + + [![Email download link](img/3e903eab58c2b1ac777ef30adf3bd44e.png)](img/import_export_mail_link.png) + +5. 或者,您可以返回项目设置并从那里下载文件,或生成新的导出. 文件可用后,页面应显示" **下载导出"**按钮: + + [![Download export](img/0b5158f524983df0ee4e4aa152abcc86.png)](img/import_export_download_export.png) + +## Importing the project[](#importing-the-project "Permalink") + +1. 在创建新项目时,GitLab 项目导入功能是第一个导入选项. 点击**GitLab 导出** : + + [![New project](img/abdf7941c6dc575d115b24d74a80a68b.png)](img/import_export_new_project.png) + +2. 输入您的项目名称和 URL. 然后选择您之前导出的文件: + + [![Select file](img/7356a350b6fac674fc341d110380f723.png)](img/import_export_select_file.png) + +3. 单击**导入项目**开始导入. 您新导入的项目页面将很快出现. + +**注意:**如果" `Internal`可见性级别[的使用受到限制](../../../public_access/public_access.html#restricting-the-use-of-public-or-internal-projects) ,则所有导入的项目都将获得" `Private`的可见性.**注意:**可以由管理员设置最大导入文件大小,默认为 50MB. 作为管理员,您可以修改最大导入文件大小. 为此,请在" [应用程序设置" API](../../../api/settings.html#change-application-settings)或" [管理界面"中](../../admin_area/settings/account_and_limit_settings.html)使用`max_import_size`选项. + +### Project import status[](#project-import-status "Permalink") + +您可以通过[Project import / export API](../../../api/project_import_export.html#import-status)查询导入. 如 API 文档中所述,查询可能返回导入错误或异常. + +### Import large projects[](#import-large-projects-core-only "Permalink") + +如果您的项目较大,请考虑使用 Rake 任务,如[开发人员文档中所述](../../../development/import_project.html#importing-via-a-rake-task) . + +## Rate limits[](#rate-limits "Permalink") + +为了避免滥用,用户的速率仅限于: + +| 请求类型 | Limit | +| --- | --- | +| Export | 每 5 分钟 30 个项目 | +| 下载导出 | 每 10 分钟有 10 个下载项目 | +| Import | 每 5 分钟 30 个项目 | \ No newline at end of file diff --git a/_book/docs/169.md b/_book/docs/169.md new file mode 100644 index 0000000000000000000000000000000000000000..b6eaea447512686c4c2b0f4791ee5cb7f073fa15 --- /dev/null +++ b/_book/docs/169.md @@ -0,0 +1,77 @@ +# Project access tokens (Alpha) + +> 原文:[https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html) + +* [Creating a project access token](#creating-a-project-access-token) +* [Project bot users](#project-bot-users) +* [Revoking a project access token](#revoking-a-project-access-token) +* [Limiting scopes of a project access token](#limiting-scopes-of-a-project-access-token) + * [Enable or disable project access tokens](#enable-or-disable-project-access-tokens) + +# Project access tokens (Alpha)[](#project-access-tokens-alpha-core-only "Permalink") + +**警告:**这是[Alpha](https://about.gitlab.com/handbook/product/#alpha)功能,随时可能更改,恕不另行通知.版本历史 + +* 在 GitLab 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2587) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上已禁用. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-project-access-tokens) . + +项目访问令牌的范围仅限于项目,可用于通过[GitLab API](../../../api/README.html#personalproject-access-tokens)进行身份验证. + +您还可以将项目访问令牌与 Git 一起使用,以通过 HTTP 或 SSH 进行身份验证. + +项目访问令牌在您定义的日期 UTC 午夜到期. + +有关如何使用项目访问令牌对 API 进行身份验证的示例,请参见[API 文档中](../../../api/README.html#personalproject-access-tokens)的以下部分. + +## Creating a project access token[](#creating-a-project-access-token "Permalink") + +1. 登录到 GitLab. +2. 导航至您要为其创建访问令牌的项目. +3. 在里面 **在设置**菜单中,选择**访问令牌** . +4. 选择令牌的名称和可选的到期日期. +5. 选择[所需的范围](#limiting-scopes-of-a-project-access-token) . +6. 单击**创建项目访问令牌**按钮. +7. 将项目访问令牌保存在安全的地方. 离开或刷新页面后,将无法再次访问它. + +## Project bot users[](#project-bot-users "Permalink") + +对于创建的每个项目访问令牌,还将创建一个机器人用户,并将其添加到具有["维护者"级别权限](../../permissions.html#project-members-permissions)的项目中. 使用项目访问令牌进行的 API 调用将与相应的 bot 用户相关联. + +这些用户将出现在" **成员"中,**但不能被修改. 此外,该漫游器用户无法添加到任何其他项目. + +[吊销](#revoking-a-project-access-token)项目访问令牌后,该漫游器用户将被删除,所有记录都将被移动到用户名" Ghost User"的系统范围内的用户. 有关更多信息,请参见[关联记录](../../profile/account/delete_account.html#associated-records) . + +## Revoking a project access token[](#revoking-a-project-access-token "Permalink") + +您可以随时通过单击相应的" **撤消"**按钮来撤消任何项目访问令牌. **设置>访问令牌** . + +## Limiting scopes of a project access token[](#limiting-scopes-of-a-project-access-token "Permalink") + +可以使用一个或多个范围创建项目访问令牌,这些范围允许给定令牌可以执行各种操作. 下表描述了可用范围. + +| Scope | Description | +| --- | --- | +| `api` | 授予对范围内的项目 API 的完全读取/写入访问权限. | +| `read_api` | 授予对范围内的项目 API 的读取权限. | +| `read_registry` | 如果项目是私有的并且需要授权,则允许对[容器注册表](../../packages/container_registry/index.html)图像的读取(拉). | +| `write_registry` | 允许对[容器注册表](../../packages/container_registry/index.html)进行写访问(推送). | +| `read_repository` | 允许对存储库进行只读访问(拉). | +| `write_repository` | 允许对存储库进行读写访问(拉,推). | + +### Enable or disable project access tokens[](#enable-or-disable-project-access-tokens "Permalink") + +项目访问令牌是[Alpha](https://about.gitlab.com/handbook/product/#alpha)功能,不建议用于生产环境. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以为您的实例启用它. + +To enable it: + +``` +Feature.enable(:resource_access_token) +``` + +禁用它: + +``` +Feature.disable(:resource_access_token) +``` \ No newline at end of file diff --git a/_book/docs/170.md b/_book/docs/170.md new file mode 100644 index 0000000000000000000000000000000000000000..1c26d2eeced0a4062a2d625612a63702b936ec39 --- /dev/null +++ b/_book/docs/170.md @@ -0,0 +1,58 @@ +# Share Projects with other Groups + +> 原文:[https://docs.gitlab.com/ee/user/project/members/share_project_with_groups.html](https://docs.gitlab.com/ee/user/project/members/share_project_with_groups.html) + +* [Groups as collections of users](#groups-as-collections-of-users) +* [Sharing a project with a group of users](#sharing-a-project-with-a-group-of-users) +* [Maximum access level](#maximum-access-level) +* [Sharing public project with private group](#sharing-public-project-with-private-group) +* [Share project with group lock](#share-project-with-group-lock) + +# Share Projects with other Groups[](#share-projects-with-other-groups "Permalink") + +您可以与其他[小组](../../group/index.html)共享项目. 这样就可以通过一个操作将一组用户添加到项目中. + +## Groups as collections of users[](#groups-as-collections-of-users "Permalink") + +组主要用于[创建项目集合](../../group/index.html) ,但是您还可以利用以下事实:组定义了*用户*集合,即组成员. + +## Sharing a project with a group of users[](#sharing-a-project-with-a-group-of-users "Permalink") + +在 GitLab 中授予一组用户(例如"工程")访问项目(例如" Acme 项目")的主要机制是使"工程"组成为" Project Acme"的所有者. 但是,如果" Acme 项目"已经属于另一个小组,比如"开源",该怎么办? 这是可以使用组共享功能的地方. + +与"工程"组共享" Acme 项目": + +1. 对于" Acme 项目",请使用左侧导航菜单转到" **会员"** + + [![share project with groups](img/0d1c10a8d14f11dd831b96878fc521e5.png)](img/share_project_with_groups.png) + +2. 选择"与组共享"标签 +3. 添加具有您选择的最大访问权限级别的"工程"组 +4. 点击**共享**分享 + + [![share project with groups tab](img/0e2287fb4b32bf9dff45f3255ddd45fe.png)](img/share_project_with_groups_tab.png) + +5. 与"工程"共享"项目 Acme"后,该项目将列在组仪表板上 + + [!['Project Acme' is listed as a shared project for 'Engineering'](img/000b14e609fee563642c55e238caca88.png)](img/other_group_sees_shared_project.png) + +请注意,您只能与以下项目共享一个项目: + +* 您具有明确定义的成员资格的组 +* 包含嵌套子组或项目的组,您对其具有明确定义的角色 + +管理员可以与系统中的任何组共享项目. + +## Maximum access level[](#maximum-access-level "Permalink") + +在上面的示例中,"工程"成员的最大"开发人员"访问级别意味着"工程"中具有较高访问级别的用户("维护者"或"所有者")将仅对" Acme 项目"具有"开发者"访问权限'. + +## Sharing public project with private group[](#sharing-public-project-with-private-group "Permalink") + +与私有组共享公共项目时,项目的所有者和维护者将在`members`页面上看到该组的名称. 所有者还可以在问题或合并请求中提及他们时,可以看到他们无权访问的私人群组的成员. + +## Share project with group lock[](#share-project-with-group-lock "Permalink") + +可以防止一个组中[的项目与另一个组共享一个项目](../members/share_project_with_groups.html) . 这样可以更严格地控​​制项目访问. + +了解更多有关[使用组锁共享的信息](../../group/index.html#share-with-group-lock) . \ No newline at end of file diff --git a/_book/docs/171.md b/_book/docs/171.md new file mode 100644 index 0000000000000000000000000000000000000000..5007724d99dac20bc2750279eb4190cba2628abd --- /dev/null +++ b/_book/docs/171.md @@ -0,0 +1,133 @@ +# Snippets + +> 原文:[https://docs.gitlab.com/ee/user/snippets.html](https://docs.gitlab.com/ee/user/snippets.html) + +* [Personal snippets](#personal-snippets) +* [Project snippets](#project-snippets) +* [Create a snippet](#create-a-snippet) +* [Versioned Snippets](#versioned-snippets) + * [File names](#file-names) + * [Cloning snippets](#cloning-snippets) + * [Limitations](#limitations) +* [Discover snippets](#discover-snippets) +* [Snippet comments](#snippet-comments) +* [Downloading snippets](#downloading-snippets) +* [Embedded snippets](#embedded-snippets) + +# Snippets[](#snippets "Permalink") + +借助 GitLab 代码片段,您可以存储和与其他用户共享代码和文本. + +[![GitLab Snippet](img/677d8f883392679f3fba97024a259665.png)](img/gitlab_snippet_v13_0.png) + +可以使用[摘要 API](../api/snippets.html)来维护[摘要](../api/snippets.html) . + +片段类型有两种: + +* 个人摘要. +* 项目摘要. + +## Personal snippets[](#personal-snippets "Permalink") + +个人代码段与任何项目均无关,可以完全独立地创建. 可以设置 3 种可见性级别,公共,内部和私有. 有关更多信息,请参见[公共访问](../public_access/public_access.html) . + +## Project snippets[](#project-snippets "Permalink") + +项目摘要始终与特定项目相关. 有关更多信息,请参见[项目功能](project/index.html#project-features) . + +## Create a snippet[](#create-a-snippet "Permalink") + +要创建个人代码段,请点击加号图标( ),然后从下拉菜单中选择" **新建代码段** ": + +[![New personal snippet from non-project pages](img/169af1eb67d287048e2bd4de1d3a178a.png)](img/new_personal_snippet_v12_10.png) + +如果您在项目页面上,但要创建一个新的个人代码段,请点击加号图标( ),然后从下拉菜单的下部选择**新代码段** (在 GitLab.com 上为**GitLab** ;在自托管实例上为**您的**实例): + +[![New personal snippet from project pages](img/ee04e8247fff074d8b122d6b5ec848f4.png)](img/new_personal_snippet_from_project_v12_10.png) + +要创建项目摘要,请导航到您的项目页面,然后点击加号图标( ),然后从下拉菜单的上方选择**新建代码段** ( **此项目** ). + +[![New personal snippet from project pages](img/ea0e34b1e4e7a7a6379bc52995143bf9.png)](img/new_project_snippet_from_project_v12_10.png) + +从那里添加**Title** , **Description**和带有适当扩展名的**文件**名(例如`example.rb` , `index.html` ). + +**警告:**确保添加文件名以突出显示代码并避免此[粘贴错误](https://gitlab.com/gitlab-org/gitlab/-/issues/22870) . + +## Versioned Snippets[](#versioned-snippets "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/239) . + +从 13.0 开始,片段(个人片段和项目片段)默认都启用了版本控制. + +这意味着在创建代码段时,所有代码段都将获得自己的基础存储库,并使用`master`分支进行初始化. 每当保存对代码段的更改时,都会记录对 master 分支的新提交. 提交消息是自动生成的. 该代码段的存储库默认情况下只有一个分支(母版),不支持将其删除或创建其他分支. + +现有代码段将在 13.0 中自动迁移. 它们的当前内容将被保存为对代码段存储库的初始提交. + +### File names[](#file-names "Permalink") + +代码段支持基于为其提供的文件名和扩展名突出显示语法. 尽管可以在不指定文件名和扩展名的情况下提交代码段,但它需要一个有效的名称,以便可以将内容作为文件创建在代码段的存储库中. + +如果用户未将文件名和扩展名归于代码段,则 GitLab 会自动以`snippetfile<x>.txt`格式添加文件名,其中`<x>`代表添加到文件的数字,从 1 开始.添加了更多没有属性文件名的代码段. + +从早期版本的 GitLab 升级到 13.0 时,不支持文件名的现有代码片段将重命名为兼容格式. 例如,如果代码段的文件名是`http://a-weird-filename.me` ,它将被更改为`http-a-weird-filename-me` ,以包含在代码段的存储库中. 由于代码段是通过 ID 存储的,因此更改其文件名不会破坏该代码段的直接链接或嵌入式链接. + +### Cloning snippets[](#cloning-snippets "Permalink") + +可以使用 SSH 或 HTTPS 将片段克隆为常规的 Git 存储库. 单击摘要内容上方的" **复制"**按钮以复制您选择的 URL. + +[![Clone Snippet](img/ed5a96971ab453e6d33b3ad9079bd47c.png)](img/snippet_clone_button_v13_0.png) + +这使您可以获取代码段存储库的本地副本,并根据需要进行更改. 您可以提交这些更改并将其推送到远程 master 分支. + +### Limitations[](#limitations "Permalink") + +* 不支持二进制文件. +* 不支持创建或删除分支. 只有默认的*主人* . 使用分支. +* 代码段存储库中不支持 Git 标签. +* 片段的存储库仅限于一个文件. 尝试推送多个文件将导致错误. +* 修订在 GitLab UI 上对用户*尚不*可见,但计划在以后的迭代中添加. 有关更新,请参见[修订标签问题](https://gitlab.com/gitlab-org/gitlab/-/issues/39271) . +* 默认情况下, [摘要](../administration/snippets/index.html#snippets-content-size-limit)的[最大大小为](../administration/snippets/index.html#snippets-content-size-limit) 50 MB. + +## Discover snippets[](#discover-snippets "Permalink") + +在 GitLab 中发现片段的主要方法有两种. + +要浏览对您可见的所有代码片段,您可以通过顶部导航转到 GitLab 实例的代码片段仪表板. 对于 GitLab.com,您可以在[这里](https://gitlab.com/dashboard/snippets)找到它. 这会将您导航到一个概述,该概述显示您创建的摘要,并允许您浏览所有摘要. + +如果要发现属于特定项目的摘录,则可以通过项目页面上的左侧导航导航到摘录页面. 项目片段被启用,默认情况下可用,但他们可以通过导航到项目的**设置** ,扩大**知名度,项目功能,权限**和向下滚动到**片段**被禁用. 从那里,您可以切换以禁用它们,或从下拉菜单中选择其他可见性级别. + +## Snippet comments[](#snippet-comments "Permalink") + +在 GitLab 9.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/12910) . + +使用 GitLab 代码片段,您可以参与有关该代码段的对话,从而促进用户之间的协作. + +## Downloading snippets[](#downloading-snippets "Permalink") + +您可以下载代码段的原始内容. + +默认情况下,将下载带有 Linux 样式的行尾( `LF` )的代码段. 如果要保留原始的行尾,则需要添加参数`line_ending=raw` (例如, `https://gitlab.com/snippets/SNIPPET_ID/raw?line_ending=raw` : `line_ending=raw` ). 如果使用 GitLab Web 界面创建了代码段,则原始行结尾类似于 Windows( `CRLF` ). + +## Embedded snippets[](#embedded-snippets "Permalink") + +在 GitLab 10.8 中引入. + +公开片段不仅可以共享,还可以嵌入任何网站中. 这样,您可以在多个地方重用 GitLab 代码段,并且对源代码的任何更改都会自动反映在嵌入式代码段中. + +To embed a snippet, first make sure that: + +* 该项目是公开的(如果是项目摘要) +* 摘要是公开的 +* 在" **项目">"设置">"权限"中** ,将片段权限设置为" **具有访问**权限的**所有人"** + +满足以上条件后,"嵌入"部分将出现在您的代码片段中,您只需单击"复制"按钮即可. 这将复制一个单行脚本,您可以将其添加到任何网站或博客文章中. + +示例代码如下所示: + +``` +<script src="https://gitlab.com/namespace/project/snippets/SNIPPET_ID.js"></script> +``` + +嵌入式代码段的外观如下: + +嵌入的代码片段带有一个标题,该标题显示文件名(如果已定义),代码片段大小,到 GitLab 的链接以及实际的代码片段内容. 标头中的操作使用户可以查看原始格式的代码段并下载. \ No newline at end of file diff --git a/_book/docs/172.md b/_book/docs/172.md new file mode 100644 index 0000000000000000000000000000000000000000..d32e3f0480fe33df72cf499b06630c224def1656 --- /dev/null +++ b/_book/docs/172.md @@ -0,0 +1,83 @@ +# Static Site Editor + +> 原文:[https://docs.gitlab.com/ee/user/project/static_site_editor/](https://docs.gitlab.com/ee/user/project/static_site_editor/) + +* [Use cases](#use-cases) +* [Requirements](#requirements) +* [How it works](#how-it-works) +* [Getting started](#getting-started) + * [Set up your project](#set-up-your-project) + * [Use the Static Site Editor to edit your content](#use-the-static-site-editor-to-edit-your-content) +* [Limitations](#limitations) + +# Static Site Editor[](#static-site-editor "Permalink") + +版本历史 + +* 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28758) . +* 在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214559)了所见即所得的编辑器. +* 支持通过 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/216640)的 WYSIWYG 编辑器添加图像. +* Markdown 前端问题隐藏在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/216834)的 WYSIWYG 编辑器中. +* 支持 GitLab 13.2 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/223171) `*.md.erb`文件. + +**危险:**在 GitLab 13.0 中,我们对静态站点编辑器的 URL 结构进行了[重大更改](https://gitlab.com/gitlab-org/gitlab/-/issues/213282) . 请按照此[代码段中](https://gitlab.com/gitlab-org/project-templates/static-site-editor-middleman/snippets/1976539)的说明使用最新更改来更新您的项目. + +静态站点编辑器使用户可以在静态网站上编辑内容,而无需事先了解基础模板语言,站点体系结构或 Git 命令. 您的项目的贡献者可以快速编辑 Markdown 页面,并将更改提交审核. + +## Use cases[](#use-cases "Permalink") + +静态站点编辑器允许协作者无缝地将更改提交到静态站点文件. 例如: + +* 非技术合作者可以直接从浏览器中轻松编辑页面; 他们不需要知道 Git 和您的项目的详细信息就能做出贡献. +* 最近雇用的团队成员可以快速编辑内容. +* 临时协作者可以从一个项目跳到另一个项目并快速编辑页面,而不必克隆或派生需要提交更改的每个项目. + +## Requirements[](#requirements "Permalink") + +* 为了使用静态站点编辑器功能,您的项目需要使用[静态站点编辑器 Middleman 模板](https://gitlab.com/gitlab-org/project-templates/static-site-editor-middleman)进行预配置. +* 该编辑器需要登录到 GitLab,并且必须是该项目的成员(具有 Developer 或更高权限级别). + +## How it works[](#how-it-works "Permalink") + +静态网站编辑器尚处于开发的早期阶段,目前仅适用于 Middleman 网站. 您必须使用特定的站点模板才能开始使用它. 项目模板配置为使用[GitLab Pages](../pages/index.html)部署[Middleman](https://middlemanapp.com/)静态网站. + +网站启动并运行后,您将在其页面的左下角看到一个" **编辑此页面"**按钮: + +[![Edit this page button](img/865915f0e39a0035ffc91de736f5a047.png)](img/edit_this_page_button_v12_10.png) + +单击它后,GitLab 将打开一个编辑器窗口,从中可以直接编辑内容. 准备就绪后,只需单击一下按钮即可提交更改: + +[![Static Site Editor](img/a7a0c433c6f01281a584ba08db57d159.png)](img/wysiwyg_editor_v13_0.png) + +当编辑者在后台提交更改时,GitLab 会自动创建一个新分支,提交更改并打开合并请求. 编辑者将直接进入合并请求,然后可以将其分配给同事进行审查. + +## Getting started[](#getting-started "Permalink") + +首先,设置项目. 完成后,您可以使用静态站点编辑器轻松地编辑您的内容. + +### Set up your project[](#set-up-your-project "Permalink") + +1. 首先,从" [静态站点编辑器-中间人"](https://gitlab.com/gitlab-org/project-templates/static-site-editor-middleman)模板创建一个新项目. 您可以将其[派生](../repository/forking_workflow.html#creating-a-fork)或[从模板创建一个新项目](../../../gitlab-basics/create-project.html#built-in-templates) . +2. 编辑`data/config.yml`文件,添加项目的路径. +3. 编辑文件将触发 CI / CD 管道,以使用 GitLab Pages 部署项目. +4. 管道完成后,从项目的左侧菜单转到**"设置">"页面"**以找到新网站的 URL. +5. 访问您的网站并查看屏幕的左下角,以查看新的" **编辑此页面"**按钮. + +满足[要求的](#requirements)任何人都可以编辑页面内容,而无需事先了解 Git 或您网站的代码库. + +**注意:**从 GitLab 13.1 开始,Markdown 文件的 YAML 前端问题被隐藏在 WYSIWYG 编辑器中,以避免意外更改. 要对其进行编辑,请使用 Markdown 编辑模式,常规的 GitLab 文件编辑器或 Web IDE. + +### Use the Static Site Editor to edit your content[](#use-the-static-site-editor-to-edit-your-content "Permalink") + +例如,假设您是一家大型公司的新近聘用的技术作家,并且该公司的产品已添加了新功能. + +1. 您被分配了更新文档的任务. +2. 您访问页面并看到需要编辑的内容. +3. 单击生产站点上的" **编辑此页面"**按钮. +4. 该文件在"静态站点编辑器"中以" **所见即所得"**模式打开. 如果您想编辑原始 Markdown,则可以在右下角切换**Markdown**模式. +5. 您在此处编辑文件,然后单击" **提交更改"** . +6. 将自动创建一个新的合并请求,然后将其分配给您的同事进行审核. + +## Limitations[](#limitations "Permalink") + +* 静态站点编辑器仍然不能快速添加到现有的 Middleman 站点. 跟随此[史诗](https://gitlab.com/groups/gitlab-org/-/epics/2784)进行更新. \ No newline at end of file diff --git a/_book/docs/173.md b/_book/docs/173.md new file mode 100644 index 0000000000000000000000000000000000000000..fce31d527ba632fee3263058a5e2c57f0fe9c5e0 --- /dev/null +++ b/_book/docs/173.md @@ -0,0 +1,202 @@ +# Wiki + +> 原文:[https://docs.gitlab.com/ee/user/project/wiki/](https://docs.gitlab.com/ee/user/project/wiki/) + +* [First time creating the Home page](#first-time-creating-the-home-page) +* [Creating a new wiki page](#creating-a-new-wiki-page) + * [Attachment storage](#attachment-storage) + * [Special characters in page titles](#special-characters-in-page-titles) + * [Length restrictions for file and directory names](#length-restrictions-for-file-and-directory-names) +* [Editing a wiki page](#editing-a-wiki-page) + * [Adding a table of contents](#adding-a-table-of-contents) +* [Deleting a wiki page](#deleting-a-wiki-page) +* [Moving a wiki page](#moving-a-wiki-page) +* [Viewing a list of all created wiki pages](#viewing-a-list-of-all-created-wiki-pages) +* [Viewing the history of a wiki page](#viewing-the-history-of-a-wiki-page) + * [Viewing the changes between page versions](#viewing-the-changes-between-page-versions) +* [Wiki activity records](#wiki-activity-records) + * [Limitations](#limitations) + * [Enable or disable Wiki Events](#enable-or-disable-wiki-events-core-only) +* [Adding and editing wiki pages locally](#adding-and-editing-wiki-pages-locally) +* [Customizing sidebar](#customizing-sidebar) + +# Wiki[](#wiki "Permalink") + +每个 GitLab 项目都内置了一个称为 Wiki 的独立文档系统. 默认情况下,所有新项目都启用此功能,您可以在项目的**Wiki**下找到它. + +如果您不想将文档保留在存储库中,但确实希望将其保留在代码所在的项目中,则 Wiki 非常方便. + +您可以在 Web 界面中或[使用 Git 在本地](#adding-and-editing-wiki-pages-locally)创建 Wiki 页面,因为每个 Wiki 都是单独的 Git 存储库. + +## First time creating the Home page[](#first-time-creating-the-home-page "Permalink") + +首次访问 Wiki 时,系统将指示您创建主页. 必须创建主页,因为它是查看 Wiki 时的登录页面. 您只需要填写**内容**部分,然后单击**创建页面** . 您以后可以随时对其进行编辑,因此继续写欢迎信息. + +[![New home page](img/909d20c0dd57155c8ac404a81c2a30cb.png)](img/wiki_create_home_page.png) + +## Creating a new wiki page[](#creating-a-new-wiki-page "Permalink") + +**注意:**需要开发者[权限](../../permissions.html) . + +通过单击可在所有 Wiki 页面中找到的" **新页面"**按钮来创建新页面. + +系统将要求您为新的 Wiki 页面填写标题. + +您可以通过在标题中使用" /"指示子目录来为 Wiki 页面指定完整路径. 任何丢失的目录将自动创建. 例如, `docs/my-page`的标题将创建一个 Wiki 页面,其路径为`/wikis/docs/my-page` . + +输入页面名称后,就该填写其内容了. GitLab Wiki 支持 Markdown,RDoc,AsciiDoc 和 Org. 对于基于 Markdown 的页面,所有[Markdown 功能](../../markdown.html)均受支持,对于链接,则存在一些[特定](../../markdown.html#wiki-specific-markdown)于[Wiki 的](../../markdown.html#wiki-specific-markdown)行为. + +在 Web 界面中,提交消息是可选的,但是 GitLab Wiki 是基于 Git 的,并且需要提交消息,因此如果您不输入消息,则会为您创建一条. + +When you’re ready, click the **建立页面** and the new page will be created. + +[![New page](img/0a61445809db70ca6bf85d986bf52223.png)](img/wiki_create_new_page.png) + +### Attachment storage[](#attachment-storage "Permalink") + +在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33475) . + +从 GitLab 11.3 开始,通过 GitLab 界面上载到 Wiki 的任何文件都将存储在 Wiki Git 存储库中,如果您在本地克隆 Wiki 存储库,该文件将可用. GitLab 11.3 之前的所有上传文件都存储在 GitLab 本身中. 如果希望它们成为 Wiki 的 Git 存储库的一部分,则必须再次上传它们. + +### Special characters in page titles[](#special-characters-in-page-titles "Permalink") + +Wiki 页面作为文件存储在 Git 存储库中,因此某些字符具有特殊含义: + +* 存储页面时,空格会转换为连字符. +* 显示页面时,连字符( `-` )转换回空格. +* 不能使用斜杠( `/` ),因为它们用作路径分隔符. + +### Length restrictions for file and directory names[](#length-restrictions-for-file-and-directory-names "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24364) . + +许多常见的文件系统[的文件名和目录名限制为 255 个字节](https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits) ,尽管 Git 和 GitLab 都支持超出这些限制的路径,但是它们的存在使这些文件系统上的用户无法在本地检出 Wiki 存储库. + +为了避免这种情况,通过 GitLab Web 界面和 API 编辑页面时会强制执行以下限制: + +* 页面标题为 245 个字节(文件扩展名保留 10 个字节). +* 255 个字节的目录名称. + +请注意: + +* 非 ASCII 字符占用多个字节. +* 仍然可以通过 Git 在本地创建超出限制的文件和目录,但这可能会在其他人的计算机上中断. + +## Editing a wiki page[](#editing-a-wiki-page "Permalink") + +**注意:**需要开发者[权限](../../permissions.html) . + +要编辑页面,只需单击" **编辑"**按钮. 从那里开始,您可以更改其内容. 完成后,单击" **保存更改"**以使更改生效. + +### Adding a table of contents[](#adding-a-table-of-contents "Permalink") + +要从 Wiki 页面中的标题生成目录,请使用`[[_TOC_]]`标签. 有关示例,请参阅[目录](../../markdown.html#table-of-contents) . + +## Deleting a wiki page[](#deleting-a-wiki-page "Permalink") + +**注意:**需要维护者[权限](../../permissions.html) . + +仅在编辑页面时才能找到" **删除"**按钮. 单击它并确认您要删除页面. + +## Moving a wiki page[](#moving-a-wiki-page "Permalink") + +通过在[编辑](#editing-a-wiki-page)表单的 Wiki 页面标题中指定完整路径,可以将 Wiki 页面从一个目录移动到另一个目录. + +[![Moving a page](img/7a0180479e056fe1c4aa11c3e8684906.png)](img/wiki_move_page_1.png) + +[![After moving a page](img/70117ebf119dd375e0def463921cc363.png)](img/wiki_move_page_2.png) + +为了将 Wiki 页面移动到根目录,必须在 Wiki 页面标题前加上斜杠( `/` )字符. + +## Viewing a list of all created wiki pages[](#viewing-a-list-of-all-created-wiki-pages "Permalink") + +每个 Wiki 都有一个侧边栏,从中可以找到所创建页面的简短列表. 该列表按字母顺序排列. + +[![Wiki sidebar](img/03d3f984ea7608322b1fd6a7feba47c0.png)](img/wiki_sidebar.png) + +如果页面很多,则不会在侧边栏中列出所有页面. 单击**查看所有页面**以**查看所有页面** . + +## Viewing the history of a wiki page[](#viewing-the-history-of-a-wiki-page "Permalink") + +Wiki 页面随时间的变化记录在 Wiki 的 Git 存储库中,您可以通过单击**Page history**按钮来查看它们. + +从历史记录页面中,您可以看到页面的修订版(Git commit SHA),其作者,提交消息以及上次更新时间. 要查看页面的先前版本的外观,请在" **页面版本"**列中单击修订号. + +[![Wiki page history](img/2fdc2024eee83764328fb015ffd4e392.png)](img/wiki_page_history.png) + +### Viewing the changes between page versions[](#viewing-the-changes-between-page-versions "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/15242) . + +类似于版本化的差异文件视图,您可以看到在给定的 Wiki 页面版本中所做的更改: + +1. 导航到您感兴趣的 Wiki 页面. +2. 单击**页面历史记录**以查看所有页面版本. +3. 单击" **更改"**列中的提交消息以获取您感兴趣的版本: + + [![Wiki page changes](img/9cc2ca9eb5afc113cacfbc529374fe3b.png)](img/wiki_page_diffs_v13_2.png) + +## Wiki activity records[](#wiki-activity-records "Permalink") + +版本历史 + +* 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/14902) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上启用了它. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-wiki-events-core-only) . + +Wiki 事件(创建,删除和更新)由 GitLab 跟踪,并显示在[用户个人资料](../../profile/index.html#user-profile) , [组](../../group/index.html#view-group-activity)和[项目](../index.html#project-activity)活动页面上. + +### Limitations[](#limitations "Permalink") + +只有在浏览器中或通过 API 进行的编辑才会记录其活动. 当前在活动列表中未列出通过 Git 进行和推送的编辑. + +### Enable or disable Wiki Events[](#enable-or-disable-wiki-events-core-only "Permalink") + +Wiki 事件活动正在开发中,尚未准备好用于生产. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/troubleshooting/navigating_gitlab_via_rails_console.html#starting-a-rails-console-session)可以为您的实例启用它. 欢迎您对其进行测试,但使用风险自负. + +要启用它: + +``` +Feature.enable(:wiki_events) +``` + +禁用它: + +``` +Feature.disable(:wiki_events) +``` + +## Adding and editing wiki pages locally[](#adding-and-editing-wiki-pages-locally "Permalink") + +由于 Wiki 基于 Git 存储库,因此您可以像在其他所有 Git 存储库中一样在本地克隆它们并进行编辑. + +在右侧栏上,单击" **克隆存储库",**然后按照屏幕上的说明进行操作. + +根据您要使用的标记语言,您在本地添加到 Wiki 的文件必须具有以下受支持的扩展名之一,否则当推送到 GitLab 时将不会显示这些文件: + +* Markdown 扩展名: `.mdown` , `.mkd` , `.mkdn` , `.md` , `.markdown` . +* AsciiDoc 扩展名: `.adoc` , `.ad` , `.asciidoc` . +* 其他标记扩展名: `.textile` , `.rdoc` , `.org` , `.creole` , `.wiki` , `.mediawiki` , `.rst` . + +## Customizing sidebar[](#customizing-sidebar "Permalink") + +在项目的 Wiki 页面上,有一个右侧导航,默认情况下呈现带有层次结构的完整 Wiki 页面列表. + +要自定义边栏,您可以创建一个名为`_sidebar`的文件以完全替换默认导航. + +**警告:**除非您从自定义导航链接`_sidebar`文件,否则要进行编辑,必须输入以下内容直接从浏览器的地址栏中访问: `https://gitlab.com/<namespace>/<project_name>/-/wikis/_sidebar` : `_sidebar` /- `https://gitlab.com/<namespace>/<project_name>/-/wikis/_sidebar` (对于自我管理的 GitLab 实例,将`gitlab.com`替换为实例的 URL). + +`_sidebar`示例(使用 Markdown 格式): + +``` +### [Home](home) + - [Hello World](hello) +- [Foo](foo) +- [Bar](bar) + --- + +- [Sidebar](_sidebar) +``` + +计划支持使用自定义侧面导航显示生成的目录. \ No newline at end of file diff --git a/_book/docs/174.md b/_book/docs/174.md new file mode 100644 index 0000000000000000000000000000000000000000..f1cc06713fde6a2feee1b61a35e0af4e514e00ba --- /dev/null +++ b/_book/docs/174.md @@ -0,0 +1,17 @@ +# Project operations + +> 原文:[https://docs.gitlab.com/ee/operations/](https://docs.gitlab.com/ee/operations/) + +# Project operations[](#project-operations "Permalink") + +manbetx 客户端打不开提供各种工具来帮助操作和维护您的应用程序: + +* Collect [Prometheus metrics](../user/project/integrations/prometheus_library/index.html). +* 部署到不同的[环境](../ci/environments/index.html) . +* 管理您的[警报](../user/project/operations/alert_management.html)和[事件](../user/incident_management/index.html) . +* 将您的项目连接到[Kubernetes 集群](../user/project/clusters/index.html) . +* 通过" [按代码实施](../user/infrastructure/index.html)基础[结构"](../user/infrastructure/index.html)管理基础[结构](../user/infrastructure/index.html) . +* 通过[错误跟踪](../user/project/operations/error_tracking.html)发现并查看由应用程序生成的[错误](../user/project/operations/error_tracking.html) . +* 创建,切换和删除[功能标记](feature_flags.html) . +* [跟踪](tracing.html)已部署应用程序的性能和运行状况. +* 更改" [监视仪表板](../user/project/operations/dashboard_settings.html) "的[设置](../user/project/operations/dashboard_settings.html) . \ No newline at end of file diff --git a/_book/docs/175.md b/_book/docs/175.md new file mode 100644 index 0000000000000000000000000000000000000000..c4fc4164df80bcf32aa16baf46b373545abad055 --- /dev/null +++ b/_book/docs/175.md @@ -0,0 +1,108 @@ +# Monitor metrics for your CI/CD environment + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/](https://docs.gitlab.com/ee/operations/metrics/) + +* [Populate your metrics dashboard](#populate-your-metrics-dashboard) +* [Customize your metrics dashboard](#customize-your-metrics-dashboard) +* [Metrics dashboard visibility](#metrics-dashboard-visibility) +* [Adding custom metrics](#adding-custom-metrics) +* [Editing additional metrics from the dashboard](#editing-additional-metrics-from-the-dashboard) +* [Keyboard shortcuts for charts](#keyboard-shortcuts-for-charts) + +# Monitor metrics for your CI/CD environment[](#monitor-metrics-for-your-cicd-environment "Permalink") + +在[为群集配置 Prometheus](../../user/project/integrations/prometheus.html)之后,GitLab 会尝试在成功部署的任何[环境中](../../ci/environments/index.html)检索性能指标. + +GitLab 在 Prometheus 服务器上扫描来自 Kubernetes 和 NGINX 等已知服务器的指标,并尝试识别各个环境. 要了解有关支持的指标和扫描过程的更多信息,请参阅[Prometheus Metrics Library 文档](../../user/project/integrations/prometheus_library/index.html) . + +要查看已[完成至少一个部署](#populate-your-metrics-dashboard)的环境的指标仪表板,请执行[以下操作](#populate-your-metrics-dashboard) : + +1. *如果指标仪表盘仅对项目成员可见,请以项目成员*身份登录到 GitLab. 了解有关[指标仪表板可见性的](#metrics-dashboard-visibility)更多[信息](#metrics-dashboard-visibility) . +2. 在您的项目中,导航到 **操作>指标** . + +GitLab 显示环境的默认指标仪表板,如以下示例所示: + +[![Example of metrics dashboard](img/b12f4326b7cccf6e82c375163842f58e.png)](img/example-dashboard_v13_1.png) + +仪表板的顶部包含一个导航栏. 从左到右,导航栏包含: + +* **仪表板** -项目可用的所有仪表板的下拉列表,其中加星标的仪表板排在最前面. +* **环境** -所有[环境的](../index.html)下拉列表,可在您键入时搜索所有环境. +* **范围** -要显示的数据的时间段. +* **刷新仪表板** -用当前数据重新加载仪表板. +* **设置刷新率** - Set a time frame for refreshing the data displayed. +* **明星仪表板** -单击以将仪表板标记为收藏夹. 已加星标的信息中心显示实心星 按钮,然后在" **仪表板"**下拉列表中首先显示. (在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214582) .) +* **创建仪表板** - [为您的项目](dashboards/index.html#adding-a-new-dashboard-to-your-project)创建一个[新的自定义仪表板](dashboards/index.html#adding-a-new-dashboard-to-your-project) . +* **指标设置** -配置[此仪表板](dashboards/index.html#manage-the-metrics-dashboard-settings)的[设置](dashboards/index.html#manage-the-metrics-dashboard-settings) . + +## Populate your metrics dashboard[](#populate-your-metrics-dashboard "Permalink") + +在[为群集配置 Prometheus](../../user/project/integrations/prometheus.html)之后,您还必须为 **操作>指标**页面以包含数据. 设置[Auto DevOps](../../topics/autodevops/index.html)有助于快速创建部署: + +1. 导航到您项目的 **操作> Kubernetes**页面. +2. 确保除了 Prometheus 外,还安装了 Runner 和 Ingress. +3. 安装 Ingress 后,复制其端点. +4. Navigate to your project’s **设置> CI / CD** page. In the **自动 DevOps** section, select a deployment strategy and save your changes. +5. 在同一页上的" **变量"**部分中,添加一个名为`KUBE_INGRESS_BASE_DOMAIN`的变量, `KUBE_INGRESS_BASE_DOMAIN`包含您先前复制的 Ingress 端点的值. 将类型保留为**Variable** . +6. 导航到您项目的 **CI / CD>管道**页面,然后在任何分支上运行管道. +7. 管道成功运行后,图表将在 **操作>指标**页面. + +[![Monitoring Dashboard](img/1bce7244cd585ee6d059a7aa1903f194.png)](../../user/project/integrations/img/prometheus_monitoring_dashboard_v13_1.png) + +## Customize your metrics dashboard[](#customize-your-metrics-dashboard "Permalink") + +创建仪表板后,您可以对其进行自定义以满足您的需求: + +* **添加自定义指标** :除了 GitLab 默认指标之外,您还可以[创建自定义指标](#adding-custom-metrics)并将其显示在指标仪表板上. +* **配置指标警报** :当环境性能超出您设置的范围时,为团队[配置自定义警报](alerts.html) . +* **通过警报触发操作** : [为您的团队打开新问题](alerts.html#trigger-actions-from-alerts-ultimate) 当环境性能超出您设置的范围时. + +## Metrics dashboard visibility[](#metrics-dashboard-visibility "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/201924) . + +您可以将指标仪表板的可见性设置为" **仅项目成员"**或" **具有访问权限的所有人"** . 当设置为" **具有访问权的所有人"时** ,指标仪表板对于已认证和未认证的用户都是可见的. + +## Adding custom metrics[](#adding-custom-metrics "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3799) . +* [移至](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28527) [GitLab Core](https://about.gitlab.com/pricing/) 12.10\. + +可以通过在监控仪表板页面上添加自定义指标来对其进行监控. 保存它们后,它们将显示在环境指标仪表板上,前提是: + +* 使用具有匹配[环境范围的](../../ci/environments/index.html#scoping-environments-with-specs) [连接的 Kubernetes 群集](../../user/project/clusters/add_remove_clusters.html) ,并将[Prometheus 安装在群集上](../../user/project/integrations/prometheus.html#enabling-prometheus-integration) . +* Prometheus 是[手动配置的](../../user/project/integrations/prometheus.html#manual-configuration-of-prometheus) . + +[![Add New Metric](img/ecb68ae545435c5eb9229937635a5aee.png)](../../user/project/integrations/img/prometheus_add_metric.png) + +必须填写几个字段: + +* **名称** :图表标题 +* **类型** :指标的类型. 相同类型的指标将一起显示. +* **查询** :有效的[PromQL 查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/basics/) . +* **Y 轴标签** :Y 轴标题显示在仪表板上. +* **单位标签** :查询单位,例如`req / sec` . 值旁边显示. + +如果指标之间的**名称** , **类型**和**Y 轴标签**字段匹配,则可以在同一图表上显示多个指标. 例如,具有" **名称** `Requests Rate` ," `Business` **类型"**和**Y 轴标签** `rec / sec`度量标准将与另一个具有相同值的度量标准显示在同一图表上. 如果使用此功能,则建议使用**图例标签** . + +## Editing additional metrics from the dashboard[](#editing-additional-metrics-from-the-dashboard "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/208976) . + +您可以通过以下方式为信息中心编辑现有的其他自定义指标: **更多操作**下拉菜单,然后选择**编辑指标** . + +[![Edit metric](img/f0d4bcbd75dfae1dbbc867343090a4ca.png)](../../user/project/integrations/img/prometheus_dashboard_edit_metric_link_v_12_9.png) + +## Keyboard shortcuts for charts[](#keyboard-shortcuts-for-charts "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/202146) . + +您可以使用键盘快捷键与当前关注的图表面板更快地进行交互. 要激活键盘快捷键,请使用键盘标签突出显示 **"更多操作"**下拉菜单,或用鼠标悬停在下拉菜单上,然后按与所需操作对应的键: + +* **展开面板** - `e` +* **查看日志** `-l` (小写" L") +* **下载 CSV** - `d` +* **复制链接到图表** - `c` +* **Alerts** - `a` \ No newline at end of file diff --git a/_book/docs/176.md b/_book/docs/176.md new file mode 100644 index 0000000000000000000000000000000000000000..a8d188de1a4f13421582bafc95d5f36f12b4c2ad --- /dev/null +++ b/_book/docs/176.md @@ -0,0 +1,88 @@ +# Set up alerts for Prometheus metrics + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/alerts.html](https://docs.gitlab.com/ee/operations/metrics/alerts.html) + +* [Managed Prometheus instances](#managed-prometheus-instances) +* [External Prometheus instances](#external-prometheus-instances) +* [Trigger actions from alerts](#trigger-actions-from-alerts-ultimate) + +# Set up alerts for Prometheus metrics[](#set-up-alerts-for-prometheus-metrics "Permalink") + +在[为 CI / CD 环境配置指标](index.html)后,您可以根据实例的位置为 Prometheus 指标设置警报,并在环境性能超出您设置的范围时[触发警报操作](#trigger-actions-from-alerts-ultimate)以通知您的团队. + +## Managed Prometheus instances[](#managed-prometheus-instances "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6590)了[自定义指标](index.html#adding-custom-metrics) ,在 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6590)了[图书馆指标](../../user/project/integrations/prometheus_library/metrics.html) . + +对于使用自动配置的托管 Prometheus 实例,您可以直接在[指标仪表板中](index.html) [配置指标警报](index.html#adding-custom-metrics) . 设置警报: + +1. 在您的项目中,导航到 **操作>指标** , +2. 确定要为其创建警报的指标,然后单击**省略号** 指标右上角的图标. +3. Choose **Alerts**. +4. 设置阈值和运算符. +5. 单击**添加**以保存并激活警报. + +[![Adding an alert](img/659964d0e0d080d80881d6eb74aaaf7e.png)](../../user/project/integrations/img/prometheus_alert.png) + +要删除警报,请在警报图标上返回所需的指标,然后单击" **删除"** . + +## External Prometheus instances[](#external-prometheus-instances "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9258) . +* 在 12.10 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) [GitLab Core](https://about.gitlab.com/pricing/) . + +对于手动配置的 Prometheus 服务器,GitLab 提供了一个通知端点,用于 Prometheus Webhooks. 如果启用了手动配置,则会将" **警报"**部分添加到 **设置>集成> Prometheus** . 本部分包含您需要的**URL**和**授权密钥** . **重置密钥**按钮将使密钥无效并生成一个新密钥. + +[![Prometheus service configuration of Alerts](img/510cd4b11aa5f23be76d594a9ad782d6.png)](../../user/project/integrations/img/prometheus_service_alerts.png) + +要发送 GitLab 警报通知,请将**URL**和**授权密钥**复制到 Prometheus Alertmanager 配置的[`webhook_configs`](https://s0prometheus0io.icopy.site/docs/alerting/latest/configuration/)部分: + +``` +receivers: + name: gitlab + webhook_configs: + - http_config: + bearer_token: 9e1cbfcd546896a9ea8be557caf13a76 + send_resolved: true + url: http://192.168.178.31:3001/root/manual_prometheus/prometheus/alerts/notify.json + ... +``` + +为了使 GitLab 将警报与[环境](../../ci/environments/index.html)相关联,您必须在 Prometheus 中设置的警报上配置`gitlab_environment_name`标签. 此值应与您在 GitLab 中的环境名称匹配. + +**Note:** In GitLab versions 13.1 and greater, you can configure your manually configured Prometheus server to use the [Generic alerts integration](../../user/project/integrations/generic_alerts.html). + +## Trigger actions from alerts[](#trigger-actions-from-alerts-ultimate "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4925) . +* [从 GitLab Ultimate 12.5 起](https://gitlab.com/gitlab-org/gitlab/-/issues/13401) ,当 GitLab 收到恢复警报时,它将自动关闭相关问题. + +警报可用于触发操作,例如自动打开问题(自`13.1`默认禁用). 要配置操作: + +1. 导航到您项目的 **设置>操作>事件** . +2. 启用该选项以创建问题. +3. 选择要从中创建问题的[问题模板](../../user/project/description_templates.html) . +4. (可选)选择是否将电子邮件通知发送给项目的开发人员. +5. Click **保存更改**. + +启用后,当触发包含包含从[警报有效负载中](https://s0prometheus0io.icopy.site/docs/alerting/latest/configuration/)提取的值的警报时,GitLab 会自动打开一个问题: + +* 问题作者: `GitLab Alert Bot` +* 问题标题:从`annotations/title` , `annotations/summary`或`labels/alertname` +* 警报`Summary` :属性列表 + * `starts_at` :通过`startsAt`警报的开始时间 + * `full_query` :从`generatorURL`提取的警报查询 + * 从`annotations/*`提取的附加注释的可选列表 +* Alert [GFM](../../user/markdown.html) :来自`annotations/gitlab_incident_markdown` GitLab 风味`annotations/gitlab_incident_markdown` + +当 GitLab 收到**Recovery Alert 时** ,它将关闭相关问题. 该操作记录为关于该问题的系统消息,表明该操作已由 GitLab Alert 机器人自动关闭. + +要进一步自定义问题,您可以在所选问题模板中添加标签,提及或任何其他受支持的[快速操作](../../user/project/quick_actions.html) ,该操作适用于所有事件. 要将快速操作或其他信息限制为仅特定类型的警报,请使用`annotations/gitlab_incident_markdown`字段. + +从[版本 12.2 开始](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/63373) ,GitLab 会使用`incident`标签自动标记每个事件问题. 如果标签尚不存在,则会自动创建. + +如果度量标准超过警报阈值超过 5 分钟,则 GitLab 会向该项目的所有[维护者和所有者](../../user/permissions.html#project-members-permissions)发送电子邮件. \ No newline at end of file diff --git a/_book/docs/177.md b/_book/docs/177.md new file mode 100644 index 0000000000000000000000000000000000000000..203fcaa1471602189f160c27a142c8b831f96862 --- /dev/null +++ b/_book/docs/177.md @@ -0,0 +1,92 @@ +# Embedding metric charts within GitLab-flavored Markdown + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/embed.html](https://docs.gitlab.com/ee/operations/metrics/embed.html) + +* [Embedding GitLab-managed Kubernetes metrics](#embedding-gitlab-managed-kubernetes-metrics) +* [Embedding metrics in issue templates](#embedding-metrics-in-issue-templates) +* [Embedding metrics based on alerts in incident issues](#embedding-metrics-based-on-alerts-in-incident-issues) +* [Embedding cluster health charts](#embedding-cluster-health-charts) + +# Embedding metric charts within GitLab-flavored Markdown[](#embedding-metric-charts-within-gitlab-flavored-markdown "Permalink") + +您可以在[GitLab 风味降价](../../user/markdown.html#gitlab-flavored-markdown-gfm)字段中显示指标图表,例如发布或合并请求说明. GitLab 风味的 Markdown 字段中允许的最大嵌入图表数为 100.当与其他人共享应用程序事件或性能指标并且您想直接获得相关信息时,嵌入图表很有用. + +## Embedding GitLab-managed Kubernetes metrics[](#embedding-gitlab-managed-kubernetes-metrics "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29691) . + +**Note:** Requires [Kubernetes](../../user/project/integrations/prometheus_library/kubernetes.html) metrics. + +要显示度量图表,请在支持 GitLab 风格的 Markdown 的字段中包含`https://<root_url>/<project>/-/environments/<environment_id>/metrics`形式的链接: + +[![Embedded Metrics Markdown](img/8f07bae8fce74cd6b8276b7dd9e59c2e.png)](../../user/project/integrations/img/embedded_metrics_markdown_v12_8.png) + +GitLab 将链接展开为嵌入式指标面板: + +[![Embedded Metrics Rendered](img/276614fbc4ef7b7b9f7a445dffbc5691.png)](../../user/project/integrations/img/embedded_metrics_rendered_v12_8.png) + +您还可以嵌入一个图表. 要获取图表链接,请点击 图表右上角的" **更多操作"**菜单,然后选择" **将链接复制到图表"** ,如本示例所示: + +[![Copy Link To Chart](img/6f52527c138db466f7fba27994ad67f8.png)](../../user/project/integrations/img/copy_link_to_chart_v12_10.png) + +指标必须满足以下要求: + +* `<environment_id>`必须与真实环境相对应. +* 普罗米修斯必须在监视环境. +* 必须将 GitLab 实例配置为从环境接收数据. +* 必须允许用户访问环境( [Reporter 或更高版本](../../user/permissions.html) )的监视仪表板. +* 仪表板必须在最近 8 小时内具有数据. + +如果以上所有条件均成立,则该指标将展开,如下所示: + +[![Embedded Metrics](img/0ff1ac0799b3b8867f4ebefa4e22d786.png)](../../user/project/integrations/img/view_embedded_metrics_v12_10.png) + +公制图表也可能被隐藏: + +[![Show Hide](img/cb4ff59b46134d4c61caedcf5a66a74f.png)](../../user/project/integrations/img/hide_embedded_metrics_v12_10.png) + +您可以直接在浏览器中打开链接[以获取数据](dashboards/index.html#expand-panel)的[详细视图](dashboards/index.html#expand-panel) . + +## Embedding metrics in issue templates[](#embedding-metrics-in-issue-templates "Permalink") + +您也可以在问题模板中嵌入默认仪表板指标或单个指标. 要使图表并排显示,请使用逗号或空格将指向整个指标仪表板或单个指标的单独链接分开. + +[![Embedded Metrics in issue templates](img/b51efc1bf28d2363ac0b4e95c4318fbe.png)](../../user/project/integrations/img/embed_metrics_issue_template.png) + +## Embedding metrics based on alerts in incident issues[](#embedding-metrics-based-on-alerts-in-incident-issues "Permalink") + +对于由[GitLab 管理的警报规则](alerts.html) ,问题包括与警报相对应的查询的嵌入式图表. 该图表显示了事件开始点前后一个小时(前后 30 分钟)的一小时数据. + +对于[手动配置的 Prometheus 实例](../../user/project/integrations/prometheus.html#manual-configuration-of-prometheus) ,如果满足以下要求,则可以包括与查询相对应的图表: + +* 该警报对应于通过 GitLab 管理的环境. +* 警报对应于[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) . +* 警报包含下表中列出的必需属性. + +| Attributes | Required | Description | +| --- | --- | --- | +| `annotations/gitlab_environment_name` | Yes | 与警报对应的由 GitLab 管理的环境的名称 | +| `annotations/title` , `annotations/summary` , `labels/alertname` | Yes | 用作图表标题 | +| `annotations/gitlab_y_label` | No | 用作图表的 y 轴标签 | + +## Embedding cluster health charts[](#embedding-cluster-health-charts "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/40997) . +* 在 13.2 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/208224) GitLab 核心. + +[Cluster Health Metrics](../../user/project/clusters/index.html#visualizing-cluster-health)也可以嵌入到[GitLab 风格的 Markdown 中](../../user/markdown.html) . + +要嵌入度量标准图表,请在支持 GitLab 风格的 Markdown 的任何位置以`https://<root_url>/<project>/-/cluster/<cluster_id>?<query_params>`的形式包含指向该图表的链接. 要生成并复制到图表的链接,请遵循[Cluster Health Metric 文档中的说明](../../user/project/clusters/index.html#visualizing-cluster-health) . + +指标必须满足以下要求: + +* `<cluster_id>`必须与实际群集相对应. +* Prometheus 必须监视群集. +* 必须允许用户访问项目集群指标. +* 仪表板必须在" [集群运行状况"页面](../../user/project/clusters/index.html#visualizing-cluster-health)上报告数据 + +如果满足上述要求,则度量标准将展开,如下所示. + +[![Embedded Cluster Metric in issue descriptions](img/f8c421bf7dd271d1aeee39c15aab183d.png)](../../user/project/integrations/img/prometheus_cluster_health_embed_v12_9.png) \ No newline at end of file diff --git a/_book/docs/178.md b/_book/docs/178.md new file mode 100644 index 0000000000000000000000000000000000000000..0e6fd4726745c7fc7d5300bf4eee899d51ea3ad1 --- /dev/null +++ b/_book/docs/178.md @@ -0,0 +1,63 @@ +# Embedding Grafana charts + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/embed_grafana.html](https://docs.gitlab.com/ee/operations/metrics/embed_grafana.html) + +* [Embedding charts via Grafana Rendered Images](#embedding-charts-via-grafana-rendered-images) +* [Embedding charts via integration with Grafana HTTP API](#embedding-charts-via-integration-with-grafana-http-api) +* [Setting up the Grafana integration](#setting-up-the-grafana-integration) +* [Generating a link to a chart](#generating-a-link-to-a-chart) + +# Embedding Grafana charts[](#embedding-grafana-charts "Permalink") + +Grafana 指标可以嵌入到[GitLab 风味 Markdown 中](../../user/markdown.html) . + +## Embedding charts via Grafana Rendered Images[](#embedding-charts-via-grafana-rendered-images "Permalink") + +可以在问题中嵌入实时[Grafana](https://docs.gitlab.com/omnibus/settings/grafana.html)图表,作为[直接链接的渲染图像](https://grafana.com/docs/grafana/latest/reference/share_panel/#direct-link-rendered-image) . + +Grafana 中的共享对话框提供了链接,如下所示. + +[![Grafana Direct Linked Rendered Image](img/f406b88682259abab36d343539b1664c.png)](../../user/project/integrations/img/grafana_live_embed.png) + +**注意:**为了使此嵌入正确显示,Grafana 实例必须可作为公共仪表板或在同一网络上供目标用户使用. + +复制链接并在 Markdown 中将图像标签添加为[内联 HTML](../../user/markdown.html#inline-html) . 您可以根据需要调整查询参数. 例如,删除`&from=`和`&to=`参数将为您提供实时图表. 这是来自 GitLab 公共仪表板的实时图表的示例标记: + +``` +<img src="https://dashboards.gitlab.com/d/RZmbBr7mk/gitlab-triage?orgId=1&refresh=30s&var-env=gprd&var-environment=gprd&var-prometheus=prometheus-01-inf-gprd&var-prometheus_app=prometheus-app-01-inf-gprd&var-backend=All&var-type=All&var-stage=main&from=1580444107655&to=1580465707655"/> +``` + +这将呈现为: + +[![Grafana dashboard embedded preview](img/b820c73810583190a0b1697c813fdda8.png)](../../user/project/integrations/img/grafana_embedded.png) + +## Embedding charts via integration with Grafana HTTP API[](#embedding-charts-via-integration-with-grafana-http-api "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31376) . + +每个项目可以支持与一个 Grafana 实例的集成. 此配置允许用户将链接复制到 Grafana 中的面板,然后将其粘贴到 GitLab Markdown 字段中. 该图表将以 GitLab 图表格式呈现. + +从 Grafana 实例嵌入的先决条件: + +1. 数据源必须是 Prometheus 实例. +2. 数据源必须是可代理的,因此 HTTP 访问设置应设置为`Server` . + +[![HTTP Proxy Access](img/7896b9b275d92d4b9cb2001cc464e509.png)](../../user/project/integrations/img/http_proxy_access_v12_5.png) + +## Setting up the Grafana integration[](#setting-up-the-grafana-integration "Permalink") + +1. [Generate an Admin-level API Token in Grafana.](https://grafana.com/docs/grafana/latest/http_api/auth/#create-api-token) +2. 在您的 GitLab 项目中,导航至**设置>操作> Grafana 身份验证** . +3. 要启用集成,请选中"活动"复选框. +4. 对于" Grafana URL",输入 Grafana 实例的基本 URL. +5. 对于" API 令牌",输入您刚生成的 Admin API 令牌. +6. Click **保存更改**. + +## Generating a link to a chart[](#generating-a-link-to-a-chart "Permalink") + +1. 在 Grafana 中,导航到要嵌入面板的仪表板. [![Grafana 公制面板](img/eb191fa059117d5fb30958d7f6241704.png)](../../user/project/integrations/img/grafana_panel_v12_5.png) +2. 在页面的左上角,为图表中查询所需的每个变量选择一个特定值. [![选择查询变量](img/40834a63780a362f429e1902450a4a7a.png)](../../user/project/integrations/img/select_query_variables_v12_5.png) +3. 在 Grafana 中,单击面板的标题,然后单击" **共享"**以将面板的共享对话框打开到" **链接"**选项卡. 如果您单击*仪表板的*共享面板,则 GitLab 将尝试在仪表板上嵌入第一个受支持的面板(如果有). +4. 如果您的普罗米修斯查询使用 Grafana 的自定义模板变量,确保"模板变量"选项切换为**开** . 在 Grafana 全局模板变量中,目前仅支持`$__interval` , `$__from`和`$__to` . 切换**"**当前时间范围"选项来指定图表的时间范围. 否则,默认范围将是最近 8 小时. [![Grafana 共享对话框](img/ce9e5e0a216a3a51d412bcb3cb11f420.png)](../../user/project/integrations/img/grafana_sharing_dialog_v12_5.png) +5. 单击**复制**将 URL **复制**到剪贴板. +6. 在 GitLab 中,将该 URL 粘贴到 Markdown 字段中并保存. 该图表将需要一些时间来呈现. [![GitLab 渲染的 Grafana 面板](img/c67bf60334fcbd1f63dc0a6515d02eca.png)](../../user/project/integrations/img/rendered_grafana_embed_v12_5.png) \ No newline at end of file diff --git a/_book/docs/179.md b/_book/docs/179.md new file mode 100644 index 0000000000000000000000000000000000000000..125d3db03ed668014a756625c930b03baf04bb72 --- /dev/null +++ b/_book/docs/179.md @@ -0,0 +1,216 @@ +# Using the Metrics Dashboard + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/dashboards/](https://docs.gitlab.com/ee/operations/metrics/dashboards/) + +* [Manage the metrics dashboard settings](#manage-the-metrics-dashboard-settings) +* [Chart Context Menu](#chart-context-menu) + * [View and edit the source file of a custom dashboard](#view-and-edit-the-source-file-of-a-custom-dashboard) + * [Expand panel](#expand-panel) + * [View Logs](#view-logs-ultimate) + * [Timeline zoom and URL sharing](#timeline-zoom-and-url-sharing) + * [Downloading data as CSV](#downloading-data-as-csv) +* [Dashboard Annotations](#dashboard-annotations) + * [Retention policy](#retention-policy) +* [Add related links to custom dashboards](#add-related-links-to-custom-dashboards) + * [Links Syntax](#links-syntax) +* [Defining custom dashboards per project](#defining-custom-dashboards-per-project) + * [Adding a new dashboard to your project](#adding-a-new-dashboard-to-your-project) + * [Navigating to a custom dashboard](#navigating-to-a-custom-dashboard) + * [Duplicating a GitLab-defined dashboard](#duplicating-a-gitlab-defined-dashboard) +* [Troubleshooting](#troubleshooting) + * [“No data found” error on Metrics dashboard page](#no-data-found-error-on-metrics-dashboard-page) + +# Using the Metrics Dashboard[](#using-the-metrics-dashboard "Permalink") + +## Manage the metrics dashboard settings[](#manage-the-metrics-dashboard-settings "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/223204) . + +要管理指标信息中心的设置,请执行以下操作: + +1. 以具有项目维护者或管理员[权限](../../../user/permissions.html#project-members-permissions)的用户身份登录. +2. 导航至以下位置的信息中心 **操作>指标** . +3. 在资讯主页的右上角,按一下 **指标设置** : + + [![Monitoring Dashboard actions menu with create new item](img/0df7602f630bb279bdd6d7dc6a5dcf2f.png)](../../../user/project/integrations/img/metrics_settings_button_v13_2.png) + +## Chart Context Menu[](#chart-context-menu "Permalink") + +在信息中心的每个面板上,您都可以通过以下方式访问上下文菜单: 面板右上角上方的" **更多操作"**下拉框可采取与图表数据相关的操作. + +[![Context Menu](img/1a3371a11e14e221f5c8e0e75e327d08.png)](../../../user/project/integrations/img/panel_context_menu_v13_0.png) + +选项包括: + +* [Expand panel](#expand-panel) +* [View logs](#view-logs-ultimate) +* [Download CSV](#downloading-data-as-csv) +* [Copy link to chart](../embed.html#embedding-gitlab-managed-kubernetes-metrics) +* [Alerts](../alerts.html) + +### View and edit the source file of a custom dashboard[](#view-and-edit-the-source-file-of-a-custom-dashboard "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34779) . + +查看项目的自定义仪表板时,可以通过单击" **编辑仪表板"**按钮来查看原始的`.yml`文件. + +### Expand panel[](#expand-panel "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/3100) . + +要查看较大的可视化版本,请点击 **更多操作**图标,然后选择**展开面板** . + +要返回指标仪表板,请单击浏览器中的" **后退"**按钮,或按`Esc`键. + +### View Logs[](#view-logs-ultimate "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/122013) . + +如果启用了[日志](../../../user/project/clusters/kubernetes_pod_logs.html) ,则可以通过单击右上角的上下文菜单从仪表板中的图表导航以查看日志. + +如果使用图表底部的**时间轴缩放**功能,日志将缩小到您选择的时间范围. + +### Timeline zoom and URL sharing[](#timeline-zoom-and-url-sharing "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/198910) . + +您可以使用图表底部的**时间轴缩放**功能来放大所选的日期和时间. 单击并拖动滑块以选择要显示的数据的其他开始或结束日期时,GitLab 会将所选的开始和结束时间添加到 URL,从而使您可以更轻松地共享特定的时间范围. + +### Downloading data as CSV[](#downloading-data-as-csv "Permalink") + +指标仪表板上 Prometheus 图表中的数据可以 CSV 格式下载. + +## Dashboard Annotations[](#dashboard-annotations "Permalink") + +版本历史 + +* 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/211330) (由功能标志`metrics_dashboard_annotations`启用). +* 在 GitLab 13.0 中[删除](https://gitlab.com/gitlab-org/gitlab/-/issues/215224)了[功能标志](https://gitlab.com/gitlab-org/gitlab/-/issues/215224) . + +您可以使用" **指标仪表板注释"**通过在每个指标仪表板上添加注释来标记任何重要事件. 在查看仪表板时,分配给所选时间范围的注释条目将自动获取并显示在该仪表板内的每个图表上. 鼠标悬停时,每个注释都会显示其他详细信息,包括事件的确切时间及其描述. + +您可以通过向[Metrics 仪表板注释 API](../../../api/metrics_dashboard_annotations.html)发出请求来创建注释 + +[![Annotations UI](img/afe1906c0ba8e9c44277342a20a48db6.png)](../../../user/project/integrations/img/metrics_dashboard_annotations_ui_v13.0.png) + +### Retention policy[](#retention-policy "Permalink") + +在 GitLab 13.01 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/211433) . + +为了避免过时的注释浪费过多的存储空间,每天都会删除附加到超过两周时间段的记录. 此重复后台作业在本地服务器时间上午 1:00 运行. + +## Add related links to custom dashboards[](#add-related-links-to-custom-dashboards "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/216385) . + +You can embed links to other dashboards or external services in your custom dashboard by adding **相关链接** to your dashboard’s YAML file. Related links open in the same tab as the dashboard. Related links can be displayed in the following locations on your dashboard: + +* 在仪表板顶部,作为顶层[`links`仪表板属性](../../../operations/metrics/dashboards/yaml.html#dashboard-top-level-properties) . +* 在图表中,上下文菜单作为[面板](../../../operations/metrics/dashboards/yaml.html#panel-panels-properties)的[`links`属性](../../../operations/metrics/dashboards/yaml.html#panel-panels-properties) . + +相关链接可以包含以下属性: + +* `url` :链接的完整 URL. 需要. +* `title` :描述链接的短语. 可选的. 如果未设置此属性,则将完整的 URL 用于链接标题. +* `type` :一个声明链接类型的字符串. 可选的. 如果设置为`grafana` ,则仪表板的时间范围值将转换为 Grafana 的时间范围格式并附加到`url` . + +仪表板的时间范围作为 URL 参数附加到`url` . + +以下示例显示了添加到仪表板的两个相关链接( `GitLab.com`和`GitLab Documentation` ): + +[![Links UI](img/fe601ff47f99f0fd5220742f61007450.png)](../../../user/project/integrations/img/related_links_v13_1.png) + +### Links Syntax[](#links-syntax "Permalink") + +``` +links: + - title: GitLab.com + url: https://gitlab.com + - title: GitLab Documentation + url: https://docs.gitlab.com + - title: Public Grafana playground dashboard + url: https://play.grafana.org/d/000000012/grafana-play-home?orgId=1 + type: grafana +``` + +## Defining custom dashboards per project[](#defining-custom-dashboards-per-project "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/59974) . + +默认情况下,所有项目都包含一个由 GitLab 定义的 Prometheus 仪表板,其中包括一些关键指标,但是您也可以定义自己的自定义仪表板. + +您可以从头开始创建新文件,也可以复制 GitLab 定义的 Prometheus 仪表板. + +**注意:**与[自定义指标](../index.html#adding-custom-metrics)不同,以下[定义的指标](../index.html#adding-custom-metrics)不支持警报. + +### Adding a new dashboard to your project[](#adding-a-new-dashboard-to-your-project "Permalink") + +GitLab 13.2 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/223204) UI 选项. + +您可以通过将新的 YAML 文件添加到项目的`.gitlab/dashboards/`目录中来配置自定义仪表`.gitlab/dashboards/` . 为了将仪表板显示在项目的 **在"操作">"度量标准"**页面上,文件必须具有`.yml`扩展名,并且应存在于项目的**默认**分支中. + +要从 GitLab 用户界面创建新的仪表板,请执行以下操作: + +1. 以具有"维护者"或"所有者" [权限](../../../user/permissions.html#project-members-permissions)的用户身份登录到 GitLab. +2. 导航至以下位置的信息中心 **操作>指标** . +3. 在信息中心的右上角,点击 **在"操作"**菜单上,然后选择" **新建"** : [![使用创建新项目的](img/b24c623173b50fdf9cd2676f1f311580.png)](../../../user/project/integrations/img/actions_menu_create_new_dashboard_v13_2.png) +4. 在模式窗口中,单击**打开存储库** ,然后按照说明从命令行创建新的仪表板. + +要从命令行创建新的仪表板: + +1. 在存储库的根目录下创建`.gitlab/dashboards/prom_alerts.yml` . 每个 YAML 文件都应定义仪表板的布局以及用于填充数据的 Prometheus 查询. 此示例仪表板显示一个面积图: + + ``` + dashboard: 'Dashboard Title' + panel_groups: + - group: 'Group Title' + panels: + - type: area-chart + title: "Chart Title" + y_label: "Y-Axis" + y_axis: + format: number + precision: 0 + metrics: + - id: my_metric_id + query_range: 'http_requests_total' + label: "Instance: {{instance}}, method: {{method}}" + unit: "count" + ``` + +2. 保存文件,提交并推送到您的存储库. 该文件必须存在于您的**默认**分支中. +3. 导航到项目的" **操作">"指标",**然后从下拉列表中选择自定义仪表板. + +**注意:**不支持嵌套在`.gitlab/dashboards`子目录下的配置文件,并且在 UI 中将不可用. + +### Navigating to a custom dashboard[](#navigating-to-a-custom-dashboard "Permalink") + +自定义仪表板通过其文件名唯一标识. 为了快速查看自定义仪表板,只需通过以下方式在 URL 中使用仪表板文件名: `https://gitlab-instance.example.com/project/-/metrics/custom_dashboard_name.yml` : `https://gitlab-instance.example.com/project/-/metrics/custom_dashboard_name.yml` . + +### Duplicating a GitLab-defined dashboard[](#duplicating-a-gitlab-defined-dashboard "Permalink") + +版本历史 + +* 在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/37238) . +* 从[GitLab 12.8 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/39505) ,自定义指标也将在您复制仪表板时被复制. + +您可以保存 GitLab 定义的仪表板的完整副本以及添加到其中的所有自定义指标. 可以对生成的`.yml`文件进行自定义并使其适合您的项目. 您可以决定将仪表板`.yml`文件保存在项目的**默认**分支或新分支中. + +1. 在仪表板下拉菜单或操作菜单中,单击**重复仪表**板. + + **注意:**您只能复制 GitLab 定义的仪表板. +2. 输入文件名和其他信息,例如新提交的消息,然后单击**Duplicate** . + +如果选择**默认**分支,新的仪表板将立即可用. 如果选择另一个分支,则应首先将此分支合并到**默认**分支. + +## Troubleshooting[](#troubleshooting "Permalink") + +对托管的 Prometheus 应用程序的问题进行故障排除时, [查看 Prometheus UI](../../../development/prometheus.html#access-the-ui-of-a-prometheus-managed-application-in-kubernetes)通常很有用. + +### “No data found” error on Metrics dashboard page[](#no-data-found-error-on-metrics-dashboard-page "Permalink") + +如果继续出现"找不到数据"屏幕,则可能是由于: + +* 此环境尚未成功部署. +* Prometheus 没有此环境的性能数据,或者指标未正确标记. 要对此进行测试,请连接到 Prometheus 服务器并[运行查询](../../../user/project/integrations/prometheus_library/kubernetes.html#metrics-supported) ,将`$CI_ENVIRONMENT_SLUG`替换`$CI_ENVIRONMENT_SLUG`您的环境名称. +* 您可能需要重新添加 GitLab 预定义的通用指标. 这可以通过运行[导入公用度量 Rake 任务来完成](../../../administration/raketasks/maintenance.html#import-common-metrics) . \ No newline at end of file diff --git a/_book/docs/180.md b/_book/docs/180.md new file mode 100644 index 0000000000000000000000000000000000000000..1f9d9484c06a84400c9edfaa57fe9cb48d809380 --- /dev/null +++ b/_book/docs/180.md @@ -0,0 +1,173 @@ +# Dashboard YAML properties + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/dashboards/yaml.html](https://docs.gitlab.com/ee/operations/metrics/dashboards/yaml.html) + +* [**Dashboard (top-level) properties**](#dashboard-top-level-properties) +* [**Templating (`templating`) properties**](#templating-templating-properties) +* [**Links (`links`) properties**](#links-links-properties) +* [**Panel group (`panel_groups`) properties**](#panel-group-panel_groups-properties) +* [**Panel (`panels`) properties**](#panel-panels-properties) +* [**Axis (`panels[].y_axis`) properties**](#axis-panelsy_axis-properties) +* [**Metrics (`metrics`) properties**](#metrics-metrics-properties) +* [Dynamic labels](#dynamic-labels) +* [Dashboard YAML syntax validation](#dashboard-yaml-syntax-validation) + +# Dashboard YAML properties[](#dashboard-yaml-properties "Permalink") + +仪表板包含几个组件: + +* 模板变量. +* 面板组,由面板组成. +* 支持一个或多个指标的面板. + +下表概述了预期属性的详细信息. + +## **Dashboard (top-level) properties**[](#dashboard-top-level-properties "Permalink") + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `dashboard` | string | yes | 前往仪表板. 每个文件只能定义一个仪表板. | +| `panel_groups` | array | yes | 应在仪表板上的面板组. | +| `templating` | hash | no | 可以在其下添加模板相关选项的顶级键. | +| `links` | array | no | 添加链接以显示在仪表板上. | + +## **Templating (`templating`) properties**[](#templating-templating-properties "Permalink") + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `variables` | hash | yes | 可以在这里定义变量. | + +阅读有关[模板](templating_variables.html)的文档. + +## **Links (`links`) properties**[](#links-links-properties "Permalink") + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `url` | string | yes | 链接的地址. | +| `title` | string | no | 显示链接的标题. | +| `type` | string | no | 链接的类型. 指定链接类型,可以是: `grafana` | + +阅读有关[链接](index.html#add-related-links-to-custom-dashboards)的文档. + +## **Panel group (`panel_groups`) properties**[](#panel-group-panel_groups-properties "Permalink") + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `group` | string | required | 前往面板组. | +| `priority` | number | 可选,默认为按文件顺序 | 命令显示在仪表板上. 数字越高意味着优先级越高,该页面上的优先级越高. 数字不必是连续的. | +| `panels` | array | required | 应在面板组中的面板. | + +面板组中的面板排成一排,每行包含两个面板. 该规则的一个例外是一行上的单个面板:这些面板将采用其所在行的整个宽度. + +## **Panel (`panels`) properties**[](#panel-panels-properties "Permalink") + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | enum | 不,默认为`area-chart` | 指定要使用的面板类型,例如`area-chart` , `line-chart`或`anomaly-chart` . [查看所有面板类型的文档.](panel_types.html) | +| `title` | string | yes | 前往面板. | +| `y_label` | string | 不,但强烈鼓励 | 面板的 Y 轴标签. | +| `y_axis` | string | no | 面板的 Y 轴配置. | +| `max_value` | number | no | 分母值用于计算[基于百分位数的结果](panel_types.html#percentile-based-results) | +| `weight` | number | 否,默认为按文件顺序 | 顺序出现在分组中. 较低的数字表示较高的优先级,在页面上较高. 数字不必是连续的. | +| `metrics` | array | yes | 应在面板中显示的指标. 当`type`是`area-chart`或`line-chart` ,可以显示任意数量的度量标准,而当`type`是`anomaly-chart`时,只能显示 3 个度量标准. | +| `links` | array | no | 添加链接以显示在图表的[上下文菜单上](index.html#chart-context-menu) . | + +## **Axis (`panels[].y_axis`) properties**[](#axis-panelsy_axis-properties "Permalink") + +| Property | Type | Required | Description |   | +| --- | --- | --- | --- | --- | +| `name` | string | 不,但强烈鼓励 | 面板的 Y 轴标签. 如果设置,则替换`y_label` . |   | +| `format` | string | 否,默认为`engineering` | 使用的单位格式. 请参阅[单位](yaml_number_format.html)的[完整列表](yaml_number_format.html) . |   | +| `precision` | number | 否,默认为`2` | 要显示在数字中的小数位数. |   | + +## **Metrics (`metrics`) properties**[](#metrics-metrics-properties "Permalink") + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | string | no | 用于将仪表板指标与数据库记录相关联. 在仪表板配置文件中必须唯一. [警报所](../alerts.html)必需(尚未启用支持,请参阅[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/27980) ). | +| `unit` | string | yes | 定义查询的返回数据的单位. | +| `label` | string | 不,但强烈鼓励 | 定义查询的图例标签. 在面板指标内应唯一. 可以包含时间序列标签作为内插变量. | +| `query` | string | 是,如果没有定义`query_range` | 定义用于填充图表/面板的 Prometheus 查询. 如果定义,将使用[Prometheus API](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/)的`query`端点. | +| `query_range` | string | 是,如果未定义`query` | 定义用于填充图表/面板的 Prometheus 查询. 如果定义,将使用[Prometheus API](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/)的`query_range`端点. | +| `step` | number | 不,如果未定义,则计算值 | 定义查询解析步长(以秒为单位). 同一面板上的指标应使用相同的`step`值. | + +## Dynamic labels[](#dynamic-labels "Permalink") + +从 Prometheus 查询返回多个时间序列时,动态标签很有用. + +当使用静态标签并且查询返回多个时间序列时,所有图例项将被标记为相同,这使得识别每个时间序列变得困难: + +``` +metrics: + - id: my_metric_id + query_range: 'http_requests_total' + label: "Time Series" + unit: "count" +``` + +这可能会生成如下图例: + +[![repeated legend label chart](img/366832d79f753b4e66470fa923fa7acf.png)](../../../user/project/integrations/img/prometheus_dashboard_repeated_label.png) + +为了使标签更明确,使用反映时间序列标签的变量是一个好习惯. 渲染图例时,变量将被时间序列标签的值替换: + +``` +metrics: + - id: my_metric_id + query_range: 'http_requests_total' + label: "Instance: {{instance}}, method: {{method}}" + unit: "count" +``` + +生成的渲染图例将如下所示: + +[![legend with label variables](img/ef26fe9cbbfc0c1f060c6e7c578bd450.png)](../../../user/project/integrations/img/prometheus_dashboard_label_variables.png) + +动态仪表板标签还有一个简写值,该标签仅使用一个时间序列标签: + +``` +metrics: + - id: my_metric_id + query_range: 'http_requests_total' + label: "Method" + unit: "count" +``` + +这可以通过降低`label`的值来实现,如果还有更多的单词用空格分隔,请用下划线( `_` )替换这些空格. 然后根据 Prometheus 查询返回的时间序列的标签检查转换后的值. 如果找到与转换后的值相等的时间序列标签,则将使用标签值并将其呈现在图例中,如下所示: + +[![legend with label shorthand variable](img/def845e9e4d65228469b73dbc625c6cd.png)](../../../user/project/integrations/img/prometheus_dashboard_label_variable_shorthand.png) + +## Dashboard YAML syntax validation[](#dashboard-yaml-syntax-validation "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33202) . + +要确认您的仪表板定义包含有效的 YAML 语法,请执行以下操作: + +1. 导航 **存储库>文件** . +2. 导航到存储库中的仪表板文件. +3. 查看文件内容上方显示的有关文件的信息窗格. + +具有有效语法的文件显示**Metrics 仪表板 YAML 定义有效** ,而具有无效语法的文件显示**Metrics Dashboard YAML 定义无效** . + +[![Metrics Dashboard_YAML_syntax_validation](img/5f3552f35a06cac8dfa02c21fd48c852.png)](../../../user/project/integrations/img/prometheus_dashboard_yaml_validation_v13_1.png) + +当" **指标仪表板" YAML 定义无效时** ,将至少显示以下消息之一: + +1. `dashboard: can't be blank` [learn more](../../../operations/metrics/dashboards/yaml.html#dashboard-top-level-properties) +2. `panel_groups: should be an array of panel_groups objects` [learn more](../../../operations/metrics/dashboards/yaml.html#dashboard-top-level-properties) +3. `group: can't be blank` [learn more](../../../operations/metrics/dashboards/yaml.html#panel-group-panel_groups-properties) +4. `panels: should be an array of panels objects` [learn more](../../../operations/metrics/dashboards/yaml.html#panel-group-panel_groups-properties) +5. `title: can't be blank` [learn more](../../../operations/metrics/dashboards/yaml.html#panel-panels-properties) +6. `metrics: should be an array of metrics objects` [learn more](../../../operations/metrics/dashboards/yaml.html#panel-panels-properties) +7. `query: can't be blank` [learn more](../../../operations/metrics/dashboards/yaml.html#metrics-metrics-properties) +8. `query_range: can't be blank` [learn more](../../../operations/metrics/dashboards/yaml.html#metrics-metrics-properties) +9. `unit: can't be blank` [learn more](../../../operations/metrics/dashboards/yaml.html#metrics-metrics-properties) +10. `YAML syntax: The parsed YAML is too big` + + 当 YAML 文件大于 1 MB 时显示. + +11. `YAML syntax: Invalid configuration format` + + 当 YAML 文件为空或不包含有效的 YAML 时显示. + +指标仪表板 YAML 定义验证信息也可以作为[GraphQL API 字段获得](../../../api/graphql/reference/index.html#metricsdashboard) \ No newline at end of file diff --git a/_book/docs/181.md b/_book/docs/181.md new file mode 100644 index 0000000000000000000000000000000000000000..d9075099a55a5d9b195a1b926874a44af194ce45 --- /dev/null +++ b/_book/docs/181.md @@ -0,0 +1,44 @@ +# Metrics dashboard settings + +> 原文:[https://docs.gitlab.com/ee/user/project/operations/dashboard_settings.html](https://docs.gitlab.com/ee/user/project/operations/dashboard_settings.html) + +* [Change the dashboard time zone](#change-the-dashboard-time-zone) +* [Link to an external dashboard](#link-to-an-external-dashboard) + +# Metrics dashboard settings[](#metrics-dashboard-settings "Permalink") + +您可以配置[监控仪表板](../integrations/prometheus.html)以显示您选择的时区以及您选择的链接. + +要配置这些设置,您必须具有"管理项目操作" [权限](../../permissions.html) . + +## Change the dashboard time zone[](#change-the-dashboard-time-zone "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214370) . + +默认情况下,监视仪表板在本地时区中显示日期和时间,但是您可以 UTC 格式显示日期和时间. 更改时区: + +1. 以具有"管理项目操作" [权限](../../permissions.html)的用户身份登录. +2. 导航 **设置>操作** ,然后滚动到" **指标仪表板"** . +3. 在" **仪表板时区"**选择框中,选择" *用户的本地时区"*或" *UTC"* : + + [![Dashboard timezone setting](img/9079254cc7f9fbc13ee5005765608b59.png)](img/dashboard_local_timezone_v13_1.png) + +4. Click **保存更改**. + +## Link to an external dashboard[](#link-to-an-external-dashboard "Permalink") + +在 GitLab 12.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/57171) . + +您可以在监视仪表板上添加一个按钮,该按钮直接链接到现有的外部仪表板: + +1. 以具有"管理项目操作" [权限](../../permissions.html)的用户身份登录. +2. 导航 **设置>操作** ,然后滚动到" **指标仪表板"** . +3. 在**外部仪表板 URL 中** ,提供您的外部仪表板的 URL: + + [![External Dashboard Setting](img/3da5d65194b00f9dc3ffde2ac5f8473b.png)](img/dashboard_external_link_v13_1.png) + +4. Click **保存更改**. + +GitLab 在[监视仪表板的](../../../ci/environments/index.html#monitoring-environments)右上角显示一个" **查看完整的仪表板"**按钮,该按钮可打开您提供的 URL: + +[![External Dashboard Link](img/ddc1b7f5f622e5c8f6581738b42964cb.png)](img/external_dashboard_link.png) \ No newline at end of file diff --git a/_book/docs/182.md b/_book/docs/182.md new file mode 100644 index 0000000000000000000000000000000000000000..3219ca57d990e9b1774d34c5f122f52c233712e0 --- /dev/null +++ b/_book/docs/182.md @@ -0,0 +1,268 @@ +# Panel types for dashboards + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/dashboards/panel_types.html](https://docs.gitlab.com/ee/operations/metrics/dashboards/panel_types.html) + +* [Area or Line Chart](#area-or-line-chart) +* [Anomaly chart](#anomaly-chart) +* [Bar chart](#bar-chart) +* [Column chart](#column-chart) +* [Stacked column](#stacked-column) +* [Single Stat](#single-stat) +* [Percentile based results](#percentile-based-results) +* [Heatmaps](#heatmaps) + +# Panel types for dashboards[](#panel-types-for-dashboards "Permalink") + +监视仪表板中支持以下面板类型. + +## Area or Line Chart[](#area-or-line-chart "Permalink") + +要将面积图面板类型添加到仪表盘,请查看以下样本仪表盘文件: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group Title' + panels: + - type: area-chart # or line-chart + title: 'Area Chart Title' + y_label: "Y-Axis" + y_axis: + format: number + precision: 0 + metrics: + - id: area_http_requests_total + query_range: 'http_requests_total' + label: "Instance: {{instance}}, Method: {{method}}" + unit: "count" +``` + +请注意以下属性: + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| type | string | no | 要渲染的面板类型. 区域面板类型的可选 | +| query_range | string | required | 对于区域面板类型,必须使用[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) | + +[![area panel chart](img/adf6de6d0c4125be4e7a25119c0193e1.png)](../../../user/project/integrations/img/prometheus_dashboard_area_panel_type_v12_8.png) + +从[版本 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/202696)开始,y 轴值将根据数据自动缩放. 以前,它总是从 0 开始. + +## Anomaly chart[](#anomaly-chart "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16530) . + +要将异常图表面板类型添加到仪表盘,请添加*恰好具有* 3 个指标的面板. + +第一个指标代表当前状态,第二个和第三个指标分别代表上限和下限: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group Title' + panels: + - type: anomaly-chart + title: "Chart Title" + y_label: "Y-Axis" + metrics: + - id: anomaly_requests_normal + query_range: 'http_requests_total' + label: "# of Requests" + unit: "count" + metrics: + - id: anomaly_requests_upper_limit + query_range: 10000 + label: "Max # of requests" + unit: "count" + metrics: + - id: anomaly_requests_lower_limit + query_range: 2000 + label: "Min # of requests" + unit: "count" +``` + +请注意以下属性: + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| type | string | required | 异常面板类型必须为`anomaly-chart` | +| query_range | yes | required | 对于异常面板类型,必须在每个指标中使用[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) . | + +[![anomaly panel type](img/8a4af39c416005af074623092e32d782.png)](../../../user/project/integrations/img/prometheus_dashboard_anomaly_panel_type.png) + +## Bar chart[](#bar-chart "Permalink") + +要将条形图添加到仪表板,请查看以下样本仪表板文件: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group title' + panels: + - type: bar + title: "Http Handlers" + x_label: 'Response Size' + y_axis: + name: "Handlers" + metrics: + - id: prometheus_http_response_size_bytes_bucket + query_range: "sum(increase(prometheus_http_response_size_bytes_bucket[1d])) by (handler)" + unit: 'Bytes' +``` + +请注意以下属性: + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | string | yes | 要渲染的面板类型. 对于条形图类型,设置为`bar` | +| `query_range` | yes | yes | 对于条形图,必须使用[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) | + +[![bar chart panel type](img/c61ac95a0fe55d92ab3c711ea814a8c8.png)](../../../user/project/integrations/img/prometheus_dashboard_bar_chart_panel_type_v12.10.png) + +## Column chart[](#column-chart "Permalink") + +要将列面板类型添加到仪表板,请查看以下样本仪表板文件: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group title' + panels: + - title: "Column" + type: "column" + metrics: + - id: 1024_memory + query: 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024' + unit: MB + label: "Memory Usage" +``` + +请注意以下属性: + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| type | string | yes | 要渲染的面板类型. 对于列面板类型,设置为`column` | +| query_range | yes | yes | 对于列面板类型,必须使用[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) | + +[![anomaly panel type](img/468eb44e935f615292705e2fc013ddb7.png)](../../../user/project/integrations/img/prometheus_dashboard_column_panel_type.png) + +## Stacked column[](#stacked-column "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30583) . + +要将堆叠的列面板类型添加到仪表板,请查看以下样本仪表板文件: + +``` +dashboard: 'Dashboard title' +priority: 1 +panel_groups: + - group: 'Group Title' + priority: 5 + panels: + - type: 'stacked-column' + title: "Stacked column" + y_label: "y label" + x_label: 'x label' + metrics: + - id: memory_1 + query_range: 'memory_query' + label: "memory query 1" + unit: "count" + series_name: 'group 1' + - id: memory_2 + query_range: 'memory_query_2' + label: "memory query 2" + unit: "count" + series_name: 'group 2' +``` + +[![stacked column panel type](img/62313a9f27e05c60c700ec9625e27d02.png)](../../../user/project/integrations/img/prometheus_dashboard_stacked_column_panel_type_v12_8.png) + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | string | yes | 要渲染的面板类型. 对于堆叠式柱面板类型,设置为" `stacked-column` | +| `query_range` | yes | yes | 对于堆叠式列面板类型,必须使用[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) | + +## Single Stat[](#single-stat "Permalink") + +要将单个状态面板类型添加到仪表板,请查看以下样本仪表板文件: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group Title' + panels: + - title: "Single Stat" + type: "single-stat" + metrics: + - id: 10 + query: 'max(go_memstats_alloc_bytes{job="prometheus"})' + unit: MB + label: "Total" +``` + +请注意以下属性: + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| type | string | yes | 要渲染的面板类型. 对于单一统计信息面板类型,设置为`single-stat` | +| field | string | no | 面板显示指标的值. 要使面板显示标签的值,请在该键中放置标签的名称. | +| query | string | yes | For single stat panel types, you must use an [instant query](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) | + +[![single stat panel type](img/51902d01ed097ad499a4e6eb984d3e86.png)](../../../user/project/integrations/img/prometheus_dashboard_single_stat_panel_type.png) + +## Percentile based results[](#percentile-based-results "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/201946) . + +有时需要将查询结果表示为 100 中的百分比值.您可以在面板定义的根部使用`max_value`属性: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group Title' + panels: + - title: "Single Stat" + type: "single-stat" + max_value: 100 + metrics: + - id: 10 + query: 'max(go_memstats_alloc_bytes{job="prometheus"})' + unit: '%' + label: "Total" +``` + +例如,如果查询值为`53.6` ,则将`%`添加为单位将得出`53.6%`的单个统计值,但是如果查询的最大期望值为`120` ,则该值为`44.6%` . 添加`max_value`会导致显示正确的百分比值. + +## Heatmaps[](#heatmaps "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30581) . + +要将热图面板类型添加到仪表板,请查看以下样本仪表板文件: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group Title' + panels: + - title: "Heatmap" + type: "heatmap" + metrics: + - id: 10 + query: 'sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[60m])) by (status_code)' + unit: req/sec + label: "Status code" +``` + +请注意以下属性: + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| type | string | yes | 要渲染的面板类型. 对于热图面板类型,设置为`heatmap` | +| query_range | yes | yes | 对于区域面板类型,必须使用[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) | + +[![heatmap panel type](img/10fd27d874d8e6ace6b74801909782ae.png)](../../../user/project/integrations/img/heatmap_panel_type.png) + +**警告:**当查询返回太多数据点时,热图数据桶的尺寸趋于向下至 0,从而使图表的数据不可见,如下图所示. 要解决此问题,请通过更改指标仪表板 UI 上的时间范围过滤器,或将**step**属性添加到仪表板的 YAML 文件中,来限制返回的数据量. + +[![heatmap chart_too_much_data](img/c89e56a24555efe89bb446cf31b5f764.png)](../../../user/project/integrations/img/heatmap_chart_too_much_data_v_13_2.png) \ No newline at end of file diff --git a/_book/docs/183.md b/_book/docs/183.md new file mode 100644 index 0000000000000000000000000000000000000000..b420a17043d07b6866fd392de6bd78395c1bcc05 --- /dev/null +++ b/_book/docs/183.md @@ -0,0 +1,55 @@ +# Using Variables + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/dashboards/variables.html](https://docs.gitlab.com/ee/operations/metrics/dashboards/variables.html) + +* [Query Variables](#query-variables) +* [Predefined variables](#predefined-variables) + * [__range](#__range) +* [User-defined variables](#user-defined-variables) +* [Query Variables from URL](#query-variables-from-url) + +# Using Variables[](#using-variables "Permalink") + +## Query Variables[](#query-variables "Permalink") + +可以使用双花括号来指定变量,例如`"{{ci_environment_slug}}"` (在 GitLab 12.7 中已[添加](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20793) ). + +在 GitLab 13.0 中[删除](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31581)了对`"%{ci_environment_slug}"`格式的支持. 继续使用旧格式的查询将不会显示任何数据. + +## Predefined variables[](#predefined-variables "Permalink") + +GitLab 在 Prometheus 查询中支持一组有限的[CI 变量](../../../ci/variables/README.html) . 这对于标识特定环境(例如`ci_environment_slug` )特别有用. 支持的变量是: + +* `ci_environment_slug` +* `kube_namespace` +* `ci_project_name` +* `ci_project_namespace` +* `ci_project_path` +* `ci_environment_name` +* `__range` + +**注意:** Prometheus 查询的变量必须小写. + +### __range[](#__range "Permalink") + +`__range`变量在 Prometheus [范围向量选择器中](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/basics/)很有用. 它的值是仪表板时间范围内的总秒数. 例如,如果仪表板时间范围设置为 8 小时,则`__range`值为`28800s` . + +## User-defined variables[](#user-defined-variables "Permalink") + +[可以](../../../operations/metrics/dashboards/yaml.html#templating-templating-properties)在自定义仪表板 YAML 文件中[定义变量](../../../operations/metrics/dashboards/yaml.html#templating-templating-properties) . + +## Query Variables from URL[](#query-variables-from-url "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214500) . + +GitLab 支持通过 URL 参数设置自定义变量. 用双花括号( `{{example}}` )包围变量名称,以在查询中插入变量: + +``` +avg(sum(container_memory_usage_bytes{container_name!="{{pod}}"}) by (job)) without (job) /1024/1024/1024' +``` + +该查询的 URL 为: + +``` +http://gitlab.com/<user>/<project>/-/environments/<environment_id>/metrics?dashboard=.gitlab%2Fdashboards%2Fcustom.yml&pod=POD +``` \ No newline at end of file diff --git a/_book/docs/184.md b/_book/docs/184.md new file mode 100644 index 0000000000000000000000000000000000000000..1f86ab43d4259275ac428e1694f3c2d9096ecc19 --- /dev/null +++ b/_book/docs/184.md @@ -0,0 +1,112 @@ +# Templating variables for metrics dashboards + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/dashboards/templating_variables.html](https://docs.gitlab.com/ee/operations/metrics/dashboards/templating_variables.html) + +* [`text` variable type](#text-variable-type) + * [Simple syntax](#simple-syntax) + * [Full syntax](#full-syntax) +* [`custom` variable type](#custom-variable-type) + * [Simple syntax](#simple-syntax-1) + * [Full syntax](#full-syntax-1) +* [`metric_label_values` variable type](#metric_label_values-variable-type) + * [Full syntax](#full-syntax-2) + +# Templating variables for metrics dashboards[](#templating-variables-for-metrics-dashboards "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214539) . + +模板变量可用于使指标仪表板更加通用. + +`templating`是[仪表板 YAML 中](yaml.html#dashboard-top-level-properties)的顶级键. 在`templating`下的`variables`键中定义变量. `variables`键的值应为哈希, `variables`下的每个键在仪表板上定义一个模板变量,并且可以包含字母数字和下划线字符. + +可以使用[使用变量中](variables.html)所述的语法在同一仪表板的 Prometheus 查询[中使用变量](variables.html) . + +## `text` variable type[](#text-variable-type "Permalink") + +**警告:**此变量类型是*alpha*功能,如有更改,恕不另行通知! + +对于仪表板 YAML 中定义的每个`text`变量,仪表板 UI 上都会有一个自由文本框,您可以为每个变量输入一个值. + +`text`变量类型支持简单和完整的语法. + +### Simple syntax[](#simple-syntax "Permalink") + +本示例创建一个名为`variable1` ,其默认值为`default value` : + +``` +templating: + variables: + variable1: 'default value' # `text` type variable with `default value` as its default. +``` + +### Full syntax[](#full-syntax "Permalink") + +本示例创建一个名为`variable1` ,其默认值为`default` . UI 上文本框的标签将为`label`键的值: + +``` +templating: + variables: + variable1: # The variable name that can be used in queries. + label: 'Variable 1' # (Optional) label that will appear in the UI for this text box. + type: text + options: + default_value: 'default' # (Optional) default value. +``` + +## `custom` variable type[](#custom-variable-type "Permalink") + +**警告:**此变量类型是*alpha*功能,如有更改,恕不另行通知! + +仪表板 YAML 中定义的每个`custom`变量都会在仪表板 UI 上创建一个下拉选择器,允许您为每个变量选择一个值. + +`custom`变量类型支持简单和完整的语法. + +### Simple syntax[](#simple-syntax-1 "Permalink") + +本示例创建一个名为`variable1` ,其默认值为`value1` . 仪表板界面将显示一个下拉列表,其中包含`value1` , `value2`和`value3`作为选择. + +``` +templating: + variables: + variable1: ['value1', 'value2', 'value3'] +``` + +### Full syntax[](#full-syntax-1 "Permalink") + +本示例创建一个名为`variable1` ,其默认值为`value_option_2` . UI 上文本框的标签将为`label`键的值. 仪表板界面将显示一个下拉列表,其中包含`Option 1`和`Option 2` . + +如果从下拉列表中选择`Option 1` ,则变量将被替换为`value option 1` . 同样,如果选择`Option 2` ,则变量将替换为`value_option_2` : + +``` +templating: + variables: + variable1: # The variable name that can be used in queries. + label: 'Variable 1' # (Optional) label that will appear in the UI for this dropdown. + type: custom + options: + values: + - value: 'value option 1' # The value that will replace the variable in queries. + text: 'Option 1' # (Optional) Text that will appear in the UI dropdown. + - value: 'value_option_2' + text: 'Option 2' + default: true # (Optional) This option should be the default value of this variable. +``` + +## `metric_label_values` variable type[](#metric_label_values-variable-type "Permalink") + +**警告:**此变量类型是*alpha*功能,如有更改,恕不另行通知! + +### Full syntax[](#full-syntax-2 "Permalink") + +本示例创建一个名为`variable2` . 下拉列表的值将是`up{env="production"}`描述的 Prometheus 系列中`backend`标签的所有不同值. + +``` +templating: + variables: + variable2: # The variable name that can be interpolated in queries. + label: 'Variable 2' # (Optional) label that will appear in the UI for this dropdown. + type: metric_label_values + options: + series_selector: 'up{env="production"}' + label: 'backend' +``` \ No newline at end of file diff --git a/_book/docs/185.md b/_book/docs/185.md new file mode 100644 index 0000000000000000000000000000000000000000..794c0445f98fbe1d89008d1410849bde93fb60f8 --- /dev/null +++ b/_book/docs/185.md @@ -0,0 +1,31 @@ +# Prometheus Metrics library + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/) + +* [Exporters](#exporters) +* [Identifying Environments](#identifying-environments) + +# Prometheus Metrics library[](#prometheus-metrics-library "Permalink") + +在 GitLab 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8935) . + +GitLab 可自动检测某些[Prometheus 出口商](https://s0prometheus0io.icopy.site/docs/instrumenting/exporters/) . + +## Exporters[](#exporters "Permalink") + +当前支持的出口商是: + +* [Kubernetes](kubernetes.html) +* [NGINX](nginx.html) +* [NGINX Ingress Controller 0.9.0-0.15.x](nginx_ingress_vts.html) +* [NGINX Ingress Controller 0.16.0+](nginx_ingress.html) +* [HAProxy](haproxy.html) +* [Amazon Cloud Watch](cloudwatch.html) + +我们已尝试为每个出口商展示最重要的指标,并将在以后的版本中继续增加对其他出口商的支持. 如果您想增加对其他官方出口商的支持,欢迎捐款. + +## Identifying Environments[](#identifying-environments "Permalink") + +GitLab 从已配置的 Prometheus 服务器检索性能数据,并尝试识别已知指标的存在. 一旦确定,GitLab 然后需要能够将数据映射到特定环境. + +为了隔离并仅显示给定环境的相关指标,GitLab 需要一种方法来检测关联了哪些标签. 为此,GitLab 使用已定义的查询并填写特定于环境的变量. 通常,这涉及寻找[`$CI_ENVIRONMENT_SLUG`](../../../../ci/variables/README.html#predefined-environment-variables) ,但也可能包括其他信息,例如项目的 Kubernetes 命名空间. 每个搜索查询都在[导出器特定的文档中](#exporters)定义. \ No newline at end of file diff --git a/_book/docs/186.md b/_book/docs/186.md new file mode 100644 index 0000000000000000000000000000000000000000..b4e4bf99e20d85eb2d1a9efe4d86b786c786d30e --- /dev/null +++ b/_book/docs/186.md @@ -0,0 +1,38 @@ +# Monitoring AWS Resources + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/cloudwatch.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/cloudwatch.html) + +* [Requirements](#requirements) +* [Metrics supported](#metrics-supported) +* [Configuring Prometheus to monitor for Cloudwatch metrics](#configuring-prometheus-to-monitor-for-cloudwatch-metrics) +* [Specifying the Environment label](#specifying-the-environment-label) + +# Monitoring AWS Resources[](#monitoring-aws-resources "Permalink") + +在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12621) + +GitLab 支持从[Elastic Load Balancer](https://aws.amazon.com/elasticloadbalancing/)开始自动检测和监视 AWS 资源. 这是通过利用官方[Cloudwatch 导出程序提供的](https://github.com/prometheus/cloudwatch_exporter) ,该程序将[Cloudwatch 指标](https://aws.amazon.com/cloudwatch/)转换为 Prometheus 可读形式. + +## Requirements[](#requirements "Permalink") + +必须启用[Prometheus 服务](../prometheus.html) . + +## Metrics supported[](#metrics-supported "Permalink") + +| Name | Query | +| --- | --- | +| 吞吐量(要求/秒) | `sum(aws_elb_request_count_sum{%{environment_filter}}) / 60` | +| 延迟(毫秒) | `avg(aws_elb_latency_average{%{environment_filter}}) * 1000` | +| HTTP 错误率(%) | `sum(aws_elb_httpcode_backend_5_xx_sum{%{environment_filter}}) / sum(aws_elb_request_count_sum{%{environment_filter}})` | + +## Configuring Prometheus to monitor for Cloudwatch metrics[](#configuring-prometheus-to-monitor-for-cloudwatch-metrics "Permalink") + +要开始使用 Cloudwatch 监控,您应该安装和配置[Cloudwatch 导出程序](https://github.com/prometheus/cloudwatch_exporter) ,该程序可检索和解析指定的 Cloudwatch 指标并将其转换为 Prometheus 监控端点. + +目前,唯一受支持的 AWS 资源是 Elastic Load Balancer,其 Cloudwatch 指标在[此处记录](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-cloudwatch-metrics.html) . + +样品的 CloudWatch 导出配置文件,配置用于基本 AWS ELB 监测,是[可供下载](../samples/cloudwatch.yml) . + +## Specifying the Environment label[](#specifying-the-environment-label "Permalink") + +为了隔离并仅显示给定环境的相关指标,GitLab 需要一种方法来检测关联了哪些标签. 为此,GitLab 将[查找`environment`标签](index.html#identifying-environments) . \ No newline at end of file diff --git a/_book/docs/187.md b/_book/docs/187.md new file mode 100644 index 0000000000000000000000000000000000000000..9427da48d5e8744eddaeb1091b46399b4e7a6b89 --- /dev/null +++ b/_book/docs/187.md @@ -0,0 +1,33 @@ +# Monitoring HAProxy + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/haproxy.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/haproxy.html) + +* [Requirements](#requirements) +* [Metrics supported](#metrics-supported) +* [Configuring Prometheus to monitor for HAProxy metrics](#configuring-prometheus-to-monitor-for-haproxy-metrics) +* [Specifying the Environment label](#specifying-the-environment-label) + +# Monitoring HAProxy[](#monitoring-haproxy "Permalink") + +在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12621) + +GitLab 支持自动检测和监视 HAProxy. 这是通过利用[HAProxy Exporter](https://github.com/prometheus/haproxy_exporter)来提供的,后者将 HAProxy 统计信息转换为 Prometheus 可读形式. + +## Requirements[](#requirements "Permalink") + +必须启用[Prometheus 服务](../prometheus.html) . + +## Metrics supported[](#metrics-supported "Permalink") + +| Name | Query | +| --- | --- | +| 吞吐量(要求/秒) | `sum(rate(haproxy_frontend_http_requests_total{%{environment_filter}}[2m])) by (code)` | +| HTTP 错误率(%) | `sum(rate(haproxy_frontend_http_requests_total{code="5xx",%{environment_filter}}[2m])) / sum(rate(haproxy_frontend_http_requests_total{%{environment_filter}}[2m]))` | + +## Configuring Prometheus to monitor for HAProxy metrics[](#configuring-prometheus-to-monitor-for-haproxy-metrics "Permalink") + +要开始使用 NGINX 监视,您应该安装并配置[HAProxy 导出程序](https://github.com/prometheus/haproxy_exporter) ,该程序可以解析这些统计信息并将其转换为 Prometheus 监视端点. + +## Specifying the Environment label[](#specifying-the-environment-label "Permalink") + +为了隔离并仅显示给定环境的相关指标,GitLab 需要一种方法来检测关联了哪些标签. 为此,GitLab 将[查找`environment`标签](index.html#identifying-environments) . \ No newline at end of file diff --git a/_book/docs/188.md b/_book/docs/188.md new file mode 100644 index 0000000000000000000000000000000000000000..5cfdd39487d7e51c41be7e1c2b13db3c1fafeb99 --- /dev/null +++ b/_book/docs/188.md @@ -0,0 +1,69 @@ +# Monitoring Kubernetes + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/kubernetes.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/kubernetes.html) + +* [Requirements](#requirements) +* [Metrics supported](#metrics-supported) +* [Configuring Prometheus to monitor for Kubernetes metrics](#configuring-prometheus-to-monitor-for-kubernetes-metrics) +* [Specifying the Environment](#specifying-the-environment) +* [Displaying Canary metrics](#displaying-canary-metrics-premium) + * [Canary metrics supported](#canary-metrics-supported) + +# Monitoring Kubernetes[](#monitoring-kubernetes "Permalink") + +在 GitLab 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8935) . + +GitLab 支持自动检测和监视 Kubernetes 指标. + +## Requirements[](#requirements "Permalink") + +必须启用[Prometheus](../prometheus.html)和[Kubernetes](../kubernetes.html)集成服务. + +## Metrics supported[](#metrics-supported "Permalink") + +* 平均内存使用量(MB): + + ``` + avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024 + ``` + +* 平均 CPU 使用率(%): + + ``` + avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job) / count(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}[15m])) by (pod_name)) + ``` + +## Configuring Prometheus to monitor for Kubernetes metrics[](#configuring-prometheus-to-monitor-for-kubernetes-metrics "Permalink") + +为了收集 Kubernetes 指标,需要将 Prometheus 部署到集群中并进行正确配置. GitLab 支持两种方法: + +* GitLab [与 Kubernetes 集成](../../clusters/index.html) ,并且可以[将 Prometheus 部署到连接的集群中](../prometheus.html#managed-prometheus-on-kubernetes) . 它被自动配置为收集 Kubernetes 指标. +* 要配置自己的 Prometheus 服务器,可以遵循[Prometheus 文档](https://s0prometheus0io.icopy.site/docs/introduction/overview/) . + +## Specifying the Environment[](#specifying-the-environment "Permalink") + +为了隔离并仅显示给定环境的相关 CPU 和内存指标,GitLab 需要一种方法来检测其正在运行的容器. 由于这些指标是在容器级别跟踪的,因此传统的 Kubernetes 标签不可用. + +相反, [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)或[DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/)名称应以[CI_ENVIRONMENT_SLUG 开头](../../../../ci/variables/README.html#predefined-environment-variables) . 如果需要,可以在其后跟一个`-`和其他内容. 例如, `review-homepage-5620p5`的部署名称将与`review/homepage`环境匹配. + +## Displaying Canary metrics[](#displaying-canary-metrics-premium "Permalink") + +在[GitLab 10.2 中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15201)引入. + +GitLab 还收集了针对[Canary 部署的](../../canary_deployments.html) Kubernetes 指标,从而可以轻松比较当前部署的版本和 Canary. + +这些度量标准期望[Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)或[DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/)名称以`$CI_ENVIRONMENT_SLUG-canary`开头,以隔离 canary 度量标准. + +### Canary metrics supported[](#canary-metrics-supported "Permalink") + +* 平均内存使用量(MB) + + ``` + avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024 + ``` + +* 平均 CPU 使用率(%) + + ``` + avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job) / count(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}[15m])) by (pod_name)) + ``` \ No newline at end of file diff --git a/_book/docs/189.md b/_book/docs/189.md new file mode 100644 index 0000000000000000000000000000000000000000..b79baafb0a4df2c97bb2a2fcb2e3d86a386b2121 --- /dev/null +++ b/_book/docs/189.md @@ -0,0 +1,39 @@ +# Monitoring NGINX + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx.html) + +* [Requirements](#requirements) +* [Metrics supported](#metrics-supported) +* [Configuring Prometheus to monitor for NGINX metrics](#configuring-prometheus-to-monitor-for-nginx-metrics) +* [Specifying the Environment label](#specifying-the-environment-label) + +# Monitoring NGINX[](#monitoring-nginx "Permalink") + +在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12621) + +GitLab 支持自动检测和监视 NGINX. 这是通过利用[NGINX VTS 导出器提供的](https://github.com/hnlq715/nginx-vts-exporter) ,该[导出](https://github.com/hnlq715/nginx-vts-exporter)器将[VTS 统计信息](https://github.com/vozlt/nginx-module-vts)转换为 Prometheus 可读形式. + +## Requirements[](#requirements "Permalink") + +必须启用[Prometheus 服务](../prometheus.html) . + +## Metrics supported[](#metrics-supported "Permalink") + +检测到 NGINX 服务器指标,该指标跟踪 NGINX 直接提供的页面和内容. + +| Name | Query | +| --- | --- | +| 吞吐量(要求/秒) | `sum(rate(nginx_server_requests{server_zone!="*", server_zone!="_", %{environment_filter}}[2m])) by (code)` | +| 延迟(毫秒) | `avg(nginx_server_requestMsec{%{environment_filter}})` | +| HTTP 错误率(HTTP 错误/秒) | `sum(rate(nginx_server_requests{code="5xx", %{environment_filter}}[2m]))` | +| HTTP 错误(%) | `sum(rate(nginx_server_requests{code=~"5.*", host="*", %{environment_filter}}[2m])) / sum(rate(nginx_server_requests{code="total", host="*", %{environment_filter}}[2m])) * 100` | + +## Configuring Prometheus to monitor for NGINX metrics[](#configuring-prometheus-to-monitor-for-nginx-metrics "Permalink") + +要开始使用 NGINX 监视,您应该首先为 NGINX 服务器启用[VTS 统计](https://github.com/vozlt/nginx-module-vts)模块. 这将捕获并以 HTML 可读形式显示统计信息. 接下来,您应该安装并配置[NGINX VTS 导出器](https://github.com/hnlq715/nginx-vts-exporter) ,该[导出器](https://github.com/hnlq715/nginx-vts-exporter)将解析这些统计信息并将其转换为 Prometheus 监视端点. + +如果您将 NGINX 用作 Kubernetes 入口,GitLab 将在 0.9.0 及更高版本中启用后[自动检测](nginx_ingress.html)指标. + +## Specifying the Environment label[](#specifying-the-environment-label "Permalink") + +为了隔离并仅显示给定环境的相关指标,GitLab 需要一种方法来检测关联了哪些标签. 为此,GitLab 将[查找`environment`标签](index.html#identifying-environments) . \ No newline at end of file diff --git a/_book/docs/190.md b/_book/docs/190.md new file mode 100644 index 0000000000000000000000000000000000000000..9a8391d0e5fe4608652337ab41412ee1a93d3b15 --- /dev/null +++ b/_book/docs/190.md @@ -0,0 +1,69 @@ +# Monitoring NGINX Ingress Controller + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx_ingress.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx_ingress.html) + +* [Requirements](#requirements) +* [Metrics supported](#metrics-supported) +* [Configuring NGINX Ingress monitoring](#configuring-nginx-ingress-monitoring) + * [About managed NGINX Ingress deployments](#about-managed-nginx-ingress-deployments) + * [Manually setting up NGINX Ingress for Prometheus monitoring](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) +* [Specifying the Environment label](#specifying-the-environment-label) + +# Monitoring NGINX Ingress Controller[](#monitoring-nginx-ingress-controller "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22133) . + +**注意:** 0.16.0 之前的 NGINX Ingress 版本提供了一个随附的[VTS Prometheus 指标导出器](nginx_ingress_vts.html) ,该导出器导出的指标与内置指标不同. + +GitLab 支持自动检测和监视 Kubernetes NGINX Ingress 控制器. 这是通过利用 Kubernetes NGINX Ingress 控制器[版本 0.16.0](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#0160)及更高[版本随附](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#0160)的内置 Prometheus 指标来提供的. + +## Requirements[](#requirements "Permalink") + +[Prometheus integration](../prometheus.html) must be active. + +## Metrics supported[](#metrics-supported "Permalink") + +| Name | Query | +| --- | --- | +| 吞吐量(要求/秒) | `sum(label_replace(rate(nginx_ingress_controller_requests{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m]), "status_code", "${1}xx", "status", "(.)..")) by (status_code)` | +| 延迟(毫秒) | `sum(rate(nginx_ingress_controller_ingress_upstream_latency_seconds_sum{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) / sum(rate(nginx_ingress_controller_ingress_upstream_latency_seconds_count{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) * 1000` | +| HTTP 错误率(%) | `sum(rate(nginx_ingress_controller_requests{status=~"5.*",namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) / sum(rate(nginx_ingress_controller_requests{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) * 100` | + +## Configuring NGINX Ingress monitoring[](#configuring-nginx-ingress-monitoring "Permalink") + +如果您已经使用 GitLab 的[Kubernetes 集群集成](../../clusters/index.html#installing-applications)部署了 NGINX Ingress,则 Prometheus 将[自动对其进行监视](#about-managed-nginx-ingress-deployments) . + +对于其他部署,需要根据您的安装进行[一些配置](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) : + +* NGINX Ingress 的版本应为 0.16.0 或更高,并启用指标. +* NGINX Ingress 应该标注为 Prometheus 监视. +* Prometheus 应该配置为监视带注释的容器. + +### About managed NGINX Ingress deployments[](#about-managed-nginx-ingress-deployments "Permalink") + +使用[官方 Helm 图表将](https://github.com/helm/charts/tree/master/stable/nginx-ingress) NGINX Ingress 部署到`gitlab-managed-apps`命名空间中. NGINX Ingress 将[通过 Load Balancer 的 Endpoint](../../../clusters/applications.html#ingress)在[外部访问](../../../clusters/applications.html#ingress) . + +通过设置以下内容,将 NGINX 配置为进行 Prometheus 监视: + +* `enable-vts-status: "true"` ,以导出 Prometheus 指标. +* `prometheus.io/scrape: "true"` ,以启用自动发现. +* `prometheus.io/port: "10254"` ,以指定度量标准端口. + +与 GitLab 部署的 Prometheus 服务结合使用时,将自动收集响应指标. + +### Manually setting up NGINX Ingress for Prometheus monitoring[](#manually-setting-up-nginx-ingress-for-prometheus-monitoring "Permalink") + +[NGINX Ingress 的](https://github.com/kubernetes/ingress-nginx) 0.9.0 及更高版本具有对导出 Prometheus 指标的内置支持. 要启用,必须传递 ConfigMap 设置: `enable-vts-status: "true"` . 启用后,Prometheus 指标端点将开始在端口 10254 上运行. + +接下来,需要对 Ingress 进行注释,以进行 Prometheus 监视. 需要添加两个新的注释: + +* `prometheus.io/scrape: "true"` +* `prometheus.io/port: "10254"` + +管理这些设置取决于如何部署 NGINX Ingress. 如果您通过[官方 Helm 图表](https://github.com/helm/charts/tree/master/stable/nginx-ingress)进行了部署,则可以使用`controller.stats.enabled`以及所需的注释来启用指标. 另外,也可以直接在[Kubernetes 仪表板中](https://github.com/kubernetes/dashboard)编辑 NGINX Ingress YML. + +## Specifying the Environment label[](#specifying-the-environment-label "Permalink") + +为了隔离并仅显示给定环境的相关指标,GitLab 需要一种方法来检测关联了哪些标签. 为此,GitLab 将搜索带有适当标签的指标. 在这种情况下, `ingress`标签必须为`<CI_ENVIRONMENT_SLUG>` . + +如果您使用[自动部署](../../../../topics/autodevops/stages.html#auto-deploy)来部署您的应用程序,则将自动使用此格式,并且无需您执行任何操作即可检测到指标. \ No newline at end of file diff --git a/_book/docs/191.md b/_book/docs/191.md new file mode 100644 index 0000000000000000000000000000000000000000..8b58916146bcc045dc767c60aca28edb448642b7 --- /dev/null +++ b/_book/docs/191.md @@ -0,0 +1,69 @@ +# Monitoring NGINX Ingress Controller with VTS metrics + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx_ingress_vts.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx_ingress_vts.html) + +* [Requirements](#requirements) +* [Metrics supported](#metrics-supported) +* [Configuring NGINX Ingress monitoring](#configuring-nginx-ingress-monitoring) + * [About managed NGINX Ingress deployments](#about-managed-nginx-ingress-deployments) + * [Manually setting up NGINX Ingress for Prometheus monitoring](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) +* [Specifying the Environment label](#specifying-the-environment-label) + +# Monitoring NGINX Ingress Controller with VTS metrics[](#monitoring-nginx-ingress-controller-with-vts-metrics "Permalink") + +在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13438) . + +**注意:** [NGINX Ingress 版本 0.16](nginx_ingress.html)及更高[版本](nginx_ingress.html)具有内置的 Prometheus 度量标准,该度量标准与基于 VTS 的度量标准不同. + +GitLab 支持自动检测和监视 Kubernetes NGINX Ingress 控制器. 这是通过利用[版本 0.9.0](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#09-beta1)至[0.15.x 中](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#0150)随附的 VTS Prometheus 度量标准导出程序来[提供的](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#0150) . + +## Requirements[](#requirements "Permalink") + +[Prometheus 集成](../prometheus.html)必须处于活动状态. + +## Metrics supported[](#metrics-supported "Permalink") + +| Name | Query | +| --- | --- | +| 吞吐量(要求/秒) | `sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) by (status_code)` | +| 延迟(毫秒) | `avg(nginx_upstream_response_msecs_avg{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"})` | +| HTTP 错误率(%) | `sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) / sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) * 100` | + +## Configuring NGINX Ingress monitoring[](#configuring-nginx-ingress-monitoring "Permalink") + +如果您已经使用 GitLab 的[Kubernetes 集群集成](../../clusters/index.html#installing-applications)部署了 NGINX Ingress,则 Prometheus 将[自动对其进行监视](#about-managed-nginx-ingress-deployments) . + +对于其他部署,需要根据您的安装进行[一些配置](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) : + +* NGINX Ingress 的版本应为 0.9.0 或更高版本,并启用指标. +* NGINX Ingress 应该标注为 Prometheus 监视. +* Prometheus 应该配置为监视带注释的容器. + +### About managed NGINX Ingress deployments[](#about-managed-nginx-ingress-deployments "Permalink") + +NGINX Ingress is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress). NGINX Ingress will be [externally reachable via the Load Balancer’s Endpoint](../../../clusters/applications.html#ingress). + +通过设置以下内容,将 NGINX 配置为进行 Prometheus 监视: + +* `enable-vts-status: "true"` ,以导出 Prometheus 指标. +* `prometheus.io/scrape: "true"` ,以启用自动发现. +* `prometheus.io/port: "10254"` ,以指定度量标准端口. + +与 GitLab 部署的 Prometheus 服务结合使用时,将自动收集响应指标. + +### Manually setting up NGINX Ingress for Prometheus monitoring[](#manually-setting-up-nginx-ingress-for-prometheus-monitoring "Permalink") + +[NGINX Ingress 的](https://github.com/kubernetes/ingress-nginx) 0.9.0 及更高版本具有对导出 Prometheus 指标的内置支持. 要启用,必须传递 ConfigMap 设置: `enable-vts-status: "true"` . 启用后,Prometheus 指标端点将开始在端口 10254 上运行. + +接下来,需要对 Ingress 进行注释,以进行 Prometheus 监视. 需要添加两个新的注释: + +* `prometheus.io/scrape: "true"` +* `prometheus.io/port: "10254"` + +管理这些设置取决于如何部署 NGINX Ingress. 如果您通过[官方 Helm 图表](https://github.com/helm/charts/tree/master/stable/nginx-ingress)进行了部署,则可以使用`controller.stats.enabled`以及所需的注释来启用指标. 或者,也可以直接在[Kubernetes 仪表板中](https://github.com/kubernetes/dashboard)编辑 NGINX Ingress YAML. + +## Specifying the Environment label[](#specifying-the-environment-label "Permalink") + +为了隔离并仅显示给定环境的相关指标,GitLab 需要一种方法来检测关联了哪些标签. 为此,GitLab 将搜索带有适当标签的指标. 在这种情况下, `upstream`标签的格式必须为`<KUBE_NAMESPACE>-<CI_ENVIRONMENT_SLUG>-*` . + +如果您使用[自动部署](../../../../topics/autodevops/stages.html#auto-deploy)来部署您的应用程序,则将自动使用此格式,并且无需您执行任何操作即可检测到指标. \ No newline at end of file diff --git a/_book/docs/192.md b/_book/docs/192.md new file mode 100644 index 0000000000000000000000000000000000000000..57d5d45c9f055a3a52fd4402abef4f38dd48ee25 --- /dev/null +++ b/_book/docs/192.md @@ -0,0 +1,210 @@ +# Alert Management + +> 原文:[https://docs.gitlab.com/ee/user/project/operations/alert_management.html](https://docs.gitlab.com/ee/user/project/operations/alert_management.html) + +* [Enable Alert Management](#enable-alert-management) + * [Enable a Generic Alerts endpoint](#enable-a-generic-alerts-endpoint) + * [Enable GitLab-managed Prometheus alerts](#enable-gitlab-managed-prometheus-alerts) + * [Enable external Prometheus alerts](#enable-external-prometheus-alerts) +* [Alert Management severity](#alert-management-severity) +* [Alert Management list](#alert-management-list) + * [Alert Management list sorting](#alert-management-list-sorting) + * [Searching alerts](#searching-alerts) + * [Alert Management statuses](#alert-management-statuses) +* [Alert Management details](#alert-management-details) + * [Update an Alert’s status](#update-an-alerts-status) + * [Create an Issue from an Alert](#create-an-issue-from-an-alert) + * [Update an Alert’s assignee](#update-an-alerts-assignee) + * [Alert system notes](#alert-system-notes) + * [View an Alert’s metrics data](#view-an-alerts-metrics-data) +* [Use cases for assigning alerts](#use-cases-for-assigning-alerts) + * [Slack Notifications](#slack-notifications) + +# Alert Management[](#alert-management "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2877) . + +警报管理使开发人员可以轻松发现和查看其应用程序生成的警报. 通过在开发代码的地方显示警报信息,可以提高效率和知名度. + +## Enable Alert Management[](#enable-alert-management "Permalink") + +**注意:**您至少需要维护者[权限](../../permissions.html)才能启用警报管理功能. + +如下所述,有几种方法可以将警报接受到您的 GitLab 项目中. 启用任何这些方法将允许显示警报列表. 配置警报后,访问 您可以在项目的边栏中[查看](#alert-management-list) **操作>警报** ,以[查看](#alert-management-list)警报[列表](#alert-management-list) . + +### Enable a Generic Alerts endpoint[](#enable-a-generic-alerts-endpoint "Permalink") + +GitLab 提供了通用警报端点,因此您可以接受来自第三方警报服务的警报. 请参阅有关[切换常规警报](../integrations/generic_alerts.html#setting-up-generic-alerts)的[说明](../integrations/generic_alerts.html#setting-up-generic-alerts)以添加此选项. 配置端点后,将启用" [警报"列表](#alert-management-list) . + +要用数据填充警报,请参阅为警报端点的请求[自定义有效负载](../integrations/generic_alerts.html#customizing-the-payload) . + +### Enable GitLab-managed Prometheus alerts[](#enable-gitlab-managed-prometheus-alerts "Permalink") + +您可以在 Kubernetes 集群上安装 GitLab 管理的 Prometheus 应用程序. 有关更多信息,请参见[Kubernetes 上的 Managed Prometheus](../integrations/prometheus.html#managed-prometheus-on-kubernetes) . 安装了由 GitLab 管理的 Prometheus 时,也会启用[警报列表](#alert-management-list) . + +要用数据填充警报,请参阅[GitLab 管理的 Prometheus 实例](../../../operations/metrics/index.html#managed-prometheus-instances) . + +### Enable external Prometheus alerts[](#enable-external-prometheus-alerts "Permalink") + +您可以配置外部管理的 Prometheus 实例,以将警报发送到 GitLab. 要设置此配置,请参阅[配置 Prometheus](../../../operations/metrics/index.html#external-prometheus-instances)文档. 激活外部 Prometheus 配置也会启用" [警报"列表](#alert-management-list) . + +要用数据填充警报,请参阅[外部 Prometheus 实例](../../../operations/metrics/index.html#external-prometheus-instances) . + +## Alert Management severity[](#alert-management-severity "Permalink") + +警报的每个级别均包含一个形状和颜色编码独特的图标,以帮助您确定特定警报的严重性. 这些严重性图标可帮助您立即确定应优先调查的警报: + +[![Alert Management Severity System](img/56eeecad0f9627fae21bc6b196391ba7.png)](img/alert_management_severity_v13_0.png) + +警报包含以下图标之一: + +| Severity | Icon | 颜色(十六进制) | +| --- | --- | --- | +| Critical | | `#8b2615` | +| High | | `#c0341d` | +| Medium | | `#fca429` | +| Low | | `#fdbc60` | +| Info | | `#418cd8` | +| Unknown | | `#bababa` | + +## Alert Management list[](#alert-management-list "Permalink") + +**注意:**您将至少需要具有开发人员[权限](../../permissions.html)才能查看警报管理列表. + +您可以在以下位置找到警报管理列表 项目侧边栏中的**操作>警报** . 每个警报包含以下指标: + +[![Alert Management List](img/c932281f198053757ebfaf5a9b99b335.png)](img/alert_list_v13_1.png) + +* **严重性** -警报的当前重要性及其应受到的关注. +* **开始时间** -警报触发前多久. 此字段使用`X time ago`的标准 GitLab 模式,但细化的日期/时间工具提示支持此字段,具体取决于用户的语言环境. +* **警报说明** - The description of the alert, which attempts to capture the most meaningful data. +* **事件计数** -警报触发的次数. +* **问题** -指向为警报创建的事件问题的链接. +* **状态** -警报的[当前状态](#alert-management-statuses) . + +### Alert Management list sorting[](#alert-management-list-sorting "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/217745) . + +警报管理列表显示按开始时间排序的警报,但是您可以通过单击警报管理列表中的标题来更改排序顺序. + +要查看列是否可排序,请将鼠标指向标题. 可排序的列在列名旁边显示一个箭头,如以下示例所示: + +[![Alert Management List Sorting](img/b46359f55df1f2affc4fe493965ebd0a.png)](img/alert_list_sort_v13_1.png) + +### Searching alerts[](#searching-alerts "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/213884) . + +警报列表支持简单的自由文本搜索. + +[![Alert List Search](img/cf0c5e15a3b44eb89d7513b961d6a274.png)](img/alert_list_search_v13_1.png) + +此搜索过滤以下字段: + +* Title +* Description +* 监控工具 +* Service + +### Alert Management statuses[](#alert-management-statuses "Permalink") + +每个警报都包含一个状态下拉列表,以指示需要调查的警报. 标准警报状态包括已`triggered` ,已`acknowledged`和已`resolved` : + +* **触发** :没有人开始调查. +* **致谢** :有人正在积极调查问题. +* **解决** :不需要进一步的工作. + +## Alert Management details[](#alert-management-details "Permalink") + +**注意:**您至少需要具有开发人员[权限](../../permissions.html)才能查看警报管理详细信息. + +通过访问[警报管理列表](#alert-management-list)并从列表中选择一个警报,导航到警报管理详细信息视图. + +[![Alert Management Detail Overview](img/fd15df8f9a5a46582845610e8b5881bb.png)](img/alert_detail_overview_v13_1.png) + +[![Alert Management Full Details](img/393dab24a6c8be1031a4cf469f3039e9.png)](img/alert_detail_full_v13_1.png) + +### Update an Alert’s status[](#update-an-alerts-status "Permalink") + +警报管理详细信息视图使您可以更新警报状态. 有关更多详细信息,请参见[警报管理状态](#alert-management-statuses) . + +### Create an Issue from an Alert[](#create-an-issue-from-an-alert "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/217745) . + +警报管理详细信息视图使您可以创建问题,并使用从警报自动填充的描述来创建问题. 要创建问题,请单击**创建问题**按钮. 然后,您可以通过单击**查看问题**按钮从警报中**查看问题** . + +关闭与警报相关的 GitLab 问题会将警报的状态更改为"已解决". 有关[状态](#alert-management-statuses)的更多详细信息,请参阅[警报管理](#alert-management-statuses)状态. + +### Update an Alert’s assignee[](#update-an-alerts-assignee "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/3066) . + +警报管理详细信息视图允许用户更新警报受让人. + +在大型团队中,共享警报的所有权,可能很难跟踪谁在调查和处理警报. 警报管理详细信息视图使您可以更新警报受让人: + +**注意:** manbetx 客户端打不开目前仅支持每个警报一个受让人. + +1. 要显示当前警报列表,请单击 **操作>警报** : + + [![Alert Management List View Assignee(s)](img/2ae8145aa44498bcadafa3451ee343b1.png)](img/alert_list_assignees_v13_1.png) + +2. 选择所需的警报以显示其**警报管理详细信息视图** : + + [![Alert Management Details View Assignee(s)](img/e80fdda43c295fbc39611b3d918d4b75.png)](img/alert_details_assignees_v13_1.png) + +3. 如果右侧栏没有展开,请单击 **展开侧边栏**以展开它. +4. 在右侧栏中,找到**受让人** ,然后点击**编辑** . 从下拉菜单中,选择要分配给警报的每个用户. GitLab 为每个用户创建一个[待办事项列表项](../../todos.html) . + + [![Alert Management Details View Assignee(s)](img/f7ae6b6be5d2dd02010825234555fee6.png)](img/alert_todo_assignees_v13_1.png) + +要删除受让人,请单击" **受让人"**下拉菜单旁边的" **编辑"** ,然后从**受让人**列表中取消选择该用户,或单击" **未分配"** . + +### Alert system notes[](#alert-system-notes "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/3066) . + +当您对警报采取措施时,它会记录为系统注释,在"警报详细信息"视图中可见. 这为您提供了警报调查和分配历史的线性时间表. + +以下操作将产生系统注释: + +* [Updating the status of an alert](#update-an-alerts-status) +* [Creating an issue based on an alert](#create-an-issue-from-an-alert) +* [Assignment of an alert to a user](#update-an-alerts-assignee) + +[![Alert Management Details View System Notes](img/b6f3d1302a444a29689905582d97eb84.png)](img/alert_detail_system_notes_v13_1.png) + +### View an Alert’s metrics data[](#view-an-alerts-metrics-data "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/217768) . + +要查看警报的指标,请执行以下操作: + +1. 以具有 Developer 或更高[权限](../../permissions.html)的用户身份登录. +2. 导航 **操作>警报** . +3. 单击您要查看的警报. +4. 在警报标题下,单击" **指标"**选项卡. + +[![Alert Management Metrics View](img/ca33b4a75b3a1bc207dd2eddae8c3949.png)](img/alert_detail_metrics_v13_2.png) + +For GitLab-managed Prometheus instances, metrics data is automatically available for the alert, making it easy to see surrounding behavior. See [Managed Prometheus instances](../../../operations/metrics/index.html#managed-prometheus-instances) for information on setting up alerts. + +对于外部管理的 Prometheus 实例,您可以配置警报规则以在警报中显示图表. 有关如何正确配置警报规则的信息,请参阅[基于警报在事件问题中嵌入指标](../../../operations/metrics/embed.html#embedding-metrics-based-on-alerts-in-incident-issues) . 有关为自己管理的 Prometheus 实例设置警报的信息,请参阅[外部](../../../operations/metrics/index.html#external-prometheus-instances) Prometheus 实例. + +## Use cases for assigning alerts[](#use-cases-for-assigning-alerts "Permalink") + +考虑一个由监视的不同部分组成的团队,在单个应用程序上进行协作. 警报浮出水面之后,将警报发送给可以处理和解决警报的团队成员非常重要. + +将警报分配给多个受让人可以简化协作和委派. 所有分配者都显示在团队的工作流程中,并且所有分配者都会收到通知,从而简化了警报的通信和所有权. + +完成调查或修复警报的部分后,用户可以在角色完成后从警报中取消分配帐户. 可以更新[警报状态](#alert-management-statuses)以反映警报是否已解决. + +### Slack Notifications[](#slack-notifications "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/216326) . + +当收到新的警报时,可以通过 Slack 消息向您发出警报. + +有关如何进行设置的信息,请参阅[Slack Notifications Service 文档](../integrations/slack.html) . \ No newline at end of file diff --git a/_book/docs/193.md b/_book/docs/193.md new file mode 100644 index 0000000000000000000000000000000000000000..6e8e1564fb4a831782c24e608d57d9e6b542c992 --- /dev/null +++ b/_book/docs/193.md @@ -0,0 +1,98 @@ +# Error Tracking + +> 原文:[https://docs.gitlab.com/ee/user/project/operations/error_tracking.html](https://docs.gitlab.com/ee/user/project/operations/error_tracking.html) + +* [Sentry error tracking](#sentry-error-tracking) + * [Deploying Sentry](#deploying-sentry) + * [Enabling Sentry](#enabling-sentry) + * [Enabling GitLab issues links](#enabling-gitlab-issues-links) +* [Error Tracking List](#error-tracking-list) +* [Error Details](#error-details) +* [Taking Action on errors](#taking-action-on-errors) + * [Ignoring errors](#ignoring-errors) + * [Resolving errors](#resolving-errors) + +# Error Tracking[](#error-tracking "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/169) . + +错误跟踪使开发人员可以轻松发现和查看其应用程序可能产生的错误. 通过在开发代码的地方显示错误信息,可以提高效率和知名度. + +## Sentry error tracking[](#sentry-error-tracking "Permalink") + +[Sentry](https://sentry.io/)是一个开源错误跟踪系统. GitLab 允许管理员将 Sentry 连接到 GitLab,以允许用户查看 GitLab 中的 Sentry 错误列表. + +### Deploying Sentry[](#deploying-sentry "Permalink") + +您可以注册到托管在[https://sentry.io](https://sentry.io)上的云,部署自己[的本地实例](https://docs.sentry.io/server/installation/)或使用 GitLab [将 Sentry 安装到 Kubernetes 集群](../../clusters/applications.html#install-sentry-using-gitlab-cicd) . + +### Enabling Sentry[](#enabling-sentry "Permalink") + +**注意:**您至少需要维护者[权限](../../permissions.html)才能启用 Sentry 集成. + +GitLab 提供了一种将 Sentry 连接到您的项目的简便方法: + +1. 注册到 Sentry.io 或[部署您自己的](#deploying-sentry) Sentry 实例. +2. [创建](https://docs.sentry.io/guides/integrate-frontend/create-new-project/)一个新的 Sentry 项目. 对于您要集成的每个 GitLab 项目,我们建议您创建一个新的 Sentry 项目. +3. [查找或生成](https://docs.sentry.io/api/auth/)您的 Sentry 项目的 Sentry 身份验证令牌. 确保至少给令牌以下范围: `event:read`和`project:read` . +4. 导航到项目的**"设置">"操作"** . +5. 确保设置了**活动**复选框. +6. 在**Sentry API URL**字段中,输入您的 Sentry 主机名. 例如,如果这是您的 Sentry 实例可用的地址,请输入`https://sentry.example.com` . 对于 Sena 的 SaaS 版本,主机名将为`https://sentry.io` . +7. 在" **验证令牌"**字段中,输入您先前生成的令牌. +8. 单击" **连接"**按钮以测试与 Sentry 的连接并填充" **项目"**下拉列表. +9. 从**项目**下拉菜单中,选择一个 Sentry 项目以链接到您的 GitLab 项目. +10. 单击**保存更改**以使更改生效. +11. 现在,您可以在项目的侧栏中访问" **操作">"错误跟踪"** ,以[查看](#error-tracking-list) Sentry 错误[的列表](#error-tracking-list) . + +### Enabling GitLab issues links[](#enabling-gitlab-issues-links "Permalink") + +您可能还需要按照[Sentry 文档中](https://docs.sentry.io/workflow/integrations/global-integrations/#gitlab)的步骤来启用 Sentry 的 GitLab 集成. + +## Error Tracking List[](#error-tracking-list "Permalink") + +**注意:**您将至少需要 Reporter [权限](../../permissions.html)才能查看"错误跟踪"列表. + +您可以在项目的边栏中的" **操作">"错误跟踪"**中找到"错误跟踪"列表. 在这里,您可以按标题或状态("已忽略","已解决"或"未解决"之一)过滤错误,并按"频率","首次看到"或"最后看到"的降序排列. 默认情况下,错误列表按"上次发现"排序,并过滤为"未解决的错误". + +[![Error Tracking list](img/8375b8805ee35febb22389954e463cb3.png)](img/error_tracking_list_v12_6.png) + +## Error Details[](#error-details "Permalink") + +从错误列表中,用户可以通过单击任何错误的标题导航到错误详细信息页面. + +该页面具有: + +* 哨兵问题的链接. +* 如果 Sentry Issue 的第一个发行[版](https://docs.sentry.io/workflow/releases/?platform=javascript#configure-sdk)的 Sentry [版本 ID /版本](https://docs.sentry.io/workflow/releases/?platform=javascript#configure-sdk)与您的 GitLab 托管项目中的提交 SHA 匹配,则指向 GitLab 提交的链接. +* 有关该问题的其他详细信息,包括完整的堆栈跟踪. +* 在[GitLab 12.7 及更高版本中](https://gitlab.com/gitlab-org/gitlab/-/issues/36246) ,显示语言和紧急度. + +默认情况下,显示**创建问题**按钮: + +[![Error Details without Issue Link](img/8d66587fae4dab1dca05f85389caa499.png)](img/error_details_v12_7.png) + +如果您从错误中创建了一个 GitLab 问题,则" **创建问题"**按钮将变为" **查看问题"**按钮,并且指向 GitLab 问题的链接将出现在"错误详细信息"部分中: + +[![Error Details with Issue Link](img/2fed535a429569e1ae792fb3960bcdd5.png)](img/error_details_with_issue_v12_8.png) + +## Taking Action on errors[](#taking-action-on-errors "Permalink") + +您可以从 GitLab UI 中对哨兵错误采取措施. + +### Ignoring errors[](#ignoring-errors "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/39665) . + +在" [错误详细信息"](#error-details)页面中,只需单击页面顶部附近的" **忽略"**按钮,就可以忽略 Sentry 错误. + +忽略错误将阻止它出现在" [错误跟踪列表"中](#error-tracking-list) ,并将使 Sentry 中设置的通知静音. + +### Resolving errors[](#resolving-errors "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/39825) . + +在" [错误详细信息"](#error-details)页面中,您可以通过单击页面顶部附近的" **解决"**按钮来解决 Sentry 错误. + +将错误标记为已解决表示错误已停止触发事件. 如果 GitLab 问题与错误相关联,则该问题将被关闭. + +如果发生另一个事件,该错误将恢复为未解决. \ No newline at end of file diff --git a/_book/docs/194.md b/_book/docs/194.md new file mode 100644 index 0000000000000000000000000000000000000000..7f6bbcc571cb43117b7468ab42fc21bd1141d472 --- /dev/null +++ b/_book/docs/194.md @@ -0,0 +1,32 @@ +# Tracing + +> 原文:[https://docs.gitlab.com/ee/operations/tracing.html](https://docs.gitlab.com/ee/operations/tracing.html) + +* [Jaeger tracing](#jaeger-tracing) + * [Deploying Jaeger](#deploying-jaeger) + * [Enabling Jaeger](#enabling-jaeger) + +# Tracing[](#tracing-ultimate "Permalink") + +在 GitLab Ultimate 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7903) . + +跟踪提供对已部署应用程序的性能和运行状况的洞察力,跟踪处理给定请求的每个功能或微服务. + +不管您使用的是整体系统还是分布式系统,这都可以轻松理解请求的端到端流程. + +## Jaeger tracing[](#jaeger-tracing "Permalink") + +[Jaeger](https://www.jaegertracing.io/)是一个开源的,端到端的分布式跟踪系统,用于监视和调试基于微服务的分布式系统. + +### Deploying Jaeger[](#deploying-jaeger "Permalink") + +要了解有关部署 Jaeger 的更多信息,请阅读官方的《 [入门指南》文档](https://www.jaegertracing.io/docs/latest/getting-started/) . 有一个易于使用[的多合一 Docker 映像](https://www.jaegertracing.io/docs/latest/getting-started/#AllinoneDockerimage) ,以及[Kubernetes](https://github.com/jaegertracing/jaeger-kubernetes)和[OpenShift 的](https://github.com/jaegertracing/jaeger-openshift)部署选项. + +### Enabling Jaeger[](#enabling-jaeger "Permalink") + +GitLab 提供了一种从项目内部打开 Jaeger UI 的简便方法: + +1. 使用[客户端库](https://www.jaegertracing.io/docs/latest/client-libraries/)之一[设置 Jaeger](https://www.jaegertracing.io)并配置您的应用[程序](https://www.jaegertracing.io/docs/latest/client-libraries/) . +2. 导航到项目的**"设置">"操作",**然后提供 Jaeger URL. +3. 单击**保存更改**以使更改生效. +4. 现在,您可以在项目的侧边栏中访问" **操作">"跟踪"** ,GitLab 会将您重定向到已配置的 Jaeger URL. \ No newline at end of file diff --git a/_book/docs/195.md b/_book/docs/195.md new file mode 100644 index 0000000000000000000000000000000000000000..95186af8e98112f3dd34615150780c235c8974ab --- /dev/null +++ b/_book/docs/195.md @@ -0,0 +1,104 @@ +# Incident Management + +> 原文:[https://docs.gitlab.com/ee/user/incident_management/](https://docs.gitlab.com/ee/user/incident_management/) + +* [Configure incidents](#configure-incidents-ultimate) + * [Notify developers of alerts](#notify-developers-of-alerts) +* [Configure PagerDuty integration](#configure-pagerduty-integration) +* [Configure Prometheus alerts](#configure-prometheus-alerts) +* [Configure external generic alerts](#configure-external-generic-alerts) +* [Embed metrics in incidents and issues](#embed-metrics-in-incidents-and-issues) + * [Context menu](#context-menu) + * [View logs from metrics panel](#view-logs-from-metrics-panel) +* [Integrate incidents with Slack](#integrate-incidents-with-slack) +* [Integrate issues with Zoom](#integrate-issues-with-zoom) + +# Incident Management[](#incident-management "Permalink") + +GitLab 提供了用于处理应用程序和服务中的事件的解决方案,例如设置 Prometheus 警报,显示指标和发送通知. + +## Configure incidents[](#configure-incidents-ultimate "Permalink") + +在 GitLab Ultimate 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4925) . + +您可以在 GitLab 用户界面中启用或禁用事件管理功能,以在触发警报时创建问题: + +1. 导航 **设置>操作>事件,**然后展开**事件** : + + [![Incident Management Settings](img/f652f5dac5bec0bb81edc08cbfd7a01b.png)](img/incident_management_settings.png) + +2. 对于 GitLab 11.11 及更高版本,您可以选中**创建问题**复选框以根据自己的[问题模板](../project/description_templates.html#creating-issue-templates)创建[问题](../project/description_templates.html#creating-issue-templates) . 有关更多信息,请参阅[从警报触发操作](../../operations/metrics/alerts.html#trigger-actions-from-alerts-ultimate) . +3. 要从警报中创建问题,请在" **问题模板"**选择框中选择**模板** . +4. 要向具有[开发者权限的](../permissions.html)用户发送[单独的电子邮件通知](#notify-developers-of-alerts) ,请选择" **向开发者发送单独的电子邮件通知"** . +5. Click **保存更改**. + +适当配置的警报包括与警报相对应的查询的[嵌入式图表](../../operations/metrics/embed.html#embedding-metrics-based-on-alerts-in-incident-issues) . 您还可以将 GitLab 配置为在收到警报已解决的通知时[关闭问题](../../operations/metrics/alerts.html#trigger-actions-from-alerts-ultimate) . + +### Notify developers of alerts[](#notify-developers-of-alerts "Permalink") + +GitLab 可以通过创建问题并通过电子邮件提醒开发人员来应对您的应用程序和服务触发的警报. 默认情况下,GitLab 将这些电子邮件发送给项目的[所有者和维护者](../permissions.html) . 这些电子邮件包含警报的详细信息以及更多信息的链接. + +要将单独的电子邮件通知发送给具有[开发者权限的](../permissions.html)用户,请参阅[配置事件](#configure-incidents-ultimate) . + +## Configure PagerDuty integration[](#configure-pagerduty-integration "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/119018) . + +您可以使用 PagerDuty 设置一个 Webhook,以便为每个 PagerDuty 事件自动创建一个 GitLab 问题. 此配置要求您同时更改 PagerDuty 和 GitLab: + +1. 以具有维护者[权限](../permissions.html)的用户身份登录. +2. 导航 **设置>操作>事件,**然后展开**事件** . +3. 选择**PagerDuty 集成**选项卡: + + [![PagerDuty incidents integration](img/370ac43323901b08b905644b04f6a802.png)](img/pagerduty_incidents_integration_13_2.png) + +4. 激活集成,并将更改保存在 GitLab 中. +5. 复制**Webhook URL**的值, **以**供以后使用. +6. 按照[PagerDuty 文档中](https://support.pagerduty.com/docs/webhooks)描述的步骤,将[Webhook](https://support.pagerduty.com/docs/webhooks) URL 添加到 PagerDuty Webhook 集成中. + +为了确认集成成功,从 PagerDuty 触发一个测试事件以确认是否从该事件中创建了一个 GitLab 问题. + +## Configure Prometheus alerts[](#configure-prometheus-alerts "Permalink") + +您可以在以下位置设置 Prometheus 警报: + +* [GitLab-managed Prometheus](../../operations/metrics/alerts.html) installations. +* [Self-managed Prometheus](../../operations/metrics/alerts.html#external-prometheus-instances) installations. + +Prometheus 警报由特殊的警报机器人用户创建. 您无法删除此用户,但不计入您的许可限制. + +## Configure external generic alerts[](#configure-external-generic-alerts "Permalink") + +GitLab 可以通过通用的 Webhook 接收器接受来自任何来源的警报. 在[配置通用警报集成时](../project/integrations/generic_alerts.html) ,GitLab 会创建一个唯一的端点,该端点接收 JSON 格式的可自定义负载. + +## Embed metrics in incidents and issues[](#embed-metrics-in-incidents-and-issues "Permalink") + +您可以在使用[GitLab Markdown 的](../markdown.html)任何地方嵌入指标,例如描述,问题评论和合并请求. 嵌入指标可帮助您在讨论事件或性能问题时共享它们. 通过[将链接复制并粘贴到指标仪表盘](../../operations/metrics/embed.html#embedding-gitlab-managed-kubernetes-metrics) ,您可以将仪表盘直接输出到 GitLab 中的任何问题,合并请求,史诗或其他 Markdown 文本字段中. + +您可以将[GitLab 托管的指标](../../operations/metrics/embed.html)和[Grafana 指标](../../operations/metrics/embed_grafana.html)都嵌入事件和问题模板中. + +### Context menu[](#context-menu "Permalink") + +您可以从上下文菜单中查看有关嵌入式指标面板的更多详细信息. 要访问上下文菜单,请单击 面板右上角上方的**更多操作**下拉框. 选项包括: + +* [View logs](#view-logs-from-metrics-panel). +* **下载 CSV-**嵌入式图表中的数据可以[CSV 格式下载](../../operations/metrics/dashboards/index.html#downloading-data-as-csv) . + +#### View logs from metrics panel[](#view-logs-from-metrics-panel "Permalink") + +版本历史 + +* 在 GitLab Ultimate 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/201846) . +* [移至](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25455) [GitLab Core](https://about.gitlab.com/pricing/) 12.9\. + +如果您要对应用程序事件进行分类并需要[浏览](../../operations/metrics/dashboards/index.html#view-logs-ultimate)整个应用程序中的日志,则从指标面板查看日志可能会很有用. 这些日志可帮助您了解影响应用程序性能的因素并解决所有问题. + +## Integrate incidents with Slack[](#integrate-incidents-with-slack "Permalink") + +使用 Slack 斜杠命令,您可以控制 GitLab 并查看 GitLab 内容,而无需离开 Slack. + +了解如何[设置 Slack 斜杠命令](../project/integrations/slack_slash_commands.html)以及如何[使用可用的斜杠命令](../../integration/slash_commands.html) . + +## Integrate issues with Zoom[](#integrate-issues-with-zoom "Permalink") + +通过 GitLab,您可以[将 Zoom 会议与](../project/issues/associate_zoom_meeting.html)事件[相关联,](../project/issues/associate_zoom_meeting.html)以便在事件管理期间进行同步通信. 在启动事件的 Zoom 呼叫后,您可以将电话会议与问题关联. 您的团队成员无需请求链接即可加入 Zoom 通话. \ No newline at end of file diff --git a/_book/docs/196.md b/_book/docs/196.md new file mode 100644 index 0000000000000000000000000000000000000000..2514473ab26b69da613234f6947ab927d00a91b1 --- /dev/null +++ b/_book/docs/196.md @@ -0,0 +1,125 @@ +# GitLab Status Page + +> 原文:[https://docs.gitlab.com/ee/user/project/status_page/](https://docs.gitlab.com/ee/user/project/status_page/) + +* [How to set up](#how-to-set-up) + * [Cloud account set up](#cloud-account-set-up) + * [AWS Setup](#aws-setup) + * [Status Page project](#status-page-project) + * [Syncing incidents to the Status Page](#syncing-incidents-to-the-status-page) +* [Status Page UI](#status-page-ui) + * [Incident detail page](#incident-detail-page) +* [How it works](#how-it-works) + * [Publishing Incidents](#publishing-incidents) + * [Publishing updates](#publishing-updates) + * [Adding comments](#adding-comments) + * [Changing the Incident status](#changing-the-incident-status) +* [Attachment storage](#attachment-storage) + * [Limit](#limit) + +# GitLab Status Page[](#gitlab-status-page-ultimate "Permalink") + +[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2479) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. + +通过 GitLab 状态页面,您可以创建和部署静态网站,以便在事件发生时与用户进行有效沟通. + +## How to set up[](#how-to-set-up "Permalink") + +**注意:**仅支持将 AWS S3 作为部署目标.图 TB 子图 GitLab 实例问题(问题更新)-触发器->中间件(背景工作:JSON 生成)结束子图 Cloud Provider 中间件-保存数据-> c1(云桶存储 JSON 文件)结束子图状态页 d( CDN 上的静态站点)-获取数据-> C1 端 + +设置状态页面非常简单,但是您需要做一些事情. + +### Cloud account set up[](#cloud-account-set-up "Permalink") + +要使用 GitLab 状态页,您首先需要在操作设置页中为您的云提供商设置帐户详细信息. 今天,仅支持 AWS. + +#### AWS Setup[](#aws-setup "Permalink") + +1. 在您的 AWS acccout 中,创建两个新的 IAM 策略. + * [创建存储桶](https://gitlab.com/gitlab-org/status-page/-/blob/master/deploy/etc/s3_create_policy.json) . + * [更新存储桶内容](https://gitlab.com/gitlab-org/status-page/-/blob/master/deploy/etc/s3_update_bucket_policy.json) (请记住用您的存储桶名称替换`S3_BUCKET_NAME` ). +2. 使用第一步中创建的权限策略创建一个新的 AWS 访问密钥. + +### Status Page project[](#status-page-project "Permalink") + +要将状态页面部署到 AWS S3,您需要添加状态页面项目并配置必要的 CI 变量. + +1. 分叉[状态页](https://gitlab.com/gitlab-org/status-page)项目. 这也可以通过" [存储库镜像"](https://gitlab.com/gitlab-org/status-page#repository-mirroring)来完成,这将确保您获得最新的"状态页"功能. +2. 在**设置> CI / CD>变量中**添加以下**变量** . (要从 Amazon 获取这些变量,请使用您的 Amazon Console): + * `S3_BUCKET_NAME` -Amazon S3 存储桶的名称(如果不存在具有提供名称的存储桶,则第一个管道运行将创建一个并为[静态网站托管](https://docs.aws.amazon.com/AmazonS3/latest/dev/HostingWebsiteOnS3Setup.html)配置它) + * `AWS_DEFAULT_REGION` -AWS 区域 + * `AWS_ACCESS_KEY_ID` -AWS 访问密钥 ID + * `AWS_SECRET_ACCESS_KEY` -AWS 秘密 +3. 运行管道以将状态页部署到 S3. + +### Syncing incidents to the Status Page[](#syncing-incidents-to-the-status-page "Permalink") + +设置 CI / CD 变量后,您需要设置要用于事件问题的项目: + +1. 要查看" [操作设置"](../settings/#operations-settings)页面,请导航至 **设置>操作>状态页面** . +2. 填写您的云提供商的凭据,并确保已选中" **活动"**复选框. +3. Click **保存更改**. + +## Status Page UI[](#status-page-ui "Permalink") + +"状态页面"登录页面显示了最近事件的概述. 单击事件将带您到事件的详细信息页面. + +[![Status Page landing page](img/d4a6279fcd73fa0a1dc68761261f4854.png)](../img/status_page_incidents_v12_10.png) + +### Incident detail page[](#incident-detail-page "Permalink") + +事件详细信息页面显示有关特定事件的详细信息. 例如: + +* 事件的状态,包括事件的最新更新时间. +* 事件标题,包括所有表情符号. +* 事件描述,包括表情符号. +* 事件描述或注释中提供的带有有效图像扩展名的任何文件附件. 在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/205166) . +* 按时间顺序排列的事件更新列表. + +[![Status Page detail](img/8f8d204a16e9c896b01a62220529b921.png)](../img/status_page_detail_v12_10.png) + +## How it works[](#how-it-works "Permalink") + +### Publishing Incidents[](#publishing-incidents "Permalink") + +要发布事件,您首先需要在启用状态页设置的项目中创建一个问题. + +默认情况下,问题不会发布到状态页面. 在问题中使用`/publish` [快速操作](../quick_actions.html)来发布问题. 仅[项目或小组所有者](../../permissions.html)可以发布问题. + +使用快速操作后,后台工作人员将使用在安装过程中提供的凭据将问题发布到"状态页"上. + +由于所有事件都是公开发布的,因此用户和组提及将由`Incident Responder`匿名,并且非公共[GitLab 参考的](../../markdown.html#special-gitlab-references)标题也将被删除. + +When an Incident is published in the GitLab project, you can access the details page of the Incident by clicking the **在状态页上发布** button displayed under the Incident’s title. + +[![Status Page detail link](img/3c9cb466046f19c70255f0de753a307c.png)](../img/status_page_detail_link_v13_1.png) + +**注意:**机密性问题无法发布. 如果您将已发布的问题设为机密,则它将不会发布. + +### Publishing updates[](#publishing-updates "Permalink") + +要发布事件更新,请更新事件问题的描述. + +**小心:**更改引用的问题(例如标题,机密性)时,引用的事件不会自动更新. + +### Adding comments[](#adding-comments "Permalink") + +要将评论添加到状态页事件中,请对事件问题创建评论. + +准备发布评论时,请在评论中添加麦克风[奖表情符号](../../../user/award_emojis.html)反应( `:microphone` ). 这会将注释标记为应部署到状态页的注释. + +**警告:**有权查看问题的任何人都可以在评论中添加表情符号奖,因此您可能希望将问题仅限于团队成员. + +### Changing the Incident status[](#changing-the-incident-status "Permalink") + +要将事件状态从`open`更改为`closed` ,请在 GitLab 中关闭事件问题. 然后将在状态页面网站上对此进行更新. + +## Attachment storage[](#attachment-storage "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/205166) . + +从 GitLab 13.1 开始,作为[发布流程的](#how-it-works)一部分,附加到事件问题描述或注释的文件将被发布和未发布到状态页存储中. + +### Limit[](#limit "Permalink") + +每个问题仅 5000 个附件将被转移到状态页面. \ No newline at end of file diff --git a/_book/docs/197.md b/_book/docs/197.md new file mode 100644 index 0000000000000000000000000000000000000000..9b247baecb1fc29e11e6190d8389698d9ba6b40e --- /dev/null +++ b/_book/docs/197.md @@ -0,0 +1,290 @@ +# Feature Flags + +> 原文:[https://docs.gitlab.com/ee/operations/feature_flags.html](https://docs.gitlab.com/ee/operations/feature_flags.html) + +* [How it works](#how-it-works) +* [Create a feature flag](#create-a-feature-flag) +* [Rollout strategy (legacy)](#rollout-strategy-legacy) +* [Feature flag strategies](#feature-flag-strategies) + * [All users](#all-users) + * [Percent of Users](#percent-of-users) + * [User IDs](#user-ids) + * [User List](#user-list) + * [Enable or disable feature flag strategies](#enable-or-disable-feature-flag-strategies) +* [Disable a feature flag for a specific environment](#disable-a-feature-flag-for-a-specific-environment) +* [Disable a feature flag for all environments](#disable-a-feature-flag-for-all-environments) +* [Integrate feature flags with your application](#integrate-feature-flags-with-your-application) + * [Get access credentials](#get-access-credentials) + * [Choose a client library](#choose-a-client-library) + * [Feature flags API information](#feature-flags-api-information) + * [Golang application example](#golang-application-example) + * [Ruby application example](#ruby-application-example) +* [Feature Flag Related Issues](#feature-flag-related-issues) + * [Enable or disable Feature Flag Related Issues](#enable-or-disable-feature-flag-related-issues-core-only) + +# Feature Flags[](#feature-flags-premium "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7433) . + +借助功能标志,您可以将应用程序的新功能部署到较小的批量生产中. 您可以将功能打开或关闭到部分用户,以帮助您实现持续交付. 功能标记有助于降低风险,使您能够进行受控测试,并将功能交付与客户发布分开. + +有关实际使用的功能标志的示例,请参阅[用于部署的 GitLab,功能标志和错误跟踪](https://www.youtube.com/embed/5tw2p6lwXxo) . + +## How it works[](#how-it-works "Permalink") + +GitLab 使用功能切换服务[Unleash](https://github.com/Unleash/unleash) . + +通过在 GitLab 中启用或禁用标记,您的应用程序可以确定要启用或禁用的功能. + +您可以在 GitLab 中创建功能标记,并使用应用程序中的 API 来获取功能标记及其状态的列表. 必须将应用程序配置为与 GitLab 进行通信,因此,开发人员可以使用兼容的客户端库并将[功能标记集成到您的应用程序中](#integrate-feature-flags-with-your-application) . + +## Create a feature flag[](#create-a-feature-flag "Permalink") + +要创建并启用功能标志: + +1. 导航到项目的" **操作">"功能标志"** . +2. 单击**新功能标志**按钮. +3. 输入一个以字母开头的名称,该名称仅包含小写字母,数字,下划线( `_` )或破折号( `-` ),并且不以破折号( `-` )或下划线( `_` )结尾. +4. 输入描述(可选,最多 255 个字符). +5. Enter details about how the flag should be applied: + * 在 GitLab 13.0 和更早版本中,添加**Environment specs** . 对于每个环境,包括" **状态"** (默认启用)和" [**部署"策略**](#rollout-strategy-legacy) (默认为" **所有用户"** ). + * 在 GitLab 13.1 和更高版本中,添加 Feature Flag [**Strategies**](#feature-flag-strategies) . 对于每种策略,请包括" **类型"** (默认为" [**所有用户"**](#all-users) )和" **环境"** (默认为所有环境). +6. Click **创建功能标志**. + +您可以通过单击 列表中任何功能标志旁边的(编辑)按钮. + +## Rollout strategy (legacy)[](#rollout-strategy-legacy "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/8240) . + +在 GitLab 13.0 和更早版本中," **推出"策略**设置会影响哪些用户将启用该功能. 选择要启用该功能的用户百分比. 如果禁用环境规范,则推出策略将无效. + +可以设置为: + +* 全部用户 +* [Percent of users](#percent-of-users) + * (可选)您可以单击" **包括其他用户 ID"**复选框,并添加特定用户 ID 列表以启用该功能. +* [User IDs](#user-ids) + +## Feature flag strategies[](#feature-flag-strategies "Permalink") + +版本历史 + +* 在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/35555) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上启用了它. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-feature-flag-strategies) . + +您可以在多个环境中应用功能标记策略,而无需多次定义策略. + +GitLab 功能标志使用[Unleash](https://unleash.github.io)作为功​​能标志引擎. 在"释放"中,有用于粒度特征标志控件的[策略](https://unleash.github.io/docs/activation_strategy) . GitLab 功能标志可以有多种策略,支持的策略有: + +* [All users](#all-users) +* [Percent of Users](#percent-of-users) +* [User IDs](#user-ids) +* [User List](#user-list) + +可以在[创建](#create-a-feature-flag)功能部件标记时将策略添加到功能部件标记,也可以在[创建](#create-a-feature-flag)后通过导航到" **操作">"功能部件标记"**并单击以编辑现有功能部件标记 (编辑). + +### All users[](#all-users "Permalink") + +为所有用户启用该功能. 它使用[`default`](https://unleash.github.io/docs/activation_strategy#default)释放激活策略. + +### Percent of Users[](#percent-of-users "Permalink") + +为一定百分比的已认证用户启用该功能. 它使用[`gradualRolloutUserId`](https://unleash.github.io/docs/activation_strategy#gradualrolloutuserid)释放激活策略. + +例如,将值设置为 15%即可为 15%的经过身份验证的用户启用该功能. + +推出百分比可以从 0%到 100%. + +**注意:**对于已登录的用户,但对于匿名用户,保证了粘性(同一用户的一致应用程序行为).**警告:**如果选择此策略,则**必须**为 Unleash 客户端提供一个用户 ID,以启用该功能. 请参见下面的[Ruby 示例](#ruby-application-example) . + +### User IDs[](#user-ids "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/8240) . [更新](https://gitlab.com/gitlab-org/gitlab/-/issues/34363)为在 GitLab 12.6 中按环境定义. + +为目标用户列表启用该功能. 它是使用 Unleash [`userWithId`](https://unleash.github.io/docs/activation_strategy#userwithid)激活策略实现的. + +输入用户 ID 作为逗号分隔的值列表. 例如, `user@example.com, user2@example.com`或`username1,username2,username3`等. + +**注意:**用户 ID 是您的应用程序用户的标识符. 他们不必是 GitLab 用户.**注意:** **必须**为 Unleash 客户端提供用户 ID,才能为目标用户启用该功能. 请参见下面的[Ruby 示例](#ruby-application-example) . + +### User List[](#user-list "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/35930) . + +为使用[Feature Flag User List API](../api/feature_flag_user_lists.html)创建的[用户列表](../api/feature_flag_user_lists.html)启用功能. 与[用户 ID](#user-ids)相似,它使用 Unleash [`userWithId`](https://unleash.github.io/docs/activation_strategy#userwithid)激活策略. + +### Enable or disable feature flag strategies[](#enable-or-disable-feature-flag-strategies "Permalink") + +此功能正在开发中,但已准备好进行测试. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../administration/feature_flags.html)可以为您的实例启用它. + +要启用它: + +``` +Feature.enable(:feature_flags_new_version) +``` + +禁用它: + +``` +Feature.disable(:feature_flags_new_version) +``` + +## Disable a feature flag for a specific environment[](#disable-a-feature-flag-for-a-specific-environment "Permalink") + +在[GitLab 13.0 和更早版本中](https://gitlab.com/gitlab-org/gitlab/-/issues/8621) ,要为特定环境禁用功能标志: + +1. 导航到项目的" **操作">"功能标志"** . +2. 对于要禁用的功能标志,请单击"铅笔"图标. +3. 禁用标志: + + * 在 GitLab 13.0 和更低版本中:滑动环境的"状态"切换. 或者,要删除环境规范,请单击右侧的" **删除(X)"**图标. + * 在 GitLab 13.1 及更高版本:对于每一个战略,它适用于在**环境** ,删除环境. +4. Click **保存更改**. + +## Disable a feature flag for all environments[](#disable-a-feature-flag-for-all-environments "Permalink") + +禁用所有环境的功能标志: + +1. 导航到项目的" **操作">"功能标志"** . +2. 对于要禁用的功能标志,请将状态切换滑动到**禁用** . + +功能标志显示在" **禁用"**选项卡上. + +## Integrate feature flags with your application[](#integrate-feature-flags-with-your-application "Permalink") + +要在应用程序中使用功能标志,请从 GitLab 获取访问凭据. 然后使用客户端库准备您的应用程序. + +### Get access credentials[](#get-access-credentials "Permalink") + +要获取您的应用程序需要与 GitLab 通信的访问凭据: + +1. 导航到项目的" **操作">"功能标志"** . +2. 单击**配置**按钮以查看以下内容: + * **API URL** :客户端(应用程序)连接以获取功能标志列表的 URL. + * **实例 ID** :授权检索功能标志的唯一令牌. + * **应用程序名称** :运行环境的名称. 例如,如果应用程序为生产服务器运行,则应用程序名称将为`production`或类似名称. 该值用于环境规格评估. + +**注意:**这些字段的含义可能会随着时间而改变. 例如,我们不确定**实例 ID**是分配给**Environment 的**是单个令牌还是多个令牌. 另外, **应用程序名称**可以描述应用程序的版本,而不是运行环境. + +### Choose a client library[](#choose-a-client-library "Permalink") + +GitLab 实现与 Unleash 客户端兼容的单个后端. + +使用 Unleash 客户端,开发人员可以在应用程序代码中定义标志的默认值. 如果提供的配置文件中不存在该标志,则每个功能标志评估都可以表达所需的结果. + +目前,Unleash [提供了许多用于各种语言和框架的 SDK](https://github.com/Unleash/unleash#client-implementations) . + +### Feature flags API information[](#feature-flags-api-information "Permalink") + +有关 API 的内容,请参见: + +* [Feature Flags API](../api/feature_flags.html) +* [功能标志规范 API](../api/feature_flag_specs.html) (已[在 GitLab 14.0 中](https://gitlab.com/gitlab-org/gitlab/-/issues/213369)弃用并[计划将其删除](https://gitlab.com/gitlab-org/gitlab/-/issues/213369) .) +* [Feature Flag User Lists API](../api/feature_flag_user_lists.html) +* [Legacy Feature Flags API](../api/feature_flags_legacy.html) + +### Golang application example[](#golang-application-example "Permalink") + +这是一个如何在 Golang 应用程序中集成特征标记的示例: + +``` +package main + +import ( + "io" + "log" + "net/http" + + "github.com/Unleash/unleash-client-go" +) + +type metricsInterface struct { +} + +func init() { + unleash.Initialize( + unleash.WithUrl("https://gitlab.com/api/v4/feature_flags/unleash/42"), + unleash.WithInstanceId("29QmjsW6KngPR5JNPMWx"), + unleash.WithAppName("production"), + unleash.WithListener(&metricsInterface{}), + ) +} + +func helloServer(w http.ResponseWriter, req *http.Request) { + if unleash.IsEnabled("my_feature_name") { + io.WriteString(w, "Feature enabled\n") + } else { + io.WriteString(w, "hello, world!\n") + } +} + +func main() { + http.HandleFunc("/", helloServer) + log.Fatal(http.ListenAndServe(":8080", nil)) +} +``` + +### Ruby application example[](#ruby-application-example "Permalink") + +这是一个如何在 Ruby 应用程序中集成功能标记的示例. + +为 Unleash 客户端提供了一个用户 ID,以与" **百分比"卷展栏(已登录用户)卷**展策略或" **目标用户"**列表一起使用. + +``` +#!/usr/bin/env ruby + +require 'unleash' +require 'unleash/context' + +unleash = Unleash::Client.new({ + url: 'http://gitlab.com/api/v4/feature_flags/unleash/42', + app_name: 'production', + instance_id: '29QmjsW6KngPR5JNPMWx' +}) + +unleash_context = Unleash::Context.new +# Replace "123" with the id of an authenticated user. +# Note that the context's user id must be a string: +# https://unleash.github.io/docs/unleash_context +unleash_context.user_id = "123" + +if unleash.is_enabled?("my_feature_name", unleash_context) + puts "Feature enabled" +else + puts "hello, world!" +end +``` + +## Feature Flag Related Issues[](#feature-flag-related-issues "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36617) . +* 它部署在默认情况下启用的功能标志后面. +* 在 GitLab.com 上启用了它. +* 不能根据项目启用或禁用它 +* 建议用于生产. +* 对于 GitLab 自我管理的实例,GitLab 管理员可以选择禁用它. + +您可以将相关问题链接到功能标志. 在" **链接的问题"**部分中,单击`+`按钮,然后输入问题参考编号或问题的完整 URL. + +此功能类似于[相关问题](../user/project/issues/related_issues.html)功能. + +### Enable or disable Feature Flag Related Issues[](#enable-or-disable-feature-flag-related-issues-core-only "Permalink") + +与功能标记相关​​的问题正在开发中,但已准备好用于生产. 它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../administration/feature_flags.html)可以选择为您的实例禁用它. + +禁用它: + +``` +Feature.disable(:feature_flags_issue_links) +``` + +To enable it: + +``` +Feature.enable(:feature_flags_issue_links) +``` \ No newline at end of file diff --git a/_book/docs/198.md b/_book/docs/198.md new file mode 100644 index 0000000000000000000000000000000000000000..7c587b7b6f8716c69c37c732b0009aafe91a6464 --- /dev/null +++ b/_book/docs/198.md @@ -0,0 +1,203 @@ +# GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/README.html](https://docs.gitlab.com/ee/ci/README.html) + +* [Overview](#overview) +* [Getting started](#getting-started) +* [Concepts](#concepts) +* [Configuration](#configuration) +* [Feature set](#feature-set) +* [Examples](#examples) +* [Administration](#administration-core-only) +* [References](#references) + * [Why GitLab CI/CD?](#why-gitlab-cicd) + * [Breaking changes](#breaking-changes) + * [13.0](#130) + * [12.0](#120) + * [11.0](#110) + * [10.0](#100) + * [9.0](#90) + +# GitLab CI/CD[](#gitlab-cicd "Permalink") + +GitLab CI / CD 是 GitLab 内置的工具,用于通过[连续方法](introduction/index.html#introduction-to-cicd-methodologies)进行软件开发: + +* 持续集成(CI) +* 连续交付(CD) +* 持续部署(CD) + +**注意:**开箱即用的管理系统可以将维护工具链所花费的时间减少 10%或更多. 观看我们的["精通持续软件开发"](https://about.gitlab.com/webcast/mastering-ci-cd/)网络广播,以了解连续方法以及 GitLab 的内置 CI 如何帮助您简化和扩展软件开发. + +## Overview[](#overview "Permalink") + +持续集成的工作原理是将小的代码块推送到 Git 存储库中托管的应用程序代码库中,并且每次推送时,都要运行脚本管道来构建,测试和验证代码更改,然后再将其合并到主分支中. + +持续交付和部署包括进一步的 CI,可在每次推送到存储库默认分支时将应用程序部署到生产环境. + +这些方法使您可以在开发周期的早期发现错误和错误,从而确保部署到生产环境的所有代码均符合为应用程序建立的代码标准. + +有关这些方法和 GitLab CI / CD 的完整概述,请阅读 GitLab 的 CI / CD [简介](introduction/index.html) . + +GitLab CI / CD 的视频演示: [演示:](https://www.youtube.com/watch?v=1iXFbchozdY) GitLab 的 CI / CD. + +<figure class="video-container"><iframe src="https://www.youtube.com/embed/1iXFbchozdY" frameborder="0" allowfullscreen=""></iframe></figure> + +## Getting started[](#getting-started "Permalink") + +GitLab CI / CD 由位于存储库根目录的名为`.gitlab-ci.yml`的文件配置. 该文件创建[管道](pipelines/index.html) ,该[管道](pipelines/index.html)运行以更改存储库中的代码. 管道包含一个或多个顺序运行的阶段,每个阶段可以包含一个或多个并行运行的作业. 这些作业(或脚本)由[GitLab Runner](https://docs.gitlab.com/runner/)代理执行. + +要开始使用 GitLab CI / CD,我们建议您通读以下文档: + +* [How GitLab CI/CD works](introduction/index.html#how-gitlab-cicd-works). +* [Fundamental pipeline architectures](pipelines/pipeline_architectures.html). +* [GitLab CI/CD basic workflow](introduction/index.html#basic-cicd-workflow). +* [Step-by-step guide for writing `.gitlab-ci.yml` for the first time](../user/project/pages/getting_started/pages_from_scratch.html). + +如果您要从其他 CI / CD 工具迁移,请查看我们方便的参考资料: + +* [Migrating from CircleCI](migration/circleci.html) +* [Migrating from Jenkins](jenkins/index.html) + +您也可以使用 UI 中提供的[`.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/lib/gitlab/ci/templates)之一来开始使用. 您可以通过创建新文件,选择适合您的应用程序的模板并根据需要进行调整来使用它们: + +[![Use a `.gitlab-ci.yml` template](img/e006fccde54b694d8c0f506a675942e0.png)](img/add_file_template_11_10.png) + +有关更广泛的概述,请参阅《 [CI / CD 入门](quick_start/README.html)指南》. + +熟悉 GitLab CI / CD 的工作原理后,请参阅[`.gitlab-ci.yml`完整参考,](yaml/README.html)以获取可以设置和使用的所有属性. + +**注意:** GitLab CI / CD 和[共享运行](runners/README.html#shared-runners)器在 GitLab.com 中启用,并且对所有用户可用,仅限于[用户的管道配额](../user/gitlab_com/index.html#shared-runners) . + +## Concepts[](#concepts "Permalink") + +GitLab CI / CD 使用许多概念来描述和运行您的构建和部署. + +| Concept | Description | +| --- | --- | +| [Pipelines](pipelines/index.html) | Structure your CI/CD process through pipelines. | +| [Environment variables](variables/README.html) | 根据变量/值键对重用值. | +| [Environments](environments/index.html) | 将您的应用程序部署到不同的环境(例如,登台,生产). | +| [Job artifacts](pipelines/job_artifacts.html) | 输出,使用和重用作业工件. | +| [Cache dependencies](caching/index.html) | 缓存您的依赖项以加快执行速度. | +| [GitLab Runner](https://docs.gitlab.com/runner/) | 配置自己的 GitLab 运行程序以执行脚本. | + +## Configuration[](#configuration "Permalink") + +GitLab CI / CD 支持多种配置选项: + +| Configuration | Description | +| --- | --- | +| [Schedule pipelines](pipelines/schedules.html) | 计划管道以根据需要运行. | +| [Custom path for `.gitlab-ci.yml`](pipelines/settings.html#custom-ci-configuration-path) | 为 CI / CD 配置文件定义自定义路径. | +| [Git submodules for CI/CD](git_submodules.html) | 配置作业以使用 Git 子模块. | +| [SSH keys for CI/CD](ssh_keys/README.html) | 在 CI 管道中使用 SSH 密钥. | +| [Pipeline triggers](triggers/README.html) | 通过 API 触发管道. | +| [Pipelines for Merge Requests](merge_request_pipelines/index.html) | 设计用于在合并请求中运行管道的管道结构. | +| [Integrate with Kubernetes clusters](../user/project/clusters/index.html) | 将您的项目连接到 Google Kubernetes Engine(GKE)或现有的 Kubernetes 集群. | +| [Optimize GitLab and Runner for large repositories](large_repositories/index.html) | 处理大型存储库的推荐策略. | +| [`.gitlab-ci.yml` full reference](yaml/README.html) | 您可以在 GitLab CI / CD 中使用的所有属性. | + +请注意,某些操作只能根据[用户](../user/permissions.html#gitlab-cicd-permissions)和[作业](../user/permissions.html#job-permissions)权限执行. + +## Feature set[](#feature-set "Permalink") + +使用庞大的 GitLab CI / CD 可以轻松地针对特定目的进行配置. 根据 DevOps 阶段,其功能集在下表中列出. + +| Feature | Description | +| --- | --- | +| **Configure** |   | +| [Auto DevOps](../topics/autodevops/index.html) | 设置应用的整个生命周期. | +| [ChatOps](chatops/README.html) | 从聊天中触发 CI 作业,并将结果发送回通道. | +| **Verify** |   | +| [Browser Performance Testing](../user/project/merge_requests/browser_performance_testing.html) | 快速确定即将发生的代码更改对浏览器性能的影响. | +| [Load Performance Testing](../user/project/merge_requests/load_performance_testing.html) | 快速确定未决代码更改对服务器性能的影响. | +| [CI services](services/README.html) | 将 Docker 容器与您的基本映像链接起来. | +| [Code Quality](../user/project/merge_requests/code_quality.html) | 分析您的源代码质量. | +| [GitLab CI/CD for external repositories](ci_cd_for_external_repos/index.html) | 结合使用 GitHub 和 Bitbucket Cloud 中的存储库,获得 GitLab CI / CD 的优势. | +| [Interactive Web Terminals](interactive_web_terminal/index.html) | 打开一个交互式 Web 终端以调试正在运行的作业. | +| [JUnit tests](junit_test_reports.html) | 直接在合并请求中识别脚本失败. | +| [Using Docker images](docker/using_docker_images.html) | 将 GitLab 和 GitLab Runner 与 Docker 结合使用来构建和测试应用程序. | +| **Release** |   | +| [Auto Deploy](../topics/autodevops/stages.html#auto-deploy) | 将您的应用程序部署到 Kubernetes 集群中的生产环境. | +| [Building Docker images](docker/using_docker_build.html) | 使用 GitLab CI / CD 维护基于 Docker 的项目. | +| [Canary Deployments](../user/project/canary_deployments.html) | 仅将功能部件运送到一部分吊舱中,并让一定比例的用户群访问临时部署的功能部件. | +| [Deploy Boards](../user/project/deploy_boards.html) | 检查 Kubernetes 上运行的每个 CI / CD 环境的当前运行状况和状态. | +| [Feature Flags](../operations/feature_flags.html) | 在功能标记后部署功能. | +| [GitLab Pages](../user/project/pages/index.html) | 部署静态网站. | +| [GitLab Releases](../user/project/releases/index.html) | 将发行说明添加到 Git 标签. | +| [Review Apps](review_apps/index.html) | 配置 GitLab CI / CD 预览代码更改. | +| [Cloud deployment](cloud_deployment/index.html) | 将您的应用程序部署到主要的云提供商. | +| **Secure** |   | +| [Container Scanning](../user/application_security/container_scanning/index.html) | 检查您的 Docker 容器是否存在已知漏洞. | +| [Dependency Scanning](../user/application_security/dependency_scanning/index.html) | 分析您的依赖项是否存在已知漏洞. | +| [License Compliance](../user/compliance/license_compliance/index.html) | 在项目依赖项中搜索其许可证. | +| [Security Test reports](../user/application_security/index.html) | 检查应用程序漏洞. | + +## Examples[](#examples "Permalink") + +在" [CI 实例"](examples/README.html)页面上查找示例项目代码和教程,以将 GitLab CI / CD 与各种应用程序框架,语言和平台结合使用. + +GitLab 还提供了[示例项目,这些项目已](https://gitlab.com/gitlab-examples)预先配置为使用 GitLab CI / CD. + +## Administration[](#administration-core-only "Permalink") + +作为 GitLab 管理员,您可以将 GitLab CI / CD 的默认行为更改为: + +* An [entire GitLab instance](../user/admin_area/settings/continuous_integration.html). +* 具体项目,使用[管道设置](pipelines/settings.html) . + +也可以看看: + +* [How to enable or disable GitLab CI/CD](enable_or_disable_ci.html). +* Other [CI administration settings](../administration/index.html#continuous-integration-settings). + +## References[](#references "Permalink") + +### Why GitLab CI/CD?[](#why-gitlab-cicd "Permalink") + +学习更多关于: + +* [Why you might chose GitLab CI/CD](https://about.gitlab.com/blog/2016/10/17/gitlab-ci-oohlala/). +* [Reasons you might migrate from another platform](https://about.gitlab.com/blog/2016/07/22/building-our-web-app-on-gitlab-ci/). +* [5 Teams that made the switch to GitLab CI/CD](https://about.gitlab.com/blog/2019/04/25/5-teams-that-made-the-switch-to-gitlab-ci-cd/) + +另请参阅[为什么选择 CI / CD?](https://docs.google.com/presentation/d/1OGgk2Tcxbpl7DJaIOzCX4Vqg3dlwfELC3u2jEeCBbDk) 介绍. + +### Breaking changes[](#breaking-changes "Permalink") + +随着 GitLab CI / CD 的发展,必须进行一些重大更改. 这些是: + +#### 13.0[](#130 "Permalink") + +* [Remove Backported `os.Expand`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4915) +* [Remove Fedora 29 package support](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/16158) +* [Remove macOS 32-bit support](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25466) +* [Removed `debug/jobs/list?v=1` endpoint](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6361) +* [Remove support for array of strings when defining services for Docker executor](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4922) +* [Remove `--docker-services` flag on register command](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6404) +* [Remove legacy build directory caching](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4180) +* [Remove `FF_USE_LEGACY_VOLUMES_MOUNTING_ORDER` feature flag](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6581) +* [Remove support for Windows Server 1803](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6553) + +#### 12.0[](#120 "Permalink") + +* [Use refspec to clone/fetch Git repository](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4069). +* [Old cache configuration](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4070). +* [Old metrics server configuration](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4072). +* [Remove `FF_K8S_USE_ENTRYPOINT_OVER_COMMAND`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4073). +* [Remove Linux distributions that reach EOL](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/1130). +* [Update command line API for helper images](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4013). +* [Remove old `git clean` flow](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4175). + +#### 11.0[](#110 "Permalink") + +* 没有重大变化. + +#### 10.0[](#100 "Permalink") + +* 没有重大变化. + +#### 9.0[](#90 "Permalink") + +* [为 GitLab 9.0 重命名 CI 变量](variables/deprecated_variables.html#gitlab-90-renamed-variables) . 了解不建议使用的 CI 变量以及在 GitLab 9.0+中应使用的内容. +* [新的 CI 作业权限模型](../user/project/new_ci_build_permissions_model.html) . 查看 GitLab 8.12 中的更改及其对工作的影响. 有一种新方法可以访问作业中的 Git 子模块和 LFS 对象. \ No newline at end of file diff --git a/_book/docs/199.md b/_book/docs/199.md new file mode 100644 index 0000000000000000000000000000000000000000..aa74f9e975ad8849b048c38868f637dd779271f4 --- /dev/null +++ b/_book/docs/199.md @@ -0,0 +1,3929 @@ +# GitLab CI/CD pipeline configuration reference + +> 原文:[https://docs.gitlab.com/ee/ci/yaml/README.html](https://docs.gitlab.com/ee/ci/yaml/README.html) + +* [Introduction](#introduction) + * [Validate the `.gitlab-ci.yml`](#validate-the-gitlab-ciyml) + * [Unavailable names for jobs](#unavailable-names-for-jobs) + * [Using reserved keywords](#using-reserved-keywords) +* [Configuration parameters](#configuration-parameters) +* [Global parameters](#global-parameters) + * [Global defaults](#global-defaults) + * [`inherit`](#inherit) + * [`stages`](#stages) + * [`workflow:rules`](#workflowrules) + * [`workflow:rules` templates](#workflowrules-templates) + * [`include`](#include) + * [`include:local`](#includelocal) + * [`include:file`](#includefile) + * [`include:remote`](#includeremote) + * [`include:template`](#includetemplate) + * [Nested includes](#nested-includes) + * [Additional `includes` examples](#additional-includes-examples) +* [Parameter details](#parameter-details) + * [`image`](#image) + * [`image:name`](#imagename) + * [`image:entrypoint`](#imageentrypoint) + * [`services`](#services) + * [`services:name`](#servicesname) + * [`services:alias`](#servicesalias) + * [`services:entrypoint`](#servicesentrypoint) + * [`services:command`](#servicescommand) + * [`script`](#script) + * [`before_script` and `after_script`](#before_script-and-after_script) + * [Coloring script output](#coloring-script-output) + * [Multiline commands](#multiline-commands) + * [`stage`](#stage) + * [Using your own Runners](#using-your-own-runners) + * [`.pre` and `.post`](#pre-and-post) + * [`extends`](#extends) + * [Merge details](#merge-details) + * [Using `extends` and `include` together](#using-extends-and-include-together) + * [`rules`](#rules) + * [Rules attributes](#rules-attributes) + * [Rules clauses](#rules-clauses) + * [Differences between `rules` and `only`/`except`](#differences-between-rules-and-onlyexcept) + * [`rules:if`](#rulesif) + * [`rules:changes`](#ruleschanges) + * [`rules:exists`](#rulesexists) + * [`rules:allow_failure`](#rulesallow_failure) + * [Complex rule clauses](#complex-rule-clauses) + * [`only`/`except` (basic)](#onlyexcept-basic) + * [Regular expressions](#regular-expressions) + * [Supported `only`/`except` regexp syntax](#supported-onlyexcept-regexp-syntax) + * [`only`/`except` (advanced)](#onlyexcept-advanced) + * [`only:refs`/`except:refs`](#onlyrefsexceptrefs) + * [`only:kubernetes`/`except:kubernetes`](#onlykubernetesexceptkubernetes) + * [`only:variables`/`except:variables`](#onlyvariablesexceptvariables) + * [`only:changes`/`except:changes`](#onlychangesexceptchanges) + * [Using `only:changes` with pipelines for merge requests](#using-onlychanges-with-pipelines-for-merge-requests) + * [Using `only:changes` without pipelines for merge requests](#using-onlychanges-without-pipelines-for-merge-requests) + * [Using `only:changes` with scheduled pipelines](#using-onlychanges-with-scheduled-pipelines) + * [`needs`](#needs) + * [Requirements and limitations](#requirements-and-limitations) + * [Changing the `needs:` job limit](#changing-the-needs-job-limit) + * [Artifact downloads with `needs`](#artifact-downloads-with-needs) + * [Cross project artifact downloads with `needs`](#cross-project-artifact-downloads-with-needs-premium) + * [Artifact downloads between pipelines in the same project](#artifact-downloads-between-pipelines-in-the-same-project) + * [`tags`](#tags) + * [`allow_failure`](#allow_failure) + * [`when`](#when) + * [`when:manual`](#whenmanual) + * [Protecting manual jobs](#protecting-manual-jobs-premium) + * [`when:delayed`](#whendelayed) + * [`environment`](#environment) + * [`environment:name`](#environmentname) + * [`environment:url`](#environmenturl) + * [`environment:on_stop`](#environmenton_stop) + * [`environment:action`](#environmentaction) + * [`environment:auto_stop_in`](#environmentauto_stop_in) + * [`environment:kubernetes`](#environmentkubernetes) + * [Dynamic environments](#dynamic-environments) + * [`cache`](#cache) + * [`cache:paths`](#cachepaths) + * [`cache:key`](#cachekey) + * [`cache:key:files`](#cachekeyfiles) + * [`cache:key:prefix`](#cachekeyprefix) + * [`cache:untracked`](#cacheuntracked) + * [`cache:policy`](#cachepolicy) + * [`artifacts`](#artifacts) + * [`artifacts:paths`](#artifactspaths) + * [`artifacts:exclude`](#artifactsexclude) + * [`artifacts:expose_as`](#artifactsexpose_as) + * [`artifacts:name`](#artifactsname) + * [`artifacts:untracked`](#artifactsuntracked) + * [`artifacts:when`](#artifactswhen) + * [`artifacts:expire_in`](#artifactsexpire_in) + * [`artifacts:reports`](#artifactsreports) + * [`dependencies`](#dependencies) + * [When a dependent job will fail](#when-a-dependent-job-will-fail) + * [`coverage`](#coverage) + * [`retry`](#retry) + * [`timeout`](#timeout) + * [`parallel`](#parallel) + * [`trigger`](#trigger) + * [Simple `trigger` syntax for multi-project pipelines](#simple-trigger-syntax-for-multi-project-pipelines) + * [Complex `trigger` syntax for multi-project pipelines](#complex-trigger-syntax-for-multi-project-pipelines) + * [`trigger` syntax for child pipeline](#trigger-syntax-for-child-pipeline) + * [Trigger child pipeline with generated configuration file](#trigger-child-pipeline-with-generated-configuration-file) + * [Linking pipelines with `trigger:strategy`](#linking-pipelines-with-triggerstrategy) + * [Trigger a pipeline by API call](#trigger-a-pipeline-by-api-call) + * [`interruptible`](#interruptible) + * [`resource_group`](#resource_group) + * [`release`](#release) + * [`release-cli` Docker image](#release-cli-docker-image) + * [Script](#script-1) + * [`release:tag_name`](#releasetag_name) + * [`release:name`](#releasename) + * [`release:description`](#releasedescription) + * [`release:ref`](#releaseref) + * [`release:milestones`](#releasemilestones) + * [`release:released_at`](#releasereleased_at) + * [Complete example for `release`](#complete-example-for-release) + * [`releaser-cli` command line](#releaser-cli-command-line) + * [`pages`](#pages) +* [`variables`](#variables) + * [Git strategy](#git-strategy) + * [Git submodule strategy](#git-submodule-strategy) + * [Git checkout](#git-checkout) + * [Git clean flags](#git-clean-flags) + * [Git fetch extra flags](#git-fetch-extra-flags) + * [Job stages attempts](#job-stages-attempts) + * [Shallow cloning](#shallow-cloning) + * [Custom build directories](#custom-build-directories) + * [Handling concurrency](#handling-concurrency) + * [Nested paths](#nested-paths) +* [Special YAML features](#special-yaml-features) + * [Anchors](#anchors) + * [YAML anchors for `before_script` and `after_script`](#yaml-anchors-for-before_script-and-after_script) + * [YAML anchors for `script`](#yaml-anchors-for-script) + * [YAML anchors for variables](#yaml-anchors-for-variables) + * [Hide jobs](#hide-jobs) +* [Skip Pipeline](#skip-pipeline) +* [Processing Git pushes](#processing-git-pushes) +* [Deprecated parameters](#deprecated-parameters) + * [Globally-defined `types`](#globally-defined-types) + * [Job-defined `type`](#job-defined-type) + * [Globally-defined `image`, `services`, `cache`, `before_script`, `after_script`](#globally-defined-image-services-cache-before_script-after_script) + +# GitLab CI/CD pipeline configuration reference[](#gitlab-cicd-pipeline-configuration-reference "Permalink") + +在每个项目中,使用名为`.gitlab-ci.yml`的 YAML 文件配置 GitLab CI / CD [管道](../pipelines/index.html) . + +`.gitlab-ci.yml`文件定义管道的结构和顺序,并确定: + +* 使用[GitLab Runner](https://docs.gitlab.com/runner/)执行什么. +* 遇到特定条件时要做出什么决定. 例如,当一个过程成功或失败时. + +本主题涵盖 CI / CD 管道配置. 有关其他 CI / CD 配置信息,请参阅: + +* [GitLab CI / CD 变量](../variables/README.html) ,用于配置运行管道的环境. +* [GitLab Runner 高级配置](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) ,用于配置 GitLab Runner. + +我们有配置管道的完整示例: + +* 有关 GitLab CI / CD 的快速介绍,请遵循我们的[快速入门指南](../quick_start/README.html) . +* 有关示例集合,请参见[GitLab CI / CD 示例](../examples/README.html) . +* 要看到一个大`.gitlab-ci.yml`在企业使用的文件,看到[`.gitlab-ci.yml`文件`gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml) . + +> 有关 GitLab CI / CD 的其他信息: +> +> * 观看[CI / CD 轻松配置](https://www.youtube.com/embed/opdLqwz6tcE)视频. +> * [在组织的](https://about.gitlab.com/compare/github-actions-alternative/)网络广播中观看" [为 CI / CD](https://about.gitlab.com/compare/github-actions-alternative/)辩护",以了解 CI / CD 的好处以及如何衡量 CI / CD 自动化的结果. +> * 了解[Verizon](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/)如何使用 GitLab [将重建工作](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/)从 30 天[减少](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/)到 8 小时以下. + +**注意:**如果您有[从 GitLab 提取镜像的存储库](../../user/project/repository/repository_mirroring.html#pulling-from-a-remote-repository-starter) ,则可能需要在项目的**"设置">"存储库">"从远程存储库中提取">"触发管道更新镜像"中**启用管道触发. + +## Introduction[](#introduction "Permalink") + +管道配置从作业开始. 作业是`.gitlab-ci.yml`文件的最基本元素. + +工作是: + +* 定义了约束,指出应在什么条件下执行它们. +* 具有任意名称的顶级元素,并且必须至少包含[`script`](#script)子句. +* 不限制可以定义多少个. + +例如: + +``` +job1: + script: "execute-script-for-job1" + +job2: + script: "execute-script-for-job2" +``` + +上面的示例是具有两个单独作业的最简单的 CI / CD 配置,其中每个作业执行一个不同的命令. 当然,命令可以直接执行代码( `./configure;make;make install` )或在存储库中运行脚本( `test.sh` ). + +乔布斯被拾起[运动员](../runners/README.html)和跑步者的环境中执行. 重要的是,每个作业彼此独立运行. + +### Validate the `.gitlab-ci.yml`[](#validate-the-gitlab-ciyml "Permalink") + +GitLab CI / CD 的每个实例都有一个称为 Lint 的嵌入式调试工具,该工具可以验证`.gitlab-ci.yml`文件的内容. 您可以在项目名称空间的`ci/lint`页下找到 Lint. 例如, `https://gitlab.example.com/gitlab-org/project-123/-/ci/lint` . + +### Unavailable names for jobs[](#unavailable-names-for-jobs "Permalink") + +每个作业必须具有唯一的名称,但是有一些**保留的`keywords`不能用作作业名称** : + +* `image` +* `services` +* `stages` +* `types` +* `before_script` +* `after_script` +* `variables` +* `cache` +* `include` + +### Using reserved keywords[](#using-reserved-keywords "Permalink") + +如果在使用特定值(例如`true`或`false` )时收到验证错误,请尝试执行以下操作: + +* 引用他们. +* 将它们更改为其他形式. 例如, `/bin/true` . + +## Configuration parameters[](#configuration-parameters "Permalink") + +作业定义为定义作业行为的参数列表. + +下表列出了作业的可用参数: + +| Keyword | Description | +| --- | --- | +| [`script`](#script) | 由 Runner 执行的 Shell 脚本. | +| [`image`](#image) | 使用 Docker 映像 也可用: `image:name`和`image:entrypoint` . | +| [`services`](#services) | Use Docker services images. Also available: `services:name`, `services:alias`, `services:entrypoint`, and `services:command`. | +| [`before_script`](#before_script-and-after_script) | 覆盖作业之前执行的一组命令. | +| [`after_script`](#before_script-and-after_script) | 覆盖作业后执行的一组命令. | +| [`stage`](#stage) | 定义一个工作阶段(默认: `test` ). | +| [`only`](#onlyexcept-basic) | 限制创建作业的时间. 也可用: [`only:refs` , `only:kubernetes` , `only:variables`和`only:changes`](#onlyexcept-advanced) . | +| [`except`](#onlyexcept-basic) | 限制未创建作业的时间. 也可用: [`except:refs` , `except:kubernetes` , `except:variables`和`except:changes`](#onlyexcept-advanced) . | +| [`rules`](#rules) | 评估和确定作业的选定属性以及是否创建作业的条件列表. 不能`only`与/ `except`一起使用. | +| [`tags`](#tags) | 用于选择 Runner 的标签列表. | +| [`allow_failure`](#allow_failure) | 允许作业失败. 失败的作业不会影响提交状态. | +| [`when`](#when) | 什么时候开始工作. 也可用: `when:manual`和`when:delayed` . | +| [`environment`](#environment) | 作业部署到的环境的名称. 也可用: `environment:name` , `environment:url` , `environment:on_stop` , `environment:auto_stop_in`和`environment:action` . | +| [`cache`](#cache) | 在后续运行之间应缓存的文件列表. 也可用: `cache:paths` , `cache:key` , `cache:untracked`和`cache:policy` . | +| [`artifacts`](#artifacts) | 成功时附加到作业的文件和目录列表. 也可以使用: `artifacts:paths` , `artifacts:exclude` , `artifacts:expose_as` , `artifacts:name` , `artifacts:untracked` , `artifacts:when` , `artifacts:expire_in` , `artifacts:reports` , `artifacts:reports:junit` , `artifacts:reports:cobertura`和`artifacts:reports:terraform` . + +在 GitLab [企业版](https://about.gitlab.com/pricing/) ,这些都是可供选择: `artifacts:reports:codequality` , `artifacts:reports:sast` , `artifacts:reports:dependency_scanning` , `artifacts:reports:container_scanning` , `artifacts:reports:dast` , `artifacts:reports:license_scanning` , `artifacts:reports:license_management` (已在 GitLab 13.0 中删除), `artifacts:reports:performance`和`artifacts:reports:metrics` . | +| [`dependencies`](#dependencies) | 通过提供要从中获取工件的作业列表,限制将哪些工件传递给特定作业. | +| [`coverage`](#coverage) | 给定作业的代码覆盖率设置. | +| [`retry`](#retry) | 发生故障时可以自动重试作业的时间和次数. | +| [`timeout`](#timeout) | 定义优先于项目范围设置的自定义作业级别超时. | +| [`parallel`](#parallel) | 多少个作业实例应并行运行. | +| [`trigger`](#trigger) | 定义下游管道触发器. | +| [`include`](#include) | 允许此作业包括外部 YAML 文件. 也可用: `include:local` , `include:file` , `include:template`和`include:remote` . | +| [`extends`](#extends) | 该作业将要继承的配置条目. | +| [`pages`](#pages) | 上载作业结果以用于 GitLab 页面. | +| [`variables`](#variables) | 在作业级别上定义作业变量. | +| [`interruptible`](#interruptible) | 定义在通过新的运行使其冗余时是否可以取消作业. | +| [`resource_group`](#resource_group) | 限制作业并发. | +| [`release`](#release) | 指示 Runner 生成[Release](../../user/project/releases/index.html)对象. | + +**Note:** Parameters `types` and `type` are [deprecated](#deprecated-parameters). + +## Global parameters[](#global-parameters "Permalink") + +必须在全局级别定义一些参数,这会影响管道中的所有作业. + +### Global defaults[](#global-defaults "Permalink") + +可以使用`default:`关键字将某些参数全局设置为所有作业的`default:` . 然后可以通过特定于作业的配置覆盖默认参数. + +可以在`default:`块内定义以下作业参数: + +* [`image`](#image) +* [`services`](#services) +* [`before_script`](#before_script-and-after_script) +* [`after_script`](#before_script-and-after_script) +* [`tags`](#tags) +* [`cache`](#cache) +* [`artifacts`](#artifacts) +* [`retry`](#retry) +* [`timeout`](#timeout) +* [`interruptible`](#interruptible) + +在以下示例中,除了`rspec 2.6`作业(使用`ruby:2.6`图像)以外,所有作业的默认设置都是`ruby:2.5`图像: + +``` +default: + image: ruby:2.5 + +rspec: + script: bundle exec rspec + +rspec 2.6: + image: ruby:2.6 + script: bundle exec rspec +``` + +#### `inherit`[](#inherit "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/207484) . + +您可以使用`inherit:`参数禁用对全局定义的默认值和变量的`inherit:` . + +要启用或禁用所有`variables:`或`default:`参数的继承,请使用以下格式: + +* `default: true` or `default: false` +* `variables: true` or `variables: false` + +要仅继承`default:`参数或`variables:`的子集,请指定要继承的内容,未列出的任何内容均**不会**被继承. 使用以下格式之一: + +``` +inherit: + default: [parameter1, parameter2] + variables: [VARIABLE1, VARIABLE2] +``` + +Or: + +``` +inherit: + default: + - parameter1 + - parameter2 + variables: + - VARIABLE1 + - VARIABLE2 +``` + +在以下示例中: + +* `rubocop`: + * **会**继承:没有. +* `rspec`: + * **将**继承:默认`image`和`WEBHOOK_URL`变量. + * **不会**继承:默认的`before_script`和`DOMAIN`变量. +* `capybara`: + * **将**继承:默认的`before_script`和`image` . + * 将**不会**继承: `DOMAIN`和`WEBHOOK_URL`变量. +* `karma`: + * **将**继承:默认`image` , `before_script`和`DOMAIN`变量. + * will **not** inherit: `WEBHOOK_URL` variable. + +``` +default: + image: 'ruby:2.4' + before_script: + - echo Hello World + +variables: + DOMAIN: example.com + WEBHOOK_URL: https://my-webhook.example.com + +rubocop: + inherit: + default: false + variables: false + script: bundle exec rubocop + +rspec: + inherit: + default: [image] + variables: [WEBHOOK_URL] + script: bundle exec rspec + +capybara: + inherit: + variables: false + script: bundle exec capybara + +karma: + inherit: + default: true + variables: [DOMAIN] + script: karma +``` + +### `stages`[](#stages "Permalink") + +`stages`用于定义包含作业的阶段,并且为管道全局定义. + +的规范`stages`允许具有灵活的多阶段流水线. `stages`中元素的顺序定义了作业执行的顺序: + +1. 同一阶段的作业并行运行. +2. 前一阶段的作业成功完成后,将运行下一阶段的作业. + +让我们考虑以下示例,该示例定义了 3 个阶段: + +``` +stages: + - build + - test + - deploy +``` + +1. 首先,所有`build`作业均并行执行. +2. 如果所有`build`作业均成功,则`test`作业将并行执行. +3. 如果所有`test`作业均成功,则将并行执行`deploy`作业. +4. 如果所有`deploy`作业均成功,则将提交标记为`passed` . +5. 如果先前的任何作业失败,则将提交标记为`failed`并且不执行后续阶段的作业. + +还有两个边缘情况值得一提: + +1. 如果`.gitlab-ci.yml`中未定义任何`stages` ,则默认允许将`build` , `test`和`deploy`用作作业的阶段. +2. 如果作业未指定`stage` ,则为该作业分配`test`阶段. + +### `workflow:rules`[](#workflowrules "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/29654) + +顶级`workflow:`关键字适用于整个管道,并将确定是否创建管道. 当前,它接受一个`rules:`与[`rules:`](#rules)类似的键:在 job 中[定义](#rules) ,可动态配置管道. + +如果您不熟悉 GitLab CI / CD 和`workflow: rules` ,则可能会发现[`workflow:rules`模板](#workflowrules-templates)很有用. + +要定义自己的`workflow: rules` ,当前可用的配置选项为: + +* [`if`](#rulesif) :定义规则. +* [`when`](#when) :可以设置为`always`或`never` . 如果未提供,则默认值`always` . + +评估`if`规则的列表,直到匹配单个规则. 如果没有比赛,最后`when`会被使用: + +``` +workflow: + rules: + - if: $CI_COMMIT_REF_NAME =~ /-wip$/ + when: never + - if: $CI_COMMIT_TAG + when: never + - when: always +``` + +#### `workflow:rules` templates[](#workflowrules-templates "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/217732) . + +我们提供预制模板,供您用于设置`workflow: rules`管道使用`workflow: rules`常见方案的`workflow: rules` . 使用这些将使事情变得容易,并防止重复的管道运行. + +[`Branch-Pipelines`模板](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Workflows/Branch-Pipelines.gitlab-ci.yml)使您的管道针对分支和标签运行. + +分支管道状态将显示在使用该分支作为源的合并请求中,但是此管道类型不支持" [合并请求管道"](../merge_request_pipelines/)提供的任何功能,例如["合并结果管道"](../merge_request_pipelines/#pipelines-for-merged-results-premium)或" [合并训练"](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/) . 如果您有意避免使用这些功能,请使用此模板. + +它[包括](#include)以下内容: + +``` +include: + - template: 'Workflows/Branch-Pipelines.gitlab-ci.yml' +``` + +The [`MergeRequest-Pipelines` template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Workflows/MergeRequest-Pipelines.gitlab-ci.yml) makes your pipelines run for the default branch (usually `master`), tags, and all types of merge request pipelines. Use this template if you use any of the the [Pipelines for Merge Requests features](../merge_request_pipelines/), as mentioned above. + +它[包括](#include)以下内容: + +``` +include: + - template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml' +``` + +### `include`[](#include "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 10.5 中引入. +* 自 10.6 开始适用于 Starter,Premium 和 Ultimate. +* 在 11.4 中[移至](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/42861) GitLab Core. + +使用`include`关键字允许包含外部 YAML 文件. 这有助于将 CI / CD 配置分解为多个文件,并提高了长配置文件的可读性. 也可以将模板文件存储在中央存储库中,并且项目包括其配置文件. 这有助于避免重复配置,例如,所有项目的全局默认变量. + +`include`要求外部 YAML 文件具有扩展名`.yml`或`.yaml` ,否则将不包含外部文件. + +`include`支持以下包含方法: + +| Method | Description | +| --- | --- | +| [`local`](#includelocal) | 包括来自本地项目存储库的文件. | +| [`file`](#includefile) | 包括来自其他项目存储库的文件. | +| [`remote`](#includeremote) | 包括来自远程 URL 的文件. 必须公开可用. | +| [`template`](#includetemplate) | 包括由 GitLab 提供的模板. | + +`include`方法不支持[变量扩展](../variables/where_variables_can_be_used.html#variables-usage) . + +**注意:**所有方法包含的`.gitlab-ci.yml`配置在创建管道时进行评估. 该配置是及时的快照,并保留在数据库中. 在创建下一个管道之前,对引用的`.gitlab-ci.yml`配置的任何更改都不会反映在 GitLab 中. + +`include`定义的文件是: + +* 与`.gitlab-ci.yml`那些合并. +* 无论`include`关键字的位置如何,始终首先评估并与`.gitlab-ci.yml`的内容合并. + +**提示:**使用合并功能可以自定义和覆盖包含本地定义的 CI / CD 配置. `.gitlab-ci.yml`本地定义将覆盖包含的定义.**注意:**不支持在`include`来源的不同 YAML 文件中使用[YAML 锚](#anchors) . 您只能引用同一文件中的锚. 除了使用 YAML 定位符,您还可以使用[`extends`关键字](#extends) . + +#### `include:local`[](#includelocal "Permalink") + +`include:local`包含与`.gitlab-ci.yml`位于同一存储库中的文件. 使用相对于根目录( `/` )的完整路径进行引用. + +您只能在配置文件所在的同一分支上使用 Git 当前跟踪的文件. 换句话说,使用`include:local` ,请确保`.gitlab-ci.yml`和本地文件都在同一分支上. + +所有[嵌套的包含](#nested-includes)将在同一项目的范围内执行,因此可以使用本地,项目,远程或模板包含. + +**注意:**不支持通过 Git 子模块路径包含本地文件. + +Example: + +``` +include: + - local: '/templates/.gitlab-ci-template.yml' +``` + +**Tip:** Local includes can be used as a replacement for symbolic links which are not followed. + +可以将其定义为简短的本地包含: + +``` +include: '.gitlab-ci-production.yml' +``` + +#### `include:file`[](#includefile "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53903) . + +要在同一 GitLab 实例下包含来自另一个私有项目的`include:file` ,请使用`include:file` . 使用相对于根目录( `/` )的完整路径引用该文件. 例如: + +``` +include: + - project: 'my-group/my-project' + file: '/templates/.gitlab-ci-template.yml' +``` + +您还可以指定`ref` ,默认值为项目的`HEAD` : + +``` +include: + - project: 'my-group/my-project' + ref: master + file: '/templates/.gitlab-ci-template.yml' + + - project: 'my-group/my-project' + ref: v1.0.0 + file: '/templates/.gitlab-ci-template.yml' + + - project: 'my-group/my-project' + ref: 787123b47f14b552955ca2786bc9542ae66fee5b # Git SHA + file: '/templates/.gitlab-ci-template.yml' +``` + +所有[嵌套的包含](#nested-includes)将在目标项目的范围内执行,因此可以使用本地(相对于目标项目),项目,远程或模板包含. + +#### `include:remote`[](#includeremote "Permalink") + +`include:remote`可用于通过 HTTP / HTTPS 包含来自其他位置的文件,并使用完整 URL 进行引用. 远程文件必须可以通过简单的 GET 请求公开访问,因为不支持远程 URL 中的身份验证模式. 例如: + +``` +include: + - remote: 'https://gitlab.com/awesome-project/raw/master/.gitlab-ci-template.yml' +``` + +所有[嵌套的 include](#nested-includes)将在没有上下文的情况下作为公共用户执行,因此仅允许另一个远程或公共项目或模板. + +#### `include:template`[](#includetemplate "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53445) . + +`include:template`可用于包含[GitLab 随附的](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates) `.gitlab-ci.yml`模板. + +例如: + +``` +# File sourced from GitLab's template collection +include: + - template: Auto-DevOps.gitlab-ci.yml +``` + +Multiple `include:template` files: + +``` +include: + - template: Android-Fastlane.gitlab-ci.yml + - template: Auto-DevOps.gitlab-ci.yml +``` + +所有[嵌套的包含](#nested-includes)将仅在用户许可下执行,因此可以使用项目,远程或模板包含. + +#### Nested includes[](#nested-includes "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/56836) . + +嵌套包含可让您组成一组包含. + +总共允许 100 个 include,但是重复的 include 被视为配置错误. + +从[GitLab 12.4 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/28212) ,解析所有文件的时间限制为 30 秒. + +#### Additional `includes` examples[](#additional-includes-examples "Permalink") + +有可用的[其他`includes`示例](includes.html)列表. + +## Parameter details[](#parameter-details "Permalink") + +以下是用于配置 CI / CD 管道的参数的详细说明. + +### `image`[](#image "Permalink") + +用于指定要用于作业[的 Docker 映像](../docker/using_docker_images.html#what-is-an-image) . + +For: + +* Simple definition examples, see [Define `image` and `services` from `.gitlab-ci.yml`](../docker/using_docker_images.html#define-image-and-services-from-gitlab-ciyml). +* 详细的使用信息,请参阅[Docker 集成](../docker/README.html)文档. + +#### `image:name`[](#imagename "Permalink") + +An [extended Docker configuration option](../docker/using_docker_images.html#extended-docker-configuration-options). + +有关更多信息,请参阅[`image`可用设置](../docker/using_docker_images.html#available-settings-for-image) . + +#### `image:entrypoint`[](#imageentrypoint "Permalink") + +An [extended Docker configuration option](../docker/using_docker_images.html#extended-docker-configuration-options). + +有关更多信息,请参阅[`image`可用设置](../docker/using_docker_images.html#available-settings-for-image) . + +#### `services`[](#services "Permalink") + +用于指定[服务 Docker 映像](../docker/using_docker_images.html#what-is-a-service) ,该映像链接到 image 中指定的基本[`image`](#image) . + +For: + +* 简单的定义示例,请参阅[从`.gitlab-ci.yml`定义`image`和`services`](../docker/using_docker_images.html#define-image-and-services-from-gitlab-ciyml) . +* 详细的使用信息,请参阅[Docker 集成](../docker/README.html)文档. +* 有关示例服务,请参见[GitLab CI / CD 服务](../services/README.html) . + +##### `services:name`[](#servicesname "Permalink") + +An [extended Docker configuration option](../docker/using_docker_images.html#extended-docker-configuration-options). + +For more information, see [Available settings for `services`](../docker/using_docker_images.html#available-settings-for-services). + +##### `services:alias`[](#servicesalias "Permalink") + +An [extended Docker configuration option](../docker/using_docker_images.html#extended-docker-configuration-options). + +有关更多信息,请参阅[`services`可用设置](../docker/using_docker_images.html#available-settings-for-services) . + +##### `services:entrypoint`[](#servicesentrypoint "Permalink") + +An [extended Docker configuration option](../docker/using_docker_images.html#extended-docker-configuration-options). + +有关更多信息,请参阅[`services`可用设置](../docker/using_docker_images.html#available-settings-for-services) . + +##### `services:command`[](#servicescommand "Permalink") + +An [extended Docker configuration option](../docker/using_docker_images.html#extended-docker-configuration-options). + +有关更多信息,请参阅[`services`可用设置](../docker/using_docker_images.html#available-settings-for-services) . + +### `script`[](#script "Permalink") + +`script`是作业所需的唯一必需关键字. 这是一个由 Runner 执行的 shell 脚本. 例如: + +``` +job: + script: "bundle exec rspec" +``` + +[脚本的 YAML 锚](#yaml-anchors-for-script)可用. + +此参数还可以包含使用数组的多个命令: + +``` +job: + script: + - uname -a + - bundle exec rspec +``` + +**注意:**有时, `script`命令将需要用单引号或双引号引起来. 例如,包含冒号命令( `:` )需要加引号,以便被包裹的 YAML 解析器知道来解释整个事情作为一个字符串,而不是一个"键:值"对. 使用特殊字符时要小心: `:` , `{` , `}` , `[` , `]` , `,` , `&` , `*` , `#` , `?` , `|` , `-` , `<` , `>` , `=` `!` , `%` , `@` , ``` . + +如果任何脚本命令返回的退出代码都不为零,则该作业将失败,并且其他命令将不再执行. 通过将退出代码存储在变量中,可以避免此行为: + +``` +job: + script: + - false || exit_code=$? + - if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi; +``` + +#### `before_script` and `after_script`[](#before_script-and-after_script "Permalink") + +在 GitLab 8.7 中引入,需要 GitLab Runner v1.2. + +`before_script`用于定义一个命令,该命令应在每个作业(包括部署作业)之前,但在还原任何[工件之后运行](#artifacts) . 这必须是一个数组. + +`before_script`中指定的[`script`](#script)与主脚本中指定的任何脚本串联在一起,并在单个 shell 中一起执行. + +`after_script`用于定义将在每个作业(包括失败的作业)之后运行的命令. 这必须是一个数组. + +`after_script`中指定的脚本在新的 shell 中执行,与任何`before_script`或`script`脚本分开. 结果,他们: + +* 将当前工作目录设置回默认目录. +* 无法访问由`before_script`或`script`定义的脚本完成的更改,包括: + * `script`脚本中导出的命令别名和变量. + * 在工作树之外进行更改(取决于 Runner 执行程序),例如`before_script`或`script`脚本安装的软件. +* 有一个单独的超时,硬编码为 5 分钟. 有关详细信息,请参见[相关问题](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2716) . +* 不要影响作业的退出代码. 如果`script`部分成功并且`after_script`超时或失败,则该作业将以代码`0` ( `Job Succeeded` )退出. + +如果按工作设置全局定义的`before_script`或`after_script`则有可能覆盖它: + +``` +default: + before_script: + - global before script + +job: + before_script: + - execute this instead of global before script + script: + - my command + after_script: + - execute this after my script +``` + +[YAML anchors for `before_script` and `after_script`](#yaml-anchors-for-before_script-and-after_script) are available. + +#### Coloring script output[](#coloring-script-output "Permalink") + +脚本输出可以使用[ANSI 转义码](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors)或运行输出 ANSI 转义码的命令或程序来着色. + +例如,使用[带有颜色代码的 Bash](https://misc.flogisoft.com/bash/tip_colors_and_formatting) : + +``` +job: + script: + - echo -e "\e[31mThis text is red,\e[0m but this text isn't\e[31m however this text is red again." +``` + +您可以在 Shell 变量甚至[自定义环境变量中](../variables/README.html#custom-environment-variables)定义颜色代码,这使命令更易于阅读和重用. + +例如,使用与上述相同的示例以及在`before_script`定义的变量: + +``` +job: + before_script: + - TXT_RED="\e[31m" && TXT_CLEAR="\e[0m" + script: + - echo -e "${TXT_RED}This text is red,${TXT_CLEAR} but this part isn't${TXT_RED} however this part is again." + - echo "This text is not colored" +``` + +或使用[PowerShell 颜色代码](https://superuser.com/a/1259916) : + +``` +job: + before_script: + - $esc="$([char]27)"; $TXT_RED="$esc[31m"; $TXT_CLEAR="$esc[0m" + script: + - Write-Host $TXT_RED"This text is red,"$TXT_CLEAR" but this text isn't"$TXT_RED" however this text is red again." + - Write-Host "This text is not colored" +``` + +#### Multiline commands[](#multiline-commands "Permalink") + +您可以使用[`|`](https://yaml-multiline.info/)将长命令分成多行命令以提高可读性[`|`](https://yaml-multiline.info/) [(文字)和`>` (折叠)YAML 多行块标量指标](https://yaml-multiline.info/) . + +**警告:**如果将多个命令组合到一个命令字符串中,则只会报告最后一个命令的失败或成功, [错误地忽略了由于 bug 导致的先前命令的失败](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394) . 如果作业的成功取决于这些命令的成功或失败,则可以将命令作为单独的`script:`项目运行,或在需要时将`exit 1`命令添加到适当的命令字符串中. + +您可以使用`|` (文字)YAML 多行块标量指示器,用于在作业描述的`script`部分中的多行上编写命令. 每行都被视为一个单独的命令. 在作业日志中仅重复第一个命令,但仍执行其他命令: + +``` +job: + script: + - | + echo "First command line." + echo "Second command line." + echo "Third command line." +``` + +上面的示例在作业日志中呈现为: + +``` +$ echo First command line # collapsed multi-line command +First command line +Second command line. +Third command line. +``` + +`>` (折叠的)YAML 多行块标量指示符将节之间的空行视为新命令的开始: + +``` +job: + script: + - > + echo "First command line + is split over two lines." + + echo "Second command line." +``` + +这与编写不带`>`或`|`多行命令的行为类似 块标量指标: + +``` +job: + script: + - echo "First command line + is split over two lines." + + echo "Second command line." +``` + +上面的两个示例在作业日志中均显示为: + +``` +$ echo First command line is split over two lines. # collapsed multi-line command +First command line is split over two lines. +Second command line. +``` + +当`>`或`|` 块标量指示符被省略,GitLab 将通过连接非空行来形成命令,因此请确保在连接时行可以运行. + +[此处的](https://en.wikipedia.org/wiki/Here_document) Shell [文件可](https://en.wikipedia.org/wiki/Here_document)与`|` 和`>`运算符. 下面的示例将小写字母音译为大写字母: + +``` +job: + script: + - | + tr a-z A-Z << END_TEXT + one two three + four five six + END_TEXT +``` + +结果是: + +``` +$ tr a-z A-Z << END_TEXT # collapsed multi-line command + ONE TWO THREE + FOUR FIVE SIX +``` + +### `stage`[](#stage "Permalink") + +`stage`是按职位定义的,并且依赖于全局定义的[`stages`](#stages) . 它允许将作业分为不同的阶段,并且同一`stage`作业可以并行执行(取决于[特定条件](#using-your-own-runners) ). 例如: + +``` +stages: + - build + - test + - deploy + +job 0: + stage: .pre + script: make something useful before build stage + +job 1: + stage: build + script: make build dependencies + +job 2: + stage: build + script: make build artifacts + +job 3: + stage: test + script: make test + +job 4: + stage: deploy + script: make deploy + +job 5: + stage: .post + script: make something useful at the end of pipeline +``` + +#### Using your own Runners[](#using-your-own-runners "Permalink") + +使用自己的 Runners 时,默认情况下,GitLab Runner 一次仅运行一个作业(有关更多信息,请参见[Runner 全局设置中](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)的`concurrent`标志). + +仅在以下情况下,作业将在您自己的跑步者上并行运行: + +* Run on different Runners. +* 跑步者的`concurrent`设置已更改. + +#### `.pre` and `.post`[](#pre-and-post "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31441) . + +每个管道均可使用以下阶段: + +* `.pre` ,它始终是管道中的第一阶段. +* `.post` ,它始终是管道中的最后一个阶段. + +用户定义的阶段在`.pre`之后和`.post`之前执行. + +即使`.gitlab-ci.yml`定义不正确, `.pre`和`.post`的顺序也无法更改. 例如,以下是等效配置: + +* 按顺序配置: + + ``` + stages: + - .pre + - a + - b + - .post + ``` + +* 配置乱序: + + ``` + stages: + - a + - .pre + - b + - .post + ``` + +* 未明确配置: + + ``` + stages: + - a + - b + ``` + +**Note:** A pipeline won’t be created if it only contains jobs in `.pre` or `.post` stages. + +### `extends`[](#extends "Permalink") + +在 GitLab 11.3 中引入. + +`extends`定义使用`extends`的作业将要继承的条目名称. + +它是使用[YAML 锚点](#anchors)的替代方法,并且更具灵活性和可读性: + +``` +.tests: + script: rake test + stage: test + only: + refs: + - branches + +rspec: + extends: .tests + script: rake rspec + only: + variables: + - $RSPEC +``` + +在上面的示例中, `rspec`作业继承自`.tests`模板作业. GitLab 将基于密钥执行反向深度合并. GitLab 将: + +* Merge the `rspec` contents into `.tests` recursively. +* 不合并键的值. + +这将导致以下`rspec`作业: + +``` +rspec: + script: rake rspec + stage: test + only: + refs: + - branches + variables: + - $RSPEC +``` + +**注意:**请注意, `script: rake test`已被`script: rake rspec`覆盖. + +如果您确实希望包含`rake test` ,请参见[`before_script`和`after_script`](#before_script-and-after_script) . + +在此示例中, `.tests`是[隐藏作业](#hide-jobs) ,但是也可以从常规作业继承. + +`extends`支持多级继承,但是不建议使用三个以上级别. 支持的最大嵌套级别为 10.以下示例具有两个继承级别: + +``` +.tests: + only: + - pushes + +.rspec: + extends: .tests + script: rake rspec + +rspec 1: + variables: + RSPEC_SUITE: '1' + extends: .rspec + +rspec 2: + variables: + RSPEC_SUITE: '2' + extends: .rspec + +spinach: + extends: .tests + script: rake spinach +``` + +在 GitLab 12.0 和更高版本中,还可以使用多个父对象进行`extends` . + +#### Merge details[](#merge-details "Permalink") + +`extends`可以合并哈希,但不能合并数组. 用于合并的算法是"最近的范围获胜",因此来自最后一个成员的键将始终覆盖在其他级别定义的任何内容. 例如: + +``` +.only-important: + variables: + URL: "http://my-url.internal" + IMPORTANT_VAR: "the details" + only: + - master + - stable + tags: + - production + script: + - echo "Hello world!" + +.in-docker: + variables: + URL: "http://docker-url.internal" + tags: + - docker + image: alpine + +rspec: + variables: + GITLAB: "is-awesome" + extends: + - .only-important + - .in-docker + script: + - rake rspec +``` + +这将导致以下`rspec`作业: + +``` +rspec: + variables: + URL: "http://docker-url.internal" + IMPORTANT_VAR: "the details" + GITLAB: "is-awesome" + only: + - master + - stable + tags: + - docker + image: alpine + script: + - rake rspec +``` + +请注意,在上面的示例中: + +* `variables`部分已合并,但`URL: "http://my-url.internal"`已被`URL: "http://docker-url.internal"`覆盖. +* `tags: ['production']`已被`tags: ['docker']`覆盖. +* `script`尚未合并,而是`script: ['echo "Hello world!"']`被`script: ['rake rspec']`覆盖. 可以使用[YAML 锚点](#anchors)合并数组. + +#### Using `extends` and `include` together[](#using-extends-and-include-together "Permalink") + +`extends`配置文件`extends`到`include`配置文件. + +例如,如果您有本地`included.yml`文件: + +``` +.template: + script: + - echo Hello! +``` + +然后,在`.gitlab-ci.yml`您可以像这样使用它: + +``` +include: included.yml + +useTemplate: + image: alpine + extends: .template +``` + +这将运行一个名为`useTemplate`的作业,该作业运行`echo Hello!` 如`.template`作业中所定义,并使用本地作业中所定义的`alpine` Docker 映像. + +### `rules`[](#rules "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27863) . + +`rules`关键字是一种设置作业策略的方法,该策略确定是否将作业添加到管道. + +将按*顺序*评估单个规则子句的列表,直到一个匹配. 匹配后,根据配置将作业包括在管道中或从管道中排除. 如果包含,则作业还会添加[某些属性](#rules-attributes) . + +**注意:** `rules`不能[`only/except`](#onlyexcept-basic)与[`only/except`](#onlyexcept-basic)不能结合使用,因为它是该功能的替代品. 如果尝试执行此操作,则 linter 返回的`key may not be used with rules`错误`key may not be used with rules` . + +#### Rules attributes[](#rules-attributes "Permalink") + +`rules`允许的作业属性是: + +* [`when`](#when) :如果未定义,则默认为`when: on_success` . + * 如果用作`when: delayed` ,则还需要`start_in` . +* [`allow_failure`](#allow_failure) :如果未定义,则默认为`allow_failure: false` . + +如果一个规则的计算结果为 true,并且`when`具有除`never`以外的任何值`when` ,该作业将包括在管道中. + +例如: + +``` +docker build: + script: docker build -t my-image:$CI_COMMIT_REF_SLUG . + rules: + - if: '$CI_COMMIT_BRANCH == "master"' + when: delayed + start_in: '3 hours' + allow_failure: true +``` + +将来可能会将其他作业配置添加到规则中. 如果没有有用的东西,请[打开一个问题](https://gitlab.com/gitlab-org/gitlab/-/issues) . + +#### Rules clauses[](#rules-clauses "Permalink") + +可用的规则子句为: + +| Clause | Description | +| --- | --- | +| [`if`](#rulesif) | 通过评估`if`语句在管道中添加或排除作业. 与[`only:variables`](#onlyvariablesexceptvariables)类似. | +| [`changes`](#ruleschanges) | 根据更改的文件在管道中添加或排除作业. 与[`only:changes`](#onlychangesexceptchanges)相同. | +| [`exists`](#rulesexists) | 根据特定文件的存在在管道中添加或排除作业. | + +Rules are evaluated in order until a match is found. If a match is found, the attributes are checked to see if the job should be added to the pipeline. If no attributes are defined, the defaults are: + +* `when: on_success` +* `allow_failure: false` + +作业已添加到管道中: + +* 如果规则匹配并且具有以下条件`when: on_success` , `when: delayed` `when: on_success`或`when: always` . +* 如果没有规则匹配,但最后一个子句为`when: on_success` , `when: delayed` `when: on_success`或`when: always` (无规则). + +作业未添加到管道: + +* 如果没有规则匹配,并且在以下情况下没有独立的条件`when: on_success` , `when: delayed` `when: on_success`或`when: always` . +* 如果规则匹配,并且具有以下条件`when: never`作为属性. + +例如,使用`if`子句严格限制作业运行的时间: + +``` +job: + script: "echo Hello, Rules!" + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + when: manual + allow_failure: true + - if: '$CI_PIPELINE_SOURCE == "schedule"' +``` + +在此示例中: + +* 如果管道用于合并请求,则第一个规则匹配,并且作业将添加到[合并请求管道](../merge_request_pipelines/index.html) ,其属性为: + * `when: manual` (手动工作) + * `allow_failure: true` (即使未运行手动作业,也允许管道继续运行) +* 如果管道**不是**用于合并请求的,则第一条规则不匹配,并且第二条规则被评估. +* 如果管道是计划的管道,则第二条规则匹配,并将作业添加到计划的管道. 由于未定义任何属性,因此添加了: + * `when: on_success` (默认) + * `allow_failure: false` (默认) +* 在**所有其他情况下** ,没有规则匹配,因此该作业**不会**添加到任何其他管道. + +另外,您可以定义一组规则以在某些情况下排除作业,但在所有其他情况下运行它们: + +``` +job: + script: "echo Hello, Rules!" + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + when: never + - if: '$CI_PIPELINE_SOURCE == "schedule"' + when: never + - when: on_success +``` + +* 如果管道用于合并请求, **则不**会将作业添加到管道. +* 如果管道是计划的管道, **则不**会将作业添加到管道. +* 在**所有其他情况下** ,将使用以下时间将作业添加到管道中`when: on_success` . + +**注意**如果你使用`when: on_success` , `always` ,或`delayed`作为最终的规则,两个同时进行的管道可能会启动. 推送管道和合并请求管道都可以由同一事件触发(对于打开的合并请求,将其推送到源分支). 请参阅[`rules`之间](#differences-between-rules-and-onlyexcept)的[重要区别, `only` / `except`](#differences-between-rules-and-onlyexcept)以获取更多详细信息. + +#### Differences between `rules` and `only`/`except`[](#differences-between-rules-and-onlyexcept "Permalink") + +默认情况下, `only/except`定义的作业不会触发合并请求管道. 您必须`only: merge_requests`明确添加`only: merge_requests` . + +用`rules`定义的作业可以触发所有类型的管道. 您不必显式配置每种类型. + +例如: + +``` +job: + script: "echo This creates double pipelines!" + rules: + - if: '$CUSTOM_VARIABLE == "false"' + when: never + - when: always +``` + +This job does not run when `$CUSTOM_VARIABLE` is false, but it *does* run in **all** other pipelines, including **both** push (branch) and merge request pipelines. With this configuration, every push to an open merge request’s source branch causes duplicated pipelines. Explicitly allowing both push and merge request pipelines in the same job could have the same effect. + +我们建议使用[`workflow: rules`](#workflowrules)来限制允许的管道类型. 仅允许合并请求管道,或仅允许分支管道,可以消除重复的管道. 另外,您也可以使用最终避免重写规则更严格,或`when` ( `always` , `on_success`或`delayed` ). + +另外,我们不建议在同一管道中将`only/except`作业与`rules`作业混合使用. 它可能不会导致 YAML 错误,但是由于`only/except`和`rules`默认行为不同,因此调试确切的执行行为可能会很复杂. + +##### `rules:if`[](#rulesif "Permalink") + +`rules:if`子句通过评估简单的`if`语句来确定是否将作业添加到管道. 如果`if`语句为 true,则将作业包括在管道中或从管道中排除. 用简单的英语, `if`规则可以解释为之一: + +* "如果此规则评估为 true,则添加作业"(默认值). +* "如果该规则评估为 true,则不要添加作业"(通过添加`when: never` ). + +`rules:if`与`only:variables`略有不同,每个规则仅接受一个表达式字符串,而不是它们的数组. 可以使用`&&`或`||`将要求值的任何表达式集组合为一个表达式. ,并使用[变量匹配语法](../variables/README.html#syntax-of-environment-variable-expressions) . + +`if:` clauses are evaluated based on the values of [predefined environment variables](../variables/predefined_variables.html) or [custom environment variables](../variables/README.html#custom-environment-variables). + +例如: + +``` +job: + script: "echo Hello, Rules!" + rules: + - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"' + when: always + - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/' + when: manual + allow_failure: true + - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME' # Checking for the presence of a variable is possible +``` + +有关确定`when`上班的逻辑的一些详细信息: + +* 如果提供的规则都不匹配,则将作业设置为以下`when: never` ,并且不包含在管道中. +* 不带任何条件子句的规则,例如不带`if`或`changes`的`when`或`allow_failure`规则,始终匹配,并且在达到条件时始终使用. +* If a rule matches and has no `when` defined, the rule uses the `when` defined for the job, which defaults to `on_success` if not defined. +* 您可以定义`when`一次按规则,或在一次作业级别,它适用于所有规则. 你不能混用`when`在作业水平`when`的规则. + +对于类似于[`only` / `except`关键字的](#onlyexcept-basic)行为,可以检查`$CI_PIPELINE_SOURCE`变量的值. + +| Value | Description | +| --- | --- | +| `push` | 对于由`git push`事件触发的管道,包括分支和标签. | +| `web` | 对于使用 GitLab UI 中的**"运行管道"**按钮创建的**管道** ,请从项目的**CI / CD>"管道"**部分. | +| `trigger` | For pipelines created by using a trigger token. | +| `schedule` | For [scheduled pipelines](../pipelines/schedules.html). | +| `api` | 对于由[管道 API](../../api/pipelines.html#create-a-new-pipeline)触发的[管道](../../api/pipelines.html#create-a-new-pipeline) . | +| `external` | 使用除 GitLab 以外的 CI 服务时. | +| `pipelines` | 对于通过[将 API 与`CI_JOB_TOKEN`一起使用](../triggers/README.html#when-used-with-multi-project-pipelines)创建的多项目管道. | +| `chat` | 对于使用[GitLab ChatOps](../chatops/README.html)命令创建的管道. | +| `webide` | 对于使用[WebIDE](../../user/project/web_ide/index.html)创建的管道. | +| `merge_request_event` | 对于在创建或更新合并请求时创建的管道. 启用[合并请求管道](../merge_request_pipelines/index.html) , [合并结果管道](../merge_request_pipelines/pipelines_for_merged_results/index.html)和[合并序列所](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)必需. | +| `external_pull_request_event` | 在 GitHub 上创建或更新外部拉取请求时. 有关[外部拉取请求,](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)请参见[管道](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests) . | +| `parent_pipeline` | 对于由具有`rules`的[父/子](../parent_child_pipelines.html)管道触发的[管道](../parent_child_pipelines.html) ,请在子管道配置中使用它,以便可以由父管道触发. | + +例如: + +``` +job: + script: "echo Hello, Rules!" + rules: + - if: '$CI_PIPELINE_SOURCE == "schedule"' + when: manual + allow_failure: true + - if: '$CI_PIPELINE_SOURCE == "push"' +``` + +此示例在以下情况下在计划的管道或推送管道(到分支或标签)中将其作为手动作业运行`when: on_success` (默认). 不会将作业添加到任何其他管道类型. + +另一个例子: + +``` +job: + script: "echo Hello, Rules!" + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + - if: '$CI_PIPELINE_SOURCE == "schedule"' +``` + +本示例将作业作为以下`when: on_success`运行`when: on_success`在[合并请求管道](../merge_request_pipelines/index.html)和计划管道中的`when: on_success`作业. 它不能在任何其他管道类型中运行. + +`if`子句的其他常用变量: + +* `if: $CI_COMMIT_TAG` :是否为标签推送更改. +* `if: $CI_COMMIT_BRANCH` :是否将更改推送到任何分支. +* `if: '$CI_COMMIT_BRANCH == "master"'` :如果将更改推送到`master` . +* `if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'` :如果将更改推送到默认分支(通常是`master` ). 如果在可能具有不同默认分支的多个项目中重用同一配置,则很有用. +* `if: '$CI_COMMIT_BRANCH =~ /regex-expression/'` :如果 commit 分支与正则表达式匹配. +* `if: '$CUSTOM_VARIABLE !~ /regex-expression/'` :如果[自定义变量](../variables/README.html#custom-environment-variables) `CUSTOM_VARIABLE`与正则表达式**不**匹配. +* `if: '$CUSTOM_VARIABLE == "value1"'` :如果自定义变量`CUSTOM_VARIABLE`恰好是`value1` . + +##### `rules:changes`[](#ruleschanges "Permalink") + +要确定是否应将作业添加到管道,请使用`rules: changes`子句检查由 Git push 事件更改的文件. + +`rules: changes`工作方式与[`only: changes`和`except: changes`](#onlychangesexceptchanges) ,接受路径数组. 同样,如果没有 Git 推送事件,则始终返回 true. 它仅应用于分支管道或合并请求管道. + +例如: + +``` +workflow: + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + +docker build: + script: docker build -t my-image:$CI_COMMIT_REF_SLUG . + rules: + - changes: + - Dockerfile + when: manual + allow_failure: true +``` + +在此示例中: + +* [`workflow: rules`](#workflowrules)仅允许用于所有作业的合并请求的管道. +* 如果`Dockerfile`已更改,则将作业作为手动作业添加到管道中,并允许管道继续运行,即使未触发该作业( `allow_failure: true` ). +* 如果`Dockerfile`尚未更改,请不要将作业添加到任何管道(与`when: never`相同). + +##### `rules:exists`[](#rulesexists "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/24021) . + +`exists` accepts an array of paths and will match if any of these paths exist as files in the repository. + +例如: + +``` +job: + script: docker build -t my-image:$CI_COMMIT_REF_SLUG . + rules: + - exists: + - Dockerfile +``` + +您还可以使用全局模式来匹配存储库中任何目录中的多个文件. + +例如: + +``` +job: + script: bundle exec rspec + rules: + - exists: + - spec/**.rb +``` + +**注意:**出于性能原因,使用`exists`与模式限制为 10000 个检查. 第 10000 次检查后,带有图案化球形的规则将始终匹配. + +##### `rules:allow_failure`[](#rulesallow_failure "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30235) . + +您可以在`rules:`使用[`allow_failure: true`](#allow_failure) `rules:`在不停止管道本身的情况下允许作业失败或手动作业等待操作. 所有使用`rules:`作业`rules:`默认为`allow_failure: false`如果`allow_failure:` , `allow_failure: false` . + +规则级`rules:allow_failure`选项将覆盖作业级[`allow_failure`](#allow_failure)选项,并且仅在特定规则触发作业时才应用. + +``` +job: + script: "echo Hello, Rules!" + rules: + - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"' + when: manual + allow_failure: true +``` + +在此示例中,如果第一个规则匹配,则作业将具有以下`when: manual`和`allow_failure: true` . + +#### Complex rule clauses[](#complex-rule-clauses "Permalink") + +要使`if` , `changes`和`exists`子句与 AND 结合在一起,请在同一规则中使用它们. + +在以下示例中: + +* 如果`Dockerfile`或`Dockerfile` `docker/scripts/`任何文件已更改并且`$VAR == "string value"`我们将手动运行作业. +* 否则,该作业将不会包含在管道中. + +``` +docker build: + script: docker build -t my-image:$CI_COMMIT_REF_SLUG . + rules: + - if: '$VAR == "string value"' + changes: # Will include the job and set to when:manual if any of the follow paths match a modified file. + - Dockerfile + - docker/scripts/* + when: manual + # - when: never would be redundant here, this is implied any time rules are listed. +``` + +当前`only`可用于/ `except`关键字(例如`branches`或`refs`在`rules`尚不可用,因为在这种情况下,它们的用法和行为被单独考虑. 我们将在[史诗](https://gitlab.com/groups/gitlab-org/-/epics/2783)中讨论未来的关键字改进, [以改进`rules`](https://gitlab.com/groups/gitlab-org/-/epics/2783) ,任何人都可以添加建议或请求. + +### `only`/`except` (basic)[](#onlyexcept-basic "Permalink") + +**注意:** [`rules`](#rules)语法是一种改进的功能更强大的解决方案,用于定义作业何时运行或不运行. 考虑使用`rules`而不是`only/except`来最大程度地利用管道. + +`only`和`except`是用于设置作业策略以限制创建作业时间的两个参数: + +1. `only` defines the names of branches and tags for which the job will run. +2. `except`定义将**不**运行作业的分支和标签的名称. + +有一些适用于作业策略的规则: + +* `only`且`except` . 如果作业规范中同时定义了`only`和`except` ,则 ref 将被`only`和`except`过滤. +* `only`且`except`允许使用正则表达式( [受支持的 regexp 语法](#supported-onlyexcept-regexp-syntax) ). +* `only`且`except`允许指定存储库路径以过滤派生作业. + +此外, `only`和`except`允许使用特殊关键字: + +| **Value** | **Description** | +| --- | --- | +| `branches` | 当管道的 Git 参考是分支时. | +| `tags` | 当管道的 Git 参考是标签时. | +| `api` | 对于由[管道 API](../../api/pipelines.html#create-a-new-pipeline)触发的[管道](../../api/pipelines.html#create-a-new-pipeline) . | +| `external` | 使用除 GitLab 以外的 CI 服务时. | +| `pipelines` | 对于通过将 API 与`CI_JOB_TOKEN`一起使用创建的多项目管道. | +| `pushes` | 对于由`git push`事件触发的管道,包括分支和标签. | +| `schedules` | For [scheduled pipelines](../pipelines/schedules.html). | +| `triggers` | 对于使用触发令牌创建的管道. | +| `web` | 对于使用 GitLab UI 中的**"运行管道"**按钮创建的**管道** ,请从项目的**CI / CD>"管道"**部分. | +| `merge_requests` | 对于在创建或更新合并请求时创建的管道. 启用[合并请求管道](../merge_request_pipelines/index.html) , [合并结果管道](../merge_request_pipelines/pipelines_for_merged_results/index.html)和[合并序列](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html) . | +| `external_pull_requests` | 在 GitHub 上创建或更新[外部拉取请求时](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests) (有关[外部拉取请求,](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)请参见[管道](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests) ). | +| `chat` | 对于使用[GitLab ChatOps](../chatops/README.html)命令创建的管道. | + +在下面的例子中, `job`将只运行了与裁判开始`issue-` ,而所有分支机构将被忽略: + +``` +job: + # use regexp + only: + - /^issue-.*$/ + # use special keyword + except: + - branches +``` + +模式匹配默认情况下区分大小写. 使用`i`标志修饰符,例如`/pattern/i` ,使模式不区分大小写: + +``` +job: + # use regexp + only: + - /^issue-.*$/i + # use special keyword + except: + - branches +``` + +在此示例中, `job`仅对标记了标签的引用运行,或者如果通过 API 触发器或[管道时间表](../pipelines/schedules.html)明确请求构建,则`job`将运行: + +``` +job: + # use special keywords + only: + - tags + - triggers + - schedules +``` + +存储库路径可用于仅对父存储库执行作业,而不能用于派生: + +``` +job: + only: + - branches@gitlab-org/gitlab + except: + - master@gitlab-org/gitlab + - /^release/.*$/@gitlab-org/gitlab +``` + +上面的示例将为`gitlab-org/gitlab`上的所有分支运行`job` ,但`master`和名称以`release/` `gitlab-org/gitlab`分支除外. + +如果作业没有`only`规则,则默认情况下`only: ['branches', 'tags']` . 如果没有`except`规则,则为空. + +例如, + +``` +job: + script: echo 'test' +``` + +转换为: + +``` +job: + script: echo 'test' + only: ['branches', 'tags'] +``` + +#### Regular expressions[](#regular-expressions "Permalink") + +因为`@`用于表示 ref 的存储库路径的开头,所以匹配正则表达式中包含`@`字符的 ref 名称需要使用十六进制字符代码匹配`\x40` . + +正则表达式只能匹配标签或分支名称. 如果给定存储库路径,则始终在字面上匹配. + +如果必须使用正则表达式来匹配标记或分支名称,则模式的整个 ref 名称部分必须是正则表达式,并且必须用`/`括起来. (在结束符`/`之后附加正则表达式标志.)因此`issue-/.*/`不能匹配所有以`issue-`开头的标记名或分支名. + +**提示**使用定位符`^`和`$`避免正则表达式仅匹配标记名称或分支名称的子字符串. 例如, `/^issue-/` `/^issue-.*$/` `/^issue-/`等效于`/^issue-/` `/^issue-.*$/` `/^issue-/` ,而只是`/issue/`也会匹配一个名为`/^issue-.*$/` `severe-issues`的分支. + +#### Supported `only`/`except` regexp syntax[](#supported-onlyexcept-regexp-syntax "Permalink") + +**警告:**这是 GitLab 11.9.4 引入的重大更改. + +在 GitLab 11.9.4 中,GitLab 开始内部将`only`用于参数(参数`except` regexp 转换为[RE2](https://github.com/google/re2/wiki/Syntax) . + +这意味着仅支持[Ruby Regexp](https://ruby-doc.org/core/Regexp.html)提供的功能子集. 由于计算复杂性, [RE2](https://github.com/google/re2/wiki/Syntax)限制了所提供的功能集,这意味着某些功能在 GitLab 11.9.4 中变得不可用. 例如,负面的前瞻. + +For GitLab versions from 11.9.7 and up to GitLab 12.0, GitLab provides a feature flag that can be enabled by administrators that allows users to use unsafe regexp syntax. This brings compatibility with previously allowed syntax version and allows users to gracefully migrate to the new syntax. + +``` +Feature.enable(:allow_unsafe_ruby_regexp) +``` + +### `only`/`except` (advanced)[](#onlyexcept-advanced "Permalink") + +**警告:**这是*Alpha 版*功能,如有更改,恕不另行通知! + +GitLab 支持简单策略和复杂策略,因此可以使用数组和哈希配置方案. + +有四个键可用: + +* `refs` +* `variables` +* `changes` +* `kubernetes` + +如果`only`或`except`下使用多个键,则这些键将被视为单个联合表达式. 那是: + +* `only:`表示"如果所有条件都匹配,则包括此作业". +* `except:`表示"如果任何条件匹配,则排除此工作". + +使用`only` ,各个键在逻辑上由 AND 联接: + +> (任何参考)AND(任何变量)AND(任何变化)AND(如果 Kubernetes 是活动的) + +在下面的示例中, `only`在满足以下**所有条件** `only`创建`test`作业: + +* 该管道已被[调度](../../user/project/pipelines/schedules.html) **或**正在`master`管道运行. +* `variables`关键字匹配. +* `kubernetes`服务在项目上处于活动状态. + +``` +test: + script: npm run test + only: + refs: + - master + - schedules + variables: + - $CI_COMMIT_MESSAGE =~ /run-end-to-end-tests/ + kubernetes: active +``` + +`except`被实现为对此完整表达式的否定: + +> NOT((任何参考)AND(任何变量)AND(任何变化)AND(如果 Kubernetes 处于活动状态)) + +This means the keys are treated as if joined by an OR. This relationship could be described as: + +> (任何参考)或(任何变量)或(任何变化)或(如果 Kubernetes 处于活动状态) + +在以下示例中,如果满足以下**任一条件** ,则**不会**创建`test`作业: + +* 该管道的运行`master` . +* 存储库的根目录中的`README.md`文件进行了更改. + +``` +test: + script: npm run test + except: + refs: + - master + changes: + - "README.md" +``` + +#### `only:refs`/`except:refs`[](#onlyrefsexceptrefs "Permalink") + +GitLab 10.0 中引入的`refs`策略. + +`refs`策略可以采用与[简化的 only / except 配置](#onlyexcept-basic)相同的值. + +在下面的示例中,仅在`master`分支[计划](../pipelines/schedules.html)或运行管道时才创建`deploy`作业: + +``` +deploy: + only: + refs: + - master + - schedules +``` + +#### `only:kubernetes`/`except:kubernetes`[](#onlykubernetesexceptkubernetes "Permalink") + +GitLab 10.0 中引入的`kubernetes`策略. + +The `kubernetes` strategy accepts only the `active` keyword. + +在下面的示例中,仅当项目中的 Kubernetes 服务处于活动状态时,才将创建`deploy`作业: + +``` +deploy: + only: + kubernetes: active +``` + +#### `only:variables`/`except:variables`[](#onlyvariablesexceptvariables "Permalink") + +GitLab 10.7 中引入了`variables`策略. + +`variables`关键字用于定义变量表达式. 换句话说,您可以使用预定义变量/项目/组或环境范围的变量来定义 GitLab 将要评估的表达式,以决定是否应创建作业. + +使用变量表达式的示例: + +``` +deploy: + script: cap staging deploy + only: + refs: + - branches + variables: + - $RELEASE == "staging" + - $STAGING +``` + +另一个用例是根据提交消息排除作业: + +``` +end-to-end: + script: rake test:end-to-end + except: + variables: + - $CI_COMMIT_MESSAGE =~ /skip-end-to-end-tests/ +``` + +了解有关[变量表达式的](../variables/README.html#environment-variables-expressions)更多信息. + +#### `only:changes`/`except:changes`[](#onlychangesexceptchanges "Permalink") + +`changes` GitLab 11.4 中[引入的](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/19232)策略. + +利用`changes`与关键字`only`或`except`能够基于通过推送操作事件被修改的文件定义,如果一个工作应该被创建. + +这意味着`only:changes`策略对以下情况的管道很有用: + +* `$CI_PIPELINE_SOURCE == 'push'` +* `$CI_PIPELINE_SOURCE == 'merge_request_event'` +* `$CI_PIPELINE_SOURCE == 'external_pull_request_event'` + +如果没有 Git 推送事件(例如,对于具有[上述三个之外的源的](../variables/predefined_variables.html)管道),则`changes`无法确定给定文件是新文件还是旧文件,并且始终返回 true. + +`only: changes`使用的一个基本示例`only: changes` : + +``` +docker build: + script: docker build -t my-image:$CI_COMMIT_REF_SLUG . + only: + changes: + - Dockerfile + - docker/scripts/* + - dockerfiles/**/* + - more_scripts/*.{rb,py,sh} +``` + +在上述场景中,当将提交推送到 GitLab 中的现有分支时,它会创建并触发`docker build`作业,只要其中一个提交包含对以下任何一项的更改: + +* The `Dockerfile` file. +* `docker/scripts/`目录中的任何文件. +* `dockerfiles`目录中的任何文件和子目录. +* `more_scripts`目录中具有`rb` , `py` , `sh`扩展名的`more_scripts`文件. + +**警告:**如果`only:changes`使用`only:changes` [仅允许在管道成功的情况下合并合并请求,则](../../user/project/merge_requests/merge_when_pipeline_succeeds.html#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds)如果不[同时使用`only:merge_requests`](#using-onlychanges-with-pipelines-for-merge-requests)则可能导致不良行为. + +您还可以使用 glob 模式来匹配存储库的根目录或存储库内*任何*目录中的多个文件,但是它们必须用双引号引起来,否则 GitLab 将无法解析`.gitlab-ci.yml` . 例如: + +``` +test: + script: npm run test + only: + changes: + - "*.json" + - "**/*.sql" +``` + +如果在存储库根目录中任何扩展名为`.md`文件中检测到更改,以下示例将跳过`build`作业: + +``` +build: + script: npm run build + except: + changes: + - "*.md" +``` + +**警告:**当[将此功能与*没有*合并请求管道的新分支或标记一起使用](#using-onlychanges-without-pipelines-for-merge-requests)时,需要注意一些要点.**警告:**在[计划的管道上使用此功能](#using-onlychanges-with-scheduled-pipelines)时,需要注意一些要点. + +##### Using `only:changes` with pipelines for merge requests[](#using-onlychanges-with-pipelines-for-merge-requests "Permalink") + +使用[用于合并请求的管道,](../merge_request_pipelines/index.html)可以根据在合并请求中修改的文件来定义要创建的作业. + +为了推断源分支的正确基础 SHA,建议`only: [merge_requests]`将此关键字与`only: [merge_requests]` . 这样,可以从任何进一步的提交中正确计算出文件差异,因此可以在管道中正确测试合并请求中的所有更改. + +例如: + +``` +docker build service one: + script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG . + only: + refs: + - merge_requests + changes: + - Dockerfile + - service-one/**/* +``` + +在上述情况下,如果创建或更新了合并请求,从而更改了`service-one`目录中的文件或`Dockerfile` ,则 GitLab 将创建并触发`Dockerfile` `docker build service one`作业. + +Note that if [pipelines for merge requests](../merge_request_pipelines/index.html) is combined with `only: [change]`, but `only: [merge_requests]` is omitted, there could be unwanted behavior. + +例如: + +``` +docker build service one: + script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG . + only: + changes: + - Dockerfile + - service-one/**/* +``` + +在上面的示例中,管道可能由于对`service-one/**/*`的文件的更改而失败. 然后可以推送更高版本的提交,该提交不包括对该文件的任何更改,但包括对`Dockerfile`更改,并且该管道可以通过,因为它仅测试对`Dockerfile`的更改. GitLab 会检查**最近** **通过的** **管道** ,并且将合并请求显示为可合并,尽管较早的管道失败是由于尚未更正的更改引起的. + +使用此配置时,必须注意检查最新的管道是否正确地纠正了先前管道的任何故障. + +##### Using `only:changes` without pipelines for merge requests[](#using-onlychanges-without-pipelines-for-merge-requests "Permalink") + +如果没有[用于合并请求的](../merge_request_pipelines/index.html)管道,则管道将在与合并请求没有明确关联的分支或标签上运行. 在这种情况下,将使用先前的 SHA 来计算 diff,这等效于`git diff HEAD~` . 这可能会导致某些意外行为,包括: + +* When pushing a new branch or a new tag to GitLab, the policy always evaluates to true. +* 推送新提交时,更改的文件将使用先前的提交作为基础 SHA 进行计算. + +##### Using `only:changes` with scheduled pipelines[](#using-onlychanges-with-scheduled-pipelines "Permalink") + +`only:changes`在[Scheduled 管道中](../pipelines/schedules.html)始终评估为" true". 当计划的管道运行时,所有文件都被视为"已更改". + +### `needs`[](#needs "Permalink") + +版本历史 + +* 在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47063) . +* 在 GitLab 12.3 中, `needs`阵列中的最大作业数从 5 个增加到 50 个. +* 在 GitLab 12.8 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/30631) `needs: []`使作业立即开始. + +`needs:`关键字可无序执行作业,使您可以在`.gitlab-ci.yml`实现有[向无环图](../directed_acyclic_graph/index.html) . + +这样,您无需等待阶段顺序即可运行某些作业,而无需等待其他任务,因此您可以让多个阶段同时运行. + +让我们考虑以下示例: + +``` +linux:build: + stage: build + +mac:build: + stage: build + +lint: + stage: test + needs: [] + +linux:rspec: + stage: test + needs: ["linux:build"] + +linux:rubocop: + stage: test + needs: ["linux:build"] + +mac:rspec: + stage: test + needs: ["mac:build"] + +mac:rubocop: + stage: test + needs: ["mac:build"] + +production: + stage: deploy +``` + +本示例创建四个执行路径: + +* 棉短绒:在`lint`作业将立即运行,而无需等待`build`阶段完成,因为它没有需求( `needs: []` + +* Linux 路径: `linux:build`作业完成后,将立即运行`linux:rspec`和`linux:rubocop`作业,而无需等待`mac:build`完成. + +* macOS 路径: `mac:build`作业完成后,将立即运行`mac:rspec`和`mac:rubocop`作业,而无需等待`linux:build`完成. + +* `production`作业将在所有先前的作业完成后立即执行; 在这种情况下: `linux:build` , `linux:rspec` , `linux:rubocop` , `mac:build` , `mac:rspec` , `mac:rubocop` . + +#### Requirements and limitations[](#requirements-and-limitations "Permalink") + +* 如果`needs:`设置为指向`only/except`因`only/except`规则而未实例化的作业,或者不存在,则创建管道时会出现 YAML 错误. +* `needs:`数组中单个作业可能需要的最大作业数是有限的: + * 对于 GitLab.com,限制为十个. 有关更多信息,请参见[基础结构问题](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7541) . + * 对于自我管理的实例,限制为: + * 10,如果`ci_dag_limit_needs`功能标志已启用(默认). + * 50,如果`ci_dag_limit_needs`功能标记被禁用. +* 如果`needs:`是指标记为" `parallel:`的作业. 当前作业将取决于创建的所有并行作业. +* `needs:`类似于`dependencies:`它需要使用之前阶段的作业,这意味着不可能创建循环依赖关系. 在当前阶段也不可能依赖于工作,但是[已计划了](https://gitlab.com/gitlab-org/gitlab/-/issues/30632)支持. +* 与上述相关,必须为所有具有关键字`needs:`或由一个人引用的作业明确定义阶段. + +##### Changing the `needs:` job limit[](#changing-the-needs-job-limit "Permalink") + +可以在`needs:`定义的最大作业数`needs:`默认为 10,但可以通过功能标志更改为 50\. 要将限制更改为 50,请[启动 Rails 控制台会话](../../administration/troubleshooting/debug.html#starting-a-rails-console-session)并运行: + +``` +Feature::disable(:ci_dag_limit_needs) +``` + +要将其设置回 10,请运行相反的命令: + +``` +Feature::enable(:ci_dag_limit_needs) +``` + +#### Artifact downloads with `needs`[](#artifact-downloads-with-needs "Permalink") + +[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/14311)在 GitLab v12.6. + +在使用`needs` ,可通过`artifacts: true` (默认)或`artifacts: false`来控制工件下载. + +从 GitLab 12.6 开始,您不能将[`dependencies`](#dependencies)关键字与控制作业中工件下载的`needs`结合使用. `dependencies`在不使用`needs`作业中仍然有效. + +在以下示例中, `rspec`作业将下载`build_job`工件,而`rubocop`作业则不会: + +``` +build_job: + stage: build + artifacts: + paths: + - binaries/ + +rspec: + stage: test + needs: + - job: build_job + artifacts: true + +rubocop: + stage: test + needs: + - job: build_job + artifacts: false +``` + +另外,在下面的三个语法示例中, `rspec`作业将从所有三个`build_jobs`下载工件,因为`artifacts`对于`build_job_1`是 true,并且对于`build_job_2`和`build_job_3`都**默认**为 true. + +``` +rspec: + needs: + - job: build_job_1 + artifacts: true + - job: build_job_2 + - build_job_3 +``` + +#### Cross project artifact downloads with `needs`[](#cross-project-artifact-downloads-with-needs-premium "Permalink") + +[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/14311)在 GitLab v12.7. + +`needs`可用于从[同一项目中其他 ref](#artifact-downloads-between-pipelines-in-the-same-project)或不同项目中的管道上的多达五个作业的工件中下载工件: + +``` +build_job: + stage: build + script: + - ls -lhR + needs: + - project: group/project-name + job: build-1 + ref: master + artifacts: true +``` + +`build_job`将从`group/project-name`项目的`master`分支上的最新成功`build-1`作业中下载工件. + +##### Artifact downloads between pipelines in the same project[](#artifact-downloads-between-pipelines-in-the-same-project "Permalink") + +通过将`project`关键字设置为当前项目的名称,并指定引用,可以使用`needs`从当前项目的不同管道中下载工件. 在下面的示例中, `build_job`将使用`other-ref` ref 下载最新成功的`build-1`作业的工件: + +``` +build_job: + stage: build + script: + - ls -lhR + needs: + - project: group/same-project-name + job: build-1 + ref: other-ref + artifacts: true +``` + +**注意:**不支持从[`parallel:`](#parallel)运行的作业中下载工件[`parallel:`](#parallel) + +### `tags`[](#tags "Permalink") + +`tags`用于从允许运行该项目的所有 Runner 列表中选择特定的 Runner. + +在 Runner 的注册过程中,您可以指定 Runner 的标签,例如`ruby` , `postgres` , `development` . + +`tags`可让您为具有指定标签的跑步者运行作业: + +``` +job: + tags: + - ruby + - postgres +``` + +上面的规范将确保`job`由同时定义了`ruby`和`postgres`标签的 Runner 构建. + +标签也是在不同平台上运行不同作业的好方法,例如,给定带有`osx`标签的 OS X Runner 和带有`windows`标签的 Windows Runner,以下作业将在各自的平台上运行: + +``` +windows job: + stage: + - build + tags: + - windows + script: + - echo Hello, %USERNAME%! + +osx job: + stage: + - build + tags: + - osx + script: + - echo "Hello, $USER!" +``` + +### `allow_failure`[](#allow_failure "Permalink") + +`allow_failure`允许作业失败,而不会影响其余 CI 套件. 默认值是`false` ,除了使用`when: manual`语法的[手动](#whenmanual)作业之外,除非使用[`rules:`](#rules)语法,否则所有作业默认为 false, *包括* `when: manual`作业. + +启用后,如果作业失败,该作业将在用户界面中显示橙色警告. 但是,管道的逻辑流程将认为作业成功/通过,并且不会被阻塞. + +假设所有其他作业均成功,则该作业的阶段及其管道将显示相同的橙色警告. 但是,关联的提交将被标记为"通过",而不会发出警告. + +在下面的示例中, `job1`和`job2`将并行运行,但是如果`job1`失败,它不会停止下一阶段的运行,因为它标记有`allow_failure: true` : + +``` +job1: + stage: test + script: + - execute_script_that_will_fail + allow_failure: true + +job2: + stage: test + script: + - execute_script_that_will_succeed + +job3: + stage: deploy + script: + - deploy_to_staging +``` + +### `when`[](#when "Permalink") + +`when`用于实现在发生故障或发生故障时运行的作业. + +`when`可以被设置为以下值中的一个: + +1. `on_success`仅在先前阶段中的所有作业都成功(或因为标记为`allow_failure`而被视为成功)时才执行作业. 这是默认值. +2. `on_failure`仅在`on_failure`中的至少一项作业失败时才执行作业. +3. `always` -执行作业,而不管先前阶段的作业状态如何. +4. `manual` -手动执行作业(在 GitLab 8.10 中已添加). 在下面阅读有关[手动操作的信息](#whenmanual) . +5. `delayed` -一定时间后执行作业(在 GitLab 11.14 中已添加). 在下面阅读有关[延迟动作的信息](#whendelayed) . + +For example: + +``` +stages: + - build + - cleanup_build + - test + - deploy + - cleanup + +build_job: + stage: build + script: + - make build + +cleanup_build_job: + stage: cleanup_build + script: + - cleanup build when failed + when: on_failure + +test_job: + stage: test + script: + - make test + +deploy_job: + stage: deploy + script: + - make deploy + when: manual + +cleanup_job: + stage: cleanup + script: + - cleanup after jobs + when: always +``` + +上面的脚本将: + +1. 仅当`build_job`失败时才执行`cleanup_build_job` . +2. 无论成功与失败,始终执行`cleanup_job`作为管道的最后一步. +3. 允许您从 GitLab 的 UI 手动执行`deploy_job` . + +#### `when:manual`[](#whenmanual "Permalink") + +版本历史 + +* 在 GitLab 8.10 中引入. +* 在 GitLab 9.0 中引入了阻止手动操作. +* GitLab 9.2 中引入了受保护的操作. + +手动操作是一种特殊类型的作业,不会自动执行,需要用户明确启动. 手动操作的示例用法是部署到生产环境. 可以从管道,作业,环境和部署视图开始手动操作. 在[环境文档中](../environments/index.html#configuring-manual-deployments)阅读更多[内容](../environments/index.html#configuring-manual-deployments) . + +手动操作可以是可选的或阻止的. 阻止手动操作将在定义此操作的阶段阻止管道的执行.当有人通过单击*播放*按钮执行阻止手动操作时,可以恢复管道的执行. + +当管道被阻塞时,如果设置了"管道成功时合并",则不会被合并. 阻塞的管道也确实有一种特殊的状态,称为*手动* . 使用`when:manual`语法`when:manual` ,默认情况下手动操作是非阻塞的. 如果要进行手动操作阻止,则必须在`.gitlab-ci.yml`的作业定义中添加`allow_failure: false` . + +可选的手动操作具有`allow_failure: true`默认情况下设置为`allow_failure: true` ,并且它们的状态不影响总体管道状态. 因此,如果手动操作失败,则管道最终将成功. + +**注意:**使用[`rules:`](#rules) , `allow_failure`默认为`false` ,包括手动作业. + +手动操作被视为写操作,因此当用户想要触发操作时,将使用[受保护分支的](../../user/project/protected_branches.html)权限. 换句话说,为了触发分配给正在为其运行管道的分支的手动操作,用户需要具有合并到该分支的能力. 可以使用受保护的环境来更严格地[保护手动部署](#protecting-manual-jobs-premium) ,以防止未经授权的用户运行. + +**注意:同时**使用`when:manual`和`trigger`导致错误`jobs:#{job-name} when should be on_success, on_failure or always` ,因为`when:manual`阻止使用触发器. + +##### Protecting manual jobs[](#protecting-manual-jobs-premium "Permalink") + +可以使用[受保护的环境](../environments/protected_environments.html)来定义授权运行手动作业的用户的精确列表. 通过仅允许与受保护环境关联的用户触发手动作业,可以实现一些特殊用例,例如: + +* 更精确地限制可以部署到环境的人员. +* 使管道能够被阻塞,直到获得批准的用户"批准"为止. + +为此,您必须: + +1. 为作业添加`environment` . 例如: + + ``` + deploy_prod: + stage: deploy + script: + - echo "Deploy to production server" + environment: + name: production + url: https://example.com + when: manual + only: + - master + ``` + +2. 在" [受保护的环境"设置中](../environments/protected_environments.html#protecting-environments) ,选择环境(上面的示例中为`production` ),然后将被授权触发手动作业的用户,角色或组添加到" **允许部署"**列表中. 只有该列表中的人员以及始终能够使用受保护环境的 GitLab 管理员才能触发此手动作业. + +此外,如果通过添加`allow_failure: false`将手动作业定义为阻塞,则直到触发手动作业后,管道的下`allow_failure: false`才会运行. 这可以用作一种方法,使定义的用户列表可以通过触发阻止的手动作业来"批准"后续的管道阶段. + +#### `when:delayed`[](#whendelayed "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51352) . + +延迟的作业用于在一定时间后执行脚本. 如果要避免作业立即进入`pending`状态,此功能很有用. + +您可以使用`start_in`键设置时间段. 除非提供了单位,否则`start_in`键的值是以秒为单位的经过时间. `start_in`键必须小于或等于一周. 有效值的示例包括: + +* `'5'` +* `10 seconds` +* `30 minutes` +* `1 day` +* `1 week` + +当阶段中有延迟的工作时,直到延迟的工作完成,管道才能继续进行. 这意味着该关键字也可以用于在不同阶段之间插入延迟. + +上一阶段完成后,延迟作业的计时器立即启动. 与其他类型的作业类似,延迟的作业计时器不会启动,除非前一个阶段通过. + +以下示例创建一个名为`timed rollout 10%`的作业,该作业在上一阶段完成后 30 分钟执行: + +``` +timed rollout 10%: + stage: deploy + script: echo 'Rolling out 10% ...' + when: delayed + start_in: 30 minutes +``` + +您可以通过单击"停止"来停止延迟作业的活动计时器. ( **计划外** )按钮. 除非您手动执行该作业,否则以后将永远不会执行该作业. + +您可以通过单击" **播放"**按钮立即开始延迟的作业. GitLab Runner 将很快开始您的工作并开始工作. + +### `environment`[](#environment "Permalink") + +版本历史 + +* 在 GitLab 8.9 中引入. +* 您可以阅读有关环境的更多信息,并在[有关环境](../environments/index.html)的[文档中](../environments/index.html)找到更多示例. + +`environment`用于定义作业部署到特定环境. 如果指定了`environment` ,但不存在该名称下的环境,则将自动创建一个新环境. + +以最简单的形式,可以将`environment`关键字定义为: + +``` +deploy to production: + stage: deploy + script: git push production HEAD:master + environment: production +``` + +在上面的示例中,将`deploy to production`作业标记为正在部署到`production`环境. + +#### `environment:name`[](#environmentname "Permalink") + +版本历史 + +* 在 GitLab 8.11 中引入. +* 在 GitLab 8.11 之前,环境的名称可以定义为类似于`environment: production`的字符串`environment: production` . 现在推荐的方法是在`name`关键字下定义它. +* `name`参数可以使用任何已定义的 CI 变量,包括预定义的安全变量和`.gitlab-ci.yml` [`variables`](#variables) . 但是,您不能使用`script`下定义的变量. + +`environment`名称可以包含: + +* letters +* digits +* spaces +* `-` +* `_` +* `/` +* `$` +* `{` +* `}` + +通用名称是`qa` , `staging`和`production` ,但是您可以使用与您的工作流程兼容的任何名称. + +除了在`environment`关键字之后直接定义环境名称之外,还可以将其定义为单独的值. 为此,请在`environment`下使用`name`关键字: + +``` +deploy to production: + stage: deploy + script: git push production HEAD:master + environment: + name: production +``` + +#### `environment:url`[](#environmenturl "Permalink") + +版本历史 + +* 在 GitLab 8.11 中引入. +* 在 GitLab 8.11 之前,只能在 GitLab 的 UI 中添加 URL. 现在推荐的方法是在`.gitlab-ci.yml`定义它. +* `url`参数可以使用任何已定义的 CI 变量,包括预定义的安全变量和`.gitlab-ci.yml` [`variables`](#variables) . 但是,您不能使用`script`下定义的变量. + +这是一个可选值,设置该值时,它将在 GitLab 中的不同位置显示按钮,单击这些按钮会将您带到定义的 URL. + +在下面的示例中,如果作业成功完成,它将在合并请求和环境/部署页面中创建按钮,这些页面将指向`https://prod.example.com` . + +``` +deploy to production: + stage: deploy + script: git push production HEAD:master + environment: + name: production + url: https://prod.example.com +``` + +#### `environment:on_stop`[](#environmenton_stop "Permalink") + +版本历史 + +* 在 GitLab 8.13 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22191) . +* 从 GitLab 8.14 开始,当您具有定义了停止动作的环境时,当删除关联的分支时,GitLab 将自动触发停止动作. + +可以通过在`on_stop`下定义的`on_stop`关键字来实现关闭(停止) `environment` . 它声明运行另一个作业以关闭环境. + +请阅读`environment:action`部分以获取示例. + +#### `environment:action`[](#environmentaction "Permalink") + +在 GitLab 8.13 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22191) . + +`action`关键字将与`on_stop`结合使用,并在调用关闭环境的作业中定义. + +举个例子: + +``` +review_app: + stage: deploy + script: make deploy-app + environment: + name: review/$CI_COMMIT_REF_NAME + url: https://$CI_ENVIRONMENT_SLUG.example.com + on_stop: stop_review_app + +stop_review_app: + stage: deploy + variables: + GIT_STRATEGY: none + script: make delete-app + when: manual + environment: + name: review/$CI_COMMIT_REF_NAME + action: stop +``` + +在上面的例子中,我们建立了`review_app`工作部署到`review`环境,我们还定义了一个新`stop_review_app`下工作`on_stop` . 一旦`review_app`作业成功完成,就会触发`stop_review_app`根据什么下定义的作业`when` . 在这种情况下,我们将其设置为`manual`因此需要通过 GitLab 的 Web 界面进行[手动操作](#whenmanual)才能运行. + +同样在该示例中, `GIT_STRATEGY`设置为`none`以便当[自动触发](../environments/index.html#automatically-stopping-an-environment) `stop_review_app`作业时,删除分支后,GitLab Runner 将不会尝试检出代码. + +**注意:**上面的示例覆盖了全局变量. 如果停止环境作业依赖于全局变量,则可以在设置`GIT_STRATEGY`时使用[锚变量](#yaml-anchors-for-variables)来更改它,而不覆盖全局变量. + +**需要** `stop_review_app`作业定义以下关键字: + +* `when` - [reference](#when) +* `environment:name` +* `environment:action` + +此外,两个作业都应具有匹配的[`rules`](../yaml/README.html#onlyexcept-basic)或[`only/except`](../yaml/README.html#onlyexcept-basic)配置[`only/except`](../yaml/README.html#onlyexcept-basic) . 在上面的示例中,如果配置不同,则`stop_review_app`作业可能未包含在所有包含`review_app`作业的管道中,并且将无法触发该`action: stop`以自动停止环境. + +#### `environment:auto_stop_in`[](#environmentauto_stop_in "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/20956) . + +`auto_stop_in`关键字用于指定环境的生命周期,当 GitLab 过期时,它将自动停止它们. + +例如, + +``` +review_app: + script: deploy-review-app + environment: + name: review/$CI_COMMIT_REF_NAME + auto_stop_in: 1 day +``` + +当执行`review_app`作业并创建评论应用程序时,环境的生命周期设置为`1 day` . + +有关更多信息,请参见[环境自动停止文档.](../environments/index.html#environments-auto-stop) + +#### `environment:kubernetes`[](#environmentkubernetes "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) . + +`kubernetes`块用于将部署配置为与您的项目关联的[Kubernetes 集群](../../user/project/clusters/index.html) . + +例如: + +``` +deploy: + stage: deploy + script: make deploy-app + environment: + name: production + kubernetes: + namespace: production +``` + +这将使用`production` [Kubernetes 名称空间](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)设置`deploy`作业以部署到`production`环境. + +有关更多信息,请参阅[`kubernetes`可用设置](../environments/index.html#configuring-kubernetes-deployments) . + +**注意:** [由 GitLab 管理的](../../user/project/clusters/index.html#gitlab-managed-clusters) Kubernetes 集群不支持 Kubernetes 配置. 要跟踪对 GitLab 管理的集群的支持进度,请参阅[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/38054) . + +#### Dynamic environments[](#dynamic-environments "Permalink") + +版本历史 + +* 在 GitLab 8.12 和 GitLab Runner 1.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21971) . +* `$CI_ENVIRONMENT_SLUG`是在 GitLab 8.15 中[引入的](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22864) . +* `name`和`url`参数可以使用任何已定义的 CI 变量,包括预定义的安全变量和`.gitlab-ci.yml` [`variables`](#variables) . 但是,您不能使用`script`下定义的变量. + +例如: + +``` +deploy as review app: + stage: deploy + script: make deploy + environment: + name: review/$CI_COMMIT_REF_NAME + url: https://$CI_ENVIRONMENT_SLUG.example.com/ +``` + +`deploy as review app`作业将被标记为部署,以动态创建`review/$CI_COMMIT_REF_NAME`环境,其中`$CI_COMMIT_REF_NAME`是 Runner 设置的[环境变量](../variables/README.html) . `$CI_ENVIRONMENT_SLUG`变量基于环境名称,但适合包含在 URL 中. 在这种情况下,如果" `deploy as review app`作业在名为`pow`的分支中运行,则可以使用`https://review-pow.example.com/`类的 URL 访问此环境. + +当然,这意味着托管应用程序的基础服务器已正确配置. + +常见的用例是为分支创建动态环境并将其用作 Review Apps. 您可以在[https://gitlab.com/gitlab-examples/review-apps-nginx/上](https://gitlab.com/gitlab-examples/review-apps-nginx/)查看使用 Review Apps 的简单示例. + +### `cache`[](#cache "Permalink") + +版本历史 + +* 在 GitLab Runner v0.7.0 中引入. +* `cache`可以全局设置,也可以按作业设置. +* 从 GitLab 9.0 起,默认情况下启用缓存并在管道和作业之间共享缓存. +* 从 GitLab 9.2 起,缓存将在[工件](#artifacts)之前恢复. + +**了解更多信息:**阅读缓存工作原理,并在[缓存依赖文档中](../caching/index.html)找到一些好的做法. + +`cache`用于指定应在作业之间缓存的文件和目录的列表. 您只能使用本地工作副本中的路径. + +如果在作业范围之外定义了`cache` ,则意味着已全局设置`cache` ,并且所有作业都将使用该定义. + +#### `cache:paths`[](#cachepaths "Permalink") + +使用`paths`指令选择要缓存的文件或目录. 路径是相对于项目目录( `$CI_PROJECT_DIR` )的,不能直接链接到其外部. 可以使用遵循[通配符](https://en.wikipedia.org/wiki/Glob_(programming))模式的[通配符,](https://en.wikipedia.org/wiki/Glob_(programming))并且: + +* 在[GitLab Runner 13.0](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620)和更高版本中,请选择[`doublestar.Glob`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#Match) . +* 在 GitLab Runner 12.10 及更早版本中, [`filepath.Match`](https://pkg.go.dev/path/filepath/#Match) . + +将所有文件缓存在以`.apk`和`.config`文件结尾的`binaries`文件中: + +``` +rspec: + script: test + cache: + paths: + - binaries/*.apk + - .config +``` + +本地定义的缓存将覆盖全局定义的选项. 以下`rspec`作业将仅缓存`binaries/` : + +``` +cache: + paths: + - my/files + +rspec: + script: test + cache: + key: rspec + paths: + - binaries/ +``` + +请注意,由于缓存是在作业之间共享的,因此如果您为不同的作业使用不同的路径,则还应该设置不同的**cache:key,**否则缓存内容可能会被覆盖. + +#### `cache:key`[](#cachekey "Permalink") + +在 GitLab Runner v1.0.0 中引入. + +由于缓存是在作业之间共享的,因此如果您为不同的作业使用不同的路径,则还应该设置不同的`cache:key`否则缓存内容可能会被覆盖. + +`key`指令允许您定义作业之间的缓存相似性,从而允许为所有作业使用单个缓存,按作业缓存,按分支缓存或适合您工作流程的任何其他方式. 这样,您可以微调缓存,从而允许您在不同作业甚至不同分支之间缓存数据. + +`cache:key`变量可以使用任何[预定义的变量](../variables/README.html) ,并且默认键(如果未设置)只是文字`default` ,这意味着从 GitLab 9.0 开始,默认情况下所有内容都在管道和作业之间共享. + +**注意:** `cache:key`变量不能包含`/`字符或等效的 URI 编码的`/` ; 也禁止仅由点( `.` , `.` )组成的值. + +例如,要启用每分支缓存: + +``` +cache: + key: "$CI_COMMIT_REF_SLUG" + paths: + - binaries/ +``` + +如果使用**Windows Batch**运行 Shell 脚本,则需要将`$`替换`$` `%` : + +``` +cache: + key: "%CI_COMMIT_REF_SLUG%" + paths: + - binaries/ +``` + +##### `cache:key:files`[](#cachekeyfiles "Permalink") + +[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/18986)在 GitLab v12.5. + +The `cache:key:files` keyword extends the `cache:key` functionality by making it easier to reuse some caches, and rebuild them less often, which will speed up subsequent pipeline runs. + +当包含`cache:key:files` ,还必须列出将用于生成密钥的项目文件,最多两个文件. 缓存`key`将是根据更改给定文件的最新提交(最多两个,如果列出了两个文件)计算出的 SHA 校验和. 如果在任何提交中都没有更改文件,则后备密钥将为`default` . + +``` +cache: + key: + files: + - Gemfile.lock + - package.json + paths: + - vendor/ruby + - node_modules +``` + +在此示例中,我们将为 Ruby 和 Node.js 依赖关系创建一个缓存,该缓存与`Gemfile.lock`和`package.json`文件的当前版本相关`Gemfile.lock` . 只要这些文件之一发生更改,就会计算新的缓存键并创建新的缓存. 任何将来的作业都使用相同的`Gemfile.lock`和`package.json`和`cache:key:files`将使用新的缓存,而不是重建依赖关系. + +##### `cache:key:prefix`[](#cachekeyprefix "Permalink") + +[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/18986)在 GitLab v12.5. + +`prefix`参数通过允许密钥由给定的`prefix`与为`cache:key:files`计算的 SHA 组合而成,从而为`key:files`添加了额外的功能. 例如,添加`test`的`prefix`将导致键看起来像: `test-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5` . 如果在任何提交中都未更改两个文件,则将前缀添加到`default` ,因此示例中的键将为`test-default` . + +像`cache:key`一样, `prefix`可以使用任何[预定义的变量](../variables/README.html) ,但是不允许以下操作: + +* `/`字符(或等效的 URI 编码的`/` ) +* 仅由组成的值`.` (或等效的 URI 编码的`.` ) + +``` +cache: + key: + files: + - Gemfile.lock + prefix: ${CI_JOB_NAME} + paths: + - vendor/ruby + +rspec: + script: + - bundle exec rspec +``` + +例如,添加`$CI_JOB_NAME` `prefix`将使密钥看起来像: `rspec-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5` ,并且作业缓存在不同分支之间共享. 如果分支更改`Gemfile.lock` ,则该分支将为`cache:key:files`具有新的 SHA 校验和. 将生成一个新的缓存密钥,并为该密钥创建一个新的缓存. 如果未找到`Gemfile.lock` ,则将前缀添加到`default` ,因此示例中的键将为`rspec-default` . + +#### `cache:untracked`[](#cacheuntracked "Permalink") + +设置`untracked: true`以缓存 Git 存储库中所有未跟踪的文件: + +``` +rspec: + script: test + cache: + untracked: true +``` + +缓存所有 Git 未跟踪的文件和`binaries` : + +``` +rspec: + script: test + cache: + untracked: true + paths: + - binaries/ +``` + +#### `cache:policy`[](#cachepolicy "Permalink") + +在 GitLab 9.4 中引入. + +缓存作业的默认行为是在执行开始时下载文件,然后在结束时重新上传文件. 这样可以将作业所做的任何更改保留下来,以备将来运行,这被称为" `pull-push`缓存策略. + +如果您知道该作业不会更改缓存的文件,则可以通过设置`policy: pull`来跳过上载步骤`policy: pull`插入作业规范. 通常,这会在较早的阶段与普通的缓存作业结合在一起,以确保不时更新缓存: + +``` +stages: + - setup + - test + +prepare: + stage: setup + cache: + key: gems + paths: + - vendor/bundle + script: + - bundle install --deployment + +rspec: + stage: test + cache: + key: gems + paths: + - vendor/bundle + policy: pull + script: + - bundle exec rspec ... +``` + +这有助于加快作业执行速度并减少缓存服务器上的负载,尤其是当您有大量并行使用缓存的作业时. + +此外,如果您有一项作业无条件地重新创建了高速缓存而不参考其先前的内容,则可以使用`policy: push`该作业以跳过下载步骤. + +### `artifacts`[](#artifacts "Permalink") + +版本历史 + +* 在非 Windows 平台的 GitLab Runner v0.7.0 中引入. +* Windows 支持已在 GitLab Runner v.1.0.0 中添加. +* 从 GitLab 9.2 起,缓存将在工件之前恢复. +* 并非所有执行程序都[受支持](https://docs.gitlab.com/runner/executors/) . +* 默认情况下,仅为成功的作业收集作业工件. + +`artifacts`用于指定在[成功,失败或始终成功](#artifactswhen)时应附加到作业的文件和目录的列表. + +作业完成后,工件将被发送到 GitLab,并可在 GitLab UI 中下载. + +[Read more about artifacts](../pipelines/job_artifacts.html). + +#### `artifacts:paths`[](#artifactspaths "Permalink") + +路径是相对于项目目录( `$CI_PROJECT_DIR` )的,不能直接链接到其外部. 可以使用遵循[通配符](https://en.wikipedia.org/wiki/Glob_(programming))模式和[`filepath.Match`](https://s0golang0org.icopy.site/pkg/path/filepath/)的[通配符](https://en.wikipedia.org/wiki/Glob_(programming)) . + +要限制特定作业将从中获取工件的作业,请参阅[dependencies](#dependencies) . + +发送所有`binaries`和`.config`文件: + +``` +artifacts: + paths: + - binaries/ + - .config +``` + +要禁用工件传递,请使用空的[依赖项](#dependencies)定义作业: + +``` +job: + stage: build + script: make build + dependencies: [] +``` + +您可能只想为标记的发行版创建构件,以避免用临时构建构件填充构建服务器存储. + +仅为标签创建工件( `default-job`不会创建工件): + +``` +default-job: + script: + - mvn test -U + except: + - tags + +release-job: + script: + - mvn package -U + artifacts: + paths: + - target/*.war + only: + - tags +``` + +您也可以为目录使用通配符. 例如,如果要获取以`xyz`结尾的目录中的所有文件: + +``` +job: + artifacts: + paths: + - path/*xyz/* +``` + +#### `artifacts:exclude`[](#artifactsexclude "Permalink") + +版本历史 + +* 在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/15122) +* 需要 GitLab Runner 13.1 + +`exclude`可以防止将文件添加到工件存档中. + +类似于[`artifacts:paths`](#artifactspaths) , `exclude`路径相对于项目目录. 可以使用遵循[通配符](https://en.wikipedia.org/wiki/Glob_(programming))模式和[`filepath.Match`](https://s0golang0org.icopy.site/pkg/path/filepath/)的[通配符](https://en.wikipedia.org/wiki/Glob_(programming)) . + +例如,所有的文件存储在`binaries/` ,而不是`*.o`位于的子目录中的文件`binaries/` : + +``` +artifacts: + paths: + - binaries/ + exclude: + - binaries/**/*.o +``` + +与[`artifacts:untracked`](#artifactsuntracked)匹配的文件也可以使用`artifacts:exclude` . + +#### `artifacts:expose_as`[](#artifactsexpose_as "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/15018) . + +关键字`expose_as`可用于在[合并请求](../../user/project/merge_requests/index.html) UI 中公开[作业工件](../pipelines/job_artifacts.html) . + +例如,要匹配单个文件: + +``` +test: + script: [ "echo 'test' > file.txt" ] + artifacts: + expose_as: 'artifact 1' + paths: ['file.txt'] +``` + +使用此配置,GitLab 会将链接**工件 1**添加到指向`file1.txt`的相关合并请求中. + +匹配整个目录的示例: + +``` +test: + script: [ "mkdir test && echo 'test' > test/file.txt" ] + artifacts: + expose_as: 'artifact 1' + paths: ['test/'] +``` + +请注意以下几点: + +* 使用变量定义`artifacts:paths`时,工件不会显示在合并请求 UI 中. +* 每个合并请求最多可以公开 10 个作业工件. +* 不支持 glob 模式. +* 如果指定了目录,那么如果目录中有多个文件,则该链接将指向作业[工件浏览器](../pipelines/job_artifacts.html#browsing-artifacts) . +* 对于带有`.html` , `.htm` , `.txt` , `.json` , `.xml`和`.log`扩展名的暴露的单个文件工件,如果[GitLab Pages](../../administration/pages/index.html)为: + * 启用后,GitLab 将自动渲染工件. + * 未启用,您将在工件浏览器中看到该文件. + +#### `artifacts:name`[](#artifactsname "Permalink") + +在 GitLab 8.6 和 GitLab Runner v1.1.0 中引入. + +通过`name`指令,您可以定义所创建的工件存档的名称. 这样,您可以为每个档案使用一个唯一的名称,这在您要从 GitLab 下载档案时很有用. `artifacts:name`变量可以使用任何[预定义变量](../variables/README.html) . 默认名称是`artifacts` ,下载`artifacts`变为`artifacts.zip` . + +**注意:**如果您的分支名称包含正斜杠(例如`feature/my-feature` ),建议使用`$CI_COMMIT_REF_SLUG`而不是`$CI_COMMIT_REF_NAME`来正确命名工件. + +要使用当前作业的名称创建档案: + +``` +job: + artifacts: + name: "$CI_JOB_NAME" + paths: + - binaries/ +``` + +要使用当前分支或标记的名称(仅包括二进制文件目录)创建档案,请执行以下操作: + +``` +job: + artifacts: + name: "$CI_COMMIT_REF_NAME" + paths: + - binaries/ +``` + +要使用当前作业的名称和当前分支或标记(仅包括二进制文件目录)创建档案,请执行以下操作: + +``` +job: + artifacts: + name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME" + paths: + - binaries/ +``` + +要创建一个具有当前[阶段](#stages)名称和分支名称的档案: + +``` +job: + artifacts: + name: "$CI_JOB_STAGE-$CI_COMMIT_REF_NAME" + paths: + - binaries/ +``` + +* * * + +如果使用**Windows Batch**运行 Shell 脚本,则需要将`$`替换`$` `%` : + +``` +job: + artifacts: + name: "%CI_JOB_STAGE%-%CI_COMMIT_REF_NAME%" + paths: + - binaries/ +``` + +如果使用**Windows PowerShell**运行 Shell 脚本,则需要将`$`替换`$` `$env:` :: + +``` +job: + artifacts: + name: "$env:CI_JOB_STAGE-$env:CI_COMMIT_REF_NAME" + paths: + - binaries/ +``` + +#### `artifacts:untracked`[](#artifactsuntracked "Permalink") + +`artifacts:untracked`用于将所有 Git 未跟踪的文件添加为工件(以及`artifacts:paths`定义的`artifacts:paths` ). + +**Note:** `artifacts:untracked` ignores configuration in the repository’s `.gitignore` file. + +发送所有未跟踪的 Git 文件: + +``` +artifacts: + untracked: true +``` + +发送所有 Git 未跟踪的文件和`binaries` : + +``` +artifacts: + untracked: true + paths: + - binaries/ +``` + +发送所有未跟踪的文件,但[不包括](#artifactsexclude) `*.txt` : + +``` +artifacts: + untracked: true + exclude: + - *.txt +``` + +#### `artifacts:when`[](#artifactswhen "Permalink") + +在 GitLab 8.9 和 GitLab Runner v1.3.0 中引入. + +`artifacts:when`用于在作业失败时或尽管失败而上传工件. + +可以设置为以下值之一的`artifacts:when` : + +1. `on_success`仅在作业成功时才上传工件. 这是默认值. +2. `on_failure`仅在作业失败时上载工件. +3. `always` -上载工件,无论作业状态如何. + +要仅在作业失败时上传工件: + +``` +job: + artifacts: + when: on_failure +``` + +#### `artifacts:expire_in`[](#artifactsexpire_in "Permalink") + +在 GitLab 8.9 和 GitLab Runner v1.3.0 中引入. + +`expire_in` allows you to specify how long artifacts should live before they expire and are therefore deleted, counting from the time they are uploaded and stored on GitLab. If the expiry time is not defined, it defaults to the [instance wide setting](../../user/admin_area/settings/continuous_integration.html#default-artifacts-expiration-core-only) (30 days by default). + +您可以使用作业页面上的" **保留"**按钮来覆盖过期并永久保留工件. + +过期后,默认情况下每小时(通过 cron 作业)删除工件,并且不再可用. + +The value of `expire_in` is an elapsed time in seconds, unless a unit is provided. Examples of valid values: + +* `42` +* `3 mins 4 sec` +* `2 hrs 20 min` +* `2h20min` +* `6 mos 1 day` +* `47 yrs 6 mos and 4d` +* `3 weeks and 2 days` + +要在上传后 1 周内使工件过期: + +``` +job: + artifacts: + expire_in: 1 week +``` + +**注意:**对于在[GitLab 13.1](https://gitlab.com/gitlab-org/gitlab/-/issues/16267)和更高版本中创建的工件,无论有效时间如何,始终会保留引用的最新工件. + +#### `artifacts:reports`[](#artifactsreports "Permalink") + +[`artifacts:reports`关键字](../pipelines/job_artifacts.html#artifactsreports)用于从作业中收集测试报告,代码质量报告和安全性报告. 它还在 GitLab 的 UI 中显示这些报告(合并请求,管道视图和安全性仪表板). + +这些是可用的报告类型: + +| Parameter | Description | +| --- | --- | +| [`artifacts:reports:junit`](../pipelines/job_artifacts.html#artifactsreportsjunit) | `junit`报告收集 JUnit XML 文件. | +| [`artifacts:reports:dotenv`](../pipelines/job_artifacts.html#artifactsreportsdotenv) | `dotenv`报告收集一组环境变量. | +| [`artifacts:reports:cobertura`](../pipelines/job_artifacts.html#artifactsreportscobertura) | `cobertura`报告收集 Co​​bertura coverage XML 文件. | +| [`artifacts:reports:terraform`](../pipelines/job_artifacts.html#artifactsreportsterraform) | `terraform`报告收集 Terraform `tfplan.json`文件. | +| [`artifacts:reports:codequality`](../pipelines/job_artifacts.html#artifactsreportscodequality-starter) | `codequality`报告收集 Co​​deQuality 问题. | +| [`artifacts:reports:sast`](../pipelines/job_artifacts.html#artifactsreportssast-ultimate) | `sast`报告收集"静态应用程序安全性测试"漏洞. | +| [`artifacts:reports:dependency_scanning`](../pipelines/job_artifacts.html#artifactsreportsdependency_scanning-ultimate) | `dependency_scanning`报告收集"依赖关系扫描"漏洞. | +| [`artifacts:reports:container_scanning`](../pipelines/job_artifacts.html#artifactsreportscontainer_scanning-ultimate) | `container_scanning`报告收集容器扫描漏洞. | +| [`artifacts:reports:dast`](../pipelines/job_artifacts.html#artifactsreportsdast-ultimate) | `dast`报告收集动态应用程序安全测试漏洞. | +| [`artifacts:reports:license_management`](../pipelines/job_artifacts.html#artifactsreportslicense_management-ultimate) | `license_management`报告收集许可证( *已从 GitLab 13.0 中删除* ). | +| [`artifacts:reports:license_scanning`](../pipelines/job_artifacts.html#artifactsreportslicense_scanning-ultimate) | `license_scanning`报告收集许可证. | +| [`artifacts:reports:performance`](../pipelines/job_artifacts.html#artifactsreportsperformance-premium) | `performance`报告收集绩效指标. | +| [`artifacts:reports:metrics`](../pipelines/job_artifacts.html#artifactsreportsmetrics-premium) | `metrics`报告收集指标. | + +#### `dependencies`[](#dependencies "Permalink") + +在 GitLab 8.6 和 GitLab Runner v1.1.1 中引入. + +默认情况下,所有先前[阶段的](#stages)所有[`artifacts`](#artifacts)都被传递,但是您可以使用`dependencies`参数来定义要从中获取工件的有限的作业列表(或没有作业). + +要使用此功能,请在作业的上下文中定义`dependencies` ,并传递所有以前的工件应从中下载工件的列表. 您只能从当前阶段之前执行的阶段定义作业. 如果您从当前阶段或下一个阶段定义作业,将显示错误. 定义一个空数组将跳过下载该作业的任何工件. 在使用`dependencies` ,不会考虑先前作业的状态,因此,如果它失败或它是未运行的手动作业,则不会发生错误. + +在以下示例中,我们使用工件定义了两个作业`build:osx`和`build:linux` . 当执行`test:osx` ,将在`build:osx`上下文中下载并提取来自`build:osx`的工件. `test:linux`和`build:linux`工件也发生了同样的情况. + +由于[阶段](#stages)优先,作业`deploy`将下载所有先前作业的工件: + +``` +build:osx: + stage: build + script: make build:osx + artifacts: + paths: + - binaries/ + +build:linux: + stage: build + script: make build:linux + artifacts: + paths: + - binaries/ + +test:osx: + stage: test + script: make test:osx + dependencies: + - build:osx + +test:linux: + stage: test + script: make test:linux + dependencies: + - build:linux + +deploy: + stage: deploy + script: make deploy +``` + +##### When a dependent job will fail[](#when-a-dependent-job-will-fail "Permalink") + +在 GitLab 10.3 中引入. + +如果设置为依赖项的作业的工件已[过期](#artifactsexpire_in)或已[擦除](../pipelines/job_artifacts.html#erasing-artifacts) ,则依赖项作业将失败. + +**注意:**您可以要求管理员[翻转此开关](../../administration/job_artifacts.html#validation-for-dependencies)并恢复原来的行为. + +### `coverage`[](#coverage "Permalink") + +在 GitLab 8.17 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20428) . + +`coverage`允许您配置如何从作业输出中提取代码 coverage. + +正则表达式是此处期望的唯一有效值. 因此,必须使用周围的`/` ,以便一致且显式表示正则表达式字符串. 如果要按字面意义匹配特殊字符,则必须转义它们. + +一个简单的例子: + +``` +job1: + script: rspec + coverage: '/Code coverage: \d+\.\d+/' +``` + +### `retry`[](#retry "Permalink") + +版本历史 + +* 在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3442) . +* [行为](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3515)在 GitLab 11.5 中进行了[扩展](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3515) ,以控制重试哪些失败. + +`retry`允许您配置在失败的情况下重试作业的次数. + +当作业失败并配置了`retry` ,它将再次处理,直到`retry`关键字指定的时间. + +如果`retry`设置为 2,并且作业在第二次运行中成功(第一次重试),则不会再次重试. `retry`值必须是一个正整数,等于或大于 0,但小于或等于 2(最多两次重试,总共运行 3 次). + +在所有失败情况下重试的简单示例: + +``` +test: + script: rspec + retry: 2 +``` + +默认情况下,将在所有失败情况下重试作业. 为了更好地控制重`retry`哪些失败,重`retry`可以是具有以下键的哈希值: + +* `max` :最大重试次数. +* `when` :失败案例重试. + +要最多仅重试运行程序系统故障两次: + +``` +test: + script: rspec + retry: + max: 2 + when: runner_system_failure +``` + +如果有其他故障,而不是运行器系统故障,则不会重试该作业. + +重试对多个故障的情况下, `when`也可以是故障的数组: + +``` +test: + script: rspec + retry: + max: 2 + when: + - runner_system_failure + - stuck_or_timeout_failure +``` + +`when`可能值为: + +* `always` :发生任何故障时重试(默认). +* `unknown_failure` :当失败原因未知时重试. +* `script_failure` :脚本失败时重试. +* `api_failure` :API 失败重试. +* `stuck_or_timeout_failure` :作业卡住或超时时重试. +* `runner_system_failure` :如果运行系统发生故障(例如,作业设置失败),请重试. +* `missing_dependency_failure` :如果缺少依赖项,请重试. +* `runner_unsupported` :如果跑步者不受支持,请重试. +* `stale_schedule` :如果无法执行延迟的作业,请重试. +* `job_execution_timeout` :如果脚本超出了为作业设置的最大执行时间,则重试. +* `archived_failure` :如果作业已存档且无法运行,请重试. +* `unmet_prerequisites` :如果作业未能完成先决条件任务,请重试. +* `scheduler_failure` :如果调度程序未能将作业分配给运行`scheduler_failure`重试. +* `data_integrity_failure` :如果检测到结构完整性问题,请重试. + +您可以使用变量指定[作业执行某些阶段的重试次数](#job-stages-attempts) . + +### `timeout`[](#timeout "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/14887) . + +`timeout`允许您为特定作业配置超时. 例如: + +``` +build: + script: build.sh + timeout: 3 hours 30 minutes + +test: + script: rspec + timeout: 3h 30m +``` + +作业级超时可以超过[项目级超时,](../pipelines/settings.html#timeout)但不能超过 Runner 特定的超时. + +### `parallel`[](#parallel "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21480) . + +`parallel`允许您配置要并行运行的作业实例数. 此值必须大于或等于两(2)并且小于或等于 50. + +这将创建 N 个并行运行的同一作业实例. 它们从`job_name 1/N`到`job_name N/N`依次命名. + +对于每个作业, `CI_NODE_INDEX`设置`CI_NODE_INDEX`和`CI_NODE_TOTAL` [环境变量](../variables/README.html#predefined-environment-variables) . + +标记要并行运行的作业需要将`parallel`添加到配置文件中. 例如: + +``` +test: + script: rspec + parallel: 5 +``` + +**提示:**跨并行作业并行测试套件. 不同的语言具有不同的工具来促进这一点. + +一个使用[信号量测试助推器](https://github.com/renderedtext/test-boosters)和 RSpec 来运行一些 Ruby 测试的简单示例: + +``` +# Gemfile +source 'https://rubygems.org' + +gem 'rspec' +gem 'semaphore_test_boosters' +``` + +``` +test: + parallel: 3 + script: + - bundle + - bundle exec rspec_booster --job $CI_NODE_INDEX/$CI_NODE_TOTAL +``` + +**警告:**请注意 semaphore_test_boosters 向作者报告使用情况统计信息. + +然后,您可以导航到新管道构建的" **作业"**选项卡,并查看 RSpec 作业分为三个单独的作业. + +### `trigger`[](#trigger "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) . +* 在 12.8 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) GitLab Core. + +`trigger`允许您定义下游管道触发器. 当 GitLab 从`trigger`定义创建的作业启动时,将创建一个下游管道. + +此关键字允许创建两种不同类型的下游管道: + +* [Multi-project pipelines](../multi_project_pipelines.html#creating-multi-project-pipelines-from-gitlab-ciyml) +* [Child pipelines](../parent_child_pipelines.html) + +**注意:**将`trigger`与`when:manual`一起使用会导致错误`jobs:#{job-name} when should be on_success, on_failure or always` ,因为`when:manual`阻止使用触发器. + +#### Simple `trigger` syntax for multi-project pipelines[](#simple-trigger-syntax-for-multi-project-pipelines "Permalink") + +配置下游触发器的最简单方法是使用带有指向下游项目的完整路径的`trigger`关键字: + +``` +rspec: + stage: test + script: bundle exec rspec + +staging: + stage: deploy + trigger: my/deployment +``` + +#### Complex `trigger` syntax for multi-project pipelines[](#complex-trigger-syntax-for-multi-project-pipelines "Permalink") + +可以配置分支名称,GitLab 将使用该分支名称来创建下游管道: + +``` +rspec: + stage: test + script: bundle exec rspec + +staging: + stage: deploy + trigger: + project: my/deployment + branch: stable +``` + +可以从触发的管道中镜像状态: + +``` +trigger_job: + trigger: + project: my/project + strategy: depend +``` + +可以从上游管道镜像状态: + +``` +upstream_bridge: + stage: test + needs: + pipeline: other/project +``` + +#### `trigger` syntax for child pipeline[](#trigger-syntax-for-child-pipeline "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/16094) . + +要创建[子管道](../parent_child_pipelines.html) ,请指定包含子管道的 CI 配置的 YAML 文件的路径: + +``` +trigger_job: + trigger: + include: path/to/child-pipeline.yml +``` + +类似于[多项目管道](../multi_project_pipelines.html#mirroring-status-from-triggered-pipeline) ,可以从触发的管道中镜像状态: + +``` +trigger_job: + trigger: + include: + - local: path/to/child-pipeline.yml + strategy: depend +``` + +##### Trigger child pipeline with generated configuration file[](#trigger-child-pipeline-with-generated-configuration-file "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/35632) . + +您还可以从[动态生成的配置文件](../parent_child_pipelines.html#dynamic-child-pipelines)触发子管道: + +``` +generate-config: + stage: build + script: generate-ci-config > generated-config.yml + artifacts: + paths: + - generated-config.yml + +child-pipeline: + stage: test + trigger: + include: + - artifact: generated-config.yml + job: generate-config +``` + +从工件中提取了`generated-config.yml` ,并用作触发子管道的配置. + +#### Linking pipelines with `trigger:strategy`[](#linking-pipelines-with-triggerstrategy "Permalink") + +默认情况下,一旦创建下游管道, `trigger`作业就会以`success`状态完成. + +要强制`trigger`作业等待下游(多项目或子项目)管道完成,请使用`strategy: depend` . 这将使触发作业以"运行"状态等待,直到触发的管道完成. 此时, `trigger`作业将完成并显示与下游作业相同的状态. + +``` +trigger_job: + trigger: + include: path/to/child-pipeline.yml + strategy: depend +``` + +这可以使您的管道执行保持线性. 在上面的示例中,后续阶段的作业将在启动之前等待触发的管道成功完成,但代价是并行化程度降低. + +#### Trigger a pipeline by API call[](#trigger-a-pipeline-by-api-call "Permalink") + +当使用触发器令牌创建管道时,触发器可以用于通过 API 调用强制重建特定的分支,标记或提交. + +不要与[`trigger`](#trigger)参数混淆. + +[Read more in the triggers documentation.](../triggers/README.html) + +### `interruptible`[](#interruptible "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32022) . + +`interruptible`可用于指示如果作业因新的管道运行而变得多余,则应取消该作业. 默认为`false` . 仅当启用了[自动取消冗余管道功能](../pipelines/settings.html#auto-cancel-pending-pipelines)时,才使用此值. + +启用后,在以下情况下,将取消同一分支上的管道: + +* 它通过新的管道运行而变得多余. +* 将所有作业都设置为可中断,或者尚未开始任何不间断的作业. + +待处理的作业始终被视为可中断的. + +**Tip:** Set jobs as interruptible that can be safely canceled once started (for instance, a build job). + +这是一个简单的示例: + +``` +stages: + - stage1 + - stage2 + - stage3 + +step-1: + stage: stage1 + script: + - echo "Can be canceled." + interruptible: true + +step-2: + stage: stage2 + script: + - echo "Can not be canceled." + +step-3: + stage: stage3 + script: + - echo "Because step-2 can not be canceled, this step will never be canceled, even though set as interruptible." + interruptible: true +``` + +在上面的示例中,新的管道运行将导致现有的正在运行的管道为: + +* 如果仅`step-1`正在运行或挂起,则取消. +* 一旦`step-2`开始运行,则不会取消. + +**注意:**一旦运行了不间断的作业,无论最终作业的状态如何,管道将永远不会被取消. + +### `resource_group`[](#resource_group "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/15536) . + +有时在环境中同时运行多个作业或管道可能会导致在部署过程中出错. + +为了避免这些错误,可以使用`resource_group`属性来确保 Runner 不会同时运行某些作业. + +当在`.gitlab-ci.yml`为作业定义了`resource_group`键时,作业执行在同一项目的不同管道之间是互斥的. 如果属于同一资源组的多个作业同时进入队列,则 Runner 将仅选择一个作业,其他作业将等待,直到`resource_group`空闲为止. + +这是一个简单的示例: + +``` +deploy-to-production: + script: deploy + resource_group: production +``` + +在这种情况下,如果`deploy-to-production`作业在管道运行,并且新的`deploy-to-production`中不同的管道创建工作,它不会运行,直到当前运行的/未决`deploy-to-production`工作完成. 结果,您可以确保并发部署永远不会在生产环境中发生. + +每个环境可以定义多个`resource_group` . 一个很好的用例是在部署到物理设备时. 您可能具有多个物理设备,并且每个物理设备都可以部署到其中,但是在任何给定时间,每个设备只能有一个部署. + +**注:**此键只能包含字母,数字, `-` `_` , `/` , `$` , `{` , `}` , `.` 和空格. 它不能以`/`开头或结尾. + +有关更多信息,请参见[部署安全](../environments/deployment_safety.html) . + +### `release`[](#release "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/merge_requests/19298) . + +`release`表示作业创建一个[Release](../../user/project/releases/index.html) ,并且可以选择包含 Release 资产的 URL. + +支持以下方法: + +* [`tag_name`](#releasetag_name) +* [`name`](#releasename) (optional) +* [`description`](#releasedescription) (optional) +* [`ref`](#releaseref) (optional) +* [`milestones`](#releasemilestones) (optional) +* [`released_at`](#releasereleased_at) (optional) + +仅当作业处理没有错误时才创建发布. 如果 Rails API 在发布创建期间返回错误,则`release`作业将失败. + +#### `release-cli` Docker image[](#release-cli-docker-image "Permalink") + +必须使用以下指令指定用于`release-cli`的 Docker 映像: + +``` +image: registry.gitlab.com/gitlab-org/release-cli:latest +``` + +#### Script[](#script-1 "Permalink") + +所有作业至少需要一个`script`标签. `:release`作业可以使用`:script`标记的输出,但是如果没有必要,则可以使用占位符脚本,例如: + +``` +script: + - echo 'release job' +``` + +在即将发布的 GitLab 版本中存在删除此要求的[问题](https://gitlab.com/gitlab-org/gitlab/-/issues/223856) . + +管道可以具有多个`release`作业,例如: + +``` +ios-release: + script: + - echo 'iOS release job' + release: + tag_name: v1.0.0-ios + description: 'iOS release v1.0.0' + +android-release: + script: + - echo 'Android release job' + release: + tag_name: v1.0.0-android + description: 'Android release v1.0.0' +``` + +#### `release:tag_name`[](#releasetag_name "Permalink") + +必须指定`tag_name` . 它可以引用现有的 Git 标记,也可以由用户指定. + +当存储库中不存在指定的标签时,将从管道的关联 SHA 创建一个新标签. + +例如,从 Git 标签创建 Release 时: + +``` +job: + release: + tag_name: $CI_COMMIT_TAG + description: changelog.txt +``` + +也可以创建任何唯一标签, `only: tags`在这种情况下`only: tags`不是必需的. 语义版本控制示例: + +``` +job: + release: + tag_name: ${MAJOR}_${MINOR}_${REVISION} + description: changelog.txt +``` + +* 仅当作业的主脚本成功时才创建发布. +* 如果版本已经存在,则不会更新,并且带有`release`关键字的作业将失败. +* `release`部分在`script`标记之后和`after_script`之前`after_script` . + +#### `release:name`[](#releasename "Permalink") + +发布名称. 如果省略,则使用`release: tag_name`的值填充`release: tag_name` . + +#### `release:description`[](#releasedescription "Permalink") + +指定发布的详细描述. + +#### `release:ref`[](#releaseref "Permalink") + +如果`release: tag_name`尚不存在,则从`ref`创建版本. `ref`可以是提交 SHA,其他标记名称或分支名称. + +#### `release:milestones`[](#releasemilestones "Permalink") + +与发行版关联的每个里程碑的标题. + +#### `release:released_at`[](#releasereleased_at "Permalink") + +发布准备就绪的日期和时间. 如果未定义,则默认为当前日期和时间. 预期为 ISO 8601 格式(2019-03-15T08:00:00Z). + +#### Complete example for `release`[](#complete-example-for-release "Permalink") + +结合上面给出的`release`示例,将产生以下代码段. 有两种选择,具体取决于生成标记的方式. 这些选项不能一起使用,因此请选择以下一种: + +* 要在按下 Git 标签或在 UI 中通过添加**存储库>标签**来添加 Git 标签时创建发行版: + + ``` + release_job: + stage: release + image: registry.gitlab.com/gitlab-org/release-cli:latest + rules: + - if: $CI_COMMIT_TAG # Run this job when a tag is created manually + script: + - echo 'running release_job' + release: + name: 'Release $CI_COMMIT_TAG' + description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION must be defined + tag_name: '$CI_COMMIT_TAG' # elsewhere in the pipeline. + ref: '$CI_COMMIT_TAG' + milestones: + - 'm1' + - 'm2' + - 'm3' + released_at: '2020-07-15T08:00:00Z' # Optional, will auto generate if not defined, + # or can use a variable. + ``` + +* 要使用更改定义的新 Git 标签,将更改推送到默认分支时自动创建发行版: + + ``` + release_job: + stage: release + image: registry.gitlab.com/gitlab-org/release-cli:latest + rules: + - if: $CI_COMMIT_TAG + when: never # Do not run this job when a tag is created manually + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when the default branch changes + script: + - echo 'running release_job' + release: + name: 'Release $CI_COMMIT_SHA' + description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION and the tag_name + tag_name: 'v${MAJOR}.${MINOR}.${REVISION}' # variables must be defined elsewhere + ref: '$CI_COMMIT_SHA' # in the pipeline. + milestones: + - 'm1' + - 'm2' + - 'm3' + released_at: '2020-07-15T08:00:00Z' # Optional, will auto generate if not defined, + # or can use a variable. + ``` + +#### `releaser-cli` command line[](#releaser-cli-command-line "Permalink") + +`:release`节点下的条目被转换为`bash`命令行,并发送到包含[release-cli](https://gitlab.com/gitlab-org/release-cli)的 Docker 容器. 您也可以直接从`script`条目调用`release-cli` . + +上面描述的 YAML 将被翻译成如下的 CLI 命令: + +``` +release-cli create --name "Release $CI_COMMIT_SHA" --description "Created using the release-cli $EXTRA_DESCRIPTION" --tag-name "v${MAJOR}.${MINOR}.${REVISION}" --ref "$CI_COMMIT_SHA" --released-at "2020-07-15T08:00:00Z" --milestone "m1" --milestone "m2" --milestone "m3" +``` + +### `pages`[](#pages "Permalink") + +`pages`是一项特殊的工作,用于将静态内容上传到 GitLab,可用于为您的网站提供服务. 它具有特殊的语法,因此必须满足以下两个要求: + +* 任何静态内容都必须放在`public/`目录下. +* 必须定义带有`public/`目录路径的`artifacts` . + +下面的示例只是将所有文件从项目的根目录移到`public/`目录. `.public`解决方法是,因此`cp`也不会在无限循环中将`public/`复制到自身: + +``` +pages: + stage: deploy + script: + - mkdir .public + - cp -r * .public + - mv .public public + artifacts: + paths: + - public + only: + - master +``` + +阅读有关[GitLab Pages 用户文档的](../../user/project/pages/index.html)更多[信息](../../user/project/pages/index.html) . + +## `variables`[](#variables "Permalink") + +在 GitLab Runner v0.5.0 中引入. + +**注意:**对于变量的名称和值,整数(以及字符串)都是合法的. 浮动广告不合法,不能使用. + +GitLab CI / CD 允许您在`.gitlab-ci.yml`中定义变量,然后在作业环境中传递这些变量. 它们可以全局设置,也可以按工作设置. 在作业级别上使用`variables`关键字时,它将覆盖全局 YAML 变量和相同名称的预定义变量. + +它们存储在 Git 存储库中,用于存储非敏感项目配置,例如: + +``` +variables: + DATABASE_URL: "postgres://postgres@postgres/my_database" +``` + +这些变量以后可以在所有执行的命令和脚本中使用. YAML 定义的变量也设置为所有创建的服务容器,从而允许对其进行微调. + +除了用户定义的变量外,还有[由 Runner 本身设置的](../variables/README.html#predefined-environment-variables)变量. 一个示例是`CI_COMMIT_REF_NAME` ,它具有为其构建项目的分支或标记名称的值. 除了可以在`.gitlab-ci.yml`设置的变量`.gitlab-ci.yml` ,还有可以在 GitLab 的 UI 中设置的所谓[变量](../variables/README.html#gitlab-cicd-environment-variables) . + +提供了[用于变量的 YAML 锚](#yaml-anchors-for-variables) . + +了解有关[变量及其优先级的](../variables/README.html)更多信息. + +### Git strategy[](#git-strategy "Permalink") + +版本历史 + +* 在 GitLab 8.9 中作为实验功能引入. +* `GIT_STRATEGY=none`要求 GitLab Runner `GIT_STRATEGY=none` +. + +**注意:**在将来的版本中可能会更改或完全删除. + +您可以在[`variables`](#variables)部分中全局或按作业设置用于获取最新应用程序代码的`GIT_STRATEGY` . 如果未指定,将使用项目设置中的默认设置. + +有三个可能的值: `clone` , `fetch`和`none` . + +`clone`是最慢的选择. 它为每个作业从头克隆存储库,以确保本地工作副本始终是原始的. + +``` +variables: + GIT_STRATEGY: clone +``` + +`fetch`速度更快,因为它可以重新使用本地工作副本(如果不存在则回退到`clone` ). `git clean`用于撤消上一个作业所做的任何更改,而`git fetch`用于检索自上一个作业运行以来进行的提交. + +``` +variables: + GIT_STRATEGY: fetch +``` + +`none`再使用本地工作副本,但是会跳过所有 Git 操作(包括 GitLab Runner 的预克隆脚本(如果存在)). 对于仅在工件上运行的作业(例如`deploy` ),它最有用. Git 存储库数据可能存在,但是肯定会过时,因此您应该仅依靠从缓存或工件导入本地工作副本的文件. + +``` +variables: + GIT_STRATEGY: none +``` + +**注意:** `GIT_STRATEGY`器不支持[GIT_STRATEGY](https://docs.gitlab.com/runner/executors/kubernetes.html) ,但将来可能会支持. 有关更新,请参阅[带有 Kubernetes 执行器功能建议](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3847)的[支持 Git 策略](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3847) . + +### Git submodule strategy[](#git-submodule-strategy "Permalink") + +> 需要 GitLab Runner v1.10 +. + +`GIT_SUBMODULE_STRATEGY`变量用于控制在构建之前获取代码时是否包含/如何包含 Git 子模块. 您可以在[`variables`](#variables)部分中全局或按作业设置它们. + +共有三个可能的值: `none` , `normal`和`recursive` : + +* `none`表示在获取项目代码时将不包含子模块. 这是默认设置,与 v1.10 之前的行为匹配. + +* `normal`意味着仅包括顶级子模块. 等效于: + + ``` + git submodule sync git submodule update --init + ``` + +* `recursive`意味着将包括所有子模块(包括子模块的子模块). 此功能需要 Git v1.8.1 及更高版本. 当将 GitLab Runner 与不基于 Docker 的执行器一起使用时,请确保 Git 版本符合该要求. 等效于: + + ``` + git submodule sync --recursive + git submodule update --init --recursive + ``` + +请注意,为使此功能正常工作,必须使用以下任一方式(在`.gitmodules` )配置子模块: + +* 可公开访问的存储库的 HTTP(S)URL,或者 +* 到同一 GitLab 服务器上另一个存储库的相对路径. 请参阅[Git 子模块](../git_submodules.html)文档. + +### Git checkout[](#git-checkout "Permalink") + +在 GitLab Runner 9.3 中引入. + +当`GIT_STRATEGY`设置为`clone`或`fetch`以指定是否应运行`git checkout`时,可以使用`GIT_CHECKOUT`变量. 如果未指定,则默认为 true. 您可以在[`variables`](#variables)部分中全局或按作业设置它们. + +如果设置为`false` ,则跑步者将: + +* 进行`fetch` -更新存​​储库,并将工作副本保留在当前版本中, +* 执行`clone` -克隆存储库,并将工作副本保留在默认分支上. + +将此设置设置为`true`意味着对于`clone`和`fetch`策略,Runner 将签出工作副本到与 CI 管道相关的修订版本: + +``` +variables: + GIT_STRATEGY: clone + GIT_CHECKOUT: "false" +script: + - git checkout -B master origin/master + - git merge $CI_COMMIT_SHA +``` + +### Git clean flags[](#git-clean-flags "Permalink") + +在 GitLab Runner 11.10 中引入 + +`GIT_CLEAN_FLAGS`变量用于在签出源代码后控制`git clean`的默认行为. 您可以在[`variables`](#variables)部分中全局设置或按作业设置. + +`GIT_CLEAN_FLAGS`接受[`git clean`](https://git-scm.com/docs/git-clean)命令的所有可能选项. + +如果指定了`GIT_CHECKOUT: "false"`则禁用`git clean` . + +If `GIT_CLEAN_FLAGS` is: + +* 未指定, `git clean`标志默认为`-ffdx` . +* 给定值`none` ,将不执行`git clean` . + +例如: + +``` +variables: + GIT_CLEAN_FLAGS: -ffdx -e cache/ +script: + - ls -al cache/ +``` + +### Git fetch extra flags[](#git-fetch-extra-flags "Permalink") + +在 GitLab Runner 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4142) . + +`GIT_FETCH_EXTRA_FLAGS`变量用于控制`git fetch`的行为. 您可以在[`variables`](#variables)部分中全局设置或按作业设置. + +`GIT_FETCH_EXTRA_FLAGS`接受[`git fetch`](https://git-scm.com/docs/git-fetch)命令的所有可能选项,但请注意, `GIT_FETCH_EXTRA_FLAGS`标志将附加在无法修改的默认标志之后. + +默认标志是: + +* [GIT_DEPTH](#shallow-cloning). +* [refspec](https://git-scm.com/book/en/v2/Git-Internals-The-Refspec)列表. +* 遥远的`origin` . + +If `GIT_FETCH_EXTRA_FLAGS` is: + +* 未指定, `git fetch`标志与默认标志一起默认为`--prune --quiet` . +* 给定值`none` ,仅使用默认标志执行`git fetch` . + +例如,默认标志是`--prune --quiet` ,因此您可以通过仅用`--prune`覆盖它来使`git fetch`更加详细: + +``` +variables: + GIT_FETCH_EXTRA_FLAGS: --prune +script: + - ls -al cache/ +``` + +上面的配置将导致以这种方式调用`git fetch` : + +``` +git fetch origin $REFSPECS --depth 50 --prune +``` + +其中`$REFSPECS`是 GitLab 内部提供给 Runner 的值. + +### Job stages attempts[](#job-stages-attempts "Permalink") + +在 GitLab 中引入,它需要 GitLab Runner v1.9 +. + +您可以设置正在运行的作业尝试执行以下每个阶段的尝试次数: + +| Variable | Description | +| --- | --- | +| **GET_SOURCES_ATTEMPTS** | 尝试获取运行作业的源的次数 | +| **ARTIFACT_DOWNLOAD_ATTEMPTS** | 尝试下载运行作业的工件的次数 | +| **RESTORE_CACHE_ATTEMPTS** | 还原运行作业的缓存的尝试次数 | +| **EXECUTOR_JOB_SECTION_ATTEMPTS** | [从 GitLab 12.10 开始](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450) ,出现[`No Such Container`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450)错误(仅限[Docker 执行器](https://docs.gitlab.com/runner/executors/docker.html) )后,尝试在作业中运行部分的次数. | + +默认为一次尝试. + +Example: + +``` +variables: + GET_SOURCES_ATTEMPTS: 3 +``` + +您可以在[`variables`](#variables)部分中全局或按作业设置它们. + +### Shallow cloning[](#shallow-cloning "Permalink") + +在 GitLab 8.9 中作为实验功能引入. + +**注意** :从 GitLab 12.0 开始,新创建的项目将自动具有[默认的`git depth`值`50`](../pipelines/settings.html#git-shallow-clone) . + +您可以使用`GIT_DEPTH`指定获取和克隆的深度. 这允许对存储库进行浅层克隆,从而可以显着加快克隆具有大量提交或旧的大型二进制文件的存储库. 该值传递给`git fetch`和`git clone` . + +**注意:**如果使用 1 的深度,并且有作业队列或重试作业,则作业可能会失败. + +由于 Git 的获取和克隆基于引用(例如分支名称),因此 Runners 无法克隆特定的提交 SHA. 如果队列中有多个作业,或者您要重试旧的作业,则要测试的提交必须在克隆的 Git 历史记录内. 如果为`GIT_DEPTH`设置的值`GIT_DEPTH`则无法运行这些旧的提交. 您将在作业日志中看到`unresolved reference` . 然后,您应该重新考虑将`GIT_DEPTH`更改为更高的值. + +设置`GIT_DEPTH`时,依赖`git describe`作业可能无法正常工作,因为仅存在一部分 Git 历史记录. + +要仅获取或克隆最后 3 个提交,请执行以下操作: + +``` +variables: + GIT_DEPTH: "3" +``` + +您可以在[`variables`](#variables)部分中全局设置或按作业设置. + +### Custom build directories[](#custom-build-directories "Permalink") + +在 GitLab Runner 11.10 中[引入](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2211) + +**注意:**仅当在[Runner 的配置中](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)启用`custom_build_dir`时,才可以使用此`custom_build_dir` . 这是默认配置`docker`和`kubernetes`执行. + +默认情况下,GitLab Runner 将存储`$CI_BUILDS_DIR`到`$CI_BUILDS_DIR`目录的唯一子路径中. 但是,您的项目可能需要特定目录中的代码(例如,Go 项目). 在这种情况下,您可以指定`GIT_CLONE_PATH`变量,以告知 Runner 在哪个目录中克隆存储库: + +``` +variables: + GIT_CLONE_PATH: $CI_BUILDS_DIR/project-name + +test: + script: + - pwd +``` + +`GIT_CLONE_PATH`必须始终在`$CI_BUILDS_DIR` . `$CI_BUILDS_DIR`设置的目录取决于执行程序和[runners.builds_dir](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)设置的配置. + +#### Handling concurrency[](#handling-concurrency "Permalink") + +使用并发性大于`1`的执行程序可能会导致失败,因为如果在作业之间共享`builds_dir`则多个作业可能在同一目录上工作. GitLab Runner 不会尝试防止这种情况. 管理员和开发人员必须遵守 Runner 配置的要求. + +为了避免这种情况,您可以在`$CI_BUILDS_DIR`内使用唯一路径,因为 Runner 公开了两个提供唯一并发`ID`的变量: + +* `$CI_CONCURRENT_ID` :给定执行程序中运行的所有作业的唯一 ID. +* `$CI_CONCURRENT_PROJECT_ID` :给定执行程序和项目中运行的所有作业的唯一 ID. + +在任何情况下以及在任何执行程序上都应能正常工作的最稳定的配置是在`$CI_CONCURRENT_ID`中使用`$CI_CONCURRENT_ID` `GIT_CLONE_PATH` . 例如: + +``` +variables: + GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/project-name + +test: + script: + - pwd +``` + +在`$CI_CONCURRENT_PROJECT_ID`应结合使用`$CI_PROJECT_PATH`为`$CI_PROJECT_PATH`提供了一个存储库的路径. 即`group/subgroup/project` . 例如: + +``` +variables: + GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH + +test: + script: + - pwd +``` + +#### Nested paths[](#nested-paths "Permalink") + +`GIT_CLONE_PATH`的值被扩展一次,并且不支持其中的嵌套变量. + +例如,您在`.gitlab-ci.yml`文件中定义以下两个变量: + +``` +variables: + GOPATH: $CI_BUILDS_DIR/go + GIT_CLONE_PATH: $GOPATH/src/namespace/project +``` + +`GIT_CLONE_PATH`的值一次扩展到`$CI_BUILDS_DIR/go/src/namespace/project` ,并且由于`$CI_BUILDS_DIR`没有扩展而导致失败. + +## Special YAML features[](#special-yaml-features "Permalink") + +可以使用特殊的 YAML 功能,例如锚点( `&` ),别名( `*` )和地图合并( `<<` ),这将使您大大降低`.gitlab-ci.yml`的复杂性. + +阅读有关各种[YAML 功能的](https://learnxinyminutes.com/docs/yaml/)更多信息. + +在大多数情况下, [`extends`关键字](#extends)更加用户友好,应该在这些特殊的 YAML 功能上使用. 可能仍需要使用 YAML 锚来合并数组. + +### Anchors[](#anchors "Permalink") + +在 GitLab 8.6 和 GitLab Runner v1.1.1 中引入. + +YAML 具有称为"锚"的便捷功能,使您可以轻松地在整个文档中复制内容. 锚可用于复制/继承属性,并且是与[隐藏作业](#hide-jobs)一起使用以为您的作业提供模板的完美示例. 当有重复的密钥时,GitLab 将基于密钥执行反向深度合并. + +以下示例使用锚点和地图合并. 它将创建两个作业`test1`和`test2` ,它们将继承`.job_template`的参数,每个参数都定义了自己的自定义`script` : + +``` +.job_template: &job_definition # Hidden key that defines an anchor named 'job_definition' + image: ruby:2.6 + services: + - postgres + - redis + +test1: + <<: *job_definition # Merge the contents of the 'job_definition' alias + script: + - test1 project + +test2: + <<: *job_definition # Merge the contents of the 'job_definition' alias + script: + - test2 project +``` + +`&`设置锚点的名称( `job_definition` ), `<<`表示"将给定的哈希值合并到当前哈希中",并且`*`包括命名的锚点(再次为`job_definition` ). 扩展版本如下所示: + +``` +.job_template: + image: ruby:2.6 + services: + - postgres + - redis + +test1: + image: ruby:2.6 + services: + - postgres + - redis + script: + - test1 project + +test2: + image: ruby:2.6 + services: + - postgres + - redis + script: + - test2 project +``` + +让我们来看另一个例子. 这次,我们将使用锚来定义两组服务. 这将创建两个作业: `test:postgres`和`test:mysql` ,它们将共享`.job_template`定义的`script`指令以及`.postgres_services`和`.mysql_services`定义的`services`指令: + +``` +.job_template: &job_definition + script: + - test project + tags: + - dev + +.postgres_services: + services: &postgres_definition + - postgres + - ruby + +.mysql_services: + services: &mysql_definition + - mysql + - ruby + +test:postgres: + <<: *job_definition + services: *postgres_definition + tags: + - postgres + +test:mysql: + <<: *job_definition + services: *mysql_definition +``` + +扩展版本如下所示: + +``` +.job_template: + script: + - test project + tags: + - dev + +.postgres_services: + services: + - postgres + - ruby + +.mysql_services: + services: + - mysql + - ruby + +test:postgres: + script: + - test project + services: + - postgres + - ruby + tags: + - postgres + +test:mysql: + script: + - test project + services: + - mysql + - ruby + tags: + - dev +``` + +您可以看到隐藏的作业可以方便地用作模板. + +**Note:** Note that `tags: [dev]` has been overwritten by `tags: [postgres]`.**注意:**利用[`include`](#include)功能时,不能在多个文件中使用 YAML 锚. 锚仅在定义它们的文件内有效.您可以使用[`extends`关键字](#extends)来代替使用 YAML 锚. + +#### YAML anchors for `before_script` and `after_script`[](#yaml-anchors-for-before_script-and-after_script "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/23005) . + +您可以将[YAML 定位](#anchors) `after_script`与`before_script`和`after_script` ,从而可以在多个作业中包括预定义的命令列表. + +Example: + +``` +.something_before: &something_before + - echo 'something before' + +.something_after: &something_after + - echo 'something after' + - echo 'another thing after' + +job_name: + before_script: + - *something_before + script: + - echo 'this is the script' + after_script: + - *something_after +``` + +#### YAML anchors for `script`[](#yaml-anchors-for-script "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/23005) . + +您可以将[YAML 锚点](#anchors)与脚本一起使用,从而可以在多个作业中包括预定义的命令列表. + +例如: + +``` +.something: &something + - echo 'something' + +job_name: + script: + - *something + - echo 'this is the script' +``` + +#### YAML anchors for variables[](#yaml-anchors-for-variables "Permalink") + +[YAML 锚](#anchors)可以与`variables`一起使用,以轻松地在多个作业之间重复分配变量. 当作业需要特定的`variables`块(否则将覆盖全局变量)时,它还可以提供更大的灵活性. + +在下面的示例中,我们将覆盖`GIT_STRATEGY`变量,而不会影响`SAMPLE_VARIABLE`变量的使用: + +``` +# global variables +variables: &global-variables + SAMPLE_VARIABLE: sample_variable_value + ANOTHER_SAMPLE_VARIABLE: another_sample_variable_value + +# a job that needs to set the GIT_STRATEGY variable, yet depend on global variables +job_no_git_strategy: + stage: cleanup + variables: + <<: *global-variables + GIT_STRATEGY: none + script: echo $SAMPLE_VARIABLE +``` + +### Hide jobs[](#hide-jobs "Permalink") + +在 GitLab 8.6 和 GitLab Runner v1.1.1 中引入. + +如果要临时"禁用"作业,而不是注释掉定义作业的所有行: + +``` +#hidden_job: +# script: +# - run test +``` + +您可以改为以点号( `.` )开头,GitLab CI / CD 不会对其进行处理. 在以下示例中, `.hidden_job`将被忽略: + +``` +.hidden_job: + script: + - run test +``` + +使用此功能可忽略作业,或使用[特殊的 YAML 功能](#special-yaml-features)并将隐藏的作业转换为模板. + +## Skip Pipeline[](#skip-pipeline "Permalink") + +如果您的提交消息包含`[ci skip]`或`[skip ci]` ,则使用大写字母将创建提交,但是将跳过管道. + +或者,如果使用 Git 2.10 或更高版本,则可以传递`ci.skip` [Git 推送选项](../../user/project/push_options.html#push-options-for-gitlab-cicd) . + +## Processing Git pushes[](#processing-git-pushes "Permalink") + +当在单个`git push`调用中推送多个更改时,GitLab 将最多创建 4 条分支和标签管道. + +此限制不影响任何更新的合并请求管道. 使用[合并请求](../merge_request_pipelines/index.html)管道时,所有更新的合并请求都将创建一个管道. + +## Deprecated parameters[](#deprecated-parameters "Permalink") + +不推荐使用以下参数. + +### Globally-defined `types`[](#globally-defined-types "Permalink") + +**不**推荐**使用:** `types`不推荐使用,可以在以后的版本中删除. 使用[`stages`](#stages)代替. + +### Job-defined `type`[](#job-defined-type "Permalink") + +**不**推荐**使用:** `type`不推荐使用,可以在将来的发行版之一中将其删除. 使用[`stage`](#stage)代替. + +### Globally-defined `image`, `services`, `cache`, `before_script`, `after_script`[](#globally-defined-image-services-cache-before_script-after_script "Permalink") + +不`after_script`全局定义`image` , `services` , `cache` , `before_script`和`after_script` . 支持可以从将来的版本中删除. + +使用[`default:`](#global-defaults)代替. 例如: + +``` +default: + image: ruby:2.5 + services: + - docker:dind + cache: + paths: [vendor/] + before_script: + - bundle install --path vendor/ + after_script: + - rm -rf tmp/ +``` \ No newline at end of file diff --git a/_book/docs/200.md b/_book/docs/200.md new file mode 100644 index 0000000000000000000000000000000000000000..e7b98b4bb89a8f79fcb190f46cc0d1c8f237ab00 --- /dev/null +++ b/_book/docs/200.md @@ -0,0 +1,206 @@ +# GitLab CI/CD include examples + +> 原文:[https://docs.gitlab.com/ee/ci/yaml/includes.html](https://docs.gitlab.com/ee/ci/yaml/includes.html) + +* [Single string or array of multiple values](#single-string-or-array-of-multiple-values) +* [Re-using a `before_script` template](#re-using-a-before_script-template) +* [Overriding external template values](#overriding-external-template-values) +* [Using nested includes](#using-nested-includes) + +# GitLab CI/CD include examples[](#gitlab-cicd-include-examples "Permalink") + +除了[GitLab CI YAML 参考中](README.html)列出的[`includes`示例](README.html#include)之外,此页面还列出了`include`用法的更多变化. + +## Single string or array of multiple values[](#single-string-or-array-of-multiple-values "Permalink") + +您可以将额外的 YAML 文件作为单个字符串或多个值的数组包含在内. 以下示例均有效. + +`include:local`方法的单个字符串暗含: + +``` +include: '/templates/.after-script-template.yml' +``` + +Array with `include` method implied: + +``` +include: + - 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml' + - '/templates/.after-script-template.yml' +``` + +具有明确指定的`include`方法的单个字符串: + +``` +include: + remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml' +``` + +`include:remote`为单个项目的数组: + +``` +include: + - remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml' +``` + +具有多个显式指定的`include`方法的数组: + +``` +include: + - remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml' + - local: '/templates/.after-script-template.yml' + - template: Auto-DevOps.gitlab-ci.yml +``` + +数组混合语法: + +``` +include: + - 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml' + - '/templates/.after-script-template.yml' + - template: Auto-DevOps.gitlab-ci.yml + - project: 'my-group/my-project' + ref: master + file: '/templates/.gitlab-ci-template.yml' +``` + +## Re-using a `before_script` template[](#re-using-a-before_script-template "Permalink") + +在以下示例中, `.before-script-template.yml`的内容将与`.gitlab-ci.yml`的内容一起自动获取和评估. + +`https://gitlab.com/awesome-project/raw/master/.before-script-template.yml`内容: + +``` +before_script: + - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs + - gem install bundler --no-document + - bundle install --jobs $(nproc) "${FLAGS[@]}" +``` + +`.gitlab-ci.yml`内容: + +``` +include: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml' + +rspec: + script: + - bundle exec rspec +``` + +## Overriding external template values[](#overriding-external-template-values "Permalink") + +以下示例显示了特定的 YAML 定义的变量以及`.gitlab-ci.yml`自定义的包含文件中`production`作业的详细信息. + +`https://company.com/autodevops-template.yml`内容: + +``` +variables: + POSTGRES_USER: user + POSTGRES_PASSWORD: testing_password + POSTGRES_DB: $CI_ENVIRONMENT_SLUG + +production: + stage: production + script: + - install_dependencies + - deploy + environment: + name: production + url: https://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN + only: + - master +``` + +`.gitlab-ci.yml`内容: + +``` +include: 'https://company.com/autodevops-template.yml' + +image: alpine:latest + +variables: + POSTGRES_USER: root + POSTGRES_PASSWORD: secure_password + +stages: + - build + - test + - production + +production: + environment: + url: https://domain.com +``` + +在这种情况下,变量`POSTGRES_USER`和`POSTGRES_PASSWORD`以及`autodevops-template.yml`定义的`production`作业的环境 URL 已被`.gitlab-ci.yml`定义的新值覆盖. + +合并使您可以扩展和覆盖字典映射,但是不能向包含的数组添加或修改项目. 例如,要将其他项目添加到生产作业脚本中,必须重复现有的脚本项目: + +`https://company.com/autodevops-template.yml`内容: + +``` +production: + stage: production + script: + - install_dependencies + - deploy +``` + +`.gitlab-ci.yml`内容: + +``` +include: 'https://company.com/autodevops-template.yml' + +stages: + - production + +production: + script: + - install_dependencies + - deploy + - notify_owner +``` + +在这种情况下,如果未在`.gitlab-ci.yml`重复`install_dependencies`和`deploy` ,则它们将不会成为组合 CI 配置中`production`作业脚本的一部分. + +## Using nested includes[](#using-nested-includes "Permalink") + +以下示例显示了如何使用不同方法的组合从不同来源嵌套包含对象. + +在此示例中, `.gitlab-ci.yml`本地包含文件`/.gitlab-ci/another-config.yml` : + +``` +include: + - local: /.gitlab-ci/another-config.yml +``` + +`/.gitlab-ci/another-config.yml`包含一个模板和另一个项目中的`/templates/docker-workflow.yml`文件: + +``` +include: + - template: Bash.gitlab-ci.yml + - project: group/my-project + file: /templates/docker-workflow.yml +``` + +该`/templates/docker-workflow.yml`出现在`group/my-project`包括的两个本地文件`group/my-project` : + +``` +include: + - local: /templates/docker-build.yml + - local: /templates/docker-testing.yml +``` + +我们在`group/my-project` `/templates/docker-build.yml`添加了一个`docker-build`作业: + +``` +docker-build: + script: docker build -t my-image . +``` + +我们在`group/my-project`出现的第二个`/templates/docker-test.yml`添加了一个`docker-test`作业: + +``` +docker-test: + script: docker run my-image /run/tests.sh +``` \ No newline at end of file diff --git a/_book/docs/201.md b/_book/docs/201.md new file mode 100644 index 0000000000000000000000000000000000000000..5fca31e1ec00b9b213a10050246be1b3695166a3 --- /dev/null +++ b/_book/docs/201.md @@ -0,0 +1,156 @@ +# Introduction to CI/CD with GitLab + +> 原文:[https://docs.gitlab.com/ee/ci/introduction/](https://docs.gitlab.com/ee/ci/introduction/) + +* [Introduction to CI/CD methodologies](#introduction-to-cicd-methodologies) + * [Continuous Integration](#continuous-integration) + * [Continuous Delivery](#continuous-delivery) + * [Continuous Deployment](#continuous-deployment) +* [Introduction to GitLab CI/CD](#introduction-to-gitlab-cicd) + * [How GitLab CI/CD works](#how-gitlab-cicd-works) + * [Basic CI/CD workflow](#basic-cicd-workflow) + * [A deeper look into the CI/CD basic workflow](#a-deeper-look-into-the-cicd-basic-workflow) + * [Setting up GitLab CI/CD for the first time](#setting-up-gitlab-cicd-for-the-first-time) + +# Introduction to CI/CD with GitLab[](#introduction-to-cicd-with-gitlab "Permalink") + +在本文档中,我们将概述持续集成,持续交付和持续部署的概念,并介绍 GitLab CI / CD. + +**开箱即用的管理系统可以将维护工具链所花费的时间减少 10%或更多.** 观看我们的["精通持续软件开发"](https://about.gitlab.com/webcast/mastering-ci-cd/)网络广播,以了解连续方法以及 GitLab 的内置 CI 如何帮助您简化和扩展软件开发. + +## Introduction to CI/CD methodologies[](#introduction-to-cicd-methodologies "Permalink") + +软件开发的连续方法基于自动执行脚本,以最大程度地减少在开发应用程序时引入错误的机会. 从开发新代码到部署新代码,他们几乎不需要人工干预,甚至根本不需要干预. + +它涉及到在每次小的迭代中就不断地构建,测试和部署代码更改,从而减少了基于错误或失败的先前版本开发新代码的机会. + +此方法有三种主要方法,每种方法都将根据最适合您的策略的方式进行应用. + +### Continuous Integration[](#continuous-integration "Permalink") + +考虑一个应用程序,其代码存储在 GitLab 的 Git 存储库中. 开发人员每天要多次推送代码更改. 对于每次向存储库的推送,您都可以创建一组脚本来自动构建和测试您的应用程序,从而减少了向应用程序引入错误的机会. + +这种做法被称为[持续整合](https://en.wikipedia.org/wiki/Continuous_integration) ; 对于提交给应用程序(甚至是开发分支)的每个更改,它都会自动连续地构建和测试,以确保所引入的更改通过您为应用程序建立的所有测试,准则和代码合规性标准. + +[GitLab 本身](https://gitlab.com/gitlab-org/gitlab-foss)就是使用持续集成作为软件开发方法的一个示例. 对于项目的每一次推送,都有一组检查脚本的脚本. + +### Continuous Delivery[](#continuous-delivery "Permalink") + +[持续交付](https://continuousdelivery.com/)是超越持续集成的一步. 您的应用程序不仅会在推送到代码库的每次代码更改时都进行构建和测试,而且作为附加步骤,尽管部署是手动触发的,但它仍会持续部署. + +此方法可确保自动检查代码,但需要人工干预才能从策略上手动触发更改的部署. + +### Continuous Deployment[](#continuous-deployment "Permalink") + +类似于持续交付, [持续部署](https://www.airpair.com/continuous-deployment/posts/continuous-deployment-for-practical-people)也是超越持续集成的又一步. 区别在于,您无需将其手动部署,而是将其设置为自动部署. 部署您的应用程序完全不需要人工干预. + +## Introduction to GitLab CI/CD[](#introduction-to-gitlab-cicd "Permalink") + +GitLab CI / CD 是内置在 GitLab 中的功能强大的工具,它使您可以将所有连续方法(连续集成,交付和部署)应用于软件,而无需第三方应用程序或集成. + +有关概述,请参阅最近的 GitLab 聚会中的[GitLab CI 简介](https://www.youtube.com/watch?v=l5705U8s_nQ&t=397) . + +### How GitLab CI/CD works[](#how-gitlab-cicd-works "Permalink") + +要使用 GitLab CI / CD,您需要做的是托管在 Git 存储库中的应用程序代码库,并在[`.gitlab-ci.yml`](../yaml/README.html)文件中指定生成,测试和部署脚本,该文件位于以下目录的根路径中:您的存储库. + +在此文件中,您可以定义要运行的脚本,定义包含和缓存依赖项,选择要按顺序运行的命令和要并行运行的命令,定义要在哪里部署应用程序,以及指定是否将要自动运行脚本或手动触发任何脚本. 熟悉 GitLab CI / CD 后,您可以在配置文件中添加更多高级步骤. + +要将脚本添加到该文件,您需要按照适合您的应用程序并符合您要执行的测试的顺序来组织它们. 为了可视化该过程,假设添加到配置文件中的所有脚本与在计算机的终端上运行的命令相同. + +将`.gitlab-ci.yml`配置文件添加到存储库后,GitLab 将检测到该文件并使用名为[GitLab Runner](https://docs.gitlab.com/runner/)的工具运行脚本,该工具的操作与终端类似. + +这些脚本被分组为**作业** ,它们共同组成了一个**管道** . `.gitlab-ci.yml`文件的一个简约示例可以包含: + +``` +before_script: + - apt-get install rubygems ruby-dev -y + +run-test: + script: + - ruby --version +``` + +`before_script`属性将在运行任何内容之前为您的应用程序安装依赖项,并且名为`run-test`的**作业**将打印当前系统的 Ruby 版本. 它们两者都构成了在每次推送到存储库的任何分支时触发的**管道** . + +GitLab CI / CD 不仅执行您已设置的作业,而且还向您显示执行期间发生的事情,就像您在终端中看到的那样: + +[![job running](img/b452a194fd7fbbdd22f73a1dda9b236a.png)](img/job_running.png) + +您为您的应用程序创建了策略,GitLab 根据您定义的内容为您运行管道. 您的管道状态也会由 GitLab 显示: + +[![pipeline status](img/be1eaf723e0603b081c01aa4310c304c.png)](img/pipeline_status.png) + +最后,如果出现任何问题,您可以轻松[回滚](../environments/index.html#retrying-and-rolling-back)所有更改: + +[![rollback button](img/ce2f28e687df2b322895dbfb6c48d389.png)](img/rollback.png) + +### Basic CI/CD workflow[](#basic-cicd-workflow "Permalink") + +考虑以下示例,以了解 GitLab CI / CD 如何适合通用开发工作流程. + +假设您已在一个问题中讨论了代码实现,并在本地进行了建议的更改. 将提交推送到 GitLab 中的远程存储库中的功能分支后,将触发项目的 CI / CD 管道集. 这样,GitLab CI / CD: + +* 运行自动化脚本(顺序或并行)以: + * 构建并测试您的应用. + * 就像在`localhost`看到的那样,使用 Review Apps 预览每个合并请求的更改. + +对实施感到满意后: + +* 让您的代码得到审查和批准. +* 将功能分支合并到默认分支. + * GitLab CI / CD 将您的更改自动部署到生产环境. +* 最后,如果出现问题,您和您的团队可以轻松地将其回滚. + +[![GitLab workflow example](img/4ab2d185d65e76a0d58ad6564dff777a.png)](img/gitlab_workflow_example_11_9.png) + +GitLab CI / CD 可以做更多的事情,但是此工作流程体现了 GitLab 跟踪整个过程的能力,而无需使用外部工具来交付软件. 而且,最有用的是,您可以通过 GitLab UI 可视化所有步骤. + +#### A deeper look into the CI/CD basic workflow[](#a-deeper-look-into-the-cicd-basic-workflow "Permalink") + +如果我们深入研究基本工作流程,则可以在 DevOps 生命周期的每个阶段看到 GitLab 中可用的功能,如下图所示. + +[![Deeper look into the basic CI/CD workflow](img/33c514aefa1ff87fe18907b27d473e03.png)](img/gitlab_workflow_example_extended_v12_3.png) + +如果您从左至右查看图像,则会根据每个阶段(验证,打包,发布)看到 GitLab 中的一些可用功能. + +1. **Verify**: + * 通过持续集成自动构建和测试您的应用程序. + * 使用[GitLab 代码质量](../../user/project/merge_requests/code_quality.html)分析您的源代码[质量](../../user/project/merge_requests/code_quality.html) . + * 使用[浏览器性能测试](../../user/project/merge_requests/browser_performance_testing.html)确定代码更改对性能的影响. + * 执行一系列测试,例如[容器扫描](../../user/application_security/container_scanning/index.html) , [依赖扫描](../../user/application_security/dependency_scanning/index.html) 和[JUnit 测试](../junit_test_reports.html) . + * 使用[Review Apps](../review_apps/index.html)部署更改,以预览每个分支上的应用程序更改. +2. **Package**: + * 使用[Container Registry](../../user/packages/container_registry/index.html)存储 Docker 映像. + * 使用[NPM Registry](../../user/packages/npm_registry/index.html)存储 NPM 软件包. + * 用[Maven 存储库](../../user/packages/maven_repository/index.html)存储 Maven 工件. + * 将 Conan 软件包存储在[Conan 仓库中](../../user/packages/conan_repository/index.html) . +3. **Release**: + * 持续部署,自动将您的应用程序部署到生产环境. + * 连续交付,手动单击以将您的应用程序部署到生产环境. + * 使用[GitLab Pages](../../user/project/pages/index.html)部署静态网站. + * 仅将功能部件运送到您的一部分吊舱中,并让一定比例的用户群通过[Canary Deployments](../../user/project/canary_deployments.html)访问临时部署的功能部件. + * 在[功能标记](../../operations/feature_flags.html)后面部署[功能](../../operations/feature_flags.html) . + * 使用[GitLab Releases](../../user/project/releases/index.html)向任何 Git 标签添加发行说明. + * View of the current health and status of each CI environment running on Kubernetes with [Deploy Boards](../../user/project/deploy_boards.html). + * 使用[Auto Deploy](../../topics/autodevops/stages.html#auto-deploy)将应用程序部署到 Kubernetes 集群中的生产环境. + +使用 GitLab CI / CD,您还可以: + +* 通过[Auto DevOps](../../topics/autodevops/index.html)轻松设置应用程序的整个生命周期. +* 将您的应用程序部署到不同的[环境](../environments/index.html) . +* 安装自己的[GitLab Runner](https://docs.gitlab.com/runner/) . +* [Schedule pipelines](../pipelines/schedules.html). +* 使用[安全测试报告](../../user/application_security/index.html)检查应用程序漏洞. + +要查看所有 CI / CD 功能,请导航回[CI / CD 索引](../README.html) . + +观看视频[GitLab CI Live 演示](https://youtu.be/l5705U8s_nQ?t=369) ,深入了解 GitLab CI / CD. + +### Setting up GitLab CI/CD for the first time[](#setting-up-gitlab-cicd-for-the-first-time "Permalink") + +要开始使用 GitLab CI / CD,您需要熟悉[`.gitlab-ci.yml`](../yaml/README.html)配置文件的语法及其属性. + +本文档[在 GitLab Pages 的范围内介绍了 GitLab CI / CD 的概念](../../user/project/pages/getting_started/pages_from_scratch.html) ,用于部署静态网站. 尽管它是为想要从头开始编写自己的 Pages 脚本的用户而设计的,但它也可以作为 GitLab CI / CD 设置过程的简介. 它涵盖了编写 CI / CD 配置文件的最初一般步骤,因此我们建议您通读它以了解 GitLab 的 CI / CD 逻辑,并学习如何为任何应用程序编写自己的脚本(或调整现有脚本). + +要深入了解 GitLab 的 CI / CD 配置选项,请查看[`.gitlab-ci.yml`完整参考](../yaml/README.html) . \ No newline at end of file diff --git a/_book/docs/202.md b/_book/docs/202.md new file mode 100644 index 0000000000000000000000000000000000000000..42613889e09d76dc10128827815209ac0d416d09 --- /dev/null +++ b/_book/docs/202.md @@ -0,0 +1,172 @@ +# Getting started with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/quick_start/README.html](https://docs.gitlab.com/ee/ci/quick_start/README.html) + +* [Creating a `.gitlab-ci.yml` file](#creating-a-gitlab-ciyml-file) + * [What is `.gitlab-ci.yml`](#what-is-gitlab-ciyml) + * [Creating a simple `.gitlab-ci.yml` file](#creating-a-simple-gitlab-ciyml-file) + * [Push `.gitlab-ci.yml` to GitLab](#push-gitlab-ciyml-to-gitlab) +* [Configuring a Runner](#configuring-a-runner) + * [Shared Runners](#shared-runners) +* [Seeing the status of your pipeline and jobs](#seeing-the-status-of-your-pipeline-and-jobs) +* [Examples](#examples) + +# Getting started with GitLab CI/CD[](#getting-started-with-gitlab-cicd "Permalink") + +**注意:**从 8.0 版开始,GitLab [持续集成](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/) (CI)已完全集成到 GitLab 本身,并且默认情况下在所有项目上都[启用](../enable_or_disable_ci.html) .**注意:**请记住,只有项目维护者和管理员用户有权访问项目的设置.**注意:**要从 Jenkins 转到 GitLab 吗? 查阅我们的[参考](../jenkins/index.html) ,将您先前存在的管道转换为我们的格式.**注意:**您可以考虑在项目中使用几种不同的[基本管道体系结构](../pipelines/pipeline_architectures.html) . 您可能需要在开始之前熟悉这些内容. + +GitLab 提供[持续集成](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)服务. 对于每次提交或推送以触发您的 CI [管道](../pipelines/index.html) ,您必须: + +* Add a [`.gitlab-ci.yml` file](#creating-a-gitlab-ciyml-file) to your repository’s root directory. +* 确保将项目配置为使用[Runner](#configuring-a-runner) . + +`.gitlab-ci.yml`文件告诉 GitLab Runner 做什么. 一个简单的管道通常包括三个[阶段](../yaml/README.html#stages) : + +* `build` +* `test` +* `deploy` + +您不需要使用所有三个阶段; 没有工作的阶段将被忽略. + +管道显示在项目的**CI / CD>管道**页面下. 如果一切运行正常(没有非零返回值),您将获得与提交关联的绿色复选标记. 这样就可以轻松查看提交是否导致任何测试失败,甚至无需查看作业(测试)日志. 许多项目使用 GitLab 的 CI 服务来运行测试套件,因此如果开发人员遇到问题,他们会立即获得反馈. + +通常,使用管道将经过测试的代码自动部署到登台和生产环境中. + +* * * + +本指南假定您具有: + +* 8.0+或正在使用[GitLab.com 的](https://gitlab.com)有效 GitLab 实例. +* 您要在其中使用 CI 的 GitLab 中的项目. +* 维护者或所有者对项目的访问 + +让我们将其分解为 GitLab CI / CD 难题. + +## Creating a `.gitlab-ci.yml` file[](#creating-a-gitlab-ciyml-file "Permalink") + +在创建`.gitlab-ci.yml`之前,让我们首先简要地解释这是怎么回事. + +### What is `.gitlab-ci.yml`[](#what-is-gitlab-ciyml "Permalink") + +您可以在`.gitlab-ci.yml`文件中配置 CI 对项目的作用. 它位于存储库的根目录中. + +在对存储库进行任何推送时,GitLab 都会查找`.gitlab-ci.yml`文件,并根据该文件的内容在*Runners*上启动作业,以进行提交. + +由于`.gitlab-ci.yml`在存储库中并且受版本控制,因此旧版本仍然可以成功构建,fork 可以轻松使用 CI,分支可以具有不同的管道和作业,并且您拥有 CI 的唯一真实来源. 您可以[在我们的博客中](https://about.gitlab.com/blog/2015/05/06/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml/)阅读更多有关为什么使用`.gitlab-ci.yml`的原因. + +### Creating a simple `.gitlab-ci.yml` file[](#creating-a-simple-gitlab-ciyml-file "Permalink") + +> **注意:** `.gitlab-ci.yml`是一个[YAML](https://en.wikipedia.org/wiki/YAML)文件,因此您必须特别注意缩进. 始终使用空格,不要使用制表符. + +您需要在存储库的根目录中创建一个名为`.gitlab-ci.yml`的文件. 以下是 Ruby on Rails 项目的示例. + +``` +image: "ruby:2.5" + +before_script: + - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs + - ruby -v + - which ruby + - gem install bundler --no-document + - bundle install --jobs $(nproc) "${FLAGS[@]}" + +rspec: + script: + - bundle exec rspec + +rubocop: + script: + - bundle exec rubocop +``` + +This is the simplest possible configuration that will work for most Ruby applications: + +1. 用要执行的不同命令定义两个作业`rspec`和`rubocop` (名称是任意的). +2. 在执行每个作业之前,将执行`before_script`定义的命令. + +`.gitlab-ci.yml`文件定义了作业集,并限制了作业的运行方式和时间. 作业被定义为具有名称的顶级元素(在我们的示例中为`rspec`和`rubocop` ),并且始终必须包含`script`关键字. 乔布斯被用于创造就业机会,然后由挑选[运动员](../runners/README.html)和跑步者的环境中执行. + +重要的是每个作业都彼此独立运行. + +如果要检查项目的`.gitlab-ci.yml`是否有效,则项目名称空间的`/-/ci/lint`页下有一个 Lint 工具. 您也可以在项目的**CI / CD➔管道**和**管道➔作业**下找到" CI Lint"按钮以转到此页面. + +有关更多信息和完整的`.gitlab-ci.yml`语法,请阅读[`.gitlab-ci.yml`上的参考文档](../yaml/README.html) . + +### Push `.gitlab-ci.yml` to GitLab[](#push-gitlab-ciyml-to-gitlab "Permalink") + +创建`.gitlab-ci.yml` ,应将其添加到 Git 存储库中并将其推送到 GitLab. + +``` +git add .gitlab-ci.yml +git commit -m "Add .gitlab-ci.yml" +git push origin master +``` + +现在,如果您转到" **管道"**页面,您将看到管道处于挂起状态. + +**注意:**如果您有一个[从 GitLab 提取镜像的存储库](../../user/project/repository/repository_mirroring.html#pulling-from-a-remote-repository-starter) ,则可能需要在项目的**"设置">"存储库">"从远程存储库中提取">"触发管道以进行镜像更新"中**启用管道触发. + +您也可以转到" **提交"**页面,注意提交 SHA 旁边的小暂停图标. + +[![New commit pending](img/3b3e644f832753a09f245236299e74b2.png)](img/new_commit.png) + +单击它,您将被定向到该特定提交的作业页面. + +[![Single commit jobs page](img/f8cfebdbd362ba809375c8d9c38416ba.png)](img/single_commit_status_pending.png) + +注意,有一个待处理的作业以我们在`.gitlab-ci.yml`编写的`.gitlab-ci.yml` . "卡住"表示尚未为此作业配置任何运行器. + +下一步是配置运行器,以便它选择挂起的作业. + +## Configuring a Runner[](#configuring-a-runner "Permalink") + +在 GitLab 中,Runners 运行您在`.gitlab-ci.yml`定义的作业. Runner 可以是虚拟机,VPS,裸机,Docker 容器甚至是容器集群. GitLab 和 Runners 通过 API 进行通信,因此唯一的要求是 Runner 的计算机具有对 GitLab 服务器的网络访问权限. + +Runner 可以特定于某个项目,也可以在 GitLab 中服务多个项目. 如果它服务于所有项目,则称为*Shared Runner* . + +在" [跑步者"](../runners/README.html)文档中查找有关不同跑步者的更多信息. + +您可以通过转到**设置➔CI / CD**来查找是否将任何跑步者分配给您的项目. 设置 Runner 既简单又直接. GitLab 支持的官方 Runner 是用 Go 编写的,其文档可以在[https://docs.gitlab.com/runner/中](https://docs.gitlab.com/runner/)找到. + +为了拥有功能正常的 Runner,您需要执行以下两个步骤: + +1. [Install it](https://docs.gitlab.com/runner/install/) +2. [Configure it](https://docs.gitlab.com/runner/configuration/) + +请按照上面的链接设置您自己的 Runner 或使用下一节所述的 Shared Runner. + +设置 Runner 之后,您应该在**设置➔CI / CD**后面的项目的 Runners 页面上看到它. + +[![Activated runners](img/423e566cce1da11ef163c69219f870aa.png)](img/runners_activated.png) + +### Shared Runners[](#shared-runners "Permalink") + +如果使用[GitLab.com](https://gitlab.com/) ,则可以使用 GitLab Inc.提供的**共享运行程序** . + +这些是在 GitLab 基础架构上运行的特殊虚拟机,可以构建任何项目. + +要启用**共享运行程序,**您必须转到项目的**设置➔CI / CD** ,然后单击**启用共享运行程序** . + +[Read more on Shared Runners](../runners/README.html). + +## Seeing the status of your pipeline and jobs[](#seeing-the-status-of-your-pipeline-and-jobs "Permalink") + +成功配置 Runner 之后,您应该看到上一次提交的状态从" *未决"*更改为" *正在* *运行"* ," *成功"*或" *失败"* . + +您可以转到项目中的" **管道"**页面来查看所有管道. + +[![Commit status](img/0748208b938145b0cf688cc0a3cb7b09.png)](img/pipelines_status.png) + +或者,您可以转到" **管道➔作业"**页面查看所有作业. + +[![Commit status](img/c0fd76908cea66a75fbd88aeb1ccec31.png)](img/builds_status.png) + +通过单击作业的状态,您将能够看到该作业的日志. 这对于诊断工作为什么失败或行为与您预期的不同很重要. + +[![Build log](img/f5f57e5e3d074f574a5b26d23eb0b721.png)](img/build_log.png) + +您还可以在 GitLab 的各个页面中查看任何提交的状态,例如**提交**和**合并请求** . + +## Examples[](#examples "Permalink") + +请访问[示例自述文件](../examples/README.html)以查看使用各种语言的 GitLab CI 的示例列表. \ No newline at end of file diff --git a/_book/docs/203.md b/_book/docs/203.md new file mode 100644 index 0000000000000000000000000000000000000000..ea42af4eb2b08c797a960758512c5396b4caebf6 --- /dev/null +++ b/_book/docs/203.md @@ -0,0 +1,80 @@ +# How to enable or disable GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/enable_or_disable_ci.html](https://docs.gitlab.com/ee/ci/enable_or_disable_ci.html) + +* [Per-project user setting](#per-project-user-setting) +* [Site-wide admin setting](#site-wide-admin-setting) + +# How to enable or disable GitLab CI/CD[](#how-to-enable-or-disable-gitlab-cicd "Permalink") + +为了有效使用 GitLab CI / CD,您需要: + +* 项目根目录中存在一个有效的[`.gitlab-ci.yml`](yaml/README.html)文件. +* [跑步者](runners/README.html)正确设置. + +您可以阅读我们的[快速入门指南](quick_start/README.html)以开始使用. + +如果您使用的是 Jenkins 或 Drone CI 之类的外部 CI / CD 服务器,建议禁用 GitLab CI / CD,以免与提交状态 API 发生冲突. + +GitLab CI/CD is exposed via the `/pipelines` and `/jobs` pages of a project. Disabling GitLab CI/CD in a project does not delete any previous jobs. In fact, the `/pipelines` and `/jobs` pages can still be accessed, although it’s hidden from the left sidebar menu. + +GitLab CI / CD 在新安装中默认情况下处于启用状态,并且可以被禁用: + +* 在每个项目的设置下单独进行. +* 通过修改分别用于源代码安装和 Omnibus 安装的`gitlab.yml`和`gitlab.rb`的设置在`gitlab.yml`站点范围内. + +**注意:**这仅适用于作为 GitLab CI / CD 的一部分运行的管道. 这将不会启用或禁用通过[外部集成](../user/project/integrations/overview.html#integrations-listing)运行的管道. + +## Per-project user setting[](#per-project-user-setting "Permalink") + +要在项目中启用或禁用 GitLab CI / CD 管道: + +1. 导航至**设置>常规>可见性,项目功能,权限** . +2. 展开**存储库**部分 +3. 根据需要启用或禁用" **管道"**切换. + +**项目可见性**还将影响管道可见性. 如果设置为: + +* **私有** :只有项目成员才能访问管道. +* **内部**或**公共** :可以通过下拉框将管道设置为" **仅项目成员"**或" **具有访问权限的所有人** ". + +按**保存更改**以使设置生效. + +## Site-wide admin setting[](#site-wide-admin-setting "Permalink") + +您可以在`gitlab.yml`站点上禁用 GitLab CI / CD,方法是修改`gitlab.yml`用于源代码安装的设置,以及`gitlab.rb`用于 Omnibus 安装的设置. + +有两件事要注意: + +* 禁用 GitLab CI / CD,将仅影响新创建的项目. 在此修改之前启用了此功能的项目将照常工作. +* 即使您禁用了 GitLab CI / CD,用户仍然可以在项目的设置中启用它. + +对于源安装, `gitlab.yml`使用编辑器打开`gitlab.yml`并将`builds`设置为`false` : + +``` +## Default project features settings +default_projects_features: + issues: true + merge_requests: true + wiki: true + snippets: false + builds: false +``` + +保存文件并重新启动 GitLab: + +``` +sudo service gitlab restart +``` + +对于 Omnibus 安装,请编辑`/etc/gitlab/gitlab.rb`并添加以下行: + +``` +gitlab_rails['gitlab_default_projects_features_builds'] = false +``` + +保存文件并重新配置 GitLab: + +``` +sudo gitlab-ctl reconfigure +``` \ No newline at end of file diff --git a/_book/docs/204.md b/_book/docs/204.md new file mode 100644 index 0000000000000000000000000000000000000000..ffe0a500e8e38d706b69bac121f09ac59af2b19c --- /dev/null +++ b/_book/docs/204.md @@ -0,0 +1,164 @@ +# Using SSH keys with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/ssh_keys/README.html](https://docs.gitlab.com/ee/ci/ssh_keys/README.html) + +* [How it works](#how-it-works) +* [SSH keys when using the Docker executor](#ssh-keys-when-using-the-docker-executor) +* [SSH keys when using the Shell executor](#ssh-keys-when-using-the-shell-executor) +* [Verifying the SSH host keys](#verifying-the-ssh-host-keys) +* [Example project](#example-project) + +# Using SSH keys with GitLab CI/CD[](#using-ssh-keys-with-gitlab-cicd "Permalink") + +GitLab 当前不支持在构建环境(运行 GitLab Runner 的环境)中管理 SSH 密钥的内置支持. + +SSH 密钥在以下情况下很有用: + +1. 您想签出内部子模块 +2. 您想使用包管理器(例如 Bundler)下载私有包 +3. 您想要将应用程序部署到自己的服务器上,例如 Heroku +4. 您要执行从构建环境到远程服务器的 SSH 命令 +5. 您想将文件从构建环境同步到远程服务器 + +如果上述任何事情都响了,那么您很可能需要 SSH 密钥. + +支持最广泛的方法是通过扩展`.gitlab-ci.yml`来将 SSH 密钥注入构建环境,该解决方案可与任何类型的[执行器](https://docs.gitlab.com/runner/executors/) (Docker,shell 等)一起使用. + +## How it works[](#how-it-works "Permalink") + +1. 使用[`ssh-keygen`](https://linux.die.net/man/1/ssh-keygen)在本地创建新的 SSH 密钥对 +2. 将私钥作为[变量](../variables/README.html)添加到您的项目中 +3. 在作业期间运行[`ssh-agent`](https://linux.die.net/man/1/ssh-agent)以加载私钥. +4. 将公用密钥复制到您要访问的服务器上(通常在`~/.ssh/authorized_keys` ),如果要访问私有的 GitLab 存储库,则将其添加为[部署密钥](../../ssh/README.html#deploy-keys) . + +**注意:**除非您启用[调试日志](../variables/README.html#debug-logging)记录,否则私钥将不会显示在作业日志中. 您可能还需要检查[管道](../pipelines/settings.html#visibility-of-pipelines)的[可见性](../pipelines/settings.html#visibility-of-pipelines) . + +## SSH keys when using the Docker executor[](#ssh-keys-when-using-the-docker-executor "Permalink") + +当您的 CI / CD 作业在 Docker 容器中运行(意味着包含环境)并且您想要在私有服务器中部署代码时,您需要一种访问它的方法. 这是 SSH 密钥对派上用场的地方. + +1. 您首先需要创建一个 SSH 密钥对. 有关更多信息,请按照说明[生成 SSH 密钥](../../ssh/README.html#generating-a-new-ssh-key-pair) . **不要**在 SSH 密钥中添加密码,否则`before_script`会提示您输入密码. + +2. 创建一个新[变量](../variables/README.html#gitlab-cicd-environment-variables) . 在" **密钥"中**输入名称`SSH_PRIVATE_KEY`然后在" **值"**字段中粘贴先前创建的*私钥*的内容. + +3. 使用`before_script`操作修改`.gitlab-ci.yml` . 在以下示例中,假定使用基于 Debian 的图像. 根据需要进行编辑: + + ``` + before_script: + ## + ## Install ssh-agent if not already installed, it is required by Docker. + ## (change apt-get to yum if you use an RPM-based image) + ## + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + + ## + ## Run ssh-agent (inside the build environment) + ## + - eval $(ssh-agent -s) + + ## + ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store + ## We're using tr to fix line endings which makes ed25519 keys work + ## without extra base64 encoding. + ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556 + ## + - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - + + ## + ## Create the SSH directory and give it the right permissions + ## + - mkdir -p ~/.ssh + - chmod 700 ~/.ssh + + ## + ## Optionally, if you will be using any Git commands, set the user name and + ## and email. + ## + #- git config --global user.email "user@example.com" + #- git config --global user.name "User name" + ``` + + **注意:** [`before_script`](../yaml/README.html#before_script-and-after_script)可以全局设置或按作业设置. +4. 确保专用服务器的[SSH 主机密钥已验证](#verifying-the-ssh-host-keys) . + +5. 作为最后一步,从添加您在第一步,你想拥有从构建环境中的接入服务创建一个*公共*密钥. 如果要访问私有的 GitLab 存储库,则需要将其添加为[部署密钥](../../ssh/README.html#deploy-keys) . + +而已! 现在,您可以在构建环境中访问私有服务器或存储库. + +## SSH keys when using the Shell executor[](#ssh-keys-when-using-the-shell-executor "Permalink") + +如果您使用的是 Shell 执行程序而不是 Docker,则设置 SSH 密钥会更加容易. + +您可以从安装了 GitLab Runner 的计算机生成 SSH 密钥,并将该密钥用于在该计算机上运行的所有项目. + +1. 首先,登录到运行您的作业的服务器. + +2. 然后,从终端以`gitlab-runner`用户身份登录: + + ``` + sudo su - gitlab-runner + ``` + +3. 按照说明生成 SSH 密钥对,以[生成 SSH 密钥](../../ssh/README.html#generating-a-new-ssh-key-pair) . **不要**在 SSH 密钥中添加密码,否则`before_script`会提示您输入密码. + +4. 作为最后一步,加前面创建要具有从构建环境中的接入服务的一个*公共*密钥. 如果要访问私有的 GitLab 存储库,则需要将其添加为[部署密钥](../../ssh/README.html#deploy-keys) . + +完成后,尝试登录到远程服务器以接受指纹: + +``` +ssh example.com +``` + +要访问 GitLab.com 上的存储库,可以使用`git@gitlab.com` . + +## Verifying the SSH host keys[](#verifying-the-ssh-host-keys "Permalink") + +最好检查私有服务器自己的公用密钥,以确保您不会受到中间人攻击的攻击. 万一发生任何可疑事件,您将注意到它,因为作业将失败(如果公钥不匹配,则 SSH 连接将失败). + +要查找服务器的主机密钥,请从受信任的网络(最好是从私有服务器本身)运行`ssh-keyscan`命令: + +``` +## Use the domain name +ssh-keyscan example.com + +## Or use an IP +ssh-keyscan 1.2.3.4 +``` + +使用`SSH_KNOWN_HOSTS`作为"密钥"创建一个新[变量](../variables/README.html#gitlab-cicd-environment-variables) ,并作为"值"添加`ssh-keyscan`的输出. + +**注意:**如果需要连接到多个服务器,则所有服务器主机密钥都需要收集在变量的**Value**中,每行一个密钥.**提示:**通过在`.gitlab-ci.yml`直接使用变量而不是`ssh-keyscan` ,这样做的好处是,如果主机域名由于某种原因而更改,则不必更改`.gitlab-ci.yml` . 而且,这些值是由您预定义的,这意味着如果主机密钥突然更改,CI / CD 作业将失败,并且您将知道服务器或网络出了点问题. + +现在已经创建了`SSH_KNOWN_HOSTS`变量,除了上面[`.gitlab-ci.yml`](#ssh-keys-when-using-the-docker-executor)的[内容](#ssh-keys-when-using-the-docker-executor)之外,还需要添加以下内容: + +``` +before_script: + ## + ## Assuming you created the SSH_KNOWN_HOSTS variable, uncomment the + ## following two lines. + ## + - echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts + - chmod 644 ~/.ssh/known_hosts + + ## + ## Alternatively, use ssh-keyscan to scan the keys of your private server. + ## Replace example.com with your private server's domain name. Repeat that + ## command if you have more than one server to connect to. + ## + #- ssh-keyscan example.com >> ~/.ssh/known_hosts + #- chmod 644 ~/.ssh/known_hosts + + ## + ## You can optionally disable host key checking. Be aware that by adding that + ## you are susceptible to man-in-the-middle attacks. + ## WARNING: Use this only with the Docker executor, if you use it with shell + ## you will overwrite your user's SSH config. + ## + #- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config' +``` + +## Example project[](#example-project "Permalink") + +为了方便起见,我们建立了一个[示例 SSH 项目](https://gitlab.com/gitlab-examples/ssh-private-key/) ,使用我们的公共[共享](../runners/README.html)运行程序在[GitLab.com](https://gitlab.com)上运行. + +想要破解吗? 只需对其进行分叉,提交并推送您的更改. 稍后,公共跑步者将选择更改并开始工作. \ No newline at end of file diff --git a/_book/docs/205.md b/_book/docs/205.md new file mode 100644 index 0000000000000000000000000000000000000000..f3530272e1b1a92eb24d051f72cc5c677e128450 --- /dev/null +++ b/_book/docs/205.md @@ -0,0 +1,342 @@ +# Migrating from CircleCI + +> 原文:[https://docs.gitlab.com/ee/ci/migration/circleci.html](https://docs.gitlab.com/ee/ci/migration/circleci.html) + +* [`config.yml` vs `gitlab-ci.yml`](#configyml-vs-gitlab-ciyml) + * [Jobs](#jobs) + * [Docker image definition](#docker-image-definition) + * [Workflows](#workflows) + * [Parallel and sequential job execution](#parallel-and-sequential-job-execution) + * [Scheduled run](#scheduled-run) + * [Manual run](#manual-run) + * [Filter job by branch](#filter-job-by-branch) + * [Caching](#caching) +* [Contexts and variables](#contexts-and-variables) +* [Orbs](#orbs) +* [Build environments](#build-environments) + * [Machine and specific build environments](#machine-and-specific-build-environments) + +# Migrating from CircleCI[](#migrating-from-circleci "Permalink") + +如果您当前正在使用 CircleCI,则可以将 CI / CD 管道迁移到[GitLab CI / CD](../introduction/index.html) ,并开始使用其所有强大功能. 查看我们的[CircleCI 与 GitLab](https://about.gitlab.com/devops-tools/circle-ci-vs-gitlab.html)比较,以了解有什么不同. + +在开始迁移之前,我们已经收集了一些您可能会觉得有用的资源. + +[快速入门指南](../quick_start/README.html)很好地概述了 GitLab CI / CD 的工作方式. 您可能还对[Auto DevOps](../../topics/autodevops/index.html)感兴趣,可以将其用于构建,测试和部署应用程序,而几乎不需要或根本不需要进行任何配置. + +对于高级 CI / CD 团队, [自定义项目模板](../../user/admin_area/custom_project_templates.html)可以启用管道配置的重用. + +如果您有未在此处回答的问题, [GitLab 社区论坛](https://forum.gitlab.com/)将是一个很好的资源. + +## `config.yml` vs `gitlab-ci.yml`[](#configyml-vs-gitlab-ciyml "Permalink") + +CircleCI 的`config.yml`配置文件定义了脚本,作业和工作流程(在 GitLab 中称为"阶段"). 在 GitLab 中,对存储库根目录中的`.gitlab-ci.yml`文件使用类似的方法. + +### Jobs[](#jobs "Permalink") + +在 CircleCI 中,作业是执行特定任务的步骤的集合. 在 GitLab 中, [作业](../yaml/README.html#introduction)也是配置文件中的基本元素. 在 GitLab CI / CD 中,不需要`checkout`参数,因为系统会自动获取存储库. + +CircleCI 示例作业定义: + +``` +jobs: + job1: + steps: + - checkout + - run: "execute-script-for-job1" +``` + +GitLab CI / CD 中相同作业定义的示例: + +``` +job1: + script: "execute-script-for-job1" +``` + +### Docker image definition[](#docker-image-definition "Permalink") + +CircleCI 在作业级别定义图像,GitLab CI / CD 也支持该图像. 此外,GitLab CI / CD 支持全局设置此设置,以供所有未定义`image`作业使用. + +CircleCI 示例图像定义: + +``` +jobs: + job1: + docker: + - image: ruby:2.6 +``` + +Example of the same image definition in GitLab CI/CD: + +``` +job1: + image: ruby:2.6 +``` + +### Workflows[](#workflows "Permalink") + +CircleCI 确定具有`workflows`作业的运行顺序. 这也可用于确定并发,顺序,计划或手动运行. GitLab CI / CD 中的等效功能称为[stage](../yaml/README.html#stages) . 同一阶段的作业并行运行,并且仅在先前阶段完成后才运行. 默认情况下,当作业失败时,将跳过下一阶段的执行,但是即使[在](../yaml/README.html#allow_failure)作业失败之后,也可以继续执行下一阶段. + +有关可使用的不同类型的管道的指南,请参见["管道体系结构概述](../pipelines/pipeline_architectures.html) ". 可以定制管道来满足您的需求,例如大型复杂项目或具有独立定义组件的 monorepo. + +#### Parallel and sequential job execution[](#parallel-and-sequential-job-execution "Permalink") + +以下示例显示了作业如何并行或顺序运行: + +1. `job1`和`job2`并行运行(在 GitLab CI / CD 的`build`阶段). +2. 仅在`job1`和`job2`成功完成之后(在`test`阶段), `job1` `job3`运行. +3. 仅在`job3`成功完成之后(在`deploy`阶段), `job3` `job4`运行. + +CircleCI `workflows`示例: + +``` +version: 2 +jobs: + job1: + steps: + - checkout + - run: make build dependencies + job2: + steps: + - run: make build artifacts + job3: + steps: + - run: make test + job4: + steps: + - run: make deploy + +workflows: + version: 2 + jobs: + - job1 + - job2 + - job3: + requires: + - job1 + - job2 + - job4: + requires: + - job3 +``` + +与 GitLab CI / CD 中的`stages`相同的工作流程示例: + +``` +stages: + - build + - test + - deploy + +job 1: + stage: build + script: make build dependencies + +job 2: + stage: build + script: make build artifacts + +job3: + stage: test + script: make test + +job4: + stage: deploy + script: make deploy +``` + +#### Scheduled run[](#scheduled-run "Permalink") + +GitLab CI / CD 具有易于使用的 UI 来[调度管道](../pipelines/schedules.html) . 同样,可以使用[规则](../yaml/README.html#rules)来确定是否应将作业包括在计划的管道中或从计划的管道中排除. + +计划的工作流程的 CircleCI 示例: + +``` +commit-workflow: + jobs: + - build +scheduled-workflow: + triggers: + - schedule: + cron: "0 1 * * *" + filters: + branches: + only: try-schedule-workflow + jobs: + - build +``` + +使用 GitLab CI / CD 中的[`rules`](../yaml/README.html#rules)使用同一调度管道的示例: + +``` +job1: + script: + - make build + rules: + - if: '$CI_PIPELINE_SOURCE == "schedule" && $CI_COMMIT_REF_NAME == "try-schedule-workflow"' +``` + +保存管道配置后,您可以在[GitLab UI 中](../pipelines/schedules.html#configuring-pipeline-schedules)配置 cron 计划,并且还可以在 UI 中启用或禁用计划. + +#### Manual run[](#manual-run "Permalink") + +手动工作流程的 CircleCI 示例: + +``` +release-branch-workflow: + jobs: + - build + - testing: + requires: + - build + - deploy: + type: approval + requires: + - testing +``` + +使用[`when: manual`](../yaml/README.html#whenmanual) GitLab CI / CD 中的[`when: manual`](../yaml/README.html#whenmanual)的相同工作流程示例: + +``` +deploy_prod: + stage: deploy + script: + - echo "Deploy to production server" + when: manual +``` + +### Filter job by branch[](#filter-job-by-branch "Permalink") + +[规则](../yaml/README.html#rules)是一种机制,用于确定作业是否将针对特定分支运行. + +按分支过滤的作业的 CircleCI 示例: + +``` +jobs: + deploy: + branches: + only: + - master + - /rc-.*/ +``` + +在 GitLab CI / CD 中使用`rules`的相同工作流程示例: + +``` +deploy_prod: + stage: deploy + script: + - echo "Deploy to production server" + rules: + - if: '$CI_COMMIT_BRANCH == "master"' +``` + +### Caching[](#caching "Permalink") + +GitLab 提供了一种缓存机制,可通过重用以前下载的依赖项来加快作业的构建时间. 重要的是要了解[缓存和工件](../caching/index.html#cache-vs-artifacts)之间的区别,以充分利用这些功能. + +使用缓存的作业的 CircleCI 示例: + +``` +jobs: + job1: + steps: + - restore_cache: + key: source-v1-< .Revision > + - checkout + - run: npm install + - save_cache: + key: source-v1-< .Revision > + paths: + - "node_modules" +``` + +在 GitLab CI / CD 中使用`cache`的同一管道的示例: + +``` +image: node:latest + +# Cache modules in between jobs +cache: + key: $CI_COMMIT_REF_SLUG + paths: + - .npm/ + +before_script: + - npm ci --cache .npm --prefer-offline + +test_async: + script: + - node ./specs/start.js ./specs/async.spec.js +``` + +## Contexts and variables[](#contexts-and-variables "Permalink") + +CircleCI 提供了[上下文,](https://s0circleci0com.icopy.site/docs/2.0/contexts/)以跨项目管道安全地传递环境变量. 在 GitLab 中,可以创建一个[组](../../user/group/index.html)来将相关项目组装在一起. 在组级别, [变量](../variables/README.html#group-level-environment-variables)可以存储在各个项目之外,并安全地传递到跨多个项目的管道中. + +## Orbs[](#orbs "Permalink") + +有两个 GitLab 问题需要解决 CircleCI Orb,以及 GitLab 如何实现类似功能. + +* [https://gitlab.com/gitlab-com/Product/-/issues/1151](https://gitlab.com/gitlab-com/Product/-/issues/1151) +* [https://gitlab.com/gitlab-org/gitlab/-/issues/195173](https://gitlab.com/gitlab-org/gitlab/-/issues/195173) + +## Build environments[](#build-environments "Permalink") + +CircleCI 为`executors`提供`executors`特定工作的基础技术. 在 GitLab 中,这是由[Runners](https://docs.gitlab.com/runner/)完成的. + +支持以下环境: + +自我管理的跑步者: + +* Linux +* Windows +* macOS + +GitLab.com 共享跑步者: + +* Linux +* Windows +* [Planned: macOS](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/5720) + +### Machine and specific build environments[](#machine-and-specific-build-environments "Permalink") + +通过告诉 GitLab 哪些 Runners 应该运行作业, [标签](../yaml/README.html#tags)可以用于在不同平台上运行作业. + +在特定环境中运行的作业的 CircleCI 示例: + +``` +jobs: + ubuntuJob: + machine: + image: ubuntu-1604:201903-01 + steps: + - checkout + - run: echo "Hello, $USER!" + osxJob: + macos: + xcode: 11.3.0 + steps: + - checkout + - run: echo "Hello, $USER!" +``` + +在 GitLab CI / CD 中使用`tags`进行同一作业的示例: + +``` +windows job: + stage: + - build + tags: + - windows + script: + - echo Hello, %USERNAME%! + +osx job: + stage: + - build + tags: + - osx + script: + - echo "Hello, $USER!" +``` \ No newline at end of file diff --git a/_book/docs/206.md b/_book/docs/206.md new file mode 100644 index 0000000000000000000000000000000000000000..0957eba2ed2600c12cfd52198be7e90ac31dd6a2 --- /dev/null +++ b/_book/docs/206.md @@ -0,0 +1,266 @@ +# Migrating from Jenkins + +> 原文:[https://docs.gitlab.com/ee/ci/jenkins/](https://docs.gitlab.com/ee/ci/jenkins/) + +* [Managing the organizational transition](#managing-the-organizational-transition) +* [JenkinsFile Wrapper](#jenkinsfile-wrapper) +* [Important product differences](#important-product-differences) +* [Agents vs. Runners](#agents-vs-runners) +* [Groovy vs. YAML](#groovy-vs-yaml) +* [Artifact publishing](#artifact-publishing) +* [Integrated features](#integrated-features) + * [Templates](#templates) +* [Converting a declarative Jenkinsfile](#converting-a-declarative-jenkinsfile) + * [Sections](#sections) + * [`agent`](#agent) + * [`post`](#post) + * [`stages`](#stages) + * [`steps`](#steps) + * [Directives](#directives) + * [`environment`](#environment) + * [`options`](#options) + * [`parameters`](#parameters) + * [`triggers` / `cron`](#triggers--cron) + * [`tools`](#tools) + * [`input`](#input) + * [`when`](#when) + +# Migrating from Jenkins[](#migrating-from-jenkins "Permalink") + +许多 GitLab 用户已经从 Jenkins 成功迁移到 GitLab CI / CD. 为了使您入门时更容易,我们在这里收集了一些您可能会在使用之前可能会发现有用的资源.请将此页面视为" Jenkins 用户的 GitLab CI / CD"指南. + +建议的步骤的以下列表是在观察能够快速完成此迁移的组织之后创建的: + +1. 首先阅读《 GitLab CI / CD [快速入门指南》](../quick_start/README.html)和[重要的产品差异](#important-product-differences) . +2. 了解[管理组织过渡](#managing-the-organizational-transition)的重要性. +3. [将 Runners 添加](../runners/README.html)到您的 GitLab 实例. +4. 教育开发人员并使他们能够在他们的项目中独立执行以下步骤: + 1. 查看《 [快速入门指南](../quick_start/README.html)和[管道配置参考》](../yaml/README.html) . + 2. 使用[Jenkins 包装器](#jenkinsfile-wrapper)暂时维护脆弱的 Jenkins 作业. + 3. 迁移构建和 CI 作业并将其配置为直接在合并请求中显示结果. 他们可以使用[Auto DevOps](../../topics/autodevops/index.html)作为起点,并[根据](../../topics/autodevops/customize.html)需要[自定义](../../topics/autodevops/customize.html)或[分解](../../topics/autodevops/customize.html#using-components-of-auto-devops)配置. + 4. 添加[评论应用](../review_apps/index.html) . + 5. 使用[云部署模板](../cloud_deployment/index.html) ,添加[环境](../environments/index.html)和[部署板](../..//user/project/deploy_boards.html)来迁移部署作业. + 6. 使用 Jenkins 包装器解开仍在运行的所有作业的包装. +5. 盘点所有常见的 CI / CD 作业定义,然后为其创建和共享[模板](#templates) . + +有关如何将 Jenkins 管道转换为 GitLab CI / CD 管道的示例,或如何使用 Auto DevOps 自动测试代码的示例,请观看[从 Jenkins 迁移到 GitLab 的](https://www.youtube.com/watch?v=RlEVGOpYF5Y)视频. + +否则,请继续阅读以获取重要信息,这些信息将帮助您取得成功. 欢迎来到 GitLab! + +如果您有未在此处回答的问题, [GitLab 社区论坛](https://forum.gitlab.com/)将是一个很好的资源. + +## Managing the organizational transition[](#managing-the-organizational-transition "Permalink") + +从詹金斯过渡到 GitLab 的一个重要部分是随之而来的文化和组织变革,并成功地对其进行了管理. 我们发现了一些有助于解决问题的方法: + +* 为您的迁移目标设定并传达清晰的愿景有助于您的用户理解为什么值得付出努力. 当工作完成时,该值将很明显,但是在进行过程中,人们也需要意识到. +* 有关领导团队的赞助和配合有助于上述观点. +* 花时间对用户进行不同的教育,与他们共享此文档等等,将有助于确保您成功. +* 寻找顺序或延迟部分迁移的方法可能会很有帮助,但是您不想让事物长时间处于未迁移(或部分迁移)状态. 要获得 GitLab 的所有好处,仅将现有的 Jenkins 设置转移到原样上(包括任何当前问题)是不够的. 您需要利用 GitLab 提供的改进,这最终需要(最终)更新您的实现. + +## JenkinsFile Wrapper[](#jenkinsfile-wrapper "Permalink") + +我们正在构建一个[JenkinsFile 包装器](https://gitlab.com/gitlab-org/jfr-container-builder/) ,它将允许您在 GitLab 作业(包括插件)中运行完整的 Jenkins 实例. 通过让您将不太紧急的管道的迁移延迟一段时间,可以帮助简化过渡过程. + +如果您有兴趣帮助 GitLab 测试包装器,请加入我们的[公共测试问题](https://gitlab.com/gitlab-org/gitlab/-/issues/215675)以获取说明并提供您的反馈. + +## Important product differences[](#important-product-differences "Permalink") + +值得一提的产品之间存在一些高级差异: + +* 使用 GitLab,您不需要根`pipeline`关键字即可包装所有内容. +* 管道触发和[触发其他管道的](../yaml/README.html#trigger)方式与詹金斯不同. 可以触发 GitLab 管道: + + * 在推 + * on [schedule](../pipelines/schedules.html) + * 从[GitLab UI](../pipelines/index.html#run-a-pipeline-manually) + * by [API call](../triggers/README.html) + * by [webhook](../triggers/README.html#triggering-a-pipeline-from-a-webhook) + * by [ChatOps](../chatops/README.html) +* 您可以使用[`rules`语法](../yaml/README.html#rules)来控制在哪种情况下运行哪些作业,具体取决于触发方式. +* GitLab [管道调度概念](../pipelines/schedules.html)也与 Jenkins 不同. +* 您可以使用[`include`关键字](../yaml/README.html#include)和[模板](#templates)重复使用管道配置. 您的模板可以保存在中央存储库中(具有不同的权限),然后任何项目都可以使用它们. 这个中央项目也可以包含脚本或其他可重用的代码. +* You can also use the [`extends` keyword](../yaml/README.html#extends) to reuse configuration within a single pipeline configuration. +* 单个阶段中的所有作业始终并行运行,并且所有阶段均按顺序运行. 我们计划通过我们的有[向无环图](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47063)功能允许某些作业根据需要中断此排序. +* [`parallel`](../yaml/README.html#parallel)关键字可以自动并行化任务,例如支持并行化的测试. +* 通常,单个阶段中的所有作业并行运行,并且所有阶段按顺序运行. 有不同的[管道体系结构](../pipelines/pipeline_architectures.html)允许您更改此行为. +* 建议使用新[`rules`语法](../yaml/README.html#rules)控制何时运行不同作业. 它比`only/except`语法更强大. +* 一个重要的区别是,作业彼此独立运行,并且每个作业都具有全新的环境. 使用[`artifacts`](../yaml/README.html#artifacts)和[`dependencies`](../yaml/README.html#dependencies)关键字控制作业之间传递工件. 完成后,计划的[工作区](https://gitlab.com/gitlab-org/gitlab/-/issues/29265)功能将使您能够更轻松地在串行作业之间持久保留公共工作区. +* `.gitlab-ci.yml`文件已签入到存储库的根目录,非常类似于 Jenkinsfile,但采用 YAML 格式(请参阅[完整参考](../yaml/README.html) )而不是 Groovy DSL. 它与声明性 Jenkinsfile 格式最相似. +* 手动批准或登机口可以设置为以下[`when:manual`作业](../yaml/README.html#whenmanual) . 这些还可以利用[`protected environments`](../yaml/README.html#protecting-manual-jobs-premium)来控制谁可以批准它们. +* GitLab 带有[容器注册表](../../user/packages/container_registry/index.html) ,我们建议使用容器映像来设置您的构建环境. 例如,设置一个管道来构建您自己的构建环境,并将其发布到容器注册表. 然后,让您的管道使用此方法,而不是每个管道都使用它们自己的环境,这将变得更慢,并且一致性可能会降低. 我们有大量有关[如何使用 Container Registry 的](../../user/packages/container_registry/index.html)文档. +* 中央实用程序存储库是放置各种计划作业或其他功能类似于实用程序的手动作业的好地方. 詹金斯的装置中往往有一些. + +## Agents vs. Runners[](#agents-vs-runners "Permalink") + +Jenkins 代理和 GitLab Runners 都是运行作业的主机. 要转换 Jenkins 代理,只需将其卸载,然后[安装并注册 Runner](../runners/README.html) . 运行程序不需要太多的开销,因此您可以像使用的 Jenkins 代理一样调整它们的大小. + +与代理相比,Runners 的工作方式存在一些重要差异: + +* 跑步者可以设置为[在实例之间共享,也可以在组级别添加,也可以在项目级别设置](../runners/README.html#types-of-runners) . 他们将从您自动定义的范围中自动选择作业. +* 您还可以[使用标签](../runners/README.html#use-tags-to-limit-the-number-of-jobs-using-the-runner)进行更精细的控制,并将跑步者与特定工作相关联. 例如,您可以将标签用于需要专用,功能更强大或特定硬件的作业. +* GitLab 具有[针对](https://docs.gitlab.com/runner/configuration/autoscale.html) Runner 的[自动缩放功能](https://docs.gitlab.com/runner/configuration/autoscale.html) ,可让您将其配置为根据需要进行设置,并在不进行缩放时进行缩放. 这类似于詹金斯中的临时代理. + +如果您使用的是`gitlab.com` ,则可以利用我们[共享的 Runner](../../user/gitlab_com/index.html#shared-runners) `gitlab.com`来运行作业,而无需置备自己的 Runners. 我们正在研究使它们也[可用于自我管理实例](https://gitlab.com/groups/gitlab-org/-/epics/835) . + +## Groovy vs. YAML[](#groovy-vs-yaml "Permalink") + +Jenkins 管道基于[Groovy](https://s0groovy-lang0org.icopy.site/) ,因此管道规范以代码形式编写. GitLab 的工作方式略有不同,我们使用结构更高级的[YAML](https://yaml.org/)格式,该格式将脚本元素放置在`script:`内部`script:`块与管道规范本身分开. + +这是 GitLab 的优势,因为它有助于使学习曲线更简单地启动和运行,并且避免了一些不受限制的复杂性问题,这些问题会使您的 Jenkinsfile 难以理解和管理. + +就是说,我们当然仍然重视 DRY(不要重复自己)的原则,并希望确保您的工作行为可以被一次编码并根据需要进行应用. 您可以使用`extends:`语法[在您的作业中重用配置](../yaml/README.html#extends) , `include:`可用于在不同项目的管道中[重用管道配置](../yaml/README.html#include) : + +``` +.in-docker: + tags: + - docker + image: alpine + +rspec: + extends: + - .in-docker + script: + - rake rspec +``` + +## Artifact publishing[](#artifact-publishing "Permalink") + +工件的工作方式可能与您与詹金斯一起使用时有所不同. 在 GitLab 中,任何作业都可以使用`artifacts:`关键字定义一组要保存的`artifacts:` . 可以将其配置为指向一个文件或一组文件,然后可以在每个作业之间将其持久化. 阅读更多关于我们详细的[工件文档的信息](../pipelines/job_artifacts.html) : + +``` +pdf: + script: xelatex mycv.tex + artifacts: + paths: + - ./mycv.pdf + - ./output/ + expire_in: 1 week +``` + +此外,我们还具有包管理功能,例如可以利用的内置容器,NPM 和 Maven 注册表. 您可以在[我们的文档](../../README.html#package)的[包装部分中](../../README.html#package)查看打包功能的完整列表(包括指向文档的链接). + +## Integrated features[](#integrated-features "Permalink") + +在 Jenkins 中,您可能曾经使用插件来获得代码质量,单元测试,安全扫描等功能,但 GitLab 充分利用了我们连接的生态系统,将这些结果自动提取到您的合并请求,管道详细信息页面和其他位置. 您可能会发现实际上不需要配置任何内容即可显示这些内容. + +如果它们无法正常工作,或者您想查看可用的[功能](../README.html#feature-set) ,则我们的[CI 功能索引](../README.html#feature-set)将提供捆绑功能的完整列表,并提供每个功能的文档链接. + +### Templates[](#templates "Permalink") + +对于高级 CI / CD 团队,项目模板可以启用管道配置的重用,并鼓励内部采购. + +In self-managed GitLab instances, you can build an [Instance Template Repository](../../user/admin_area/settings/instance_template_repository.html). Development teams across the whole organization can select templates from a dropdown menu. A group administrator is able to set a group to use as the source for the [custom project templates](../../user/admin_area/custom_project_templates.html), which can be used by all projects in the group. An instance administrator can set a group as the source for [instance project templates](../../user/group/custom_project_templates.html), which can be used by projects in that instance. + +## Converting a declarative Jenkinsfile[](#converting-a-declarative-jenkinsfile "Permalink") + +声明性 Jenkinsfile 包含用于控制管道行为的" Sections"和" Directives". GitLab 中有所有这些的等效项,我们在下面对此进行了介绍. + +本节基于[Jenkinsfile 语法文档](https://www.jenkins.io/doc/book/pipeline/syntax/) ,旨在将其中的概念映射到 GitLab 中的概念. + +### Sections[](#sections "Permalink") + +#### `agent`[](#agent "Permalink") + +代理部分用于定义如何执行管道. 对于 GitLab,我们使用[GitLab Runner](../runners/README.html)来提供此功能. 您可以在 Kubernetes 或任何主机上配置自己的运行程序,也可以利用我们的共享运行程序队列(请注意,共享运行程序队列仅适用于 GitLab.com 用户.)以上链接将带您进入说明文档的文档如何快速起步和运行. 我们还支持使用[标签](../runners/README.html#use-tags-to-limit-the-number-of-jobs-using-the-runner)将不同的作业定向到不同的 Runner(执行代理). + +`agent`部分还允许您定义应使用哪些 Docker 映像执行,而我们使用[`image`](../yaml/README.html#image)关键字. 该`image`可以设置在单个作业或顶层,在这种情况下,它将应用于管道中的所有作业: + +``` +my_job: + image: alpine + ... +``` + +#### `post`[](#post "Permalink") + +`post`部分定义了应在管道末尾执行的操作. GitLab 也通过阶段的使用来支持这一点. 您可以按以下方式定义阶段,分配给`before_pipeline`或`after_pipeline`阶段的所有作业都将按预期运行. 您可以根据需要将这些阶段称为: + +``` +stages: + - before_pipeline + - build + - test + - deploy + - after_pipeline +``` + +可以通过[`before_script`和`after_script`关键字](../yaml/README.html#before_script-and-after_script)设置要在任何作业之前和之后执行的步骤: + +``` +default: + before_script: + - echo "I run before any jobs starts in the entire pipeline, and can be responsible for setting up the environment." +``` + +#### `stages`[](#stages "Permalink") + +GitLab CI / CD 也可以让您定义阶段,但是可以自由配置一些. GitLab [`stages`关键字](../yaml/README.html#stages)是一个顶级设置,它枚举了阶段列表,但是您不需要在" `stages`部分下嵌套单个作业. 通过使用[`stage:`关键字,](../yaml/README.html#stage)可以使`.gitlab-ci.yml`定义的任何作业成为任何阶段的一部分. + +请注意,除非另有说明,否则每个管道都以`build` , `test`和`deploy`阶段实例化,并按该顺序运行. 未定义`stage`作业默认情况下放置在`test`阶段. 当然,引用阶段的每个作业都必须引用管道配置中存在的阶段. + +``` +stages: + - build + - test + - deploy + +my_job: + stage: build + ... +``` + +#### `steps`[](#steps "Permalink") + +The `steps` section is equivalent to the [`script` section](../yaml/README.html#script) of an individual job. This is a simple YAML array with each line representing an individual command to be run: + +``` +my_job: + script: + - echo "hello! the current time is:" + - time + ... +``` + +### Directives[](#directives "Permalink") + +#### `environment`[](#environment "Permalink") + +在 GitLab 中,我们使用[`variables`关键字](../yaml/README.html#variables)在运行时定义不同的变量. 这些也可以通过 CI / CD 设置下的 GitLab UI 进行设置. 另请参阅我们[有关变量](../variables/README.html)的[一般文档](../variables/README.html) ,包括有关[受保护变量](../variables/README.html#protect-a-custom-variable)的部分,该部分可用于将对某些变量的访问限制为某些环境或运行程序: + +``` +variables: + POSTGRES_USER: user + POSTGRES_PASSWORD: testing_password +``` + +#### `options`[](#options "Permalink") + +这里,存在与所讨论的对象本身相关联的用于不同事物的选项. 例如,与作业相关的选项是相对于作业本身定义的. 如果您正在寻找某个选项,则应该可以通过搜索[完整的配置参考](../yaml/README.html)页面来找到它的位置. + +#### `parameters`[](#parameters "Permalink") + +GitLab 不需要您定义在开始手动作业时希望可用的变量. 用户可以提供他们喜欢的任何变量. + +#### `triggers` / `cron`[](#triggers--cron "Permalink") + +Because GitLab is integrated tightly with Git, SCM polling options for triggers are not needed. We support an easy to use [syntax for scheduling pipelines](../pipelines/schedules.html). + +#### `tools`[](#tools "Permalink") + +GitLab 不支持单独的`tools`指令. 我们的最佳实践建议是使用预构建的容器映像,该映像可以缓存,并且可以构建为包含管道所需的工具. 可以设置管道以根据需要自动构建这些映像,并将它们部署到[容器注册表中](../../user/packages/container_registry/index.html) . + +如果您没有在 Docker / Kubernetes 上使用容器映像,例如在 Mac 或 FreeBSD 上,则`shell`执行程序确实需要您预先设置环境或作为作业的一部分. 您可以创建一个`before_script`动作来为您处理. + +#### `input`[](#input "Permalink") + +与`parameters`关键字类似,这是不需要的,因为始终可以为运行时变量条目提供手动作业. + +#### `when`[](#when "Permalink") + +GitLab 确实支持[`when`关键字](../yaml/README.html#when) ,用于指示在(或尽管发生)故障的情况下应在何时运行作业,但是大多数用于控制管道的逻辑都可以在我们功能非常强大的[`only/except`规则系统中找到](../yaml/README.html#onlyexcept-basic) (另请参见[高级语法](../yaml/README.html#onlyexcept-basic) ): + +``` +my_job: + only: [branches] +``` \ No newline at end of file diff --git a/_book/docs/207.md b/_book/docs/207.md new file mode 100644 index 0000000000000000000000000000000000000000..c5403aeb4b4c621ef2265ead1b3d413db4471a6c --- /dev/null +++ b/_book/docs/207.md @@ -0,0 +1,302 @@ +# Auto DevOps + +> 原文:[https://docs.gitlab.com/ee/topics/autodevops/](https://docs.gitlab.com/ee/topics/autodevops/) + +* [Overview](#overview) +* [Enabled by default](#enabled-by-default) +* [Quick start](#quick-start) +* [Comparison to application platforms and PaaS](#comparison-to-application-platforms-and-paas) +* [Features](#features) +* [Auto DevOps base domain](#auto-devops-base-domain) +* [Enabling/Disabling Auto DevOps](#enablingdisabling-auto-devops) + * [At the project level](#at-the-project-level) + * [At the group level](#at-the-group-level) + * [At the instance level (Administrators only)](#at-the-instance-level-administrators-only) + * [Deployment strategy](#deployment-strategy) +* [Using multiple Kubernetes clusters](#using-multiple-kubernetes-clusters-premium) +* [Limitations](#limitations) + * [Private registry support](#private-registry-support) + * [Installing Helm behind a proxy](#installing-helm-behind-a-proxy) +* [Troubleshooting](#troubleshooting) + * [Unable to select a buildpack](#unable-to-select-a-buildpack) + * [Pipeline that extends Auto DevOps with only / except fails](#pipeline-that-extends-auto-devops-with-only--except-fails) + * [Failure to create a Kubernetes namespace](#failure-to-create-a-kubernetes-namespace) + * [Detected an existing PostgreSQL database](#detected-an-existing-postgresql-database) +* [Development guides](#development-guides) + +# Auto DevOps[](#auto-devops "Permalink") + +版本历史 + +* 在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/37115) . +* 通常在 GitLab 11.0 上可用. + +Auto DevOps provides pre-defined CI/CD configuration allowing you to automatically detect, build, test, deploy, and monitor your applications. Leveraging CI/CD best practices and tools, Auto DevOps aims to simplify the setup and execution of a mature and modern software development lifecycle. + +## Overview[](#overview "Permalink") + +您可以花费大量精力来设置构建,部署和监视项目所需的工作流和流程. 当您的公司要维护数百个(甚至数千个)项目时,情况会变得更糟. 随着新项目的不断启动,整个软件开发过程变得难以管理. + +Auto DevOps 通过自动检测以最小的配置测试,构建,打包,部署和监视每个项目所需的所有依赖关系和语言技术,为您提供了无缝的软件开发过程. 自动化可确保项目之间的一致性,流程的无缝管理以及更快地创建新项目:推送代码,而 GitLab 则完成其余工作,从而提高了生产率和效率. + +有关 Auto DevOps 的介绍, [请在 GitLab 11.0 中](https://youtu.be/0Tc0YYBxqi4)观看[AutoDevOps](https://youtu.be/0Tc0YYBxqi4) . + +有关要求,请参阅[Auto DevOps 要求以](requirements.html)获取更多信息. + +## Enabled by default[](#enabled-by-default "Permalink") + +在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41729) . + +默认情况下,所有项目都会启用 Auto DevOps,并尝试在每个项目的所有管道中运行. 实例管理员可以在[Auto DevOps 设置中](../../user/admin_area/settings/continuous_integration.html#auto-devops-core-only)启用或禁用此默认[设置](../../user/admin_area/settings/continuous_integration.html#auto-devops-core-only) . 如果尚未为项目显式启用,Auto DevOps 会在各个项目的第一个管道故障时自动将其禁用. + +从[GitLab 12.7 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/26655) ,仅当存在[`Dockerfile`或匹配的 buildpack](stages.html#auto-build)时,Auto DevOps 才会在管道上自动运行. + +如果项目中存在[CI / CD 配置文件](../../ci/yaml/README.html) ,则无论是否启用了 Auto DevOps,它都将继续使用. + +## Quick start[](#quick-start "Permalink") + +如果您使用的是 GitLab.com,请参阅[快速入门指南](quick_start_guide.html) ,以使用 GitLab.com 和 Google Kubernetes Engine(GKE)上的 Kubernetes 集群设置 Auto DevOps. + +如果使用 GitLab 的自我管理实例,则必须先配置[Google OAuth2 OmniAuth Provider,](../../integration/google.html)然后才能在 GKE 上配置集群. 配置提供程序后,您可以按照[快速入门指南中](quick_start_guide.html)的步骤进行入门. + +In [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/208132) and later, it is possible to leverage Auto DevOps to deploy to [AWS ECS](requirements.html#auto-devops-requirements-for-amazon-ecs). + +## Comparison to application platforms and PaaS[](#comparison-to-application-platforms-and-paas "Permalink") + +Auto DevOps provides features often included in an application platform or a Platform as a Service (PaaS). It takes inspiration from the innovative work done by [Heroku](https://www.heroku.com/) and goes beyond it in multiple ways: + +* Auto DevOps 可与任何 Kubernetes 集群一起使用; 您不仅限于在 GitLab 的基础架构上运行. (请注意,许多功能在没有 Kubernetes 的情况下也可以使用). +* 没有额外的费用(基础设施费用没有加价),您可以在任何公共云(例如[Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/) )上使用托管的 Kubernetes 群集或容器即服务. +* Auto DevOps 具有更多功能,包括安全测试,性能测试和代码质量测试. +* Auto DevOps 提供增量的毕业路径. 如果需要高级自定义,则可以开始修改模板,而无需在完全不同的平台上重新开始. 查看[定制](customize.html)文档以获取更多信息. + +## Features[](#features "Permalink") + +Auto DevOps 由一组[阶段组成](stages.html) ,以简单,自动的方式为您的项目带来了这些最佳实践: + +1. [Auto Build](stages.html#auto-build) +2. [Auto Test](stages.html#auto-test) +3. [Auto Code Quality](stages.html#auto-code-quality-starter) +4. [Auto SAST (Static Application Security Testing)](stages.html#auto-sast-ultimate) +5. [Auto Secret Detection](stages.html#auto-secret-detection-ultimate) +6. [Auto Dependency Scanning](stages.html#auto-dependency-scanning-ultimate) +7. [Auto License Compliance](stages.html#auto-license-compliance-ultimate) +8. [Auto Container Scanning](stages.html#auto-container-scanning-ultimate) +9. [Auto Review Apps](stages.html#auto-review-apps) +10. [Auto DAST (Dynamic Application Security Testing)](stages.html#auto-dast-ultimate) +11. [Auto Deploy](stages.html#auto-deploy) +12. [Auto Browser Performance Testing](stages.html#auto-browser-performance-testing-premium) +13. [Auto Monitoring](stages.html#auto-monitoring) + +由于 Auto DevOps 依赖于许多不同的组件,因此您应该具有以下基本知识: + +* [Kubernetes](https://kubernetes.io/docs/home/) +* [Helm](https://helm.sh/docs/) +* [Docker](https://s0docs0docker0com.icopy.site) +* [GitLab Runner](https://docs.gitlab.com/runner/) +* [Prometheus](https://s0prometheus0io.icopy.site/docs/introduction/overview/) + +Auto DevOps 为所有阶段提供了出色的默认设置. 但是,您可以[根据](customize.html)需要[自定义](customize.html)几乎所有内容. + +有关创建 Auto DevOps 的概述,请阅读[本博客文章中的](https://about.gitlab.com/blog/2017/06/29/whats-next-for-gitlab-ci/)更多[信息](https://about.gitlab.com/blog/2017/06/29/whats-next-for-gitlab-ci/) . + +**注意** Kubernetes 集群可以[在没有](../../user/project/clusters/index.html) Auto DevOps 的[情况下使用](../../user/project/clusters/index.html) . + +## Auto DevOps base domain[](#auto-devops-base-domain "Permalink") + +必须使用 Auto DevOps 基本域才能使用[Auto Review Apps](stages.html#auto-review-apps) , [Auto Deploy](stages.html#auto-deploy)和[Auto Monitoring](stages.html#auto-monitoring) . 您可以在以下任意位置定义基本域: + +* 在集群的设置下(对于实例, [项目](../../user/project/clusters/index.html#base-domain)还是[组)](../../user/group/clusters/index.html#base-domain) +* 或在项目级别作为变量: `KUBE_INGRESS_BASE_DOMAIN` +* 或在组级别作为变量: `KUBE_INGRESS_BASE_DOMAIN` +* 或作为实例范围的后备 **持续集成和交付**部分下的**管理区域>设置** + +基本域变量`KUBE_INGRESS_BASE_DOMAIN`与其他环境[变量](../../ci/variables/README.html#priority-of-environment-variables)遵循相同的优先级顺序. 如果未设置 CI / CD 变量,并且群集设置为空,则在设置实例范围的**Auto DevOps 域**设置时将使用该设置. + +**提示:**如果您将[GitLab 托管应用程序用于 Ingress](../../user/clusters/applications.html#ingress) ,则应自动为您配置 URL 端点. 您所要做的就是将其值用于`KUBE_INGRESS_BASE_DOMAIN`变量.**注:** `AUTO_DEVOPS_DOMAIN`被[弃用 GitLab 11.8](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52363) ,取而代之的`KUBE_INGRESS_BASE_DOMAIN` ,并在除去[GitLab 12.0](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/56959) . + +Auto DevOps 需要与基础域匹配的通配符 DNS A 记录. 对于`example.com`的基本域,您需要一个 DNS 条目,例如: + +``` +*.example.com 3600 A 1.2.3.4 +``` + +在这种情况下,已部署的应用程序是从`example.com` ,而`1.2.3.4`是负载均衡器的 IP 地址. 通常为 NGINX( [请参阅要求](#requirements) ). 设置 DNS 记录不在本文档的讨论范围内. 请与您的 DNS 提供商联系以获取信息. + +另外,您可以使用免费的公共服务,例如[nip.io](https://nip.io) ,无需任何配置即可提供自动通配符 DNS. 对于[nip.io](https://nip.io) ,将 Auto DevOps 基本域设置为`1.2.3.4.nip.io` + +完成设置后,所有请求都将到达负载均衡器,该负载均衡器会将请求路由到运行您的应用程序的 Kubernetes Pod. + +## Enabling/Disabling Auto DevOps[](#enablingdisabling-auto-devops "Permalink") + +首次使用 Auto DevOps 时,请查看[要求,](#requirements)以确保可以充分利用 Auto DevOps 的所有必需组件. 初学者应遵循[快速入门指南](quick_start_guide.html) . + +GitLab.com 用户只能在项目级别启用或禁用 Auto DevOps. 自我管理的用户可以在项目,组或实例级别启用或禁用 Auto DevOps. + +### At the project level[](#at-the-project-level "Permalink") + +如果启用,请检查您的项目是否没有`.gitlab-ci.yml` ,或者如果存在,请将其删除. + +1. 转到项目的 **设置> CI / CD>自动 DevOps** . +2. 选中**默认为 Auto DevOps 管道**复选框以启用它. +3. (可选,但建议使用)启用后,您可以在 Auto DevOps 用于[部署应用程序](stages.html#auto-deploy)的[基本域中](#auto-devops-base-domain)添加,并选择[部署策略](#deployment-strategy) . +4. 单击**保存更改**以使更改生效. + +启用该功能后,将在默认分支上触发 Auto DevOps 管道. + +### At the group level[](#at-the-group-level "Permalink") + +在 GitLab 11.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52447) . + +仅管理员和组所有者可以在组级别启用或禁用自动 DevOps. + +在组级别启用或禁用 Auto DevOps 时,除非在子组或项目上专门启用或禁用了 Auto DevOps,否则组配置将隐式用于该组内的子组和项目. + +要在组级别启用或禁用自动 DevOps: + +1. 前往您小组的 **设置> CI / CD>自动 DevOps**页面. +2. 选中**默认为 Auto DevOps 管道**复选框以启用它. +3. 单击**保存更改**以使更改生效. + +### At the instance level (Administrators only)[](#at-the-instance-level-administrators-only "Permalink") + +即使在实例级别被禁用,组所有者和项目维护者仍可以分别在组和项目级别启用 Auto DevOps. + +1. 去 **管理区域>设置>持续集成和部署** . +2. **为所有项目**选择" **默认为自动 DevOps 管道"**以启用它. +3. (可选)您可以设置 Auto DevOps [基本域](#auto-devops-base-domain) ,以供 Auto Deploy 和 Auto Review Apps 使用. +4. 单击**保存更改**以使更改生效. + +### Deployment strategy[](#deployment-strategy "Permalink") + +在 GitLab 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/38542) . + +您可以转到项目的目录,更改 Auto DevOps 使用的部署策略. **设置> CI / CD>自动 DevOps** . 提供以下选项: + +* **持续部署到生产中** :启用将`master`分支直接部署到生产中的[自动部署](stages.html#auto-deploy) . +* **使用定时增量部署连续部署到生产中** :将[`INCREMENTAL_ROLLOUT_MODE`](customize.html#timed-incremental-rollout-to-production-premium)变量设置为`timed` . 生产部署在每次部署增量之间有 5 分钟的延迟执行. +* **自动部署到登台,手动部署到生产** :将[`STAGING_ENABLED`](customize.html#deploy-policy-for-staging-and-production-environments)和[`INCREMENTAL_ROLLOUT_MODE`](customize.html#incremental-rollout-to-production-premium)变量设置为`1`并`manual` . 这表示: + + * `master`分支直接部署到登台. + * 提供了手动操作以逐步推广到生产中. + +**提示:**使用[蓝绿色部署](../../ci/environments/incremental_rollouts.html#blue-green-deployment)技术可最大程度地减少停机时间和风险. + +## Using multiple Kubernetes clusters[](#using-multiple-kubernetes-clusters-premium "Permalink") + +使用 Auto DevOps 时,由于[它们之间存在](../../user/project/clusters/index.html#multiple-kubernetes-clusters-premium) 1:1 连接,因此可以将不同的环境部署到不同的 Kubernetes 集群. + +Auto DevOps 使用的" [部署作业"模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml)当前定义了 3 个环境名称: + +* `review/` (从`review/`开始的所有环境`review/` ) +* `staging` +* `production` + +这些环境使用[Auto Deploy](stages.html#auto-deploy)与作业绑定,因此,除了环境范围外,它们必须具有不同的部署域. 您必须[根据环境](../../ci/variables/README.html#limit-the-environment-scopes-of-environment-variables)为上述每个项定义一个单独的`KUBE_INGRESS_BASE_DOMAIN`变量. + +下表是如何配置三个不同群集的示例: + +| 集群名称 | 集群环境范围 | `KUBE_INGRESS_BASE_DOMAIN`变量值 | 可变环境范围 | Notes | +| --- | --- | --- | --- | --- | +| review | `review/*` | `review.example.com` | `review/*` | 运行所有[Review Apps](../../ci/review_apps/index.html)的评论集群. `*`是一个通配符,每个环境名称都以`review/`开头使用. | +| staging | `staging` | `staging.example.com` | `staging` | (可选)运行临时环境的部署的临时集群. 您必须先[启用它](customize.html#deploy-policy-for-staging-and-production-environments) . | +| production | `production` | `example.com` | `production` | 运行生产环境部署的生产集群. 您可以使用[增量卷展栏](customize.html#incremental-rollout-to-production-premium) . | + +为每个环境添加不同的集群: + +1. 导航到您项目的 **运营> Kubernetes** . +2. 如上表所述,使用各自的环境范围创建 Kubernetes 集群. +3. 创建集群后,导航至每个集群并安装 Helm Tiller 和 Ingress. 等待分配入口 IP 地址. +4. 确保已使用指定的 Auto DevOps 域[配置 DNS](#auto-devops-base-domain) . +5. 导航到每个集群的页面,方法是 **操作> Kubernetes** ,然后根据其入口 IP 地址添加域. + +完成配置后,您可以通过创建合并请求并验证您的应用程序是否已作为具有 Review `review/*`环境范围的 Kubernetes 集群中的 Review App 部署来测试设置. 同样,您可以检查其他环境. + +## Limitations[](#limitations "Permalink") + +以下限制适用. + +### Private registry support[](#private-registry-support "Permalink") + +没有记录的将私有容器注册表与 Auto DevOps 结合使用的方式. 我们强烈建议将 GitLab 容器注册表与 Auto DevOps 结合使用,以简化配置并防止任何不可预见的问题. + +### Installing Helm behind a proxy[](#installing-helm-behind-a-proxy "Permalink") + +当在代理后面时,GitLab 不支持将[Helm 作为 GitLab 管理的应用程序](../../user/clusters/applications.html#helm)安装. 想要这样做的用户必须在运行时将其代理设置注入到安装 Pod 中,例如使用[`PodPreset`](https://kubernetes.io/docs/concepts/workloads/pods/podpreset/) : + +``` +apiVersion: settings.k8s.io/v1alpha1 +kind: PodPreset +metadata: + name: gitlab-managed-apps-default-proxy + namespace: gitlab-managed-apps +spec: + env: + - name: http_proxy + value: "PUT_YOUR_HTTP_PROXY_HERE" + - name: https_proxy + value: "PUT_YOUR_HTTPS_PROXY_HERE" +``` + +## Troubleshooting[](#troubleshooting "Permalink") + +### Unable to select a buildpack[](#unable-to-select-a-buildpack "Permalink") + +自动构建和自动测试可能无法检测到您的语言或框架,并出现以下错误: + +``` +Step 5/11 : RUN /bin/herokuish buildpack build + ---> Running in eb468cd46085 + -----> Unable to select a buildpack +The command '/bin/sh -c /bin/herokuish buildpack build' returned a non-zero code: 1 +``` + +以下是可能的原因: + +* 您的应用程序可能缺少 buildpack 寻找的关键文件. Ruby 应用程序需要正确检测`Gemfile` ,即使编写不带`Gemfile`的 Ruby 应用程序也是`Gemfile` . +* 您的应用程序可能不存在 buildpack. 尝试指定[自定义 buildpack](customize.html#custom-buildpacks) . + +### Pipeline that extends Auto DevOps with only / except fails[](#pipeline-that-extends-auto-devops-with-only--except-fails "Permalink") + +如果您的管道失败并显示以下消息: + +``` +Found errors in your .gitlab-ci.yml: + + jobs:test config key may not be used with `rules`: only +``` + +当包含作业的规则配置已被`only`或`except`语法覆盖时,将出现此错误. 要解决此问题,您必须: + +* 将您的`only/except`语法转换为规则. +* (临时)将模板固定到[基于 GitLab 12.10 的模板](https://gitlab.com/gitlab-org/auto-devops-v12-10) . + +### Failure to create a Kubernetes namespace[](#failure-to-create-a-kubernetes-namespace "Permalink") + +如果 GitLab 无法为您的项目创建 Kubernetes 命名空间和服务帐户,则 Auto Deploy 将失败. 有关调试此问题的帮助,请参阅[对失败的部署作业进行故障排除](../../user/project/clusters/index.html#troubleshooting) . + +### Detected an existing PostgreSQL database[](#detected-an-existing-postgresql-database "Permalink") + +升级到 GitLab 13.0 后,使用 Auto DevOps 部署时可能会遇到以下消息: + +> 检测到已安装在不赞成使用的通道 1 上的现有 PostgreSQL 数据库,但当前通道设置为 2.在 GitLab 13.0 中,默认通道更改为 2\. […] + +默认情况下,Auto DevOps 会在应用程序旁边安装集群内 PostgreSQL 数据库. 在 GitLab 13.0 中更改了默认安装方法,并且升级现有数据库需要用户参与. 两种安装方法是: + +* **通道 1(不建议使用):**作为关联的 Helm 图表的依赖项拉入数据库. 只支持 Kubernetes 版本 1.15 之前的版本. +* **通道 2(当前):**将数据库安装为独立的 Helm 图表. 将集群内数据库功能与 Kubernetes 1.16 及更高版本一起使用时是必需的. + +如果收到此错误,则可以执行以下操作之一: + +* 通过将`AUTO_DEVOPS_POSTGRES_CHANNEL`设置为`1`并重新部署,可以*放心地*忽略该警告并继续使用通道 1 PostgreSQL 数据库. + +* 通过将`AUTO_DEVOPS_POSTGRES_DELETE_V1`设置为非空值并重新部署,可以删除通道 1 PostgreSQL 数据库并安装新的通道 2 数据库. + + **危险:**删除通道 1 PostgreSQL 数据库将永久删除现有的通道 1 数据库及其所有数据. 有关备份和升级数据库的更多信息,请参见[升级 PostgreSQL](upgrading_postgresql.html) . +* 如果不使用集群内数据库,则可以将`POSTGRES_ENABLED`设置为`false`并重新部署. 此选项与*没有图表内 PostgreSQL 依赖项*的*自定义图表的*用户特别相关. 数据库自动检测基于您的发行版的`postgresql.enabled` Helm 值. 该值是基于`POSTGRES_ENABLED` CI 变量设置的,并且由 Helm 保留,无论您的图表是否使用该变量. + +**危险:**将`POSTGRES_ENABLED`设置为`false`永久删除您环境中的任何现有通道 1 数据库. + +## Development guides[](#development-guides "Permalink") + +[Development guide for Auto DevOps](../../development/auto_devops.html) \ No newline at end of file diff --git a/_book/docs/208.md b/_book/docs/208.md new file mode 100644 index 0000000000000000000000000000000000000000..a9e705c9a0a9d42d71b0ebc103400754053832ae --- /dev/null +++ b/_book/docs/208.md @@ -0,0 +1,214 @@ +# Getting started with Auto DevOps + +> 原文:[https://docs.gitlab.com/ee/topics/autodevops/quick_start_guide.html](https://docs.gitlab.com/ee/topics/autodevops/quick_start_guide.html) + +* [Configure your Google account](#configure-your-google-account) +* [Create a new project from a template](#create-a-new-project-from-a-template) +* [Create a Kubernetes cluster from within GitLab](#create-a-kubernetes-cluster-from-within-gitlab) +* [Install Ingress and Prometheus](#install-ingress-and-prometheus) +* [Enable Auto DevOps (optional)](#enable-auto-devops-optional) +* [Deploy the application](#deploy-the-application) + * [Monitor your project](#monitor-your-project) + * [Work with branches](#work-with-branches) +* [Conclusion](#conclusion) + +# Getting started with Auto DevOps[](#getting-started-with-auto-devops "Permalink") + +本分步指南将帮助您使用[Auto DevOps](index.html)将 GitLab.com 上托管的项目部署到 Google Kubernetes Engine. + +您将使用 GitLab 的本地 Kubernetes 集成,因此您无需使用 Google Cloud Platform 控制台手动创建 Kubernetes 集群. 您将创建并部署一个从 GitLab 模板创建的简单应用程序. + +这些说明也适用于自我管理的 GitLab 实例; 您只需要确保[配置了](../../ci/runners/README.html)自己的[Runners](../../ci/runners/README.html)并[启用了 Google OAuth](../../integration/google.html) . + +## Configure your Google account[](#configure-your-google-account "Permalink") + +在创建 Kubernetes 集群并将其连接到 GitLab 项目之前,您需要一个[Google Cloud Platform 帐户](https://console.cloud.google.com) . 使用现有的 Google 帐户登录,例如用于访问 Gmail 或 Google 云端硬盘的帐户,或创建一个新帐户. + +1. 请按照 Kubernetes Engine 文档的["开始之前"一节](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin)中描述的步骤来启用所需的 API 和相关服务. +2. 确保您已使用 Google Cloud Platform 创建了一个[结算帐户](https://cloud.google.com/billing/docs/how-to/manage-billing-account) . + +**提示:**每个新的 Google Cloud Platform(GCP)帐户都会获得[$ 300 的信用额](https://console.cloud.google.com/freetrial) ,并且与 Google 合作,GitLab 能够为新的 GCP 帐户提供额外的$ 200,以开始使用 GitLab 的 Google Kubernetes Engine Integration. [点击此链接](https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form)并申请信用. + +## Create a new project from a template[](#create-a-new-project-from-a-template "Permalink") + +我们将使用 GitLab 的项目模板之一来开始. 顾名思义,这些项目提供了基于某些知名框架的准系统应用程序. + +1. 在 GitLab 中,单击加号( ),然后选择**新建项目** . +2. 转到**从模板创建**选项卡,您可以在其中选择 Ruby on Rails,Spring 或 NodeJS Express 项目. 对于本教程,请使用 Ruby on Rails 模板. + + [![Select project template](img/db0b9c2164464a7b2e1772c54232681a.png)](img/guide_project_template_v12_3.png) + +3. 给您的项目起一个名字,或者选择一个描述,并将其公开,以便您可以利用[GitLab Gold 计划](https://about.gitlab.com/pricing/#gitlab-com)中的可用功能. + + [![Create project](img/0991c603daeaefcd2df14e098fa66ea4.png)](img/guide_create_project_v12_3.png) + +4. Click **建立专案**. + +现在,您已经创建了一个项目,接下来将创建 Kubernetes 集群以将该项目部署到该集群. + +## Create a Kubernetes cluster from within GitLab[](#create-a-kubernetes-cluster-from-within-gitlab "Permalink") + +1. 在项目的登录页面上,单击**添加 Kubernetes 集群** (请注意,当您导航到 **操作> Kubernetes** ). + + [![Project landing page](img/0bef311ef1713ebb246577aeaaa012c3.png)](img/guide_project_landing_page_v12_10.png) + +2. 在" **添加 Kubernetes 集群集成"**页面上,单击" **创建新集群"**选项卡,然后单击" **Google GKE"** . + +3. 与您的 Google 帐户关联,然后单击" **允许"**以允许访问您的 Google 帐户. (此授权请求仅在您第一次将 GitLab 与您的 Google 帐户连接时显示.) + + 授权访问后,将显示" **添加 Kubernetes 集群集成"**页面. + +4. 在**输入 Kubernetes 集群的详细信息**部分中,提供有关集群的详细信息: + + * **Kubernetes cluster name** + * **环境范围** -保留此字段不变. + * **Google Cloud Platform 项目** -选择一个项目. 在[配置 Google 帐户后](#configure-your-google-account) ,应该已经为您创建了一个项目. + * **区域** -要在其中创建群集的[区域/区域](https://cloud.google.com/compute/docs/regions-zones/) . + * **节点数** + * **机器类型** -有关[机器类型的](https://cloud.google.com/compute/docs/machine-types)更多信息,请参阅 Google 文档. + * **为 Anthos 启用 Cloud Run-**选中此复选框以对该集群使用[Cloud Run](../../user/project/clusters/add_gke_clusters.html#cloud-run-for-anthos) ,Istio 和 HTTP Load Balancing 加载项. + * **由 GitLab 管理的群集** -选中此复选框以[允许 GitLab 管理](../../user/project/clusters/index.html#gitlab-managed-clusters)该群集的[名称空间和服务帐户](../../user/project/clusters/index.html#gitlab-managed-clusters) . +5. Click **创建一个 Kubernetes 集群**. + +几分钟后,将创建集群. 您还可以在[GCP 仪表板上](https://console.cloud.google.com/kubernetes)查看其状态. + +接下来,您将在群集上安装一些需要充分利用 Auto DevOps 的应用程序. + +## Install Ingress and Prometheus[](#install-ingress-and-prometheus "Permalink") + +集群运行后,您可以安装第一个应用程序. 在本指南中,我们将安装 Ingress 和 Prometheus: + +* 入口-在后台使用 NGINX 提供负载平衡,SSL 终止和基于名称的虚拟主机. +* Prometheus-一种用于监视已部署应用程序的开源监视和警报系统. + +**注意:**我们不会在此快速入门指南中安装 GitLab Runner,因为该指南使用了 GitLab.com 提供的共享 Runners. + +要安装应用程序: + +* 单击**Ingress**的**安装**按钮. +* 显示**入口端点时** ,复制 IP 地址. +* 添加您的**基本域** . 对于本指南,我们将使用 GitLab 建议的域. +* Click **保存更改**. + +[![Cluster Base Domain](img/3b33bfa40900241891ce4c916e441a22.png)](img/guide_base_domain_v12_3.png) + +## Enable Auto DevOps (optional)[](#enable-auto-devops-optional "Permalink") + +默认情况下启用 Auto DevOps 时,可以在实例级别(对于自我管理的实例)和组级别禁用 Auto DevOps. 完成以下步骤以启用 Auto DevOps(如果已禁用): + +1. 导航 **设置> CI / CD>自动 DevOps** ,然后点击**扩展** . +2. 选择**默认为自动 DevOps 管道**以显示更多选项. +3. 在" **部署策略"中** ,选择所需的[连续部署策略](index.html#deployment-strategy) ,以在管道成功在`master`分支上运行之后将应用程序部署到生产中. +4. Click **保存更改**. + + [![Auto DevOps settings](img/80a62bce7846a67c7743ef7324a58757.png)](img/guide_enable_autodevops_v12_3.png) + +保存更改后,GitLab 将创建一个新管道. 要查看它,请转到 **CI / CD>管道** . + +在下一节中,我们将解释管道中每个作业的作用. + +## Deploy the application[](#deploy-the-application "Permalink") + +当管道运行时,它在做什么? + +要查看管道中的作业,请单击管道的状态标记. 的 图标在管道作业运行时显示,并在不刷新页面的情况下进行更新 (成功)或 (失败)作业完成时. + +作业分为以下几个阶段: + +[![Pipeline stages](img/bc03121106ba9696b67a617d6aeb3878.png)](img/guide_pipeline_stages_v13_0.png) + +* **构建** -应用程序将构建 Docker 映像并将其上传到项目的[Container Registry](../../user/packages/container_registry/index.html) ( [Auto Build](stages.html#auto-build) ). +* **测试** -GitLab 在应用程序上运行各种检查: + + * `test`作业通过检测语言和框架来运行单元测试和集成测试( [自动测试](stages.html#auto-test) ) + * `code_quality`作业检查代码质量,并允许失败( [自动代码质量](stages.html#auto-code-quality-starter) ) + * `container_scanning`作业检查 Docker 容器是否存在任何漏洞并被允许失败( [自动容器扫描](stages.html#auto-container-scanning-ultimate) ) + * `dependency_scanning`作业检查应用程序是否具有易受漏洞影响的任何依赖关系,并允许其失败( [自动依赖关系扫描](stages.html#auto-dependency-scanning-ultimate) ) + * 后缀为`-sast`作业在当前代码上运行静态分析,以检查潜在的安全问题,并允许其失败( [Auto SAST](stages.html#auto-sast-ultimate) ) + * `secret-detection`作业会检查泄漏的机密并允许其失败( [自动机密检测](stages.html#auto-secret-detection-ultimate) ) + * `license_management`作业搜索应用程序的依存关系,以确定其每个许可证并被允许失败( [自动许可证合规](stages.html#auto-license-compliance-ultimate) )**注意:**除`test`外,所有作业均允许在测试阶段失败. +* **回顾** -对输水管道`master`包括这个阶段有`dast_environment_deploy`工作. 要了解更多信息,请参阅[动态应用程序安全性测试(DAST)](../../user/application_security/dast/index.html) . + +* **生产** -测试和检查完成后,该应用程序将在 Kubernetes 中进行部署( [Auto Deploy](stages.html#auto-deploy) ). + +* **性能** -性能测试在已部署的应用程序上运行( [自动浏览器性能测试](stages.html#auto-browser-performance-testing-premium) ). + +* **清理** -对输水管道`master`包括这个阶段有`stop_dast_environment`工作. + +在运行管道之后,您应该查看已部署的网站并学习如何对其进行监视. + +### Monitor your project[](#monitor-your-project "Permalink") + +成功部署您的应用程序后,您可以通过导航到" **环境"**页面来查看其网站并检查其运行状况. **运营>环境** . 该页面显示有关已部署应用程序的详细信息,右侧列显示将您链接到常见环境任务的图标: + +[![Environments](img/c2b9039967ef1a229c8db9d7542591fb.png)](img/guide_environments_v12_3.png) + +* **开放的现场环境** ( )-打开生产环境中部署的应用程序的 URL +* **Monitoring** () - Opens the metrics page where Prometheus collects data about the Kubernetes cluster and how the application affects it in terms of memory usage, CPU usage, and latency +* **部署到** ( )-显示可以部署到的环境的列表 +* **终端** ( )-在运行应用程序的容器内打开[Web 终端](../../ci/environments/index.html#web-terminals)会话 +* **重新部署到环境** ( )-有关更多信息,请参阅[重试和回滚](../../ci/environments/index.html#retrying-and-rolling-back) +* **停止环境** ( )-有关更多信息,请参阅[停止环境](../../ci/environments/index.html#stopping-an-environment) + +GitLab 在环境信息下方显示[部署板](../../user/project/deploy_boards.html) ,并用正方形表示 Kubernetes 集群中的 Pod,并用颜色编码以显示其状态. 将鼠标悬停在部署板上的正方形上会显示部署的状态,单击该正方形会将您带到窗格的日志页面. + +**提示:**该示例目前仅显示一个托管应用程序的 Pod,但是您可以通过在以下[`REPLICAS`](customize.html#environment-variables)定义[`REPLICAS`变量](customize.html#environment-variables)来添加更多 Pod **设置> CI / CD>环境变量** . + +### Work with branches[](#work-with-branches "Permalink") + +按照[GitLab 流程](../gitlab_flow.html#working-with-feature-branches) ,您接下来应该创建一个功能分支以向您的应用程序添加内容: + +1. 在项目的存储库中,导航到以下文件: `app/views/welcome/index.html.erb` . 该文件应仅包含一个段落: `<p>You're on Rails!</p>` . +2. 打开 GitLab [Web IDE](../../user/project/web_ide/index.html)进行更改. +3. 编辑文件,使其包含: + + ``` + <p>You're on Rails! Powered by GitLab Auto DevOps.</p> + ``` + +4. 暂存文件. 添加提交消息,然后通过单击**Commit**创建一个新分支和一个合并请求. + + [![Web IDE commit](img/d8baae909b3683bffff327402580132f.png)](img/guide_ide_commit_v12_3.png) + +提交合并请求后,GitLab 运行你的管道,而在这一切的工作,如[前文所述](#deploy-the-application) ,除了仅在比其他分支多跑几个`master` . + +[![Merge request](img/161780e2fab1ff78247b22985553ba96.png)](img/guide_merge_request_v12_3.png) + +几分钟后,您会注意到测试失败,这意味着您的更改"破坏了"测试. 单击失败的`test`作业以查看有关它的更多信息: + +``` +Failure: +WelcomeControllerTest#test_should_get_index [/app/test/controllers/welcome_controller_test.rb:7]: +<You're on Rails!> expected but was +<You're on Rails! Powered by GitLab Auto DevOps.>.. +Expected 0 to be >= 1. + +bin/rails test test/controllers/welcome_controller_test.rb:4 +``` + +要修复损坏的测试: + +1. 返回到合并请求的" **概述"**页面,然后单击" **在 Web IDE 中打开"** . +2. 在文件的左侧目录中,找到`test/controllers/welcome_controller_test.rb`文件,然后单击将其打开. +3. 更改第 7 行,说" `You're on Rails! Powered by GitLab Auto DevOps.` `You're on Rails! Powered by GitLab Auto DevOps.` +4. Click **Commit**. +5. 在左侧列的"未**分段的更改"下** ,单击选中标记图标( )进行更改. +6. 编写提交消息,然后单击**提交** . + +返回到合并请求的" **概述"**页面,您不仅应该看到测试通过,而且应该看到部署为[审阅应用程序的应用程序](stages.html#auto-review-apps) . 您可以通过单击**查看应用程序**来访问它 按钮以查看已部署的更改. + +[![Review app](img/afdb4890858bdb916f8a393b22b8ef96.png)](img/guide_merge_request_review_app_v12_3.png) + +合并合并请求后,GitLab 在`master`分支上运行管道,然后将应用程序部署到生产环境. + +## Conclusion[](#conclusion "Permalink") + +实施该项目之后,您应该对 Auto DevOps 的基础有深入的了解. 您从构建和测试开始,到在 GitLab 中全部部署和监视应用程序. 尽管具有自动特性,但也可以配置和自定义 Auto DevOps 以适合您的工作流程. 以下是一些有用的资源,供您进一步阅读: + +1. [Auto DevOps](index.html) +2. [Multiple Kubernetes clusters](index.html#using-multiple-kubernetes-clusters) +3. [Incremental rollout to production](customize.html#incremental-rollout-to-production-premium) +4. [Disable jobs you don’t need with environment variables](customize.html#environment-variables) +5. [Use a static IP for your cluster](../../user/clusters/applications.html#using-a-static-ip) +6. [Use your own buildpacks to build your application](customize.html#custom-buildpacks) +7. [Prometheus monitoring](../../user/project/integrations/prometheus.html) \ No newline at end of file diff --git a/_book/docs/209.md b/_book/docs/209.md new file mode 100644 index 0000000000000000000000000000000000000000..9897a69e0d73d0715ddcb6678d536188f6be3c44 --- /dev/null +++ b/_book/docs/209.md @@ -0,0 +1,73 @@ +# Requirements for Auto DevOps + +> 原文:[https://docs.gitlab.com/ee/topics/autodevops/requirements.html](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) + +* [Auto DevOps requirements for Kubernetes](#auto-devops-requirements-for-kubernetes) +* [Auto DevOps requirements for Amazon ECS](#auto-devops-requirements-for-amazon-ecs) + +# Requirements for Auto DevOps[](#requirements-for-auto-devops "Permalink") + +您可以为[Kubernetes](#auto-devops-requirements-for-kubernetes)或[Amazon Elastic Container Service(ECS)](#auto-devops-requirements-for-amazon-ecs)设置 Auto DevOps. 有关 Auto DevOps 的更多信息,请参见[Auto DevOps 主页](index.html)或[快速入门指南](quick_start_guide.html) . + +## Auto DevOps requirements for Kubernetes[](#auto-devops-requirements-for-kubernetes "Permalink") + +要充分利用 Auto DevOps 和 Kubernetes,您需要: + +* **Kubernetes** (用于[自动审阅应用程序](stages.html#auto-review-apps) , [自动部署](stages.html#auto-deploy)和[自动监视](stages.html#auto-monitoring) ) + + 要启用部署,您需要: + + 1. 您的项目的[Kubernetes 1.12+集群](../../user/project/clusters/index.html) . 最简单的方法是[使用 GitLab UI](../../user/project/clusters/add_remove_clusters.html#create-new-cluster)创建[新集群](../../user/project/clusters/add_remove_clusters.html#create-new-cluster) . 对于 Kubernetes 1.16+群集,您必须为[Auto Deploy for Kubernetes 1.16+](stages.html#kubernetes-116)执行附加配置. + 2. NGINX 入口. 在上一步中配置了 GitLab 的 Kubernetes 集成之后,可以通过安装[用于 Ingress](../../user/clusters/applications.html#ingress)的[GitLab 托管的应用程序,](../../user/clusters/applications.html#ingress)将其部署到 Kubernetes 集群中. + + 另外,您可以使用[`nginx-ingress`](https://github.com/helm/charts/tree/master/stable/nginx-ingress) Helm 图表手动安装 Ingress. + + **注意:**如果您使用自己的 Ingress 而不是 GitLab 托管应用程序提供的 Ingress,请确保您至少运行的是 NGINX Ingress 0.9.0 版,并[启用 Prometheus](https://github.com/helm/charts/tree/master/stable/nginx-ingress#prometheus-metrics)指标以显示响应指标. 您还必须使用`prometheus.io/scrape: "true"`和`prometheus.io/port: "10254"` [注释](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)由 Prometheus 抓取的 NGINX Ingress 部署. +* **基本域** (用于[自动审阅应用程序](stages.html#auto-review-apps) , [自动部署](stages.html#auto-deploy)和[自动监视](stages.html#auto-monitoring) ) + + 您需要一个配置了通配符 DNS 的域,所有您的 Auto DevOps 应用程序都将使用该域. 如果您使用的是[GitLab 托管的 Ingress 应用程序](../../user/clusters/applications.html#ingress) ,则会自动为您配置 URL 端点. + + 您还必须[指定 Auto DevOps 基本域](index.html#auto-devops-base-domain) . + +* **GitLab Runner** (所有阶段) + + 必须将 Runner 配置为运行 Docker,通常使用[Docker](https://docs.gitlab.com/runner/executors/docker.html)或[Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html)执行程序,并[启用特权模式](https://docs.gitlab.com/runner/executors/docker.html) . Runner 不需要安装在 Kubernetes 集群中,但是 Kubernetes 执行器易于使用,并且可以自动缩放. 您还可以使用[Docker Machine 将](https://docs.gitlab.com/runner/install/autoscaling.html)基于 Docker 的 Runner 配置为自动缩放. + + 如果您在第一步中配置了 GitLab 的 Kubernetes 集成,则可以通过[为 GitLab Runner](../../user/clusters/applications.html#gitlab-runner)安装由[GitLab 管理的应用程序](../../user/clusters/applications.html#gitlab-runner)将其部署到集群中. + + 运动员应注册为[共享亚军](../../ci/runners/README.html#shared-runners)整个 GitLab 实例或[特定的运动员](../../ci/runners/README.html#specific-runners)被分配到具体项目(默认值,如果你已经安装了 GitLab 亚军管理应用程序). + +* **Prometheus** (for [Auto Monitoring](stages.html#auto-monitoring)) + + 要启用自动监控,您需要在集群内部或外部安装 Prometheus,并配置为刮取 Kubernetes 集群. 如果已经配置了 GitLab 的 Kubernetes 集成,则可以通过安装[Prometheus](../../user/clusters/applications.html#prometheus)的[GitLab 托管的应用程序](../../user/clusters/applications.html#prometheus)将其部署到集群中. + + 必须为项目启用[Prometheus 服务](../../user/project/integrations/prometheus.html)集成,或者将其作为整个 GitLab 安装的[默认服务模板](../../user/project/integrations/services_templates.html)启用. + + 要获取响应指标(除了系统指标之外),您必须[配置 Prometheus 来监视 NGINX](../../user/project/integrations/prometheus_library/nginx_ingress.html#configuring-nginx-ingress-monitoring) . + +* **cert-manager** (可选,用于 TLS / HTTPS) + + 要为您的应用程序启用 HTTPS 端点,必须安装 cert-manager,这是一个本地 Kubernetes 证书管理控制器,可帮助颁发证书. 在您的群集上安装 cert-manager 会发出[Let's Encrypt](https://letsencrypt.org/)证书,并确保证书有效和最新. 如果已经配置了 GitLab 的 Kubernetes 集成,则可以通过安装[GitLab 托管的 cert-manager 应用程序](../../user/clusters/applications.html#cert-manager)将其部署到集群中. + +如果您没有安装 Kubernetes 或 Prometheus,则将跳过[Auto Review Apps](stages.html#auto-review-apps) , [Auto Deploy](stages.html#auto-deploy)和[Auto Monitoring](stages.html#auto-monitoring) . + +满足所有要求后,您可以[启用 Auto DevOps](index.html#enablingdisabling-auto-devops) . + +## Auto DevOps requirements for Amazon ECS[](#auto-devops-requirements-for-amazon-ecs "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208132) in GitLab 13.0. + +您可以选择将[AWS ECS](../../ci/cloud_deployment/index.html)定位为部署平台,而不是使用 Kubernetes. + +要开始使用针对 AWS ECS 的 Auto DevOps,您必须添加特定的环境变量. 这样做,请按照下列步骤操作: + +1. 在您的项目中,转到**"设置">" CI / CD",**然后展开" **变量"**部分. + +2. 通过添加具有以下值之一的`AUTO_DEVOPS_PLATFORM_TARGET`变量,指定在 Auto DevOps 部署期间要定位的 AWS 平台: + + * `FARGATE`如果您的目标服务必须启动类型 FARGATE 的. + * `ECS`如果部署到 ECS,当你不执行任何启动类型检查. + +触发管道时,如果启用了 Auto DevOps 且已正确[输入 AWS 凭证作为环境变量](../../ci/cloud_deployment/index.html#deploy-your-application-to-the-aws-elastic-container-service-ecs) ,则您的应用程序将部署到 AWS ECS. + +**注意:**部署到 AWS ECS 时, [GitLab 托管应用程序](../../user/clusters/applications.html)不可用. 您必须在 AWS ECS 上手动配置应用程序(例如 Ingress 或 Help).**注意:**如果您同时具有有效的`AUTO_DEVOPS_PLATFORM_TARGET`变量和与项目绑定的 Kubernetes 集群,则仅运行 Kubernetes 的部署.**警告:**将`AUTO_DEVOPS_PLATFORM_TARGET`变量设置为`ECS`将触发[`Jobs/Deploy/ECS.gitlab-ci.yml`模板中](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml)定义的[`Jobs/Deploy/ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml) . 但是,不建议单独[包含](../../ci/yaml/README.html#includetemplate)它. 该模板仅设计用于 Auto DevOps. 如果单独包含它,它可能会发生意外更改,从而导致您的管道失败. 同样,此模板中的作业名称也可能会更改. 不要在自己的管道中覆盖这些作业的名称,因为当名称更改时,覆盖将停止工作. \ No newline at end of file diff --git a/_book/docs/210.md b/_book/docs/210.md new file mode 100644 index 0000000000000000000000000000000000000000..907af70b387223245f60e4766cd922a110266c59 --- /dev/null +++ b/_book/docs/210.md @@ -0,0 +1,471 @@ +# Customizing Auto DevOps + +> 原文:[https://docs.gitlab.com/ee/topics/autodevops/customize.html](https://docs.gitlab.com/ee/topics/autodevops/customize.html) + +* [Custom buildpacks](#custom-buildpacks) + * [Multiple buildpacks](#multiple-buildpacks) +* [Custom `Dockerfile`](#custom-dockerfile) +* [Passing arguments to `docker build`](#passing-arguments-to-docker-build) +* [Forward CI variables to the build environment](#forward-ci-variables-to-the-build-environment) +* [Custom Helm Chart](#custom-helm-chart) +* [Customize values for Helm Chart](#customize-values-for-helm-chart) +* [Custom Helm chart per environment](#custom-helm-chart-per-environment) +* [Customizing `.gitlab-ci.yml`](#customizing-gitlab-ciyml) +* [Customizing the Kubernetes namespace](#customizing-the-kubernetes-namespace) +* [Using components of Auto DevOps](#using-components-of-auto-devops) +* [PostgreSQL database support](#postgresql-database-support) + * [Upgrading PostgresSQL](#upgrading-postgressql) + * [Using external PostgreSQL database providers](#using-external-postgresql-database-providers) +* [Environment variables](#environment-variables) + * [Build and deployment](#build-and-deployment) + * [Database](#database) + * [Disable jobs](#disable-jobs) + * [Application secret variables](#application-secret-variables) + * [Advanced replica variables setup](#advanced-replica-variables-setup) + * [Deploy policy for staging and production environments](#deploy-policy-for-staging-and-production-environments) + * [Deploy policy for canary environments](#deploy-policy-for-canary-environments-premium) + * [Incremental rollout to production](#incremental-rollout-to-production-premium) + * [Timed incremental rollout to production](#timed-incremental-rollout-to-production-premium) +* [Auto DevOps banner](#auto-devops-banner) + +# Customizing Auto DevOps[](#customizing-auto-devops "Permalink") + +尽管[Auto DevOps](index.html)提供了很好的默认设置来帮助您入门,但是您可以自定义几乎所有内容以满足您的需求. Auto DevOps 提供了从自定义[buildpacks](#custom-buildpacks)到[Dockerfiles](#custom-dockerfile)和[Helm 图表的所有内容](#custom-helm-chart) . 您甚至可以将完整的[CI / CD 配置](#customizing-gitlab-ciyml)复制到您的项目中,以启用暂存和 Canary 部署等. + +## Custom buildpacks[](#custom-buildpacks "Permalink") + +如果您的项目无法自动检测到构建包,或者要使用自定义构建包,则可以在项目中使用项目变量或`.buildpacks`文件覆盖`.buildpacks` : + +* **项目变量** -使用要使用的 buildpack 的 URL 创建项目变量`BUILDPACK_URL` . +* **`.buildpacks`文件** -在项目的存储库中添加一个名为`.buildpacks`的文件,并添加要在文件中一行使用的 buildpack 的 URL. 如果要使用多个 buildpack,请每行输入一个 buildpack. + +buildpack URL 可以指向 Git 存储库 URL 或 tarball URL. 对于 Git 存储库,您可以通过将`#<ref>`附加到 Git 存储库 URL 来指向特定的 Git 引用(例如,提交 SHA,标记名称或分支名称). 例如: + +* 标签`v142` : `https://github.com/heroku/heroku-buildpack-ruby.git#v142` : `https://github.com/heroku/heroku-buildpack-ruby.git#v142` . +* 分支`mybranch` : `https://github.com/heroku/heroku-buildpack-ruby.git#mybranch` : `https://github.com/heroku/heroku-buildpack-ruby.git#mybranch` . +* 提交 SHA `f97d8a8ab49` : `https://github.com/heroku/heroku-buildpack-ruby.git#f97d8a8ab49` : `https://github.com/heroku/heroku-buildpack-ruby.git#f97d8a8ab49` . + +### Multiple buildpacks[](#multiple-buildpacks "Permalink") + +Auto DevOps 不完全支持使用多个 buildpack,因为在使用`.buildpacks`文件时,自动测试将不起作用. 在后端用于解析`.buildpacks`文件的 buildpack [heroku-buildpack-multi](https://github.com/heroku/heroku-buildpack-multi/)没有提供必要的命令`bin/test-compile`和`bin/test` . + +If your goal is to use only a single custom buildpack, you should provide the project variable `BUILDPACK_URL` instead. + +## Custom `Dockerfile`[](#custom-dockerfile "Permalink") + +> [在 GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35662)中[添加了](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35662)对`DOCKERFILE_PATH`支持 + +如果您的项目在项目存储库的根目录中有一个`Dockerfile` ,则 Auto DevOps 会基于 Dockerfile 而不是使用 buildpacks 构建 Docker 映像. 这样可以更快,并产生较小的映像,尤其是在您的 Dockerfile 基于[Alpine 的情况下](https://hub.docker.com/_/alpine/) . + +如果设置`DOCKERFILE_PATH` CI 变量,则"自动构建"将在其中查找 Dockerfile. + +## Passing arguments to `docker build`[](#passing-arguments-to-docker-build "Permalink") + +可以使用`AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS`项目变量将参数传递给`AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` `docker build`命令. 例如,要基于`ruby:alpine`而不是默认的`ruby:latest`构建 Docker 映像: + +1. Set `AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` to `--build-arg=RUBY_VERSION=alpine`. +2. 将以下内容添加到自定义`Dockerfile` : + + ``` + ARG RUBY_VERSION=latest + FROM ruby:$RUBY_VERSION + + # ... put your stuff here + ``` + +**注意:**如果需要传递复杂的值(例如换行符和空格), **请**使用 Base64 编码. 由于 Auto DevOps 如何使用自变量,此类未经编码的复杂值可能导致转义问题.**警告:**尽可能避免将秘密作为 Docker 构建参数传递,因为它们可能会保留在映像中. 有关详细信息,请参见[有关最佳实践的讨论](https://github.com/moby/moby/issues/13490) . + +## Forward CI variables to the build environment[](#forward-ci-variables-to-the-build-environment "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/25514) ,但在 11.9 及更高版本中可用. + +可以使用`AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` CI 变量将 CI 变量转发到构建环境中. 转发的变量应在逗号分隔的列表中按名称指定. 例如,要转发变量`CI_COMMIT_SHA`和`CI_ENVIRONMENT_NAME` ,请将`AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES`设置为`CI_COMMIT_SHA,CI_ENVIRONMENT_NAME` . + +* 使用 Buildpacks 时,转发的变量将自动用作环境变量. +* 使用`Dockerfile` ,需要执行以下附加步骤: + + 1. 通过将以下代码添加到文件顶部来激活实验性`Dockerfile`语法: + + ``` + # syntax = docker/dockerfile:experimental + ``` + + 2. 要在任何可用的秘密`RUN $COMMAND`在`Dockerfile` ,秘密文件和源安装运行之前,它`$COMMAND` : + + ``` + RUN --mount=type=secret,id=auto-devops-build-secrets . /run/secrets/auto-devops-build-secrets && $COMMAND + ``` + +**注意:**设置`AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` ,Auto DevOps 会启用实验性[Docker BuildKit](https://s0docs0docker0com.icopy.site/develop/develop-images/build_enhancements/)功能以使用`--secret`标志. + +## Custom Helm Chart[](#custom-helm-chart "Permalink") + +Auto DevOps 使用[Helm](https://helm.sh/)将您的应用程序部署到 Kubernetes. 您可以通过将图表捆绑到项目存储库中或通过指定项目变量来覆盖使用的 Helm 图表: + +* **捆绑图** -如果您的项目中有一个带有`Chart.yaml`文件的`./chart`目录,则 Auto DevOps 将检测到该图并使用它代替[默认图](https://gitlab.com/gitlab-org/charts/auto-deploy-app) ,从而使您能够精确地控制应用程序的部署方式. +* **项目变量** -创建一个[项目变量](../../ci/variables/README.html#gitlab-cicd-environment-variables) `AUTO_DEVOPS_CHART`有一个自定义图表的 URL 来使用,或创建两个项目变量: `AUTO_DEVOPS_CHART_REPOSITORY`有一个自定义图表库的 URL,并`AUTO_DEVOPS_CHART`与路径图. + +## Customize values for Helm Chart[](#customize-values-for-helm-chart "Permalink") + +[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/30628)在 GitLab 12.6, `.gitlab/auto-deploy-values.yaml`将默认为头盔升级使用. + +您可以通过以下任一方式覆盖[默认 Helm 图表中](https://gitlab.com/gitlab-org/charts/auto-deploy-app) `values.yaml`文件中的[默认值](https://gitlab.com/gitlab-org/charts/auto-deploy-app) : + +* 将名为`.gitlab/auto-deploy-values.yaml`的文件添加到您的存储库,如果找到,该文件将自动使用. +* 将具有不同名称或路径的文件添加到存储库,并使用路径和名称设置`HELM_UPGRADE_VALUES_FILE` [环境变量](#environment-variables) . + +**注:**对于 GitLab 12.5 和更早的版本,使用`HELM_UPGRADE_EXTRA_ARGS`环境变量设置以覆盖默认图表值`HELM_UPGRADE_EXTRA_ARGS`到`--values <my-values.yaml>` + +## Custom Helm chart per environment[](#custom-helm-chart-per-environment "Permalink") + +您可以通过将环境变量定义为所需环境来指定每个环境使用自定义 Helm 图表. 请参阅[限制变量的环境范围](../../ci/variables/README.html#limit-the-environment-scopes-of-environment-variables) . + +## Customizing `.gitlab-ci.yml`[](#customizing-gitlab-ciyml "Permalink") + +Auto DevOps 是完全可自定义的,因为[Auto DevOps 模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)只是[`.gitlab-ci.yml`](../../ci/yaml/README.html)文件的实现,并且仅使用任何`.gitlab-ci.yml`实现的`.gitlab-ci.yml` . + +要修改 Auto DevOps 使用的 CI / CD 管道,请[`include`模板](../../ci/yaml/README.html#includetemplate) ,并根据需要通过向包含以下内容的存储库的根目录中添加`.gitlab-ci.yml`文件来自定义它: + +``` +include: + - template: Auto-DevOps.gitlab-ci.yml +``` + +添加您的更改,您的添加将使用[`include`](../../ci/yaml/README.html#include)所描述的行为与[Auto DevOps 模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)合并. + +如果您需要专门删除文件的一部分,还可以将[Auto DevOps 模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)的内容复制并粘贴到您的项目中,并根据需要进行编辑. + +## Customizing the Kubernetes namespace[](#customizing-the-kubernetes-namespace "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) . + +对于不受 GitLab 管理的集群,可以通过指定[`environment:kubernetes:namespace`](../../ci/environments/index.html#configuring-kubernetes-deployments)来自定义`.gitlab-ci.yml`的[`environment:kubernetes:namespace`](../../ci/environments/index.html#configuring-kubernetes-deployments) . 例如,以下配置将覆盖用于`production`部署的名称空间: + +``` +include: + - template: Auto-DevOps.gitlab-ci.yml + +production: + environment: + kubernetes: + namespace: production +``` + +使用 Auto DevOps 部署到自定义名称空间时,群集随附的服务帐户至少需要名称空间内的`edit`角色. + +* 如果服务帐户可以创建名称空间,则可以按需创建名称空间. +* 否则,名称空间必须在部署之前存在. + +## Using components of Auto DevOps[](#using-components-of-auto-devops "Permalink") + +如果仅需要 Auto DevOps 提供的功能的子集,则可以将各个 Auto DevOps 作业包括在自己的`.gitlab-ci.yml` . 每个组件作业都依赖于一个阶段,该阶段应该在包含模板的`.gitlab-ci.yml`中定义. + +例如,要使用[自动构建](stages.html#auto-build) ,可以将以下内容添加到`.gitlab-ci.yml` : + +``` +stages: + - build + +include: + - template: Jobs/Build.gitlab-ci.yml +``` + +有关可用作业的信息,请参见[Auto DevOps 模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml) . + +**弃用:**从[GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213336)开始,使用[`only`](../../ci/yaml/README.html#onlyexcept-basic)或[`except`](../../ci/yaml/README.html#onlyexcept-basic)语法的 Auto DevOps 模板将切换到[`rules`](../../ci/yaml/README.html#rules)语法. 如果您`.gitlab-ci.yml`扩展了这些汽车的 DevOps 模板和覆盖`only`或`except`关键字,您必须迁移模板使用[`rules`](../../ci/yaml/README.html#rules)语法的基本模板被迁移到使用后`rules`语法. 对于尚不能迁移的用户,您可以选择将模板固定到[基于 GitLab 12.10 的模板](https://gitlab.com/gitlab-org/auto-devops-v12-10) . + +## PostgreSQL database support[](#postgresql-database-support "Permalink") + +为了支持需要数据库的应用程序,默认情况下配置[PostgreSQL](https://s0www0postgresql0org.icopy.site/) . 访问数据库的凭据已预先配置,但可以通过设置关联[变量](#environment-variables)进行自定义. 您可以使用这些凭据来定义`DATABASE_URL` : + +``` +postgres://user:password@postgres-host:postgres-port/postgres-database +``` + +### Upgrading PostgresSQL[](#upgrading-postgressql "Permalink") + +**弃用:**用于控制默认`AUTO_DEVOPS_POSTGRES_CHANNEL`配置 PostgreSQL 的变量`AUTO_DEVOPS_POSTGRES_CHANNEL`在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/issues/210499)已更改为`2` . 要继续使用旧的 PostgreSQL,请将`AUTO_DEVOPS_POSTGRES_CHANNEL`变量设置为`1` . + +用于配置 PostgreSQL 的图表的版本: + +* 在 GitLab 13.0 和更高版本中为 8.2.1,但如果需要可以将其设置回 0.7.1. +* 可以在 GitLab 12.9 和 12.10 中设置为 0.7.1 至 8.2.1. +* 在 GitLab 12.8 及更早版本中为 0.7.1. + +GitLab 鼓励用户[将其数据库迁移](upgrading_postgresql.html)到较新的 PostgreSQL. + +### Using external PostgreSQL database providers[](#using-external-postgresql-database-providers "Permalink") + +尽管 Auto DevOps 为生产环境提供了对 PostgreSQL 容器的开箱即用支持,但在某些情况下,它可能不够安全或没有弹性,您可能要使用外部托管提供程序(例如 AWS Relational Database)服务)(适用于 PostgreSQL). + +您必须在项目的 CI / CD 设置中为`POSTGRES_ENABLED`和`DATABASE_URL`定义环境范围的变量: + +1. 使用范围内的[环境变量](../../ci/environments/index.html#scoping-environments-with-specs)针对所需环境禁用内置 PostgreSQL 安装. 对于此用例,可能只需要将`production`添加到此列表中. 用于 Review Apps 和登台的内置 PostgreSQL 设置就足够了. + + [![Auto Metrics](img/f4a6d7020c73bd402fc6428d02a4e550.png)](img/disable_postgres.png) + +2. Define the `DATABASE_URL` CI variable as a scoped environment variable that will be available to your application. This should be a URL in the following format: + + ``` + postgres://user:password@postgres-host:postgres-port/postgres-database + ``` + +您必须确保您的 Kubernetes 集群可以访问托管 PostgreSQL 的任何地方的网络. + +## Environment variables[](#environment-variables "Permalink") + +以下变量可用于设置 Auto DevOps 域,提供自定义 Helm 图表或缩放应用程序. PostgreSQL 也可以自定义,您可以使用[自定义 buildpack](#custom-buildpacks) . + +### Build and deployment[](#build-and-deployment "Permalink") + +下表列出了与构建和部署应用程序有关的变量. + +| **Variable** | **Description** | +| --- | --- | +| `ADDITIONAL_HOSTS` | 指定为逗号分隔列表的标准域名,添加到 Ingress 主机中. | +| `<ENVIRONMENT>_ADDITIONAL_HOSTS` | 对于特定环境,将指定为逗号分隔列表的标准域名添加到 Ingress 主机. 这优先于`ADDITIONAL_HOSTS` . | +| `AUTO_DEVOPS_ATOMIC_RELEASE` | 从 GitLab 13.0 开始,默认情况下,Auto DevOps 使用[`--atomic`](https://v2.helm.sh/docs/helm/#options-43)进行 Helm 部署. 将此变量设置为`false`可禁用`--atomic` | +| `AUTO_DEVOPS_BUILD_IMAGE_CNB_ENABLED` | 当设置为非空值且不存在`Dockerfile` ,"自动构建"将使用 Cloud Native Buildpacks 而非 Herokuish 构建应用程序. [更多细节](stages.html#auto-build-using-cloud-native-buildpacks-beta) . | +| `AUTO_DEVOPS_BUILD_IMAGE_CNB_BUILDER` | 使用 Cloud Native Buildpacks 构建时使用的构建器. 默认的构建器是`heroku/buildpacks:18` . [更多细节](stages.html#auto-build-using-cloud-native-buildpacks-beta) . | +| `AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` | 要传递给`docker build`命令的额外参数. 请注意,使用引号不会阻止单词拆分. [更多细节](#passing-arguments-to-docker-build) . | +| `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` | A [comma-separated list of CI variable names](#forward-ci-variables-to-the-build-environment) to be forwarded to the build environment (the buildpack builder or `docker build`). | +| `AUTO_DEVOPS_CHART` | Helm Chart 用于部署您的应用程序. 默认为[GitLab 提供的](https://gitlab.com/gitlab-org/charts/auto-deploy-app) . | +| `AUTO_DEVOPS_CHART_REPOSITORY` | Helm Chart 存储库用于搜索图表. 默认为`https://charts.gitlab.io` . | +| `AUTO_DEVOPS_CHART_REPOSITORY_NAME` | 从 GitLab 11.11 开始,用于设置 Helm 存储库的名称. 默认为`gitlab` . | +| `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME` | 从 GitLab 11.11 开始,用于设置用户名以连接到 Helm 存储库. 默认为无凭据. 还要设置`AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD` . | +| `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD` | 从 GitLab 11.11 开始,用于设置密码以连接到 Helm 存储库. 默认为无凭据. 还要设置`AUTO_DEVOPS_CHART_REPOSITORY_USERNAME` . | +| `AUTO_DEVOPS_DEPLOY_DEBUG` | 从 GitLab 13.1 开始,如果存在此变量,Helm 将输出调试日志. | +| `AUTO_DEVOPS_ALLOW_TO_FORCE_DEPLOY_V<N>` | 从[auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image) v1.0.0 起,如果存在此变量,则将强制部署新的主要图表版本. [更多细节](upgrading_chart.html#ignore-warning-and-continue-deploying) | +| `AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE` | 从 GitLab 12.5 起,与[ModSecurity 功能标记](../../user/clusters/applications.html#web-application-firewall-modsecurity)结合使用可切换[ModSecurity 的`SecRuleEngine`](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#SecRuleEngine)行为. 默认为`DetectionOnly` . | +| `BUILDPACK_URL` | Buildpack’s full URL. Can point to either [a Git repository URL or a tarball URL](#custom-buildpacks). | +| `CANARY_ENABLED` | 从 GitLab 11.0 开始,用于定义[Canary 环境](#deploy-policy-for-canary-environments-premium)的[部署策略](#deploy-policy-for-canary-environments-premium) . | +| `CANARY_PRODUCTION_REPLICAS` | 要在生产环境中为[Canary 部署](../../user/project/canary_deployments.html)进行部署的 Canary 副本数. 优先于`CANARY_REPLICAS` . 默认为 1. | +| `CANARY_REPLICAS` | 用于[Canary 部署](../../user/project/canary_deployments.html)的 Canary 副本数. 默认为 1. | +| `DOCKERFILE_PATH` | 从 GitLab 13.2 开始,允许[在构建阶段](#custom-dockerfile)覆盖[默认的 Dockerfile 路径](#custom-dockerfile) | +| `HELM_RELEASE_NAME` | 从 GitLab 12.1 起,可以覆盖`helm`发布名称. 将多个项目部署到单个名称空间时,可用于分配唯一的发行版名称. | +| `HELM_UPGRADE_VALUES_FILE` | 从 GitLab 12.6 起,可以覆盖`helm upgrade`值文件. 默认为`.gitlab/auto-deploy-values.yaml` . | +| `HELM_UPGRADE_EXTRA_ARGS` | 从 GitLab 11.11 开始,在部署应用程序时允许在`helm`命令中使用其他参数. 请注意,使用引号不会阻止单词拆分. | +| `INCREMENTAL_ROLLOUT_MODE` | 从 GitLab 11.4 起,如果存在的话,可用于为生产环境启用应用程序的[增量部署](#incremental-rollout-to-production-premium) . 对于手动部署作业,设置为" `manual` ;对于自动部署部署,则设置为" `timed` ,每个延迟 5 分钟. | +| `K8S_SECRET_*` | 从 GitLab 11.7 开始,Auto DevOps 会将任何前缀为[`K8S_SECRET_`](#application-secret-variables)变量作为环境变量提供给已部署的应用程序. | +| `KUBE_INGRESS_BASE_DOMAIN` | 从 GitLab 11.8 开始,可用于为每个群集设置一个域. 有关更多信息,请参见[群集域](../../user/project/clusters/index.html#base-domain) . | +| `PRODUCTION_REPLICAS` | 要在生产环境中部署的副本数. 优先于`REPLICAS` ,默认值为 1.对于零停机升级,设置为 2 或更大. | +| `REPLICAS` | 要部署的副本数. 默认为 1. | +| `ROLLOUT_RESOURCE_TYPE` | 从 GitLab 11.9 开始,允许使用自定义 Helm 图表指定正在部署的资源类型. 默认值为`deployment` . | +| `ROLLOUT_STATUS_DISABLED` | 从 GitLab 12.0 开始,用于禁用推出状态检查,因为它不支持所有资源类型,例如`cronjob` . | +| `STAGING_ENABLED` | 从 GitLab 10.8 开始,用于定义[登台和生产环境](#deploy-policy-for-staging-and-production-environments)的[部署策略](#deploy-policy-for-staging-and-production-environments) . | + +**提示:**使用[项目变量](../../ci/variables/README.html#gitlab-cicd-environment-variables)设置副本[变量后](../../ci/variables/README.html#gitlab-cicd-environment-variables) ,可以通过重新部署来缩放应用程序.**注意:**您*不*应该直接扩展使用 Kubernetes 您的应用程序. 这可能会导致 Helm 无法检测到更改而造成混乱,随后使用 Auto DevOps 进行的部署可能会撤消您的更改. + +### Database[](#database "Permalink") + +下表列出了与数据库有关的变量. + +| **Variable** | **Description** | +| --- | --- | +| `DB_INITIALIZE` | 从 GitLab 11.4 开始,用于指定运行以初始化应用程序的 PostgreSQL 数据库的命令. 在应用程序窗格中运行. | +| `DB_MIGRATE` | 从 GitLab 11.4 开始,用于指定运行以迁移应用程序的 PostgreSQL 数据库的命令. 在应用程序窗格中运行. | +| `POSTGRES_ENABLED` | 是否启用 PostgreSQL. 默认为`true` . 设置为`false`可禁用 PostgreSQL 的自动部署. | +| `POSTGRES_USER` | PostgreSQL 用户. 默认为`user` . 将其设置为使用自定义用户名. | +| `POSTGRES_PASSWORD` | PostgreSQL 密码. 默认为`testing-password` . 将其设置为使用自定义密码. | +| `POSTGRES_DB` | PostgreSQL 数据库名称. 默认为[`$CI_ENVIRONMENT_SLUG`](../../ci/variables/README.html#predefined-environment-variables)的值. 将其设置为使用自定义数据库名称. | +| `POSTGRES_VERSION` | 用于[`postgres` Docker 映像的](https://hub.docker.com/_/postgres)标签. 对于`9.6.16` GitLab 13.0 `9.6.16`的测试和部署,默认值为`9.6.16` (以前为`9.6.2` ). 如果`AUTO_DEVOPS_POSTGRES_CHANNEL`设置为`1` ,则部署将使用默认版本`9.6.2` . | + +### Disable jobs[](#disable-jobs "Permalink") + +下表列出了用于禁用作业的变量. + +| **Variable** | **Description** | +| --- | --- | +| `CODE_QUALITY_DISABLED` | 从 GitLab 11.0 起,用于禁用`codequality`作业. 如果存在变量,则不会创建作业. | +| `CONTAINER_SCANNING_DISABLED` | From GitLab 11.0, used to disable the `sast:container` job. If the variable is present, the job won’t be created. | +| `DAST_DISABLED` | 从 GitLab 11.0 起,用于禁用`dast`作业. 如果存在变量,则不会创建作业. | +| `DEPENDENCY_SCANNING_DISABLED` | 从 GitLab 11.0 起,用于禁用`dependency_scanning`作业. 如果存在变量,则不会创建作业. | +| `LICENSE_MANAGEMENT_DISABLED` | 从 GitLab 11.0 开始,用于禁用`license_management`作业. 如果存在变量,则不会创建作业. | +| `PERFORMANCE_DISABLED` | 从 GitLab 11.0 起,用于禁用浏览器`performance`作业. 如果存在变量,则不会创建作业. | +| `LOAD_PERFORMANCE_DISABLED` | 从 GitLab 13.2 开始,用于禁用`load_performance`作业. 如果存在变量,则不会创建作业. | +| `REVIEW_DISABLED` | 从 GitLab 11.0 开始,用于禁用`review`和手动`review:stop`作业. 如果存在该变量,则不会创建这些作业. | +| `SAST_DISABLED` | 从 GitLab 11.0 起,用于禁用`sast`作业. 如果存在变量,则不会创建作业. | +| `TEST_DISABLED` | 从 GitLab 11.0 起,用于禁用`test`作业. 如果存在变量,则不会创建作业. | + +### Application secret variables[](#application-secret-variables "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49056) . + +某些应用程序需要定义可由部署的应用程序访问的秘密变量. Auto DevOps 会检测以`K8S_SECRET_`开头的变量,并将这些带前缀的变量作为环境变量提供给已部署的应用程序. + +要配置您的应用程序变量: + +1. Go to your project’s **设置> CI / CD**, then expand the **Variables** section. + +2. 创建一个 CI / CD 变量,确保密钥以`K8S_SECRET_`为前缀. 例如,您可以使用键`K8S_SECRET_RAILS_MASTER_KEY`创建一个变量. + +3. 通过手动创建新管道或将代码更改推送到 GitLab 来运行 Auto DevOps 管道. + +Auto DevOps 管道将使用您的应用程序秘密变量来填充 Kubernetes 秘密. 这个秘密在每个环境中都是唯一的. 部署应用程序时,机密将作为环境变量加载到运行应用程序的容器中. 在上面的示例之后,您可以在下面看到包含`RAILS_MASTER_KEY`变量的机密. + +``` +$ kubectl get secret production-secret -n minimal-ruby-app-54 -o yaml + +apiVersion: v1 +data: + RAILS_MASTER_KEY: MTIzNC10ZXN0 +kind: Secret +metadata: + creationTimestamp: 2018-12-20T01:48:26Z + name: production-secret + namespace: minimal-ruby-app-54 + resourceVersion: "429422" + selfLink: /api/v1/namespaces/minimal-ruby-app-54/secrets/production-secret + uid: 57ac2bfd-03f9-11e9-b812-42010a9400e4 +type: Opaque +``` + +通常认为环境变量在 Kubernetes 容器中是不可变的. 如果在不更改任何代码的情况下更新应用程序机密,然后手动创建新管道,则会发现任何正在运行的应用程序吊舱都不会具有更新后的机密. 要更新机密,请执行以下任一操作: + +* 将代码更新推送到 GitLab,以强制 Kubernetes 部署重新创建 Pod. +* 手动删除正在运行的 Pod,以使 Kubernetes 创建具有更新机密的新 Pod. + +**注意:**由于当前 Auto DevOps 脚本环境的限制,当前不支持具有多行值的变量. + +### Advanced replica variables setup[](#advanced-replica-variables-setup "Permalink") + +除了上面提到的两个与副本相关的生产变量之外,您还可以将其他变量用于不同的环境. + +Kubernetes 的标签名为`track` ,GitLab CI / CD 环境名称和副本环境变量被组合为`TRACK_ENV_REPLICAS`格式,使您能够定义自己的变量来扩展 Pod 的副本: + +* `TRACK` :Helm Chart 应用程序定义中`track` [Kubernetes 标签](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)的大写值. 如果未设置,则不会考虑到变量名. +* `ENV` :部署作业的大写环境名称,在`.gitlab-ci.yml`设置. + +在下面的示例中,环境的名称为`qa` ,并且部署了轨道`foo` ,这将导致一个名为`FOO_QA_REPLICAS`的环境变量: + +``` +QA testing: + stage: deploy + environment: + name: qa + script: + - deploy foo +``` + +还必须在应用程序的 Helm 图表中定义被引用的`foo`轨道,例如: + +``` +replicaCount: 1 +image: + repository: gitlab.example.com/group/project + tag: stable + pullPolicy: Always + secrets: + - name: gitlab-registry +application: + track: foo + tier: web +service: + enabled: true + name: web + type: ClusterIP + url: http://my.host.com/ + externalPort: 5000 + internalPort: 5000 +``` + +### Deploy policy for staging and production environments[](#deploy-policy-for-staging-and-production-environments "Permalink") + +在 GitLab 10.8 中[引入](https://gitlab.com/gitlab-org/gitlab-ci-yml/-/merge_requests/160) . + +**提示:**您也可以在[项目的设置中进行设置](index.html#deployment-strategy) . + +Auto DevOps 的正常行为是使用连续部署,每次在默认分支上运行新管道时,都会自动推送到`production`环境. 但是,在某些情况下,您可能需要使用暂存环境并手动部署到生产环境. 对于这种情况,引入了`STAGING_ENABLED`环境变量. + +如果您定义`STAGING_ENABLED` ,例如将`STAGING_ENABLED`设置为`1`作为 CI / CD 变量,则 GitLab 会自动将应用程序部署到`staging`环境,并在准备好手动部署到生产环境时为您创建`production_manual`作业. + +### Deploy policy for canary environments[](#deploy-policy-for-canary-environments-premium "Permalink") + +在 GitLab 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab-ci-yml/-/merge_requests/171) . + +在将任何更改部署到生产之前,可以使用[Canary 环境](../../user/project/canary_deployments.html) . + +如果您在项目中定义`CANARY_ENABLED` ,例如将`CANARY_ENABLED`设置为`1`作为 CI / CD 变量,则会创建两个手动作业: + +* `canary` -将应用程序部署到金丝雀环境. +* `production_manual`手动将应用程序部署到生产环境. + +### Incremental rollout to production[](#incremental-rollout-to-production-premium "Permalink") + +在 GitLab 10.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/5415) . + +**提示:**您也可以在[项目的设置中进行设置](index.html#deployment-strategy) . + +当您准备将新版本的应用程序部署到生产环境时,您可能希望使用增量部署将最新的代码替换为少数 Pod,以检查应用程序的行为,然后手动将部署率提高到 100% . + +如果在项目中将`INCREMENTAL_ROLLOUT_MODE`设置为`manual` ,则将创建 4 个不同的[手动](../../ci/pipelines/index.html#add-manual-interaction-to-your-pipeline)作业,而不是标准`production`作业: + +1. `rollout 10%` +2. `rollout 25%` +3. `rollout 50%` +4. `rollout 100%` + +该百分比基于`REPLICAS`变量,并定义了您要用于部署的 Pod 数量. 如果该值为`10` ,并且您运行`10%`部署作业,那么将有`1`新容器+ `9`个旧容器. + +要开始工作,请点击播放图标( )旁边的职位名称. 您不需要从`10%`增加到`100%` ,您可以跳到所需的任何工作. 您也可以在达到`100%`之前通过执行较低百分比的作业来缩小规模. 一旦达到`100%` ,您将无法缩小规模,并且必须通过使用环境页面中的" [回滚"按钮](../../ci/environments/index.html#retrying-and-rolling-back)重新部署旧版本来进行[回滚](../../ci/environments/index.html#retrying-and-rolling-back) . + +在下面,您可以看到如果定义了发布或登台变量,管道的外观. + +没有`INCREMENTAL_ROLLOUT_MODE`和`STAGING_ENABLED` : + +[![Staging and rollout disabled](img/4a3c28657f884da12667bc861ea60e0c.png)](img/rollout_staging_disabled.png) + +没有`INCREMENTAL_ROLLOUT_MODE`和`STAGING_ENABLED` : + +[![Staging enabled](img/c79ebe6e2611f151d42f879eaee753fe.png)](img/staging_enabled.png) + +在将`INCREMENTAL_ROLLOUT_MODE`设置为`manual`且没有`STAGING_ENABLED`情况`STAGING_ENABLED` : + +[![Rollout enabled](img/ceb135d0071e5591ba58f5d2820e8f4b.png)](img/rollout_enabled.png) + +将`INCREMENTAL_ROLLOUT_MODE`设置为`manual` ,并将`STAGING_ENABLED` + +[![Rollout and staging enabled](img/1780684b75826fc70c4f9d6a00cd9984.png)](img/rollout_staging_enabled.png) + +**注意:**在 GitLab 11.4 之前, `INCREMENTAL_ROLLOUT_ENABLED`环境变量的存在启用了此功能. 此配置已弃用,以后将被删除. + +### Timed incremental rollout to production[](#timed-incremental-rollout-to-production-premium "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7545) . + +**提示:**您也可以在[项目的设置中进行设置](index.html#deployment-strategy) . + +此配置基于[向生产的增量部署](#incremental-rollout-to-production-premium) . + +除以下内容外,其他所有行为均相同: + +* 要启用它,请将`INCREMENTAL_ROLLOUT_MODE`变量设置为`timed` . +* Instead of the standard `production` job, the following jobs are created with a 5 minute delay between each: + + 1. `timed rollout 10%` + 2. `timed rollout 25%` + 3. `timed rollout 50%` + 4. `timed rollout 100%` + +## Auto DevOps banner[](#auto-devops-banner "Permalink") + +在未启用自动 DevOps 的情况下,对新项目具有维护者或更高权限的用户将显示以下 Auto DevOps 标语: + +[![Auto DevOps banner](img/5262199c26e59a11bfa467901c29122a.png)](img/autodevops_banner_v12_6.png) + +可以为以下内容禁用横幅: + +* 用户,当他们自己关闭它时. +* 通过显式[禁用 Auto DevOps 的项目](index.html#enablingdisabling-auto-devops) . +* 整个 GitLab 实例: + * 由管理员在 Rails 控制台中运行以下命令: + + ``` + Feature . enable ( :auto_devops_banner_disabled ) + ``` + + * 通过带有管理员访问令牌的 REST API: + + ``` + curl --data "value=true" --header "PRIVATE-TOKEN: <personal_access_token>" https://gitlab.example.com/api/v4/features/auto_devops_banner_disabled + ``` \ No newline at end of file diff --git a/_book/docs/211.md b/_book/docs/211.md new file mode 100644 index 0000000000000000000000000000000000000000..f50e8796dbb60ee4e09dac60d1ff30d8a92aa950 --- /dev/null +++ b/_book/docs/211.md @@ -0,0 +1,442 @@ +# Stages of Auto DevOps + +> 原文:[https://docs.gitlab.com/ee/topics/autodevops/stages.html](https://docs.gitlab.com/ee/topics/autodevops/stages.html) + +* [Auto Build](#auto-build) + * [Auto Build using a Dockerfile](#auto-build-using-a-dockerfile) + * [Auto Build using Heroku buildpacks](#auto-build-using-heroku-buildpacks) + * [Auto Build using Cloud Native Buildpacks (beta)](#auto-build-using-cloud-native-buildpacks-beta) +* [Auto Test](#auto-test) + * [Currently supported languages](#currently-supported-languages) +* [Auto Code Quality](#auto-code-quality-starter) +* [Auto SAST](#auto-sast-ultimate) +* [Auto Secret Detection](#auto-secret-detection-ultimate) +* [Auto Dependency Scanning](#auto-dependency-scanning-ultimate) +* [Auto License Compliance](#auto-license-compliance-ultimate) +* [Auto Container Scanning](#auto-container-scanning-ultimate) +* [Auto Review Apps](#auto-review-apps) +* [Auto DAST](#auto-dast-ultimate) + * [Overriding the DAST target](#overriding-the-dast-target) + * [Disabling Auto DAST](#disabling-auto-dast) +* [Auto Browser Performance Testing](#auto-browser-performance-testing-premium) +* [Auto Load Performance Testing](#auto-load-performance-testing-premium) +* [Auto Deploy](#auto-deploy) + * [GitLab deploy tokens](#gitlab-deploy-tokens) + * [Kubernetes 1.16+](#kubernetes-116) + * [Migrations](#migrations) + * [Workers](#workers) + * [Network Policy](#network-policy) + * [Web Application Firewall (ModSecurity) customization](#web-application-firewall-modsecurity-customization) + * [Running commands in the container](#running-commands-in-the-container) +* [Auto Monitoring](#auto-monitoring) + +# Stages of Auto DevOps[](#stages-of-auto-devops "Permalink") + +以下各节描述了[Auto DevOps](index.html)的阶段. 仔细阅读它们,以了解它们的工作原理. + +## Auto Build[](#auto-build "Permalink") + +自动构建使用现有的`Dockerfile`或 Heroku 构建包创建应用程序的构建. 生成的 Docker 映像被推送到[Container Registry](../../user/packages/container_registry/index.html) ,并用提交 SHA 或标记进行标记. + +### Auto Build using a Dockerfile[](#auto-build-using-a-dockerfile "Permalink") + +如果项目的存储库在其根目录中包含`Dockerfile` ,则"自动构建"将使用`Dockerfile` `docker build`来创建 Docker 映像. + +如果您还使用 Auto Review Apps 和 Auto Deploy,并且选择提供自己的`Dockerfile` ,那么您必须: + +* 将您的应用程序公开到端口`5000` ,因为[默认的 Helm 图表](https://gitlab.com/gitlab-org/charts/auto-deploy-app)假定此端口可用. +* 通过[自定义 Auto Deploy Helm 图表来](customize.html#custom-helm-chart)覆盖默认值. + +### Auto Build using Heroku buildpacks[](#auto-build-using-heroku-buildpacks "Permalink") + +自动构建使用项目的`Dockerfile`如果存在)构建应用程序. 如果不存在`Dockerfile` ,它将使用[Herokuish](https://github.com/gliderlabs/herokuish)和[Heroku buildpacks](https://devcenter.heroku.com/articles/buildpacks)检测应用程序并将其构建到 Docker 映像中. + +每个 buildpack 都需要您项目的存储库包含某些文件,以便 Auto Build 成功构建您的应用程序. 例如,您的应用程序的根目录必须包含与您的应用程序语言相对应的文件: + +* 对于 Python 项目,为`Pipfile`或`requirements.txt`文件. +* 对于 Ruby 项目,请使用`Gemfile`或`Gemfile.lock`文件. + +有关其他语言和框架的要求,请阅读[Heroku buildpacks 文档](https://devcenter.heroku.com/articles/buildpacks#officially-supported-buildpacks) . + +**提示:**如果尽管项目满足 buildpack 要求,但 Auto Build 失败,请设置项目变量`TRACE=true`启用详细日志记录,这可能有助于您进行故障排除. + +### Auto Build using Cloud Native Buildpacks (beta)[](#auto-build-using-cloud-native-buildpacks-beta "Permalink") + +在[GitLab 12.10 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28165)引入. + +自动构建支持通过[`pack`命令](https://github.com/buildpacks/pack)使用[Cloud Native Buildpacks](https://buildpacks.io)构建应用程序. 要使用 Cloud Native Buildpacks,请将 CI 变量`AUTO_DEVOPS_BUILD_IMAGE_CNB_ENABLED`设置为非空值. 默认的构建器是`heroku/buildpacks:18`但是可以使用 CI 变量`AUTO_DEVOPS_BUILD_IMAGE_CNB_BUILDER`选择其他构建器. + +Cloud Native Buildpacks(CNB)是 Heroku buildpack 的演进,最终将取代 Auto DevOps 中基于 Herokuish 的构建. 有关更多信息,请参见此[问题](https://gitlab.com/gitlab-org/gitlab/-/issues/212692) . + +使用 Cloud Native Buildpacks 的构建与使用 Heroku buildpacks 的构建支持相同的选项,但有以下警告: + +* 该构建包必须是 Cloud Native Buildpack. 可以使用 Heroku 的 cnb [`cnb-shim`](https://github.com/heroku/cnb-shim)将 Heroku 构建包转换为 Cloud Native 构建包. +* `BUILDPACK_URL`必须[采用`pack`支持](https://buildpacks.io/docs/app-developer-guide/specific-buildpacks/)的格式. +* `/bin/herokuish`命令不出现在结果图像中,并且不再需要(也不可能)使用`/bin/herokuish procfile exec`作为前缀命令. + +**Note:** Auto Test still uses Herokuish, as test suite detection is not yet part of the Cloud Native Buildpack specification. For more information, see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/212689). + +## Auto Test[](#auto-test "Permalink") + +自动测试通过分析项目以检测语言和框架,使用[Herokuish](https://github.com/gliderlabs/herokuish)和[Heroku](https://devcenter.heroku.com/articles/buildpacks)构建[包](https://github.com/gliderlabs/herokuish)为您的应用程序运行适当的测试. 系统会自动检测到多种语言和框架,但是如果未检测到您的语言,则可以创建[自定义 buildpack](customize.html#custom-buildpacks) . 检查[当前支持的语言](#currently-supported-languages) . + +自动测试使用您的应用程序中已有的测试. 如果没有测试,则由您决定添加它们. + +### Currently supported languages[](#currently-supported-languages "Permalink") + +请注意,并不是所有的 buildpack 都支持自动测试,因为它是一个相对较新的增强功能. Heroku 的所有[官方支持的语言都](https://devcenter.heroku.com/articles/heroku-ci#supported-languages)支持自动测试. Heroku 的 Herokuish buildpack 支持的语言都支持自动测试,但值得注意的是 multi-buildpack 不支持. + +支持的构建包是: + +``` +- heroku-buildpack-multi +- heroku-buildpack-ruby +- heroku-buildpack-nodejs +- heroku-buildpack-clojure +- heroku-buildpack-python +- heroku-buildpack-java +- heroku-buildpack-gradle +- heroku-buildpack-scala +- heroku-buildpack-play +- heroku-buildpack-php +- heroku-buildpack-go +- buildpack-nginx +``` + +如果您的应用程序需要的构建包不在上面的列表中,则可能要使用[自定义的 buildpack](customize.html#custom-buildpacks) . + +## Auto Code Quality[](#auto-code-quality-starter "Permalink") + +自动代码质量使用[代码质量图像](https://gitlab.com/gitlab-org/ci-cd/codequality)对当前代码运行静态分析和其他代码检查. 创建报告后,报告将作为工件上传,您可以稍后下载并签出. 合并请求小部件还显示[源分支和目标分支之间的](../../user/project/merge_requests/code_quality.html)任何[差异](../../user/project/merge_requests/code_quality.html) . + +## Auto SAST[](#auto-sast-ultimate "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.3 中引入. + +Static Application Security Testing (SAST) uses the [SAST Docker image](https://gitlab.com/gitlab-org/security-products/sast) to run static analysis on the current code, and checks for potential security issues. The Auto SAST stage will be skipped on licenses other than [Ultimate](https://about.gitlab.com/pricing/), and requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 or above. + +创建报告后,报告将作为工件上传,您可以稍后下载并签出. 合并请求小部件还显示任何安全警告. + +要了解有关[SAST 工作原理的](../../user/application_security/sast/index.html)更多信息,请参阅文档. + +## Auto Secret Detection[](#auto-secret-detection-ultimate "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1 中引入. + +秘密检测使用[秘密检测 Docker 映像](https://gitlab.com/gitlab-org/security-products/analyzers/secrets)在当前代码上运行秘密检测,并检查泄漏的秘密. 自动秘密检测阶段仅在[Ultimate](https://about.gitlab.com/pricing/)层上运行,并且需要[GitLab Runner](https://docs.gitlab.com/runner/) 11.5 或更高版本. + +创建报告后,报告将作为工件上传,您可以稍后下载和评估. 合并请求小部件还显示任何安全警告. + +要了解更多信息,请参阅[秘密检测](../../user/application_security/secret_detection/index.html) . + +## Auto Dependency Scanning[](#auto-dependency-scanning-ultimate "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.7 中引入. + +Dependency Scanning 使用[Dependency Scanning Docker 映像](https://gitlab.com/gitlab-org/security-products/dependency-scanning)对项目依赖项进行分析,并检查潜在的安全问题. 在非[Ultimate](https://about.gitlab.com/pricing/)许可证上,将跳过"自动依赖项扫描"阶段,并且需要[GitLab Runner](https://docs.gitlab.com/runner/) 11.5 或更高版本. + +创建报告后,报告将作为工件上传,您可以稍后下载并签出. 合并请求小部件显示检测到的所有安全警告, + +要了解有关" [依赖关系扫描"的](../../user/application_security/dependency_scanning/index.html)更多信息,请参阅文档. + +## Auto License Compliance[](#auto-license-compliance-ultimate "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0 中引入. + +许可证合规性使用[许可证合规性 Docker 映像](https://gitlab.com/gitlab-org/security-products/license-management)在项目依赖项中搜索其许可证. 除[Ultimate](https://about.gitlab.com/pricing/)以外的其他许可证将跳过"自动许可证合规性"阶段. + +创建报告后,报告将作为工件上传,您可以稍后下载并签出. 合并请求显示所有检测到的许可证. + +要了解有关[许可证合规性的](../../user/compliance/license_compliance/index.html)更多[信息](../../user/compliance/license_compliance/index.html) ,请参阅文档. + +## Auto Container Scanning[](#auto-container-scanning-ultimate "Permalink") + +在 GitLab 10.4 中引入. + +Vulnerability Static Analysis for containers uses [Clair](https://github.com/quay/clair) to check for potential security issues on Docker images. The Auto Container Scanning stage is skipped on licenses other than [Ultimate](https://about.gitlab.com/pricing/). + +创建报告后,报告将作为工件上传,您可以稍后下载并签出. 合并请求显示所有检测到的安全问题. + +To learn more about [Container Scanning](../../user/application_security/container_scanning/index.html), see the documentation. + +## Auto Review Apps[](#auto-review-apps "Permalink") + +这是一个可选步骤,因为许多项目没有可用的 Kubernetes 集群. 如果不满足[要求](requirements.html) ,则将跳过该作业. + +[Review App](../../ci/review_apps/index.html)是基于分支机构代码的临时应用程序环境,因此开发人员,设计人员,质量检查人员,产品经理和其他审阅者可以在审阅过程中实际查看代码更改并与之交互. 自动审核应用程序为每个分支创建一个审核应用程序. + +Auto Review Apps 仅将您的应用程序部署到 Kubernetes 集群. 如果没有可用的群集,则不会进行部署. + +Review App 具有基于项目 ID,分支或标签名称,唯一编号和 Auto DevOps 基本域(例如`13083-review-project-branch-123456.example.com`的组合的唯一 URL. 合并请求小部件显示指向 Review App 的链接,以便于发现. 当删除分支或标签时,例如在合并合并请求之后,Review App 也将被删除. + +可以使用带有 Helm 的[auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app)图表来部署评论应用,您可以对其进行[自定义](customize.html#custom-helm-chart) . 该应用程序将部署到环境的[Kubernetes 命名空间](../../user/project/clusters/index.html#deployment-variables)中. + +从 GitLab 11.4 开始,使用[本地 Tiller](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22036) . 早期版本的 GitLab 在项目名称空间中安装了一个 Tiller. + +**注意:**您的应用程序*不*应该(直接使用 Kubernetes)以外的操纵舵的. 这可能会导致 Helm 无法检测到更改而造成混乱,随后使用 Auto DevOps 进行的部署可能会撤消您的更改. 同样,如果您更改了某些内容并想通过再次部署来撤消它,Helm 可能不会在一开始就检测到任何更改,因此不会意识到它需要重新应用旧配置. + +## Auto DAST[](#auto-dast-ultimate "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4 中引入. + +动态应用程序安全测试(DAST)使用流行的开源工具[OWASP ZAProxy](https://github.com/zaproxy/zaproxy)分析当前代码并检查潜在的安全问题. 除[Ultimate](https://about.gitlab.com/pricing/)以外的其他许可证将跳过 Auto DAST 阶段. + +* 在默认分支上,除非您[覆盖目标分支](#overriding-the-dast-target) ,否则 DAST 会扫描专门为此目的部署的应用程序. DAST 运行后,该应用将被删除. +* 在功能分支上,DAST 扫描[审阅应用程序](#auto-review-apps) . + +DAST 扫描完成后,所有安全警告都会显示在" [安全仪表板"](../../user/application_security/security_dashboard/index.html)和"合并请求"小部件上. + +To learn more about [Dynamic Application Security Testing](../../user/application_security/dast/index.html), see the documentation. + +### Overriding the DAST target[](#overriding-the-dast-target "Permalink") + +要使用自定义目标而不是自动部署的审阅应用程序,请将`DAST_WEBSITE`环境变量设置为 URL 以便 DAST 进行扫描. + +**危险:**如果启用了[DAST Full Scan](../../user/application_security/dast/index.html#full-scan) ,则 GitLab 强烈建议**不要**将`DAST_WEBSITE`设置为任何暂存或生产环境. DAST 全面扫描会主动攻击目标,这可能会破坏您的应用程序并导致数据丢失或损坏. + +### Disabling Auto DAST[](#disabling-auto-dast "Permalink") + +您可以禁用 DAST: + +* 通过将`DAST_DISABLED`环境变量设置为`"true"`在所有分支上. +* 通过将`DAST_DISABLED_FOR_DEFAULT_BRANCH`环境变量设置为`"true"`仅在默认分支上. +* 通过将环境变量`REVIEW_DISABLED`设置为`"true"`仅在要素分支上. 这也会禁用 Review App. + +## Auto Browser Performance Testing[](#auto-browser-performance-testing-premium "Permalink") + +在[GitLab Premium](https://about.gitlab.com/pricing/) 10.4 中引入. + +自动[浏览器性能测试](../../user/project/merge_requests/browser_performance_testing.html)使用[Sitespeed.io 容器](https://hub.docker.com/r/sitespeedio/sitespeed.io/)测量网页的浏览器性能,创建包括每个页面的整体性能得分的 JSON 报告,并将报告作为工件上传. 默认情况下,它将测试"审阅"和"生产"环境的根页面. 如果要测试其他 URL,请将路径添加到根目录中名为`.gitlab-urls.txt`的文件中,每行一个文件. 例如: + +``` +/ +/features +/direction +``` + +[合并请求小部件](../../user/project/merge_requests/browser_performance_testing.html)中还会[显示](../../user/project/merge_requests/browser_performance_testing.html)源分支与目标分支之间的任何浏览器性能差异. + +## Auto Load Performance Testing[](#auto-load-performance-testing-premium "Permalink") + +在[GitLab Premium](https://about.gitlab.com/pricing/) 13.2 中引入. + +自动[负载性能测试](../../user/project/merge_requests/load_performance_testing.html)使用[k6 容器](https://hub.docker.com/r/loadimpact/k6/)测量应用程序的服务器性能,创建包含多个关键结果指标的 JSON 报告,并将报告作为工件上传. + +需要一些初始设置. 需要编写针对您的特定应用的[k6](https://k6.io/)测试. 还需要配置测试,以便它可以通过环境变量获取环境的动态 URL. + +[合并请求小部件](../../user/project/merge_requests/load_performance_testing.html)中还会[显示](../../user/project/merge_requests/load_performance_testing.html)源分支与目标分支之间的任何负载性能测试结果差异. + +## Auto Deploy[](#auto-deploy "Permalink") + +这是一个可选步骤,因为许多项目没有可用的 Kubernetes 集群. 如果不满足[要求](requirements.html) ,则跳过该作业. + +将分支或合并请求合并到项目的默认分支(通常是`master` )后,Auto Deploy 会将应用程序部署到 Kubernetes 集群中的`production`环境中,该环境具有基于项目名称和唯一项目 ID 的命名空间,例如`project-4321` . + +默认情况下,"自动部署"不包括到暂存或 Canary 环境的部署,但是如果要启用这些任务,则" [Auto DevOps"模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)包含这些任务的作业定义. + +您可以使用[环境变量](customize.html#environment-variables)来自动缩放 Pod 副本,并将自定义参数应用于 Auto DevOps `helm upgrade`命令. 这是[自定义 Auto Deploy Helm 图表](customize.html#custom-helm-chart)的简便方法. + +Helm 使用[auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app)图表将应用程序部署到环境的[Kubernetes 命名空间](../../user/project/clusters/index.html#deployment-variables)中. + +从 GitLab 11.4 开始,将使用[本地 Tiller](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22036) . 早期版本的 GitLab 在项目名称空间中安装了一个 Tiller. + +**注意:**您的应用程序*不*应该(直接使用 Kubernetes)以外的操纵舵的. 这可能会导致 Helm 无法检测到更改而造成混乱,随后使用 Auto DevOps 进行的部署可能会撤消您的更改. 同样,如果您更改了某些内容并想通过再次部署来撤消它,Helm 可能不会在一开始就检测到任何更改,因此不会意识到它需要重新应用旧配置. + +### GitLab deploy tokens[](#gitlab-deploy-tokens "Permalink") + +在 GitLab 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19507) . + +启用 Auto DevOps 时,将为内部和私有项目创建[GitLab 部署令牌](../../user/project/deploy_tokens/index.html#gitlab-deploy-token) ,并保存 Auto DevOps 设置. 您可以使用部署令牌对注册表进行永久访问. 手动吊销 GitLab 部署令牌后,将不会自动创建它. + +如果找不到 GitLab 部署令牌,则使用`CI_REGISTRY_PASSWORD` . + +**Note:** `CI_REGISTRY_PASSWORD` is only valid during deployment. Kubernetes will be able to successfully pull the container image during deployment, but if the image must be pulled again, such as after pod eviction, Kubernetes will fail to do so as it attempts to fetch the image using `CI_REGISTRY_PASSWORD`. + +### Kubernetes 1.16+[](#kubernetes-116 "Permalink") + +版本历史 + +* 在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/charts/auto-deploy-app/-/merge_requests/51) . +* 在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/merge_requests/49)了对部署支持 Kubernetes 1.16+的 PostgreSQL 版本的支持. +* 自 GitLab 13.0 起为新部署提供开箱即用的支持. + +**弃用:**在[GitLab 13.0 中](https://gitlab.com/gitlab-org/charts/auto-deploy-app/-/issues/47) , `deploymentApiVersion`设置的默认值已从`extensions/v1beta`更改为`apps/v1` . + +在 Kubernetes 1.16 和更高版本中, [删除](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/)了许多[API](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/) ,包括在`extensions/v1beta1`版本中支持`Deployment` . + +要在 Kubernetes 1.16+群集上使用 Auto Deploy: + +1. 如果您是第一次在 GitLab 13.0 或更高版本上部署应用程序,则无需进行配置. + +2. 在 GitLab 12.10 或更旧版本上,在[`.gitlab/auto-deploy-values.yaml`文件中](customize.html#customize-values-for-helm-chart)设置以下内容: + + ``` + deploymentApiVersion: apps/v1 + ``` + +3. 如果您安装了集群内 PostgreSQL 数据库,并且`AUTO_DEVOPS_POSTGRES_CHANNEL`设置为`1` ,请按照[指南升级 PostgreSQL](upgrading_postgresql.html) . + +4. 如果您是第一次部署应用程序,并且使用的是 GitLab 12.9 或 12.10,请将`AUTO_DEVOPS_POSTGRES_CHANNEL`设置为`2` . + +**危险:**在 GitLab 12.9 和 12.10 上,选择使用`AUTO_DEVOPS_POSTGRES_CHANNEL`版本`2`会删除版本`1` PostgreSQL 数据库. 在选择版本`2`之前,请遵循[升级 PostgreSQL](upgrading_postgresql.html)的[指南来](upgrading_postgresql.html)备份和还原数据库(在 GitLab 13.0 上,需要附加变量来触发数据库删除). + +### Migrations[](#migrations "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21955) + +您可以通过分别设置项目变量`DB_INITIALIZE`和`DB_MIGRATE`来配置 PostgreSQL 的数据库初始化和迁移,以使其在应用程序窗格中运行. + +如果存在, `DB_INITIALIZE`作为 Shell 命令作为 Helm 安装后挂钩在外壳中运行. 由于某些应用程序如果没有成功的数据库初始化步骤就无法运行,因此 GitLab 部署的第一个发行版没有应用程序部署,而只有数据库初始化步骤. 数据库初始化完成后,GitLab 部署第二个版本,并且应用程序部署正常. + +请注意,安装后挂钩意味着如果任何部署成功,则`DB_INITIALIZE`将不再处理`DB_INITIALIZE` . + +如果存在, `DB_MIGRATE`作为 Shell 命令作为 Helm 预升级挂钩在 Shell 中运行. + +例如,在用[Herokuish](https://github.com/gliderlabs/herokuish)构建的图像中的 Rails 应用程序中: + +* 可以将`DB_INITIALIZE`设置为`RAILS_ENV=production /bin/herokuish procfile exec bin/rails db:setup` +* 可以将`DB_MIGRATE`设置为`RAILS_ENV=production /bin/herokuish procfile exec bin/rails db:migrate` + +除非您的存储库包含`Dockerfile` ,否则映像是使用 Herokuish 构建的,并且必须在这些映像中运行的命令前加上`/bin/herokuish procfile exec`前缀,以复制将在其中运行应用程序的环境. + +### Workers[](#workers "Permalink") + +某些 Web 应用程序必须为"工作流程"运行额外的部署. 例如,Rails 应用程序通常使用单独的工作进程来运行后台任务,例如发送电子邮件. + +Auto Deploy 中使用的[默认 Helm 图表](https://gitlab.com/gitlab-org/charts/auto-deploy-app) [支持运行工作进程](https://gitlab.com/gitlab-org/charts/auto-deploy-app/-/merge_requests/9) . + +要运行工作程序,必须确保工作程序可以响应标准的运行状况检查,该检查将在端口`5000`上期望成功的 HTTP 响应. 对于[Sidekiq](https://github.com/mperham/sidekiq) ,可以使用[`sidekiq_alive` gem](https://rubygems.org/gems/sidekiq_alive) . + +要使用 Sidekiq,还必须确保您的部署可以访问 Redis 实例. Auto DevOps 不会为您部署此实例,因此您必须: + +* 维护您自己的 Redis 实例. +* 设置 CI 变量`K8S_SECRET_REDIS_URL` ,它是该实例的 URL,以确保将其传递到您的部署中. + +在将工作程序配置为对运行状况检查作出响应之后,为您的 Rails 应用程序运行 Sidekiq 工作程序. 您可以通过在[`.gitlab/auto-deploy-values.yaml`文件中](customize.html#customize-values-for-helm-chart)设置以下内容来启用工作[`.gitlab/auto-deploy-values.yaml`](customize.html#customize-values-for-helm-chart) : + +``` +workers: + sidekiq: + replicaCount: 1 + command: + - /bin/herokuish + - procfile + - exec + - sidekiq + preStopCommand: + - /bin/herokuish + - procfile + - exec + - sidekiqctl + - quiet + terminationGracePeriodSeconds: 60 +``` + +### Network Policy[](#network-policy "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/charts/auto-deploy-app/-/merge_requests/30) . + +默认情况下,所有 Kubernetes 容器都是[非隔离的](https://kubernetes.io/docs/concepts/services-networking/network-policies/#isolated-and-non-isolated-pods) ,并且接受来自任何来源的流量. 您可以使用[NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/)限制与选定 Pod,名称空间和 Internet 之间的连接. + +**注意:**您必须使用 Kubernetes 网络插件来实现对`NetworkPolicy`支持. Kubernetes( `kubenet` )的默认网络插件[未实现](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/#kubenet) `kubenet`支持. 可以将[Cilium](https://cilium.io/)网络插件安装为[群集应用程序,](../../user/clusters/applications.html#install-cilium-using-gitlab-cicd)以支持网络策略. + +您可以通过在`.gitlab/auto-deploy-values.yaml`文件中设置以下内容来启用网络策略`.gitlab/auto-deploy-values.yaml` : + +``` +networkPolicy: + enabled: true +``` + +Auto Deploy 管道部署的默认策略允许本地名称空间内以及`gitlab-managed-apps`名称空间的`gitlab-managed-apps` . 所有其他入站连接均被阻止. 出站流量(例如,到 Internet 的流量)不受默认策略的影响. + +您还可以在`.gitlab/auto-deploy-values.yaml`文件中提供自定义[策略规范](https://kubernetes.io/docs/concepts/services-networking/network-policies/) ,例如: + +``` +networkPolicy: + enabled: true + spec: + podSelector: + matchLabels: + app.gitlab.com/env: staging + ingress: + - from: + - podSelector: + matchLabels: {} + - namespaceSelector: + matchLabels: + app.gitlab.com/managed_by: gitlab +``` + +有关安装网络策略的更多信息,请参阅[使用 GitLab CI / CD 安装 Cilium](../../user/clusters/applications.html#install-cilium-using-gitlab-cicd) . + +### Web Application Firewall (ModSecurity) customization[](#web-application-firewall-modsecurity-customization "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/charts/auto-deploy-app/-/merge_requests/44) . + +[安装](../../user/clusters/applications.html#web-application-firewall-modsecurity)了[ModSecurity 的](../../user/clusters/applications.html#web-application-firewall-modsecurity)群集可以在[Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)或部署基础上进行自定义. + +要在 Auto Deploy 中启用 ModSecurity,必须在项目中使用以下属性创建`.gitlab/auto-deploy-values.yaml`文件. + +| Attribute | Description | Default | +| --- | --- | --- | +| `enabled` | 启用 ModSecurity 的自定义配置,默认为" [核心规则集"](https://coreruleset.org/) | `false` | +| `secRuleEngine` | 配置[规则引擎](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#secruleengine) | `DetectionOnly` | +| `secRules` | 创建一个或多个其他[规则](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#SecRule) | `nil` | + +在以下`auto-deploy-values.yaml`示例中,为 ModSecurity 启用了一些自定义设置. 其中包括将其引擎设置为处理规则,而不是仅记录规则,同时添加两个基于标头的特定规则: + +``` +ingress: + modSecurity: + enabled: true + secRuleEngine: "On" + secRules: + - variable: "REQUEST_HEADERS:User-Agent" + operator: "printer" + action: "log,deny,id:'2010',status:403,msg:'printer is an invalid agent'" + - variable: "REQUEST_HEADERS:Content-Type" + operator: "text/plain" + action: "log,deny,id:'2011',status:403,msg:'Text is not supported as content type'" +``` + +### Running commands in the container[](#running-commands-in-the-container "Permalink") + +除非您的存储库包含[自定义 Dockerfile](#auto-build-using-a-dockerfile) ,否则默认情况下使用 Herokuish 使用[Auto Build 构建的](#auto-build)应用程序可能要求将命令包装如下: + +``` +/bin/herokuish procfile exec $COMMAND +``` + +您可能需要包装命令的一些原因: + +* 使用`kubectl exec`附加. +* 使用 GitLab 的[Web 终端](../../ci/environments/index.html#web-terminals) . + +例如,要从应用程序根目录启动 Rails 控制台,请运行: + +``` +/bin/herokuish procfile exec bin/rails c +``` + +## Auto Monitoring[](#auto-monitoring "Permalink") + +部署应用程序后,"自动监视"可帮助您立即监视应用程序的服务器和响应指标. 自动监控使用[Prometheus](../../user/project/integrations/prometheus.html)直接从[Kubernetes](../../user/project/integrations/prometheus_library/kubernetes.html)检索系统指标,例如 CPU 和内存使用情况,以及从[NGINX 服务器](../../user/project/integrations/prometheus_library/nginx_ingress.html)检索响应指标,例如 HTTP 错误率,延迟和吞吐量. + +指标包括: + +* **响应指标:**延迟,吞吐量,错误率 +* **系统指标:** CPU 利用率,内存利用率 + +安装 Prometheus 之后,GitLab 会为您提供一些初始警报: + +* 入口状态码`500` > 0.1% +* NGINX 状态码`500` > 0.1% + +要使用自动监视: + +1. [Install and configure the Auto DevOps requirements](requirements.html). +2. 如果尚未[启用 Auto DevOps](index.html#enablingdisabling-auto-devops) ,请[启用它](index.html#enablingdisabling-auto-devops) . +3. 导航到您项目的 **CI / CD>管道** ,然后单击**运行管道** . +4. 管道成功完成后,打开已[部署环境](../../ci/environments/index.html#monitoring-environments)的[监视仪表板](../../ci/environments/index.html#monitoring-environments)以查看已部署应用程序的指标. 要查看整个 Kubernetes 集群的指标,请导航至 **操作>指标** . + +[![Auto Metrics](img/96aa3b50d60a091349e8d39c74877a5d.png)](img/auto_monitoring.png) \ No newline at end of file diff --git a/_book/docs/212.md b/_book/docs/212.md new file mode 100644 index 0000000000000000000000000000000000000000..ba474c1b9b9bffbda9cfc82ebf20db71516cd56f --- /dev/null +++ b/_book/docs/212.md @@ -0,0 +1,207 @@ +# Upgrading PostgreSQL for Auto DevOps + +> 原文:[https://docs.gitlab.com/ee/topics/autodevops/upgrading_postgresql.html](https://docs.gitlab.com/ee/topics/autodevops/upgrading_postgresql.html) + +* [Prerequisites](#prerequisites) +* [Take your application offline](#take-your-application-offline) +* [Backup](#backup) +* [Retain persistent volumes](#retain-persistent-volumes) +* [Install new PostgreSQL](#install-new-postgresql) +* [Restore](#restore) +* [Reinstate your application](#reinstate-your-application) + +# Upgrading PostgreSQL for Auto DevOps[](#upgrading-postgresql-for-auto-devops "Permalink") + +Auto DevOps 为您的应用程序提供[集群内 PostgreSQL 数据库](customize.html#postgresql-database-support) . + +用于配置 PostgreSQL 的图表的版本: + +* 在 GitLab 12.8 及更早版本中为 0.7.1. +* 在 GitLab 12.9 及更高版本中可以设置为 0.7.1 至 8.2.1. + +GitLab 鼓励用户将其数据库迁移到较新的 PostgreSQL 图表. + +本指南提供有关如何迁移 PostgreSQL 数据库的说明,其中包括: + +1. 对数据进行数据库转储. +2. 使用图表的较新版本 8.2.1 安装新的 PostgreSQL 数据库,并删除旧的 PostgreSQL 安装. +3. 将数据库转储还原到新的 PostgreSQL 中. + +## Prerequisites[](#prerequisites "Permalink") + +1. Install [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/). +2. 确保您可以使用`kubectl`访问 Kubernetes 集群. 这取决于 Kubernetes 提供者. +3. 准备停机. 下面的步骤包括使应用程序脱机,以便在创建数据库转储后不修改集群内数据库. +4. 确保尚未将`POSTGRES_ENABLED`设置为`false` ,因为此设置将删除任何现有的通道 1 数据库. 有关更多信息,请参见[检测到现有的 PostgreSQL 数据库](index.html#detected-an-existing-postgresql-database) . + +**提示:**如果已将 Auto DevOps 配置为具有暂存,请考虑先尝试暂存并还原备份和还原步骤,或者在审阅应用程序中尝试此步骤. + +## Take your application offline[](#take-your-application-offline "Permalink") + +如果需要,请使应用程序脱机,以防止在创建数据库转储后修改数据库. + +1. 获取环境的 Kubernetes 命名空间. 它通常看起来像`<project-name>-<project-id>-<environment>` . 在我们的示例中,名称空间称为`minimal-ruby-app-4349298-production` . + + ``` + $ kubectl get ns + + NAME STATUS AGE + minimal-ruby-app-4349298-production Active 7d14h + ``` + +2. 为了易于使用,请导出名称空间名称: + + ``` + export APP_NAMESPACE=minimal-ruby-app-4349298-production + ``` + +3. 使用以下命令获取应用程序的部署名称. 在我们的示例中,部署名称为`production` . + + ``` + $ kubectl get deployment --namespace "$APP_NAMESPACE" + NAME READY UP-TO-DATE AVAILABLE AGE + production 2/2 2 2 7d21h + production-postgres 1/1 1 1 7d21h + ``` + +4. 为了防止数据库被修改,请使用以下命令将副本的副本数设置为 0\. 我们使用上一步中的部署名称( `deployments/<DEPLOYMENT_NAME>` ). + + ``` + $ kubectl scale --replicas=0 deployments/production --namespace "$APP_NAMESPACE" + deployment.extensions/production scaled + ``` + +5. 如果有的话,还需要将 worker 的副本设置为零. + +## Backup[](#backup "Permalink") + +1. 获取 PostgreSQL 的服务名称. 服务的名称应以`-postgres` . 在我们的示例中,服务名称为`production-postgres` . + + ``` + $ kubectl get svc --namespace "$APP_NAMESPACE" + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + production-auto-deploy ClusterIP 10.30.13.90 <none> 5000/TCP 7d14h + production-postgres ClusterIP 10.30.4.57 <none> 5432/TCP 7d14h + ``` + +2. 使用以下命令获取 PostgreSQL 的 pod 名称. 在我们的示例中,吊舱名称为`production-postgres-5db86568d7-qxlxv` . + + ``` + $ kubectl get pod --namespace "$APP_NAMESPACE" -l app=production-postgres + NAME READY STATUS RESTARTS AGE + production-postgres-5db86568d7-qxlxv 1/1 Running 0 7d14h + ``` + +3. 通过以下方式连接到吊舱: + + ``` + kubectl exec -it production-postgres-5db86568d7-qxlxv --namespace "$APP_NAMESPACE" bash + ``` + +4. 连接后,使用以下命令创建转储文件. + + * `SERVICE_NAME`是在上一步中获得的服务名称. + * `USERNAME`是您为 PostgreSQL 配置的用户名. 默认值为`user` . + * `DATABASE_NAME`通常是环境名称. + + * 系统将要求您输入数据库密码,默认`testing-password`是`testing-password` . + + ``` + ## Format is: + # pg_dump -h SERVICE_NAME -U USERNAME DATABASE_NAME > /tmp/backup.sql + + pg_dump -h production-postgres -U user production > /tmp/backup.sql + ``` + +5. 备份转储完成后,使用`Control-D` `exit` Kubernetes exec 进程或`exit` . + +6. 使用以下命令下载转储文件: + + ``` + kubectl cp --namespace "$APP_NAMESPACE" production-postgres-5db86568d7-qxlxv:/tmp/backup.sql backup.sql + ``` + +## Retain persistent volumes[](#retain-persistent-volumes "Permalink") + +默认情况下,当`Delete`使用该卷的 Pod 和 Pod 声明时,用于存储 PostgreSQL 基础数据的[持久卷](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)将标记为`Delete` . + +这很重要,因为当您选择使用较新的 8.2.1 PostgreSQL 时,会删除较旧的 0.7.1 PostgreSQL,从而导致永久卷也被删除. + +您可以使用以下命令进行验证: + +``` +$ kubectl get pv +NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE +pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 8Gi RWO Delete Bound minimal-ruby-app-4349298-staging/staging-postgres standard 7d22h +pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096 8Gi RWO Delete Bound minimal-ruby-app-4349298-production/production-postgres standard 7d22h +``` + +为了保留持久卷,即使删除了较旧的 0.7.1 PostgreSQL,我们也可以将保留策略更改为`Retain` . 在此示例中,我们通过查看声明名称来找到持久卷名称. 由于我们有兴趣保留用于`minimal-ruby-app-4349298`应用程序的阶段和生产的卷,因此此处的卷名称为`pvc-0da80c08-5239-11ea-9c8d-42010a8e0096`和`pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096` : + +``` +$ kubectl patch pv pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' +persistentvolume/pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 patched +$ kubectl patch pv pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096 -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' +persistentvolume/pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096 patched +$ kubectl get pv +NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE +pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 8Gi RWO Retain Bound minimal-ruby-app-4349298-staging/staging-postgres standard 7d22h +pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096 8Gi RWO Retain Bound minimal-ruby-app-4349298-production/production-postgres standard 7d22h +``` + +## Install new PostgreSQL[](#install-new-postgresql "Permalink") + +**注意:**使用较新版本的 PostgreSQL 将删除较旧的 0.7.1 PostgreSQL. 为了防止基础数据被删除,您可以选择保留[持久卷](#retain-persistent-volumes) .**提示:**您还可以将`AUTO_DEVOPS_POSTGRES_CHANNEL` , `AUTO_DEVOPS_POSTGRES_DELETE_V1`和`POSTGRES_VERSION`变量的[作用域](../../ci/environments/index.html#scoping-environments-with-specs)设置为特定环境,例如`staging` . + +1. 将`AUTO_DEVOPS_POSTGRES_CHANNEL`设置为`2` . 选择使用较新的基于 8.2.1 的 PostgreSQL,并删除较旧的基于 0.7.1 的 PostgreSQL. +2. 将`AUTO_DEVOPS_POSTGRES_DELETE_V1`设置为非空值. 此标志是防止意外删除数据库的保护措施. +3. 将`POSTGRES_VERSION`设置为`11.7` . 这是支持的最低 PostgreSQL 版本. +4. 将`PRODUCTION_REPLICAS`设置为`0` . 对于其他环境, `REPLICAS`在[环境范围内](../../ci/environments/index.html#scoping-environments-with-specs)使用`REPLICAS` . +5. 如果已设置`DB_INITIALIZE`或`DB_MIGRATE`变量,请删除变量,或将变量临时重命名为`XDB_INITIALIZE`或`XDB_MIGRATE`以有效地禁用它们. +6. Run a new CI pipeline for the branch. In this case, we run a new CI pipeline for `master`. +7. 一旦管道成功,您的应用程序现在将安装新的 PostgreSQL 进行升级. 复制品也将为零,这意味着将不为您的应用程序提供任何流量(以防止新数据进入). + +## Restore[](#restore "Permalink") + +1. 获取新 PostgreSQL 的容器名称,在我们的示例中,容器名称为`production-postgresql-0` : + + ``` + $ kubectl get pod --namespace "$APP_NAMESPACE" -l app=postgresql + NAME READY STATUS RESTARTS AGE + production-postgresql-0 1/1 Running 0 19m + ``` + +2. 将转储文件从备份步骤复制到 Pod: + + ``` + kubectl cp --namespace "$APP_NAMESPACE" backup.sql production-postgresql-0:/tmp/backup.sql + ``` + +3. 连接到吊舱: + + ``` + kubectl exec -it production-postgresql-0 --namespace "$APP_NAMESPACE" bash + ``` + +4. 连接到 Pod 后,运行以下命令来还原数据库. + + * 系统将要求您输入数据库密码,默认`testing-password`是`testing-password` . + * `USERNAME`是您为 PostgreSQL 配置的用户名. 默认值为`user` . + * `DATABASE_NAME`通常是环境名称. + + ``` + ## Format is: + # psql -U USERNAME -d DATABASE_NAME < /tmp/backup.sql + + psql -U user -d production < /tmp/backup.sql + ``` + +5. 现在,您可以检查还原完成后是否已正确还原数据. 您可以使用`psql`对数据进行抽查. + +## Reinstate your application[](#reinstate-your-application "Permalink") + +对数据库已还原感到满意后,请运行以下步骤来恢复您的应用程序: + +1. 如果先前已删除或禁用了`DB_INITIALIZE`和`DB_MIGRATE`变量,则将其还原. +2. 将`PRODUCTION_REPLICAS`或`REPLICAS`变量恢复为其原始值. +3. 为分支运行新的 CI 管道. 在这种情况下,我们为`master`运行新的 CI 管道. 管道成功后,您的应用程序应该像以前一样提供流量. \ No newline at end of file diff --git a/_book/docs/213.md b/_book/docs/213.md new file mode 100644 index 0000000000000000000000000000000000000000..e63a1b68af65fe7ac8588b3955c531c4d72eef7d --- /dev/null +++ b/_book/docs/213.md @@ -0,0 +1,477 @@ +# Cache dependencies in GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/caching/](https://docs.gitlab.com/ee/ci/caching/) + +* [Cache vs artifacts](#cache-vs-artifacts) +* [Good caching practices](#good-caching-practices) + * [Sharing caches across the same branch](#sharing-caches-across-the-same-branch) + * [Sharing caches across different branches](#sharing-caches-across-different-branches) + * [Disabling cache on specific jobs](#disabling-cache-on-specific-jobs) + * [Inherit global config, but override specific settings per job](#inherit-global-config-but-override-specific-settings-per-job) +* [Common use cases](#common-use-cases) + * [Caching Node.js dependencies](#caching-nodejs-dependencies) + * [Caching PHP dependencies](#caching-php-dependencies) + * [Caching Python dependencies](#caching-python-dependencies) + * [Caching Ruby dependencies](#caching-ruby-dependencies) + * [Caching Go dependencies](#caching-go-dependencies) +* [Availability of the cache](#availability-of-the-cache) + * [Where the caches are stored](#where-the-caches-are-stored) + * [How archiving and extracting works](#how-archiving-and-extracting-works) + * [Cache mismatch](#cache-mismatch) + * [Examples](#examples) +* [Clearing the cache](#clearing-the-cache) + * [Clearing the cache by changing `cache:key`](#clearing-the-cache-by-changing-cachekey) + * [Clearing the cache manually](#clearing-the-cache-manually) + +# Cache dependencies in GitLab CI/CD[](#cache-dependencies-in-gitlab-cicd "Permalink") + +GitLab CI / CD 提供了一种缓存机制,可用于在作业运行时节省时间. + +缓存是指通过重用先前作业的相同内容来加快执行作业的时间. 当您开发依赖于在构建期间通过 Internet 获取的其他库的软件时,此功能特别有用. + +如果启用了缓存,则默认情况下从 GitLab 9.0 开始,它在项目级别的管道和作业之间共享. 缓存不跨项目共享. + +确保您阅读了[`cache`参考](../yaml/README.html#cache)以了解`.gitlab-ci.yml`定义. + +## Cache vs artifacts[](#cache-vs-artifacts "Permalink") + +**注意:**如果您使用缓存和工件在作业中存储相同的路径时要小心,因为在覆盖**工件**和内容**之前** ,将**还原缓存** . + +不要使用缓存在阶段之间传递工件,因为缓存旨在存储编译项目所需的运行时依赖项: + +* `cache`: **用于存储项目依赖项** + + 缓存用于通过存储下载的依赖项来加快后续作业在给定**管道中的**运行速度,这样就不必再次从 Internet 上获取它们(例如 npm 软件包,Go 供应商软件包等).配置为在阶段之间传递中间构建结果,则应该使用工件来完成. + +* `artifacts`: **用于在阶段之间传递的阶段结果.** + + 工件是由作业生成的文件,可以存储并上载,然后可以在**同一管道的**后续阶段中由作业获取和使用. 换句话说, [您不能在阶段 1 的 job-A 中创建工件,然后在阶段 1 的 job-B 中使用此工件](https://gitlab.com/gitlab-org/gitlab/-/issues/25837) . 此数据在不同的管道中将不可用,但可以从 UI 下载. + +`artifacts`的名称听起来像是仅在工作之外有用,例如用于下载最终图像,但是人工制品也可以在管道的后期阶段使用. 因此,如果通过下载所有必需的模块来构建应用程序,则可能需要将它们声明为工件,以便后续阶段可以使用它们. 有一些优化措施,例如声明[到期时间,](../yaml/README.html#artifactsexpire_in)这样您就不会将工件保留太长时间,或者使用[依赖项](../yaml/README.html#dependencies)来控制哪些作业会获取工件. + +Caches: + +* 如果未全局定义或未按作业定义(使用`cache:` :),则禁用该功能. +* 如果全局启用,则可用于`.gitlab-ci.yml`所有作业. +* 可以由创建缓存的同一作业在后续管道中使用(如果未全局定义). +* 如果[启用了分布式缓存](https://docs.gitlab.com/runner/configuration/autoscale.html) ,则将它们存储在 Runner 安装的位置**并**上传到 S3. +* 如果按作业定义,则使用: + * 通过后续管道中的相同作业. + * 如果它们具有相同的依赖关系,则由同一管道中的后续作业组成. + +Artifacts: + +* 如果未按作业定义(使用`artifacts:` :),则将其禁用. +* 只能针对每个作业启用,不能全局启用. +* 在管道中创建,并且可以被当前活动管道的后续作业使用. +* 始终上传到 GitLab(称为协调器). +* 可以具有用于控制磁盘使用量的到期值(默认为 30 天). + +**注意:**工件和缓存均定义了相对于项目目录的路径,并且无法链接到其外部的文件. + +## Good caching practices[](#good-caching-practices "Permalink") + +We have the cache from the perspective of the developers (who consume a cache within the job) and the cache from the perspective of the Runner. Depending on which type of Runner you are using, cache can act differently. + +从开发人员的角度来看,要确保高速缓存的最大可用性,在作业中声明`cache` ,请使用以下一项或多项: + +* [为跑步者](../runners/README.html#use-tags-to-limit-the-number-of-jobs-using-the-runner)添加标签,并在共享其缓存的作业上使用标签. +* [使用](../runners/README.html#prevent-a-specific-runner-from-being-enabled-for-other-projects)仅适用于特定项目的[粘性运行器](../runners/README.html#prevent-a-specific-runner-from-being-enabled-for-other-projects) . +* [使用](../yaml/README.html#cachekey)适合您的工作流[的`key`](../yaml/README.html#cachekey) (例如,每个分支上的不同缓存). 为此,您可以利用[CI / CD 预定义变量](../variables/README.html#predefined-environment-variables) . + +**提示:**在管道中使用相同的 Runner 是在一个阶段或管道中缓存文件,并以有保证的方式将该缓存传递到后续阶段或管道的最简单,最有效的方法. + +从 Runner 的角度来看,为了使缓存有效运行,必须满足以下条件之一: + +* 为您的所有工作使用一个赛跑者. +* 使用多个使用[分布式缓存的](https://docs.gitlab.com/runner/configuration/autoscale.html) Runner(无论是否处于自动缩放模式),这些[缓存](https://docs.gitlab.com/runner/configuration/autoscale.html)将缓存存储在 S3 存储桶中(例如 GitLab.com 上的共享 Runner). +* 使用具有相同体系结构的多个运行程序(不在自动伸缩模式下)共享公共网络安装目录(使用 NFS 或类似方式),以存储缓存. + +**提示:**了解[缓存](#availability-of-the-cache)的[可用性,](#availability-of-the-cache)以了解有关内部的更多信息,并更好地了解缓存的工作方式. + +### Sharing caches across the same branch[](#sharing-caches-across-the-same-branch "Permalink") + +使用`key: ${CI_COMMIT_REF_SLUG}`定义一个缓存,以便每个分支的作业始终使用相同的缓存: + +``` +cache: + key: ${CI_COMMIT_REF_SLUG} +``` + +尽管这似乎可以防止意外覆盖缓存,但是这意味着合并请求的第一个流水线很慢,这可能会给开发人员带来糟糕的体验. 下次将新提交推送到分支时,将重新使用缓存. + +To enable per-job and per-branch caching: + +``` +cache: + key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG" +``` + +要启用每个分支和每个阶段的缓存: + +``` +cache: + key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG" +``` + +### Sharing caches across different branches[](#sharing-caches-across-different-branches "Permalink") + +如果要缓存的文件需要在所有分支和所有作业之间共享,则可以对所有这些文件使用相同的密钥: + +``` +cache: + key: one-key-to-rule-them-all +``` + +要在分支之间共享相同的缓存,但按作业将它们分开: + +``` +cache: + key: ${CI_JOB_NAME} +``` + +### Disabling cache on specific jobs[](#disabling-cache-on-specific-jobs "Permalink") + +如果已全局定义了缓存,则意味着每个作业将使用相同的定义. 您可以按工作覆盖此行为,如果要完全禁用它,请使用空哈希: + +``` +job: + cache: {} +``` + +### Inherit global config, but override specific settings per job[](#inherit-global-config-but-override-specific-settings-per-job "Permalink") + +您可以使用[定位符](../yaml/README.html#anchors)覆盖缓存设置,而无需覆盖全局缓存. 例如,如果要覆盖一项作业的`policy` : + +``` +cache: &global_cache + key: ${CI_COMMIT_REF_SLUG} + paths: + - node_modules/ + - public/ + - vendor/ + policy: pull-push + +job: + cache: + # inherit all global cache settings + <<: *global_cache + # override the policy + policy: pull +``` + +要进行更精细的调整,还请阅读有关[`cache: policy`](../yaml/README.html#cachepolicy) . + +## Common use cases[](#common-use-cases "Permalink") + +缓存最常见的用例是在后续作业之间保留内容,以用于诸如依赖项和常用库(Node.js 包,PHP 包,rubygems,Python 库等)之类的东西,因此不必从公共互联网重新获取. + +**注意:**有关更多示例,请查看我们的[GitLab CI / CD 模板](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates) . + +### Caching Node.js dependencies[](#caching-nodejs-dependencies "Permalink") + +假设您的项目正在使用[npm](https://s0www0npmjs0com.icopy.site/)安装 Node.js 依赖项,下面的示例将全局定义`cache` ,以便所有作业都继承它. 默认情况下,npm 将缓存数据存储在主文件夹`~/.npm`但是由于[您无法缓存项目目录之外的内容](../yaml/README.html#cachepaths) ,因此我们告诉 npm 使用`./.npm` ,它按分支缓存: + +``` +# +# https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml +# +image: node:latest + +# Cache modules in between jobs +cache: + key: ${CI_COMMIT_REF_SLUG} + paths: + - .npm/ + +before_script: + - npm ci --cache .npm --prefer-offline + +test_async: + script: + - node ./specs/start.js ./specs/async.spec.js +``` + +### Caching PHP dependencies[](#caching-php-dependencies "Permalink") + +假设您的项目正在使用[Composer](https://s0getcomposer0org.icopy.site/)安装 PHP 依赖项,下面的示例将全局定义`cache` ,以便所有作业都继承它. PHP 库模块安装在`vendor/`并按分支缓存: + +``` +# +# https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates/PHP.gitlab-ci.yml +# +image: php:7.2 + +# Cache libraries in between jobs +cache: + key: ${CI_COMMIT_REF_SLUG} + paths: + - vendor/ + +before_script: + # Install and run Composer + - curl --show-error --silent https://getcomposer.org/installer | php + - php composer.phar install + +test: + script: + - vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never +``` + +### Caching Python dependencies[](#caching-python-dependencies "Permalink") + +假设您的项目正在使用[pip](https://pip.pypa.io/en/stable/)安装 Python 依赖项,以下示例将全局定义`cache` ,以便所有作业都继承它. Python 库安装在`venv/`下的虚拟环境中,pip 的缓存在`.cache/pip/`下定义,并且两者均按分支缓存: + +``` +# +# https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates/Python.gitlab-ci.yml +# +image: python:latest + +# Change pip's cache directory to be inside the project directory since we can +# only cache local items. +variables: + PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" + +# Pip's cache doesn't store the python packages +# https://pip.pypa.io/en/stable/reference/pip_install/#caching +# +# If you want to also cache the installed packages, you have to install +# them in a virtualenv and cache it as well. +cache: + paths: + - .cache/pip + - venv/ + +before_script: + - python -V # Print out python version for debugging + - pip install virtualenv + - virtualenv venv + - source venv/bin/activate + +test: + script: + - python setup.py test + - pip install flake8 + - flake8 . +``` + +### Caching Ruby dependencies[](#caching-ruby-dependencies "Permalink") + +假设您的项目正在使用[Bundler](https://bundler.io)安装 gem 依赖项,以下示例将全局定义`cache` ,以便所有作业都继承它. 宝石安装在`vendor/ruby/`并按分支缓存: + +``` +# +# https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml +# +image: ruby:2.6 + +# Cache gems in between builds +cache: + key: ${CI_COMMIT_REF_SLUG} + paths: + - vendor/ruby + +before_script: + - ruby -v # Print out ruby version for debugging + - bundle install -j $(nproc) --path vendor/ruby # Install dependencies into ./vendor/ruby + +rspec: + script: + - rspec spec +``` + +### Caching Go dependencies[](#caching-go-dependencies "Permalink") + +假设您的项目正在使用[Go Modules](https://github.com/golang/go/wiki/Modules)安装 Go 依赖项,以下示例在`go-cache`模板中定义了`cache` ,任何作业都可以扩展. Go 模块安装在`${GOPATH}/pkg/mod/` ,并为所有`go`项目缓存: + +``` +.go-cache: + variables: + GOPATH: $CI_PROJECT_DIR/.go + before_script: + - mkdir -p .go + cache: + paths: + - .go/pkg/mod/ + +test: + image: golang:1.13 + extends: .go-cache + script: + - go test ./... -v -short +``` + +## Availability of the cache[](#availability-of-the-cache "Permalink") + +缓存是一种优化,但不能保证始终有效,因此您需要准备好在需要它们的每个作业中重新生成所有缓存的文件. + +假设您已根据工作流程[在`.gitlab-ci.yml`](../yaml/README.html#cache)正确[定义了`cache`](../yaml/README.html#cache) ,则缓存的可用性最终取决于 Runner 的配置方式(执行程序类型以及是否使用不同的 Runner 在作业之间传递缓存). + +### Where the caches are stored[](#where-the-caches-are-stored "Permalink") + +由于亚军是一个负责存储的缓存,这是必须要知道它的存储**位置** . 在`.gitlab-ci.yml`中的作业下定义的所有缓存路径都存储在单个`cache.zip`文件中,并存储在 Runner 的配置缓存位置中. 默认情况下,它们存储在本地安装了 Runner 的计算机中,具体取决于执行程序的类型. + +| GitLab Runner 执行器 | 缓存的默认路径 | +| --- | --- | +| [Shell](https://docs.gitlab.com/runner/executors/shell.html) | 在本地,存储在`gitlab-runner`用户的主目录下: `/home/gitlab-runner/cache/<user>/<project>/<cache-key>/cache.zip` home/ `gitlab-runner` user>/< `gitlab-runner` < `gitlab-runner` `/home/gitlab-runner/cache/<user>/<project>/<cache-key>/cache.zip` . | +| [Docker](https://docs.gitlab.com/runner/executors/docker.html) | 在本地存储在[Docker 卷下](https://docs.gitlab.com/runner/executors/docker.html) :/ `/var/lib/docker/volumes/<volume-id>/_data/<user>/<project>/<cache-key>/cache.zip` [docker / volumes / <卷](https://docs.gitlab.com/runner/executors/docker.html) `/var/lib/docker/volumes/<volume-id>/_data/<user>/<project>/<cache-key>/cache.zip` _ `/var/lib/docker/volumes/<volume-id>/_data/<user>/<project>/<cache-key>/cache.zip` . | +| [Docker 机器](https://docs.gitlab.com/runner/executors/docker_machine.html) (自动缩放赛跑者) | 行为与 Docker 执行器相同. | + +### How archiving and extracting works[](#how-archiving-and-extracting-works "Permalink") + +在最简单的情况下,请考虑仅使用一台安装了 Runner 的计算机,并且项目的所有作业都在同一主机上运行. + +让我们看下面两个属于两个连续阶段的作业的示例: + +``` +stages: + - build + - test + +before_script: + - echo "Hello" + +job A: + stage: build + script: + - mkdir vendor/ + - echo "build" > vendor/hello.txt + cache: + key: build-cache + paths: + - vendor/ + after_script: + - echo "World" + +job B: + stage: test + script: + - cat vendor/hello.txt + cache: + key: build-cache +``` + +这是幕后发生的事情: + +1. 管道开始. +2. `job A` runs. +3. 执行`before_script` . +4. `script`已执行. +5. `after_script`被执行. +6. `cache`运行,并且`vendor/`目录被压缩到`cache.zip` . 然后根据[Runner 的设置](#where-the-caches-are-stored)和`cache: key`将该文件保存在目录中. +7. `job B` runs. +8. 提取缓存(如果找到). +9. 执行`before_script` . +10. `script`已执行. +11. 管道完成. + +通过在单台计算机上使用单个 Runner,就不会出现`job B`可能在不同于`job A`的 Runner 上执行的问题,从而保证了各个阶段之间的缓存. 仅当构建在同一 Runner /机器上从阶段`build`到`test` ,此方法才有效,否则,您[可能没有可用的缓存](#cache-mismatch) . + +在缓存过程中,还需要考虑以下几点: + +* 如果具有其他缓存配置的某些其他作业已将其缓存保存在同一 zip 文件中,则它将被覆盖. 如果使用了基于 S3 的共享缓存,则还会根据缓存密钥将文件另外上传到 S3 到对象. 因此,路径不同但缓存键相同的两个作业将覆盖其缓存. +* 从`cache.zip`提取缓存时,zip 文件中的所有内容都提取到作业的工作目录(通常是下拉的存储库)中,并且 Runner 不在乎`job A`的存档是否覆盖了`job B` + +之所以以这种方式工作,是因为为一个 Runner 创建的缓存通常在由可以在**不同体系结构**上运行的缓存使用时才无效(例如,当缓存包含二进制文件时). 而且由于不同的步骤可能由运行在不同计算机上的运行程序执行,因此这是安全的默认设置. + +### Cache mismatch[](#cache-mismatch "Permalink") + +在下表中,您可以看到可能导致缓存不匹配的一些原因以及一些解决方法. + +| 缓存不匹配的原因 | 如何修复 | +| --- | --- | +| 您使用多个独立运行器(不在自动缩放模式下)附加到一个项目,而没有共享缓存 | 您的项目仅使用一个 Runner 或使用启用了分布式缓存的多个 Runner | +| 您在未启用分布式缓存的自动缩放模式下使用 Runners | 配置自动缩放运行器以使用分布式缓存 | +| 安装了 Runner 的计算机磁盘空间不足,或者,如果设置了分布式缓存,则存储缓存的 S3 存储桶空间不足 | 确保清除一些空间以允许存储新的缓存. 当前,没有自动的方法可以做到这一点. | +| 对于作业中缓存不同路径的作业,请使用相同的`key` . | Use different cache keys to that the cache archive is stored to a different location and doesn’t overwrite wrong caches. | + +让我们探索一些例子. + +#### Examples[](#examples "Permalink") + +假设您只为项目分配了一个 Runner,因此默认情况下缓存将存储在 Runner 的计算机中. 如果两个作业 A 和 B 具有相同的缓存密钥,但是它们缓存不同的路径,则即使它们的`paths`不匹配,缓存 B 也会覆盖缓存 A: + +当管道第二次运行时,我们希望`job A`和`job B`重用其缓存. + +``` +stages: + - build + - test + +job A: + stage: build + script: make build + cache: + key: same-key + paths: + - public/ + +job B: + stage: test + script: make test + cache: + key: same-key + paths: + - vendor/ +``` + +1. `job A` runs. +2. `public/`作为 cache.zip 缓存. +3. `job B` runs. +4. 先前的缓存(如果有)已解压缩. +5. `vendor/`作为 cache.zip 缓存,并覆盖前一个. +6. 下次`job A`运行时,它将使用`job B`的缓存,缓存不同,因此无效. + +要解决此问题,请为每个作业使用不同的`keys` . + +在另一种情况下,假设您为项目分配了多个运行器,但是未启用分布式缓存. 第二次运行管道时,我们希望`job A`和`job B`重用其缓存(在这种情况下将有所不同): + +``` +stages: + - build + - test + +job A: + stage: build + script: build + cache: + key: keyA + paths: + - vendor/ + +job B: + stage: test + script: test + cache: + key: keyB + paths: + - vendor/ +``` + +在这种情况下,即使`key`不同(不必担心覆盖),如果作业在后续管道中的不同运行器上运行,您也可能会在每个阶段之前"清理"缓存的文件. + +## Clearing the cache[](#clearing-the-cache "Permalink") + +GitLab Runners 使用[缓存](../yaml/README.html#cache)通过重用现有数据来加快作业的执行速度. 但是,这有时可能导致行为不一致. + +要从缓存的新副本开始,有两种方法可以做到这一点. + +### Clearing the cache by changing `cache:key`[](#clearing-the-cache-by-changing-cachekey "Permalink") + +您所需要做的就是设置一个新的`cache: key` `.gitlab-ci.yml` . 在下一个管道运行中,缓存将存储在其他位置. + +### Clearing the cache manually[](#clearing-the-cache-manually "Permalink") + +在 GitLab 10.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41249) . + +如果要避免编辑`.gitlab-ci.yml` ,则可以通过 GitLab 的 UI 轻松清除缓存: + +1. 导航到项目的**CI / CD>管道**页面. +2. 单击" **清除流道缓存"**按钮以清理缓存. + + [![Clear Runners cache](img/97c7baeb5e993264f4619e443bdacebc.png)](img/clear_runners_cache.png) + +3. 在下一次推送时,您的 CI / CD 作业将使用新的缓存. + +在后台,这可以通过在数据库中增加一个计数器来实现,该计数器的值用于通过将整数附加到`-1` , `-2`等来为高速缓存创建密钥.密钥已生成,旧的缓存不再有效. \ No newline at end of file diff --git a/_book/docs/214.md b/_book/docs/214.md new file mode 100644 index 0000000000000000000000000000000000000000..d08c22d196819a0e3ac71e583487528b881d8f85 --- /dev/null +++ b/_book/docs/214.md @@ -0,0 +1,80 @@ +# GitLab ChatOps + +> 原文:[https://docs.gitlab.com/ee/ci/chatops/README.html](https://docs.gitlab.com/ee/ci/chatops/README.html) + +* [How GitLab ChatOps works](#how-gitlab-chatops-works) +* [Best practices for ChatOps CI jobs](#best-practices-for-chatops-ci-jobs) + * [Controlling the ChatOps reply](#controlling-the-chatops-reply) +* [GitLab ChatOps examples](#gitlab-chatops-examples) +* [GitLab ChatOps icon](#gitlab-chatops-icon) + +# GitLab ChatOps[](#gitlab-chatops "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) . +* 在 11.9 中[移至](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) [GitLab Core](https://about.gitlab.com/pricing/) . + +GitLab ChatOps 提供了一种通过 Slack 等聊天服务与 CI / CD 作业进行交互的方法. 许多组织的讨论,协作和故障排除都是在聊天服务中进行的. 拥有一种方法来运行 CI / CD 作业并将输出回传到渠道,可以极大地增强团队的工作流程. + +## How GitLab ChatOps works[](#how-gitlab-chatops-works "Permalink") + +GitLab ChatOps 是基于[GitLab CI / CD](../README.html)和[Slack Slash Commands](../../user/project/integrations/slack_slash_commands.html)构建的. ChatOps 使用以下参数为[斜杠命令](../../integration/slash_commands.html)提供`run`操作: + +* 要执行的`<job name>` . +* The `<job arguments>`. + +ChatOps 将以下[CI / CD 变量](../variables/README.html#predefined-environment-variables)传递给作业: + +* `CHAT_INPUT`包含任何其他参数. +* `CHAT_CHANNEL`设置为触发该动作的通道的名称. + +当执行时,ChatOps 查找指定的作业名称,并尝试将其与[`.gitlab-ci.yml`](../yaml/README.html)的相应作业匹配. 如果在`master`上找到匹配的作业,则计划仅包含该作业的管道. 作业完成后: + +* 如果作业在*不到 30 分钟内完成* ,则 ChatOps 会将作业的输出发送到 Slack. +* 如果作业在*30 分钟内完成* ,则该作业必须使用[Slack API](https://api.slack.com/)将数据发送到通道. + +要使用`run`命令,您必须具有[Developer 访问权限或更高权限](../../user/permissions.html#project-members-permissions) . 如果不能从聊天中触发某项工作,则可以将其设置为下列`except: [chat]` . + +## Best practices for ChatOps CI jobs[](#best-practices-for-chatops-ci-jobs "Permalink") + +由于 ChatOps 是基于 GitLab CI / CD 构建的,因此该作业具有可用的所有相同功能. 创建 ChatOps 作业时,请考虑以下最佳做法: + +* GitLab 强烈建议您`only: [chat]`设置`only: [chat]`以便该作业不会作为标准 CI 管道的一部分运行. +* 如果作业设置为以下`when: manual` ,则 ChatOps 将创建管道,但是作业等待启动. +* ChatOps 为访问控制提供了有限的支持. 如果触发斜杠命令的用户在项目中具有" [开发人员"访问权限或更高权限](../../user/permissions.html#project-members-permissions) ,则作业将运行. 作业本身可以使用现有的[CI / CD 变量(](../variables/README.html#predefined-environment-variables)例如`GITLAB_USER_ID`来执行其他权限验证,但是可以[覆盖](../variables/README.html#priority-of-environment-variables)这些变量. + +### Controlling the ChatOps reply[](#controlling-the-chatops-reply "Permalink") + +单个命令的作业输出将作为答复发送到通道. 例如,以下任务的聊天回复是频道中的`Hello World` : + +``` +hello-world: + stage: chatops + only: [chat] + script: + - echo "Hello World" +``` + +包含多个命令(或`before_script` )的作业将在聊天回复中返回其他内容. 在这些情况下,命令和它们的输出都包括在内,并且命令以 ANSI 颜色代码包装. + +To selectively reply with the output of one command, its output must be bounded by the `chat_reply` section. For example, the following job lists the files in the current directory: + +``` +ls: + stage: chatops + only: [chat] + script: + - echo "This command will not be shown." + - echo -e "section_start:$( date +%s ):chat_reply\r\033[0K\n$( ls -la )\nsection_end:$( date +%s ):chat_reply\r\033[0K" +``` + +## GitLab ChatOps examples[](#gitlab-chatops-examples "Permalink") + +GitLab.com 团队创建了一个[常见 ChatOps 脚本](https://gitlab.com/gitlab-com/chatops)的存储库,它们用于与我们的 GitLab 生产实例进行交互. 其他 GitLab 实例的管理员可能会发现它们很有用. 它们可以作为您可以编写以与自己的应用程序进行交互的 ChatOps 脚本的灵感. + +## GitLab ChatOps icon[](#gitlab-chatops-icon "Permalink") + +[官方的 GitLab ChatOps 图标](img/gitlab-chatops-icon.png)可以下载. 您可以在此处找到并下载官方的 GitLab ChatOps 图标. + +[![GitLab ChatOps bot icon](img/b7658a174f8b110251a289f5276dc822.png)](img/gitlab-chatops-icon-small.png) \ No newline at end of file diff --git a/_book/docs/215.md b/_book/docs/215.md new file mode 100644 index 0000000000000000000000000000000000000000..16926e32d734b773c166a41dde8781db9ddfcc39 --- /dev/null +++ b/_book/docs/215.md @@ -0,0 +1,122 @@ +# Cloud deployment + +> 原文:[https://docs.gitlab.com/ee/ci/cloud_deployment/](https://docs.gitlab.com/ee/ci/cloud_deployment/) + +* [AWS](#aws) + * [Run AWS commands from GitLab CI/CD](#run-aws-commands-from-gitlab-cicd) + * [Use an AWS Elastic Container Registry (ECR) image in your CI/CD](#use-an-aws-elastic-container-registry-ecr-image-in-your-cicd) + * [Deploy your application to the AWS Elastic Container Service (ECS)](#deploy-your-application-to-the-aws-elastic-container-service-ecs) + +# Cloud deployment[](#cloud-deployment "Permalink") + +与主要的云提供商进行交互可能已成为交付过程中非常需要的任务. GitLab 通过提供预安装了所需库和工具的 Docker 映像,减轻了这一过程的麻烦. 通过在 CI / CD 管道中引用它们,您将能够更轻松地与所选的云提供商进行交互. + +## AWS[](#aws "Permalink") + +GitLab 提供了可用于[从 GitLab CI / CD 运行 AWS 命令的](#run-aws-commands-from-gitlab-cicd) Docker 映像,并提供了一个模板,以使其更易于[部署到 AWS](#deploy-your-application-to-the-aws-elastic-container-service-ecs) . + +### Run AWS commands from GitLab CI/CD[](#run-aws-commands-from-gitlab-cicd "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31167) . + +GitLab 的 AWS Docker 映像提供了[AWS Command Line Interface](https://aws.amazon.com/cli/) ,可让您运行`aws`命令. 作为部署策略的一部分,您可以通过指定[GitLab 的 AWS Docker 映像](https://gitlab.com/gitlab-org/cloud-deploy)直接从`.gitlab-ci.yml`运行`aws`命令. + +需要一些凭据才能运行`aws`命令: + +1. 如果您还没有[一个 AWS 账户](https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-set-up.html) ,请注册一个. +2. 登录到控制台并创建[一个新的 IAM 用户](https://console.aws.amazon.com/iam/home#/home) . +3. 选择您新创建的用户以访问其详细信息. 导航到**安全凭证>创建新的访问密钥** . + + **注意:**将生成新的**访问密钥 ID**和**秘密访问密钥**对. 请立即记录下来. +4. 在您的 GitLab 项目中,转到**"设置">" CI / CD"** . 将以下内容设置为[环境变量](../variables/README.html#gitlab-cicd-environment-variables) (请参见下表): + + * 访问密钥 ID. + * 秘密访问密钥. + * 地区代码. 您可以检查[AWS 区域终端节点列表](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints) . 您可能想要检查要使用的 AWS 服务[在所选区域中](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/)是否[可用](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/) . + + | 环保 变量名 | Value | + | --- | --- | + | `AWS_ACCESS_KEY_ID` | 您的访问密钥 ID | + | `AWS_SECRET_ACCESS_KEY` | 您的秘密访问密钥 | + | `AWS_DEFAULT_REGION` | 您的地区代码 | + +5. 现在,您可以在此项目的`.gitlab-ci.yml`文件中使用`aws`命令: + + ``` + deploy: + stage: deploy + image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest # see the note below + script: + - aws s3 ... + - aws create-deployment ... + ``` + + **注意:**上例中使用的映像( `registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest` )托管在[GitLab 容器注册表中](../../user/packages/container_registry/index.html) ,可以使用. 或者,将映像替换为 AWS ECR 上托管的映像. + +### Use an AWS Elastic Container Registry (ECR) image in your CI/CD[](#use-an-aws-elastic-container-registry-ecr-image-in-your-cicd "Permalink") + +除了引用托管在 GitLab 注册表上的映像外,您还可以引用托管在任何第三方注册表上的映像,例如[Amazon Elastic Container Registry(ECR)](https://aws.amazon.com/ecr/) . + +为此, [将映像推送到 ECR 存储库中](https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-push-ecr-image.html) . 然后在`.gitlab-ci.yml`文件中引用它,并替换`image`路径以指向您的 ECR 图像. + +### Deploy your application to the AWS Elastic Container Service (ECS)[](#deploy-your-application-to-the-aws-elastic-container-service-ecs "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/207962) . + +GitLab 提供了一系列[CI 模板,您可以将其包含在项目中](../yaml/README.html#include) . 要自动将应用程序部署到[Amazon Elastic Container Service](https://aws.amazon.com/ecs/) (AWS ECS)集群,您可以在`.gitlab-ci.yml`文件中`include` `Deploy-ECS.gitlab-ci.yml`模板. + +GitLab 还提供了可在您的`gitlab-ci.yml`文件中使用的[Docker 映像](https://gitlab.com/gitlab-org/cloud-deploy/-/tree/master/aws) ,以简化使用 AWS 的工作: + +* 使用`registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest`以使用 AWS CLI 命令. +* 使用`registry.gitlab.com/gitlab-org/cloud-deploy/aws-ecs:latest`将您的应用程序部署到 AWS ECS. + +在开始此过程之前,您需要 AWS ECS 上的集群以及相关组件,例如 ECS 服务,ECS 任务定义,AWS RDS 上的数据库等. [了解有关 AWS ECS 的更多信息](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html) . + +在 AWS ECS 上完成所有设置后,请执行以下步骤: + +1. 确保将您的 AWS 凭证设置为项目的环境变量. 您可以按照[上述步骤](#run-aws-commands-from-gitlab-cicd)完成此设置. +2. Add these variables to your project’s `.gitlab-ci.yml` file: + + ``` + variables: + CI_AWS_ECS_CLUSTER: my-cluster + CI_AWS_ECS_SERVICE: my-service + CI_AWS_ECS_TASK_DEFINITION: my-task-definition + ``` + + Three variables are defined in this snippet: + + * `CI_AWS_ECS_CLUSTER` :您要为部署目标的 AWS ECS 集群的名称. + * `CI_AWS_ECS_SERVICE` :绑定到您的 AWS ECS 集群的目标服务的名称. + * `CI_AWS_ECS_TASK_DEFINITION` :与上述服务绑定的任务定义的名称. + + 您可以在[AWS ECS 仪表板上](https://console.aws.amazon.com/ecs/home)选择目标集群后找到这些名称: + + [![AWS ECS dashboard](img/7dc58177067caac48605788b7932d846.png)](../img/ecs_dashboard_v12_9.png) + +3. 将此模板包括在`.gitlab-ci.yml` : + + ``` + include: + - template: AWS/Deploy-ECS.gitlab-ci.yml + ``` + + `Deploy-ECS`模板随 GitLab 一起提供[,](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml)可[在 GitLab.com 上获得](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml) . + +4. 提交更新的`.gitlab-ci.yml`并将其推送到项目的存储库中,您就完成了! + + 您的应用程序 Docker 映像将被重建并推送到 GitLab 注册表中. 然后,目标任务定义将使用新 Docker 映像的位置进行更新,结果将在 ECS 中创建新的修订版. + + 最后,您的 AWS ECS 服务将使用任务定义的新修订版进行更新,从而使群集提取应用程序的最新版本. + +**警告:** [`Deploy-ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml)模板包括[`Jobs/Build.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml)和[`Jobs/Deploy/ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml) "子模板". 不要单独包括这些"子模板",而仅包括主`Deploy-ECS.gitlab-ci.yml`模板. "子模板"旨在仅与主模板一起使用. 如果不包括主模板,它们可能会移动或发生意外更改,从而导致您的管道失败. 此外,这些模板中的作业名称可能会更改. 不要在您自己的管道中覆盖这些作业的名称,因为当名称更改时,覆盖将停止工作. + +另外,如果您不希望使用`Deploy-ECS.gitlab-ci.yml`模板部署到 AWS ECS,则始终可以使用基于`aws-base` Docker 映像[为 ECS](https://docs.aws.amazon.com/cli/latest/reference/ecs/index.html#cli-aws-ecs)运行您自己的[AWS CLI 命令](https://docs.aws.amazon.com/cli/latest/reference/ecs/index.html#cli-aws-ecs) . + +``` +deploy: + stage: deploy + image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest + script: + - aws ecs register-task-definition ... +``` \ No newline at end of file diff --git a/_book/docs/216.md b/_book/docs/216.md new file mode 100644 index 0000000000000000000000000000000000000000..0cf03ca0e5dc67955c96e15a164262c8ac63e314 --- /dev/null +++ b/_book/docs/216.md @@ -0,0 +1,13 @@ +# Docker integration + +> 原文:[https://docs.gitlab.com/ee/ci/docker/README.html](https://docs.gitlab.com/ee/ci/docker/README.html) + +# Docker integration[](#docker-integration "Permalink") + +GitLab CI / CD 可以与[Docker](https://www.docker.com)结合使用,以实现两者之间的集成. + +以下文档可用于将 GitLab CI / CD 与 Docker 结合使用: + +* [Using Docker images](using_docker_images.html). +* [Building Docker images with GitLab CI/CD](using_docker_build.html). +* [Building images with kaniko and GitLab CI/CD](using_kaniko.html). \ No newline at end of file diff --git a/_book/docs/217.md b/_book/docs/217.md new file mode 100644 index 0000000000000000000000000000000000000000..a9456d40ff747b45f77488b574029d7a6272582c --- /dev/null +++ b/_book/docs/217.md @@ -0,0 +1,436 @@ +# Building Docker images with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/docker/using_docker_build.html](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html) + +* [Runner Configuration](#runner-configuration) + * [Use shell executor](#use-shell-executor) + * [Use Docker-in-Docker workflow with Docker executor](#use-docker-in-docker-workflow-with-docker-executor) + * [TLS enabled](#tls-enabled) + * [TLS disabled](#tls-disabled) + * [Use Docker socket binding](#use-docker-socket-binding) +* [Making Docker-in-Docker builds faster with Docker layer caching](#making-docker-in-docker-builds-faster-with-docker-layer-caching) + * [How Docker caching works](#how-docker-caching-works) + * [Using Docker caching](#using-docker-caching) +* [Use the OverlayFS driver](#use-the-overlayfs-driver) + * [Requirements](#requirements) + * [Use the OverlayFS driver per project](#use-the-overlayfs-driver-per-project) + * [Use the OverlayFS driver for every project](#use-the-overlayfs-driver-for-every-project) +* [Using the GitLab Container Registry](#using-the-gitlab-container-registry) +* [Troubleshooting](#troubleshooting) + * [`docker: Cannot connect to the Docker daemon at tcp://docker:2375\. Is the docker daemon running?`](#docker-cannot-connect-to-the-docker-daemon-at-tcpdocker2375-is-the-docker-daemon-running) + +# Building Docker images with GitLab CI/CD[](#building-docker-images-with-gitlab-cicd "Permalink") + +GitLab CI / CD 允许您使用 Docker Engine 来构建和测试基于 Docker 的项目. + +持续集成/部署中的新趋势之一是: + +1. Create an application image. +2. 针对创建的图像运行测试. +3. 将映像推送到远程注册表. +4. 从推送的映像部署到服务器. + +当您的应用程序已经具有可用于创建和测试映像的`Dockerfile` ,它也很有用: + +``` +docker build -t my-image dockerfiles/ +docker run my-image /script/to/run/tests +docker tag my-image my-registry:5000/my-image +docker push my-registry:5000/my-image +``` + +这需要对 GitLab Runner 进行特殊配置才能在作业期间启用`docker`支持. + +## Runner Configuration[](#runner-configuration "Permalink") + +有三种方法可在作业期间启用`docker build`和`docker run`的使用: 每个都有自己的权衡. + +[使用 docker](using_kaniko.html) `docker build`的替代方法是[使用 kaniko](using_kaniko.html) . 这避免了必须在特权模式下执行 Runner. + +**提示:**要了解如何在 GitLab.com 上为共享的 Runner 配置 Docker 和 Runner,请参阅[GitLab.com 的共享的 Runners](../../user/gitlab_com/index.html#shared-runners) . + +### Use shell executor[](#use-shell-executor "Permalink") + +最简单的方法是在`shell`执行模式下安装 GitLab Runner. 然后,GitLab Runner 以`gitlab-runner`用户身份执行作业脚本. + +1. Install [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/#installation). + +2. 在 GitLab Runner 安装过程中,选择`shell`作为执行作业脚本的方法或使用命令: + + ``` + sudo gitlab-runner register -n \ + --url https://gitlab.com/ \ + --registration-token REGISTRATION_TOKEN \ + --executor shell \ + --description "My Runner" + ``` + +3. 在服务器上安装 Docker Engine. + + 有关如何在不同系统上安装 Docker Engine 的更多信息,请查看[支持的安装](https://s0docs0docker0com.icopy.site/engine/installation/) . + +4. Add `gitlab-runner` user to `docker` group: + + ``` + sudo usermod -aG docker gitlab-runner + ``` + +5. 确认`gitlab-runner`有权访问 Docker: + + ``` + sudo -u gitlab-runner -H docker info + ``` + + 现在,您可以通过将`.gitlab-ci.yml` `docker info`添加到`.gitlab-ci.yml`来验证一切正常: + + ``` + before_script: + - docker info + + build_image: + script: + - docker build -t my-docker-image . + - docker run my-docker-image /script/to/run/tests + ``` + +6. 您现在可以使用`docker`命令(并在需要时**安装** `docker-compose` ). + +**注:**通过添加`gitlab-runner`的`docker`您可以有效地授予组`gitlab-runner`完整的 root 权限. 有关更多信息,请阅读[关于 Docker 安全性: `docker` group 认为是有害的](https://www.andreas-jung.com/contents/on-docker-security-docker-group-considered-harmful) . + +### Use Docker-in-Docker workflow with Docker executor[](#use-docker-in-docker-workflow-with-docker-executor "Permalink") + +第二种方法是使用特殊泊坞窗功能于泊坞(DIND) [泊坞窗图像](https://hub.docker.com/_/docker/)安装(所有工具`docker` ),并在特权模式图像的上下文中运行作业脚本. + +**注意:** `docker-compose`不是 Docker-in-Docker(dind)的一部分. 要在 CI 构建中使用`docker-compose` ,请遵循`docker-compose` [安装说明](https://s0docs0docker0com.icopy.site/compose/install/) .**危险:**通过启用`--docker-privileged` ,可以有效地禁用容器的所有安全机制,并使主机暴露于特权升级之下,这可能导致容器突破. 有关更多信息,请查看有关[运行时特权和 Linux 功能](https://s0docs0docker0com.icopy.site/engine/reference/run/)的官方 Docker 文档. + +Docker-in-Docker 运作良好,是推荐的配置,但并非没有挑战: + +* When using Docker-in-Docker, each job is in a clean environment without the past history. Concurrent jobs work fine because every build gets its own instance of Docker engine so they won’t conflict with each other. But this also means that jobs can be slower because there’s no caching of layers. +* 默认情况下,Docker 17.09 及更高版本使用`--storage-driver overlay2` ,这是推荐的存储驱动程序. 有关详细信息,请参见[使用 overlayfs 驱动程序](#use-the-overlayfs-driver) . +* 由于`docker:19.03.12-dind`容器和 Runner 容器不共享其根文件系统,因此作业的工作目录可用作子容器的安装点. 例如,如果您有要与子容器共享的文件,则可以在`/builds/$CI_PROJECT_PATH`下创建一个子目录,并将其用作安装点(有关更详尽的解释,请[参见问题#41227](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41227) ): + + ``` + variables: + MOUNT_POINT: /builds/$CI_PROJECT_PATH/mnt + + script: + - mkdir -p "$MOUNT_POINT" + - docker run -v "$MOUNT_POINT:/mnt" my-docker-image + ``` + +可在以下位置找到使用此方法的示例项目: [https](https://gitlab.com/gitlab-examples/docker) : [//gitlab.com/gitlab-examples/docker](https://gitlab.com/gitlab-examples/docker) . + +在以下示例中,我们使用 Docker images 标签指定特定版本,例如`docker:19.03.12` . 如果使用了诸如`docker:stable`类的标签,则您将无法控制要使用的版本,这可能导致无法预测的行为,尤其是在发布新版本时. + +#### TLS enabled[](#tls-enabled "Permalink") + +**注意:**需要 GitLab Runner 11.11 或更高版本,但是如果使用[Helm chart](https://docs.gitlab.com/runner/install/kubernetes.html)安装了 GitLab Runner,则不支持. 有关详细信息,请参见[相关问题](https://gitlab.com/gitlab-org/charts/gitlab-runner/-/issues/83) . + +Docker 守护程序支持通过 TLS 的连接,默认情况下,对于 Docker 19.03.12 或更高版本,它已完成. 这是使用 Docker-in-Docker 服务的**建议**方法, [GitLab.com 共享运行程序](../../user/gitlab_com/index.html#shared-runners)支持此方法. + +1. Install [GitLab Runner](https://docs.gitlab.com/runner/install/). + +2. 从命令行注册 GitLab Runner 以使用`docker`和`privileged`模式: + + ``` + sudo gitlab-runner register -n \ + --url https://gitlab.com/ \ + --registration-token REGISTRATION_TOKEN \ + --executor docker \ + --description "My Docker Runner" \ + --docker-image "docker:19.03.12" \ + --docker-privileged \ + --docker-volumes "/certs/client" + ``` + + 上面的命令将注册一个新的 Runner 以使用由 Docker 提供的特殊`docker:19.03.12`映像. **注意,它使用`privileged`模式来启动构建和服务容器.** 如果要使用[Docker-in-Docker](https://www.docker.com/blog/docker-can-now-run-within-docker/)模式,则始终必须在 Docker 容器中使用`privileged = true` . + + 这还将为服务安装`/certs/client`并构建容器,这是 Docker 客户端使用该目录内的证书所必需的. 有关更多信息,请参阅[https://hub.docker.com/_/docker/#tls](https://hub.docker.com/_/docker/#tls) . + + 上面的命令将创建一个类似于以下内容的`config.toml`条目: + + ``` + [[runners]] + url = "https://gitlab.com/" + token = TOKEN + executor = "docker" + [runners.docker] + tls_verify = false + image = "docker:19.03.12" + privileged = true + disable_cache = false + volumes = ["/certs/client", "/cache"] + [runners.cache] + [runners.cache.s3] + [runners.cache.gcs] + ``` + +3. 您现在可以使用`docker`在构建脚本(注意列入`docker:19.03.12-dind`服务): + + ``` + image: docker:19.03.12 + + variables: + # When using dind service, we need to instruct docker, to talk with + # the daemon started inside of the service. The daemon is available + # with a network connection instead of the default + # /var/run/docker.sock socket. Docker 19.03 does this automatically + # by setting the DOCKER_HOST in + # https://github.com/docker-library/docker/blob/d45051476babc297257df490d22cbd806f1b11e4/19.03/docker-entrypoint.sh#L23-L29 + # + # The 'docker' hostname is the alias of the service container as described at + # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services. + # + # Note that if you're using GitLab Runner 12.7 or earlier with the Kubernetes executor and Kubernetes 1.6 or earlier, + # the variable must be set to tcp://localhost:2376 because of how the + # Kubernetes executor connects services to the job container + # DOCKER_HOST: tcp://localhost:2376 + # + # Specify to Docker where to create the certificates, Docker will + # create them automatically on boot, and will create + # `/certs/client` that will be shared between the service and job + # container, thanks to volume mount from config.toml + DOCKER_TLS_CERTDIR: "/certs" + + services: + - docker:19.03.12-dind + + before_script: + - docker info + + build: + stage: build + script: + - docker build -t my-docker-image . + - docker run my-docker-image /script/to/run/tests + ``` + +#### TLS disabled[](#tls-disabled "Permalink") + +有时出于某些合理原因,您可能想要禁用 TLS. 例如,您无法控制所使用的 GitLab Runner 配置. + +假设 Runner `config.toml`类似于: + +``` +[[runners]] + url = "https://gitlab.com/" + token = TOKEN + executor = "docker" + [runners.docker] + tls_verify = false + image = "docker:19.03.12" + privileged = true + disable_cache = false + volumes = ["/cache"] + [runners.cache] + [runners.cache.s3] + [runners.cache.gcs] +``` + +您现在可以使用`docker`在构建脚本(注意列入`docker:19.03.12-dind`服务): + +``` +image: docker:19.03.12 + +variables: + # When using dind service we need to instruct docker, to talk with the + # daemon started inside of the service. The daemon is available with + # a network connection instead of the default /var/run/docker.sock socket. + # + # The 'docker' hostname is the alias of the service container as described at + # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services + # + # Note that if you're using GitLab Runner 12.7 or earlier with the Kubernetes executor and Kubernetes 1.6 or earlier, + # the variable must be set to tcp://localhost:2375 because of how the + # Kubernetes executor connects services to the job container + # DOCKER_HOST: tcp://localhost:2375 + # + DOCKER_HOST: tcp://docker:2375 + # + # This will instruct Docker not to start over TLS. + DOCKER_TLS_CERTDIR: "" + +services: + - docker:19.03.12-dind + +before_script: + - docker info + +build: + stage: build + script: + - docker build -t my-docker-image . + - docker run my-docker-image /script/to/run/tests +``` + +### Use Docker socket binding[](#use-docker-socket-binding "Permalink") + +第三种方法是将`/var/run/docker.sock`绑定安装到容器中,以便 Docker 在该映像的上下文中可用. + +**注意:**如果[在使用 GitLab Runner 11.11 或更高版本时](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/1261)绑定 Docker 套接字,则不能再将`docker:19.03.12-dind`用作服务,因为对服务也进行了卷绑定,从而使它们不兼容. + +为此,请按照下列步骤操作: + +1. Install [GitLab Runner](https://docs.gitlab.com/runner/install/). + +2. 从命令行注册 GitLab Runner 以使用`docker`并共享`/var/run/docker.sock` : + + ``` + sudo gitlab-runner register -n \ + --url https://gitlab.com/ \ + --registration-token REGISTRATION_TOKEN \ + --executor docker \ + --description "My Docker Runner" \ + --docker-image "docker:19.03.12" \ + --docker-volumes /var/run/docker.sock:/var/run/docker.sock + ``` + + 上面的命令将注册一个新的 Runner 以使用由 Docker 提供的特殊`docker:19.03.12`映像. **请注意,它使用的是 Runner 本身的 Docker 守护进程,并且 Docker 命令产生的任何容器都将是 Runner 的兄弟,而不是 Runner 的子代.** 这可能会带来一些不适合您的工作流程的复杂性和局限性. + + 上面的命令将创建一个类似于以下内容的`config.toml`条目: + + ``` + [[runners]] + url = "https://gitlab.com/" + token = REGISTRATION_TOKEN + executor = "docker" + [runners.docker] + tls_verify = false + image = "docker:19.03.12" + privileged = false + disable_cache = false + volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"] + [runners.cache] + Insecure = false + ``` + +3. 您现在可以使用`docker`在构建脚本(请注意,您不需要包括`docker:19.03.12-dind`服务泊坞执行使用泊坞时): + + ``` + image: docker:19.03.12 + + before_script: + - docker info + + build: + stage: build + script: + - docker build -t my-docker-image . + - docker run my-docker-image /script/to/run/tests + ``` + +尽管上述方法避免在特权模式下使用 Docker,但您应注意以下含义: + +* 通过共享 Docker 守护程序,您可以有效地禁用容器的所有安全机制,并使主机暴露于特权升级之下,这可能导致容器突破. 例如,如果一个项目运行`docker rm -f $(docker ps -a -q)` ,它将删除 GitLab Runner 容器. +* 并发工作可能无法正常工作; 如果您的测试创建了具有特定名称的容器,则它们可能会相互冲突. +* 将源仓库中的文件和目录共享到容器中可能无法正常工作,因为卷安装是在主机而不是构建容器的上下文中完成的. 例如: + + ``` + docker run --rm -t -i -v $(pwd)/src:/home/app/src test-image:latest run_app_tests + ``` + +## Making Docker-in-Docker builds faster with Docker layer caching[](#making-docker-in-docker-builds-faster-with-docker-layer-caching "Permalink") + +在使用 Docker-in-Docker 时,每次创建构建时 Docker 都会下载映像的所有层. 最新版本的 Docker(Docker 1.13 及更高版本)可以在 Docker `docker build`步骤中使用预先存在的映像作为缓存,从而大大加快了构建过程. + +### How Docker caching works[](#how-docker-caching-works "Permalink") + +运行`Dockerfile` `docker build` , `Dockerfile`中的每个命令`Dockerfile`一个图层. 这些层保留为高速缓存,如果没有任何更改,可以重复使用. 一层中的更改将导致重新创建所有后续层. + +您可以使用`--cache-from`参数指定标记的图像用作`--cache-from` `docker build`命令的缓存源. 可以使用多个`--cache-from`参数将多个图像指定为缓存源. 请记住,与`--cache-from`参数一起使用的任何映像都必须先被拉出(使用`docker pull` ),然后才能用作缓存源. + +### Using Docker caching[](#using-docker-caching "Permalink") + +这是一个`.gitlab-ci.yml`文件,显示了如何使用 Docker 缓存: + +``` +image: docker:19.03.12 + +services: + - docker:19.03.12-dind + +variables: + # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled + DOCKER_HOST: tcp://docker:2376 + DOCKER_TLS_CERTDIR: "/certs" + +before_script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + +build: + stage: build + script: + - docker pull $CI_REGISTRY_IMAGE:latest || true + - docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest . + - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA + - docker push $CI_REGISTRY_IMAGE:latest +``` + +`build`阶段的`script`部分中的步骤可以总结为: + +1. 第一个命令尝试从注册表中提取映像,以便将其用作`docker build`命令的缓存. +2. 第二个命令使用拉取的映像作为缓存来构建 Docker 映像(请注意`--cache-from $CI_REGISTRY_IMAGE:latest`参数),并对其进行标记. +3. 最后两个命令将标记的 Docker 映像推送到容器注册表,以便它们也可用作后续构建的缓存. + +## Use the OverlayFS driver[](#use-the-overlayfs-driver "Permalink") + +**注意:**默认情况下,GitLab.com 上的共享 Runners 使用`overlay2`驱动程序. + +默认情况下,使用`docker:dind` ,Docker 使用`vfs`存储驱动程序,该驱动程序会在每次运行时复制文件系统. 这是磁盘密集型操作,如果使用其他驱动程序(例如`overlay2` ,则可以避免. + +### Requirements[](#requirements "Permalink") + +1. 确保使用最新内核,最好`>= 4.2` . +2. 检查是否已加载`overlay`模块: + + ``` + sudo lsmod | grep overlay + ``` + + 如果看不到任何结果,则说明未加载. 要加载它,请使用: + + ``` + sudo modprobe overlay + ``` + + 如果一切正常,则需要确保模块在重新启动时已加载. 在 Ubuntu 系统上,这是通过编辑`/etc/modules` . 只需将以下行添加到其中: + + ``` + overlay + ``` + +### Use the OverlayFS driver per project[](#use-the-overlayfs-driver-per-project "Permalink") + +您可以使用`.gitlab-ci.yml`的`DOCKER_DRIVER`环境[变量](../yaml/README.html#variables)分别为每个项目启用驱动程序: + +``` +variables: + DOCKER_DRIVER: overlay2 +``` + +### Use the OverlayFS driver for every project[](#use-the-overlayfs-driver-for-every-project "Permalink") + +如果使用自己的[GitLab Runners](https://docs.gitlab.com/runner/) ,则可以通过在[`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)的[`[[runners]]`部分中](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)设置`DOCKER_DRIVER`环境变量来为每个项目启用驱动程序: + +``` +environment = ["DOCKER_DRIVER=overlay2"] +``` + +如果您正在运行多个运行程序,则必须修改所有配置文件. + +**注意:**阅读有关[Runner 配置](https://docs.gitlab.com/runner/configuration/)和[使用 OverlayFS 存储驱动程序的更多信息](https://s0docs0docker0com.icopy.site/engine/userguide/storagedriver/overlayfs-driver/) . + +## Using the GitLab Container Registry[](#using-the-gitlab-container-registry "Permalink") + +构建 Docker 映像后,可以将其推送到内置的[GitLab Container Registry 中](../../user/packages/container_registry/index.html#build-and-push-images-using-gitlab-cicd) . + +## Troubleshooting[](#troubleshooting "Permalink") + +### `docker: Cannot connect to the Docker daemon at tcp://docker:2375\. Is the docker daemon running?`[](#docker-cannot-connect-to-the-docker-daemon-at-tcpdocker2375-is-the-docker-daemon-running "Permalink") + +[在 Docker](#use-docker-in-docker-workflow-with-docker-executor) v19.03 或更高版本中使用[Docker](#use-docker-in-docker-workflow-with-docker-executor)时,这是一个常见错误. + +发生这种情况是因为 Docker 自动在 TLS 上启动,因此您需要进行一些设置. 如果: + +* 这是第一次设置,请[在 Docker 工作流程中使用 Docker](#use-docker-in-docker-workflow-with-docker-executor)仔细阅读. +* 您要从 v18.09 或更早版本[升级](https://about.gitlab.com/releases/2019/07/31/docker-in-docker-with-docker-19-dot-03/) ,请阅读我们的[升级指南](https://about.gitlab.com/releases/2019/07/31/docker-in-docker-with-docker-19-dot-03/) . \ No newline at end of file diff --git a/_book/docs/218.md b/_book/docs/218.md new file mode 100644 index 0000000000000000000000000000000000000000..1d2e08533a91c8f5b7b1aa64728bf53fba0cb0ac --- /dev/null +++ b/_book/docs/218.md @@ -0,0 +1,687 @@ +# Using Docker images + +> 原文:[https://docs.gitlab.com/ee/ci/docker/using_docker_images.html](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html) + +* [Register Docker Runner](#register-docker-runner) +* [What is an image](#what-is-an-image) +* [What is a service](#what-is-a-service) + * [How services are linked to the job](#how-services-are-linked-to-the-job) + * [How the health check of services works](#how-the-health-check-of-services-works) + * [What services are not for](#what-services-are-not-for) + * [Accessing the services](#accessing-the-services) +* [Define `image` and `services` from `.gitlab-ci.yml`](#define-image-and-services-from-gitlab-ciyml) +* [Passing environment variables to services](#passing-environment-variables-to-services) +* [Extended Docker configuration options](#extended-docker-configuration-options) + * [Available settings for `image`](#available-settings-for-image) + * [Available settings for `services`](#available-settings-for-services) + * [Starting multiple services from the same image](#starting-multiple-services-from-the-same-image) + * [Setting a command for the service](#setting-a-command-for-the-service) + * [Overriding the entrypoint of an image](#overriding-the-entrypoint-of-an-image) +* [Define image and services in `config.toml`](#define-image-and-services-in-configtoml) +* [Define an image from a private Container Registry](#define-an-image-from-a-private-container-registry) + * [Requirements and limitations](#requirements-and-limitations) + * [Using statically-defined credentials](#using-statically-defined-credentials) + * [Determining your `DOCKER_AUTH_CONFIG` data](#determining-your-docker_auth_config-data) + * [Configuring a job](#configuring-a-job) + * [Configuring a Runner](#configuring-a-runner) + * [Using Credentials Store](#using-credentials-store) + * [Using Credential Helpers](#using-credential-helpers) +* [Configuring services](#configuring-services) + * [PostgreSQL service example](#postgresql-service-example) + * [MySQL service example](#mysql-service-example) +* [How Docker integration works](#how-docker-integration-works) +* [How to debug a job locally](#how-to-debug-a-job-locally) + +# Using Docker images[](#using-docker-images "Permalink") + +GitLab CI / CD 与[GitLab Runner](../runners/README.html)一起可以使用[Docker Engine](https://www.docker.com/)测试和构建任何应用程序. + +Docker 是一个开源项目,它允许您使用预定义的映像在单个 Linux 实例中运行的独立"容器"中运行应用程序. [Docker Hub](https://hub.docker.com/)具有丰富的预构建映像数据库,可用于测试和构建您的应用程序. + +与 GitLab CI / CD 一起使用时,Docker 使用[`.gitlab-ci.yml`](../yaml/README.html)设置的预定义映像在单独的隔离容器中运行每个作业. + +这使得拥有可以在您的工作站上运行的简单且可复制的构建环境更加容易. 额外的好处是您可以测试稍后将在您的 Shell 中探索的所有命令,而不必在专用的 CI 服务器上对其进行测试. + +## Register Docker Runner[](#register-docker-runner "Permalink") + +要将 GitLab Runner 与 Docker 一起使用,您需要[注册一个新的 Runner](https://docs.gitlab.com/runner/register/)以使用`docker` executor. + +An example can be seen below. First we set up a temporary template to supply the services: + +``` +cat > /tmp/test-config.template.toml << EOF [[runners]] +[runners.docker] +[[runners.docker.services]] +name = "postgres:latest" +[[runners.docker.services]] +name = "mysql:latest" EOF +``` + +然后,我们使用刚刚创建的模板注册跑步者: + +``` +sudo gitlab-runner register \ + --url "https://gitlab.example.com/" \ + --registration-token "PROJECT_REGISTRATION_TOKEN" \ + --description "docker-ruby:2.6" \ + --executor "docker" \ + --template-config /tmp/test-config.template.toml \ + --docker-image ruby:2.6 +``` + +注册的运行器将使用`ruby:2.6` Docker 映像,并将运行两个服务`postgres:latest`和`mysql:latest` ,在构建过程中均可访问这两个服务. + +## What is an image[](#what-is-an-image "Permalink") + +`image`关键字是 Docker 执行程序将运行以执行 CI 任务的 Docker 映像的名称. + +默认情况下,执行程序仅从[Docker Hub](https://hub.docker.com/)提取图像,但是可以通过设置[Docker 提取策略](https://docs.gitlab.com/runner/executors/docker.html)以允许使用本地映像在`gitlab-runner/config.toml`进行配置. + +有关映像和 Docker Hub 的更多信息,请阅读[Docker Fundamentals](https://s0docs0docker0com.icopy.site/engine/understanding-docker/)文档. + +## What is a service[](#what-is-a-service "Permalink") + +`services`关键字仅定义在您的工作期间运行的另一个 Docker 映像,并链接到`image`关键字定义的 Docker 映像. 这样,您就可以在构建期间访问服务映像. + +服务映像可以运行任何应用程序,但是最常见的用例是运行数据库容器,例如`mysql` . 与每次安装项目时都安装`mysql`相比,使用现有映像并将其作为附加容器运行更容易,更快捷. + +您不仅限于仅具有数据库服务. 您可以将所需的服务添加到`.gitlab-ci.yml`或手动修改`config.toml` . 在[Docker Hub](https://hub.docker.com/)或您的私有 Container Registry 中找到的任何映像都可以用作服务. + +服务继承与 CI 容器本身相同的 DNS 服务器,搜索域和其他主机. + +您可以在[CI 服务示例](../services/README.html)的相关文档中看到一些广泛使用的[服务示例](../services/README.html) . + +### How services are linked to the job[](#how-services-are-linked-to-the-job "Permalink") + +为了更好地了解容器链接的工作方式,请阅读[将容器链接在一起](https://s0docs0docker0com.icopy.site/engine/userguide/networking/default_network/dockerlinks/) . + +总而言之,如果将`mysql`作为服务添加到应用程序,则该映像将用于创建链接到作业容器的容器. + +The service container for MySQL will be accessible under the hostname `mysql`. So, in order to access your database service you have to connect to the host named `mysql` instead of a socket or `localhost`. Read more in [accessing the services](#accessing-the-services). + +### How the health check of services works[](#how-the-health-check-of-services-works "Permalink") + +服务旨在提供可通过**网络访问的**附加功能. 它可能是一个数据库,例如 MySQL 或 Redis,甚至是`docker:stable-dind` ,它允许您在 Docker 中使用 Docker. CI / CD 作业继续进行并可以通过网络进行访问几乎是任何事情. + +为确保此方法有效,跑步者: + +1. 检查默认情况下哪些端口从容器中暴露出来. +2. 启动一个特殊的容器,等待这些端口可访问. + +当检查的第二阶段失败时(由于服务中没有打开的端口,或者由于在超时之前服务未正确启动且端口没有响应),它会显示警告: `*** WARNING: Service XYZ probably didn't start properly` . + +在大多数情况下,它将影响作业,但是在某些情况下,即使打印了该警告,作业仍将成功. 例如: + +* 发出警告后不久,该服务已启动,并且该作业从一开始就没有使用链接的服务. 在那种情况下,当作业需要访问服务时,它可能已经在那里等待连接. +* 服务容器不提供任何网络服务,但是它正在使用作业的目录(所有服务都将作业目录作为卷挂载在`/builds` ). 在这种情况下,服务将完成其工作,并且由于该工作未尝试与其连接,因此它不会失败. + +### What services are not for[](#what-services-are-not-for "Permalink") + +如前所述,此功能旨在提供**网络可访问的**服务. 数据库是此类服务的最简单示例. + +**注意:**服务功能并非旨在且不会将已定义的`services`映像中的任何软件添加到作业的容器中. + +例如,如果您在作业中定义了以下`services` ,则脚本**无法**使用`php` , `node`或`go`命令,因此该作业将失败: + +``` +job: + services: + - php:7 + - node:latest + - golang:1.10 + image: alpine:3.7 + script: + - php -v + - node -v + - go version +``` + +如果你需要有`php` , `node`和`go`供你的脚本,你应该: + +* 选择一个包含所有必需工具的现有 Docker 映像. +* 创建您自己的 Docker 映像,它将包含所有必需的工具,并在您的工作中使用它. + +### Accessing the services[](#accessing-the-services "Permalink") + +假设您需要一个 Wordpress 实例来测试与应用程序的某些 API 集成. + +然后,您可以在`.gitlab-ci.yml`使用例如[tutum / wordpress](https://hub.docker.com/r/tutum/wordpress/)图像: + +``` +services: + - tutum/wordpress:latest +``` + +如果未[指定服务别名](#available-settings-for-services) ,则在运行作业时,将启动`tutum/wordpress` ,您将可以从构建容器中使用以下两个主机名访问它: + +* `tutum-wordpress` +* `tutum__wordpress` + +**注意:**带下划线的主机名是 RFC 无效的,可能会导致第三方应用程序出现问题. + +服务主机名的默认别名是根据以下规则从其映像名称创建的: + +* 冒号后一切( `:` )被剥离. +* 将斜杠( `/` )替换为双下划线( `__` ),并创建主别名. +* 斜杠( `/` )替换为单破折号( `-` ),并创建了辅助别名(需要 GitLab Runner v1.1.0 或更高版本). + +要覆盖默认行为,可以[指定服务别名](#available-settings-for-services) . + +## Define `image` and `services` from `.gitlab-ci.yml`[](#define-image-and-services-from-gitlab-ciyml "Permalink") + +您可以简单地定义将用于所有作业的映像以及要在构建期间使用的服务列表: + +``` +default: + image: ruby:2.6 + + services: + - postgres:11.7 + + before_script: + - bundle install + +test: + script: + - bundle exec rake spec +``` + +图像名称必须采用以下格式之一: + +* `image: <image-name>` (同使用`<image-name>`与`latest`标签) +* `image: <image-name>:<tag>` +* `image: <image-name>@<digest>` + +还可以为每个作业定义不同的图像和服务: + +``` +default: + before_script: + - bundle install + +test:2.6: + image: ruby:2.6 + services: + - postgres:11.7 + script: + - bundle exec rake spec + +test:2.7: + image: ruby:2.7 + services: + - postgres:12.2 + script: + - bundle exec rake spec +``` + +或者,您可以传递一些[扩展](#extended-docker-configuration-options)的`image`和`services` [配置选项](#extended-docker-configuration-options) : + +``` +default: + image: + name: ruby:2.6 + entrypoint: ["/bin/bash"] + + services: + - name: my-postgres:11.7 + alias: db-postgres + entrypoint: ["/usr/local/bin/db-postgres"] + command: ["start"] + + before_script: + - bundle install + +test: + script: + - bundle exec rake spec +``` + +## Passing environment variables to services[](#passing-environment-variables-to-services "Permalink") + +您还可以传递自定义环境[变量,](../variables/README.html)以直接在`.gitlab-ci.yml`文件中微调 Docker `images`和`services` . 有关更多信息,请参见[自定义环境变量.](../variables/README.html#gitlab-ciyml-defined-variables) + +``` +# The following variables will automatically be passed down to the Postgres container +# as well as the Ruby container and available within each. +variables: + HTTPS_PROXY: "https://10.1.1.1:8090" + HTTP_PROXY: "https://10.1.1.1:8090" + POSTGRES_DB: "my_custom_db" + POSTGRES_USER: "postgres" + POSTGRES_PASSWORD: "example" + PGDATA: "/var/lib/postgresql/data" + POSTGRES_INITDB_ARGS: "--encoding=UTF8 --data-checksums" + +services: + - name: postgres:11.7 + alias: db + entrypoint: ["docker-entrypoint.sh"] + command: ["postgres"] + +image: + name: ruby:2.6 + entrypoint: ["/bin/bash"] + +before_script: + - bundle install + +test: + script: + - bundle exec rake spec +``` + +## Extended Docker configuration options[](#extended-docker-configuration-options "Permalink") + +在 GitLab 和 GitLab Runner 9.4 中引入. + +配置`image`或`services`条目时,可以使用字符串或地图作为选项: + +* 使用字符串作为选项时,它必须是要使用的映像的全名(如果要从 Docker Hub 以外的注册表中下载映像,则应包括注册表部分) +* 使用地图作为选项时,它必须至少包含`name`选项,该名称与用于字符串设置的图像名称相同 + +例如,以下两个定义相等: + +1. 使用字符串作为`image`和`services`的选项: + + ``` + image: "registry.example.com/my/image:latest" + + services: + - postgresql:9.4 + - redis:latest + ``` + +2. 使用地图作为`image`和`services`的选项. 必须使用`image:name` : + + ``` + image: + name: "registry.example.com/my/image:latest" + + services: + - name: postgresql:9.4 + - name: redis:latest + ``` + +### Available settings for `image`[](#available-settings-for-image "Permalink") + +在 GitLab 和 GitLab Runner 9.4 中引入. + +| Setting | Required | GitLab 版本 | Description | +| --- | --- | --- | --- | +| `name` | 是的,当与任何其他选项一起使用时 | 9.4 | 应使用的图像的全名. 如果需要,它应包含注册表部分. | +| `entrypoint` | no | 9.4 | 应该作为容器的入口点执行的命令或脚本. 创建容器时,它将转换为 Docker 的`--entrypoint`选项. 语法类似于[`Dockerfile`的`ENTRYPOINT`](https://s0docs0docker0com.icopy.site/engine/reference/builder/)指令,其中每个 shell 令牌是数组中的单独字符串. | + +### Available settings for `services`[](#available-settings-for-services "Permalink") + +在 GitLab 和 GitLab Runner 9.4 中引入. + +| Setting | Required | GitLab 版本 | Description | +| --- | --- | --- | --- | +| `name` | 是的,当与任何其他选项一起使用时 | 9.4 | Full name of the image that should be used. It should contain the Registry part if needed. | +| `entrypoint` | no | 9.4 | 应该作为容器的入口点执行的命令或脚本. 创建容器时,它将转换为 Docker 的`--entrypoint`选项. 语法类似于[`Dockerfile`的`ENTRYPOINT`](https://s0docs0docker0com.icopy.site/engine/reference/builder/)指令,其中每个 shell 令牌是数组中的单独字符串. | +| `command` | no | 9.4 | 应该用作容器命令的命令或脚本. 它将转换为映像名称后传递给 Docker 的参数. 语法类似于[`Dockerfile`的`CMD`](https://s0docs0docker0com.icopy.site/engine/reference/builder/)指令,其中每个 shell 令牌是数组中的单独字符串. | +| `alias` | no | 9.4 | 可用于从作业的容器访问服务的其他别名. 请阅读[访问服务](#accessing-the-services)以获取更多信息. | + +**注意:** GitLab Runner 12.8 [引入](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2229)了对 Kubernetes 执行器的别名支持,并且仅对 Kubernetes 1.7 或更高版本可用. + +### Starting multiple services from the same image[](#starting-multiple-services-from-the-same-image "Permalink") + +在 GitLab 和 GitLab Runner 9.4 中引入. 阅读有关[扩展配置选项的](#extended-docker-configuration-options)更多信息. + +在使用新的扩展 Docker 配置选项之前,以下配置将无法正常工作: + +``` +services: + - mysql:latest + - mysql:latest +``` + +The Runner would start two containers using the `mysql:latest` image, but both of them would be added to the job’s container with the `mysql` alias based on the [default hostname naming](#accessing-the-services). This would end with one of the services not being accessible. + +在新的扩展 Docker 配置选项之后,以上示例将如下所示: + +``` +services: + - name: mysql:latest + alias: mysql-1 + - name: mysql:latest + alias: mysql-2 +``` + +Runner 仍将使用`mysql:latest`映像启动两个容器,但是现在每个容器也可以使用`.gitlab-ci.yml`文件中配置的别名进行访问. + +### Setting a command for the service[](#setting-a-command-for-the-service "Permalink") + +在 GitLab 和 GitLab Runner 9.4 中引入. 阅读有关[扩展配置选项的](#extended-docker-configuration-options)更多信息. + +假设您有一个`super/sql:latest`映像,其中包含一些 SQL 数据库,并且想将其用作您的工作服务. 我们还假设该映像在启动容器时不会启动数据库进程,并且用户需要手动使用`/usr/bin/super-sql run`作为命令来启动数据库. + +在使用新的扩展 Docker 配置选项之前,您需要基于`super/sql:latest`映像创建自己的映像,添加默认命令,然后在作业的配置中使用它,例如: + +``` +# my-super-sql:latest image's Dockerfile + +FROM super/sql:latest +CMD ["/usr/bin/super-sql", "run"] +``` + +``` +# .gitlab-ci.yml + +services: + - my-super-sql:latest +``` + +在新的扩展 Docker 配置选项之后,您现在可以简单地在`.gitlab-ci.yml`设置`command` ,例如: + +``` +# .gitlab-ci.yml + +services: + - name: super/sql:latest + command: ["/usr/bin/super-sql", "run"] +``` + +如您所见, `command`的语法类似于[Dockerfile 的`CMD`](https://s0docs0docker0com.icopy.site/engine/reference/builder/) . + +### Overriding the entrypoint of an image[](#overriding-the-entrypoint-of-an-image "Permalink") + +在 GitLab 和 GitLab Runner 9.4 中引入. 阅读有关[扩展配置选项的](#extended-docker-configuration-options)更多信息. + +在显示可用的入口点覆盖方法之前,让我们简要介绍一下 Runner 如何启动以及如何将 Docker 映像用于 CI 作业中使用的容器: + +1. Runner 使用定义的入口点启动 Docker 容器( `Dockerfile`中的默认值,该文件可能会在`.gitlab-ci.yml`覆盖) +2. 跑步者将自己附加到正在运行的容器上. +3. 跑步者准备一个脚本( [`before_script`](../yaml/README.html#before_script-and-after_script) , [`script`](../yaml/README.html#script)和[`after_script`](../yaml/README.html#before_script-and-after_script)的组合). +4. 运行程序将脚本发送到容器的外壳 STDIN 并接收输出. + +要覆盖 Docker 映像的入口点,建议的解决方案是在`.gitlab-ci.yml`定义一个空`entrypoint` `.gitlab-ci.yml` ,以便 Runner 不会启动无用的 shell 层. 但是,这不适用于所有 Docker 版本,因此您应检查 Runner 使用的是哪个版本. 特别: + +* 如果使用 Docker 17.06 或更高版本,则`entrypoint`可以设置为空值. +* 如果使用 Docker 17.03 或更早版本,则`entrypoint`可以设置为`/bin/sh -c` , `/bin/bash -c`或映像中可用的等效 shell. + +`image:entrypoint`的语法类似于[Dockerfile 的`ENTRYPOINT`](https://s0docs0docker0com.icopy.site/engine/reference/builder/) . + +假设您有一个`super/sql:experimental`映像,其中包含一些 SQL 数据库,并且您想将其用作工作的基础映像,因为您想使用此数据库二进制文件执行一些测试. 我们还假设此映像是使用`/usr/bin/super-sql run`作为入口点配置的. 这意味着在启动没有其他选项的容器时,它将运行数据库的进程,而 Runner 希望映像没有入口点,或者入口点已准备好启动 Shell 命令. + +使用扩展的 Docker 配置选项,而不是基于`super/sql:experimental`创建自己的映像,将`ENTRYPOINT`设置为 shell,然后在 CI 作业中使用新映像,您现在只需在`.gitlab-ci.yml`定义一个`entrypoint` `.gitlab-ci.yml` . + +**对于 Docker 17.06+:** + +``` +image: + name: super/sql:experimental + entrypoint: [""] +``` + +**对于 Docker = <17.03:** + +``` +image: + name: super/sql:experimental + entrypoint: ["/bin/sh", "-c"] +``` + +## Define image and services in `config.toml`[](#define-image-and-services-in-configtoml "Permalink") + +查找`[runners.docker]`部分: + +``` +[runners.docker] + image = "ruby:latest" + services = ["mysql:latest", "postgres:latest"] +``` + +以这种方式定义的图像和服务将添加到该运行程序运行的所有作业中. + +## Define an image from a private Container Registry[](#define-an-image-from-a-private-container-registry "Permalink") + +要访问私有容器注册表,GitLab Runner 进程可以使用: + +* [静态定义的凭证](#using-statically-defined-credentials) . 也就是说,特定注册表的用户名和密码. +* [凭证存储](#using-credentials-store) . 有关更多信息,请参阅[相关的 Docker 文档](https://docs.docker.com/engine/reference/commandline/login/#credentials-store) . +* [凭证助手](#using-credential-helpers) . 有关更多信息,请参阅[相关的 Docker 文档](https://docs.docker.com/engine/reference/commandline/login/#credential-helpers) . + +为了定义应该使用哪个,GitLab Runner 进程按以下顺序读取配置: + +* `DOCKER_AUTH_CONFIG`变量提供为: + * `.gitlab-ci.yml` [变量](../variables/README.html#gitlab-cicd-environment-variables) . + * 项目的变量存储在项目的**"设置">" CI / CD"**页面上. +* Runner 的`config.toml`中提供了`DOCKER_AUTH_CONFIG`变量作为环境变量. +* `config.json`文件放置在运行 GitLab Runner 进程的用户的`$HOME/.docker`目录中. 如果提供了`--user`标志以非特权用户身份运行 GitLab Runner 子进程,则将使用 GitLab Runner 主进程用户的主目录. + +**注意:** GitLab Runner **仅从** `config.toml`读取此配置,并且如果它是作为环境变量提供的,则忽略它. 这是因为 GitLab Runner **仅**使用`config.toml`配置,并且不会在运行时内插**任何**环境变量. + +### Requirements and limitations[](#requirements-and-limitations "Permalink") + +* 此功能需要 GitLab Runner **1.8**或更高版本. +* 对于**> = 0.6,<1.8 的** GitLab Runner 版本**,**部分支持使用私有注册表,这要求在运行者的主机上手动配置凭据. 如果要使用私人注册表,建议将 Runner 至少升级到**1.8**版. +* 在 GitLab Runner 13.1 和更高版本中适用于[Kubernetes 执行器](https://docs.gitlab.com/runner/executors/kubernetes.html) . + +### Using statically-defined credentials[](#using-statically-defined-credentials "Permalink") + +您可以采用两种方法来访问私有注册表. 两者都需要使用适当的身份验证信息设置环境变量`DOCKER_AUTH_CONFIG` . + +1. 每个作业:要配置一个作业以访问专用注册表,请添加`DOCKER_AUTH_CONFIG`作为作业变量. +2. 每个运行者:要配置 Runner 以便其所有作业都可以访问私有注册表,请在 Runner 的配置中将`DOCKER_AUTH_CONFIG`添加到环境中. + +请参阅下面的示例. + +#### Determining your `DOCKER_AUTH_CONFIG` data[](#determining-your-docker_auth_config-data "Permalink") + +例如,假设您要使用`registry.example.com:5000/private/image:latest`映像,该映像是私有映像,需要您登录到私有容器注册表. + +我们还假设这些是登录凭据: + +| Key | Value | +| --- | --- | +| registry | `registry.example.com:5000` | +| username | `my_username` | +| password | `my_password` | + +有两种方法可以确定`DOCKER_AUTH_CONFIG`的值: + +* **第一种方法-**在本地计算机上进行`docker login` : + + ``` + docker login registry.example.com:5000 --username my_username --password my_password + ``` + + 然后复制`~/.docker/config.json` . + + 如果您不需要从计算机访问注册表,则可以执行`docker logout` : + + ``` + docker logout registry.example.com:5000 + ``` + +* **第二种方式-**在某些设置中,Docker 客户端可能会使用可用的系统密钥存储区来存储`docker login`的结果. 在这种情况下,无法读取`~/.docker/config.json` ,因此您将需要准备所需的`${username}:${password}` base64 编码版本,并手动创建 Docker 配置 JSON. 打开一个终端并执行以下命令: + + ``` + # Note the use of "-n" - it prevents encoding a newline in the password. + echo -n "my_username:my_password" | base64 + + # Example output to copy + bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ= + ``` + + 创建 Docker JSON 配置内容,如下所示: + + ``` + { "auths": { "registry.example.com:5000": { "auth": "(Base64 content from above)" } } } + ``` + +#### Configuring a job[](#configuring-a-job "Permalink") + +要配置具有对`registry.example.com:5000`访问权限的单个作业,请按照下列步骤操作: + +1. 创建一个[变量](../variables/README.html#gitlab-cicd-environment-variables) `DOCKER_AUTH_CONFIG` ,并将 Docker 配置文件的内容作为值: + + ``` + { "auths": { "registry.example.com:5000": { "auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=" } } } + ``` + +2. 现在,您可以使用`.gitlab-ci.yml`文件中`image`和/或`services`中定义的`registry.example.com:5000`任何私有图像: + + ``` + image: registry.example.com:5000/namespace/image:tag + ``` + + 在上面的例子,GitLab 转轮会看`registry.example.com:5000`用于图像`namespace/image:tag` . + +您可以根据需要添加任意数量的注册表配置,如上所述,将更多注册表添加到`"auths"`哈希中. + +**注意:** Runner 到处都需要完整的`hostname:port`组合,以使其与`DOCKER_AUTH_CONFIG`相匹配. 例如,如果`registry.example.com:5000/namespace/image:tag`中指定`.gitlab-ci.yml` ,则`DOCKER_AUTH_CONFIG`还必须指定`registry.example.com:5000` . 仅指定`registry.example.com`将不起作用. + +### Configuring a Runner[](#configuring-a-runner "Permalink") + +如果您有许多访问同一注册表的管道,最好在运行程序级别设置注册表访问. 这使管道作者仅通过在适当的运行程序上运行作业即可访问私有注册表. 这也使注册表更改和凭据轮换更加简单. + +当然,这意味着该运行程序上的任何作业都可以使用相同的特权访问注册表,即使在整个项目中也是如此. 如果需要控制对注册表的访问,则需要确保控制对运行器的访问. + +要将`DOCKER_AUTH_CONFIG`添加到运行器: + +1. 修改 Runner 的`config.toml`文件,如下所示: + + ``` + [[runners]] + environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"registry.example.com:5000\":{\"auth\":\"bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=\"}}}"] + ``` + +2. 重新启动 Runner 服务. + +**注意:** `DOCKER_AUTH_CONFIG`数据中包含的双引号必须使用反斜杠转义. 这样可以防止将它们解释为 TOML.**注意:** `environment`选项是一个列表. 因此,您的跑步者可能已有条目,您应该将其添加到列表中,而不是替换它. + +### Using Credentials Store[](#using-credentials-store "Permalink") + +> 在 GitLab Runner 9.5 中添加了对使用凭据存储的支持. + +要配置凭据存储,请按照下列步骤操作: + +1. 要使用凭据存储,您需要一个外部帮助程序来与特定的钥匙串或外部存储进行交互. 确保 GitLab Runner `$PATH`有可用的帮助程序. + +2. 使 GitLab Runner 使用它. 有两种方法可以完成此操作. 要么: + + * 创建一个[变量](../variables/README.html#gitlab-cicd-environment-variables) `DOCKER_AUTH_CONFIG` ,并将 Docker 配置文件的内容作为值: + + ``` + { "credsStore": "osxkeychain" } + ``` + + * 或者,如果您正在运行自我管理的`${GITLAB_RUNNER_HOME}/.docker/config.json` ,请将上面的 JSON 添加到`${GITLAB_RUNNER_HOME}/.docker/config.json` . GitLab Runner 将读取此配置文件,并将使用此特定存储库所需的帮助程序. + +**注意:** `credsStore`用于访问所有注册表. 如果要同时使用私有注册表中的映像和 DockerHub 中的公共映像,则从 DockerHub 提取将失败,因为 Docker 守护程序将尝试对**所有**注册表使用相同的凭据. + +### Using Credential Helpers[](#using-credential-helpers "Permalink") + +> 在 GitLab Runner 12.0 中添加了对使用凭据助手的支持 + +作为示例,假设您要使用`aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest`映像,该映像是私有的,需要您登录到私有容器注册表. + +要配置`aws_account_id.dkr.ecr.region.amazonaws.com`访问`aws_account_id.dkr.ecr.region.amazonaws.com` ,请按照以下步骤操作: + +1. 确保`docker-credential-ecr-login`在 GitLab Runner 的`$PATH`可用. + +2. 具有以下任何[AWS 凭证设置](https://github.com/awslabs/amazon-ecr-credential-helper#aws-credentials) . 确保 GitLab Runner 可以访问凭据. + +3. 使 GitLab Runner 使用它. 有两种方法可以完成此操作. 要么: + + * 创建一个[变量](../variables/README.html#gitlab-cicd-environment-variables) `DOCKER_AUTH_CONFIG` ,并将 Docker 配置文件的内容作为值: + + ``` + { "credHelpers": { "aws_account_id.dkr.ecr.region.amazonaws.com": "ecr-login" } } + ``` + + 这会将 Docker 配置为对特定注册表使用凭据帮助器. + + or + + ``` + { "credsStore": "ecr-login" } + ``` + + 这会将 Docker 配置为对所有 Amazon ECR 注册表使用凭证帮助器. + + * 或者,如果您正在运行自我管理的`${GITLAB_RUNNER_HOME}/.docker/config.json` ,请将上面的 JSON 添加到`${GITLAB_RUNNER_HOME}/.docker/config.json` . GitLab Runner 将读取此配置文件,并将使用此特定存储库所需的帮助程序. + +4. 现在,您可以使用`.gitlab-ci.yml`文件中`image`和/或`services`中定义的`aws_account_id.dkr.ecr.region.amazonaws.com`任何私有图像: + + ``` + image: aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest + ``` + + 在上面的示例中,GitLab Runner 将查看`aws_account_id.dkr.ecr.region.amazonaws.com`中的图像`private/image:latest` . + +您可以根据需要添加`"credHelpers"`数量的注册表配置,如上所述,将更多注册表添加到`"credHelpers"`哈希中. + +## Configuring services[](#configuring-services "Permalink") + +许多服务接受环境变量,这些变量使您可以根据环境轻松更改数据库名称或设置帐户名称. + +GitLab Runner 0.5.0 及更高版本将所有 YAML 定义的变量传递到创建的服务容器. + +For all possible configuration variables check the documentation of each image provided in their corresponding Docker hub page. + +**注意:**所有变量都将传递到所有服务容器. 它并非旨在区分哪个变量应该放在哪里. + +### PostgreSQL service example[](#postgresql-service-example "Permalink") + +请参阅有关将[PostgreSQL 用作服务](../services/postgres.html)的特定文档. + +### MySQL service example[](#mysql-service-example "Permalink") + +请参阅有关将[MySQL 用作服务](../services/mysql.html)的特定文档. + +## How Docker integration works[](#how-docker-integration-works "Permalink") + +以下是 Docker 在作业期间执行的步骤的高级概述. + +1. 创建任何服务容器: `mysql` , `postgresql` , `mongodb` , `redis` . +2. 创建缓存容器以存储`config.toml`和构建映像的`Dockerfile`中定义的所有卷(如上例中的`ruby:2.6` ). +3. 创建构建容器并将任何服务容器链接到构建容器. +4. 启动构建容器并将作业脚本发送到该容器. +5. 运行作业脚本. +6. 检出代码: `/builds/group-name/project-name/` . +7. 运行`.gitlab-ci.yml`定义的任何步骤. +8. 检查构建脚本的退出状态. +9. 删除构建容器和所有创建的服务容器. + +## How to debug a job locally[](#how-to-debug-a-job-locally "Permalink") + +**注意:**以下命令在没有 root 特权的情况下运行. 您应该能够使用常规用户帐户运行 Docker. + +首先从创建一个名为`build_script`的文件`build_script` : + +``` +cat <<EOF > build_script +git clone https://gitlab.com/gitlab-org/gitlab-runner.git /builds/gitlab-org/gitlab-runner +cd /builds/gitlab-org/gitlab-runner +make EOF +``` + +在这里,我们以包含 Makefile 的 GitLab Runner 存储库为例,因此运行`make`将执行 Makefile 中定义的命令. 您的里程可能会有所不同,所以不是`make`你可以运行它是特定于项目的命令. + +然后创建一些服务容器: + +``` +docker run -d --name service-mysql mysql:latest +docker run -d --name service-postgres postgres:latest +``` + +这将创建两个服务容器,分别名为`service-mysql`和`service-postgres` ,它们分别使用最新的 MySQL 和 PostgreSQL 映像. 它们都将在后台( `-d` )运行. + +最后,通过执行我们之前创建的`build_script`文件来创建构建容器: + +``` +docker run --name build -i --link=service-mysql:mysql --link=service-postgres:postgres ruby:2.6 /bin/bash < build_script +``` + +上面的命令将创建一个名为`build`的容器,该容器是从`ruby:2.6`镜像派生的,并且有两个链接到它的服务. 使用 STDIN 将`build_script`通过管道传输到 bash 解释器,然后 bash 解释器将在`build`容器中执行`build_script` . + +完成测试后,不再需要这些容器时,可以使用以下方法删除它们: + +``` +docker rm -f -v build service-mysql service-postgres +``` + +这将强制( `-f` )删除`build`容器,两个服务容器以及随容器创建而创建的所有卷( `-v` ). \ No newline at end of file diff --git a/_book/docs/219.md b/_book/docs/219.md new file mode 100644 index 0000000000000000000000000000000000000000..f556d8c15e2fee018f8927a7f3bba8ab1e947637 --- /dev/null +++ b/_book/docs/219.md @@ -0,0 +1,88 @@ +# Building images with kaniko and GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/docker/using_kaniko.html](https://docs.gitlab.com/ee/ci/docker/using_kaniko.html) + +* [Requirements](#requirements) +* [Building a Docker image with kaniko](#building-a-docker-image-with-kaniko) +* [Using a registry with a custom certificate](#using-a-registry-with-a-custom-certificate) +* [Video walkthrough of a working example](#video-walkthrough-of-a-working-example) + +# Building images with kaniko and GitLab CI/CD[](#building-images-with-kaniko-and-gitlab-cicd "Permalink") + +在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45512) . 需要 GitLab Runner 11.2 及更高版本. + +[kaniko](https://github.com/GoogleContainerTools/kaniko)是从容器或 Kubernetes 集群内部的 Dockerfile 构建容器映像的工具. + +kaniko 使用[Docker-in-Docker 构建](using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor)方法解决了两个问题: + +* Docker-in-Docker 需要[特权模式](https://s0docs0docker0com.icopy.site/engine/reference/run/)才能运行,这是一个重大的安全问题. +* Docker-in-Docker 通常会导致性能下降,并且可能会非常慢. + +## Requirements[](#requirements "Permalink") + +为了在 GitLab 中使用 kaniko,需要使用以下执行程序之一的[GitLab Runner](https://docs.gitlab.com/runner/) : + +* [Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html). +* [Docker](https://docs.gitlab.com/runner/executors/docker.html). +* [Docker Machine](https://docs.gitlab.com/runner/executors/docker_machine.html). + +## Building a Docker image with kaniko[](#building-a-docker-image-with-kaniko "Permalink") + +使用 kaniko 和 GitLab CI / CD 构建映像时,应注意一些重要细节: + +* 推荐使用 kaniko 调试映像( `gcr.io/kaniko-project/executor:debug` ),因为它具有外壳,并且该映像与 GitLab CI / CD 一起使用时需要外壳. +* 入口点将需要被[覆盖](using_docker_images.html#overriding-the-entrypoint-of-an-image) ,否则构建脚本将无法运行. +* 需要使用所需容器注册表的身份验证信息创建一个 Docker `config.json`文件. + +In the following example, kaniko is used to: + +1. 构建一个 Docker 镜像 +2. 然后将其推送到[GitLab 容器注册表](../../user/packages/container_registry/index.html) . + +仅当按下标签时作业才会运行. 使用从 GitLab CI / CD 提供的[环境变量中](../variables/README.html#predefined-environment-variables)获取的所需 GitLab 容器注册表凭据在`/kaniko/.docker`下创建一个`config.json`文件. + +在最后一步中,kaniko 使用项目根目录下的`Dockerfile` ,构建 Docker 映像并将其推送到项目的 Container Registry,同时使用 Git 标签对其进行标记: + +``` +build: + stage: build + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] + script: + - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json + - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG + only: + - tags +``` + +## Using a registry with a custom certificate[](#using-a-registry-with-a-custom-certificate "Permalink") + +尝试推送到使用由自定义 CA 签名的证书的 Docker 注册表时,您可能会遇到以下错误: + +``` +$ /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --no-push +INFO[0000] Downloading base image registry.gitlab.example.com/group/docker-image +error building image: getting stage builder for stage 0: Get https://registry.gitlab.example.com/v2/: x509: certificate signed by unknown authority +``` + +可以通过将您的 CA 证书添加到 kaniko 证书存储区来解决: + +``` + before_script: + - mkdir -p /kaniko/.docker + - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json + - | + echo "-----BEGIN CERTIFICATE----- + ... + -----END CERTIFICATE-----" >> /kaniko/ssl/certs/additional-ca-cert-bundle.crt +``` + +## Video walkthrough of a working example[](#video-walkthrough-of-a-working-example "Permalink") + +[在 GitLab](https://www.youtube.com/watch?v=d96ybcELpFs)视频[上使用 Kaniko](https://www.youtube.com/watch?v=d96ybcELpFs)的[最低权限容器构建](https://www.youtube.com/watch?v=d96ybcELpFs)是对[Kaniko Docker Build](https://gitlab.com/guided-explorations/containers/kaniko-docker-build) Guided Exploration 项目管道的演练. 经过测试: + +* [GitLab.com Shared Runners](../../user/gitlab_com/index.html#shared-runners) +* [The Kubernetes Runner executor](https://docs.gitlab.com/runner/executors/kubernetes.html) + +可以将示例复制到您自己的组或实例中进行测试. 项目页面上提供了有关演示其他 GitLab CI 模式的更多详细信息. \ No newline at end of file diff --git a/_book/docs/220.md b/_book/docs/220.md new file mode 100644 index 0000000000000000000000000000000000000000..713bd405ff07c5ae5fc3fdffa9b138877586e463 --- /dev/null +++ b/_book/docs/220.md @@ -0,0 +1,893 @@ +# GitLab CI/CD environment variables + +> 原文:[https://docs.gitlab.com/ee/ci/variables/README.html](https://docs.gitlab.com/ee/ci/variables/README.html) + +* [Predefined environment variables](#predefined-environment-variables) + * [Use predefined environment variables](#use-predefined-environment-variables) +* [Custom environment variables](#custom-environment-variables) + * [Create a custom variable in `.gitlab-ci.yml`](#create-a-custom-variable-in-gitlab-ciyml) + * [Create a custom variable in the UI](#create-a-custom-variable-in-the-ui) + * [Custom environment variables of type Variable](#custom-environment-variables-of-type-variable) + * [Custom environment variables of type File](#custom-environment-variables-of-type-file) + * [Mask a custom variable](#mask-a-custom-variable) + * [Masked variable requirements](#masked-variable-requirements) + * [Protect a custom variable](#protect-a-custom-variable) + * [Custom variables validated by GitLab](#custom-variables-validated-by-gitlab) +* [Syntax of environment variables in job scripts](#syntax-of-environment-variables-in-job-scripts) + * [Bash](#bash) + * [PowerShell](#powershell) + * [Windows Batch](#windows-batch) + * [List all environment variables](#list-all-environment-variables) +* [`.gitlab-ci.yml` defined variables](#gitlab-ciyml-defined-variables) +* [Group-level environment variables](#group-level-environment-variables) +* [Instance-level CI/CD environment variables](#instance-level-cicd-environment-variables) + * [Enable or disable UI interface for instance-level CI/CD variables](#enable-or-disable-ui-interface-for-instance-level-cicd-variables) +* [Inherit environment variables](#inherit-environment-variables) +* [Priority of environment variables](#priority-of-environment-variables) +* [Unsupported variables](#unsupported-variables) +* [Where variables can be used](#where-variables-can-be-used) +* [Advanced use](#advanced-use) + * [Limit the environment scopes of environment variables](#limit-the-environment-scopes-of-environment-variables) + * [Deployment environment variables](#deployment-environment-variables) + * [Auto DevOps environment variables](#auto-devops-environment-variables) + * [Override a variable by manually running a pipeline](#override-a-variable-by-manually-running-a-pipeline) +* [Environment variables expressions](#environment-variables-expressions) + * [Syntax of environment variable expressions](#syntax-of-environment-variable-expressions) + * [Storing regular expressions in variables](#storing-regular-expressions-in-variables) +* [Debug logging](#debug-logging) +* [Video walkthrough of a working example](#video-walkthrough-of-a-working-example) + +# GitLab CI/CD environment variables[](#gitlab-cicd-environment-variables "Permalink") + +环境变量是一个动态命名的值,它可以影响正在运行的进程在操作系统上的行为方式. + +环境变量是进程在其中运行的环境的一部分. 例如,正在运行的进程可以查询`TEMP`环境变量的值以发现合适的位置来存储临时文件,或者为可以在不同脚本中重用的数据库定义`URL` . + +变量对于在 GitLab CI / CD 中自定义作业很有用. 使用变量时,不必对值进行硬编码. + +> 有关高级使用 GitLab CI / CD 的更多信息: +> +> * 由 GitLab 工程师共享的这[7 种高级 GitLab CI 工作流程黑客,](https://about.gitlab.com/webcast/7cicd-hacks/)可以更快地提高生产力. +> * 了解 Cloud Native Computing Foundation(CNCF)如何通过 GitLab CI / CD [消除](https://about.gitlab.com/customers/cncf/)许多云提供商之间管理项目[的复杂性](https://about.gitlab.com/customers/cncf/) . + +## Predefined environment variables[](#predefined-environment-variables "Permalink") + +GitLab CI / CD 具有一组[默认的预定义变量](predefined_variables.html) ,您可以使用它们而无需任何其他说明. 您可以呼叫问题编号,用户名,分支名称,管道和提交 ID 等. + +GitLab 为 Runner 的本地环境提供了预定义的环境变量. + +GitLab 读取`.gitlab-ci.yml`文件,并将信息发送到 Runner,在此处公开变量. 然后,运行程序运行脚本命令. + +### Use predefined environment variables[](#use-predefined-environment-variables "Permalink") + +您可以选择现有的预定义变量之一,以由 Runner 输出. + +本示例说明如何使用预定义变量`CI_JOB_STAGE`输出作业的阶段. + +在您的`.gitlab-ci.yml`文件中,从脚本中调用变量. 确保使用正确的[语法](#syntax-of-environment-variables-in-job-scripts) . + +``` +test_variable: + stage: test + script: + - echo $CI_JOB_STAGE +``` + +在这种情况下,跑步者输出工作`test_variable`的`stage` ,即`test` : + +[![Output `$CI_JOB_STAGE`](img/b6a9c5aa2e348263baf61cb961ac802f.png)](img/ci_job_stage_output_example.png) + +再举一个例子,假设您使用自己的 GitLab 实例,并且想知道 GitLab 页面在哪个域下提供服务. 您可以通过在脚本中使用预定义变量`$CI_PAGES_DOMAIN`来调用它: + +``` +pages: + script: + - ... + - echo $CI_PAGES_DOMAIN +``` + +对于 GitLab.com 用户,输出将为`gitlab.io` . 对于您的私有实例,输出将是您的系统管理员定义的任何内容. + +## Custom environment variables[](#custom-environment-variables "Permalink") + +当需要特定的自定义环境变量时,可以[在 UI](#create-a-custom-variable-in-the-ui)中[,API](../../api/project_level_variables.html)中或直接[在`.gitlab-ci.yml`文件中进行设置](#create-a-custom-variable-in-gitlab-ciyml) . + +每当管道运行时,Runner 就会使用这些变量. 您还[可以手动覆盖特定管道的变量值](../pipelines/index.html#specifying-variables-when-running-manual-jobs) . + +变量有两种类型: **Variable**和**File** . 您无法在`.gitlab-ci.yml`文件中设置类型,但可以在 UI 和 API 中进行设置. + +### Create a custom variable in `.gitlab-ci.yml`[](#create-a-custom-variable-in-gitlab-ciyml "Permalink") + +要创建自定义`env_var`在可变[`.gitlab-ci.yml`](../yaml/README.html#variables)文件中,定义下的变量/值对`variables` : + +``` +variables: + TEST: "HELLO WORLD" +``` + +然后,您可以在脚本中调用其值: + +``` + script: + - echo "$TEST" +``` + +有关更多详细信息,请参见[`.gitlab-ci.yml`定义的变量](#gitlab-ciyml-defined-variables) . + +### Create a custom variable in the UI[](#create-a-custom-variable-in-the-ui "Permalink") + +在用户界面中,您可以添加或更新自定义环境变量: + +1. 转到项目的**"设置">" CI / CD",**然后展开" **变量"**部分. +2. 单击**添加变量**按钮. 在" **添加变量**模式"中,填写详细信息: + + * **密钥** :必须是一行,没有空格,只能使用字母,数字或`_` . + * **价值** :无限制. + * **Type**: `File` or `Variable`. + * **环境范围** : `All`或特定环境. + * **保护变量** (可选):如果选中,则该变量将仅在在受保护的分支或标签上运行的管道中可用. + * **屏蔽变量** (可选):如果选中,则变量的**值**将在作业日志中被屏蔽. 如果该值不满足[屏蔽要求,](#masked-variable-requirements)则变量将无法保存. + +创建变量后,您可以通过点击 **编辑**按钮. + +设置变量后,请从`.gitlab-ci.yml`文件中调用它: + +``` +test_variable: + stage: test + script: + - echo $CI_JOB_STAGE # calls a predefined variable + - echo $TEST # calls a custom variable of type `env_var` + - echo $GREETING # calls a custom variable of type `file` that contains the path to the temp file + - cat $GREETING # the temp file itself contains the variable value +``` + +输出将是: + +[![Output custom variable](img/4401376aa4e3f3764851b2dbb25f6f2e.png)](img/custom_variables_output.png) + +### Custom environment variables of type Variable[](#custom-environment-variables-of-type-variable "Permalink") + +在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46806) . + +对于类型为**Variable 的变量** ,Runner 会创建一个环境变量,该环境变量将键用作名称,并将值用作值. + +有[一些](#custom-variables-validated-by-gitlab)这种类型的[预定义变量](#custom-variables-validated-by-gitlab) ,可以进一步验证. 它们在您在 UI 中添加或更新变量时出现. + +### Custom environment variables of type File[](#custom-environment-variables-of-type-file "Permalink") + +在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46806) . + +对于**File**类型的变量,Runner 创建一个环境变量,该环境变量使用键作为名称. 对于该值,Runner 将变量值写入临时文件并使用此路径. + +您可以使用诸如[AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)和[`kubectl`](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#the-kubeconfig-environment-variable)类[的](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)工具通过使用**File** type 变量来自定义配置. + +过去,常见的模式是读取 CI 变量的值,将其保存在文件中,然后在脚本中使用新创建的文件: + +``` +# Read certificate stored in $KUBE_CA_PEM variable and save it in a new file +echo "$KUBE_CA_PEM" > "$(pwd)/kube.ca.pem" +# Pass the newly created file to kubectl +kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$(pwd)/kube.ca.pem" +``` + +代替此,您可以使用**文件**类型变量. 例如,如果您具有以下变量: + +* 类型为**Variable** : `KUBE_URL` **变量** ,其值为`https://example.com` . +* 类型为**File** : `KUBE_CA_PEM`变量,其值为证书. + +您可以从`.gitlab-ci.yml`调用它们,如下所示: + +``` +kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$KUBE_CA_PEM" +``` + +### Mask a custom variable[](#mask-a-custom-variable "Permalink") + +在 GitLab 11.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/13784) + +可以屏蔽变量,以便将变量的值隐藏在作业日志中. + +要屏蔽变量: + +1. 转到**设置> CI / CD** . +2. 展开**变量**部分. +3. 在您要保护的变量旁边,点击**编辑** . +4. 选择**掩码变量**复选框. +5. Click **更新变量**. + +#### Masked variable requirements[](#masked-variable-requirements "Permalink") + +变量的值必须: + +* 在一行中. +* 至少要包含 8 个字符. +* 不是预定义或自定义环境变量. +* 仅由 Base64 字母(RFC4648)中的字符组成. [在 GitLab 12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/63043)和更高版本中, `@`和`:`也是有效值. + +您不能屏蔽不满足这些要求的变量. + +### Protect a custom variable[](#protect-a-custom-variable "Permalink") + +在 GitLab 9.3 中引入. + +变量可以被保护. 受保护的变量将安全地传递到仅在[受保护的分支](../../user/project/protected_branches.html)或[受保护的标签](../../user/project/protected_tags.html)上运行的管道. 其他管道不获取受保护的变量. + +要保护变量: + +1. 转到**设置> CI / CD** . +2. 展开**变量**部分. +3. 在您要保护的变量旁边,点击**编辑** . +4. 选择**保护变量**复选框. +5. Click **更新变量**. + +该变量可用于所有后续管道. 受保护的变量只能由拥有[维护者权限的](../../user/permissions.html#project-members-permissions)项目成员更新或查看. + +### Custom variables validated by GitLab[](#custom-variables-validated-by-gitlab "Permalink") + +UI 中列出了一些变量,因此您可以更快地选择它们. GitLab 会验证这些变量的值,以确保它们的格式正确. + +| Variable | 允许值 | 引入 | +| --- | --- | --- | +| `AWS_ACCESS_KEY_ID` | 20 个字符:字母,数字 | 12.10 | +| `AWS_DEFAULT_REGION` | Any | 12.10 | +| `AWS_SECRET_ACCESS_KEY` | 40 个字符:字母,数字,特殊字符 | 12.10 | + +**注意:**存储凭据时,会涉及安全性. 例如,如果您使用的是 AWS 密钥,请遵循其[最佳做法](https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html) . + +## Syntax of environment variables in job scripts[](#syntax-of-environment-variables-in-job-scripts "Permalink") + +所有变量都在构建环境中设置为环境变量,并且可以使用用于访问此类变量的常规方法来访问它们. 在大多数情况下, `bash`或`sh`用于执行作业脚本. + +要访问环境变量,请为 Runner's [shell](https://docs.gitlab.com/runner/executors/)使用语法. + +| Shell | Usage | +| --- | --- | +| bash/sh | `$variable` | +| PowerShell | `$env:variable` (主`$env:variable` )或`$variable` | +| Windows 批处理 | `%variable%` | + +### Bash[](#bash "Permalink") + +要在**bash 中**访问环境变量,请在变量名前加上( `$` ): + +``` +job_name: + script: + - echo $CI_JOB_ID +``` + +### PowerShell[](#powershell "Permalink") + +要访问**Windows PowerShell**环境中的环境变量,请在变量名前加上( `$env:` . 对于由 GitLab CI 设置的环境变量,包括由[`variables`](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/ci/yaml/README.md#variables)参数设置的环境[`variables`](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/ci/yaml/README.md#variables) ,还可以通过在[GitLab Runner 1.0.0 开始](https://gitlab.com/gitlab-org/gitlab-runner/-/commit/abc44bb158008cd3a49c0d8173717c38dadb29ae#47afd7e8f12afdb8f0246262488f24e6dd071a22) ,通过在变量名称前加上( `$` )来访问它们. 但是,必须使用( `$env:`访问系统设置的环境变量. + +``` +job_name: + script: + - echo $env:CI_JOB_ID + - echo $CI_JOB_ID + - echo $env:PATH +``` + +在[某些情况下,](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4115#note_157692820)环境变量可能需要用引号引起来才能正确扩展: + +``` +job_name: + script: + - D:\\qislsf\\apache-ant-1.10.5\\bin\\ant.bat "-DsosposDailyUsr=$env:SOSPOS_DAILY_USR" portal_test +``` + +### Windows Batch[](#windows-batch "Permalink") + +要访问**Windows Batch 中的**环境变量,请用( `%` )包围变量: + +``` +job_name: + script: + - echo %CI_JOB_ID% +``` + +### List all environment variables[](#list-all-environment-variables "Permalink") + +您还可以使用 Bash 中的`export`命令或 PowerShell 中的`dir env:`命令列出所有环境变量. 请注意,这还将在作业日志中公开您设置的所有变量的值: + +``` +job_name: + script: + - export + # - 'dir env:' # use this for PowerShell +``` + +值示例: + +``` +export CI_JOB_ID="50" +export CI_COMMIT_SHA="1ecfd275763eff1d6b4844ea3168962458c9f27a" +export CI_COMMIT_SHORT_SHA="1ecfd275" +export CI_COMMIT_REF_NAME="master" +export CI_REPOSITORY_URL="https://gitlab-ci-token:abcde-1234ABCD5678ef@example.com/gitlab-org/gitlab-foss.git" +export CI_COMMIT_TAG="1.0.0" +export CI_JOB_NAME="spec:other" +export CI_JOB_STAGE="test" +export CI_JOB_MANUAL="true" +export CI_JOB_TRIGGERED="true" +export CI_JOB_TOKEN="abcde-1234ABCD5678ef" +export CI_PIPELINE_ID="1000" +export CI_PIPELINE_IID="10" +export CI_PAGES_DOMAIN="gitlab.io" +export CI_PAGES_URL="https://gitlab-org.gitlab.io/gitlab-foss" +export CI_PROJECT_ID="34" +export CI_PROJECT_DIR="/builds/gitlab-org/gitlab-foss" +export CI_PROJECT_NAME="gitlab-foss" +export CI_PROJECT_TITLE="GitLab FOSS" +export CI_PROJECT_NAMESPACE="gitlab-org" +export CI_PROJECT_ROOT_NAMESPACE="gitlab-org" +export CI_PROJECT_PATH="gitlab-org/gitlab-foss" +export CI_PROJECT_URL="https://example.com/gitlab-org/gitlab-foss" +export CI_REGISTRY="registry.example.com" +export CI_REGISTRY_IMAGE="registry.example.com/gitlab-org/gitlab-foss" +export CI_REGISTRY_USER="gitlab-ci-token" +export CI_REGISTRY_PASSWORD="longalfanumstring" +export CI_RUNNER_ID="10" +export CI_RUNNER_DESCRIPTION="my runner" +export CI_RUNNER_TAGS="docker, linux" +export CI_SERVER="yes" +export CI_SERVER_URL="https://example.com" +export CI_SERVER_HOST="example.com" +export CI_SERVER_PORT="443" +export CI_SERVER_PROTOCOL="https" +export CI_SERVER_NAME="GitLab" +export CI_SERVER_REVISION="70606bf" +export CI_SERVER_VERSION="8.9.0" +export CI_SERVER_VERSION_MAJOR="8" +export CI_SERVER_VERSION_MINOR="9" +export CI_SERVER_VERSION_PATCH="0" +export GITLAB_USER_EMAIL="user@example.com" +export GITLAB_USER_ID="42" +``` + +## `.gitlab-ci.yml` defined variables[](#gitlab-ciyml-defined-variables "Permalink") + +**注意:**此功能需要 GitLab Runner 0.5.0 或更高版本以及 GitLab 7.14 或更高版本. + +您可以将在构建环境中设置的变量添加到`.gitlab-ci.yml` . 这些变量保存在存储库中,它们旨在存储非敏感项目配置,例如`RAILS_ENV`或`DATABASE_URL` . + +例如,如果将变量全局设置为下方(而不是在作业内部),它将在所有已执行的命令和脚本中使用: + +``` +variables: + DATABASE_URL: "postgres://postgres@postgres/my_database" +``` + +还将 YAML 定义的变量设置为所有创建的[服务容器](../docker/using_docker_images.html) ,以便您可以对其进行微调. + +变量可以在全局级别定义,也可以在作业级别定义. 要在作业中关闭全局定义的变量,请定义一个空哈希: + +``` +job_name: + variables: {} +``` + +您可以在变量定义内使用其他变量(或使用`$$`对其进行转义): + +``` +variables: + LS_CMD: 'ls $FLAGS $$TMP_DIR' + FLAGS: '-al' +script: + - 'eval $LS_CMD' # will execute 'ls -al $TMP_DIR' +``` + +## Group-level environment variables[](#group-level-environment-variables "Permalink") + +Introduced in GitLab 9.4. + +您可以定义在管道环境中设置的每个项目或每个组的变量. 组级变量存储在存储库之外(不在`.gitlab-ci.yml` ),并安全地传递到 GitLab Runner,这使它们在管道运行期间可用. 对于**不**使用外部密钥存储或使用 GitLab [与 HashiCorp Vault 集成的](../examples/authenticating-with-hashicorp-vault/index.html)高级用户,我们建议使用组环境变量来存储密码,SSH 密钥和凭据之类的机密. + +组级变量可以通过以下方式添加: + +1. 导航到组的**"设置">" CI / CD"**页面. +2. 在" **变量"**部分中输入变量类型,键和值. [子组的](../../user/group/subgroups/index.html)任何变量将被递归继承. + +设置它们后,它们将可用于所有后续管道. 可以通过以下方式在项目中查看任何组级用户定义的变量: + +1. 导航到项目的**"设置">" CI / CD"**页面. +2. 展开**变量**部分. + +[![CI/CD settings - inherited variables](img/bcbedbd56c50879eb35c2fc2f534d693.png)](img/inherited_group_variables_v12_5.png) + +## Instance-level CI/CD environment variables[](#instance-level-cicd-environment-variables "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/14108) . + +实例变量非常有用,因为不再需要为所有项目重复手动输入相同的凭据. 实例级变量可用于实例上的所有项目和组. + +**注意:**实例级变量的最大数量[计划为 25](https://gitlab.com/gitlab-org/gitlab/-/issues/216097) . + +您可以通过 UI 或[API](../../api/instance_level_ci_variables.html)定义实例级变量. + +要添加实例级变量: + +1. 导航到管理区域的**"设置">" CI / CD",**然后展开" **变量"**部分. +2. 单击**添加变量**按钮,然后填写详细信息: + + * **密钥** :必须为一行,只能使用字母,数字或`_` (下划线),且不能有空格. + * **值** :允许 700 个字符. + * **Type**: `File` or `Variable`. + * **保护变量** (可选):如果选中,则该变量将仅在在受保护的分支或标签上运行的管道中可用. + * **屏蔽变量** (可选):如果选中,则变量的**值**将不会显示在作业日志中. 如果该值不满足[屏蔽要求,](#masked-variable-requirements)则不会保存该变量. + +创建变量后,您可以通过点击 **编辑**按钮. + +### Enable or disable UI interface for instance-level CI/CD variables[](#enable-or-disable-ui-interface-for-instance-level-cicd-variables "Permalink") + +实例级 CI / CD 变量的 UI 界面正在开发中,但可用于生产环境. 它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../administration/feature_flags.html)可以选择为您的实例禁用它. + +禁用它: + +``` +Feature.disable(:instance_variables_ui) +``` + +要启用它: + +``` +Feature.enable(:instance_variables_ui) +``` + +## Inherit environment variables[](#inherit-environment-variables "Permalink") + +版本历史 + +* [介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/22638)在 GitLab 13.0 后面的禁用[功能标志](../../administration/feature_flags.html) : `ci_dependency_variables` . +* 在 GitLab 13.1 中[已删除功能标记](https://gitlab.com/gitlab-org/gitlab/-/issues/217834) . + +您可以从相关作业中继承环境变量. + +该功能利用了[`artifacts:reports:dotenv`](../pipelines/job_artifacts.html#artifactsreportsdotenv)报告功能. + +带有[`dependencies`](../yaml/README.html#dependencies)关键字的示例. + +``` +build: + stage: build + script: + - echo "BUILD_VERSION=hello" >> build.env + artifacts: + reports: + dotenv: build.env + +deploy: + stage: deploy + script: + - echo $BUILD_VERSION # => hello + dependencies: + - build +``` + +带[`needs`](../yaml/README.html#artifact-downloads-with-needs)关键字的示例: + +``` +build: + stage: build + script: + - echo "BUILD_VERSION=hello" >> build.env + artifacts: + reports: + dotenv: build.env + +deploy: + stage: deploy + script: + - echo $BUILD_VERSION # => hello + needs: + - job: build + artifacts: true +``` + +## Priority of environment variables[](#priority-of-environment-variables "Permalink") + +不同类型的变量可以优先于其他变量,具体取决于它们的定义位置. + +变量的优先顺序为(从最高到最低): + +1. [触发器变量](../triggers/README.html#making-use-of-trigger-variables) , [计划的管道变量](../pipelines/schedules.html#using-variables)和[手动管道运行变量](#override-a-variable-by-manually-running-a-pipeline) . +2. Project-level [variables](#custom-environment-variables) or [protected variables](#protect-a-custom-variable). +3. Group-level [variables](#group-level-environment-variables) or [protected variables](#protect-a-custom-variable). +4. [Inherited environment variables](#inherit-environment-variables). +5. YAML-defined [job-level variables](../yaml/README.html#variables). +6. YAML-defined [global variables](../yaml/README.html#variables). +7. [Deployment variables](#deployment-environment-variables). +8. [Predefined environment variables](predefined_variables.html). + +例如,如果您定义: + +* `API_TOKEN=secure`作为项目变量. +* 您的`.gitlab-ci.yml` `API_TOKEN=yaml` . + +`API_TOKEN`将采用`secure`值,因为项目变量优先于`.gitlab-ci.yml`定义`.gitlab-ci.yml` . + +## Unsupported variables[](#unsupported-variables "Permalink") + +Variable names are limited by the underlying shell used to execute scripts (see [available shells](https://docs.gitlab.com/runner/shells/index.html). Each shell has its own unique set of reserved variable names. You will also want to keep in mind the [scope of environment variables](where_variables_can_be_used.html) to ensure a variable is defined in the scope in which you wish to use it. + +## Where variables can be used[](#where-variables-can-be-used "Permalink") + +单击[此处](where_variables_can_be_used.html)以获得描述在何处以及如何使用不同类型的变量的部分. + +## Advanced use[](#advanced-use "Permalink") + +### Limit the environment scopes of environment variables[](#limit-the-environment-scopes-of-environment-variables "Permalink") + +您可以通过[定义](../environments/index.html)变量可用于的环境来限制变量的环境范围. + +要了解有关范围界定环境的更多信息,请参阅[使用规范范围界定环境](../environments/index.html#scoping-environments-with-specs) . + +### Deployment environment variables[](#deployment-environment-variables "Permalink") + +在 GitLab 8.15 中引入. + +负责部署配置的[集成](../../user/project/integrations/overview.html)可以定义在构建环境中设置的自己的变量. 这些变量仅为[部署作业](../environments/index.html)定义. 请查阅所用集成的文档,以了解它们定义了哪些变量. + +定义部署变量的示例集成是[Kubernetes 集成](../../user/project/clusters/index.html#deployment-variables) . + +### Auto DevOps environment variables[](#auto-devops-environment-variables "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49056) . + +您可以配置[Auto DevOps,](../../topics/autodevops/index.html)以将 CI 变量传递给正在运行的应用程序,方法是在变量的键之前添加`K8S_SECRET_` . + +然后,这些[前缀变量](../../topics/autodevops/customize.html#application-secret-variables)将在运行的应用程序容器上用作环境变量. + +**警告:**由于当前 Auto DevOps 脚本环境的限制,当前不支持具有多行值的变量. + +### Override a variable by manually running a pipeline[](#override-a-variable-by-manually-running-a-pipeline "Permalink") + +在 GitLab 10.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44059) . + +您可以通过[手动运行管道](../pipelines/index.html#run-a-pipeline-manually)来覆盖当前变量的值. + +例如,假设您添加了一个名为`$TEST`的自定义变量,并且想在手动管道中覆盖它. + +导航到项目的**CI / CD>管道** ,然后单击**运行管道** . 选择要为其运行管道的分支,然后在 UI 中添加变量及其值: + +[![Override variable value](img/599297cd25b4f282b1340e8e61e2e087.png)](img/override_variable_manual_pipeline.png) + +运行器将覆盖先前设置的值,并将自定义值用于此特定管道. + +[![Manually overridden variable output](img/e392f78e991a2b0865f4a2fe825fd7fc.png)](img/override_value_via_manual_pipeline_output.png) + +## Environment variables expressions[](#environment-variables-expressions "Permalink") + +版本历史 + +* 在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/37397) [了`only`和`except` CI 关键字](../yaml/README.html#onlyexcept-advanced) +* 在 GitLab 12.3 中使用[`rules`关键字](../yaml/README.html#rules) [扩展](https://gitlab.com/gitlab-org/gitlab/-/issues/27863) + +使用变量表达式来限制将更改推送到 GitLab 之后在管道中创建的作业. + +在`.gitlab-ci.yml` ,变量表达式可同时用于以下两种情况: + +* [`rules`](../yaml/README.html#rules) ,这是推荐的方法,以及 +* [`only`和`except`](../yaml/README.html#onlyexcept-basic) ,它们是不推荐使用的候选对象. + +与变量和触发的管道变量结合使用时,这特别有用. + +``` +deploy: + script: cap staging deploy + environment: staging + only: + variables: + - $RELEASE == "staging" + - $STAGING +``` + +在创建管道之前,将对提供的每个表达式进行求值. + +如果`only`使用时`variables`任何条件评估为 true,则会创建一个新作业. 如果在使用`except`任何表达式的结果为 true,则不会创建作业. + +这遵循[`only` / `except`策略](../yaml/README.html#onlyexcept-advanced)的常规规则. + +### Syntax of environment variable expressions[](#syntax-of-environment-variable-expressions "Permalink") + +您可以在下面找到受支持的语法参考: + +1. 使用字符串进行相等匹配 + + Examples: + + * `$VARIABLE == "some value"` + * `$VARIABLE != "some value"` (在 GitLab 11.11 中引入) + + 您可以使用等于运算符`==`或`!=`将变量内容与字符串进行比较. 我们支持双引号和单引号来定义字符串值,因此同时支持`$VARIABLE == "some value"`和`$VARIABLE == 'some value'` . `"some value" == $VARIABLE`也正确. + +2. 检查未定义的值 + + Examples: + + * `$VARIABLE == null` + * `$VARIABLE != null` (在 GitLab 11.11 中引入) + + 有时,您可能想检查是否定义了变量. 为此,您可以将变量与`null`关键字进行比较,例如`$VARIABLE == null` . 如果在使用`==`时未定义变量,则该表达式的值为 true;如果使用`!=`则该表达式的值为 false. + +3. 检查空变量 + + Examples: + + * `$VARIABLE == ""` + * `$VARIABLE != ""` (introduced in GitLab 11.11) + + 如果要检查变量是否已定义但为空,则可以将其与空字符串(例如`$VAR == ''`或非空字符串`$VARIABLE != ""` . + +4. 比较两个变量 + + Examples: + + * `$VARIABLE_1 == $VARIABLE_2` + * `$VARIABLE_1 != $VARIABLE_2` (在 GitLab 11.11 中引入) + + 可以比较两个变量. 这将比较这些变量的值. + +5. 可变状态检查 + + Example: `$STAGING` + + 如果只想在存在某个变量时创建作业,这意味着它是已定义且非空的,则可以简单地使用变量名作为表达式,例如`$STAGING` . 如果`$STAGING`变量已定义且不为空,则表达式将求值为真. `$STAGING`值必须是长度大于零的字符串. 仅包含空格字符的变量不是空变量. + +6. 模式匹配(在 GitLab 11.0 中引入) + + Examples: + + * `=~` :如果模式匹配则为真. 例如: `$VARIABLE =~ /^content.*/` + * `!~` :如果模式不匹配,则为 true. 例如: `$VARIABLE_1 !~ /^content.*/` (在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/61900) ) + + 与正则表达式匹配的变量模式使用[RE2 正则表达式语法](https://github.com/google/re2/wiki/Syntax) . 如果满足以下条件,则表达式的计算结果为`true` : + + * 使用`=~`时找到匹配项. + * 当使用火柴都*没有*发现`!~` + + 模式匹配默认情况下区分大小写. 使用`i`标志修饰符,例如`/pattern/i` ,使模式不区分大小写. + +7. Conjunction / Disjunction ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27925) in GitLab 12.0) + + Examples: + + * `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"` + * `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3` + * `$VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3` + + 可以使用`&&`或`||`加入多个条件 . 任何在其他情况下受支持的语法都可以在合并或不合并语句中使用. 运算符的优先级遵循[Ruby 2.5 标准](https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html) ,因此`&&`在`||`之前进行评估 . + +### Storing regular expressions in variables[](#storing-regular-expressions-in-variables "Permalink") + +可以将正则表达式存储在变量中,以用于模式匹配: + +``` +variables: + STAGINGRELS: '/staging0|staging1/' + +deploy_staging: + script: do.sh deploy staging + environment: staging + rules: + - if: '$RELEASE =~ $STAGINGRELS' +``` + +**注意:**可用的正则表达式语法受到限制. 有关更多详细信息,请参见[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/35438) . + +如果需要,您可以使用测试管道来确定正则表达式是否可以在变量中工作. 下面的示例直接从变量内部测试`^mast.*`正则表达式: + +``` +variables: + MYSTRING: 'master' + MYREGEX: '/^mast.*/' + +testdirect: + script: /bin/true + rules: + - if: '$MYSTRING =~ /^mast.*/' + +testvariable: + script: /bin/true + rules: + - if: '$MYSTRING =~ $MYREGEX' +``` + +## Debug logging[](#debug-logging "Permalink") + +在 GitLab Runner 1.7 中引入. + +**警告:**启用调试跟踪可能会严重影响安全性. 输出**将**包含所有变量和其他任何秘密的内容! 输出**将**上传到 GitLab 服务器,并在作业日志中显示! + +默认情况下,GitLab Runner 隐藏处理作业时所执行操作的大多数细节. 此行为使作业日志简短,并防止机密信息泄露到日志中,除非您的脚本将其写入屏幕. + +如果一项工作没有按预期进行,则可能使问题难以调查. 在这种情况下,您可以在`.gitlab-ci.yml`启用调试跟踪. 在 GitLab Runner v1.7 +上可用,此功能启用外壳程序的执行日志,从而产生详细的作业日志,其中列出了所有已运行的命令,已设置的变量等. + +在启用此功能之前,您应确保作业[仅对团队成员](../../user/permissions.html#project-features)可见. 您还应该[清除](../pipelines/index.html#view-jobs-in-a-pipeline)所有生成的作业日志,然后才能再次显示它们. + +要启用调试日志(跟踪),请将`CI_DEBUG_TRACE`变量设置为`true` : + +``` +job_name: + variables: + CI_DEBUG_TRACE: "true" +``` + +将`CI_DEBUG_TRACE`设置为`true`示例截断输出: + +``` +... + +export CI_SERVER_TLS_CA_FILE="/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE" +if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then echo $'\''\x1b[32;1mFetching changes...\x1b[0;m'\'' + $'\''cd'\'' "/builds/gitlab-examples/ci-debug-trace" + $'\''git'\'' "config" "fetch.recurseSubmodules" "false" + $'\''rm'\'' "-f" ".git/index.lock" + $'\''git'\'' "clean" "-ffdx" + $'\''git'\'' "reset" "--hard" + $'\''git'\'' "remote" "set-url" "origin" "https://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@example.com/gitlab-examples/ci-debug-trace.git" + $'\''git'\'' "fetch" "origin" "--prune" "+refs/heads/*:refs/remotes/origin/*" "+refs/tags/*:refs/tags/lds" +++ CI_BUILDS_DIR=/builds +++ export CI_PROJECT_DIR=/builds/gitlab-examples/ci-debug-trace +++ CI_PROJECT_DIR=/builds/gitlab-examples/ci-debug-trace +++ export CI_CONCURRENT_ID=87 +++ CI_CONCURRENT_ID=87 +++ export CI_CONCURRENT_PROJECT_ID=0 +++ CI_CONCURRENT_PROJECT_ID=0 +++ export CI_SERVER=yes +++ CI_SERVER=yes +++ mkdir -p /builds/gitlab-examples/ci-debug-trace.tmp +++ echo -n '-----BEGIN CERTIFICATE----- +-----END CERTIFICATE-----' +++ export CI_SERVER_TLS_CA_FILE=/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE +++ CI_SERVER_TLS_CA_FILE=/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE +++ export CI_PIPELINE_ID=52666 +++ CI_PIPELINE_ID=52666 +++ export CI_PIPELINE_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/pipelines/52666 +++ CI_PIPELINE_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/pipelines/52666 +++ export CI_JOB_ID=7046507 +++ CI_JOB_ID=7046507 +++ export CI_JOB_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/-/jobs/379424655 +++ CI_JOB_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/-/jobs/379424655 +++ export CI_JOB_TOKEN=[MASKED] +++ CI_JOB_TOKEN=[MASKED] +++ export CI_BUILD_ID=379424655 +++ CI_BUILD_ID=379424655 +++ export CI_BUILD_TOKEN=[MASKED] +++ CI_BUILD_TOKEN=[MASKED] +++ export CI_REGISTRY_USER=gitlab-ci-token +++ CI_REGISTRY_USER=gitlab-ci-token +++ export CI_REGISTRY_PASSWORD=[MASKED] +++ CI_REGISTRY_PASSWORD=[MASKED] +++ export CI_REPOSITORY_URL=https://gitlab-ci-token:[MASKED]@gitlab.com/gitlab-examples/ci-debug-trace.git +++ CI_REPOSITORY_URL=https://gitlab-ci-token:[MASKED]@gitlab.com/gitlab-examples/ci-debug-trace.git +++ export CI_JOB_NAME=debug_trace +++ CI_JOB_NAME=debug_trace +++ export CI_JOB_STAGE=test +++ CI_JOB_STAGE=test +++ export CI_NODE_TOTAL=1 +++ CI_NODE_TOTAL=1 +++ export CI_BUILD_NAME=debug_trace +++ CI_BUILD_NAME=debug_trace +++ export CI_BUILD_STAGE=test +++ CI_BUILD_STAGE=test +++ export CI=true +++ CI=true +++ export GITLAB_CI=true +++ GITLAB_CI=true +++ export CI_SERVER_URL=https://gitlab.com:3000 +++ CI_SERVER_URL=https://gitlab.com:3000 +++ export CI_SERVER_HOST=gitlab.com +++ CI_SERVER_HOST=gitlab.com +++ export CI_SERVER_PORT=3000 +++ CI_SERVER_PORT=3000 +++ export CI_SERVER_PROTOCOL=https +++ CI_SERVER_PROTOCOL=https +++ export CI_SERVER_NAME=GitLab +++ CI_SERVER_NAME=GitLab +++ export CI_SERVER_VERSION=12.6.0-pre +++ CI_SERVER_VERSION=12.6.0-pre +++ export CI_SERVER_VERSION_MAJOR=12 +++ CI_SERVER_VERSION_MAJOR=12 +++ export CI_SERVER_VERSION_MINOR=6 +++ CI_SERVER_VERSION_MINOR=6 +++ export CI_SERVER_VERSION_PATCH=0 +++ CI_SERVER_VERSION_PATCH=0 +++ export CI_SERVER_REVISION=f4cc00ae823 +++ CI_SERVER_REVISION=f4cc00ae823 +++ export GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_project_service_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,pseudonymizer,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal +++ GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_project_service_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,cluster_health,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,pseudonymizer,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal +++ export CI_PROJECT_ID=17893 +++ CI_PROJECT_ID=17893 +++ export CI_PROJECT_NAME=ci-debug-trace +++ CI_PROJECT_NAME=ci-debug-trace +++ export CI_PROJECT_TITLE='GitLab FOSS' +++ CI_PROJECT_TITLE='GitLab FOSS' +++ export CI_PROJECT_PATH=gitlab-examples/ci-debug-trace +++ CI_PROJECT_PATH=gitlab-examples/ci-debug-trace +++ export CI_PROJECT_PATH_SLUG=gitlab-examples-ci-debug-trace +++ CI_PROJECT_PATH_SLUG=gitlab-examples-ci-debug-trace +++ export CI_PROJECT_NAMESPACE=gitlab-examples +++ CI_PROJECT_NAMESPACE=gitlab-examples +++ export CI_PROJECT_ROOT_NAMESPACE=gitlab-examples +++ CI_PROJECT_ROOT_NAMESPACE=gitlab-examples +++ export CI_PROJECT_URL=https://gitlab.com/gitlab-examples/ci-debug-trace +++ CI_PROJECT_URL=https://gitlab.com/gitlab-examples/ci-debug-trace +++ export CI_PROJECT_VISIBILITY=public +++ CI_PROJECT_VISIBILITY=public +++ export CI_PROJECT_REPOSITORY_LANGUAGES= +++ CI_PROJECT_REPOSITORY_LANGUAGES= +++ export CI_DEFAULT_BRANCH=master +++ CI_DEFAULT_BRANCH=master +++ export CI_REGISTRY=registry.gitlab.com +++ CI_REGISTRY=registry.gitlab.com +++ export CI_API_V4_URL=https://gitlab.com/api/v4 +++ CI_API_V4_URL=https://gitlab.com/api/v4 +++ export CI_PIPELINE_IID=123 +++ CI_PIPELINE_IID=123 +++ export CI_PIPELINE_SOURCE=web +++ CI_PIPELINE_SOURCE=web +++ export CI_CONFIG_PATH=.gitlab-ci.yml +++ CI_CONFIG_PATH=.gitlab-ci.yml +++ export CI_COMMIT_SHA=dd648b2e48ce6518303b0bb580b2ee32fadaf045 +++ CI_COMMIT_SHA=dd648b2e48ce6518303b0bb580b2ee32fadaf045 +++ export CI_COMMIT_SHORT_SHA=dd648b2e +++ CI_COMMIT_SHORT_SHA=dd648b2e +++ export CI_COMMIT_BEFORE_SHA=0000000000000000000000000000000000000000 +++ CI_COMMIT_BEFORE_SHA=0000000000000000000000000000000000000000 +++ export CI_COMMIT_REF_NAME=master +++ CI_COMMIT_REF_NAME=master +++ export CI_COMMIT_REF_SLUG=master +++ CI_COMMIT_REF_SLUG=master +++ export CI_COMMIT_MESSAGE=s/CI/Runner +++ CI_COMMIT_MESSAGE=s/CI/Runner +++ export CI_COMMIT_TITLE=s/CI/Runner +++ CI_COMMIT_TITLE=s/CI/Runner +++ export CI_COMMIT_DESCRIPTION= +++ CI_COMMIT_DESCRIPTION= +++ export CI_COMMIT_REF_PROTECTED=true +++ CI_COMMIT_REF_PROTECTED=true +++ export CI_BUILD_REF=dd648b2e48ce6518303b0bb580b2ee32fadaf045 +++ CI_BUILD_REF=dd648b2e48ce6518303b0bb580b2ee32fadaf045 +++ export CI_BUILD_BEFORE_SHA=0000000000000000000000000000000000000000 +++ CI_BUILD_BEFORE_SHA=0000000000000000000000000000000000000000 +++ export CI_BUILD_REF_NAME=master +++ CI_BUILD_REF_NAME=master +++ export CI_BUILD_REF_SLUG=master +++ CI_BUILD_REF_SLUG=master +++ export CI_RUNNER_ID=1337 +++ CI_RUNNER_ID=1337 +++ export CI_RUNNER_DESCRIPTION=shared-runners-manager-4.gitlab.com +++ CI_RUNNER_DESCRIPTION=shared-runners-manager-4.gitlab.com +++ export 'CI_RUNNER_TAGS=gce, east-c, shared, docker, linux, ruby, mysql, postgres, mongo, git-annex' +++ CI_RUNNER_TAGS='gce, east-c, shared, docker, linux, ruby, mysql, postgres, mongo, git-annex' +++ export CI_DEBUG_TRACE=true +++ CI_DEBUG_TRACE=true +++ export GITLAB_USER_ID=42 +++ GITLAB_USER_ID=42 +++ export GITLAB_USER_EMAIL=user@example.com +++ GITLAB_USER_EMAIL=user@example.com +++ export GITLAB_USER_LOGIN=root +++ GITLAB_USER_LOGIN=root +++ export 'GITLAB_USER_NAME=User' +++ GITLAB_USER_NAME='User' +++ export CI_DISPOSABLE_ENVIRONMENT=true +++ CI_DISPOSABLE_ENVIRONMENT=true +++ export CI_RUNNER_VERSION=12.5.0 +++ CI_RUNNER_VERSION=12.5.0 +++ export CI_RUNNER_REVISION=577f813d +++ CI_RUNNER_REVISION=577f813d +++ export CI_RUNNER_EXECUTABLE_ARCH=linux/amd64 +++ CI_RUNNER_EXECUTABLE_ARCH=linux/amd64 +++ export VERY_SECURE_VARIABLE=imaverysecurevariable +++ VERY_SECURE_VARIABLE=imaverysecurevariable + +... +``` + +## Video walkthrough of a working example[](#video-walkthrough-of-a-working-example "Permalink") + +[使用 GitLab 管理复杂配置数据管理怪兽](https://www.youtube.com/watch?v=v4ZOJ96hAck)视频是[复杂配置数据 Monorepo](https://gitlab.com/guided-explorations/config-data-top-scope/config-data-subscope/config-data-monorepo)工作示例项目的演练. 它解释了如何将多个级别的组 CI / CD 变量与环境范围的项目变量组合在一起,以实现应用程序构建或部署的复杂配置. + +可以将示例复制到您自己的组或实例中进行测试. 项目页面上提供了有关演示其他 GitLab CI 模式的更多详细信息. \ No newline at end of file diff --git a/_book/docs/221.md b/_book/docs/221.md new file mode 100644 index 0000000000000000000000000000000000000000..02caa08909b904b5b9a2be4d8815f528186618f5 --- /dev/null +++ b/_book/docs/221.md @@ -0,0 +1,128 @@ +# Predefined environment variables reference + +> 原文:[https://docs.gitlab.com/ee/ci/variables/predefined_variables.html](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) + +# Predefined environment variables reference[](#predefined-environment-variables-reference "Permalink") + +有关此主题的介绍,请通读[环境变量入门](README.html)文档. + +仅当使用最低版本的[GitLab Runner 时,](https://docs.gitlab.com/runner/)某些预定义的环境变量才可用. 请查阅下表以查找所需的 Runner 版本. + +**注意:**从 GitLab 9.0 开始,我们已弃用了一些变量. 阅读[9.0 重命名](deprecated_variables.html#gitlab-90-renamed-variables)部分以查找其替换内容. **强烈建议您使用新变量,因为我们将在以后的 GitLab 版本中删除旧变量.** + +您可以在`.gitlab-ci.yml`文件中添加命令,以[输出可用于作业的所有变量的值](README.html#list-all-environment-variables) . + +Kubernetes 特定于环境的环境变量在[Kubernetes 部署变量](../../user/project/clusters/index.html#deployment-variables)部分中进行了详细介绍. + +| Variable | GitLab | Runner | Description | +| --- | --- | --- | --- | +| `CHAT_CHANNEL` | 10.6 | all | 触发[ChatOps](../chatops/README.html)命令的源聊天通道 | +| `CHAT_INPUT` | 10.6 | all | 在[ChatOps](../chatops/README.html)命令中传递的其他参数 | +| `CI` | all | 0.4 | 标记作业在 CI 环境中执行 | +| `CI_API_V4_URL` | 11.7 | all | GitLab API v4 根 URL | +| `CI_BUILDS_DIR` | all | 11.10 | 执行构建的顶级目录. | +| `CI_COMMIT_BEFORE_SHA` | 11.2 | all | 先前的最新提交存在于分支中. 合并请求的管道中始终为`0000000000000000000000000000000000000000` | +| `CI_COMMIT_DESCRIPTION` | 10.8 | all | 提交的描述:如果标题少于 100 个字符,则不带第一行的消息; 在其他情况下为完整消息. | +| `CI_COMMIT_MESSAGE` | 10.8 | all | 完整的提交消息. | +| `CI_COMMIT_REF_NAME` | 9.0 | all | 构建项目的分支或标记名称 | +| `CI_COMMIT_REF_PROTECTED` | 11.11 | all | 如果作业在受保护的引用上运行,则为`true`否则为`false` | +| `CI_COMMIT_REF_SLUG` | 9.0 | all | `$CI_COMMIT_REF_NAME`小写,缩短为 63 个字节,并且将`0-9`和`az`以外的所有内容替换为`-` . 没有前导/尾随`-` . 在 URL,主机名和域名中使用. | +| `CI_COMMIT_SHA` | 9.0 | all | 为其构建项目的提交修订 | +| `CI_COMMIT_SHORT_SHA` | 11.7 | all | `CI_COMMIT_SHA`的前八个字符 | +| `CI_COMMIT_BRANCH` | 12.6 | 0.5 | 提交分支名称. 仅在建立分支时显示. | +| `CI_COMMIT_TAG` | 9.0 | 0.5 | 提交标记名称. 仅在构建标签时显示. | +| `CI_COMMIT_TITLE` | 10.8 | all | 提交的标题-消息的第一行 | +| `CI_CONCURRENT_ID` | all | 11.10 | 单个执行程序中生成执行的唯一 ID. | +| `CI_CONCURRENT_PROJECT_ID` | all | 11.10 | 单个执行程序和项目中生成执行的唯一 ID. | +| `CI_CONFIG_PATH` | 9.4 | 0.5 | CI 配置文件的路径. 默认为`.gitlab-ci.yml` | +| `CI_DEBUG_TRACE` | all | 1.7 | 是否启用[调试日志记录(跟踪)](README.html#debug-logging) | +| `CI_DEFAULT_BRANCH` | 12.4 | all | 项目的默认分支的名称. | +| `CI_DEPLOY_PASSWORD` | 10.8 | all | [GitLab Deploy 令牌的](../../user/project/deploy_tokens/index.html#gitlab-deploy-token)身份验证密码,仅在项目具有相关性时才提供. | +| `CI_DEPLOY_USER` | 10.8 | all | [GitLab Deploy 令牌的](../../user/project/deploy_tokens/index.html#gitlab-deploy-token)身份验证用户名,仅在项目具有相关性时才存在. | +| `CI_DISPOSABLE_ENVIRONMENT` | all | 10.1 | 标记作业是在一次性环境中执行的(仅为该作业创建并在执行后处置/销毁的东西-除`shell`和`ssh`以外的所有执行程序). 如果环境是一次性的,则将其设置为 true,否则将完全未定义. | +| `CI_ENVIRONMENT_NAME` | 8.15 | all | 该作业的环境名称. 仅在设置了[`environment:name`](../yaml/README.html#environmentname)存在. | +| `CI_ENVIRONMENT_SLUG` | 8.15 | all | 环境名称的简化版本,适合包含在 DNS,URL,Kubernetes 标签等中.仅在设置了[`environment:name`](../yaml/README.html#environmentname)存在. | +| `CI_ENVIRONMENT_URL` | 9.3 | all | 该作业的环境的 URL. 仅当设置了[`environment:url`](../yaml/README.html#environmenturl)时才存在. | +| `CI_EXTERNAL_PULL_REQUEST_IID` | 12.3 | all | 如果[管道用于外部请求,](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)则来自 GitHub 的请求请求 ID. 仅在以下情况`only: [external_pull_requests]`可用`only: [external_pull_requests]`或[`rules`](../yaml/README.html#rules)语法,并且拉取请求处于打开状态. | +| `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_NAME` | 12.3 | all | 如果[管道用于外部](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)请求,则请求请求的源分支名称. 仅在以下情况`only: [external_pull_requests]`可用`only: [external_pull_requests]`或[`rules`](../yaml/README.html#rules)语法,并且拉取请求处于打开状态. | +| `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_SHA` | 12.3 | all | 如果[管道用于外部](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)请求,则请求请求的源分支的 HEAD SHA. 仅在以下情况`only: [external_pull_requests]`可用`only: [external_pull_requests]`或[`rules`](../yaml/README.html#rules)语法,并且拉取请求处于打开状态. | +| `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_NAME` | 12.3 | all | 如果[管道用于外部](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)请求,则请求请求的目标分支名称. 仅在以下情况`only: [external_pull_requests]`可用`only: [external_pull_requests]`或[`rules`](../yaml/README.html#rules)语法,并且拉取请求处于打开状态. | +| `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_SHA` | 12.3 | all | 如果[管道用于外部](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)请求,则请求请求目标分支的 HEAD SHA. 仅在以下情况`only: [external_pull_requests]`可用`only: [external_pull_requests]`或[`rules`](../yaml/README.html#rules)语法,并且拉取请求处于打开状态. | +| `CI_HAS_OPEN_REQUIREMENTS` | 13.1 | all | 仅当管道的项目有任何开放[要求时,](../../user/project/requirements/index.html)才将值包括为`true` . 如果管道项目没有开放要求,则不包括在内. | +| `CI_JOB_ID` | 9.0 | all | GitLab CI / CD 在内部使用的当前作业的唯一 ID | +| `CI_JOB_IMAGE` | 12.9 | 12.9 | 运行 CI 作业的图像的名称 | +| `CI_JOB_MANUAL` | 8.12 | all | 指示作业已手动启动的标志 | +| `CI_JOB_NAME` | 9.0 | 0.5 | `.gitlab-ci.yml`定义的作业名称 | +| `CI_JOB_STAGE` | 9.0 | 0.5 | `.gitlab-ci.yml`定义的阶段名称 | +| `CI_JOB_TOKEN` | 9.0 | 1.2 | 用于通过[GitLab 容器注册表](../../user/packages/container_registry/index.html)进行身份验证,下载[从属存储库](../../user/project/new_ci_build_permissions_model.html#dependent-repositories)以及访问[GitLab 管理的 Terraform 状态的](../../user/infrastructure/index.html#gitlab-managed-terraform-state)令牌. | +| `CI_JOB_JWT` | 12.10 | all | RS256 JSON Web 令牌,可用于与支持 JWT 身份验证的第三方系统进行身份验证,例如[HashiCorp 的 Vault](../examples/authenticating-with-hashicorp-vault) . | +| `CI_JOB_URL` | 11.1 | 0.5 | 职位详情网址 | +| `CI_KUBERNETES_ACTIVE` | 13.0 | all | Included with the value `true` only if the pipeline has a Kubernetes cluster available for deployments. Not included if no cluster is available. Can be used as an alternative to [`only:kubernetes`/`except:kubernetes`](../yaml/README.html#onlykubernetesexceptkubernetes) with [`rules:if`](../yaml/README.html#rulesif) | +| `CI_MERGE_REQUEST_ASSIGNEES` | 11.9 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则该合并请求的受让人的用户名列表用逗号分隔. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_ID` | 11.6 | all | 合并请求的项目级别 ID. 仅当[管道用于合并请求](../merge_request_pipelines/index.html)并且创建[合并请求](../merge_request_pipelines/index.html)时才可用. | +| `CI_MERGE_REQUEST_IID` | 11.6 | all | 合并请求的实例级 IID. 仅[当管道用于合并请求](../merge_request_pipelines/index.html)并且创建[合并请求](../merge_request_pipelines/index.html)时才可用. | +| `CI_MERGE_REQUEST_LABELS` | 11.9 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的逗号分隔标签名称. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_MILESTONE` | 11.9 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的里程碑标题. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_PROJECT_ID` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的项目的 ID. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_PROJECT_PATH` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的项目路径(例如, `namespace/awesome-project` ). 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_PROJECT_URL` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的项目的 URL(例如`http://192.168.10.15:3000/namespace/awesome-project` ). 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_REF_PATH` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的 ref 路径. (例如`refs/merge-requests/1/head` ). 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_SOURCE_BRANCH_NAME` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的源分支名称. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` | 11.9 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的源分支的 HEAD SHA. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法,创建合并请求,并且管道是[合并结果管道](../merge_request_pipelines/pipelines_for_merged_results/index.html) . | +| `CI_MERGE_REQUEST_SOURCE_PROJECT_ID` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的源项目的 ID. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的源项目的路径. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_SOURCE_PROJECT_URL` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的源项目的 URL. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_TARGET_BRANCH_NAME` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的目标分支名称. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` | 11.9 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的目标分支的 HEAD SHA. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法,创建合并请求,并且管道是[合并结果管道](../merge_request_pipelines/pipelines_for_merged_results/index.html) . | +| `CI_MERGE_REQUEST_TITLE` | 11.9 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的标题. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_EVENT_TYPE` | 12.3 | all | 合并请求的事件类型(如果[管道用于合并请求)](../merge_request_pipelines/index.html) . 可以`detached` , `merged_result`或`merge_train` . | +| `CI_NODE_INDEX` | 11.5 | all | 作业在作业集中的索引. 如果作业未并行化,则不会设置此变量. | +| `CI_NODE_TOTAL` | 11.5 | all | Total number of instances of this job running in parallel. If the job is not parallelized, this variable is set to `1`. | +| `CI_PAGES_DOMAIN` | 11.8 | all | 托管 GitLab 页面的已配置域. | +| `CI_PAGES_URL` | 11.8 | all | GitLab 页面构建页面的 URL. 始终属于`CI_PAGES_DOMAIN`的子域. | +| `CI_PIPELINE_ID` | 8.10 | all | GitLab CI / CD 在内部使用的当前管道的唯一 ID | +| `CI_PIPELINE_IID` | 11.0 | all | 当前管道的唯一 ID 范围为项目 | +| `CI_PIPELINE_SOURCE` | 10.0 | all | 指示如何触发管道. 可能的选项是: `push` , `web` , `schedule` , `api` , `external` , `chat` , `webide` , `merge_request_event` , `external_pull_request_event` , `parent_pipeline` , [`trigger`或`pipeline`](../triggers/README.html#authentication-tokens) (自 13.0 起改名为`cross_project_pipeline` ). 对于在 GitLab 9.5 之前创建的管道,这将显示为`unknown` . | +| `CI_PIPELINE_TRIGGERED` | all | all | 指示已[触发](../triggers/README.html)作业的标志 | +| `CI_PIPELINE_URL` | 11.1 | 0.5 | 管道详细资料网址 | +| `CI_PROJECT_DIR` | all | all | 克隆存储库以及运行作业的完整路径. 如果设置了 GitLab Runner 的`builds_dir`参数,则相对于`builds_dir`的值设置此变量. 有关更多信息,请参见 GitLab Runner 的[高级配置](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) . | +| `CI_PROJECT_ID` | all | all | GitLab CI / CD 在内部使用的当前项目的唯一 ID | +| `CI_PROJECT_NAME` | 8.10 | 0.5 | 当前正在构建的项目的目录名称. 例如,如果项目 URL 为`gitlab.example.com/group-name/project-1` ,则`CI_PROJECT_NAME`将为`project-1` . | +| `CI_PROJECT_NAMESPACE` | 8.10 | 0.5 | 当前正在构建的项目名称空间(用户名或组名) | +| `CI_PROJECT_ROOT_NAMESPACE` | 13.2 | 0.5 | 当前正在构建的**根**项目名称空间(用户名或组名). 例如,如果`CI_PROJECT_NAME`是`root-group/child-group/grandchild-group` ,则`CI_PROJECT_ROOT_NAMESPACE`将是`root-group` . | +| `CI_PROJECT_PATH` | 8.10 | 0.5 | 具有项目名称的名称空间 | +| `CI_PROJECT_PATH_SLUG` | 9.3 | all | `$CI_PROJECT_PATH`小写,除`0-9`和`az`以外的所有内容都用`-`代替. 在 URL 和域名中使用. | +| `CI_PROJECT_REPOSITORY_LANGUAGES` | 12.3 | all | 库中使用的语言的逗号分隔,小写列表(例如`ruby,javascript,html,css` ) | +| `CI_PROJECT_TITLE` | 12.4 | all | 可读的项目名称,显示在 GitLab Web 界面中. | +| `CI_PROJECT_URL` | 8.10 | 0.5 | The HTTP(S) address to access project | +| `CI_PROJECT_VISIBILITY` | 10.3 | all | 项目可见性(内部,私人,公共) | +| `CI_REGISTRY` | 8.10 | 0.5 | 如果启用了 Container Registry,它将返回 GitLab 的 Container Registry 的地址. 如果在注册表配置中指定了一个变量,则该变量将包含`:port`值. | +| `CI_REGISTRY_IMAGE` | 8.10 | 0.5 | 如果为项目启用了容器注册表,则它将返回绑定到特定项目的注册表地址 | +| `CI_REGISTRY_PASSWORD` | 9.0 | all | The password to use to push containers to the GitLab Container Registry, for the current project. | +| `CI_REGISTRY_USER` | 9.0 | all | 用于将容器推送到当前项目的 GitLab 容器注册表的用户名. | +| `CI_REPOSITORY_URL` | 9.0 | all | 克隆 Git 存储库的 URL | +| `CI_RUNNER_DESCRIPTION` | 8.10 | 0.5 | 保存在 GitLab 中的跑步者的描述 | +| `CI_RUNNER_EXECUTABLE_ARCH` | all | 10.6 | GitLab Runner 可执行文件的操作系统/体系结构(请注意,它不一定与执行程序的环境相同) | +| `CI_RUNNER_ID` | 8.10 | 0.5 | 正在使用的跑步者的唯一 ID | +| `CI_RUNNER_REVISION` | all | 10.6 | 正在执行当前作业的 GitLab Runner 版本 | +| `CI_RUNNER_SHORT_TOKEN` | all | 12.3 | GitLab Runner 令牌的前八个字符用于验证新的作业请求. 用作跑步者的唯一 ID | +| `CI_RUNNER_TAGS` | 8.10 | 0.5 | 定义的运行器标签 | +| `CI_RUNNER_VERSION` | all | 10.6 | 正在执行当前作业的 GitLab Runner 版本 | +| `CI_SERVER` | all | all | 标记作业在 CI 环境中执行 | +| `CI_SERVER_URL` | 12.7 | all | GitLab 实例的基本 URL,包括协议和端口(例如`https://gitlab.example.com:8080` ) | +| `CI_SERVER_HOST` | 12.1 | all | GitLab 实例 URL 的主机组件,不带协议和端口(例如`gitlab.example.com` ) | +| `CI_SERVER_PORT` | 12.8 | all | GitLab 实例 URL 的端口组件,不包含主机和协议(例如`3000` ) | +| `CI_SERVER_PROTOCOL` | 12.8 | all | GitLab 实例 URL 的协议组件,不带主机和端口(例如`https` ) | +| `CI_SERVER_NAME` | all | all | 用于协调作业的 CI 服务器的名称 | +| `CI_SERVER_REVISION` | all | all | 用于计划作业的 GitLab 修订版 | +| `CI_SERVER_VERSION` | all | all | 用于计划作业的 GitLab 版本 | +| `CI_SERVER_VERSION_MAJOR` | 11.4 | all | GitLab 版本主要组件 | +| `CI_SERVER_VERSION_MINOR` | 11.4 | all | GitLab 版本次要组件 | +| `CI_SERVER_VERSION_PATCH` | 11.4 | all | GitLab 版本补丁组件 | +| `CI_SHARED_ENVIRONMENT` | all | 10.1 | 标记作业是在共享环境中执行的(在诸如`shell`或`ssh`执行程序之类的 CI 调用之间持久存在的内容). 如果共享环境,则将其设置为 true,否则将完全未定义. | +| `GITLAB_CI` | all | all | 标记作业在 GitLab CI / CD 环境中执行 | +| `GITLAB_FEATURES` | 10.6 | all | 以逗号分隔的实例和计划可用的许可功能列表 | +| `GITLAB_USER_EMAIL` | 8.12 | all | 开始工作的用户的电子邮件 | +| `GITLAB_USER_ID` | 8.12 | all | 开始工作的用户的 ID | +| `GITLAB_USER_LOGIN` | 10.0 | all | 开始工作的用户的登录用户名 | +| `GITLAB_USER_NAME` | 10.0 | all | 开始工作的用户的真实姓名 | \ No newline at end of file diff --git a/_book/docs/222.md b/_book/docs/222.md new file mode 100644 index 0000000000000000000000000000000000000000..ec18696bc75fa49e2c97ede4fe8073a80dd37f38 --- /dev/null +++ b/_book/docs/222.md @@ -0,0 +1,148 @@ +# Where variables can be used + +> 原文:[https://docs.gitlab.com/ee/ci/variables/where_variables_can_be_used.html](https://docs.gitlab.com/ee/ci/variables/where_variables_can_be_used.html) + +* [Variables usage](#variables-usage) + * [`.gitlab-ci.yml` file](#gitlab-ciyml-file) + * [`config.toml` file](#configtoml-file) +* [Expansion mechanisms](#expansion-mechanisms) + * [GitLab internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) + * [GitLab Runner internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) + * [Execution shell environment](#execution-shell-environment) +* [Persisted variables](#persisted-variables) +* [Variables with an environment scope](#variables-with-an-environment-scope) + +# Where variables can be used[](#where-variables-can-be-used "Permalink") + +如[CI / CD 变量](README.html)文档中所述,您可以定义许多不同的变量. 其中一些可用于所有 GitLab CI / CD 功能,但其中某些功能或多或少受到限制. + +本文档描述了在何处以及如何使用不同类型的变量. + +## Variables usage[](#variables-usage "Permalink") + +有两个地方可以使用定义的变量. 在: + +1. GitLab 端,位于`.gitlab-ci.yml` . +2. 跑步者方面,位于`config.toml` . + +### `.gitlab-ci.yml` file[](#gitlab-ciyml-file "Permalink") + +| Definition | 可以扩大吗? | 扩展地点 | Description | +| --- | --- | --- | --- | +| `environment:url` | yes | GitLab | 变量扩展由 GitLab 的[内部变量扩展机制完成](#gitlab-internal-variable-expansion-mechanism) . + +支持为作业定义的所有变量(项目/组变量, `.gitlab-ci.yml`中的变量,触发器中的变量,管道计划中的变量). + +不支持在 Runner 的`config.toml`定义的变量和在 job 的`script`创建的变量. | +| `environment:name` | yes | GitLab | 与`environment:url`相似,但是变量扩展不支持以下内容: + +-基于环境名称的变量( `CI_ENVIRONMENT_NAME` , `CI_ENVIRONMENT_SLUG` ). +-与环境相关的任何其他变量(当前仅`CI_ENVIRONMENT_URL` ). +- [持久变量](#persisted-variables) . | +| `resource_group` | yes | GitLab | 与`environment:url`相似,但是变量扩展不支持以下内容: + +-基于环境名称的变量( `CI_ENVIRONMENT_NAME` , `CI_ENVIRONMENT_SLUG` ). +-与环境相关的任何其他变量(当前仅`CI_ENVIRONMENT_URL` ). +- [持久变量](#persisted-variables) . | +| `variables` | yes | Runner | 变量扩展由 GitLab Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `image` | yes | Runner | 变量扩展由 GitLab Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `services:[]` | yes | Runner | 变量扩展由 GitLab Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `services:[]:name` | yes | Runner | 变量扩展由 GitLab Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `cache:key` | yes | Runner | 变量扩展由 GitLab Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `artifacts:name` | yes | Runner | 变量扩展由 GitLab Runner 的外壳环境完成 | +| `script`, `before_script`, `after_script` | yes | 脚本执行外壳 | 变量扩展由[执行外壳环境进行](#execution-shell-environment) | +| `only:variables:[]`, `except:variables:[]` | no | n/a | 变量必须采用`$variable`的形式. 以下不支持: + +-基于环境名称的变量( `CI_ENVIRONMENT_NAME` , `CI_ENVIRONMENT_SLUG` ). +-与环境相关的任何其他变量(当前仅`CI_ENVIRONMENT_URL` ). +- [持久变量](#persisted-variables) . | + +### `config.toml` file[](#configtoml-file "Permalink") + +**注意:**您可以在[Runner 的 docs 中](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)阅读有关`config.toml`更多信息. + +| Definition | 可以扩大吗? | Description | +| --- | --- | --- | +| `runners.environment` | yes | 变量扩展由 Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `runners.kubernetes.pod_labels` | yes | 变量扩展由 Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `runners.kubernetes.pod_annotations` | yes | 变量扩展由 Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | + +## Expansion mechanisms[](#expansion-mechanisms "Permalink") + +共有三种扩展机制: + +* GitLab +* 亚搏体育 app Runner +* 执行外壳环境 + +### GitLab internal variable expansion mechanism[](#gitlab-internal-variable-expansion-mechanism "Permalink") + +扩展部分需要采用`$variable`或`${variable}`或`%variable%` . 每种格式都以相同的方式处理,无论最终由哪个 OS / shell 处理,因为扩展是在任何 Runner 获得该工作之前在 GitLab 中完成的. + +### GitLab Runner internal variable expansion mechanism[](#gitlab-runner-internal-variable-expansion-mechanism "Permalink") + +* 支持:项目/组变量, `.gitlab-ci.yml`变量, `config.toml`变量以及触发器,管道计划和手动管道中的变量. +* 不支持:在脚本内部定义的变量(例如, `export MY_VARIABLE="test"` ). + +跑步者使用 Go 的`os.Expand()`方法进行变量扩展. 这意味着它将仅处理定义为`$variable`和`${variable}` . 同样重要的是,扩展只能执行一次,因此嵌套变量可能会或可能不会起作用,这取决于变量定义的顺序. + +### Execution shell environment[](#execution-shell-environment "Permalink") + +这是`script`执行期间发生的扩展. 它的工作方式取决于所使用的 shell( `bash` , `sh` , `cmd` ,PowerShell). 例如,如果作业的`script`包含行`echo $MY_VARIABLE-${MY_VARIABLE_2}` ,则应由 bash / sh 正确处理(保留空字符串或某些值,具体取决于是否定义了变量),但不适用于 Windows 的`cmd`或 PowerShell,因为这些外壳使用不同的变量语法. + +Supported: + +* 该`script`可以使用外壳默认的所有可用变量(例如,应在所有 bash / sh 外壳中包含的`$PATH` )以及 GitLab CI / CD 定义的所有变量(项目/组变量, `.gitlab-ci.yml`变量, `config.toml`变量以及触发器和管道计划中的变量). +* 该`script`还可以使用前面各行中定义的所有变量. 因此,例如,如果您定义变量`export MY_VARIABLE="test"` : + * 在`before_script` ,这将在以下几行工作`before_script`和相关的所有行`script` . + * 在`script` ,它将在以下`script`行中工作. + * 在`after_script` ,它将在`after_script`以下行中`after_script` . + +对于`after_script`脚本,它们可以: + +* 仅在同一`after_script`部分中使用在脚本之前定义的变量. +* 不要使用在`before_script`和`script`定义的变量. + +这些限制是因为`after_script`脚本在[单独的 shell 上下文](../yaml/README.html#before_script-and-after_script)中执行. + +## Persisted variables[](#persisted-variables "Permalink") + +**注意:**一些持久变量包含令牌,由于安全原因,某些定义不能使用它们. + +以下变量称为"持久": + +* `CI_PIPELINE_ID` +* `CI_JOB_ID` +* `CI_JOB_TOKEN` +* `CI_BUILD_ID` +* `CI_BUILD_TOKEN` +* `CI_REGISTRY_USER` +* `CI_REGISTRY_PASSWORD` +* `CI_REPOSITORY_URL` +* `CI_DEPLOY_USER` +* `CI_DEPLOY_PASSWORD` + +他们是: + +* 支持["扩展位置"](#gitlab-ciyml-file)为的定义: + * 赛跑者. + * 脚本执行外壳. +* 不支持: + * 对于["扩展位置"](#gitlab-ciyml-file)是 GitLab 的定义. + * 在`only`和`except` [变量表达式中](README.html#environment-variables-expressions) . + +## Variables with an environment scope[](#variables-with-an-environment-scope "Permalink") + +支持使用环境范围定义的变量. 鉴于在`review/staging/*`范围内定义了一个变量`$STAGING_SECRET` ,将基于匹配的变量表达式创建以下使用动态环境的作业: + +``` +my-job: + stage: staging + environment: + name: review/$CI_JOB_STAGE/deploy + script: + - 'deploy staging' + only: + variables: + - $STAGING_SECRET == 'something' +``` \ No newline at end of file diff --git a/_book/docs/223.md b/_book/docs/223.md new file mode 100644 index 0000000000000000000000000000000000000000..853b4c25debfe15d6d5b64dcf93b23144d5ae2a0 --- /dev/null +++ b/_book/docs/223.md @@ -0,0 +1,30 @@ +# Deprecated GitLab CI/CD variables + +> 原文:[https://docs.gitlab.com/ee/ci/variables/deprecated_variables.html](https://docs.gitlab.com/ee/ci/variables/deprecated_variables.html) + +* [GitLab 9.0 renamed variables](#gitlab-90-renamed-variables) + +# Deprecated GitLab CI/CD variables[](#deprecated-gitlab-cicd-variables "Permalink") + +通读本文档以了解不赞成使用哪些预定义变量及其新引用. + +## GitLab 9.0 renamed variables[](#gitlab-90-renamed-variables "Permalink") + +为了在整个 GitLab 上遵循命名约定,并进一步远离`build`术语而转向`job` ,一些[CI / CD 环境变量](README.html#predefined-environment-variables)被重命名为 GitLab 9.0 版本. + +**注意:**从 GitLab 9.0 开始,我们已弃用`$CI_BUILD_*`变量. **强烈建议您使用新变量,因为我们将在以后的 GitLab 版本中删除旧变量.** + +| 8.x 名称 | 9.0+ name | +| --- | --- | +| `CI_BUILD_BEFORE_SHA` | `CI_COMMIT_BEFORE_SHA` | +| `CI_BUILD_ID` | `CI_JOB_ID` | +| `CI_BUILD_MANUAL` | `CI_JOB_MANUAL` | +| `CI_BUILD_NAME` | `CI_JOB_NAME` | +| `CI_BUILD_REF` | `CI_COMMIT_SHA` | +| `CI_BUILD_REF_NAME` | `CI_COMMIT_REF_NAME` | +| `CI_BUILD_REF_SLUG` | `CI_COMMIT_REF_SLUG` | +| `CI_BUILD_REPO` | `CI_REPOSITORY_URL` | +| `CI_BUILD_STAGE` | `CI_JOB_STAGE` | +| `CI_BUILD_TAG` | `CI_COMMIT_TAG` | +| `CI_BUILD_TOKEN` | `CI_JOB_TOKEN` | +| `CI_BUILD_TRIGGERED` | `CI_PIPELINE_TRIGGERED` | \ No newline at end of file diff --git a/_book/docs/224.md b/_book/docs/224.md new file mode 100644 index 0000000000000000000000000000000000000000..76ec5964158d052f10ba1b05b38190ec1aedfa81 --- /dev/null +++ b/_book/docs/224.md @@ -0,0 +1,853 @@ +# Environments and deployments + +> 原文:[https://docs.gitlab.com/ee/ci/environments/](https://docs.gitlab.com/ee/ci/environments/) + +* [Introduction](#introduction) +* [Configuring environments](#configuring-environments) + * [Defining environments](#defining-environments) + * [Environment variables and Runner](#environment-variables-and-runner) + * [Set dynamic environment URLs after a job finishes](#set-dynamic-environment-urls-after-a-job-finishes) + * [Example of setting dynamic environment URLs](#example-of-setting-dynamic-environment-urls) + * [Configuring manual deployments](#configuring-manual-deployments) + * [Configuring dynamic environments](#configuring-dynamic-environments) + * [Allowed variables](#allowed-variables) + * [Example configuration](#example-configuration) + * [Configuring Kubernetes deployments](#configuring-kubernetes-deployments) + * [Configuring incremental rollouts](#configuring-incremental-rollouts) + * [Deployment safety](#deployment-safety) + * [Complete example](#complete-example) + * [Protected environments](#protected-environments) +* [Working with environments](#working-with-environments) + * [Viewing environments and deployments](#viewing-environments-and-deployments) + * [Viewing deployment history](#viewing-deployment-history) + * [Retrying and rolling back](#retrying-and-rolling-back) + * [What to expect with a rollback](#what-to-expect-with-a-rollback) + * [Using the environment URL](#using-the-environment-url) + * [Going from source files to public pages](#going-from-source-files-to-public-pages) + * [Stopping an environment](#stopping-an-environment) + * [Automatically stopping an environment](#automatically-stopping-an-environment) + * [Environments auto-stop](#environments-auto-stop) + * [Auto-stop example](#auto-stop-example) + * [Delete a stopped environment](#delete-a-stopped-environment) + * [Delete environments through the UI](#delete-environments-through-the-ui) + * [Delete environments through the API](#delete-environments-through-the-api) + * [Prepare an environment](#prepare-an-environment) + * [Grouping similar environments](#grouping-similar-environments) + * [Monitoring environments](#monitoring-environments) + * [Embedding metrics in GitLab Flavored Markdown](#embedding-metrics-in-gitlab-flavored-markdown) + * [Web terminals](#web-terminals) + * [Check out deployments locally](#check-out-deployments-locally) + * [Scoping environments with specs](#scoping-environments-with-specs) + * [Environments Dashboard](#environments-dashboard-premium) +* [Limitations](#limitations) +* [Further reading](#further-reading) + +# Environments and deployments[](#environments-and-deployments "Permalink") + +在 GitLab 8.9 中引入. + +环境允许您在 GitLab 中控制软件的连续部署. + +## Introduction[](#introduction "Permalink") + +在准备将软件投入大众使用之前,软件开发过程需要许多阶段. + +例如: + +1. 开发代码. +2. 测试您的代码. +3. 在将代码发布给公众之前,请将其部署到测试或暂存环境中. + +This helps find bugs in your software, and also in the deployment process as well. + +GitLab CI / CD 不仅能够测试或构建您的项目,而且还可以在基础架构中部署它们,并具有给您提供一种跟踪部署的方式的额外好处. 换句话说,您将始终知道服务器上当前正在部署或已经部署了什么. + +重要的是要知道: + +* 环境就像您的 CI 作业的标签一样,描述了代码的部署位置. +* [作业](../yaml/README.html#introduction)是在[作业](../yaml/README.html#introduction)将代码版本部署到环境时创建的,因此每个环境可以有一个或多个部署. + +GitLab: + +* 提供每种环境的完整部署历史记录. +* 跟踪您的部署,因此您始终知道服务器上当前正在部署什么. + +如果您有与项目关联的部署服务(例如[Kubernetes)](../../user/project/clusters/index.html) ,则可以使用它来协助您的部署,甚至可以从 GitLab 中访问您环境的[Web 终端](#web-terminals) ! + +## Configuring environments[](#configuring-environments "Permalink") + +配置环境涉及: + +1. 了解[管道的](../pipelines/index.html)工作方式. +2. 在项目的[`.gitlab-ci.yml`](../yaml/README.html)文件中定义环境. +3. 创建配置为部署您的应用程序的作业. 例如,配置了[`environment`](../yaml/README.html#environment)的部署作业将您的应用程序部署到[Kubernetes 集群](../../user/project/clusters/index.html) . + +本节的其余部分说明了如何使用示例方案配置环境和部署. 假设您已经: + +* 在 GitLab 中创建了一个[项目](../../gitlab-basics/create-project.html) . +* 设置[亚军](../runners/README.html) . + +在方案中: + +* 我们正在开发一个应用程序. +* 我们想运行测试并在所有分支上构建我们的应用程序. +* 我们的默认分支是`master` . +* We deploy the app only when a pipeline on `master` branch is run. + +### Defining environments[](#defining-environments "Permalink") + +让我们考虑以下`.gitlab-ci.yml`示例: + +``` +stages: + - test + - build + - deploy + +test: + stage: test + script: echo "Running tests" + +build: + stage: build + script: echo "Building the app" + +deploy_staging: + stage: deploy + script: + - echo "Deploy to staging server" + environment: + name: staging + url: https://staging.example.com + only: + - master +``` + +我们定义了三个[阶段](../yaml/README.html#stages) : + +* `test` +* `build` +* `deploy` + +分配给这些阶段的作业将按此顺序运行. 如果任何作业失败,则管道将失败,分配给下一阶段的作业将不会运行. + +在我们的情况下: + +* `test`作业将首先运行. +* 然后是`build`作业. +* 最后, `deploy_staging`作业. + +使用此配置,我们: + +* 检查测试是否通过. +* 确保我们的应用程序能够成功构建. +* 最后,我们部署到登台服务器. + +**注意:** `environment`关键字定义了应用程序的部署位置. 环境`name`和`url`在 GitLab 中的各个位置公开. 每次指定环境的作业成功执行时,都会记录部署,Git SHA 和环境名称.**注意:**环境名称中不允许使用某些字符. 仅使用字母,数字,空格和`-` , `_` , `/` , `{` , `}`或`.` . 另外,它不得以`/`开头或结尾. + +总而言之,使用上述`.gitlab-ci.yml`我们已经实现了以下目标: + +* 所有分支机构将运行`test`并`build`作业. +* `deploy_staging`作业将[仅](../yaml/README.html#onlyexcept-basic)在`master`分支上运行,这意味着从分支创建的所有合并请求都不会部署到登台服务器. +* 合并请求合并后,所有作业将运行,并且`deploy_staging`作业会将我们的代码部署到登台服务器,而部署将记录在名为`staging`的环境中. + +#### Environment variables and Runner[](#environment-variables-and-runner "Permalink") + +从 GitLab 8.15 开始,环境名称以两种形式向 Runner 显示: + +* `$CI_ENVIRONMENT_NAME` . `.gitlab-ci.yml`给出的名称(扩展了所有变量). +* `$CI_ENVIRONMENT_SLUG` . 名称的"清理"版本,适用于 URL,DNS 等. + +如果更改现有环境的名称,则: + +* `$CI_ENVIRONMENT_NAME`变量将使用新的环境名称进行更新. +* `$CI_ENVIRONMENT_SLUG`变量将保持不变,以防止意外的副作用. + +从 GitLab 9.3 开始,环境 URL 通过`$CI_ENVIRONMENT_URL`向 Runner `$CI_ENVIRONMENT_URL` . URL 可以从以下任意一个展开: + +* `.gitlab-ci.yml`. +* 如果未在`.gitlab-ci.yml`定义,则来自环境的外部 URL. + +#### Set dynamic environment URLs after a job finishes[](#set-dynamic-environment-urls-after-a-job-finishes "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/17066) . + +在作业脚本中,您可以指定静态[环境 URL](#using-the-environment-url) . 但是,有时可能需要动态 URL. 例如,如果您将 Review App 部署到一个外部托管服务,该服务会为每个部署生成一个随机 URL,例如`https://94dd65b.amazonaws.com/qa-lambda-1234567` ,则在部署脚本之前您不会知道该 URL 完成. 如果要在 GitLab 中使用环境 URL,则必须手动更新. + +为了解决此问题,您可以配置部署作业以报告一组变量,包括由外部服务动态生成的 URL. GitLab 支持[dotenv( `.env` )](https://github.com/bkeepers/dotenv)文件格式,并使用`.env`文件中定义的变量扩展`environment:url`值. + +要使用此功能,请在`.gitlab-ci.yml`指定[`artifacts:reports:dotenv`](../pipelines/job_artifacts.html#artifactsreportsdotenv)关键字. + +有关概述,请参阅[在作业完成后设置动态 URL](https://youtu.be/70jDXtOf4Ig) . + +##### Example of setting dynamic environment URLs[](#example-of-setting-dynamic-environment-urls "Permalink") + +以下示例显示了一个 Review App,该 App 为每个合并请求创建一个新环境. 每次推送都会触发`review`作业,并创建或更新一个名为`review/your-branch-name` . 环境 URL 设置为`$DYNAMIC_ENVIRONMENT_URL` : + +``` +review: + script: + - DYNAMIC_ENVIRONMENT_URL=$(deploy-script) # In script, get the environment URL. + - echo "DYNAMIC_ENVIRONMENT_URL=$DYNAMIC_ENVIRONMENT_URL" >> deploy.env # Add the value to a dotenv file. + artifacts: + reports: + dotenv: deploy.env # Report back dotenv file to rails. + environment: + name: review/$CI_COMMIT_REF_SLUG + url: $DYNAMIC_ENVIRONMENT_URL # and set the variable produced in script to `environment:url` + on_stop: stop_review + +stop_review: + script: + - ./teardown-environment + when: manual + environment: + name: review/$CI_COMMIT_REF_SLUG + action: stop +``` + +`review`作业完成后,GitLab 会立即更新`review/your-branch-name`环境的 URL. 它解析`deploy.env`报告工件,将变量列表注册为在运行时创建的变量,并将其用于扩展`environment:url: $DYNAMIC_ENVIRONMENT_URL`并将其设置为环境 URL. 您还可以在`environment:url:`处指定 URL 的静态部分,例如`https://$DYNAMIC_ENVIRONMENT_URL` . 如果`DYNAMIC_ENVIRONMENT_URL`值为`example.com` ,则最终结果将为`https://example.com` . + +[在 UI 中可以看到](#using-the-environment-url)为`review/your-branch-name`环境分配的 URL. + +> **Notes:** +> +> * `stop_review`不会生成 dotenv 报告工件,因此不会识别`DYNAMIC_ENVIRONMENT_URL`变量. 因此,您不应在`stop_review`作业中设置`environment:url:` `stop_review` +> * 如果环境 URL 无效(例如,URL 格式错误),则系统不会更新环境 URL. + +### Configuring manual deployments[](#configuring-manual-deployments "Permalink") + +添加`when: manual`添加到自动执行的作业的配置会将其转换为需要手动操作的作业. + +为了扩展[前面的示例](#defining-environments) ,以下内容包括另一个作业,该作业将我们的应用程序部署到生产服务器,并由`production`环境进行跟踪. + +`.gitlab-ci.yml`文件如下: + +``` +stages: + - test + - build + - deploy + +test: + stage: test + script: echo "Running tests" + +build: + stage: build + script: echo "Building the app" + +deploy_staging: + stage: deploy + script: + - echo "Deploy to staging server" + environment: + name: staging + url: https://staging.example.com + only: + - master + +deploy_prod: + stage: deploy + script: + - echo "Deploy to production server" + environment: + name: production + url: https://example.com + when: manual + only: + - master +``` + +The `when: manual` action: + +* 在 GitLab 的用户界面中显示该作业的"播放"按钮. +* 意味着仅在单击"播放"按钮时才会触发`deploy_prod`作业. + +您可以在管道,环境,部署和作业视图中找到"播放"按钮. + +| View | Screenshot | +| --- | --- | +| Pipelines | [![Pipelines manual action](img/379bd77b46dd7f0617bc273a203c9a29.png)](../img/environments_manual_action_pipelines.png) | +| 单管道 | [![Pipelines manual action](img/e2e1d44121ea24d32b388b9b84bd7ea5.png)](../img/environments_manual_action_single_pipeline.png) | +| Environments | [![Environments manual action](img/14b1dcd13ed2d776e5cab726504e2df9.png)](../img/environments_manual_action_environments.png) | +| Deployments | [![Deployments manual action](img/85b07bb9804f9dd3c4e3edfc1e562f31.png)](../img/environments_manual_action_deployments.png) | +| Jobs | [![Builds manual action](img/ef8ff296b4a28ddcd52a6c4fd3ded454.png)](../img/environments_manual_action_jobs.png) | + +在任何视图中单击播放按钮都将触发`deploy_prod`作业,并且部署将记录为名为`production`的新环境. + +**注意:**如果您环境的名称是`production` (全部为小写),它将记录在[Value Stream Analytics 中](../../user/project/cycle_analytics.html) . + +### Configuring dynamic environments[](#configuring-dynamic-environments "Permalink") + +当部署到"稳定"的环境(例如分阶段或生产)时,常规环境会很好. + +但是,对于`master`以外的分支环境,可以使用动态环境. 动态环境可以通过在`.gitlab-ci.yml`动态声明其名称来动态创建环境. + +动态环境是[Review 应用程序](../review_apps/index.html)的基本组成部分. + +#### Allowed variables[](#allowed-variables "Permalink") + +动态环境的`name`和`url`参数可以使用大多数可用的 CI / CD 变量,包括: + +* [Predefined environment variables](../variables/README.html#predefined-environment-variables) +* [Project and group variables](../variables/README.html#gitlab-cicd-environment-variables) +* [`.gitlab-ci.yml` variables](../yaml/README.html#variables) + +但是,不能使用定义的变量: + +* Under `script`. +* 在跑步者方面. + +在`environment:name`上下文中还不支持其他变量. 有关更多信息,请参见[在哪里可以使用变量](../variables/where_variables_can_be_used.html) . + +#### Example configuration[](#example-configuration "Permalink") + +GitLab Runner 在作业运行时会公开各种[环境变量](../variables/README.html) ,因此您可以将它们用作环境名称. + +在以下示例中,作业将部署到`master`以外的所有分支: + +``` +deploy_review: + stage: deploy + script: + - echo "Deploy a review app" + environment: + name: review/$CI_COMMIT_REF_NAME + url: https://$CI_ENVIRONMENT_SLUG.example.com + only: + - branches + except: + - master +``` + +在此示例中: + +* 作业的名称为`deploy_review` ,它在`deploy`阶段运行. +* 我们将`environment`设置为`environment` `environment:name`作为`review/$CI_COMMIT_REF_NAME` . 由于[环境名称](../yaml/README.html#environmentname)可以包含斜杠( `/` ),因此我们可以使用此模式来区分动态环境和常规环境. +* We tell the job to run [`only`](../yaml/README.html#onlyexcept-basic) on branches, [`except`](../yaml/README.html#onlyexcept-basic) `master`. + +对于以下值: + +* `environment:name` ,第一部分是`review` ,后跟一个`/` ,然后是`$CI_COMMIT_REF_NAME` ,它接收分支名称的值. +* `environment:url` ,我们希望每个分支都有一个特定且不同的 URL. `$CI_COMMIT_REF_NAME`可能包含`/`或其他在域名或 URL 中无效的字符,因此我们使用`$CI_ENVIRONMENT_SLUG`来确保获得有效的 URL. + + 例如,给定`$CI_COMMIT_REF_NAME`为`100-Do-The-Thing` ,URL 将类似于`https://100-do-the-4f99a2.example.com` . 同样,设置 Web 服务器来满足这些请求的方式取决于您的设置. + + 我们在这里使用了`$CI_ENVIRONMENT_SLUG` ,因为它保证是唯一的. 如果您使用的是[GitLab Flow 之](../../topics/gitlab_flow.html)类的工作[流程](../../topics/gitlab_flow.html) ,则冲突不太可能发生,并且您可能更希望环境名称与分支名称更紧密地[关联](../../topics/gitlab_flow.html) . 在这种情况下,您可以在上面的示例中的`environment:url`中使用`$CI_COMMIT_REF_NAME` : `https://$CI_COMMIT_REF_NAME.example.com` ,其 URL 为`https://100-do-the-thing.example.com` . + +**注意:**您不需要在动态环境的名称中使用相同的前缀或仅使用斜杠( `/` ). 但是,使用此格式将启用[类似环境分组](#grouping-similar-environments)功能. + +### Configuring Kubernetes deployments[](#configuring-kubernetes-deployments "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) . + +如果要部署到与项目关联的[Kubernetes 集群](../../user/project/clusters/index.html) ,则可以从`gitlab-ci.yml`文件配置这些部署. + +支持以下配置选项: + +* [`namespace`](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) + +在以下示例中,作业会将您的应用程序部署到`production` Kubernetes 命名空间. + +``` +deploy: + stage: deploy + script: + - echo "Deploy to production server" + environment: + name: production + url: https://example.com + kubernetes: + namespace: production + only: + - master +``` + +使用 GitLab 的 Kubernetes 集成部署到 Kubernetes 集群时,有关集群和名称空间的信息将显示在部署作业页面上的作业跟踪上方: + +[![Deployment cluster information](img/5e3cf2019e5c2c58b6dd5868fffb9e81.png)](../img/environments_deployment_cluster_v12_8.png) + +**注意:** [由 GitLab 管理的](../../user/project/clusters/index.html#gitlab-managed-clusters) Kubernetes 集群不支持 Kubernetes 配置. 要跟踪对 GitLab 管理的集群的支持进度,请参阅[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/38054) . + +#### Configuring incremental rollouts[](#configuring-incremental-rollouts "Permalink") + +了解如何通过[增量部署](../environments/incremental_rollouts.html)仅对 Kubernetes Pod 的一部分发布生产更改. + +### Deployment safety[](#deployment-safety "Permalink") + +部署作业可能比管道中的其他作业更敏感,并且可能需要格外小心. GitLab 中有多个功能可帮助维护部署安全性和稳定性. + +* [Restrict write-access to a critical environment](deployment_safety.html#restrict-write-access-to-a-critical-environment) +* [Limit the job-concurrency for deployment jobs](deployment_safety.html#ensure-only-one-deployment-job-runs-at-a-time) +* [Skip outdated deployment jobs](deployment_safety.html#skip-outdated-deployment-jobs) +* [Prevent deployments during deploy freeze windows](deployment_safety.html#prevent-deployments-during-deploy-freeze-windows) + +### Complete example[](#complete-example "Permalink") + +本节中的配置提供了完整的开发工作流程,其中您的应用程序是: + +* Tested. +* Built. +* 部署为 Review App. +* 合并请求合并后,部署到登台服务器. +* 最后,能够手动部署到生产服务器. + +以下内容结合了之前的配置示例,包括: + +* Defining [simple environments](#defining-environments) for testing, building, and deployment to staging. +* 添加[手动操作](#configuring-manual-deployments)以部署到生产中. +* 为部署创建[动态环境](#configuring-dynamic-environments)以供查看. + +``` +stages: + - test + - build + - deploy + +test: + stage: test + script: echo "Running tests" + +build: + stage: build + script: echo "Building the app" + +deploy_review: + stage: deploy + script: + - echo "Deploy a review app" + environment: + name: review/$CI_COMMIT_REF_NAME + url: https://$CI_ENVIRONMENT_SLUG.example.com + only: + - branches + except: + - master + +deploy_staging: + stage: deploy + script: + - echo "Deploy to staging server" + environment: + name: staging + url: https://staging.example.com + only: + - master + +deploy_prod: + stage: deploy + script: + - echo "Deploy to production server" + environment: + name: production + url: https://example.com + when: manual + only: + - master +``` + +一个更现实的示例还包括将文件复制到 Web 服务器(例如 NGINX)可以访问并为其提供服务的位置. + +下面的示例将`public`目录复制到`/srv/nginx/$CI_COMMIT_REF_SLUG/public` : + +``` +review_app: + stage: deploy + script: + - rsync -av --delete public /srv/nginx/$CI_COMMIT_REF_SLUG + environment: + name: review/$CI_COMMIT_REF_NAME + url: https://$CI_COMMIT_REF_SLUG.example.com +``` + +此示例要求在要运行此作业的服务器上设置 NGINX 和 GitLab Runner. + +**注意:**有关分支机构和 Review Apps 命名的一些极端情况,请参阅" [限制"](#limitations)部分. + +完整的示例为开发人员提供了以下工作流程: + +* 在本地创建分支. +* 进行更改并提交. +* 将分支推送到 GitLab. +* 创建一个合并请求. + +在后台,GitLab Runner 将: + +* 拾取更改并开始运行作业. +* 按`stages`定义顺序运行作业: + * 首先,运行测试. + * 如果测试成功,请构建应用程序. + * 如果构建成功,则将应用程序部署到具有特定于分支机构名称的环境. + +所以现在,每个分支: + +* 获取自己的环境. +* 已部署到其自己的唯一位置,具有以下优点: + * 有[部署历史](#viewing-deployment-history) . + * 如果需要,能够[回滚更改](#retrying-and-rolling-back) . + +有关更多信息,请参见[使用环境 URL](#using-the-environment-url) . + +### Protected environments[](#protected-environments "Permalink") + +可以对环境进行"保护",限制对它们的访问. + +有关更多信息,请参阅[受保护的环境](protected_environments.html) . + +## Working with environments[](#working-with-environments "Permalink") + +配置环境后,GitLab 将提供许多用于处理环境的功能,如下所述. + +### Viewing environments and deployments[](#viewing-environments-and-deployments "Permalink") + +每个项目的" **操作">"环境"**页面上都提供了环境和部署状态的列表. + +例如: + +[![Environment view](img/9121e1772146daa5a3259be82cde8902.png)](../img/environments_available.png) + +此示例显示: + +* 环境名称以及指向其部署的链接. +* 最后的部署 ID 号以及执行者. +* 上次部署的作业 ID 及其各自的作业名称. +* 上次部署的提交信息,例如谁提交了它,到哪个分支以及提交的 Git SHA. +* 上次部署的确切时间. +* 该按钮`.gitlab-ci.yml`您带到您在`.gitlab-ci.yml`的`environment`关键字下定义的 URL. +* 重新部署最新部署的按钮,这意味着它将运行由环境名称定义的特定提交的作业. + +" **环境"**页面中显示的信息仅限于最新的部署,但是一个环境可以具有多个部署. + +> **Notes:** +> +> * 虽然您可以在 Web 界面中手动创建环境,但建议您首先在`.gitlab-ci.yml`定义环境. 首次部署后,将自动为您创建它们. +> * 只有具有[Reporter 权限](../../user/permissions.html#project-members-permissions)及以上[权限](../../user/permissions.html#project-members-permissions)的用户才能查看环境页面. 有关权限的更多信息,请参阅[权限文档](../../user/permissions.html) . +> * 只有在正确配置`.gitlab-ci.yml`之后发生的部署才会显示在" **环境"**和" **最后部署"**列表中. + +### Viewing deployment history[](#viewing-deployment-history "Permalink") + +GitLab keeps track of your deployments, so you: + +* 始终知道服务器上当前正在部署什么. +* 可以具有每种环境的完整部署历史记录. + +单击环境可显示其部署的历史记录. 这是具有多个部署的**环境**示例页面: + +[![Deployments](img/e3feca46add6d42b1afc92fcf120dbfb.png)](../img/deployments_view.png) + +该视图类似于" **环境"**页面,但是显示了所有部署. 在此视图中,还有一个" **回滚"**按钮. 有关更多信息,请参阅[重试和回滚](#retrying-and-rolling-back) . + +### Retrying and rolling back[](#retrying-and-rolling-back "Permalink") + +如果部署存在问题,则可以重试或回滚. + +要重试或回滚部署: + +1. 导航到" **操作">"环境"** . +2. 单击环境. +3. 在环境的部署历史记录列表中,单击: + * 最后部署旁边的" **重试"**按钮,以重试该部署. + * 先前成功部署旁边的" **回滚"**按钮,以回滚到该部署. + +#### What to expect with a rollback[](#what-to-expect-with-a-rollback "Permalink") + +在特定提交上按**回滚**按钮将触发具有其自己的唯一作业 ID 的*新*部署. + +这意味着您将看到一个新的部署,该部署指向您要回滚的提交. + +**注意:**作业`script`定义的部署过程确定回滚是否成功. + +### Using the environment URL[](#using-the-environment-url "Permalink") + +[环境 URL](../yaml/README.html#environmenturl)在 GitLab 中的几个位置公开: + +* 在合并请求小部件中作为链接: [![合并请求中的环境 URL](img/3d8b21038a5aa14baa75dc65de55d728.png)](../img/environments_mr_review_app.png) +* 在"环境"视图中作为按钮: [![环境中的环境 URL](img/9121e1772146daa5a3259be82cde8902.png)](../img/environments_available.png) +* 在"部署"视图中作为按钮: [![部署中的环境 URL](img/e3feca46add6d42b1afc92fcf120dbfb.png)](../img/deployments_view.png) + +在以下情况下,您可以在合并请求本身中看到此信息: + +* 合并请求最终合并到默认分支(通常是`master` ). +* 该分支还部署到环境(例如, `staging`或`production` ). + +例如: + +[![Environment URLs in merge request](img/061d5d0d60fdf019ad696860942563af.png)](../img/environments_link_url_mr.png) + +#### Going from source files to public pages[](#going-from-source-files-to-public-pages "Permalink") + +使用 GitLab 的[路线图,](../review_apps/index.html#route-maps)您可以在为 Review Apps 设置的环境中直接从源文件转到公共页面. + +### Stopping an environment[](#stopping-an-environment "Permalink") + +停止环境: + +* 将其从" **可用"**环境列表移至" [**环境"**页面](#viewing-environments-and-deployments)上的"已**停止"**环境列表. +* 执行[`on_stop`操作](../yaml/README.html#environmenton_stop) (如果已定义). + +当多个开发人员同时在一个项目上工作时,通常会使用此方法,每个开发人员都将推入自己的分支,从而创建了许多动态环境. + +**注意:**从 GitLab 8.14 开始,删除动态环境的关联分支后,它们会自动停止. + +#### Automatically stopping an environment[](#automatically-stopping-an-environment "Permalink") + +可以使用特殊配置自动停止环境. + +考虑以下示例,其中`deploy_review`作业调用`stop_review`清理并停止环境: + +``` +deploy_review: + stage: deploy + script: + - echo "Deploy a review app" + environment: + name: review/$CI_COMMIT_REF_NAME + url: https://$CI_ENVIRONMENT_SLUG.example.com + on_stop: stop_review + only: + - branches + except: + - master + +stop_review: + stage: deploy + variables: + GIT_STRATEGY: none + script: + - echo "Remove review app" + when: manual + environment: + name: review/$CI_COMMIT_REF_NAME + action: stop +``` + +设置[`GIT_STRATEGY`](../yaml/README.html#git-strategy)到`none`是必要的`stop_review`使各项工作[GitLab 亚军](https://docs.gitlab.com/runner/)不会尝试分支被删除后退房的代码. + +当您的环境中定义了停止动作时(通常在该环境描述了 Review App 时),当关联的分支被删除时,GitLab 将自动触发停止动作. `stop_review`作业必须与`deploy_review`作业处于同一`stage` ,以便环境自动停止. + +此外,两个作业都应具有匹配的[`rules`](../yaml/README.html#onlyexcept-basic)或[`only/except`](../yaml/README.html#onlyexcept-basic)配置[`only/except`](../yaml/README.html#onlyexcept-basic) . 在上面的示例中,如果配置不同,则`stop_review`作业可能不会包含在所有包含`deploy_review`作业的管道中,并且将无法触发该`action: stop`会自动停止环境. + +您可以在[`.gitlab-ci.yml`参考中](../yaml/README.html#environmenton_stop)阅读更多[`.gitlab-ci.yml`](../yaml/README.html#environmenton_stop) . + +#### Environments auto-stop[](#environments-auto-stop "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/20956) . + +您可以设置环境的到期时间,并在一定时间后自动将其停止. + +例如,考虑在 Review Apps 环境中使用此功能. 设置 Review Apps 时,有时它们会长时间运行,因为某些合并请求处于打开状态. 这种情况的一个示例是,由于优先级更改或决定采用其他方法而导致合并请求的作者未积极处理合并请求,而合并请求却被遗忘了. 空闲环境会浪费资源,因此应尽快终止它们. + +要解决此问题,您可以为 Review Apps 环境指定一个可选的到期日期. 当达到到期时间时,GitLab 将自动触发作业以停止环境,而无需手动执行此操作. 万一更新了环境,则到期将得到更新,以确保只有活动的合并请求才能继续运行 Review Apps. + +要启用此功能,您需要在`.gitlab-ci.yml`指定[`environment:auto_stop_in`](../yaml/README.html#environmentauto_stop_in)关键字. 您可以指定一个对人类友好的日期作为值,例如`1 hour and 30 minutes`或`1 day` . `auto_stop_in`使用相同的[`artifacts:expire_in`](../yaml/README.html#artifactsexpire_in)格式[`artifacts:expire_in` docs](../yaml/README.html#artifactsexpire_in) . + +**注意:**由于资源限制,用于停止环境的后台工作器每小时仅运行一次. 这意味着不会按指定的确切时间在特定的时间戳记下停止环境,而是在每小时的 cron 工作者检测到过期的环境时将其停止. + +##### Auto-stop example[](#auto-stop-example "Permalink") + +在以下示例中,有一个基本的审阅应用程序设置,可为每个合并请求创建一个新环境. 每次推送都会触发`review_app`作业,并创建或更新一个名为`review/your-branch-name` . 环境一直运行,直到执行`stop_review_app` : + +``` +review_app: + script: deploy-review-app + environment: + name: review/$CI_COMMIT_REF_NAME + on_stop: stop_review_app + auto_stop_in: 1 week + +stop_review_app: + script: stop-review-app + environment: + name: review/$CI_COMMIT_REF_NAME + action: stop + when: manual +``` + +只要合并请求处于活动状态并不断获得新的提交,审阅应用程序就不会停止,因此开发人员无需担心重新启动审阅应用程序. + +另一方面,由于将`stop_review_app`设置为`auto_stop_in: 1 week` ,如果合并请求变得不活动超过一个星期,则 G​​itLab 会自动触发`stop_review_app`作业以停止环境. + +您还可以通过 GitLab UI 检查环境的到期日期. 为此,请转到**操作>环境>环境** . 您可以在左上部分看到自动停止时间,并在右上部分看到一个记号按钮. 此固定标记按钮可用于防止环境自动停止. 单击此按钮,将`auto_stop_in`设置,并且环境将处于活动状态,直到手动将其停止为止. + +[![Environment auto stop](img/c67faf1fb34407861ed68b426e46da72.png)](../img/environment_auto_stop_v12_8.png) + +#### Delete a stopped environment[](#delete-a-stopped-environment "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/20620) . + +您可以通过以下两种方式之一删除已[停止的环境](#stopping-an-environment) :通过 GitLab UI 或通过 API. + +##### Delete environments through the UI[](#delete-environments-through-the-ui "Permalink") + +要查看已**停止**环境的列表,请导航至" **操作">"环境"** ,然后单击"已**停止"**选项卡. + +在此处,您可以直接单击" **删除"**按钮,也可以单击环境名称以查看其详细信息,然后从此处**删除**它. + +您还可以通过查看已停止环境的详细信息来删除环境: + +1. 导航到" **操作">"环境"** . +2. 在"已**停止的**环境"列表中单击环境的名称. +3. 单击显示在所有已停止环境顶部的" **删除"**按钮. +4. 最后,在似乎要删除它的模式中确认您选择的环境. + +##### Delete environments through the API[](#delete-environments-through-the-api "Permalink") + +也可以使用[Environments API](../../api/environments.html#delete-an-environment)删除[环境](../../api/environments.html#delete-an-environment) . + +### Prepare an environment[](#prepare-an-environment "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/208655) . + +默认情况下,每次运行具有指定环境的构建时,GitLab 都会创建一个[部署](#viewing-deployment-history) . 较新的部署也可以[取消较旧的](deployment_safety.html#skip-outdated-deployment-jobs)部署. + +您可能需要指定一个环境关键字来[保护构建免受未经授权的访问](protected_environments.html) ,或获得对[范围变量的](#scoping-environments-with-specs)访问. 在这些情况下,可以使用以下`action: prepare`关键字以确保不会创建部署,并且不会取消任何构建: + +``` +build: + stage: build + script: + - echo "Building the app" + environment: + name: staging + action: prepare + url: https://staging.example.com +``` + +### Grouping similar environments[](#grouping-similar-environments "Permalink") + +在 GitLab 8.14 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7015) . + +如[配置动态环境中所述](#configuring-dynamic-environments) ,您可以在环境名称前添加一个单词,后跟一个`/` ,最后是分支名称,该分支名称由`CI_COMMIT_REF_NAME`变量自动定义. + +简而言之,所有名为`type/foo`的环境都在同一个名为`type`组下显示. + +在[最小的示例中](#example-configuration) ,我们将环境命名为`review/$CI_COMMIT_REF_NAME` ,其中`$CI_COMMIT_REF_NAME`是分支名称. 这是示例的片段: + +``` +deploy_review: + stage: deploy + script: + - echo "Deploy a review app" + environment: + name: review/$CI_COMMIT_REF_NAME +``` + +在这种情况下,如果您访问" **环境"**页面并且分支存在,则应该看到类似以下内容的内容: + +[![Environment groups](img/60958029f56e4c49c6a21082ea151191.png)](../img/environments_dynamic_groups.png) + +### Monitoring environments[](#monitoring-environments "Permalink") + +如果已启用[Prometheus 来监视系统和响应指标](../../user/project/integrations/prometheus.html) ,则可以监视在每个环境中运行的应用程序的行为. 为了显示监视仪表板,您需要配置 Prometheus 来收集至少一个[支持的指标](../../user/project/integrations/prometheus_library/index.html) . + +**注意:**从 GitLab 9.2 开始,到环境的所有部署都直接显示在监视仪表板上. + +配置完成后,GitLab 将尝试为成功部署的任何环境检索[支持的性能指标](../../user/project/integrations/prometheus_library/index.html) . 如果成功检索到监视数据,则将为每个环境显示一个" **监视"**按钮. + +[![Environment Detail with Metrics](img/e3feca46add6d42b1afc92fcf120dbfb.png)](../img/deployments_view.png) + +单击" **监视"**按钮将显示一个新页面,该页面最多显示最近 8 个小时的性能数据. 初始部署后,可能需要一两分钟的时间才能显示数据. + +环境的所有部署都直接显示在监视仪表板上,这使性能的任何变化与应用程序的新版本之间都可以轻松关联,而无需离开 GitLab. + +[![Monitoring dashboard](img/8c80632a58ede646cb8f2046924a504a.png)](../img/environments_monitoring.png) + +#### Embedding metrics in GitLab Flavored Markdown[](#embedding-metrics-in-gitlab-flavored-markdown "Permalink") + +公制图表可以嵌入到 GitLab Flavored Markdown 中. 有关更多详细信息,请参见[在 GitLab 风味 Markdown 中嵌入指标](../../operations/metrics/embed.html) . + +### Web terminals[](#web-terminals "Permalink") + +> Web 终端已在 GitLab 8.15 中添加,仅对项目维护者和所有者可用. + +If you deploy to your environments with the help of a deployment service (for example, the [Kubernetes integration](../../user/project/clusters/index.html)), GitLab can open a terminal session to your environment. + +这是一项功能强大的功能,可让您调试问题而不会离开 Web 浏览器. 要启用它,只需按照服务集成文档中给出的说明进行操作. + +启用后,您的环境将获得一个"终端"按钮: + +[![Terminal button on environment index](img/47c6e09feffe93d1d9f758d50837b31b.png)](../img/environments_terminal_button_on_index.png) + +您还可以从页面访问特定环境的终端按钮: + +[![Terminal button for an environment](img/b6d33f6e98bcf842659df9a637bbaeb9.png)](../img/environments_terminal_button_on_show.png) + +无论在哪里找到它,单击按钮都会带您到单独的页面来建立终端会话: + +[![Terminal page](img/92601175945fcac1aee644fd449e9adf.png)](../img/environments_terminal_page.png) + +就像其他终端一样工作. 您将处于部署创建的容器中,因此您可以: + +* 运行 shell 命令并实时获取响应. +* 检查日志. +* 试用配置或代码调整等. + +您可以在同一环境中打开多个终端,它们每个都有自己的 shell 会话,甚至可以是`screen`或`tmux`的多路复用器. + +**注意:**基于容器的部署通常缺少基本工具(例如编辑器),并且可以随时停止或重新启动. 如果发生这种情况,您将丢失所有更改. 将此视为调试工具,而不是全面的在线 IDE. + +### Check out deployments locally[](#check-out-deployments-locally "Permalink") + +从 GitLab 8.13 开始,每次部署都会在 Git 存储库中保存一个引用,因此仅需`git fetch`知道当前环境的状态. + +In your Git configuration, append the `[remote "<your-remote>"]` block with an extra fetch line: + +``` +fetch = +refs/environments/*:refs/remotes/origin/environments/* +``` + +### Scoping environments with specs[](#scoping-environments-with-specs "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2112) . +* 在 GitLab 12.2 中将[环境变量的作用域移至 Core](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30779) . + +您可以通过定义变量可用于的环境来限制变量的环境范围. + +可以使用通配符,默认环境范围是`*` ,这意味着任何作业都将具有此变量,与是否定义环境无关. + +例如,如果环境范围是`production` ,那么只有定义了环境`production`的作业才具有此特定变量. 通配符( `*` )可以与环境名称一起使用,因此,如果环境范围是`review/*`那么任何以环境名称以`review/`开头的作业都将具有该特定变量. + +对于每个环境,某些 GitLab 功能可能会有不同的行为. 例如,您可以[创建一个秘密变量,仅将其注入生产环境](../variables/README.html#limit-the-environment-scopes-of-environment-variables) . + +在大多数情况下,这些功能使用*环境规范*机制,该机制提供了一种在每个环境组内实现作用域的有效方法. + +假设有四种环境: + +* `production` +* `staging` +* `review/feature-1` +* `review/feature-2` + +Each environment can be matched with the following environment spec: + +| 环境规格 | `production` | `staging` | `review/feature-1` | `review/feature-2` | +| --- | --- | --- | --- | --- | +| * | Matched | Matched | Matched | Matched | +| production | Matched |   |   |   | +| staging |   | Matched |   |   | +| review/* |   |   | Matched | Matched | +| review/feature-1 |   |   | Matched |   | + +如您所见,您可以使用特定的匹配来选择特定的环境,也可以使用通配符匹配( `*` )来选择特定的环境组,例如[Review Apps](../review_apps/index.html) ( `review/*` ). + +**注意:**最*具体的*规范优先于其他通配符匹配. 在这种情况下, `review/feature-1`规范优先于`review/*`和`*`规范. + +### Environments Dashboard[](#environments-dashboard-premium "Permalink") + +有关每个环境的运行状况的摘要,请参见[环境仪表板](../environments/environments_dashboard.html) . + +## Limitations[](#limitations "Permalink") + +在`environment: name` ,您仅限于[预定义的环境变量](../variables/predefined_variables.html) . 重用`script`内部定义为环境名称一部分的变量将不起作用. + +## Further reading[](#further-reading "Permalink") + +以下是一些您可能会发现有趣的链接: + +* [The `.gitlab-ci.yml` definition of environments](../yaml/README.html#environment) +* [A blog post on Deployments & Environments](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/) +* [Review Apps - Use dynamic environments to deploy your code for every branch](../review_apps/index.html) +* [Deploy Boards for your applications running on Kubernetes](../../user/project/deploy_boards.html) \ No newline at end of file diff --git a/_book/docs/225.md b/_book/docs/225.md new file mode 100644 index 0000000000000000000000000000000000000000..9bb6b86f0f33ebbcdcacee8f754a68eaba697fa4 --- /dev/null +++ b/_book/docs/225.md @@ -0,0 +1,52 @@ +# Protected Environments + +> 原文:[https://docs.gitlab.com/ee/ci/environments/protected_environments.html](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) + +* [Overview](#overview) +* [Protecting environments](#protecting-environments) +* [Modifying and unprotecting environments](#modifying-and-unprotecting-environments) + +# Protected Environments[](#protected-environments-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6303) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.3. + +## Overview[](#overview "Permalink") + +可以出于多种原因使用[环境](../environments/index.html) : + +* 其中一些仅用于测试. +* 其他用于生产. + +由于部署工作可以由具有不同角色的不同用户来提出,因此对"特定"环境进行"保护"以防止未经授权的人员影响他们很重要. + +默认情况下,受保护的环境会做一件事:它确保只有具有适当特权的人才能部署到该环境,从而确保其安全. + +**注意:**始终允许 GitLab 管理员使用环境,即使环境受到保护也是如此. + +要保护,更新或取消保护环境,您至少需要具有[维护者权限](../../user/permissions.html) . + +## Protecting environments[](#protecting-environments "Permalink") + +为了保护环境: + +1. 导航到项目的**"设置">" CI / CD"** . +2. 展开" **保护环境"**部分. +3. 从" **环境"**下拉菜单中,选择要保护的环境. +4. 在" **允许部署"**下拉菜单中,选择要授予其部署访问权限的角色,用户或组. 请记住: + * 有两种角色可供选择: + * **维护者** :将允许访问项目中的所有维护者. + * **开发人员** :将允许访问该项目中的所有维护人员和所有开发人员. + * 您只能选择已经与项目关联的组. + * 只有具有至少开发人员权限级别的用户才会显示在" **允许部署"**下拉菜单中. +5. 单击**保护**按钮. + +现在,受保护的环境将出现在受保护环境的列表中. + +## Modifying and unprotecting environments[](#modifying-and-unprotecting-environments "Permalink") + +维护者可以: + +* 通过在" **允许部署"**下拉菜单中更改访问权限,可以随时更新现有的受保护环境. +* 通过单击该环境的" **取消保护"**按钮来**取消保护**该环境. + +有关更多信息,请参阅[部署安全](deployment_safety.html) . \ No newline at end of file diff --git a/_book/docs/226.md b/_book/docs/226.md new file mode 100644 index 0000000000000000000000000000000000000000..0a508732bc371af564f93c4cedd40e2779ce55e2 --- /dev/null +++ b/_book/docs/226.md @@ -0,0 +1,174 @@ +# GitLab CI/CD Examples + +> 原文:[https://docs.gitlab.com/ee/ci/examples/README.html](https://docs.gitlab.com/ee/ci/examples/README.html) + +* [CI/CD examples](#cicd-examples) + * [Contributing examples](#contributing-examples) +* [CI/CD templates](#cicd-templates) + * [Adding templates to your GitLab installation](#adding-templates-to-your-gitlab-installation-premium-only) +* [Other resources](#other-resources) + * [CI/CD in the cloud](#cicd-in-the-cloud) + * [Customer stories](#customer-stories) + * [Getting started](#getting-started) + * [Implementing GitLab CI/CD](#implementing-gitlab-cicd) + * [Migrating to GitLab from third-party CI tools](#migrating-to-gitlab-from-third-party-ci-tools) + * [Integrating GitLab CI/CD with other systems](#integrating-gitlab-cicd-with-other-systems) + * [Mobile development](#mobile-development) + +# GitLab CI/CD Examples[](#gitlab-cicd-examples "Permalink") + +该页面包含指向各种示例的链接,这些示例可以帮助您了解如何针对特定用例实现[GitLab CI / CD](../README.html) . + +示例有几种形式. 作为以下内容的集合: + +* 在 GitLab 中维护的`.gitlab-ci.yml` [模板文件](#cicd-templates) ,用于许多常见的框架和编程语言. +* 具有各种语言[示例项目的](https://gitlab.com/gitlab-examples)存储库. 您可以分叉并根据自己的需要进行调整. 项目包括[多项目管道的](https://gitlab.com/gitlab-examples/multi-project-pipelines)演示以及[在 NGINX 服务的静态站点上](https://gitlab.com/gitlab-examples/review-apps-nginx/)使用[Review Apps](https://gitlab.com/gitlab-examples/review-apps-nginx/) . +* 下面列出了示例和[其他资源](#other-resources) . + +## CI/CD examples[](#cicd-examples "Permalink") + +下表列出了本节中包含分步教程的示例. + +| 用例 | Resource | +| --- | --- | +| 浏览器性能测试 | [Browser Performance Testing with the Sitespeed.io container](../../user/project/merge_requests/browser_performance_testing.html). | +| 负载性能测试 | [Load Performance Testing with the k6 container](../../user/project/merge_requests/load_performance_testing.html). | +| Clojure | [Test a Clojure application with GitLab CI/CD](test-clojure-application.html). | +| 使用 Dpl 进行部署 | [Using `dpl` as deployment tool](deployment/README.html). | +| Elixir | [Testing a Phoenix application with GitLab CI/CD](test_phoenix_app_with_gitlab_ci_cd/index.html). | +| 端到端测试 | [End-to-end testing with GitLab CI/CD and WebdriverIO](end_to_end_testing_webdriverio/index.html). | +| Game development | [DevOps and Game Dev with GitLab CI/CD](devops_and_game_dev_with_gitlab_ci_cd/index.html). | +| GitLab 页面 | 有关部署静态站点的完整示例,请参见[GitLab Pages](../../user/project/pages/index.html)文档. | +| 带有 Spring Boot 的 Java | [Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD](deploy_spring_boot_to_cloud_foundry/index.html). | +| Java 与 Maven | [How to deploy Maven projects to Artifactory with GitLab CI/CD](artifactory_and_gitlab/index.html). | +| PHP 与 PHPunit,Atoum | [Testing PHP projects](php.html). | +| PHP 与 NPM,SCP | [Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD](deployment/composer-npm-deploy.html). | +| PHP 与 Laravel,Envoy | [Test and deploy Laravel applications with GitLab CI/CD and Envoy](laravel_with_gitlab_and_envoy/index.html). | +| Heroku 上的 Python | [Test and deploy a Python application with GitLab CI/CD](test-and-deploy-python-application-to-heroku.html). | +| 红宝石在 Heroku 上 | [Test and deploy a Ruby application with GitLab CI/CD](test-and-deploy-ruby-application-to-heroku.html). | +| Heroku 上的 Scala | [Test and deploy a Scala application to Heroku](test-scala-application.html). | +| 并行测试 Ruby 和 JS | [GitLab CI/CD parallel jobs testing for Ruby & JavaScript projects](https://docs.knapsackpro.com/2019/how-to-run-parallel-jobs-for-rspec-tests-on-gitlab-ci-pipeline-and-speed-up-ruby-javascript-testing). | +| Vault 的秘密管理 | [Authenticating and Reading Secrets With Hashicorp Vault](authenticating-with-hashicorp-vault/index.html). | + +### Contributing examples[](#contributing-examples "Permalink") + +欢迎捐款! 您可以通过发送合并请求和该语言的指南来帮助您最喜欢的编程语言用户和 GitLab. + +## CI/CD templates[](#cicd-templates "Permalink") + +使用`.gitlab-ci.yml` [模板](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates)开始使用 GitLab CI / CD 和您喜欢的编程语言或框架. + +在用户界面中创建`gitlab-ci.yml`文件时,可以选择以下模板之一: + +* [Android (`Android.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Android.gitlab-ci.yml) +* [Android with fastlane (`Android-Fastlane.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml) +* [Bash (`Bash.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Bash.gitlab-ci.yml) +* [C++ (`C++.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/C++.gitlab-ci.yml) +* [Chef (`Chef.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Chef.gitlab-ci.yml) +* [Clojure (`Clojure.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml) +* [Composer `Composer.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Composer.gitlab-ci.yml) +* [Crystal (`Crystal.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml) +* [Django (`Django.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Django.gitlab-ci.yml) +* [Docker (`Docker.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Docker.gitlab-ci.yml) +* [dotNET (`dotNET.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml) +* [dotNET Core (`dotNET-Core.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/dotNET-Core.yml) +* [Elixir (`Elixir.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml) +* [goLang (`Go.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Go.gitlab-ci.yml) +* [Gradle (`Gradle.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Gradle.gitlab-ci.yml) +* [Grails (`Grails.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Grails.gitlab-ci.yml) +* [iOS with fastlane (`iOS-Fastlane.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml) +* [Julia (`Julia.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Julia.gitlab-ci.yml) +* [Laravel (`Laravel.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml) +* [LaTeX (`LaTeX.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/LaTeX.gitlab-ci.yml) +* [Maven (`Maven.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Maven.gitlab-ci.yml) +* [Mono (`Mono.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Mono.gitlab-ci.yml) +* [NPM (`npm.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/npm.gitlab-ci.yml) +* [Node.js (`Nodejs.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml) +* [OpenShift (`OpenShift.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/OpenShift.gitlab-ci.yml) +* [Packer (`Packer.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Packer.gitlab-ci.yml) +* [PHP (`PHP.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/PHP.gitlab-ci.yml) +* [Python (`Python.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Python.gitlab-ci.yml) +* [Ruby (`Ruby.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml) +* [Rust (`Rust.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Rust.gitlab-ci.yml) +* [Scala (`Scala.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Scala.gitlab-ci.yml) +* [Swift (`Swift.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Swift.gitlab-ci.yml) +* [Terraform (`Terraform.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml) + +如果编程语言或框架模板不在此列表中,则可以提供一种. 要创建模板,请向[https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates)提交合并请求. + +### Adding templates to your GitLab installation[](#adding-templates-to-your-gitlab-installation-premium-only "Permalink") + +您可以将自定义示例和模板添加到自我管理的 GitLab 实例. 您的 GitLab 管理员可以[指定一个实例模板存储库](../../user/admin_area/settings/instance_template_repository.html) ,其中包含特定于您组织的示例和模板. + +## Other resources[](#other-resources "Permalink") + +本节提供更多资源,以帮助您熟悉 GitLab CI / CD 的各种用法. 请注意,较早的文章和视频可能无法反映最新的 GitLab 版本的状态. + +### CI/CD in the cloud[](#cicd-in-the-cloud "Permalink") + +有关为基于云的环境设置 GitLab CI / CD 的示例,请参见: + +* [How to set up multi-account AWS SAM deployments with GitLab CI](https://about.gitlab.com/blog/2019/02/04/multi-account-aws-sam-deployments-with-gitlab-ci/) +* [Automating Kubernetes Deployments with GitLab CI/CD](https://www.youtube.com/watch?v=wEDRfAz6_Uw) +* [How to autoscale continuous deployment with GitLab Runner on DigitalOcean](https://about.gitlab.com/blog/2018/06/19/autoscale-continuous-deployment-gitlab-runner-digital-ocean/) +* [How to create a CI/CD pipeline with Auto Deploy to Kubernetes using GitLab and Helm](https://about.gitlab.com/blog/2017/09/21/how-to-create-ci-cd-pipeline-with-autodeploy-to-kubernetes-using-gitlab-and-helm/) +* [Demo - Deploying from GitLab to OpenShift Container Cluster](https://youtu.be/EwbhA53Jpp4) + +另请参阅以下视频概述: + +* [Kubernetes, GitLab, and Cloud Native](https://www.youtube.com/watch?v=d-9awBxEbvQ). +* [Deploying to IBM Cloud with GitLab CI/CD](https://www.youtube.com/watch?v=6ZF4vgKMd-g). + +### Customer stories[](#customer-stories "Permalink") + +有关使用 GitLab CI / CD 的一些客户体验,请参阅: + +* [How Verizon Connect reduced datacenter deploys from 30 days to under 8 hours with GitLab](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/) +* [How Wag! cut their release process from 40 minutes to just 6](https://about.gitlab.com/blog/2019/01/16/wag-labs-blog-post/) +* [How Jaguar Land Rover embraced CI to speed up their software lifecycle](https://about.gitlab.com/blog/2018/07/23/chris-hill-devops-enterprise-summit-talk/) + +### Getting started[](#getting-started "Permalink") + +有关帮助您入门的一些示例,请参阅: + +* [GitLab CI/CD’s 2018 highlights](https://about.gitlab.com/blog/2019/01/21/gitlab-ci-cd-features-improvements/) +* [A beginner’s guide to continuous integration](https://about.gitlab.com/blog/2018/01/22/a-beginners-guide-to-continuous-integration/) + +### Implementing GitLab CI/CD[](#implementing-gitlab-cicd "Permalink") + +有关其他已实施 GitLab CI / CD 的示例,请参见: + +* [How to streamline interactions between multiple repositories with multi-project pipelines](https://about.gitlab.com/blog/2018/10/31/use-multiproject-pipelines-with-gitlab-cicd/) +* [How we used GitLab CI to build GitLab faster](https://about.gitlab.com/blog/2018/05/02/using-gitlab-ci-to-build-gitlab-faster/) +* [Test all the things in GitLab CI with Docker by example](https://about.gitlab.com/blog/2018/02/05/test-all-the-things-gitlab-ci-docker-examples/) +* [A Craftsman looks at continuous integration](https://about.gitlab.com/blog/2018/01/17/craftsman-looks-at-continuous-integration/) +* [Go tools and GitLab: How to do continuous integration like a boss](https://about.gitlab.com/blog/2017/11/27/go-tools-and-gitlab-how-to-do-continuous-integration-like-a-boss/) +* [GitBot – automating boring Git operations with CI](https://about.gitlab.com/blog/2017/11/02/automating-boring-git-operations-gitlab-ci/) +* [How to use GitLab CI for Vue.js](https://about.gitlab.com/blog/2017/09/12/vuejs-app-gitlab/) +* Video: [GitLab CI/CD Deep Dive](https://youtu.be/pBe4t1CD8Fc?t=195) +* [Dockerizing GitLab Review Apps](https://about.gitlab.com/blog/2017/07/11/dockerizing-review-apps/) +* [Fast and natural continuous integration with GitLab CI](https://about.gitlab.com/blog/2017/05/22/fast-and-natural-continuous-integration-with-gitlab-ci/) +* [Demo: CI/CD with GitLab in action](https://about.gitlab.com/blog/2017/03/13/ci-cd-demo/) + +### Migrating to GitLab from third-party CI tools[](#migrating-to-gitlab-from-third-party-ci-tools "Permalink") + +* [Migrating from Jenkins to GitLab](https://youtu.be/RlEVGOpYF5Y) + +### Integrating GitLab CI/CD with other systems[](#integrating-gitlab-cicd-with-other-systems "Permalink") + +要查看如何将 GitLab CI / CD 与第三方系统集成,请参阅: + +* [Streamline and shorten error remediation with Sentry’s new GitLab integration](https://about.gitlab.com/blog/2019/01/25/sentry-integration-blog-post/) +* [How to simplify your smart home configuration with GitLab CI/CD](https://about.gitlab.com/blog/2018/08/02/using-the-gitlab-ci-slash-cd-for-smart-home-configuration-management/) +* [Demo: GitLab + Jira + Jenkins](https://about.gitlab.com/blog/2018/07/30/gitlab-workflow-with-jira-jenkins/) +* [Introducing Auto Breakfast from GitLab (sort of)](https://about.gitlab.com/blog/2018/06/29/introducing-auto-breakfast-from-gitlab/) + +### Mobile development[](#mobile-development "Permalink") + +有关使用 GitLab CI / CD 进行移动应用程序开发的帮助,请参阅: + +* [How to publish Android apps to the Google Play Store with GitLab and fastlane](https://about.gitlab.com/blog/2019/01/28/android-publishing-with-gitlab-and-fastlane/) +* [Setting up GitLab CI for Android projects](https://about.gitlab.com/blog/2018/10/24/setting-up-gitlab-ci-for-android-projects/) +* [Working with YAML in GitLab CI from the Android perspective](https://about.gitlab.com/blog/2017/11/20/working-with-yaml-gitlab-ci-android/) +* [How to use GitLab CI and MacStadium to build your macOS or iOS projects](https://about.gitlab.com/blog/2017/05/15/how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects/) +* [Setting up GitLab CI for iOS projects](https://about.gitlab.com/blog/2016/03/10/setting-up-gitlab-ci-for-ios-projects/) \ No newline at end of file diff --git a/_book/docs/227.md b/_book/docs/227.md new file mode 100644 index 0000000000000000000000000000000000000000..be771bafe32f9488d4e2b84c00e889484adab1a1 --- /dev/null +++ b/_book/docs/227.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/ci/examples/browser_performance.html](https://docs.gitlab.com/ee/ci/examples/browser_performance.html) \ No newline at end of file diff --git a/_book/docs/228.md b/_book/docs/228.md new file mode 100644 index 0000000000000000000000000000000000000000..04e39d536302e82065c76aac7aa475e606ab6618 --- /dev/null +++ b/_book/docs/228.md @@ -0,0 +1,43 @@ +# Test a Clojure application with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/test-clojure-application.html](https://docs.gitlab.com/ee/ci/examples/test-clojure-application.html) + +* [Configure the project](#configure-the-project) + +**注意:**本文档最近未更新,可能已过期. 有关最新文档,请参见[GitLab CI / CD](../README.html)页面和《 [GitLab CI / CD 管道配置参考》](../yaml/README.html) . + +# Test a Clojure application with GitLab CI/CD[](#test-a-clojure-application-with-gitlab-cicd "Permalink") + +本示例将指导您如何在 Clojure 应用程序上运行测试. + +您可以查看或派生[示例源,](https://gitlab.com/dzaporozhets/clojure-web-application)并查看其过去的[CI 作业](https://gitlab.com/dzaporozhets/clojure-web-application/builds?scope=finished)的日志. + +## Configure the project[](#configure-the-project "Permalink") + +这是此项目的`.gitlab-ci.yml`文件的外观: + +``` +variables: + POSTGRES_DB: sample-test + DATABASE_URL: "postgresql://postgres@postgres:5432/sample-test" + +before_script: + - apt-get update -y + - apt-get install default-jre postgresql-client -y + - wget https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein + - chmod a+x lein + - export LEIN_ROOT=1 + - PATH=$PATH:. + - lein deps + - lein migratus migrate + +test: + script: + - lein test +``` + +在`before_script` ,我们安装了 JRE 和[Leiningen](https://leiningen.org/) . + +该示例项目使用[migratus](https://github.com/yogthos/migratus)库管理数据库迁移,并且在`before_script`的最后一步中添加了数据库迁移. + +您可以使用`gitlab.com`可用的公共`gitlab.com`程序来使用此配置测试您的应用程序. \ No newline at end of file diff --git a/_book/docs/229.md b/_book/docs/229.md new file mode 100644 index 0000000000000000000000000000000000000000..10f1daf2ab444e3ab4237981c2525a6d91016d17 --- /dev/null +++ b/_book/docs/229.md @@ -0,0 +1,115 @@ +# Using Dpl as deployment tool + +> 原文:[https://docs.gitlab.com/ee/ci/examples/deployment/README.html](https://docs.gitlab.com/ee/ci/examples/deployment/README.html) + +* [Requirements](#requirements) +* [Basic usage](#basic-usage) +* [Using Dpl with Docker](#using-dpl-with-docker) +* [Usage in staging and production](#usage-in-staging-and-production) +* [Storing API keys](#storing-api-keys) + +# Using Dpl as deployment tool[](#using-dpl-as-deployment-tool "Permalink") + +[Dpl](https://github.com/travis-ci/dpl) (发音为 DPL)是由 Travis CI 开发和使用的,用于连续部署的部署工具,但也可以与 GitLab CI / CD 一起使用. + +Dpl 可用于部署到任何[受支持的提供程序](https://github.com/travis-ci/dpl#supported-providers) . + +## Requirements[](#requirements "Permalink") + +要使用 Dpl,您至少需要具备安装 gem 的 Ruby 1.9.3. + +## Basic usage[](#basic-usage "Permalink") + +可以将 Dpl 安装在具有以下条件的任何计算机上: + +``` +gem install dpl +``` + +这使您可以从本地终端测试所有命令,而不必在 CI 服务器上进行测试. + +如果您没有安装 Ruby,则可以在兼容 Debian 的 Linux 上执行以下操作: + +``` +apt-get update +apt-get install ruby-dev +``` + +Dpl 为大量服务提供支持,包括:Heroku,Cloud Foundry,AWS / S3 等. 要使用它,只需定义提供者和提供者所需的任何其他参数. + +例如,如果要使用它将应用程序部署到 Heroku,则需要将`heroku`指定为提供者,并指定`api-key`和`app` . 所有可能的参数都可以在这里找到: [https](https://github.com/travis-ci/dpl#heroku-api) : [//github.com/travis-ci/dpl#heroku-api](https://github.com/travis-ci/dpl#heroku-api) . + +``` +staging: + stage: deploy + script: + - gem install dpl + - dpl --provider=heroku --app=my-app-staging --api-key=$HEROKU_STAGING_API_KEY +``` + +在上面的示例中,我们使用 Dpl 通过存储在`HEROKU_STAGING_API_KEY`安全变量中的 API 密钥将`my-app-staging`部署到 Heroku 服务器. + +要使用其他提供程序,请查看一整列[受支持的提供程序](https://github.com/travis-ci/dpl#supported-providers) . + +## Using Dpl with Docker[](#using-dpl-with-docker "Permalink") + +在大多数情况下,您将配置[GitLab Runner](https://docs.gitlab.com/runner/)以使用服务器的 Shell 命令. 这意味着所有命令都在本地用户的上下文中运行(例如`gitlab_runner`或`gitlab_ci_multi_runner` ). 这也意味着最有可能在 Docker 容器中没有安装 Ruby 运行时. 您将必须安装它: + +``` +staging: + stage: deploy + script: + - apt-get update -yq + - apt-get install -y ruby-dev + - gem install dpl + - dpl --provider=heroku --app=my-app-staging --api-key=$HEROKU_STAGING_API_KEY + only: + - master +``` + +第一行`apt-get update -yq`更新可用软件包的列表,第二行`apt-get install -y ruby-dev`在系统上安装 Ruby 运行时. 上面的示例对所有与 Debian 兼容的系统均有效. + +## Usage in staging and production[](#usage-in-staging-and-production "Permalink") + +在开发工作流程中具有暂存(开发)和生产环境是很常见的 + +让我们考虑以下示例:我们希望将`master`分支部署到`staging`并将所有标签部署到`production`环境. 该设置的最终`.gitlab-ci.yml`如下所示: + +``` +staging: + stage: deploy + script: + - gem install dpl + - dpl --provider=heroku --app=my-app-staging --api-key=$HEROKU_STAGING_API_KEY + only: + - master + +production: + stage: deploy + script: + - gem install dpl + - dpl --provider=heroku --app=my-app-production --api-key=$HEROKU_PRODUCTION_API_KEY + only: + - tags +``` + +我们创建了两个在不同事件上执行的部署作业: + +1. `staging` is executed for all commits that were pushed to `master` branch, +2. 对所有推送的标签执行`production` . + +我们还使用两个安全变量: + +1. `HEROKU_STAGING_API_KEY` -Heroku API 密钥,用于部署登台应用程序, +2. `HEROKU_PRODUCTION_API_KEY` -Heroku API 密钥,用于部署生产应用程序. + +## Storing API keys[](#storing-api-keys "Permalink") + +可以通过在项目的**设置➔CI / CD➔变量中**添加安全**变量** . 项目设置中定义的变量与构建脚本一起发送到 Runner. 安全变量存储在存储库之外. 切勿将机密存储在项目的`.gitlab-ci.yml` . 将秘密的值隐藏在作业日志中也很重要. + +您可以通过使用`$` (在非 Windows 运行程序上)或`%` (对于 Windows 批处理运行程序)前缀名称来访问添加的变量: + +1. `$VARIABLE`用于非 Windows 运行器 +2. `%VARIABLE%` -用于 Windows 批处理运行器 + +阅读有关[CI 变量的](../../variables/README.html)更多信息. \ No newline at end of file diff --git a/_book/docs/230.md b/_book/docs/230.md new file mode 100644 index 0000000000000000000000000000000000000000..c89200a474a67cf33dc10914c14199309fde131a --- /dev/null +++ b/_book/docs/230.md @@ -0,0 +1,326 @@ +# Testing a Phoenix application with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/test_phoenix_app_with_gitlab_ci_cd/](https://docs.gitlab.com/ee/ci/examples/test_phoenix_app_with_gitlab_ci_cd/) + +* [Introduction](#introduction) + * [What is Phoenix?](#what-is-phoenix) + * [What is Elixir?](#what-is-elixir) +* [Requirements](#requirements) + * [Create a new Phoenix project](#create-a-new-phoenix-project) + * [Initialize the PostgreSQL database](#initialize-the-postgresql-database) + * [Start Phoenix server](#start-phoenix-server) +* [Introducing GitLab CI/CD](#introducing-gitlab-cicd) +* [Adjusting Phoenix configuration](#adjusting-phoenix-configuration) +* [Testing](#testing) +* [Configuring CI/CD Pipeline](#configuring-cicd-pipeline) +* [Watching the build](#watching-the-build) +* [Conclusion](#conclusion) +* [References](#references) + +# Testing a Phoenix application with GitLab CI/CD[](#testing-a-phoenix-application-with-gitlab-cicd "Permalink") + +[Phoenix](https://www.phoenixframework.org/)是用[Elixir](https://s0elixir-lang0org.icopy.site)编写的 Web 开发框架, [Elixir](https://s0elixir-lang0org.icopy.site)是在[Erlang VM](https://www.erlang.org)上运行的旨在提高生产力和可维护性的功能性语言. Erlang VM 确实非常快,并且可以处理大量同时用户. + +这就是为什么我们今天听到太多有关 Phoenix 的原因. + +在本教程中,我们将教您如何设置[GitLab CI / CD](../../README.html)来构建和测试 Phoenix 应用程序. + +本教程假定您知道如何创建 Phoenix 应用程序,在本地运行测试以及如何使用 Git 和 GitLab UI. + +## Introduction[](#introduction "Permalink") + +### What is Phoenix?[](#what-is-phoenix "Permalink") + +[Phoenix](https://www.phoenixframework.org/) is a web development framework written in [Elixir](https://s0elixir-lang0org.icopy.site). It’s useful for building fast, reliable, and high-performance applications, as it uses [Erlang VM](https://www.erlang.org). + +许多组件和概念类似于 Ruby on Rails 或 Python 的 Django. 高开发人员生产率和高应用程序性能只是学习如何使用它的几个优点. 使用 MVC 模式,它被设计为模块化和灵活的. 易于维护不断增长的应用程序是一个加号. + +Phoenix 可以在任何支持 Erlang 的操作系统上运行: + +* Ubuntu +* CentOS +* Mac OS X +* Debian +* Windows +* Fedora +* Raspberry Pi 操作系统 + +查看[Phoenix 学习指南](https://s0hexdocs0pm.icopy.site/phoenix/overview.html)以获取更多信息. + +### What is Elixir?[](#what-is-elixir "Permalink") + +[Elixir](https://s0elixir-lang0org.icopy.site)是一种动态的,功能性的语言,旨在轻松地使用当今所有成熟的 Erlang(已有 30 年的历史!). 它与 Ruby 有相似之处,特别是在语法上,因此 Ruby 开发人员对 Elixir 的快速增长感到非常兴奋. 一个全栈的 Ruby 开发人员可以在短短几周内学会如何使用 Elixir 和 Phoenix. + +在药剂我们有一个叫做命令`mix` ,这是一个帮助创建项目,测试,运行迁移和[更多](https://s0elixir-lang0org.icopy.site/getting-started/mix-otp/introduction-to-mix) . 我们将在本教程的后面部分中使用它. + +查看[Elixir 文档](https://s0elixir-lang0org.icopy.site/getting-started/introduction)以获取更多信息. + +## Requirements[](#requirements "Permalink") + +要遵循本教程,您需要先安装: + +* Elixir [installation instructions](https://s0elixir-lang0org.icopy.site/install) +* Phoenix Framework [安装说明](https://s0hexdocs0pm.icopy.site/phoenix/installation.html) +* PostgreSQL(如果需要使用 MySQL 服务器,请查看[Phoenix 说明](https://s0hexdocs0pm.icopy.site/phoenix/ecto.html) ) + +### Create a new Phoenix project[](#create-a-new-phoenix-project "Permalink") + +打开终端,然后转到要创建项目的目录. 您无需为项目的文件创建一个空目录,因为`mix`命令将为我们完成此操作. + +当我们调用`mix`命令时,我们将传递两个参数: + +* 我们希望它运行的任务: `phoenix.new` +* 参数`phoenix.new`需要,这是新项目的名称. 在这种情况下,我们称其为`hello_gitlab_ci` ,但您可以自由设置自己的名称: + +``` +mix phoenix.new hello_gitlab_ci +``` + +当询问时,请回答`Y`以获取并安装依赖项. + +如果一切顺利,您将获得如下输出: + +[![mix phoenix.new](img/28300ad671ab6b5aec8525cb2a7af157.png)](img/mix-phoenix-new.png) + +现在,我们的项目位于目录中,该目录与传递给`mix`命令的名称相同,例如`~/GitLab/hello_gitlab_ci` . 如果查看目录,我们将看到 Phoenix 文件和运行所需的依赖项. + +### Initialize the PostgreSQL database[](#initialize-the-postgresql-database "Permalink") + +By default, Phoenix requires a PostgreSQL database to store whatever we need to store in our app. In this case, we’ll only create an empty database. + +首先,我们需要导航到我们最近创建的项目的目录,然后再次执行`mix` . 这次, `mix`将收到参数`ecto.create` ,这是创建新数据库的任务. [Ecto](https://s0hexdocs0pm.icopy.site/ecto/Ecto.html)是 Elixir 的数据库包装器. + +创建项目后第一次运行`mix`时,它将把我们的文件编译为字节码,然后由 Erlang VM 解释. 在接下来的时间里,它只会编译我们的更改. + +运行以下命令以创建我们的空数据库: + +``` +cd hello_gitlab_ci +mix ecto.create +``` + +我们希望在命令末尾看到以下输出: + +``` +Generated hello_gitlab_ci app +The database for HelloGitlabCi.Repo has been created +``` + +> **注意:** Phoenix 假设我们的 PostgreSQL 数据库将具有一个具有正确权限的`postgres`用户帐户和一个`postgres`密码. 如果不是您的情况,请查看[Ecto 的说明](https://s0hexdocs0pm.icopy.site/ecto/Ecto.html) . + +### Start Phoenix server[](#start-phoenix-server "Permalink") + +现在,该看看我们到目前为止所做的一切是否进展顺利. 我们将再次使用`phoenix.server`参数调用`mix` ,它将启动 Phoenix 的 HTTP Server. + +``` +mix phoenix.server +``` + +这将是此命令的输出: + +``` +[info] Running HelloGitlabCi.Endpoint with Cowboy using http://localhost:4000 +23 May 11:44:35 - info: compiling +23 May 11:44:37 - info: compiled 6 files into 2 files, copied 3 in 9.8 sec +``` + +现在,我们的应用程序在本地运行. 我们可以直接在浏览器中预览它. 让我们打开[`localhost:4000`](http://localhost:4000)来查看我们的 Phoenix Framework 欢迎页面. 如果链接不起作用,请改为打开[`127.0.0.1:4000`](http://127.0.0.1:4000) ,然后[`127.0.0.1:4000`](http://127.0.0.1:4000)操作系统配置为将`localhost`指向`127.0.0.1` . + +[![mix phoenix.server](img/13c910771ce7fad76e82ba7b8bdd440b.png)](img/mix-phoenix-server.png) + +太好了,现在我们有一个本地 Phoenix Server 运行我们的应用程序. + +在本地,我们的应用程序在[`iex`](https://s0elixir-lang0org.icopy.site/getting-started/introduction.html)会话中运行,该会话代表 Interactive Elixir. 在这种交互模式下,我们可以键入任何 Elixir 表达式并获取其结果. 要退出`iex` ,我们需要按两次`Ctrl+C` 因此,当我们需要停止 Phoenix 服务器时,我们必须`Ctrl+C`两次`Ctrl+C` + +## Introducing GitLab CI/CD[](#introducing-gitlab-cicd "Permalink") + +借助 GitLab,我们可以在一个平台上管理开发工作流程,提高生产力,跟踪问题,执行代码审查等. 使用 GitLab CI / CD,我们可以提高工作效率,因为每次我们或我们的同事发布任何代码时,GitLab CI / CD 都会构建并测试更改,并实时告诉我们是否有任何问题. + +当然,当我们的应用程序开始增长时,我们将需要更多的开发人员在同一个项目上工作,并且这种构建和测试过程很容易在没有适当管理的情况下变得一团糟. 这也是为什么 GitLab CI / CD 对我们的应用如此重要的原因. 每当有人将其代码推送到 GitLab 时,我们都会很快知道他们的更改是否破坏了某些内容. 我们不需要停止所做的一切工作,就可以手动进行测试,而无需在团队中进行任何更改. + +让我们在实践中看一下. + +## Adjusting Phoenix configuration[](#adjusting-phoenix-configuration "Permalink") + +现在,我们需要在配置 GitLab CI / CD 之前调整 Phoenix 配置. Phoenix 项目中有一个目录( `config` ),其中包含可以运行的每个环境的配置文件. 由于我们将在单个环境中工作,因此我们将仅编辑测试配置文件( `test.exs` ). + +但是,为什么我们需要调整配置? 好吧,GitLab CI / CD 使用 Docker 技术在一个称为[Runner 的](../../runners/README.html)隔离虚拟机中构建和测试我们的代码. 在此 Runner 中,GitLab CI / CD 可以访问 Phoenix 应用程序需要运行的所有内容,就像在`localhost` ,但是我们必须告诉 GitLab CI / CD 使用系统变量在哪里创建和找到该数据库. 这样,GitLab CI / CD 将在 Runner 内部创建测试数据库,就像在`localhost`运行 Phoenix 时一样. + +* 在您喜欢的代码编辑器上打开`hello_gitlab_ci/config/test.exs` +* 转到" **配置数据库**会话"并编辑该块以包含`System.get_env` : + + ``` + # Configure your database + config :hello_gitlab_ci, HelloGitlabCi.Repo, + adapter: Ecto.Adapters.Postgres, + username: System.get_env("POSTGRES_USER") || "postgres", + password: System.get_env("POSTGRES_PASSWORD") || "postgres", + database: System.get_env("POSTGRES_DB") || "hello_gitlab_ci_test", + hostname: System.get_env("POSTGRES_HOST") || "localhost", + pool: Ecto.Adapters.SQL.Sandbox + ``` + + 稍后我们将需要这些系统变量. + +* 在`hello_gitlab_ci/priv/repo/migrations`创建一个名为`.gitkeep`的空文件 + + 由于我们的项目仍然很新鲜,因此我们的数据库上没有任何数据,因此`migrations`目录将为空. 如果没有`.gitkeep` ,Git 将不会上传该空目录,并且在 GitLab 上运行测试时会出现错误. + + > **注意:**如果我们通过 GitLab UI 添加文件夹,则 GitLab 本身会将`.gitkeep`添加到该新目录中. + +现在,让我们运行一个本地测试,看看我们所做的一切是否都没有破坏任何东西. + +## Testing[](#testing "Permalink") + +之前,当我们创建项目时,我们运行了`mix phoenix.new` . 该任务创建了 Phoenix 应用程序所需的所有内容,包括一些进入`hello_gitlab_ci/test`目录的单元测试. + +让我们运行带有`mix`的新任务来为我们运行这些测试. 这次,预期的参数是`test` . 我们可以添加`--trace`参数以进行调试. + +在您的终端中,导航到目录`hello_gitlab_ci`并运行: + +``` +mix test +``` + +我们的预期结果是: + +``` +.... + +Finished in 0.7 seconds +4 tests, 0 failures + +Randomized with seed 610000 +``` + +我们的测试成功了. 是时候将我们的文件推送到 GitLab 了. + +## Configuring CI/CD Pipeline[](#configuring-cicd-pipeline "Permalink") + +第一步是在我们项目的`hello_gitlab_ci`目录中创建一个名为`.gitlab-ci.yml`的新文件. + +* 最简单的方法是单击项目主页上的" **设置 CI / CD** ": + + [![Set up CI](img/8a05f3552d23f56607411f613a5ceb05.png)](img/set_up_ci_v12_6.png) + +* 在下一个屏幕上,我们可以使用已包含 Elixir 测试的模板. 单击" **应用模板",**然后选择**Elixir** : + + [![Select template](img/b96e754d4dd8ba06065aac231327e160.png)](img/select_template_v12_6.png) + + 该模板文件告诉 GitLab CI / CD 每次新的提交时我们希望做什么. 但是,我们必须对其稍作调整才能运行 Phoenix 应用程序. + +* The first line tells GitLab what Docker image will be used. + + 还记得我们了解 Runners 时,GitLab CI / CD 在其中构建和测试我们的应用程序的隔离虚拟机吗? 该虚拟机必须具有所有依赖关系才能运行我们的应用程序. 这是需要 Docker 映像的地方. 正确的图像将为我们提供整个系统. + + 当我们专注于测试(而不是部署)时,可以使用[elixir:latest](https://hub.docker.com/_/elixir) Docker 映像,该映像已经具有用于运行 Phoenix 测试的依赖项,例如 Elixir 和 Erlang: + + ``` + image: elixir:latest + ``` + +* 我们将仅使用`postgres` ,因此我们可以从`services`部分删除`mysql`和`redis`行: + + ``` + services: + - postgres:latest + ``` + +* 现在,我们将在`before_script`部分之前创建一个名为`variables`的新部分: + + ``` + variables: + POSTGRES_DB: hello_gitlab_ci_test + POSTGRES_HOST: postgres + POSTGRES_USER: postgres + POSTGRES_PASSWORD: "postgres" + MIX_ENV: "test" + ``` + + 上面,我们设置了 GitLab CI / CD 的值以验证到 PostgreSQL,就像我们之前在`config/test.exs`那样. `postgres`服务使用`POSTGRES_USER`和`POSTGRES_PASSWORD`值来创建具有这些凭据的用户. + +* 在`before_script`部分中,我们将添加一些命令来为测试做准备: + + ``` + before_script: + - mix local.rebar --force + - mix local.hex --force + - mix deps.get --only test + - mix ecto.create + - mix ecto.migrate + ``` + + 这样可以确保在尝试获取运行测试所需的依赖项之前,都同时安装了[rebar3](https://www.rebar3.org)和[hex](https://s0hex0pm.icopy.site) . 接下来,使用`ecto`创建并迁移`postgres` db,以确保它是最新的. + +* 最后,我们将`mix`部分保持不变. + +让我们看一下更改后的更新文件: + +``` +image: elixir:latest + +services: + - postgres:latest + +variables: + POSTGRES_DB: hello_gitlab_ci_test + POSTGRES_HOST: postgres + POSTGRES_USER: postgres + POSTGRES_PASSWORD: "postgres" + MIX_ENV: "test" + +before_script: + - mix local.rebar --force + - mix local.hex --force + - mix deps.get --only test + - mix ecto.create + - mix ecto.migrate + +mix: + script: + - mix test +``` + +为了安全起见,在将此文件提交到 GitLab 之前,我们可以检查是否有语法错误. 复制`.gitlab-ci.yml`的内容并将其粘贴到[GitLab CI / CD Lint 工具上](https://gitlab.com/ci/lint) . 请注意,此链接仅对登录用户有效. + +## Watching the build[](#watching-the-build "Permalink") + +我不了解您,但是我喜欢看黑屏上充满了编译输出. 这样,我可以感觉到我所做的正确工作带来的快乐. 在`localhost` ,很容易观看我们的构建,但是在 GitLab 上,这可能吗? 是! + +让我们去**管道** ,看看 GitLab 做这项工作. 只需单击**管道**以查找实际正在运行的构建作业. + +[![Pipelines](img/d7b0c4003d725d7125fdfb9c24aae17e.png)](img/pipelines.png) + +单击内部版本的 ID 观看整个过程. 如果一切都按预期进行,我们可以等待**构建成功**完成! :) + +``` +$ mix test +.... + +Finished in 0.3 seconds +4 tests, 0 failures + +Randomized with seed 206909 +Build succeeded +``` + +如果我们在 GitLab UI 上查看项目的主页,我们可以看到 GitLab CI / CD 进行的最后构建的状态. + +是时候向世界展示我们的绿色建筑徽章! 导航到项目的**"设置">" CI / CD",**然后展开" **常规管道设置"** . 向下滚动到**管道状态,**并复制您的徽章的降价代码. 将其粘贴到`README.md`文件的顶部,以使项目外的人员可以看到我们的最新代码是否正在正确运行. + +完成此版本后,GitLab 将启动另一个构建并显示一个**运行**徽标. 可以预期的是,毕竟我们只是配置了 GitLab CI / CD 来完成每次推送! 但是您可能会想"为什么要针对诸如 README.md 之类的简单操作运行构建和测试?" 这是一个很好的问题. 对于不影响您的应用程序的更改,您可以添加关键字[`[ci skip]`](../../yaml/README.html#skip-pipeline)来提交消息,并且与该提交相关的内部版本将被跳过. + +最后,我们终于获得了绿色环保的成功徽章! 通过将结果输出到 README 文件中,它可以向登录项目页面的任何人显示您的代码是最新的并且可以正常工作. + +## Conclusion[](#conclusion "Permalink") + +当我们的应用程序不断增长且有许多开发人员在处理该应用程序时,或者当社区正在监视和贡献一个开源项目时,使我们的代码永久运行非常重要. GitLab CI / CD 是节省时间的强大工具,可帮助我们维护代码的组织和工作. + +正如我们在这篇文章中所看到的,GitLab CI / CD 确实很容易配置和使用. 我们还有[许多其他理由](https://about.gitlab.com/blog/2015/02/03/7-reasons-why-you-should-be-using-ci/)继续使用 GitLab CI / CD. 给我们团队带来的好处是巨大的! + +## References[](#references "Permalink") + +* [GitLab CI/CD introductory guide](https://about.gitlab.com/blog/2015/12/14/getting-started-with-gitlab-and-gitlab-ci/) +* [GitLab CI/CD full Documentation](../../README.html) +* [GitLab Runners documentation](../../runners/README.html) +* [Using Docker images documentation](../../docker/using_docker_images.html) \ No newline at end of file diff --git a/_book/docs/231.md b/_book/docs/231.md new file mode 100644 index 0000000000000000000000000000000000000000..6787ab5b2f762f708fed5dcbc04e148eb9062e34 --- /dev/null +++ b/_book/docs/231.md @@ -0,0 +1,168 @@ +# End-to-end testing with GitLab CI/CD and WebdriverIO + +> 原文:[https://docs.gitlab.com/ee/ci/examples/end_to_end_testing_webdriverio/](https://docs.gitlab.com/ee/ci/examples/end_to_end_testing_webdriverio/) + +* [What to test](#what-to-test) +* [Selenium and WebdriverIO](#selenium-and-webdriverio) +* [Writing tests](#writing-tests) +* [Running locally](#running-locally) +* [Configuring GitLab CI/CD](#configuring-gitlab-cicd) +* [What’s next](#whats-next) + +# End-to-end testing with GitLab CI/CD and WebdriverIO[](#end-to-end-testing-with-gitlab-cicd-and-webdriverio "Permalink") + +[Review App](../../review_apps/index.html)很棒:对于每个合并请求(或分支),都可以将新代码复制并部署到新的类似于生产的实时环境中,从而非常省力地评估更改的影响. 因此,当我们使用像[Dependencies.io](https://www.dependencies.io/)这样的依赖项管理器时,它可以提交具有更新的依赖项的合并请求,并且很明显,仍然可以正确地构建和部署应用程序. 毕竟,您可以*看到*它正在运行! + +![dependencies.io](img/423fb353db83bd90502f2f029c398e43.png) + +但是,查看新部署的代码以检查其外观和行为是否仍符合预期是重复的手动工作,这意味着它是自动化的主要候选对象. 这就是自动[端到端测试的目的](https://martinfowler.com/bliki/BroadStackTest.html) :让计算机在几种简单的场景下运行,这些场景要求您的应用程序的所有层(从前[端到数据库)](https://martinfowler.com/bliki/BroadStackTest.html)都具有适当的功能. + +在本文中,我们将讨论如何编写这样的端到端测试,以及如何设置 GitLab CI / CD 以逐分支的基础针对新代码自动运行这些测试. 在本文的范围内,我们将引导您完成设置 GitLab CI / CD 的过程,以使用 WebdriverIO 端对端测试基于 JavaScript 的应用程序,但是一般策略应延续到其他语言. 我们假设您熟悉 GitLab, [GitLab CI / CD](../../README.html) , [Review Apps](../../review_apps/index.html) ,并在本地运行您的应用程序,例如,在`localhost:8000` . + +## What to test[](#what-to-test "Permalink") + +在广泛使用的[测试金字塔策略中](https://martinfowler.com/bliki/TestPyramid.html) ,端到端测试的行为更像是一种保护措施: [大多数代码应包含在单元测试中](https://vincenttunru.com/100-percent-coverage/) ,以使您可以轻松地确定问题的根源. 相反,您可能希望将[端到端测试的数量限制](https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html)为刚好足以使您确信部署按预期进行,基础结构已启动并正在运行以及代码单元可以很好地协同工作. + +## Selenium and WebdriverIO[](#selenium-and-webdriverio "Permalink") + +[Selenium](https://s0www0selenium0dev.icopy.site/)是一款可以控制 Web 浏览器的软件,例如,使它们能够访问特定的 URL 或与页面上的元素进行交互. 它可以通过多种编程语言进行编程控制. 在本文中,我们将使用[WebdriverIO](https://webdriver.io/) JavaScript 绑定,但是一般概念应该可以很好地延续到[Selenium 支持的其他编程语言中](https://s0www0selenium0dev.icopy.site/documentation/en/legacy_docs/selenium_rc/) . + +## Writing tests[](#writing-tests "Permalink") + +您可以使用[WebdriverIO 支持的多个测试框架](https://webdriver.io/guide/testrunner/frameworks.html)编写测试. 我们将在这里使用[茉莉花](https://jasmine.github.io/) : + +``` +describe('A visitor without account', function(){ + it('should be able to navigate to the homepage from the 404 page', function(){ + browser.url('/page-that-does-not-exist'); + + expect(browser.getUrl()).toMatch('page-that-does-not-exist'); + + browser.element('.content a[href="/"]').click(); + + expect(browser.getUrl()).not.toMatch('page-that-does-not-exist'); + }); +}); +``` + +WebdriverIO 提供了`describe` , `it`和`browser`的功能. 让我们一一分解. + +函数`describe`允许您对相关测试进行分组. 例如,如果您想对多个测试运行相同的初始化命令(使用[`beforeEach`](https://jasmine.github.io/api/2.9/global.html#beforeEach) ),例如确保您已登录,则这将很有用. + +`it`定义了单个测试的功能. + +[`browser`对象](https://webdriver.io/guide/testrunner/browserobject.html)是 WebdriverIO 的特长. 它提供了大多数[WebdriverIO API 方法](https://webdriver.io/api.html) ,这些[方法](https://webdriver.io/api.html)是引导浏览器的关键. 在这种情况下,我们可以使用[`browser.url`](https://webdriver.io/api/protocol/url.html)来访问`/page-that-does-not-exist`以访问 404 页面. 然后,我们可以使用[`browser.getUrl`](https://webdriver.io/api/property/getUrl.html)验证当前页面确实在我们指定的位置. 要与页面进行交互,我们只需将 CSS 选择器传递给[`browser.element`](https://webdriver.io/api/protocol/element.html)即可访问页面上的元素并与其进行交互-例如,单击返回首页的链接. + +上面显示的简单测试如果通过则可以给我们很大的信心:我们知道我们的部署成功了,这些元素在页面上可见,并且实际的浏览器可以与它交互,并且路由按预期工作. 所有这些仅用免费的空格就可以在 10 行中完成! 加上后续的单元测试和成功完成的管道,您可以完全确信,依赖项升级不会破坏任何内容,甚至无需查看您的网站. + +## Running locally[](#running-locally "Permalink") + +稍后我们将在 CI / CD 中运行上述测试. 但是,在编写测试时,如果您不必等待管道成功以检查它们是否按照您期望的方式工作,那么它会有所帮助. 换句话说,让它在本地运行. + +确保您的应用程序在本地运行. 如果使用 Webpack,则可以使用[Webpack Dev Server WebdriverIO 插件](https://s0www0npmjs0com.icopy.site/package/wdio-webpack-dev-server-service)在执行测试之前自动启动开发服务器. + +The WebdriverIO documentation has [an overview of all configuration options](https://webdriver.io/guide/getstarted/configuration.html), but the easiest way to get started is to start with [WebdriverIO’s default configuration](https://webdriver.io/guide/testrunner/configurationfile.html), which provides an overview of all available options. The two options that are going to be most relevant now are the `specs` option, which is an array of paths to your tests, and the `baseUrl` option, which points to where your app is running. And finally, we will need to tell WebdriverIO in which browsers we would like to run our tests. This can be configured through the `capabilities` option, which is an array of browser names (e.g. `firefox` or `chrome`). It is recommended to install [selenium-assistant](https://googlechromelabs.github.io/selenium-assistant/) to detect all installed browsers: + +``` + const seleniumAssistant = require('selenium-assistant'); + const browsers = seleniumAssistant.getLocalBrowsers(); + config.capabilities = browsers.map(browser => ({ browserName: browser.getId() })); +``` + +但是,当然,简单的配置`config.capabilities = ['firefox']`也可以. + +如果已将 WebdriverIO 安装为依赖项( `npm install --save-dev webdriverio` ),则可以在`package.json`中的`scripts`属性中添加一行,该行运行`wdio`并将配置文件的路径作为值,例如: + +``` + "confidence-check": "wdio wdio.conf.js", +``` + +然后,您可以使用`npm run confidence-check`执行测试,之后您实际上会看到一个新的浏览器窗口,与您指定的应用交互. + +## Configuring GitLab CI/CD[](#configuring-gitlab-cicd "Permalink") + +这使我们进入了令人兴奋的部分:我们如何在 GitLab CI / CD 中运行它? 为此,我们需要做两件事: + +1. 设置实际上具有浏览器的[CI / CD 作业](../../yaml/README.html#introduction) . +2. 更新我们的 WebdriverIO 配置以使用那些浏览器来访问评论应用程序. + +对于本文的范围,我们定义了一个附加的[CI / CD 阶段](../../yaml/README.html#stages) `confidence-check` ,该`confidence-check` *在*部署审阅应用程序的阶段*之后*执行. 它使用`node:latest` [Docker image](../../docker/using_docker_images.html) . 但是,WebdriverIO 会启动实际的浏览器来与您的应用程序进行交互,因此我们需要安装并运行它们. 此外,WebdriverIO 使用 Selenium 作为控制不同浏览器的通用接口,因此我们也需要安装和运行 Selenium. 幸运的是,Selenium 项目提供了分别为 Firefox 和 Chrome 提供的 Docker 映像[standalone-firefox](https://hub.docker.com/r/selenium/standalone-firefox/)和[standalone-chrome](https://hub.docker.com/r/selenium/standalone-chrome/) . (由于 Safari 和 Internet Explorer / Edge 不是开源的,并且不适用于 Linux,因此很遗憾,我们无法在 GitLab CI / CD 中使用它们.) + +GitLab CI / CD 使用`service`属性将这些图像链接到我们的`confidence-check`作业变得轻而易举,这使得 Selenium 服务器可以在基于图像名称的主机名下使用. 我们的工作配置如下所示: + +``` +e2e:firefox: + stage: confidence-check + services: + - selenium/standalone-firefox + script: + - npm run confidence-check --host=selenium__standalone-firefox +``` + +对于 Chrome 同样如此: + +``` +e2e:chrome: + stage: confidence-check + services: + - selenium/standalone-chrome + script: + - npm run confidence-check --host=selenium__standalone-chrome +``` + +现在我们有一项工作可以运行端到端测试,我们需要告诉 WebdriverIO 如何连接到与其并排运行的 Selenium 服务器. 通过将[`host`](https://webdriver.io/guide/getstarted/configuration.html#host)选项的值作为参数传递给`npm run confidence-check`命令在命令行上`npm run confidence-check` ,我们已经作弊了. 但是,我们仍然需要告诉 WebdriverIO 使用哪个浏览器. + +[GitLab CI / CD 提供了许多](../../variables/README.html#predefined-environment-variables)有关当前 CI 作业的信息[的变量](../../variables/README.html#predefined-environment-variables) . 我们可以使用此信息根据正在运行的作业动态设置 WebdriverIO 配置. 更具体地说,我们可以根据当前正在运行的作业的名称,告诉 WebdriverIO 使用哪个浏览器执行测试. 我们可以在 WebdriverIO 的配置文件中执行此操作,在上面将其命名为`wdio.conf.js` : + +``` +if(process.env.CI_JOB_NAME) { + dynamicConfig.capabilities = [ + { browserName: process.env.CI_JOB_NAME === 'e2e:chrome' ? 'chrome' : 'firefox' }, + ]; +} +``` + +同样,我们可以告诉 WebdriverIO 审阅应用程序在哪里运行-在本示例中,它位于`<branch name>.flockademic.com` : + +``` +if(process.env.CI_COMMIT_REF_SLUG) { + dynamicConfig.baseUrl = `https://${process.env.CI_COMMIT_REF_SLUG}.flockademic.com`; +} +``` + +并且我们可以确保仅当*不*使用`if (!process.env.CI)`在 CI 中运行时,才使用本地特定的配置. 基本上,这是在 GitLab CI / CD 上进行端到端测试所需的全部成分! + +回顾一下,我们的`.gitlab-ci.yml`配置文件如下所示: + +``` +image: node:8.10 +stages: + - deploy + - confidence-check +deploy_terraform: + stage: deploy + script: + # Your Review App deployment scripts - for a working example please check https://gitlab.com/Flockademic/Flockademic/blob/5a45f1c2412e93810fab50e2dab8949e2d0633c7/.gitlab-ci.yml#L315 +e2e:firefox: + stage: confidence-check + services: + - selenium/standalone-firefox + script: + - npm run confidence-check --host=selenium__standalone-firefox +e2e:chrome: + stage: confidence-check + services: + - selenium/standalone-chrome + script: + - npm run confidence-check --host=selenium__standalone-chrome +``` + +## What’s next[](#whats-next "Permalink") + +如果您要自己进行设置并希望了解生产项目的工作配置,请参阅: + +* [Flockademic’s `wdio.conf.js`](https://gitlab.com/Flockademic/Flockademic/blob/dev/wdio.conf.js) +* [Flockademic’s `.gitlab-ci.yml`](https://gitlab.com/Flockademic/Flockademic/blob/dev/.gitlab-ci.yml) +* [Flockademic’s tests](https://gitlab.com/Flockademic/Flockademic/tree/dev/__e2e__) + +WebdriverIO 还可以做更多的事情. 例如,您可以配置一个[`screenshotPath`](https://webdriver.io/guide/getstarted/configuration.html#screenshotPath)以告诉 WebdriverIO 在测试失败时进行截图. 然后告诉 GitLab CI / CD 存储这些[工件](../../yaml/README.html#artifacts) ,您将能够看到 GitLab 中出了什么问题. \ No newline at end of file diff --git a/_book/docs/232.md b/_book/docs/232.md new file mode 100644 index 0000000000000000000000000000000000000000..bc5bcc6cb4219aabe25f120181f86c59ba666884 --- /dev/null +++ b/_book/docs/232.md @@ -0,0 +1,460 @@ +# DevOps and Game Dev with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/](https://docs.gitlab.com/ee/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/) + +* [The game](#the-game) +* [Requirements and setup](#requirements-and-setup) +* [Continuous Integration](#continuous-integration) + * [Build your game with GitLab CI/CD](#build-your-game-with-gitlab-cicd) + * [Test your game with GitLab CI/CD](#test-your-game-with-gitlab-cicd) + * [Run your CI/CD pipeline](#run-your-cicd-pipeline) +* [Continuous Deployment](#continuous-deployment) + * [Set up S3 Bucket](#set-up-s3-bucket) + * [Set up AWS Secrets](#set-up-aws-secrets) + * [Deploy your game with GitLab CI/CD](#deploy-your-game-with-gitlab-cicd) +* [Conclusion](#conclusion) +* [Further settings](#further-settings) + +# DevOps and Game Dev with GitLab CI/CD[](#devops-and-game-dev-with-gitlab-cicd "Permalink") + +随着 WebGL 和 WebSockets 的进步,浏览器作为游戏开发平台非常可行,而无需使用 Adobe Flash 之类的插件. 此外,通过使用 GitLab 和[AWS](https://aws.amazon.com/) ,单个游戏开发人员以及游戏开发团队可以轻松地在线托管基于浏览器的游戏. + +在本教程中,我们将专注于 DevOps,以及使用[GitLab CI / CD](../../README.html)使用持续集成/部署方法测试和托管游戏. 我们假设您熟悉 GitLab,JavaScript 和游戏开发的基础知识. + +## The game[](#the-game "Permalink") + +我们的[演示游戏](http://gitlab-game-demo.s3-website-us-east-1.amazonaws.com/)由一个简单的太空飞船组成,该太空飞船通过在给定方向上单击鼠标进行射击. + +在开发另一款游戏[Dark Nova](https://www.darknova.io)的开始时,创建强大的 CI / CD 流水线对于团队工作的快速节奏至关重要. 本教程将以我[之前的介绍性文章为基础,](https://ryanhallcs.wordpress.com/2017/03/15/devops-and-game-dev/)并执行以下步骤: + +1. 使用上一篇文章中的代码开始由 gulp 文件构建的准[相位](https://phaser.io)游戏 +2. 添加和运行单元测试 +3. 创建可以触发以给定方向生成`Bullet`的`Weapon`类 +4. 添加使用此武器并在屏幕上四处移动的`Player`类 +5. 添加我们将用于`Player`和`Weapon`的精灵 +6. 使用持续集成和持续部署方法进行测试和部署 + +到最后,我们将拥有一个[可玩游戏](http://gitlab-game-demo.s3-website-us-east-1.amazonaws.com/)的核心,该[游戏](http://gitlab-game-demo.s3-website-us-east-1.amazonaws.com/)在每次推送到[代码库](https://gitlab.com/blitzgren/gitlab-game-demo) `master`分支时都经过测试和部署. 这还将提供样板代码,用于启动具有以下组件的基于浏览器的游戏: + +* 用[TypeScript](https://s0www0typescriptlang0org.icopy.site/)和[PhaserJs 编写](https://phaser.io) +* 使用[Gulp](https://gulpjs.com)构建,运行和测试 +* [Chai](https://www.chaijs.com)和[Mocha 的](https://s0mochajs0org.icopy.site/)单元测试 +* 使用 GitLab 进行 CI / CD +* 在 GitLab.com 上托管代码库 +* 在 AWS 上托管游戏 +* 部署到 AWS + +## Requirements and setup[](#requirements-and-setup "Permalink") + +请参考我以前的文章[DevOps 和 Game Dev,](https://ryanhallcs.wordpress.com/2017/03/15/devops-and-game-dev/)以学习基础开发工具,运行类似于 Hello World 的游戏,以及从每次新推手到使用 GitLab CI / CD 来构建此游戏. 此游戏[存储库](https://gitlab.com/blitzgren/gitlab-game-demo)的`master`分支包含具有所有配置的完整版本. 如果您想继续阅读本文,可以从`devops-article`分支进行克隆并进行工作: + +``` +git clone git@gitlab.com:blitzgren/gitlab-game-demo.git +git checkout devops-article +``` + +接下来,我们将创建一小部分测试,以举例说明我希望该`Weapon`类经历的大多数状态. 首先,创建一个名为`lib/tests`的文件夹,并将以下代码添加到一个新文件`weaponTests.ts` : + +``` +import { expect } from 'chai'; +import { Weapon, BulletFactory } from '../lib/weapon'; + +describe('Weapon', () => { + var subject: Weapon; + var shotsFired: number = 0; + // Mocked bullet factory + var bulletFactory: BulletFactory = <BulletFactory>{ + generate: function(px, py, vx, vy, rot) { + shotsFired++; + } + }; + var parent: any = { x: 0, y: 0 }; + + beforeEach(() => { + shotsFired = 0; + subject = new Weapon(bulletFactory, parent, 0.25, 1); + }); + + it('should shoot if not in cooldown', () => { + subject.trigger(true); + subject.update(0.1); + expect(shotsFired).to.equal(1); + }); + + it('should not shoot during cooldown', () => { + subject.trigger(true); + subject.update(0.1); + subject.update(0.1); + expect(shotsFired).to.equal(1); + }); + + it('should shoot after cooldown ends', () => { + subject.trigger(true); + subject.update(0.1); + subject.update(0.3); // longer than timeout + expect(shotsFired).to.equal(2); + }); + + it('should not shoot if not triggered', () => { + subject.update(0.1); + subject.update(0.1); + expect(shotsFired).to.equal(0); + }); +}); +``` + +为了使用`gulpfile.js`构建和运行这些测试,我们还要将以下`gulpfile.js`函数添加到现有的`gulpfile.js`文件中: + +``` +gulp.task('build-test', function () { + return gulp.src('src/tests/**/*.ts', { read: false }) + .pipe(tap(function (file) { + // replace file contents with browserify's bundle stream + file.contents = browserify(file.path, { debug: true }) + .plugin(tsify, { project: "./tsconfig.test.json" }) + .bundle(); + })) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true}) ) + .pipe(gulp.dest('built/tests')); +}); + +gulp.task('run-test', function() { + gulp.src(['./built/tests/**/*.ts']).pipe(mocha()); +}); +``` + +我们将开始实施游戏的第一部分,并通过这些`Weapon`测试. `Weapon`类将公开一种方法,以给定的方向和速度触发子弹的生成. 稍后,我们将实现一个`Player`类,将用户输入绑定在一起以触发武器. 在`src/lib`文件夹中,创建一个`weapon.ts`文件. 我们将添加两个类: `Weapon`和`BulletFactory` ,它们将封装 Phaser 的**sprite**和**group**对象,以及游戏特定的逻辑. + +``` +export class Weapon { + private isTriggered: boolean = false; + private currentTimer: number = 0; + + constructor(private bulletFactory: BulletFactory, private parent: Phaser.Sprite, private cooldown: number, private bulletSpeed: number) { + } + + public trigger(on: boolean): void { + this.isTriggered = on; + } + + public update(delta: number): void { + this.currentTimer -= delta; + + if (this.isTriggered && this.currentTimer <= 0) { + this.shoot(); + } + } + + private shoot(): void { + // Reset timer + this.currentTimer = this.cooldown; + + // Get velocity direction from player rotation + var parentRotation = this.parent.rotation + Math.PI / 2; + var velx = Math.cos(parentRotation); + var vely = Math.sin(parentRotation); + + // Apply a small forward offset so bullet shoots from head of ship instead of the middle + var posx = this.parent.x - velx * 10 + var posy = this.parent.y - vely * 10; + + this.bulletFactory.generate(posx, posy, -velx * this.bulletSpeed, -vely * this.bulletSpeed, this.parent.rotation); + } +} + +export class BulletFactory { + + constructor(private bullets: Phaser.Group, private poolSize: number) { + // Set all the defaults for this BulletFactory's bullet object + this.bullets.enableBody = true; + this.bullets.physicsBodyType = Phaser.Physics.ARCADE; + this.bullets.createMultiple(30, 'bullet'); + this.bullets.setAll('anchor.x', 0.5); + this.bullets.setAll('anchor.y', 0.5); + this.bullets.setAll('outOfBoundsKill', true); + this.bullets.setAll('checkWorldBounds', true); + } + + public generate(posx: number, posy: number, velx: number, vely: number, rot: number): Phaser.Sprite { + // Pull a bullet from Phaser's Group pool + var bullet = this.bullets.getFirstExists(false); + + // Set the few unique properties about this bullet: rotation, position, and velocity + if (bullet) { + bullet.reset(posx, posy); + bullet.rotation = rot; + bullet.body.velocity.x = velx; + bullet.body.velocity.y = vely; + } + + return bullet; + } +} +``` + +最后,我们将重做我们的入口点`game.ts` ,将`Player`和`Weapon`对象绑定在一起,并将它们添加到更新循环中. 这是更新的`game.ts`文件的外观: + +``` +import { Player } from "./player"; +import { Weapon, BulletFactory } from "./weapon"; + +window.onload = function() { + var game = new Phaser.Game(800, 600, Phaser.AUTO, 'gameCanvas', { preload: preload, create: create, update: update }); + var player: Player; + var weapon: Weapon; + + // Import all assets prior to loading the game + function preload () { + game.load.image('player', 'assets/player.png'); + game.load.image('bullet', 'assets/bullet.png'); + } + + // Create all entities in the game, after Phaser loads + function create () { + // Create and position the player + var playerSprite = game.add.sprite(400, 550, 'player'); + playerSprite.anchor.setTo(0.5); + player = new Player(game.input, playerSprite, 150); + + var bulletFactory = new BulletFactory(game.add.group(), 30); + weapon = new Weapon(bulletFactory, player.sprite, 0.25, 1000); + + player.loadWeapon(weapon); + } + + // This function is called once every tick, default is 60fps + function update() { + var deltaSeconds = game.time.elapsedMS / 1000; // convert to seconds + player.update(deltaSeconds); + weapon.update(deltaSeconds); + } +} +``` + +运行`gulp serve` ,您可以四处奔跑射击. 精彩! 让我们更新 CI 管道,使其包括运行测试以及现有的构建作业. + +## Continuous Integration[](#continuous-integration "Permalink") + +为了确保我们的更改不会破坏构建并且所有测试仍然通过,我们利用持续集成(CI)来为每次推送自动运行这些检查. 通读本文以了解[持续集成,持续交付和持续部署](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) ,以及 GitLab 如何利用这些方法. 在上[一教程中,](https://ryanhallcs.wordpress.com/2017/03/15/devops-and-game-dev/)我们已经设置了一个`.gitlab-ci.yml`文件,用于从每次推送开始构建我们的应用程序. 我们需要设置一个新的 CI 作业进行测试,GitLab CI / CD 将使用我们从 gulp 生成的工件在构建作业后运行. + +请通读[CI / CD 配置](../../../ci/yaml/README.html)文件[上](../../../ci/yaml/README.html)的[文档,](../../../ci/yaml/README.html)以探索其内容并根据需要进行调整. + +### Build your game with GitLab CI/CD[](#build-your-game-with-gitlab-cicd "Permalink") + +我们需要更新构建作业以确保测试也能运行. 将`gulp build-test`添加到现有`build`作业的`script`数组的末尾. 一旦这些命令运行,我们就知道需要访问 GitLab CI / CD `artifacts`提供的`built`文件夹中的所有内容. 我们还将缓存`node_modules`以避免不得不完全重新拉动那些依赖项:只需将它们打包在缓存中即可. 这是完整的`build`工作: + +``` +build: + stage: build + script: + - npm i gulp -g + - npm i + - gulp + - gulp build-test + cache: + policy: push + paths: + - node_modules + artifacts: + paths: + - built +``` + +### Test your game with GitLab CI/CD[](#test-your-game-with-gitlab-cicd "Permalink") + +对于本地测试,我们只需要运行`gulp run-tests` ,这需要像`build`作业一样在全球范围内安装 gulp. 我们从缓存中拉出`node_modules` ,因此`npm i`命令不必做太多事情. 在准备部署时,我们知道我们仍然需要工件中的`built`文件夹,该文件夹将作为上一个作业的默认行为被带入. 最后,按照惯例,我们通过给 GitLab CI / CD 一个`test` [阶段](../../../ci/yaml/README.html#stages)来告知需要在`build`工作之后运行它. 按照 YAML 结构, `test`作业应如下所示: + +``` +test: + stage: test + script: + - npm i gulp -g + - npm i + - gulp run-test + cache: + policy: push + paths: + - node_modules/ + artifacts: + paths: + - built/ +``` + +我们为以指定间隔射击的`Weapon`类添加了单元测试. `Player`类实现了`Weapon`以及四处移动和射击的能力. 此外,我们还使用`.gitlab-ci.yml`在 GitLab CI / CD 管道中添加了测试工件和测试阶段,从而使我们能够在每次推送时运行测试. 现在,我们整个`.gitlab-ci.yml`文件应如下所示: + +``` +image: node:10 + +build: + stage: build + script: + - npm i gulp -g + - npm i + - gulp + - gulp build-test + cache: + policy: push + paths: + - node_modules/ + artifacts: + paths: + - built/ + +test: + stage: test + script: + - npm i gulp -g + - npm i + - gulp run-test + cache: + policy: pull + paths: + - node_modules/ + artifacts: + paths: + - built/ +``` + +### Run your CI/CD pipeline[](#run-your-cicd-pipeline "Permalink") + +而已! 添加所有新文件,提交并推送. 有关此时存储库外观的参考,请参考[示例存储库中与本文相关](https://gitlab.com/blitzgren/gitlab-game-demo/commit/8b36ef0ecebcf569aeb251be4ee13743337fcfe2)的[最终提交](https://gitlab.com/blitzgren/gitlab-game-demo/commit/8b36ef0ecebcf569aeb251be4ee13743337fcfe2) . 通过同时应用构建和测试阶段,GitLab 将在每次推送到我们的存储库时按顺序运行它们. 如果一切顺利,您将在管道的每个作业上得到一个绿色的复选标记: + +[![Passing Pipeline](img/1d8faac0ce4cf1206b5c2745df725ca6.png)](img/test_pipeline_pass.png) + +您可以通过单击`test`作业以输入完整的构建日志来确认测试通过. 滚动到底部,观察所有过去的荣耀: + +``` +$ gulp run-test +[18:37:24] Using gulpfile /builds/blitzgren/gitlab-game-demo/gulpfile.js +[18:37:24] Starting 'run-test'... +[18:37:24] Finished 'run-test' after 21 ms + + Weapon + ✓ should shoot if not in cooldown + ✓ should not shoot during cooldown + ✓ should shoot after cooldown ends + ✓ should not shoot if not triggered + + 4 passing (18ms) + +Uploading artifacts... +built/: found 17 matching files +Uploading artifacts to coordinator... ok id=17095874 responseStatus=201 Created token=aaaaaaaa Job succeeded +``` + +## Continuous Deployment[](#continuous-deployment "Permalink") + +我们在每次推送时都构建并测试了代码库. 为了完成持续部署的全部流程,让我们[使用 AWS S3](https://aws.amazon.com/free/)设置[免费的 Web 托管,](https://aws.amazon.com/free/)并通过一项工作来部署构建工件. GitLab 还提供了免费的静态站点托管服务[GitLab Pages](https://about.gitlab.com/stages-devops-lifecycle/pages/) ,但是 Dark Nova 特别使用需要使用`AWS S3`其他 AWS 工具. 通读本文,该文章描述了[如何同时部署到 S3 和 GitLab 页面,](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/)并且比本文讨论的内容更深入地研究 GitLab CI / CD 的原理. + +### Set up S3 Bucket[](#set-up-s3-bucket "Permalink") + +1. 登录您的 AWS 账户并转到[S3](https://console.aws.amazon.com/s3/home) +2. 点击顶部的**创建存储桶**链接 +3. 输入您选择的名称,然后单击下一步 +4. 保留默认**属性** ,然后单击下一步 +5. 单击" **管理组"权限** ,然后为" **所有人"**组允许" **读取** ",单击"下一步". +6. 创建存储桶,然后在您的 S3 存储桶列表中选择它 +7. 在右侧,单击" **属性"**并启用" **静态网站托管"**类别 +8. Update the radio button to the **使用此存储桶托管网站** selection. Fill in `index.html` and `error.html` respectively + +### Set up AWS Secrets[](#set-up-aws-secrets "Permalink") + +我们需要能够使用我们的 AWS 账户凭证部署到 AWS,但是我们当然不希望在源代码中添加机密信息. 幸运的是,GitLab 通过[Variables](../../../ci/variables/README.html)提供了解决方案. 由于[IAM](https://aws.amazon.com/iam/)管理,这可能会变得复杂. 作为最佳实践,您不应使用根安全凭证. 正确的 IAM 凭据管理不在本文讨论范围之内,但是 AWS 会提醒您,不建议使用 root 凭据,并且应该违反其最佳做法. 随意遵循最佳实践并使用自定义 IAM 用户的凭据,这将是两个相同的凭据(密钥 ID 和密钥). 充分了解[AWS 中的 IAM 最佳做法](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html)是一个好主意. 我们需要将以下凭据添加到 GitLab: + +1. 登录您的 AWS 账户并转到[安全凭证页面](https://console.aws.amazon.com/iam/home#/security_credential) +2. 单击**访问密钥**部分,然后**创建新的访问密钥** . 创建密钥并保留 ID 和秘密,以后需要它们 + + [![AWS Access Key Configuration](img/6b5837eb8878551d4881e94247d957e9.png)](img/aws_config_window.png) + +3. 转到您的 GitLab 项目,单击左侧栏中的**设置> CI / CD** . +4. 展开**变量**部分 + + [![GitLab Secret Config](img/7ac2e224cec000f3932b1186bc1d643f.png)](img/gitlab_config.png) + +5. 添加一个名为`AWS_KEY_ID`的密钥,并将步骤 2 中的密钥 ID 复制到" **值"**字段中 +6. 添加一个名为`AWS_KEY_SECRET`的密钥,并将步骤 2 中的密钥机密复制到" **值"**字段中 + +### Deploy your game with GitLab CI/CD[](#deploy-your-game-with-gitlab-cicd "Permalink") + +要部署构建工件,我们需要在 Shared Runner 上安装[AWS CLI](https://aws.amazon.com/cli/) . Shared Runner 还需要能够通过您的 AWS 账户进行身份验证以部署工件. 按照约定,AWS CLI 将寻找`AWS_ACCESS_KEY_ID`和`AWS_SECRET_ACCESS_KEY` . GitLab 的 CI 为我们提供了一种使用`deploy`作业的`variables`部分传递在上一节中设置的`variables`的方法. 最后,我们添加指令以确保`only`在推送到`master`时进行部署. 这样,每个分支仍然通过 CI 运行,并且只有合并(或直接提交)到 master 才会触发管道的`deploy`工作. 将它们放在一起可获得以下内容: + +``` +deploy: + stage: deploy + variables: + AWS_ACCESS_KEY_ID: "$AWS_KEY_ID" + AWS_SECRET_ACCESS_KEY: "$AWS_KEY_SECRET" + script: + - apt-get update + - apt-get install -y python3-dev python3-pip + - easy_install3 -U pip + - pip3 install --upgrade awscli + - aws s3 sync ./built s3://gitlab-game-demo --region "us-east-1" --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --cache-control "no-cache, no-store, must-revalidate" --delete + only: + - master +``` + +确保在最后一个脚本命令中更新区域和 S3 URL 以适合您的设置. 我们的最终配置文件`.gitlab-ci.yml`看起来像: + +``` +image: node:10 + +build: + stage: build + script: + - npm i gulp -g + - npm i + - gulp + - gulp build-test + cache: + policy: push + paths: + - node_modules/ + artifacts: + paths: + - built/ + +test: + stage: test + script: + - npm i gulp -g + - gulp run-test + cache: + policy: pull + paths: + - node_modules/ + artifacts: + paths: + - built/ + +deploy: + stage: deploy + variables: + AWS_ACCESS_KEY_ID: "$AWS_KEY_ID" + AWS_SECRET_ACCESS_KEY: "$AWS_KEY_SECRET" + script: + - apt-get update + - apt-get install -y python3-dev python3-pip + - easy_install3 -U pip + - pip3 install --upgrade awscli + - aws s3 sync ./built s3://gitlab-game-demo --region "us-east-1" --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --cache-control "no-cache, no-store, must-revalidate" --delete + only: + - master +``` + +## Conclusion[](#conclusion "Permalink") + +在[演示存储库中,](https://gitlab.com/blitzgren/gitlab-game-demo)您还可以找到一些样板代码来使[TypeScript](https://s0www0typescriptlang0org.icopy.site/) , [Mocha](https://s0mochajs0org.icopy.site/) , [Gulp](https://gulpjs.com/)和[Phaser](https://phaser.io)与 GitLab CI / CD 完美地结合在一起,这是在制作[Dark Nova 时](https://www.darknova.io)汲取的教训的结果. 使用免费和开源软件的组合,我们拥有完整的 CI / CD 流水线,游戏基础和单元测试,所有这些操作和部署都可以在每次熟练掌握的情况下完成-只需很少的代码. 可以通过 GitLab 的构建日志轻松调试错误,并且在成功提交后的几分钟内,您就可以在游戏中实时看到更改. + +借助 Dark Nova 从一开始就设置持续集成和持续部署可实现快速而稳定的开发. 我们可以轻松地在单独的[环境中](../../environments/index.html)测试更改,如果需要,可以在多个环境中测试更改. 平衡和更新多人游戏可能会持续且乏味,但是相信使用 GitLab CI / CD 进行稳定部署会在快速获得玩家更改方面有很大的喘息空间. + +## Further settings[](#further-settings "Permalink") + +以下是一些可以进一步研究的想法,可以加快或改善您的流程: + +* [纱线](https://yarnpkg.com)代替 npm +* 设置可以预加载依赖项和工具(如 AWS CLI)的自定义[Docker](../../../ci/docker/using_docker_images.html#define-image-and-services-from-gitlab-ciyml)映像 +* 将[自定义域](https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html)转发到游戏的 S3 静态网站 +* 如果您发现小型项目不必要,请合并工作 +* 避免排队,并设置自己的[自定义 GitLab CI / CD 运行器](https://about.gitlab.com/blog/2016/03/01/gitlab-runner-with-docker/) \ No newline at end of file diff --git a/_book/docs/233.md b/_book/docs/233.md new file mode 100644 index 0000000000000000000000000000000000000000..e49839b0b200df36d47ece2f15094399cfdbab85 --- /dev/null +++ b/_book/docs/233.md @@ -0,0 +1,107 @@ +# Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/deploy_spring_boot_to_cloud_foundry/](https://docs.gitlab.com/ee/ci/examples/deploy_spring_boot_to_cloud_foundry/) + +* [Introduction](#introduction) +* [Requirements](#requirements) +* [Create your project](#create-your-project) +* [Configure the deployment to Cloud Foundry](#configure-the-deployment-to-cloud-foundry) +* [Configure GitLab CI/CD to deploy your application](#configure-gitlab-cicd-to-deploy-your-application) + +# Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD[](#deploy-a-spring-boot-application-to-cloud-foundry-with-gitlab-cicd "Permalink") + +## Introduction[](#introduction "Permalink") + +在本文中,我们将演示如何使用[连续部署](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-deployment)方法通过 GitLab CI / CD 将[Spring Boot](https://projects.spring.io/spring-boot/)应用程序部署到[Cloud Foundry(CF)](https://www.cloudfoundry.org/) . + +该项目的所有代码都可以在该[GitLab 存储库中](https://gitlab.com/gitlab-examples/spring-gitlab-cf-deploy-demo)找到. + +如果您有兴趣使用 GitLab CI / CD 将 Spring Boot 应用程序部署到 Kubernetes,请通读博客文章[GitLab CI 和 Kubernetes 持续交付 Spring Boot 应用程序](https://about.gitlab.com/blog/2016/12/14/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/) . + +## Requirements[](#requirements "Permalink") + +本教程假定您熟悉 Java,GitLab,Cloud Foundry 和 GitLab CI / CD. + +要继续进行,您将需要: + +* [Pivotal Web 服务(PWS)](https://run.pivotal.io/)或任何其他 Cloud Foundry(CF)实例上的帐户. +* 在 GitLab 上的帐户. + +**注意:**如果您没有部署到 PWS,则需要将以下所有命令中的`api.run.pivotal.io` URL 替换为 CF 实例的[API URL](https://docs.cloudfoundry.org/running/cf-api-endpoint.html) . + +## Create your project[](#create-your-project "Permalink") + +要创建您的 Spring Boot 应用程序,可以在创建新项目时在 GitLab 中使用 Spring 模板: + +[![New Project From Template](img/b64907bafa7c740c069ec7395a5c5471.png)](img/create_from_template.png) + +## Configure the deployment to Cloud Foundry[](#configure-the-deployment-to-cloud-foundry "Permalink") + +要部署到 Cloud Foundry,我们需要添加`manifest.yml`文件. 这是我们将用于部署应用程序的 CF CLI 的配置. 我们将在项目的根目录中创建以下内容: + +``` +--- +applications: + - name: gitlab-hello-world + random-route: true + memory: 1G + path: target/demo-0.0.1-SNAPSHOT.jar +``` + +## Configure GitLab CI/CD to deploy your application[](#configure-gitlab-cicd-to-deploy-your-application "Permalink") + +现在,我们需要将 GitLab CI / CD 配置文件( [`.gitlab-ci.yml`](../../yaml/README.html) )添加到项目的根目录. 这就是 GitLab 找出每当将代码推送到我们的存储库时需要运行哪些命令的方式. 我们将以下`.gitlab-ci.yml`文件添加到存储库的根目录中,GitLab 将自动检测该文件,并在推送代码后运行定义的步骤: + +``` +image: java:8 + +stages: + - build + - deploy + +before_script: + - chmod +x mvnw + +build: + stage: build + script: ./mvnw package + artifacts: + paths: + - target/demo-0.0.1-SNAPSHOT.jar + +production: + stage: deploy + script: + - curl --location "https://cli.run.pivotal.io/stable?release=linux64-binary&source=github" | tar zx + - ./cf login -u $CF_USERNAME -p $CF_PASSWORD -a api.run.pivotal.io + - ./cf push + only: + - master +``` + +我们使用了`java:8` [Docker 映像](../../docker/using_docker_images.html)来构建我们的应用程序,因为它在[Docker Hub](https://hub.docker.com/)上提供了最新的 Java 8 JDK. 我们还添加了[`only`子句,](../../yaml/README.html#onlyexcept-basic)以确保仅当我们推送到 master 分支[`only`](../../yaml/README.html#onlyexcept-basic)进行部署. + +现在,由于`.gitlab-ci.yml`定义的步骤需要凭据才能登录到 CF,因此您需要将 CF 凭据作为[环境变量添加](../../variables/README.html#predefined-environment-variables)到 GitLab CI / CD 上. 要设置环境变量,请导航至项目的**"设置">" CI / CD",**然后展开" **变量"** . 将变量命名为`CF_USERNAME`和`CF_PASSWORD`并将其设置为正确的值. + +[![Variable Settings in GitLab](img/75ff7ad133721fa954b7960ba4edc025.png)](img/cloud_foundry_variables.png) + +设置完成后,每次推送到存储库默认分支时,GitLab CI / CD 都会将您的应用程序部署到 CF. 要查看构建日志或观看构建的实时运行,请导航至**CI / CD> Pipelines** . + +**注意:**为安全性的最佳做法是为应用程序创建一个单独的部署用户,并将其凭据添加到 GitLab,而不使用开发人员的凭据. + +要在 GitLab 中开始手动部署,请转到**CI / CD>管道,**然后单击**运行管道** . 应用程序完成部署后,它将在`production`作业的日志中显示应用程序的 URL,例如: + +``` +requested state: started +instances: 1/1 +usage: 1G x 1 instances +urls: gitlab-hello-world-undissembling-hotchpot.cfapps.io +last uploaded: Mon Nov 6 10:02:25 UTC 2017 +stack: cflinuxfs2 +buildpack: client-certificate-mapper=1.2.0_RELEASE container-security-provider=1.8.0_RELEASE java-buildpack=v4.5-offline-https://github.com/cloudfoundry/java-buildpack.git#ffeefb9 java-main java-opts jvmkill-agent=1.10.0_RELEASE open-jdk-like-jre=1.8.0_1... + + state since cpu memory disk details +#0 running 2017-11-06 09:03:22 PM 120.4% 291.9M of 1G 137.6M of 1G +``` + +然后,您可以访问已部署的应用程序(对于本示例,为`https://gitlab-hello-world-undissembling-hotchpot.cfapps.io/` ),您应该看到"春天在这里!" 信息. \ No newline at end of file diff --git a/_book/docs/234.md b/_book/docs/234.md new file mode 100644 index 0000000000000000000000000000000000000000..dd7a45957a34536d92deee9f38dd59b8ace6682b --- /dev/null +++ b/_book/docs/234.md @@ -0,0 +1,263 @@ +# How to deploy Maven projects to Artifactory with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/artifactory_and_gitlab/](https://docs.gitlab.com/ee/ci/examples/artifactory_and_gitlab/) + +* [Introduction](#introduction) +* [Create the simple Maven dependency](#create-the-simple-maven-dependency) + * [Prepare the dependency application](#prepare-the-dependency-application) + * [Configure the Artifactory deployment](#configure-the-artifactory-deployment) + * [Configure GitLab CI/CD for `simple-maven-dep`](#configure-gitlab-cicd-for-simple-maven-dep) +* [Create the main Maven application](#create-the-main-maven-application) + * [Prepare the main application](#prepare-the-main-application) + * [Configure the Artifactory repository location](#configure-the-artifactory-repository-location) + * [Configure GitLab CI/CD for `simple-maven-app`](#configure-gitlab-cicd-for-simple-maven-app) +* [Conclusion](#conclusion) + +# How to deploy Maven projects to Artifactory with GitLab CI/CD[](#how-to-deploy-maven-projects-to-artifactory-with-gitlab-cicd "Permalink") + +## Introduction[](#introduction "Permalink") + +在本文中,我们展示了如何利用[GitLab CI / CD 的功能](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)来构建[Maven](https://maven.apache.org/)项目,将其部署到[Artifactory](https://jfrog.com/artifactory/) ,然后从另一个 Maven 应用程序中将其用作依赖项. + +您将创建两个不同的项目: + +* `simple-maven-dep` :构建并部署到 Artifactory 的应用程序(请参阅[simple-maven-dep](https://gitlab.com/gitlab-examples/maven/simple-maven-dep)示例项目) +* `simple-maven-app` :使用前一个作为依赖[项的应用程序](https://gitlab.com/gitlab-examples/maven/simple-maven-app) (请参见[simple-maven-app](https://gitlab.com/gitlab-examples/maven/simple-maven-app)示例项目) + +我们假设您已经在[GitLab.com](https://gitlab.com/)上拥有一个 GitLab 帐户,并且您知道 Git 和[GitLab CI / CD](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)的基本用法. 我们还假定 Artifactory 实例在 Internet 上可用且可访问,并且您具有在其上部署的有效凭据. + +## Create the simple Maven dependency[](#create-the-simple-maven-dependency "Permalink") + +First of all, you need an application to work with: in this specific case we will use a simple one, but it could be any Maven application. This will be the dependency you want to package and deploy to Artifactory, in order to be available to other projects. + +### Prepare the dependency application[](#prepare-the-dependency-application "Permalink") + +对于本文,您将使用可以从示例项目中克隆的 Maven 应用程序: + +1. 登录到您的 GitLab 帐户 +2. 通过选择**URL 通过 URL 回购导入项目来**创建新项目 +3. 添加以下 URL: + + ``` + https://gitlab.com/gitlab-examples/maven/simple-maven-dep.git + ``` + +4. Click **建立专案** + +该应用程序不过是带有基于 JUnit 的测试套件的存根的基本类. 它公开了一种名为`hello`的方法,该方法接受字符串作为输入,并在屏幕上显示 hello 消息. + +该项目的结构非常简单,您应该考虑以下两个资源: + +* `pom.xml` :项目对象模型(POM)配置文件 +* `src/main/java/com/example/dep/Dep.java` :我们应用程序的源代码 + +### Configure the Artifactory deployment[](#configure-the-artifactory-deployment "Permalink") + +该应用程序已准备就绪,可以使用,但是您需要一些其他步骤才能将其部署到 Artifactory: + +1. 使用您的用户凭据登录到 Artifactory. +2. 在主屏幕上,单击" **设置我"**面板中的`libs-release-local`项目. +3. 将" **部署"**段落下的配置片段复制到剪贴板. +4. 更改`url`值,以使其可通过变量进行配置. +5. 在`dependencies`部分之后,将片段复制到项目的`pom.xml`文件中. 该代码段应如下所示: + + ``` + <distributionManagement> + <repository> + <id>central</id> + <name>83d43b5afeb5-releases</name> + <url>${env.MAVEN_REPO_URL}/libs-release-local</url> + </repository> + </distributionManagement> + ``` + +将依赖项部署到 Artifactory 之前,您需要做的另一步骤是配置身份验证数据. 这是一个简单的任务,但是 Maven 要求它保留在一个名为`settings.xml`的文件中,该文件必须位于用户 homedir 的`.m2`子目录中. + +由于要使用 GitLab Runner 自动部署应用程序,因此应在项目的主目录中创建文件,并在`.gitlab-ci.yml`设置命令行参数以使用自定义位置,而不是默认位置: + +1. 在存储库的根目录中创建一个名为`.m2`的文件夹 +2. 在`.m2`文件夹中创建一个名为`settings.xml`的文件 +3. 将以下内容复制到`settings.xml`文件中: + + ``` + <settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd" + xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <servers> + <server> + <id>central</id> + <username>${env.MAVEN_REPO_USER}</username> + <password>${env.MAVEN_REPO_PASS}</password> + </server> + </servers> + </settings> + ``` + + 用户名和密码将使用变量替换为正确的值. + +### Configure GitLab CI/CD for `simple-maven-dep`[](#configure-gitlab-cicd-for-simple-maven-dep "Permalink") + +现在是时候设置[GitLab CI / CD](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)来自动构建,测试和部署依赖项了! + +GitLab CI / CD 使用存储库根目录中的一个名为`.gitlab-ci.yml`来读取将由已配置的 GitLab Runners 执行的作业的定义. 您可以在[GitLab 文档中](../../yaml/README.html)阅读有关此文件的更多信息. + +首先,请记住为您的部署设置变量. 导航到项目的**"设置">" CI / CD">"环境变量"**页面,并添加以下内容(当然,将它们替换为当前值): + +* **MAVEN_REPO_URL** : `http://artifactory.example.com:8081/artifactory` : **//artifactory.example.com** : **8081/artifactory** (您的 Artifactory URL) +* **MAVEN_REPO_USER** : `gitlab` (您的 Artifactory 用户名) +* **MAVEN_REPO_PASS** : `AKCp2WXr3G61Xjz1PLmYa3arm3yfBozPxSta4taP3SeNu2HPXYa7FhNYosnndFNNgoEds8BCS` (您的 Artifactory 加密密码) + +现在是时候在`.gitlab-ci.yml`定义作业并将其推送到存储库了: + +``` +image: maven:latest + +variables: + MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode" + MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository" + +cache: + paths: + - .m2/repository/ + - target/ + +build: + stage: build + script: + - mvn $MAVEN_CLI_OPTS compile + +test: + stage: test + script: + - mvn $MAVEN_CLI_OPTS test + +deploy: + stage: deploy + script: + - mvn $MAVEN_CLI_OPTS deploy + only: + - master +``` + +GitLab Runner 将使用最新的[Maven Docker 映像](https://hub.docker.com/_/maven/) ,该[映像](https://hub.docker.com/_/maven/)已经包含了管理项目以运行作业所需的所有工具和依赖项. + +设置环境变量以指示 Maven 在搜索配置和依赖项时使用存储库的`homedir`而不是用户的`homedir` . + +缓存`.m2/repository folder` ( `.m2/repository folder`所有 Maven 文件的位置)和`target`文件夹(将创建我们的应用程序的位置),对于按顺序运行所有 Maven 阶段来加快过程非常有用,因此,执行`mvn test`会在必要时自动运行`mvn compile` . + +`build`作业和`test`作业均利用`mvn`命令来编译应用程序,并按照应用程序一部分的测试套件中的定义对其进行测试. + +部署到 Artifactory 的过程已由我们刚刚设置的变量定义. 仅当我们推送或合并到`master`分支时才进行部署,以便开发版本经过测试但未发布. + +做完了! 现在,您已在 GitLab 存储库中进行了所有更改,并且已经为此提交启动了管道. 在" **管道"**选项卡中,您可以查看正在发生的事情. 如果部署成功,则部署作业日志将输出: + +``` +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 1.983 s +``` + +> **注意** : `mvn`命令从 Internet 下载大量文件,因此,首次运行日志时,您会在日志中看到很多额外的活动. + +好极了! 你做到了! 检入 Artifactory 将确认`libs-release-local`存储库中有可用的新工件. + +## Create the main Maven application[](#create-the-main-maven-application "Permalink") + +现在您已经有了 Artifactory 上的依赖项,是时候使用它了! 让我们看看如何将其作为对主应用程序的依赖. + +### Prepare the main application[](#prepare-the-main-application "Permalink") + +我们将再次使用可以从示例项目中克隆的 Maven 应用程序: + +1. 通过选择**URL 通过 URL 回购导入项目来**创建新项目 +2. 添加以下 URL: + + ``` + https://gitlab.com/gitlab-examples/maven/simple-maven-app.git + ``` + +3. Click **建立专案** + +This one is a simple app as well. If you look at the `src/main/java/com/example/app/App.java` file you can see that it imports the `com.example.dep.Dep` class and calls the `hello` method passing `GitLab` as a parameter. + +由于 Maven 不知道如何解决依赖关系,因此您需要修改配置: + +1. 回到 Artifactory +2. 浏览`libs-release-local`存储库 +3. 选择`simple-maven-dep-1.0.jar`文件 +4. 从主面板的**Dependency Declaration**部分中找到配置片段 +5. 将代码段复制到`pom.xml`文件的`dependencies`部分中. 该代码段应如下所示: + + ``` + <dependency> + <groupId>com.example.dep</groupId> + <artifactId>simple-maven-dep</artifactId> + <version>1.0</version> + </dependency> + ``` + +### Configure the Artifactory repository location[](#configure-the-artifactory-repository-location "Permalink") + +至此,您已经定义了应用程序的依赖关系,但是仍然错过了可以找到所需文件的位置. 您需要像创建依赖项项目一样创建一个`.m2/settings.xml`文件,并使用环境变量让 Maven 知道位置. + +这是直接从 Artifactory 获取文件内容的方法: + +1. 在主屏幕上,单击" **设置我"**面板中的`libs-release-local`项目 +2. 单击**生成 Maven 设置** +3. 点击**生成设置** +4. 将配置文件复制到剪贴板 +5. 在存储库中将文件另存为`.m2/settings.xml` + +现在您可以使用 Artifactory 存储库来解决依赖关系,并在主应用程序中使用`simple-maven-dep` ! + +### Configure GitLab CI/CD for `simple-maven-app`[](#configure-gitlab-cicd-for-simple-maven-app "Permalink") + +您需要完成所有步骤:为该项目配置`.gitlab-ci.yml`文件,就像对`simple-maven-dep`所做的那样. + +您想利用[GitLab CI / CD](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)自动构建,测试和运行您的超赞应用程序,并查看是否可以按预期方式获得欢迎! + +您需要做的就是将以下`.gitlab-ci.yml`添加到存储库中: + +``` +image: maven:latest + +stages: + - build + - test + - run + +variables: + MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode" + MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository" + +cache: + paths: + - .m2/repository/ + - target/ + +build: + stage: build + script: + - mvn $MAVEN_CLI_OPTS compile + +test: + stage: test + script: + - mvn $MAVEN_CLI_OPTS test + +run: + stage: run + script: + - mvn $MAVEN_CLI_OPTS package + - mvn $MAVEN_CLI_OPTS exec:java -Dexec.mainClass="com.example.app.App" +``` + +它与用于`simple-maven-dep`的配置非常相似,但是有一个`run`作业代替了`deploy`作业. 可能是您不想在实际项目中使用的东西,但是在这里查看自动执行的应用程序很有用. + +就是这样! 在`run`作业输出日志中,您会找到与 GitLab 的友好问好! + +## Conclusion[](#conclusion "Permalink") + +在本文中,我们介绍了使用 Artifactory Maven 存储库自动发布和使用工件的基本步骤. + +可以使用类似的方法与任何其他 Maven 兼容的 Binary Repository Manager 进行交互. 显然,您可以改进这些示例,优化`.gitlab-ci.yml`文件以更好地满足您的需求,并适应您的工作流程. \ No newline at end of file diff --git a/_book/docs/235.md b/_book/docs/235.md new file mode 100644 index 0000000000000000000000000000000000000000..144596339736522ac6362914b9227fb6b665edca --- /dev/null +++ b/_book/docs/235.md @@ -0,0 +1,255 @@ +# Testing PHP projects + +> 原文:[https://docs.gitlab.com/ee/ci/examples/php.html](https://docs.gitlab.com/ee/ci/examples/php.html) + +* [Test PHP projects using the Docker executor](#test-php-projects-using-the-docker-executor) + * [Test against different PHP versions in Docker builds](#test-against-different-php-versions-in-docker-builds) + * [Custom PHP configuration in Docker builds](#custom-php-configuration-in-docker-builds) +* [Test PHP projects using the Shell executor](#test-php-projects-using-the-shell-executor) + * [Test against different PHP versions in Shell builds](#test-against-different-php-versions-in-shell-builds) + * [Install custom extensions](#install-custom-extensions) +* [Extend your tests](#extend-your-tests) + * [Using atoum](#using-atoum) + * [Using Composer](#using-composer) +* [Access private packages or dependencies](#access-private-packages-or-dependencies) +* [Use databases or other services](#use-databases-or-other-services) +* [Testing things locally](#testing-things-locally) +* [Example project](#example-project) + +# Testing PHP projects[](#testing-php-projects "Permalink") + +本指南涵盖了 PHP 项目的基本构建说明. + +涵盖了两种测试方案:使用 Docker 执行程序和使用 Shell 执行程序. + +## Test PHP projects using the Docker executor[](#test-php-projects-using-the-docker-executor "Permalink") + +尽管可以在任何系统上测试 PHP 应用程序,但这都需要开发人员进行手动配置. 为了克服这个问题,我们将使用可在 Docker Hub 中找到的官方[PHP Docker 映像](https://hub.docker.com/_/php) . + +这将使我们能够针对不同版本的 PHP 测试 PHP 项目. 但是,并非所有事情都是即插即用的,您仍然需要手动配置一些东西. + +与每项工作一样,您需要创建一个描述构建环境的有效`.gitlab-ci.yml` . + +首先,让我们指定将用于作业过程的 PHP 映像(您可以在 Runner 的术语中阅读有关[使用 Docker 映像的](../docker/using_docker_images.html#what-is-an-image)更多信息,以了解映像的含义). + +首先将图像添加到您的`.gitlab-ci.yml` : + +``` +image: php:5.6 +``` + +官方图片很棒,但是缺少一些有用的测试工具. 我们需要首先准备构建环境. 解决此问题的一种方法是创建一个脚本,该脚本在完成实际测试之前会安装所有必备组件. + +Let’s create a `ci/docker_install.sh` file in the root directory of our repository with the following content: + +``` +#!/bin/bash + +# We need to install dependencies only for Docker +[[ ! -e /.dockerenv ]] && exit 0 + +set -xe + +# Install git (the php image doesn't have it) which is required by composer +apt-get update -yqq +apt-get install git -yqq + +# Install phpunit, the tool that we will use for testing +curl --location --output /usr/local/bin/phpunit https://phar.phpunit.de/phpunit.phar +chmod +x /usr/local/bin/phpunit + +# Install mysql driver +# Here you can install any other extension that you need +docker-php-ext-install pdo_mysql +``` + +您可能想知道`docker-php-ext-install`是什么. 简而言之,它是官方 PHP Docker 映像提供的脚本,可用于轻松安装扩展. 有关更多信息,请参阅[https://hub.docker.com/_/php 上](https://hub.docker.com/_/php)的文档. + +现在,我们创建了包含构建环境的所有先决条件的脚本,让我们将其添加到`.gitlab-ci.yml` : + +``` +... + +before_script: + - bash ci/docker_install.sh > /dev/null + +... +``` + +最后一步,使用`phpunit`运行实际测试: + +``` +... + +test:app: + script: + - phpunit --configuration phpunit_myapp.xml + +... +``` + +最后,提交文件并将其推送到 GitLab,以查看构建成功(或失败). + +最终的`.gitlab-ci.yml`应该类似于以下内容: + +``` +# Select image from https://hub.docker.com/_/php +image: php:5.6 + +before_script: +# Install dependencies + - bash ci/docker_install.sh > /dev/null + +test:app: + script: + - phpunit --configuration phpunit_myapp.xml +``` + +### Test against different PHP versions in Docker builds[](#test-against-different-php-versions-in-docker-builds "Permalink") + +针对多个版本的 PHP 进行测试非常容易. 只需添加另一个具有不同 Docker 映像版本的作业,即可由跑步者完成其余工作: + +``` +before_script: +# Install dependencies + - bash ci/docker_install.sh > /dev/null + +# We test PHP5.6 +test:5.6: + image: php:5.6 + script: + - phpunit --configuration phpunit_myapp.xml + +# We test PHP7.0 (good luck with that) +test:7.0: + image: php:7.0 + script: + - phpunit --configuration phpunit_myapp.xml +``` + +### Custom PHP configuration in Docker builds[](#custom-php-configuration-in-docker-builds "Permalink") + +有时,您需要通过将`.ini`文件放入`/usr/local/etc/php/conf.d/`来自定义 PHP 环境. 为此,添加一个`before_script`动作: + +``` +before_script: + - cp my_php.ini /usr/local/etc/php/conf.d/test.ini +``` + +当然, `my_php.ini`必须存在于存储库的根目录中. + +## Test PHP projects using the Shell executor[](#test-php-projects-using-the-shell-executor "Permalink") + +Shell 执行程序在服务器上的终端会话中运行您的作业. 因此,为了测试您的项目,您首先需要确保已安装所有依赖项. + +例如,在运行 Debian 8 的 VM 中,我们首先更新缓存,然后安装`phpunit`和`php5-mysql` : + +``` +sudo apt-get update -y +sudo apt-get install -y phpunit php5-mysql +``` + +接下来,将以下代码段添加到`.gitlab-ci.yml` : + +``` +test:app: + script: + - phpunit --configuration phpunit_myapp.xml +``` + +最后,推送到 GitLab 并开始测试! + +### Test against different PHP versions in Shell builds[](#test-against-different-php-versions-in-shell-builds "Permalink") + +[phpenv](https://github.com/phpenv/phpenv)项目使您可以轻松管理不同版本的 PHP,每个版本都有自己的配置. 当使用 Shell 执行程序测试 PHP 项目时,这特别有用. + +您必须按照[上游安装指南](https://github.com/phpenv/phpenv#installation)在`gitlab-runner`用户下将其安装在构建计算机[上](https://github.com/phpenv/phpenv#installation) . + +使用 phpenv 还可以通过以下方式轻松配置 PHP 环境: + +``` +phpenv config-add my_config.ini +``` + +***重要说明:**似乎`phpenv/phpenv` [被放弃了](https://github.com/phpenv/phpenv/issues/57) . [madumlao / phpenv](https://github.com/madumlao/phpenv)上有一个分叉,试图使该项目[复活](https://github.com/madumlao/phpenv) . [CHH / phpenv](https://github.com/CHH/phpenv)似乎也是一个不错的选择. 选择任何提到的工具将与基本 phpenv 命令一起使用. 指导您选择正确的 phpenv 不在本教程的范围内.* + +### Install custom extensions[](#install-custom-extensions "Permalink") + +由于这是 PHP 环境的裸机安装,因此您可能需要一些构建机器上当前不存在的扩展. + +要安装其他扩展,只需执行以下命令: + +``` +pecl install <extension> +``` + +不建议将其添加到`.gitlab-ci.yml` . 您应该只执行一次此命令,仅用于设置构建环境. + +## Extend your tests[](#extend-your-tests "Permalink") + +### Using atoum[](#using-atoum "Permalink") + +除了 PHPUnit,您可以使用任何其他工具来运行单元测试. 例如,您可以使用[atoum](https://github.com/atoum/atoum) : + +``` +before_script: + - wget http://downloads.atoum.org/nightly/mageekguy.atoum.phar + +test:atoum: + script: + - php mageekguy.atoum.phar +``` + +### Using Composer[](#using-composer "Permalink") + +大多数 PHP 项目使用 Composer 来管理其 PHP 软件包. 为了在运行测试之前执行 Composer,只需在`.gitlab-ci.yml`添加以下`.gitlab-ci.yml` : + +``` +... + +# Composer stores all downloaded packages in the vendor/ directory. +# Do not use the following if the vendor/ directory is committed to +# your git repository. +cache: + paths: + - vendor/ + +before_script: +# Install composer dependencies + - wget https://composer.github.io/installer.sig -O - -q | tr -d '\n' > installer.sig + - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + - php -r "if (hash_file('SHA384', 'composer-setup.php') === file_get_contents('installer.sig')) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" + - php composer-setup.php + - php -r "unlink('composer-setup.php'); unlink('installer.sig');" + - php composer.phar install + +... +``` + +## Access private packages or dependencies[](#access-private-packages-or-dependencies "Permalink") + +如果您的测试套件需要访问私有存储库,则需要配置[SSH 密钥](../ssh_keys/README.html)才能克隆它. + +## Use databases or other services[](#use-databases-or-other-services "Permalink") + +大多数时候,您将需要一个正在运行的数据库才能运行测试. 如果您使用的是 Docker 执行器,则可以利用 Docker 链接到其他容器的功能. 使用 GitLab Runner,可以通过定义`service`来实现. + +[CI 服务](../services/README.html)文档中涵盖了此功能. + +## Testing things locally[](#testing-things-locally "Permalink") + +使用 GitLab Runner 1.0,您还可以在本地测试所有更改. 从您的终端执行: + +``` +# Check using docker executor +gitlab-runner exec docker test:app + +# Check using shell executor +gitlab-runner exec shell test:app +``` + +## Example project[](#example-project "Permalink") + +为了方便起见,我们建立了一个[示例 PHP 项目](https://gitlab.com/gitlab-examples/php) ,该[项目](https://gitlab.com/gitlab-examples/php)使用我们的公共[共享](../runners/README.html)运行器在[GitLab.com](https://gitlab.com)上运行. + +想要破解吗? 只需对其进行分叉,提交并推送您的更改. 稍后,公共跑步者将选择更改并开始工作. \ No newline at end of file diff --git a/_book/docs/236.md b/_book/docs/236.md new file mode 100644 index 0000000000000000000000000000000000000000..eefebd37bc90e2fcabd066affce9dfe0338504af --- /dev/null +++ b/_book/docs/236.md @@ -0,0 +1,165 @@ +# Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/deployment/composer-npm-deploy.html](https://docs.gitlab.com/ee/ci/examples/deployment/composer-npm-deploy.html) + +* [How to transfer files to a live server](#how-to-transfer-files-to-a-live-server) + * [Security tip](#security-tip) +* [How to deploy](#how-to-deploy) + * [Why we do it this way](#why-we-do-it-this-way) +* [Where to go next](#where-to-go-next) + +# Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD[](#running-composer-and-npm-scripts-with-deployment-via-scp-in-gitlab-cicd "Permalink") + +本指南涵盖了在使用[GitLab CI / CD](../../README.html)通过 NPM 脚本编译资产时,如何构建 PHP 项目的依赖项. + +虽然可以使用自定义的 PHP 和 Node.js 版本创建自己的映像,但为了简便起见,我们将使用既包含 PHP 又安装 Node.js 的现有[Docker 映像](https://hub.docker.com/r/tetraweb/php/) . + +``` +image: tetraweb/php +``` + +下一步是安装 zip / unzip 软件包并使 composer 可用. 我们将它们放在`before_script`部分中: + +``` +before_script: + - apt-get update + - apt-get install zip unzip + - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + - php composer-setup.php + - php -r "unlink('composer-setup.php');" +``` + +这将确保我们已准备好所有要求. 接下来,我们要运行`composer install`来获取所有 PHP 依赖项,然后运行`npm install`来加载 Node.js 包,然后运行`npm`脚本. 我们需要将它们附加到`before_script`部分: + +``` +before_script: + # ... + - php composer.phar install + - npm install + - npm run deploy +``` + +在此特定情况下, `npm deploy`脚本是执行以下操作的 Gulp 脚本: + +1. 编译 CSS 和 JS +2. Create sprites +3. 复制各种资产(图像,字体) +4. 替换一些字符串 + +所有这些操作会将所有文件放入一个`build`文件夹,该文件夹准备好部署到实时服务器中. + +## How to transfer files to a live server[](#how-to-transfer-files-to-a-live-server "Permalink") + +您有多种选择:rsync,SCP,SFTP 等. 现在,我们将使用 SCP. + +为此,您需要添加一个 GitLab CI / CD 变量(可在`gitlab.example/your-project-name/variables` ). 该变量将称为`STAGING_PRIVATE_KEY` ,它是服务器的**私密** SSH 密钥. + +### Security tip[](#security-tip "Permalink") + +创建一个**仅**可以访问需要更新的文件夹的用户. + +创建该变量后,需要确保在运行时将密钥添加到 Docker 容器中: + +``` +before_script: + # - .... + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + - mkdir -p ~/.ssh + - eval $(ssh-agent -s) + - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' +``` + +按顺序,这意味着: + +1. 我们检查`ssh-agent`是否可用,如果没有,则安装它. +2. 我们创建`~/.ssh`文件夹. +3. 我们确保正在运行 bash. +4. 我们禁用主机检查(当我们首次连接到服务器时,我们不要求用户接受,并且由于每个作业都将等同于首次连接,因此我们有点需要这样做). + +这基本上是您在`before_script`部分中所需要的. + +## How to deploy[](#how-to-deploy "Permalink") + +如上所述,我们需要将 Docker 镜像中的`build`文件夹部署到我们的服务器. 为此,我们创建了一个新作业: + +``` +stage_deploy: + artifacts: + paths: + - build/ + only: + - dev + script: + - ssh-add <(echo "$STAGING_PRIVATE_KEY") + - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp" + - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp + - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live" + - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old" +``` + +这是细分: + +1. `only:dev`表示仅当将某些内容推送到`dev`分支时,此构建才会运行. 您可以完全删除此块,并在每次推送时都运行所有内容(但是这可能是您不想要的) +2. `ssh-add ...`我们会将您在 Web UI 上添加的私钥添加到 Docker 容器中 +3. 我们将通过`ssh`连接并创建一个新的`_tmp`文件夹 +4. 我们将通过`scp`连接并将`build`文件夹(由`npm`脚本生成)上传到我们先前创建的`_tmp`文件夹中 +5. 我们将再次通过`ssh`连接,然后将`live`文件夹移至`_old`文件夹,然后将`_tmp`移至`live` . +6. 我们连接到 SSH 并删除`_old`文件夹 + +这些文物怎么处理? 我们只是告诉 GitLab CI / CD 保留`build`目录(以后,您可以根据需要下载该目录). + +### Why we do it this way[](#why-we-do-it-this-way "Permalink") + +如果仅将其用于舞台服务器,则可以分两个步骤进行操作: + +``` +- ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/live/*" +- scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/live +``` + +问题在于,服务器将在短时间内没有该应用程序. + +因此,对于生产环境,我们使用其他步骤来确保在任何给定时间都可以使用功能正常的应用程序. + +## Where to go next[](#where-to-go-next "Permalink") + +由于这是一个 WordPress 项目,因此我给出了真实的代码片段. 您可以追求一些进一步的想法: + +* `master`分支的脚本稍有不同,将使您可以从该分支部署到生产服务器,并从任何其他分支部署到阶段服务器. +* 除了将其实时发布之外,您还可以将其推送到 WordPress 官方存储库(创建 SVN 提交等). +* 您可以动态生成 i18n 文本域. + +* * * + +我们最终的`.gitlab-ci.yml`将如下所示: + +``` +image: tetraweb/php + +before_script: + - apt-get update + - apt-get install zip unzip + - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + - php composer-setup.php + - php -r "unlink('composer-setup.php');" + - php composer.phar install + - npm install + - npm run deploy + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + - mkdir -p ~/.ssh + - eval $(ssh-agent -s) + - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' + +stage_deploy: + artifacts: + paths: + - build/ + only: + - dev + script: + - ssh-add <(echo "$STAGING_PRIVATE_KEY") + - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp" + - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp + - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live" + - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old" +``` \ No newline at end of file diff --git a/_book/docs/237.md b/_book/docs/237.md new file mode 100644 index 0000000000000000000000000000000000000000..0bd7654e9b9d3d29578b11e353fcfe9d30937192 --- /dev/null +++ b/_book/docs/237.md @@ -0,0 +1,644 @@ +# Test and deploy Laravel applications with GitLab CI/CD and Envoy + +> 原文:[https://docs.gitlab.com/ee/ci/examples/laravel_with_gitlab_and_envoy/](https://docs.gitlab.com/ee/ci/examples/laravel_with_gitlab_and_envoy/) + +* [Introduction](#introduction) +* [Initialize our Laravel app on GitLab](#initialize-our-laravel-app-on-gitlab) + * [Unit Test](#unit-test) + * [Push to GitLab](#push-to-gitlab) +* [Configure the production server](#configure-the-production-server) + * [Create a new user](#create-a-new-user) + * [Add SSH key](#add-ssh-key) + * [Configuring NGINX](#configuring-nginx) +* [Setting up Envoy](#setting-up-envoy) + * [How Envoy works](#how-envoy-works) + * [Zero downtime deployment](#zero-downtime-deployment) + * [@setup directive](#setup-directive) + * [@story directive](#story-directive) + * [Clone the repository](#clone-the-repository) + * [Installing dependencies with Composer](#installing-dependencies-with-composer) + * [Activate new release](#activate-new-release) + * [Full script](#full-script) +* [Continuous Integration with GitLab](#continuous-integration-with-gitlab) + * [Create a Container Image](#create-a-container-image) + * [Setting Up GitLab Container Registry](#setting-up-gitlab-container-registry) + * [Setting up GitLab CI/CD](#setting-up-gitlab-cicd) + * [Image and Services](#image-and-services) + * [Variables](#variables) + * [Unit Test as the first job](#unit-test-as-the-first-job) + * [Deploy to production](#deploy-to-production) + * [Turn on GitLab CI/CD](#turn-on-gitlab-cicd) +* [Conclusion](#conclusion) + +# Test and deploy Laravel applications with GitLab CI/CD and Envoy[](#test-and-deploy-laravel-applications-with-gitlab-cicd-and-envoy "Permalink") + +## Introduction[](#introduction "Permalink") + +GitLab 通过持续集成为我们的应用程序提供功能,并且可以随时将新的代码更改轻松部署到生产服务器. + +在本教程中,我们将向您展示如何初始化[Laravel](https://s0laravel0com.icopy.site)应用程序并设置[Envoy](https://s0laravel0com.icopy.site/docs/master/envoy)任务,然后我们将跳入如何使用[GitLab CI / CD](../README.html)通过[Continuous Delivery](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/)测试和部署它的方法. + +我们假设您具有 Laravel 和 Linux 服务器的基本经验,并且知道如何使用 GitLab. + +Laravel 是一个用 PHP 编写的高质量 Web 框架. 它有一个很棒的社区,提供了[很棒的文档](https://s0laravel0com.icopy.site/docs) . 除了常规的路由,控制器,请求,响应,视图和(刀片)模板外,Laravel 还提供了许多其他服务,例如缓存,事件,本地化,身份验证以及许多其他服务. + +我们将使用[Envoy](https://s0laravel0com.icopy.site/docs/master/envoy)作为基于 PHP 的 SSH 任务运行程序. 它使用简洁的[Blade 语法](https://s0laravel0com.icopy.site/docs/master/blade)来设置可以在远程服务器上运行的任务,例如,从存储库克隆项目,安装 Composer 依赖项以及运行[Artisan 命令](https://s0laravel0com.icopy.site/docs/master/artisan) . + +## Initialize our Laravel app on GitLab[](#initialize-our-laravel-app-on-gitlab "Permalink") + +我们假设[您已经安装了一个新的 Laravel 项目](https://s0laravel0com.icopy.site/docs/master/installation) ,所以让我们从单元测试开始,并为该项目初始化 Git. + +### Unit Test[](#unit-test "Permalink") + +Laravel 的每个新安装(当前为 5.4)都在测试目录中放置了两种类型的测试:"功能"和"单元". 这是来自`test/Unit/ExampleTest.php`的单元测试: + +``` +<?php + +namespace Tests\Unit; + +... + +class ExampleTest extends TestCase +{ + public function testBasicTest() + { + $this->assertTrue(true); + } +} +``` + +该测试就像断言给定值是 true 一样简单. + +Laravel 默认使用`PHPUnit`进行测试. 如果运行`vendor/bin/phpunit`我们应该看到绿色输出: + +``` +vendor/bin/phpunit +OK (1 test, 1 assertions) +``` + +该测试将在以后用于通过 GitLab CI / CD 持续测试我们的应用程序. + +### Push to GitLab[](#push-to-gitlab "Permalink") + +由于我们已经在本地启动并运行了应用程序,因此现在是将代码库推送到我们的远程存储库的时候了. 让我们在 GitLab 中创建[一个](../../../gitlab-basics/create-project.html)名为`laravel-sample` [的新项目](../../../gitlab-basics/create-project.html) . 之后,按照项目主页上显示的命令行说明在我们的计算机上启动存储库并推送第一个提交. + +``` +cd laravel-sample +git init +git remote add origin git@gitlab.example.com:<USERNAME>/laravel-sample.git +git add . +git commit -m 'Initial Commit' +git push -u origin master +``` + +## Configure the production server[](#configure-the-production-server "Permalink") + +在开始设置 Envoy 和 GitLab CI / CD 之前,让我们快速确保生产服务器已准备好进行部署. 我们已经在 Ubuntu 16.04 上安装了 LEMP 堆栈,该堆栈代表 Linux,NGINX,MySQL 和 PHP. + +### Create a new user[](#create-a-new-user "Permalink") + +现在,让我们创建一个新用户,该用户将用于部署我们的网站并使用[Linux ACL](https://serversforhackers.com/c/linux-acls)为其授予所需的权限: + +``` +# Create user deployer +sudo adduser deployer +# Give the read-write-execute permissions to deployer user for directory /var/www +sudo setfacl -R -m u:deployer:rwx /var/www +``` + +如果您的 Ubuntu 服务器上未安装 ACL,请使用以下命令进行安装: + +``` +sudo apt install acl +``` + +### Add SSH key[](#add-ssh-key "Permalink") + +假设我们要从 GitLab 上的私有存储库将应用程序部署到生产服务器. 首先,我们需要为部署者用户[生成一个**没有密码短语**的新 SSH 密钥对](../../../ssh/README.html) . + +之后,我们需要复制私钥,以使用 SSH 作为部署者用户将其用于连接到我们的服务器,以便能够自动化部署过程: + +``` +# As the deployer user on server +# +# Copy the content of public key to authorized_keys +cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys +# Copy the private key text block +cat ~/.ssh/id_rsa +``` + +现在,让我们将其作为[变量](../../variables/README.html#gitlab-cicd-environment-variables)添加到您的 GitLab 项目中. 变量是用户定义的变量,出于安全目的,它们存储在`.gitlab-ci.yml` . 可以通过导航到项目的**设置** > **CI / CD**来为每个项目添加它们. + +在**KEY**字段中,添加名称`SSH_PRIVATE_KEY` ,然后在**VALUE**字段中,粘贴您先前复制的私钥. 稍后,我们将在`.gitlab-ci.yml`使用此变量,以轻松地以部署者用户身份连接到我们的远程服务器,而无需输入其密码. + +[![variables page](img/a51fbcc597a6bc32e35c13c31799e36c.png)](img/variables_page.png) + +我们还需要将公共密钥作为[部署密钥](../../../ssh/README.html#deploy-keys)添加到" **项目"** > **"设置"** >" **存储库"** ,这使我们能够通过[SSH 协议](../../../gitlab-basics/command-line-commands.html#start-working-on-your-project)从服务器访问存储库. + +``` +# As the deployer user on the server +# +# Copy the public key +cat ~/.ssh/id_rsa.pub +``` + +在" **标题** "字段中,添加所需的任何名称,然后将公共密钥粘贴到" **密钥"**字段中. + +[![deploy keys page](img/9443fbb9f077bc7be6beb1486c392c96.png)](img/deploy_keys_page.png) + +现在,让我们在服务器上克隆存储库,以确保`deployer`用户可以访问该存储库. + +``` +# As the deployer user on server +# +git clone git@gitlab.example.com:<USERNAME>/laravel-sample.git +``` + +> **注意:**如果询问, **请**回答**是.** `Are you sure you want to continue connecting (yes/no)?` . 它将 GitLab.com 添加到已知主机. + +### Configuring NGINX[](#configuring-nginx "Permalink") + +现在,让我们确保我们的 Web 服务器配置指向`current/public`而不是`public` . + +通过键入以下内容来打开默认的 NGINX 服务器块配置文件: + +``` +sudo nano /etc/nginx/sites-available/default +``` + +配置应该是这样的. + +``` +server { + root /var/www/app/current/public; + server_name example.com; + # Rest of the configuration +} +``` + +> **注意:**您可以将`/var/www/app/current/public`的应用程序名称替换为应用程序的文件夹名称. + +## Setting up Envoy[](#setting-up-envoy "Permalink") + +因此,我们已经准备好生产 Laravel 应用. 接下来是使用 Envoy 执行部署. + +要使用 Envoy,我们应该首先[按照 Laravel 给出的说明](https://s0laravel0com.icopy.site/docs/master/envoy/)将其安装在本地计算机上. + +### How Envoy works[](#how-envoy-works "Permalink") + +Envoy 的优点是它不需要 Blade 引擎,只使用 Blade 语法定义任务. 首先,我们在应用程序的根目录中创建一个`Envoy.blade.php` ,其中包含一个简单的测试 Envoy 的任务. + +``` +@servers(['web' => 'remote_username@remote_host']) + +@task('list', ['on' => 'web']) + ls -l +@endtask +``` + +如您所料,我们在文件顶部的`@servers`指令中有一个数组,其中包含一个名为`web`的键,其值为服务器地址的值(例如, `deployer@192.168.1.1` 192.168.1.1). 然后,在我们的`@task`指令中,定义执行任务时应在服务器上运行的 bash 命令. + +在本地计算机上,使用`run`命令运行 Envoy 任务. + +``` +envoy run list +``` + +它应该执行我们之前定义的`list`任务,该任务连接到服务器并列出目录内容. + +Envoy 不是 Laravel 的依赖项,因此您可以将其用于任何 PHP 应用程序. + +### Zero downtime deployment[](#zero-downtime-deployment "Permalink") + +每次我们部署到生产服务器时,Envoy 都会从 GitLab 存储库下载我们应用程序的最新版本,并将其替换为预览版本. Envoy 做到了这一点,没有任何[停机时间](https://en.wikipedia.org/wiki/Downtime) ,因此我们在部署过程中不必担心有人在审查站点. 我们的部署计划是从 GitLab 存储库克隆最新版本,安装 Composer 依赖项,最后激活新版本. + +#### [@setup](https://gitlab.com/setup) directive[](#setup-directive "Permalink") + +我们部署过程的第一步是在内部定义一组变量 [](https://s0laravel0com.icopy.site/docs/master/envoy/)[@setup](https://gitlab.com/setup)指令. 您可以将`app`更改为您的应用名称: + +``` +... + +@setup + $repository = 'git@gitlab.example.com:<USERNAME>/laravel-sample.git'; + $releases_dir = '/var/www/app/releases'; + $app_dir = '/var/www/app'; + $release = date('YmdHis'); + $new_release_dir = $releases_dir .'/'. $release; +@endsetup + +... +``` + +* `$repository`是我们存储库的地址 +* `$releases_dir`目录是我们部署应用程序的位置 +* `$app_dir`是服务器上实时存在的应用程序的实际位置 +* `$release` contains a date, so every time that we deploy a new release of our app, we get a new folder with the current date as name +* `$new_release_dir`是新版本的完整路径,仅用于使任务更整洁 + +#### [@story](https://gitlab.com/story) directive[](#story-directive "Permalink") + +的 [](https://s0laravel0com.icopy.site/docs/master/envoy/)[@story](https://gitlab.com/story)指令允许我们定义可以作为单个任务运行的任务列表. 在这里,我们有三个任务,称为`clone_repository` , `run_composer`和`update_symlinks` . 这些变量可用于使我们的任务代码更清晰: + +``` +... + +@story('deploy') + clone_repository + run_composer + update_symlinks +@endstory + +... +``` + +让我们一一创建这三个任务. + +#### Clone the repository[](#clone-the-repository "Permalink") + +第一个任务将创建`releases`目录(如果不存在),然后将存储库的`master`分支(默认情况下)克隆到由`$new_release_dir`变量指定的新 release 目录中. `releases`目录将包含我们所有的部署: + +``` +... + +@task('clone_repository') + echo 'Cloning repository' + [ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }} + git clone --depth 1 {{ $repository }} {{ $new_release_dir }} + cd {{ $new_release_dir }} + git reset --hard {{ $commit }} +@endtask + +... +``` + +随着我们项目的发展,它的 Git 历史将随着时间的流逝而持续很长时间. 由于我们为每个版本创建一个目录,因此不必为每个版本下载项目的历史记录. `--depth 1`选项是一个很好的解决方案, `--depth 1`可以节省系统时间和磁盘空间. + +#### Installing dependencies with Composer[](#installing-dependencies-with-composer "Permalink") + +您可能知道,此任务只是导航到新的发行目录并运行 Composer 来安装应用程序依赖项: + +``` +... + +@task('run_composer') + echo "Starting deployment ({{ $release }})" + cd {{ $new_release_dir }} + composer install --prefer-dist --no-scripts -q -o +@endtask + +... +``` + +#### Activate new release[](#activate-new-release "Permalink") + +在准备好新版本的要求之后,接下来要做的就是从其中删除存储目录,并创建两个符号链接,以将应用程序的`storage`目录和`.env`文件指向新版本. 然后,我们需要创建另一个符号链接到新版本用的名称`current`放置在 app 目录. `current`符号链接始终指向我们应用程序的最新版本: + +``` +... + +@task('update_symlinks') + echo "Linking storage directory" + rm -rf {{ $new_release_dir }}/storage + ln -nfs {{ $app_dir }}/storage {{ $new_release_dir }}/storage + + echo 'Linking .env file' + ln -nfs {{ $app_dir }}/.env {{ $new_release_dir }}/.env + + echo 'Linking current release' + ln -nfs {{ $new_release_dir }} {{ $app_dir }}/current +@endtask +``` + +如您所见,我们使用`-nfs`作为`ln`命令的选项,它表示`storage` , `.env`和`current`不再指向预览的发行版, `-nfs`通过强制将它们指向新发行版( `-nfs` `f`表示强制) ,这是我们进行多个部署的情况. + +### Full script[](#full-script "Permalink") + +脚本已准备就绪,但请确保将`deployer@192.168.1.1`更改为服务器,并使用要部署应用程序的目录更改`/var/www/app` app. + +最后,我们的`Envoy.blade.php`文件将如下所示: + +``` +@servers(['web' => 'deployer@192.168.1.1']) + +@setup + $repository = 'git@gitlab.example.com:<USERNAME>/laravel-sample.git'; + $releases_dir = '/var/www/app/releases'; + $app_dir = '/var/www/app'; + $release = date('YmdHis'); + $new_release_dir = $releases_dir .'/'. $release; +@endsetup + +@story('deploy') + clone_repository + run_composer + update_symlinks +@endstory + +@task('clone_repository') + echo 'Cloning repository' + [ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }} + git clone --depth 1 {{ $repository }} {{ $new_release_dir }} + cd {{ $new_release_dir }} + git reset --hard {{ $commit }} +@endtask + +@task('run_composer') + echo "Starting deployment ({{ $release }})" + cd {{ $new_release_dir }} + composer install --prefer-dist --no-scripts -q -o +@endtask + +@task('update_symlinks') + echo "Linking storage directory" + rm -rf {{ $new_release_dir }}/storage + ln -nfs {{ $app_dir }}/storage {{ $new_release_dir }}/storage + + echo 'Linking .env file' + ln -nfs {{ $app_dir }}/.env {{ $new_release_dir }}/.env + + echo 'Linking current release' + ln -nfs {{ $new_release_dir }} {{ $app_dir }}/current +@endtask +``` + +在进行任何部署之前,我们应该做的另一件事是第一次将我们的应用程序`storage`文件夹手动复制到服务器上的`/var/www/app`目录. 您可能想要创建另一个 Envoy 任务来为您完成此任务. 我们还在同一路径中创建`.env`文件, `.env`设置生产环境变量. 这些是永久性数据,将与每个新版本共享. + +现在,我们需要通过运行`envoy run deploy`来部署我们的应用程序,但这不是必需的,因为 GitLab 可以在 CI 的[环境下](../../environments/index.html)为我们处理此事,这将在本教程的[后面部分](#setting-up-gitlab-cicd)进行介绍. + +现在是时候提交[Envoy.blade.php](https://gitlab.com/mehranrasulian/laravel-sample/blob/master/Envoy.blade.php)并将其推送到`master`分支了. 为了简化起见,我们直接致力于`master` ,而无需使用[功能分支,](../../../topics/gitlab_flow.html#github-flow-as-a-simpler-alternative)因为协作不在本教程的讨论范围之内. 在现实世界的项目中,团队可以使用[问题跟踪程序](../../../user/project/issues/index.html)和[合并请求](../../../user/project/merge_requests/index.html)在分支之间移动代码: + +``` +git add Envoy.blade.php +git commit -m 'Add Envoy' +git push origin master +``` + +## Continuous Integration with GitLab[](#continuous-integration-with-gitlab "Permalink") + +我们已经在 GitLab 上准备好了我们的应用程序,我们也可以手动部署它. 但是,让我们向前迈出一步,使用" [持续交付"](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-delivery)方法自动完成此操作. 我们需要使用一组自动化测试来检查每个提交,以尽早发现问题,然后,如果我们对测试结果感到满意,则可以将其部署到目标环境. + +[GitLab CI / CD](../../README.html)允许我们使用[Docker](https://www.docker.com)引擎来处理测试和部署应用程序的过程. 如果您不熟悉 Docker,请参阅[如何自动化 Docker 部署](http://paislee.io/how-to-automate-docker-deployments/) . + +为了能够使用 GitLab CI / CD 构建,测试和部署我们的应用程序,我们需要准备工作环境. 为此,我们将使用具有 Laravel 应用程序运行最低要求的 Docker 映像. [也有其他方法](../php.html#test-php-projects-using-the-docker-executor)可以执行此操作,但是它们可能会使我们的构建运行缓慢,而在使用更快的选项时,这不是我们想要的. + +有了 Docker 映像,我们的构建运行得异常快! + +### Create a Container Image[](#create-a-container-image "Permalink") + +让我们在应用程序的根目录中创建一个[包含](https://gitlab.com/mehranrasulian/laravel-sample/blob/master/Dockerfile)以下内容的[Dockerfile](https://gitlab.com/mehranrasulian/laravel-sample/blob/master/Dockerfile) : + +``` +# Set the base image for subsequent instructions +FROM php:7.1 + +# Update packages +RUN apt-get update + +# Install PHP and composer dependencies +RUN apt-get install -qq git curl libmcrypt-dev libjpeg-dev libpng-dev libfreetype6-dev libbz2-dev + +# Clear out the local repository of retrieved package files +RUN apt-get clean + +# Install needed extensions +# Here you can install any other extension that you need during the test and deployment process +RUN docker-php-ext-install mcrypt pdo_mysql zip + +# Install Composer +RUN curl --silent --show-error https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Install Laravel Envoy +RUN composer global require "laravel/envoy=~1.0" +``` + +我们添加了[官方的 PHP 7.1 Docker 映像](https://hub.docker.com/_/php) ,该[映像](https://hub.docker.com/_/php)由 Debian Jessie 的最低安装和预安装的 PHP 组成,并且非常适合我们的用例. + +我们使用了`docker-php-ext-install` (由官方 PHP Docker 映像提供)来安装所需的 PHP 扩展. + +#### Setting Up GitLab Container Registry[](#setting-up-gitlab-container-registry "Permalink") + +现在我们有了`Dockerfile`让我们构建并将其推送到[GitLab 容器注册表](../../../user/packages/container_registry/index.html) . + +> 注册表是存储和标记图像以供以后使用的地方. 开发人员可能希望维护自己的注册表,以用于私人,公司映像或仅用于测试的一次性映像. 使用 GitLab 容器注册表意味着您无需设置和管理另一项服务或使用公共注册表. + +在您的 GitLab 项目存储库上,导航到" **注册表"**选项卡. + +[![container registry page empty image](img/31d242e54217fe005ee1481fbb81c786.png)](img/container_registry_page_empty_image.png) + +您可能需要对项目[启用 Container Registry](../../../user/packages/container_registry/index.html#enable-the-container-registry-for-your-project)才能看到此选项卡. 您可以在项目的**设置>常规>可见性,项目功能,权限**下找到它. + +要在我们的机器上开始使用 Container Registry,我们首先需要使用我们的 GitLab 用户名和密码登录到 GitLab 注册表: + +``` +docker login registry.gitlab.com +``` + +然后,我们可以构建图像并将其推送到 GitLab: + +``` +docker build -t registry.gitlab.com/<USERNAME>/laravel-sample . + +docker push registry.gitlab.com/<USERNAME>/laravel-sample +``` + +> **注意:**要运行上述命令,我们首先需要在计算机上安装[Docker](https://s0docs0docker0com.icopy.site/engine/installation/) . + +恭喜你! 您刚刚将第一个 Docker 映像推送到了 GitLab 注册表,如果刷新页面,您应该可以看到它: + +[![container registry page with image](img/771e5d2c3cbeba5811f78938b976dfdf.png)](img/container_registry_page_with_image.jpg) + +> **注意:**您也可以[使用 GitLab CI / CD](https://about.gitlab.com/blog/2016/05/23/gitlab-container-registry/#use-with-gitlab-ci)来构建和推送 Docker 映像,而不是在计算机上执行. + +我们将在`.gitlab-ci.yml`配置文件中进一步使用此图像,以处理测试和部署我们的应用程序的过程. + +让我们提交`Dockerfile`文件. + +``` +git add Dockerfile +git commit -m 'Add Dockerfile' +git push origin master +``` + +### Setting up GitLab CI/CD[](#setting-up-gitlab-cicd "Permalink") + +为了使用 GitLab CI / CD 构建和测试我们的应用程序,我们需要在存储库的根目录中有一个名为`.gitlab-ci.yml`的文件. 它类似于 Circle CI 和 Travis CI,但内置 GitLab. + +我们的`.gitlab-ci.yml`文件将如下所示: + +``` +image: registry.gitlab.com/<USERNAME>/laravel-sample:latest + +services: + - mysql:5.7 + +variables: + MYSQL_DATABASE: homestead + MYSQL_ROOT_PASSWORD: secret + DB_HOST: mysql + DB_USERNAME: root + +stages: + - test + - deploy + +unit_test: + stage: test + script: + - cp .env.example .env + - composer install + - php artisan key:generate + - php artisan migrate + - vendor/bin/phpunit + +deploy_production: + stage: deploy + script: + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + - eval $(ssh-agent -s) + - ssh-add <(echo "$SSH_PRIVATE_KEY") + - mkdir -p ~/.ssh + - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' + + - ~/.composer/vendor/bin/envoy run deploy --commit="$CI_COMMIT_SHA" + environment: + name: production + url: http://192.168.1.1 + when: manual + only: + - master +``` + +需要很多东西,不是吗? 让我们逐步进行操作. + +#### Image and Services[](#image-and-services "Permalink") + +[GitLab Runners](../../runners/README.html)运行`.gitlab-ci.yml`定义的脚本. `image`关键字告诉跑步者要使用哪个图像. `services`关键字定义[链接到主图像的其他图像](../../docker/using_docker_images.html#what-is-a-service) . 在这里,我们将之前创建的容器映像用作主映像,还将 MySQL 5.7 用作服务. + +``` +image: registry.gitlab.com/<USERNAME>/laravel-sample:latest + +services: + - mysql:5.7 + +... +``` + +> **注意:**如果要使用不同的 PHP 版本和[数据库管理系统](../../services/README.html)测试应用程序,则可以为每个测试作业定义不同的`image`和`services`关键字. + +#### Variables[](#variables "Permalink") + +GitLab CI / CD 允许我们在工作中使用[环境变量](../../yaml/README.html#variables) . 我们将 MySQL 定义为数据库管理系统,它带有默认创建的超级用户根. + +因此,我们应该通过将`MYSQL_DATABASE`变量定义为数据库名称并将`MYSQL_ROOT_PASSWORD`变量定义为`root`的密码来调整 MySQL 实例的配置. 在[官方的 MySQL Docker Image 中](https://hub.docker.com/_/mysql)找到有关 MySQL 变量的更多信息. + +还要将变量`DB_HOST`设置为`mysql` ,将`DB_USERNAME`为`root` ,这是 Laravel 特定的变量. 我们将`DB_HOST`定义为`mysql`而不是`127.0.0.1` ,因为我们将 MySQL Docker 映像用作[与主 Docker 映像链接](../../docker/using_docker_images.html#how-services-are-linked-to-the-job)的服务. + +``` +... + +variables: + MYSQL_DATABASE: homestead + MYSQL_ROOT_PASSWORD: secret + DB_HOST: mysql + DB_USERNAME: root + +... +``` + +#### Unit Test as the first job[](#unit-test-as-the-first-job "Permalink") + +我们将所需的外壳程序脚本定义为运行`unit_test`作业时要执行的[脚本](../../yaml/README.html#script)变量的数组. + +These scripts are some Artisan commands to prepare the Laravel, and, at the end of the script, we’ll run the tests by `PHPUnit`. + +``` +... + +unit_test: + script: + # Install app dependencies + - composer install + # Set up .env + - cp .env.example .env + # Generate an environment key + - php artisan key:generate + # Run migrations + - php artisan migrate + # Run tests + - vendor/bin/phpunit + +... +``` + +#### Deploy to production[](#deploy-to-production "Permalink") + +`deploy_production`作业会将应用程序部署到生产服务器. 要使用 Envoy 部署我们的应用程序,我们必须将`$SSH_PRIVATE_KEY`变量设置为[SSH 私钥](../../ssh_keys/README.html#ssh-keys-when-using-the-docker-executor) . 如果 SSH 密钥已成功添加,我们可以运行 Envoy. + +如前所述,GitLab 也支持[持续交付](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-delivery)方法. [环境](../../yaml/README.html#environment)关键字告诉 GitLab 该作业已部署到`production`环境. `url`关键字用于在 GitLab 环境页面上生成指向我们应用程序的链接. `only`关键字告诉 GitLab CI / CD 只有在管道正在构建`master`分支时才应执行作业. 最后, `when: manual`用于将作业从自动运行转变为手动操作. + +``` +... + +deploy_production: + script: + # Add the private SSH key to the build environment + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + - eval $(ssh-agent -s) + - ssh-add <(echo "$SSH_PRIVATE_KEY") + - mkdir -p ~/.ssh + - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' + + # Run Envoy + - ~/.composer/vendor/bin/envoy run deploy + + environment: + name: production + url: http://192.168.1.1 + when: manual + only: + - master +``` + +您可能还需要为[登台环境](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/)添加另一个作业,以便在部署到生产[环境](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/)之前对应用程序进行最终测试. + +### Turn on GitLab CI/CD[](#turn-on-gitlab-cicd "Permalink") + +我们已经准备好使用 GitLab CI / CD 测试和部署应用程序所需的一切. 为此,请提交`.gitlab-ci.yml`并将其推入`master`分支. 它将触发管道,您可以在项目的**Pipelines**下实时观看. + +[![pipelines page](img/3ca3bc9234ff248b19d9555bb5f1cff4.png)](img/pipelines_page.png) + +Here we see our **Test** and **Deploy** stages. The **Test** stage has the `unit_test` build running. click on it to see the Runner’s output. + +[![pipeline page](img/55c6a94e74c9a00da3a400ae60e3bf41.png)](img/pipeline_page.png) + +代码成功通过管道后,我们可以通过单击右侧的**播放**按钮将其部署到生产服务器. + +[![pipelines page deploy button](img/52c8f25cfabbe64b4ed7e579d9a27e4a.png)](img/pipelines_page_deploy_button.png) + +部署管道成功通过后,导航至" **管道">"环境"** . + +[![environments page](img/d0e9aaf43b9e19912342dddfb4b6be13.png)](img/environments_page.png) + +如果某些操作无法正常工作,则可以回滚到应用程序的最新工作版本. + +[![environment page](img/bd8c2bfd77b1834503e87e4dc5b58420.png)](img/environment_page.png) + +通过单击右侧指定的外部链接图标,GitLab 将打开生产网站. 我们的部署成功完成,我们可以看到该应用程序正在运行. + +[![Laravel welcome page](img/c6a214b87abe3ccc6a5287ea1d256834.png)](img/laravel_welcome_page.png) + +如果您想了解部署后生产服务器上的应用程序目录结构如何,这里有三个目录,分别名为`current` , `releases`和`storage` . 如您所知, `current`目录是指向最新版本的符号链接. `.env`文件包含我们的 Laravel 环境变量. + +[![production server app directory](img/262e648fe4e99ca02b386ebade539097.png)](img/production_server_app_directory.png) + +如果导航到`current`目录,则应该看到应用程序的内容. 如您所见, `.env`指向`/var/www/app/.env`文件, `storage`也指向`/var/www/app/storage/`目录. + +[![production server current directory](img/6ad15d363481e18f443e6709fc8d1368.png)](img/production_server_current_directory.png) + +## Conclusion[](#conclusion "Permalink") + +我们将 GitLab CI / CD 配置为执行自动化测试,并使用" [持续交付](https://continuousdelivery.com/) "方法直接从代码库部署到带有 Envoy 的 Laravel 应用程序. + +Envoy 也非常适合帮助我们在不编写自定义 bash 脚本和进行 Linux 魔术的情况下部署应用程序. \ No newline at end of file diff --git a/_book/docs/238.md b/_book/docs/238.md new file mode 100644 index 0000000000000000000000000000000000000000..53ddd23f9e79ed7dd8138ce1524bb469c0e583d5 --- /dev/null +++ b/_book/docs/238.md @@ -0,0 +1,97 @@ +# Test and deploy a Python application with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/test-and-deploy-python-application-to-heroku.html](https://docs.gitlab.com/ee/ci/examples/test-and-deploy-python-application-to-heroku.html) + +* [Configure project](#configure-project) +* [Store API keys](#store-api-keys) +* [Create Heroku application](#create-heroku-application) +* [Create Runner](#create-runner) + +# Test and deploy a Python application with GitLab CI/CD[](#test-and-deploy-a-python-application-with-gitlab-cicd "Permalink") + +本示例将指导您如何在 Python 应用程序中运行测试,以及如何将其自动部署为 Heroku 应用程序. + +您也可以查看或生成完整的[示例源](https://gitlab.com/ayufan/python-getting-started) . + +## Configure project[](#configure-project "Permalink") + +这是此项目的`.gitlab-ci.yml`文件的外观: + +``` +stages: + - test + - deploy + +test: + stage: test + script: + # this configures Django application to use attached postgres database that is run on `postgres` host + - export DATABASE_URL=postgres://postgres:@postgres:5432/python-test-app + - apt-get update -qy + - apt-get install -y python-dev python-pip + - pip install -r requirements.txt + - python manage.py test + +staging: + stage: deploy + script: + - apt-get update -qy + - apt-get install -y ruby-dev + - gem install dpl + - dpl --provider=heroku --app=gitlab-ci-python-test-staging --api-key=$HEROKU_STAGING_API_KEY + only: + - master + +production: + stage: deploy + script: + - apt-get update -qy + - apt-get install -y ruby-dev + - gem install dpl + - dpl --provider=heroku --app=gitlab-ci-python-test-prod --api-key=$HEROKU_PRODUCTION_API_KEY + only: + - tags +``` + +这个项目有三个工作: + +* `test` -用于测试 Django 应用程序. +* `staging` -用于每次推送到`master`分支时自动部署登台环境. +* `production` -用于为每个创建的标签自动部署生产环境. + +## Store API keys[](#store-api-keys "Permalink") + +您需要在 GitLab 项目的**"设置">" CI / CD">"环境变量"**中创建两个变量: + +* `HEROKU_STAGING_API_KEY` -Heroku API 密钥,用于部署登台应用程序. +* `HEROKU_PRODUCTION_API_KEY` -Heroku API 密钥,用于部署生产应用程序. + +在" [管理帐户"中](https://dashboard.heroku.com/account)找到您的 Heroku API 密钥. + +## Create Heroku application[](#create-heroku-application "Permalink") + +对于每个环境,您都需要创建一个新的 Heroku 应用程序. 您可以通过[仪表板](https://dashboard.heroku.com/)执行此操作. + +## Create Runner[](#create-runner "Permalink") + +首先安装[Docker Engine](https://s0docs0docker0com.icopy.site/installation/) . + +要构建此项目,您还需要安装[GitLab Runner](https://docs.gitlab.com/runner/index.html) . 您可以使用`gitlab.com`上的公共跑步者,也可以注册自己的跑步者: + +``` +cat > /tmp/test-config.template.toml << EOF [[runners]] +[runners.docker] +[[runners.docker.services]] +name = "postgres:latest" EOF gitlab-runner register \ + --non-interactive \ + --url "https://gitlab.com/" \ + --registration-token "PROJECT_REGISTRATION_TOKEN" \ + --description "python-3.5" \ + --executor "docker" \ + --template-config /tmp/test-config.template.toml \ + --docker-image python:3.5 +``` + +使用上面的命令,您将创建一个使用[`python:3.5`](https://hub.docker.com/_/python)图像并使用[PostgreSQL](https://hub.docker.com/_/postgres)数据库的运行器. + +要访问 PostgreSQL 数据库,请以没有密码的用户`postgres`身份连接到`host: postgres` . \ No newline at end of file diff --git a/_book/docs/239.md b/_book/docs/239.md new file mode 100644 index 0000000000000000000000000000000000000000..9d9a7b7a174627eee18583ad49ac36418f945fd0 --- /dev/null +++ b/_book/docs/239.md @@ -0,0 +1,94 @@ +# Test and deploy a Ruby application with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/test-and-deploy-ruby-application-to-heroku.html](https://docs.gitlab.com/ee/ci/examples/test-and-deploy-ruby-application-to-heroku.html) + +* [Configure the project](#configure-the-project) +* [Store API keys](#store-api-keys) +* [Create Heroku application](#create-heroku-application) +* [Create Runner](#create-runner) + +# Test and deploy a Ruby application with GitLab CI/CD[](#test-and-deploy-a-ruby-application-with-gitlab-cicd "Permalink") + +该示例将指导您如何在 Ruby on Rails 应用程序中运行测试,以及如何将其自动部署为 Heroku 应用程序. + +您还可以查看或派生完整的[示例源,](https://gitlab.com/ayufan/ruby-getting-started)并查看其过去[CI 作业](https://gitlab.com/ayufan/ruby-getting-started/-/jobs?scope=finished)的日志. + +## Configure the project[](#configure-the-project "Permalink") + +这是此项目的`.gitlab-ci.yml`文件的外观: + +``` +test: + stage: test + script: + - apt-get update -qy + - apt-get install -y nodejs + - bundle install --path /cache + - bundle exec rake db:create RAILS_ENV=test + - bundle exec rake test + +staging: + stage: deploy + script: + - gem install dpl + - dpl --provider=heroku --app=gitlab-ci-ruby-test-staging --api-key=$HEROKU_STAGING_API_KEY + only: + - master + +production: + stage: deploy + script: + - gem install dpl + - dpl --provider=heroku --app=gitlab-ci-ruby-test-prod --api-key=$HEROKU_PRODUCTION_API_KEY + only: + - tags +``` + +这个项目有三个工作: + +* `test` -用于测试 Rails 应用程序. +* `staging` -用于每次推送到`master`分支时自动部署登台环境. +* `production` -用于为每个创建的标签自动部署生产环境. + +## Store API keys[](#store-api-keys "Permalink") + +您需要在项目的**设置> CI / CD>环境变量中**创建两个**变量** : + +* `HEROKU_STAGING_API_KEY` -Heroku API 密钥,用于部署登台应用程序. +* `HEROKU_PRODUCTION_API_KEY` -Heroku API 密钥,用于部署生产应用程序. + +Find your Heroku API key in [Manage Account](https://dashboard.heroku.com/account). + +## Create Heroku application[](#create-heroku-application "Permalink") + +对于每个环境,您都需要创建一个新的 Heroku 应用程序. 您可以通过[Heroku 仪表板](https://dashboard.heroku.com/)执行此操作. + +## Create Runner[](#create-runner "Permalink") + +首先安装[Docker Engine](https://s0docs0docker0com.icopy.site/installation/) . + +要构建此项目,您还需要安装[GitLab Runner](https://docs.gitlab.com/runner/) . 您可以使用`gitlab.com`上的公共跑步者或注册自己的跑步者. 首先创建模板配置文件以通过复杂的配置: + +``` +cat > /tmp/test-config.template.toml << EOF [[runners]] +[runners.docker] +[[runners.docker.services]] +name = "postgres:latest" EOF +``` + +最后,注册运行器,并传递新创建的模板配置文件: + +``` +gitlab-runner register \ + --non-interactive \ + --url "https://gitlab.com/" \ + --registration-token "PROJECT_REGISTRATION_TOKEN" \ + --description "ruby:2.6" \ + --executor "docker" \ + --template-config /tmp/test-config.template.toml \ + --docker-image ruby:2.6 +``` + +使用上面的命令,您将创建一个使用[`ruby:2.6`](https://hub.docker.com/_/ruby)图像并使用[PostgreSQL](https://hub.docker.com/_/postgres)数据库的 Runner. + +要访问 PostgreSQL 数据库,请以没有密码的用户`postgres`身份连接到`host: postgres` . \ No newline at end of file diff --git a/_book/docs/240.md b/_book/docs/240.md new file mode 100644 index 0000000000000000000000000000000000000000..c4cc0864baf52886caefa405f4500acbe51c1852 --- /dev/null +++ b/_book/docs/240.md @@ -0,0 +1,70 @@ +# Test and deploy a Scala application to Heroku + +> 原文:[https://docs.gitlab.com/ee/ci/examples/test-scala-application.html](https://docs.gitlab.com/ee/ci/examples/test-scala-application.html) + +* [Add `.gitlab-ci.yml` file to project](#add-gitlab-ciyml-file-to-project) +* [Display test coverage in job](#display-test-coverage-in-job) +* [Heroku application](#heroku-application) +* [Heroku API key](#heroku-api-key) + +# Test and deploy a Scala application to Heroku[](#test-and-deploy-a-scala-application-to-heroku "Permalink") + +该示例演示了使用 SBT 将 GitLab CI / CD 与 Scala 应用程序集成. 您可以查看或创建[示例项目,](https://gitlab.com/gitlab-examples/scala-sbt)并查看其过去的[CI 作业](https://gitlab.com/gitlab-examples/scala-sbt/-/jobs?scope=finished)的日志. + +## Add `.gitlab-ci.yml` file to project[](#add-gitlab-ciyml-file-to-project "Permalink") + +以下`.gitlab-ci.yml`应该添加到存储库的根目录中以触发 CI: + +``` +image: openjdk:8 + +stages: + - test + - deploy + +before_script: + - apt-get update -y + - apt-get install apt-transport-https -y + ## Install SBT + - echo "deb http://dl.bintray.com/sbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list + - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823 + - apt-get update -y + - apt-get install sbt -y + - sbt sbtVersion + +test: + stage: test + script: + - sbt clean coverage test coverageReport + +deploy: + stage: deploy + script: + - apt-get update -yq + - apt-get install rubygems ruby-dev -y + - gem install dpl + - dpl --provider=heroku --app=gitlab-play-sample-app --api-key=$HEROKU_API_KEY +``` + +在以上配置中: + +* `before_script`将安装[SBT](https://www.scala-sbt.org/)并显示正在使用的版本. +* `test`阶段执行 SBT 来编译和测试项目. + * [sbt-scoverage](https://github.com/scoverage/sbt-scoverage)用作 SBT 插件来测量测试覆盖率. +* `deploy`阶段使用 dpl 将项目自动部署到 Heroku. + +您可以通过在`build.sbt`定义其他版本的 Scala 和 SBT 来使用它们. + +## Display test coverage in job[](#display-test-coverage-in-job "Permalink") + +在**设置➔管道➔覆盖率报告**项目设置中,将`Coverage was \[\d+.\d+\%\]`添加`Coverage was \[\d+.\d+\%\]`正则表达式,以从构建跟踪中检索[测试覆盖率](../pipelines/settings.html#test-coverage-report-badge)并将其与作业一起显示. + +必须启用**管道**才能显示此选项. + +## Heroku application[](#heroku-application "Permalink") + +需要 Heroku 应用程序. 您可以通过[仪表板](https://dashboard.heroku.com/)创建一个. 用您的应用程序名称`.gitlab-ci.yml`文件中的`gitlab-play-sample-app` . + +## Heroku API key[](#heroku-api-key "Permalink") + +您可以在[帐户中](https://dashboard.heroku.com/account)查找 Heroku API 密钥. 使用键`HEROKU_API_KEY`在**项目➔变量中**添加具有此值的[受保护变量](../variables/README.html#protect-a-custom-variable) . \ No newline at end of file diff --git a/_book/docs/241.md b/_book/docs/241.md new file mode 100644 index 0000000000000000000000000000000000000000..3c238ff41e268fb1762670e2b39cc2359f6bab0f --- /dev/null +++ b/_book/docs/241.md @@ -0,0 +1,81 @@ +# GitLab CI/CD for external repositories + +> 原文:[https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/) + +* [Pipelines for external pull requests](#pipelines-for-external-pull-requests) + * [How it works](#how-it-works) + * [Additional predefined variables](#additional-predefined-variables) + * [Limitations](#limitations) + +# GitLab CI/CD for external repositories[](#gitlab-cicd-for-external-repositories-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4642) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.6. + +GitLab CI / CD 可用于: + +* [GitHub](github_integration.html). +* [Bitbucket Cloud](bitbucket_integration.html). +* 任何其他 Git 服务器. + +无需将整个项目移至 GitLab,您可以连接外部存储库以获得 GitLab CI / CD 的好处. + +连接外部存储库将建立[存储库镜像](../../user/project/repository/repository_mirroring.html)并创建一个轻型项目,其中禁用了问题,合并请求,Wiki 和代码片段. 这些功能[可以稍后重新启用](../../user/project/settings/index.html#sharing-and-permissions) . + +要连接到外部存储库: + +1. 在您的 GitLab 仪表板上,点击**新建项目** . +2. 切换到**CI / CD 的外部回购**标签. +3. Choose **GitHub** or **通过 URL 回购**. +4. 后续步骤类似于[导入流程](../../user/project/import/index.html) . + +[![CI/CD for external repository project creation](img/8855ae33dbb80420649c523afdf3fe8b.png)](img/ci_cd_for_external_repo.png) + +## Pipelines for external pull requests[](#pipelines-for-external-pull-requests "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/65139) in GitLab Premium 12.3. + +当将 GitLab CI / CD 与[GitHub 上](github_integration.html)的[外部存储库一起使用时](github_integration.html) ,可以在 Pull Request 上下文中运行管道. + +当您将更改推送到 GitHub 中的远程分支时,GitLab CI / CD 可以为该分支运行管道. 但是,当您打开或更新该分支的"拉取请求"时,您可能需要: + +* 运行额外的工作. +* 不运行特定作业. + +例如: + +``` +always-run: + script: echo 'this should always run' + +on-pull-requests: + script: echo 'this should run on pull requests' + only: + - external_pull_requests + +except-pull-requests: + script: echo 'this should not run on pull requests' + except: + - external_pull_requests +``` + +### How it works[](#how-it-works "Permalink") + +从 GitHub 导入存储库时,GitLab 会订阅 webhooks 的`push`和`pull_request`事件. 收到`pull_request`事件后,将存储请求请求数据并将其保留为参考. 如果刚刚创建了 Pull Request,则 GitLab 会立即为外部 Pull Request 创建管道. + +如果将更改推送到"拉取请求"所引用的分支,并且"拉取请求"仍处于打开状态,则会创建用于外部拉取请求的管道. + +**注意:**在这种情况下,GitLab CI / CD 将创建 2 条管道. 一种用于分支推送,另一种用于外部拉取请求. + +关闭"拉取请求"后,即使将新的更改推送到同一分支,也不会为外部拉取请求创建任何管道. + +### Additional predefined variables[](#additional-predefined-variables "Permalink") + +通过将管道用于外部拉取请求,GitLab 将其他[预定义变量](../variables/predefined_variables.html)公开给管道作业. + +变量名称以`CI_EXTERNAL_PULL_REQUEST_`为前缀. + +### Limitations[](#limitations "Permalink") + +此功能当前不支持来自派生存储库的拉取请求. 来自 fork 存储库的任何 Pull Requests 将被忽略. [阅读更多](https://gitlab.com/gitlab-org/gitlab/-/issues/5667) . + +鉴于 GitLab 将创建 2 条管道,如果将更改推送到引用了打开的 Pull Request 的远程分支,则两者都将通过 GitHub 集成促进 Pull Request 的状态. 如果要只在外部请求请求上而不是在分支上运行管道,则可以添加以下内容, `except: [branches]`到作业规范. [阅读更多](https://gitlab.com/gitlab-org/gitlab/-/issues/24089#workaround) . \ No newline at end of file diff --git a/_book/docs/242.md b/_book/docs/242.md new file mode 100644 index 0000000000000000000000000000000000000000..78c54e2be361f77edce7e59c8ff2e4c363b100fa --- /dev/null +++ b/_book/docs/242.md @@ -0,0 +1,130 @@ +# Using GitLab CI/CD with a Bitbucket Cloud repository + +> 原文:[https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/bitbucket_integration.html](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/bitbucket_integration.html) + +# Using GitLab CI/CD with a Bitbucket Cloud repository[](#using-gitlab-cicd-with-a-bitbucket-cloud-repository-premium "Permalink") + +GitLab CI / CD 可以通过以下方式与 Bitbucket Cloud 一起使用: + +1. 创建一个[CI / CD 项目](../../user/project/ci_cd_for_external_repo.html) . +2. 通过 URL 连接您的 Git 存储库. + +要将 GitLab CI / CD 与 Bitbucket Cloud 存储库一起使用: + +1. 在 GitLab 中**为外部** **仓库**创建一个**CI / CD** ,选择" **按 URL 进行仓库"**并创建项目. + + [![Create project](img/d4fcdfd2497a9936b17469dbafbd320e.png)](img/external_repository.png) + + GitLab 将导入存储库并启用[Pull Mirroring](../../user/project/repository/repository_mirroring.html#pulling-from-a-remote-repository-starter) . + +2. 在 GitLab 中,创建具有`api`作用域的[个人访问令牌](../../user/profile/personal_access_tokens.html) . 这将用于验证来自 Web 钩子的请求,该请求将在 Bitbucket 中创建,以将新提交通知 GitLab. + +3. 在 Bitbucket 中,从**"设置">" Webhooks"**中创建一个新的 Web 挂钩,以将新的提交通知 GitLab. + + 应该使用我们刚刚生成的用于身份验证的个人访问令牌,将 Web 挂钩 URL 设置为 GitLab API 来触发拉镜像. + + ``` + https://gitlab.com/api/v4/projects/<PROJECT_ID>/mirror/pull?private_token=<PERSONAL_ACCESS_TOKEN> + ``` + + 网络挂钩触发器应设置为" Repository Push". + + [![Bitbucket Cloud webhook](img/3a328cbf9c83e567fa5921d3580a84cb.png)](img/bitbucket_webhook.png) + + 保存后,通过将更改推送到您的 Bitbucket 存储库来测试 Web 挂钩. + +4. 在 Bitbucket 中,从" **Bitbucket 设置">"应用程序密码"中**创建一个**应用** **程序密码,**以验证构建状态脚本设置来提交 Bitbucket 中的构建状态. 存储库写权限是必需的. + + [![Bitbucket Cloud webhook](img/0d3f7491de96f0f5d1d30a594ec42739.png)](img/bitbucket_app_password.png) + +5. 在 GitLab 中,从**设置> CI / CD>环境变量中** ,添加变量以允许通过 Bitbucket API 与 Bitbucket 通信: + + `BITBUCKET_ACCESS_TOKEN` :上面创建的 Bitbucket 应用密码. + + `BITBUCKET_USERNAME` :Bitbucket 帐户的用户名. + + `BITBUCKET_NAMESPACE` :如果您的 GitLab 和 Bitbucket 命名空间不同,请设置此项. + + `BITBUCKET_REPOSITORY` :如果您的 GitLab 和 Bitbucket 项目名称不同,请设置此项. + +6. 在 Bitbucket 中,添加脚本以将管道状态推送到 Bitbucket. + + > 注意:在 GitLab 中所做的更改将被 Bitbucket 在上游进行的任何更改所覆盖. + + 创建一个文件`build_status`并在下面插入脚本,然后在终端中运行`chmod +x build_status`以使脚本可执行. + + ``` + #!/usr/bin/env bash + + # Push GitLab CI/CD build status to Bitbucket Cloud + + if [ -z "$BITBUCKET_ACCESS_TOKEN" ]; then echo "ERROR: BITBUCKET_ACCESS_TOKEN is not set" + exit 1 + fi + if [ -z "$BITBUCKET_USERNAME" ]; then echo "ERROR: BITBUCKET_USERNAME is not set" + exit 1 + fi + if [ -z "$BITBUCKET_NAMESPACE" ]; then echo "Setting BITBUCKET_NAMESPACE to $CI_PROJECT_NAMESPACE" + BITBUCKET_NAMESPACE=$CI_PROJECT_NAMESPACE + fi + if [ -z "$BITBUCKET_REPOSITORY" ]; then echo "Setting BITBUCKET_REPOSITORY to $CI_PROJECT_NAME" + BITBUCKET_REPOSITORY=$CI_PROJECT_NAME + fi BITBUCKET_API_ROOT="https://api.bitbucket.org/2.0" + BITBUCKET_STATUS_API="$BITBUCKET_API_ROOT/repositories/$BITBUCKET_NAMESPACE/$BITBUCKET_REPOSITORY/commit/$CI_COMMIT_SHA/statuses/build" + BITBUCKET_KEY="ci/gitlab-ci/$CI_JOB_NAME" + + case "$BUILD_STATUS" in running) + BITBUCKET_STATE="INPROGRESS" + BITBUCKET_DESCRIPTION="The build is running!" + ;; + passed) + BITBUCKET_STATE="SUCCESSFUL" + BITBUCKET_DESCRIPTION="The build passed!" + ;; + failed) + BITBUCKET_STATE="FAILED" + BITBUCKET_DESCRIPTION="The build failed." + ;; + esac + + echo "Pushing status to $BITBUCKET_STATUS_API..." + curl --request POST $BITBUCKET_STATUS_API \ + --user $BITBUCKET_USERNAME:$BITBUCKET_ACCESS_TOKEN \ + --header "Content-Type:application/json" \ + --silent \ + --data "{ \"state\": \"$BITBUCKET_STATE\", \"key\": \"$BITBUCKET_KEY\", \"description\": \"$BITBUCKET_DESCRIPTION\",\"url\": \"$CI_PROJECT_URL/-/jobs/$CI_JOB_ID\" }" + ``` + +7. 仍在 Bitbucket 中,创建一个`.gitlab-ci.yml`文件以使用该脚本将管道成功与失败推送到 Bitbucket. + + ``` + stages: + - test + - ci_status + + unit-tests: + script: + - echo "Success. Add your tests!" + + success: + stage: ci_status + before_script: + - "" + after_script: + - "" + script: + - BUILD_STATUS=passed BUILD_KEY=push ./build_status + when: on_success + + failure: + stage: ci_status + before_script: + - "" + after_script: + - "" + script: + - BUILD_STATUS=failed BUILD_KEY=push ./build_status + when: on_failure + ``` + +现在已将 GitLab 配置为从 Bitbucket 镜像更改,运行在`.gitlab-ci.yml`配置的 CI / CD 管道,并将状态推送到 Bitbucket. \ No newline at end of file diff --git a/_book/docs/243.md b/_book/docs/243.md new file mode 100644 index 0000000000000000000000000000000000000000..ac3d52db88deadc18aa76c4d83759fb85ffcb80e --- /dev/null +++ b/_book/docs/243.md @@ -0,0 +1,71 @@ +# Using GitLab CI/CD with a GitHub repository + +> 原文:[https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/github_integration.html](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/github_integration.html) + +* [Connect with Personal Access Token](#connect-with-personal-access-token) +* [Connect manually](#connect-manually) + +# Using GitLab CI/CD with a GitHub repository[](#using-gitlab-cicd-with-a-github-repository-premium "Permalink") + +通过创建[CI / CD 项目](index.html)将 GitHub 存储库连接到 GitLab,GitLab CI / CD 可与**GitHub.com**和**GitHub Enterprise**一起使用. + +观看有关在[GitHub 存储库中使用 GitLab CI / CD 管道](https://www.youtube.com/watch?v=qgl3F2j-1cI)的视频. + +**注意:**由于[GitHub 的限制](https://gitlab.com/gitlab-org/gitlab/-/issues/9147) ,不能将[GitHub OAuth](../../integration/github.html#enabling-github-oauth)用于作为外部 CI / CD 存储库的 GitHub 进行身份验证. + +## Connect with Personal Access Token[](#connect-with-personal-access-token "Permalink") + +**注意:**个人访问令牌只能用于将 GitHub.com 存储库连接到 GitLab,并且 GitHub 用户必须具有[owner 角色](https://help.github.com/en/github/getting-started-with-github/access-permissions-on-github) . + +要通过 GitHub 一次性授权以授予 GitLab 访问您的存储库的权限,请执行以下操作: + +1. 打开[https://github.com/settings/tokens/new](https://github.com/settings/tokens/new)来创建**个人访问令牌** . 该令牌将用于访问您的存储库并将提交状态推送到 GitHub. + + 应该启用`repo`和`admin:repo_hook`以允许 GitLab 访问您的项目,更新提交状态并创建 Web 挂钩以将新提交通知 GitLab. + +2. 在 GitLab 中,转到[新项目页面](../../gitlab-basics/create-project.html#create-a-project-in-gitlab) ,选择**CI / CD 作为外部仓库**选项卡,然后单击**GitHub** . + +3. 将令牌粘贴到" **个人访问令牌"**字段中,然后单击" **列出存储库"** . 单击" **连接"**以选择存储库. + +4. 在 GitHub 中,添加`.gitlab-ci.yml`以[配置 GitLab CI / CD](../quick_start/README.html) . + +GitLab 将: + +1. 导入项目. +2. Enable [Pull Mirroring](../../user/project/repository/repository_mirroring.html#pulling-from-a-remote-repository-starter) +3. Enable [GitHub project integration](../../user/project/integrations/github.html) +4. 在 GitHub 上创建一个 Web 挂钩,以通知 GitLab 新提交. + +## Connect manually[](#connect-manually "Permalink") + +**注意:**要将**GitHub Enterprise**与**GitLab.com 一起**使用,请使用此方法. + +要为您的存储库手动启用 GitLab CI / CD: + +1. 在 GitHub 中打开[https://github.com/settings/tokens/new](https://github.com/settings/tokens/new)创建**个人访问令牌.** GitLab 将使用此令牌访问您的存储库并推送提交状态. + + 输入**令牌描述**并更新范围以允许: + + `repo`以便 GitLab 可以访问您的项目并更新提交状态 + +2. 在 GitLab 中,使用 Git URL 选项和 GitHub 存储库的 HTTPS URL 创建一个**CI / CD 项目** . 如果您的项目是私人项目,请使用您刚创建的个人访问令牌进行身份验证. + + GitLab 将自动配置基于轮询的拉镜像. + +3. 仍在 GitLab 中,从**"设置">"集成"**启用[GitHub 项目](../../user/project/integrations/github.html) **集成.** + + 选中" **活动"**复选框以启用集成,将您的个人访问令牌和 HTTPS 存储库 URL 粘贴到表单中,然后**保存.** + +4. 仍在 GitLab 中,创建具有`API`范围的**个人访问令牌** ,以验证 GitHub Web 挂钩,以通知 GitLab 新提交. + +5. 在 GitHub 中的**"设置">" Webhooks"中**创建一个 Web 挂钩,以通知 GitLab 新提交. + + 应使用我们刚刚创建的 GitLab 个人访问令牌,将 Web 挂钩 URL 设置为 GitLab API 来[触发拉镜像](../../api/projects.html#start-the-pull-mirroring-process-for-a-project-starter) : + + ``` + https://gitlab.com/api/v4/projects/<NAMESPACE>%2F<PROJECT>/mirror/pull?private_token=<PERSONAL_ACCESS_TOKEN> + ``` + + 选择" **让我选择单个事件"**选项,然后选中" **拉**取**请求**和**推送"**复选框. [对于外部拉取请求的管道,](index.html#pipelines-for-external-pull-requests)需要这些设置. + +6. 在 GitHub 中添加`.gitlab-ci.yml`以配置 GitLab CI / CD. \ No newline at end of file diff --git a/_book/docs/244.md b/_book/docs/244.md new file mode 100644 index 0000000000000000000000000000000000000000..170ce5f9ce13f639981b251a1c10bd933d3e849f --- /dev/null +++ b/_book/docs/244.md @@ -0,0 +1,101 @@ +# GitLab Pages + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/](https://docs.gitlab.com/ee/user/project/pages/) + +* [Getting started](#getting-started) +* [How it works](#how-it-works) +* [Access to your Pages site](#access-to-your-pages-site) +* [Pages examples](#pages-examples) +* [Administer GitLab Pages for self-managed instances](#administer-gitlab-pages-for-self-managed-instances) + +# GitLab Pages[](#gitlab-pages "Permalink") + +版本历史 + +* 在 GitLab 企业版 8.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80) . +* GitLab 企业版 8.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173)了具有 TLS 支持的自定义 CNAME. +* [移植](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14605)到 GitLab 8.17 中的 GitLab 社区版. +* 在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30548)了对子组项目网站的支持. +* 捆绑的项目模板在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47857) . + +借助 GitLab 页面,您可以直接从 GitLab 中的存储库发布静态网站. + +* 用于任何个人或企业网站. +* 使用任何静态站点生成器(SSG)或纯 HTML. +* 为您的项目,组或用户帐户创建网站. +* 免费在自己的 GitLab 实例或 GitLab.com 上托管您的网站. +* 连接您的自定义域和 TLS 证书. +* 将任何许可归于您的内容. + +![Examples of SSGs supported by Pages](img/50ffc4ae0babeef44a73e82cfe49bb30.png) + +要发布包含 Pages 的网站,您可以使用任何 SSG,例如 Gatsby,Jekyll,Hugo,Middleman,Harp,Hexo 和 Brunch 等. 您还可以发布直接用纯 HTML,CSS 和 JavaScript 编写的任何网站. + +网页**不**支持动态服务器端的处理,例如,作为`.php`和`.asp`需要. 了解更多有关[静态网站和动态网站的信息](https://about.gitlab.com/blog/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) . + +## Getting started[](#getting-started "Permalink") + +要创建一个 GitLab Pages 网站: + +| Document | Description | +| --- | --- | +| [Fork a sample project](getting_started/pages_forked_sample_project.html) | 通过分叉示例项目,使用已配置的 Pages 创建一个新项目. | +| [Use a new project template](getting_started/pages_new_project_template.html) | 使用已经使用新项目模板配置的 Pages 创建一个新项目. | +| [Use a `.gitlab-ci.yml` template](getting_started/pages_ci_cd_template.html) | 将 Pages 网站添加到现有项目. 使用预填充的 CI 模板文件. | +| [Create a `gitlab-ci.yml` file from scratch](getting_started/pages_from_scratch.html) | 将 Pages 网站添加到现有项目. 了解如何创建和配置自己的 CI 文件. | + +要更新 GitLab Pages 网站: + +| Document | Description | +| --- | --- | +| [GitLab Pages domain names, URLs, and base URLs](getting_started_part_one.html) | 了解有关 GitLab Pages 默认域的信息. | +| [Explore GitLab Pages](introduction.html) | 要求,技术方面,特定的 GitLab CI / CD 配置选项,访问控制,自定义 404 页面,限制,常见问题解答. | +| [Custom domains and SSL/TLS Certificates](custom_domains_ssl_tls_certification/index.html) | 自定义域和子域,DNS 记录和 SSL / TLS 证书. | +| [Let’s Encrypt integration](custom_domains_ssl_tls_certification/lets_encrypt_integration.html) | 使用 Let's Encrypt 证书保护您的 Pages 网站,该证书由 GitLab 自动获取并更新. | +| [CloudFlare certificates](https://about.gitlab.com/blog/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) | 使用 CloudFlare 证书保护您的 Pages 网站. | + +了解更多信息并查看示例: + +| Document | Description | +| --- | --- | +| [Static vs dynamic websites](https://about.gitlab.com/blog/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) | 静态与动态网站概述. | +| [Modern static site generators](https://about.gitlab.com/blog/2016/06/10/ssg-overview-gitlab-pages-part-2/) | SSG 概述. | +| [Build any SSG site with GitLab Pages](https://about.gitlab.com/blog/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/) | 对 GitLab 页面使用 SSG. | + +## How it works[](#how-it-works "Permalink") + +要使用 GitLab 页面,您必须在 GitLab 中创建一个项目以将您网站的文件上传到该项目. 这些项目可以是公共的,内部的或私人的. + +GitLab 始终从资源库中一个非常特定的文件夹`public`部署您的网站. 在 GitLab 中创建新项目时, [存储库](../repository/index.html)将自动可用. + +为了部署您的站点,GitLab 使用其内置工具[GitLab CI / CD](../../../ci/README.html)来构建您的站点并将其发布到 GitLab Pages 服务器. GitLab CI / CD 运行以完成此任务的脚本序列是从名为`.gitlab-ci.yml`的文件中[创建的](getting_started/pages_from_scratch.html) ,您可以随意[创建和修改](getting_started/pages_from_scratch.html) . 配置文件中称为`pages`的特定`job`会使 GitLab 知道您正在部署 GitLab Pages 网站. + +您可以将 GitLab 的[默认域用于](getting_started_part_one.html#gitlab-pages-default-domain-names) `*.gitlab.io` [GitLab Pages 网站](getting_started_part_one.html#gitlab-pages-default-domain-names) `*.gitlab.io` ,也可以使用自己的域( `example.com` ). 在这种情况下,您需要对您域的注册商(或控制面板)具有管理员权限,才能使用 Pages 对其进行设置. + +下图显示了开始使用 Pages 可能需要遵循的工作流程. + +![New projects for GitLab Pages](img/8db9ef3ba0d1153ab46b990e98372677.png) + +## Access to your Pages site[](#access-to-your-pages-site "Permalink") + +如果您使用的是 GitLab Pages 默认域( `.gitlab.io` ),则您的网站将自动安全并在 HTTPS 下可用. 如果您使用自己的自定义域,则可以选择使用 SSL / TLS 证书对其进行保护. + +If you’re using GitLab.com, your website will be publicly available to the internet. To restrict access to your website, enable [GitLab Pages Access Control](pages_access_control.html). + +如果您使用的是自我管理的实例(Core,Starter,Premium 或 Ultimate),则根据 sysadmin 选择的[Pages admin 设置](../../../administration/pages/index.html) ,您的网站将发布在您自己的服务器上,管理员可以将其设置为公开或内部. + +## Pages examples[](#pages-examples "Permalink") + +有一些因特定原因而建立的 GitLab Pages 网站的出色示例. 这些示例可以教您使用高级技术并适应您自己的需求: + +* [Posting to your GitLab Pages blog from iOS](https://about.gitlab.com/blog/2016/08/19/posting-to-your-gitlab-pages-blog-from-ios/). +* [GitLab CI: Run jobs sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/). +* [GitLab CI: Deployment & environments](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/). +* [Building a new GitLab docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/blog/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/). +* [Publish code coverage reports with GitLab Pages](https://about.gitlab.com/blog/2016/11/03/publish-code-coverage-report-with-gitlab-pages/). + +## Administer GitLab Pages for self-managed instances[](#administer-gitlab-pages-for-self-managed-instances "Permalink") + +如果您正在运行 GitLab 的自我管理实例(GitLab 社区版和企业版),请[按照管理步骤](../../../administration/pages/index.html)来配置页面. + +观看有关如何开始使用 GitLab 页面管理的[视频教程](https://www.youtube.com/watch?v=dD8c7WNcc6s) . \ No newline at end of file diff --git a/_book/docs/245.md b/_book/docs/245.md new file mode 100644 index 0000000000000000000000000000000000000000..23d47103ba183b0ca5c459527ab374e60067f567 --- /dev/null +++ b/_book/docs/245.md @@ -0,0 +1,101 @@ +# GitLab Pages + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/#getting-started](https://docs.gitlab.com/ee/user/project/pages/#getting-started) + +* [Getting started](#getting-started) +* [How it works](#how-it-works) +* [Access to your Pages site](#access-to-your-pages-site) +* [Pages examples](#pages-examples) +* [Administer GitLab Pages for self-managed instances](#administer-gitlab-pages-for-self-managed-instances) + +# GitLab Pages[](#gitlab-pages "Permalink") + +版本历史 + +* 在 GitLab 企业版 8.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80) . +* GitLab 企业版 8.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173)了具有 TLS 支持的自定义 CNAME. +* [移植](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14605)到 GitLab 8.17 中的 GitLab 社区版. +* 在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30548)了对子组项目网站的支持. +* 捆绑的项目模板在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47857) . + +借助 GitLab 页面,您可以直接从 GitLab 中的存储库发布静态网站. + +* 用于任何个人或企业网站. +* 使用任何静态站点生成器(SSG)或纯 HTML. +* 为您的项目,组或用户帐户创建网站. +* 免费在自己的 GitLab 实例或 GitLab.com 上托管您的网站. +* 连接您的自定义域和 TLS 证书. +* 将任何许可归于您的内容. + +![Examples of SSGs supported by Pages](img/50ffc4ae0babeef44a73e82cfe49bb30.png) + +要发布包含 Pages 的网站,您可以使用任何 SSG,例如 Gatsby,Jekyll,Hugo,Middleman,Harp,Hexo 和 Brunch 等. 您还可以发布直接用纯 HTML,CSS 和 JavaScript 编写的任何网站. + +网页**不**支持动态服务器端的处理,例如,作为`.php`和`.asp`需要. 了解更多有关[静态网站和动态网站的信息](https://about.gitlab.com/blog/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) . + +## Getting started[](#getting-started "Permalink") + +要创建一个 GitLab Pages 网站: + +| Document | Description | +| --- | --- | +| [Fork a sample project](getting_started/pages_forked_sample_project.html) | 通过分叉示例项目,使用已配置的 Pages 创建一个新项目. | +| [Use a new project template](getting_started/pages_new_project_template.html) | 使用已经使用新项目模板配置的 Pages 创建一个新项目. | +| [Use a `.gitlab-ci.yml` template](getting_started/pages_ci_cd_template.html) | 将 Pages 网站添加到现有项目. 使用预填充的 CI 模板文件. | +| [Create a `gitlab-ci.yml` file from scratch](getting_started/pages_from_scratch.html) | 将 Pages 网站添加到现有项目. 了解如何创建和配置自己的 CI 文件. | + +要更新 GitLab Pages 网站: + +| Document | Description | +| --- | --- | +| [GitLab Pages domain names, URLs, and base URLs](getting_started_part_one.html) | 了解有关 GitLab Pages 默认域的信息. | +| [Explore GitLab Pages](introduction.html) | 要求,技术方面,特定的 GitLab CI / CD 配置选项,访问控制,自定义 404 页面,限制,常见问题解答. | +| [Custom domains and SSL/TLS Certificates](custom_domains_ssl_tls_certification/index.html) | 自定义域和子域,DNS 记录和 SSL / TLS 证书. | +| [Let’s Encrypt integration](custom_domains_ssl_tls_certification/lets_encrypt_integration.html) | 使用 Let's Encrypt 证书保护您的 Pages 网站,该证书由 GitLab 自动获取并更新. | +| [CloudFlare certificates](https://about.gitlab.com/blog/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) | 使用 CloudFlare 证书保护您的 Pages 网站. | + +了解更多信息并查看示例: + +| Document | Description | +| --- | --- | +| [Static vs dynamic websites](https://about.gitlab.com/blog/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) | 静态与动态网站概述. | +| [Modern static site generators](https://about.gitlab.com/blog/2016/06/10/ssg-overview-gitlab-pages-part-2/) | SSG 概述. | +| [Build any SSG site with GitLab Pages](https://about.gitlab.com/blog/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/) | 对 GitLab 页面使用 SSG. | + +## How it works[](#how-it-works "Permalink") + +要使用 GitLab 页面,您必须在 GitLab 中创建一个项目以将您网站的文件上传到该项目. 这些项目可以是公共的,内部的或私人的. + +GitLab 始终从资源库中一个非常特定的文件夹`public`部署您的网站. 在 GitLab 中创建新项目时, [存储库](../repository/index.html)将自动可用. + +为了部署您的站点,GitLab 使用其内置工具[GitLab CI / CD](../../../ci/README.html)来构建您的站点并将其发布到 GitLab Pages 服务器. GitLab CI / CD 运行以完成此任务的脚本序列是从名为`.gitlab-ci.yml`的文件中[创建的](getting_started/pages_from_scratch.html) ,您可以随意[创建和修改](getting_started/pages_from_scratch.html) . 配置文件中称为`pages`的特定`job`会使 GitLab 知道您正在部署 GitLab Pages 网站. + +您可以将 GitLab 的[默认域用于](getting_started_part_one.html#gitlab-pages-default-domain-names) `*.gitlab.io` [GitLab Pages 网站](getting_started_part_one.html#gitlab-pages-default-domain-names) `*.gitlab.io` ,也可以使用自己的域( `example.com` ). 在这种情况下,您需要对您域的注册商(或控制面板)具有管理员权限,才能使用 Pages 对其进行设置. + +下图显示了开始使用 Pages 可能需要遵循的工作流程. + +![New projects for GitLab Pages](img/8db9ef3ba0d1153ab46b990e98372677.png) + +## Access to your Pages site[](#access-to-your-pages-site "Permalink") + +如果您使用的是 GitLab Pages 默认域( `.gitlab.io` ),则您的网站将自动安全并在 HTTPS 下可用. 如果您使用自己的自定义域,则可以选择使用 SSL / TLS 证书对其进行保护. + +If you’re using GitLab.com, your website will be publicly available to the internet. To restrict access to your website, enable [GitLab Pages Access Control](pages_access_control.html). + +如果您使用的是自我管理的实例(Core,Starter,Premium 或 Ultimate),则根据 sysadmin 选择的[Pages admin 设置](../../../administration/pages/index.html) ,您的网站将发布在您自己的服务器上,管理员可以将其设置为公开或内部. + +## Pages examples[](#pages-examples "Permalink") + +有一些因特定原因而建立的 GitLab Pages 网站的出色示例. 这些示例可以教您使用高级技术并适应您自己的需求: + +* [Posting to your GitLab Pages blog from iOS](https://about.gitlab.com/blog/2016/08/19/posting-to-your-gitlab-pages-blog-from-ios/). +* [GitLab CI: Run jobs sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/). +* [GitLab CI: Deployment & environments](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/). +* [Building a new GitLab docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/blog/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/). +* [Publish code coverage reports with GitLab Pages](https://about.gitlab.com/blog/2016/11/03/publish-code-coverage-report-with-gitlab-pages/). + +## Administer GitLab Pages for self-managed instances[](#administer-gitlab-pages-for-self-managed-instances "Permalink") + +如果您正在运行 GitLab 的自我管理实例(GitLab 社区版和企业版),请[按照管理步骤](../../../administration/pages/index.html)来配置页面. + +观看有关如何开始使用 GitLab 页面管理的[视频教程](https://www.youtube.com/watch?v=dD8c7WNcc6s) . \ No newline at end of file diff --git a/_book/docs/246.md b/_book/docs/246.md new file mode 100644 index 0000000000000000000000000000000000000000..413c705f0389238faac70db80eccc60c169c4e28 --- /dev/null +++ b/_book/docs/246.md @@ -0,0 +1,68 @@ +# GitLab Pages domain names, URLs, and baseurls + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/getting_started_part_one.html](https://docs.gitlab.com/ee/user/project/pages/getting_started_part_one.html) + +* [GitLab Pages default domain names](#gitlab-pages-default-domain-names) + * [Project website examples](#project-website-examples) + * [User and Group website examples](#user-and-group-website-examples) +* [URLs and baseurls](#urls-and-baseurls) +* [Custom domains](#custom-domains) + +# GitLab Pages domain names, URLs, and baseurls[](#gitlab-pages-domain-names-urls-and-baseurls "Permalink") + +在本文档中,了解如何根据所需网站的 URL 为 GitLab Pages 命名项目. + +## GitLab Pages default domain names[](#gitlab-pages-default-domain-names "Permalink") + +> **注意:**如果您使用自己的 GitLab 实例通过 GitLab Pages 部署站点,请与 sysadmin 一起检查什么是 Pages 通配符域. 本指南适用于任何 GitLab 实例,您只需要用自己的实例替换 GitLab.com( `*.gitlab.io` )上的 Pages 通配符域. + +如果您在 GitLab 上设置了 GitLab Pages 项目,则可以在`namespace.example.io`的子域下自动访问它. [`namespace`](../../group/index.html#namespaces)由您在 GitLab.com 上的用户名或在其下创建此项目的组名定义. 对于 GitLab 自我管理的实例,将`example.io`替换为实例的 Pages 域. 对于 GitLab.com,页面域为`*.gitlab.io` . + +| GitLab 页面的类型 | The name of the project created in GitLab | 网址 | +| --- | --- | --- | +| 用户页面 | `username.example.io` | `http(s)://username.example.io` | +| 组页面 | `groupname.example.io` | `http(s)://groupname.example.io` | +| 用户拥有的项目页面 | `projectname` | `http(s)://username.example.io/projectname` | +| 小组拥有的项目页面 | `projectname` | `http(s)://groupname.example.io/projectname` | +| 子组拥有的项目页面 | `subgroup/projectname` | `http(s)://groupname.example.io/subgroup/projectname` | + +**警告:**关于在通用域名和 HTTPS 下提供的名称空间存在一些已知[限制](introduction.html#limitations) . 确保阅读该部分. + +要清楚地了解 Pages 域,请阅读以下示例. + +### Project website examples[](#project-website-examples "Permalink") + +* 您在用户名`john`下创建了一个名为`blog`的项目,因此您的项目 URL 为`https://gitlab.com/john/blog/` . 为该项目启用 GitLab Pages 并构建您的网站后,即可在`https://john.gitlab.io/blog/`下找到该网站. +* 您为所有网站创建了一个组,称为`websites` ,该组中的一个项目称为`blog` . 您的项目 URL 为`https://gitlab.com/websites/blog/` . 为该项目启用 GitLab 页面后,该站点将位于`https://websites.gitlab.io/blog/`下. +* 您为工程部门创建了一个名为`engineering`的组,为所有文档网站创建了一个名为`docs`的子组,该子组中的一个项目称为`workflows` . 您的项目网址为`https://gitlab.com/engineering/docs/workflows/` . 为该项目启用 GitLab 页面后,该站点将位于`https://engineering.gitlab.io/docs/workflows`下. + +### User and Group website examples[](#user-and-group-website-examples "Permalink") + +* 在您的用户名`john` ,您创建了一个名为`john.gitlab.io`的项目. 您的项目 URL 将为`https://gitlab.com/john/john.gitlab.io` . 为项目启用 GitLab Pages 后,您的网站将发布在`https://john.gitlab.io`下. +* 在小组`websites` ,您创建了一个名为`websites.gitlab.io`的项目. 您项目的 URL 将为`https://gitlab.com/websites/websites.gitlab.io` . 为项目启用 GitLab Pages 后,您的网站将发布在`https://websites.gitlab.io`下. + +**一般示例:** + +* 在 GitLab.com 上,项目站点将始终在`https://namespace.gitlab.io/project-name`下可用 +* 在 GitLab.com 上,将在`https://namespace.gitlab.io/`下提供用户或组网站. +* 在您的 GitLab 实例上,将上述`gitlab.io`替换为 Pages 服务器域. 向您的系统管理员询问此信息. + +## URLs and baseurls[](#urls-and-baseurls "Permalink") + +每个静态网站发生器(SSG)的默认配置期望找到您的网站下一个(子)域( `example.com` ),而不是在该领域(的子目录`example.com/subdir` ). 因此,每当发布项目网站( `namespace.gitlab.io/project-name` )时,都必须在 SSG 文档中查找此配置(基本 URL)并进行设置以反映此模式. + +例如,对于 Jekyll 站点, `baseurl`是在 Jekyll 配置文件`_config.yml`定义的. 如果您的网站 URL 是`https://john.gitlab.io/blog/` ,则需要将此行添加到`_config.yml` : + +``` +baseurl: "/blog" +``` + +相反,如果您在派生我们的[默认示例](https://gitlab.com/pages)之一后部署网站,则已经以这种方式配置了 baseurl,因为所有示例都包含项目网站. 如果您决定将自己的网站设为用户或网上论坛,则必须从项目中删除此配置. 对于我们刚刚提到的 Jekyll 示例,您必须将 Jekyll 的`_config.yml`更改为: + +``` +baseurl: "" +``` + +## Custom domains[](#custom-domains "Permalink") + +GitLab 页面支持通过 HTTP 或 HTTPS 提供服务的自定义域和子域. 有关更多信息,请参见[GitLab Pages 自定义域和 SSL / TLS 证书](custom_domains_ssl_tls_certification/index.html) . \ No newline at end of file diff --git a/_book/docs/247.md b/_book/docs/247.md new file mode 100644 index 0000000000000000000000000000000000000000..75738768515df4883cace3f596b4b30369b44cb5 --- /dev/null +++ b/_book/docs/247.md @@ -0,0 +1,362 @@ +# Create a GitLab Pages website from scratch + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/getting_started/pages_from_scratch.html](https://docs.gitlab.com/ee/user/project/pages/getting_started/pages_from_scratch.html) + +* [Prerequisites](#prerequisites) +* [Choose a Docker image](#choose-a-docker-image) +* [Install Jekyll](#install-jekyll) +* [Specify the `public` directory for output](#specify-the-public-directory-for-output) +* [Specify the `public` directory for artifacts](#specify-the-public-directory-for-artifacts) +* [Deploy specific branches to a Pages site](#deploy-specific-branches-to-a-pages-site) +* [Specify a stage to deploy](#specify-a-stage-to-deploy) +* [Remove duplicate commands](#remove-duplicate-commands) +* [Build faster with cached dependencies](#build-faster-with-cached-dependencies) +* [Related topics](#related-topics) + +# Create a GitLab Pages website from scratch[](#create-a-gitlab-pages-website-from-scratch "Permalink") + +本教程向您展示如何从头开始创建 Pages 站点. 您将从一个空白项目开始,并创建自己的 CI 文件,该文件向[GitLab Runner](https://docs.gitlab.com/runner/)提供指导. 当您的 CI / CD [管道](../../../../ci/pipelines/index.html)运行时,将创建 Pages 站点. + +本示例使用[Jekyll](https://jekyllrb.com/)静态站点生成器(SSG). 其他 SSG 遵循类似的步骤. 您无需熟悉 Jekyll 或 SSG 即可完成本教程. + +## Prerequisites[](#prerequisites "Permalink") + +要继续执行本示例,请从 GitLab 中的空白项目开始. 在根(顶级)目录中创建三个文件. + +* `.gitlab-ci.yml`一个 YAML 文件,其中包含要运行的命令. 现在,将文件内容保留为空白. + +* `index.html`您可以使用所需的 HTML 内容填充 HTML 文件,例如: + + ``` + <html> + <head> + <title>Home + + +

    Hello World!

    + + + ``` + +* [`Gemfile`](https://bundler.io/gemfile.html)一个描述 Ruby 程序依赖性的文件. 用以下内容填充它: + + ``` + source "https://rubygems.org" + + gem "jekyll" + ``` + +## Choose a Docker image[](#choose-a-docker-image "Permalink") + +In this example, the Runner uses a [Docker image](../../../../ci/docker/using_docker_images.html) to run scripts and deploy the site. + +这个特定的 Ruby 映像在[DockerHub](https://hub.docker.com/_/ruby)上[维护](https://hub.docker.com/_/ruby) . + +编辑您的`.gitlab-ci.yml`并将此文本添加为​​第一行. + +``` +image: ruby:2.7 +``` + +如果您的 SSG 需要构建[NodeJS](https://s0nodejs0org.icopy.site/) ,则必须指定一个包含 NodeJS 的映像作为其文件系统的一部分. 例如,对于[Hexo](https://gitlab.com/pages/hexo)网站,可以使用`image: node:12.17.0` . + +## Install Jekyll[](#install-jekyll "Permalink") + +要在本地运行[Jekyll](https://jekyllrb.com/) ,您需要打开终端并执行以下操作: + +* 通过运行`gem install bundler`安装[Bundler](https://bundler.io/) . +* 通过运行`bundle install`创建`Gemfile.lock` . +* 通过运行`bundle exec jekyll build`安装 Jekyll. + +在`.gitlab-ci.yml`文件中,其写为​​: + +``` +script: + - gem install bundler + - bundle install + - bundle exec jekyll build +``` + +此外,在`.gitlab-ci.yml`文件中,每个`script`均由`job`组织. `job`包括您要应用于该特定任务的脚本和设置. + +``` +job: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build +``` + +对于 GitLab Pages,此`job`有一个特定的名称,称为`pages` . 此设置告诉 Runner 您希望工作通过 GitLab Pages 部署您的网站: + +``` +pages: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build +``` + +## Specify the `public` directory for output[](#specify-the-public-directory-for-output "Permalink") + +Jekyll 需要知道在何处生成其输出. GitLab Pages 仅考虑名为`public`的目录中的文件. + +Jekyll 使用目标( `-d` )为构建的网站指定输出目录: + +``` +pages: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public +``` + +## Specify the `public` directory for artifacts[](#specify-the-public-directory-for-artifacts "Permalink") + +既然 Jekyll 已将文件输出到`public`目录,则 Runner 需要知道从何处获取文件. 工件存储在`public`目录中: + +``` +pages: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public +``` + +将其粘贴到`.gitlab-ci.yml`文件中,因此现在看起来像这样: + +``` +image: ruby:2.7 + +pages: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public +``` + +现在保存并提交`.gitlab-ci.yml`文件. 您可以转到**CI / CD>管道**来观看管道运行. + +成功后,请转到**"设置">"页面"**以查看您的网站现在可用的 URL. + +如果您想执行更多高级任务,则可以使用[任何可用设置](../../../../ci/yaml/README.html)更新`.gitlab-ci.yml`文件. 您可以使用[GitLab CI / CD Lint Tool](../../../../ci/yaml/README.html#validate-the-gitlab-ciyml)来检查 CI 语法. + +以下主题显示了可以添加到 CI / CD 文件中的其他选项的其他示例. + +## Deploy specific branches to a Pages site[](#deploy-specific-branches-to-a-pages-site "Permalink") + +您可能只想从特定分支部署到 Pages 站点. + +首先,添加`workflow`部分以强制管道仅在将更改推送到分支时才运行: + +``` +image: ruby:2.7 + +workflow: + rules: + - if: '$CI_COMMIT_BRANCH' + +pages: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public +``` + +然后将管道配置为仅运行 master 分支的作业. + +``` +image: ruby:2.7 + +workflow: + rules: + - if: '$CI_COMMIT_BRANCH' + +pages: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public + rules: + - if: '$CI_COMMIT_BRANCH == "master"' +``` + +## Specify a stage to deploy[](#specify-a-stage-to-deploy "Permalink") + +GitLab CI / CD 有三个默认阶段:构建,测试和部署. + +如果要测试脚本并在部署到生产环境之前检查构建的站点,则可以完全按按`master`来运行测试. + +要为您的作业指定一个阶段,请在您的 CI 文件中添加一个`stage`行: + +``` +image: ruby:2.7 + +workflow: + rules: + - if: '$CI_COMMIT_BRANCH' + +pages: + stage: deploy + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public + rules: + - if: '$CI_COMMIT_BRANCH == "master"' +``` + +现在,将另一个作业添加到 CI 文件,告诉它测试**除** `master`分支**以外**的每个分支上的每次推送: + +``` +image: ruby:2.7 + +workflow: + rules: + - if: '$CI_COMMIT_BRANCH' + +pages: + stage: deploy + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public + rules: + - if: '$CI_COMMIT_BRANCH == "master"' + +test: + stage: test + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d test + artifacts: + paths: + - test + rules: + - if: '$CI_COMMIT_BRANCH != "master"' +``` + +当`test`作业在`test`阶段运行时,Jekyll 在名为`test`的目录中构建站点. 该工作影响除`master`之外的所有分支. + +将阶段应用于不同的作业时,同一阶段中的每个作业都是并行构建的. 如果您的 Web 应用程序在部署之前需要多个测试,则可以同时运行所有测试. + +## Remove duplicate commands[](#remove-duplicate-commands "Permalink") + +为了避免在每个作业中重复相同的脚本,可以将它们添加到`before_script`部分. + +在示例中, `gem install bundler`和`bundle install`对于作业, `pages`和`test`都在运行. + +将这些命令移至`before_script`部分: + +``` +image: ruby:2.7 + +workflow: + rules: + - if: '$CI_COMMIT_BRANCH' + +before_script: + - gem install bundler + - bundle install + +pages: + stage: deploy + script: + - bundle exec jekyll build -d public + artifacts: + paths: + - public + rules: + - if: '$CI_COMMIT_BRANCH == "master"' + +test: + stage: test + script: + - bundle exec jekyll build -d test + artifacts: + paths: + - test + rules: + - if: '$CI_COMMIT_BRANCH != "master"' +``` + +## Build faster with cached dependencies[](#build-faster-with-cached-dependencies "Permalink") + +为了加快构建速度,您可以使用`cache`参数为项目的依赖项缓存安装文件. + +此示例在运行`bundle install`时将 Jekyll 依赖项缓存在`vendor`目录中: + +``` +image: ruby:2.7 + +workflow: + rules: + - if: '$CI_COMMIT_BRANCH' + +cache: + paths: + - vendor/ + +before_script: + - gem install bundler + - bundle install --path vendor + +pages: + stage: deploy + script: + - bundle exec jekyll build -d public + artifacts: + paths: + - public + rules: + - if: '$CI_COMMIT_BRANCH == "master"' + +test: + stage: test + script: + - bundle exec jekyll build -d test + artifacts: + paths: + - test + rules: + - if: '$CI_COMMIT_BRANCH != "master"' +``` + +在这种情况下,您需要从 Jekyll 构建的文件夹列表中排除`/vendor`目录. 否则,Jekyll 将尝试与站点一起构建目录内容. + +在根目录中,创建一个名为`_config.yml`的文件并添加以下内容: + +``` +exclude: + - vendor +``` + +现在,GitLab CI / CD 不仅可以构建网站,还可以通过对功能分支的**连续测试**进行推送, **缓存**与 Bundler 一起安装的依赖项,并将每次推送**持续部署**到`master`分支. + +## Related topics[](#related-topics "Permalink") + +有关更多信息,请参见以下博客文章. + +* [Use GitLab CI/CD `environments` to deploy your web app to staging and production](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/). +* Learn [how to run jobs sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/). +* 了解[如何从不同项目中提取特定目录](https://about.gitlab.com/blog/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/)以部署此网站[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site) . +* Learn [how to use GitLab Pages to produce a code coverage report](https://about.gitlab.com/blog/2016/11/03/publish-code-coverage-report-with-gitlab-pages/). \ No newline at end of file diff --git a/_book/docs/248.md b/_book/docs/248.md new file mode 100644 index 0000000000000000000000000000000000000000..a4a095d9decb9d81aa4ba5371190956e3ca2b638 --- /dev/null +++ b/_book/docs/248.md @@ -0,0 +1,236 @@ +# Custom domains and SSL/TLS Certificates + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/) + +* [Set up Pages with a custom domain](#set-up-pages-with-a-custom-domain) + * [Requirements](#requirements) + * [Steps](#steps) + * [1\. Add a custom domain to Pages](#1-add-a-custom-domain-to-pages) + * [2\. Get the verification code](#2-get-the-verification-code) + * [3\. Set up DNS records for Pages](#3-set-up-dns-records-for-pages) + * [For root domains](#for-root-domains) + * [For subdomains](#for-subdomains) + * [For both root and subdomains](#for-both-root-and-subdomains) + * [4\. Verify the domain’s ownership](#4-verify-the-domains-ownership) + * [Troubleshooting Pages domain verification](#troubleshooting-pages-domain-verification) + * [Adding more domain aliases](#adding-more-domain-aliases) + * [Redirecting `www.domain.com` to `domain.com` with Cloudflare](#redirecting-wwwdomaincom-to-domaincom-with-cloudflare) +* [Adding an SSL/TLS certificate to Pages](#adding-an-ssltls-certificate-to-pages) + * [Requirements](#requirements-1) + * [Steps](#steps-1) +* [Force HTTPS for GitLab Pages websites](#force-https-for-gitlab-pages-websites) + +# Custom domains and SSL/TLS Certificates[](#custom-domains-and-ssltls-certificates "Permalink") + +使用自定义域设置 GitLab 页面,并向其中添加 SSL / TLS 证书,是 GitLab 页面的可选功能. + +要将一个或多个自定义域名用于您的 Pages 网站,您可以: + +* 添加[自定义**根域**或**子域**](#set-up-pages-with-a-custom-domain) . +* Add [SSL/TLS certification](#adding-an-ssltls-certificate-to-pages). + +## Set up Pages with a custom domain[](#set-up-pages-with-a-custom-domain "Permalink") + +要使用自定义域名设置页面,请阅读以下要求和步骤. + +### Requirements[](#requirements "Permalink") + +* 在默认的 Pages 域( `*.gitlab.io` ,对于 GitLab.com)下运行的 GitLab Pages 网站已启动并正在运行. +* 自定义域名`example.com`或子`subdomain.example.com` . +* 访问您域的服务器控制面板以设置 DNS 记录: + * 将您的域指向 GitLab Pages 服务器的 DNS A 或 CNAME 记录. + * DNS TXT 记录以验证您的域的所有权. + +### Steps[](#steps "Permalink") + +请按照以下步骤将您的自定义域添加到 Pages. 另请参阅本文档,以获取[有关 DNS 记录](dns_concepts.html)的[概述](dns_concepts.html) . + +#### 1\. Add a custom domain to Pages[](#1-add-a-custom-domain-to-pages "Permalink") + +导航到项目的" **设置">"页面"** ,然后单击" **+新域"**将自定义域添加到 GitLab 页面. 您可以选择是否: + +* Add an [SSL/TLS certificate](#adding-an-ssltls-certificate-to-pages). +* 保留为空白(以后可以添加). + +Click **建立新网域**. + +[![Add new domain](img/78801b2f265bdecdb7a5ff7e8be47802.png)](img/add_certificate_to_pages.png) + +#### 2\. Get the verification code[](#2-get-the-verification-code "Permalink") + +将新域添加到 Pages 后,系统将提示您输入验证码. 从 GitLab 复制值,并将其作为下一步的 TXT 记录粘贴到您域的控制面板中. + +[![Get the verification code](img/137ac74ffc45b0c50cf354baa972ca89.png)](img/get_domain_verification_code_v12_0.png) + +#### 3\. Set up DNS records for Pages[](#3-set-up-dns-records-for-pages "Permalink") + +阅读本文档以[获取 Pages 的 DNS 记录概述](dns_concepts.html) . 如果您熟悉此主题,请根据您要与 Pages 网站一起使用的域类型,按照以下说明进行操作: + +* [For root domains](#for-root-domains), `example.com`. +* [For subdomains](#for-subdomains), `subdomain.example.com`. +* [For both](#for-both-root-and-subdomains). + +**注意:**您可以[在自管实例上配置 IPv6](../../../../administration/pages/index.html#advanced-configuration) ,但是 GitLab.com 上的 Pages 当前未配置 IPv6\. 有关详细信息,请关注[此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/214718) . + +##### For root domains[](#for-root-domains "Permalink") + +根域( `example.com` )要求: + +* 指向您的域指向 Pages 服务器的[DNS A 记录](dns_concepts.html#a-record) . +* [TXT 记录](dns_concepts.html#txt-record)以验证您的域的所有权. + +| From | DNS 记录 | To | +| --- | --- | --- | +| `example.com` | A | `35.185.44.232` | +| `_gitlab-pages-verification-code.example.com` | TXT | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` | + +对于 GitLab.com 上的项目,此 IP 为`35.185.44.232` . 对于位于其他 GitLab 实例(CE 或 EE)中的项目,请联系您的系统管理员以询问此信息(该 IP 地址是实例上运行的 Pages 服务器). + +[![DNS A record pointing to GitLab.com Pages server](img/2b38faa6a2c817e4d1b8b32f803db372.png)](img/dns_add_new_a_record_example_updated_2018.png) + +**注意:**请注意,如果**仅**将根域用于 GitLab Pages 网站,并且域注册商支持此功能,则可以添加 DNS 顶点`CNAME`记录而不是`A`记录. 这样做的主要优点是,当 GitLab.com 上的 GitLab Pages IP 出于任何原因更改时,您无需更新`A`记录. 可能会有一些例外,但是**不建议使用此方法,**因为如果您为根域设置[`MX`记录](dns_concepts.html#mx-record) ,则**该方法**很可能不起作用. + +##### For subdomains[](#for-subdomains "Permalink") + +子域( `subdomain.example.com` )要求: + +* 将您的子域指向 Pages 服务器的 DNS [CNAME 记录](dns_concepts.html#cname-record)记录. +* DNS [TXT 记录](dns_concepts.html#txt-record)以验证您的域的所有权. + +| From | DNS 记录 | To | +| --- | --- | --- | +| `subdomain.example.com` | CNAME | `namespace.gitlab.io` | +| `_gitlab-pages-verification-code.subdomain.example.com` | TXT | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` | + +请注意,无论是用户网站还是项目网站, `CNAME`都应指向您的 Pages 域( `namespace.gitlab.io` ),而不包含任何`/project-name` . + +[![DNS CNAME record pointing to GitLab.com project](img/00cb101eb824b3ede4fa4a3914f95c09.png)](img/dns_cname_record_example.png) + +##### For both root and subdomains[](#for-both-root-and-subdomains "Permalink") + +在某些情况下,您需要将子域和根域都指向同一个网站,例如`example.com`和`www.example.com` . + +他们要求: + +* 域的 DNS A 记录. +* 子域的 DNS CNAME 记录. +* 每个 DNS TXT 记录. + +| From | DNS 记录 | To | +| --- | --- | --- | +| `example.com` | A | `35.185.44.232` | +| `_gitlab-pages-verification-code.example.com` | TXT | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` | +| `www.example.com` | CNAME | `namespace.gitlab.io` | +| `_gitlab-pages-verification-code.www.example.com` | TXT | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` | + +如果您使用的是 CloudFlare,请选中[使用 Cloudflare 将`www.domain.com`重定向到`domain.com`](#redirecting-wwwdomaincom-to-domaincom-with-cloudflare) . + +> **Notes**: +> +> * 如果要将`domain.com`指向 GitLab Pages 网站,请**不要**使用 CNAME 记录. 请改用`A`记录. +> * **不要**在默认的 Pages 域之后添加任何特殊字符. 例如,不要将`subdomain.domain.com`指向或`namespace.gitlab.io/` . 但是,某些域托管服务提供商可能会请求结尾点( `namespace.gitlab.io.` ). +> * GitLab.com 上的 GitLab Pages IP 在 2017 年[进行了更改](https://about.gitlab.com/releases/2017/03/06/we-are-changing-the-ip-of-gitlab-pages-on-gitlab-com/) . +> * GitLab.com [上的](https://about.gitlab.com/blog/2018/07/19/gcp-move-update/#gitlab-pages-and-custom-domains) GitLab Pages IP `35.185.44.232` 2018 年的 52.167.214.135 [更改](https://about.gitlab.com/blog/2018/07/19/gcp-move-update/#gitlab-pages-and-custom-domains)为`52.167.214.135` . + +#### 4\. Verify the domain’s ownership[](#4-verify-the-domains-ownership "Permalink") + +添加所有 DNS 记录后: + +1. 返回项目的**设置>页面** . +2. 找到您的域名,然后单击" **详细信息"** . +3. 点击**重试验证**按钮以激活您的新域. + +[![Verify your domain](img/62b879dea0345cb8767d9cd4fb041f97.png)](img/retry_domain_verification_v12_0.png) + +一旦您的域名启用,您的网站就会通过您的域名可用. + +**注意:**考虑到启用了域验证的 GitLab 实例,如果该域不能在 7 天之内得到验证,它将被从 GitLab 项目中删除. + +> **Notes:** +> +> * **GitLab.com 用户必须进行**域验证; 对于 GitLab 自管实例,您的 GitLab 管理员可以选择[禁用自定义域验证](../../../../administration/pages/index.html#custom-domain-verification) . +> * [DNS 传播可能需要一些时间(最多 24 小时)](https://www.inmotionhosting.com/support/domain-names/dns-nameserver-changes/domain-names-dns-changes/) ,尽管通常只需几分钟即可完成. 否则,验证将失败,并且尝试访问您的域的尝试将以 404 响应. +> * 验证您的域后,请保留验证记录:您的域将定期重新验证,如果删除该记录,则可能会被禁用. + +##### Troubleshooting Pages domain verification[](#troubleshooting-pages-domain-verification "Permalink") + +要手动验证您已正确配置了域验证`TXT` DNS 条目,可以在终端中运行以下命令: + +``` +dig _gitlab-pages-verification-code. TXT +``` + +期望输出: + +``` +;; ANSWER SECTION: +_gitlab-pages-verification-code.. 300 IN TXT "gitlab-pages-verification-code=" +``` + +### Adding more domain aliases[](#adding-more-domain-aliases "Permalink") + +You can add more than one alias (custom domains and subdomains) to the same project. An alias can be understood as having many doors leading to the same room. + +您为网站设置的所有别名都将在" **设置">"页面"**上列出. 在该页面上,您可以查看,添加和删除它们. + +### Redirecting `www.domain.com` to `domain.com` with Cloudflare[](#redirecting-wwwdomaincom-to-domaincom-with-cloudflare "Permalink") + +如果您使用 Cloudflare,则可以将`www`重定向到`domain.com`而无需同时将`www.domain.com`和`domain.com`添加到 GitLab. + +为此,您可以使用与 CNAME 记录关联的 Cloudflare 的页面规则将`www.domain.com`重定向到`domain.com` . 您可以使用以下设置: + +1. 在 Cloudflare 中,创建一个 DNS `A`记录,将`domain.com`指向`35.185.44.232` . +2. 在 GitLab 中,将域添加到 GitLab 页面中并获取验证码. +3. 在 Cloudflare 中,创建 DNS `TXT`记录以验证您的域. +4. 在 GitLab 中,验证您的域. +5. 在 Cloudflare 中,创建将`www`指向`domain.com`的 DNS `CNAME`记录. +6. 在 Cloudflare 中,添加将`www.domain.com`指向`domain.com`的页面规则: + * 导航到您域的信息中心,然后点击顶部导航栏中的**页面规则** . + * 单击**创建页面规则** . + * 输入域名`www.domain.com` ,然后点击**+添加设置** . + * 从下拉菜单中,选择**转发 URL** ,然后选择状态代码**301-永久重定向** . + * 输入目标网址`https://domain.com` . + +## Adding an SSL/TLS certificate to Pages[](#adding-an-ssltls-certificate-to-pages "Permalink") + +阅读本文档以获取[有关 SSL / TLS 认证](ssl_tls_concepts.html)的[概述](ssl_tls_concepts.html) . + +要使用 GitLab 页面保护您的自定义域,您可以选择: + +* 使用[Let's Encrypt 与 GitLab Pages 的集成](lets_encrypt_integration.html) ,该[集成](lets_encrypt_integration.html)会自动获取和续订您 Pages 域的 SSL 证书. +* 遵循以下步骤,将 SSL / TLS 证书手动添加到 GitLab Pages 网站. + +### Requirements[](#requirements-1 "Permalink") + +* 可通过自定义域访问 GitLab Pages 网站并正在运行. +* **PEM 证书** :它是由 CA 生成的证书,需要将其添加到字段**Certificate(PEM)中** . +* **[中间证书](https://en.wikipedia.org/wiki/Intermediate_certificate_authority)** :(也称为"根证书"),它是标识 CA 的加密密钥链的一部分. 通常,它与 PEM 证书结合在一起,但是在某些情况下,您需要手动添加它们. [CloudFlare 证书](https://about.gitlab.com/blog/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/)就是其中一种. +* **私钥** ,这是一个加密密钥,可根据您的域验证您的 PEM. + +### Steps[](#steps-1 "Permalink") + +* 要在添加新域时添加证书,请转至项目的**"设置">"页面">"新域"** ,添加域名和证书. +* 要将证书添加到先前添加的域中,请转到项目的**"设置">"页面"** ,找到您的域名,单击" **详细信息"**和" **编辑"**以添加证书. + +[![Pages project - adding certificates](img/78801b2f265bdecdb7a5ff7e8be47802.png)](img/add_certificate_to_pages.png) + +1. 将 PEM 证书添加到其相应的字段. +2. 如果您的证书缺少中间证书,请复制并粘贴根证书(通常可从您的 CA 网站获得),然后将其粘贴到[与 PEM 证书相同的字段中](https://about.gitlab.com/blog/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) ,只需在它们之间跳过一行即可. +3. 复制您的私钥并将其粘贴到最后一个字段中. + +**注意:** **请勿**在常规文本编辑器中打开证书或加密密钥. 始终使用代码编辑器(例如 Sublime Text,Atom,Dreamweaver,括号等). + +## Force HTTPS for GitLab Pages websites[](#force-https-for-gitlab-pages-websites "Permalink") + +在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28857) . + +为了使您的网站访问者更加安全,您可以选择对 GitLab 页面强制使用 HTTPS. 这样,所有通过 HTTP 访问您的网站的尝试都会通过 301 自动重定向到 HTTPS. + +它既可以与 GitLab 的默认域一起使用,也可以与您的自定义域一起使用(只要您为其设置了有效的证书). + +要启用此设置: + +1. 导航到项目的**"设置">"页面"** . +2. 选中" **强制 HTTPS** "复选框**(需要有效的证书)** . + +**注意:**如果在 GitLab 页面前面使用 CloudFlare CDN,请确保将 SSL 连接设置设置为`full`而不是`flexible` . 有关更多详细信息,请参阅[CloudFlare CDN 指导](https://support.cloudflare.com/hc/en-us/articles/200170416-End-to-end-HTTPS-with-Cloudflare-Part-3-SSL-options#h_4e0d1a7c-eb71-4204-9e22-9d3ef9ef7fef) . \ No newline at end of file diff --git a/_book/docs/249.md b/_book/docs/249.md new file mode 100644 index 0000000000000000000000000000000000000000..d582de0453fe3c403ed310be8ecce97e8b6f0a82 --- /dev/null +++ b/_book/docs/249.md @@ -0,0 +1,82 @@ +# GitLab Pages integration with Let's Encrypt + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html) + +* [Requirements](#requirements) +* [Enabling Let’s Encrypt integration for your custom domain](#enabling-lets-encrypt-integration-for-your-custom-domain) +* [Troubleshooting](#troubleshooting) + * [Error “Something went wrong while obtaining the Let’s Encrypt certificate”](#error-something-went-wrong-while-obtaining-the-lets-encrypt-certificate) + * [Message “GitLab is obtaining a Let’s Encrypt SSL certificate for this domain. This process can take some time. Please try again later.” hangs for more than an hour](#message-gitlab-is-obtaining-a-lets-encrypt-ssl-certificate-for-this-domain-this-process-can-take-some-time-please-try-again-later-hangs-for-more-than-an-hour) + +# GitLab Pages integration with Let’s Encrypt[](#gitlab-pages-integration-with-lets-encrypt "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28996) . 对于 GitLab 12.1 之前的版本,请参见[手册"让我们加密"说明](../lets_encrypt_for_gitlab_pages.html) . + +GitLab Pages 与 Let's Encrypt(LE)的集成使您可以将 LE 证书用于具有自定义域的 Pages 网站,而不必麻烦自己发行和更新它们. GitLab 现成的为您服务. + +[Let's Encrypt](https://letsencrypt.org)是一个免费,自动化和开源的证书颁发机构. + +**警告:**此功能仅涵盖**自定义域的**证书,而不包含运行[Pages 守护程序](../../../../administration/pages/index.html)所需的通配符证书 . 在[此问题中](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3342)跟踪通配符证书的生成. + +## Requirements[](#requirements "Permalink") + +在为您的域启用自动配置 SSL 证书之前,请确保您具有: + +* 创建一个[项目](../getting_started_part_two.html)在 GitLab 包含您的网站的源代码. +* 获取域( `example.com` )并添加一个[DNS 条目,](index.html)将其指向您的 Pages 网站. +* [将您的域添加到您的 Pages 项目](index.html#1-add-a-custom-domain-to-pages)并验证您的所有权. +* 确认您的网站已启动并且正在运行,可以通过您的自定义域进行访问. + +**注意:** GitLab 的"让我们加密"集成已启用,并在 GitLab.com 上可用. 对于**自我管理的** GitLab 实例,请确保您的管理员已[启用它](../../../../administration/pages/index.html#lets-encrypt-integration) . + +## Enabling Let’s Encrypt integration for your custom domain[](#enabling-lets-encrypt-integration-for-your-custom-domain "Permalink") + +满足要求后,启用"让我们加密"集成: + +1. 导航到项目的**"设置">"页面"** . +2. 找到您的域,然后单击**详细信息** . +3. 点击右上角的**编辑** . +4. 通过**使用 Let's Encrypt**切换**自动证书管理来**启用 Let's Encrypt 集成: + + [![Enable Let's Encrypt](img/b2499f834ff0e8252829dd96bad93d97.png)](img/lets_encrypt_integration_v12_1.png) + +5. Click **保存更改**. + +启用后,GitLab 将获得 LE 证书并将其添加到关联的 Pages 域中. 它也会由 GitLab 自动更新. + +> **Notes:** +> +> * 颁发证书和更新 Pages 配置**可能需要一个小时** . +> * 如果您在域设置中已经具有 SSL 证书,它将继续工作,直到被 Let's Encrypt 的证书替换为止. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Error “Something went wrong while obtaining the Let’s Encrypt certificate”[](#error-something-went-wrong-while-obtaining-the-lets-encrypt-certificate "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30146) . + +如果您遇到错误, **则在获取 Let's Encrypt 证书时出了点问题** ,您可以尝试按照以下步骤再次获取证书: + +1. 转到项目的**设置>页面** . +2. 在您的域上单击" **编辑** ". +3. Click **Retry**. +4. 如果您仍然看到相同的错误: + 1. 请确保您已正确设置只有一个`CNAME`或`A` DNS 记录为您的域. + 2. 确保您的域**没有** `AAAA` DNS 记录. + 3. 如果您的域或任何更高级别的域都有`CAA` DNS 记录,请确保[其中包含`letsencrypt.org`](https://letsencrypt.org/docs/caa/) . + 4. 确保[您的域已验证](index.html#1-add-a-custom-domain-to-pages) . + 5. 转到步骤 1\. + +### Message “GitLab is obtaining a Let’s Encrypt SSL certificate for this domain. This process can take some time. Please try again later.” hangs for more than an hour[](#message-gitlab-is-obtaining-a-lets-encrypt-ssl-certificate-for-this-domain-this-process-can-take-some-time-please-try-again-later-hangs-for-more-than-an-hour "Permalink") + +如果您启用了 Let's Encrypt 集成,但是一个小时后缺少证书,则会看到以下消息:" GitLab 正在为此域获取 Let's Encrypt SSL 证书. 此过程可能需要一些时间. 请稍后再试.",请按照以下步骤尝试删除并再次为 GitLab 页面添加域: + +1. 转到项目的**设置>页面** . +2. 在您的域上单击**删除** . +3. [Add the domain again and verify it](index.html#1-add-a-custom-domain-to-pages). +4. [Enable Let’s Encrypt integration for your domain](#enabling-lets-encrypt-integration-for-your-custom-domain). +5. 如果一段时间后仍然看到相同的消息: + 1. 请确保您已正确设置只有一个`CNAME`或`A` DNS 记录为您的域. + 2. 确保您的域**没有** `AAAA` DNS 记录. + 3. 如果您的域或任何更高级别的域都有`CAA` DNS 记录,请确保[其中包含`letsencrypt.org`](https://letsencrypt.org/docs/caa/) . + 4. 转到步骤 1\. \ No newline at end of file diff --git a/_book/docs/250.md b/_book/docs/250.md new file mode 100644 index 0000000000000000000000000000000000000000..d36ab73f06624b2d953a1b16813a483a2850840b --- /dev/null +++ b/_book/docs/250.md @@ -0,0 +1,44 @@ +# GitLab Pages Access Control + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/pages_access_control.html](https://docs.gitlab.com/ee/user/project/pages/pages_access_control.html) + +* [Terminating a Pages session](#terminating-a-pages-session) + +# GitLab Pages Access Control[](#gitlab-pages-access-control "Permalink") + +版本历史 + +* 在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33422) . +* 在 GitLab 12.4 的 GitLab.com 上可用. + +您可以在项目上启用 Pages 访问控制,以便只有[项目成员](../../permissions.html#project-members-permissions) (至少是 Guest)才能访问您的网站: + +有关演示,请参阅[页面访问控制](https://www.youtube.com/watch?v=tSPAr5mQYc8) . + +1. 导航到项目的**"设置">"常规",**然后展开" **可见性","项目功能,权限"** . +2. 切换**页面**按钮以启用访问控制. + + **注意:**如果看不到切换按钮,则表示该按钮未启用. 请您的管理员[启用它](../../../administration/pages/index.html#access-control) . +3. 页面访问控制下拉菜单允许您设置谁可以查看 GitLab 页面托管的页面,具体取决于项目的可见性: + + * 如果您的项目是私人的: + * **只有项目成员** :只有项目成员才能浏览网站. + * **所有人** :无论登录或退出 GitLab 的**每个**人,无论其项目成员身份如何,都可以浏览该网站. + * 如果您的项目是内部项目: + * **只有项目成员** :只有项目成员才能浏览网站. + * **具有访问权限的**每个人:登录到 GitLab 的每个人都可以浏览该网站,无论其项目成员身份如何. + * **所有人** :无论登录或退出 GitLab 的**每个**人,无论其项目成员身份如何,都可以浏览该网站. + * 如果您的项目是公开的: + * **只有项目成员** :只有项目成员才能浏览网站. + * **具有访问权限的**所有人:无论登录或退出 GitLab 的每个人,无论其项目成员身份如何,都可以浏览该网站. +4. Click **保存更改**. + +下次有人尝试访问您的网站并启用访问控制时,将向他们显示一个页面,以登录 GitLab 并验证他们可以访问该网站. + +## Terminating a Pages session[](#terminating-a-pages-session "Permalink") + +如果要从 Pages 网站注销,可以通过撤销 GitLab Pages 的应用程序访问令牌来注销: + +1. 浏览至个人资料的**"设置">"应用程序"** . +2. 在页面底部找到**授权的应用程序** . +3. 查找**GitLab 页面** ,然后按**撤消**按钮. \ No newline at end of file diff --git a/_book/docs/251.md b/_book/docs/251.md new file mode 100644 index 0000000000000000000000000000000000000000..28a2dec9336841ea064d069b43cfb3f90d087833 --- /dev/null +++ b/_book/docs/251.md @@ -0,0 +1,249 @@ +# Exploring GitLab Pages + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/introduction.html](https://docs.gitlab.com/ee/user/project/pages/introduction.html) + +* [GitLab Pages requirements](#gitlab-pages-requirements) +* [GitLab Pages on GitLab.com](#gitlab-pages-on-gitlabcom) +* [Example projects](#example-projects) +* [Custom error codes Pages](#custom-error-codes-pages) +* [Redirects in GitLab Pages](#redirects-in-gitlab-pages) +* [GitLab Pages Access Control](#gitlab-pages-access-control-core) +* [Unpublishing your Pages](#unpublishing-your-pages) +* [Limitations](#limitations) +* [Specific configuration options for Pages](#specific-configuration-options-for-pages) + * [`.gitlab-ci.yml` for plain HTML websites](#gitlab-ciyml-for-plain-html-websites) + * [`.gitlab-ci.yml` for a static site generator](#gitlab-ciyml-for-a-static-site-generator) + * [`.gitlab-ci.yml` for a repository where there’s also actual code](#gitlab-ciyml-for-a-repository-where-theres-also-actual-code) + * [Serving compressed assets](#serving-compressed-assets) + * [Resolving ambiguous URLs](#resolving-ambiguous-urls) +* [Frequently Asked Questions](#frequently-asked-questions) + * [Can I download my generated pages?](#can-i-download-my-generated-pages) + * [Can I use GitLab Pages if my project is private?](#can-i-use-gitlab-pages-if-my-project-is-private) + * [Do I need to create a user/group website before creating a project website?](#do-i-need-to-create-a-usergroup-website-before-creating-a-project-website) +* [Known issues](#known-issues) + +# Exploring GitLab Pages[](#exploring-gitlab-pages "Permalink") + +本文档是用户指南,用于探索 GitLab Pages 提供的选项和设置. + +首先要熟悉 GitLab 页面: + +* 阅读[有关 GitLab Pages](index.html#overview)的[介绍](index.html#overview) . +* Learn [how to get started with Pages](index.html#getting-started). +* 在[管理员文档中](../../../administration/pages/index.html)了解如何在整个 GitLab 实例上启用 GitLab 页面. + +## GitLab Pages requirements[](#gitlab-pages-requirements "Permalink") + +简而言之,这是您需要在 GitLab 页面中上传网站的内容: + +1. 实例的域:用于 GitLab 页面的域名(询问管理员). +2. GitLab CI / CD:一个`.gitlab-ci.yml`文件,在存储库的根目录中有一个名为[`pages`](../../../ci/yaml/README.html#pages)的特定作业. +3. 您网站存储库中一个名为`public`的目录,其中包含要发布的内容. +4. 为项目启用了 GitLab Runner. + +## GitLab Pages on GitLab.com[](#gitlab-pages-on-gitlabcom "Permalink") + +如果您使用[GitLab.com](#gitlab-pages-on-gitlabcom)上的[GitLab 页面](#gitlab-pages-on-gitlabcom)来托管您的网站,则: + +* The domain name for GitLab Pages on GitLab.com is `gitlab.io`. +* 自定义域和 TLS 支持已启用. +* 共享运行器默认情况下处于启用状态,免费提供,可用于构建您的网站. 如果您愿意,仍然可以携带自己的跑步者. + +## Example projects[](#example-projects "Permalink") + +访问[GitLab 页面组](https://gitlab.com/groups/pages)以获得示例项目的完整列表. 欢迎捐款. + +## Custom error codes Pages[](#custom-error-codes-pages "Permalink") + +您可以通过在将包含在工件中的`public/`目录的根目录中分别创建`403.html`和`404.html`文件来提供自己的 403 和 404 错误页面. 通常,这是项目的根目录,但是根据您的静态生成器配置,它可能有所不同. + +如果是`404.html` ,则有不同的方案. 例如: + +* 如果您使用项目 Pages(在`/projectname/` )并尝试访问`/projectname/non/existing_file` ,则 GitLab Pages 将尝试首先提供`/projectname/404.html` ,然后提供`/404.html` . +* 如果您使用用户/组页面(在`/`下提供)并尝试访问`/non/existing_file` GitLab Pages 将尝试提供`/404.html` . +* 如果您使用自定义域并尝试访问`/non/existing_file` ,则 GitLab Pages 将尝试仅提供`/404.html` . + +## Redirects in GitLab Pages[](#redirects-in-gitlab-pages "Permalink") + +由于您不能使用任何自定义服务器配置文件(例如`.htaccess`或任何`.conf`文件),因此,如果要将页面重定向到其他位置,可以使用[HTTP meta refresh 标签](https://en.wikipedia.org/wiki/Meta_refresh) . + +一些静态网站生成器提供了该功能的插件,因此您不必手动创建和编辑 HTML 文件. 例如,Jekyll 具有[redirect-from 插件](https://github.com/jekyll/jekyll-redirect-from) . + +## GitLab Pages Access Control[](#gitlab-pages-access-control-core "Permalink") + +要限制对您网站的访问,请启用[GitLab 页面访问控制](pages_access_control.html) . + +## Unpublishing your Pages[](#unpublishing-your-pages "Permalink") + +如果您需要清除 Pages 内容,可以通过右上角的齿轮图标进入项目设置,然后导航至**Pages** . 点击**删除页面**按钮,您的页面网站将被删除. + +[![Remove pages](img/987208c515a3f2627904cc38b355dc15.png)](img/remove_pages.png) + +## Limitations[](#limitations "Permalink") + +在 GitLab 实例的常规域( `*.example.io` )下使用 Pages 时, *不能*将 HTTPS 与子子域一起使用. 这意味着,如果你的用户名或组名称中包含一个圆点,例如`foo.bar` ,域`https://foo.bar.example.io`将*无法*正常工作. 这是[HTTP Over TLS 协议](https://tools.ietf.org/html/rfc2818#section-3.1)的限制. 如果您不将 HTTP 重定向到 HTTPS,HTTP 页面将继续工作. + +GitLab 网页[**不**支持组为网站分组](../../group/subgroups/index.html#limitations) . 您只能创建最高级别的群组网站. + +## Specific configuration options for Pages[](#specific-configuration-options-for-pages "Permalink") + +了解如何针对特定用例设置 GitLab CI / CD. + +### `.gitlab-ci.yml` for plain HTML websites[](#gitlab-ciyml-for-plain-html-websites "Permalink") + +假设您的存储库包含以下文件: + +``` +├── index.html +├── css +│ └── main.css +└── js + └── main.js +``` + +然后,下面的`.gitlab-ci.yml`示例仅将所有文件从项目的根目录移至`public/`目录. `.public`解决方法是, `cp`不会在无限循环中将`public/`复制到自身: + +``` +pages: + script: + - mkdir .public + - cp -r * .public + - mv .public public + artifacts: + paths: + - public + only: + - master +``` + +### `.gitlab-ci.yml` for a static site generator[](#gitlab-ciyml-for-a-static-site-generator "Permalink") + +请参阅本文档,以获取[分步指南](getting_started/pages_from_scratch.html) . + +### `.gitlab-ci.yml` for a repository where there’s also actual code[](#gitlab-ciyml-for-a-repository-where-theres-also-actual-code "Permalink") + +请记住,默认情况下,GitLab 页面是分支/标签不可知的,它们的部署仅取决于您在`.gitlab-ci.yml`指定`.gitlab-ci.yml` . 每当将新的提交推送到专门用于页面的分支时,就可以使用[`only`参数](../../../ci/yaml/README.html#onlyexcept-basic)限制`pages`作业. + +这样,您可以将项目的代码保存在`master`分支中,并使用一个孤儿分支(将其命名为`pages` )来托管您的静态生成器站点. + +您可以这样创建一个新的空分支: + +``` +git checkout --orphan pages +``` + +在这个新分支上进行的第一次提交将没有父母,这将是与所有其他分支和提交完全脱节的新历史的根源. 在`pages`分支中推送静态生成器的源文件. + +以下是`.gitlab-ci.yml`的副本,其中最重要的一行是最后一行,指定要执行`pages`分支中的所有`pages` : + +``` +image: ruby:2.6 + +pages: + script: + - gem install jekyll + - jekyll build -d public/ + artifacts: + paths: + - public + only: + - pages +``` + +请参见一个示例,该示例在[`master`分支](https://gitlab.com/pages/jekyll-branched/tree/master)中具有不同的文件,而 Jekyll 的源文件在[`pages`分支中](https://gitlab.com/pages/jekyll-branched/tree/pages) ,该[分支](https://gitlab.com/pages/jekyll-branched/tree/pages)还包含`.gitlab-ci.yml` . + +### Serving compressed assets[](#serving-compressed-assets "Permalink") + +大多数现代的浏览器都支持下载压缩格式的文件. 通过减小文件大小,可以加快下载速度. + +Pages 将提供未压缩的文件之前,将检查是否存在扩展名为`.gz`的相同文件. 如果支持,并且浏览器支持接收压缩文件,它将使用该版本而不是未压缩版本. + +要利用此功能,您上传到页面的工件应具有以下结构: + +``` +public/ +├─┬ index.html +│ └ index.html.gz +│ +├── css/ +│ └─┬ main.css +│ └ main.css.gz +│ +└── js/ + └─┬ main.js + └ main.js.gz +``` + +这可以通过在`.gitlab-ci.yml`页面作业中包含以下`script:`来实现: + +``` +pages: + # Other directives + script: + # Build the public/ directory first + - find public -type f -regex '.*\.\(htm\|html\|txt\|text\|js\|css\)$' -exec gzip -f -k {} \; +``` + +通过预压缩文件并在工件中包括两个版本,Pages 可以处理对压缩和未压缩内容的请求,而无需按需压缩文件. + +### Resolving ambiguous URLs[](#resolving-ambiguous-urls "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/95) + +当接收到不包含扩展名的 URL 的请求时,GitLab Pages 会假设要提供哪些文件. + +考虑使用以下文件部署的 Pages 站点: + +``` +public/ +├─┬ index.html +│ ├ data.html +│ └ info.html +│ +├── data/ +│ └── index.html +├── info/ +│ └── details.html +└── other/ + └── index.html +``` + +页面支持通过几个不同的 URL 来访问每个文件. 特别是,如果 URL 仅指定目录,它将始终寻找`index.html`文件. 如果该 URL 引用了一个不存在的文件,但是将`.html`添加到该 URL 中会导致该文件*确实*存在,将改为提供该文件. 以下是在上述 Pages 网站上发生的情况的一些示例: + +| URL path | HTTP 响应 | 文件送达 | +| --- | --- | --- | +| `/` | `200 OK` | `public/index.html` | +| `/index.html` | `200 OK` | `public/index.html` | +| `/index` | `200 OK` | `public/index.html` | +| `/data` | `200 OK` | `public/data/index.html` | +| `/data/` | `200 OK` | `public/data/index.html` | +| `/data.html` | `200 OK` | `public/data.html` | +| `/info` | `200 OK` | `public/info.html` | +| `/info/` | `200 OK` | `public/info.html` | +| `/info.html` | `200 OK` | `public/info.html` | +| `/info/details` | `200 OK` | `public/info/details.html` | +| `/info/details.html` | `200 OK` | `public/info/details.html` | +| `/other` | `302 Found` | `public/other/index.html` | +| `/other/` | `200 OK` | `public/other/index.html` | +| `/other/index` | `200 OK` | `public/other/index.html` | +| `/other/index.html` | `200 OK` | `public/other/index.html` | + +**注意:**当存在`public/data/index.html`时,对于`/data`和`/data/` URL 路径,其优先于`public/data.html`文件. + +## Frequently Asked Questions[](#frequently-asked-questions "Permalink") + +### Can I download my generated pages?[](#can-i-download-my-generated-pages "Permalink") + +当然. 您需要做的就是从作业页面下载工件存档. + +### Can I use GitLab Pages if my project is private?[](#can-i-use-gitlab-pages-if-my-project-is-private "Permalink") + +是. GitLab Pages 不在乎将项目的可见性级别设置为私有,内部还是公共. + +### Do I need to create a user/group website before creating a project website?[](#do-i-need-to-create-a-usergroup-website-before-creating-a-project-website "Permalink") + +不,你没有. 您可以先创建您的项目,然后将在`http(s)://namespace.example.io/projectname`下对其进行访问. + +## Known issues[](#known-issues "Permalink") + +有关已知问题的列表,请访问 GitLab 的[公共问题跟踪器](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name[]=Category:Pages) . \ No newline at end of file diff --git a/_book/docs/252.md b/_book/docs/252.md new file mode 100644 index 0000000000000000000000000000000000000000..5f410fd0de4e381c2bca9f1348405e141ceb7241 --- /dev/null +++ b/_book/docs/252.md @@ -0,0 +1,104 @@ +# Incremental Rollouts with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/environments/incremental_rollouts.html](https://docs.gitlab.com/ee/ci/environments/incremental_rollouts.html) + +* [Manual Rollouts](#manual-rollouts) +* [Timed Rollouts](#timed-rollouts) +* [Blue-Green Deployment](#blue-green-deployment) + +# Incremental Rollouts with GitLab CI/CD[](#incremental-rollouts-with-gitlab-cicd "Permalink") + +在对应用程序进行更改时,可以将生产更改仅发布到 Kubernetes 吊舱的一部分,作为降低风险的策略. 通过逐步发布生产更改,可以监视错误率或性能下降,并且如果没有问题,则可以更新所有吊舱. + +manbetx 客户端打不开支持使用增量卷展到 Kubernetes 生产系统的手动触发和定时卷展. 使用"手动卷展"时,将手动触发每个吊舱的释放,而在"定时卷展"中,默认的暂停时间为 5 分钟,然后按批次进行释放. 也可以在暂停时间到期之前手动触发定时启动. + +手动和定时卷展栏自动包含在由[AutoDevOps](../../topics/autodevops/index.html)控制的项目中,但也可以通过 GitLab CI / CD 在`.gitlab-ci.yml`配置文件中`.gitlab-ci.yml`配置. + +可以使用" [持续交付"](../introduction/index.html#continuous-delivery)方法来实现手动触发的部署,而定时部署不需要干预,并且可以作为" [持续部署"](../introduction/index.html#continuous-deployment)策略的一部分. 您还可以通过自动部署应用程序的方式将两者结合在一起,除非最终在必要时进行手动干预. + +我们创建了示例应用程序来演示这三个选项,您可以将其用作构建自己的示例: + +* [Manual incremental rollouts](https://gitlab.com/gl-release/incremental-rollout-example/blob/master/.gitlab-ci.yml) +* [Timed incremental rollouts](https://gitlab.com/gl-release/timed-rollout-example/blob/master/.gitlab-ci.yml) +* [Both manual and timed rollouts](https://gitlab.com/gl-release/incremental-timed-rollout-example/blob/master/.gitlab-ci.yml) + +## Manual Rollouts[](#manual-rollouts "Permalink") + +在 GitLab 10.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/5415) . + +可以将 GitLab 配置为通过`.gitlab-ci.yml`手动进行增量部署. 手动配置允许对该功能进行更多控制. 增量部署的步骤取决于为部署定义的 Pod 数量,这些 Pod 是在创建 Kubernetes 集群时配置的. + +例如,如果您的应用程序有 10 个容器,并且运行了 10%的部署作业,则该应用程序的新实例将被部署到单个容器中,而其余 9 个将显示前一个实例. + +首先,我们[将模板定义为手动](https://gitlab.com/gl-release/incremental-rollout-example/blob/master/.gitlab-ci.yml#L100-103) : + +``` +.manual_rollout_template: &manual_rollout_template + <<: *rollout_template + stage: production + when: manual +``` + +然后,我们[定义每个步骤的推出量](https://gitlab.com/gl-release/incremental-rollout-example/blob/master/.gitlab-ci.yml#L152-155) : + +``` +rollout 10%: + <<: *manual_rollout_template + variables: + ROLLOUT_PERCENTAGE: 10 +``` + +When the jobs are built, a **play** button will appear next to the job’s name. Click the **play** button to release each stage of pods. You can also rollback by running a lower percentage job. Once 100% is reached, you cannot roll back using this method. It is still possible to roll back by redeploying the old version using the **Rollback** button on the environment page. + +[![Play button](img/184e7323733c8aa9331e3fbef102e17c.png)](img/incremental_rollouts_play_v12_7.png) + +一个[可部署的应用程序](https://gitlab.com/gl-release/incremental-rollout-example)可用,演示了手动触发的增量部署. + +## Timed Rollouts[](#timed-rollouts "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7545) . + +定时部署的行为与手动部署的行为相同,不同之处在于,每个作业在部署前都会延迟几分钟. 单击作业将显示倒计时. + +[![Timed rollout](img/261e6c6422bccbb978c24c0728f3a593.png)](img/timed_rollout_v12_7.png) + +可以将此功能与手动增量部署相结合,以便作业倒计时然后部署. + +首先,我们[将模板定义为 timed](https://gitlab.com/gl-release/timed-rollout-example/blob/master/.gitlab-ci.yml#L86-89) : + +``` +.timed_rollout_template: &timed_rollout_template + <<: *rollout_template + when: delayed + start_in: 1 minutes +``` + +我们可以使用`start_in`键定义延迟时间: + +``` +start_in: 1 minutes +``` + +然后,我们[定义每个步骤的推出量](https://gitlab.com/gl-release/timed-rollout-example/blob/master/.gitlab-ci.yml#L97-101) : + +``` +timed rollout 30%: + <<: *timed_rollout_template + stage: timed rollout 30% + variables: + ROLLOUT_PERCENTAGE: 30 +``` + +一个[可部署的应用程序](https://gitlab.com/gl-release/timed-rollout-example)可用, [演示了定时部署的配置](https://gitlab.com/gl-release/timed-rollout-example/blob/master/.gitlab-ci.yml#L86-95) . + +## Blue-Green Deployment[](#blue-green-deployment "Permalink") + +有时也称为 A / B 部署或红黑色部署,此技术用于减少部署期间的停机时间和风险. 当与增量推出结合使用时,您可以最大程度地减少导致问题的部署的影响. + +使用这种技术,有两种部署方式("蓝色"和"绿色",但是可以使用任何命名). 在任何给定时间,这些部署中只有一个处于活动状态,除非在增量部署期间. + +例如,您的蓝色部署当前可以在生产中处于活动状态,而绿色部署"处于活动状态"可以进行测试,但不能部署到生产中. 如果发现问题,则可以在不影响生产部署的情况下更新绿色部署(当前为蓝色). 如果测试没有问题,则将生产切换到绿色部署,并且蓝色现在可用于测试下一个版本. + +此过程减少了停机时间,因为无需停止生产部署即可切换到其他部署. 两种部署都并行运行,并且可以随时切换到. + +提供了一个[示例可部署应用程序](https://gitlab.com/gl-release/blue-green-example) ,带有一个[`gitlab-ci.yml` CI / CD 配置文件](https://gitlab.com/gl-release/blue-green-example/blob/master/.gitlab-ci.yml) ,该[文件](https://gitlab.com/gl-release/blue-green-example/blob/master/.gitlab-ci.yml)演示了蓝绿色的部署. \ No newline at end of file diff --git a/_book/docs/253.md b/_book/docs/253.md new file mode 100644 index 0000000000000000000000000000000000000000..7d9bfa0ba4e4b4cdac673a1df64901eced6be5da --- /dev/null +++ b/_book/docs/253.md @@ -0,0 +1,45 @@ +# Interactive Web Terminals + +> 原文:[https://docs.gitlab.com/ee/ci/interactive_web_terminal/](https://docs.gitlab.com/ee/ci/interactive_web_terminal/) + +* [Configuration](#configuration) +* [Debugging a running job](#debugging-a-running-job) +* [Interactive Web Terminals for the Web IDE](#interactive-web-terminals-for-the-web-ide) + +# Interactive Web Terminals[](#interactive-web-terminals "Permalink") + +在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/50144) . + +交互式 Web 终端使用户可以访问 GitLab 中的终端,以为其 CI 管道运行一次性命令. 由于这使用户可以通过外壳访问[GitLab Runner](https://docs.gitlab.com/runner/)部署环境,因此采取了一些[安全预防](../../administration/integration/terminal.html#security)措施来保护用户. + +**注意:** [GitLab.com 上的共享跑步者](../quick_start/README.html#shared-runners)不提供交互式 Web 终端. 请遵循[此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/24674)以获取增加支持方面的进展. 对于在 GitLab.com 上托管的组和项目,使用自己的组或项目运行器时可以使用交互式 Web 终端. + +## Configuration[](#configuration "Permalink") + +为了使交互式 Web 终端正常工作,需要配置两件事: + +* 跑步者需要[正确配置`[session_server]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) +* 如果您在 GitLab 实例上使用反向代理,则需要[启用](../../administration/integration/terminal.html#enabling-and-disabling-terminal-support) Web 终端 + +**注意:** [`gitlab-runner` Helm chart](https://docs.gitlab.com/charts/charts/gitlab/gitlab-runner/index.html)尚不支持交互式 Web 终端,但[已计划](https://gitlab.com/gitlab-org/charts/gitlab-runner/-/issues/79)支持. + +## Debugging a running job[](#debugging-a-running-job "Permalink") + +**注意:**并非所有执行程序都[受支持](https://docs.gitlab.com/runner/executors/) .**注意:**构建脚本完成后, `docker` executor 不会继续运行. 届时,终端将自动断开连接,并且不会等待用户完成操作. 请关注[此问题,](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3605)以获取有关改进此行为的更新. + +有时,当一项作业正在运行时,事情并没有按您期望的那样进行,如果可以有一个外壳来帮助调试,这将很有帮助. 运行作业时,在右侧面板上可以看到一个`debug`按钮,它将打开当前作业的终端. + +[![Example of job running with terminal +available](img/206da14c2b9fd76390be58e7103b69c7.png)](img/interactive_web_terminal_running_job.png) + +单击后,新选项卡将打开到终端页面,您可以在其中访问终端并键入命令,如普通的 shell. + +[![terminal of the job](img/86b62f200c6aa129ed945d20ec0fbfa2.png)](img/interactive_web_terminal_page.png) + +如果您打开终端并且作业已完成其任务,则终端将在[`[session_server].session_timeout`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)配置的持续时间内阻止作业完成,直到关闭终端窗口. + +[![finished job with terminal open](img/2823aaef9502e47fb72734606099a98a.png)](img/finished_job_with_terminal_open.png) + +## Interactive Web Terminals for the Web IDE[](#interactive-web-terminals-for-the-web-ide "Permalink") + +阅读 Web IDE 文档,以了解如何[通过 Web IDE](../../user/project/web_ide/index.html#interactive-web-terminals-for-the-web-ide)运行[交互式终端](../../user/project/web_ide/index.html#interactive-web-terminals-for-the-web-ide) . \ No newline at end of file diff --git a/_book/docs/254.md b/_book/docs/254.md new file mode 100644 index 0000000000000000000000000000000000000000..6e84d270f17bb26de57606615cdb739f725892c3 --- /dev/null +++ b/_book/docs/254.md @@ -0,0 +1,206 @@ +# Optimizing GitLab for large repositories + +> 原文:[https://docs.gitlab.com/ee/ci/large_repositories/](https://docs.gitlab.com/ee/ci/large_repositories/) + +* [Shallow cloning](#shallow-cloning) +* [Git strategy](#git-strategy) +* [Git clone path](#git-clone-path) +* [Git clean flags](#git-clean-flags) +* [Git fetch extra flags](#git-fetch-extra-flags) +* [Fork-based workflow](#fork-based-workflow) + * [`shell` executor example](#shell-executor-example) + * [`docker` executor example](#docker-executor-example) + * [Our `.gitlab-ci.yml`](#our-gitlab-ciyml) + * [Store custom clone options in `config.toml`](#store-custom-clone-options-in-configtoml) + +# Optimizing GitLab for large repositories[](#optimizing-gitlab-for-large-repositories "Permalink") + +通常,由于克隆和签出所需的时间,在工作树中包含超过 5 万个文件的大型存储库通常需要特别考虑. + +GitLab 和 GitLab Runner 可以很好地处理这种情况,但是需要优化的配置才能有效地执行其操作. + +处理大型存储库的一般准则很简单. 以下各节将更详细地描述每个准则: + +* 始终以增量方式获取. 请勿以导致重新创建所有工作树的方式进行克隆. +* 始终使用浅克隆来减少数据传输. 请注意,由于 CPU 影响更大,这给 GitLab 实例带来了更多负担. +* 如果您大量使用基于 fork 的工作流,请控制克隆目录. +* 优化`git clean`标志,以确保删除或保留可能影响或加快构建速度的数据. + +## Shallow cloning[](#shallow-cloning "Permalink") + +在 GitLab Runner 8.9 中引入. + +默认情况下,GitLab 和 GitLab Runner 始终执行完整克隆. 虽然这意味着已收到来自 GitLab 的所有更改,但通常会导致接收额外的提交日志. + +理想情况下,您应始终使用`GIT_DEPTH` ,该数字应较小,例如 10.这将指示 GitLab Runner 执行浅表克隆. 浅克隆使 Git 仅请求给定分支的最新一组更改,最多达到`GIT_DEPTH`变量定义的所需提交`GIT_DEPTH` . + +这极大地加快了从 Git 存储库获取更改的速度,特别是如果存储库积压的事务由很多个大文件组成的积压很长时,因为我们有效地减少了数据传输量. + +以下示例使 GitLab Runner 浅表克隆仅获取给定的分支; 它不会获取任何其他分支或标签. + +``` +variables: + GIT_DEPTH: 10 + +test: + script: + - ls -al +``` + +## Git strategy[](#git-strategy "Permalink") + +在 GitLab Runner 8.9 中引入. + +默认情况下,GitLab 配置为始终首选`GIT_STRATEGY: fetch`策略. 如果在磁盘上找到`GIT_STRATEGY: fetch`策略,则会重新使用现有的工作树. 这与`GIT_STRATEGY: clone`策略不同, `GIT_STRATEGY: clone`一样,如果找到了工作树,则会在克隆之前将其删除. + +首选使用`fetch` ,因为它会减少要传输的数据量,并且不会真正影响您可能会从 CI 对存储库执行的操作. + +但是, `fetch`确实需要访问以前的工作树. 使用时,这种运作良好, `shell`或`docker`执行,因为这些努力保持 worktrees,默认情况下尽量重复使用它们. + +目前不适用于`kubernetes`执行器,并且在使用`kubernetes` `docker+machine`时有限制. `kubernetes`执行器总是克隆到临时目录中. + +GitLab 还提供了`GIT_STRATEGY: none`策略. 这会禁用任何由 GitLab 完成的`fetch`和`checkout`命令,要求您执行这些操作. + +## Git clone path[](#git-clone-path "Permalink") + +在 GitLab Runner 11.10 中引入. + +[`GIT_CLONE_PATH`](../yaml/README.html#custom-build-directories)允许您控制在何处克隆源. 如果您在 fork 工作流中大量使用大型存储库,则可能会产生影响. + +从 GitLab Runner 的角度来看,前叉工作流存储为具有单独工作树的单独存储库. 这意味着 GitLab Runner 无法优化工作树的使用,您可能必须指示 GitLab Runner 使用它. + +在这种情况下,理想情况下,您希望使 GitLab Runner 执行程序仅用于给定项目,而不是在不同项目之间共享,以使此过程更高效. + +[`GIT_CLONE_PATH`](../yaml/README.html#custom-build-directories)必须在`$CI_BUILDS_DIR` . 当前,不可能从磁盘选择任何路径. + +## Git clean flags[](#git-clean-flags "Permalink") + +在 GitLab Runner 11.10 中引入. + +[`GIT_CLEAN_FLAGS`](../yaml/README.html#git-clean-flags)允许您控制是否要求对每个 CI 作业执行`git clean`命令. 默认情况下,GitLab 确保您的工作树在给定的 SHA 上,并且您的存储库是干净的. + +设置为`none`时,将禁用[`GIT_CLEAN_FLAGS`](../yaml/README.html#git-clean-flags) . 在非常大的存储库上,这可能是理想的,因为`git clean`是磁盘 I / O 密集型的. 使用`GIT_CLEAN_FLAGS: -ffdx -e .build/`控制`GIT_CLEAN_FLAGS: -ffdx -e .build/` (例如)使您可以控制和禁用后续运行之间工作树中某些目录的删除,这可以加快增量生成的速度. 如果您重复使用现有计算机并拥有可用于构建的现有工作树,则效果最大. + +有关[`GIT_CLEAN_FLAGS`](../yaml/README.html#git-clean-flags)接受的确切参数,请参见[`git clean`](https://git-scm.com/docs/git-clean)的文档. 可用参数取决于 Git 版本. + +## Git fetch extra flags[](#git-fetch-extra-flags "Permalink") + +在 GitLab Runner 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4142) . + +[`GIT_FETCH_EXTRA_FLAGS`](../yaml/README.html#git-fetch-extra-flags) allows you to modify `git fetch` behavior by passing extra flags. + +有关更多信息,请参见[`GIT_FETCH_EXTRA_FLAGS`文档](../yaml/README.html#git-fetch-extra-flags) . + +## Fork-based workflow[](#fork-based-workflow "Permalink") + +在 GitLab Runner 11.10 中引入. + +遵循以上准则,让我们假设我们想要: + +* 针对大型项目进行优化(目录中有超过 5 万个文件). +* 使用基于分叉的工作流进行贡献. +* 重用现有的工作树. 预先配置了存储库的预配置运行器. +* 赛跑者仅分配给项目和所有分叉. + +让我们考虑以下两个示例,一个使用`shell` executor,另一个使用`docker` executor. + +### `shell` executor example[](#shell-executor-example "Permalink") + +假设您具有以下[`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) . + +``` +concurrent = 4 + +[[runners]] + url = "GITLAB_URL" + token = "TOKEN" + executor = "shell" + builds_dir = "/builds" + cache_dir = "/cache" + + [runners.custom_build_dir] + enabled = true +``` + +This `config.toml`: + +* 使用`shell`执行器, +* 指定一个自定义`/builds`目录,其中将存储所有克隆. +* 启用指定`GIT_CLONE_PATH` , +* 一次最多运行 4 个作业. + +### `docker` executor example[](#docker-executor-example "Permalink") + +假设您具有以下[`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) . + +``` +concurrent = 4 + +[[runners]] + url = "GITLAB_URL" + token = "TOKEN" + executor = "docker" + builds_dir = "/builds" + cache_dir = "/cache" + + [runners.docker] + volumes = ["/builds:/builds", "/cache:/cache"] +``` + +This `config.toml`: + +* 使用`docker` executor, +* 在磁盘上指定将存储所有克隆的自定义`/builds`目录. 我们在主机上挂载`/builds`目录,以使其在后续运行之间可重复使用,并允许其覆盖克隆策略. +* 默认情况下已启用,因此未启用指定`GIT_CLONE_PATH`功能. +* 一次最多运行 4 个作业. + +### Our `.gitlab-ci.yml`[](#our-gitlab-ciyml "Permalink") + +一旦配置了执行程序,就需要微调`.gitlab-ci.yml` . + +Our pipeline will be most performant if we use the following `.gitlab-ci.yml`: + +``` +variables: + GIT_DEPTH: 10 + GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_NAME + +build: + script: ls -al +``` + +上面配置了: + +* 浅克隆 10,以加快后续`git fetch`命令的速度. +* 自定义克隆路径,使我们可以在父项目和所有分支之间重用工作树,因为我们对所有分支使用相同的克隆路径. + +为什么要使用`$CI_CONCURRENT_ID` ? 主要原因是要确保使用的工作树在项目之间不冲突. `$CI_CONCURRENT_ID`表示给定执行器中的唯一标识符,因此只要我们使用它来构造路径,就可以确保该目录不会与其他正在运行的并发作业冲突. + +### Store custom clone options in `config.toml`[](#store-custom-clone-options-in-configtoml "Permalink") + +理想情况下,所有与作业相关的配置都应存储在`.gitlab-ci.yml` . 但是,有时希望使这些方案成为 Runner 配置的一部分. + +在以上 Forks 的示例中,使此配置对于用户可发现可能是首选,但这会带来管理开销,因为需要为每个分支更新`.gitlab-ci.yml` . 在这种情况下,可能希望保持`.gitlab-ci.yml`克隆路径不可知,但是将其配置为 Runner. + +我们可以使用以下规范扩展[`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) ,如果`.gitlab-ci.yml`不覆盖它,它将由 Runner 使用: + +``` +concurrent = 4 + +[[runners]] + url = "GITLAB_URL" + token = "TOKEN" + executor = "docker" + builds_dir = "/builds" + cache_dir = "/cache" + + environment = [ + "GIT_DEPTH=10", + "GIT_CLONE_PATH=$CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_NAME" + ] + + [runners.docker] + volumes = ["/builds:/builds", "/cache:/cache"] +``` + +这使得克隆配置成为给定 Runner 的一部分,并且不需要我们更新每个`.gitlab-ci.yml` . \ No newline at end of file diff --git a/_book/docs/255.md b/_book/docs/255.md new file mode 100644 index 0000000000000000000000000000000000000000..e64cc6b42df354242b07d1bef877bbc1a711fb4a --- /dev/null +++ b/_book/docs/255.md @@ -0,0 +1,60 @@ +# Metrics Reports + +> 原文:[https://docs.gitlab.com/ee/ci/metrics_reports.html](https://docs.gitlab.com/ee/ci/metrics_reports.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [How it works](#how-it-works) +* [How to set it up](#how-to-set-it-up) +* [Advanced Example](#advanced-example) + +# Metrics Reports[](#metrics-reports-premium "Permalink") + +在[GitLab Premium](https://about.gitlab.com/pricing/) 11.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9788) . 需要 GitLab Runner 11.10 及更高版本. + +## Overview[](#overview "Permalink") + +GitLab 提供了许多用于[合并请求](../user/project/merge_requests/index.html)的出色报告工具[-JUnit 报告](junit_test_reports.html) , [代码质量](../user/project/merge_requests/code_quality.html) ,性能测试等.尽管 JUnit 是用于"通过"或"失败"的测试的出色开放框架,但查看其他类型的测试也很重要.给定更改的指标. + +您可以将作业配置为使用自定义指标报告,并且 GitLab 会在合并请求上显示报告,以便更轻松,更快速地识别更改而无需检查整个日志. + +[![Metrics Reports](img/a6d06d0c4a54ff34856e0fbc07a50a60.png)](img/metrics_reports_v13_0.png) + +## Use cases[](#use-cases "Permalink") + +考虑以下可以利用指标报告的数据示例: + +1. 内存使用情况 +2. 负载测试结果 +3. 代码复杂度 +4. 代码覆盖率统计 + +## How it works[](#how-it-works "Permalink") + +从指标报告中读取指标(默认值: `metrics.txt` ). 它们被解析并显示在 MR 小部件中. + +所有值都视为字符串,并且使用字符串比较来查找来自以下各项的最新可用`metrics`工件之间的差异: + +* `master` +* 功能分支 + +## How to set it up[](#how-to-set-it-up "Permalink") + +添加一个创建[指标报告](pipelines/job_artifacts.html#artifactsreportsmetrics-premium)的作业(默认文件名: `metrics.txt` ). 该文件应符合[OpenMetrics](https://openmetrics.io/)格式. + +例如: + +``` +metrics: + script: + - echo 'metric_name metric_value' > metrics.txt + artifacts: + reports: + metrics: metrics.txt +``` + +## Advanced Example[](#advanced-example "Permalink") + +OpenMetrics 文本文件的高级示例(来自[Prometheus 文档](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-format-example) )在合并请求小部件中呈现为: + +[![Metrics Reports Advanced](img/1ab2181cd0be5aa7d8e96f16a1348ef9.png)](img/metrics_reports_advanced_v13_0.png) \ No newline at end of file diff --git a/_book/docs/256.md b/_book/docs/256.md new file mode 100644 index 0000000000000000000000000000000000000000..66dd12cbf8e6f84b77dea5452c83da471109cc3b --- /dev/null +++ b/_book/docs/256.md @@ -0,0 +1,498 @@ +# CI/CD pipelines + +> 原文:[https://docs.gitlab.com/ee/ci/pipelines/](https://docs.gitlab.com/ee/ci/pipelines/) + +* [Types of pipelines](#types-of-pipelines) +* [Configure a pipeline](#configure-a-pipeline) + * [View pipelines](#view-pipelines) + * [Run a pipeline manually](#run-a-pipeline-manually) + * [Run a pipeline by using a URL query string](#run-a-pipeline-by-using-a-url-query-string) + * [Add manual interaction to your pipeline](#add-manual-interaction-to-your-pipeline) + * [Start multiple manual actions in a stage](#start-multiple-manual-actions-in-a-stage) + * [Delete a pipeline](#delete-a-pipeline) + * [Pipeline quotas](#pipeline-quotas) + * [How pipeline duration is calculated](#how-pipeline-duration-is-calculated) + * [Pipeline security on protected branches](#pipeline-security-on-protected-branches) +* [View jobs in a pipeline](#view-jobs-in-a-pipeline) + * [See why a job failed](#see-why-a-job-failed) + * [The order of jobs in a pipeline](#the-order-of-jobs-in-a-pipeline) + * [Group jobs in a pipeline](#group-jobs-in-a-pipeline) + * [Specifying variables when running manual jobs](#specifying-variables-when-running-manual-jobs) + * [Delay a job](#delay-a-job) + * [Expand and collapse job log sections](#expand-and-collapse-job-log-sections) + * [Custom collapsible sections](#custom-collapsible-sections) +* [Visualize pipelines](#visualize-pipelines) + * [Regular pipeline graphs](#regular-pipeline-graphs) + * [Pipeline mini graphs](#pipeline-mini-graphs) + * [Pipeline success and duration charts](#pipeline-success-and-duration-charts) + * [Pipeline badges](#pipeline-badges) +* [Pipelines API](#pipelines-api) +* [Troubleshooting `fatal: reference is not a tree:`](#troubleshooting-fatal-reference-is-not-a-tree) + +# CI/CD pipelines[](#cicd-pipelines "Permalink") + +在 GitLab 8.8 中引入. + +**提示:**观看["精通持续软件开发"](https://about.gitlab.com/webcast/mastering-ci-cd/)网络广播,以观看 GitLab CI / CD 管道的全面演示. + +管道是持续集成,交付和部署的顶级组件. + +Pipelines comprise: + +* 作业,定义*要做*什么. 例如,编译或测试代码的作业. +* 阶段,定义*何时*运行作业. 例如,在编译代码的阶段之后运行测试的阶段. + +作业由[Runners](../runners/README.html)执行. 如果有足够的并发运行程序,则可以并行执行同一阶段中的多个作业. + +如果一个阶段中的*所有*作业*都*成功,则管道将继续进行下一个阶段. + +If *any* job in a stage fails, the next stage is not (usually) executed and the pipeline ends early. + +通常,管道是自动执行的,创建后就无需干预. 但是,有时您还可以手动与管道进行交互. + +典型的管道可能包含四个阶段,按以下顺序执行: + +* 一个`build`阶段,其工作称为`compile` . +* 一个`test`阶段,具有两个作业,分别称为`test1`和`test2` . +* `staging`阶段,其工作称为`deploy-to-stage` . +* `production`阶段,其工作称为`deploy-to-prod` . + +**注意:**如果您有[从 GitLab 提取镜像的存储库,则](../../user/project/repository/repository_mirroring.html#pulling-from-a-remote-repository-starter)可能需要在项目的**"设置">"存储库">"从远程存储库中提取">"触发管道更新镜像"中**启用管道触发. + +## Types of pipelines[](#types-of-pipelines "Permalink") + +管道可以通过许多不同的方式进行配置: + +* [基本管道](pipeline_architectures.html#basic-pipelines)在每个阶段同时运行所有内容,随后是下一阶段. +* [定向非循环图管线(DAG)管线](../directed_acyclic_graph/index.html)基于作业之间的关系,并且比基本管线运行得更快. +* [多项目管道](../multi_project_pipelines.html)将不同项目的[管道](../multi_project_pipelines.html)组合在一起. +* [父子管道](../parent_child_pipelines.html)将复杂的管道分解为一个父管道,该管道可以触发多个子管道,这些子管道都在同一项目中并以相同的 SHA 运行. +* [合并请求的管道仅针对合并请求](../merge_request_pipelines/index.html)运行(而不是针对每次提交). +* [合并结果管道](../merge_request_pipelines/pipelines_for_merged_results/index.html)是合并请求管道,其作用就像源分支的更改已被合并到目标分支一样. +* [合并列车](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)使用管道获取合并结果,以使合并一个接一个地排队. + +## Configure a pipeline[](#configure-a-pipeline "Permalink") + +在 CI / CD 管道配置文件中为每个项目定义了管道及其组件作业和阶段. + +* 作业是[基本的配置](../yaml/README.html#introduction)组件. +* 阶段是通过使用[`stages`](../yaml/README.html#stages)关键字定义的. + +有关 CI 管道文件中配置选项的列表,请参见《 [GitLab CI / CD 管道配置参考》](../yaml/README.html) . + +您还可以通过 GitLab UI 配置管道的特定方面. 例如: + +* 每个项目的[管道设置](settings.html) . +* [Pipeline schedules](schedules.html). +* [Custom CI/CD variables](../variables/README.html#custom-environment-variables). + +### View pipelines[](#view-pipelines "Permalink") + +您可以在项目的**CI / CD>管道**页面下找到当前和历史管道运行. 您还可以通过导航到" **管道"**选项卡来访问合并请求的**管道** . + +[![Pipelines index page](img/44be1cce97f886ea1f1c93950d764041.png)](img/pipelines_index_v13_0.png) + +单击管道将带您进入" **管道详细信息"**页面,并显示为该管道运行的作业. 在这里,您可以取消正在运行的管道,在发生故障的管道上重试作业或[删除管道](#delete-a-pipeline) . + +[从 GitLab 12.3 开始,](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/50499)可以在`/project/pipelines/[branch]/latest`找到指向给定分支的最后提交的最新管道的链接. 另外, `/project/pipelines/latest`会将您重定向到项目默认分支上最后一次提交的最新管道. + +[从 GitLab 13.0 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/215367) ,您可以通过以下方式过滤管道列表: + +* 触发作者 +* 分店名称 +* 状态( [自 GitLab 13.1 起](https://gitlab.com/gitlab-org/gitlab/-/issues/217617) ) +* 标签( [自 GitLab 13.1 起](https://gitlab.com/gitlab-org/gitlab/-/issues/217617) ) + +### Run a pipeline manually[](#run-a-pipeline-manually "Permalink") + +可以使用预定义或手动指定的[变量](../variables/README.html)手动执行管道. + +如果在管道的正常操作之外需要管道的结果(例如,代码生成),则可以执行此操作. + +要手动执行管道: + +1. 导航到项目的**CI / CD>管道** . +2. 单击**运行管道**按钮. +3. 在" **运行管道"**页面上: + 1. 在" **创建位置"**字段中选择要为其运行管道的分支. + 2. 输入管道运行所需的任何[环境变量](../variables/README.html) . + 3. 单击**创建管道**按钮. + +管道将按照配置执行作业. + +### Run a pipeline by using a URL query string[](#run-a-pipeline-by-using-a-url-query-string "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/24146) . + +您可以使用查询字符串来预填充" **运行管道"**页面. 例如,查询字符串`.../pipelines/new?ref=my_branch&var[foo]=bar&file_var[file_foo]=file_bar`将使用以下内容预填充" **运行管道"**页面: + +* **竞选** field: `my_branch`. +* **Variables** section: + * Variable: + * Key: `foo` + * Value: `bar` + * File: + * Key: `file_foo` + * Value: `file_bar` + +`pipelines/new` URL 的格式为: + +``` +.../pipelines/new?ref=&var[]=&file_var[]= +``` + +支持以下参数: + +* `ref` :指定用于填充" **运行为"**字段的分支. +* `var` :指定一个`Variable`变量. +* `file_var` :指定一个`File`变量. + +对于每个`var`或`file_var` ,都需要一个键和一个值. + +### Add manual interaction to your pipeline[](#add-manual-interaction-to-your-pipeline "Permalink") + +在 GitLab 8.15 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7931) . + +使用[`when:manual`](../yaml/README.html#whenmanual)参数配置的手动操作使您可以要求手动交互,然后才能在管道中继续前进. + +您可以直接从管道图执行此操作. 只需单击播放按钮即可执行该特定作业. + +例如,您的管道可能会自动启动,但是需要手动操作才能[部署到生产中](../environments/index.html#configuring-manual-deployments) . 在下面的示例中, `production`阶段有一个需要手动操作的工作. + +[![Pipelines example](img/d2f0725099f8a66ed235d537ea6592a4.png)](img/pipelines.png) + +#### Start multiple manual actions in a stage[](#start-multiple-manual-actions-in-a-stage "Permalink") + +在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27188) . + +可以使用"全部播放手动"按钮同时启动一个阶段中的多个手动动作. 用户单击此按钮后,将触发每个单独的手动操作并将其刷新为更新状态. + +此功能仅可用: + +* 至少具有开发者访问权限的用户. +* 如果阶段包含[手动操作](#add-manual-interaction-to-your-pipeline) . + +### Delete a pipeline[](#delete-a-pipeline "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/24851) . + +在项目中具有[所有者权限的](../../user/permissions.html)用户可以通过以下方式删除管道:单击**CI / CD>管道中的管道**以转到" **管道详细信息"**页面,然后使用" **删除"**按钮. + +[![Pipeline Delete Button](img/86614ecfb76f8a91344d98d3effa7d2a.png)](img/pipeline-delete.png) + +**警告:**删除管道将使所有管道缓存失效,并删除所有相关对象,例如构建,日志,工件和触发器. **此操作无法撤消.** + +### Pipeline quotas[](#pipeline-quotas "Permalink") + +每个用户都有一个个人管道配额,该配额跟踪所有个人项目中共享运行者的使用情况. 每个组都有一个[使用配额](../../subscriptions/index.html#ci-pipeline-minutes) ,该[配额](../../subscriptions/index.html#ci-pipeline-minutes)跟踪该组内创建的所有项目的共享运行器的使用. + +触发管道时,无论是谁触发的,都会使用项目所有者的[名称空间](../../user/group/index.html#namespaces)的管道配额. 在这种情况下,名称空间可以是拥有项目的用户或组. + +#### How pipeline duration is calculated[](#how-pipeline-duration-is-calculated "Permalink") + +给定管道的总运行时间不包括重试和挂起(排队)时间. + +每个作业都表示为一个`Period` ,它包括: + +* `Period#first` (作业开始时). +* `Period#last` (作业完成时). + +一个简单的例子是: + +* A(1、3) +* B(2,4) +* C(6、7) + +在示例中: + +* A 从 1 开始到 3 结束. +* B 从 2 开始到 4 结束. +* C 从 6 开始到 7 结束. + +在视觉上,它可以被视为: + +``` +0 1 2 3 4 5 6 7 + AAAAAAA + BBBBBBB + CCCC +``` + +A,B 和 C 的并集是(1、4)和(6、7). 因此,总运行时间为: + +``` +(4 - 1) + (7 - 6) => 4 +``` + +### Pipeline security on protected branches[](#pipeline-security-on-protected-branches "Permalink") + +在[受保护的分支](../../user/project/protected_branches.html)上执行管道时,将强制执行严格的安全模型. + +仅当[允许](../../user/project/protected_branches.html#using-the-allowed-to-merge-and-allowed-to-push-settings)用户[合并或推送到](../../user/project/protected_branches.html#using-the-allowed-to-merge-and-allowed-to-push-settings)该特定分支时,才可以在受保护的分支上执行以下操作: + +* 运行手动管道(使用[Web UI](#run-a-pipeline-manually)或[管道 API](#pipelines-api) ). +* 运行预定的管道. +* 使用触发器运行管道. +* 在现有管道上触发手动操作. +* 重试或取消现有作业(使用 Web UI 或管道 API). + +标记为**受保护的** **变量**只能由在受保护的分支上运行的作业访问,从而防止不受信任的用户意外访问敏感信息,如部署凭据和令牌. + +**运动员**标记为**保护**只能保护分支机构运行的作业,防止不可信代码在受保护亚军执行和不小心被访问保护部署密钥和其它凭证. 为了确保打算在受保护的运行程序上执行的作业不会使用常规运行程序,必须对它们进行相应标记. + +## View jobs in a pipeline[](#view-jobs-in-a-pipeline "Permalink") + +访问管道时,可以看到该管道的相关作业. + +单击单个作业将向您显示其作业日志,并允许您: + +* 取消作业. +* 重试该作业. +* 删除作业日志. + +### See why a job failed[](#see-why-a-job-failed "Permalink") + +在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17782) . + +当管道发生故障或被允许失败时,可以在几个地方找到原因: + +* 在[管道图中](#visualize-pipelines) ,在管道详细信息视图上. +* 在管道小部件中,在合并请求和提交页面中. +* 在工作视图中,在工作的全局视图和详细视图中. + +在每个地方,如果将鼠标悬停在失败的作业上,都可以看到失败的原因. + +[![Pipeline detail](img/b6069220bf06467d1d434d3652c5d82a.png)](img/job_failure_reason.png) + +在[GitLab 10.8](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17814)及更高版本中,您还可以在"作业详细信息"页面上查看其失败的原因. + +### The order of jobs in a pipeline[](#the-order-of-jobs-in-a-pipeline "Permalink") + +管道中作业的顺序取决于管道图的类型. + +* 对于[常规管道图](#regular-pipeline-graphs) ,按名称对作业进行排序. +* 对于[管道微型图](#pipeline-mini-graphs) ,将按严重性然后按名称对作业进行排序. + +严重性顺序为: + +* failed +* warning +* pending +* running +* manual +* scheduled +* canceled +* success +* skipped +* created + +例如: + +[![Pipeline mini graph sorting](img/9abb23a34d42854b307382ef64d9a013.png)](img/pipelines_mini_graph_sorting.png) + +### Group jobs in a pipeline[](#group-jobs-in-a-pipeline "Permalink") + +在 GitLab 8.12 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6242) . + +如果您有许多类似的工作,则[管道图](#visualize-pipelines)将变得很长且难以阅读. + +您可以自动将相似的作业分组在一起. 如果以某种方式格式化作业名称,它们将在常规管道图(而不是迷你图)中折叠为一组. + +如果看不到管道中的重试或取消按钮,您将知道管道何时将其分组. 将鼠标悬停在它们上面将显示分组的作业数. 单击以展开它们. + +[![Grouped pipelines](img/0d6a90afbcbb1f9414d4a9a8437e49f8.png)](img/pipelines_grouped.png) + +要创建一组作业,请在[CI / CD 管道配置文件中](../yaml/README.html) ,用数字和以下其中一个分隔每个作业名称: + +* 斜线( `/` ),例如`test 1/3` , `test 2/3` , `test 3/3` . +* 冒号( `:` )中,例如, `test 1:3` , `test 2:3` , `test 3:3` . +* 一个空格,例如`test 0 3` , `test 1 3` , `test 2 3` . + +您可以互换使用这些符号. + +例如,这三个作业将在一个名为`build ruby`的组中: + +``` +build ruby 1/3: + stage: build + script: + - echo "ruby1" + +build ruby 2/3: + stage: build + script: + - echo "ruby2" + +build ruby 3/3: + stage: build + script: + - echo "ruby3" +``` + +在管道中,结果是一个名为`build ruby`的组,具有三个作业: + +[![Job group](img/7bcf8d15daa1fb25935d7638acd8eb43.png)](img/job_group_v12_10.png) + +作业将通过从左到右比较数字进行排序. 通常,您希望第一个数字为索引,第二个数字为总数. + +[此正则表达式](https://gitlab.com/gitlab-org/gitlab/blob/2f3dc314f42dbd79813e6251792853bc231e69dd/app/models/commit_status.rb#L99)计算作业名称: `\d+[\s:\/\\]+\d+\s*` . + +### Specifying variables when running manual jobs[](#specifying-variables-when-running-manual-jobs "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30485) . + +运行手动作业时,您可以提供其他特定于作业的变量. + +您可以从要运行其他变量的手动作业的作业页面执行此操作. 要访问此页面,请在管道视图中单击手动作业的**名称** , *而不是*播放( )按钮. + +当您想要更改使用[自定义环境变量](../variables/README.html#custom-environment-variables)的作业的执行时,这很有用. 在此处添加变量名称(键)和值将覆盖[UI 或`.gitlab-ci.yml`](../variables/README.html#custom-environment-variables)定义的值,以供手动运行一次. + +[![Manual job variables](img/185cfb126a59b17e7d802717876f8725.png)](img/manual_job_variables.png) + +### Delay a job[](#delay-a-job "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21767) . + +当您不想立即运行作业时,可以使用[`when:delayed`](../yaml/README.html#whendelayed)参数将作业的执行延迟一定时间. + +这对于定时增量式部署特别有用,在这种情况下,新代码将逐步推出. + +例如,如果您开始推出新代码并执行以下操作: + +* 用户不会遇到麻烦,GitLab 可以从 0%到 100%自动完成部署. +* 用户在使用新代码时会遇到麻烦,您可以通过取消管道并[回滚](../environments/index.html#retrying-and-rolling-back)到最后一个稳定版本来停止定时增量推出. + +[![Pipelines example](img/3444bd33319e0b2d996233cf9e1103c5.png)](img/pipeline_incremental_rollout.png) + +### Expand and collapse job log sections[](#expand-and-collapse-job-log-sections "Permalink") + +在 GitLab 12.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14664) . + +作业日志分为可折叠或扩展的部分. 每个部分将显示持续时间. + +在以下示例中: + +* 两个部分已折叠并且可以展开. +* 三个部分被展开并且可以折叠. + +[![Collapsible sections](img/53dc09446080b42329a76d4ecbb64aa3.png)](img/collapsible_log_v12_6.png) + +#### Custom collapsible sections[](#custom-collapsible-sections "Permalink") + +您可以通过手动输出特殊代码来在作业日志中创建可折叠部分,GitLab 将使用这些特殊代码来确定要折叠的部分: + +* 节开始标记: `section_start:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + `TEXT_OF_SECTION_HEADER` +* 节结束标记: `section_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + +您必须将这些代码添加到 CI 配置的脚本部分. 例如,使用`echo` : + +``` +job1: + script: + - echo -e "section_start:`date +%s`:my_first_section\r\e[0KHeader of the 1st collapsible section" + - echo 'this line should be hidden when collapsed' + - echo -e "section_end:`date +%s`:my_first_section\r\e[0K" +``` + +在上面的示例中: + +* `date +%s` :Unix 时间戳(例如`1560896352` ). +* `my_first_section` :为节指定的名称. +* `\r\e[0K` :阻止区域标记显示在渲染的(彩色)作业日志中,但它们显示在原始作业日志中. 要查看它们,请在作业日志的右上方,单击 ( **显示完整的原始文件** ). + * `\r` :回车. + * `\e[0K` :清除 ANSI 转义代码. + +原始作业日志样本: + +``` +section_start:1560896352:my_first_section\r\e[0KHeader of the 1st collapsible section +this line should be hidden when collapsed +section_end:1560896353:my_first_section\r\e[0K +``` + +## Visualize pipelines[](#visualize-pipelines "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5742) . + +管道可以是具有许多顺序和并行作业的复杂结构. + +为了更容易理解管道的流程,GitLab 提供了管道图来查看管道及其状态. + +管道图可以两种不同的方式显示,具体取决于您从中访问该图的页面. + +**注意:** GitLab 在管线图中将各阶段的名称大写. + +### Regular pipeline graphs[](#regular-pipeline-graphs "Permalink") + +常规管道图显示每个阶段的作业名称. 当您在[单个管道页面](#view-pipelines)上时,可以找到常规管道图. 例如: + +[![Pipelines example](img/d2f0725099f8a66ed235d537ea6592a4.png)](img/pipelines.png) + +[多项目管道图可](../multi_project_pipelines.html#multi-project-pipeline-visualization-premium)帮助您可视化整个管道,包括所有跨项目的相互依存关系. + +### Pipeline mini graphs[](#pipeline-mini-graphs "Permalink") + +管道微型图占用的空间更少,并且可以一眼告诉您所有作业都通过还是失败. 当您导航到以下位置时,可以找到管道迷你图: + +* 管道索引页面. +* 单个提交页面. +* 合并请求页面. + +管道微型图使您可以查看一次提交的所有相关作业以及管道每个阶段的最终结果. 这使您可以快速查看失败的原因并进行修复. + +管道微型图中的阶段是可折叠的. 将鼠标悬停在他们上方,然后单击以展开他们的工作. + +| 迷你图 | 迷你图展开 | +| --- | --- | +| [![Pipelines mini graph](img/12e557e74666b1c90827cdd5bfe4d87a.png)](img/pipelines_mini_graph_simple.png) | [![Pipelines mini graph extended](img/28ba73ced40f830058c21c46c8291bfe.png)](img/pipelines_mini_graph.png) | + +### Pipeline success and duration charts[](#pipeline-success-and-duration-charts "Permalink") + +版本历史 + +* 在 GitLab 3.1.1 中作为"提交统计信息"引入,后来更名为"管线图". +* 在 GitLab 12.8 中[重命名](https://gitlab.com/gitlab-org/gitlab/-/issues/38318)为 CI / CD Analytics. + +GitLab 跟踪您的管道成功与失败的历史记录,以及每个管道的运行时间. 要查看此信息,请转到**分析> CI / CD 分析** . + +查看成功的管道: + +[![Successful pipelines](img/a88692f85b1b05ca94199204a3cc1f00.png)](img/pipelines_success_chart.png) + +查看管道持续时间历史记录: + +[![Pipeline duration](img/6867e53bf251ef0cb0e190c2e702d188.png)](img/pipelines_duration_chart.png) + +### Pipeline badges[](#pipeline-badges "Permalink") + +管道状态和测试覆盖率报告标记可用于每个项目,并可对其进行配置. 有关将管道标记添加到项目的信息,请参见[管道标记](settings.html#pipeline-badges) . + +## Pipelines API[](#pipelines-api "Permalink") + +GitLab 提供 API 端点以: + +* 执行基本功能. 有关更多信息,请参见[Pipelines API](../../api/pipelines.html) . +* 维护管道时间表. 有关更多信息,请参见[管道时间表 API](../../api/pipeline_schedules.html) . +* 触发管道运行. 有关更多信息,请参见: + * [通过 API 触发管道](../triggers/README.html) . + * [管道触发器 API](../../api/pipeline_triggers.html) . + +## Troubleshooting `fatal: reference is not a tree:`[](#troubleshooting-fatal-reference-is-not-a-tree "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17043) . + +以前,当您强制将分支推入其远程存储库时,会遇到意外的管道故障. 为了说明问题,假设您已经拥有当前的工作流程: + +1. 用户创建一个名为`example`的功能分支并将其推送到远程存储库. +2. 新的管道开始在`example`分支上运行. +3. 用户将`example`分支基于最新的`master`分支,然后将其强制推送到其远程存储库. +4. 新的管道再次在`example`分支上运行,但是,先前的管道(2)由于`fatal: reference is not a tree:`错误`fatal: reference is not a tree:`失败. + +这是因为先前的管道无法从`example`分支中找到校验历史 SHA(与管道记录相关联),该历史历史已被强制推送覆盖. 同样,由于[相同的原因](../merge_request_pipelines/pipelines_for_merged_results/index.html#intermittently-pipelines-fail-by-fatal-reference-is-not-a-tree-error) [,合并结果的管道](../merge_request_pipelines/pipelines_for_merged_results/index.html)可能会间歇性地失败. + +从 GitLab 12.4 开始,我们通过专门保留管道引用来改善了这种行为. 为了说明其生命周期: + +1. 在名为`example`的功能分支上创建了管道. +2. 在`refs/pipelines/`创建一个持久的管道 ref,该`refs/pipelines/`保留相关管道记录的 checkout-SHA. 即使在`example`分支的提交历史记录已被强制推送覆盖的情况下,该持久引用在管道执行期间也保持不变. +3. GitLab Runner fetches the persistent pipeline ref and gets source code from the checkout-SHA. +4. 管道完成后,将在后台进程中清除其持久引用. \ No newline at end of file diff --git a/_book/docs/257.md b/_book/docs/257.md new file mode 100644 index 0000000000000000000000000000000000000000..afba6d3365b7f3261f1ec8dddaa784e53af3ec6e --- /dev/null +++ b/_book/docs/257.md @@ -0,0 +1,217 @@ +# Pipeline Architecture + +> 原文:[https://docs.gitlab.com/ee/ci/pipelines/pipeline_architectures.html](https://docs.gitlab.com/ee/ci/pipelines/pipeline_architectures.html) + +* [Basic Pipelines](#basic-pipelines) +* [Directed Acyclic Graph Pipelines](#directed-acyclic-graph-pipelines) +* [Child / Parent Pipelines](#child--parent-pipelines) + +# Pipeline Architecture[](#pipeline-architecture "Permalink") + +管道是 GitLab 中 CI / CD 的基本构建块. 本页记录了一些与它们有关的重要概念. + +构造管道的主要方法有三种,每种都有自己的优势. 如果需要,可以混合使用以下方法: + +* [基本](#basic-pipelines) :适用于简单的项目,其中所有配置都在一个易于查找的位置. +* [有向无环图](#directed-acyclic-graph-pipelines) :适用于需要有效执行的大型,复杂项目. +* [子级/父级管道](#child--parent-pipelines) :适用于具有大量独立定义组件的 monorepos 和项目. + +有关下面使用的任何关键字的更多详细信息,请查看我们的[CI YAML 参考](../yaml/README.html)以获取详细信息. + +## Basic Pipelines[](#basic-pipelines "Permalink") + +这是 GitLab 中最简单的管道. 它会在构建阶段同时运行所有内容,一旦所有这些操作完成,它将以相同的方式在测试阶段运行所有内容,依此类推. 它不是最有效的,并且如果您有很多步骤,它可能会变得非常复杂,但更易于维护: + +图 LR 子图部署阶段部署-> deploy_a 部署-> deploy_b 结束子图测试阶段测试-> test_a 测试-> test_b 结束子图构建阶段构建-> build_a 构建-> build_b 结束 build_a -.->测试 build_b -.->测试 test_a -.->部署 test_b -.->部署 + +匹配该图的示例基本`/.gitlab-ci.yml`管道配置: + +``` +stages: + - build + - test + - deploy + +image: alpine + +build_a: + stage: build + script: + - echo "This job builds something." + +build_b: + stage: build + script: + - echo "This job builds something else." + +test_a: + stage: test + script: + - echo "This job tests something. It will only run when all jobs in the" + - echo "build stage are complete." + +test_b: + stage: test + script: + - echo "This job tests something else. It will only run when all jobs in the" + - echo "build stage are complete too. It will start at about the same time as test_a." + +deploy_a: + stage: deploy + script: + - echo "This job deploys something. It will only run when all jobs in the" + - echo "test stage complete." + +deploy_b: + stage: deploy + script: + - echo "This job deploys something else. It will only run when all jobs in the" + - echo "test stage complete. It will start at about the same time as deploy_a." +``` + +## Directed Acyclic Graph Pipelines[](#directed-acyclic-graph-pipelines "Permalink") + +如果效率对您很重要,并且您希望所有内容尽快运行,则可以使用有向无[环图(DAG)](../directed_acyclic_graph/index.html) . 使用[`needs`关键字](../yaml/README.html#needs)定义作业之间的依赖关系. 当 GitLab 知道您的工作之间的关系时,它可以尽快运行所有内容,甚至在可能的情况下跳入后续阶段. + +在下面的示例中,如果`build_a`和`test_a`的速度比`build_b`和`test_b` ,则即使`build_b`仍在运行,GitLab 也会启动`deploy_a` . + +使用 DAG build_a-> test_a-> deploy_a build_b-> test_b-> deploy_b 结束的图 LR 子图管道 + +匹配该图的示例 DAG `/.gitlab-ci.yml`配置: + +``` +stages: + - build + - test + - deploy + +image: alpine + +build_a: + stage: build + script: + - echo "This job builds something quickly." + +build_b: + stage: build + script: + - echo "This job builds something else slowly." + +test_a: + stage: test + needs: [build_a] + script: + - echo "This test job will start as soon as build_a finishes." + - echo "It will not wait for build_b, or other jobs in the build stage, to finish." + +test_b: + stage: test + needs: [build_b] + script: + - echo "This test job will start as soon as build_b finishes." + - echo "It will not wait for other jobs in the build stage to finish." + +deploy_a: + stage: deploy + needs: [test_a] + script: + - echo "Since build_a and test_a run quickly, this deploy job can run much earlier." + - echo "It does not need to wait for build_b or test_b." + +deploy_b: + stage: deploy + needs: [test_b] + script: + - echo "Since build_b and test_b run slowly, this deploy job will run much later." +``` + +## Child / Parent Pipelines[](#child--parent-pipelines "Permalink") + +在上面的示例中,很明显,我们可以独立构建两种类型的东西. 这是通过[`trigger`关键字](../yaml/README.html#trigger)使用" [子/父管道"](../parent_child_pipelines.html)的理想情况. 它将配置分成多个文件,使事情变得非常简单. 您还可以将其与: + +* [`rules`关键字](../yaml/README.html#rules) :例如,仅在对该区域进行更改时才触发子管道. +* [`include`关键字](../yaml/README.html#include) :引入常见行为,确保您不会重复自己. +* 子[管道](#directed-acyclic-graph-pipelines)内部的[DAG 管道](#directed-acyclic-graph-pipelines) ,实现了两者的好处. + +graph LR subgraph Parent pipeline trigger_a -.-> build_a trigger_b -.-> build_b subgraph child pipeline B build_b --> test_b --> deploy_b end subgraph child pipeline A build_a --> test_a --> deploy_a end end + +匹配该图的父管道的示例`/.gitlab-ci.yml`配置: + +``` +stages: + - triggers + +trigger_a: + stage: triggers + trigger: + include: a/.gitlab-ci.yml + rules: + - changes: + - a/* + +trigger_b: + stage: triggers + trigger: + include: b/.gitlab-ci.yml + rules: + - changes: + - b/* +``` + +例如孩子`a`管道配置,位于`/a/.gitlab-ci.yml` ,利用的 DAG `needs:`关键字: + +``` +stages: + - build + - test + - deploy + +image: alpine + +build_a: + stage: build + script: + - echo "This job builds something." + +test_a: + stage: test + needs: [build_a] + script: + - echo "This job tests something." + +deploy_a: + stage: deploy + needs: [test_a] + script: + - echo "This job deploys something." +``` + +子`b`管道配置示例位于`/b/.gitlab-ci.yml` ,利用 DAG `needs:`关键字: + +``` +stages: + - build + - test + - deploy + +image: alpine + +build_b: + stage: build + script: + - echo "This job builds something else." + +test_b: + stage: test + needs: [build_b] + script: + - echo "This job tests something else." + +deploy_b: + stage: deploy + needs: [test_b] + script: + - echo "This job deploys something else." +``` + +也可以将作业设置为在触发子管道之前或之后运行,例如,如果您具有通用的设置步骤或最后进行统一部署. \ No newline at end of file diff --git a/_book/docs/258.md b/_book/docs/258.md new file mode 100644 index 0000000000000000000000000000000000000000..a47dbd01d69b4558031df4584245ba0c9ffed6be --- /dev/null +++ b/_book/docs/258.md @@ -0,0 +1,92 @@ +# Directed Acyclic Graph + +> 原文:[https://docs.gitlab.com/ee/ci/directed_acyclic_graph/](https://docs.gitlab.com/ee/ci/directed_acyclic_graph/) + +* [Use cases](#use-cases) +* [Usage](#usage) +* [Limitations](#limitations) +* [DAG Visualization](#dag-visualization) + * [Enable or disable DAG Visualization](#enable-or-disable-dag-visualization-core-only) + +# Directed Acyclic Graph[](#directed-acyclic-graph "Permalink") + +版本历史 + +* 在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47063) . +* 在 GitLab 12.10 中[已删除功能标记](https://gitlab.com/gitlab-org/gitlab/-/issues/206902) . + +可以在 CI / CD 管道的上下文中使用有[向无环图,](https://www.techopedia.com/definition/5739/directed-acyclic-graph-dag)以建立作业之间的关系,从而以最快的方式执行,而不管如何设置阶段. + +例如,您可能拥有特定的工具或单独的网站,这些网站是作为主项目的一部分而构建的. 使用 DAG,您可以指定这些作业之间的关系,然后 GitLab 将尽快执行作业,而不是等待每个阶段完成. + +与其他针对 CI / CD 的 DAG 解决方案不同,GitLab 不需要您选择其中一个. 您可以在单个管道中实现 DAG 和传统的基于阶段的操作的混合组合. 配置非常简单,只需一个关键字即可为任何作业启用该功能. + +考虑如下的 monorepo: + +``` +./service_a +./service_b +./service_c +./service_d +``` + +它具有如下所示的管道: + +| build | test | deploy | +| --- | --- | --- | +| build_a | test_a | deploy_a | +| build_b | test_b | deploy_b | +| build_c | test_c | deploy_c | +| build_d | test_d | deploy_d | + +使用 DAG,您可以将`_a`作业与`_b`作业彼此关联,即使服务`a`构建时间很长,服务`b`也不会等待它,并且会尽快完成. 在这个非常相同的管道中, `_c`和`_d`可以单独放置,并且可以像任何普通的 GitLab 管道一样以分段的顺序一起运行. + +## Use cases[](#use-cases "Permalink") + +DAG 可以帮助解决 CI / CD 管道中作业之间的几种不同类型的关系. 最典型的情况是,当作业需要展开或展开和/或合并回去时(钻石相关性),这可以解决. 当您处理多平台构建或复杂的依赖关系网时,例如在操作系统构建或可独立部署但相关的微服务的复杂部署图中,可能会发生这种情况. + +此外,DAG 可以帮助提高管道的总体速度,并有助于提供快速反馈. 通过创建不会相互阻塞的依赖关系,您的管道将尽可能快地运行,而不管管道的阶段如何,从而确保开发人员可以尽快获得输出(包括错误). + +## Usage[](#usage "Permalink") + +使用[`needs:`关键字](../yaml/README.html#needs)定义作业之间的关系. + +请注意, `needs:`也可与[parallel](../yaml/README.html#parallel)关键字一起使用,从而为管道内的[并行化](../yaml/README.html#parallel)提供了强大的选项. + +## Limitations[](#limitations "Permalink") + +有向无环图是一个复杂的功能,从最初的 MVC 开始,您可能需要解决某些用例. 想要查询更多的信息: + +* [`needs` requirements and limitations](../yaml/README.html#requirements-and-limitations). +* 相关的史诗[跟踪计划的改进](https://gitlab.com/groups/gitlab-org/-/epics/1716) . + +## DAG Visualization[](#dag-visualization "Permalink") + +版本历史 + +* 在 GitLab 13.1 中作为[Beta 功能](https://about.gitlab.com/handbook/product/#beta) [引入](https://gitlab.com/gitlab-org/gitlab/-/issues/215517) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* [默认情况下](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36802)在 13.2 中[启用](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36802) . +* 在 GitLab.com 上启用了它. +* 对于 GitLab 自我管理的实例,GitLab 管理员可以选择[禁用它](#enable-or-disable-dag-visualization-core-only) . + +通过 DAG 可视化,可以更轻松地可视化 DAG 中依赖作业之间的关系. 此图将显示管道中需要或其他作业需要的所有作业. 没有关系的作业不会显示在该视图中. + +[![DAG visualization example](img/33ae5f16a8ad7c683e894a2a3032cfa9.png)](img/dag_graph_example_v13_1.png) + +单击节点将突出显示其依赖的所有作业路径. + +[![DAG visualization with path highlight](img/61dd95f1efb048c48f6ab843e79120d0.png)](img/dag_graph_example_clicked_v13_1.png) + +### Enable or disable DAG Visualization[](#enable-or-disable-dag-visualization-core-only "Permalink") + +DAG 可视化正在开发中,但已作为 Beta 功能提供,因此用户可以检查其限制和用途. + +它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../administration/feature_flags.html)可以选择为您的实例禁用它: + +``` +# Instance-wide +Feature.disable(:dag_pipeline_tab) +# or by project +Feature.disable(:dag_pipeline_tab, Project.find()) +``` \ No newline at end of file diff --git a/_book/docs/259.md b/_book/docs/259.md new file mode 100644 index 0000000000000000000000000000000000000000..c8ce11892168b9f762aaf982ff109107c3639fb1 --- /dev/null +++ b/_book/docs/259.md @@ -0,0 +1,219 @@ +# Multi-project pipelines + +> 原文:[https://docs.gitlab.com/ee/ci/multi_project_pipelines.html](https://docs.gitlab.com/ee/ci/multi_project_pipelines.html) + +* [Use cases](#use-cases) +* [Multi-project pipeline visualization](#multi-project-pipeline-visualization-premium) +* [Triggering multi-project pipelines through API](#triggering-multi-project-pipelines-through-api) +* [Creating multi-project pipelines from `.gitlab-ci.yml`](#creating-multi-project-pipelines-from-gitlab-ciyml) + * [Triggering a downstream pipeline using a bridge job](#triggering-a-downstream-pipeline-using-a-bridge-job) + * [Specifying a downstream pipeline branch](#specifying-a-downstream-pipeline-branch) + * [Passing variables to a downstream pipeline](#passing-variables-to-a-downstream-pipeline) + * [Mirroring status from triggered pipeline](#mirroring-status-from-triggered-pipeline) + * [Mirroring status from upstream pipeline](#mirroring-status-from-upstream-pipeline) + * [Limitations](#limitations) +* [Trigger a pipeline when an upstream project is rebuilt](#trigger-a-pipeline-when-an-upstream-project-is-rebuilt) + +# Multi-project pipelines[](#multi-project-pipelines "Permalink") + +版本历史 + +* 在 GitLab 7.14 中作为构建触发器[引入](https://about.gitlab.com/releases/2015/08/22/gitlab-7-14-released/#build-triggers-api-gitlab-ci) . +* 在 GitLab 12.8 中的所有层中[均可](https://gitlab.com/gitlab-org/gitlab/-/issues/199224)用. + +您可以跨多个项目设置[GitLab CI / CD](README.html) ,以便一个项目中的管道可以触发另一个项目中的管道. + +GitLab CI / CD 是一个功能强大的持续集成工具,不仅适用于每个项目,而且适用于具有多项目管道的项目. + +多项目管道对于需要跨项目相互依赖的较大产品很有用,例如采用[微服务架构的产品](https://about.gitlab.com/blog/2016/08/16/trends-in-version-control-land-microservices/) . + +有关跨功能开发团队如何使用跨管道触发来为不同的微服务项目触发多个管道的演示,请参阅[跨项目管道触发和可视化](https://about.gitlab.com/handbook/marketing/product-marketing/demo/#cross-project-pipeline-triggering-and-visualization-may-2019---1110) . + +此外,还可以可视化整个管道,包括所有跨项目的相互依存关系. + +## Use cases[](#use-cases "Permalink") + +Let’s assume you deploy your web app from different projects in GitLab: + +* 一个免费版本,它有自己的管道来构建和测试您的应用 +* 一个用于付费版本的附加组件,还可以通过构建和测试 +* 一个用于文档的文档,该文档还使用 SSG 进行构建,测试和部署 + +使用多项目管道,您可以可视化整个管道,包括三个项目的所有构建和测试阶段. + +## Multi-project pipeline visualization[](#multi-project-pipeline-visualization-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2121) in [GitLab Premium 9.3](https://about.gitlab.com/releases/2017/06/22/gitlab-9-3-released/#multi-project-pipeline-graphs). + +为项目配置 GitLab CI / CD 时,可以在[管道图](pipelines/index.html#visualize-pipelines)上可视化[作业](pipelines/index.html#configure-a-pipeline)的阶段. + +[![Multi-project pipeline graph](img/8013884e699eb543397343ba53b7f107.png)](img/multi_project_pipeline_graph.png) + +在"合并请求"小组件中,将显示多项目管道微型图,并且当悬停或轻击(在触摸屏设备上)时,它们将展开并显示为彼此相邻. + +[![Multi-project mini graph](img/c4c2d27f307636160d5773556cb14345.png)](img/multi_pipeline_mini_graph.gif) + +## Triggering multi-project pipelines through API[](#triggering-multi-project-pipelines-through-api "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 9.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2017)了`CI_JOB_TOKEN`在多项目管道中的使用. +* 在 GitLab 12.4 的所有层中都[可以](https://gitlab.com/gitlab-org/gitlab/-/issues/31573)将`CI_JOB_TOKEN`用于多项目管道. + +当您使用[`CI_JOB_TOKEN`触发管道时](triggers/README.html#ci-job-token) ,GitLab 会识别作业令牌的来源,因此在内部将这些管道[`CI_JOB_TOKEN`](triggers/README.html#ci-job-token)在一起,从而可以在管道图上可视化它们的关系. + +通过显示上游和下游管道依存关系的入站和出站连接,可以在管道图中显示这些关系. + +## Creating multi-project pipelines from `.gitlab-ci.yml`[](#creating-multi-project-pipelines-from-gitlab-ciyml "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) . +* 在 12.8 中[可](https://gitlab.com/gitlab-org/gitlab/-/issues/199224)用于所有层. + +### Triggering a downstream pipeline using a bridge job[](#triggering-a-downstream-pipeline-using-a-bridge-job "Permalink") + +在 GitLab 11.8 之前,有必要实现一个管道作业,该作业负责发出 API 请求[以触​​发](#triggering-multi-project-pipelines-through-api)另一个项目中[的管道](#triggering-multi-project-pipelines-through-api) . + +在 GitLab 11.8 中,GitLab 提供了新的 CI / CD 配置语法,使此任务更容易,并且避免需要 GitLab Runner 来触发跨项目管道. 下图说明了配置桥接作业: + +``` +rspec: + stage: test + script: bundle exec rspec + +staging: + variables: + ENVIRONMENT: staging + stage: deploy + trigger: my/deployment +``` + +在上面的示例中,一旦`rspec`作业在`test`阶段成功完成,则将启动`staging`桥作业. 该作业的初始状态将`pending` . manbetx 客户端打不开将在`my/deployment`项目中创建一个下游管道,并且,一旦创建管道, `staging`作业将成功. `my/deployment`是该项目的完整路径. + +创建上游管道的用户需要具有对下游项目的访问权限(在本例中为`my/deployment` ). 如果找不到下游项目,或者用户没有访问权限以在其中创建管道,则`staging`作业将被标记为*failed* . + +**警告:**在该示例中,一旦创建了下游管道,该`staging`将被标记为成功. 如果要显示下游管道的状态,请参阅[从触发的管道镜像状态](#mirroring-status-from-triggered-pipeline) .**注意:**对于常规作业,网桥作业不支持用户可以使用的每个配置条目. Runner 不会选择 Bridge 作业,因此添加对`script`支持毫无意义. 如果用户尝试使用不受支持的配置语法,则在创建管道时,YAML 验证将失败. + +### Specifying a downstream pipeline branch[](#specifying-a-downstream-pipeline-branch "Permalink") + +可以指定下游管道将使用的分支名称: + +``` +rspec: + stage: test + script: bundle exec rspec + +staging: + stage: deploy + trigger: + project: my/deployment + branch: stable-11-2 +``` + +Use: + +* `project`关键字,用于指定下游项目的完整路径. +* 该`branch`关键字指定由指定的项目分支的名称`project` . [从 GitLab 12.4 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/10126) ,支持变量扩展. + +在创建下游管道时,GitLab 将使用当前在分支的 HEAD 上的提交. + +### Passing variables to a downstream pipeline[](#passing-variables-to-a-downstream-pipeline "Permalink") + +有时您可能想将变量传递到下游管道. 您可以使用`variables`关键字来执行此操作,就像定义常规作业时一样. + +``` +rspec: + stage: test + script: bundle exec rspec + +staging: + variables: + ENVIRONMENT: staging + stage: deploy + trigger: my/deployment +``` + +`ENVIRONMENT`变量将传递到下游管道中定义的每个作业. 当 GitLab Runner 选择工作时,它将作为环境变量使用. + +在以下配置中, `MY_VARIABLE`变量将传递到在`trigger-downstream`作业排队时创建的下游管道. 这是因为`trigger-downstream`作业继承了在全局变量块中声明的变量,然后将这些变量传递到下游管道. + +``` +variables: + MY_VARIABLE: my-value + +trigger-downstream: + variables: + ENVIRONMENT: something + trigger: my/project +``` + +您可能想使用例如预定义的变量传递有关上游管道的一些信息. 为此,您可以使用插值传递任何变量. 例如: + +``` +downstream-job: + variables: + UPSTREAM_BRANCH: $CI_COMMIT_REF_NAME + trigger: my/project +``` + +在这种情况下,具有与上游管道相关的值的`UPSTREAM_BRANCH`变量将传递到`downstream-job`作业,并在所有下游构建的上下文中可用. + +**提示:**上游管道优先于下游管道. 如果在上游和下游项目中定义了两个具有相同名称的变量,则在上游项目中定义的变量将优先. + +### Mirroring status from triggered pipeline[](#mirroring-status-from-triggered-pipeline "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/11238) . +* 在 12.8 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) GitLab Core. + +您可以使用`strategy: depend`将镜像状态从触发的管道镜像到源网桥作业. 例如: + +``` +trigger_job: + trigger: + project: my/project + strategy: depend +``` + +### Mirroring status from upstream pipeline[](#mirroring-status-from-upstream-pipeline "Permalink") + +您可以使用`needs:pipeline`关键字将管道状态从上游管道镜像到桥作业. 来自主服务器的最新管道状态将复制到桥接作业. + +Example: + +``` +upstream_bridge: + stage: test + needs: + pipeline: other/project +``` + +### Limitations[](#limitations "Permalink") + +由于网桥作业与常规作业略有不同,因此此处无法使用完全相同的配置语法,就像在定义要由跑步者选择的常规作业时通常使用的配置语法一样. + +某些功能尚未实现. 例如,对环境的支持. + +可用于网桥作业的[配置关键字](yaml/README.html)是: + +* `trigger` (定义下游管道触发器) +* `stage` +* `allow_failure` +* [`rules`](yaml/README.html#rules) +* `only` and `except` +* `when` (仅适用于`on_success` , `on_failure`和`always`值为) +* `extends` + +## Trigger a pipeline when an upstream project is rebuilt[](#trigger-a-pipeline-when-an-upstream-project-is-rebuilt "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9045) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.8. + +You can trigger a pipeline in your project whenever a pipeline finishes for a new tag in a different project: + +1. 转到项目的**"设置">" CI / CD"**页面,然后展开" **管道订阅"**部分. +2. 输入您要订阅的项目的路径. +3. 单击订阅. + +现在,成功完成已订阅项目中新标签的任何管道都将在当前项目的默认分支上触发管道. 对于上游和下游项目,上游管道订阅的最大数量为 2. \ No newline at end of file diff --git a/_book/docs/260.md b/_book/docs/260.md new file mode 100644 index 0000000000000000000000000000000000000000..f817a4a7caba999eceac25dee1ede8ee2fd48902 --- /dev/null +++ b/_book/docs/260.md @@ -0,0 +1,133 @@ +# Parent-child pipelines + +> 原文:[https://docs.gitlab.com/ee/ci/parent_child_pipelines.html](https://docs.gitlab.com/ee/ci/parent_child_pipelines.html) + +* [Examples](#examples) +* [Merge Request child pipelines](#merge-request-child-pipelines) +* [Dynamic child pipelines](#dynamic-child-pipelines) +* [Limitations](#limitations) + +# Parent-child pipelines[](#parent-child-pipelines "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/16094) . + +随着管道变得越来越复杂,一些相关的问题开始出现: + +* 分阶段的结构(其中一个阶段的所有步骤必须在下一阶段的第一个作业开始之前完成)会导致任意等待,从而使事情变慢. +* 单个全局管道的配置变得非常漫长和复杂,使其难以管理. +* 使用[`include`](yaml/README.html#include)导入会增加配置的复杂性,并可能在无意间复制作业的情况下发生名称空间冲突. +* 如此多的工作和阶段可以使流水线用户体验变得笨拙. + +此外,有时管道的行为需要更动态. 选择启动(或不启动)子管道的功能是一项强大的功能,尤其是在动态生成 YAML 的情况下. + +[![Parent pipeline graph expanded](img/c5d0cec2b61194796c06f7c2c5294294.png)](img/parent_pipeline_graph_expanded_v12_6.png) + +与[多项目管道](multi_project_pipelines.html)类似,管道可以触发一组同时运行的子管道,但是在同一项目中: + +* 子管道仍按阶段顺序执行其每个作业,但可以自由地继续执行各个阶段,而不必等待父管道中无关的作业完成. +* 该配置分为较小的子管道配置,这些子管道配置更易于理解. 这减少了理解整体配置的认知负担. +* 导入在子管道级别进行,从而减少了发生冲突的可能性. +* 每个管道只有相关的步骤,因此更容易理解正在发生的事情. + +子管道可与其他 GitLab CI / CD 功能配合使用: + +* [`only: changes`](yaml/README.html#onlychangesexceptchanges)仅在某些文件更改时才触发管道. 例如,这对于 monorepos 很有用. +* 由于`.gitlab-ci.yml`的父管道和子管道都像普通管道一样运行,因此它们可以具有自己的行为和与触发器相关的顺序. + +所有这些都将与[`include:`](yaml/README.html#include)功能一起使用,因此您可以组成子管道配置. + +有关概述,请参见[父子管道功能演示](https://youtu.be/n8KpBSqZNbk) . + +## Examples[](#examples "Permalink") + +最简单的情况是使用本地 YAML 文件定义管道配置来[触发子管道](yaml/README.html#trigger) . 在这种情况下,父管道将触发子管道,并继续运行而无需等待: + +``` +microservice_a: + trigger: + include: path/to/microservice_a.yml +``` + +组成子管道时可以包含多个文件: + +``` +microservice_a: + trigger: + include: + - local: path/to/microservice_a.yml + - template: SAST.gitlab-ci.yml +``` + +**注意:** `trigger:include:`可接受的最大条目数为三. + +类似于[多项目管道](multi_project_pipelines.html#mirroring-status-from-triggered-pipeline) ,我们可以在完成时将父管道设置为依赖于子管道的状​​态: + +``` +microservice_a: + trigger: + include: + - local: path/to/microservice_a.yml + - template: SAST.gitlab-ci.yml + strategy: depend +``` + +## Merge Request child pipelines[](#merge-request-child-pipelines "Permalink") + +要将子管道触发为[合并请求管道,](merge_request_pipelines/index.html)我们需要: + +* 将触发器作业设置为在合并请求上运行: + +``` +# parent .gitlab-ci.yml +microservice_a: + trigger: + include: path/to/microservice_a.yml + rules: + - if: $CI_MERGE_REQUEST_ID +``` + +* 通过以下任一方式配置子管道: + + * 设置子管道中的所有作业以在合并请求的上下文中进行评估: + + ``` + # child path/to/microservice_a.yml + workflow: + rules: + - if: $CI_MERGE_REQUEST_ID + + job1: + script: ... + + job2: + script: ... + ``` + + * Alternatively, setting the rule per job. For example, to create only `job1` in the context of merge request pipelines: + + ``` + # child path/to/microservice_a.yml + job1: + script: ... + rules: + - if: $CI_MERGE_REQUEST_ID + + job2: + script: ... + ``` + +## Dynamic child pipelines[](#dynamic-child-pipelines "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/35632) . + +您可以定义一个作业,该作业运行您自己的脚本来生成 YAML 文件,而不是从静态 YAML 文件运行子管道,然后将其[用于触发子管道](yaml/README.html#trigger-child-pipeline-with-generated-configuration-file) . + +该技术在生成针对更改内容的流水线或构建目标和体系结构矩阵方面可能非常强大. + +有关概述,请参阅[使用动态生成的配置创建子管道](https://youtu.be/nMdfus2JWHM) . + +在 GitLab 12.9 中,在某些情况下可能无法创建子管道,从而导致父管道失败. 这[在 GitLab 12.10 中](https://gitlab.com/gitlab-org/gitlab/-/issues/209070)已[解决](https://gitlab.com/gitlab-org/gitlab/-/issues/209070) . + +## Limitations[](#limitations "Permalink") + +父管道可以触发许多子管道,但是子管道不能触发其他子管道. 请参阅[相关问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/29651)以获取有关未来可能改进的讨论. \ No newline at end of file diff --git a/_book/docs/261.md b/_book/docs/261.md new file mode 100644 index 0000000000000000000000000000000000000000..fac49c3451c026d1b3d6797e05525d962cf5c4ca --- /dev/null +++ b/_book/docs/261.md @@ -0,0 +1,186 @@ +# Pipelines for Merge Requests + +> 原文:[https://docs.gitlab.com/ee/ci/merge_request_pipelines/](https://docs.gitlab.com/ee/ci/merge_request_pipelines/) + +* [Prerequisites](#prerequisites) +* [Configuring pipelines for merge requests](#configuring-pipelines-for-merge-requests) + * [Use `rules` to run pipelines for merge requests](#use-rules-to-run-pipelines-for-merge-requests) + * [Use `only` or `except` to run pipelines for merge requests](#use-only-or-except-to-run-pipelines-for-merge-requests) + * [Excluding certain jobs](#excluding-certain-jobs) + * [Excluding certain branches](#excluding-certain-branches) +* [Pipelines for Merged Results](#pipelines-for-merged-results-premium) + * [Merge Trains](#merge-trains-premium) +* [Important notes about merge requests from forked projects](#important-notes-about-merge-requests-from-forked-projects) +* [Additional predefined variables](#additional-predefined-variables) +* [Troubleshooting](#troubleshooting) + * [Two pipelines created when pushing to a merge request](#two-pipelines-created-when-pushing-to-a-merge-request) + * [Two pipelines created when pushing an invalid CI configuration file](#two-pipelines-created-when-pushing-an-invalid-ci-configuration-file) + +# Pipelines for Merge Requests[](#pipelines-for-merge-requests "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/15310) . + +在[基本配置中](../pipelines/pipeline_architectures.html#basic-pipelines) ,每次更改被推送到分支时,GitLab 都会运行管道. + +如果希望管道**仅**在创建或更新合并请求时运行作业,则可以将*管道用于合并请求* . + +在用户界面中,这些管道被标记为`detached` . 否则,这些管道看起来与其他管道相同. + +具有开发者[权限的](../../user/permissions.html)任何用户都可以为合并请求运行管道. + +[![Merge request page](img/d5a5a91fe5e2b490b9388b43801b6a39.png)](img/merge_request.png) + +**Note:** If you use this feature with [merge when pipeline succeeds](../../user/project/merge_requests/merge_when_pipeline_succeeds.html), pipelines for merge requests take precedence over the other regular pipelines. + +## Prerequisites[](#prerequisites "Permalink") + +要为合并请求启用管道: + +* 您的存储库必须是 GitLab 存储库,而不是[外部存储库](../ci_cd_for_external_repos/index.html) . +* [在 GitLab 11.10 和更高版本中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25504) ,您必须使用 GitLab Runner 11.9. + +## Configuring pipelines for merge requests[](#configuring-pipelines-for-merge-requests "Permalink") + +要为合并请求配置管道,您需要配置[CI / CD 配置文件](../yaml/README.html) . 有几种不同的方法可以做到这一点: + +### Use `rules` to run pipelines for merge requests[](#use-rules-to-run-pipelines-for-merge-requests "Permalink") + +当使用`rules` ,这是首选方法,我们建议从[`workflow:rules`模板开始,](../yaml/README.html#workflowrules-templates)以确保基本配置正确. 该链接提供了有关如何执行此操作以及如何进行自定义的说明. + +### Use `only` or `except` to run pipelines for merge requests[](#use-only-or-except-to-run-pipelines-for-merge-requests "Permalink") + +If you want to continue using `only/except`, this is possible but please review the drawbacks below. + +使用此方法时,只需指定`only: - merge_requests`每个作业的`only: - merge_requests` . 在此示例中,管道包含配置为在合并请求上运行的`test`作业. + +`build`和`deploy`作业没有`only: - merge_requests`参数,因此它们将不会在合并请求上运行. + +``` +build: + stage: build + script: ./build + only: + - master + +test: + stage: test + script: ./test + only: + - merge_requests + +deploy: + stage: deploy + script: ./deploy + only: + - master +``` + +#### Excluding certain jobs[](#excluding-certain-jobs "Permalink") + +`only: [merge_requests]`参数的行为是, *只有*具有该参数的作业*才*在合并请求的上下文中运行; 没有其他作业将运行. + +但是,您可以反转此行为,并运行*除*一两个*之外的*所有作业. + +考虑下面的管道,作业`A` , `B`和`C` 假设您要: + +* 所有管道始终运行`A`和`B` +* `C`仅针对合并请求运行. + +为此,可以如下配置`.gitlab-ci.yml`文件: + +``` +.only-default: &only-default + only: + - master + - merge_requests + - tags + +A: + <<: *only-default + script: + - ... + +B: + <<: *only-default + script: + - ... + +C: + script: + - ... + only: + - merge_requests +``` + +Therefore: + +* 由于`A`和`B`在所有情况下都具有`only:`执行规则,因此它们将始终运行. +* 由于`C`指定仅针对合并请求运行,因此它将不会针对除合并请求管道之外的任何管道运行. + +这可以帮助您避免为所有作业添加`only:`规则,以使其始终运行. 您可以使用这种格式来设置评论应用,以帮助节省资源. + +#### Excluding certain branches[](#excluding-certain-branches "Permalink") + +[`only`](../yaml/README.html#onlyexcept-basic)使用[/ `except`](../yaml/README.html#onlyexcept-basic)时,合并请求的管道需要特殊处理. 与普通的分支引用(例如`refs/heads/my-feature-branch` )不同,合并请求引用使用特殊的 Git 引用,看起来像`refs/merge-requests/:iid/head` . 因此,以下配置将**无法**正常工作: + +``` +# Does not exclude a branch named "docs-my-fix"! +test: + only: [merge_requests] + except: [/^docs-/] +``` + +相反,可以将[`$CI_COMMIT_REF_NAME`预定义环境变量](../variables/predefined_variables.html)与[`only:variables`](../yaml/README.html#onlyvariablesexceptvariables)结合使用以完成此行为: + +``` +test: + only: [merge_requests] + except: + variables: + - $CI_COMMIT_REF_NAME =~ /^docs-/ +``` + +## Pipelines for Merged Results[](#pipelines-for-merged-results-premium "Permalink") + +阅读[有关合并结果的管道](pipelines_for_merged_results/index.html)的[文档](pipelines_for_merged_results/index.html) . + +### Merge Trains[](#merge-trains-premium "Permalink") + +阅读[有关合并火车](pipelines_for_merged_results/merge_trains/index.html)的[文档](pipelines_for_merged_results/merge_trains/index.html) . + +## Important notes about merge requests from forked projects[](#important-notes-about-merge-requests-from-forked-projects "Permalink") + +请注意,当前行为可能会更改. 在通常的贡献流程中,外部贡献者遵循以下步骤: + +1. 分叉一个父项目. +2. 从分支项目中创建一个以父项目中的`master`分支为目标的合并请求. +3. 管道在合并请求上运行. +4. 父项目的维护者检查管道结果,如果最新的管道通过,则合并到目标分支. + +当前,这些管道是在**派生**项目中创建的,而不是在父项目中创建的. 这意味着您不能完全信任管道结果,因为从技术上讲,外部贡献者可以通过在派生项目中调整其 GitLab Runner 来掩盖其管道结果. + +GitLab 不允许在父项目中创建这些管道有多种原因,但是最大的原因之一是安全性问题. 外部用户可以通过修改`.gitlab-ci.yml` (可能是某种凭据)从父项目中窃取秘密变量. 这不应该发生. + +我们正在讨论一种安全的解决方案,该解决方案针对从分支项目提交的合并请求运行管道,请参阅[有关权限扩展的问题](https://gitlab.com/gitlab-org/gitlab/-/issues/11934) . + +## Additional predefined variables[](#additional-predefined-variables "Permalink") + +通过将管道用于合并请求,GitLab 将其他预定义变量公开给管道作业. 这些变量包含关联的合并请求的信息,因此将您的作业与[GitLab 合并请求 API](../../api/merge_requests.html)集成非常有用. + +您可以在[参考表中](../variables/predefined_variables.html)找到可用变量的列表. 变量名称以`CI_MERGE_REQUEST_`前缀开头. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Two pipelines created when pushing to a merge request[](#two-pipelines-created-when-pushing-to-a-merge-request "Permalink") + +如果使用`rules`时遇到重复的管道,请查看[`rules`和`only` / `except`之间](../yaml/README.html#differences-between-rules-and-onlyexcept)的[重要区别](../yaml/README.html#differences-between-rules-and-onlyexcept) ,这将帮助您正确设置起始配置. + +如果您在使用`only/except`时看到两个管道,请参见上述与`only/except`一起使用的注意事项(或者,考虑使用`rules` ). + +### Two pipelines created when pushing an invalid CI configuration file[](#two-pipelines-created-when-pushing-an-invalid-ci-configuration-file "Permalink") + +推送到具有无效 CI 配置文件的分支会触发两种类型的失败管道的创建. 一个管道是失败的合并请求管道,另一个管道是失败的分支管道,但两者都是由相同的无效配置引起的. + +在极少数情况下,会创建重复的管道. + +有关详细信息,请参[见此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/201845) . \ No newline at end of file diff --git a/_book/docs/262.md b/_book/docs/262.md new file mode 100644 index 0000000000000000000000000000000000000000..e6f379633e0963b8757c30e17bf67adba4240e69 --- /dev/null +++ b/_book/docs/262.md @@ -0,0 +1,102 @@ +# Pipelines for Merged Results + +> 原文:[https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/) + +* [Prerequisites](#prerequisites) +* [Enable pipelines for merged results](#enable-pipelines-for-merged-results) +* [Using Merge Trains](#using-merge-trains) +* [Automatic pipeline cancellation](#automatic-pipeline-cancellation) +* [Troubleshooting](#troubleshooting) + * [Pipelines for merged results not created even with new change pushed to merge request](#pipelines-for-merged-results-not-created-even-with-new-change-pushed-to-merge-request) + * [Intermittently pipelines fail by `fatal: reference is not a tree:` error](#intermittently-pipelines-fail-by-fatal-reference-is-not-a-tree-error) + +# Pipelines for Merged Results[](#pipelines-for-merged-results-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7380) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.10. + +提交合并请求时,您正在请求将更改从源分支合并到目标分支. 默认情况下,CI 管道针对源分支运行作业. + +使用*用于合并结果*的管道,管道可以像源分支中的更改已被合并到目标分支中一样运行. + +如果管道由于目标分支中的问题而失败,则可以等到目标修复后再重新运行管道. 这个新管道将像源与已更新的目标合并一样运行,并且您无需重新设置基准. + +目标分支更改时,管道不会自动运行. 仅对源分支的更改会触发新的管道. 如果自上一个成功的管道以来已经过去了很长时间,则您可能需要在合并之前重新运行它,以确保源更改仍然可以成功合并到目标中. + +当合并请求无法合并时,管道仅针对源分支运行. 例如,当: + +* 目标分支的更改与源分支的更改冲突. +* 合并请求是[**草稿**合并请求](../../../user/project/merge_requests/work_in_progress_merge_requests.html) . + +在这些情况下,管道将作为[合并请求](../index.html)的管道运行,并标记为`detached` . 如果这些情况不再存在,则新管道将再次针对合并结果运行. + +具有开发者[权限的](../../../user/permissions.html)任何用户都可以运行管道以合并结果. + +## Prerequisites[](#prerequisites "Permalink") + +要启用管道以合并结果: + +* 您必须具有维护者[权限](../../../user/permissions.html) . +* 您必须使用[GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) 11.9 或更高版本. +* 您一定不要分叉或使用跨仓库工作流. 要跟踪进度,请参阅[#11934](https://gitlab.com/gitlab-org/gitlab/-/issues/11934) . +* 您一定不能使用[快速前进合并](../../../user/project/merge_requests/fast_forward_merge.html) . 要跟踪进度,请参阅[#58226](https://gitlab.com/gitlab-org/gitlab/-/issues/26996) . + +## Enable pipelines for merged results[](#enable-pipelines-for-merged-results "Permalink") + +要为项目的合并结果启用管道: + +1. [配置您的 CI / CD 配置文件,](../index.html#configuring-pipelines-for-merge-requests)以便为合并请求运行管道或单个作业. +2. 访问项目的**设置>常规,**然后展开**合并请求** . +3. Check **为合并结果启用合并训练和管道**. +4. Click **保存更改**. + +**警告:**如果选中该复选框,但未将 CI / CD 配置为使用管道处理合并请求,则合并请求可能会停留在未解决的状态,或者管道可能会被丢弃. + +## Using Merge Trains[](#using-merge-trains "Permalink") + +[为合并结果](#pipelines-for-merged-results-premium)启用[管道时](#pipelines-for-merged-results-premium) ,GitLab 会[自动显示"](merge_trains/index.html#add-a-merge-request-to-a-merge-train) **开始/添加合并训练"按钮** . + +通常,这是比立即合并合并请求更安全的选择,因为在实际合并发生之前,将使用预期的合并后结果评估合并请求. + +有关更多信息,请阅读[合并火车上](merge_trains/index.html)的[文档](merge_trains/index.html) . + +## Automatic pipeline cancellation[](#automatic-pipeline-cancellation "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12996) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3. + +GitLab CI / CD 可以检测到冗余管道的存在,并会自动取消它们以节省 CI 资源. + +当用户在进行中的合并列车中立即合并请求时,将重新构建该列车,因为它将重新创建预期的合并后提交和管道. 在这种情况下,合并序列可能已经具有针对先前预期的合并后提交运行的管道. 这些管道被认为是多余的,将被自动取消. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Pipelines for merged results not created even with new change pushed to merge request[](#pipelines-for-merged-results-not-created-even-with-new-change-pushed-to-merge-request "Permalink") + +可能是由于某些禁用的功能标志引起的. 请确保在您的 GitLab 实例上启用了以下功能标志: + +* `:merge_ref_auto_sync` + +要检查和设置这些功能标志值,请要求管理员: + +1. 登录到 GitLab 实例的 Rails 控制台: + + ``` + sudo gitlab-rails console + ``` + +2. 检查标志是否启用: + + ``` + Feature.enabled?(:merge_ref_auto_sync) + ``` + +3. 如果需要,启用功能标志: + + ``` + Feature.enable(:merge_ref_auto_sync) + ``` + +### Intermittently pipelines fail by `fatal: reference is not a tree:` error[](#intermittently-pipelines-fail-by-fatal-reference-is-not-a-tree-error "Permalink") + +由于用于合并结果的管道是在合并请求( `refs/merge-requests//merge` )的合并 ref 上运行的,因此 Git 引用可能会在意外的时间被覆盖. 例如,当源分支或目标分支是高级时. 在这种情况下,流水线由于`fatal: reference is not a tree:`错误而失败,这表明在合并引用中未找到 checkout-SHA. + +在 GitLab 12.4 上,通过引入[Persistent pipe refs](../../pipelines/index.html#troubleshooting-fatal-reference-is-not-a-tree)改进了此行为. 您应该能够在任何时候创建管道,而不必考虑错误. \ No newline at end of file diff --git a/_book/docs/263.md b/_book/docs/263.md new file mode 100644 index 0000000000000000000000000000000000000000..a9c83f69440d33cf9337210c02bc06eec6da978a --- /dev/null +++ b/_book/docs/263.md @@ -0,0 +1,179 @@ +# Merge Trains + +> 原文:[https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/) + +* [Merge train example](#merge-train-example) +* [Prerequisites](#prerequisites) +* [Enable merge trains](#enable-merge-trains) +* [Start a merge train](#start-a-merge-train) +* [Add a merge request to a merge train](#add-a-merge-request-to-a-merge-train) +* [Remove a merge request from a merge train](#remove-a-merge-request-from-a-merge-train) +* [View a merge request’s current position on the merge train](#view-a-merge-requests-current-position-on-the-merge-train) +* [Immediately merge a merge request with a merge train](#immediately-merge-a-merge-request-with-a-merge-train) +* [Troubleshooting](#troubleshooting) + * [Merge request dropped from the merge train immediately](#merge-request-dropped-from-the-merge-train-immediately) + * [Merge When Pipeline Succeeds cannot be chosen](#merge-when-pipeline-succeeds-cannot-be-chosen) + * [Merge Train Pipeline cannot be retried](#merge-train-pipeline-cannot-be-retried) + * [Unable to add to merge train with message “The pipeline for this merge request failed.”](#unable-to-add-to-merge-train-with-message-the-pipeline-for-this-merge-request-failed) + * [Merge Trains feature flag](#merge-trains-feature-flag-premium-only) + +# Merge Trains[](#merge-trains-premium "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9186) . +* [GitLab Premium](https://about.gitlab.com/pricing/) 12.6 中[引入了压](https://gitlab.com/gitlab-org/gitlab/-/issues/13001)入[和合并](../../../../user/project/merge_requests/squash_and_merge.html)支持. + +启用[用于合并结果](../index.html#pipelines-for-merged-results-premium)的管道时,管道作业将运行,就好像源分支中的更改已被合并到目标分支中一样. + +但是,目标分支可能正在快速变化. 准备合并时,如果有一段时间没有运行管道,则目标分支可能已更改. 现在合并可能会带来重大变化. + +*合并列车*可以防止这种情况的发生. 合并列是合并请求的排队列表,每个请求都等待合并到目标分支中. + +可以将许多合并请求添加到火车. 每个合并请求都运行其自己的合并结果管道,该管道包括列车上位于其*前面*的所有其他合并请求的更改. 所有管道并行运行,以节省时间. + +如果合并请求的管道失败,则不会合并重大更改,并且目标分支不受影响. 合并请求已从火车中删除,并且其后面的所有管道都重新启动. + +如果火车前部用于合并请求的管道成功完成,则更改将合并到目标分支中,其他管道将继续运行. + +要将合并请求添加到合并系列,您需要具有[权限](../../../../user/permissions.html)才能推送到目标分支. + +**注意:**每个合并列车最多可以并行运行**20 条**管道. 如果将超过二十个合并请求添加到合并列,则合并请求将排队,直到合并列中的插槽可用为止. 可以排队的合并请求数量没有限制. + +## Merge train example[](#merge-train-example "Permalink") + +将三个合并请求( `A` , `B`和`C` )依次添加到合并序列中,这将创建三个并行运行的合并结果管道: + +1. 第一条管道基于`A`与目标分支组合的更改运行. +2. 第二个管道基于`A`和`B`的更改以及目标分支运行. +3. 第三条流水线基于`A` , `B`和`C`的更改以及目标分支. + +如果`B`的管道发生故障,则将其从火车上移除. `C`的管道将在`A`和`C`更改的情况下重新启动,但`B`不会更改. + +如果`A`然后成功完成,它将合并到目标分支中,并且`C`继续运行. 如果将更多合并请求添加到火车,它们现在将包括目标分支中包含的`A`更改,以及来自火车中已经存在的合并请求的`C`更改. + +阅读有关[合并火车如何使您的主人保持绿色的](https://about.gitlab.com/blog/2020/01/30/all-aboard-merge-trains/)更多信息. + +观看此视频,以获取有关[并行执行合并训练如何防止提交破坏默认分支](https://www.youtube.com/watch?v=D4qCqXgZkHQ)的演示. + +## Prerequisites[](#prerequisites "Permalink") + +要启用合并火车: + +* 您必须具有维护者[权限](../../../../user/permissions.html) . +* 您必须使用[GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) 11.9 或更高版本. +* 在 GitLab 12.0 和更高版本中,您需要[Redis](https://s0redis0io.icopy.site/) 3.2 或更高版本. + +## Enable merge trains[](#enable-merge-trains "Permalink") + +为您的项目启用合并火车: + +1. 如果您使用的是自我管理的 GitLab 实例,请确保正确设置了[功能标志](#merge-trains-feature-flag-premium-only) . +2. [配置您的 CI / CD 配置文件,](../../index.html#configuring-pipelines-for-merge-requests)以便为合并请求运行管道或单个作业. +3. 访问项目的**设置>常规,**然后展开**合并请求** . +4. Check **为合并结果启用合并训练和管道**. +5. Click **保存更改**. + +**警告:**如果选中该复选框,但未将 CI / CD 配置为使用管道处理合并请求,则合并请求可能会停留在未解决的状态,或者管道可能会被丢弃. + +## Start a merge train[](#start-a-merge-train "Permalink") + +要开始合并火车: + +1. 访问合并请求. +2. Click the **开始合并火车** button. + +[![Start merge train](img/7775f0c2ba5f85e61aae351b9939cdf2.png)](img/merge_train_start_v12_0.png) + +现在可以将其他合并请求添加到列车中. + +## Add a merge request to a merge train[](#add-a-merge-request-to-a-merge-train "Permalink") + +要将合并请求添加到合并火车: + +1. 访问合并请求. +2. 单击**添加以合并火车**按钮. + +如果用于合并请求的管道已经在运行,则无法将合并请求添加到列车. 相反,您可以计划**在最新管道成功时将**合并请求添加到合并**序列中** . + +[![Add to merge train when pipeline succeeds](img/1c78b1078232f166ee3d03d64f2b3907.png)](img/merge_train_start_when_pipeline_succeeds_v12_0.png) + +## Remove a merge request from a merge train[](#remove-a-merge-request-from-a-merge-train "Permalink") + +1. 访问合并请求. +2. 单击**从合并火车中删除**按钮. + +[![Cancel merge train](img/1a5840885de676ed33d7cdb688b26a12.png)](img/merge_train_cancel_v12_0.png) + +如果您想稍后再将合并请求添加到合并训练中,则可以. + +## View a merge request’s current position on the merge train[](#view-a-merge-requests-current-position-on-the-merge-train "Permalink") + +将合并请求添加到合并列之后,合并请求的当前位置显示在管道小部件下: + +[![Merge train position indicator](img/c3c7ade0ae9c901a64dedf780f4efdaf.png)](img/merge_train_position_v12_0.png) + +## Immediately merge a merge request with a merge train[](#immediately-merge-a-merge-request-with-a-merge-train "Permalink") + +如果您有必须紧急合并的高优先级合并请求(例如,重要补丁程序),则可以使用" **立即合并"**选项绕过合并程序. 这是将更改合并到目标分支的最快选项. + +[![Merge Immediately](img/5844f1567aec337f6ba990bc855c348a.png)](img/merge_train_immediate_merge_v12_6.png) + +**警告:**每次您立即合并一个合并请求时,都会重新创建当前的合并序列,并重新启动所有管道. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Merge request dropped from the merge train immediately[](#merge-request-dropped-from-the-merge-train-immediately "Permalink") + +如果合并请求不可合并(例如,在制品,存在合并冲突等),则您的合并请求将自动从合并列中删除. + +在这些情况下,删除合并请求的原因在**系统注释中** . + +检查原因: + +1. 打开从合并序列中删除的合并请求. +2. 打开**讨论**选项卡. +3. 查找包含以下任一内容的系统注释: + * 文本**…从合并列表中删除了此合并请求,因为…** + * **…中止了来自合并序列的合并请求,因为…**原因在" **…"**短语之后的文本中给出. + +[![Merge Train Failure](img/cdce9b0515678bb30cdd0e1173a30749.png)](img/merge_train_failure.png) + +### Merge When Pipeline Succeeds cannot be chosen[](#merge-when-pipeline-succeeds-cannot-be-chosen "Permalink") + +启用合并训练后,当前无法[在管道成功](../../../../user/project/merge_requests/merge_when_pipeline_succeeds.html)时合并. + +有关更多信息,请参见[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/12267) . + +### Merge Train Pipeline cannot be retried[](#merge-train-pipeline-cannot-be-retried "Permalink") + +合并火车管道无法重试,因为合并请求在失败后会从合并火车中删除. 因此,重试按钮不会出现在管道图标旁边. + +如果管道发生故障,则应将合并请求[重新排队](#add-a-merge-request-to-a-merge-train)到合并[序列中](#add-a-merge-request-to-a-merge-train) ,然后合并[序列](#add-a-merge-request-to-a-merge-train)将启动新的管道. + +### Unable to add to merge train with message “The pipeline for this merge request failed.”[](#unable-to-add-to-merge-train-with-message-the-pipeline-for-this-merge-request-failed "Permalink") + +有时" **开始/添加到合并训练"**按钮不可用,合并请求显示"此合并请求的管道失败. 请重试该作业或推送新的提交以修复故障." + +在**"设置">"常规">"合并请求"中**启用**"** [**管道必须成功"**](../../../../user/project/merge_requests/merge_when_pipeline_succeeds.html#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds)时,会发生此问题. 此选项要求您运行新的成功管道,然后才能将合并请求重新添加到合并系列. + +合并训练可确保在合并发生之前每个管道都已成功完成,因此您可以清除" **管道必须成功"**复选框,并保持**启用"启用合并训练和合并结果的管道** (合并训练)". + +如果要与合并训练一起保持启用" **管道必须成功"**选项,可以在发生此错误时为合并结果创建新管道,方法是转到" **管道"**选项卡,然后单击**"运行管道"** . 然后**在管道成功时**单击" **开始/添加"以合并火车** . + +有关更多信息,请参见[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/35135) . + +### Merge Trains feature flag[](#merge-trains-feature-flag-premium-only "Permalink") + +要启用和禁用合并训练功能,请使用`:disable_merge_trains`功能标志. + +要检查您的 GitLab 实例上是否启用了功能标志,请要求管理员执行以下命令: + +``` +> sudo gitlab-rails console # Login to Rails console of GitLab instance. +> Feature.enabled?(:disable_merge_trains) # Check if it's disabled or not. +> Feature.enable(:disable_merge_trains) # Disable Merge Trains. +> Feature.disable(:disable_merge_trains) # Enable Merge Trains. +``` + +禁用此功能后,所有现有的合并训练都将被取消,并且" **开始/添加到合并训练"**按钮不再出现在合并请求中. \ No newline at end of file diff --git a/_book/docs/264.md b/_book/docs/264.md new file mode 100644 index 0000000000000000000000000000000000000000..1d50e07a1ff6bc68c3b93a3556b0b8adf9f19038 --- /dev/null +++ b/_book/docs/264.md @@ -0,0 +1,393 @@ +# Job artifacts + +> 原文:[https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html](https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html) + +* [Defining artifacts in `.gitlab-ci.yml`](#defining-artifacts-in-gitlab-ciyml) + * [`artifacts:reports`](#artifactsreports) + * [`artifacts:reports:junit`](#artifactsreportsjunit) + * [`artifacts:reports:dotenv`](#artifactsreportsdotenv) + * [`artifacts:reports:cobertura`](#artifactsreportscobertura) + * [`artifacts:reports:terraform`](#artifactsreportsterraform) + * [`artifacts:reports:codequality`](#artifactsreportscodequality-starter) + * [`artifacts:reports:sast`](#artifactsreportssast-ultimate) + * [`artifacts:reports:secret_detection`](#artifactsreportssecret_detection-ultimate) + * [`artifacts:reports:dependency_scanning`](#artifactsreportsdependency_scanning-ultimate) + * [`artifacts:reports:container_scanning`](#artifactsreportscontainer_scanning-ultimate) + * [`artifacts:reports:dast`](#artifactsreportsdast-ultimate) + * [`artifacts:reports:license_management`](#artifactsreportslicense_management-ultimate) + * [`artifacts:reports:license_scanning`](#artifactsreportslicense_scanning-ultimate) + * [`artifacts:reports:performance`](#artifactsreportsperformance-premium) + * [`artifacts:reports:load_performance`](#artifactsreportsload_performance-premium) + * [`artifacts:reports:metrics`](#artifactsreportsmetrics-premium) + * [`artifacts:reports:requirements`](#artifactsreportsrequirements-ultimate) +* [Browsing artifacts](#browsing-artifacts) +* [Downloading artifacts](#downloading-artifacts) +* [Downloading the latest artifacts](#downloading-the-latest-artifacts) +* [Erasing artifacts](#erasing-artifacts) +* [Retrieve artifacts of private projects when using GitLab CI](#retrieve-artifacts-of-private-projects-when-using-gitlab-ci) + +# Job artifacts[](#job-artifacts "Permalink") + +版本历史 + +* 在 GitLab 8.2 和 GitLab Runner 0.7.0 中引入. +* 从 GitLab 8.4 和 GitLab Runner 1.0 开始,工件存档格式已更改为`ZIP` ,现在可以浏览其内容,并具有分别下载文件的功能. +* 在 GitLab 8.17 中,将构建重命名为 job. +* 工件浏览器仅适用于使用 GitLab Runner 1.0 及更高版本发送到 GitLab 的新工件. 无法浏览已经上传到 GitLab 的旧工件. + +作业工件是作业完成后创建的文件和目录的列表. [默认情况下](../../administration/job_artifacts.html) ,所有 GitLab 安装中均[启用](../../administration/job_artifacts.html)此功能. + +由 GitLab Runner 创建的作业工件被上传到 GitLab,并可以使用 GitLab UI 或[GitLab API](../../api/jobs.html#get-job-artifacts)作为单个存档下载. + +有关概述,请观看视频[GitLab CI 管道,工件和环境](https://www.youtube.com/watch?v=PCKDICEe10s) . 也请观看[面向初学者的 GitLab CI 管道教程](https://www.youtube.com/watch?v=Jav4vbUrqII) . + +## Defining artifacts in `.gitlab-ci.yml`[](#defining-artifacts-in-gitlab-ciyml "Permalink") + +在`.gitlab-ci.yml`中使用工件定义的一个简单示例如下: + +``` +pdf: + script: xelatex mycv.tex + artifacts: + paths: + - mycv.pdf + expire_in: 1 week +``` + +名为`pdf`的作业会调用`xelatex`命令,以便从乳胶源文件`mycv.tex`生成 PDF 文件. 然后,我们定义`artifacts`路径,这些路径又用`paths`关键字定义. 文件和目录的所有路径都相对于在构建过程中克隆的存储库. + +默认情况下,当作业成功时将上传工件,但是可以将其设置为在作业失败时上传,或者如果使用[`artifacts:when`](../yaml/README.html#artifactswhen)参数,则始终设置为上传. 根据`expire_in`定义,这些上传的工件将在 GitLab 中保存 1 周. 您可以通过[Web 界面](#browsing-artifacts)防止工件过期. 如果未定义到期时间,则默认为[实例范围设置](../../user/admin_area/settings/continuous_integration.html#default-artifacts-expiration-core-only) . + +有关工件的更多示例,请遵循[`.gitlab-ci.yml`](../yaml/README.html#artifacts)的[工件参考](../yaml/README.html#artifacts) . + +### `artifacts:reports`[](#artifactsreports "Permalink") + +版本历史 + +* 在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20390) . +* 需要 GitLab Runner 11.2 及更高版本. + +`artifacts:reports`关键字用于从作业中收集测试报告,代码质量报告和安全性报告. 它还在 GitLab 的 UI 中显示这些报告(合并请求,管道视图和安全性仪表板). + +**注意:**无论作业结果(成功或失败),都将收集测试报告. 您可以使用[`artifacts:expire_in`](../yaml/README.html#artifactsexpire_in)设置其工件的到期日期.**注:**如果您还希望能够浏览报告输出文件,请包括[`artifacts:paths`](../yaml/README.html#artifactspaths)关键字. + +#### `artifacts:reports:junit`[](#artifactsreportsjunit "Permalink") + +版本历史 + +* 在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20390) . +* 需要 GitLab Runner 11.2 及更高版本. + +`junit`报告将[JUnit XML 文件](https://www.ibm.com/support/knowledgecenter/en/SSQ2R2_14.1.0/com.ibm.rsar.analysis.codereview.cobol.doc/topics/cac_useresults_junit.html)收集为工件. 尽管 JUnit 最初是用 Java 开发的,但是还有许多其他[端口可以](https://en.wikipedia.org/wiki/JUnit#Ports)用于其他语言,例如 JavaScript,Python,Ruby 等. + +有关更多详细信息和示例,请参见[JUnit 测试报告](../junit_test_reports.html) . 下面是从 Ruby 的 RSpec 测试工具收集 JUnit XML 文件的示例: + +``` +rspec: + stage: test + script: + - bundle install + - rspec --format RspecJunitFormatter --out rspec.xml + artifacts: + reports: + junit: rspec.xml +``` + +收集的 JUnit 报告将作为工件上传到 GitLab,并将自动显示在合并请求中. + +**注意:**如果您使用的 JUnit 工具导出到多个 XML 文件,则可以在一个作业中指定多个测试报告路径,它们将被自动串联到一个文件中. 使用文件名模式( `junit: rspec-*.xml` ),文件名数组( `junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]` )或其组合( `junit: [rspec.xml, test-results/TEST-*.xml]` ). + +#### `artifacts:reports:dotenv`[](#artifactsreportsdotenv "Permalink") + +版本历史 + +* 在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/17066) . +* 需要 GitLab Runner 11.5 及更高版本. + +`dotenv`报告收集一组环境变量作为工件. + +收集的变量注册为作业的运行时创建的变量,这对于[在作业完成后设置动态环境 URL](../environments/index.html#set-dynamic-environment-urls-after-a-job-finishes)很有用. + +[原始 dotenv 规则](https://github.com/motdotla/dotenv#rules)有两个例外: + +* 可变键只能包含字母,数字和下划线( `_` ). +* `.env`文件的最大大小为 5 KB. +* 变量的最大数量为 10. +* 不支持`.env`文件中的变量替换. +* `.env`文件不能包含空行或注释(以`#`开头). +* `env`文件中的键值不能包含空格或换行符( `\n` ),包括使用单引号或双引号时. +* 不支持在解析过程中使用引号转义( `key = 'value'` -> `{key: "value"}` ). + +#### `artifacts:reports:cobertura`[](#artifactsreportscobertura "Permalink") + +版本历史 + +* 在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) . +* 需要[GitLab Runner](https://docs.gitlab.com/runner/) 11.5 及更高版本. + +The `cobertura` report collects [Cobertura coverage XML files](../../user/project/merge_requests/test_coverage_visualization.html). The collected Cobertura coverage reports will be uploaded to GitLab as an artifact and will be automatically shown in merge requests. + +Cobertura 最初是为 Java 开发的,但是有许多第三方端口可用于其他语言,例如 JavaScript,Python,Ruby 等. + +#### `artifacts:reports:terraform`[](#artifactsreportsterraform "Permalink") + +版本历史 + +* 在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/207528) . +* 需要[GitLab Runner](https://docs.gitlab.com/runner/) 11.5 及更高版本. + +`terraform`报告获取 Terraform `tfplan.json`文件. [需要进行 JQ 处理才能删除凭据](../../user/infrastructure/index.html#output-terraform-plan-information-into-a-merge-request) . 收集的 Terraform 计划报告将作为工件上传到 GitLab,并将在合并请求中自动显示. 有关更多信息,请参见将[`terraform plan`信息输出到合并请求中](../../user/infrastructure/index.html#output-terraform-plan-information-into-a-merge-request) . + +#### `artifacts:reports:codequality`[](#artifactsreportscodequality-starter "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`codequality`报告将[CodeQuality 问题](../../user/project/merge_requests/code_quality.html)收集为工件. + +收集的代码质量报告将作为工件上传到 GitLab,并在合并请求中进行汇总. + +#### `artifacts:reports:sast`[](#artifactsreportssast-ultimate "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`sast`报告将[SAST 漏洞](../../user/application_security/sast/index.html)收集为工件. + +收集的 SAST 报告将作为工件上传到 GitLab,并将在合并请求和管道视图中进行汇总. 它还用于为安全仪表板提供数据. + +#### `artifacts:reports:secret_detection`[](#artifactsreportssecret_detection-ultimate "Permalink") + +版本历史 + +* 在 GitLab 13.1 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`secret-detection`报告将[检测到的机密](../../user/application_security/secret_detection/index.html)收集为伪像. + +收集的 Secret Detection 报告作为工件上传到 GitLab,并在合并请求和管道视图中进行汇总. 它还用于为安全仪表板提供数据. + +#### `artifacts:reports:dependency_scanning`[](#artifactsreportsdependency_scanning-ultimate "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`dependency_scanning`报告将" [依赖关系扫描"漏洞](../../user/application_security/dependency_scanning/index.html)收集为工件. + +收集的"依赖关系扫描"报告将作为工件上传到 GitLab,并将在合并请求和管道视图中进行汇总. 它还用于为安全仪表板提供数据. + +#### `artifacts:reports:container_scanning`[](#artifactsreportscontainer_scanning-ultimate "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`container_scanning`报告收集[容器扫描漏洞](../../user/application_security/container_scanning/index.html)作为工件. + +收集的"容器扫描"报告将作为工件上传到 GitLab,并将在合并请求和管道视图中进行汇总. 它还用于为安全仪表板提供数据. + +#### `artifacts:reports:dast`[](#artifactsreportsdast-ultimate "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`dast`报告将[DAST 漏洞](../../user/application_security/dast/index.html)收集为工件. + +收集的 DAST 报告将作为工件上传到 GitLab,并将在合并请求和管道视图中进行汇总. 它还用于为安全仪表板提供数据. + +#### `artifacts:reports:license_management`[](#artifactsreportslicense_management-ultimate "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +**警告:**此工件仍然有效,但**不推荐使用** ,而**推荐使用** GitLab 12.8 中引入的[artifacts:reports:license_scanning](../pipelines/job_artifacts.html#artifactsreportslicense_scanning-ultimate) . + +`license_management`报告收集[许可证](../../user/compliance/license_compliance/index.html)作为工件. + +The collected License Compliance report will be uploaded to GitLab as an artifact and will be summarized in the merge requests and pipeline view. It’s also used to provide data for security dashboards. + +#### `artifacts:reports:license_scanning`[](#artifactsreportslicense_scanning-ultimate "Permalink") + +版本历史 + +* 在 GitLab 12.8 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`license_scanning`报告收集[许可证](../../user/compliance/license_compliance/index.html)作为工件. + +许可证合规性报告将作为工件上传到 GitLab,并将自动显示在合并请求,管道视图中,并为安全仪表板提供数据. + +#### `artifacts:reports:performance`[](#artifactsreportsperformance-premium "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`performance`报告收集[浏览器性能测试指标](../../user/project/merge_requests/browser_performance_testing.html)作为工件. + +收集的浏览器性能报告将作为工件上传到 GitLab,并将自动显示在合并请求中. + +#### `artifacts:reports:load_performance`[](#artifactsreportsload_performance-premium "Permalink") + +版本历史 + +* 介绍了[GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35260)在[GitLab 溢价](https://about.gitlab.com/pricing/) 13.2\. +* 需要 GitLab Runner 11.5 及更高版本. + +`load_performance`报告收集工件的[负载性能测试指标](../../user/project/merge_requests/load_performance_testing.html) . + +该报告作为工件被上传到 GitLab,并自动显示在合并请求中. + +#### `artifacts:reports:metrics`[](#artifactsreportsmetrics-premium "Permalink") + +在 GitLab 11.10 中引入. + +`metrics`报告收集[指标](../metrics_reports.html)作为工件. + +收集的指标报告将作为工件上传到 GitLab,并将自动显示在合并请求中. + +#### `artifacts:reports:requirements`[](#artifactsreportsrequirements-ultimate "Permalink") + +版本历史 + +* 在 GitLab 13.1 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2859) . +* 需要 GitLab Runner 11.5 及更高版本. + +`requirements`报告收集工件的`requirements.json`文件. + +收集的需求报告将作为工件上传到 GitLab,现有[需求](../../user/project/requirements/index.html)将标记为"满意". + +## Browsing artifacts[](#browsing-artifacts "Permalink") + +版本历史 + +* 从 GitLab 9.2,可以直接在工作工件浏览器中预览 PDF,图像,视频和其他格式,而无需下载它们. +* 在[GitLab 10.1 中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14399)引入的公共项目中的 HTML 文件可以在新选项卡中直接预览,而在启用[GitLab Pages](../../administration/pages/index.html)时无需下载它们. 文本格式也是如此(当前支持的扩展名: `.txt` , `.json`和`.log` ). +* 在[GitLab 12.4 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16675)引入后,启用[GitLab 页面访问控制后,便](../../administration/pages/index.html#access-control)可以预览私有项目中的工件. + +作业完成后,如果您访问作业的特定页面,则有三个按钮. 您可以下载工件归档文件或浏览其内容,而" **保留"**按钮仅在您为工件设置了[有效日期](../yaml/README.html#artifactsexpire_in)的情况下出现,以防万一您改变主意并希望保留它们. + +[![Job artifacts browser button](img/ae307552914d8ff018365bbde4d23479.png)](img/job_artifacts_browser_button.png) + +存档浏览器显示存档中每个文件的名称和实际文件大小. 如果您的工件包含目录,那么您也可以在其中进行浏览. + +您可以在下面看到浏览的样子. 在这种情况下,我们浏览了档案内部,此时有一个目录,几个文件和一个 HTML 文件,启用[GitLab 页面](../../administration/pages/index.html) (在新选项卡中打开)后,您可以直接在线查看. + +[![Job artifacts browser](img/212946086e16f591c716728308d49ca3.png)](img/job_artifacts_browser.png) + +## Downloading artifacts[](#downloading-artifacts "Permalink") + +如果您需要下载工件或整个档案,请在 GitLab UI 的不同位置进行操作: + +1. 在管道页面上,您可以在右上角看到每个作业的工件和存档的下载图标: + + [![Job artifacts in Pipelines page](img/b22d9654d7ad1868d2368d7e3f82e9a3.png)](img/job_artifacts_pipelines_page.png) + +2. 在" **作业"**页面上,您可以在右上角看到每个作业的工件和存档的下载图标: + + [![Job artifacts in Builds page](img/82c2caa32c2aff60b744c3ede8725ac9.png)](img/job_artifacts_builds_page.png) + +3. While inside a specific job, you’re presented with a download button along with the one that browses the archive: + + [![Job artifacts browser button](img/ae307552914d8ff018365bbde4d23479.png)](img/job_artifacts_browser_button.png) + +4. 最后,在浏览档案时,您可以在右上角看到下载按钮: + + [![Job artifacts browser](img/212946086e16f591c716728308d49ca3.png)](img/job_artifacts_browser.png) + +## Downloading the latest artifacts[](#downloading-the-latest-artifacts "Permalink") + +可以通过众所周知的 URL 下载作业的最新工件,以便将其用于脚本目的. + +**注意:**最新工件是由作业在特定引用的**最新**成功管道中创建的. 如果您为相同的参考运行两种类型的管道,则最新的工件将通过计时来确定. 例如,如果通过合并合并请求创建的分支管道与计划的管道同时运行,则最新的工件将来自最近完成的管道. + +可以直接访问其他管道的工件. + +用于下载整个工件存档的 URL 的结构如下: + +``` +https://example.com///-/jobs/artifacts//download?job= +``` + +To download a single file from the artifacts use the following URL: + +``` +https://example.com///-/jobs/artifacts//raw/?job= +``` + +例如,要下载名为`gitlab`项目的`master`分支(属于`gitlab-org`命名空间)的`coverage`的作业的最新工件,URL 为: + +``` +https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/download?job=coverage +``` + +要从相同的工件下载文件`coverage/index.html` ,请使用以下 URL: + +``` +https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/raw/coverage/index.html?job=coverage +``` + +还有一个 URL 可浏览最新的作业工件: + +``` +https://example.com///-/jobs/artifacts//browse?job= +``` + +例如: + +``` +https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/browse?job=coverage +``` + +还有一个指向特定文件的 URL,包括在[GitLab 页面](../../administration/pages/index.html)中显示的 HTML 文件: + +``` +https://example.com///-/jobs/artifacts//file/?job= +``` + +例如,当一个作业`coverage`创建神器`htmlcov/index.html` ,你可以访问它: + +``` +https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/file/htmlcov/index.html?job=coverage +``` + +UI 的不同位置也公开了最新版本. 具体来说,请在以下位置查找下载按钮: + +* 主项目页面 +* 分支机构页面 +* 标签页面 + +如果最新作业未能上传工件,则可以在 UI 中看到该信息. + +[![Latest artifacts button](img/a3acce71246e984986cedc7a1cece8f9.png)](img/job_latest_artifacts_browser.png) + +## Erasing artifacts[](#erasing-artifacts "Permalink") + +**警告:**这是一种破坏性行为,会导致数据丢失. 请谨慎使用. + +您可以通过 UI 删除单个作业,如果您是以下情况,则它也将删除作业的工件和跟踪: + +* 工作的所有者. +* 项目的[维护者](../../user/permissions.html#gitlab-cicd-permissions) . + +删除作业: + +1. 导航到工作页面. +2. 单击作业跟踪右上方的垃圾桶图标. +3. 确认删除. + +## Retrieve artifacts of private projects when using GitLab CI[](#retrieve-artifacts-of-private-projects-when-using-gitlab-ci "Permalink") + +为了检索不同项目的作业工件,您可能需要使用专用令牌来[认证和下载](../../api/jobs.html#get-job-artifacts)工件. \ No newline at end of file diff --git a/_book/docs/265.md b/_book/docs/265.md new file mode 100644 index 0000000000000000000000000000000000000000..30a25e4d130e0ca79bcac4cf275d874f2c26f05c --- /dev/null +++ b/_book/docs/265.md @@ -0,0 +1,133 @@ +# Pipeline schedules + +> 原文:[https://docs.gitlab.com/ee/ci/pipelines/schedules.html](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) + +* [Prerequisites](#prerequisites) +* [Configuring pipeline schedules](#configuring-pipeline-schedules) + * [Using variables](#using-variables) + * [Using only and except](#using-only-and-except) + * [Advanced configuration](#advanced-configuration) +* [Working with scheduled pipelines](#working-with-scheduled-pipelines) + * [Running manually](#running-manually) + * [Taking ownership](#taking-ownership) + +# Pipeline schedules[](#pipeline-schedules "Permalink") + +版本历史 + +* 在 GitLab 9.1 中作为[触发计划](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10533)引入. +* 在 GitLab 9.2 中[重命名为 Pipeline Schedule](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10853) . + +**注意:** Cron 表示法由[Fugit](https://github.com/floraison/fugit)解析. + +管道通常是在满足某些条件的情况下运行的. 例如,将分支推送到存储库时. + +管道计划可以用于以特定间隔运行[管道](index.html) . 例如: + +* 每个月的 22 号都有特定的分支机构. +* 每天一次. + +除了使用 GitLab UI 外,还可以使用[Pipeline schedules API](../../api/pipeline_schedules.html)维护[管道时间表](../../api/pipeline_schedules.html) . + +## Prerequisites[](#prerequisites "Permalink") + +为了成功创建计划的管道: + +* 计划所有者必须具有合并到目标分支的[权限](../../user/permissions.html) . +* 管道配置必须有效. + +否则,不会创建管道. + +## Configuring pipeline schedules[](#configuring-pipeline-schedules "Permalink") + +计划项目的管道: + +1. 导航到项目的**CI / CD>计划**页面. +2. 单击**新建计划**按钮. +3. 填写**计划表中的新管道**表单. +4. 单击**保存管道计划**按钮. + +[![New Schedule Form](img/b379b1821f4b3d10ab0be61a59bcd491.png)](img/pipeline_schedules_new_form.png) + +**注意:**管道执行[时间取决于](#advanced-configuration) Sidekiq 自己的时间表. + +在" **计划**索引"页面中,您可以看到计划运行的管道的列表. 下次运行由安装了 GitLab 的服务器自动计算. + +[![Schedules list](img/de408a3a079dceb2e72d044abac21ac3.png)](img/pipeline_schedules_list.png) + +### Using variables[](#using-variables "Permalink") + +在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12328) . + +您可以传递任意数量的任意变量,它们将在 GitLab CI / CD 中可用,以便可以在您的[`.gitlab-ci.yml`文件中使用](../../ci/yaml/README.html) . + +[![Scheduled pipeline variables](img/2e1001a11cd343049b87ebf60a315e9f.png)](img/pipeline_schedule_variables.png) + +### Using only and except[](#using-only-and-except "Permalink") + +要配置仅在计划了管道(或相反)时才可以执行作业,您只能使用[且](../yaml/README.html#onlyexcept-basic)不能使用配置关键字. + +For example: + +``` +job:on-schedule: + only: + - schedules + script: + - make world + +job: + except: + - schedules + script: + - make build +``` + +### Advanced configuration[](#advanced-configuration "Permalink") + +管道不会完全按计划执行,因为计划由 Sidekiq 处理,Sidekiq 根据其间隔运行. + +例如,如果满足以下条件,则每天只会创建两个管道: + +* 您设置时间表以每分钟( `* * * * *` )创建一条管道. +* Sidekiq 工作者每天在 00:00 和 12:00( `0 */12 * * *` )运行. + +更改 Sidekiq 工作人员的频率: + +1. 在实例的`gitlab.rb`文件中编辑`gitlab_rails['pipeline_schedule_worker_cron']`值. +2. [重新配置 GitLab,](../../administration/restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +对于 GitLab.com,请参阅[专用设置页面](../../user/gitlab_com/index.html#gitlab-cicd) . + +## Working with scheduled pipelines[](#working-with-scheduled-pipelines "Permalink") + +配置完成后,GitLab 将支持许多用于计划管道的功能. + +### Running manually[](#running-manually "Permalink") + +在 GitLab 10.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15700) . + +要手动触发管道计划,请单击"播放"按钮: + +[![Play Pipeline Schedule](img/4ffe26c8f949643669a5c295958616cf.png)](img/pipeline_schedule_play.png) + +这将安排一个后台作业来运行管道计划. 一条简短消息将提供指向 CI / CD 管道索引页面的链接. + +**注意:**为避免滥用,限制了用户每分钟触发一次管道的速率. + +### Taking ownership[](#taking-ownership "Permalink") + +管道以拥有日程表的用户身份执行. 这影响管道可以访问哪些项目和其他资源. + +如果用户不拥有管道,则可以通过单击" **获取所有权"**按钮**获取所有权** . 下次计划管道时,将使用您的凭据. + +[![Schedules list](img/94b9b90ebfb15979835f3e48d710cb45.png)](img/pipeline_schedules_ownership.png) + +如果管道计划的所有者没有能力在目标分支上创建管道,则该计划将停止创建新管道. + +例如,如果发生这种情况: + +* 所有者被阻止或从项目中删除. +* 目标分支或标签受保护. + +在这种情况下,具有足够特权的人必须拥有日程表的所有权. \ No newline at end of file diff --git a/_book/docs/266.md b/_book/docs/266.md new file mode 100644 index 0000000000000000000000000000000000000000..f696af833957f6da872358f0d1e058ff58afa3e1 --- /dev/null +++ b/_book/docs/266.md @@ -0,0 +1,291 @@ +# Pipeline settings + +> 原文:[https://docs.gitlab.com/ee/ci/pipelines/settings.html](https://docs.gitlab.com/ee/ci/pipelines/settings.html) + +* [Git strategy](#git-strategy) +* [Git shallow clone](#git-shallow-clone) +* [Timeout](#timeout) + * [Timeout overriding on Runner level](#timeout-overriding-on-runner-level) +* [Maximum artifacts size](#maximum-artifacts-size-core-only) +* [Custom CI configuration path](#custom-ci-configuration-path) +* [Test coverage parsing](#test-coverage-parsing) + * [Code Coverage history](#code-coverage-history) + * [Removing color codes](#removing-color-codes) +* [Visibility of pipelines](#visibility-of-pipelines) +* [Auto-cancel pending pipelines](#auto-cancel-pending-pipelines) +* [Skip outdated deployment jobs](#skip-outdated-deployment-jobs) +* [Pipeline Badges](#pipeline-badges) + * [Pipeline status badge](#pipeline-status-badge) + * [Test coverage report badge](#test-coverage-report-badge) + * [Badge styles](#badge-styles) + * [Flat (default)](#flat-default) + * [Flat square](#flat-square) + * [Custom badge text](#custom-badge-text) +* [Environment Variables](#environment-variables) + +# Pipeline settings[](#pipeline-settings "Permalink") + +要达到管道设置,请导航至项目的**"设置">" CI / CD"** . + +可以为每个项目配置以下设置. + +有关概述,请观看视频[GitLab CI 管道,工件和环境](https://www.youtube.com/watch?v=PCKDICEe10s) . 也请观看[面向初学者的 GitLab CI 管道教程](https://www.youtube.com/watch?v=Jav4vbUrqII) . + +## Git strategy[](#git-strategy "Permalink") + +使用 Git 策略,您可以选择从作业中的 GitLab 提取存储库的默认方式. + +有两种选择. 使用: + +* `git clone` ,速度较慢,因为它会为每个作业从头开始克隆存储库,以确保本地工作副本始终是原始的. +* `git fetch` ,它更快地重新使用本地工作副本(如果不存在,则回退为克隆). + +默认的 Git 策略可以由`.gitlab-ci.yml`的[GIT_STRATEGY 变量](../yaml/README.html#git-strategy)覆盖. + +## Git shallow clone[](#git-shallow-clone "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28919) in GitLab 12.0. + +**注意:**从 GitLab 12.0 开始,新创建的项目将自动具有默认的`git depth`值`50` . + +克隆存储库时,可以限制 GitLab CI / CD 获取的更改数量. 设置`git depth`的限制可以加快管道的执行速度. 最大允许值为`1000` . + +要禁用浅表克隆并使 GitLab CI / CD 每次获取所有分支和标签,请将值保留为空或设置为`0` . + +`.gitlab-ci.yml`文件中的[`GIT_DEPTH`](../large_repositories/index.html#shallow-cloning)变量也可以[覆盖](../large_repositories/index.html#shallow-cloning)此值. + +## Timeout[](#timeout "Permalink") + +超时定义了作业可以运行的最长时间(以分钟为单位). 这可以在项目的**设置> CI / CD>常规管道设置下进行配置** . 默认值为 60 分钟. 如果要对作业的运行时间施加硬性限制,则减少时间限制,否则增加该限制. 无论如何,如果作业超过阈值,则将其标记为失败. + +### Timeout overriding on Runner level[](#timeout-overriding-on-runner-level "Permalink") + +在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17221) . + +项目定义的超时(用户设置的特定超时或默认的 60 分钟超时)可以[在 Runner 级别](../runners/README.html#set-maximum-job-timeout-for-a-runner)上[覆盖](../runners/README.html#set-maximum-job-timeout-for-a-runner) . + +## Maximum artifacts size[](#maximum-artifacts-size-core-only "Permalink") + +有关为项目设置最大工件大小的信息,请参见[最大工件大小](../../user/admin_area/settings/continuous_integration.html#maximum-artifacts-size-core-only) . + +## Custom CI configuration path[](#custom-ci-configuration-path "Permalink") + +版本历史 + +* 在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12509) . +* [支持](https://gitlab.com/gitlab-org/gitlab/-/issues/14376)在 GitLab 12.6 中引入的[外部`.gitlab-ci.yml`位置](https://gitlab.com/gitlab-org/gitlab/-/issues/14376) . + +默认情况下,我们在项目的根目录中查找`.gitlab-ci.yml`文件. 如果需要,您可以指定备用路径和文件名,包括项目外部的位置. + +要自定义路径: + +1. 转到项目的**设置> CI / CD** . +2. 展开**常规管道**部分. +3. 在" **定制 CI 配置路径"**字段中提供一个值. +4. Click **保存更改**. + +如果 CI 配置在非默认位置存储在资源库中,则该路径必须相对于根目录. 有效路径和文件名的示例包括: + +* `.gitlab-ci.yml` (default) +* `.my-custom-file.yml` +* `my/path/.gitlab-ci.yml` +* `my/path/.my-custom-file.yml` + +如果 CI 配置将托管在外部站点上,则 URL 链接必须以`.yml` : + +* `http://example.com/generate/ci/config.yml` + +如果 CI 配置将托管在 GitLab 中的其他项目中,则该路径必须相对于另一个项目中的根目录,并在最后添加组和项目名称: + +* `.gitlab-ci.yml@mygroup/another-project` +* `my/path/.my-custom-file.yml@mygroup/another-project` + +将配置文件托管在单独的项目中,可以更严格地控​​制配置文件. 例如: + +* 创建一个公共项目来承载配置文件. +* 仅向被允许编辑文件的用户授予对项目的写权限. + +其他用户和项目将能够访问配置文件而无需对其进行编辑. + +## Test coverage parsing[](#test-coverage-parsing "Permalink") + +如果您在代码中使用测试覆盖率,则 GitLab 可以使用正则表达式将其输出捕获到作业日志中. 在管道设置中,搜索"测试 coverage 解析"部分. + +[![Pipelines settings test coverage](img/1c1c9ba40bbb3c1ab789e70a4c4d42e6.png)](img/pipelines_settings_test_coverage.png) + +如果要禁用它或输入 Ruby 正则表达式,请保留空白. 您可以使用[https://rubular.com](https://rubular.com)来测试您的正则表达式. 正则表达式返回在输出中找到的**最后一个**匹配项. + +如果管道成功,则覆盖范围将显示在合并请求窗口小部件和作业表中. + +[![MR widget coverage](img/afec6ffec0973dba40a3e3bc2c244bad.png)](img/pipelines_test_coverage_mr_widget.png) + +[![Build status coverage](img/f81ccf2ef168880473496ad46b2d991f.png)](img/pipelines_test_coverage_build.png) + +可以在管道设置页面中找到一些针对多种语言的已知覆盖工具的示例. + +### Code Coverage history[](#code-coverage-history "Permalink") + +Version history + +* [引入](https://gitlab.com/gitlab-org/gitlab/-/issues/209121)了在 GitLab 12.10 中下载`.csv` . +* GitLab 13.1 中[引入的图](https://gitlab.com/gitlab-org/gitlab/-/issues/33743) . + +如果您想查看项目代码覆盖率随时间的变化,则可以查看图形或下载包含此数据的 CSV 文件. 从您的项目中: + +1. 去 **单击项目分析>存储库,**以查看图表上方下拉列表中列出的每个作业的历史数据. +2. 如果您想要该数据的 CSV 文件,请点击**下载原始数据(.csv)** + +[![Code coverage graph of a project over time](img/45c66aeb387e650cfe717047d1b78263.png)](img/code_coverage_graph_v13_1.png) + +### Removing color codes[](#removing-color-codes "Permalink") + +某些使用 ANSI 颜色代码输出的测试 coverage 工具无法通过正则表达式正确解析,并且会导致 coverage 解析失败. + +如果 Coverage 工具没有提供禁用输出中颜色代码的选项,则可以通过一个小的单行脚本通过管道传递 Coverage 工具的输出,该脚本将去除颜色代码. + +例如: + +``` +lein cloverage | perl -pe 's/\e\[?.*?[\@-~]//g' +``` + +## Visibility of pipelines[](#visibility-of-pipelines "Permalink") + +Pipeline visibility is determined by: + +* 您当前的[用户访问级别](../../user/permissions.html) . +* 项目**设置> CI / CD>常规管道**下的**公共管道**项目设置. + +**注意:**如果项目可见性设置为" **私有"** ,则" [**公共管道"**设置将无效](../enable_or_disable_ci.html#per-project-user-setting) . + +这也决定了这些相关功能的可见性: + +* 作业输出日志 +* 工作文物 +* The [pipeline security dashboard](../../user/application_security/security_dashboard/index.html#pipeline-security) + +**注意:**当前, [访客用户和非项目成员尚看不到](https://gitlab.com/gitlab-org/gitlab/-/issues/25649)作业日志和工件. + +如果启用了**公共管道** (默认): + +* 对于**公共**项目,任何人都可以查看管道和相关功能. +* 对于**内部**项目,任何登录的用户都可以查看管道和相关功能. +* 对于**私有**项目,任何项目成员(访客或更高级别)都可以查看管道和相关功能. + +如果禁用**公共管道** : + +* 对于**公共**项目,任何人都可以查看管道,但是只有成员(报告者或更高级别)可以访问相关功能. +* 对于**内部**项目,任何登录的用户都可以查看管道. 但是,只有成员(记者或更高级别)可以访问与工作相关的功能. +* 对于**私有**项目,只有项目成员(报告者或更高版本)才能查看管道或访问相关功能. + +## Auto-cancel pending pipelines[](#auto-cancel-pending-pipelines "Permalink") + +在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9362) . + +如果您希望每次创建新管道时(例如在 Git 推送之后或从 UI 手动创建)每次自动取消分支上所有未决的非 HEAD 管道,都可以在项目设置中启用此功能: + +1. 去 **设置> CI / CD** . +2. Expand **通用管道**. +3. 选中**自动取消冗余的未决管道**复选框. +4. Click **保存更改**. + +请注意,只有可[中断](../yaml/README.html#interruptible)设置为`true`作业才会被取消. + +## Skip outdated deployment jobs[](#skip-outdated-deployment-jobs "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/25276) . + +您的项目可能有多个并发部署作业,这些作业计划在同一时间范围内运行. + +这可能导致旧的部署作业在新的作业之后运行,而这可能不是您想要的. + +为了避免这种情况: + +1. 去 **设置> CI / CD** . +2. Expand **通用管道**. +3. 选中**跳过过期的部署作业**复选框. +4. Click **保存更改**. + +挂起的部署作业将被跳过. + +有关更多信息,请参阅[部署安全](../environments/deployment_safety.html) . + +## Pipeline Badges[](#pipeline-badges "Permalink") + +在管道设置页面中,您可以找到项目的管道状态和测试覆盖率标志. 最新成功的管道将用于读取管道状态和测试覆盖率值. + +访问项目中的管道设置页面,以查看指向徽章的确切链接,以及将徽章图像嵌入 HTML 或 Markdown 页面的方法. + +[![Pipelines badges](img/9fd7b49e564d04c79644e7fb8c7d7d5d.png)](img/pipelines_settings_badges.png) + +### Pipeline status badge[](#pipeline-status-badge "Permalink") + +根据您的工作状态,徽章可以具有以下值: + +* pending +* running +* passed +* failed +* skipped +* canceled +* unknown + +您可以使用以下链接访问管道状态标志图像: + +``` +https://example.gitlab.com///badges//pipeline.svg +``` + +### Test coverage report badge[](#test-coverage-report-badge "Permalink") + +GitLab 使定义[覆盖率报告](#test-coverage-parsing)的正则表达式成为可能,每个作业日志都将与之匹配. 这意味着管道中的每个作业都可以定义测试覆盖率百分比值. + +可以使用以下链接访问测试覆盖率徽章: + +``` +https://example.gitlab.com///badges//coverage.svg +``` + +如果要从特定作业获取覆盖率报告,可以将`job=coverage_job_name`参数添加到 URL. 例如,以下 Markdown 代码会将`coverage`作业的测试覆盖率报告标志嵌入到`README.md` : + +``` +![coverage](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=coverage) +``` + +### Badge styles[](#badge-styles "Permalink") + +通过向 URL 添加`style=style_name`参数,可以以不同的样式呈现管道标志. 当前有两种样式: + +#### Flat (default)[](#flat-default "Permalink") + +``` +https://example.gitlab.com///badges//coverage.svg?style=flat +``` + +[![Badge flat style](img/69a8b09a09599e563d1796eac13f945e.png)](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=coverage&style=flat) + +#### Flat square[](#flat-square "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30120) . + +``` +https://example.gitlab.com///badges//coverage.svg?style=flat-square +``` + +[![Badge flat square style](img/c7918abdac813cb6d0b57bb682269b93.png)](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=coverage&style=flat-square) + +### Custom badge text[](#custom-badge-text "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/17555) . + +徽章的文本可以自定义. 这有助于区分在同一管道中运行的多个 Coverage 作业. 通过将`key_text=custom_text`和`key_width=custom_key_width`参数添加到 URL 来定制徽章文本和宽度: + +``` +https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=karma&key_text=Frontend+Coverage&key_width=100 +``` + +[![Badge with custom text and width](img/8e5585152d153d9f1f4073f0cddba269.png)](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=karma&key_text=Frontend+Coverage&key_width=100) + +## Environment Variables[](#environment-variables "Permalink") + +可以在环境中设置[环境变量](../variables/README.html#gitlab-cicd-environment-variables)以供跑步者使用. \ No newline at end of file diff --git a/_book/docs/267.md b/_book/docs/267.md new file mode 100644 index 0000000000000000000000000000000000000000..78d7b9f730208be57c28de8816ec5ad222b6d851 --- /dev/null +++ b/_book/docs/267.md @@ -0,0 +1,251 @@ +# Triggering pipelines through the API + +> 原文:[https://docs.gitlab.com/ee/ci/triggers/README.html](https://docs.gitlab.com/ee/ci/triggers/README.html) + +* [Authentication tokens](#authentication-tokens) + * [Trigger token](#trigger-token) + * [CI job token](#ci-job-token) + * [When used with multi-project pipelines](#when-used-with-multi-project-pipelines) + * [When a pipeline depends on the artifacts of another pipeline](#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium) +* [Adding a new trigger](#adding-a-new-trigger) +* [Revoking a trigger](#revoking-a-trigger) +* [Triggering a pipeline](#triggering-a-pipeline) +* [Triggering a pipeline from a webhook](#triggering-a-pipeline-from-a-webhook) +* [Making use of trigger variables](#making-use-of-trigger-variables) +* [Using cron to trigger nightly pipelines](#using-cron-to-trigger-nightly-pipelines) +* [Legacy triggers](#legacy-triggers) + +# Triggering pipelines through the API[](#triggering-pipelines-through-the-api "Permalink") + +版本历史 + +**注意事项** : + +* 在 GitLab 7.14 中[引入](https://about.gitlab.com/releases/2015/08/22/gitlab-7-14-released/) . +* GitLab 8.12 具有完全重新设计的工作权限系统. 阅读有关[新模型及其含义的](../../user/project/new_ci_build_permissions_model.html#pipeline-triggers)所有信息. + +触发器可用于通过 API 调用强制重新运行特定`ref` (分支或标签)的管道. + +## Authentication tokens[](#authentication-tokens "Permalink") + +支持以下身份验证方法: + +* [Trigger token](#trigger-token) +* [CI job token](#ci-job-token) + +如果使用`$CI_PIPELINE_SOURCE` [预定义环境变量](../variables/predefined_variables.html)来限制在管道中运行的作业,则值可以是`pipeline`或`trigger` ,具体取决于所使用的触发器方法. + +| `$CI_PIPELINE_SOURCE` value | 触发方式 | +| --- | --- | +| `pipeline` | 使用 CI / CD 配置文件中的`trigger:`关键字,或将触发器 API 与`$CI_JOB_TOKEN` . | +| `trigger` | 使用生成的触发令牌使用触发 API | + +当使用`pipelines`或使用[`only/except`](../yaml/README.html#onlyexcept-basic)传统[`only/except`基本语法`only/except`](../yaml/README.html#onlyexcept-basic) `triggers`关键字时,这也适用. + +### Trigger token[](#trigger-token "Permalink") + +A unique trigger token can be obtained when [adding a new trigger](#adding-a-new-trigger). + +**危险:**在公共项目中传递纯文本令牌是一个安全问题. 潜在的攻击者可以在`.gitlab-ci.yml`文件中假冒公开暴露其触发令牌的用户. 使用[变量](../variables/README.html#gitlab-cicd-environment-variables)来保护触发令牌. + +### CI job token[](#ci-job-token "Permalink") + +You can use the `CI_JOB_TOKEN` [variable](../variables/README.html#predefined-environment-variables) (used to authenticate with the [GitLab Container Registry](../../user/packages/container_registry/index.html)) in the following cases. + +#### When used with multi-project pipelines[](#when-used-with-multi-project-pipelines "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 9.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2017)了`CI_JOB_TOKEN`在多项目管道中的使用. +* 在 GitLab 12.4 的所有层中都[可以](https://gitlab.com/gitlab-org/gitlab/-/issues/31573)将`CI_JOB_TOKEN`用于多项目管道. + +这种触发方式只能在`.gitlab-ci.yml`内部调用时使用,并且会在[管道图](../multi_project_pipelines.html#overview)上创建可见的依赖管道关系. 例如: + +``` +build_docs: + stage: deploy + script: + - curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=master https://gitlab.example.com/api/v4/projects/9/trigger/pipeline + only: + - tags +``` + +以这种方式触发的管道还公开了一个特殊变量: `CI_PIPELINE_SOURCE=pipeline` . + +阅读有关[管道触发器 API 的](../../api/pipeline_triggers.html)更多信息. + +#### When a pipeline depends on the artifacts of another pipeline[](#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium "Permalink") + +在[GitLab Premium](https://about.gitlab.com/pricing/) 9.5 中[引入了](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2346)在工件下载 API 中使用`CI_JOB_TOKEN` . + +随着不同项目之间的依赖关系的引入,其中一个项目可能需要访问由前一个项目创建的工件. 必须为授权访问授予此过程,并且可以使用标识特定作业的`CI_JOB_TOKEN`变量完成此过程. 例如: + +``` +build_submodule: + image: debian + stage: test + script: + - apt update && apt install -y unzip + - curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test&job_token=$CI_JOB_TOKEN" + - unzip artifacts.zip + only: + - tags +``` + +这使您可以将其用于多项目管道,并从您有权访问的任何项目下载工件,因为这遵循与[权限模型](../../user/permissions.html#job-permissions)相同的原则. + +了解有关[Jobs API 的](../../api/jobs.html#download-the-artifacts-archive)更多信息. + +## Adding a new trigger[](#adding-a-new-trigger "Permalink") + +您可以通过在"触发器"下转到项目的**"设置"➔CI / CD**来添加新**触发器** . **添加触发器**按钮将创建一个新令牌,然后您可以使用该令牌来触发此特定项目管道的重新运行. + +您创建的每个新触发器都会被分配一个不同的令牌,然后您可以在脚本或`.gitlab-ci.yml`使用该令牌. 您还可以很好地了解上一次使用触发器的时间. + +[![Triggers page overview](img/d25fe780083ad8adbc24cf5fcc4feaf8.png)](img/triggers_page.png) + +## Revoking a trigger[](#revoking-a-trigger "Permalink") + +您可以随时通过单击" **触发器"**下项目的**"设置"➔CI / CD**并单击" **撤消"**按钮来**撤消** **触发器** . 动作是不可逆的. + +## Triggering a pipeline[](#triggering-a-pipeline "Permalink") + +> **Notes**: +> +> * 有效的引用只是分支和标签. 如果通过提交 SHA 作为参考,它将不会触发作业. + +要触发作业,您需要向 gitLab 的 API 端点发送`POST`请求: + +``` +POST /projects/:id/trigger/pipeline +``` + +必需的参数是[触发器的`token`](#authentication-tokens)和将在其上执行触发器的 Git `ref` . 有效的引用是分支和标签. 可以通过[查询 API](../../api/projects.html)或访问**CI / CD**设置页面(提供不言自明的示例)来找到项目的`:id` . + +触发管道的重新运行时,该信息会在 GitLab 的 UI 中显示在**Jobs**页面下,并且作业被标记为"由 API 触发". + +[![Marked rebuilds as on jobs page](img/a68a3a59d914e3b3ef4b3cd56a67c1e1.png)](img/builds_page.png) + +* * * + +您可以通过访问单个作业页面查看是哪个触发器导致了重建. 从下图中可以看到,触发器的令牌的一部分显示在 UI 中. + +[![Marked rebuilds as triggered on a single job page](img/74017afb9b6459aed36b4c4a53df62e9.png)](img/trigger_single_build.png) + +* * * + +通过使用 cURL,您可以以最小的努力触发管道重新运行,例如: + +``` +curl --request POST \ + --form token=TOKEN \ + --form ref=master \ + https://gitlab.example.com/api/v4/projects/9/trigger/pipeline +``` + +在这种情况下,ID `9`的项目将在`master`分支上重建. + +或者,您可以在查询字符串中传递`token`和`ref`参数: + +``` +curl --request POST \ + "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline?token=TOKEN&ref=master" +``` + +您还可以在`.gitlab-ci.yml`使用触发器来`.gitlab-ci.yml` . 假设您有两个项目 A 和 B,并且每当在项目 A 上创建标签时,您都希望在项目 B 的`master`分支上触发重建. 这是您需要在项目 A 的`.gitlab-ci.yml`添加的工作: + +``` +build_docs: + stage: deploy + script: + - "curl --request POST --form token=TOKEN --form ref=master https://gitlab.example.com/api/v4/projects/9/trigger/pipeline" + only: + - tags +``` + +这意味着每当在项目 A 上添加新标签时,该作业就会运行,并且`build_docs`作业将被执行,从而触发项目 B 的重建`build_docs` `stage: deploy`确保该作业仅在所有带有`stage: test`作业之后运行成功完成. + +## Triggering a pipeline from a webhook[](#triggering-a-pipeline-from-a-webhook "Permalink") + +版本历史 + +**注意事项** : + +* 在 GitLab 8.14 中引入. +* `ref`应该作为 URL 的一部分传递,以便优先于来自 Webhook 主体的`ref` ,该 Webhook 主体指定了触发源存储库中的触发器的分支 ref. +* `ref`包含斜杠,则应进行 URL 编码. + +要从另一个项目的 Webhook 触发作业,您需要为 Push 和 Tag 事件添加以下 Webhook URL(更改项目 ID,ref 和 token): + +``` +https://gitlab.example.com/api/v4/projects/9/ref/master/trigger/pipeline?token=TOKEN +``` + +## Making use of trigger variables[](#making-use-of-trigger-variables "Permalink") + +您可以在触发器 API 调用中传递任意数量的任意变量,这些变量将在 GitLab CI / CD 中可用,以便可以在您的`.gitlab-ci.yml`文件中使用. 参数的形式为: + +``` +variables[key]=value +``` + +此信息也显示在 UI 中. 请注意,只有所有者和维护者才能看到这些*值* . + +[![Job variables in UI](img/8a6c0fc733a099005b7f7f9bcfbfe2ff.png)](img/trigger_variables.png) + +出于多种原因,使用触发器变量可能被证明是有用的: + +* 可识别的工作. 由于该变量在 UI 中公开,因此您可以通过传递解释目的的变量来知道为什么触发了重建. +* 有条件的作业处理. 您可以让有条件的作业在存在某个变量时运行. + +考虑以下`.gitlab-ci.yml` ,我们在其中设置了三个[阶段](../yaml/README.html#stages) ,仅当测试和构建阶段中的所有作业都通过时, `upload_package`作业才运行. 当`UPLOAD_TO_S3`变量不为零时,运行`make upload` . + +``` +stages: + - test + - build + - package + +run_tests: + stage: test + script: + - make test + +build_package: + stage: build + script: + - make build + +upload_package: + stage: package + script: + - if [ -n "${UPLOAD_TO_S3}" ]; then make upload; fi +``` + +然后,您可以在传递`UPLOAD_TO_S3`变量时触发重建,并且`upload_package`作业的脚本将运行: + +``` +curl --request POST \ + --form token=TOKEN \ + --form ref=master \ + --form "variables[UPLOAD_TO_S3]=true" \ + https://gitlab.example.com/api/v4/projects/9/trigger/pipeline +``` + +触发变量在所有类型的变量中具有[最高优先级](../variables/README.html#priority-of-environment-variables) . + +## Using cron to trigger nightly pipelines[](#using-cron-to-trigger-nightly-pipelines "Permalink") + +> **注意:**以下行为也可以通过 GitLab 的 UI 与[管道计划一起实现](../pipelines/schedules.html) . + +无论您编写脚本还是直接运行 cURL,都可以与 cron 一起触发作业. 以下示例每晚`00:30`在 ID 为`9`的项目的`master`分支上触发一个作业: + +``` +30 0 * * * curl --request POST --form token=TOKEN --form ref=master https://gitlab.example.com/api/v4/projects/9/trigger/pipeline +``` + +## Legacy triggers[](#legacy-triggers "Permalink") + +在 GitLab 9.0 之前创建的旧触发器将被标记为旧触发器. + +具有旧标签的触发器没有关联的用户,只能访问当前项目. 它们被认为已弃用,并将在将来的 GitLab 版本中删除. \ No newline at end of file diff --git a/_book/docs/268.md b/_book/docs/268.md new file mode 100644 index 0000000000000000000000000000000000000000..fc0ccfc4dc2a724a782e0912699a9a38adc4f1f3 --- /dev/null +++ b/_book/docs/268.md @@ -0,0 +1,261 @@ +# Review Apps + +> 原文:[https://docs.gitlab.com/ee/ci/review_apps/](https://docs.gitlab.com/ee/ci/review_apps/) + +* [Introduction](#introduction) +* [How Review Apps work](#how-review-apps-work) +* [Configuring Review Apps](#configuring-review-apps) + * [Enable Review Apps button](#enable-review-apps-button) +* [Review Apps auto-stop](#review-apps-auto-stop) +* [Review Apps examples](#review-apps-examples) +* [Route Maps](#route-maps) + * [Route Maps example](#route-maps-example) +* [Visual Reviews](#visual-reviews-starter) + * [Configuring Visual Reviews](#configuring-visual-reviews) + * [Determining merge request ID](#determining-merge-request-id) + * [Visual Reviews in private or internal projects](#visual-reviews-in-private-or-internal-projects) + * [Using Visual Reviews](#using-visual-reviews) +* [Limitations](#limitations) + +# Review Apps[](#review-apps "Permalink") + +版本历史 + +* 在 GitLab 8.12 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21971) . 在 GitLab 8.13 和 8.14 中进行了进一步添加. +* 受到[Heroku 的 Review Apps 的](https://devcenter.heroku.com/articles/github-integration-review-apps)启发,该[应用程序](https://devcenter.heroku.com/articles/github-integration-review-apps)本身也受到[Fourchette 的](https://github.com/rainforestapp/fourchette)启发. + +Review Apps 是一种协作工具,可消除提供展示产品更改环境的艰苦工作. + +## Introduction[](#introduction "Permalink") + +查看应用程序: + +* 通过为合并请求扩展动态环境,提供功能分支中所做更改的自动实时预览. +* 允许设计人员和产品经理查看您的更改,而无需检出分支机构并在沙盒环境中运行您的更改. +* 与[GitLab DevOps LifeCycle](../../README.html#the-entire-devops-lifecycle)完全集成. +* 允许您将更改部署到任何地方. + +[![Review Apps Workflow](img/45586bacf83042f9bfcdb01d5576fe3c.png)](img/continuous-delivery-review-apps.svg) + +在上面的示例中: + +* 每次将提交推送到`topic branch`时,都会构建一个 Review App. +* 审阅者在通过第三次审阅之前未通过两次审阅. +* 审核通过后, `topic branch`将合并到`master` `topic branch`中,并在该`topic branch`中进行部署. +* 在阶段中获得批准后,已合并到`master`中的更改将部署到生产中. + +## How Review Apps work[](#how-review-apps-work "Permalink") + +Review App 是分支与[环境](../environments/index.html)的映射. 通过与分支相关的[合并请求](../../user/project/merge_requests.html)上的链接,可以访问 Review App. + +以下是动态设置环境的合并请求的示例. + +[![Review App in merge request](img/a19f68ae0d29248e1f28009bfb10a89a.png)](img/review_apps_preview_in_mr.png) + +在此示例中,分支为: + +* 成功建立. +* 通过单击" **查看应用程序"**按钮可以到达的动态环境中进行部署. + +将 Review Apps 添加到您的工作流后,您将遵循分支的 Git 流. 那是: + +1. 推送一个分支,让 Runner 根据动态环境作业的`script`定义部署 Review App. +2. 等待 Runner 构建和部署您的 Web 应用程序. +3. 单击合并请求中与分支相关的链接,以实时查看更改. + +## Configuring Review Apps[](#configuring-review-apps "Permalink") + +Review Apps 建立在[动态环境上](../environments/index.html#configuring-dynamic-environments) ,可让您为每个分支动态创建一个新环境. + +配置 Review Apps 的过程如下: + +1. 设置基础结构以托管和部署 Review Apps(请查看下面的[示例](#review-apps-examples) ). +2. [安装](https://docs.gitlab.com/runner/install/)并[配置](https://docs.gitlab.com/runner/commands/) Runner 以进行部署. +3. 在`.gitlab-ci.yml`中设置一个作业,该作业使用[预定义的 CI 环境变量](../variables/README.html) `${CI_COMMIT_REF_NAME}`创建动态环境并将其限制为仅在分支上运行. 或者,您可以通过为项目[启用审阅应用程序](#enable-review-apps-button)来获得此工作的 YML 模板. +4. (可选)设置一个作业,以[手动停止](../environments/index.html#stopping-an-environment) Review Apps. + +### Enable Review Apps button[](#enable-review-apps-button "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/118844) . + +为项目配置 Review Apps 时,如上所述,您需要向`.gitlab-ci.yml`添加新作业. 为此,如果您正在使用 Kubernetes,则可以单击**Enable Review Apps**按钮,GitLab 会提示您一个模板代码块,您可以将该模板代码块复制并粘贴到`.gitlab-ci.yml`作为起点. 为此: + +1. 转到要为其创建 Review App 作业的项目. +2. 从左侧导航栏中,转到**运营** > **环境** . +3. 单击**启用审阅应用程序**按钮. 如果您对该项目具有开发人员或更高[权限,则](../../user/permissions.html)可以使用它. +4. 复制提供的代码段并将其粘贴到您的`.gitlab-ci.yml`文件中: + + [![Enable Review Apps modal](img/ced764ccc10657c7f37a1ffe8a7e338a.png)](img/enable_review_app_v12_8.png) + +5. 可以根据自己的需要随意调整此模板. + +## Review Apps auto-stop[](#review-apps-auto-stop "Permalink") + +了解如何在给定的时间段后将[Review Apps 环境配置为过期并自动停止](../environments/index.html#environments-auto-stop) . + +## Review Apps examples[](#review-apps-examples "Permalink") + +以下是演示 Review App 配置的示例项目: + +* [NGINX](https://gitlab.com/gitlab-examples/review-apps-nginx). +* [OpenShift](https://gitlab.com/gitlab-examples/review-apps-openshift). + +评论应用的其他示例: + +* [Cloud Native Development with GitLab](https://www.youtube.com/watch?v=jfIyQEwrocw). +* [Review Apps for Android](https://about.gitlab.com/blog/2020/05/06/how-to-create-review-apps-for-android-with-gitlab-fastlane-and-appetize-dot-io/). + +## Route Maps[](#route-maps "Permalink") + +Introduced in GitLab 8.17\. In GitLab 11.5, the file links are available in the merge request widget. + +借助路线图,您可以直接从源文件进入为 Review Apps 定义的[环境中的](../environments/index.html)公共页面. + +设置完成后,合并请求小部件中的审阅应用程序链接可以直接将您带到更改的页面,从而使预览建议的修改变得更加轻松快捷. + +配置路由图涉及到告诉 GitLab 使用路由图如何将存储库中文件的路径映射到网站上的页面路径. 设置后,GitLab 将**在" ..."**按钮**上**显示" **视图"** ,这将带您进入直接从合并请求更改的页面. + +要设置路线图,请在资源库中的`.gitlab/route-map.yml`添加一个文件,其中包含一个 YAML 数组,该数组将`source`路径(资源库中)映射到`public`路径(网站上). + +### Route Maps example[](#route-maps-example "Permalink") + +以下是[Middleman](https://middlemanapp.com)路线图的示例, [Middleman](https://middlemanapp.com)是用于构建[GitLab 网站](https://about.gitlab.com)的静态站点生成器(SSG),是从其[在 GitLab.com 上的项目](https://gitlab.com/gitlab-com/www-gitlab-com)部署的: + +``` +# Team data +- source: 'data/team.yml' # data/team.yml + public: 'team/' # team/ + +# Blogposts +- source: /source\/posts\/([0-9]{4})-([0-9]{2})-([0-9]{2})-(.+?)\..*/ # source/posts/2017-01-30-around-the-world-in-6-releases.html.md.erb + public: '\1/\2/\3/\4/' # 2017/01/30/around-the-world-in-6-releases/ + +# HTML files +- source: /source\/(.+?\.html).*/ # source/index.html.haml + public: '\1' # index.html + +# Other files +- source: /source\/(.*)/ # source/images/blogimages/around-the-world-in-6-releases-cover.png + public: '\1' # images/blogimages/around-the-world-in-6-releases-cover.png +``` + +映射定义为根 YAML 数组中的条目,并以`-`前缀标识. 在一个条目中,有一个带有两个键的哈希映射: + +* `source` + * 完全匹配的字符串,以`'`开头和结尾. + * 正则表达式,以`/`开头和结尾,用于模式匹配: + * 正则表达式需要匹配整个源路径-隐含`^`和`$`锚. + * 可以包括由`()`表示的捕获组,这些捕获组可以在`public`路径中引用. + * 斜杠( `/` )可以但不必转为`\/` . + * 文字句号( `.` )应转为`\.` . +* `public` ,一个以`'`开头和结尾的字符串. + * 可以包含`\N`表达式,从`source`正则表达式开始,以其出现的顺序引用捕获组,从`\1`开始. + +通过找到与之匹配的第一个`source`表达式,然后返回相应的`public`路径,并用`()`捕获组的值替换`\N`表达式,来确定源路径的`public`路径. + +在上面的示例中,按照定义顺序对映射进行求值的事实用于确保`source/index.html.haml`将匹配`/source\/(.+?\.html).*/`而不是`/source\/(.*)/` ,并将导致`index.html`的公共路径,而不是`index.html.haml` . + +设置路由映射后,它将在以下位置生效: + +* 在合并请求小部件中. 该: + * **"查看应用程序"**按钮将带您进入`.gitlab-ci.yml`设置的环境 URL. + * 下拉菜单将列出路线图中的前 5 个匹配项,但如果有 5 个以上可用项,则可以对其进行过滤. + + [![在合并请求小部件中查看应用程序文件列表](img/738413ec37e13f47706eeda5de3b9dfb.png)](img/view_on_mr_widget.png) + +* 在差异中进行合并请求,比较或提交. + + [!["View on env" button in merge request diff](img/ed8e7e034537074afe857aa208bd315c.png)](img/view_on_env_mr.png) + +* 在 Blob 文件视图中. + + [!["View on env" button in file view](img/1bb73cd8d699dd8fa617c328abafb76b.png)](img/view_on_env_blob.png) + +## Visual Reviews[](#visual-reviews-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10761) in GitLab Starter 12.0. + +使用视觉评论,您可以向您的评论应用程序提供反馈表单,以便评论者可以将评论直接从应用程序发布回产生评论应用程序的合并请求. + +### Configuring Visual Reviews[](#configuring-visual-reviews "Permalink") + +确保启用了`anonymous_visual_review_feedback`功能标志. 管理员可以使用 Rails 控制台启用,如下所示: + +``` +Feature.enable(:anonymous_visual_review_feedback) +``` + +反馈表单是通过您添加到 Review App 中页面的脚本提供的. 如果您拥有该项目的[开发人员权限](../../user/permissions.html) ,则可以通过单击合并请求的" **管道"**部分中的" **查看"**按钮来访问它. 如果在项目中配置了[路线图,](#route-maps)则表格模式还将显示更改页面的下拉列表. + +[![review button](img/4feb8b1885ea3a6c0945d7d32d15e8ff.png)](img/review_button.png) + +提供的脚本应添加到应用程序的``中,并由一些项目和合并请求特定的值组成. 看起来是这样的: + +``` + +``` + +理想情况下,创建每个审阅应用程序时,应在运行时使用[环境变量](../variables/predefined_variables.html)替换这些值: + +* `data-project-id`是项目 ID,可通过`CI_PROJECT_ID`变量找到. +* `data-merge-request-id`是合并请求 ID,可以通过`CI_MERGE_REQUEST_IID`变量找到它. `CI_MERGE_REQUEST_IID`仅当[`only: [merge_requests]`](../merge_request_pipelines/index.html)被使用并且在创建合并请求. +* `data-mr-url`是 GitLab 实例的 URL,并且对于所有评论应用程序都是相同的. +* `data-project-path`是项目的路径,可以通过`CI_PROJECT_PATH`找到. +* `data-require-auth`对于公共项目是可选的,但对于[私有和内部](#visual-reviews-in-private-or-internal-projects)项目则是必需[的](#visual-reviews-in-private-or-internal-projects) . 如果将其设置为`true` ,则将要求用户输入其[个人访问令牌,](../../user/profile/personal_access_tokens.html)而不是其名称和电子邮件. +* `id`始终是`review-app-toolbar-script` ,您无需更改它. +* `src`是审阅工具栏脚本的源代码,该脚本位于相应的 GitLab 实例中,并且对于所有审阅应用程序都是相同的. + +例如,在 Ruby 应用程序中,您需要具有以下脚本: + +``` + +``` + +然后,当通过 GitLab CI / CD 部署您的应用程序时,这些变量应替换为其实际值. + +### Determining merge request ID[](#determining-merge-request-id "Permalink") + +视觉审核工具从`script` HTML 标签中包含的`data-merge-request-id`数据属性中检索合并请求 ID,该`script` HTML 标签用于将视觉审核工具添加到您的审核应用中. + +确定合并请求以链接到可视评论应用程序的 ID 后,您可以通过以下任一方式提供 ID: + +* 通过应用程序的数据属性`data-merge-request-id`在 script 标签中对其进行硬编码. +* 在应用程序的构建过程中动态添加`data-merge-request-id`值. +* 通过应用中的视觉查看表单手动提供. + +### Visual Reviews in private or internal projects[](#visual-reviews-in-private-or-internal-projects "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/42750#note_317271120) . + +要对私有项目和内部项目启用可视化审阅,请将[`data-require-auth`变量设置](#configuring-visual-reviews)为`true` . 启用后,用户必须输入具有`api`范围的[个人访问令牌](../../user/profile/personal_access_tokens.html) ,然后才能提交反馈. + +### Using Visual Reviews[](#using-visual-reviews "Permalink") + +在为"评论"应用程序[启用](#configuring-visual-reviews) "视觉评论"后,"视觉评论"反馈表单将覆盖在应用程序页面的右下角. + +[![Visual review feedback form](img/482b8e23d226428516ae20fae41ca7cf.png)](img/toolbar_feeback_form.png) + +要使用反馈表: + +1. 对视觉评论发表评论. 您可以使用合并请求注释中所有可用的[Markdown 注释](../../user/markdown.html) . +2. 如果`data-require-auth`为`true` ,则必须输入[个人访问令牌](../../user/profile/personal_access_tokens.html) . 否则,您必须输入您的姓名,以及可选的电子邮件地址. +3. 最后,点击**发送反馈** . + +在视觉检查框中做出评论并提交评论后,评论将自动出现在相应的合并请求中. + +## Limitations[](#limitations "Permalink") + +Review App 限制与[环境限制](../environments/index.html#limitations)相同. \ No newline at end of file diff --git a/_book/docs/269.md b/_book/docs/269.md new file mode 100644 index 0000000000000000000000000000000000000000..40fb962b095b044da1b425473f67a6df30d5fa56 --- /dev/null +++ b/_book/docs/269.md @@ -0,0 +1,401 @@ +# Configuring GitLab Runners + +> 原文:[https://docs.gitlab.com/ee/ci/runners/README.html](https://docs.gitlab.com/ee/ci/runners/README.html) + +* [Types of Runners](#types-of-runners) + * [Shared Runners](#shared-runners) + * [How shared Runners pick jobs](#how-shared-runners-pick-jobs) + * [Enable shared Runners](#enable-shared-runners) + * [Disable shared Runners](#disable-shared-runners) + * [Group Runners](#group-runners) + * [Create a group Runner](#create-a-group-runner) + * [View and manage group Runners](#view-and-manage-group-runners) + * [Pause or remove a group Runner](#pause-or-remove-a-group-runner) + * [Specific Runners](#specific-runners) + * [Create a specific Runner](#create-a-specific-runner) + * [Enable a specific Runner for a specific project](#enable-a-specific-runner-for-a-specific-project) + * [Prevent a specific Runner from being enabled for other projects](#prevent-a-specific-runner-from-being-enabled-for-other-projects) +* [Manually clear the Runner cache](#manually-clear-the-runner-cache) +* [Set maximum job timeout for a Runner](#set-maximum-job-timeout-for-a-runner) +* [Be careful with sensitive information](#be-careful-with-sensitive-information) + * [Prevent Runners from revealing sensitive information](#prevent-runners-from-revealing-sensitive-information) + * [Forks](#forks) + * [Attack vectors in Runners](#attack-vectors-in-runners) + * [Reset the Runner registration token for a project](#reset-the-runner-registration-token-for-a-project) +* [Determine the IP address of a Runner](#determine-the-ip-address-of-a-runner) + * [Determine the IP address of a shared Runner](#determine-the-ip-address-of-a-shared-runner) + * [Determine the IP address of a specific Runner](#determine-the-ip-address-of-a-specific-runner) +* [Use tags to limit the number of jobs using the Runner](#use-tags-to-limit-the-number-of-jobs-using-the-runner) + * [Runner runs only tagged jobs](#runner-runs-only-tagged-jobs) + * [Runner is allowed to run untagged jobs](#runner-is-allowed-to-run-untagged-jobs) + +# Configuring GitLab Runners[](#configuring-gitlab-runners "Permalink") + +在 GitLab CI / CD 中,运行程序运行[`.gitlab-ci.yml`](../yaml/README.html)定义的代码. GitLab Runner 是一种轻量级,高度可扩展的代理,它通过 GitLab CI / CD 的协调器 API 提取 CI 作业,运行该作业,并将结果发送回 GitLab 实例. + +运行程序由管理员创建,并在 GitLab UI 中可见. 运行者可以特定于某些项目,也可以适用于所有项目. + +## Types of Runners[](#types-of-runners "Permalink") + +跑步者共有三种类型: + +* [共享](#shared-runners) (对于所有项目) +* [组](#group-runners) (对于[组](#group-runners)中的所有项目) +* [具体](#specific-runners) (针对特定项目) + +如果您正在运行自我管理的 GitLab,则可以创建自己的 Runners. + +如果使用的是 GitLab.com,则可以使用 GitLab 提供的共享运行程序,也可以创建自己的组或特定运行程序. + +### Shared Runners[](#shared-runners "Permalink") + +GitLab 实例中的每个项目都可以使用*共享运行器* . + +当您有多个要求相似的作业时,请使用共享的运行器. 您可以让几个处理多个项目的 Runner 而不是让多个 Runner 空闲多个项目. + +如果您使用的是 GitLab 的自我管理实例: + +* 您的管理员可以通过查看[此处](https://docs.gitlab.com/runner/install/index.html)的说明来安装和注册共享运行程序. +* 管理员还可[以为每个组](../../user/admin_area/settings/continuous_integration.html#shared-runners-pipeline-minutes-quota-starter-only)配置最大的共享 Runner [管道分钟数](../../user/admin_area/settings/continuous_integration.html#shared-runners-pipeline-minutes-quota-starter-only) . + +如果您使用的是 GitLab.com: + +* 您可以从[GitLab 维护](../../user/gitlab_com/index.html#shared-runners)的[共享运行程序](../../user/gitlab_com/index.html#shared-runners)列表中进行选择. +* 共享的跑步者会消耗您帐户中包含的[管道分钟](../../subscriptions/index.html#ci-pipeline-minutes) . + +#### How shared Runners pick jobs[](#how-shared-runners-pick-jobs "Permalink") + +共享运行者通过使用合理使用队列来处理作业. 此队列可防止项目创建数百个作业并使用所有可用的共享 Runner 资源. + +合理使用队列算法根据已在共享 Runner 上运行的作业数量最少的项目分配作业. + +**Example 1** + +如果这些作业在队列中: + +* 项目 1 的工作 1 +* 项目 1 的工作 2 +* 项目 1 的工作 3 +* 项目 2 的工作 4 +* 项目 2 的工作 5 +* 项目 3 的工作 6 + +合理使用算法按以下顺序分配作业: + +1. 首先选择作业 1,因为它在没有正在运行的作业的项目(即所有项目)中具有最低的作业编号. +2. 接下来是作业 4,因为现在 4 是来自没有正在运行的作业的项目中最低的作业编号(项目 1 有正在运行的作业). +3. 接下来是作业 6,因为 6 现在是没有正在运行的作业的项目中最低的作业编号(项目 1 和 2 有正在运行的作业). +4. 接下来是作业 2,因为在运行的作业数量最少的项目(每个都有 1)中,它是最低的作业数量. +5. 接下来是作业 5,因为项目 1 现在有 2 个正在运行的作业,而作业 5 是项目 2 和项目 3 之间剩余的最低编号. +6. 最后是工作 3…,因为这是剩下的唯一工作. + +* * * + +**例子 2** + +如果这些作业在队列中: + +* 项目 1 的工作 1 +* 项目 1 的工作 2 +* 项目 1 的工作 3 +* 项目 2 的工作 4 +* 项目 2 的工作 5 +* 项目 3 的工作 6 + +合理使用算法按以下顺序分配作业: + +1. 首先选择作业 1,因为它在没有正在运行的作业的项目(即所有项目)中具有最低的作业编号. +2. 我们完成工作 1. +3. 接下来是作业 2,因为完成作业 1 后,所有项目都再次运行 0 个作业,而 2 是最低的可用作业号. +4. 接下来是作业 4,因为在项目 1 运行作业的情况下,项目 4 在没有运行作业的项目(项目 2 和 3)中是最低的. +5. 我们完成工作 4. +6. 接下来是作业 5,因为完成了作业 4,所以项目 2 没有再次运行的作业. +7. 接下来是作业 6,因为项目 3 是唯一没有运行作业的项目. +8. 最后,我们选择作业 3…,因为它再次是唯一剩下的作业. + +#### Enable shared Runners[](#enable-shared-runners "Permalink") + +在 GitLab.com 上,默认情况下在所有项目中启用[共享运行器](#shared-runners) . + +On self-managed instances of GitLab, an administrator must [install](https://docs.gitlab.com/runner/install/index.html) and [register](https://docs.gitlab.com/runner/register/index.html) them. + +您还可以为单个项目启用共享运行器. + +要启用共享跑步者: + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. Click **允许共享跑步者**. + +#### Disable shared Runners[](#disable-shared-runners "Permalink") + +您可以为单个项目禁用共享运行器. 您必须具有项目的所有者权限. + +要为项目禁用共享运行器: + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. 在" **共享运行程序"**区域中,单击" **禁用共享运行程序"** . + +### Group Runners[](#group-runners "Permalink") + +当您希望组中的所有项目都可以访问一组运行器时,请使用" *组运行器"* . + +Group Runners process jobs by using a first in, first out ([FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics))) queue. + +#### Create a group Runner[](#create-a-group-runner "Permalink") + +您可以为自己管理的 GitLab 实例或 GitLab.com 创建一个组 Runner. 您必须具有该组的[所有者权限](../../user/permissions.html#group-members-permissions) . + +创建组跑步者: + +1. [Install Runner](https://docs.gitlab.com/runner/install/). +2. 转到您要使 Runner 运行的组. +3. 去 **设置> CI / CD,**然后展开" **跑步者"**部分. +4. 注意 URL 和令牌. +5. [Register the Runner](https://docs.gitlab.com/runner/register/). + +#### View and manage group Runners[](#view-and-manage-group-runners "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/37366/) . + +您可以查看和管理组,其子组和项目的所有运行器. 您可以为自己管理的 GitLab 实例或 GitLab.com 执行此操作. 您必须具有该组的[所有者权限](../../user/permissions.html#group-members-permissions) . + +1. 转到要查看跑步者的组. +2. 去 **设置> CI / CD,**然后展开" **跑步者"**部分. +3. 显示以下字段. + + | Attribute | Description | + | --- | --- | + | Type | 以下一种或多种状态:共享,组,特定,锁定或暂停 | + | 赛跑者令牌 | 令牌用于标识 Runner,并且 Runner 用于与 GitLab 实例进行通信 | + | Description | 创建跑步者时的描述 | + | Version | GitLab Runner 版本 | + | IP 地址 | 注册了运行程序的主机的 IP 地址 | + | Projects | Runner 分配到的项目数 | + | Jobs | 跑步者所从事的工作总数 | + | Tags | 与跑步者相关的标签 | + | 最后联络人 | 指示 GitLab 实例最后一次与 Runner 联系的时间戳 | + +在此页面上,您可以编辑,暂停和从组,其子组和项目中删除"跑步者". + +#### Pause or remove a group Runner[](#pause-or-remove-a-group-runner "Permalink") + +您可以为自己管理的 GitLab 实例或 GitLab.com 暂停或删除组运行器. 您必须具有该组的[所有者权限](../../user/permissions.html#group-members-permissions) . + +1. 转到您要删除或暂停 Runner 的组. +2. 去 **设置> CI / CD,**然后展开" **跑步者"**部分. +3. Click **Pause** or **删除亚军**. + * 如果您暂停由多个项目使用的组 Runner,则 Runner 会暂停所有项目. + * 从组视图中,您无法删除分配给多个项目的运行器. 您必须先从每个项目中将其删除. +4. 在确认对话框中,单击**确定** . + +### Specific Runners[](#specific-runners "Permalink") + +当你想使用运动员的具体项目使用*特定的运动员* . 例如,当您拥有: + +* 有特定要求的作业,例如需要凭据的部署作业. +* CI 活动很多的项目可以从与其他运行者分离中受益. + +您可以设置一个特定的 Runner,以供多个项目使用. 必须为每个项目明确启用特定的运行器. + +特定运行程序通过使用[先进先出](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)) ( [FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)) )队列来处理作业. + +**注意:**特定运行器不会自动与分支项目共享. 分支*确实会*复制克隆存储库的 CI / CD 设置. + +#### Create a specific Runner[](#create-a-specific-runner "Permalink") + +您可以为自己管理的 GitLab 实例或 GitLab.com 创建特定的 Runner. 您必须具有项目的[所有者权限](../../user/permissions.html#project-members-permissions) . + +要创建特定的运行器: + +1. [Install Runner](https://docs.gitlab.com/runner/install/). +2. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +3. 注意 URL 和令牌. +4. [Register the Runner](https://docs.gitlab.com/runner/register/). + +#### Enable a specific Runner for a specific project[](#enable-a-specific-runner-for-a-specific-project "Permalink") + +在为其创建的项目中提供了特定的 Runner. 管理员可以使特定的 Runner 应用于其他项目. + +* 您必须具有项目的所有者权限. +* 特定的跑步者一定不能被[锁定](#prevent-a-specific-runner-from-being-enabled-for-other-projects) . + +要为项目启用或禁用特定的运行器: + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. Click **为此项目启用** or **为此项目禁用**. + +#### Prevent a specific Runner from being enabled for other projects[](#prevent-a-specific-runner-from-being-enabled-for-other-projects "Permalink") + +您可以配置一个特定的运行器,使其"锁定"并且不能为其他项目启用. 首次[注册 Runner](https://docs.gitlab.com/runner/register/)时可以启用此设置,但以后也可以更改. + +锁定或解锁跑步者: + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. 找到您想要锁定或解锁的亚军. 确保已启用. +3. 单击铅笔按钮. +4. 选中" **锁定到当前项目"**选项. +5. Click **保存更改**. + +## Manually clear the Runner cache[](#manually-clear-the-runner-cache "Permalink") + +Read [clearing the cache](../caching/index.html#clearing-the-cache). + +## Set maximum job timeout for a Runner[](#set-maximum-job-timeout-for-a-runner "Permalink") + +对于每个跑步者,您可以指定*最大作业超时时间* . 如果此超时时间小于[项目定义的超时时间](../pipelines/settings.html#timeout) ,则优先. + +此功能可用于防止共享的 Runner 被具有较长超时(例如,一个星期)的工作的项目淹没. + +未配置时,Runner 将不会覆盖项目超时. + +此功能的工作原理: + +**示例 1-运行程序超时大于项目超时** + +1. 您将跑步者的*最大作业超时*设置为 24 小时 +2. 您将项目的*CI / CD 超时*设置为**2 小时** +3. 你开始工作 +4. 如果工作时间更长,则**2 小时**后将超时 + +**示例 2-未配置运行程序超时** + +1. 您从运行器中删除*最大作业超时*配置 +2. 您将项目的*CI / CD 超时*设置为**2 小时** +3. 你开始工作 +4. 如果工作时间更长,则**2 小时**后将超时 + +**示例 3-运行程序超时小于项目超时** + +1. 您将跑步者的*最大作业超时*设置为**30 分钟** +2. 您将项目的*CI / CD 超时*设置为 2 小时 +3. 你开始工作 +4. 如果作业时间更长,则**30 分钟**后将超时 + +## Be careful with sensitive information[](#be-careful-with-sensitive-information "Permalink") + +使用某些[Runner Executors](https://docs.gitlab.com/runner/executors/README.html) ,如果可以在 Runner 上运行作业,则可以完全访问文件系统,从而可以运行该文件的任何代码以及 Runner 的令牌. 使用共享的运行程序,这意味着在运行程序上运行作业的任何人都可以访问在运行程序上运行的任何其他人的代码. + +另外,由于您可以访问 Runner 令牌,因此可以创建 Runner 的克隆并提交错误的作业. + +通过限制在大型公共 GitLab 实例上共享[Runner 的](https://docs.gitlab.com/runner/executors/README.html)使用,控制对 GitLab 实例的访问以及使用更安全的[Runner Executor](https://docs.gitlab.com/runner/executors/README.html) ,可以轻松避免上述情况. + +### Prevent Runners from revealing sensitive information[](#prevent-runners-from-revealing-sensitive-information "Permalink") + +在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13194) . + +您可以保护赛跑者,使他们不会泄露敏感信息. 当运行器受到保护时,运行器仅选择在[受保护分支](../../user/project/protected_branches.html)或[受保护标签](../../user/project/protected_tags.html)上创建的作业,而忽略其他作业. + +保护或取消保护跑步者: + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. 找到您要保护或取消保护的跑步者. 确保已启用. +3. 单击铅笔按钮. +4. 检查**受保护的**选项. +5. Click **保存更改**. + +[![specific Runners edit icon](img/91abd5be225ec3a5c131075cce857fb8.png)](img/protected_runners_check_box.png) + +### Forks[](#forks "Permalink") + +每当分支一个项目时,它都会复制与其相关的作业的设置. 这意味着,如果您已经为项目设置了共享的 Runners,并且有人分叉了该项目,则共享的 Runners 也将为该项目的工作提供服务. + +### Attack vectors in Runners[](#attack-vectors-in-runners "Permalink") + +前面已经简要提到过,但是可以利用 Runners 的以下功能. 我们一直在寻找可以减轻这些[安全注意事项的因素](https://docs.gitlab.com/runner/security/) . + +### Reset the Runner registration token for a project[](#reset-the-runner-registration-token-for-a-project "Permalink") + +如果您认为某个项目的注册令牌已公开,则应将其重置. 令牌可用于为该项目注册另一个 Runner. 然后可以使用该新 Runner 来获取秘密变量的值或克隆项目代码. + +重置令牌: + +1. 转到项目的 **设置> CI / CD** . +2. 展开**常规管道设置**部分. +3. 找到" **跑步者令牌"**表单字段,然后单击" **显示值"**按钮. +4. 删除值并保存表单. +5. 刷新页面后,展开" **跑步者设置"**部分并检查注册令牌-应该更改它. + +从现在开始,旧令牌将不再有效,并且不会在项目中注册任何新的运行者. 如果您使用任何工具来供应和注册新的运行器,则应更新这些工具中使用的令牌以反映新令牌的价值. + +## Determine the IP address of a Runner[](#determine-the-ip-address-of-a-runner "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17286) . + +知道 Runner 的 IP 地址可能很有用,以便您可以解决该 Runner 的问题. GitLab 通过在轮询作业时查看向 GitLab 发出的 HTTP 请求的源来存储和显示 IP 地址. IP 地址始终保持最新,因此,如果 Runner IP 更改,它将在 GitLab 中自动更新. + +共享运行程序和特定运行程序的 IP 地址可以在不同位置找到. + +### Determine the IP address of a shared Runner[](#determine-the-ip-address-of-a-shared-runner "Permalink") + +要查看共享运行器的 IP 地址,您必须具有对 GitLab 实例的管理员访问权限. 要确定这一点: + +1. Visit **管理区域>概述>跑步者**. +2. 在表中查找 Runner,您应该看到**IP Address**列. + +[![shared Runner IP address](img/d0b0b1ad83988d76ef9c42281782f961.png)](img/shared_runner_ip_address.png) + +### Determine the IP address of a specific Runner[](#determine-the-ip-address-of-a-specific-runner "Permalink") + +若要查找特定项目的运行程序的 IP 地址,您必须具有该项目的所有者[权限](../../user/permissions.html#project-members-permissions) . + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. 在详细信息页面上,您应该看到**IP 地址**行. + +[![specific Runner IP address](img/b6c59d6785a7941658315a7e8e148751.png)](img/specific_runner_ip_address.png) + +## Use tags to limit the number of jobs using the Runner[](#use-tags-to-limit-the-number-of-jobs-using-the-runner "Permalink") + +您必须设置一个 Runner 才能运行它在共享项目上可能遇到的所有不同类型的作业. 如果不是标签,这对于大量项目将是有问题的. + +通过将 Runner 标记为它可以处理的作业类型,可以确保共享的 Runners [仅运行其能够运行的作业](../yaml/README.html#tags) . + +例如,在 GitLab 上,如果 Runners 包含运行 Rails 测试套件的适当依赖项,我们会将它们标记为`rails` . + +[注册 Runner 时](https://docs.gitlab.com/runner/register/) ,其默认行为是**仅选择带** [标签的作业](../yaml/README.html#tags) . 要更改此设置,您必须具有项目的所有者[权限](../../user/permissions.html#project-members-permissions) . + +要使跑步者选择无标签的工作,请执行以下操作: + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. 找到您要选择未加标签的作业的 Runner,并确保已启用它. +3. 单击铅笔按钮. +4. 选中**运行未加标签的作业**选项. +5. 单击**保存更改**按钮以使更改生效. + +**注意:**不允许选择未标记的作业时,"运行者标签"列表不能为空. + +以下是一些不同变化的示例场景. + +### Runner runs only tagged jobs[](#runner-runs-only-tagged-jobs "Permalink") + +以下示例说明了将 Runner 设置为仅运行带标签的作业的潜在影响. + +范例 1: + +1. Runner 配置为仅运行带标签的作业,并具有`docker`标签. +2. 具有`hello`标签的作业将被执行并卡住. + +Example 2: + +1. Runner 配置为仅运行带标签的作业,并具有`docker`标签. +2. 具有`docker`标签的作业将被执行并运行. + +范例 3: + +1. Runner 配置为仅运行带标签的作业,并具有`docker`标签. +2. 没有定义标签的作业将被执行并卡住. + +### Runner is allowed to run untagged jobs[](#runner-is-allowed-to-run-untagged-jobs "Permalink") + +以下示例说明了将 Runner 设置为运行带标签和未带标签的作业的潜在影响. + +范例 1: + +1. Runner 配置为运行未加标签的作业,并具有`docker`标签. +2. 没有定义标签的作业将被执行并运行. +3. 执行并运行定义了`docker`标签的第二项作业. + +范例 2: + +1. Runner 配置为运行未加标签的作业,并且未定义标签. +2. 没有定义标签的作业将被执行并运行. +3. 卡有定义了`docker`标签的第二项工作. \ No newline at end of file diff --git a/_book/docs/270.md b/_book/docs/270.md new file mode 100644 index 0000000000000000000000000000000000000000..60d75537429e5245d76951ac3b4f82e032dedf8f --- /dev/null +++ b/_book/docs/270.md @@ -0,0 +1,13 @@ +# GitLab CI services examples + +> 原文:[https://docs.gitlab.com/ee/ci/services/README.html](https://docs.gitlab.com/ee/ci/services/README.html) + +# GitLab CI services examples[](#gitlab-ci-services-examples "Permalink") + +[`services`](../docker/using_docker_images.html#what-is-a-service)关键字定义了一个 Docker 映像,该映像在与 image 关键字定义的 Docker 映像链接的`job`中运行. 这样,您就可以在构建期间访问服务映像. + +服务映像可以运行任何应用程序,但是最常见的用例是运行数据库容器,例如: + +* [Using MySQL](mysql.html) +* [Using PostgreSQL](postgres.html) +* [Using Redis](redis.html) \ No newline at end of file diff --git a/_book/docs/271.md b/_book/docs/271.md new file mode 100644 index 0000000000000000000000000000000000000000..02831128f8e31db9a482fe8f649ba3718f2a48e4 --- /dev/null +++ b/_book/docs/271.md @@ -0,0 +1,111 @@ +# Using MySQL + +> 原文:[https://docs.gitlab.com/ee/ci/services/mysql.html](https://docs.gitlab.com/ee/ci/services/mysql.html) + +* [Use MySQL with the Docker executor](#use-mysql-with-the-docker-executor) +* [Use MySQL with the Shell executor](#use-mysql-with-the-shell-executor) +* [Example project](#example-project) + +# Using MySQL[](#using-mysql "Permalink") + +由于许多应用程序都依赖 MySQL 作为其数据库,因此最终需要它才能运行测试. 下面将指导您如何使用 GitLab Runner 的 Docker 和 Shell 执行程序执行此操作. + +## Use MySQL with the Docker executor[](#use-mysql-with-the-docker-executor "Permalink") + +如果您将[GitLab Runner](../runners/README.html)与 Docker 执行程序一起使用,则基本上已经完成了所有设置. + +First, in your `.gitlab-ci.yml` add: + +``` +services: + - mysql:latest + +variables: + # Configure mysql environment variables (https://hub.docker.com/_/mysql/) + MYSQL_DATABASE: "" + MYSQL_ROOT_PASSWORD: "" +``` + +**注意:**无法在 GitLab UI 中设置`MYSQL_DATABASE`和`MYSQL_ROOT_PASSWORD`变量. 要设置它们,请将它们分配给[UI 中](../variables/README.html#create-a-custom-variable-in-the-ui)的变量,然后将该变量分配给`.gitlab-ci.yml`的`MYSQL_DATABASE`和`MYSQL_ROOT_PASSWORD`变量. + +然后将您的应用程序配置为使用数据库,例如: + +``` +Host: mysql +User: root +Password: +Database: +``` + +如果您想知道为什么我们对`Host`使用`mysql` ,请阅读[如何将服务链接到作业的更多信息](../docker/using_docker_images.html#how-services-are-linked-to-the-job) . + +您还可以使用[Docker Hub](https://hub.docker.com/_/mysql/)上可用的任何其他 Docker 映像. 例如,要使用 MySQL 5.5,服务将变为`mysql:5.5` . + +`mysql`映像可以接受一些环境变量. 有关更多详细信息,请参阅[Docker Hub](https://hub.docker.com/_/mysql/)上的文档. + +## Use MySQL with the Shell executor[](#use-mysql-with-the-shell-executor "Permalink") + +您还可以在手动配置的服务器上使用 MySQL,该服务器通过 Shell 执行程序使用 GitLab Runner. + +首先安装 MySQL 服务器: + +``` +sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev +``` + +选择一个 MySQL 根密码(可以是任何密码),并在询问时键入两次. + +*注意:作为一项安全措施,您可以运行`mysql_secure_installation`删除匿名用户,删除测试数据库并以 root 用户禁用远程登录.* + +下一步是创建用户,因此以 root 用户身份登录 MySQL: + +``` +mysql -u root -p +``` + +然后创建一个将由您的应用程序使用的用户(在我们的示例中为`runner` ). 将以下命令中的`$password`更改`$password`真实的强密码. + +*注意:请勿键入`mysql>` ,这是 MySQL 提示符的一部分.* + +``` +mysql> CREATE USER 'runner'@'localhost' IDENTIFIED BY '$password'; +``` + +创建数据库: + +``` +mysql> CREATE DATABASE IF NOT EXISTS `` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`; +``` + +授予对数据库的必要权限: + +``` +mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES ON ``.* TO 'runner'@'localhost'; +``` + +如果一切顺利,您现在可以退出数据库会话: + +``` +mysql> \q +``` + +现在,尝试连接到新创建的数据库以检查一切是否就绪: + +``` +mysql -u runner -p -D +``` + +最后,配置您的应用程序以使用数据库,例如: + +``` +Host: localhost +User: runner +Password: $password +Database: +``` + +## Example project[](#example-project "Permalink") + +为了方便起见,我们使用公共可[共享的](../runners/README.html)运行程序在[GitLab.com](https://gitlab.com)上运行了一个[MySQL 示例项目](https://gitlab.com/gitlab-examples/mysql) . + +想要破解吗? 只需对其进行分叉,提交并推送您的更改. 稍后,公共跑步者将选择更改并开始工作. \ No newline at end of file diff --git a/_book/docs/272.md b/_book/docs/272.md new file mode 100644 index 0000000000000000000000000000000000000000..9e1748a8c9e857e83976a37c80e059e917526e95 --- /dev/null +++ b/_book/docs/272.md @@ -0,0 +1,106 @@ +# Using PostgreSQL + +> 原文:[https://docs.gitlab.com/ee/ci/services/postgres.html](https://docs.gitlab.com/ee/ci/services/postgres.html) + +* [Use PostgreSQL with the Docker executor](#use-postgresql-with-the-docker-executor) +* [Use PostgreSQL with the Shell executor](#use-postgresql-with-the-shell-executor) +* [Example project](#example-project) + +# Using PostgreSQL[](#using-postgresql "Permalink") + +由于许多应用程序都依赖 PostgreSQL 作为其数据库,因此最终需要它才能运行测试. 下面将指导您如何使用 GitLab Runner 的 Docker 和 Shell 执行程序执行此操作. + +## Use PostgreSQL with the Docker executor[](#use-postgresql-with-the-docker-executor "Permalink") + +如果您将[GitLab Runner](../runners/README.html)与 Docker 执行程序一起使用,则基本上已经完成了所有设置. + +首先,在您的`.gitlab-ci.yml`添加: + +``` +services: + - postgres:12.2-alpine + +variables: + POSTGRES_DB: nice_marmot + POSTGRES_USER: runner + POSTGRES_PASSWORD: "" + POSTGRES_HOST_AUTH_METHOD: trust +``` + +**注意:**不能在 GitLab UI 中设置`POSTGRES_DB` , `POSTGRES_USER` , `POSTGRES_PASSWORD`和`POSTGRES_HOST_AUTH_METHOD`变量. 要设置它们,请将它们分配给[UI 中](../variables/README.html#create-a-custom-variable-in-the-ui)的变量,然后将该变量分配给`.gitlab-ci.yml`的`POSTGRES_DB` , `POSTGRES_USER` , `POSTGRES_PASSWORD`和`POSTGRES_HOST_AUTH_METHOD`变量. + +然后将您的应用程序配置为使用数据库,例如: + +``` +Host: postgres +User: runner +Password: '' +Database: nice_marmot +``` + +如果您想知道为什么我们对`Host`使用`postgres` ,请阅读[如何将服务链接到作业的更多信息](../docker/using_docker_images.html#how-services-are-linked-to-the-job) . + +您还可以使用[Docker Hub](https://hub.docker.com/_/postgres)上可用的任何其他 Docker 映像. 例如,要使用 PostgreSQL 9.3,服务将变为`postgres:9.3` . + +`postgres`图像可以接受一些环境变量. 有关更多详细信息,请参阅[Docker Hub](https://hub.docker.com/_/postgres)上的文档. + +## Use PostgreSQL with the Shell executor[](#use-postgresql-with-the-shell-executor "Permalink") + +您还可以在手动配置的服务器上使用 PostgreSQL,这些服务器将 GitLab Runner 与 Shell 执行程序一起使用. + +首先安装 PostgreSQL 服务器: + +``` +sudo apt-get install -y postgresql postgresql-client libpq-dev +``` + +下一步是创建用户,因此登录 PostgreSQL: + +``` +sudo -u postgres psql -d template1 +``` + +然后创建一个将由您的应用程序使用的用户(在我们的示例中为`runner` ). 将以下命令中的`$password`更改`$password`真实的强密码. + +***注意:**不要输入`template1=#` ,这是 PostgreSQL 提示的一部分.* + +``` +template1=# CREATE USER runner WITH PASSWORD '$password' CREATEDB; +``` + +***注意:**请注意,我们创建的用户具有创建数据库的特权( `CREATEDB` ). 在以下步骤中,我们将为该用户显式创建一个数据库,但是如果在您的测试框架中有删除和创建数据库的工具,则具有该特权将很有用.* + +创建数据库,并授予其上的所有特权用户`runner` : + +``` +template1=# CREATE DATABASE nice_marmot OWNER runner; +``` + +如果一切顺利,您现在可以退出数据库会话: + +``` +template1=# \q +``` + +现在,尝试连接到与用户新创建的数据库`runner`检查一切就绪. + +``` +psql -U runner -h localhost -d nice_marmot -W +``` + +***注意:**我们明确告诉`psql`连接到 localhost 以便使用 md5 身份验证. 如果您省略此步骤,则将被拒绝访问.* + +最后,将您的应用程序配置为使用数据库,例如: + +``` +Host: localhost +User: runner +Password: $password +Database: nice_marmot +``` + +## Example project[](#example-project "Permalink") + +为了方便起见,我们使用公共可[共享的](../runners/README.html)运行程序在[GitLab.com](https://gitlab.com)上运行了一个[示例 PostgreSQL 项目](https://gitlab.com/gitlab-examples/postgres) . + +想要破解吗? 只需对其进行分叉,提交并推送您的更改. 稍后,公共跑步者将选择更改并开始工作. \ No newline at end of file diff --git a/_book/docs/273.md b/_book/docs/273.md new file mode 100644 index 0000000000000000000000000000000000000000..618b9ef1c1723e2d6caf917dc7d613fd8fe5d029 --- /dev/null +++ b/_book/docs/273.md @@ -0,0 +1,64 @@ +# Using Redis + +> 原文:[https://docs.gitlab.com/ee/ci/services/redis.html](https://docs.gitlab.com/ee/ci/services/redis.html) + +* [Use Redis with the Docker executor](#use-redis-with-the-docker-executor) +* [Use Redis with the Shell executor](#use-redis-with-the-shell-executor) +* [Example project](#example-project) + +# Using Redis[](#using-redis "Permalink") + +由于许多应用程序都将 Redis 用作键值存储,因此最终需要它才能运行测试. 下面将指导您如何使用 GitLab Runner 的 Docker 和 Shell 执行程序执行此操作. + +## Use Redis with the Docker executor[](#use-redis-with-the-docker-executor "Permalink") + +如果您将[GitLab Runner](../runners/README.html)与 Docker 执行程序一起使用,则基本上已经完成了所有设置. + +首先,在您的`.gitlab-ci.yml`添加: + +``` +services: + - redis:latest +``` + +然后,您需要配置您的应用程序以使用 Redis 数据库,例如: + +``` +Host: redis +``` + +就是这样. 现在可以在您的测试框架中使用 Redis. + +您还可以使用[Docker Hub](https://hub.docker.com/_/redis)上可用的任何其他 Docker 映像. 例如,要使用 Redis 2.8,服务将变为`redis:2.8` . + +## Use Redis with the Shell executor[](#use-redis-with-the-shell-executor "Permalink") + +Redis 也可以在手动配置的服务器上使用,该服务器与 Shell 执行程序一起使用 GitLab Runner. + +在您的构建机器中安装 Redis 服务器: + +``` +sudo apt-get install redis-server +``` + +验证您可以使用`gitlab-runner`用户连接到服务器: + +``` +# Try connecting the Redis server +sudo -u gitlab-runner -H redis-cli + +# Quit the session +127.0.0.1:6379> quit +``` + +最后,将您的应用程序配置为使用数据库,例如: + +``` +Host: localhost +``` + +## Example project[](#example-project "Permalink") + +为了方便起见,我们使用公共可[共享的](../runners/README.html)运行程序在[GitLab.com](https://gitlab.com)上运行了[示例 Redis 项目](https://gitlab.com/gitlab-examples/redis) . + +想要破解吗? 只需对其进行分叉,提交并推送您的更改. 稍后,公共跑步者将选择更改并开始工作. \ No newline at end of file diff --git a/_book/docs/274.md b/_book/docs/274.md new file mode 100644 index 0000000000000000000000000000000000000000..4fd99cdea4fcd3d15007dc8ba14e373593e5ea04 --- /dev/null +++ b/_book/docs/274.md @@ -0,0 +1,40 @@ +# Troubleshooting CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/troubleshooting.html](https://docs.gitlab.com/ee/ci/troubleshooting.html) + +* [Merge request pipeline widget](#merge-request-pipeline-widget) + * [“Checking pipeline status”](#checking-pipeline-status) +* [Merge request ability to merge widget](#merge-request-ability-to-merge-widget) + * [“A CI/CD pipeline must run and be successful before merge”](#a-cicd-pipeline-must-run-and-be-successful-before-merge) + +# Troubleshooting CI/CD[](#troubleshooting-cicd "Permalink") + +## Merge request pipeline widget[](#merge-request-pipeline-widget "Permalink") + +合并请求管道小部件在"合并请求"中显示有关管道状态的信息. [在合并小部件](#merge-request-ability-to-merge-widget)的[合并请求功能](#merge-request-ability-to-merge-widget)上方显示. + +根据管道的状态,可以显示几条消息. + +### “Checking pipeline status”[](#checking-pipeline-status "Permalink") + +This message is shown when the merge request has no pipeline associated with the latest commit yet and [Pipelines must succeed](../user/project/merge_requests/merge_when_pipeline_succeeds.html#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds) is turned on. This might be because: + +* GitLab 尚未完成创建管道. +* 您正在使用外部 CI 服务,但 GitLab 尚未收到该服务的回音. +* 您没有在项目中使用 CI / CD 管道. + +创建管道后,该消息将更新为管道状态. + +注意:当前,如果您删除合并请求的最新管道,则将显示此消息,而不是有意义的错误消息. 这是一个已知问题,应尽快解决. + +## Merge request ability to merge widget[](#merge-request-ability-to-merge-widget "Permalink") + +合并请求状态窗口小部件显示" **合并"**按钮以及合并请求是否准备就绪. 如果合并请求无法合并,则会显示原因. + +如果管道仍在运行,则将" **合并"**按钮替换为" **管道成功后合并"**按钮. + +如果[**合并火车**](merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)被启用,按钮要么**加入到合并列车**或**添加到合并火车时管道成功** . + +### “A CI/CD pipeline must run and be successful before merge”[](#a-cicd-pipeline-must-run-and-be-successful-before-merge "Permalink") + +如果在项目中启用了" [管道必须成功"](../user/project/merge_requests/merge_when_pipeline_succeeds.html#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds)设置,并且管道尚未成功运行,则会显示此消息. 如果尚未创建管道,或者正在等待外部 CI 服务,则这也适用. 如果您的项目不使用管道,则应禁用**管道必须成功**才能接受合并请求. \ No newline at end of file diff --git a/_book/docs/275.md b/_book/docs/275.md new file mode 100644 index 0000000000000000000000000000000000000000..ca98781ccc53d11ca2fe0b4aad258ea0065ab15b --- /dev/null +++ b/_book/docs/275.md @@ -0,0 +1,120 @@ +# GitLab Package Registry + +> 原文:[https://docs.gitlab.com/ee/user/packages/](https://docs.gitlab.com/ee/user/packages/) + +* [View packages](#view-packages) +* [Use GitLab CI/CD to build packages](#use-gitlab-cicd-to-build-packages) +* [Download a package](#download-a-package) +* [Delete a package](#delete-a-package) +* [Disable the Package Registry](#disable-the-package-registry) +* [Package workflows](#package-workflows) +* [Suggested contributions](#suggested-contributions) + +# GitLab Package Registry[](#gitlab-package-registry "Permalink") + +借助 GitLab 软件包注册表,您可以将 GitLab 用作各种常见软件包管理器的私有或公共存储库. 您可以构建和发布程序包,这些程序包可以很容易地作为下游项目中的依赖项使用. + +GitLab 充当以下内容的存储库: + +| 软件库 | Description | 在 GitLab 版本中可用 | +| --- | --- | --- | +| [Container Registry](container_registry/index.html) | GitLab 容器注册表使 GitLab 中的每个项目都有自己的空间来存储[Docker](https://www.docker.com/)映像. | 8.8+ | +| [Dependency Proxy](dependency_proxy/index.html) | GitLab 依赖代理为经常使用的上游映像/软件包设置了本地代理. | 11.11+ | +| [Conan Repository](conan_repository/index.html) | GitLab 柯南存储库使 GitLab 中的每个项目都有自己的空间来存储[柯南](https://conan.io/)软件包. | 12.6+ | +| [Maven Repository](maven_repository/index.html) | GitLab Maven 存储库使 GitLab 中的每个项目都有自己的空间来存储[Maven](https://maven.apache.org/)软件包. | 11.3+ | +| [NPM Registry](npm_registry/index.html) | GitLab NPM 注册表使 GitLab 中的每个项目都有自己的空间来存储[NPM](https://s0www0npmjs0com.icopy.site/)软件包. | 11.7+ | +| [NuGet Repository](nuget_repository/index.html) | GitLab NuGet 存储库将使 GitLab 中的每个项目都有自己的空间来存储[NuGet](https://www.nuget.org/)软件包. | 12.8+ | +| [PyPi Repository](pypi_repository/index.html) | GitLab PyPi 存储库将使 GitLab 中的每个项目都有自己的空间来存储[PyPi](https://s0pypi0org.icopy.site/)软件包. | 12.10+ | +| [Go Proxy](go_proxy/index.html) | GitLab 的 Go 代理使 GitLab 中的每个项目都可以通过[Go 代理协议](https://proxy.golang.org/)获取. | 13.1+ | +| [Composer Repository](composer_repository/index.html) | GitLab Composer 存储库将使 GitLab 中的每个项目都有自己的空间来存储[Composer](https://s0getcomposer0org.icopy.site/)软件包. | 13.2+ | + +## View packages[](#view-packages "Permalink") + +您可以查看项目或组的软件包. + +1. 转到项目或组. +2. 去 **程序包和注册表>程序包注册表** . + +您可以在此页面上搜索,排序和过滤软件包. + +有关如何创建和上传软件包的信息,请查看您的软件包类型的 GitLab 文档. + +## Use GitLab CI/CD to build packages[](#use-gitlab-cicd-to-build-packages "Permalink") + +您可以使用[GitLab CI / CD](./../../ci/README.html)来构建软件包. 对于 Maven 和 NPM 软件包以及 Composer 依赖项,可以使用`CI_JOB_TOKEN`向 GitLab 进行身份验证. + +CI / CD 模板,你可以用它来上手,在[此回购](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates) . + +了解有关[使用 CI / CD 构建 Maven 软件包](maven_repository/index.html#creating-maven-packages-with-gitlab-cicd)和[NPM 软件包的更多信息](npm_registry/index.html#publishing-a-package-with-cicd) . + +如果使用 CI / CD 构建软件包,则在查看软件包详细信息时会显示扩展的活动信息: + +[![Package CI/CD activity](img/5d1d35707b32fd37e1e218e8b1df1771.png)](img/package_activity_v12_10.png) + +您可以查看哪个管道发布了程序包,以及触发该程序包的提交和用户. + +## Download a package[](#download-a-package "Permalink") + +要下载软件包: + +1. 去 **程序包和注册表>程序包注册表** . +2. 单击您要下载的软件包的名称. +3. 在" **活动"**部分中,单击要下载的程序包的名称. + +## Delete a package[](#delete-a-package "Permalink") + +在程序包注册表中发布程序包后,您将无法对其进行编辑. 相反,您必须删除并重新创建它. + +* 您无法从组视图中删除软件包. 您必须改为从项目视图中删除它们. 有关详细信息,请参[见此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/227714) . +* 您必须具有适当的[权限](../permissions.html) . + +您可以使用[API](../../api/packages.html#delete-a-project-package)或 UI 删除软件包. + +要在用户界面中删除程序包: + +1. 去 **程序包和注册表>程序包注册表** . +2. 查找您要删除的程序包的名称. +3. Click **Delete**. + +该软件包将被永久删除. + +## Disable the Package Registry[](#disable-the-package-registry "Permalink") + +程序包注册表自动启用. + +如果您使用的是 GitLab 的自我管理实例,则管理员可以删除菜单项, **软件包和注册表** ,位于 GitLab 侧边栏. 有关更多信息,请参阅[管理文档](../../administration/packages/index.html) . + +您还可以专门删除项目的 Package Registry: + +1. 在您的项目中,转到 **设置>常规** . +2. 展开" **可见性","项目功能","权限"**部分,并禁用" **软件包"**功能. +3. Click **Save changes**. + +的 **Packages&Registries> Package Registry**条目已从侧栏中删除. + +## Package workflows[](#package-workflows "Permalink") + +了解如何使用 GitLab 软件包注册表来构建自己的自定义软件包工作流程. + +* [使用项目作为程序包注册表](./workflows/project_registry.html)将所有[程序包](./workflows/project_registry.html)发布到一个项目. +* 从一个[monorepo 项目](./workflows/monorepo.html)发布多个不同的软件包. + +## Suggested contributions[](#suggested-contributions "Permalink") + +考虑为 GitLab 做贡献. 此[开发文档](../../development/packages.html)将指导您完成该过程. 或者查看社区的其他成员如何添加对[PHP](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17417)或[Terraform 的](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834)支持. + +| Format | 用例 | +| --- | --- | +| [Cargo](https://gitlab.com/gitlab-org/gitlab/-/issues/33060) | Cargo 是 Rust 的包裹经理. 构建,发布和共享 Rust 包 | +| [Chef](https://gitlab.com/gitlab-org/gitlab/-/issues/36889) | 使用 Chef 的配置管理,利用存储库管理器的所有优点. | +| [CocoaPods](https://gitlab.com/gitlab-org/gitlab/-/issues/36890) | 使用 Xcode 和 CocoaPods 加快开发速度. | +| [Conda](https://gitlab.com/gitlab-org/gitlab/-/issues/36891) | 安全和私有的本地 Conda 存储库. | +| [CRAN](https://gitlab.com/gitlab-org/gitlab/-/issues/36892) | 部署和解析 R 语言的 CRAN 软件包. | +| [Debian](https://gitlab.com/gitlab-org/gitlab/-/issues/5835) | 托管和设置 Debian 软件包. | +| [Opkg](https://gitlab.com/gitlab-org/gitlab/-/issues/36894) | 使用 Opkg 存储库优化 OpenWrt 的工作. | +| [P2](https://gitlab.com/gitlab-org/gitlab/-/issues/36895) | 将所有 Eclipse 插件托管在自己的 GitLab P2 存储库中. | +| [Puppet](https://gitlab.com/gitlab-org/gitlab/-/issues/36897) | 配置管理通过 Puppet 存储库满足存储库管理. | +| [RPM](https://gitlab.com/gitlab-org/gitlab/-/issues/5932) | 直接从 GitLab 分发 RPM. | +| [RubyGems](https://gitlab.com/gitlab-org/gitlab/-/issues/803) | 使用 GitLab 托管您自己的宝石. | +| [SBT](https://gitlab.com/gitlab-org/gitlab/-/issues/36898) | 运行 SBT 构建时,解析来自 SBT 存储库的依赖性并将构建输出部署到 SBT 存储库. | +| [Vagrant](https://gitlab.com/gitlab-org/gitlab/-/issues/36899) | 将您的 Vagrant 盒子安全地托管在本地存储库中. | \ No newline at end of file diff --git a/_book/docs/276.md b/_book/docs/276.md new file mode 100644 index 0000000000000000000000000000000000000000..ba7f9fdeee2ab01f3af0b21f4dad444d9568cda2 --- /dev/null +++ b/_book/docs/276.md @@ -0,0 +1,580 @@ +# GitLab Container Registry + +> 原文:[https://docs.gitlab.com/ee/user/packages/container_registry/](https://docs.gitlab.com/ee/user/packages/container_registry/) + +* [Enable the Container Registry for your project](#enable-the-container-registry-for-your-project) +* [Control Container Registry from within GitLab](#control-container-registry-from-within-gitlab) + * [Control Container Registry for your project](#control-container-registry-for-your-project) + * [Control Container Registry for your group](#control-container-registry-for-your-group) + * [Image Repository details page](#image-repository-details-page) +* [Use images from GitLab Container Registry](#use-images-from-gitlab-container-registry) +* [Authenticating to the GitLab Container Registry](#authenticating-to-the-gitlab-container-registry) +* [Build and push images from your local machine](#build-and-push-images-from-your-local-machine) +* [Build and push images using GitLab CI/CD](#build-and-push-images-using-gitlab-cicd) + * [Authenticating to the Container Registry with GitLab CI/CD](#authenticating-to-the-container-registry-with-gitlab-cicd) + * [Container Registry examples with GitLab CI/CD](#container-registry-examples-with-gitlab-cicd) + * [Using a Docker-in-Docker image from your Container Registry](#using-a-docker-in-docker-image-from-your-container-registry) +* [Delete images](#delete-images) + * [Delete images from within GitLab](#delete-images-from-within-gitlab) + * [Delete images using the API](#delete-images-using-the-api) + * [Delete images using GitLab CI/CD](#delete-images-using-gitlab-cicd) + * [Delete images by using a cleanup policy](#delete-images-by-using-a-cleanup-policy) +* [Cleanup policy](#cleanup-policy) + * [Managing project cleanup policy through the UI](#managing-project-cleanup-policy-through-the-ui) + * [Troubleshooting cleanup policies](#troubleshooting-cleanup-policies) + * [Managing project cleanup policy through the API](#managing-project-cleanup-policy-through-the-api) + * [Use with external container registries](#use-with-external-container-registries) + * [Regex pattern examples](#regex-pattern-examples) +* [Use the Container Registry to store Helm Charts](#use-the-container-registry-to-store-helm-charts) +* [Limitations](#limitations) +* [Troubleshooting the GitLab Container Registry](#troubleshooting-the-gitlab-container-registry) + * [Docker connection error](#docker-connection-error) + * [Troubleshoot as a GitLab server admin](#troubleshoot-as-a-gitlab-server-admin) + * [Unable to change path or transfer a project](#unable-to-change-path-or-transfer-a-project) + +# GitLab Container Registry[](#gitlab-container-registry "Permalink") + +版本历史 + +* 在 GitLab 8.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4040) . +* 在 GitLab 8.9 中添加了 Docker Registry manifest `v1`支持,以支持 1.10 之前的 Docker 版本. +* 从 GitLab 8.12 开始,如果您的帐户中启用了 2FA,则需要传递[个人访问令牌(](../../profile/personal_access_tokens.html)而不是密码)才能登录到 GitLab 的 Container Registry. +* 在 GitLab 9.1 中添加了多级图像名称支持. +* 组级容器注册表是在 GitLab 12.10 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/23315) . +* 在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31322)了按图像存储库名称搜索. + +**注意:**本文档是用户指南. 要了解如何在整个 GitLab 实例上启用 GitLab 容器注册表,请访问[管理员文档](../../../administration/packages/container_registry.html) . + +通过将 Docker 容器注册表集成到 GitLab 中,每个项目都可以拥有自己的空间来存储其 Docker 映像. + +您可以在[https://docs.docker.com/registry/introduction/上](https://s0docs0docker0com.icopy.site/registry/introduction/)了解有关 Docker Registry 的更多信息. + +[![Container Registry repositories](img/62073039b38c0dfa370251cfe07ca5e5.png)](img/container_registry_repositories_v13_1.png) + +## Enable the Container Registry for your project[](#enable-the-container-registry-for-your-project "Permalink") + +**警告:**容器注册表遵循项目的可见性设置. 如果项目是公开的,则容器注册表也是如此. + +If you cannot find the **包和注册表>容器注册表** entry under your project’s sidebar, it is not enabled in your GitLab instance. Ask your administrator to enable GitLab Container Registry following the [administration documentation](../../../administration/packages/container_registry.html). + +如果您使用的是 GitLab.com,则默认情况下启用此功能,因此您可以立即开始使用注册表. 当前,作为[存储库大小限制的](../../project/repository/index.html)一部分,GitLab.com 上的 Registry 有一个软的(10GB)大小限制. + +为您的 GitLab 实例启用后,要为您的项目启用 Container Registry: + +1. 转到项目的**"设置">"常规"**页面. +2. 展开" **可见性","项目功能","权限"**部分,并在项目上启用" **容器注册表"**功能. 对于新项目,默认情况下可以启用. 对于现有项目(GitLab 8.8 之前的版本),您必须显式启用它. +3. 按**保存更改**以使更改生效. 现在,您应该能够在侧栏中看到**Packages&Registries> Container Registry**链接. + +## Control Container Registry from within GitLab[](#control-container-registry-from-within-gitlab "Permalink") + +GitLab 提供了一个简单的 Container Registry 管理面板. 该管理面板可用于项目和组. + +### Control Container Registry for your project[](#control-container-registry-for-your-project "Permalink") + +导航到您项目的 **包裹和注册>集装箱注册** . + +[![Container Registry project repositories](img/8a2c3991978374372fe0370f27f4fad4.png)](img/container_registry_repositories_with_quickstart_v13_1.png) + +该视图将: + +* 显示属于该项目的所有图像存储库. +* 允许您按图像存储库的名称过滤. +* 允许您[删除](#delete-images-from-within-gitlab)一个或多个图像存储库. +* 允许您导航到图像存储库详细信息页面. +* 显示具有最常用命令的**快速入门**下拉列表,以登录,构建和推送 +* (可选)如果为该项目启用了[清理策略](#cleanup-policy) ,则将显示横幅. + +### Control Container Registry for your group[](#control-container-registry-for-your-group "Permalink") + +导航到您小组的 **包裹和注册>集装箱注册** . + +[![Container Registry group repositories](img/71c2f22b2aef83c58870637723d6f7ef.png)](img/container_registry_group_repositories_v13_1.png) + +该视图将: + +* Show all the image repositories of the projects that belong to this group. +* 允许[删除](#delete-images-from-within-gitlab)一个或多个图像存储库. +* 允许导航到特定的图像存储库详细信息页面. + +### Image Repository details page[](#image-repository-details-page "Permalink") + +单击任何图像存储库的名称将导航到详细信息. + +[![Container Registry project repository details](img/c3f7298c5f6d1b4dbd0a120ce98b9d06.png)](img/container_registry_repository_details_v13.0.png) + +**注意:**下一页在**组级别容器注册表**和**项目级别容器注册表中**具有相同的功能. + +此视图: + +* 显示所有图像存储库详细信息. +* 显示图像存储库的所有标记. +* 允许您快速复制标签路径(通过单击标签名称附近的剪贴板按钮). +* 允许您[删除一个或多个标签](#delete-images-from-within-gitlab) . + +## Use images from GitLab Container Registry[](#use-images-from-gitlab-container-registry "Permalink") + +要从 GitLab 容器注册表中托管的映像下载并运行容器,请使用`docker run` : + +``` +docker run [options] registry.example.com/group/project/image [arguments] +``` + +有关运行 Docker 容器的更多信息,请访问[Docker 文档](https://s0docs0docker0com.icopy.site/engine/userguide/intro/) . + +## Authenticating to the GitLab Container Registry[](#authenticating-to-the-gitlab-container-registry "Permalink") + +如果访问项目菜单下的**Packages&Registries> Container Registry**链接,则可以看到使用 GitLab 凭据登录到 Container Registry 的明确说明. + +例如,如果注册表的 URL 是`registry.example.com` ,那么您应该能够使用以下命令登录: + +``` +docker login registry.example.com +``` + +**注意:**如果您的帐户中启用了[2 因子身份验证](../../profile/account/two_factor_authentication.html) ,则需要传递[个人访问令牌(](../../profile/personal_access_tokens.html)而不是密码)才能登录到 GitLab 的 Container Registry. + +如果项目是私有项目,则需要提供凭据进行授权. 有两种方法可以做到这一点: + +* 通过使用[个人访问令牌](../../profile/personal_access_tokens.html) . +* 通过使用[部署令牌](../../project/deploy_tokens/index.html) . + +两者所需的最小范围是`read_registry` . + +使用令牌的示例: + +``` +docker login registry.example.com -u -p +``` + +## Build and push images from your local machine[](#build-and-push-images-from-your-local-machine "Permalink") + +建立和发布图像应该是一个简单的过程. 只需确保您将注册表 URL 与 GitLab 上托管的名称空间和项目名称一起使用即可: + +``` +docker build -t registry.example.com/group/project/image . +docker push registry.example.com/group/project/image +``` + +您的图片将按照以下方案命名: + +``` +/// +``` + +GitLab 最多支持三个级别的图像存储库名称. 以下图像标签示例有效: + +``` +registry.example.com/group/project:some-tag +registry.example.com/group/project/image:latest +registry.example.com/group/project/my/image:rc1 +``` + +## Build and push images using GitLab CI/CD[](#build-and-push-images-using-gitlab-cicd "Permalink") + +While you can build and push your images from your local machine, the true power of the Container Registry comes when you combine it with GitLab CI/CD. You can then create workflows and automate any processes that involve testing, building, and eventually deploying your project from the Docker image you created. + +在深入研究细节之前,您应该注意一些事项: + +* 运行任何命令之前,必须[先向容器注册表](#authenticating-to-the-container-registry-with-gitlab-cicd)进行[身份验证](#authenticating-to-the-container-registry-with-gitlab-cicd) . 如果有多个作业依赖于它,则可以在`before_script`执行此操作. +* 使用`docker build --pull`在构建之前获取对基础映像的所有更改,以防缓存过时. 它花费的时间稍长一些,但这意味着如果没有基础映像的安全补丁,您将不会陷入困境. +* 在每次`docker run` docker 之前进行显式`docker pull`都会获取刚刚构建的最新映像. 如果您正在使用多个在本地缓存图像的运行程序,则这一点尤其重要. 在图像标签中使用 Git SHA 使得此操作变得不必要,因为每个作业都是唯一的,并且您永远都不会过时的图像. 但是,如果在依赖项发生更改后重新构建给定的提交,则仍然可能会有陈旧的映像. +* 如果有多个作业同时发生,则您不想直接构建到`latest`标记. + +### Authenticating to the Container Registry with GitLab CI/CD[](#authenticating-to-the-container-registry-with-gitlab-cicd "Permalink") + +通过[GitLab CI / CD](../../../ci/yaml/README.html)向容器注册表进行身份验证的三种方法取决于您项目的可见性. + +适用于所有项目,但更适合公共项目: + +* **使用特殊的`CI_REGISTRY_USER`变量** :为您创建此变量指定的用户,以便推送到连接到您的项目的注册表. 它的密码是使用`CI_REGISTRY_PASSWORD`变量自动设置的. 这使您可以自动构建和部署 Docker 映像,并具有对注册表的读/写访问权限. 这是短暂的,因此仅适用于一项工作. 您可以按原样使用以下示例: + + ``` + docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + ``` + +对于私人和内部项目: + +* **使用个人访问令牌** :如果您的项目是私有的,则可以创建和使用[个人访问令牌](../../profile/personal_access_tokens.html) : + + * 对于读取(拉)访问,范围应为`read_registry` . + * 要进行读/写(拉/推)访问,请使用`api` . + + Replace the `` and `` in the following example: + + ``` + docker login -u -p $CI_REGISTRY + ``` + +* **使用 GitLab 部署令牌** :您可以在私有项目中创建和使用[特殊的部署令牌](../../project/deploy_tokens/index.html#gitlab-deploy-token) . 它提供对注册表的只读(拉)访问. 创建后,您可以使用特殊的环境变量,GitLab CI / CD 将为您填充它们. 您可以按原样使用以下示例: + + ``` + docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY + ``` + +### Container Registry examples with GitLab CI/CD[](#container-registry-examples-with-gitlab-cicd "Permalink") + +如果您在 Runners 上使用 Docker-in-Docker,则`.gitlab-ci.yml`外观应与此类似: + +``` +build: + image: docker:19.03.12 + stage: build + services: + - docker:19.03.12-dind + script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker build -t $CI_REGISTRY/group/project/image:latest . + - docker push $CI_REGISTRY/group/project/image:latest +``` + +您还可以利用[其他变量](../../../ci/variables/README.html)来避免硬编码: + +``` +build: + image: docker:19.03.12 + stage: build + services: + - docker:19.03.12-dind + variables: + IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker build -t $IMAGE_TAG . + - docker push $IMAGE_TAG +``` + +在这里, `$CI_REGISTRY_IMAGE`将解析为与此项目`$CI_REGISTRY_IMAGE`的注册表的地址. 由于`$CI_COMMIT_REF_NAME`解析为分支名称或标记名称,并且您的分支名称可以包含正斜杠(例如,feature / my-feature),因此将`$CI_COMMIT_REF_SLUG`用作图像标记`$CI_COMMIT_REF_SLUG`安全. 这是因为图像标记不能包含正斜杠. 我们还声明了自己的变量`$IMAGE_TAG` ,将两者结合起来可以节省一些在`script`部分键入的内容. + +这是一个更详细的示例,将任务分为 4 个管道阶段,包括两个并行运行的测试. 内部`build`存储在容器注册表中,供后续阶段使用,并在需要时下载映像. 对`master`所做的更改也将被标记为`latest`并使用特定于应用程序的部署脚本进行部署: + +``` +image: docker:19.03.12 +services: + - docker:19.03.12-dind + +stages: + - build + - test + - release + - deploy + +variables: + # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled + DOCKER_HOST: tcp://docker:2376 + DOCKER_TLS_CERTDIR: "/certs" + CONTAINER_TEST_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest + +before_script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + +build: + stage: build + script: + - docker build --pull -t $CONTAINER_TEST_IMAGE . + - docker push $CONTAINER_TEST_IMAGE + +test1: + stage: test + script: + - docker pull $CONTAINER_TEST_IMAGE + - docker run $CONTAINER_TEST_IMAGE /script/to/run/tests + +test2: + stage: test + script: + - docker pull $CONTAINER_TEST_IMAGE + - docker run $CONTAINER_TEST_IMAGE /script/to/run/another/test + +release-image: + stage: release + script: + - docker pull $CONTAINER_TEST_IMAGE + - docker tag $CONTAINER_TEST_IMAGE $CONTAINER_RELEASE_IMAGE + - docker push $CONTAINER_RELEASE_IMAGE + only: + - master + +deploy: + stage: deploy + script: + - ./deploy.sh + only: + - master +``` + +**注意:**此示例显式调用`docker pull` . 如果您希望使用`image:`隐式拉出构建的映像,并使用[Docker](https://docs.gitlab.com/runner/executors/docker.html)或[Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html)执行程序,请确保[`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html)设置为`always` . + +### Using a Docker-in-Docker image from your Container Registry[](#using-a-docker-in-docker-image-from-your-container-registry "Permalink") + +如果要为 Docker-in-Docker 使用自己的 Docker 映像,除了[Docker-in-Docker](../../../ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor)部分中的步骤外,还需要做一些其他事情: + +1. 更新`image`和`service`以指向您的注册表. +2. 添加服务[别名](../../../ci/yaml/README.html#servicesalias) . + +以下是您的`.gitlab-ci.yml`外观示例: + +``` + build: + image: $CI_REGISTRY/group/project/docker:19.03.12 + services: + - name: $CI_REGISTRY/group/project/docker:19.03.12-dind + alias: docker + stage: build + script: + - docker build -t my-docker-image . + - docker run my-docker-image /script/to/run/tests +``` + +如果您忘记设置服务别名,则`docker:19.03.12`映像将找不到`dind`服务,并且将引发类似以下的错误: + +``` +error during connect: Get http://docker:2376/v1.39/info: dial tcp: lookup docker on 192.168.0.1:53: no such host +``` + +## Delete images[](#delete-images "Permalink") + +您可以通过多种方式从 Container Registry 中删除图像. + +**警告:**删除图像是一种破坏性行为,无法撤消. 要还原已删除的图像,必须重建并重新上传它.**注意:**管理员应查看如何[垃圾收集](../../../administration/packages/container_registry.html#container-registry-garbage-collection)删除的图像. + +### Delete images from within GitLab[](#delete-images-from-within-gitlab "Permalink") + +要从 GitLab 中删除图像: + +1. Navigate to your project’s or group’s **包和注册表>容器注册表**. +2. 在" **容器注册表"**页面上,可以通过以下任一方法选择要删除的内容: + + * 通过单击红色删除整个存储库及其包含的所有标签 **垃圾桶**图标. + * 导航到存储库,然后通过单击红色单独或批量删除标签 您要删除的标签旁边的**垃圾桶**图标. +3. 在对话框中,点击**删除标签** . + + [![Container Registry tags](img/c3f7298c5f6d1b4dbd0a120ce98b9d06.png)](img/container_registry_repository_details_v13.0.png) + +### Delete images using the API[](#delete-images-using-the-api "Permalink") + +如果要自动执行删除图像的过程,GitLab 提供了一个 API. 有关更多信息,请参见以下端点: + +* [Delete a Registry repository](../../../api/container_registry.html#delete-registry-repository) +* [Delete an individual Registry repository tag](../../../api/container_registry.html#delete-a-registry-repository-tag) +* [Delete Registry repository tags in bulk](../../../api/container_registry.html#delete-registry-repository-tags-in-bulk) + +### Delete images using GitLab CI/CD[](#delete-images-using-gitlab-cicd "Permalink") + +**警告:** GitLab CI / CD 没有提供删除图像的内置方法,但是本示例使用了名为[reg](https://github.com/genuinetools/reg)的第三方工具,该工具与 GitLab Registry API 进行通信. 您应对自己的行为负责. 有关此工具的帮助,请参见[reg 的发行队列](https://github.com/genuinetools/reg/issues) . + +以下示例定义了两个阶段: `build`和`clean` . `build_image`作业将为分支构建 Docker 映像,而`delete_image`作业将其删除. `reg`可执行文件已下载并用于删除与`$CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG` [环境变量](../../../ci/variables/predefined_variables.html)匹配的映像. + +要使用此示例,请更改`IMAGE_TAG`变量以符合您的需求: + +``` +stages: + - build + - clean + +build_image: + image: docker:19.03.12 + stage: build + services: + - docker:19.03.12-dind + variables: + IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker build -t $IMAGE_TAG . + - docker push $IMAGE_TAG + only: + - branches + except: + - master + +delete_image: + image: docker:19.03.12 + stage: clean + services: + - docker:19.03.12-dind + variables: + IMAGE_TAG: $CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG + REG_SHA256: ade837fc5224acd8c34732bf54a94f579b47851cc6a7fd5899a98386b782e228 + REG_VERSION: 0.16.1 + before_script: + - apk add --no-cache curl + - curl --fail --show-error --location "https://github.com/genuinetools/reg/releases/download/v$REG_VERSION/reg-linux-amd64" --output /usr/local/bin/reg + - echo "$REG_SHA256 /usr/local/bin/reg" | sha256sum -c - + - chmod a+x /usr/local/bin/reg + script: + - /usr/local/bin/reg rm -d --auth-url $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $IMAGE_TAG + only: + - branches + except: + - master +``` + +**提示:**您可以从[发布页面](https://github.com/genuinetools/reg/releases)下载最新的`reg`版本,然后通过更改`delete_image`作业中定义的`REG_SHA256`和`REG_VERSION`变量来更新代码示例. + +### Delete images by using a cleanup policy[](#delete-images-by-using-a-cleanup-policy "Permalink") + +您可以创建每个项目的[清理策略,](#cleanup-policy)以确保定期从 Container Registry 中删除较旧的标记和图像. + +## Cleanup policy[](#cleanup-policy "Permalink") + +版本历史 + +* 在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/15398) . +* 在 GitLab 13.2 中从"过期策略" [重命名](https://gitlab.com/gitlab-org/gitlab/-/issues/218737)为"清理策略". + +对于特定项目,如果要删除不再需要的标签,则可以创建清除策略. 应用该策略时,将删除与正则表达式模式匹配的标记. 底层和图像仍然保留. + +要删除不再与任何标签关联的基础层和图像,实例管理员可以通过`-m`开关使用[垃圾回收](../../../administration/packages/container_registry.html#removing-unused-layers-not-referenced-by-manifests) . + +**注意:**对于 GitLab.com,清理策略不适用于将该功能部署到生产之前(2020 年 2 月)创建的项目. 计划在 GitLab.com 上[为](https://gitlab.com/gitlab-org/gitlab/-/issues/196124)现有项目提供支持. 对于自我管理的实例,管理员可以在[GitLab 应用程序设置中](../../../api/settings.html#change-application-settings)通过将`container_expiration_policies_enable_historic_entries`设置为 true 来启用清除策略. 注意[涉及](./index.html#use-with-external-container-registries)的固有[风险](./index.html#use-with-external-container-registries) . + +清理策略算法首先从列表中收集给定存储库的所有标记,然后进行从标记中排除标记的过程,直到仅保留要删除的标记为止: + +1. 在列表中收集给定存储库的所有标记. +2. 排除名为标签`latest`从列表中. +3. 评估`name_regex` ,从列表中排除不匹配的名称. +4. 排除所有没有清单的标签(不是选项的一部分). +5. 按`created_date`其余标签. +6. 从列表中排除基于`keep_n`值的 N 个标签(要保留的标签数). +7. 从列表中排除比`older_than`值(清除间隔)更新的标签. +8. 从列表中排除与`name_regex_keep`值匹配的所有标签(要保留的图像). +9. 最后,列表中的其余标签将从 Container Registry 中删除. + +### Managing project cleanup policy through the UI[](#managing-project-cleanup-policy-through-the-ui "Permalink") + +要管理项目清理策略,请导航至 **设置> CI / CD>容器注册表标记清除策略** . + +用户界面允许您配置以下内容: + +* **清理策略:**启用或禁用清理策略. +* **清除间隔:**标签可以删除多长时间. +* **清理计划:**检查标签的 cron 作业应运行的频率. +* **要保留的标签数量:**每个图像*始终*保留多少个标签. +* **名称与该正则表达式模式匹配的 Docker 标签将过期:**用于确定应清除哪些标签的正则表达式. 要使所有标签都合格,请使用默认值`.*` . +* **名称与该正则表达式模式匹配的 Docker 标签将被保留:**用于确定应保留哪些标签的正则表达式. 要保留所有标签,请使用默认值`.*` . + +#### Troubleshooting cleanup policies[](#troubleshooting-cleanup-policies "Permalink") + +如果看到以下消息: + +"更新清理策略时出了点问题." + +检查正则表达式模式以确保它们有效. + +您可以使用[Rubular](https://rubular.com/)检查您的正则表达式. 查看一些常见的[regex 模式示例](#regex-pattern-examples) . + +### Managing project cleanup policy through the API[](#managing-project-cleanup-policy-through-the-api "Permalink") + +您可以使用 GitLab API 设置,更新和禁用清理策略. + +Examples: + +* 选择所有标签,每个图像至少保留 1 个标签,清理超过 14 天的所有标签,每月运行一次,使用名称`master`保留所有图像并启用该策略: + + ``` + curl --request PUT --header 'Content-Type: application/json;charset=UTF-8' --header "PRIVATE-TOKEN: " --data-binary '{"container_expiration_policy_attributes":{"cadence":"1month","enabled":true,"keep_n":1,"older_than":"14d","name_regex":"","name_regex_delete":".*","name_regex_keep":".*-master"}}' 'https://gitlab.example.com/api/v4/projects/2' + ``` + +有关更多详细信息,请参见 API 文档: [编辑项目](../../../api/projects.html#edit-project) . + +### Use with external container registries[](#use-with-external-container-registries "Permalink") + +使用[外部容器注册表时](./../../../administration/packages/container_registry.html#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint) ,在项目上运行清除策略可能会带来性能风险. 如果项目要运行的策略将删除大量标签(成千上万个),则运行该策略的 GitLab 后台作业可能会备份或完全失败. 如果您确信要清除的标签数量很少,建议仅对在 GitLab 12.8 之前创建的项目启用容器清理策略. + +### Regex pattern examples[](#regex-pattern-examples "Permalink") + +清理策略使用正则表达式模式来确定应在 UI 和 API 中保留或删除哪些标签. + +以下是您可能要使用的正则表达式模式的示例: + +* 匹配所有标签: + + ``` + .* + ``` + +* 匹配以`v`开头的标签: + + ``` + v.+ + ``` + +* 匹配包含`master`标签: + + ``` + master + ``` + +* 匹配以`v`开头,包含`master`或包含`release`标签: + + ``` + (?:v.+|master|release) + ``` + +## Use the Container Registry to store Helm Charts[](#use-the-container-registry-to-store-helm-charts "Permalink") + +随着[Helm v3](https://helm.sh/docs/topics/registries/)的发布,您可以使用 Container Registry 存储 Helm Charts. 但是,由于 Docker 传递和存储元数据的方式,GitLab 无法解析此数据并达到性能标准. [本史诗](https://gitlab.com/groups/gitlab-org/-/epics/2313)更新了 Container Registry 的体系结构以支持 Helm Charts. + +您可以[在此处](https://gitlab.com/gitlab-org/gitlab/-/issues/38047#note_298842890)阅读有关上述挑战的更多信息. + +## Limitations[](#limitations "Permalink") + +* 推送图像后,不支持移动或重命名现有 Container Registry 存储库,因为图像已签名,并且签名包含存储库名称. 要使用 Container Registry 移动或重命名存储库,必须删除所有现有映像. +* 在 GitLab 12.10 之前,清理策略不会删除使用与`latest`标签相同的图像 ID 的任何标签. + +## Troubleshooting the GitLab Container Registry[](#troubleshooting-the-gitlab-container-registry "Permalink") + +### Docker connection error[](#docker-connection-error "Permalink") + +当组,项目或分支名​​称中包含特殊字符时,可能会发生 Docker 连接错误. 特殊字符可以包括: + +* 领先的下划线 +* 尾随连字符/破折号 + +为了解决这个问题,您可以[更改组路径](../../group/index.html#changing-a-groups-path) , [更改项目路径](../../project/settings/index.html#renaming-a-repository)或更改分支名称. + +### Troubleshoot as a GitLab server admin[](#troubleshoot-as-a-gitlab-server-admin "Permalink") + +大多数情况下,对 GitLab 容器注册表进行故障排除需要管理员对 GitLab 服务器的访问. + +[Read how to troubleshoot the Container Registry](../../../administration/packages/container_registry.html#troubleshooting). + +### Unable to change path or transfer a project[](#unable-to-change-path-or-transfer-a-project "Permalink") + +如果您尝试更改项目的路径或将项目转移到新的名称空间,则可能会收到以下错误之一: + +* "由于容器的注册表中存在标签,因此无法传输项目." +* "无法移动名称空间,因为至少一个项目在容器注册表中具有标签." + +当项目在容器注册表中有图像时,会发生此问题. 必须先删除或移动这些图像,然后才能更改路径或传输项目. + +以下过程使用这些样本项目名称: + +* 对于当前项目: `example.gitlab.com/org/build/sample_project/cr:v2.9.1` : `example.gitlab.com/org/build/sample_project/cr:v2.9.1` +* 对于新项目: `example.gitlab.com/new_org/build/new_sample_project/cr:v2.9.1` : `example.gitlab.com/new_org/build/new_sample_project/cr:v2.9.1` + +使用您自己的 URL 完成以下步骤: + +1. 将 Docker 映像下载到您的计算机上: + + ``` + docker login example.gitlab.com + docker pull example.gitlab.com/org/build/sample_project/cr:v2.9.1 + ``` + +2. 重命名图像以匹配新的项目名称: + + ``` + docker tag example.gitlab.com/org/build/sample_project/cr:v2.9.1 example.gitlab.com/new_org/build/new_sample_project/cr:v2.9.1 + ``` + +3. 使用[UI](#delete-images)或[API](../../../api/packages.html#delete-a-project-package)删除两个项目中的图像. 图像排队和删除时可能会有延迟. +4. 通过转到**"设置">"常规"**并展开" **高级"**来更改路径或传输项目. +5. 恢复图像: + + ``` + docker push example.gitlab.com/new_org/build/new_sample_project/cr:v2.9.1 + ``` + +有关详细信息,请关注[此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/18383) . \ No newline at end of file diff --git a/_book/docs/277.md b/_book/docs/277.md new file mode 100644 index 0000000000000000000000000000000000000000..b5ae883df925814fcad23d3b1a9b450dd9f200f9 --- /dev/null +++ b/_book/docs/277.md @@ -0,0 +1,71 @@ +# Dependency Proxy + +> 原文:[https://docs.gitlab.com/ee/user/packages/dependency_proxy/](https://docs.gitlab.com/ee/user/packages/dependency_proxy/) + +* [Supported dependency proxies](#supported-dependency-proxies) +* [Using the Docker dependency proxy](#using-the-docker-dependency-proxy) +* [Clearing the cache](#clearing-the-cache) +* [Limitations](#limitations) + +# Dependency Proxy[](#dependency-proxy-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7934) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.11. + +**注意:**这是用户指南. 为了使用依赖代理,管理员必须首先对其进行[配置](../../../administration/packages/dependency_proxy.html) . + +对于许多组织而言,希望为经常使用的上游映像/程序包提供本地代理. 在 CI / CD 的情况下,代理负责接收请求并从注册表中返回上游映像,并充当下拉缓存. + +依赖项代理在组级别可用. 要访问它,请导航到组的**Packages&Registries> Dependency Proxy** . + +[![Dependency Proxy group page](img/64d10619e1633359be63480f18d60b90.png)](img/group_dependency_proxy.png) + +## Supported dependency proxies[](#supported-dependency-proxies "Permalink") + +***注意:**有关代理即将添加的列表,请访问[指导页面](https://about.gitlab.com/direction/package/dependency_proxy/#top-vision-items) .* + +支持以下依赖代理. + +| 依赖代理 | GitLab 版本 | +| --- | --- | +| Docker | 11.11+ | + +## Using the Docker dependency proxy[](#using-the-docker-dependency-proxy "Permalink") + +借助 Docker 依赖项代理,您可以将 GitLab 用作 Docker 映像的源. 要将 Docker 映像放入依赖代理中: + +1. 在" **软件包和** `gitlab.com/groupname/dependency_proxy/containers` **>"依赖代理"**下的组页面上找到代理 URL,例如`gitlab.com/groupname/dependency_proxy/containers` . +2. 触发 GitLab 提取所需的 Docker 映像(例如`alpine:latest`或`linuxserver/nextcloud:latest` ),然后使用以下方法之一将其存储在代理存储中: + + * 手动拉 Docker 镜像: + + ``` + docker pull gitlab.com/groupname/dependency_proxy/containers/alpine:latest + ``` + + * 从`Dockerfile` : + + ``` + FROM gitlab.com/groupname/dependency_proxy/containers/alpine:latest + ``` + + * In [`.gitlab-ci.yml`](../../../ci/yaml/README.html#image): + + ``` + image: gitlab.com/groupname/dependency_proxy/containers/alpine:latest + ``` + +然后,GitLab 将从 Docker Hub 中提取 Docker 映像,并将 blob 缓存在 GitLab 服务器上. 下次您提取同一映像时,它将从 Docker Hub 获取有关该映像的最新信息,但将为 GitLab 提供的现有 Blob 服务. + +斑点被永久保存,并且可以存储多少数据没有硬性限制. + +## Clearing the cache[](#clearing-the-cache "Permalink") + +可以使用 GitLab API 清除给定组的依赖项代理缓存,以获取可能不再需要的图像 Blob 占用的磁盘空间. 有关更多详细信息,请参见[依赖项代理 API 文档](../../../api/dependency_proxy.html) . + +## Limitations[](#limitations "Permalink") + +适用以下限制: + +* 仅支持公共组(尚不支持身份验证). +* 仅支持 Docker Hub. +* 此功能需要 Docker Hub 可用. \ No newline at end of file diff --git a/_book/docs/278.md b/_book/docs/278.md new file mode 100644 index 0000000000000000000000000000000000000000..1502d9f5f4dc663c0e470800c582595f5a497c0d --- /dev/null +++ b/_book/docs/278.md @@ -0,0 +1,126 @@ +# GitLab Composer Repository + +> 原文:[https://docs.gitlab.com/ee/user/packages/composer_repository/](https://docs.gitlab.com/ee/user/packages/composer_repository/) + +* [Enabling the Composer Repository](#enabling-the-composer-repository) +* [Getting started](#getting-started) + * [Creating a package project](#creating-a-package-project) + * [Publishing the package](#publishing-the-package) + * [Installing a package](#installing-a-package) + +# GitLab Composer Repository[](#gitlab-composer-repository-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15886) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + +使用 GitLab Composer 信息库,每个项目都可以有自己的空间来存储[Composer](https://s0getcomposer0org.icopy.site/)软件包. + +## Enabling the Composer Repository[](#enabling-the-composer-repository "Permalink") + +**注意:**仅当您的 GitLab 管理员[启用了对 Package Registry 的支持时,](../../../administration/packages/index.html)此选项才可用. + +启用 Composer 信息库后,默认情况下它将可用于所有新项目. 要为现有项目启用它,或者要禁用它: + +1. 导航到项目的**"设置">"常规">"可见性,项目功能,权限"** . +2. 找到"软件包"功能并启用或禁用它. +3. 单击**保存更改**以使更改生效. + +然后,您应该能够在左侧栏中看到" **程序包和注册表"**部分. + +## Getting started[](#getting-started "Permalink") + +本节将介绍如何创建一个新的示例 Composer 软件包进行发布. 这是测试**GitLab Composer 注册表**的快速入门. + +您将需要最新版本的[Composer](https://s0getcomposer0org.icopy.site/) . + +### Creating a package project[](#creating-a-package-project "Permalink") + +了解如何创建完整的 Composer 项目不在本指南的范围内,但是您可以创建一个小程序包来测试注册表. 首先创建一个名为`my-composer-package`的新目录: + +``` +mkdir my-composer-package && cd my-composer-package +``` + +在此目录中创建一个新的`composer.json`文件以设置基本项目: + +``` +touch composer.json +``` + +在`composer.json`内部,添加以下代码: + +``` +{ "name": "/composer-test", "type": "library", "license": "GPL-3.0-only", "version": "1.0.0" } +``` + +将``替换为唯一的命名空间,例如您的 GitLab 用户名或组名. + +在创建了基本的包结构之后,我们需要在 Git 中对其进行标记并将其推送到存储库中. + +``` +git init +git add composer.json +git commit -m 'Composer package test' +git tag v1.0.0 +git add origin git@gitlab.com:/.git +git push origin v1.0.0 +``` + +### Publishing the package[](#publishing-the-package "Permalink") + +现在,我们的项目基础已经完成,我们可以发布该软件包了. 为此,您将需要以下内容: + +* 个人访问令牌. 您可以生成范围设置为`api`的[个人访问令牌](../../../user/profile/personal_access_tokens.html) ,以进行存储库身份验证. +* 您的项目 ID,可以在项目的主页上找到. + +要发布托管在 GitLab 上的软件包,我们需要使用`curl`这样的工具对 GitLab 软件包 API 进行`POST` : + +``` +curl --data tag= 'https://__token__:@gitlab.com/api/v4/projects//packages/composer' +``` + +Where: + +* ``是您的个人访问令牌. +* ``是您的项目 ID. +* ``是您要发布的版本的 Git 标记名称. 在此示例中,它应为`v1.0.0` . 请注意,除了使用`tag=`您还可以使用`branch=`来发布分支. + +如果上面的命令成功执行,您现在应该可以在项目页面的" **程序包和注册表"**部分下看到该程序包. + +### Installing a package[](#installing-a-package "Permalink") + +要安装您的软件包,您需要: + +* 个人访问令牌. 您可以生成范围设置为`api`的[个人访问令牌](../../../user/profile/personal_access_tokens.html) ,以进行存储库身份验证. +* 您的组 ID,可在项目组的主页上找到. + +将 GitLab Composer 软件包存储库以及要安装的软件包名称和版本添加到现有项目的`composer.json`文件中,如下所示: + +``` +{ ... "repositories": [ { "type": "composer", "url": "https://gitlab.com/api/v4/group//-/packages/composer/packages.json" } ], "require": { ... "": "" }, ... } +``` + +Where: + +* ``是在项目的"组"页面下找到的组 ID. +* ``是软件包的`composer.json`文件中定义的软件包名称. +* ``是您的软件包版本(在此示例中为`1.0.0` ). + +您还需要使用 GitLab 凭据创建一个`auth.json`文件: + +``` +{ "http-basic": { "gitlab.com": { "username": "___token___", "password": "" } } } +``` + +Where: + +* ``是您的个人访问令牌. + +配置了`composer.json`和`auth.json`文件后,您可以通过运行`composer`安装软件包: + +``` +composer update +``` + +如果成功,您应该能够看到指示软件包已成功安装的输出. + +**重要提示:**请确保不要将`auth.json`文件提交到您的存储库. 要从 CI 作业安装软件包,请考虑将[`composer config`](https://s0getcomposer0org.icopy.site/doc/articles/handling-private-packages-with-satis.md)工具与您的个人访问令牌一起使用,并将其存储在[GitLab CI / CD 环境变量](../../../ci/variables/README.html)或[Hashicorp Vault 中](../../../ci/examples/authenticating-with-hashicorp-vault/index.html) . \ No newline at end of file diff --git a/_book/docs/279.md b/_book/docs/279.md new file mode 100644 index 0000000000000000000000000000000000000000..d776d6b24c05554ec8746a8d7c78090e8c29b8dc --- /dev/null +++ b/_book/docs/279.md @@ -0,0 +1,290 @@ +# GitLab Conan Repository + +> 原文:[https://docs.gitlab.com/ee/user/packages/conan_repository/](https://docs.gitlab.com/ee/user/packages/conan_repository/) + +* [Enabling the Conan Repository](#enabling-the-conan-repository) +* [Getting started](#getting-started) + * [Installing Conan](#installing-conan) + * [Installing CMake](#installing-cmake) + * [Creating a project](#creating-a-project) + * [Building a package](#building-a-package) +* [Adding the GitLab Package Registry as a Conan remote](#adding-the-gitlab-package-registry-as-a-conan-remote) +* [Authenticating to the GitLab Conan Repository](#authenticating-to-the-gitlab-conan-repository) + * [Adding a Conan user to the GitLab remote](#adding-a-conan-user-to-the-gitlab-remote) + * [Setting a default remote to your project (optional)](#setting-a-default-remote-to-your-project-optional) +* [Uploading a package](#uploading-a-package) + * [Package recipe naming convention](#package-recipe-naming-convention) +* [Installing a package](#installing-a-package) +* [Removing a package](#removing-a-package) +* [Searching the GitLab Package Registry for Conan packages](#searching-the-gitlab-package-registry-for-conan-packages) +* [Fetching Conan package information from the GitLab Package Registry](#fetching-conan-package-information-from-the-gitlab-package-registry) +* [List of supported CLI commands](#list-of-supported-cli-commands) +* [Using GitLab CI with Conan packages](#using-gitlab-ci-with-conan-packages) + +# GitLab Conan Repository[](#gitlab-conan-repository-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8248) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.6. + +有了 GitLab 柯南存储库,每个项目都可以有自己的空间来存储柯南软件包. + +[![GitLab Conan Repository](img/5bf127e31dfc7f61e3134780f75114ff.png)](img/conan_package_view.png) + +## Enabling the Conan Repository[](#enabling-the-conan-repository "Permalink") + +**注意:**仅当您的 GitLab 管理员[启用了对 Conan Repository 的支持时,](../../../administration/packages/index.html)此选项才可用. + +启用柯南存储库后,默认情况下它将可用于所有新项目. 要为现有项目启用它,或者要禁用它: + +1. 导航到项目的**"设置">"常规">"可见性,项目功能,权限"** . +2. 找到"软件包"功能并启用或禁用它. +3. 单击**保存更改**以使更改生效. + +然后,您应该能够在左侧栏中看到" **程序包和注册表"**部分. + +## Getting started[](#getting-started "Permalink") + +本节将介绍如何安装 Conan 以及为 C / C ++项目构建软件包. 如果您不熟悉柯南,这是一个快速入门. 如果您已经在使用 Conan 并且了解如何构建自己的软件包,请继续[下一节](#adding-the-gitlab-package-registry-as-a-conan-remote) . + +### Installing Conan[](#installing-conan "Permalink") + +按照[conan.io](https://conan.io/downloads.html)上的说明将 Conan 软件包管理器下载到本地开发环境. + +安装完成后,通过运行以下命令验证您可以在终端中使用 Conan + +``` +conan --version +``` + +您应该在输出中看到柯南版本: + +``` +Conan version 1.20.5 +``` + +### Installing CMake[](#installing-cmake "Permalink") + +使用 C ++和 Conan 进行开发时,编译器有多种选择. 本教程将逐步介绍如何使用 cmake 编译器. 在您的终端中,运行命令 + +``` +cmake --version +``` + +您应该会在输出中看到 cmake 版本. 如果看到其他内容,则可能必须安装 cmake. + +在 Mac 上,您可以通过运行`brew install cmake`来使用[自制软件](https://brew.sh/) `brew install cmake` . 否则,请按照[cmake.org 中](https://cmake.org/install/)针对您的操作系统的说明进行操作. + +### Creating a project[](#creating-a-project "Permalink") + +了解创建有效且可编译的 C ++项目所需的内容不在本指南的范围之内,但是,如果您是 C ++的新手,并且想尝试 GitLab 软件包注册表,那么 Conan.io 会提供一个很棒的[Hello World 入门项目](https://github.com/conan-io/hello)可以克隆以开始使用. + +如果您没有自己的 C ++项目,请克隆该存储库,并将其用于本教程的其余部分. + +### Building a package[](#building-a-package "Permalink") + +在终端中,导航到项目的根文件夹. 通过运行`conan new`并为其提供程序包名称和版本来生成新配方: + +``` +conan new Hello/0.1 -t +``` + +接下来,您将通过运行提供 Conan 用户和频道的`conan create`来为该配方创建一个程序包: + +``` +conan create . my-org+my-group+my-project/beta +``` + +**注意:**当前的[命名限制](#package-recipe-naming-convention)要求您将`user`值[命名](#package-recipe-naming-convention)为项目在 GitLab 上的`+`分隔路径. + +上面的示例将创建一个属于该项目的软件包: `https://gitlab.com/my-org/my-group/my-project` : `https://gitlab.com/my-org/my-group/my-project` ,其通道为`beta` . + +这两个示例命令将使用配方`Hello/0.1@my-org+my-group+my-project/beta`生成最终软件包. + +有关创建和管理软件包的更多高级详细信息,请参阅[Conan docs](https://docs.conan.io/en/latest/creating_packages.html) . + +现在,您可以将软件包上传到 GitLab 注册表了. 首先,您需要将 GitLab 设置为远程,然后需要为该远程添加一个 Conan 用户以验证您的请求. + +## Adding the GitLab Package Registry as a Conan remote[](#adding-the-gitlab-package-registry-as-a-conan-remote "Permalink") + +Add a new remote to your Conan configuration: + +``` +conan remote add gitlab https://gitlab.example.com/api/v4/packages/conan +``` + +一旦设置了遥控器,您就可以在运行 Conan 命令时使用遥控器,方法是在命令末尾添加`--remote=gitlab` . + +例如: + +``` +conan search Hello* --all --remote=gitlab +``` + +## Authenticating to the GitLab Conan Repository[](#authenticating-to-the-gitlab-conan-repository "Permalink") + +您将需要一个个人访问令牌或部署令牌. + +对于存储库身份验证: + +* 您可以将范围设置为`api`来生成[个人访问令牌](../../../user/profile/personal_access_tokens.html) . +* 您可以生成[令牌部署](./../../project/deploy_tokens/index.html)与范围设置为`read_package_registry` , `write_package_registry` ,或两者兼而有之. + +### Adding a Conan user to the GitLab remote[](#adding-a-conan-user-to-the-gitlab-remote "Permalink") + +一旦有了个人访问令牌并[设置了 Conan remote](#adding-the-gitlab-package-registry-as-a-conan-remote) ,就可以将令牌与远程关联,因此您不必将它们显式添加到您运行的每个 Conan 命令中: + +``` +conan user -r gitlab -p +``` + +**注意:**如果您使用`gitlab`以外的名称来命名远程,则应在此命令中使用您的远程名称,而不是`gitlab` . + +从现在开始,当您使用`--remote=gitlab`运行命令时,您的用户名和密码将自动包含在请求中. + +**注意:**个人访问令牌不会随时存储在本地. Conan 使用 JWT,因此当您运行此命令时,Conan 将使用您的令牌从 GitLab 请求一个过期的令牌. JWT 确实会定期失效,因此您需要在这种情况下重新输入个人访问令牌. + +或者,您可以在任何给定命令中显式包括您的凭据. 例如: + +``` +CONAN_LOGIN_USERNAME= CONAN_PASSWORD= conan upload Hello/0.1@my-group+my-project/beta --all --remote=gitlab +``` + +### Setting a default remote to your project (optional)[](#setting-a-default-remote-to-your-project-optional "Permalink") + +如果您希望柯南始终使用 GitLab 作为软件包的注册表,则可以告诉柯南始终为给定的软件包配方引用 GitLab 远程: + +``` +conan remote add_ref Hello/0.1@my-group+my-project/beta gitlab +``` + +**注意:**软件包配方中确实包含该版本,因此为`Hello/0.1@user/channel`设置默认远程将不适用于`Hello/0.2@user/channel` . 此功能最适合需要从 GitLab 注册表使用或安装软件包而无需指定远程服务器的情况. + +本文档中其余的示例命令假定您已将具有凭据的 Conan 用户添加到`gitlab`远程,并且不包括显式凭据或远程选项,但是请注意,可以在不添加任何命令的情况下运行任何命令.用户或默认遥控器: + +``` +`CONAN_LOGIN_USERNAME= CONAN_PASSWORD= --remote=gitlab +``` + +## Uploading a package[](#uploading-a-package "Permalink") + +首先,您需要在[本地创建 Conan 软件包](https://docs.conan.io/en/latest/creating_packages/getting_started.html) . 为了使用 GitLab 软件包注册表,必须遵循特定的[命名约定](#package-recipe-naming-convention) . + +通过选择`api` [范围,](../../../user/profile/personal_access_tokens.html#limiting-scopes-of-a-personal-access-token)确保在 GitLab 上创建了一个项目,并且所使用的个人访问令牌具有对容器注册表进行写访问的正确权限. + +您可以使用`conan upload`命令将软件包上传到 GitLab 软件包注册表: + +``` +conan upload Hello/0.1@my-group+my-project/beta --all +``` + +### Package recipe naming convention[](#package-recipe-naming-convention "Permalink") + +标准柯南食谱约定看起来像`package_name/version@user/channel` . + +**配方用户必须是`+`分隔的项目路径** . 程序包名称可以是任何名称,但最好使用项目名称,除非由于命名冲突而无法使用. 例如: + +| Project | Package | Supported | +| --- | --- | --- | +| `foo/bar` | `my-package/1.0.0@foo+bar/stable` | Yes | +| `foo/bar-baz/buz` | `my-package/1.0.0@foo+bar-baz+buz/stable` | Yes | +| `gitlab-org/gitlab-ce` | `my-package/1.0.0@gitlab-org+gitlab-ce/stable` | Yes | +| `gitlab-org/gitlab-ce` | `my-package/1.0.0@foo/stable` | No | + +**注意:**将来的迭代将扩展对[项目和组级别](https://gitlab.com/gitlab-org/gitlab/-/issues/11679)远程服务器的支持,这将允许更灵活的命名约定. + +## Installing a package[](#installing-a-package "Permalink") + +通常使用`conanfile.txt`文件将 Conan 软件包作为依赖项安装. + +在要作为依赖项安装 Conan 软件包的项目中,打开`conanfile.txt`或在项目的根目录中创建一个名为`conanfile.txt`的空文件. + +将柯南食谱添加到文件的`[requires]`部分: + +``` + [requires] + Hello/0.1@my-group+my-project/beta + + [generators] + cmake +``` + +接下来,从您的项目的根目录创建一个构建目录并导航到它: + +``` +mkdir build && cd build +``` + +现在,您可以安装`conanfile.txt`列出的依赖`conanfile.txt` : + +``` +conan install .. +``` + +**注意:**如果您要安装在本教程中刚刚创建的软件包,则不会发生太多事情,因为该软件包已在本地计算机上存在. + +## Removing a package[](#removing-a-package "Permalink") + +有两种方法可以从 GitLab 软件包注册表中删除 Conan 软件包. + +* **在命令行中使用 Conan 客户端:** + + ``` + conan remove Hello/0.2@user/channel --remote=gitlab + ``` + + 您需要在此命令中明确包含遥控器,否则该程序包将仅从本地系统缓存中删除. + + **注意:**此命令将从软件包注册表中删除所有配方和二进制软件包文件. +* **GitLab 项目界面** :在项目页面的软件包视图中,您可以通过单击红色垃圾图标来删除软件包. + +## Searching the GitLab Package Registry for Conan packages[](#searching-the-gitlab-package-registry-for-conan-packages "Permalink") + +`conan search`命令可以按完整或部分软件包名称或精确配方进行搜索. + +要使用部分名称进行搜索,请使用通配符`*` ,该通配符应放在搜索的末尾(例如, `my-packa*` ): + +``` +conan search Hello --all --remote=gitlab +conan search He* --all --remote=gitlab +conan search Hello/0.1@my-group+my-project/beta --all --remote=gitlab +``` + +搜索范围将包括您有权访问的所有项目,包括私人项目以及所有公共项目. + +## Fetching Conan package information from the GitLab Package Registry[](#fetching-conan-package-information-from-the-gitlab-package-registry "Permalink") + +`conan info`命令将返回有关给定软件包的信息: + +``` +conan info Hello/0.1@my-group+my-project/beta +``` + +## List of supported CLI commands[](#list-of-supported-cli-commands "Permalink") + +GitLab Conan 存储库支持以下 Conan CLI 命令: + +* `conan upload` :将您的配方和包文件上载到 GitLab 包注册表. +* `conan install` :从 GitLab 软件包注册表中安装`conanfile.txt`软件包,包括使用`conanfile.txt`文件. +* `conan search`: Search the GitLab Package Registry for public packages, and private packages you have permission to view. +* `conan info` :从 GitLab 软件包注册表中查看有关给定软件包的信息. +* `conan remove` :从 GitLab 软件包注册表中删除该软件包. + +## Using GitLab CI with Conan packages[](#using-gitlab-ci-with-conan-packages "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11678) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7. + +要在[GitLab CI / CD 中](./../../../ci/README.html)使用柯南命令,可以在命令中使用`CI_JOB_TOKEN`代替个人访问令牌. + +在`.gitlab-ci.yml`文件中为每个柯南命令提供`CONAN_LOGIN_USERNAME`和`CONAN_PASSWORD`是最简单的: + +``` +image: conanio/gcc7 + +create_package: + stage: deploy + script: + - conan remote add gitlab https://gitlab.example.com/api/v4/packages/conan + - conan create . my-group+my-project/beta + - CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload Hello/0.1@root+ci-conan/beta1 --all --remote=gitlab +``` + +您可以在[Conan 文档中](https://docs.conan.io/en/latest/howtos/run_conan_in_docker.html#available-docker-images)找到其他柯南图像用作 CI 文件的基础. \ No newline at end of file diff --git a/_book/docs/280.md b/_book/docs/280.md new file mode 100644 index 0000000000000000000000000000000000000000..2fbb9a627598724b6e505ea3ceb2888d3c427908 --- /dev/null +++ b/_book/docs/280.md @@ -0,0 +1,784 @@ +# GitLab Maven Repository + +> 原文:[https://docs.gitlab.com/ee/user/packages/maven_repository/](https://docs.gitlab.com/ee/user/packages/maven_repository/) + +* [Enabling the Maven Repository](#enabling-the-maven-repository) +* [Getting Started with Maven](#getting-started-with-maven) + * [Installing Maven](#installing-maven) + * [Creating a project](#creating-a-project) +* [Getting started with Gradle](#getting-started-with-gradle) + * [Installing Gradle](#installing-gradle) + * [Creating a project in Gradle](#creating-a-project-in-gradle) +* [Adding the GitLab Package Registry as a Maven remote](#adding-the-gitlab-package-registry-as-a-maven-remote) + * [Authenticating with a personal access token](#authenticating-with-a-personal-access-token) + * [Authenticating with a personal access token in Maven](#authenticating-with-a-personal-access-token-in-maven) + * [Authenticating with a personal access token in Gradle](#authenticating-with-a-personal-access-token-in-gradle) + * [Authenticating with a CI job token](#authenticating-with-a-ci-job-token) + * [Authenticating with a CI job token in Maven](#authenticating-with-a-ci-job-token-in-maven) + * [Authenticating with a CI job token in Gradle](#authenticating-with-a-ci-job-token-in-gradle) + * [Authenticating with a deploy token](#authenticating-with-a-deploy-token) + * [Authenticating with a deploy token in Maven](#authenticating-with-a-deploy-token-in-maven) + * [Authenticating with a deploy token in Gradle](#authenticating-with-a-deploy-token-in-gradle) +* [Configuring your project to use the GitLab Maven repository URL](#configuring-your-project-to-use-the-gitlab-maven-repository-url) + * [Project level Maven endpoint](#project-level-maven-endpoint) + * [Group level Maven endpoint](#group-level-maven-endpoint) + * [Instance level Maven endpoint](#instance-level-maven-endpoint) +* [Uploading packages](#uploading-packages) + * [Upload using Maven](#upload-using-maven) + * [Upload using Gradle](#upload-using-gradle) +* [Installing a package](#installing-a-package) + * [Install using Maven with `mvn install`](#install-using-maven-with-mvn-install) + * [Install with `mvn dependency:get`](#install-with-mvn-dependencyget) + * [Install using Gradle](#install-using-gradle) +* [Removing a package](#removing-a-package) +* [Creating Maven packages with GitLab CI/CD](#creating-maven-packages-with-gitlab-cicd) + * [Creating Maven packages with GitLab CI/CD using Maven](#creating-maven-packages-with-gitlab-cicd-using-maven) + * [Creating Maven packages with GitLab CI/CD using Gradle](#creating-maven-packages-with-gitlab-cicd-using-gradle) + * [Version validation](#version-validation) +* [Troubleshooting](#troubleshooting) + * [Useful Maven command line options](#useful-maven-command-line-options) + * [Verifying your Maven settings](#verifying-your-maven-settings) + +# GitLab Maven Repository[](#gitlab-maven-repository-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5811) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.3. + +使用 GitLab [Maven](https://maven.apache.org)存储库,每个项目都可以有自己的空间来存储其 Maven 工件. + +[![GitLab Maven Repository](img/243c1a9fc7dab75d6576c27470e73bf0.png)](img/maven_package_view_v12_6.png) + +## Enabling the Maven Repository[](#enabling-the-maven-repository "Permalink") + +**注意:**仅当您的 GitLab 管理员[启用了对 Maven 存储库的支持时,](../../../administration/packages/index.html)此选项才可用. + +启用"软件包"功能后,默认情况下,Maven 存储库将可用于所有新项目. 要为现有项目启用它,或者要禁用它: + +1. 导航到项目的**"设置">"常规">"可见性,项目功能,权限"** . +2. 找到"软件包"功能并启用或禁用它. +3. 单击**保存更改**以使更改生效. + +然后,您应该能够在左侧栏中看到" **程序包和注册表"**部分. 接下来,您必须配置您的项目以使用 GitLab Maven 存储库进行授权. + +## Getting Started with Maven[](#getting-started-with-maven "Permalink") + +本节将介绍安装 Maven 和构建软件包. 如果您不熟悉构建 Maven 软件包,这是一个快速入门. 如果您已经在使用 Maven 并且了解如何构建自己的软件包,请转到[下一节](#adding-the-gitlab-package-registry-as-a-maven-remote) . + +Maven 仓库也可以与 Gradle 一起很好地工作. 如果要设置 Gradle 项目,请继续[使用 Gradle 入门](#getting-started-with-gradle) . + +### Installing Maven[](#installing-maven "Permalink") + +所需的最低版本为: + +* Java 11.0.5 以上 +* Maven 3.6+ + +按照[maven.apache.org](https://maven.apache.org/install.html)上的说明下载并安装适用于您本地开发环境的 Maven. 安装完成后,通过运行以下命令验证您可以在终端中使用 Maven: + +``` +mvn --version +``` + +您应该在输出中看到类似于以下内容的内容: + +``` +Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-04T20:00:29+01:00) +Maven home: /Users//apache-maven-3.6.1 +Java version: 12.0.2, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-12.0.2.jdk/Contents/Home +Default locale: en_GB, platform encoding: UTF-8 +OS name: "mac os x", version: "10.15.2", arch: "x86_64", family: "mac" +``` + +### Creating a project[](#creating-a-project "Permalink") + +了解如何创建完整的 Java 项目不在本指南的范围内,但是您可以按照以下步骤创建一个新项目,该项目可以发布到 GitLab Package Registry. + +首先打开终端并创建一个目录,您要将目录存储在环境中. 从目录内部,您可以运行以下 Maven 命令来初始化新程序包: + +``` +mvn archetype:generate -DgroupId=com.mycompany.mydepartment -DartifactId=my-project -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false +``` + +参数如下: + +* `DgroupId` :标识您的包裹的唯一字符串. 您应该遵循[Maven 命名约定](https://maven.apache.org/guides/mini/guide-naming-conventions.html) . +* `DartifactId` :JAR 的名称,附加在`DgroupId`的末尾. +* `DarchetypeArtifactId` :用于创建项目初始结构的原型. +* `DinteractiveMode` :使用批处理模式(可选)创建项目. + +运行该命令后,您应该看到以下消息,表明您的项目已成功设置: + +``` +... +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 3.429 s +[INFO] Finished at: 2020-01-28T11:47:04Z +[INFO] ------------------------------------------------------------------------ +``` + +您应该看到一个新目录,在该目录中运行与`DartifactId`参数匹配的命令(在这种情况下,它应该是`my-project` ). + +## Getting started with Gradle[](#getting-started-with-gradle "Permalink") + +本节将介绍如何安装 Gradle 和初始化 Java 项目. 如果您不熟悉 Gradle,这是一个快速入门. 如果您已经在使用 Gradle 并且了解如何构建自己的软件包,请转到[下一部分](#adding-the-gitlab-package-registry-as-a-maven-remote) . + +### Installing Gradle[](#installing-gradle "Permalink") + +仅当您要创建新的 Gradle 项目时才需要安装. 按照[gradle.org](https://s0gradle0org.icopy.site/install/)上的说明为您的本地开发环境下载并安装 Gradle. + +通过运行以下命令验证您可以在终端中使用 Gradle: + +``` +gradle -version +``` + +如果要使用现有的 Gradle 项目,则不需要安装. 只需在项目目录中执行`gradlew` (在 Linux 上)或`gradlew.bat` (在 Windows 上)即可. + +You should see something imilar to the below printed in the output: + +``` +------------------------------------------------------------ +Gradle 6.0.1 +------------------------------------------------------------ + +Build time: 2019-11-18 20:25:01 UTC +Revision: fad121066a68c4701acd362daf4287a7c309a0f5 + +Kotlin: 1.3.50 +Groovy: 2.5.8 +Ant: Apache Ant(TM) version 1.10.7 compiled on September 1 2019 +JVM: 11.0.5 (Oracle Corporation 11.0.5+10) +OS: Windows 10 10.0 amd64 +``` + +### Creating a project in Gradle[](#creating-a-project-in-gradle "Permalink") + +了解如何在 Gradle 中创建完整的 Java 项目不在本指南的范围内,但是您可以按照以下步骤创建一个可以发布到 GitLab Package Registry 的新项目. + +首先打开终端并创建一个目录,您要将目录存储在环境中. 从目录内部,您可以运行以下 Maven 命令来初始化新程序包: + +``` +gradle init +``` + +输出应为 + +``` +Select type of project to generate: + 1: basic + 2: application + 3: library + 4: Gradle plugin +Enter selection (default: basic) [1..4] +``` + +输入`3`创建一个新的 Library 项目. 输出应为: + +``` +Select implementation language: + 1: C++ + 2: Groovy + 3: Java + 4: Kotlin + 5: Scala + 6: Swift +``` + +输入`3`创建一个新的 Java 库项目. 输出应为: + +``` +Select build script DSL: + 1: Groovy + 2: Kotlin +Enter selection (default: Groovy) [1..2] +``` + +选择`1`创建一个新的 Java 库项目,该项目将在 Groovy DSL 中进行描述. 输出应为: + +``` +Select test framework: + 1: JUnit 4 + 2: TestNG + 3: Spock + 4: JUnit Jupiter +``` + +选择`1`以使用 JUnit 4 测试库初始化项目. 输出应为: + +``` +Project name (default: test): +``` + +输入项目名称或按 Enter 键以使用目录名称作为项目名称. + +## Adding the GitLab Package Registry as a Maven remote[](#adding-the-gitlab-package-registry-as-a-maven-remote "Permalink") + +下一步是将 GitLab 软件包注册表添加为 Maven 遥控器. 如果项目是私有的,或者您想将 Maven 工件上传到 GitLab,则也需要提供凭据进行授权. 仅对[个人访问令牌](#authenticating-with-a-personal-access-token) , [CI 作业令牌](#authenticating-with-a-ci-job-token)和[部署令牌提供支持](../../project/deploy_tokens/index.html) . 常规的用户名/密码凭据不起作用. + +### Authenticating with a personal access token[](#authenticating-with-a-personal-access-token "Permalink") + +要使用[个人访问令牌进行](../../profile/personal_access_tokens.html)身份验证,请在创建[令牌](../../profile/personal_access_tokens.html)时将范围设置为`api` ,并将其添加到您的 Maven 或 Gradle 配置文件中. + +#### Authenticating with a personal access token in Maven[](#authenticating-with-a-personal-access-token-in-maven "Permalink") + +将相应的部分添加到[`settings.xml`](https://maven.apache.org/settings.html)文件中: + +``` + + + + gitlab-maven + + + + Private-Token + REPLACE_WITH_YOUR_PERSONAL_ACCESS_TOKEN + + + + + + +``` + +#### Authenticating with a personal access token in Gradle[](#authenticating-with-a-personal-access-token-in-gradle "Permalink") + +创建具有以下内容的文件`~/.gradle/gradle.properties` : + +``` +gitLabPrivateToken=REPLACE_WITH_YOUR_PERSONAL_ACCESS_TOKEN +``` + +在您的[`build.gradle`](https://s0docs0gradle0org.icopy.site/current/userguide/tutorial_using_tasks.html)文件中添加一个存储库部分: + +``` +repositories { + maven { + url "https:///api/v4/groups//-/packages/maven" + name "GitLab" + credentials(HttpHeaderCredentials) { + name = 'Private-Token' + value = gitLabPrivateToken + } + authentication { + header(HttpHeaderAuthentication) + } + } +} +``` + +You should now be able to upload Maven artifacts to your project. + +### Authenticating with a CI job token[](#authenticating-with-a-ci-job-token "Permalink") + +如果您使用的是 GitLab CI / CD,则可以使用 CI 作业令牌代替个人访问令牌. + +#### Authenticating with a CI job token in Maven[](#authenticating-with-a-ci-job-token-in-maven "Permalink") + +要使用 CI 作业令牌进行身份验证,请将相应部分添加到[`settings.xml`](https://maven.apache.org/settings.html)文件中: + +``` + + + + gitlab-maven + + + + Job-Token + ${env.CI_JOB_TOKEN} + + + + + + +``` + +您可以阅读有关[如何使用 GitLab CI / CD 创建 Maven 软件包的](#creating-maven-packages-with-gitlab-cicd)更多信息. + +#### Authenticating with a CI job token in Gradle[](#authenticating-with-a-ci-job-token-in-gradle "Permalink") + +要使用 CI 作业令牌进行身份验证,请在[`build.gradle`](https://s0docs0gradle0org.icopy.site/current/userguide/tutorial_using_tasks.html)文件中添加一个存储库部分: + +``` +repositories { + maven { + url "https:///api/v4/groups//-/packages/maven" + name "GitLab" + credentials(HttpHeaderCredentials) { + name = 'Job-Token' + value = '${CI_JOB_TOKEN}' + } + authentication { + header(HttpHeaderAuthentication) + } + } +} +``` + +### Authenticating with a deploy token[](#authenticating-with-a-deploy-token "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0. + +要使用[部署令牌进行](./../../project/deploy_tokens/index.html)身份验证,请在创建[令牌](./../../project/deploy_tokens/index.html)时将范围设置为`api` ,然后将其添加到您的 Maven 或 Gradle 配置文件中. + +#### Authenticating with a deploy token in Maven[](#authenticating-with-a-deploy-token-in-maven "Permalink") + +将相应的部分添加到[`settings.xml`](https://maven.apache.org/settings.html)文件中: + +``` + + + + gitlab-maven + + + + Deploy-Token + REPLACE_WITH_YOUR_DEPLOY_TOKEN + + + + + + +``` + +#### Authenticating with a deploy token in Gradle[](#authenticating-with-a-deploy-token-in-gradle "Permalink") + +要使用部署令牌进行身份验证,请将存储库部分添加到[`build.gradle`](https://s0docs0gradle0org.icopy.site/current/userguide/tutorial_using_tasks.html)文件中: + +``` +repositories { + maven { + url "https:///api/v4/groups//-/packages/maven" + name "GitLab" + credentials(HttpHeaderCredentials) { + name = 'Deploy-Token' + value = '' + } + authentication { + header(HttpHeaderAuthentication) + } + } +} +``` + +## Configuring your project to use the GitLab Maven repository URL[](#configuring-your-project-to-use-the-gitlab-maven-repository-url "Permalink") + +要从 GitLab 下载和上传软件包,您需要在`pom.xml`文件中的" `repository` and `distributionManagement`部分. 如果您按照上面的步骤操作,则需要将以下信息添加到`my-project/pom.xml`文件中. + +根据您的工作流程和所拥有的 Maven 软件包的数量,可以通过 3 种方式配置项目以将 GitLab 端点用于 Maven 软件包: + +* **项目级别** :当您有几个不在同一 GitLab 组中的 Maven 软件包时,此选项很有用. +* **组级别** :当您在同一个 GitLab 组中有多个 Maven 软件包时,此选项很有用. +* **实例级别** :当您在不同的 GitLab 组下或它们自己的名称空间上有许多 Maven 软件包时很有用. + +**注意:**在所有情况下,都需要一个项目特定的 URL 才能在`distributionManagement`部分中上载软件包. + +### Project level Maven endpoint[](#project-level-maven-endpoint "Permalink") + +下面的示例显示了`pom.xml`的相关`repository`部分在 Maven 中的样子: + +``` + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + +``` + +Gradle 中的相应部分如下所示: + +``` +repositories { + maven { + url "https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven" + name "GitLab" + } +} +``` + +该`id`必须与您[在`settings.xml`定义](#adding-the-gitlab-package-registry-as-a-maven-remote)的`id`相同. + +将`PROJECT_ID`替换为可以在项目主页上找到的项目 ID. + +如果您具有自行管理的 GitLab 安装, `gitlab.com`使用您的域名替换`gitlab.com` . + +**注意:**要检索工件,可以使用项目的[URL 编码](../../../api/README.html#namespaced-path-encoding)路径(例如`group/project` )或项目的 ID(例如`42` ). 但是,只能使用项目的 ID 进行上传. + +### Group level Maven endpoint[](#group-level-maven-endpoint "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8798) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7. + +如果您依赖于许多软件包,则在`repository`部分中为每个软件包添加唯一的 URL 可能效率不高. 相反,您可以将组级别端点用于存储在一个 GitLab 组中的所有 Maven 软件包. 只有您有权访问的软件包才可以下载. + +组级别端点可与任何程序包名称一起使用,这意味着与[实例级别端点](#instance-level-maven-endpoint)相比,您具有更大的命名灵活性. 但是,GitLab 不能保证软件包名称在组中的唯一性. 您可以有两个具有相同软件包名称和软件包版本的项目. 因此,GitLab 将服务于较新的那个. + +下面的示例显示`pom.xml`的相关`repository`部分的外观. 您仍需要一个特定于项目的 URL 来在`distributionManagement`部分中上传软件包: + +``` + + + gitlab-maven + https://gitlab.com/api/v4/groups/GROUP_ID/-/packages/maven + + + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + +``` + +对于 Gradle,相应的存储库部分如下所示: + +``` +repositories { + maven { + url "https://gitlab.com/api/v4/groups/GROUP_ID/-/packages/maven" + name "GitLab" + } +} +``` + +该`id`必须与您[在`settings.xml`定义](#adding-the-gitlab-package-registry-as-a-maven-remote)的`id`相同. + +在您的项目主页上可以找到您的组名,将`my-group`替换为您的组名,将`PROJECT_ID`替换为您的项目 ID. + +如果您具有自行管理的 GitLab 安装, `gitlab.com`使用您的域名替换`gitlab.com` . + +**注意:**对于检索工件,您可以使用组的[URL 编码](../../../api/README.html#namespaced-path-encoding)路径(例如`group/subgroup` )或组的 ID(例如`12` ). + +### Instance level Maven endpoint[](#instance-level-maven-endpoint "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8274) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7. + +如果您依赖于许多软件包,则在`repository`部分中为每个软件包添加唯一的 URL 可能效率不高. 相反,您可以对存储在 GitLab 中的所有 maven 程序包使用实例级别端点,并且可以访问您有权访问的程序包. + +请注意, **只有与项目路径相同的软件包才**通过实例级别端点公开. + +| Project | Package | 实例级别端点可用 | +| --- | --- | --- | +| `foo/bar` | `foo/bar/1.0-SNAPSHOT` | Yes | +| `gitlab-org/gitlab` | `foo/bar/1.0-SNAPSHOT` | No | +| `gitlab-org/gitlab` | `gitlab-org/gitlab/1.0-SNAPSHOT` | Yes | + +下面的示例显示`pom.xml`的相关`repository`部分的外观. 您仍需要一个特定于项目的 URL 来在`distributionManagement`部分中上传软件包: + +``` + + + gitlab-maven + https://gitlab.com/api/v4/packages/maven + + + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + +``` + +Gradle 中相应的存储库部分如下所示: + +``` +repositories { + maven { + url "https://gitlab.com/api/v4/packages/maven" + name "GitLab" + } +} +``` + +该`id`必须与您[在`settings.xml`定义](#adding-the-gitlab-package-registry-as-a-maven-remote)的`id`相同. + +将`PROJECT_ID`替换为可以在项目主页上找到的项目 ID. + +如果您具有自行管理的 GitLab 安装, `gitlab.com`使用您的域名替换`gitlab.com` . + +**Note:** For retrieving artifacts, you can use either the [URL encoded](../../../api/README.html#namespaced-path-encoding) path of the project (e.g., `group%2Fproject`) or the project’s ID (e.g., `42`). However, only the project’s ID can be used for uploading. + +## Uploading packages[](#uploading-packages "Permalink") + +一旦设置了[远程和身份验证](#adding-the-gitlab-package-registry-as-a-maven-remote)并[配置了项目](#configuring-your-project-to-use-the-gitlab-maven-repository-url) ,请测试以从[您的项目](#configuring-your-project-to-use-the-gitlab-maven-repository-url)中上传 Maven 工件. + +### Upload using Maven[](#upload-using-maven "Permalink") + +``` +mvn deploy +``` + +如果部署成功,您应该再次看到构建成功消息: + +``` +... +[INFO] BUILD SUCCESS +... +``` + +您还应该看到上传已上传到正确的注册表: + +``` +Uploading to gitlab-maven: https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.jar +``` + +### Upload using Gradle[](#upload-using-gradle "Permalink") + +将 Gradle 插件[`maven-publish`](https://s0docs0gradle0org.icopy.site/current/userguide/publishing_maven.html)添加到插件部分: + +``` +plugins { + id 'java' + id 'maven-publish' +} +``` + +添加`publishing`部分: + +``` +publishing { + publications { + library(MavenPublication) { + from components.java + } + } + repositories { + maven { + url "https://gitlab.com/api/v4/projects//packages/maven" + credentials(HttpHeaderCredentials) { + name = "Private-Token" + value = gitLabPrivateToken // the variable resides in ~/.gradle/gradle.properties + } + authentication { + header(HttpHeaderAuthentication) + } + } + } +} +``` + +将`PROJECT_ID`替换为可以在项目主页上找到的项目 ID. + +运行发布任务: + +``` +gradle publish +``` + +然后,您可以导航到项目的**Packages&Registries**页面,并查看上载的工件,甚至删除它们. + +## Installing a package[](#installing-a-package "Permalink") + +从 GitLab 程序包注册表安装程序包要求您如上所述设置[远程和身份验证](#adding-the-gitlab-package-registry-as-a-maven-remote) . 一旦完成,就有两种安装软件包的方法. + +### Install using Maven with `mvn install`[](#install-using-maven-with-mvn-install "Permalink") + +手动将依赖项添加到您的项目`pom.xml`文件中. 要添加上面创建的示例,XML 如下所示: + +``` + + com.mycompany.mydepartment + my-project + 1.0-SNAPSHOT + +``` + +然后,在您的项目中,运行以下命令: + +``` +mvn install +``` + +如果一切设置正确,您应该会看到从 GitLab 软件包注册表下载的依赖项: + +``` +Downloading from gitlab-maven: http://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.pom +``` + +#### Install with `mvn dependency:get`[](#install-with-mvn-dependencyget "Permalink") + +安装软件包的第二种方法是直接使用 Maven 命令. 在您的项目目录中,运行: + +``` +mvn dependency:get -Dartifact=com.nickkipling.app:nick-test-app:1.1-SNAPSHOT +``` + +您应该看到相同的下载消息,确认从 GitLab 软件包注册表中检索了该项目. + +**提示:** XML 块和 Maven 命令都可以从"软件包详细信息"页面中方便地复制和粘贴,从而可以快速简便地进行安装. + +### Install using Gradle[](#install-using-gradle "Permalink") + +添加[依赖](https://s0docs0gradle0org.icopy.site/current/userguide/declaring_dependencies.html)于依赖部分的 build.gradle: + +``` +dependencies { + implementation 'com.mycompany.mydepartment:my-project:1.0-SNAPSHOT' +} +``` + +## Removing a package[](#removing-a-package "Permalink") + +在项目页面的软件包视图中,您可以通过单击红色垃圾图标或单击软件包详细信息页面上的**删除**按钮来**删除**软件包. + +## Creating Maven packages with GitLab CI/CD[](#creating-maven-packages-with-gitlab-cicd "Permalink") + +一旦您的存储库配置为使用 GitLab Maven 存储库,就可以配置 GitLab CI / CD 来自动构建新软件包. + +### Creating Maven packages with GitLab CI/CD using Maven[](#creating-maven-packages-with-gitlab-cicd-using-maven "Permalink") + +下面的示例显示了每次更新`master`分支时如何创建新程序包: + +1. 创建一个`ci_settings.xml`文件,它将用作 Maven 的`settings.xml`文件. 添加与您在`pom.xml`文件中定义的 ID 相同的服务器部分. 例如,在我们的例子中是`gitlab-maven` : + + ``` + + + + gitlab-maven + + + + Job-Token + ${env.CI_JOB_TOKEN} + + + + + + + ``` + +2. 确保您的`pom.xml`文件包含以下内容: + + ``` + + + gitlab-maven + https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven + + + + + gitlab-maven + https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven + + + gitlab-maven + https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven + + + ``` + + **提示:**您可以让 Maven 利用 CI 环境变量,也可以硬编码项目的 ID. +3. 将`deploy`作业添加到您的`.gitlab-ci.yml`文件中: + + ``` + deploy: + image: maven:3.3.9-jdk-8 + script: + - 'mvn deploy -s ci_settings.xml' + only: + - master + ``` + +4. 将这些文件推送到您的存储库. + +下次运行`deploy`作业时,它将`ci_settings.xml`复制到用户的本地位置(在这种情况下,用户是`root`用户,因为它在 Docker 容器中运行),并且 Maven 将利用配置的 CI [环境变量](../../../ci/variables/README.html#predefined-environment-variables) . + +### Creating Maven packages with GitLab CI/CD using Gradle[](#creating-maven-packages-with-gitlab-cicd-using-gradle "Permalink") + +下面的示例显示了每次更新`master`分支时如何创建新程序包: + +1. 确保按照["使用 Gradle 中的 CI 作业令牌进行身份](#authenticating-with-a-ci-job-token-in-gradle)验证"中所述使用 Job-Token 身份[验证](#authenticating-with-a-ci-job-token-in-gradle) . + +2. 将`deploy`作业添加到您的`.gitlab-ci.yml`文件中: + + ``` + deploy: + image: gradle:latest + script: + - 'gradle publish' + only: + - master + ``` + +3. 将这些文件推送到您的存储库. + +下次运行`deploy`作业时,它将`ci_settings.xml`复制到用户的本地位置(在这种情况下,用户是`root`用户,因为它在 Docker 容器中运行),并且 Maven 将使用配置的 CI [环境变量](../../../ci/variables/README.html#predefined-environment-variables) . + +### Version validation[](#version-validation "Permalink") + +使用以下正则表达式验证版本字符串. + +``` +\A(\.?[\w\+-]+\.?)+\z +``` + +您可以使用正则表达式,并在[此正则表达式编辑器](https://rubular.com/r/rrLQqUXjfKEoL6)上尝试使用版本字符串. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Useful Maven command line options[](#useful-maven-command-line-options "Permalink") + +有一些[Maven 命令行选项](https://maven.apache.org/ref/current/maven-embedder/cli.html)在使用 GitLab CI / CD 执行任务时可能有用. + +* 文件传输进度会使 CI 日志难以阅读. 选项`-ntp,--no-transfer-progress`已在[3.6.1](https://maven.apache.org/docs/3.6.1/release-notes.html#User_visible_Changes)中添加. 或者,查看`-B,--batch-mode` [或较低级别的日志记录更改.](https://stackoverflow.com/questions/21638697/disable-maven-download-progress-indication) + +* 指定在哪里可以找到 POM 文件( `-f,--file` ): + + ``` + package: + script: + - 'mvn --no-transfer-progress -f helloworld/pom.xml package' + ``` + +* 指定在哪里可以找到用户设置( `-s,--settings` ),而不是[默认位置](https://maven.apache.org/settings.html) . 还有一个`-gs,--global-settings`选项: + + ``` + package: + script: + - 'mvn -s settings/ci.xml package' + ``` + +### Verifying your Maven settings[](#verifying-your-maven-settings "Permalink") + +如果您在 CI 中遇到与`settings.xml`文件有关的问题,则添加其他脚本任务或作业以[验证有效设置](https://maven.apache.org/plugins/maven-help-plugin/effective-settings-mojo.html)可能会很有用. + +帮助插件还可以提供[系统属性](https://maven.apache.org/plugins/maven-help-plugin/system-mojo.html) ,包括环境变量: + +``` +mvn-settings: + script: + - 'mvn help:effective-settings' + +package: + script: + - 'mvn help:system' + - 'mvn package' +``` \ No newline at end of file diff --git a/_book/docs/281.md b/_book/docs/281.md new file mode 100644 index 0000000000000000000000000000000000000000..a84123dd0133e4236c57d1cc279090956de61922 --- /dev/null +++ b/_book/docs/281.md @@ -0,0 +1,367 @@ +# GitLab NPM Registry + +> 原文:[https://docs.gitlab.com/ee/user/packages/npm_registry/](https://docs.gitlab.com/ee/user/packages/npm_registry/) + +* [Enabling the NPM Registry](#enabling-the-npm-registry) +* [Getting started](#getting-started) + * [Installing NPM](#installing-npm) + * [Installing Yarn](#installing-yarn) + * [Creating a project](#creating-a-project) +* [Authenticating to the GitLab NPM Registry](#authenticating-to-the-gitlab-npm-registry) + * [Authenticating with a personal access token or deploy token](#authenticating-with-a-personal-access-token-or-deploy-token) + * [Using variables to avoid hard-coding auth token values](#using-variables-to-avoid-hard-coding-auth-token-values) + * [Authenticating with a CI job token](#authenticating-with-a-ci-job-token) +* [Uploading packages](#uploading-packages) +* [Uploading a package with the same version twice](#uploading-a-package-with-the-same-version-twice) +* [Package naming convention](#package-naming-convention) +* [Installing a package](#installing-a-package) + * [Forwarding requests to npmjs.org](#forwarding-requests-to-npmjsorg) +* [Removing a package](#removing-a-package) +* [Publishing a package with CI/CD](#publishing-a-package-with-cicd) +* [Troubleshooting](#troubleshooting) + * [Error running yarn with NPM registry](#error-running-yarn-with-npm-registry) + * [`npm publish` targets default NPM registry (`registry.npmjs.org`)](#npm-publish-targets-default-npm-registry-registrynpmjsorg) + * [`npm install` returns `Error: Failed to replace env in config: ${NPM_TOKEN}`](#npm-install-returns-error-failed-to-replace-env-in-config-npm_token) + * [`npm install` returns `npm ERR! 403 Forbidden`](#npm-install-returns-npm-err-403-forbidden) +* [NPM dependencies metadata](#npm-dependencies-metadata) +* [NPM distribution tags](#npm-distribution-tags) + +# GitLab NPM Registry[](#gitlab-npm-registry-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7. + +使用 GitLab NPM 注册表,每个项目都可以拥有自己的空间来存储 NPM 软件包. + +[![GitLab NPM Registry](img/72befe6a3da1a58465dbf55200aefd26.png)](img/npm_package_view_v12_5.png) + +**注意:**仅支持[作用域的](https://s0docs0npmjs0com.icopy.site/misc/scope)程序包. + +## Enabling the NPM Registry[](#enabling-the-npm-registry "Permalink") + +**注意:**仅当您的 GitLab 管理员[启用了对 NPM 注册表的支持时,](../../../administration/packages/index.html)此选项才可用. + +启用 NPM 注册表后,默认情况下它将可用于所有新项目. 要为现有项目启用它,或者要禁用它: + +1. 导航到项目的**"设置">"常规">"可见性,项目功能,权限"** . +2. 找到"软件包"功能并启用或禁用它. +3. 单击**保存更改**以使更改生效. + +然后,您应该能够在左侧栏中看到" **程序包和注册表"**部分. + +在继续使用 GitLab NPM 注册表进行身份验证之前,您应该熟悉软件包的命名约定. + +## Getting started[](#getting-started "Permalink") + +本节将介绍安装 NPM(或 Yarn)并为您的 JavaScript 项目构建软件包. 如果您不熟悉 NPM 软件包,这是一个快速入门. 如果您已经在使用 NPM 并了解如何构建自己的软件包,请继续[下一节](#authenticating-to-the-gitlab-npm-registry) . + +### Installing NPM[](#installing-npm "Permalink") + +按照[npmjs.com](https://s0docs0npmjs0com.icopy.site/downloading-and-installing-node-js-and-npm)上的说明下载 Node.js 和 NPM 并将其安装到本地开发环境. + +安装完成后,通过运行以下命令验证您可以在终端中使用 NPM: + +``` +npm --version +``` + +您应该会在输出中看到 NPM 版本: + +``` +6.10.3 +``` + +### Installing Yarn[](#installing-yarn "Permalink") + +您可能需要安装并使用 Yarn 替代 NPM. 请按照[yarnpkg.com](https://classic.yarnpkg.com/en/docs/install)上的说明在您的开发环境上进行安装. + +Once installed, you can verify that Yarn is available with the following command: + +``` +yarn --version +``` + +You should see the version printed like so: + +``` +1.19.1 +``` + +### Creating a project[](#creating-a-project "Permalink") + +了解如何创建完整的 JavaScript 项目不在本指南的范围内,但是您可以通过创建并导航到空目录并使用以下命令来初始化新的空包: + +``` +npm init +``` + +或者,如果您使用的是 Yarn: + +``` +yarn init +``` + +这将带您解决一系列问题,以产生`package.json`文件,这是所有 NPM 软件包所必需的. 最重要的问题是软件包名称. NPM 软件包必须[遵循命名约定,](#package-naming-convention)并且范围应限于注册表所在的项目或组. + +完成设置后,现在就可以将软件包上传到 GitLab 注册表了. 首先,您需要设置身份验证,然后将 GitLab 配置为远程注册表. + +## Authenticating to the GitLab NPM Registry[](#authenticating-to-the-gitlab-npm-registry "Permalink") + +如果项目是私有项目,或者您要将 NPM 软件包上传到 GitLab,则需要提供凭据进行身份验证. 首选[个人访问令牌](../../profile/personal_access_tokens.html)和[部署令牌](../../project/deploy_tokens/index.html) ,但支持[OAuth 令牌](../../../api/oauth2.html#resource-owner-password-credentials-flow) . + +**双因素认证(2FA)仅支持个人访问令牌:**如果你有 2FA 启用,你需要使用一个[令牌个人访问](../../profile/personal_access_tokens.html)使用 OAuth 标题与范围设置为`api`或[令牌部署](../../project/deploy_tokens/index.html)与`read_package_registry`或`write_package_registry`范围. 标准 OAuth 令牌将无法向 GitLab NPM 注册表进行身份验证. + +### Authenticating with a personal access token or deploy token[](#authenticating-with-a-personal-access-token-or-deploy-token "Permalink") + +要使用[个人访问令牌](../../profile/personal_access_tokens.html)或[部署令牌进行](../../project/deploy_tokens/index.html)身份验证,请设置 NPM 配置: + +``` +# Set URL for your scoped packages. +# For example package with name `@foo/bar` will use this URL for download +npm config set @foo:registry https://gitlab.com/api/v4/packages/npm/ + +# Add the token for the scoped packages URL. This will allow you to download +# `@foo/` packages from private projects. +npm config set '//gitlab.com/api/v4/packages/npm/:_authToken' "" + +# Add token for uploading to the registry. Replace +# with the project you want your package to be uploaded to. +npm config set '//gitlab.com/api/v4/projects//packages/npm/:_authToken' "" +``` + +将``替换为可以在项目主页上找到的项目 ID,并将``替换为个人访问令牌或部署令牌. + +如果您具有自行管理的 GitLab 安装, `gitlab.com`使用您的域名替换`gitlab.com` . + +现在,您应该能够将 NPM 软件包下载并上传到您的项目. + +**注意:**如果遇到有关[Yarn](https://classic.yarnpkg.com/en/)的错误消息,请参阅[故障排除部分](#troubleshooting) . + +### Using variables to avoid hard-coding auth token values[](#using-variables-to-avoid-hard-coding-auth-token-values "Permalink") + +为了避免对`authToken`值进行硬编码,可以在其位置使用变量: + +``` +npm config set '//gitlab.com/api/v4/projects//packages/npm/:_authToken' "${NPM_TOKEN}" +npm config set '//gitlab.com/api/v4/packages/npm/:_authToken' "${NPM_TOKEN}" +``` + +然后,您可以在本地或通过 GitLab CI / CD 运行`npm publish` : + +* **本地:**发布前导出`NPM_TOKEN` : + + ``` + NPM_TOKEN= npm publish + ``` + +* **GitLab CI / CD:**设置`NPM_TOKEN` [变量](../../../ci/variables/README.html)下,项目的**设置> CI / CD>变量** . + +### Authenticating with a CI job token[](#authenticating-with-a-ci-job-token "Permalink") + +在 GitLab Premium 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9104) . + +如果您将 NPM 与 GitLab CI / CD 一起使用,则可以使用 CI 作业令牌代替个人访问令牌或部署令牌. 令牌将继承生成管道的用户的权限. + +将相应的部分添加到您的`.npmrc`文件中: + +``` +@foo:registry=https://gitlab.com/api/v4/packages/npm/ +//gitlab.com/api/v4/packages/npm/:_authToken=${CI_JOB_TOKEN} +//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN} +``` + +## Uploading packages[](#uploading-packages "Permalink") + +在能够上载软件包之前,您需要为 NPM 指定注册表. 为此,将以下部分添加到`package.json`的底部: + +``` +"publishConfig": { "@foo:registry":"https://gitlab.com/api/v4/projects//packages/npm/" } +``` + +将``替换为您的项目 ID(可在项目的主页上找到),然后将`@foo`替换为您自己的作用域. + +如果您具有自行管理的 GitLab 安装, `gitlab.com`使用您的域名替换`gitlab.com` . + +启用它并设置[身份验证后](#authenticating-to-the-gitlab-npm-registry) ,您可以将 NPM 包上传到您的项目中: + +``` +npm publish +``` + +然后,您可以导航到项目的" **程序包和注册表"**页面,查看上载的程序包,甚至删除它们. + +如果尝试使用给定范围内已经存在的名称发布程序包,则会收到`403 Forbidden!` 错误. + +## Uploading a package with the same version twice[](#uploading-a-package-with-the-same-version-twice "Permalink") + +您不能两次上传相同名称和版本的软件包,除非先删除现有软件包. 这与 npmjs.org 的行为保持一致,但 npmjs.org 不允许用户多次发布同一版本,即使该版本已被删除也是如此. + +## Package naming convention[](#package-naming-convention "Permalink") + +**程序包的作用域必须在项目的根名称空间中** . 程序包名称可以是任何名称,但最好使用项目名称,除非由于命名冲突而无法使用. 例如: + +| Project | Package | Supported | +| --- | --- | --- | +| `foo/bar` | `@foo/bar` | Yes | +| `foo/bar/baz` | `@foo/baz` | Yes | +| `foo/bar/buz` | `@foo/anything` | Yes | +| `gitlab-org/gitlab` | `@gitlab-org/gitlab` | Yes | +| `gitlab-org/gitlab` | `@foo/bar` | No | + +用于命名的正则表达式正在验证来自所有程序包管理器的所有程序包名称: + +``` +/\A\@?(([\w\-\.\+]*)\/)*([\w\-\.]+)@?(([\w\-\.\+]*)\/)*([\w\-\.]*)\z/ +``` + +它允许使用大写字母,而 NPM 不允许,并且几乎允许 NPM 允许的所有字符,但有少数例外(不允许`~` ). + +**注意:**需要大写字母,因为要求范围必须与项目的顶级名称空间相同. 因此,例如,如果您的项目路径为`My-Group/project-foo` ,则您的程序包必须命名为`@My-Group/any-package-name` . `@my-group/any-package-name`不起作用.**在更新用户/组的路径或传输(子)组/项目时:**如果使用 NPM 包更新**项目**的根名称空间,则更改将被拒绝. 为此,请确保先删除所有 NPM 软件包. 不要忘记更新`.npmrc`文件以遵循上述命名约定,并在必要时运行`npm publish` . + +现在,您可以配置项目以通过 GitLab NPM 注册表进行身份验证. + +## Installing a package[](#installing-a-package "Permalink") + +NPM 软件包通常使用 JavaScript 项目中的`npm`或`yarn`命令安装. 如果尚未安装,则需要设置作用域软件包的 URL. 您可以使用以下命令执行此操作: + +``` +npm config set @foo:registry https://gitlab.com/api/v4/packages/npm/ +``` + +您将需要用您的作用域替换`@foo` . + +接下来,您需要确保已设置[身份验证](#authenticating-to-the-gitlab-npm-registry) ,以便成功安装软件包. 完成此操作后,您可以在项目中运行以下命令来安装软件包: + +``` +npm install @my-project-scope/my-package +``` + +或者,如果您使用的是 Yarn: + +``` +yarn add @my-project-scope/my-package +``` + +### Forwarding requests to npmjs.org[](#forwarding-requests-to-npmjsorg "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/55344) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.9. + +默认情况下,当在 GitLab NPM 注册表中找不到 NPM 软件包时,该请求将转发到[npmjs.com](https://s0www0npmjs0com.icopy.site/) . + +管理员可以在" [持续集成"设置中](../../admin_area/settings/continuous_integration.html)禁用此行为. + +## Removing a package[](#removing-a-package "Permalink") + +在项目页面的软件包视图中,您可以通过单击红色垃圾图标或单击软件包详细信息页面上的**删除**按钮来**删除**软件包. + +## Publishing a package with CI/CD[](#publishing-a-package-with-cicd "Permalink") + +要在[GitLab CI / CD 中](./../../../ci/README.html)使用 NPM 命令,可以使用`CI_JOB_TOKEN`代替个人访问令牌或在命令中部署令牌. + +一个简单的`.gitlab-ci.yml`文件示例,用于发布 NPM 软件包: + +``` +image: node:latest + +stages: + - deploy + +deploy: + stage: deploy + script: + - echo '//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}'>.npmrc + - npm publish +``` + +了解有关[使用`CI_JOB_TOKEN`验证 GitLab NPM 注册表的更多信息](#authenticating-with-a-ci-job-token) . + +## Troubleshooting[](#troubleshooting "Permalink") + +### Error running yarn with NPM registry[](#error-running-yarn-with-npm-registry "Permalink") + +如果您在 NPM 注册表中使用[yarn](https://classic.yarnpkg.com/en/) ,则可能会收到以下错误消息: + +``` +yarn install v1.15.2 +warning package.json: No license field +info No lockfile found. +warning XXX: No license field +[1/4] 🔍 Resolving packages... +[2/4] 🚚 Fetching packages... +error An unexpected error occurred: "https://gitlab.com/api/v4/projects/XXX/packages/npm/XXX/XXX/-/XXX/XXX-X.X.X.tgz: Request failed \"404 Not Found\"". +info If you think this is a bug, please open a bug report with the information provided in "/Users/XXX/gitlab-migration/module-util/yarn-error.log". +info Visit https://classic.yarnpkg.com/en/docs/cli/install for documentation about this command +``` + +在这种情况下,请尝试将其添加到您的`.npmrc`文件中(并将``替换为您的个人访问令牌或部署令牌): + +``` +//gitlab.com/api/v4/projects/:_authToken= +``` + +### `npm publish` targets default NPM registry (`registry.npmjs.org`)[](#npm-publish-targets-default-npm-registry-registrynpmjsorg "Permalink") + +确保在`package.json`和`.npmrc`文件中一致设置了包作用域. + +例如,如果您在 GitLab 中的项目名称为`foo/my-package` ,则`package.json`文件应如下所示: + +``` +{ "name": "@foo/my-package", "version": "1.0.0", "description": "Example package for GitLab NPM registry", "publishConfig": { "@foo:registry":"https://gitlab.com/api/v4/projects//packages/npm/" } } +``` + +`.npmrc`文件应如下所示: + +``` +//gitlab.com/api/v4/projects//packages/npm/:_authToken= +//gitlab.com/api/v4/packages/npm/:_authToken= +@foo:registry=https://gitlab.com/api/v4/packages/npm/ +``` + +### `npm install` returns `Error: Failed to replace env in config: ${NPM_TOKEN}`[](#npm-install-returns-error-failed-to-replace-env-in-config-npm_token "Permalink") + +除非您的项目是私有的,否则您不需要令牌即可运行`npm install` (仅要求发布令牌). 如果`.npmrc`文件是以`$NPM_TOKEN`的引用签`$NPM_TOKEN` ,则可以将其删除. 如果您希望保留参考,则需要在运行`npm install`之前设置一个值,或者使用[GitLab 环境变量](./../../../ci/variables/README.html)来设置该值: + +``` +NPM_TOKEN= npm install +``` + +### `npm install` returns `npm ERR! 403 Forbidden`[](#npm-install-returns-npm-err-403-forbidden "Permalink") + +* 检查您的令牌是否已过期并具有适当的权限. +* 检查您是否尝试发布名称在给定范围内已经存在的软件包. +* 确保作用域的软件包 URL 包含斜杠: + * 正确: `//gitlab.com/api/v4/packages/npm/` + * 错误的: `//gitlab.com/api/v4/packages/npm` + +## NPM dependencies metadata[](#npm-dependencies-metadata "Permalink") + +在 GitLab Premium 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/11867) . + +从 GitLab 12.6 开始,发布到 GitLab NPM 注册表的新软件包向 NPM 客户端公开了以下属性: + +* name +* version +* dist-tags +* dependencies + * dependencies + * devDependencies + * bundleDependencies + * peerDependencies + * deprecated + +## NPM distribution tags[](#npm-distribution-tags "Permalink") + +在 GitLab Premium 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9425) . + +您可以为新发布的软件包添加[分发标签](https://s0docs0npmjs0com.icopy.site/cli/dist-tag) . 它们遵循 NPM 的约定,在这些约定中它们是可选的,并且每个标签一次只能分配给一个软件包. 当发布没有标签的软件包时,默认情况下会添加`latest`标签. 在未指定标签或版本的情况下安装软件包也是如此. + +支持的`dist-tag`命令和通常使用标签的示例: + +``` +npm publish @scope/package --tag # Publish new package with new tag +npm dist-tag add @scope/package@version my-tag # Add a tag to an existing package +npm dist-tag ls @scope/package # List all tags under the package +npm dist-tag rm @scope/package@version my-tag # Delete a tag from the package +npm install @scope/package@my-tag # Install a specific tag +``` + +**警告:**由于 NPM 6.9.0 中的错误,删除 dist 标签失败. 确保您的 NPM 版本大于 6.9.1. \ No newline at end of file diff --git a/_book/docs/282.md b/_book/docs/282.md new file mode 100644 index 0000000000000000000000000000000000000000..97a3e60efbd14a3f18e7fa1f5df2c29bdfe55845 --- /dev/null +++ b/_book/docs/282.md @@ -0,0 +1,227 @@ +# GitLab NuGet Repository + +> 原文:[https://docs.gitlab.com/ee/user/packages/nuget_repository/](https://docs.gitlab.com/ee/user/packages/nuget_repository/) + +* [Setting up your development environment](#setting-up-your-development-environment) + * [macOS support](#macos-support) +* [Enabling the NuGet Repository](#enabling-the-nuget-repository) +* [Adding the GitLab NuGet Repository as a source to NuGet](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget) + * [Add NuGet Repository source with NuGet CLI](#add-nuget-repository-source-with-nuget-cli) + * [Add NuGet Repository source with Visual Studio](#add-nuget-repository-source-with-visual-studio) + * [Add NuGet Repository source with .NET CLI](#add-nuget-repository-source-with-net-cli) +* [Uploading packages](#uploading-packages) + * [Upload packages with NuGet CLI](#upload-packages-with-nuget-cli) + * [Upload packages with .NET CLI](#upload-packages-with-net-cli) +* [Install packages](#install-packages) + * [Install a package with NuGet CLI](#install-a-package-with-nuget-cli) + * [Install a package with .NET CLI](#install-a-package-with-net-cli) + +# GitLab NuGet Repository[](#gitlab-nuget-repository-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20050) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.8. + +使用 GitLab NuGet 存储库,每个项目都可以拥有自己的空间来存储 NuGet 软件包. + +GitLab NuGet 存储库可用于: + +* [NuGet CLI](https://docs.microsoft.com/en-us/nuget/reference/nuget-exe-cli-reference) +* [.NET Core CLI](https://docs.microsoft.com/en-us/dotnet/core/tools/) +* [Visual Studio](https://visualstudio.microsoft.com/vs/) + +## Setting up your development environment[](#setting-up-your-development-environment "Permalink") + +您将需要[NuGet CLI 5.2 或更高版本](https://www.nuget.org/downloads) . 早期版本尚未针对 GitLab NuGet 存储库进行测试,因此可能无法正常工作. 如果您具有[Visual Studio](https://visualstudio.microsoft.com/vs/) ,则可能已经安装了 NuGet CLI. + +或者,您可以使用[.NET SDK 3.0 或更高版本](https://dotnet.microsoft.com/download/dotnet-core/3.0) ,该版本将安装 NuGet CLI. + +您可以通过以下方法确认已正确安装[NuGet CLI](https://www.nuget.org/) : + +``` +nuget help +``` + +您应该看到类似以下内容: + +``` +NuGet Version: 5.2.0.6090 +usage: NuGet [args] [options] +Type 'NuGet help ' for help on a specific command. + +Available commands: + +[output truncated] +``` + +### macOS support[](#macos-support "Permalink") + +对于 macOS,您还可以使用[Mono](https://www.mono-project.com/)运行 NuGet CLI. 对于 Homebrew 用户,请运行`brew install mono`来安装 Mono. 然后,您应该能够从[NuGet CLI 页面](https://www.nuget.org/downloads)下载 Windows C#二进制文件`nuget.exe`并运行: + +``` +mono nuget.exe +``` + +## Enabling the NuGet Repository[](#enabling-the-nuget-repository "Permalink") + +**注意:**仅当您的 GitLab 管理员[启用了对 Package Registry 的支持时,](../../../administration/packages/index.html)此选项才可用. + +启用 NuGet 存储库后,默认情况下它将可用于所有新项目. 要为现有项目启用它,或者要禁用它: + +1. 导航到项目的**"设置">"常规">"可见性,项目功能,权限"** . +2. 找到"软件包"功能并启用或禁用它. +3. 单击**保存更改**以使更改生效. + +然后,您应该能够在左侧栏中看到" **程序包和注册表"**部分. + +## Adding the GitLab NuGet Repository as a source to NuGet[](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget "Permalink") + +您将需要以下内容: + +* 您的 GitLab 用户名. +* 个人访问令牌或部署令牌. 对于存储库身份验证: + * 您可以将范围设置为`api`来生成[个人访问令牌](../../../user/profile/personal_access_tokens.html) . + * 您可以生成[令牌部署](./../../project/deploy_tokens/index.html)与范围设置为`read_package_registry` , `write_package_registry` ,或两者兼而有之. +* 您的来源的合适名称. +* 您的项目 ID,可以在项目的主页上找到. + +您现在可以使用以下方法向 NuGet 添加新的源: + +* [NuGet CLI](#add-nuget-repository-source-with-nuget-cli) +* [Visual Studio](#add-nuget-repository-source-with-visual-studio). +* [.NET CLI](#add-nuget-repository-source-with-net-cli) + +### Add NuGet Repository source with NuGet CLI[](#add-nuget-repository-source-with-nuget-cli "Permalink") + +要将 GitLab NuGet 存储库添加为带有`nuget`的源: + +``` +nuget source Add -Name -Source "https://gitlab-instance.example.com/api/v4/projects//packages/nuget/index.json" -UserName -Password +``` + +Where: + +* ``是所需的源名称. + +例如: + +``` +nuget source Add -Name "GitLab" -Source "https://gitlab.example/api/v4/projects/10/packages/nuget/index.json" -UserName carol -Password 12345678asdf +``` + +### Add NuGet Repository source with Visual Studio[](#add-nuget-repository-source-with-visual-studio "Permalink") + +1. Open [Visual Studio](https://visualstudio.microsoft.com/vs/). +2. 打开" **文件">"选项"** (Windows)或" **Visual Studio">"首选项"** (Mac OS). +3. 在**NuGet**部分中,打开**Sources** . 您将看到所有 NuGet 来源的列表. +4. Click **Add**. +5. 填写以下字段: + * **名称** :源的期望名称 + * **位置** : `https://gitlab.com/api/v4/projects//packages/nuget/index.json` : `https://gitlab.com/api/v4/projects//packages/nuget/index.json` + * 将``替换为您的项目 ID. + * 如果您具有自行管理的 GitLab 安装, `gitlab.com`使用您的域名替换`gitlab.com` . + * **用户**名:您的 GitLab 用户名或部署令牌用户名 + * **密码** :您的个人访问令牌或部署令牌 + + [![Visual Studio 添加 NuGet 源](img/a792de1a5441a31253d7a939dfd2de54.png)](img/visual_studio_adding_nuget_source.png) + +6. Click **Save**. + + [![Visual Studio NuGet source added](img/f6b1fbcae610d7e8b04ec117e32573f3.png)](img/visual_studio_nuget_source_added.png) + +如有任何警告,请确保**Location** , **Username**和**Password**正确. + +### Add NuGet Repository source with .NET CLI[](#add-nuget-repository-source-with-net-cli "Permalink") + +要将 GitLab NuGet 存储库添加为.NET 的源, `nuget.config`在项目的根目录中创建一个名为`nuget.config`的文件,其内容如下: + +``` + + + + + + + + + + + + + +``` + +## Uploading packages[](#uploading-packages "Permalink") + +上载套件时,请注意: + +* 允许的最大大小为 50 MB. +* 如果您多次上传具有相同版本的相同程序包,则每次连续上传都将保存为单独的文件. 安装软件包时,GitLab 将提供最新文件. +* 将软件包上传到 GitLab 时,它们不会立即显示在项目的软件包 UI 中. 处理包裹最多可能需要 10 分钟. + +### Upload packages with NuGet CLI[](#upload-packages-with-nuget-cli "Permalink") + +本部分假定您的项目已正确构建,并且已经[使用 NuGet CLI 创建了 NuGet 软件包](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package) . 使用以下命令上传软件包: + +``` +nuget push -Source +``` + +Where: + +* ``是您的软件包文件名,以`.nupkg`结尾. +* ``是[安装过程中使用](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget)的[源名称](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget) . + +### Upload packages with .NET CLI[](#upload-packages-with-net-cli "Permalink") + +本节假定您的项目已正确构建,并且已经[使用.NET CLI 创建了 NuGet 软件包](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package-dotnet-cli) . 使用以下命令上传软件包: + +``` +dotnet nuget push --source +``` + +Where: + +* ``是您的软件包文件名,以`.nupkg`结尾. +* ``是[安装过程中使用](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget)的[源名称](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget) . + +例如: + +``` +dotnet nuget push MyPackage.1.0.0.nupkg --source gitlab +``` + +## Install packages[](#install-packages "Permalink") + +### Install a package with NuGet CLI[](#install-a-package-with-nuget-cli "Permalink") + +**警告:**默认情况下, `nuget`检查的官方消息`nuget.org`第一. 如果您在 GitLab NuGet 存储库中拥有与`nuget.org`的软件包同名的软件包, `nuget.org`必须指定源名称,否则将安装错误的软件包. + +使用以下命令安装最新版本的软件包: + +``` +nuget install -OutputDirectory \ + -Version \ + -Source +``` + +Where: + +* ``是软件包 ID. +* ``是将在其中安装软件包的输出目录. +* `` (可选)是软件包版本. +* `` (可选)是源名称. + +### Install a package with .NET CLI[](#install-a-package-with-net-cli "Permalink") + +**Warning:** If you have a package in the GitLab NuGet Repository with the same name as a package at a different source, you should verify the order in which `dotnet` checks sources during install. This is defined in the `nuget.config` file. + +使用以下命令安装最新版本的软件包: + +``` +dotnet add package \ + -v +``` + +Where: + +* ``是软件包 ID. +* `` (可选)是软件包版本. \ No newline at end of file diff --git a/_book/docs/283.md b/_book/docs/283.md new file mode 100644 index 0000000000000000000000000000000000000000..71392653e80d122b62ad9c6e7221942b88bf9432 --- /dev/null +++ b/_book/docs/283.md @@ -0,0 +1,264 @@ +# GitLab PyPi Repository + +> 原文:[https://docs.gitlab.com/ee/user/packages/pypi_repository/](https://docs.gitlab.com/ee/user/packages/pypi_repository/) + +* [Setting up your development environment](#setting-up-your-development-environment) +* [Enabling the PyPi Repository](#enabling-the-pypi-repository) +* [Getting started](#getting-started) + * [Create a project](#create-a-project) + * [Create a package](#create-a-package) +* [Adding the GitLab PyPi Repository as a source](#adding-the-gitlab-pypi-repository-as-a-source) + * [Authenticating with a personal access token](#authenticating-with-a-personal-access-token) + * [Authenticating with a deploy token](#authenticating-with-a-deploy-token) +* [Uploading packages](#uploading-packages) + * [Upload packages with Twine](#upload-packages-with-twine) +* [Install packages](#install-packages) + +# GitLab PyPi Repository[](#gitlab-pypi-repository-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208747) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10. + +使用 GitLab PyPi 信息库,每个项目都可以有自己的空间来存储 PyPi 软件包. + +GitLab PyPi 存储库可用于: + +* [pip](https://s0pypi0org.icopy.site/project/pip/) +* [twine](https://s0pypi0org.icopy.site/project/twine/) + +## Setting up your development environment[](#setting-up-your-development-environment "Permalink") + +您将需要最新版本的[pip](https://s0pypi0org.icopy.site/project/pip/)和[twine](https://s0pypi0org.icopy.site/project/twine/) . + +## Enabling the PyPi Repository[](#enabling-the-pypi-repository "Permalink") + +**注意:**仅当您的 GitLab 管理员[启用了对 Package Registry 的支持时,](../../../administration/packages/index.html)此选项才可用. + +启用 PyPi 储存库后,默认情况下它将可用于所有新项目. 要为现有项目启用它,或者要禁用它: + +1. 导航到项目的**"设置">"常规">"可见性,项目功能,权限"** . +2. 找到"软件包"功能并启用或禁用它. +3. 单击**保存更改**以使更改生效. + +然后,您应该能够在左侧栏中看到" **程序包和注册表"**部分. + +## Getting started[](#getting-started "Permalink") + +本节将介绍如何创建一个新的示例 PyPi 包进行上传. 这是测试**GitLab PyPi Registry**的快速入门. 如果您已经了解如何构建和发布自己的软件包,请继续[下一节](#adding-the-gitlab-pypi-repository-as-a-source) . + +### Create a project[](#create-a-project "Permalink") + +了解如何创建完整的 Python 项目不在本指南的范围内,但是您可以创建一个小包来测试注册表. 首先创建一个名为`MyPyPiPackage`的新目录: + +``` +mkdir MyPyPiPackage && cd MyPyPiPackage +``` + +创建此目录后,在其中创建另一个目录: + +``` +mkdir mypypipackage && cd mypypipackage +``` + +在此目录中创建两个新文件以设置基本项目: + +``` +touch __init__.py +touch greet.py +``` + +在`greet.py` ,添加以下代码: + +``` +def SayHello(): + print("Hello from MyPyPiPackage") + return +``` + +在`__init__.py`文件中,添加以下内容: + +``` +from .greet import SayHello +``` + +现在,我们的项目基础已经完成,我们可以测试代码是否运行. 在顶部`MyPyPiPackage`目录中启动 Python 提示符. 然后运行: + +``` +>>> from mypypipackage import SayHello +>>> SayHello() +``` + +您应该看到类似于以下内容的输出: + +``` +Python 3.8.2 (v3.8.2:7b3ab5921f, Feb 24 2020, 17:52:18) +[Clang 6.0 (clang-600.0.57)] on darwin +Type "help", "copyright", "credits" or "license" for more information. +>>> from mypypipackage import SayHello +>>> SayHello() +Hello from MyPyPiPackage +``` + +验证示例项目是否按上述要求工作后,接下来就可以创建包了. + +### Create a package[](#create-a-package "Permalink") + +在您的`MyPyPiPackage`目录中,我们需要创建一个`setup.py`文件. 运行以下命令: + +``` +touch setup.py +``` + +该文件包含有关我们软件包的所有信息. 有关此文件的更多信息,请参见[创建 setup.py](https://packaging.python.org/tutorials/packaging-projects/#creating-setup-py) . 对于本指南,我们不需要大量填写此文件,只需将以下内容添加到您的`setup.py` : + +``` +import setuptools + +setuptools.setup( + name="mypypipackage", + version="0.0.1", + author="Example Author", + author_email="author@example.com", + description="A small example package", + packages=setuptools.find_packages(), + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], + python_requires='>=3.6', +) +``` + +保存文件,然后执行如下设置: + +``` +python3 setup.py sdist bdist_wheel +``` + +如果成功,您应该能够在新创建的`dist`文件夹中看到输出. 跑: + +``` +ls dist +``` + +并确认您的输出与以下内容匹配: + +``` +mypypipackage-0.0.1-py3-none-any.whl mypypipackage-0.0.1.tar.gz +``` + +现在,我们的软件包已全部设置好,可以上传到**GitLab PyPi 软件包注册中心** . 在此之前,我们接下来需要设置身份验证. + +## Adding the GitLab PyPi Repository as a source[](#adding-the-gitlab-pypi-repository-as-a-source "Permalink") + +### Authenticating with a personal access token[](#authenticating-with-a-personal-access-token "Permalink") + +您将需要以下内容: + +* 个人访问令牌. 您可以生成范围设置为`api`的[个人访问令牌](../../../user/profile/personal_access_tokens.html) ,以进行存储库身份验证. +* 您的来源的合适名称. +* 您的项目 ID,可以在项目的主页上找到. + +编辑`~/.pypirc`文件并添加以下内容: + +``` +[distutils] +index-servers = + gitlab + +[gitlab] +repository = https://gitlab.com/api/v4/projects//packages/pypi +username = __token__ +password = +``` + +### Authenticating with a deploy token[](#authenticating-with-a-deploy-token "Permalink") + +您将需要以下内容: + +* 部署令牌. 您可以生成[令牌部署](./../../project/deploy_tokens/index.html)与`read_package_registry`和/或`write_package_registry`范围为存储库认证. +* 您的来源的合适名称. +* 您的项目 ID,可以在项目的主页上找到. + +编辑`~/.pypirc`文件并添加以下内容: + +``` +[distutils] +index-servers = + gitlab + +[gitlab] +repository = https://gitlab.com/api/v4/projects//packages/pypi +username = +password = +``` + +## Uploading packages[](#uploading-packages "Permalink") + +上载套件时,请注意: + +* 允许的最大大小为 50 MB. +* 如果您多次上传具有相同版本的相同程序包,则每次连续上传都将保存为单独的文件. 安装软件包时,GitLab 将提供最新文件. + +### Upload packages with Twine[](#upload-packages-with-twine "Permalink") + +如果您按照上面的指南进行操作,则`MyPyPiPackage`软件包应已准备好上载. 运行以下命令: + +``` +python3 -m twine upload --repository gitlab dist/* +``` + +如果成功,您应该看到以下内容: + +``` +Uploading distributions to https://gitlab.com/api/v4/projects//packages/pypi +Uploading mypypipackage-0.0.1-py3-none-any.whl +100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.58k/4.58k [00:00<00:00, 10.9kB/s] +Uploading mypypipackage-0.0.1.tar.gz +100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.24k/4.24k [00:00<00:00, 11.0kB/s] +``` + +这表明该软件包已成功上传. 然后,您可以导航到项目的" **程序包和注册表"**页面,并查看上载的程序包. + +如果您没有遵循上述指南,则需要确保已正确构建[软件包,并使用 setuptools 创建了 PyPi 软件包](https://packaging.python.org/tutorials/packaging-projects/) . + +然后,您可以使用以下命令上传软件包: + +``` +python -m twine upload --repository dist/ +``` + +Where: + +* `` is your package filename, ending in `.tar.gz` or `.whl`. +* ``是[安装过程中使用](#adding-the-gitlab-pypi-repository-as-a-source)的[源名称](#adding-the-gitlab-pypi-repository-as-a-source) . + +## Install packages[](#install-packages "Permalink") + +使用以下命令安装最新版本的软件包: + +``` +pip install --index-url https://__token__:@gitlab.com/api/v4/projects//packages/pypi/simple --no-deps +``` + +Where: + +* ``是软件包名称. +* ``是具有`read_api`范围的个人访问令牌. +* ``是项目 ID. + +如果您遵循上面的指南,并且想测试安装`MyPyPiPackage`软件包,则可以运行以下命令: + +``` +pip install mypypipackage --no-deps --index-url https://__token__:@gitlab.com/api/v4/projects//packages/pypi/simple +``` + +这将导致以下结果: + +``` +Looking in indexes: https://__token__:****@gitlab.com/api/v4/projects//packages/pypi/simple +Collecting mypypipackage + Downloading https://gitlab.com/api/v4/projects//packages/pypi/files/d53334205552a355fee8ca35a164512ef7334f33d309e60240d57073ee4386e6/mypypipackage-0.0.1-py3-none-any.whl (1.6 kB) +Installing collected packages: mypypipackage +Successfully installed mypypipackage-0.0.1 +``` \ No newline at end of file diff --git a/_book/docs/284.md b/_book/docs/284.md new file mode 100644 index 0000000000000000000000000000000000000000..6efa8bd35b64410590558f0e0dc2465e4d8d318f --- /dev/null +++ b/_book/docs/284.md @@ -0,0 +1,595 @@ +# API Docs + +> 原文:[https://docs.gitlab.com/ee/api/README.html](https://docs.gitlab.com/ee/api/README.html) + +* [Available API resources](#available-api-resources) +* [SCIM](#scim-silver-only) +* [Road to GraphQL](#road-to-graphql) +* [Compatibility guidelines](#compatibility-guidelines) + * [Current status](#current-status) +* [Basic usage](#basic-usage) +* [Authentication](#authentication) + * [OAuth2 tokens](#oauth2-tokens) + * [Personal/project access tokens](#personalproject-access-tokens) + * [Session cookie](#session-cookie) + * [GitLab CI job token](#gitlab-ci-job-token) + * [Impersonation tokens](#impersonation-tokens) + * [Disable impersonation](#disable-impersonation) + * [Sudo](#sudo) +* [Status codes](#status-codes) +* [Pagination](#pagination) + * [Offset-based pagination](#offset-based-pagination) + * [Pagination Link header](#pagination-link-header) + * [Other pagination headers](#other-pagination-headers) + * [Keyset-based pagination](#keyset-based-pagination) +* [Path parameters](#path-parameters) +* [Namespaced path encoding](#namespaced-path-encoding) +* [File path, branches, and tags name encoding](#file-path-branches-and-tags-name-encoding) +* [Request Payload](#request-payload) +* [Encoding API parameters of `array` and `hash` types](#encoding-api-parameters-of-array-and-hash-types) + * [`array`](#array) + * [`hash`](#hash) + * [Array of hashes](#array-of-hashes) +* [`id` vs `iid`](#id-vs-iid) +* [Data validation and error reporting](#data-validation-and-error-reporting) +* [Unknown route](#unknown-route) +* [Encoding `+` in ISO 8601 dates](#encoding--in-iso-8601-dates) +* [Clients](#clients) +* [Rate limits](#rate-limits) + +# API Docs[](#api-docs "Permalink") + +通过简单而强大的 API 自动化 GitLab. + +主要的 GitLab API 是[REST](https://en.wikipedia.org/wiki/Representational_state_transfer) API. 因此,本节中的文档假定您具有 REST 概念的知识. + +## Available API resources[](#available-api-resources "Permalink") + +有关可用资源及其端点的列表,请参阅[API 资源](api_resources.html) . + +## SCIM[](#scim-silver-only "Permalink") + +[GitLab.com Silver 和更高版本](https://about.gitlab.com/pricing/)提供了[SCIM API](scim.html) , [该](https://tools.ietf.org/html/rfc7644) [API](scim.html)实现[RFC7644 协议](https://tools.ietf.org/html/rfc7644)并提供`/Users`端点. 基本网址为: `/api/scim/v2/groups/:group_path/Users/` . + +## Road to GraphQL[](#road-to-graphql "Permalink") + +[GitLab](graphql/index.html)中提供了[GraphQL](graphql/index.html) ,它将允许弃用控制器特定的端点. + +GraphQL 具有许多优点: + +1. 我们避免维护两个不同的 API. +2. API 的调用者只能请求他们需要的东西. +3. 默认情况下为版本. + +它将与当前的 v4 REST API 共存. 如果我们有 v5 API,则这应该是 GraphQL 之上的兼容性层. + +尽管 GraphQL 存在一些专利和许可问题,但通过 MIT 下的参考实现的重新许可以及 GraphQL 规范使用 OWF 许可证,这些问题已得到我们的满意解决. + +## Compatibility guidelines[](#compatibility-guidelines "Permalink") + +HTTP API 使用单个数字进行版本控制,当前数字为 4.此数字与[SemVer](https://semver.org/)描述的主要版本号[相同](https://semver.org/) . 这意味着向后不兼容的更改将需要更改此版本号. 但是,次要版本不明确. 这可以实现稳定的 API 端点,但也意味着可以将新功能以相同的版本号添加到 API. + +新功能和错误修复与新的 GitLab 一起发布,除附带的修补程序和安全版本外,还于每月 22 日发布. 向后不兼容的更改(例如,端点删除,参数删除等)以及整个 API 版本的删除与 GitLab 本身的主要版本一起进行. 两个版本之间的所有弃用和更改都应在文档中列出. 对于 v3 和 v4 之间的更改; 请阅读[v3 至 v4 文档](v3_to_v4.html) + +### Current status[](#current-status "Permalink") + +当前仅提供 API 版本 v4\. v3 版本已在[GitLab 11.0](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36819)中删除. + +## Basic usage[](#basic-usage "Permalink") + +API 请求应以`api`和 API 版本为前缀. API 版本在[`lib/api.rb`](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/api/api.rb)定义. 例如,v4 API 的根位于`/api/v4` . + +使用 cURL 的有效 API 请求的示例: + +``` +curl "https://gitlab.example.com/api/v4/projects" +``` + +该 API 使用 JSON 序列化数据. 您无需在 API URL 的末尾指定`.json` . + +## Authentication[](#authentication "Permalink") + +大多数 API 请求都需要身份验证,或者仅在不提供身份验证时才返回公共数据. 对于不需要的情况,将在文档中针对每个端点进行提及. 例如, [`/projects/:id`端点](projects.html#get-single-project) . + +使用 GitLab API 进行身份验证的方法有几种: + +1. [OAuth2 tokens](#oauth2-tokens) +2. [Personal access tokens](../user/profile/personal_access_tokens.html) +3. [Project access tokens](../user/project/settings/project_access_tokens.html) +4. [Session cookie](#session-cookie) +5. [GitLab CI/CD job token](#gitlab-ci-job-token) **(仅特定端点)** + +对于想要以特定用户身份向 API 进行身份验证的管理员,或者想要构建执行此操作的应用程序或脚本的管理员,可以使用以下两种方法: + +1. [Impersonation tokens](#impersonation-tokens) +2. [Sudo](#sudo) + +如果身份验证信息无效或被忽略,将返回一条错误消息,状态码为`401` : + +``` +{ "message": "401 Unauthorized" } +``` + +### OAuth2 tokens[](#oauth2-tokens "Permalink") + +您可以通过在`access_token`参数或`Authorization`标头中传递[OAuth2 令牌](oauth2.html)来对 API 进行身份验证. + +在参数中使用 OAuth2 令牌的示例: + +``` +curl "https://gitlab.example.com/api/v4/projects?access_token=OAUTH-TOKEN" +``` + +在标头中使用 OAuth2 令牌的示例: + +``` +curl --header "Authorization: Bearer OAUTH-TOKEN" "https://gitlab.example.com/api/v4/projects" +``` + +阅读有关[GitLab 作为 OAuth2 提供程序的](oauth2.html)更多信息. + +### Personal/project access tokens[](#personalproject-access-tokens "Permalink") + +Access tokens can be used to authenticate with the API by passing it in either the `private_token` parameter or the `Private-Token` header. + +在参数中使用个人/项目访问令牌的示例: + +``` +curl "https://gitlab.example.com/api/v4/projects?private_token=" +``` + +在标头中使用个人/项目访问令牌的示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/projects" +``` + +您还可以将个人/项目访问令牌与 OAuth 兼容标头一起使用: + +``` +curl --header "Authorization: Bearer " "https://gitlab.example.com/api/v4/projects" +``` + +### Session cookie[](#session-cookie "Permalink") + +登录主 GitLab 应用程序时,将设置`_gitlab_session` cookie. 如果存在,API 将使用此 cookie 进行身份验证,但是当前不支持使用 API​​生成新的会话 cookie. + +这种身份验证方法的主要用户是 GitLab 本身的 Web 前端,它可以将 API 用作经过身份验证的用户来获取其项目列表,例如,而无需显式传递访问令牌. + +### GitLab CI job token[](#gitlab-ci-job-token "Permalink") + +通过一些 API 端点,您可以使用[GitLab CI / CD 作业令牌](../user/project/new_ci_build_permissions_model.html#job-token)来对该 API 进行身份验证: + +* [Get job artifacts](jobs.html#get-job-artifacts) +* [Pipeline triggers](pipeline_triggers.html) +* [Release creation](releases/index.html#create-a-release) + +### Impersonation tokens[](#impersonation-tokens "Permalink") + +在 GitLab 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9099) . 需要管理员权限. + +模拟令牌是一种[个人访问令牌](../user/profile/personal_access_tokens.html) ,只能由管理员为特定用户创建. 如果您要构建以特定用户身份通过​​API 进行身份验证的应用程序或脚本,则它们非常适合. + +它们是直接使用用户密码或他们的个人访问令牌之一以及使用[Sudo](#sudo)功能的替代方法,因为用户(或管理员,对于 Sudo 而言)的密码/令牌可能是未知的,或者可能随时间变化. + +有关更多信息,请参考[用户 API](users.html#create-an-impersonation-token)文档. + +模拟令牌的使用与常规个人访问令牌完全一样,并且可以在`private_token`参数或`Private-Token`标头中传递. + +#### Disable impersonation[](#disable-impersonation "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/40385) . + +默认情况下,模拟是启用的. 禁用模拟: + +**对于所有安装** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitlab_rails['impersonation_enabled'] = false + ``` + +2. 保存文件并[重新配置](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure) GitLab,以使更改生效. + +要重新启用模拟,请删除此配置并重新配置 GitLab. + +**对于源安装** + +1. Edit `config/gitlab.yml`: + + ``` + gitlab: + impersonation_enabled: false + ``` + +2. 保存文件并[重新启动](../administration/restart_gitlab.html#installations-from-source) GitLab,以使更改生效. + +要重新启用模拟,请删除此配置并重新启动 GitLab. + +### Sudo[](#sudo "Permalink") + +**注意:**仅对[管理员](../user/permissions.html)可用. + +如果已通过具有`sudo`范围的 OAuth 或 Personal Access Token 作为管理员进行身份验证,则所有 API 请求都支持执行 API 调用,就好像您是另一个用户一样. + +您需要通过查询字符串或带有您要执行操作的用户的 ID /用户名的标头传递`sudo`参数. 如果作为标题传递,则标题名称必须为`Sudo` . + +**注意:**用户名不区分大小写. + +如果提供了非管理访问令牌,将返回错误消息,状态码为`403` : + +``` +{ "message": "403 Forbidden - Must be admin to use sudo" } +``` + +如果提供了没有`sudo`范围的访问令牌,则将返回错误消息,状态码为`403` : + +``` +{ "error": "insufficient_scope", "error_description": "The request requires higher privileges than provided by the access token.", "scope": "sudo" } +``` + +如果找不到 sudo 用户 ID 或用户名,将返回错误消息,状态码为`404` : + +``` +{ "message": "404 User with ID or username '123' Not Found" } +``` + +有效的 API 调用和使用 cURL 和 sudo request(提供用户名)的请求的示例: + +``` +GET /projects?private_token=&sudo=username +``` + +``` +curl --header "Private-Token: " --header "Sudo: username" "https://gitlab.example.com/api/v4/projects" +``` + +提供 ID 的有效 API 调用和使用 cURL 和 sudo request 的请求的示例: + +``` +GET /projects?private_token=&sudo=23 +``` + +``` +curl --header "Private-Token: " --header "Sudo: 23" "https://gitlab.example.com/api/v4/projects" +``` + +## Status codes[](#status-codes "Permalink") + +该 API 旨在根据上下文和操作返回不同的状态代码. 这样,如果请求导致错误,则调用者可以洞悉出了什么问题. + +下表概述了 API 函数的一般行为. + +| 请求类型 | Description | +| --- | --- | +| `GET` | 访问一个或多个资源,并将结果作为 JSON 返回. | +| `POST` | 如果成功创建资源,则返回`201 Created` ,然后将新创建的资源作为 JSON 返回. | +| `GET` / `PUT` | 如果成功访问或修改了资源,则返回`200 OK` . (修改后的)结果作为 JSON 返回. | +| `DELETE` | 如果资源已成功删除,则返回`204 No Content` . | + +下表显示了 API 请求的可能返回码. + +| 返回值 | Description | +| --- | --- | +| `200 OK` | `GET` , `PUT`或`DELETE`请求成功,资源本身作为 JSON 返回. | +| `204 No Content` | 服务器已成功满足请求,并且响应有效载荷主体中没有其他要发送的内容. | +| `201 Created` | `POST`请求成功,资源作为 JSON 返回. | +| `304 Not Modified` | 指示自上次请求以来尚未修改资源. | +| `400 Bad Request` | API 请求的必需属性丢失,例如,未提供问题标题. | +| `401 Unauthorized` | 用户未通过身份验证,有效的[用户令牌](#authentication)是必需的. | +| `403 Forbidden` | 不允许该请求,例如,不允许用户删除项目. | +| `404 Not Found` | 无法访问资源,例如,找不到资源的 ID. | +| `405 Method Not Allowed` | The request is not supported. | +| `409 Conflict` | 已经存在冲突的资源,例如,使用已经存在的名称创建项目. | +| `412` | 表示请求被拒绝. `If-Unmodified-Since`尝试删除资源时提供了`If-Unmodified-Since`标头,则可能会发生这种情况. | +| `422 Unprocessable` | 无法处理该实体. | +| `500 Server Error` | 在处理请求时,服务器端出了点问题. | + +## Pagination[](#pagination "Permalink") + +我们支持两种分页方法: + +* 基于偏移的分页. 这是默认方法,并且在所有端点上都可用. +* 基于键集的分页. 已添加到选定的端点,但会[逐步推出](https://gitlab.com/groups/gitlab-org/-/epics/2039) . + +对于大型集合,出于性能原因,我们建议键集分页(如果有)而不是偏移分页. + +### Offset-based pagination[](#offset-based-pagination "Permalink") + +有时,返回的结果将跨越许多页面. 列出资源时,可以传递以下参数: + +| Parameter | Description | +| --- | --- | +| `page` | 页码(默认: `1` ) | +| `per_page` | 每页要列出的项目数(默认: `20` ,最大: `100` ) | + +在下面的示例中,我们每页列出 50 个[名称空间](namespaces.html) . + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/namespaces?per_page=50" +``` + +#### Pagination Link header[](#pagination-link-header "Permalink") + +[链接头](https://www.w3.org/wiki/LinkHeader)随每个响应一起发送回去. 它们的`rel`设置为 prev / next / first / last 并包含相关的 URL. 请使用这些链接,而不是生成自己的 URL. + +在下面的卷曲的例子,我们限制输出到每页 3 项( `per_page=3` ),我们要求的第二页( `page=2`的) [评论](notes.html)与 ID 问题的`8`属于与 ID 项目`8` : + +``` +curl --head --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/8/issues/8/notes?per_page=3&page=2" +``` + +响应将是: + +``` +HTTP/1.1 200 OK +Cache-Control: no-cache +Content-Length: 1103 +Content-Type: application/json +Date: Mon, 18 Jan 2016 09:43:18 GMT +Link: ; rel="prev", ; rel="next", ; rel="first", ; rel="last" +Status: 200 OK +Vary: Origin +X-Next-Page: 3 +X-Page: 2 +X-Per-Page: 3 +X-Prev-Page: 1 +X-Request-Id: 732ad4ee-9870-4866-a199-a9db0cde3c86 +X-Runtime: 0.108688 +X-Total: 8 +X-Total-Pages: 3 +``` + +#### Other pagination headers[](#other-pagination-headers "Permalink") + +其他分页标题也会发送回. + +| Header | Description | +| --- | --- | +| `X-Total` | 项目总数 | +| `X-Total-Pages` | 总页数 | +| `X-Per-Page` | 每页的项目数 | +| `X-Page` | 当前页面的索引(从 1 开始) | +| `X-Next-Page` | 下一页的索引 | +| `X-Prev-Page` | 前一页的索引 | + +**注意:**由于性能原因,自[GitLab 11.8 起](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23931)并**在`api_kaminari_count_with_limit` [功能标志](../development/feature_flags/index.html)后面** ,如果资源数量大于 10,000,则`X-Total`和`X-Total-Pages`标头以及`rel="last"` `Link`将不存在响应头. + +### Keyset-based pagination[](#keyset-based-pagination "Permalink") + +键集分页可以更有效地检索页面,并且与基于偏移的分页相比,运行时与集合的大小无关. + +此方法由以下参数控制: + +| Parameter | Description | +| --- | --- | +| `pagination` | `keyset` (启用键集分页) | +| `per_page` | 每页要列出的项目数(默认: `20` ,最大: `100` ) | + +在下面的示例中,我们每页列出 50 [个项目](projects.html) ,并按`id`升序排列. + +``` +curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects?pagination=keyset&per_page=50&order_by=id&sort=asc" +``` + +响应头包括指向下一页的链接. 例如: + +``` +HTTP/1.1 200 OK +... +Links: ; rel="next" +Link: ; rel="next" +Status: 200 OK +... +``` + +**弃用:** `Links`标题将在 GitLab 14.0 中删除,以符合[W3C `Link`规范](https://www.w3.org/wiki/LinkHeader) + +指向下一页的链接包含一个附加过滤器`id_after=42` ,该过滤器不包括我们已经检索到的记录. 请注意,过滤器的类型取决于所使用的`order_by`选项,我们可能有多个过滤器. + +当到达集合的末尾并且没有其他要检索的记录时,将没有`Links`头,并且结果数组为空. + +我们建议仅使用给定的链接来检索下一页,而不要构建自己的 URL. 除了显示的标题外,我们不公开其他分页标题. + +仅针对所选资源和订购选项支持基于键集的分页: + +| Resource | Order | +| --- | --- | +| [Projects](projects.html) | `order_by=id` only | + +## Path parameters[](#path-parameters "Permalink") + +如果端点具有路径参数,则文档将在它们前面加上冒号. + +例如: + +``` +DELETE /projects/:id/share/:group_id +``` + +`:id`路径参数需要替换为项目 ID,而`:group_id`需要替换为组的 ID. 冒号`:`不应包含在内. + +因此,对 ID 为`5` ,组 ID 为`17`的项目的 cURL 调用为: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/share/17" +``` + +**注意:**必须遵循要求进行 URL 编码的路径参数. 如果不是,它将与 API 端点不匹配并以 404 进行响应.如果 API 前面有某些内容(例如 Apache),请确保它不会对 URL 编码的路径参数进行解码. + +## Namespaced path encoding[](#namespaced-path-encoding "Permalink") + +如果使用命名空间的 API 调用,请确保`NAMESPACE/PROJECT_PATH`是 URL 编码的. + +例如, `/`由`/`表示: + +``` +GET /api/v4/projects/diaspora%2Fdiaspora +``` + +**注意:**项目的**路径**不必与**名称**相同. 可以在项目的 URL 或项目设置中的**常规>高级>更改路径**下找到项目的**路径** . + +## File path, branches, and tags name encoding[](#file-path-branches-and-tags-name-encoding "Permalink") + +如果文件路径,分支或标记包含`/` ,请确保其经过 URL 编码. + +例如, `/`由`/`表示: + +``` +GET /api/v4/projects/1/repository/files/src%2FREADME.md?ref=master +GET /api/v4/projects/1/branches/my%2Fbranch/commits +GET /api/v4/projects/1/repository/tags/my%2Ftag +``` + +## Request Payload[](#request-payload "Permalink") + +API 请求可以使用作为[查询字符串](https://en.wikipedia.org/wiki/Query_string)或[有效载荷主体](https://tools.ietf.org/html/draft-ietf-httpbis-p3-payload-14#section-3.2)发送的参数. GET 请求通常发送查询字符串,而 PUT / POST 请求通常发送有效内容正文: + +* 请求参数: + + ``` + curl --request POST "https://gitlab/api/v4/projects?name=&description=" + ``` + +* 请求有效载荷(JSON): + + ``` + curl --request POST --header "Content-Type: application/json" --data '{"name":"", "description":"" \ +-d "import_sources[]=github" \ +-d "import_sources[]=bitbucket" \ +https://gitlab.example.com/api/v4/some_endpoint +``` + +### `hash`[](#hash "Permalink") + +`override_params`是`hash`类型的参数: + +``` +curl --request POST --header "PRIVATE-TOKEN: " \ +--form "namespace=email" \ +--form "path=impapi" \ +--form "file=@/path/to/somefile.txt" +--form "override_params[visibility]=private" \ +--form "override_params[some_other_param]=some_value" \ +https://gitlab.example.com/api/v4/projects/import +``` + +### Array of hashes[](#array-of-hashes "Permalink") + +`variables`是包含哈希键/值对`[{ 'key' => 'UPLOAD_TO_S3', 'value' => 'true' }]` `array`类型的参数: + +``` +curl --globoff --request POST --header "PRIVATE-TOKEN: " \ +"https://gitlab.example.com/api/v4/projects/169/pipeline?ref=master&variables[][key]=VAR1&variables[][value]=hello&variables[][key]=VAR2&variables[][value]=world" + +curl --request POST --header "PRIVATE-TOKEN: " \ +--header "Content-Type: application/json" \ +--data '{ "ref": "master", "variables": [ {"key": "VAR1", "value": "hello"}, {"key": "VAR2", "value": "world"} ] }' \ +"https://gitlab.example.com/api/v4/projects/169/pipeline" +``` + +## `id` vs `iid`[](#id-vs-iid "Permalink") + +Some resources have two similarly-named fields. For example, [issues](issues.html), [merge requests](merge_requests.html), and [project milestones](merge_requests.html). The fields are: + +* `id` :在所有项目中唯一的 ID. +* `iid` :在单个项目范围内唯一的附加内部 ID. + +**注意:** `iid`显示在 Web UI 中. + +如果资源具有`iid`字段和`id`字段,则通常使用`iid`字段代替`id`来获取资源. + +例如,假设一个`id: 42`的项目有一个`id: 46`和`iid: 5` . 在这种情况下: + +* 检索问题的有效 API 调用是`GET /projects/42/issues/5` +* 检索问题的无效 API 调用是`GET /projects/42/issues/46` . + +**注意:**并非所有具有`iid`字段的资源都由`iid`获取. 有关使用哪个字段的指导,请参阅特定资源的文档. + +## Data validation and error reporting[](#data-validation-and-error-reporting "Permalink") + +使用 API​​时,您可能会遇到验证错误,在这种情况下,API 会以 HTTP `400`状态进行回答. + +这种错误在两种情况下出现: + +* API 请求的必需属性丢失,例如,未给出问题标题 +* 属性未通过验证,例如,用户简历太长 + +当缺少属性时,您将获得类似以下内容的信息: + +``` +HTTP/1.1 400 Bad Request +Content-Type: application/json +{ + "message":"400 (Bad request) \"title\" not given" +} +``` + +发生验证错误时,错误消息将有所不同. 它们将包含验证错误的所有详细信息: + +``` +HTTP/1.1 400 Bad Request +Content-Type: application/json +{ + "message": { + "bio": [ + "is too long (maximum is 255 characters)" + ] + } +} +``` + +这使错误消息更加机器可读. 格式可以描述如下: + +``` +{ "message": { "": [ "", "", ... ], "": { "": [ "", "", ... ], } } } +``` + +## Unknown route[](#unknown-route "Permalink") + +当您尝试访问不存在的 API URL 时,您将收到 404 Not Found. + +``` +HTTP/1.1 404 Not Found +Content-Type: application/json +{ + "error": "404 Not Found" +} +``` + +## Encoding `+` in ISO 8601 dates[](#encoding--in-iso-8601-dates "Permalink") + +如果需要在查询参数中包含`+` ,则由于[W3 建议](http://www.w3.org/Addressing/URL/4_URI_Recommentations.html)会将`+`解释为空格,因此可能需要使用`+`来代替. 例如,在一个 ISO 8601 日期中,您可能希望以"山区标准时间"传递时间,例如: + +``` +2017-10-17T23:11:13.000+05:30 +``` + +The correct encoding for the query parameter would be: + +``` +2017-10-17T23:11:13.000%2B05:30 +``` + +## Clients[](#clients "Permalink") + +大多数流行的编程语言都有许多非官方的 GitLab API 客户端. 访问[GitLab 网站](https://about.gitlab.com/partners/#api-clients)以获取完整列表. + +## Rate limits[](#rate-limits "Permalink") + +有关速率限制设置的管理员文档,请参阅[速率限制](../security/rate_limits.html) . 要查找 GitLab.com 专门使用的设置,请参阅[GitLab.com 特定的速率限制](../user/gitlab_com/index.html#gitlabcom-specific-rate-limits) . \ No newline at end of file diff --git a/_book/docs/285.md b/_book/docs/285.md new file mode 100644 index 0000000000000000000000000000000000000000..b94d28780f2bbbaf8f1568df77ee53e85e63930a --- /dev/null +++ b/_book/docs/285.md @@ -0,0 +1,173 @@ +# API resources + +> 原文:[https://docs.gitlab.com/ee/api/api_resources.html](https://docs.gitlab.com/ee/api/api_resources.html) + +* [Project resources](#project-resources) +* [Group resources](#group-resources) +* [Standalone resources](#standalone-resources) +* [Templates API resources](#templates-api-resources) + +# API resources[](#api-resources "Permalink") + +可在以下上下文中对[GitLab API 的](README.html)可用资源进行分组: + +* [Projects](#project-resources). +* [Groups](#group-resources). +* [Standalone](#standalone-resources). + +也可以看看: + +* [V3 to V4](v3_to_v4.html). +* Adding [deploy keys for multiple projects](deploy_key_multiple_projects.html). +* [API Resources for various templates](#templates-api-resources). + +## Project resources[](#project-resources "Permalink") + +在项目上下文中可以使用以下 API 资源: + +| Resource | 可用端点 | +| --- | --- | +| [Access requests](access_requests.html) | `/projects/:id/access_requests` (也可用于组) | +| [Award emoji](award_emoji.html) | `/projects/:id/issues/.../award_emoji`, `/projects/:id/merge_requests/.../award_emoji`, `/projects/:id/snippets/.../award_emoji` | +| [Branches](branches.html) | `/projects/:id/repository/branches/`, `/projects/:id/repository/merged_branches` | +| [Commits](commits.html) | `/projects/:id/repository/commits`, `/projects/:id/statuses` | +| [Container Registry](container_registry.html) | `/projects/:id/registry/repositories` | +| [Custom attributes](custom_attributes.html) | `/projects/:id/custom_attributes` (也适用于组和用户) | +| [Dependencies](dependencies.html) | `/projects/:id/dependencies` | +| [Deploy keys](deploy_keys.html) | `/projects/:id/deploy_keys` (也可以独立使用) | +| [Freeze Periods](freeze_periods.html) | `/projects/:id/freeze_periods` | +| [Deployments](deployments.html) | `/projects/:id/deployments` | +| [讨论](discussions.html) (主题注释) | `/projects/:id/issues/.../discussions` , `/projects/:id/snippets/.../discussions` , `/projects/:id/merge_requests/.../discussions` , `/projects/:id/commits/.../discussions` (也适用于团体) | +| [Environments](environments.html) | `/projects/:id/environments` | +| [Error Tracking](error_tracking.html) | `/projects/:id/error_tracking/settings` | +| [Events](events.html) | `/projects/:id/events` (也可用于用户和独立用户) | +| [Feature Flags](feature_flags.html) | `/projects/:id/feature_flags` | +| [Feature Flag User Lists](feature_flag_user_lists.html) | `/projects/:id/feature_flags_user_lists` | +| [Issues](issues.html) | `/projects/:id/issues` (也可用于团体和独立团体) | +| [Issues Statistics](issues_statistics.html) | `/projects/:id/issues_statistics` (也适用于组和独立用户) | +| [Issue boards](boards.html) | `/projects/:id/boards` | +| [Issue links](issue_links.html) | `/projects/:id/issues/.../links` | +| [Jobs](jobs.html) | `/projects/:id/jobs`, `/projects/:id/pipelines/.../jobs` | +| [Labels](labels.html) | `/projects/:id/labels` | +| [Managed licenses](managed_licenses.html) | `/projects/:id/managed_licenses` | +| [Members](members.html) | `/projects/:id/members` (也可用于组) | +| [Merge request approvals](merge_request_approvals.html) | `/projects/:id/approvals`, `/projects/:id/merge_requests/.../approvals` | +| [Merge requests](merge_requests.html) | `/projects/:id/merge_requests` (也可用于组和独立) | +| [Notes](notes.html) (comments) | `/projects/:id/issues/.../notes` : `/projects/:id/snippets/.../notes` / `/projects/:id/merge_requests/.../notes` `/projects/:id/issues/.../notes` ,/ `/projects/:id/snippets/.../notes` : `/projects/:id/merge_requests/.../notes` `/projects/:id/issues/.../notes` ,/ `/projects/:id/snippets/.../notes` : `/projects/:id/merge_requests/.../notes` (也可用于团体) | +| [Notification settings](notification_settings.html) | `/projects/:id/notification_settings` (也可用于组和独立) | +| [Packages](packages.html) | `/projects/:id/packages` | +| [Pages domains](pages_domains.html) | `/projects/:id/pages` (也可以独立使用) | +| [Pipelines](pipelines.html) | `/projects/:id/pipelines` | +| [Pipeline schedules](pipeline_schedules.html) | `/projects/:id/pipeline_schedules` | +| [Pipeline triggers](pipeline_triggers.html) | `/projects/:id/triggers` | +| [项目](projects.html)包括设置 Webhooks | `/projects` , `/projects/:id/hooks` (也可供用户使用) | +| [Project badges](project_badges.html) | `/projects/:id/badges` | +| [Project clusters](project_clusters.html) | `/projects/:id/clusters` | +| [Project-level variables](project_level_variables.html) | `/projects/:id/variables` | +| [Project import/export](project_import_export.html) | `/projects/:id/export`, `/projects/import`, `/projects/:id/import` | +| [Project milestones](milestones.html) | `/projects/:id/milestones` | +| [Project snippets](project_snippets.html) | `/projects/:id/snippets` | +| [Project templates](project_templates.html) | `/projects/:id/templates` | +| [Protected environments](protected_environments.html) | `/projects/:id/protected_environments` | +| [Protected branches](protected_branches.html) | `/projects/:id/protected_branches` | +| [Protected tags](protected_tags.html) | `/projects/:id/protected_tags` | +| [Releases](releases/index.html) | `/projects/:id/releases` | +| [Release links](releases/links.html) | `/projects/:id/releases/.../assets/links` | +| [Remote mirrors](remote_mirrors.html) | `/projects/:id/remote_mirrors` | +| [Repositories](repositories.html) | `/projects/:id/repository` | +| [Repository files](repository_files.html) | `/projects/:id/repository/files` | +| [Repository submodules](repository_submodules.html) | `/projects/:id/repository/submodules` | +| [Resource label events](resource_label_events.html) | `/projects/:id/issues/.../resource_label_events` : `/projects/:id/merge_requests/.../resource_label_events` `/projects/:id/issues/.../resource_label_events` ,/ `/projects/:id/merge_requests/.../resource_label_events` : `/projects/:id/issues/.../resource_label_events` / `/projects/:id/merge_requests/.../resource_label_events` (也可用于团体) | +| [Runners](runners.html) | `/projects/:id/runners` (也可以独立使用) | +| [Search](search.html) | `/projects/:id/search` (also available for groups and standalone) | +| [Services](services.html) | `/projects/:id/services` | +| [Tags](tags.html) | `/projects/:id/repository/tags` | +| [User-starred metrics dashboards](metrics_user_starred_dashboards.html) | `/projects/:id/metrics/user_starred_dashboards` | +| [Visual Review discussions](visual_review_discussions.html) | `/projects/:id/merge_requests/:merge_request_id/visual_review_discussions` | +| [Vulnerabilities](vulnerabilities.html) | `/vulnerabilities/:id` | +| [Vulnerability exports](vulnerability_exports.html) | `/projects/:id/vulnerability_exports` | +| [Project vulnerabilities](project_vulnerabilities.html) | `/projects/:id/vulnerabilities` | +| [Vulnerability findings](vulnerability_findings.html) | `/projects/:id/vulnerability_findings` | +| [Wikis](wikis.html) | `/projects/:id/wikis` | + +## Group resources[](#group-resources "Permalink") + +组上下文中提供了以下 API 资源: + +| Resource | 可用端点 | +| --- | --- | +| [Access requests](access_requests.html) | `/groups/:id/access_requests/` (也可用于项目) | +| [Custom attributes](custom_attributes.html) | `/groups/:id/custom_attributes` (也适用于项目和用户) | +| [讨论](discussions.html) (主题注释) | `/groups/:id/epics/.../discussions` (也可用于项目) | +| [Epic issues](epic_issues.html) | `/groups/:id/epics/.../issues` | +| [Epic links](epic_links.html) | `/groups/:id/epics/.../epics` | +| [Epics](epics.html) | `/groups/:id/epics` | +| [Groups](groups.html) | `/groups`, `/groups/.../subgroups` | +| [Group badges](group_badges.html) | `/groups/:id/badges` | +| [Group issue boards](group_boards.html) | `/groups/:id/boards` | +| [Group labels](group_labels.html) | `/groups/:id/labels` | +| [Group-level variables](group_level_variables.html) | `/groups/:id/variables` | +| [Group milestones](group_milestones.html) | `/groups/:id/milestones` | +| [Issues](issues.html) | `/groups/:id/issues` (也可用于项目和独立版本) | +| [Issues Statistics](issues_statistics.html) | `/groups/:id/issues_statistics` (也可用于项目和独立版本) | +| [Members](members.html) | `/groups/:id/members` (也可用于项目) | +| [Merge requests](merge_requests.html) | `/groups/:id/merge_requests` (也可用于项目和独立版本) | +| [Notes](notes.html) (comments) | `/groups/:id/epics/.../notes` (也适用于项目) | +| [Notification settings](notification_settings.html) | `/groups/:id/notification_settings` (也可用于项目和独立版本) | +| [Resource label events](resource_label_events.html) | `/groups/:id/epics/.../resource_label_events` (也可用于项目) | +| [Search](search.html) | `/groups/:id/search` (也可用于项目和独立版本) | + +## Standalone resources[](#standalone-resources "Permalink") + +在项目和组上下文(包括`/users` )之外可以使用以下 API 资源: + +| Resource | 可用端点 | +| --- | --- | +| [Instance-level CI/CD variables](instance_level_ci_variables.html) | `/admin/ci/variables` | +| [Admin Sidekiq queues](admin_sidekiq_queues.html) | `/admin/sidekiq/queues/:queue_name` | +| [Appearance](appearance.html) | `/application/appearance` | +| [Applications](applications.html) | `/applications` | +| [Audit Events](audit_events.html) | `/audit_events` | +| [Avatar](avatar.html) | `/avatar` | +| [Broadcast messages](broadcast_messages.html) | `/broadcast_messages` | +| [Code snippets](snippets.html) | `/snippets` | +| [Custom attributes](custom_attributes.html) | `/users/:id/custom_attributes` (也可用于组和项目) | +| [Deploy keys](deploy_keys.html) | `/deploy_keys` (也可用于项目) | +| [Events](events.html) | `/events` , `/users/:id/events` (也可用于项目) | +| [Feature flags](features.html) | `/features` | +| [Geo Nodes](geo_nodes.html) | `/geo_nodes` | +| [Group Activity Analytics](group_activity_analytics.html) | `/analytics/group_activity/{issues_count | merge_requests_count | new_members_count }` | +| [Import repository from GitHub](import.html) | `/import/github` | +| [Instance clusters](instance_clusters.html) | `/admin/clusters` | +| [Issues](issues.html) | `/issues` (也可用于小组和项目) | +| [Issues Statistics](issues_statistics.html) | `/issues_statistics` (也适用于小组和项目) | +| [Keys](keys.html) | `/keys` | +| [License](license.html) | `/license` | +| [Markdown](markdown.html) | `/markdown` | +| [Merge requests](merge_requests.html) | `/merge_requests` (也适用于小组和项目) | +| [Metrics dashboard annotations](metrics_dashboard_annotations.html) | `/environments/:id/metrics_dashboard/annotations`, `/clusters/:id/metrics_dashboard/annotations` | +| [Namespaces](namespaces.html) | `/namespaces` | +| [Notification settings](notification_settings.html) | `/notification_settings` (也适用于小组和项目) | +| [Pages domains](pages_domains.html) | `/pages/domains` (也可用于项目) | +| [Projects](projects.html) | `/users/:id/projects` (也可用于项目) | +| [Project repository storage moves](project_repository_storage_moves.html) | `/project_repository_storage_moves` | +| [Runners](runners.html) | `/runners` (也可用于项目) | +| [Search](search.html) | `/search` (也可用于小组和项目) | +| [Settings](settings.html) | `/application/settings` | +| [Statistics](statistics.html) | `/application/statistics` | +| [Sidekiq metrics](sidekiq_metrics.html) | `/sidekiq` | +| [Suggestions](suggestions.html) | `/suggestions` | +| [System hooks](system_hooks.html) | `/hooks` | +| [Todos](todos.html) | `/todos` | +| [Users](users.html) | `/users` | +| [Validate `.gitlab-ci.yml` file](lint.html) | `/lint` | +| [Version](version.html) | `/version` | + +## Templates API resources[](#templates-api-resources "Permalink") + +端点可用于: + +* [Dockerfile templates](templates/dockerfiles.html). +* [`.gitignore` templates](templates/gitignores.html). +* [GitLab CI/CD YAML templates](templates/gitlab_ci_ymls.html). +* [Open source license templates](templates/licenses.html). \ No newline at end of file diff --git a/_book/docs/286.md b/_book/docs/286.md new file mode 100644 index 0000000000000000000000000000000000000000..8531818e2241a623599729145bd3f5424e79ed0d --- /dev/null +++ b/_book/docs/286.md @@ -0,0 +1,54 @@ +# `.gitignore` API + +> 原文:[https://docs.gitlab.com/ee/api/templates/gitignores.html](https://docs.gitlab.com/ee/api/templates/gitignores.html) + +* [List `.gitignore` templates](#list-gitignore-templates) +* [Single `.gitignore` template](#single-gitignore-template) + +# `.gitignore` API[](#gitignore-api "Permalink") + +在 GitLab 中,有一个`.gitignore`可用的 API 端点. 有关`gitignore`更多信息,请参见[Git 文档](https://git-scm.com/docs/gitignore) . + +## List `.gitignore` templates[](#list-gitignore-templates "Permalink") + +获取所有`.gitignore`模板. + +``` +GET /templates/gitignores +``` + +请求示例: + +``` +curl https://gitlab.example.com/api/v4/templates/gitignores +``` + +响应示例: + +``` +[ { "key": "Actionscript", "name": "Actionscript" }, { "key": "Ada", "name": "Ada" }, { "key": "Agda", "name": "Agda" }, { "key": "Android", "name": "Android" }, { "key": "AppEngine", "name": "AppEngine" }, { "key": "AppceleratorTitanium", "name": "AppceleratorTitanium" }, { "key": "ArchLinuxPackages", "name": "ArchLinuxPackages" }, { "key": "Autotools", "name": "Autotools" }, { "key": "C", "name": "C" }, { "key": "C++", "name": "C++" }, { "key": "CFWheels", "name": "CFWheels" }, { "key": "CMake", "name": "CMake" }, { "key": "CUDA", "name": "CUDA" }, { "key": "CakePHP", "name": "CakePHP" }, { "key": "ChefCookbook", "name": "ChefCookbook" }, { "key": "Clojure", "name": "Clojure" }, { "key": "CodeIgniter", "name": "CodeIgniter" }, { "key": "CommonLisp", "name": "CommonLisp" }, { "key": "Composer", "name": "Composer" }, { "key": "Concrete5", "name": "Concrete5" } ] +``` + +## Single `.gitignore` template[](#single-gitignore-template "Permalink") + +获取单个`.gitignore`模板. + +``` +GET /templates/gitignores/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `key` | string | yes | `.gitignore`模板的键 | + +请求示例: + +``` +curl https://gitlab.example.com/api/v4/templates/gitignores/Ruby +``` + +响应示例: + +``` +{ "name": "Ruby", "content": "*.gem\n*.rbc\n/.config\n/coverage/\n/InstalledFiles\n/pkg/\n/spec/reports/\n/spec/examples.txt\n/test/tmp/\n/test/version_tmp/\n/tmp/\n\n# Used by dotenv library to load environment variables.\n# .env\n\n## Specific to RubyMotion:\n.dat*\n.repl_history\nbuild/\n*.bridgesupport\nbuild-iPhoneOS/\nbuild-iPhoneSimulator/\n\n## Specific to RubyMotion (use of CocoaPods):\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control\n#\n# vendor/Pods/\n\n## Documentation cache and generated files:\n/.yardoc/\n/_yardoc/\n/doc/\n/rdoc/\n\n## Environment normalization:\n/.bundle/\n/vendor/bundle\n/lib/bundler/man/\n\n# for a library or gem, you might want to ignore these files since the code is\n# intended to run in multiple environments; otherwise, check them in:\n# Gemfile.lock\n# .ruby-version\n# .ruby-gemset\n\n# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:\n.rvmrc\n" } +``` \ No newline at end of file diff --git a/_book/docs/287.md b/_book/docs/287.md new file mode 100644 index 0000000000000000000000000000000000000000..439b7d89f1b23d96123835794101331d207c31bd --- /dev/null +++ b/_book/docs/287.md @@ -0,0 +1,54 @@ +# GitLab CI YMLs API + +> 原文:[https://docs.gitlab.com/ee/api/templates/gitlab_ci_ymls.html](https://docs.gitlab.com/ee/api/templates/gitlab_ci_ymls.html) + +* [List GitLab CI YML templates](#list-gitlab-ci-yml-templates) +* [Single GitLab CI YML template](#single-gitlab-ci-yml-template) + +# GitLab CI YMLs API[](#gitlab-ci-ymls-api "Permalink") + +在 GitLab 中,有一个 API 端点可用于 GitLab CI / CD YML. 有关 GitLab 中 CI / CD 管道配置的更多信息,请参阅[配置参考文档](../../ci/yaml/README.html) . + +## List GitLab CI YML templates[](#list-gitlab-ci-yml-templates "Permalink") + +获取所有的 GitLab CI / CD YML 模板. + +``` +GET /templates/gitlab_ci_ymls +``` + +请求示例: + +``` +curl https://gitlab.example.com/api/v4/templates/gitlab_ci_ymls +``` + +响应示例: + +``` +[ { "key": "Android", "name": "Android" }, { "key": "Android-Fastlane", "name": "Android-Fastlane" }, { "key": "Auto-DevOps", "name": "Auto-DevOps" }, { "key": "Bash", "name": "Bash" }, { "key": "C++", "name": "C++" }, { "key": "Chef", "name": "Chef" }, { "key": "Clojure", "name": "Clojure" }, { "key": "Code-Quality", "name": "Code-Quality" }, { "key": "Crystal", "name": "Crystal" }, { "key": "Django", "name": "Django" }, { "key": "Docker", "name": "Docker" }, { "key": "Elixir", "name": "Elixir" }, { "key": "Go", "name": "Go" }, { "key": "Gradle", "name": "Gradle" }, { "key": "Grails", "name": "Grails" }, { "key": "Julia", "name": "Julia" }, { "key": "LaTeX", "name": "LaTeX" }, { "key": "Laravel", "name": "Laravel" }, { "key": "Maven", "name": "Maven" }, { "key": "Mono", "name": "Mono" } ] +``` + +## Single GitLab CI YML template[](#single-gitlab-ci-yml-template "Permalink") + +获取单个 GitLab CI / CD YML 模板. + +``` +GET /templates/gitlab_ci_ymls/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `key` | string | yes | GitLab CI / CD YML 模板的密钥 | + +请求示例: + +``` +curl https://gitlab.example.com/api/v4/templates/gitlab_ci_ymls/Ruby +``` + +响应示例: + +``` +{ "name": "Ruby", "content": "# This file is a template, and might need editing before it works on your project.\n# Official language image. Look for the different tagged releases at:\n# https://hub.docker.com/r/library/ruby/tags/\nimage: \"ruby:2.5\"\n\n# Pick zero or more services to be used on all builds.\n# Only needed when using a docker container to run your tests in.\n# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service\nservices:\n - mysql:latest\n - redis:latest\n - postgres:latest\n\nvariables:\n POSTGRES_DB: database_name\n\n# Cache gems in between builds\ncache:\n paths:\n - vendor/ruby\n\n# This is a basic example for a gem or script which doesn't use\n# services such as redis or postgres\nbefore_script:\n - ruby -v # Print out ruby version for debugging\n # Uncomment next line if your rails app needs a JS runtime:\n # - apt-get update -q && apt-get install nodejs -yqq\n - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby\n\n# Optional - Delete if not using `rubocop`\nrubocop:\n script:\n - rubocop\n\nrspec:\n script:\n - rspec spec\n\nrails:\n variables:\n DATABASE_URL: \"postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB\"\n script:\n - rails db:migrate\n - rails db:seed\n - rails test\n\n# This deploy job uses a simple deploy flow to Heroku, other providers, e.g. AWS Elastic Beanstalk\n# are supported too: https://github.com/travis-ci/dpl\ndeploy:\n type: deploy\n environment: production\n script:\n - gem install dpl\n - dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_PRODUCTION_KEY\n" } +``` \ No newline at end of file diff --git a/_book/docs/288.md b/_book/docs/288.md new file mode 100644 index 0000000000000000000000000000000000000000..95389b2396f0f3bc5eddf52b44ad98fded6f8318 --- /dev/null +++ b/_book/docs/288.md @@ -0,0 +1,125 @@ +# Group and project access requests API + +> 原文:[https://docs.gitlab.com/ee/api/access_requests.html](https://docs.gitlab.com/ee/api/access_requests.html) + +* [Valid access levels](#valid-access-levels) +* [List access requests for a group or project](#list-access-requests-for-a-group-or-project) +* [Request access to a group or project](#request-access-to-a-group-or-project) +* [Approve an access request](#approve-an-access-request) +* [Deny an access request](#deny-an-access-request) + +# Group and project access requests API[](#group-and-project-access-requests-api "Permalink") + +**注意:**此功能是在 GitLab 8.11 中引入的 + +## Valid access levels[](#valid-access-levels "Permalink") + +访问级别在`Gitlab::Access`模块中定义. 当前,这些级别被认可: + +* 无法访问( `0` ) +* 宾客( `10` ) +* 记者( `20` ) +* 显影剂( `30` ) +* 养护者( `40` ) +* 所有者( `50` )-仅对组有效 + +## List access requests for a group or project[](#list-access-requests-for-a-group-or-project "Permalink") + +获取认证用户可见的访问请求列表. + +``` +GET /groups/:id/access_requests +GET /projects/:id/access_requests +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/access_requests" +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/access_requests" +``` + +响应示例: + +``` +[ { "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "created_at": "2012-10-22T14:13:35Z", "requested_at": "2012-10-22T14:13:35Z" }, { "id": 2, "username": "john_doe", "name": "John Doe", "state": "active", "created_at": "2012-10-22T14:13:35Z", "requested_at": "2012-10-22T14:13:35Z" } ] +``` + +## Request access to a group or project[](#request-access-to-a-group-or-project "Permalink") + +请求已验证用户访问组或项目. + +``` +POST /groups/:id/access_requests +POST /projects/:id/access_requests +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/access_requests" +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/access_requests" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "created_at": "2012-10-22T14:13:35Z", "requested_at": "2012-10-22T14:13:35Z" } +``` + +## Approve an access request[](#approve-an-access-request "Permalink") + +批准给定用户的访问请求. + +``` +PUT /groups/:id/access_requests/:user_id/approve +PUT /projects/:id/access_requests/:user_id/approve +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 访问请求者的用户标识 | +| `access_level` | integer | no | 有效的访问级别(默认值: `30` ,开发人员访问级别) | + +请求示例: + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/access_requests/:user_id/approve?access_level=20" +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/access_requests/:user_id/approve?access_level=20" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "created_at": "2012-10-22T14:13:35Z", "access_level": 20 } +``` + +## Deny an access request[](#deny-an-access-request "Permalink") + +拒绝给定用户的访问请求. + +``` +DELETE /groups/:id/access_requests/:user_id +DELETE /projects/:id/access_requests/:user_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 访问请求者的用户标识 | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/access_requests/:user_id" +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/access_requests/:user_id" +``` \ No newline at end of file diff --git a/_book/docs/289.md b/_book/docs/289.md new file mode 100644 index 0000000000000000000000000000000000000000..43765222275a58f465f5598f16c89b461fa35c0c --- /dev/null +++ b/_book/docs/289.md @@ -0,0 +1,63 @@ +# Appearance API + +> 原文:[https://docs.gitlab.com/ee/api/appearance.html](https://docs.gitlab.com/ee/api/appearance.html) + +* [Get current appearance configuration](#get-current-appearance-configuration) +* [Change appearance configuration](#change-appearance-configuration) + +# Appearance API[](#appearance-api-core-only "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/16647) . + +Appearance API 使您可以像在`/admin/appearance`使用 GitLab UI 一样维护 GitLab 的`/admin/appearance` . 该 API 需要管理员权限. + +## Get current appearance configuration[](#get-current-appearance-configuration "Permalink") + +列出 GitLab 实例的当前外观配置. + +``` +GET /application/appearance +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/application/appearance" +``` + +响应示例: + +``` +{ "title": "GitLab Test Instance", "description": "gitlab-test.example.com", "logo": "/uploads/-/system/appearance/logo/1/logo.png", "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", "favicon": "/uploads/-/system/appearance/favicon/1/favicon.png", "new_project_guidelines": "Please read the FAQs for help.", "profile_image_guidelines": "Custom profile image guidelines", "header_message": "", "footer_message": "", "message_background_color": "#e75e40", "message_font_color": "#ffffff", "email_header_and_footer_enabled": false } +``` + +## Change appearance configuration[](#change-appearance-configuration "Permalink") + +使用 API​​调用来修改 GitLab 实例外观配置. + +``` +PUT /application/appearance +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `title` | string | no | 登录/注册页面上的实例标题 | +| `description` | string | no | 降价文字显示在登录/注册页面上 | +| `logo` | mixed | no | 登录/注册页面上使用的实例图像 | +| `header_logo` | mixed | no | 用于主导航栏的实例图像 | +| `favicon` | mixed | no | `.ico`或`.png`格式的实例图标 | +| `new_project_guidelines` | string | no | 新项目页面上显示的降价文字 | +| `profile_image_guidelines` | string | no | 降价文字显示在个人头像下方的个人资料页面上 | +| `header_message` | string | no | 系统标题栏中的消息 | +| `footer_message` | string | no | 系统页脚栏中的消息 | +| `message_background_color` | string | no | 系统页眉/页脚栏的背景颜色 | +| `message_font_color` | string | no | 系统页眉/页脚栏的字体颜色 | +| `email_header_and_footer_enabled` | boolean | no | 如果启用,则在所有外发电子邮件中添加页眉和页脚 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/application/appearance?email_header_and_footer_enabled=true&header_message=test" +``` + +响应示例: + +``` +{ "title": "GitLab Test Instance", "description": "gitlab-test.example.com", "logo": "/uploads/-/system/appearance/logo/1/logo.png", "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", "favicon": "/uploads/-/system/appearance/favicon/1/favicon.png", "new_project_guidelines": "Please read the FAQs for help.", "profile_image_guidelines": "Custom profile image guidelines", "header_message": "test", "footer_message": "", "message_background_color": "#e75e40", "message_font_color": "#ffffff", "email_header_and_footer_enabled": true } +``` \ No newline at end of file diff --git a/_book/docs/290.md b/_book/docs/290.md new file mode 100644 index 0000000000000000000000000000000000000000..2c7066bde63fd10a24e1fc5cdb56d6eb7d530b99 --- /dev/null +++ b/_book/docs/290.md @@ -0,0 +1,93 @@ +# Applications API + +> 原文:[https://docs.gitlab.com/ee/api/applications.html](https://docs.gitlab.com/ee/api/applications.html) + +* [Create an application](#create-an-application) +* [List all applications](#list-all-applications) +* [Delete an application](#delete-an-application) + +# Applications API[](#applications-api "Permalink") + +在 GitLab 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8160) . + +应用程序 API 在以下 OAuth 应用程序上运行: + +* [Using GitLab as an authentication provider](../integration/oauth_provider.html). +* [Allowing access to GitLab resources on a user’s behalf](oauth2.html). + +**注意:**只有管​​理员用户才能使用 Applications API. + +## Create an application[](#create-an-application "Permalink") + +通过发布 JSON 有效负载来创建应用程序. + +如果请求成功,则返回`200` . + +``` +POST /applications +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | string | yes | 应用程序的名称. | +| `redirect_uri` | string | yes | 重定向应用程序的 URI. | +| `scopes` | string | yes | 应用范围. | +| `confidential` | boolean | no | 该应用程序将在可以对客户机密保密的地方使用. 本机移动应用程序和单页应用程序被认为是非机密的. 如果未提供,则默认为`true` | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " --data "name=MyApplication&redirect_uri=http://redirect.uri&scopes=" "https://gitlab.example.com/api/v4/applications" +``` + +响应示例: + +``` +{ "id":1, "application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737", "application_name": "MyApplication", "secret": "ee1dd64b6adc89cf7e2c23099301ccc2c61b441064e9324d963c46902a85ec34", "callback_url": "http://redirect.uri", "confidential": true } +``` + +## List all applications[](#list-all-applications "Permalink") + +列出所有注册的应用程序. + +``` +GET /applications +``` + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/applications" +``` + +响应示例: + +``` +[ { "id":1, "application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737", "application_name": "MyApplication", "callback_url": "http://redirect.uri", "confidential": true } ] +``` + +**注意:**此 API 不会公开`secret`值. + +## Delete an application[](#delete-an-application "Permalink") + +删除特定的应用程序. + +如果请求成功,则返回`204` . + +``` +DELETE /applications/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 应用程序的 ID(不是 application_id). | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/applications/:id" +``` \ No newline at end of file diff --git a/_book/docs/291.md b/_book/docs/291.md new file mode 100644 index 0000000000000000000000000000000000000000..faa74b50ab2943fba035472e03c75b1c0feb9136 --- /dev/null +++ b/_book/docs/291.md @@ -0,0 +1,182 @@ +# Audit Events API + +> 原文:[https://docs.gitlab.com/ee/api/audit_events.html](https://docs.gitlab.com/ee/api/audit_events.html) + +* [Instance Audit Events](#instance-audit-events-premium-only) + * [Retrieve all instance audit events](#retrieve-all-instance-audit-events) + * [Retrieve single instance audit event](#retrieve-single-instance-audit-event) +* [Group Audit Events](#group-audit-events-starter) + * [Retrieve all group audit events](#retrieve-all-group-audit-events) + * [Retrieve a specific group audit event](#retrieve-a-specific-group-audit-event) +* [Project Audit Events](#project-audit-events-starter) + * [Retrieve all project audit events](#retrieve-all-project-audit-events) + * [Retrieve a specific project audit event](#retrieve-a-specific-project-audit-event) + +# Audit Events API[](#audit-events-api "Permalink") + +## Instance Audit Events[](#instance-audit-events-premium-only "Permalink") + +Audit Events API 使您可以检索[实例审核事件](../administration/audit_events.html#instance-events-premium-only) . + +要使用 API​​检索审核事件,您必须以管理员[身份进行身份验证](README.html#authentication) . + +### Retrieve all instance audit events[](#retrieve-all-instance-audit-events "Permalink") + +``` +GET /audit_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `created_after` | string | no | 返回在给定时间或之后创建的审核事件. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `created_before` | string | no | 返回在给定时间或之前创建的审核事件. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `entity_type` | string | no | 返回给定实体类型的审核事件. 有效值为: `User` , `Group`或`Project` . | +| `entity_id` | integer | no | 返回给定实体 ID 的审核事件. 需要`entity_type`属性存在. | + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/audit_events" +``` + +响应示例: + +``` +[ { "id": 1, "author_id": 1, "entity_id": 6, "entity_type": "Project", "details": { "custom_message": "Project archived", "author_name": "Administrator", "target_id": "flightjs/flight", "target_type": "Project", "target_details": "flightjs/flight", "ip_address": "127.0.0.1", "entity_path": "flightjs/flight" }, "created_at": "2019-08-30T07:00:41.885Z" }, { "id": 2, "author_id": 1, "entity_id": 60, "entity_type": "Group", "details": { "add": "group", "author_name": "Administrator", "target_id": "flightjs", "target_type": "Group", "target_details": "flightjs", "ip_address": "127.0.0.1", "entity_path": "flightjs" }, "created_at": "2019-08-27T18:36:44.162Z" }, { "id": 3, "author_id": 51, "entity_id": 51, "entity_type": "User", "details": { "change": "email address", "from": "hello@flightjs.com", "to": "maintainer@flightjs.com", "author_name": "Andreas", "target_id": 51, "target_type": "User", "target_details": "Andreas", "ip_address": null, "entity_path": "Andreas" }, "created_at": "2019-08-22T16:34:25.639Z" } ] +``` + +### Retrieve single instance audit event[](#retrieve-single-instance-audit-event "Permalink") + +``` +GET /audit_events/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 审核事件的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/audit_events/1" +``` + +响应示例: + +``` +{ "id": 1, "author_id": 1, "entity_id": 6, "entity_type": "Project", "details": { "custom_message": "Project archived", "author_name": "Administrator", "target_id": "flightjs/flight", "target_type": "Project", "target_details": "flightjs/flight", "ip_address": "127.0.0.1", "entity_path": "flightjs/flight" }, "created_at": "2019-08-30T07:00:41.885Z" } +``` + +## Group Audit Events[](#group-audit-events-starter "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34078) . + +组审核事件 API 使您可以检索[组审核事件](../administration/audit_events.html#group-events-starter) . + +要使用 API​​检索组审核事件,您必须通过管理员[身份](README.html#authentication)或组所有者[身份进行身份验证](README.html#authentication) . + +### Retrieve all group audit events[](#retrieve-all-group-audit-events "Permalink") + +``` +GET /groups/:id/audit_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `created_after` | string | no | 在给定时间或之后创建的返回组审核事件. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `created_before` | string | no | 返回在给定时间或之前创建的组审核事件. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/groups/60/audit_events" +``` + +响应示例: + +``` +[ { "id": 2, "author_id": 1, "entity_id": 60, "entity_type": "Group", "details": { "custom_message": "Group marked for deletion", "author_name": "Administrator", "target_id": "flightjs", "target_type": "Group", "target_details": "flightjs", "ip_address": "127.0.0.1", "entity_path": "flightjs" }, "created_at": "2019-08-28T19:36:44.162Z" }, { "id": 1, "author_id": 1, "entity_id": 60, "entity_type": "Group", "details": { "add": "group", "author_name": "Administrator", "target_id": "flightjs", "target_type": "Group", "target_details": "flightjs", "ip_address": "127.0.0.1", "entity_path": "flightjs" }, "created_at": "2019-08-27T18:36:44.162Z" } ] +``` + +### Retrieve a specific group audit event[](#retrieve-a-specific-group-audit-event "Permalink") + +仅对组所有者和管理员可用. + +``` +GET /groups/:id/audit_events/:audit_event_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `audit_event_id` | integer | yes | 审核事件的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/groups/60/audit_events/2" +``` + +响应示例: + +``` +{ "id": 2, "author_id": 1, "entity_id": 60, "entity_type": "Group", "details": { "custom_message": "Group marked for deletion", "author_name": "Administrator", "target_id": "flightjs", "target_type": "Group", "target_details": "flightjs", "ip_address": "127.0.0.1", "entity_path": "flightjs" }, "created_at": "2019-08-28T19:36:44.162Z" } +``` + +## Project Audit Events[](#project-audit-events-starter "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/219238) . + +通过 Project Audit Events API,您可以检索[项目审核事件](../administration/audit_events.html#project-events-starter) . + +To retrieve project audit events using the API, you must [authenticate yourself](README.html#authentication) as a Maintainer or an Owner of the project. + +### Retrieve all project audit events[](#retrieve-all-project-audit-events "Permalink") + +``` +GET /projects/:id/audit_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `created_after` | string | no | 返回在给定时间或之后创建的项目审核事件. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `created_before` | string | no | 返回在给定时间或之前创建的项目审核事件. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +``` +curl --header "PRIVATE-TOKEN: " https://primary.example.com/api/v4/projects/7/audit_events +``` + +响应示例: + +``` +[ { "id": 5, "author_id": 1, "entity_id": 7, "entity_type": "Project", "details": { "change": "prevent merge request approval from reviewers", "from": "", "to": "true", "author_name": "Administrator", "target_id": 7, "target_type": "Project", "target_details": "twitter/typeahead-js", "ip_address": "127.0.0.1", "entity_path": "twitter/typeahead-js" }, "created_at": "2020-05-26T22:55:04.230Z" }, { "id": 4, "author_id": 1, "entity_id": 7, "entity_type": "Project", "details": { "change": "prevent merge request approval from authors", "from": "false", "to": "true", "author_name": "Administrator", "target_id": 7, "target_type": "Project", "target_details": "twitter/typeahead-js", "ip_address": "127.0.0.1", "entity_path": "twitter/typeahead-js" }, "created_at": "2020-05-26T22:55:04.218Z" } ] +``` + +### Retrieve a specific project audit event[](#retrieve-a-specific-project-audit-event "Permalink") + +仅适用于项目维护者或所有者. + +``` +GET /projects/:id/audit_events/:audit_event_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `audit_event_id` | integer | yes | 审核事件的 ID | + +``` +curl --header "PRIVATE-TOKEN: " https://primary.example.com/api/v4/projects/7/audit_events/5 +``` + +响应示例: + +``` +{ "id": 5, "author_id": 1, "entity_id": 7, "entity_type": "Project", "details": { "change": "prevent merge request approval from reviewers", "from": "", "to": "true", "author_name": "Administrator", "target_id": 7, "target_type": "Project", "target_details": "twitter/typeahead-js", "ip_address": "127.0.0.1", "entity_path": "twitter/typeahead-js" }, "created_at": "2020-05-26T22:55:04.230Z" } +``` \ No newline at end of file diff --git a/_book/docs/292.md b/_book/docs/292.md new file mode 100644 index 0000000000000000000000000000000000000000..101b6cb11ed4f65dcc12d31632ebfbe614497045 --- /dev/null +++ b/_book/docs/292.md @@ -0,0 +1,43 @@ +# Avatar API + +> 原文:[https://docs.gitlab.com/ee/api/avatar.html](https://docs.gitlab.com/ee/api/avatar.html) + +* [Get a single avatar URL](#get-a-single-avatar-url) + +# Avatar API[](#avatar-api "Permalink") + +在 GitLab 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19121) . + +## Get a single avatar URL[](#get-a-single-avatar-url "Permalink") + +使用给定的电子邮件地址为用户获取一个[头像](../user/profile/index.html#profile-settings) URL. + +If: + +* 找不到具有给定公共电子邮件地址的用户,返回来自外部化身服务的结果. +* 公开可见性受到限制,未经身份验证时,响应将为`403 Forbidden` . + +**注意:**无需身份验证即可访问此端点. + +``` +GET /avatar?email=admin@example.com +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `email` | string | yes | 用户的公共电子邮件地址. | +| `size` | integer | no | 单像素尺寸(因为图像是正方形). 仅用于在`Gravatar`或已配置的`Libravatar`服务器上的头像查找. | + +请求示例: + +``` +curl "https://gitlab.example.com/api/v4/avatar?email=admin@example.com&size=32" +``` + +响应示例: + +``` +{ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=64&d=identicon" } +``` \ No newline at end of file diff --git a/_book/docs/293.md b/_book/docs/293.md new file mode 100644 index 0000000000000000000000000000000000000000..570b37b33929db58a7b52122957c8dc042eafb90 --- /dev/null +++ b/_book/docs/293.md @@ -0,0 +1,260 @@ +# Award Emoji API + +> 原文:[https://docs.gitlab.com/ee/api/award_emoji.html](https://docs.gitlab.com/ee/api/award_emoji.html) + +* [Issues, merge requests, and snippets](#issues-merge-requests-and-snippets) + * [List an awardable’s award emoji](#list-an-awardables-award-emoji) + * [Get single award emoji](#get-single-award-emoji) + * [Award a new emoji](#award-a-new-emoji) + * [Delete an award emoji](#delete-an-award-emoji) +* [Award Emoji on Comments](#award-emoji-on-comments) + * [List a comment’s award emoji](#list-a-comments-award-emoji) + * [Get an award emoji for a comment](#get-an-award-emoji-for-a-comment) + * [Award a new emoji on a comment](#award-a-new-emoji-on-a-comment) + * [Delete an award emoji from a comment](#delete-an-award-emoji-from-a-comment) + +# Award Emoji API[](#award-emoji-api "Permalink") + +在 GitLab 8.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4575) . 在 8.12 中添加了代码段支持. + +[获奖的表情符号](../user/award_emojis.html)讲出一千个单词. + +可以通过以下方式授予表情符号(称为"奖项"): + +* [Issues](../user/project/issues/index.html) ([API](issues.html)). +* [Merge requests](../user/project/merge_requests/index.html) ([API](merge_requests.html)). +* [Snippets](../user/snippets.html) ([API](snippets.html)). + +Emoji can also [be awarded](../user/award_emojis.html#award-emoji-for-comments) on comments (also known as notes). See also [Notes API](notes.html). + +## Issues, merge requests, and snippets[](#issues-merge-requests-and-snippets "Permalink") + +有关将这些端点与注释一起使用的信息,请参见[在注释](#award-emoji-on-comments)上[授予 Emoji 表情](#award-emoji-on-comments) . + +### List an awardable’s award emoji[](#list-an-awardables-award-emoji "Permalink") + +获取指定奖励的所有奖励表情符号的列表. + +``` +GET /projects/:id/issues/:issue_iid/award_emoji +GET /projects/:id/merge_requests/:merge_request_iid/award_emoji +GET /projects/:id/snippets/:snippet_id/award_emoji +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid`/`merge_request_iid`/`snippet_id` | integer | yes | `iid` ID(合并请求/问题的`id` ,摘要的`id` ). | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji" +``` + +响应示例: + +``` +[ { "id": 4, "name": "1234", "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2016-06-15T10:09:34.206Z", "updated_at": "2016-06-15T10:09:34.206Z", "awardable_id": 80, "awardable_type": "Issue" }, { "id": 1, "name": "microphone", "user": { "name": "User 4", "username": "user4", "id": 26, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/7e65550957227bd38fe2d7fbc6fd2f7b?s=80&d=identicon", "web_url": "http://gitlab.example.com/user4" }, "created_at": "2016-06-15T10:09:34.177Z", "updated_at": "2016-06-15T10:09:34.177Z", "awardable_id": 80, "awardable_type": "Issue" } ] +``` + +### Get single award emoji[](#get-single-award-emoji "Permalink") + +从问题,摘要或合并请求中获取单个奖励表情符号. + +``` +GET /projects/:id/issues/:issue_iid/award_emoji/:award_id +GET /projects/:id/merge_requests/:merge_request_iid/award_emoji/:award_id +GET /projects/:id/snippets/:snippet_id/award_emoji/:award_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid`/`merge_request_iid`/`snippet_id` | integer | yes | `iid` ID(合并请求/问题的`id` ,摘要的`id` ). | +| `award_id` | integer | yes | 奖励表情符号的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/1" +``` + +响应示例: + +``` +{ "id": 1, "name": "microphone", "user": { "name": "User 4", "username": "user4", "id": 26, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/7e65550957227bd38fe2d7fbc6fd2f7b?s=80&d=identicon", "web_url": "http://gitlab.example.com/user4" }, "created_at": "2016-06-15T10:09:34.177Z", "updated_at": "2016-06-15T10:09:34.177Z", "awardable_id": 80, "awardable_type": "Issue" } +``` + +### Award a new emoji[](#award-a-new-emoji "Permalink") + +在指定的奖励对象上创建奖励表情符号. + +``` +POST /projects/:id/issues/:issue_iid/award_emoji +POST /projects/:id/merge_requests/:merge_request_iid/award_emoji +POST /projects/:id/snippets/:snippet_id/award_emoji +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid`/`merge_request_iid`/`snippet_id` | integer | yes | `iid` ID(合并请求/问题的`id` ,摘要的`id` ). | +| `name` | string | yes | 不含冒号的表情符号名称. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji?name=blowfish" +``` + +示例响应: + +``` +{ "id": 344, "name": "blowfish", "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2016-06-17T17:47:29.266Z", "updated_at": "2016-06-17T17:47:29.266Z", "awardable_id": 80, "awardable_type": "Issue" } +``` + +### Delete an award emoji[](#delete-an-award-emoji "Permalink") + +有时候,这并不是必须的,您必须取消该奖项. + +**注意:**仅适用于管理员或奖项的作者. + +``` +DELETE /projects/:id/issues/:issue_iid/award_emoji/:award_id +DELETE /projects/:id/merge_requests/:merge_request_iid/award_emoji/:award_id +DELETE /projects/:id/snippets/:snippet_id/award_emoji/:award_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid`/`merge_request_iid`/`snippet_id` | integer | yes | `iid` ID(合并请求/问题的`id` ,摘要的`id` ). | +| `award_id` | integer | yes | 奖励表情符号的 ID. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/344" +``` + +## Award Emoji on Comments[](#award-emoji-on-comments "Permalink") + +注释(也称为注释)是问题,合并请求和摘要的子资源. + +**注意:**以下示例描述了如何使用奖励表情符号处理问题的注释,但可以轻松地将其用于合并请求或摘要中的注释. 因此,您必须用`merge_request_iid`或`snippet_id`替换`issue_iid` . + +### List a comment’s award emoji[](#list-a-comments-award-emoji "Permalink") + +获取所有奖励表情符号的评论(注释). + +``` +GET /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid` | integer | yes | 问题的内部 ID. | +| `note_id` | integer | yes | 注释(注释)的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji" +``` + +响应示例: + +``` +[ { "id": 2, "name": "mood_bubble_lightning", "user": { "name": "User 4", "username": "user4", "id": 26, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/7e65550957227bd38fe2d7fbc6fd2f7b?s=80&d=identicon", "web_url": "http://gitlab.example.com/user4" }, "created_at": "2016-06-15T10:09:34.197Z", "updated_at": "2016-06-15T10:09:34.197Z", "awardable_id": 1, "awardable_type": "Note" } ] +``` + +### Get an award emoji for a comment[](#get-an-award-emoji-for-a-comment "Permalink") + +获得单个奖励表情符号作为注释(注释). + +``` +GET /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji/:award_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid` | integer | yes | 问题的内部 ID. | +| `note_id` | integer | yes | 注释(注释)的 ID. | +| `award_id` | integer | yes | 奖励表情符号的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji/2" +``` + +响应示例: + +``` +{ "id": 2, "name": "mood_bubble_lightning", "user": { "name": "User 4", "username": "user4", "id": 26, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/7e65550957227bd38fe2d7fbc6fd2f7b?s=80&d=identicon", "web_url": "http://gitlab.example.com/user4" }, "created_at": "2016-06-15T10:09:34.197Z", "updated_at": "2016-06-15T10:09:34.197Z", "awardable_id": 1, "awardable_type": "Note" } +``` + +### Award a new emoji on a comment[](#award-a-new-emoji-on-a-comment "Permalink") + +在指定的注释(注释)上创建一个奖励表情符号. + +``` +POST /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid` | integer | yes | 问题的内部 ID. | +| `note_id` | integer | yes | 注释(注释)的 ID. | +| `name` | string | yes | 不含冒号的表情符号名称. | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji?name=rocket" +``` + +响应示例: + +``` +{ "id": 345, "name": "rocket", "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2016-06-17T19:59:55.888Z", "updated_at": "2016-06-17T19:59:55.888Z", "awardable_id": 1, "awardable_type": "Note" } +``` + +### Delete an award emoji from a comment[](#delete-an-award-emoji-from-a-comment "Permalink") + +有时候,这并不是必须的,您必须取消该奖项. + +**注意:**仅适用于管理员或奖项的作者. + +``` +DELETE /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji/:award_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid` | integer | yes | 问题的内部 ID. | +| `note_id` | integer | yes | 注释(注释)的 ID. | +| `award_id` | integer | yes | award_emoji 的 ID. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/345" +``` \ No newline at end of file diff --git a/_book/docs/294.md b/_book/docs/294.md new file mode 100644 index 0000000000000000000000000000000000000000..90201afce148eed352697804380fc3708c370d5d --- /dev/null +++ b/_book/docs/294.md @@ -0,0 +1,160 @@ +# Project badges API + +> 原文:[https://docs.gitlab.com/ee/api/project_badges.html](https://docs.gitlab.com/ee/api/project_badges.html) + +* [Placeholder tokens](#placeholder-tokens) +* [List all badges of a project](#list-all-badges-of-a-project) +* [Get a badge of a project](#get-a-badge-of-a-project) +* [Add a badge to a project](#add-a-badge-to-a-project) +* [Edit a badge of a project](#edit-a-badge-of-a-project) +* [Remove a badge from a project](#remove-a-badge-from-a-project) +* [Preview a badge from a project](#preview-a-badge-from-a-project) + +# Project badges API[](#project-badges-api "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17082) . + +## Placeholder tokens[](#placeholder-tokens "Permalink") + +徽章支持占位符,这些占位符将在链接和图像 URL 中被实时替换. 允许的占位符为: + +* **%{project_path}** :将被项目路径替换. +* **%{project_id}** :将被项目 ID 取代. +* **%{default_branch}** :将被项目默认分支替换. +* **%{commit_sha}** :将被上一个项目的提交 sha 取代. + +## List all badges of a project[](#list-all-badges-of-a-project "Permalink") + +获取项目徽章及其组徽章的列表. + +``` +GET /projects/:id/badges +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | no | 要返回的徽章名称(区分大小写). | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/badges" +``` + +响应示例: + +``` +[ { "name": "Coverage", "id": 1, "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", "kind": "project" }, { "name": "Pipeline", "id": 2, "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", "kind": "group" }, ] +``` + +## Get a badge of a project[](#get-a-badge-of-a-project "Permalink") + +获取项目的徽章. + +``` +GET /projects/:id/badges/:badge_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `badge_id` | integer | yes | 徽章 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id" +``` + +响应示例: + +``` +{ "id": 1, "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", "kind": "project" } +``` + +## Add a badge to a project[](#add-a-badge-to-a-project "Permalink") + +将徽章添加到项目. + +``` +POST /projects/:id/badges +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `link_url` | string | yes | 徽章链接的 URL | +| `image_url` | string | yes | 徽章图片的网址 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --data "link_url=https://gitlab.com/gitlab-org/gitlab-foss/commits/master&image_url=https://shields.io/my/badge1&position=0" "https://gitlab.example.com/api/v4/projects/:id/badges" +``` + +响应示例: + +``` +{ "id": 1, "link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "image_url": "https://shields.io/my/badge1", "rendered_link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "rendered_image_url": "https://shields.io/my/badge1", "kind": "project" } +``` + +## Edit a badge of a project[](#edit-a-badge-of-a-project "Permalink") + +更新项目的徽章. + +``` +PUT /projects/:id/badges/:badge_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `badge_id` | integer | yes | 徽章 ID | +| `link_url` | string | no | 徽章链接的 URL | +| `image_url` | string | no | 徽章图片的网址 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id" +``` + +响应示例: + +``` +{ "id": 1, "link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "image_url": "https://shields.io/my/badge", "rendered_link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "rendered_image_url": "https://shields.io/my/badge", "kind": "project" } +``` + +## Remove a badge from a project[](#remove-a-badge-from-a-project "Permalink") + +从项目中删除徽章. 使用此端点将仅删除项目的标志. + +``` +DELETE /projects/:id/badges/:badge_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `badge_id` | integer | yes | 徽章 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id" +``` + +## Preview a badge from a project[](#preview-a-badge-from-a-project "Permalink") + +返回解析占位符插值后的`link_url`和`image_url`最终 URL. + +``` +GET /projects/:id/badges/render +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `link_url` | string | yes | 徽章链接的 URL | +| `image_url` | string | yes | 徽章图片的网址 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/badges/render?link_url=http%3A%2F%2Fexample.com%2Fci_status.svg%3Fproject%3D%25%7Bproject_path%7D%26ref%3D%25%7Bdefault_branch%7D&image_url=https%3A%2F%2Fshields.io%2Fmy%2Fbadge" +``` + +响应示例: + +``` +{ "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", } +``` \ No newline at end of file diff --git a/_book/docs/295.md b/_book/docs/295.md new file mode 100644 index 0000000000000000000000000000000000000000..b4f207a702c613f22666101b2e6d7a1899b8b3af --- /dev/null +++ b/_book/docs/295.md @@ -0,0 +1,162 @@ +# Group badges API + +> 原文:[https://docs.gitlab.com/ee/api/group_badges.html](https://docs.gitlab.com/ee/api/group_badges.html) + +* [Placeholder tokens](#placeholder-tokens) +* [List all badges of a group](#list-all-badges-of-a-group) +* [Get a badge of a group](#get-a-badge-of-a-group) +* [Add a badge to a group](#add-a-badge-to-a-group) +* [Edit a badge of a group](#edit-a-badge-of-a-group) +* [Remove a badge from a group](#remove-a-badge-from-a-group) +* [Preview a badge from a group](#preview-a-badge-from-a-group) + +# Group badges API[](#group-badges-api "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17082) . + +## Placeholder tokens[](#placeholder-tokens "Permalink") + +徽章支持占位符,这些占位符将在链接和图像 URL 中被实时替换. 允许的占位符为: + +* **%{project_path}** :将被项目路径替换. +* **%{project_id}** :将被项目 ID 取代. +* **%{default_branch}** :将被项目默认分支替换. +* **%{commit_sha}** :将由上一个项目的提交 SHA 替换. + +由于这些端点不在项目上下文中,因此用于替换占位符的信息将在创建日期之前来自第一组项目. 如果该组没有任何项目,则将返回带有占位符的原始 URL. + +## List all badges of a group[](#list-all-badges-of-a-group "Permalink") + +获取小组徽章的列表. + +``` +GET /groups/:id/badges +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | no | 要返回的徽章名称(区分大小写). | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/badges?name=Coverage" +``` + +响应示例: + +``` +[ { "name": "Coverage", "id": 1, "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", "kind": "group" } ] +``` + +## Get a badge of a group[](#get-a-badge-of-a-group "Permalink") + +获取组的徽章. + +``` +GET /groups/:id/badges/:badge_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `badge_id` | integer | yes | 徽章 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id" +``` + +响应示例: + +``` +{ "id": 1, "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", "kind": "group" } +``` + +## Add a badge to a group[](#add-a-badge-to-a-group "Permalink") + +将徽章添加到组. + +``` +POST /groups/:id/badges +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `link_url` | string | yes | 徽章链接的 URL | +| `image_url` | string | yes | 徽章图片的网址 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --data "link_url=https://gitlab.com/gitlab-org/gitlab-foss/commits/master&image_url=https://shields.io/my/badge1&position=0" "https://gitlab.example.com/api/v4/groups/:id/badges" +``` + +响应示例: + +``` +{ "id": 1, "link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "image_url": "https://shields.io/my/badge1", "rendered_link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "rendered_image_url": "https://shields.io/my/badge1", "kind": "group" } +``` + +## Edit a badge of a group[](#edit-a-badge-of-a-group "Permalink") + +Updates a badge of a group. + +``` +PUT /groups/:id/badges/:badge_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `badge_id` | integer | yes | 徽章 ID | +| `link_url` | string | no | 徽章链接的 URL | +| `image_url` | string | no | 徽章图片的网址 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id" +``` + +响应示例: + +``` +{ "id": 1, "link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "image_url": "https://shields.io/my/badge", "rendered_link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "rendered_image_url": "https://shields.io/my/badge", "kind": "group" } +``` + +## Remove a badge from a group[](#remove-a-badge-from-a-group "Permalink") + +从组中删除徽章. + +``` +DELETE /groups/:id/badges/:badge_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `badge_id` | integer | yes | 徽章 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id" +``` + +## Preview a badge from a group[](#preview-a-badge-from-a-group "Permalink") + +返回解析占位符插值后的`link_url`和`image_url`最终 URL. + +``` +GET /groups/:id/badges/render +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `link_url` | string | yes | 徽章链接的 URL | +| `image_url` | string | yes | 徽章图片的网址 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/badges/render?link_url=http%3A%2F%2Fexample.com%2Fci_status.svg%3Fproject%3D%25%7Bproject_path%7D%26ref%3D%25%7Bdefault_branch%7D&image_url=https%3A%2F%2Fshields.io%2Fmy%2Fbadge" +``` + +响应示例: + +``` +{ "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", } +``` \ No newline at end of file diff --git a/_book/docs/296.md b/_book/docs/296.md new file mode 100644 index 0000000000000000000000000000000000000000..7ed91667a58a1d73509e15dfc0f04a5d5a4ac6d7 --- /dev/null +++ b/_book/docs/296.md @@ -0,0 +1,156 @@ +# Branches API + +> 原文:[https://docs.gitlab.com/ee/api/branches.html](https://docs.gitlab.com/ee/api/branches.html) + +* [List repository branches](#list-repository-branches) +* [Get single repository branch](#get-single-repository-branch) +* [Protect repository branch](#protect-repository-branch) +* [Unprotect repository branch](#unprotect-repository-branch) +* [Create repository branch](#create-repository-branch) +* [Delete repository branch](#delete-repository-branch) +* [Delete merged branches](#delete-merged-branches) + +# Branches API[](#branches-api "Permalink") + +该 API 在[存储库分支上运行](../user/project/repository/branches/index.html) . + +**提示:**另请参阅[受保护的分支机构 API](protected_branches.html) . + +## List repository branches[](#list-repository-branches "Permalink") + +从项目中获取存储库分支的列表,按名称的字母顺序排序. + +**注意:**如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/branches +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `search` | string | no | 返回包含搜索字符串的分支列表. 您可以使用`^term`和`term$`查找分别以`term`开头和结尾的分支. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/branches" +``` + +响应示例: + +``` +[ { "name": "master", "merged": false, "protected": true, "default": true, "developers_can_push": false, "developers_can_merge": false, "can_push": true, "web_url": "http://gitlab.example.com/my-group/my-project/-/tree/master", "commit": { "author_email": "john@example.com", "author_name": "John Smith", "authored_date": "2012-06-27T05:51:39-07:00", "committed_date": "2012-06-28T03:44:20-07:00", "committer_email": "john@example.com", "committer_name": "John Smith", "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c", "short_id": "7b5c3cc", "title": "add projects API", "message": "add projects API", "parent_ids": [ "4ad91d3c1144c406e50c7b33bae684bd6837faf8" ] } }, ... ] +``` + +## Get single repository branch[](#get-single-repository-branch "Permalink") + +获取单个项目存储库分支. + +**注意:**如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/branches/:branch +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `branch` | string | yes | 分支名称. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/branches/master" +``` + +响应示例: + +``` +{ "name": "master", "merged": false, "protected": true, "default": true, "developers_can_push": false, "developers_can_merge": false, "can_push": true, "web_url": "http://gitlab.example.com/my-group/my-project/-/tree/master", "commit": { "author_email": "john@example.com", "author_name": "John Smith", "authored_date": "2012-06-27T05:51:39-07:00", "committed_date": "2012-06-28T03:44:20-07:00", "committer_email": "john@example.com", "committer_name": "John Smith", "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c", "short_id": "7b5c3cc", "title": "add projects API", "message": "add projects API", "parent_ids": [ "4ad91d3c1144c406e50c7b33bae684bd6837faf8" ] } } +``` + +## Protect repository branch[](#protect-repository-branch "Permalink") + +有关保护存储库分支的信息,请参见[`POST /projects/:id/protected_branches`](protected_branches.html#protect-repository-branches) . + +## Unprotect repository branch[](#unprotect-repository-branch "Permalink") + +有关取消保护存储库分支的信息,请参见[`DELETE /projects/:id/protected_branches/:name`](protected_branches.html#unprotect-repository-branches) . + +## Create repository branch[](#create-repository-branch "Permalink") + +在存储库中创建一个新分支. + +``` +POST /projects/:id/repository/branches +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `branch` | string | yes | 分支名称. | +| `ref` | string | yes | 分支名称或提交 SHA 以从中创建分支. | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/branches?branch=newbranch&ref=master" +``` + +响应示例: + +``` +{ "commit": { "author_email": "john@example.com", "author_name": "John Smith", "authored_date": "2012-06-27T05:51:39-07:00", "committed_date": "2012-06-28T03:44:20-07:00", "committer_email": "john@example.com", "committer_name": "John Smith", "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c", "short_id": "7b5c3cc", "title": "add projects API", "message": "add projects API", "parent_ids": [ "4ad91d3c1144c406e50c7b33bae684bd6837faf8" ] }, "name": "newbranch", "merged": false, "protected": false, "default": false, "developers_can_push": false, "developers_can_merge": false, "can_push": true, "web_url": "http://gitlab.example.com/my-group/my-project/-/tree/newbranch" } +``` + +## Delete repository branch[](#delete-repository-branch "Permalink") + +从存储库中删除一个分支. + +**注意:**如果发生错误,将提供说明消息. + +``` +DELETE /projects/:id/repository/branches/:branch +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `branch` | string | yes | 分支名称. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/branches/newbranch" +``` + +## Delete merged branches[](#delete-merged-branches "Permalink") + +Will delete all branches that are merged into the project’s default branch. + +**注意:**此操作不会删除[受保护的分支](../user/project/protected_branches.html) . + +``` +DELETE /projects/:id/repository/merged_branches +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/merged_branches" +``` \ No newline at end of file diff --git a/_book/docs/297.md b/_book/docs/297.md new file mode 100644 index 0000000000000000000000000000000000000000..b2d427473e84f9e14f20e47034b405399dbcf64a --- /dev/null +++ b/_book/docs/297.md @@ -0,0 +1,153 @@ +# Broadcast Messages API + +> 原文:[https://docs.gitlab.com/ee/api/broadcast_messages.html](https://docs.gitlab.com/ee/api/broadcast_messages.html) + +* [Get all broadcast messages](#get-all-broadcast-messages) +* [Get a specific broadcast message](#get-a-specific-broadcast-message) +* [Create a broadcast message](#create-a-broadcast-message) +* [Update a broadcast message](#update-a-broadcast-message) +* [Delete a broadcast message](#delete-a-broadcast-message) + +# Broadcast Messages API[](#broadcast-messages-api "Permalink") + +在 GitLab 8.12 中引入. + +广播消息 API 对[广播消息进行操作](../user/admin_area/broadcast_messages.html) . + +从 GitLab 12.8 开始,GET 请求不需要身份验证. 所有其他广播消息 API 终结点只能由管理员访问. 非 GET 请求者: + +* 来宾将导致`401 Unauthorized` . +* 普通用户将导致`403 Forbidden` . + +## Get all broadcast messages[](#get-all-broadcast-messages "Permalink") + +列出所有广播消息. + +``` +GET /broadcast_messages +``` + +请求示例: + +``` +curl "https://gitlab.example.com/api/v4/broadcast_messages" +``` + +响应示例: + +``` +[ { "message":"Example broadcast message", "starts_at":"2016-08-24T23:21:16.078Z", "ends_at":"2016-08-26T23:21:16.080Z", "color":"#E75E40", "font":"#FFFFFF", "id":1, "active": false, "target_path": "*/welcome", "broadcast_type": "banner", "dismissable": false } ] +``` + +## Get a specific broadcast message[](#get-a-specific-broadcast-message "Permalink") + +获取特定的广播消息. + +``` +GET /broadcast_messages/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要检索的广播消息的 ID. | + +请求示例: + +``` +curl "https://gitlab.example.com/api/v4/broadcast_messages/1" +``` + +响应示例: + +``` +{ "message":"Deploy in progress", "starts_at":"2016-08-24T23:21:16.078Z", "ends_at":"2016-08-26T23:21:16.080Z", "color":"#cecece", "font":"#FFFFFF", "id":1, "active":false, "target_path": "*/welcome", "broadcast_type": "banner", "dismissable": false } +``` + +## Create a broadcast message[](#create-a-broadcast-message "Permalink") + +创建一个新的广播消息. + +``` +POST /broadcast_messages +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `message` | string | yes | 显示的消息. | +| `starts_at` | datetime | no | 开始时间(默认为当前时间). | +| `ends_at` | datetime | no | 结束时间(默认为当前时间的一小时). | +| `color` | string | no | 背景色十六进制代码. | +| `font` | string | no | 前景颜色十六进制代码. | +| `target_path` | string | no | 广播消息的目标路径. | +| `broadcast_type` | string | no | 外观类型(默认为横幅) | +| `dismissable` | boolean | no | 用户可以关闭该消息吗? | + +请求示例: + +``` +curl --data "message=Deploy in progress&color=#cecece" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/broadcast_messages" +``` + +响应示例: + +``` +{ "message":"Deploy in progress", "starts_at":"2016-08-26T00:41:35.060Z", "ends_at":"2016-08-26T01:41:35.060Z", "color":"#cecece", "font":"#FFFFFF", "id":1, "active": true, "target_path": "*/welcome", "broadcast_type": "notification", "dismissable": false } +``` + +## Update a broadcast message[](#update-a-broadcast-message "Permalink") + +更新现有的广播消息. + +``` +PUT /broadcast_messages/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要更新的广播消息的 ID. | +| `message` | string | no | 显示的消息. | +| `starts_at` | datetime | no | 起始时间. | +| `ends_at` | datetime | no | 结束时间. | +| `color` | string | no | 背景色十六进制代码. | +| `font` | string | no | 前景颜色十六进制代码. | +| `target_path` | string | no | 广播消息的目标路径. | +| `broadcast_type` | string | no | 外观类型(默认为横幅) | +| `dismissable` | boolean | no | 用户可以关闭该消息吗? | + +请求示例: + +``` +curl --request PUT --data "message=Update message&color=#000" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/broadcast_messages/1" +``` + +响应示例: + +``` +{ "message":"Update message", "starts_at":"2016-08-26T00:41:35.060Z", "ends_at":"2016-08-26T01:41:35.060Z", "color":"#000", "font":"#FFFFFF", "id":1, "active": true, "target_path": "*/welcome", "broadcast_type": "notification", "dismissable": false } +``` + +## Delete a broadcast message[](#delete-a-broadcast-message "Permalink") + +删除广播消息. + +``` +DELETE /broadcast_messages/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要删除的广播消息的 ID. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/broadcast_messages/1" +``` \ No newline at end of file diff --git a/_book/docs/298.md b/_book/docs/298.md new file mode 100644 index 0000000000000000000000000000000000000000..13889a3a3662f61f2c471f21f36e5349d76b69b5 --- /dev/null +++ b/_book/docs/298.md @@ -0,0 +1,168 @@ +# Project clusters API + +> 原文:[https://docs.gitlab.com/ee/api/project_clusters.html](https://docs.gitlab.com/ee/api/project_clusters.html) + +* [List project clusters](#list-project-clusters) +* [Get a single project cluster](#get-a-single-project-cluster) +* [Add existing cluster to project](#add-existing-cluster-to-project) +* [Edit project cluster](#edit-project-cluster) +* [Delete project cluster](#delete-project-cluster) + +# Project clusters API[](#project-clusters-api "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23922) . + +**注意:**用户将至少需要维护者访问权限才能使用这些端点. + +## List project clusters[](#list-project-clusters "Permalink") + +返回项目集群的列表. + +``` +GET /projects/:id/clusters +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 认证用户拥有的项目的 ID | + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/projects/26/clusters" +``` + +响应示例: + +``` +[ { "id":18, "name":"cluster-1", "domain":"example.com", "created_at":"2019-01-02T20:18:12.563Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"project_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://104.197.68.152", "namespace":"cluster-1-namespace", "authorization_type":"rbac", "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----" }, "management_project": { "id":2, "description":null, "name":"project2", "name_with_namespace":"John Doe8 / project2", "path":"project2", "path_with_namespace":"namespace2/project2", "created_at":"2019-10-11T02:55:54.138Z" } }, { "id":19, "name":"cluster-2", ... } ] +``` + +## Get a single project cluster[](#get-a-single-project-cluster "Permalink") + +获取单个项目集群. + +``` +GET /projects/:id/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 认证用户拥有的项目的 ID | +| `cluster_id` | integer | yes | 集群的 ID | + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/projects/26/clusters/18" +``` + +响应示例: + +``` +{ "id":18, "name":"cluster-1", "domain":"example.com", "created_at":"2019-01-02T20:18:12.563Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"project_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://104.197.68.152", "namespace":"cluster-1-namespace", "authorization_type":"rbac", "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----" }, "management_project": { "id":2, "description":null, "name":"project2", "name_with_namespace":"John Doe8 / project2", "path":"project2", "path_with_namespace":"namespace2/project2", "created_at":"2019-10-11T02:55:54.138Z" }, "project": { "id":26, "description":"", "name":"project-with-clusters-api", "name_with_namespace":"Administrator / project-with-clusters-api", "path":"project-with-clusters-api", "path_with_namespace":"root/project-with-clusters-api", "created_at":"2019-01-02T20:13:32.600Z", "default_branch":null, "tag_list":[], "ssh_url_to_repo":"ssh://gitlab.example.com/root/project-with-clusters-api.git", "http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git", "web_url":"https://gitlab.example.com/root/project-with-clusters-api", "readme_url":null, "avatar_url":null, "star_count":0, "forks_count":0, "last_activity_at":"2019-01-02T20:13:32.600Z", "namespace": { "id":1, "name":"root", "path":"root", "kind":"user", "full_path":"root", "parent_id":null } } } +``` + +## Add existing cluster to project[](#add-existing-cluster-to-project "Permalink") + +将现有的 Kubernetes 集群添加到项目中. + +``` +POST /projects/:id/clusters/user +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 认证用户拥有的项目的 ID | +| `name` | string | yes | 集群名称 | +| `domain` | string | no | 集群的[基础域](../user/project/clusters/index.html#base-domain) | +| `management_project_id` | integer | no | 集群[管理项目](../user/clusters/management_project.html)的 ID | +| `enabled` | boolean | no | 确定集群是否处于活动状态,默认为 true | +| `managed` | boolean | no | Determines if GitLab will manage namespaces and service accounts for this cluster, defaults to true | +| `platform_kubernetes_attributes[api_url]` | string | yes | 访问 Kubernetes API 的 URL | +| `platform_kubernetes_attributes[token]` | string | yes | 针对 Kubernetes 进行身份验证的令牌 | +| `platform_kubernetes_attributes[ca_cert]` | string | no | TLS 证书. 如果 API 使用自签名 TLS 证书,则为必填. | +| `platform_kubernetes_attributes[namespace]` | string | no | 与项目相关的唯一名称空间 | +| `platform_kubernetes_attributes[authorization_type]` | string | no | 集群授权类型: `rbac` , `abac`或`unknown_authorization` . 默认为`rbac` . | +| `environment_scope` | string | no | 集群的关联环境. 默认为`*` | + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/projects/26/clusters/user" \ +-H "Accept: application/json" \ +-H "Content-Type:application/json" \ +-X POST --data '{"name":"cluster-5", "platform_kubernetes_attributes":{"api_url":"https://35.111.51.20","token":"12345","namespace":"cluster-5-namespace","ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----"}}' +``` + +响应示例: + +``` +{ "id":24, "name":"cluster-5", "created_at":"2019-01-03T21:53:40.610Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"project_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://35.111.51.20", "namespace":"cluster-5-namespace", "authorization_type":"rbac", "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----" }, "management_project":null, "project": { "id":26, "description":"", "name":"project-with-clusters-api", "name_with_namespace":"Administrator / project-with-clusters-api", "path":"project-with-clusters-api", "path_with_namespace":"root/project-with-clusters-api", "created_at":"2019-01-02T20:13:32.600Z", "default_branch":null, "tag_list":[], "ssh_url_to_repo":"ssh:://gitlab.example.com/root/project-with-clusters-api.git", "http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git", "web_url":"https://gitlab.example.com/root/project-with-clusters-api", "readme_url":null, "avatar_url":null, "star_count":0, "forks_count":0, "last_activity_at":"2019-01-02T20:13:32.600Z", "namespace": { "id":1, "name":"root", "path":"root", "kind":"user", "full_path":"root", "parent_id":null } } } +``` + +## Edit project cluster[](#edit-project-cluster "Permalink") + +更新现有项目集群. + +``` +PUT /projects/:id/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 认证用户拥有的项目的 ID | +| `cluster_id` | integer | yes | 集群的 ID | +| `name` | string | no | 集群名称 | +| `domain` | string | no | 集群的[基础域](../user/project/clusters/index.html#base-domain) | +| `management_project_id` | integer | no | 集群[管理项目](../user/clusters/management_project.html)的 ID | +| `platform_kubernetes_attributes[api_url]` | string | no | 访问 Kubernetes API 的 URL | +| `platform_kubernetes_attributes[token]` | string | no | 针对 Kubernetes 进行身份验证的令牌 | +| `platform_kubernetes_attributes[ca_cert]` | string | no | TLS 证书. 如果 API 使用自签名 TLS 证书,则为必填. | +| `platform_kubernetes_attributes[namespace]` | string | no | 与项目相关的唯一名称空间 | +| `environment_scope` | string | no | 集群的关联环境 | + +**注意:**仅通过["添加现有 Kubernetes 群集"](../user/project/clusters/add_remove_clusters.html#add-existing-cluster)选项或通过["将现有群集添加到项目"](#add-existing-cluster-to-project)端点[添加群集时,](#add-existing-cluster-to-project)才能更新`name` , `api_url` , `ca_cert`和`token` . + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/projects/26/clusters/24" \ +-H "Content-Type:application/json" \ +-X PUT --data '{"name":"new-cluster-name","domain":"new-domain.com","api_url":"https://new-api-url.com"}' +``` + +响应示例: + +``` +{ "id":24, "name":"new-cluster-name", "domain":"new-domain.com", "created_at":"2019-01-03T21:53:40.610Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"project_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://new-api-url.com", "namespace":"cluster-5-namespace", "authorization_type":"rbac", "ca_cert":null }, "management_project": { "id":2, "description":null, "name":"project2", "name_with_namespace":"John Doe8 / project2", "path":"project2", "path_with_namespace":"namespace2/project2", "created_at":"2019-10-11T02:55:54.138Z" }, "project": { "id":26, "description":"", "name":"project-with-clusters-api", "name_with_namespace":"Administrator / project-with-clusters-api", "path":"project-with-clusters-api", "path_with_namespace":"root/project-with-clusters-api", "created_at":"2019-01-02T20:13:32.600Z", "default_branch":null, "tag_list":[], "ssh_url_to_repo":"ssh:://gitlab.example.com/root/project-with-clusters-api.git", "http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git", "web_url":"https://gitlab.example.com/root/project-with-clusters-api", "readme_url":null, "avatar_url":null, "star_count":0, "forks_count":0, "last_activity_at":"2019-01-02T20:13:32.600Z", "namespace": { "id":1, "name":"root", "path":"root", "kind":"user", "full_path":"root", "parent_id":null } } } +``` + +## Delete project cluster[](#delete-project-cluster "Permalink") + +删除现有项目集群. + +``` +DELETE /projects/:id/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 认证用户拥有的项目的 ID | +| `cluster_id` | integer | yes | 集群的 ID | + +请求示例: + +``` +curl --request DELETE --header "Private-Token: " "https://gitlab.example.com/api/v4/projects/26/clusters/23" +``` \ No newline at end of file diff --git a/_book/docs/299.md b/_book/docs/299.md new file mode 100644 index 0000000000000000000000000000000000000000..21aba4164edbe858cc8de7abde9a9d323194a33a --- /dev/null +++ b/_book/docs/299.md @@ -0,0 +1,166 @@ +# Group clusters API + +> 原文:[https://docs.gitlab.com/ee/api/group_clusters.html](https://docs.gitlab.com/ee/api/group_clusters.html) + +* [List group clusters](#list-group-clusters) +* [Get a single group cluster](#get-a-single-group-cluster) +* [Add existing cluster to group](#add-existing-cluster-to-group) +* [Edit group cluster](#edit-group-cluster) +* [Delete group cluster](#delete-group-cluster) + +# Group clusters API[](#group-clusters-api "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30213) . + +**注意:组**将至少需要用户具有维护者访问权限才能使用这些端点. + +## List group clusters[](#list-group-clusters "Permalink") + +返回组集群的列表. + +``` +GET /groups/:id/clusters +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/groups/26/clusters" +``` + +响应示例: + +``` +[ { "id":18, "name":"cluster-1", "domain":"example.com", "created_at":"2019-01-02T20:18:12.563Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"group_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://104.197.68.152", "authorization_type":"rbac", "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----" }, "management_project": { "id":2, "description":null, "name":"project2", "name_with_namespace":"John Doe8 / project2", "path":"project2", "path_with_namespace":"namespace2/project2", "created_at":"2019-10-11T02:55:54.138Z" } }, { "id":19, "name":"cluster-2", ... } ] +``` + +## Get a single group cluster[](#get-a-single-group-cluster "Permalink") + +获取单个组集群. + +``` +GET /groups/:id/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cluster_id` | integer | yes | 集群的 ID | + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/groups/26/clusters/18" +``` + +响应示例: + +``` +{ "id":18, "name":"cluster-1", "domain":"example.com", "created_at":"2019-01-02T20:18:12.563Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"group_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://104.197.68.152", "authorization_type":"rbac", "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----" }, "management_project": { "id":2, "description":null, "name":"project2", "name_with_namespace":"John Doe8 / project2", "path":"project2", "path_with_namespace":"namespace2/project2", "created_at":"2019-10-11T02:55:54.138Z" }, "group": { "id":26, "name":"group-with-clusters-api", "web_url":"https://gitlab.example.com/group-with-clusters-api" } } +``` + +## Add existing cluster to group[](#add-existing-cluster-to-group "Permalink") + +将现有的 Kubernetes 集群添加到组中. + +``` +POST /groups/:id/clusters/user +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 集群名称 | +| `domain` | string | no | 集群的[基础域](../user/group/clusters/index.html#base-domain) | +| `management_project_id` | integer | no | 集群[管理项目](../user/clusters/management_project.html)的 ID | +| `enabled` | boolean | no | 确定集群是否处于活动状态,默认为 true | +| `managed` | boolean | no | 确定 GitLab 是否将管理该集群的名称空间和服务帐户,默认为 true | +| `platform_kubernetes_attributes[api_url]` | string | yes | 访问 Kubernetes API 的 URL | +| `platform_kubernetes_attributes[token]` | string | yes | 针对 Kubernetes 进行身份验证的令牌 | +| `platform_kubernetes_attributes[ca_cert]` | string | no | TLS 证书. 如果 API 使用自签名 TLS 证书,则为必填. | +| `platform_kubernetes_attributes[authorization_type]` | string | no | 集群授权类型: `rbac` , `abac`或`unknown_authorization` . 默认为`rbac` . | +| `environment_scope` | string | no | 集群的关联环境. 默认为`*` | + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/groups/26/clusters/user" \ +-H "Accept: application/json" \ +-H "Content-Type:application/json" \ +--request POST --data '{"name":"cluster-5", "platform_kubernetes_attributes":{"api_url":"https://35.111.51.20","token":"12345","ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----"}}' +``` + +响应示例: + +``` +{ "id":24, "name":"cluster-5", "created_at":"2019-01-03T21:53:40.610Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"group_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://35.111.51.20", "authorization_type":"rbac", "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----" }, "management_project":null, "group": { "id":26, "name":"group-with-clusters-api", "web_url":"https://gitlab.example.com/root/group-with-clusters-api" } } +``` + +## Edit group cluster[](#edit-group-cluster "Permalink") + +更新现有的组群集. + +``` +PUT /groups/:id/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cluster_id` | integer | yes | 集群的 ID | +| `name` | string | no | 集群名称 | +| `domain` | string | no | 集群的[基础域](../user/group/clusters/index.html#base-domain) | +| `management_project_id` | integer | no | 集群[管理项目](../user/clusters/management_project.html)的 ID | +| `platform_kubernetes_attributes[api_url]` | string | no | 访问 Kubernetes API 的 URL | +| `platform_kubernetes_attributes[token]` | string | no | 针对 Kubernetes 进行身份验证的令牌 | +| `platform_kubernetes_attributes[ca_cert]` | string | no | TLS 证书. 如果 API 使用自签名 TLS 证书,则为必填. | +| `environment_scope` | string | no | 集群的关联环境 | + +**注意:**仅通过["添加现有 Kubernetes 群集"](../user/project/clusters/add_remove_clusters.html#add-existing-cluster)选项或通过["将现有群集添加到组"](#add-existing-cluster-to-group)端点[添加群集时,](#add-existing-cluster-to-group)才能更新`name` , `api_url` , `ca_cert`和`token` . + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/groups/26/clusters/24" \ +-H "Content-Type:application/json" \ +--request PUT --data '{"name":"new-cluster-name","domain":"new-domain.com","api_url":"https://new-api-url.com"}' +``` + +响应示例: + +``` +{ "id":24, "name":"new-cluster-name", "domain":"new-domain.com", "created_at":"2019-01-03T21:53:40.610Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"group_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://new-api-url.com", "authorization_type":"rbac", "ca_cert":null }, "management_project": { "id":2, "description":null, "name":"project2", "name_with_namespace":"John Doe8 / project2", "path":"project2", "path_with_namespace":"namespace2/project2", "created_at":"2019-10-11T02:55:54.138Z" }, "group": { "id":26, "name":"group-with-clusters-api", "web_url":"https://gitlab.example.com/group-with-clusters-api" } } +``` + +## Delete group cluster[](#delete-group-cluster "Permalink") + +删除现有的组群集. + +``` +DELETE /groups/:id/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cluster_id` | integer | yes | 集群的 ID | + +请求示例: + +``` +curl --request DELETE --header "Private-Token: " "https://gitlab.example.com/api/v4/groups/26/clusters/23" +``` \ No newline at end of file diff --git a/_book/docs/300.md b/_book/docs/300.md new file mode 100644 index 0000000000000000000000000000000000000000..03badc2b38ab4b5937b6ab437296ead554f41df4 --- /dev/null +++ b/_book/docs/300.md @@ -0,0 +1,161 @@ +# Instance clusters API + +> 原文:[https://docs.gitlab.com/ee/api/instance_clusters.html](https://docs.gitlab.com/ee/api/instance_clusters.html) + +* [List instance clusters](#list-instance-clusters) +* [Get a single instance cluster](#get-a-single-instance-cluster) +* [Add existing instance cluster](#add-existing-instance-cluster) +* [Edit instance cluster](#edit-instance-cluster) +* [Delete instance cluster](#delete-instance-cluster) + +# Instance clusters API[](#instance-clusters-api "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36001) . + +**注意:**用户将需要管理员权限才能使用这些端点. + +将这些 API 端点与实例集群一起使用,使您可以在多个项目中使用同一集群. [更多信息](../user/instance/clusters/index.html) + +## List instance clusters[](#list-instance-clusters "Permalink") + +返回实例集群的列表. + +``` +GET /admin/clusters +``` + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/admin/clusters" +``` + +响应示例: + +``` +[ { "id": 9, "name": "cluster-1", "created_at": "2020-07-14T18:36:10.440Z", "domain": null, "provider_type": "user", "platform_type": "kubernetes", "environment_scope": "*", "cluster_type": "instance_type", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url": "https://example.com", "namespace": null, "authorization_type": "rbac", "ca_cert":"-----BEGIN CERTIFICATE-----IxMDM1MV0ZDJkZjM...-----END CERTIFICATE-----" }, "provider_gcp": null, "management_project": null }, { "id": 10, "name": "cluster-2", "created_at": "2020-07-14T18:39:05.383Z", "domain": null, "provider_type": "user", "platform_type": "kubernetes", "environment_scope": "staging", "cluster_type": "instance_type", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url": "https://example.com", "namespace": null, "authorization_type": "rbac", "ca_cert":"-----BEGIN CERTIFICATE-----LzEtMCadtaLGxcsGAZjM...-----END CERTIFICATE-----" }, "provider_gcp": null, "management_project": null } { "id": 11, "name": "cluster-3", ... } ] +``` + +## Get a single instance cluster[](#get-a-single-instance-cluster "Permalink") + +返回单个实例集群. + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `cluster_id` | integer | yes | 集群的 ID | + +``` +GET /admin/clusters/:cluster_id +``` + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/admin/clusters/9" +``` + +响应示例: + +``` +{ "id": 9, "name": "cluster-1", "created_at": "2020-07-14T18:36:10.440Z", "domain": null, "provider_type": "user", "platform_type": "kubernetes", "environment_scope": "*", "cluster_type": "instance_type", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url": "https://example.com", "namespace": null, "authorization_type": "rbac", "ca_cert":"-----BEGIN CERTIFICATE-----IxMDM1MV0ZDJkZjM...-----END CERTIFICATE-----" }, "provider_gcp": null, "management_project": null } +``` + +## Add existing instance cluster[](#add-existing-instance-cluster "Permalink") + +添加现有的 Kubernetes 实例集群. + +``` +POST /admin/clusters/add +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | string | yes | 集群名称 | +| `domain` | string | no | 集群的[基础域](../user/project/clusters/index.html#base-domain) | +| `environment_scope` | string | no | 集群的关联环境. 默认为`*` | +| `management_project_id` | integer | no | The ID of the [management project](../user/clusters/management_project.html) for the cluster | +| `enabled` | boolean | no | 确定集群是否处于活动状态,默认为 true | +| `managed` | boolean | no | 确定 GitLab 是否将管理该集群的名称空间和服务帐户,默认为 true | +| `platform_kubernetes_attributes[api_url]` | string | yes | 访问 Kubernetes API 的 URL | +| `platform_kubernetes_attributes[token]` | string | yes | 针对 Kubernetes 进行身份验证的令牌 | +| `platform_kubernetes_attributes[ca_cert]` | string | no | TLS 证书. 如果 API 使用自签名 TLS 证书,则为必填. | +| `platform_kubernetes_attributes[namespace]` | string | no | 与项目相关的唯一名称空间 | +| `platform_kubernetes_attributes[authorization_type]` | string | no | 集群授权类型: `rbac` , `abac`或`unknown_authorization` . 默认为`rbac` . | + +请求示例: + +``` +curl --header "Private-Token:" "http://gitlab.example.com/api/v4/admin/clusters/add" \ +-H "Accept:application/json" \ +-H "Content-Type:application/json" \ +-X POST --data '{"name":"cluster-3", "environment_scope":"production", "platform_kubernetes_attributes":{"api_url":"https://example.com", "token":"12345", "ca_cert":"-----BEGIN CERTIFICATE-----qpoeiXXZafCM0ZDJkZjM...-----END CERTIFICATE-----"}}' +``` + +响应示例: + +``` +{ "id": 11, "name": "cluster-3", "created_at": "2020-07-14T18:42:50.805Z", "domain": null, "provider_type": "user", "platform_type": "kubernetes", "environment_scope": "production", "cluster_type": "instance_type", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com:3000/root" }, "platform_kubernetes": { "api_url": "https://example.com", "namespace": null, "authorization_type": "rbac", "ca_cert":"-----BEGIN CERTIFICATE-----qpoeiXXZafCM0ZDJkZjM...-----END CERTIFICATE-----" }, "provider_gcp": null, "management_project": null } +``` + +## Edit instance cluster[](#edit-instance-cluster "Permalink") + +更新现有的实例集群. + +``` +PUT /admin/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `cluster_id` | integer | yes | 集群的 ID | +| `name` | string | no | 集群名称 | +| `domain` | string | no | 集群的[基础域](../user/project/clusters/index.html#base-domain) | +| `environment_scope` | string | no | 集群的关联环境 | +| `management_project_id` | integer | no | 集群[管理项目](../user/clusters/management_project.html)的 ID | +| `enabled` | boolean | no | 确定集群是否处于活动状态,默认为 true | +| `platform_kubernetes_attributes[api_url]` | string | no | 访问 Kubernetes API 的 URL | +| `platform_kubernetes_attributes[token]` | string | no | 针对 Kubernetes 进行身份验证的令牌 | +| `platform_kubernetes_attributes[ca_cert]` | string | no | TLS 证书. 如果 API 使用自签名 TLS 证书,则为必填. | +| `platform_kubernetes_attributes[namespace]` | string | no | 与项目相关的唯一名称空间 | + +**注意:**仅通过通过[添加现有 Kubernetes 集群](../user/project/clusters/add_remove_clusters.html#add-existing-cluster)选项或通过[添加现有实例集群](#add-existing-instance-cluster)端点[添加](#add-existing-instance-cluster)集群时,才能更新`name` , `api_url` , `ca_cert`和`token` . + +请求示例: + +``` +curl --header "Private-Token: " "http://gitlab.example.com/api/v4/admin/clusters/9" \ +-H "Content-Type:application/json" \ +-X PUT --data '{"name":"update-cluster-name", "platform_kubernetes_attributes":{"api_url":"https://new-example.com","token":"new-token"}}' +``` + +响应示例: + +``` +{ "id": 9, "name": "update-cluster-name", "created_at": "2020-07-14T18:36:10.440Z", "domain": null, "provider_type": "user", "platform_type": "kubernetes", "environment_scope": "*", "cluster_type": "instance_type", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url": "https://new-example.com", "namespace": null, "authorization_type": "rbac", "ca_cert":"-----BEGIN CERTIFICATE-----IxMDM1MV0ZDJkZjM...-----END CERTIFICATE-----" }, "provider_gcp": null, "management_project": null, "project": null } +``` + +## Delete instance cluster[](#delete-instance-cluster "Permalink") + +删除现有的实例集群. + +``` +DELETE /admin/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `cluster_id` | integer | yes | 集群的 ID | + +请求示例: + +``` +curl --request DELETE --header "Private-Token: " "https://gitlab.example.com/api/v4/admin/clusters/11" +``` \ No newline at end of file diff --git a/_book/docs/301.md b/_book/docs/301.md new file mode 100644 index 0000000000000000000000000000000000000000..ef16eb6110474bc010f6716322e676df2bc6792c --- /dev/null +++ b/_book/docs/301.md @@ -0,0 +1,514 @@ +# Commits API + +> 原文:[https://docs.gitlab.com/ee/api/commits.html](https://docs.gitlab.com/ee/api/commits.html) + +* [List repository commits](#list-repository-commits) +* [Create a commit with multiple files and actions](#create-a-commit-with-multiple-files-and-actions) +* [Get a single commit](#get-a-single-commit) +* [Get references a commit is pushed to](#get-references-a-commit-is-pushed-to) +* [Cherry pick a commit](#cherry-pick-a-commit) +* [Revert a commit](#revert-a-commit) +* [Get the diff of a commit](#get-the-diff-of-a-commit) +* [Get the comments of a commit](#get-the-comments-of-a-commit) +* [Post comment to commit](#post-comment-to-commit) +* [Get the discussions of a commit](#get-the-discussions-of-a-commit) +* [Commit status](#commit-status) + * [List the statuses of a commit](#list-the-statuses-of-a-commit) + * [Post the build status to a commit](#post-the-build-status-to-a-commit) +* [List Merge Requests associated with a commit](#list-merge-requests-associated-with-a-commit) +* [Get GPG signature of a commit](#get-gpg-signature-of-a-commit) + +# Commits API[](#commits-api "Permalink") + +## List repository commits[](#list-repository-commits "Permalink") + +获取项目中存储库提交的列表. + +``` +GET /projects/:id/repository/commits +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `ref_name` | string | no | 存储库分支的名称,标签或修订范围,或者如果未提供默认分支 | +| `since` | string | no | 仅此日期之后的提交将以 ISO 8601 格式返回 YYYY-MM-DDTHH:MM:SSZ | +| `until` | string | no | 仅在此日期之前或当天的提交将以 ISO 8601 格式返回 YYYY-MM-DDTHH:MM:SSZ | +| `path` | string | no | 文件路径 | +| `all` | boolean | no | 从存储库中检索每个提交 | +| `with_stats` | boolean | no | 有关每次提交的统计信息将添加到响应中 | +| `first_parent` | boolean | no | 看到合并提交后,仅关注第一个父提交 | +| `order` | string | no | 按顺序列出提交. 可能的值: `default` , [`topo`](https://git-scm.com/docs/git-log#Documentation/git-log.txt---topo-order) . 默认设置为`default` ,提交按时间倒序显示. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits" +``` + +响应示例: + +``` +[ { "id": "ed899a2f4b50b4370feeea94676502b42383c746", "short_id": "ed899a2f4b5", "title": "Replace sanitize with escape once", "author_name": "Example User", "author_email": "user@example.com", "authored_date": "2012-09-20T11:50:22+03:00", "committer_name": "Administrator", "committer_email": "admin@example.com", "committed_date": "2012-09-20T11:50:22+03:00", "created_at": "2012-09-20T11:50:22+03:00", "message": "Replace sanitize with escape once", "parent_ids": [ "6104942438c14ec7bd21c6cd5bd995272b3faff6" ], "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746" }, { "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", "short_id": "6104942438c", "title": "Sanitize for network graph", "author_name": "randx", "author_email": "user@example.com", "committer_name": "ExampleName", "committer_email": "user@example.com", "created_at": "2012-09-20T09:06:12+03:00", "message": "Sanitize for network graph", "parent_ids": [ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" ], "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746" } ] +``` + +## Create a commit with multiple files and actions[](#create-a-commit-with-multiple-files-and-actions "Permalink") + +在 GitLab 8.13 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6096) . + +通过发布 JSON 有效负载来创建提交 + +``` +POST /projects/:id/repository/commits +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `branch` | string | yes | 要提交的分支名称. 要创建一个新分支,还提供`start_branch`或`start_sha` ,还可以提供`start_project` . | +| `commit_message` | string | yes | 提交讯息 | +| `start_branch` | string | no | 从中开始新分支的分支名称 | +| `start_sha` | string | no | 从以下位置启动新分支的提交的 SHA | +| `start_project` | integer/string | no | 从中开始新分支的项目 ID 或项目的[URL 编码路径](README.html#namespaced-path-encoding) . 默认为`id`的值. | +| `actions[]` | array | yes | 动作哈希数组要批量提交. 请参阅下表以了解它可以采用的属性. | +| `author_email` | string | no | 指定提交作者的电子邮件地址 | +| `author_name` | string | no | 指定提交作者的姓名 | +| `stats` | boolean | no | 包括提交统计信息. 默认为 true | +| `force` | boolean | no | 如果为`true`则基于`start_branch`或`start_sha`的新提交覆盖目标分支 | + +| `actions[]` Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `action` | string | yes | 执行, `create` , `delete` , `move` , `update` , `chmod` | +| `file_path` | string | yes | 文件的完整路径. 例如 `lib/class.rb` | +| `previous_path` | string | no | 要移动文件的原始完整路径. 例如 `lib/class1.rb` . 仅考虑`move`动作. | +| `content` | string | no | 除`delete` , `chmod`和`move`以外的所有文件所必需的文件内容. 未指定`content`移动动作将保留现有文件内容,而任何其他`content`值都将覆盖文件内容. | +| `encoding` | string | no | `text`或`base64` . `text`是默认值. | +| `last_commit_id` | string | no | 上次已知的文件提交 ID. 仅在更新,移动和删除操作中考虑. | +| `execute_filemode` | boolean | no | 当为`true/false`启用/禁用文件上的 execute 标志. 仅考虑用于`chmod`操作. | + +``` +PAYLOAD=$(cat << 'JSON' +{ + "branch": "master", + "commit_message": "some commit message", + "actions": [ + { + "action": "create", + "file_path": "foo/bar", + "content": "some content" + }, + { + "action": "delete", + "file_path": "foo/bar2" + }, + { + "action": "move", + "file_path": "foo/bar3", + "previous_path": "foo/bar4", + "content": "some content" + }, + { + "action": "update", + "file_path": "foo/bar5", + "content": "new content" + }, + { + "action": "chmod", + "file_path": "foo/bar5", + "execute_filemode": true + } + ] +} JSON ) +curl --request POST --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" --data "$PAYLOAD" "https://gitlab.example.com/api/v4/projects/1/repository/commits" +``` + +响应示例: + +``` +{ "id": "ed899a2f4b50b4370feeea94676502b42383c746", "short_id": "ed899a2f4b5", "title": "some commit message", "author_name": "Example User", "author_email": "user@example.com", "committer_name": "Example User", "committer_email": "user@example.com", "created_at": "2016-09-20T09:26:24.000-07:00", "message": "some commit message", "parent_ids": [ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" ], "committed_date": "2016-09-20T09:26:24.000-07:00", "authored_date": "2016-09-20T09:26:24.000-07:00", "stats": { "additions": 2, "deletions": 2, "total": 4 }, "status": null, "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746" } +``` + +GitLab 支持[表单编码](README.html#encoding-api-parameters-of-array-and-hash-types) . 以下是使用 Commit API 和表单编码的示例: + +``` +curl --request POST \ + --form "branch=master" \ + --form "commit_message=some commit message" \ + --form "start_branch=master" \ + --form "actions[][action]=create" \ + --form "actions[][file_path]=foo/bar" \ + --form "actions[][content]=" \ + "https://gitlab.example.com/api/v4/projects/1/repository/commits" +``` + +## Get a single commit[](#get-a-single-commit "Permalink") + +获取由提交哈希或分支或标记的名称标识的特定提交. + +``` +GET /projects/:id/repository/commits/:sha +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希或存储库分支或标记的名称 | +| `stats` | boolean | no | 包括提交统计信息. 默认为 true | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits/master" +``` + +响应示例: + +``` +{ "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", "short_id": "6104942438c", "title": "Sanitize for network graph", "author_name": "randx", "author_email": "user@example.com", "committer_name": "Dmitriy", "committer_email": "user@example.com", "created_at": "2012-09-20T09:06:12+03:00", "message": "Sanitize for network graph", "committed_date": "2012-09-20T09:06:12+03:00", "authored_date": "2012-09-20T09:06:12+03:00", "parent_ids": [ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" ], "last_pipeline" : { "id": 8, "ref": "master", "sha": "2dc6aa325a317eda67812f05600bdf0fcdc70ab0", "status": "created" }, "stats": { "additions": 15, "deletions": 10, "total": 25 }, "status": "running", "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/6104942438c14ec7bd21c6cd5bd995272b3faff6" } +``` + +## Get references a commit is pushed to[](#get-references-a-commit-is-pushed-to "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15026) + +获取提交已提交的所有引用(从分支或标签). 分页参数`page`和`per_page`可用于限制引用列表. + +``` +GET /projects/:id/repository/commits/:sha/refs +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希 | +| `type` | string | no | 提交范围. 可能的值是`branch` , `tag` , `all` . 默认为`all` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits/5937ac0a7beb003549fc5fd26fc247adbce4a52e/refs?type=all" +``` + +Example response: + +``` +[ {"type": "branch", "name": "'test'"}, {"type": "branch", "name": "add-balsamiq-file"}, {"type": "branch", "name": "wip"}, {"type": "tag", "name": "v1.1.0"} ] +``` + +## Cherry pick a commit[](#cherry-pick-a-commit "Permalink") + +在 GitLab 8.15 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8047) . + +Cherry 选择了对给定分支的提交. + +``` +POST /projects/:id/repository/commits/:sha/cherry_pick +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希 | +| `branch` | string | yes | 分支名称 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/cherry_pick" +``` + +响应示例: + +``` +{ "id": "8b090c1b79a14f2bd9e8a738f717824ff53aebad", "short_id": "8b090c1b", "title": "Feature added", "author_name": "Example User", "author_email": "user@example.com", "authored_date": "2016-12-12T20:10:39.000+01:00", "created_at": "2016-12-12T20:10:39.000+01:00", "committer_name": "Administrator", "committer_email": "admin@example.com", "committed_date": "2016-12-12T20:10:39.000+01:00", "title": "Feature added", "message": "Feature added\n\nSigned-off-by: Example User \n", "parent_ids": [ "a738f717824ff53aebad8b090c1b79a14f2bd9e8" ], "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/8b090c1b79a14f2bd9e8a738f717824ff53aebad" } +``` + +如果选择失败,响应将提供有关以下原因的上下文: + +``` +{ "message": "Sorry, we cannot cherry-pick this commit automatically. This commit may already have been cherry-picked, or a more recent commit may have updated some of its content.", "error_code": "empty" } +``` + +在这种情况下,cherry-pick 失败,因为变更集为空,并且很可能表明提交已存在于目标分支中. 另一个可能的错误代码是`conflict` ,表示存在合并冲突. + +## Revert a commit[](#revert-a-commit "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22919) . + +恢复给定分支中的提交. + +``` +POST /projects/:id/repository/commits/:sha/revert +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交 SHA 还原 | +| `branch` | string | yes | 目标分支名称 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/a738f717824ff53aebad8b090c1b79a14f2bd9e8/revert" +``` + +响应示例: + +``` +{ "id":"8b090c1b79a14f2bd9e8a738f717824ff53aebad", "short_id": "8b090c1b", "title":"Revert \"Feature added\"", "created_at":"2018-11-08T15:55:26.000Z", "parent_ids":["a738f717824ff53aebad8b090c1b79a14f2bd9e8"], "message":"Revert \"Feature added\"\n\nThis reverts commit a738f717824ff53aebad8b090c1b79a14f2bd9e8", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2018-11-08T15:55:26.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2018-11-08T15:55:26.000Z", "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/8b090c1b79a14f2bd9e8a738f717824ff53aebad" } +``` + +如果还原失败,则响应将提供有关以下原因的上下文: + +``` +{ "message": "Sorry, we cannot revert this commit automatically. This commit may already have been reverted, or a more recent commit may have updated some of its content.", "error_code": "conflict" } +``` + +在这种情况下,还原失败,因为尝试的还原产生了合并冲突. 另一个可能的错误代码为`empty` ,表明变更集为空,这可能是由于变更已被还原. + +## Get the diff of a commit[](#get-the-diff-of-a-commit "Permalink") + +获取项目中提交的差异. + +``` +GET /projects/:id/repository/commits/:sha/diff +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希或存储库分支或标记的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/diff" +``` + +响应示例: + +``` +[ { "diff": "--- a/doc/update/5.4-to-6.0.md\n+++ b/doc/update/5.4-to-6.0.md\n@@ -71,6 +71,8 @@\n sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production\n sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production\n \n+sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production\n+\n ```\n \n ### 6\. Update config files", "new_path": "doc/update/5.4-to-6.0.md", "old_path": "doc/update/5.4-to-6.0.md", "a_mode": null, "b_mode": "100644", "new_file": false, "renamed_file": false, "deleted_file": false } ] +``` + +## Get the comments of a commit[](#get-the-comments-of-a-commit "Permalink") + +获取项目中提交的注释. + +``` +GET /projects/:id/repository/commits/:sha/comments +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希或存储库分支或标记的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/comments" +``` + +响应示例: + +``` +[ { "note": "this code is really nice", "author": { "id": 11, "username": "admin", "email": "admin@local.host", "name": "Administrator", "state": "active", "created_at": "2014-03-06T08:17:35.000Z" } } ] +``` + +## Post comment to commit[](#post-comment-to-commit "Permalink") + +在提交中添加评论. + +为了在特定文件的特定行中发布评论,您必须指定完整的提交 SHA, `path` , `line`和`line_type`应该是`new` . + +如果以下至少一种情况有效,则注释将在最后一次提交的末尾添加: + +* 相反, `sha`是分支或标签,并且`line`或`path`无效 +* `line`号无效(不存在) +* `path`无效(不存在) + +在上述任何情况下, `line` , `line_type`和`path`的响应都设置为`null` . + +``` +POST /projects/:id/repository/commits/:sha/comments +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交 SHA 或存储库分支或标记的名称 | +| `note` | string | yes | 评论文字 | +| `path` | string | no | 相对于存储库的文件路径 | +| `line` | integer | no | 放置评论的行号 | +| `line_type` | string | no | 线型. 采用`new`或`old`的争论 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "note=Nice picture man\!" --form "path=dudeism.md" --form "line=11" --form "line_type=new" "https://gitlab.example.com/api/v4/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/comments" +``` + +响应示例: + +``` +{ "author" : { "web_url" : "https://gitlab.example.com/thedude", "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png", "username" : "thedude", "state" : "active", "name" : "Jeff Lebowski", "id" : 28 }, "created_at" : "2016-01-19T09:44:55.600Z", "line_type" : "new", "path" : "dudeism.md", "line" : 11, "note" : "Nice picture man!" } +``` + +## Get the discussions of a commit[](#get-the-discussions-of-a-commit "Permalink") + +获取项目中提交的讨论. + +``` +GET /projects/:id/repository/commits/:sha/discussions +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希或存储库分支或标记的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits/4604744a1c64de00ff62e1e8a6766919923d2b41/discussions" +``` + +响应示例: + +``` +[ { "id": "4604744a1c64de00ff62e1e8a6766919923d2b41", "individual_note": true, "notes": [ { "id": 334686748, "type": null, "body": "I'm the Dude, so that's what you call me.", "attachment": null, "author" : { "id" : 28, "name" : "Jeff Lebowski", "username" : "thedude", "web_url" : "https://gitlab.example.com/thedude", "state" : "active", "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png" }, "created_at": "2020-04-30T18:48:11.432Z", "updated_at": "2020-04-30T18:48:11.432Z", "system": false, "noteable_id": null, "noteable_type": "Commit", "resolvable": false, "confidential": null, "noteable_iid": null, "commands_changes": {} } ] } ] +``` + +## Commit status[](#commit-status "Permalink") + +从 GitLab 8.1 开始,这是新的提交状态 API. + +### List the statuses of a commit[](#list-the-statuses-of-a-commit "Permalink") + +列出项目中提交的状态. 分页参数`page`和`per_page`可用于限制引用列表. + +``` +GET /projects/:id/repository/commits/:sha/statuses +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交 SHA | +| `ref` | string | no | The name of a repository branch or tag or, if not given, the default branch | +| `stage` | string | no | 按[构建阶段](../ci/yaml/README.html#stages)过滤,例如`test` | +| `name` | string | no | 按[工作名称](../ci/yaml/README.html#introduction)过滤,例如`bundler:audit` | +| `all` | boolean | no | 返回所有状态,不仅是最新状态 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/statuses +``` + +响应示例: + +``` +[ ... { "status" : "pending", "created_at" : "2016-01-19T08:40:25.934Z", "started_at" : null, "name" : "bundler:audit", "allow_failure" : true, "author" : { "username" : "thedude", "state" : "active", "web_url" : "https://gitlab.example.com/thedude", "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png", "id" : 28, "name" : "Jeff Lebowski" }, "description" : null, "sha" : "18f3e63d05582537db6d183d9d557be09e1f90c8", "target_url" : "https://gitlab.example.com/thedude/gitlab-foss/builds/91", "finished_at" : null, "id" : 91, "ref" : "master" }, { "started_at" : null, "name" : "test", "allow_failure" : false, "status" : "pending", "created_at" : "2016-01-19T08:40:25.832Z", "target_url" : "https://gitlab.example.com/thedude/gitlab-foss/builds/90", "id" : 90, "finished_at" : null, "ref" : "master", "sha" : "18f3e63d05582537db6d183d9d557be09e1f90c8", "author" : { "id" : 28, "name" : "Jeff Lebowski", "username" : "thedude", "web_url" : "https://gitlab.example.com/thedude", "state" : "active", "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png" }, "description" : null }, ... ] +``` + +### Post the build status to a commit[](#post-the-build-status-to-a-commit "Permalink") + +添加或更新提交的构建状态. + +``` +POST /projects/:id/statuses/:sha +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交 SHA | +| `state` | string | yes | 状态的状态. 可以是以下之一: `pending` , `running` , `success` , `failed` , `canceled` | +| `ref` | string | no | 状态所`ref` (分支或标签) | +| `name` or `context` | string | no | 区分此状态和其他系统状态的标签. 默认值是`default` | +| `target_url` | string | no | 与该状态关联的目标 URL | +| `description` | string | no | 状态的简短描述 | +| `coverage` | float | no | 总代码覆盖率 | +| `pipeline_id` | integer | no | 要设置状态的管道的 ID. 在同一 SHA 上有多个管道的情况下使用. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/17/statuses/18f3e63d05582537db6d183d9d557be09e1f90c8?state=success" +``` + +响应示例: + +``` +{ "author" : { "web_url" : "https://gitlab.example.com/thedude", "name" : "Jeff Lebowski", "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png", "username" : "thedude", "state" : "active", "id" : 28 }, "name" : "default", "sha" : "18f3e63d05582537db6d183d9d557be09e1f90c8", "status" : "success", "coverage": 100.0, "description" : null, "id" : 93, "target_url" : null, "ref" : null, "started_at" : null, "created_at" : "2016-01-19T09:05:50.355Z", "allow_failure" : false, "finished_at" : "2016-01-19T09:05:50.365Z" } +``` + +## List Merge Requests associated with a commit[](#list-merge-requests-associated-with-a-commit "Permalink") + +在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18004) . + +获取与指定提交相关的合并请求列表. + +``` +GET /projects/:id/repository/commits/:sha/merge_requests +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交 SHA | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits/af5b13261899fb2c0db30abdd0af8b07cb44fdc5/merge_requests" +``` + +响应示例: + +``` +[ { "id":45, "iid":1, "project_id":35, "title":"Add new file", "description":"", "state":"opened", "created_at":"2018-03-26T17:26:30.916Z", "updated_at":"2018-03-26T17:26:30.916Z", "target_branch":"master", "source_branch":"test-branch", "upvotes":0, "downvotes":0, "author" : { "web_url" : "https://gitlab.example.com/thedude", "name" : "Jeff Lebowski", "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png", "username" : "thedude", "state" : "active", "id" : 28 }, "assignee":null, "source_project_id":35, "target_project_id":35, "labels":[ ], "work_in_progress":false, "milestone":null, "merge_when_pipeline_succeeds":false, "merge_status":"can_be_merged", "sha":"af5b13261899fb2c0db30abdd0af8b07cb44fdc5", "merge_commit_sha":null, "squash_commit_sha":null, "user_notes_count":0, "discussion_locked":null, "should_remove_source_branch":null, "force_remove_source_branch":false, "web_url":"http://https://gitlab.example.com/root/test-project/merge_requests/1", "time_stats":{ "time_estimate":0, "total_time_spent":0, "human_time_estimate":null, "human_total_time_spent":null } } ] +``` + +## Get GPG signature of a commit[](#get-gpg-signature-of-a-commit "Permalink") + +[从提交](../user/project/repository/gpg_signed_commits/index.html)获取[GPG 签名](../user/project/repository/gpg_signed_commits/index.html) (如果已签名). 对于未签名的提交,将导致 404 响应. + +``` +GET /projects/:id/repository/commits/:sha/signature +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希或存储库分支或标记的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/repository/commits/da738facbc19eb2fc2cef57c49be0e6038570352/signature" +``` + +如果提交是由 GPG 签名的,则示例响应: + +``` +{ "signature_type": "PGP", "verification_status": "verified", "gpg_key_id": 1, "gpg_key_primary_keyid": "8254AAB3FBD54AC9", "gpg_key_user_name": "John Doe", "gpg_key_user_email": "johndoe@example.com", "gpg_key_subkey_id": null } +``` + +如果提交是 X.509 签名的示例响应: + +``` +{ "signature_type": "X509", "verification_status": "unverified", "x509_certificate": { "id": 1, "subject": "CN=gitlab@example.org,OU=Example,O=World", "subject_key_identifier": "BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC", "email": "gitlab@example.org", "serial_number": 278969561018901340486471282831158785578, "certificate_status": "good", "x509_issuer": { "id": 1, "subject": "CN=PKI,OU=Example,O=World", "subject_key_identifier": "AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB", "crl_url": "http://example.com/pki.crl" } } } +``` + +如果提交是未签名的,示例响应: + +``` +{ "message": "404 GPG Signature Not Found" } +``` \ No newline at end of file diff --git a/_book/docs/302.md b/_book/docs/302.md new file mode 100644 index 0000000000000000000000000000000000000000..8081312eb4a0b18d494f79578acaba93ef5406cc --- /dev/null +++ b/_book/docs/302.md @@ -0,0 +1,218 @@ +# Container Registry API + +> 原文:[https://docs.gitlab.com/ee/api/container_registry.html](https://docs.gitlab.com/ee/api/container_registry.html) + +* [List registry repositories](#list-registry-repositories) + * [Within a project](#within-a-project) + * [Within a group](#within-a-group) +* [Delete registry repository](#delete-registry-repository) +* [List registry repository tags](#list-registry-repository-tags) + * [Within a project](#within-a-project-1) +* [Get details of a registry repository tag](#get-details-of-a-registry-repository-tag) +* [Delete a registry repository tag](#delete-a-registry-repository-tag) +* [Delete registry repository tags in bulk](#delete-registry-repository-tags-in-bulk) + +# Container Registry API[](#container-registry-api "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55978) . + +这是[GitLab 容器注册表](../user/packages/container_registry/index.html)的 API 文档. + +## List registry repositories[](#list-registry-repositories "Permalink") + +### Within a project[](#within-a-project "Permalink") + +获取项目中的注册表存储库列表. + +``` +GET /projects/:id/registry/repositories +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户可以访问[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `tags` | boolean | no | 如果参数包含为 true,则每个存储库在响应中都将包含一个`"tags"`数组. | +| `name` | string | no | 返回名称与值匹配的存储库列表. (在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29763) ). | +| `tags_count` | boolean | no | 如果参数包含为 true,则每个存储库的响应中都将包含`"tags_count"` (在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32141) ). | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories" +``` + +响应示例: + +``` +[ { "id": 1, "name": "", "path": "group/project", "project_id": 9, "location": "gitlab.example.com:5000/group/project", "created_at": "2019-01-10T13:38:57.391Z" }, { "id": 2, "name": "releases", "path": "group/project/releases", "project_id": 9, "location": "gitlab.example.com:5000/group/project/releases", "created_at": "2019-01-10T13:39:08.229Z" } ] +``` + +### Within a group[](#within-a-group "Permalink") + +获取组中的注册表存储库列表. + +``` +GET /groups/:id/registry/repositories +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户可以访问[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `tags` | boolean | no | 如果参数包含为 true,则每个存储库在响应中都将包含一个`"tags"`数组. | +| `name` | string | no | 返回名称与值匹配的存储库列表. (在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29763) ). | +| `tags_count` | boolean | no | 如果参数包含为 true,则每个存储库的响应中都将包含`"tags_count"` (在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32141) ). | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/2/registry/repositories?tags=1&tags_count=true" +``` + +响应示例: + +``` +[ { "id": 1, "name": "", "path": "group/project", "project_id": 9, "location": "gitlab.example.com:5000/group/project", "created_at": "2019-01-10T13:38:57.391Z", "tags_count": 1, "tags": [ { "name": "0.0.1", "path": "group/project:0.0.1", "location": "gitlab.example.com:5000/group/project:0.0.1" } ] }, { "id": 2, "name": "", "path": "group/other_project", "project_id": 11, "location": "gitlab.example.com:5000/group/other_project", "created_at": "2019-01-10T13:39:08.229Z", "tags_count": 3, "tags": [ { "name": "0.0.1", "path": "group/other_project:0.0.1", "location": "gitlab.example.com:5000/group/other_project:0.0.1" }, { "name": "0.0.2", "path": "group/other_project:0.0.2", "location": "gitlab.example.com:5000/group/other_project:0.0.2" }, { "name": "latest", "path": "group/other_project:latest", "location": "gitlab.example.com:5000/group/other_project:latest" } ] } ] +``` + +## Delete registry repository[](#delete-registry-repository "Permalink") + +删除注册表中的存储库. + +该操作是异步执行的,可能要花一些时间才能执行. + +``` +DELETE /projects/:id/registry/repositories/:repository_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.html#namespaced-path-encoding) owned by the authenticated user. | +| `repository_id` | integer | yes | 注册表存储库的标识. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2" +``` + +## List registry repository tags[](#list-registry-repository-tags "Permalink") + +### Within a project[](#within-a-project-1 "Permalink") + +获取给定注册表存储库的标签列表. + +``` +GET /projects/:id/registry/repositories/:repository_id/tags +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户可以访问[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `repository_id` | integer | yes | 注册表存储库的标识. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags" +``` + +响应示例: + +``` +[ { "name": "A", "path": "group/project:A", "location": "gitlab.example.com:5000/group/project:A" }, { "name": "latest", "path": "group/project:latest", "location": "gitlab.example.com:5000/group/project:latest" } ] +``` + +## Get details of a registry repository tag[](#get-details-of-a-registry-repository-tag "Permalink") + +获取注册表存储库标签的详细信息. + +``` +GET /projects/:id/registry/repositories/:repository_id/tags/:tag_name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户可以访问[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `repository_id` | integer | yes | 注册表存储库的标识. | +| `tag_name` | string | yes | 标签名称. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags/v10.0.0" +``` + +响应示例: + +``` +{ "name": "v10.0.0", "path": "group/project:latest", "location": "gitlab.example.com:5000/group/project:latest", "revision": "e9ed9d87c881d8c2fd3a31b41904d01ba0b836e7fd15240d774d811a1c248181", "short_revision": "e9ed9d87c", "digest": "sha256:c3490dcf10ffb6530c1303522a1405dfaf7daecd8f38d3e6a1ba19ea1f8a1751", "created_at": "2019-01-06T16:49:51.272+00:00", "total_size": 350224384 } +``` + +## Delete a registry repository tag[](#delete-a-registry-repository-tag "Permalink") + +删除注册表存储库标记. + +``` +DELETE /projects/:id/registry/repositories/:repository_id/tags/:tag_name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `repository_id` | integer | yes | 注册表存储库的标识. | +| `tag_name` | string | yes | 标签名称. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags/v10.0.0" +``` + +此操作不会删除 Blob. 为了删除它们并回收磁盘空间,请[运行垃圾回收](https://docs.gitlab.com/omnibus/maintenance/README.html) . + +## Delete registry repository tags in bulk[](#delete-registry-repository-tags-in-bulk "Permalink") + +根据给定的标准批量删除注册表存储库标签. + +有关概述,请参阅[利用 Container Registry API 删除除*之外的所有标签](https://youtu.be/Hi19bKe_xsg) . + +``` +DELETE /projects/:id/registry/repositories/:repository_id/tags +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `repository_id` | integer | yes | 注册表存储库的标识. | +| `name_regex` | string | no | 要删除的名称的[re2](https://github.com/google/re2/wiki/Syntax)正则表达式. 要删除所有标签,请指定`.*` . **注意:**不建议使用`name_regex`而建议使用`name_regex_delete` . 此字段已验证. | +| `name_regex_delete` | string | yes | 要删除的名称的[re2](https://github.com/google/re2/wiki/Syntax)正则表达式. 要删除所有标签,请指定`.*` . 此字段已验证. | +| `name_regex_keep` | string | no | 要保留名称的[re2](https://github.com/google/re2/wiki/Syntax)正则表达式. 此值将覆盖`name_regex_delete`所有匹配`name_regex_delete` . 此字段已验证. 注意:设置为`.*`将导致无操作. | +| `keep_n` | integer | no | 要保留的给定名称的最新标签的数量. | +| `older_than` | string | no | 早于给定时间的要删除的标签,以人类可读的格式`1h` , `1d` , `1month`编写. | + +此 API 调用执行以下操作: + +1. 它按创建日期排序所有标签. 创建日期是清单创建的时间,而不是标签推送的时间. +2. 它仅删除与给定`name_regex_delete` (或不`name_regex`使用的`name_regex` )匹配的标签,并保留所有与`name_regex_keep`匹配的`name_regex_keep` . +3. 它绝不会取消对标签命名`latest` . +4. 它保留 N 个最新的匹配标签(如果指定了`keep_n` ). +5. 它仅删除时间超过 X 时间的标签(如果指定了`older_than` ). +6. 它安排异步作业在后台执行. + +这些操作是异步执行的,可能要花一些时间才能执行. 对于给定的容器存储库,您最多可以每小时运行一次. 此操作不会删除 Blob. 为了删除它们并回收磁盘空间,请[运行垃圾回收](https://docs.gitlab.com/omnibus/maintenance/README.html) . + +**注意:**从 GitLab 12.4 开始,将删除各个标签. 有关更多详细信息,请参见[讨论](https://gitlab.com/gitlab-org/gitlab/-/issues/15737) . + +Examples: + +1. 删除与正则表达式(Git SHA)匹配的标记名,始终至少保留 5 个,并删除 2 天以上的标记名: + + ``` + curl --request DELETE --data 'name_regex_delete=[0-9a-z]{40}' --data 'keep_n=5' --data 'older_than=2d' --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags" + ``` + +2. 删除所有标签,但始终保留最新的 5 个标签: + + ``` + curl --request DELETE --data 'name_regex_delete=.*' --data 'keep_n=5' --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags" + ``` + +3. 删除所有标签,但始终保留以`stable`开头的标签: + + ``` + curl --request DELETE --data 'name_regex_delete=.*' --data 'name_regex_keep=stable.*' --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags" + ``` + +4. 删除所有超过 1 个月的标签: + + ``` + curl --request DELETE --data 'name_regex_delete=.*' --data 'older_than=1month' --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags" + ``` \ No newline at end of file diff --git a/_book/docs/303.md b/_book/docs/303.md new file mode 100644 index 0000000000000000000000000000000000000000..58fb56a6f3ea81d5ace64bb8c9eccd635301e319 --- /dev/null +++ b/_book/docs/303.md @@ -0,0 +1,108 @@ +# Custom Attributes API + +> 原文:[https://docs.gitlab.com/ee/api/custom_attributes.html](https://docs.gitlab.com/ee/api/custom_attributes.html) + +* [List custom attributes](#list-custom-attributes) +* [Single custom attribute](#single-custom-attribute) +* [Set custom attribute](#set-custom-attribute) +* [Delete custom attribute](#delete-custom-attribute) + +# Custom Attributes API[](#custom-attributes-api "Permalink") + +每个对自定义属性的 API 调用都必须经过管理员身份验证. + +自定义属性当前可用于用户,组和项目,在本文档中将其称为"资源". + +## List custom attributes[](#list-custom-attributes "Permalink") + +获取资源上的所有自定义属性. + +``` +GET /users/:id/custom_attributes +GET /groups/:id/custom_attributes +GET /projects/:id/custom_attributes +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 资源的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/42/custom_attributes" +``` + +响应示例: + +``` +[ { "key": "location", "value": "Antarctica" }, { "key": "role", "value": "Developer" } ] +``` + +## Single custom attribute[](#single-custom-attribute "Permalink") + +在资源上获取单个自定义属性. + +``` +GET /users/:id/custom_attributes/:key +GET /groups/:id/custom_attributes/:key +GET /projects/:id/custom_attributes/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 资源的 ID | +| `key` | string | yes | 自定义属性的键 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/42/custom_attributes/location" +``` + +响应示例: + +``` +{ "key": "location", "value": "Antarctica" } +``` + +## Set custom attribute[](#set-custom-attribute "Permalink") + +在资源上设置自定义属性. 如果该属性已经存在,则将对其进行更新;否则,将重新创建该属性. + +``` +PUT /users/:id/custom_attributes/:key +PUT /groups/:id/custom_attributes/:key +PUT /projects/:id/custom_attributes/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 资源的 ID | +| `key` | string | yes | 自定义属性的键 | +| `value` | string | yes | 自定义属性的值 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --data "value=Greenland" "https://gitlab.example.com/api/v4/users/42/custom_attributes/location" +``` + +响应示例: + +``` +{ "key": "location", "value": "Greenland" } +``` + +## Delete custom attribute[](#delete-custom-attribute "Permalink") + +删除资源上的自定义属性. + +``` +DELETE /users/:id/custom_attributes/:key +DELETE /groups/:id/custom_attributes/:key +DELETE /projects/:id/custom_attributes/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 资源的 ID | +| `key` | string | yes | 自定义属性的键 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/42/custom_attributes/location" +``` \ No newline at end of file diff --git a/_book/docs/304.md b/_book/docs/304.md new file mode 100644 index 0000000000000000000000000000000000000000..2c36d326f99874396737a3fe276cb726b3ea9ee7 --- /dev/null +++ b/_book/docs/304.md @@ -0,0 +1,44 @@ +# Dashboard annotations API + +> 原文:[https://docs.gitlab.com/ee/api/metrics_dashboard_annotations.html](https://docs.gitlab.com/ee/api/metrics_dashboard_annotations.html) + +* [Create a new annotation](#create-a-new-annotation) + +# Dashboard annotations API[](#dashboard-annotations-api "Permalink") + +版本历史 + +* 在 GitLab 12.10 中在禁用的功能标志后面[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29089) . + +指标仪表板注释使您可以在单个时间点或整个时间段内指示图形上的事件. + +## Create a new annotation[](#create-a-new-annotation "Permalink") + +``` +POST /environments/:id/metrics_dashboard/annotations/ +POST /clusters/:id/metrics_dashboard/annotations/ +``` + +**注意:** `dashboard_path`的值将被视为 CGI 转义的路径,并自动取消转义. + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `dashboard_path` | string | yes | 需要注释的仪表盘的 ID. | +| `starting_at` | string | yes | 日期时间字符串,ISO 8601 格式,例如`2016-03-11T03:45:40Z` . 注释的时间戳标记起点. | +| `ending_at` | string | no | 日期时间字符串,ISO 8601 格式,例如`2016-03-11T03:45:40Z` . 注释的时间戳标记终点. 如果未提供,注释将在起点显示为单个事件. | +| `description` | string | yes | 注释的描述. | + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/environments/1/metrics_dashboard/annotations" \ + --data-urlencode "dashboard_path=.gitlab/dashboards/custom_metrics.yml" \ + --data-urlencode "starting_at=2016-03-11T03:45:40Z" \ + --data-urlencode "description=annotation description" +``` + +示例响应: + +``` +{ "id": 4, "starting_at": "2016-04-08T03:45:40.000Z", "ending_at": null, "dashboard_path": ".gitlab/dashboards/custom_metrics.yml", "description": "annotation description", "environment_id": 1, "cluster_id": null } +``` \ No newline at end of file diff --git a/_book/docs/305.md b/_book/docs/305.md new file mode 100644 index 0000000000000000000000000000000000000000..370727fc20a50e850246ad6772046beae9b798d5 --- /dev/null +++ b/_book/docs/305.md @@ -0,0 +1,36 @@ +# Dependencies API + +> 原文:[https://docs.gitlab.com/ee/api/dependencies.html](https://docs.gitlab.com/ee/api/dependencies.html) + +* [List project dependencies](#list-project-dependencies) + +# Dependencies API[](#dependencies-api-ultimate "Permalink") + +**警告:**此 API 处于 alpha 阶段,被认为是不稳定的. 响应有效载荷可能会在 GitLab 版本之间发生更改或损坏. + +对此端点的每次调用都需要身份验证. 要执行此调用,应授权用户读取存储库. 要查看响应中的漏洞,应授权用户阅读[Project Security Dashboard](../user/application_security/security_dashboard/index.html#project-security-dashboard) . + +## List project dependencies[](#list-project-dependencies "Permalink") + +获取项目依赖项列表. 该 API 部分镜像了[依赖项列表](../user/application_security/dependency_list/index.html)功能. 只能为 Gemnasium 支持的[语言和程序包管理器](../user/application_security/dependency_scanning/index.html#supported-languages-and-package-managers)生成此列表. + +``` +GET /projects/:id/dependencies +GET /projects/:id/dependencies?package_manager=maven +GET /projects/:id/dependencies?package_manager=yarn,bundler +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `package_manager` | 字符串数组 | no | 返回属于指定程序包管理器的依赖项. 有效值: `bundler` , `composer` , `maven` , `npm` , `pip`或`yarn` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/dependencies" +``` + +响应示例: + +``` +[ { "name": "rails", "version": "5.0.1", "package_manager": "bundler", "dependency_file_path": "Gemfile.lock", "vulnerabilities": [{ "name": "DDoS", "severity": "unknown" }] }, { "name": "hanami", "version": "1.3.1", "package_manager": "bundler", "dependency_file_path": "Gemfile.lock", "vulnerabilities": [] } ] +``` \ No newline at end of file diff --git a/_book/docs/306.md b/_book/docs/306.md new file mode 100644 index 0000000000000000000000000000000000000000..6c223fcccfa6edd1fdf3ce71166432c00b34e30a --- /dev/null +++ b/_book/docs/306.md @@ -0,0 +1,196 @@ +# Deploy Keys API + +> 原文:[https://docs.gitlab.com/ee/api/deploy_keys.html](https://docs.gitlab.com/ee/api/deploy_keys.html) + +* [List all deploy keys](#list-all-deploy-keys) +* [List project deploy keys](#list-project-deploy-keys) +* [Single deploy key](#single-deploy-key) +* [Add deploy key](#add-deploy-key) +* [Update deploy key](#update-deploy-key) +* [Delete deploy key](#delete-deploy-key) +* [Enable a deploy key](#enable-a-deploy-key) +* [Adding deploy keys to multiple projects](#adding-deploy-keys-to-multiple-projects) + +# Deploy Keys API[](#deploy-keys-api "Permalink") + +## List all deploy keys[](#list-all-deploy-keys "Permalink") + +获取 GitLab 实例的所有项目中所有部署密钥的列表. 该端点需要管理员访问权限,并且在 GitLab.com 上不可用. + +``` +GET /deploy_keys +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/deploy_keys" +``` + +响应示例: + +``` +[ { "id": 1, "title": "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2013-10-02T10:12:29Z" }, { "id": 3, "title": "Another Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2013-10-02T11:12:29Z" } ] +``` + +## List project deploy keys[](#list-project-deploy-keys "Permalink") + +获取项目的部署密钥的列表. + +``` +GET /projects/:id/deploy_keys +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/deploy_keys" +``` + +响应示例: + +``` +[ { "id": 1, "title": "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2013-10-02T10:12:29Z", "can_push": false }, { "id": 3, "title": "Another Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2013-10-02T11:12:29Z", "can_push": false } ] +``` + +## Single deploy key[](#single-deploy-key "Permalink") + +Get a single key. + +``` +GET /projects/:id/deploy_keys/:key_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `key_id` | integer | yes | 部署密钥的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/deploy_keys/11" +``` + +响应示例: + +``` +{ "id": 1, "title": "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2013-10-02T10:12:29Z", "can_push": false } +``` + +## Add deploy key[](#add-deploy-key "Permalink") + +为项目创建一个新的部署密钥. + +如果部署密钥已经存在于另一个项目中,则只有在同一用户可以访问原始密钥的情况下,它才会加入到当前项目中. + +``` +POST /projects/:id/deploy_keys +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `title` | string | yes | 新部署密钥的标题 | +| `key` | string | yes | 新的部署密钥 | +| `can_push` | boolean | no | 可以将按键推送部署到项目的存储库 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" --data '{"title": "My deploy key", "key": "ssh-rsa AAAA...", "can_push": "true"}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/" +``` + +响应示例: + +``` +{ "key" : "ssh-rsa AAAA...", "id" : 12, "title" : "My deploy key", "can_push": true, "created_at" : "2015-08-29T12:44:31.550Z" } +``` + +## Update deploy key[](#update-deploy-key "Permalink") + +更新项目的部署密钥. + +``` +PUT /projects/:id/deploy_keys/:key_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `title` | string | no | 新部署密钥的标题 | +| `can_push` | boolean | no | 可以将按键推送部署到项目的存储库 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" --data '{"title": "New deploy key", "can_push": true}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/11" +``` + +响应示例: + +``` +{ "id": 11, "title": "New deploy key", "key": "ssh-rsa AAAA...", "created_at": "2015-08-29T12:44:31.550Z", "can_push": true } +``` + +## Delete deploy key[](#delete-deploy-key "Permalink") + +从项目中删除部署密钥. 如果部署密钥仅用于该项目,则它将从系统中删除. + +``` +DELETE /projects/:id/deploy_keys/:key_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `key_id` | integer | yes | 部署密钥的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/deploy_keys/13" +``` + +## Enable a deploy key[](#enable-a-deploy-key "Permalink") + +为项目启用部署密钥,以便可以使用它. 返回成功的密钥,成功时返回状态码 201. + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/deploy_keys/13/enable" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `key_id` | integer | yes | 部署密钥的 ID | + +响应示例: + +``` +{ "key" : "ssh-rsa AAAA...", "id" : 12, "title" : "My deploy key", "created_at" : "2015-08-29T12:44:31.550Z" } +``` + +## Adding deploy keys to multiple projects[](#adding-deploy-keys-to-multiple-projects "Permalink") + +如果您想轻松地将相同的部署密钥添加到同一组中的多个项目中,则可以使用 API​​轻松实现. + +首先,通过列出所有项目来找到您感兴趣的项目的 ID: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects" +``` + +或查找组的 ID: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups" +``` + +然后列出该组中的所有项目(例如,组 1234): + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1234" +``` + +使用这些 ID,将相同的部署密钥添加到所有: + +``` +for project_id in 321 456 987; do curl --request POST --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" \ + --data '{"title": "my key", "key": "ssh-rsa AAAA..."}' "https://gitlab.example.com/api/v4/projects/${project_id}/deploy_keys" +done +``` \ No newline at end of file diff --git a/_book/docs/307.md b/_book/docs/307.md new file mode 100644 index 0000000000000000000000000000000000000000..905bc23c935b610877c3b5a7c19c2a0d24106843 --- /dev/null +++ b/_book/docs/307.md @@ -0,0 +1,139 @@ +# Deployments API + +> 原文:[https://docs.gitlab.com/ee/api/deployments.html](https://docs.gitlab.com/ee/api/deployments.html) + +* [List project deployments](#list-project-deployments) +* [Get a specific deployment](#get-a-specific-deployment) +* [Create a deployment](#create-a-deployment) +* [Updating a deployment](#updating-a-deployment) +* [List of merge requests associated with a deployment](#list-of-merge-requests-associated-with-a-deployment) + +# Deployments API[](#deployments-api "Permalink") + +## List project deployments[](#list-project-deployments "Permalink") + +获取项目中的部署列表. + +``` +GET /projects/:id/deployments +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `order_by` | string | no | 返回按`id`或`iid`或`created_at`或`updated_at`或`ref`字段排序的部署. 默认为`id` | +| `sort` | string | no | 返回按`asc`或`desc`排列的部署. 默认为`asc` | +| `updated_after` | datetime | no | 返回指定日期之后更新的部署 | +| `updated_before` | datetime | no | 返回在指定日期之前更新的部署 | +| `environment` | string | no | 用于过滤部署的环境名称 | +| `status` | string | no | 用来过滤部署的状态 | + +status 属性可以是以下值之一: + +* created +* running +* success +* failed +* canceled + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/deployments" +``` + +回应范例 + +``` +[ { "created_at": "2016-08-11T07:36:40.222Z", "updated_at": "2016-08-11T07:38:12.414Z", "status": "created", "deployable": { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2016-08-11T09:36:01.000+02:00", "id": "99d03678b90d914dbb1b109132516d71a4a03ea8", "message": "Merge branch 'new-title' into 'master'\r\n\r\nUpdate README\r\n\r\n\r\n\r\nSee merge request !1", "short_id": "99d03678", "title": "Merge branch 'new-title' into 'master'\r" }, "coverage": null, "created_at": "2016-08-11T07:36:27.357Z", "finished_at": "2016-08-11T07:36:39.851Z", "id": 657, "name": "deploy", "ref": "master", "runner": null, "stage": "deploy", "started_at": null, "status": "success", "tag": false, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" }, "pipeline": { "created_at": "2016-08-11T02:12:10.222Z", "id": 36, "ref": "master", "sha": "99d03678b90d914dbb1b109132516d71a4a03ea8", "status": "success", "updated_at": "2016-08-11T02:12:10.222Z", "web_url": "http://gitlab.dev/root/project/pipelines/12" } }, "environment": { "external_url": "https://about.gitlab.com", "id": 9, "name": "production" }, "id": 41, "iid": 1, "ref": "master", "sha": "99d03678b90d914dbb1b109132516d71a4a03ea8", "user": { "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "id": 1, "name": "Administrator", "state": "active", "username": "root", "web_url": "http://localhost:3000/root" } }, { "created_at": "2016-08-11T11:32:35.444Z", "updated_at": "2016-08-11T11:34:01.123Z", "status": "created", "deployable": { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2016-08-11T13:28:26.000+02:00", "id": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "message": "Merge branch 'rename-readme' into 'master'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2", "short_id": "a91957a8", "title": "Merge branch 'rename-readme' into 'master'\r" }, "coverage": null, "created_at": "2016-08-11T11:32:24.456Z", "finished_at": "2016-08-11T11:32:35.145Z", "id": 664, "name": "deploy", "ref": "master", "runner": null, "stage": "deploy", "started_at": null, "status": "success", "tag": false, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" }, "pipeline": { "created_at": "2016-08-11T07:43:52.143Z", "id": 37, "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "status": "success", "updated_at": "2016-08-11T07:43:52.143Z", "web_url": "http://gitlab.dev/root/project/pipelines/13" } }, "environment": { "external_url": "https://about.gitlab.com", "id": 9, "name": "production" }, "id": 42, "iid": 2, "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "user": { "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "id": 1, "name": "Administrator", "state": "active", "username": "root", "web_url": "http://localhost:3000/root" } } ] +``` + +## Get a specific deployment[](#get-a-specific-deployment "Permalink") + +``` +GET /projects/:id/deployments/:deployment_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `deployment_id` | integer | yes | 部署的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/deployments/1" +``` + +回应范例 + +``` +{ "id": 42, "iid": 2, "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "created_at": "2016-08-11T11:32:35.444Z", "updated_at": "2016-08-11T11:34:01.123Z", "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "environment": { "id": 9, "name": "production", "external_url": "https://about.gitlab.com" }, "deployable": { "id": 664, "status": "success", "stage": "deploy", "name": "deploy", "ref": "master", "tag": false, "coverage": null, "created_at": "2016-08-11T11:32:24.456Z", "started_at": null, "finished_at": "2016-08-11T11:32:35.145Z", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" }, "commit": { "id": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "short_id": "a91957a8", "title": "Merge branch 'rename-readme' into 'master'\r", "author_name": "Administrator", "author_email": "admin@example.com", "created_at": "2016-08-11T13:28:26.000+02:00", "message": "Merge branch 'rename-readme' into 'master'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2" }, "pipeline": { "created_at": "2016-08-11T07:43:52.143Z", "id": 42, "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "status": "success", "updated_at": "2016-08-11T07:43:52.143Z", "web_url": "http://gitlab.dev/root/project/pipelines/5" } "runner": null } } +``` + +## Create a deployment[](#create-a-deployment "Permalink") + +``` +POST /projects/:id/deployments +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `environment` | string | yes | 要为其创建部署的环境的名称 | +| `sha` | string | yes | 部署的提交的 SHA | +| `ref` | string | yes | 部署的分支或标记的名称 | +| `tag` | boolean | yes | A boolean that indicates if the deployed ref is a tag (true) or not (false) | +| `status` | string | yes | 部署状态 | + +状态可以是以下值之一: + +* created +* running +* success +* failed +* canceled + +``` +curl --data "environment=production&sha=a91957a858320c0e17f3a0eca7cfacbff50ea29a&ref=master&tag=false&status=success" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/deployments" +``` + +响应示例: + +``` +{ "id": 42, "iid": 2, "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "created_at": "2016-08-11T11:32:35.444Z", "status": "success", "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "environment": { "id": 9, "name": "production", "external_url": "https://about.gitlab.com" }, "deployable": null } +``` + +## Updating a deployment[](#updating-a-deployment "Permalink") + +``` +PUT /projects/:id/deployments/:deployment_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `deployment_id` | integer | yes | 要更新的部署的 ID | +| `status` | string | yes | 部署的新状态 | + +``` +curl --request PUT --data "status=success" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/deployments/42" +``` + +响应示例: + +``` +{ "id": 42, "iid": 2, "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "created_at": "2016-08-11T11:32:35.444Z", "status": "success", "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "environment": { "id": 9, "name": "production", "external_url": "https://about.gitlab.com" }, "deployable": null } +``` + +## List of merge requests associated with a deployment[](#list-of-merge-requests-associated-with-a-deployment "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/35739) . + +此 API 检索给定部署附带的合并请求列表: + +``` +GET /projects/:id/deployments/:deployment_id/merge_requests +``` + +它支持与[Merge Requests API](./merge_requests.html#list-merge-requests)相同的参数,并将以相同的格式返回响应: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/deployments/42" +``` \ No newline at end of file diff --git a/_book/docs/308.md b/_book/docs/308.md new file mode 100644 index 0000000000000000000000000000000000000000..bd54101a3d25440a91d7b2205a777cbe3c66e3c7 --- /dev/null +++ b/_book/docs/308.md @@ -0,0 +1,790 @@ +# Discussions API + +> 原文:[https://docs.gitlab.com/ee/api/discussions.html](https://docs.gitlab.com/ee/api/discussions.html) + +* [Discussions pagination](#discussions-pagination) +* [Issues](#issues) + * [List project issue discussion items](#list-project-issue-discussion-items) + * [Get single issue discussion item](#get-single-issue-discussion-item) + * [Create new issue thread](#create-new-issue-thread) + * [Add note to existing issue thread](#add-note-to-existing-issue-thread) + * [Modify existing issue thread note](#modify-existing-issue-thread-note) + * [Delete an issue thread note](#delete-an-issue-thread-note) +* [Snippets](#snippets) + * [List project snippet discussion items](#list-project-snippet-discussion-items) + * [Get single snippet discussion item](#get-single-snippet-discussion-item) + * [Create new snippet thread](#create-new-snippet-thread) + * [Add note to existing snippet thread](#add-note-to-existing-snippet-thread) + * [Modify existing snippet thread note](#modify-existing-snippet-thread-note) + * [Delete a snippet thread note](#delete-a-snippet-thread-note) +* [Epics](#epics-ultimate) + * [List group epic discussion items](#list-group-epic-discussion-items) + * [Get single epic discussion item](#get-single-epic-discussion-item) + * [Create new epic thread](#create-new-epic-thread) + * [Add note to existing epic thread](#add-note-to-existing-epic-thread) + * [Modify existing epic thread note](#modify-existing-epic-thread-note) + * [Delete an epic thread note](#delete-an-epic-thread-note) +* [Merge requests](#merge-requests) + * [List project merge request discussion items](#list-project-merge-request-discussion-items) + * [Get single merge request discussion item](#get-single-merge-request-discussion-item) + * [Create new merge request thread](#create-new-merge-request-thread) + * [Resolve a merge request thread](#resolve-a-merge-request-thread) + * [Add note to existing merge request thread](#add-note-to-existing-merge-request-thread) + * [Modify an existing merge request thread note](#modify-an-existing-merge-request-thread-note) + * [Delete a merge request thread note](#delete-a-merge-request-thread-note) +* [Commits](#commits) + * [List project commit discussion items](#list-project-commit-discussion-items) + * [Get single commit discussion item](#get-single-commit-discussion-item) + * [Create new commit thread](#create-new-commit-thread) + * [Add note to existing commit thread](#add-note-to-existing-commit-thread) + * [Modify an existing commit thread note](#modify-an-existing-commit-thread-note) + * [Delete a commit thread note](#delete-a-commit-thread-note) + +# Discussions API[](#discussions-api "Permalink") + +讨论是关于以下方面的一组相关注释: + +* Snippets +* Issues +* Epics +* 合并要求 +* Commits + +这包括系统注释,这些注释是有关对象更改的注释(例如,当里程碑更改时,将有相应的系统注释). 标签注释不是此 API 的一部分,而是在[资源标签事件中](resource_label_events.html)记录为单独的[事件](resource_label_events.html) . + +## Discussions pagination[](#discussions-pagination "Permalink") + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +## Issues[](#issues "Permalink") + +### List project issue discussion items[](#list-project-issue-discussion-items "Permalink") + +获取单个问题的所有讨论项目的列表. + +``` +GET /projects/:id/issues/:issue_iid/discussions +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | + +``` +[ { "id": "6a9c1750b37d513a43987b574953fceb50b03ce7", "individual_note": false, "notes": [ { "id": 1126, "type": "DiscussionNote", "body": "discussion text", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-03T21:54:39.668Z", "updated_at": "2018-03-03T21:54:39.668Z", "system": false, "noteable_id": 3, "noteable_type": "Issue", "noteable_iid": null }, { "id": 1129, "type": "DiscussionNote", "body": "reply to the discussion", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T13:38:02.127Z", "updated_at": "2018-03-04T13:38:02.127Z", "system": false, "noteable_id": 3, "noteable_type": "Issue", "noteable_iid": null, "resolvable": false } ] }, { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": true, "notes": [ { "id": 1128, "type": null, "body": "a single comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Issue", "noteable_iid": null, "resolvable": false } ] } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions" +``` + +### Get single issue discussion item[](#get-single-issue-discussion-item "Permalink") + +返回特定项目问题的单个讨论项 + +``` +GET /projects/:id/issues/:issue_iid/discussions/:discussion_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `discussion_id` | integer | yes | 讨论项目的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7" +``` + +### Create new issue thread[](#create-new-issue-thread "Permalink") + +为单个项目问题创建一个新线程. 这类似于创建便笺,但其他注释(回复)可以在以后添加. + +``` +POST /projects/:id/issues/:issue_iid/discussions +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `body` | string | yes | 线程的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions?body=comment" +``` + +### Add note to existing issue thread[](#add-note-to-existing-issue-thread "Permalink") + +向该线程添加新注释. 这也可以[从单个注释创建线程](../user/discussions/#start-a-thread-by-replying-to-a-standard-comment) . + +**警告**注释可以添加到注释(系统注释等)之外的其他项目中,从而使其成为主题. + +``` +POST /projects/:id/issues/:issue_iid/discussions/:discussion_id/notes +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment" +``` + +### Modify existing issue thread note[](#modify-existing-issue-thread-note "Permalink") + +修改问题的现有线程注释. + +``` +PUT /projects/:id/issues/:issue_iid/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment" +``` + +### Delete an issue thread note[](#delete-an-issue-thread-note "Permalink") + +删除问题的现有主题注释. + +``` +DELETE /projects/:id/issues/:issue_iid/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `discussion_id` | integer | yes | 讨论的 ID | +| `note_id` | integer | yes | 讨论记录的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/636" +``` + +## Snippets[](#snippets "Permalink") + +### List project snippet discussion items[](#list-project-snippet-discussion-items "Permalink") + +获取单个代码段的所有讨论项的列表. + +``` +GET /projects/:id/snippets/:snippet_id/discussions +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | + +``` +[ { "id": "6a9c1750b37d513a43987b574953fceb50b03ce7", "individual_note": false, "notes": [ { "id": 1126, "type": "DiscussionNote", "body": "discussion text", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-03T21:54:39.668Z", "updated_at": "2018-03-03T21:54:39.668Z", "system": false, "noteable_id": 3, "noteable_type": "Snippet", "noteable_id": null }, { "id": 1129, "type": "DiscussionNote", "body": "reply to the discussion", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T13:38:02.127Z", "updated_at": "2018-03-04T13:38:02.127Z", "system": false, "noteable_id": 3, "noteable_type": "Snippet", "noteable_id": null, "resolvable": false } ] }, { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": true, "notes": [ { "id": 1128, "type": null, "body": "a single comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Snippet", "noteable_id": null, "resolvable": false } ] } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions" +``` + +### Get single snippet discussion item[](#get-single-snippet-discussion-item "Permalink") + +返回特定项目片段的单个讨论项 + +``` +GET /projects/:id/snippets/:snippet_id/discussions/:discussion_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | +| `discussion_id` | integer | yes | 讨论项目的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7" +``` + +### Create new snippet thread[](#create-new-snippet-thread "Permalink") + +Creates a new thread to a single project snippet. This is similar to creating a note but other comments (replies) can be added to it later. + +``` +POST /projects/:id/snippets/:snippet_id/discussions +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | +| `body` | string | yes | 讨论内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions?body=comment" +``` + +### Add note to existing snippet thread[](#add-note-to-existing-snippet-thread "Permalink") + +向该线程添加新注释. + +``` +POST /projects/:id/snippets/:snippet_id/discussions/:discussion_id/notes +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment" +``` + +### Modify existing snippet thread note[](#modify-existing-snippet-thread-note "Permalink") + +修改代码段的现有线程注释. + +``` +PUT /projects/:id/snippets/:snippet_id/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment" +``` + +### Delete a snippet thread note[](#delete-a-snippet-thread-note "Permalink") + +删除代码段的现有线程注释. + +``` +DELETE /projects/:id/snippets/:snippet_id/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | +| `discussion_id` | integer | yes | 讨论的 ID | +| `note_id` | integer | yes | 讨论记录的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/636" +``` + +## Epics[](#epics-ultimate "Permalink") + +### List group epic discussion items[](#list-group-epic-discussion-items "Permalink") + +获取单个史诗的所有讨论项的列表. + +``` +GET /groups/:id/epics/:epic_id/discussions +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | + +``` +[ { "id": "6a9c1750b37d513a43987b574953fceb50b03ce7", "individual_note": false, "notes": [ { "id": 1126, "type": "DiscussionNote", "body": "discussion text", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-03T21:54:39.668Z", "updated_at": "2018-03-03T21:54:39.668Z", "system": false, "noteable_id": 3, "noteable_type": "Epic", "noteable_id": null, "resolvable": false }, { "id": 1129, "type": "DiscussionNote", "body": "reply to the discussion", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T13:38:02.127Z", "updated_at": "2018-03-04T13:38:02.127Z", "system": false, "noteable_id": 3, "noteable_type": "Epic", "noteable_id": null, "resolvable": false } ] }, { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": true, "notes": [ { "id": 1128, "type": null, "body": "a single comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Epic", "noteable_id": null, "resolvable": false } ] } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions" +``` + +### Get single epic discussion item[](#get-single-epic-discussion-item "Permalink") + +返回特定小组史诗的单个讨论项 + +``` +GET /groups/:id/epics/:epic_id/discussions/:discussion_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `discussion_id` | integer | yes | 讨论项目的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7" +``` + +### Create new epic thread[](#create-new-epic-thread "Permalink") + +Creates a new thread to a single group epic. This is similar to creating a note but other comments (replies) can be added to it later. + +``` +POST /groups/:id/epics/:epic_id/discussions +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `body` | string | yes | 线程的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions?body=comment" +``` + +### Add note to existing epic thread[](#add-note-to-existing-epic-thread "Permalink") + +向该线程添加新注释. 这也可以[从单个注释创建线程](../user/discussions/#start-a-thread-by-replying-to-a-standard-comment) . + +``` +POST /groups/:id/epics/:epic_id/discussions/:discussion_id/notes +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment" +``` + +### Modify existing epic thread note[](#modify-existing-epic-thread-note "Permalink") + +修改史诗的现有线程注释. + +``` +PUT /groups/:id/epics/:epic_id/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment" +``` + +### Delete an epic thread note[](#delete-an-epic-thread-note "Permalink") + +删除史诗的现有主题注释. + +``` +DELETE /groups/:id/epics/:epic_id/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/636" +``` + +## Merge requests[](#merge-requests "Permalink") + +### List project merge request discussion items[](#list-project-merge-request-discussion-items "Permalink") + +获取单个合并请求的所有讨论项的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/discussions +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | + +``` +[ { "id": "6a9c1750b37d513a43987b574953fceb50b03ce7", "individual_note": false, "notes": [ { "id": 1126, "type": "DiscussionNote", "body": "discussion text", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-03T21:54:39.668Z", "updated_at": "2018-03-03T21:54:39.668Z", "system": false, "noteable_id": 3, "noteable_type": "Merge request", "noteable_iid": null, "resolved": false, "resolvable": true, "resolved_by": null }, { "id": 1129, "type": "DiscussionNote", "body": "reply to the discussion", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T13:38:02.127Z", "updated_at": "2018-03-04T13:38:02.127Z", "system": false, "noteable_id": 3, "noteable_type": "Merge request", "noteable_iid": null, "resolved": false, "resolvable": true, "resolved_by": null } ] }, { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": true, "notes": [ { "id": 1128, "type": null, "body": "a single comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Merge request", "noteable_iid": null, "resolved": false, "resolvable": true, "resolved_by": null } ] } ] +``` + +差异评论还包含以下位置: + +``` +[ { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": false, "notes": [ { "id": 1128, "type": DiffNote, "body": "diff comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Merge request", "noteable_iid": null, "position": { "base_sha": "b5d6e7b1613fca24d250fa8e5bc7bcc3dd6002ef", "start_sha": "7c9c2ead8a320fb7ba0b4e234bd9529a2614e306", "head_sha": "4803c71e6b1833ca72b8b26ef2ecd5adc8a38031", "old_path": "package.json", "new_path": "package.json", "position_type": "text", "old_line": 27, "new_line": 27, "line_range": { "start": { "line_code": "588440f66559714280628a4f9799f0c4eb880a4a_10_10", "type": "new", }, "end": { "line_code": "588440f66559714280628a4f9799f0c4eb880a4a_11_11", "type": "old" }, } }, "resolved": false, "resolvable": true, "resolved_by": null } ] } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions" +``` + +### Get single merge request discussion item[](#get-single-merge-request-discussion-item "Permalink") + +返回特定项目合并请求的单个讨论项 + +``` +GET /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `discussion_id` | integer | yes | 讨论项目的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7 +``` + +### Create new merge request thread[](#create-new-merge-request-thread "Permalink") + +为单个项目合并请求创建一个新线程. 这类似于创建便笺,但其他注释(回复)可以在以后添加. + +``` +POST /projects/:id/merge_requests/:merge_request_iid/discussions +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `body` | string | yes | 线程的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | +| `position` | hash | no | 创建差异注释时的位置 | +| `position[base_sha]` | string | yes | 源分支中的基本提交 SHA | +| `position[start_sha]` | string | yes | SHA 引用目标分支中的提交 | +| `position[head_sha]` | string | yes | SHA 引用此合并请求的 HEAD | +| `position[position_type]` | string | yes | 位置参考的类型",允许的值:"文本"或"图像" | +| `position[new_path]` | string | no | 更改后的文件路径 | +| `position[new_line]` | integer | no | 更改后的行号(用于"文本"差异注释) | +| `position[old_path]` | string | no | 更改前的文件路径 | +| `position[old_line]` | integer | no | 更改前的行号(用于"文本"差异注释) | +| `position[line_range]` | hash | no | 多行差异注释的行范围 | +| `position[line_range][start]` | hash | no | 多行音符起始行 | +| `position[line_range][start][line_code]` | string | yes | 起始行的行代码 | +| `position[line_range][start][type]` | string | yes | 起始线的线型 | +| `position[line_range][end]` | hash | no | 多行注释结束行 | +| `position[line_range][end][line_code]` | string | yes | 结束行的行代码 | +| `position[line_range][end][type]` | string | yes | 终点线的线型 | +| `position[width]` | integer | no | 图片宽度(用于"图片"差异注释) | +| `position[height]` | integer | no | 图片的高度(用于"图片"差异注释) | +| `position[x]` | integer | no | X 坐标(用于"图像"差异注释) | +| `position[y]` | integer | no | Y 坐标(用于"图像"差异注释) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions?body=comment" +``` + +### Resolve a merge request thread[](#resolve-a-merge-request-thread "Permalink") + +解决/取消解决合并请求的整个线程. + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `discussion_id` | integer | yes | 线程的 ID | +| `resolved` | boolean | yes | 解决/取消讨论 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7?resolved=true" +``` + +### Add note to existing merge request thread[](#add-note-to-existing-merge-request-thread "Permalink") + +向该线程添加新注释. 这也可以[从单个注释创建线程](../user/discussions/#start-a-thread-by-replying-to-a-standard-comment) . + +``` +POST /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id/notes +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment" +``` + +### Modify an existing merge request thread note[](#modify-an-existing-merge-request-thread-note "Permalink") + +修改或解决合并请求的现有线程注释. + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | no | 备注/回复的内容(必须是`body`或已`resolved`的内容之一) | +| `resolved` | boolean | no | 解析/取消解析音符(必须设置为刚好为`body`或已`resolved` | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment" +``` + +解决注释: + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?resolved=true" +``` + +### Delete a merge request thread note[](#delete-a-merge-request-thread-note "Permalink") + +删除合并请求的现有线程注释. + +``` +DELETE /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/636" +``` + +## Commits[](#commits "Permalink") + +### List project commit discussion items[](#list-project-commit-discussion-items "Permalink") + +获取单个提交的所有讨论项的列表. + +``` +GET /projects/:id/commits/:commit_id/discussions +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `commit_id` | integer | yes | 提交的 ID | + +``` +[ { "id": "6a9c1750b37d513a43987b574953fceb50b03ce7", "individual_note": false, "notes": [ { "id": 1126, "type": "DiscussionNote", "body": "discussion text", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-03T21:54:39.668Z", "updated_at": "2018-03-03T21:54:39.668Z", "system": false, "noteable_id": 3, "noteable_type": "Commit", "noteable_iid": null, "resolvable": false }, { "id": 1129, "type": "DiscussionNote", "body": "reply to the discussion", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T13:38:02.127Z", "updated_at": "2018-03-04T13:38:02.127Z", "system": false, "noteable_id": 3, "noteable_type": "Commit", "noteable_iid": null, "resolvable": false } ] }, { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": true, "notes": [ { "id": 1128, "type": null, "body": "a single comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Commit", "noteable_iid": null, "resolvable": false } ] } ] +``` + +差异评论还包含以下位置: + +``` +[ { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": false, "notes": [ { "id": 1128, "type": DiffNote, "body": "diff comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Commit", "noteable_iid": null, "position": { "base_sha": "b5d6e7b1613fca24d250fa8e5bc7bcc3dd6002ef", "start_sha": "7c9c2ead8a320fb7ba0b4e234bd9529a2614e306", "head_sha": "4803c71e6b1833ca72b8b26ef2ecd5adc8a38031", "old_path": "package.json", "new_path": "package.json", "position_type": "text", "old_line": 27, "new_line": 27 }, "resolvable": false } ] } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions" +``` + +### Get single commit discussion item[](#get-single-commit-discussion-item "Permalink") + +返回特定项目提交的单个讨论项 + +``` +GET /projects/:id/commits/:commit_id/discussions/:discussion_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `commit_id` | integer | yes | 提交的 ID | +| `discussion_id` | integer | yes | 讨论项目的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7" +``` + +### Create new commit thread[](#create-new-commit-thread "Permalink") + +为单个项目提交创建一个新线程. 这类似于创建便笺,但其他注释(回复)可以在以后添加. + +``` +POST /projects/:id/commits/:commit_id/discussions +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `commit_id` | integer | yes | 提交的 ID | +| `body` | string | yes | 线程的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | +| `position` | hash | no | 创建差异注释时的位置 | +| `position[base_sha]` | string | yes | 源分支中的基本提交 SHA | +| `position[start_sha]` | string | yes | SHA 引用目标分支中的提交 | +| `position[head_sha]` | string | yes | SHA 引用此提交的 HEAD | +| `position[position_type]` | string | yes | 位置参考的类型",允许的值:"文本"或"图像" | +| `position[new_path]` | string | no | 更改后的文件路径 | +| `position[new_line]` | integer | no | 变更后的行号 | +| `position[old_path]` | string | no | 更改前的文件路径 | +| `position[old_line]` | integer | no | 更改前的行号 | +| `position[width]` | integer | no | 图片宽度(用于"图片"差异注释) | +| `position[height]` | integer | no | 图片的高度(用于"图片"差异注释) | +| `position[x]` | integer | no | X 坐标(用于"图像"差异注释) | +| `position[y]` | integer | no | Y 坐标(用于"图像"差异注释) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions?body=comment" +``` + +### Add note to existing commit thread[](#add-note-to-existing-commit-thread "Permalink") + +向该线程添加新注释. + +``` +POST /projects/:id/commits/:commit_id/discussions/:discussion_id/notes +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `commit_id` | integer | yes | 提交的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment +``` + +### Modify an existing commit thread note[](#modify-an-existing-commit-thread-note "Permalink") + +修改或解决提交的现有线程注释. + +``` +PUT /projects/:id/commits/:commit_id/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `commit_id` | integer | yes | 提交的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | no | 笔记内容 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment" +``` + +解决注释: + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?resolved=true" +``` + +### Delete a commit thread note[](#delete-a-commit-thread-note "Permalink") + +删除提交的现有线程注释. + +``` +DELETE /projects/:id/commits/:commit_id/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `commit_id` | integer | yes | 提交的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/636" +``` \ No newline at end of file diff --git a/_book/docs/309.md b/_book/docs/309.md new file mode 100644 index 0000000000000000000000000000000000000000..78b448eb290678d4c25e95118d00947f442e178a --- /dev/null +++ b/_book/docs/309.md @@ -0,0 +1,50 @@ +# Dockerfiles API + +> 原文:[https://docs.gitlab.com/ee/api/templates/dockerfiles.html](https://docs.gitlab.com/ee/api/templates/dockerfiles.html) + +* [List Dockerfile templates](#list-dockerfile-templates) +* [Single Dockerfile template](#single-dockerfile-template) + +# Dockerfiles API[](#dockerfiles-api "Permalink") + +在 GitLab 中,有一个可用于 Dockerfile 的 API 端点. 有关 Dockerfile 的更多信息,请参阅[Docker 文档](https://s0docs0docker0com.icopy.site/engine/reference/builder/) . + +## List Dockerfile templates[](#list-dockerfile-templates "Permalink") + +获取所有 Dockerfile 模板. + +``` +GET /templates/dockerfiles +``` + +``` +curl https://gitlab.example.com/api/v4/templates/dockerfiles +``` + +响应示例: + +``` +[ { "key": "Binary", "name": "Binary" }, { "key": "Binary-alpine", "name": "Binary-alpine" }, { "key": "Binary-scratch", "name": "Binary-scratch" }, { "key": "Golang", "name": "Golang" }, { "key": "Golang-alpine", "name": "Golang-alpine" }, { "key": "Golang-scratch", "name": "Golang-scratch" }, { "key": "HTTPd", "name": "HTTPd" }, { "key": "Node", "name": "Node" }, { "key": "Node-alpine", "name": "Node-alpine" }, { "key": "OpenJDK", "name": "OpenJDK" }, { "key": "OpenJDK-alpine", "name": "OpenJDK-alpine" }, { "key": "PHP", "name": "PHP" }, { "key": "Python", "name": "Python" }, { "key": "Python-alpine", "name": "Python-alpine" }, { "key": "Python2", "name": "Python2" }, { "key": "Ruby", "name": "Ruby" }, { "key": "Ruby-alpine", "name": "Ruby-alpine" }, { "key": "Swift", "name": "Swift" } ] +``` + +## Single Dockerfile template[](#single-dockerfile-template "Permalink") + +获取单个 Dockerfile 模板. + +``` +GET /templates/dockerfiles/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `key` | string | yes | Dockerfile 模板的关键 | + +``` +curl https://gitlab.example.com/api/v4/templates/dockerfiles/Binary +``` + +响应示例: + +``` +{ "name": "Binary", "content": "# This file is a template, and might need editing before it works on your project.\n# This Dockerfile installs a compiled binary into a bare system.\n# You must either commit your compiled binary into source control (not recommended)\n# or build the binary first as part of a CI/CD pipeline.\n\nFROM buildpack-deps:jessie\n\nWORKDIR /usr/local/bin\n\n# Change `app` to whatever your binary is called\nAdd app .\nCMD [\"./app\"]\n" } +``` \ No newline at end of file diff --git a/_book/docs/310.md b/_book/docs/310.md new file mode 100644 index 0000000000000000000000000000000000000000..5ef44bb2bf56f0288ea8b09e020c342791ba2e99 --- /dev/null +++ b/_book/docs/310.md @@ -0,0 +1,151 @@ +# Environments API + +> 原文:[https://docs.gitlab.com/ee/api/environments.html](https://docs.gitlab.com/ee/api/environments.html) + +* [List environments](#list-environments) +* [Get a specific environment](#get-a-specific-environment) +* [Create a new environment](#create-a-new-environment) +* [Edit an existing environment](#edit-an-existing-environment) +* [Delete an environment](#delete-an-environment) +* [Stop an environment](#stop-an-environment) + +# Environments API[](#environments-api "Permalink") + +## List environments[](#list-environments "Permalink") + +获取给定项目的所有环境. + +``` +GET /projects/:id/environments +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | no | 使用此名称返回环境. 与`search`互斥 | +| `search` | string | no | 返回符合搜索条件的环境列表. 与`name`互斥 | +| `states` | string | no | 列出与特定状态匹配的所有环境. 接受的值: `available`或已`stopped` . 如果没有给出状态值,则返回所有环境. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments?name=review%2Ffix-foo" +``` + +响应示例: + +``` +[ { "id": 1, "name": "review/fix-foo", "slug": "review-fix-foo-dfjre3", "external_url": "https://review-fix-foo-dfjre3.example.gitlab.com", "state": "available" } ] +``` + +## Get a specific environment[](#get-a-specific-environment "Permalink") + +``` +GET /projects/:id/environments/:environment_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `environment_id` | integer | yes | 环境的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments/1" +``` + +回应范例 + +``` +{ "id": 1, "name": "review/fix-foo", "slug": "review-fix-foo-dfjre3", "external_url": "https://review-fix-foo-dfjre3.example.gitlab.com" "state": "available", "last_deployment": { "id": 100, "iid": 34, "ref": "fdroid", "sha": "416d8ea11849050d3d1f5104cf8cf51053e790ab", "created_at": "2019-03-25T18:55:13.252Z", "status": "success", "user": { "id": 1, "name": "Administrator", "state": "active", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" } "deployable": { "id": 710, "status": "success", "stage": "deploy", "name": "staging", "ref": "fdroid", "tag": false, "coverage": null, "created_at": "2019-03-25T18:55:13.215Z", "started_at": "2019-03-25T12:54:50.082Z", "finished_at": "2019-03-25T18:55:13.216Z", "duration": 21623.13423, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": null } "commit": { "id": "416d8ea11849050d3d1f5104cf8cf51053e790ab", "short_id": "416d8ea1", "created_at": "2016-01-02T15:39:18.000Z", "parent_ids": [ "e9a4449c95c64358840902508fc827f1a2eab7df" ], "title": "Removed fabric to fix #40", "message": "Removed fabric to fix #40\n", "author_name": "Administrator", "author_email": "admin@example.com", "authored_date": "2016-01-02T15:39:18.000Z", "committer_name": "Administrator", "committer_email": "admin@example.com", "committed_date": "2016-01-02T15:39:18.000Z" }, "pipeline": { "id": 34, "sha": "416d8ea11849050d3d1f5104cf8cf51053e790ab", "ref": "fdroid", "status": "success", "web_url": "http://localhost:3000/Commit451/lab-coat/pipelines/34" }, "web_url": "http://localhost:3000/Commit451/lab-coat/-/jobs/710", "artifacts": [ { "file_type": "trace", "size": 1305, "filename": "job.log", "file_format": null } ], "runner": null, "artifacts_expire_at": null } } } +``` + +## Create a new environment[](#create-a-new-environment "Permalink") + +使用给定名称和`external_url`创建一个新环境. + +如果成功创建了环境,则返回`201`否则返回`400` . + +``` +POST /projects/:id/environments +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 环境名称 | +| `external_url` | string | no | Place to link to for this environment | + +``` +curl --data "name=deploy&external_url=https://deploy.example.gitlab.com" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments" +``` + +响应示例: + +``` +{ "id": 1, "name": "deploy", "slug": "deploy", "external_url": "https://deploy.example.gitlab.com", "state": "available" } +``` + +## Edit an existing environment[](#edit-an-existing-environment "Permalink") + +更新现有环境的名称和/或`external_url` . + +如果成功更新了环境,它将返回`200` . 如果出现错误,则返回状态码`400` . + +``` +PUT /projects/:id/environments/:environments_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `environment_id` | integer | yes | 环境的 ID | +| `name` | string | no | 环境的新名称 | +| `external_url` | string | no | 新的`external_url` | + +``` +curl --request PUT --data "name=staging&external_url=https://staging.example.gitlab.com" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments/1" +``` + +响应示例: + +``` +{ "id": 1, "name": "staging", "slug": "staging", "external_url": "https://staging.example.gitlab.com", "state": "available" } +``` + +## Delete an environment[](#delete-an-environment "Permalink") + +如果成功删除了环境,则返回`204`如果环境不存在,则返回`404` . + +``` +DELETE /projects/:id/environments/:environment_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `environment_id` | integer | yes | 环境的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments/1" +``` + +## Stop an environment[](#stop-an-environment "Permalink") + +如果成功停止了环境,则返回`200`如果环境不存在,则返回`404` . + +``` +POST /projects/:id/environments/:environment_id/stop +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `environment_id` | integer | yes | 环境的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments/1/stop" +``` + +响应示例: + +``` +{ "id": 1, "name": "deploy", "slug": "deploy", "external_url": "https://deploy.example.gitlab.com", "state": "stopped" } +``` \ No newline at end of file diff --git a/_book/docs/311.md b/_book/docs/311.md new file mode 100644 index 0000000000000000000000000000000000000000..955fc44fe850e65750002a5b775723d41e7a4c43 --- /dev/null +++ b/_book/docs/311.md @@ -0,0 +1,217 @@ +# Epics API + +> 原文:[https://docs.gitlab.com/ee/api/epics.html](https://docs.gitlab.com/ee/api/epics.html) + +* [Epic issues API](#epic-issues-api) +* [Milestone dates integration](#milestone-dates-integration) +* [Epics pagination](#epics-pagination) +* [List epics for a group](#list-epics-for-a-group) +* [Single epic](#single-epic) +* [New epic](#new-epic) +* [Update epic](#update-epic) +* [Delete epic](#delete-epic) +* [Create a todo](#create-a-todo) + +# Epics API[](#epics-api-premium "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.2 中引入. +* 单级史诗在 12.8 [中移至](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) [GitLab Premium](https://about.gitlab.com/pricing/) . + +对史诗的每个 API 调用都必须经过身份验证. + +如果用户不是组的成员,并且该组是私有的,则对该组的`GET`请求将导致`404`状态代码. + +如果没有史诗功能,将返回`403`状态代码. + +## Epic issues API[](#epic-issues-api "Permalink") + +[史诗问题 API](epic_issues.html)使您可以与[史诗相关的问题](epic_issues.html)进行交互. + +## Milestone dates integration[](#milestone-dates-integration "Permalink") + +在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6448) . + +由于可以从相关的发行里程碑动态地获取开始日期和截止日期,因此当用户具有编辑权限时,将显示其他字段. 其中包括两个布尔字段`start_date_is_fixed`和`due_date_is_fixed` ,以及四个日期字段`start_date_fixed` , `start_date_from_inherited_source` , `due_date_fixed`和`due_date_from_inherited_source` . + +* 不建议使用`end_date` ,而应使用`due_date` . +* 不赞成使用`start_date_from_milestones` ,而建议使用`start_date_from_inherited_source` +* 不建议使用`due_date_from_milestones` ,而应使用`due_date_from_inherited_source` + +## Epics pagination[](#epics-pagination "Permalink") + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +**弃用:不建议使用**响应中的`reference`属性,而推荐使用`references` . >推出了[GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354)**注意:** > `references.relative`相对于正在请求史诗的组. 从史诗组的原始组中提取史诗时, `relative`格式将与`short`格式相同,而在请求的交叉组中, `relative`格式应与`full`格式相同. + +## List epics for a group[](#list-epics-for-a-group "Permalink") + +获取请求的组及其子组的所有史诗. + +``` +GET /groups/:id/epics +GET /groups/:id/epics?author_id=5 +GET /groups/:id/epics?labels=bug,reproduced +GET /groups/:id/epics?state=opened +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.html#namespaced-path-encoding) owned by the authenticated user | +| `author_id` | integer | no | 返回由给定用户`id`创建的史诗 | +| `labels` | string | no | 返回与以逗号分隔的标签名称列表匹配的史诗. 可以使用史诗组或父组的标签名称 | +| `with_labels_details` | boolean | no | 如果为`true` ,则响应将为标签字段中的每个标签返回更多详细信息`:name` , `:color` , `:description` , `:description_html` , `:text_color` . 默认值为`false` . 在[GitLab 12.7 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)引入 | +| `order_by` | string | no | 返回按`created_at`或`updated_at`字段排序的史诗. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`排列的史诗. 默认为`desc` | +| `search` | string | no | 根据`title`和`description`搜索史诗 | +| `state` | string | no | 根据`state`搜索史诗,可能的过滤条件: `opened` , `closed`和`all` ,默认值: `all` | +| `created_after` | datetime | no | 返回在给定时间或之后创建的史诗 | +| `created_before` | datetime | no | 返回在给定时间或之前创建的史诗 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的史诗 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的史诗 | +| `include_ancestor_groups` | boolean | no | 包括请求组祖先的史诗. 默认为`false` | +| `include_descendant_groups` | boolean | no | 包括请求组后代的史诗. 默认为`true` | +| `my_reaction_emoji` | string | no | 返回给定表情符号由已认证用户做出反应的史诗. `None`返回没有反应的史诗. 给定至少一个反应, `Any`回报史诗. 在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31479)引入 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics" +``` + +响应示例: + +``` +[ { "id": 29, "iid": 4, "group_id": 7, "parent_id": 23, "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "state": "opened", "confidential": "false", "web_url": "http://localhost:3001/groups/test/-/epics/4", "reference": "&4", "references": { "short": "&4", "relative": "&4", "full": "test&4" }, "author": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, "downvotes": 0 }, { "id": 50, "iid": 35, "group_id": 17, "parent_id": 19, "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "state": "opened", "web_url": "http://localhost:3001/groups/test/sample/-/epics/4", "reference": "&4", "references": { "short": "&4", "relative": "sample&4", "full": "test/sample&4" }, "author": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, "downvotes": 0 } ] +``` + +## Single epic[](#single-epic "Permalink") + +取得史诗 + +``` +GET /groups/:id/epics/:epic_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5" +``` + +响应示例: + +``` +{ "id": 30, "iid": 5, "group_id": 7, "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "state": "opened", "web_url": "http://localhost:3001/groups/test/-/epics/5", "reference": "&5", "references": { "short": "&5", "relative": "&5", "full": "test&5" }, "author":{ "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, "downvotes": 0, "subscribed": true } +``` + +## New epic[](#new-epic "Permalink") + +创建一个新的史诗. + +**注意:**从 GitLab [11.3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6448)开始,不应再直接分配`start_date`和`end_date` ,因为它们现在表示复合值. 您可以改为通过`*_is_fixed`和`*_fixed`字段进行配置. + +``` +POST /groups/:id/epics +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `title` | string | yes | 史诗的标题 | +| `labels` | string | no | 以逗号分隔的标签列表 | +| `description` | string | no | 史诗般的描述. 限制为 1,048,576 个字符. | +| `confidential` | boolean | no | 史诗是否应该保密. 如果禁用`confidential_epics`功能标志,将被忽略. | +| `start_date_is_fixed` | boolean | no | 开始日期是从`start_date_fixed`还是从里程碑(自 11.3 开始) | +| `start_date_fixed` | string | no | 史诗的固定开始日期(自 11.3 开始) | +| `due_date_is_fixed` | boolean | no | 是否应从`due_date_fixed`或里程碑(从 11.3 开始)中`due_date_fixed`到期日期 | +| `due_date_fixed` | string | no | 史诗的固定到期日(自 11.3 开始) | +| `parent_id` | integer/string | no | 父级史诗的 ID(自 11.11 起) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics?title=Epic&description=Epic%20description" +``` + +响应示例: + +``` +{ "id": 33, "iid": 6, "group_id": 7, "title": "Epic", "description": "Epic description", "state": "opened", "confidential": "false", "web_url": "http://localhost:3001/groups/test/-/epics/6", "reference": "&6", "references": { "short": "&6", "relative": "&6", "full": "test&6" }, "author": { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, "downvotes": 0 } +``` + +## Update epic[](#update-epic "Permalink") + +更新史诗. + +**注意:**从 GitLab [11.3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6448)开始,不应再直接分配`start_date`和`end_date` ,因为它们现在表示复合值. 您可以改为通过`*_is_fixed`和`*_fixed`字段进行配置. + +``` +PUT /groups/:id/epics/:epic_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID | +| `title` | string | no | 史诗的标题 | +| `description` | string | no | 史诗的描述. 限制为 1,048,576 个字符. | +| `confidential` | boolean | no | 史诗是否应该保密. 如果禁用`confidential_epics`功能标志,将被忽略. | +| `labels` | string | no | 以逗号分隔的标签列表 | +| `start_date_is_fixed` | boolean | no | 开始日期是从`start_date_fixed`还是从里程碑(自 11.3 开始) | +| `start_date_fixed` | string | no | 史诗的固定开始日期(自 11.3 开始) | +| `due_date_is_fixed` | boolean | no | 是否应从`due_date_fixed`或里程碑(从 11.3 开始)中`due_date_fixed`到期日期 | +| `due_date_fixed` | string | no | 史诗的固定到期日(自 11.3 开始) | +| `state_event` | string | no | 史诗般的状态事件. 设置为`close`以关闭史诗,然后`reopen`以重新打开(自 11.4 开始) | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5?title=New%20Title" +``` + +响应示例: + +``` +{ "id": 33, "iid": 6, "group_id": 7, "title": "New Title", "description": "Epic description", "state": "opened", "confidential": "false", "web_url": "http://localhost:3001/groups/test/-/epics/6", "reference": "&6", "references": { "short": "&6", "relative": "&6", "full": "test&6" }, "author": { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, "downvotes": 0 } +``` + +## Delete epic[](#delete-epic "Permalink") + +删除史诗 + +``` +DELETE /groups/:id/epics/:epic_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5" +``` + +## Create a todo[](#create-a-todo "Permalink") + +在史诗上为当前用户手动创建待办事项. 如果该史诗上已经存在用户的待办事项,则返回状态码`304` . + +``` +POST /groups/:id/epics/:epic_iid/todo +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer | yes | 群组史诗的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/todo" +``` + +响应示例: + +``` +{ "id": 112, "group": { "id": 1, "name": "Gitlab", "path": "gitlab", "kind": "group", "full_path": "base/gitlab", "parent_id": null }, "author": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "action_name": "marked", "target_type": "epic", "target": { "id": 30, "iid": 5, "group_id": 1, "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author":{ "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }, "web_url": "http://localhost:3001/groups/test/-/epics/5", "reference": "&5", "references": { "short": "&5", "relative": "&5", "full": "test&5" }, "start_date": null, "end_date": null, "created_at": "2018-01-21T06:21:13.165Z", "updated_at": "2018-01-22T12:41:41.166Z", "closed_at": "2018-08-18T12:22:05.239Z" }, "target_url": "https://gitlab.example.com/groups/epics/5", "body": "Vel voluptas atque dicta mollitia adipisci qui at.", "state": "pending", "created_at": "2016-07-01T11:09:13.992Z" } +``` \ No newline at end of file diff --git a/_book/docs/312.md b/_book/docs/312.md new file mode 100644 index 0000000000000000000000000000000000000000..ab925710125313d08409ac572631809a2c9a999a --- /dev/null +++ b/_book/docs/312.md @@ -0,0 +1,157 @@ +# Events + +> 原文:[https://docs.gitlab.com/ee/api/events.html](https://docs.gitlab.com/ee/api/events.html) + +* [Filter parameters](#filter-parameters) + * [Action Types](#action-types) + * [Target Types](#target-types) + * [Date formatting](#date-formatting) + * [Event Time Period Limit](#event-time-period-limit) +* [List currently authenticated user’s events](#list-currently-authenticated-users-events) + * [Get user contribution events](#get-user-contribution-events) +* [List a Project’s visible events](#list-a-projects-visible-events) + +# Events[](#events "Permalink") + +## Filter parameters[](#filter-parameters "Permalink") + +### Action Types[](#action-types "Permalink") + +`action`参数的可用操作类型为: + +* `created` +* `updated` +* `closed` +* `reopened` +* `pushed` +* `commented` +* `merged` +* `joined` +* `left` +* `destroyed` +* `expired` + +请注意,这些选项是小写的. + +### Target Types[](#target-types "Permalink") + +`target_type`参数的可用目标类型为: + +* `issue` +* `milestone` +* `merge_request` +* `note` +* `project` +* `snippet` +* `user` + +请注意,这些选项是小写的. + +### Date formatting[](#date-formatting "Permalink") + +`before`和`after`参数的日期应以以下格式提供: + +``` +YYYY-MM-DD +``` + +### Event Time Period Limit[](#event-time-period-limit "Permalink") + +GitLab removes events older than 2 years from the events table for performance reasons. + +## List currently authenticated user’s events[](#list-currently-authenticated-users-events "Permalink") + +**注意:**该端点是在 GitLab 9.3 中引入的. 在 GitLab 11.3 中引入了`read_user`访问. + +获取经过身份验证的用户的事件列表. 范围`read_user`或`api`是必需的. + +``` +GET /events +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `action` | string | no | 仅包括特定[动作类型的](#action-types)事件 | +| `target_type` | string | no | 仅包括特定[目标类型的](#target-types)事件 | +| `before` | date | no | 仅包括在特定日期之前创建的事件. 请[在此处查看受支持的格式](#date-formatting) | +| `after` | date | no | 仅包括在特定日期之后创建的事件. 请[在此处查看受支持的格式](#date-formatting) | +| `scope` | string | no | 包括用户项目中的所有事件. | +| `sort` | string | no | 按`created_at`对事件进行`asc`或`desc`排序. 默认为`desc` | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/events?target_type=issue&action=created&after=2017-01-31&before=2017-03-01&scope=all" +``` + +响应示例: + +``` +[ { "title":null, "project_id":1, "action_name":"opened", "target_id":160, "target_type":"Issue", "author_id":25, "target_title":"Qui natus eos odio tempore et quaerat consequuntur ducimus cupiditate quis.", "created_at":"2017-02-09T10:43:19.667Z", "author":{ "name":"User 3", "username":"user3", "id":25, "state":"active", "avatar_url":"http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/user3" }, "author_username":"user3" }, { "title":null, "project_id":1, "action_name":"opened", "target_id":159, "target_type":"Issue", "author_id":21, "target_title":"Nostrum enim non et sed optio illo deleniti non.", "created_at":"2017-02-09T10:43:19.426Z", "author":{ "name":"Test User", "username":"ted", "id":21, "state":"active", "avatar_url":"http://www.gravatar.com/avatar/80fb888c9a48b9a3f87477214acaa63f?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/ted" }, "author_username":"ted" } ] +``` + +### Get user contribution events[](#get-user-contribution-events "Permalink") + +**注意:**文档以前位于" [用户 API"页面中](users.html) . 在 GitLab 11.3 中引入了`read_user`访问. + +获取指定用户的贡献事件,从最新到最旧排序. 范围`read_user`或`api`是必需的. + +``` +GET /users/:id/events +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 用户的 ID 或用户名 | +| `action` | string | no | 仅包括特定[动作类型的](#action-types)事件 | +| `target_type` | string | no | 仅包括特定[目标类型的](#target-types)事件 | +| `before` | date | no | 仅包括在特定日期之前创建的事件. 请[在此处查看受支持的格式](#date-formatting) | +| `after` | date | no | 仅包括在特定日期之后创建的事件. 请[在此处查看受支持的格式](#date-formatting) | +| `sort` | string | no | 按`created_at`对事件进行`asc`或`desc`排序. 默认为`desc` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/:id/events" +``` + +响应示例: + +``` +[ { "title": null, "project_id": 15, "action_name": "closed", "target_id": 830, "target_type": "Issue", "author_id": 1, "target_title": "Public project search field", "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", "web_url": "http://localhost:3000/root" }, "author_username": "root" }, { "title": null, "project_id": 15, "action_name": "pushed", "target_id": null, "target_type": null, "author_id": 1, "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", "web_url": "http://localhost:3000/root" }, "author_username": "john", "push_data": { "commit_count": 1, "action": "pushed", "ref_type": "branch", "commit_from": "50d4420237a9de7be1304607147aec22e4a14af7", "commit_to": "c5feabde2d8cd023215af4d2ceeb7a64839fc428", "ref": "master", "commit_title": "Add simple search to projects in public area" }, "target_title": null }, { "title": null, "project_id": 15, "action_name": "closed", "target_id": 840, "target_type": "Issue", "author_id": 1, "target_title": "Finish & merge Code search PR", "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", "web_url": "http://localhost:3000/root" }, "author_username": "root" }, { "title": null, "project_id": 15, "action_name": "commented on", "target_id": 1312, "target_type": "Note", "author_id": 1, "target_title": null, "created_at": "2015-12-04T10:33:58.089Z", "note": { "id": 1312, "body": "What an awesome day!", "attachment": null, "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", "web_url": "http://localhost:3000/root" }, "created_at": "2015-12-04T10:33:56.698Z", "system": false, "noteable_id": 377, "noteable_type": "Issue" }, "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", "web_url": "http://localhost:3000/root" }, "author_username": "root" } ] +``` + +## List a Project’s visible events[](#list-a-projects-visible-events "Permalink") + +> **注意:**此端点的时间比其他端点长. 文档以前位于[Projects API 页面中](projects.html) . + +获取特定项目的可见事件列表. + +``` +GET /projects/:project_id/events +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `project_id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `action` | string | no | 仅包括特定[动作类型的](#action-types)事件 | +| `target_type` | string | no | 仅包括特定[目标类型的](#target-types)事件 | +| `before` | date | no | 仅包括在特定日期之前创建的事件. 请[在此处查看受支持的格式](#date-formatting) | +| `after` | date | no | 仅包括在特定日期之后创建的事件. 请[在此处查看受支持的格式](#date-formatting) | +| `sort` | string | no | 按`created_at`对事件进行`asc`或`desc`排序. 默认为`desc` | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:project_id/events?target_type=issue&action=created&after=2017-01-31&before=2017-03-01" +``` + +响应示例: + +``` +[ { "title":null, "project_id":1, "action_name":"opened", "target_id":160, "target_iid":160, "target_type":"Issue", "author_id":25, "target_title":"Qui natus eos odio tempore et quaerat consequuntur ducimus cupiditate quis.", "created_at":"2017-02-09T10:43:19.667Z", "author":{ "name":"User 3", "username":"user3", "id":25, "state":"active", "avatar_url":"http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/user3" }, "author_username":"user3" }, { "title":null, "project_id":1, "action_name":"opened", "target_id":159, "target_iid":159, "target_type":"Issue", "author_id":21, "target_title":"Nostrum enim non et sed optio illo deleniti non.", "created_at":"2017-02-09T10:43:19.426Z", "author":{ "name":"Test User", "username":"ted", "id":21, "state":"active", "avatar_url":"http://www.gravatar.com/avatar/80fb888c9a48b9a3f87477214acaa63f?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/ted" }, "author_username":"ted" }, { "title": null, "project_id": 1, "action_name": "commented on", "target_id": 1312, "target_iid": 1312, "target_type": "Note", "author_id": 1, "data": null, "target_title": null, "created_at": "2015-12-04T10:33:58.089Z", "note": { "id": 1312, "body": "What an awesome day!", "attachment": null, "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "https://gitlab.example.com/uploads/user/avatar/1/fox_avatar.png", "web_url": "https://gitlab.example.com/root" }, "created_at": "2015-12-04T10:33:56.698Z", "system": false, "noteable_id": 377, "noteable_type": "Issue", "noteable_iid": 377 }, "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "https://gitlab.example.com/uploads/user/avatar/1/fox_avatar.png", "web_url": "https://gitlab.example.com/root" }, "author_username": "root" } ] +``` \ No newline at end of file diff --git a/_book/docs/313.md b/_book/docs/313.md new file mode 100644 index 0000000000000000000000000000000000000000..a62c22d15fe46a1578426d736b17c33df8b3c5c4 --- /dev/null +++ b/_book/docs/313.md @@ -0,0 +1,160 @@ +# Feature Flags API + +> 原文:[https://docs.gitlab.com/ee/api/feature_flags.html](https://docs.gitlab.com/ee/api/feature_flags.html) + +* [Feature Flags pagination](#feature-flags-pagination) +* [List feature flags for a project](#list-feature-flags-for-a-project) +* [Get a single feature flag](#get-a-single-feature-flag) +* [Create a feature flag](#create-a-feature-flag) +* [Update a feature flag](#update-a-feature-flag) +* [Delete a feature flag](#delete-a-feature-flag) + +# Feature Flags API[](#feature-flags-api-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5. + +**注意:**此 API 位于[功能标志的](../operations/feature_flags.html#enable-or-disable-feature-flag-strategies)后面. 如果您的环境中未启用此标志,则可以使用[旧功能标志 API](feature_flags_legacy.html) . + +用于访问[GitLab 功能标记](../operations/feature_flags.html)资源的 API. + +具有开发者或更高[权限的用户](../user/permissions.html)可以访问功能标记 API. + +## Feature Flags pagination[](#feature-flags-pagination "Permalink") + +默认情况下,因为 API 结果是[分页的](README.html#pagination) ,所以`GET`请求一次返回 20 个结果. + +## List feature flags for a project[](#list-feature-flags-for-a-project "Permalink") + +获取所请求项目的所有功能标志. + +``` +GET /projects/:id/feature_flags +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `scope` | string | no | 功能标志的条件,其中之一: `enabled` , `disabled` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/feature_flags" +``` + +响应示例: + +``` +[ { "name":"merge_train", "description":"This feature is about merge train", "version": "new_version_flag", "created_at":"2019-11-04T08:13:51.423Z", "updated_at":"2019-11-04T08:13:51.423Z", "scopes":[], "strategies": [ { "id": 1, "name": "userWithId", "parameters": { "userIds": "user1" }, "scopes": [ { "id": 1, "environment_scope": "production" } ] } ] }, { "name":"new_live_trace", "description":"This is a new live trace feature", "version": "new_version_flag", "created_at":"2019-11-04T08:13:10.507Z", "updated_at":"2019-11-04T08:13:10.507Z", "scopes":[] "strategies": [ { "id": 2, "name": "default", "parameters": {}, "scopes": [ { "id": 2, "environment_scope": "staging" } ] } ] } ] +``` + +## Get a single feature flag[](#get-a-single-feature-flag "Permalink") + +获取单个功能标志. + +``` +GET /projects/:id/feature_flags/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `name` | string | yes | The name of the feature flag. | + +``` +curl --header "PRIVATE-TOKEN: " https://gitlab.example.com/api/v4/projects/1/feature_flags/awesome_feature +``` + +响应示例: + +``` +{ "name": "awesome_feature", "description": null, "version": "new_version_flag", "created_at": "2020-05-13T19:56:33.119Z", "updated_at": "2020-05-13T19:56:33.119Z", "scopes": [], "strategies": [ { "id": 36, "name": "default", "parameters": {}, "scopes": [ { "id": 37, "environment_scope": "production" } ] } ] } +``` + +## Create a feature flag[](#create-a-feature-flag "Permalink") + +创建一个新的功能标志. + +``` +POST /projects/:id/feature_flags +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `name` | string | yes | 功能标志的名称. | +| `version` | string | yes | 功能标志的版本. 必须是`new_version_flag` . 省略或设置为`legacy_flag`即可创建[旧版功能标志](feature_flags_legacy.html) . | +| `description` | string | no | 功能标志的描述. | +| `strategies` | JSON | no | 特征标志[策略](../operations/feature_flags.html#feature-flag-strategies) . | +| `strategies:name` | JSON | no | 策略名称. | +| `strategies:parameters` | JSON | no | 策略参数. | +| `strategies:scopes` | JSON | no | 策略的范围. | +| `strategies:scopes:environment_scope` | string | no | 范围的环境规格. | + +``` +curl "https://gitlab.example.com/api/v4/projects/1/feature_flags" \ + --header "PRIVATE-TOKEN: " \ + --header "Content-type: application/json" \ + --data @- << EOF { + "name": "awesome_feature", + "version": "new_version_flag", + "strategies": [{ "name": "default", "parameters": {}, "scopes": [{ "environment_scope": "production" }] }] +} EOF +``` + +响应示例: + +``` +{ "name": "awesome_feature", "description": null, "version": "new_version_flag", "created_at": "2020-05-13T19:56:33.119Z", "updated_at": "2020-05-13T19:56:33.119Z", "scopes": [], "strategies": [ { "id": 36, "name": "default", "parameters": {}, "scopes": [ { "id": 37, "environment_scope": "production" } ] } ] } +``` + +## Update a feature flag[](#update-a-feature-flag "Permalink") + +更新功能标志. + +``` +PUT /projects/:id/feature_flags/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `name` | string | yes | 功能标志的名称. | +| `description` | string | no | 功能标志的描述. | +| `strategies` | JSON | no | 特征标志[策略](../operations/feature_flags.html#feature-flag-strategies) . | +| `strategies:id` | JSON | no | 功能标记策略 ID. | +| `strategies:name` | JSON | no | 策略名称. | +| `strategies:parameters` | JSON | no | 策略参数. | +| `strategies:scopes` | JSON | no | 策略的范围. | +| `strategies:scopes:id` | JSON | no | 范围 ID. | +| `strategies:scopes:environment_scope` | string | no | 范围的环境规格. | + +``` +curl "https://gitlab.example.com/api/v4/projects/1/feature_flags/awesome_feature" \ + --header "PRIVATE-TOKEN: " \ + --header "Content-type: application/json" \ + --data @- << EOF { + "strategies": [{ "name": "gradualRolloutUserId", "parameters": { "groupId": "default", "percentage": "25" }, "scopes": [{ "environment_scope": "staging" }] }] +} EOF +``` + +响应示例: + +``` +{ "name": "awesome_feature", "description": null, "version": "new_version_flag", "created_at": "2020-05-13T20:10:32.891Z", "updated_at": "2020-05-13T20:10:32.891Z", "scopes": [], "strategies": [ { "id": 38, "name": "gradualRolloutUserId", "parameters": { "groupId": "default", "percentage": "25" }, "scopes": [ { "id": 40, "environment_scope": "staging" } ] }, { "id": 37, "name": "default", "parameters": {}, "scopes": [ { "id": 39, "environment_scope": "production" } ] } ] } +``` + +## Delete a feature flag[](#delete-a-feature-flag "Permalink") + +删除功能标志. + +``` +DELETE /projects/:id/feature_flags/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `name` | string | yes | 功能标志的名称. | + +``` +curl --header "PRIVATE-TOKEN: " --request DELETE "https://gitlab.example.com/api/v4/projects/1/feature_flags/awesome_feature" +``` \ No newline at end of file diff --git a/_book/docs/314.md b/_book/docs/314.md new file mode 100644 index 0000000000000000000000000000000000000000..5127fc0288d4243b900553d132e9543afe99489d --- /dev/null +++ b/_book/docs/314.md @@ -0,0 +1,142 @@ +# Feature flag user lists API + +> 原文:[https://docs.gitlab.com/ee/api/feature_flag_user_lists.html](https://docs.gitlab.com/ee/api/feature_flag_user_lists.html) + +* [List all feature flag user lists for a project](#list-all-feature-flag-user-lists-for-a-project) +* [Create a feature flag user list](#create-a-feature-flag-user-list) +* [Get a feature flag user list](#get-a-feature-flag-user-list) +* [Update a feature flag user list](#update-a-feature-flag-user-list) +* [Delete feature flag user list](#delete-feature-flag-user-list) + +# Feature flag user lists API[](#feature-flag-user-lists-api-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/205409) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10. + +用于访问 GitLab 功能标志用户列表的 API. + +具有开发者或更高[权限的用户](../user/permissions.html)可以访问功能标志用户列表 API. + +**注意:** `GET`请求一次返回 20 个结果,因为 API 结果是[分页的](README.html#pagination) . 您可以更改此值. + +## List all feature flag user lists for a project[](#list-all-feature-flag-user-lists-for-a-project "Permalink") + +获取所请求项目的所有功能标志用户列表. + +``` +GET /projects/:id/feature_flags_user_lists +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists" +``` + +响应示例: + +``` +[ { "name": "user_list", "user_xids": "user1,user2", "id": 1, "iid": 1, "project_id": 1, "created_at": "2020-02-04T08:13:51.423Z", "updated_at": "2020-02-04T08:13:51.423Z" }, { "name": "test_users", "user_xids": "user3,user4,user5", "id": 2, "iid": 2, "project_id": 1, "created_at": "2020-02-04T08:13:10.507Z", "updated_at": "2020-02-04T08:13:10.507Z" } ] +``` + +## Create a feature flag user list[](#create-a-feature-flag-user-list "Permalink") + +创建功能标记用户列表. + +``` +POST /projects/:id/feature_flags_user_lists +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `name` | string | yes | 功能标志的名称. | +| `user_xids` | string | yes | 以逗号分隔的用户 ID 列表. | + +``` +curl "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists" \ + --header "PRIVATE-TOKEN: " \ + --header "Content-type: application/json" \ + --data @- << EOF { + "name": "my_user_list", + "user_xids": "user1,user2,user3" +} EOF +``` + +响应示例: + +``` +{ "name": "my_user_list", "user_xids": "user1,user2,user3", "id": 1, "iid": 1, "project_id": 1, "created_at": "2020-02-04T08:32:27.288Z", "updated_at": "2020-02-04T08:32:27.288Z" } +``` + +## Get a feature flag user list[](#get-a-feature-flag-user-list "Permalink") + +获取功能标志用户列表. + +``` +GET /projects/:id/feature_flags_user_lists/:iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `iid` | integer/string | yes | 项目的功能标志用户列表的内部 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists/1" +``` + +响应示例: + +``` +{ "name": "my_user_list", "user_xids": "123,456", "id": 1, "iid": 1, "project_id": 1, "created_at": "2020-02-04T08:13:10.507Z", "updated_at": "2020-02-04T08:13:10.507Z", } +``` + +## Update a feature flag user list[](#update-a-feature-flag-user-list "Permalink") + +更新功能标志用户列表. + +``` +PUT /projects/:id/feature_flags_user_lists/:iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `iid` | integer/string | yes | 项目的功能标志用户列表的内部 ID. | +| `name` | string | no | 功能标志的名称. | +| `user_xids` | string | no | 以逗号分隔的用户 ID 列表. | + +``` +curl "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists/1" \ + --header "PRIVATE-TOKEN: " \ + --header "Content-type: application/json" \ + --request PUT \ + --data @- << EOF { + "user_xids": "user2,user3,user4" +} EOF +``` + +响应示例: + +``` +{ "name": "my_user_list", "user_xids": "user2,user3,user4", "id": 1, "iid": 1, "project_id": 1, "created_at": "2020-02-04T08:32:27.288Z", "updated_at": "2020-02-05T09:33:17.179Z" } +``` + +## Delete feature flag user list[](#delete-feature-flag-user-list "Permalink") + +删除功能标志用户列表. + +``` +DELETE /projects/:id/feature_flags_user_lists/:iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `iid` | integer/string | yes | 项目的功能标志用户列表的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " --request DELETE "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists/1" +``` \ No newline at end of file diff --git a/_book/docs/315.md b/_book/docs/315.md new file mode 100644 index 0000000000000000000000000000000000000000..25cd7e923c4f80a25ae79a5906e2aae2231269aa --- /dev/null +++ b/_book/docs/315.md @@ -0,0 +1,147 @@ +# Freeze Periods API + +> 原文:[https://docs.gitlab.com/ee/api/freeze_periods.html](https://docs.gitlab.com/ee/api/freeze_periods.html) + +* [Permissions and security](#permissions-and-security) +* [List Freeze Periods](#list-freeze-periods) +* [Get a Freeze Period by a `freeze_period_id`](#get-a-freeze-period-by-a-freeze_period_id) +* [Create a Freeze Period](#create-a-freeze-period) +* [Update a Freeze Period](#update-a-freeze-period) +* [Delete a Freeze Period](#delete-a-freeze-period) + +# Freeze Periods API[](#freeze-periods-api "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29382) . + +您可以使用 Freeze Periods API 来操纵 GitLab 的[Freeze Period](../user/project/releases/index.html#prevent-unintentional-releases-by-setting-a-deploy-freeze)条目. + +## Permissions and security[](#permissions-and-security "Permalink") + +只有具有维护者[权限的](../user/permissions.html)用户才能与 Freeze Period API 端点进行交互. + +## List Freeze Periods[](#list-freeze-periods "Permalink") + +冻结期间的分页列表,按`created_at`升序排序. + +``` +GET /projects/:id/freeze_periods +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" "https://gitlab.example.com/api/v4/projects/19/freeze_periods" +``` + +响应示例: + +``` +[ { "id":1, "freeze_start":"0 23 * * 5", "freeze_end":"0 8 * * 1", "cron_timezone":"UTC", "created_at":"2020-05-15T17:03:35.702Z", "updated_at":"2020-05-15T17:06:41.566Z" } ] +``` + +## Get a Freeze Period by a `freeze_period_id`[](#get-a-freeze-period-by-a-freeze_period_id "Permalink") + +获取给定的`freeze_period_id`的冻结期. + +``` +GET /projects/:id/freeze_periods/:freeze_period_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `freeze_period_id` | string | yes | 冻结期的数据库 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" "https://gitlab.example.com/api/v4/projects/19/freeze_periods/1" +``` + +响应示例: + +``` +{ "id":1, "freeze_start":"0 23 * * 5", "freeze_end":"0 8 * * 1", "cron_timezone":"UTC", "created_at":"2020-05-15T17:03:35.702Z", "updated_at":"2020-05-15T17:06:41.566Z" } +``` + +## Create a Freeze Period[](#create-a-freeze-period "Permalink") + +创建冻结期. + +``` +POST /projects/:id/freeze_periods +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `freeze_start` | string | yes | [Cron](https://crontab.guru/)格式的冻结期开始. | +| `freeze_end` | string | yes | [Cron](https://crontab.guru/)格式的冻结期结束. | +| `cron_timezone` | string | no | cron 字段的时区,如果未提供,则默认为 UTC. | + +请求示例: + +``` +curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" \ + --data '{ "freeze_start": "0 23 * * 5", "freeze_end": "0 7 * * 1", "cron_timezone": "UTC" }' \ + --request POST https://gitlab.example.com/api/v4/projects/19/freeze_periods +``` + +响应示例: + +``` +{ "id":1, "freeze_start":"0 23 * * 5", "freeze_end":"0 7 * * 1", "cron_timezone":"UTC", "created_at":"2020-05-15T17:03:35.702Z", "updated_at":"2020-05-15T17:03:35.702Z" } +``` + +## Update a Freeze Period[](#update-a-freeze-period "Permalink") + +为给定的`freeze_period_id`更新冻结期. + +``` +PUT /projects/:id/freeze_periods/:tag_name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `freeze_period_id` | 整数或字符串 | yes | 冻结期的数据库 ID. | +| `freeze_start` | string | no | [Cron](https://crontab.guru/)格式的冻结期开始. | +| `freeze_end` | string | no | [Cron](https://crontab.guru/)格式的冻结期结束. | +| `cron_timezone` | string | no | cron 字段的时区. | + +请求示例: + +``` +curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" \ + --data '{ "freeze_end": "0 8 * * 1" }' \ + --request PUT https://gitlab.example.com/api/v4/projects/19/freeze_periods/1 +``` + +响应示例: + +``` +{ "id":1, "freeze_start":"0 23 * * 5", "freeze_end":"0 8 * * 1", "cron_timezone":"UTC", "created_at":"2020-05-15T17:03:35.702Z", "updated_at":"2020-05-15T17:06:41.566Z" } +``` + +## Delete a Freeze Period[](#delete-a-freeze-period "Permalink") + +删除给定的`freeze_period_id`的冻结期. + +``` +DELETE /projects/:id/freeze_periods/:freeze_period_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `freeze_period_id` | string | yes | 冻结期的数据库 ID. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" "https://gitlab.example.com/api/v4/projects/19/freeze_periods/1" +``` \ No newline at end of file diff --git a/_book/docs/316.md b/_book/docs/316.md new file mode 100644 index 0000000000000000000000000000000000000000..1930d6cdec7c780dbea2111dce0874ac8929038c --- /dev/null +++ b/_book/docs/316.md @@ -0,0 +1,213 @@ +# Geo Nodes API + +> 原文:[https://docs.gitlab.com/ee/api/geo_nodes.html](https://docs.gitlab.com/ee/api/geo_nodes.html) + +* [Create a new Geo node](#create-a-new-geo-node) +* [Retrieve configuration about all Geo nodes](#retrieve-configuration-about-all-geo-nodes) +* [Retrieve configuration about a specific Geo node](#retrieve-configuration-about-a-specific-geo-node) +* [Edit a Geo node](#edit-a-geo-node) +* [Delete a Geo node](#delete-a-geo-node) +* [Repair a Geo node](#repair-a-geo-node) +* [Retrieve status about all Geo nodes](#retrieve-status-about-all-geo-nodes) +* [Retrieve status about a specific Geo node](#retrieve-status-about-a-specific-geo-node) +* [Retrieve project sync or verification failures that occurred on the current node](#retrieve-project-sync-or-verification-failures-that-occurred-on-the-current-node) + +# Geo Nodes API[](#geo-nodes-api-premium-only "Permalink") + +为了与地理节点端点进行交互,您需要以管理员身份进行身份验证. + +## Create a new Geo node[](#create-a-new-geo-node "Permalink") + +创建一个新的地理节点. + +``` +POST /geo_nodes +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/geo_nodes" \ + --request POST \ + -d "name=himynameissomething" \ + -d "url=https://another-node.example.com/" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `primary` | boolean | no | 指定此节点是否为主节点. 默认为 false. | +| `enabled` | boolean | no | 指示是否启用地理节点的标志. 默认为 true. | +| `name` | string | yes | 地理节点的唯一标识符. 必须匹配`geo_node_name`如果在设定`gitlab.rb` ,否则必须匹配`external_url` | +| `url` | string | yes | Geo 节点的面向用户的 URL. | +| `internal_url` | string | no | 在主节点上定义的 URL,辅助节点应使用该 URL 与之联系. 如果未设置,则返回`url` . | +| `files_max_capacity` | integer | no | 控制此辅助节点的 LFS /附件回填的最大并发性. 默认为 10 | +| `repos_max_capacity` | integer | no | 控制此辅助节点的存储库回填的最大并发性. 默认为 25. | +| `verification_max_capacity` | integer | no | 控制此节点的存储库验证的最大并发性. 默认为 100. | +| `container_repositories_max_capacity` | integer | no | 控制此节点的容器存储库同步的最大并发性. 默认为 10 | +| `sync_object_storage` | boolean | no | 指示辅助 Geo 节点是否将复制对象存储中的 Blob 的标志. 默认为 false. | +| `selective_sync_type` | string | no | Limit syncing to only specific groups or shards. Valid values: `"namespaces"`, `"shards"`, or `null`. | +| `selective_sync_shards` | array | no | 如果`selective_sync_type` == `shards` ,则同步项目的存储库存储. | +| `selective_sync_namespace_ids` | array | no | 如果`selective_sync_type` == `namespaces` ,则应同步的组的 ID. | +| `minimum_reverification_interval` | integer | no | 存储库验证有效的时间间隔(以天为单位). 一旦过期,它将被重新验证. 在辅助节点上进行设置时,这无效. | + +响应示例: + +``` +{ "id": 3, "name": "Test Node 1", "url": "https://secondary.example.com/", "internal_url": "https://secondary.example.com/", "primary": false, "enabled": true, "current": false, "files_max_capacity": 10, "repos_max_capacity": 25, "verification_max_capacity": 100, "selective_sync_type": "namespaces", "selective_sync_shards": [], "selective_sync_namespace_ids": [1, 25], "minimum_reverification_interval": 7, "container_repositories_max_capacity": 10, "sync_object_storage": false, "clone_protocol": "http", "web_edit_url": "https://primary.example.com/admin/geo/nodes/3/edit", "web_geo_projects_url": "http://secondary.example.com/admin/geo/projects", "_links": { "self": "https://primary.example.com/api/v4/geo_nodes/3", "status": "https://primary.example.com/api/v4/geo_nodes/3/status", "repair": "https://primary.example.com/api/v4/geo_nodes/3/repair" } } +``` + +## Retrieve configuration about all Geo nodes[](#retrieve-configuration-about-all-geo-nodes "Permalink") + +``` +GET /geo_nodes +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/geo_nodes" +``` + +响应示例: + +``` +[ { "id": 1, "name": "us-node", "url": "https://primary.example.com/", "internal_url": "https://internal.example.com/", "primary": true, "enabled": true, "current": true, "files_max_capacity": 10, "repos_max_capacity": 25, "container_repositories_max_capacity": 10, "verification_max_capacity": 100, "selective_sync_type": "namespaces", "selective_sync_shards": [], "selective_sync_namespace_ids": [1, 25], "minimum_reverification_interval": 7, "clone_protocol": "http", "web_edit_url": "https://primary.example.com/admin/geo/nodes/1/edit", "_links": { "self": "https://primary.example.com/api/v4/geo_nodes/1", "status":"https://primary.example.com/api/v4/geo_nodes/1/status", "repair":"https://primary.example.com/api/v4/geo_nodes/1/repair" } }, { "id": 2, "name": "cn-node", "url": "https://secondary.example.com/", "internal_url": "https://secondary.example.com/", "primary": false, "enabled": true, "current": false, "files_max_capacity": 10, "repos_max_capacity": 25, "container_repositories_max_capacity": 10, "verification_max_capacity": 100, "selective_sync_type": "namespaces", "selective_sync_shards": [], "selective_sync_namespace_ids": [1, 25], "minimum_reverification_interval": 7, "sync_object_storage": true, "clone_protocol": "http", "web_edit_url": "https://primary.example.com/admin/geo/nodes/2/edit", "web_geo_projects_url": "https://secondary.example.com/admin/geo/projects", "_links": { "self":"https://primary.example.com/api/v4/geo_nodes/2", "status":"https://primary.example.com/api/v4/geo_nodes/2/status", "repair":"https://primary.example.com/api/v4/geo_nodes/2/repair" } } ] +``` + +## Retrieve configuration about a specific Geo node[](#retrieve-configuration-about-a-specific-geo-node "Permalink") + +``` +GET /geo_nodes/:id +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/geo_nodes/1" +``` + +响应示例: + +``` +{ "id": 1, "name": "us-node", "url": "https://primary.example.com/", "internal_url": "https://primary.example.com/", "primary": true, "enabled": true, "current": true, "files_max_capacity": 10, "repos_max_capacity": 25, "container_repositories_max_capacity": 10, "verification_max_capacity": 100, "selective_sync_type": "namespaces", "selective_sync_shards": [], "selective_sync_namespace_ids": [1, 25], "minimum_reverification_interval": 7, "clone_protocol": "http", "web_edit_url": "https://primary.example.com/admin/geo/nodes/1/edit", "_links": { "self": "https://primary.example.com/api/v4/geo_nodes/1", "status":"https://primary.example.com/api/v4/geo_nodes/1/status", "repair":"https://primary.example.com/api/v4/geo_nodes/1/repair" } } +``` + +## Edit a Geo node[](#edit-a-geo-node "Permalink") + +更新现有地理节点的设置. + +*这只能在主要的地理节点上运行.* + +``` +PUT /geo_nodes/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 地理位置节点的 ID. | +| `enabled` | boolean | no | 指示是否启用地理节点的标志. | +| `name` | string | yes | 地理节点的唯一标识符. 必须匹配`geo_node_name`如果在设定`gitlab.rb` ,否则必须匹配`external_url` . | +| `url` | string | yes | Geo 节点的面向用户的 URL. | +| `internal_url` | string | no | 在主节点上定义的 URL,辅助节点应使用该 URL 与之联系. 如果未设置,则返回`url` . | +| `files_max_capacity` | integer | no | 控制此辅助节点的 LFS /附件回填的最大并发性. | +| `repos_max_capacity` | integer | no | 控制此辅助节点的存储库回填的最大并发性. | +| `verification_max_capacity` | integer | no | 控制此节点的最大并发验证. | +| `container_repositories_max_capacity` | integer | no | 控制此节点的容器存储库同步的最大并发性. | +| `sync_object_storage` | boolean | no | 指示辅助 Geo 节点是否将复制对象存储中的 Blob 的标志. | +| `selective_sync_type` | string | no | 将同步限制为仅特定的组或碎片. 有效值: `"namespaces"` , `"shards"`或`null` . | +| `selective_sync_shards` | array | no | 如果`selective_sync_type` == `shards` ,则同步项目的存储库存储. | +| `selective_sync_namespace_ids` | array | no | 如果`selective_sync_type` == `namespaces` ,则应同步的组的 ID. | +| `minimum_reverification_interval` | integer | no | 存储库验证有效的时间间隔(以天为单位). 一旦过期,它将被重新验证. 在辅助节点上进行设置时,这无效. | + +响应示例: + +``` +{ "id": 1, "name": "cn-node", "url": "https://secondary.example.com/", "internal_url": "https://secondary.example.com/", "primary": false, "enabled": true, "current": true, "files_max_capacity": 10, "repos_max_capacity": 25, "container_repositories_max_capacity": 10, "verification_max_capacity": 100, "selective_sync_type": "namespaces", "selective_sync_shards": [], "selective_sync_namespace_ids": [1, 25], "minimum_reverification_interval": 7, "sync_object_storage": true, "clone_protocol": "http", "web_edit_url": "https://primary.example.com/admin/geo/nodes/2/edit", "web_geo_projects_url": "https://secondary.example.com/admin/geo/projects", "_links": { "self":"https://primary.example.com/api/v4/geo_nodes/2", "status":"https://primary.example.com/api/v4/geo_nodes/2/status", "repair":"https://primary.example.com/api/v4/geo_nodes/2/repair" } } +``` + +## Delete a Geo node[](#delete-a-geo-node "Permalink") + +删除地理节点. + +**注意:**只有 Geo 主节点将接受此请求. + +``` +DELETE /geo_nodes/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 地理位置节点的 ID. | + +## Repair a Geo node[](#repair-a-geo-node "Permalink") + +修复地理节点的 OAuth 身份验证. + +*这只能在主要的地理节点上运行.* + +``` +POST /geo_nodes/:id/repair +``` + +响应示例: + +``` +{ "id": 1, "name": "us-node", "url": "https://primary.example.com/", "internal_url": "https://primary.example.com/", "primary": true, "enabled": true, "current": true, "files_max_capacity": 10, "repos_max_capacity": 25, "container_repositories_max_capacity": 10, "verification_max_capacity": 100, "clone_protocol": "http", "web_edit_url": "https://primary.example.com/admin/geo/nodes/1/edit", "_links": { "self": "https://primary.example.com/api/v4/geo_nodes/1", "status":"https://primary.example.com/api/v4/geo_nodes/1/status", "repair":"https://primary.example.com/api/v4/geo_nodes/1/repair" } } +``` + +## Retrieve status about all Geo nodes[](#retrieve-status-about-all-geo-nodes "Permalink") + +``` +GET /geo_nodes/status +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/geo_nodes/status" +``` + +响应示例: + +``` +[ { "geo_node_id": 1, "healthy": true, "health": "Healthy", "health_status": "Healthy", "missing_oauth_application": false, "attachments_count": 1, "attachments_synced_count": nil, "attachments_failed_count": nil, "attachments_synced_missing_on_primary_count": 0, "attachments_synced_in_percentage": "0.00%", "db_replication_lag_seconds": nil, "lfs_objects_count": 0, "lfs_objects_synced_count": nil, "lfs_objects_failed_count": nil, "lfs_objects_synced_missing_on_primary_count": 0, "lfs_objects_synced_in_percentage": "0.00%", "job_artifacts_count": 2, "job_artifacts_synced_count": nil, "job_artifacts_failed_count": nil, "job_artifacts_synced_missing_on_primary_count": 0, "job_artifacts_synced_in_percentage": "0.00%", "container_repositories_count": 3, "container_repositories_synced_count": nil, "container_repositories_failed_count": nil, "container_repositories_synced_in_percentage": "0.00%", "design_repositories_count": 3, "design_repositories_synced_count": nil, "design_repositories_failed_count": nil, "design_repositories_synced_in_percentage": "0.00%", "projects_count": 41, "repositories_failed_count": nil, "repositories_synced_count": nil, "repositories_synced_in_percentage": "0.00%", "wikis_failed_count": nil, "wikis_synced_count": nil, "wikis_synced_in_percentage": "0.00%", "replication_slots_count": 1, "replication_slots_used_count": 1, "replication_slots_used_in_percentage": "100.00%", "replication_slots_max_retained_wal_bytes": 0, "repositories_checked_count": 20, "repositories_checked_failed_count": 20, "repositories_checked_in_percentage": "100.00%", "repositories_checksummed_count": 20, "repositories_checksum_failed_count": 5, "repositories_checksummed_in_percentage": "48.78%", "wikis_checksummed_count": 10, "wikis_checksum_failed_count": 3, "wikis_checksummed_in_percentage": "24.39%", "repositories_verified_count": 20, "repositories_verification_failed_count": 5, "repositories_verified_in_percentage": "48.78%", "repositories_checksum_mismatch_count": 3, "wikis_verified_count": 10, "wikis_verification_failed_count": 3, "wikis_verified_in_percentage": "24.39%", "wikis_checksum_mismatch_count": 1, "repositories_retrying_verification_count": 1, "wikis_retrying_verification_count": 3, "repositories_checked_count": 7, "repositories_checked_failed_count": 2, "repositories_checked_in_percentage": "17.07%", "last_event_id": 23, "last_event_timestamp": 1509681166, "cursor_last_event_id": nil, "cursor_last_event_timestamp": 0, "last_successful_status_check_timestamp": 1510125024, "version": "10.3.0", "revision": "33d33a096a", "package_files_count": 10, "package_files_checksummed_count": 10, "package_files_checksum_failed_count": 0, "package_files_registry_count": 10, "package_files_synced_count": 6, "package_files_failed_count": 3 }, { "geo_node_id": 2, "healthy": true, "health": "Healthy", "health_status": "Healthy", "missing_oauth_application": false, "attachments_count": 1, "attachments_synced_count": 1, "attachments_failed_count": 0, "attachments_synced_missing_on_primary_count": 0, "attachments_synced_in_percentage": "100.00%", "db_replication_lag_seconds": 0, "lfs_objects_count": 0, "lfs_objects_synced_count": 0, "lfs_objects_failed_count": 0, "lfs_objects_synced_missing_on_primary_count": 0, "lfs_objects_synced_in_percentage": "0.00%", "job_artifacts_count": 2, "job_artifacts_synced_count": 1, "job_artifacts_failed_count": 1, "job_artifacts_synced_missing_on_primary_count": 0, "job_artifacts_synced_in_percentage": "50.00%", "container_repositories_count": 3, "container_repositories_synced_count": nil, "container_repositories_failed_count": nil, "container_repositories_synced_in_percentage": "0.00%", "design_repositories_count": 3, "design_repositories_synced_count": nil, "design_repositories_failed_count": nil, "design_repositories_synced_in_percentage": "0.00%", "projects_count": 41, "repositories_failed_count": 1, "repositories_synced_count": 40, "repositories_synced_in_percentage": "97.56%", "wikis_failed_count": 0, "wikis_synced_count": 41, "wikis_synced_in_percentage": "100.00%", "replication_slots_count": nil, "replication_slots_used_count": nil, "replication_slots_used_in_percentage": "0.00%", "replication_slots_max_retained_wal_bytes": nil, "repositories_checksummed_count": 20, "repositories_checksum_failed_count": 5, "repositories_checksummed_in_percentage": "48.78%", "wikis_checksummed_count": 10, "wikis_checksum_failed_count": 3, "wikis_checksummed_in_percentage": "24.39%", "repositories_verified_count": 20, "repositories_verification_failed_count": 5, "repositories_verified_in_percentage": "48.78%", "repositories_checksum_mismatch_count": 3, "wikis_verified_count": 10, "wikis_verification_failed_count": 3, "wikis_verified_in_percentage": "24.39%", "wikis_checksum_mismatch_count": 1, "repositories_retrying_verification_count": 4, "wikis_retrying_verification_count": 2, "repositories_checked_count": 5, "repositories_checked_failed_count": 1, "repositories_checked_in_percentage": "12.20%", "last_event_id": 23, "last_event_timestamp": 1509681166, "cursor_last_event_id": 23, "cursor_last_event_timestamp": 1509681166, "last_successful_status_check_timestamp": 1510125024, "version": "10.3.0", "revision": "33d33a096a", "package_files_count": 10, "package_files_checksummed_count": 10, "package_files_checksum_failed_count": 0, "package_files_registry_count": 10, "package_files_synced_count": 6, "package_files_failed_count": 3 } ] +``` + +**注意:**在 GitLab 12.0 中,已弃用的字段`wikis_count`和`repositories_count`被删除. 请改用`projects_count` . + +## Retrieve status about a specific Geo node[](#retrieve-status-about-a-specific-geo-node "Permalink") + +``` +GET /geo_nodes/:id/status +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/geo_nodes/2/status" +``` + +响应示例: + +``` +{ "geo_node_id": 2, "healthy": true, "health": "Healthy", "health_status": "Healthy", "missing_oauth_application": false, "attachments_count": 1, "attachments_synced_count": 1, "attachments_failed_count": 0, "attachments_synced_missing_on_primary_count": 0, "attachments_synced_in_percentage": "100.00%", "db_replication_lag_seconds": 0, "lfs_objects_count": 0, "lfs_objects_synced_count": 0, "lfs_objects_failed_count": 0, "lfs_objects_synced_missing_on_primary_count": 0, "lfs_objects_synced_in_percentage": "0.00%", "job_artifacts_count": 2, "job_artifacts_synced_count": 1, "job_artifacts_failed_count": 1, "job_artifacts_synced_missing_on_primary_count": 0, "job_artifacts_synced_in_percentage": "50.00%", "container_repositories_count": 3, "container_repositories_synced_count": nil, "container_repositories_failed_count": nil, "container_repositories_synced_in_percentage": "0.00%", "design_repositories_count": 3, "design_repositories_synced_count": nil, "design_repositories_failed_count": nil, "design_repositories_synced_in_percentage": "0.00%", "projects_count": 41, "repositories_failed_count": 1, "repositories_synced_count": 40, "repositories_synced_in_percentage": "97.56%", "wikis_failed_count": 0, "wikis_synced_count": 41, "wikis_synced_in_percentage": "100.00%", "replication_slots_count": nil, "replication_slots_used_count": nil, "replication_slots_used_in_percentage": "0.00%", "replication_slots_max_retained_wal_bytes": nil, "last_event_id": 23, "last_event_timestamp": 1509681166, "cursor_last_event_id": 23, "cursor_last_event_timestamp": 1509681166, "last_successful_status_check_timestamp": 1510125268, "version": "10.3.0", "revision": "33d33a096a" } +``` + +注意: `health_status`参数只能处于"健康"或"不健康"状态,而`health`参数可以为空,"健康"或包含实际错误消息. + +**注意:**在 GitLab 12.0 中,已弃用的字段`wikis_count`和`repositories_count`被删除. 请改用`projects_count` . + +## Retrieve project sync or verification failures that occurred on the current node[](#retrieve-project-sync-or-verification-failures-that-occurred-on-the-current-node "Permalink") + +这仅适用于辅助节点. + +``` +GET /geo_nodes/current/failures +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | string | no | 失败对象的类型( `repository` / `wiki` ) | +| `failure_type` | string | no | 故障类型( `sync` / `checksum_mismatch` / `verification` ) | + +该端点使用[分页](README.html#pagination) . + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/geo_nodes/current/failures" +``` + +响应示例: + +``` +[ { "project_id": 3, "last_repository_synced_at": "2017-10-31 14:25:55 UTC", "last_repository_successful_sync_at": "2017-10-31 14:26:04 UTC", "last_wiki_synced_at": "2017-10-31 14:26:04 UTC", "last_wiki_successful_sync_at": "2017-10-31 14:26:11 UTC", "repository_retry_count": null, "wiki_retry_count": 1, "last_repository_sync_failure": null, "last_wiki_sync_failure": "Error syncing Wiki repository", "last_repository_verification_failure": "", "last_wiki_verification_failure": "", "repository_verification_checksum_sha": "da39a3ee5e6b4b0d32e5bfef9a601890afd80709", "wiki_verification_checksum_sha": "da39a3ee5e6b4b0d3255bfef9ef0189aafd80709", "repository_checksum_mismatch": false, "wiki_checksum_mismatch": false } ] +``` \ No newline at end of file diff --git a/_book/docs/317.md b/_book/docs/317.md new file mode 100644 index 0000000000000000000000000000000000000000..71de959c7994e6d07221e5cd324bdf9280db8bf9 --- /dev/null +++ b/_book/docs/317.md @@ -0,0 +1,83 @@ +# Group Activity Analytics API + +> 原文:[https://docs.gitlab.com/ee/api/group_activity_analytics.html](https://docs.gitlab.com/ee/api/group_activity_analytics.html) + +* [Get count of recently created issues for group](#get-count-of-recently-created-issues-for-group) +* [Get count of recently created merge requests for group](#get-count-of-recently-created-merge-requests-for-group) +* [Get count of members recently added to group](#get-count-of-members-recently-added-to-group) + +# Group Activity Analytics API[](#group-activity-analytics-api "Permalink") + +**注意:**此功能是在 GitLab 12.9 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26460) . + +## Get count of recently created issues for group[](#get-count-of-recently-created-issues-for-group "Permalink") + +``` +GET /analytics/group_activity/issues_count +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `group_path` | string | yes | 组路径 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/analytics/group_activity/issues_count?group_path=gitlab-org" +``` + +响应示例: + +``` +{ "issues_count": 10 } +``` + +## Get count of recently created merge requests for group[](#get-count-of-recently-created-merge-requests-for-group "Permalink") + +``` +GET /analytics/group_activity/merge_requests_count +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `group_path` | string | yes | 组路径 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/analytics/group_activity/merge_requests_count?group_path=gitlab-org" +``` + +响应示例: + +``` +{ "merge_requests_count": 10 } +``` + +## Get count of members recently added to group[](#get-count-of-members-recently-added-to-group "Permalink") + +``` +GET /analytics/group_activity/new_members_count +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `group_path` | string | yes | 组路径 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/analytics/group_activity/new_members_count?group_path=gitlab-org" +``` + +响应示例: + +``` +{ "new_members_count": 10 } +``` \ No newline at end of file diff --git a/_book/docs/318.md b/_book/docs/318.md new file mode 100644 index 0000000000000000000000000000000000000000..f801dc8b2293ced5c7d764eaef495a2e73a47c78 --- /dev/null +++ b/_book/docs/318.md @@ -0,0 +1,697 @@ +# Groups API + +> 原文:[https://docs.gitlab.com/ee/api/groups.html](https://docs.gitlab.com/ee/api/groups.html) + +* [List groups](#list-groups) +* [List a group’s subgroups](#list-a-groups-subgroups) +* [List a group’s projects](#list-a-groups-projects) +* [List a group’s shared projects](#list-a-groups-shared-projects) +* [Details of a group](#details-of-a-group) + * [Disabling the results limit](#disabling-the-results-limit) +* [New group](#new-group) + * [Options for `default_branch_protection`](#options-for-default_branch_protection) +* [New Subgroup](#new-subgroup) +* [Transfer project to group](#transfer-project-to-group) +* [Update group](#update-group) + * [Disabling the results limit](#disabling-the-results-limit-1) +* [Remove group](#remove-group) +* [Restore group marked for deletion](#restore-group-marked-for-deletion-premium) +* [Search for group](#search-for-group) +* [Hooks](#hooks) + * [List group hooks](#list-group-hooks) + * [Get group hook](#get-group-hook) + * [Add group hook](#add-group-hook) + * [Edit group hook](#edit-group-hook) + * [Delete group hook](#delete-group-hook) +* [Group Audit Events](#group-audit-events-starter) +* [Sync group with LDAP](#sync-group-with-ldap-starter) +* [Group members](#group-members) +* [LDAP Group Links](#ldap-group-links) + * [List LDAP group links](#list-ldap-group-links-starter) + * [Add LDAP group link with CN or filter](#add-ldap-group-link-with-cn-or-filter-starter) + * [Delete LDAP group link](#delete-ldap-group-link-starter) + * [Delete LDAP group link with CN or filter](#delete-ldap-group-link-with-cn-or-filter-starter) +* [Namespaces in groups](#namespaces-in-groups) +* [Group badges](#group-badges) +* [Group Import/Export](#group-importexport) +* [Share Groups with Groups](#share-groups-with-groups) + * [Create a link to share a group with another group](#create-a-link-to-share-a-group-with-another-group) + * [Delete link sharing group with another group](#delete-link-sharing-group-with-another-group) + +# Groups API[](#groups-api "Permalink") + +## List groups[](#list-groups "Permalink") + +获取已认证用户的可见组列表. 在未经身份验证的情况下访问时,仅返回公共组. + +默认情况下,此请求一次返回 20 个结果,因为 API 结果[是分页的](README.html#pagination) . + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `skip_groups` | 整数数组 | no | 跳过传递的组 ID | +| `all_available` | boolean | no | 显示您有权访问的所有组(对于经过身份验证的用户,默认值为`false` ;对于管理员,默认`false` `true` ); `owned`属性和`min_access_level`具有优先权 | +| `search` | string | no | 返回符合搜索条件的授权组列表 | +| `order_by` | string | no | 按`name` , `path`或`id` . 默认`name` | +| `sort` | string | no | 按`asc`或`desc`顺序排列组. 默认为`asc` | +| `statistics` | boolean | no | 包括组统计信息(仅管理员) | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | +| `owned` | boolean | no | 限制为当前用户明确拥有的组 | +| `min_access_level` | integer | no | 限制为当前用户至少具有此[访问级别的组](members.html#valid-access-levels) | +| `top_level_only` | boolean | no | 限于顶级组,不包括所有子组 | + +``` +GET /groups +``` + +``` +[ { "id": 1, "name": "Foobar Group", "path": "foo-bar", "description": "An interesting group", "visibility": "public", "share_with_group_lock": false, "require_two_factor_authentication": false, "two_factor_grace_period": 48, "project_creation_level": "developer", "auto_devops_enabled": null, "subgroup_creation_level": "owner", "emails_disabled": null, "mentions_disabled": null, "lfs_enabled": true, "default_branch_protection": 2, "avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg", "web_url": "http://localhost:3000/groups/foo-bar", "request_access_enabled": false, "full_name": "Foobar Group", "full_path": "foo-bar", "file_template_project_id": 1, "parent_id": null, "created_at": "2020-01-15T12:36:29.590Z" } ] +``` + +当添加参数`statistics=true`且经过身份验证的用户是管理员时,将返回其他组统计信息. + +``` +GET /groups?statistics=true +``` + +``` +[ { "id": 1, "name": "Foobar Group", "path": "foo-bar", "description": "An interesting group", "visibility": "public", "share_with_group_lock": false, "require_two_factor_authentication": false, "two_factor_grace_period": 48, "project_creation_level": "developer", "auto_devops_enabled": null, "subgroup_creation_level": "owner", "emails_disabled": null, "mentions_disabled": null, "lfs_enabled": true, "default_branch_protection": 2, "avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg", "web_url": "http://localhost:3000/groups/foo-bar", "request_access_enabled": false, "full_name": "Foobar Group", "full_path": "foo-bar", "file_template_project_id": 1, "parent_id": null, "created_at": "2020-01-15T12:36:29.590Z", "statistics": { "storage_size" : 212, "repository_size" : 33, "wiki_size" : 100, "lfs_objects_size" : 123, "job_artifacts_size" : 57, "packages_size": 0, "snippets_size" : 50, } } ] +``` + +您可以按名称或路径搜索组,请参见下文. + +您可以使用以下[自定义属性](custom_attributes.html)进行过滤: + +``` +GET /groups?custom_attributes[key]=value&custom_attributes[other_key]=other_value +``` + +## List a group’s subgroups[](#list-a-groups-subgroups "Permalink") + +在 GitLab 10.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15142) . + +获取此组中可见的直接子组的列表. 在未经身份验证的情况下访问时,仅返回公共组. + +默认情况下,此请求一次返回 20 个结果,因为 API 结果[是分页的](README.html#pagination) . + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 直接父组[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `skip_groups` | 整数数组 | no | 跳过传递的组 ID | +| `all_available` | boolean | no | 显示您有权访问的所有组(对于经过身份验证的用户,默认值为`false` ;对于管理员,默认`false` `true` ); `owned`属性和`min_access_level`具有优先权 | +| `search` | string | no | 返回符合搜索条件的授权组列表 | +| `order_by` | string | no | 按`name` , `path`或`id` . 默认`name` | +| `sort` | string | no | 按`asc`或`desc`顺序排列组. 默认为`asc` | +| `statistics` | boolean | no | 包括组统计信息(仅管理员) | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | +| `owned` | boolean | no | 限制为当前用户明确拥有的组 | +| `min_access_level` | integer | no | 限制为当前用户至少具有此[访问级别的组](members.html#valid-access-levels) | + +``` +GET /groups/:id/subgroups +``` + +``` +[ { "id": 1, "name": "Foobar Group", "path": "foo-bar", "description": "An interesting group", "visibility": "public", "share_with_group_lock": false, "require_two_factor_authentication": false, "two_factor_grace_period": 48, "project_creation_level": "developer", "auto_devops_enabled": null, "subgroup_creation_level": "owner", "emails_disabled": null, "mentions_disabled": null, "lfs_enabled": true, "default_branch_protection": 2, "avatar_url": "http://gitlab.example.com/uploads/group/avatar/1/foo.jpg", "web_url": "http://gitlab.example.com/groups/foo-bar", "request_access_enabled": false, "full_name": "Foobar Group", "full_path": "foo-bar", "file_template_project_id": 1, "parent_id": 123, "created_at": "2020-01-15T12:36:29.590Z" } ] +``` + +## List a group’s projects[](#list-a-groups-projects "Permalink") + +获取此组中的项目列表. 在未经身份验证的情况下访问时,仅返回公共项目. + +默认情况下,此请求一次返回 20 个结果,因为 API 结果[是分页的](README.html#pagination) . + +``` +GET /groups/:id/projects +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `archived` | boolean | no | 受存档状态限制 | +| `visibility` | string | no | 受`public` , `internal`或`private`可见性限制 | +| `order_by` | string | no | 返回按`id` , `name` , `path` , `created_at` , `updated_at`或`last_activity_at`字段排序的项目. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的项目. 默认为`desc` | +| `search` | string | no | 返回符合搜索条件的授权项目列表 | +| `simple` | boolean | no | 仅返回每个项目的 ID,URL,名称和路径 | +| `owned` | boolean | no | 受当前用户拥有的项目限制 | +| `starred` | boolean | no | 受当前用户加注星标的项目限制 | +| `with_issues_enabled` | boolean | no | 受具有问题功能的项目限制. 默认为`false` | +| `with_merge_requests_enabled` | boolean | no | 受启用合并请求功能的项目限制. 默认为`false` | +| `with_shared` | boolean | no | 包括共享给该组的项目. 默认为`true` | +| `include_subgroups` | boolean | no | 将项目包括在该组的子组中. 默认为`false` | +| `min_access_level` | integer | no | 限于当前用户至少具有此[访问级别的项目](members.html#valid-access-levels) | +| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.html) in response (admins only) | +| `with_security_reports` | boolean | no | 仅返回在任何版本中都存在安全报告工件的项目. 这意味着"启用了安全报告的项目". 默认为`false` | + +响应示例: + +``` +[ { "id": 9, "description": "foo", "default_branch": "master", "tag_list": [], "archived": false, "visibility": "internal", "ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git", "http_url_to_repo": "http://gitlab.example.com/h5bp/html5-boilerplate.git", "web_url": "http://gitlab.example.com/h5bp/html5-boilerplate", "name": "Html5 Boilerplate", "name_with_namespace": "Experimental / Html5 Boilerplate", "path": "html5-boilerplate", "path_with_namespace": "h5bp/html5-boilerplate", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, "jobs_enabled": true, "snippets_enabled": true, "created_at": "2016-04-05T21:40:50.169Z", "last_activity_at": "2016-04-06T16:52:08.432Z", "shared_runners_enabled": true, "creator_id": 1, "namespace": { "id": 5, "name": "Experimental", "path": "h5bp", "kind": "group" }, "avatar_url": null, "star_count": 1, "forks_count": 0, "open_issues_count": 3, "public_jobs": true, "shared_with_groups": [], "request_access_enabled": false } ] +``` + +**注意:**为了区分组中的项目和共享给组的项目,可以使用`namespace`属性. 将项目共享给组后,其`namespace`将与请求的组不同. + +## List a group’s shared projects[](#list-a-groups-shared-projects "Permalink") + +获取共享给该组的项目的列表. 未经身份验证访问时,仅返回公共共享项目. + +默认情况下,此请求一次返回 20 个结果,因为 API 结果[是分页的](README.html#pagination) . + +``` +GET /groups/:id/projects/shared +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `archived` | boolean | no | 受存档状态限制 | +| `visibility` | string | no | 受`public` , `internal`或`private`可见性限制 | +| `order_by` | string | no | 返回按`id` , `name` , `path` , `created_at` , `updated_at`或`last_activity_at`字段排序的项目. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的项目. 默认为`desc` | +| `search` | string | no | 返回符合搜索条件的授权项目列表 | +| `simple` | boolean | no | 仅返回每个项目的 ID,URL,名称和路径 | +| `starred` | boolean | no | 受当前用户加注星标的项目限制 | +| `with_issues_enabled` | boolean | no | 受具有问题功能的项目限制. 默认为`false` | +| `with_merge_requests_enabled` | boolean | no | 受启用合并请求功能的项目限制. 默认为`false` | +| `min_access_level` | integer | no | 限于当前用户至少具有此[访问级别的项目](members.html#valid-access-levels) | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | + +响应示例: + +``` +[ { "id":8, "description":"Shared project for Html5 Boilerplate", "name":"Html5 Boilerplate", "name_with_namespace":"H5bp / Html5 Boilerplate", "path":"html5-boilerplate", "path_with_namespace":"h5bp/html5-boilerplate", "created_at":"2020-04-27T06:13:22.642Z", "default_branch":"master", "tag_list":[ ], "ssh_url_to_repo":"ssh://git@gitlab.com/h5bp/html5-boilerplate.git", "http_url_to_repo":"http://gitlab.com/h5bp/html5-boilerplate.git", "web_url":"http://gitlab.com/h5bp/html5-boilerplate", "readme_url":"http://gitlab.com/h5bp/html5-boilerplate/-/blob/master/README.md", "avatar_url":null, "star_count":0, "forks_count":4, "last_activity_at":"2020-04-27T06:13:22.642Z", "namespace":{ "id":28, "name":"H5bp", "path":"h5bp", "kind":"group", "full_path":"h5bp", "parent_id":null, "avatar_url":null, "web_url":"http://gitlab.com/groups/h5bp" }, "_links":{ "self":"http://gitlab.com/api/v4/projects/8", "issues":"http://gitlab.com/api/v4/projects/8/issues", "merge_requests":"http://gitlab.com/api/v4/projects/8/merge_requests", "repo_branches":"http://gitlab.com/api/v4/projects/8/repository/branches", "labels":"http://gitlab.com/api/v4/projects/8/labels", "events":"http://gitlab.com/api/v4/projects/8/events", "members":"http://gitlab.com/api/v4/projects/8/members" }, "empty_repo":false, "archived":false, "visibility":"public", "resolve_outdated_diff_discussions":false, "container_registry_enabled":true, "container_expiration_policy":{ "cadence":"7d", "enabled":true, "keep_n":null, "older_than":null, "name_regex":null, "name_regex_keep":null, "next_run_at":"2020-05-04T06:13:22.654Z" }, "issues_enabled":true, "merge_requests_enabled":true, "wiki_enabled":true, "jobs_enabled":true, "snippets_enabled":true, "can_create_merge_request_in":true, "issues_access_level":"enabled", "repository_access_level":"enabled", "merge_requests_access_level":"enabled", "forking_access_level":"enabled", "wiki_access_level":"enabled", "builds_access_level":"enabled", "snippets_access_level":"enabled", "pages_access_level":"enabled", "emails_disabled":null, "shared_runners_enabled":true, "lfs_enabled":true, "creator_id":1, "import_status":"failed", "open_issues_count":10, "ci_default_git_depth":50, "public_jobs":true, "build_timeout":3600, "auto_cancel_pending_pipelines":"enabled", "build_coverage_regex":null, "ci_config_path":null, "shared_with_groups":[ { "group_id":24, "group_name":"Commit451", "group_full_path":"Commit451", "group_access_level":30, "expires_at":null } ], "only_allow_merge_if_pipeline_succeeds":false, "request_access_enabled":true, "only_allow_merge_if_all_discussions_are_resolved":false, "remove_source_branch_after_merge":true, "printing_merge_request_link_enabled":true, "merge_method":"merge", "suggestion_commit_message":null, "auto_devops_enabled":true, "auto_devops_deploy_strategy":"continuous", "autoclose_referenced_issues":true, "repository_storage":"default" } ] +``` + +## Details of a group[](#details-of-a-group "Permalink") + +获取组的所有详细信息. 如果可以公开访问该组,则无需身份验证即可访问该端点. 如果请求的用户是该组的管理员,它将也返回该组的`runners_token` . + +``` +GET /groups/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员). | +| `with_projects` | boolean | no | 包括属于指定组的项目的详细信息(默认为`true` ). (已弃用, [将在 API v5 中删除](https://gitlab.com/gitlab-org/gitlab/-/issues/213797) .要获取组中所有项目的详细信息,请使用[列出组的项目终结点](#list-a-groups-projects) .) | + +**注意:**响应中的`projects`和`shared_projects`属性已弃用,并将[在 API v5 中删除](https://gitlab.com/gitlab-org/gitlab/-/issues/213797) . 要获取组内所有项目的详细信息,请使用[列出组的项目](#list-a-groups-projects)或[列出组的共享项目](#list-a-groups-shared-projects)端点. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4" +``` + +该端点返回: + +* GitLab 12.5 和更早版本中的所有项目和共享项目. +* [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/31031)及更高版本中最多有 100 个项目和共享项目. 要获取组中所有项目的详细信息,请使用[列出组的项目端点](#list-a-groups-projects)的[列表](#list-a-groups-projects) . + +响应示例: + +``` +{ "id": 4, "name": "Twitter", "path": "twitter", "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.", "visibility": "public", "avatar_url": null, "web_url": "https://gitlab.example.com/groups/twitter", "request_access_enabled": false, "full_name": "Twitter", "full_path": "twitter", "runners_token": "ba324ca7b1c77fc20bb9", "file_template_project_id": 1, "parent_id": null, "created_at": "2020-01-15T12:36:29.590Z", "shared_with_groups": [ { "group_id": 28, "group_name": "H5bp", "group_full_path": "h5bp", "group_access_level": 20, "expires_at": null } ], "projects": [ // Deprecated and will be removed in API v5 { "id": 7, "description": "Voluptas veniam qui et beatae voluptas doloremque explicabo facilis.", "default_branch": "master", "tag_list": [], "archived": false, "visibility": "public", "ssh_url_to_repo": "git@gitlab.example.com:twitter/typeahead-js.git", "http_url_to_repo": "https://gitlab.example.com/twitter/typeahead-js.git", "web_url": "https://gitlab.example.com/twitter/typeahead-js", "name": "Typeahead.Js", "name_with_namespace": "Twitter / Typeahead.Js", "path": "typeahead-js", "path_with_namespace": "twitter/typeahead-js", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, "jobs_enabled": true, "snippets_enabled": false, "container_registry_enabled": true, "created_at": "2016-06-17T07:47:25.578Z", "last_activity_at": "2016-06-17T07:47:25.881Z", "shared_runners_enabled": true, "creator_id": 1, "namespace": { "id": 4, "name": "Twitter", "path": "twitter", "kind": "group" }, "avatar_url": null, "star_count": 0, "forks_count": 0, "open_issues_count": 3, "public_jobs": true, "shared_with_groups": [], "request_access_enabled": false }, { "id": 6, "description": "Aspernatur omnis repudiandae qui voluptatibus eaque.", "default_branch": "master", "tag_list": [], "archived": false, "visibility": "internal", "ssh_url_to_repo": "git@gitlab.example.com:twitter/flight.git", "http_url_to_repo": "https://gitlab.example.com/twitter/flight.git", "web_url": "https://gitlab.example.com/twitter/flight", "name": "Flight", "name_with_namespace": "Twitter / Flight", "path": "flight", "path_with_namespace": "twitter/flight", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, "jobs_enabled": true, "snippets_enabled": false, "container_registry_enabled": true, "created_at": "2016-06-17T07:47:24.661Z", "last_activity_at": "2016-06-17T07:47:24.838Z", "shared_runners_enabled": true, "creator_id": 1, "namespace": { "id": 4, "name": "Twitter", "path": "twitter", "kind": "group" }, "avatar_url": null, "star_count": 0, "forks_count": 0, "open_issues_count": 8, "public_jobs": true, "shared_with_groups": [], "request_access_enabled": false } ], "shared_projects": [ // Deprecated and will be removed in API v5 { "id": 8, "description": "Velit eveniet provident fugiat saepe eligendi autem.", "default_branch": "master", "tag_list": [], "archived": false, "visibility": "private", "ssh_url_to_repo": "git@gitlab.example.com:h5bp/html5-boilerplate.git", "http_url_to_repo": "https://gitlab.example.com/h5bp/html5-boilerplate.git", "web_url": "https://gitlab.example.com/h5bp/html5-boilerplate", "name": "Html5 Boilerplate", "name_with_namespace": "H5bp / Html5 Boilerplate", "path": "html5-boilerplate", "path_with_namespace": "h5bp/html5-boilerplate", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, "jobs_enabled": true, "snippets_enabled": false, "container_registry_enabled": true, "created_at": "2016-06-17T07:47:27.089Z", "last_activity_at": "2016-06-17T07:47:27.310Z", "shared_runners_enabled": true, "creator_id": 1, "namespace": { "id": 5, "name": "H5bp", "path": "h5bp", "kind": "group" }, "avatar_url": null, "star_count": 0, "forks_count": 0, "open_issues_count": 4, "public_jobs": true, "shared_with_groups": [ { "group_id": 4, "group_name": "Twitter", "group_full_path": "twitter", "group_access_level": 30, "expires_at": null }, { "group_id": 3, "group_name": "Gitlab Org", "group_full_path": "gitlab-org", "group_access_level": 10, "expires_at": "2018-08-14" } ] } ] } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`shared_runners_minutes_limit`和`extra_shared_runners_minutes_limit`参数: + +其他响应参数: + +``` +{ "id": 4, "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.", "shared_runners_minutes_limit": 133, "extra_shared_runners_minutes_limit": 133, ... } +``` + +Users on GitLab [Silver, Premium, or higher](https://about.gitlab.com/pricing/) will also see the `marked_for_deletion_on` attribute: + +``` +{ "id": 4, "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.", "marked_for_deletion_on": "2020-04-03", ... } +``` + +当添加参数`with_projects=false` ,将不返回项目. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4?with_projects=false" +``` + +响应示例: + +``` +{ "id": 4, "name": "Twitter", "path": "twitter", "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.", "visibility": "public", "avatar_url": null, "web_url": "https://gitlab.example.com/groups/twitter", "request_access_enabled": false, "full_name": "Twitter", "full_path": "twitter", "file_template_project_id": 1, "parent_id": null } +``` + +### Disabling the results limit[](#disabling-the-results-limit "Permalink") + +如果它破坏了使用 GitLab 12.4 和更早版本开发的集成,则可以禁用 100 个结果限制. + +要在迁移到使用[列表的组项目](#list-a-groups-projects)终结点时禁用限制,请要求具有 Rails 控制台访问权限的 GitLab 管理员运行以下命令: + +``` +Feature.disable(:limit_projects_in_groups_api) +``` + +## New group[](#new-group "Permalink") + +创建一个新的项目组. 仅适用于可以创建组的用户. + +``` +POST /groups +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | string | yes | 组的名称. | +| `path` | string | yes | 组的路径. | +| `description` | string | no | 组的描述. | +| `membership_lock` | boolean | no | 阻止将新成员添加到该组中的项目成员中. | +| `visibility` | string | no | 小组的知名度. 可以是`private` , `internal`或`public` . | +| `share_with_group_lock` | boolean | no | 防止与该组中的另一个组共享项目. | +| `require_two_factor_authentication` | boolean | no | 要求该组中的所有用户设置双重身份验证. | +| `two_factor_grace_period` | integer | no | 实施两因素身份验证之前的时间(以小时为单位). | +| `project_creation_level` | string | no | 确定开发人员是否可以在组中创建项目. 可`noone` (没有之一), `maintainer` (维护者),或`developer` (开发+维护者). | +| `auto_devops_enabled` | boolean | no | 对于该组中的所有项目,默认为 Auto DevOps 管道. | +| `subgroup_creation_level` | string | no | 允许创建子组. 可以是`owner` (所有者)或`maintainer` (维护者). | +| `emails_disabled` | boolean | no | 禁用电子邮件通知 | +| `avatar` | mixed | no | 该组头像的图像文件. [在 GitLab 12.9 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) | +| `mentions_disabled` | boolean | no | 禁止一个人被提及 | +| `lfs_enabled` | boolean | no | 为该组中的项目启用/禁用大文件存储(LFS). | +| `request_access_enabled` | boolean | no | 允许用户请求成员访问权限. | +| `parent_id` | integer | no | 用于创建嵌套组的父组 ID. | +| `default_branch_protection` | integer | no | 请参阅[`default_branch_protection`选项](#options-for-default_branch_protection) . 默认为全局级别的默认分支保护设置. | +| `shared_runners_minutes_limit` | integer | no | 该组的管道分钟配额(包括在计划中). 可以为`nil` (默认值;继承系统默认值), `0` (无限制)或`> 0` | +| `extra_shared_runners_minutes_limit` | integer | no | 该组的额外管道分钟配额(在计划中包括的分钟之外购买). | + +### Options for `default_branch_protection`[](#options-for-default_branch_protection "Permalink") + +`default_branch_protection`属性确定开发人员和维护人员是否可以推送到适用的 master 分支,如下表所示: + +| Value | Description | +| --- | --- | +| `0` | 没有保护. 开发人员和维护人员可以: +-推送新的提交 +-强制推送更改 +-删除分支 | +| `1` | 部分保护. 开发人员和维护人员可以: +-推送新的提交 | +| `2` | 全面保护. 只有维护者可以: +-推送新的提交 | + +## New Subgroup[](#new-subgroup "Permalink") + +这类似于创建" [新建"组](#new-group) . 您将需要" [列表"组](#list-groups)调用中的`parent_id` . 然后,您可以输入所需的内容: + +* `subgroup_path` +* `subgroup_name` + +``` +curl --request POST --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" \ + --data '{"path": "", "name": "", "parent_id": } \ + "https://gitlab.example.com/api/v4/groups/" +``` + +## Transfer project to group[](#transfer-project-to-group "Permalink") + +将项目传输到组名称空间. 尽管不需要实例管理员访问权限的[替代 API 端点](projects.html#transfer-a-project-to-a-new-namespace)可用,但仅对实例管理员可用. 当项目存储库中存在标记的程序包时,传输项目可能会失败. + +``` +POST /groups/:id/projects/:project_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](README.html#namespaced-path-encoding) | +| `project_id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4/projects/56" +``` + +## Update group[](#update-group "Permalink") + +更新项目组. 仅对组所有者和管理员可用. + +``` +PUT /groups/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 组的 ID. | +| `name` | string | no | 组的名称. | +| `path` | string | no | 组的路径. | +| `description` | string | no | 组的描述. | +| `membership_lock` | boolean | no | 阻止将新成员添加到该组中的项目成员中. | +| `share_with_group_lock` | boolean | no | 防止与该组中的另一个组共享项目. | +| `visibility` | string | no | 组的可见性级别. 可以是`private` , `internal`或`public` . | +| `require_two_factor_authentication` | boolean | no | 要求该组中的所有用户设置双重身份验证. | +| `two_factor_grace_period` | integer | no | 实施两因素身份验证之前的时间(以小时为单位). | +| `project_creation_level` | string | no | 确定开发人员是否可以在组中创建项目. 可`noone` (没有之一), `maintainer` (维护者),或`developer` (开发+维护者). | +| `auto_devops_enabled` | boolean | no | 对于该组中的所有项目,默认为 Auto DevOps 管道. | +| `subgroup_creation_level` | string | no | 允许创建子组. 可以是`owner` (所有者)或`maintainer` (维护者). | +| `emails_disabled` | boolean | no | 禁用电子邮件通知 | +| `avatar` | mixed | no | 该组头像的图像文件. [在 GitLab 12.9 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) | +| `mentions_disabled` | boolean | no | 禁止一个人被提及 | +| `lfs_enabled` (optional) | boolean | no | 为该组中的项目启用/禁用大文件存储(LFS). | +| `request_access_enabled` | boolean | no | 允许用户请求成员访问权限. | +| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). | +| `file_template_project_id` | integer | no | 从中加载自定义文件模板的项目的 ID. | +| `shared_runners_minutes_limit` | integer | no | 该组的管道分钟配额(包括在计划中). 可以为`nil` (默认值;继承系统默认值), `0` (无限制)或`> 0` | +| `extra_shared_runners_minutes_limit` | integer | no | 该组的额外管道分钟配额(在计划中包括的分钟之外购买). | + +**注意:**响应中的`projects`和`shared_projects`属性已弃用,并将[在 API v5 中删除](https://gitlab.com/gitlab-org/gitlab/-/issues/213797) . 要获取组内所有项目的详细信息,请使用[列出组的项目](#list-a-groups-projects)或[列出组的共享项目](#list-a-groups-shared-projects)端点. + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5?name=Experimental" +``` + +该端点返回: + +* GitLab 12.5 和更早版本中的所有项目和共享项目. +* [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/31031)及更高版本中最多有 100 个项目和共享项目. 要获取组中所有项目的详细信息,请使用[列出组的项目端点](#list-a-groups-projects)的[列表](#list-a-groups-projects) . + +响应示例: + +``` +{ "id": 5, "name": "Experimental", "path": "h5bp", "description": "foo", "visibility": "internal", "avatar_url": null, "web_url": "http://gitlab.example.com/groups/h5bp", "request_access_enabled": false, "full_name": "Foobar Group", "full_path": "foo-bar", "file_template_project_id": 1, "parent_id": null, "created_at": "2020-01-15T12:36:29.590Z", "projects": [ // Deprecated and will be removed in API v5 { "id": 9, "description": "foo", "default_branch": "master", "tag_list": [], "public": false, "archived": false, "visibility": "internal", "ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git", "http_url_to_repo": "http://gitlab.example.com/h5bp/html5-boilerplate.git", "web_url": "http://gitlab.example.com/h5bp/html5-boilerplate", "name": "Html5 Boilerplate", "name_with_namespace": "Experimental / Html5 Boilerplate", "path": "html5-boilerplate", "path_with_namespace": "h5bp/html5-boilerplate", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, "jobs_enabled": true, "snippets_enabled": true, "created_at": "2016-04-05T21:40:50.169Z", "last_activity_at": "2016-04-06T16:52:08.432Z", "shared_runners_enabled": true, "creator_id": 1, "namespace": { "id": 5, "name": "Experimental", "path": "h5bp", "kind": "group" }, "avatar_url": null, "star_count": 1, "forks_count": 0, "open_issues_count": 3, "public_jobs": true, "shared_with_groups": [], "request_access_enabled": false } ] } +``` + +### Disabling the results limit[](#disabling-the-results-limit-1 "Permalink") + +The 100 results limit can be disabled if it breaks integrations developed using GitLab 12.4 and earlier. + +要在迁移到使用[列表的组项目](#list-a-groups-projects)终结点时禁用限制,请要求具有 Rails 控制台访问权限的 GitLab 管理员运行以下命令: + +``` +Feature.disable(:limit_projects_in_groups_api) +``` + +## Remove group[](#remove-group "Permalink") + +仅对组所有者和管理员可用. + +该端点: + +* 删除组,并在后台作业中排队以删除该组中的所有项目. +* 从[GitLab 12.8 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/33257) ,在[Premium 或 Silver](https://about.gitlab.com/pricing/)或更高级别上,将一个组标记为删除. 默认情况下,删除将在 7 天后进行,但是可以在[实例设置中](../user/admin_area/settings/visibility_and_access_controls.html#default-deletion-adjourned-period-premium-only)进行更改. + +``` +DELETE /groups/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +如果用户具有授权,则响应将为`202 Accepted` . + +## Restore group marked for deletion[](#restore-group-marked-for-deletion-premium "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33257) . + +恢复标记为删除的组. + +``` +POST /groups/:id/restore +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +## Search for group[](#search-for-group "Permalink") + +获取名称或路径中与您的字符串匹配的所有组. + +``` +GET /groups?search=foobar +``` + +``` +[ { "id": 1, "name": "Foobar Group", "path": "foo-bar", "description": "An interesting group" } ] +``` + +## Hooks[](#hooks "Permalink") + +也称为群组挂钩和 Webhooks. 这些不同于系统范围的[系统挂钩](system_hooks.html)和限于一个项目的[项目挂钩](projects.html#hooks) . + +### List group hooks[](#list-group-hooks "Permalink") + +获取组挂钩列表 + +``` +GET /groups/:id/hooks +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +### Get group hook[](#get-group-hook "Permalink") + +获取组的特定挂钩. + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `hook_id` | integer | yes | 组挂钩的 ID | + +``` +GET /groups/:id/hooks/:hook_id +``` + +``` +{ "id": 1, "url": "http://example.com/hook", "group_id": 3, "push_events": true, "issues_events": true, "confidential_issues_events": true, "merge_requests_events": true, "tag_push_events": true, "note_events": true, "confidential_note_events": true, "job_events": true, "pipeline_events": true, "wiki_page_events": true, "enable_ssl_verification": true, "created_at": "2012-10-12T17:04:47Z" } +``` + +### Add group hook[](#add-group-hook "Permalink") + +将钩子添加到指定的组. + +``` +POST /groups/:id/hooks +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `url` | string | yes | 挂钩网址 | +| `push_events` | boolean | no | 在推送事件上触发钩子 | +| `issues_events` | boolean | no | 触发问题事件挂钩 | +| `confidential_issues_events` | boolean | no | 触发机密问题事件的钩子 | +| `merge_requests_events` | boolean | no | 触发合并请求事件的钩子 | +| `tag_push_events` | boolean | no | 触发标签推送事件的钩子 | +| `note_events` | boolean | no | 在音符事件上触发钩子 | +| `confidential_note_events` | boolean | no | 触发机密笔记事件的钩子 | +| `job_events` | boolean | no | 触发工作事件挂钩 | +| `pipeline_events` | boolean | no | 触发管道事件钩子 | +| `wiki_page_events` | boolean | no | 触发 Wiki 事件的钩子 | +| `enable_ssl_verification` | boolean | no | 触发挂钩时执行 SSL 验证 | +| `token` | string | no | 用于验证收到的有效载荷的秘密令牌; 这将不会在响应中返回 | + +### Edit group hook[](#edit-group-hook "Permalink") + +编辑指定组的挂钩. + +``` +PUT /groups/:id/hooks/:hook_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `hook_id` | integer | yes | 组挂钩的 ID | +| `url` | string | yes | 挂钩网址 | +| `push_events` | boolean | no | 在推送事件上触发钩子 | +| `issues_events` | boolean | no | 触发问题事件挂钩 | +| `confidential_issues_events` | boolean | no | 触发机密问题事件的钩子 | +| `merge_requests_events` | boolean | no | 触发合并请求事件的钩子 | +| `tag_push_events` | boolean | no | 触发标签推送事件的钩子 | +| `note_events` | boolean | no | 在音符事件上触发钩子 | +| `confidential_note_events` | boolean | no | 触发机密笔记事件的钩子 | +| `job_events` | boolean | no | 触发工作事件挂钩 | +| `pipeline_events` | boolean | no | 触发管道事件钩子 | +| `wiki_events` | boolean | no | 触发 Wiki 事件的钩子 | +| `enable_ssl_verification` | boolean | no | 触发挂钩时执行 SSL 验证 | +| `token` | string | no | 用于验证收到的有效载荷的秘密令牌; 这将不会在响应中返回 | + +### Delete group hook[](#delete-group-hook "Permalink") + +从组中删除钩子. 这是幂等方法,可以多次调用. 挂钩是否可用. + +``` +DELETE /groups/:id/hooks/:hook_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `hook_id` | integer | yes | 组挂钩的 ID. | + +## Group Audit Events[](#group-audit-events-starter "Permalink") + +可以通过" [组审核事件" API](audit_events.html#group-audit-events-starter)访问[组审核事件](audit_events.html#group-audit-events-starter) + +## Sync group with LDAP[](#sync-group-with-ldap-starter "Permalink") + +将组与其链接的 LDAP 组同步. 仅对组所有者和管理员可用. + +``` +POST /groups/:id/ldap_sync +``` + +Parameters: + +* `id` (必填)-用户组的 ID 或路径 + +## Group members[](#group-members "Permalink") + +请查阅[小组成员](members.html)文档. + +## LDAP Group Links[](#ldap-group-links "Permalink") + +列出,添加和删除 LDAP 组链接. + +### List LDAP group links[](#list-ldap-group-links-starter "Permalink") + +列出 LDAP 组链接. + +``` +GET /groups/:id/ldap_group_links +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +### Add LDAP group link with CN or filter[](#add-ldap-group-link-with-cn-or-filter-starter "Permalink") + +使用 CN 或过滤器添加 LDAP 组链接. 仅在高级级别和更高级别中,才支持通过过滤器添加组链接. + +``` +POST /groups/:id/ldap_group_links +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cn` | string | no | LDAP 组的 CN | +| `filter` | string | no | 组的 LDAP 过滤器 | +| `group_access` | integer | yes | LDAP 组成员的最低[访问级别](members.html#valid-access-levels) | +| `provider` | string | yes | LDAP 组链接的 LDAP 提供程序 | + +**注意:**要定义 LDAP 组链接,请提供`cn`或`filter` ,但不能同时提供两者. + +### Delete LDAP group link[](#delete-ldap-group-link-starter "Permalink") + +删除 LDAP 组链接. 不推荐使用. 在将来的版本中将被删除. + +``` +DELETE /groups/:id/ldap_group_links/:cn +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cn` | string | yes | LDAP 组的 CN | + +删除特定 LDAP 提供程序的 LDAP 组链接. 不推荐使用. 在将来的版本中将被删除. + +``` +DELETE /groups/:id/ldap_group_links/:provider/:cn +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cn` | string | yes | LDAP 组的 CN | +| `provider` | string | yes | LDAP 组链接的 LDAP 提供程序 | + +### Delete LDAP group link with CN or filter[](#delete-ldap-group-link-with-cn-or-filter-starter "Permalink") + +使用 CN 或过滤器删除 LDAP 组链接. 仅高级级别和更高级别支持按过滤器删除. + +``` +DELETE /groups/:id/ldap_group_links +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cn` | string | no | LDAP 组的 CN | +| `filter` | string | no | 组的 LDAP 过滤器 | +| `provider` | string | yes | LDAP 组链接的 LDAP 提供程序 | + +**注意:**要删除 LDAP 组链接,请提供`cn`或`filter` ,但不能同时提供两者. + +## Namespaces in groups[](#namespaces-in-groups "Permalink") + +默认情况下,由于 API 结果是分页的,因此组一次只能获得 20 个名称空间. + +要获得更多(最多 100 个),请将以下内容作为参数传递给 API 调用: + +``` +/groups?per_page=100 +``` + +并切换页面添加: + +``` +/groups?per_page=100&page=2 +``` + +## Group badges[](#group-badges "Permalink") + +在[组徽章](group_badges.html)文档中了解更多信息. + +## Group Import/Export[](#group-importexport "Permalink") + +在[组导入/导出](group_import_export.html)文档中了解更多信息. + +## Share Groups with Groups[](#share-groups-with-groups "Permalink") + +这些端点创建和删除用于与另一个组共享一个组的链接. 有关更多信息,请参见[GitLab 组](../user/group/index.html#sharing-a-group-with-another-group)页面中的相关讨论. + +### Create a link to share a group with another group[](#create-a-link-to-share-a-group-with-another-group "Permalink") + +与另一个群组共享群组. 返回`200`和成功的[组详细信息](#details-of-a-group) . + +``` +POST /groups/:id/share +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `group_id` | integer | yes | 与之共享的组的 ID | +| `group_access` | integer | yes | 授予组的[访问级别](members.html#valid-access-levels) | +| `expires_at` | string | no | ISO 8601 格式的股份到期日:2016-09-26 | + +### Delete link sharing group with another group[](#delete-link-sharing-group-with-another-group "Permalink") + +取消与其他群组共享该群组. 返回`204` ,成功则不返回任何内容. + +``` +DELETE /groups/:id/share/:group_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `group_id` | integer | yes | 与之共享的组的 ID | \ No newline at end of file diff --git a/_book/docs/319.md b/_book/docs/319.md new file mode 100644 index 0000000000000000000000000000000000000000..39220f8566a222046c581236386357080f1fcda4 --- /dev/null +++ b/_book/docs/319.md @@ -0,0 +1,67 @@ +# Import API + +> 原文:[https://docs.gitlab.com/ee/api/import.html](https://docs.gitlab.com/ee/api/import.html) + +* [Import repository from GitHub](#import-repository-from-github) +* [Import repository from Bitbucket Server](#import-repository-from-bitbucket-server) + +# Import API[](#import-api "Permalink") + +## Import repository from GitHub[](#import-repository-from-github "Permalink") + +通过 API 将项目从 GitHub 导入到 GitLab. + +``` +POST /import/github +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `personal_access_token` | string | yes | GitHub 个人访问令牌 | +| `repo_id` | integer | yes | GitHub 存储库 ID | +| `new_name` | string | no | 新存储库名称 | +| `target_namespace` | string | yes | 要将存储库导入的命名空间 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --data "personal_access_token=abc123&repo_id=12345&target_namespace=root" "https://gitlab.example.com/api/v4/import/github" +``` + +响应示例: + +``` +{ "id": 27, "name": "my-repo", "full_path": "/root/my-repo", "full_name": "Administrator / my-repo" } +``` + +## Import repository from Bitbucket Server[](#import-repository-from-bitbucket-server "Permalink") + +通过 API 将项目从 Bitbucket Server 导入到 GitLab. + +**注意:** Bitbucket 项目密钥仅用于在 Bitbucket 中查找存储库. 如果要将存储库导入到 GitLab 组,则必须指定`target_namespace` . 如果您未指定`target_namespace` ,则项目将导入您的个人用户名称空间. + +``` +POST /import/bitbucket_server +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `bitbucket_server_url` | string | yes | Bitbucket 服务器网址 | +| `bitbucket_server_username` | string | yes | Bitbucket 服务器用户名 | +| `personal_access_token` | string | yes | Bitbucket 服务器个人访问令牌/密码 | +| `bitbucket_server_project` | string | yes | Bitbucket 项目密钥 | +| `bitbucket_server_repo` | string | yes | Bitbucket 存储库名称 | +| `new_name` | string | no | 新的回购名称 | +| `target_namespace` | string | no | 导入仓库的命名空间 | + +``` +curl --request POST \ + --url https://gitlab.example.com/api/v4/import/bitbucket_server \ + --header "content-type: application/json" \ + --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \ + --data '{ + "bitbucket_server_url": "http://bitbucket.example.com", + "bitbucket_server_username": "root", + "personal_access_token": "Nzk4MDcxODY4MDAyOiP8y410zF3tGAyLnHRv/E0+3xYs", + "bitbucket_server_project": "NEW", + "bitbucket_server_repo": "my-repo" +}' +``` \ No newline at end of file diff --git a/_book/docs/320.md b/_book/docs/320.md new file mode 100644 index 0000000000000000000000000000000000000000..8f0bbdee9babf1db8f3815e6a3e272ca970460e9 --- /dev/null +++ b/_book/docs/320.md @@ -0,0 +1,253 @@ +# Issue Boards API + +> 原文:[https://docs.gitlab.com/ee/api/boards.html](https://docs.gitlab.com/ee/api/boards.html) + +* [Project Board](#project-board) +* [Single board](#single-board) +* [Create a board](#create-a-board-starter) +* [Update a board](#update-a-board-starter) +* [Delete a board](#delete-a-board-starter) +* [List board lists](#list-board-lists) +* [Single board list](#single-board-list) +* [New board list](#new-board-list) +* [Edit board list](#edit-board-list) +* [Delete a board list](#delete-a-board-list) + +# Issue Boards API[](#issue-boards-api "Permalink") + +对板的每个 API 调用都必须经过验证. + +如果用户不是项目成员,并且该项目是私有项目,则对该项目的`GET`请求将导致`404`状态代码. + +## Project Board[](#project-board "Permalink") + +列出给定项目中的发行板. + +``` +GET /projects/:id/boards +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards" +``` + +响应示例: + +``` +[ { "id" : 1, "project": { "id": 5, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site" }, "milestone": { "id": 12, "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } ] } ] +``` + +## Single board[](#single-board "Permalink") + +拿一块板. + +``` +GET /projects/:id/boards/:board_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1" +``` + +响应示例: + +``` + { "id": 1, "name": "project issue board", "project": { "id": 5, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site" }, "milestone": { "id": 12, "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } ] } +``` + +## Create a board[](#create-a-board-starter "Permalink") + +创建一个木板. + +``` +POST /projects/:id/boards +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 新板的名称 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards?name=newboard" +``` + +响应示例: + +``` + { "id": 1, "project": { "id": 5, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site" }, "name": "newboard", "milestone": { "id": 12 "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } ] } +``` + +## Update a board[](#update-a-board-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5954) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.1. + +更新板. + +``` +PUT /projects/:id/boards/:board_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `name` | string | no | 董事会的新名称 | +| `assignee_id` | integer | no | 董事会受让人的范围应为 | +| `milestone_id` | integer | no | 董事会应达到的里程碑 | +| `labels` | string | no | 以逗号分隔的标签名称列表,该范围应适用于板 | +| `weight` | integer | no | 重量范围从 0 到 9,该板的范围应为 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1?name=new_name&milestone_id=43&assignee_id=1&labels=Doing&weight=4" +``` + +响应示例: + +``` + { "id": 1, "project": { "id": 5, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "created_at": "2018-07-03T05:48:49.982Z", "default_branch": null, "tag_list": [], "ssh_url_to_repo": "ssh://user@example.com/diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": null, "avatar_url": null, "star_count": 0, "forks_count": 0, "last_activity_at": "2018-07-03T05:48:49.982Z" }, "lists": [], "name": "new_name", "group": null, "milestone": { "id": 43, "iid": 1, "project_id": 15, "title": "Milestone 1", "description": "Milestone 1 desc", "state": "active", "created_at": "2018-07-03T06:36:42.618Z", "updated_at": "2018-07-03T06:36:42.618Z", "due_date": null, "start_date": null, "web_url": "http://example.com/root/board1/milestones/1" }, "assignee": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://example.com/root" }, "labels": [{ "id": 10, "name": "Doing", "color": "#5CB85C", "description": null }], "weight": 4 } +``` + +## Delete a board[](#delete-a-board-starter "Permalink") + +删除板. + +``` +DELETE /projects/:id/boards/:board_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1" +``` + +## List board lists[](#list-board-lists "Permalink") + +获取董事会名单的清单. 不包括`open`和`closed`列表 + +``` +GET /projects/:id/boards/:board_id/lists +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1/lists" +``` + +响应示例: + +``` +[ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } ] +``` + +## Single board list[](#single-board-list "Permalink") + +获取单板列表. + +``` +GET /projects/:id/boards/:board_id/lists/:list_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `list_id` | integer | yes | 单板编号 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1" +``` + +响应示例: + +``` +{ "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } +``` + +## New board list[](#new-board-list "Permalink") + +创建一个新的发行委员会列表. + +``` +POST /projects/:id/boards/:board_id/lists +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `label_id` | integer | no | 标签的 ID | +| `assignee_id` | integer | no | 用户的 ID | +| `milestone_id` | integer | no | 里程碑的 ID | + +**注意:**标签,受让人和里程碑参数是互斥的,也就是说,请求中仅接受其中一个. 查看[发行委员会文档](../user/project/issue_board.html#summary-of-features-per-tier) ,以获取有关每种列表类型所需许可证的更多信息. + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1/lists?label_id=5" +``` + +响应示例: + +``` +{ "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } +``` + +## Edit board list[](#edit-board-list "Permalink") + +更新现有的发行委员会列表. 此调用用于更改列表位置. + +``` +PUT /projects/:id/boards/:board_id/lists/:list_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `list_id` | integer | yes | 单板编号 | +| `position` | integer | yes | The position of the list | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1?position=2" +``` + +响应示例: + +``` +{ "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } +``` + +## Delete a board list[](#delete-a-board-list "Permalink") + +仅适用于管理员和项目所有者. 删除相关的单板列表. + +``` +DELETE /projects/:id/boards/:board_id/lists/:list_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `list_id` | integer | yes | 单板编号 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1" +``` \ No newline at end of file diff --git a/_book/docs/321.md b/_book/docs/321.md new file mode 100644 index 0000000000000000000000000000000000000000..1654badc4b2377c646c928d1c0b0480042ad0cc9 --- /dev/null +++ b/_book/docs/321.md @@ -0,0 +1,265 @@ +# Group Issue Boards API + +> 原文:[https://docs.gitlab.com/ee/api/group_boards.html](https://docs.gitlab.com/ee/api/group_boards.html) + +* [List all group issue boards in a group](#list-all-group-issue-boards-in-a-group) +* [Single group issue board](#single-group-issue-board) +* [Create a group issue board](#create-a-group-issue-board-premium) +* [Update a group issue board](#update-a-group-issue-board-premium) +* [Delete a group issue board](#delete-a-group-issue-board-premium) +* [List group issue board lists](#list-group-issue-board-lists) +* [Single group issue board list](#single-group-issue-board-list) +* [New group issue board list](#new-group-issue-board-list) +* [Edit group issue board list](#edit-group-issue-board-list) +* [Delete a group issue board list](#delete-a-group-issue-board-list) + +# Group Issue Boards API[](#group-issue-boards-api "Permalink") + +对组板的每个 API 调用都必须经过身份验证. + +If a user is not a member of a group and the group is private, a `GET` request will result in `404` status code. + +## List all group issue boards in a group[](#list-all-group-issue-boards-in-a-group "Permalink") + +列出给定组中的发行板. + +``` +GET /groups/:id/boards +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards" +``` + +响应示例: + +``` +[ { "id": 1, "name:": "group issue board", "group": { "id": 5, "name": "Documentcloud", "web_url": "http://example.com/groups/documentcloud" }, "milestone": { "id": 12 "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2 }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3 } ] } ] +``` + +由于具有多个组板的能力,使用 GitLab [Premium,Silver 或更高版本的用户](https://about.gitlab.com/pricing/)将看到不同的参数. + +响应示例: + +``` +[ { "id": 1, "name:": "group issue board", "group": { "id": 5, "name": "Documentcloud", "web_url": "http://example.com/groups/documentcloud" }, "milestone": { "id": 12 "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2 }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3 } ] } ] +``` + +## Single group issue board[](#single-group-issue-board "Permalink") + +获取单个小组问题委员会. + +``` +GET /groups/:id/boards/:board_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards/1" +``` + +响应示例: + +``` + { "id": 1, "name:": "group issue board", "group": { "id": 5, "name": "Documentcloud", "web_url": "http://example.com/groups/documentcloud" }, "milestone": { "id": 12 "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2 }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3 } ] } +``` + +GitLab [Premium,Silver 或更高版本的用户](https://about.gitlab.com/pricing/)将看到不同的参数,这是因为它具有多个组发行板的功能. + +响应示例: + +``` + { "id": 1, "name:": "group issue board", "group": { "id": 5, "name": "Documentcloud", "web_url": "http://example.com/groups/documentcloud" }, "milestone": { "id": 12 "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2 }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3 } ] } +``` + +## Create a group issue board[](#create-a-group-issue-board-premium "Permalink") + +创建一个小组发行委员会. + +``` +POST /groups/:id/boards +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 新板的名称 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards?name=newboard" +``` + +响应示例: + +``` + { "id": 1, "name": "newboard", "group": { "id": 5, "name": "Documentcloud", "web_url": "http://example.com/groups/documentcloud" }, "milestone": { "id": 12 "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2 }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3 } ] } +``` + +## Update a group issue board[](#update-a-group-issue-board-premium "Permalink") + +在 GitLab 11.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5954) . + +更新组发行板. + +``` +PUT /groups/:id/boards/:board_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `name` | string | no | 董事会的新名称 | +| `assignee_id` | integer | no | 董事会受让人的范围应为 | +| `milestone_id` | integer | no | 董事会应达到的里程碑 | +| `labels` | string | no | 以逗号分隔的标签名称列表,该范围应适用于板 | +| `weight` | integer | no | 重量范围从 0 到 9,该板的范围应为 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards/1?name=new_name&milestone_id=44&assignee_id=1&labels=GroupLabel&weight=4" +``` + +响应示例: + +``` + { "id": 1, "project": null, "lists": [], "name": "new_name", "group": { "id": 5, "name": "Documentcloud", "web_url": "http://example.com/groups/documentcloud" }, "milestone": { "id": 44, "iid": 1, "group_id": 5, "title": "Group Milestone", "description": "Group Milestone Desc", "state": "active", "created_at": "2018-07-03T07:15:19.271Z", "updated_at": "2018-07-03T07:15:19.271Z", "due_date": null, "start_date": null, "web_url": "http://example.com/groups/documentcloud/-/milestones/1" }, "assignee": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://example.com/root" }, "labels": [{ "id": 11, "name": "GroupLabel", "color": "#428BCA", "description": "" }], "weight": 4 } +``` + +## Delete a group issue board[](#delete-a-group-issue-board-premium "Permalink") + +删除组发行板. + +``` +DELETE /groups/:id/boards/:board_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards/1" +``` + +## List group issue board lists[](#list-group-issue-board-lists "Permalink") + +获取董事会名单的清单. 不包括`open`和`closed`列表 + +``` +GET /groups/:id/boards/:board_id/lists +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards/1/lists" +``` + +响应示例: + +``` +[ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2 }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3 } ] +``` + +## Single group issue board list[](#single-group-issue-board-list "Permalink") + +获取单板列表. + +``` +GET /groups/:id/boards/:board_id/lists/:list_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `list_id` | integer | yes | 单板编号 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards/1/lists/1" +``` + +响应示例: + +``` +{ "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 } +``` + +## New group issue board list[](#new-group-issue-board-list "Permalink") + +创建一个新的发行委员会列表. + +``` +POST /groups/:id/boards/:board_id/lists +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `label_id` | integer | yes | 标签的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4/boards/12/lists?milestone_id=7" +``` + +响应示例: + +``` +{ "id": 9, "label": null, "position": 0, "milestone": { "id": 7, "iid": 3, "group_id": 12, "title": "Milestone with due date", "description": "", "state": "active", "created_at": "2017-09-03T07:16:28.596Z", "updated_at": "2017-09-03T07:16:49.521Z", "due_date": null, "start_date": null, "web_url": "https://gitlab.example.com/groups/issue-reproduce/-/milestones/3" } } +``` + +## Edit group issue board list[](#edit-group-issue-board-list "Permalink") + +更新现有的发行委员会列表. 此调用用于更改列表位置. + +``` +PUT /groups/:id/boards/:board_id/lists/:list_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `list_id` | integer | yes | 单板编号 | +| `position` | integer | yes | 清单的位置 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/group/5/boards/1/lists/1?position=2" +``` + +响应示例: + +``` +{ "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 } +``` + +## Delete a group issue board list[](#delete-a-group-issue-board-list "Permalink") + +仅适用于管理员和群组所有者. 删除相关的单板列表. + +``` +DELETE /groups/:id/boards/:board_id/lists/:list_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `list_id` | integer | yes | 单板编号 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards/1/lists/1" +``` \ No newline at end of file diff --git a/_book/docs/322.md b/_book/docs/322.md new file mode 100644 index 0000000000000000000000000000000000000000..a612126453ea5b9021fee73a1782e2222b5e3451 --- /dev/null +++ b/_book/docs/322.md @@ -0,0 +1,779 @@ +# Issues API + +> 原文:[https://docs.gitlab.com/ee/api/issues.html](https://docs.gitlab.com/ee/api/issues.html) + +* [Issues pagination](#issues-pagination) +* [List issues](#list-issues) +* [List group issues](#list-group-issues) +* [List project issues](#list-project-issues) +* [Single issue](#single-issue) +* [New issue](#new-issue) +* [Rate limits](#rate-limits) +* [Edit issue](#edit-issue) +* [Delete an issue](#delete-an-issue) +* [Reorder an issue](#reorder-an-issue) +* [Move an issue](#move-an-issue) +* [Subscribe to an issue](#subscribe-to-an-issue) +* [Unsubscribe from an issue](#unsubscribe-from-an-issue) +* [Create a todo](#create-a-todo) +* [Set a time estimate for an issue](#set-a-time-estimate-for-an-issue) +* [Reset the time estimate for an issue](#reset-the-time-estimate-for-an-issue) +* [Add spent time for an issue](#add-spent-time-for-an-issue) +* [Reset spent time for an issue](#reset-spent-time-for-an-issue) +* [Get time tracking stats](#get-time-tracking-stats) +* [List merge requests related to issue](#list-merge-requests-related-to-issue) +* [List merge requests that will close issue on merge](#list-merge-requests-that-will-close-issue-on-merge) +* [Participants on issues](#participants-on-issues) +* [Comments on issues](#comments-on-issues) +* [Get user agent details](#get-user-agent-details) + +# Issues API[](#issues-api "Permalink") + +如果用户不是项目成员,并且该项目是私有项目,则对该项目的`GET`请求将产生`404`状态代码. + +## Issues pagination[](#issues-pagination "Permalink") + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +**弃用:不建议使用**响应中的`reference`属性,而推荐使用`references` . >推出了[GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354)**注意:** > `references.relative`相对于正在请求问题的组/项目. 从其项目中获取问题时> `relative`格式将与`short`格式相同,并且在跨组/项目进行请求时, `relative`格式将与`full`格式相同. + +## List issues[](#list-issues "Permalink") + +获取经过身份验证的用户有权访问的所有问题. 默认情况下,它仅返回当前用户创建的问题. 要获取所有问题,请使用参数`scope=all` . + +``` +GET /issues +GET /issues?state=opened +GET /issues?state=closed +GET /issues?labels=foo +GET /issues?labels=foo,bar +GET /issues?labels=foo,bar&state=opened +GET /issues?milestone=1.0.0 +GET /issues?milestone=1.0.0&state=opened +GET /issues?iids[]=42&iids[]=43 +GET /issues?author_id=5 +GET /issues?assignee_id=5 +GET /issues?my_reaction_emoji=star +GET /issues?search=foo&in=title +GET /issues?confidential=true +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `state` | string | no | 返回`all`问题,或者仅返回已`opened`或`closed` | +| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. | +| `with_labels_details` | boolean | no | 如果为`true` ,则响应将为标签字段中的每个标签返回更多详细信息`:name` , `:color` , `:description` , `:description_html` , `:text_color` . 默认值为`false` . [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)中引入了`description_html`属性 | +| `milestone` | string | no | 里程碑标题. `None`列出没有里程碑的所有问题. `Any`列出具有指定里程碑的所有问题. | +| `scope` | string | no | 回到问题在给定范围: `created_by_me` , `assigned_to_me`或`all` . 默认为`created_by_me` +对于 11.0 之前的版本,请改用现在不建议使用`created-by-me`范围或`created-by-me` `assigned-to-me`范围. +*(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) .在 GitLab 11.0 中[更改为 snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) )* | +| `author_id` | integer | no | 返回由给定用户`id`创建的问题. 与`author_username` . 与`scope=all`或`scope=assigned_to_me`结合使用. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) )* | +| `author_username` | string | no | 返回由给定`username`创建的问题. 类似于`author_id`并且与`author_id` . | +| `assignee_id` | integer | no | 返回分配给给定用户`id` . 互斥与`assignee_username` . `None`返回未分配的问题. 受让人有`Any`退货问题. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) )* | +| `assignee_username` | 字符串数组 | no | 返回分配给给定`username` . 类似于`assignee_id`并且与`assignee_id`互斥. 在 GitLab CE 中, `assignee_username`数组应仅包含单个值,否则将返回无效的参数错误. | +| `my_reaction_emoji` | string | no | 返回的问题由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. *(在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) )* | +| `weight` | integer | no | 以指定的`weight`返回问题. `None`返回没有分配权重的问题. 分配了权重的`Any`退货问题. | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的问题 | +| `order_by` | string | no | 回到问题下令`created_at` , `updated_at` , `priority` , `due_date` , `relative_position` , `label_priority` , `milestone_due` , `popularity` , `weight`领域. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`排列的问题. 默认为`desc` | +| `search` | string | no | 根据`title`和`description`搜索问题 | +| `in` | string | no | 修改`search`属性的范围. `title` , `description`或以逗号将它们连接在一起的字符串. 默认为`title,description` | +| `created_after` | datetime | no | 返回在给定时间或之后创建的问题 | +| `created_before` | datetime | no | 返回在给定时间或之前创建的问题 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的问题 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的问题 | +| `confidential` | boolean | no | 过滤机密或公共问题. | +| `not` | Hash | no | 返回与提供的参数不匹配的问题. 接受: `labels` , `milestone` , `author_id` , `author_username` , `assignee_id` , `assignee_username` , `my_reaction_emoji` | +| `non_archived` | boolean | no | 仅从未归档的项目返回问题. 如果为`false` ,则响应将返回已归档和未归档项目中的问题. 默认值为`true` . *(在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/issues/197170)引入)* | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/issues" +``` + +响应示例: + +``` +[ { "state" : "opened", "description" : "Ratione dolores corrupti mollitia soluta quia.", "author" : { "state" : "active", "id" : 18, "web_url" : "https://gitlab.example.com/eileen.lowe", "name" : "Alexandra Bashirian", "avatar_url" : null, "username" : "eileen.lowe" }, "milestone" : { "project_id" : 1, "description" : "Ducimus nam enim ex consequatur cumque ratione.", "state" : "closed", "due_date" : null, "iid" : 2, "created_at" : "2016-01-04T15:31:39.996Z", "title" : "v4.0", "id" : 17, "updated_at" : "2016-01-04T15:31:39.996Z" }, "project_id" : 1, "assignees" : [{ "state" : "active", "id" : 1, "name" : "Administrator", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root" }], "assignee" : { "state" : "active", "id" : 1, "name" : "Administrator", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root" }, "updated_at" : "2016-01-04T15:31:51.081Z", "closed_at" : null, "closed_by" : null, "id" : 76, "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", "created_at" : "2016-01-04T15:31:51.081Z", "moved_to_id" : null, "iid" : 6, "labels" : ["foo", "bar"], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "user_notes_count": 1, "due_date": "2016-07-22", "web_url": "http://example.com/my-group/my-project/issues/6", "references": { "short": "#6", "relative": "my-group/my-project#6", "full": "my-group/my-project#6" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "has_tasks": true, "task_status": "10 of 15 tasks completed", "confidential": false, "discussion_locked": false, "_links":{ "self":"http://example.com/api/v4/projects/1/issues/76", "notes":"`http://example.com/`api/v4/projects/1/issues/76/notes", "award_emoji":"http://example.com/api/v4/projects/1/issues/76/award_emoji", "project":"http://example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, "completed_count":0 } } ] +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +[ { "state" : "opened", "description" : "Ratione dolores corrupti mollitia soluta quia.", "weight": null, ... } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## List group issues[](#list-group-issues "Permalink") + +获取小组问题的列表. + +如果该组是私有的,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /groups/:id/issues +GET /groups/:id/issues?state=opened +GET /groups/:id/issues?state=closed +GET /groups/:id/issues?labels=foo +GET /groups/:id/issues?labels=foo,bar +GET /groups/:id/issues?labels=foo,bar&state=opened +GET /groups/:id/issues?milestone=1.0.0 +GET /groups/:id/issues?milestone=1.0.0&state=opened +GET /groups/:id/issues?iids[]=42&iids[]=43 +GET /groups/:id/issues?search=issue+title+or+description +GET /groups/:id/issues?author_id=5 +GET /groups/:id/issues?assignee_id=5 +GET /groups/:id/issues?my_reaction_emoji=star +GET /groups/:id/issues?confidential=true +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `state` | string | no | 返回所有问题,或者仅返回已`opened`或`closed` | +| `labels` | string | no | 标签名称的逗号分隔列表,必须具有要返回的所有标签的问题. `None`列出所有没有标签的问题. `Any`列出至少带有一个标签的所有问题. `No+Label` (不推荐使用)列出所有问题且不带标签. 预定义名称不区分大小写. | +| `with_labels_details` | boolean | no | 如果为`true` ,则响应将为标签字段中的每个标签返回更多详细信息`:name` , `:color` , `:description` , `:description_html` , `:text_color` . 默认值为`false` . [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)中引入了`description_html`属性 | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的问题 | +| `milestone` | string | no | 里程碑标题. `None`列出没有里程碑的所有问题. `Any`列出具有指定里程碑的所有问题. | +| `scope` | string | no | 回到问题在给定范围: `created_by_me` , `assigned_to_me`或`all` . +对于 11.0 之前的版本,请改用现在不建议使用`created-by-me`范围或`created-by-me` `assigned-to-me`范围. +*(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) .在 GitLab 11.0 中[更改为 snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) )* | +| `author_id` | integer | no | 返回由给定用户`id`创建的问题. 与`author_username` . 与`scope=all`或`scope=assigned_to_me`结合使用. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) )* | +| `author_username` | string | no | 返回由给定`username`创建的问题. 类似于`author_id`并且与`author_id` . | +| `assignee_id` | integer | no | 返回分配给给定用户`id` . 互斥与`assignee_username` . `None`返回未分配的问题. 受让人有`Any`退货问题. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) )* | +| `assignee_username` | 字符串数组 | no | 返回分配给给定`username` . 类似于`assignee_id`并且与`assignee_id`互斥. 在 GitLab CE 中, `assignee_username`数组应仅包含单个值,否则将返回无效的参数错误. | +| `my_reaction_emoji` | string | no | 返回的问题由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. *(在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) )* | +| `weight` | integer | no | 以指定的`weight`返回问题. `None`返回没有分配权重的问题. 分配了权重的`Any`退货问题. | +| `order_by` | string | no | 回到问题下令`created_at` , `updated_at` , `priority` , `due_date` , `relative_position` , `label_priority` , `milestone_due` , `popularity` , `weight`领域. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`排列的问题. 默认为`desc` | +| `search` | string | no | 搜索组问题的`title`和`description` | +| `created_after` | datetime | no | 返回在给定时间或之后创建的问题 | +| `created_before` | datetime | no | 返回在给定时间或之前创建的问题 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的问题 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的问题 | +| `confidential` | boolean | no | 过滤机密或公共问题. | +| `not` | Hash | no | 返回与提供的参数不匹配的问题. 接受: `labels` , `milestone` , `author_id` , `author_username` , `assignee_id` , `assignee_username` , `my_reaction_emoji` , `search` , `in` | +| `non_archived` | boolean | no | 从未归档的项目返回问题. 默认为 true. *(在[GitLab 12.8 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23785)引入)* | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4/issues" +``` + +响应示例: + +``` +[ { "project_id" : 4, "milestone" : { "due_date" : null, "project_id" : 4, "state" : "closed", "description" : "Rerum est voluptatem provident consequuntur molestias similique ipsum dolor.", "iid" : 3, "id" : 11, "title" : "v3.0", "created_at" : "2016-01-04T15:31:39.788Z", "updated_at" : "2016-01-04T15:31:39.788Z" }, "author" : { "state" : "active", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root", "id" : 1, "name" : "Administrator" }, "description" : "Omnis vero earum sunt corporis dolor et placeat.", "state" : "closed", "iid" : 1, "assignees" : [{ "avatar_url" : null, "web_url" : "https://gitlab.example.com/lennie", "state" : "active", "username" : "lennie", "id" : 9, "name" : "Dr. Luella Kovacek" }], "assignee" : { "avatar_url" : null, "web_url" : "https://gitlab.example.com/lennie", "state" : "active", "username" : "lennie", "id" : 9, "name" : "Dr. Luella Kovacek" }, "labels" : ["foo", "bar"], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "id" : 41, "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "updated_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z", "closed_at" : null, "closed_by" : null, "user_notes_count": 1, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/1", "references": { "short": "#1", "relative": "my-project#1", "full": "my-group/my-project#1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "has_tasks": true, "task_status": "10 of 15 tasks completed", "confidential": false, "discussion_locked": false, "_links":{ "self":"http://example.com/api/v4/projects/4/issues/41", "notes":"`http://example.com/`api/v4/projects/4/issues/41/notes", "award_emoji":"http://example.com/api/v4/projects/4/issues/41/award_emoji", "project":"http://example.com/api/v4/projects/4" }, "task_completion_status":{ "count":0, "completed_count":0 } } ] +``` + +Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see the `weight` parameter: + +``` +[ { "project_id" : 4, "description" : "Omnis vero earum sunt corporis dolor et placeat.", "weight": null, ... } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## List project issues[](#list-project-issues "Permalink") + +Get a list of a project’s issues. + +如果项目为私人项目,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /projects/:id/issues +GET /projects/:id/issues?state=opened +GET /projects/:id/issues?state=closed +GET /projects/:id/issues?labels=foo +GET /projects/:id/issues?labels=foo,bar +GET /projects/:id/issues?labels=foo,bar&state=opened +GET /projects/:id/issues?milestone=1.0.0 +GET /projects/:id/issues?milestone=1.0.0&state=opened +GET /projects/:id/issues?iids[]=42&iids[]=43 +GET /projects/:id/issues?search=issue+title+or+description +GET /projects/:id/issues?author_id=5 +GET /projects/:id/issues?assignee_id=5 +GET /projects/:id/issues?my_reaction_emoji=star +GET /projects/:id/issues?confidential=true +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的问题 | +| `state` | string | no | 返回所有问题,或者仅返回已`opened`或`closed` | +| `labels` | string | no | 标签名称的逗号分隔列表,必须具有要返回的所有标签的问题. `None`列出所有没有标签的问题. `Any`列出至少带有一个标签的所有问题. `No+Label` (不推荐使用)列出所有问题且不带标签. 预定义名称不区分大小写. | +| `with_labels_details` | boolean | no | 如果为`true` ,则响应将为标签字段中的每个标签返回更多详细信息`:name` , `:color` , `:description` , `:description_html` , `:text_color` . 默认值为`false` . `description_html`在[GitLab 12.7 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)引入 | +| `milestone` | string | no | 里程碑标题. `None`列出没有里程碑的所有问题. `Any`列出具有指定里程碑的所有问题. | +| `scope` | string | no | 回到问题在给定范围: `created_by_me` , `assigned_to_me`或`all` . +对于 11.0 之前的版本,请改用现在不建议使用`created-by-me`范围或`created-by-me` `assigned-to-me`范围. +*(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) .在 GitLab 11.0 中[更改为 snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) )* | +| `author_id` | integer | no | 返回由给定用户`id`创建的问题. 与`author_username` . 与`scope=all`或`scope=assigned_to_me`结合使用. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) )* | +| `author_username` | string | no | 返回由给定`username`创建的问题. 类似于`author_id`并且与`author_id` . | +| `assignee_id` | integer | no | 返回分配给给定用户`id` . 互斥与`assignee_username` . `None`返回未分配的问题. 受让人有`Any`退货问题. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) )* | +| `assignee_username` | 字符串数组 | no | 返回分配给给定`username` . 类似于`assignee_id`并且与`assignee_id`互斥. 在 GitLab CE 中, `assignee_username`数组应仅包含单个值,否则将返回无效的参数错误. | +| `my_reaction_emoji` | string | no | 返回的问题由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. *(在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) )* | +| `weight` | integer | no | 以指定的`weight`返回问题. `None`返回没有分配权重的问题. 分配了权重的`Any`退货问题. | +| `order_by` | string | no | 回到问题下令`created_at` , `updated_at` , `priority` , `due_date` , `relative_position` , `label_priority` , `milestone_due` , `popularity` , `weight`领域. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`排列的问题. 默认为`desc` | +| `search` | string | no | 根据`title`和`description`搜索项目问题 | +| `created_after` | datetime | no | 返回在给定时间或之后创建的问题 | +| `created_before` | datetime | no | 返回在给定时间或之前创建的问题 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的问题 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的问题 | +| `confidential` | boolean | no | 过滤机密或公共问题. | +| `not` | Hash | no | 返回与提供的参数不匹配的问题. 接受: `labels` , `milestone` , `author_id` , `author_username` , `assignee_id` , `assignee_username` , `my_reaction_emoji` , `search` , `in` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues" +``` + +响应示例: + +``` +[ { "project_id" : 4, "milestone" : { "due_date" : null, "project_id" : 4, "state" : "closed", "description" : "Rerum est voluptatem provident consequuntur molestias similique ipsum dolor.", "iid" : 3, "id" : 11, "title" : "v3.0", "created_at" : "2016-01-04T15:31:39.788Z", "updated_at" : "2016-01-04T15:31:39.788Z" }, "author" : { "state" : "active", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root", "id" : 1, "name" : "Administrator" }, "description" : "Omnis vero earum sunt corporis dolor et placeat.", "state" : "closed", "iid" : 1, "assignees" : [{ "avatar_url" : null, "web_url" : "https://gitlab.example.com/lennie", "state" : "active", "username" : "lennie", "id" : 9, "name" : "Dr. Luella Kovacek" }], "assignee" : { "avatar_url" : null, "web_url" : "https://gitlab.example.com/lennie", "state" : "active", "username" : "lennie", "id" : 9, "name" : "Dr. Luella Kovacek" }, "labels" : ["foo", "bar"], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "id" : 41, "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "updated_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z", "closed_at" : "2016-01-05T15:31:46.176Z", "closed_by" : { "state" : "active", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root", "id" : 1, "name" : "Administrator" }, "user_notes_count": 1, "due_date": "2016-07-22", "web_url": "http://example.com/my-group/my-project/issues/1", "references": { "short": "#1", "relative": "#1", "full": "my-group/my-project#1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "has_tasks": true, "task_status": "10 of 15 tasks completed", "confidential": false, "discussion_locked": false, "_links":{ "self":"http://example.com/api/v4/projects/4/issues/41", "notes":"`http://example.com/`api/v4/projects/4/issues/41/notes", "award_emoji":"http://example.com/api/v4/projects/4/issues/41/award_emoji", "project":"http://example.com/api/v4/projects/4" }, "task_completion_status":{ "count":0, "completed_count":0 } } ] +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +[ { "project_id" : 4, "description" : "Omnis vero earum sunt corporis dolor et placeat.", "weight": null, ... } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## Single issue[](#single-issue "Permalink") + +获得单个项目问题. + +如果项目为私人项目或问题为机密,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /projects/:id/issues/:issue_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | The internal ID of a project’s issue | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues/41" +``` + +响应示例: + +``` +{ "project_id" : 4, "milestone" : { "due_date" : null, "project_id" : 4, "state" : "closed", "description" : "Rerum est voluptatem provident consequuntur molestias similique ipsum dolor.", "iid" : 3, "id" : 11, "title" : "v3.0", "created_at" : "2016-01-04T15:31:39.788Z", "updated_at" : "2016-01-04T15:31:39.788Z", "closed_at" : "2016-01-05T15:31:46.176Z" }, "author" : { "state" : "active", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root", "id" : 1, "name" : "Administrator" }, "description" : "Omnis vero earum sunt corporis dolor et placeat.", "state" : "closed", "iid" : 1, "assignees" : [{ "avatar_url" : null, "web_url" : "https://gitlab.example.com/lennie", "state" : "active", "username" : "lennie", "id" : 9, "name" : "Dr. Luella Kovacek" }], "assignee" : { "avatar_url" : null, "web_url" : "https://gitlab.example.com/lennie", "state" : "active", "username" : "lennie", "id" : 9, "name" : "Dr. Luella Kovacek" }, "labels" : [], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "id" : 41, "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "updated_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z", "closed_at" : null, "closed_by" : null, "subscribed": false, "user_notes_count": 1, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/1", "references": { "short": "#1", "relative": "#1", "full": "my-group/my-project#1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "confidential": false, "discussion_locked": false, "_links": { "self": "http://example.com/api/v4/projects/1/issues/2", "notes": "http://example.com/api/v4/projects/1/issues/2/notes", "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", "project": "http://example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +{ "project_id" : 4, "description" : "Omnis vero earum sunt corporis dolor et placeat.", "weight": null, ... } +``` + +使用 GitLab [Premium 的](https://about.gitlab.com/pricing/)用户还将看到`epic`属性: + +``` +{ + "project_id" : 4, + "description" : "Omnis vero earum sunt corporis dolor et placeat.", + "epic_iid" : 5, //deprecated, use `iid` of the `epic` attribute + "epic": { + "id" : 42, + "iid" : 5, + "title": "My epic epic", + "url" : "/groups/h5bp/-/epics/5", + "group_id": 8 + }, + // ... +} +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +**注意** : `epic_iid`属性已过时, [将在版本 5 中删除](https://gitlab.com/gitlab-org/gitlab/-/issues/35157) . 请改用`epic`属性的`iid` . + +## New issue[](#new-issue "Permalink") + +创建一个新的项目问题. + +``` +POST /projects/:id/issues +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `iid` | integer/string | no | 项目问题的内部 ID(需要管理员或项目所有者权限) | +| `title` | string | yes | 问题标题 | +| `description` | string | no | 问题的描述. 限制为 1,048,576 个字符. | +| `confidential` | boolean | no | 将问题设置为机密. 默认值为`false` . | +| `assignee_ids` | 整数数组 | no | 要分配问题的用户的 ID | +| `milestone_id` | integer | no | 分配问题的里程碑的全局 ID | +| `labels` | string | no | 问题的逗号分隔标签名称 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如`2016-03-11T03:45:40Z` (需要管理员或项目/组所有者权限) | +| `due_date` | string | no | 日期时间字符串,格式为 YEAR-MONTH-DAY,例如`2016-03-11` | +| `merge_request_to_resolve_discussions_of` | integer | no | 解决所有问题的合并请求的 IID. 这将使用默认描述填充问题,并将所有讨论标记为已解决. 传递描述或标题时,这些值将优先于默认值. | +| `discussion_to_resolve` | string | no | 要解决的讨论的​​ID. 这将使用默认描述填充问题,并将讨论标记为已解决. 与`merge_request_to_resolve_discussions_of`结合使用. | +| `weight` | integer | no | 问题的分量. 有效值大于或等于 0. | +| `epic_id` | integer | no | 要添加问题的史诗的 ID. 有效值大于或等于 0. | +| `epic_iid` | integer | no | 要添加问题的史诗的 IID. 有效值大于或等于 0.(不建议使用, [将在版本 5 中将其删除](https://gitlab.com/gitlab-org/gitlab/-/issues/35157) ) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues?title=Issues%20with%20auth&labels=bug" +``` + +响应示例: + +``` +{ "project_id" : 4, "id" : 84, "created_at" : "2016-01-07T12:44:33.959Z", "iid" : 14, "title" : "Issues with auth", "state" : "opened", "assignees" : [], "assignee" : null, "labels" : [ "bug" ], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "closed_at" : null, "closed_by" : null, "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/14", "references": { "short": "#14", "relative": "#14", "full": "my-group/my-project#14" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "confidential": false, "discussion_locked": false, "_links": { "self": "http://example.com/api/v4/projects/1/issues/2", "notes": "http://example.com/api/v4/projects/1/issues/2/notes", "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", "project": "http://example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +{ "project_id" : 4, "description" : null, "weight": null, ... } +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## Rate limits[](#rate-limits "Permalink") + +为了避免滥用,用户仅限于: + +| 请求类型 | Limit | +| --- | --- | +| Create | 每分钟 300 期 | + +## Edit issue[](#edit-issue "Permalink") + +更新现有项目问题. 此调用还用于将问题标记为已结束. + +``` +PUT /projects/:id/issues/:issue_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `title` | string | no | 问题标题 | +| `description` | string | no | 问题的描述. 限制为 1,048,576 个字符. | +| `confidential` | boolean | no | 将问题更新为机密 | +| `assignee_ids` | 整数数组 | no | 要分配问题的用户的 ID. 设置为`0`或提供一个空值以取消分配所有受让人. | +| `milestone_id` | integer | no | 要分配问题的里程碑的全局 ID. 设置为`0`或提供一个空值以取消分配里程碑. | +| `labels` | string | no | 问题的标签名称,以逗号分隔. 设置为空字符串以取消分配所有标签. | +| `add_labels` | string | no | 以逗号分隔的标签名称添加到问题中. | +| `remove_labels` | string | no | 逗号分隔的标签名称可从问题中删除. | +| `state_event` | string | no | 问题的状态事件. 设为`close`以关闭问题,然后`reopen`以重新打开它 | +| `updated_at` | string | no | 日期时间字符串,ISO 8601 格式,例如`2016-03-11T03:45:40Z` (需要管理员或项目所有者权限). 不接受空字符串或空值. | +| `due_date` | string | no | 日期时间字符串,格式为 YEAR-MONTH-DAY,例如`2016-03-11` | +| `weight` | integer | no | 问题的分量. 有效值大于或等于 0.0 | +| `discussion_locked` | boolean | no | 指示问题的讨论是否被锁定的标志. 如果讨论被锁定,则只有项目成员可以添加或编辑评论. | +| `epic_id` | integer | no | 要添加问题的史诗的 ID. 有效值大于或等于 0. | +| `epic_iid` | integer | no | 要添加问题的史诗的 IID. 有效值大于或等于 0.(不建议使用, [将在版本 5 中将其删除](https://gitlab.com/gitlab-org/gitlab/-/issues/35157) ) | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues/85?state_event=close" +``` + +响应示例: + +``` +{ "created_at" : "2016-01-07T12:46:01.410Z", "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "username" : "eileen.lowe", "id" : 18, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe" }, "state" : "closed", "title" : "Issues with auth", "project_id" : 4, "description" : null, "updated_at" : "2016-01-07T12:55:16.213Z", "closed_at" : "2016-01-08T12:55:16.213Z", "closed_by" : { "state" : "active", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root", "id" : 1, "name" : "Administrator" }, "iid" : 15, "labels" : [ "bug" ], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "id" : 85, "assignees" : [], "assignee" : null, "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": "2016-07-22", "web_url": "http://example.com/my-group/my-project/issues/15", "references": { "short": "#15", "relative": "#15", "full": "my-group/my-project#15" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "confidential": false, "discussion_locked": false, "_links": { "self": "http://example.com/api/v4/projects/1/issues/2", "notes": "http://example.com/api/v4/projects/1/issues/2/notes", "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", "project": "http://example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +{ "project_id" : 4, "description" : null, "weight": null, ... } +``` + +**注:**至少以下参数之一是需要传递的请求是成功的: `:assignee_id` , `:assignee_ids` , `:confidential` , `:created_at` , `:description` , `:discussion_locked` , `:due_date` , `:labels` , `:milestone_id` , `:state_event` ,或`:title` .**注意:**不建议使用`assignee`列. 现在,我们将其显示为符合 GitLab EE API 的单个大小的数组`assignees` .**注意:** `closed_by`属性是[在 GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入的](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) . 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## Delete an issue[](#delete-an-issue "Permalink") + +仅适用于管理员和项目所有者. 删除相关问题. + +``` +DELETE /projects/:id/issues/:issue_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues/85" +``` + +## Reorder an issue[](#reorder-an-issue "Permalink") + +> 作为[社区贡献](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35349) [引入](https://gitlab.com/gitlab-org/gitlab/-/issues/211864)到 GitLab 13.2 中. + +重新排序问题,手动排序问题时可以看到结果 + +``` +PUT /projects/:id/issues/:issue_iid/reorder +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `move_after_id` | integer | no | 一个项目的 ID,以便在以后移动此问题 | +| `move_before_id` | integer | no | 一个项目的 ID,以便在此之前移此问题 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues/85/reorder?move_after_id=51&move_before_id=92" +``` + +## Move an issue[](#move-an-issue "Permalink") + +将问题移到其他项目. 如果目标项目等于源项目,或者用户没有足够的权限来移动问题,则返回错误`400`和解释性错误消息. + +If a given label and/or milestone with the same name also exists in the target project, it will then be assigned to the issue that is being moved. + +``` +POST /projects/:id/issues/:issue_iid/move +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `to_project_id` | integer | yes | 新项目的 ID | + +``` +curl --header "PRIVATE-TOKEN: " --form to_project_id=5 "https://gitlab.example.com/api/v4/projects/4/issues/85/move" +``` + +Example response: + +``` +{ "id": 92, "iid": 11, "project_id": 5, "title": "Sit voluptas tempora quisquam aut doloribus et.", "description": "Repellat voluptas quibusdam voluptatem exercitationem.", "state": "opened", "created_at": "2016-04-05T21:41:45.652Z", "updated_at": "2016-04-07T12:20:17.596Z", "closed_at": null, "closed_by": null, "labels": [], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "milestone": null, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "assignee": { "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }, "author": { "name": "Kris Steuber", "username": "solon.cremin", "id": 10, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/7a190fecbaa68212a4b68aeb6e3acd10?s=80&d=identicon", "web_url": "https://gitlab.example.com/solon.cremin" }, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/11", "references": { "short": "#11", "relative": "#11", "full": "my-group/my-project#11" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "confidential": false, "discussion_locked": false, "_links": { "self": "http://example.com/api/v4/projects/1/issues/2", "notes": "http://example.com/api/v4/projects/1/issues/2/notes", "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", "project": "http://example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +{ "project_id": 5, "description": "Repellat voluptas quibusdam voluptatem exercitationem.", "weight": null, ... } +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## Subscribe to an issue[](#subscribe-to-an-issue "Permalink") + +为经过身份验证的用户订阅问题以接收通知. 如果用户已经订阅了该问题,则返回状态码`304` . + +``` +POST /projects/:id/issues/:issue_iid/subscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/subscribe" +``` + +响应示例: + +``` +{ "id": 92, "iid": 11, "project_id": 5, "title": "Sit voluptas tempora quisquam aut doloribus et.", "description": "Repellat voluptas quibusdam voluptatem exercitationem.", "state": "opened", "created_at": "2016-04-05T21:41:45.652Z", "updated_at": "2016-04-07T12:20:17.596Z", "closed_at": null, "closed_by": null, "labels": [], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "milestone": null, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "assignee": { "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }, "author": { "name": "Kris Steuber", "username": "solon.cremin", "id": 10, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/7a190fecbaa68212a4b68aeb6e3acd10?s=80&d=identicon", "web_url": "https://gitlab.example.com/solon.cremin" }, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/11", "references": { "short": "#11", "relative": "#11", "full": "my-group/my-project#11" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "confidential": false, "discussion_locked": false, "_links": { "self": "http://example.com/api/v4/projects/1/issues/2", "notes": "http://example.com/api/v4/projects/1/issues/2/notes", "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", "project": "http://example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +{ "project_id": 5, "description": "Repellat voluptas quibusdam voluptatem exercitationem.", "weight": null, ... } +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## Unsubscribe from an issue[](#unsubscribe-from-an-issue "Permalink") + +从问题中退订已认证的用户,以不接收来自该问题的通知. 如果用户未订阅该问题,则返回状态码`304` . + +``` +POST /projects/:id/issues/:issue_iid/unsubscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/unsubscribe" +``` + +响应示例: + +``` +{ "id": 93, "iid": 12, "project_id": 5, "title": "Incidunt et rerum ea expedita iure quibusdam.", "description": "Et cumque architecto sed aut ipsam.", "state": "opened", "created_at": "2016-04-05T21:41:45.217Z", "updated_at": "2016-04-07T13:02:37.905Z", "labels": [], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "milestone": null, "assignee": { "name": "Edwardo Grady", "username": "keyon", "id": 21, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/3e6f06a86cf27fa8b56f3f74f7615987?s=80&d=identicon", "web_url": "https://gitlab.example.com/keyon" }, "closed_at": null, "closed_by": null, "author": { "name": "Vivian Hermann", "username": "orville", "id": 11, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/5224fd70153710e92fb8bcf79ac29d67?s=80&d=identicon", "web_url": "https://gitlab.example.com/orville" }, "subscribed": false, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/12", "references": { "short": "#12", "relative": "#12", "full": "my-group/my-project#12" }, "confidential": false, "discussion_locked": false, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +## Create a todo[](#create-a-todo "Permalink") + +在问题上为当前用户手动创建待办事项. 如果在该问题上已经存在用户的待办事项,则返回状态码`304` . + +``` +POST /projects/:id/issues/:issue_iid/todo +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/todo" +``` + +响应示例: + +``` +{ "id": 112, "project": { "id": 5, "name": "GitLab CI/CD", "name_with_namespace": "GitLab Org / GitLab CI/CD", "path": "gitlab-ci", "path_with_namespace": "gitlab-org/gitlab-ci" }, "author": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "action_name": "marked", "target_type": "Issue", "target": { "id": 93, "iid": 10, "project_id": 5, "title": "Vel voluptas atque dicta mollitia adipisci qui at.", "description": "Tempora laboriosam sint magni sed voluptas similique.", "state": "closed", "created_at": "2016-06-17T07:47:39.486Z", "updated_at": "2016-07-01T11:09:13.998Z", "labels": [], "milestone": { "id": 26, "iid": 1, "project_id": 5, "title": "v0.0", "description": "Accusantium nostrum rerum quae quia quis nesciunt suscipit id.", "state": "closed", "created_at": "2016-06-17T07:47:33.832Z", "updated_at": "2016-06-17T07:47:33.832Z", "due_date": null }, "assignees": [{ "name": "Jarret O'Keefe", "username": "francisca", "id": 14, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a7fa515d53450023c83d62986d0658a8?s=80&d=identicon", "web_url": "https://gitlab.example.com/francisca" }], "assignee": { "name": "Jarret O'Keefe", "username": "francisca", "id": 14, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a7fa515d53450023c83d62986d0658a8?s=80&d=identicon", "web_url": "https://gitlab.example.com/francisca" }, "author": { "name": "Maxie Medhurst", "username": "craig_rutherford", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", "web_url": "https://gitlab.example.com/craig_rutherford" }, "subscribed": true, "user_notes_count": 7, "upvotes": 0, "downvotes": 0, "merge_requests_count": 0, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/10", "references": { "short": "#10", "relative": "#10", "full": "my-group/my-project#10" }, "confidential": false, "discussion_locked": false, "task_completion_status":{ "count":0, "completed_count":0 } }, "target_url": "https://gitlab.example.com/gitlab-org/gitlab-ci/issues/10", "body": "Vel voluptas atque dicta mollitia adipisci qui at.", "state": "pending", "created_at": "2016-07-01T11:09:13.992Z" } +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## Set a time estimate for an issue[](#set-a-time-estimate-for-an-issue "Permalink") + +设置此问题的估计工作时间. + +``` +POST /projects/:id/issues/:issue_iid/time_estimate +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `duration` | string | yes | 以人类格式表示的持续时间. 例如:3h30m | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/time_estimate?duration=3h30m" +``` + +响应示例: + +``` +{ "human_time_estimate": "3h 30m", "human_total_time_spent": null, "time_estimate": 12600, "total_time_spent": 0 } +``` + +## Reset the time estimate for an issue[](#reset-the-time-estimate-for-an-issue "Permalink") + +将此问题的估计时间重置为 0 秒. + +``` +POST /projects/:id/issues/:issue_iid/reset_time_estimate +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/reset_time_estimate" +``` + +响应示例: + +``` +{ "human_time_estimate": null, "human_total_time_spent": null, "time_estimate": 0, "total_time_spent": 0 } +``` + +## Add spent time for an issue[](#add-spent-time-for-an-issue "Permalink") + +增加了解决此问题的时间 + +``` +POST /projects/:id/issues/:issue_iid/add_spent_time +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `duration` | string | yes | 以人类格式表示的持续时间. 例如:3h30m | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/add_spent_time?duration=1h" +``` + +Example response: + +``` +{ "human_time_estimate": null, "human_total_time_spent": "1h", "time_estimate": 0, "total_time_spent": 3600 } +``` + +## Reset spent time for an issue[](#reset-spent-time-for-an-issue "Permalink") + +将此问题的总花费时间重置为 0 秒. + +``` +POST /projects/:id/issues/:issue_iid/reset_spent_time +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/reset_spent_time" +``` + +响应示例: + +``` +{ "human_time_estimate": null, "human_total_time_spent": null, "time_estimate": 0, "total_time_spent": 0 } +``` + +## Get time tracking stats[](#get-time-tracking-stats "Permalink") + +如果项目为私人项目或问题为机密,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /projects/:id/issues/:issue_iid/time_stats +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/time_stats" +``` + +响应示例: + +``` +{ "human_time_estimate": "2h", "human_total_time_spent": "1h", "time_estimate": 7200, "total_time_spent": 3600 } +``` + +## List merge requests related to issue[](#list-merge-requests-related-to-issue "Permalink") + +获取与该问题相关的所有合并请求. + +如果项目为私人项目或问题为机密,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /projects/:id/issues/:issue_id/related_merge_requests +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/11/related_merge_requests" +``` + +响应示例: + +``` +[ { "id": 29, "iid": 11, "project_id": 1, "title": "Provident eius eos blanditiis consequatur neque odit.", "description": "Ut consequatur ipsa aspernatur quisquam voluptatum fugit. Qui harum corporis quo fuga ut incidunt veritatis. Autem necessitatibus et harum occaecati nihil ea.\r\n\r\ntwitter/flight#8", "state": "opened", "created_at": "2018-09-18T14:36:15.510Z", "updated_at": "2018-09-19T07:45:13.089Z", "closed_by": null, "closed_at": null, "target_branch": "v2.x", "source_branch": "so_long_jquery", "user_notes_count": 9, "upvotes": 0, "downvotes": 0, "author": { "id": 14, "name": "Verna Hills", "username": "lawanda_reinger", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/de68a91aeab1cff563795fb98a0c2cc0?s=80&d=identicon", "web_url": "https://gitlab.example.com/lawanda_reinger" }, "assignee": { "id": 19, "name": "Jody Baumbach", "username": "felipa.kuvalis", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/6541fc75fc4e87e203529bd275fafd07?s=80&d=identicon", "web_url": "https://gitlab.example.com/felipa.kuvalis" }, "source_project_id": 1, "target_project_id": 1, "labels": [], "work_in_progress": false, "milestone": { "id": 27, "iid": 2, "project_id": 1, "title": "v1.0", "description": "Et tenetur voluptatem minima doloribus vero dignissimos vitae.", "state": "active", "created_at": "2018-09-18T14:35:44.353Z", "updated_at": "2018-09-18T14:35:44.353Z", "due_date": null, "start_date": null, "web_url": "https://gitlab.example.com/twitter/flight/milestones/2" }, "merge_when_pipeline_succeeds": false, "merge_status": "cannot_be_merged", "sha": "3b7b528e9353295c1c125dad281ac5b5deae5f12", "merge_commit_sha": null, "squash_commit_sha": null, "discussion_locked": null, "should_remove_source_branch": null, "force_remove_source_branch": false, "reference": "!11", "web_url": "https://gitlab.example.com/twitter/flight/merge_requests/4", "references": { "short": "!4", "relative": "!4", "full": "twitter/flight!4" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "task_completion_status": { "count": 0, "completed_count": 0 }, "changes_count": "10", "latest_build_started_at": "2018-12-05T01:16:41.723Z", "latest_build_finished_at": "2018-12-05T02:35:54.046Z", "first_deployed_to_production_at": null, "pipeline": { "id": 38980952, "sha": "81c6a84c7aebd45a1ac2c654aa87f11e32338e0a", "ref": "test-branch", "status": "success", "web_url": "https://gitlab.com/gitlab-org/gitlab/pipelines/38980952" }, "head_pipeline": { "id": 38980952, "sha": "81c6a84c7aebd45a1ac2c654aa87f11e32338e0a", "ref": "test-branch", "status": "success", "web_url": "https://gitlab.example.com/twitter/flight/pipelines/38980952", "before_sha": "3c738a37eb23cf4c0ed0d45d6ddde8aad4a8da51", "tag": false, "yaml_errors": null, "user": { "id": 19, "name": "Jody Baumbach", "username": "felipa.kuvalis", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/6541fc75fc4e87e203529bd275fafd07?s=80&d=identicon", "web_url": "https://gitlab.example.com/felipa.kuvalis" }, "created_at": "2018-12-05T01:16:13.342Z", "updated_at": "2018-12-05T02:35:54.086Z", "started_at": "2018-12-05T01:16:41.723Z", "finished_at": "2018-12-05T02:35:54.046Z", "committed_at": null, "duration": 4436, "coverage": "46.68", "detailed_status": { "icon": "status_warning", "text": "passed", "label": "passed with warnings", "group": "success-with-warnings", "tooltip": "passed", "has_details": true, "details_path": "/twitter/flight/pipelines/38", "illustration": null, "favicon": "https://gitlab.example.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png" } }, "diff_refs": { "base_sha": "d052d768f0126e8cddf80afd8b1eb07f406a3fcb", "head_sha": "81c6a84c7aebd45a1ac2c654aa87f11e32338e0a", "start_sha": "d052d768f0126e8cddf80afd8b1eb07f406a3fcb" }, "merge_error": null, "user": { "can_merge": true } } ] +``` + +## List merge requests that will close issue on merge[](#list-merge-requests-that-will-close-issue-on-merge "Permalink") + +获取所有合并请求,这些合并请求将在合并时关闭问题. + +如果项目为私人项目或问题为机密,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /projects/:id/issues/:issue_iid/closed_by +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/11/closed_by" +``` + +响应示例: + +``` +[ { "id": 6471, "iid": 6432, "project_id": 1, "title": "add a test for cgi lexer options", "description": "closes #11", "state": "opened", "created_at": "2017-04-06T18:33:34.168Z", "updated_at": "2017-04-09T20:10:24.983Z", "target_branch": "master", "source_branch": "feature.custom-highlighting", "upvotes": 0, "downvotes": 0, "author": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "assignee": null, "source_project_id": 1, "target_project_id": 1, "closed_at": null, "closed_by": null, "labels": [], "work_in_progress": false, "milestone": null, "merge_when_pipeline_succeeds": false, "merge_status": "unchecked", "sha": "5a62481d563af92b8e32d735f2fa63b94e806835", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "should_remove_source_branch": null, "force_remove_source_branch": false, "web_url": "https://gitlab.example.com/gitlab-org/gitlab-test/merge_requests/6432", "reference": "!6432", "references": { "short": "!6432", "relative": "!6432", "full": "gitlab-org/gitlab-test!6432" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +## Participants on issues[](#participants-on-issues "Permalink") + +如果项目为私人项目或问题为机密,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /projects/:id/issues/:issue_iid/participants +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/participants" +``` + +响应示例: + +``` +[ { "id": 1, "name": "John Doe1", "username": "user1", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://localhost/user1" }, { "id": 5, "name": "John Doe5", "username": "user5", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/4aea8cf834ed91844a2da4ff7ae6b491?s=80&d=identicon", "web_url": "http://localhost/user5" } ] +``` + +## Comments on issues[](#comments-on-issues "Permalink") + +注释是通过[notes](notes.html)资源完成的. + +## Get user agent details[](#get-user-agent-details "Permalink") + +仅适用于管理员. + +``` +GET /projects/:id/issues/:issue_iid/user_agent_detail +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | The internal ID of a project’s issue | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/user_agent_detail" +``` + +响应示例: + +``` +{ "user_agent": "AppleWebKit/537.36", "ip_address": "127.0.0.1", "akismet_submitted": false } +``` \ No newline at end of file diff --git a/_book/docs/323.md b/_book/docs/323.md new file mode 100644 index 0000000000000000000000000000000000000000..e816f675bdb507aafd39465d2ab3bd68d9503cb1 --- /dev/null +++ b/_book/docs/323.md @@ -0,0 +1,119 @@ +# Epic Issues API + +> 原文:[https://docs.gitlab.com/ee/api/epic_issues.html](https://docs.gitlab.com/ee/api/epic_issues.html) + +* [List issues for an epic](#list-issues-for-an-epic) +* [Assign an issue to the epic](#assign-an-issue-to-the-epic) +* [Remove an issue from the epic](#remove-an-issue-from-the-epic) +* [Update epic - issue association](#update-epic---issue-association) + +# Epic Issues API[](#epic-issues-api-premium "Permalink") + +每个对 epic_issues 的 API 调用都必须经过验证. + +如果用户不是组的成员,并且该组是私有的,则对该组的`GET`请求将产生`404`状态代码. + +Epics 仅在 GitLab [Premium 和更高版本](https://about.gitlab.com/pricing/)中可用. 如果 Epics 功能不可用,将返回`403`状态代码. + +## List issues for an epic[](#list-issues-for-an-epic "Permalink") + +获取分配给史诗且经过身份验证的用户有权访问的所有问题. + +``` +GET /groups/:id/epics/:epic_iid/issues +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/issues/" +``` + +响应示例: + +``` +[ { "id": 76, "iid": 6, "project_id": 8, "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", "description" : "Ratione dolores corrupti mollitia soluta quia.", "state": "opened", "created_at": "2017-11-15T13:39:24.670Z", "updated_at": "2018-01-04T10:49:19.506Z", "closed_at": null, "labels": [], "milestone": { "id": 38, "iid": 3, "project_id": 8, "title": "v2.0", "description": "In tempore culpa inventore quo accusantium.", "state": "closed", "created_at": "2017-11-15T13:39:13.825Z", "updated_at": "2017-11-15T13:39:13.825Z", "due_date": null, "start_date": null }, "assignees": [{ "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }], "assignee": { "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }, "author": { "id": 13, "name": "Michell Johns", "username": "chris_hahn", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/30e3b2122ccd6b8e45e8e14a3ffb58fc?s=80&d=identicon", "web_url": "http://localhost:3001/chris_hahn" }, "user_notes_count": 8, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "weight": null, "discussion_locked": null, "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/6", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "_links":{ "self": "http://localhost:3001/api/v4/projects/8/issues/6", "notes": "http://localhost:3001/api/v4/projects/8/issues/6/notes", "award_emoji": "http://localhost:3001/api/v4/projects/8/issues/6/award_emoji", "project": "http://localhost:3001/api/v4/projects/8" }, "subscribed": true, "epic_issue_id": 2 } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +## Assign an issue to the epic[](#assign-an-issue-to-the-epic "Permalink") + +创建史诗-事件关联. 如果所讨论的问题属于另一个史诗,则不会从该史诗中分配该问题. + +``` +POST /groups/:id/epics/:epic_iid/issues/:issue_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID. | +| `issue_id` | integer/string | yes | 问题的 ID. | + +``` +curl --header POST "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/issues/55" +``` + +响应示例: + +``` +{ "id": 11, "epic": { "id": 30, "iid": 5, "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author": { "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }, "start_date": null, "end_date": null }, "issue": { "id": 55, "iid": 13, "project_id": 8, "title": "Beatae laborum voluptatem voluptate eligendi ex accusamus.", "description": "Quam veritatis debitis omnis aliquam sit.", "state": "opened", "created_at": "2017-11-05T13:59:12.782Z", "updated_at": "2018-01-05T10:33:03.900Z", "closed_at": null, "labels": [], "milestone": { "id": 48, "iid": 6, "project_id": 8, "title": "Sprint - Sed sed maxime temporibus ipsa ullam qui sit.", "description": "Quos veritatis qui expedita sunt deleniti accusamus.", "state": "active", "created_at": "2017-11-05T13:59:12.445Z", "updated_at": "2017-11-05T13:59:12.445Z", "due_date": "2017-11-13", "start_date": "2017-11-05" }, "assignees": [{ "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }], "assignee": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "author": { "id": 25, "name": "User 3", "username": "user3", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80&d=identicon", "web_url": "http://localhost:3001/user3" }, "user_notes_count": 0, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "weight": null, "discussion_locked": null, "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/13", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } } +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +## Remove an issue from the epic[](#remove-an-issue-from-the-epic "Permalink") + +删除史诗-问题关联. + +``` +DELETE /groups/:id/epics/:epic_iid/issues/:epic_issue_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID. | +| `epic_issue_id` | integer/string | yes | 问题的 ID-史诗般的协会. | + +``` +curl --header DELETE "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/issues/11" +``` + +响应示例: + +``` +{ "id": 11, "epic": { "id": 30, "iid": 5, "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author": { "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }, "start_date": null, "end_date": null }, "issue": { "id": 223, "iid": 13, "project_id": 8, "title": "Beatae laborum voluptatem voluptate eligendi ex accusamus.", "description": "Quam veritatis debitis omnis aliquam sit.", "state": "opened", "created_at": "2017-11-05T13:59:12.782Z", "updated_at": "2018-01-05T10:33:03.900Z", "closed_at": null, "labels": [], "milestone": { "id": 48, "iid": 6, "project_id": 8, "title": "Sprint - Sed sed maxime temporibus ipsa ullam qui sit.", "description": "Quos veritatis qui expedita sunt deleniti accusamus.", "state": "active", "created_at": "2017-11-05T13:59:12.445Z", "updated_at": "2017-11-05T13:59:12.445Z", "due_date": "2017-11-13", "start_date": "2017-11-05" }, "assignees": [{ "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }], "assignee": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "author": { "id": 25, "name": "User 3", "username": "user3", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80&d=identicon", "web_url": "http://localhost:3001/user3" }, "user_notes_count": 0, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "weight": null, "discussion_locked": null, "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/13", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } } +``` + +**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. + +## Update epic - issue association[](#update-epic---issue-association "Permalink") + +更新史诗-问题关联. + +``` +PUT /groups/:id/epics/:epic_iid/issues/:epic_issue_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID. | +| `epic_issue_id` | integer/string | yes | 问题的 ID-史诗般的协会. | +| `move_before_id` | integer/string | no | 问题的 ID-史诗般的关联,应放在问题中的链接之前. | +| `move_after_id` | integer/string | no | 问题的 ID-史诗般的关联,应该放在问题中的链接之后. | + +``` +curl --header PUT "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/issues/11?move_before_id=20" +``` + +响应示例: + +``` +[ { "id": 30, "iid": 6, "project_id": 8, "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", "description" : "Ratione dolores corrupti mollitia soluta quia.", "state": "opened", "created_at": "2017-11-15T13:39:24.670Z", "updated_at": "2018-01-04T10:49:19.506Z", "closed_at": null, "labels": [], "milestone": { "id": 38, "iid": 3, "project_id": 8, "title": "v2.0", "description": "In tempore culpa inventore quo accusantium.", "state": "closed", "created_at": "2017-11-15T13:39:13.825Z", "updated_at": "2017-11-15T13:39:13.825Z", "due_date": null, "start_date": null }, "assignees": [{ "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }], "assignee": { "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }, "author": { "id": 13, "name": "Michell Johns", "username": "chris_hahn", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/30e3b2122ccd6b8e45e8e14a3ffb58fc?s=80&d=identicon", "web_url": "http://localhost:3001/chris_hahn" }, "user_notes_count": 8, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "weight": null, "discussion_locked": null, "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/6", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "_links":{ "self": "http://localhost:3001/api/v4/projects/8/issues/6", "notes": "http://localhost:3001/api/v4/projects/8/issues/6/notes", "award_emoji": "http://localhost:3001/api/v4/projects/8/issues/6/award_emoji", "project": "http://localhost:3001/api/v4/projects/8" }, "subscribed": true, "epic_issue_id": 11, "relative_position": 55 } ] +``` \ No newline at end of file diff --git a/_book/docs/324.md b/_book/docs/324.md new file mode 100644 index 0000000000000000000000000000000000000000..2daad0ba9a23a87a1eaa232494f435921f3d0674 --- /dev/null +++ b/_book/docs/324.md @@ -0,0 +1,157 @@ +# Issues Statistics API + +> 原文:[https://docs.gitlab.com/ee/api/issues_statistics.html](https://docs.gitlab.com/ee/api/issues_statistics.html) + +* [Get issues statistics](#get-issues-statistics) +* [Get group issues statistics](#get-group-issues-statistics) +* [Get project issues statistics](#get-project-issues-statistics) + +# Issues Statistics API[](#issues-statistics-api "Permalink") + +每个对 issue_statistics 的 API 调用都必须经过身份验证. + +如果用户不是项目成员,并且该项目是私有项目,则对该项目的`GET`请求将导致`404`状态代码. + +## Get issues statistics[](#get-issues-statistics "Permalink") + +获取有关经过身份验证的用户有权访问的所有问题的问题计数统计信息. 默认情况下,它仅返回当前用户创建的问题. 要获取所有问题,请使用参数`scope=all` . + +``` +GET /issues_statistics +GET /issues_statistics?labels=foo +GET /issues_statistics?labels=foo,bar +GET /issues_statistics?labels=foo,bar&state=opened +GET /issues_statistics?milestone=1.0.0 +GET /issues_statistics?milestone=1.0.0&state=opened +GET /issues_statistics?iids[]=42&iids[]=43 +GET /issues_statistics?author_id=5 +GET /issues_statistics?assignee_id=5 +GET /issues_statistics?my_reaction_emoji=star +GET /issues_statistics?search=foo&in=title +GET /issues_statistics?confidential=true +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `labels` | string | no | 标签名称的逗号分隔列表,必须具有要返回的所有标签的问题. `None`列出所有没有标签的问题. `Any`列出至少带有一个标签的所有问题. | +| `milestone` | string | no | 里程碑标题. `None`列出没有里程碑的所有问题. `Any`列出具有指定里程碑的所有问题. | +| `scope` | string | no | 回到问题在给定范围: `created_by_me` , `assigned_to_me`或`all` . 默认为`created_by_me` | +| `author_id` | integer | no | 返回由给定用户`id`创建的问题. 与`author_username` . 与`scope=all`或`scope=assigned_to_me`结合使用. | +| `author_username` | string | no | 返回由给定`username`创建的问题. 类似于`author_id`并且与`author_id` . | +| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. | +| `assignee_username` | 字符串数组 | no | 返回分配给给定`username` . 类似于`assignee_id`并且与`assignee_id`互斥. 在 GitLab CE 中, `assignee_username`数组应仅包含单个值,否则将返回无效的参数错误. | +| `my_reaction_emoji` | string | no | 返回的问题由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的问题 | +| `search` | string | no | 根据`title`和`description`搜索问题 | +| `in` | string | no | 修改`search`属性的范围. `title` , `description`或以逗号将它们连接在一起的字符串. 默认为`title,description` | +| `created_after` | datetime | no | 返回在给定时间或之后创建的问题 | +| `created_before` | datetime | no | 返回在给定时间或之前创建的问题 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的问题 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的问题 | +| `confidential` | boolean | no | 过滤机密或公共问题. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/issues_statistics" +``` + +响应示例: + +``` +{ "statistics": { "counts": { "all": 20, "closed": 5, "opened": 15 } } } +``` + +## Get group issues statistics[](#get-group-issues-statistics "Permalink") + +获取给定组的问题计数统计信息. + +``` +GET /groups/:id/issues_statistics +GET /groups/:id/issues_statistics?labels=foo +GET /groups/:id/issues_statistics?labels=foo,bar +GET /groups/:id/issues_statistics?labels=foo,bar&state=opened +GET /groups/:id/issues_statistics?milestone=1.0.0 +GET /groups/:id/issues_statistics?milestone=1.0.0&state=opened +GET /groups/:id/issues_statistics?iids[]=42&iids[]=43 +GET /groups/:id/issues_statistics?search=issue+title+or+description +GET /groups/:id/issues_statistics?author_id=5 +GET /groups/:id/issues_statistics?assignee_id=5 +GET /groups/:id/issues_statistics?my_reaction_emoji=star +GET /groups/:id/issues_statistics?confidential=true +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `labels` | string | no | 标签名称的逗号分隔列表,必须具有要返回的所有标签的问题. `None`列出所有没有标签的问题. `Any`列出至少带有一个标签的所有问题. | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的问题 | +| `milestone` | string | no | 里程碑标题. `None`列出没有里程碑的所有问题. `Any`列出具有指定里程碑的所有问题. | +| `scope` | string | no | 回到问题在给定范围: `created_by_me` , `assigned_to_me`或`all` . | +| `author_id` | integer | no | 返回由给定用户`id`创建的问题. 与`author_username` . 与`scope=all`或`scope=assigned_to_me`结合使用. | +| `author_username` | string | no | 返回由给定`username`创建的问题. 类似于`author_id`并且与`author_id` . | +| `assignee_id` | integer | no | 返回分配给给定用户`id` . 互斥与`assignee_username` . `None`返回未分配的问题. 受让人有`Any`退货问题. | +| `assignee_username` | 字符串数组 | no | 返回分配给给定`username` . 类似于`assignee_id`并且与`assignee_id`互斥. 在 GitLab CE 中, `assignee_username`数组应仅包含单个值,否则将返回无效的参数错误. | +| `my_reaction_emoji` | string | no | 返回的问题由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. | +| `search` | string | no | 搜索组问题的`title`和`description` | +| `created_after` | datetime | no | 返回在给定时间或之后创建的问题 | +| `created_before` | datetime | no | 返回在给定时间或之前创建的问题 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的问题 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的问题 | +| `confidential` | boolean | no | 过滤机密或公共问题. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4/issues_statistics" +``` + +响应示例: + +``` +{ "statistics": { "counts": { "all": 20, "closed": 5, "opened": 15 } } } +``` + +## Get project issues statistics[](#get-project-issues-statistics "Permalink") + +获取给定项目的问题计数统计信息. + +``` +GET /projects/:id/issues_statistics +GET /projects/:id/issues_statistics?labels=foo +GET /projects/:id/issues_statistics?labels=foo,bar +GET /projects/:id/issues_statistics?labels=foo,bar&state=opened +GET /projects/:id/issues_statistics?milestone=1.0.0 +GET /projects/:id/issues_statistics?milestone=1.0.0&state=opened +GET /projects/:id/issues_statistics?iids[]=42&iids[]=43 +GET /projects/:id/issues_statistics?search=issue+title+or+description +GET /projects/:id/issues_statistics?author_id=5 +GET /projects/:id/issues_statistics?assignee_id=5 +GET /projects/:id/issues_statistics?my_reaction_emoji=star +GET /projects/:id/issues_statistics?confidential=true +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的里程碑 | +| `labels` | string | no | 标签名称的逗号分隔列表,必须具有要返回的所有标签的问题. `None`列出所有没有标签的问题. `Any`列出至少带有一个标签的所有问题. | +| `milestone` | string | no | 里程碑标题. `None`列出没有里程碑的所有问题. `Any`列出具有指定里程碑的所有问题. | +| `scope` | string | no | 回到问题在给定范围: `created_by_me` , `assigned_to_me`或`all` . | +| `author_id` | integer | no | 返回由给定用户`id`创建的问题. 与`author_username` . 与`scope=all`或`scope=assigned_to_me`结合使用. | +| `author_username` | string | no | 返回由给定`username`创建的问题. 类似于`author_id`并且与`author_id` . | +| `assignee_id` | integer | no | 返回分配给给定用户`id` . 互斥与`assignee_username` . `None`返回未分配的问题. 受让人有`Any`退货问题. | +| `assignee_username` | 字符串数组 | no | 返回分配给给定`username` . 类似于`assignee_id`并且与`assignee_id`互斥. 在 GitLab CE 中, `assignee_username`数组应仅包含单个值,否则将返回无效的参数错误. | +| `my_reaction_emoji` | string | no | 返回的问题由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. | +| `search` | string | no | 根据`title`和`description`搜索项目问题 | +| `created_after` | datetime | no | Return issues created on or after the given time | +| `created_before` | datetime | no | 返回在给定时间或之前创建的问题 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的问题 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的问题 | +| `confidential` | boolean | no | 过滤机密或公共问题. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues_statistics" +``` + +响应示例: + +``` +{ "statistics": { "counts": { "all": 20, "closed": 5, "opened": 15 } } } +``` \ No newline at end of file diff --git a/_book/docs/325.md b/_book/docs/325.md new file mode 100644 index 0000000000000000000000000000000000000000..5b3b373215debee4c84d544f65c6264f62d667d8 --- /dev/null +++ b/_book/docs/325.md @@ -0,0 +1,465 @@ +# Jobs API + +> 原文:[https://docs.gitlab.com/ee/api/jobs.html](https://docs.gitlab.com/ee/api/jobs.html) + +* [List project jobs](#list-project-jobs) +* [List pipeline jobs](#list-pipeline-jobs) +* [List pipeline bridges](#list-pipeline-bridges) +* [Get a single job](#get-a-single-job) +* [Get job artifacts](#get-job-artifacts) +* [Download the artifacts archive](#download-the-artifacts-archive) +* [Download a single artifact file by job ID](#download-a-single-artifact-file-by-job-id) +* [Download a single artifact file from specific tag or branch](#download-a-single-artifact-file-from-specific-tag-or-branch) +* [Get a log file](#get-a-log-file) +* [Cancel a job](#cancel-a-job) +* [Retry a job](#retry-a-job) +* [Erase a job](#erase-a-job) +* [Keep artifacts](#keep-artifacts) +* [Delete artifacts](#delete-artifacts) +* [Play a job](#play-a-job) + +# Jobs API[](#jobs-api "Permalink") + +## List project jobs[](#list-project-jobs "Permalink") + +获取项目中的作业列表. 作业按 ID 的降序排列. + +``` +GET /projects/:id/jobs +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `scope` | 字符串**或**字符串数组 | no | 要显示的工作范围. 以下一项或多项: `created` , `pending` , `running` , `failed` , `success` , `canceled` , `skipped`或`manual` . 如果未提供`scope`则返回所有作业. | + +``` +curl --globoff --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs?scope[]=pending&scope[]=running" +``` + +回应范例 + +``` +[ { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2015-12-24T15:51:21.802Z", "started_at": "2015-12-24T17:54:27.722Z", "finished_at": "2015-12-24T17:54:27.895Z", "duration": 0.173, "artifacts_file": { "filename": "artifacts.zip", "size": 1000 }, "artifacts": [ {"file_type": "archive", "size": 1000, "filename": "artifacts.zip", "file_format": "zip"}, {"file_type": "metadata", "size": 186, "filename": "metadata.gz", "file_format": "gzip"}, {"file_type": "trace", "size": 1500, "filename": "job.log", "file_format": "raw"}, {"file_type": "junit", "size": 750, "filename": "junit.xml.gz", "file_format": "gzip"} ], "artifacts_expire_at": "2016-01-23T17:54:27.895Z", "id": 7, "name": "teaspoon", "pipeline": { "id": 6, "ref": "master", "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "status": "pending" }, "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/7", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" } }, { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2015-12-24T15:51:21.727Z", "started_at": "2015-12-24T17:54:24.729Z", "finished_at": "2015-12-24T17:54:24.921Z", "duration": 0.192, "artifacts_expire_at": "2016-01-23T17:54:24.921Z", "id": 6, "name": "rspec:other", "pipeline": { "id": 6, "ref": "master", "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "status": "pending" }, "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/6", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" } } ] +``` + +## List pipeline jobs[](#list-pipeline-jobs "Permalink") + +获取管道的作业列表. + +``` +GET /projects/:id/pipelines/:pipeline_id/jobs +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `pipeline_id` | integer | yes | 管道的 ID. | +| `scope` | 字符串**或**字符串数组 | no | 要显示的工作范围. 以下一项或多项: `created` , `pending` , `running` , `failed` , `success` , `canceled` , `skipped`或`manual` . 如果未提供`scope`则返回所有作业. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/6/jobs?scope[]=pending&scope[]=running" +``` + +回应范例 + +``` +[ { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2015-12-24T15:51:21.727Z", "started_at": "2015-12-24T17:54:24.729Z", "finished_at": "2015-12-24T17:54:24.921Z", "duration": 0.192, "artifacts_expire_at": "2016-01-23T17:54:24.921Z", "id": 6, "name": "rspec:other", "pipeline": { "id": 6, "ref": "master", "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "status": "pending" }, "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/6", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" } }, { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2015-12-24T15:51:21.802Z", "started_at": "2015-12-24T17:54:27.722Z", "finished_at": "2015-12-24T17:54:27.895Z", "duration": 0.173, "artifacts_file": { "filename": "artifacts.zip", "size": 1000 }, "artifacts": [ {"file_type": "archive", "size": 1000, "filename": "artifacts.zip", "file_format": "zip"}, {"file_type": "metadata", "size": 186, "filename": "metadata.gz", "file_format": "gzip"}, {"file_type": "trace", "size": 1500, "filename": "job.log", "file_format": "raw"}, {"file_type": "junit", "size": 750, "filename": "junit.xml.gz", "file_format": "gzip"} ], "artifacts_expire_at": "2016-01-23T17:54:27.895Z", "id": 7, "name": "teaspoon", "pipeline": { "id": 6, "ref": "master", "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "status": "pending" }, "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/7", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" } } ] +``` + +从 GitLab 13.2 开始,此端点[将返回任何管道(](pipelines.html#single-pipeline-requests)包括[子管道)的数据](../ci/parent_child_pipelines.html) . + +## List pipeline bridges[](#list-pipeline-bridges "Permalink") + +获取管道的桥作业列表. + +``` +GET /projects/:id/pipelines/:pipeline_id/bridges +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `pipeline_id` | integer | yes | 管道的 ID. | +| `scope` | 字符串**或**字符串数组 | no | 要显示的工作范围. 以下一项或多项: `created` , `pending` , `running` , `failed` , `success` , `canceled` , `skipped`或`manual` . 如果未提供`scope`则返回所有作业. | + +``` +curl --header "PRIVATE-TOKEN: " 'https://gitlab.example.com/api/v4/projects/1/pipelines/6/bridges?scope[]=pending&scope[]=running' +``` + +回应范例 + +``` +[ { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2015-12-24T15:51:21.802Z", "started_at": "2015-12-24T17:54:27.722Z", "finished_at": "2015-12-24T17:58:27.895Z", "duration": 240, "id": 7, "name": "teaspoon", "pipeline": { "id": 6, "ref": "master", "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "status": "pending", "created_at": "2015-12-24T15:50:16.123Z", "updated_at": "2015-12-24T18:00:44.432Z", "web_url": "https://example.com/foo/bar/pipelines/6" }, "ref": "master", "stage": "test", "status": "pending", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/7", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" }, "downstream_pipeline": { "id": 5, "sha": "f62a4b2fb89754372a346f24659212eb8da13601", "ref": "master", "status": "pending", "created_at": "2015-12-24T17:54:27.722Z", "updated_at": "2015-12-24T17:58:27.896Z", "web_url": "https://example.com/diaspora/diaspora-client/pipelines/5" } } ] +``` + +## Get a single job[](#get-a-single-job "Permalink") + +获得项目的一份工作 + +``` +GET /projects/:id/jobs/:job_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/8" +``` + +回应范例 + +``` +{ "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2015-12-24T15:51:21.880Z", "started_at": "2015-12-24T17:54:30.733Z", "finished_at": "2015-12-24T17:54:31.198Z", "duration": 0.465, "artifacts_expire_at": "2016-01-23T17:54:31.198Z", "id": 8, "name": "rubocop", "pipeline": { "id": 6, "ref": "master", "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "status": "pending" }, "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/8", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" } } +``` + +## Get job artifacts[](#get-job-artifacts "Permalink") + +版本历史 + +**注意事项** : + +* 在 GitLab 8.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2893) . +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 9.5 中[引入了](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2346)在工件下载 API 中使用`CI_JOB_TOKEN` . + +获取项目的工件压缩文件存档. + +``` +GET /projects/:id/jobs/:job_id/artifacts +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | +| `job_token` | string | no | 与多项目管道的[触发器](../ci/triggers/README.html#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium)一起使用. 它只能在`.gitlab-ci.yml`内部调用. 其值始终`$CI_JOB_TOKEN` . | + +使用`PRIVATE-TOKEN`标头的示例请求: + +``` +curl --output artifacts.zip --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts" +``` + +要在`.gitlab-ci.yml`中的[`script`定义中](../ci/yaml/README.html#script)使用它 ,您可以使用以下任一方法: + +* GitLab 提供的`CI_JOB_TOKEN`变量的`JOB-TOKEN`标头. 例如,以下作业将下载 ID 为`42`的作业工件. 注意,该命令被缠绕成单引号,因为它含有一个冒号( `:` ): + + ``` + artifact_download: + stage: test + script: + - 'curl --location --output artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts"' + ``` + +* 或带有 GitLab 提供的`CI_JOB_TOKEN`变量的`job_token`属性. 例如,以下作业将下载 ID 为`42`的作业的工件: + + ``` + artifact_download: + stage: test + script: + - 'curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts?job_token=$CI_JOB_TOKEN"' + ``` + +可能的响应状态代码: + +| Status | Description | +| --- | --- | +| 200 | Serves the artifacts file. | +| 404 | 找不到构建或没有工件. | + +## Download the artifacts archive[](#download-the-artifacts-archive "Permalink") + +版本历史 + +**注意事项** : + +* 在 GitLab 8.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5347) . +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 9.5 中[引入了](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2346)在工件下载 API 中使用`CI_JOB_TOKEN` . + +如果作业成功完成,请从最新成功的管道中下载给定参考名称和作业的工件压缩存档. 这与[获取作业的工件相同](#get-job-artifacts) ,但是通过定义作业的名称而不是其 ID. + +``` +GET /projects/:id/jobs/artifacts/:ref_name/download?job=name +``` + +Parameters + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `ref_name` | string | yes | 存储库中的分支或标记名称. 不支持 HEAD 或 SHA 引用. | +| `job` | string | yes | 工作名称. | +| `job_token` | string | no | 与多项目管道的[触发器](../ci/triggers/README.html#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium)一起使用. 它只能在`.gitlab-ci.yml`内部调用. 其值始终`$CI_JOB_TOKEN` . | + +使用`PRIVATE-TOKEN`标头的示例请求: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test" +``` + +要在`.gitlab-ci.yml`中的[`script`定义中](../ci/yaml/README.html#script)使用它 ,您可以使用以下任一方法: + +* GitLab 提供的`CI_JOB_TOKEN`变量的`JOB-TOKEN`标头. 例如,以下作业将下载`master`分支的`test`作业的工件. 注意,该命令被缠绕成单引号,因为它含有一个冒号( `:` ): + + ``` + artifact_download: + stage: test + script: + - 'curl --location --output artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/master/download?job=test"' + ``` + +* 或带有 GitLab 提供的`CI_JOB_TOKEN`变量的`job_token`属性. 例如,以下作业将下载`master`分支的`test`作业的工件: + + ``` + artifact_download: + stage: test + script: + - 'curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/master/download?job=test&job_token=$CI_JOB_TOKEN"' + ``` + +可能的响应状态代码: + +| Status | Description | +| --- | --- | +| 200 | 服务工件文件. | +| 404 | 找不到构建或没有工件. | + +## Download a single artifact file by job ID[](#download-a-single-artifact-file-by-job-id "Permalink") + +在 GitLab 10.0 中引入 + +从作业的工件压缩文件中以指定的 ID 下载作业中的单个工件文件. 从存档中提取文件,并将其流式传输到客户端. + +``` +GET /projects/:id/jobs/:job_id/artifacts/*artifact_path +``` + +Parameters + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 唯一的作业标识符. | +| `artifact_path` | string | yes | 工件存档内文件的路径. | + +请求示例: + +``` +curl --location --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/5/artifacts/some/release/file.pdf" +``` + +可能的响应状态代码: + +| Status | Description | +| --- | --- | +| 200 | 发送单个工件文件 | +| 400 | 提供的路径无效 | +| 404 | 找不到版本或没有文件/工件 | + +## Download a single artifact file from specific tag or branch[](#download-a-single-artifact-file-from-specific-tag-or-branch "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23538) . + +从作业的工件存档中为给定的参考名称下载最新成功管道的特定作业的单个工件文件. 从存档中提取文件,并将其流式传输到客户端. + +``` +GET /projects/:id/jobs/artifacts/:ref_name/raw/*artifact_path?job=name +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `ref_name` | string | yes | 存储库中的分支或标记名称. 不支持 HEAD 或 SHA 引用. | +| `artifact_path` | string | yes | 工件存档内文件的路径. | +| `job` | string | yes | 工作名称. | + +请求示例: + +``` +curl --location --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/raw/some/release/file.pdf?job=pdf" +``` + +可能的响应状态代码: + +| Status | Description | +| --- | --- | +| 200 | 发送单个工件文件 | +| 400 | 提供的路径无效 | +| 404 | 找不到版本或没有文件/工件 | + +## Get a log file[](#get-a-log-file "Permalink") + +获取项目的特定作业的日志(跟踪): + +``` +GET /projects/:id/jobs/:job_id/trace +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +``` +curl --location --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/8/trace" +``` + +可能的响应状态代码: + +| Status | Description | +| --- | --- | +| 200 | 服务日志文件 | +| 404 | 找不到作业或没有日志文件 | + +## Cancel a job[](#cancel-a-job "Permalink") + +取消项目的一项工作 + +``` +POST /projects/:id/jobs/:job_id/cancel +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/cancel" +``` + +回应范例 + +``` +{ "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2016-01-11T10:13:33.506Z", "started_at": "2016-01-11T10:14:09.526Z", "finished_at": null, "duration": 8, "id": 42, "name": "rubocop", "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "canceled", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/42", "user": null } +``` + +## Retry a job[](#retry-a-job "Permalink") + +重试项目的一项工作 + +``` +POST /projects/:id/jobs/:job_id/retry +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/retry" +``` + +回应范例 + +``` +{ "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2016-01-11T10:13:33.506Z", "started_at": null, "finished_at": null, "duration": null, "id": 42, "name": "rubocop", "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "pending", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/42", "user": null } +``` + +## Erase a job[](#erase-a-job "Permalink") + +擦除项目的单个作业(删除作业工件和作业日志) + +``` +POST /projects/:id/jobs/:job_id/erase +``` + +Parameters + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +Example of request + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/erase" +``` + +回应范例 + +``` +{ "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "download_url": null, "id": 42, "name": "rubocop", "ref": "master", "artifacts": [], "runner": null, "stage": "test", "created_at": "2016-01-11T10:13:33.506Z", "started_at": "2016-01-11T10:13:33.506Z", "finished_at": "2016-01-11T10:15:10.506Z", "duration": 97.0, "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/42", "user": null } +``` + +## Keep artifacts[](#keep-artifacts "Permalink") + +设置过期时,防止删除工件. + +``` +POST /projects/:id/jobs/:job_id/artifacts/keep +``` + +Parameters + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts/keep" +``` + +响应示例: + +``` +{ "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "download_url": null, "id": 42, "name": "rubocop", "ref": "master", "artifacts": [], "runner": null, "stage": "test", "created_at": "2016-01-11T10:13:33.506Z", "started_at": "2016-01-11T10:13:33.506Z", "finished_at": "2016-01-11T10:15:10.506Z", "duration": 97.0, "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/42", "user": null } +``` + +## Delete artifacts[](#delete-artifacts "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25522) . + +删除作业的工件. + +``` +DELETE /projects/:id/jobs/:job_id/artifacts +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `job_id` | integer | yes | 工作 ID. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts" +``` + +**注意:**至少需要具有维护者角色才能删除工件. + +如果工件被成功删除,则返回状态为`204 No Content`的响应. + +## Play a job[](#play-a-job "Permalink") + +触发手动操作以开始作业. + +``` +POST /projects/:id/jobs/:job_id/play +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/play" +``` + +回应范例 + +``` +{ "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2016-01-11T10:13:33.506Z", "started_at": null, "finished_at": null, "duration": null, "id": 42, "name": "rubocop", "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "started", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/42", "user": null } +``` \ No newline at end of file diff --git a/_book/docs/326.md b/_book/docs/326.md new file mode 100644 index 0000000000000000000000000000000000000000..b10f6cb7872880d5c022c23aa671dc2727657374 --- /dev/null +++ b/_book/docs/326.md @@ -0,0 +1,81 @@ +# Keys API + +> 原文:[https://docs.gitlab.com/ee/api/keys.html](https://docs.gitlab.com/ee/api/keys.html) + +* [Get SSH key with user by ID of an SSH key](#get-ssh-key-with-user-by-id-of-an-ssh-key) +* [Get user by fingerprint of SSH key](#get-user-by-fingerprint-of-ssh-key) +* [Get user by deploy key fingerprint](#get-user-by-deploy-key-fingerprint) + +# Keys API[](#keys-api "Permalink") + +## Get SSH key with user by ID of an SSH key[](#get-ssh-key-with-user-by-id-of-an-ssh-key "Permalink") + +通过 SSH 密钥的 ID 获取具有用户的 SSH 密钥. 请注意,只有管理员才能通过 SSH 密钥 ID 用用户查找 SSH 密钥. + +``` +GET /keys/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | SSH 密钥的 ID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/keys/1" +``` + +``` +{ "id": 1, "title": "Sample key 25", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt1256k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2015-09-03T07:24:44.627Z", "expires_at": "2020-05-05T00:00:00.000Z" "user": { "name": "John Smith", "username": "john_smith", "id": 25, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/cfa35b8cd2ec278026357769582fa563?s=40\u0026d=identicon", "web_url": "http://localhost:3000/john_smith", "created_at": "2015-09-03T07:24:01.670Z", "bio": null, "location": null, "public_email": "john@example.com", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": null, "last_sign_in_at": "2015-09-03T07:24:01.670Z", "confirmed_at": "2015-09-03T07:24:01.670Z", "last_activity_on": "2015-09-03", "email": "john@example.com", "theme_id": 2, "color_scheme_id": 1, "projects_limit": 10, "current_sign_in_at": null, "identities": [], "can_create_group": true, "can_create_project": true, "two_factor_enabled": false "external": false, "private_profile": null } } +``` + +## Get user by fingerprint of SSH key[](#get-user-by-fingerprint-of-ssh-key "Permalink") + +您可以搜索拥有特定 SSH 密钥的用户. 请注意,只有管理员才能使用 SSH 密钥的指纹查找 SSH 密钥. + +``` +GET /keys +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `fingerprint` | string | yes | SSH 密钥的指纹 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/keys?fingerprint=ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1" +``` + +如果使用 sha256 指纹 API 调用,请确保指纹经过 URL 编码. + +例如, `/`由`/`表示,而`:`由`:`表示: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/keys?fingerprint=SHA256%3AnUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo%2FlCg" +``` + +响应示例: + +``` +{ "id": 1, "title": "Sample key 1", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt1016k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2019-11-14T15:11:13.222Z", "expires_at": "2020-05-05T00:00:00.000Z" "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://0.0.0.0:3000/root", "created_at": "2019-11-14T15:09:34.831Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": null, "last_sign_in_at": "2019-11-16T22:41:26.663Z", "confirmed_at": "2019-11-14T15:09:34.575Z", "last_activity_on": "2019-11-20", "email": "admin@example.com", "theme_id": 1, "color_scheme_id": 1, "projects_limit": 100000, "current_sign_in_at": "2019-11-19T14:42:18.078Z", "identities": [ ], "can_create_group": true, "can_create_project": true, "two_factor_enabled": false, "external": false, "private_profile": false, "shared_runners_minutes_limit": null, "extra_shared_runners_minutes_limit": null } } +``` + +## Get user by deploy key fingerprint[](#get-user-by-deploy-key-fingerprint "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/119209) . + +部署密钥绑定到创建用户,因此,如果使用部署密钥指纹进行查询,则将获得有关使用该密钥的项目的其他信息. + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/keys?fingerprint=SHA256%3AnUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo%2FlCg" +``` + +响应示例: + +``` +{ "id": 1, "title": "Sample key 1", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt1016k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2019-11-14T15:11:13.222Z", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://0.0.0.0:3000/root", "created_at": "2019-11-14T15:09:34.831Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": null, "last_sign_in_at": "2019-11-16T22:41:26.663Z", "confirmed_at": "2019-11-14T15:09:34.575Z", "last_activity_on": "2019-11-20", "email": "admin@example.com", "theme_id": 1, "color_scheme_id": 1, "projects_limit": 100000, "current_sign_in_at": "2019-11-19T14:42:18.078Z", "identities": [ ], "can_create_group": true, "can_create_project": true, "two_factor_enabled": false, "external": false, "private_profile": false, "shared_runners_minutes_limit": null, "extra_shared_runners_minutes_limit": null }, "deploy_keys_projects": [ { "id": 1, "deploy_key_id": 1, "project_id": 1, "created_at": "2020-01-09T07:32:52.453Z", "updated_at": "2020-01-09T07:32:52.453Z", "can_push": false } ] } +``` \ No newline at end of file diff --git a/_book/docs/327.md b/_book/docs/327.md new file mode 100644 index 0000000000000000000000000000000000000000..dd535dcfffabe4f0fd6abfc677a0649b23702b5b --- /dev/null +++ b/_book/docs/327.md @@ -0,0 +1,207 @@ +# Labels API + +> 原文:[https://docs.gitlab.com/ee/api/labels.html](https://docs.gitlab.com/ee/api/labels.html) + +* [List labels](#list-labels) +* [Get a single project label](#get-a-single-project-label) +* [Create a new label](#create-a-new-label) +* [Delete a label](#delete-a-label) +* [Edit an existing label](#edit-an-existing-label) +* [Promote a project label to a group label](#promote-a-project-label-to-a-group-label) +* [Subscribe to a label](#subscribe-to-a-label) +* [Unsubscribe from a label](#unsubscribe-from-a-label) + +# Labels API[](#labels-api "Permalink") + +**注意:** `description_html`已添加到[GitLab 12.7 中的](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)响应 JSON. + +## List labels[](#list-labels "Permalink") + +获取给定项目的所有标签. + +默认情况下,此请求一次返回 20 个结果,因为 API 结果[是分页的](README.html#pagination) . + +``` +GET /projects/:id/labels +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `with_counts` | boolean | no | 是否包括发布和合并请求计数. 默认为`false` . *( [在 GitLab 12.2 中引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31543) )* | +| `include_ancestor_groups` | boolean | no | 包括祖先组. 默认为`true` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/labels?with_counts=true" +``` + +响应示例: + +``` +[ { "id" : 1, "name" : "bug", "color" : "#d9534f", "text_color" : "#FFFFFF", "description": "Bug reported by user", "description_html": "Bug reported by user", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 1, "subscribed": false, "priority": 10, "is_project_label": true }, { "id" : 4, "color" : "#d9534f", "text_color" : "#FFFFFF", "name" : "confirmed", "description": "Confirmed issue", "description_html": "Confirmed issue", "open_issues_count": 2, "closed_issues_count": 5, "open_merge_requests_count": 0, "subscribed": false, "priority": null, "is_project_label": true }, { "id" : 7, "name" : "critical", "color" : "#d9534f", "text_color" : "#FFFFFF", "description": "Critical issue. Need fix ASAP", "description_html": "Critical issue. Need fix ASAP", "open_issues_count": 1, "closed_issues_count": 3, "open_merge_requests_count": 1, "subscribed": false, "priority": null, "is_project_label": true }, { "id" : 8, "name" : "documentation", "color" : "#f0ad4e", "text_color" : "#FFFFFF", "description": "Issue about documentation", "description_html": "Issue about documentation", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 2, "subscribed": false, "priority": null, "is_project_label": false }, { "id" : 9, "color" : "#5cb85c", "text_color" : "#FFFFFF", "name" : "enhancement", "description": "Enhancement proposal", "description_html": "Enhancement proposal", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 1, "subscribed": true, "priority": null, "is_project_label": true } ] +``` + +## Get a single project label[](#get-a-single-project-label "Permalink") + +获取给定项目的单个标签. + +``` +GET /projects/:id/labels/:label_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 项目标签的 ID 或标题. | +| `include_ancestor_groups` | boolean | no | 包括祖先组. 默认为`true` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/labels/bug" +``` + +响应示例: + +``` +{ "id" : 1, "name" : "bug", "color" : "#d9534f", "text_color" : "#FFFFFF", "description": "Bug reported by user", "description_html": "Bug reported by user", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 1, "subscribed": false, "priority": 10, "is_project_label": true } +``` + +## Create a new label[](#create-a-new-label "Permalink") + +使用给定的名称和颜色为给定的存储库创建一个新标签. + +``` +POST /projects/:id/labels +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 标签名称 | +| `color` | string | yes | 标签的颜色以 6 位十六进制表示法加上前导"#"符号(例如#FFAABB)或[CSS 颜色名称之一给出](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/CSS/color_value) | +| `description` | string | no | 标签说明 | +| `priority` | integer | no | 标签的优先级. 必须大于或等于零或为`null`才能删除优先级. | + +``` +curl --data "name=feature&color=#5843AD" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/labels" +``` + +响应示例: + +``` +{ "id" : 10, "name" : "feature", "color" : "#5843AD", "text_color" : "#FFFFFF", "description":null, "description_html":null, "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false, "priority": null, "is_project_label": true } +``` + +## Delete a label[](#delete-a-label "Permalink") + +删除具有给定名称的标签. + +``` +DELETE /projects/:id/labels/:label_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/labels/bug" +``` + +**注意:**参数中带有`name`的较旧的端点`DELETE /projects/:id/labels`仍然可用,但已弃用. + +## Edit an existing label[](#edit-an-existing-label "Permalink") + +用新名称或新颜色更新现有标签. 至少需要一个参数来更新标签. + +``` +PUT /projects/:id/labels/:label_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | +| `new_name` | string | 是,如果未提供`color` | 标签的新名称 | +| `color` | string | 是,如果未提供`new_name` | 标签的颜色以 6 位十六进制表示法加上前导"#"符号(例如#FFAABB)或[CSS 颜色名称之一给出](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/CSS/color_value) | +| `description` | string | no | 标签的新说明 | +| `priority` | integer | no | 标签的新优先级. 必须大于或等于零或为`null`才能删除优先级. | + +``` +curl --request PUT --data "new_name=docs&color=#8E44AD&description=Documentation" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/labels/documentation" +``` + +响应示例: + +``` +{ "id" : 8, "name" : "docs", "color" : "#8E44AD", "text_color" : "#FFFFFF", "description": "Documentation", "description_html": "Documentation", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 2, "subscribed": false, "priority": null, "is_project_label": true } +``` + +**注意:**参数中带有`name`或`label_id`的较早的端点`PUT /projects/:id/labels`仍然可用,但已弃用. + +## Promote a project label to a group label[](#promote-a-project-label-to-a-group-label "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25218) . + +将项目标签提升为组标签. + +``` +PUT /projects/:id/labels/:label_id/promote +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/labels/documentation/promote" +``` + +响应示例: + +``` +{ "id" : 8, "name" : "documentation", "color" : "#8E44AD", "description": "Documentation", "description_html": "Documentation", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 2, "subscribed": false } +``` + +**注意:**在参数中带有`name`的较早的端点`PUT /projects/:id/labels/promote`仍然可用,但已弃用. + +## Subscribe to a label[](#subscribe-to-a-label "Permalink") + +将经过身份验证的用户订阅标签以接收通知. 如果用户已经订阅了标签,则返回状态码`304` . + +``` +POST /projects/:id/labels/:label_id/subscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 项目标签的 ID 或标题 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/labels/1/subscribe" +``` + +响应示例: + +``` +{ "id" : 1, "name" : "bug", "color" : "#d9534f", "text_color" : "#FFFFFF", "description": "Bug reported by user", "description_html": "Bug reported by user", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 1, "subscribed": true, "priority": null, "is_project_label": true } +``` + +## Unsubscribe from a label[](#unsubscribe-from-a-label "Permalink") + +Unsubscribes the authenticated user from a label to not receive notifications from it. If the user is not subscribed to the label, the status code `304` is returned. + +``` +POST /projects/:id/labels/:label_id/unsubscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 项目标签的 ID 或标题 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/labels/1/unsubscribe" +``` \ No newline at end of file diff --git a/_book/docs/328.md b/_book/docs/328.md new file mode 100644 index 0000000000000000000000000000000000000000..a562127baa4304d43d52581cf0e33f96d0846d3e --- /dev/null +++ b/_book/docs/328.md @@ -0,0 +1,185 @@ +# Group Labels API + +> 原文:[https://docs.gitlab.com/ee/api/group_labels.html](https://docs.gitlab.com/ee/api/group_labels.html) + +* [List group labels](#list-group-labels) +* [Get a single group label](#get-a-single-group-label) +* [Create a new group label](#create-a-new-group-label) +* [Update a group label](#update-a-group-label) +* [Delete a group label](#delete-a-group-label) +* [Subscribe to a group label](#subscribe-to-a-group-label) +* [Unsubscribe from a group label](#unsubscribe-from-a-group-label) + +# Group Labels API[](#group-labels-api "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21368) . + +该 API 支持[组标签的](../user/project/labels.html#project-labels-and-group-labels)管理. 它允许列出,创建,更新和删除组标签. 此外,用户可以订阅和取消订阅组标签. + +**注意:** `description_html`已添加到[GitLab 12.7 中的](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)响应 JSON. + +## List group labels[](#list-group-labels "Permalink") + +获取给定组的所有标签. + +``` +GET /groups/:id/labels +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `with_counts` | boolean | no | 是否包括发布和合并请求计数. 默认为`false` . *( [在 GitLab 12.2 中引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31543) )* | +| `include_ancestor_groups` | boolean | no | 包括祖先组. 默认为`true` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/labels?with_counts=true" +``` + +响应示例: + +``` +[ { "id": 7, "name": "bug", "color": "#FF0000", "text_color" : "#FFFFFF", "description": null, "description_html": null, "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false }, { "id": 4, "name": "feature", "color": "#228B22", "text_color" : "#FFFFFF", "description": null, "description_html": null, "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false } ] +``` + +## Get a single group label[](#get-a-single-group-label "Permalink") + +获取给定组的单个标签. + +``` +GET /groups/:id/labels/:label_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | +| `include_ancestor_groups` | boolean | no | 包括祖先组. 默认为`true` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/labels/bug" +``` + +Example response: + +``` +{ "id": 7, "name": "bug", "color": "#FF0000", "text_color" : "#FFFFFF", "description": null, "description_html": null, "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false } +``` + +## Create a new group label[](#create-a-new-group-label "Permalink") + +为给定的组创建一个新的组标签. + +``` +POST /groups/:id/labels +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 标签名称 | +| `color` | string | yes | 标签的颜色以 6 位十六进制表示法加上前导"#"符号(例如#FFAABB)或[CSS 颜色名称之一给出](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/CSS/color_value) | +| `description` | string | no | 标签的说明, | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" --data '{"name": "Feature Proposal", "color": "#FFA500", "description": "Describes new ideas" }' "https://gitlab.example.com/api/v4/groups/5/labels" +``` + +响应示例: + +``` +{ "id": 9, "name": "Feature Proposal", "color": "#FFA500", "text_color" : "#FFFFFF", "description": "Describes new ideas", "description_html": "Describes new ideas", "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false } +``` + +## Update a group label[](#update-a-group-label "Permalink") + +更新现有的组标签. 至少需要一个参数来更新组标签. + +``` +PUT /groups/:id/labels/:label_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | +| `new_name` | string | no | 标签的新名称 | +| `color` | string | no | 标签的颜色以 6 位十六进制表示法加上前导"#"符号(例如#FFAABB)或[CSS 颜色名称之一给出](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/CSS/color_value) | +| `description` | string | no | 标签的描述. | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" --data '{"new_name": "Feature Idea" }' "https://gitlab.example.com/api/v4/groups/5/labels/Feature%20Proposal" +``` + +响应示例: + +``` +{ "id": 9, "name": "Feature Idea", "color": "#FFA500", "text_color" : "#FFFFFF", "description": "Describes new ideas", "description_html": "Describes new ideas", "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false } +``` + +**注意:**参数中带有`name`的较早的端点`PUT /groups/:id/labels`仍然可用,但已弃用. + +## Delete a group label[](#delete-a-group-label "Permalink") + +删除具有给定名称的组标签. + +``` +DELETE /groups/:id/labels/:label_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/labels/bug" +``` + +**注意:**参数中带有`name`的较旧的端点`DELETE /groups/:id/labels`仍然可用,但已弃用. + +## Subscribe to a group label[](#subscribe-to-a-group-label "Permalink") + +将经过身份验证的用户订阅到组标签以接收通知. 如果用户已经订阅了标签,则返回状态码`304` . + +``` +POST /groups/:id/labels/:label_id/subscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/labels/9/subscribe" +``` + +响应示例: + +``` +{ "id": 9, "name": "Feature Idea", "color": "#FFA500", "text_color" : "#FFFFFF", "description": "Describes new ideas", "description_html": "Describes new ideas", "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": true } +``` + +## Unsubscribe from a group label[](#unsubscribe-from-a-group-label "Permalink") + +从组标签退订已认证的用户以不接收来自该组标签的通知. 如果用户未订阅标签,则返回状态码`304` . + +``` +POST /groups/:id/labels/:label_id/unsubscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/labels/9/unsubscribe" +``` + +响应示例: + +``` +{ "id": 9, "name": "Feature Idea", "color": "#FFA500", "text_color" : "#FFFFFF", "description": "Describes new ideas", "description_html": "Describes new ideas", "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false } +``` \ No newline at end of file diff --git a/_book/docs/329.md b/_book/docs/329.md new file mode 100644 index 0000000000000000000000000000000000000000..3985c678d52e476fca0b323591a105655a1da00c --- /dev/null +++ b/_book/docs/329.md @@ -0,0 +1,93 @@ +# License + +> 原文:[https://docs.gitlab.com/ee/api/license.html](https://docs.gitlab.com/ee/api/license.html) + +* [Retrieve information about the current license](#retrieve-information-about-the-current-license) +* [Retrieve information about all licenses](#retrieve-information-about-all-licenses) +* [Add a new license](#add-a-new-license) +* [Delete a license](#delete-a-license) + +# License[](#license-core-only "Permalink") + +为了与许可证端点进行交互,您需要以管理员身份进行身份验证. + +## Retrieve information about the current license[](#retrieve-information-about-the-current-license "Permalink") + +``` +GET /license +``` + +``` +{ "id": 2, "plan": "gold", "created_at": "2018-02-27T23:21:58.674Z", "starts_at": "2018-01-27", "expires_at": "2022-01-27", "historical_max": 300, "maximum_user_count": 300, "expired": false, "overage": 200, "user_limit": 100, "active_users": 300, "licensee": { "Name": "John Doe1" }, "add_ons": { "GitLab_FileLocks": 1, "GitLab_Auditor_User": 1 } } +``` + +## Retrieve information about all licenses[](#retrieve-information-about-all-licenses "Permalink") + +``` +GET /licenses +``` + +``` +[ { "id": 1, "plan": "silver", "created_at": "2018-02-27T23:21:58.674Z", "starts_at": "2018-01-27", "expires_at": "2022-01-27", "historical_max": 300, "maximum_user_count": 300, "expired": false, "overage": 200, "user_limit": 100, "licensee": { "Name": "John Doe1" }, "add_ons": { "GitLab_FileLocks": 1, "GitLab_Auditor_User": 1 } }, { "id": 2, "plan": "gold", "created_at": "2018-02-27T23:21:58.674Z", "starts_at": "2018-01-27", "expires_at": "2022-01-27", "historical_max": 300, "maximum_user_count": 300, "expired": false, "overage": 200, "user_limit": 100, "licensee": { "Name": "Doe John" }, "add_ons": { "GitLab_FileLocks": 1, } } ] +``` + +超出数是活动用户数与许可用户数之差. 根据许可证是否已过期,计算方法会有所不同. + +* 如果许可证已过期,则使用历史最大活动用户数( `historical_max` ). +* 如果许可证尚未过期,则使用当前活动用户数. + +Returns: + +* `200 OK` ,响应包含 JSON 格式的许可证. 如果没有许可证,这将是一个空的 JSON 数组. +* `403 Forbidden`如果当前用户不允许阅读许可证, `403 Forbidden` . + +## Add a new license[](#add-a-new-license "Permalink") + +``` +POST /license +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `license` | string | yes | 许可证字符串 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/license?license=eyJkYXRhIjoiMHM5Q...S01Udz09XG4ifQ==" +``` + +响应示例: + +``` +{ "id": 1, "plan": "gold", "created_at": "2018-02-27T23:21:58.674Z", "starts_at": "2018-01-27", "expires_at": "2022-01-27", "historical_max": 300, "maximum_user_count": 300, "expired": false, "overage": 200, "user_limit": 100, "active_users": 300, "licensee": { "Name": "John Doe1" }, "add_ons": { "GitLab_FileLocks": 1, "GitLab_Auditor_User": 1 } } +``` + +Returns: + +* `201 Created`如果成功添加许可证,则`201 Created` . +* `400 Bad Request`如果无法添加许可证),并附有一条错误消息,说明原因. + +## Delete a license[](#delete-a-license "Permalink") + +``` +DELETE /license/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | GitLab 许可证的 ID. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/license/:id" +``` + +响应示例: + +``` +{ "id": 2, "plan": "gold", "created_at": "2018-02-27T23:21:58.674Z", "starts_at": "2018-01-27", "expires_at": "2022-01-27", "historical_max": 300, "maximum_user_count": 300, "expired": false, "overage": 200, "user_limit": 100, "licensee": { "Name": "John Doe" }, "add_ons": { "GitLab_FileLocks": 1, "GitLab_Auditor_User": 1 } } +``` + +Returns: + +* `204 No Content`如果成功删除了许可证,则`204 No Content` . +* `403 Forbidden`如果当前用户不允许删除许可证,则禁止. +* 如果`404 Not Found`删除许可证,则`404 Not Found` . \ No newline at end of file diff --git a/_book/docs/330.md b/_book/docs/330.md new file mode 100644 index 0000000000000000000000000000000000000000..466b1255b82f4d05849552c176fbc6f9359422f2 --- /dev/null +++ b/_book/docs/330.md @@ -0,0 +1,58 @@ +# Licenses API + +> 原文:[https://docs.gitlab.com/ee/api/templates/licenses.html](https://docs.gitlab.com/ee/api/templates/licenses.html) + +* [List license templates](#list-license-templates) +* [Single license template](#single-license-template) + +# Licenses API[](#licenses-api "Permalink") + +在 GitLab 中,有一个 API 端点可用于处理各种开源许可证模板. 有关各种许可条款的更多信息,请访问[此站点](https://choosealicense.com/)或在线提供的许多其他资源. + +## List license templates[](#list-license-templates "Permalink") + +获取所有许可证模板. + +``` +GET /templates/licenses +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `popular` | boolean | no | 如果通过,则仅返回常用许​​可证 | + +``` +curl https://gitlab.example.com/api/v4/templates/licenses?popular=1 +``` + +响应示例: + +``` +[ { "key": "apache-2.0", "name": "Apache License 2.0", "nickname": null, "featured": true, "html_url": "http://choosealicense.com/licenses/apache-2.0/", "source_url": "http://www.apache.org/licenses/LICENSE-2.0.html", "description": "A permissive license that also provides an express grant of patent rights from contributors to users.", "conditions": [ "include-copyright", "document-changes" ], "permissions": [ "commercial-use", "modifications", "distribution", "patent-use", "private-use" ], "limitations": [ "trademark-use", "no-liability" ], "content": " Apache License\n Version 2.0, January 2004\n [...]" }, { "key": "gpl-3.0", "name": "GNU General Public License v3.0", "nickname": "GNU GPLv3", "featured": true, "html_url": "http://choosealicense.com/licenses/gpl-3.0/", "source_url": "http://www.gnu.org/licenses/gpl-3.0.txt", "description": "The GNU GPL is the most widely used free software license and has a strong copyleft requirement. When distributing derived works, the source code of the work must be made available under the same license.", "conditions": [ "include-copyright", "document-changes", "disclose-source", "same-license" ], "permissions": [ "commercial-use", "modifications", "distribution", "patent-use", "private-use" ], "limitations": [ "no-liability" ], "content": " GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n [...]" }, { "key": "mit", "name": "MIT License", "nickname": null, "featured": true, "html_url": "http://choosealicense.com/licenses/mit/", "source_url": "http://opensource.org/licenses/MIT", "description": "A permissive license that is short and to the point. It lets people do anything with your code with proper attribution and without warranty.", "conditions": [ "include-copyright" ], "permissions": [ "commercial-use", "modifications", "distribution", "private-use" ], "limitations": [ "no-liability" ], "content": "The MIT License (MIT)\n\nCopyright (c) [year] [fullname]\n [...]" } ] +``` + +## Single license template[](#single-license-template "Permalink") + +获取单个许可证模板. 您可以传递参数来替换许可证占位符. + +``` +GET /templates/licenses/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `key` | string | yes | 许可证模板的密钥 | +| `project` | string | no | 受版权保护的项目名称 | +| `fullname` | string | no | 著作权人的全名 | + +> **注意:**如果省略`fullname`参数但对请求进行身份验证,则将使用经过身份验证的用户名来替换版权所有者占位符. + +``` +curl --header "PRIVATE-TOKEN: " https://gitlab.example.com/api/v4/templates/licenses/mit?project=My+Cool+Project +``` + +响应示例: + +``` +{ "key": "mit", "name": "MIT License", "nickname": null, "featured": true, "html_url": "http://choosealicense.com/licenses/mit/", "source_url": "http://opensource.org/licenses/MIT", "description": "A permissive license that is short and to the point. It lets people do anything with your code with proper attribution and without warranty.", "conditions": [ "include-copyright" ], "permissions": [ "commercial-use", "modifications", "distribution", "private-use" ], "limitations": [ "no-liability" ], "content": "The MIT License (MIT)\n\nCopyright (c) 2016 John Doe\n [...]" } +``` \ No newline at end of file diff --git a/_book/docs/331.md b/_book/docs/331.md new file mode 100644 index 0000000000000000000000000000000000000000..d719cd58865b6641495f02ed96fa2617720b23a8 --- /dev/null +++ b/_book/docs/331.md @@ -0,0 +1,73 @@ +# Issue links API + +> 原文:[https://docs.gitlab.com/ee/api/issue_links.html](https://docs.gitlab.com/ee/api/issue_links.html) + +* [List issue relations](#list-issue-relations) +* [Create an issue link](#create-an-issue-link) +* [Delete an issue link](#delete-an-issue-link) + +# Issue links API[](#issue-links-api-starter "Permalink") + +## List issue relations[](#list-issue-relations "Permalink") + +获取给定问题的相关问题列表,按关系创建日期时间(升序)排序. 问题将根据用户授权进行过滤. + +``` +GET /projects/:id/issues/:issue_iid/links +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +[ { "id" : 84, "iid" : 14, "issue_link_id": 1 "project_id" : 4, "created_at" : "2016-01-07T12:44:33.959Z", "title" : "Issues with auth", "state" : "opened", "assignees" : [], "assignee" : null, "labels" : [ "bug" ], "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": null, "web_url": "http://example.com/example/example/issues/14", "confidential": false, "weight": null, "link_type": "relates_to" } ] +``` + +## Create an issue link[](#create-an-issue-link "Permalink") + +在两个问题之间创建双向关系. 必须允许用户更新两个问题才能成功. + +``` +POST /projects/:id/issues/:issue_iid/links +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `target_project_id` | integer/string | yes | 目标项目[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `target_issue_iid` | integer/string | yes | 目标项目的内部 ID | +| `link_type` | string | no | 关系的类型(" relates_to"," blocks"," is_blocked_by")默认为" relates_to". | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues/1/links?target_project_id=5&target_issue_iid=1" +``` + +响应示例: + +``` +{ "source_issue" : { "id" : 83, "iid" : 11, "project_id" : 4, "created_at" : "2016-01-07T12:44:33.959Z", "title" : "Issues with auth", "state" : "opened", "assignees" : [], "assignee" : null, "labels" : [ "bug" ], "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": null, "web_url": "http://example.com/example/example/issues/11", "confidential": false, "weight": null, }, "target_issue" : { "id" : 84, "iid" : 14, "project_id" : 4, "created_at" : "2016-01-07T12:44:33.959Z", "title" : "Issues with auth", "state" : "opened", "assignees" : [], "assignee" : null, "labels" : [ "bug" ], "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": null, "web_url": "http://example.com/example/example/issues/14", "confidential": false, "weight": null, }, "link_type": "relates_to" } +``` + +## Delete an issue link[](#delete-an-issue-link "Permalink") + +删除问题链接,从而删除双向关系. + +``` +DELETE /projects/:id/issues/:issue_iid/links/:issue_link_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `issue_link_id` | integer/string | yes | 发行关系的 ID | +| `link_type` | string | no | 关系的类型(" relates_to"," blocks"," is_blocked_by")默认为" relates_to" | + +``` +{ "source_issue" : { "id" : 83, "iid" : 11, "project_id" : 4, "created_at" : "2016-01-07T12:44:33.959Z", "title" : "Issues with auth", "state" : "opened", "assignees" : [], "assignee" : null, "labels" : [ "bug" ], "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": null, "web_url": "http://example.com/example/example/issues/11", "confidential": false, "weight": null, }, "target_issue" : { "id" : 84, "iid" : 14, "project_id" : 4, "created_at" : "2016-01-07T12:44:33.959Z", "title" : "Issues with auth", "state" : "opened", "assignees" : [], "assignee" : null, "labels" : [ "bug" ], "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": null, "web_url": "http://example.com/example/example/issues/14", "confidential": false, "weight": null, }, "link_type": "relates_to" } +``` \ No newline at end of file diff --git a/_book/docs/332.md b/_book/docs/332.md new file mode 100644 index 0000000000000000000000000000000000000000..831ca06a9cd44d4e2f6b6e090fd4f72678fc92c7 --- /dev/null +++ b/_book/docs/332.md @@ -0,0 +1,140 @@ +# Epic Links API + +> 原文:[https://docs.gitlab.com/ee/api/epic_links.html](https://docs.gitlab.com/ee/api/epic_links.html) + +* [List epics related to a given epic](#list-epics-related-to-a-given-epic) +* [Assign a child epic](#assign-a-child-epic) +* [Create and assign a child epic](#create-and-assign-a-child-epic) +* [Re-order a child epic](#re-order-a-child-epic) +* [Unassign a child epic](#unassign-a-child-epic) + +# Epic Links API[](#epic-links-api-ultimate "Permalink") + +**注意:**该端点是在 GitLab 11.8 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9188) . + +管理亲子[史诗般的关系](../user/group/epics/index.html#multi-level-child-epics-ultimate) . + +每个对`epic_links` API 调用`epic_links`必须经过身份验证. + +如果用户不是组的成员,并且该组是私有的,则对该组的`GET`请求将导致`404`状态代码. + +多级史诗仅在 GitLab [Ultimate / Gold](https://about.gitlab.com/pricing/)中可用. 如果"多级史诗"功能不可用,将返回`403`状态代码. + +## List epics related to a given epic[](#list-epics-related-to-a-given-epic "Permalink") + +获取史诗的所有子史诗. + +``` +GET /groups/:id/epics/:epic_iid/epics +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer | yes | 史诗的内部 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/epics/" +``` + +响应示例: + +``` +[ { "id": 29, "iid": 6, "group_id": 1, "parent_id": 5, "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "labels": [] } ] +``` + +## Assign a child epic[](#assign-a-child-epic "Permalink") + +在两个史诗之间创建关联,将一个史诗指定为父史诗,将另一个史诗指定为子史诗. 父史诗可以有多个子史诗. 如果新的子史诗已经属于另一个史诗,则该子史诗不会从先前的父史诗中分配. + +``` +POST /groups/:id/epics/:epic_iid/epics +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.html#namespaced-path-encoding) owned by the authenticated user | +| `epic_iid` | integer | yes | 史诗的内部 ID. | +| `child_epic_id` | integer | yes | 子史诗的全局 ID. 内部 ID 无法使用,因为它们可能与其他组的史诗冲突. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/epics/6" +``` + +响应示例: + +``` +{ "id": 6, "iid": 38, "group_id": 1, "parent_id": 5 "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "labels": [] } +``` + +## Create and assign a child epic[](#create-and-assign-a-child-epic "Permalink") + +创建一个新的史诗并将其与提供的父史诗相关联. 响应是 LinkedEpic 对象. + +``` +POST /groups/:id/epics/:epic_iid/epics +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer | yes | (未来父级)史诗的内部 ID. | +| `title` | string | yes | 新创建的史诗的标题. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/epics?title=Newpic" +``` + +响应示例: + +``` +{ "id": 24, "iid": 2, "title": "child epic", "group_id": 49, "parent_id": 23, "has_children": false, "has_issues": false, "reference": "&2", "url": "http://localhost/groups/group16/-/epics/2", "relation_url": "http://localhost/groups/group16/-/epics/1/links/24" } +``` + +## Re-order a child epic[](#re-order-a-child-epic "Permalink") + +``` +PUT /groups/:id/epics/:epic_iid/epics/:child_epic_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `epic_iid` | integer | yes | 史诗的内部 ID. | +| `child_epic_id` | integer | yes | 子史诗的全局 ID. 内部 ID 无法使用,因为它们可能与其他组的史诗冲突. | +| `move_before_id` | integer | no | 同胞史诗的全局 ID,应放在子史诗之前. | +| `move_after_id` | integer | no | 同胞史诗的全局 ID,应放在子史诗之后. | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/4/epics/5" +``` + +响应示例: + +``` +[ { "id": 29, "iid": 6, "group_id": 1, "parent_id": 5, "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "labels": [] } ] +``` + +## Unassign a child epic[](#unassign-a-child-epic "Permalink") + +从父级史诗中取消分配子级史诗. + +``` +DELETE /groups/:id/epics/:epic_iid/epics/:child_epic_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `epic_iid` | integer | yes | 史诗的内部 ID. | +| `child_epic_id` | integer | yes | 子史诗的全局 ID. 内部 ID 无法使用,因为它们可能与其他组的史诗冲突. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/4/epics/5" +``` + +响应示例: + +``` +{ "id": 5, "iid": 38, "group_id": 1, "parent_id": null, "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "labels": [] } +``` \ No newline at end of file diff --git a/_book/docs/333.md b/_book/docs/333.md new file mode 100644 index 0000000000000000000000000000000000000000..f6808738c1d9fa0b3ddcedffc3fa711d5ad2eb1d --- /dev/null +++ b/_book/docs/333.md @@ -0,0 +1,123 @@ +# Managed Licenses API + +> 原文:[https://docs.gitlab.com/ee/api/managed_licenses.html](https://docs.gitlab.com/ee/api/managed_licenses.html) + +* [List managed licenses](#list-managed-licenses) +* [Show an existing managed license](#show-an-existing-managed-license) +* [Create a new managed license](#create-a-new-managed-license) +* [Delete a managed license](#delete-a-managed-license) +* [Edit an existing managed license](#edit-an-existing-managed-license) + +# Managed Licenses API[](#managed-licenses-api-ultimate "Permalink") + +## List managed licenses[](#list-managed-licenses "Permalink") + +获取给定项目的所有托管许可证. + +``` +GET /projects/:id/managed_licenses +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/managed_licenses" +``` + +响应示例: + +``` +[ { "id": 1, "name": "MIT", "approval_status": "approved" }, { "id": 3, "name": "ISC", "approval_status": "blacklisted" } ] +``` + +## Show an existing managed license[](#show-an-existing-managed-license "Permalink") + +显示现有的托管许可证. + +``` +GET /projects/:id/managed_licenses/:managed_license_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `managed_license_id` | integer/string | yes | 属于项目的许可证的 ID 或 URL 编码名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6" +``` + +响应示例: + +``` +{ "id": 1, "name": "MIT", "approval_status": "blacklisted" } +``` + +## Create a new managed license[](#create-a-new-managed-license "Permalink") + +使用给定的名称和批准状态为给定的项目创建一个新的托管许可证. + +``` +POST /projects/:id/managed_licenses +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 托管许可证的名称 | +| `approval_status` | string | yes | 批准状态. "批准"或"列入黑名单" | + +``` +curl --data "name=MIT&approval_status=blacklisted" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/managed_licenses" +``` + +响应示例: + +``` +{ "id": 1, "name": "MIT", "approval_status": "approved" } +``` + +## Delete a managed license[](#delete-a-managed-license "Permalink") + +删除具有给定 ID 的托管许可证. + +``` +DELETE /projects/:id/managed_licenses/:managed_license_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `managed_license_id` | integer/string | yes | 属于项目的许可证的 ID 或 URL 编码名称 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/managed_licenses/4" +``` + +成功后,它将以 HTTP 204 响应进行回复. + +## Edit an existing managed license[](#edit-an-existing-managed-license "Permalink") + +使用新的批准状态更新现有的托管许可证. + +``` +PATCH /projects/:id/managed_licenses/:managed_license_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `managed_license_id` | integer/string | yes | 属于项目的许可证的 ID 或 URL 编码名称 | +| `approval_status` | string | yes | 批准状态. "批准"或"列入黑名单" | + +``` +curl --request PATCH --data "approval_status=blacklisted" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6" +``` + +响应示例: + +``` +{ "id": 1, "name": "MIT", "approval_status": "blacklisted" } +``` \ No newline at end of file diff --git a/_book/docs/334.md b/_book/docs/334.md new file mode 100644 index 0000000000000000000000000000000000000000..2fddbd1e238fa7eae31113cc11425c8168620cd4 --- /dev/null +++ b/_book/docs/334.md @@ -0,0 +1,33 @@ +# Markdown API + +> 原文:[https://docs.gitlab.com/ee/api/markdown.html](https://docs.gitlab.com/ee/api/markdown.html) + +* [Render an arbitrary Markdown document](#render-an-arbitrary-markdown-document) + +# Markdown API[](#markdown-api "Permalink") + +在 GitLab 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18926) . + +仅在 APIv4 中可用. + +## Render an arbitrary Markdown document[](#render-an-arbitrary-markdown-document "Permalink") + +``` +POST /api/v4/markdown +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `text` | string | yes | Markdown 文本呈现 | +| `gfm` | boolean | 否(可选) | 使用 GitLab 风味 Markdown 渲染文本. 默认为`false` | +| `project` | string | 否(可选) | 使用 GitLab Flavored Markdown 创建引用时,请使用`project`作为上下文. 如果项目不是公开的,则需要[认证](README.html#authentication) . | + +``` +curl --header Content-Type:application/json --data '{"text":"Hello world! :tada:", "gfm":true, "project":"group_example/project_example"}' "https://gitlab.example.com/api/v4/markdown" +``` + +响应示例: + +``` +{ "html": "

    Hello world! 🎉

    " } +``` \ No newline at end of file diff --git a/_book/docs/335.md b/_book/docs/335.md new file mode 100644 index 0000000000000000000000000000000000000000..b2cf4d898c1f0765f5b0b58d1c58d43052f25a35 --- /dev/null +++ b/_book/docs/335.md @@ -0,0 +1,266 @@ +# Group and project members API + +> 原文:[https://docs.gitlab.com/ee/api/members.html](https://docs.gitlab.com/ee/api/members.html) + +* [Valid access levels](#valid-access-levels) +* [List all members of a group or project](#list-all-members-of-a-group-or-project) +* [List all members of a group or project including inherited members](#list-all-members-of-a-group-or-project-including-inherited-members) +* [Get a member of a group or project](#get-a-member-of-a-group-or-project) +* [Get a member of a group or project, including inherited members](#get-a-member-of-a-group-or-project-including-inherited-members) +* [Add a member to a group or project](#add-a-member-to-a-group-or-project) +* [Edit a member of a group or project](#edit-a-member-of-a-group-or-project) + * [Set override flag for a member of a group](#set-override-flag-for-a-member-of-a-group) + * [Remove override for a member of a group](#remove-override-for-a-member-of-a-group) +* [Remove a member from a group or project](#remove-a-member-from-a-group-or-project) +* [Give a group access to a project](#give-a-group-access-to-a-project) + +# Group and project members API[](#group-and-project-members-api "Permalink") + +## Valid access levels[](#valid-access-levels "Permalink") + +访问级别在`Gitlab::Access`模块中定义. 当前,这些级别被认可: + +* 无法访问( `0` ) +* 宾客( `10` ) +* 记者( `20` ) +* 显影剂( `30` ) +* 养护者( `40` ) +* 所有者( `50` )-仅对组有效 + +**注意:**由于[存在问题](https://gitlab.com/gitlab-org/gitlab/-/issues/219299) ,个人名称空间中的项目将不会显示所有者( `50` )所有者的权限. + +## List all members of a group or project[](#list-all-members-of-a-group-or-project "Permalink") + +获取可通过身份验证的用户查看的组或项目成员的列表. 仅返回直接成员,而不返回通过祖先组继承的成员. + +此函数使用分页参数`page`和`per_page`来限制用户列表. + +``` +GET /groups/:id/members +GET /projects/:id/members +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `query` | string | no | 查询字符串以搜索成员 | +| `user_ids` | 整数数组 | no | 根据给定的用户 ID 过滤结果 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/members" +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/members" +``` + +响应示例: + +``` +[ { "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 30, "group_saml_identity": null }, { "id": 2, "username": "john_doe", "name": "John Doe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 30, "email": "john@example.com", "group_saml_identity": { "extern_uid":"ABC-1234567890", "provider": "group_saml", "saml_provider_id": 10 } } ] +``` + +## List all members of a group or project including inherited members[](#list-all-members-of-a-group-or-project-including-inherited-members "Permalink") + +获取可通过身份验证的用户查看的组或项目成员的列表,包括通过祖先组继承的成员. 当用户是项目/组和一个或多个祖先组的成员时,仅以项目`access_level` (如果存在)或用户所属项目组中第一个组的用户的`access_level`返回一次祖先链. + +此函数使用分页参数`page`和`per_page`来限制用户列表. + +``` +GET /groups/:id/members/all +GET /projects/:id/members/all +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `query` | string | no | 查询字符串以搜索成员 | +| `user_ids` | 整数数组 | no | 根据给定的用户 ID 过滤结果 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/members/all" +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/members/all" +``` + +响应示例: + +``` +[ { "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 30, "group_saml_identity": null }, { "id": 2, "username": "john_doe", "name": "John Doe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 30 "email": "john@example.com", "group_saml_identity": { "extern_uid":"ABC-1234567890", "provider": "group_saml", "saml_provider_id": 10 } }, { "id": 3, "username": "foo_bar", "name": "Foo bar", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-11-22T14:13:35Z", "access_level": 30, "group_saml_identity": null } ] +``` + +## Get a member of a group or project[](#get-a-member-of-a-group-or-project "Permalink") + +获取组或项目的成员. 仅返回直接成员,而不返回通过祖先组继承的成员. + +``` +GET /groups/:id/members/:user_id +GET /projects/:id/members/:user_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 成员的用户标识 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/members/:user_id" +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/members/:user_id" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "access_level": 30, "expires_at": null, "group_saml_identity": null } +``` + +## Get a member of a group or project, including inherited members[](#get-a-member-of-a-group-or-project-including-inherited-members "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17744) . + +获取组或项目的成员,包括通过祖先组继承的成员. 有关详细信息,请参见相应的[端点以列出所有继承的成员](#list-all-members-of-a-group-or-project-including-inherited-members) . + +``` +GET /groups/:id/members/all/:user_id +GET /projects/:id/members/all/:user_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 成员的用户标识 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/members/all/:user_id" +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/members/all/:user_id" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "access_level": 30, "expires_at": null, "group_saml_identity": null } +``` + +## Add a member to a group or project[](#add-a-member-to-a-group-or-project "Permalink") + +将成员添加到组或项目. + +``` +POST /groups/:id/members +POST /projects/:id/members +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 新成员的用户标识 | +| `access_level` | integer | yes | 有效的访问级别 | +| `expires_at` | string | no | 日期格式为 YEAR-MONTH-DAY 的日期字符串 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --data "user_id=1&access_level=30" "https://gitlab.example.com/api/v4/groups/:id/members" +curl --request POST --header "PRIVATE-TOKEN: " --data "user_id=1&access_level=30" "https://gitlab.example.com/api/v4/projects/:id/members" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 30, "group_saml_identity": null } +``` + +## Edit a member of a group or project[](#edit-a-member-of-a-group-or-project "Permalink") + +更新组或项目的成员. + +``` +PUT /groups/:id/members/:user_id +PUT /projects/:id/members/:user_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 成员的用户标识 | +| `access_level` | integer | yes | 有效的访问级别 | +| `expires_at` | string | no | 日期格式为 YEAR-MONTH-DAY 的日期字符串 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/members/:user_id?access_level=40" +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/members/:user_id?access_level=40" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 40, "group_saml_identity": null } +``` + +### Set override flag for a member of a group[](#set-override-flag-for-a-member-of-a-group "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4875) . + +默认情况下,LDAP 组成员的访问级别设置为 LDAP 通过组同步指定的值. 您可以通过调用此端点来允许访问级别替代. + +``` +POST /groups/:id/members/:user_id/override +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 成员的用户标识 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/override" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 40, "override": true } +``` + +### Remove override for a member of a group[](#remove-override-for-a-member-of-a-group "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4875) . + +将替代标志设置为 false,并允许 LDAP 组同步将访问级别重置为 LDAP 指定的值. + +``` +DELETE /groups/:id/members/:user_id/override +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 成员的用户标识 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/override" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 40, "override": false } +``` + +## Remove a member from a group or project[](#remove-a-member-from-a-group-or-project "Permalink") + +从组或项目中删除用户. + +``` +DELETE /groups/:id/members/:user_id +DELETE /projects/:id/members/:user_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 成员的用户标识 | +| `unassign_issuables` | boolean | false | 标志,指示是否应从给定的组或项目内取消分配任何问题或合并请求的已删除成员 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/members/:user_id" +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/members/:user_id" +``` + +## Give a group access to a project[](#give-a-group-access-to-a-project "Permalink") + +See [share project with group](projects.html#share-project-with-group) \ No newline at end of file diff --git a/_book/docs/336.md b/_book/docs/336.md new file mode 100644 index 0000000000000000000000000000000000000000..e36243f8c1014856aa12ffcd14c4802364b3596b --- /dev/null +++ b/_book/docs/336.md @@ -0,0 +1,430 @@ +# Merge request approvals API + +> 原文:[https://docs.gitlab.com/ee/api/merge_request_approvals.html](https://docs.gitlab.com/ee/api/merge_request_approvals.html) + +* [Project-level MR approvals](#project-level-mr-approvals) + * [Get Configuration](#get-configuration) + * [Change configuration](#change-configuration) + * [Get project-level rules](#get-project-level-rules) + * [Create project-level rule](#create-project-level-rule) + * [Update project-level rule](#update-project-level-rule) + * [Delete project-level rule](#delete-project-level-rule) + * [Change allowed approvers](#change-allowed-approvers) +* [Merge Request-level MR approvals](#merge-request-level-mr-approvals) + * [Get Configuration](#get-configuration-1) + * [Change approval configuration](#change-approval-configuration) + * [Change allowed approvers for Merge Request](#change-allowed-approvers-for-merge-request) + * [Get the approval state of merge requests](#get-the-approval-state-of-merge-requests) + * [Get merge request level rules](#get-merge-request-level-rules) + * [Create merge request level rule](#create-merge-request-level-rule) + * [Update merge request level rule](#update-merge-request-level-rule) + * [Delete merge request level rule](#delete-merge-request-level-rule) +* [Approve Merge Request](#approve-merge-request) +* [Unapprove Merge Request](#unapprove-merge-request) + +# Merge request approvals API[](#merge-request-approvals-api-starter "Permalink") + +配置项目中所有合并请求(MR)的批准. 必须对所有端点进行身份验证. + +## Project-level MR approvals[](#project-level-mr-approvals "Permalink") + +### Get Configuration[](#get-configuration "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. + +您可以使用以下端点请求有关项目批准配置的信息: + +``` +GET /projects/:id/approvals +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | + +``` +{ "approvals_before_merge": 2, "reset_approvals_on_push": true, "disable_overriding_approvers_per_merge_request": false, "merge_requests_author_approval": true, "merge_requests_disable_committers_approval": false, "require_password_to_approve": true } +``` + +### Change configuration[](#change-configuration "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. + +如果允许,则可以使用以下端点更改批准配置: + +``` +POST /projects/:id/approvals +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `approvals_before_merge` | integer | no | MR 可以合并之前需要多少批准. 在 12.0 中已弃用,以支持批准规则 API. | +| `reset_approvals_on_push` | boolean | no | 重置批准以进行新的推送 | +| `disable_overriding_approvers_per_merge_request` | boolean | no | 允许/禁止每个 MR 的替代批准者 | +| `merge_requests_author_approval` | boolean | no | 允许/禁止作者自行批准合并请求; `true`表示作者可以自行批准 | +| `merge_requests_disable_committers_approval` | boolean | no | 允许/禁止提交者自我批准合并请求 | +| `require_password_to_approve` | boolean | no | 在添加批准之前,需要批准者输入密码才能进行身份验证 | + +``` +{ "approvals_before_merge": 2, "reset_approvals_on_push": true, "disable_overriding_approvers_per_merge_request": false, "merge_requests_author_approval": false, "merge_requests_disable_committers_approval": false, "require_password_to_approve": true } +``` + +### Get project-level rules[](#get-project-level-rules "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) . +* [GitLab Premium](https://about.gitlab.com/pricing/) 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/460)了`protected_branches`属性. + +您可以使用以下端点请求有关项目批准规则的信息: + +``` +GET /projects/:id/approval_rules +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | + +``` +[ { "id": 1, "name": "security", "rule_type": "regular", "eligible_approvers": [ { "id": 5, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" }, { "id": 50, "name": "Group Member 1", "username": "group_member_1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/group_member_1" } ], "approvals_required": 3, "users": [ { "id": 5, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [ { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } ], "protected_branches": [ { "id": 1, "name": "master", "push_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "merge_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "unprotect_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } ], "contains_hidden_groups": false } ] +``` + +### Create project-level rule[](#create-project-level-rule "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点创建项目批准规则: + +``` +POST /projects/:id/approval_rules +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `name` | string | yes | 批准规则的名称 | +| `approvals_required` | integer | yes | 此规则所需的批准数量 | +| `user_ids` | Array | no | 批准者的用户 ID | +| `group_ids` | Array | no | 小组的 ID 为批准者 | +| `protected_branch_ids` | Array | no | 受保护分支的 ID 范围 | + +``` +{ "id": 1, "name": "security", "rule_type": "regular", "eligible_approvers": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" }, { "id": 50, "name": "Group Member 1", "username": "group_member_1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/group_member_1" } ], "approvals_required": 1, "users": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [ { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } ], "protected_branches": [ { "id": 1, "name": "master", "push_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "merge_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "unprotect_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } ], "contains_hidden_groups": false } +``` + +### Update project-level rule[](#update-project-level-rule "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点更新项目批准规则: + +``` +PUT /projects/:id/approval_rules/:approval_rule_id +``` + +**重要提示:**不在`users` / `groups`参数中的批准者和组将被**删除** + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `approval_rule_id` | integer | yes | 批准规则的 ID | +| `name` | string | yes | 批准规则的名称 | +| `approvals_required` | integer | yes | 此规则所需的批准数量 | +| `user_ids` | Array | no | The ids of users as approvers | +| `group_ids` | Array | no | 小组的 ID 为批准者 | +| `protected_branch_ids` | Array | no | 受保护分支的 ID 范围 | + +``` +{ "id": 1, "name": "security", "rule_type": "regular", "eligible_approvers": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" }, { "id": 50, "name": "Group Member 1", "username": "group_member_1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/group_member_1" } ], "approvals_required": 1, "users": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [ { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } ], "protected_branches": [ { "id": 1, "name": "master", "push_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "merge_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "unprotect_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } ], "contains_hidden_groups": false } +``` + +### Delete project-level rule[](#delete-project-level-rule "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点删除项目批准规则: + +``` +DELETE /projects/:id/approval_rules/:approval_rule_id +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `approval_rule_id` | integer | yes | 批准规则的 ID | + +### Change allowed approvers[](#change-allowed-approvers "Permalink") + +**注意:**此 API 端点已被弃用. 请改用批准规则 API. 在[GitLab Starter](https://about.gitlab.com/pricing/) 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/183) . + +如果允许,则可以使用以下端点更改批准者和批准者组: + +``` +PUT /projects/:id/approvers +``` + +**重要提示:**不在请求中的批准者和组将被**删除** + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `approver_ids` | Array | yes | 可以批准 MR 的用户 ID 数组 | +| `approver_group_ids` | Array | yes | 一组可以批准 MR 的组 ID | + +``` +{ "approvers": [ { "user": { "id": 5, "name": "John Doe6", "username": "user5", "state":"active","avatar_url":"https://www.gravatar.com/avatar/4aea8cf834ed91844a2da4ff7ae6b491?s=80\u0026d=identicon","web_url":"http://localhost/user5" } } ], "approver_groups": [ { "group": { "id": 1, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } } ], "approvals_before_merge": 2, "reset_approvals_on_push": true, "disable_overriding_approvers_per_merge_request": false, "merge_requests_author_approval": true, "merge_requests_disable_committers_approval": false, "require_password_to_approve": true } +``` + +## Merge Request-level MR approvals[](#merge-request-level-mr-approvals "Permalink") + +配置特定合并请求的批准. 必须对所有端点进行身份验证. + +### Get Configuration[](#get-configuration-1 "Permalink") + +在[GitLab Starter](https://about.gitlab.com/pricing/) 8.9 中引入. + +您可以使用以下端点来请求有关合并请求的批准状态的信息: + +``` +GET /projects/:id/merge_requests/:merge_request_iid/approvals +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | + +``` +{ "id": 5, "iid": 5, "project_id": 1, "title": "Approvals API", "description": "Test", "state": "opened", "created_at": "2016-06-08T00:19:52.638Z", "updated_at": "2016-06-08T21:20:42.470Z", "merge_status": "cannot_be_merged", "approvals_required": 2, "approvals_left": 1, "approved_by": [ { "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url": "http://localhost:3000/root" } } ], } +``` + +### Change approval configuration[](#change-approval-configuration "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. + +如果你被允许,你可以改变`approvals_required`使用以下端点: + +``` +POST /projects/:id/merge_requests/:merge_request_iid/approvals +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | +| `approvals_required` | integer | yes | 可以合并 MR 之前需要获得批准. 在 12.0 中已弃用,以支持批准规则 API. | + +``` +{ "id": 5, "iid": 5, "project_id": 1, "title": "Approvals API", "description": "Test", "state": "opened", "created_at": "2016-06-08T00:19:52.638Z", "updated_at": "2016-06-08T21:20:42.470Z", "merge_status": "cannot_be_merged", "approvals_required": 2, "approvals_left": 2, "approved_by": [] } +``` + +### Change allowed approvers for Merge Request[](#change-allowed-approvers-for-merge-request "Permalink") + +**注意:**此 API 端点已被弃用. 请改用批准规则 API. 在[GitLab Starter](https://about.gitlab.com/pricing/) 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/183) . + +如果允许,则可以使用以下端点更改批准者和批准者组: + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/approvers +``` + +**重要提示:**不在请求中的批准者和组将被**删除** + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | +| `approver_ids` | Array | yes | 可以批准 MR 的用户 ID 数组 | +| `approver_group_ids` | Array | yes | 一组可以批准 MR 的组 ID | + +``` +{ "id": 5, "iid": 5, "project_id": 1, "title": "Approvals API", "description": "Test", "state": "opened", "created_at": "2016-06-08T00:19:52.638Z", "updated_at": "2016-06-08T21:20:42.470Z", "merge_status": "cannot_be_merged", "approvals_required": 2, "approvals_left": 2, "approved_by": [], "approvers": [ { "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url": "http://localhost:3000/root" } } ], "approver_groups": [ { "group": { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } } ] } +``` + +### Get the approval state of merge requests[](#get-the-approval-state-of-merge-requests "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13712) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点来请求有关合并请求的批准状态的信息: + +``` +GET /projects/:id/merge_requests/:merge_request_iid/approval_state +``` + +如果为合并请求创建了合并请求级别规则,则`approval_rules_overwritten`将为`true` . 如果不存在,则为`false` . + +这包括有关已经批准的用户的更多信息( `approved_by` ),以及规则是否已经批准的( `approved` ). + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | + +``` +{ "approval_rules_overwritten": true, "rules": [ { "id": 1, "name": "Ruby", "rule_type": "regular", "eligible_approvers": [ { "id": 4, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "approvals_required": 2, "users": [ { "id": 4, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [], "contains_hidden_groups": false, "approved_by": [ { "id": 4, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "source_rule": null, "approved": true, "overridden": false } ] } +``` + +### Get merge request level rules[](#get-merge-request-level-rules "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13712) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点来请求有关合并请求的批准规则的信息: + +``` +GET /projects/:id/merge_requests/:merge_request_iid/approval_rules +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | + +``` +[ { "id": 1, "name": "security", "rule_type": "regular", "eligible_approvers": [ { "id": 5, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" }, { "id": 50, "name": "Group Member 1", "username": "group_member_1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/group_member_1" } ], "approvals_required": 3, "source_rule": null, "users": [ { "id": 5, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [ { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } ], "contains_hidden_groups": false, "overridden": false } ] +``` + +### Create merge request level rule[](#create-merge-request-level-rule "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点创建合并请求批准规则: + +``` +POST /projects/:id/merge_requests/:merge_request_iid/approval_rules +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | +| `name` | string | yes | 批准规则的名称 | +| `approvals_required` | integer | yes | 此规则所需的批准数量 | +| `approval_project_rule_id` | integer | no | 项目级批准规则的 ID | +| `user_ids` | Array | no | 批准者的用户 ID | +| `group_ids` | Array | no | 小组的 ID 为批准者 | + +**重要提示:**当`approval_project_rule_id`被设置, `name` , `users`和`groups`项目级的规则将被复制. 该`approvals_required`指定将被使用. + +``` +{ "id": 1, "name": "security", "rule_type": "regular", "eligible_approvers": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" }, { "id": 50, "name": "Group Member 1", "username": "group_member_1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/group_member_1" } ], "approvals_required": 1, "source_rule": null, "users": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [ { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } ], "contains_hidden_groups": false, "overridden": false } +``` + +### Update merge request level rule[](#update-merge-request-level-rule "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点更新合并请求批准规则: + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/approval_rules/:approval_rule_id +``` + +**重要提示:**不在`users` / `groups`参数中的批准者和组将被**删除** + +**重要提示:**不允许更新`report_approver`或`code_owner`规则. 这些是系统生成的规则. + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 ID | +| `approval_rule_id` | integer | yes | 批准规则的 ID | +| `name` | string | yes | 批准规则的名称 | +| `approvals_required` | integer | yes | 此规则所需的批准数量 | +| `user_ids` | Array | no | 批准者的用户 ID | +| `group_ids` | Array | no | 小组的 ID 为批准者 | + +``` +{ "id": 1, "name": "security", "rule_type": "regular", "eligible_approvers": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" }, { "id": 50, "name": "Group Member 1", "username": "group_member_1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/group_member_1" } ], "approvals_required": 1, "source_rule": null, "users": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [ { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } ], "contains_hidden_groups": false, "overridden": false } +``` + +### Delete merge request level rule[](#delete-merge-request-level-rule "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点删除合并请求批准规则: + +``` +DELETE /projects/:id/merge_requests/:merge_request_iid/approval_rules/:approval_rule_id +``` + +**重要提示:**不允许删除`report_approver`或`code_owner`规则. 这些是系统生成的规则. + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 ID | +| `approval_rule_id` | integer | yes | 批准规则的 ID | + +## Approve Merge Request[](#approve-merge-request "Permalink") + +在[GitLab Starter](https://about.gitlab.com/pricing/) 8.9 中引入. + +如果允许,则可以使用以下端点批准合并请求: + +``` +POST /projects/:id/merge_requests/:merge_request_iid/approve +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | +| `sha` | string | no | MR 的头 | +| `approval_password` | string | no | 当前用户的密码. 如果在项目设置中启用了" [**需要用户密码批准",**](../user/project/merge_requests/merge_request_approvals.html#require-authentication-when-approving-a-merge-request)则为必需. | + +`sha`参数的工作方式与[接受合并请求](merge_requests.html#accept-mr)时的工作方式相同:如果传递了它,则它必须与合并请求的当前 HEAD 匹配才能添加批准. 如果不匹配,则响应代码将为`409` . + +``` +{ "id": 5, "iid": 5, "project_id": 1, "title": "Approvals API", "description": "Test", "state": "opened", "created_at": "2016-06-08T00:19:52.638Z", "updated_at": "2016-06-09T21:32:14.105Z", "merge_status": "can_be_merged", "approvals_required": 2, "approvals_left": 0, "approved_by": [ { "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url": "http://localhost:3000/root" } }, { "user": { "name": "Nico Cartwright", "username": "ryley", "id": 2, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/cf7ad14b34162a76d593e3affca2adca?s=80\u0026d=identicon", "web_url": "http://localhost:3000/ryley" } } ], } +``` + +## Unapprove Merge Request[](#unapprove-merge-request "Permalink") + +在[GitLab Starter](https://about.gitlab.com/pricing/) 9.0 中引入. + +如果您确实批准了合并请求,则可以使用以下端点取消批准它: + +``` +POST /projects/:id/merge_requests/:merge_request_iid/unapprove +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | \ No newline at end of file diff --git a/_book/docs/337.md b/_book/docs/337.md new file mode 100644 index 0000000000000000000000000000000000000000..ad4f7e7e31de6e841c2c882b8b896ae6500de8bf --- /dev/null +++ b/_book/docs/337.md @@ -0,0 +1,854 @@ +# Merge requests API + +> 原文:[https://docs.gitlab.com/ee/api/merge_requests.html](https://docs.gitlab.com/ee/api/merge_requests.html) + +* [List merge requests](#list-merge-requests) +* [List project merge requests](#list-project-merge-requests) +* [List group merge requests](#list-group-merge-requests) +* [Get single MR](#get-single-mr) +* [Get single MR participants](#get-single-mr-participants) +* [Get single MR commits](#get-single-mr-commits) +* [Get single MR changes](#get-single-mr-changes) +* [List MR pipelines](#list-mr-pipelines) +* [Create MR Pipeline](#create-mr-pipeline) +* [Create MR](#create-mr) +* [Update MR](#update-mr) +* [Delete a merge request](#delete-a-merge-request) +* [Accept MR](#accept-mr) +* [Merge to default merge ref path](#merge-to-default-merge-ref-path) +* [Cancel Merge When Pipeline Succeeds](#cancel-merge-when-pipeline-succeeds) +* [Rebase a merge request](#rebase-a-merge-request) +* [Comments on merge requests](#comments-on-merge-requests) +* [List issues that will close on merge](#list-issues-that-will-close-on-merge) +* [Subscribe to a merge request](#subscribe-to-a-merge-request) +* [Unsubscribe from a merge request](#unsubscribe-from-a-merge-request) +* [Create a todo](#create-a-todo) +* [Get MR diff versions](#get-mr-diff-versions) +* [Get a single MR diff version](#get-a-single-mr-diff-version) +* [Set a time estimate for a merge request](#set-a-time-estimate-for-a-merge-request) +* [Reset the time estimate for a merge request](#reset-the-time-estimate-for-a-merge-request) +* [Add spent time for a merge request](#add-spent-time-for-a-merge-request) +* [Reset spent time for a merge request](#reset-spent-time-for-a-merge-request) +* [Get time tracking stats](#get-time-tracking-stats) +* [Approvals](#approvals-starter) + +# Merge requests API[](#merge-requests-api "Permalink") + +合并请求的每个 API 调用都必须经过验证. + +**弃用** > `reference`响应属性有利于已弃用`references` . >推出了[GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354)**注意** > `references.relative`相对于正在请求合并请求的组/项目. 当从其项目中获取合并请求时> `relative`格式将与`short`格式相同,并且在跨组/项目进行请求时, `relative`格式应与`full`格式相同. + +## List merge requests[](#list-merge-requests "Permalink") + +在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) . + +获取所有通过身份验证的用户有权访问的合并请求. 默认情况下,它仅返回当前用户创建的合并请求. 要获取所有合并请求,请使用参数`scope=all` . + +`state`参数可用于仅获取具有给定状态( `opened` , `closed` , `locked`或`merged` )或全部( `all` )的合并请求. 应该注意的是,通过`locked`进行搜索时,由于它是短暂的过渡状态,因此几乎不会返回任何结果. 分页参数`page`和`per_page`可用于限制合并请求的列表. + +``` +GET /merge_requests +GET /merge_requests?state=opened +GET /merge_requests?state=all +GET /merge_requests?milestone=release +GET /merge_requests?labels=bug,reproduced +GET /merge_requests?author_id=5 +GET /merge_requests?author_username=gitlab-bot +GET /merge_requests?my_reaction_emoji=star +GET /merge_requests?scope=assigned_to_me +GET /merge_requests?search=foo&in=title +``` + +Parameters: + +| Attribute | Type | Required | Description |   | +| --- | --- | --- | --- | --- | +| `state` | string | no | 返回所有合并请求,或者仅返回已`opened` , `closed` , `locked`或`merged`请求 |   | +| `order_by` | string | no | 返回由`created_at`或`updated_at`字段排序的请求. 默认为`created_at` |   | +| `sort` | string | no | 返回请求按`asc`或`desc`顺序排序. 默认为`desc` |   | +| `milestone` | string | no | 返回特定里程碑的合并请求. `None`返回没有里程碑的合并请求. `Any`返回将合并具有指定里程碑的请求. |   | +| `view` | string | no | 如果为`simple` ,则返回`iid` ,URL,标题,描述和合并请求的基本状态 |   | +| `labels` | string | no | 返回与逗号分隔的标签列表匹配的合并请求. `None`列出所有没有标签的合并请求. `Any`列出所有具有至少一个标签的合并请求. `No+Label` (不推荐使用)列出所有没有标签的合并请求. 预定义名称不区分大小写. |   | +| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) |   | +| `with_merge_status_recheck` | boolean | no | 如果为`true` ,则此投影请求(但不保证)异步地重新计算`merge_status`字段. 默认值为`false` . 在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890)引入 |   | +| `created_after` | datetime | no | 返回在给定时间或之后创建的合并请求 |   | +| `created_before` | datetime | no | 返回在给定时间或之前创建的合并请求 |   | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的合并请求 |   | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的合并请求 |   | +| `scope` | string | no | 对于给定的范围内返回的合并请求: `created_by_me` , `assigned_to_me`或`all` . 默认为`created_by_me` +对于 11.0 之前的版本,请改用现在不建议使用`created-by-me`范围或`created-by-me` `assigned-to-me`范围. |   | +| `author_id` | integer | no | 返回由给定用户`id`创建的合并请求. 与`author_username` . 与`scope=all`或`scope=assigned_to_me` |   | +| `author_username` | string | no | 返回由给定`username`创建的合并请求. 与`author_id` . *(在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `assignee_id` | integer | no | 返回分配给给定用户`id`合并请求. `None`将返回未分配的合并请求. `Any`退货将请求与受让人合并. |   | +| `approver_ids` | 整数数组 | no | 返回将所有具有给定`id`的用户指定为单独批准者的合并请求. `None`返回没有批准者的合并请求. `Any`退货将合并请求与批准人. |   | +| `approved_by_ids` | 整数数组 | no | 返回已被所有具有给定`id`的用户(最大:5)批准的合并请求. `None`返回没有批准的合并请求. `Any`退货将请求与批准合并. |   | +| `my_reaction_emoji` | string | no | 返回合并请求,该合并请求由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. *(在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) )* |   | +| `source_branch` | string | no | 返回具有给定源分支的合并请求 |   | +| `target_branch` | string | no | 返回具有给定目标分支的合并请求 |   | +| `search` | string | no | 根据`title`和`description`搜索合并请求 |   | +| `in` | string | no | 修改`search`属性的范围. `title` , `description`或以逗号将它们连接在一起的字符串. 默认为`title,description` |   | +| `wip` | string | no | 过滤合并请求对他们的`wip`状态. `yes` , *仅*返回 WIP 合并请求, `no` ,返回*非* WIP 合并请求 |   | +| `not` | Hash | no | 返回与提供的参数不匹配的合并请求. 接受: `labels` , `milestone` , `author_id` , `author_username` , `assignee_id` , `assignee_username` , `my_reaction_emoji` |   | + +**注意:** [从 GitLab 13.0 开始](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) ,列出合并请求可能不会主动更新`merge_status`字段(这也会影响`has_conflicts`字段),因为这可能是一项昂贵的操作. 如果您对此端点的这些字段的值感兴趣,请在查询`with_merge_status_recheck`参数设置为`true` .**注意:** [从 GitLab 12.8 开始,](https://gitlab.com/gitlab-org/gitlab/-/issues/29984)当对此端点发出请求时,将异步检查每个合并请求的可合并性( `merge_status` ). 轮询此 API 端点以获取更新状态. 这会影响`has_conflicts`属性,因为它取决于`merge_status` . 除非`merge_status`为`cannot_be_merged`否则它将返回`false` . + +``` +[ { "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "my-group/my-project!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "task_completion_status":{ "count":0, "completed_count":0 } } ] +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +[ { "id": 1, "title": "test1", "approvals_before_merge": null ... } ] +``` + +## List project merge requests[](#list-project-merge-requests "Permalink") + +获取此项目的所有合并请求. `state`参数可用于仅获取具有给定状态( `opened` , `closed` , `locked`或`merged` )或全部( `all` )的合并请求. 分页参数`page`和`per_page`可用于限制合并请求的列表. + +``` +GET /projects/:id/merge_requests +GET /projects/:id/merge_requests?state=opened +GET /projects/:id/merge_requests?state=all +GET /projects/:id/merge_requests?iids[]=42&iids[]=43 +GET /projects/:id/merge_requests?milestone=release +GET /projects/:id/merge_requests?labels=bug,reproduced +GET /projects/:id/merge_requests?my_reaction_emoji=star +``` + +`project_id`代表 MR 所在项目的 ID. `project_id`将始终等于`target_project_id` . + +如果来自同一项目的合并请求,则`source_project_id` , `target_project_id`和`project_id`将相同. 对于来自派生的合并请求, `target_project_id`和`project_id`将相同,并且`source_project_id`将是派生项目的 ID. + +Parameters: + +| Attribute | Type | Required | Description |   | +| --- | --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID |   | +| `iids[]` | 整数数组 | no | 返回具有给定`iid`的请求 |   | +| `state` | string | no | 返回所有合并请求,或者仅返回已`opened` , `closed` , `locked`或`merged`请求 |   | +| `order_by` | string | no | 返回由`created_at`或`updated_at`字段排序的请求. 默认为`created_at` |   | +| `sort` | string | no | 返回请求按`asc`或`desc`顺序排序. 默认为`desc` |   | +| `milestone` | string | no | 返回特定里程碑的合并请求. `None`返回没有里程碑的合并请求. `Any`返回将合并具有指定里程碑的请求. |   | +| `view` | string | no | 如果为`simple` ,则返回`iid` ,URL,标题,描述和合并请求的基本状态 |   | +| `labels` | string | no | 返回与逗号分隔的标签列表匹配的合并请求. `None`列出所有没有标签的合并请求. `Any`列出所有具有至少一个标签的合并请求. `No+Label` (不推荐使用)列出所有没有标签的合并请求. 预定义名称不区分大小写. |   | +| `with_labels_details` | boolean | no | 如果为`true` ,则响应将为标签字段中的每个标签返回更多详细信息`:name` , `:color` , `:description` , `:description_html` , `:text_color` . 默认值为`false` . 在[GitLab 12.7 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)引入 |   | +| `with_merge_status_recheck` | boolean | no | 如果为`true` ,则此投影请求(但不保证)异步地重新计算`merge_status`字段. 默认值为`false` . 在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890)引入 |   | +| `created_after` | datetime | no | 返回在给定时间或之后创建的合并请求 |   | +| `created_before` | datetime | no | 返回在给定时间或之前创建的合并请求 |   | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的合并请求 |   | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的合并请求 |   | +| `scope` | string | no | 对于给定的范围内返回的合并请求: `created_by_me` , `assigned_to_me`或`all` . +对于 11.0 之前的版本,请改用现在不建议使用`created-by-me`范围或`created-by-me` `assigned-to-me`范围. +*(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) .在 GitLab 11.0 中[更改为 snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) )* |   | +| `author_id` | integer | no | 返回由给定用户`id`创建的合并请求. 与`author_username` . *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `author_username` | string | no | 返回由给定`username`创建的合并请求. 与`author_id` . *(在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `assignee_id` | integer | no | 返回分配给给定用户`id`合并请求. `None`将返回未分配的合并请求. `Any`退货将请求与受让人合并. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `approver_ids` | 整数数组 | no | 返回将所有具有给定`id`的用户指定为单独批准者的合并请求. `None`返回没有批准者的合并请求. `Any`退货将合并请求与批准人. |   | +| `approved_by_ids` | 整数数组 | no | 返回已被所有具有给定`id`的用户(最大:5)批准的合并请求. `None`返回没有批准的合并请求. `Any`退货将请求与批准合并. |   | +| `my_reaction_emoji` | string | no | 返回合并请求,该合并请求由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. *(在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) )* |   | +| `source_branch` | string | no | 返回具有给定源分支的合并请求 |   | +| `target_branch` | string | no | 返回具有给定目标分支的合并请求 |   | +| `search` | string | no | 根据`title`和`description`搜索合并请求 |   | +| `wip` | string | no | 过滤合并请求对他们的`wip`状态. `yes` , *仅*返回 WIP 合并请求, `no` ,返回*非* WIP 合并请求 |   | + +``` +[ { "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "task_completion_status":{ "count":0, "completed_count":0 }, "has_conflicts": false, "blocking_discussions_resolved": true } ] +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +[ { "id": 1, "title": "test1", "approvals_before_merge": null ... } ] +``` + +## List group merge requests[](#list-group-merge-requests "Permalink") + +获取该组及其子组的所有合并请求. `state`参数可用于仅获取具有给定状态( `opened` , `closed` , `locked`或`merged` )或全部( `all` )的合并请求. 分页参数`page`和`per_page`可用于限制合并请求的列表. + +``` +GET /groups/:id/merge_requests +GET /groups/:id/merge_requests?state=opened +GET /groups/:id/merge_requests?state=all +GET /groups/:id/merge_requests?milestone=release +GET /groups/:id/merge_requests?labels=bug,reproduced +GET /groups/:id/merge_requests?my_reaction_emoji=star +``` + +`group_id`代表包含 MR 所在项目的组的 ID. + +Parameters: + +| Attribute | Type | Required | Description |   | +| --- | --- | --- | --- | --- | +| `id` | integer | yes | 组的 ID |   | +| `state` | string | no | 返回所有合并请求,或者仅返回已`opened` , `closed` , `locked`或`merged`请求 |   | +| `order_by` | string | no | 返回由`created_at`或`updated_at`字段排序的合并请求. 默认为`created_at` |   | +| `sort` | string | no | 返回以`asc`或`desc`顺序排序的合并请求. 默认为`desc` |   | +| `milestone` | string | no | 返回特定里程碑的合并请求. `None`返回没有里程碑的合并请求. `Any`返回将合并具有指定里程碑的请求. |   | +| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request |   | +| `labels` | string | no | 返回与逗号分隔的标签列表匹配的合并请求. `None`列出所有没有标签的合并请求. `Any`列出所有具有至少一个标签的合并请求. `No+Label` (不推荐使用)列出所有没有标签的合并请求. 预定义名称不区分大小写. |   | +| `with_labels_details` | boolean | no | 如果为`true` ,则响应将为标签字段中的每个标签返回更多详细信息`:name` , `:color` , `:description` , `:description_html` , `:text_color` . 默认值为`false` . 在[GitLab 12.7 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)引入 |   | +| `with_merge_status_recheck` | boolean | no | 如果为`true` ,则此投影请求(但不保证)异步地重新计算`merge_status`字段. 默认值为`false` . 在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890)引入 |   | +| `created_after` | datetime | no | 返回在给定时间或之后创建的合并请求 |   | +| `created_before` | datetime | no | 返回在给定时间或之前创建的合并请求 |   | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的合并请求 |   | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的合并请求 |   | +| `scope` | string | no | 对于给定的范围内返回的合并请求: `created_by_me` , `assigned_to_me`或`all` . + |   | +| `author_id` | integer | no | 返回由给定用户`id`创建的合并请求. 与`author_username` . *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `author_username` | string | no | 返回由给定`username`创建的合并请求. 与`author_id` . *(在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `assignee_id` | integer | no | 返回分配给给定用户`id`合并请求. `None`将返回未分配的合并请求. `Any`退货将请求与受让人合并. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `approver_ids` | 整数数组 | no | 返回将所有具有给定`id`的用户指定为单独批准者的合并请求. `None`返回没有批准者的合并请求. `Any`退货将合并请求与批准人. |   | +| `approved_by_ids` | 整数数组 | no | 返回已被所有具有给定`id`的用户(最大:5)批准的合并请求. `None`返回没有批准的合并请求. `Any`退货将请求与批准合并. |   | +| `my_reaction_emoji` | string | no | 返回合并请求,该合并请求由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. *(在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) )* |   | +| `source_branch` | string | no | 返回具有给定源分支的合并请求 |   | +| `target_branch` | string | no | 返回具有给定目标分支的合并请求 |   | +| `search` | string | no | 根据`title`和`description`搜索合并请求 |   | +| `non_archived` | boolean | no | 仅从非归档项目返回合并请求. 默认为 true. *(在[GitLab 12.8 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23809)引入)* |   | + +``` +[ { "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-10-22", "start_date": "2018-09-08", "web_url": "gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "my-project!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "task_completion_status":{ "count":0, "completed_count":0 }, "has_conflicts": false, "blocking_discussions_resolved": true } ] +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +[ { "id": 1, "title": "test1", "approvals_before_merge": null ... } ] +``` + +## Get single MR[](#get-single-mr "Permalink") + +显示有关单个合并请求的信息. + +**注意** :响应中的`changes_count`值是一个字符串,而不是整数. 这是因为当 MR 有太多要显示和存储的更改时,其上限为 1,000\. 在这种情况下,API 将为更改计数返回字符串`"1000+"` . + +``` +GET /projects/:id/merge_requests/:merge_request_iid +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需)-合并请求的内部 ID +* `render_html` (optional) - If `true` response includes rendered HTML for title and description +* `include_diverged_commits_count` (可选)-如果为`true`包括目标分支后面的提交 +* `include_rebase_in_progress` (可选)-如果为`true`包括是否正在进行 rebase 操作 + +**注意:** [从 GitLab 12.8 开始,](https://gitlab.com/gitlab-org/gitlab/-/issues/29984)当对此端点发出请求时,将异步检查合并请求的可合并性( `merge_status` ). 轮询此 API 端点以获取更新状态. 这会影响`has_conflicts`属性,因为它取决于`merge_status` . 除非`merge_status`为`cannot_be_merged`否则它将返回`false` . + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "user" : { "can_merge" : false }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "merge_error": null, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "rebase_in_progress": false, "first_contribution": false, "task_completion_status":{ "count":0, "completed_count":0 }, "has_conflicts": false, "blocking_discussions_resolved": true } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Get single MR participants[](#get-single-mr-participants "Permalink") + +获取合并请求参与者的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/participants +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需)-合并请求的内部 ID + +``` +[ { "id": 1, "name": "John Doe1", "username": "user1", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://localhost/user1" }, { "id": 2, "name": "John Doe2", "username": "user2", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/10fc7f102be8de7657fb4d80898bbfe3?s=80&d=identicon", "web_url": "http://localhost/user2" } ] +``` + +## Get single MR commits[](#get-single-mr-commits "Permalink") + +获取合并请求提交的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/commits +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需)-合并请求的内部 ID + +``` +[ { "id": "ed899a2f4b50b4370feeea94676502b42383c746", "short_id": "ed899a2f4b5", "title": "Replace sanitize with escape once", "author_name": "Example User", "author_email": "user@example.com", "created_at": "2012-09-20T11:50:22+03:00", "message": "Replace sanitize with escape once" }, { "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", "short_id": "6104942438c", "title": "Sanitize for network graph", "author_name": "Example User", "author_email": "user@example.com", "created_at": "2012-09-20T09:06:12+03:00", "message": "Sanitize for network graph" } ] +``` + +## Get single MR changes[](#get-single-mr-changes "Permalink") + +显示有关合并请求的信息,包括其文件和更改. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/changes +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需)-合并请求的内部 ID + +``` +{ "id": 21, "iid": 1, "project_id": 4, "title": "Blanditiis beatae suscipit hic assumenda et molestias nisi asperiores repellat et.", "state": "reopened", "created_at": "2015-02-02T19:49:39.159Z", "updated_at": "2015-02-02T20:08:49.959Z", "target_branch": "secret_token", "source_branch": "version-1-9", "upvotes": 0, "downvotes": 0, "author": { "name": "Chad Hamill", "username": "jarrett", "id": 5, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/b95567800f828948baf5f4160ebb2473?s=40&d=identicon", "web_url" : "https://gitlab.example.com/jarrett" }, "assignee": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40&d=identicon", "web_url" : "https://gitlab.example.com/root" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 4, "target_project_id": 4, "labels": [ ], "description": "Qui voluptatibus placeat ipsa alias quasi. Deleniti rem ut sint. Optio velit qui distinctio.", "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 4, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": null }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "subscribed" : true, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "changes_count": "1", "should_remove_source_branch": true, "force_remove_source_branch": false, "squash": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "discussion_locked": false, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "task_completion_status":{ "count":0, "completed_count":0 }, "changes": [ { "old_path": "VERSION", "new_path": "VERSION", "a_mode": "100644", "b_mode": "100644", "diff": "--- a/VERSION\ +++ b/VERSION\ @@ -1 +1 @@\ -1.9.7\ +1.9.8", "new_file": false, "renamed_file": false, "deleted_file": false } ] } +``` + +## List MR pipelines[](#list-mr-pipelines "Permalink") + +在 GitLab 10.5.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15454) . + +获取合并请求管道的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/pipelines +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需)-合并请求的内部 ID + +``` +[ { "id": 77, "sha": "959e04d7c7a30600c894bd3c0cd0e1ce7f42c11d", "ref": "master", "status": "success" } ] +``` + +## Create MR Pipeline[](#create-mr-pipeline "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31722) . + +[为合并请求](../ci/merge_request_pipelines/index.html)创建一个新[管道](../ci/merge_request_pipelines/index.html) . 通过这个端点创建的管道将无法运行常规的分支/标签的管道,它需要`.gitlab-ci.yml`与配置`only: [merge_requests]`创造就业机会. + +新管道可以是: + +* 分离的合并请求管道. +* A [pipeline for merged results](../ci/merge_request_pipelines/pipelines_for_merged_results/index.html) if the [project setting is enabled](../ci/merge_request_pipelines/pipelines_for_merged_results/index.html#enable-pipelines-for-merged-results). + +``` +POST /projects/:id/merge_requests/:merge_request_iid/pipelines +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需)-合并请求的内部 ID + +``` +{ "id": 2, "sha": "b83d6e391c22777fca1ed3012fce84f633d7fed0", "ref": "refs/merge-requests/1/head", "status": "pending", "web_url": "http://localhost/user1/project1/pipelines/2", "before_sha": "0000000000000000000000000000000000000000", "tag": false, "yaml_errors": null, "user": { "id": 1, "name": "John Doe1", "username": "user1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://example.com" }, "created_at": "2019-09-04T19:20:18.267Z", "updated_at": "2019-09-04T19:20:18.459Z", "started_at": null, "finished_at": null, "committed_at": null, "duration": null, "coverage": null, "detailed_status": { "icon": "status_pending", "text": "pending", "label": "pending", "group": "pending", "tooltip": "pending", "has_details": false, "details_path": "/user1/project1/pipelines/2", "illustration": null, "favicon": "/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png" } } +``` + +## Create MR[](#create-mr "Permalink") + +创建一个新的合并请求. + +``` +POST /projects/:id/merge_requests +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `source_branch` | string | yes | 源分支 | +| `target_branch` | string | yes | 目标分支 | +| `title` | string | yes | 先生的头衔 | +| `assignee_id` | integer | no | 受让人用户 ID | +| `assignee_ids` | 整数数组 | no | 要将 MR 分配给的用户的 ID. 设置为`0`或提供一个空值以取消分配所有受让人. | +| `description` | string | no | MR 的描述. 限制为 1,048,576 个字符. | +| `target_project_id` | integer | no | 目标项目(数字 ID) | +| `labels` | string | no | MR 的标签以逗号分隔的列表 | +| `milestone_id` | integer | no | 里程碑的全局 ID | +| `remove_source_branch` | boolean | no | 指示合并请求是否应在合并时删除源分支的标志 | +| `allow_collaboration` | boolean | no | 允许来自可以合并到目标分支的成员的提交 | +| `allow_maintainer_to_push` | boolean | no | Deprecated, see allow_collaboration | +| `squash` | boolean | no | 合并时将 Squash 提交到单个提交中 | + +如果`approvals_before_merge` 未提供,它将从目标项目继承值. 如果提供了它,则必须满足以下条件才能使其生效: + +1. 目标项目的`approvals_before_merge`必须大于零. 零值将禁用该项目的批准. +2. 所提供的价值`approvals_before_merge`必须比目标项目的更大`approvals_before_merge` . + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "merge_error": null, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Update MR[](#update-mr "Permalink") + +更新现有的合并请求. 您可以更改目标分支,标题,甚至关闭 MR. + +``` +PUT /projects/:id/merge_requests/:merge_request_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 ID | +| `target_branch` | string | no | 目标分支 | +| `title` | string | no | 先生的头衔 | +| `assignee_id` | integer | no | 要将合并请求分配给的用户的 ID. 设置为`0`或提供一个空值以取消分配所有受让人. | +| `assignee_ids` | 整数数组 | no | 要将 MR 分配给的用户的 ID. 设置为`0`或提供一个空值以取消分配所有受让人. | +| `milestone_id` | integer | no | 要将合并请求分配给的里程碑的全局 ID. 设置为`0`或提供一个空值以取消分配里程碑. | +| `labels` | string | no | 合并请求的逗号分隔标签名称. 设置为空字符串以取消分配所有标签. | +| `add_labels` | string | no | 以逗号分隔的标签名称,添加到合并请求中. | +| `remove_labels` | string | no | 逗号分隔的标签名称,可从合并请求中删除. | +| `description` | string | no | MR 的描述. 限制为 1,048,576 个字符. | +| `state_event` | string | no | 新状态(关闭/重新打开) | +| `remove_source_branch` | boolean | no | 指示合并请求是否应在合并时删除源分支的标志 | +| `squash` | boolean | no | 合并时将 Squash 提交到单个提交中 | +| `discussion_locked` | boolean | no | 指示合并请求的讨论是否已锁定的标志. 如果讨论被锁定,则只有项目成员可以添加,编辑或解决评论. | +| `allow_collaboration` | boolean | no | 允许来自可以合并到目标分支的成员的提交 | +| `allow_maintainer_to_push` | boolean | no | 已弃用,请参见 allow_collaboration | + +必须至少包含一个以上非必需的属性. + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "merge_error": null, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Delete a merge request[](#delete-a-merge-request "Permalink") + +仅适用于管理员和项目所有者. 删除相关合并请求. + +``` +DELETE /projects/:id/merge_requests/:merge_request_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/merge_requests/85" +``` + +## Accept MR[](#accept-mr "Permalink") + +使用此 API 合并通过 MR 提交的更改. + +如果合并请求无法被接受(例如:进行中,已关闭,正在等待管道完成或在要求成功时失败)-您将收到`405`和错误消息"不允许使用方法" + +如果存在一些冲突且无法合并-您将收到`406` ,并且错误消息"分支无法合并" + +如果传递了`sha`参数,但与源头的 HEAD 不匹配-您将得到`409`且错误消息" SHA 与源分支的 HEAD 不匹配" + +如果您没有接受此合并请求的权限-您会收到`401` + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/merge +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需) `merge_request_iid`内部 ID +* `merge_commit_message` (optional) - Custom merge commit message +* `squash_commit_message` (可选)-自定义南瓜提交消息 +* `squash` (可选)-如果为`true`则提交将在合并时被压缩为单个提交 +* `should_remove_source_branch` (可选)-如果为`true`删除源分支 +* `merge_when_pipeline_succeeds` (可选)-如果为`true` ,则在管道成功时合并 MR +* `sha` (可选)-如果存在,则此 SHA 必须与源分支的 HEAD 匹配,否则合并将失败 + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "merge_error": null, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Merge to default merge ref path[](#merge-to-default-merge-ref-path "Permalink") + +如果可能,将合并请求源和目标分支之间的更改合并到目标项目存储库的`refs/merge-requests/:iid/merge` ref 中. 如果执行常规合并操作,此引用将具有目标分支将具有的状态. + +这不是常规的合并操作,因为它不会以任何方式更改合并请求目标分支的状态. + +向此 API 提交请求时,此 ref( `refs/merge-requests/:iid/merge` )不一定会被覆盖,尽管它可以确保 ref 具有最新的状态. + +如果合并请求有冲突,为空或已经合并,您将收到一条`400`和一个描述性错误消息. + +如果为`200`它将在响应正文中返回`refs/merge-requests/:iid/merge`的 HEAD 提交. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/merge_ref +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需) `merge_request_iid`内部 ID + +``` +{ "commit_id": "854a3a7a17acbcc0bbbea170986df1eb60435f34" } +``` + +## Cancel Merge When Pipeline Succeeds[](#cancel-merge-when-pipeline-succeeds "Permalink") + +如果您没有接受此合并请求的权限-您会收到`401` + +如果合并请求已被合并或关闭-您将收到`405`和错误消息"不允许使用方法" + +如果在管道成功时未将合并请求设置为要合并,则还会收到`406`错误. + +``` +POST /projects/:id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_succeeds +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需) `merge_request_iid`内部 ID + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": false, "merge_status": "can_be_merged", "merge_error": null, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Rebase a merge request[](#rebase-a-merge-request "Permalink") + +自动将合并请求的`source_branch`与其`target_branch` . + +如果您无权推送到合并请求的源分支-您将收到`403 Forbidden`响应. + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/rebase +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | +| `skip_ci` | boolean | no | 设置为`true`以跳过创建 CI 管道 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/76/merge_requests/1/rebase" +``` + +这是一个异步请求. 如果请求成功入队,API 将返回`202 Accepted`响应,响应包含: + +``` +{ "rebase_in_progress": true } +``` + +您可以使用`include_rebase_in_progress`参数轮询" [获取单个 MR"](#get-single-mr)端点,以检查异步请求的状态. + +如果正在进行 rebase 操作,则响应将包括以下内容: + +``` +{ "rebase_in_progress": true, "merge_error": null } +``` + +一旦成功完成了变基操作,响应将包括以下内容: + +``` +{ "rebase_in_progress": false, "merge_error": null } +``` + +如果 rebase 操作失败,响应将包括以下内容: + +``` +{ "rebase_in_progress": false, "merge_error": "Rebase failed. Please rebase locally" } +``` + +## Comments on merge requests[](#comments-on-merge-requests "Permalink") + +注释是通过[notes](notes.html)资源完成的. + +## List issues that will close on merge[](#list-issues-that-will-close-on-merge "Permalink") + +通过合并提供的合并请求来获取所有将要解决的问题. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/closes_issues +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/76/merge_requests/1/closes_issues" +``` + +使用 GitLab 问题跟踪器时的示例响应: + +``` +[ { "state" : "opened", "description" : "Ratione dolores corrupti mollitia soluta quia.", "author" : { "state" : "active", "id" : 18, "web_url" : "https://gitlab.example.com/eileen.lowe", "name" : "Alexandra Bashirian", "avatar_url" : null, "username" : "eileen.lowe" }, "milestone" : { "project_id" : 1, "description" : "Ducimus nam enim ex consequatur cumque ratione.", "state" : "closed", "due_date" : null, "iid" : 2, "created_at" : "2016-01-04T15:31:39.996Z", "title" : "v4.0", "id" : 17, "updated_at" : "2016-01-04T15:31:39.996Z" }, "project_id" : 1, "assignee" : { "state" : "active", "id" : 1, "name" : "Administrator", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root" }, "updated_at" : "2016-01-04T15:31:51.081Z", "id" : 76, "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", "created_at" : "2016-01-04T15:31:51.081Z", "iid" : 6, "labels" : [], "user_notes_count": 1, "changes_count": "1" } ] +``` + +使用外部问题跟踪器(例如 Jira)时的示例响应: + +``` +[ { "id" : "PROJECT-123", "title" : "Title of this issue" } ] +``` + +## Subscribe to a merge request[](#subscribe-to-a-merge-request "Permalink") + +向已认证的用户订阅合并请求以接收通知. 如果用户已经订阅了合并请求,则返回状态码`304` . + +``` +POST /projects/:id/merge_requests/:merge_request_iid/subscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/17/subscribe" +``` + +响应示例: + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Unsubscribe from a merge request[](#unsubscribe-from-a-merge-request "Permalink") + +从合并请求中退订已认证的用户,以不接收来自该合并请求的通知. 如果用户未订阅合并请求,则返回状态码`304` . + +``` +POST /projects/:id/merge_requests/:merge_request_iid/unsubscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/17/unsubscribe" +``` + +响应示例: + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Create a todo[](#create-a-todo "Permalink") + +在合并请求上为当前用户手动创建待办事项. 如果在该合并请求上已经存在用户的待办事项,则返回状态码`304` . + +``` +POST /projects/:id/merge_requests/:merge_request_iid/todo +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/27/todo" +``` + +响应示例: + +``` +{ "id": 113, "project": { "id": 3, "name": "GitLab CI/CD", "name_with_namespace": "GitLab Org / GitLab CI/CD", "path": "gitlab-ci", "path_with_namespace": "gitlab-org/gitlab-ci" }, "author": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "action_name": "marked", "target_type": "MergeRequest", "target": { "id": 27, "iid": 7, "project_id": 3, "title": "Et voluptas laudantium minus nihil recusandae ut accusamus earum aut non.", "description": "Veniam sunt nihil modi earum cumque illum delectus. Nihil ad quis distinctio quia. Autem eligendi at quibusdam repellendus.", "state": "merged", "created_at": "2016-06-17T07:48:04.330Z", "updated_at": "2016-07-01T11:14:15.537Z", "target_branch": "allow_regex_for_project_skip_ref", "source_branch": "backup", "upvotes": 0, "downvotes": 0, "author": { "name": "Jarret O'Keefe", "username": "francisca", "id": 14, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a7fa515d53450023c83d62986d0658a8?s=80&d=identicon", "web_url": "https://gitlab.example.com/francisca", "discussion_locked": false }, "assignee": { "name": "Dr. Gabrielle Strosin", "username": "barrett.krajcik", "id": 4, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/733005fcd7e6df12d2d8580171ccb966?s=80&d=identicon", "web_url": "https://gitlab.example.com/barrett.krajcik" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 3, "target_project_id": 3, "labels": [], "work_in_progress": false, "milestone": { "id": 27, "iid": 2, "project_id": 3, "title": "v1.0", "description": "Quis ea accusantium animi hic fuga assumenda.", "state": "active", "created_at": "2016-06-17T07:47:33.840Z", "updated_at": "2016-06-17T07:47:33.840Z", "due_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "unchecked", "subscribed": true, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 7, "changes_count": "1", "should_remove_source_branch": true, "force_remove_source_branch": false, "squash": false, "web_url": "http://example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, }, "target_url": "https://gitlab.example.com/gitlab-org/gitlab-ci/merge_requests/7", "body": "Et voluptas laudantium minus nihil recusandae ut accusamus earum aut non.", "state": "pending", "created_at": "2016-07-01T11:14:15.530Z" } +``` + +## Get MR diff versions[](#get-mr-diff-versions "Permalink") + +获取合并请求差异版本的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/versions +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | String | yes | 项目 ID | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions" +``` + +响应示例: + +``` +[{ "id": 110, "head_commit_sha": "33e2ee8579fda5bc36accc9c6fbd0b4fefda9e30", "base_commit_sha": "eeb57dffe83deb686a60a71c16c32f71046868fd", "start_commit_sha": "eeb57dffe83deb686a60a71c16c32f71046868fd", "created_at": "2016-07-26T14:44:48.926Z", "merge_request_id": 105, "state": "collected", "real_size": "1" }, { "id": 108, "head_commit_sha": "3eed087b29835c48015768f839d76e5ea8f07a24", "base_commit_sha": "eeb57dffe83deb686a60a71c16c32f71046868fd", "start_commit_sha": "eeb57dffe83deb686a60a71c16c32f71046868fd", "created_at": "2016-07-25T14:21:33.028Z", "merge_request_id": 105, "state": "collected", "real_size": "1" }] +``` + +## Get a single MR diff version[](#get-a-single-mr-diff-version "Permalink") + +获取单个合并请求的差异版本. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/versions/:version_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | String | yes | 项目 ID | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | +| `version_id` | integer | yes | 合并请求差异版本的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions/1" +``` + +响应示例: + +``` +{ "id": 110, "head_commit_sha": "33e2ee8579fda5bc36accc9c6fbd0b4fefda9e30", "base_commit_sha": "eeb57dffe83deb686a60a71c16c32f71046868fd", "start_commit_sha": "eeb57dffe83deb686a60a71c16c32f71046868fd", "created_at": "2016-07-26T14:44:48.926Z", "merge_request_id": 105, "state": "collected", "real_size": "1", "commits": [{ "id": "33e2ee8579fda5bc36accc9c6fbd0b4fefda9e30", "short_id": "33e2ee85", "title": "Change year to 2018", "author_name": "Administrator", "author_email": "admin@example.com", "created_at": "2016-07-26T17:44:29.000+03:00", "message": "Change year to 2018" }, { "id": "aa24655de48b36335556ac8a3cd8bb521f977cbd", "short_id": "aa24655d", "title": "Update LICENSE", "author_name": "Administrator", "author_email": "admin@example.com", "created_at": "2016-07-25T17:21:53.000+03:00", "message": "Update LICENSE" }, { "id": "3eed087b29835c48015768f839d76e5ea8f07a24", "short_id": "3eed087b", "title": "Add license", "author_name": "Administrator", "author_email": "admin@example.com", "created_at": "2016-07-25T17:21:20.000+03:00", "message": "Add license" }], "diffs": [{ "old_path": "LICENSE", "new_path": "LICENSE", "a_mode": "0", "b_mode": "100644", "diff": "--- /dev/null\n+++ b/LICENSE\n@@ -0,0 +1,21 @@\n+The MIT License (MIT)\n+\n+Copyright (c) 2018 Administrator\n+\n+Permission is hereby granted, free of charge, to any person obtaining a copy\n+of this software and associated documentation files (the \"Software\"), to deal\n+in the Software without restriction, including without limitation the rights\n+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n+copies of the Software, and to permit persons to whom the Software is\n+furnished to do so, subject to the following conditions:\n+\n+The above copyright notice and this permission notice shall be included in all\n+copies or substantial portions of the Software.\n+\n+THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n+SOFTWARE.\n", "new_file": true, "renamed_file": false, "deleted_file": false }] } +``` + +## Set a time estimate for a merge request[](#set-a-time-estimate-for-a-merge-request "Permalink") + +Sets an estimated time of work for this merge request. + +``` +POST /projects/:id/merge_requests/:merge_request_iid/time_estimate +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | +| `duration` | string | yes | 以人类格式表示的持续时间. 例如:3h30m | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_estimate?duration=3h30m" +``` + +响应示例: + +``` +{ "human_time_estimate": "3h 30m", "human_total_time_spent": null, "time_estimate": 12600, "total_time_spent": 0 } +``` + +## Reset the time estimate for a merge request[](#reset-the-time-estimate-for-a-merge-request "Permalink") + +将此合并请求的估计时间重置为 0 秒. + +``` +POST /projects/:id/merge_requests/:merge_request_iid/reset_time_estimate +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 项目的 merge_request 的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_time_estimate" +``` + +响应示例: + +``` +{ "human_time_estimate": null, "human_total_time_spent": null, "time_estimate": 0, "total_time_spent": 0 } +``` + +## Add spent time for a merge request[](#add-spent-time-for-a-merge-request "Permalink") + +增加此合并请求的时间 + +``` +POST /projects/:id/merge_requests/:merge_request_iid/add_spent_time +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | +| `duration` | string | yes | 以人类格式表示的持续时间. 例如:3h30m | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/add_spent_time?duration=1h" +``` + +响应示例: + +``` +{ "human_time_estimate": null, "human_total_time_spent": "1h", "time_estimate": 0, "total_time_spent": 3600 } +``` + +## Reset spent time for a merge request[](#reset-spent-time-for-a-merge-request "Permalink") + +将此合并请求的总花费时间重置为 0 秒. + +``` +POST /projects/:id/merge_requests/:merge_request_iid/reset_spent_time +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 项目的 merge_request 的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_spent_time" +``` + +响应示例: + +``` +{ "human_time_estimate": null, "human_total_time_spent": null, "time_estimate": 0, "total_time_spent": 0 } +``` + +## Get time tracking stats[](#get-time-tracking-stats "Permalink") + +``` +GET /projects/:id/merge_requests/:merge_request_iid/time_stats +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_stats" +``` + +响应示例: + +``` +{ "human_time_estimate": "2h", "human_total_time_spent": "1h", "time_estimate": 7200, "total_time_spent": 3600 } +``` + +## Approvals[](#approvals-starter "Permalink") + +有关批准,请参阅[合并请求批准](merge_request_approvals.html) \ No newline at end of file diff --git a/_book/docs/338.md b/_book/docs/338.md new file mode 100644 index 0000000000000000000000000000000000000000..a17013eef83f07590dce514792fe3ebcac443c4a --- /dev/null +++ b/_book/docs/338.md @@ -0,0 +1,167 @@ +# Project milestones API + +> 原文:[https://docs.gitlab.com/ee/api/milestones.html](https://docs.gitlab.com/ee/api/milestones.html) + +* [List project milestones](#list-project-milestones) +* [Get single milestone](#get-single-milestone) +* [Create new milestone](#create-new-milestone) +* [Edit milestone](#edit-milestone) +* [Delete project milestone](#delete-project-milestone) +* [Get all issues assigned to a single milestone](#get-all-issues-assigned-to-a-single-milestone) +* [Get all merge requests assigned to a single milestone](#get-all-merge-requests-assigned-to-a-single-milestone) +* [Promote project milestone to a group milestone](#promote-project-milestone-to-a-group-milestone) +* [Get all burndown chart events for a single milestone](#get-all-burndown-chart-events-for-a-single-milestone-starter) + +# Project milestones API[](#project-milestones-api "Permalink") + +This page describes the project milestones API. There’s a separate [group milestones API](./group_milestones.html) page. + +## List project milestones[](#list-project-milestones "Permalink") + +返回项目里程碑的列表. + +``` +GET /projects/:id/milestones +GET /projects/:id/milestones?iids[]=42 +GET /projects/:id/milestones?iids[]=42&iids[]=43 +GET /projects/:id/milestones?state=active +GET /projects/:id/milestones?state=closed +GET /projects/:id/milestones?title=1.0 +GET /projects/:id/milestones?search=version +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `iids[]` | 整数数组 | optional | 仅返回具有给定`iid`的里程碑 | +| `state` | string | optional | 仅返回`active`或`closed`里程碑 | +| `title` | string | optional | 仅返回具有给定`title`的里程碑 | +| `search` | string | optional | 仅返回标题或描述与提供的字符串匹配的里程碑 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/milestones" +``` + +示例响应: + +``` +[ { "id": 12, "iid": 3, "project_id": 16, "title": "10.0", "description": "Version", "due_date": "2013-11-29", "start_date": "2013-11-10", "state": "active", "updated_at": "2013-10-02T09:24:18Z", "created_at": "2013-10-02T09:24:18Z" } ] +``` + +## Get single milestone[](#get-single-milestone "Permalink") + +获得单个项目里程碑. + +``` +GET /projects/:id/milestones/:milestone_id +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID + +## Create new milestone[](#create-new-milestone "Permalink") + +创建一个新的项目里程碑. + +``` +POST /projects/:id/milestones +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `title` (必填)-里程碑的标题 +* `description` (可选)-里程碑的说明 +* `due_date` (可选)-里程碑的截止日期 +* `start_date` (可选)-里程碑的开始日期 + +## Edit milestone[](#edit-milestone "Permalink") + +更新现有项目的里程碑. + +``` +PUT /projects/:id/milestones/:milestone_id +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID +* `title` (可选)-里程碑的标题 +* `description` (可选)-里程碑的说明 +* `due_date` (可选)-里程碑的截止日期 +* `start_date` (可选)-里程碑的开始日期 +* `state_event` (可选)-里程碑的状态事件(关闭或激活) + +## Delete project milestone[](#delete-project-milestone "Permalink") + +仅适用于具有开发人员访问项目权限的用户. + +``` +DELETE /projects/:id/milestones/:milestone_id +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID + +## Get all issues assigned to a single milestone[](#get-all-issues-assigned-to-a-single-milestone "Permalink") + +获取分配给单个项目里程碑的所有问题. + +``` +GET /projects/:id/milestones/:milestone_id/issues +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID + +## Get all merge requests assigned to a single milestone[](#get-all-merge-requests-assigned-to-a-single-milestone "Permalink") + +获取分配给单个项目里程碑的所有合并请求. + +``` +GET /projects/:id/milestones/:milestone_id/merge_requests +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID + +## Promote project milestone to a group milestone[](#promote-project-milestone-to-a-group-milestone "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53861) + +仅针对具有开发者访问权限的用户. + +``` +POST /projects/:id/milestones/:milestone_id/promote +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID + +## Get all burndown chart events for a single milestone[](#get-all-burndown-chart-events-for-a-single-milestone-starter "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4737) + +获取单个里程碑的所有燃尽图事件. + +``` +GET /projects/:id/milestones/:milestone_id/burndown_events +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID \ No newline at end of file diff --git a/_book/docs/339.md b/_book/docs/339.md new file mode 100644 index 0000000000000000000000000000000000000000..721d2e5fec6d16859d54e4cc268d95e423ef882a --- /dev/null +++ b/_book/docs/339.md @@ -0,0 +1,167 @@ +# Group milestones API + +> 原文:[https://docs.gitlab.com/ee/api/group_milestones.html](https://docs.gitlab.com/ee/api/group_milestones.html) + +* [List group milestones](#list-group-milestones) +* [Get single milestone](#get-single-milestone) +* [Create new milestone](#create-new-milestone) +* [Edit milestone](#edit-milestone) +* [Delete group milestone](#delete-group-milestone) +* [Get all issues assigned to a single milestone](#get-all-issues-assigned-to-a-single-milestone) +* [Get all merge requests assigned to a single milestone](#get-all-merge-requests-assigned-to-a-single-milestone) +* [Get all burndown chart events for a single milestone](#get-all-burndown-chart-events-for-a-single-milestone-starter) + +# Group milestones API[](#group-milestones-api "Permalink") + +在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12819) . + +此页面描述了组里程碑 API. 有一个单独的[项目里程碑 API](./group_milestones.html)页面. + +## List group milestones[](#list-group-milestones "Permalink") + +返回组里程碑列表. + +``` +GET /groups/:id/milestones +GET /groups/:id/milestones?iids[]=42 +GET /groups/:id/milestones?iids[]=42&iids[]=43 +GET /groups/:id/milestones?state=active +GET /groups/:id/milestones?state=closed +GET /groups/:id/milestones?title=1.0 +GET /groups/:id/milestones?search=version +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的里程碑 | +| `state` | string | no | 仅返回`active`或`closed`里程碑 | +| `title` | string | no | 仅返回具有给定`title`的里程碑 | +| `search` | string | no | 仅返回标题或描述与提供的字符串匹配的里程碑 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/milestones" +``` + +示例响应: + +``` +[ { "id": 12, "iid": 3, "group_id": 16, "title": "10.0", "description": "Version", "due_date": "2013-11-29", "start_date": "2013-11-10", "state": "active", "updated_at": "2013-10-02T09:24:18Z", "created_at": "2013-10-02T09:24:18Z", "web_url": "https://gitlab.com/groups/gitlab-org/-/milestones/42" } ] +``` + +## Get single milestone[](#get-single-milestone "Permalink") + +获取单个组里程碑. + +``` +GET /groups/:id/milestones/:milestone_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `milestone_id` | integer | yes | 组里程碑的 ID | + +## Create new milestone[](#create-new-milestone "Permalink") + +创建一个新的组里程碑. + +``` +POST /groups/:id/milestones +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `title` | string | yes | 里程碑的标题 | +| `description` | string | no | 里程碑的描述 | +| `due_date` | date | no | 里程碑的到期日期,格式为 YYYY-MM-DD(ISO 8601) | +| `start_date` | date | no | 里程碑的开始日期,格式为 YYYY-MM-DD(ISO 8601) | + +## Edit milestone[](#edit-milestone "Permalink") + +更新现有的组里程碑. + +``` +PUT /groups/:id/milestones/:milestone_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `milestone_id` | integer | yes | 组里程碑的 ID | +| `title` | string | no | 里程碑的标题 | +| `description` | string | no | 里程碑的描述 | +| `due_date` | date | no | 里程碑的到期日期,格式为 YYYY-MM-DD(ISO 8601) | +| `start_date` | date | no | 里程碑的开始日期,格式为 YYYY-MM-DD(ISO 8601) | +| `state_event` | string | no | 里程碑的状态事件*( `close`或`activate` )* | + +## Delete group milestone[](#delete-group-milestone "Permalink") + +仅针对具有开发者访问权限的用户. + +``` +DELETE /groups/:id/milestones/:milestone_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `milestone_id` | integer | yes | 小组里程碑的 ID | + +## Get all issues assigned to a single milestone[](#get-all-issues-assigned-to-a-single-milestone "Permalink") + +获取分配给单个组里程碑的所有问题. + +``` +GET /groups/:id/milestones/:milestone_id/issues +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `milestone_id` | integer | yes | 组里程碑的 ID | + +## Get all merge requests assigned to a single milestone[](#get-all-merge-requests-assigned-to-a-single-milestone "Permalink") + +获取分配给单个组里程碑的所有合并请求. + +``` +GET /groups/:id/milestones/:milestone_id/merge_requests +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `milestone_id` | integer | yes | 组里程碑的 ID | + +## Get all burndown chart events for a single milestone[](#get-all-burndown-chart-events-for-a-single-milestone-starter "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4737) + +获取单个里程碑的所有燃尽图事件. + +``` +GET /groups/:id/milestones/:milestone_id/burndown_events +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `milestone_id` | integer | yes | 组里程碑的 ID | \ No newline at end of file diff --git a/_book/docs/340.md b/_book/docs/340.md new file mode 100644 index 0000000000000000000000000000000000000000..2170615597d2b0708c00b806690a5370b75ea665 --- /dev/null +++ b/_book/docs/340.md @@ -0,0 +1,103 @@ +# Namespaces API + +> 原文:[https://docs.gitlab.com/ee/api/namespaces.html](https://docs.gitlab.com/ee/api/namespaces.html) + +* [List namespaces](#list-namespaces) +* [Search for namespace](#search-for-namespace) +* [Get namespace by ID](#get-namespace-by-id) + +# Namespaces API[](#namespaces-api "Permalink") + +用户名和组名属于称为命名空间的特殊类别. + +对于用户和组支持的 API 调用,请分别参阅[用户](users.html)和[组](groups.html)文档. + +[使用分页](README.html#pagination) . + +## List namespaces[](#list-namespaces "Permalink") + +获取已认证用户的名称空间列表. 如果用户是管理员,则会显示 GitLab 实例中所有名称空间的列表. + +``` +GET /namespaces +``` + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/namespaces" +``` + +响应示例: + +``` +[ { "id": 1, "name": "user1", "path": "user1", "kind": "user", "full_path": "user1" }, { "id": 2, "name": "group1", "path": "group1", "kind": "group", "full_path": "group1", "parent_id": null, "members_count_with_descendants": 2 }, { "id": 3, "name": "bar", "path": "bar", "kind": "group", "full_path": "foo/bar", "parent_id": 9, "members_count_with_descendants": 5 } ] +``` + +GitLab.com [Bronze 或更高版本](https://about.gitlab.com/pricing/#gitlab-com)上的用户可能还会看到与名称空间关联的`plan`参数: + +``` +[ { "id": 1, "name": "user1", "plan": "bronze", ... } ] +``` + +**注意:**仅向组维护者/所有者提供了`members_count_with_descendants`和`plan` . + +## Search for namespace[](#search-for-namespace "Permalink") + +获取与名称或路径中的字符串匹配的所有名称空间. + +``` +GET /namespaces?search=foobar +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `search` | string | no | 返回基于搜索条件授权用户查看的名称空间列表 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/namespaces?search=twitter" +``` + +响应示例: + +``` +[ { "id": 4, "name": "twitter", "path": "twitter", "kind": "group", "full_path": "twitter", "parent_id": null, "members_count_with_descendants": 2 } ] +``` + +## Get namespace by ID[](#get-namespace-by-id "Permalink") + +通过 ID 获取名称空间. + +``` +GET /namespaces/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | [名称空间的](README.html#namespaced-path-encoding) ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/namespaces/2" +``` + +响应示例: + +``` +{ "id": 2, "name": "group1", "path": "group1", "kind": "group", "full_path": "group1", "parent_id": null, "members_count_with_descendants": 2 } +``` + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/namespaces/group1" +``` + +响应示例: + +``` +{ "id": 2, "name": "group1", "path": "group1", "kind": "group", "full_path": "group1", "parent_id": null, "members_count_with_descendants": 2 } +``` \ No newline at end of file diff --git a/_book/docs/341.md b/_book/docs/341.md new file mode 100644 index 0000000000000000000000000000000000000000..9395abce622f49c66c925d999bc879becd1ed20f --- /dev/null +++ b/_book/docs/341.md @@ -0,0 +1,456 @@ +# Notes API + +> 原文:[https://docs.gitlab.com/ee/api/notes.html](https://docs.gitlab.com/ee/api/notes.html) + +* [Notes pagination](#notes-pagination) +* [Issues](#issues) + * [List project issue notes](#list-project-issue-notes) + * [Get single issue note](#get-single-issue-note) + * [Create new issue note](#create-new-issue-note) + * [Modify existing issue note](#modify-existing-issue-note) + * [Delete an issue note](#delete-an-issue-note) +* [Snippets](#snippets) + * [List all snippet notes](#list-all-snippet-notes) + * [Get single snippet note](#get-single-snippet-note) + * [Create new snippet note](#create-new-snippet-note) + * [Modify existing snippet note](#modify-existing-snippet-note) + * [Delete a snippet note](#delete-a-snippet-note) +* [Merge Requests](#merge-requests) + * [List all merge request notes](#list-all-merge-request-notes) + * [Get single merge request note](#get-single-merge-request-note) + * [Create new merge request note](#create-new-merge-request-note) + * [Modify existing merge request note](#modify-existing-merge-request-note) + * [Delete a merge request note](#delete-a-merge-request-note) +* [Epics](#epics-ultimate) + * [List all epic notes](#list-all-epic-notes) + * [Get single epic note](#get-single-epic-note) + * [Create new epic note](#create-new-epic-note) + * [Modify existing epic note](#modify-existing-epic-note) + * [Delete an epic note](#delete-an-epic-note) + +# Notes API[](#notes-api "Permalink") + +注释是对以下内容的评论: + +* Snippets +* Issues +* 合并要求 +* Epics + +这包括系统注释,这些注释是有关对象更改的注释(例如,当里程碑更改时,将有相应的系统注释). 标签注释不是此 API 的一部分,而是在[资源标签事件中](resource_label_events.html)记录为单独的[事件](resource_label_events.html) . + +## Notes pagination[](#notes-pagination "Permalink") + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +## Issues[](#issues "Permalink") + +### List project issue notes[](#list-project-issue-notes "Permalink") + +获取单个问题的所有注释的列表. + +``` +GET /projects/:id/issues/:issue_iid/notes +GET /projects/:id/issues/:issue_iid/notes?sort=asc&order_by=updated_at +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `sort` | string | no | 返回按`asc`或`desc`排列的发行说明. 默认为`desc` | +| `order_by` | string | no | 返回按`created_at`或`updated_at`字段排序的发行说明. 默认为`created_at` | + +``` +[ { "id": 302, "body": "closed", "attachment": null, "author": { "id": 1, "username": "pipin", "email": "admin@example.com", "name": "Pip", "state": "active", "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T09:22:45Z", "updated_at": "2013-10-02T10:22:45Z", "system": true, "noteable_id": 377, "noteable_type": "Issue", "noteable_iid": 377, "resolvable": false, "confidential": false }, { "id": 305, "body": "Text of the comment\r\n", "attachment": null, "author": { "id": 1, "username": "pipin", "email": "admin@example.com", "name": "Pip", "state": "active", "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T09:56:03Z", "updated_at": "2013-10-02T09:56:03Z", "system": true, "noteable_id": 121, "noteable_type": "Issue", "noteable_iid": 121, "resolvable": false, "confidential": true } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/notes" +``` + +### Get single issue note[](#get-single-issue-note "Permalink") + +返回有关特定项目问题的单个注释 + +``` +GET /projects/:id/issues/:issue_iid/notes/:note_id +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `issue_iid` (必填)-项目问题的 IID +* `note_id` (必填)-问题注释的 ID + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/notes/1" +``` + +### Create new issue note[](#create-new-issue-note "Permalink") + +为单个项目问题创建新的注释. + +``` +POST /projects/:id/issues/:issue_iid/notes +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `issue_iid` (必填)-问题的 IID +* `body` (必填)-注释的内容. 限制为 1,000,000 个字符. +* `confidential` (可选)-便笺的机密标志. 默认为 false. +* `created_at` (可选)-日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/notes?body=note" +``` + +### Modify existing issue note[](#modify-existing-issue-note "Permalink") + +修改问题的现有注释. + +``` +PUT /projects/:id/issues/:issue_iid/notes/:note_id +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `issue_iid` (必填)-问题的 IID +* `note_id` (必填)-注释的 ID +* `body` (必填)-注释的内容. 限制为 1,000,000 个字符. + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/notes?body=note" +``` + +### Delete an issue note[](#delete-an-issue-note "Permalink") + +删除问题的现有注释. + +``` +DELETE /projects/:id/issues/:issue_iid/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `note_id` | integer | yes | 笔记的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/notes/636" +``` + +## Snippets[](#snippets "Permalink") + +### List all snippet notes[](#list-all-snippet-notes "Permalink") + +获取单个代码段的所有注释的列表. 片段注释是用户可以发布到片段的注释. + +``` +GET /projects/:id/snippets/:snippet_id/notes +GET /projects/:id/snippets/:snippet_id/notes?sort=asc&order_by=updated_at +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 项目代码段的 ID | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的`asc`注释. 默认为`desc` | +| `order_by` | string | no | 返回按`created_at`或`updated_at`字段排序的`created_at`注释. 默认为`created_at` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/notes" +``` + +### Get single snippet note[](#get-single-snippet-note "Permalink") + +返回给定片段的单个音符. + +``` +GET /projects/:id/snippets/:snippet_id/notes/:note_id +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-项目代码段的 ID +* `note_id` (必填)- `note_id`的 ID + +``` +{ "id": 52, "title": "Snippet", "file_name": "snippet.rb", "author": { "id": 1, "username": "pipin", "email": "admin@example.com", "name": "Pip", "state": "active", "created_at": "2013-09-30T13:46:01Z" }, "expires_at": null, "updated_at": "2013-10-02T07:34:20Z", "created_at": "2013-10-02T07:34:20Z" } +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/notes/11" +``` + +### Create new snippet note[](#create-new-snippet-note "Permalink") + +为单个代码段创建新的音符. 片段注释是用户可以发布到片段的注释. 如果您在主体仅包含奖励表情符号的位置创建注释,则会收到该对象的回信. + +``` +POST /projects/:id/snippets/:snippet_id/notes +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-代码段的 ID +* `body` (必填)-注释的内容. 限制为 1,000,000 个字符. +* `created_at` (可选)-日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippet/11/notes?body=note" +``` + +### Modify existing snippet note[](#modify-existing-snippet-note "Permalink") + +修改代码段的现有注释. + +``` +PUT /projects/:id/snippets/:snippet_id/notes/:note_id +``` + +Parameters: + +* `id` (required) - The ID or [URL-encoded path of the project](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-代码段的 ID +* `note_id` (必填)-注释的 ID +* `body` (必填)-注释的内容. 限制为 1,000,000 个字符. + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/notes?body=note" +``` + +### Delete a snippet note[](#delete-a-snippet-note "Permalink") + +删除片段的现有注释. + +``` +DELETE /projects/:id/snippets/:snippet_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | +| `note_id` | integer | yes | 笔记的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/52/notes/1659" +``` + +## Merge Requests[](#merge-requests "Permalink") + +### List all merge request notes[](#list-all-merge-request-notes "Permalink") + +获取单个合并请求的所有注释的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/notes +GET /projects/:id/merge_requests/:merge_request_iid/notes?sort=asc&order_by=updated_at +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 项目合并请求的 IID | +| `sort` | string | no | 返回以`asc`或`desc`顺序排序的合并请求注释. 默认为`desc` | +| `order_by` | string | no | 返回由`created_at`或`updated_at`字段排序的合并请求注释. 默认为`created_at` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes" +``` + +### Get single merge request note[](#get-single-merge-request-note "Permalink") + +返回给定合并请求的单个注释. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/notes/:note_id +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必填)-项目合并请求的 IID +* `note_id` (必需)-合并请求注释的 ID + +``` +{ "id": 301, "body": "Comment for MR", "attachment": null, "author": { "id": 1, "username": "pipin", "email": "admin@example.com", "name": "Pip", "state": "active", "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T08:57:14Z", "updated_at": "2013-10-02T08:57:14Z", "system": false, "noteable_id": 2, "noteable_type": "MergeRequest", "noteable_iid": 2, "resolvable": false, "confidential": false } +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes/1" +``` + +### Create new merge request note[](#create-new-merge-request-note "Permalink") + +为单个合并请求创建一个新注释. 如果您在主体仅包含奖励表情符号的位置创建注释,则会收到该对象的回信. + +``` +POST /projects/:id/merge_requests/:merge_request_iid/notes +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必填)-合并请求的 IID +* `body` (必填)-注释的内容. 限制为 1,000,000 个字符. +* `created_at` (可选)-日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z + +### Modify existing merge request note[](#modify-existing-merge-request-note "Permalink") + +修改合并请求的现有注释. + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/notes/:note_id +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必填)-合并请求的 IID +* `note_id` (必填)-注释的 ID +* `body` (必填)-注释的内容. 限制为 1,000,000 个字符. + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes?body=note" +``` + +### Delete a merge request note[](#delete-a-merge-request-note "Permalink") + +删除合并请求的现有注释. + +``` +DELETE /projects/:id/merge_requests/:merge_request_iid/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `note_id` | integer | yes | 笔记的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/7/notes/1602" +``` + +## Epics[](#epics-ultimate "Permalink") + +### List all epic notes[](#list-all-epic-notes "Permalink") + +获取单个史诗的所有注释的列表. 史诗笔记是用户可以发布到史诗中的评论. + +``` +GET /groups/:id/epics/:epic_id/notes +GET /groups/:id/epics/:epic_id/notes?sort=asc&order_by=updated_at +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 小组史诗的 ID | +| `sort` | string | no | 返回按`asc`或`desc`排列的史诗笔记. 默认为`desc` | +| `order_by` | string | no | 返回按`created_at`或`updated_at`字段排序的史诗笔记. 默认为`created_at` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/notes" +``` + +### Get single epic note[](#get-single-epic-note "Permalink") + +返回给定史诗的单个音符. + +``` +GET /groups/:id/epics/:epic_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `note_id` | integer | yes | 笔记的 ID | + +``` +{ "id": 52, "title": "Epic", "file_name": "epic.rb", "author": { "id": 1, "username": "pipin", "email": "admin@example.com", "name": "Pip", "state": "active", "created_at": "2013-09-30T13:46:01Z" }, "expires_at": null, "updated_at": "2013-10-02T07:34:20Z", "created_at": "2013-10-02T07:34:20Z", "confidential": false } +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/notes/1" +``` + +### Create new epic note[](#create-new-epic-note "Permalink") + +为单个史诗创建新的音符. 史诗笔记是用户可以发布到史诗中的评论. 如果您在主体仅包含奖励表情符号的位置创建注释,则会收到该对象的回信. + +``` +POST /groups/:id/epics/:epic_id/notes +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `body` | string | yes | 注释的内容. 限制为 1,000,000 个字符. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippet/11/notes?body=note" +``` + +### Modify existing epic note[](#modify-existing-epic-note "Permalink") + +修改史诗的现有注释. + +``` +PUT /groups/:id/epics/:epic_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `note_id` | integer | yes | 笔记的 ID | +| `body` | string | yes | 注释的内容. 限制为 1,000,000 个字符. | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippet/11/notes?body=note" +``` + +### Delete an epic note[](#delete-an-epic-note "Permalink") + +删除史诗的现有音符. + +``` +DELETE /groups/:id/epics/:epic_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `note_id` | integer | yes | 笔记的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/52/notes/1659" +``` \ No newline at end of file diff --git a/_book/docs/342.md b/_book/docs/342.md new file mode 100644 index 0000000000000000000000000000000000000000..de74ec9ec0f0e0ba3ef18d12d4ffc9151d18478f --- /dev/null +++ b/_book/docs/342.md @@ -0,0 +1,173 @@ +# Notification settings API + +> 原文:[https://docs.gitlab.com/ee/api/notification_settings.html](https://docs.gitlab.com/ee/api/notification_settings.html) + +* [Valid notification levels](#valid-notification-levels) +* [Global notification settings](#global-notification-settings) +* [Update global notification settings](#update-global-notification-settings) +* [Group / project level notification settings](#group--project-level-notification-settings) +* [Update group/project level notification settings](#update-groupproject-level-notification-settings) + +# Notification settings API[](#notification-settings-api "Permalink") + +在 GitLab 8.12 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5632) . + +## Valid notification levels[](#valid-notification-levels "Permalink") + +通知级别在`NotificationSetting.level`模型枚举中定义. 当前,这些级别被认可: + +``` +disabled +participating +watch +global +mention +custom +``` + +如果使用`custom`级别,则可以控制特定的电子邮件事件. 可用事件由`NotificationSetting.email_events`返回. 当前,这些事件被认可: + +* `new_note` +* `new_issue` +* `reopen_issue` +* `close_issue` +* `reassign_issue` +* `issue_due` +* `new_merge_request` +* `push_to_merge_request` +* `reopen_merge_request` +* `close_merge_request` +* `reassign_merge_request` +* `merge_merge_request` +* `failed_pipeline` +* `fixed_pipeline` +* `success_pipeline` +* `new_epic` + +## Global notification settings[](#global-notification-settings "Permalink") + +获取当前的通知设置和电子邮件地址. + +``` +GET /notification_settings +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/notification_settings" +``` + +响应示例: + +``` +{ "level": "participating", "notification_email": "admin@example.com" } +``` + +## Update global notification settings[](#update-global-notification-settings "Permalink") + +更新当前的通知设置和电子邮件地址. + +``` +PUT /notification_settings +``` + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/notification_settings?level=watch" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `level` | string | no | 全局通知级别 | +| `notification_email` | string | no | 发送通知的电子邮件地址 | +| `new_note` | boolean | no | 启用/禁用此通知 | +| `new_issue` | boolean | no | 启用/禁用此通知 | +| `reopen_issue` | boolean | no | 启用/禁用此通知 | +| `close_issue` | boolean | no | 启用/禁用此通知 | +| `reassign_issue` | boolean | no | 启用/禁用此通知 | +| `issue_due` | boolean | no | 启用/禁用此通知 | +| `new_merge_request` | boolean | no | 启用/禁用此通知 | +| `push_to_merge_request` | boolean | no | 启用/禁用此通知 | +| `reopen_merge_request` | boolean | no | 启用/禁用此通知 | +| `close_merge_request` | boolean | no | 启用/禁用此通知 | +| `reassign_merge_request` | boolean | no | 启用/禁用此通知 | +| `merge_merge_request` | boolean | no | 启用/禁用此通知 | +| `failed_pipeline` | boolean | no | 启用/禁用此通知 | +| `fixed_pipeline` | boolean | no | 启用/禁用此通知 | +| `success_pipeline` | boolean | no | 启用/禁用此通知 | +| `new_epic` | boolean | no | 启用/禁用此通知(在 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6626) ) | + +响应示例: + +``` +{ "level": "watch", "notification_email": "admin@example.com" } +``` + +## Group / project level notification settings[](#group--project-level-notification-settings "Permalink") + +获取当前的组或项目通知设置. + +``` +GET /groups/:id/notification_settings +GET /projects/:id/notification_settings +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/notification_settings" +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/8/notification_settings" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组/项目 ID 或路径 | + +响应示例: + +``` +{ "level": "global" } +``` + +## Update group/project level notification settings[](#update-groupproject-level-notification-settings "Permalink") + +更新当前的组/项目通知设置. + +``` +PUT /groups/:id/notification_settings +PUT /projects/:id/notification_settings +``` + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/notification_settings?level=watch" +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/8/notification_settings?level=custom&new_note=true" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组/项目 ID 或路径 | +| `level` | string | no | 全局通知级别 | +| `new_note` | boolean | no | 启用/禁用此通知 | +| `new_issue` | boolean | no | 启用/禁用此通知 | +| `reopen_issue` | boolean | no | 启用/禁用此通知 | +| `close_issue` | boolean | no | 启用/禁用此通知 | +| `reassign_issue` | boolean | no | 启用/禁用此通知 | +| `issue_due` | boolean | no | 启用/禁用此通知 | +| `new_merge_request` | boolean | no | 启用/禁用此通知 | +| `push_to_merge_request` | boolean | no | 启用/禁用此通知 | +| `reopen_merge_request` | boolean | no | 启用/禁用此通知 | +| `close_merge_request` | boolean | no | 启用/禁用此通知 | +| `reassign_merge_request` | boolean | no | 启用/禁用此通知 | +| `merge_merge_request` | boolean | no | 启用/禁用此通知 | +| `failed_pipeline` | boolean | no | 启用/禁用此通知 | +| `fixed_pipeline` | boolean | no | 启用/禁用此通知 | +| `success_pipeline` | boolean | no | 启用/禁用此通知 | +| `new_epic` | boolean | no | 启用/禁用此通知(在 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6626) ) | + +响应示例: + +``` +{ "level": "watch" } { "level": "custom", "events": { "new_note": true, "new_issue": false, "reopen_issue": false, "close_issue": false, "reassign_issue": false, "issue_due": false, "new_merge_request": false, "push_to_merge_request": false, "reopen_merge_request": false, "close_merge_request": false, "reassign_merge_request": false, "merge_merge_request": false, "failed_pipeline": false, "fixed_pipeline": false, "success_pipeline": false } } +``` + +使用 GitLab [Ultimate 或 Gold 的](https://about.gitlab.com/pricing/)用户还将看到`new_epic`参数: + +``` +{ "level": "custom", "events": { "new_note": true, "new_issue": false, "new_epic": false, ... } } +``` \ No newline at end of file diff --git a/_book/docs/343.md b/_book/docs/343.md new file mode 100644 index 0000000000000000000000000000000000000000..85f49c8547788c6e156a22688e32a2140a5ed980 --- /dev/null +++ b/_book/docs/343.md @@ -0,0 +1,167 @@ +# Packages API + +> 原文:[https://docs.gitlab.com/ee/api/packages.html](https://docs.gitlab.com/ee/api/packages.html) + +* [List packages](#list-packages) + * [Within a project](#within-a-project) + * [Within a group](#within-a-group) +* [Get a project package](#get-a-project-package) +* [List package files](#list-package-files) +* [Delete a project package](#delete-a-project-package) + +# Packages API[](#packages-api-premium "Permalink") + +这是[GitLab 软件包](../administration/packages/index.html)的 API 文档. + +## List packages[](#list-packages "Permalink") + +### Within a project[](#within-a-project "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9259) . + +获取项目包列表. 结果中包括所有包装类型. 在未经身份验证的情况下访问时,仅返回公共项目的软件包. + +``` +GET /projects/:id/packages +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `order_by` | string | no | 用作订单的字段. `created_at` (默认), `name` , `version`或`type` . | +| `sort` | string | no | 顺序的方向, `asc` (默认)或`desc` (降序). | +| `package_type` | string | no | 按类型过滤返回的软件包. `conan` , `maven` , `npm` , `pypi` , `composer`或`nuget` . ( *在 GitLab 12.9 中引入* ) | +| `package_name` | string | no | 按名称用模糊搜索过滤项目包. ( *在 GitLab 12.9 中引入* ) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/packages" +``` + +响应示例: + +``` +[ { "id": 1, "name": "com/mycompany/my-app", "version": "1.0-SNAPSHOT", "package_type": "maven", "created_at": "2019-11-27T03:37:38.711Z" }, { "id": 2, "name": "@foo/bar", "version": "1.0.3", "package_type": "npm", "created_at": "2019-11-27T03:37:38.711Z" } ] +``` + +默认情况下,由于 API 是[分页的](README.html#pagination) ,因此`GET`请求将返回 20 个结果. + +### Within a group[](#within-a-group "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18871) . + +获取组级别的项目包列表. 在未经身份验证的情况下访问时,仅返回公共项目的软件包. + +``` +GET /groups/:id/packages +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | [群组的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `exclude_subgroups` | boolean | false | 如果参数包含为 true,则不列出子组中项目的软件包. 默认值为`false` . | +| `order_by` | string | no | 用作订单的字段. `created_at` (默认), `name` , `version` , `type`或`project_path` . | +| `sort` | string | no | 顺序的方向, `asc` (默认)或`desc` (降序). | +| `package_type` | string | no | 按类型过滤返回的软件包. `conan` , `maven` , `npm` , `pypi` , `composer`或`nuget` . ( *在 GitLab 12.9 中引入* ) | +| `package_name` | string | no | 按名称用模糊搜索过滤项目包. ( *在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30980)* ) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/packages?exclude_subgroups=true" +``` + +**弃用:>**的`build_info`在响应属性赞成不赞成`pipeline` . >引入了[GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040) . + +响应示例: + +``` +[ { "id": 1, "name": "com/mycompany/my-app", "version": "1.0-SNAPSHOT", "package_type": "maven", "_links": { "web_path": "/namespace1/project1/-/packages/1", "delete_api_path": "/namespace1/project1/-/packages/1" }, "created_at": "2019-11-27T03:37:38.711Z", "pipeline": { "id": 123, "status": "pending", "ref": "new-pipeline", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "web_url": "https://example.com/foo/bar/pipelines/47", "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "user": { "name": "Administrator", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" } } }, { "id": 2, "name": "@foo/bar", "version": "1.0.3", "package_type": "npm", "_links": { "web_path": "/namespace1/project1/-/packages/1", "delete_api_path": "/namespace1/project1/-/packages/1" }, "created_at": "2019-11-27T03:37:38.711Z", "pipeline": { "id": 123, "status": "pending", "ref": "new-pipeline", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "web_url": "https://example.com/foo/bar/pipelines/47", "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "user": { "name": "Administrator", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" } } } ] +``` + +默认情况下,由于 API 是[分页的](README.html#pagination) ,因此`GET`请求将返回 20 个结果. + +`_links`对象包含以下属性: + +* `web_path` :您可以在 GitLab 中访问并查看软件包详细信息的路径. +* `delete_api_path` :删除程序包的 API 路径. 仅在请求用户有权执行此操作时可用. + +## Get a project package[](#get-a-project-package "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9667) . + +获得一个项目包. + +``` +GET /projects/:id/packages/:package_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `package_id` | integer | yes | 包裹的 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/packages/:package_id" +``` + +**弃用:>**的`build_info`在响应属性赞成不赞成`pipeline` . >引入了[GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040) . + +Example response: + +``` +{ "id": 1, "name": "com/mycompany/my-app", "version": "1.0-SNAPSHOT", "package_type": "maven", "_links": { "web_path": "/namespace1/project1/-/packages/1", "delete_api_path": "/namespace1/project1/-/packages/1" }, "created_at": "2019-11-27T03:37:38.711Z", "pipeline": { "id": 123, "status": "pending", "ref": "new-pipeline", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "web_url": "https://example.com/foo/bar/pipelines/47", "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "user": { "name": "Administrator", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" } }, "versions": [ { "id":2, "version":"2.0-SNAPSHOT", "created_at":"2020-04-28T04:42:11.573Z", "pipeline": { "id": 234, "status": "pending", "ref": "new-pipeline", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "web_url": "https://example.com/foo/bar/pipelines/58", "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "user": { "name": "Administrator", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" } } } ] } +``` + +`_links`对象包含以下属性: + +* `web_path` :您可以在 GitLab 中访问并查看软件包详细信息的路径. +* `delete_api_path` :删除程序包的 API 路径. 仅在请求用户有权执行此操作时可用. + +## List package files[](#list-package-files "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9305) . + +获取单个软件包的软件包文件列表. + +``` +GET /projects/:id/packages/:package_id/package_files +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `package_id` | integer | yes | 包裹的 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/packages/4/package_files" +``` + +响应示例: + +``` +[ { "id": 25, "package_id": 4, "created_at": "2018-11-07T15:25:52.199Z", "file_name": "my-app-1.5-20181107.152550-1.jar", "size": 2421, "file_md5": "58e6a45a629910c6ff99145a688971ac", "file_sha1": "ebd193463d3915d7e22219f52740056dfd26cbfe" }, { "id": 26, "package_id": 4, "created_at": "2018-11-07T15:25:56.776Z", "file_name": "my-app-1.5-20181107.152550-1.pom", "size": 1122, "file_md5": "d90f11d851e17c5513586b4a7e98f1b2", "file_sha1": "9608d068fe88aff85781811a42f32d97feb440b5" }, { "id": 27, "package_id": 4, "created_at": "2018-11-07T15:26:00.556Z", "file_name": "maven-metadata.xml", "size": 767, "file_md5": "6dfd0cce1203145a927fef5e3a1c650c", "file_sha1": "d25932de56052d320a8ac156f745ece73f6a8cd2" } ] +``` + +默认情况下,由于 API 是[分页的](README.html#pagination) ,因此`GET`请求将返回 20 个结果. + +## Delete a project package[](#delete-a-project-package "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9623) . + +删除项目包. + +``` +DELETE /projects/:id/packages/:package_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `package_id` | integer | yes | 包裹的 ID. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/packages/:package_id" +``` + +可以返回以下状态码: + +* `204 No Content` ,如果软件包已成功删除. +* `404 Not Found` ,如果`404 Not Found`包. \ No newline at end of file diff --git a/_book/docs/344.md b/_book/docs/344.md new file mode 100644 index 0000000000000000000000000000000000000000..01dd248ad230e6d4af8f2eca03b7d62cda7422ab --- /dev/null +++ b/_book/docs/344.md @@ -0,0 +1,185 @@ +# Pages domains API + +> 原文:[https://docs.gitlab.com/ee/api/pages_domains.html](https://docs.gitlab.com/ee/api/pages_domains.html) + +* [List all pages domains](#list-all-pages-domains) +* [List pages domains](#list-pages-domains) +* [Single pages domain](#single-pages-domain) +* [Create new pages domain](#create-new-pages-domain) +* [Update pages domain](#update-pages-domain) + * [Adding certificate](#adding-certificate) + * [Enabling Let’s Encrypt integration for Pages custom domains](#enabling-lets-encrypt-integration-for-pages-custom-domains) + * [Removing certificate](#removing-certificate) +* [Delete pages domain](#delete-pages-domain) + +# Pages domains API[](#pages-domains-api "Permalink") + +在[GitLab Pages 中](https://about.gitlab.com/stages-devops-lifecycle/pages/)连接自定义域和 TLS 证书的端点. + +必须启用 GitLab 页面功能才能使用这些端点. 了解有关[管理](../administration/pages/index.html)和[使用](../user/project/pages/index.html)功能的更多信息. + +## List all pages domains[](#list-all-pages-domains "Permalink") + +获取所有页面域的列表. 用户必须具有管理员权限. + +``` +GET /pages/domains +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/pages/domains" +``` + +``` +[ { "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "project_id": 1337, "auto_ssl_enabled": false, "certificate": { "expired": false, "expiration": "2020-04-12T14:32:00.000Z" } } ] +``` + +## List pages domains[](#list-pages-domains "Permalink") + +Get a list of project pages domains. The user must have permissions to view pages domains. + +``` +GET /projects/:id/pages/domains +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/pages/domains" +``` + +``` +[ { "domain": "www.domain.example", "url": "http://www.domain.example" }, { "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "auto_ssl_enabled": false, "certificate": { "subject": "/O=Example, Inc./OU=Example Origin CA/CN=Example Origin Certificate", "expired": false, "certificate": "-----BEGIN CERTIFICATE-----\n … \n-----END CERTIFICATE-----", "certificate_text": "Certificate:\n … \n" } } ] +``` + +## Single pages domain[](#single-pages-domain "Permalink") + +获取单个项目页面域. 用户必须具有查看页面域的权限. + +``` +GET /projects/:id/pages/domains/:domain +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `domain` | string | yes | 用户指定的自定义域 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/pages/domains/www.domain.example" +``` + +``` +{ "domain": "www.domain.example", "url": "http://www.domain.example" } +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example" +``` + +``` +{ "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "auto_ssl_enabled": false, "certificate": { "subject": "/O=Example, Inc./OU=Example Origin CA/CN=Example Origin Certificate", "expired": false, "certificate": "-----BEGIN CERTIFICATE-----\n … \n-----END CERTIFICATE-----", "certificate_text": "Certificate:\n … \n" } } +``` + +## Create new pages domain[](#create-new-pages-domain "Permalink") + +创建一个新的页面域. 用户必须具有创建新页面域的权限. + +``` +POST /projects/:id/pages/domains +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `domain` | string | yes | 用户指定的自定义域 | +| `auto_ssl_enabled` | boolean | no | 启用[自动生成](../user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html)由 Let's Encrypt 为自定义域颁发的 SSL 证书的功能. | +| `certificate` | file/string | no | PEM 格式的证书,其中的中间体按照从最高到最低的顺序排列. | +| `key` | file/string | no | PEM 格式的证书密钥. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "domain=ssl.domain.example" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" "https://gitlab.example.com/api/v4/projects/5/pages/domains" +``` + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "domain=ssl.domain.example" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" "https://gitlab.example.com/api/v4/projects/5/pages/domains" +``` + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "domain=ssl.domain.example" --form "auto_ssl_enabled=true" "https://gitlab.example.com/api/v4/projects/5/pages/domains" +``` + +``` +{ "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "auto_ssl_enabled": true, "certificate": { "subject": "/O=Example, Inc./OU=Example Origin CA/CN=Example Origin Certificate", "expired": false, "certificate": "-----BEGIN CERTIFICATE-----\n … \n-----END CERTIFICATE-----", "certificate_text": "Certificate:\n … \n" } } +``` + +## Update pages domain[](#update-pages-domain "Permalink") + +更新现有的项目页面域. 用户必须具有更改现有页面域的权限. + +``` +PUT /projects/:id/pages/domains/:domain +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `domain` | string | yes | 用户指定的自定义域 | +| `auto_ssl_enabled` | boolean | no | 启用[自动生成](../user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html)由 Let's Encrypt 为自定义域颁发的 SSL 证书的功能. | +| `certificate` | file/string | no | PEM 格式的证书,其中的中间体按照从最高到最低的顺序排列. | +| `key` | file/string | no | PEM 格式的证书密钥. | + +### Adding certificate[](#adding-certificate "Permalink") + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example" +``` + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example" +``` + +``` +{ "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "auto_ssl_enabled": false, "certificate": { "subject": "/O=Example, Inc./OU=Example Origin CA/CN=Example Origin Certificate", "expired": false, "certificate": "-----BEGIN CERTIFICATE-----\n … \n-----END CERTIFICATE-----", "certificate_text": "Certificate:\n … \n" } } +``` + +### Enabling Let’s Encrypt integration for Pages custom domains[](#enabling-lets-encrypt-integration-for-pages-custom-domains "Permalink") + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form "auto_ssl_enabled=true" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example" +``` + +``` +{ "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "auto_ssl_enabled": true } +``` + +### Removing certificate[](#removing-certificate "Permalink") + +要删除附加到 Pages 域的 SSL 证书,请运行: + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form "certificate=" --form "key=" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example" +``` + +``` +{ "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "auto_ssl_enabled": false } +``` + +## Delete pages domain[](#delete-pages-domain "Permalink") + +删除现有的项目页面域. + +``` +DELETE /projects/:id/pages/domains/:domain +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `domain` | string | yes | 用户指定的自定义域 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example" +``` \ No newline at end of file diff --git a/_book/docs/345.md b/_book/docs/345.md new file mode 100644 index 0000000000000000000000000000000000000000..7d7636528a65edc9172ce2a147817b2f9d36ba74 --- /dev/null +++ b/_book/docs/345.md @@ -0,0 +1,255 @@ +# Pipeline schedules API + +> 原文:[https://docs.gitlab.com/ee/api/pipeline_schedules.html](https://docs.gitlab.com/ee/api/pipeline_schedules.html) + +* [Get all pipeline schedules](#get-all-pipeline-schedules) +* [Get a single pipeline schedule](#get-a-single-pipeline-schedule) +* [Create a new pipeline schedule](#create-a-new-pipeline-schedule) +* [Edit a pipeline schedule](#edit-a-pipeline-schedule) +* [Take ownership of a pipeline schedule](#take-ownership-of-a-pipeline-schedule) +* [Delete a pipeline schedule](#delete-a-pipeline-schedule) +* [Run a scheduled pipeline immediately](#run-a-scheduled-pipeline-immediately) +* [Pipeline schedule variables](#pipeline-schedule-variables) +* [Create a new pipeline schedule variable](#create-a-new-pipeline-schedule-variable) +* [Edit a pipeline schedule variable](#edit-a-pipeline-schedule-variable) +* [Delete a pipeline schedule variable](#delete-a-pipeline-schedule-variable) + +# Pipeline schedules API[](#pipeline-schedules-api "Permalink") + +您可以阅读有关[管道计划的](../ci/pipelines/schedules.html)更多信息. + +## Get all pipeline schedules[](#get-all-pipeline-schedules "Permalink") + +获取项目的管道时间表的列表. + +``` +GET /projects/:id/pipeline_schedules +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.html#namespaced-path-encoding) owned by the authenticated user | +| `scope` | string | no | 管道计划的范围,其中之一: `active` , `inactive` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules" +``` + +``` +[ { "id": 13, "description": "Test schedule pipeline", "ref": "master", "cron": "* * * * *", "cron_timezone": "Asia/Tokyo", "next_run_at": "2017-05-19T13:41:00.000Z", "active": true, "created_at": "2017-05-19T13:31:08.849Z", "updated_at": "2017-05-19T13:40:17.727Z", "owner": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" } } ] +``` + +## Get a single pipeline schedule[](#get-a-single-pipeline-schedule "Permalink") + +获取项目的管道计划. + +``` +GET /projects/:id/pipeline_schedules/:pipeline_schedule_id +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13" +``` + +``` +{ "id": 13, "description": "Test schedule pipeline", "ref": "master", "cron": "* * * * *", "cron_timezone": "Asia/Tokyo", "next_run_at": "2017-05-19T13:41:00.000Z", "active": true, "created_at": "2017-05-19T13:31:08.849Z", "updated_at": "2017-05-19T13:40:17.727Z", "last_pipeline": { "id": 332, "sha": "0e788619d0b5ec17388dffb973ecd505946156db", "ref": "master", "status": "pending" }, "owner": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "variables": [ { "key": "TEST_VARIABLE_1", "variable_type": "env_var", "value": "TEST_1" } ] } +``` + +## Create a new pipeline schedule[](#create-a-new-pipeline-schedule "Permalink") + +创建一个新的项目管道计划. + +``` +POST /projects/:id/pipeline_schedules +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `description` | string | yes | 管道进度表的描述 | +| `ref` | string | yes | 分支/标签名称将被触发 | +| `cron` | string | yes | cron(例如`0 1 * * *` )( [Cron 语法](https://en.wikipedia.org/wiki/Cron) ) | +| `cron_timezone` | string | no | `ActiveSupport::TimeZone`支持的时`ActiveSupport::TimeZone` (例如`Pacific Time (US & Canada)` )(默认值: `'UTC'` ) | +| `active` | boolean | no | 激活管道计划. 如果设置为 false,则管道调度最初将被停用(默认值: `true` ) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form description="Build packages" --form ref="master" --form cron="0 1 * * 5" --form cron_timezone="UTC" --form active="true" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules" +``` + +``` +{ "id": 14, "description": "Build packages", "ref": "master", "cron": "0 1 * * 5", "cron_timezone": "UTC", "next_run_at": "2017-05-26T01:00:00.000Z", "active": true, "created_at": "2017-05-19T13:43:08.169Z", "updated_at": "2017-05-19T13:43:08.169Z", "last_pipeline": null, "owner": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" } } +``` + +## Edit a pipeline schedule[](#edit-a-pipeline-schedule "Permalink") + +更新项目的管道计划. 更新完成后,将自动重新安排. + +``` +PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | +| `description` | string | no | 管道进度表的描述 | +| `ref` | string | no | 分支/标签名称将被触发 | +| `cron` | string | no | cron(例如`0 1 * * *` )( [Cron 语法](https://en.wikipedia.org/wiki/Cron) ) | +| `cron_timezone` | string | no | `ActiveSupport::TimeZone` (例如`Pacific Time (US & Canada)` )或`TZInfo::Timezone` (例如`America/Los_Angeles` )支持的`TZInfo::Timezone` | +| `active` | boolean | no | 激活管道计划. 如果设置为 false,则管道计划将首先停用. | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form cron="0 2 * * *" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13" +``` + +``` +{ "id": 13, "description": "Test schedule pipeline", "ref": "master", "cron": "0 2 * * *", "cron_timezone": "Asia/Tokyo", "next_run_at": "2017-05-19T17:00:00.000Z", "active": true, "created_at": "2017-05-19T13:31:08.849Z", "updated_at": "2017-05-19T13:44:16.135Z", "last_pipeline": { "id": 332, "sha": "0e788619d0b5ec17388dffb973ecd505946156db", "ref": "master", "status": "pending" }, "owner": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" } } +``` + +## Take ownership of a pipeline schedule[](#take-ownership-of-a-pipeline-schedule "Permalink") + +更新项目的管道计划的所有者. + +``` +POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/take_ownership +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/take_ownership" +``` + +``` +{ "id": 13, "description": "Test schedule pipeline", "ref": "master", "cron": "0 2 * * *", "cron_timezone": "Asia/Tokyo", "next_run_at": "2017-05-19T17:00:00.000Z", "active": true, "created_at": "2017-05-19T13:31:08.849Z", "updated_at": "2017-05-19T13:46:37.468Z", "last_pipeline": { "id": 332, "sha": "0e788619d0b5ec17388dffb973ecd505946156db", "ref": "master", "status": "pending" }, "owner": { "name": "shinya", "username": "maeda", "id": 50, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/8ca0a796a679c292e3a11da50f99e801?s=80&d=identicon", "web_url": "https://gitlab.example.com/maeda" } } +``` + +## Delete a pipeline schedule[](#delete-a-pipeline-schedule "Permalink") + +删除项目的管道计划. + +``` +DELETE /projects/:id/pipeline_schedules/:pipeline_schedule_id +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13" +``` + +``` +{ "id": 13, "description": "Test schedule pipeline", "ref": "master", "cron": "0 2 * * *", "cron_timezone": "Asia/Tokyo", "next_run_at": "2017-05-19T17:00:00.000Z", "active": true, "created_at": "2017-05-19T13:31:08.849Z", "updated_at": "2017-05-19T13:46:37.468Z", "last_pipeline": { "id": 332, "sha": "0e788619d0b5ec17388dffb973ecd505946156db", "ref": "master", "status": "pending" }, "owner": { "name": "shinya", "username": "maeda", "id": 50, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/8ca0a796a679c292e3a11da50f99e801?s=80&d=identicon", "web_url": "https://gitlab.example.com/maeda" } } +``` + +## Run a scheduled pipeline immediately[](#run-a-scheduled-pipeline-immediately "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/201786) . + +触发一个新的计划管道,该管道将立即运行. 该管道的下一个计划运行不受影响. + +``` +POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/play +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/42/pipeline_schedules/1/play" +``` + +响应示例: + +``` +{ "message": "201 Created" } +``` + +## Pipeline schedule variables[](#pipeline-schedule-variables "Permalink") + +在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34518) . + +## Create a new pipeline schedule variable[](#create-a-new-pipeline-schedule-variable "Permalink") + +创建管道计划的新变量. + +``` +POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | +| `key` | string | yes | 变量的`key` ; 不得超过 255 个字符; 仅允许`AZ` , `az` , `0-9`和`_` | +| `value` | string | yes | 变量的`value` | +| `variable_type` | string | no | 变量的类型. 可用类型为: `env_var` (默认)和`file` | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "key=NEW_VARIABLE" --form "value=new value" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables" +``` + +``` +{ "key": "NEW_VARIABLE", "variable_type": "env_var", "value": "new value" } +``` + +## Edit a pipeline schedule variable[](#edit-a-pipeline-schedule-variable "Permalink") + +更新管道计划的变量. + +``` +PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | +| `key` | string | yes | 变量的`key` | +| `value` | string | yes | 变量的`value` | +| `variable_type` | string | no | 变量的类型. 可用类型为: `env_var` (默认)和`file` | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form "value=updated value" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables/NEW_VARIABLE" +``` + +``` +{ "key": "NEW_VARIABLE", "value": "updated value" "variable_type": "env_var", } +``` + +## Delete a pipeline schedule variable[](#delete-a-pipeline-schedule-variable "Permalink") + +删除管道计划的变量. + +``` +DELETE /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | +| `key` | string | yes | 变量的`key` | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables/NEW_VARIABLE" +``` + +``` +{ "key": "NEW_VARIABLE", "value": "updated value" } +``` \ No newline at end of file diff --git a/_book/docs/346.md b/_book/docs/346.md new file mode 100644 index 0000000000000000000000000000000000000000..3d496d731698bc2143362b3049c45f002f7b233f --- /dev/null +++ b/_book/docs/346.md @@ -0,0 +1,114 @@ +# Pipeline triggers API + +> 原文:[https://docs.gitlab.com/ee/api/pipeline_triggers.html](https://docs.gitlab.com/ee/api/pipeline_triggers.html) + +* [List project triggers](#list-project-triggers) +* [Get trigger details](#get-trigger-details) +* [Create a project trigger](#create-a-project-trigger) +* [Update a project trigger](#update-a-project-trigger) +* [Remove a project trigger](#remove-a-project-trigger) + +# Pipeline triggers API[](#pipeline-triggers-api "Permalink") + +您可以阅读有关[通过 API 触发管道的](../ci/triggers/README.html)更多信息. + +## List project triggers[](#list-project-triggers "Permalink") + +获取项目的构建触发器的列表. + +``` +GET /projects/:id/triggers +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/triggers" +``` + +``` +[ { "id": 10, "description": "my trigger", "created_at": "2016-01-07T09:53:58.235Z", "last_used": null, "token": "6d056f63e50fe6f8c5f8f4aa10edb7", "updated_at": "2016-01-07T09:53:58.235Z", "owner": null } ] +``` + +## Get trigger details[](#get-trigger-details "Permalink") + +获取项目构建触发器的详细信息. + +``` +GET /projects/:id/triggers/:trigger_id +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `trigger_id` | integer | yes | 触发 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/triggers/5" +``` + +``` +{ "id": 10, "description": "my trigger", "created_at": "2016-01-07T09:53:58.235Z", "last_used": null, "token": "6d056f63e50fe6f8c5f8f4aa10edb7", "updated_at": "2016-01-07T09:53:58.235Z", "owner": null } +``` + +## Create a project trigger[](#create-a-project-trigger "Permalink") + +为项目创建触发器. + +``` +POST /projects/:id/triggers +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `description` | string | yes | 触发名称 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers" +``` + +``` +{ "id": 10, "description": "my trigger", "created_at": "2016-01-07T09:53:58.235Z", "last_used": null, "token": "6d056f63e50fe6f8c5f8f4aa10edb7", "updated_at": "2016-01-07T09:53:58.235Z", "owner": null } +``` + +## Update a project trigger[](#update-a-project-trigger "Permalink") + +更新项目的触发器. + +``` +PUT /projects/:id/triggers/:trigger_id +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `trigger_id` | integer | yes | 触发 ID | +| `description` | string | no | 触发名称 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers/10" +``` + +``` +{ "id": 10, "description": "my trigger", "created_at": "2016-01-07T09:53:58.235Z", "last_used": null, "token": "6d056f63e50fe6f8c5f8f4aa10edb7", "updated_at": "2016-01-07T09:53:58.235Z", "owner": null } +``` + +## Remove a project trigger[](#remove-a-project-trigger "Permalink") + +删除项目的生成触发器. + +``` +DELETE /projects/:id/triggers/:trigger_id +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `trigger_id` | integer | yes | 触发 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/triggers/5" +``` \ No newline at end of file diff --git a/_book/docs/347.md b/_book/docs/347.md new file mode 100644 index 0000000000000000000000000000000000000000..84235d2fc1b98ef65229e1758929d9a96ab46620 --- /dev/null +++ b/_book/docs/347.md @@ -0,0 +1,219 @@ +# Pipelines API + +> 原文:[https://docs.gitlab.com/ee/api/pipelines.html](https://docs.gitlab.com/ee/api/pipelines.html) + +* [Single Pipeline Requests](#single-pipeline-requests) +* [Pipelines pagination](#pipelines-pagination) +* [List project pipelines](#list-project-pipelines) +* [Get a single pipeline](#get-a-single-pipeline) + * [Get variables of a pipeline](#get-variables-of-a-pipeline) + * [Get a pipeline’s test report](#get-a-pipelines-test-report) +* [Create a new pipeline](#create-a-new-pipeline) +* [Retry jobs in a pipeline](#retry-jobs-in-a-pipeline) +* [Cancel a pipeline’s jobs](#cancel-a-pipelines-jobs) +* [Delete a pipeline](#delete-a-pipeline) + +# Pipelines API[](#pipelines-api "Permalink") + +## Single Pipeline Requests[](#single-pipeline-requests "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36494) . + +请求有关单个管道的信息的端点返回任何管道的数据. 在 13.2 之前, [对子管道的](../ci/parent_child_pipelines.html)请求返回了 404 错误. + +## Pipelines pagination[](#pipelines-pagination "Permalink") + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +## List project pipelines[](#list-project-pipelines "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) + +``` +GET /projects/:id/pipelines +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `scope` | string | no | 管道的范围,其中之一: `running` , `pending` , `finished` , `branches` , `tags` | +| `status` | string | no | 管道的状态,其中之一: `running` , `pending` , `success` , `failed` , `canceled` , `skipped` , `created` , `manual` | +| `ref` | string | no | 管道的引用 | +| `sha` | string | no | 管道的 SHA | +| `yaml_errors` | boolean | no | 返回无效配置的管道 | +| `name` | string | no | 触发管道的用户名 | +| `username` | string | no | 触发管道的用户的用户名 | +| `updated_after` | datetime | no | 返回在指定日期之后更新的管道. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `updated_before` | datetime | no | 返回在指定日期之前更新的管道. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `order_by` | string | no | 按`id` , `status` , `ref` , `updated_at`或`user_id` `updated_at`管道(默认值: `id` ) | +| `sort` | string | no | 按`asc`或`desc`顺序对管道进行排序(默认值: `desc` ) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines" +``` + +回应范例 + +``` +[ { "id": 47, "status": "pending", "ref": "new-pipeline", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "web_url": "https://example.com/foo/bar/pipelines/47", "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", }, { "id": 48, "status": "pending", "ref": "new-pipeline", "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a", "web_url": "https://example.com/foo/bar/pipelines/48", "created_at": "2016-08-12T10:06:04.561Z", "updated_at": "2016-08-12T10:09:56.223Z", } ] +``` + +## Get a single pipeline[](#get-a-single-pipeline "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) + +``` +GET /projects/:id/pipelines/:pipeline_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_id` | integer | yes | 管道的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/46" +``` + +回应范例 + +``` +{ "id": 46, "status": "success", "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "tag": false, "yaml_errors": null, "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "started_at": null, "finished_at": "2016-08-11T11:32:35.145Z", "committed_at": null, "duration": null, "coverage": "30.0", "web_url": "https://example.com/foo/bar/pipelines/46" } +``` + +### Get variables of a pipeline[](#get-variables-of-a-pipeline "Permalink") + +``` +GET /projects/:id/pipelines/:pipeline_id/variables +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_id` | integer | yes | 管道的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/46/variables" +``` + +回应范例 + +``` +[ { "key": "RUN_NIGHTLY_BUILD", "variable_type": "env_var", "value": "true" }, { "key": "foo", "value": "bar" } ] +``` + +### Get a pipeline’s test report[](#get-a-pipelines-test-report "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/202525) . + +**警告:**此 API 路由是[JUnit 测试报告](../ci/junit_test_reports.html)功能的一部分. 它受一个[功能标志](../development/feature_flags/index.html)保护,该[功能标志](../development/feature_flags/index.html)由于非常大的数据集的性能问题而被**禁用** . + +``` +GET /projects/:id/pipelines/:pipeline_id/test_report +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_id` | integer | yes | The ID of a pipeline | + +样品要求: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/46/test_report" +``` + +样本回复: + +``` +{ "total_time": 5, "total_count": 1, "success_count": 1, "failed_count": 0, "skipped_count": 0, "error_count": 0, "test_suites": [ { "name": "Secure", "total_time": 5, "total_count": 1, "success_count": 1, "failed_count": 0, "skipped_count": 0, "error_count": 0, "test_cases": [ { "status": "success", "name": "Security Reports can create an auto-remediation MR", "classname": "vulnerability_management_spec", "execution_time": 5, "system_output": null, "stack_trace": null } ] } ] } +``` + +## Create a new pipeline[](#create-a-new-pipeline "Permalink") + +在 GitLab 8.14 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7209) + +``` +POST /projects/:id/pipeline +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `ref` | string | yes | 提交参考 | +| `variables` | array | no | 包含管道中可用变量的数组,与结构`[{ 'key' => 'UPLOAD_TO_S3', 'variable_type' => 'file', 'value' => 'true' }]`匹配 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipeline?ref=master" +``` + +回应范例 + +``` +{ "id": 61, "sha": "384c444e840a515b23f21915ee5766b87068a70d", "ref": "master", "status": "pending", "before_sha": "0000000000000000000000000000000000000000", "tag": false, "yaml_errors": null, "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2016-11-04T09:36:13.747Z", "updated_at": "2016-11-04T09:36:13.977Z", "started_at": null, "finished_at": null, "committed_at": null, "duration": null, "coverage": null, "web_url": "https://example.com/foo/bar/pipelines/61" } +``` + +## Retry jobs in a pipeline[](#retry-jobs-in-a-pipeline "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) + +``` +POST /projects/:id/pipelines/:pipeline_id/retry +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_id` | integer | yes | 管道的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/46/retry" +``` + +Response: + +``` +{ "id": 46, "status": "pending", "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "tag": false, "yaml_errors": null, "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "started_at": null, "finished_at": "2016-08-11T11:32:35.145Z", "committed_at": null, "duration": null, "coverage": null, "web_url": "https://example.com/foo/bar/pipelines/46" } +``` + +## Cancel a pipeline’s jobs[](#cancel-a-pipelines-jobs "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) + +``` +POST /projects/:id/pipelines/:pipeline_id/cancel +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_id` | integer | yes | 管道的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/46/cancel" +``` + +Response: + +``` +{ "id": 46, "status": "canceled", "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "tag": false, "yaml_errors": null, "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "started_at": null, "finished_at": "2016-08-11T11:32:35.145Z", "committed_at": null, "duration": null, "coverage": null, "web_url": "https://example.com/foo/bar/pipelines/46" } +``` + +## Delete a pipeline[](#delete-a-pipeline "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22988) . + +``` +DELETE /projects/:id/pipelines/:pipeline_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_id` | integer | yes | 管道的 ID | + +``` +curl --header "PRIVATE-TOKEN: " --request "DELETE" "https://gitlab.example.com/api/v4/projects/1/pipelines/46" +``` \ No newline at end of file diff --git a/_book/docs/348.md b/_book/docs/348.md new file mode 100644 index 0000000000000000000000000000000000000000..eddaf608261ae8152e4124e7b48c1b1d0f558cbd --- /dev/null +++ b/_book/docs/348.md @@ -0,0 +1,99 @@ +# Project Aliases API + +> 原文:[https://docs.gitlab.com/ee/api/project_aliases.html](https://docs.gitlab.com/ee/api/project_aliases.html) + +* [List all project aliases](#list-all-project-aliases) +* [Get project alias’ details](#get-project-alias-details) +* [Create a project alias](#create-a-project-alias) +* [Delete a project alias](#delete-a-project-alias) + +# Project Aliases API[](#project-aliases-api-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3264) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.1. + +所有方法都需要管理员授权. + +## List all project aliases[](#list-all-project-aliases "Permalink") + +获取所有项目别名的列表: + +``` +GET /project_aliases +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_aliases" +``` + +响应示例: + +``` +[ { "id": 1, "project_id": 1, "name": "gitlab-foss" }, { "id": 2, "project_id": 2, "name": "gitlab" } ] +``` + +## Get project alias’ details[](#get-project-alias-details "Permalink") + +获取项目别名的详细信息: + +``` +GET /project_aliases/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | string | yes | 别名的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_aliases/gitlab" +``` + +响应示例: + +``` +{ "id": 1, "project_id": 1, "name": "gitlab" } +``` + +## Create a project alias[](#create-a-project-alias "Permalink") + +为项目添加新的别名. 成功时回应 201,当验证错误时回应 400(例如别名已经存在): + +``` +POST /project_aliases +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `project_id` | integer/string | yes | 项目的 ID 或路径. | +| `name` | string | yes | 别名的名称. 必须是唯一的. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_aliases" --form "project_id=1" --form "name=gitlab" +``` + +or + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_aliases" --form "project_id=gitlab-org/gitlab" --form "name=gitlab" +``` + +响应示例: + +``` +{ "id": 1, "project_id": 1, "name": "gitlab" } +``` + +## Delete a project alias[](#delete-a-project-alias "Permalink") + +删除项目别名. 存在项目别名时以 204 响应,如果不存在则以 404 响应: + +``` +DELETE /project_aliases/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | string | yes | 别名的名称 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_aliases/gitlab" +``` \ No newline at end of file diff --git a/_book/docs/349.md b/_book/docs/349.md new file mode 100644 index 0000000000000000000000000000000000000000..d40dd391e57b2ffa059f7465d1d05eb516136fb3 --- /dev/null +++ b/_book/docs/349.md @@ -0,0 +1,191 @@ +# Project import/export API + +> 原文:[https://docs.gitlab.com/ee/api/project_import_export.html](https://docs.gitlab.com/ee/api/project_import_export.html) + +* [Schedule an export](#schedule-an-export) +* [Export status](#export-status) +* [Export download](#export-download) +* [Import a file](#import-a-file) +* [Import status](#import-status) + +# Project import/export API[](#project-importexport-api "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41899) . + +也可以看看: + +* [Project import/export documentation](../user/project/settings/import_export.html). +* [Project import/export administration Rake tasks](../administration/raketasks/project_import_export.html). + +## Schedule an export[](#schedule-an-export "Permalink") + +开始新的导出. + +端点还接受`upload`参数. 此参数是一个哈希,其中包含将导出的项目上载到 Web 服务器或任何 S3 兼容平台的所有必要信息. 目前,我们仅支持将二进制数据文件上传到最终服务器. + +从 GitLab 10.7 开始,如果存在`upload`参数,则需要`upload[url]`参数. + +``` +POST /projects/:id/export +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `description` | string | no | 覆盖项目描述 | +| `upload` | hash | no | Hash that contains the information to upload the exported project to a web server | +| `upload[url]` | string | yes | 上传项目的网址 | +| `upload[http_method]` | string | no | 上传输出项目的 HTTP 方法. 仅允许使用`PUT`和`POST`方法. 默认为`PUT` | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/export" \ + --data "upload[http_method]=PUT" \ + --data-urlencode "upload[url]=https://example-bucket.s3.eu-west-3.amazonaws.com/backup?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIMBJHN2O62W8IELQ%2F20180312%2Feu-west-3%2Fs3%2Faws4_request&X-Amz-Date=20180312T110328Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=8413facb20ff33a49a147a0b4abcff4c8487cc33ee1f7e450c46e8f695569dbd" +``` + +``` +{ "message": "202 Accepted" } +``` + +**注意:**上载请求将与`Content-Type: application/gzip`标头一起发送. 确保您的预签名 URL 将此内容作为签名的一部分. + +## Export status[](#export-status "Permalink") + +获取导出状态. + +``` +GET /projects/:id/export +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/export" +``` + +状态可以是以下之一: + +* `none` +* `queued` +* `started` +* `finished` +* `regeneration_in_progress` + +`queued`状态表示已接收到导出请求,并且当前处于要处理的队列中. + +`started`状态表示导出过程已开始并且当前正在进行中. 它包括导出过程,对生成的文件执行的操作,例如发送电子邮件通知用户下载文件,将导出的文件上传到 Web 服务器等. + +`finished`状态是在导出过程完成并且已通知用户之后. + +`regeneration_in_progress`是可以下载导出文件且正在处理生成新导出文件的请求. + +`_links`仅在导出完成时存在. + +``` +{ "id": 1, "description": "Itaque perspiciatis minima aspernatur corporis consequatur.", "name": "Gitlab Test", "name_with_namespace": "Gitlab Org / Gitlab Test", "path": "gitlab-test", "path_with_namespace": "gitlab-org/gitlab-test", "created_at": "2017-08-29T04:36:44.383Z", "export_status": "finished", "_links": { "api_url": "https://gitlab.example.com/api/v4/projects/1/export/download", "web_url": "https://gitlab.example.com/gitlab-org/gitlab-test/download_export", } } +``` + +## Export download[](#export-download "Permalink") + +下载完成的导出. + +``` +GET /projects/:id/export/download +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " --remote-header-name --remote-name "https://gitlab.example.com/api/v4/projects/5/export/download" +``` + +``` +ls *export.tar.gz +2017-12-05_22-11-148_namespace_project_export.tar.gz +``` + +## Import a file[](#import-a-file "Permalink") + +``` +POST /projects/import +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `namespace` | integer/string | no | 项目将导入到的名称空间的 ID 或路径. 默认为当前用户的名称空间 | +| `name` | string | no | 要导入的项目的名称. 如果未提供,则默认为项目的路径 | +| `file` | string | yes | 要上传的文件 | +| `path` | string | yes | 新项目的名称和路径 | +| `overwrite` | boolean | no | 如果存在具有相同路径的项目,则导入将覆盖它. 默认为假 | +| `override_params` | Hash | no | 支持在[Project API 中](projects.html)定义的所有字段 | + +传递的覆盖参数将优先于导出文件中定义的所有值. + +要从文件系统上载文件,请使用`--form`参数. 这将导致 cURL 使用标题`Content-Type: multipart/form-data` . `file=`参数必须指向文件系统上的文件,并以`@`开头. 例如: + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "path=api-project" --form "file=@/path/to/file" "https://gitlab.example.com/api/v4/projects/import" +``` + +cURL 不支持从远程服务器发布文件. 从远程服务器导入项目可以通过以下方式完成: + +``` +import requests +from io import BytesIO + +s3_file = requests.get(presigned_url) + +url = 'https://gitlab.example.com/api/v4/projects/import' +files = {'file': ('file.tar.gz', BytesIO(s3_file.content))} +data = { + "path": "example-project", + "namespace": "example-group" +} +headers = { + 'Private-Token': "" +} + +requests.post(url, headers=headers, data=data, files=files) +``` + +``` +{ "id": 1, "description": null, "name": "api-project", "name_with_namespace": "Administrator / api-project", "path": "api-project", "path_with_namespace": "root/api-project", "created_at": "2018-02-13T09:05:58.023Z", "import_status": "scheduled", "correlation_id": "mezklWso3Za", "failed_relations": [] } +``` + +**注意:**可以由管理员设置最大导入文件大小,默认为 50MB. 作为管理员,您可以修改最大导入文件大小. 为此,请在" [应用程序设置" API](settings.html#change-application-settings)或" [管理界面"中](../user/admin_area/settings/account_and_limit_settings.html)使用`max_import_size`选项. + +## Import status[](#import-status "Permalink") + +获取导入状态. + +``` +GET /projects/:id/import +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/import" +``` + +状态可以是以下之一: + +* `none` +* `scheduled` +* `failed` +* `started` +* `finished` + +如果状态`failed` ,它将在`import_error`下包含导入错误消息. 如果状态为`failed` , `started`或`finished`时, `failed_relations`阵列可能与关系的任何事件未能导入无论是由于不可恢复的错误或因重试次数已经用尽被填充(一个典型的例子是查询超时.) + +**注意:** `failed_relations`的元素的`id`字段引用失败记录,而不是关系.**注意:** `failed_relations`数组当前限制为 100 个项目. + +``` +{ "id": 1, "description": "Itaque perspiciatis minima aspernatur corporis consequatur.", "name": "Gitlab Test", "name_with_namespace": "Gitlab Org / Gitlab Test", "path": "gitlab-test", "path_with_namespace": "gitlab-org/gitlab-test", "created_at": "2017-08-29T04:36:44.383Z", "import_status": "started", "correlation_id": "mezklWso3Za", "failed_relations": [ { "id": 42, "created_at": "2020-04-02T14:48:59.526Z", "exception_class": "RuntimeError", "exception_message": "A failure occurred", "source": "custom error context", "relation_name": "merge_requests" } ] } +``` \ No newline at end of file diff --git a/_book/docs/350.md b/_book/docs/350.md new file mode 100644 index 0000000000000000000000000000000000000000..b81ac1e5cb6dd6aeb89bc47c80612f69464aaa21 --- /dev/null +++ b/_book/docs/350.md @@ -0,0 +1,136 @@ +# Project repository storage moves API + +> 原文:[https://docs.gitlab.com/ee/api/project_repository_storage_moves.html](https://docs.gitlab.com/ee/api/project_repository_storage_moves.html) + +* [Retrieve all project repository storage moves](#retrieve-all-project-repository-storage-moves) +* [Retrieve all repository storage moves for a project](#retrieve-all-repository-storage-moves-for-a-project) +* [Get a single project repository storage move](#get-a-single-project-repository-storage-move) +* [Get a single repository storage move for a project](#get-a-single-repository-storage-move-for-a-project) +* [Schedule a repository storage move for a project](#schedule-a-repository-storage-move-for-a-project) + +# Project repository storage moves API[](#project-repository-storage-moves-api-core-only "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31285) . + +项目存储库存储可以移动. 要使用 API​​检索项目存储库存储移动,您必须以管理员[身份进行身份验证](README.html#authentication) . + +## Retrieve all project repository storage moves[](#retrieve-all-project-repository-storage-moves "Permalink") + +``` +GET /project_repository_storage_moves +``` + +默认情况下,因为 API 结果是[分页的](README.html#pagination) ,所以`GET`请求一次返回 20 个结果. + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_repository_storage_moves" +``` + +响应示例: + +``` +[ { "id": 1, "created_at": "2020-05-07T04:27:17.234Z", "state": "scheduled", "source_storage_name": "default", "destination_storage_name": "storage2", "project": { "id": 1, "description": null, "name": "project1", "name_with_namespace": "John Doe2 / project1", "path": "project1", "path_with_namespace": "namespace1/project1", "created_at": "2020-05-07T04:27:17.016Z" } ] +``` + +## Retrieve all repository storage moves for a project[](#retrieve-all-repository-storage-moves-for-a-project "Permalink") + +``` +GET /projects/:project_id/repository_storage_moves +``` + +默认情况下,因为 API 结果是[分页的](README.html#pagination) ,所以`GET`请求一次返回 20 个结果. + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `project_id` | integer | yes | 项目编号 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/repository_storage_moves" +``` + +响应示例: + +``` +[ { "id": 1, "created_at": "2020-05-07T04:27:17.234Z", "state": "scheduled", "source_storage_name": "default", "destination_storage_name": "storage2", "project": { "id": 1, "description": null, "name": "project1", "name_with_namespace": "John Doe2 / project1", "path": "project1", "path_with_namespace": "namespace1/project1", "created_at": "2020-05-07T04:27:17.016Z" } ] +``` + +## Get a single project repository storage move[](#get-a-single-project-repository-storage-move "Permalink") + +``` +GET /project_repository_storage_moves/:repository_storage_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `repository_storage_id` | integer | yes | 项目存储库存储移动的标识 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_repository_storage_moves/1" +``` + +响应示例: + +``` +{ "id": 1, "created_at": "2020-05-07T04:27:17.234Z", "state": "scheduled", "source_storage_name": "default", "destination_storage_name": "storage2", "project": { "id": 1, "description": null, "name": "project1", "name_with_namespace": "John Doe2 / project1", "path": "project1", "path_with_namespace": "namespace1/project1", "created_at": "2020-05-07T04:27:17.016Z" } +``` + +## Get a single repository storage move for a project[](#get-a-single-repository-storage-move-for-a-project "Permalink") + +``` +GET /projects/:project_id/repository_storage_moves/:repository_storage_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `project_id` | integer | yes | 项目编号 | +| `repository_storage_id` | integer | yes | 项目存储库存储移动的标识 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/repository_storage_moves/1" +``` + +响应示例: + +``` +{ "id": 1, "created_at": "2020-05-07T04:27:17.234Z", "state": "scheduled", "source_storage_name": "default", "destination_storage_name": "storage2", "project": { "id": 1, "description": null, "name": "project1", "name_with_namespace": "John Doe2 / project1", "path": "project1", "path_with_namespace": "namespace1/project1", "created_at": "2020-05-07T04:27:17.016Z" } +``` + +## Schedule a repository storage move for a project[](#schedule-a-repository-storage-move-for-a-project "Permalink") + +``` +POST /projects/:project_id/repository_storage_moves +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `project_id` | integer | yes | 项目编号 | +| `destination_storage_name` | string | yes | 目标存储分片的名称 | + +请求示例: + +``` +curl --request POST --header "PRIVATE_TOKEN: " --header "Content-Type: application/json" \ +--data '{"destination_storage_name":"storage2"}' "https://gitlab.example.com/api/v4/projects/1/repository_storage_moves" +``` + +响应示例: + +``` +{ "id": 1, "created_at": "2020-05-07T04:27:17.234Z", "state": "scheduled", "source_storage_name": "default", "destination_storage_name": "storage2", "project": { "id": 1, "description": null, "name": "project1", "name_with_namespace": "John Doe2 / project1", "path": "project1", "path_with_namespace": "namespace1/project1", "created_at": "2020-05-07T04:27:17.016Z" } +``` \ No newline at end of file diff --git a/_book/docs/351.md b/_book/docs/351.md new file mode 100644 index 0000000000000000000000000000000000000000..c9ac08338397420fd47bace46a3c716033af5204 --- /dev/null +++ b/_book/docs/351.md @@ -0,0 +1,27 @@ +# Project statistics API + +> 原文:[https://docs.gitlab.com/ee/api/project_statistics.html](https://docs.gitlab.com/ee/api/project_statistics.html) + +* [Get the statistics of the last 30 days](#get-the-statistics-of-the-last-30-days) + +# Project statistics API[](#project-statistics-api "Permalink") + +每个对[项目](../user/project/index.html)统计信息的 API 调用都必须经过验证. + +## Get the statistics of the last 30 days[](#get-the-statistics-of-the-last-30-days "Permalink") + +检索统计信息需要对存储库的写权限. 当前仅返回 HTTP 提取统计信息. 提取统计信息包括克隆和提取计数,并且仅用于 HTTP,不包括 SSH 提取. + +``` +GET /projects/:id/statistics +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数/字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +响应示例: + +``` +{ "fetches": { "total": 50, "days": [ { "count": 10, "date": "2018-01-10" }, { "count": 10, "date": "2018-01-09" }, { "count": 10, "date": "2018-01-08" }, { "count": 10, "date": "2018-01-07" }, { "count": 10, "date": "2018-01-06" } ] } } +``` \ No newline at end of file diff --git a/_book/docs/352.md b/_book/docs/352.md new file mode 100644 index 0000000000000000000000000000000000000000..83ca4b1f6f17dede312511308c29e267442a70de --- /dev/null +++ b/_book/docs/352.md @@ -0,0 +1,66 @@ +# Project templates API + +> 原文:[https://docs.gitlab.com/ee/api/project_templates.html](https://docs.gitlab.com/ee/api/project_templates.html) + +* [Get all templates of a particular type](#get-all-templates-of-a-particular-type) +* [Get one template of a particular type](#get-one-template-of-a-particular-type) + +# Project templates API[](#project-templates-api "Permalink") + +此 API 是这些端点的特定于项目的版本: + +* [Dockerfile templates](templates/dockerfiles.html) +* [Gitignore templates](templates/gitignores.html) +* [GitLab CI/CD Configuration templates](templates/gitlab_ci_ymls.html) +* [Open source license templates](templates/licenses.html) + +它不赞成使用这些端点,对​​于 API 版本 5 将会删除这些端点. + +除了整个实例通用的模板之外,该 API 端点还提供特定于项目的模板. + +在以后的[版本中,](../user/project/description_templates.html)将添加对[发布和合并请求模板的](../user/project/description_templates.html)支持. + +支持[组级文件模板](../user/group/index.html#group-file-templates-premium) 是在 GitLab 11.5 中[添加的](https://gitlab.com/gitlab-org/gitlab/-/issues/5987) + +## Get all templates of a particular type[](#get-all-templates-of-a-particular-type "Permalink") + +``` +GET /projects/:id/templates/:type +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数/字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `type` | string | yes | 模板的类型`(dockerfiles|gitignores|gitlab_ci_ymls|licenses)` | + +响应示例(许可证): + +``` +[ { "key": "epl-1.0", "name": "Eclipse Public License 1.0" }, { "key": "lgpl-3.0", "name": "GNU Lesser General Public License v3.0" }, { "key": "unlicense", "name": "The Unlicense" }, { "key": "agpl-3.0", "name": "GNU Affero General Public License v3.0" }, { "key": "gpl-3.0", "name": "GNU General Public License v3.0" }, { "key": "bsd-3-clause", "name": "BSD 3-clause \"New\" or \"Revised\" License" }, { "key": "lgpl-2.1", "name": "GNU Lesser General Public License v2.1" }, { "key": "mit", "name": "MIT License" }, { "key": "apache-2.0", "name": "Apache License 2.0" }, { "key": "bsd-2-clause", "name": "BSD 2-clause \"Simplified\" License" }, { "key": "mpl-2.0", "name": "Mozilla Public License 2.0" }, { "key": "gpl-2.0", "name": "GNU General Public License v2.0" } ] +``` + +## Get one template of a particular type[](#get-one-template-of-a-particular-type "Permalink") + +``` +GET /projects/:id/templates/:type/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数/字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `type` | string | yes | 模板的类型`(dockerfiles|gitignores|gitlab_ci_ymls|licenses)` | +| `key` | string | yes | 从集合端点获取的模板的密钥 | +| `project` | string | no | 在模板中扩展占位符时要使用的项目名称. 仅影响许可证 | +| `fullname` | string | no | 在模板中扩展占位符时使用的版权所有者的全名. 仅影响许可证 | + +响应示例(Dockerfile): + +``` +{ "name": "Binary", "content": "# This file is a template, and might need editing before it works on your project.\n# This Dockerfile installs a compiled binary into a bare system.\n# You must either commit your compiled binary into source control (not recommended)\n# or build the binary first as part of a CI/CD pipeline.\n\nFROM buildpack-deps:jessie\n\nWORKDIR /usr/local/bin\n\n# Change `app` to whatever your binary is called\nAdd app .\nCMD [\"./app\"]\n" } +``` + +响应示例(许可证): + +``` +{ "key": "mit", "name": "MIT License", "nickname": null, "popular": true, "html_url": "http://choosealicense.com/licenses/mit/", "source_url": "https://opensource.org/licenses/MIT", "description": "A short and simple permissive license with conditions only requiring preservation of copyright and license notices. Licensed works, modifications, and larger works may be distributed under different terms and without source code.", "conditions": [ "include-copyright" ], "permissions": [ "commercial-use", "modifications", "distribution", "private-use" ], "limitations": [ "liability", "warranty" ], "content": "MIT License\n\nCopyright (c) 2018 [fullname]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" } +``` \ No newline at end of file diff --git a/_book/docs/353.md b/_book/docs/353.md new file mode 100644 index 0000000000000000000000000000000000000000..e098157aab143ab518f835b06845455153079db3 --- /dev/null +++ b/_book/docs/353.md @@ -0,0 +1,1059 @@ +# Projects API + +> 原文:[https://docs.gitlab.com/ee/api/projects.html](https://docs.gitlab.com/ee/api/projects.html) + +* [Project visibility level](#project-visibility-level) +* [Project merge method](#project-merge-method) +* [List all projects](#list-all-projects) + * [Pagination limits](#pagination-limits) +* [List user projects](#list-user-projects) +* [List projects starred by a user](#list-projects-starred-by-a-user) +* [Get single project](#get-single-project) +* [Get project users](#get-project-users) +* [Get project events](#get-project-events) +* [Create project](#create-project) +* [Create project for user](#create-project-for-user) +* [Edit project](#edit-project) +* [Fork project](#fork-project) +* [List Forks of a project](#list-forks-of-a-project) +* [Star a project](#star-a-project) +* [Unstar a project](#unstar-a-project) +* [List Starrers of a project](#list-starrers-of-a-project) +* [Languages](#languages) +* [Archive a project](#archive-a-project) +* [Unarchive a project](#unarchive-a-project) +* [Remove project](#remove-project) +* [Restore project marked for deletion](#restore-project-marked-for-deletion-premium) +* [Upload a file](#upload-a-file) +* [Share project with group](#share-project-with-group) +* [Delete a shared project link within a group](#delete-a-shared-project-link-within-a-group) +* [Hooks](#hooks) + * [List project hooks](#list-project-hooks) + * [Get project hook](#get-project-hook) + * [Add project hook](#add-project-hook) + * [Edit project hook](#edit-project-hook) + * [Delete project hook](#delete-project-hook) +* [Fork relationship](#fork-relationship) + * [Create a forked from/to relation between existing projects](#create-a-forked-fromto-relation-between-existing-projects) + * [Delete an existing forked from relationship](#delete-an-existing-forked-from-relationship) +* [Search for projects by name](#search-for-projects-by-name) +* [Start the Housekeeping task for a Project](#start-the-housekeeping-task-for-a-project) +* [Push Rules](#push-rules-starter) + * [Get project push rules](#get-project-push-rules) + * [Add project push rule](#add-project-push-rule) + * [Edit project push rule](#edit-project-push-rule) + * [Delete project push rule](#delete-project-push-rule) +* [Transfer a project to a new namespace](#transfer-a-project-to-a-new-namespace) +* [Branches](#branches) +* [Project Import/Export](#project-importexport) +* [Project members](#project-members) +* [Start the pull mirroring process for a Project](#start-the-pull-mirroring-process-for-a-project-starter) +* [Project badges](#project-badges) +* [Issue and merge request description templates](#issue-and-merge-request-description-templates) +* [Download snapshot of a Git repository](#download-snapshot-of-a-git-repository) + +# Projects API[](#projects-api "Permalink") + +## Project visibility level[](#project-visibility-level "Permalink") + +GitLab 中的项目可以是私有的,内部的或公共的. 这由项目中的`visibility`字段确定. + +项目可见性级别的值为: + +* `private` :必须为每个用户显式授予项目访问权限. +* `internal` :任何登录的用户都可以克隆该项目. +* `public` :无需任何身份验证即可访问该项目. + +## Project merge method[](#project-merge-method "Permalink") + +`merge_method`当前有三个选项可供选择: + +* `merge` :为每个合并创建一个合并提交,只要没有冲突就允许合并. +* `rebase_merge` :为每个合并创建一个合并提交,但是仅当可能进行快速合并时才允许合并. 这样,您可以确保在合并到目标分支后,如果此合并请求将生成,则该请求也将生成. +* `ff` :没有创建合并提交,并且所有合并都被快速转发,这意味着仅当分支可以被快速转发时才允许合并. + +## List all projects[](#list-all-projects "Permalink") + +获取已认证用户跨 GitLab 的所有可见项目的列表. 在未经身份验证的情况下访问时,仅返回带有"简单"字段的公共项目. + +``` +GET /projects +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `archived` | boolean | no | 受存档状态限制 | +| `visibility` | string | no | 受`public` , `internal`或`private`可见性的限制 | +| `order_by` | string | no | 返回按`id` , `name` , `path` , `created_at` , `updated_at`或`last_activity_at`字段排序的项目. 只有管​​理员可以使用`repository_size` , `storage_size`或`wiki_size`字段. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的项目. 默认为`desc` | +| `search` | string | no | 返回符合搜索条件的项目列表 | +| `search_namespaces` | boolean | no | 匹配搜索条件时包括祖先名称空间. 默认为`false` | +| `simple` | boolean | no | 仅返回每个项目的有限字段. 这是没有身份验证的无操作操作,因为这样*只会*返回简单的字段. | +| `owned` | boolean | no | 受当前用户明确拥有的项目限制 | +| `membership` | boolean | no | 受当前用户是其成员的项目的限制 | +| `starred` | boolean | no | 受当前用户加注星标的项目限制 | +| `statistics` | boolean | no | 包括项目统计 | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | +| `with_issues_enabled` | boolean | no | 受启用的问题限制功能 | +| `with_merge_requests_enabled` | boolean | no | 通过启用的合并请求限制功能 | +| `with_programming_language` | string | no | 受使用给定编程语言的项目限制 | +| `wiki_checksum_failed` | boolean | no | 限制维基校验和计算失败的项目(在[GitLab Premium](https://about.gitlab.com/pricing/) 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) ) | +| `repository_checksum_failed` | boolean | no | 限制存储库校验和计算失败的项目(在[GitLab Premium](https://about.gitlab.com/pricing/) 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) ) | +| `min_access_level` | integer | no | 受当前用户的最小[访问权限](members.html)限制 | +| `id_after` | integer | no | 将结果限制为 ID 大于指定 ID 的项目 | +| `id_before` | integer | no | 将结果限制为 ID 小于指定 ID 的项目 | +| `last_activity_after` | datetime | no | 在指定时间后,将结果限制为具有 last_activity 的项目. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `last_activity_before` | datetime | no | 将结果限制为在指定时间之前具有 last_activity 的项目. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `repository_storage` | string | no | 将结果限制为存储在 repository_storage 上的项目. 仅适用于管理员. | + +**注意:**此端点支持所选`order_by`选项的[键集分页](README.html#keyset-based-pagination) . + +当`simple=true`或用户未经身份验证时,这将返回如下内容: + +``` +[ { "id": 4, "description": null, "default_branch": "master", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", "web_url": "http://example.com/diaspora/diaspora-client", "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md", "tag_list": [ "example", "disapora client" ], "name": "Diaspora Client", "name_with_namespace": "Diaspora / Diaspora Client", "path": "diaspora-client", "path_with_namespace": "diaspora/diaspora-client", "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "forks_count": 0, "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png", "star_count": 0, }, { "id": 6, "description": null, "default_branch": "master", ... +``` + +当用户通过身份验证且未设置`simple` ,将返回以下内容: + +``` +[ { "id": 4, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", "web_url": "http://example.com/diaspora/diaspora-client", "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md", "tag_list": [ "example", "disapora client" ], "owner": { "id": 3, "name": "Diaspora", "created_at": "2013-09-30T13:46:02Z" }, "name": "Diaspora Client", "name_with_namespace": "Diaspora / Diaspora Client", "path": "diaspora-client", "path_with_namespace": "diaspora/diaspora-client", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "archived": false, "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png", "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", "ci_default_git_depth": 50, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on "marked_for_deletion_on": "2020-04-03", "statistics": { "commit_count": 37, "storage_size": 1038090, "repository_size": 1038090, "wiki_size" : 0, "lfs_objects_size": 0, "job_artifacts_size": 0, "packages_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" }, }, { "id": 6, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:brightbox/puppet.git", "http_url_to_repo": "http://example.com/brightbox/puppet.git", "web_url": "http://example.com/brightbox/puppet", "readme_url": "http://example.com/brightbox/puppet/blob/master/README.md", "tag_list": [ "example", "puppet" ], "owner": { "id": 4, "name": "Brightbox", "created_at": "2013-09-30T13:46:02Z" }, "name": "Puppet", "name_with_namespace": "Brightbox / Puppet", "path": "puppet", "path_with_namespace": "brightbox/puppet", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 4, "name": "Brightbox", "path": "brightbox", "kind": "group", "full_path": "brightbox" }, "import_status": "none", "import_error": null, "permissions": { "project_access": { "access_level": 10, "notification_level": 3 }, "group_access": { "access_level": 50, "notification_level": 3 } }, "archived": false, "avatar_url": null, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", "ci_default_git_depth": 0, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "auto_devops_enabled": true, "auto_devops_deploy_strategy": "continuous", "repository_storage": "default", "approvals_before_merge": 0, "mirror": false, "mirror_user_id": 45, "mirror_trigger_builds": false, "only_mirror_protected_branches": false, "mirror_overwrites_diverged_branches": false, "external_authorization_classification_label": null, "packages_enabled": true, "service_desk_enabled": false, "service_desk_address": null, "autoclose_referenced_issues": true, "suggestion_commit_message": null, "statistics": { "commit_count": 12, "storage_size": 2066080, "repository_size": 2066080, "wiki_size" : 0, "lfs_objects_size": 0, "job_artifacts_size": 0, "packages_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } ] +``` + +**注意:**对于使用 GitLab [Silver,Premium 或更高版本](https://about.gitlab.com/pricing/)的用户[,](https://about.gitlab.com/pricing/)已不推荐使用`marked_for_deletion_at`属性,并将在 API v5 中将其删除,以支持`marked_for_deletion_on`属性. + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +[ { "id": 4, "description": null, "approvals_before_merge": 0, ... } ] +``` + +您可以使用以下[自定义属性](custom_attributes.html)进行过滤: + +``` +GET /projects?custom_attributes[key]=value&custom_attributes[other_key]=other_value +``` + +### Pagination limits[](#pagination-limits "Permalink") + +从 GitLab 13.0 开始, [基于偏移量的分页](README.html#offset-based-pagination)将被[限制为 50,000 条记录](https://gitlab.com/gitlab-org/gitlab/-/issues/34565) . 要检索超出此限制的项目,将需要进行[键集分页](README.html#keyset-based-pagination) . + +请注意,键集分页仅支持`order_by=id` . 其他排序选项不可用. + +## List user projects[](#list-user-projects "Permalink") + +获取给定用户拥有的可见项目的列表. 在未经身份验证的情况下访问时,仅返回公共项目. + +``` +GET /users/:user_id/projects +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | string | yes | 用户的 ID 或用户名 | +| `archived` | boolean | no | 受存档状态限制 | +| `visibility` | string | no | 受`public` , `internal`或`private`可见性的限制 | +| `order_by` | string | no | 返回按`id` , `name` , `path` , `created_at` , `updated_at`或`last_activity_at`字段排序的项目. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的项目. 默认为`desc` | +| `search` | string | no | 返回符合搜索条件的项目列表 | +| `simple` | boolean | no | 仅返回每个项目的有限字段. 这是没有身份验证的无操作操作,因为这样*只会*返回简单的字段. | +| `owned` | boolean | no | 受当前用户明确拥有的项目限制 | +| `membership` | boolean | no | 受当前用户是其成员的项目的限制 | +| `starred` | boolean | no | Limit by projects starred by the current user | +| `statistics` | boolean | no | 包括项目统计 | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | +| `with_issues_enabled` | boolean | no | 受启用的问题限制功能 | +| `with_merge_requests_enabled` | boolean | no | 通过启用的合并请求限制功能 | +| `with_programming_language` | string | no | 受使用给定编程语言的项目限制 | +| `min_access_level` | integer | no | 受当前用户的最小[访问权限](members.html)限制 | +| `id_after` | integer | no | 将结果限制为 ID 大于指定 ID 的项目 | +| `id_before` | integer | no | 将结果限制为 ID 小于指定 ID 的项目 | + +**注意:**此端点支持所选`order_by`选项的[键集分页](README.html#keyset-based-pagination) . + +``` +[ { "id": 4, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", "web_url": "http://example.com/diaspora/diaspora-client", "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md", "tag_list": [ "example", "disapora client" ], "owner": { "id": 3, "name": "Diaspora", "created_at": "2013-09-30T13:46:02Z" }, "name": "Diaspora Client", "name_with_namespace": "Diaspora / Diaspora Client", "path": "diaspora-client", "path_with_namespace": "diaspora/diaspora-client", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "archived": false, "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png", "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", "ci_default_git_depth": 50, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on "marked_for_deletion_on": "2020-04-03", "statistics": { "commit_count": 37, "storage_size": 1038090, "repository_size": 1038090, "wiki_size" : 0, "lfs_objects_size": 0, "job_artifacts_size": 0, "packages_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } }, { "id": 6, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:brightbox/puppet.git", "http_url_to_repo": "http://example.com/brightbox/puppet.git", "web_url": "http://example.com/brightbox/puppet", "readme_url": "http://example.com/brightbox/puppet/blob/master/README.md", "tag_list": [ "example", "puppet" ], "owner": { "id": 4, "name": "Brightbox", "created_at": "2013-09-30T13:46:02Z" }, "name": "Puppet", "name_with_namespace": "Brightbox / Puppet", "path": "puppet", "path_with_namespace": "brightbox/puppet", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 4, "name": "Brightbox", "path": "brightbox", "kind": "group", "full_path": "brightbox" }, "import_status": "none", "import_error": null, "permissions": { "project_access": { "access_level": 10, "notification_level": 3 }, "group_access": { "access_level": 50, "notification_level": 3 } }, "archived": false, "avatar_url": null, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", "ci_default_git_depth": 0, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "auto_devops_enabled": true, "auto_devops_deploy_strategy": "continuous", "repository_storage": "default", "approvals_before_merge": 0, "mirror": false, "mirror_user_id": 45, "mirror_trigger_builds": false, "only_mirror_protected_branches": false, "mirror_overwrites_diverged_branches": false, "external_authorization_classification_label": null, "packages_enabled": true, "service_desk_enabled": false, "service_desk_address": null, "autoclose_referenced_issues": true, "suggestion_commit_message": null, "statistics": { "commit_count": 12, "storage_size": 2066080, "repository_size": 2066080, "wiki_size" : 0, "lfs_objects_size": 0, "job_artifacts_size": 0, "packages_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } ] +``` + +## List projects starred by a user[](#list-projects-starred-by-a-user "Permalink") + +获取给定用户拥有的可见项目的列表. 在未经身份验证的情况下访问时,仅返回公共项目. + +``` +GET /users/:user_id/starred_projects +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | string | yes | 用户的 ID 或用户名. | +| `archived` | boolean | no | 受存档状态限制. | +| `visibility` | string | no | 受`public` , `internal`或`private`可见性的限制. | +| `order_by` | string | no | 返回按`id` , `name` , `path` , `created_at` , `updated_at`或`last_activity_at`字段排序的项目. 默认值为`created_at` . | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的项目. 默认为`desc` . | +| `search` | string | no | 返回符合搜索条件的项目列表. | +| `simple` | boolean | no | 仅返回每个项目的有限字段. 这是没有身份验证的无操作操作,因为*仅*返回简单字段. | +| `owned` | boolean | no | 受当前用户明确拥有的项目限制. | +| `membership` | boolean | no | 受当前用户所属项目的限制. | +| `starred` | boolean | no | 受当前用户加注星标的项目限制. | +| `statistics` | boolean | no | 包括项目统计信息. | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员). | +| `with_issues_enabled` | boolean | no | 受启用的问题限制功能. | +| `with_merge_requests_enabled` | boolean | no | 通过启用的合并请求限制功能. | +| `min_access_level` | integer | no | 受当前用户的最小[访问权限](members.html)限制. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/5/starred_projects" +``` + +响应示例: + +``` +[ { "id": 4, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", "web_url": "http://example.com/diaspora/diaspora-client", "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md", "tag_list": [ "example", "disapora client" ], "owner": { "id": 3, "name": "Diaspora", "created_at": "2013-09-30T13:46:02Z" }, "name": "Diaspora Client", "name_with_namespace": "Diaspora / Diaspora Client", "path": "diaspora-client", "path_with_namespace": "diaspora/diaspora-client", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "archived": false, "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png", "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "statistics": { "commit_count": 37, "storage_size": 1038090, "repository_size": 1038090, "lfs_objects_size": 0, "job_artifacts_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } }, { "id": 6, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:brightbox/puppet.git", "http_url_to_repo": "http://example.com/brightbox/puppet.git", "web_url": "http://example.com/brightbox/puppet", "readme_url": "http://example.com/brightbox/puppet/blob/master/README.md", "tag_list": [ "example", "puppet" ], "owner": { "id": 4, "name": "Brightbox", "created_at": "2013-09-30T13:46:02Z" }, "name": "Puppet", "name_with_namespace": "Brightbox / Puppet", "path": "puppet", "path_with_namespace": "brightbox/puppet", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 4, "name": "Brightbox", "path": "brightbox", "kind": "group", "full_path": "brightbox" }, "import_status": "none", "import_error": null, "permissions": { "project_access": { "access_level": 10, "notification_level": 3 }, "group_access": { "access_level": 50, "notification_level": 3 } }, "archived": false, "avatar_url": null, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "auto_devops_enabled": true, "auto_devops_deploy_strategy": "continuous", "repository_storage": "default", "approvals_before_merge": 0, "mirror": false, "mirror_user_id": 45, "mirror_trigger_builds": false, "only_mirror_protected_branches": false, "mirror_overwrites_diverged_branches": false, "external_authorization_classification_label": null, "packages_enabled": true, "service_desk_enabled": false, "service_desk_address": null, "autoclose_referenced_issues": true, "suggestion_commit_message": null, "statistics": { "commit_count": 12, "storage_size": 2066080, "repository_size": 2066080, "lfs_objects_size": 0, "job_artifacts_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } ] +``` + +## Get single project[](#get-single-project "Permalink") + +获取一个特定的项目. 如果可以公开访问该项目,则无需身份验证即可访问该端点. + +``` +GET /projects/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `statistics` | boolean | no | 包括项目统计 | +| `license` | boolean | no | 包括项目许可证数据 | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | + +``` +{ "id": 3, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ "example", "disapora project" ], "owner": { "id": 3, "name": "Diaspora", "created_at": "2013-09-30T13:46:02Z" }, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "container_expiration_policy": { "cadence": "7d", "enabled": false, "keep_n": null, "older_than": null, "name_regex": null, // to be deprecated in GitLab 13.0 in favor of `name_regex_delete` "name_regex_delete": null, "name_regex_keep": null, "next_run_at": "2020-01-07T21:42:58.658Z" }, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora", "avatar_url": "http://localhost:3000/uploads/group/avatar/3/foo.jpg", "web_url": "http://localhost:3000/groups/diaspora" }, "import_status": "none", "import_error": null, "permissions": { "project_access": { "access_level": 10, "notification_level": 3 }, "group_access": { "access_level": 50, "notification_level": 3 } }, "archived": false, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE", "license": { "key": "lgpl-3.0", "name": "GNU Lesser General Public License v3.0", "nickname": "GNU LGPLv3", "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" }, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b", "ci_default_git_depth": 50, "public_jobs": true, "shared_with_groups": [ { "group_id": 4, "group_name": "Twitter", "group_full_path": "twitter", "group_access_level": 30 }, { "group_id": 3, "group_name": "Gitlab Org", "group_full_path": "gitlab-org", "group_access_level": 10 } ], "repository_storage": "default", "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "printing_merge_requests_link_enabled": true, "request_access_enabled": false, "merge_method": "merge", "auto_devops_enabled": true, "auto_devops_deploy_strategy": "continuous", "repository_storage": "default", "approvals_before_merge": 0, "mirror": false, "mirror_user_id": 45, "mirror_trigger_builds": false, "only_mirror_protected_branches": false, "mirror_overwrites_diverged_branches": false, "external_authorization_classification_label": null, "packages_enabled": true, "service_desk_enabled": false, "service_desk_address": null, "autoclose_referenced_issues": true, "suggestion_commit_message": null, "marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on "marked_for_deletion_on": "2020-04-03", "compliance_frameworks": [ "sox" ], "statistics": { "commit_count": 37, "storage_size": 1038090, "repository_size": 1038090, "wiki_size" : 0, "lfs_objects_size": 0, "job_artifacts_size": 0, "packages_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 3, "description": null, "approvals_before_merge": 0, ... } +``` + +**注意** :GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27427)了`namespace`上的`web_url`和`avatar_url`属性. + +如果项目是 fork,并且您提供了有效的令牌进行身份验证,则`forked_from_project`字段将出现在响应中. + +``` +{ "id":3, ... "forked_from_project":{ "id":13083, "description":"GitLab Community Edition", "name":"GitLab Community Edition", "name_with_namespace":"GitLab.org / GitLab Community Edition", "path":"gitlab-foss", "path_with_namespace":"gitlab-org/gitlab-foss", "created_at":"2013-09-26T06:02:36.000Z", "default_branch":"master", "tag_list":[], "ssh_url_to_repo":"git@gitlab.com:gitlab-org/gitlab-foss.git", "http_url_to_repo":"https://gitlab.com/gitlab-org/gitlab-foss.git", "web_url":"https://gitlab.com/gitlab-org/gitlab-foss", "avatar_url":"https://assets.gitlab-static.net/uploads/-/system/project/avatar/13083/logo-extra-whitespace.png", "license_url": "https://gitlab.com/gitlab-org/gitlab/blob/master/LICENSE", "license": { "key": "mit", "name": "MIT License", "nickname": null, "html_url": "http://choosealicense.com/licenses/mit/", "source_url": "https://opensource.org/licenses/MIT", }, "star_count":3812, "forks_count":3561, "last_activity_at":"2018-01-02T11:40:26.570Z", "namespace": { "id": 72, "name": "GitLab.org", "path": "gitlab-org", "kind": "group", "full_path": "gitlab-org", "parent_id": null } } ... } +``` + +## Get project users[](#get-project-users "Permalink") + +获取项目的用户列表. + +``` +GET /projects/:id/users +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `search` | string | no | 搜索特定用户 | +| `skip_users` | 整数数组 | no | 筛选出具有指定 ID 的用户 | + +``` +[ { "id": 1, "username": "john_smith", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", "web_url": "http://localhost:3000/john_smith" }, { "id": 2, "username": "jack_smith", "name": "Jack Smith", "state": "blocked", "avatar_url": "http://gravatar.com/../e32131cd8.jpeg", "web_url": "http://localhost:3000/jack_smith" } ] +``` + +## Get project events[](#get-project-events "Permalink") + +请参考[Events API 文档](events.html#list-a-projects-visible-events) . + +## Create project[](#create-project "Permalink") + +创建一个经过身份验证的用户拥有的新项目. + +``` +POST /projects +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | string | 是,如果未提供路径 | 新项目的名称. 如果未提供,则等于路径. | +| `path` | string | 是,如果未提供名称 | 新项目的存储库名称. 如果未提供,则根据名称生成(生成的小写字母加短划线). | +| `namespace_id` | integer | no | 新项目的命名空间(默认为当前用户的命名空间) | +| `default_branch` | string | no | `master`默认 | +| `description` | string | no | 简短的项目说明 | +| `issues_enabled` | boolean | no | (不建议使用)为此项目启用问题. 改用`issues_access_level` | +| `merge_requests_enabled` | boolean | no | (不建议使用)为此项目启用合并请求. 改用`merge_requests_access_level` | +| `jobs_enabled` | boolean | no | (不建议使用)为此项目启用作业. 改用`builds_access_level` | +| `wiki_enabled` | boolean | no | (已弃用)为此项目启用 Wiki. 改用`wiki_access_level` | +| `snippets_enabled` | boolean | no | (不建议使用)为此项目启用摘要. 请改用`snippets_access_level` | +| `issues_access_level` | string | no | `disabled` , `private`或`enabled` | +| `repository_access_level` | string | no | `disabled` , `private`或`enabled` | +| `merge_requests_access_level` | string | no | `disabled` , `private`或`enabled` | +| `forking_access_level` | string | no | `disabled` , `private`或`enabled` | +| `builds_access_level` | string | no | `disabled` , `private`或`enabled` | +| `wiki_access_level` | string | no | `disabled` , `private`或`enabled` | +| `snippets_access_level` | string | no | `disabled` , `private`或`enabled` | +| `pages_access_level` | string | no | `disabled` , `private` , `enabled`或`public` | +| `emails_disabled` | boolean | no | 禁用电子邮件通知 | +| `show_default_award_emojis` | boolean | no | 显示默认的奖励表情符号 | +| `resolve_outdated_diff_discussions` | boolean | no | 自动解决合并请求差异讨论(通过推送更改) | +| `container_registry_enabled` | boolean | no | 为该项目启用容器注册表 | +| `container_expiration_policy_attributes` | hash | no | 更新此项目的图像过期策略. 接受: `cadence` (字符串), `keep_n` (字符串), `older_than` (字符串), `name_regex` (字符串), `name_regex_delete` (字符串), `name_regex_keep` (字符串), `enabled` (布尔值) | +| `shared_runners_enabled` | boolean | no | 为此项目启用共享跑步者 | +| `visibility` | string | no | See [project visibility level](#project-visibility-level) | +| `import_url` | string | no | 从中导入存储库的 URL | +| `public_builds` | boolean | no | 如果为`true` ,则非项目成员可以查看作业 | +| `only_allow_merge_if_pipeline_succeeds` | boolean | no | 设置是否只能将合并请求与成功的作业合并 | +| `allow_merge_on_skipped_pipeline` | boolean | no | 设置是否可以将合并请求与跳过的作业合并 | +| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | 设置是否仅在所有讨论都解决后才能合并合并请求 | +| `merge_method` | string | no | 设置使用的[合并方法](#project-merge-method) | +| `autoclose_referenced_issues` | boolean | no | 设置是否自动关闭默认分支上的引用问题 | +| `remove_source_branch_after_merge` | boolean | no | 默认情况下,为所有新合并请求启用" `Delete source branch`选项 | +| `lfs_enabled` | boolean | no | 启用 LFS | +| `request_access_enabled` | boolean | no | 允许用户请求成员访问 | +| `tag_list` | array | no | 项目标签列表; 放置标签数组,这些标签应最终分配给项目 | +| `avatar` | mixed | no | 项目头像的图像文件 | +| `printing_merge_request_link_enabled` | boolean | no | 从命令行推送时显示创建/查看合并请求的链接 | +| `build_git_strategy` | string | no | Git 策略. 默认为`fetch` | +| `build_timeout` | integer | no | 作业可以运行的最长时间(以分钟为单位)(以秒为单位) | +| `auto_cancel_pending_pipelines` | string | no | 自动取消挂起的管道(注意:这不是布尔值,但已启用/禁用 | +| `build_coverage_regex` | string | no | 测试覆盖率解析 | +| `ci_config_path` | string | no | CI 配置文件的路径 | +| `auto_devops_enabled` | boolean | no | 为该项目启用 Auto DevOps | +| `auto_devops_deploy_strategy` | string | no | 自动部署策略( `continuous` , `manual`或`timed_incremental` ) | +| `repository_storage` | string | no | 存储库位于哪个存储分片上. 仅适用于管理员 | +| `approvals_before_merge` | integer | no | 默认情况下,应有多少个批准者批准合并请求 | +| `external_authorization_classification_label` | string | no | 项目的分类标签 | +| `mirror` | boolean | no | 在项目中启用拉镜像 | +| `mirror_trigger_builds` | boolean | no | 拉镜像触发器构建 | +| `initialize_with_readme` | boolean | no | 默认为`false` | +| `template_name` | string | no | 不使用`use_custom_template` ,为[内置项目模板的名称](../gitlab-basics/create-project.html#built-in-templates) . 与`use_custom_template`使用时,自定义项目模板的名称 | +| `template_project_id` | integer | no | 与`use_custom_template`使用时,是自定义项目模板的项目 ID. 这比使用`template_name`更可取,因为`template_name`可能含糊. | +| `use_custom_template` | boolean | no | 使用自定义[实例](../user/admin_area/custom_project_templates.html)或[组](../user/group/custom_project_templates.html) (带有`group_with_project_templates_id` )项目模板 | +| `group_with_project_templates_id` | integer | no | 对于组级别的自定义模板,指定所有自定义项目模板所源自的组的 ID. 将实例级模板留空. 要求`use_custom_template`为 true | +| `packages_enabled` | boolean | no | 启用或禁用软件包存储库功能 | + +**注意:**如果您的 HTTP 存储库不可公开访问,请将身份验证信息添加到 URL: `https://username:password@gitlab.company.com/group/project.git` ,其中`password`是启用了`api`范围的公共访问密钥. + +## Create project for user[](#create-project-for-user "Permalink") + +创建一个由指定用户拥有的新项目. 仅适用于管理员. + +``` +POST /projects/user/:user_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | integer | yes | 项目所有者的用户标识 | +| `name` | string | yes | 新项目的名称 | +| `path` | string | no | 新项目的自定义存储库名称. 默认情况下根据名称生成 | +| `namespace_id` | integer | no | Namespace for the new project (defaults to the current user’s namespace) | +| `description` | string | no | 简短的项目说明 | +| `issues_enabled` | boolean | no | (不建议使用)为此项目启用问题. 改用`issues_access_level` | +| `merge_requests_enabled` | boolean | no | (不建议使用)为此项目启用合并请求. 改用`merge_requests_access_level` | +| `jobs_enabled` | boolean | no | (不建议使用)为此项目启用作业. 改用`builds_access_level` | +| `wiki_enabled` | boolean | no | (已弃用)为此项目启用 Wiki. 改用`wiki_access_level` | +| `snippets_enabled` | boolean | no | (不建议使用)为此项目启用摘要. 请改用`snippets_access_level` | +| `issues_access_level` | string | no | `disabled` , `private`或`enabled` | +| `repository_access_level` | string | no | `disabled` , `private`或`enabled` | +| `merge_requests_access_level` | string | no | `disabled` , `private`或`enabled` | +| `forking_access_level` | string | no | `disabled` , `private`或`enabled` | +| `builds_access_level` | string | no | `disabled` , `private`或`enabled` | +| `wiki_access_level` | string | no | `disabled` , `private`或`enabled` | +| `snippets_access_level` | string | no | `disabled` , `private`或`enabled` | +| `pages_access_level` | string | no | `disabled` , `private` , `enabled`或`public` | +| `emails_disabled` | boolean | no | 禁用电子邮件通知 | +| `show_default_award_emojis` | boolean | no | 显示默认的奖励表情符号 | +| `resolve_outdated_diff_discussions` | boolean | no | 自动解决合并请求差异讨论(通过推送更改) | +| `container_registry_enabled` | boolean | no | 为该项目启用容器注册表 | +| `shared_runners_enabled` | boolean | no | 为此项目启用共享跑步者 | +| `visibility` | string | no | See [project visibility level](#project-visibility-level) | +| `import_url` | string | no | 从中导入存储库的 URL | +| `public_builds` | boolean | no | 如果为`true` ,则非项目成员可以查看作业 | +| `only_allow_merge_if_pipeline_succeeds` | boolean | no | 设置是否只能将合并请求与成功的作业合并 | +| `allow_merge_on_skipped_pipeline` | boolean | no | 设置是否可以将合并请求与跳过的作业合并 | +| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | 设置是否仅在所有讨论都解决后才能合并合并请求 | +| `merge_method` | string | no | 设置使用的[合并方法](#project-merge-method) | +| `autoclose_referenced_issues` | boolean | no | 设置是否自动关闭默认分支上的引用问题 | +| `suggestion_commit_message` | string | no | 用于应用合并请求建议的提交消息 | +| `remove_source_branch_after_merge` | boolean | no | 默认情况下,为所有新合并请求启用" `Delete source branch`选项 | +| `lfs_enabled` | boolean | no | 启用 LFS | +| `request_access_enabled` | boolean | no | 允许用户请求成员访问 | +| `tag_list` | array | no | 项目标签列表; 放置标签数组,这些标签应最终分配给项目 | +| `avatar` | mixed | no | 项目头像的图像文件 | +| `printing_merge_request_link_enabled` | boolean | no | 从命令行推送时显示创建/查看合并请求的链接 | +| `build_git_strategy` | string | no | Git 策略. 默认为`fetch` | +| `build_timeout` | integer | no | 作业可以运行的最长时间(以分钟为单位)(以秒为单位) | +| `auto_cancel_pending_pipelines` | string | no | 自动取消挂起的管道(注意:这不是布尔值,但已启用/禁用 | +| `build_coverage_regex` | string | no | 测试覆盖率解析 | +| `ci_config_path` | string | no | CI 配置文件的路径 | +| `auto_devops_enabled` | boolean | no | 为该项目启用 Auto DevOps | +| `auto_devops_deploy_strategy` | string | no | 自动部署策略( `continuous` , `manual`或`timed_incremental` ) | +| `repository_storage` | string | no | 存储库位于哪个存储分片上. 仅适用于管理员 | +| `approvals_before_merge` | integer | no | 默认情况下,应有多少个批准者批准合并请求 | +| `external_authorization_classification_label` | string | no | 项目的分类标签 | +| `mirror` | boolean | no | 在项目中启用拉镜像 | +| `mirror_trigger_builds` | boolean | no | 拉镜像触发器构建 | +| `initialize_with_readme` | boolean | no | 默认为`false` | +| `template_name` | string | no | 不使用`use_custom_template` ,为[内置项目模板的名称](../gitlab-basics/create-project.html#built-in-templates) . 与`use_custom_template`使用时,自定义项目模板的名称 | +| `use_custom_template` | boolean | no | Use either custom [instance](../user/admin_area/custom_project_templates.html) or [group](../user/group/custom_project_templates.html) (with `group_with_project_templates_id`) project template | +| `group_with_project_templates_id` | integer | no | 对于组级别的自定义模板,指定所有自定义项目模板所源自的组的 ID. 将实例级模板留空. 要求`use_custom_template`为 true | +| `packages_enabled` | boolean | no | 启用或禁用软件包存储库功能 | + +**注意:**如果您的 HTTP 存储库不可公开访问,请将身份验证信息添加到 URL: `https://username:password@gitlab.company.com/group/project.git` ,其中`password`是启用了`api`范围的公共访问密钥. + +## Edit project[](#edit-project "Permalink") + +更新现有项目. + +``` +PUT /projects/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `name` | string | no | 项目名称 | +| `path` | string | no | 项目的自定义存储库名称. 默认情况下根据名称生成 | +| `default_branch` | string | no | `master`默认 | +| `description` | string | no | 简短的项目说明 | +| `issues_enabled` | boolean | no | (不建议使用)为此项目启用问题. 改用`issues_access_level` | +| `merge_requests_enabled` | boolean | no | (不建议使用)为此项目启用合并请求. 改用`merge_requests_access_level` | +| `jobs_enabled` | boolean | no | (不建议使用)为此项目启用作业. 改用`builds_access_level` | +| `wiki_enabled` | boolean | no | (已弃用)为此项目启用 Wiki. 改用`wiki_access_level` | +| `snippets_enabled` | boolean | no | (不建议使用)为此项目启用摘要. 请改用`snippets_access_level` | +| `issues_access_level` | string | no | `disabled` , `private`或`enabled` | +| `repository_access_level` | string | no | `disabled` , `private`或`enabled` | +| `merge_requests_access_level` | string | no | `disabled` , `private`或`enabled` | +| `forking_access_level` | string | no | `disabled` , `private`或`enabled` | +| `builds_access_level` | string | no | `disabled` , `private`或`enabled` | +| `wiki_access_level` | string | no | `disabled` , `private`或`enabled` | +| `snippets_access_level` | string | no | `disabled` , `private`或`enabled` | +| `pages_access_level` | string | no | `disabled` , `private` , `enabled`或`public` | +| `emails_disabled` | boolean | no | 禁用电子邮件通知 | +| `show_default_award_emojis` | boolean | no | 显示默认的奖励表情符号 | +| `resolve_outdated_diff_discussions` | boolean | no | 自动解决合并请求差异讨论(通过推送更改) | +| `container_registry_enabled` | boolean | no | 为该项目启用容器注册表 | +| `container_expiration_policy_attributes` | hash | no | 更新此项目的图像过期策略. 接受: `cadence` (字符串), `keep_n` (字符串), `older_than` (字符串), `name_regex` (字符串), `name_regex_delete` (字符串), `name_regex_keep` (字符串), `enabled` (布尔值) | +| `shared_runners_enabled` | boolean | no | 为此项目启用共享跑步者 | +| `visibility` | string | no | See [project visibility level](#project-visibility-level) | +| `import_url` | string | no | 从中导入存储库的 URL | +| `public_builds` | boolean | no | 如果为`true` ,则非项目成员可以查看作业 | +| `only_allow_merge_if_pipeline_succeeds` | boolean | no | 设置是否只能将合并请求与成功的作业合并 | +| `allow_merge_on_skipped_pipeline` | boolean | no | 设置是否可以将合并请求与跳过的作业合并 | +| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | 设置是否仅在所有讨论都解决后才能合并合并请求 | +| `merge_method` | string | no | 设置使用的[合并方法](#project-merge-method) | +| `autoclose_referenced_issues` | boolean | no | 设置是否自动关闭默认分支上的引用问题 | +| `suggestion_commit_message` | string | no | 用于应用合并请求建议的提交消息 | +| `remove_source_branch_after_merge` | boolean | no | 默认情况下,为所有新合并请求启用" `Delete source branch`选项 | +| `lfs_enabled` | boolean | no | 启用 LFS | +| `request_access_enabled` | boolean | no | 允许用户请求成员访问 | +| `tag_list` | array | no | 项目标签列表; 放置标签数组,这些标签应最终分配给项目 | +| `avatar` | mixed | no | 项目头像的图像文件 | +| `build_git_strategy` | string | no | Git 策略. 默认为`fetch` | +| `build_timeout` | integer | no | 作业可以运行的最长时间(以分钟为单位)(以秒为单位) | +| `auto_cancel_pending_pipelines` | string | no | 自动取消挂起的管道(注意:这不是布尔值,但已启用/禁用 | +| `build_coverage_regex` | string | no | 测试覆盖率解析 | +| `ci_config_path` | string | no | CI 配置文件的路径 | +| `ci_default_git_depth` | integer | no | [浅克隆的](../ci/pipelines/settings.html#git-shallow-clone)默认修订版本数 | +| `auto_devops_enabled` | boolean | no | 为该项目启用 Auto DevOps | +| `auto_devops_deploy_strategy` | string | no | 自动部署策略( `continuous` , `manual`或`timed_incremental` ) | +| `repository_storage` | string | no | 存储库位于哪个存储分片上. 仅适用于管理员 | +| `approvals_before_merge` | integer | no | How many approvers should approve merge request by default | +| `external_authorization_classification_label` | string | no | 项目的分类标签 | +| `mirror` | boolean | no | 在项目中启用拉镜像 | +| `mirror_user_id` | integer | no | 用户负责拉镜事件周围的所有活动. 只能由管理员设置. | +| `mirror_trigger_builds` | boolean | no | 拉镜像触发器构建 | +| `only_mirror_protected_branches` | boolean | no | 仅镜像保护的分支 | +| `mirror_overwrites_diverged_branches` | boolean | no | 拉镜将覆盖分散的分支 | +| `packages_enabled` | boolean | no | 启用或禁用软件包存储库功能 | +| `service_desk_enabled` | boolean | no | 启用或禁用服务台功能 | + +**注意:**如果您的 HTTP 存储库不可公开访问,请将身份验证信息添加到 URL: `https://username:password@gitlab.company.com/group/project.git` ,其中`password`是启用了`api`范围的公共访问密钥. + +## Fork project[](#fork-project "Permalink") + +将项目派生到已认证用户或提供的用户的用户名称空间中. + +项目的分叉操作是异步的,并在后台作业中完成. 该请求将立即返回. 要确定项目的分支是否已完成,请查询`import_status`以获取新项目. + +``` +POST /projects/:id/fork +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `namespace` | integer/string | no | (不建议使用)项目将分叉到的名称空间的 ID 或路径 | +| `namespace_id` | integer | no | 项目将分叉到的名称空间的 ID | +| `namespace_path` | string | no | 项目将分叉到的名称空间的路径 | +| `path` | string | no | 分叉后将分配给结果项目的路径 | +| `name` | string | no | 分叉后将分配给结果项目的名称 | + +## List Forks of a project[](#list-forks-of-a-project "Permalink") + +**注意:**此功能是在 GitLab 10.1 中引入的. + +列出呼叫用户可访问的与指定项目具有已建立的分叉关系的项目 + +``` +GET /projects/:id/forks +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `archived` | boolean | no | 受存档状态限制 | +| `visibility` | string | no | 受`public` , `internal`或`private`可见性的限制 | +| `order_by` | string | no | 返回按`id` , `name` , `path` , `created_at` , `updated_at`或`last_activity_at`字段排序的项目. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的项目. 默认为`desc` | +| `search` | string | no | 返回符合搜索条件的项目列表 | +| `simple` | boolean | no | 仅返回每个项目的有限字段. 这是没有身份验证的无操作操作,因为这样*只会*返回简单的字段. | +| `owned` | boolean | no | 受当前用户明确拥有的项目限制 | +| `membership` | boolean | no | 受当前用户是其成员的项目的限制 | +| `starred` | boolean | no | 受当前用户加注星标的项目限制 | +| `statistics` | boolean | no | 包括项目统计 | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | +| `with_issues_enabled` | boolean | no | 受启用的问题限制功能 | +| `with_merge_requests_enabled` | boolean | no | 通过启用的合并请求限制功能 | +| `min_access_level` | integer | no | 受当前用户的最小[访问权限](members.html)限制 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/forks" +``` + +响应示例: + +``` +[ { "id": 3, "description": null, "default_branch": "master", "visibility": "internal", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ "example", "disapora project" ], "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "archived": true, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "shared_runners_enabled": true, "forks_count": 0, "star_count": 1, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } ] +``` + +## Star a project[](#star-a-project "Permalink") + +明星给定的项目. 如果项目已加星标,则返回状态码`304` . + +``` +POST /projects/:id/star +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/star" +``` + +响应示例: + +``` +{ "id": 3, "description": null, "default_branch": "master", "visibility": "internal", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ "example", "disapora project" ], "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "archived": true, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE", "license": { "key": "lgpl-3.0", "name": "GNU Lesser General Public License v3.0", "nickname": "GNU LGPLv3", "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" }, "shared_runners_enabled": true, "forks_count": 0, "star_count": 1, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } +``` + +## Unstar a project[](#unstar-a-project "Permalink") + +取消给定项目的星标. 如果项目未加星标,则返回状态码`304` . + +``` +POST /projects/:id/unstar +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/unstar" +``` + +响应示例: + +``` +{ "id": 3, "description": null, "default_branch": "master", "visibility": "internal", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ "example", "disapora project" ], "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "archived": true, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE", "license": { "key": "lgpl-3.0", "name": "GNU Lesser General Public License v3.0", "nickname": "GNU LGPLv3", "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" }, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } +``` + +## List Starrers of a project[](#list-starrers-of-a-project "Permalink") + +列出为指定项目加注星标的用户. + +``` +GET /projects/:id/starrers +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `search` | string | no | 搜索特定用户. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/starrers" +``` + +响应示例: + +``` +[ { "starred_since": "2019-01-28T14:47:30.642Z", "user": { "id": 1, "username": "jane_smith", "name": "Jane Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", "web_url": "http://localhost:3000/jane_smith" } }, "starred_since": "2018-01-02T11:40:26.570Z", "user": { "id": 2, "username": "janine_smith", "name": "Janine Smith", "state": "blocked", "avatar_url": "http://gravatar.com/../e32131cd8.jpeg", "web_url": "http://localhost:3000/janine_smith" } ] +``` + +## Languages[](#languages "Permalink") + +获取具有百分比值的项目中使用的语言. + +``` +GET /projects/:id/languages +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/languages" +``` + +响应示例: + +``` +{ "Ruby": 66.69, "JavaScript": 22.98, "HTML": 7.91, "CoffeeScript": 2.42 } +``` + +## Archive a project[](#archive-a-project "Permalink") + +如果用户是该项目的管理员或项目所有者,则归档该项目. 此操作是幂等的,因此归档已归档的项目不会更改该项目. + +``` +POST /projects/:id/archive +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/archive" +``` + +响应示例: + +``` +{ "id": 3, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ "example", "disapora project" ], "owner": { "id": 3, "name": "Diaspora", "created_at": "2013-09-30T13:46:02Z" }, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "import_error": null, "permissions": { "project_access": { "access_level": 10, "notification_level": 3 }, "group_access": { "access_level": 50, "notification_level": 3 } }, "archived": true, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE", "license": { "key": "lgpl-3.0", "name": "GNU Lesser General Public License v3.0", "nickname": "GNU LGPLv3", "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" }, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b", "ci_default_git_depth": 50, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } +``` + +## Unarchive a project[](#unarchive-a-project "Permalink") + +如果用户是该项目的管理员或项目所有者,则取消归档该项目. 此操作是幂等的,因此取消存档未存档的项目不会更改该项目. + +``` +POST /projects/:id/unarchive +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/unarchive" +``` + +响应示例: + +``` +{ "id": 3, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ "example", "disapora project" ], "owner": { "id": 3, "name": "Diaspora", "created_at": "2013-09-30T13:46:02Z" }, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "import_error": null, "permissions": { "project_access": { "access_level": 10, "notification_level": 3 }, "group_access": { "access_level": 50, "notification_level": 3 } }, "archived": false, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE", "license": { "key": "lgpl-3.0", "name": "GNU Lesser General Public License v3.0", "nickname": "GNU LGPLv3", "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" }, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b", "ci_default_git_depth": 50, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } +``` + +## Remove project[](#remove-project "Permalink") + +该端点: + +* 删除包含所有相关资源(问题,合并请求等)的项目. +* 从[Premium 或 Silver](https://about.gitlab.com/pricing/)或更高级别的[GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/32935)开始,将项目标记为删除. 实际删除发生在[实例设置中](../user/admin_area/settings/visibility_and_access_controls.html#default-deletion-adjourned-period-premium-only)指定的天数之后. + +``` +DELETE /projects/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +## Restore project marked for deletion[](#restore-project-marked-for-deletion-premium "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) . + +恢复标记为删除的项目. + +``` +POST /projects/:id/restore +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +## Upload a file[](#upload-a-file "Permalink") + +将文件上载到指定的项目,以在发布或合并请求描述或注释中使用. + +``` +POST /projects/:id/uploads +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `file` | string | yes | 要上传的文件 | + +要从文件系统上载文件,请使用`--form`参数. 这将导致 cURL 使用标题`Content-Type: multipart/form-data` . `file=`参数必须指向文件系统上的文件,并以`@`开头. 例如: + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "file=@dk.png" "https://gitlab.example.com/api/v4/projects/5/uploads" +``` + +Returned object: + +``` +{ "alt": "dk", "url": "/uploads/66dbcd21ec5d24ed6ea225176098d52b/dk.png", "full_path": "/namespace1/project1/uploads/66dbcd21ec5d24ed6ea225176098d52b/dk.png", "markdown": "![dk](/uploads/66dbcd21ec5d24ed6ea225176098d52b/dk.png)" } +``` + +> **注意** :返回的`url`是相对于项目路径的. 返回的`full_path`是文件的绝对路径. 在 Markdown 上下文中,当使用`markdown`的格式时,链接会自动展开. + +## Share project with group[](#share-project-with-group "Permalink") + +允许与小组共享项目. + +``` +POST /projects/:id/share +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `group_id` | integer | yes | 与之共享的组的 ID | +| `group_access` | integer | yes | 授予组的[权限级别](members.html) | +| `expires_at` | string | no | ISO 8601 格式的股份到期日:2016-09-26 | + +## Delete a shared project link within a group[](#delete-a-shared-project-link-within-a-group "Permalink") + +从小组取消共享项目. 返回`204` ,成功则不返回任何内容. + +``` +DELETE /projects/:id/share/:group_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `group_id` | integer | yes | 组的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/share/17" +``` + +## Hooks[](#hooks "Permalink") + +也称为 Project Hooks 和 Webhooks. 对于系统范围的[系统挂钩](system_hooks.html) ,这些是不同的. + +### List project hooks[](#list-project-hooks "Permalink") + +获取项目挂钩的列表. + +``` +GET /projects/:id/hooks +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +### Get project hook[](#get-project-hook "Permalink") + +获取项目的特定挂钩. + +``` +GET /projects/:id/hooks/:hook_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `hook_id` | integer | yes | 项目挂钩的 ID | + +``` +{ "id": 1, "url": "http://example.com/hook", "project_id": 3, "push_events": true, "push_events_branch_filter": "", "issues_events": true, "confidential_issues_events": true, "merge_requests_events": true, "tag_push_events": true, "note_events": true, "confidential_note_events": true, "job_events": true, "pipeline_events": true, "wiki_page_events": true, "enable_ssl_verification": true, "created_at": "2012-10-12T17:04:47Z" } +``` + +### Add project hook[](#add-project-hook "Permalink") + +将钩子添加到指定项目. + +``` +POST /projects/:id/hooks +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `url` | string | yes | 挂钩网址 | +| `push_events` | boolean | no | 在推送事件上触发钩子 | +| `push_events_branch_filter` | string | no | 触发推送事件上的钩子,仅用于匹配分支 | +| `issues_events` | boolean | no | 触发问题事件挂钩 | +| `confidential_issues_events` | boolean | no | 触发机密问题事件的钩子 | +| `merge_requests_events` | boolean | no | 触发合并请求事件的钩子 | +| `tag_push_events` | boolean | no | 触发标签推送事件的钩子 | +| `note_events` | boolean | no | 在音符事件上触发钩子 | +| `confidential_note_events` | boolean | no | 触发机密笔记事件的钩子 | +| `job_events` | boolean | no | 触发工作事件挂钩 | +| `pipeline_events` | boolean | no | 触发管道事件钩子 | +| `wiki_page_events` | boolean | no | 触发 Wiki 事件的钩子 | +| `enable_ssl_verification` | boolean | no | 触发挂钩时执行 SSL 验证 | +| `token` | string | no | 用于验证收到的有效载荷的秘密令牌; 这将不会在响应中返回 | + +### Edit project hook[](#edit-project-hook "Permalink") + +Edits a hook for a specified project. + +``` +PUT /projects/:id/hooks/:hook_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `hook_id` | integer | yes | 项目挂钩的 ID | +| `url` | string | yes | 挂钩网址 | +| `push_events` | boolean | no | 在推送事件上触发钩子 | +| `push_events_branch_filter` | string | no | 触发推送事件上的钩子,仅用于匹配分支 | +| `issues_events` | boolean | no | Trigger hook on issues events | +| `confidential_issues_events` | boolean | no | 触发机密问题事件的钩子 | +| `merge_requests_events` | boolean | no | 触发合并请求事件的钩子 | +| `tag_push_events` | boolean | no | 触发标签推送事件的钩子 | +| `note_events` | boolean | no | 在音符事件上触发钩子 | +| `confidential_note_events` | boolean | no | 触发机密笔记事件的钩子 | +| `job_events` | boolean | no | 触发工作事件挂钩 | +| `pipeline_events` | boolean | no | 触发管道事件钩子 | +| `wiki_events` | boolean | no | 触发 Wiki 事件的钩子 | +| `enable_ssl_verification` | boolean | no | 触发挂钩时执行 SSL 验证 | +| `token` | string | no | 用于验证收到的有效载荷的秘密令牌; 这将不会在响应中返回 | + +### Delete project hook[](#delete-project-hook "Permalink") + +从项目中删除一个钩子. 这是幂等方法,可以多次调用. 挂钩是否可用. + +``` +DELETE /projects/:id/hooks/:hook_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `hook_id` | integer | yes | 项目挂钩的 ID | + +请注意,无论挂钩是否可用,JSON 响应都会有所不同. 如果项目挂钩在 JSON 响应中返回之前可用,或者返回空响应. + +## Fork relationship[](#fork-relationship "Permalink") + +允许修改现有项目之间的分支关系. 仅适用于项目所有者和管理员. + +### Create a forked from/to relation between existing projects[](#create-a-forked-fromto-relation-between-existing-projects "Permalink") + +``` +POST /projects/:id/fork/:forked_from_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `forked_from_id` | ID | yes | 分叉的项目的 ID | + +### Delete an existing forked from relationship[](#delete-an-existing-forked-from-relationship "Permalink") + +``` +DELETE /projects/:id/fork +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +## Search for projects by name[](#search-for-projects-by-name "Permalink") + +通过名称搜索可通过身份验证的用户访问的项目. 如果可以公开访问该项目,则无需身份验证即可访问该端点. + +``` +GET /projects +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `search` | string | yes | 项目名称中包含的字符串 | +| `order_by` | string | no | 返回按`id` , `name` , `created_at`或`last_activity_at`字段排序的请求 | +| `sort` | string | no | 返回请求按`asc`或`desc`排序 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects?search=test" +``` + +## Start the Housekeeping task for a Project[](#start-the-housekeeping-task-for-a-project "Permalink") + +在 GitLab 9.0 中引入. + +``` +POST /projects/:id/housekeeping +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目或 NAMESPACE / PROJECT_NAME 的 ID | + +## Push Rules[](#push-rules-starter "Permalink") + +### Get project push rules[](#get-project-push-rules "Permalink") + +获取项目的推送规则. + +``` +GET /projects/:id/push_rule +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目或 NAMESPACE / PROJECT_NAME 的 ID | + +``` +{ "id": 1, "project_id": 3, "commit_message_regex": "Fixes \d+\..*", "commit_message_negative_regex": "ssh\:\/\/", "branch_name_regex": "", "deny_delete_tag": false, "created_at": "2012-10-12T17:04:47Z", "member_check": false, "prevent_secrets": false, "author_email_regex": "", "file_name_regex": "", "max_file_size": 5, "commit_committer_check": false, "reject_unsigned_commits": false } +``` + +使用 GitLab [Premium,Silver 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`commit_committer_check`和`reject_unsigned_commits`参数: + +``` +{ "id": 1, "project_id": 3, "commit_committer_check": false, "reject_unsigned_commits": false ... } +``` + +### Add project push rule[](#add-project-push-rule "Permalink") + +将推送规则添加到指定项目. + +``` +POST /projects/:id/push_rule +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目或 NAMESPACE / PROJECT_NAME 的 ID | +| `deny_delete_tag` | boolean | no | 拒绝删除标签 | +| `member_check` | boolean | no | 限制作者(电子邮件)对现有 GitLab 用户的提交 | +| `prevent_secrets` | boolean | no | GitLab 将拒绝任何可能包含机密的文件 | +| `commit_message_regex` | string | no | 所有提交消息都必须与此匹配,例如`Fixed \d+\..*` | +| `commit_message_negative_regex` | string | no | 不允许任何提交消息与此匹配,例如`ssh\:\/\/` | +| `branch_name_regex` | string | no | 所有分支名称必须与此匹配,例如`(feature|hotfix)\/*` | +| `author_email_regex` | string | no | 所有提交作者的电子邮件都必须与此匹配,例如`@my-company.com$` | +| `file_name_regex` | string | no | 所有提交的文件名都**不能**与此匹配,例如`(jar|exe)$` | +| `max_file_size` | integer | no | 档案大小上限(MB) | +| `commit_committer_check` | boolean | no | 用户只能将使用自己的已验证电子邮件之一提交的提交推送到该存储库. | +| `reject_unsigned_commits` | boolean | no | 如果未通过 GPG 签名,则拒绝提交. | + +### Edit project push rule[](#edit-project-push-rule "Permalink") + +编辑指定项目的推送规则. + +``` +PUT /projects/:id/push_rule +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目或 NAMESPACE / PROJECT_NAME 的 ID | +| `deny_delete_tag` | boolean | no | 拒绝删除标签 | +| `member_check` | boolean | no | 限制作者(电子邮件)对现有 GitLab 用户的提交 | +| `prevent_secrets` | boolean | no | GitLab will reject any files that are likely to contain secrets | +| `commit_message_regex` | string | no | 所有提交消息都必须与此匹配,例如`Fixed \d+\..*` | +| `commit_message_negative_regex` | string | no | 不允许任何提交消息与此匹配,例如`ssh\:\/\/` | +| `branch_name_regex` | string | no | 所有分支名称必须与此匹配,例如`(feature|hotfix)\/*` | +| `author_email_regex` | string | no | 所有提交作者的电子邮件都必须与此匹配,例如`@my-company.com$` | +| `file_name_regex` | string | no | 所有提交的文件名都**不能**与此匹配,例如`(jar|exe)$` | +| `max_file_size` | integer | no | 档案大小上限(MB) | +| `commit_committer_check` | boolean | no | 用户只能将使用自己的已验证电子邮件之一提交的提交推送到该存储库. | +| `reject_unsigned_commits` | boolean | no | 没有 GPG 签名时拒绝提交. | + +### Delete project push rule[](#delete-project-push-rule "Permalink") + +在[GitLab Starter](https://about.gitlab.com/pricing/) 9.0 中引入. + +从项目中删除推送规则. 这是幂等方法,可以多次调用. 推送规则是否可用. + +``` +DELETE /projects/:id/push_rule +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +## Transfer a project to a new namespace[](#transfer-a-project-to-a-new-namespace "Permalink") + +在 GitLab 11.1 中引入. + +``` +PUT /projects/:id/transfer +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `namespace` | integer/string | yes | 要转移到项目的名称空间的 ID 或路径 | + +## Branches[](#branches "Permalink") + +在" [分支机构"](branches.html)文档中了解更多信息. + +## Project Import/Export[](#project-importexport "Permalink") + +在[项目导入/导出](project_import_export.html)文档中了解更多信息. + +## Project members[](#project-members "Permalink") + +在[项目成员](members.html)文档中了解更多信息. + +## Start the pull mirroring process for a Project[](#start-the-pull-mirroring-process-for-a-project-starter "Permalink") + +在[GitLab Starter](https://about.gitlab.com/pricing/) 10.3 中引入. + +``` +POST /projects/:id/mirror/pull +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/mirror/pull" +``` + +## Project badges[](#project-badges "Permalink") + +在[Project Badges](project_badges.html)文档中了解更多信息. + +## Issue and merge request description templates[](#issue-and-merge-request-description-templates "Permalink") + +非默认的[问题和合并请求描述模板](../user/project/description_templates.html)在项目的存储库中进行管理. 因此,您可以通过[Repositories API](repositories.html)和[Repository Files API](repository_files.html)通过 API 管理它们. + +## Download snapshot of a Git repository[](#download-snapshot-of-a-git-repository "Permalink") + +在 GitLab 10.7 中引入 + +该端点只能由管理用户访问. + +下载项目(或 Wiki,如果需要)Git 存储库的快照. 该快照始终为未压缩的[tar](https://en.wikipedia.org/wiki/Tar_(computing))格式. + +如果存储库损坏到`git clone`不起作用的程度,则快照可能允许检索某些数据. + +``` +GET /projects/:id/snapshot +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `wiki` | boolean | no | 是否下载 Wiki,而不是项目存储库 | \ No newline at end of file diff --git a/_book/docs/354.md b/_book/docs/354.md new file mode 100644 index 0000000000000000000000000000000000000000..fbc6745000c29fc8c28ab04f4512f62792ae76cf --- /dev/null +++ b/_book/docs/354.md @@ -0,0 +1,174 @@ +# Protected branches API + +> 原文:[https://docs.gitlab.com/ee/api/protected_branches.html](https://docs.gitlab.com/ee/api/protected_branches.html) + +* [List protected branches](#list-protected-branches) +* [Get a single protected branch or wildcard protected branch](#get-a-single-protected-branch-or-wildcard-protected-branch) +* [Protect repository branches](#protect-repository-branches) + * [Example with user / group level access](#example-with-user--group-level-access-starter) +* [Unprotect repository branches](#unprotect-repository-branches) +* [Require code owner approvals for a single branch](#require-code-owner-approvals-for-a-single-branch) + +# Protected branches API[](#protected-branches-api "Permalink") + +**注意:**此功能是在 GitLab 9.5 中引入的 + +**有效的访问级别** + +访问级别在`ProtectedRefAccess.allowed_access_levels`方法中定义. 当前,这些级别被认可: + +``` +0 => No access +30 => Developer access +40 => Maintainer access +60 => Admin access +``` + +## List protected branches[](#list-protected-branches "Permalink") + +从项目中获取受保护分支的列表. + +``` +GET /projects/:id/protected_branches +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `search` | string | no | 要搜索的受保护分支的名称或名称的一部分 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_branches" +``` + +响应示例: + +``` +[ { "id": 1, "name": "master", "push_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "merge_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" }, ... ] +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`user_id`和`group_id`参数: + +响应示例: + +``` +[ { "id": 1, "name": "master", "push_access_levels": [ { "access_level": 40, "user_id": null, "group_id": null, "access_level_description": "Maintainers" } ], "merge_access_levels": [ { "access_level": null, "user_id": null, "group_id": 1234, "access_level_description": "Example Merge Group" } ], "code_owner_approval_required": "false" }, ... ] +``` + +## Get a single protected branch or wildcard protected branch[](#get-a-single-protected-branch-or-wildcard-protected-branch "Permalink") + +获取单个受保护分支或通配符受保护分支. + +``` +GET /projects/:id/protected_branches/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 分支或通配符的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_branches/master" +``` + +响应示例: + +``` +{ "id": 1, "name": "master", "push_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "merge_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`user_id`和`group_id`参数: + +响应示例: + +``` +{ "id": 1, "name": "master", "push_access_levels": [ { "access_level": 40, "user_id": null, "group_id": null, "access_level_description": "Maintainers" } ], "merge_access_levels": [ { "access_level": null, "user_id": null, "group_id": 1234, "access_level_description": "Example Merge Group" } ], "code_owner_approval_required": "false" } +``` + +## Protect repository branches[](#protect-repository-branches "Permalink") + +使用通配符保护的分支来保护单个存储库分支或几个项目存储库分支. + +``` +POST /projects/:id/protected_branches +``` + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_branches?name=*-stable&push_access_level=30&merge_access_level=30&unprotect_access_level=40" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 分支或通配符的名称 | +| `push_access_level` | string | no | 允许推送的访问级别(默认值: `40` ,维护者访问级别) | +| `merge_access_level` | string | no | 允许合并的访问级别(默认值: `40` ,维护者访问级别) | +| `unprotect_access_level` | string | no | 允许取消保护的访问级别(默认值: `40` ,维护者访问级别) | +| `allowed_to_push` | array | no | 允许推送的访问级别数组,每个访问级别由一个哈希表描述 | +| `allowed_to_merge` | array | no | 允许合并的访问级别数组,每个访问级别由哈希描述 | +| `allowed_to_unprotect` | array | no | 允许取消保护的访问级别数组,每个访问级别由一个哈希表描述 | +| `code_owner_approval_required` | boolean | no | 如果它与[`CODEOWNERS`文件](../user/project/code_owners.html)中的项目匹配,则阻止推送到此分支. (默认值:false) | + +响应示例: + +``` +{ "id": 1, "name": "*-stable", "push_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "merge_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "unprotect_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`user_id`和`group_id`参数: + +响应示例: + +``` +{ "id": 1, "name": "*-stable", "push_access_levels": [ { "access_level": 30, "user_id": null, "group_id": null, "access_level_description": "Developers + Maintainers" } ], "merge_access_levels": [ { "access_level": 30, "user_id": null, "group_id": null, "access_level_description": "Developers + Maintainers" } ], "unprotect_access_levels": [ { "access_level": 40, "user_id": null, "group_id": null, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } +``` + +### Example with user / group level access[](#example-with-user--group-level-access-starter "Permalink") + +`allowed_to_push` / `allowed_to_merge` / `allowed_to_unprotect`数组中的元素应采用`{user_id: integer}` , `{group_id: integer}`或`{access_level: integer}` . 每个用户必须有权访问该项目,并且每个组都必须[共享该项目](../user/project/members/share_project_with_groups.html) . 这些访问级别允许[对受保护的分支访问](../user/project/protected_branches.html#restricting-push-and-merge-access-to-certain-users-starter)进行[更精细的控制,](../user/project/protected_branches.html#restricting-push-and-merge-access-to-certain-users-starter)并在 GitLab 10.3 EE [中将其添加到 API 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3516) . + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_branches?name=*-stable&allowed_to_push%5B%5D%5Buser_id%5D=1" +``` + +响应示例: + +``` +{ "id": 1, "name": "*-stable", "push_access_levels": [ { "access_level": null, "user_id": 1, "group_id": null, "access_level_description": "Administrator" } ], "merge_access_levels": [ { "access_level": 40, "user_id": null, "group_id": null, "access_level_description": "Maintainers" } ], "unprotect_access_levels": [ { "access_level": 40, "user_id": null, "group_id": null, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } +``` + +## Unprotect repository branches[](#unprotect-repository-branches "Permalink") + +取消保护给定的受保护分支或通配符受保护分支. + +``` +DELETE /projects/:id/protected_branches/:name +``` + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_branches/*-stable" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 分支名称 | + +## Require code owner approvals for a single branch[](#require-code-owner-approvals-for-a-single-branch "Permalink") + +为给定的受保护分支受保护分支更新"需要代码所有者批准"选项. + +``` +PATCH /projects/:id/protected_branches/:name +``` + +``` +curl --request PATCH --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_branches/feature-branch" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 分支名称 | +| `code_owner_approval_required` | boolean | no | 如果它与[`CODEOWNERS`文件](../user/project/code_owners.html)中的项目匹配,则阻止推送到此分支. (默认值:false) | \ No newline at end of file diff --git a/_book/docs/355.md b/_book/docs/355.md new file mode 100644 index 0000000000000000000000000000000000000000..db727351855489c47306b27be006e9f42cff4cae --- /dev/null +++ b/_book/docs/355.md @@ -0,0 +1,108 @@ +# Protected tags API + +> 原文:[https://docs.gitlab.com/ee/api/protected_tags.html](https://docs.gitlab.com/ee/api/protected_tags.html) + +* [List protected tags](#list-protected-tags) +* [Get a single protected tag or wildcard protected tag](#get-a-single-protected-tag-or-wildcard-protected-tag) +* [Protect repository tags](#protect-repository-tags) +* [Unprotect repository tags](#unprotect-repository-tags) + +# Protected tags API[](#protected-tags-api "Permalink") + +**注意:**此功能是在 GitLab 11.3 中引入的 + +**有效的访问级别** + +当前,这些级别被认可: + +``` +0 => No access +30 => Developer access +40 => Maintainer access +``` + +## List protected tags[](#list-protected-tags "Permalink") + +从项目中获取受保护标签的列表. 此函数使用分页参数`page`和`per_page`来限制受保护标签的列表. + +``` +GET /projects/:id/protected_tags +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_tags" +``` + +响应示例: + +``` +[ { "name": "release-1-0", "create_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ] }, ... ] +``` + +## Get a single protected tag or wildcard protected tag[](#get-a-single-protected-tag-or-wildcard-protected-tag "Permalink") + +获取单个受保护标签或通配符受保护标签. 分页参数`page`和`per_page`可用于限制受保护标签的列表. + +``` +GET /projects/:id/protected_tags/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 标签或通配符的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_tags/release-1-0" +``` + +响应示例: + +``` +{ "name": "release-1-0", "create_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ] } +``` + +## Protect repository tags[](#protect-repository-tags "Permalink") + +使用通配符保护的标签保护单个存储库标签或几个项目存储库标签. + +``` +POST /projects/:id/protected_tags +``` + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_tags?name=*-stable&create_access_level=30" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 标签或通配符的名称 | +| `create_access_level` | string | no | 允许创建的访问级别(默认值: `40` ,维护者访问级别) | + +响应示例: + +``` +{ "name": "*-stable", "create_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ] } +``` + +## Unprotect repository tags[](#unprotect-repository-tags "Permalink") + +取消保护给定的受保护标签或通配符受保护标签. + +``` +DELETE /projects/:id/protected_tags/:name +``` + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_tags/*-stable" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 标签名称 | \ No newline at end of file diff --git a/_book/docs/356.md b/_book/docs/356.md new file mode 100644 index 0000000000000000000000000000000000000000..4da3b1bccf63a03875289155cf5f1c08ddb1afa4 --- /dev/null +++ b/_book/docs/356.md @@ -0,0 +1,195 @@ +# Releases API + +> 原文:[https://docs.gitlab.com/ee/api/releases/](https://docs.gitlab.com/ee/api/releases/) + +* [List Releases](#list-releases) +* [Get a Release by a tag name](#get-a-release-by-a-tag-name) +* [Create a release](#create-a-release) +* [Collect release evidence](#collect-release-evidence-premium-only) +* [Update a release](#update-a-release) +* [Delete a Release](#delete-a-release) +* [Upcoming Releases](#upcoming-releases) + +# Releases API[](#releases-api "Permalink") + +版本历史 + +* 在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766) . +* 使用此 API,您可以操纵 GitLab 的[Release](../../user/project/releases/index.html)条目. +* 有关将链接作为发布资产进行操作,请参见[Release Links API](links.html) . +* 在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/26019)了发布证据. + +## List Releases[](#list-releases "Permalink") + +分页发布列表,按`released_at`排序. + +``` +GET /projects/:id/releases +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases" +``` + +响应示例: + +``` +[ { "tag_name":"v0.2", "description":"## CHANGELOG\r\n\r\n- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2740\r\n- Prevent private snippets from being embeddable.\r\n- Add subresources removal to member destroy service.", "name":"Awesome app v0.2 beta", "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eEscape label and milestone titles to prevent XSS in GFM autocomplete. !2740\u003c/li\u003e\n\u003cli\u003ePrevent private snippets from being embeddable.\u003c/li\u003e\n\u003cli\u003eAdd subresources removal to member destroy service.\u003c/li\u003e\n\u003c/ul\u003e", "created_at":"2019-01-03T01:56:19.539Z", "released_at":"2019-01-03T01:56:19.539Z", "author":{ "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/root" }, "commit":{ "id":"079e90101242458910cccd35eab0e211dfc359c0", "short_id":"079e9010", "title":"Update README.md", "created_at":"2019-01-03T01:55:38.000Z", "parent_ids":[ "f8d3d94cbd347e924aa7b715845e439d00e80ca4" ], "message":"Update README.md", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2019-01-03T01:55:38.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:55:38.000Z" }, "milestones": [ { "id":51, "iid":1, "project_id":24, "title":"v1.0-rc", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"closed", "created_at":"2019-07-12T19:45:44.256Z", "updated_at":"2019-07-12T19:45:44.256Z", "due_date":"2019-08-16T11:00:00.256Z", "start_date":"2019-07-30T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1", "issue_stats": { "total": 98, "closed": 76 } }, { "id":52, "iid":2, "project_id":24, "title":"v1.0", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"closed", "created_at":"2019-07-16T14:00:12.256Z", "updated_at":"2019-07-16T14:00:12.256Z", "due_date":"2019-08-16T11:00:00.256Z", "start_date":"2019-07-30T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2", "issue_stats": { "total": 24, "closed": 21 } } ], "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", "assets":{ "count":6, "sources":[ { "format":"zip", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.zip" }, { "format":"tar.gz", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar.gz" }, { "format":"tar.bz2", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar.bz2" }, { "format":"tar", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar" } ], "links":[ { "id":2, "name":"awesome-v0.2.msi", "url":"http://192.168.10.15:3000/msi", "external":true, "link_type":"other" }, { "id":1, "name":"awesome-v0.2.dmg", "url":"http://192.168.10.15:3000", "external":true, "link_type":"other" } ], "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.2/evidence.json" }, "evidences":[ { sha: "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", filepath: "https://gitlab.example.com/root/awesome-app/-/releases/v0.2/evidence.json", collected_at: "2019-01-03T01:56:19.539Z" } ] }, { "tag_name":"v0.1", "description":"## CHANGELOG\r\n\r\n-Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516", "name":"Awesome app v0.1 alpha", "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e", "created_at":"2019-01-03T01:55:18.203Z", "released_at":"2019-01-03T01:55:18.203Z", "author":{ "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/root" }, "commit":{ "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4", "short_id":"f8d3d94c", "title":"Initial commit", "created_at":"2019-01-03T01:53:28.000Z", "parent_ids":[ ], "message":"Initial commit", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2019-01-03T01:53:28.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:53:28.000Z" }, "assets":{ "count":4, "sources":[ { "format":"zip", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip" }, { "format":"tar.gz", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz" }, { "format":"tar.bz2", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2" }, { "format":"tar", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar" } ], "links":[ ], "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json" }, "evidences":[ { sha: "c3ffedec13af470e760d6cdfb08790f71cf52c6cde4d", filepath: "https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json", collected_at: "2019-01-03T01:55:18.203Z" } ] } ] +``` + +## Get a Release by a tag name[](#get-a-release-by-a-tag-name "Permalink") + +获取给定标签的发布. + +``` +GET /projects/:id/releases/:tag_name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 将在其中创建发行版的标签. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" +``` + +响应示例: + +``` +{ "tag_name":"v0.1", "description":"## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516", "name":"Awesome app v0.1 alpha", "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e", "created_at":"2019-01-03T01:55:18.203Z", "released_at":"2019-01-03T01:55:18.203Z", "author":{ "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/root" }, "commit":{ "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4", "short_id":"f8d3d94c", "title":"Initial commit", "created_at":"2019-01-03T01:53:28.000Z", "parent_ids":[ ], "message":"Initial commit", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2019-01-03T01:53:28.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:53:28.000Z" }, "milestones": [ { "id":51, "iid":1, "project_id":24, "title":"v1.0-rc", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"closed", "created_at":"2019-07-12T19:45:44.256Z", "updated_at":"2019-07-12T19:45:44.256Z", "due_date":"2019-08-16T11:00:00.256Z", "start_date":"2019-07-30T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1", "issue_stats": { "total": 98, "closed": 76 } }, { "id":52, "iid":2, "project_id":24, "title":"v1.0", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"closed", "created_at":"2019-07-16T14:00:12.256Z", "updated_at":"2019-07-16T14:00:12.256Z", "due_date":"2019-08-16T11:00:00.256Z", "start_date":"2019-07-30T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2", "issue_stats": { "total": 24, "closed": 21 } } ], "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", "assets":{ "count":5, "sources":[ { "format":"zip", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip" }, { "format":"tar.gz", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz" }, { "format":"tar.bz2", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2" }, { "format":"tar", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar" } ], "links":[ { "id":3, "name":"hoge", "url":"https://gitlab.example.com/root/awesome-app/-/tags/v0.11.1/binaries/linux-amd64", "external":true, "link_type":"other" } ] }, "evidences":[ { sha: "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", filepath: "https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json", collected_at: "2019-07-16T14:00:12.256Z" } ] } +``` + +## Create a release[](#create-a-release "Permalink") + +创建发布. 您需要对存储库的推送访问权限才能创建发行版. + +``` +POST /projects/:id/releases +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `name` | string | no | 发布名称. | +| `tag_name` | string | yes | 将在其中创建发行版的标签. | +| `description` | string | no | 版本说明. 您可以使用[Markdown](../../user/markdown.html) . | +| `ref` | string | 是的,如果`tag_name`不存在 | If `tag_name` doesn’t exist, the release will be created from `ref`. It can be a commit SHA, another tag name, or a branch name. | +| `milestones` | 字符串数组 | no | 与发行版关联的每个里程碑的标题. | +| `assets:links` | 哈希数组 | no | 一系列资产链接. | +| `assets:links:name` | string | 要求: `assets:links` | 链接的名称. | +| `assets:links:url` | string | 要求: `assets:links` | 链接的 URL. | +| `assets:links:filepath` | string | no | [直接资产链接的](../../user/project/releases.html)可选路径. | +| `assets:links:link_type` | string | no | 链接的类型: `other` , `runbook` , `image` , `package` . 默认为`other` . | +| `released_at` | datetime | no | 发布准备/准备就绪的日期. 默认为当前时间. 预期为 ISO 8601 格式( `2019-03-15T08:00:00Z` ). | + +请求示例: + +``` +curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" \ + --data '{ "name": "New release", "tag_name": "v0.3", "description": "Super nice release", "milestones": ["v1.0", "v1.0-rc"], "assets": { "links": [{ "name": "hoge", "url": "https://google.com", "filepath": "/binaries/linux-amd64", "link_type":"other" }] } }' \ + --request POST https://gitlab.example.com/api/v4/projects/24/releases +``` + +响应示例: + +``` +{ "tag_name":"v0.3", "description":"Super nice release", "name":"New release", "description_html":"\u003cp dir=\"auto\"\u003eSuper nice release\u003c/p\u003e", "created_at":"2019-01-03T02:22:45.118Z", "released_at":"2019-01-03T02:22:45.118Z", "author":{ "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/root" }, "commit":{ "id":"079e90101242458910cccd35eab0e211dfc359c0", "short_id":"079e9010", "title":"Update README.md", "created_at":"2019-01-03T01:55:38.000Z", "parent_ids":[ "f8d3d94cbd347e924aa7b715845e439d00e80ca4" ], "message":"Update README.md", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2019-01-03T01:55:38.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:55:38.000Z" }, "milestones": [ { "id":51, "iid":1, "project_id":24, "title":"v1.0-rc", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"closed", "created_at":"2019-07-12T19:45:44.256Z", "updated_at":"2019-07-12T19:45:44.256Z", "due_date":"2019-08-16T11:00:00.256Z", "start_date":"2019-07-30T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1", "issue_stats": { "total": 99, "closed": 76 } }, { "id":52, "iid":2, "project_id":24, "title":"v1.0", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"closed", "created_at":"2019-07-16T14:00:12.256Z", "updated_at":"2019-07-16T14:00:12.256Z", "due_date":"2019-08-16T11:00:00.256Z", "start_date":"2019-07-30T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2", "issue_stats": { "total": 24, "closed": 21 } } ], "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", "evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", "assets":{ "count":5, "sources":[ { "format":"zip", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.3/awesome-app-v0.3.zip" }, { "format":"tar.gz", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.3/awesome-app-v0.3.tar.gz" }, { "format":"tar.bz2", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.3/awesome-app-v0.3.tar.bz2" }, { "format":"tar", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.3/awesome-app-v0.3.tar" } ], "links":[ { "id":3, "name":"hoge", "url":"https://gitlab.example.com/root/awesome-app/-/tags/v0.11.1/binaries/linux-amd64", "external":true, "link_type":"other" } ], "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.3/evidence.json" }, } +``` + +## Collect release evidence[](#collect-release-evidence-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199065) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10. + +为现有版本创建证据. + +``` +POST /projects/:id/releases/:tag_name/evidence +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 将在其中创建发行版的标签. | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/evidence" +``` + +响应示例: + +``` +200 +``` + +## Update a release[](#update-a-release "Permalink") + +更新发行版. + +``` +PUT /projects/:id/releases/:tag_name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 将在其中创建发行版的标签. | +| `name` | string | no | 发布名称. | +| `description` | string | no | 版本说明. 您可以使用[Markdown](../../user/markdown.html) . | +| `milestones` | 字符串数组 | no | 与发布关联的每个里程碑的标题( `[]`从发布中删除所有里程碑). | +| `released_at` | datetime | no | 发布准备/准备就绪的日期. 预期为 ISO 8601 格式( `2019-03-15T08:00:00Z` ). | + +请求示例: + +``` +curl --header 'Content-Type: application/json' --request PUT --data '{"name": "new name", "milestones": ["v1.2"]}' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" +``` + +响应示例: + +``` +{ "tag_name":"v0.1", "description":"## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516", "name":"new name", "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e", "created_at":"2019-01-03T01:55:18.203Z", "released_at":"2019-01-03T01:55:18.203Z", "author":{ "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/root" }, "commit":{ "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4", "short_id":"f8d3d94c", "title":"Initial commit", "created_at":"2019-01-03T01:53:28.000Z", "parent_ids":[ ], "message":"Initial commit", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2019-01-03T01:53:28.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:53:28.000Z" }, "milestones": [ { "id":53, "iid":3, "project_id":24, "title":"v1.0", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"active", "created_at":"2019-09-01T13:00:00.256Z", "updated_at":"2019-09-01T13:00:00.256Z", "due_date":"2019-09-20T13:00:00.256Z", "start_date":"2019-09-05T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/3", "issue_stats": { "opened": 11, "closed": 78 } } ], "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", "evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", "assets":{ "count":4, "sources":[ { "format":"zip", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip" }, { "format":"tar.gz", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz" }, { "format":"tar.bz2", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2" }, { "format":"tar", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar" } ], "links":[ ], "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json" }, } +``` + +## Delete a Release[](#delete-a-release "Permalink") + +删除发行版. 删除发行版不会删除关联的标签. + +``` +DELETE /projects/:id/releases/:tag_name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 将在其中创建发行版的标签. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" +``` + +响应示例: + +``` +{ "tag_name":"v0.1", "description":"## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516", "name":"new name", "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e", "created_at":"2019-01-03T01:55:18.203Z", "released_at":"2019-01-03T01:55:18.203Z", "author":{ "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/root" }, "commit":{ "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4", "short_id":"f8d3d94c", "title":"Initial commit", "created_at":"2019-01-03T01:53:28.000Z", "parent_ids":[ ], "message":"Initial commit", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2019-01-03T01:53:28.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:53:28.000Z" }, "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", "evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", "assets":{ "count":4, "sources":[ { "format":"zip", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip" }, { "format":"tar.gz", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz" }, { "format":"tar.bz2", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2" }, { "format":"tar", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar" } ], "links":[ ], "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json" }, } +``` + +## Upcoming Releases[](#upcoming-releases "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/38105) . + +有一种剥离`released_at`属性设置为将来的日期将被标记在 UI **即将推出**的**版本** : + +[![Upcoming release](img/c1ff864dc0ff6749087bc64b4781d767.png)](img/upcoming_release_v12_1.png) \ No newline at end of file diff --git a/_book/docs/357.md b/_book/docs/357.md new file mode 100644 index 0000000000000000000000000000000000000000..fcd51acc20d0288ba448ae9f6f0b2ff52f0360b5 --- /dev/null +++ b/_book/docs/357.md @@ -0,0 +1,155 @@ +# Release links API + +> 原文:[https://docs.gitlab.com/ee/api/releases/links.html](https://docs.gitlab.com/ee/api/releases/links.html) + +* [Get links](#get-links) +* [Get a link](#get-a-link) +* [Create a link](#create-a-link) +* [Update a link](#update-a-link) +* [Delete a link](#delete-a-link) + +# Release links API[](#release-links-api "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766) . + +使用此 API,您可以操纵 GitLab 的[Release](../../user/project/releases/index.html)链接. 有关操纵其他 Release 资产的信息,请参见[Release API](index.html) . GitLab 支持指向`http` , `https`和`ftp`资产的链接. + +## Get links[](#get-links "Permalink") + +从发布中获取资产作为链接. + +``` +GET /projects/:id/releases/:tag_name/assets/links +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 与发行版关联的标签. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links" +``` + +响应示例: + +``` +[ { "id":2, "name":"awesome-v0.2.msi", "url":"http://192.168.10.15:3000/msi", "external":true, "link_type":"other" }, { "id":1, "name":"awesome-v0.2.dmg", "url":"http://192.168.10.15:3000", "external":true, "link_type":"other" } ] +``` + +## Get a link[](#get-a-link "Permalink") + +从发布中获取资产作为链接. + +``` +GET /projects/:id/releases/:tag_name/assets/links/:link_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 与发行版关联的标签. | +| `link_id` | integer | yes | 链接的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1" +``` + +响应示例: + +``` +{ "id":1, "name":"awesome-v0.2.dmg", "url":"http://192.168.10.15:3000", "external":true, "link_type":"other" } +``` + +## Create a link[](#create-a-link "Permalink") + +从发布创建资产作为链接. + +``` +POST /projects/:id/releases/:tag_name/assets/links +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 与发行版关联的标签. | +| `name` | string | yes | 链接的名称. | +| `url` | string | yes | 链接的 URL. | +| `link_type` | string | no | 链接的类型: `other` , `runbook` , `image` , `package` . 默认为`other` . | + +请求示例: + +``` +curl --request POST \ + --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" \ + --data name="awesome-v0.2.dmg" \ + --data url="http://192.168.10.15:3000" \ + "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links" +``` + +响应示例: + +``` +{ "id":1, "name":"awesome-v0.2.dmg", "url":"http://192.168.10.15:3000", "external":true, "link_type":"other" } +``` + +## Update a link[](#update-a-link "Permalink") + +将资产更新为发布中的链接. + +``` +PUT /projects/:id/releases/:tag_name/assets/links/:link_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 与发行版关联的标签. | +| `link_id` | integer | yes | 链接的 ID. | +| `name` | string | no | 链接的名称. | +| `url` | string | no | 链接的 URL. | +| `link_type` | string | no | 链接的类型: `other` , `runbook` , `image` , `package` . 默认为`other` . | + +**注意**您必须至少指定`name`或`url` + +请求示例: + +``` +curl --request PUT --data name="new name" --data link_type="runbook" --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1" +``` + +响应示例: + +``` +{ "id":1, "name":"new name", "url":"http://192.168.10.15:3000", "external":true, "link_type":"runbook" } +``` + +## Delete a link[](#delete-a-link "Permalink") + +从发布中删除资产作为链接. + +``` +DELETE /projects/:id/releases/:tag_name/assets/links/:link_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 与发行版关联的标签. | +| `link_id` | integer | yes | 链接的 ID. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1" +``` + +响应示例: + +``` +{ "id":1, "name":"new name", "url":"http://192.168.10.15:3000", "external":true, "link_type":"other" } +``` \ No newline at end of file diff --git a/_book/docs/358.md b/_book/docs/358.md new file mode 100644 index 0000000000000000000000000000000000000000..a58f425b845128e660f4a30d1d13b5b77765f007 --- /dev/null +++ b/_book/docs/358.md @@ -0,0 +1,150 @@ +# Repositories API + +> 原文:[https://docs.gitlab.com/ee/api/repositories.html](https://docs.gitlab.com/ee/api/repositories.html) + +* [List repository tree](#list-repository-tree) +* [Get a blob from repository](#get-a-blob-from-repository) +* [Raw blob content](#raw-blob-content) +* [Get file archive](#get-file-archive) +* [Compare branches, tags or commits](#compare-branches-tags-or-commits) +* [Contributors](#contributors) +* [Merge Base](#merge-base) + +# Repositories API[](#repositories-api "Permalink") + +## List repository tree[](#list-repository-tree "Permalink") + +获取项目中存储库文件和目录的列表. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +此命令提供的功能与`git ls-tree`命令基本相同. 有关更多信息,请参阅[Git internals 文档](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects/#_tree_objects)中的*Tree Objects*部分. + +``` +GET /projects/:id/repository/tree +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `path` (可选)-存储库中的路径. 用于获取子目录的内容 +* `ref` (可选)-存储库分支或标记的名称,或者如果未提供默认分支的名称 +* `recursive` (可选)-用于获取递归树的布尔值(默认为 false) +* `per_page` (可选)-每页显示的结果数. 如果未指定,则默认为`20` + +``` +[ { "id": "a1e8f8d745cc87e3a9248358d9352bb7f9a0aeba", "name": "html", "type": "tree", "path": "files/html", "mode": "040000" }, { "id": "4535904260b1082e14f867f7a24fd8c21495bde3", "name": "images", "type": "tree", "path": "files/images", "mode": "040000" }, { "id": "31405c5ddef582c5a9b7a85230413ff90e2fe720", "name": "js", "type": "tree", "path": "files/js", "mode": "040000" }, { "id": "cc71111cfad871212dc99572599a568bfe1e7e00", "name": "lfs", "type": "tree", "path": "files/lfs", "mode": "040000" }, { "id": "fd581c619bf59cfdfa9c8282377bb09c2f897520", "name": "markdown", "type": "tree", "path": "files/markdown", "mode": "040000" }, { "id": "23ea4d11a4bdd960ee5320c5cb65b5b3fdbc60db", "name": "ruby", "type": "tree", "path": "files/ruby", "mode": "040000" }, { "id": "7d70e02340bac451f281cecf0a980907974bd8be", "name": "whitespace", "type": "blob", "path": "files/whitespace", "mode": "100644" } ] +``` + +## Get a blob from repository[](#get-a-blob-from-repository "Permalink") + +Allows you to receive information about blob in repository like size and content. Note that blob content is Base64 encoded. This endpoint can be accessed without authentication if the repository is publicly accessible. + +``` +GET /projects/:id/repository/blobs/:sha +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `sha` (必填)-Blob SHA + +## Raw blob content[](#raw-blob-content "Permalink") + +通过 blob SHA 获取 blob 的原始文件内容. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/blobs/:sha/raw +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `sha` (必填)-Blob SHA + +## Get file archive[](#get-file-archive "Permalink") + +获取存储库的存档. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +该端点的速率限制阈值为每分钟 5 个请求. + +``` +GET /projects/:id/repository/archive[.format] +``` + +`format`是归档格式的可选后缀. 默认值为`tar.gz` 选项是`tar.gz` , `tar.bz2` , `tbz` , `tbz2` , `tb2` , `bz2` , `tar`和`zip` . 例如,指定`archive.zip`将以 ZIP 格式发送存档. + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `sha` (可选)-提交要下载的 SHA. 可以使用标签,分支引用或 SHA. 如果未指定,则默认为默认分支的尖端. 例如: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.com/api/v4/projects//repository/archive?sha=" +``` + +## Compare branches, tags or commits[](#compare-branches-tags-or-commits "Permalink") + +如果可公开访问该存储库,则无需身份验证即可访问此端点. 请注意,如果达到[差异限制](../development/diffs.html#diff-limits) ,差异可能会有一个空的差异字符串. + +``` +GET /projects/:id/repository/compare +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `from` (必填)-提交 SHA 或分支名称 +* `to` (必需)-提交 SHA 或分支名称 +* `straight` (可选)-比较方法,对于`from`和`to`之间( `from` .. `to` )之间的直接比较,为`true`对于使用合并基数( `from` ... `to` )'比较`to` `false` . 默认值为`false` . + +``` +GET /projects/:id/repository/compare?from=master&to=feature +``` + +Response: + +``` + { "commit": { "id": "12d65c8dd2b2676fa3ac47d955accc085a37a9c1", "short_id": "12d65c8dd2b", "title": "JS fix", "author_name": "Example User", "author_email": "user@example.com", "created_at": "2014-02-27T10:27:00+02:00" }, "commits": [{ "id": "12d65c8dd2b2676fa3ac47d955accc085a37a9c1", "short_id": "12d65c8dd2b", "title": "JS fix", "author_name": "Example User", "author_email": "user@example.com", "created_at": "2014-02-27T10:27:00+02:00" }], "diffs": [{ "old_path": "files/js/application.js", "new_path": "files/js/application.js", "a_mode": null, "b_mode": "100644", "diff": "--- a/files/js/application.js\n+++ b/files/js/application.js\n@@ -24,8 +24,10 @@\n //= require g.raphael-min\n //= require g.bar-min\n //= require branch-graph\n-//= require highlightjs.min\n-//= require ace/ace\n //= require_tree .\n //= require d3\n //= require underscore\n+\n+function fix() { \n+ alert(\"Fixed\")\n+}", "new_file": false, "renamed_file": false, "deleted_file": false }], "compare_timeout": false, "compare_same_ref": false } +``` + +## Contributors[](#contributors "Permalink") + +获取存储库贡献者列表. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/contributors +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `order_by` (可选)-返回按`name` , `email`或`commits` (按提交日期排序)字段排序的贡献者. 默认为`commits` +* `sort` (可选)-返回贡献者按`asc`或`desc`顺序排序. 默认为`asc` + +Response: + +``` +[{ "name": "Example User", "email": "example@example.com", "commits": 117, "additions": 2097, "deletions": 517 }, { "name": "Sample User", "email": "sample@example.com", "commits": 33, "additions": 338, "deletions": 244 }] +``` + +## Merge Base[](#merge-base "Permalink") + +获取 2 个或更多引用(提交 SHA,分支名称或标签)的公共祖先. + +``` +GET /projects/:id/repository/merge_base +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `refs` | array | yes | 裁判找到共同的祖先,可以传递多个裁判 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/merge_base?refs[]=304d257dcb821665ab5110318fc58a007bd104ed&refs[]=0031876facac3f2b2702a0e53a26e89939a42209" +``` + +响应示例: + +``` +{ "id": "1a0b36b3cdad1d2ee32457c102a8c0b7056fa863", "short_id": "1a0b36b3", "title": "Initial commit", "created_at": "2014-02-27T08:03:18.000Z", "parent_ids": [], "message": "Initial commit\n", "author_name": "Example User", "author_email": "user@example.com", "authored_date": "2014-02-27T08:03:18.000Z", "committer_name": "Example User", "committer_email": "user@example.com", "committed_date": "2014-02-27T08:03:18.000Z" } +``` \ No newline at end of file diff --git a/_book/docs/359.md b/_book/docs/359.md new file mode 100644 index 0000000000000000000000000000000000000000..bece27cea359a6c2f36459d5455a75bd145127f8 --- /dev/null +++ b/_book/docs/359.md @@ -0,0 +1,238 @@ +# Repository files API + +> 原文:[https://docs.gitlab.com/ee/api/repository_files.html](https://docs.gitlab.com/ee/api/repository_files.html) + +* [Get file from repository](#get-file-from-repository) +* [Get file blame from repository](#get-file-blame-from-repository) +* [Get raw file from repository](#get-raw-file-from-repository) +* [Create new file in repository](#create-new-file-in-repository) +* [Update existing file in repository](#update-existing-file-in-repository) +* [Delete existing file in repository](#delete-existing-file-in-repository) + +# Repository files API[](#repository-files-api "Permalink") + +**库文件的 CRUD** + +**使用此 API 创建,读取,更新和删除存储库文件** + +下表描述了使用[个人访问令牌](../user/profile/personal_access_tokens.html)可用的不同范围. + +| Scope | Description | +| --- | --- | +| `read_repository` | 允许对存储库文件进行读取访问. | +| `api` | 允许对存储库文件进行读写访问. | + +`read_repository` scope was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23534) in GitLab 11.6. + +## Get file from repository[](#get-file-from-repository "Permalink") + +允许您接收有关存储库中文件的信息,例如名称,大小,内容. 请注意,文件内容是 Base64 编码的. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/files/:file_path +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master" +``` + +响应示例: + +``` +{ "file_name": "key.rb", "file_path": "app/models/key.rb", "size": 1476, "encoding": "base64", "content": "IyA9PSBTY2hlbWEgSW5mb3...", "content_sha256": "4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481", "ref": "master", "blob_id": "79f7bbd25901e8334750839545a9bd021f0e4c83", "commit_id": "d5a3ff139356ce33e37e73add446f16869741b50", "last_commit_id": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d" } +``` + +Parameters: + +* `file_path` (必需)-URL 编码的新文件的完整路径. 例如 lib%2Fclass%2Erb +* `ref` (必填)-分支,标记或提交的名称 + +**注意:** `blob_id`是 blob SHA,请参见[存储库-从存储库获取 blob](repositories.html#get-a-blob-from-repository) + +除了`GET`方法外,您还可以使用`HEAD`来获取文件元数据. + +``` +HEAD /projects/:id/repository/files/:file_path +``` + +``` +curl --head --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master" +``` + +响应示例: + +``` +HTTP/1.1 200 OK +... +X-Gitlab-Blob-Id: 79f7bbd25901e8334750839545a9bd021f0e4c83 +X-Gitlab-Commit-Id: d5a3ff139356ce33e37e73add446f16869741b50 +X-Gitlab-Content-Sha256: 4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481 +X-Gitlab-Encoding: base64 +X-Gitlab-File-Name: key.rb +X-Gitlab-File-Path: app/models/key.rb +X-Gitlab-Last-Commit-Id: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d +X-Gitlab-Ref: master +X-Gitlab-Size: 1476 +... +``` + +## Get file blame from repository[](#get-file-blame-from-repository "Permalink") + +允许您接收责备信息. 每个责任范围包含行和相应的提交信息. + +``` +GET /projects/:id/repository/files/:file_path/blame +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/13083/repository/files/path%2Fto%2Ffile.rb/blame?ref=master" +``` + +响应示例: + +``` +[ { "commit": { "id": "d42409d56517157c48bf3bd97d3f75974dde19fb", "message": "Add feature\n\nalso fix bug\n", "parent_ids": [ "cc6e14f9328fa6d7b5a0d3c30dc2002a3f2a3822" ], "authored_date": "2015-12-18T08:12:22.000Z", "author_name": "John Doe", "author_email": "john.doe@example.com", "committed_date": "2015-12-18T08:12:22.000Z", "committer_name": "John Doe", "committer_email": "john.doe@example.com" }, "lines": [ "require 'fileutils'", "require 'open3'", "" ] }, ... ] +``` + +Parameters: + +* `file_path` (必需)-URL 编码的新文件的完整路径. 例如 lib%2Fclass%2Erb +* `ref` (必填)-分支,标记或提交的名称 + +**注意:** `HEAD`方法仅返回文件元数据,如[从存储库](repository_files.html#get-file-from-repository)中[获取文件中所示](repository_files.html#get-file-from-repository) . + +``` +curl --head --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/13083/repository/files/path%2Fto%2Ffile.rb/blame?ref=master" +``` + +响应示例: + +``` +HTTP/1.1 200 OK +... +X-Gitlab-Blob-Id: 79f7bbd25901e8334750839545a9bd021f0e4c83 +X-Gitlab-Commit-Id: d5a3ff139356ce33e37e73add446f16869741b50 +X-Gitlab-Content-Sha256: 4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481 +X-Gitlab-Encoding: base64 +X-Gitlab-File-Name: file.rb +X-Gitlab-File-Path: path/to/file.rb +X-Gitlab-Last-Commit-Id: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d +X-Gitlab-Ref: master +X-Gitlab-Size: 1476 +... +``` + +## Get raw file from repository[](#get-raw-file-from-repository "Permalink") + +``` +GET /projects/:id/repository/files/:file_path/raw +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb/raw?ref=master" +``` + +Parameters: + +* `file_path` (必需)-URL 编码的新文件的完整路径. 例如 lib%2Fclass%2Erb +* `ref` (必填)-分支,标记或提交的名称 + +**注意:**像[从存储库中获取文件](repository_files.html#get-file-from-repository)一样[,](repository_files.html#get-file-from-repository)您可以使用`HEAD`仅获取文件元数据. + +## Create new file in repository[](#create-new-file-in-repository "Permalink") + +这使您可以创建一个文件. 要使用一个请求创建多个文件,请参阅[commits API](commits.html#create-a-commit-with-multiple-files-and-actions) . + +``` +POST /projects/:id/repository/files/:file_path +``` + +``` +curl --request POST --header 'PRIVATE-TOKEN: ' --header "Content-Type: application/json" \ + --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \ + "content": "some content", "commit_message": "create a new file"}' \ + "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb" +``` + +响应示例: + +``` +{ "file_path": "app/project.rb", "branch": "master" } +``` + +Parameters: + +* `file_path` (必需)-URL 编码的新文件的完整路径. 例如 lib%2Fclass%2Erb +* `branch` (必填)-分支的名称 +* `start_branch` (可选)-从中开始新提交的分支名称 +* `encoding` (可选)-将编码更改为" base64". 默认为文本. +* `author_email` (可选)-指定提交作者的电子邮件地址 +* `author_name` (可选)-指定提交作者的姓名 +* `content` (必填)-文件内容 +* `commit_message` (必填)-提交消息 + +## Update existing file in repository[](#update-existing-file-in-repository "Permalink") + +这使您可以更新单个文件. 有关通过单个请求更新多个文件的信息,请参见[commits API](commits.html#create-a-commit-with-multiple-files-and-actions) . + +``` +PUT /projects/:id/repository/files/:file_path +``` + +``` +curl --request PUT --header 'PRIVATE-TOKEN: ' --header "Content-Type: application/json" \ + --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \ + "content": "some content", "commit_message": "update file"}' \ + "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb" +``` + +响应示例: + +``` +{ "file_path": "app/project.rb", "branch": "master" } +``` + +Parameters: + +* `file_path` (必需)-URL 编码的新文件的完整路径. 例如 lib%2Fclass%2Erb +* `branch` (必填)-分支的名称 +* `start_branch` (可选)-从中开始新提交的分支名称 +* `encoding` (可选)-将编码更改为" base64". 默认为文本. +* `author_email` (可选)-指定提交作者的电子邮件地址 +* `author_name` (可选)-指定提交作者的姓名 +* `content` (必填)-新文件内容 +* `commit_message` (必填)-提交消息 +* `last_commit_id` (可选)-已知文件的最新提交 ID + +如果提交由于任何原因失败,我们将返回 400 错误,并显示非特定错误消息. 提交失败的可能原因包括: + +* `file_path`包含`/../` (试图遍历目录); +* 新文件内容与当前文件内容相同. 也就是说,用户尝试进行空提交; +* 在进行文件编辑时,通过 Git 推送更新了分支. + +当前,GitLab Shell 具有布尔返回码,可防止 GitLab 指定错误. + +## Delete existing file in repository[](#delete-existing-file-in-repository "Permalink") + +这使您可以删除单个文件. 有关通过单个请求删除多个文件的信息,请参见[commits API](commits.html#create-a-commit-with-multiple-files-and-actions) . + +``` +DELETE /projects/:id/repository/files/:file_path +``` + +``` +curl --request DELETE --header 'PRIVATE-TOKEN: ' --header "Content-Type: application/json" \ + --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \ + "commit_message": "delete file"}' \ + "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb" +``` + +Parameters: + +* `file_path` (必需)-URL 编码的新文件的完整路径. 例如 lib%2Fclass%2Erb +* `branch` (必填)-分支的名称 +* `start_branch` (可选)-从中开始新提交的分支名称 +* `author_email` (可选)-指定提交作者的电子邮件地址 +* `author_name` (可选)-指定提交作者的姓名 +* `commit_message` (必填)-提交消息 +* `last_commit_id` (可选)-已知文件的最新提交 ID \ No newline at end of file diff --git a/_book/docs/360.md b/_book/docs/360.md new file mode 100644 index 0000000000000000000000000000000000000000..a12645ec7d7bbdc79d52209b2e36fa620086c94b --- /dev/null +++ b/_book/docs/360.md @@ -0,0 +1,36 @@ +# Repository submodules API + +> 原文:[https://docs.gitlab.com/ee/api/repository_submodules.html](https://docs.gitlab.com/ee/api/repository_submodules.html) + +* [Update existing submodule reference in repository](#update-existing-submodule-reference-in-repository) + +# Repository submodules API[](#repository-submodules-api "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41213) + +## Update existing submodule reference in repository[](#update-existing-submodule-reference-in-repository "Permalink") + +在某些工作流程中,尤其是自动化的工作流程中,更新子模块的引用以使使用它的其他项目保持最新是很有用的. 该端点允许您在特定分支中更新[Git 子模块](https://git-scm.com/book/en/v2/Git-Tools-Submodules)引用. + +``` +PUT /projects/:id/repository/submodules/:submodule +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `submodule` | string | yes | URL 编码的子模块完整路径. 例如, `lib/class.rb` | +| `branch` | string | yes | 要提交的分支名称 | +| `commit_sha` | string | yes | 完全提交 SHA 以将子模块更新为 | +| `commit_message` | string | no | 提交消息. 如果未提供任何消息,则将设置默认消息 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/submodules/lib%2Fmodules%2Fexample" +--data "branch=master&commit_sha=3ddec28ea23acc5caa5d8331a6ecb2a65fc03e88&commit_message=Update submodule reference" +``` + +响应示例: + +``` +{ "id": "ed899a2f4b50b4370feeea94676502b42383c746", "short_id": "ed899a2f4b5", "title": "Updated submodule example_submodule with oid 3ddec28ea23acc5caa5d8331a6ecb2a65fc03e88", "author_name": "Dmitriy Zaporozhets", "author_email": "dzaporozhets@sphereconsultinginc.com", "committer_name": "Dmitriy Zaporozhets", "committer_email": "dzaporozhets@sphereconsultinginc.com", "created_at": "2018-09-20T09:26:24.000-07:00", "message": "Updated submodule example_submodule with oid 3ddec28ea23acc5caa5d8331a6ecb2a65fc03e88", "parent_ids": [ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" ], "committed_date": "2018-09-20T09:26:24.000-07:00", "authored_date": "2018-09-20T09:26:24.000-07:00", "status": null } +``` \ No newline at end of file diff --git a/_book/docs/361.md b/_book/docs/361.md new file mode 100644 index 0000000000000000000000000000000000000000..73ffe54f7b09ba150c70ef323e57d148efb81ca7 --- /dev/null +++ b/_book/docs/361.md @@ -0,0 +1,146 @@ +# Resource label events API + +> 原文:[https://docs.gitlab.com/ee/api/resource_label_events.html](https://docs.gitlab.com/ee/api/resource_label_events.html) + +* [Issues](#issues) + * [List project issue label events](#list-project-issue-label-events) + * [Get single issue label event](#get-single-issue-label-event) +* [Epics](#epics-ultimate) + * [List group epic label events](#list-group-epic-label-events) + * [Get single epic label event](#get-single-epic-label-event) +* [Merge requests](#merge-requests) + * [List project merge request label events](#list-project-merge-request-label-events) + * [Get single merge request label event](#get-single-merge-request-label-event) + +# Resource label events API[](#resource-label-events-api "Permalink") + +资源标签事件可跟踪有关向可发行对象添加或删除对象的时间,对象和对象. + +## Issues[](#issues "Permalink") + +### List project issue label events[](#list-project-issue-label-events "Permalink") + +获取单个问题的所有标签事件的列表. + +``` +GET /projects/:id/issues/:issue_iid/resource_label_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | + +``` +[ { "id": 142, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T13:38:20.077Z", "resource_type": "Issue", "resource_id": 253, "label": { "id": 73, "name": "a1", "color": "#34495E", "description": "" }, "action": "add" }, { "id": 143, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T13:38:20.077Z", "resource_type": "Issue", "resource_id": 253, "label": { "id": 74, "name": "p1", "color": "#0033CC", "description": "" }, "action": "remove" } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_label_events" +``` + +### Get single issue label event[](#get-single-issue-label-event "Permalink") + +返回特定项目问题的单个标签事件 + +``` +GET /projects/:id/issues/:issue_iid/resource_label_events/:resource_label_event_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `resource_label_event_id` | integer | yes | 标签事件的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_label_events/1" +``` + +## Epics[](#epics-ultimate "Permalink") + +### List group epic label events[](#list-group-epic-label-events "Permalink") + +获取单个史诗的所有标签事件的列表. + +``` +GET /groups/:id/epics/:epic_id/resource_label_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | + +``` +[ { "id": 106, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-19T11:43:01.746Z", "resource_type": "Epic", "resource_id": 33, "label": { "id": 73, "name": "a1", "color": "#34495E", "description": "" }, "action": "add" }, { "id": 107, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-19T11:43:01.746Z", "resource_type": "Epic", "resource_id": 33, "label": { "id": 37, "name": "glabel2", "color": "#A8D695", "description": "" }, "action": "add" } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/11/resource_label_events" +``` + +### Get single epic label event[](#get-single-epic-label-event "Permalink") + +返回特定组史诗的单个标签事件 + +``` +GET /groups/:id/epics/:epic_id/resource_label_events/:resource_label_event_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `resource_label_event_id` | integer | yes | 标签事件的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/11/resource_label_events/107" +``` + +## Merge requests[](#merge-requests "Permalink") + +### List project merge request label events[](#list-project-merge-request-label-events "Permalink") + +获取单个合并请求的所有标签事件的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/resource_label_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | + +``` +[ { "id": 119, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T06:17:28.394Z", "resource_type": "MergeRequest", "resource_id": 28, "label": { "id": 74, "name": "p1", "color": "#0033CC", "description": "" }, "action": "add" }, { "id": 120, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T06:17:28.394Z", "resource_type": "MergeRequest", "resource_id": 28, "label": { "id": 41, "name": "project", "color": "#D1D100", "description": "" }, "action": "add" } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/resource_label_events" +``` + +### Get single merge request label event[](#get-single-merge-request-label-event "Permalink") + +返回特定项目合并请求的单个标签事件 + +``` +GET /projects/:id/merge_requests/:merge_request_iid/resource_label_events/:resource_label_event_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `resource_label_event_id` | integer | yes | 标签事件的 ID | + +``` +curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/resource_label_events/120" +``` \ No newline at end of file diff --git a/_book/docs/362.md b/_book/docs/362.md new file mode 100644 index 0000000000000000000000000000000000000000..b492b46c8bcef59ec72a7b2ce3fa1e3b913c63ba --- /dev/null +++ b/_book/docs/362.md @@ -0,0 +1,114 @@ +# Resource milestone events API + +> 原文:[https://docs.gitlab.com/ee/api/resource_milestone_events.html](https://docs.gitlab.com/ee/api/resource_milestone_events.html) + +* [Issues](#issues) + * [List project issue milestone events](#list-project-issue-milestone-events) + * [Get single issue milestone event](#get-single-issue-milestone-event) +* [Merge requests](#merge-requests) + * [List project merge request milestone events](#list-project-merge-request-milestone-events) + * [Get single merge request milestone event](#get-single-merge-request-milestone-event) + +# Resource milestone events API[](#resource-milestone-events-api "Permalink") + +资源里程碑事件跟踪 GitLab [问题](../user/project/issues/)和[合并请求的处理情况](../user/project/merge_requests/) . + +使用它们来跟踪添加或删除了哪个里程碑,谁进行了里程碑以及何时发生. + +## Issues[](#issues "Permalink") + +### List project issue milestone events[](#list-project-issue-milestone-events "Permalink") + +获取单个问题的所有里程碑事件的列表. + +``` +GET /projects/:id/issues/:issue_iid/resource_milestone_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_milestone_events" +``` + +响应示例: + +``` +[ { "id": 142, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T13:38:20.077Z", "resource_type": "Issue", "resource_id": 253, "milestone": { "id": 61, "iid": 9, "project_id": 7, "title": "v1.2", "description": "Ipsum Lorem", "state": "active", "created_at": "2020-01-27T05:07:12.573Z", "updated_at": "2020-01-27T05:07:12.573Z", "due_date": null, "start_date": null, "web_url": "http://gitlab.example.com:3000/group/project/-/milestones/9" }, "action": "add" }, { "id": 143, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-21T14:38:20.077Z", "resource_type": "Issue", "resource_id": 253, "milestone": { "id": 61, "iid": 9, "project_id": 7, "title": "v1.2", "description": "Ipsum Lorem", "state": "active", "created_at": "2020-01-27T05:07:12.573Z", "updated_at": "2020-01-27T05:07:12.573Z", "due_date": null, "start_date": null, "web_url": "http://gitlab.example.com:3000/group/project/-/milestones/9" }, "action": "remove" } ] +``` + +### Get single issue milestone event[](#get-single-issue-milestone-event "Permalink") + +返回特定项目问题的单个里程碑事件 + +``` +GET /projects/:id/issues/:issue_iid/resource_milestone_events/:resource_milestone_event_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `resource_milestone_event_id` | integer | yes | 里程碑事件的 ID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_milestone_events/1" +``` + +## Merge requests[](#merge-requests "Permalink") + +### List project merge request milestone events[](#list-project-merge-request-milestone-events "Permalink") + +获取单个合并请求的所有里程碑事件的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/resource_milestone_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/resource_milestone_events" +``` + +响应示例: + +``` +[ { "id": 142, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T13:38:20.077Z", "resource_type": "MergeRequest", "resource_id": 142, "milestone": { "id": 61, "iid": 9, "project_id": 7, "title": "v1.2", "description": "Ipsum Lorem", "state": "active", "created_at": "2020-01-27T05:07:12.573Z", "updated_at": "2020-01-27T05:07:12.573Z", "due_date": null, "start_date": null, "web_url": "http://gitlab.example.com:3000/group/project/-/milestones/9" }, "action": "add" }, { "id": 143, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-21T14:38:20.077Z", "resource_type": "MergeRequest", "resource_id": 142, "milestone": { "id": 61, "iid": 9, "project_id": 7, "title": "v1.2", "description": "Ipsum Lorem", "state": "active", "created_at": "2020-01-27T05:07:12.573Z", "updated_at": "2020-01-27T05:07:12.573Z", "due_date": null, "start_date": null, "web_url": "http://gitlab.example.com:3000/group/project/-/milestones/9" }, "action": "remove" } ] +``` + +### Get single merge request milestone event[](#get-single-merge-request-milestone-event "Permalink") + +返回特定项目合并请求的单个里程碑事件 + +``` +GET /projects/:id/merge_requests/:merge_request_iid/resource_milestone_events/:resource_milestone_event_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `resource_milestone_event_id` | integer | yes | 里程碑事件的 ID | + +请求示例: + +``` +curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/resource_milestone_events/120" +``` \ No newline at end of file diff --git a/_book/docs/363.md b/_book/docs/363.md new file mode 100644 index 0000000000000000000000000000000000000000..74ed5a7919cf09294face47920ab8ddcf3830a78 --- /dev/null +++ b/_book/docs/363.md @@ -0,0 +1,68 @@ +# Resource weight events API + +> 原文:[https://docs.gitlab.com/ee/api/resource_weight_events.html](https://docs.gitlab.com/ee/api/resource_weight_events.html) + +* [Issues](#issues) + * [List project issue weight events](#list-project-issue-weight-events) + * [Get single issue weight event](#get-single-issue-weight-event) + +# Resource weight events API[](#resource-weight-events-api "Permalink") + +资源权重事件跟踪 GitLab [问题的](../user/project/issues/)发生情况. + +使用它们来跟踪设置了哪些权重,由谁进行权重以及何时发生. + +## Issues[](#issues "Permalink") + +### List project issue weight events[](#list-project-issue-weight-events "Permalink") + +获取单个问题的所有举重事件的列表. + +``` +GET /projects/:id/issues/:issue_iid/resource_weight_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_weight_events" +``` + +响应示例: + +``` +[ { "id": 142, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T13:38:20.077Z", "issue_id": 253, "weight": 3 }, { "id": 143, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-21T14:38:20.077Z", "issue_id": 253, "weight": 2 } ] +``` + +### Get single issue weight event[](#get-single-issue-weight-event "Permalink") + +返回特定项目问题的单个权重事件 + +``` +GET /projects/:id/issues/:issue_iid/resource_weight_events/:resource_weight_event_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `resource_weight_event_id` | integer | yes | 举重事件的 ID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_weight_events/143" +``` + +响应示例: + +``` +{ "id": 143, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-21T14:38:20.077Z", "issue_id": 253, "weight": 2 } +``` \ No newline at end of file diff --git a/_book/docs/364.md b/_book/docs/364.md new file mode 100644 index 0000000000000000000000000000000000000000..1d0a259a294d446da9eb16697a99d99e1e8a80c6 --- /dev/null +++ b/_book/docs/364.md @@ -0,0 +1,378 @@ +# Runners API + +> 原文:[https://docs.gitlab.com/ee/api/runners.html](https://docs.gitlab.com/ee/api/runners.html) + +* [Registration and authentication tokens](#registration-and-authentication-tokens) +* [List owned runners](#list-owned-runners) +* [List all runners](#list-all-runners) +* [Get runner’s details](#get-runners-details) +* [Update runner’s details](#update-runners-details) +* [Remove a runner](#remove-a-runner) +* [List runner’s jobs](#list-runners-jobs) +* [List project’s runners](#list-projects-runners) +* [Enable a runner in project](#enable-a-runner-in-project) +* [Disable a runner from project](#disable-a-runner-from-project) +* [List group’s runners](#list-groups-runners) +* [Register a new Runner](#register-a-new-runner) +* [Delete a registered Runner](#delete-a-registered-runner) +* [Verify authentication for a registered Runner](#verify-authentication-for-a-registered-runner) + +# Runners API[](#runners-api "Permalink") + +在 GitLab 8.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2640) + +## Registration and authentication tokens[](#registration-and-authentication-tokens "Permalink") + +将 Runner 与 GitLab 连接时要考虑两个标记. + +| Token | Description | +| --- | --- | +| 注册令牌 | 用于[注册 Runner 的](https://docs.gitlab.com/runner/register/)令牌. 可以[通过 GitLab 获得](../ci/runners/README.html) . | +| 认证令牌 | 用于通过 GitLab 实例对 Runner 进行身份验证的令牌. 它可以在[注册 Runner](https://docs.gitlab.com/runner/register/)时自动获得,也可以[通过 Runners API](#register-a-new-runner)手动[注册时获得](#register-a-new-runner) . | + +这是在 Runner 注册中如何使用两个令牌的示例: + +1. 您使用注册令牌通过 GitLab API 注册了 Runner,并返回了身份验证令牌. +2. 您使用该身份验证令牌并将其添加到[Runner 的配置文件中](https://docs.gitlab.com/runner/commands/) : + + ``` + [[runners]] + token = "" + ``` + +然后将 GitLab 和 Runner 连接起来. + +## List owned runners[](#list-owned-runners "Permalink") + +获取可供用户使用的特定跑步者的列表. + +``` +GET /runners +GET /runners?scope=active +GET /runners?type=project_type +GET /runners?status=active +GET /runners?tag_list=tag1,tag2 +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided | +| `type` | string | no | 要显示的跑步者的类型,其中之一: `instance_type` , `group_type` , `project_type` | +| `status` | string | no | 要显示的跑步者状态,其中之一: `active` , `paused` , `online` , `offline` | +| `tag_list` | 字符串数组 | no | 跑步者标签列表 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/runners" +``` + +响应示例: + +``` +[ { "active": true, "description": "test-1-20150125", "id": 6, "is_shared": false, "ip_address": "127.0.0.1", "name": null, "online": true, "status": "online" }, { "active": true, "description": "test-2-20150125", "id": 8, "ip_address": "127.0.0.1", "is_shared": false, "name": null, "online": false, "status": "offline" } ] +``` + +## List all runners[](#list-all-runners "Permalink") + +获取 GitLab 实例中所有跑步者的列表(特定的和共享的). 访问仅限于具有`admin`权限的用户. + +``` +GET /runners/all +GET /runners/all?scope=online +GET /runners/all?type=project_type +GET /runners/all?status=active +GET /runners/all?tag_list=tag1,tag2 +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `scope` | string | no | 不推荐使用:改为使用`type`或`status` . 参与者显示的范围,其中之一: `specific` , `shared` , `active` ,已`paused` , `online` , `offline` ; 显示所有跑步者(如果未提供) | +| `type` | string | no | 要显示的跑步者的类型,其中之一: `instance_type` , `group_type` , `project_type` | +| `status` | string | no | 要显示的跑步者状态,其中之一: `active` , `paused` , `online` , `offline` | +| `tag_list` | 字符串数组 | no | 跑步者标签列表 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/runners/all" +``` + +响应示例: + +``` +[ { "active": true, "description": "shared-runner-1", "id": 1, "ip_address": "127.0.0.1", "is_shared": true, "name": null, "online": true, "status": "online" }, { "active": true, "description": "shared-runner-2", "id": 3, "ip_address": "127.0.0.1", "is_shared": true, "name": null, "online": false "status": "offline" }, { "active": true, "description": "test-1-20150125", "id": 6, "ip_address": "127.0.0.1", "is_shared": false, "name": null, "online": true "status": "paused" }, { "active": true, "description": "test-2-20150125", "id": 8, "ip_address": "127.0.0.1", "is_shared": false, "name": null, "online": false, "status": "offline" } ] +``` + +## Get runner’s details[](#get-runners-details "Permalink") + +获取跑步者的详细信息. + +``` +GET /runners/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 跑步者 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/runners/6" +``` + +**注意:**响应中的`token`属性[在 GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/issues/214320)中已弃用. 并在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/issues/214322)删除. + +响应示例: + +``` +{ "active": true, "architecture": null, "description": "test-1-20150125", "id": 6, "ip_address": "127.0.0.1", "is_shared": false, "contacted_at": "2016-01-25T16:39:48.066Z", "name": null, "online": true, "status": "online", "platform": null, "projects": [ { "id": 1, "name": "GitLab Community Edition", "name_with_namespace": "GitLab.org / GitLab Community Edition", "path": "gitlab-foss", "path_with_namespace": "gitlab-org/gitlab-foss" } ], "revision": null, "tag_list": [ "ruby", "mysql" ], "version": null, "access_level": "ref_protected", "maximum_timeout": 3600 } +``` + +## Update runner’s details[](#update-runners-details "Permalink") + +更新跑步者的详细信息. + +``` +PUT /runners/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 跑步者 ID | +| `description` | string | no | 跑步者 | +| `active` | boolean | no | 跑步者的状态; 可以设置为`true`或`false` | +| `tag_list` | array | no | 跑步者的标签列表; 放置标签数组,这些标签应最终分配给跑步者 | +| `run_untagged` | boolean | no | 指示跑步者可以执行未加标签的作业的标志 | +| `locked` | boolean | no | 指示跑步者被锁定的标志 | +| `access_level` | string | no | 跑步者的 access_level; `not_protected`或`ref_protected` | +| `maximum_timeout` | integer | no | 此 Runner 处理作业的最大超时时间 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/runners/6" --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2" +``` + +**注意:**响应中的`token`属性[在 GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/issues/214320)中已弃用. 并在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/issues/214322)删除. + +响应示例: + +``` +{ "active": true, "architecture": null, "description": "test-1-20150125-test", "id": 6, "ip_address": "127.0.0.1", "is_shared": false, "contacted_at": "2016-01-25T16:39:48.066Z", "name": null, "online": true, "status": "online", "platform": null, "projects": [ { "id": 1, "name": "GitLab Community Edition", "name_with_namespace": "GitLab.org / GitLab Community Edition", "path": "gitlab-foss", "path_with_namespace": "gitlab-org/gitlab-foss" } ], "revision": null, "tag_list": [ "ruby", "mysql", "tag1", "tag2" ], "version": null, "access_level": "ref_protected", "maximum_timeout": null } +``` + +## Remove a runner[](#remove-a-runner "Permalink") + +卸下流道. + +``` +DELETE /runners/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | The ID of a runner | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/runners/6" +``` + +## List runner’s jobs[](#list-runners-jobs "Permalink") + +在 GitLab 10.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15432) . + +列出正在处理或由指定运行程序处理的作业. + +``` +GET /runners/:id/jobs +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 跑步者 ID | +| `status` | string | no | 工作状态; 其中之一: `running` , `success` , `failed` , `canceled` | +| `order_by` | string | no | 按`id`订购工作. | +| `sort` | string | no | 按`asc`或`desc`顺序对作业进行排序(默认值: `desc` ) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/runners/1/jobs?status=running" +``` + +响应示例: + +``` +[ { "id": 2, "ip_address": "127.0.0.1", "status": "running", "stage": "test", "name": "test", "ref": "master", "tag": false, "coverage": null, "created_at": "2017-11-16T08:50:29.000Z", "started_at": "2017-11-16T08:51:29.000Z", "finished_at": "2017-11-16T08:53:29.000Z", "duration": 120, "user": { "id": 1, "name": "John Doe2", "username": "user2", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://localhost/user2", "created_at": "2017-11-16T18:38:46.000Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": null }, "commit": { "id": "97de212e80737a608d939f648d959671fb0a0142", "short_id": "97de212e", "title": "Update configuration\r", "created_at": "2017-11-16T08:50:28.000Z", "parent_ids": [ "1b12f15a11fc6e62177bef08f47bc7b5ce50b141", "498214de67004b1da3d820901307bed2a68a8ef6" ], "message": "See merge request !123", "author_name": "John Doe2", "author_email": "user2@example.org", "authored_date": "2017-11-16T08:50:27.000Z", "committer_name": "John Doe2", "committer_email": "user2@example.org", "committed_date": "2017-11-16T08:50:27.000Z" }, "pipeline": { "id": 2, "sha": "97de212e80737a608d939f648d959671fb0a0142", "ref": "master", "status": "running" }, "project": { "id": 1, "description": null, "name": "project1", "name_with_namespace": "John Doe2 / project1", "path": "project1", "path_with_namespace": "namespace1/project1", "created_at": "2017-11-16T18:38:46.620Z" } } ] +``` + +## List project’s runners[](#list-projects-runners "Permalink") + +List all runners (specific and shared) available in the project. 列出项目中所有可用的跑步者(特定的和共享的). Shared runners are listed if at least one shared runner is defined. 如果定义了至少一个共享运行程序,则列出共享运行程序. + +``` +GET /projects/:id/runners +GET /projects/:id/runners?scope=active +GET /projects/:id/runners?type=project_type +GET /projects/:id/runners?status=active +GET /projects/:id/runners?tag_list=tag1,tag2 +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `scope` | string | no | 不推荐使用:改为使用`type`或`status` . 要显示的特定跑步者的范围,其中之一: `active` , `paused` , `online` , `offline` ; 显示所有跑步者(如果未提供) | +| `type` | string | no | 要显示的跑步者的类型,其中之一: `instance_type` , `group_type` , `project_type` | +| `status` | string | no | 要显示的跑步者状态,其中之一: `active` , `paused` , `online` , `offline` | +| `tag_list` | 字符串数组 | no | 跑步者标签列表 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/9/runners" +``` + +响应示例: + +``` +[ { "active": true, "description": "test-2-20150125", "id": 8, "ip_address": "127.0.0.1", "is_shared": false, "name": null, "online": false, "status": "offline" }, { "active": true, "description": "development_runner", "id": 5, "ip_address": "127.0.0.1", "is_shared": true, "name": null, "online": true "status": "paused" } ] +``` + +## Enable a runner in project[](#enable-a-runner-in-project "Permalink") + +在项目中启用可用的特定运行器. + +``` +POST /projects/:id/runners +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `runner_id` | integer | yes | 跑步者 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/9/runners" --form "runner_id=9" +``` + +响应示例: + +``` +{ "active": true, "description": "test-2016-02-01", "id": 9, "ip_address": "127.0.0.1", "is_shared": false, "name": null, "online": true, "status": "online" } +``` + +## Disable a runner from project[](#disable-a-runner-from-project "Permalink") + +禁用项目中的特定运行器. 仅当该项目不是与指定运行器关联的唯一项目时,它才有效. 如果是这样,则返回错误. 改用" [删除亚军"](#remove-a-runner)电话. + +``` +DELETE /projects/:id/runners/:runner_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `runner_id` | integer | yes | 跑步者 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/9/runners/9" +``` + +## List group’s runners[](#list-groups-runners "Permalink") + +列出组中的所有跑步者(特定的和共享的)以及其祖先组. 如果定义了至少一个共享运行程序,则列出共享运行程序. + +``` +GET /groups/:id/runners +GET /groups/:id/runners?type=group_type +GET /groups/:id/runners?status=active +GET /groups/:id/runners?tag_list=tag1,tag2 +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 认证用户拥有的组的 ID | +| `type` | string | no | 要显示的跑步者的类型,其中之一: `instance_type` , `group_type` , `project_type` | +| `status` | string | no | 要显示的跑步者状态,其中之一: `active` , `paused` , `online` , `offline` | +| `tag_list` | 字符串数组 | no | 跑步者标签列表 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/9/runners" +``` + +响应示例: + +``` +[ { "id": 3, "description": "Shared", "ip_address": "127.0.0.1", "active": true, "is_shared": true, "name": "gitlab-runner", "online": null, "status": "not_connected" }, { "id": 6, "description": "Test", "ip_address": "127.0.0.1", "active": true, "is_shared": true, "name": "gitlab-runner", "online": false, "status": "offline" }, { "id": 8, "description": "Test 2", "ip_address": "127.0.0.1", "active": true, "is_shared": false, "name": "gitlab-runner", "online": null, "status": "not_connected" } ] +``` + +## Register a new Runner[](#register-a-new-runner "Permalink") + +为该实例注册一个新的运行器. + +``` +POST /runners +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | yes | [Registration token](#registration-and-authentication-tokens). | +| `description` | string | no | 跑步者的描述 | +| `info` | hash | no | 跑步者的元数据 | +| `active` | boolean | no | 跑步者是否活跃 | +| `locked` | boolean | no | Runner 是否应该为当前项目锁定 | +| `run_untagged` | boolean | no | 跑步者是否应处理未加标签的工作 | +| `tag_list` | 字符串数组 | no | 跑步者标签列表 | +| `access_level` | string | no | 跑步者的 access_level; `not_protected`或`ref_protected` | +| `maximum_timeout` | integer | no | 此 Runner 处理作业的最大超时时间 | + +``` +curl --request POST "https://gitlab.example.com/api/v4/runners" --form "token=" --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2" +``` + +Response: + +| Status | Description | +| --- | --- | +| 201 | 跑步者已创建 | + +响应示例: + +``` +{ "id": "12345", "token": "6337ff461c94fd3fa32ba3b1ff4125" } +``` + +## Delete a registered Runner[](#delete-a-registered-runner "Permalink") + +删除注册的跑步者. + +``` +DELETE /runners +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | yes | Runner’s [authentication token](#registration-and-authentication-tokens). | + +``` +curl --request DELETE "https://gitlab.example.com/api/v4/runners" --form "token=" +``` + +Response: + +| Status | Description | +| --- | --- | +| 204 | 跑步者已被删除 | + +## Verify authentication for a registered Runner[](#verify-authentication-for-a-registered-runner "Permalink") + +验证注册的运行程序的身份验证凭据. + +``` +POST /runners/verify +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | yes | Runner’s [authentication token](#registration-and-authentication-tokens). | + +``` +curl --request POST "https://gitlab.example.com/api/v4/runners/verify" --form "token=" +``` + +Response: + +| Status | Description | +| --- | --- | +| 200 | 凭证有效 | +| 403 | 凭证无效 | \ No newline at end of file diff --git a/_book/docs/365.md b/_book/docs/365.md new file mode 100644 index 0000000000000000000000000000000000000000..34125a73853dd1bc91f52454f1fa851ef75b6166 --- /dev/null +++ b/_book/docs/365.md @@ -0,0 +1,189 @@ +# SCIM API + +> 原文:[https://docs.gitlab.com/ee/api/scim.html](https://docs.gitlab.com/ee/api/scim.html) + +* [Get a list of SAML users](#get-a-list-of-saml-users) +* [Get a single SAML user](#get-a-single-saml-user) +* [Create a SAML user](#create-a-saml-user) +* [Update a single SAML user](#update-a-single-saml-user) +* [Remove a single SAML user](#remove-a-single-saml-user) +* [Available filters](#available-filters) +* [Available operations](#available-operations) + +# SCIM API[](#scim-api-silver-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in [GitLab Silver](https://about.gitlab.com/pricing/) 11.10. + +SCIM API 实现[RFC7644 协议](https://tools.ietf.org/html/rfc7644) . + +**警告:**此 API 供内部系统用于与 SCIM 提供程序连接. 虽然可以直接使用,但如有更改,恕不另行通知.**注意:**必须为组启用[组 SSO](../user/group/saml_sso/index.html) . 有关更多信息,请参见[SCIM 设置文档](../user/group/saml_sso/scim_setup.html#requirements) . + +## Get a list of SAML users[](#get-a-list-of-saml-users "Permalink") + +**注意:**此端点用作 SCIM 同步机制的一部分,并且它仅基于唯一 ID(应与用户的`extern_uid`相匹配)返回一个用户. + +``` +GET /api/scim/v2/groups/:group_path/Users +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `filter` | string | no | A [filter](#available-filters) expression. | +| `group_path` | string | yes | 组的完整路径. | +| `startIndex` | integer | no | 从 1 开始的索引,指示从何处开始返回结果. 小于 1 的值将被解释为 1. | +| `count` | integer | no | 所需的最大查询结果数. | + +**注意:**分页遵循[SCIM 规范,](https://tools.ietf.org/html/rfc7644#section-3.4.2.4)而不是其他地方使用的 GitLab 分页. 如果记录在请求之间更改,则页面可能丢失已移至其他页面的记录,或者重复上一个请求的记录. + +请求示例: + +``` +curl 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users?filter=id%20eq%20"0b1d561c-21ff-4092-beab-8154b17f82f2"' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +响应示例: + +``` +{ "schemas": [ "urn:ietf:params:scim:api:messages:2.0:ListResponse" ], "totalResults": 1, "itemsPerPage": 20, "startIndex": 1, "Resources": [ { "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User" ], "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", "active": true, "name.formatted": "Test User", "userName": "username", "meta": { "resourceType":"User" }, "emails": [ { "type": "work", "value": "name@example.com", "primary": true } ] } ] } +``` + +## Get a single SAML user[](#get-a-single-saml-user "Permalink") + +``` +GET /api/scim/v2/groups/:group_path/Users/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | string | yes | 用户的外部 UID. | +| `group_path` | string | yes | 组的完整路径. | + +请求示例: + +``` +curl "https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +响应示例: + +``` +{ "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User" ], "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", "active": true, "name.formatted": "Test User", "userName": "username", "meta": { "resourceType":"User" }, "emails": [ { "type": "work", "value": "name@example.com", "primary": true } ] } +``` + +## Create a SAML user[](#create-a-saml-user "Permalink") + +``` +POST /api/scim/v2/groups/:group_path/Users/ +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `externalId` | string | yes | 用户的外部 UID. | +| `userName` | string | yes | 用户的用户名. | +| `emails` | JSON 字符串 | yes | 工作电子邮件. | +| `name` | JSON 字符串 | yes | 用户名. | +| `meta` | string | no | 资源类型( `User` ). | + +请求示例: + +``` +curl --verbose --request POST "https://example.gitlab.com/api/scim/v2/groups/test_group/Users" --data '{"externalId":"test_uid","active":null,"userName":"username","emails":[{"primary":true,"type":"work","value":"name@example.com"}],"name":{"formatted":"Test User","familyName":"User","givenName":"Test"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"meta":{"resourceType":"User"}}' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +响应示例: + +``` +{ "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User" ], "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", "active": true, "name.formatted": "Test User", "userName": "username", "meta": { "resourceType":"User" }, "emails": [ { "type": "work", "value": "name@example.com", "primary": true } ] } +``` + +如果成功,则返回`201`状态代码. + +## Update a single SAML user[](#update-a-single-saml-user "Permalink") + +可以更新的字段是: + +| SCIM / IdP 字段 | GitLab 领域 | +| --- | --- | +| `id/externalId` | `extern_uid` | +| `name.formatted` | `name` | +| `emails\[type eq "work"\].value` | `email` | +| `active` | 如果`active` = `false`删除身份 | +| `userName` | `username` | + +``` +PATCH /api/scim/v2/groups/:group_path/Users/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | string | yes | 用户的外部 UID. | +| `group_path` | string | yes | 组的完整路径. | +| `Operations` | JSON 字符串 | yes | An [operations](#available-operations) expression. | + +请求示例: + +``` +curl --verbose --request PATCH "https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --data '{ "Operations": [{"op":"Add","path":"name.formatted","value":"New Name"}] }' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +如果成功,则返回带有`204`状态代码的空响应. + +## Remove a single SAML user[](#remove-a-single-saml-user "Permalink") + +删除用户的 SSO 身份和组成员身份. + +``` +DELETE /api/scim/v2/groups/:group_path/Users/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | string | yes | 用户的外部 UID. | +| `group_path` | string | yes | 组的完整路径. | + +请求示例: + +``` +curl --verbose --request DELETE "https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +如果成功,则返回带有`204`状态代码的空响应. + +## Available filters[](#available-filters "Permalink") + +它们与[RFC7644 过滤部分中](https://tools.ietf.org/html/rfc7644#section-3.4.2.2)指定的表达式匹配. + +| Filter | Description | +| --- | --- | +| `eq` | 该属性与指定值完全匹配. | + +Example: + +``` +id eq a-b-c-d +``` + +## Available operations[](#available-operations "Permalink") + +They perform an operation as specified in [the RFC7644 update section](https://tools.ietf.org/html/rfc7644#section-3.5.2). + +| Operator | Description | +| --- | --- | +| `Replace` | 该属性的值已更新. | +| `Add` | 该属性具有新值. | + +Example: + +``` +{ "op": "Add", "path": "name.formatted", "value": "New Name" } +``` \ No newline at end of file diff --git a/_book/docs/366.md b/_book/docs/366.md new file mode 100644 index 0000000000000000000000000000000000000000..f7dac4b36657dd5f503f541e83c344f783de6ae9 --- /dev/null +++ b/_book/docs/366.md @@ -0,0 +1,476 @@ +# Search API + +> 原文:[https://docs.gitlab.com/ee/api/search.html](https://docs.gitlab.com/ee/api/search.html) + +* [Global Search API](#global-search-api) + * [Scope: projects](#scope-projects) + * [Scope: issues](#scope-issues) + * [Scope: merge_requests](#scope-merge_requests) + * [Scope: milestones](#scope-milestones) + * [Scope: snippet_titles](#scope-snippet_titles) + * [Scope: wiki_blobs](#scope-wiki_blobs-starter) + * [Scope: commits](#scope-commits-starter) + * [Scope: blobs](#scope-blobs-starter) + * [Scope: users](#scope-users) +* [Group Search API](#group-search-api) + * [Scope: projects](#scope-projects-1) + * [Scope: issues](#scope-issues-1) + * [Scope: merge_requests](#scope-merge_requests-1) + * [Scope: milestones](#scope-milestones-1) + * [Scope: wiki_blobs](#scope-wiki_blobs-starter-1) + * [Scope: commits](#scope-commits-starter-1) + * [Scope: blobs](#scope-blobs-starter-1) + * [Scope: users](#scope-users-1) +* [Project Search API](#project-search-api) + * [Scope: issues](#scope-issues-2) + * [Scope: merge_requests](#scope-merge_requests-2) + * [Scope: milestones](#scope-milestones-2) + * [Scope: notes](#scope-notes) + * [Scope: wiki_blobs](#scope-wiki_blobs) + * [Scope: commits](#scope-commits) + * [Scope: blobs](#scope-blobs) + * [Scope: users](#scope-users-2) + +# Search API[](#search-api "Permalink") + +在 GitLab 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41763) . + +搜索的每个 API 调用都必须经过验证. + +## Global Search API[](#global-search-api "Permalink") + +在整个 GitLab 实例中进行全局搜索. + +``` +GET /search +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `scope` | string | yes | 搜索范围 | +| `search` | string | yes | 搜索查询 | + +在指定范围内搜索表达式. 当前支持以下范围:项目,问题,merge_requests,里程碑,snippet_titles,用户. + +如果启用了 Elasticsearch,则其他可用范围是 blob,wiki_blobs 和 commits. 查找有关[该功能的](../integration/elasticsearch.html)更多信息. + +响应取决于请求的范围. + +### Scope: projects[](#scope-projects "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=projects&search=flight" +``` + +响应示例: + +``` +[ { "id": 6, "description": "Nobis sed ipsam vero quod cupiditate veritatis hic.", "name": "Flight", "name_with_namespace": "Twitter / Flight", "path": "flight", "path_with_namespace": "twitter/flight", "created_at": "2017-09-05T07:58:01.621Z", "default_branch": "master", "tag_list":[], "ssh_url_to_repo": "ssh://jarka@localhost:2222/twitter/flight.git", "http_url_to_repo": "http://localhost:3000/twitter/flight.git", "web_url": "http://localhost:3000/twitter/flight", "avatar_url": null, "star_count": 0, "forks_count": 0, "last_activity_at": "2018-01-31T09:56:30.902Z" } ] +``` + +### Scope: issues[](#scope-issues "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=issues&search=file" +``` + +响应示例: + +``` +[ { "id": 83, "iid": 1, "project_id": 12, "title": "Add file", "description": "Add first file", "state": "opened", "created_at": "2018-01-24T06:02:15.514Z", "updated_at": "2018-02-06T12:36:23.263Z", "closed_at": null, "labels":[], "milestone": null, "assignees": [{ "id": 20, "name": "Ceola Deckow", "username": "sammy.collier", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c23d85a4f50e0ea76ab739156c639231?s=80&d=identicon", "web_url": "http://localhost:3000/sammy.collier" }], "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "assignee": { "id": 20, "name": "Ceola Deckow", "username": "sammy.collier", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c23d85a4f50e0ea76ab739156c639231?s=80&d=identicon", "web_url": "http://localhost:3000/sammy.collier" }, "user_notes_count": 0, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "discussion_locked": null, "web_url": "http://localhost:3000/h5bp/7bp/subgroup-prj/issues/1", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +### Scope: merge_requests[](#scope-merge_requests "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=merge_requests&search=file" +``` + +响应示例: + +``` +[ { "id": 56, "iid": 8, "project_id": 6, "title": "Add first file", "description": "This is a test MR to add file", "state": "opened", "created_at": "2018-01-22T14:21:50.830Z", "updated_at": "2018-02-06T12:40:33.295Z", "target_branch": "master", "source_branch": "jaja-test", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "assignee": { "id": 5, "name": "Jacquelyn Kutch", "username": "abigail", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/3138c66095ee4bd11a508c2f7f7772da?s=80&d=identicon", "web_url": "http://localhost:3000/abigail" }, "source_project_id": 6, "target_project_id": 6, "labels": [ "ruby", "tests" ], "work_in_progress": false, "milestone": { "id": 13, "iid": 3, "project_id": 6, "title": "v2.0", "description": "Qui aut qui eos dolor beatae itaque tempore molestiae.", "state": "active", "created_at": "2017-09-05T07:58:29.099Z", "updated_at": "2017-09-05T07:58:29.099Z", "due_date": null, "start_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "can_be_merged", "sha": "78765a2d5e0a43585945c58e61ba2f822e4d090b", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 0, "discussion_locked": null, "should_remove_source_branch": null, "force_remove_source_branch": true, "web_url": "http://localhost:3000/twitter/flight/merge_requests/8", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +### Scope: milestones[](#scope-milestones "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=milestones&search=release" +``` + +响应示例: + +``` +[ { "id": 44, "iid": 1, "project_id": 12, "title": "next release", "description": "Next release milestone", "state": "active", "created_at": "2018-02-06T12:43:39.271Z", "updated_at": "2018-02-06T12:44:01.298Z", "due_date": "2018-04-18", "start_date": "2018-02-04" } ] +``` + +### Scope: snippet_titles[](#scope-snippet_titles "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=snippet_titles&search=sample" +``` + +响应示例: + +``` +[ { "id": 50, "title": "Sample file", "file_name": "file.rb", "description": "Simple ruby file", "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "updated_at": "2018-02-06T12:49:29.104Z", "created_at": "2017-11-28T08:20:18.071Z", "project_id": 9, "web_url": "http://localhost:3000/root/jira-test/snippets/50" } ] +``` + +### Scope: wiki_blobs[](#scope-wiki_blobs-starter "Permalink") + +仅当启用[Elasticsearch 时,](../integration/elasticsearch.html)此范围才可用. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=wiki_blobs&search=bye" +``` + +Example response: + +``` + [ { "basename": "home", "data": "hello\n\nand bye\n\nend", "path": "home.md", "filename": "home.md", "id": null, "ref": "master", "startline": 5, "project_id": 6 } ] +``` + +**注意:**不建议使用`filename`而推荐使用`path` . 两者都返回存储库中文件的完整路径,但将来`filename`名将仅是文件名,而不是完整路径. 有关详细信息,请参见[问题 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521) . + +### Scope: commits[](#scope-commits-starter "Permalink") + +仅当启用[Elasticsearch 时,](../integration/elasticsearch.html)此范围才可用. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=commits&search=bye" +``` + +响应示例: + +``` + [ { "id": "4109c2d872d5fdb1ed057400d103766aaea97f98", "short_id": "4109c2d8", "title": "goodbye $.browser", "created_at": "2013-02-18T22:02:54.000Z", "parent_ids": [ "59d05353ab575bcc2aa958fe1782e93297de64c9" ], "message": "goodbye $.browser\n", "author_name": "angus croll", "author_email": "anguscroll@gmail.com", "authored_date": "2013-02-18T22:02:54.000Z", "committer_name": "angus croll", "committer_email": "anguscroll@gmail.com", "committed_date": "2013-02-18T22:02:54.000Z", "project_id": 6 } ] +``` + +### Scope: blobs[](#scope-blobs-starter "Permalink") + +仅当启用[Elasticsearch 时,](../integration/elasticsearch.html)此范围才可用. + +过滤器可用于以下范围: + +* filename +* path +* extension + +要使用过滤器,只需将其包含在查询中,如下所示: `a query filename:some_name*` . + +您可以使用通配符( `*` )使用全局匹配. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=blobs&search=installation" +``` + +响应示例: + +``` + [ { "basename": "README", "data": "```\n\n## Installation\n\nQuick start using the [pre-built", "path": "README.md", "filename": "README.md", "id": null, "ref": "master", "startline": 46, "project_id": 6 } ] +``` + +**注意:**不建议使用`filename`而推荐使用`path` . 两者都返回存储库中文件的完整路径,但将来`filename`名将仅是文件名,而不是完整路径. 有关详细信息,请参见[问题 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521) . + +### Scope: users[](#scope-users "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=users&search=doe" +``` + +响应示例: + +``` +[ { "id": 1, "name": "John Doe1", "username": "user1", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://localhost/user1" } ] +``` + +## Group Search API[](#group-search-api "Permalink") + +在指定的组中搜索. + +如果用户不是组的成员,并且该组是私有的,则对该组的`GET`请求将导致`404`状态代码. + +``` +GET /groups/:id/search +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `scope` | string | yes | 搜索范围 | +| `search` | string | yes | 搜索查询 | + +在指定范围内搜索表达式. 当前支持以下范围:项目,问题,merge_requests,里程碑,用户. + +如果启用了 Elasticsearch,则其他可用范围是 blob,wiki_blobs 和 commits. 查找有关[该功能的](../integration/elasticsearch.html)更多信息. + +响应取决于请求的范围. + +### Scope: projects[](#scope-projects-1 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/3/search?scope=projects&search=flight" +``` + +响应示例: + +``` +[ { "id": 6, "description": "Nobis sed ipsam vero quod cupiditate veritatis hic.", "name": "Flight", "name_with_namespace": "Twitter / Flight", "path": "flight", "path_with_namespace": "twitter/flight", "created_at": "2017-09-05T07:58:01.621Z", "default_branch": "master", "tag_list":[], "ssh_url_to_repo": "ssh://jarka@localhost:2222/twitter/flight.git", "http_url_to_repo": "http://localhost:3000/twitter/flight.git", "web_url": "http://localhost:3000/twitter/flight", "avatar_url": null, "star_count": 0, "forks_count": 0, "last_activity_at": "2018-01-31T09:56:30.902Z" } ] +``` + +### Scope: issues[](#scope-issues-1 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/3/search?scope=issues&search=file" +``` + +响应示例: + +``` +[ { "id": 83, "iid": 1, "project_id": 12, "title": "Add file", "description": "Add first file", "state": "opened", "created_at": "2018-01-24T06:02:15.514Z", "updated_at": "2018-02-06T12:36:23.263Z", "closed_at": null, "labels":[], "milestone": null, "assignees": [{ "id": 20, "name": "Ceola Deckow", "username": "sammy.collier", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c23d85a4f50e0ea76ab739156c639231?s=80&d=identicon", "web_url": "http://localhost:3000/sammy.collier" }], "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "assignee": { "id": 20, "name": "Ceola Deckow", "username": "sammy.collier", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c23d85a4f50e0ea76ab739156c639231?s=80&d=identicon", "web_url": "http://localhost:3000/sammy.collier" }, "user_notes_count": 0, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "discussion_locked": null, "web_url": "http://localhost:3000/h5bp/7bp/subgroup-prj/issues/1", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +### Scope: merge_requests[](#scope-merge_requests-1 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/3/search?scope=merge_requests&search=file" +``` + +响应示例: + +``` +[ { "id": 56, "iid": 8, "project_id": 6, "title": "Add first file", "description": "This is a test MR to add file", "state": "opened", "created_at": "2018-01-22T14:21:50.830Z", "updated_at": "2018-02-06T12:40:33.295Z", "target_branch": "master", "source_branch": "jaja-test", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "assignee": { "id": 5, "name": "Jacquelyn Kutch", "username": "abigail", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/3138c66095ee4bd11a508c2f7f7772da?s=80&d=identicon", "web_url": "http://localhost:3000/abigail" }, "source_project_id": 6, "target_project_id": 6, "labels": [ "ruby", "tests" ], "work_in_progress": false, "milestone": { "id": 13, "iid": 3, "project_id": 6, "title": "v2.0", "description": "Qui aut qui eos dolor beatae itaque tempore molestiae.", "state": "active", "created_at": "2017-09-05T07:58:29.099Z", "updated_at": "2017-09-05T07:58:29.099Z", "due_date": null, "start_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "can_be_merged", "sha": "78765a2d5e0a43585945c58e61ba2f822e4d090b", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 0, "discussion_locked": null, "should_remove_source_branch": null, "force_remove_source_branch": true, "web_url": "http://localhost:3000/twitter/flight/merge_requests/8", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +### Scope: milestones[](#scope-milestones-1 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/3/search?scope=milestones&search=release" +``` + +响应示例: + +``` +[ { "id": 44, "iid": 1, "project_id": 12, "title": "next release", "description": "Next release milestone", "state": "active", "created_at": "2018-02-06T12:43:39.271Z", "updated_at": "2018-02-06T12:44:01.298Z", "due_date": "2018-04-18", "start_date": "2018-02-04" } ] +``` + +### Scope: wiki_blobs[](#scope-wiki_blobs-starter-1 "Permalink") + +仅当启用[Elasticsearch 时,](../integration/elasticsearch.html)此范围才可用. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/6/search?scope=wiki_blobs&search=bye" +``` + +响应示例: + +``` + [ { "basename": "home", "data": "hello\n\nand bye\n\nend", "path": "home.md", "filename": "home.md", "id": null, "ref": "master", "startline": 5, "project_id": 6 } ] +``` + +**注意:**不建议使用`filename`而推荐使用`path` . 两者都返回存储库中文件的完整路径,但将来`filename`名将仅是文件名,而不是完整路径. 有关详细信息,请参见[问题 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521) . + +### Scope: commits[](#scope-commits-starter-1 "Permalink") + +仅当启用[Elasticsearch 时,](../integration/elasticsearch.html)此范围才可用. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/6/search?scope=commits&search=bye" +``` + +响应示例: + +``` + [ { "id": "4109c2d872d5fdb1ed057400d103766aaea97f98", "short_id": "4109c2d8", "title": "goodbye $.browser", "created_at": "2013-02-18T22:02:54.000Z", "parent_ids": [ "59d05353ab575bcc2aa958fe1782e93297de64c9" ], "message": "goodbye $.browser\n", "author_name": "angus croll", "author_email": "anguscroll@gmail.com", "authored_date": "2013-02-18T22:02:54.000Z", "committer_name": "angus croll", "committer_email": "anguscroll@gmail.com", "committed_date": "2013-02-18T22:02:54.000Z", "project_id": 6 } ] +``` + +### Scope: blobs[](#scope-blobs-starter-1 "Permalink") + +仅当启用[Elasticsearch 时,](../integration/elasticsearch.html)此范围才可用. + +过滤器可用于以下范围: + +* filename +* path +* extension + +要使用过滤器,只需将其包含在查询中,如下所示: `a query filename:some_name*` . + +您可以使用通配符( `*` )使用全局匹配. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/6/search?scope=blobs&search=installation" +``` + +响应示例: + +``` + [ { "basename": "README", "data": "```\n\n## Installation\n\nQuick start using the [pre-built", "path": "README.md", "filename": "README.md", "id": null, "ref": "master", "startline": 46, "project_id": 6 } ] +``` + +**注意:**不建议使用`filename`而推荐使用`path` . 两者都返回存储库中文件的完整路径,但将来`filename`名将仅是文件名,而不是完整路径. 有关详细信息,请参见[问题 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521) . + +### Scope: users[](#scope-users-1 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/3/search?scope=users&search=doe" +``` + +响应示例: + +``` +[ { "id": 1, "name": "John Doe1", "username": "user1", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://localhost/user1" } ] +``` + +## Project Search API[](#project-search-api "Permalink") + +在指定项目中搜索. + +如果用户不是项目成员,并且该项目是私有项目,则对该项目的`GET`请求将导致`404`状态代码. + +``` +GET /projects/:id/search +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `scope` | string | yes | 搜索范围 | +| `search` | string | yes | 搜索查询 | +| `ref` | string | no | 要搜索的存储库分支或标记的名称. 默认情况下使用项目的默认分支. 这仅适用于范围:commit,blob 和 wiki_blobs. | + +在指定范围内搜索表达式. 当前支持以下范围:问题,merge_requests,里程碑,注释,wiki_blob,提交,blob,用户. + +响应取决于请求的范围. + +### Scope: issues[](#scope-issues-2 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/12/search?scope=issues&search=file" +``` + +响应示例: + +``` +[ { "id": 83, "iid": 1, "project_id": 12, "title": "Add file", "description": "Add first file", "state": "opened", "created_at": "2018-01-24T06:02:15.514Z", "updated_at": "2018-02-06T12:36:23.263Z", "closed_at": null, "labels":[], "milestone": null, "assignees": [{ "id": 20, "name": "Ceola Deckow", "username": "sammy.collier", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c23d85a4f50e0ea76ab739156c639231?s=80&d=identicon", "web_url": "http://localhost:3000/sammy.collier" }], "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "assignee": { "id": 20, "name": "Ceola Deckow", "username": "sammy.collier", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c23d85a4f50e0ea76ab739156c639231?s=80&d=identicon", "web_url": "http://localhost:3000/sammy.collier" }, "user_notes_count": 0, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "discussion_locked": null, "web_url": "http://localhost:3000/h5bp/7bp/subgroup-prj/issues/1", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +### Scope: merge_requests[](#scope-merge_requests-2 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/6/search?scope=merge_requests&search=file" +``` + +响应示例: + +``` +[ { "id": 56, "iid": 8, "project_id": 6, "title": "Add first file", "description": "This is a test MR to add file", "state": "opened", "created_at": "2018-01-22T14:21:50.830Z", "updated_at": "2018-02-06T12:40:33.295Z", "target_branch": "master", "source_branch": "jaja-test", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "assignee": { "id": 5, "name": "Jacquelyn Kutch", "username": "abigail", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/3138c66095ee4bd11a508c2f7f7772da?s=80&d=identicon", "web_url": "http://localhost:3000/abigail" }, "source_project_id": 6, "target_project_id": 6, "labels": [ "ruby", "tests" ], "work_in_progress": false, "milestone": { "id": 13, "iid": 3, "project_id": 6, "title": "v2.0", "description": "Qui aut qui eos dolor beatae itaque tempore molestiae.", "state": "active", "created_at": "2017-09-05T07:58:29.099Z", "updated_at": "2017-09-05T07:58:29.099Z", "due_date": null, "start_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "can_be_merged", "sha": "78765a2d5e0a43585945c58e61ba2f822e4d090b", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 0, "discussion_locked": null, "should_remove_source_branch": null, "force_remove_source_branch": true, "web_url": "http://localhost:3000/twitter/flight/merge_requests/8", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +### Scope: milestones[](#scope-milestones-2 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/12/search?scope=milestones&search=release" +``` + +响应示例: + +``` +[ { "id": 44, "iid": 1, "project_id": 12, "title": "next release", "description": "Next release milestone", "state": "active", "created_at": "2018-02-06T12:43:39.271Z", "updated_at": "2018-02-06T12:44:01.298Z", "due_date": "2018-04-18", "start_date": "2018-02-04" } ] +``` + +### Scope: notes[](#scope-notes "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/6/search?scope=notes&search=maxime" +``` + +响应示例: + +``` +[ { "id": 191, "body": "Harum maxime consequuntur et et deleniti assumenda facilis.", "attachment": null, "author": { "id": 23, "name": "User 1", "username": "user1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/111d68d06e2d317b5a59c2c6c5bad808?s=80&d=identicon", "web_url": "http://localhost:3000/user1" }, "created_at": "2017-09-05T08:01:32.068Z", "updated_at": "2017-09-05T08:01:32.068Z", "system": false, "noteable_id": 22, "noteable_type": "Issue", "noteable_iid": 2 } ] +``` + +### Scope: wiki_blobs[](#scope-wiki_blobs "Permalink") + +过滤器可用于以下范围: + +* filename +* path +* extension + +要使用过滤器,只需将其包含在查询中,例如: `a query filename:some_name*` . 您可以使用通配符( `*` )使用全局匹配. + +Wiki blobs searches are performed on both filenames and contents. Search results: + +* 在文件名中找到的结果显示在内容中之前. +* 可能包含同一 blob 的多个匹配项,因为可能在文件名和内容中都找到了搜索字符串,或者在内容中可能出现了多次. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/6/search?scope=wiki_blobs&search=bye" +``` + +响应示例: + +``` + [ { "basename": "home", "data": "hello\n\nand bye\n\nend", "path": "home.md", "filename": "home.md", "id": null, "ref": "master", "startline": 5, "project_id": 6 } ] +``` + +**注意:**不建议使用`filename`而推荐使用`path` . 两者都返回存储库中文件的完整路径,但将来`filename`名将仅是文件名,而不是完整路径. 有关详细信息,请参见[问题 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521) . + +### Scope: commits[](#scope-commits "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/6/search?scope=commits&search=bye" +``` + +响应示例: + +``` + [ { "id": "4109c2d872d5fdb1ed057400d103766aaea97f98", "short_id": "4109c2d8", "title": "goodbye $.browser", "created_at": "2013-02-18T22:02:54.000Z", "parent_ids": [ "59d05353ab575bcc2aa958fe1782e93297de64c9" ], "message": "goodbye $.browser\n", "author_name": "angus croll", "author_email": "anguscroll@gmail.com", "authored_date": "2013-02-18T22:02:54.000Z", "committer_name": "angus croll", "committer_email": "anguscroll@gmail.com", "committed_date": "2013-02-18T22:02:54.000Z", "project_id": 6 } ] +``` + +### Scope: blobs[](#scope-blobs "Permalink") + +过滤器可用于以下范围: + +* filename +* path +* extension + +要使用过滤器,只需将其包含在查询中,例如: `a query filename:some_name*` . 您可以使用通配符( `*` )使用全局匹配. + +对文件名和内容都进行 Blob 搜索. 搜索结果: + +* 在文件名中找到的结果显示在内容中之前. +* 可能包含同一 blob 的多个匹配项,因为可能在文件名和内容中都找到了搜索字符串,或者在内容中可能出现了多次. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/6/search?scope=blobs&search=installation&ref=feature" +``` + +响应示例: + +``` + [ { "basename": "README", "data": "```\n\n## Installation\n\nQuick start using the [pre-built", "path": "README.md", "filename": "README.md", "id": null, "ref": "feature", "startline": 46, "project_id": 6 } ] +``` + +**注意:**不建议使用`filename`而推荐使用`path` . 两者都返回存储库中文件的完整路径,但将来`filename`名将仅是文件名,而不是完整路径. 有关详细信息,请参见[问题 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521) . + +### Scope: users[](#scope-users-2 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/6/search?scope=users&search=doe" +``` + +响应示例: + +``` +[ { "id": 1, "name": "John Doe1", "username": "user1", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://localhost/user1" } ] +``` \ No newline at end of file diff --git a/_book/docs/367.md b/_book/docs/367.md new file mode 100644 index 0000000000000000000000000000000000000000..1cfc6353476802260ee5078711915088bd73182d --- /dev/null +++ b/_book/docs/367.md @@ -0,0 +1,1578 @@ +# Services API + +> 原文:[https://docs.gitlab.com/ee/api/services.html](https://docs.gitlab.com/ee/api/services.html) + +* [List all active services](#list-all-active-services) +* [Asana](#asana) + * [Create/Edit Asana service](#createedit-asana-service) + * [Delete Asana service](#delete-asana-service) + * [Get Asana service settings](#get-asana-service-settings) +* [Assembla](#assembla) + * [Create/Edit Assembla service](#createedit-assembla-service) + * [Delete Assembla service](#delete-assembla-service) + * [Get Assembla service settings](#get-assembla-service-settings) +* [Atlassian Bamboo CI](#atlassian-bamboo-ci) + * [Create/Edit Atlassian Bamboo CI service](#createedit-atlassian-bamboo-ci-service) + * [Delete Atlassian Bamboo CI service](#delete-atlassian-bamboo-ci-service) + * [Get Atlassian Bamboo CI service settings](#get-atlassian-bamboo-ci-service-settings) +* [Bugzilla](#bugzilla) + * [Create/Edit Bugzilla service](#createedit-bugzilla-service) + * [Delete Bugzilla Service](#delete-bugzilla-service) + * [Get Bugzilla Service Settings](#get-bugzilla-service-settings) +* [Buildkite](#buildkite) + * [Create/Edit Buildkite service](#createedit-buildkite-service) + * [Delete Buildkite service](#delete-buildkite-service) + * [Get Buildkite service settings](#get-buildkite-service-settings) +* [Campfire](#campfire) + * [Create/Edit Campfire service](#createedit-campfire-service) + * [Delete Campfire service](#delete-campfire-service) + * [Get Campfire service settings](#get-campfire-service-settings) +* [Unify Circuit](#unify-circuit) + * [Create/Edit Unify Circuit service](#createedit-unify-circuit-service) + * [Delete Unify Circuit service](#delete-unify-circuit-service) + * [Get Unify Circuit service settings](#get-unify-circuit-service-settings) +* [Webex Teams](#webex-teams) + * [Create/Edit Webex Teams service](#createedit-webex-teams-service) + * [Delete Webex Teams service](#delete-webex-teams-service) + * [Get Webex Teams service settings](#get-webex-teams-service-settings) +* [Custom Issue Tracker](#custom-issue-tracker) + * [Create/Edit Custom Issue Tracker service](#createedit-custom-issue-tracker-service) + * [Delete Custom Issue Tracker service](#delete-custom-issue-tracker-service) + * [Get Custom Issue Tracker service settings](#get-custom-issue-tracker-service-settings) +* [Drone CI](#drone-ci) + * [Create/Edit Drone CI service](#createedit-drone-ci-service) + * [Delete Drone CI service](#delete-drone-ci-service) + * [Get Drone CI service settings](#get-drone-ci-service-settings) +* [Emails on push](#emails-on-push) + * [Create/Edit Emails on push service](#createedit-emails-on-push-service) + * [Delete Emails on push service](#delete-emails-on-push-service) + * [Get Emails on push service settings](#get-emails-on-push-service-settings) +* [Confluence service](#confluence-service) + * [Create/Edit Confluence service](#createedit-confluence-service) + * [Delete Confluence service](#delete-confluence-service) + * [Get Confluence service settings](#get-confluence-service-settings) +* [External Wiki](#external-wiki) + * [Create/Edit External Wiki service](#createedit-external-wiki-service) + * [Delete External Wiki service](#delete-external-wiki-service) + * [Get External Wiki service settings](#get-external-wiki-service-settings) +* [Flowdock](#flowdock) + * [Create/Edit Flowdock service](#createedit-flowdock-service) + * [Delete Flowdock service](#delete-flowdock-service) + * [Get Flowdock service settings](#get-flowdock-service-settings) +* [GitHub](#github-premium) + * [Create/Edit GitHub service](#createedit-github-service) + * [Delete GitHub service](#delete-github-service) + * [Get GitHub service settings](#get-github-service-settings) +* [Hangouts Chat](#hangouts-chat) + * [Create/Edit Hangouts Chat service](#createedit-hangouts-chat-service) + * [Delete Hangouts Chat service](#delete-hangouts-chat-service) + * [Get Hangouts Chat service settings](#get-hangouts-chat-service-settings) +* [HipChat](#hipchat) + * [Create/Edit HipChat service](#createedit-hipchat-service) + * [Delete HipChat service](#delete-hipchat-service) + * [Get HipChat service settings](#get-hipchat-service-settings) +* [Irker (IRC gateway)](#irker-irc-gateway) + * [Create/Edit Irker (IRC gateway) service](#createedit-irker-irc-gateway-service) + * [Delete Irker (IRC gateway) service](#delete-irker-irc-gateway-service) + * [Get Irker (IRC gateway) service settings](#get-irker-irc-gateway-service-settings) +* [Jira](#jira) + * [Get Jira service settings](#get-jira-service-settings) + * [Create/Edit Jira service](#createedit-jira-service) + * [Delete Jira service](#delete-jira-service) +* [Slack slash commands](#slack-slash-commands) + * [Get Slack slash command service settings](#get-slack-slash-command-service-settings) + * [Create/Edit Slack slash command service](#createedit-slack-slash-command-service) + * [Delete Slack slash command service](#delete-slack-slash-command-service) +* [Mattermost slash commands](#mattermost-slash-commands) + * [Get Mattermost slash command service settings](#get-mattermost-slash-command-service-settings) + * [Create/Edit Mattermost slash command service](#createedit-mattermost-slash-command-service) + * [Delete Mattermost slash command service](#delete-mattermost-slash-command-service) +* [Packagist](#packagist) + * [Create/Edit Packagist service](#createedit-packagist-service) + * [Delete Packagist service](#delete-packagist-service) + * [Get Packagist service settings](#get-packagist-service-settings) +* [Pipeline-Emails](#pipeline-emails) + * [Create/Edit Pipeline-Emails service](#createedit-pipeline-emails-service) + * [Delete Pipeline-Emails service](#delete-pipeline-emails-service) + * [Get Pipeline-Emails service settings](#get-pipeline-emails-service-settings) +* [PivotalTracker](#pivotaltracker) + * [Create/Edit PivotalTracker service](#createedit-pivotaltracker-service) + * [Delete PivotalTracker service](#delete-pivotaltracker-service) + * [Get PivotalTracker service settings](#get-pivotaltracker-service-settings) +* [Prometheus](#prometheus) + * [Create/Edit Prometheus service](#createedit-prometheus-service) + * [Delete Prometheus service](#delete-prometheus-service) + * [Get Prometheus service settings](#get-prometheus-service-settings) +* [Pushover](#pushover) + * [Create/Edit Pushover service](#createedit-pushover-service) + * [Delete Pushover service](#delete-pushover-service) + * [Get Pushover service settings](#get-pushover-service-settings) +* [Redmine](#redmine) + * [Create/Edit Redmine service](#createedit-redmine-service) + * [Delete Redmine service](#delete-redmine-service) + * [Get Redmine service settings](#get-redmine-service-settings) +* [Slack notifications](#slack-notifications) + * [Create/Edit Slack service](#createedit-slack-service) + * [Delete Slack service](#delete-slack-service) + * [Get Slack service settings](#get-slack-service-settings) +* [Microsoft Teams](#microsoft-teams) + * [Create/Edit Microsoft Teams service](#createedit-microsoft-teams-service) + * [Delete Microsoft Teams service](#delete-microsoft-teams-service) + * [Get Microsoft Teams service settings](#get-microsoft-teams-service-settings) +* [Mattermost notifications](#mattermost-notifications) + * [Create/Edit Mattermost notifications service](#createedit-mattermost-notifications-service) + * [Delete Mattermost notifications service](#delete-mattermost-notifications-service) + * [Get Mattermost notifications service settings](#get-mattermost-notifications-service-settings) +* [JetBrains TeamCity CI](#jetbrains-teamcity-ci) + * [Create/Edit JetBrains TeamCity CI service](#createedit-jetbrains-teamcity-ci-service) + * [Delete JetBrains TeamCity CI service](#delete-jetbrains-teamcity-ci-service) + * [Get JetBrains TeamCity CI service settings](#get-jetbrains-teamcity-ci-service-settings) +* [Jenkins CI](#jenkins-ci-starter) + * [Create/Edit Jenkins CI service](#createedit-jenkins-ci-service) + * [Delete Jenkins CI service](#delete-jenkins-ci-service) + * [Get Jenkins CI service settings](#get-jenkins-ci-service-settings) +* [Jenkins CI (Deprecated) Service](#jenkins-ci-deprecated-service) + * [Create/Edit Jenkins CI (Deprecated) service](#createedit-jenkins-ci-deprecated-service) + * [Delete Jenkins CI (Deprecated) service](#delete-jenkins-ci-deprecated-service) + * [Get Jenkins CI (Deprecated) service settings](#get-jenkins-ci-deprecated-service-settings) +* [MockCI](#mockci) + * [Create/Edit MockCI service](#createedit-mockci-service) + * [Delete MockCI service](#delete-mockci-service) + * [Get MockCI service settings](#get-mockci-service-settings) +* [YouTrack](#youtrack) + * [Create/Edit YouTrack service](#createedit-youtrack-service) + * [Delete YouTrack Service](#delete-youtrack-service) + * [Get YouTrack Service Settings](#get-youtrack-service-settings) + +# Services API[](#services-api "Permalink") + +> **注意:**此 API 需要具有维护者或所有者权限的访问令牌 + +## List all active services[](#list-all-active-services "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21330) . + +获取所有活动项目服务的列表. + +``` +GET /projects/:id/services +``` + +响应示例: + +``` +[ { "id": 75, "title": "Jenkins CI", "slug": "jenkins", "created_at": "2019-11-20T11:20:25.297Z", "updated_at": "2019-11-20T12:24:37.498Z", "active": true, "commit_events": true, "push_events": true, "issues_events": true, "confidential_issues_events": true, "merge_requests_events": true, "tag_push_events": false, "note_events": true, "confidential_note_events": true, "pipeline_events": true, "wiki_page_events": true, "job_events": true, "comment_on_event_enabled": true } { "id": 76, "title": "Alerts endpoint", "slug": "alerts", "created_at": "2019-11-20T11:20:25.297Z", "updated_at": "2019-11-20T12:24:37.498Z", "active": true, "commit_events": true, "push_events": true, "issues_events": true, "confidential_issues_events": true, "merge_requests_events": true, "tag_push_events": true, "note_events": true, "confidential_note_events": true, "pipeline_events": true, "wiki_page_events": true, "job_events": true, "comment_on_event_enabled": true } ] +``` + +## Asana[](#asana "Permalink") + +Asana-无需电子邮件的团队合作 + +### Create/Edit Asana service[](#createedit-asana-service "Permalink") + +为项目设置 Asana 服务. + +> 该服务将提交消息添加为 Asana 任务的注释. 启用后,将检查提交消息中的 Asana 任务 URL(例如`https://app.asana.com/0/123456/987654` )或以#开头的任务 ID(例如`#987654` ). 找到的每个任务 ID 都会在其中添加提交注释. 您还可以通过以下消息关闭任务: `fix #123456` . 您可以在以下位置找到您的 API 密钥: [https](https://developers.asana.com/docs/#authentication-basics) : [//developers.asana.com/docs/#authentication-basics](https://developers.asana.com/docs/#authentication-basics) . + +``` +PUT /projects/:id/services/asana +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `api_key` | string | true | 用户 API 令牌. 用户必须有权访问任务,所有评论都将归于该用户. | +| `restrict_to_branch` | string | false | 以逗号分隔的分支列表,将自动对其进行检查. 保留空白以包括所有分支. | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Asana service[](#delete-asana-service "Permalink") + +删除项目的 Asana 服务. + +``` +DELETE /projects/:id/services/asana +``` + +### Get Asana service settings[](#get-asana-service-settings "Permalink") + +获取项目的 Asana 服务设置. + +``` +GET /projects/:id/services/asana +``` + +## Assembla[](#assembla "Permalink") + +项目管理软件(源提交端点) + +### Create/Edit Assembla service[](#createedit-assembla-service "Permalink") + +为项目设置 Assembla 服务. + +``` +PUT /projects/:id/services/assembla +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | 认证令牌 | +| `subdomain` | string | false | 子域设置 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Assembla service[](#delete-assembla-service "Permalink") + +删除项目的 Assembla 服务. + +``` +DELETE /projects/:id/services/assembla +``` + +### Get Assembla service settings[](#get-assembla-service-settings "Permalink") + +获取项目的 Assembla 服务设置. + +``` +GET /projects/:id/services/assembla +``` + +## Atlassian Bamboo CI[](#atlassian-bamboo-ci "Permalink") + +持续集成和构建服务器 + +### Create/Edit Atlassian Bamboo CI service[](#createedit-atlassian-bamboo-ci-service "Permalink") + +为项目设置 Atlassian Bamboo CI 服务. + +> 您必须在 Bamboo 中设置自动修订标签和存储库触发器. + +``` +PUT /projects/:id/services/bamboo +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `bamboo_url` | string | true | 竹根 URL. 例如, `https://bamboo.example.com` . | +| `build_key` | string | true | 竹构建计划密钥,如 KEY | +| `username` | string | true | 具有 API 访问权限的用户(如果适用) | +| `password` | string | true | 用户密码 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Atlassian Bamboo CI service[](#delete-atlassian-bamboo-ci-service "Permalink") + +删除项目的 Atlassian Bamboo CI 服务. + +``` +DELETE /projects/:id/services/bamboo +``` + +### Get Atlassian Bamboo CI service settings[](#get-atlassian-bamboo-ci-service-settings "Permalink") + +获取项目的 Atlassian Bamboo CI 服务设置. + +``` +GET /projects/:id/services/bamboo +``` + +## Bugzilla[](#bugzilla "Permalink") + +Bugzilla 问题追踪器 + +### Create/Edit Bugzilla service[](#createedit-bugzilla-service "Permalink") + +为项目设置 Bugzilla 服务. + +``` +PUT /projects/:id/services/bugzilla +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `new_issue_url` | string | true | 新发行网址 | +| `issues_url` | string | true | 发行网址 | +| `project_url` | string | true | 项目网址 | +| `description` | string | false | Description | +| `title` | string | false | Title | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Bugzilla Service[](#delete-bugzilla-service "Permalink") + +删除项目的 Bugzilla 服务. + +``` +DELETE /projects/:id/services/bugzilla +``` + +### Get Bugzilla Service Settings[](#get-bugzilla-service-settings "Permalink") + +获取项目的 Bugzilla 服务设置. + +``` +GET /projects/:id/services/bugzilla +``` + +## Buildkite[](#buildkite "Permalink") + +持续集成和部署 + +### Create/Edit Buildkite service[](#createedit-buildkite-service "Permalink") + +为项目设置 Buildkite 服务. + +``` +PUT /projects/:id/services/buildkite +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | Buildkite 项目 GitLab 令牌 | +| `project_url` | string | true | `https://buildkite.com/example/project` | +| `enable_ssl_verification` | boolean | false | 启用 S​​SL 验证 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Buildkite service[](#delete-buildkite-service "Permalink") + +删除项目的 Buildkite 服务. + +``` +DELETE /projects/:id/services/buildkite +``` + +### Get Buildkite service settings[](#get-buildkite-service-settings "Permalink") + +获取项目的 Buildkite 服务设置. + +``` +GET /projects/:id/services/buildkite +``` + +## Campfire[](#campfire "Permalink") + +基于网络的简单实时群聊 + +### Create/Edit Campfire service[](#createedit-campfire-service "Permalink") + +为项目设置篝火服务. + +``` +PUT /projects/:id/services/campfire +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | 篝火令牌 | +| `subdomain` | string | false | 篝火子域 | +| `room` | string | false | 篝火室 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Campfire service[](#delete-campfire-service "Permalink") + +删除项目的 Campfire 服务. + +``` +DELETE /projects/:id/services/campfire +``` + +### Get Campfire service settings[](#get-campfire-service-settings "Permalink") + +获取项目的 Campfire 服务设置. + +``` +GET /projects/:id/services/campfire +``` + +## Unify Circuit[](#unify-circuit "Permalink") + +统一电路 RTC 和协作工具. + +### Create/Edit Unify Circuit service[](#createedit-unify-circuit-service "Permalink") + +为项目设置"统一电路"服务. + +``` +PUT /projects/:id/services/unify-circuit +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `webhook` | string | true | 统一电路网络挂钩. 例如, `https://circuit.com/rest/v2/webhooks/incoming/...` | +| `notify_only_broken_pipelines` | boolean | false | 发送有关管道中断的通知 | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `push_events` | boolean | false | 启用推送事件通知 | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `confidential_issues_events` | boolean | false | 启用机密问题事件的通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `note_events` | boolean | false | 启用笔记事件通知 | +| `confidential_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | +| `wiki_page_events` | boolean | false | 启用 Wiki 页面事件的通知 | + +### Delete Unify Circuit service[](#delete-unify-circuit-service "Permalink") + +删除项目的统一电路服务. + +``` +DELETE /projects/:id/services/unify-circuit +``` + +### Get Unify Circuit service settings[](#get-unify-circuit-service-settings "Permalink") + +获取项目的统一电路服务设置. + +``` +GET /projects/:id/services/unify-circuit +``` + +## Webex Teams[](#webex-teams "Permalink") + +Webex Teams 协作工具. + +### Create/Edit Webex Teams service[](#createedit-webex-teams-service "Permalink") + +为项目设置 Webex Teams 服务. + +``` +PUT /projects/:id/services/webex-teams +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `webhook` | string | true | Webex Teams Webhook. 例如, `https://api.ciscospark.com/v1/webhooks/incoming/...` | +| `notify_only_broken_pipelines` | boolean | false | 发送有关管道中断的通知 | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `push_events` | boolean | false | 启用推送事件通知 | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `confidential_issues_events` | boolean | false | 启用机密问题事件的通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `note_events` | boolean | false | 启用笔记事件通知 | +| `confidential_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | +| `wiki_page_events` | boolean | false | 启用 Wiki 页面事件的通知 | + +### Delete Webex Teams service[](#delete-webex-teams-service "Permalink") + +删除项目的 Webex Teams 服务. + +``` +DELETE /projects/:id/services/webex-teams +``` + +### Get Webex Teams service settings[](#get-webex-teams-service-settings "Permalink") + +获取项目的 Webex Teams 服务设置. + +``` +GET /projects/:id/services/webex-teams +``` + +## Custom Issue Tracker[](#custom-issue-tracker "Permalink") + +自定义问题跟踪器 + +### Create/Edit Custom Issue Tracker service[](#createedit-custom-issue-tracker-service "Permalink") + +为项目设置自定义问题跟踪服务. + +``` +PUT /projects/:id/services/custom-issue-tracker +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `new_issue_url` | string | true | 新发行网址 | +| `issues_url` | string | true | 发行网址 | +| `project_url` | string | true | 项目网址 | +| `description` | string | false | Description | +| `title` | string | false | Title | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Custom Issue Tracker service[](#delete-custom-issue-tracker-service "Permalink") + +删除项目的自定义问题跟踪服务. + +``` +DELETE /projects/:id/services/custom-issue-tracker +``` + +### Get Custom Issue Tracker service settings[](#get-custom-issue-tracker-service-settings "Permalink") + +获取项目的自定义问题跟踪服务设置. + +``` +GET /projects/:id/services/custom-issue-tracker +``` + +## Drone CI[](#drone-ci "Permalink") + +Drone 是一个基于 Go 编写的基于 Docker 的持续集成平台 + +### Create/Edit Drone CI service[](#createedit-drone-ci-service "Permalink") + +为项目设置 Drone CI 服务. + +``` +PUT /projects/:id/services/drone-ci +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | 无人机 CI 项目专用令牌 | +| `drone_url` | string | true | `http://drone.example.com` | +| `enable_ssl_verification` | boolean | false | 启用 S​​SL 验证 | +| `push_events` | boolean | false | 启用推送事件通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | + +### Delete Drone CI service[](#delete-drone-ci-service "Permalink") + +删除项目的 Drone CI 服务. + +``` +DELETE /projects/:id/services/drone-ci +``` + +### Get Drone CI service settings[](#get-drone-ci-service-settings "Permalink") + +获取项目的 Drone CI 服务设置. + +``` +GET /projects/:id/services/drone-ci +``` + +## Emails on push[](#emails-on-push "Permalink") + +通过电子邮件将每次推送的提交和差异发送到收件人列表. + +### Create/Edit Emails on push service[](#createedit-emails-on-push-service "Permalink") + +在项目的推送服务上设置电子邮件. + +``` +PUT /projects/:id/services/emails-on-push +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `recipients` | string | true | 用空格分隔的电子邮件 | +| `disable_diffs` | boolean | false | 禁用代码差异 | +| `send_from_committer_email` | boolean | false | 从提交者发送 | +| `push_events` | boolean | false | 启用推送事件通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected". 推送标签会始终触发通知. | + +### Delete Emails on push service[](#delete-emails-on-push-service "Permalink") + +删除项目的推送服务电子邮件. + +``` +DELETE /projects/:id/services/emails-on-push +``` + +### Get Emails on push service settings[](#get-emails-on-push-service-settings "Permalink") + +获取有关项目的推送服务设置的电子邮件. + +``` +GET /projects/:id/services/emails-on-push +``` + +## Confluence service[](#confluence-service "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/220934) . + +将到内部 Wiki 的链接替换为到 Confluence Cloud Workspace 的链接. + +### Create/Edit Confluence service[](#createedit-confluence-service "Permalink") + +为项目设置 Confluence 服务. + +``` +PUT /projects/:id/services/confluence +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `confluence_url` | string | true | Confluence Cloud Workspace 的 URL 托管在 atlassian.net 上. | + +### Delete Confluence service[](#delete-confluence-service "Permalink") + +删除项目的 Confluence 服务. + +``` +DELETE /projects/:id/services/confluence +``` + +### Get Confluence service settings[](#get-confluence-service-settings "Permalink") + +获取项目的 Confluence 服务设置. + +``` +GET /projects/:id/services/confluence +``` + +## External Wiki[](#external-wiki "Permalink") + +将指向内部 Wiki 的链接替换为指向外部 Wiki 的链接. + +### Create/Edit External Wiki service[](#createedit-external-wiki-service "Permalink") + +为项目设置外部 Wiki 服务. + +``` +PUT /projects/:id/services/external-wiki +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `external_wiki_url` | string | true | 外部 Wiki 的 URL | + +### Delete External Wiki service[](#delete-external-wiki-service "Permalink") + +删除项目的外部 Wiki 服务. + +``` +DELETE /projects/:id/services/external-wiki +``` + +### Get External Wiki service settings[](#get-external-wiki-service-settings "Permalink") + +获取项目的外部 Wiki 服务设置. + +``` +GET /projects/:id/services/external-wiki +``` + +## Flowdock[](#flowdock "Permalink") + +Flowdock 是面向技术团队的协作 Web 应用程序. + +### Create/Edit Flowdock service[](#createedit-flowdock-service "Permalink") + +为项目设置 Flowdock 服务. + +``` +PUT /projects/:id/services/flowdock +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | Flowdock Git 源令牌 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Flowdock service[](#delete-flowdock-service "Permalink") + +删除项目的 Flowdock 服务. + +``` +DELETE /projects/:id/services/flowdock +``` + +### Get Flowdock service settings[](#get-flowdock-service-settings "Permalink") + +获取项目的 Flowdock 服务设置. + +``` +GET /projects/:id/services/flowdock +``` + +## GitHub[](#github-premium "Permalink") + +代码协作软件. + +### Create/Edit GitHub service[](#createedit-github-service "Permalink") + +为项目设置 GitHub 服务. + +``` +PUT /projects/:id/services/github +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | 具有`repo:status` OAuth 范围的 GitHub API 令牌 | +| `repository_url` | string | true | GitHub 存储库 URL | +| `static_context` | boolean | false | 将实例名称而不是分支附加到[状态检查名称](../user/project/integrations/github.html#static--dynamic-status-check-names) | + +### Delete GitHub service[](#delete-github-service "Permalink") + +删除项目的 GitHub 服务. + +``` +DELETE /projects/:id/services/github +``` + +### Get GitHub service settings[](#get-github-service-settings "Permalink") + +获取项目的 GitHub 服务设置. + +``` +GET /projects/:id/services/github +``` + +## Hangouts Chat[](#hangouts-chat "Permalink") + +Google GSuite 团队协作工具. + +> **注意:**此服务是[在 v11.2](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20290)中[引入的](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20290) + +### Create/Edit Hangouts Chat service[](#createedit-hangouts-chat-service "Permalink") + +为项目设置环聊聊天服务. + +``` +PUT /projects/:id/services/hangouts-chat +``` + +> **注意:** [v10.4](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435)特定的事件参数(例如`push_events`标志) + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `webhook` | string | true | Hangouts 即时通讯网路挂钩. 例如, `https://chat.googleapis.com/v1/spaces...` | +| `notify_only_broken_pipelines` | boolean | false | 发送有关管道中断的通知 | +| `notify_only_default_branch` | boolean | false | 已弃用:此参数已替换为`branches_to_be_notified` | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `push_events` | boolean | false | 启用推送事件通知 | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `note_events` | boolean | false | 启用笔记事件通知 | +| `confidential_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | +| `wiki_page_events` | boolean | false | 启用 Wiki 页面事件的通知 | + +### Delete Hangouts Chat service[](#delete-hangouts-chat-service "Permalink") + +删除项目的环聊聊天服务. + +``` +DELETE /projects/:id/services/hangouts-chat +``` + +### Get Hangouts Chat service settings[](#get-hangouts-chat-service-settings "Permalink") + +获取项目的环聊聊天服务设置. + +``` +GET /projects/:id/services/hangouts-chat +``` + +## HipChat[](#hipchat "Permalink") + +私人群聊和即时消息 + +### Create/Edit HipChat service[](#createedit-hipchat-service "Permalink") + +为项目设置 HipChat 服务. + +``` +PUT /projects/:id/services/hipchat +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | 房间代币 | +| `color` | string | false | 房间颜色 | +| `notify` | boolean | false | 启用通知 | +| `room` | string | false | 房间名称或 ID | +| `api_version` | string | false | 默认保留空白(v2) | +| `server` | string | false | 默认保留空白. 例如, `https://hipchat.example.com` . | +| `push_events` | boolean | false | 启用推送事件通知 | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `confidential_issues_events` | boolean | false | 启用机密问题事件的通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `note_events` | boolean | false | Enable notifications for note events | +| `confidental_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | + +### Delete HipChat service[](#delete-hipchat-service "Permalink") + +删除项目的 HipChat 服务. + +``` +DELETE /projects/:id/services/hipchat +``` + +### Get HipChat service settings[](#get-hipchat-service-settings "Permalink") + +获取项目的 HipChat 服务设置. + +``` +GET /projects/:id/services/hipchat +``` + +## Irker (IRC gateway)[](#irker-irc-gateway "Permalink") + +通过 Irker 网关在更新后将 IRC 消息发送到收件人列表. + +### Create/Edit Irker (IRC gateway) service[](#createedit-irker-irc-gateway-service "Permalink") + +为项目设置 Irker(IRC 网关)服务. + +> Irker 没有内置的身份验证,如果托管在防火墙外部,则容易受到 IRC 垃圾邮件的攻击. 请确保在安全的网络中运行守护程序,以防止滥用. 有关更多详细信息,请阅读: [http](http://www.catb.org/~esr/irker/security.html) : [//www.catb.org/~esr/irker/security.html](http://www.catb.org/~esr/irker/security.html) . + +``` +PUT /projects/:id/services/irker +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `recipients` | string | true | 用空格分隔的收件人/渠道 | +| `default_irc_uri` | string | false | `irc://irc.network.net:6697/` | +| `server_host` | string | false | localhost | +| `server_port` | integer | false | 6659 | +| `colorize_messages` | boolean | false | 为邮件着色 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Irker (IRC gateway) service[](#delete-irker-irc-gateway-service "Permalink") + +删除项目的 Irker(IRC 网关)服务. + +``` +DELETE /projects/:id/services/irker +``` + +### Get Irker (IRC gateway) service settings[](#get-irker-irc-gateway-service-settings "Permalink") + +Get Irker (IRC gateway) service settings for a project. + +``` +GET /projects/:id/services/irker +``` + +## Jira[](#jira "Permalink") + +吉拉问题追踪器. + +### Get Jira service settings[](#get-jira-service-settings "Permalink") + +获取项目的 Jira 服务设置. + +``` +GET /projects/:id/services/jira +``` + +### Create/Edit Jira service[](#createedit-jira-service "Permalink") + +为项目设置 Jira 服务. + +> 与 GitLab 8.14 开始, `api_url` , `issues_url` , `new_issue_url`和`project_url`被替换`url` . 如果您使用的是旧版本,请[遵循此文档](https://gitlab.com/gitlab-org/gitlab/blob/8-13-stable-ee/doc/api/services.md#jira) . + +``` +PUT /projects/:id/services/jira +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `url` | string | yes | 链接到该 GitLab 项目的 Jira 项目的 URL. 例如, `https://jira.example.com` . | +| `api_url` | string | no | Jira 实例 API 的基本 URL. 如果未设置,将使用 Web URL 值. 例如, `https://jira-api.example.com` . | +| `username` | string | yes | 创建用于 GitLab / Jira 的用户的用户名. | +| `password` | string | yes | 创建的用于 GitLab / Jira 的用户密码. | +| `active` | boolean | no | 激活或停用服务. 默认为 false(停用). | +| `jira_issue_transition_id` | string | no | 将问题移到关闭状态的过渡的 ID. 您可以在 Jira 工作流管理( **管理>问题>工作流** )下找到该编号,方法是在所需项目工作流的" **操作** **"**下选择" **查看** **"** . 每个状态的 ID 可以在" **转换(id)"**列下每个转换名称的括号内找到. 默认情况下,此 ID 设置为`2` . | +| `commit_events` | boolean | false | 启用提交事件通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `comment_on_event_enabled` | boolean | false | 在每个 GitLab 事件(提交/合并请求)的 Jira 问题中启用评论 | + +### Delete Jira service[](#delete-jira-service "Permalink") + +从项目中删除所有以前的 Jira 设置. + +``` +DELETE /projects/:id/services/jira +``` + +## Slack slash commands[](#slack-slash-commands "Permalink") + +能够从 Slack 聊天实例接收斜线命令. + +### Get Slack slash command service settings[](#get-slack-slash-command-service-settings "Permalink") + +获取项目的 Slack 斜杠命令服务设置. + +``` +GET /projects/:id/services/slack-slash-commands +``` + +响应示例: + +``` +{ "id": 4, "title": "Slack slash commands", "slug": "slack-slash-commands", "created_at": "2017-06-27T05:51:39-07:00", "updated_at": "2017-06-27T05:51:39-07:00", "active": true, "push_events": true, "issues_events": true, "confidential_issues_events": true, "merge_requests_events": true, "tag_push_events": true, "note_events": true, "job_events": true, "pipeline_events": true, "comment_on_event_enabled": false, "properties": { "token": "" } } +``` + +### Create/Edit Slack slash command service[](#createedit-slack-slash-command-service "Permalink") + +为项目设置 Slack 斜杠命令. + +``` +PUT /projects/:id/services/slack-slash-commands +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | yes | Slack 令牌 | + +### Delete Slack slash command service[](#delete-slack-slash-command-service "Permalink") + +删除项目的 Slack 斜杠命令服务. + +``` +DELETE /projects/:id/services/slack-slash-commands +``` + +## Mattermost slash commands[](#mattermost-slash-commands "Permalink") + +能够从 Mattermost 聊天实例接收斜线命令. + +### Get Mattermost slash command service settings[](#get-mattermost-slash-command-service-settings "Permalink") + +获取项目的 Mattermost 斜杠命令服务设置. + +``` +GET /projects/:id/services/mattermost-slash-commands +``` + +### Create/Edit Mattermost slash command service[](#createedit-mattermost-slash-command-service "Permalink") + +为项目设置 Mattermost 斜杠命令. + +``` +PUT /projects/:id/services/mattermost-slash-commands +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | yes | 最重要的令牌 | +| `username` | string | no | 用于发布消息的用户名 | + +### Delete Mattermost slash command service[](#delete-mattermost-slash-command-service "Permalink") + +删除项目的 Mattermost 斜杠命令服务. + +``` +DELETE /projects/:id/services/mattermost-slash-commands +``` + +## Packagist[](#packagist "Permalink") + +当提交或标签被推送到 GitLab 时,在 Packagist(主要的 Composer 存储库)上更新您的项目. + +### Create/Edit Packagist service[](#createedit-packagist-service "Permalink") + +为项目设置 Packagist 服务. + +``` +PUT /projects/:id/services/packagist +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `username` | string | yes | Packagist 帐户的用户名 | +| `token` | string | yes | Packagist 服务器的 API 令牌 | +| `server` | boolean | no | Packagist 服务器的 URL. 默认保留空白: [https](https://packagist.org) : [//packagist.org](https://packagist.org) | +| `push_events` | boolean | false | 启用推送事件通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | + +### Delete Packagist service[](#delete-packagist-service "Permalink") + +删除项目的 Packagist 服务. + +``` +DELETE /projects/:id/services/packagist +``` + +### Get Packagist service settings[](#get-packagist-service-settings "Permalink") + +获取项目的 Packagist 服务设置. + +``` +GET /projects/:id/services/packagist +``` + +## Pipeline-Emails[](#pipeline-emails "Permalink") + +获取有关 GitLab CI / CD 管道的电子邮件. + +### Create/Edit Pipeline-Emails service[](#createedit-pipeline-emails-service "Permalink") + +设置项目的管道电子邮件服务. + +``` +PUT /projects/:id/services/pipelines-email +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `recipients` | string | yes | 以逗号分隔的收件人电子邮件地址列表 | +| `add_pusher` | boolean | no | 将推送器添加到收件人列表 | +| `notify_only_broken_pipelines` | boolean | no | 仅通知断开的管道 | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `notify_only_default_branch` | boolean | no | 仅针对默认分支发送通知( [在 GitLab 12.0 中引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28271) ) | +| `pipeline_events` | boolean | false | 启用管道事件通知 | + +### Delete Pipeline-Emails service[](#delete-pipeline-emails-service "Permalink") + +删除项目的管道电子邮件服务. + +``` +DELETE /projects/:id/services/pipelines-email +``` + +### Get Pipeline-Emails service settings[](#get-pipeline-emails-service-settings "Permalink") + +获取项目的管道电子邮件服务设置. + +``` +GET /projects/:id/services/pipelines-email +``` + +## PivotalTracker[](#pivotaltracker "Permalink") + +项目管理软件(源提交端点) + +### Create/Edit PivotalTracker service[](#createedit-pivotaltracker-service "Permalink") + +为项目设置 PivotalTracker 服务. + +``` +PUT /projects/:id/services/pivotaltracker +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | PivotalTracker 令牌 | +| `restrict_to_branch` | boolean | false | 以逗号分隔的分支列表,将自动对其进行检查. 保留空白以包括所有分支. | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete PivotalTracker service[](#delete-pivotaltracker-service "Permalink") + +删除项目的 PivotalTracker 服务. + +``` +DELETE /projects/:id/services/pivotaltracker +``` + +### Get PivotalTracker service settings[](#get-pivotaltracker-service-settings "Permalink") + +获取项目的 PivotalTracker 服务设置. + +``` +GET /projects/:id/services/pivotaltracker +``` + +## Prometheus[](#prometheus "Permalink") + +Prometheus 是一项功能强大的时间序列监视服务. + +### Create/Edit Prometheus service[](#createedit-prometheus-service "Permalink") + +为项目设置 Prometheus 服务. + +``` +PUT /projects/:id/services/prometheus +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `api_url` | string | true | Prometheus API 基本 URL. 例如, `http://prometheus.example.com/` . | +| `google_iap_audience_client_id` | string | false | IAP 受保护资源的客户端 ID(看起来像 IAP_CLIENT_ID.apps.googleusercontent.com) | +| `google_iap_service_account_json` | string | false | 您的服务帐户的`credentials.json`文件,例如{" type":" service_account"," project_id":…} | + +### Delete Prometheus service[](#delete-prometheus-service "Permalink") + +删除项目的 Prometheus 服务. + +``` +DELETE /projects/:id/services/prometheus +``` + +### Get Prometheus service settings[](#get-prometheus-service-settings "Permalink") + +获取项目的 Prometheus 服务设置. + +``` +GET /projects/:id/services/prometheus +``` + +## Pushover[](#pushover "Permalink") + +通过 Pushover,可以轻松在 Android 设备,iPhone,iPad 和台式机上获取实时通知. + +### Create/Edit Pushover service[](#createedit-pushover-service "Permalink") + +为项目设置 Pushover 服务. + +``` +PUT /projects/:id/services/pushover +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `api_key` | string | true | Your application key | +| `user_key` | string | true | 您的用户密钥 | +| `priority` | string | true | 优先事项 | +| `device` | string | false | 对于所有活动设备保留空白 | +| `sound` | string | false | 通知的声音 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Pushover service[](#delete-pushover-service "Permalink") + +删除项目的 Pushover 服务. + +``` +DELETE /projects/:id/services/pushover +``` + +### Get Pushover service settings[](#get-pushover-service-settings "Permalink") + +获取项目的 Pushover 服务设置. + +``` +GET /projects/:id/services/pushover +``` + +## Redmine[](#redmine "Permalink") + +Redmine 问题追踪器 + +### Create/Edit Redmine service[](#createedit-redmine-service "Permalink") + +为项目设置 Redmine 服务. + +``` +PUT /projects/:id/services/redmine +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `new_issue_url` | string | true | 新发行网址 | +| `project_url` | string | true | 项目网址 | +| `issues_url` | string | true | 发行网址 | +| `description` | string | false | Description | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Redmine service[](#delete-redmine-service "Permalink") + +删除项目的 Redmine 服务. + +``` +DELETE /projects/:id/services/redmine +``` + +### Get Redmine service settings[](#get-redmine-service-settings "Permalink") + +获取项目的 Redmine 服务设置. + +``` +GET /projects/:id/services/redmine +``` + +## Slack notifications[](#slack-notifications "Permalink") + +在 Slack 中接收事件通知 + +### Create/Edit Slack service[](#createedit-slack-service "Permalink") + +为项目设置 Slack 服务. + +``` +PUT /projects/:id/services/slack +``` + +> **注意:** [v10.4](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435)特定的事件参数(例如`push_events`标志和`push_channel` ) + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `webhook` | string | true | `https://hooks.slack.com/services/...` | +| `username` | string | false | username | +| `channel` | string | false | 如果未配置其他频道,则使用默认频道 | +| `notify_only_broken_pipelines` | boolean | false | 发送有关管道中断的通知 | +| `notify_only_default_branch` | boolean | false | 已弃用:此参数已替换为`branches_to_be_notified` | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `commit_events` | boolean | false | 启用提交事件通知 | +| `confidential_issue_channel` | string | false | 接收机密问题事件通知的渠道的名称 | +| `confidential_issues_events` | boolean | false | 启用机密问题事件的通知 | +| `confidential_note_channel` | string | false | 接收机密笔记事件通知的渠道的名称 | +| `confidential_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `deployment_channel` | string | false | 接收部署事件通知的通道的名称 | +| `deployment_events` | boolean | false | 启用部署事件通知 | +| `issue_channel` | string | false | 接收问题事件通知的渠道的名称 | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `job_events` | boolean | false | 启用工作事件通知 | +| `merge_request_channel` | string | false | 接收合并请求事件通知的通道的名称 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `note_channel` | string | false | 接收音符事件通知的频道名称 | +| `note_events` | boolean | false | 启用笔记事件通知 | +| `pipeline_channel` | string | false | 接收管道事件通知的通道的名称 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | +| `push_channel` | string | false | 接收推送事件通知的通道的名称 | +| `push_events` | boolean | false | 启用推送事件通知 | +| `tag_push_channel` | string | false | 接收标签推送事件通知的通道的名称 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `wiki_page_channel` | string | false | 接收维基页面事件通知的频道名称 | +| `wiki_page_events` | boolean | false | 启用 Wiki 页面事件的通知 | + +### Delete Slack service[](#delete-slack-service "Permalink") + +删除项目的 Slack 服务. + +``` +DELETE /projects/:id/services/slack +``` + +### Get Slack service settings[](#get-slack-service-settings "Permalink") + +获取项目的 Slack 服务设置. + +``` +GET /projects/:id/services/slack +``` + +## Microsoft Teams[](#microsoft-teams "Permalink") + +群聊软件 + +### Create/Edit Microsoft Teams service[](#createedit-microsoft-teams-service "Permalink") + +为项目设置 Microsoft Teams 服务. + +``` +PUT /projects/:id/services/microsoft-teams +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `webhook` | string | true | Microsoft Teams 网络挂钩. 例如, `https://outlook.office.com/webhook/...` | +| `notify_only_broken_pipelines` | boolean | false | 发送有关管道中断的通知 | +| `notify_only_default_branch` | boolean | false | 已弃用:此参数已替换为`branches_to_be_notified` | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `push_events` | boolean | false | Enable notifications for push events | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `confidential_issues_events` | boolean | false | 启用机密问题事件的通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `note_events` | boolean | false | 启用笔记事件通知 | +| `confidential_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | +| `wiki_page_events` | boolean | false | 启用 Wiki 页面事件的通知 | + +### Delete Microsoft Teams service[](#delete-microsoft-teams-service "Permalink") + +删除项目的 Microsoft Teams 服务. + +``` +DELETE /projects/:id/services/microsoft-teams +``` + +### Get Microsoft Teams service settings[](#get-microsoft-teams-service-settings "Permalink") + +获取项目的 Microsoft Teams 服务设置. + +``` +GET /projects/:id/services/microsoft-teams +``` + +## Mattermost notifications[](#mattermost-notifications "Permalink") + +在 Mattermost 接收事件通知 + +### Create/Edit Mattermost notifications service[](#createedit-mattermost-notifications-service "Permalink") + +为项目设置 Mattermost 服务. + +``` +PUT /projects/:id/services/mattermost +``` + +> **注意:** [v10.4](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435)特定的事件参数(例如`push_events`标志和`push_channel` ) + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `webhook` | string | true | 最重要的网络挂钩. 例如, `http://mattermost_host/hooks/...` | +| `username` | string | false | username | +| `channel` | string | false | 如果未配置其他频道,则使用默认频道 | +| `notify_only_broken_pipelines` | boolean | false | 发送有关管道中断的通知 | +| `notify_only_default_branch` | boolean | false | 已弃用:此参数已替换为`branches_to_be_notified` | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `push_events` | boolean | false | 启用推送事件通知 | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `confidential_issues_events` | boolean | false | 启用机密问题事件的通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `note_events` | boolean | false | 启用笔记事件通知 | +| `confidential_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | +| `wiki_page_events` | boolean | false | 启用 Wiki 页面事件的通知 | +| `push_channel` | string | false | 接收推送事件通知的通道的名称 | +| `issue_channel` | string | false | 接收问题事件通知的渠道的名称 | +| `confidential_issue_channel` | string | false | 接收机密问题事件通知的渠道的名称 | +| `merge_request_channel` | string | false | 接收合并请求事件通知的通道的名称 | +| `note_channel` | string | false | 接收音符事件通知的频道名称 | +| `confidential_note_channel` | boolean | 接收机密笔记事件通知的渠道的名称 |   | +| `tag_push_channel` | string | false | 接收标签推送事件通知的通道的名称 | +| `pipeline_channel` | string | false | 接收管道事件通知的通道的名称 | +| `wiki_page_channel` | string | false | 接收维基页面事件通知的频道名称 | + +### Delete Mattermost notifications service[](#delete-mattermost-notifications-service "Permalink") + +删除项目的 Mattermost Notifications 服务. + +``` +DELETE /projects/:id/services/mattermost +``` + +### Get Mattermost notifications service settings[](#get-mattermost-notifications-service-settings "Permalink") + +获取项目的"最重要的通知"服务设置. + +``` +GET /projects/:id/services/mattermost +``` + +## JetBrains TeamCity CI[](#jetbrains-teamcity-ci "Permalink") + +持续集成和构建服务器 + +### Create/Edit JetBrains TeamCity CI service[](#createedit-jetbrains-teamcity-ci-service "Permalink") + +为项目设置 JetBrains TeamCity CI 服务. + +> TeamCity 中的构建配置必须使用构建格式编号`%build.vcs.number%`您还将要配置对所有分支的监视,以便合并请求得以构建,该设置位于 VSC 根高级设置中. + +``` +PUT /projects/:id/services/teamcity +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `teamcity_url` | string | true | TeamCity 根 URL. 例如, `https://teamcity.example.com` | +| `build_type` | string | true | 构建配置 ID | +| `username` | string | true | 有权触发手动构建的用户 | +| `password` | string | true | 用户密码 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete JetBrains TeamCity CI service[](#delete-jetbrains-teamcity-ci-service "Permalink") + +删除项目的 JetBrains TeamCity CI 服务. + +``` +DELETE /projects/:id/services/teamcity +``` + +### Get JetBrains TeamCity CI service settings[](#get-jetbrains-teamcity-ci-service-settings "Permalink") + +获取项目的 JetBrains TeamCity CI 服务设置. + +``` +GET /projects/:id/services/teamcity +``` + +## Jenkins CI[](#jenkins-ci-starter "Permalink") + +持续集成和构建服务器 + +### Create/Edit Jenkins CI service[](#createedit-jenkins-ci-service "Permalink") + +为项目设置 Jenkins CI 服务. + +``` +PUT /projects/:id/services/jenkins +``` + +Parameters: + +* `jenkins_url` ( **必填** ) `jenkins_url` URL,例如`http://jenkins.example.com` +* `project_name` ( **必需** )-URL 友好的项目名称. 示例:my_project_name +* `username` (可选)-有权访问 Jenkins 服务器的`username` (如果适用) +* `password` (可选)-用户的密码 + +### Delete Jenkins CI service[](#delete-jenkins-ci-service "Permalink") + +删除项目的 Jenkins CI 服务. + +``` +DELETE /projects/:id/services/jenkins +``` + +### Get Jenkins CI service settings[](#get-jenkins-ci-service-settings "Permalink") + +获取项目的 Jenkins CI 服务设置. + +``` +GET /projects/:id/services/jenkins +``` + +## Jenkins CI (Deprecated) Service[](#jenkins-ci-deprecated-service "Permalink") + +持续集成和构建服务器 + +**注意:**此服务已[在 v13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/1600)中[删除](https://gitlab.com/gitlab-org/gitlab/-/issues/1600) + +### Create/Edit Jenkins CI (Deprecated) service[](#createedit-jenkins-ci-deprecated-service "Permalink") + +为项目设置 Jenkins CI(不推荐使用)服务. + +``` +PUT /projects/:id/services/jenkins-deprecated +``` + +Parameters: + +* `project_url` ( **必填** )-Jenkins 项目网址,例如`http://jenkins.example.com/job/my-project/` +* `multiproject_enabled` (可选)-在 Jenkins GitLab Hook 插件中配置了多项目模式 +* `pass_unstable` (可选)-不稳定的版本将被视为通过 + +### Delete Jenkins CI (Deprecated) service[](#delete-jenkins-ci-deprecated-service "Permalink") + +删除项目的 Jenkins CI(不推荐使用)服务. + +``` +DELETE /projects/:id/services/jenkins-deprecated +``` + +### Get Jenkins CI (Deprecated) service settings[](#get-jenkins-ci-deprecated-service-settings "Permalink") + +获取项目的 Jenkins CI(不推荐使用)服务设置. + +``` +GET /projects/:id/services/jenkins-deprecated +``` + +## MockCI[](#mockci "Permalink") + +模拟一个外部配置项. 有关伴随模拟服务的示例,请参见[`gitlab-org/gitlab-mock-ci-service`](https://gitlab.com/gitlab-org/gitlab-mock-ci-service) service. + +仅当您的环境设置为开发时,此服务才可用. + +### Create/Edit MockCI service[](#createedit-mockci-service "Permalink") + +为项目设置 MockCI 服务. + +``` +PUT /projects/:id/services/mock-ci +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `mock_service_url` | string | true | `http://localhost:4004` | + +### Delete MockCI service[](#delete-mockci-service "Permalink") + +删除项目的 MockCI 服务. + +``` +DELETE /projects/:id/services/mock-ci +``` + +### Get MockCI service settings[](#get-mockci-service-settings "Permalink") + +获取项目的 MockCI 服务设置. + +``` +GET /projects/:id/services/mock-ci +``` + +## YouTrack[](#youtrack "Permalink") + +YouTrack 问题追踪器 + +### Create/Edit YouTrack service[](#createedit-youtrack-service "Permalink") + +为项目设置 YouTrack 服务. + +``` +PUT /projects/:id/services/youtrack +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `issues_url` | string | true | 发行网址 | +| `project_url` | string | true | 项目网址 | +| `description` | string | false | Description | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete YouTrack Service[](#delete-youtrack-service "Permalink") + +删除项目的 YouTrack 服务. + +``` +DELETE /projects/:id/services/youtrack +``` + +### Get YouTrack Service Settings[](#get-youtrack-service-settings "Permalink") + +获取项目的 YouTrack 服务设置. + +``` +GET /projects/:id/services/youtrack +``` \ No newline at end of file diff --git a/_book/docs/368.md b/_book/docs/368.md new file mode 100644 index 0000000000000000000000000000000000000000..91bfc325f748e319f26a6a54c0f4507ef721ed62 --- /dev/null +++ b/_book/docs/368.md @@ -0,0 +1,254 @@ +# Application settings API + +> 原文:[https://docs.gitlab.com/ee/api/settings.html](https://docs.gitlab.com/ee/api/settings.html) + +* [Get current application settings](#get-current-application-settings) +* [Change application settings](#change-application-settings) +* [List of settings that can be accessed via API calls](#list-of-settings-that-can-be-accessed-via-api-calls) + +# Application settings API[](#application-settings-api-core-only "Permalink") + +这些 API 调用使您可以阅读和修改`/admin/application_settings/general`显示的 GitLab 实例[应用程序设置](#list-of-settings-that-can-be-accessed-via-api-calls) . 您必须是管理员才能执行此操作. + +## Get current application settings[](#get-current-application-settings "Permalink") + +列出 GitLab 实例的当前[应用程序设置](#list-of-settings-that-can-be-accessed-via-api-calls) . + +``` +GET /application/settings +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/application/settings" +``` + +响应示例: + +``` +{ "default_projects_limit" : 100000, "signup_enabled" : true, "id" : 1, "default_branch_protection" : 2, "restricted_visibility_levels" : [], "password_authentication_enabled_for_web" : true, "after_sign_out_path" : null, "max_attachment_size" : 10, "max_import_size": 50, "user_oauth_applications" : true, "updated_at" : "2016-01-04T15:44:55.176Z", "session_expire_delay" : 10080, "home_page_url" : null, "default_snippet_visibility" : "private", "outbound_local_requests_whitelist": [], "domain_whitelist" : [], "domain_blacklist_enabled" : false, "domain_blacklist" : [], "created_at" : "2016-01-04T15:44:55.176Z", "default_ci_config_path" : null, "default_project_visibility" : "private", "default_group_visibility" : "private", "gravatar_enabled" : true, "sign_in_text" : null, "container_expiration_policies_enable_historic_entries": true, "container_registry_token_expire_delay": 5, "repository_storages_weighted": {"default": 100}, "plantuml_enabled": false, "plantuml_url": null, "terminal_max_session_time": 0, "polling_interval_multiplier": 1.0, "rsa_key_restriction": 0, "dsa_key_restriction": 0, "ecdsa_key_restriction": 0, "ed25519_key_restriction": 0, "first_day_of_week": 0, "enforce_terms": true, "terms": "Hello world!", "performance_bar_allowed_group_id": 42, "instance_statistics_visibility_private": false, "user_show_add_ssh_key_message": true, "local_markdown_version": 0, "allow_local_requests_from_hooks_and_services": true, "allow_local_requests_from_web_hooks_and_services": true, "allow_local_requests_from_system_hooks": false, "asset_proxy_enabled": true, "asset_proxy_url": "https://assets.example.com", "asset_proxy_whitelist": ["example.com", "*.example.com", "your-instance.com"], "npm_package_requests_forwarding": true, "snippet_size_limit": 52428800, "issues_create_limit": 300, "raw_blob_request_limit": 300, "wiki_page_max_content_bytes": 52428800 } +``` + +在 GitLab 用户[高级版或旗舰](https://about.gitlab.com/pricing/)也可以看到`file_template_project_id` , `deletion_adjourned_period` ,或`geo_node_allowed_ips`参数: + +``` +{ "id" : 1, "signup_enabled" : true, "file_template_project_id": 1, "geo_node_allowed_ips": "0.0.0.0/0, ::/0", "deletion_adjourned_period": 7, ... } +``` + +## Change application settings[](#change-application-settings "Permalink") + +使用 API​​调用来修改 GitLab 实例[应用程序设置](#list-of-settings-that-can-be-accessed-via-api-calls) . + +``` +PUT /application/settings +``` + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/application/settings?signup_enabled=false&default_project_visibility=internal" +``` + +响应示例: + +``` +{ "id": 1, "default_projects_limit": 100000, "signup_enabled": false, "password_authentication_enabled_for_web": true, "gravatar_enabled": true, "sign_in_text": "", "created_at": "2015-06-12T15:51:55.432Z", "updated_at": "2015-06-30T13:22:42.210Z", "home_page_url": "", "default_branch_protection": 2, "restricted_visibility_levels": [], "max_attachment_size": 10, "max_import_size": 50, "session_expire_delay": 10080, "default_ci_config_path" : null, "default_project_visibility": "internal", "default_snippet_visibility": "private", "default_group_visibility": "private", "outbound_local_requests_whitelist": [], "domain_whitelist": [], "domain_blacklist_enabled" : false, "domain_blacklist" : [], "external_authorization_service_enabled": true, "external_authorization_service_url": "https://authorize.me", "external_authorization_service_default_label": "default", "external_authorization_service_timeout": 0.5, "user_oauth_applications": true, "after_sign_out_path": "", "container_registry_token_expire_delay": 5, "repository_storages": ["default"], "plantuml_enabled": false, "plantuml_url": null, "terminal_max_session_time": 0, "polling_interval_multiplier": 1.0, "rsa_key_restriction": 0, "dsa_key_restriction": 0, "ecdsa_key_restriction": 0, "ed25519_key_restriction": 0, "first_day_of_week": 0, "enforce_terms": true, "terms": "Hello world!", "performance_bar_allowed_group_id": 42, "instance_statistics_visibility_private": false, "user_show_add_ssh_key_message": true, "file_template_project_id": 1, "local_markdown_version": 0, "asset_proxy_enabled": true, "asset_proxy_url": "https://assets.example.com", "asset_proxy_whitelist": ["example.com", "*.example.com", "your-instance.com"], "geo_node_allowed_ips": "0.0.0.0/0, ::/0", "allow_local_requests_from_hooks_and_services": true, "allow_local_requests_from_web_hooks_and_services": true, "allow_local_requests_from_system_hooks": false, "npm_package_requests_forwarding": true, "snippet_size_limit": 52428800, "issues_create_limit": 300, "raw_blob_request_limit": 300, "wiki_page_max_content_bytes": 52428800 } +``` + +使用 GitLab [Premium 或 Ultimate 的](https://about.gitlab.com/pricing/)用户可能还会看到以下参数: + +* `file_template_project_id` +* `geo_node_allowed_ips` +* `geo_status_timeout` +* `deletion_adjourned_period` + +响应示例: + +``` + "file_template_project_id": 1, "geo_node_allowed_ips": "0.0.0.0/0, ::/0" +``` + +## List of settings that can be accessed via API calls[](#list-of-settings-that-can-be-accessed-via-api-calls "Permalink") + +通常,所有设置都是可选的. 但是,如果启用了某些设置,则需要设置其他设置才能正常运行. 这些要求在相关设置的说明中列出. + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `admin_notification_email` | string | no | 如果设置了滥用报告,它将发送到该地址. 滥用报告始终在管理区域中可用. | +| `after_sign_out_path` | string | no | 注销后将用户重定向到的位置. | +| `after_sign_up_text` | string | no | 注册后向用户显示的文字 | +| `akismet_api_key` | string | 要求: `akismet_enabled` | Akismet 垃圾邮件防护的 API 密钥. | +| `akismet_enabled` | boolean | no | ( **如果启用,则要求:** `akismet_api_key` )启用或禁用 Akismet 垃圾邮件防护. | +| `allow_group_owners_to_manage_ldap` | boolean | no | 设置为`true`以允许组所有者管理 LDAP | +| `allow_local_requests_from_hooks_and_services` | boolean | no | (不建议使用:改用`allow_local_requests_from_web_hooks_and_services` )允许从挂钩和服务到本地网络的请求. | +| `allow_local_requests_from_system_hooks` | boolean | no | 允许从系统挂钩向本地网络发出请求. | +| `allow_local_requests_from_web_hooks_and_services` | boolean | no | 允许从 Web 挂钩和服务到本地网络的请求. | +| `archive_builds_in_human_readable` | string | no | 设置将作业视为过期和过期的持续时间. 一旦超过该时间,作业将被存档,并且不再能够重试. 将其设为空以永不过期作业. 它必须不少于 1 天,例如: `15 days` , `1 month` , `2 years` . | +| `asset_proxy_enabled` | boolean | no | ( **如果启用,则要求:** `asset_proxy_url` )启用资产代理. 需要重启 GitLab 才能应用更改. | +| `asset_proxy_secret_key` | string | no | 与资产代理服务器共享的机密. 需要重启 GitLab 才能应用更改. | +| `asset_proxy_url` | string | no | 资产代理服务器的 URL. 需要重启 GitLab 才能应用更改. | +| `asset_proxy_whitelist` | 字符串或字符串数​​组 | no | 与这些域匹配的资产将不会被代理. 允许使用通配符. 您的 GitLab 安装网址会自动列入白名单. 需要重启 GitLab 才能应用更改. | +| `authorized_keys_enabled` | boolean | no | 默认情况下,我们无需经过其他配置即可写入`authorized_keys`文件以通过 SSH 支持 Git. 可以对 GitLab 进行优化,以通过数据库文件对 SSH 密钥进行身份验证. 仅当您已将 OpenSSH 服务器配置为使用 AuthorizedKeysCommand 时,才禁用此功能. | +| `auto_devops_domain` | string | no | 指定默认情况下用于每个项目的 Auto Review Apps 和 Auto Deploy 阶段的域. | +| `auto_devops_enabled` | boolean | no | 默认情况下,为项目启用 Auto DevOps. 它将基于预定义的 CI / CD 配置自动构建,测试和部署应用程序. | +| `check_namespace_plan` | boolean | no | 如果项目名称空间的计划包括该功能或项目为公共项目,则启用此选项将仅使许可的 EE 功能可用于项目. | +| `commit_email_hostname` | string | no | 自定义主机名(用于私人提交电子邮件). | +| `container_registry_token_expire_delay` | integer | no | 容器注册表令牌持续时间(以分钟为单位). | +| `default_artifacts_expire_in` | string | no | 设置每个作业的工件的默认到期时间. | +| `default_branch_protection` | integer | no | 确定开发者是否可以掌握. 可以采用: `0` *(不受保护,开发人员和维护人员都可以推送新的提交,强制推送或删除分支)* , `1` *(部分受保护的开发人员和维护人员可以推送新的提交,但是不能强制推送或删除分支)*或`2` *(受完全保护的开发人员无法推送新的提交,但维护者可以;没有人可以强制推送或删除分支)*作为参数. 默认值为`2` . | +| `default_ci_config_path` | string | no | 新项目的默认 CI 配置路径(如果未设置, `.gitlab-ci.yml` ). | +| `default_group_visibility` | string | no | 新群组获得的可见度级别. 可以将`private` , `internal`和`public`作为参数. 默认值为`private` . | +| `default_project_creation` | integer | no | 默认的项目创建保护. 可以采用: `0` *(无人)* , `1` *(维护者)*或`2` *(开发人员+维护者)* | +| `default_projects_limit` | integer | no | 每个用户的项目限制. 默认值为`100000` . | +| `default_project_visibility` | string | no | 新项目获得什么可见度级别. 可以将`private` , `internal`和`public`作为参数. 默认值为`private` . | +| `default_snippet_visibility` | string | no | 新摘要的可见性级别是多少. 可以将`private` , `internal`和`public`作为参数. 默认值为`private` . | +| `diff_max_patch_bytes` | integer | no | 最大差异补丁大小(字节). | +| `disabled_oauth_sign_in_sources` | 字符串数组 | no | 禁用的 OAuth 登录源. | +| `dns_rebinding_protection_enabled` | boolean | no | 实施 DNS 重新绑定攻击保护. | +| `domain_blacklist` | 字符串数组 | no | 电子邮件地址与这些域匹配的用户将无法注册. 允许使用通配符. 对多个条目使用单独的行. 例如: `domain.com` , `*.domain.com` . | +| `domain_blacklist_enabled` | boolean | no | ( **如果启用,则要求:** `domain_blacklist` )允许阻止来自特定域的电子邮件的注册. | +| `domain_whitelist` | 字符串数组 | no | 强迫人们仅使用公司电子邮件进行注册. 默认值为`null` ,表示没有限制. | +| `dsa_key_restriction` | integer | no | 上载 DSA 密钥的最小允许位长. 默认值为`0` (无限制). `-1`禁用 DSA 密钥. | +| `ecdsa_key_restriction` | integer | no | 上载的 ECDSA 密钥的最小允许曲线大小(以位为单位). 默认值为`0` (无限制). `-1`禁用 ECDSA 密钥. | +| `ed25519_key_restriction` | integer | no | 上载的 ED25519 密钥的最小允许曲线大小(以位为单位). 默认值为`0` (无限制). `-1`禁用 ED25519 键. | +| `eks_integration_enabled` | boolean | no | 启用与 Amazon EKS 的集成 | +| `eks_account_id` | string | no | 亚马逊帐号 | +| `eks_access_key_id` | string | no | AWS IAM 访问密钥 ID | +| `eks_secret_access_key` | string | no | AWS IAM 秘密访问密钥 | +| `elasticsearch_aws_access_key` | string | no | AWS IAM 访问密钥 | +| `elasticsearch_aws` | boolean | no | 启用使用 AWS 托管的 Elasticsearch | +| `elasticsearch_aws_region` | string | no | 配置 Elasticsearch 域的 AWS 区域 | +| `elasticsearch_aws_secret_access_key` | string | no | AWS IAM 秘密访问密钥 | +| `elasticsearch_indexed_field_length_limit` | integer | no | Elasticsearch 将索引的文本字段的最大大小. 0 值表示没有限制. 这不适用于存储库和 Wiki 索引. | +| `elasticsearch_indexing` | boolean | no | 启用 Elasticsearch 索引 | +| `elasticsearch_limit_indexing` | boolean | no | 限制 Elasticsearch 索引某些命名空间和项目 | +| `elasticsearch_max_bulk_concurrency` | integer | no | 每个索引操作的 Elasticsearch 批量请求的最大并发性. 这仅适用于存储库索引操作. | +| `elasticsearch_max_bulk_size_mb` | integer | no | Maximum size of Elasticsearch bulk indexing requests in MB. This only applies to repository indexing operations. | +| `elasticsearch_namespace_ids` | 整数数组 | no | 如果启用 elasticsearch_limit_indexing, `elasticsearch_limit_indexing`通过 Elasticsearch 进行索引的名称空间. | +| `elasticsearch_project_ids` | 整数数组 | no | 如果启用了 elasticsearch_limit_indexing, `elasticsearch_limit_indexing`通过 Elasticsearch 进行索引的项目. | +| `elasticsearch_search` | boolean | no | 启用 Elasticsearch 搜索 | +| `elasticsearch_url` | string | no | 用于连接到 Elasticsearch 的 URL. 使用逗号分隔的列表来支持集群(例如, `http://localhost:9200, http://localhost:9201"` ).如果您的 Elasticsearch 实例受密码保护,请在 URL 中传递`username:password` (例如, `http://:@:9200/` ). | +| `email_additional_text` | string | no | 出于法律/审核/合规原因,在每封电子邮件的底部添加了其他文本 | +| `email_author_in_body` | boolean | no | 某些电子邮件服务器不支持覆盖电子邮件发件人名称. 启用此选项可在邮件正文中包含问题作者的名称,合并请求或评论. | +| `enabled_git_access_protocol` | string | no | 已启用 Git 访问协议. 允许的值为: `ssh` , `http`和`nil`以允许两种协议. | +| `enforce_terms` | boolean | no | ( **如果启用,则要求:** `terms` )对所有用户强制应用 ToS. | +| `external_auth_client_cert` | string | no | ( **如果启用,则要求:** `external_auth_client_key` )用于与外部授权服务进行身份验证的证书 | +| `external_auth_client_key_pass` | string | no | 与外部服务进行身份验证时用于私钥的密码,存储时会加密 | +| `external_auth_client_key` | string | 要求: `external_auth_client_cert` | 外部授权服务需要身份验证时证书的私钥,存储时将被加密 | +| `external_authorization_service_default_label` | string | 所需者: `external_authorization_service_enabled` | 请求授权时使用的默认分类标签,并且在项目上未指定任何分类标签 | +| `external_authorization_service_enabled` | boolean | no | ( **如果启用,则要求:** `external_authorization_service_default_label` , `external_authorization_service_timeout`和`external_authorization_service_url` )启用使用外部授权服务访问项目 | +| `external_authorization_service_timeout` | float | 所需者: `external_authorization_service_enabled` | 授权请求终止后的超时时间(以秒为单位). 当请求超时时,将拒绝用户访问. (最小值:0.001,最大值:10,步长:0.001) | +| `external_authorization_service_url` | string | 所需者: `external_authorization_service_enabled` | 授权请求将定向到的 URL | +| `file_template_project_id` | integer | no | 从中加载自定义文件模板的项目的 ID | +| `first_day_of_week` | integer | no | 日历视图和日期选择器的星期几开始. 有效值为星期日( `0` (默认),星期一( `1` )和星期六( `6` . | +| `geo_node_allowed_ips` | string | yes | 允许的辅助节点的 IP 和 CIDR 的逗号分隔列表. 例如`1.1.1.1, 2.2.2.0/24` . | +| `geo_status_timeout` | integer | no | 请求获取辅助节点状态的超时时间(秒). | +| `gitaly_timeout_default` | integer | no | 默认 Gitaly 超时(以秒为单位). 对于 Git 提取/推送操作或 Sidekiq 作业,不会强制使用此超时. 设置为`0`以禁用超时. | +| `gitaly_timeout_fast` | integer | no | 快速运行超时,以秒为单位. 预计某些 Gitaly 行动会很快. 如果它们超过此阈值,则存储碎片可能存在问题,并且"快速失败"可以帮助维护 GitLab 实例的稳定性. 设置为`0`以禁用超时. | +| `gitaly_timeout_medium` | integer | no | Gitaly 中度超时,以秒为单位. 这应该是快速超时和默认超时之间的一个值. 设置为`0`以禁用超时. | +| `grafana_enabled` | boolean | no | 启用 Grafana. | +| `grafana_url` | string | no | Grafana URL. | +| `gravatar_enabled` | boolean | no | 启用 Gravatar. | +| `hashed_storage_enabled` | boolean | no | 使用哈希存储路径创建新项目:启用基于哈希的不可变路径和存储库名称,以将存储库存储在磁盘上. 这样可以避免在项目 URL 更改时必须移动或重命名存储库,并可以提高磁盘 I / O 性能. (从 13.0 开始始终启用,在 14.0 中将删除配置) | +| `help_page_hide_commercial_content` | boolean | no | 隐藏帮助中与营销相关的条目. | +| `help_page_support_url` | string | no | 帮助页面和帮助下拉列表的备用支持 URL. | +| `help_page_text` | string | no | 帮助页面上显示的自定义文本. | +| `help_text` | string | no | GitLab 服务器管理员信息 | +| `hide_third_party_offers` | boolean | no | 不要在 GitLab 中显示来自第三方的报价. | +| `home_page_url` | string | no | 未登录时重定向到该 URL. | +| `housekeeping_bitmaps_enabled` | boolean | 要求: `housekeeping_enabled` | 启用 Git 包文件位图创建. | +| `housekeeping_enabled` | boolean | no | ( **如果启用,则要求:** `housekeeping_bitmaps_enabled` , `housekeeping_full_repack_period` , `housekeeping_gc_period`和`housekeeping_incremental_repack_period` ).启用或禁用 Git 整理. | +| `housekeeping_full_repack_period` | integer | 要求: `housekeeping_enabled` | Git 推送的次数,之后运行增量`git repack` . | +| `housekeeping_gc_period` | integer | 要求: `housekeeping_enabled` | 运行`git gc`之后的 Git 推送次数. | +| `housekeeping_incremental_repack_period` | integer | 要求: `housekeeping_enabled` | Git 推送的次数,之后运行增量`git repack` . | +| `html_emails_enabled` | boolean | no | 启用 HTML 电子邮件. | +| `import_sources` | 字符串数组 | no | 允许从中导入项目的来源,可能的值包括: `github` , `bitbucket` , `bitbucket_server` , `gitlab` , `google_code` , `fogbugz` , `git` , `gitlab_project` , `gitea` , `manifest`和`phabricator` . | +| `instance_statistics_visibility_private` | boolean | no | 设置为`true`实例统计信息仅对管理员可用. | +| `local_markdown_version` | integer | no | 当任何缓存的 Markdown 无效时,请增加此值. | +| `max_artifacts_size` | integer | no | 最大工件大小(MB) | +| `max_attachment_size` | integer | no | 限制附件大小(MB) | +| `max_import_size` | integer | no | 最大导入大小(MB). 0 代表无限. 默认值= 50 | +| `max_pages_size` | integer | no | 页面存储库的最大大小(MB) | +| `max_personal_access_token_lifetime` | integer | no | 个人访问令牌的最大允许寿命(天) | +| `metrics_method_call_threshold` | integer | no | 仅当方法调用花费的时间超过给定的毫秒数时,才会跟踪该方法调用. | +| `mirror_available` | boolean | no | 允许存储库镜像由项目维护者配置. 如果禁用,则只有管理员可以配置存储库镜像. | +| `mirror_capacity_threshold` | integer | no | 抢先计划更多镜像之前需要提供的最小容量 | +| `mirror_max_capacity` | integer | no | 可以同时同步的最大镜像数. | +| `mirror_max_delay` | integer | no | 计划进行同步时,镜像可以具有的两次更新之间的最长时间(以分钟为单位). | +| `npm_package_requests_forwarding` | boolean | no | 在 GitLab NPM 注册表中找不到软件包时,请使用 npmjs.org 作为默认的远程存储库 | +| `maintenance_mode` | boolean | no | 实例处于维护模式时,非管理员用户可以使用只读访问权限登录并发出只读 API 请求 | +| `maintenance_mode_message` | string | no | 实例处于维护模式时显示的消息 | +| `outbound_local_requests_whitelist` | 字符串数组 | no | 定义在禁用对钩子和服务的本地请求时允许对本地请求的信任域或 ip 地址的列表. | +| `pages_domain_verification_enabled` | boolean | no | 要求用户证明自定义域的所有权. 域验证是公共 GitLab 站点必不可少的安全措施. 在启用域之前,要求用户证明他们控制着域. | +| `password_authentication_enabled_for_git` | boolean | no | 通过 GitLab 帐户密码启用基于 HTTP(S)的 Git 身份验证. 默认值为`true` . | +| `password_authentication_enabled_for_web` | boolean | no | 通过 GitLab 帐户密码启用 Web 界面的身份验证. 默认值为`true` . | +| `performance_bar_allowed_group_id` | string | no | (不建议使用:改用`performance_bar_allowed_group_path` )允许切换性能栏的组的路径. | +| `performance_bar_allowed_group_path` | string | no | Path of the group that is allowed to toggle the performance bar. | +| `performance_bar_enabled` | boolean | no | (不建议使用:传递`performance_bar_allowed_group_path: nil`代替)允许启用性能栏. | +| `plantuml_enabled` | boolean | no | ( **如果启用,则要求:** `plantuml_url` )启用 PlantUML 集成. 默认值为`false` . | +| `plantuml_url` | string | 要求: `plantuml_enabled` | 用于集成的 PlantUML 实例 URL. | +| `polling_interval_multiplier` | decimal | no | Interval multiplier used by endpoints that perform polling. Set to `0` to disable polling. | +| `deletion_adjourned_period` | integer | no | 删除标记为删除的项目或组之前要等待的天数. 值必须介于 0 到 90 之间. | +| `project_export_enabled` | boolean | no | 启用项目导出. | +| `prometheus_metrics_enabled` | boolean | no | 启用 Prometheus 指标. | +| `protected_ci_variables` | boolean | no | 默认情况下,环境变量受保护. | +| `pseudonymizer_enabled` | boolean | no | 启用后,GitLab 将运行一个后台作业,该作业将生成 GitLab 数据库的假名化 CSV,并将其上传到您配置的对象存储目录中. | +| `push_event_hooks_limit` | integer | no | 一次按下更改(分支或标签)的次数,以确定是否将触发 Webhook 和服务. 如果超过该值,则不会提交 Webhooks 和服务. | +| `push_event_activities_limit` | integer | no | 一次推送中更改(分支或标签)的数量,以确定将创建单个推送事件还是批量推送事件. [如果批量推送事件](../user/admin_area/settings/push_event_activities_limit.html)超过该值, [则会创建](../user/admin_area/settings/push_event_activities_limit.html)该[事件](../user/admin_area/settings/push_event_activities_limit.html) . | +| `recaptcha_enabled` | boolean | no | ( **如果启用,则要求:** `recaptcha_private_key`和`recaptcha_site_key` )启用 reCAPTCHA. | +| `recaptcha_private_key` | string | 要求: `recaptcha_enabled` | reCAPTCHA 的私钥. | +| `recaptcha_site_key` | string | 要求: `recaptcha_enabled` | reCAPTCHA 的站点密钥. | +| `receive_max_input_size` | integer | no | 最大推送大小(MB). | +| `repository_checks_enabled` | boolean | no | GitLab 将在所有项目和 Wiki 存储库中定期运行`git fsck` ,以查找静默磁盘损坏问题. | +| `repository_size_limit` | integer | no | 每个存储库的大小限制(MB) | +| `repository_storages` | 字符串数组 | no | (GitLab 13.0 和更早版本)已启用的存储路径的名称列表,取自`gitlab.yml` . 在这些商店之一中创建新项目,这些项目是随机选择的. | +| `repository_storages_weighted` | 字符串哈希到整数 | no | (GitLab 13.1 和更高版本)从`gitlab.yml`到权重的名称的哈希值. 在这些存储库之一中创建新项目,并通过加权随机选择进行选择. | +| `require_two_factor_authentication` | boolean | no | ( **如果启用,则要求:** `two_factor_grace_period` )要求所有用户设置两因素身份验证. | +| `restricted_visibility_levels` | 字符串数组 | no | 非管理员用户不能将所选级别用于组,项目或摘要. 可以将`private` , `internal`和`public`作为参数. 默认值为`null` ,表示没有限制. | +| `rsa_key_restriction` | integer | no | 上载 RSA 密钥的最小允许比特长度. 默认值为`0` (无限制). `-1`禁用 RSA 密钥. | +| `send_user_confirmation_email` | boolean | no | 在注册时发送确认电子邮件. | +| `session_expire_delay` | integer | no | 会话持续时间(以分钟为单位). 需要重启 GitLab 才能应用更改 | +| `shared_runners_enabled` | boolean | no | ( **如果启用,则要求:** `shared_runners_text`和`shared_runners_minutes` )为新项目启用共享运行器. | +| `shared_runners_minutes` | integer | 所需者: `shared_runners_enabled` | 设置组每月可以在共享运行者上使用的最大管道分钟数. | +| `shared_runners_text` | string | 所需者: `shared_runners_enabled` | 共享跑步者文字. | +| `signin_enabled` | string | no | (不建议使用:改为使用`password_authentication_enabled_for_web` )该标志指示是否为 Web 界面启用了密码认证. | +| `sign_in_text` | string | no | 登录页面上的文本. | +| `signup_enabled` | boolean | no | 启用注册. 默认值为`true` . | +| `slack_app_enabled` | boolean | no | ( **如果启用,则要求:** `slack_app_id` , `slack_app_secret`和`slack_app_secret` )启用 Slack 应用. | +| `slack_app_id` | string | 所需者: `slack_app_enabled` | The app ID of the Slack-app. | +| `slack_app_secret` | string | 所需者: `slack_app_enabled` | Slack-app 的应用程序秘诀. | +| `slack_app_verification_token` | string | 所需者: `slack_app_enabled` | Slack-app 的验证令牌. | +| `snowplow_collector_hostname` | string | 所需者: `snowplow_enabled` | 扫雪机收集器主机名. (例如, `snowplow.trx.gitlab.net` ) | +| `snowplow_cookie_domain` | string | no | Snowplow cookie 域. (例如, `.gitlab.com` ) | +| `snowplow_enabled` | boolean | no | 启用扫雪机跟踪. | +| `snowplow_app_id` | string | no | Snowplow 站点名称/应用程序 ID. (例如`gitlab` ) | +| `snowplow_iglu_registry_url` | string | no | Snowplow 基本 Iglu Schema 注册表 URL,用于自定义上下文和自我描述事件' | +| `sourcegraph_enabled` | boolean | no | 启用 S​​ourcegraph 集成. 默认值为`false` . **如果启用,则需要** `sourcegraph_url` . | +| `sourcegraph_url` | string | 要求: `sourcegraph_enabled` | 用于集成的 Sourcegraph 实例 URL. | +| `sourcegraph_public_only` | boolean | no | 阻止将 Sourcegraph 加载到私有和内部项目中. 默认值为`true` . | +| `spam_check_endpoint_enabled` | boolean | no | 通过外部 API 端点启用垃圾邮件检查. 默认值为`false` . | +| `spam_check_endpoint_url` | string | no | 外部垃圾邮件检查服务端点的 URL. | +| `terminal_max_session_time` | integer | no | Web 终端 websocket 连接的最长时间(以秒为单位). 设置为`0`表示无限时间. | +| `terms` | text | 要求: `enforce_terms` | ( **要求:** `enforce_terms` )ToS 的降价内容. | +| `throttle_authenticated_api_enabled` | boolean | no | ( **如果启用,则要求:** `throttle_authenticated_api_period_in_seconds`和`throttle_authenticated_api_requests_per_period` )启用经过身份验证的 API 请求速率限制. 帮助减少请求量(例如,来自爬虫或恶意机器人的请求量). | +| `throttle_authenticated_api_period_in_seconds` | integer | 所需者: `throttle_authenticated_api_enabled` _ 已验证`throttle_authenticated_api_enabled` | 限速时间(秒). | +| `throttle_authenticated_api_requests_per_period` | integer | 所需者: `throttle_authenticated_api_enabled` _ 已验证`throttle_authenticated_api_enabled` | 每个用户每个时段的最大请求数. | +| `throttle_authenticated_web_enabled` | boolean | no | ( **如果启用,则要求:** `throttle_authenticated_web_period_in_seconds`和`throttle_authenticated_web_requests_per_period` )启用经过身份验证的 Web 请求速率限制. 帮助减少请求量(例如,来自爬虫或恶意机器人的请求量). | +| `throttle_authenticated_web_period_in_seconds` | integer | 所需者: `throttle_authenticated_web_enabled` _ 已验证网络 _ 已`throttle_authenticated_web_enabled` | 限速时间(秒). | +| `throttle_authenticated_web_requests_per_period` | integer | 所需者: `throttle_authenticated_web_enabled` _ 已验证网络 _ 已`throttle_authenticated_web_enabled` | 每个用户每个时段的最大请求数. | +| `throttle_unauthenticated_enabled` | boolean | no | ( **如果启用,则要求:** `throttle_unauthenticated_period_in_seconds`和`throttle_unauthenticated_requests_per_period` )启用未认证的请求速率限制. 帮助减少请求量(例如,来自爬虫或恶意机器人的请求量). | +| `throttle_unauthenticated_period_in_seconds` | integer | 所需者: `throttle_unauthenticated_enabled` _ 未`throttle_unauthenticated_enabled`的 _ `throttle_unauthenticated_enabled` | 限速时间(秒). | +| `throttle_unauthenticated_requests_per_period` | integer | required by: `throttle_unauthenticated_enabled` | 每个 IP 的每个周期的最大请求数. | +| `time_tracking_limit_to_hours` | boolean | no | 将时间跟踪单位的显示限制为小时. 默认值为`false` . | +| `two_factor_grace_period` | integer | 要求者: `require_two_factor_authentication` | 允许用户跳过两因素身份验证的强制配置的时间(以小时为单位). | +| `unique_ips_limit_enabled` | boolean | no | ( **如果启用,则要求:** `unique_ips_limit_per_user`和`unique_ips_limit_time_window` )限制从多个`unique_ips_limit_time_window`登录. | +| `unique_ips_limit_per_user` | integer | 所需者: `unique_ips_limit_enabled` | 每个用户的最大 IP 数. | +| `unique_ips_limit_time_window` | integer | 所需者: `unique_ips_limit_enabled` | IP 将计入限制多少秒. | +| `usage_ping_enabled` | boolean | no | GitLab 每周都会向 GitLab,Inc.报告许可证使用情况. | +| `user_default_external` | boolean | no | 默认情况下,新注册的用户将是外部用户. | +| `user_default_internal_regex` | string | no | 指定电子邮件地址正则表达式模式以标识默认的内部用户. | +| `user_oauth_applications` | boolean | no | 允许用户注册任何应用程序以将 GitLab 用作 OAuth 提供程序. | +| `user_show_add_ssh_key_message` | boolean | no | 设置为`false`时,向没有上载 SSH 密钥的用户显示"您将无法通过 SSH 推送或推送项目代码"警告. | +| `version_check_enabled` | boolean | no | 让 GitLab 在更新可用时通知您. | +| `web_ide_clientside_preview_enabled` | boolean | no | 实时预览(允许使用 CodeSandbox 实时预览在 Web IDE 中对 JavaScript 项目进行实时预览). | +| `snippet_size_limit` | integer | no | 摘录内容的最大大小(以**字节为单位)** . 默认值:52428800 字节(50MB). | +| `issues_create_limit` | integer | no | 每位用户每分钟每分钟最多可创建问题的请求数. 默认值:300.要禁用限制,请将其设置为 0. | +| `raw_blob_request_limit` | integer | no | 每条原始路径每分钟的最大请求数. 默认值:300.要禁用限制,请将其设置为 0. | +| `wiki_page_max_content_bytes` | integer | no | Wiki 页面的最大内容大小(以**字节为单位)** . 默认值:52428800 字节(50MB). | \ No newline at end of file diff --git a/_book/docs/369.md b/_book/docs/369.md new file mode 100644 index 0000000000000000000000000000000000000000..d393a7c7f38e681c6eb176f6193288795d245f8b --- /dev/null +++ b/_book/docs/369.md @@ -0,0 +1,86 @@ +# Sidekiq Metrics API + +> 原文:[https://docs.gitlab.com/ee/api/sidekiq_metrics.html](https://docs.gitlab.com/ee/api/sidekiq_metrics.html) + +* [Get the current Queue Metrics](#get-the-current-queue-metrics) +* [Get the current Process Metrics](#get-the-current-process-metrics) +* [Get the current Job Statistics](#get-the-current-job-statistics) +* [Get a compound response of all the previously mentioned metrics](#get-a-compound-response-of-all-the-previously-mentioned-metrics) + +# Sidekiq Metrics API[](#sidekiq-metrics-api "Permalink") + +> **注意:**此端点仅在 GitLab 8.9 及更高版本上可用. + +通过此 API 端点,您可以检索有关 Sidekiq 当前状态,其作业,队列和进程的一些信息. + +## Get the current Queue Metrics[](#get-the-current-queue-metrics "Permalink") + +列出有关所有已注册队列,其积压和延迟的信息. + +``` +GET /sidekiq/queue_metrics +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/sidekiq/queue_metrics" +``` + +响应示例: + +``` +{ "queues": { "default": { "backlog": 0, "latency": 0 } } } +``` + +## Get the current Process Metrics[](#get-the-current-process-metrics "Permalink") + +列出有关所有注册来处理您的队列的 Sidekiq 工作者的信息. + +``` +GET /sidekiq/process_metrics +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/sidekiq/process_metrics" +``` + +响应示例: + +``` +{ "processes": [ { "hostname": "gitlab.example.com", "pid": 5649, "tag": "gitlab", "started_at": "2016-06-14T10:45:07.159-05:00", "queues": [ "post_receive", "mailers", "archive_repo", "system_hook", "project_web_hook", "gitlab_shell", "incoming_email", "runner", "common", "default" ], "labels": [], "concurrency": 25, "busy": 0 } ] } +``` + +## Get the current Job Statistics[](#get-the-current-job-statistics "Permalink") + +列出有关 Sidekiq 执行的作业的信息. + +``` +GET /sidekiq/job_stats +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/sidekiq/job_stats" +``` + +响应示例: + +``` +{ "jobs": { "processed": 2, "failed": 0, "enqueued": 0, "dead": 0 } } +``` + +## Get a compound response of all the previously mentioned metrics[](#get-a-compound-response-of-all-the-previously-mentioned-metrics "Permalink") + +列出有关 Sidekiq 的所有当前可用信息. + +``` +GET /sidekiq/compound_metrics +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/sidekiq/compound_metrics" +``` + +响应示例: + +``` +{ "queues": { "default": { "backlog": 0, "latency": 0 } }, "processes": [ { "hostname": "gitlab.example.com", "pid": 5649, "tag": "gitlab", "started_at": "2016-06-14T10:45:07.159-05:00", "queues": [ "post_receive", "mailers", "archive_repo", "system_hook", "project_web_hook", "gitlab_shell", "incoming_email", "runner", "common", "default" ], "labels": [], "concurrency": 25, "busy": 0 } ], "jobs": { "processed": 2, "failed": 0, "enqueued": 0, "dead": 0 } } +``` \ No newline at end of file diff --git a/_book/docs/370.md b/_book/docs/370.md new file mode 100644 index 0000000000000000000000000000000000000000..a302d7f9df61a3e42c47f816599198276316487b --- /dev/null +++ b/_book/docs/370.md @@ -0,0 +1,285 @@ +# Snippets API + +> 原文:[https://docs.gitlab.com/ee/api/snippets.html](https://docs.gitlab.com/ee/api/snippets.html) + +* [Snippet visibility level](#snippet-visibility-level) +* [List all snippets for a user](#list-all-snippets-for-a-user) +* [Get a single snippet](#get-a-single-snippet) +* [Single snippet contents](#single-snippet-contents) +* [Snippet repository file content](#snippet-repository-file-content) +* [Create new snippet](#create-new-snippet) +* [Update snippet](#update-snippet) +* [Delete snippet](#delete-snippet) +* [List all public snippets](#list-all-public-snippets) +* [Get user agent details](#get-user-agent-details) + +# Snippets API[](#snippets-api "Permalink") + +在 GitLab 8.15 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6373) . + +片段 API 在[片段上](../user/snippets.html)运行. + +## Snippet visibility level[](#snippet-visibility-level "Permalink") + +GitLab 中的代码段可以是私有的,内部的或公共的. 您可以使用代码段中的`visibility`字段进行设置. + +代码段可见性级别的有效值为: + +| Visibility | Description | +| --- | --- | +| `private` | 摘要仅对摘要创建者可见. | +| `internal` | 所有已登录用户都可以看到该代码段. | +| `public` | 无需任何身份验证即可访问代码段. | + +## List all snippets for a user[](#list-all-snippets-for-a-user "Permalink") + +获取当前用户的片段列表. + +``` +GET /snippets +``` + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets" +``` + +响应示例: + +``` +[ { "id": 42, "title": "Voluptatem iure ut qui aut et consequatur quaerat.", "file_name": "mclaughlin.rb", "description": null, "visibility": "internal", "author": { "id": 22, "name": "User 0", "username": "user0", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/52e4ce24a915fb7e51e1ad3b57f4b00a?s=80&d=identicon", "web_url": "http://example.com/user0" }, "updated_at": "2018-09-18T01:12:26.383Z", "created_at": "2018-09-18T01:12:26.383Z", "project_id": null, "web_url": "http://example.com/snippets/42", "raw_url": "http://example.com/snippets/42/raw" }, { "id": 41, "title": "Ut praesentium non et atque.", "file_name": "ondrickaemard.rb", "description": null, "visibility": "internal", "author": { "id": 22, "name": "User 0", "username": "user0", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/52e4ce24a915fb7e51e1ad3b57f4b00a?s=80&d=identicon", "web_url": "http://example.com/user0" }, "updated_at": "2018-09-18T01:12:26.360Z", "created_at": "2018-09-18T01:12:26.360Z", "project_id": 1, "web_url": "http://example.com/gitlab-org/gitlab-test/snippets/41", "raw_url": "http://example.com/gitlab-org/gitlab-test/snippets/41/raw" } ] +``` + +## Get a single snippet[](#get-a-single-snippet "Permalink") + +取得一个摘要. + +``` +GET /snippets/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要检索的代码段的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets/1" +``` + +响应示例: + +``` +{ "id": 1, "title": "test", "file_name": "add.rb", "description": "Ruby test snippet", "visibility": "private", "author": { "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "created_at": "2012-05-23T08:00:58Z" }, "expires_at": null, "updated_at": "2012-06-28T10:52:04Z", "created_at": "2012-06-28T10:52:04Z", "project_id": null, "web_url": "http://example.com/snippets/1", "raw_url": "http://example.com/snippets/1/raw" } +``` + +## Single snippet contents[](#single-snippet-contents "Permalink") + +获取单个代码段的原始内容. + +``` +GET /snippets/:id/raw +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要检索的代码段的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets/1/raw" +``` + +响应示例: + +``` +Hello World snippet +``` + +## Snippet repository file content[](#snippet-repository-file-content "Permalink") + +以纯文本形式返回原始文件的内容. + +``` +GET /snippets/:id/files/:ref/:file_path/raw +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要检索的代码段 ID | +| `ref` | string | yes | 引用标签,分支或提交 | +| `file_path` | string | yes | 文件的 URL 编码路径 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets/1/files/master/snippet%2Erb/raw" +``` + +响应示例: + +``` +Hello World snippet +``` + +## Create new snippet[](#create-new-snippet "Permalink") + +创建一个新的代码段. + +**注意:**用户必须具有创建新代码段的权限. + +``` +POST /snippets +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `title` | string | yes | 摘要的标题. | +| `file_name` | string | yes | 片段文件的名称. | +| `content` | string | yes | 摘要的内容. | +| `description` | string | no | 片段说明. | +| `visibility` | string | no | Snippet’s [visibility](#snippet-visibility-level). | + +请求示例: + +``` +curl --request POST \ + --data '{"title": "This is a snippet", "content": "Hello world", "description": "Hello World snippet", "file_name": "test.txt", "visibility": "internal" }' \ + --header 'Content-Type: application/json' \ + --header "PRIVATE-TOKEN: " \ + "https://gitlab.example.com/api/v4/snippets" +``` + +响应示例: + +``` +{ "id": 1, "title": "This is a snippet", "file_name": "test.txt", "description": "Hello World snippet", "visibility": "internal", "author": { "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "created_at": "2012-05-23T08:00:58Z" }, "expires_at": null, "updated_at": "2012-06-28T10:52:04Z", "created_at": "2012-06-28T10:52:04Z", "project_id": null, "web_url": "http://example.com/snippets/1", "raw_url": "http://example.com/snippets/1/raw" } +``` + +## Update snippet[](#update-snippet "Permalink") + +更新现有代码段. + +**注意:**用户必须具有更改现有代码段的权限. + +``` +PUT /snippets/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要更新的代码段 ID. | +| `title` | string | no | 摘要的标题. | +| `file_name` | string | no | 片段文件的名称. | +| `description` | string | no | 片段说明. | +| `content` | string | no | 摘要的内容. | +| `visibility` | string | no | Snippet’s [visibility](#snippet-visibility-level). | + +请求示例: + +``` +curl --request PUT \ + --data '{"title": "foo", "content": "bar"}' \ + --header 'Content-Type: application/json' \ + --header "PRIVATE-TOKEN: " \ + "https://gitlab.example.com/api/v4/snippets/1" +``` + +响应示例: + +``` +{ "id": 1, "title": "test", "file_name": "add.rb", "description": "description of snippet", "visibility": "internal", "author": { "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "created_at": "2012-05-23T08:00:58Z" }, "expires_at": null, "updated_at": "2012-06-28T10:52:04Z", "created_at": "2012-06-28T10:52:04Z", "project_id": null, "web_url": "http://example.com/snippets/1", "raw_url": "http://example.com/snippets/1/raw" } +``` + +## Delete snippet[](#delete-snippet "Permalink") + +删除现有的代码段. + +``` +DELETE /snippets/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要删除的代码段的 ID. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets/1" +``` + +以下是可能的返回码: + +| Code | Description | +| --- | --- | +| `204` | 删除成功. 没有数据返回. | +| `404` | 找不到该代码段. | + +## List all public snippets[](#list-all-public-snippets "Permalink") + +列出所有公共摘要. + +``` +GET /snippets/public +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `per_page` | integer | no | 每页要返回的代码段数. | +| `page` | integer | no | 要检索的页面. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets/public?per_page=2&page=1" +``` + +响应示例: + +``` +[ { "author": { "avatar_url": "http://www.gravatar.com/avatar/edaf55a9e363ea263e3b981d09e0f7f7?s=80&d=identicon", "id": 12, "name": "Libby Rolfson", "state": "active", "username": "elton_wehner", "web_url": "http://example.com/elton_wehner" }, "created_at": "2016-11-25T16:53:34.504Z", "file_name": "oconnerrice.rb", "id": 49, "title": "Ratione cupiditate et laborum temporibus.", "updated_at": "2016-11-25T16:53:34.504Z", "project_id": null, "web_url": "http://example.com/snippets/49", "raw_url": "http://example.com/snippets/49/raw" }, { "author": { "avatar_url": "http://www.gravatar.com/avatar/36583b28626de71061e6e5a77972c3bd?s=80&d=identicon", "id": 16, "name": "Llewellyn Flatley", "state": "active", "username": "adaline", "web_url": "http://example.com/adaline" }, "created_at": "2016-11-25T16:53:34.479Z", "file_name": "muellershields.rb", "id": 48, "title": "Minus similique nesciunt vel fugiat qui ullam sunt.", "updated_at": "2016-11-25T16:53:34.479Z", "project_id": null, "web_url": "http://example.com/snippets/48", "raw_url": "http://example.com/snippets/49/raw", "visibility": "public" } ] +``` + +## Get user agent details[](#get-user-agent-details "Permalink") + +在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12655) . + +**注意:**仅适用于管理员. + +``` +GET /snippets/:id/user_agent_detail +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 摘要的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets/1/user_agent_detail" +``` + +响应示例: + +``` +{ "user_agent": "AppleWebKit/537.36", "ip_address": "127.0.0.1", "akismet_submitted": false } +``` \ No newline at end of file diff --git a/_book/docs/371.md b/_book/docs/371.md new file mode 100644 index 0000000000000000000000000000000000000000..5b493ac8262fd4dbc96d63b157e2ea2ab0bd9ac1 --- /dev/null +++ b/_book/docs/371.md @@ -0,0 +1,212 @@ +# Project snippets + +> 原文:[https://docs.gitlab.com/ee/api/project_snippets.html](https://docs.gitlab.com/ee/api/project_snippets.html) + +* [Snippet visibility level](#snippet-visibility-level) +* [List snippets](#list-snippets) +* [Single snippet](#single-snippet) +* [Create new snippet](#create-new-snippet) +* [Update snippet](#update-snippet) +* [Delete snippet](#delete-snippet) +* [Snippet content](#snippet-content) +* [Snippet repository file content](#snippet-repository-file-content) +* [Get user agent details](#get-user-agent-details) + +# Project snippets[](#project-snippets "Permalink") + +## Snippet visibility level[](#snippet-visibility-level "Permalink") + +GitLab 中的片段可以是私有的,内部的或公共的. 您可以使用代码段中的`visibility`字段进行设置. + +摘要可见性级别的常量为: + +| visibility | Description | +| --- | --- | +| `private` | 该代码段仅在代码段创建者中可见 | +| `internal` | 所有已登录的用户都可以看到该代码段 | +| `public` | 无需任何身份验证即可访问该代码段 | + +**注意:**从 2019 年 7 月开始,GitLab.com 上的新项目,组和摘要的`` `Internal`可见性''设置被禁用. 使用" `Internal`可见性"设置的现有项目,组和摘录保留此设置. 您可以在[相关问题中](https://gitlab.com/gitlab-org/gitlab/-/issues/12388)阅读有关更改的更多信息. + +## List snippets[](#list-snippets "Permalink") + +获取项目摘要列表. + +``` +GET /projects/:id/snippets +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) + +## Single snippet[](#single-snippet "Permalink") + +获得一个项目片段. + +``` +GET /projects/:id/snippets/:snippet_id +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-项目代码段的 ID + +``` +{ "id": 1, "title": "test", "file_name": "add.rb", "description": "Ruby test snippet", "author": { "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "created_at": "2012-05-23T08:00:58Z" }, "updated_at": "2012-06-28T10:52:04Z", "created_at": "2012-06-28T10:52:04Z", "project_id": 1, "web_url": "http://example.com/example/example/snippets/1", "raw_url": "http://example.com/example/example/snippets/1/raw" } +``` + +## Create new snippet[](#create-new-snippet "Permalink") + +创建一个新的项目片段. 用户必须具有创建新代码段的权限. + +``` +POST /projects/:id/snippets +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `title` (required) - The title of a snippet +* `file_name` (必填)-代码段文件的名称 +* `description` (可选)-代码段的说明 +* `content` (必填)-代码段的内容 +* `visibility` (必填)-代码段的可见性 + +请求示例: + +``` +curl --request POST "https://gitlab.com/api/v4/projects/:id/snippets" \ + --header "PRIVATE-TOKEN: " \ + --header "Content-Type: application/json" \ + -d @snippet.json +``` + +上面的示例请求中使用的`snippet.json` : + +``` +{ "title" : "Example Snippet Title", "description" : "More verbose snippet description", "file_name" : "example.txt", "content" : "source code \n with multiple lines\n", "visibility" : "private" } +``` + +## Update snippet[](#update-snippet "Permalink") + +更新现有的项目代码段. 用户必须具有更改现有代码段的权限. + +``` +PUT /projects/:id/snippets/:snippet_id +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-项目代码段的 ID +* `title` (可选)-摘要的标题 +* `file_name` (可选)-代码段文件的名称 +* `description` (可选)-代码段的说明 +* `content` (可选)-代码段的内容 +* `visibility` (可选)-代码段的可见性 + +请求示例: + +``` +curl --request PUT "https://gitlab.com/api/v4/projects/:id/snippets/:snippet_id" \ + --header "PRIVATE-TOKEN: " \ + --header "Content-Type: application/json" \ + -d @snippet.json +``` + +上面的示例请求中使用的`snippet.json` : + +``` +{ "title" : "Updated Snippet Title", "description" : "More verbose snippet description", "file_name" : "new_filename.txt", "content" : "updated source code \n with multiple lines\n", "visibility" : "private" } +``` + +## Delete snippet[](#delete-snippet "Permalink") + +删除现有项目片段. 如果操作成功,则返回`204 No Content`状态代码;如果找不到资源,则返回`404` . + +``` +DELETE /projects/:id/snippets/:snippet_id +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-项目代码段的 ID + +请求示例: + +``` +curl --request DELETE "https://gitlab.com/api/v4/projects/:id/snippets/:snippet_id" \ + --header "PRIVATE-TOKEN: " +``` + +## Snippet content[](#snippet-content "Permalink") + +以纯文本形式返回原始项目代码段. + +``` +GET /projects/:id/snippets/:snippet_id/raw +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-项目代码段的 ID + +请求示例: + +``` +curl "https://gitlab.com/api/v4/projects/:id/snippets/:snippet_id/raw" \ + --header "PRIVATE-TOKEN: " +``` + +## Snippet repository file content[](#snippet-repository-file-content "Permalink") + +以纯文本形式返回原始文件的内容. + +``` +GET /projects/:id/snippets/:snippet_id/files/:ref/:file_path/raw +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-项目代码段的 ID +* `ref` (必填)-分支,标记或提交的名称,例如 master +* `file_path` (必填)-文件的 URL 编码路径,例如 snippet%2Erb + +请求示例: + +``` +curl "https://gitlab.com/api/v4/projects/1/snippets/2/files/master/snippet%2Erb/raw" \ + --header "PRIVATE-TOKEN: " +``` + +## Get user agent details[](#get-user-agent-details "Permalink") + +在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29508) . + +仅适用于管理员. + +``` +GET /projects/:id/snippets/:snippet_id/user_agent_detail +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | Integer | yes | 项目 ID | +| `snippet_id` | Integer | yes | 片段的 ID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/snippets/2/user_agent_detail" +``` + +响应示例: + +``` +{ "user_agent": "AppleWebKit/537.36", "ip_address": "127.0.0.1", "akismet_submitted": false } +``` \ No newline at end of file diff --git a/_book/docs/372.md b/_book/docs/372.md new file mode 100644 index 0000000000000000000000000000000000000000..1d2c9f9ed88f0c7e336b4aa8298fa7dfa70f6aaa --- /dev/null +++ b/_book/docs/372.md @@ -0,0 +1,27 @@ +# Application statistics API + +> 原文:[https://docs.gitlab.com/ee/api/statistics.html](https://docs.gitlab.com/ee/api/statistics.html) + +* [Get current application statistics](#get-current-application-statistics) + +# Application statistics API[](#application-statistics-api "Permalink") + +## Get current application statistics[](#get-current-application-statistics "Permalink") + +列出 GitLab 实例的当前统计信息. 您必须是管理员才能执行此操作. + +**注意:**这些统计数据是近似的. + +``` +GET /application/statistics +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/application/statistics" +``` + +响应示例: + +``` +{ "forks": "10", "issues": "76", "merge_requests": "27", "notes": "954", "snippets": "50", "ssh_keys": "10", "milestones": "40", "users": "50", "groups": "10", "projects": "20", "active_users": "50" } +``` \ No newline at end of file diff --git a/_book/docs/373.md b/_book/docs/373.md new file mode 100644 index 0000000000000000000000000000000000000000..e40ea7e2a620d119f42ce42c5ca752ed5a0e629d --- /dev/null +++ b/_book/docs/373.md @@ -0,0 +1,31 @@ +# Suggest Changes API + +> 原文:[https://docs.gitlab.com/ee/api/suggestions.html](https://docs.gitlab.com/ee/api/suggestions.html) + +* [Applying suggestions](#applying-suggestions) + +# Suggest Changes API[](#suggest-changes-api "Permalink") + +每个对建议的 API 调用都必须经过验证. + +## Applying suggestions[](#applying-suggestions "Permalink") + +在合并请求中应用建议的补丁. 用户必须至少是[Developer](../user/permissions.html)才能执行此操作. + +``` +PUT /suggestions/:id/apply +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 建议的 ID | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/suggestions/5/apply" +``` + +响应示例: + +``` + { "id": 36, "from_line": 10, "to_line": 10, "appliable": false, "applied": true, "from_content": " \"--talk-name=org.freedesktop.\",\n", "to_content": " \"--talk-name=org.free.\",\n \"--talk-name=org.desktop.\",\n" } +``` \ No newline at end of file diff --git a/_book/docs/374.md b/_book/docs/374.md new file mode 100644 index 0000000000000000000000000000000000000000..2a673adcc7e18658d75fcc7ee09e17659cc7561e --- /dev/null +++ b/_book/docs/374.md @@ -0,0 +1,106 @@ +# System hooks API + +> 原文:[https://docs.gitlab.com/ee/api/system_hooks.html](https://docs.gitlab.com/ee/api/system_hooks.html) + +* [List system hooks](#list-system-hooks) +* [Add new system hook](#add-new-system-hook) +* [Test system hook](#test-system-hook) +* [Delete system hook](#delete-system-hook) + +# System hooks API[](#system-hooks-api "Permalink") + +所有方法都需要管理员授权. + +也可以使用**Admin Area> System Hooks** ( `/admin/hooks` )中的 UI 来配置系统挂钩的 URL 端点. + +阅读有关[系统挂钩的](../system_hooks/system_hooks.html)更多信息. + +## List system hooks[](#list-system-hooks "Permalink") + +获取所有系统挂钩的列表. + +``` +GET /hooks +``` + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/hooks" +``` + +响应示例: + +``` +[ { "id":1, "url":"https://gitlab.example.com/hook", "created_at":"2016-10-31T12:32:15.192Z", "push_events":true, "tag_push_events":false, "merge_requests_events": true, "repository_update_events": true, "enable_ssl_verification":true } ] +``` + +## Add new system hook[](#add-new-system-hook "Permalink") + +添加一个新的系统挂钩. + +``` +POST /hooks +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `url` | string | yes | 挂钩网址 | +| `token` | string | no | 用于验证收到的有效载荷的秘密令牌; 这将不会在响应中返回 | +| `push_events` | boolean | no | 设置为 true 时,挂钩将在推送事件时触发 | +| `tag_push_events` | boolean | no | 设置为 true 时,挂钩将在被推送的新标签上触发 | +| `merge_requests_events` | boolean | no | 触发合并请求事件的钩子 | +| `repository_update_events` | boolean | no | 触发挂钩存储库更新事件 | +| `enable_ssl_verification` | boolean | no | 触发挂钩时执行 SSL 验证 | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/hooks?url=https://gitlab.example.com/hook" +``` + +响应示例: + +``` +[ { "id":1, "url":"https://gitlab.example.com/hook", "created_at":"2016-10-31T12:32:15.192Z", "push_events":true, "tag_push_events":false, "merge_requests_events": true, "repository_update_events": true, "enable_ssl_verification":true } ] +``` + +## Test system hook[](#test-system-hook "Permalink") + +``` +GET /hooks/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 钩子的 ID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/hooks/2" +``` + +响应示例: + +``` +{ "project_id" : 1, "owner_email" : "example@gitlabhq.com", "owner_name" : "Someone", "name" : "Ruby", "path" : "ruby", "event_name" : "project_create" } +``` + +## Delete system hook[](#delete-system-hook "Permalink") + +删除系统挂钩. + +``` +DELETE /hooks/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 钩子的 ID | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/hooks/2" +``` \ No newline at end of file diff --git a/_book/docs/375.md b/_book/docs/375.md new file mode 100644 index 0000000000000000000000000000000000000000..16e6ccc3f9f47c1feb69f425f172e9cdcc5f70d3 --- /dev/null +++ b/_book/docs/375.md @@ -0,0 +1,159 @@ +# Tags API + +> 原文:[https://docs.gitlab.com/ee/api/tags.html](https://docs.gitlab.com/ee/api/tags.html) + +* [List project repository tags](#list-project-repository-tags) +* [Get a single repository tag](#get-a-single-repository-tag) +* [Create a new tag](#create-a-new-tag) +* [Delete a tag](#delete-a-tag) +* [Create a new release](#create-a-new-release) +* [Update a release](#update-a-release) + +# Tags API[](#tags-api "Permalink") + +## List project repository tags[](#list-project-repository-tags "Permalink") + +从项目中获取存储库标签的列表,按名称以相反的字母顺序排序. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/tags +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `order_by` | string | no | 返回按`name`或`updated`字段排序的标签. 默认值已`updated` | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的标签. 默认为`desc` | +| `search` | string | no | 返回符合搜索条件的标签列表. 您可以使用`^term`和`term$`查找分别以`term`开头和结尾的标签. | + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54401)了对`search`支持. + +``` +[ { "commit": { "id": "2695effb5807a22ff3d138d593fd856244e155e7", "short_id": "2695effb", "title": "Initial commit", "created_at": "2017-07-26T11:08:53.000+02:00", "parent_ids": [ "2a4b78934375d7f53875269ffd4f45fd83a84ebe" ], "message": "Initial commit", "author_name": "John Smith", "author_email": "john@example.com", "authored_date": "2012-05-28T04:42:42-07:00", "committer_name": "Jack Smith", "committer_email": "jack@example.com", "committed_date": "2012-05-28T04:42:42-07:00" }, "release": { "tag_name": "1.0.0", "description": "Amazing release. Wow" }, "name": "v1.0.0", "target": "2695effb5807a22ff3d138d593fd856244e155e7", "message": null, "protected": true } ] +``` + +## Get a single repository tag[](#get-a-single-repository-tag "Permalink") + +获取由其名称确定的特定存储库标签. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/tags/:tag_name +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `tag_name` | string | yes | 标签名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/tags/v1.0.0" +``` + +示例响应: + +``` +{ "name": "v5.0.0", "message": null, "target": "60a8ff033665e1207714d6670fcd7b65304ec02f", "commit": { "id": "60a8ff033665e1207714d6670fcd7b65304ec02f", "short_id": "60a8ff03", "title": "Initial commit", "created_at": "2017-07-26T11:08:53.000+02:00", "parent_ids": [ "f61c062ff8bcbdb00e0a1b3317a91aed6ceee06b" ], "message": "v5.0.0\n", "author_name": "Arthur Verschaeve", "author_email": "contact@arthurverschaeve.be", "authored_date": "2015-02-01T21:56:31.000+01:00", "committer_name": "Arthur Verschaeve", "committer_email": "contact@arthurverschaeve.be", "committed_date": "2015-02-01T21:56:31.000+01:00" }, "release": null, "protected": false } +``` + +## Create a new tag[](#create-a-new-tag "Permalink") + +在存储库中创建一个新标签,该标签指向提供的参考. + +``` +POST /projects/:id/repository/tags +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `tag_name` (必需)-标签的名称 +* `ref` (必需)-使用提交 SHA,另一个标签名称或分支名称创建标签. +* `message` (可选)-创建带注释的标签. +* `release_description` (可选)-将发行说明添加到 Git 标签并将其存储在 GitLab 数据库中. + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/tags?tag_name=test&ref=master" +``` + +响应示例: + +``` +{ "commit": { "id": "2695effb5807a22ff3d138d593fd856244e155e7", "short_id": "2695effb", "title": "Initial commit", "created_at": "2017-07-26T11:08:53.000+02:00", "parent_ids": [ "2a4b78934375d7f53875269ffd4f45fd83a84ebe" ], "message": "Initial commit", "author_name": "John Smith", "author_email": "john@example.com", "authored_date": "2012-05-28T04:42:42-07:00", "committer_name": "Jack Smith", "committer_email": "jack@example.com", "committed_date": "2012-05-28T04:42:42-07:00" }, "release": { "tag_name": "1.0.0", "description": "Amazing release. Wow" }, "name": "v1.0.0", "target": "2695effb5807a22ff3d138d593fd856244e155e7", "message": null, "protected": false } +``` + +创建轻量级标签时,该消息将为`null` ,否则将包含注释. + +在创建带注释的标签时,目标将包含标签对象 ID,否则在创建轻量级标签时将包含提交 ID. + +如果出现错误,则返回带有解释性错误消息的状态代码`405` . + +## Delete a tag[](#delete-a-tag "Permalink") + +删除具有给定名称的存储库的标记. + +``` +DELETE /projects/:id/repository/tags/:tag_name +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `tag_name` (必需)-标签的名称 + +## Create a new release[](#create-a-new-release "Permalink") + +将发行说明添加到现有的 Git 标签. 如果给定标签已经存在发行版,则返回状态码`409` . + +``` +POST /projects/:id/repository/tags/:tag_name/release +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `tag_name` (必需)-标签的名称 + +要求正文: + +* `description` (必需)-具有 Markdown 支持的发行说明 + +``` +{ "description": "Amazing release. Wow" } +``` + +Response: + +``` +{ "tag_name": "1.0.0", "description": "Amazing release. Wow" } +``` + +## Update a release[](#update-a-release "Permalink") + +更新给定发行版的发行说明. + +``` +PUT /projects/:id/repository/tags/:tag_name/release +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `tag_name` (必需)-标签的名称 + +要求正文: + +* `description` (必需)-具有 Markdown 支持的发行说明 + +``` +{ "description": "Amazing release. Wow" } +``` + +Response: + +``` +{ "tag_name": "1.0.0", "description": "Amazing release. Wow" } +``` \ No newline at end of file diff --git a/_book/docs/376.md b/_book/docs/376.md new file mode 100644 index 0000000000000000000000000000000000000000..02548615c7b9cc0f3f651e360ef8adee9c1d9bd2 --- /dev/null +++ b/_book/docs/376.md @@ -0,0 +1,76 @@ +# Todos API + +> 原文:[https://docs.gitlab.com/ee/api/todos.html](https://docs.gitlab.com/ee/api/todos.html) + +* [Get a list of todos](#get-a-list-of-todos) +* [Mark a todo as done](#mark-a-todo-as-done) +* [Mark all todos as done](#mark-all-todos-as-done) + +# Todos API[](#todos-api "Permalink") + +在 GitLab 8.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3188) . + +## Get a list of todos[](#get-a-list-of-todos "Permalink") + +返回待办事项列表. 如果未应用任何过滤器,它将返回当前用户的所有待处理的待办事项. 不同的过滤器使用户可以精确地处理请求. + +``` +GET /todos +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `action` | string | no | 要过滤的动作. 可以`assigned` , `mentioned` , `build_failed` , `marked` , `approval_required` , `unmergeable`或`directly_addressed` `unmergeable` . | +| `author_id` | integer | no | 作者的 ID | +| `project_id` | integer | no | 项目 ID | +| `group_id` | integer | no | 组的 ID | +| `state` | string | no | 待办事项的状态. 可以`pending`或`done` | +| `type` | string | no | 待办事项的类型. 可以是`Issue`或`MergeRequest` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/todos" +``` + +示例响应: + +``` +[ { "id": 102, "project": { "id": 2, "name": "Gitlab Ce", "name_with_namespace": "Gitlab Org / Gitlab Ce", "path": "gitlab-foss", "path_with_namespace": "gitlab-org/gitlab-foss" }, "author": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "action_name": "marked", "target_type": "MergeRequest", "target": { "id": 34, "iid": 7, "project_id": 2, "title": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", "description": "Et ea et omnis illum cupiditate. Dolor aspernatur tenetur ducimus facilis est nihil. Quo esse cupiditate molestiae illo corrupti qui quidem dolor.", "state": "opened", "created_at": "2016-06-17T07:49:24.419Z", "updated_at": "2016-06-17T07:52:43.484Z", "target_branch": "tutorials_git_tricks", "source_branch": "DNSBL_docs", "upvotes": 0, "downvotes": 0, "author": { "name": "Maxie Medhurst", "username": "craig_rutherford", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", "web_url": "https://gitlab.example.com/craig_rutherford" }, "assignee": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "source_project_id": 2, "target_project_id": 2, "labels": [], "work_in_progress": false, "milestone": { "id": 32, "iid": 2, "project_id": 2, "title": "v1.0", "description": "Assumenda placeat ea voluptatem voluptate qui.", "state": "active", "created_at": "2016-06-17T07:47:34.163Z", "updated_at": "2016-06-17T07:47:34.163Z", "due_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "cannot_be_merged", "subscribed": true, "user_notes_count": 7 }, "target_url": "https://gitlab.example.com/gitlab-org/gitlab-foss/-/merge_requests/7", "body": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", "state": "pending", "created_at": "2016-06-17T07:52:35.225Z", "updated_at": "2016-06-17T07:52:35.225Z" }, { "id": 98, "project": { "id": 2, "name": "Gitlab Ce", "name_with_namespace": "Gitlab Org / Gitlab Ce", "path": "gitlab-foss", "path_with_namespace": "gitlab-org/gitlab-foss" }, "author": { "name": "Maxie Medhurst", "username": "craig_rutherford", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", "web_url": "https://gitlab.example.com/craig_rutherford" }, "action_name": "assigned", "target_type": "MergeRequest", "target": { "id": 34, "iid": 7, "project_id": 2, "title": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", "description": "Et ea et omnis illum cupiditate. Dolor aspernatur tenetur ducimus facilis est nihil. Quo esse cupiditate molestiae illo corrupti qui quidem dolor.", "state": "opened", "created_at": "2016-06-17T07:49:24.419Z", "updated_at": "2016-06-17T07:52:43.484Z", "target_branch": "tutorials_git_tricks", "source_branch": "DNSBL_docs", "upvotes": 0, "downvotes": 0, "author": { "name": "Maxie Medhurst", "username": "craig_rutherford", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", "web_url": "https://gitlab.example.com/craig_rutherford" }, "assignee": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "source_project_id": 2, "target_project_id": 2, "labels": [], "work_in_progress": false, "milestone": { "id": 32, "iid": 2, "project_id": 2, "title": "v1.0", "description": "Assumenda placeat ea voluptatem voluptate qui.", "state": "active", "created_at": "2016-06-17T07:47:34.163Z", "updated_at": "2016-06-17T07:47:34.163Z", "due_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "cannot_be_merged", "subscribed": true, "user_notes_count": 7 }, "target_url": "https://gitlab.example.com/gitlab-org/gitlab-foss/-/merge_requests/7", "body": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", "state": "pending", "created_at": "2016-06-17T07:49:24.624Z", "updated_at": "2016-06-17T07:49:24.624Z" } ] +``` + +## Mark a todo as done[](#mark-a-todo-as-done "Permalink") + +将其 ID 给当前用户的单个待处理待办事项标记为已完成. 标记为已完成的待办事项在响应中返回. + +``` +POST /todos/:id/mark_as_done +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 待办事项编号 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/todos/130/mark_as_done" +``` + +示例响应: + +``` +{ "id": 102, "project": { "id": 2, "name": "Gitlab Ce", "name_with_namespace": "Gitlab Org / Gitlab Ce", "path": "gitlab-foss", "path_with_namespace": "gitlab-org/gitlab-foss" }, "author": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "action_name": "marked", "target_type": "MergeRequest", "target": { "id": 34, "iid": 7, "project_id": 2, "title": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", "description": "Et ea et omnis illum cupiditate. Dolor aspernatur tenetur ducimus facilis est nihil. Quo esse cupiditate molestiae illo corrupti qui quidem dolor.", "state": "opened", "created_at": "2016-06-17T07:49:24.419Z", "updated_at": "2016-06-17T07:52:43.484Z", "target_branch": "tutorials_git_tricks", "source_branch": "DNSBL_docs", "upvotes": 0, "downvotes": 0, "author": { "name": "Maxie Medhurst", "username": "craig_rutherford", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", "web_url": "https://gitlab.example.com/craig_rutherford" }, "assignee": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "source_project_id": 2, "target_project_id": 2, "labels": [], "work_in_progress": false, "milestone": { "id": 32, "iid": 2, "project_id": 2, "title": "v1.0", "description": "Assumenda placeat ea voluptatem voluptate qui.", "state": "active", "created_at": "2016-06-17T07:47:34.163Z", "updated_at": "2016-06-17T07:47:34.163Z", "due_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "cannot_be_merged", "subscribed": true, "user_notes_count": 7 }, "target_url": "https://gitlab.example.com/gitlab-org/gitlab-foss/-/merge_requests/7", "body": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", "state": "done", "created_at": "2016-06-17T07:52:35.225Z", "updated_at": "2016-06-17T07:52:35.225Z" } +``` + +## Mark all todos as done[](#mark-all-todos-as-done "Permalink") + +将当前用户的所有待处理待办事项标记为已完成. 它返回带有空响应的 HTTP 状态代码`204` . + +``` +POST /todos/mark_as_done +``` + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/todos/mark_as_done" +``` \ No newline at end of file diff --git a/_book/docs/377.md b/_book/docs/377.md new file mode 100644 index 0000000000000000000000000000000000000000..d1a4af3143959ce56fc9ed98a40bfaf2b0c687ce --- /dev/null +++ b/_book/docs/377.md @@ -0,0 +1,1095 @@ +# Users API + +> 原文:[https://docs.gitlab.com/ee/api/users.html](https://docs.gitlab.com/ee/api/users.html) + +* [List users](#list-users) + * [For normal users](#for-normal-users) + * [For admins](#for-admins) +* [Single user](#single-user) + * [For user](#for-user) + * [For admin](#for-admin) +* [User creation](#user-creation) +* [User modification](#user-modification) +* [Delete authentication identity from user](#delete-authentication-identity-from-user) +* [User deletion](#user-deletion) +* [List current user (for normal users)](#list-current-user-for-normal-users) +* [List current user (for admins)](#list-current-user-for-admins) +* [User status](#user-status) +* [Get the status of a user](#get-the-status-of-a-user) +* [Set user status](#set-user-status) +* [User counts](#user-counts) +* [List user projects](#list-user-projects) +* [List SSH keys](#list-ssh-keys) +* [List SSH keys for user](#list-ssh-keys-for-user) +* [Single SSH key](#single-ssh-key) +* [Add SSH key](#add-ssh-key) +* [Add SSH key for user](#add-ssh-key-for-user) +* [Delete SSH key for current user](#delete-ssh-key-for-current-user) +* [Delete SSH key for given user](#delete-ssh-key-for-given-user) +* [List all GPG keys](#list-all-gpg-keys) +* [Get a specific GPG key](#get-a-specific-gpg-key) +* [Add a GPG key](#add-a-gpg-key) +* [Delete a GPG key](#delete-a-gpg-key) +* [List all GPG keys for given user](#list-all-gpg-keys-for-given-user) +* [Get a specific GPG key for a given user](#get-a-specific-gpg-key-for-a-given-user) +* [Add a GPG key for a given user](#add-a-gpg-key-for-a-given-user) +* [Delete a GPG key for a given user](#delete-a-gpg-key-for-a-given-user) +* [List emails](#list-emails) +* [List emails for user](#list-emails-for-user) +* [Single email](#single-email) +* [Add email](#add-email) +* [Add email for user](#add-email-for-user) +* [Delete email for current user](#delete-email-for-current-user) +* [Delete email for given user](#delete-email-for-given-user) +* [Block user](#block-user) +* [Unblock user](#unblock-user) +* [Deactivate user](#deactivate-user) +* [Activate user](#activate-user) + * [Get user contribution events](#get-user-contribution-events) +* [Get all impersonation tokens of a user](#get-all-impersonation-tokens-of-a-user) +* [Get an impersonation token of a user](#get-an-impersonation-token-of-a-user) +* [Create an impersonation token](#create-an-impersonation-token) +* [Revoke an impersonation token](#revoke-an-impersonation-token) + * [Get user activities (admin only)](#get-user-activities-admin-only) +* [User memberships (admin only)](#user-memberships-admin-only) + +# Users API[](#users-api "Permalink") + +## List users[](#list-users "Permalink") + +活动用户=帐户总数-被阻止的用户 + +获取用户列表. + +此函数使用分页参数`page`和`per_page`来限制用户列表. + +### For normal users[](#for-normal-users "Permalink") + +``` +GET /users +``` + +``` +[ { "id": 1, "username": "john_smith", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", "web_url": "http://localhost:3000/john_smith" }, { "id": 2, "username": "jack_smith", "name": "Jack Smith", "state": "blocked", "avatar_url": "http://gravatar.com/../e32131cd8.jpeg", "web_url": "http://localhost:3000/jack_smith" } ] +``` + +您还可以使用`?search=`通过名称或主要电子邮件搜索用户. 例如. `/users?search=John` . + +另外,您可以按用户名查找用户: + +``` +GET /users?username=:username +``` + +例如: + +``` +GET /users?username=jack_smith +``` + +另外,您可以根据状态过滤用户,例如. `blocked` , `active`此选项仅用于过滤被`blocked`或`active`用户. 它不支持`active=false`或`blocked=false` . + +``` +GET /users?active=true +``` + +``` +GET /users?blocked=true +``` + +**注意:**用户名搜索不区分大小写. + +### For admins[](#for-admins "Permalink") + +``` +GET /users +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `order_by` | string | no | 返回按`id` , `name` , `username` , `created_at`或`updated_at`字段排序的`username` . 默认为`id` | +| `sort` | string | no | 返回用户按`asc`或`desc`排列. 默认为`desc` | +| `two_factor` | string | no | 通过两因素身份验证过滤用户. `enabled`或`disabled`过滤器值. 默认情况下,它返回所有用户 | +| `without_projects` | boolean | no | 过滤没有项目的用户. 默认为`false` | + +``` +[ { "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "is_admin": false, "bio": null, "bio_html": null, "location": null, "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "", "job_title": "", "last_sign_in_at": "2012-06-01T11:41:01Z", "confirmed_at": "2012-05-23T09:05:22Z", "theme_id": 1, "last_activity_on": "2012-05-23", "color_scheme_id": 2, "projects_limit": 100, "current_sign_in_at": "2012-06-02T06:36:55Z", "note": "DMCA Request: 2018-11-05 | DMCA Violation | Abuse | https://gitlab.zendesk.com/agent/tickets/123", "identities": [ {"provider": "github", "extern_uid": "2435223452345"}, {"provider": "bitbucket", "extern_uid": "john.smith"}, {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"} ], "can_create_group": true, "can_create_project": true, "two_factor_enabled": true, "external": false, "private_profile": false, "current_sign_in_ip": "196.165.1.102", "last_sign_in_ip": "172.127.2.22" }, { "id": 2, "username": "jack_smith", "email": "jack@example.com", "name": "Jack Smith", "state": "blocked", "avatar_url": "http://localhost:3000/uploads/user/avatar/2/index.jpg", "web_url": "http://localhost:3000/jack_smith", "created_at": "2012-05-23T08:01:01Z", "is_admin": false, "bio": null, "bio_html": null, "location": null, "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "", "job_title": "", "last_sign_in_at": null, "confirmed_at": "2012-05-30T16:53:06.148Z", "theme_id": 1, "last_activity_on": "2012-05-23", "color_scheme_id": 3, "projects_limit": 100, "current_sign_in_at": "2014-03-19T17:54:13Z", "identities": [], "can_create_group": true, "can_create_project": true, "two_factor_enabled": true, "external": false, "private_profile": false, "current_sign_in_ip": "10.165.1.102", "last_sign_in_ip": "172.127.2.22" } ] +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`shared_runners_minutes_limit`和`extra_shared_runners_minutes_limit`参数. + +``` +[ { "id": 1, ... "shared_runners_minutes_limit": 133, "extra_shared_runners_minutes_limit": 133, ... } ] +``` + +使用 GitLab [Silver 或更高版本的](https://about.gitlab.com/pricing/)用户还将看到`group_saml`提供程序选项: + +``` +[ { "id": 1, ... "identities": [ {"provider": "github", "extern_uid": "2435223452345"}, {"provider": "bitbucket", "extern_uid": "john.smith"}, {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"}, {"provider": "group_saml", "extern_uid": "123789", "saml_provider_id": 10} ], ... } ] +``` + +您可以通过外部 UID 和提供程序查找用户: + +``` +GET /users?extern_uid=:extern_uid&provider=:provider +``` + +例如: + +``` +GET /users?extern_uid=1234567&provider=github +``` + +您可以使用`/users?external=true`搜索外部`/users?external=true` + +您可以使用以下创建日期时间范围来搜索用户: + +``` +GET /users?created_before=2001-01-02T00:00:00.060Z&created_after=1999-01-02T00:00:00.060 +``` + +您可以使用`/users?without_projects=true`搜索没有项目的`/users?without_projects=true` + +您可以使用以下[自定义属性](custom_attributes.html)进行过滤: + +``` +GET /users?custom_attributes[key]=value&custom_attributes[other_key]=other_value +``` + +您可以通过以下方式在响应中包括用户的[自定义属性](custom_attributes.html) : + +``` +GET /users?with_custom_attributes=true +``` + +## Single user[](#single-user "Permalink") + +获得一个用户. + +### For user[](#for-user "Permalink") + +``` +GET /users/:id +``` + +Parameters: + +* `id` (必填)-用户的 ID + +``` +{ "id": 1, "username": "john_smith", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "bio": null, "bio_html": null, "location": null, "public_email": "john@example.com", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "", "job_title": "Operations Specialist" } +``` + +### For admin[](#for-admin "Permalink") + +``` +GET /users/:id +``` + +Parameters: + +* `id` (必填)-用户的 ID + +响应示例: + +``` +{ "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "is_admin": false, "bio": null, "bio_html": null, "location": null, "public_email": "john@example.com", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "", "job_title": "Operations Specialist", "last_sign_in_at": "2012-06-01T11:41:01Z", "confirmed_at": "2012-05-23T09:05:22Z", "theme_id": 1, "last_activity_on": "2012-05-23", "color_scheme_id": 2, "projects_limit": 100, "current_sign_in_at": "2012-06-02T06:36:55Z", "note": "DMCA Request: 2018-11-05 | DMCA Violation | Abuse | https://gitlab.zendesk.com/agent/tickets/123", "identities": [ {"provider": "github", "extern_uid": "2435223452345"}, {"provider": "bitbucket", "extern_uid": "john.smith"}, {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"} ], "can_create_group": true, "can_create_project": true, "two_factor_enabled": true, "external": false, "private_profile": false, "current_sign_in_ip": "196.165.1.102", "last_sign_in_ip": "172.127.2.22", "plan": "gold", "trial": true } +``` + +**注意:** `plan`和`trial`参数仅在 GitLab 企业版上可用. + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`shared_runners_minutes_limit`和`extra_shared_runners_minutes_limit`参数. + +``` +{ "id": 1, "username": "john_smith", "shared_runners_minutes_limit": 133, "extra_shared_runners_minutes_limit": 133, ... } +``` + +GitLab.com [Silver 或更高版本](https://about.gitlab.com/pricing/)上的用户还将看到`group_saml`选项: + +``` +{ "id": 1, "username": "john_smith", "shared_runners_minutes_limit": 133, "extra_shared_runners_minutes_limit": 133, "identities": [ {"provider": "github", "extern_uid": "2435223452345"}, {"provider": "bitbucket", "extern_uid": "john.smith"}, {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"}, {"provider": "group_saml", "extern_uid": "123789", "saml_provider_id": 10} ], ... } +``` + +您可以通过以下方式在响应中包括用户的[自定义属性](custom_attributes.html) : + +``` +GET /users/:id?with_custom_attributes=true +``` + +## User creation[](#user-creation "Permalink") + +Creates a new user. Note only administrators can create new users. Either `password`, `reset_password`, or `force_random_password` must be specified. If `reset_password` and `force_random_password` are both `false`, then `password` is required. + +请注意, `force_random_password`和`reset_password`优先级高于`password` . 此外, `reset_password`和`force_random_password`可以一起使用. + +**注意:**从[GitLab 12.1 开始](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29888/) , `private_profile`将默认为`false` . + +``` +POST /users +``` + +Parameters: + +| Attribute | Required | Description | +| --- | --- | --- | +| `admin` | No | 用户是管理员-正确或错误(默认) | +| `avatar` | No | 用户头像的图像文件 | +| `bio` | No | 用户的传记 | +| `can_create_group` | No | 用户可以创建组-正确或错误 | +| `color_scheme_id` | No | 用户针对文件查看器的配色方案(有关更多信息,请参见[用户首选项文档](../user/profile/preferences.html#syntax-highlighting-theme) ) | +| `email` | Yes | Email | +| `extern_uid` | No | 外部 UID | +| `external` | No | 将用户标记为外部用户-true 或 false(默认) | +| `extra_shared_runners_minutes_limit` | No | 该用户的额外管道分钟配额(在计划中包括的分钟之外购买) | +| `force_random_password` | No | 将用户密码设置为随机值-正确或错误(默认) | +| `group_id_for_saml` | No | 已配置 SAML 的组的 ID | +| `linkedin` | No | LinkedIn | +| `location` | No | 用户位置 | +| `name` | Yes | Name | +| `note` | No | 该用户的管理说明 | +| `organization` | No | 机构名称 | +| `password` | No | Password | +| `private_profile` | No | 用户的个人资料是私有的-true,false(默认)或 null(将转换为 false) | +| `projects_limit` | No | 用户可以创建的项目数 | +| `provider` | No | 外部提供商名称 | +| `public_email` | No | 用户的公开电子邮件 | +| `reset_password` | No | 发送用户密码重置链接-正确或错误(默认) | +| `shared_runners_minutes_limit` | No | 该用户的管道分钟配额(包括在计划中). 可以为`nil` (默认值;继承系统默认值), `0` (无限制)或`> 0` | +| `skip_confirmation` | No | 跳过确认-正确或错误(默认) | +| `skype` | No | Skype 帐号 | +| `theme_id` | No | 用户的 GitLab 主题(有关更多信息,请参见[用户首选项文档](../user/profile/preferences.html#navigation-theme) ) | +| `twitter` | No | Twitter 账号 | +| `username` | Yes | Username | +| `website_url` | No | 网址 | + +## User modification[](#user-modification "Permalink") + +修改现有用户. 只有管​​理员可以更改用户的属性. + +``` +PUT /users/:id +``` + +Parameters: + +| Attribute | Required | Description | +| --- | --- | --- | +| `admin` | No | 用户是管理员-正确或错误(默认) | +| `avatar` | No | 用户头像的图像文件 | +| `bio` | No | 用户的传记 | +| `can_create_group` | No | 用户可以创建组-正确或错误 | +| `color_scheme_id` | No | 用户针对文件查看器的配色方案(有关更多信息,请参见[用户首选项文档](../user/profile/preferences.html#syntax-highlighting-theme) ) | +| `email` | No | Email | +| `extern_uid` | No | 外部 UID | +| `external` | No | 将用户标记为外部用户-true 或 false(默认) | +| `extra_shared_runners_minutes_limit` | No | 该用户的额外管道分钟配额(在计划中包括的分钟之外购买) | +| `group_id_for_saml` | No | 已配置 SAML 的组的 ID | +| `id` | Yes | 用户的 ID | +| `linkedin` | No | LinkedIn | +| `location` | No | 用户位置 | +| `name` | No | Name | +| `note` | No | 该用户的管理说明 | +| `organization` | No | 机构名称 | +| `password` | No | Password | +| `private_profile` | No | 用户的个人资料是私有的-true,false(默认)或 null(将转换为 false) | +| `projects_limit` | No | 限制每个用户可以创建的项目 | +| `provider` | No | 外部提供商名称 | +| `public_email` | No | 用户的公开电子邮件 | +| `shared_runners_minutes_limit` | No | 该用户的管道分钟配额(包括在计划中). 可以为`nil` (默认值;继承系统默认值), `0` (无限制)或`> 0` | +| `skip_reconfirmation` | No | 跳过确认-正确或错误(默认) | +| `skype` | No | Skype 帐号 | +| `theme_id` | No | 用户的 GitLab 主题(有关更多信息,请参见[用户首选项文档](../user/profile/preferences.html#navigation-theme) ) | +| `twitter` | No | Twitter 账号 | +| `username` | No | Username | +| `website_url` | No | 网址 | + +密码更新时,用户将被迫在下次登录时进行更改. 请注意,此方法目前仅返回`404`错误,即使在`409` (冲突)更为合适的情况下也是如此. 例如,将电子邮件地址重命名为某个现有地址时. + +## Delete authentication identity from user[](#delete-authentication-identity-from-user "Permalink") + +使用与该身份关联的提供者名称删除用户的身份验证身份. 仅适用于管理员. + +``` +DELETE /users/:id/identities/:provider +``` + +Parameters: + +* `id` (必填)-用户的 ID +* `provider` (必填)-外部提供程序名称 + +## User deletion[](#user-deletion "Permalink") + +删除用户. 仅适用于管理员. 如果操作成功,则返回`204 No Content`状态代码;如果找不到资源,则返回`404`如果无法软删除用户,则返回`409` . + +``` +DELETE /users/:id +``` + +Parameters: + +* `id` (必填)-用户的 ID +* `hard_delete` (可选)-如果为 true,则通常会[移至](../user/profile/account/delete_account.html#associated-records) `hard_delete` [用户的](../user/profile/account/delete_account.html#associated-records)贡献以及该用户`hard_delete`组将被删除. + +## List current user (for normal users)[](#list-current-user-for-normal-users "Permalink") + +获取当前经过身份验证的用户. + +``` +GET /user +``` + +``` +{ "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "bio": null, "bio_html": null, "location": null, "public_email": "john@example.com", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "", "last_sign_in_at": "2012-06-01T11:41:01Z", "confirmed_at": "2012-05-23T09:05:22Z", "theme_id": 1, "last_activity_on": "2012-05-23", "color_scheme_id": 2, "projects_limit": 100, "current_sign_in_at": "2012-06-02T06:36:55Z", "identities": [ {"provider": "github", "extern_uid": "2435223452345"}, {"provider": "bitbucket", "extern_uid": "john_smith"}, {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"} ], "can_create_group": true, "can_create_project": true, "two_factor_enabled": true, "external": false, "private_profile": false } +``` + +## List current user (for admins)[](#list-current-user-for-admins "Permalink") + +Parameters: + +* `sudo` (可选)-在其位置进行呼叫的用户的 ID + +``` +GET /user +``` + +``` +{ "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "is_admin": false, "bio": null, "bio_html": null, "location": null, "public_email": "john@example.com", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "", "job_title": "", "last_sign_in_at": "2012-06-01T11:41:01Z", "confirmed_at": "2012-05-23T09:05:22Z", "theme_id": 1, "last_activity_on": "2012-05-23", "color_scheme_id": 2, "projects_limit": 100, "current_sign_in_at": "2012-06-02T06:36:55Z", "identities": [ {"provider": "github", "extern_uid": "2435223452345"}, {"provider": "bitbucket", "extern_uid": "john_smith"}, {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"} ], "can_create_group": true, "can_create_project": true, "two_factor_enabled": true, "external": false, "private_profile": false, "current_sign_in_ip": "196.165.1.102", "last_sign_in_ip": "172.127.2.22" } +``` + +## User status[](#user-status "Permalink") + +获取当前登录用户的状态. + +``` +GET /user/status +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/user/status" +``` + +响应示例: + +``` +{ "emoji":"coffee", "message":"I crave coffee :coffee:", "message_html": "I crave coffee " } +``` + +## Get the status of a user[](#get-the-status-of-a-user "Permalink") + +获取用户的状态. + +``` +GET /users/:id_or_username/status +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id_or_username` | string | yes | 用户的 ID 或用户名,以获取状态 | + +``` +curl "https://gitlab.example.com/users/janedoe/status" +``` + +响应示例: + +``` +{ "emoji":"coffee", "message":"I crave coffee :coffee:", "message_html": "I crave coffee " } +``` + +## Set user status[](#set-user-status "Permalink") + +设置当前用户的状态. + +``` +PUT /user/status +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `emoji` | string | no | 用作状态的表情符号名称. 如果省略,则使用`speech_balloon` . 表情符号名称可以是[Gemojione 索引中](https://github.com/bonusly/gemojione/blob/master/config/index.json)指定的名称之一. | +| `message` | string | no | 设置为状态的消息. 它还可以包含表情符号代码. | + +当参数`emoji`和`message`都为空时,状态将被清除. + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --data "emoji=coffee" --data "message=I crave coffee" "https://gitlab.example.com/api/v4/user/status" +``` + +回应范例 + +``` +{ "emoji":"coffee", "message":"I crave coffee", "message_html": "I crave coffee" } +``` + +## User counts[](#user-counts "Permalink") + +获取当前登录用户的计数(与右上角菜单相同). + +| Attribute | Type | Description | +| --- | --- | --- | +| `merge_requests` | number | 合并活动的请求并分配给当前用户. | + +``` +GET /user_counts +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/user_counts" +``` + +响应示例: + +``` +{ "merge_requests": 4 } +``` + +## List user projects[](#list-user-projects "Permalink") + +请参考[用户项目列表](projects.html#list-user-projects) . + +## List SSH keys[](#list-ssh-keys "Permalink") + +获取当前经过身份验证的用户的 SSH 密钥的列表. + +``` +GET /user/keys +``` + +``` +[ { "id": 1, "title": "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2014-08-01T14:47:39.080Z" }, { "id": 3, "title": "Another Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2014-08-01T14:47:39.080Z" } ] +``` + +Parameters: + +* **none** + +## List SSH keys for user[](#list-ssh-keys-for-user "Permalink") + +获取指定用户的 SSH 密钥的列表. + +``` +GET /users/:id_or_username/keys +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id_or_username` | string | yes | 要为其获取 SSH 密钥的用户的 ID 或用户名. | + +## Single SSH key[](#single-ssh-key "Permalink") + +获取一个密钥. + +``` +GET /user/keys/:key_id +``` + +Parameters: + +* `key_id` (必填) `key_id`密钥的 ID + +``` +{ "id": 1, "title": "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2014-08-01T14:47:39.080Z" } +``` + +## Add SSH key[](#add-ssh-key "Permalink") + +创建当前经过身份验证的用户拥有的新密钥. + +``` +POST /user/keys +``` + +Parameters: + +* `title` (必填)-新的 SSH 密钥的标题 +* `key` (必填)-新的 SSH 密钥 +* `expires_at` (可选)-ISO 8601 格式的 SSH 密钥的到期日期( `YYYY-MM-DDTHH:MM:SSZ` ) + +``` +{ "title": "ABC", "key": "ssh-dss AAAAB3NzaC1kc3MAAACBAMLrhYgI3atfrSD6KDas1b/3n6R/HP+bLaHHX6oh+L1vg31mdUqK0Ac/NjZoQunavoyzqdPYhFz9zzOezCrZKjuJDS3NRK9rspvjgM0xYR4d47oNZbdZbwkI4cTv/gcMlquRy0OvpfIvJtjtaJWMwTLtM5VhRusRuUlpH99UUVeXAAAAFQCVyX+92hBEjInEKL0v13c/egDCTQAAAIEAvFdWGq0ccOPbw4f/F8LpZqvWDydAcpXHV3thwb7WkFfppvm4SZte0zds1FJ+Hr8Xzzc5zMHe6J4Nlay/rP4ewmIW7iFKNBEYb/yWa+ceLrs+TfR672TaAgO6o7iSRofEq5YLdwgrwkMmIawa21FrZ2D9SPao/IwvENzk/xcHu7YAAACAQFXQH6HQnxOrw4dqf0NqeKy1tfIPxYYUZhPJfo9O0AmBW2S36pD2l14kS89fvz6Y1g8gN/FwFnRncMzlLY/hX70FSc/3hKBSbH6C6j8hwlgFKfizav21eS358JJz93leOakJZnGb8XlWvz1UJbwCsnR2VEY8Dz90uIk1l/UqHkA= loic@call", "expires_at": "2016-01-21T00:00:00.000Z" } +``` + +将返回状态为`201 Created`成功的已创建密钥. 如果发生错误,则会返回`400 Bad Request` ,并附有一条解释该错误的消息: + +``` +{ "message": { "fingerprint": [ "has already been taken" ], "key": [ "has already been taken" ] } } +``` + +## Add SSH key for user[](#add-ssh-key-for-user "Permalink") + +创建指定用户拥有的新密钥. 仅适用于管理员 + +``` +POST /users/:id/keys +``` + +Parameters: + +* `id` (必填)-指定用户的 ID +* `title` (必填)-新的 SSH 密钥的标题 +* `key` (必填)-新的 SSH 密钥 +* `expires_at` (可选)-ISO 8601 格式的 SSH 密钥的到期日期( `YYYY-MM-DDTHH:MM:SSZ` ) + +**注意:**这还会添加一个审核事件,如[审核实例事件中所述](../administration/audit_events.html#instance-events-premium-only) . + +## Delete SSH key for current user[](#delete-ssh-key-for-current-user "Permalink") + +删除当前经过身份验证的用户拥有的密钥. 如果操作成功,则返回`204 No Content`状态代码;如果找不到资源,则返回`404` . + +``` +DELETE /user/keys/:key_id +``` + +Parameters: + +* `key_id` (必填) `key_id`密钥 ID + +## Delete SSH key for given user[](#delete-ssh-key-for-given-user "Permalink") + +删除指定用户拥有的密钥. 仅适用于管理员. + +``` +DELETE /users/:id/keys/:key_id +``` + +Parameters: + +* `id` (必填)-指定用户的 ID +* `key_id` (必填) `key_id`密钥 ID + +## List all GPG keys[](#list-all-gpg-keys "Permalink") + +获取当前已验证用户的 GPG 密钥的列表. + +``` +GET /user/gpg_keys +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/user/gpg_keys" +``` + +响应示例: + +``` +[ { "id": 1, "key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj\r\nt1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O\r\nCfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa\r\nqKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO\r\nVaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57\r\nvilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp\r\nIDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV\r\nCAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/\r\noO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5\r\ncrfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4\r\nbjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn\r\niE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp\r\no4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=\r\n=XQoy\r\n-----END PGP PUBLIC KEY BLOCK-----", "created_at": "2017-09-05T09:17:46.264Z" } ] +``` + +## Get a specific GPG key[](#get-a-specific-gpg-key "Permalink") + +获取当前已认证用户的特定 GPG 密钥. + +``` +GET /user/gpg_keys/:key_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `key_id` | integer | yes | GPG 密钥的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/user/gpg_keys/1" +``` + +响应示例: + +``` + { "id": 1, "key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj\r\nt1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O\r\nCfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa\r\nqKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO\r\nVaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57\r\nvilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp\r\nIDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV\r\nCAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/\r\noO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5\r\ncrfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4\r\nbjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn\r\niE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp\r\no4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=\r\n=XQoy\r\n-----END PGP PUBLIC KEY BLOCK-----", "created_at": "2017-09-05T09:17:46.264Z" } +``` + +## Add a GPG key[](#add-a-gpg-key "Permalink") + +创建由当前身份验证用户拥有的新 GPG 密钥. + +``` +POST /user/gpg_keys +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| key | string | yes | 新的 GPG 密钥 | + +``` +curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/user/gpg_keys" +``` + +响应示例: + +``` +[ { "id": 1, "key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj\r\nt1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O\r\nCfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa\r\nqKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO\r\nVaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57\r\nvilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp\r\nIDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV\r\nCAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/\r\noO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5\r\ncrfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4\r\nbjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn\r\niE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp\r\no4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=\r\n=XQoy\r\n-----END PGP PUBLIC KEY BLOCK-----", "created_at": "2017-09-05T09:17:46.264Z" } ] +``` + +## Delete a GPG key[](#delete-a-gpg-key "Permalink") + +删除当前经过身份验证的用户拥有的 GPG 密钥. + +``` +DELETE /user/gpg_keys/:key_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `key_id` | integer | yes | GPG 密钥的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/user/gpg_keys/1" +``` + +成功时返回`204 No Content` ,如果`404 Not found`密钥,则返回`404 Not found` found. + +## List all GPG keys for given user[](#list-all-gpg-keys-for-given-user "Permalink") + +获取指定用户的 GPG 密钥的列表. 仅适用于管理员. + +``` +GET /users/:id/gpg_keys +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 用户的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/2/gpg_keys" +``` + +响应示例: + +``` +[ { "id": 1, "key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj\r\nt1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O\r\nCfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa\r\nqKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO\r\nVaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57\r\nvilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp\r\nIDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV\r\nCAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/\r\noO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5\r\ncrfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4\r\nbjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn\r\niE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp\r\no4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=\r\n=XQoy\r\n-----END PGP PUBLIC KEY BLOCK-----", "created_at": "2017-09-05T09:17:46.264Z" } ] +``` + +## Get a specific GPG key for a given user[](#get-a-specific-gpg-key-for-a-given-user "Permalink") + +获取给定用户的特定 GPG 密钥. 仅适用于管理员. + +``` +GET /users/:id/gpg_keys/:key_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 用户的 ID | +| `key_id` | integer | yes | GPG 密钥的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/2/gpg_keys/1" +``` + +响应示例: + +``` + { "id": 1, "key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj\r\nt1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O\r\nCfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa\r\nqKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO\r\nVaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57\r\nvilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp\r\nIDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV\r\nCAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/\r\noO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5\r\ncrfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4\r\nbjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn\r\niE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp\r\no4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=\r\n=XQoy\r\n-----END PGP PUBLIC KEY BLOCK-----", "created_at": "2017-09-05T09:17:46.264Z" } +``` + +## Add a GPG key for a given user[](#add-a-gpg-key-for-a-given-user "Permalink") + +创建指定用户拥有的新 GPG 密钥. 仅适用于管理员. + +``` +POST /users/:id/gpg_keys +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 用户的 ID | +| `key_id` | integer | yes | GPG 密钥的 ID | + +``` +curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/2/gpg_keys" +``` + +响应示例: + +``` +[ { "id": 1, "key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj\r\nt1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O\r\nCfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa\r\nqKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO\r\nVaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57\r\nvilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp\r\nIDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV\r\nCAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/\r\noO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5\r\ncrfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4\r\nbjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn\r\niE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp\r\no4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=\r\n=XQoy\r\n-----END PGP PUBLIC KEY BLOCK-----", "created_at": "2017-09-05T09:17:46.264Z" } ] +``` + +## Delete a GPG key for a given user[](#delete-a-gpg-key-for-a-given-user "Permalink") + +删除指定用户拥有的 GPG 密钥. 仅适用于管理员. + +``` +DELETE /users/:id/gpg_keys/:key_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 用户的 ID | +| `key_id` | integer | yes | The ID of the GPG key | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/2/gpg_keys/1" +``` + +## List emails[](#list-emails "Permalink") + +获取当前经过身份验证的用户电子邮件列表. + +``` +GET /user/emails +``` + +``` +[ { "id": 1, "email": "email@example.com" }, { "id": 3, "email": "email2@example.com" } ] +``` + +Parameters: + +* **none** + +## List emails for user[](#list-emails-for-user "Permalink") + +获取指定用户的电子邮件列表. 仅适用于管理员 + +``` +GET /users/:id/emails +``` + +Parameters: + +* `id` (必填)-指定用户的 ID + +## Single email[](#single-email "Permalink") + +收到一封电子邮件. + +``` +GET /user/emails/:email_id +``` + +Parameters: + +* `email_id` (必填)-电子邮件 ID + +``` +{ "id": 1, "email": "email@example.com" } +``` + +## Add email[](#add-email "Permalink") + +创建由当前身份验证用户拥有的新电子邮件. + +``` +POST /user/emails +``` + +Parameters: + +* `email` (必填)-电子邮件地址 + +``` +{ "id": 4, "email": "email@example.com" } +``` + +将返回状态为`201 Created`成功的已创建电子邮件. 如果发生错误,则会返回`400 Bad Request` ,并附有一条解释该错误的消息: + +``` +{ "message": { "email": [ "has already been taken" ] } } +``` + +## Add email for user[](#add-email-for-user "Permalink") + +创建指定用户拥有的新电子邮件. 仅适用于管理员 + +``` +POST /users/:id/emails +``` + +Parameters: + +* `id` (必填)-指定用户的 ID +* `email` (必填)-电子邮件地址 +* `skip_confirmation` (可选)-跳过确认并假定电子邮件已通过验证`skip_confirmation`或 false(默认) + +## Delete email for current user[](#delete-email-for-current-user "Permalink") + +删除当前经过身份验证的用户拥有的电子邮件. 如果操作成功,则返回`204 No Content`状态代码;如果找不到资源,则返回`404` . + +``` +DELETE /user/emails/:email_id +``` + +Parameters: + +* `email_id` (必填)-电子邮件 ID + +## Delete email for given user[](#delete-email-for-given-user "Permalink") + +删除指定用户拥有的电子邮件. 仅适用于管理员. + +``` +DELETE /users/:id/emails/:email_id +``` + +Parameters: + +* `id` (必填)-指定用户的 ID +* `email_id` (必填)-电子邮件 ID + +## Block user[](#block-user "Permalink") + +阻止指定的用户. 仅适用于管理员. + +``` +POST /users/:id/block +``` + +Parameters: + +* `id` (必填)-指定用户的 ID + +Returns: + +* `201 OK`成功成功. +* `404 User Not Found`如果`404 User Not Found`用户,则`404 User Not Found`用户. +* `403 Forbidden`尝试通过 LDAP 同步阻止已阻止的用户时禁止. + +## Unblock user[](#unblock-user "Permalink") + +取消阻止指定的用户. 仅适用于管理员. + +``` +POST /users/:id/unblock +``` + +Parameters: + +* `id` (必填)-指定用户的 ID + +尝试取消阻止被 LDAP 同步阻止的用户时,成功返回`201 OK` ,成功返回`404 User Not Found`或`403 Forbidden` . + +## Deactivate user[](#deactivate-user "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) . + +停用指定的用户. 仅适用于管理员. + +``` +POST /users/:id/deactivate +``` + +Parameters: + +* `id` (必填)-指定用户的 ID + +Returns: + +* `201 OK`成功成功. +* `404 User Not Found`如果`404 User Not Found`用户,则`404 User Not Found`用户. +* `403 Forbidden`尝试停用用户时被禁止: + * 被管理员或 LDAP 同步阻止. + * 在过去 180 天内没有任何活动. 这些用户无法停用. + +## Activate user[](#activate-user "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) . + +激活指定的用户. 仅适用于管理员. + +``` +POST /users/:id/activate +``` + +Parameters: + +* `id` (必填)-指定用户的 ID + +Returns: + +* `201 OK`成功成功. +* `404 User Not Found`如果`404 User Not Found`用户,则`404 User Not Found`用户. +* `403 Forbidden`尝试激活被管理员或 LDAP 同步阻止的用户时禁止. + +### Get user contribution events[](#get-user-contribution-events "Permalink") + +请参阅[事件 API 文档](events.html#get-user-contribution-events) + +## Get all impersonation tokens of a user[](#get-all-impersonation-tokens-of-a-user "Permalink") + +> 需要管理员权限. + +它检索用户的每个模拟令牌. 使用分页参数`page`和`per_page`可以限制模拟令牌的列表. + +``` +GET /users/:user_id/impersonation_tokens +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | integer | yes | 用户的 ID | +| `state` | string | no | 根据状态( `all` , `active` , `inactive` )过滤令牌 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/42/impersonation_tokens" +``` + +响应示例: + +``` +[ { "active" : true, "scopes" : [ "api" ], "revoked" : false, "name" : "mytoken", "id" : 2, "created_at" : "2017-03-17T17:18:09.283Z", "impersonation" : true, "expires_at" : "2017-04-04" }, { "active" : false, "scopes" : [ "read_user" ], "revoked" : true, "name" : "mytoken2", "created_at" : "2017-03-17T17:19:28.697Z", "id" : 3, "impersonation" : true, "expires_at" : "2017-04-14" } ] +``` + +## Get an impersonation token of a user[](#get-an-impersonation-token-of-a-user "Permalink") + +> 需要管理员权限. + +它显示了用户的模拟令牌. + +``` +GET /users/:user_id/impersonation_tokens/:impersonation_token_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | integer | yes | 用户的 ID | +| `impersonation_token_id` | integer | yes | 模拟令牌的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/42/impersonation_tokens/2" +``` + +响应示例: + +``` +{ "active" : true, "scopes" : [ "api" ], "revoked" : false, "name" : "mytoken", "id" : 2, "created_at" : "2017-03-17T17:18:09.283Z", "impersonation" : true, "expires_at" : "2017-04-04" } +``` + +## Create an impersonation token[](#create-an-impersonation-token "Permalink") + +> 需要管理员权限. 令牌值返回一次. 确保将其保存-您将无法再次访问它. + +它创建一个新的模拟令牌. 请注意,只有管理员可以执行此操作. 您只能创建模拟令牌来模拟用户,并执行 API 调用和 Git 读写. 用户将不会在其个人资料设置页面中看到这些令牌. + +``` +POST /users/:user_id/impersonation_tokens +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | integer | yes | 用户的 ID | +| `name` | string | yes | 模拟令牌的名称 | +| `expires_at` | date | no | ISO 格式( `YYYY-MM-DD` )的模拟令牌的到期日期 | +| `scopes` | array | yes | 模拟令牌作用域的数组( `api` , `read_user` ) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --data "name=mytoken" --data "expires_at=2017-04-04" --data "scopes[]=api" "https://gitlab.example.com/api/v4/users/42/impersonation_tokens" +``` + +响应示例: + +``` +{ "id" : 2, "revoked" : false, "scopes" : [ "api" ], "token" : "EsMo-vhKfXGwX9RKrwiy", "active" : true, "impersonation" : true, "name" : "mytoken", "created_at" : "2017-03-17T17:18:09.283Z", "expires_at" : "2017-04-04" } +``` + +## Revoke an impersonation token[](#revoke-an-impersonation-token "Permalink") + +> 需要管理员权限. + +它撤销模拟令牌. + +``` +DELETE /users/:user_id/impersonation_tokens/:impersonation_token_id +``` + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/42/impersonation_tokens/1" +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | integer | yes | 用户的 ID | +| `impersonation_token_id` | integer | yes | 模拟令牌的 ID | + +### Get user activities (admin only)[](#get-user-activities-admin-only "Permalink") + +**注意:**此 API 端点仅在 8.15(EE)和 9.1(CE)及更高版本上可用. + +获取所有用户的上次活动日期,从最旧到最新. + +更新时间戳记的活动是: + +* Git HTTP / SSH 活动(例如克隆,推送) +* 用户登录 GitLab +* 与仪表板,项目,问题和合并请求相关的用户访问页面(在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54947) ) +* 用户使用 API +* 用户使用 GraphQL API + +默认情况下,它显示最近 6 个月内所有用户的活动,但是可以使用`from`参数进行修改. + +``` +GET /user/activities +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `from` | string | no | 日期字符串,格式为 YEAR-MONTH-DAY. 例如, `2016-03-11` . 默认为 6 个月前. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/user/activities" +``` + +响应示例: + +``` +[ { "username": "user1", "last_activity_on": "2015-12-14", "last_activity_at": "2015-12-14" }, { "username": "user2", "last_activity_on": "2015-12-15", "last_activity_at": "2015-12-15" }, { "username": "user3", "last_activity_on": "2015-12-16", "last_activity_at": "2015-12-16" } ] +``` + +请注意, `last_activity_at`已过时,请使用`last_activity_on` . + +## User memberships (admin only)[](#user-memberships-admin-only "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/20532) . + +列出用户所属的所有项目和组. 该端点仅适用于管理员. 它返回成员资格的`source_id` , `source_name` , `source_type`和`access_level` . 源可以是`Namespace` (代表一个组)或`Project` . 响应仅代表直接成员身份. 不包括继承的成员资格,例如在子组中. 访问级别由整数值表示. 有关更多详细信息,请阅读有关[访问级别值](access_requests.html#valid-access-levels)的含义. + +``` +GET /users/:id/memberships +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 指定用户的 ID | +| `type` | string | no | 按类型过滤成员资格. 可以是`Project`或`Namespace` | + +Returns: + +* `200 OK`成功. +* `404 User Not Found` if user can’t be found. +* `403 Forbidden`管理员未要求时禁止. +* 不支持请求的类型时出现`400 Bad Request` . + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/:user_id/memberships" +``` + +响应示例: + +``` +[ { "source_id": 1, "source_name": "Project one", "source_type": "Project", "access_level": "20" }, { "source_id": 3, "source_name": "Group three", "source_type": "Namespace", "access_level": "20" }, ] +``` \ No newline at end of file diff --git a/_book/docs/378.md b/_book/docs/378.md new file mode 100644 index 0000000000000000000000000000000000000000..76e2cea8ba0695f5cbd398678490fa90a2bb1bbd --- /dev/null +++ b/_book/docs/378.md @@ -0,0 +1,159 @@ +# Project-level Variables API + +> 原文:[https://docs.gitlab.com/ee/api/project_level_variables.html](https://docs.gitlab.com/ee/api/project_level_variables.html) + +* [List project variables](#list-project-variables) +* [Show variable details](#show-variable-details) +* [Create variable](#create-variable) +* [Update variable](#update-variable) +* [Remove variable](#remove-variable) +* [The `filter` parameter](#the-filter-parameter) + * [Enable or disable](#enable-or-disable) + +# Project-level Variables API[](#project-level-variables-api "Permalink") + +## List project variables[](#list-project-variables "Permalink") + +获取项目变量的列表. + +``` +GET /projects/:id/variables +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 一个项目的 ID 或经过身份验证的用户拥有[的该项目的 Urlencoded NAMESPACE / PROJECT_NAME](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/variables" +``` + +``` +[ { "key": "TEST_VARIABLE_1", "variable_type": "env_var", "value": "TEST_1" }, { "key": "TEST_VARIABLE_2", "variable_type": "env_var", "value": "TEST_2" } ] +``` + +## Show variable details[](#show-variable-details "Permalink") + +获取项目特定变量的详细信息. + +``` +GET /projects/:id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 一个项目的 ID 或经过身份验证的用户拥有[的该项目的 Urlencoded NAMESPACE / PROJECT_NAME](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` | +| `filter` | hash | no | 可用的过滤器: `[environment_scope]` . 请参阅[`filter`参数详细信息](#the-filter-parameter) . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/variables/TEST_VARIABLE_1" +``` + +``` +{ "key": "TEST_VARIABLE_1", "variable_type": "env_var", "value": "TEST_1", "protected": false, "masked": true } +``` + +## Create variable[](#create-variable "Permalink") + +创建一个新变量. + +``` +POST /projects/:id/variables +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 一个项目的 ID 或经过身份验证的用户拥有[的该项目的 Urlencoded NAMESPACE / PROJECT_NAME](README.html#namespaced-path-encoding) | +| `key` | string | yes | The `key` of a variable; must have no more than 255 characters; only `A-Z`, `a-z`, `0-9`, and `_` are allowed | +| `value` | string | yes | 变量的`value` | +| `variable_type` | string | no | 变量的类型. 可用类型为: `env_var` (默认)和`file` | +| `protected` | boolean | no | 变量是否受保护 | +| `masked` | boolean | no | 变量是否被屏蔽 | +| `environment_scope` | string | no | 变量的`environment_scope` | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/variables" --form "key=NEW_VARIABLE" --form "value=new value" +``` + +``` +{ "key": "NEW_VARIABLE", "value": "new value", "protected": false, "variable_type": "env_var", "masked": false, "environment_scope": "*" } +``` + +## Update variable[](#update-variable "Permalink") + +更新项目的变量. + +``` +PUT /projects/:id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 一个项目的 ID 或经过身份验证的用户拥有[的该项目的 Urlencoded NAMESPACE / PROJECT_NAME](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` | +| `value` | string | yes | 变量的`value` | +| `variable_type` | string | no | 变量的类型. 可用类型为: `env_var` (默认)和`file` | +| `protected` | boolean | no | 变量是否受保护 | +| `masked` | boolean | no | 变量是否被屏蔽 | +| `environment_scope` | string | no | 变量的`environment_scope` | +| `filter` | hash | no | 可用的过滤器: `[environment_scope]` . 请参阅[`filter`参数详细信息](#the-filter-parameter) . | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/variables/NEW_VARIABLE" --form "value=updated value" +``` + +``` +{ "key": "NEW_VARIABLE", "value": "updated value", "variable_type": "env_var", "protected": true, "masked": false, "environment_scope": "*" } +``` + +## Remove variable[](#remove-variable "Permalink") + +删除项目的变量. + +``` +DELETE /projects/:id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 一个项目的 ID 或经过身份验证的用户拥有[的该项目的 Urlencoded NAMESPACE / PROJECT_NAME](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` | +| `filter` | hash | no | 可用的过滤器: `[environment_scope]` . 请参阅[`filter`参数详细信息](#the-filter-parameter) . | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/variables/VARIABLE_1" +``` + +## The `filter` parameter[](#the-filter-parameter "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34490) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上已禁用. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员启用它. + +此参数用于按属性(例如`environment_scope`进行过滤. + +用法示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/variables/VARIABLE_1?filter[environment_scope]=production" +``` + +### Enable or disable[](#enable-or-disable "Permalink") + +[有权访问 GitLab Rails 控制台的 GitLab 管理员](../administration/feature_flags.html)可以为您的实例启用它. + +要启用它: + +``` +Feature.enable(:ci_variables_api_filter_environment_scope) +``` + +禁用它: + +``` +Feature.disable(:ci_variables_api_filter_environment_scope) +``` \ No newline at end of file diff --git a/_book/docs/379.md b/_book/docs/379.md new file mode 100644 index 0000000000000000000000000000000000000000..b6410d0b1091e5fb0a46f893d60c55efc2b23a1a --- /dev/null +++ b/_book/docs/379.md @@ -0,0 +1,121 @@ +# Group-level Variables API + +> 原文:[https://docs.gitlab.com/ee/api/group_level_variables.html](https://docs.gitlab.com/ee/api/group_level_variables.html) + +* [List group variables](#list-group-variables) +* [Show variable details](#show-variable-details) +* [Create variable](#create-variable) +* [Update variable](#update-variable) +* [Remove variable](#remove-variable) + +# Group-level Variables API[](#group-level-variables-api "Permalink") + +在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34519) + +## List group variables[](#list-group-variables "Permalink") + +获取组变量的列表. + +``` +GET /groups/:id/variables +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有的组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/variables" +``` + +``` +[ { "key": "TEST_VARIABLE_1", "variable_type": "env_var", "value": "TEST_1", "protected": false, "masked": false }, { "key": "TEST_VARIABLE_2", "variable_type": "env_var", "value": "TEST_2", "protected": false, "masked": false } ] +``` + +## Show variable details[](#show-variable-details "Permalink") + +获取组特定变量的详细信息. + +``` +GET /groups/:id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有的组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/variables/TEST_VARIABLE_1" +``` + +``` +{ "key": "TEST_VARIABLE_1", "variable_type": "env_var", "value": "TEST_1", "protected": false, "masked": false } +``` + +## Create variable[](#create-variable "Permalink") + +创建一个新变量. + +``` +POST /groups/:id/variables +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有的组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` ; 不得超过 255 个字符; 仅允许`AZ` , `az` , `0-9`和`_` | +| `value` | string | yes | 变量的`value` | +| `variable_type` | string | no | 变量的类型. 可用类型为: `env_var` (默认)和`file` | +| `protected` | boolean | no | 变量是否受保护 | +| `masked` | boolean | no | 变量是否被屏蔽 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/variables" --form "key=NEW_VARIABLE" --form "value=new value" +``` + +``` +{ "key": "NEW_VARIABLE", "value": "new value", "variable_type": "env_var", "protected": false, "masked": false } +``` + +## Update variable[](#update-variable "Permalink") + +更新组的变量. + +``` +PUT /groups/:id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有的组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` | +| `value` | string | yes | 变量的`value` | +| `variable_type` | string | no | 变量的类型. 可用类型为: `env_var` (默认)和`file` | +| `protected` | boolean | no | 变量是否受保护 | +| `masked` | boolean | no | 变量是否被屏蔽 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/variables/NEW_VARIABLE" --form "value=updated value" +``` + +``` +{ "key": "NEW_VARIABLE", "value": "updated value", "variable_type": "env_var", "protected": true, "masked": true } +``` + +## Remove variable[](#remove-variable "Permalink") + +删除组的变量. + +``` +DELETE /groups/:id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有的组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/variables/VARIABLE_1" +``` \ No newline at end of file diff --git a/_book/docs/380.md b/_book/docs/380.md new file mode 100644 index 0000000000000000000000000000000000000000..af745d25421b333b1ea5f8634bd8d9ac500f3bf7 --- /dev/null +++ b/_book/docs/380.md @@ -0,0 +1,23 @@ +# Version API + +> 原文:[https://docs.gitlab.com/ee/api/version.html](https://docs.gitlab.com/ee/api/version.html) + +# Version API[](#version-api "Permalink") + +**注意:**此功能是在 GitLab 8.13 中引入的 + +检索此 GitLab 实例的版本信息. 对已认证的用户响应`200 OK` . + +``` +GET /version +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/version" +``` + +响应示例: + +``` +{ "version": "8.13.0-pre", "revision": "4e963fe" } +``` \ No newline at end of file diff --git a/_book/docs/381.md b/_book/docs/381.md new file mode 100644 index 0000000000000000000000000000000000000000..e9b70c80abfc83455648ecb04d09a495c5a03acf --- /dev/null +++ b/_book/docs/381.md @@ -0,0 +1,112 @@ +# Vulnerabilities API + +> 原文:[https://docs.gitlab.com/ee/api/vulnerabilities.html](https://docs.gitlab.com/ee/api/vulnerabilities.html) + +* [Single vulnerability](#single-vulnerability) +* [Confirm vulnerability](#confirm-vulnerability) +* [Resolve vulnerability](#resolve-vulnerability) +* [Dismiss vulnerability](#dismiss-vulnerability) + +# Vulnerabilities API[](#vulnerabilities-api-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10242) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6. + +**注意:**以前的 Vulnerabilities API 已重命名为 Vulnerability Findings API,其文档已移至[其他位置](vulnerability_findings.html) . 现在,本文描述了新的漏洞 API,该 API 提供对[独立漏洞的](https://gitlab.com/groups/gitlab-org/-/epics/634)访问.**警告:**此 API 处于 alpha 阶段,被认为是不稳定的. 响应有效载荷可能会在 GitLab 版本之间发生更改或损坏. + +每个对漏洞的 API 调用都必须经过[身份验证](README.html#authentication) . + +漏洞权限从其项目继承权限. 如果项目是私有项目,并且用户不是该漏洞所属项目的成员,则对该项目的请求将返回`404 Not Found`状态代码. + +## Single vulnerability[](#single-vulnerability "Permalink") + +获得一个漏洞 + +``` +GET /vulnerabilities/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 要获取的漏洞的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/vulnerabilities/1" +``` + +响应示例: + +``` +{ "id": 1, "title": "Predictable pseudorandom number generator", "description": null, "state": "opened", "severity": "medium", "confidence": "medium", "report_type": "sast", "project": { "id": 32, "name": "security-reports", "full_path": "/gitlab-examples/security/security-reports", "full_name": "gitlab-examples / security / security-reports" }, "author_id": 1, "updated_by_id": null, "last_edited_by_id": null, "closed_by_id": null, "start_date": null, "due_date": null, "created_at": "2019-10-13T15:08:40.219Z", "updated_at": "2019-10-13T15:09:40.382Z", "last_edited_at": null, "closed_at": null } +``` + +## Confirm vulnerability[](#confirm-vulnerability "Permalink") + +确认给定漏洞. 如果已经确认该漏洞,则返回状态码`304` . + +如果经过身份验证的用户无权[确认漏洞](../user/permissions.html#project-members-permissions) ,则此请求将导致`403`状态代码. + +``` +POST /vulnerabilities/:id/confirm +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 确认漏洞的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/vulnerabilities/5/confirm" +``` + +响应示例: + +``` +{ "id": 2, "title": "Predictable pseudorandom number generator", "description": null, "state": "confirmed", "severity": "medium", "confidence": "medium", "report_type": "sast", "project": { "id": 32, "name": "security-reports", "full_path": "/gitlab-examples/security/security-reports", "full_name": "gitlab-examples / security / security-reports" }, "author_id": 1, "updated_by_id": null, "last_edited_by_id": null, "closed_by_id": null, "start_date": null, "due_date": null, "created_at": "2019-10-13T15:08:40.219Z", "updated_at": "2019-10-13T15:09:40.382Z", "last_edited_at": null, "closed_at": null } +``` + +## Resolve vulnerability[](#resolve-vulnerability "Permalink") + +解决给定漏洞. 如果漏洞已解决,则返回状态码`304` . + +如果经过身份验证的用户无权[解决漏洞](../user/permissions.html#project-members-permissions) ,则此请求将导致`403`状态代码. + +``` +POST /vulnerabilities/:id/resolve +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 解决的漏洞的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/vulnerabilities/5/resolve" +``` + +响应示例: + +``` +{ "id": 2, "title": "Predictable pseudorandom number generator", "description": null, "state": "resolved", "severity": "medium", "confidence": "medium", "report_type": "sast", "project": { "id": 32, "name": "security-reports", "full_path": "/gitlab-examples/security/security-reports", "full_name": "gitlab-examples / security / security-reports" }, "author_id": 1, "updated_by_id": null, "last_edited_by_id": null, "closed_by_id": null, "start_date": null, "due_date": null, "created_at": "2019-10-13T15:08:40.219Z", "updated_at": "2019-10-13T15:09:40.382Z", "last_edited_at": null, "closed_at": null } +``` + +## Dismiss vulnerability[](#dismiss-vulnerability "Permalink") + +消除给定的漏洞. 如果漏洞已被`304`则返回状态码`304` . + +If an authenticated user does not have permission to [dismiss vulnerabilities](../user/permissions.html#project-members-permissions), this request will result in a `403` status code. + +``` +POST /vulnerabilities/:id/dismiss +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 消除漏洞的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/vulnerabilities/5/dismiss" +``` + +响应示例: + +``` +{ "id": 2, "title": "Predictable pseudorandom number generator", "description": null, "state": "closed", "severity": "medium", "confidence": "medium", "report_type": "sast", "project": { "id": 32, "name": "security-reports", "full_path": "/gitlab-examples/security/security-reports", "full_name": "gitlab-examples / security / security-reports" }, "author_id": 1, "updated_by_id": null, "last_edited_by_id": null, "closed_by_id": null, "start_date": null, "due_date": null, "created_at": "2019-10-13T15:08:40.219Z", "updated_at": "2019-10-13T15:09:40.382Z", "last_edited_at": null, "closed_at": null } +``` \ No newline at end of file diff --git a/_book/docs/382.md b/_book/docs/382.md new file mode 100644 index 0000000000000000000000000000000000000000..e7acf908a72a714b3fa2844bc28380fcbd03082b --- /dev/null +++ b/_book/docs/382.md @@ -0,0 +1,65 @@ +# Vulnerability Findings API + +> 原文:[https://docs.gitlab.com/ee/api/vulnerability_findings.html](https://docs.gitlab.com/ee/api/vulnerability_findings.html) + +* [Vulnerability findings pagination](#vulnerability-findings-pagination) +* [List project vulnerability findings](#list-project-vulnerability-findings) + +# Vulnerability Findings API[](#vulnerability-findings-api-ultimate "Permalink") + +在 GitLab Ultimate 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19029) . + +**注意:**此 API 资源已从"漏洞"重命名为"漏洞发现",因为这些漏洞是为服务即将到来的[独立漏洞对象](https://gitlab.com/gitlab-org/gitlab/-/issues/13561)而保留的. 要修复与以前的 Vulnerabilities API 的任何损坏的集成,请将`vulnerabilities` URL 部分更改为`vulnerabilities` _ `vulnerability_findings` . + +每个对漏洞发现的 API 调用都必须经过[身份验证](README.html#authentication) . + +漏洞发现是项目约束的实体. 如果用户不是项目成员,并且该项目是私有项目,则对该项目的请求将产生`404`状态代码. + +如果用户能够访问该项目但无权[使用 Project Security 仪表板](../user/permissions.html#project-members-permissions) ,则任何对此项目的漏洞发现的请求都将生成`403`状态代码. + +**警告:**此 API 处于 alpha 阶段,被认为是不稳定的. 响应有效载荷可能会在 GitLab 版本之间发生更改或损坏. + +## Vulnerability findings pagination[](#vulnerability-findings-pagination "Permalink") + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +## List project vulnerability findings[](#list-project-vulnerability-findings "Permalink") + +列出项目的所有漏洞发现. + +``` +GET /projects/:id/vulnerability_findings +GET /projects/:id/vulnerability_findings?report_type=sast +GET /projects/:id/vulnerability_findings?report_type=container_scanning +GET /projects/:id/vulnerability_findings?report_type=sast,dast +GET /projects/:id/vulnerability_findings?scope=all +GET /projects/:id/vulnerability_findings?scope=dismissed +GET /projects/:id/vulnerability_findings?severity=high +GET /projects/:id/vulnerability_findings?confidence=unknown,experimental +GET /projects/:id/vulnerability_findings?scanner=bandit,find_sec_bugs +GET /projects/:id/vulnerability_findings?pipeline_id=42 +``` + +**弃用:**从 GitLab 12.9 开始,不再报告`undefined`严重性和可信度级别. + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户[所属的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `report_type` | 字符串数组 | no | 返回属于指定报告类型的漏洞发现. 有效值: `sast` , `dast` , `dependency_scanning`或`container_scanning` . 默认为全部. | +| `scope` | string | no | 返回给定范围内的漏洞发现结果: `all`或已`dismissed` . 默认为`dismissed` . | +| `severity` | 字符串数组 | no | 返回属于指定严重性级别的漏洞发现: `info` , `unknown` , `low` , `medium` , `high`或`critical` . 默认为全部. | +| `confidence` | 字符串数组 | no | 返回属于指定置信度的漏洞发现: `ignore` , `unknown` , `experimental` , `low` , `medium` , `high`或`confirmed` . 默认为全部. | +| `scanner` | 字符串数组 | no | 返回指定扫描程序检测到的漏洞发现. | +| `pipeline_id` | integer/string | no | 返回属于指定管道的漏洞发现. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/vulnerability_findings" +``` + +Example response: + +``` +[ { "id": null, "report_type": "dependency_scanning", "name": "Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js", "severity": "unknown", "confidence": "undefined", "scanner": { "external_id": "gemnasium", "name": "Gemnasium" }, "identifiers": [ { "external_type": "gemnasium", "external_id": "9952e574-7b5b-46fa-a270-aeb694198a98", "name": "Gemnasium-9952e574-7b5b-46fa-a270-aeb694198a98", "url": "https://deps.sec.gitlab.com/packages/npm/saml2-js/versions/1.5.0/advisories" }, { "external_type": "cve", "external_id": "CVE-2017-11429", "name": "CVE-2017-11429", "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429" } ], "project_fingerprint": "fa6f5b6c5d240b834ac5e901dc69f9484cef89ec", "create_vulnerability_feedback_issue_path": "/tests/yarn-remediation-test/vulnerability_feedback", "create_vulnerability_feedback_merge_request_path": "/tests/yarn-remediation-test/vulnerability_feedback", "create_vulnerability_feedback_dismissal_path": "/tests/yarn-remediation-test/vulnerability_feedback", "project": { "id": 31, "name": "yarn-remediation-test", "full_path": "/tests/yarn-remediation-test", "full_name": "tests / yarn-remediation-test" }, "dismissal_feedback": null, "issue_feedback": null, "merge_request_feedback": null, "description": "Some XML DOM traversal and canonicalization APIs may be inconsistent in handling of comments within XML nodes. Incorrect use of these APIs by some SAML libraries results in incorrect parsing of the inner text of XML nodes such that any inner text after the comment is lost prior to cryptographically signing the SAML message. Text after the comment therefore has no impact on the signature on the SAML message.\r\n\r\nA remote attacker can modify SAML content for a SAML service provider without invalidating the cryptographic signature, which may allow attackers to bypass primary authentication for the affected SAML service provider.", "links": [ { "url": "https://github.com/Clever/saml2/commit/3546cb61fd541f219abda364c5b919633609ef3d#diff-af730f9f738de1c9ad87596df3f6de84R279" }, { "url": "https://www.kb.cert.org/vuls/id/475445" }, { "url": "https://github.com/Clever/saml2/issues/127" } ], "location": { "file": "yarn.lock", "dependency": { "package": { "name": "saml2-js" }, "version": "1.5.0" } }, "solution": "Upgrade to fixed version.\r\n", "blob_path": "/tests/yarn-remediation-test/blob/cc6c4a0778460455ae5d16ca7025ca9ca1ca75ac/yarn.lock" } ] +``` \ No newline at end of file diff --git a/_book/docs/383.md b/_book/docs/383.md new file mode 100644 index 0000000000000000000000000000000000000000..6dd92f491b4727c6702594a3dfce815b8cbdfe6f --- /dev/null +++ b/_book/docs/383.md @@ -0,0 +1,158 @@ +# Wikis API + +> 原文:[https://docs.gitlab.com/ee/api/wikis.html](https://docs.gitlab.com/ee/api/wikis.html) + +* [List wiki pages](#list-wiki-pages) +* [Get a wiki page](#get-a-wiki-page) +* [Create a new wiki page](#create-a-new-wiki-page) +* [Edit an existing wiki page](#edit-an-existing-wiki-page) +* [Delete a wiki page](#delete-a-wiki-page) +* [Upload an attachment to the wiki repository](#upload-an-attachment-to-the-wiki-repository) + +# Wikis API[](#wikis-api "Permalink") + +在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13372) . + +仅在 APIv4 中可用. + +## List wiki pages[](#list-wiki-pages "Permalink") + +获取给定项目的所有 Wiki 页面. + +``` +GET /projects/:id/wikis +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `with_content` | boolean | no | 包含页面内容 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/wikis?with_content=1" +``` + +响应示例: + +``` +[ { "content" : "Here is an instruction how to deploy this project.", "format" : "markdown", "slug" : "deploy", "title" : "deploy" }, { "content" : "Our development process is described here.", "format" : "markdown", "slug" : "development", "title" : "development" },{ "content" : "* [Deploy](deploy)\n* [Development](development)", "format" : "markdown", "slug" : "home", "title" : "home" } ] +``` + +## Get a wiki page[](#get-a-wiki-page "Permalink") + +获取给定项目的 Wiki 页面. + +``` +GET /projects/:id/wikis/:slug +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `slug` | string | yes | Wiki 页面的段(唯一字符串) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/wikis/home" +``` + +响应示例: + +``` +{ "content" : "home page", "format" : "markdown", "slug" : "home", "title" : "home" } +``` + +## Create a new wiki page[](#create-a-new-wiki-page "Permalink") + +使用给定的标题,条目和内容为给定的存储库创建一个新的 Wiki 页面. + +``` +POST /projects/:id/wikis +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `content` | string | yes | Wiki 页面的内容 | +| `title` | string | yes | 维基页面的标题 | +| `format` | string | no | Wiki 页面的格式. 可用格式为: `markdown` (默认), `rdoc` , `asciidoc`和`org` | + +``` +curl --data "format=rdoc&title=Hello&content=Hello world" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/wikis" +``` + +响应示例: + +``` +{ "content" : "Hello world", "format" : "markdown", "slug" : "Hello", "title" : "Hello" } +``` + +## Edit an existing wiki page[](#edit-an-existing-wiki-page "Permalink") + +更新现有的 Wiki 页面. 至少需要一个参数才能更新 Wiki 页面. + +``` +PUT /projects/:id/wikis/:slug +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `content` | string | 是,如果未提供`title` | Wiki 页面的内容 | +| `title` | string | 是,如果未提供`content` | 维基页面的标题 | +| `format` | string | no | Wiki 页面的格式. 可用格式为: `markdown` (默认), `rdoc` , `asciidoc`和`org` | +| `slug` | string | yes | Wiki 页面的段(唯一字符串) | + +``` +curl --request PUT --data "format=rdoc&content=documentation&title=Docs" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/wikis/foo" +``` + +响应示例: + +``` +{ "content" : "documentation", "format" : "markdown", "slug" : "Docs", "title" : "Docs" } +``` + +## Delete a wiki page[](#delete-a-wiki-page "Permalink") + +删除带有给定子弹的 Wiki 页面. + +``` +DELETE /projects/:id/wikis/:slug +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `slug` | string | yes | Wiki 页面的段(唯一字符串) | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/wikis/foo" +``` + +成功时,HTTP 状态代码为`204`并且不需要 JSON 响应. + +## Upload an attachment to the wiki repository[](#upload-an-attachment-to-the-wiki-repository "Permalink") + +将文件上传到 Wiki 信息库中的附件文件夹. 附件文件夹是`uploads`文件夹. + +``` +POST /projects/:id/wikis/attachments +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `file` | string | yes | 要上传的附件 | +| `branch` | string | no | 分支的名称. 默认为 Wiki 存储库默认分支 | + +要从文件系统上载文件,请使用`--form`参数. 这将导致 cURL 使用标题`Content-Type: multipart/form-data` . `file=`参数必须指向文件系统上的文件,并以`@`开头. 例如: + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "file=@dk.png" "https://gitlab.example.com/api/v4/projects/1/wikis/attachments" +``` + +响应示例: + +``` +{ "file_name" : "dk.png", "file_path" : "uploads/6a061c4cf9f1c28cb22c384b4b8d4e3c/dk.png", "branch" : "master", "link" : { "url" : "uploads/6a061c4cf9f1c28cb22c384b4b8d4e3c/dk.png", "markdown" : "![dk](uploads/6a061c4cf9f1c28cb22c384b4b8d4e3c/dk.png)" } } +``` \ No newline at end of file diff --git a/_book/docs/384.md b/_book/docs/384.md new file mode 100644 index 0000000000000000000000000000000000000000..d23f9437ea12cbd583049696fe92155b3dde10a9 --- /dev/null +++ b/_book/docs/384.md @@ -0,0 +1,83 @@ +# GraphQL API + +> 原文:[https://docs.gitlab.com/ee/api/graphql/](https://docs.gitlab.com/ee/api/graphql/) + +* [Getting Started](#getting-started) + * [Quick Reference](#quick-reference) + * [GraphiQL](#graphiql) +* [What is GraphQL?](#what-is-graphql) +* [Vision](#vision) +* [Available queries](#available-queries) + * [Multiplex queries](#multiplex-queries) +* [Reference](#reference) + +# GraphQL API[](#graphql-api "Permalink") + +版本历史 + +* 在 GitLab 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19008) (由功能标志`graphql`启用). +* [始终](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30444)在 GitLab 12.1 中[启用](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30444) . + +## Getting Started[](#getting-started "Permalink") + +有关 GitLab GraphQL API 的新知识,请参见 GitLab GraphQL API [入门](getting_started.html) . + +### Quick Reference[](#quick-reference "Permalink") + +* GitLab 的 GraphQL API 端点位于`/api/graphql` . +* [从 graphql.org](https://s0graphql0org.icopy.site/)获得[GraphQL 的简介](https://s0graphql0org.icopy.site/) . +* GitLab 支持广泛的资源,在[GraphQL API Reference 中](reference/index.html)列出. + +#### GraphiQL[](#graphiql "Permalink") + +使用交互式[GraphiQL](https://gitlab.com/-/graphql-explorer)浏览器浏览 GraphQL API,或在`https:///-/graphql-explorer`上的自管理 GitLab 实例上`https:///-/graphql-explorer` . + +有关 GraphiQL Explorer 的更多信息,请参见[GitLab GraphQL 概述](getting_started.html#graphiql) . + +## What is GraphQL?[](#what-is-graphql "Permalink") + +[GraphQL](https://s0graphql0org.icopy.site/)是 API 的查询语言,它允许客户端准确地请求他们所需的数据,从而有可能在有限数量的请求中获得所有必需的数据. + +可以以类型的形式描述 GraphQL 数据(字段),从而允许客户端使用[客户端 GraphQL 库](https://s0graphql0org.icopy.site/code/)来使用 API​​并避免手动解析. + +由于没有固定的端点和数据模型,因此可以在不进行重大更改的情况下将新功能添加到 API. 这使我们可以拥有[GraphQL 文档](https://s0graphql0org.icopy.site/learn/best-practices/)中[所述的无](https://s0graphql0org.icopy.site/learn/best-practices/)版本 API. + +## Vision[](#vision "Permalink") + +我们希望 GraphQL API 是与 GitLab 进行编程交互的**主要**方式. 为此,它需要全面覆盖-REST API 中可能的一切在 GraphQL API 中也应该可行. + +为了帮助我们实现这一愿景,前端应优先使用 GraphQL 而不是 REST API 的新功能. + +There are no plans to deprecate the REST API. To reduce the technical burden of supporting two APIs in parallel, they should share implementations as much as possible. + +## Available queries[](#available-queries "Permalink") + +GraphQL API 在根级别包含以下查询: + +1. `project` :项目信息及其许多关联,例如问题和合并请求. +2. `group` :基本组信息和史诗 目前受支持. +3. `user` :有关特定用户的信息. +4. `namespace` :在名称空间内,也可以提取`projects` . +5. `currentUser` :有关当前登录用户的信息. +6. `users` :有关用户集合的信息. +7. `metaData` :有关 GitLab 和 GraphQL API 的元数据. +8. `snippets` :当前登录用户可见的`snippets` . + +新的关联和根级别对象正在不断添加. 有关最新信息,请参见《 [GraphQL API 参考](reference/index.html) 》. + +根级查询在[`app/graphql/types/query_type.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/graphql/types/query_type.rb) . + +### Multiplex queries[](#multiplex-queries "Permalink") + +GitLab 支持使用[apollo-link-batch-http 将](https://www.apollographql.com/docs/link/links/batch-http/)查询批量处理为单个请求. GitLab 在后端使用的库[GraphQL Ruby](https://graphql-ruby.org/queries/multiplex.html)也提供了有关多路查询的更多信息. + +## Reference[](#reference "Permalink") + +GitLab 的 GraphQL 参考[可用](reference/index.html) . + +它是从 GitLab 的 GraphQL 模式自动生成的,并嵌入到 Markdown 文件中. + +机器可读版本也可用: + +* [JSON format](reference/gitlab_schema.json) +* [IDL format](reference/gitlab_schema.graphql) \ No newline at end of file diff --git a/_book/docs/385.md b/_book/docs/385.md new file mode 100644 index 0000000000000000000000000000000000000000..73759a09113438879de555180bc62a17f195f1ea --- /dev/null +++ b/_book/docs/385.md @@ -0,0 +1,203 @@ +# Getting started with GitLab GraphQL API + +> 原文:[https://docs.gitlab.com/ee/api/graphql/getting_started.html](https://docs.gitlab.com/ee/api/graphql/getting_started.html) + +* [Running examples](#running-examples) + * [Command line](#command-line) + * [GraphiQL](#graphiql) +* [Queries and mutations](#queries-and-mutations) + * [Graph traversal](#graph-traversal) + * [Authorization](#authorization) + * [Mutations](#mutations) + * [Creation mutations](#creation-mutations) + * [Update mutations](#update-mutations) + * [Deletion mutations](#deletion-mutations) + * [Introspective queries](#introspective-queries) +* [Sorting](#sorting) +* [Pagination](#pagination) + +# Getting started with GitLab GraphQL API[](#getting-started-with-gitlab-graphql-api "Permalink") + +本指南演示了 GitLab 的 GraphQL API 的基本用法. + +请参见[GraphQL API 样式指南,](../../development/api_graphql_styleguide.html)以了解针对希望开发 API 本身的开发人员的实现细节. + +## Running examples[](#running-examples "Permalink") + +此处记录的示例可以使用以下命令运行: + +* 命令行. +* GraphiQL. + +### Command line[](#command-line "Permalink") + +您可以在本地计算机上的命令行中的`curl`请求中运行 GraphQL 查询. 可以将 GraphQL 请求作为对`/api/graphql`的`POST`请求,并将查询作为有效负载. 您可以通过生成[个人访问令牌](../../user/profile/personal_access_tokens.html)以用作承载令牌来授权您的请求. + +Example: + +``` +GRAPHQL_TOKEN= +curl 'https://gitlab.com/api/graphql' --header "Authorization: Bearer $GRAPHQL_TOKEN" --header "Content-Type: application/json" --request POST --data "{\"query\": \"query {currentUser {name}}\"}" +``` + +### GraphiQL[](#graphiql "Permalink") + +GraphiQL(发音为"图形")允许您使用语法突出显示和自动完成功能直接针对服务器端点运行查询. 它还允许您探索模式和类型. + +下面的例子: + +* 可以直接在 GitLab 11.0 或更高版本上运行,尽管某些类型和字段在较早的版本中可能不受支持. +* 无需任何进一步设置即可在 GitLab.com 上运行. 确保您已登录并导航到[GraphiQL Explorer](https://gitlab.com/-/graphql-explorer) . + +如果要在本地或在自管实例上运行查询,则需要执行以下任一操作: + +* 创建`gitlab-org`组,并在其下创建一个名为`graphql-sandbox`的项目. 在项目中创建多个问题. +* 编辑查询以将`gitlab-org/graphql-sandbox`替换为您自己的组和项目. + +有关更多信息,请参考[运行 GraphiQL](index.html#graphiql) . + +**注意:**如果您正在运行 GitLab 11.0 到 12.0,请启用`graphql` [功能标记](../features.html#set-or-create-a-feature) . + +## Queries and mutations[](#queries-and-mutations "Permalink") + +GitLab GraphQL API 可用于执行: + +* 数据检索查询. +* 用于创建,更新和删除数据的[突变](#mutations) . + +**注意:**在 GitLab GraphQL API 中, `id`通常是指全局 ID,它是对象标识符,格式为`gid://gitlab/Issue/123` . + +[GitLab 的 GraphQL Schema](reference/index.html)概述了哪些对象和字段可供客户端查询以及它们对应的数据类型. + +示例:在`gitlab-org`组中,仅获取当前登录用户可以访问的所有项目的名称(最大限制,稍后再介绍). + +``` +query { group(fullPath: "gitlab-org") { id name projects { nodes { name } } } } +``` + +示例:获得一个特定的项目和标题#2. + +``` +query { project(fullPath: "gitlab-org/graphql-sandbox") { name issue(iid: "2") { title } } } +``` + +### Graph traversal[](#graph-traversal "Permalink") + +检索子节点时,请使用: + +* the `edges { node { } }` syntax. +* 缩写形式`nodes { }`语法. + +在它的下面是一个我们正在遍历的图,因此命名为 GraphQL. + +示例:获得一个项目(仅名称)及其所有期刊的标题. + +``` +query { project(fullPath: "gitlab-org/graphql-sandbox") { name issues { nodes { title description } } } } +``` + +有关查询的更多信息: [GraphQL 文档](https://s0graphql0org.icopy.site/learn/queries/) + +### Authorization[](#authorization "Permalink") + +授权使用与 GitLab 应用程序(和 GitLab.com)相同的引擎. 因此,如果您已经登录到 GitLab 并使用 GraphiQL,则所有查询都将以您(登录用户)的身份执行. 有关更多信息,请参见[GitLab API 文档](../README.html#authentication) . + +### Mutations[](#mutations "Permalink") + +变异会改变数据. 我们可以更新,删除或创建新记录. 变异通常使用 InputTypes 和变量,在此都不会出现. + +变异有: + +* 输入. 例如,参数,例如您想要授予的表情符号以及对象. +* 返回语句. 也就是说,成功后您希望获得什么. +* 错误. 总是问出什么问题了,以防万一. + +#### Creation mutations[](#creation-mutations "Permalink") + +示例:让我们喝点茶-在问题中添加`:tea:`反应表情符号. + +``` +mutation { awardEmojiAdd(input: { awardableId: "gid://gitlab/Issue/27039960", name: "tea" }) { awardEmoji { name description unicode emoji unicodeVersion user { name } } errors } } +``` + +示例:在问题上添加评论(我们使用的是`GitLab.com`问题的 ID,但是如果您使用的是本地实例,则需要获取可以写入的问题的 ID). + +``` +mutation { createNote(input: { noteableId: "gid://gitlab/Issue/27039960", body: "*sips tea*" }) { note { id body discussion { id } } errors } } +``` + +#### Update mutations[](#update-mutations "Permalink") + +当您看到创建的注释的结果`id`时,请记下它. 现在,让我们对其进行编辑以更快地 ip 饮! + +``` +mutation { updateNote(input: { id: "gid://gitlab/Note/", body: "*SIPS TEA*" }) { note { id body } errors } } +``` + +#### Deletion mutations[](#deletion-mutations "Permalink") + +让我们删除评论,因为我们的茶都没了. + +``` +mutation { destroyNote(input: { id: "gid://gitlab/Note/" }) { note { id body } errors } } +``` + +您应该得到类似以下输出的内容: + +``` +{ "data": { "destroyNote": { "errors": [], "note": null } } } +``` + +我们已经要求提供注释的详细信息,但是它不再存在,因此我们得到`null` . + +有关突变的更多信息: [GraphQL Docs](https://s0graphql0org.icopy.site/learn/queries/) . + +### Introspective queries[](#introspective-queries "Permalink") + +客户端可以查询 GraphQL 端点以获取有关其自身架构的信息. 通过进行[内省性查询](https://s0graphql0org.icopy.site/learn/introspection/) . + +通过自省查询, [GraphiQL 查询资源管理器](https://gitlab.com/-/graphql-explorer)获得了有关我们的 GraphQL 模式的所有知识,以执行自动补全并提供其交互式`Docs`选项卡. + +示例:获取架构中的所有类型名称. + +``` +{ __schema { types { name } } } +``` + +示例:获取与 Issue 相关的所有字段. `kind`告诉我们该类型的枚举值,例如`OBJECT` , `SCALAR`或`INTERFACE` . + +``` +query IssueTypes { __type(name: "Issue") { kind name fields { name description type { name } } } } +``` + +有关自省的更多信息: [GraphQL 文档](https://s0graphql0org.icopy.site/learn/introspection/) + +## Sorting[](#sorting "Permalink") + +GitLab 的一些 GraphQL 端点允许您指定想要对对象集合进行排序的方式. 您只能按架构允许的排序. + +示例:可以按创建日期对问题进行排序: + +``` +query { project(fullPath: "gitlab-org/graphql-sandbox") { name issues(sort: created_asc) { nodes { title createdAt } } } } +``` + +## Pagination[](#pagination "Permalink") + +分页是仅询问记录子集(例如前 10 个)的一种方法. 如果我们想要更多,我们可以从服务器再次请求下 10 条记录(例如"请给我下 10 条记录"). + +默认情况下,GitLab 的 GraphQL API 将仅返回任何集合的前 100 条记录. 可以使用`first`或`last`参数来更改. 这两个参数都有一个值,因此`first: 10`将返回前 10 条记录, `last: 10`将最后 10 条记录. + +示例:仅检索前两个问题(切片). `cursor`字段为我们提供了一个位置,从中可以检索相对于该位置的其他记录. + +``` +query { project(fullPath: "gitlab-org/graphql-sandbox") { name issues(first: 2) { edges { node { title } } pageInfo { endCursor hasNextPage } } } } +``` + +示例:检索下一个 3.(游标值`eyJpZCI6IjI3MDM4OTMzIiwiY3JlYXRlZF9hdCI6IjIwMTktMTEtMTQgMDU6NTY6NDQgVVRDIn0`可能有所不同,但它是上面返回的第二个问题返回的`cursor`值.) + +``` +query { project(fullPath: "gitlab-org/graphql-sandbox") { name issues(first: 3, after: "eyJpZCI6IjI3MDM4OTMzIiwiY3JlYXRlZF9hdCI6IjIwMTktMTEtMTQgMDU6NTY6NDQgVVRDIn0") { edges { node { title } cursor } pageInfo { endCursor hasNextPage } } } } +``` + +有关分页和游标的更多信息: [GraphQL 文档](https://s0graphql0org.icopy.site/learn/pagination/) \ No newline at end of file diff --git a/_book/docs/386.md b/_book/docs/386.md new file mode 100644 index 0000000000000000000000000000000000000000..02674e78ac009e07067101b1c52c47407c3e3168 --- /dev/null +++ b/_book/docs/386.md @@ -0,0 +1,2524 @@ +# GraphQL API Resources + +> 原文:[https://docs.gitlab.com/ee/api/graphql/reference/](https://docs.gitlab.com/ee/api/graphql/reference/) + +* [AccessLevel](#accesslevel) +* [AddAwardEmojiPayload](#addawardemojipayload) +* [AddProjectToSecurityDashboardPayload](#addprojecttosecuritydashboardpayload) +* [AdminSidekiqQueuesDeleteJobsPayload](#adminsidekiqqueuesdeletejobspayload) +* [AlertManagementAlert](#alertmanagementalert) +* [AlertManagementAlertStatusCountsType](#alertmanagementalertstatuscountstype) +* [AlertSetAssigneesPayload](#alertsetassigneespayload) +* [AlertTodoCreatePayload](#alerttodocreatepayload) +* [AwardEmoji](#awardemoji) +* [AwardEmojiAddPayload](#awardemojiaddpayload) +* [AwardEmojiRemovePayload](#awardemojiremovepayload) +* [AwardEmojiTogglePayload](#awardemojitogglepayload) +* [BaseService](#baseservice) +* [Blob](#blob) +* [Board](#board) +* [BoardList](#boardlist) +* [BoardListUpdateLimitMetricsPayload](#boardlistupdatelimitmetricspayload) +* [Branch](#branch) +* [Commit](#commit) +* [CommitCreatePayload](#commitcreatepayload) +* [ComplianceFramework](#complianceframework) +* [ContainerExpirationPolicy](#containerexpirationpolicy) +* [CreateAlertIssuePayload](#createalertissuepayload) +* [CreateAnnotationPayload](#createannotationpayload) +* [CreateBranchPayload](#createbranchpayload) +* [CreateDiffNotePayload](#creatediffnotepayload) +* [CreateEpicPayload](#createepicpayload) +* [CreateImageDiffNotePayload](#createimagediffnotepayload) +* [CreateIterationPayload](#createiterationpayload) +* [CreateNotePayload](#createnotepayload) +* [CreateRequirementPayload](#createrequirementpayload) +* [CreateSnippetPayload](#createsnippetpayload) +* [DastSiteProfileCreatePayload](#dastsiteprofilecreatepayload) +* [DeleteAnnotationPayload](#deleteannotationpayload) +* [DeleteJobsResponse](#deletejobsresponse) +* [Design](#design) +* [DesignAtVersion](#designatversion) +* [DesignCollection](#designcollection) +* [DesignManagement](#designmanagement) +* [DesignManagementDeletePayload](#designmanagementdeletepayload) +* [DesignManagementUploadPayload](#designmanagementuploadpayload) +* [DesignVersion](#designversion) +* [DestroyNotePayload](#destroynotepayload) +* [DestroySnippetPayload](#destroysnippetpayload) +* [DetailedStatus](#detailedstatus) +* [DiffPosition](#diffposition) +* [DiffRefs](#diffrefs) +* [DiffStats](#diffstats) +* [DiffStatsSummary](#diffstatssummary) +* [Discussion](#discussion) +* [DiscussionToggleResolvePayload](#discussiontoggleresolvepayload) +* [DismissVulnerabilityPayload](#dismissvulnerabilitypayload) +* [Environment](#environment) +* [Epic](#epic) +* [EpicAddIssuePayload](#epicaddissuepayload) +* [EpicDescendantCount](#epicdescendantcount) +* [EpicDescendantWeights](#epicdescendantweights) +* [EpicHealthStatus](#epichealthstatus) +* [EpicIssue](#epicissue) +* [EpicPermissions](#epicpermissions) +* [EpicSetSubscriptionPayload](#epicsetsubscriptionpayload) +* [EpicTreeReorderPayload](#epictreereorderpayload) +* [GeoNode](#geonode) +* [GrafanaIntegration](#grafanaintegration) +* [Group](#group) +* [GroupMember](#groupmember) +* [GroupPermissions](#grouppermissions) +* [Issue](#issue) +* [IssuePermissions](#issuepermissions) +* [IssueSetConfidentialPayload](#issuesetconfidentialpayload) +* [IssueSetDueDatePayload](#issuesetduedatepayload) +* [IssueSetIterationPayload](#issuesetiterationpayload) +* [IssueSetLockedPayload](#issuesetlockedpayload) +* [IssueSetWeightPayload](#issuesetweightpayload) +* [Iteration](#iteration) +* [JiraImport](#jiraimport) +* [JiraImportStartPayload](#jiraimportstartpayload) +* [JiraImportUsersPayload](#jiraimportuserspayload) +* [JiraProject](#jiraproject) +* [JiraService](#jiraservice) +* [JiraUser](#jirauser) +* [Label](#label) +* [MarkAsSpamSnippetPayload](#markasspamsnippetpayload) +* [MergeRequest](#mergerequest) +* [MergeRequestCreatePayload](#mergerequestcreatepayload) +* [MergeRequestPermissions](#mergerequestpermissions) +* [MergeRequestSetAssigneesPayload](#mergerequestsetassigneespayload) +* [MergeRequestSetLabelsPayload](#mergerequestsetlabelspayload) +* [MergeRequestSetLockedPayload](#mergerequestsetlockedpayload) +* [MergeRequestSetMilestonePayload](#mergerequestsetmilestonepayload) +* [MergeRequestSetSubscriptionPayload](#mergerequestsetsubscriptionpayload) +* [MergeRequestSetWipPayload](#mergerequestsetwippayload) +* [MergeRequestUpdatePayload](#mergerequestupdatepayload) +* [Metadata](#metadata) +* [MetricsDashboard](#metricsdashboard) +* [MetricsDashboardAnnotation](#metricsdashboardannotation) +* [Milestone](#milestone) +* [MilestoneStats](#milestonestats) +* [Namespace](#namespace) +* [Note](#note) +* [NotePermissions](#notepermissions) +* [Package](#package) +* [PackageFileRegistry](#packagefileregistry) +* [PageInfo](#pageinfo) +* [Pipeline](#pipeline) +* [PipelinePermissions](#pipelinepermissions) +* [Project](#project) +* [ProjectMember](#projectmember) +* [ProjectPermissions](#projectpermissions) +* [ProjectStatistics](#projectstatistics) +* [Release](#release) +* [ReleaseAssetLink](#releaseassetlink) +* [ReleaseAssets](#releaseassets) +* [ReleaseEvidence](#releaseevidence) +* [ReleaseLinks](#releaselinks) +* [ReleaseSource](#releasesource) +* [RemoveAwardEmojiPayload](#removeawardemojipayload) +* [RemoveProjectFromSecurityDashboardPayload](#removeprojectfromsecuritydashboardpayload) +* [Repository](#repository) +* [Requirement](#requirement) +* [RequirementPermissions](#requirementpermissions) +* [RequirementStatesCount](#requirementstatescount) +* [RootStorageStatistics](#rootstoragestatistics) +* [RunDASTScanPayload](#rundastscanpayload) +* [SastCiConfigurationAnalyzersEntity](#sastciconfigurationanalyzersentity) +* [SastCiConfigurationEntity](#sastciconfigurationentity) +* [SastCiConfigurationOptionsEntity](#sastciconfigurationoptionsentity) +* [ScannedResource](#scannedresource) +* [SecurityReportSummary](#securityreportsummary) +* [SecurityReportSummarySection](#securityreportsummarysection) +* [SecurityScanners](#securityscanners) +* [SentryDetailedError](#sentrydetailederror) +* [SentryError](#sentryerror) +* [SentryErrorCollection](#sentryerrorcollection) +* [SentryErrorFrequency](#sentryerrorfrequency) +* [SentryErrorStackTrace](#sentryerrorstacktrace) +* [SentryErrorStackTraceContext](#sentryerrorstacktracecontext) +* [SentryErrorStackTraceEntry](#sentryerrorstacktraceentry) +* [SentryErrorTags](#sentryerrortags) +* [Snippet](#snippet) +* [SnippetBlob](#snippetblob) +* [SnippetBlobViewer](#snippetblobviewer) +* [SnippetPermissions](#snippetpermissions) +* [Submodule](#submodule) +* [TaskCompletionStatus](#taskcompletionstatus) +* [TestReport](#testreport) +* [Timelog](#timelog) +* [Todo](#todo) +* [TodoMarkDonePayload](#todomarkdonepayload) +* [TodoRestoreManyPayload](#todorestoremanypayload) +* [TodoRestorePayload](#todorestorepayload) +* [TodosMarkAllDonePayload](#todosmarkalldonepayload) +* [ToggleAwardEmojiPayload](#toggleawardemojipayload) +* [Tree](#tree) +* [TreeEntry](#treeentry) +* [UpdateAlertStatusPayload](#updatealertstatuspayload) +* [UpdateContainerExpirationPolicyPayload](#updatecontainerexpirationpolicypayload) +* [UpdateEpicPayload](#updateepicpayload) +* [UpdateImageDiffNotePayload](#updateimagediffnotepayload) +* [UpdateIssuePayload](#updateissuepayload) +* [UpdateIterationPayload](#updateiterationpayload) +* [UpdateNotePayload](#updatenotepayload) +* [UpdateRequirementPayload](#updaterequirementpayload) +* [UpdateSnippetPayload](#updatesnippetpayload) +* [User](#user) +* [UserPermissions](#userpermissions) +* [VulnerabilitiesCountByDayAndSeverity](#vulnerabilitiescountbydayandseverity) +* [Vulnerability](#vulnerability) +* [VulnerabilityIdentifier](#vulnerabilityidentifier) +* [VulnerabilityIssueLink](#vulnerabilityissuelink) +* [VulnerabilityLocationContainerScanning](#vulnerabilitylocationcontainerscanning) +* [VulnerabilityLocationDast](#vulnerabilitylocationdast) +* [VulnerabilityLocationDependencyScanning](#vulnerabilitylocationdependencyscanning) +* [VulnerabilityLocationSast](#vulnerabilitylocationsast) +* [VulnerabilityLocationSecretDetection](#vulnerabilitylocationsecretdetection) +* [VulnerabilityPermissions](#vulnerabilitypermissions) +* [VulnerabilityScanner](#vulnerabilityscanner) +* [VulnerabilitySeveritiesCount](#vulnerabilityseveritiescount) +* [VulnerableDependency](#vulnerabledependency) +* [VulnerablePackage](#vulnerablepackage) + +# GraphQL API Resources[](#graphql-api-resources "Permalink") + +本文档是基于 GitLab 当前的 GraphQL 模式自行生成的. + +可以使用[GraphiQL IDE](../index.html#graphiql)交互式地探索该 API. + +下表每个都记录了 GraphQL 类型. 类型可以轻松地与模型匹配,但是并非所有的字段和方法都可以通过 GraphQL 获得. + +**警告:**不推荐使用的字段标有 . + +## AccessLevel[](#accesslevel "Permalink") + +表示用户与之相关的对象之间的关系的访问级别 + +| Name | Type | Description | +| --- | --- | --- | +| `integerValue` | Int | 访问级别的整数表示 | +| `stringValue` | AccessLevelEnum | 访问级别的字符串表示形式 | + +## AddAwardEmojiPayload[](#addawardemojipayload "Permalink") + +自动生成的 AddAwardEmoji 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `awardEmoji` | AwardEmoji | 突变后的奖励表情符号 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## AddProjectToSecurityDashboardPayload[](#addprojecttosecuritydashboardpayload "Permalink") + +自动生成的 AddProjectToSecurityDashboard 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `project` | Project | 添加到 Instance Security 仪表盘的项目 | + +## AdminSidekiqQueuesDeleteJobsPayload[](#adminsidekiqqueuesdeletejobspayload "Permalink") + +自动生成的 AdminSidekiqQueuesDeleteJobs 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `result` | DeleteJobsResponse | 有关删除请求状态的信息 | + +## AlertManagementAlert[](#alertmanagementalert "Permalink") + +描述来自项目警报管理的警报 + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time | 创建警报的时间戳 | +| `description` | String | 警报说明 | +| `details` | JSON | 警报详细信息 | +| `endedAt` | Time | 警报结束的时间戳记 | +| `eventCount` | Int | 此警报的事件数 | +| `hosts` | 串! =>数组 | 警报来自的主机列表 | +| `iid` | ID! | 警报的内部 ID | +| `issueIid` | ID | 警报附带的 GitLab 问题的内部 ID | +| `metricsDashboardUrl` | String | 嵌入警报的指标的 URL | +| `monitoringTool` | String | 警报来自的监视工具 | +| `service` | String | 服务警报来自 | +| `severity` | AlertManagementSeverity | 警报的严重程度 | +| `startedAt` | Time | 发出警报的时间戳记 | +| `status` | AlertManagementStatus | 警报状态 | +| `title` | String | 警报标题 | +| `updatedAt` | Time | 警报的时间戳记最新更新 | + +## AlertManagementAlertStatusCountsType[](#alertmanagementalertstatuscountstype "Permalink") + +代表所代表类别的警报总数 + +| Name | Type | Description | +| --- | --- | --- | +| `acknowledged` | Int | 项目状态为 ACKNOWLEDGED 的警报数 | +| `all` | Int | 项目警报总数 | +| `ignored` | Int | 项目状态为 IGNORED 的警报数 | +| `open` | Int | 项目状态为 TRIGGERED 或 ACKNOWLEDGED 的警报数 | +| `resolved` | Int | 项目状态为"已解决"的警报数 | +| `triggered` | Int | 项目状态为 TRIGGERED 的警报数 | + +## AlertSetAssigneesPayload[](#alertsetassigneespayload "Permalink") + +自动生成的 AlertSetAssignees 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `alert` | AlertManagementAlert | 突变后的警报 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后产生的问题 | +| `todo` | Todo | 突变后的待办事项 | + +## AlertTodoCreatePayload[](#alerttodocreatepayload "Permalink") + +自动生成的 AlertTodoCreate 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `alert` | AlertManagementAlert | 突变后的警报 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后产生的问题 | +| `todo` | Todo | 突变后的待办事项 | + +## AwardEmoji[](#awardemoji "Permalink") + +用户授予的表情符号. + +| Name | Type | Description | +| --- | --- | --- | +| `description` | String! | 表情符号说明 | +| `emoji` | String! | 表情符号作为图标 | +| `name` | String! | 表情符号名称 | +| `unicode` | String! | Unicode 中的表情符号 | +| `unicodeVersion` | String! | 此表情符号的 unicode 版本 | +| `user` | User! | 授予表情符号的用户 | + +## AwardEmojiAddPayload[](#awardemojiaddpayload "Permalink") + +自动生成的 AwardEmojiAdd 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `awardEmoji` | AwardEmoji | 突变后的奖励表情符号 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## AwardEmojiRemovePayload[](#awardemojiremovepayload "Permalink") + +自动生成的 AwardEmoji 退货类型 + +| Name | Type | Description | +| --- | --- | --- | +| `awardEmoji` | AwardEmoji | The award emoji after mutation | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## AwardEmojiTogglePayload[](#awardemojitogglepayload "Permalink") + +自动生成的 AwardEmojiToggle 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `awardEmoji` | AwardEmoji | 突变后的奖励表情符号 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `toggledOn` | Boolean! | 指示表情符号的状态. 如果切换开关授予表情符号,则为 true;如果切换开关删除了表情符号,则为 false. | + +## BaseService[](#baseservice "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `active` | Boolean | 指示服务是否处于活动状态 | +| `type` | String | 服务的类别名称 | + +## Blob[](#blob "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `flatPath` | String! | 条目的平坦路径 | +| `id` | ID! | 条目 ID | +| `lfsOid` | String | Blob 的 LFS ID | +| `mode` | String | 数字格式的 Blob 模式 | +| `name` | String! | 条目名称 | +| `path` | String! | 条目路径 | +| `sha` | String! | 提交的最后提交 sha | +| `type` | EntryType! | 树条目的类型 | +| `webUrl` | String | Blob 的网址 | + +## Board[](#board "Permalink") + +代表一个项目或小组委员会 + +| Name | Type | Description | +| --- | --- | --- | +| `id` | ID! | 单板的 ID(全局 ID) | +| `name` | String | 董事会名称 | +| `weight` | Int | 木板重量 | + +## BoardList[](#boardlist "Permalink") + +代表发行板的列表 + +| Name | Type | Description | +| --- | --- | --- | +| `assignee` | User | 列表中的受让人 | +| `collapsed` | Boolean | 指示此用户的列表是否折叠 | +| `id` | ID! | 列表的 ID(全局 ID) | +| `label` | Label | 清单标签 | +| `limitMetric` | ListLimitMetric | 列表的当前限制指标 | +| `listType` | String! | 清单类型 | +| `maxIssueCount` | Int | 列表中的最大问题数 | +| `maxIssueWeight` | Int | 清单中的最大问题权重 | +| `milestone` | Milestone | 名单的里程碑 | +| `position` | Int | 名单在董事会中的位置 | +| `title` | String! | 清单标题 | + +## BoardListUpdateLimitMetricsPayload[](#boardlistupdatelimitmetricspayload "Permalink") + +自动生成的 BoardListUpdateLimitMetrics 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `list` | BoardList | 更新清单 | + +## Branch[](#branch "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `commit` | Commit | 提交分支 | +| `name` | String! | 分行名称 | + +## Commit[](#commit "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User | 提交的作者 | +| `authorGravatar` | String | 提交作者 | +| `authorName` | String | 提交作者姓名 | +| `authoredDate` | Time | 提交提交的时间戳 | +| `description` | String | 提交消息的描述 | +| `id` | ID! | 提交的 ID(全局 ID) | +| `latestPipeline` | Pipeline | **不推荐使用:**使用`pipelines` . 在 12.5 中弃用 | +| `message` | String | 原始提交消息 | +| `sha` | String! | 提交的 SHA1 ID | +| `signatureHtml` | String | 提交签名的 HTML | +| `title` | String | 提交消息的标题 | +| `titleHtml` | String | GitLab 风味 Markdown `title`渲染 | +| `webUrl` | String! | 提交的 Web URL | + +## CommitCreatePayload[](#commitcreatepayload "Permalink") + +自动生成的 CommitCreate 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `commit` | Commit | 突变后的提交 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## ComplianceFramework[](#complianceframework "Permalink") + +表示与项目关联的 ComplianceFramework + +| Name | Type | Description | +| --- | --- | --- | +| `name` | ProjectSettingEnum! | 合规框架名称 | + +## ContainerExpirationPolicy[](#containerexpirationpolicy "Permalink") + +标签过期策略旨在仅保留最重要的图像 + +| Name | Type | Description | +| --- | --- | --- | +| `cadence` | ContainerExpirationPolicyCadenceEnum! | 该容器到期政策时间表 | +| `createdAt` | Time! | 创建容器到期策略的时间戳 | +| `enabled` | Boolean! | 指示是否启用了此容器过期策略 | +| `keepN` | ContainerExpirationPolicyKeepEnum | 要保留的标签数 | +| `nameRegex` | UntrustedRegexp | 名称与此正则表达式模式匹配的标签将过期 | +| `nameRegexKeep` | UntrustedRegexp | 名称与该正则表达式模式匹配的标签将被保留 | +| `nextRunAt` | Time | 下次该容器到期策略将被执行 | +| `olderThan` | ContainerExpirationPolicyOlderThanEnum | Tags older that this will expire | +| `updatedAt` | Time! | 容器过期策略更新的时间戳 | + +## CreateAlertIssuePayload[](#createalertissuepayload "Permalink") + +自动生成的 CreateAlertIssue 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `alert` | AlertManagementAlert | 突变后的警报 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后产生的问题 | +| `todo` | Todo | 突变后的待办事项 | + +## CreateAnnotationPayload[](#createannotationpayload "Permalink") + +自动生成的 CreateAnnotation 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `annotation` | MetricsDashboardAnnotation | 创建的注释 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## CreateBranchPayload[](#createbranchpayload "Permalink") + +自动生成的 CreateBranch 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `branch` | Branch | 突变后分支 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## CreateDiffNotePayload[](#creatediffnotepayload "Permalink") + +自动生成的 CreateDiffNote 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `note` | Note | 突变后的音符 | + +## CreateEpicPayload[](#createepicpayload "Permalink") + +自动生成的 CreateEpic 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `epic` | Epic | 创造的史诗 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## CreateImageDiffNotePayload[](#createimagediffnotepayload "Permalink") + +自动生成的 CreateImageDiffNote 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `note` | Note | 突变后的音符 | + +## CreateIterationPayload[](#createiterationpayload "Permalink") + +自动生成的 CreateIteration 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `iteration` | Iteration | 创建的迭代 | + +## CreateNotePayload[](#createnotepayload "Permalink") + +自动生成的 CreateNote 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `note` | Note | 突变后的音符 | + +## CreateRequirementPayload[](#createrequirementpayload "Permalink") + +自动生成的 CreateRequirement 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `requirement` | Requirement | 突变后的要求 | + +## CreateSnippetPayload[](#createsnippetpayload "Permalink") + +自动生成的 CreateSnippet 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `snippet` | Snippet | 突变后的代码段 | + +## DastSiteProfileCreatePayload[](#dastsiteprofilecreatepayload "Permalink") + +自动生成的 DastSiteProfileCreate 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `id` | ID | 网站配置文件的 ID. | + +## DeleteAnnotationPayload[](#deleteannotationpayload "Permalink") + +自动生成的 DeleteAnnotation 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## DeleteJobsResponse[](#deletejobsresponse "Permalink") + +来自 AdminSidekiqQueuesDeleteJobs 突变的响应. + +| Name | Type | Description | +| --- | --- | --- | +| `completed` | Boolean | 是否及时处理了整个队列; 如果没有,重试相同的请求是安全的 | +| `deletedJobs` | Int | 删除的匹配作业数 | +| `queueSize` | Int | 处理后的队列大小 | + +## Design[](#design "Permalink") + +单一设计 + +| Name | Type | Description | +| --- | --- | --- | +| `diffRefs` | DiffRefs! | 此设计的差异参考 | +| `event` | DesignVersionEvent! | 当前版本中该设计的更改方式 | +| `filename` | String! | 设计的文件名 | +| `fullPath` | String! | 设计文件的完整路径 | +| `id` | ID! | 此设计的 ID | +| `image` | String! | 完整尺寸图片的网址 | +| `imageV432x230` | String | 调整了设计网址的大小,以适合 432x230 的范围. 如果尚未生成图像,则为`null` | +| `issue` | Issue! | 设计属于的问题 | +| `notesCount` | Int! | 用户为此设计创建的注释总数 | +| `project` | Project! | 设计所属的项目 | + +## DesignAtVersion[](#designatversion "Permalink") + +固定到特定版本的设计. 图像字段反映了相关版本的设计. + +| Name | Type | Description | +| --- | --- | --- | +| `design` | Design! | 基础设计. | +| `diffRefs` | DiffRefs! | 此设计的差异参考 | +| `event` | DesignVersionEvent! | 当前版本中该设计的更改方式 | +| `filename` | String! | 设计的文件名 | +| `fullPath` | String! | 设计文件的完整路径 | +| `id` | ID! | 此设计的 ID | +| `image` | String! | 完整尺寸图片的网址 | +| `imageV432x230` | String | 调整了设计网址的大小,以适合 432x230 的范围. 如果尚未生成图像,则为`null` | +| `issue` | Issue! | 设计属于的问题 | +| `notesCount` | Int! | 用户为此设计创建的注释总数 | +| `project` | Project! | 设计所属的项目 | +| `version` | DesignVersion! | 此版本设计版本固定到的版本 | + +## DesignCollection[](#designcollection "Permalink") + +设计的集合. + +| Name | Type | Description | +| --- | --- | --- | +| `design` | Design | 查找特定的设计 | +| `designAtVersion` | DesignAtVersion | 查找版本设计 | +| `issue` | Issue! | 与设计收藏相关的问题 | +| `project` | Project! | 与设计收藏关联的项目 | +| `version` | DesignVersion | 特定版本 | + +## DesignManagement[](#designmanagement "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `designAtVersion` | DesignAtVersion | 查找版本设计 | +| `version` | DesignVersion | 查找版本 | + +## DesignManagementDeletePayload[](#designmanagementdeletepayload "Permalink") + +自动生成的 DesignManagementDelete 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `version` | DesignVersion | 删除了设计的新版本 | + +## DesignManagementUploadPayload[](#designmanagementuploadpayload "Permalink") + +自动生成的 DesignManagementUpload 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `designs` | 设计! =>数组 | 突变上传的设计 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `skippedDesigns` | 设计! =>数组 | 由于上一版本以来其内容没有更改,因此从上载中跳过的任何设计 | + +## DesignVersion[](#designversion "Permalink") + +在其中添加,修改或删除设计的特定版本 + +| Name | Type | Description | +| --- | --- | --- | +| `designAtVersion` | DesignAtVersion! | 此版本的特定设计,只要该版本可见 | +| `id` | ID! | 设计版本号 | +| `sha` | ID! | 设计版本的 SHA | + +## DestroyNotePayload[](#destroynotepayload "Permalink") + +自动生成的销毁返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `note` | Note | 突变后的音符 | + +## DestroySnippetPayload[](#destroysnippetpayload "Permalink") + +自动生成的 DestroySnippet 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `snippet` | Snippet | 突变后的代码段 | + +## DetailedStatus[](#detailedstatus "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `detailsPath` | String! | 管道状态的详细信息路径 | +| `favicon` | String! | 管道状态图标 | +| `group` | String! | 组管道状态 | +| `hasDetails` | Boolean! | 指示管道状态是否有更多详细信息 | +| `icon` | String! | 管道状态图标 | +| `label` | String! | 管道状态标签 | +| `text` | String! | 管道状态文字 | +| `tooltip` | String! | 与管道状态相关的工具提示 | + +## DiffPosition[](#diffposition "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `diffRefs` | DiffRefs! | 评论时有关分支,HEAD 和基础的信息 | +| `filePath` | String! | 更改文件的路径 | +| `height` | Int | 图片总高度 | +| `newLine` | Int | HEAD SHA 上的线已更改 | +| `newPath` | String | HEAD SHA 上文件的路径 | +| `oldLine` | Int | 起始 SHA 上已更改的行 | +| `oldPath` | String | 起始 SHA 上文件的路径 | +| `positionType` | DiffPositionType! | 位置所指的文件类型 | +| `width` | Int | 图片总宽度 | +| `x` | Int | 笔记的 X 位置 | +| `y` | Int | 音符的 Y 位置 | + +## DiffRefs[](#diffrefs "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `baseSha` | String | Merge base of the branch the comment was made on | +| `headSha` | String! | 发表评论时,HEAD 的 SHA | +| `startSha` | String! | 与之比较的分支的 SHA | + +## DiffStats[](#diffstats "Permalink") + +更改为单个文件 + +| Name | Type | Description | +| --- | --- | --- | +| `additions` | Int! | 添加到此文件的行数 | +| `deletions` | Int! | 从此文件中删除的行数 | +| `path` | String! | 相对于存储库根的文件路径 | + +## DiffStatsSummary[](#diffstatssummary "Permalink") + +汇总汇总 + +| Name | Type | Description | +| --- | --- | --- | +| `additions` | Int! | 添加的行数 | +| `changes` | Int! | 行数已更改 | +| `deletions` | Int! | 删除的行数 | +| `fileCount` | Int! | 文件数量已更改 | + +## Discussion[](#discussion "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time! | 讨论创建的时间戳 | +| `id` | ID! | 讨论的 ID | +| `replyId` | ID! | 用来回复此讨论的 ID | +| `resolvable` | Boolean! | 指示对象是否可以解析 | +| `resolved` | Boolean! | 指示对象是否已解析 | +| `resolvedAt` | Time | 解析对象的时间戳 | +| `resolvedBy` | User | 解决对象的用户 | + +## DiscussionToggleResolvePayload[](#discussiontoggleresolvepayload "Permalink") + +自动生成的 DiscussionToggleResolve 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `discussion` | Discussion | 突变后的讨论 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## DismissVulnerabilityPayload[](#dismissvulnerabilitypayload "Permalink") + +自动生成的 DismissVulnerability 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `vulnerability` | Vulnerability | 解雇后的漏洞 | + +## Environment[](#environment "Permalink") + +描述项目的代码部署位置 + +| Name | Type | Description | +| --- | --- | --- | +| `id` | ID! | 环境 ID | +| `metricsDashboard` | MetricsDashboard | 环境的指标仪表板架构 | +| `name` | String! | 易读的环境名称 | +| `state` | String! | 环境状态,例如:可用/已停止 | + +## Epic[](#epic "Permalink") + +代表史诗. + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User! | 史诗的作者 | +| `closedAt` | Time | 史诗关闭的时间戳 | +| `confidential` | Boolean | 指示该史诗是否为机密 | +| `createdAt` | Time | 史诗创作的时间戳 | +| `descendantCounts` | EpicDescendantCount | 打开和关闭的后代史诗和问题的数量 | +| `descendantWeightSum` | EpicDescendantWeights | 史诗及其后代中未解决和未解决问题的总权重 | +| `description` | String | 史诗的描述 | +| `downvotes` | Int! | 史诗获得的降票数 | +| `dueDate` | Time | 史诗的截止日期 | +| `dueDateFixed` | Time | 史诗的固定截止日期 | +| `dueDateFromMilestones` | Time | 从里程碑继承了史诗的到期日 | +| `dueDateIsFixed` | Boolean | 指示是否已手动设置截止日期 | +| `group` | Group! | 史诗所属的组 | +| `hasChildren` | Boolean! | 指示史诗是否有孩子 | +| `hasIssues` | Boolean! | 指示史诗是否有直接问题 | +| `hasParent` | Boolean! | 指示该史诗是否具有父史诗 | +| `healthStatus` | EpicHealthStatus | Current health status of the epic | +| `id` | ID! | 史诗编号 | +| `iid` | ID! | 史诗的内部 ID | +| `parent` | Epic | 史诗的父史诗 | +| `reference` | String! | 史诗的内部参考. 默认以缩写形式返回 | +| `relationPath` | String | 史诗问题的 URI 路径 | +| `relativePosition` | Int | 史诗在史诗树中的相对位置 | +| `startDate` | Time | 史诗的开始日期 | +| `startDateFixed` | Time | 固定的史诗开始日期 | +| `startDateFromMilestones` | Time | 从里程碑继承了史诗的开始日期 | +| `startDateIsFixed` | Boolean | 指示开始日期是否已手动设置 | +| `state` | EpicState! | 史诗般的状态 | +| `subscribed` | Boolean! | 指示当前登录的用户已订阅史诗 | +| `title` | String | 史诗的标题 | +| `updatedAt` | Time | 史诗最后一次活动的时间戳 | +| `upvotes` | Int! | 史诗已收到的投票数 | +| `userPermissions` | EpicPermissions! | 当前用户对该资源的权限 | +| `webPath` | String! | 史诗的网络路径 | +| `webUrl` | String! | 史诗的网址 | + +## EpicAddIssuePayload[](#epicaddissuepayload "Permalink") + +自动生成的 EpicAddIssue 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `epic` | Epic | 突变后的史诗 | +| `epicIssue` | EpicIssue | 史诗般的关系 | +| `errors` | 串! =>数组 | Errors encountered during execution of the mutation. | + +## EpicDescendantCount[](#epicdescendantcount "Permalink") + +后代史诗的计数. + +| Name | Type | Description | +| --- | --- | --- | +| `closedEpics` | Int | 封闭亚史诗数量 | +| `closedIssues` | Int | 已解决的史诗问题的数量 | +| `openedEpics` | Int | 打开的子史诗数量 | +| `openedIssues` | Int | 公开史诗问题的数量 | + +## EpicDescendantWeights[](#epicdescendantweights "Permalink") + +开放和封闭后代问题的总权重 + +| Name | Type | Description | +| --- | --- | --- | +| `closedIssues` | Int | 此史诗(包括史诗后代)中已完成(已关闭)期刊的总权重 | +| `openedIssues` | Int | 此史诗(包括史诗后代)中未解决问题的总权重 | + +## EpicHealthStatus[](#epichealthstatus "Permalink") + +儿童健康状况 + +| Name | Type | Description | +| --- | --- | --- | +| `issuesAtRisk` | Int | 有风险的问题数量 | +| `issuesNeedingAttention` | Int | 需要注意的问题数量 | +| `issuesOnTrack` | Int | 进行中的问题数量 | + +## EpicIssue[](#epicissue "Permalink") + +史诗与问题之间的关系 + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User! | 造成问题的使用者 | +| `closedAt` | Time | 该问题何时结束的时间戳 | +| `confidential` | Boolean! | 表示问题是机密的 | +| `createdAt` | Time! | 问题创建时间的时间戳记 | +| `description` | String | 问题说明 | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `designCollection` | DesignCollection | 与此问题相关的设计图像的收集 | +| `designs` | DesignCollection | **不推荐使用:**使用`designCollection` . 在 12.2 中弃用 | +| `discussionLocked` | Boolean! | 表示讨论已锁定在该问题上 | +| `downvotes` | Int! | 问题已收到的否决票数 | +| `dueDate` | Time | 发行日期 | +| `epic` | Epic | 此问题所属的史诗 | +| `epicIssueId` | ID! | 史诗般的关系的 ID | +| `healthStatus` | HealthStatus | 当前的健康状况. 如果禁用了`save_issuable_health_status`功能标志,则返回 null. | +| `id` | ID | 史诗关系的全局 ID | +| `iid` | ID! | 问题的内部 ID | +| `iteration` | Iteration | 迭代问题 | +| `milestone` | Milestone | 问题的里程碑 | +| `reference` | String! | 内部参考的问题. 默认以缩写形式返回 | +| `relationPath` | String | 史诗问题的 URI 路径 | +| `relativePosition` | Int | 问题的相对位置(用于在史诗树和问题板上定位) | +| `state` | IssueState! | 问题状态 | +| `subscribed` | Boolean! | 指示当前登录的用户已订阅该问题 | +| `taskCompletionStatus` | TaskCompletionStatus! | 问题的任务完成状态 | +| `timeEstimate` | Int! | 问题的时间估算 | +| `title` | String! | 问题标题 | +| `titleHtml` | String | GitLab 风味 Markdown `title`渲染 | +| `totalTimeSpent` | Int! | 报告在此问题上花费的总时间 | +| `updatedAt` | Time! | 问题上次更新的时间戳 | +| `upvotes` | Int! | 问题已收到的投票数 | +| `userNotesCount` | Int! | 用户对此问题的注释数 | +| `userPermissions` | IssuePermissions! | 当前用户对该资源的权限 | +| `webPath` | String! | 问题的网络路径 | +| `webUrl` | String! | 问题的网址 | +| `weight` | Int | 问题的权重 | + +## EpicPermissions[](#epicpermissions "Permalink") + +检查史诗级当前用户的权限 + +| Name | Type | Description | +| --- | --- | --- | +| `adminEpic` | Boolean! | 指示用户可以对此资源执行`admin_epic` | +| `awardEmoji` | Boolean! | 表示用户可以在此资源上执行`award_emoji` | +| `createEpic` | Boolean! | 指示用户可以在此资源上执行`create_epic` | +| `createNote` | Boolean! | 指示用户可以在此资源上执行`create_note` | +| `destroyEpic` | Boolean! | 指示用户可以对此资源执行`destroy_epic` | +| `readEpic` | Boolean! | 指示用户可以对此资源执行`read_epic` | +| `readEpicIid` | Boolean! | 指示用户可以对此资源执行`read_epic_iid` | +| `updateEpic` | Boolean! | 指示用户可以对此资源执行`update_epic` | + +## EpicSetSubscriptionPayload[](#epicsetsubscriptionpayload "Permalink") + +自动生成的 EpicSetSubscription 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `epic` | Epic | 突变后的史诗 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## EpicTreeReorderPayload[](#epictreereorderpayload "Permalink") + +自动生成的 EpicTreeReorder 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## GeoNode[](#geonode "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `containerRepositoriesMaxCapacity` | Int | 此辅助节点的容器存储库同步的最大并发性 | +| `enabled` | Boolean | 指示是否启用了此地理节点 | +| `filesMaxCapacity` | Int | 此辅助节点的 LFS /附件回填的最大并发性 | +| `id` | ID! | 此 GeoNode 的 ID | +| `internalUrl` | String | 在主节点上定义的 URL,辅助节点应使用该 URL 与之联系 | +| `minimumReverificationInterval` | Int | 存储库验证有效的时间间隔(以天为单位). 一旦过期,它将被重新验证 | +| `name` | String | 此地理节点的唯一标识符 | +| `primary` | Boolean | 指示此地理节点是否为主要节点 | +| `reposMaxCapacity` | Int | 此辅助节点的存储库回填的最大并发性 | +| `selectiveSyncShards` | 串! =>数组 | 如果`selective_sync_type` == `shards` ,应同步其项目的存储库存储 | +| `selectiveSyncType` | String | 指示同步是否仅限于特定的组或分片 | +| `syncObjectStorage` | Boolean | 指示此辅助节点是否将复制对象存储中的 Blob | +| `url` | String | 此地理位置节点的面向用户的网址 | +| `verificationMaxCapacity` | Int | 此辅助节点的存储库验证的最大并发性 | + +## GrafanaIntegration[](#grafanaintegration "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time! | 问题创建的时间戳 | +| `enabled` | Boolean! | 指示是否启用 Grafana 集成 | +| `grafanaUrl` | String! | 用于 Grafana 集成的 Grafana 主机的 URL | +| `id` | ID! | Grafana 集成的内部 ID | +| `token` | String! | **不推荐使用:**出于安全原因,纯文本令牌已被屏蔽. 在 12.7 中弃用 | +| `updatedAt` | Time! | 问题上次活动的时间戳 | + +## Group[](#group "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `autoDevopsEnabled` | Boolean | 指示是否为该组内的所有项目启用了 Auto DevOps | +| `avatarUrl` | String | 群组的头像网址 | +| `board` | Board | 小组的一个董事会 | +| `description` | String | 命名空间的描述 | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `emailsDisabled` | Boolean | 指示组是否禁用了电子邮件通知 | +| `epic` | Epic | 查找单个史诗 | +| `epicsEnabled` | Boolean | 指示是否为名称空间启用了 Epics | +| `fullName` | String! | 命名空间的全名 | +| `fullPath` | ID! | 命名空间的完整路径 | +| `groupTimelogsEnabled` | Boolean | 指示是否为名称空间启用了组时间日志 | +| `id` | ID! | 命名空间的 ID | +| `label` | Label | 该组可用的标签 | +| `lfsEnabled` | Boolean | 指示是否为名称空间启用了大文件存储(LFS) | +| `mentionsDisabled` | Boolean | 指示是否禁止某人被提及 | +| `name` | String! | 命名空间的名称 | +| `parent` | Group | 家长组 | +| `path` | String! | 命名空间的路径 | +| `projectCreationLevel` | String | 在组中创建项目所需的权限级别 | +| `requestAccessEnabled` | Boolean | 指示用户是否可以请求访问名称空间 | +| `requireTwoFactorAuthentication` | Boolean | 指示是否需要该组中的所有用户来设置两因素身份验证 | +| `rootStorageStatistics` | RootStorageStatistics | 命名空间的聚合存储统计信息. 仅适用于根名称空间 | +| `shareWithGroupLock` | Boolean | 指示是否禁止与该组中的另一个组共享项目 | +| `storageSizeLimit` | Float | 根名称空间的总存储限制(以字节为单位) | +| `subgroupCreationLevel` | String | 在组内创建子组所需的权限级别 | +| `temporaryStorageIncreaseEndsOn` | Time | 直到临时存储增加生效的日期 | +| `twoFactorGracePeriod` | Int | 强制执行两因素身份验证的时间 | +| `userPermissions` | GroupPermissions! | 当前用户对该资源的权限 | +| `visibility` | String | 名称空间的可见性 | +| `webUrl` | String! | 网上论坛网址 | + +## GroupMember[](#groupmember "Permalink") + +代表小组成员 + +| Name | Type | Description | +| --- | --- | --- | +| `accessLevel` | AccessLevel | GitLab ::访问级别 | +| `createdAt` | Time | 创建成员的日期和时间 | +| `createdBy` | User | 授权会员的用户 | +| `expiresAt` | Time | 成员资格到期的日期和时间 | +| `group` | Group | 用户所属的组 | +| `updatedAt` | Time | 成员的最新更新日期和时间 | +| `userPermissions` | GroupPermissions! | 当前用户对该资源的权限 | + +## GroupPermissions[](#grouppermissions "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `readGroup` | Boolean! | 指示用户可以对此资源执行`read_group` | + +## Issue[](#issue "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User! | 造成问题的使用者 | +| `closedAt` | Time | 该问题何时结束的时间戳 | +| `confidential` | Boolean! | 表示问题是机密的 | +| `createdAt` | Time! | 问题创建时间的时间戳记 | +| `description` | String | 问题说明 | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `designCollection` | DesignCollection | 与此问题相关的设计图像的收集 | +| `designs` | DesignCollection | **不推荐使用:**使用`designCollection` . 在 12.2 中弃用 | +| `discussionLocked` | Boolean! | 表示讨论已锁定在该问题上 | +| `downvotes` | Int! | 问题已收到的否决票数 | +| `dueDate` | Time | 发行日期 | +| `epic` | Epic | 此问题所属的史诗 | +| `healthStatus` | HealthStatus | 当前的健康状况. 如果禁用了`save_issuable_health_status`功能标志,则返回 null. | +| `id` | ID! | 问题编号 | +| `iid` | ID! | 问题的内部 ID | +| `iteration` | Iteration | 迭代问题 | +| `milestone` | Milestone | 问题的里程碑 | +| `reference` | String! | 内部参考的问题. 默认以缩写形式返回 | +| `relativePosition` | Int | 问题的相对位置(用于在史诗树和问题板上定位) | +| `state` | IssueState! | 问题状态 | +| `subscribed` | Boolean! | 指示当前登录的用户已订阅该问题 | +| `taskCompletionStatus` | TaskCompletionStatus! | 问题的任务完成状态 | +| `timeEstimate` | Int! | 问题的时间估算 | +| `title` | String! | 问题标题 | +| `titleHtml` | String | GitLab 风味 Markdown `title`渲染 | +| `totalTimeSpent` | Int! | 报告在此问题上花费的总时间 | +| `updatedAt` | Time! | 问题上次更新的时间戳 | +| `upvotes` | Int! | 问题已收到的投票数 | +| `userNotesCount` | Int! | 用户对此问题的注释数 | +| `userPermissions` | IssuePermissions! | 当前用户对该资源的权限 | +| `webPath` | String! | 问题的网络路径 | +| `webUrl` | String! | 问题的网址 | +| `weight` | Int | 问题的权重 | + +## IssuePermissions[](#issuepermissions "Permalink") + +检查当前用户在问题上的权限 + +| Name | Type | Description | +| --- | --- | --- | +| `adminIssue` | Boolean! | 指示用户可以对此资源执行`admin_issue` | +| `createDesign` | Boolean! | 指示用户可以对此资源执行`create_design` | +| `createNote` | Boolean! | 指示用户可以在此资源上执行`create_note` | +| `destroyDesign` | Boolean! | 指示用户可以对此资源执行`destroy_design` | +| `readDesign` | Boolean! | 指示用户可以对此资源执行`read_design` | +| `readIssue` | Boolean! | 指示用户可以对此资源执行`read_issue` | +| `reopenIssue` | Boolean! | 指示用户可以对此资源执行`reopen_issue` | +| `updateIssue` | Boolean! | 指示用户可以对此资源执行`update_issue` | + +## IssueSetConfidentialPayload[](#issuesetconfidentialpayload "Permalink") + +自动生成的 IssueSetConfidential 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后的问题 | + +## IssueSetDueDatePayload[](#issuesetduedatepayload "Permalink") + +自动生成的 IssueSetDueDate 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后的问题 | + +## IssueSetIterationPayload[](#issuesetiterationpayload "Permalink") + +自动生成的 IssueSetIteration 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后的问题 | + +## IssueSetLockedPayload[](#issuesetlockedpayload "Permalink") + +自动生成的 IssueSetLocked 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后的问题 | + +## IssueSetWeightPayload[](#issuesetweightpayload "Permalink") + +自动生成的 IssueSetWeight 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后的问题 | + +## Iteration[](#iteration "Permalink") + +表示一个迭代对象. + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time! | 迭代创建的时间戳 | +| `description` | String | 迭代描述 | +| `dueDate` | Time | 迭代到期日期的时间戳 | +| `id` | ID! | 迭代 ID | +| `iid` | ID! | 迭代的内部 ID | +| `startDate` | Time | 迭代开始日期的时间戳 | +| `state` | IterationState! | 迭代状态 | +| `title` | String! | 迭代标题 | +| `updatedAt` | Time! | 上次迭代更新的时间戳 | +| `webPath` | String! | 迭代的 Web 路径 | +| `webUrl` | String! | 迭代的 Web URL | + +## JiraImport[](#jiraimport "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time | 创建 Jira 导入的时间戳 | +| `failedToImportCount` | Int! | 导入失败的问题数 | +| `importedIssuesCount` | Int! | 成功导入的问题数 | +| `jiraProjectKey` | String! | 导入的 Jira 项目的项目密钥 | +| `scheduledAt` | Time | 计划导入 Jira 的时间戳 | +| `scheduledBy` | User | 开始导入 Jira 的用户 | +| `totalIssueCount` | Int! | 尝试导入的问题总数 | + +## JiraImportStartPayload[](#jiraimportstartpayload "Permalink") + +自动生成的 JiraImportStart 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | Errors encountered during execution of the mutation. | +| `jiraImport` | JiraImport | 突变后的 Jira 导入数据 | + +## JiraImportUsersPayload[](#jiraimportuserspayload "Permalink") + +自动生成的 JiraImportUsers 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `jiraUsers` | JiraUser! =>数组 | 从 Jira 返回的用户,并通过电子邮件和姓名进行匹配(如果可能). | + +## JiraProject[](#jiraproject "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `key` | String! | 吉拉项目的关键 | +| `name` | String | Jira 项目的名称 | +| `projectId` | Int! | Jira 项目的 ID | + +## JiraService[](#jiraservice "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `active` | Boolean | 指示服务是否处于活动状态 | +| `projects` | JiraProjectConnection | 通过 Jira REST API 获取的所有 Jira 项目的列表 | +| `type` | String | 服务的类别名称 | + +## JiraUser[](#jirauser "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `gitlabId` | Int | 匹配的 GitLab 用户的 ID | +| `gitlabName` | String | 匹配的 GitLab 用户名 | +| `gitlabUsername` | String | 匹配的 GitLab 用户的用户名 | +| `jiraAccountId` | String! | Jira 用户的帐户 ID | +| `jiraDisplayName` | String! | Jira 用户的显示名称 | +| `jiraEmail` | String | Jira 用户的电子邮件,仅针对具有公共电子邮件的用户返回 | + +## Label[](#label "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `color` | String! | 标签的背景色 | +| `description` | String | 标签的说明(Markdown 呈现为 HTML 以进行缓存) | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `id` | ID! | 标签编号 | +| `textColor` | String! | 标签的文字颜色 | +| `title` | String! | 标签内容 | + +## MarkAsSpamSnippetPayload[](#markasspamsnippetpayload "Permalink") + +自动生成的 MarkAsSpamSnippet 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `snippet` | Snippet | 突变后的代码段 | + +## MergeRequest[](#mergerequest "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `allowCollaboration` | Boolean | 指示目标项目的成员是否可以推送到分叉 | +| `author` | User | 创建此合并请求的用户 | +| `createdAt` | Time! | 创建合并请求的时间戳 | +| `defaultMergeCommitMessage` | String | 合并请求的默认合并提交消息 | +| `description` | String | 合并请求的描述(Markdown 渲染为 HTML 以进行缓存) | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `diffHeadSha` | String | 合并请求的不同头 SHA | +| `diffRefs` | DiffRefs | 此合并请求的基础 SHA,头部 SHA 和起始 SHA 的引用 | +| `diffStats` | DiffStats! =>数组 | 有关在此合并请求中更改了哪些文件的详细信息 | +| `diffStatsSummary` | DiffStatsSummary | 在此合并请求中更改了哪些文件的摘要 | +| `discussionLocked` | Boolean! | 指示是否仅将对合并请求的注释锁定为成员 | +| `downvotes` | Int! | 合并请求的否决票数 | +| `forceRemoveSourceBranch` | Boolean | 指示合并后项目设置是否会导致源分支删除 | +| `headPipeline` | Pipeline | 在合并请求的分支 HEAD 上运行的管道 | +| `id` | ID! | 合并请求的 ID | +| `iid` | String! | 合并请求的内部 ID | +| `inProgressMergeCommitSha` | String | 如果合并正在进行,则提交合并请求的 SHA | +| `mergeCommitMessage` | String | **不推荐使用:**使用`defaultMergeCommitMessage` . 在 11.8 中已弃用 | +| `mergeCommitSha` | String | 合并请求提交的 SHA(一旦合并就设置) | +| `mergeError` | String | 由于合并错误而导致的错误消息 | +| `mergeOngoing` | Boolean! | 指示当前是否正在发生合并 | +| `mergeStatus` | String | 合并请求的状态 | +| `mergeWhenPipelineSucceeds` | Boolean | 指示在管道成功(MWPS)时是否已将合并设置为要合并 | +| `mergeableDiscussionsState` | Boolean | 指示合并请求中的所有讨论是否都已解决,从而允许合并请求被合并 | +| `mergedAt` | Time | 合并请求合并的时间戳记;如果未合并,则为 null | +| `milestone` | Milestone | 合并请求的里程碑 | +| `project` | Project! | target_project 的别名 | +| `projectId` | Int! | 合并请求项目的 ID | +| `rebaseCommitSha` | String | 重新设置合并请求的提交 SHA | +| `rebaseInProgress` | Boolean! | 指示合并请求当前是否正在进行重新设置 | +| `reference` | String! | 合并请求的内部参考. 默认以缩写形式返回 | +| `shouldBeRebased` | Boolean! | 指示合并请求是否将被重定基础 | +| `shouldRemoveSourceBranch` | Boolean | 指示在合并后是否会删除合并请求的源分支 | +| `sourceBranch` | String! | 合并请求的源分支 | +| `sourceBranchExists` | Boolean! | 指示合并请求的源分支是否存在 | +| `sourceProject` | Project | 合并请求的源项目 | +| `sourceProjectId` | Int | 合并请求源项目的 ID | +| `state` | MergeRequestState! | 合并请求的状态 | +| `subscribed` | Boolean! | 指示当前登录的用户是否订阅了此合并请求 | +| `targetBranch` | String! | 合并请求的目标分支 | +| `targetBranchExists` | Boolean! | 指示合并请求的目标分支是否存在 | +| `targetProject` | Project! | 合并请求的目标项目 | +| `targetProjectId` | Int! | 合并请求目标项目的 ID | +| `taskCompletionStatus` | TaskCompletionStatus! | 任务的完成状态 | +| `timeEstimate` | Int! | 合并请求的时间估算 | +| `title` | String! | 合并请求的标题 | +| `titleHtml` | String | GitLab 风味 Markdown `title`渲染 | +| `totalTimeSpent` | Int! | 报告为在合并请求上花费的总时间 | +| `updatedAt` | Time! | 合并请求上次更新的时间戳 | +| `upvotes` | Int! | 合并请求的投票数 | +| `userNotesCount` | Int | 用户记录合并请求的数量 | +| `userPermissions` | MergeRequestPermissions! | 当前用户对该资源的权限 | +| `webUrl` | String | 合并请求的网址 | +| `workInProgress` | Boolean! | 指示合并请求是否正在进行中(WIP) | + +## MergeRequestCreatePayload[](#mergerequestcreatepayload "Permalink") + +自动生成的 MergeRequestCreate 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestPermissions[](#mergerequestpermissions "Permalink") + +检查合并请求中当前用户的权限 + +| Name | Type | Description | +| --- | --- | --- | +| `adminMergeRequest` | Boolean! | 指示用户可以对此资源执行`admin_merge_request` | +| `cherryPickOnCurrentMergeRequest` | Boolean! | 表示用户可以对此资源执行`cherry_pick_on_current_merge_request` | +| `createNote` | Boolean! | 指示用户可以在此资源上执行`create_note` | +| `pushToSourceBranch` | Boolean! | 指示用户可以对此资源执行`push_to_source_branch` | +| `readMergeRequest` | Boolean! | 指示用户可以对此资源执行`read_merge_request` | +| `removeSourceBranch` | Boolean! | 指示用户可以对此资源执行`remove_source_branch` | +| `revertOnCurrentMergeRequest` | Boolean! | 指示用户可以对此资源执行`revert_on_current_merge_request` | +| `updateMergeRequest` | Boolean! | 指示用户可以对此资源执行`update_merge_request` | + +## MergeRequestSetAssigneesPayload[](#mergerequestsetassigneespayload "Permalink") + +自动生成的 MergeRequestSetAssignees 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestSetLabelsPayload[](#mergerequestsetlabelspayload "Permalink") + +自动生成的 MergeRequestSetLabels 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestSetLockedPayload[](#mergerequestsetlockedpayload "Permalink") + +自动生成的 MergeRequestSetLocked 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestSetMilestonePayload[](#mergerequestsetmilestonepayload "Permalink") + +自动生成的 MergeRequestSetMilestone 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestSetSubscriptionPayload[](#mergerequestsetsubscriptionpayload "Permalink") + +自动生成的 MergeRequestSetSubscription 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestSetWipPayload[](#mergerequestsetwippayload "Permalink") + +自动生成的 MergeRequestSetWip 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestUpdatePayload[](#mergerequestupdatepayload "Permalink") + +自动生成的 MergeRequestUpdate 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## Metadata[](#metadata "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `revision` | String! | Revision | +| `version` | String! | Version | + +## MetricsDashboard[](#metricsdashboard "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `path` | String | 具有仪表板定义的文件的路径 | +| `schemaValidationWarnings` | 串! =>数组 | 仪表板架构验证警告 | + +## MetricsDashboardAnnotation[](#metricsdashboardannotation "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `description` | String | 注释说明 | +| `endingAt` | Time | 注释时间跨度的时间戳标记结束 | +| `id` | ID! | 注释的 ID | +| `panelId` | String | 注释应作用于的仪表板面板的 ID | +| `startingAt` | Time | 带注释的时间跨度的时间戳标记开始 | + +## Milestone[](#milestone "Permalink") + +代表一个里程碑. + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time! | 里程碑创建的时间戳 | +| `description` | String | 里程碑说明 | +| `dueDate` | Time | 里程碑到期日期的时间戳记 | +| `groupMilestone` | Boolean! | 指示里程碑是否在组级别 | +| `id` | ID! | 里程碑的 ID | +| `projectMilestone` | Boolean! | 指示里程碑是否在项目级别 | +| `startDate` | Time | 里程碑开始日期的时间戳记 | +| `state` | MilestoneStateEnum! | 里程碑状态 | +| `stats` | MilestoneStats | 里程碑统计 | +| `subgroupMilestone` | Boolean! | 指示里程碑是否在子组级别 | +| `title` | String! | 里程碑标题 | +| `updatedAt` | Time! | 最近里程碑更新的时间戳 | +| `webPath` | String! | 里程碑的 Web 路径 | + +## MilestoneStats[](#milestonestats "Permalink") + +包含有关里程碑的统计信息 + +| Name | Type | Description | +| --- | --- | --- | +| `closedIssuesCount` | Int | 与里程碑相关的已解决问题的数量 | +| `totalIssuesCount` | Int | 与里程碑相关的总问题数 | + +## Namespace[](#namespace "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `description` | String | 命名空间的描述 | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `fullName` | String! | 命名空间的全名 | +| `fullPath` | ID! | 命名空间的完整路径 | +| `id` | ID! | 命名空间的 ID | +| `lfsEnabled` | Boolean | 指示是否为名称空间启用了大文件存储(LFS) | +| `name` | String! | 命名空间的名称 | +| `path` | String! | 命名空间的路径 | +| `requestAccessEnabled` | Boolean | 指示用户是否可以请求访问名称空间 | +| `rootStorageStatistics` | RootStorageStatistics | 命名空间的聚合存储统计信息. 仅适用于根名称空间 | +| `storageSizeLimit` | Float | 根名称空间的总存储限制(以字节为单位) | +| `temporaryStorageIncreaseEndsOn` | Time | 直到临时存储增加生效的日期 | +| `visibility` | String | 名称空间的可见性 | + +## Note[](#note "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User! | 撰写此笔记的用户 | +| `body` | String! | 注释内容 | +| `bodyHtml` | String | GitLab 风味 Markdown 渲染`note` | +| `confidential` | Boolean | 指示此注释是否保密 | +| `createdAt` | Time! | 笔记创建的时间戳 | +| `discussion` | Discussion | 本说明的讨论属于 | +| `id` | ID! | 笔记编号 | +| `position` | DiffPosition | 此注释在差异上的位置 | +| `project` | Project | 与笔记相关的项目 | +| `resolvable` | Boolean! | 指示对象是否可以解析 | +| `resolved` | Boolean! | 指示对象是否已解析 | +| `resolvedAt` | Time | 解析对象的时间戳 | +| `resolvedBy` | User | 解决对象的用户 | +| `system` | Boolean! | 指示此注释是由系统还是由用户创建的 | +| `systemNoteIconName` | String | 系统注释对应的图标名称 | +| `updatedAt` | Time! | 笔记上一次活动的时间戳 | +| `userPermissions` | NotePermissions! | 当前用户对该资源的权限 | + +## NotePermissions[](#notepermissions "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `adminNote` | Boolean! | 指示用户可以对此资源执行`admin_note` | +| `awardEmoji` | Boolean! | 表示用户可以在此资源上执行`award_emoji` | +| `createNote` | Boolean! | 指示用户可以在此资源上执行`create_note` | +| `readNote` | Boolean! | 指示用户可以对此资源执行`read_note` | +| `resolveNote` | Boolean! | 指示用户可以对此资源执行`resolve_note` | + +## Package[](#package "Permalink") + +代表包裹 + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time! | 创建日期 | +| `id` | ID! | 包裹 ID | +| `name` | String! | 包装名称 | +| `packageType` | PackageTypeEnum! | 包装类型 | +| `updatedAt` | Time! | 更新日期 | +| `version` | String | 包的版本 | + +## PackageFileRegistry[](#packagefileregistry "Permalink") + +表示软件包文件的同步和验证状态 + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time | PackageFileRegistry 创建时的时间戳记 | +| `id` | ID! | PackageFileRegistry 的 ID | +| `lastSyncFailure` | String | PackageFileRegistry 同步期间的错误消息 | +| `lastSyncedAt` | Time | PackageFileRegistry 最近一次成功同步的时间戳 | +| `packageFileId` | ID! | PackageFile 的 ID | +| `retryAt` | Time | 时间戳,之后 PackageFileRegistry 应该重新同步 | +| `retryCount` | Int | PackageFileRegistry 连续失败的同步尝试次数 | +| `state` | RegistryState | PackageFileRegistry 的同步状态 | + +## PageInfo[](#pageinfo "Permalink") + +有关连接中的分页的信息. + +| Name | Type | Description | +| --- | --- | --- | +| `endCursor` | String | 向前分页时,光标继续. | +| `hasNextPage` | Boolean! | 在向前分页时,还有更多项目吗? | +| `hasPreviousPage` | Boolean! | 向后分页时,还有更多项目吗? | +| `startCursor` | String | 向后分页时,光标继续. | + +## Pipeline[](#pipeline "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `beforeSha` | String | 源分支的基本 SHA | +| `committedAt` | Time | 管道提交的时间戳 | +| `coverage` | Float | 覆盖率 | +| `createdAt` | Time! | 管道创建的时间戳 | +| `detailedStatus` | DetailedStatus! | 管道的详细状态 | +| `duration` | Int | 管道持续时间(以秒为单位) | +| `finishedAt` | Time | 管道完成的时间戳 | +| `id` | ID! | 管道 ID | +| `iid` | String! | 管道的内部 ID | +| `securityReportSummary` | SecurityReportSummary | 管道的每个安全扫描程序的漏洞和扫描的资源计数 | +| `sha` | String! | 管道提交的 SHA | +| `startedAt` | Time | 管道启动的时间戳 | +| `status` | PipelineStatusEnum! | 管道的状态(已创建,正在等待 _ 资源,正在准备,正在挂起,正在运行,失败,成功,已取消,已跳过,已手动,已计划) | +| `updatedAt` | Time! | 管道上次活动的时间戳 | +| `userPermissions` | PipelinePermissions! | 当前用户对该资源的权限 | + +## PipelinePermissions[](#pipelinepermissions "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `adminPipeline` | Boolean! | 指示用户可以对此资源执行`admin_pipeline` | +| `destroyPipeline` | Boolean! | 指示用户可以在此资源上执行`destroy_pipeline` | +| `updatePipeline` | Boolean! | 指示用户可以对此资源执行`update_pipeline` | + +## Project[](#project "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `alertManagementAlert` | AlertManagementAlert | 项目的单个警报管理警报 | +| `alertManagementAlertStatusCounts` | AlertManagementAlertStatusCountsType | 按项目状态的警报计数 | +| `allowMergeOnSkippedPipeline` | Boolean | 如果`only_allow_merge_if_pipeline_succeeds`为 true,则指示是否还可以将项目的合并请求与跳过的作业合并 | +| `archived` | Boolean | 指示项目的存档状态 | +| `autocloseReferencedIssues` | Boolean | 指示是否自动关闭默认分支中的合并请求和提交引用的问题 | +| `avatarUrl` | String | 项目头像图像文件的 URL | +| `board` | Board | 该项目的一块板 | +| `containerExpirationPolicy` | ContainerExpirationPolicy | 项目的集装箱过期政策 | +| `containerRegistryEnabled` | Boolean | 指示项目是否在容器注册表中存储 Docker 容器映像 | +| `createdAt` | Time | 项目创建的时间戳 | +| `description` | String | 项目简介 | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `forksCount` | Int! | 分叉项目的次数 | +| `fullPath` | ID! | 项目的完整路径 | +| `grafanaIntegration` | GrafanaIntegration | 该项目的 Grafana 集成详细信息 | +| `group` | Group | 项目组 | +| `httpUrlToRepo` | String | 通过 HTTPS 连接到项目的 URL | +| `id` | ID! | 项目编号 | +| `importStatus` | String | Status of import background job of the project | +| `issue` | Issue | 该项目的一期 | +| `issuesEnabled` | Boolean | 指示是否为当前用户启用了问题 | +| `jiraImportStatus` | String | 项目的 Jira 导入后台作业的状态 | +| `jobsEnabled` | Boolean | 指示是否为当前用户启用 CI / CD 管道作业 | +| `label` | Label | 此项目上可用的标签 | +| `lastActivityAt` | Time | 项目上次活动的时间戳 | +| `lfsEnabled` | Boolean | 指示项目是否启用了大文件存储(LFS) | +| `mergeRequest` | MergeRequest | 项目的单个合并请求 | +| `mergeRequestsEnabled` | Boolean | 指示是否为当前用户启用了合并请求 | +| `mergeRequestsFfOnlyEnabled` | Boolean | 指示是否不应该创建合并提交,而应该快速转发所有合并,这意味着仅当分支可以快速转发时才允许合并. | +| `name` | String! | 项目名称(无名称空间) | +| `nameWithNamespace` | String! | 项目的全名及其名称空间 | +| `namespace` | Namespace | 项目的命名空间 | +| `onlyAllowMergeIfAllDiscussionsAreResolved` | Boolean | 指示是否只有在解决所有讨论后才能合并项目的合并请求 | +| `onlyAllowMergeIfPipelineSucceeds` | Boolean | 指示项目的合并请求是否只能与成功的作业合并 | +| `openIssuesCount` | Int | 项目未解决的问题数 | +| `path` | String! | 项目路径 | +| `pipeline` | Pipeline | 建立项目管道 | +| `printingMergeRequestLinkEnabled` | Boolean | 指示从命令行推送到项目的 Git 存储库后是否显示用于创建或查看合并请求的链接 | +| `publicJobs` | Boolean | 指示是否可以公共访问项目的管道和作业详细信息,包括输出日志和工件 | +| `release` | Release | 该项目的一个版本 | +| `removeSourceBranchAfterMerge` | Boolean | 指示默认情况下是否应为项目的所有新合并请求启用" `Delete source branch`选项 | +| `repository` | Repository | 项目的 Git 存储库 | +| `requestAccessEnabled` | Boolean | 指示用户是否可以请求成员访问项目 | +| `requirement` | Requirement | 查找单个需求. 仅在启用功能标志`requirements_management`可用. | +| `requirementStatesCount` | RequirementStatesCount | 按状态列出的项目需求数量 | +| `sastCiConfiguration` | SastCiConfiguration | 项目的 SAST CI 配置 | +| `securityScanners` | SecurityScanners | 有关项目中使用的安全分析器的信息 | +| `sentryDetailedError` | SentryDetailedError | 该项目的 Sentry 错误的详细版本 | +| `sentryErrors` | SentryErrorCollection | 分批收集 Sentry 错误的项目 | +| `serviceDeskAddress` | String | 服务台的电子邮件地址. | +| `serviceDeskEnabled` | Boolean | 指示项目是否启用了服务台. | +| `sharedRunnersEnabled` | Boolean | 指示是否为项目启用了共享运行器 | +| `snippetsEnabled` | Boolean | 指示是否为当前用户启用了代码片段 | +| `sshUrlToRepo` | String | 通过 SSH 连接到项目的 URL | +| `starCount` | Int! | 已加注星标的次数 | +| `statistics` | ProjectStatistics | 项目统计 | +| `suggestionCommitMessage` | String | 用于应用合并请求建议的提交消息 | +| `tagList` | String | 项目主题列表(不是 Git 标签) | +| `userPermissions` | ProjectPermissions! | 当前用户对该资源的权限 | +| `visibility` | String | 项目的可见性 | +| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | 计算项目漏洞的每个严重程度 | +| `webUrl` | String | 项目的网址 | +| `wikiEnabled` | Boolean | 指示是否为当前用户启用了 Wiki | + +## ProjectMember[](#projectmember "Permalink") + +代表项目成员 + +| Name | Type | Description | +| --- | --- | --- | +| `accessLevel` | AccessLevel | GitLab ::访问级别 | +| `createdAt` | Time | 创建成员的日期和时间 | +| `createdBy` | User | 授权会员的用户 | +| `expiresAt` | Time | 成员资格到期的日期和时间 | +| `id` | ID! | 会员编号 | +| `project` | Project | 用户是其成员的项目 | +| `updatedAt` | Time | 成员的最新更新日期和时间 | +| `user` | User! | 与成员对象关联的用户 | +| `userPermissions` | ProjectPermissions! | 当前用户对该资源的权限 | + +## ProjectPermissions[](#projectpermissions "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `adminOperations` | Boolean! | 指示用户可以对此资源执行`admin_operations` | +| `adminProject` | Boolean! | 指示用户可以对此资源执行`admin_project` | +| `adminRemoteMirror` | Boolean! | 指示用户可以对此资源执行`admin_remote_mirror` | +| `adminWiki` | Boolean! | 指示用户可以对此资源执行`admin_wiki` | +| `archiveProject` | Boolean! | 指示用户可以对此资源执行`archive_project` | +| `changeNamespace` | Boolean! | 指示用户可以在此资源上执行`change_namespace` | +| `changeVisibilityLevel` | Boolean! | 指示用户可以对此资源执行`change_visibility_level` | +| `createDeployment` | Boolean! | 指示用户可以对此资源执行`create_deployment` | +| `createDesign` | Boolean! | 指示用户可以对此资源执行`create_design` | +| `createIssue` | Boolean! | 指示用户可以对此资源执行`create_issue` | +| `createLabel` | Boolean! | 指示用户可以在此资源上执行`create_label` | +| `createMergeRequestFrom` | Boolean! | 指示用户可以在此资源上执行`create_merge_request_from` | +| `createMergeRequestIn` | Boolean! | 指示用户可以在此资源上执行`create_merge_request_in` | +| `createPages` | Boolean! | 指示用户可以在此资源上执行`create_pages` | +| `createPipeline` | Boolean! | Indicates the user can perform `create_pipeline` on this resource | +| `createPipelineSchedule` | Boolean! | 指示用户可以对此资源执行`create_pipeline_schedule` | +| `createSnippet` | Boolean! | 指示用户可以对此资源执行`create_snippet` | +| `createWiki` | Boolean! | 指示用户可以在此资源上执行`create_wiki` | +| `destroyDesign` | Boolean! | 指示用户可以对此资源执行`destroy_design` | +| `destroyPages` | Boolean! | 指示用户可以在此资源上执行`destroy_pages` | +| `destroyWiki` | Boolean! | 指示用户可以对此资源执行`destroy_wiki` | +| `downloadCode` | Boolean! | 指示用户可以对此资源执行`download_code` | +| `downloadWikiCode` | Boolean! | 指示用户可以在此资源上执行`download_wiki_code` | +| `forkProject` | Boolean! | 指示用户可以对此资源执行`fork_project` | +| `pushCode` | Boolean! | 指示用户可以对此资源执行`push_code` | +| `pushToDeleteProtectedBranch` | Boolean! | 指示用户可以对此资源执行`push_to_delete_protected_branch` | +| `readCommitStatus` | Boolean! | 指示用户可以对此资源执行`read_commit_status` | +| `readCycleAnalytics` | Boolean! | 指示用户可以对此资源执行`read_cycle_analytics` | +| `readDesign` | Boolean! | 指示用户可以对此资源执行`read_design` | +| `readMergeRequest` | Boolean! | 指示用户可以对此资源执行`read_merge_request` | +| `readPagesContent` | Boolean! | 指示用户可以对此资源执行`read_pages_content` | +| `readProject` | Boolean! | 指示用户可以对此资源执行`read_project` | +| `readProjectMember` | Boolean! | 指示用户可以对此资源执行`read_project_member` | +| `readWiki` | Boolean! | 指示用户可以对此资源执行`read_wiki` | +| `removeForkProject` | Boolean! | 指示用户可以对此资源执行`remove_fork_project` | +| `removePages` | Boolean! | 指示用户可以对此资源执行`remove_pages` | +| `removeProject` | Boolean! | 指示用户可以对此资源执行`remove_project` | +| `renameProject` | Boolean! | 指示用户可以对此资源执行`rename_project` | +| `requestAccess` | Boolean! | 指示用户可以对此资源执行`request_access` | +| `updatePages` | Boolean! | 指示用户可以对此资源执行`update_pages` | +| `updateWiki` | Boolean! | 指示用户可以对此资源执行`update_wiki` | +| `uploadFile` | Boolean! | 指示用户可以在此资源上执行`upload_file` | + +## ProjectStatistics[](#projectstatistics "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `buildArtifactsSize` | Float! | 构建项目的工件大小 | +| `commitCount` | Float! | 提交项目数 | +| `lfsObjectsSize` | Float! | 项目的大文件存储(LFS)对象大小 | +| `packagesSize` | Float! | 项目包装尺寸 | +| `repositorySize` | Float! | 项目的存储库大小 | +| `snippetsSize` | Float | 项目片段大小 | +| `storageSize` | Float! | 项目的存储大小 | +| `wikiSize` | Float | 项目的 Wiki 大小 | + +## Release[](#release "Permalink") + +代表发行 + +| Name | Type | Description | +| --- | --- | --- | +| `assets` | ReleaseAssets | 发行资产 | +| `author` | User | 创建发布的用户 | +| `commit` | Commit | 与发布相关的提交 | +| `createdAt` | Time | 创建版本的时间戳 | +| `description` | String | 版本说明(也称为"发行说明") | +| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | +| `links` | ReleaseLinks | 版本链接 | +| `name` | String | 发布名称 | +| `releasedAt` | Time | 发布版本的时间戳 | +| `tagName` | String | 与版本关联的标签名称 | +| `tagPath` | String | 与版本关联的标签的相对 Web 路径 | + +## ReleaseAssetLink[](#releaseassetlink "Permalink") + +表示与版本关联的资产链接 + +| Name | Type | Description | +| --- | --- | --- | +| `external` | Boolean | 表示链接指向外部资源 | +| `id` | ID! | 链接 ID | +| `linkType` | ReleaseAssetLinkType | 链接的类型: `other` , `runbook` , `image` , `package` ; 默认为`other` | +| `name` | String | Name of the link | +| `url` | String | 链接的 URL | + +## ReleaseAssets[](#releaseassets "Permalink") + +与发布相关的所有资产的容器 + +| Name | Type | Description | +| --- | --- | --- | +| `count` | Int | 发布的资产数量 | + +## ReleaseEvidence[](#releaseevidence "Permalink") + +释放证据 + +| Name | Type | Description | +| --- | --- | --- | +| `collectedAt` | Time | 证据收集的时间戳 | +| `filepath` | String | 可从中下载证据的 URL | +| `id` | ID! | 证据编号 | +| `sha` | String | 证据哈希的 SHA1 ID | + +## ReleaseLinks[](#releaselinks "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `editUrl` | String | 版本的编辑页面的 HTTP URL | +| `issuesUrl` | String | 此版本过滤的问题页面的 HTTP URL | +| `mergeRequestsUrl` | String | 此版本过滤的合并请求页面的 HTTP URL | +| `selfUrl` | String | 版本的 HTTP URL | + +## ReleaseSource[](#releasesource "Permalink") + +表示特定格式附加到发行版的源代码 + +| Name | Type | Description | +| --- | --- | --- | +| `format` | String | 来源格式 | +| `url` | String | 源代码下载 URL | + +## RemoveAwardEmojiPayload[](#removeawardemojipayload "Permalink") + +自动生成的 RemoveAwardEmoji 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `awardEmoji` | AwardEmoji | 突变后的奖励表情符号 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## RemoveProjectFromSecurityDashboardPayload[](#removeprojectfromsecuritydashboardpayload "Permalink") + +自动生成的 RemoveProjectFromSecurityDashboard 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## Repository[](#repository "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `empty` | Boolean! | 表示存储库中没有可见的内容 | +| `exists` | Boolean! | 表示磁盘上存在相应的 Git 存储库 | +| `rootRef` | String | 存储库的默认分支 | +| `tree` | Tree | 仓库的树 | + +## Requirement[](#requirement "Permalink") + +代表一个要求 + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User! | 需求的作者 | +| `createdAt` | Time! | 创建需求的时间戳 | +| `id` | ID! | 需求 ID | +| `iid` | ID! | 需求的内部 ID | +| `project` | Project! | 需求所属的项目 | +| `state` | RequirementState! | 需求状态 | +| `title` | String | 要求的标题 | +| `updatedAt` | Time! | 上一次更新需求的时间戳 | +| `userPermissions` | RequirementPermissions! | 当前用户对该资源的权限 | + +## RequirementPermissions[](#requirementpermissions "Permalink") + +根据需要检查当前用户的权限 + +| Name | Type | Description | +| --- | --- | --- | +| `adminRequirement` | Boolean! | 指示用户可以对此资源执行`admin_requirement` | +| `createRequirement` | Boolean! | 指示用户可以对此资源执行`create_requirement` | +| `destroyRequirement` | Boolean! | 指示用户可以对此资源执行`destroy_requirement` | +| `readRequirement` | Boolean! | 指示用户可以对此资源执行`read_requirement` | +| `updateRequirement` | Boolean! | 指示用户可以对此资源执行`update_requirement` | + +## RequirementStatesCount[](#requirementstatescount "Permalink") + +需求状态的计数. + +| Name | Type | Description | +| --- | --- | --- | +| `archived` | Int | 已归档需求数 | +| `opened` | Int | 打开的需求数 | + +## RootStorageStatistics[](#rootstoragestatistics "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `buildArtifactsSize` | Float! | CI 工件大小(以字节为单位) | +| `lfsObjectsSize` | Float! | LFS 对象大小(以字节为单位) | +| `packagesSize` | Float! | 包大小(以字节为单位) | +| `repositorySize` | Float! | Git 存储库大小(以字节为单位) | +| `snippetsSize` | Float! | 片段大小(以字节为单位) | +| `storageSize` | Float! | 总存储字节数 | +| `wikiSize` | Float! | Wiki 大小(以字节为单位) | + +## RunDASTScanPayload[](#rundastscanpayload "Permalink") + +自动生成的 RunDASTScan 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `pipelineUrl` | String | 创建的管道的 URL. | + +## SastCiConfigurationAnalyzersEntity[](#sastciconfigurationanalyzersentity "Permalink") + +代表 SAST CI 配置中的分析器实体 + +| Name | Type | Description | +| --- | --- | --- | +| `description` | String | 表单上显示的分析器描述. | +| `enabled` | Boolean | 指示是否启用分析仪. | +| `label` | String | 配置 UI 中使用的分析器标签. | +| `name` | String | 分析仪的名称. | + +## SastCiConfigurationEntity[](#sastciconfigurationentity "Permalink") + +代表 SAST CI 配置中的实体 + +| Name | Type | Description | +| --- | --- | --- | +| `defaultValue` | String | 如果值为空,则使用默认值. | +| `description` | String | 表单上显示的实体描述. | +| `field` | String | 实体的 CI 关键字. | +| `label` | String | 表单中使用的实体的标签. | +| `type` | String | 字段值的类型. | +| `value` | String | 实体的当前值. | + +## SastCiConfigurationOptionsEntity[](#sastciconfigurationoptionsentity "Permalink") + +代表 SAST CI 配置中选项的实体 + +| Name | Type | Description | +| --- | --- | --- | +| `label` | String | 期权实体的标签. | +| `value` | String | 期权实体的价值. | + +## ScannedResource[](#scannedresource "Permalink") + +表示通过安全扫描扫描的资源 + +| Name | Type | Description | +| --- | --- | --- | +| `requestMethod` | String | 用于访问 URL 的 HTTP 请求方法 | +| `url` | String | 扫描仪扫描的 URL | + +## SecurityReportSummary[](#securityreportsummary "Permalink") + +代表安全报告摘要 + +| Name | Type | Description | +| --- | --- | --- | +| `containerScanning` | SecurityReportSummarySection | container_scanning 扫描的汇总计数 | +| `coverageFuzzing` | SecurityReportSummarySection | coverage_fuzzing 扫描的总计数 | +| `dast` | SecurityReportSummarySection | Dast 扫描的累计计数 | +| `dependencyScanning` | SecurityReportSummarySection | dependency_scanning 扫描的汇总计数 | +| `sast` | SecurityReportSummarySection | sast 扫描的累计计数 | +| `secretDetection` | SecurityReportSummarySection | secret_detection 扫描的总计计数 | + +## SecurityReportSummarySection[](#securityreportsummarysection "Permalink") + +代表安全报告摘要的一部分 + +| Name | Type | Description | +| --- | --- | --- | +| `scannedResourcesCount` | Int | 扫描资源总数 | +| `scannedResourcesCsvPath` | String | 以 CSV 格式下载所有扫描资源的路径 | +| `vulnerabilitiesCount` | Int | 漏洞总数 | + +## SecurityScanners[](#securityscanners "Permalink") + +代表安全扫描器列表 + +| Name | Type | Description | +| --- | --- | --- | +| `available` | SecurityScannerType! =>数组 | 可用于项目的分析仪列表. | +| `enabled` | SecurityScannerType! =>数组 | 为项目启用的分析器列表. | +| `pipelineRun` | SecurityScannerType! => Array | 在最新管道中成功运行的分析仪列表. | + +## SentryDetailedError[](#sentrydetailederror "Permalink") + +哨兵错误. + +| Name | Type | Description | +| --- | --- | --- | +| `count` | Int! | 发生次数 | +| `culprit` | String! | 错误的罪魁祸首 | +| `externalBaseUrl` | String! | Sentry 实例的外部基本 URL | +| `externalUrl` | String! | 错误的外部网址 | +| `firstReleaseLastCommit` | String | 提交错误是第一次被发现 | +| `firstReleaseShortVersion` | String | 发布简短版本错误首次被发现 | +| `firstReleaseVersion` | String | 发布版本错误首次被发现 | +| `firstSeen` | Time! | 首次发现错误的时间戳 | +| `frequency` | SentryErrorFrequency! =>数组 | 最近 24 小时的错误统计信息 | +| `gitlabCommit` | String | 基于发行版的 GitLab 提交 SHA 归因于 Error | +| `gitlabCommitPath` | String | 错误归因于 GitLab 提交的 GitLab 页面的路径 | +| `gitlabIssuePath` | String | GitLab 问题的网址 | +| `id` | ID! | ID (global ID) of the error | +| `lastReleaseLastCommit` | String | 提交错误最后一次出现 | +| `lastReleaseShortVersion` | String | 发布简短版本错误最后一次出现 | +| `lastReleaseVersion` | String | 发布版本错误最后一次出现 | +| `lastSeen` | Time! | 上次出现错误的时间戳 | +| `message` | String | 错误的哨兵元数据消息 | +| `sentryId` | String! | 错误的 ID(哨兵 ID) | +| `sentryProjectId` | ID! | 项目的 ID(哨兵项目) | +| `sentryProjectName` | String! | 受错误影响的项目名称 | +| `sentryProjectSlug` | String! | 错误造成的项目影响 | +| `shortId` | String! | 错误的简称(Sentry ID) | +| `status` | SentryErrorStatus! | 错误状态 | +| `tags` | SentryErrorTags! | 与哨兵错误相关的标签 | +| `title` | String! | 错误标题 | +| `type` | String! | 错误类型 | +| `userCount` | Int! | 受错误影响的用户数 | + +## SentryError[](#sentryerror "Permalink") + +哨兵错误. SentryDetailedError 的简化版本. + +| Name | Type | Description | +| --- | --- | --- | +| `count` | Int! | 发生次数 | +| `culprit` | String! | 错误的罪魁祸首 | +| `externalUrl` | String! | 错误的外部网址 | +| `firstSeen` | Time! | 首次发现错误的时间戳 | +| `frequency` | SentryErrorFrequency! =>数组 | 最近 24 小时的错误统计信息 | +| `id` | ID! | 错误的 ID(全局 ID) | +| `lastSeen` | Time! | 上次出现错误的时间戳 | +| `message` | String | 错误的哨兵元数据消息 | +| `sentryId` | String! | 错误的 ID(哨兵 ID) | +| `sentryProjectId` | ID! | 项目的 ID(哨兵项目) | +| `sentryProjectName` | String! | 受错误影响的项目名称 | +| `sentryProjectSlug` | String! | 错误造成的项目影响 | +| `shortId` | String! | 错误的简称(Sentry ID) | +| `status` | SentryErrorStatus! | 错误状态 | +| `title` | String! | 错误标题 | +| `type` | String! | 错误类型 | +| `userCount` | Int! | 受错误影响的用户数 | + +## SentryErrorCollection[](#sentryerrorcollection "Permalink") + +包含 Sentry 错误和详细错误的集合的对象. + +| Name | Type | Description | +| --- | --- | --- | +| `detailedError` | SentryDetailedError | 该项目的 Sentry 错误的详细版本 | +| `errorStackTrace` | SentryErrorStackTrace | 哨兵错误的堆栈跟踪 | +| `errors` | SentryErrorConnection | 哨兵错误的收集 | +| `externalUrl` | String | 哨兵的外部网址 | + +## SentryErrorFrequency[](#sentryerrorfrequency "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `count` | Int! | 自先前记录的时间以来收到的错误计数 | +| `time` | Time! | 记录错误频率统计信息的时间 | + +## SentryErrorStackTrace[](#sentryerrorstacktrace "Permalink") + +包含用于 Sentry 错误的堆栈跟踪条目的对象. + +| Name | Type | Description | +| --- | --- | --- | +| `dateReceived` | String! | Sentry 收到堆栈跟踪的时间 | +| `issueId` | String! | Sentry 错误的 ID | +| `stackTraceEntries` | SentryErrorStackTraceEntry! =>数组 | 堆栈跟踪条目的 Sentry 错误 | + +## SentryErrorStackTraceContext[](#sentryerrorstacktracecontext "Permalink") + +Sentry 错误堆栈跟踪的对象上下文 + +| Name | Type | Description | +| --- | --- | --- | +| `code` | String! | 上下文的代码号 | +| `line` | Int! | 上下文的行号 | + +## SentryErrorStackTraceEntry[](#sentryerrorstacktraceentry "Permalink") + +包含用于 Sentry 错误的堆栈跟踪条目的对象. + +| Name | Type | Description | +| --- | --- | --- | +| `col` | String | 发生哨兵错误的功能 | +| `fileName` | String | 发生 Sentry 错误的文件 | +| `function` | String | 发生哨兵错误的功能 | +| `line` | String | 发生哨兵错误的功能 | +| `traceContext` | SentryErrorStackTraceContext! =>数组 | Sentry 错误的上下文 | + +## SentryErrorTags[](#sentryerrortags "Permalink") + +哨兵状态错误 + +| Name | Type | Description | +| --- | --- | --- | +| `level` | String | 哨兵错误的严重程度 | +| `logger` | String | 哨兵记录仪错误 | + +## Snippet[](#snippet "Permalink") + +代表代码段条目 + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User | 摘要的所有者 | +| `blob` | SnippetBlob! | 摘要片段 | +| `blobs` | SnippetBlob! =>数组 | 摘要片段 | +| `createdAt` | Time! | 创建此片段的时间戳 | +| `description` | String | 片段说明 | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `fileName` | String | 片段的文件名 | +| `httpUrlToRepo` | String | 片段存储库的 HTTP URL | +| `id` | ID! | 摘要的 ID | +| `project` | Project | 代码段与之关联的项目 | +| `rawUrl` | String! | 代码段的原始 URL | +| `sshUrlToRepo` | String | 到代码段存储库的 SSH URL | +| `title` | String! | 摘要标题 | +| `updatedAt` | Time! | 此代码段的时间戳已更新 | +| `userPermissions` | SnippetPermissions! | 当前用户对该资源的权限 | +| `visibilityLevel` | VisibilityLevelsEnum! | 摘要的可见度级别 | +| `webUrl` | String! | 代码段的网址 | + +## SnippetBlob[](#snippetblob "Permalink") + +代表代码段 Blob + +| Name | Type | Description | +| --- | --- | --- | +| `binary` | Boolean! | 显示 Blob 是否为二进制 | +| `externalStorage` | String | Blob 外部存储 | +| `mode` | String | 斑点模式 | +| `name` | String | Blob 名称 | +| `path` | String | 斑点路径 | +| `plainData` | String | Blob 普通高亮数据 | +| `rawPath` | String! | Blob 原始内容端点路径 | +| `renderedAsText` | Boolean! | 显示 Blob 是否呈现为文本 | +| `richData` | String | Blob 高亮显示的数据 | +| `richViewer` | SnippetBlobViewer | Blob 内容丰富的查看器 | +| `simpleViewer` | SnippetBlobViewer! | Blob 内容简单查看器 | +| `size` | Int! | 斑点大小 | + +## SnippetBlobViewer[](#snippetblobviewer "Permalink") + +表示应如何显示 Blob 内容 + +| Name | Type | Description | +| --- | --- | --- | +| `collapsed` | Boolean! | 显示是否应折叠显示 Blob | +| `fileType` | String! | 内容文件类型 | +| `loadAsync` | Boolean! | 显示 blob 内容是否异步加载 | +| `loadingPartialName` | String! | 载入部分名称 | +| `renderError` | String | 呈现 Blob 内容时出错 | +| `tooLarge` | Boolean! | 显示斑点是否太大而无法显示 | +| `type` | BlobViewersType! | Blob 查看器类型 | + +## SnippetPermissions[](#snippetpermissions "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `adminSnippet` | Boolean! | 指示用户可以对此资源执行`admin_snippet` | +| `awardEmoji` | Boolean! | 表示用户可以在此资源上执行`award_emoji` | +| `createNote` | Boolean! | 指示用户可以在此资源上执行`create_note` | +| `readSnippet` | Boolean! | 指示用户可以对此资源执行`read_snippet` | +| `reportSnippet` | Boolean! | 指示用户可以对此资源执行`report_snippet` | +| `updateSnippet` | Boolean! | 指示用户可以对此资源执行`update_snippet` | + +## Submodule[](#submodule "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `flatPath` | String! | 条目的平坦路径 | +| `id` | ID! | 条目 ID | +| `name` | String! | 条目名称 | +| `path` | String! | 条目路径 | +| `sha` | String! | 提交的最后提交 sha | +| `treeUrl` | String | 子模块的树 URL | +| `type` | EntryType! | 树条目的类型 | +| `webUrl` | String | 子模块的 Web URL | + +## TaskCompletionStatus[](#taskcompletionstatus "Permalink") + +任务的完成状态 + +| Name | Type | Description | +| --- | --- | --- | +| `completedCount` | Int! | 完成的任务数 | +| `count` | Int! | 总任务数 | + +## TestReport[](#testreport "Permalink") + +表示需求测试报告. + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User | 测试报告的作者 | +| `createdAt` | Time! | 创建测试报告的时间戳 | +| `id` | ID! | 测试报告编号 | +| `state` | TestReportState! | 测试报告的状态 | + +## Timelog[](#timelog "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `date` | Time! | **不推荐使用:**使用`spentAt` . 在 12.10 中弃用 | +| `issue` | Issue | 记录时间已添加到的问题 | +| `spentAt` | Time | 跟踪时间的时间戳记 | +| `timeSpent` | Int! | 显示的时间(以秒为单位) | +| `user` | User! | 记录时间的用户 | + +## Todo[](#todo "Permalink") + +代表待办事项 + +| Name | Type | Description | +| --- | --- | --- | +| `action` | TodoActionEnum! | 待办事项的动作 | +| `author` | User! | 此待办事项的所有者 | +| `body` | String! | 待办事项的正文 | +| `createdAt` | Time! | 待办事项的时间戳记已创建 | +| `group` | Group | 与该待办事项相关的组 | +| `id` | ID! | 待办事项编号 | +| `project` | Project | 此待办事项与之相关的项目 | +| `state` | TodoStateEnum! | 待办事项的状态 | +| `targetType` | TodoTargetEnum! | 待办事项的目标类型 | + +## TodoMarkDonePayload[](#todomarkdonepayload "Permalink") + +自动生成的 TodoMarkDone 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `todo` | Todo! | 要求的待办事项 | + +## TodoRestoreManyPayload[](#todorestoremanypayload "Permalink") + +自动生成的 TodoRestoreMany 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `todos` | 一切! =>数组 | 全部更新 | +| `updatedIds` | ID! =>数组 | **不推荐使用:**使用待办事项. 在 13.2 中已弃用 | + +## TodoRestorePayload[](#todorestorepayload "Permalink") + +自动生成的 TodoRestore 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `todo` | Todo! | 要求的待办事项 | + +## TodosMarkAllDonePayload[](#todosmarkalldonepayload "Permalink") + +自动生成的 TodosMarkAllDone 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `todos` | 一切! =>数组 | 全部更新 | +| `updatedIds` | ID! =>数组 | **不推荐使用:**使用待办事项. 在 13.2 中已弃用 | + +## ToggleAwardEmojiPayload[](#toggleawardemojipayload "Permalink") + +自动生成的 ToggleAwardEmoji 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `awardEmoji` | AwardEmoji | 突变后的奖励表情符号 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `toggledOn` | Boolean! | 指示表情符号的状态. 如果切换开关授予表情符号,则为 true;如果切换开关删除了表情符号,则为 false. | + +## Tree[](#tree "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `lastCommit` | Commit | 树的最后提交 | + +## TreeEntry[](#treeentry "Permalink") + +代表目录 + +| Name | Type | Description | +| --- | --- | --- | +| `flatPath` | String! | 条目的平坦路径 | +| `id` | ID! | 条目 ID | +| `name` | String! | 条目名称 | +| `path` | String! | 条目路径 | +| `sha` | String! | 提交的最后提交 sha | +| `type` | EntryType! | 树条目的类型 | +| `webUrl` | String | 树条目(目录)的 Web URL | + +## UpdateAlertStatusPayload[](#updatealertstatuspayload "Permalink") + +自动生成的 UpdateAlertStatus 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `alert` | AlertManagementAlert | 突变后的警报 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后产生的问题 | +| `todo` | Todo | 突变后的待办事项 | + +## UpdateContainerExpirationPolicyPayload[](#updatecontainerexpirationpolicypayload "Permalink") + +自动生成的 UpdateContainerExpirationPolicy 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `containerExpirationPolicy` | ContainerExpirationPolicy | 变更后的容器到期政策 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## UpdateEpicPayload[](#updateepicpayload "Permalink") + +自动生成的 UpdateEpic 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `epic` | Epic | 突变后的史诗 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## UpdateImageDiffNotePayload[](#updateimagediffnotepayload "Permalink") + +自动生成的 UpdateImageDiffNote 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `note` | Note | 突变后的音符 | + +## UpdateIssuePayload[](#updateissuepayload "Permalink") + +自动生成的 UpdateIssue 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后的问题 | + +## UpdateIterationPayload[](#updateiterationpayload "Permalink") + +自动生成的 UpdateIteration 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `iteration` | Iteration | 更新的迭代 | + +## UpdateNotePayload[](#updatenotepayload "Permalink") + +自动生成的 UpdateNote 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `note` | Note | 突变后的音符 | + +## UpdateRequirementPayload[](#updaterequirementpayload "Permalink") + +自动生成的 UpdateRequirement 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `requirement` | Requirement | 突变后的要求 | + +## UpdateSnippetPayload[](#updatesnippetpayload "Permalink") + +自动生成的 UpdateSnippet 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `snippet` | Snippet | 突变后的代码段 | + +## User[](#user "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `avatarUrl` | String | URL of the user’s avatar | +| `id` | ID! | 用户 ID | +| `name` | String! | 用户易读的名称 | +| `state` | UserState! | 用户状态 | +| `userPermissions` | UserPermissions! | 当前用户对该资源的权限 | +| `username` | String! | 用户的用户名. 在此 GitLab 实例中是唯一的 | +| `webUrl` | String! | 用户的网址 | + +## UserPermissions[](#userpermissions "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `createSnippet` | Boolean! | 指示用户可以对此资源执行`create_snippet` | + +## VulnerabilitiesCountByDayAndSeverity[](#vulnerabilitiescountbydayandseverity "Permalink") + +表示在特定日期的特定严重性的漏洞数量 + +| Name | Type | Description | +| --- | --- | --- | +| `count` | Int | 漏洞数量 | +| `day` | ISO8601Date | 计数日期 | +| `severity` | VulnerabilitySeverity | 所计算漏洞的严重性 | + +## Vulnerability[](#vulnerability "Permalink") + +表示漏洞. + +| Name | Type | Description | +| --- | --- | --- | +| `description` | String | 漏洞描述 | +| `id` | ID! | 漏洞的 GraphQL ID | +| `identifiers` | 漏洞标识符! =>数组 | 漏洞的标识符. | +| `location` | VulnerabilityLocation | 漏洞的位置元数据. 其字段取决于发现漏洞的安全扫描的类型 | +| `primaryIdentifier` | VulnerabilityIdentifier | 漏洞的主要标识符. | +| `project` | Project | 发现漏洞的项目 | +| `reportType` | VulnerabilityReportType | 发现漏洞的安全报告的类型(SAST,DEPENDENCY_SCANNING,CONTAINER_SCANNING,DAST,SECRET_DETECTION,COVERAGE_FUZZING) | +| `scanner` | VulnerabilityScanner | 漏洞的扫描程序元数据. | +| `severity` | VulnerabilitySeverity | 漏洞的严重程度(INFO,未知,LOW,MEDIUM,HIGH,CRITICAL) | +| `state` | VulnerabilityState | 漏洞状态(检测,已拒绝,已解决,已确认) | +| `title` | String | 漏洞标题 | +| `userNotesCount` | Int! | 漏洞附带的用户注释数 | +| `userPermissions` | VulnerabilityPermissions! | 当前用户对该资源的权限 | +| `vulnerabilityPath` | String | 漏洞详细信息页面的 URL | + +## VulnerabilityIdentifier[](#vulnerabilityidentifier "Permalink") + +表示漏洞标识符. + +| Name | Type | Description | +| --- | --- | --- | +| `externalId` | String | 漏洞标识符的外部 ID | +| `externalType` | String | 漏洞标识符的外部类型 | +| `name` | String | 漏洞标识符的名称 | +| `url` | String | 漏洞标识符的 URL | + +## VulnerabilityIssueLink[](#vulnerabilityissuelink "Permalink") + +表示漏洞的问题链接. + +| Name | Type | Description | +| --- | --- | --- | +| `id` | ID! | 漏洞的 GraphQL ID | +| `issue` | Issue! | 问题附在问题链接上 | +| `linkType` | VulnerabilityIssueLinkType! | 问题链接的类型 | + +## VulnerabilityLocationContainerScanning[](#vulnerabilitylocationcontainerscanning "Permalink") + +表示通过容器安全扫描发现的漏洞的位置 + +| Name | Type | Description | +| --- | --- | --- | +| `dependency` | VulnerableDependency | 包含漏洞的依赖项 | +| `image` | String | 易受攻击的容器映像的名称 | +| `operatingSystem` | String | 在易受攻击的容器映像上运行的操作系统 | + +## VulnerabilityLocationDast[](#vulnerabilitylocationdast "Permalink") + +表示通过 DAST 扫描发现的漏洞的位置 + +| Name | Type | Description | +| --- | --- | --- | +| `hostname` | String | 漏洞请求的域名 | +| `param` | String | 发生漏洞的 URL 的查询参数 | +| `path` | String | 漏洞请求的 URL 路径和查询字符串 | +| `requestMethod` | String | 易受攻击请求的 HTTP 方法 | + +## VulnerabilityLocationDependencyScanning[](#vulnerabilitylocationdependencyscanning "Permalink") + +表示依赖关系安全扫描发现的漏洞的位置 + +| Name | Type | Description | +| --- | --- | --- | +| `dependency` | VulnerableDependency | 包含漏洞的依赖项 | +| `file` | String | 易受攻击文件的路径 | + +## VulnerabilityLocationSast[](#vulnerabilitylocationsast "Permalink") + +表示通过 SAST 扫描发现的漏洞的位置 + +| Name | Type | Description | +| --- | --- | --- | +| `endLine` | String | 易受攻击的文件中最后相关的行号 | +| `file` | String | 易受攻击文件的路径 | +| `startLine` | String | 漏洞文件中第一相关行的编号 | +| `vulnerableClass` | String | 包含漏洞的类 | +| `vulnerableMethod` | String | 包含漏洞的方法 | + +## VulnerabilityLocationSecretDetection[](#vulnerabilitylocationsecretdetection "Permalink") + +表示通过秘密检测扫描发现的漏洞的位置 + +| Name | Type | Description | +| --- | --- | --- | +| `endLine` | String | 易受攻击的文件中最后相关的行号 | +| `file` | String | 易受攻击文件的路径 | +| `startLine` | String | 漏洞文件中第一相关行的编号 | +| `vulnerableClass` | String | 包含漏洞的类 | +| `vulnerableMethod` | String | 包含漏洞的方法 | + +## VulnerabilityPermissions[](#vulnerabilitypermissions "Permalink") + +检查当前用户对漏洞的权限 + +| Name | Type | Description | +| --- | --- | --- | +| `adminVulnerability` | Boolean! | 指示用户可以对此资源执行`admin_vulnerability` | +| `adminVulnerabilityIssueLink` | Boolean! | 指示用户可以对此资源执行`admin_vulnerability_issue_link` | +| `createVulnerability` | Boolean! | 指示用户可以对此资源执行`create_vulnerability` | +| `createVulnerabilityExport` | Boolean! | 指示用户可以对此资源执行`create_vulnerability_export` | +| `createVulnerabilityFeedback` | Boolean! | 指示用户可以对此资源执行`create_vulnerability_feedback` | +| `destroyVulnerabilityFeedback` | Boolean! | 指示用户可以对此资源执行`destroy_vulnerability_feedback` | +| `readVulnerabilityFeedback` | Boolean! | 指示用户可以对此资源执行`read_vulnerability_feedback` | +| `updateVulnerabilityFeedback` | Boolean! | 指示用户可以对此资源执行`update_vulnerability_feedback` | + +## VulnerabilityScanner[](#vulnerabilityscanner "Permalink") + +表示漏洞扫描程序. + +| Name | Type | Description | +| --- | --- | --- | +| `externalId` | String | 漏洞扫描器的外部 ID | +| `name` | String | 漏洞扫描程序的名称 | +| `reportType` | VulnerabilityReportType | 漏洞报告的类型 | +| `vendor` | String | 漏洞扫描程序的供应商 | + +## VulnerabilitySeveritiesCount[](#vulnerabilityseveritiescount "Permalink") + +按严重性表示漏洞计数 + +| Name | Type | Description | +| --- | --- | --- | +| `critical` | Int | 项目严重程度的漏洞数量 | +| `high` | Int | 项目严重性高的漏洞数量 | +| `info` | Int | 项目的 INFO 严重性漏洞数量 | +| `low` | Int | 项目严重性为 LOW 的漏洞数量 | +| `medium` | Int | 项目 MEDIUM 严重程度的漏洞数量 | +| `unknown` | Int | 该项目严重程度未知的漏洞数量 | + +## VulnerableDependency[](#vulnerabledependency "Permalink") + +表示脆弱的依赖关系. 用于漏洞位置数据 + +| Name | Type | Description | +| --- | --- | --- | +| `package` | VulnerablePackage | 与弱势依赖项相关的软件包 | +| `version` | String | 脆弱依赖的版本 | + +## VulnerablePackage[](#vulnerablepackage "Permalink") + +表示易受攻击的程序包. 用于漏洞依赖性数据 + +| Name | Type | Description | +| --- | --- | --- | +| `name` | String | 易受攻击软件包的名称 | \ No newline at end of file diff --git a/_book/docs/387.md b/_book/docs/387.md new file mode 100644 index 0000000000000000000000000000000000000000..e083ab6cb171fc028f5f8e796f02a32c2af5c52c --- /dev/null +++ b/_book/docs/387.md @@ -0,0 +1,87 @@ +# API V3 to API V4 + +> 原文:[https://docs.gitlab.com/ee/api/v3_to_v4.html](https://docs.gitlab.com/ee/api/v3_to_v4.html) + +* [8.17](#817) +* [9.0](#90) + +# API V3 to API V4[](#api-v3-to-api-v4 "Permalink") + +从 GitLab 9.0 开始,API V4 是首选的版本. + +API V3 从 GitLab 9.5 不支持的,在 8 月 22 日公布,2017 年 API V3 中取出[GitLab 11.0](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36819) . V3 API 文档仍然[可用](https://gitlab.com/gitlab-org/gitlab-foss/blob/8-16-stable/doc/api/README.md) . + +以下是 V3 和 V4 之间所做的更改. + +## 8.17[](#817 "Permalink") + +* Removed `GET /projects/:search` (use: `GET /projects?search=x`) [!8877](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8877) +* `iid`过滤器已从`GET /projects/:id/issues` [!8967 中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8967)删除[.](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8967) +* `GET /projects/:id/merge_requests?iid[]=x&iid[]=y`数组过滤器已重命名为`iids` [!8793](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8793) +* `GET /projects/merge_request/:id`下的端点已被删除(使用: `GET /projects/merge_requests/:id` ) [!8793](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8793) +* 项目摘要不返回不建议使用的字段`expires_at` [!8723](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8723) +* `GET /projects/:id/keys`下的端点已被删除(使用`GET /projects/:id/deploy_keys` ) [!8716](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8716) + +## 9.0[](#90 "Permalink") + +* 当成员已经存在时,为`POST /projects/:id/members`返回状态 409 [!9093](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9093) +* Moved `DELETE /projects/:id/star` to `POST /projects/:id/unstar` [!9328](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9328) +* 删除了以下不建议使用的模板端点(仍然可以使用`/templates`前缀访问这些端点) [!8853](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8853) + * `/licenses` + * `/licenses/:key` + * `/gitignores` + * `/gitlab_ci_ymls` + * `/dockerfiles` + * `/gitignores/:key` + * `/gitlab_ci_ymls/:key` + * `/dockerfiles/:key` +* Moved `POST /projects/fork/:id` to `POST /projects/:id/fork` [!8940](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8940) +* Moved `DELETE /todos` to `POST /todos/mark_as_done` and `DELETE /todos/:todo_id` to `POST /todos/:todo_id/mark_as_done` [!9410](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9410) +* 项目过滤器不再作为`GET /projects/foo` ,而是作为`GET /projects?foo=true`代替[!8962](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8962) + * `GET /projects/visible`和`GET /projects/all`合并到`GET /projects` ,可以在有或没有授权的情况下使用 + * `GET /projects/owned`移至`GET /projects?owned=true` + * `GET /projects/starred`移至`GET /projects?starred=true` +* `GET /projects`返回当前用户可见的所有项目,即使该用户不是成员[!9674](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9674) + * 要获取用户所属的`GET /projects?membership=true` ,请使用`GET /projects?membership=true` +* 返回所有返回数组的端点的分页头[!8606](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8606) +* 添加了`POST /environments/:environment_id/stop`以停止环境[!8808](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8808) +* 删除了`DELETE /projects/:id/deploy_keys/:key_id/disable` 使用`DELETE /projects/:id/deploy_keys/:key_id`代替[!9366](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9366) +* Moved `PUT /users/:id/(block|unblock)` to `POST /users/:id/(block|unblock)` [!9371](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9371) +* 使订阅 API 更 RESTful. 使用`POST /projects/:id/:subscribable_type/:subscribable_id/subscribe`进行订阅,并使用`POST /projects/:id/:subscribable_type/:subscribable_id/unsubscribe`取消订阅资源. [!9325](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9325) +* 标签在`GET /projects/:id/issues`上过滤,并且`GET /issues`现在仅匹配包含所有标签的问题(即:逻辑 AND,而非 OR) [!8849](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8849) +* 将参数`branch_name`重命名为在以下端点上`branch` [!8936](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8936) + * `POST /projects/:id/repository/branches` + * `POST /projects/:id/repository/commits` + * `POST/PUT/DELETE :id/repository/files` +* 改名`merge_when_build_succeeds`参数`merge_when_pipeline_succeeds`以下端点: [!9335](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/) + * `PUT /projects/:id/merge_requests/:merge_request_id/merge` + * `POST /projects/:id/merge_requests/:merge_request_id/cancel_merge_when_pipeline_succeeds` + * `POST /projects` + * `POST /projects/user/:user_id` + * `PUT /projects/:id` +* Renamed `branch_name` to `branch` on `DELETE /projects/:id/repository/branches/:branch` response [!8936](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8936) +* 从项目的创建和编辑操作中删除`public`参数[!8736](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8736) +* 从返回问题列表或合并请求的响应中删除已`subscribed`字段. 获取单个问题或合并请求以获取已`subscribed` [!9661](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9661)的值 +* 在各处使用`visibility`作为字符串参数[!9337](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9337) +* Notes do not return deprecated field `upvote` and `downvote` [!9384](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9384) +* 创建或更新成员时,针对所有验证错误返回 HTTP 状态代码`400` ,而不是有时为`422`错误. [!9523](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9523) +* 删除`GET /groups/owned` . 使用`GET /groups?owned=true`代替[!9505](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9505) +* 在 V4 API 上以异步删除方式返回带有 JSON 正文的 202( `DELETE /projects/:id/repository/merged_branches`和`DELETE /projects/:id` ) [!9449](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9449) +* `GET /projects/:id/milestones?iid[]=x&iid[]=y`数组过滤器已重命名为`iids` [!9096](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9096) +* 在`GET /projects/:id/pipelines`返回有关管道的基本信息[!8875](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8875) +* 将所有`build`参考重命名为`job` [!9463](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9463) +* Drop `GET /projects/:id/repository/commits/:sha/jobs` [!9463](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9463) +* Rename Build Triggers to be Pipeline Triggers API [!9713](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9713) 将构建触发器重命名为管道触发器 API [!9713](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9713) + * `POST /projects/:id/trigger/builds` to `POST /projects/:id/trigger/pipeline` `POST /projects/:id/trigger/builds`到`POST /projects/:id/trigger/pipeline` + * Require description when creating a new trigger `POST /projects/:id/triggers` 创建新触发器`POST /projects/:id/triggers`时需要说明`POST /projects/:id/triggers` +* 简化环境端点上暴露的项目有效负载[!9675](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9675) +* API uses merge request `IID`s (internal ID, as in the web UI) rather than `ID`s. This affects the merge requests, award emoji, todos, and time tracking APIs. [!9530](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9530) +* API 使用问题`IID` (内部 ID,如 Web UI),而不使用`ID` . 这会影响问题,奖励表情符号,待办事项和时间跟踪 API. [!9530](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9530) +* 将`GET /projects/:id/repository/commits`上的初始页面从`0`更改为`1` (类似于 API 的其余部分) [!9679](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9679) +* 返回正确的`GET /projects/:id/repository/commits` `Link`标头数据[!9679](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9679) +* 更新存储库文件的端点[!9637](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9637) + * 将`GET /projects/:id/repository/files?file_path=:file_path`移到`GET /projects/:id/repository/files/:file_path` ( `:file_path`应该用 URL 编码) + * `GET /projects/:id/repository/blobs/:sha`现在返回由`:sha`标识的 blob 的 JSON 属性,而不是查找由`:sha`标识的提交,并在必需的`?filepath=:filepath`标识的那个提交中返回 blob 的原始内容`?filepath=:filepath` + * 将`GET /projects/:id/repository/commits/:sha/blob?file_path=:file_path`和`GET /projects/:id/repository/blobs/:sha?file_path=:file_path`移至`GET /projects/:id/repository/files/:file_path/raw?ref=:sha` + * `GET /projects/:id/repository/tree`参数`ref_name`已重命名为`ref`以保持一致性 +* `confirm`为参数`POST /users`已被弃用,取而代之的`skip_confirmation`参数 \ No newline at end of file diff --git a/_book/docs/388.md b/_book/docs/388.md new file mode 100644 index 0000000000000000000000000000000000000000..cce2b23ddea7c347afb4002fe759d0c97bf047b6 --- /dev/null +++ b/_book/docs/388.md @@ -0,0 +1,43 @@ +# Validate the `.gitlab-ci.yml` (API) + +> 原文:[https://docs.gitlab.com/ee/api/lint.html](https://docs.gitlab.com/ee/api/lint.html) + +# Validate the `.gitlab-ci.yml` (API)[](#validate-the-gitlab-ciyml-api "Permalink") + +在 GitLab 8.12 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5953) . + +检查您的`.gitlab-ci.yml`文件是否有效. + +``` +POST /ci/lint +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `content` | string | yes | the `.gitlab-ci.yaml` content | + +``` +curl --header "Content-Type: application/json" "https://gitlab.example.com/api/v4/ci/lint" --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}' +``` + +请务必复制并粘贴`.gitlab-ci.yml`的确切内容,因为 YAML 对于缩进和空格非常挑剔. + +响应示例: + +* 有效内容: + + ``` + { "status": "valid", "errors": [] } + ``` + +* 无效的内容: + + ``` + { "status": "invalid", "errors": [ "variables config should be a hash of key value pairs" ] } + ``` + +* 没有 content 属性: + + ``` + { "error": "content is missing" } + ``` \ No newline at end of file diff --git a/_book/docs/389.md b/_book/docs/389.md new file mode 100644 index 0000000000000000000000000000000000000000..4788610e5c046492f5f20a9ad136ae5f587c1b0f --- /dev/null +++ b/_book/docs/389.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/api/oauth2.html](https://docs.gitlab.com/ee/api/oauth2.html) \ No newline at end of file diff --git a/_book/docs/390.md b/_book/docs/390.md new file mode 100644 index 0000000000000000000000000000000000000000..f78cfbb934bcd083545ec5ea4e3031b311231e0c --- /dev/null +++ b/_book/docs/390.md @@ -0,0 +1,167 @@ +# User Docs + +> 原文:[https://docs.gitlab.com/ee/user/](https://docs.gitlab.com/ee/user/) + +* [Overview](#overview) + * [Concepts](#concepts) +* [Use cases](#use-cases) +* [Projects](#projects) +* [GitLab CI/CD](#gitlab-cicd) +* [Account](#account) +* [Groups](#groups) +* [Discussions](#discussions) + * [GitLab Flavored Markdown (GFM)](#gitlab-flavored-markdown-gfm) +* [Todos](#todos) +* [Search](#search) +* [Snippets](#snippets) +* [Keyboard shortcuts](#keyboard-shortcuts) +* [Integrations](#integrations) +* [Webhooks](#webhooks) +* [API](#api) +* [Git and GitLab](#git-and-gitlab) +* [Instance statistics](#instance-statistics) +* [Operations Dashboard](#operations-dashboard-premium) + +# User Docs[](#user-docs "Permalink") + +欢迎来到 GitLab! 我们很高兴您在这里! + +作为 GitLab 用户,您将有权访问您的[订阅](https://about.gitlab.com/pricing/)包括的所有功能,但[GitLab 管理员](../administration/index.html)设置除外,除非您具有安装,配置和升级 GitLab 实例的管理员权限. + +[GitLab.com 的](https://gitlab.com/)管理员特权仅限于 GitLab 团队. + +有关配置 GitLab 自管理实例的更多信息,请参阅[管理员文档](../administration/index.html) . + +## Overview[](#overview "Permalink") + +GitLab 是一个完全集成的软件开发平台,使您的团队能够在同一平台上保持透明,快速,有效和凝聚力,从讨论新想法到正式生产. + +有关更多信息,请参见[所有 GitLab 功能](https://about.gitlab.com/features/) . + +### Concepts[](#concepts "Permalink") + +要熟悉在 GitLab 上开发代码所需的概念,请阅读以下文章: + +* [Demo: Mastering Code Review With GitLab](https://about.gitlab.com/blog/2017/03/17/demo-mastering-code-review-with-gitlab/). +* [GitLab Workflow: An Overview](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/#gitlab-workflow-use-case-scenario). +* [教程:在 GitLab 中都已连接](https://about.gitlab.com/blog/2016/03/08/gitlab-tutorial-its-all-connected/) :与 GitLab 进行代码协作的概述. +* [Trends in Version Control Land: Microservices](https://about.gitlab.com/blog/2016/08/16/trends-in-version-control-land-microservices/). +* [Trends in Version Control Land: Innersourcing](https://about.gitlab.com/blog/2016/07/07/trends-version-control-innersourcing/). + +## Use cases[](#use-cases "Permalink") + +GitLab 是一个基于 Git 的平台,它集成了许多用于软件开发和部署以及项目管理的基本工具: + +* 通过版本控制在存储库中托管代码. +* 使用功能齐全的[问题跟踪器](project/issues/index.html#issues-list)跟踪有关新实现,错误报告和反馈的建议. +* 组织和[发行委员会的](project/issues/index.html#issue-boards)优先次序. +* 使用[Review Apps](../ci/review_apps/index.html)查看[合并请求中](project/merge_requests/index.html)每个分支的实时预览更改中的代码. +* 使用内置的[持续集成进行](../ci/README.html)构建,测试和部署. +* 使用[GitLab Pages](project/pages/index.html)部署个人和专业静态网站. +* 通过使用[GitLab 容器注册表](packages/container_registry/index.html)与 Docker 集成. +* 通过使用[GitLab 价值流分析](project/cycle_analytics.html)跟踪开发生命周期. +* 提供[服务台](project/service_desk.html)支持. + +使用 GitLab 企业版,您还可以: + +* 通过以下方式改善协作: + * [合并请求批准](project/merge_requests/merge_request_approvals.html) . + * [问题的多个受让人](project/issues/multiple_assignees_for_issues.html) . + * [多个发行委员会](project/issue_board.html#multiple-issue-boards) . +* 在[相关问题](project/issues/related_issues.html)之间创建正式关系. +* 使用[Burndown Charts](project/milestones/burndown_charts.html)可以在冲刺期间或在使用其新版本软件时跟踪进度. +* 利用[Elasticsearch](../integration/elasticsearch.html)和[Advanced Global Search](search/advanced_global_search.html)和[Advanced Syntax Search](search/advanced_search_syntax.html)在整个 GitLab 实例上进行更快,更高级的代码搜索. +* [Authenticate users with Kerberos](../integration/kerberos.html). +* 从本地服务器上的其他地方[镜像存储库](project/repository/repository_mirroring.html) . +* [Export issues as CSV](project/issues/csv_export.html). +* 使用[Multiple-Project Pipelines](../ci/multi_project_pipeline_graphs.html)查看涉及多个项目的整个 CI / CD [管道](../ci/multi_project_pipeline_graphs.html) . +* [锁定文件](project/file_lock.html)以防止冲突. +* 使用[Deploy Boards](project/deploy_boards.html)查看在 Kubernetes 上运行的每个 CI 环境的当前运行状况和状态. +* 利用[Canary 部署的](project/canary_deployments.html)连续交付方法. +* 扫描您的代码中的漏洞, [并在合并请求中显示它们](application_security/sast/index.html) . + +您还可以[将](project/integrations/overview.html) GitLab 与众多第三方应用程序[集成](project/integrations/overview.html) ,例如 Mattermost,Microsoft Teams,HipChat,Trello,Slack,Bamboo CI,Jira 等. + +## Projects[](#projects "Permalink") + +在 GitLab 中,您可以创建[项目](project/index.html)来托管代码,跟踪问题,在代码上进行协作以及使用内置的 GitLab CI / CD 持续构建,测试和部署应用程序. 或者,您可以从一个项目中一次完成所有操作. + +* [存储库](project/repository/index.html) :将代码[库](project/repository/index.html)托管在具有版本控制的存储库中,并作为完全集成平台的一部分. +* [问题](project/issues/index.html) :探索 GitLab 问题的最佳功能. +* [合并请求](project/merge_requests/index.html) :在代码,评论,每个分支的实时预览更改方面进行协作,并通过合并请求请求批准. +* [里程碑](project/milestones/index.html) :处理多个问题,并与里程碑在同一目标日期合并请求. + +## GitLab CI/CD[](#gitlab-cicd "Permalink") + +使用内置的[GitLab CI / CD](../ci/README.html)直接从 GitLab 测试,构建和部署应用程序. 无需第三方集成. + +* [GitLab Auto Deploy](../topics/autodevops/stages.html#auto-deploy) :通过 GitLab Auto Deploy 开箱即用地部署您的应用程序. +* [Review Apps](../ci/review_apps/index.html) :实时预览带有 Review Apps 的合并请求所引入的更改. +* [GitLab 页面](project/pages/index.html) :使用 GitLab 页面直接从 GitLab 发布您的静态站点. 您可以使用 Pages 构建,测试和部署任何静态站点生成器. +* [GitLab Container Registry](packages/container_registry/index.html) :使用 Container Registry 构建和部署 Docker 映像. + +## Account[](#account "Permalink") + +您可以自定义和配置很多东西,以享受 GitLab 的最佳体验. + +* [设置](profile/index.html) :管理用户设置以更改您的个人信息,个人访问令牌,授权的应用程序等. +* [身份验证](../topics/authentication/index.html) :通读 GitLab 中可用的身份验证方法. +* [权限](permissions.html) :了解每种用户类型(访客,记者,开发人员,维护人员,所有者)的不同权限级别集. +* [功能亮点](feature_highlight.html) :了解有关应用周围的小蓝点的更多信息,这些小点可以解释某些功能. +* [滥用报告](abuse_reports.html) :向 GitLab 管理员报告用户的[滥用情况](abuse_reports.html) . + +## Groups[](#groups "Permalink") + +使用 GitLab [组,](group/index.html)您可以将相关项目组合在一起,并授予成员一次访问多个项目的权限. + +组也可以嵌套在[子组中](group/subgroups/index.html) . + +## Discussions[](#discussions "Permalink") + +在 GitLab 中,您可以在问题,合并请求,代码段和提交中注释和提及合作者. + +通过合并请求对代码库的实现执行内联检查时,可以通过[可解析的线程](discussions/index.html#resolvable-comments-and-threads)收集反馈. + +### GitLab Flavored Markdown (GFM)[](#gitlab-flavored-markdown-gfm "Permalink") + +通读[GFM 文档,](markdown.html)以了解如何在线程,注释,问题和合并请求描述以及所有支持 GFM 的其他地方应用最好的 GitLab 风味 Markdown. + +## Todos[](#todos "Permalink") + +Never forget to reply to your collaborators. [GitLab Todos](todos.html) are a tool for working faster and more effectively with your team, by listing all user or group mentions, as well as issues and merge requests you’re assigned to. + +## Search[](#search "Permalink") + +[搜索和筛选](search/index.html)组,项目,问题,合并请求,文件,代码等. + +## Snippets[](#snippets "Permalink") + +[片段](snippets.html)是您要存储在 GitLab 中的代码块,您可以从中快速访问它们. 您还可以通过" [讨论"](#discussions)收集有关它们的反馈. + +## Keyboard shortcuts[](#keyboard-shortcuts "Permalink") + +GitLab 中有许多[键盘快捷键](shortcuts.html) ,可帮助您在页面之间导航并更快地完成任务. + +## Integrations[](#integrations "Permalink") + +[将 GitLab](../integration/README.html)与您喜欢的工具(例如 Trello,Jira 等) [集成](../integration/README.html) . + +## Webhooks[](#webhooks "Permalink") + +配置[webhook](project/integrations/webhooks.html)以侦听特定事件,例如推送,问题或合并请求. GitLab 会将带有数据的 POST 请求发送到 webhook URL. + +## API[](#api "Permalink") + +通过[API](../api/README.html)自动化 GitLab. + +## Git and GitLab[](#git-and-gitlab "Permalink") + +了解什么是[Git](../topics/git/index.html)及其最佳实践. + +## Instance statistics[](#instance-statistics "Permalink") + +查看您的 GitLab 实例的[各种统计信息](instance_statistics/index.html) . + +## Operations Dashboard[](#operations-dashboard-premium "Permalink") + +See [Operations Dashboard](operations_dashboard/index.html) for a summary of each project’s operational health. \ No newline at end of file diff --git a/_book/docs/391.md b/_book/docs/391.md new file mode 100644 index 0000000000000000000000000000000000000000..c59744cfd180826c893636e0dfbd02cb528331bc --- /dev/null +++ b/_book/docs/391.md @@ -0,0 +1,62 @@ +# Abuse reports + +> 原文:[https://docs.gitlab.com/ee/user/abuse_reports.html](https://docs.gitlab.com/ee/user/abuse_reports.html) + +* [Reporting abuse through a user’s profile](#reporting-abuse-through-a-users-profile) +* [Reporting abuse through a user’s comment](#reporting-abuse-through-a-users-comment) +* [Reporting abuse through a user’s issue or merge request](#reporting-abuse-through-a-users-issue-or-merge-request) +* [Managing abuse reports](#managing-abuse-reports) + +# Abuse reports[](#abuse-reports "Permalink") + +您可以将其他 GitLab 用户的滥用情况报告给 GitLab 管理员. + +然后,GitLab 管理员[可以选择](admin_area/abuse_reports.html) : + +* 删除用户,这会将其从实例中删除. +* 阻止用户,这将拒绝他们访问实例. +* 或删除报告,以保留用户对实例的访问权限. + +您可以通过以下方式报告用户: + +* [Profile](#reporting-abuse-through-a-users-profile) +* [Comments](#reporting-abuse-through-a-users-comment) +* [Issues and Merge requests](#reporting-abuse-through-a-users-issue-or-merge-request) + +## Reporting abuse through a user’s profile[](#reporting-abuse-through-a-users-profile "Permalink") + +要从用户的个人资料页面举报滥用行为,请执行以下操作: + +1. 单击用户个人资料右上方的感叹号报告滥用按钮. +2. 完成滥用情况报告. +3. Click the **发送报告** button. + +## Reporting abuse through a user’s comment[](#reporting-abuse-through-a-users-comment "Permalink") + +要报告用户评论中的滥用行为,请执行以下操作: + +1. 单击垂直省略号(⋮)其他操作按钮以打开下拉列表. +2. Select **举报为滥用**. +3. 完成滥用情况报告. +4. 点击**发送报告**按钮. + +**注意:**在滥用情况报告的" **消息"**字段中,将预先填写报告用户评论的 URL. + +## Reporting abuse through a user’s issue or merge request[](#reporting-abuse-through-a-users-issue-or-merge-request "Permalink") + +**报告滥用**按钮显示在问题或合并请求的右上方: + +* 对于单击有权关闭问题或合并请求的用户,从单击" **关闭问题"**或" **关闭合并请求"**按钮时出现的菜单中选择**"报告滥用**情况". +* 查看问题或合并请求时,对于没有权限关闭问题或合并请求的用户. + +显示" **举报滥用行为"**按钮后,要提交滥用行为报告: + +1. 点击**举报滥用行为**按钮. +2. 提交滥用情况报告. +3. 点击**发送报告**按钮. + +**注意:**在滥用情况报告的" **消息"**字段中,将预先填写报告用户的问题或合并请求的 URL. + +## Managing abuse reports[](#managing-abuse-reports "Permalink") + +管理员能够查看和解决滥用报告. 有关更多信息,请参阅[滥用报告管理文档](admin_area/abuse_reports.html) . \ No newline at end of file diff --git a/_book/docs/392.md b/_book/docs/392.md new file mode 100644 index 0000000000000000000000000000000000000000..91c404f217544cca8344dc3a2d3ae6fb4d389922 --- /dev/null +++ b/_book/docs/392.md @@ -0,0 +1,248 @@ +# User account + +> 原文:[https://docs.gitlab.com/ee/user/profile/](https://docs.gitlab.com/ee/user/profile/) + +* [Creating users](#creating-users) +* [Signing in](#signing-in) + * [Unknown sign-in](#unknown-sign-in) +* [User profile](#user-profile) +* [Profile settings](#profile-settings) +* [Changing your password](#changing-your-password) +* [Changing your username](#changing-your-username) +* [Private profile](#private-profile) +* [Add details of external accounts](#add-details-of-external-accounts) +* [Private contributions](#private-contributions) +* [Current status](#current-status) +* [Commit email](#commit-email) + * [Private commit email](#private-commit-email) +* [Troubleshooting](#troubleshooting) + * [Why do I keep getting signed out?](#why-do-i-keep-getting-signed-out) + * [Increased sign-in time](#increased-sign-in-time) + +# User account[](#user-account "Permalink") + +每个 GitLab 帐户都有一个用户个人资料和设置. 您的[个人资料](#user-profile)包含有关您以及您的 GitLab 活动的信息. 您的[设置](#profile-settings)允许您自定义 GitLab 的某些方面以适合自己. + +## Creating users[](#creating-users "Permalink") + +在 GitLab 上有几种创建用户的方法. 有关更多详细信息,请参见[创建用户文档](account/create_accounts.html) . + +## Signing in[](#signing-in "Permalink") + +有几种方法可以登录您的 GitLab 帐户. 有关更多详细信息,请参见[身份验证主题](../../topics/authentication/index.html) . + +### Unknown sign-in[](#unknown-sign-in "Permalink") + +GitLab will notify you if a sign-in occurs that is from an unknown IP address or device. See [Unknown Sign-In Notification](unknown_sign_in_notification.html) for more details. + +## User profile[](#user-profile "Permalink") + +要访问您的个人资料: + +1. 单击您的头像. +2. Select **Profile**. + +在您的个人资料页面上,您将看到以下信息: + +* 个人信息 +* 活动流:查看您的活动流线和贡献历史 +* 组: [组](../group/index.html)你的成员 +* 参与的项目:您参与的[项目](../project/index.html) +* 个人项目:您的个人项目(尊重项目的可见性级别) +* 已加星标的项目:您已加星标的项目 +* 片段:您的个人代码[片段](../snippets.html#personal-snippets) + +## Profile settings[](#profile-settings "Permalink") + +要访问您的个人资料设置: + +1. 单击您的头像. +2. Select **Settings**. + +从那里,您可以: + +* 更新您的个人信息 +* 修改[密码](#changing-your-password) +* 为您的个人资料设置[自定义状态](#current-status) +* 管理您的个人资料的[提交电子邮件](#commit-email) +* Manage [2FA](account/two_factor_authentication.html) +* 添加[外部帐户的](#add-details-of-external-accounts)详细信息. +* 更改您的用户名并[删除您的帐户](account/delete_account.html) +* 管理可以[将 GitLab 用作 OAuth 提供](../../integration/oauth_provider.html#introduction-to-oauth)程序的应用[程序](../../integration/oauth_provider.html#introduction-to-oauth) +* 管理[个人访问令牌](personal_access_tokens.html)以通过 API 和授权的应用程序访问您的帐户 +* 添加和删​​除链接到您帐户的电子邮件 +* 选择用于[通知](notifications.html) ,基于 Web 的提交并显示在您的公开个人资料上的电子邮件 +* 管理[SSH 密钥](../../ssh/README.html)以通过 SSH 访问您的帐户 +* 管理您的[首选项](preferences.html#syntax-highlighting-theme)以自定义自己的 GitLab 体验 +* [查看您的活动会话](active_sessions.html)并在必要时撤消其中的任何一个 +* 访问审核日志,这是涉及您帐户的重要事件的安全日志 + +## Changing your password[](#changing-your-password "Permalink") + +1. 导航到您的[个人资料的](#profile-settings) **设置>密码** . +2. 在"当前密码"字段中输入您的当前密码. +3. 两次输入所需的新密码,一次在"新密码"字段中,一次在"密码确认"字段中. +4. 点击"保存密码"按钮. + +如果您不知道当前密码,请选择"我忘记了密码"链接. + +[![Change your password](img/87be547831d2207399009a0f9dd4b91a.png)](./img/change_password_v13_0.png) + +## Changing your username[](#changing-your-username "Permalink") + +`username`是与用户 ID 相关的唯一[`namespace`](../group/index.html#namespaces) . 对其进行更改可能会产生意想不到的副作用,请在继续之前阅读[重定向的行为](../project/index.html#redirects-when-changing-repository-paths) . + +更改`username` : + +1. 导航到您的[个人资料的](#profile-settings) **设置>帐户** . +2. 在**更改用户**名下输入新的用户**名** . +3. Click **更新用户名**. + +**注意:**如果用户名包含带有[Container Registry](../packages/container_registry/index.html)标签的项目,则当前无法更改用户名,因为该项目无法移动.**提示:**如果要保留对原始名称空间的所有权并保护 URL 重定向,则可以更改一个组并向其传输项目,而无需更改组的路径或重命名用户名. 另外,您可以按照[《 GitLab 团队手册》中的详细步骤进行操作,该手册](https://about.gitlab.com/handbook/tools-and-tips/#how-to-change-your-username-at-gitlabcom)还介绍了使用[GitLab Pages](../project/pages/index.html)托管项目的情况. + +## Private profile[](#private-profile "Permalink") + +如果启用了此功能,将从用户配置文件页面( `https://gitlab.example.com/username` )中隐藏以下信息: + +* 原子饲料 +* 创建帐户的日期 +* 活动标签 +* 组选项卡 +* 参与项目标签 +* 个人项目标签 +* 已加星标的项目标签 +* 片段标签 + +要启用私人资料: + +1. 单击您的头像. +2. Select **Profile**. +3. 单击**编辑配置文件** (铅笔图标). +4. 在" **主要设置"**部分中选中" **私人个人资料"**选项. +5. Click **更新配置文件设置**. + +**Note:** All your profile information can be seen by yourself, and GitLab admins, even if the **私人简介** option is enabled. + +## Add details of external accounts[](#add-details-of-external-accounts "Permalink") + +GitLab 允许您将链接添加到您可能拥有的某些其他外部帐户,例如 Skype 和 Twitter. 他们可以帮助其他用户在其他平台上与您建立联系. + +要将链接添加到其他帐户: + +1. 单击您的头像. +2. Select **Profile**. +3. 单击**编辑配置文件** (铅笔图标). +4. 在" **主要设置"**部分中完成外部帐户的所需字段: + * Skype 的 + * 推特 + * 领英 +5. Click **更新配置文件设置**. + +## Private contributions[](#private-contributions "Permalink") + +在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14078) . + +启用私人捐款将包括对私人项目的捐款,用户捐款日历图和用户最近的活动. + +要启用私人捐款: + +1. 单击您的头像. +2. Select **Profile**. +3. 单击**编辑配置文件** (铅笔图标). +4. 选中**私人捐款**选项. +5. Click **更新配置文件设置**. + +## Current status[](#current-status "Permalink") + +在 GitLab 11.2 中引入. + +您可以为用户个人资料提供自定义状态消息以及描述它的表情符号. 当您不在办公室或不在家时,这可能会有所帮助. 然后,其他用户可以在回答您的问题或为您分配工作时考虑您的身份. 请注意,即使您的[个人资料是私人的](#private-profile) ,您的状态也是公开可见的. + +状态消息限制为 100 个纯文本字符. 但是,它们可能包含表情符号代码,例如" `I'm on vacation :palm_tree:` . + +设置当前状态: + +1. 单击您的头像. +2. 点击**设置状态** ,或点击**编辑状态(**如果您已经设置了状态). +3. 设置所需的表情符号和/或状态消息. +4. 点击**设置状态** . 或者,您可以单击" **删除状态"**以完全删除您的用户状态. + +or + +1. 单击您的头像. +2. Select **Profile**. +3. 单击**编辑配置文件** (铅笔图标). +4. 在**您的状态**文本字段中输入您的状态消息. +5. 点击**添加状态表情符号** (笑脸),然后选择所需的表情符号. +6. Click **更新配置文件设置**. + +您还可以[使用 API](../../api/users.html#user-status)设置当前状态. + +## Commit email[](#commit-email "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21598) . + +提交电子邮件是在通过 GitLab 界面执行的每个与 Git 相关的操作中显示的电子邮件地址. + +您自己的任何已验证电子邮件地址都可以用作提交电子邮件. + +要更改您的提交电子邮件: + +1. 单击您的头像. +2. Select **Profile**. +3. 单击**编辑配置文件** (铅笔图标). +4. Click **提交电子邮件** dropdown. +5. 选择任何已验证的电子邮件. +6. Click **更新配置文件设置**. + +### Private commit email[](#private-commit-email "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22560) . + +GitLab 为用户提供了一个自动生成的私人提交电子邮件选项,该选项允许用户将其电子邮件信息保密. + +要启用此选项: + +1. 单击您的头像. +2. Select **Profile**. +3. 单击**编辑配置文件** (铅笔图标). +4. Click **提交电子邮件** dropdown. +5. Select **使用私人电子邮件** option. +6. Click **更新配置文件设置**. + +启用此选项后,将使用私有提交电子邮件执行与 Git 相关的所有操作. + +要保持完全匿名,您还可以复制此私人提交电子邮件,并使用以下命令在本地计算机上对其进行配置: + +``` +git config --global user.email +``` + +## Troubleshooting[](#troubleshooting "Permalink") + +### Why do I keep getting signed out?[](#why-do-i-keep-getting-signed-out "Permalink") + +登录主 GitLab 应用程序时,将设置`_gitlab_session` cookie. `_gitlab_session`在您关闭浏览器时在客户端清除,并在"应用程序设置->会话持续时间(分钟)" / `session_expire_delay` (默认为`10080`分钟= 7 天)后过期. + +登录到主要的 GitLab 应用程序时,您还可以选中" Remember me"选项,该选项设置了`remember_user_token` cookie(通过[`devise`](https://github.com/heartcombo/devise) ). `remember_user_token`之后到期`config/initializers/devise.rb` > - `config.remember_for` (默认为 2 周). + +当`_gitlab_session`过期或不可用,GitLab 使用`remember_user_token`让你一个新的`_gitlab_session` ,让你在浏览器中通过重新签署. + +你的后`remember_user_token`到期,你的`_gitlab_session`清/过期,你会被要求再次登录验证您的身份出于安全原因. + +### Increased sign-in time[](#increased-sign-in-time "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/20340) . + +该`remember_user_token`一个 cookie 的寿命,现在可以通过超出期限延长集`config.remember_for` ,作为`config.extend_remember_period`标志现在设置为 true. + +GitLab 使用会话和持久性 Cookie: + +* 会话 cookie:通常,在关闭浏览器后,会话 cookie 会在浏览器会话结束时删除. `_gitlab_session` cookie 没有到期日期. +* 永久性 cookie: `remember_me_token`是有效期为两周的 cookie. 如果您在登录时单击"记住我",则 GitLab 会激活此 cookie. + +默认情况下,服务器在使用的任何会话上将生存时间(TTL)设置为 1 周. + +当您关闭浏览器时,会话 cookie 可能仍然保留. 例如,Chrome 具有"恢复上次退出的位置"选项,该选项可还原会话 Cookie. 换句话说,只要您每两周至少访问 GitLab 一次,只要打开浏览器选项卡,就可以保持登录状态. 无论是否安装了 2FA,服务器都会继续为该会话重置 TTL.如果关闭浏览器并再次打开它,则`remember_user_token`用户令牌 cookie 允许您的用户重新进行身份验证. + +如果没有`config.extend_remember_period`标志,则两周后您将被迫再次登录. \ No newline at end of file diff --git a/_book/docs/393.md b/_book/docs/393.md new file mode 100644 index 0000000000000000000000000000000000000000..a1f86b48349efe0ba22f3eaf42bb8d146d186ca9 --- /dev/null +++ b/_book/docs/393.md @@ -0,0 +1,32 @@ +# Active sessions + +> 原文:[https://docs.gitlab.com/ee/user/profile/active_sessions.html](https://docs.gitlab.com/ee/user/profile/active_sessions.html) + +* [Listing all active sessions](#listing-all-active-sessions) +* [Active sessions limit](#active-sessions-limit) +* [Revoking a session](#revoking-a-session) + +# Active sessions[](#active-sessions "Permalink") + +在 GitLab 10.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17867) . + +GitLab 列出了已登录到您帐户的所有设备. 这使您可以查看会话,并撤销所有您不认识的会话. + +## Listing all active sessions[](#listing-all-active-sessions "Permalink") + +1. 单击您的头像. +2. Select **Settings**. +3. 点击边栏中的**活动会话** . + +[![Active sessions list](img/2d1845503f8ff90d4dc71459313e4e62.png)](img/active_sessions_list.png) + +## Active sessions limit[](#active-sessions-limit "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31611) . + +GitLab 允许用户一次拥有多达 100 个活动会话. 如果活动会话数超过 100,则最早的会话将被删除. + +## Revoking a session[](#revoking-a-session "Permalink") + +1. 使用前面的步骤导航到" **活动会话"** . +2. 单击除会话外的**撤消** . 当前会话无法撤消,因为这将使您退出 GitLab. \ No newline at end of file diff --git a/_book/docs/394.md b/_book/docs/394.md new file mode 100644 index 0000000000000000000000000000000000000000..1d57720712c71d3336c854d982e4c4d5770779d8 --- /dev/null +++ b/_book/docs/394.md @@ -0,0 +1,63 @@ +# Deleting a User account + +> 原文:[https://docs.gitlab.com/ee/user/profile/account/delete_account.html](https://docs.gitlab.com/ee/user/profile/account/delete_account.html) + +* [As a user](#as-a-user) +* [As an administrator](#as-an-administrator) +* [Associated Records](#associated-records) + +# Deleting a User account[](#deleting-a-user-account "Permalink") + +可以通过以下方法从 GitLab 实例中删除用户: + +* 用户自己. +* 管理员. + +**注意:**删除用户将删除该用户名称空间中的所有项目. + +## As a user[](#as-a-user "Permalink") + +作为用户,您可以通过以下方式删除自己的帐户: + +1. 点击您的头像. +2. 导航至**设置>帐户** . +3. Selecting **删除帐户**. + +## As an administrator[](#as-an-administrator "Permalink") + +作为管理员,您可以通过以下方式删除用户帐户: + +1. 导航到**管理区域>概述>用户** . +2. 选择一个用户. +3. 在" **帐户"**标签下,单击: + * **删除用户**仅**删除用户** ,但保留其[相关记录](#associated-records) . + * **删除用户和贡献**以删除用户及其相关记录. + +**危险:**使用" **删除用户和贡献"**选项可能会导致删除的数据超出预期. [有关](#associated-records)其他详细信息,请参见下面的[关联记录](#associated-records) . + +## Associated Records[](#associated-records "Permalink") + +版本历史 + +* 针对[GitLab 9.0 中的](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7393)问题进行了介绍. +* 在[GitLab 9.1 中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10467)引入了合并请求,奖励表情符号,注释和滥用报告. +* 从滥用报告和垃圾邮件日志中进行硬删除是在[GitLab 9.1](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10273)中以及从[GitLab 9.3 中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11853)的 API 中引入的. + +有两种删除用户的选项: + +* **Delete user** +* **删除用户和贡献** + +使用" **删除用户"**选项时,并非所有关联记录都随用户一起删除. 以下是**不会**删除的内容的列表: + +* 用户创建的问题. +* 合并用户创建的请求. +* 注意用户创建的. +* 用户报告了滥用报告. +* 用户创建的奖励表情符号. + +这些记录将被删除,而不是被删除,而是被移至用户名" Ghost User"的系统级用户,其唯一目的是充当此类记录的容器. 删除的用户所做的任何提交仍将显示原始用户的用户名. + +使用" **删除用户和贡献"**选项时,将**删除** **所有**关联的记录. 这包括上面提到的所有项目,包括问题,合并请求,注释/评论等等. 考虑[阻止用户](../../admin_area/blocking_unblocking_users.html)或使用" **删除用户"**选项. + +从[滥用情况报告](../../admin_area/abuse_reports.html)或垃圾邮件日志中删除用户时,这些关联的记录不会被重影,并且会与该用户的唯一所有者一起删除. 从[API](../../../api/users.html#user-deletion)或管理区域中删除用户时,管理员也可以请求此行为. \ No newline at end of file diff --git a/_book/docs/395.md b/_book/docs/395.md new file mode 100644 index 0000000000000000000000000000000000000000..4ad2b1e87d86ddf9ca076baa9cdde9428c5103c8 --- /dev/null +++ b/_book/docs/395.md @@ -0,0 +1,419 @@ +# Permissions + +> 原文:[https://docs.gitlab.com/ee/user/permissions.html](https://docs.gitlab.com/ee/user/permissions.html) + +* [Principles behind permissions](#principles-behind-permissions) +* [Instance-wide user permissions](#instance-wide-user-permissions) +* [Project members permissions](#project-members-permissions) +* [Project features permissions](#project-features-permissions) + * [Wiki and issues](#wiki-and-issues) + * [Protected branches](#protected-branches) + * [Value Stream Analytics permissions](#value-stream-analytics-permissions) + * [Issue Board permissions](#issue-board-permissions) + * [File Locking permissions](#file-locking-permissions-premium) + * [Confidential Issues permissions](#confidential-issues-permissions) +* [Group members permissions](#group-members-permissions) + * [Subgroup permissions](#subgroup-permissions) +* [External users](#external-users-core-only) + * [Setting new users to external](#setting-new-users-to-external) +* [Free Guest users](#free-guest-users-ultimate) +* [Auditor users](#auditor-users-premium-only) +* [Project features](#project-features) +* [GitLab CI/CD permissions](#gitlab-cicd-permissions) + * [Job permissions](#job-permissions) + * [New CI job permissions model](#new-ci-job-permissions-model) +* [Running pipelines on protected branches](#running-pipelines-on-protected-branches) +* [LDAP users permissions](#ldap-users-permissions) +* [Project aliases](#project-aliases) + +# Permissions[](#permissions "Permalink") + +用户具有不同的能力,具体取决于他们在特定组或项目中具有的访问级别. 如果用户既属于项目组又属于项目本身,则使用最高权限级别. + +在公共和内部项目上,不执行来宾角色. 所有用户将能够: + +* 创造问题. +* 留言. +* 克隆或下载项目代码. + +当成员离开团队的项目时,所有分配的" [问题"](project/issues/index.html)和" [合并请求"](project/merge_requests/index.html)将自动取消分配. + +GitLab [管理员拥有](../administration/index.html)所有权限. + +要添加或导入用户,可以遵循[项目成员文档](project/members/index.html) . + +## Principles behind permissions[](#principles-behind-permissions "Permalink") + +有关[权限的信息,](https://about.gitlab.com/handbook/product/gitlab-the-product/#permissions-in-gitlab)请参见我们的[产品手册](https://about.gitlab.com/handbook/product/gitlab-the-product/#permissions-in-gitlab) . + +## Instance-wide user permissions[](#instance-wide-user-permissions "Permalink") + +默认情况下,用户可以创建顶级组并更改其用户名. GitLab 管理员可以配置 GitLab 实例来[修改此行为](../administration/user_settings.html) . + +## Project members permissions[](#project-members-permissions "Permalink") + +**注意:**在 GitLab 11.0 中,"主"角色已重命名为"维护者". + +虽然维护者是项目级别的最高角色,但是某些操作只能由拥有所有权限的个人名称空间或组所有者或实例管理员执行. 有关更多信息,请参阅[项目成员文档](project/members/index.html) . + +下表描述了项目中的各种用户权限级别. + +| Action | Guest | Reporter | Developer | Maintainer | Owner* | +| --- | --- | --- | --- | --- | --- | +| 下载专案 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 留言 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看允许和拒绝的许可证 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看许可证合规性报告 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看安全报告 | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | +| 查看相关性列表 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看许可证列表 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 在相关性列表中查看许可证 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| View [Design Management](project/issues/design_management.html) pages | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看项目代码 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 拉项目代码 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看受[访问控制](project/pages/introduction.html#gitlab-pages-access-control-core)保护的 GitLab 页面 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看维基页面 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看工作清单 | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | +| 查看工作日志 | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | +| 下载和浏览工作工件 | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | +| 创刊号 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看相关问题 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 创建机密问题 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看机密问题 | (*2*) | ✓ | ✓ | ✓ | ✓ | +| View [Releases](project/releases/index.html) | ✓ (*6*) | ✓ | ✓ | ✓ | ✓ | +| 查看要求 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 管理用户加星标的指标仪表板( *7* ) | ✓ | ✓ | ✓ | ✓ | ✓ | +| 分配问题 |   | ✓ | ✓ | ✓ | ✓ | +| 标签问题 |   | ✓ | ✓ | ✓ | ✓ | +| 设定发行权重 |   | ✓ | ✓ | ✓ | ✓ | +| 锁定问题线程 |   | ✓ | ✓ | ✓ | ✓ | +| 管理问题追踪器 |   | ✓ | ✓ | ✓ | ✓ | +| 管理相关问题 |   | ✓ | ✓ | ✓ | ✓ | +| 管理标签 |   | ✓ | ✓ | ✓ | ✓ | +| 创建代码段 |   | ✓ | ✓ | ✓ | ✓ | +| 查看提交状态 |   | ✓ | ✓ | ✓ | ✓ | +| 查看容器注册表 |   | ✓ | ✓ | ✓ | ✓ | +| 查看环境 |   | ✓ | ✓ | ✓ | ✓ | +| 查看合并请求列表 |   | ✓ | ✓ | ✓ | ✓ | +| 查看项目统计 |   |   | ✓ | ✓ | ✓ | +| 查看错误跟踪列表 |   | ✓ | ✓ | ✓ | ✓ | +| 创建新的合并请求 |   | ✓ | ✓ | ✓ | ✓ | +| 查看指标仪表板注释 |   | ✓ | ✓ | ✓ | ✓ | +| 创建/编辑需求 |   | ✓ | ✓ | ✓ | ✓ | +| Pull [packages](packages/index.html) |   | ✓ | ✓ | ✓ | ✓ | +| Publish [packages](packages/index.html) |   |   | ✓ | ✓ | ✓ | +| Upload [Design Management](project/issues/design_management.html) files |   |   | ✓ | ✓ | ✓ | +| Create/edit/delete [Releases](project/releases/index.html) |   |   | ✓ | ✓ | ✓ | +| 创建新分支 |   |   | ✓ | ✓ | ✓ | +| 推送到不受保护的分支 |   |   | ✓ | ✓ | ✓ | +| 强制推送到不受保护的分支 |   |   | ✓ | ✓ | ✓ | +| 删除不受保护的分支 |   |   | ✓ | ✓ | ✓ | +| 分配合并请求 |   |   | ✓ | ✓ | ✓ | +| 标签合并请求 |   |   | ✓ | ✓ | ✓ | +| 锁定合并请求线程 |   |   | ✓ | ✓ | ✓ | +| 批准合并请求( *9* ) |   |   | ✓ | ✓ | ✓ | +| 管理/接受合并请求 |   |   | ✓ | ✓ | ✓ | +| 创建新环境 |   |   | ✓ | ✓ | ✓ | +| 停止环境 |   |   | ✓ | ✓ | ✓ | +| 启用评论应用 |   |   | ✓ | ✓ | ✓ | +| 添加标签 |   |   | ✓ | ✓ | ✓ | +| 取消并重试作业 |   |   | ✓ | ✓ | ✓ | +| 创建或更新提交状态 |   |   | ✓ (*5*) | ✓ | ✓ | +| 更新容器注册表 |   |   | ✓ | ✓ | ✓ | +| 删除容器注册表映像 |   |   | ✓ | ✓ | ✓ | +| 创建/编辑/删除项目里程碑 |   |   | ✓ | ✓ | ✓ | +| 使用安全仪表板 |   |   | ✓ | ✓ | ✓ | +| 在"依赖关系"列表中查看漏洞发现 |   |   | ✓ | ✓ | ✓ | +| 从漏洞发现中创建问题 |   |   | ✓ | ✓ | ✓ | +| 消除漏洞发现 |   |   | ✓ | ✓ | ✓ | +| 查看漏洞 |   |   | ✓ | ✓ | ✓ | +| 通过漏洞发现创建漏洞 |   |   | ✓ | ✓ | ✓ | +| 解决漏洞 |   |   | ✓ | ✓ | ✓ | +| 消除漏洞 |   |   | ✓ | ✓ | ✓ | +| 应用代码更改建议 |   |   | ✓ | ✓ | ✓ | +| 创建和编辑 Wiki 页面 |   |   | ✓ | ✓ | ✓ | +| 重写/删除 Git 标签 |   |   | ✓ | ✓ | ✓ | +| 管理功能标记 |   |   | ✓ | ✓ | ✓ | +| 创建/编辑/删除指标仪表板注释 |   |   | ✓ | ✓ | ✓ | +| 针对受保护的分支运行 CI / CD 管道 |   |   | ✓ (*5*) | ✓ | ✓ | +| 使用环境终端 |   |   |   | ✓ | ✓ | +| 运行 Web IDE 的交互式 Web 终端 |   |   |   | ✓ | ✓ | +| 添加新的团队成员 |   |   |   | ✓ | ✓ | +| 启用/禁用分支保护 |   |   |   | ✓ | ✓ | +| 推送到受保护的分支 |   |   |   | ✓ | ✓ | +| 为开发人员打开/关闭受保护的分支推送 |   |   |   | ✓ | ✓ | +| 启用/禁用标签保护 |   |   |   | ✓ | ✓ | +| 编辑专案 |   |   |   | ✓ | ✓ | +| 编辑项目徽章 |   |   |   | ✓ | ✓ | +| 与小组共享(邀请)项目 |   |   |   | ✓ (*8*) | ✓ (*8*) | +| 将部署密钥添加到项目 |   |   |   | ✓ | ✓ | +| 配置项目挂钩 |   |   |   | ✓ | ✓ | +| 管理跑步者 |   |   |   | ✓ | ✓ | +| 管理工作触发器 |   |   |   | ✓ | ✓ | +| 管理 CI / CD 变量 |   |   |   | ✓ | ✓ | +| 管理 GitLab 页面 |   |   |   | ✓ | ✓ | +| 管理 GitLab Pages 域和证书 |   |   |   | ✓ | ✓ | +| 删除 GitLab 页面 |   |   |   | ✓ | ✓ | +| 管理集群 |   |   |   | ✓ | ✓ | +| 管理项目运作 |   |   |   | ✓ | ✓ | +| 查看 Pod 日志 |   |   |   | ✓ | ✓ | +| 管理许可政策 |   |   |   | ✓ | ✓ | +| 编辑评论(由任何用户发布) |   |   |   | ✓ | ✓ | +| 管理错误跟踪 |   |   |   | ✓ | ✓ | +| 删除维基页面 |   |   |   | ✓ | ✓ | +| 查看项目审核事件 |   |   |   | ✓ | ✓ | +| Manage [push rules](../push_rules/push_rules.html) |   |   |   | ✓ | ✓ | +| Manage [project access tokens](./project/settings/project_access_tokens.html) |   |   |   | ✓ | ✓ | +| Switch visibility level |   |   |   |   | ✓ | +| 将项目转移到另一个名称空间 |   |   |   |   | ✓ | +| 重命名项目 |   |   |   |   | ✓ | +| 删除分叉关系 |   |   |   |   | ✓ | +| 移除专案 |   |   |   |   | ✓ | +| 存档项目 |   |   |   |   | ✓ | +| 删除问题 |   |   |   |   | ✓ | +| 删除管道 |   |   |   |   | ✓ | +| 删除合并请求 |   |   |   |   | ✓ | +| 禁用通知电子邮件 |   |   |   |   | ✓ | +| 用力推动到受保护的分支( *4* ) |   |   |   |   |   | +| 卸下受保护的分支( *4* ) |   |   |   |   |   | +| 查看 CI \ CD 分析 |   | ✓ | ✓ | ✓ | ✓ | +| 查看代码审查分析 |   | ✓ | ✓ | ✓ | ✓ | +| 查看见解 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看问题分析 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看存储库分析 |   | ✓ | ✓ | ✓ | ✓ | +| 查看价值流分析 | ✓ | ✓ | ✓ | ✓ | ✓ | + +*所有者权限仅在组或个人名称空间级别(例如,管理员)可用,并由其项目继承. + +1. 来宾用户能够对公共和内部项目执行此操作,但不能对私有项目执行此操作. +2. 来宾用户只能查看他们自己创建的机密问题. +3. 如果在**项目设置> CI / CD 中**启用了**公共管道** . +4. 不允许访客,记者,开发人员,维护人员或所有者使用. 请参阅[受保护的分支](./project/protected_branches.html) . +5. 如果[分支受保护](./project/protected_branches.html#using-the-allowed-to-merge-and-allowed-to-push-settings) ,则取决于授予开发人员和维护人员的权限. +6. 来宾用户可以访问 GitLab [**版本**](project/releases/index.html)来下载资产,但不能下载源代码,也不能查看存储库信息(例如标签和提交). +7. 操作仅限于用户拥有(引用)的记录​​. +8. 启用" [共享组锁定"后](./group/index.html#share-with-group-lock) ,该项目将无法与其他组共享. 它不影响具有组共享的组. +9. 有关合并请求的[合格批准人的](project/merge_requests/merge_request_approvals.html#eligible-approvers)信息,请参阅[合格](project/merge_requests/merge_request_approvals.html#eligible-approvers)合并[人](project/merge_requests/merge_request_approvals.html#eligible-approvers) . + +## Project features permissions[](#project-features-permissions "Permalink") + +### Wiki and issues[](#wiki-and-issues "Permalink") + +可以根据用户在项目设置上选择的可见性级别对用户隐藏 Wiki 和问题等项目功能. + +* 禁用:所有人禁用 +* 仅团队成员:即使您的项目是公开的或内部的,也只有团队成员才能看到 +* 有访问权限的所有人:每个人都可以看到,具体取决于您的项目可见性级别 +* 每个人:为所有人启用(仅适用于 GitLab 页面) + +### Protected branches[](#protected-branches "Permalink") + +可以在每个分支的[受保护](project/protected_branches.html)分支上应用其他限制. 此外,您可以自定义权限,以允许或阻止项目维护者和开发者推送到受保护的分支. 阅读有关" [允许合并"和"允许推送"设置](project/protected_branches.html#using-the-allowed-to-merge-and-allowed-to-push-settings)的文档以了解更多信息. + +### Value Stream Analytics permissions[](#value-stream-analytics-permissions "Permalink") + +如[相关文档](analytics/value_stream_analytics.html#permissions)所述,在 Value Stream Analytics 仪表板上找到当前权限. + +### Issue Board permissions[](#issue-board-permissions "Permalink") + +具有较高权限级别的开发人员和用户可以使用发行版的所有功能,即创建/删除列表并拖动发行版. 通读[有关发行板权限](project/issue_board.html#permissions)的[文档](project/issue_board.html#permissions)以了解更多信息. + +### File Locking permissions[](#file-locking-permissions-premium "Permalink") + +锁定文件或目录的用户是唯一可以编辑并将其更改推回锁定对象所在存储库的用户. + +通读[有关文件锁定权限的文档](project/file_lock.html#permissions-on-file-locking)以了解更多信息. + +### Confidential Issues permissions[](#confidential-issues-permissions "Permalink") + +报告者和更高的权限级别以及创建机密问题的来宾用户都可以访问机密问题. 要了解更多信息,请通读有关[权限和访问机密问题](project/issues/confidential_issues.html#permissions-and-access-to-confidential-issues)的文档. + +## Group members permissions[](#group-members-permissions "Permalink") + +**注意:**在 GitLab 11.0 中,"主"角色已重命名为"维护者". + +任何用户都可以将自己从组中删除,除非他们是该组的最后一个所有者. 下表描述了组中的各种用户权限级别. + +| Action | Guest | Reporter | Developer | Maintainer | Owner | +| --- | --- | --- | --- | --- | --- | +| 浏览组 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看见解图表 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看小组史诗 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 创建/编辑小组史诗 |   | ✓ | ✓ | ✓ | ✓ | +| 管理群组标签 |   | ✓ | ✓ | ✓ | ✓ | +| 查看容器注册表 |   | ✓ | ✓ | ✓ | ✓ | +| Pull [packages](packages/index.html) |   | ✓ | ✓ | ✓ | ✓ | +| Publish [packages](packages/index.html) |   |   | ✓ | ✓ | ✓ | +| 查看指标仪表板注释 |   | ✓ | ✓ | ✓ | ✓ | +| 分组创建项目 |   |   | ✓ (3) | ✓ (3) | ✓ (3) | +| 与群组分享(邀请)群组 |   |   |   |   | ✓ | +| 创建/编辑/删除组里程碑 |   |   | ✓ | ✓ | ✓ | +| 创建/编辑/删除迭代 |   |   | ✓ | ✓ | ✓ | +| 启用/禁用依赖项代理 |   |   | ✓ | ✓ | ✓ | +| 使用安全仪表板 |   |   | ✓ | ✓ | ✓ | +| 创建/编辑/删除指标仪表板注释 |   |   | ✓ | ✓ | ✓ | +| 查看/管理组级别的 Kubernetes 集群 |   |   |   | ✓ | ✓ | +| 创建子组 |   |   |   | ✓ (1) | ✓ | +| 编辑史诗般的评论(由任何用户发布) |   |   |   | ✓ (2) | ✓ (2) | +| 编辑群组设定 |   |   |   |   | ✓ | +| 管理组级 CI / CD 变量 |   |   |   |   | ✓ | +| 列出组部署令牌 |   |   |   | ✓ | ✓ | +| 创建/删除组部署令牌 |   |   |   |   | ✓ | +| 管理小组成员 |   |   |   |   | ✓ | +| 删除群组 |   |   |   |   | ✓ | +| 删除组史诗 |   |   |   |   | ✓ | +| 编辑 SAML SSO 帐单 | ✓ | ✓ | ✓ | ✓ | ✓ (4) | +| 查看组审核事件 |   |   |   |   | ✓ | +| 禁用通知电子邮件 |   |   |   |   | ✓ | +| 查看贡献分析 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看见解 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看问题分析 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看生产力分析 |   | ✓ | ✓ | ✓ | ✓ | +| 查看价值流分析 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看帐单 |   |   |   |   | ✓ (4) | +| 查看使用配额 |   |   |   |   | ✓ (4) | + +1. 可以设置组以[允许所有者或所有者和维护者创建子组](group/subgroups/index.html#creating-a-subgroup) +2. 在 GitLab 12.2 中引入. +3. 可以在以下位置更改默认项目创建角色: + * [实例级别](admin_area/settings/visibility_and_access_controls.html#default-project-creation-protection) . + * [小组级别](group/index.html#default-project-creation-level) . +4. 不适用于子组. + +### Subgroup permissions[](#subgroup-permissions "Permalink") + +将成员添加到子组时,它们将从父组继承成员资格和权限级别. 如果您是其父级成员之一,则该模型允许访问嵌套组. + +To learn more, read through the documentation on [subgroups memberships](group/subgroups/index.html#membership). + +## External users[](#external-users-core-only "Permalink") + +如果希望用户只能访问某些内部或私有项目,则可以选择创建**外部用户** . 例如,当承包商在给定项目上工作且仅应访问该项目时,此功能可能很有用. + +外部用户: + +* 无法创建群组,项目或个人摘要. +* 只能访问公共项目和显式授予其访问权限的项目,从而对它们隐藏所有其他内部或私有项目(例如注销). + +可以通过将用户添加为项目或组的成员来授予访问权限. 与普通用户一样,他们将在项目或组中获得角色,具有[上面权限表](#project-members-permissions)中提到的所有功能. 例如,如果将外部用户添加为 Guest,而您的项目是私有项目,则他们将无权访问该代码; 如果您希望外部用户具有访问代码的权限,则需要授予其外部访问权限. 您应始终考虑[项目的可见性和权限设置](project/settings/index.html#sharing-and-permissions)以及用户的权限级别. + +**注意:**外部用户仍然计入许可证席位. + +管理员可以通过以下两种方法之一将用户标记为外部用户: + +* Either [through the API](../api/users.html#user-modification). +* 或通过导航到**管理区域>概述>用户**来创建新用户或编辑现有用户. 在那里,您将找到将用户标记为外部的选项. + +### Setting new users to external[](#setting-new-users-to-external "Permalink") + +默认情况下,新用户未设置为外部用户. 管理员可以在" **帐户和限制"**下的" **管理区域">"设置">"常规"**页面上更改此行为. + +如果更改了将新用户创建为外部用户的默认行为,则可以选择通过定义一组内部用户来缩小范围. **内部用户**字段允许指定电子邮件地址正则表达式模式以标识默认内部用户. 默认情况下,其电子邮件地址与正则表达式模式匹配的新用户将设置为内部用户,而不是外部协作者. + +正则表达式模式格式为 Ruby,但需要将其转换为 JavaScript,并将设置大小写忽略标志( `/regex pattern/i` ). 这里有些例子: + +* 使用`\.internal@domain\.com$`将以`.internal@domain.com`结尾的电子邮件地址标记为内部. +* 使用`^(?:(?!\.ext@domain\.com).)*$\r?` 使用不包含`.ext@domain.com`电子邮件地址标记用户为内部用户. + +**警告:**请注意,此正则表达式可能导致[正则表达式拒绝服务(ReDoS)攻击](https://en.wikipedia.org/wiki/ReDoS) . + +## Free Guest users[](#free-guest-users-ultimate "Permalink") + +如果为用户授予了项目,组或组或两者的来宾权限,并且对 GitLab 实例上的任何其他项目或组均没有更高的权限级别,则该用户被 GitLab 视为来宾用户,并且不会占用许可证席位. 对于新创建的用户,没有其他特定的"来宾"指定. + +如果在任何项目或组上为用户分配了更高的角色,则该用户将获得许可席位. 如果用户创建项目,则该用户将成为该项目的维护者,从而导致使用许可证席位. 另外,请注意,如果您的项目是内部项目或私有项目,则来宾用户将具有[上面](#project-members-permissions)的[权限表](#project-members-permissions)中提到的所有功能(例如,他们将无法浏览项目的存储库). + +**提示:**为防止访客用户创建项目,请以管理员身份编辑用户的个人资料,以将该用户标记为[external](#external-users-core-only) . 请注意,即使用户是外部用户,如果他们在任何项目或组中已经具有 Reporter 或更高权限, **也不**会将其计为免费的来宾用户. + +## Auditor users[](#auditor-users-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/998) in [GitLab Premium](https://about.gitlab.com/pricing/) 8.17. + +审核员用户被授予对 GitLab 实例上所有项目,组和其他资源的只读访问权限. + +审核员用户应能够使用[审核员用户权限](../administration/auditor_users.html#permissions-and-restrictions-of-an-auditor-user)文档中所述的权限访问 GitLab 实例的所有项目和组. + +[Read more about Auditor users.](../administration/auditor_users.html) + +## Project features[](#project-features "Permalink") + +可以根据用户在项目设置上选择的可见性级别对用户隐藏 Wiki 和问题等项目功能. + +* 禁用:所有人禁用 +* 仅团队成员:即使您的项目是公开的或内部的,也只有团队成员才能看到 +* 有访问权限的所有人:每个人都可以看到,具体取决于您的项目可见性级别 +* 每个人:为所有人启用(仅适用于 GitLab 页面) + +## GitLab CI/CD permissions[](#gitlab-cicd-permissions "Permalink") + +**注意:**在 GitLab 11.0 中,"主"角色已重命名为"维护者". + +GitLab CI / CD 权限取决于用户在 GitLab 中的角色. 共有四个权限级别: + +* admin +* maintainer +* developer +* guest/reporter + +管理员用户可以在 GitLab 实例和项目范围内对 GitLab CI / CD 执行任何操作. 此外,所有管理员都可以使用`/admin/runners`下的管理界面. + +| Action | 来宾,记者 | Developer | Maintainer | Admin | +| --- | --- | --- | --- | --- | +| 查看提交和工作 | ✓ | ✓ | ✓ | ✓ | +| 重试或取消作业 |   | ✓ | ✓ | ✓ | +| 擦除工件和跟踪 |   | ✓ (*1*) | ✓ | ✓ | +| 移除专案 |   |   | ✓ | ✓ | +| 建立专案 |   |   | ✓ | ✓ | +| 更改项目配置 |   |   | ✓ | ✓ | +| 添加特定跑步者 |   |   | ✓ | ✓ | +| 添加共享的跑步者 |   |   |   | ✓ | +| 查看系统中的事件 |   |   |   | ✓ | +| 管理界面 |   |   |   | ✓ | + +1. 仅当工作是: + * 由用户触发 + * [从 GitLab 13.0 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/35069) ,不为受保护的分支运行 + +### Job permissions[](#job-permissions "Permalink") + +**注意:**在 GitLab 11.0 中,"主"角色已重命名为"维护者". + +> **注意:** GitLab 8.12 具有完全重新设计的作业权限系统. 阅读有关[新模型及其含义的](project/new_ci_build_permissions_model.html)所有信息. + +下表显示了由特定类型的用户触发的作业的授予特权: + +| Action | 来宾,记者 | Developer | Maintainer | Admin | +| --- | --- | --- | --- | --- | +| 运行 CI 作业 |   | ✓ | ✓ | ✓ | +| 从当前项目克隆源和 LFS |   | ✓ | ✓ | ✓ | +| 从公共项目克隆源和 LFS |   | ✓ | ✓ | ✓ | +| 从内部项目克隆源和 LFS |   | ✓ (*1*) | ✓ (*1*) | ✓ | +| 从私有项目克隆源和 LFS |   | ✓ (*2*) | ✓ (*2*) | ✓ (*2*) | +| 从当前项目中提取容器图像 |   | ✓ | ✓ | ✓ | +| 从公共项目中提取容器图像 |   | ✓ | ✓ | ✓ | +| 从内部项目中提取容器图像 |   | ✓ (*1*) | ✓ (*1*) | ✓ | +| 从私有项目中提取容器图像 |   | ✓ (*2*) | ✓ (*2*) | ✓ (*2*) | +| 将容器图像推送到当前项目 |   | ✓ | ✓ | ✓ | +| 将容器图像推送到其他项目 |   |   |   |   | +| 推送源和 LFS |   |   |   |   | + +1. 仅当用户不是外部用户时 +2. 仅当用户是项目成员时 + +### New CI job permissions model[](#new-ci-job-permissions-model "Permalink") + +GitLab 8.12 具有完全重新设计的工作权限系统. 要了解更多信息,请通读有关[新 CI / CD 权限模型](project/new_ci_build_permissions_model.html#new-ci-job-permissions-model)的文档. + +## Running pipelines on protected branches[](#running-pipelines-on-protected-branches "Permalink") + +合并或推送到受保护分支的权限用于定义用户是否可以运行 CI / CD 管道并在与那些分支相关的作业上执行操作. + +有关管道安全模型的详细信息,请参阅[受保护分支上](../ci/pipelines/index.html#pipeline-security-on-protected-branches)的安全性. + +## LDAP users permissions[](#ldap-users-permissions "Permalink") + +从 GitLab 8.15 开始,LDAP 用户权限现在可以由管理员用户手动覆盖. 通读有关[LDAP 用户权限](group/index.html#manage-group-memberships-via-ldap)的文档以了解更多信息. + +## Project aliases[](#project-aliases "Permalink") + +项目别名只能由 GitLab 管理员读取,创建和删除. 通读有关[项目别名](../user/project/index.html#project-aliases-premium-only)的文档以了解更多信息. \ No newline at end of file diff --git a/_book/docs/396.md b/_book/docs/396.md new file mode 100644 index 0000000000000000000000000000000000000000..1c22f5247f2515a893dbe819f6e3486c85089967 --- /dev/null +++ b/_book/docs/396.md @@ -0,0 +1,106 @@ +# Personal access tokens + +> 原文:[https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) + +* [Creating a personal access token](#creating-a-personal-access-token) + * [Revoking a personal access token](#revoking-a-personal-access-token) + * [Token activity](#token-activity) +* [Limiting scopes of a personal access token](#limiting-scopes-of-a-personal-access-token) +* [Programmatically creating a personal access token](#programmatically-creating-a-personal-access-token) +* [Programmatically revoking a personal access token](#programmatically-revoking-a-personal-access-token) + +# Personal access tokens[](#personal-access-tokens "Permalink") + +版本历史 + +* 在 GitLab 8.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3749) . +* 在 GitLab 12.6 中添加了[有关令牌过期的通知](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) . +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6 中添加了[令牌生存期限制](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) . + +If you’re unable to use [OAuth2](../../api/oauth2.html), you can use a personal access token to authenticate with the [GitLab API](../../api/README.html#personalproject-access-tokens). + +您还可以将个人访问令牌与 Git 一起使用,以通过 HTTP 或 SSH 进行身份验证. 启用[两因素身份验证(2FA)](../account/two_factor_authentication.html)时,需要个人访问令牌. 在这两种情况下,都可以使用令牌代替密码进行身份验证. + +个人访问令牌在您定义的日期 UTC 午夜到期. + +* GitLab 每天在世界标准时间 01:00 AM 进行检查,以识别将在 7 天内到期的个人访问令牌. 这些令牌的所有者通过电子邮件通知. +* 在 GitLab Ultimate 中,管理员可以[限制个人访问令牌的寿命](../admin_area/settings/account_and_limit_settings.html#limiting-lifetime-of-personal-access-tokens-ultimate-only) . +* 在 GitLab Ultimate 中,管理员可以[切换个人访问令牌到期的执行](../admin_area/settings/account_and_limit_settings.html#optional-enforcement-of-personal-access-token-expiry-ultimate-only) . + +有关如何使用个人访问令牌向 API 进行身份验证的示例,请参见[API 文档中](../../api/README.html#personalproject-access-tokens)的以下部分. + +GitLab 还提供了[模拟令牌](../../api/README.html#impersonation-tokens) ,这些[令牌](../../api/README.html#impersonation-tokens)是管理员通过 API 创建的. 它们非常适合作为特定用户的自动身份验证. + +## Creating a personal access token[](#creating-a-personal-access-token "Permalink") + +您可以在 GitLab 个人资料中创建任意数量的个人访问令牌. + +1. 登录到 GitLab. +2. 点击右上角的头像,然后选择**设置** . +3. 在" **用户设置"**菜单上,选择" **访问令牌"** . +4. 选择令牌的名称和可选的到期日期. +5. 选择[所需的范围](#limiting-scopes-of-a-personal-access-token) . +6. 单击**创建个人访问令牌**按钮. +7. 将个人访问令牌保存在安全的地方. 离开或刷新页面后,将无法再次访问它. + +### Revoking a personal access token[](#revoking-a-personal-access-token "Permalink") + +您可以随时单击" **活动个人访问令牌"**区域下的相应" **撤消"**按钮来撤消任何个人访问令牌. + +### Token activity[](#token-activity "Permalink") + +您可以从" **个人访问令牌"**页面**查看**上次使用**令牌的时间** . 令牌使用情况的更新每 24 小时固定一次. 对[API 资源](../../api/api_resources.html)和[GraphQL API 的](../../api/graphql/index.html)请求将更新令牌的用法. + +## Limiting scopes of a personal access token[](#limiting-scopes-of-a-personal-access-token "Permalink") + +可以使用一个或多个范围创建个人访问令牌,这些范围允许给定令牌可以执行各种操作. 下表描述了可用范围. + +| Scope | 引入 | Description | +| --- | --- | --- | +| `read_user` | [GitLab 8.15](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5951) | 允许访问`/users`下的只读端点. 本质上,允许[用户 API](../../api/users.html)中的任何`GET`请求. | +| `api` | [GitLab 8.15](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5951) | 授予对 API 的完全读写访问权限,包括所有组和项目,容器注册表和程序包注册表. | +| `read_api` | [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28944) | 授予对 API 的读取权限,包括所有组和项目,容器注册表和程序包注册表. | +| `read_registry` | [GitLab 9.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11845) | 如果项目是私有的并且需要授权,则允许读取(拉出) [容器注册表](../packages/container_registry/index.html)图像. | +| `sudo` | [GitLab 10.2](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14838) | 允许以系统中的任何用户身份执行 API 操作(如果经过身份验证的用户是管理员). | +| `read_repository` | [GitLab 10.7](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17894) | 允许通过`git clone`对存储库进行只读访问(拉). | +| `write_repository` | [GitLab 11.11](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26021) | 允许通过`git clone`对存储库进行读写访问(拉,推). 启用 2FA 时,通过 HTTP 访问 Git 存储库是必需的. | + +## Programmatically creating a personal access token[](#programmatically-creating-a-personal-access-token "Permalink") + +您可以以编程方式创建预定的个人访问令牌,以用于自动化或测试. 您将需要足够的访问权限才能为 GitLab 实例运行[Rails 控制台会话](../../administration/troubleshooting/debug.html#starting-a-rails-console-session) . + +要使用用户名`automation-bot`创建属于用户的令牌,请在 Rails 控制台( `sudo gitlab-rails console` )中运行以下`sudo gitlab-rails console` : + +``` +user = User.find_by_username('automation-bot') +token = user.personal_access_tokens.create(scopes: [:read_user, :read_repository], name: 'Automation token') +token.set_token('token-string-here123') +token.save! +``` + +使用[GitLab Rails Runner](../../administration/troubleshooting/debug.html#using-the-rails-runner)可以将其简化为单行 shell 命令: + +``` +sudo gitlab-rails runner "token = User.find_by_username('automation-bot').personal_access_tokens.create(scopes: [:read_user, :read_repository], name: 'Automation token'); token.set_token('token-string-here123'); token.save!" +``` + +**注意:**令牌字符串的长度必须为 20 个字符,否则将不会被识别为个人访问令牌. + +有效范围的列表及其作用可以[在源代码中](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/auth.rb)找到. + +## Programmatically revoking a personal access token[](#programmatically-revoking-a-personal-access-token "Permalink") + +您可以通过编程方式撤消个人访问令牌. 您将需要足够的访问权限才能为 GitLab 实例运行[Rails 控制台会话](../../administration/troubleshooting/debug.html#starting-a-rails-console-session) . + +要撤销已知令牌`token-string-here123` ,请在 Rails 控制台( `sudo gitlab-rails console` )中运行以下`sudo gitlab-rails console` : + +``` +token = PersonalAccessToken.find_by_token('token-string-here123') +token.revoke! +``` + +可以使用[GitLab Rails Runner](../../administration/troubleshooting/debug.html#using-the-rails-runner)将其[简化](../../administration/troubleshooting/debug.html#using-the-rails-runner)为单行 shell 命令: + +``` +sudo gitlab-rails runner "PersonalAccessToken.find_by_token('token-string-here123').revoke!" +``` \ No newline at end of file diff --git a/_book/docs/397.md b/_book/docs/397.md new file mode 100644 index 0000000000000000000000000000000000000000..231666c92dc07a9647f7b0292db980dd5ddf6c66 --- /dev/null +++ b/_book/docs/397.md @@ -0,0 +1,163 @@ +# Profile preferences + +> 原文:[https://docs.gitlab.com/ee/user/profile/preferences.html](https://docs.gitlab.com/ee/user/profile/preferences.html) + +* [Navigation theme](#navigation-theme) +* [Dark mode](#dark-mode) +* [Syntax highlighting theme](#syntax-highlighting-theme) +* [Behavior](#behavior) + * [Layout width](#layout-width) + * [Default dashboard](#default-dashboard) + * [Group overview content](#group-overview-content) + * [Project overview content](#project-overview-content) + * [Tab width](#tab-width) +* [Localization](#localization) + * [Language](#language) + * [First day of the week](#first-day-of-the-week) +* [Integrations](#integrations) + * [Sourcegraph](#sourcegraph) + +# Profile preferences[](#profile-preferences "Permalink") + +用户的个人资料首选项页面允许用户自定义 GitLab 的各个方面. + +要导航至个人资料的首选项,请执行以下操作: + +1. 单击您的头像. +2. Select **Settings**. +3. 单击边栏中的**首选项** . + +## Navigation theme[](#navigation-theme "Permalink") + +GitLab 导航主题设置可让您个性化 GitLab 体验. 您可以从多个颜色主题中进行选择,这些主题可以为顶部导航和左侧导航添加独特的颜色. 使用单独的颜色主题可以帮助您区分不同的 GitLab 实例. + +默认主题为 Indigo. 您可以选择 10 个主题: + +* Indigo +* 浅靛蓝 +* Blue +* 浅蓝 +* Green +* 浅绿色 +* Red +* 红灯 +* Dark +* Light + +[![Profile preferences navigation themes](img/c6c38f70c273cc4412f6d3bd29af3829.png)](img/profil-preferences-navigation-theme.png) + +## Dark mode[](#dark-mode "Permalink") + +[介绍](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28252)在 GitLab 13.1 作为一个 alpha 版本. + +manbetx 客户端打不开已经开始在黑暗模式下工作! 深色[版本](https://about.gitlab.com/handbook/product/#alpha)的[Alpha 版本](https://about.gitlab.com/handbook/product/#alpha)本着迭代的精神和[Alpha 版本](https://about.gitlab.com/handbook/product/#alpha)的较低期望提供. + +[黑暗主题史诗中](https://gitlab.com/groups/gitlab-org/-/epics/2902)追踪了黑暗模式的进展. 见史诗: + +* 已知问题列表. +* 我们计划的方向和下一步. + +如果发现未列出的问题,请在史诗上发表评论或创建新的问题. + +出于 MVC 和兼容性原因,暗模式可用作导航主题. 将来,我们计划使其在自己的部分中可配置,同时支持[不同的导航主题](https://gitlab.com/gitlab-org/gitlab/-/issues/219512) . + +**注意:**深色主题当前仅适用于"深色"语法突出显示. + +## Syntax highlighting theme[](#syntax-highlighting-theme "Permalink") + +**注意:** GitLab 使用[rouge Ruby 库](http://rouge.jneen.net/ "胭脂网站")在任何 Editor 上下文之外突出显示语法. WebIDE(如代码片段)使用[Monaco Editor](https://microsoft.github.io/monaco-editor/) ,并提供了[Monarch](https://microsoft.github.io/monaco-editor/monarch.html)库以突出显示语法. 有关支持的语言的列表,请访问相应库的文档. + +更改此设置可让您在 GitLab 上查看语法突出显示的代码时自定义颜色主题. + +默认语法主题为"白色",您可以在 5 个不同的主题中进行选择: + +* White +* Dark +* 日光灯 +* 日光暗 +* Monokai + +[![Profile preferences syntax highlighting themes](img/bde796b0c195045db9849eef2842bd0e.png)](img/profile-preferences-syntax-themes.png) + +您在 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2389)的主题也适用于[Web IDE](../project/web_ide/index.html)的代码编辑器和[Snippets](../snippets.html) . 主题仅在 Web IDE 文件编辑器中可用, [深色主题](https://gitlab.com/gitlab-org/gitlab/-/issues/209808)和[日光化深色主题](https://gitlab.com/gitlab-org/gitlab/-/issues/219228)除外,它们适用于整个 Web IDE 屏幕. + +## Behavior[](#behavior "Permalink") + +以下设置可让您自定义 GitLab 布局的行为以及仪表板和项目登录页面的默认视图. + +### Layout width[](#layout-width "Permalink") + +可以根据喜好将 GitLab 设置为使用不同的宽度. 在固定(最大`1280px` )和流畅( `100%` )应用程序布局之间选择. + +**注意:**虽然使用固定版式时`1280px`是标准最大宽度,但是某些页面仍根据内容使用 100%宽度. + +### Default dashboard[](#default-dashboard "Permalink") + +对于有权访问大量项目但仅能跟上少数项目的用户,默认"仪表板"页面上的活动量可能会很大. 更改此设置可让您重新定义默认的仪表板. + +您可以在此处使用 8 个选项作为默认仪表板视图: + +* 您的项目(默认) +* 已加星标的项目 +* 您的项目活动 +* 已加星标项目的活动 +* 您的团体 +* Your [Todos](../todos.html) +* 分配的问题 +* 分配的合并请求 +* 操作仪表板 + +### Group overview content[](#group-overview-content "Permalink") + +网上**论坛概述内容**下拉菜单允许您选择网上论坛首页上显示的信息. + +您可以选择 2 个选项: + +* 详细信息(默认) +* [Security dashboard](../application_security/security_dashboard/index.html) + +### Project overview content[](#project-overview-content "Permalink") + +项目概述内容设置允许您选择想要在项目主页上看到的内容. + +您可以选择 3 个选项: + +* 文件和自述文件(默认) +* Readme +* Activity + +### Tab width[](#tab-width "Permalink") + +您可以在 GitLab 的各个部分设置标签字符的显示宽度,例如 blob,diff 和片段. + +**注意:** GitLab 的某些部分不遵守此设置,包括 WebIDE,文件编辑器和 Markdown 编辑器. + +## Localization[](#localization "Permalink") + +### Language[](#language "Permalink") + +从支持的语言列表中选择首选语言. + +*此功能是实验性的,翻译尚未完成.* + +### First day of the week[](#first-day-of-the-week "Permalink") + +可以针对日历视图和日期选择器自定义一周的第一天. + +您可以选择以下选项之一作为一周的第一天: + +* Saturday +* Sunday +* Monday + +如果选择**System Default** ,则将使用系统范围的默认设置. + +## Integrations[](#integrations "Permalink") + +使用第三方服务配置您的首选项,这些服务可增强您的 GitLab 体验. + +### Sourcegraph[](#sourcegraph "Permalink") + +**注意:**仅当 GitLab 管理员已启用 Sourcegraph 时,此设置才可见. + +管理由 Sourcegraph 支持的集成代码智能功能的可用性. 查看[Sourcegraph 功能文档](../../integration/sourcegraph.html#enable-sourcegraph-in-user-preferences)以获取更多信息. \ No newline at end of file diff --git a/_book/docs/398.md b/_book/docs/398.md new file mode 100644 index 0000000000000000000000000000000000000000..0fec52eeae6545c505d517087656d1cf33aebb4e --- /dev/null +++ b/_book/docs/398.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html) \ No newline at end of file diff --git a/_book/docs/399.md b/_book/docs/399.md new file mode 100644 index 0000000000000000000000000000000000000000..e88667ae9a5c57927e4db687a44733868110ccdf --- /dev/null +++ b/_book/docs/399.md @@ -0,0 +1,475 @@ +# Threads + +> 原文:[https://docs.gitlab.com/ee/user/discussions/](https://docs.gitlab.com/ee/user/discussions/) + +* [Resolvable comments and threads](#resolvable-comments-and-threads) + * [Commit threads in the context of a merge request](#commit-threads-in-the-context-of-a-merge-request) + * [Jumping between unresolved threads](#jumping-between-unresolved-threads) + * [Marking a comment or thread as resolved](#marking-a-comment-or-thread-as-resolved) + * [Move all unresolved threads in a merge request to an issue](#move-all-unresolved-threads-in-a-merge-request-to-an-issue) + * [Moving a single thread to a new issue](#moving-a-single-thread-to-a-new-issue) + * [Only allow merge requests to be merged if all threads are resolved](#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved) + * [Automatically resolve merge request diff threads when they become outdated](#automatically-resolve-merge-request-diff-threads-when-they-become-outdated) +* [Commit threads](#commit-threads) +* [Threaded discussions](#threaded-discussions) +* [Image threads](#image-threads) +* [Lock discussions](#lock-discussions) +* [Merge Request Reviews](#merge-request-reviews) + * [Starting a review](#starting-a-review) + * [Resolving/Unresolving threads](#resolvingunresolving-threads) + * [Submitting a review](#submitting-a-review) +* [Filtering notes](#filtering-notes) +* [Suggest Changes](#suggest-changes) + * [Multi-line Suggestions](#multi-line-suggestions) + * [Code block nested in Suggestions](#code-block-nested-in-suggestions) + * [Configure the commit message for applied Suggestions](#configure-the-commit-message-for-applied-suggestions) + * [Batch Suggestions](#batch-suggestions) + * [Enable or disable Batch Suggestions](#enable-or-disable-batch-suggestions) +* [Start a thread by replying to a standard comment](#start-a-thread-by-replying-to-a-standard-comment) +* [Assign an issue to the commenting user](#assign-an-issue-to-the-commenting-user) + +# Threads[](#threads "Permalink") + +整个 GitLab 都提供了进行对话的能力. + +您可以在以下位置发表评论: + +* Issues +* Epics +* 合并要求 +* Snippets +* Commits +* 提交差异 + +有标准注释,您还可以选择以线程形式创建注释. 收到回复后,评论也可以[变成主题](#start-a-thread-by-replying-to-a-standard-comment) . + +评论区域支持[Markdown](../markdown.html)和[快速操作](../project/quick_actions.html) . 您可以随时编辑自己的评论,拥有" [维护者"访问级别](../permissions.html)或更高[权限的](../permissions.html)任何人也可以编辑其他人的评论. + +如果为您的 GitLab 实例配置了" [通过电子邮件回复",](../../administration/reply_by_email.html)您还可以回复评论通知电子邮件以回复评论. 回复标准评论会创建另一个标准评论. 回复主题注释会在主题中创建回复. 电子邮件回复支持[Markdown](../markdown.html)和[快速操作](../project/quick_actions.html) ,就像您从网络上回复一样. + +**注意:**每个对象最多只能有 5,000 条注释,例如:issue,epic 和 merge request. + +## Resolvable comments and threads[](#resolvable-comments-and-threads "Permalink") + +版本历史 + +* 在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5022) . +* 可解决的线程只能添加到合并请求差异中. + +线程解析有助于跟踪计划或代码审查期间的进度. + +合并请求,提交,提交差异和摘要中的每个标准注释或线程最初都显示为未解决. 然后,至少具有开发人员访问项目权限的任何人或所检查的更改的作者都可以单独解决这些问题. 如果该线程已解决,并且非成员取消了他们自己的响应,则这也将取消解决讨论线程. 如果非成员然后解决了相同的答复,则将解决讨论线程. + +解决所有标准注释或线程的需求可以防止您忘记处理反馈,并可以隐藏不再相关的线程. + +[!["A thread between two people on a piece of code"](img/18f2b22b7daf0beab9074c6695c99960.png)](img/thread_view.png) + +### Commit threads in the context of a merge request[](#commit-threads-in-the-context-of-a-merge-request "Permalink") + +在 GitLab 10.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/31847) . + +对于具有基于提交的工作流的审阅者,在合并请求的上下文中将线程添加到特定的提交差异可能很有用. 在以下情况下,这些线程将通过更改提交 ID 保持不变: + +* 重新设置后强制推动 +* 修改提交 + +创建提交差异线程: + +1. 导航到合并请求的" **提交"**选项卡. 将显示构成合并请求的提交列表. + + [![Merge request commits tab](img/b061980557a1e04fe2a2f3836b8dd9c1.png)](img/merge_request_commits_tab.png) + +2. 导航到特定的提交,单击" **更改"**选项卡(在该选项卡中,将仅显示与所选提交不同的内容),并留下评论. + + [![Commit diff discussion in merge request context](img/fc09af9303f629aff49a9a4dc5327e65.png)](img/commit_comment_mr_context.png) + +3. 以这种方式创建的任何线程都将显示在合并请求的" **讨论"**选项卡中,并且可以解决. + + [![Merge request Discussions tab](img/033c41dc1122d52872dcb67228037524.png)](img/commit_comment_mr_discussions_tab.png) + +以这种方式创建的线程将仅出现在原始合并请求中,而不是导航到项目的" **存储库">"提交"**页面下的**提交时** . + +**提示:**在合并请求内的线程中找到提交引用的链接时,它将在当前合并请求的上下文中自动转换为链接. + +### Jumping between unresolved threads[](#jumping-between-unresolved-threads "Permalink") + +当合并请求中包含大量注释时,可能很难跟踪仍未解决的问题. 您可以使用线程上"回复"字段旁边的"跳转"按钮在未解决的线程之间跳转. + +您也可以从已解决的线程跟踪器旁边的按钮跳转到下一个未解决的线程. + +您还可以使用键盘快捷键在线程之间导航: + +* 使用`n`跳到下一个未解决的线程. +* 使用`p`跳到上一个未解决的线程. + +[!["8/9 threads resolved"](img/27b77c1cf5861234d7e06b742e7cbf58.png)](img/threads_resolved.png) + +### Marking a comment or thread as resolved[](#marking-a-comment-or-thread-as-resolved "Permalink") + +您可以通过单击**线程**底部的" **解决线程"**按钮将其标记为已解决. + +[!["Resolve thread" button](img/f94efd219528f7641e29dbca3bc215ad.png)](img/resolve_thread_button.png) + +或者,您可以将每个评论标记为单独解决. + +[!["Resolve comment" button](img/9246e597493024c10e4f678f7de7318e.png)](img/resolve_comment_button.png) + +### Move all unresolved threads in a merge request to an issue[](#move-all-unresolved-threads-in-a-merge-request-to-an-issue "Permalink") + +在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8266) + +要在新问题中继续执行来自合并请求的所有打开的线程,请单击" **解决新问题中的所有线程"**按钮. + +[![Open new issue for all unresolved threads](img/c7b2f6ed12531da21a4512becdf843af.png)](img/btn_new_issue_for_all_threads.png) + +或者,当您的项目仅[在解决所有线程](#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved)后才接受合并请求[时](#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved) ,将存在**一个问题,即以后**在合并请求小部件中**解决它们的**链接. + +[![Link in merge request widget](img/4e480a29eb679b62ed97f748fc9acdd7.png)](img/resolve_thread_open_issue.png) + +这将准备一个问题,其内容涉及合并请求和未解决的线程. + +[![Issue mentioning threads in a merge request](img/cbf589a2c41bb518f8f2da56b76a59dc.png)](img/preview_issue_for_threads.png) + +击中" **提交"问题**将导致所有线程被标记为已解决,并添加注释以引用新创建的问题. + +[![Mark threads as resolved notice](img/b36e59e0da065f17e34891efef2ee0a1.png)](img/resolve_thread_issue_notice.png) + +现在,您可以继续从 UI 合并合并请求. + +### Moving a single thread to a new issue[](#moving-a-single-thread-to-a-new-issue "Permalink") + +在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8266) + +要为单个线程创建新问题,可以使用" **在新问题中解决此线程"**按钮. + +[![Create issue for thread](img/c3948ae724d699cf1ec0da64ab3e6a14.png)](img/new_issue_for_thread.png) + +这会将您定向到预填充了线程内容的新问题,类似于为一次委派多个线程而创建的问题. 保存问题将把该线程标记为已解决,并在合并请求线程中添加引用新问题的注释. + +[![New issue for a single thread](img/e5d9c1be329fa86c36614dea613f69a3.png)](img/preview_issue_for_thread.png) + +### Only allow merge requests to be merged if all threads are resolved[](#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved "Permalink") + +在 GitLab 8.14 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7125) . + +在解决所有线程之前,可以阻止合并请求. + +导航到项目的设置页面,选中" **仅在解决所有线程后才允许合并请求"**复选框,然后单击" **保存"**以使更改生效. + +[![Only allow merge if all the threads are resolved settings](img/9bc04e4a71e5ed3917efabdca45725c7.png)](img/only_allow_merge_if_all_threads_are_resolved.png) + +从现在开始,直到所有线程解决后,您才能从 UI 进行合并. + +[![Only allow merge if all the threads are resolved message](img/4e480a29eb679b62ed97f748fc9acdd7.png)](img/resolve_thread_open_issue.png) + +### Automatically resolve merge request diff threads when they become outdated[](#automatically-resolve-merge-request-diff-threads-when-they-become-outdated "Permalink") + +在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14053) . + +您可以在使用新的推送修改的行上自动解决合并请求差异线程. + +导航到您的项目的设置页面,选中" **使用推送更改的行上**的**自动解析合并请求差异线程"**复选框,然后单击" **保存"**以使更改生效. + +[![Automatically resolve merge request diff threads when they become outdated](img/a283d966822ac6a760d1a650273fbb3b.png)](img/automatically_resolve_outdated_discussions.png) + +从现在开始,如果推送使 diff 部分过时,默认情况下将解决 diff 上的所有线程. 不变的线上线程和顶级可解析线程不会自动解析. + +## Commit threads[](#commit-threads "Permalink") + +您可以在项目的**Repository> Commits**下向特定提交添加注释和线程. + +**注意:**如果在强制推送后更改了提交 ID,则以这种方式创建的线程将丢失. + +## Threaded discussions[](#threaded-discussions "Permalink") + +在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7527) . + +尽管可解析线程仅可用于合并请求差异,但也可以添加没有差异的线程. 您可以针对问题,提交,摘要和合并请求启动一个看起来像线程的特定线程. + +要开始主题讨论,请单击" **评论"**按钮切换下拉列表,选择" **开始主题",**并在准备发布评论时单击" **开始主题** ". + +[![Comment type toggle](img/66e7cbbe98ed69a6154c1adcd7ec4f6e.png)](img/comment_type_toggle.gif) + +这将以单个线程发布评论,使您可以更详细地讨论特定评论. + +[![Thread comment](img/d3cc00bf5599be56b0b3154ca2751cbc.png)](img/discussion_comment.png) + +## Image threads[](#image-threads "Permalink") + +在 GitLab 10.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14061) . + +有时线程围绕图像旋转. 使用图像线程,您可以轻松地定位图像的特定坐标并在其周围启动线程. 图像线程在合并请求和提交详细信息视图中可用. + +要启动图像线程,请将鼠标悬停在图像上. 您的鼠标指针应转换为图标,表示该图像可用于注释. 只需单击图像上的任意位置以创建新线程. + +[![Start image thread](img/72a8c3cb5bafa1e02d93f68a624b6094.png)](img/start_image_discussion.gif) + +单击图像后,将显示注释表单,该注释表单将成为您线程的开始. 保存评论后,您会在图像顶部看到一个新的徽章. 此徽章代表您的话题. + +> **注意:**该线程标志通常与一个数字关联,该数字仅用作每个线程的可视参考. 在合并请求线程选项卡中,此标记将带有注释图标,因为每个线程都会呈现一个新的图像部分. + +图像线程还可以在替换现有图像的差异上工作. 在此差异查看模式下,您可以切换不同的查看模式,但仍可以看到线点标记. + +| 2-up | Swipe | 洋葱皮 | +| --- | --- | --- | +| [![2-up view](img/be7e963d6561756bb87f6fea0cd245fa.png)](img/two_up_view.png) | [![swipe view](img/14110c067c5c98646bcad82dbd3be10b.png)](img/swipe_view.png) | [![onion skin view](img/5113c12752dd029f29a28c6f0660cde1.png)](img/onion_skin_view.png) | + +映像线程也可与可解析线程一起很好地工作. 差异上的已解析线程(不在"合并请求讨论"选项卡上)在页面加载时将显示为折叠状态,并且将具有对应的标记计数器以匹配图像上的计数器. + +[![Image resolved thread](img/fc692dde7a0c9ce30f0036b1a05b2768.png)](img/image_resolved_discussion.png) + +## Lock discussions[](#lock-discussions "Permalink") + +在 GitLab 10.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14531) . + +For large projects with many contributors, it may be useful to stop threads in issues or merge requests in these scenarios: + +* 项目维护者已经解决了该线程,对于继续反馈没有帮助. +* 项目维护者已经将新对话指向新问题或合并请求. +* 参与线程的人正在拖钓,辱骂或没有生产力. + +在这些情况下,项目中具有开发者权限或更高权限的用户可以使用边栏中的"锁定"部分来锁定(和解锁)问题或合并请求. 对于问题,具有记者权限的用户可以锁定(和解锁). + +| Unlock | Lock | +| --- | --- | +| [![Turn off discussion lock](img/e7d7b1c5ccf121da6fcfbbc1eb78bbcd.png)](img/turn_off_lock.png) | [![Turn on discussion lock](img/3ed7ccf7499687536cf254fc6f47d5e7.png)](img/turn_on_lock.png) | + +系统注释指示锁定和解锁. + +[![Discussion lock system notes](img/2629e4ef9252e4970d626ca424e88dd2.png)](img/discussion_lock_system_notes.png) + +在锁定的问题或合并请求中,只有团队成员才能添加新评论和编辑现有评论. 禁止非团队成员添加或编辑评论. + +| 队员 | 非团队成员 | +| --- | --- | +| [![Comment form member](img/5c0acf7979c7bc1e89dc413017b70870.png)](img/lock_form_member.png) | [![Comment form non-member](img/94675a32947787d4e216a44e3047d0b5.png)](img/lock_form_non_member.png) | + +此外,无法重新打开锁定的问题和合并请求. + +## Merge Request Reviews[](#merge-request-reviews "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4213) . +* 在 13.1 版中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/28154) GitLab Core. + +查看"合并请求"差异时,您可以开始审阅. 这样,您便可以在"合并请求"中创建**仅**在发布之前才对**您可见的**注释,以便您可以将所有注释作为单个操作提交. + +### Starting a review[](#starting-a-review "Permalink") + +为了开始审阅,只需像往常一样在 MR 的" **更改"**选项卡下对差异添加注释,然后单击" **开始审阅"**按钮. + +[![Starting a review](img/40dbd9d2f1f965f42a1c417a258da575.png)](img/mr_review_start.png) + +Once a review is started, you will see any comments that are part of this review marked `Pending`. All comments that are part of a review show two buttons: + +* **完成审阅** :提交**审阅中的**所有评论,使其他用户可以看到它们. +* **立即添加评论** :提交特定评论作为常规评论,而不是审阅的一部分. + +[![A comment that is part of a review](img/9fa9d16dd2302ab20167b7ff1ca62575.png)](img/pending_review_comment.png) + +您可以在评论中使用[快速操作](../project/quick_actions.html) . 注释将显示发布后将执行的操作. + +[![A review comment with quick actions](img/2927b047cacec2945671ab2484aafe9d.png)](img/review_comment_quickactions.png) + +要向评论添加更多评论,请照常开始写评论,然后单击**添加到评论**按钮. + +[![Adding a second comment to a review](img/996ea860188e6458fe761cf86b2b72b1.png)](img/mr_review_second_comment.png) + +这会将评论添加到评论中. + +[![Second review comment](img/a102a1abbf4c760dba4b8b3daef8fe26.png)](img/mr_review_second_comment_added.png) + +### Resolving/Unresolving threads[](#resolvingunresolving-threads "Permalink") + +评论注释也可以解决/无法解决[可解决的线程](#resolvable-comments-and-threads) . 回复评论时,您将看到一个复选框,您可以单击该复选框以在发布后解决或取消解决线程. + +[![Resolve checkbox](img/865329b4b113d6de44cf382bd77178fa.png)](img/mr_review_resolve.png) + +如果特定的待处理注释将解决或取消解决该线程,它将显示在待处理注释本身上. + +[![Resolve status](img/83da8fe833233875ee4fe28fa21eb1dd.png)](img/mr_review_resolve2.png) + +[![Unresolve status](img/ce6315abe3d0bf8a315febe4ab497312.png)](img/mr_review_unresolve.png) + +### Submitting a review[](#submitting-a-review "Permalink") + +If you have any comments that have not been submitted, you will see a bar at the bottom of the screen with two buttons: + +* **舍弃** : **舍弃**所有尚未提交的评论. +* **完成审阅** :打开准备提交审阅的评论列表. 单击**提交评论**将发布所有评论. 此时将执行所有提交的快速操作. + +另外,要通过待审核的评论完成整个审核,请执行以下操作: + +* 单击**评论**上的" **完成审阅"**按钮. +* 在非评论注释的文本中使用`/submit_review` [快速操作](../project/quick_actions.html) . + +[![Review submission](img/c6daa1e81d653cfd0b476144f1f71874.png)](img/review_preview.png) + +提交审阅将向合并请求的每个应通知用户发送一封电子邮件,其中包含与之相关的所有注释. + +因此,回复此电子邮件将在关联的合并请求上创建一个新注释. + +## Filtering notes[](#filtering-notes "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26723) . + +对于活动注释和用户注释等具有许多注释的问题,有时很难找到有用的信息. 有一种方法可以针对合并请求和问题从单个注释和线程中过滤注释. + +从合并请求的" **讨论"**选项卡,或史诗/问题概述中,找到页面右侧的过滤器下拉菜单,您可以从中选择以下选项之一: + +* **显示所有活动** :显示所有用户评论和系统注释(问题更新,对其他问题的提及,对描述的更改等). +* **仅显示评论** :仅在列表中显示用户评论. +* **仅显示历史记录** :仅显示活动记录. + +[![Notes filters dropdown options](img/5a26f77375b52645c2387aec1f77a777.png)](img/index_notes_filters.png) + +在给定问题或 MR 中选择过滤器之一后,GitLab 将保存您的首选项,这样当您从已登录的任何设备再次访问同一页面时,该首选项将保持不变. + +## Suggest Changes[](#suggest-changes "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/18008) . + +作为审阅者,您可以在 Merge Request Diff 线程中使用简单的 Markdown 语法建议代码更改. 然后,合并请求作者(或具有适当[权限的](../permissions.html)其他用户)能够通过单击来应用这些建议,这将在应用了这些建议的用户创作的合并请求中生成提交. + +1. 选择要更改的代码行,添加新注释,然后单击工具栏中的" **插入建议"**图标: + + [![Add a new comment](img/d7cb226977bb46d9aaa1c1d7e195025a.png)](img/suggestion_button_v12_7.png) + +2. 在注释中,将您的建议添加到预填充的代码块中: + + [![Add a suggestion into a code block tagged properly](img/44cad341f814ae94da18480c3dc1d2be.png)](img/make_suggestion_v12_7.png) + +3. 单击**开始审查**或**加入审查** ,以您的评论添加到[审查](#merge-request-reviews) ,或者**现在添加注释** ,注释立即加入到线程. + + 注释中的"建议"可由合并请求作者直接从合并请求中应用: + + [![Apply suggestions](img/0dd0fc53dcaa34b76a16be18538c1a35.png)](img/apply_suggestion_v12_7.png) + +一旦作者应用了一个建议,它将被标记为"已**应用"**标签,该线程将被自动解析,并且 GitLab 将创建一个新的提交,并将建议的更改直接推送到合并请求分支中的代码库中. 这样做需要[开发人员许可](../permissions.html) . + +### Multi-line Suggestions[](#multi-line-suggestions "Permalink") + +在 GitLab 11.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53310) . + +审阅者还可以通过调整范围偏移,在合并请求差异线程中使用单个"建议"来建议对多行进行更改. 偏移量相对于 diff 线程的位置,并指定应用建议时要被建议替换的范围. + +[![Multi-line suggestion syntax](img/317167b85f9604b741e71e57b1702b6c.png)](img/multi-line-suggestion-syntax.png) + +在上面的示例中,建议涵盖了注释行上方的三行和注释行下方的四行. 应用时,它将用建议的更改从注释行*上方的* 3 行替换为注释行*下方*的 4 行. + +[![Multi-line suggestion preview](img/590715bab1c8704d5a4c16437c011ed5.png)](img/multi-line-suggestion-preview.png) + +**注意:**涵盖多行的建议仅限于已注释差异行*上方的* 100 行和*下方*的差异行*下方*的 100 行,每个建议最多可更改 200 行. + +### Code block nested in Suggestions[](#code-block-nested-in-suggestions "Permalink") + +如果您需要提出涉及[受限制的代码块](../markdown.html#code-spans-and-blocks)的建议,请将您的建议换成四个反引号,而不是通常的三个. + +[![A comment editor with a suggestion with a fenced code block](img/a4e7c4f55411323814dd3b9cb30ab9f8.png)](img/suggestion_code_block_editor_v12_8.png) + +[![Output of a comment with a suggestion with a fenced code block](img/db0182b2e43670178e35b1a3485ca25e.png)](img/suggestion_code_block_output_v12_8.png) + +### Configure the commit message for applied Suggestions[](#configure-the-commit-message-for-applied-suggestions "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13086) . + +GitLab 在应用建议时使用默认的提交消息: `Apply %{suggestions_count} suggestion(s) to %{files_count} file(s)` + +例如,假设用户将 3 条建议应用于 2 个不同的文件,则默认的提交消息将是: **将 3 条建议应用于 2 个文件** + +可以自定义这些提交消息,以遵循您可能拥有的任何准则. 为此, **请**在项目的" **常规"**设置中展开" **合并请求"**选项卡,然后更改" **合并建议"**文本: + +[![Custom commit message for applied Suggestions](img/182928c540d17ccf275438850fc7592d.png)](img/suggestions_custom_commit_messages_v13_1.jpg) + +除了静态文本,您还可以使用以下变量: + +| Variable | Description | 输出示例 | +| --- | --- | --- | +| `%{branch_name}` | 建议所应用到的分支的名称. | `my-feature-branch` | +| `%{files_count}` | 应用了建议的文件数. | **2** | +| `%{file_paths}` | 应用了建议文件的路径. 路径用逗号分隔. | `docs/index.md, docs/about.md` | +| `%{project_path}` | 项目路径. | `my-group/my-project` | +| `%{project_name}` | 项目的可读名称. | **我的项目** | +| `%{suggestions_count}` | 应用的建议数. | **3** | +| `%{username}` | 应用建议的用户的用户名. | `user_1` | +| `%{user_full_name}` | 应用建议的用户的全名. | **用户 1** | + +例如,要自定义提交消息以输出**Addresses user_1 的评论** ,请将自定义文本设置为`Addresses %{username}'s review` . + +**注意:** [#25381](https://gitlab.com/gitlab-org/gitlab/-/issues/25381)将为每个应用的建议(以及批量建议)引入自定义提交消息. + +### Batch Suggestions[](#batch-suggestions "Permalink") + +版本历史 + +* 在 GitLab 13.1 中作为[Alpha 功能](https://about.gitlab.com/handbook/product/#alpha) [引入](https://gitlab.com/gitlab-org/gitlab/-/issues/25486) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上已禁用. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-batch-suggestions) . + +您可以一次应用多个建议,以减少为满足审阅者的请求而添加到分支的提交数量. + +1. 要启动将在一次提交中应用的一批建议,请单击" **将建议添加到批处理"** : + + [![A code change suggestion displayed, with the button to add the suggestion to a batch highlighted.](img/f12701028e6548c505318ef2d4e378db.png "Add a suggestion to a batch")](img/add_first_suggestion_to_batch_v13_1.jpg) + +2. 根据需要向批处理中添加尽可能多的其他建议: + + [![A code change suggestion displayed, with the button to add an additional suggestion to a batch highlighted.](img/f60803ec89d6ae84310e181507eb2ad8.png "Add another suggestion to a batch")](img/add_another_suggestion_to_batch_v13_1.jpg) + +3. 要删除建议,请单击" **从批处理中删除"** : + + [![A code change suggestion displayed, with the button to remove that suggestion from its batch highlighted.](img/e28a69b4996ee400ca3df4431df0ab13.png "Remove a suggestion from a batch")](img/remove_suggestion_from_batch_v13_1.jpg) + +4. 将所有建议添加到您的喜好中后,准备好后,请点击**应用建议** : + + [![A code change suggestion displayed, with the button to apply the batch of suggestions highlighted.](img/ed8bdb5d349320bc1d470f096578dfe7.png "Apply a batch of suggestions")](img/apply_batch_of_suggestions_v13_1.jpg) + +#### Enable or disable Batch Suggestions[](#enable-or-disable-batch-suggestions "Permalink") + +批处理建议部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../administration/feature_flags.html)可以为您的实例启用它. + +要启用它: + +``` +# Instance-wide +Feature.enable(:batch_suggestions) +``` + +禁用它: + +``` +# Instance-wide +Feature.disable(:batch_suggestions) +``` + +## Start a thread by replying to a standard comment[](#start-a-thread-by-replying-to-a-standard-comment "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30299) + +要回复标准(非线程)评论,可以使用" **回复评论"**按钮. + +[![Reply to comment button](img/d198d958fcf8be60727c232ff69b9713.png)](img/reply_to_comment_button.png) + +仅当您有权回复现有主题或从标准评论启动主题时,才会显示" **回复评论"**按钮. + +单击" **回复评论"**按钮将使回复区域成为焦点,您可以键入回复. + +[![Reply to comment feature](img/9f29552692cfb04d323dc62cc4bc1d1e.png)](img/reply_to_comment.gif) + +提交回复后,回复非线程注释将把非线程注释转换为线程. 该转换被认为是对原始评论的修改,因此在其下方会出现一条有关上次编辑时间的注释. + +此功能仅适用于"问题","合并请求"和"事件". 尚不支持提交,摘要和合并请求差异线程. + +## Assign an issue to the commenting user[](#assign-an-issue-to-the-commenting-user "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/191455) . + +您可以将问题分配给发表评论的用户. + +在评论中,单击" **更多操作"**菜单,然后单击" **分配给评论用户"** . + +再次单击按钮以取消分配评论者. + +[![Assign to commenting user](img/9b6a8d0d96113fcaadd766cecfbecdbc.png)](img/quickly_assign_commenter_v13_1.png) \ No newline at end of file diff --git a/_book/docs/400.md b/_book/docs/400.md new file mode 100644 index 0000000000000000000000000000000000000000..78df8124308ef04e7c771c58a15b44eeb18c6a0b --- /dev/null +++ b/_book/docs/400.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/topics/authentication/](https://docs.gitlab.com/ee/topics/authentication/) \ No newline at end of file diff --git a/_book/docs/401.md b/_book/docs/401.md new file mode 100644 index 0000000000000000000000000000000000000000..78df8124308ef04e7c771c58a15b44eeb18c6a0b --- /dev/null +++ b/_book/docs/401.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/topics/authentication/](https://docs.gitlab.com/ee/topics/authentication/) \ No newline at end of file diff --git a/_book/docs/402.md b/_book/docs/402.md new file mode 100644 index 0000000000000000000000000000000000000000..4712fda47542d4bc7c4a04b9f09c47d70f0fa590 --- /dev/null +++ b/_book/docs/402.md @@ -0,0 +1,368 @@ +# GitLab and SSH keys + +> 原文:[https://docs.gitlab.com/ee/ssh/README.html](https://docs.gitlab.com/ee/ssh/README.html) + +* [Requirements](#requirements) +* [Options for SSH keys](#options-for-ssh-keys) +* [Review existing SSH keys](#review-existing-ssh-keys) +* [Generating a new SSH key pair](#generating-a-new-ssh-key-pair) + * [ED25519 SSH keys](#ed25519-ssh-keys) + * [RSA SSH keys](#rsa-ssh-keys) + * [Common steps for generating an SSH key pair](#common-steps-for-generating-an-ssh-key-pair) + * [RSA keys and OpenSSH from versions 6.5 to 7.8](#rsa-keys-and-openssh-from-versions-65-to-78) +* [Adding an SSH key to your GitLab account](#adding-an-ssh-key-to-your-gitlab-account) +* [Testing that everything is set up correctly](#testing-that-everything-is-set-up-correctly) +* [Working with non-default SSH key pair paths](#working-with-non-default-ssh-key-pair-paths) +* [Per-repository SSH keys](#per-repository-ssh-keys) +* [Multiple accounts on a single GitLab instance](#multiple-accounts-on-a-single-gitlab-instance) +* [Deploy keys](#deploy-keys) +* [Applications](#applications) + * [Eclipse](#eclipse) +* [SSH on the GitLab server](#ssh-on-the-gitlab-server) + * [Options for Microsoft Windows](#options-for-microsoft-windows) +* [Troubleshooting](#troubleshooting) + +# GitLab and SSH keys[](#gitlab-and-ssh-keys "Permalink") + +Git 是一个分布式版本控制系统,这意味着您可以在本地工作. 此外,您还可以将更改共享或"推送"到其他服务器. GitLab 支持使用 SSH 密钥在 Git 及其服务器之间进行安全通信. + +SSH 协议提供了这种安全性,并允许您向 GitLab 远程服务器进行身份验证,而无需每次都提供用户名或密码. + +该页面可以帮助您配置安全的 SSH 密钥,这些密钥可用于帮助保护与 GitLab 存储库的连接. + +* 如果您需要有关创建 SSH 密钥的信息,请从我们[的 SSH 密钥选项](#options-for-ssh-keys)开始. +* 如果您有专用于 GitLab 帐户的 SSH 密钥,则可能对[使用非默认 SSH 密钥对路径](#working-with-non-default-ssh-key-pair-paths)感兴趣. +* 如果您已经有了 SSH 密钥对,则可以转到[将 SSH 密钥添加到 GitLab 帐户的方法](#adding-an-ssh-key-to-your-gitlab-account) . + +## Requirements[](#requirements "Permalink") + +为了支持 SSH,GitLab 需要安装 OpenSSH 客户端,该客户端已预安装在 GNU / Linux 和 macOS 上,但未预先安装在 Windows 上. + +确保您的系统包括 SSH 6.5 或更高版本,因为它不包括现在不安全的 MD5 签名方案. 以下命令返回系统上安装的 SSH 版本: + +``` +ssh -V +``` + +尽管 GitLab 不[支持在 Microsoft Windows 上进行安装](../install/requirements.html#microsoft-windows) ,但是您可以设置 SSH 密钥以将 Windows 设置[为客户端](#options-for-microsoft-windows) . + +## Options for SSH keys[](#options-for-ssh-keys "Permalink") + +GitLab 支持使用 RSA,DSA,ECDSA 和 ED25519 密钥. + +* GitLab 在 GitLab 11.0 中已[弃用](https://about.gitlab.com/releases/2018/06/22/gitlab-11-0-released/#support-for-dsa-ssh-keys) DSA 密钥. +* 如[Go 实用密码术中](https://leanpub.com/gocrypto/read#leanpub-auto-ecdsa)所述,与 DSA 相关的安全性问题也适用于 ECDSA. + +**提示:**现有文档表明 ED25519 更安全. 如果使用 RSA 密钥,则美国国家科学技术研究院[出版物 800-57 第 3 部分(PDF)](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf)建议密钥大小至少为 2048 位. + +因此,我们的文档集中在 ED25519 和 RSA 密钥的使用上. + +管理员可以[限制应允许的密钥及其最小长度](../security/ssh_keys_restrictions.html) . + +## Review existing SSH keys[](#review-existing-ssh-keys "Permalink") + +如果您已有 SSH 密钥,则可以使用它们来帮助保护与 GitLab 存储库的连接. 默认情况下,Linux 和 macOS 系统上的 SSH 密钥存储在用户的主目录中的`.ssh/`子目录中. 下表包括每种 SSH 密钥算法的默认文件名: + +| Algorithm | 公钥 | 私钥 | +| --- | --- | --- | +| ED25519(首选) | `id_ed25519.pub` | `id_ed25519` | +| RSA(至少 2048 位密钥大小) | `id_rsa.pub` | `id_rsa` | +| DSA(已弃用) | `id_dsa.pub` | `id_dsa` | +| ECDSA | `id_ecdsa.pub` | `id_ecdsa` | + +有关建议,请参阅[SSH 密钥的选项](#options-for-ssh-keys) . + +## Generating a new SSH key pair[](#generating-a-new-ssh-key-pair "Permalink") + +如果要创建: + +* ED25519 密钥,请阅读[ED25519 SSH 密钥](#ed25519-ssh-keys) . +* RSA 密钥,请阅读[RSA SSH 密钥](#rsa-ssh-keys) . + +### ED25519 SSH keys[](#ed25519-ssh-keys "Permalink") + +The book [Practical Cryptography With Go](https://leanpub.com/gocrypto/read#leanpub-auto-chapter-5-digital-signatures) suggests that [ED25519](https://ed25519.cr.yp.to/) keys are more secure and performant than RSA keys. + +随着 OpenSSH 6.5 在 2014 年引入 ED25519 SSH 密钥,它们应该在任何当前操作系统上都可用. + +您可以使用以下命令创建和配置 ED25519 密钥: + +``` +ssh-keygen -t ed25519 -C "" +``` + +`-C`标志(带引号的注释,例如电子邮件地址)是标记 SSH 密钥的可选方法. + +您将看到类似于以下内容的响应: + +``` +Generating public/private ed25519 key pair. +Enter file in which to save the key (/home/user/.ssh/id_ed25519): +``` + +要获得指导,请继续执行[常见步骤](#common-steps-for-generating-an-ssh-key-pair) . + +### RSA SSH keys[](#rsa-ssh-keys "Permalink") + +如果您将 RSA 密钥用于 SSH,则美国国家标准技术研究院建议您使用[至少 2048 位](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf)的密钥大小. 缺省情况下, `ssh-keygen`命令创建一个 1024 位 RSA 密钥. + +您可以使用以下命令创建和配置 RSA 密钥,如果需要,可以使用建议的最小密钥大小`2048`代替: + +``` +ssh-keygen -t rsa -b 2048 -C "email@example.com" +``` + +`-C`标志(带引号的注释,例如电子邮件地址)是标记 SSH 密钥的可选方法. + +您将看到类似于以下内容的响应: + +``` +Generating public/private rsa key pair. +Enter file in which to save the key (/home/user/.ssh/id_rsa): +``` + +要获得指导,请继续执行[常见步骤](#common-steps-for-generating-an-ssh-key-pair) . + +**注意:**如果您具有 7.8 或更低版本的 OpenSSH,请考虑与[编码](#rsa-keys-and-openssh-from-versions-65-to-78)相关的问题. + +### Common steps for generating an SSH key pair[](#common-steps-for-generating-an-ssh-key-pair "Permalink") + +无论是创建[ED25519](#ed25519-ssh-keys)还是创建[RSA](#rsa-ssh-keys)密钥,您都从`ssh-keygen`命令开始. 此时,您将在命令行中看到以下消息(用于 ED25519 键): + +``` +Generating public/private ed25519 key pair. +Enter file in which to save the key (/home/user/.ssh/id_rsa): +``` + +如果您还没有 SSH 密钥对并且没有生成[部署密钥](#deploy-keys) ,请接受建议的文件和目录. 您的 SSH 客户端将使用生成的 SSH 密钥对,而无需其他配置. + +或者,您可以将新的 SSH 密钥对保存在其他位置. 您可以分配您选择的目录和文件名. 您还可以将 SSH 密钥对专用于[特定主机](#working-with-non-default-ssh-key-pair-paths) . + +分配文件以保存 SSH 密钥后,您将有机会为 SSH 密钥设置[密码](https://www.ssh.com/ssh/passphrase/) : + +``` +Enter passphrase (empty for no passphrase): +Enter same passphrase again: +``` + +如果成功,您将看到有关`ssh-keygen`命令将标识和私钥保存在何处的确认. + +需要时,可以使用以下命令更新密码: + +``` +ssh-keygen -p -f /path/to/ssh_key +``` + +### RSA keys and OpenSSH from versions 6.5 to 7.8[](#rsa-keys-and-openssh-from-versions-65-to-78 "Permalink") + +在 OpenSSH 7.8 之前,RSA 密钥的默认公共密钥指纹基于 MD5,因此不安全. + +如果您的 OpenSSH 版本介于 6.5 至 7.8(含)之间,请使用`-o`选项运行`ssh-keygen` ,以更安全的 OpenSSH 格式保存您的私人 SSH 密钥. + +如果您已经具有可用于 GitLab 的 RSA SSH 密钥对,请考虑对其进行升级以使用更安全的密码加密格式. 您可以使用以下命令进行操作: + +``` +ssh-keygen -o -f ~/.ssh/id_rsa +``` + +或者,您可以使用以下命令以更安全的加密格式生成新的 RSA 密钥: + +``` +ssh-keygen -o -t rsa -b 4096 -C "email@example.com" +``` + +**注意:**如`ssh-keygen`手册页所述,ED25519 已将密钥加密为更安全的 OpenSSH 格式. + +## Adding an SSH key to your GitLab account[](#adding-an-ssh-key-to-your-gitlab-account "Permalink") + +现在,您可以将创建的 SSH 密钥复制到您的 GitLab 帐户. 这样做,请按照下列步骤操作: + +1. 将您的**公共** SSH 密钥复制到以文本格式保存信息的位置. 以下选项将 ED25519 键的信息保存到指定操作系统的剪贴板中: + + **macOS:** + + ``` + pbcopy < ~/.ssh/id_ed25519.pub + ``` + + **Linux(需要 xclip 软件包):** + + ``` + xclip -sel clip < ~/.ssh/id_ed25519.pub + ``` + + **Windows 上的 Git Bash:** + + ``` + cat ~/.ssh/id_ed25519.pub | clip + ``` + + 如果您使用的是 RSA 密钥,请相应地进行替换. + +2. 导航到`http://gitlab.com`并登录. +3. 选择右上角的头像,然后单击**设置** +4. Click **SSH 密钥**. +5. 将复制的公共密钥粘贴到" **密钥"**文本框中. +6. 确保您的密钥在" **标题"**文本框中包含描述性名称,例如" *工作笔记本电脑"*或" *家用工作站"* . +7. 在"过期时间"部分下包含密钥的(可选)过期日期. (在[GitLab 12.9 中](https://gitlab.com/gitlab-org/gitlab/-/issues/36243)引入.) +8. 单击**添加键**按钮. + +使用此过程"过期"的 SSH 密钥在 GitLab 工作流程中仍然有效. 由于 GitLab 配置的到期日期不包含在 SSH 密钥本身中,因此您仍然可以根据需要导出公共 SSH 密钥. + +**注意:**如果您手动复制了公共 SSH 密钥,请确保复制了整个密钥,以`ssh-ed25519` (或`ssh-rsa` )开头,并以您的电子邮件地址结尾. + +## Testing that everything is set up correctly[](#testing-that-everything-is-set-up-correctly "Permalink") + +要测试是否正确添加了 SSH 密钥,请在终端中运行以下命令(将`gitlab.com`替换为 GitLab 的实例域): + +``` +ssh -T git@gitlab.com +``` + +The first time you connect to GitLab via SSH, you will be asked to verify the authenticity of the GitLab host that you’re connecting to. For example, when connecting to GitLab.com, answer `yes` to add GitLab.com to the list of trusted hosts: + +``` +The authenticity of host 'gitlab.com (35.231.145.151)' can't be established. +ECDSA key fingerprint is SHA256:HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw. +Are you sure you want to continue connecting (yes/no)? yes +Warning: Permanently added 'gitlab.com' (ECDSA) to the list of known hosts. +``` + +**注意:**对于 GitLab.com,请查阅[SSH 主机密钥指纹](../user/gitlab_com/index.html#ssh-host-keys-fingerprints)一节,以确保您连接到正确的服务器. 例如,您会在链接的部分中看到上面显示的 ECDSA 密钥指纹. + +一旦添加到已知主机列表中,将不再要求您再次验证 GitLab 主机的真实性. 再次运行以上命令,您将只收到*欢迎使用 GitLab 的`@username` !* 信息. + +如果未出现欢迎消息,则可以通过使用以下命令在详细模式下运行`ssh`来解决问题: + +``` +ssh -Tvvv git@gitlab.com +``` + +## Working with non-default SSH key pair paths[](#working-with-non-default-ssh-key-pair-paths "Permalink") + +如果您为 GitLab SSH 密钥对使用了非默认文件路径,请配置 SSH 客户端以指向 GitLab 私有 SSH 密钥. + +要进行这些更改,请运行以下命令: + +``` +eval $(ssh-agent -s) +ssh-add +``` + +现在将这些设置保存到`~/.ssh/config`文件中. 这里显示了两个专用于 GitLab 的 SSH 密钥示例: + +``` +# GitLab.com Host gitlab.com + Preferredauthentications publickey + IdentityFile ~/.ssh/gitlab_com_rsa + +# Private GitLab instance Host gitlab.company.com + Preferredauthentications publickey + IdentityFile ~/.ssh/example_com_rsa +``` + +公用 SSH 密钥对于 GitLab 必须是唯一的,因为它们将绑定到您的帐户. SSH 密钥是通过 SSH 推送代码时唯一的标识符,这就是为什么它需要唯一地映射到单个用户的原因. + +## Per-repository SSH keys[](#per-repository-ssh-keys "Permalink") + +如果要根据正在使用的存储库使用不同的密钥,则可以在存储库中发出以下命令: + +``` +git config core.sshCommand "ssh -o IdentitiesOnly=yes -i ~/.ssh/private-key-filename-for-this-repository -F /dev/null" +``` + +这将不使用 SSH 代理,并且至少需要 Git 2.10. + +## Multiple accounts on a single GitLab instance[](#multiple-accounts-on-a-single-gitlab-instance "Permalink") + +[每个存储库](#per-repository-ssh-keys)方法还适用于在单个 GitLab 实例中使用多个帐户. + +或者,可以直接在`~.ssh/config`为主机分配别名. 如果在`.ssh/config`中的`Host`块之外设置了`IdentityFile` ,则 SSH 和作为扩展的 Git 将无法登录. 这是由于 SSH 组装`IdentityFile`条目的方式,因此不能通过将`IdentitiesOnly`设置为`yes`来更改. `IdentityFile`条目应指向 SSH 密钥对的私钥. + +**注意:**私钥和公用密钥应仅由用户读取. 通过运行以下`chmod 0400 ~/.ssh/`在 Linux 和 macOS 上完成此操作: `chmod 0400 ~/.ssh/`和`chmod 0400 ~/.ssh/` . + +``` +# User1 Account Identity Host + Hostname gitlab.com + PreferredAuthentications publickey + IdentityFile ~/.ssh/ + +# User2 Account Identity Host + Hostname gitlab.com + PreferredAuthentications publickey + IdentityFile ~/.ssh/ +``` + +**注意:**为提高效率和透明度,示例`Host`别名定义为`user_1.gitlab.com`和`user_2.gitlab.com` . 高级配置更难以维护. 使用这种别名使使用其他工具(如`git remote`子命令)时更容易理解. SSH 可以将任何字符串理解为`Host`别名,因此`Tanuki1`和`Tanuki2`尽管提供了很少的上下文指向它们,也可以使用. + +克隆`gitlab`存储库通常如下所示: + +``` +git clone git@gitlab.com:gitlab-org/gitlab.git +``` + +要为`user_1`克隆它,请将`gitlab.com`替换为 SSH 别名`user_1.gitlab.com` : + +``` +git clone git@:gitlab-org/gitlab.git +``` + +使用`git remote`命令修复以前克隆的存储库. + +下面的示例假定远程存储库被别名为`origin` . + +``` +git remote set-url origin git@:gitlab-org/gitlab.git +``` + +## Deploy keys[](#deploy-keys "Permalink") + +阅读[有关部署密钥](../user/project/deploy_keys/index.html)的[文档](../user/project/deploy_keys/index.html) . + +## Applications[](#applications "Permalink") + +### Eclipse[](#eclipse "Permalink") + +如果使用的是[EGit](https://www.eclipse.org/egit/) ,则可以[将 SSH 密钥添加到 Eclipse](https://wiki.eclipse.org/EGit/User_Guide#Eclipse_SSH_Configuration) . + +## SSH on the GitLab server[](#ssh-on-the-gitlab-server "Permalink") + +GitLab 与系统安装的 SSH 守护程序集成,指定一个用户(通常名为`git` )来处理所有访问请求. 通过 SSH 连接到 GitLab 服务器的用户由其 SSH 密钥而不是其用户名标识. + +在 GitLab 服务器上执行的 SSH *客户端*操作将以该用户身份执行. 尽管可以修改此用户的 SSH 配置,例如提供专用 SSH 密钥来验证这些请求,但是这种做法**不受支持** ,并且强烈建议这样做,因为这样做会带来重大的安全风险. + +GitLab 检查过程包括对这种情况的检查,如果您的服务器配置如下,它将引导您进入本节,例如: + +``` +$ gitlab-rake gitlab:check + +Git user has default SSH configuration? ... no + Try fixing it: + mkdir ~/gitlab-check-backup-1504540051 + sudo mv /var/lib/git/.ssh/id_rsa ~/gitlab-check-backup-1504540051 + sudo mv /var/lib/git/.ssh/id_rsa.pub ~/gitlab-check-backup-1504540051 + For more information see: + doc/ssh/README.md in section "SSH on the GitLab server" + Please fix the error above and rerun the checks. +``` + +尽快删除自定义配置. 这些自定义项*明确不受支持,*并且可能随时停止工作. + +### Options for Microsoft Windows[](#options-for-microsoft-windows "Permalink") + +如果您运行的是 Windows 10, [适用于 Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10)的[Windows 子系统(WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10)及其最新的[WSL 2](https://docs.microsoft.com/en-us/windows/wsl/install-win10#update-to-wsl-2)版本,则支持安装不同的 Linux 发行版,其中包括 Git 和 SSH 客户端. + +对于当前版本的 Windows,您还可以通过[Git for Windows](https://gitforwindows.org)安装 Git 和 SSH 客户端. + +替代工具包括: + +* [Cygwin](https://www.cygwin.com) +* [PuttyGen](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) + +## Troubleshooting[](#troubleshooting "Permalink") + +如果在 Git 克隆上,系统会提示您输入密码,例如`git@gitlab.com's password:` SSH 设置有问题. + +* 确保您正确生成了 SSH 密钥对,并将公共 SSH 密钥添加到了 GitLab 配置文件 +* 尝试使用`ssh-agent`手动注册您的私有 SSH 密钥,如本文档前面所述 +* 尝试通过运行`ssh -Tv git@example.com`调试连接(将 GitLab 域替换为`example.com` ) \ No newline at end of file diff --git a/_book/docs/403.md b/_book/docs/403.md new file mode 100644 index 0000000000000000000000000000000000000000..5fa604d27549b679c78b4a628b000efd2dc8725f --- /dev/null +++ b/_book/docs/403.md @@ -0,0 +1,104 @@ +# GitLab integrations + +> 原文:[https://docs.gitlab.com/ee/integration/README.html](https://docs.gitlab.com/ee/integration/README.html) + +* [Issue trackers](#issue-trackers) +* [Authentication sources](#authentication-sources) +* [Security enhancements](#security-enhancements) +* [Continuous integration](#continuous-integration) +* [Feature enhancements](#feature-enhancements) +* [Integrations](#integrations) +* [Troubleshooting](#troubleshooting) + * [SSL certificate errors](#ssl-certificate-errors) + +# GitLab integrations[](#gitlab-integrations "Permalink") + +GitLab can be integrated with external services for enhanced functionality. + +## Issue trackers[](#issue-trackers "Permalink") + +您可以与 GitLab 问题跟踪器同时使用[外部问题跟踪](external-issue-tracker.html)器,也可以仅使用外部问题跟踪器. + +GitLab 可以与以下外部问题跟踪器集成: + +* Jira +* Redmine +* Bugzilla +* YouTrack + +## Authentication sources[](#authentication-sources "Permalink") + +可以将 GitLab 配置为使用以下身份验证源对访问请求进行身份验证: + +* 启用[Auth0 OmniAuth](auth0.html)提供程序. +* 启用使用[Bitbucket](bitbucket.html)帐户登录. +* 配置 GitLab 以使用[CAS 登录](cas.html) . +* 与[Kerberos](kerberos.html)集成. +* 启用通过[LDAP](ldap.html)登录. +* 启用[OAuth2 提供](oauth_provider.html)程序应用程序创建. +* 使用[OmniAuth](omniauth.html)可以通过 Twitter,GitHub,GitLab.com,Google,Bitbucket,Facebook,Shibboleth,SAML,Crowd,Azure 或 Authentiq ID 启用登录. +* 使用 GitLab 作为[OpenID Connect](openid_connect_provider.html)身份提供者. +* 通过 GitLab OpenID Connect 对[保险柜](vault.html)进行身份验证. +* 将 GitLab 配置为[SAML](saml.html) 2.0 服务提供商. + +## Security enhancements[](#security-enhancements "Permalink") + +GitLab 可以与以下外部服务集成以增强安全性: + +* [Akismet](akismet.html)有助于减少垃圾邮件. +* Google [reCAPTCHA](recaptcha.html)有助于验证新用户. + +manbetx 客户端打不开还提供功能来提高您自己的应用程序的安全性. 有关更多详细信息,请参见[GitLab Secure](../user/application_security/index.html) . + +## Continuous integration[](#continuous-integration "Permalink") + +GitLab 可以与以下外部服务集成以实现持续集成: + +* [Jenkins](jenkins.html) CI. + +## Feature enhancements[](#feature-enhancements "Permalink") + +GitLab 可以集成以下增强功能: + +* 将 GitLab 操作添加到[Gmail 操作按钮](gmail_action_buttons_for_gitlab.html) . +* 配置[PlantUML](../administration/integration/plantuml.html)以使用 AsciiDoc 文档中的图. +* 将合并请求附加到[Trello](trello_power_up.html)卡. +* 启用由[Sourcegraph](sourcegraph.html)支持的集成代码智能. +* 添加[Elasticsearch](elasticsearch.html)进行[Advanced Global Search](../user/search/advanced_global_search.html) , [Advanced System Search](../user/search/advanced_search_syntax.html)和更快的搜索. + +## Integrations[](#integrations "Permalink") + +可以与 Campfire,Flowdock,HipChat,Pivotal Tracker 和 Slack 等服务[集成](../user/project/integrations/overview.html) . + +## Troubleshooting[](#troubleshooting "Permalink") + +### SSL certificate errors[](#ssl-certificate-errors "Permalink") + +当尝试将 GitLab 与使用自签名证书的服务集成时,很可能在应用程序的不同部分(最可能是 Sidekiq)会发生 SSL 证书错误. + +您可以采用两种方法来解决此问题: + +1. 将根证书添加到操作系统的受信任链. +2. 如果使用 Omnibus,则可以将证书添加到 GitLab 的可信证书中. + +**操作系统主要信任链** + +此[资源](https://manuals.gfi.com/en/kerio/connect/content/server-configuration/ssl-certificates/adding-trusted-root-certificates-to-the-server-1605.html)包含将证书添加到主信任链所需的所有信息. + +超级用户的此[答案](https://superuser.com/questions/437330/how-do-you-add-a-certificate-authority-ca-to-ubuntu)也具有相关信息. + +**所有可信任链** + +[将自签名证书或自定义证书颁发机构安装](https://docs.gitlab.com/omnibus/common_installation_problems/README.html)到 Omnibus GitLab. + +将证书连接到主要的受信任证书就足够了,但是在升级过程中它可能会被覆盖: + +``` +cat jira.pem >> /opt/gitlab/embedded/ssl/certs/cacert.pem +``` + +之后,使用以下命令重新启动 GitLab: + +``` +sudo gitlab-ctl restart +``` \ No newline at end of file diff --git a/_book/docs/404.md b/_book/docs/404.md new file mode 100644 index 0000000000000000000000000000000000000000..e10d3d3dcec26d3fec6d83acae199f4d7b9851bc --- /dev/null +++ b/_book/docs/404.md @@ -0,0 +1,103 @@ +# Git + +> 原文:[https://docs.gitlab.com/ee/topics/git/](https://docs.gitlab.com/ee/topics/git/) + +* [Getting started](#getting-started) + * [Concepts](#concepts) +* [Git tips](#git-tips) +* [Troubleshooting Git](#troubleshooting-git) +* [Branching strategies](#branching-strategies) +* [Advanced use](#advanced-use) +* [API](#api) +* [Git Large File Storage (LFS)](#git-large-file-storage-lfs) + +# Git[](#git "Permalink") + +Git 是一个[免费的开源](https://git-scm.com/about/free-and-open-source)分布式版本控制系统,旨在快速高效地处理从小型项目到大型项目的所有内容. + +[GitLab](https://about.gitlab.com)是用于软件开发的基于 Git 的完全集成平台. 除了 Git 的功能外,GitLab 还具有许多强大的[功能](https://about.gitlab.com/features/)来增强您的[工作流程](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/) . + +我们已经收集了一些资源,可帮助您通过 GitLab 从 Git 中获得最大收益. + +还可以在[Git 网站](https://git-scm.com)上获得更多信息. + +## Getting started[](#getting-started "Permalink") + +以下资源将帮助您开始使用 Git: + +* [Git-ing 从 Git](https://www.youtube.com/watch?v=Ce5nz5n41z4)的视频介绍开始. +* [Git Basics](https://git-scm.com/book/en/v2/Getting-Started-Git-Basics) +* [Git on the Server - GitLab](https://git-scm.com/book/en/v2/Git-on-the-Server-GitLab) +* [How to install Git](how_to_install_git/index.html) +* [Git terminology](../../gitlab-basics/start-using-git.html#git-terminology) +* [Start using Git on the command line](../../gitlab-basics/start-using-git.html) +* [Edit files through the command line](../../gitlab-basics/command-line-commands.html) +* [GitLab Git Cheat Sheet (download)](https://about.gitlab.com/images/press/git-cheat-sheet.pdf) +* Commits: + * [Revert a commit](../../user/project/merge_requests/revert_changes.html#reverting-a-commit) + * [Cherry-picking a commit](../../user/project/merge_requests/cherry_pick_changes.html#cherry-picking-a-commit) + * [Squashing commits](../gitlab_flow.html#squashing-commits-with-rebase) + * [Squash-and-merge](../../user/project/merge_requests/squash_and_merge.html) + * [Signing commits](../../user/project/repository/gpg_signed_commits/index.html) +* [Git stash](../../university/training/topics/stash.html) +* [Git file blame](../../user/project/repository/git_blame.html) +* [Git file history](../../user/project/repository/git_history.html) +* [Git tags](../../university/training/user_training.html#tags) + +### Concepts[](#concepts "Permalink") + +以下是有关版本控制概念的资源: + +* [Git concepts](../../university/training/user_training.html#git-concepts) +* [Why Git is Worth the Learning Curve](https://about.gitlab.com/blog/2017/05/17/learning-curve-is-the-biggest-challenge-developers-face-with-git/) +* [The future of SaaS hosted Git repository pricing](https://about.gitlab.com/blog/2016/05/11/git-repository-pricing/) +* [Git website on version control](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control) +* [GitLab University presentation about Version Control](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit?usp=sharing) + +## Git tips[](#git-tips "Permalink") + +以下资源可以帮助您提高使用 Git 的效率: + +* GitLab 支持团队收集的[有用的 Git 命令](useful_git_commands.html) . +* [Git Tips & Tricks](https://about.gitlab.com/blog/2016/12/08/git-tips-and-tricks/) +* [Eight Tips to help you work better with Git](https://about.gitlab.com/blog/2015/02/19/8-tips-to-help-you-work-better-with-git/) + +## Troubleshooting Git[](#troubleshooting-git "Permalink") + +如果您在使用 Git 时遇到问题,以下方法可能会有所帮助: + +* [Numerous *undo* possibilities in Git](numerous_undo_possibilities_in_git/index.html) +* 了解一些[Git 故障排除](troubleshooting_git.html)技术 + +## Branching strategies[](#branching-strategies "Permalink") + +* [Feature branch workflow](../../gitlab-basics/feature_branch_workflow.html) +* [Develop on a feature branch](feature_branch_development.html) +* [GitLab Flow](../gitlab_flow.html) +* [Git Branching - Branches in a Nutshell](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell) +* [Git Branching - Branching Workflows](https://git-scm.com/book/en/v2/Git-Branching-Branching-Workflows) + +## Advanced use[](#advanced-use "Permalink") + +以下是针对那些想充分利用 Git 的人的高级主题: + +* [Server Hooks](../../administration/server_hooks.html) +* [Git Attributes](../../user/project/git_attributes.html) +* Git 子模块: [将 Git 子模块与 GitLab CI 一起使用](../../ci/git_submodules.html#using-git-submodules-with-gitlab-ci) +* [Partial Clone](partial_clone.html) + +## API[](#api "Permalink") + +[Gitignore 模板](../../api/templates/gitignores.html) API 允许来自 GitLab 的与 Git 相关的查询. + +## Git Large File Storage (LFS)[](#git-large-file-storage-lfs "Permalink") + +以下与 Git 大文件存储有关: + +* [Getting Started with Git LFS](https://about.gitlab.com/blog/2017/01/30/getting-started-with-git-lfs-tutorial/) +* [Migrate an existing Git repository with Git LFS](lfs/migrate_to_git_lfs.html) +* [Removing objects from LFS](lfs/index.html#removing-objects-from-lfs) +* [GitLab Git LFS user documentation](lfs/index.html) +* [GitLab Git LFS admin documentation](../../administration/lfs/index.html) +* [Git Annex to Git LFS migration guide](lfs/migrate_from_git_annex_to_git_lfs.html) +* [Towards a production quality open source Git LFS server](https://about.gitlab.com/blog/2015/08/13/towards-a-production-quality-open-source-git-lfs-server/) \ No newline at end of file diff --git a/_book/docs/405.md b/_book/docs/405.md new file mode 100644 index 0000000000000000000000000000000000000000..71a8d67b702484beab949c2c6233dd1aedcab18a --- /dev/null +++ b/_book/docs/405.md @@ -0,0 +1,576 @@ +# GitLab.com settings + +> 原文:[https://docs.gitlab.com/ee/user/gitlab_com/](https://docs.gitlab.com/ee/user/gitlab_com/) + +* [SSH host keys fingerprints](#ssh-host-keys-fingerprints) +* [SSH `known_hosts` entries](#ssh-known_hosts-entries) +* [Mail configuration](#mail-configuration) +* [Backups](#backups) +* [Alternative SSH port](#alternative-ssh-port) +* [GitLab Pages](#gitlab-pages) +* [GitLab CI/CD](#gitlab-cicd) +* [Repository size limit](#repository-size-limit) +* [IP range](#ip-range) +* [Maximum number of webhooks](#maximum-number-of-webhooks) +* [Shared Runners](#shared-runners) + * [Linux Shared Runners](#linux-shared-runners) + * [Pre-clone script](#pre-clone-script) + * [`config.toml`](#configtoml) + * [Windows Shared Runners (beta)](#windows-shared-runners-beta) + * [Configuration](#configuration) + * [Example](#example) + * [Limitations and known issues](#limitations-and-known-issues) +* [Sidekiq](#sidekiq) +* [PostgreSQL](#postgresql) +* [Unicorn](#unicorn) +* [GitLab.com-specific rate limits](#gitlabcom-specific-rate-limits) + * [HAProxy API throttle](#haproxy-api-throttle) + * [Rack Attack initializer](#rack-attack-initializer) + * [Protected paths throttle](#protected-paths-throttle) + * [Git and container registry failed authentication ban](#git-and-container-registry-failed-authentication-ban) + * [Admin Area settings](#admin-area-settings) + * [Visibility settings](#visibility-settings) + * [SSH maximum number of connections](#ssh-maximum-number-of-connections) + * [Import/export](#importexport) +* [GitLab.com Logging](#gitlabcom-logging) +* [GitLab.com at scale](#gitlabcom-at-scale) + * [Elastic Cluster](#elastic-cluster) + * [Fluentd](#fluentd) + * [Prometheus](#prometheus) + * [Grafana](#grafana) + * [Sentry](#sentry) + * [Consul](#consul) + * [HAProxy](#haproxy) + +# GitLab.com settings[](#gitlabcom-settings "Permalink") + +在此页面中,您将找到有关[GitLab.com](https://about.gitlab.com/pricing/)上使用的设置的信息. + +## SSH host keys fingerprints[](#ssh-host-keys-fingerprints "Permalink") + +以下是 GitLab.com 的 SSH 主机密钥的指纹. 首次连接到 GitLab.com 存储库时,您将在输出中看到这些键之一. + +| Algorithm | MD5(已弃用) | SHA256 | +| --- | --- | --- | +| DSA(已弃用) | `7a:47:81:3a:ee:89:89:64:33:ca:44:52:3d:30:d4:87` | `p8vZBUOR0XQz6sYiaWSMLmh0t9i8srqYKool/Xfdfqw` | +| ECDSA | `f1:d0:fb:46:73:7a:70:92:5a:ab:5d:ef:43:e2:1c:35` | `HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw` | +| ED25519 | `2e:65:6a:c8:cf:bf:b2:8b:9a:bd:6d:9f:11:5c:12:16` | `eUXGGm1YGsMAS7vkcx6JOJdOGHPem5gQp4taiCfCLB8` | +| RSA | `b6:03:0e:39:97:9e:d0:e7:24:ce:a3:77:3e:01:42:09` | `ROQFvPThGrW4RuWLoL9tq9I9zJ42fK4XywyRtbOz/EQ` | + +## SSH `known_hosts` entries[](#ssh-known_hosts-entries "Permalink") + +将以下内容添加到`.ssh/known_hosts`以跳过 SSH 中的手动指纹确认: + +``` +gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf +gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9 +gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY= +``` + +## Mail configuration[](#mail-configuration "Permalink") + +GitLab.com 通过[Mailgun](https://www.mailgun.com/)从`mg.gitlab.com`域发送电子邮件,并拥有自己的专用 IP 地址( `192.237.158.143` ). + +**注意:** `mg.gitlab.com`的 IP 地址可能随时更改. + +## Backups[](#backups "Permalink") + +[See our backup strategy](https://about.gitlab.com/handbook/engineering/infrastructure/production/#backups). + +## Alternative SSH port[](#alternative-ssh-port "Permalink") + +可以通过`git+ssh`的[其他 SSH 端口](https://about.gitlab.com/blog/2016/02/18/gitlab-dot-com-now-supports-an-alternate-git-plus-ssh-port/)访问 GitLab.com. + +| Setting | Value | +| --- | --- | +| `Hostname` | `altssh.gitlab.com` | +| `Port` | `443` | + +以下是`~/.ssh/config`的示例: + +``` +Host gitlab.com + Hostname altssh.gitlab.com + User git + Port 443 + PreferredAuthentications publickey + IdentityFile ~/.ssh/gitlab +``` + +## GitLab Pages[](#gitlab-pages "Permalink") + +以下是[GitLab 页面](https://about.gitlab.com/stages-devops-lifecycle/pages/)的设置. + +| Setting | GitLab.com | Default | +| --- | --- | --- | +| 域名 | `gitlab.io` | - | +| IP 地址 | `35.185.44.232` | - | +| 自定义域支持 | yes | no | +| TLS 证书支持 | yes | no | +| 最大大小(未压缩) | 1G | 100M | + +**注意:** Pages 站点的最大大小由[GitLab CI / CD 中](#gitlab-cicd)的工件最大大小决定. + +## GitLab CI/CD[](#gitlab-cicd "Permalink") + +以下是有关[GitLab CI / CD](../../ci/README.html)的当前设置. + +| Setting | GitLab.com | Default | +| --- | --- | --- | +| 工件最大尺寸(未压缩) | 1G | 100M | +| Artifacts [expiry time](../../ci/yaml/README.html#artifactsexpire_in) | 从 2020 年 6 月 22 日开始,除非另有说明,否则在 30 天后删除(该日期之前创建的工件没有过期). | 除非另有说明,否则 30 天后删除 | +| 预定管道计划 | `*/5 * * * *` | `19 * * * *` | +| [Max jobs in active pipelines](../../administration/instance_limits.html#number-of-jobs-in-active-pipelines) | 免费套餐为`500` ,否则为无限制 | Unlimited | +| [Max pipeline schedules in projects](../../administration/instance_limits.html#number-of-pipeline-schedules) | 免费套餐`10` `50` ,所有付费套餐`50` | Unlimited | +| [Max number of instance level variables](../../administration/instance_limits.html#number-of-instance-level-variables) | `25` | `25` | +| [Scheduled Job Archival](../../user/admin_area/settings/continuous_integration.html#archive-jobs-core-only) | 3 个月 | Never | + +## Repository size limit[](#repository-size-limit "Permalink") + +GitLab.com 已启用以下[帐户限制](../admin_area/settings/account_and_limit_settings.html) . 如果未列出设置,则将其设置为默认值. + +如果您接近或超过存储库大小限制,则可以[使用 Git 减小存储库大小](../project/repository/reducing_the_repo_size_using_git.html) . + +| Setting | GitLab.com | Default | +| --- | --- | --- | +| 资料库大小,包括 LFS | 10 GB | Unlimited | + +**注意:**每个请求通过 Cloudflare 的`git push`和 GitLab 项目导入限制为 5 GB. Git LFS 和文件上传以外的导入不受此限制的影响. + +## IP range[](#ip-range "Permalink") + +GitLab.com 将 IP 范围`34.74.90.64/28`用于其 Web / API `34.74.90.64/28`的流量. 这整个范围仅分配给 GitLab. 您可以期望来自 Webhooks 或存储库镜像的连接来自这些 IP 并允许它们. + +GitLab.com 由 Cloudflare 领导. 对于与 GitLab.com 的传入连接,您可能需要允许 Cloudflare 的 CIDR 块( [IPv4](https://www.cloudflare.com/ips-v4)和[IPv6](https://www.cloudflare.com/ips-v6) ). + +对于 CI / CD 运行程序的传出连接,我们不提供静态 IP 地址. 我们所有的运行程序都已部署到 Google Cloud Platform(GCP)中-通过查找[GCP 的](https://cloud.google.com/compute/docs/faq#where_can_i_find_product_name_short_ip_ranges)所有[IP 地址范围或 CIDR 块,](https://cloud.google.com/compute/docs/faq#where_can_i_find_product_name_short_ip_ranges)可以配置任何基于 IP 的防火墙. + +## Maximum number of webhooks[](#maximum-number-of-webhooks "Permalink") + +限制: + +* 100 个 webhooks 适用于项目. +* 50 个 webhooks 适用于组. + +## Shared Runners[](#shared-runners "Permalink") + +GitLab 提供在 GitLab.com 上托管的 Linux 和 Windows 共享运行程序,用于执行管道. + +**注意:** GitLab 提供的共享运行器**不可**配置. 如果您有特定的配置需求,请考虑[安装自己的 Runner](https://docs.gitlab.com/runner/install/) . + +### Linux Shared Runners[](#linux-shared-runners "Permalink") + +Linux Shared Runners on GitLab.com run in [autoscale mode](https://docs.gitlab.com/runner/configuration/autoscale.html) and are powered by Google Cloud Platform. Autoscaling means reduced waiting times to spin up CI/CD jobs, and isolated VMs for each project, thus maximizing security. They’re free to use for public open source projects and limited to 2000 CI minutes per month per group for private projects. More minutes [can be purchased](../../subscriptions/index.html#purchasing-additional-ci-minutes), if needed. Read about all [GitLab.com plans](https://about.gitlab.com/pricing/). + +您的所有 CI / CD 作业都在具有 3.75GB RAM,CoreOS 和最新 Docker Engine 的[n1-standard-1 实例](https://cloud.google.com/compute/docs/machine-types)上运行. 实例提供 1 个 vCPU 和 25GB 的 HDD 磁盘空间. VM 的默认区域是 US East1\. 每个实例仅用于一项作业,这确保了其他人无法访问其 CI 作业访问系统上剩余的任何敏感数据. + +`gitlab-shared-runners-manager-X.gitlab.com`专用于 GitLab 项目以及它们的社区分支. 它们使用稍大的计算机类型(n1-standard-2),并且具有更大的 SSD 磁盘大小. 它们将不会运行未加标签的作业,并且与共享赛跑者的一般团队不同,这些实例最多可重复使用 40 次. + +由 GitLab.com( `shared-runners-manager-X.gitlab.com` )上的共享 Runner 处理的作业**将在 3 小时后**超时,无论项目中配置的超时时间如何. 检查问题[4010](https://gitlab.com/gitlab-com/infrastructure/-/issues/4010)和[4070,](https://gitlab.com/gitlab-com/infrastructure/-/issues/4070)以供参考. + +以下是共享的"跑步者"设置. + +| Setting | GitLab.com | Default | +| --- | --- | --- | +| [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) | [Runner versions dashboard](https://dashboards.gitlab.com/d/000000159/ci?from=now-1h&to=now&refresh=5m&orgId=1&panelId=12&fullscreen&theme=light) | - | +| Executor | `docker+machine` | - | +| 默认 Docker 映像 | `ruby:2.5` | - | +| `privileged` (run [Docker in Docker](https://hub.docker.com/_/docker/)) | `true` | `false` | + +#### Pre-clone script[](#pre-clone-script "Permalink") + +在 Runner 尝试运行`git init`和`git fetch`下载 GitLab 存储库之前,GitLab.com 上的 Linux Shared Runner 提供了一种在 CI 作业中运行命令的方法. [`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)可用于: + +* 用存储库数据播种构建目录 +* 向服务器发送请求 +* 从 CDN 下载资产 +* `git init`之前必须运行的任何其他命令 + +要使用此功能,请定义一个包含 bash 脚本的[CI / CD 变量](../../ci/variables/README.html#create-a-custom-variable-in-the-ui) `CI_PRE_CLONE_SCRIPT` . + +[本示例](../../development/pipelines.html#pre-clone-step)演示了如何使用预克隆步骤为构建目录添加种子. + +#### `config.toml`[](#configtoml "Permalink") + +我们的`config.toml`的完整内容是: + +**注意:**非公开的设置显示为`X` + +**Google Cloud Platform** + +``` +concurrent = X +check_interval = 1 +metrics_server = "X" +sentry_dsn = "X" + +[[runners]] + name = "docker-auto-scale" + request_concurrency = X + url = "https://gitlab.com/" + token = "SHARED_RUNNER_TOKEN" + pre_clone_script = "eval \"$CI_PRE_CLONE_SCRIPT\"" + executor = "docker+machine" + environment = [ + "DOCKER_DRIVER=overlay2", + "DOCKER_TLS_CERTDIR=" + ] + limit = X + [runners.docker] + image = "ruby:2.5" + privileged = true + volumes = [ + "/certs/client", + "/dummy-sys-class-dmi-id:/sys/class/dmi/id:ro" # Make kaniko builds work on GCP. + ] + [runners.machine] + IdleCount = 50 + IdleTime = 3600 + OffPeakPeriods = ["* * * * * sat,sun *"] + OffPeakTimezone = "UTC" + OffPeakIdleCount = 15 + OffPeakIdleTime = 3600 + MaxBuilds = 1 # For security reasons we delete the VM after job has finished so it's not reused. + MachineName = "srm-%s" + MachineDriver = "google" + MachineOptions = [ + "google-project=PROJECT", + "google-disk-size=25", + "google-machine-type=n1-standard-1", + "google-username=core", + "google-tags=gitlab-com,srm", + "google-use-internal-ip", + "google-zone=us-east1-d", + "engine-opt=mtu=1460", # Set MTU for container interface, for more information check https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3214#note_82892928 + "google-machine-image=PROJECT/global/images/IMAGE", + "engine-opt=ipv6", # This will create IPv6 interfaces in the containers. + "engine-opt=fixed-cidr-v6=fc00::/7", + "google-operation-backoff-initial-interval=2" # Custom flag from forked docker-machine, for more information check https://github.com/docker/machine/pull/4600 + ] + [runners.cache] + Type = "gcs" + Shared = true + [runners.cache.gcs] + CredentialsFile = "/path/to/file" + BucketName = "bucket-name" +``` + +### Windows Shared Runners (beta)[](#windows-shared-runners-beta "Permalink") + +Windows Shared Runners 当前处于[beta 中](https://about.gitlab.com/handbook/product/#beta) ,不应用于生产工作负载. + +在测试版期间, [共享运行程序管道配额](../admin_area/settings/continuous_integration.html#shared-runners-pipeline-minutes-quota-starter-only)将以与 Linux Runners 相同的方式应用于组和项目. 如本[相关问题所述](https://gitlab.com/gitlab-org/gitlab/-/issues/30834) ,当 beta 时期结束时,这可能会改变. + +通过在 Google Cloud Platform 上启动虚拟机,GitLab.com 上的 Windows Shared Runners 可以自动自动缩放. 此解决方案使用 GitLab 为[自定义执行](https://docs.gitlab.com/runner/executors/custom.html) [程序](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md)开发的新[自动缩放驱动程序](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md) . Windows 共享运行程序在具有 2 个 vCPU 和 7.5GB RAM 的`n1-standard-2`实例上执行 CI / CD 作业. 您可以在[软件包文档中](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/master/cookbooks/preinstalled-software/README.md)找到可用的 Windows 软件包的完整列表. + +我们希望不断进行迭代,以使 Windows Shared Runners 处于稳定状态并[普遍可用](https://about.gitlab.com/handbook/product/#generally-available-ga) . 您可以在[相关的史诗中](https://gitlab.com/groups/gitlab-org/-/epics/2162)按照我们的工作朝着这个目标迈进. + +#### Configuration[](#configuration "Permalink") + +The full contents of our `config.toml` are: + +**注意:**非公开的设置显示为`X` + +``` +concurrent = X +check_interval = 3 + +[[runners]] + name = "windows-runner" + url = "https://gitlab.com/" + token = "TOKEN" + executor = "custom" + builds_dir = "C:\\GitLab-Runner\\builds" + cache_dir = "C:\\GitLab-Runner\\cache" + shell = "powershell" + [runners.custom] + config_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe" + config_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "config"] + prepare_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe" + prepare_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "prepare"] + run_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe" + run_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "run"] + cleanup_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe" + cleanup_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "cleanup"] +``` + +我们的`autoscaler/config.toml`的完整内容是: + +``` +Provider = "gcp" +Executor = "winrm" +OS = "windows" +LogLevel = "info" +LogFormat = "text" +LogFile = "C:\\GitLab-Runner\\autoscaler\\autoscaler.log" +VMTag = "windows" + +[GCP] + ServiceAccountFile = "PATH" + Project = "some-project-df9323" + Zone = "us-east1-c" + MachineType = "n1-standard-2" + Image = "IMAGE" + DiskSize = 50 + DiskType = "pd-standard" + Subnetwork = "default" + Network = "default" + Tags = ["TAGS"] + Username = "gitlab_runner" + +[WinRM] + MaximumTimeout = 3600 + ExecutionMaxRetries = 0 + +[ProviderCache] + Enabled = true + Directory = "C:\\GitLab-Runner\\autoscaler\\machines" +``` + +#### Example[](#example "Permalink") + +下面是一个简单的`.gitlab-ci.yml`文件,以显示如何开始使用 Windows Shared Runners: + +``` +.shared_windows_runners: + tags: + - shared-windows + - windows + - windows-1809 + +stages: + - build + - test + +before_script: + - Set-Variable -Name "time" -Value (date -Format "%H:%m") + - echo ${time} + - echo "started by ${GITLAB_USER_NAME}" + +build: + extends: + - .shared_windows_runners + stage: build + script: + - echo "running scripts in the build job" + +test: + extends: + - .shared_windows_runners + stage: test + script: + - echo "running scripts in the test job" +``` + +#### Limitations and known issues[](#limitations-and-known-issues "Permalink") + +* [Beta 定义中](https://about.gitlab.com/handbook/product/#beta)提到的所有限制. +* 新 Windows VM 的平均配置时间为 5 分钟. 这意味着在测试期间,您可能会注意到 Windows Shared Runner 机群上的构建开始时间变慢. 在将来的版本中,我们将更新自动缩放器以启用虚拟机的预配置. 这将大大减少在 Windows 机群上配置 VM 所花费的时间. 您可以按照[相关问题进行操作](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/-/issues/32) . +* Windows Shared Runner 舰队可能偶尔不可用进行维护或更新. +* Windows Shared Runner 虚拟机实例不使用 GitLab Docker 执行器. 这意味着您将无法在管道配置中指定[`image`](../../ci/yaml/README.html#image)或[`services`](../../ci/yaml/README.html#services) . +* 对于 Beta 版本,我们在基本 VM 映像中包含了一组软件包. 如果您的 CI 作业需要此列表中未包含的其他软件,那么您将需要在[`before_script`](../../ci/yaml/README.html#before_script-and-after_script)或[`script`](../../ci/yaml/README.html#script)添加安装命令以安装所需的软件. 请注意,每个作业都在新的 VM 实例上运行,因此需要为管道中的每个作业重复安装其他软件包. +* 作业在等待状态中的停留时间可能比 Linux 共享运行器更长. +* 我们有可能引入重大更改,这将需要更新使用 Windows Shared Runner 组件的管道. + +## Sidekiq[](#sidekiq "Permalink") + +GitLab.com 使用参数`--timeout=4 --concurrency=4`和以下环境变量运行[Sidekiq](https://sidekiq.org) : + +| Setting | GitLab.com | Default | +| --- | --- | --- | +| `SIDEKIQ_DAEMON_MEMORY_KILLER` | - | - | +| `SIDEKIQ_MEMORY_KILLER_MAX_RSS` | `2000000` | `2000000` | +| `SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS` | - | - | +| `SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL` | - | `3` | +| `SIDEKIQ_MEMORY_KILLER_GRACE_TIME` | - | `900` | +| `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT` | - | `30` | +| `SIDEKIQ_LOG_ARGUMENTS` | `1` | - | + +**注意:**在 Sidekiq 导入节点和 Sidekiq 导出节点上, `SIDEKIQ_MEMORY_KILLER_MAX_RSS`设置为`16000000` . + +## PostgreSQL[](#postgresql "Permalink") + +GitLab.com being a fairly large installation of GitLab means we have changed various PostgreSQL settings to better suit our needs. For example, we use streaming replication and servers in hot-standby mode to balance queries across different database servers. + +GitLab.com 特定设置(及其默认设置)的列表如下: + +| Setting | GitLab.com | Default | +| --- | --- | --- | +| `archive_command` | `/usr/bin/envdir /etc/wal-e.d/env /opt/wal-e/bin/wal-e wal-push %p` | empty | +| `archive_mode` | on | off | +| `autovacuum_analyze_scale_factor` | 0.01 | 0.01 | +| `autovacuum_max_workers` | 6 | 3 | +| `autovacuum_vacuum_cost_limit` | 1000 | -1 | +| `autovacuum_vacuum_scale_factor` | 0.01 | 0.02 | +| `checkpoint_completion_target` | 0.7 | 0.9 | +| `checkpoint_segments` | 32 | 10 | +| `effective_cache_size` | 338688MB | 基于可用内存量 | +| `hot_standby` | on | off | +| `hot_standby_feedback` | on | off | +| `log_autovacuum_min_duration` | 0 | -1 | +| `log_checkpoints` | on | off | +| `log_line_prefix` | `%t [%p]: [%l-1]` | empty | +| `log_min_duration_statement` | 1000 | -1 | +| `log_temp_files` | 0 | -1 | +| `maintenance_work_mem` | 2048MB | 16 兆字节 | +| `max_replication_slots` | 5 | 0 | +| `max_wal_senders` | 32 | 0 | +| `max_wal_size` | 5GB | 1GB | +| `shared_buffers` | 112896MB | 基于可用内存量 | +| `shared_preload_libraries` | pg_stat_statements | empty | +| `shmall` | 30146560 | 基于服务器的功能 | +| `shmmax` | 123480309760 | 基于服务器的功能 | +| `wal_buffers` | 16MB | -1 | +| `wal_keep_segments` | 512 | 10 | +| `wal_level` | replica | minimal | +| `statement_timeout` | 15s | 60s | +| `idle_in_transaction_session_timeout` | 60s | 60s | + +其中一些设置正在调整过程中. 例如, `shared_buffers`的值很高,因此我们正在考虑对其进行调整. 有关此特定更改的更多信息,请参见[https://gitlab.com/gitlab-com/infrastructure/-/issues/1555](https://gitlab.com/gitlab-com/infrastructure/-/issues/1555) . 可以在[https://gitlab.com/gitlab-com/infrastructure/-/issues?scope=all&utf8=✓&state=opened&label_name[]=database&label_name[]=change](https://gitlab.com/gitlab-com/infrastructure/-/issues?scope=all&utf8=✓&state=opened&label_name[]=database&label_name[]=change)找到最新的建议更改列表. + +## Unicorn[](#unicorn "Permalink") + +GitLab.com 调整了[独角兽杀手级](https://rubygems.org/gems/unicorn-worker-killer)宝石的内存限制. + +基本默认值: + +* `memory_limit_min` = 750MiB +* `memory_limit_max` = 1024MiB + +Web 前端: + +* `memory_limit_min` = 1024MiB +* `memory_limit_max` = 1280MiB + +## GitLab.com-specific rate limits[](#gitlabcom-specific-rate-limits "Permalink") + +**注意:**有关管理员文档,请参阅[速率限制](../../security/rate_limits.html) . + +当 GitLab.com 从单个 IP 地址接收到异常流量时,通常会发生 IP 阻止,系统根据速率限制设置将其视为潜在恶意软件. 在异常流量停止后,IP 地址将根据阻止类型自动释放,如下所述. + +如果您对 GitLab.com 的所有请求均收到`403 Forbidden`错误,请检查是否有任何自动流程可能触发了阻止. 要获得帮助,请与[GitLab 支持人员](https://support.gitlab.com/hc/en-us)联系,以获取详细信息,例如受影响的 IP 地址. + +### HAProxy API throttle[](#haproxy-api-throttle "Permalink") + +对于每个 IP 地址每秒超过 10 个请求的 API 请求,GitLab.com 会以 HTTP 状态代码`429`进行响应. + +所有 API 请求均包含以下示例标头: + +``` +RateLimit-Limit: 600 +RateLimit-Observed: 6 +RateLimit-Remaining: 594 +RateLimit-Reset: 1563325137 +RateLimit-ResetTime: Wed, 17 Jul 2019 00:58:57 GMT +``` + +Source: + +* 在[GitLab.com 的当前 HAProxy 设置中](https://gitlab.com/gitlab-cookbooks/gitlab-haproxy/blob/master/attributes/default.rb)搜索`rate_limit_http_rate_per_minute`和`rate_limit_sessions_per_second` . + +### Rack Attack initializer[](#rack-attack-initializer "Permalink") + +[机架攻击](../../security/rack_attack.html)实施的速率限制的详细信息. + +#### Protected paths throttle[](#protected-paths-throttle "Permalink") + +GitLab.com 以 HTTP 状态代码`429`响应在每个 IP 地址每**分钟**超过 10 个请求的受保护路径上的 POST 请求. + +请参阅下面的源,了解哪些路径受保护. 这包括用户创建,用户确认,用户登录和密码重置. + +此标头包含在对阻止的请求的响应中: + +``` +Retry-After: 60 +``` + +有关更多详细信息,请参见[受保护的路径](../admin_area/settings/protected_paths.html) . + +#### Git and container registry failed authentication ban[](#git-and-container-registry-failed-authentication-ban "Permalink") + +如果在 3 分钟内从一个 IP 地址收到 30 个失败的身份验证请求,则 GitLab.com 会以 HTTP 状态代码`403`响应 1 小时. + +这仅适用于 Git 请求和容器注册表( `/jwt/auth` )请求(组合). + +此限制: + +* 由成功认证的请求重置. 例如,29 个失败的身份验证请求后跟 1 个成功的请求,然后再有 29 个失败的身份验证请求不会触发禁止. +* 不适用于`gitlab-ci-token`认证的 JWT 请求. + +没有提供响应头. + +### Admin Area settings[](#admin-area-settings "Permalink") + +GitLab.com: + +* [将原始端点的速率限制](../../user/admin_area/settings/rate_limits_on_raw_endpoints.html)设置为默认值. +* 没有启用用户和 IP 速率限制设置. + +### Visibility settings[](#visibility-settings "Permalink") + +在 GitLab.com 上,自 GitLab 12.2(2019 年 7 月)起创建的项目,组和代码段[在 GitLab.com 上禁用](https://gitlab.com/gitlab-org/gitlab/-/issues/12388)了[**内部**可见性](../../public_access/public_access.html#internal-projects)设置. + +### SSH maximum number of connections[](#ssh-maximum-number-of-connections "Permalink") + +GitLab.com 通过使用[MaxStartups 设置](http://man.openbsd.org/sshd_config.5#MaxStartups)来定义并发,未经[身份](http://man.openbsd.org/sshd_config.5#MaxStartups)验证的 SSH 连接的最大数量. 如果同时发生的连接数超过了允许的最大连接数,则会将其丢弃,并且用户会收到[`ssh_exchange_identification`错误](../../topics/git/troubleshooting_git.html#ssh_exchange_identification-error) . + +### Import/export[](#importexport "Permalink") + +为了避免滥用,对项目和组的导入,导出和导出下载进行了速率限制. 有关详细信息,请参见[项目导入/导出速率限制](../../user/project/settings/import_export.html#rate-limits)和[组导入/导出速率限制](../../user/group/settings/import_export.html#rate-limits) . + +## GitLab.com Logging[](#gitlabcom-logging "Permalink") + +我们使用[Fluentd](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#fluentd)解析日志. Fluentd 将我们的日志发送到 Stackdriver [Logging](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#stackdriver)和[Cloud Pub / Sub](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#cloud-pubsub) . Stackdriver 用于将日志长期存储在 Google Cold Storage(GCS)中. Cloud Pub / Sub 用于使用[pubsubbeat](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#pubsubbeat-vms)将日志转发到[Elastic 集群](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#elastic) . + +您可以在我们的运行手册中查看更多信息,例如: + +* A [detailed list of what we’re logging](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging#what-are-we-logging) +* Our [current log retention policies](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging#retention) +* A [diagram of our logging infrastructure](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging#logging-infrastructure-overview) + +## GitLab.com at scale[](#gitlabcom-at-scale "Permalink") + +In addition to the GitLab Enterprise Edition Omnibus install, GitLab.com uses the following applications and settings to achieve scale. All settings are publicly available at [chef cookbooks](https://gitlab.com/gitlab-cookbooks). + +### Elastic Cluster[](#elastic-cluster "Permalink") + +我们使用 Elasticsearch 和 Kibana 作为我们的监控解决方案的一部分: + +* [`gitlab-cookbooks` / `gitlab-elk` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab-elk) +* [`gitlab-cookbooks` / `gitlab_elasticsearch` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab_elasticsearch) + +### Fluentd[](#fluentd "Permalink") + +我们使用 Fluentd 统一我们的 GitLab 日志: + +* [`gitlab-cookbooks` / `gitlab_fluentd` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab_fluentd) + +### Prometheus[](#prometheus "Permalink") + +Prometheus 完成了我们的监视堆栈: + +* [`gitlab-cookbooks` / `gitlab-prometheus` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab-prometheus) + +### Grafana[](#grafana "Permalink") + +为了可视化监视数据: + +* [`gitlab-cookbooks` / `gitlab-grafana` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab-grafana) + +### Sentry[](#sentry "Permalink") + +开源错误跟踪: + +* [`gitlab-cookbooks` / `gitlab-sentry` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab-sentry) + +### Consul[](#consul "Permalink") + +服务发现: + +* [`gitlab-cookbooks` / `gitlab_consul` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab_consul) + +### HAProxy[](#haproxy "Permalink") + +高性能 TCP / HTTP 负载均衡器: + +* [`gitlab-cookbooks` / `gitlab-haproxy` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab-haproxy) \ No newline at end of file diff --git a/_book/docs/406.md b/_book/docs/406.md new file mode 100644 index 0000000000000000000000000000000000000000..3fabd96e316d92bf5de307b7ced4895231e8ec26 --- /dev/null +++ b/_book/docs/406.md @@ -0,0 +1,338 @@ +# Infrastructure as code with Terraform and GitLab + +> 原文:[https://docs.gitlab.com/ee/user/infrastructure/index.html](https://docs.gitlab.com/ee/user/infrastructure/index.html) + +* [Motivation](#motivation) +* [GitLab managed Terraform State](#gitlab-managed-terraform-state) +* [Permissions for using Terraform](#permissions-for-using-terraform) +* [Get started using local development](#get-started-using-local-development) +* [Get started using GitLab CI](#get-started-using-gitlab-ci) +* [Configure the backend](#configure-the-backend) +* [Example project](#example-project) +* [Output Terraform Plan information into a merge request](#output-terraform-plan-information-into-a-merge-request) + * [Example `.gitlab-ci.yaml` file](#example-gitlab-ciyaml-file) + * [Multiple Terraform Plan reports](#multiple-terraform-plan-reports) + +# Infrastructure as code with Terraform and GitLab[](#infrastructure-as-code-with-terraform-and-gitlab "Permalink") + +## Motivation[](#motivation "Permalink") + +GitLab 中的 Terraform 集成功能使您的 GitOps /基础设施即代码(IaC)工作流能够与 GitLab 的身份验证和授权结合在一起. 这些功能着重于降低团队采用 Terraform,在 GitLab 中有效协作以及支持 Terraform 最佳实践的准入门槛. + +## GitLab managed Terraform State[](#gitlab-managed-terraform-state "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2673) . + +[Terraform 远程后端](https://www.terraform.io/docs/backends/index.html)使您可以将状态文件存储在远程共享存储中. GitLab 使用[Terraform HTTP 后端](https://www.terraform.io/docs/backends/types/http.html)将状态文件安全地存储在本地存储(默认)或[您选择的远程存储中](../../administration/terraform_state.html) . + +由 GitLab 管理的 Terraform 状态后端可以轻松安全地存储 Terraform 状态,并使您免于设置其他远程资源(如 Amazon S3 或 Google Cloud Storage). 其功能包括: + +* 在传输和静止时都支持状态文件的加密. +* 锁定和解锁状态. +* 远程 Terraform 计划并执行. + +要开始使用 GitLab 管理的 Terraform State,有两种不同的选择: + +* [Use a local machine](#get-started-using-local-development). +* [Use GitLab CI](#get-started-using-gitlab-ci). + +## Permissions for using Terraform[](#permissions-for-using-terraform "Permalink") + +在 GitLab 版本 13.1 中,需要[维护者访问权限](../permissions.html)才能使用 GitLab 管理的 Terraform 状态后端. 在 GitLab 版本 13.2 和更高版本中,需要[维护者访问权限](../permissions.html)才能锁定,解锁和写入状态(使用`terraform apply` ),而需要[开发人员访问权限](../permissions.html)来读取状态(使用`terraform plan -lock=false` ). + +## Get started using local development[](#get-started-using-local-development "Permalink") + +如果您计划仅运行`terraform plan`并从本地计算机上执行`terraform plan` `terraform apply`命令,这是一种入门的简单方法: + +1. 在您的 GitLab 实例上创建项目. +2. 导航 **设置>常规,**并记下您的**项目名称**和**项目 ID** . +3. Define the Terraform backend in your Terraform project to be: + + ``` + terraform { + backend "http" { + } + } + ``` + +4. 使用`api`范围创建一个[个人访问令牌](../profile/personal_access_tokens.html) . + +5. 在本地计算机上,运行`terraform init` ,传入以下选项,并用相关值替换`` , `` , ``和`` . 此命令将初始化 Terraform 状态,并将该状态存储在 GitLab 项目中. 这个例子使用`gitlab.com` : + + ``` + terraform init \ + -backend-config="address=https://gitlab.com/api/v4/projects//terraform/state/" \ + -backend-config="lock_address=https://gitlab.com/api/v4/projects//terraform/state//lock" \ + -backend-config="unlock_address=https://gitlab.com/api/v4/projects//terraform/state//lock" \ + -backend-config="username=" \ + -backend-config="password=" \ + -backend-config="lock_method=POST" \ + -backend-config="unlock_method=DELETE" \ + -backend-config="retry_wait_min=5" + ``` + +Next, [configure the backend](#configure-the-backend). + +## Get started using GitLab CI[](#get-started-using-gitlab-ci "Permalink") + +如果您不想开始本地开发,也可以使用 GitLab CI 来运行`terraform plan`和`terraform apply`命令. + +Next, [configure the backend](#configure-the-backend). + +## Configure the backend[](#configure-the-backend "Permalink") + +执行`terraform init`命令后,必须配置 Terraform 后端和 CI YAML 文件: + +1. 在 Terraform 项目中,通过在`.tf`文件(例如`backend.tf` )中添加以下代码块来定义远程后端,以定义[HTTP](https://www.terraform.io/docs/backends/types/http.html)后端: + + ``` + terraform { + backend "http" { + } + } + ``` + +2. 在项目存储库的根目录中,配置`.gitlab-ci.yaml`文件. 本示例使用一个包含`gitlab-terraform`帮助器的预构建图像. 有关受支持的 Terraform 版本,请参见[GitLab Terraform Images 项目](https://gitlab.com/gitlab-org/terraform-images) . + + ``` + image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest + ``` + +3. 在`.gitlab-ci.yaml`文件中,定义一些环境变量以简化开发. 在此示例中, `TF_ROOT`是必须执行 Terraform 命令的目录, `TF_ADDRESS`是该管道在其上运行的 GitLab 实例上的状态的 URL,并且`TF_ADDRESS`的最后路径段是 Terraform 状态的名称. 项目可能具有多个状态,并且该名称是任意的,因此在此示例中,我们将其设置为项目的名称,并确保使用基于缓存的缓存键在管道中的作业之间缓存`.terraform`目录.州名: + + ``` + variables: + TF_ROOT: ${CI_PROJECT_DIR}/environments/cloudflare/production + TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_PROJECT_NAME} + + cache: + key: ${CI_PROJECT_NAME} + paths: + - ${TF_ROOT}/.terraform + ``` + +4. 在`before_script` ,更改为`TF_ROOT` : + + ``` + before_script: + - cd ${TF_ROOT} + + stages: + - prepare + - validate + - build + - deploy + + init: + stage: prepare + script: + - gitlab-terraform init + + validate: + stage: validate + script: + - gitlab-terraform validate + + plan: + stage: build + script: + - gitlab-terraform plan + - gitlab-terraform plan-json + artifacts: + name: plan + paths: + - ${TF_ROOT}/plan.cache + reports: + terraform: ${TF_ROOT}/plan.json + + apply: + stage: deploy + environment: + name: production + script: + - gitlab-terraform apply + dependencies: + - plan + when: manual + only: + - master + ``` + +5. 将项目推送到 GitLab,这将触发 CI 作业管道. 该管道运行`gitlab-terraform init` , `gitlab-terraform validate`和`gitlab-terraform plan`命令. + +以上`terraform`命令的输出应在作业日志中可见. + +## Example project[](#example-project "Permalink") + +请参阅使用 GitLab 和 Terraform 在自定义 VPC 中部署基本 AWS EC2 的[参考项目](https://gitlab.com/nicholasklick/gitlab-terraform-aws) . + +## Output Terraform Plan information into a merge request[](#output-terraform-plan-information-into-a-merge-request "Permalink") + +使用[GitLab Terraform Report 工件](../../ci/pipelines/job_artifacts.html#artifactsreportsterraform) ,您可以将`terraform plan`运行中的详细信息直接暴露到合并请求小部件中,使您能够查看有关 Terraform 将创建,修改或销毁的资源的统计信息. + +让我们探索如何配置 GitLab Terraform Report 工件. 您可以使用包含上述`gitlab-terraform`帮助器的预构建映像,其中`gitlab-terraform plan-json`输出所需的工件,或者您可以按以下方式手动进行配置: + +1. 为简单起见,让我们定义一些可重用的变量,以允许我们多次引用这些文件: + + ``` + variables: + PLAN: plan.cache + PLAN_JSON: plan.json + ``` + +2. 安装`jq` ,这是一种[轻巧灵活的命令行 JSON 处理器](https://stedolan.github.io/jq/) . +3. 为特定的`jq`命令创建一个别名,该别名解析出我们要从`terraform plan`输出中提取的信息: + + ``` + before_script: + - apk --no-cache add jq + - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'" + ``` + + **注意:**在使用 Bash 的发行版(例如,Ubuntu)中, `alias`语句不会在非交互模式下扩展. 如果您的管道失败并显示错误`convert_report: command not found` ,则可以通过在脚本中添加`shopt`命令来明确激活别名扩展: + + ``` + before_script: + - shopt -s expand_aliases + - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'" + ``` + +4. 定义运行`terraform plan`和`terraform show`的`script` . 这些命令通过管道`PLAN_JSON`输出并将相关位转换为存储变量`PLAN_JSON` . 此 JSON 用于创建[GitLab Terraform Report 工件](../../ci/pipelines/job_artifacts.html#artifactsreportsterraform) . Terraform 报告获取 Terraform `tfplan.json`文件. 收集的 Terraform 计划报告作为工件上传到 GitLab,并在合并请求中显示. + + ``` + plan: + stage: build + script: + - terraform plan -out=$PLAN + - terraform show --json $PLAN | convert_report > $PLAN_JSON + artifacts: + reports: + terraform: $PLAN_JSON + ``` + + 有关使用预构建图像的完整示例,请参见[Example `.gitlab-ci.yaml`文件](#example-gitlab-ciyaml-file) . + + 有关显示多个报告的示例,请参见[`.gitlab-ci.yaml`多个报告文件](#multiple-terraform-plan-reports) . + +5. 运行管道会在合并请求中显示小部件,如下所示: + + [![Merge Request Terraform widget](img/f3550bb5a4a6074ef46ae27848adc308.png)](img/terraform_plan_widget_v13_2.png) + +6. Clicking the **查看完整日志** button in the widget takes you directly to the plan output present in the pipeline logs: + + [![Terraform plan logs](img/0a8c15f1fa2c2e0a210d9baae9fff372.png)](img/terraform_plan_log_v13_0.png) + +### Example `.gitlab-ci.yaml` file[](#example-gitlab-ciyaml-file "Permalink") + +``` +image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest + +variables: + TF_ROOT: ${CI_PROJECT_DIR}/environments/cloudflare/production + TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_PROJECT_NAME} + +cache: + key: ${CI_PROJECT_NAME} + paths: + - ${TF_ROOT}/.terraform + +before_script: + - cd ${TF_ROOT} + +stages: + - prepare + - validate + - build + - deploy + +init: + stage: prepare + script: + - gitlab-terraform init + +validate: + stage: validate + script: + - gitlab-terraform validate + +plan: + stage: build + script: + - gitlab-terraform plan + - gitlab-terraform plan-json + artifacts: + name: plan + paths: + - ${TF_ROOT}/plan.cache + reports: + terraform: ${TF_ROOT}/plan.json + +apply: + stage: deploy + environment: + name: production + script: + - gitlab-terraform apply + dependencies: + - plan + when: manual + only: + - master +``` + +### Multiple Terraform Plan reports[](#multiple-terraform-plan-reports "Permalink") + +从 13.2 开始,您可以在"合并请求"页面上显示多个报告. 报告还将显示`artifact: name:` 有关建议的设置,请参见下面的示例. + +``` +image: + name: registry.gitlab.com/gitlab-org/gitlab-build-images:terraform + entrypoint: + - '/usr/bin/env' + - 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' + +cache: + paths: + - .terraform + +stages: + - build + +.terraform-plan-generation: + stage: build + variables: + PLAN: plan.tfplan + JSON_PLAN_FILE: tfplan.json + before_script: + - cd ${TERRAFORM_DIRECTORY} + - terraform --version + - terraform init + - apk --no-cache add jq + script: + - terraform validate + - terraform plan -out=${PLAN} + - terraform show --json ${PLAN} | jq -r '([.resource_changes[]?.change.actions?]|flatten)|{"create":(map(select(.=="create"))|length),"update":(map(select(.=="update"))|length),"delete":(map(select(.=="delete"))|length)}' > ${JSON_PLAN_FILE} + artifacts: + reports: + terraform: ${TERRAFORM_DIRECTORY}/${JSON_PLAN_FILE} + +review_plan: + extends: .terraform-plan-generation + variables: + TERRAFORM_DIRECTORY: "review/" + # Review will not include an artifact name + +staging_plan: + extends: .terraform-plan-generation + variables: + TERRAFORM_DIRECTORY: "staging/" + artifacts: + name: Staging + +production_plan: + extends: .terraform-plan-generation + variables: + TERRAFORM_DIRECTORY: "production/" + artifacts: + name: Production +``` \ No newline at end of file diff --git a/_book/docs/407.md b/_book/docs/407.md new file mode 100644 index 0000000000000000000000000000000000000000..02c759136d79a0fb5acfa2c0f7a68dea8eb5ce4d --- /dev/null +++ b/_book/docs/407.md @@ -0,0 +1,147 @@ +# GitLab keyboard shortcuts + +> 原文:[https://docs.gitlab.com/ee/user/shortcuts.html](https://docs.gitlab.com/ee/user/shortcuts.html) + +* [Global Shortcuts](#global-shortcuts) +* [Project](#project) + * [Issues and Merge Requests](#issues-and-merge-requests) + * [Project Files](#project-files) + * [Web IDE](#web-ide) + * [Repository Graph](#repository-graph) + * [Wiki pages](#wiki-pages) + * [Filtered Search](#filtered-search) +* [Epics](#epics-ultimate) + +# GitLab keyboard shortcuts[](#gitlab-keyboard-shortcuts "Permalink") + +GitLab 有许多有用的键盘快捷键,使您可以更轻松地访问不同的功能. 您可以通过按`?`在 GitLab 本身中看到模式列表键盘快捷键`.` ,或单击右上角"帮助"菜单中的" **键盘快捷键"** . 在[GitLab 12.8 和更高版本中](https://gitlab.com/gitlab-org/gitlab/-/issues/22113) ,可以使用此模式窗口中的" **启用** / **禁用"**切换来禁用键盘快捷键. + +[全局快捷方式](#global-shortcuts)可在 GitLab 的任何区域使用,但是您必须在特定页面中才能使用其他快捷方式,如以下各节所述. + +## Global Shortcuts[](#global-shortcuts "Permalink") + +在 GitLab 的大多数区域中都可以使用这些快捷方式 + +| 键盘快捷键 | Description | +| --- | --- | +| `?` | 显示/隐藏快捷方式参考表. | +| `Shift` + `p` | 转到您的项目页面. | +| `Shift` + `g` | 转到您的网上论坛页面. | +| `Shift` + `a` | 转到"活动"页面. | +| `Shift` + `l` | 转到您的里程碑页面. | +| `Shift` + `s` | 转到您的代码段页面. | +| `s` | 将光标放在问题/合并请求搜索中. | +| `Shift` + `i` | 转到您的问题页面. | +| `Shift` + `m` | 转到"合并请求"页面. | +| `Shift` + `t` | 转到待办事项列表页面. | +| `p` + `b` | 显示/隐藏性能栏. | + +此外,在文本字段中编辑文本时,可以使用以下快捷方式,例如,注释,回复,问题描述和合并请求描述: + +| 键盘快捷键 | Description | +| --- | --- | +| `↑` | 编辑您的最后评论. 您必须在线程下方的空白文本字段中,并且该线程中必须已经至少有一个注释. | +| `⌘` (Mac)/ `Ctrl` + `Shift` + `p` | 在顶部具有" **编写"**和" **预览"**选项卡的文本字段中编辑文本时,切换 Markdown 预览. | + +## Project[](#project "Permalink") + +这些快捷方式可从项目中的任何页面获得. 您必须相对快速地键入它们才能工作,并且它们会将您带到项目中的另一个页面. + +| 键盘快捷键 | Description | +| --- | --- | +| `g` + `p` | 转到项目主页(" **项目">"详细信息"** ). | +| `g` + `v` | 转到项目活动提要(" **项目">"活动"** ). | +| `g` + `r` | 转到项目发布列表(" **项目">"发布"** ). | +| `g` + `f` | 转到[项目文件](#project-files)列表(" **存储库">"文件"** ). | +| `t` | 转到项目文件搜索页面. (" **存储库">"文件"** ,单击" **查找文件"** ). | +| `g` + `c` | 转到项目提交列表( **存储库>提交** ). | +| `g` + `n` | 转到[存储库图](#repository-graph)页面( **Repository> Graph** ). | +| `g` + `d` | Go to repository charts (**分析>存储库分析**). | +| `g` + `i` | 转到项目问题列表( **问题>列表** ). | +| `i` | 转到"新问题"页面(" **问题"** ,单击" **新问题"** ). | +| `g` + `b` | 转到项目问题委员会列表( **问题>委员会** ). | +| `g` + `m` | 转到项目合并请求列表( **合并请求** ). | +| `g` + `j` | 转到 CI / CD 作业列表( **CI / CD>作业** ). | +| `g` + `l` | 转到项目指标(" **操作">"指标"** ). | +| `g` + `e` | 转到项目环境(" **操作">"环境"** ). | +| `g` + `k` | 转到项目 Kubernetes 集群集成页面( **操作> Kubernetes** ). 请注意,您必须至少具有[`maintainer`权限](permissions.html)才能访问此页面. | +| `g` + `s` | 转到项目片段列表( **片段** ). | +| `g` + `w` | 转到项目 Wiki( **Wiki** )(如果已启用). | + +### Issues and Merge Requests[](#issues-and-merge-requests "Permalink") + +这些快捷方式在查看问题和合并请求时可用. + +| 键盘快捷键 | Description | +| --- | --- | +| `e` | 编辑说明. | +| `a` | 更改受让人. | +| `m` | 更改里程碑. | +| `l` | 更改标签. | +| `r` | 开始写评论. 如果选择了任何文本,它将在注释中引用. 不能用于在线程内回复. | +| `n` | 移至下一个未解决的讨论(仅合并请求). | +| `p` | 移至上一个未解决的讨论(仅合并请求). | +| `]` or `j` | 移至下一个文件(仅合并请求). | +| `[` or `k` | 移至上一个文件(仅合并请求). | +| `b` | 复制源分支名称(仅合并请求). | + +### Project Files[](#project-files "Permalink") + +这些快捷方式在浏览项目中的文件时可用(导航至**Repository** > **Files** ): + +| 键盘快捷键 | Description | +| --- | --- | +| `↑` | 向上移动选择. | +| `↓` | 向下移动选择. | +| `enter` | 打开选择. | +| `esc` | 返回文件列表屏幕(仅在搜索文件时," **存储库">"文件",**然后单击" **查找文件"** ). | +| `y` | 转到文件永久链接(仅在查看文件时). | + +### Web IDE[](#web-ide "Permalink") + +使用[Web IDE](project/web_ide/index.html)编辑文件时,可以使用以下快捷方式: + +| 键盘快捷键 | Description | +| --- | --- | +| `⌘` (Mac)/ `Ctrl` + `p` | 搜索,然后打开另一个文件进行编辑. | +| `⌘` (Mac)/ `Ctrl` + `Enter` | 提交(在编辑提交消息时). | + +### Repository Graph[](#repository-graph "Permalink") + +这些快捷方式在查看项目[存储库图形](project/repository/index.html#repository-graph)页面时可用(导航至**Repository> Graph** ): + +| 键盘快捷键 | Description | +| --- | --- | +| `←` or `h` | 向左滚动. | +| `→` or `l` | 向右滚动. | +| `↑` or `k` | 向上滚动. | +| `↓` or `j` | 向下滚动. | +| `Shift` + `↑` or `Shift` + `k` | 滚动到顶部. | +| `Shift` + `↓` or `Shift` + `j` | 滚动到底部. | + +### Wiki pages[](#wiki-pages "Permalink") + +查看[维基页面](project/wiki/index.html)时,可以使用此快捷方式: + +| 键盘快捷键 | Description | +| --- | --- | +| `e` | 编辑 Wiki 页面. | + +### Filtered Search[](#filtered-search "Permalink") + +这些快捷方式在使用[过滤的搜索输入](search/index.html)时可用: + +| 键盘快捷键 | Description | +| --- | --- | +| `⌘` (Mac)+ `⌫` | 清除整个搜索过滤器. | +| `⌥` (Mac)/ `Ctrl` + `⌫` | 一次清除一个令牌. | + +## Epics[](#epics-ultimate "Permalink") + +这些快捷方式在查看[Epics](group/epics/index.html)时可用: + +| 键盘快捷键 | Description | +| --- | --- | +| `r` | 开始写评论. 如果选择了任何文本,它将在注释中引用. 不能用于在线程内回复. | +| `e` | 编辑说明. | +| `l` | 更改标签. | \ No newline at end of file diff --git a/_book/docs/408.md b/_book/docs/408.md new file mode 100644 index 0000000000000000000000000000000000000000..671115e21a47f70b81b16b2da8f0689bffa63b88 --- /dev/null +++ b/_book/docs/408.md @@ -0,0 +1,1277 @@ +# GitLab Markdown + +> 原文:[https://docs.gitlab.com/ee/user/markdown.html](https://docs.gitlab.com/ee/user/markdown.html) + +* [GitLab Flavored Markdown (GFM)](#gitlab-flavored-markdown-gfm) + * [Transition from Redcarpet to CommonMark](#transition-from-redcarpet-to-commonmark) + * [GFM extends standard Markdown](#gfm-extends-standard-markdown) +* [New GFM Markdown extensions](#new-gfm-markdown-extensions) + * [Colors](#colors) + * [Diagrams and flowcharts](#diagrams-and-flowcharts) + * [Mermaid](#mermaid) + * [PlantUML](#plantuml) + * [Emoji](#emoji) + * [Front matter](#front-matter) + * [Inline diff](#inline-diff) + * [Math](#math) + * [Special GitLab references](#special-gitlab-references) + * [Task lists](#task-lists) + * [Table of contents](#table-of-contents) + * [Wiki-specific Markdown](#wiki-specific-markdown) + * [Wiki - direct page link](#wiki---direct-page-link) + * [Wiki - direct file link](#wiki---direct-file-link) + * [Wiki - hierarchical link](#wiki---hierarchical-link) + * [Wiki - root link](#wiki---root-link) + * [Embedding metrics in GitLab Flavored Markdown](#embedding-metrics-in-gitlab-flavored-markdown) +* [Standard Markdown and extensions in GitLab](#standard-markdown-and-extensions-in-gitlab) + * [Blockquotes](#blockquotes) + * [Multiline blockquote](#multiline-blockquote) + * [Code spans and blocks](#code-spans-and-blocks) + * [Colored code and syntax highlighting](#colored-code-and-syntax-highlighting) + * [Emphasis](#emphasis) + * [Multiple underscores in words and mid-word emphasis](#multiple-underscores-in-words-and-mid-word-emphasis) + * [Footnotes](#footnotes) + * [Headers](#headers) + * [Header IDs and links](#header-ids-and-links) + * [Horizontal Rule](#horizontal-rule) + * [Images](#images) + * [Videos](#videos) + * [Audio](#audio) + * [Inline HTML](#inline-html) + * [Details and summary](#details-and-summary) + * [Line breaks](#line-breaks) + * [Newlines](#newlines) + * [Links](#links) + * [URL auto-linking](#url-auto-linking) + * [Lists](#lists) + * [Superscripts / Subscripts](#superscripts--subscripts) + * [Tables](#tables) + * [Copy from spreadsheet and paste in Markdown](#copy-from-spreadsheet-and-paste-in-markdown) +* [References](#references) + +# GitLab Markdown[](#gitlab-markdown "Permalink") + +该 Markdown 指南**仅对 GitLab 的内部 Markdown 渲染系统的条目和文件有效** . 它是**无效**的[GitLab 文档,网站](https://s0docs0gitlab0com.icopy.site)或[GitLab 的主要网站](https://about.gitlab.com) ,因为它们都使用[Kramdown](https://kramdown.gettalong.org)作为他们的降价引擎. 文档网站使用扩展的 Kramdown 宝石[GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown) . 有关完整的 Kramdown 参考,请查阅《 [GitLab Kramdown 指南》](https://about.gitlab.com/handbook/markdown-guide/) . + +**注意:**我们建议您查看[GitLab 本身提供的](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md)此文档. + +## GitLab Flavored Markdown (GFM)[](#gitlab-flavored-markdown-gfm "Permalink") + +GitLab 使用" GitLab 风味降价"(GFM). 它以几种方式扩展了[CommonMark 规范](https://spec.commonmark.org/current/) (基于标准 Markdown),以添加其他有用的功能. 它的灵感来自[GitHub Flavored Markdown](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax) . + +您可以在以下区域使用 GFM: + +* Comments +* Issues +* 合并要求 +* Milestones +* 代码段(代码段必须以`.md`扩展名命名) +* 维基页面 +* 仓库中的 Markdown 文档 +* Epics + +您还可以在 GitLab 中使用其他 RTF 文件. 您可能必须安装依赖项才能这样做. 请参阅[`gitlab-markup` gem 项目](https://gitlab.com/gitlab-org/gitlab-markup)以获取更多信息. + +### Transition from Redcarpet to CommonMark[](#transition-from-redcarpet-to-commonmark "Permalink") + +从 11.1 开始,GitLab 使用[CommonMark Ruby 库](https://github.com/gjtorikian/commonmarker)对[Markit](https://github.com/gjtorikian/commonmarker)处理 GitLab 系统中的所有新问题,合并请求,注释和其他 Markdown 内容. 从 11.3 开始,存储库中的 Wiki 页面和 Markdown 文件( `*.md` )也将通过 CommonMark 处理. 从 11.8 开始, [Redcarpet Ruby 库](https://github.com/vmg/redcarpet)已被删除,所有问题和注释,包括 11.1 之前的问题和注释,现在都可以使用[CommonMark Ruby Library 处理](https://github.com/gjtorikian/commonmarker) . + +该文档网站的[Markdown 引擎](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/108)已于 2018 年 10 月[从 Redcarpet 迁移到 Kramdown](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/108) . + +您的存储库中可能存在较旧的问题,合并请求或 Markdown 文档,这些文档是使用 GitLab 的 RedCarpet 版本的 Markdown 的细微差别编写的. 由于 CommonMark 使用了稍微严格的语法,因此自我们过渡到 CommonMark 以来,这些文档现在看起来可能会有所不同. + +通常很容易修复. 例如,带嵌套列表的编号列表可能会错误显示: + +``` +1. Chocolate + - dark + - milk +``` + +只需在每个嵌套项目中添加一个空格即可使`-`与顶部列表项的第一个字符对齐(本例中为`C` ): + +``` +1. Chocolate + - dark + - milk +``` + +1. Chocolate + * dark + * milk + +**注意:**我们将在本文档中标记 Redcarpet 和 CommonMark Markdown 之间的任何重大差异. + +如果您有大量的 Markdown 文件,确定它们是否正确显示可能很繁琐. 您可以使用[diff_redcarpet_cmark](https://gitlab.com/digitalmoksha/diff_redcarpet_cmark)工具(不是官方支持的产品)来生成文件列表以及 RedCarpet 和 CommonMark 呈现文件的方式之间的差异. 它可以指示是否需要更改任何内容-通常不需要更改. + +### GFM extends standard Markdown[](#gfm-extends-standard-markdown "Permalink") + +GitLab 充分利用了标准(CommonMark)格式,但还包括对 GitLab 用户有用的附加功能. + +它利用了[Markdown](#new-GFM-markdown-extensions)的[新功能](#new-GFM-markdown-extensions) ,这些[功能](#new-GFM-markdown-extensions)是标准 Markdown 所没有的: + +* [Color “chips” written in HEX, RGB or HSL](#colors) +* [Diagrams and flowcharts](#diagrams-and-flowcharts) +* [Emoji](#emoji) +* [Front matter](#front-matter) +* [Inline diffs](#inline-diff) +* [Math equations and symbols written in LaTeX](#math) +* [Special GitLab references](#special-gitlab-references) +* [Task Lists](#task-lists) +* [Table of Contents](#table-of-contents) +* [Wiki specific Markdown](#wiki-specific-markdown) + +它还具有[扩展的 Markdown 功能](#standard-markdown-and-extensions-in-gitlab) ,而无需更改标准 Markdown 的使用方式: + +| 标准减价 | 在 GitLab 中扩展 Markdown | +| --- | --- | +| [blockquotes](#blockquotes) | [multi-line blockquotes](#multiline-blockquote) | +| [code blocks](#code-spans-and-blocks) | [colored code and syntax highlighting](#colored-code-and-syntax-highlighting) | +| [emphasis](#emphasis) | [multiple underscores in words](#multiple-underscores-in-words-and-mid-word-emphasis) | +| [headers](#headers) | [linkable Header IDs](#header-ids-and-links) | +| [images](#images) | [embedded videos](#videos) and [audio](#audio) | +| [line breaks](#line-breaks) | [more line break control](#newlines) | +| [links](#links) | [automatically linking URLs](#url-auto-linking) | + +## New GFM Markdown extensions[](#new-gfm-markdown-extensions "Permalink") + +### Colors[](#colors "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#colors) . + +可以使用颜色指示器呈现以 HEX,RGB 或 HSL 格式书写的颜色. + +支持的格式(不支持命名的颜色): + +* HEX: ``#RGB[A]`` or ``#RRGGBB[AA]`` +* RGB: ``RGB[A](R, G, B[, A])`` +* HSL: ``HSL[A](H, S, L[, A])`` + +反引号内的颜色后面将带有颜色"碎片": + +``` +- `#F00` +- `#F00A` +- `#FF0000` +- `#FF0000AA` +- `RGB(0,255,0)` +- `RGB(0%,100%,0%)` +- `RGBA(0,255,0,0.3)` +- `HSL(540,70%,50%)` +- `HSLA(540,70%,50%,0.3)` +``` + +* `#F00` +* `#F00A` +* `#FF0000` +* `#FF0000AA` +* `RGB(0,255,0)` +* `RGB(0%,100%,0%)` +* `RGBA(0,255,0,0.3)` +* `HSL(540,70%,50%)` +* `HSLA(540,70%,50%,0.3)` + +### Diagrams and flowcharts[](#diagrams-and-flowcharts "Permalink") + +可以使用[Mermaid](https://s0mermaidjs0github0io.icopy.site/)或[PlantUML](https://plantuml.com)从 GitLab 中的文本生成图表和流程图. + +#### Mermaid[](#mermaid "Permalink") + +在 GitLab 10.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15107) . + +访问[官方页面](https://s0mermaidjs0github0io.icopy.site/)以获取更多详细信息. 如果您不熟悉使用 Mermaid,或者需要帮助来确定 Mermaid 代码中的问题,则[Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/)是一个有用的工具,可用于在 Mermaid 图中创建和解决问题. + +为了生成图表或流程图,您应该在`mermaid`块内编写文本: + +``` +```mermaid graph TD; + A-->B; + A-->C; + B-->D; + C-->D; +``` +``` + +图 TD; A-> B; A-> C; B-> D; C-> D; + +子图也可以包括: + +``` +```mermaid graph TB + + SubGraph1 --> SubGraph1Flow + subgraph "SubGraph 1 Flow" + SubGraph1Flow(SubNode 1) + SubGraph1Flow -- Choice1 --> DoChoice1 + SubGraph1Flow -- Choice2 --> DoChoice2 + end + + subgraph "Main Graph" + Node1[Node 1] --> Node2[Node 2] + Node2 --> SubGraph1[Jump to SubGraph1] + SubGraph1 --> FinalThing[Final Thing] +end +``` +``` + +图 TB SubGraph1-> SubGraph1Flow 子图" SubGraph 1 Flow" SubGraph1Flow(SubNode 1)SubGraph1Flow-Choice1-> DoChoice1 SubGraph1Flow-Choice2-> DoChoice2 结束子图" Main Graph" Node1 [Node 1]-> Node2 [ Node 2] Node2-> SubGraph1 [Jump to SubGraph1] SubGraph1-> FinalThing [Final Thing]结束 + +#### PlantUML[](#plantuml "Permalink") + +为了使 PlantUML 在 GitLab 中可用,GitLab 管理员需要首先启用它. 在[PlantUML&GitLab 中](../administration/integration/plantuml.html)了解更多[信息](../administration/integration/plantuml.html) . + +### Emoji[](#emoji "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#emoji) . + +``` +Sometimes you want to :monkey: around a bit and add some :star2: to your :speech_balloon:. Well we have a gift for you: + +:zap: You can use emoji anywhere GFM is supported. :v: + +You can use it to point out a :bug: or warn about :speak_no_evil: patches. And if someone improves your really :snail: code, send them some :birthday:. People will :heart: you for that. + +If you're new to this, don't be :fearful:. You can easily join the emoji :family:. All you need to do is to look up one of the supported codes. + +Consult the [Emoji Cheat Sheet](https://www.emojicopy.com) for a list of all supported emoji codes. :thumbsup: +``` + +有时候你想 ![](img/a5023ba03c96276e989dc4dbff1ca8dd.png) 大约添加一些 ![](img/bb7ff3b17ad66e05a64ee12def63524b.png) 给你 ![](img/49d46d08d1ca6c3cd3d0b0ef98472512.png) . 好吧,我们有礼物送给您: + +![](img/13b2b9b44dbf46de0243edc068ecab42.png)您可以在支持 GFM 的任何地方使用表情符号. ![](img/cff0e046ac8eca2d9fde8f13a3365d66.png) + +您可以使用它指出一个 ![](img/7710cb575c3aefd0769c3f6aadb6e879.png) 或警告 ![](img/773702223af81c9872bccd88d63ad3a5.png) 补丁. 如果有人真的改善了你 ![](img/17e23e08ff33b405e039adae1f73cb83.png) 代码,给他们发送一些 ![](img/fd7124974fcca5463d2ce7385bfb700e.png) . 人们会 ![](img/bab86c57be5bd24c1329a7de56df456a.png) 为此. + +如果您是新手,请不要 ![](img/e41f9ac1eea140d12bc83ea9312e71d0.png) . 您可以轻松加入表情符号 ![](img/d5171d012a8ff616032035f890d8dbd5.png) . 您需要做的只是查找受支持的代码之一. + +有关所有受支持的表情符号代码的列表,请查阅[表情符号备忘单](https://www.webfx.com/tools/emoji-cheat-sheet/) . ![](img/d0b9fcc8669d772a04d7d72ccb5a82cc.png) + +> **注意:**以上表情符号示例在本文档中使用了硬编码图像. 在 GitLab 中呈现时,表情符号可能会出现不同,具体取决于所使用的操作系统和浏览器. + +大多数 emoji 表情在 macOS,Windows,iOS,Android 上均受本机支持,并且将退回到不支持图像的基于图像的表情上. + +**注意:**在 Linux 上,您可以下载[Noto Color Emoji](https://www.google.com/get/noto/help/emoji/)以获得完整的本机表情符号支持. Ubuntu 18.04(与许多现代 Linux 发行版一样)默认情况下已安装此字体. + +### Front matter[](#front-matter "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23331) . + +首要事项是 Markdown 文档开头,内容之前的元数据. 静态站点生成器(例如[Jekyll](https://jekyllrb.com/docs/front-matter/) , [Hugo](https://s0gohugo0io.icopy.site/content-management/front-matter/)和许多其他应用程序)可以使用此数据. + +当您查看由 GitLab 渲染的 Markdown 文件时,任何前端问题都会按原样显示在文档顶部的框中,位于渲染的 HTML 内容之前. 要查看示例,可以在[GitLab 文档文件](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/README.md)的源版本和渲染版本之间切换. + +在 GitLab 中,仅在 Markdown 文件和 Wiki 页面中使用前题,而不在支持 Markdown 格式的其他地方使用. 它必须在文档的最顶部,并且必须在定界符之间,如下所述. + +支持以下定界符: + +* YAML( `---` ): + + ``` + --- + title: About Front Matter + example: + language: yaml + --- + ``` + +* TOML( `+++` ): + + ``` + +++ + title = "About Front Matter" + [example] + language = "toml" + +++ + ``` + +* JSON( `;;;` ): + + ``` + ;;; { "title": "About Front Matter" "example": { "language": "json" } } ;;; + ``` + +通过向任何现有定界符添加说明符来支持其他语言. 例如: + +``` +---php +$title = "About Front Matter"; +$example = array( + 'language' => "php", +); +--- +``` + +### Inline diff[](#inline-diff "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#inline-diff) . + +使用内联 diff 标签,您可以显示`{+ additions +}`或`[- deletions -]` . + +包装标签可以是大括号或方括号: + +``` +- {+ addition 1 +} +- [+ addition 2 +] +- {- deletion 3 -} +- [- deletion 4 -] +``` + +* {+加法 1 +} +* [+加法 2 +] +* {-删除 3-} +* [-删除 4-] + +* * * + +但是,包装标签不能混合使用: + +``` +- {+ addition +] +- [+ addition +} +- {- deletion -] +- [- deletion -} +``` + +如果您的差异包含``code``字体的单词,请确保使用反斜杠`\`来转义每个反引号``` ,否则差异突出显示将无法正确呈现: + +``` +- {+ Just regular text +} +- {+ Text with `backticks` inside +} +- {+ Text with escaped \`backticks\` inside +} +``` + +* {+普通文字+} +* {+带有`backticks`文字+} +* {+内含转义的`反引号'的文字+} + +### Math[](#math "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#math) . + +可以使用[KaTeX](https://github.com/KaTeX/KaTeX)渲染用 LaTeX 语法编写的数学运算. + +在美元符号`$`之间写的数学将与文本内嵌. 用声明为`math`的语言在[代码块中](#code-spans-and-blocks)编写的`math`将在单独的行上呈现: + +``` +This math is inline $`a^2+b^2=c^2`$. + +This is on a separate line + +```math a^2+b^2=c^2 +``` +``` + +此数学`a^2+b^2=c^2`为内联$ `a^2+b^2=c^2` $. + +这是在单独的行上 + +``` +a^2+b^2=c^2 +``` + +*请注意,KaTeX 仅支持 LaTeX 的[子集](https://katex.org/docs/supported.html) .* + +**注意:**这也适用于 Asciidoctor `:stem: latexmath` . 有关详细信息,请参见[Asciidoctor 用户手册](https://asciidoctor.org/docs/user-manual/#activating-stem-support) . + +### Special GitLab references[](#special-gitlab-references "Permalink") + +GFM 可以识别与 GitLab 相关的特殊参考. 例如,您可以轻松地引用项目中的问题,提交,团队成员甚至整个团队. GFM 会将引用转换为链接,以便您可以轻松地在它们之间导航. + +此外,GFM 可以识别某些跨项目引用,并且还具有一个速记版本,可以引用同一名称空间中的其他项目. + +GFM 将识别以下内容: + +| references | input | 跨项目参考 | shortcut within same namespace | +| --- | --- | --- | --- | +| 特定使用者 | `@user_name` |   |   | +| 特定人群 | `@group_name` |   |   | +| 整个团队 | `@all` |   |   | +| project | `namespace/project>` |   |   | +| issue | `#123` | `namespace/project#123` | `project#123` | +| 合并要求 | `!123` | `namespace/project!123` | `project!123` | +| snippet | `$123` | `namespace/project$123` | `project$123` | +| epic | `&123` | `group1/subgroup&123` |   | +| 通过 ID 标签 | `~123` | `namespace/project~123` | `project~123` | +| 一词标签名称 | `~bug` | `namespace/project~bug` | `project~bug` | +| 多词标签名称 | `~"feature request"` | `namespace/project~"feature request"` | `project~"feature request"` | +| 范围标签按名称 | `~"priority::high"` | `namespace/project~"priority::high"` | `project~"priority::high"` | +| ID 项目里程碑 | `%123` | `namespace/project%123` | `project%123` | +| 一词里程碑 | `%v1.23` | `namespace/project%v1.23` | `project%v1.23` | +| 多词里程碑 | `%"release candidate"` | `namespace/project%"release candidate"` | `project%"release candidate"` | +| 具体提交 | `9ba12248` | `namespace/project@9ba12248` | `project@9ba12248` | +| 提交范围比较 | `9ba12248...b19a04f5` | `namespace/project@9ba12248...b19a04f5` | `project@9ba12248...b19a04f5` | +| 仓库文件参考 | `[README](doc/README)` |   |   | +| 存储库文件行参考 | `[README](doc/README#L13)` |   |   | + +除此之外,还可以识别和格式化指向某些对象的链接. 这些示例包括: + +* 对问题的评论: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234#note_101075757"` ,它将呈现为`#1234 (note1)` +* 问题设计标签: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234/designs"` ,该标签将显示为`#1234 (designs)` . +* 链接到各个设计: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234/designs/layout.png"` ,它将呈现为`#1234[layout.png]` . + +### Task lists[](#task-lists "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#task-lists) . + +您可以在支持 Markdown 的任何位置添加任务列表,但是如果它们处于问题,合并请求或注释中,则只能"单击"以切换它们. 在其他地方,您必须手动编辑 Markdown 以通过在方括号内添加或删除`x`来更改状态. + +要创建任务列表,请添加特殊格式的 Markdown 列表. 您可以使用无序列表或有序列表: + +``` +- [x] Completed task +- [ ] Incomplete task + - [ ] Sub-task 1 + - [x] Sub-task 2 + - [ ] Sub-task 3 + 1. [x] Completed task +1. [ ] Incomplete task + 1. [ ] Sub-task 1 + 1. [x] Sub-task 2 +``` + +* [x]完成的任务 +* []未完成的任务 + * []子任务 1 + * [x]子任务 2 + * []子任务 3 + +1. [x] Completed task +2. []未完成的任务 + 1. []子任务 1 + 2. [x]子任务 2 + +### Table of contents[](#table-of-contents "Permalink") + +通过在标记行`[[_TOC_]]`上添加标记,您可以将目录添加到 Markdown 文件,Wiki 页面或发布/合并请求描述中. 它将显示为链接到各种标题的无序列表. + +``` +This is an intro sentence to my Wiki page. + +[[_TOC_]] + +## My first heading + +First section content. + +## My second heading + +Second section content. +``` + +[![Preview of an auto-generated TOC in a Wiki](img/77707dedee5c3b669fd992a327698362.png)](img/markdown_toc_preview_v12_9.png) + +### Wiki-specific Markdown[](#wiki-specific-markdown "Permalink") + +以下示例显示了 Wiki 内部链接的行为. + +#### Wiki - direct page link[](#wiki---direct-page-link "Permalink") + +仅包含页面的子弹的链接将指向该页面, *位于 Wiki 的基本级别* . + +该代码段将链接到 Wiki 根目录下的`documentation`页面: + +``` +[Link to Documentation](documentation) +``` + +#### Wiki - direct file link[](#wiki---direct-file-link "Permalink") + +*相对于当前页面* ,带有文件扩展名的链接指向该文件. + +如果下面的代码段放在`/documentation/related`的页面上,它将链接到`/documentation/file.md` : + +``` +[Link to File](file.md) +``` + +#### Wiki - hierarchical link[](#wiki---hierarchical-link "Permalink") + +可以使用`./` , `../`来相对于当前 Wiki 页面构建链接. + +如果此代码段放在`/documentation/main`的页面上,它将链接到`/documentation/related` : + +``` +[Link to Related Page](./related) +``` + +如果此代码段放在`/documentation/related/content`的页面上,它将链接到`/documentation/main` : + +``` +[Link to Related Page](../main) +``` + +如果此代码段放在`/documentation/main`的页面上,它将链接到`/documentation/related.md` : + +``` +[Link to Related Page](./related.md) +``` + +如果此代码段放在`/documentation/related/content`的页面上,它将链接到`/documentation/main.md` : + +``` +[Link to Related Page](../main.md) +``` + +#### Wiki - root link[](#wiki---root-link "Permalink") + +以`/`开头的链接是相对于 Wiki 根目录的. + +该代码段链接到`/documentation` : + +``` +[Link to Related Page](/documentation) +``` + +该代码段链接到`/miscellaneous.md` : + +``` +[Link to Related Page](/miscellaneous.md) +``` + +### Embedding metrics in GitLab Flavored Markdown[](#embedding-metrics-in-gitlab-flavored-markdown "Permalink") + +公制图表可以嵌入到 GitLab 风味 Markdown 中. 有关更多详细信息,请参见[在 GitLab 风格的 Markdown 中嵌入度量标准](../user/project/integrations/prometheus.html#embedding-metric-charts-within-gitlab-flavored-markdown) . + +## Standard Markdown and extensions in GitLab[](#standard-markdown-and-extensions-in-gitlab "Permalink") + +所有标准 Markdown 格式均应在 GitLab 中按预期工作. 一些标准功能通过附加功能进行了扩展,而不会影响标准用法. 如果扩展了功能,则新选项将作为子节列出. + +### Blockquotes[](#blockquotes "Permalink") + +块引号是突出显示信息(如边注)的简便方法. 它是通过以`>`开头的 blockquote 行来生成的: + +``` +> Blockquotes are very handy to emulate reply text. +> This line is part of the same quote. + +Quote break. + > This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote. +``` + +> 块引用非常容易模拟回复文本. 该行是同一报价的一部分. + +报价中断. + +> 这是一条很长的行,当它换行时仍会被正确引用. 哦,男孩,让我们继续写作,以确保它足够长,可以实际包裹所有人. 哦,您可以*将* **Markdown**放入 blockquote 中. + +#### Multiline blockquote[](#multiline-blockquote "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#multiline-blockquote) . + +GFM 还支持`>>>`围起来的多行块引用,从而扩展了标准的 Markdown 标准: + +``` +>>> +If you paste a message from somewhere else + +that spans multiple lines, + +you can quote that without having to manually prepend `>` to every line! +>>> +``` + +> 如果您从其他地方粘贴消息 +> +> 跨越多行, +> +> 您可以引用它,而不必手动在每行前面加上`>` ! + +### Code spans and blocks[](#code-spans-and-blocks "Permalink") + +您可以轻松突出显示应视为代码而非简单文本的任何内容. + +简单的内联代码很容易用单个反引号```突出显示: + +``` +Inline `code` has `back-ticks around` it. +``` + +Inline `code` has `back-ticks around` it. + +* * * + +同样,整个代码块可以用三个反引号( ````` ),三个波浪号( `~~~` )或缩进 4 个或更多的空格来围起来,以实现较大代码体的相似效果. + +``` +```python def function(): + #indenting works just fine in the fenced code block + s = "Python code" + print s +``` Using 4 spaces + is like using + 3-backtick fences. +``` + +``` +~~~ +Tildes are OK too. +~~~ +``` + +上面的三个示例呈现为: + +``` +def function(): + #indenting works just fine in the fenced code block + s = "Python code" + print s +``` + +``` +Using 4 spaces +is like using +3-backtick fences. +``` + +``` +Tildes are OK too. +``` + +#### Colored code and syntax highlighting[](#colored-code-and-syntax-highlighting "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#colored-code-and-syntax-highlighting) . + +GitLab 使用[Rouge Ruby 库](http://rouge.jneen.net/)在代码块中突出显示了更加丰富多彩的语法. 有关支持的语言的列表,请访问[Rouge 项目 Wiki](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers) . 语法突出显示仅在代码块中受支持,因此在内联时无法突出显示代码. + +代码块由带有三个反引号( ````` )或三个波浪号( `~~~` )的行围起来,并在第一个围栏的末尾标识了语言: + +``` +```javascript var s = "JavaScript syntax highlighting"; +alert(s); +``` + +```python def function(): + #indenting works just fine in the fenced code block + s = "Python syntax highlighting" + print s +``` + +```ruby require 'redcarpet' +markdown = Redcarpet.new("Hello World!") +puts markdown.to_html +``` + +``` No language indicated, so no syntax highlighting. +s = "There is no highlighting for this." +But let's throw in a tag. +``` +``` + +上面的四个示例呈现为: + +``` +var s = "JavaScript syntax highlighting"; +alert(s); +``` + +``` +def function(): + #indenting works just fine in the fenced code block + s = "Python syntax highlighting" + print s +``` + +``` +require 'redcarpet' +markdown = Redcarpet.new("Hello World!") +puts markdown.to_html +``` + +``` +No language indicated, so no syntax highlighting. +s = "There is no highlighting for this." +But let's throw in a tag. +``` + +### Emphasis[](#emphasis "Permalink") + +在 Markdown 中有多种强调文本的方法. 您可以斜体,粗体,删除线,以及将这些强调样式结合在一起. + +Examples: + +``` +Emphasis, aka italics, with *asterisks* or _underscores_. + +Strong emphasis, aka bold, with double **asterisks** or __underscores__. + +Combined emphasis with **asterisks and _underscores_**. + +Strikethrough uses two tildes. ~~Scratch this.~~ +``` + +强调,又称斜体,带有*星号*或*下划线* . + +重点突出,又大胆,带有双星**号**或**下划线** . + +结合强调与**星号和*下划线*** . + +删除线使用两个波浪号. ~~抓这个.~~ + +**注意:**删除线不是 Markdown 核心标准的一部分,而是 GFM 的一部分. + +#### Multiple underscores in words and mid-word emphasis[](#multiple-underscores-in-words-and-mid-word-emphasis "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#multiple-underscores-in-words) . + +仅将单词的*一部分*斜体化通常是没有用的,尤其是当您要处理经常带有多个下划线的代码和名称时. 结果,GFM 通过忽略单词中的多个下划线来扩展了标准的 Markdown 标准,以更好地呈现讨论代码的 Markdown 文档: + +``` +perform_complicated_task + +do_this_and_do_that_and_another_thing + +but_emphasis is_desired _here_ +``` + +perform_complicated_task + +do_this_and_do_that_and_another_thing + +但是*在这里需要重点* + +* * * + +如果您只想强调单词的一部分,仍然可以使用星号来完成: + +``` +perform*complicated*task + +do*this*and*do*that*and*another thing +``` + +perform*complicated*task + +做*这个* , *做*那个*和*另一件事 + +### Footnotes[](#footnotes "Permalink") + +脚注会添加指向注释的链接,该链接将在 Markdown 文件的末尾呈现. + +要创建脚注,您既需要参考标记,又需要带有注释内容的单独行(文件中的任何地方). + +无论标签名称如何,参考标签的相对顺序都决定了呈现的编号. + +参考标记可以使用字母和其他字符. 在解决[此错误](https://gitlab.com/gitlab-org/gitlab/-/issues/24423)之前,请避免在脚注标签名称中使用小写`w`或下划线( `_` ). + +``` +A footnote reference tag looks like this: [^1] + +This reference tag is a mix of letters and numbers. [^footnote-42] + +[^1]: This is the text inside a footnote. + +[^footnote-42]: This is another footnote. +``` + +脚注参考标记如下所示: [1](#fn:1) + +此参考标记是字母和数字的组合. [2](#fn:footnote-42) + +### Headers[](#headers "Permalink") + +``` +# H1 +## H2 +### H3 +#### H4 +##### H5 +###### H6 + +Alternatively, for H1 and H2, an underline-ish style: + +Alt-H1 +====== +Alt-H2 +------ +``` + +#### Header IDs and links[](#header-ids-and-links "Permalink") + +GFM 扩展了标准 Markdown 标准,以便所有 Markdown 呈现的标头都自动获取 ID,可以将 ID 链接到该 ID,注释中除外. + +悬停时,将显示到这些 ID 的链接,从而可以更轻松地将链接复制到标头以在其他地方使用. + +根据以下规则从标头的内容生成 ID: + +1. 所有文本都将转换为小写. +2. 删除所有非单词文本(例如标点符号或 HTML). +3. 所有空格都将转换为连字符. +4. 连续的两个或多个连字符转换为 1. +5. If a header with the same ID has already been generated, a unique incrementing number is appended, starting at 1. + +Example: + +``` +# This header has spaces in it +## This header has a :thumbsup: in it +# This header has Unicode in it: 한글 +## This header has spaces in it +### This header has spaces in it +## This header has 3.5 in it (and parentheses) +``` + +将生成以下链接 ID: + +1. `this-header-has-spaces-in-it` +2. `this-header-has-a-in-it` +3. `this-header-has-unicode-in-it-한글` +4. `this-header-has-spaces-in-it-1` +5. `this-header-has-spaces-in-it-2` +6. `this-header-has-3-5-in-it-and-parentheses` + +请注意,表情符号处理是在生成标题 ID 之前进行的,因此表情符号将转换为图像,然后从 ID 中删除. + +### Horizontal Rule[](#horizontal-rule "Permalink") + +使用三个或多个连字符,星号或下划线来创建水平尺非常简单: + +``` +Three or more hyphens, + --- +asterisks, + *** +or underscores + +___ +``` + +### Images[](#images "Permalink") + +Examples: + +``` +Inline-style (hover to see title text): + +![alt text](img/markdown_logo.png "Title Text") + +Reference-style (hover to see title text): + +![alt text1][logo] + +[logo]: img/markdown_logo.png "Title Text" +``` + +Inline-style (hover to see title text): + +[![alt text](img/c5c16791538bd6838d6196a0b4ec5bb7.png "Title Text")](img/markdown_logo.png) + +参考样式(悬停以查看标题文本): + +[![alt text](img/c5c16791538bd6838d6196a0b4ec5bb7.png "Title Text")](img/markdown_logo.png) + +#### Videos[](#videos "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#videos) . + +链接到带有视频扩展名的文件的图像标签会自动转换为视频播放器. 有效的视频扩展名是`.mp4` , `.m4v` , `.mov` , `.webm`和`.ogv` : + +``` +Here's a sample video: + +![Sample Video](img/markdown_video.mp4) +``` + +这是一个示例视频: + +[![Sample Video](img/bf99e217a01388f7c11df39626ab9e22.png)](img/markdown_video.mp4) + +#### Audio[](#audio "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#audio) . + +与视频类似,带有音频扩展名的文件的链接标签会自动转换为音频播放器. 有效的音频扩展名是`.mp3` , `.oga` , `.ogg` , `.spx`和`.wav` : + +``` +Here's a sample audio clip: + +![Sample Audio](img/markdown_audio.mp3) +``` + +这是一个示例音频剪辑: + +[![Sample Audio](img/8095440bd29d634de897ae56f76a4969.png)](img/markdown_audio.mp3) + +### Inline HTML[](#inline-html "Permalink") + +> 要在第二个示例中[查看](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#inline-html)在 HTML 中呈现的 Markdown,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#inline-html) . + +您还可以在 Markdown 中使用原始 HTML,通常效果很好. + +有关允许的 HTML 标记和属性的列表,请参见 HTML :: Pipeline 的[SanitizationFilter](https://github.com/jch/html-pipeline/blob/v2.12.3/lib/html/pipeline/sanitization_filter.rb#L42)类的文档. 除了默认`SanitizationFilter`允许列表,GitLab 允许`span` , `abbr` , `details`和`summary`元素. + +``` +
    +
    Definition list
    +
    Is something people use sometimes.
    + +
    Markdown in HTML
    +
    Does *not* work **very** well. HTML tags will work, in most cases.
    +
    +``` + +Definition list + +人们有时会用到的东西. + +Markdown in HTML + +*不是*很好**. HTML *标签*将工作 ,在大多数情况下. + +* * * + +仍然可以在 HTML 标记内使用 Markdown,但前提是包含 Markdown 的行分为各自的行: + +``` +
    +
    Markdown in HTML
    +
    Does *not* work **very** well. HTML tags will work, in most cases.
    + +
    Markdown in HTML
    +
    + + Does *not* work **very** well. HTML tags will work, in most cases. + +
    +
    +``` + +Markdown in HTML + +*不是*很好**. HTML 标记在大多数情况下都可以使用. + +Markdown in HTML + +*不能* 很好地工作. HTML 标记在大多数情况下都可以使用. + +#### Details and summary[](#details-and-summary "Permalink") + +> 要在第二个示例中[查看](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#details-and-summary)在 HTML 中呈现的 Markdown,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#details-and-summary) . + +可以使用 HTML 的[`
    `](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/HTML/Element/details)和[``](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/HTML/Element/summary)标记折叠内容. 这对于折叠长日志特别有用,因为它们占用更少的屏幕空间. + +``` +

    +

    +Click this to collapse/fold. + +These details will remain hidden until expanded. + +
    PASTE LOGS HERE
    + +
    +

    +``` + +
    单击以折叠/折叠. 这些细节*将*保持**隐藏,**直到扩展. + +``` + PASTE LOGS HERE +```
    + +* * * + +这些标记内的 Markdown 也受支持. + +**注意:**如果 Markdown 无法正确呈现,请尝试在页面顶部添加`{::options parse_block_html="true" /}` ,然后将`markdown="span"`添加到开头的摘要标记中,如下所示: `` . + +请记住,在``标记之后和`
    `标记之前留空行,如示例所示: + +``` +
    +Click this to collapse/fold. + +These details _will_ remain **hidden** until expanded. + +``` +PASTE LOGS HERE +``` + +
    +``` + +
    单击以折叠/折叠. 这些细节*将*保持隐藏,直到扩展. + +``` + PASTE LOGS HERE +```
    + +### Line breaks[](#line-breaks "Permalink") + +如果先前的文本以两个换行符结尾,则会插入一个换行符(将开始一个新的段落),例如当您连续两次按`Enter 键`时. 如果仅使用一个换行符( `按`一次`Enter 键` ),则下一个句子将成为同一段落的一部分. 如果要避免长行换行并使它们易于编辑,这很有用: + +``` +Here's a line for us to start with. + +This longer line is separated from the one above by two newlines, so it will be a *separate paragraph*. + +This line is also a separate paragraph, but... +These lines are only separated by single newlines, +so they *do not break* and just follow the previous lines +in the *same paragraph*. +``` + +这是我们要开始的一行. + +该较长的行与上面的一行由两个换行符*隔开* ,因此它将是一个*单独的段落* . + +该行也是一个单独的段落,但是…这些行仅由单个换行符分隔,因此它们*不会中断*并且仅遵循*同一段落中*的前几行. + +#### Newlines[](#newlines "Permalink") + +GFM 在[处理段落和换行符方面](https://spec.commonmark.org/current/)遵循 Markdown 规范. + +段落是一个或多个连续的文本行,由一个或多个空行分隔(第一段末尾有两个新行), [如上所述](#line-breaks) . + +如果您需要对换行符或换行符进行更多控制,则可以通过以反斜杠或两个或多个空格结束一行来添加单个换行符. 连续两个换行符将创建一个新的段落,中间有一个空行: + +``` +First paragraph. +Another line in the same paragraph. +A third line in the same paragraph, but this time ending with two spaces.{space}{space} +A new line directly under the first paragraph. + +Second paragraph. +Another line, this time ending with a backslash.\ +A new line due to the previous backslash. +``` + +### Links[](#links "Permalink") + +有两种创建链接的方法,即内联样式和引用样式: + +``` +- This is an [inline-style link](https://www.google.com) +- This is a [link to a repository file in the same directory](index.md) +- This is a [relative link to a readme one directory higher](../README.md) +- This is a [link that also has title text](https://www.google.com "This link takes you to Google!") + +Using header ID anchors: + +- This links to [a section on a different Markdown page, using a "#" and the header ID](index.md#overview) +- This links to [a different section on the same page, using a "#" and the header ID](#header-ids-and-links) + +Using references: + +- This is a [reference-style link, see below][Arbitrary case-insensitive reference text] +- You can [use numbers for reference-style link definitions, see below][1] +- Or leave it empty and use the [link text itself][], see below. + +Some text to show that the reference links can follow later. + +[arbitrary case-insensitive reference text]: https://www.mozilla.org/en-US/ +[1]: https://slashdot.org +[link text itself]: https://www.reddit.com +``` + +* 这是一个[内联样式的链接](https://www.google.com) +* 这是[指向同一目录中存储库文件](index.html)的[链接](index.html) +* 这是[指向自述文件的上一级目录](../README.html)的[相对链接](../README.html) +* 这是一个[也有标题文字](https://www.google.com "此链接将您带到 Google!")的[链接](https://www.google.com "此链接将您带到 Google!") + +使用标头 ID 锚点: + +* 该链接[使用"#"和标题 ID](index.html#overview)链接到[另一个 Markdown 页面上的部分](index.html#overview) +* 这[使用"#"和标题 ID](#header-ids-and-links)链接到[同一页面上的不同部分.](#header-ids-and-links) + +使用参考: + +* 这是[参考样式的链接,请参见下文](https://www.mozilla.org/en-US/) +* 您可以[将数字用于引用样式的链接定义,请参见下文](https://slashdot.org) +* 或将其保留为空,并使用[链接文本本身](https://www.reddit.com) ,请参见下文. + +一些文本表明参考链接可以在以后使用. + +**注意:**相对链接不允许引用 Wiki 页面或项目文件中的 Wiki 页面中的项目文件. 这样做的原因是,Wiki 始终位于 GitLab 中的单独 Git 存储库中. 例如,仅当链接位于 Wiki Markdown 文件内部时, `[I'm a reference-style link](style)`才会将链接指向`wikis/style` . + +#### URL auto-linking[](#url-auto-linking "Permalink") + +GFM will auto-link almost any URL you put into your text: + +``` +- https://www.google.com +- https://www.google.com +- ftp://ftp.us.debian.org/debian/ +- smb://foo/bar/baz +- irc://irc.freenode.net/ +- http://localhost:3000 +``` + +* [https://www.google.com](https://www.google.com) +* [https://www.google.com](https://www.google.com) +* [ftp://ftp.us.debian.org/debian/](ftp://ftp.us.debian.org/debian/) +* +* +* [http://localhost:3000](http://localhost:3000) + +### Lists[](#lists "Permalink") + +可以轻松创建有序列表和无序列表. + +对于有序列表,请在有序列表的每一行的开头添加希望列表以其开头的数字,例如`1.` ,后跟一个空格. 在第一个数字之后,使用什么数字都没有关系,有序列表将按垂直顺序自动编号,因此对同一列表中的所有项目重复`1.` .. 如果你开始以外的其他数字`1.` ,它会用它作为第一个数字,并从那里计数. + +Examples: + +``` +1. First ordered list item +2. Another item + - Unordered sub-list. +1. Actual numbers don't matter, just that it's a number + 1. Ordered sub-list + 1. Next ordered sub-list item +4. And another item. +``` + +1. 首先订购的清单项目 +2. 另一个项目 + * 无序子列表. +3. 实际数字并不重要,只是一个数字 + 1. 订购子清单 + 2. 下一个订购的子清单项目 +4. 还有另一个项目. + +对于无序列表,请在无序列表的每一行的开头添加`-` , `*`或`+` ,然后加上一个空格,但是您不能混合使用它们. + +``` +Unordered lists can: + - use +- minuses + +They can also: + * use +* asterisks + +They can even: + + use ++ pluses +``` + +无序列表可以: + +* use +* minuses + +他们还可以: + +* use +* asterisks + +They can even: + +* use +* pluses + +* * * + +如果列表项包含多个段落,则每个后续段落都应缩进到与列表项文本开头相同的级别. + +Example: + +``` +1. First ordered list item + + Second paragraph of first item. + 1. Another item +``` + +1. 首先订购的清单项目 + + 第一项第二段. + +2. Another item + +* * * + +如果第一项的段落没有缩进适当的空格数,则该段落将出现在列表外部,而不是在列表项下方正确缩进. + +Example: + +``` +1. First ordered list item + + Paragraph of first item. + 1. Another item +``` + +1. 首先订购的清单项目 + +第一项的段落. + +1. 另一个项目 + +### Superscripts / Subscripts[](#superscripts--subscripts "Permalink") + +当前,CommonMark 和 GFM 不支持 Redcarpet 支持的上标语法( `x^2` ). 您可以对上标和下标使用标准的 HTML 语法: + +``` +The formula for water is H2O +while the equation for the theory of relativity is E = mc2. +``` + +水的公式为 H 2 O,而相对论的公式为 E = mc 2 . + +### Tables[](#tables "Permalink") + +表不是 Markdown 核心规范的一部分,但它们是 GFM 的一部分. + +1. 第一行包含标头,并用"竖线"( `|` )分隔. +2. 第二行将标题与单元格分开,并且必须包含三个或更多破折号. +3. 第三行以及随后的任何行均包含单元格值. + * 您**不能**在 Markdown 中将单元格分隔成多行,它们必须保持为单行,但它们可能会很长. 如果需要,还可以包含 HTML `
    `标记以强制换行. + * 像元大小**不必**彼此匹配. 它们很灵活,但必须用管道( `|` )分隔. + * 您**可以**有空白单元格. + +Example: + +``` +| header 1 | header 2 | header 3 | +| --- | ------ |---------:| +| cell 1 | cell 2 | cell 3 | +| cell 4 | cell 5 is longer | cell 6 is much longer than the others, but that's ok. It will eventually wrap the text when the cell is too large for the display size. | +| cell 7 | | cell
    9 | +``` + +| 标题 1 | 标头 2 | 标头 3 | +| --- | --- | --- | +| 单元格 1 | 单元格 2 | 单元格 3 | +| 单元格 4 | 单元格 5 更长 | 单元格 6 比其他单元格长得多,但这没关系. 当单元格太大而无法显示时,它将最终包裹文本. | +| 单元格 7 |   | cell +9 | + +(另外,你可以通过添加冒号选择文本列中的对齐`:`第二行中的"破折号"线条的两侧). 这将影响列中的每个单元格. + +**注意:** [在 GitLab 本身中](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#tables) ,标题始终在 Chrome 和 Firefox 中左对齐,并在 Safari 中居中. + +``` +| Left Aligned | Centered | Right Aligned | Left Aligned | Centered | Right Aligned | +| :--- | :---: | ---: | :----------- | :------: | ------------: | +| Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | +| Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | +``` + +| 左对齐 | Centered | 右对齐 | 左对齐 | Centered | 右对齐 | +| --- | --- | --- | --- | --- | --- | +| 单元格 1 | 单元格 2 | 单元格 3 | 单元格 4 | 单元格 5 | 单元格 6 | +| 单元格 7 | 单元格 8 | 单元格 9 | 单元格 10 | 单元格 11 | 单元格 12 | + +#### Copy from spreadsheet and paste in Markdown[](#copy-from-spreadsheet-and-paste-in-markdown "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27205) . + +如果您使用电子表格软件(例如 Microsoft Excel,Google 表格或 Apple Numbers),则可以从电子表格中进行复制,GitLab 会将其粘贴为 Markdown 表. 例如,假设您具有以下电子表格: + +[![Copy from spreadsheet](img/c2f9cb2f2c88244b3dbf094572214a02.png)](img/markdown_copy_from_spreadsheet_v12_7.png) + +选择单元格并将其复制到剪贴板. 打开一个 GitLab Markdown 条目并粘贴电子表格: + +[![Paste to Markdown table](img/56c21932bdeb67b5407d18238e8ec7f3.png)](img/markdown_paste_table_v12_7.png) + +## References[](#references "Permalink") + +* 该文档从[Markdown-Cheatsheet 中](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)大量利用. +* Daring Fireball 上的原始[Markdown 语法指南](https://daringfireball.net/projects/markdown/syntax)是详细解释标准 Markdown 的绝佳资源. +* 有关 CommonMark 的详细规范,请参见[CommonMark 规范.](https://spec.commonmark.org/current/) +* [CommonMark Dingus](http://try.commonmark.org)是用于测试 CommonMark 语法的便捷工具. + +1. 这是脚注中的文本. [↩](#fnref:1) + +2. 这是另一个脚注. [↩](#fnref:footnote-42) \ No newline at end of file diff --git a/_book/docs/409.md b/_book/docs/409.md new file mode 100644 index 0000000000000000000000000000000000000000..cadc95682467e24fb8b5ed711168ac376f8ccad5 --- /dev/null +++ b/_book/docs/409.md @@ -0,0 +1,409 @@ +# AsciiDoc + +> 原文:[https://docs.gitlab.com/ee/user/asciidoc.html](https://docs.gitlab.com/ee/user/asciidoc.html) + +* [Syntax](#syntax) + * [Paragraphs](#paragraphs) + * [Text Formatting](#text-formatting) + * [Attributes](#attributes) + * [Links](#links) + * [Anchors](#anchors) + * [Lists](#lists) + * [Unordered](#unordered) + * [Ordered](#ordered) + * [Checklist](#checklist) + * [Callout](#callout) + * [Description](#description) + * [Document Structure](#document-structure) + * [Header](#header) + * [Sections](#sections) + * [Includes](#includes) + * [Blocks](#blocks) + * [Tables](#tables) + * [Multimedia](#multimedia) + * [Breaks](#breaks) + +# AsciiDoc[](#asciidoc "Permalink") + +GitLab 使用[Asciidoctor](https://asciidoctor.org) gem 将 AsciiDoc 内容转换为 HTML5\. 有关完整的 Asciidoctor 参考,请查阅《 [Asciidoctor 用户手册](https://asciidoctor.org/docs/user-manual/) 》. + +## Syntax[](#syntax "Permalink") + +这是最常用的 AsciiDoc 语法的简要参考. 您可以在[https://asciidoctor.org/docs/上](https://asciidoctor.org/docs/)找到有关 AsciiDoc 语法的完整文档. + +### Paragraphs[](#paragraphs "Permalink") + +``` +A normal paragraph. +Line breaks are not preserved. +``` + +跳过以`//`开头的行注释: + +``` +// this is a comment +``` + +空白行分隔段落. + +带有`[%hardbreaks]`选项的段落将保留换行符: + +``` +[%hardbreaks] +This paragraph carries the `hardbreaks` option. +Notice how line breaks are now preserved. +``` + +缩进(文字)段落会禁用文本格式,保留空格和换行符,并以等宽字体显示: + +``` + This literal paragraph is indented with one space. + As a consequence, *text formatting*, spaces, + and lines breaks will be preserved. +``` + +一条警告段落引起了读者的注意: + +``` +NOTE: This is a brief reference, please read the full documentation at https://asciidoctor.org/docs/. + +TIP: Lists can be indented. Leading whitespace is not significant. +``` + +### Text Formatting[](#text-formatting "Permalink") + +**受约束的(应用于单词边界)** + +``` +*strong importance* (aka bold) +_stress emphasis_ (aka italic) +`monospaced` (aka typewriter text) +"`double`" and '`single`' typographic quotes ++passthrough text+ (substitutions disabled) +`+literal text+` (monospaced with substitutions disabled) +``` + +**不受限制(适用于任何地方)** + +``` +**C**reate+**R**ead+**U**pdate+**D**elete +fan__freakin__tastic +``mono``culture +``` + +**Replacements** + +``` +A long time ago in a galaxy far, far away... +(C) 1976 Arty Artisan +I believe I shall--no, actually I won't. +``` + +**Macros** + +``` +// where c=specialchars, q=quotes, a=attributes, r=replacements, m=macros, p=post_replacements, etc. +The European icon:flag[role=blue] is blue & contains pass:[************] arranged in a icon:circle-o[role=yellow]. +The pass:c[->] operator is often referred to as the stabby lambda. +Since `pass:[++]` has strong priority in AsciiDoc, you can rewrite pass:c,a,r[C++ => C{pp}]. +// activate stem support by adding `:stem:` to the document header +stem:[sqrt(4) = 2] +``` + +### Attributes[](#attributes "Permalink") + +**用户定义的属性** + +``` +// define attributes in the document header +:name: value +``` + +``` +:url-gem: https://rubygems.org/gems/asciidoctor + +You can download and install Asciidoctor {asciidoctor-version} from {url-gem}. +C{pp} is not required, only Ruby. +Use a leading backslash to output a word enclosed in curly braces, like \{name}. +``` + +**环境属性** + +GitLab 设置以下环境属性: + +| Attribute | Description | +| --- | --- | +| `docname` | 源文档的根名称(无前导路径或文件扩展名). | +| `outfilesuffix` | 对应于后端输出的文件扩展名(默认为`.adoc`以使文档间的交叉引用起作用). | + +### Links[](#links "Permalink") + +``` +https://example.org/page[A webpage] +link:../path/to/file.txt[A local file] +xref:document.adoc[A sibling document] +mailto:hello@example.org[Email to say hello!] +``` + +### Anchors[](#anchors "Permalink") + +``` +[[idname,reference text]] +// or written using normal block attributes as `[#idname,reftext=reference text]` +A paragraph (or any block) with an anchor (aka ID) and reftext. + +See <> or <>. + +xref:document.adoc#idname[Jumps to anchor in another document]. + +This paragraph has a footnote.footnote:[This is the text of the footnote.] +``` + +### Lists[](#lists "Permalink") + +#### Unordered[](#unordered "Permalink") + +``` +* level 1 +** level 2 +*** level 3 +**** level 4 +***** etc. +* back at level 1 ++ +Attach a block or paragraph to a list item using a list continuation (which you can enclose in an open block). + +.Some Authors +[circle] +- Edgar Allen Poe +- Sheri S. Tepper +- Bill Bryson +``` + +#### Ordered[](#ordered "Permalink") + +``` +. Step 1 +. Step 2 +.. Step 2a +.. Step 2b +. Step 3 + +.Remember your Roman numerals? +[upperroman] +. is one +. is two +. is three +``` + +#### Checklist[](#checklist "Permalink") + +``` +* [x] checked +* [ ] not checked +``` + +#### Callout[](#callout "Permalink") + +``` +// enable callout bubbles by adding `:icons: font` to the document header +[,ruby] +---- +puts 'Hello, World!' # <1> +---- +<1> Prints `Hello, World!` to the console. +``` + +#### Description[](#description "Permalink") + +``` +first term:: description of first term +second term:: +description of second term +``` + +### Document Structure[](#document-structure "Permalink") + +#### Header[](#header "Permalink") + +``` += Document Title +Author Name +v1.0, 2019-01-01 +``` + +#### Sections[](#sections "Permalink") + +``` += Document Title (Level 0) +== Level 1 +=== Level 2 +==== Level 3 +===== Level 4 +====== Level 5 +== Back at Level 1 +``` + +#### Includes[](#includes "Permalink") + +``` +include::basics.adoc[] + +// define -a allow-uri-read to allow content to be read from URI +include::https://example.org/installation.adoc[] +``` + +为了保证良好的系统性能并防止恶意文档引起问题,GitLab 对任何一个文档中处理的 include 指令的数量实施了**最大限制** . 当前总共可以包含 32 个文档,其中包括传递依赖项. + +### Blocks[](#blocks "Permalink") + +``` +-- +open - a general-purpose content wrapper; useful for enclosing content to attach to a list item +-- +``` + +``` +// recognized types include CAUTION, IMPORTANT, NOTE, TIP, and WARNING +// enable admonition icons by setting `:icons: font` in the document header +[NOTE] +==== +admonition - a notice for the reader, ranging in severity from a tip to an alert +==== +``` + +``` +==== +example - a demonstration of the concept being documented +==== +``` + +``` +.Toggle Me +[%collapsible] +==== +collapsible - these details are revealed by clicking the title +==== +``` + +``` +**** +sidebar - auxiliary content that can be read independently of the main content +**** +``` + +``` +.... +literal - an exhibit that features program output +.... +``` + +``` +---- +listing - an exhibit that features program input, source code, or the contents of a file +---- +``` + +``` +[,language] +---- +source - a listing that is embellished with (colorized) syntax highlighting +---- +``` + +``` +\```language +fenced code - a shorthand syntax for the source block +\``` +``` + +``` +[,attribution,citetitle] +____ +quote - a quotation or excerpt; attribution with title of source are optional +____ +``` + +``` +[verse,attribution,citetitle] +____ +verse - a literary excerpt, often a poem; attribution with title of source are optional +____ +``` + +``` +++++ +pass - content passed directly to the output document; often raw HTML +++++ +``` + +``` +// activate stem support by adding `:stem:` to the document header +[stem] +++++ +x = y^2 +++++ +``` + +``` +//// +comment - content which is not included in the output document +//// +``` + +### Tables[](#tables "Permalink") + +``` +.Table Attributes +[cols=>1h;2d,width=50%,frame=topbot] +|=== +| Attribute Name | Values + +| options +| header,footer,autowidth + +| cols +| colspec[;colspec;...] + +| grid +| all \| cols \| rows \| none + +| frame +| all \| sides \| topbot \| none + +| stripes +| all \| even \| odd \| none + +| width +| (0%..100%) + +| format +| psv {vbar} csv {vbar} dsv +|=== +``` + +### Multimedia[](#multimedia "Permalink") + +``` +image::screenshot.png[block image,800,450] + +Press image:reload.svg[reload,16,opts=interactive] to reload the page. + +video::movie.mp4[width=640,start=60,end=140,options=autoplay] + +video::aHjpOzsQ9YI[youtube] + +video::300817511[vimeo] +``` + +### Breaks[](#breaks "Permalink") + +``` +// thematic break (aka horizontal rule) +--- +``` + +``` +// page break +<<< +``` \ No newline at end of file diff --git a/_book/docs/410.md b/_book/docs/410.md new file mode 100644 index 0000000000000000000000000000000000000000..58aedae74fa6e76313dd6e7c1f74796da7c7399a --- /dev/null +++ b/_book/docs/410.md @@ -0,0 +1,243 @@ +# GitLab Notification Emails + +> 原文:[https://docs.gitlab.com/ee/user/profile/notifications.html](https://docs.gitlab.com/ee/user/profile/notifications.html) + +* [Receiving notifications](#receiving-notifications) +* [Tuning your notifications](#tuning-your-notifications) + * [Editing notification settings](#editing-notification-settings) +* [Global notification settings](#global-notification-settings) + * [Notification scope](#notification-scope) + * [Project notifications](#project-notifications) + * [Group notifications](#group-notifications) + * [Group notification level](#group-notification-level) + * [Group notification email address](#group-notification-email-address) + * [Notification levels](#notification-levels) +* [Notification events](#notification-events) +* [Issue / Epics / Merge request events](#issue--epics--merge-request-events) +* [Filtering email](#filtering-email) + * [X-GitLab-NotificationReason](#x-gitlab-notificationreason) + +# GitLab Notification Emails[](#gitlab-notification-emails "Permalink") + +GitLab 通知使您可以随时了解 GitLab 中发生的事情. 启用通知后,您可以接收有关问题,合并请求和史诗活动的更新. 通知通过电子邮件发送. + +## Receiving notifications[](#receiving-notifications "Permalink") + +您将由于以下原因之一收到通知: + +* 您参与发行,合并请求或史诗. 在这种情况下, *参与*意味着评论或编辑. +* You enable notifications in an issue, merge request, or epic. To enable notifications, click the **Notifications** toggle in the sidebar to *on*. + +启用通知后,您将收到有关该问题,合并请求或史诗中发生的操作的通知. + +**注意:**通知可能会被管理员阻止,从而阻止发送通知. + +## Tuning your notifications[](#tuning-your-notifications "Permalink") + +通知的数量可能是巨大的. GitLab 允许您调整收到的通知. 例如,您可能希望收到有关特定项目中所有活动的通知,而对于其他项目,仅当您的名字被提及时才得到通知. + +您可以通过组合通知设置来调整收到的通知: + +* [Global notification settings](#global-notification-settings) +* [Notification scope](#notification-scope) +* [Notification levels](#notification-levels) + +### Editing notification settings[](#editing-notification-settings "Permalink") + +编辑通知设置: + +1. 点击您的个人资料图片,然后选择**设置** . +2. 点击左侧边栏中的**通知** . +3. 编辑所需的通知设置. 编辑的设置将自动保存并启用. + +这些通知设置仅适用于您. 它们不会影响同一项目或组中其他任何人收到的通知. + +[![notification settings](img/81fe297de1dccaedd3340735454273bc.png)](img/notification_global_settings.png) + +## Global notification settings[](#global-notification-settings "Permalink") + +**全局通知设置**是默认设置,除非您为项目或组选择不同的值. + +* 通知电子邮件 + * 这是您的通知将发送到的电子邮件地址. +* 全局通知级别 + * 这是适用于所有通知的默认[通知级别](#notification-levels) . +* 接收有关您自己的活动的通知. + * 如果您想接收有关自己活动的通知,请选中此复选框. 默认值:未选中. + +### Notification scope[](#notification-scope "Permalink") + +您可以通过为每个项目和组选择不同的通知级别来调整通知的范围. + +通知范围按优先级顺序应用(从高到低): + +* Project + * 对于每个项目,您可以选择一个通知级别. 您的项目设置将覆盖组设置. +* Group + * 对于每个组,您可以选择一个通知级别. 您的群组设置会覆盖您的默认设置. +* 全局(默认) + * 如果尚未为发生活动的项目或组选择通知级别,则将应用全局或*默认*通知级别. + +#### Project notifications[](#project-notifications "Permalink") + +您可以为每个项目选择一个通知级别. 如果您需要密切监视选定项目中的活动,这将很有用. + +[![notification settings](img/bab81ba0a915cec8b039166d2defc074.png)](img/notification_project_settings_v12_8.png) + +要为项目选择通知级别,请使用以下两种方法之一: + +1. 点击您的个人资料图片,然后选择**设置** . +2. 点击左侧边栏中的**通知** . +3. 在" **项目"**部分中找到该项目. +4. 选择所需的[通知级别](#notification-levels) . + +Or: + +1. 导航到项目页面. +2. 单击带有下拉图标的通知下拉列表. +3. 选择所需的[通知级别](#notification-levels) . + +有关如何在有新版本发布时通知的演示,请参阅[发布通知](https://www.youtube.com/watch?v=qyeNkGgqmH4) . + +#### Group notifications[](#group-notifications "Permalink") + +您可以为每个组选择通知级别和电子邮件地址. + +[![notification settings](img/c39dc466882289b42ad827dbbc05b39f.png)](img/notification_group_settings_v12_8.png) + +##### Group notification level[](#group-notification-level "Permalink") + +要为组选择通知级别,请使用以下两种方法之一: + +1. 点击您的个人资料图片,然后选择**设置** . +2. 点击左侧边栏中的**通知** . +3. 在" **组"**部分中找到该项目. +4. 选择所需的[通知级别](#notification-levels) . + +* * * + +1. 导航到组的页面. +2. 单击带有下拉图标的通知下拉列表. +3. 选择所需的[通知级别](#notification-levels) . + +##### Group notification email address[](#group-notification-email-address "Permalink") + +在 GitLab 12.0 中引入 + +您可以选择一个电子邮件地址,以接收您所属的每个组的通知. 例如,如果您是自由职业者,并且希望将有关客户项目的电子邮件分开存放,这可能会很有用. + +1. 点击您的个人资料图片,然后选择**设置** . +2. 点击左侧边栏中的**通知** . +3. 在" **组"**部分中找到该项目. +4. 选择所需的电子邮件地址. + +### Notification levels[](#notification-levels "Permalink") + +对于每个项目和组,您可以选择以下级别之一: + +| Level | Description | +| --- | --- | +| Global | 您的全局设置适用. | +| Watch | 接收任何活动的通知. | +| 提一下 | `@mentioned`在评论中`@mentioned`接收通知. | +| Participate | 接收有关您参与的线程的通知. | +| Disabled | 关闭通知. | +| Custom | 接收有关自定义选定事件的通知. | + +## Notification events[](#notification-events "Permalink") + +将通知用户以下事件: + +| Event | 发给 | 设定等级 | +| --- | --- | --- | +| 添加了新的 SSH 密钥 | User | 安全电子邮件,始终发送. | +| 添加了新电子邮件 | User | 安全电子邮件,始终发送. | +| 电邮已变更 | User | 安全电子邮件,始终发送. | +| 密码已更改 | User | 安全电子邮件,始终发送. | +| 新用户创建 | User | 在创建用户时发送,但 OmniAuth(LDAP)除外 | +| 用户已添加到项目 | User | 将用户添加到项目时发送 | +| 项目访问权限级别已更改 | User | 更改用户项目访问级别时发送 | +| 用户已添加到组 | User | 将用户添加到组时发送 | +| 群组访问权限级别已更改 | User | 更改用户组访问级别时发送 | +| 项目已移 | 项目成员(1) | (1)不禁用 | +| 新品发布 | 项目成员 | 自定义通知 | + +## Issue / Epics / Merge request events[](#issue--epics--merge-request-events "Permalink") + +在以下大多数情况下,通知将发送到: + +* Participants: + * 发行/合并请求的作者和受让人 + * 关于问题/合并请求的评论的作者 + * `@username`在问题,合并请求或史诗的标题或描述中提到的任何人 + * `@username`在有关问题,合并请求或史诗的任何评论中提及的"参与"或更高通知级别的任何人 +* 观察者:通知级别为"观察"的用户 +* 订阅者:手动订阅问题,合并请求或史诗的任何人 +* 自定义:通知级别为"自定义"的用户针对下表中显示的任何事件打开了通知 + +**注意:**为了最大程度地减少不需要任何操作的通知的数量,从[GitLab 12.9 起](https://gitlab.com/gitlab-org/gitlab/-/issues/616) ,不再为项目中的所有活动通知合格的批准者. 要接收它们,他们必须将其用户通知设置更改为" **观看"** . + +| Event | 发给 | +| --- | --- | +| 新问题 |   | +| 结束期 |   | +| 重新分配问题 | 以上,加上旧的受让人 | +| 重新打开问题 |   | +| 到期问题 | 选择此事件的参与者和自定义通知级别 | +| 更改里程碑问题 | 选择了此事件的订户,提及的参与者和自定义通知级别 | +| 消除里程碑问题 | 选择了此事件的订户,提及的参与者和自定义通知级别 | +| 新合并请求 |   | +| 推送合并请求 | 选择此事件的参与者和自定义通知级别 | +| 重新分配合并请求 | 以上,加上旧的受让人 | +| 关闭合并请求 |   | +| 重新打开合并请求 |   | +| 合并合并请求 |   | +| 更改里程碑合并请求 | 选择了此事件的订户,提及的参与者和自定义通知级别 | +| 删除里程碑合并请求 | 选择了此事件的订户,提及的参与者和自定义通知级别 | +| 新评论 | 以上内容,加上评论中`@username`提及的任何人,通知级别为"提及"或更高 | +| 管道失败 | 管道的作者 | +| 固定管道 | 管道的作者. 默认启用. 在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/24309) . 管理员可以使用`ci_pipeline_fixed_notifications` [功能标记](../../administration/feature_flags.html)禁用此通知选项. | +| 成功的管道 | 管道的作者(如果他们具有成功管道的自定义通知设置). 如果管道先前失败,则将为失败后的第一个成功管道发送`Fixed pipeline`消息,然后为任何进一步成功的管道发送`Successful pipeline`消息. | +| 新史诗 |   | +| 接近史诗 |   | +| 重新开启史诗 |   | + +此外,如果发布或合并请求的标题或描述发生了更改,则通知将通过`@username`发送到任何**新**提及的内容,就像在原始文本中提到的一样. + +您不会收到有关您自己创建的问题,合并请求或里程碑的通知(除非由于问题而定). 仅当其他人对您创建或提及的内容进行评论或添加更改时,您才会收到自动通知. + +如果开放的合并请求由于冲突而变得不可合并,则将通知其原因. 如果用户还将合并请求设置为一旦管道成功就自动合并,则该用户也会收到通知. + +## Filtering email[](#filtering-email "Permalink") + +通知电子邮件包括特定于 GitLab 的标题. 您可以根据这些标头的内容过滤通知电子邮件,以更好地管理您的通知. 例如,您可以过滤特定项目的所有电子邮件,在该项目中您将被分配合并请求或问题. + +下表列出了所有特定于 GitLab 的电子邮件标题: + +| Header | Description | +| --- | --- | +| `X-GitLab-Group-Id` | 组的 ID. 仅在史诗的通知电子邮件中显示. | +| `X-GitLab-Group-Path` | 组的路径. 仅在史诗的通知电子邮件中显示. | +| `X-GitLab-Project` | 通知所属的项目的名称. | +| `X-GitLab-Project-Id` | 项目的 ID. | +| `X-GitLab-Project-Path` | 项目的路径. | +| `X-GitLab-(Resource)-ID` | 通知所针对的资源的 ID. 该资源例如可以是`Issue` , `MergeRequest` , `Commit`或其他此类资源. | +| `X-GitLab-Discussion-ID` | 注释所属的线程的 ID,用于注释的通知电子邮件中. | +| `X-GitLab-Pipeline-Id` | 通知所针对的管道的 ID,在管道的通知电子邮件中. | +| `X-GitLab-Reply-Key` | 支持通过电子邮件回复的唯一令牌. | +| `X-GitLab-NotificationReason` | 通知原因. 可以`mentioned` , `assigned`或`own_activity` . | +| `List-Id` | The path of the project in an RFC 2919 mailing list identifier. This is useful for email organization with filters, for example. | + +### X-GitLab-NotificationReason[](#x-gitlab-notificationreason "Permalink") + +`X-GitLab-NotificationReason`标头包含`X-GitLab-NotificationReason`的原因. 该值是按优先级顺序的以下值之一: + +* `own_activity` +* `assigned` +* `mentioned` + +通知的原因也包含在通知电子邮件的页脚中. 例如有原因的电子邮件`assigned`都会有这句话的注脚: + +* `You are receiving this email because you have been assigned an item on .` + +**注意:**正在考虑将其他事件的通知包含在`X-GitLab-NotificationReason`标头中. 有关详细信息,请参见此[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/20689) . \ No newline at end of file diff --git a/_book/docs/411.md b/_book/docs/411.md new file mode 100644 index 0000000000000000000000000000000000000000..240ac323635d29bc6e1542eb7c9eb6dac0a39072 --- /dev/null +++ b/_book/docs/411.md @@ -0,0 +1,106 @@ +# GitLab Quick Actions + +> 原文:[https://docs.gitlab.com/ee/user/project/quick_actions.html](https://docs.gitlab.com/ee/user/project/quick_actions.html) + +* [Quick Actions for issues, merge requests and epics](#quick-actions-for-issues-merge-requests-and-epics) +* [Autocomplete characters](#autocomplete-characters) +* [Quick actions parameters](#quick-actions-parameters) +* [Quick actions for commit messages](#quick-actions-for-commit-messages) + +# GitLab Quick Actions[](#gitlab-quick-actions "Permalink") + +版本历史 + +* 在[GitLab 12.1 中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26672)引入:一旦执行了一项操作,成功执行快速操作后将显示一条警报. +* 在[GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/16877)和更高版本中,您可以在更新问题,史诗和合并请求的描述时使用快速操作. + +快速操作是针对问题,史诗,合并请求和提交的常见操作的文本快捷方式,通常可通过在 GitLab 用户界面中单击按钮或下拉菜单来完成. 您可以在说明中或问题,史诗,合并请求和提交的注释中输入这些命令. 每个命令应放在单独的行上,以便正确检测和执行. + +## Quick Actions for issues, merge requests and epics[](#quick-actions-for-issues-merge-requests-and-epics "Permalink") + +以下快速操作适用于其中的描述,讨论和主题: + +* Issues +* 合并要求 +* Epics + +| Command | Issue | 合并要求 | Epic | Action | +| --- | --- | --- | --- | --- | +| `/approve` |   | ✓ |   | 批准合并请求. | +| `/assign @user` | ✓ | ✓ |   | 分配一个用户. | +| `/assign @user1 @user2` | ✓ | ✓ |   | 分配多个用户. | +| `/assign me` | ✓ | ✓ |   | 分配自己. | +| `/award :emoji:` | ✓ | ✓ | ✓ | 切换表情符号奖. | +| `/child_epic ` |   |   | ✓ | 将子史诗添加到`` . ``值的格式应为`&epic` , `group&epic`或`group&epic`的 URL( [在 GitLab 12.0 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7330) ). | +| `/clear_weight` | ✓ |   |   | 净重. | +| `/close` | ✓ | ✓ | ✓ | Close. | +| `/confidential` | ✓ |   |   | 保密. | +| `/copy_metadata ` | ✓ | ✓ |   | 从项目中的另一个合并请求中复制标签和里程碑. | +| `/copy_metadata <#issue>` | ✓ | ✓ |   | Copy labels and milestone from another issue in the project. | +| `/create_merge_request ` | ✓ |   |   | 从当前问题开始创建一个新的合并请求. | +| `/done` | ✓ | ✓ | ✓ | 将待办事项标记为已完成. | +| `/due ` | ✓ |   |   | 设置截止日期. 有效的``示例包括`in 2 days` ( `this Friday`和`December 31st` . | +| `/duplicate <#issue>` | ✓ |   |   | 关闭此问题,并将其标记为另一个问题的副本. 另外,将两者都标记为相关. | +| `/epic ` | ✓ |   |   | 添加到史诗`` . ``值的格式应为`&epic` , `group&epic`或`group&epic`的 URL. | +| `/estimate <w
    d h m>` | ✓ | ✓ |   | 设置时间估计. 例如, `/estimate 1w 3d 2h 14m` . | +| `/iteration *iteration:iteration` | ✓ |   |   | 设置迭代( [在 GitLab 13.1 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/196795) ) | +| `/label ~label1 ~label2` | ✓ | ✓ | ✓ | 添加一个或多个标签. 标签名称也可以不使用波浪号( `~` )开头,但是不支持混合语法. | +| `/lock` | ✓ | ✓ |   | 锁定螺纹. | +| `/merge` |   | ✓ |   | 合并更改. 根据项目设置,这可能是[管道成功](merge_requests/merge_when_pipeline_succeeds.html) ,添加到" [合并火车](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html) "等时. | +| `/milestone %milestone` | ✓ | ✓ |   | 设定里程碑. | +| `/move ` | ✓ |   |   | 将此问题移到另一个项目. | +| `/parent_epic ` |   |   | ✓ | 将父级史诗设置为`` . ``值的格式应为`&epic` , `group&epic`或`group&epic`的 URL( [在 GitLab 12.1 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/10556) ). | +| `/promote` | ✓ |   |   | 将问题升级为史诗. | +| `/publish` | ✓ |   |   | 将问题发布到关联的[状态页](status_page/index.html) ( [在 GitLab 13.0 中引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30906) ) | +| `/reassign @user1 @user2` | ✓ | ✓ |   | 更改受让人. | +| `/relabel ~label1 ~label2` | ✓ | ✓ | ✓ | 用指定的标签替换现有的标签. | +| `/relate #issue1 #issue2` | ✓ |   |   | 将问题标记为相关. | +| `/remove_child_epic ` |   |   | ✓ | 从``删除儿童史诗. ``值的格式应为`&epic` , `group&epic`或`group&epic`的 URL( [在 GitLab 12.0 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7330) ). | +| `/remove_due_date` | ✓ |   |   | 删除到期日. | +| `/remove_epic` | ✓ |   |   | 从史诗中删除. | +| `/remove_estimate` | ✓ | ✓ |   | 删除时间估计. | +| `/remove_iteration` | ✓ |   |   | 删除迭代( [在 GitLab 13.1 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/196795) ) | +| `/remove_milestone` | ✓ | ✓ |   | 删除里程碑. | +| `/remove_parent_epic` |   |   | ✓ | 从史诗中删除父史诗( [在 GitLab 12.1 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/10556) ). | +| `/remove_time_spent` | ✓ | ✓ |   | 消除花费的时间. | +| `/remove_zoom` | ✓ |   |   | 从此问题中删除 Zoom 会议( [在 GitLab 12.4 中引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16609) ). | +| `/reopen` | ✓ | ✓ | ✓ | Reopen. | +| `/shrug ` | ✓ | ✓ | ✓ | 将注释附加到`¯\_(ツ)_/¯` . | +| `/spend h m)> )>` | ✓ | ✓ |   | 减去花费的时间. (可选)指定花费时间的日期. 例如`/spend time(-1h 30m)`或`/spend time(-1h 30m) date(2018-08-26)` . | +| `/spend h m)> )>` | ✓ | ✓ |   | 增加花费的时间. (可选)指定花费时间的日期. 例如`/spend time(1h 30m)`或`/spend time(1h 30m) date(2018-08-26)` . | +| `/submit_review` |   | ✓ |   | Submit a pending review ([introduced in GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/issues/8041)). | +| `/subscribe` | ✓ | ✓ | ✓ | 订阅通知. | +| `/tableflip ` | ✓ | ✓ | ✓ | 在`(╯°□°)╯︵ ┻━┻`添加注释. | +| `/target_branch ` |   | ✓ |   | 设置目标分支. | +| `/title ` | ✓ | ✓ | ✓ | 更改标题. | +| `/todo` | ✓ | ✓ | ✓ | 添加待办事项. | +| `/unassign @user1 @user2` | ✓ | ✓ |   | 删除特定的受让人. | +| `/unassign` | ✓ | ✓ |   | 删除所有受让人. | +| `/unlabel ~label1 ~label2` or `/remove_label ~label1 ~label2` | ✓ | ✓ | ✓ | 删除所有或特定标签. | +| `/unlock` | ✓ | ✓ |   | 解锁线程. | +| `/unsubscribe` | ✓ | ✓ | ✓ | 退订通知. | +| `/weight ` | ✓ |   |   | 设定重量. 为有效选项``包括`0` , `1` , `2` ,依此类推. | +| `/wip` |   | ✓ |   | 切换"进行中"状态. | +| `/zoom ` | ✓ |   |   | 将 Zoom [Meeting](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16609)添加到此问题( [在 GitLab 12.4 中引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16609) ). | + +## Autocomplete characters[](#autocomplete-characters "Permalink") + +许多快速操作都需要一个参数,例如:用户名,里程碑和标签. 与从列表中选择项目相比, [自动完成字符](autocomplete_characters.html)可以使输入参数更加容易. + +## Quick actions parameters[](#quick-actions-parameters "Permalink") + +设置快速操作参数的最简单方法是使用自动完成功能. 如果您手动输入参数,则该参数必须用双引号( `"` )括起来,除非它仅包含以下字符: + +1. ASCII 字母. +2. 数字(0-9). +3. 下划线( `_` ),连字符( `-` ),问号( `?` ),点( `.` )或`&` ( `&` ). + +参数也区分大小写. 自动完成功能会自动处理此问题,并自动插入引号. + +## Quick actions for commit messages[](#quick-actions-for-commit-messages "Permalink") + +以下快速操作适用于提交消息: + +| Command | Action | +| --- | --- | +| `/tag v1.2.3 ` | 使用可选消息标记此提交 | \ No newline at end of file diff --git a/_book/docs/412.md b/_book/docs/412.md new file mode 100644 index 0000000000000000000000000000000000000000..3635b2e3935b0a8e751d1828e06c610c8cd2ddeb --- /dev/null +++ b/_book/docs/412.md @@ -0,0 +1,45 @@ +# Autocomplete characters + +> 原文:[https://docs.gitlab.com/ee/user/project/autocomplete_characters.html](https://docs.gitlab.com/ee/user/project/autocomplete_characters.html) + +* [Example](#example) + +# Autocomplete characters[](#autocomplete-characters "Permalink") + +自动完成字符提供了一种在 Markdown 字段中输入字段值的快速方法. 当您开始在 Markdown 字段中使用以下字符之一键入单词时,GitLab 将针对一组匹配值逐步自动完成. 字符串匹配不区分大小写. + +| Character | Autocompletes | +| --- | --- | +| `~` | Labels | +| `%` | Milestones | +| `@` | 用户和组 | +| `#` | Issues | +| `!` | 合并要求 | +| `&` | Epics | +| `$` | Snippets | +| `:` | Emoji | +| `/` | 快速行动 | + +弹出列表中最多显示 5 个最相关的匹配项. 当您从列表中选择一个项目时,该值将输入到该字段中. 输入的字符越多,匹配项就越精确. + +与" [快速操作"](quick_actions.html)结合使用时,自动完成字符很有用. + +## Example[](#example "Permalink") + +假设您的 GitLab 实例包括以下用户: + +| Username | Name | +| --- | --- | +| alessandra | 罗斯·格兰特 | +| lawrence.white | 凯尔西·克鲁克 | +| leanna | 罗斯玛丽·罗甘(Rosemarie Rogahn) | +| logan_gutkowski | 李·沃克特 | +| shelba | 约瑟芬·海利 | + +在"问题"注释中,输入`@l`将显示以下弹出列表. 请注意,不包括用户`shelba` ,因为该列表仅包含与问题最相关的 5 个用户. + +[![Popup list which includes users whose username or name contains the letter `l`](img/7b1af71091089deb54dbd357d9679d9c.png)](img/autocomplete_characters_example1_v12_0.png) + +如果继续输入`@le` ,弹出列表将更改为以下内容. 现在,弹出窗口仅包括用户名中出现`le`或用户名中的单词的用户. + +[![Popup list which includes users whose username or name contains the string `le`](img/09a583a4343d2359d87040afc14139dd.png)](img/autocomplete_characters_example2_v12_0.png) \ No newline at end of file diff --git a/_book/docs/413.md b/_book/docs/413.md new file mode 100644 index 0000000000000000000000000000000000000000..305f9b1b62feddd8594b890515f9cf50447c9332 --- /dev/null +++ b/_book/docs/413.md @@ -0,0 +1,92 @@ +# Reserved project and group names + +> 原文:[https://docs.gitlab.com/ee/user/reserved_names.html](https://docs.gitlab.com/ee/user/reserved_names.html) + +* [Reserved project names](#reserved-project-names) +* [Reserved group names](#reserved-group-names) + +# Reserved project and group names[](#reserved-project-and-group-names "Permalink") + +并非所有项目和组名都被允许,因为它们会与 GitLab 使用的现有路由冲突. + +有关不允许用作组名或项目名的单词的列表,请参阅`TOP_LEVEL_ROUTES` , `PROJECT_WILDCARD_ROUTES`和`GROUP_ROUTES`列表下的[`path_regex.rb`文件](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/path_regex.rb) : + +* `TOP_LEVEL_ROUTES` :是保留为用户名或顶级组的名称 +* `PROJECT_WILDCARD_ROUTES` :是为子组或项目保留的名称. +* `GROUP_ROUTES` :是为所有组或项目保留的名称. + +## Reserved project names[](#reserved-project-names "Permalink") + +当前无法创建具有以下名称的项目: + +* `\-` +* `badges` +* `blame` +* `blob` +* `builds` +* `commits` +* `create` +* `create_dir` +* `edit` +* `environments/folders` +* `files` +* `find_file` +* `gitlab-lfs/objects` +* `info/lfs/objects` +* `new` +* `preview` +* `raw` +* `refs` +* `tree` +* `update` +* `wikis` + +## Reserved group names[](#reserved-group-names "Permalink") + +当前,以下名称保留为顶级组: + +* `\-` +* `.well-known` +* `404.html` +* `422.html` +* `500.html` +* `502.html` +* `503.html` +* `abuse_reports` +* `admin` +* `api` +* `apple-touch-icon-precomposed.png` +* `apple-touch-icon.png` +* `assets` +* `autocomplete` +* `dashboard` +* `deploy.html` +* `explore` +* `favicon.ico` +* `favicon.png` +* `files` +* `groups` +* `health_check` +* `help` +* `import` +* `invites` +* `jwt` +* `login` +* `oauth` +* `profile` +* `projects` +* `public` +* `robots.txt` +* `s` +* `search` +* `sent_notifications` +* `slash-command-logo.png` +* `snippets` +* `unsubscribes` +* `uploads` +* `users` +* `v2` + +这些组名不能用作子组名: + +* `\-` \ No newline at end of file diff --git a/_book/docs/414.md b/_book/docs/414.md new file mode 100644 index 0000000000000000000000000000000000000000..179795c525a219da28846844b658b99fbeb92366 --- /dev/null +++ b/_book/docs/414.md @@ -0,0 +1,193 @@ +# Search through GitLab + +> 原文:[https://docs.gitlab.com/ee/user/search/](https://docs.gitlab.com/ee/user/search/) + +* [Issues and merge requests](#issues-and-merge-requests) + * [Issues and MRs assigned to you or created by you](#issues-and-mrs-assigned-to-you-or-created-by-you) + * [Filtering issue and merge request lists](#filtering-issue-and-merge-request-lists) + * [Filtering by **None** / **Any**](#filtering-by-none--any) + * [Searching for specific terms](#searching-for-specific-terms) + * [Filtering by ID](#filtering-by-id) + * [Filtering merge requests by approvers](#filtering-merge-requests-by-approvers-starter) + * [Filtering merge requests by “approved by”](#filtering-merge-requests-by-approved-by-starter) +* [Filters autocomplete](#filters-autocomplete) +* [Search history](#search-history) +* [Removing search filters](#removing-search-filters) +* [Filtering with multiple filters of the same type](#filtering-with-multiple-filters-of-the-same-type) +* [Shortcut](#shortcut) +* [To-Do List](#to-do-list) +* [Projects](#projects) +* [Groups](#groups) +* [Issue Boards](#issue-boards) +* [Advanced Global Search](#advanced-global-search-starter) +* [Advanced Syntax Search](#advanced-syntax-search-starter) + +# Search through GitLab[](#search-through-gitlab "Permalink") + +## Issues and merge requests[](#issues-and-merge-requests "Permalink") + +要搜索问题并合并多个项目中的请求,可以使用屏幕右上角的" **问题"**或" **合并请求"**链接. + +它们两者都以相同的方式工作,因此,以下说明对两者均有效. + +右边显示的数字代表分配给您的问题和合并请求的数量. + +[![issues and MRs dashboard links](img/d0143a44aad793332527a786d79524f7.png)](img/dashboard_links.png) + +点击**问题时** ,您会立即看到分配给您的未解决问题: + +[![Issues assigned to you](img/41371f9efeaf03eb888ba8e19a486185.png)](img/issues_assigned_to_you.png) + +You can search through **Open**, **Closed**, or **All** issues. + +您还可以使用搜索和过滤器字段过滤结果,如下面的[过滤问题和合并请求列表中所述](#filtering-issue-and-merge-request-lists) . + +### Issues and MRs assigned to you or created by you[](#issues-and-mrs-assigned-to-you-or-created-by-you "Permalink") + +您还可以在屏幕右上角的搜索字段中找到问题的快捷方式,并合并由您创建或分配给您的请求: + +[![shortcut to your issues and mrs](img/a223e320ef570ec303a4e7346a899af7.png)](img/issues_mrs_shortcut.png) + +### Filtering issue and merge request lists[](#filtering-issue-and-merge-request-lists "Permalink") + +请按照以下步骤筛选项目和组中的" **问题**和**合并请求"**列表页面: + +1. 单击字段**搜索或过滤结果…** . +2. 在出现的下拉菜单中,选择您要过滤的属性: + * 作者 + * 受让人 + * [里程碑](../project/milestones/index.html) + * 释放 + * [标签](../project/labels.html) + * 我的反应 + * 机密 + * Epic(在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) ),包括[儿童史诗](../group/epics/index.html#multi-level-child-epics-ultimate) (在[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) ) + * 搜索此文字 +3. 选择或键入用于过滤属性的运算符. 可以使用以下运算符: + * `=` :是 + * `!=` :不是(在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/18059) ) +4. 输入文本以按[过滤属性](#filters-autocomplete) . +5. 重复此过程以按多个属性进行过滤. 多个属性通过逻辑`AND` . + +例如,按作者`=` Jane 和 Milestone `!=` 12.6 进行过滤,以解决 Jane 是作者而里程碑不是 12.6 的问题. + +[![filter issues in a project](img/9570df3750a76ee8a88eddb48512daa3.png)](img/issue_search_filter_v12_7.png) + +### Filtering by **None** / **Any**[](#filtering-by-none--any "Permalink") + +一些过滤字段(例如里程碑和受让人)允许您按**None**或**Any**进行过滤. + +[![filter by none any](img/e1f4f357a93d9362f282810a575d73e3.png)](img/issues_filter_none_any.png) + +选择" **无"**将返回该字段为空值的结果. 例如:没有里程碑,没有受让人. + +选择" **任意** "则相反. 它返回该字段具有非空值的结果. + +### Searching for specific terms[](#searching-for-specific-terms "Permalink") + +您可以按标题或说明中包含的特定术语过滤问题并合并请求. + +* Syntax + * 搜索以任何顺序查找查询中的所有单词. 例如:搜索问题以寻找`display bug` ,将以任何顺序返回匹配这两个单词的所有问题. + * 要找到确切的术语,请使用双引号: `"display bug"` +* Limitation + * 出于性能原因,少于 3 个字符的术语将被忽略. 例如:搜索问题`included in titles`是一样`included titles` + * 每个查询只能搜索 4096 个字符和 64 个字词. + +[![filter issues by specific terms](img/e336833accfac93c8ed18718b667dab5.png)](img/issue_search_by_term.png) + +### Filtering by ID[](#filtering-by-id "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39908) . + +您可以按 ID 将" **问题"**列表过滤到单个实例. 例如,输入过滤器`#10`仅返回问题 10.这同样适用于" **合并请求"**列表. 输入过滤器`#30`以仅返回合并请求 30. + +[![filter issues by specific id](img/1dcfd40d9306c4cfb80013c0cebdcac0.png)](img/issue_search_by_id.png) + +### Filtering merge requests by approvers[](#filtering-merge-requests-by-approvers-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9468) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.9. + +要过滤单个批准者的合并请求,您可以键入(或从下拉列表中选择) **批准者**并选择用户. + +[![Filter MRs by an approver](img/5ec08a62b534de16956701e85c41e6b5.png)](img/filter_approver_merge_requests.png) + +### Filtering merge requests by “approved by”[](#filtering-merge-requests-by-approved-by-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30335) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.0. + +要过滤已由特定个人批准的合并请求,您可以键入(或从下拉列表中选择)" **批准",**然后选择用户. + +[![Filter MRs by approved by](img/fe213f080418c1bd6d92faa7e49770d3.png)](img/filter_approved_by_merge_requests_v13_0.png) + +## Filters autocomplete[](#filters-autocomplete "Permalink") + +GitLab 在许多页面(问题,合并请求,史诗和管道等)中提供了许多过滤器,您可以使用它们来缩小搜索范围. 使用过滤器功能时,可以开始键入字符以显示相关用户或其他属性. + +为了优化性能,至少需要三个字符才能开始搜索. 例如,如果您要搜索受让人" Simone Presley"的问题,则您需要至少键入" Sim",然后自动完成才能给出任何相关结果. + +## Search history[](#search-history "Permalink") + +您可以通过单击搜索输入左侧的小箭头图标来查看最近的搜索. 单击搜索条目以再次运行该搜索. 此功能可用于问题和合并请求. 搜索结果存储在本地浏览器中. + +[![search history](img/3863add8513c90ad786112f7a200a568.png)](img/search_history.gif) + +## Removing search filters[](#removing-search-filters "Permalink") + +单击过滤器的(x)按钮或退格可以删除单个过滤器. 整个搜索过滤器可以通过点击搜索框的(X)按钮,或通过`⌘`键`(Mac)+⌫`被清除. + +要一次删除一个过滤器令牌,可以使用`⌥` (Mac)/ `Ctrl` + `⌫`键盘组合. + +## Filtering with multiple filters of the same type[](#filtering-with-multiple-filters-of-the-same-type "Permalink") + +某些过滤器可以多次添加. 这些包括但不限于受让人和标签. 当使用相同类型的多个过滤器进行过滤时,将应用"与"逻辑. 例如,如果您要过滤`assignee:@sam assignee:@sarah` ,那么您的结果将仅包含将受让人分配给 Sam 和 Sarah 的条目. + +[![multiple assignees filtering](img/1165fee2238c55848aeb09d59c76cf7b.png)](img/multiple_assignees.png) + +## Shortcut[](#shortcut "Permalink") + +您还可以在项目仪表板右上方的搜索字段中找到快捷方式,以快速访问问题并合并在该项目中创建或分配给您的请求: + +[![search per project - shortcut](img/3001efd4ffb849af0c15eb8dda4d4050.png)](img/project_search.png) + +## To-Do List[](#to-do-list "Permalink") + +可以通过"待办事项"和"完成"来搜索您[的待办事项列表](../todos.html#gitlab-to-do-list) . 您可以按项目,作者,类型和操作[过滤](../todos.html#filtering-your-to-do-list)它们. 另外,您可以按[**标签优先级**](../../user/project/labels.html#label-priority) , **最后创建**和**最早创建**对其进行排序. + +## Projects[](#projects "Permalink") + +您可以从左侧菜单中搜索项目,方法是依次点击菜单栏和**项目** . 在" **按名称过滤** "字段上,输入要查找的项目或组名称,GitLab 会在您键入时为您过滤它们. + +你也可以去找你的项目[出演](../project/index.html#star-a-project) ( **加星标的项目** ),并**探索**所有的公共和内部项目 GitLab.com 可用,从中你可以通过可视性筛选,通过**趋势** ,最好与**大多数明星**评分,或他们的**全部** . + +您还可以按**名称** , **最后创建** , **最旧创建** , **最后更新** , **最新更新** , **所有者**对它们进行排序,并选择隐藏或显示**已归档的项目** : + +[![sort projects](img/7ff67c276870da733a9bc04b2aa9d969.png)](img/sort_projects.png) + +## Groups[](#groups "Permalink") + +Similarly to [projects search](#projects), you can search through your groups from the left menu, by clicking the menu bar, then **Groups**. + +在" **按名称过滤** "字段上,输入要查找的组名,GitLab 将在您键入时为您过滤它们. + +您也可以**浏览**所有的公共和 GitLab.com 可用的内部组,您可以按照**最新创建的** , **最早建立** , **最后更新** ,或**最早的更新** . + +## Issue Boards[](#issue-boards "Permalink") + +在[问题板上](../../user/project/issue_board.html) ,您可以按**作者** , **受让人** , **里程碑**和**标签**过滤问题. 您还可以从键入时加载的字段中**按名称过滤** (按名称)(问题标题). + +当您要搜索要添加到**问题**面板中列表中的问题时,请点击屏幕右上角的**添加问题**按钮,打开一个模态窗口,除了按**名称**过滤它们之外,您还可以从中找到一个模式窗口**作者** , **受让人** , **里程碑**和**标签** ,选择多个问题以添加到您选择的列表中: + +[![search and select issues to add to board](img/e57526dd100a1b0a33bdae55e3bf32c7.png)](img/search_issues_board.png) + +## Advanced Global Search[](#advanced-global-search-starter "Permalink") + +利用 Elasticsearch 在整个 GitLab 实例上进行更快,更高级的代码搜索. + +[Learn how to use the Advanced Global Search.](advanced_global_search.html) + +## Advanced Syntax Search[](#advanced-syntax-search-starter "Permalink") + +使用高级查询获得更具针对性的搜索结果. + +[Learn how to use the Advanced Syntax Search.](advanced_search_syntax.html) \ No newline at end of file diff --git a/_book/docs/415.md b/_book/docs/415.md new file mode 100644 index 0000000000000000000000000000000000000000..93e6acbba1d41a7c1e08704776b5cd8b2f1432b9 --- /dev/null +++ b/_book/docs/415.md @@ -0,0 +1,59 @@ +# Advanced Global Search + +> 原文:[https://docs.gitlab.com/ee/user/search/advanced_global_search.html](https://docs.gitlab.com/ee/user/search/advanced_global_search.html) + +* [Overview](#overview) +* [Use cases](#use-cases) + * [Faster searches](#faster-searches) + * [Promote innersourcing](#promote-innersourcing) +* [Searching globally](#searching-globally) + +# Advanced Global Search[](#advanced-global-search-starter-only "Permalink") + +版本历史 + +* 在 GitLab [Starter](https://about.gitlab.com/pricing/) 8.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109) . + +**GitLab.com 的可用性:**高级全局搜索(由 Elasticsearch 支持)在 GitLab.com 上尚不可用. 它将在 2020 年第三季度为所有付费群体逐步启用.请[遵循此史诗](https://gitlab.com/groups/gitlab-com/-/epics/649) ,以获取时间表上的最新更新. + +利用 Elasticsearch 在整个 GitLab 实例上进行更快,更高级的代码搜索. + +这是用户文档. 要安装和配置 Elasticsearch,请访问[管理员文档](../../integration/elasticsearch.html) . + +## Overview[](#overview "Permalink") + +GitLab 中的 Advanced Global Search 是一项功能强大的搜索服务,可以节省您的时间. 现在,您可以在其他团队中搜索可以为您自己的项目提供帮助的代码,而不必创建重复的代码和浪费时间. + +manbetx 客户端打不开利用[Elasticsearch](https://www.elastic.co/elasticsearch/)的搜索功能,并在搜索时启用它: + +* Projects +* Repositories +* Commits +* Issues +* 合并要求 +* Milestones +* 注释(评论) +* Snippets +* Wiki + +## Use cases[](#use-cases "Permalink") + +高级全局搜索在各种情况下都非常有用. + +### Faster searches[](#faster-searches "Permalink") + +如果您要处理大量数据,并希望保持 GitLab 的快速搜索,高级全局搜索将帮助您实现这一目标. + +### Promote innersourcing[](#promote-innersourcing "Permalink") + +您的公司可能由许多不同的开发人员团队组成,每个开发人员团队都有各自的团队来托管各种项目. 您的某些应用程序可能会相互连接,因此您的开发人员需要立即在整个 GitLab 实例中进行搜索并找到他们搜索的代码. + +## Searching globally[](#searching-globally "Permalink") + +像以前一样使用搜索,GitLab 会向您显示您有权访问的每个项目中的匹配代码. + +[![Advanced Global Search](img/a3626522e1409168b7c977ecebbaee6e.png)](img/advanced_global_search.png) + +您还可以使用提供一些有用查询的[高级语法搜索](advanced_search_syntax.html) . + +**注意:** Elasticsearch 仅具有默认分支的数据. 这意味着,如果您转到存储库树并将分支从默认分支切换到其他分支,那么即使启用了 Elasticsearch,常规搜索也会提供搜索结果页面中的"代码"选项卡. \ No newline at end of file diff --git a/_book/docs/416.md b/_book/docs/416.md new file mode 100644 index 0000000000000000000000000000000000000000..b317aded91bfb32efaaeb4c2a604d1746f036e3e --- /dev/null +++ b/_book/docs/416.md @@ -0,0 +1,66 @@ +# Advanced Syntax Search + +> 原文:[https://docs.gitlab.com/ee/user/search/advanced_search_syntax.html](https://docs.gitlab.com/ee/user/search/advanced_search_syntax.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Using the Advanced Syntax Search](#using-the-advanced-syntax-search) + * [Syntax search filters](#syntax-search-filters) + +# Advanced Syntax Search[](#advanced-syntax-search-starter "Permalink") + +版本历史 + +* 在[GitLab Enterprise Starter](https://about.gitlab.com/pricing/) 9.2 中引入 + +**GitLab.com 可用性:**自 2020-07-10 起,在 GitLab.com 上启用了 Bronze 及更高版本的 Advanced Global Search(由 Elasticsearch 支持). + +使用高级查询获得更具针对性的搜索结果. + +这是用户文档. 要安装和配置 Elasticsearch,请访问[管理员文档](../../integration/elasticsearch.html) . + +## Overview[](#overview "Permalink") + +"高级语法搜索"是" [高级全局搜索"](advanced_global_search.html)的子集,如果您想要更具体的搜索结果,可以使用它. + +Advanced Global Search 仅支持搜索[默认分支](../project/repository/branches/index.html#default-branch) . + +## Use cases[](#use-cases "Permalink") + +例如,假设您开发的产品依赖于另一个组中托管的另一种产品的代码. + +由于在您的 GitLab 实例下托管了数百个不同的项目,因此您需要搜索结果尽可能地高效. 您对要查找的内容有感觉(例如,函数名),但是同时您也不太确定. + +在这种情况下,在查询中使用高级搜索语法将产生更好的结果. + +## Using the Advanced Syntax Search[](#using-the-advanced-syntax-search "Permalink") + +高级语法搜索支持带有前缀,布尔运算符等的模糊或精确搜索查询. + +可以在[Elasticsearch 文档中](https://www.elastic.co/guide/en/elasticsearch/reference/5.3/query-dsl-simple-query-string-query.html#_simple_query_string_syntax)找到完整的详细信息,但是这里有一个快速指南: + +* 搜索以任何顺序搜索查询中的所有单词,例如:搜索`display bug`问题将以任何顺序返回匹配这两个单词的所有问题. +* 要查找确切的词组(仍然适用词干),请使用双引号: `"display bug"` +* 要查找未提及显示的错误,请使用`-` : `bug -display` +* 要查找显示或声音中的错误,请使用`|` : `bug display | sound` `bug display | sound` +* 要组术语一起,使用括号: `bug | (display +sound)` `bug | (display +sound)` +* 要匹配部分单词,请使用`*` : `bug find_by_*` +* 要查找包含这些符号之一的术语,请使用`\` : `argument \-last` + +### Syntax search filters[](#syntax-search-filters "Permalink") + +高级语法搜索还支持使用过滤器. 可用的过滤器是: + +* filename:按文件名过滤. 您可以使用 glob( `*` )运算符进行模糊匹配. +* path:按路径过滤. 您可以使用 glob( `*` )运算符进行模糊匹配. +* 扩展名:按扩展名过滤文件名. 请写扩展名,不要带引号. 仅完全匹配. + +要使用它们,只需将它们添加到您的查询格式`:`没有冒号之间的空格( `:` )和值. + +Examples: + +* 查找包含任何名为`hello_world.rb`内容的文件: `* filename:hello_world.rb` +* 查找一个名为`hello_world`的文件,其中包含文本`whatever` : `whatever filename:hello_world` +* 在扩展名为`.rb`文件中查找文本" def create": `def create extension:rb` +* 在名为`encryption`的文件夹中的文件内查找文本`sha` : `sha path:encryption` +* 查找任何以`hello`开头的文件,其中包含`world`并带有`.js`扩展名: `world filename:hello* extension:js` \ No newline at end of file diff --git a/_book/docs/417.md b/_book/docs/417.md new file mode 100644 index 0000000000000000000000000000000000000000..ccba4d2186540c05d73f79f0bf64bfa7f0d5dd68 --- /dev/null +++ b/_book/docs/417.md @@ -0,0 +1,84 @@ +# Time Tracking + +> 原文:[https://docs.gitlab.com/ee/user/project/time_tracking.html](https://docs.gitlab.com/ee/user/project/time_tracking.html) + +* [Overview](#overview) +* [How to enter data](#how-to-enter-data) + * [Estimates](#estimates) + * [Time spent](#time-spent) +* [Configuration](#configuration) + * [Limit displayed units to hours](#limit-displayed-units-to-hours-core-only) +* [Other interesting links](#other-interesting-links) + +# Time Tracking[](#time-tracking "Permalink") + +在 GitLab 8.14 中引入. + +时间跟踪允许您跟踪估计和花费在问题上的时间以及在 GitLab 中合并请求. + +## Overview[](#overview "Permalink") + +时间跟踪使您能够: + +* 记录处理问题或合并请求所花费的时间. +* 添加完成问题或合并请求所需时间的估计. + +您不必输入估算值即可输入花费的时间,反之亦然. + +有关时间跟踪的数据显示在问题/合并请求侧栏上,如下所示. + +[![Time tracking in the sidebar](img/05a0790512923394006a9c3face18d58.png)](img/time_tracking_sidebar_v8_16.png) + +## How to enter data[](#how-to-enter-data "Permalink") + +时间跟踪使用了 GitLab 通过此新功能引入的两个[快速操作](quick_actions.html) : `/spend`和`/estimate` . + +快速操作既可以用于问题或合并请求的正文中,也可以用于问题或合并请求的注释中. + +下面是一个示例,说明如何在评论中使用这些新的快速操作. + +[![Time tracking example in a comment](img/37cb6e38ded4ec606f9bc7776f765e70.png)](img/time_tracking_example_v12_2.png) + +添加时间条目(花费的时间或估计的时间)仅限于项目成员. + +### Estimates[](#estimates "Permalink") + +要输入估算值,请输入`/estimate` ,然后输入时间. 例如,如果您需要输入 3 天 5 小时 10 分钟的估算值,则可以输入`/estimate 3d 5h 10m` . 我们支持的时间单位列在此帮助页面的底部. + +每次输入新的时间估算值时,任何先前的时间估算值都将被该新值覆盖. 在发布或合并请求中应该只有一个有效的估计. + +要完全删除估算,请使用`/remove_estimate` . + +### Time spent[](#time-spent "Permalink") + +要输入花费的时间,请使用`/spend 3d 5h 10m` . + +每个新花费的时间条目将被添加到当前用于发布或合并请求的总时间中. + +您可以通过输入负数来减少时间: `/spend -3d`将从总花费时间中删除 3 天. 您所花费的时间不能少于 0 分钟,因此,如果您删除的时间量与已输入的时间相比更长,则 GitLab 将自动重置所花费的时间. + +要删除一次花费的所有时间,请使用`/remove_time_spent` . + +## Configuration[](#configuration "Permalink") + +以下时间单位可用: + +* 月(mo) +* 周(w) +* Days (d) +* 小时(h) +* 分钟(米) + +默认转换率是 1mo = 4w,1w = 5d 和 1d = 8h. + +### Limit displayed units to hours[](#limit-displayed-units-to-hours-core-only "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29469/) . + +在 GitLab 自我管理实例中,可以通过**"** **本地化** **"**下**"管理">"设置">"首**选项"中的选项将时间单位的显示限制为小时. + +启用此选项后,将显示`75h`而不是`1w 4d 3h` . + +## Other interesting links[](#other-interesting-links "Permalink") + +* [Time Tracking landing page in the GitLab handbook](https://about.gitlab.com/solutions/time-tracking/) \ No newline at end of file diff --git a/_book/docs/418.md b/_book/docs/418.md new file mode 100644 index 0000000000000000000000000000000000000000..55e1daba40cc512edc65b372402bac9de1b5ef2a --- /dev/null +++ b/_book/docs/418.md @@ -0,0 +1,136 @@ +# GitLab To-Do List + +> 原文:[https://docs.gitlab.com/ee/user/todos.html](https://docs.gitlab.com/ee/user/todos.html) + +* [What triggers a To Do](#what-triggers-a-to-do) + * [Directly addressing a To Do](#directly-addressing-a-to-do) + * [Manually creating a To Do](#manually-creating-a-to-do) +* [Marking a To Do as done](#marking-a-to-do-as-done) +* [Filtering your To-Do List](#filtering-your-to-do-list) + +# GitLab To-Do List[](#gitlab-to-do-list "Permalink") + +在 GitLab 8.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2817) . + +当您登录到 GitLab 时,通常需要查看应该花些时间在哪里,采取一些措施或知道需要注意什么而无需大量电子邮件通知. GitLab 是您工作的地方,因此快速入门非常重要. + +待办事项列表在一个简单的仪表板中按时间顺序列出了等待您输入的项目. + +[![To Do screenshot showing a list of items to check on](img/aafa273009fd04415444f040f8b4c6cc.png)](img/todos_index.png) + +通过单击顶部导航中搜索栏旁边的对勾图标,可以快速访问待办事项列表. 如果计数为: + +* 小于 100 的蓝色数字是待办事项的数量. +* 大于或等于 100,则数字显示为 99+. 确切的数字显示在"任务列表"上. 你还有空. 否则,该数字将显示为 99+. 确切的数字显示在"任务列表"上. + +[![To Do icon](img/7f8f5e942a32629817a87b08e33d9071.png)](img/todos_icon.png) + +## What triggers a To Do[](#what-triggers-a-to-do "Permalink") + +在以下情况下,待办事项会显示在您的待办事项列表中: + +* 分配或合并请求已分配给您 +* 在以下内容的描述或评论中`@mentioned`您`@mentioned` : + * 问题 + * 合并请求 + * 史诗 +* 在以下评论中`@mentioned`您: + * 承诺 + * 设计 +* 您的合并请求的 CI / CD 管道失败 +* 由于冲突,一个打开的合并请求变得不可合并,并且满足以下条件之一: + * 你是作者 + * 您是将其设置为在管道成功后自动合并的用户 +* [从 GitLab 13.2 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/12136) ,合并请求将从[合并火车中](../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)删除,您是添加请求的用户. + +待办事项触发器不受[GitLab 通知电子邮件设置的影响](profile/notifications.html) . + +**注意:**当用户不再有权访问与待办事项相关的资源(例如问题,合并请求,项目或组)时,出于安全原因,相关的待办事项将在下一小时内删除. 如果用户的访问被错误地取消,则删除操作会延迟以防止数据丢失. + +### Directly addressing a To Do[](#directly-addressing-a-to-do "Permalink") + +在 GitLab 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7926) . + +如果在一行的开头提到您,则您收到的待办事项将列为"直接处理". 例如,在此注释中: + +``` +@alice What do you think? cc: @bob + - @carol can you please have a look? + >>> +@dan what do you think? +>>> + +@erin @frank thank you! +``` + +接收直接处理的待办事项的人是`@alice` , `@erin`和`@frank` . 直接寻址的待办事项仅出于过滤目的而与提及事项有所不同; 否则,它们显示为正常. + +### Manually creating a To Do[](#manually-creating-a-to-do "Permalink") + +您还可以通过在以下位置单击" **添加待办事项"**按钮,将以下内容添加到"待办事项列表": + +* Issue +* 合并请求 +* Epic + +[![Adding a To Do from the issuable sidebar](img/f44886a0dc98ed48e0854c7d2ac6a220.png)](img/todos_add_todo_sidebar.png) + +## Marking a To Do as done[](#marking-a-to-do-as-done "Permalink") + +采取以下任何措施都会将相应的待办事项标记为已完成: + +* Issue +* 合并请求 +* Epic + +取消待办事项的动作包括: + +* 更换受让人 +* 改变里程碑 +* 添加/删除标签 +* 对这个问题发表评论 + +Your To-Do List is personal, and items are only marked as done if the action comes from you. If you close the issue or merge request, your To Do is automatically marked as done. + +为防止其他用户在不通知您的情况下关闭问题,如果其他人关闭,合并或对以下任何一项采取了措施,则您的待办事项将保持待处理状态: + +* Issue +* 合并要求 +* Epic + +每种情况只有一个待办事项,因此在一个问题中提到用户一百次只会触发一个待办事项. + +如果不需要采取任何措施,您可以通过单击相应的**"完成"**按钮来手动将"待办事项"标记为已完成,该按钮将从您的"待办事项列表"中消失. + +[![A To Do in the To-Do List](img/235fdd047e32990019bc08c92ced8299.png)](img/todos_todo_list_item.png) + +您还可以通过单击以下边栏中的" **标记为已完成"**按钮将"待办事项" **标记为已完成** : + +* Issue +* 合并请求 +* Epic + +[![Mark as done from the issuable sidebar](img/5e63fee9a28bb3e02eb772646de82b5c.png)](img/todos_mark_done_sidebar.png) + +您可以通过单击**全部标记为已完成**按钮将所有待办事项**标记为已完成** . + +## Filtering your To-Do List[](#filtering-your-to-do-list "Permalink") + +您可以在待办事项列表中使用四种过滤器. + +| Filter | Description | +| --- | --- | +| Project | 按项目筛选 | +| Group | 按组筛选 | +| Author | 按触发待办事项的作者过滤 | +| Type | 按问题,合并请求,设计或史诗过滤 | +| Action | 按触发待办事项的动作过滤 | + +您还可以同时按多个过滤条件之一进行过滤. [上面描述了](#what-triggers-a-to-do)可能的操作,包括: + +* 任何行动 +* Assigned +* Mentioned +* Added +* Pipelines +* 直接寻址 \ No newline at end of file diff --git a/_book/docs/419.md b/_book/docs/419.md new file mode 100644 index 0000000000000000000000000000000000000000..9511acca74037624440b708d20758dc38983cd66 --- /dev/null +++ b/_book/docs/419.md @@ -0,0 +1,234 @@ +# Administrator Docs + +> 原文:[https://docs.gitlab.com/ee/administration/](https://docs.gitlab.com/ee/administration/) + +* [Installing and maintaining GitLab](#installing-and-maintaining-gitlab) + * [Installing GitLab](#installing-gitlab) + * [Configuring GitLab](#configuring-gitlab) + * [Customizing GitLab’s appearance](#customizing-gitlabs-appearance) + * [Maintaining GitLab](#maintaining-gitlab) + * [Updating GitLab](#updating-gitlab) + * [Upgrading or downgrading GitLab](#upgrading-or-downgrading-gitlab) + * [GitLab platform integrations](#gitlab-platform-integrations) +* [User settings and permissions](#user-settings-and-permissions) +* [Project settings](#project-settings) +* [Package Registry administration](#package-registry-administration) + * [Repository settings](#repository-settings) +* [Continuous Integration settings](#continuous-integration-settings) +* [Snippet settings](#snippet-settings) +* [Git configuration options](#git-configuration-options) +* [Monitoring GitLab](#monitoring-gitlab) + * [Performance Monitoring](#performance-monitoring) +* [Analytics](#analytics) +* [Troubleshooting](#troubleshooting) + * [Support Team Docs](#support-team-docs) + +# Administrator Docs[](#administrator-docs-core-only "Permalink") + +了解如何管理自己的 GitLab 实例. + +manbetx 客户端打不开有两个产品发行版可以通过[不同的订阅获得](https://about.gitlab.com/pricing/) : + +* 开源[GitLab 社区版(CE)](https://gitlab.com/gitlab-org/gitlab-foss) . +* The open core [GitLab Enterprise Edition (EE)](https://gitlab.com/gitlab-org/gitlab). + +您可以[安装 GitLab CE 或 GitLab EE](https://about.gitlab.com/install/ce-or-ee/) . 但是,您可以使用的功能取决于您选择的订阅(Core,Starter,Premium 或 Ultimate). + +**注意:** GitLab 社区版安装只能访问核心功能. + +GitLab.com 由 GitLab,Inc.管理,因此,只有 GitLab 团队成员才能访问其管理配置. 如果您是 GitLab.com 用户,请检查[用户文档](../user/index.html) . + +**注意:**非管理员用户无权访问 GitLab 管理工具和设置. + +## Installing and maintaining GitLab[](#installing-and-maintaining-gitlab "Permalink") + +了解如何安装,配置,更新和维护您的 GitLab 实例. + +### Installing GitLab[](#installing-gitlab "Permalink") + +* [安装](../install/README.html) :要求,目录结构和安装方法. + * [数据库负载平衡](database_load_balancing.html) :在多个数据库服务器之间分配数据库查询. + * [Omnibus 支持日志转发](https://docs.gitlab.com/omnibus/settings/logs.html) +* [参考体系结构](reference_architectures/index.html) :添加其他资源以支持更多用户. + * [在 Amazon Web Services(AWS)上安装 GitLab](../install/aws/index.html) :在 Amazon AWS 上设置 GitLab. +* [地理位置](geo/replication/index.html) :将 GitLab 实例复制到其他地理位置,作为只读的完全可操作版本. +* [灾难恢复](geo/disaster_recovery/index.html) :在灾难情况下,只需最少的精力即可快速故障转移到其他站点. +* [Pivotal Tile](../install/pivotal/index.html) :使用用于 Pivotal Cloud Foundry 的 Ops Manager(BOSH)将 GitLab 部署为预配置的设备. +* [添加许可证](../user/admin_area/license.html) :在安装时上传许可证以解锁 GitLab 付费层中的功能. + +### Configuring GitLab[](#configuring-gitlab "Permalink") + +* [调整实例的时区](timezone.html) :定制 GitLab 的默认时区. +* [系统挂钩](../system_hooks/system_hooks.html) :更改用户,项目和键时的通知. +* [安全性](../security/README.html) :了解如何进一步保护 GitLab 实例. +* [使用情况统计信息,版本检查和使用情况 ping](../user/admin_area/settings/usage_statistics.html) :启用或禁用有关要发送到 GitLab,Inc.的实例的信息. +* [全局用户设置](user_settings.html) :配置实例范围的用户权限. +* [轮询](polling.html) :配置 GitLab UI 轮询更新的频率. +* [GitLab 页面配置](pages/index.html) :启用和配置 GitLab 页面. +* [用于 GitLab 源代码安装的 GitLab Pages 配置](pages/source.html) :在[源代码安装](../install/installation.html#installation-from-source)上启用和配置 GitLab Pages. +* [上传管理](uploads.html) :配置 GitLab 上传存储. +* [环境变量](environment_variables.html) :受支持的环境变量,可用于覆盖其默认值以配置 GitLab. +* [插件](plugins.html) :使用自定义插件,GitLab 管理员可以引入自定义集成,而无需修改 GitLab 的源代码. +* [Enforcing Terms of Service](../user/admin_area/settings/terms.html) +* [Third party offers](../user/admin_area/settings/third_party_offers.html) +* [合规性](compliance.html) :您可以配置整个应用程序中的功能集合,以帮助确保您的 GitLab 实例和 DevOps 工作流程符合合规性标准. +* 差异[限制](../user/admin_area/diff_limits.html) :配置分支比较页面的差异渲染大小限制. +* [合并请求差异存储](merge_request_diffs.html) :配置合并请求差异外部存储. +* [广播消息](../user/admin_area/broadcast_messages.html) :通过 UI 向 GitLab 用户发送消息. +* [Elasticsearch](../integration/elasticsearch.html) :使 Elasticsearch 能够授权 GitLab 的 Advanced Global Search. 当您处理大量数据时很有用. +* [External Classification Policy Authorization](../user/admin_area/settings/external_authorization.html) +* [上载许可证](../user/admin_area/license.html) :上载许可证以解锁 GitLab 付费层中的功能. +* [管理区域](../user/admin_area/index.html) :用于自我管理的实例范围内的配置和维护. +* [S / MIME 签名](smime_signing_email.html) :如何使用 S / MIME 对所有传出的通知电子邮件进行签名. +* [启用和禁用功能标志](feature_flags.html) :如何启用和禁用部署在功能标志后面的 GitLab 功能. + +#### Customizing GitLab’s appearance[](#customizing-gitlabs-appearance "Permalink") + +* [标头徽标](../user/admin_area/appearance.html#navigation-bar) :更改所有页面和电子邮件标头上的徽标. +* [网站](../user/admin_area/appearance.html#favicon)图标:将默认网站图标更改为您自己的徽标. +* [品牌登录页面](../user/admin_area/appearance.html#sign-in--sign-up-pages) :使用您自己的徽标,标题和描述来自定义登录页面. +* ["新项目"页面](../user/admin_area/appearance.html#new-project-pages) :自定义在用户创建新项目时打开的页面上显示的文本. +* [其他自定义电子邮件文本](../user/admin_area/settings/email.html#custom-additional-text-premium-only) :将其他自定义文本添加到从 GitLab 发送的电子邮件中. + +### Maintaining GitLab[](#maintaining-gitlab "Permalink") + +* [瑞克任务](../raketasks/README.html) :执行各种维护,备份,自动 Webhooks 设置等任务. + * [备份和还原](../raketasks/backup_restore.html) :备份和还原您的 GitLab 实例. +* [操作](operations/index.html) :保持 GitLab 正常运行(清理 Redis 会话,移动存储库,Sidekiq MemoryKiller,Puma). +* [重新启动 GitLab](restart_gitlab.html) :了解如何重新启动 GitLab 及其组件. +* [使 Markdown 缓存](invalidate_markdown_cache.html)无效:使所有缓存的 Markdown 无效. + +#### Updating GitLab[](#updating-gitlab "Permalink") + +* [GitLab 版本和维护策略](../policy/maintenance.html) :了解 GitLab 版本和发行版(主要,次要,补丁,安全)以及更新建议. +* [更新 GitLab](../update/README.html) :更新指南将您的安装升级到新版本. +* [无需停机](../update/README.html#upgrading-without-downtime)即可进行[升级:无需中断](../update/README.html#upgrading-without-downtime) GitLab 实例即可升级到较新的主要,次要或补丁版本的 GitLab. +* [将您的 GitLab CI / CD 数据迁移到另一个版本的 GitLab](../migrate_ci_to_ce/README.html) :如果您安装的是旧的 GitLab(版本低于 8.0),请按照本指南将现有的 GitLab CI / CD 数据迁移到另一个版本的 GitLab. + +### Upgrading or downgrading GitLab[](#upgrading-or-downgrading-gitlab "Permalink") + +* [从 GitLab CE 升级到 GitLab EE](../update/README.html#upgrading-between-editions) :了解如何将 GitLab 社区版升级到 GitLab 企业版. +* [从 GitLab EE 降级到 GitLab CE](../downgrade_ee_to_ce/README.html) :了解如何将 GitLab 企业版降级到社区版. + +### GitLab platform integrations[](#gitlab-platform-integrations "Permalink") + +* [Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/) :与[Mattermost](https://mattermost.com)集成, [后者](https://mattermost.com)是一个用于 Web 消息传递的开源私有云工作场所. +* [PlantUML](integration/plantuml.html) :在片段,Wiki 和存储库中创建的 AsciiDoc 和 Markdown 文档中创建简单图. +* [Web 终端](integration/terminal.html) :从 GitLab 的 CI / CD [环境中](../ci/environments/index.html#web-terminals)提供对部署到 Kubernetes 的应用程序的终端访问. + +## User settings and permissions[](#user-settings-and-permissions "Permalink") + +* [创建用户](../user/profile/account/create_accounts.html) :手动或通过身份验证集成创建用户. +* [Libravatar](libravatar.html) :使用 Libravatar 代替 Gravatar 进行用户化身. +* [注册限制](../user/admin_area/settings/sign_up_restrictions.html) :阻止特定域的电子邮件地址,或仅将特定域列入白名单. +* [访问限制](../user/admin_area/settings/visibility_and_access_controls.html#enabled-git-access-protocols) :定义可用于与 GitLab 进行通信的 Git 访问协议(SSH,HTTP,HTTPS). +* [身份验证和授权](auth/README.html) :使用 LDAP,SAML,CAS 和其他提供程序配置外部身份验证. + * [同步 LDAP](auth/ldap/index.html) + * [Kerberos 身份验证](../integration/kerberos.html) + * 另请参阅其他[身份验证](../topics/authentication/index.html#gitlab-administrators)主题(例如,实施 2FA). +* [电子邮件用户](../tools/email.html) :从 GitLab 内部向 GitLab 用户发送电子邮件. +* [用户群组](../user/admin_area/user_cohorts.html) :显示新用户及其在一段时间内的活动的每月群组. +* [审核日志和事件](audit_events.html) :查看在 GitLab 服务器中对以下内容所做的更改: + * 小组和项目. + * 实例. +* [Auditor 用户](auditor_users.html) :对 GitLab 实例上的所有项目,组和其他资源具有只读访问权限的用户. +* [传入电子邮件](incoming_email.html) :配置传入电子邮件,以允许用户[通过电子邮件](reply_by_email.html)进行[答复,通过电子邮件](reply_by_email.html)创建[问题](../user/project/issues/managing_issues.html#new-issue-via-email)以及[通过电子邮件](../user/project/issues/managing_issues.html#new-issue-via-email) [合并请求](../user/project/merge_requests/creating_merge_requests.html#new-merge-request-by-email-core-only) ,以及启用[Service Desk](../user/project/service_desk.html) . + * [传入电子邮件的 Postfix](reply_by_email_postfix_setup.html) :在 Ubuntu 上为传入电子邮件设置具有 IMAP 身份验证的基本 Postfix 邮件服务器. +* [滥用情况报告](../user/admin_area/abuse_reports.html) :查看和解决用户的滥用情况报告. +* [凭证清单](../user/admin_area/credentials_inventory.html) :通过凭证清单,GitLab 管理员可以在其 GitLab 自我管理实例中跟踪其用户使用的凭证. + +## Project settings[](#project-settings "Permalink") + +* [问题关闭模式](issue_closing_pattern.html) :自定义如何从提交消息中关闭问题. +* [Gitaly](gitaly/index.html) :配置 GitLab 的 Git 仓库存储服务 Gitaly. +* [默认标签](../user/admin_area/labels.html) :创建将自动添加到每个新项目的标签. +* [限制使用公共或内部项目](../public_access/public_access.html#restricting-the-use-of-public-or-internal-projects) :限制用户在创建项目或代码段时使用可见性级别. +* [自定义项目模板](../user/admin_area/custom_project_templates.html) :配置一组项目,以在创建新项目时用作自定义模板. + +## Package Registry administration[](#package-registry-administration "Permalink") + +* [容器注册表](packages/container_registry.html) :使用 GitLab 配置容器注册表. +* [软件包注册表](packages/index.html) :使 GitLab 可以充当 NPM 注册表和 Maven 存储库. +* [Dependency Proxy](packages/dependency_proxy.html): Configure the Dependency Proxy, a local proxy for frequently used upstream images/packages. + +### Repository settings[](#repository-settings "Permalink") + +* [仓库检查](repository_checks.html) :定期的 Git 仓库检查. +* [存储库存储路径](repository_storage_paths.html) :管理用于存储存储库的路径. +* [存储库存储类型](repository_storage_types.html) :有关不同存储库存储类型的信息. +* [存储库存储 Rake 任务](raketasks/storage.html) :一组 Rake 任务,用于列出并将与之关联的现有项目和附件从旧版存储迁移到哈希存储. +* [限制存储库大小](../user/admin_area/settings/account_and_limit_settings.html) :设置[存储库大小](../user/admin_area/settings/account_and_limit_settings.html)的硬限制. +* [静态对象外部存储](static_objects_external_storage.html) :为存储库中的静态对象设置外部存储. + +## Continuous Integration settings[](#continuous-integration-settings "Permalink") + +* [启用/禁用 GitLab CI / CD](../ci/enable_or_disable_ci.html#site-wide-admin-setting) :为您的实例启用或禁用 GitLab CI / CD. +* [GitLab CI / CD 管理员设置](../user/admin_area/settings/continuous_integration.html) :在整个站点范围内启用或禁用 Auto DevOps 并定义工件的最大大小和有效时间. +* [外部管道验证](external_pipeline_validation.html) :启用,禁用和配置外部管道验证. +* [作业工件](job_artifacts.html) :启用,禁用和配置作业工件(作业成功完成时输出的一组文件和目录). +* [作业日志](job_logs.html) :有关作业日志的信息. +* [注册跑步者](../ci/runners/README.html#types-of-runners) :了解如何注册和配置跑步者. +* [共享运行程序管道配额](../user/admin_area/settings/continuous_integration.html#shared-runners-pipeline-minutes-quota-starter-only) :限制共享运行程序的管道分钟的使用. +* [启用/禁用 Auto DevOps](../topics/autodevops/index.html#enablingdisabling-auto-devops) :为您的实例启用或禁用 Auto DevOps. + +## Snippet settings[](#snippet-settings "Permalink") + +* [设置](snippets/index.html)摘要[内容的大小限制](snippets/index.html) :设置摘要内容的最大大小限制. + +## Git configuration options[](#git-configuration-options "Permalink") + +* [服务器挂钩](server_hooks.html) :服务器挂钩(在文件系统上),用于当 Webhooks 不够用时. +* [Git LFS 配置](lfs/index.html) :了解如何为 GitLab 配置 LFS. +* [客房整理](housekeeping.html) :保持您的 Git 存储库整洁,快速. +* [配置 Git 协议 v2](git_protocol.html) :支持 Git 协议版本 2. +* [Manage large files with `git-annex` (Deprecated)](git_annex.html) + +## Monitoring GitLab[](#monitoring-gitlab "Permalink") + +* [Monitoring GitLab](monitoring/index.html): + * [监视正常运行时间](../user/admin_area/monitoring/health_check.html) :使用运行状况检查端点检查服务器状态. + * [IP 白名单](monitoring/ip_whitelist.html) :监视在探查时提供健康检查信息的端点. + * [监视 GitHub 导入](monitoring/github_imports.html) :GitLab 的 GitHub 导入器显示 Prometheus 指标以监视导入器的运行状况和进度. + +### Performance Monitoring[](#performance-monitoring "Permalink") + +* [GitLab Performance Monitoring](monitoring/performance/index.html): + * [启用性能监控](monitoring/performance/gitlab_configuration.html) :启用 GitLab 性能监控. + * [使用 Prometheus 监视 GitLab 性能](monitoring/prometheus/index.html) :配置 GitLab 和 Prometheus 以测量性能指标. + * [使用 Grafana 进行 GitLab 性能监视](monitoring/performance/grafana_configuration.html) :配置 GitLab 以通过图形和仪表板可视化时间序列指标. + * [请求分析](monitoring/performance/request_profiling.html) :获取有关慢速请求的详细资料. + * [效果栏](monitoring/performance/performance_bar.html) :获取当前页面的性能信息. + +## Analytics[](#analytics "Permalink") + +* [Pseudonymizer](pseudonymizer.html) :以安全的方式将数据从 GitLab 的数据库导出到 CSV 文件. + +## Troubleshooting[](#troubleshooting "Permalink") + +* [Debugging tips](troubleshooting/debug.html): Tips to debug problems when things go wrong +* [日志系统](logs.html) :在哪里查找日志. +* [Sidekiq 故障排除](troubleshooting/sidekiq.html) :在 Sidekiq 挂起且不处理作业时进行调试. +* [Troubleshooting Elasticsearch](troubleshooting/elasticsearch.html) +* [Navigating GitLab via Rails console](troubleshooting/navigating_gitlab_via_rails_console.html) +* [GitLab application limits](instance_limits.html) + +### Support Team Docs[](#support-team-docs "Permalink") + +GitLab 支持团队已经收集了许多有关对 GitLab 实例进行故障排除的信息. 这些文档通常由支持团队本身使用,或由客户在支持团队成员的直接指导下使用. GitLab 管理员可能会找到有用的信息来进行故障排除,但是如果您在使用 GitLab 实例时遇到麻烦,则应在参考这些文档之前检查[支持选项](https://about.gitlab.com/support/) . + +**警告:**使用下面文档中列出的命令可能会导致数据丢失或对 GitLab 实例的其他损坏,并且仅应由意识到风险的有经验的管理员使用. + +* [Useful diagnostics tools](troubleshooting/diagnostics_tools.html) +* [Useful Linux commands](troubleshooting/linux_cheat_sheet.html) +* [Troubleshooting Kubernetes](troubleshooting/kubernetes_cheat_sheet.html) +* [Troubleshooting PostgreSQL](troubleshooting/postgresql.html) +* [Guide to test environments](troubleshooting/test_environments.html) (for Support Engineers) +* [GitLab Rails 控制台命令](troubleshooting/gitlab_rails_cheat_sheet.html) (适用于支持工程师) +* [Troubleshooting SSL](troubleshooting/ssl.html) +* 有用的链接: + * [GitLab 开发人员文档](../development/README.html) + * [修复和恢复损坏的 Git 存储库](https://git.seveas.net/repairing-and-recovering-broken-git-repositories.html) + * [使用 OpenSSL 进行测试](https://www.feistyduck.com/library/openssl-cookbook/online/ch-testing-with-openssl.html) + * [`Strace`杂志](https://wizardzines.com/zines/strace/) +* GitLab.com 专用资源: + * [组 SAML / SCIM 设置](troubleshooting/group_saml_scim.html) \ No newline at end of file diff --git a/_book/docs/420.md b/_book/docs/420.md new file mode 100644 index 0000000000000000000000000000000000000000..effd4008cf620778b94c993b01f2c6170fbc7e97 --- /dev/null +++ b/_book/docs/420.md @@ -0,0 +1,167 @@ +# Reference architectures + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/](https://docs.gitlab.com/ee/administration/reference_architectures/) + +* [Available reference architectures](#available-reference-architectures) +* [Availability Components](#availability-components) + * [Automated backups](#automated-backups-core-only) + * [Traffic load balancer](#traffic-load-balancer-starter-only) + * [Zero downtime updates](#zero-downtime-updates-starter-only) + * [Automated database failover](#automated-database-failover-premium-only) + * [Instance level replication with GitLab Geo](#instance-level-replication-with-gitlab-geo-premium-only) +* [Configure GitLab to scale](#configure-gitlab-to-scale) + * [Configuring select components with Cloud Native Helm](#configuring-select-components-with-cloud-native-helm) +* [Footnotes](#footnotes) + +# Reference architectures[](#reference-architectures "Permalink") + +您可以在单个服务器上设置 GitLab 或扩展它以服务许多用户. 本页详细介绍了由 GitLab 的质量和支持团队构建和验证的推荐参考架构. + +下面的图表表示每个体系结构层及其可处理的用户数量. 随着用户数量的增长,建议您相应地调整 GitLab. + +[![Reference Architectures](img/eec4d73b57835f2caa3ad88d45260b49.png)](img/reference-architectures.png) + +这些参考架构的测试是使用[GitLab 的 Performance Tool](https://gitlab.com/gitlab-org/quality/performance)在特定的编码工作负载下进行的,用于测试的吞吐量是根据样本客户数据计算得出的. 选择适合您规模的参考架构后,请参考将[GitLab 配置为可缩放](#configure-gitlab-to-scale)以查看所涉及的组件以及如何配置它们. + +每 1000 个用户使用以下每秒请求数(RPS)测试每种端点类型: + +* API:20 RPS +* 网络:2 RPS +* 转到:2 RPS + +对于用户数少于 2,000 的 GitLab 实例,建议您通过在单个计算机上[安装 GitLab](../../install/README.html)来使用[默认设置](#automated-backups-core-only) ,以最大程度地减少维护和资源成本. + +如果您的组织有 2000 多名用户,则建议将 GitLab 的组件扩展到多个机器节点. 机器节点按组件分组. 这些节点的增加提高了您的 GitLab 实例的性能和可伸缩性. + +扩展 GitLab 时,需要考虑以下几个因素: + +* 多个应用程序节点来处理前端流量. +* 前面添加了一个负载均衡器,以在应用程序节点之间分配流量. +* 应用程序节点连接到共享文件服务器以及后端的 PostgreSQL 和 Redis 服务. + +**注意:**根据您的工作流程,以下建议的参考体系结构可能需要进行相应的调整. 您的工作负载受以下因素影响,这些因素包括用户的活跃程度,使用的自动化程度,镜像和存储库/更改大小. 此外,显示的内存值由[GCP 机器类型提供](https://cloud.google.com/compute/docs/machine-types) . 对于不同的云供应商,请尝试选择最匹配所提供架构的选项. + +## Available reference architectures[](#available-reference-architectures "Permalink") + +提供以下参考体系结构: + +* [Up to 1,000 users](1k_users.html) +* [Up to 2,000 users](2k_users.html) +* [Up to 3,000 users](3k_users.html) +* [Up to 5,000 users](5k_users.html) +* [Up to 10,000 users](10k_users.html) +* [Up to 25,000 users](25k_users.html) +* [Up to 50,000 users](50k_users.html) + +## Availability Components[](#availability-components "Permalink") + +GitLab 随附以下组件供您使用,从最小到最复杂列出: + +1. [Automated backups](#automated-backups-core-only) +2. [Traffic load balancer](#traffic-load-balancer-starter-only) +3. [Zero downtime updates](#zero-downtime-updates-starter-only) +4. [Automated database failover](#automated-database-failover-premium-only) +5. [Instance level replication with GitLab Geo](#instance-level-replication-with-gitlab-geo-premium-only) + +在实现这些组件时,请从单个服务器开始,然后再进行备份. 仅在完成第一台服务器后,才可以继续执行下一个. + +此外,不为 GitLab 实施额外的服务器并不一定意味着您将有更多的停机时间. 根据您的需求和经验水平,单个服务器可以为用户带来更多实际的正常运行时间. + +### Automated backups[](#automated-backups-core-only "Permalink") + +> * 复杂程度: **低** +> * 必需的领域知识:PostgreSQL,GitLab 配置,Git +> * 支持的级别: [GitLab Core,Starter,Premium 和 Ultimate](https://about.gitlab.com/pricing/) + +该解决方案适用于具有默认 GitLab 安装的许多团队. 通过自动备份 GitLab 存储库,配置和数据库,如果您没有严格的要求,这可能是最佳的解决方案. [自动备份](../../raketasks/backup_restore.html#configuring-cron-to-make-daily-backups)的设置最简单. 这提供了预定时间表的时间点恢复. + +### Traffic load balancer[](#traffic-load-balancer-starter-only "Permalink") + +> * 复杂程度: **中** +> * 必需的领域知识:HAProxy,共享存储,分布式系统 +> * 支持的级别: [GitLab Starter,Premium 和 Ultimate](https://about.gitlab.com/pricing/) + +这需要使用添加的[负载平衡器](../high_availability/load_balancer.html)将 GitLab 分离为多个应用程序节点. 负载平衡器将在 GitLab 应用程序节点之间分配流量. 同时,每个应用程序节点都连接到后端的共享文件服务器和数据库系统. 这样,如果其中一台应用程序服务器发生故障,则工作流不会中断. 建议使用[HAProxy](https://www.haproxy.org/)作为负载平衡器. + +与默认安装相比,有了此添加的组件,您具有许多优点: + +* 增加用户数量. +* 启用零停机时间升级. +* 提高可用性. + +### Zero downtime updates[](#zero-downtime-updates-starter-only "Permalink") + +> * 复杂程度: **中** +> * 必需的领域知识:PostgreSQL,HAProxy,共享存储,分布式系统 +> * 支持的级别: [GitLab Starter,Premium 和 Ultimate](https://about.gitlab.com/pricing/) + +GitLab 支持[零停机时间更新](https://docs.gitlab.com/omnibus/update/) . 尽管您可以使用单个 GitLab 节点执行零停机时间更新,但是建议将 GitLab 分为几个应用程序节点. 只要每个组件中的至少一个在线且能够处理实例的使用负载,您的团队的生产力就不会在更新期间被打断. + +### Automated database failover[](#automated-database-failover-premium-only "Permalink") + +> * 复杂程度: **高** +> * 必需的领域知识:PgBouncer,Repmgr 或 Patroni,共享存储,分布式系统 +> * 支持的级别: [GitLab Premium 和 Ultimate](https://about.gitlab.com/pricing/) + +通过为数据库系统添加自动故障转移,可以通过其他数据库节点来提高正常运行时间. 这将使用群集管理和故障转移策略扩展默认数据库. [建议将 PgBouncer 与 Repmgr 或 Patroni 结合使用](../postgresql/replication_and_failover.html) . + +### Instance level replication with GitLab Geo[](#instance-level-replication-with-gitlab-geo-premium-only "Permalink") + +> * 复杂程度: **很高** +> * 必需的域知识:存储复制 +> * 支持的级别: [GitLab Premium 和 Ultimate](https://about.gitlab.com/pricing/) + +[GitLab Geo](../geo/replication/index.html)允许您将 GitLab 实例复制到其他地理位置,作为只读的完全可操作实例,如果发生灾难,也可以升级它. + +## Configure GitLab to scale[](#configure-gitlab-to-scale "Permalink") + +**Note:** From GitLab 13.0, using NFS for Git repositories is deprecated. In GitLab 14.0, support for NFS for Git repositories is scheduled to be removed. Upgrade to [Gitaly Cluster](../gitaly/praefect.html) as soon as possible. + +以下组件是您需要配置以扩展 GitLab 的组件. 如果您选择的[参考体系结构](#reference-architectures)要求它们,则按照通常配置它们的顺序列出它们. + +它们大多数捆绑在 GitLab deb / rpm 软件包(称为 Omnibus GitLab)中,但是根据您的系统架构,您可能需要其中未包含的某些组件. 如果需要,应在设置 GitLab 提供的组件之前对其进行配置. 配置说明列中提供了有关如何为您的组织选择正确的解决方案的建议. + +| Component | Description | 配置说明 | 与 Omnibus GitLab 捆绑在一起 | +| --- | --- | --- | --- | +| 负载均衡器( [6](#footnotes) ) | 处理负载平衡,通常在您有多个 GitLab 应用程序服务节点时 | [Load balancer configuration](../high_availability/load_balancer.html) ([6](#footnotes)) | No | +| 对象存储服务( [4](#footnotes) ) | 推荐的共享数据对象存储 | [Object Storage configuration](../object_storage.html) | No | +| NFS( [5](#footnotes) )( [7](#footnotes) ) | 共享磁盘存储服务. 可以用作备用对象存储. GitLab 页面必需 | [NFS configuration](../high_availability/nfs.html) | No | +| [Consul](../../development/architecture.html#consul) ([3](#footnotes)) | Service discovery and health checks/failover | [Consul configuration](../high_availability/consul.html) | Yes | +| [PostgreSQL](../../development/architecture.html#postgresql) | Database | [PostgreSQL configuration](https://docs.gitlab.com/omnibus/settings/database.html) | Yes | +| [PgBouncer](../../development/architecture.html#pgbouncer) | 数据库连接池 | [PgBouncer configuration](../high_availability/pgbouncer.html#running-pgbouncer-as-part-of-a-non-ha-gitlab-installation) | Yes | +| Repmgr | PostgreSQL 集群管理和故障转移 | [PostgreSQL and Repmgr configuration](../postgresql/replication_and_failover.html) | Yes | +| Patroni | 替代的 PostgreSQL 集群管理和故障转移 | [PostgreSQL and Patroni configuration](../postgresql/replication_and_failover.html#patroni) | Yes | +| [Redis](../../development/architecture.html#redis) ([3](#footnotes)) | 键/值存储,用于快速查找和缓存数据 | [Redis configuration](../high_availability/redis.html) | Yes | +| Redis 前哨 | Redis | [Redis Sentinel configuration](../high_availability/redis.html) | Yes | +| [吉塔利](../../development/architecture.html#gitaly) ( [2](#footnotes) )( [7](#footnotes) ) | 提供对 Git 存储库的访问 | [Gitaly configuration](../gitaly/index.html#run-gitaly-on-its-own-server) | Yes | +| [Sidekiq](../../development/architecture.html#sidekiq) | 异步/后台作业 | [Sidekiq configuration](../high_availability/sidekiq.html) | Yes | +| [GitLab application services](../../development/architecture.html#unicorn)([1](#footnotes)) | Puma / Unicorn,Workhorse,GitLab Shell-服务于前端请求(UI,API,基于 HTTP / SSH 的 Git) | [GitLab app scaling configuration](../high_availability/gitlab.html) | Yes | +| [Prometheus](../../development/architecture.html#prometheus) and [Grafana](../../development/architecture.html#grafana) | GitLab 环境监控 | [Monitoring node for scaling](../high_availability/monitoring_node.html) | Yes | + +### Configuring select components with Cloud Native Helm[](#configuring-select-components-with-cloud-native-helm "Permalink") + +我们还提供[Helm 图表](https://docs.gitlab.com/charts/)作为 GitLab 的 Cloud Native 安装方法. 对于参考体系结构,如果需要,可以以这种方式设置选择组件. + +对于此类设置,我们支持在[高级配置](https://docs.gitlab.com/charts/)中使用图表,在这些[高级配置中](https://docs.gitlab.com/charts/) ,有状态后端组件(例如数据库或 Gitaly)可通过 Omnibus 或信誉良好的第三方服务在外部运行. 请注意,我们目前不支持通过 Helm *大规模*运行有状态组件. + +设计这些环境时,应[参考](#available-reference-architectures)上面的相应[参考体系结构](#available-reference-architectures)以获取有关大小调整的指导. 通过 Helm 运行的组件将按类似比例缩放到其 Omnibus 规格,仅转换为 Kubernetes 资源. + +例如,如果您要设置一个 50k 的安装,并且 Rails 节点在 Helm 中运行,那么应该为 Kubernetes 集群提供与 Omnibus 相同数量的资源,并且将 Rails 节点分解为多个较小的 Pod 跨集群. + +## Footnotes[](#footnotes "Permalink") + +1. 在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数量设置为 90%的可用 CPU 以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +2. Gitaly 节点的要求取决于客户数据,特别是项目数量及其规模. 我们建议每个 Gitaly 节点应存储不超过 5TB 的数据,并且将[`gitaly-ruby`工作者](../gitaly/index.html#gitaly-ruby)的数量设置为可用 CPU 的 20%. 根据以上建议,应结合其他节点并结合对预期数据大小和分布的审查. + +3. 推荐的 Redis 设置因架构的大小而异. 对于较小的体系结构(少于 3000 个用户),一个实例就足够了. 对于中型安装(3,000-5,000),我们建议为所有课程使用一个 Redis 集群,并且 Redis Sentinel 与 Consul 一起托管. 对于较大的体系结构(10,000 个或更多用户),我们建议分别为 Cache 类和队列和 Shared State 类运行一个单独的[Redis 群集](../redis/replication_and_failover.html#running-multiple-redis-clusters) . 我们还建议您为每个 Redis 群集分别运行 Redis Sentinel 群集. + +4. 对于 LFS,Uploads,Artifacts 等数据对象.由于性能更好,我们建议尽可能在 NFS 上使用[对象存储服务](../object_storage.html) . + +5. NFS 可以用作对象存储的替代方法,但是出于性能考虑,通常不建议使用 NFS. 请注意,但是[GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)是必需的. + +6. 我们的架构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +7. 我们强烈建议为任何 Gitaly 或 NFS 节点设置 HDD 之上的 SSD 磁盘,其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS,因为这些组件的 I / O 繁重. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您正在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +8. 这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. \ No newline at end of file diff --git a/_book/docs/421.md b/_book/docs/421.md new file mode 100644 index 0000000000000000000000000000000000000000..5a41f039d2cb0afa142b9731f00a805d98baaa19 --- /dev/null +++ b/_book/docs/421.md @@ -0,0 +1,46 @@ +# Reference architecture: up to 1,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/1k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/1k_users.html) + +* [Setup instructions](#setup-instructions) +* [Footnotes](#footnotes) + +# Reference architecture: up to 1,000 users[](#reference-architecture-up-to-1000-users "Permalink") + +该页面描述了最多可容纳 1,000 位用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +> * **支持的用户(大约):** 1,000 +> * **高可用性:** False + +| Users | Configuration([8](#footnotes)) | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | +| 500 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | +| 1000 | 8 个 vCPU,7.2GB 内存 | `n1-highcpu-8` | `c5.2xlarge` | F8s v2 | + +除上述之外,即使您当前有足够的可用 RAM,我们也建议您在服务器上至少有 2GB 的交换空间. 如果您的可用内存发生更改,那么进行交换将有助于减少发生错误的机会. 我们还建议将内核的 swappiness 设置配置为较低的值(例如`10`以充分利用您的 RAM,同时在需要时仍可使用交换功能. + +对于需要服务多达 1,000 个用户的情况,具有[频繁备份](index.html#automated-backups-core-only)的单节点解决方案适用于许多组织. 通过自动备份 GitLab 存储库,配置和数据库,如果您对可用性没有严格的要求,这是理想的解决方案. + +## Setup instructions[](#setup-instructions "Permalink") + +* 对于此默认参考体系结构,请使用标准[安装说明](../../install/README.html)来安装 GitLab. + +**注意:**您还可以选择将 GitLab 配置为使用[外部 PostgreSQL 服务](../postgresql/external.html)或[外部对象存储服务](../high_availability/object_storage.html) ,从而以降低的复杂性成本来提高性能和可靠性. + +## Footnotes[](#footnotes "Permalink") + +1. 在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数量设置为 90%的可用 CPU 以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +2. Gitaly 节点的要求取决于客户数据,特别是项目数量及其规模. 对于 HA 环境,我们建议绝对最少使用两个节点,并且在支持 50,000 个或更多用户时,至少应使用四个节点. 我们还建议每个 Gitaly 节点存储的数据不得超过 5TB,并且将[`gitaly-ruby`工作者](../gitaly/index.html#gitaly-ruby)的数量设置为可用 CPU 的 20%. 根据以上建议,应结合其他节点并结合对预期数据大小和分布的审查. + +3. Recommended Redis setup differs depending on the size of the architecture. For smaller architectures (less than 3,000 users) a single instance should suffice. For medium sized installs (3,000 - 5,000) we suggest one Redis cluster for all classes and that Redis Sentinel is hosted alongside Consul. For larger architectures (10,000 users or more) we suggest running a separate [Redis Cluster](../redis/replication_and_failover.html#running-multiple-redis-clusters) for the Cache class and another for the Queues and Shared State classes respectively. We also recommend that you run the Redis Sentinel clusters separately for each Redis Cluster. + +4. 对于 LFS,Uploads,Artifacts 等数据对象.由于性能和可用性更好,我们建议尽可能在 NFS 上使用[对象存储服务](../object_storage.html) . + +5. NFS 可以用作存储库数据(替代 Gitaly)和对象存储的替代方法,但是出于性能原因,通常不建议使用 NFS. 请注意,但是[GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)是必需的. + +6. 我们的架构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +7. 我们强烈建议为任何 Gitaly 或 NFS 节点设置 HDD 之上的 SSD 磁盘,其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS,因为这些组件的 I / O 繁重. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您正在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +8. 这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. \ No newline at end of file diff --git a/_book/docs/422.md b/_book/docs/422.md new file mode 100644 index 0000000000000000000000000000000000000000..ee6dea952f1c18cb2e2bcb5bdb6b2f98e9e0041d --- /dev/null +++ b/_book/docs/422.md @@ -0,0 +1,657 @@ +# Reference architecture: up to 2,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/2k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/2k_users.html) + +* [Setup components](#setup-components) +* [Configure the load balancer](#configure-the-load-balancer) + * [Application node terminates SSL](#application-node-terminates-ssl) + * [Load balancer terminates SSL without backend SSL](#load-balancer-terminates-ssl-without-backend-ssl) + * [Load balancer terminates SSL with backend SSL](#load-balancer-terminates-ssl-with-backend-ssl) + * [Ports](#ports) + * [Alternate SSH Port](#alternate-ssh-port) +* [Configure PostgreSQL](#configure-postgresql) + * [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance) + * [Standalone PostgreSQL using Omnibus GitLab](#standalone-postgresql-using-omnibus-gitlab) +* [Configure Redis](#configure-redis) + * [Provide your own Redis instance](#provide-your-own-redis-instance) + * [Standalone Redis using Omnibus GitLab](#standalone-redis-using-omnibus-gitlab) +* [Configure Gitaly](#configure-gitaly) + * [Gitaly TLS support](#gitaly-tls-support) +* [Configure GitLab Rails](#configure-gitlab-rails) +* [Configure Prometheus](#configure-prometheus) +* [Configure the object storage](#configure-the-object-storage) +* [Configure NFS (optional)](#configure-nfs-optional) +* [Troubleshooting](#troubleshooting) + +# Reference architecture: up to 2,000 users[](#reference-architecture-up-to-2000-users "Permalink") + +该页面描述了最多可容纳 2,000 位用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +> * **支持的用户(大约):** 2,000 +> * **高可用性:** False +> * **每秒测试请求(RPS)速率:** API:40 RPS,Web:4 RPS,Git:4 RPS + +| Service | Nodes | Configuration | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | --- | +| 负载均衡器 | 1 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| PostgreSQL | 1 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| Redis | 1 | 1 个 vCPU,3.75GB 内存 | `n1-standard-1` | `m5.large` | `D2s v3` | +| Gitaly | 1 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | `D4s v3` | +| 亚搏体育 app Rails | 2 | 8 个 vCPU,7.2GB 内存 | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` | +| 监控节点 | 1 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| 对象存储 | n/a | n/a | n/a | n/a | n/a | +| NFS 服务器(可选,不推荐) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` | + +Google Cloud Platform(GCP)架构是使用[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行更低或更高的调整. 有关更多信息,请参见我们基于[Sysbench](https://github.com/akopytov/sysbench)的[CPU 基准测试](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks) . + +由于具有更好的性能和可用性,对于数据对象(例如 LFS,上载或工件),建议使用[对象存储服务](#configure-the-object-storage)而不是 NFS. 使用对象存储服务也不需要您配置和维护节点. + +## Setup components[](#setup-components "Permalink") + +设置 GitLab 及其组件以容纳多达 2,000 个用户: + +1. [配置外部负载平衡节点](#configure-the-load-balancer)以处理两个 GitLab 应用程序服务节点的负载平衡. +2. [配置 PostgreSQL](#configure-postgresql) (GitLab 的数据库). +3. [Configure Redis](#configure-redis). +4. [配置 Gitaly](#configure-gitaly) ,它提供对 Git 存储库的访问. +5. [配置主要的 GitLab Rails 应用程序](#configure-gitlab-rails)以运行 Puma / Unicorn,Workhorse,GitLab Shell,并满足所有前端请求(包括 UI,API 和基于 HTTP / SSH 的 Git). +6. [配置 Prometheus](#configure-prometheus)来监视您的 GitLab 环境. +7. [配置](#configure-the-object-storage)用于共享数据对象[的对象存储](#configure-the-object-storage) . +8. [配置 NFS](#configure-nfs-optional) (可选,不建议使用)以具有共享磁盘存储服务,以替代 Gitaly 或对象存储. 如果您不使用 GitLab 页面(需要 NFS),则可以跳过此步骤. + +## Configure the load balancer[](#configure-the-load-balancer "Permalink") + +**注意:**此体系结构已经过[HAProxy 的](https://www.haproxy.org/)测试和验证. 尽管您可以使用具有类似功能的负载均衡器,但 GitLab 尚未验证其他负载均衡器. + +在主动/主动 GitLab 配置中,您需要一个负载平衡器才能将流量路由到应用程序服务器. GitLab 文档超出了使用负载平衡器或其确切配置的详细信息. 如果要管理多节点系统(包括 GitLab),则可能已经选择了负载均衡器. 一些示例包括 HAProxy(开源),F5 Big-IP LTM 和 Citrix Net Scaler. 本文档包括与 GitLab 一起使用的端口和协议. + +下一个问题是如何在环境中处理 SSL. 有几种不同的选择: + +* [The application node terminates SSL](#application-node-terminates-ssl). +* [负载平衡器终止没有后端 SSL 的 SSL,](#load-balancer-terminates-ssl-without-backend-ssl)并且负载平衡器与应用程序节点之间的通信不安全. +* [负载均衡器使用后端 SSL 终止 SSL,](#load-balancer-terminates-ssl-with-backend-ssl)并且负载均衡器与应用程序节点之间的通信是*安全*的. + +### Application node terminates SSL[](#application-node-terminates-ssl "Permalink") + +配置您的负载均衡器以将端口 443 上的连接作为`TCP`而不是`HTTP(S)`传递. 这会将连接保持不变地传递到应用程序节点的 NGINX 服务,该服务具有 SSL 证书并侦听端口 443. + +有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load balancer terminates SSL without backend SSL[](#load-balancer-terminates-ssl-without-backend-ssl "Permalink") + +将负载平衡器配置为使用`HTTP(S)`协议而不是`TCP` . 负载平衡器将负责管理 SSL 证书和终止 SSL. + +由于负载平衡器和 GitLab 之间的通信不安全,因此您需要完成一些其他配置. 有关详细信息,请参见[NGINX 代理的 SSL 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load balancer terminates SSL with backend SSL[](#load-balancer-terminates-ssl-with-backend-ssl "Permalink") + +配置您的负载平衡器(如果只有一个,则为单个平衡器)以使用`HTTP(S)`协议而不是`TCP` . 负载平衡器将负责为最终用户管理 SSL 证书. + +在这种情况下,负载平衡器和 NGINX 之间的流量将是安全的,并且无需为代理 SSL 添加配置. 但是,您需要向 GitLab 添加配置以配置 SSL 证书. 有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Ports[](#ports "Permalink") + +The basic load balancer ports you should use are described in the following table: + +| Port | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 80 | HTTP( *1* ) | +| 443 | 443 | TCP 或 HTTPS( *1* )( *2* ) | +| 22 | 22 | TCP | + +* ( *1* ): [Web 终端](../../ci/environments/index.html#web-terminals)支持要求您的负载平衡器正确处理 WebSocket 连接. 当使用 HTTP 或 HTTPS 代理,负载平衡器必须被配置为通过`Connection`和`Upgrade`逐跳头. 有关详细信息,请参见[Web 终端](../integration/terminal.html)集成指南. +* ( *2* ):在端口 443 上使用 HTTPS 协议时,您需要向负载均衡器添加 SSL 证书. 如果需要在 GitLab 应用程序服务器上终止 SSL,请使用 TCP 协议. + +如果您使用具有自定义域支持的 GitLab 页面,则将需要一些其他端口配置. GitLab 页面需要一个单独的虚拟 IP 地址. 配置 DNS,以将`pages_external_url`的`/etc/gitlab/gitlab.rb`指向新的虚拟 IP 地址. 有关更多信息,请参见[GitLab 页面文档](../pages/index.html) . + +| Port | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 变化( *1* ) | HTTP | +| 443 | 变化( *1* ) | TCP( *2* ) | + +* ( *1* ):GitLab 页面的后端端口取决于`gitlab_pages['external_http']`和`gitlab_pages['external_https']`设置. 有关详细信息,请参见[GitLab 页面文档](../pages/index.html) . +* ( *2* ):GitLab 页面的端口 443 必须使用 TCP 协议. 用户可以使用自定义 SSL 配置自定义域,如果 SSL 在负载均衡器处终止,则无法实现. + +#### Alternate SSH Port[](#alternate-ssh-port "Permalink") + +某些组织有禁止打开 SSH 端口 22 的策略.在这种情况下,配置备用 SSH 主机名可能会有所帮助,该主机名改为允许用户通过端口 443 使用 SSH.与先前描述的相比,备用 SSH 主机名需要新的虚拟 IP 地址. GitLab HTTP 配置. + +为备用 SSH 主机名配置 DNS,例如`altssh.gitlab.example.com` : + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 443 | 22 | TCP | + +[Back to setup components](#setup-components) + +## Configure PostgreSQL[](#configure-postgresql "Permalink") + +在本节中,将指导您配置与 GitLab 一起使用的外部 PostgreSQL 数据库. + +### Provide your own PostgreSQL instance[](#provide-your-own-postgresql-instance "Permalink") + +如果您将 GitLab 托管在云提供商上,则可以选择将托管服务用于 PostgreSQL. 例如,AWS 提供了运行 PostgreSQL 的托管关系数据库服务(RDS). + +如果您使用云托管服务,或提供自己的 PostgreSQL: + +1. 根据[数据库要求文档](../../install/requirements.html#database)设置 PostgreSQL. +2. 使用您选择的密码创建一个`gitlab`用户名. `gitlab`用户需要特权才能创建`gitlabhq_production`数据库. +3. 使用适当的详细信息配置 GitLab 应用程序服务器. [配置 GitLab Rails 应用程序](#configure-gitlab-rails)涵盖了此步骤. + +### Standalone PostgreSQL using Omnibus GitLab[](#standalone-postgresql-using-omnibus-gitlab "Permalink") + +1. SSH 进入 PostgreSQL 服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 不要完成下载页面上的任何其他步骤. +3. 为 PostgreSQL 生成密码哈希. 假设您将使用默认用户名`gitlab` (推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作`POSTGRESQL_PASSWORD_HASH`的值. + + ``` + sudo gitlab-ctl pg-password-md5 gitlab + ``` + +4. 编辑`/etc/gitlab/gitlab.rb`并添加以下内容,以适当地更新占位符值. + + * `POSTGRESQL_PASSWORD_HASH`上一步的输出值 + * `APPLICATION_SERVER_IP_BLOCKS`将连接到数据库的 GitLab 应用程序服务器的 IP 子网或 IP 地址的空格分隔列表. 示例: `%w(123.123.123.123/32 123.123.123.234/32)` + + ``` + # Disable all components except PostgreSQL + roles ['postgres_role'] + repmgr['enable'] = false + consul['enable'] = false + prometheus['enable'] = false + alertmanager['enable'] = false + pgbouncer_exporter['enable'] = false + redis_exporter['enable'] = false + gitlab_exporter['enable'] = false + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + postgres_exporter['dbname'] = 'gitlabhq_production' + postgres_exporter['password'] = 'POSTGRESQL_PASSWORD_HASH' + + # Set the PostgreSQL address and port + postgresql['listen_address'] = '0.0.0.0' + postgresql['port'] = 5432 + + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH' + + # Replace APPLICATION_SERVER_IP_BLOCK with the CIDR address of the application node + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 APPLICATION_SERVER_IP_BLOCK) + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + ``` + +5. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +6. 注意 PostgreSQL 节点的 IP 地址或主机名,端口和纯文本密码. 这些在以后配置[GitLab 应用程序服务器](#configure-gitlab-rails)时是必需的. + +支持高级[配置选项](https://docs.gitlab.com/omnibus/settings/database.html) ,可以根据需要添加. + +[Back to setup components](#setup-components) + +## Configure Redis[](#configure-redis "Permalink") + +在本节中,将指导您配置与 GitLab 一起使用的外部 Redis 实例. + +### Provide your own Redis instance[](#provide-your-own-redis-instance "Permalink") + +需要 Redis 5.0 或更高版本,因为这是从 GitLab 13.0 开始的 Omnibus GitLab 软件包附带的版本. 较旧的 Redis 版本不支持 SPOP 的可选 count 参数,这对于[合并火车](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)现在是必需的. + +此外,GitLab 还利用了某些命令,例如`UNLINK`和`USAGE` ,这些命令仅在 Redis 4 中引入. + +来自云提供商(例如 AWS ElastiCache)的托管 Redis 将可以使用. 如果这些服务支持高可用性,请确保它不是 Redis 群集类型. + +注意 Redis 节点的 IP 地址或主机名,端口和密码(如果需要). 这些在以后配置[GitLab 应用程序服务器](#configure-gitlab-rails)时是必需的. + +### Standalone Redis using Omnibus GitLab[](#standalone-redis-using-omnibus-gitlab "Permalink") + +Omnibus GitLab 软件包可用于配置独立的 Redis 服务器. 以下步骤是使用 Omnibus 配置 Redis 服务器的最低必需步骤: + +1. SSH 进入 Redis 服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + ## Enable Redis + redis['enable'] = true + + ## Disable all other services + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + postgresql['enable'] = false + nginx['enable'] = false + prometheus['enable'] = false + alertmanager['enable'] = false + pgbouncer_exporter['enable'] = false + gitlab_exporter['enable'] = false + gitaly['enable'] = false + grafana['enable'] = false + + redis['bind'] = '0.0.0.0' + redis['port'] = 6379 + redis['password'] = 'SECRET_PASSWORD_HERE' + + gitlab_rails['enable'] = false + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + redis_exporter['flags'] = { + 'redis.addr' => 'redis://0.0.0.0:6379', + 'redis.password' => 'SECRET_PASSWORD_HERE', + } + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +5. 注意 Redis 节点的 IP 地址或主机名,端口和 Redis 密码. 这些在以后[配置 GitLab 应用程序服务器](#configure-gitlab-rails)时是必需的. + +支持高级[配置选项](https://docs.gitlab.com/omnibus/settings/redis.html) ,可以根据需要添加. + +[Back to setup components](#setup-components) + +## Configure Gitaly[](#configure-gitaly "Permalink") + +在自己的服务器上部署 Gitaly 可以使大于单个计算机的 GitLab 安装受益. Gitaly 节点的要求取决于数据,特别是项目的数量及其大小. 建议每个 Gitaly 节点存储的数据量不得超过 5TB. 您的 2K 设置可能需要一个或多个节点,具体取决于您的存储库存储要求. + +我们强烈建议所有 Gitaly 节点都安装 SSD 磁盘,因为 Gitaly I / O 繁重,因此其读取操作的吞吐量至少为 8,000 IOPS,写入操作的吞吐量至少为 2,000 IOPS. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您正在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +Some things to note: + +* GitLab Rails 应用程序将[存储库分](../repository_storage_paths.html)片到[存储库中](../repository_storage_paths.html) . +* A Gitaly server can host one or more storages. +* 一个 GitLab 服务器可以使用一个或多个 Gitaly 服务器. +* 必须以对所有 Gitaly 客户端正确解析的方式指定 Gitaly 地址. +* Gitaly 服务器一定不能暴露在公共互联网上,因为默认情况下,Gitaly 的网络流量是未加密的. 强烈建议使用防火墙以限制对 Gitaly 服务器的访问. 另一种选择是[使用 TLS](#gitaly-tls-support) . + +**提示:**有关 Gitaly 历史和网络体系结构的更多信息,请参见[独立的 Gitaly 文档](../gitaly/index.html) . + +注意: **注意:** Gitaly 文档中引用的令牌只是管理员选择的任意密码. 它与为 GitLab API 创建的令牌或其他类似的 Web API 令牌无关. + +下面我们将介绍如何配置一个 Gitaly 服务器`gitaly1.internal`与秘密令牌`gitalysecret` . 我们假设您的 GitLab 安装有两个存储库存储: `default`和`storage1` . + +要配置 Gitaly 服务器: + +1. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包,但**不**提供`EXTERNAL_URL`值. +2. 编辑`/etc/gitlab/gitlab.rb`以配置存储路径,启用网络侦听器并配置令牌: + + ``` + # /etc/gitlab/gitlab.rb + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the GitLab Rails application setup + gitaly['auth_token'] = 'gitlaysecret' + gitlab_shell['secret_token'] = 'shellsecret' + + # Avoid running unnecessary services on the Gitaly server + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + grafana['enable'] = false + + # If you run a seperate monitoring node you can disable these services + alertmanager['enable'] = false + prometheus['enable'] = false + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your 'front door' GitLab URL or an internal load + # balancer. + # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server. + gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' + + # Make Gitaly accept connections on all network interfaces. You must use + # firewalls to restrict access to this address/port. + # Comment out following line if you only want to support TLS connections + gitaly['listen_addr'] = "0.0.0.0:8075" + gitaly['prometheus_listen_addr'] = "0.0.0.0:9236" + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + ``` + +3. 将以下内容添加到`/etc/gitlab/gitlab.rb`上的`gitaly1.internal` : + + ``` + git_data_dirs({ + 'default' => { + 'path' => '/var/opt/gitlab/git-data' + }, + 'storage1' => { + 'path' => '/mnt/gitlab/git-data' + }, + }) + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 确认 Gitaly 可以执行对内部 API 的回调: + + ``` + sudo /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml + ``` + +### Gitaly TLS support[](#gitaly-tls-support "Permalink") + +Gitaly 支持 TLS 加密. 为了能够与侦听安全连接的 Gitaly 实例进行通信,您将需要在 GitLab 配置中相应存储条目的`gitaly_address`中使用`tls://` URL 方案. + +您将需要携带自己的证书,因为该证书不会自动提供. 证书或其证书颁发机构必须按照[GitLab 自定义证书配置中](https://docs.gitlab.com/omnibus/settings/ssl.html)所述的步骤,安装在所有 Gitaly 节点(包括使用证书的 Gitaly 节点)上,以及与之通信的所有客户端节点上. + +**注意:**自签名证书必须指定用于访问 Gitaly 服务器的地址. 如果要通过主机名寻址 Gitaly 服务器,则可以为此使用"公用名"字段,也可以将其添加为"使用者备用名". 如果要通过 Gitaly 服务器的 IP 地址对其进行寻址,则必须将其作为主题备用名称添加到证书中. [gRPC 不支持在证书中使用 IP 地址作为公用名](https://github.com/grpc/grpc/issues/2691) .**注意:**可以同时为 Gitaly 服务器配置未加密的侦听地址`listen_addr`和已加密的侦听地址`tls_listen_addr` . 如果需要,这使您可以从未加密的流量逐渐过渡到加密的流量. + +要使用 TLS 配置 Gitaly: + +1. 创建`/etc/gitlab/ssl`目录,并在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +2. 将证书复制到`/etc/gitlab/trusted-certs`以便 Gitaly 在调用自身时信任该证书: + + ``` + sudo cp /etc/gitlab/ssl/cert.pem /etc/gitlab/trusted-certs/ + ``` + +3. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + gitaly['tls_listen_addr'] = "0.0.0.0:9999" + gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + gitaly['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +4. Delete `gitaly['listen_addr']` to allow only encrypted connections. +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +[Back to setup components](#setup-components) + +## Configure GitLab Rails[](#configure-gitlab-rails "Permalink") + +**注意:**在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数设置为可用 CPU 的 90%以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +本节介绍如何配置 GitLab 应用程序(Rails)组件. 在每个节点上执行以下操作: + +1. 如果您[使用的是 NFS](#configure-nfs-optional) : + + 1. 如有必要,请使用以下命令安装 NFS 客户端实用程序软件包: + + ``` + # Ubuntu/Debian + apt-get install nfs-common + + # CentOS/Red Hat + yum install nfs-utils nfs-utils-lib + ``` + + 2. 在`/etc/fstab`指定必要的 NFS 挂载. `/etc/fstab`的确切内容取决于您选择配置 NFS 服务器的方式. 有关示例和各种选项,请参见[NFS 文档](../high_availability/nfs.html) . + + 3. 创建共享目录. 这些可能会有所不同,具体取决于您的 NFS 安装位置. + + ``` + mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data + ``` + +2. 使用[GitLab 下载中的](https://about.gitlab.com/install/) **步骤 1 和 2**下载/安装 Omnibus GitLab. 不要完成下载页面上的其他步骤. +3. 创建/编辑`/etc/gitlab/gitlab.rb`并使用以下配置. 为了保持整个节点的链接均匀性, `external_url`在应用服务器上应指向外部 URL,用户将用来访问 GitLab. 这将是[负载均衡器](#configure-the-load-balancer)的 URL,它将把流量路由到 GitLab 应用程序服务器: + + ``` + external_url 'https://gitlab.example.com' + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the Gitaly setup + gitlab_rails['gitaly_token'] = 'gitalyecret' + gitlab_shell['secret_token'] = 'shellsecret' + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + + ## Disable components that will not be on the GitLab application server + roles ['application_role'] + gitaly['enable'] = false + nginx['enable'] = true + + ## PostgreSQL connection details + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['db_host'] = '10.1.0.5' # IP/hostname of database server + gitlab_rails['db_password'] = 'DB password' + + ## Redis connection details + gitlab_rails['redis_port'] = '6379' + gitlab_rails['redis_host'] = '10.1.0.6' # IP/hostname of Redis server + gitlab_rails['redis_password'] = 'Redis Password' + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' + sidekiq['listen_address'] = "0.0.0.0" + puma['listen'] = '0.0.0.0' + + # Add the monitoring node's IP address to the monitoring whitelist and allow it to + # scrape the NGINX metrics. Replace placeholder `monitoring.gitlab.example.com` with + # the address and/or subnets gathered from the monitoring node + gitlab_rails['monitoring_whitelist'] = ['/32', '127.0.0.0/8'] + nginx['status']['options']['allow'] = ['/32', '127.0.0.0/8'] + + ## Uncomment and edit the following options if you have set up NFS + ## + ## Prevent GitLab from starting if NFS data mounts are not available + ## + #high_availability['mountpoint'] = '/var/opt/gitlab/git-data' + ## + ## Ensure UIDs and GIDs match between servers for permissions via NFS + ## + #user['uid'] = 9000 + #user['gid'] = 9000 + #web_server['uid'] = 9001 + #web_server['gid'] = 9001 + #registry['uid'] = 9002 + #registry['gid'] = 9002 + ``` + +4. 如果您正在使用[具有 TLS 支持](#gitaly-tls-support)的`git_data_dirs` ,请确保`git_data_dirs`条目配置了`tls`而不是`tcp` : + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' }, + }) + ``` + + 1. 将证书复制到`/etc/gitlab/trusted-certs` : + + ``` + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +6. 运行`sudo gitlab-rake gitlab:gitaly:check`确认节点可以连接到 Gitaly. +7. 拖尾日志以查看请求: + + ``` + sudo gitlab-ctl tail gitaly + ``` + +**注意:**如上例所示,当在`external_url`指定`https`时,GitLab 会假定您在`/etc/gitlab/ssl/`具有 SSL 证书. 如果没有证书,NGINX 将无法启动. 有关更多信息,请参见[NGINX 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) .[Back to setup components](#setup-components) + +## Configure Prometheus[](#configure-prometheus "Permalink") + +The Omnibus GitLab package can be used to configure a standalone Monitoring node running [Prometheus](../monitoring/prometheus/index.html) and [Grafana](../monitoring/performance/grafana_configuration.html): + +1. SSH 进入"监视"节点. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + external_url 'http://gitlab.example.com' + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Login form + grafana['disable_login_form'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = 'toomanysecrets' + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + node_exporter['enable'] = false + gitlab_exporter['enable'] = false + ``` + +4. Prometheus 还需要一些抓取配置,以从我们配置了导出器的各个节点中提取所有数据. 假设您节点的 IP 为: + + ``` + 1.1.1.1: postgres + 1.1.1.2: redis + 1.1.1.3: gitaly1 + 1.1.1.4: rails1 + 1.1.1.5: rails2 + ``` + + 将以下内容添加到`/etc/gitlab/gitlab.rb` : + + ``` + prometheus['scrape_configs'] = [ + { + 'job_name': 'postgres', + 'static_configs' => [ + 'targets' => ['1.1.1.1:9187'], + ], + }, + { + 'job_name': 'redis', + 'static_configs' => [ + 'targets' => ['1.1.1.2:9121'], + ], + }, + { + 'job_name': 'gitaly', + 'static_configs' => [ + 'targets' => ['1.1.1.3:9236'], + ], + }, + { + 'job_name': 'gitlab-nginx', + 'static_configs' => [ + 'targets' => ['1.1.1.4:8060', '1.1.1.5:8060'], + ], + }, + { + 'job_name': 'gitlab-workhorse', + 'static_configs' => [ + 'targets' => ['1.1.1.4:9229', '1.1.1.5:9229'], + ], + }, + { + 'job_name': 'gitlab-rails', + 'metrics_path': '/-/metrics', + 'static_configs' => [ + 'targets' => ['1.1.1.4:8080', '1.1.1.5:8080'], + ], + }, + { + 'job_name': 'gitlab-sidekiq', + 'static_configs' => [ + 'targets' => ['1.1.1.4:8082', '1.1.1.5:8082'], + ], + }, + { + 'job_name': 'node', + 'static_configs' => [ + 'targets' => ['1.1.1.1:9100', '1.1.1.2:9100', '1.1.1.3:9100', '1.1.1.4:9100', '1.1.1.5:9100'], + ], + }, + ] + ``` + +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +6. 在 GitLab 用户界面中,将`admin/application_settings/metrics_and_profiling` >指标-Grafana 设置为`/-/grafana`到`http[s]:///-/grafana` + +[Back to setup components](#setup-components) + +## Configure the object storage[](#configure-the-object-storage "Permalink") + +GitLab 支持使用对象存储服务来保存多种类型的数据,建议在[NFS 上使用](#configure-nfs-optional) . 通常,对象存储服务更适合较大的环境,因为对象存储通常具有更高的性能,可靠性和可伸缩性. + +GitLab 已测试或了解客户使用的对象存储选项包括: + +* SaaS / Cloud 解决方案(例如[Amazon S3](https://aws.amazon.com/s3/)或[Google Cloud Storage](https://cloud.google.com/storage) ). +* 来自各种存储供应商的本地硬件和设备. +* MinIO( [部署指南](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) ). + +要将 GitLab 配置为使用对象存储,请根据要使用的功能参考以下指南: + +1. [Object storage for backups](../../raketasks/backup_restore.html#uploading-backups-to-a-remote-cloud-storage). +2. [Object storage for job artifacts](../job_artifacts.html#using-object-storage) including [incremental logging](../job_logs.html#new-incremental-logging-architecture). +3. [Object storage for LFS objects](../lfs/index.html#storing-lfs-objects-in-remote-object-storage). +4. [Object storage for uploads](../uploads.html#using-object-storage-core-only). +5. [Object storage for merge request diffs](../merge_request_diffs.html#using-object-storage). +6. [容器注册表的对象存储](../packages/container_registry.html#use-object-storage) (可选功能). +7. [Mattermost 的对象存储](https://docs.mattermost.com/administration/config-settings.html#file-storage) (可选功能). +8. [包的对象存储](../packages/index.html#using-object-storage) (可选功能). +9. [依赖代理的对象存储](../packages/dependency_proxy.html#using-object-storage) (可选功能). +10. [Pseudonymizer 的对象存储](../pseudonymizer.html#configuration) (可选功能). +11. [用于自动缩放 Runner 缓存的对象存储](https://docs.gitlab.com/runner/configuration/autoscale.html) (可选,以提高性能). +12. [Object storage for Terraform state files](../terraform_state.html#using-object-storage-core-only). + +对于 GitLab,建议为每种数据类型使用单独的存储桶. + +我们的配置的局限性是对象存储的每次使用都是单独配置的. 我们有一个[问题](https://gitlab.com/gitlab-org/gitlab/-/issues/23345)需要改进,那就是允许一个存储桶具有单独的文件夹. + +在通过 Helm 图表部署 GitLab 时使用单个存储桶会导致从备份还原[无法正常运行](https://docs.gitlab.com/charts/advanced/external-object-storage/) . 尽管您可能暂时不使用 Helm 部署,但是如果稍后将 GitLab 迁移到 Helm 部署,GitLab 仍然可以工作,但是您可能不会意识到备份无法正常工作,直到遇到对备份起作用的关键要求. + +[Back to setup components](#setup-components) + +## Configure NFS (optional)[](#configure-nfs-optional "Permalink") + +为了提高性能,建议尽可能使用[对象存储](#configure-the-object-storage)以及[Gitaly](#configure-gitaly) ,而不是使用 NFS. 但是,如果您打算使用 GitLab 页面,则[必须使用 NFS](troubleshooting.html#gitlab-pages-requires-nfs) . + +有关配置 NFS 的信息,请参阅[NFS 文档页面](../high_availability/nfs.html) . + +[Back to setup components](#setup-components) + +## Troubleshooting[](#troubleshooting "Permalink") + +请参阅[故障排除文档](troubleshooting.html) . + +[Back to setup components](#setup-components) \ No newline at end of file diff --git a/_book/docs/423.md b/_book/docs/423.md new file mode 100644 index 0000000000000000000000000000000000000000..414f222a6bbfd280f938da39e94b4de2f43de7c0 --- /dev/null +++ b/_book/docs/423.md @@ -0,0 +1,1451 @@ +# Reference architecture: up to 3,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/3k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/3k_users.html) + +* [Setup components](#setup-components) +* [Configure the external load balancer](#configure-the-external-load-balancer) + * [Application node terminates SSL](#application-node-terminates-ssl) + * [Load balancer terminates SSL without backend SSL](#load-balancer-terminates-ssl-without-backend-ssl) + * [Load balancer terminates SSL with backend SSL](#load-balancer-terminates-ssl-with-backend-ssl) + * [Ports](#ports) + * [Alternate SSH Port](#alternate-ssh-port) +* [Configure Redis](#configure-redis) + * [Provide your own Redis instance](#provide-your-own-redis-instance) + * [Standalone Redis using Omnibus GitLab](#standalone-redis-using-omnibus-gitlab) + * [Configuring the primary Redis instance](#configuring-the-primary-redis-instance) + * [Configuring the replica Redis instances](#configuring-the-replica-redis-instances) +* [Configure Consul and Sentinel](#configure-consul-and-sentinel) +* [Configure PostgreSQL](#configure-postgresql) + * [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance) + * [Standalone PostgreSQL using Omnibus GitLab](#standalone-postgresql-using-omnibus-gitlab) + * [PostgreSQL primary node](#postgresql-primary-node) + * [PostgreSQL secondary nodes](#postgresql-secondary-nodes) + * [PostgreSQL post-configuration](#postgresql-post-configuration) +* [Configure PgBouncer](#configure-pgbouncer) + * [Configure the internal load balancer](#configure-the-internal-load-balancer) +* [Configure Gitaly](#configure-gitaly) + * [Gitaly TLS support](#gitaly-tls-support) +* [Configure Sidekiq](#configure-sidekiq) +* [Configure GitLab Rails](#configure-gitlab-rails) + * [GitLab Rails post-configuration](#gitlab-rails-post-configuration) +* [Configure Prometheus](#configure-prometheus) +* [Configure the object storage](#configure-the-object-storage) +* [Configure NFS (optional)](#configure-nfs-optional) +* [Troubleshooting](#troubleshooting) + +# Reference architecture: up to 3,000 users[](#reference-architecture-up-to-3000-users "Permalink") + +此页面描述了最多 3,000 个用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +**注意:**下面记录的 3,000 个用户参考体系结构旨在帮助您的组织实现高度可用的 GitLab 部署. 如果您没有专业知识或需要维护高度可用的环境,则可以遵循[2,000 个用户的参考体系结构](2k_users.html) ,从而拥有一个更简单且成本更低的操作环境. + +> * **支持的用户(大约):** 3,000 +> * **高可用性:** True +> * **测试 RPS 速率:** API:60 RPS,网站:6 RPS,Git:6 RPS + +| Service | Nodes | Configuration | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | --- | +| 外部负载平衡节点 | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| Redis | 3 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| 领事+前哨 | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| PostgreSQL | 3 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| PgBouncer | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| 内部负载平衡节点 | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| Gitaly | 最少 2 个 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | `D4s v3` | +| Sidekiq | 4 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| 亚搏体育 app Rails | 3 | 8 个 vCPU,7.2GB 内存 | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` | +| 监控节点 | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| 对象存储 | n/a | n/a | n/a | n/a | n/a | +| NFS 服务器(可选,不推荐) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` | + +这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. + +对于 LFS,Uploads,Artifacts 等数据对象,由于性能和可用性更好,建议在 NFS 上尽可能使用[对象存储服务](#configure-the-object-storage) . 由于这不需要设置节点,因此在上表中将其标记为不适用(n / a). + +## Setup components[](#setup-components "Permalink") + +设置 GitLab 及其组件以容纳多达 3,000 个用户: + +1. [配置外部负载平衡节点](#configure-the-external-load-balancer) ,该[节点](#configure-the-external-load-balancer)将处理两个 GitLab 应用程序服务节点的负载平衡. +2. [Configure Redis](#configure-redis). +3. [Configure Consul and Sentinel](#configure-consul-and-sentinel). +4. [配置 PostgreSQL](#configure-postgresql) (GitLab 的数据库). +5. [Configure PgBouncer](#configure-pgbouncer). +6. [Configure the internal load balancing node](#configure-the-internal-load-balancer) +7. [配置 Gitaly](#configure-gitaly) ,它提供对 Git 存储库的访问. +8. [Configure Sidekiq](#configure-sidekiq). +9. [配置主 GitLab Rails 应用程序](#configure-gitlab-rails)以运行 Puma / Unicorn,Workhorse,GitLab Shell,并服务所有前端请求(UI,API,基于 HTTP / SSH 的 Git). +10. [配置 Prometheus](#configure-prometheus)来监视您的 GitLab 环境. +11. [配置](#configure-the-object-storage)用于共享数据对象[的对象存储](#configure-the-object-storage) . +12. [将 NFS(可选)配置](#configure-nfs-optional)为具有共享磁盘存储服务,以替代 Gitaly 和/或对象存储(尽管不建议这样做). GitLab 页面需要 NFS,如果不使用该功能,则可以跳过此步骤. + +我们从同一 10.6.0.0/16 专用网络范围内的所有服务器开始,它们可以在这些地址上自由地相互连接. + +这是每台机器和分配的 IP 的列表和说明: + +* `10.6.0.10` :外部负载平衡器 +* `10.6.0.61`主要 +* `10.6.0.62` :返回副本 1 +* `10.6.0.63` :返回副本 2 +* `10.6.0.11` :领事/前哨 1 +* `10.6.0.12` :领事/前哨 2 +* `10.6.0.13` :领事/前哨 3 +* `10.6.0.31`主 +* `10.6.0.32`中学 1 +* `10.6.0.33`中学 2 +* `10.6.0.21` :PgBouncer 1 +* `10.6.0.22` :PgBouncer 2 +* `10.6.0.23` :PgBouncer 3 +* `10.6.0.20` :内部负载均衡器 +* `10.6.0.51` :Gitaly 1 +* `10.6.0.52` :Gitaly 2 +* `10.6.0.71` :Sidekiq 1 +* `10.6.0.72` :Sidekiq 2 +* `10.6.0.73` :Sidekiq 3 +* `10.6.0.74` :Sidekiq 4 +* `10.6.0.41`应用程序 1 +* `10.6.0.42`应用程序 2 +* `10.6.0.43`应用程序 3 +* `10.6.0.81` :普罗米修斯 + +## Configure the external load balancer[](#configure-the-external-load-balancer "Permalink") + +**注意:**此体系结构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +在主动/主动 GitLab 配置中,您将需要一个负载均衡器来将流量路由到应用程序服务器. 有关使用负载均衡器或进行确切配置的细节超出了 GitLab 文档的范围. 我们希望,如果您要管理像 GitLab 这样的多节点系统,那么已经选择了负载均衡器. 一些示例包括 HAProxy(开源),F5 Big-IP LTM 和 Citrix Net Scaler. 本文档将概述需要在 GitLab 上使用哪些端口和协议. + +下一个问题是如何在环境中处理 SSL. 有几种不同的选择: + +* [The application node terminates SSL](#application-node-terminates-ssl). +* [负载平衡器终止没有后端 SSL 的 SSL,](#load-balancer-terminates-ssl-without-backend-ssl)并且负载平衡器与应用程序节点之间的通信不安全. +* [负载均衡器使用后端 SSL 终止 SSL,](#load-balancer-terminates-ssl-with-backend-ssl)并且负载均衡器与应用程序节点之间的通信是*安全*的. + +### Application node terminates SSL[](#application-node-terminates-ssl "Permalink") + +配置您的负载均衡器以将端口 443 上的连接作为`TCP`而不是`HTTP(S)`协议进行传递. 这会将连接直接传递到应用程序节点的 NGINX 服务. NGINX 将具有 SSL 证书并在端口 443 上侦听. + +有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load balancer terminates SSL without backend SSL[](#load-balancer-terminates-ssl-without-backend-ssl "Permalink") + +将您的负载均衡器配置为使用`HTTP(S)`协议而不是`TCP` . 然后,负载平衡器将负责管理 SSL 证书和终止 SSL. + +由于负载均衡器和 GitLab 之间的通信将不安全,因此需要一些其他配置. 有关详细信息,请参见[NGINX 代理的 SSL 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load balancer terminates SSL with backend SSL[](#load-balancer-terminates-ssl-with-backend-ssl "Permalink") + +Configure your load balancer(s) to use the ‘HTTP(S)’ protocol rather than ‘TCP’. The load balancer(s) will be responsible for managing SSL certificates that end users will see. + +在这种情况下,负载均衡器和 NGINX 之间的流量也将是安全的. 无需为代理 SSL 添加配置,因为连接将一直保持安全. 但是,需要将配置添加到 GitLab 来配置 SSL 证书. 有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Ports[](#ports "Permalink") + +下表显示了要使用的基本端口. + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 80 | HTTP( *1* ) | +| 443 | 443 | TCP 或 HTTPS( *1* )( *2* ) | +| 22 | 22 | TCP | + +* ( *1* ): [Web 终端](../../ci/environments/index.html#web-terminals)支持要求您的负载平衡器正确处理 WebSocket 连接. 当使用 HTTP 或 HTTPS 代理,这意味着负载平衡器必须被配置为通过`Connection`和`Upgrade`逐跳头. 有关更多详细信息,请参见[Web 终端](../integration/terminal.html)集成指南. +* ( *2* ):当对端口 443 使用 HTTPS 协议时,需要向负载均衡器添加 SSL 证书. 如果您想在 GitLab 应用程序服务器上终止 SSL,请使用 TCP 协议. + +如果您使用具有自定义域支持的 GitLab 页面,则将需要一些其他端口配置. GitLab 页面需要一个单独的虚拟 IP 地址. 配置 DNS,将`pages_external_url`的`/etc/gitlab/gitlab.rb`指向新的虚拟 IP 地址. 有关更多信息,请参见[GitLab 页面文档](../pages/index.html) . + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 变化( *1* ) | HTTP | +| 443 | 变化( *1* ) | TCP( *2* ) | + +* ( *1* ):GitLab 页面的后端端口取决于`gitlab_pages['external_http']`和`gitlab_pages['external_https']`设置. 有关更多详细信息,请参见[GitLab Pages 文档](../pages/index.html) . +* ( *2* ):GitLab 页面的端口 443 应该始终使用 TCP 协议. 用户可以使用自定义 SSL 配置自定义域,如果 SSL 在负载均衡器处终止,则不可能. + +#### Alternate SSH Port[](#alternate-ssh-port "Permalink") + +某些组织有禁止打开 SSH 端口 22 的策略.在这种情况下,配置允许用户在端口 443 上使用 SSH 的备用 SSH 主机名可能会有所帮助.与其他 GitLab 相比,备用 SSH 主机名将需要一个新的虚拟 IP 地址.上面的 HTTP 配置. + +为备用 SSH 主机名(例如`altssh.gitlab.example.com`配置 DNS. + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 443 | 22 | TCP | + +[Back to setup components](#setup-components) + +## Configure Redis[](#configure-redis "Permalink") + +使用[Redis 的](https://s0redis0io.icopy.site/)可扩展环境,可以使用**一次** X **副本**拓扑与[Redis 的哨兵](https://s0redis0io.icopy.site/topics/sentinel)服务来观看,并自动启动故障转移过程. + +如果与 Sentinel 一起使用,Redis 需要身份验证. 有关更多信息,请参见[Redis 安全性](https://s0redis0io.icopy.site/topics/security)文档. 我们建议结合使用 Redis 密码和严格的防火墙规则来保护您的 Redis 服务. 强烈建议您在使用 GitLab 配置 Redis 之前阅读[Redis Sentinel](https://s0redis0io.icopy.site/topics/sentinel)文档,以充分了解拓扑和体系结构. + +在本节中,将指导您配置与 GitLab 一起使用的外部 Redis 实例. 以下 IP 将作为示例: + +* `10.6.0.61`主要 +* `10.6.0.62` :返回副本 1 +* `10.6.0.63` :返回副本 2 + +### Provide your own Redis instance[](#provide-your-own-redis-instance "Permalink") + +来自云提供商(例如 AWS ElastiCache)的托管 Redis 将可以使用. 如果这些服务支持高可用性,请确保它**不是** Redis 群集类型. + +需要 Redis 5.0 或更高版本,因为这是从 GitLab 13.0 开始的 Omnibus GitLab 软件包附带的版本. 较旧的 Redis 版本不支持 SPOP 的可选 count 参数,这对于[合并火车](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)现在是必需的. + +注意 Redis 节点的 IP 地址或主机名,端口和密码(如果需要). 这些在以后配置[GitLab 应用程序服务器](#configure-gitlab-rails)时是必需的. + +### Standalone Redis using Omnibus GitLab[](#standalone-redis-using-omnibus-gitlab "Permalink") + +这是我们安装和设置新 Redis 实例的部分. + +Redis 设置的要求如下: + +1. 所有 Redis 节点必须能够互相通信并接受通过 Redis( `6379` )和 Sentinel( `26379` )端口的传入连接(除非您更改默认端口). +2. 托管 GitLab 应用程序的服务器必须能够访问 Redis 节点. +3. 使用防火墙保护节点免受来自外部网络( [Internet](https://gitlab.com/gitlab-org/gitlab-foss/uploads/c4cc8cd353604bd80315f9384035ff9e/The_Internet_IT_Crowd.png) )的访问. + +**注意:** Redis 节点(主节点和副本节点)将需要使用`redis['password']`定义的相同密码. 在故障转移期间的任何时间,Sentinels 都可以重新配置节点并将其状态从主节点更改为副本节点,反之亦然. + +#### Configuring the primary Redis instance[](#configuring-the-primary-redis-instance "Permalink") + +1. SSH 进入**主** Redis 服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 确保选择正确的 Omnibus 软件包,并使用与当前安装相同的版本和类型(社区版,企业版). + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + # Specify server role as 'redis_master_role' + roles ['redis_master_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.61' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Set up password authentication for Redis (use the same password in all nodes). + redis['password'] = 'redis-password-goes-here' + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + redis_exporter['flags'] = { + 'redis.addr' => 'redis://10.6.0.61:6379', + 'redis.password' => 'redis-password-goes-here', + } + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**注意:**您可以将多个角色(如哨兵和 Redis)指定为: `roles ['redis_sentinel_role', 'redis_master_role']` . 阅读有关[角色的](https://docs.gitlab.com/omnibus/roles/)更多信息. + +您可以通过以下方式列出当前 Redis 主副本服务器状态: + +``` +/opt/gitlab/embedded/bin/redis-cli -h -a 'redis-password-goes-here' info replication +``` + +通过以下方式显示正在运行的 GitLab 服务: + +``` +gitlab-ctl status +``` + +输出应类似于以下内容: + +``` +run: consul: (pid 30043) 76863s; run: log: (pid 29691) 76892s +run: logrotate: (pid 31152) 3070s; run: log: (pid 29595) 76908s +run: node-exporter: (pid 30064) 76862s; run: log: (pid 29624) 76904s +run: redis: (pid 30070) 76861s; run: log: (pid 29573) 76914s +run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s +``` + +#### Configuring the replica Redis instances[](#configuring-the-replica-redis-instances "Permalink") + +1. SSH 进入**副本** Redis 服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 确保选择正确的 Omnibus 软件包,并使用与当前安装相同的版本和类型(社区版,企业版). + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + # Specify server role as 'redis_replica_role' + roles ['redis_replica_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.62' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # The same password for Redis authentication you set up for the primary node. + redis['password'] = 'redis-password-goes-here' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + redis_exporter['flags'] = { + 'redis.addr' => 'redis://10.6.0.62:6379', + 'redis.password' => 'redis-password-goes-here', + } + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +5. 对于所有其他副本节点,请再次执行该步骤,并确保正确设置 IP. + +**注意:**您可以将多个角色(如哨兵和 Redis)指定为: `roles ['redis_sentinel_role', 'redis_master_role']` . 阅读有关[角色的](https://docs.gitlab.com/omnibus/roles/)更多信息. + +故障转移后, `/etc/gitlab/gitlab.rb`在`/etc/gitlab/gitlab.rb`再次更改这些值,因为节点将由[Sentinels](#configure-consul-and-sentinel)管理,即使在`gitlab-ctl reconfigure` ,它们也将通过恢复配置恢复.同样的哨兵 + +支持高级[配置选项](https://docs.gitlab.com/omnibus/settings/redis.html) ,可以根据需要添加. + +[Back to setup components](#setup-components) + +## Configure Consul and Sentinel[](#configure-consul-and-sentinel "Permalink") + +**注意:**如果您使用的是外部 Redis Sentinel 实例,请确保从 Sentinel 配置中排除`requirepass`参数. 此参数将导致客户端报告`NOAUTH Authentication required.` . [Redis Sentinel 3.2.x 不支持密码身份验证](https://github.com/antirez/redis/issues/3279) . + +现在已经全部安装了 Redis 服务器,让我们配置 Sentinel 服务器. 以下 IP 将作为示例: + +* `10.6.0.11` :领事/前哨 1 +* `10.6.0.12` :领事/前哨 2 +* `10.6.0.13` :领事/前哨 3 + +要配置 Sentinel: + +1. SSH 进入将托管 Consul / Sentinel 的服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/) Omnibus GitLab 企业版软件包. + * 确保选择正确的 Omnibus 软件包,并且与 GitLab 应用程序正在运行的版本相同. + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + roles ['redis_sentinel_role', 'consul_role'] + + # Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + # The same password for Redis authentication you set up for the primary node. + redis['master_password'] = 'redis-password-goes-here' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Configure Sentinel + sentinel['bind'] = '10.6.0.11' + + # Port that Sentinel listens on, uncomment to change to non default. Defaults + # to `26379`. + # sentinel['port'] = 26379 + + ## Quorum must reflect the amount of voting sentinels it take to start a failover. + ## Value must NOT be greater then the amount of sentinels. + ## + ## The quorum can be used to tune Sentinel in two ways: + ## 1\. If a the quorum is set to a value smaller than the majority of Sentinels + ## we deploy, we are basically making Sentinel more sensible to primary failures, + ## triggering a failover as soon as even just a minority of Sentinels is no longer + ## able to talk with the primary. + ## 1\. If a quorum is set to a value greater than the majority of Sentinels, we are + ## making Sentinel able to failover only when there are a very large number (larger + ## than majority) of well connected Sentinels which agree about the primary being down.s + sentinel['quorum'] = 2 + + ## Consider unresponsive server down after x amount of ms. + # sentinel['down_after_milliseconds'] = 10000 + + ## Specifies the failover timeout in milliseconds. It is used in many ways: + ## + ## - The time needed to re-start a failover after a previous failover was + ## already tried against the same primary by a given Sentinel, is two + ## times the failover timeout. + ## + ## - The time needed for a replica replicating to a wrong primary according + ## to a Sentinel current configuration, to be forced to replicate + ## with the right primary, is exactly the failover timeout (counting since + ## the moment a Sentinel detected the misconfiguration). + ## + ## - The time needed to cancel a failover that is already in progress but + ## did not produced any configuration change (REPLICAOF NO ONE yet not + ## acknowledged by the promoted replica). + ## + ## - The maximum time a failover in progress waits for all the replica to be + ## reconfigured as replicas of the new primary. However even after this time + ## the replicas will be reconfigured by the Sentinels anyway, but not with + ## the exact parallel-syncs progression as specified. + # sentinel['failover_timeout'] = 60000 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + server: true, + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +5. 对于其他所有 Consul / Sentinel 节点,请再次执行步骤,并确保设置了正确的 IP. + +**注意:**第三个 Consul 服务器的配置完成后,将选举 Consul 负责人. 查看领事日志`sudo gitlab-ctl tail consul`将显示`...[INFO] consul: New leader elected: ...` + +You can list the current Consul members (server, client): + +``` +sudo /opt/gitlab/embedded/bin/consul members +``` + +您可以验证 GitLab 服务正在运行: + +``` +sudo gitlab-ctl status +``` + +输出应类似于以下内容: + +``` +run: consul: (pid 30074) 76834s; run: log: (pid 29740) 76844s +run: logrotate: (pid 30925) 3041s; run: log: (pid 29649) 76861s +run: node-exporter: (pid 30093) 76833s; run: log: (pid 29663) 76855s +run: sentinel: (pid 30098) 76832s; run: log: (pid 29704) 76850s +``` + +[Back to setup components](#setup-components) + +## Configure PostgreSQL[](#configure-postgresql "Permalink") + +在本节中,将指导您配置与 GitLab 一起使用的外部 PostgreSQL 数据库. + +### Provide your own PostgreSQL instance[](#provide-your-own-postgresql-instance "Permalink") + +如果您将 GitLab 托管在云提供商上,则可以选择将托管服务用于 PostgreSQL. 例如,AWS 提供了运行 PostgreSQL 的托管关系数据库服务(RDS). + +如果您使用云托管服务,或提供自己的 PostgreSQL: + +1. 根据[数据库要求文档](../../install/requirements.html#database)设置 PostgreSQL. +2. 使用您选择的密码设置一个`gitlab`用户名. `gitlab`用户需要特权才能创建`gitlabhq_production`数据库. +3. 使用适当的详细信息配置 GitLab 应用程序服务器. [配置 GitLab Rails 应用程序](#configure-gitlab-rails)涵盖了此步骤. + +### Standalone PostgreSQL using Omnibus GitLab[](#standalone-postgresql-using-omnibus-gitlab "Permalink") + +以下 IP 将作为示例: + +* `10.6.0.31`主 +* `10.6.0.32`中学 1 +* `10.6.0.33`中学 2 + +首先,请确保**在每个节点上** [安装](https://about.gitlab.com/install/) Linux GitLab 软件包. 按照以下步骤,从步骤 1 安装必需的依赖项,并从步骤 2 添加 GitLab 软件包存储库.在第二步中安装 GitLab 时,请勿提供`EXTERNAL_URL`值. + +#### PostgreSQL primary node[](#postgresql-primary-node "Permalink") + +1. SSH 进入 PostgreSQL 主节点. +2. 为 PostgreSQL 用户名/密码对生成密码哈希. 假设您将使用默认用户名`gitlab` (推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作``的值: + + ``` + sudo gitlab-ctl pg-password-md5 gitlab + ``` + +3. 为 PgBouncer 用户名/密码对生成密码哈希. 假设您将使用`pgbouncer`的默认用户名(推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作``的值: + + ``` + sudo gitlab-ctl pg-password-md5 pgbouncer + ``` + +4. 为 Consul 数据库用户名/密码对生成密码哈希. 假设您将使用默认用户名`gitlab-consul` (推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作``的值: + + ``` + sudo gitlab-ctl pg-password-md5 gitlab-consul + ``` + +5. 在主数据库节点上,编辑`/etc/gitlab/gitlab.rb`替换`/etc/gitlab/gitlab.rb` `# START user configuration`部分中记录的值: + + ``` + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # START user configuration + # Please set the real values as explained in Required Information section + # + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace XXX.XXX.XXX.XXX/YY with Network Address + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + postgres_exporter['dbname'] = 'gitlabhq_production' + postgres_exporter['password'] = '' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + # + # END user configuration + ``` + +6. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +7. 您可以通过以下方式列出当前 PostgreSQL 主,辅助节点的状态: + + ``` + sudo /opt/gitlab/bin/gitlab-ctl repmgr cluster show + ``` + +8. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 30593) 77133s; run: log: (pid 29912) 77156s + run: logrotate: (pid 23449) 3341s; run: log: (pid 29794) 77175s + run: node-exporter: (pid 30613) 77133s; run: log: (pid 29824) 77170s + run: postgres-exporter: (pid 30620) 77132s; run: log: (pid 29894) 77163s + run: postgresql: (pid 30630) 77132s; run: log: (pid 29618) 77181s + run: repmgrd: (pid 30639) 77132s; run: log: (pid 29985) 77150s + ``` + +[Back to setup components](#setup-components) + +#### PostgreSQL secondary nodes[](#postgresql-secondary-nodes "Permalink") + +1. 在两个辅助节点上,添加与上面为主要节点指定的配置相同的附加设置,该设置将告知`gitlab-ctl`最初它们是备用节点,无需尝试将它们注册为主要节点: + + ``` + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # Specify if a node should attempt to be primary on initialization. + repmgr['master_on_initialization'] = false + + # START user configuration + # Please set the real values as explained in Required Information section + # + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace XXX.XXX.XXX.XXX/YY with Network Address + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + postgres_exporter['dbname'] = 'gitlabhq_production' + postgres_exporter['password'] = '' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + # END user configuration + ``` + +2. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +支持高级[配置选项](https://docs.gitlab.com/omnibus/settings/database.html) ,可以根据需要添加. + +[Back to setup components](#setup-components) + +#### PostgreSQL post-configuration[](#postgresql-post-configuration "Permalink") + +SSH 进入**主节点** : + +1. 打开数据库提示: + + ``` + gitlab-psql -d gitlabhq_production + ``` + +2. Enable the `pg_trgm` extension: + + ``` + CREATE EXTENSION pg_trgm; + ``` + +3. 键入`\q`并按 Enter 退出数据库提示. + +4. 验证集群是否已用一个节点初始化: + + ``` + gitlab-ctl repmgr cluster show + ``` + + 输出应类似于以下内容: + + ``` + Role | Name | Upstream | Connection String + ----------+----------|----------|---------------------------------------- + * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr + ``` + +5. 在连接字符串中记下主机名或 IP 地址: `host=HOSTNAME` . 在下一节中,我们将主机名称为`` . 如果该值不是 IP 地址,则必须是可解析的名称(通过 DNS 或`/etc/hosts` ) + +SSH 进入**辅助节点** : + +1. 设置 repmgr 备用数据库: + + ``` + gitlab-ctl repmgr standby setup + ``` + + Do note that this will remove the existing data on the node. The command has a wait time. + + 输出应类似于以下内容: + + ``` + Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data + If this is not what you want, hit Ctrl-C now to exit + To skip waiting, rerun with the -w option + Sleeping for 30 seconds + Stopping the database + Removing the data + Cloning the data + Starting the database + Registering the node with the cluster + ok: run: repmgrd: (pid 19068) 0s + ``` + +在继续之前,请确保正确配置了数据库. 在**主**节点上运行以下命令以验证复制是否正常工作,并且辅助节点是否出现在群集中: + +``` +gitlab-ctl repmgr cluster show +``` + +输出应类似于以下内容: + +``` +Role | Name | Upstream | Connection String +----------+---------|-----------|------------------------------------------------ +* master | MASTER | | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr +``` + +如果任何节点的"角色"列显示"失败",请在继续操作之前检查" [故障排除"部分](troubleshooting.html) . + +另外,请检查`repmgr-check-master`命令在每个节点上是否都能正常工作: + +``` +su - gitlab-consul +gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' +``` + +此命令依靠退出代码来告诉 Consul 特定节点是主节点还是辅助节点. 这里最重要的是该命令不会产生错误. 如果有错误,很可能是由于`gitlab-consul`数据库用户权限不正确`gitlab-consul` . 在继续之前,请检查" [故障排除"部分](troubleshooting.html) . + +[Back to setup components](#setup-components) + +## Configure PgBouncer[](#configure-pgbouncer "Permalink") + +现在已经安装了 PostgreSQL 服务器,让我们配置 PgBouncer. 以下 IP 将作为示例: + +* `10.6.0.21` :PgBouncer 1 +* `10.6.0.22` :PgBouncer 2 +* `10.6.0.23` :PgBouncer 3 + +1. 在每个 PgBouncer 节点上,编辑`/etc/gitlab/gitlab.rb` ,并将``和``替换为[之前设置](#postgresql-primary-node)的密码哈希: + + ``` + # Disable all components except Pgbouncer and Consul agent + roles ['pgbouncer_role'] + + # Configure PgBouncer + pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) + + pgbouncer['users'] = { + 'gitlab-consul': { + password: '' + }, + 'pgbouncer': { + password: '' + } + } + + # Configure Consul agent + consul['watchers'] = %w(postgresql) + consul['enable'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + pgbouncer_exporter['listen_address'] = '0.0.0.0:9188' + ``` + +2. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +3. 创建一个`.pgpass`文件,以便 Consul 能够重新加载 PgBouncer. 询问时两次输入 PgBouncer 密码: + + ``` + gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul + ``` + +4. 确保每个节点都在与当前主节点通信: + + ``` + gitlab-ctl pgb-console # You will be prompted for PGBOUNCER_PASSWORD + ``` + + 如果出现错误`psql: ERROR: Auth failed`输入密码后`psql: ERROR: Auth failed` ,请确保您以前以正确的格式生成了 MD5 密码哈希. 正确的格式是连接密码和用户名`PASSWORDUSERNAME` . 例如, `Sup3rS3cr3tpgbouncer`将是为`pgbouncer`用户生成 MD5 密码哈希所需的文本. + +5. 控制台提示可用后,请运行以下查询: + + ``` + show databases ; show clients ; + ``` + + 输出应类似于以下内容: + + ``` + name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections + ---------------------+-------------+------+---------------------+------------+-----------+--------------+-----------+-----------------+--------------------- + gitlabhq_production | MASTER_HOST | 5432 | gitlabhq_production | | 20 | 0 | | 0 | 0 + pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0 + (2 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | remote_pid | tls + ------+-----------+---------------------+---------+----------------+-------+------------+------------+---------------------+---------------------+-----------+------+------------+----- + C | pgbouncer | pgbouncer | active | 127.0.0.1 | 56846 | 127.0.0.1 | 6432 | 2017-08-21 18:09:59 | 2017-08-21 18:10:48 | 0x22b3880 | | 0 | + (2 rows) + ``` + +6. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + The output should be similar to the following: + + ``` + run: consul: (pid 31530) 77150s; run: log: (pid 31106) 77182s + run: logrotate: (pid 32613) 3357s; run: log: (pid 30107) 77500s + run: node-exporter: (pid 31550) 77149s; run: log: (pid 30138) 77493s + run: pgbouncer: (pid 32033) 75593s; run: log: (pid 31117) 77175s + run: pgbouncer-exporter: (pid 31558) 77148s; run: log: (pid 31498) 77156s + ``` + +[Back to setup components](#setup-components) + +### Configure the internal load balancer[](#configure-the-internal-load-balancer "Permalink") + +如果按照建议运行多个 PgBouncer 节点,那么此时,您将需要设置一个 TCP 内部负载均衡器以正确地服务每个负载均衡器. + +以下 IP 将作为示例: + +* `10.6.0.20` :内部负载均衡器 + +使用[HAProxy 的方法](https://www.haproxy.org/)如下: + +``` +global + log /dev/log local0 + log localhost local1 notice + log stdout format raw local0 + +defaults + log global + default-server inter 10s fall 3 rise 2 + balance leastconn + +frontend internal-pgbouncer-tcp-in + bind *:6432 + mode tcp + option tcplog + + default_backend pgbouncer + +backend pgbouncer + mode tcp + option tcp-check + + server pgbouncer1 10.6.0.21:6432 check + server pgbouncer2 10.6.0.22:6432 check + server pgbouncer3 10.6.0.23:6432 check +``` + +请参阅您首选的负载均衡器的文档以获取更多指导. + +[Back to setup components](#setup-components) + +## Configure Gitaly[](#configure-gitaly "Permalink") + +在自己的服务器上部署 Gitaly 可以使大于单个计算机的 GitLab 安装受益. + +Gitaly 节点要求取决于客户数据,特别是项目数量及其存储库大小. 建议将两个节点作为绝对最小值. 每个 Gitaly 节点应存储的数据不超过 5TB,并将[`gitaly-ruby`工作者](../gitaly/index.html#gitaly-ruby)的数量设置为可用 CPU 的 20%. 根据以上建议,应结合其他节点并结合对预期数据大小和分布的审查. + +强烈建议所有 Gitaly 节点都安装 SSD 磁盘,因为 Gitaly I / O 繁重,因此其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +注意事项: + +* GitLab Rails 应用程序将[存储库分](../repository_storage_paths.html)片到[存储库中](../repository_storage_paths.html) . +* Gitaly 服务器可以托管一个或多个存储. +* 一个 GitLab 服务器可以使用一个或多个 Gitaly 服务器. +* 必须以对所有 Gitaly 客户端正确解析的方式指定 Gitaly 地址. +* Gitaly 服务器一定不能暴露在公共互联网上,因为默认情况下,Gitaly 的网络流量是未加密的. 强烈建议使用防火墙以限制对 Gitaly 服务器的访问. 另一种选择是[使用 TLS](#gitaly-tls-support) . + +**提示:**有关 Gitaly 历史和网络体系结构的更多信息,请参见[独立的 Gitaly 文档](../gitaly/index.html) . + +注意: **注意:** Gitaly 文档中引用的令牌只是管理员选择的任意密码. 它与为 GitLab API 创建的令牌或其他类似的 Web API 令牌无关. + +下面我们描述如何配置两个具有 IP 和域名的 Gitaly 服务器: + +* `10.6.0.51` 1( `gitaly1.internal` ) +* `10.6.0.52` 2( `gitaly2.internal` ) + +假定该秘密令牌为`gitalysecret` ,并且您的 GitLab 安装具有三个存储库存储: + +* `default`为 Gitaly 1 +* `storage1`在 Gitaly 1 +* `storage2`上 Gitaly 2 + +在每个节点上: + +1. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包,但**不**提供`EXTERNAL_URL`值. +2. 编辑`/etc/gitlab/gitlab.rb`以配置存储路径,启用网络侦听器并配置令牌: + + ``` + # /etc/gitlab/gitlab.rb + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the GitLab Rails application setup + gitaly['auth_token'] = 'gitlaysecret' + gitlab_shell['secret_token'] = 'shellsecret' + + # Avoid running unnecessary services on the Gitaly server + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + grafana['enable'] = false + gitlab_exporter['enable'] = false + + # If you run a seperate monitoring node you can disable these services + alertmanager['enable'] = false + prometheus['enable'] = false + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your 'front door' GitLab URL or an internal load + # balancer. + # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server. + gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' + + # Make Gitaly accept connections on all network interfaces. You must use + # firewalls to restrict access to this address/port. + # Comment out following line if you only want to support TLS connections + gitaly['listen_addr'] = "0.0.0.0:8075" + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + gitaly['prometheus_listen_addr'] = "0.0.0.0:9236" + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_rails['prometheus_address'] = '10.6.0.81:9090' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + ``` + +3. 对于每个服务器,将以下内容附加到`/etc/gitlab/gitlab.rb` : + 1. 在`gitaly1.internal` : + + ``` + git_data_dirs ({ 'default' => { 'path' => '/var/opt/gitlab/git-data' }, 'storage1' => { 'path' => '/mnt/gitlab/git-data' }, }) + ``` + + 2. 在`gitaly2.internal` : + + ``` + git_data_dirs ({ 'storage2' => { 'path' => '/mnt/gitlab/git-data' }, }) + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 确认 Gitaly 可以执行对内部 API 的回调: + + ``` + sudo /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml + ``` + +6. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 30339) 77006s; run: log: (pid 29878) 77020s + run: gitaly: (pid 30351) 77005s; run: log: (pid 29660) 77040s + run: logrotate: (pid 7760) 3213s; run: log: (pid 29782) 77032s + run: node-exporter: (pid 30378) 77004s; run: log: (pid 29812) 77026s + ``` + +### Gitaly TLS support[](#gitaly-tls-support "Permalink") + +Gitaly 支持 TLS 加密. 为了能够与侦听安全连接的 Gitaly 实例进行通信,您将需要在 GitLab 配置中相应存储条目的`gitaly_address`中使用`tls://` URL 方案. + +您将需要携带自己的证书,因为该证书不会自动提供. 证书或其证书颁发机构必须按照[GitLab 自定义证书配置中](https://docs.gitlab.com/omnibus/settings/ssl.html)所述的步骤,安装在所有 Gitaly 节点(包括使用证书的 Gitaly 节点)上,以及与之通信的所有客户端节点上. + +**注意:**自签名证书必须指定用于访问 Gitaly 服务器的地址. 如果要通过主机名寻址 Gitaly 服务器,则可以为此使用"公用名"字段,也可以将其添加为"使用者备用名". 如果要通过 Gitaly 服务器的 IP 地址对其进行寻址,则必须将其作为主题备用名称添加到证书中. [gRPC 不支持在证书中使用 IP 地址作为公用名](https://github.com/grpc/grpc/issues/2691) .**注意:**可以同时为 Gitaly 服务器配置未加密的侦听地址`listen_addr`和已加密的侦听地址`tls_listen_addr` . 如果需要,这使您可以从未加密的流量逐渐过渡到加密的流量. + +要使用 TLS 配置 Gitaly: + +1. 创建`/etc/gitlab/ssl`目录,并在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +2. 将证书复制到`/etc/gitlab/trusted-certs`以便 Gitaly 在调用自身时信任该证书: + + ``` + sudo cp /etc/gitlab/ssl/cert.pem /etc/gitlab/trusted-certs/ + ``` + +3. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + gitaly['tls_listen_addr'] = "0.0.0.0:9999" + gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + gitaly['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +4. 删除`gitaly['listen_addr']`以仅允许加密连接. +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +[Back to setup components](#setup-components) + +## Configure Sidekiq[](#configure-sidekiq "Permalink") + +Sidekiq 需要连接到 Redis,PostgreSQL 和 Gitaly 实例. 以下 IP 将作为示例: + +* `10.6.0.71` :Sidekiq 1 +* `10.6.0.72` :Sidekiq 2 +* `10.6.0.73` :Sidekiq 3 +* `10.6.0.74` :Sidekiq 4 + +要配置 Sidekiq 节点,每个节点一个: + +1. SSH 到 Sidekiq 服务器. +2. 从 GitLab 下载页面使用步骤 1 和 2 [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. **不要完成下载页面上的任何其他步骤.** +3. 使用编辑器打开`/etc/gitlab/gitlab.rb` : + + ``` + ######################################## + ##### Services Disabled ### + ######################################## + + nginx['enable'] = false + grafana['enable'] = false + prometheus['enable'] = false + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + puma['enable'] = false + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + gitlab_exporter['enable'] = false + + ######################################## + #### Redis ### + ######################################## + + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + ## The same password for Redis authentication you set up for the master node. + redis['master_password'] = '' + + ## A list of sentinels with `host` and `port` + gitlab_rails['redis_sentinels'] = [ + {'host' => '10.6.0.11', 'port' => 26379}, + {'host' => '10.6.0.12', 'port' => 26379}, + {'host' => '10.6.0.13', 'port' => 26379}, + ] + + ####################################### + ### Gitaly ### + ####################################### + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + + ####################################### + ### Postgres ### + ####################################### + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['auto_migrate'] = false + + ####################################### + ### Sidekiq configuration ### + ####################################### + sidekiq['listen_address'] = "0.0.0.0" + + ####################################### + ### Monitoring configuration ### + ####################################### + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + + # Rails Status for prometheus + gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8'] + gitlab_rails['prometheus_address'] = '10.6.0.81:9090' + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 30114) 77353s; run: log: (pid 29756) 77367s + run: logrotate: (pid 9898) 3561s; run: log: (pid 29653) 77380s + run: node-exporter: (pid 30134) 77353s; run: log: (pid 29706) 77372s + run: sidekiq: (pid 30142) 77351s; run: log: (pid 29638) 77386s + ``` + +**提示:**您还可以运行[多个 Sidekiq 进程](../operations/extra_sidekiq_processes.html) .[Back to setup components](#setup-components) + +## Configure GitLab Rails[](#configure-gitlab-rails "Permalink") + +**注意:**在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数设置为可用 CPU 的 90%以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +本节介绍如何配置 GitLab 应用程序(Rails)组件. 在每个节点上执行以下操作: + +1. 如果您[使用的是 NFS](#configure-nfs-optional) : + + 1. 如有必要,请使用以下命令安装 NFS 客户端实用程序软件包: + + ``` + # Ubuntu/Debian + apt-get install nfs-common + + # CentOS/Red Hat + yum install nfs-utils nfs-utils-lib + ``` + + 2. 在`/etc/fstab`指定必要的 NFS 挂载. `/etc/fstab`的确切内容取决于您选择配置 NFS 服务器的方式. 有关示例和各种选项,请参见[NFS 文档](../high_availability/nfs.html) . + + 3. 创建共享目录. 这些可能会有所不同,具体取决于您的 NFS 安装位置. + + ``` + mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data + ``` + +2. 使用[GitLab 下载中的](https://about.gitlab.com/install/) **步骤 1 和 2**下载/安装 Omnibus GitLab. 不要完成下载页面上的其他步骤. +3. 创建/编辑`/etc/gitlab/gitlab.rb`并使用以下配置. 为了保持整个节点的链接均匀性, `external_url`在应用服务器上应指向外部 URL,用户将用来访问 GitLab. 这将是[外部负载平衡器](#configure-the-external-load-balancer)的 URL,它将[负载](#configure-the-external-load-balancer)流量路由到 GitLab 应用程序服务器: + + ``` + external_url 'https://gitlab.example.com' + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the Gitaly setup + gitlab_rails['gitaly_token'] = 'gitalyecret' + gitlab_shell['secret_token'] = 'shellsecret' + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + + ## Disable components that will not be on the GitLab application server + roles ['application_role'] + gitaly['enable'] = false + nginx['enable'] = true + sidekiq['enable'] = false + + ## PostgreSQL connection details + # Disable PostgreSQL on the application node + postgresql['enable'] = false + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['auto_migrate'] = false + + ## Redis connection details + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + ## The same password for Redis authentication you set up for the Redis primary node. + redis['master_password'] = '' + + ## A list of sentinels with `host` and `port` + gitlab_rails['redis_sentinels'] = [ + {'host' => '10.6.0.11', 'port' => 26379}, + {'host' => '10.6.0.12', 'port' => 26379}, + {'host' => '10.6.0.13', 'port' => 26379} + ] + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' + sidekiq['listen_address'] = "0.0.0.0" + puma['listen'] = '0.0.0.0' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Add the monitoring node's IP address to the monitoring whitelist and allow it to + # scrape the NGINX metrics + gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8'] + nginx['status']['options']['allow'] = ['10.6.0.81/32', '127.0.0.0/8'] + gitlab_rails['prometheus_address'] = '10.6.0.81:9090' + + ## Uncomment and edit the following options if you have set up NFS + ## + ## Prevent GitLab from starting if NFS data mounts are not available + ## + #high_availability['mountpoint'] = '/var/opt/gitlab/git-data' + ## + ## Ensure UIDs and GIDs match between servers for permissions via NFS + ## + #user['uid'] = 9000 + #user['gid'] = 9000 + #web_server['uid'] = 9001 + #web_server['gid'] = 9001 + #registry['uid'] = 9002 + #registry['gid'] = 9002 + ``` + +4. 如果您正在使用[具有 TLS 支持](#gitaly-tls-support)的`git_data_dirs` ,请确保`git_data_dirs`条目配置了`tls`而不是`tcp` : + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' }, + }) + ``` + + 1. 将证书复制到`/etc/gitlab/trusted-certs` : + + ``` + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +6. 运行`sudo gitlab-rake gitlab:gitaly:check`确认节点可以连接到 Gitaly. +7. 拖尾日志以查看请求: + + ``` + sudo gitlab-ctl tail gitaly + ``` + +8. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 4890) 8647s; run: log: (pid 29962) 79128s + run: gitlab-exporter: (pid 4902) 8647s; run: log: (pid 29913) 79134s + run: gitlab-workhorse: (pid 4904) 8646s; run: log: (pid 29713) 79155s + run: logrotate: (pid 12425) 1446s; run: log: (pid 29798) 79146s + run: nginx: (pid 4925) 8646s; run: log: (pid 29726) 79152s + run: node-exporter: (pid 4931) 8645s; run: log: (pid 29855) 79140s + run: puma: (pid 4936) 8645s; run: log: (pid 29656) 79161s + ``` + +**注意:**如上例所示,当在`external_url`指定`https`时,GitLab 会假定您在`/etc/gitlab/ssl/`具有 SSL 证书. 如果没有证书,NGINX 将无法启动. 有关更多信息,请参见[NGINX 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### GitLab Rails post-configuration[](#gitlab-rails-post-configuration "Permalink") + +1. 确保运行所有迁移: + + ``` + gitlab-rake gitlab:db:configure + ``` + + **注意:**如果遇到`rake aborted!` 错误,指出 PgBouncer 是无法连接到 PostgreSQL 也可能是您的 PgBouncer 节点的 IP 地址是从 PostgreSQL 的缺失`trust_auth_cidr_addresses`在`gitlab.rb`你的数据库节点. 请参阅"故障排除"部分中的[PgBouncer 错误`ERROR: pgbouncer cannot connect to server`](troubleshooting.html#pgbouncer-error-error-pgbouncer-cannot-connect-to-server) ,然后再继续. +2. [Configure fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.html). + +[Back to setup components](#setup-components) + +## Configure Prometheus[](#configure-prometheus "Permalink") + +Omnibus GitLab 软件包可用于配置运行[Prometheus](../monitoring/prometheus/index.html)和[Grafana](../monitoring/performance/grafana_configuration.html)的独立 Monitoring 节点: + +1. SSH 进入"监视"节点. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + external_url 'http://gitlab.example.com' + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + node_exporter['enable'] = false + gitlab_exporter['enable'] = false + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Login form + grafana['disable_login_form'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = '' + + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 在 GitLab 用户界面中,将`admin/application_settings/metrics_and_profiling` >指标-Grafana 设置为`/-/grafana`到`http[s]:///-/grafana` . +6. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 31637) 17337s; run: log: (pid 29748) 78432s + run: grafana: (pid 31644) 17337s; run: log: (pid 29719) 78438s + run: logrotate: (pid 31809) 2936s; run: log: (pid 29581) 78462s + run: nginx: (pid 31665) 17335s; run: log: (pid 29556) 78468s + run: prometheus: (pid 31672) 17335s; run: log: (pid 29633) 78456s + ``` + +[Back to setup components](#setup-components) + +## Configure the object storage[](#configure-the-object-storage "Permalink") + +GitLab 支持使用对象存储服务来保存多种类型的数据. 建议在[NFS](#configure-nfs-optional)上使用它,并且通常在较大的设置中更好,因为对象存储通常具有更高的性能,可靠性和可伸缩性. + +manbetx 客户端打不开已经测试过或知道使用的客户的对象存储选项包括: + +* SaaS / Cloud 解决方案,例如[Amazon S3](https://aws.amazon.com/s3/) , [Google 云存储](https://cloud.google.com/storage) . +* 来自各种存储供应商的本地硬件和设备. +* MinIO. 我们的 Helm Chart 文档中[提供了有关部署的指南](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) . + +要配置 GitLab 以使用对象存储,请根据要使用的功能参考以下指南: + +1. Configure [object storage for backups](../../raketasks/backup_restore.html#uploading-backups-to-a-remote-cloud-storage). +2. Configure [object storage for job artifacts](../job_artifacts.html#using-object-storage) including [incremental logging](../job_logs.html#new-incremental-logging-architecture). +3. Configure [object storage for LFS objects](../lfs/index.html#storing-lfs-objects-in-remote-object-storage). +4. Configure [object storage for uploads](../uploads.html#using-object-storage-core-only). +5. Configure [object storage for merge request diffs](../merge_request_diffs.html#using-object-storage). +6. 配置[容器注册表的对象存储](../packages/container_registry.html#use-object-storage) (可选功能). +7. [为 Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)配置[对象存储](https://docs.mattermost.com/administration/config-settings.html#file-storage) (可选功能). +8. 配置[软件包的对象存储](../packages/index.html#using-object-storage) (可选功能). +9. 配置[依赖项代理的对象存储](../packages/dependency_proxy.html#using-object-storage) (可选功能). +10. [为 Pseudonymizer](../pseudonymizer.html#configuration) (可选功能)配置[对象存储](../pseudonymizer.html#configuration) . +11. 配置[对象存储以自动缩放 Runner 缓存](https://docs.gitlab.com/runner/configuration/autoscale.html) (可选-为了提高性能). +12. Configure [object storage for Terraform state files](../terraform_state.html#using-object-storage-core-only). + +对于 GitLab,建议为每种数据类型使用单独的存储桶. + +我们的配置的局限性是对象存储的每次使用都是单独配置的. [我们有一个需要改进的问题](https://gitlab.com/gitlab-org/gitlab/-/issues/23345) ,轻松地将一个存储桶与单独的文件夹一起使用可能会带来一个改进. + +使用同一个存储桶至少有一个特定的问题:当使用 Helm 图表部署 GitLab 时,除非使用单独的存储桶,否则从备份还原[将无法正常工作](https://docs.gitlab.com/charts/advanced/external-object-storage/) . + +如果您的组织将来决定将 GitLab 迁移到 Helm 部署,则使用单个存储桶的一种风险是. GitLab 可以运行,但是直到组织对备份起作用的关键要求之前,备份的情况可能无法实现. + +[Back to setup components](#setup-components) + +## Configure NFS (optional)[](#configure-nfs-optional "Permalink") + +建议尽可能在 NFS 上使用[对象存储](#configure-the-object-storage)以及[Gitaly](#configure-gitaly) ,以提高性能. 如果您打算使用 GitLab 页面,则当前[需要 NFS](troubleshooting.html#gitlab-pages-requires-nfs) . + +请参阅如何[配置 NFS](../high_availability/nfs.html) . + +[Back to setup components](#setup-components) + +## Troubleshooting[](#troubleshooting "Permalink") + +请参阅[故障排除文档](troubleshooting.html) . + +[Back to setup components](#setup-components) \ No newline at end of file diff --git a/_book/docs/424.md b/_book/docs/424.md new file mode 100644 index 0000000000000000000000000000000000000000..d80495f7a08268f1f8d8f78354cb5fc519d31fae --- /dev/null +++ b/_book/docs/424.md @@ -0,0 +1,1451 @@ +# Reference architecture: up to 5,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/5k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/5k_users.html) + +* [Setup components](#setup-components) +* [Configure the external load balancer](#configure-the-external-load-balancer) + * [Application node terminates SSL](#application-node-terminates-ssl) + * [Load balancer terminates SSL without backend SSL](#load-balancer-terminates-ssl-without-backend-ssl) + * [Load balancer terminates SSL with backend SSL](#load-balancer-terminates-ssl-with-backend-ssl) + * [Ports](#ports) + * [Alternate SSH Port](#alternate-ssh-port) +* [Configure Redis](#configure-redis) + * [Provide your own Redis instance](#provide-your-own-redis-instance) + * [Standalone Redis using Omnibus GitLab](#standalone-redis-using-omnibus-gitlab) + * [Configuring the primary Redis instance](#configuring-the-primary-redis-instance) + * [Configuring the replica Redis instances](#configuring-the-replica-redis-instances) +* [Configure Consul and Sentinel](#configure-consul-and-sentinel) +* [Configure PostgreSQL](#configure-postgresql) + * [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance) + * [Standalone PostgreSQL using Omnibus GitLab](#standalone-postgresql-using-omnibus-gitlab) + * [PostgreSQL primary node](#postgresql-primary-node) + * [PostgreSQL secondary nodes](#postgresql-secondary-nodes) + * [PostgreSQL post-configuration](#postgresql-post-configuration) +* [Configure PgBouncer](#configure-pgbouncer) + * [Configure the internal load balancer](#configure-the-internal-load-balancer) +* [Configure Gitaly](#configure-gitaly) + * [Gitaly TLS support](#gitaly-tls-support) +* [Configure Sidekiq](#configure-sidekiq) +* [Configure GitLab Rails](#configure-gitlab-rails) + * [GitLab Rails post-configuration](#gitlab-rails-post-configuration) +* [Configure Prometheus](#configure-prometheus) +* [Configure the object storage](#configure-the-object-storage) +* [Configure NFS (optional)](#configure-nfs-optional) +* [Troubleshooting](#troubleshooting) + +# Reference architecture: up to 5,000 users[](#reference-architecture-up-to-5000-users "Permalink") + +该页面描述了最多可容纳 5,000 个用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +**注意:**下面记录的 5,000 个用户参考体系结构旨在帮助您的组织实现高度可用的 GitLab 部署. 如果您没有专业知识或需要维护高度可用的环境,则可以遵循[2,000 个用户的参考体系结构](2k_users.html) ,从而拥有一个更简单且成本更低的操作环境. + +> * **支持的用户(大约):** 5,000 +> * **高可用性:** True +> * **测试 RPS 速率:** API:100 RPS,网站:10 RPS,Git:10 RPS + +| Service | Nodes | Configuration | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | --- | +| 外部负载平衡节点 | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| Redis | 3 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| 领事+前哨 | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| PostgreSQL | 3 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| PgBouncer | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| 内部负载平衡节点 | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| Gitaly | 最少 2 个 | 8 个 vCPU,30GB 内存 | `n1-standard-8` | `m5.2xlarge` | `D8s v3` | +| Sidekiq | 4 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| 亚搏体育 app Rails | 3 | 16 个 vCPU,14.4GB 内存 | `n1-highcpu-16` | `c5.4xlarge` | `F16s v2` | +| 监控节点 | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| 对象存储 | n/a | n/a | n/a | n/a | n/a | +| NFS 服务器(可选,不推荐) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` | + +这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. + +对于 LFS,Uploads,Artifacts 等数据对象,由于性能和可用性更好,建议在 NFS 上尽可能使用[对象存储服务](#configure-the-object-storage) . 由于这不需要设置节点,因此在上表中将其标记为不适用(n / a). + +## Setup components[](#setup-components "Permalink") + +设置 GitLab 及其组件以容纳多达 5,000 个用户: + +1. [配置外部负载平衡节点](#configure-the-external-load-balancer) ,该[节点](#configure-the-external-load-balancer)将处理两个 GitLab 应用程序服务节点的负载平衡. +2. [Configure Redis](#configure-redis). +3. [Configure Consul and Sentinel](#configure-consul-and-sentinel). +4. [配置 PostgreSQL](#configure-postgresql) (GitLab 的数据库). +5. [Configure PgBouncer](#configure-pgbouncer). +6. [Configure the internal load balancing node](#configure-the-internal-load-balancer) +7. [配置 Gitaly](#configure-gitaly) ,它提供对 Git 存储库的访问. +8. [Configure Sidekiq](#configure-sidekiq). +9. [配置主 GitLab Rails 应用程序](#configure-gitlab-rails)以运行 Puma / Unicorn,Workhorse,GitLab Shell,并服务所有前端请求(UI,API,基于 HTTP / SSH 的 Git). +10. [配置 Prometheus](#configure-prometheus)来监视您的 GitLab 环境. +11. [配置](#configure-the-object-storage)用于共享数据对象[的对象存储](#configure-the-object-storage) . +12. [将 NFS(可选)配置](#configure-nfs-optional)为具有共享磁盘存储服务,以替代 Gitaly 和/或对象存储(尽管不建议这样做). GitLab 页面需要 NFS,如果不使用该功能,则可以跳过此步骤. + +我们从同一 10.6.0.0/16 专用网络范围内的所有服务器开始,它们可以在这些地址上自由地相互连接. + +这是每台机器和分配的 IP 的列表和说明: + +* `10.6.0.10` :外部负载平衡器 +* `10.6.0.61`主要 +* `10.6.0.62` :返回副本 1 +* `10.6.0.63` :返回副本 2 +* `10.6.0.11` :领事/前哨 1 +* `10.6.0.12` :领事/前哨 2 +* `10.6.0.13` :领事/前哨 3 +* `10.6.0.31`主 +* `10.6.0.32`中学 1 +* `10.6.0.33`中学 2 +* `10.6.0.21` :PgBouncer 1 +* `10.6.0.22` :PgBouncer 2 +* `10.6.0.23` :PgBouncer 3 +* `10.6.0.20` :内部负载均衡器 +* `10.6.0.51` :Gitaly 1 +* `10.6.0.52` :Gitaly 2 +* `10.6.0.71` :Sidekiq 1 +* `10.6.0.72` :Sidekiq 2 +* `10.6.0.73` :Sidekiq 3 +* `10.6.0.74` :Sidekiq 4 +* `10.6.0.41`应用程序 1 +* `10.6.0.42`应用程序 2 +* `10.6.0.43`应用程序 3 +* `10.6.0.81` :普罗米修斯 + +## Configure the external load balancer[](#configure-the-external-load-balancer "Permalink") + +**注意:**此体系结构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +在主动/主动 GitLab 配置中,您将需要一个负载均衡器来将流量路由到应用程序服务器. 有关使用负载均衡器或进行确切配置的细节超出了 GitLab 文档的范围. 我们希望,如果您要管理像 GitLab 这样的多节点系统,那么已经选择了负载均衡器. 一些示例包括 HAProxy(开源),F5 Big-IP LTM 和 Citrix Net Scaler. 本文档将概述需要在 GitLab 上使用哪些端口和协议. + +下一个问题是如何在环境中处理 SSL. 有几种不同的选择: + +* [The application node terminates SSL](#application-node-terminates-ssl). +* [负载平衡器终止没有后端 SSL 的 SSL,](#load-balancer-terminates-ssl-without-backend-ssl)并且负载平衡器与应用程序节点之间的通信不安全. +* [负载均衡器使用后端 SSL 终止 SSL,](#load-balancer-terminates-ssl-with-backend-ssl)并且负载均衡器与应用程序节点之间的通信是*安全*的. + +### Application node terminates SSL[](#application-node-terminates-ssl "Permalink") + +配置您的负载均衡器以将端口 443 上的连接作为`TCP`而不是`HTTP(S)`协议进行传递. 这会将连接直接传递到应用程序节点的 NGINX 服务. NGINX 将具有 SSL 证书并在端口 443 上侦听. + +有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load balancer terminates SSL without backend SSL[](#load-balancer-terminates-ssl-without-backend-ssl "Permalink") + +将您的负载均衡器配置为使用`HTTP(S)`协议而不是`TCP` . 然后,负载平衡器将负责管理 SSL 证书和终止 SSL. + +由于负载均衡器和 GitLab 之间的通信将不安全,因此需要一些其他配置. 有关详细信息,请参见[NGINX 代理的 SSL 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load balancer terminates SSL with backend SSL[](#load-balancer-terminates-ssl-with-backend-ssl "Permalink") + +Configure your load balancer(s) to use the ‘HTTP(S)’ protocol rather than ‘TCP’. The load balancer(s) will be responsible for managing SSL certificates that end users will see. + +在这种情况下,负载均衡器和 NGINX 之间的流量也将是安全的. 无需为代理 SSL 添加配置,因为连接将一直保持安全. 但是,需要将配置添加到 GitLab 来配置 SSL 证书. 有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Ports[](#ports "Permalink") + +下表显示了要使用的基本端口. + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 80 | HTTP( *1* ) | +| 443 | 443 | TCP 或 HTTPS( *1* )( *2* ) | +| 22 | 22 | TCP | + +* ( *1* ): [Web 终端](../../ci/environments/index.html#web-terminals)支持要求您的负载平衡器正确处理 WebSocket 连接. 当使用 HTTP 或 HTTPS 代理,这意味着负载平衡器必须被配置为通过`Connection`和`Upgrade`逐跳头. 有关更多详细信息,请参见[Web 终端](../integration/terminal.html)集成指南. +* ( *2* ):当对端口 443 使用 HTTPS 协议时,需要向负载均衡器添加 SSL 证书. 如果您想在 GitLab 应用程序服务器上终止 SSL,请使用 TCP 协议. + +如果您使用具有自定义域支持的 GitLab 页面,则将需要一些其他端口配置. GitLab 页面需要一个单独的虚拟 IP 地址. 配置 DNS,将`pages_external_url`的`/etc/gitlab/gitlab.rb`指向新的虚拟 IP 地址. 有关更多信息,请参见[GitLab 页面文档](../pages/index.html) . + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 变化( *1* ) | HTTP | +| 443 | 变化( *1* ) | TCP( *2* ) | + +* ( *1* ):GitLab 页面的后端端口取决于`gitlab_pages['external_http']`和`gitlab_pages['external_https']`设置. 有关更多详细信息,请参见[GitLab Pages 文档](../pages/index.html) . +* ( *2* ):GitLab 页面的端口 443 应该始终使用 TCP 协议. 用户可以使用自定义 SSL 配置自定义域,如果 SSL 在负载均衡器处终止,则不可能. + +#### Alternate SSH Port[](#alternate-ssh-port "Permalink") + +某些组织有禁止打开 SSH 端口 22 的策略.在这种情况下,配置允许用户在端口 443 上使用 SSH 的备用 SSH 主机名可能会有所帮助.与其他 GitLab 相比,备用 SSH 主机名将需要一个新的虚拟 IP 地址.上面的 HTTP 配置. + +为备用 SSH 主机名(例如`altssh.gitlab.example.com`配置 DNS. + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 443 | 22 | TCP | + +[Back to setup components](#setup-components) + +## Configure Redis[](#configure-redis "Permalink") + +使用[Redis 的](https://s0redis0io.icopy.site/)可扩展环境,可以使用**一次** X **副本**拓扑与[Redis 的哨兵](https://s0redis0io.icopy.site/topics/sentinel)服务来观看,并自动启动故障转移过程. + +如果与 Sentinel 一起使用,Redis 需要身份验证. 有关更多信息,请参见[Redis 安全性](https://s0redis0io.icopy.site/topics/security)文档. 我们建议结合使用 Redis 密码和严格的防火墙规则来保护您的 Redis 服务. 强烈建议您在使用 GitLab 配置 Redis 之前阅读[Redis Sentinel](https://s0redis0io.icopy.site/topics/sentinel)文档,以充分了解拓扑和体系结构. + +在本节中,将指导您配置与 GitLab 一起使用的外部 Redis 实例. 以下 IP 将作为示例: + +* `10.6.0.61`主要 +* `10.6.0.62` :返回副本 1 +* `10.6.0.63` :返回副本 2 + +### Provide your own Redis instance[](#provide-your-own-redis-instance "Permalink") + +来自云提供商(例如 AWS ElastiCache)的托管 Redis 将可以使用. 如果这些服务支持高可用性,请确保它**不是** Redis 群集类型. + +需要 Redis 5.0 或更高版本,因为这是从 GitLab 13.0 开始的 Omnibus GitLab 软件包附带的版本. 较旧的 Redis 版本不支持 SPOP 的可选 count 参数,这对于[合并火车](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)现在是必需的. + +注意 Redis 节点的 IP 地址或主机名,端口和密码(如果需要). 这些在以后配置[GitLab 应用程序服务器](#configure-gitlab-rails)时是必需的. + +### Standalone Redis using Omnibus GitLab[](#standalone-redis-using-omnibus-gitlab "Permalink") + +这是我们安装和设置新 Redis 实例的部分. + +Redis 设置的要求如下: + +1. 所有 Redis 节点必须能够互相通信并接受通过 Redis( `6379` )和 Sentinel( `26379` )端口的传入连接(除非您更改默认端口). +2. 托管 GitLab 应用程序的服务器必须能够访问 Redis 节点. +3. 使用防火墙保护节点免受来自外部网络( [Internet](https://gitlab.com/gitlab-org/gitlab-foss/uploads/c4cc8cd353604bd80315f9384035ff9e/The_Internet_IT_Crowd.png) )的访问. + +**注意:** Redis 节点(主节点和副本节点)将需要使用`redis['password']`定义的相同密码. 在故障转移期间的任何时间,Sentinels 都可以重新配置节点并将其状态从主节点更改为副本节点,反之亦然. + +#### Configuring the primary Redis instance[](#configuring-the-primary-redis-instance "Permalink") + +1. SSH 进入**主** Redis 服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 确保选择正确的 Omnibus 软件包,并使用与当前安装相同的版本和类型(社区版,企业版). + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + # Specify server role as 'redis_master_role' + roles ['redis_master_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.61' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Set up password authentication for Redis (use the same password in all nodes). + redis['password'] = 'redis-password-goes-here' + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + redis_exporter['flags'] = { + 'redis.addr' => 'redis://10.6.0.61:6379', + 'redis.password' => 'redis-password-goes-here', + } + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**注意:**您可以将多个角色(如哨兵和 Redis)指定为: `roles ['redis_sentinel_role', 'redis_master_role']` . 阅读有关[角色的](https://docs.gitlab.com/omnibus/roles/)更多信息. + +您可以通过以下方式列出当前 Redis 主副本服务器状态: + +``` +/opt/gitlab/embedded/bin/redis-cli -h -a 'redis-password-goes-here' info replication +``` + +通过以下方式显示正在运行的 GitLab 服务: + +``` +gitlab-ctl status +``` + +输出应类似于以下内容: + +``` +run: consul: (pid 30043) 76863s; run: log: (pid 29691) 76892s +run: logrotate: (pid 31152) 3070s; run: log: (pid 29595) 76908s +run: node-exporter: (pid 30064) 76862s; run: log: (pid 29624) 76904s +run: redis: (pid 30070) 76861s; run: log: (pid 29573) 76914s +run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s +``` + +#### Configuring the replica Redis instances[](#configuring-the-replica-redis-instances "Permalink") + +1. SSH 进入**副本** Redis 服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 确保选择正确的 Omnibus 软件包,并使用与当前安装相同的版本和类型(社区版,企业版). + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + # Specify server role as 'redis_replica_role' + roles ['redis_replica_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.62' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # The same password for Redis authentication you set up for the primary node. + redis['password'] = 'redis-password-goes-here' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + redis_exporter['flags'] = { + 'redis.addr' => 'redis://10.6.0.62:6379', + 'redis.password' => 'redis-password-goes-here', + } + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +5. 对于所有其他副本节点,请再次执行该步骤,并确保正确设置 IP. + +**注意:**您可以将多个角色(如哨兵和 Redis)指定为: `roles ['redis_sentinel_role', 'redis_master_role']` . 阅读有关[角色的](https://docs.gitlab.com/omnibus/roles/)更多信息. + +故障转移后, `/etc/gitlab/gitlab.rb`在`/etc/gitlab/gitlab.rb`再次更改这些值,因为节点将由[Sentinels](#configure-consul-and-sentinel)管理,即使在`gitlab-ctl reconfigure` ,它们也将通过恢复配置恢复.同样的哨兵 + +支持高级[配置选项](https://docs.gitlab.com/omnibus/settings/redis.html) ,可以根据需要添加. + +[Back to setup components](#setup-components) + +## Configure Consul and Sentinel[](#configure-consul-and-sentinel "Permalink") + +**注意:**如果您使用的是外部 Redis Sentinel 实例,请确保从 Sentinel 配置中排除`requirepass`参数. 此参数将导致客户端报告`NOAUTH Authentication required.` . [Redis Sentinel 3.2.x 不支持密码身份验证](https://github.com/antirez/redis/issues/3279) . + +现在已经全部安装了 Redis 服务器,让我们配置 Sentinel 服务器. 以下 IP 将作为示例: + +* `10.6.0.11` :领事/前哨 1 +* `10.6.0.12` :领事/前哨 2 +* `10.6.0.13` :领事/前哨 3 + +要配置 Sentinel: + +1. SSH 进入将托管 Consul / Sentinel 的服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/) Omnibus GitLab 企业版软件包. + * 确保选择正确的 Omnibus 软件包,并且与 GitLab 应用程序正在运行的版本相同. + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + roles ['redis_sentinel_role', 'consul_role'] + + # Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + # The same password for Redis authentication you set up for the primary node. + redis['master_password'] = 'redis-password-goes-here' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Configure Sentinel + sentinel['bind'] = '10.6.0.11' + + # Port that Sentinel listens on, uncomment to change to non default. Defaults + # to `26379`. + # sentinel['port'] = 26379 + + ## Quorum must reflect the amount of voting sentinels it take to start a failover. + ## Value must NOT be greater then the amount of sentinels. + ## + ## The quorum can be used to tune Sentinel in two ways: + ## 1\. If a the quorum is set to a value smaller than the majority of Sentinels + ## we deploy, we are basically making Sentinel more sensible to primary failures, + ## triggering a failover as soon as even just a minority of Sentinels is no longer + ## able to talk with the primary. + ## 1\. If a quorum is set to a value greater than the majority of Sentinels, we are + ## making Sentinel able to failover only when there are a very large number (larger + ## than majority) of well connected Sentinels which agree about the primary being down.s + sentinel['quorum'] = 2 + + ## Consider unresponsive server down after x amount of ms. + # sentinel['down_after_milliseconds'] = 10000 + + ## Specifies the failover timeout in milliseconds. It is used in many ways: + ## + ## - The time needed to re-start a failover after a previous failover was + ## already tried against the same primary by a given Sentinel, is two + ## times the failover timeout. + ## + ## - The time needed for a replica replicating to a wrong primary according + ## to a Sentinel current configuration, to be forced to replicate + ## with the right primary, is exactly the failover timeout (counting since + ## the moment a Sentinel detected the misconfiguration). + ## + ## - The time needed to cancel a failover that is already in progress but + ## did not produced any configuration change (REPLICAOF NO ONE yet not + ## acknowledged by the promoted replica). + ## + ## - The maximum time a failover in progress waits for all the replica to be + ## reconfigured as replicas of the new primary. However even after this time + ## the replicas will be reconfigured by the Sentinels anyway, but not with + ## the exact parallel-syncs progression as specified. + # sentinel['failover_timeout'] = 60000 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + server: true, + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +5. 对于其他所有 Consul / Sentinel 节点,请再次执行步骤,并确保设置了正确的 IP. + +**注意:**第三个 Consul 服务器的配置完成后,将选举 Consul 负责人. 查看领事日志`sudo gitlab-ctl tail consul`将显示`...[INFO] consul: New leader elected: ...` + +You can list the current Consul members (server, client): + +``` +sudo /opt/gitlab/embedded/bin/consul members +``` + +您可以验证 GitLab 服务正在运行: + +``` +sudo gitlab-ctl status +``` + +输出应类似于以下内容: + +``` +run: consul: (pid 30074) 76834s; run: log: (pid 29740) 76844s +run: logrotate: (pid 30925) 3041s; run: log: (pid 29649) 76861s +run: node-exporter: (pid 30093) 76833s; run: log: (pid 29663) 76855s +run: sentinel: (pid 30098) 76832s; run: log: (pid 29704) 76850s +``` + +[Back to setup components](#setup-components) + +## Configure PostgreSQL[](#configure-postgresql "Permalink") + +在本节中,将指导您配置与 GitLab 一起使用的外部 PostgreSQL 数据库. + +### Provide your own PostgreSQL instance[](#provide-your-own-postgresql-instance "Permalink") + +如果您将 GitLab 托管在云提供商上,则可以选择将托管服务用于 PostgreSQL. 例如,AWS 提供了运行 PostgreSQL 的托管关系数据库服务(RDS). + +如果您使用云托管服务,或提供自己的 PostgreSQL: + +1. 根据[数据库要求文档](../../install/requirements.html#database)设置 PostgreSQL. +2. 使用您选择的密码设置一个`gitlab`用户名. `gitlab`用户需要特权才能创建`gitlabhq_production`数据库. +3. 使用适当的详细信息配置 GitLab 应用程序服务器. [配置 GitLab Rails 应用程序](#configure-gitlab-rails)涵盖了此步骤. + +### Standalone PostgreSQL using Omnibus GitLab[](#standalone-postgresql-using-omnibus-gitlab "Permalink") + +以下 IP 将作为示例: + +* `10.6.0.31`主 +* `10.6.0.32`中学 1 +* `10.6.0.33`中学 2 + +首先,请确保**在每个节点上** [安装](https://about.gitlab.com/install/) Linux GitLab 软件包. 按照以下步骤,从步骤 1 安装必需的依赖项,并从步骤 2 添加 GitLab 软件包存储库.在第二步中安装 GitLab 时,请勿提供`EXTERNAL_URL`值. + +#### PostgreSQL primary node[](#postgresql-primary-node "Permalink") + +1. SSH 进入 PostgreSQL 主节点. +2. 为 PostgreSQL 用户名/密码对生成密码哈希. 假设您将使用默认用户名`gitlab` (推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作``的值: + + ``` + sudo gitlab-ctl pg-password-md5 gitlab + ``` + +3. 为 PgBouncer 用户名/密码对生成密码哈希. 假设您将使用`pgbouncer`的默认用户名(推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作``的值: + + ``` + sudo gitlab-ctl pg-password-md5 pgbouncer + ``` + +4. 为 Consul 数据库用户名/密码对生成密码哈希. 假设您将使用默认用户名`gitlab-consul` (推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作``的值: + + ``` + sudo gitlab-ctl pg-password-md5 gitlab-consul + ``` + +5. 在主数据库节点上,编辑`/etc/gitlab/gitlab.rb`替换`/etc/gitlab/gitlab.rb` `# START user configuration`部分中记录的值: + + ``` + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # START user configuration + # Please set the real values as explained in Required Information section + # + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace XXX.XXX.XXX.XXX/YY with Network Address + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + postgres_exporter['dbname'] = 'gitlabhq_production' + postgres_exporter['password'] = '' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + # + # END user configuration + ``` + +6. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +7. 您可以通过以下方式列出当前 PostgreSQL 主,辅助节点的状态: + + ``` + sudo /opt/gitlab/bin/gitlab-ctl repmgr cluster show + ``` + +8. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 30593) 77133s; run: log: (pid 29912) 77156s + run: logrotate: (pid 23449) 3341s; run: log: (pid 29794) 77175s + run: node-exporter: (pid 30613) 77133s; run: log: (pid 29824) 77170s + run: postgres-exporter: (pid 30620) 77132s; run: log: (pid 29894) 77163s + run: postgresql: (pid 30630) 77132s; run: log: (pid 29618) 77181s + run: repmgrd: (pid 30639) 77132s; run: log: (pid 29985) 77150s + ``` + +[Back to setup components](#setup-components) + +#### PostgreSQL secondary nodes[](#postgresql-secondary-nodes "Permalink") + +1. 在两个辅助节点上,添加与上面为主要节点指定的配置相同的附加设置,该设置将告知`gitlab-ctl`最初它们是备用节点,无需尝试将它们注册为主要节点: + + ``` + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # Specify if a node should attempt to be primary on initialization. + repmgr['master_on_initialization'] = false + + # START user configuration + # Please set the real values as explained in Required Information section + # + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace XXX.XXX.XXX.XXX/YY with Network Address + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + postgres_exporter['dbname'] = 'gitlabhq_production' + postgres_exporter['password'] = '' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + # END user configuration + ``` + +2. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +支持高级[配置选项](https://docs.gitlab.com/omnibus/settings/database.html) ,可以根据需要添加. + +[Back to setup components](#setup-components) + +#### PostgreSQL post-configuration[](#postgresql-post-configuration "Permalink") + +SSH 进入**主节点** : + +1. 打开数据库提示: + + ``` + gitlab-psql -d gitlabhq_production + ``` + +2. Enable the `pg_trgm` extension: + + ``` + CREATE EXTENSION pg_trgm; + ``` + +3. 键入`\q`并按 Enter 退出数据库提示. + +4. 验证集群是否已用一个节点初始化: + + ``` + gitlab-ctl repmgr cluster show + ``` + + 输出应类似于以下内容: + + ``` + Role | Name | Upstream | Connection String + ----------+----------|----------|---------------------------------------- + * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr + ``` + +5. 在连接字符串中记下主机名或 IP 地址: `host=HOSTNAME` . 在下一节中,我们将主机名称为`` . 如果该值不是 IP 地址,则必须是可解析的名称(通过 DNS 或`/etc/hosts` ) + +SSH 进入**辅助节点** : + +1. 设置 repmgr 备用数据库: + + ``` + gitlab-ctl repmgr standby setup + ``` + + Do note that this will remove the existing data on the node. The command has a wait time. + + 输出应类似于以下内容: + + ``` + Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data + If this is not what you want, hit Ctrl-C now to exit + To skip waiting, rerun with the -w option + Sleeping for 30 seconds + Stopping the database + Removing the data + Cloning the data + Starting the database + Registering the node with the cluster + ok: run: repmgrd: (pid 19068) 0s + ``` + +在继续之前,请确保正确配置了数据库. 在**主**节点上运行以下命令以验证复制是否正常工作,并且辅助节点是否出现在群集中: + +``` +gitlab-ctl repmgr cluster show +``` + +输出应类似于以下内容: + +``` +Role | Name | Upstream | Connection String +----------+---------|-----------|------------------------------------------------ +* master | MASTER | | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr +``` + +如果任何节点的"角色"列显示"失败",请在继续操作之前检查" [故障排除"部分](troubleshooting.html) . + +另外,请检查`repmgr-check-master`命令在每个节点上是否都能正常工作: + +``` +su - gitlab-consul +gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' +``` + +此命令依靠退出代码来告诉 Consul 特定节点是主节点还是辅助节点. 这里最重要的是该命令不会产生错误. 如果有错误,很可能是由于`gitlab-consul`数据库用户权限不正确`gitlab-consul` . 在继续之前,请检查" [故障排除"部分](troubleshooting.html) . + +[Back to setup components](#setup-components) + +## Configure PgBouncer[](#configure-pgbouncer "Permalink") + +现在已经安装了 PostgreSQL 服务器,让我们配置 PgBouncer. 以下 IP 将作为示例: + +* `10.6.0.21` :PgBouncer 1 +* `10.6.0.22` :PgBouncer 2 +* `10.6.0.23` :PgBouncer 3 + +1. 在每个 PgBouncer 节点上,编辑`/etc/gitlab/gitlab.rb` ,并将``和``替换为[之前设置](#postgresql-primary-node)的密码哈希: + + ``` + # Disable all components except Pgbouncer and Consul agent + roles ['pgbouncer_role'] + + # Configure PgBouncer + pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) + + pgbouncer['users'] = { + 'gitlab-consul': { + password: '' + }, + 'pgbouncer': { + password: '' + } + } + + # Configure Consul agent + consul['watchers'] = %w(postgresql) + consul['enable'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + pgbouncer_exporter['listen_address'] = '0.0.0.0:9188' + ``` + +2. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +3. 创建一个`.pgpass`文件,以便 Consul 能够重新加载 PgBouncer. 询问时两次输入 PgBouncer 密码: + + ``` + gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul + ``` + +4. 确保每个节点都在与当前主节点通信: + + ``` + gitlab-ctl pgb-console # You will be prompted for PGBOUNCER_PASSWORD + ``` + + 如果出现错误`psql: ERROR: Auth failed`输入密码后`psql: ERROR: Auth failed` ,请确保您以前以正确的格式生成了 MD5 密码哈希. 正确的格式是连接密码和用户名`PASSWORDUSERNAME` . 例如, `Sup3rS3cr3tpgbouncer`将是为`pgbouncer`用户生成 MD5 密码哈希所需的文本. + +5. 控制台提示可用后,请运行以下查询: + + ``` + show databases ; show clients ; + ``` + + 输出应类似于以下内容: + + ``` + name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections + ---------------------+-------------+------+---------------------+------------+-----------+--------------+-----------+-----------------+--------------------- + gitlabhq_production | MASTER_HOST | 5432 | gitlabhq_production | | 20 | 0 | | 0 | 0 + pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0 + (2 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | remote_pid | tls + ------+-----------+---------------------+---------+----------------+-------+------------+------------+---------------------+---------------------+-----------+------+------------+----- + C | pgbouncer | pgbouncer | active | 127.0.0.1 | 56846 | 127.0.0.1 | 6432 | 2017-08-21 18:09:59 | 2017-08-21 18:10:48 | 0x22b3880 | | 0 | + (2 rows) + ``` + +6. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + The output should be similar to the following: + + ``` + run: consul: (pid 31530) 77150s; run: log: (pid 31106) 77182s + run: logrotate: (pid 32613) 3357s; run: log: (pid 30107) 77500s + run: node-exporter: (pid 31550) 77149s; run: log: (pid 30138) 77493s + run: pgbouncer: (pid 32033) 75593s; run: log: (pid 31117) 77175s + run: pgbouncer-exporter: (pid 31558) 77148s; run: log: (pid 31498) 77156s + ``` + +[Back to setup components](#setup-components) + +### Configure the internal load balancer[](#configure-the-internal-load-balancer "Permalink") + +如果按照建议运行多个 PgBouncer 节点,那么此时,您将需要设置一个 TCP 内部负载均衡器以正确地服务每个负载均衡器. + +以下 IP 将作为示例: + +* `10.6.0.20` :内部负载均衡器 + +使用[HAProxy 的方法](https://www.haproxy.org/)如下: + +``` +global + log /dev/log local0 + log localhost local1 notice + log stdout format raw local0 + +defaults + log global + default-server inter 10s fall 3 rise 2 + balance leastconn + +frontend internal-pgbouncer-tcp-in + bind *:6432 + mode tcp + option tcplog + + default_backend pgbouncer + +backend pgbouncer + mode tcp + option tcp-check + + server pgbouncer1 10.6.0.21:6432 check + server pgbouncer2 10.6.0.22:6432 check + server pgbouncer3 10.6.0.23:6432 check +``` + +请参阅您首选的负载均衡器的文档以获取更多指导. + +[Back to setup components](#setup-components) + +## Configure Gitaly[](#configure-gitaly "Permalink") + +在自己的服务器上部署 Gitaly 可以使大于单个计算机的 GitLab 安装受益. + +Gitaly 节点要求取决于客户数据,特别是项目数量及其存储库大小. 建议将两个节点作为绝对最小值. 每个 Gitaly 节点应存储的数据不超过 5TB,并将[`gitaly-ruby`工作者](../gitaly/index.html#gitaly-ruby)的数量设置为可用 CPU 的 20%. 根据以上建议,应结合其他节点并结合对预期数据大小和分布的审查. + +强烈建议所有 Gitaly 节点都安装 SSD 磁盘,因为 Gitaly I / O 繁重,因此其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +注意事项: + +* GitLab Rails 应用程序将[存储库分](../repository_storage_paths.html)片到[存储库中](../repository_storage_paths.html) . +* Gitaly 服务器可以托管一个或多个存储. +* 一个 GitLab 服务器可以使用一个或多个 Gitaly 服务器. +* 必须以对所有 Gitaly 客户端正确解析的方式指定 Gitaly 地址. +* Gitaly 服务器一定不能暴露在公共互联网上,因为默认情况下,Gitaly 的网络流量是未加密的. 强烈建议使用防火墙以限制对 Gitaly 服务器的访问. 另一种选择是[使用 TLS](#gitaly-tls-support) . + +**提示:**有关 Gitaly 历史和网络体系结构的更多信息,请参见[独立的 Gitaly 文档](../gitaly/index.html) . + +注意: **注意:** Gitaly 文档中引用的令牌只是管理员选择的任意密码. 它与为 GitLab API 创建的令牌或其他类似的 Web API 令牌无关. + +下面我们描述如何配置两个具有 IP 和域名的 Gitaly 服务器: + +* `10.6.0.51` 1( `gitaly1.internal` ) +* `10.6.0.52` 2( `gitaly2.internal` ) + +假定该秘密令牌为`gitalysecret` ,并且您的 GitLab 安装具有三个存储库存储: + +* `default`为 Gitaly 1 +* `storage1`在 Gitaly 1 +* `storage2`上 Gitaly 2 + +在每个节点上: + +1. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包,但**不**提供`EXTERNAL_URL`值. +2. 编辑`/etc/gitlab/gitlab.rb`以配置存储路径,启用网络侦听器并配置令牌: + + ``` + # /etc/gitlab/gitlab.rb + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the GitLab Rails application setup + gitaly['auth_token'] = 'gitlaysecret' + gitlab_shell['secret_token'] = 'shellsecret' + + # Avoid running unnecessary services on the Gitaly server + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + grafana['enable'] = false + gitlab_exporter['enable'] = false + + # If you run a seperate monitoring node you can disable these services + alertmanager['enable'] = false + prometheus['enable'] = false + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your 'front door' GitLab URL or an internal load + # balancer. + # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server. + gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' + + # Make Gitaly accept connections on all network interfaces. You must use + # firewalls to restrict access to this address/port. + # Comment out following line if you only want to support TLS connections + gitaly['listen_addr'] = "0.0.0.0:8075" + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + gitaly['prometheus_listen_addr'] = "0.0.0.0:9236" + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_rails['prometheus_address'] = '10.6.0.81:9090' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + ``` + +3. 对于每个服务器,将以下内容附加到`/etc/gitlab/gitlab.rb` : + 1. 在`gitaly1.internal` : + + ``` + git_data_dirs ({ 'default' => { 'path' => '/var/opt/gitlab/git-data' }, 'storage1' => { 'path' => '/mnt/gitlab/git-data' }, }) + ``` + + 2. 在`gitaly2.internal` : + + ``` + git_data_dirs ({ 'storage2' => { 'path' => '/mnt/gitlab/git-data' }, }) + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 确认 Gitaly 可以执行对内部 API 的回调: + + ``` + sudo /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml + ``` + +6. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 30339) 77006s; run: log: (pid 29878) 77020s + run: gitaly: (pid 30351) 77005s; run: log: (pid 29660) 77040s + run: logrotate: (pid 7760) 3213s; run: log: (pid 29782) 77032s + run: node-exporter: (pid 30378) 77004s; run: log: (pid 29812) 77026s + ``` + +### Gitaly TLS support[](#gitaly-tls-support "Permalink") + +Gitaly 支持 TLS 加密. 为了能够与侦听安全连接的 Gitaly 实例进行通信,您将需要在 GitLab 配置中相应存储条目的`gitaly_address`中使用`tls://` URL 方案. + +您将需要携带自己的证书,因为该证书不会自动提供. 证书或其证书颁发机构必须按照[GitLab 自定义证书配置中](https://docs.gitlab.com/omnibus/settings/ssl.html)所述的步骤,安装在所有 Gitaly 节点(包括使用证书的 Gitaly 节点)上,以及与之通信的所有客户端节点上. + +**注意:**自签名证书必须指定用于访问 Gitaly 服务器的地址. 如果要通过主机名寻址 Gitaly 服务器,则可以为此使用"公用名"字段,也可以将其添加为"使用者备用名". 如果要通过 Gitaly 服务器的 IP 地址对其进行寻址,则必须将其作为主题备用名称添加到证书中. [gRPC 不支持在证书中使用 IP 地址作为公用名](https://github.com/grpc/grpc/issues/2691) .**注意:**可以同时为 Gitaly 服务器配置未加密的侦听地址`listen_addr`和已加密的侦听地址`tls_listen_addr` . 如果需要,这使您可以从未加密的流量逐渐过渡到加密的流量. + +要使用 TLS 配置 Gitaly: + +1. 创建`/etc/gitlab/ssl`目录,并在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +2. 将证书复制到`/etc/gitlab/trusted-certs`以便 Gitaly 在调用自身时信任该证书: + + ``` + sudo cp /etc/gitlab/ssl/cert.pem /etc/gitlab/trusted-certs/ + ``` + +3. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + gitaly['tls_listen_addr'] = "0.0.0.0:9999" + gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + gitaly['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +4. 删除`gitaly['listen_addr']`以仅允许加密连接. +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +[Back to setup components](#setup-components) + +## Configure Sidekiq[](#configure-sidekiq "Permalink") + +Sidekiq 需要连接到 Redis,PostgreSQL 和 Gitaly 实例. 以下 IP 将作为示例: + +* `10.6.0.71` :Sidekiq 1 +* `10.6.0.72` :Sidekiq 2 +* `10.6.0.73` :Sidekiq 3 +* `10.6.0.74` :Sidekiq 4 + +要配置 Sidekiq 节点,每个节点一个: + +1. SSH 到 Sidekiq 服务器. +2. 从 GitLab 下载页面使用步骤 1 和 2 [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. **不要完成下载页面上的任何其他步骤.** +3. 使用编辑器打开`/etc/gitlab/gitlab.rb` : + + ``` + ######################################## + ##### Services Disabled ### + ######################################## + + nginx['enable'] = false + grafana['enable'] = false + prometheus['enable'] = false + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + puma['enable'] = false + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + gitlab_exporter['enable'] = false + + ######################################## + #### Redis ### + ######################################## + + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + ## The same password for Redis authentication you set up for the master node. + redis['master_password'] = '' + + ## A list of sentinels with `host` and `port` + gitlab_rails['redis_sentinels'] = [ + {'host' => '10.6.0.11', 'port' => 26379}, + {'host' => '10.6.0.12', 'port' => 26379}, + {'host' => '10.6.0.13', 'port' => 26379}, + ] + + ####################################### + ### Gitaly ### + ####################################### + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + + ####################################### + ### Postgres ### + ####################################### + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['auto_migrate'] = false + + ####################################### + ### Sidekiq configuration ### + ####################################### + sidekiq['listen_address'] = "0.0.0.0" + + ####################################### + ### Monitoring configuration ### + ####################################### + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + + # Rails Status for prometheus + gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8'] + gitlab_rails['prometheus_address'] = '10.6.0.81:9090' + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 30114) 77353s; run: log: (pid 29756) 77367s + run: logrotate: (pid 9898) 3561s; run: log: (pid 29653) 77380s + run: node-exporter: (pid 30134) 77353s; run: log: (pid 29706) 77372s + run: sidekiq: (pid 30142) 77351s; run: log: (pid 29638) 77386s + ``` + +**提示:**您还可以运行[多个 Sidekiq 进程](../operations/extra_sidekiq_processes.html) .[Back to setup components](#setup-components) + +## Configure GitLab Rails[](#configure-gitlab-rails "Permalink") + +**注意:**在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数设置为可用 CPU 的 90%以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +本节介绍如何配置 GitLab 应用程序(Rails)组件. 在每个节点上执行以下操作: + +1. 如果您[使用的是 NFS](#configure-nfs-optional) : + + 1. 如有必要,请使用以下命令安装 NFS 客户端实用程序软件包: + + ``` + # Ubuntu/Debian + apt-get install nfs-common + + # CentOS/Red Hat + yum install nfs-utils nfs-utils-lib + ``` + + 2. 在`/etc/fstab`指定必要的 NFS 挂载. `/etc/fstab`的确切内容取决于您选择配置 NFS 服务器的方式. 有关示例和各种选项,请参见[NFS 文档](../high_availability/nfs.html) . + + 3. 创建共享目录. 这些可能会有所不同,具体取决于您的 NFS 安装位置. + + ``` + mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data + ``` + +2. 使用[GitLab 下载中的](https://about.gitlab.com/install/) **步骤 1 和 2**下载/安装 Omnibus GitLab. 不要完成下载页面上的其他步骤. +3. 创建/编辑`/etc/gitlab/gitlab.rb`并使用以下配置. 为了保持整个节点的链接均匀性, `external_url`在应用服务器上应指向外部 URL,用户将用来访问 GitLab. 这将是[外部负载平衡器](#configure-the-external-load-balancer)的 URL,它将[负载](#configure-the-external-load-balancer)流量路由到 GitLab 应用程序服务器: + + ``` + external_url 'https://gitlab.example.com' + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the Gitaly setup + gitlab_rails['gitaly_token'] = 'gitalyecret' + gitlab_shell['secret_token'] = 'shellsecret' + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + + ## Disable components that will not be on the GitLab application server + roles ['application_role'] + gitaly['enable'] = false + nginx['enable'] = true + sidekiq['enable'] = false + + ## PostgreSQL connection details + # Disable PostgreSQL on the application node + postgresql['enable'] = false + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['auto_migrate'] = false + + ## Redis connection details + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + ## The same password for Redis authentication you set up for the Redis primary node. + redis['master_password'] = '' + + ## A list of sentinels with `host` and `port` + gitlab_rails['redis_sentinels'] = [ + {'host' => '10.6.0.11', 'port' => 26379}, + {'host' => '10.6.0.12', 'port' => 26379}, + {'host' => '10.6.0.13', 'port' => 26379} + ] + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' + sidekiq['listen_address'] = "0.0.0.0" + puma['listen'] = '0.0.0.0' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Add the monitoring node's IP address to the monitoring whitelist and allow it to + # scrape the NGINX metrics + gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8'] + nginx['status']['options']['allow'] = ['10.6.0.81/32', '127.0.0.0/8'] + gitlab_rails['prometheus_address'] = '10.6.0.81:9090' + + ## Uncomment and edit the following options if you have set up NFS + ## + ## Prevent GitLab from starting if NFS data mounts are not available + ## + #high_availability['mountpoint'] = '/var/opt/gitlab/git-data' + ## + ## Ensure UIDs and GIDs match between servers for permissions via NFS + ## + #user['uid'] = 9000 + #user['gid'] = 9000 + #web_server['uid'] = 9001 + #web_server['gid'] = 9001 + #registry['uid'] = 9002 + #registry['gid'] = 9002 + ``` + +4. 如果您正在使用[具有 TLS 支持](#gitaly-tls-support)的`git_data_dirs` ,请确保`git_data_dirs`条目配置了`tls`而不是`tcp` : + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' }, + }) + ``` + + 1. 将证书复制到`/etc/gitlab/trusted-certs` : + + ``` + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +6. 运行`sudo gitlab-rake gitlab:gitaly:check`确认节点可以连接到 Gitaly. +7. 拖尾日志以查看请求: + + ``` + sudo gitlab-ctl tail gitaly + ``` + +8. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 4890) 8647s; run: log: (pid 29962) 79128s + run: gitlab-exporter: (pid 4902) 8647s; run: log: (pid 29913) 79134s + run: gitlab-workhorse: (pid 4904) 8646s; run: log: (pid 29713) 79155s + run: logrotate: (pid 12425) 1446s; run: log: (pid 29798) 79146s + run: nginx: (pid 4925) 8646s; run: log: (pid 29726) 79152s + run: node-exporter: (pid 4931) 8645s; run: log: (pid 29855) 79140s + run: puma: (pid 4936) 8645s; run: log: (pid 29656) 79161s + ``` + +**注意:**如上例所示,当在`external_url`指定`https`时,GitLab 会假定您在`/etc/gitlab/ssl/`具有 SSL 证书. 如果没有证书,NGINX 将无法启动. 有关更多信息,请参见[NGINX 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### GitLab Rails post-configuration[](#gitlab-rails-post-configuration "Permalink") + +1. 确保运行所有迁移: + + ``` + gitlab-rake gitlab:db:configure + ``` + + **注意:**如果遇到`rake aborted!` 错误,指出 PgBouncer 是无法连接到 PostgreSQL 也可能是您的 PgBouncer 节点的 IP 地址是从 PostgreSQL 的缺失`trust_auth_cidr_addresses`在`gitlab.rb`你的数据库节点. 请参阅"故障排除"部分中的[PgBouncer 错误`ERROR: pgbouncer cannot connect to server`](troubleshooting.html#pgbouncer-error-error-pgbouncer-cannot-connect-to-server) ,然后再继续. +2. [Configure fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.html). + +[Back to setup components](#setup-components) + +## Configure Prometheus[](#configure-prometheus "Permalink") + +Omnibus GitLab 软件包可用于配置运行[Prometheus](../monitoring/prometheus/index.html)和[Grafana](../monitoring/performance/grafana_configuration.html)的独立 Monitoring 节点: + +1. SSH 进入"监视"节点. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + external_url 'http://gitlab.example.com' + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + node_exporter['enable'] = false + gitlab_exporter['enable'] = false + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Login form + grafana['disable_login_form'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = '' + + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 在 GitLab 用户界面中,将`admin/application_settings/metrics_and_profiling` >指标-Grafana 设置为`/-/grafana`到`http[s]:///-/grafana` . +6. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 31637) 17337s; run: log: (pid 29748) 78432s + run: grafana: (pid 31644) 17337s; run: log: (pid 29719) 78438s + run: logrotate: (pid 31809) 2936s; run: log: (pid 29581) 78462s + run: nginx: (pid 31665) 17335s; run: log: (pid 29556) 78468s + run: prometheus: (pid 31672) 17335s; run: log: (pid 29633) 78456s + ``` + +[Back to setup components](#setup-components) + +## Configure the object storage[](#configure-the-object-storage "Permalink") + +GitLab 支持使用对象存储服务来保存多种类型的数据. 建议在[NFS](#configure-nfs-optional)上使用它,并且通常在较大的设置中更好,因为对象存储通常具有更高的性能,可靠性和可伸缩性. + +manbetx 客户端打不开已经测试过或知道使用的客户的对象存储选项包括: + +* SaaS / Cloud 解决方案,例如[Amazon S3](https://aws.amazon.com/s3/) , [Google 云存储](https://cloud.google.com/storage) . +* 来自各种存储供应商的本地硬件和设备. +* MinIO. 我们的 Helm Chart 文档中[提供了有关部署的指南](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) . + +要配置 GitLab 以使用对象存储,请根据要使用的功能参考以下指南: + +1. Configure [object storage for backups](../../raketasks/backup_restore.html#uploading-backups-to-a-remote-cloud-storage). +2. Configure [object storage for job artifacts](../job_artifacts.html#using-object-storage) including [incremental logging](../job_logs.html#new-incremental-logging-architecture). +3. Configure [object storage for LFS objects](../lfs/index.html#storing-lfs-objects-in-remote-object-storage). +4. Configure [object storage for uploads](../uploads.html#using-object-storage-core-only). +5. Configure [object storage for merge request diffs](../merge_request_diffs.html#using-object-storage). +6. 配置[容器注册表的对象存储](../packages/container_registry.html#use-object-storage) (可选功能). +7. [为 Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)配置[对象存储](https://docs.mattermost.com/administration/config-settings.html#file-storage) (可选功能). +8. 配置[软件包的对象存储](../packages/index.html#using-object-storage) (可选功能). +9. 配置[依赖项代理的对象存储](../packages/dependency_proxy.html#using-object-storage) (可选功能). +10. [为 Pseudonymizer](../pseudonymizer.html#configuration) (可选功能)配置[对象存储](../pseudonymizer.html#configuration) . +11. 配置[对象存储以自动缩放 Runner 缓存](https://docs.gitlab.com/runner/configuration/autoscale.html) (可选-为了提高性能). +12. Configure [object storage for Terraform state files](../terraform_state.html#using-object-storage-core-only). + +对于 GitLab,建议为每种数据类型使用单独的存储桶. + +我们的配置的局限性是对象存储的每次使用都是单独配置的. [我们有一个需要改进的问题](https://gitlab.com/gitlab-org/gitlab/-/issues/23345) ,轻松地将一个存储桶与单独的文件夹一起使用可能会带来一个改进. + +使用同一个存储桶至少有一个特定的问题:当使用 Helm 图表部署 GitLab 时,除非使用单独的存储桶,否则从备份还原[将无法正常工作](https://docs.gitlab.com/charts/advanced/external-object-storage/) . + +如果您的组织将来决定将 GitLab 迁移到 Helm 部署,则使用单个存储桶的一种风险是. GitLab 可以运行,但是直到组织对备份起作用的关键要求之前,备份的情况可能无法实现. + +[Back to setup components](#setup-components) + +## Configure NFS (optional)[](#configure-nfs-optional "Permalink") + +建议尽可能在 NFS 上使用[对象存储](#configure-the-object-storage)以及[Gitaly](#configure-gitaly) ,以提高性能. 如果您打算使用 GitLab 页面,则当前[需要 NFS](troubleshooting.html#gitlab-pages-requires-nfs) . + +请参阅如何[配置 NFS](../high_availability/nfs.html) . + +[Back to setup components](#setup-components) + +## Troubleshooting[](#troubleshooting "Permalink") + +请参阅[故障排除文档](troubleshooting.html) . + +[Back to setup components](#setup-components) \ No newline at end of file diff --git a/_book/docs/425.md b/_book/docs/425.md new file mode 100644 index 0000000000000000000000000000000000000000..31e7e894d45a91f47c423cb724633ff2b0e0ed6e --- /dev/null +++ b/_book/docs/425.md @@ -0,0 +1,49 @@ +# Reference architecture: up to 10,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/10k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/10k_users.html) + +* [Footnotes](#footnotes) + +# Reference architecture: up to 10,000 users[](#reference-architecture-up-to-10000-users "Permalink") + +该页面描述了多达 10,000 个用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +> * **支持的用户(大约):** 10,000 +> * **高可用性:** True +> * **测试 RPS 速率:** API:200 RPS,网站:20 RPS,Git:20 RPS + +| Service | Nodes | 配置( [8](#footnotes) ) | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | --- | +| 亚搏体育应用程序轨道( [1](#footnotes) ) | 3 | 32 个 vCPU,28.8GB 内存 | n1-highcpu-32 | c5.9xlarge | F32s v2 | +| PostgreSQL | 3 | 4 个 vCPU,15GB 内存 | n1-standard-4 | m5.xlarge | D4s v3 | +| PgBouncer | 3 | 2 个 vCPU,1.8GB 内存 | n1-highcpu-2 | c5.large | F2s v2 | +| 吉塔利( [2](#footnotes) )( [5](#footnotes) )( [7](#footnotes) ) | X | 16 个 vCPU,60GB 内存 | n1-standard-16 | m5.4xlarge | D16s v3 | +| Redis( [3](#footnotes) )-缓存 | 3 | 4 个 vCPU,15GB 内存 | n1-standard-4 | m5.xlarge | D4s v3 | +| Redis( [3](#footnotes) )-队列/共享状态 | 3 | 4 个 vCPU,15GB 内存 | n1-standard-4 | m5.xlarge | D4s v3 | +| Redis 前哨( [3](#footnotes) )-缓存 | 3 | 1 个 vCPU,1.7GB 内存 | g1-small | t2.small | B1MS | +| Redis 前哨( [3](#footnotes) )-队列/共享状态 | 3 | 1 个 vCPU,1.7GB 内存 | g1-small | t2.small | B1MS | +| Consul | 3 | 2 个 vCPU,1.8GB 内存 | n1-highcpu-2 | c5.large | F2s v2 | +| Sidekiq | 4 | 4 个 vCPU,15GB 内存 | n1-standard-4 | m5.xlarge | D4s v3 | +| 对象存储( [4](#footnotes) ) | - | - | - | - | - | +| NFS 服务器( [5](#footnotes) )( [7](#footnotes) ) | 1 | 4 个 vCPU,3.6GB 内存 | n1-highcpu-4 | c5.xlarge | F4s v2 | +| 监控节点 | 1 | 4 个 vCPU,3.6GB 内存 | n1-highcpu-4 | c5.xlarge | F4s v2 | +| 外部负载平衡节点( [6](#footnotes) ) | 1 | 2 个 vCPU,1.8GB 内存 | n1-highcpu-2 | c5.large | F2s v2 | +| 内部负载平衡节点( [6](#footnotes) ) | 1 | 2 个 vCPU,1.8GB 内存 | n1-highcpu-2 | c5.large | F2s v2 | + +## Footnotes[](#footnotes "Permalink") + +1. 在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数量设置为 90%的可用 CPU 以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +2. Gitaly 节点的要求取决于客户数据,特别是项目数量及其规模. 对于 HA 环境,我们建议绝对最少使用两个节点,并且在支持 50,000 个或更多用户时,至少应使用四个节点. 我们还建议每个 Gitaly 节点存储的数据不得超过 5TB,并且将[`gitaly-ruby`工作者](../gitaly/index.html#gitaly-ruby)的数量设置为可用 CPU 的 20%. 根据以上建议,应结合其他节点并结合对预期数据大小和分布的审查. + +3. 推荐的 Redis 设置因架构的大小而异. 对于较小的体系结构(少于 3000 个用户),一个实例就足够了. 对于中型安装(3,000-5,000),我们建议为所有课程使用一个 Redis 集群,并且 Redis Sentinel 与 Consul 一起托管. 对于较大的体系结构(10,000 个或更多用户),我们建议分别为 Cache 类和队列和 Shared State 类运行一个单独的[Redis 群集](../redis/replication_and_failover.html#running-multiple-redis-clusters) . 我们还建议您为每个 Redis 群集分别运行 Redis Sentinel 群集. + +4. 对于 LFS,Uploads,Artifacts 等数据对象.由于性能和可用性更好,我们建议尽可能在 NFS 上使用[对象存储服务](../object_storage.html) . + +5. NFS 可以用作存储库数据(替代 Gitaly)和对象存储的替代方法,但是出于性能原因,通常不建议使用 NFS. 请注意,但是[GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)是必需的. + +6. 我们的架构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +7. 我们强烈建议为任何 Gitaly 或 NFS 节点设置 HDD 之上的 SSD 磁盘,其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS,因为这些组件的 I / O 繁重. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您正在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +8. 这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. \ No newline at end of file diff --git a/_book/docs/426.md b/_book/docs/426.md new file mode 100644 index 0000000000000000000000000000000000000000..b344de569b6c80c8f42285d8c1ea2d0501c96a1c --- /dev/null +++ b/_book/docs/426.md @@ -0,0 +1,49 @@ +# Reference architecture: up to 25,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/25k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/25k_users.html) + +* [Footnotes](#footnotes) + +# Reference architecture: up to 25,000 users[](#reference-architecture-up-to-25000-users "Permalink") + +本页描述了最多 25,000 个用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +> * **支持的用户(大约):** 25,000 +> * **高可用性:** True +> * **测试 RPS 速率:** API:500 RPS,网站:50 RPS,Git:50 RPS + +| Service | Nodes | 配置( [8](#footnotes) ) | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | --- | +| 亚搏体育应用程序轨道( [1](#footnotes) ) | 5 | 32 个 vCPU,28.8GB 内存 | `n1-highcpu-32` | `c5.9xlarge` | F32s v2 | +| PostgreSQL | 3 | 8 个 vCPU,30GB 内存 | `n1-standard-8` | `m5.2xlarge` | D8s v3 | +| PgBouncer | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | F2s v2 | +| 吉塔利( [2](#footnotes) )( [5](#footnotes) )( [7](#footnotes) ) | X | 32 个 vCPU,120GB 内存 | `n1-standard-32` | `m5.8xlarge` | D32s v3 | +| Redis( [3](#footnotes) )-缓存 | 3 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | D4s v3 | +| Redis( [3](#footnotes) )-队列/共享状态 | 3 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | D4s v3 | +| Redis 前哨( [3](#footnotes) )-缓存 | 3 | 1 个 vCPU,1.7GB 内存 | `g1-small` | `t2.small` | B1MS | +| Redis 前哨( [3](#footnotes) )-队列/共享状态 | 3 | 1 个 vCPU,1.7GB 内存 | `g1-small` | `t2.small` | B1MS | +| Consul | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | F2s v2 | +| Sidekiq | 4 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | D4s v3 | +| 对象存储( [4](#footnotes) ) | - | - | - | - | - | +| NFS 服务器( [5](#footnotes) )( [7](#footnotes) ) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | +| 监控节点 | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | +| 外部负载平衡节点( [6](#footnotes) ) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | +| 内部负载平衡节点( [6](#footnotes) ) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | + +## Footnotes[](#footnotes "Permalink") + +1. 在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数量设置为 90%的可用 CPU 以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +2. Gitaly node requirements are dependent on customer data, specifically the number of projects and their sizes. We recommend two nodes as an absolute minimum for HA environments and at least four nodes should be used when supporting 50,000 or more users. We also recommend that each Gitaly node should store no more than 5TB of data and have the number of [`gitaly-ruby` workers](../gitaly/index.html#gitaly-ruby) set to 20% of available CPUs. Additional nodes should be considered in conjunction with a review of expected data size and spread based on the recommendations above. + +3. 推荐的 Redis 设置因架构的大小而异. 对于较小的体系结构(少于 3000 个用户),一个实例就足够了. 对于中型安装(3,000-5,000),我们建议为所有课程使用一个 Redis 集群,并且 Redis Sentinel 与 Consul 一起托管. 对于较大的体系结构(10,000 个或更多用户),我们建议分别为 Cache 类和队列和 Shared State 类运行一个单独的[Redis 群集](../redis/replication_and_failover.html#running-multiple-redis-clusters) . 我们还建议您为每个 Redis 群集分别运行 Redis Sentinel 群集. + +4. 对于 LFS,Uploads,Artifacts 等数据对象.由于性能和可用性更好,我们建议尽可能在 NFS 上使用[对象存储服务](../object_storage.html) . + +5. NFS 可以用作存储库数据(替代 Gitaly)和对象存储的替代方法,但是出于性能原因,通常不建议使用 NFS. 请注意,但是[GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)是必需的. + +6. 我们的架构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +7. 我们强烈建议为任何 Gitaly 或 NFS 节点设置 HDD 之上的 SSD 磁盘,其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS,因为这些组件的 I / O 繁重. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您正在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +8. 这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. \ No newline at end of file diff --git a/_book/docs/427.md b/_book/docs/427.md new file mode 100644 index 0000000000000000000000000000000000000000..081ef0daef2fea0cdb75348353faeb3fee6a2a01 --- /dev/null +++ b/_book/docs/427.md @@ -0,0 +1,49 @@ +# Reference architecture: up to 50,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/50k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/50k_users.html) + +* [Footnotes](#footnotes) + +# Reference architecture: up to 50,000 users[](#reference-architecture-up-to-50000-users "Permalink") + +此页面描述了多达 50,000 个用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +> * **支持的用户(大约):** 50,000 +> * **高可用性:** True +> * **测试 RPS 速率:** API:1000 RPS,网站:100 RPS,Git:100 RPS + +| Service | Nodes | 配置( [8](#footnotes) ) | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | --- | +| 亚搏体育应用程序轨道( [1](#footnotes) ) | 12 | 32 个 vCPU,28.8GB 内存 | `n1-highcpu-32` | `c5.9xlarge` | F32s v2 | +| PostgreSQL | 3 | 16 个 vCPU,60GB 内存 | `n1-standard-16` | `m5.4xlarge` | D16s v3 | +| PgBouncer | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | F2s v2 | +| 吉塔利( [2](#footnotes) )( [5](#footnotes) )( [7](#footnotes) ) | X | 64 个 vCPU,240GB 内存 | `n1-standard-64` | `m5.16xlarge` | D64s v3 | +| Redis( [3](#footnotes) )-缓存 | 3 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | D4s v3 | +| Redis( [3](#footnotes) )-队列/共享状态 | 3 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | D4s v3 | +| Redis 前哨( [3](#footnotes) )-缓存 | 3 | 1 个 vCPU,1.7GB 内存 | `g1-small` | `t2.small` | B1MS | +| Redis 前哨( [3](#footnotes) )-队列/共享状态 | 3 | 1 个 vCPU,1.7GB 内存 | `g1-small` | `t2.small` | B1MS | +| Consul | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | F2s v2 | +| Sidekiq | 4 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | D4s v3 | +| NFS 服务器( [5](#footnotes) )( [7](#footnotes) ) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | +| 对象存储( [4](#footnotes) ) | - | - | - | - | - | +| 监控节点 | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | +| 外部负载平衡节点( [6](#footnotes) ) | 1 | 8 个 vCPU,7.2GB 内存 | `n1-highcpu-8` | `c5.2xlarge` | F8s v2 | +| 内部负载平衡节点( [6](#footnotes) ) | 1 | 8 个 vCPU,7.2GB 内存 | `n1-highcpu-8` | `c5.2xlarge` | F8s v2 | + +## Footnotes[](#footnotes "Permalink") + +1. 在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数量设置为 90%的可用 CPU 以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +2. Gitaly node requirements are dependent on customer data, specifically the number of projects and their sizes. We recommend two nodes as an absolute minimum for HA environments and at least four nodes should be used when supporting 50,000 or more users. We also recommend that each Gitaly node should store no more than 5TB of data and have the number of [`gitaly-ruby` workers](../gitaly/index.html#gitaly-ruby) set to 20% of available CPUs. Additional nodes should be considered in conjunction with a review of expected data size and spread based on the recommendations above. + +3. 推荐的 Redis 设置因架构的大小而异. 对于较小的体系结构(少于 3000 个用户),一个实例就足够了. 对于中型安装(3,000-5,000),我们建议为所有课程使用一个 Redis 集群,并且 Redis Sentinel 与 Consul 一起托管. 对于较大的体系结构(10,000 个或更多用户),我们建议分别为 Cache 类和队列和 Shared State 类运行一个单独的[Redis 群集](../redis/replication_and_failover.html#running-multiple-redis-clusters) . 我们还建议您为每个 Redis 群集分别运行 Redis Sentinel 群集. + +4. 对于 LFS,Uploads,Artifacts 等数据对象.由于性能和可用性更好,我们建议尽可能在 NFS 上使用[对象存储服务](../object_storage.html) . + +5. NFS 可以用作存储库数据(替代 Gitaly)和对象存储的替代方法,但是出于性能原因,通常不建议使用 NFS. 请注意,但是[GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)是必需的. + +6. 我们的架构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +7. 我们强烈建议为任何 Gitaly 或 NFS 节点设置 HDD 之上的 SSD 磁盘,其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS,因为这些组件的 I / O 繁重. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您正在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +8. 这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. \ No newline at end of file diff --git a/_book/docs/428.md b/_book/docs/428.md new file mode 100644 index 0000000000000000000000000000000000000000..ff368d89adef68064adbc5fc43251362c24b43f7 --- /dev/null +++ b/_book/docs/428.md @@ -0,0 +1,289 @@ +# Troubleshooting a reference architecture set up + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/troubleshooting.html](https://docs.gitlab.com/ee/administration/reference_architectures/troubleshooting.html) + +* [Troubleshooting object storage](#troubleshooting-object-storage) + * [S3 API compatibility issues](#s3-api-compatibility-issues) + * [GitLab Pages requires NFS](#gitlab-pages-requires-nfs) + * [Incremental logging is required for CI to use object storage](#incremental-logging-is-required-for-ci-to-use-object-storage) + * [Proxy Download](#proxy-download) + * [ETag mismatch](#etag-mismatch) +* [Troubleshooting Redis](#troubleshooting-redis) +* [Troubleshooting Gitaly](#troubleshooting-gitaly) + * [Checking versions when using standalone Gitaly nodes](#checking-versions-when-using-standalone-gitaly-nodes) + * [`gitaly-debug`](#gitaly-debug) + * [Commits, pushes, and clones return a 401](#commits-pushes-and-clones-return-a-401) + * [Client side gRPC logs](#client-side-grpc-logs) + * [Observing `gitaly-ruby` traffic](#observing-gitaly-ruby-traffic) + * [Repository changes fail with a `401 Unauthorized` error](#repository-changes-fail-with-a-401-unauthorized-error) + * [Command line tools cannot connect to Gitaly](#command-line-tools-cannot-connect-to-gitaly) + * [Gitaly not listening on new address after reconfiguring](#gitaly-not-listening-on-new-address-after-reconfiguring) + * [Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly node](#permission-denied-errors-appearing-in-gitaly-logs-when-accessing-repositories-from-a-standalone-gitaly-node) +* [Troubleshooting the GitLab Rails application](#troubleshooting-the-gitlab-rails-application) +* [Troubleshooting Monitoring](#troubleshooting-monitoring) + +# Troubleshooting a reference architecture set up[](#troubleshooting-a-reference-architecture-set-up "Permalink") + +如果您遵循一种[参考体系结构,](index.html#reference-architectures)则此页面可作为故障排除文档. + +## Troubleshooting object storage[](#troubleshooting-object-storage "Permalink") + +### S3 API compatibility issues[](#s3-api-compatibility-issues "Permalink") + +并非所有 S3 提供程序[都](../../raketasks/backup_restore.html#other-s3-providers)与 GitLab 使用的 Fog 库[完全兼容](../../raketasks/backup_restore.html#other-s3-providers) . 症状包括: + +``` +411 Length Required +``` + +### GitLab Pages requires NFS[](#gitlab-pages-requires-nfs "Permalink") + +如果您打算使用[GitLab 页面](../../user/project/pages/index.html) ,则当前需要[NFS](../high_availability/nfs.html) . 有[工作正在进行中](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)去除这种依赖性. 将来,GitLab 页面可能会使用[对象存储](https://gitlab.com/gitlab-org/gitlab/-/issues/208135) . + +对磁盘存储的依赖性还阻止了使用[GitLab Helm 图表](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/37)部署 Pages. + +### Incremental logging is required for CI to use object storage[](#incremental-logging-is-required-for-ci-to-use-object-storage "Permalink") + +如果将 GitLab 配置为将对象存储用于 CI 日志和工件,则[还必须启用增量日志记录](../job_logs.html#new-incremental-logging-architecture) . + +### Proxy Download[](#proxy-download "Permalink") + +对象存储的许多使用情况都允许将客户端流量重定向到对象存储后端,例如当 Git 客户端通过 LFS 请求大文件时或在下载 CI 工件和日志时. + +当文件存储在本地块存储或 NFS 上时,GitLab 必须充当代理. 对于对象存储,GitLab 的默认行为是重定向到对象存储设备,而不是代理请求. + +`proxy_download`设置控制此行为:默认设置通常为`false` . 在每个用例的文档中对此进行验证. 将其设置为`true`可使 GitLab 代理文件而不是重定向. + +当不代理文件时,GitLab 将返回[HTTP 302 重定向,该重定向带有预先签名的有时间限制的对象存储 URL](https://gitlab.com/gitlab-org/gitlab/-/issues/32117#note_218532298) . 这可能会导致以下一些问题: + +* 如果 GitLab 使用非安全的 HTTP 访问对象存储,则客户端可能会生成`https->http`降级错误,并拒绝处理重定向. 解决方案是让 GitLab 使用 HTTPS. 例如,LFS 将产生此错误: + + ``` + LFS: lfsapi/client: refusing insecure redirect, https->http + ``` + +* 客户端将需要信任颁发对象存储证书的证书颁发机构,或者可能返回常见的 TLS 错误,例如: + + ``` + x509: certificate signed by unknown authority + ``` + +* 客户端将需要网络访问对象存储. 如果没有此访问权限,则可能导致的错误包括: + + ``` + Received status code 403 from server: Forbidden + ``` + +### ETag mismatch[](#etag-mismatch "Permalink") + +Using the default GitLab settings, some object storage back-ends such as [MinIO](https://gitlab.com/gitlab-org/gitlab/-/issues/23188) and [Alibaba](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564) might generate `ETag mismatch` errors. + +使用 GitLab 直接上传时, [MinIO](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564#note_244497658)的[解决方法](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564#note_244497658)是在服务器上使用`--compat`参数. + +我们正在致力于 GitLab 组件 Workhorse 的修复,同时,也正在尝试一种解决方法,以[允许禁用 ETag 验证](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18175) . + +## Troubleshooting Redis[](#troubleshooting-redis "Permalink") + +如果应用程序节点无法连接到 Redis 节点,请检查您的防火墙规则,并确保 Redis 可以接受端口`6379`下的 TCP 连接. + +## Troubleshooting Gitaly[](#troubleshooting-gitaly "Permalink") + +### Checking versions when using standalone Gitaly nodes[](#checking-versions-when-using-standalone-gitaly-nodes "Permalink") + +使用独立的 Gitaly 节点时,必须确保它们与 GitLab 的版本相同,以确保完全兼容. 检查您的 GitLab 实例上的**管理区域> Gitaly 服务器** ,并确认所有 Gitaly 服务器都是`Up to date` . + +[![Gitaly standalone software versions diagram](img/ba685b05a8bb7c09fe3b58048ac4884e.png)](../gitaly/img/gitlab_gitaly_version_mismatch_v12_4.png) + +### `gitaly-debug`[](#gitaly-debug "Permalink") + +`gitaly-debug`命令提供用于" Gitaly"和" Git"性能的"生产调试"工具. 它旨在帮助生产工程师和支持工程师调查 Gitaly 性能问题. + +如果您使用的是 GitLab 11.6 或更高版本,则此工具应已安装在您的 GitLab / Gitaly 服务器上,位于`/opt/gitlab/embedded/bin/gitaly-debug` . 如果要研究旧版本的 GitLab,可以离线编译此工具,然后将可执行文件复制到服务器: + +``` +git clone https://gitlab.com/gitlab-org/gitaly.git +cd cmd/gitaly-debug +GOOS=linux GOARCH=amd64 go build -o gitaly-debug +``` + +要查看`gitaly-debug`的帮助页面以`gitaly-debug`受支持的子命令列表,请运行: + +``` +gitaly-debug -h +``` + +### Commits, pushes, and clones return a 401[](#commits-pushes-and-clones-return-a-401 "Permalink") + +``` +remote: GitLab: 401 Unauthorized +``` + +您将需要将`gitlab-secrets.json`文件与 GitLab 应用程序节点同步. + +### Client side gRPC logs[](#client-side-grpc-logs "Permalink") + +Gitaly 使用[gRPC](https://grpc.io/) RPC 框架. Ruby gRPC 客户端具有自己的日志文件,当您看到 Gitaly 错误时,该文件可能包含有用的信息. 您可以使用`GRPC_LOG_LEVEL`环境变量控制 gRPC 客户端的日志级别. 默认级别为`WARN` . + +您可以使用以下命令运行 gRPC 跟踪: + +``` +sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check +``` + +### Observing `gitaly-ruby` traffic[](#observing-gitaly-ruby-traffic "Permalink") + +[`gitaly-ruby`](../gitaly/index.html#gitaly-ruby)是[`gitaly-ruby`](../gitaly/index.html#gitaly-ruby)的内部实现细节,因此,对`gitaly-ruby`流程内部发生的情况`gitaly-ruby` . + +如果已设置 Prometheus 来抓取 Gitaly 进程,则可以通过查询`grpc_client_handled_total`来`grpc_client_handled_total` `gitaly-ruby`各个 RPC 的请求率和错误代码. 严格来说,此度量标准并未区分`gitaly-ruby`和其他 RPC,但实际上(自 GitLab 11.9 起),Gitaly 本身进行的所有 gRPC 调用都是从 Gitaly 主过程到其`gitaly-ruby`边车之一的内部调用. + +假设您的`grpc_client_handled_total`计数器仅观察到 Gitaly,以下查询将显示 RPC 在内部(最有可能)实现为对`gitaly-ruby`调用: + +``` +sum(rate(grpc_client_handled_total[5m])) by (grpc_method) > 0 +``` + +### Repository changes fail with a `401 Unauthorized` error[](#repository-changes-fail-with-a-401-unauthorized-error "Permalink") + +If you’re running Gitaly on its own server and notice that users can successfully clone and fetch repositories (via both SSH and HTTPS), but can’t push to them or make changes to the repository in the web UI without getting a `401 Unauthorized` message, then it’s possible Gitaly is failing to authenticate with the other nodes due to having the wrong secrets file. + +确认以下所有内容均正确: + +* 当任何用户向该 Gitaly 节点上的任何存储库执行`git push` ,它都会失败,并显示以下错误(请注意`401 Unauthorized` ): + + ``` + remote: GitLab: 401 Unauthorized + To + ! [remote rejected] branch-name -> branch-name (pre-receive hook declined) + error: failed to push some refs to '' + ``` + +* 当任何用户使用 GitLab UI 从存储库添加或修改文件时,该文件都会立即失败,并显示红色`401 Unauthorized`横幅. +* 创建一个新项目并[使用 README 对其进行初始化会](../../gitlab-basics/create-project.html#blank-projects)成功创建该项目,但不会创建 README. +* [将日志拖到](https://docs.gitlab.com/omnibus/settings/logs.html)应用程序节点上并重现错误时,到达`/api/v4/internal/allowed`端点时会出现`401`错误: + + ``` + # api_json.log + { + "time": "2019-07-18T00:30:14.967Z", + "severity": "INFO", + "duration": 0.57, + "db": 0, + "view": 0.57, + "status": 401, + "method": "POST", + "path": "\/api\/v4\/internal\/allowed", + "params": [ + { + "key": "action", + "value": "git-receive-pack" + }, + { + "key": "changes", + "value": "REDACTED" + }, + { + "key": "gl_repository", + "value": "REDACTED" + }, + { + "key": "project", + "value": "\/path\/to\/project.git" + }, + { + "key": "protocol", + "value": "web" + }, + { + "key": "env", + "value": "{\"GIT_ALTERNATE_OBJECT_DIRECTORIES\":[],\"GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE\":[],\"GIT_OBJECT_DIRECTORY\":null,\"GIT_OBJECT_DIRECTORY_RELATIVE\":null}" + }, + { + "key": "user_id", + "value": "2" + }, + { + "key": "secret_token", + "value": "[FILTERED]" + } + ], + "host": "gitlab.example.com", + "ip": "REDACTED", + "ua": "Ruby", + "route": "\/api\/:version\/internal\/allowed", + "queue_duration": 4.24, + "gitaly_calls": 0, + "gitaly_duration": 0, + "correlation_id": "XPUZqTukaP3" + } + + # nginx_access.log + [IP] - - [18/Jul/2019:00:30:14 +0000] "POST /api/v4/internal/allowed HTTP/1.1" 401 30 "" "Ruby" + ``` + +要解决此问题,请确认 Gitaly 节点上的 gitlab `gitlab-secrets.json`文件与所有其他节点上的 gitlab `gitlab-secrets.json`文件匹配. 如果不匹配,请更新 Gitaly 节点上的 secrets 文件以使其与其他文件匹配,然后[重新配置该节点](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +### Command line tools cannot connect to Gitaly[](#command-line-tools-cannot-connect-to-gitaly "Permalink") + +如果使用命令行(CLI)工具连接到 Gitaly 节点时遇到问题,并且某些操作导致出现`14: Connect Failed`错误消息,则表明 gRPC 无法到达您的 Gitaly 节点. + +确认您可以通过 TCP 到达 Gitaly: + +``` +sudo gitlab-rake gitlab:tcp_check[GITALY_SERVER_IP,GITALY_LISTEN_PORT] +``` + +如果 TCP 连接失败,请检查您的网络设置和防火墙规则. 如果 TCP 连接成功,则您的网络和防火墙规则正确. + +如果您在命令行环境(例如 Bash)中使用代理服务器,则这些代理服务器可能会干扰您的 gRPC 通信. + +如果使用 Bash 或兼容的命令行环境,请运行以下命令来确定是否配置了代理服务器: + +``` +echo $http_proxy +echo $https_proxy +``` + +如果这些变量中的任何一个都有值,则您的 Gitaly CLI 连接可能正在通过无法连接到 Gitaly 的代理进行路由. + +要删除代理设置,请运行以下命令(取决于哪些变量具有值): + +``` +unset http_proxy +unset https_proxy +``` + +### Gitaly not listening on new address after reconfiguring[](#gitaly-not-listening-on-new-address-after-reconfiguring "Permalink") + +当更新`gitaly['listen_addr']`或`gitaly['prometheus_listen_addr']`值时,Gitaly 可能会在`sudo gitlab-ctl reconfigure`后继续侦听旧地址. + +发生这种情况时,执行`sudo gitlab-ctl restart`将解决此问题. 解决[此问题](https://gitlab.com/gitlab-org/gitaly/-/issues/2521)后,将不再需要[此操作](https://gitlab.com/gitlab-org/gitaly/-/issues/2521) . + +### Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly node[](#permission-denied-errors-appearing-in-gitaly-logs-when-accessing-repositories-from-a-standalone-gitaly-node "Permalink") + +如果即使文件许可权正确也发生此错误,则 Gitaly 节点很可能正在发生[时钟漂移](https://en.wikipedia.org/wiki/Clock_drift) . + +请确保 GitLab 和 Gitaly 节点已同步,并在可能的情况下使用 NTP 时间服务器使其保持同步. + +## Troubleshooting the GitLab Rails application[](#troubleshooting-the-gitlab-rails-application "Permalink") + +* `mount: wrong fs type, bad option, bad superblock on` + +您尚未安装必要的 NFS 客户端实用程序. 请参阅上面的步骤 1. + +* `mount: mount point /var/opt/gitlab/... does not exist` + +NFS 服务器上不存在此特定目录. 确保共享已导出并且存在于 NFS 服务器上,然后尝试重新安装. + +## Troubleshooting Monitoring[](#troubleshooting-monitoring "Permalink") + +如果监视节点未接收到任何数据,请检查导出器是否正在捕获数据. + +``` +curl http[s]://localhost:/metric +``` + +or + +``` +curl http[s]://localhost:/-/metric +``` \ No newline at end of file diff --git a/_book/docs/429.md b/_book/docs/429.md new file mode 100644 index 0000000000000000000000000000000000000000..84f8ba2760426b3cd680b6a3f0e60b94c2ba71aa --- /dev/null +++ b/_book/docs/429.md @@ -0,0 +1,205 @@ +# Working with the bundled Consul service + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/consul.html](https://docs.gitlab.com/ee/administration/high_availability/consul.html) + +* [Prerequisites](#prerequisites) +* [Configuring the Consul nodes](#configuring-the-consul-nodes) + * [Consul checkpoint](#consul-checkpoint) +* [Operations](#operations) + * [Checking cluster membership](#checking-cluster-membership) + * [Restarting the server cluster](#restarting-the-server-cluster) +* [Upgrades for bundled Consul](#upgrades-for-bundled-consul) +* [Troubleshooting](#troubleshooting) + * [Consul server agents unable to communicate](#consul-server-agents-unable-to-communicate) + * [Consul agents do not start - Multiple private IPs](#consul-agents-do-not-start---multiple-private-ips) + * [Outage recovery](#outage-recovery) + * [Recreate from scratch](#recreate-from-scratch) + * [Recover a failed cluster](#recover-a-failed-cluster) + +# Working with the bundled Consul service[](#working-with-the-bundled-consul-service-premium-only "Permalink") + +作为其高可用性堆栈的一部分,GitLab Premium 包含可通过`/etc/gitlab/gitlab.rb`管理的捆绑版本的[Consul](https://www.consul.io/) . Consul 是服务网络解决方案. 对于[GitLab Architecture](../../development/architecture.html) ,支持 Consul 利用来配置: + +1. [Monitoring in Scaled and Highly Available environments](monitoring_node.html) +2. [PostgreSQL High Availability with Omnibus](../postgresql/replication_and_failover.html) + +Consul 群集由多个服务器代理以及在其他需要与 Consul 群集通信的节点上运行的客户端代理组成. + +## Prerequisites[](#prerequisites "Permalink") + +首先,请确保**在每个节点上** [下载/安装](https://about.gitlab.com/install/) Omnibus GitLab. + +选择一种安装方法,然后确保完成以下步骤: + +1. 安装和配置必要的依赖项. +2. 添加 GitLab 软件包存储库并安装软件包. + +安装 GitLab 软件包时,请勿提供`EXTERNAL_URL`值. + +## Configuring the Consul nodes[](#configuring-the-consul-nodes "Permalink") + +在每个 Consul 节点上执行以下操作: + +1. 在执行下一步之前,请确保为[`CONSUL_SERVER_NODES`](../postgresql/replication_and_failover.html#consul-information)收集[`CONSUL_SERVER_NODES`](../postgresql/replication_and_failover.html#consul-information) ,它们是 Consul 服务器节点的 IP 地址或 DNS 记录. + +2. 编辑`/etc/gitlab/gitlab.rb`替换`/etc/gitlab/gitlab.rb` `# START user configuration`部分中记录的值: + + ``` + # Disable all components except Consul + roles ['consul_role'] + + # START user configuration + # Replace placeholders: + # + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses gathered for CONSUL_SERVER_NODES + consul['configuration'] = { + server: true, + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z) + } + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + # + # END user configuration + ``` + + > `consul_role`在 GitLab 10.3 中引入 + +3. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +### Consul checkpoint[](#consul-checkpoint "Permalink") + +在继续之前,请确保 Consul 配置正确. 运行以下命令以验证所有服务器节点都在通信: + +``` +/opt/gitlab/embedded/bin/consul members +``` + +输出应类似于: + +``` +Node Address Status Type Build Protocol DC +CONSUL_NODE_ONE XXX.XXX.XXX.YYY:8301 alive server 0.9.2 2 gitlab_consul +CONSUL_NODE_TWO XXX.XXX.XXX.YYY:8301 alive server 0.9.2 2 gitlab_consul +CONSUL_NODE_THREE XXX.XXX.XXX.YYY:8301 alive server 0.9.2 2 gitlab_consul +``` + +如果任何一个节点都不`alive`或三个节点中的任何一个都不`alive` ,请在继续操作之前检查" [疑难解答"部分](#troubleshooting) . + +## Operations[](#operations "Permalink") + +### Checking cluster membership[](#checking-cluster-membership "Permalink") + +要查看哪些节点是集群的一部分,请在集群中的任何成员上运行以下命令 + +``` +$ /opt/gitlab/embedded/bin/consul members +Node Address Status Type Build Protocol DC +consul-b XX.XX.X.Y:8301 alive server 0.9.0 2 gitlab_consul +consul-c XX.XX.X.Y:8301 alive server 0.9.0 2 gitlab_consul +consul-c XX.XX.X.Y:8301 alive server 0.9.0 2 gitlab_consul +db-a XX.XX.X.Y:8301 alive client 0.9.0 2 gitlab_consul +db-b XX.XX.X.Y:8301 alive client 0.9.0 2 gitlab_consul +``` + +Ideally all nodes will have a `Status` of `alive`. + +### Restarting the server cluster[](#restarting-the-server-cluster "Permalink") + +**注意:**本部分仅适用于服务器代理. 在需要时重新启动客户端代理是安全的. + +如果有必要重新启动服务器群集,则以受控方式进行此操作很重要,以保持仲裁. 如果仲裁丢失,则需要遵循 Consul [中断恢复](#outage-recovery)过程来恢复群集. + +为了安全起见,建议您一次仅重新启动一个服务器代理,以确保群集保持完整. + +对于较大的群集,可以一次重新启动多个代理. 请参阅[领事共识文档,](https://www.consul.io/docs/internals/consensus.html#deployment-table)以了解可以容忍多少次失败. 这是它可以承受的同时重启的次数. + +## Upgrades for bundled Consul[](#upgrades-for-bundled-consul "Permalink") + +运行 GitLab 捆绑的 Consul 的节点应为: + +* 升级 Omnibus GitLab 软件包之前,健康集群的成员. +* 一次升级一个节点. + +**注意:**从任何 Consul 节点运行`curl http://127.0.0.1:8500/v1/health/state/critical` ,将识别群集中的现有运行状况问题. 如果群集运行状况良好,该命令将返回一个空数组. + +领事群集使用筏协议进行通信. 如果当前领导者下线,则需要进行领导者选举. 必须存在一个领导者节点,以促进整个集群之间的同步. 如果同时有太多节点脱机,则由于[共识破裂](https://www.consul.io/docs/internals/consensus.html) ,群集将失去仲裁且不会选举领导者. + +如果群集在升级后无法恢复,请参考[故障排除部分](#troubleshooting) . [中断恢复](#outage-recovery)可能特别有意义. + +**注意:** GitLab 仅使用 Consul 来存储易于重新生成的瞬态数据. 如果捆绑包的 Consul 除了 GitLab 本身以外没有被其他进程使用,那么[从头开始重建集群](#recreate-from-scratch)就可以了. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Consul server agents unable to communicate[](#consul-server-agents-unable-to-communicate "Permalink") + +默认情况下,服务器代理将尝试[绑定](https://www.consul.io/docs/agent/options.html#_bind)到" 0.0.0.0",但是它们将通告节点上的第一个私有 IP 地址,以供其他代理与其通信. 如果其他节点无法与此地址上的节点通信,则群集将处于故障状态. + +如果遇到此问题,您将在`gitlab-ctl tail consul`输出中看到类似以下的消息: + +``` +2017-09-25_19:53:39.90821 2017/09/25 19:53:39 [WARN] raft: no known peers, aborting election +2017-09-25_19:53:41.74356 2017/09/25 19:53:41 [ERR] agent: failed to sync remote state: No cluster leader +``` + +要解决此问题: + +1. 在每个其他节点都可以到达的节点上选择一个地址. +2. 更新您的`/etc/gitlab/gitlab.rb` + + ``` + consul['configuration'] = { + ... + bind_addr: 'IP ADDRESS' + } + ``` + +3. Run `gitlab-ctl reconfigure` + +如果仍然看到错误,则可能必须[删除 Consul 数据库并](#recreate-from-scratch)在受影响的节点上[重新初始化](#recreate-from-scratch) . + +### Consul agents do not start - Multiple private IPs[](#consul-agents-do-not-start---multiple-private-ips "Permalink") + +如果一个节点具有多个专用 IP,则代理会混淆要播发哪个专用地址,然后在启动时立即退出. + +如果遇到此问题,您将在`gitlab-ctl tail consul`输出中看到类似以下的消息: + +``` +2017-11-09_17:41:45.52876 ==> Starting Consul agent... +2017-11-09_17:41:45.53057 ==> Error creating agent: Failed to get advertise address: Multiple private IPs found. Please configure one. +``` + +要解决此问题: + +1. 在该节点上选择一个地址,所有其他节点都可以通过该地址到达该节点. +2. 更新您的`/etc/gitlab/gitlab.rb` + + ``` + consul['configuration'] = { + ... + bind_addr: 'IP ADDRESS' + } + ``` + +3. Run `gitlab-ctl reconfigure` + +### Outage recovery[](#outage-recovery "Permalink") + +如果您在群集中丢失了足够的服务器代理以破坏仲裁,则该群集将被视为失败,并且如果没有手动干预,它将无法运行. + +#### Recreate from scratch[](#recreate-from-scratch "Permalink") + +默认情况下,GitLab 不会在 Consul 群集中存储任何无法重新创建的内容. 删除 Consul 数据库并重新初始化 + +``` +gitlab-ctl stop consul +rm -rf /var/opt/gitlab/consul/data +gitlab-ctl start consul +``` + +此后,群集应开始备份,并且服务器代理重新加入. 之后不久,客户代理也应重新加入. + +#### Recover a failed cluster[](#recover-a-failed-cluster "Permalink") + +如果您已利用 Consul 来存储其他数据,并想还原发生故障的群集,请按照[Consul 指南](https://learn.hashicorp.com/consul/day-2-operations/outage)来恢复发生故障的群集. \ No newline at end of file diff --git a/_book/docs/430.md b/_book/docs/430.md new file mode 100644 index 0000000000000000000000000000000000000000..fa72dca9827f5f429c4bf890aa9bdc8947fd425a --- /dev/null +++ b/_book/docs/430.md @@ -0,0 +1,31 @@ +# Configuring PostgreSQL for scaling + +> 原文:[https://docs.gitlab.com/ee/administration/postgresql/](https://docs.gitlab.com/ee/administration/postgresql/) + +* [PostgreSQL replication and failover with Omnibus GitLab](#postgresql-replication-and-failover-with-omnibus-gitlab-premium-only) +* [Standalone PostgreSQL using Omnibus GitLab](#standalone-postgresql-using-omnibus-gitlab-core-only) +* [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance-core-only) + +# Configuring PostgreSQL for scaling[](#configuring-postgresql-for-scaling "Permalink") + +在本节中,将指导您配置 PostgreSQL 数据库,以在我们的[可扩展和高度可用的设置](../reference_architectures/index.html)之一中与 GitLab 一起使用. 基本上有三种设置可供选择. + +## PostgreSQL replication and failover with Omnibus GitLab[](#postgresql-replication-and-failover-with-omnibus-gitlab-premium-only "Permalink") + +此设置适用于使用[Omnibus GitLab **企业版** (EE)软件包](https://about.gitlab.com/install/?version=ee)安装 GitLab 的情况. + +所有必需的工具(如 PostgreSQL,PgBouncer,Repmgr)都捆绑在软件包中,因此您可以用它来设置整个 PostgreSQL 基础结构(主数据库,副本数据库). + +[> Read how to set up PostgreSQL replication and failover using Omnibus GitLab](replication_and_failover.html) + +## Standalone PostgreSQL using Omnibus GitLab[](#standalone-postgresql-using-omnibus-gitlab-core-only "Permalink") + +此设置适用于您安装[Omnibus GitLab 软件包](https://about.gitlab.com/install/) (CE 或 EE)时使用仅启用了服务的捆绑 PostgreSQL 的情况. + +[> Read how to set up a standalone PostgreSQL instance using Omnibus GitLab](standalone.html) + +## Provide your own PostgreSQL instance[](#provide-your-own-postgresql-instance-core-only "Permalink") + +此设置适用于使用[Omnibus GitLab 软件包](https://about.gitlab.com/install/) (CE 或 EE)安装 GitLab 或[从源代码](../../install/installation.html)安装 GitLab 的情况,但您想使用自己的外部 PostgreSQL 服务器. + +[> Read how to set up an external PostgreSQL instance](external.html) \ No newline at end of file diff --git a/_book/docs/431.md b/_book/docs/431.md new file mode 100644 index 0000000000000000000000000000000000000000..0bb165ea01025aadbad45172214762e9eaab4a39 --- /dev/null +++ b/_book/docs/431.md @@ -0,0 +1,163 @@ +# Configuring GitLab application (Rails) + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/gitlab.html](https://docs.gitlab.com/ee/administration/high_availability/gitlab.html) + +* [First GitLab application server](#first-gitlab-application-server) +* [Extra configuration for additional GitLab application servers](#extra-configuration-for-additional-gitlab-application-servers) +* [Enable Monitoring](#enable-monitoring) +* [Troubleshooting](#troubleshooting) +* [Upgrading GitLab HA](#upgrading-gitlab-ha) + +# Configuring GitLab application (Rails)[](#configuring-gitlab-application-rails "Permalink") + +本节介绍如何配置 GitLab 应用程序(Rails)组件. + +**注意:**底部附近还有一些其他配置,用于其他 GitLab 应用程序服务器. 在继续安装 GitLab 之前,阅读并理解这些其他步骤非常重要.**注意:**建议尽可能通过[NFS](nfs.html)使用[Gitaly 的](gitaly.html) [Cloud Object Storage 服务](object_storage.html) ,以提高性能. + +1. 如有必要,请使用以下命令安装 NFS 客户端实用程序软件包: + + ``` + # Ubuntu/Debian + apt-get install nfs-common + + # CentOS/Red Hat + yum install nfs-utils nfs-utils-lib + ``` + +2. 在`/etc/fstab`指定必要的 NFS 导出. `/etc/fstab`的确切内容取决于您选择配置 NFS 服务器的方式. 有关示例和各种选项,请参见[NFS 文档](nfs.html#nfs-client-mount-options) . + +3. 创建共享目录. 这些可能会有所不同,具体取决于您的 NFS 安装位置. + + ``` + mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data + ``` + +4. 使用[GitLab 下载中的](https://about.gitlab.com/install/) **步骤 1 和 2**下载/安装 Omnibus GitLab. 不要完成下载页面上的其他步骤. +5. 创建/编辑`/etc/gitlab/gitlab.rb`并使用以下配置. 确保更改`external_url`以匹配最终的 GitLab 前端 URL. 根据您的 NFS 配置,您可能需要更改某些 GitLab 数据位置. 有关各种情况的`/etc/gitlab/gitlab.rb`配置值,请参见[NFS 文档](nfs.html) . 下面的示例假定您已在默认数据位置中添加了 NFS 挂载. 此外,给出的 UID 和 GID 只是示例,您应该使用首选值进行配置. + + ``` + external_url 'https://gitlab.example.com' + + # Prevent GitLab from starting if NFS data mounts are not available + high_availability['mountpoint'] = '/var/opt/gitlab/git-data' + + # Disable components that will not be on the GitLab application server + roles ['application_role'] + nginx['enable'] = true + + # PostgreSQL connection details + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['db_host'] = '10.1.0.5' # IP/hostname of database server + gitlab_rails['db_password'] = 'DB password' + + # Redis connection details + gitlab_rails['redis_port'] = '6379' + gitlab_rails['redis_host'] = '10.1.0.6' # IP/hostname of Redis server + gitlab_rails['redis_password'] = 'Redis Password' + + # Ensure UIDs and GIDs match between servers for permissions via NFS + user['uid'] = 9000 + user['gid'] = 9000 + web_server['uid'] = 9001 + web_server['gid'] = 9001 + registry['uid'] = 9002 + registry['gid'] = 9002 + ``` + +6. [Enable monitoring](#enable-monitoring) + + **注意:**为了保持 HA 群集之间链接的统一性,第一个应用程序服务器上的`external_url`以及其他应用程序服务器应指向用户将用来访问 GitLab 的外部 URL. 在典型的 HA 设置中,这将是负载平衡器的 URL,它将把流量路由到 HA 群集中的所有 GitLab 应用程序服务器.**注意:**如上例所示,当在`external_url`指定`https`时,GitLab 会假定您在`/etc/gitlab/ssl/`具有 SSL 证书. 如果没有证书,NGINX 将无法启动. 有关更多信息,请参见[NGINX 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) .**注意:**最好在初始重新配置 GitLab 之前设置`uid`和`gid` . 如果在初始重新配置后设置,Omnibus 将不会递归`chown`目录. + +## First GitLab application server[](#first-gitlab-application-server "Permalink") + +在第一台应用程序服务器上,运行: + +``` +sudo gitlab-ctl reconfigure +``` + +这应该编译配置并初始化数据库. 在下一步之前,不要在其他应用程序服务器上运行此命令. + +## Extra configuration for additional GitLab application servers[](#extra-configuration-for-additional-gitlab-application-servers "Permalink") + +其他的 GitLab 服务器( **在**第一个 GitLab 服务器**之后**配置的服务器)需要一些额外的配置. + +1. 配置共享机密. 这些值可以从`/etc/gitlab/gitlab-secrets.json`的主要 GitLab 服务器`/etc/gitlab/gitlab-secrets.json` . **在**运行上述步骤中的第一次`reconfigure` **之前,**将此文件复制到辅助服务器. + + ``` + gitlab_shell['secret_token'] = 'fbfb19c355066a9afb030992231c4a363357f77345edd0f2e772359e5be59b02538e1fa6cae8f93f7d23355341cea2b93600dab6d6c3edcdced558fc6d739860' + gitlab_rails['otp_key_base'] = 'b719fe119132c7810908bba18315259ed12888d4f5ee5430c42a776d840a396799b0a5ef0a801348c8a357f07aa72bbd58e25a84b8f247a25c72f539c7a6c5fa' + gitlab_rails['secret_key_base'] = '6e657410d57c71b4fc3ed0d694e7842b1895a8b401d812c17fe61caf95b48a6d703cb53c112bc01ebd197a85da81b18e29682040e99b4f26594772a4a2c98c6d' + gitlab_rails['db_key_base'] = 'bf2e47b68d6cafaef1d767e628b619365becf27571e10f196f98dc85e7771042b9203199d39aff91fcb6837c8ed83f2a912b278da50999bb11a2fbc0fba52964' + ``` + +2. 运行`touch /etc/gitlab/skip-auto-reconfigure`以防止数据库迁移在升级时运行. 只有主 GitLab 应用程序服务器才能处理迁移. + +3. **推荐**配置主机密钥. 将主应用程序服务器上`/etc/ssh/`的内容(私钥和公钥)复制到所有辅助服务器上的`/etc/ssh` . 这样可以防止访问负载平衡器后面的高可用性群集中的服务器时出现虚假的中间人攻击警报. + +4. 运行`sudo gitlab-ctl reconfigure`来编译配置. + +**注意:**发生更新并执行数据库迁移后,您将需要重新启动 GitLab 应用程序节点. + +## Enable Monitoring[](#enable-monitoring "Permalink") + +在 GitLab 12.0 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) . + +如果启用了监视,则必须在**所有** GitLab 服务器上将其启用. + +1. Make sure to collect [`CONSUL_SERVER_NODES`](../postgresql/replication_and_failover.html#consul-information), which are the IP addresses or DNS records of the Consul server nodes, for the next step. Note they are presented as `Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z` + +2. 创建/编辑`/etc/gitlab/gitlab.rb`并添加以下配置: + + ``` + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Replace placeholders + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses of the Consul server nodes + consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' + sidekiq['listen_address'] = "0.0.0.0" + puma['listen'] = '0.0.0.0' + + # Add the monitoring node's IP address to the monitoring list that allows it to + # scrape the NGINX metrics. Replace placeholder `monitoring.gitlab.example.com` with + # the address and/or subnets gathered from the monitoring node(s). + gitlab_rails['monitoring_whitelist'] = ['monitoring.gitlab.example.com', '127.0.0.0/8'] + nginx['status']['options']['allow'] = ['monitoring.gitlab.example.com', '127.0.0.0/8'] + ``` + +3. 运行`sudo gitlab-ctl reconfigure`来编译配置. + + **警告:**如果运行 Unicorn,则在`gitlab.rb`更改`unicorn['listen']`并运行`sudo gitlab-ctl reconfigure`后,收到`HUP`后,Unicorn 可能需要较长的时间才能完成重新加载. 有关更多信息,请参见[问题](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4401) . + +## Troubleshooting[](#troubleshooting "Permalink") + +* `mount: wrong fs type, bad option, bad superblock on` + +您尚未安装必要的 NFS 客户端实用程序. 请参阅上面的步骤 1. + +* `mount: mount point /var/opt/gitlab/... does not exist` + +NFS 服务器上不存在此特定目录. 确保共享已导出并且存在于 NFS 服务器上,然后尝试重新安装. + +* * * + +## Upgrading GitLab HA[](#upgrading-gitlab-ha "Permalink") + +可以在不停机的情况下升级 GitLab HA 安装,但是必须仔细协调升级过程,以免发生故障. 有关更多详细信息,请参见[Omnibus GitLab 多节点升级文档](https://docs.gitlab.com/omnibus/update/) . + +阅读更多有关高可用性配置的信息: + +1. [Configure the database](../postgresql/replication_and_failover.html) +2. [Configure Redis](redis.html) +3. [Configure NFS](nfs.html) +4. [Configure the load balancers](load_balancer.html) \ No newline at end of file diff --git a/_book/docs/432.md b/_book/docs/432.md new file mode 100644 index 0000000000000000000000000000000000000000..439cd599fb7b887dd522b5ca26294cbac0f60797 --- /dev/null +++ b/_book/docs/432.md @@ -0,0 +1,91 @@ +# Load Balancer for multi-node GitLab + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/load_balancer.html](https://docs.gitlab.com/ee/administration/high_availability/load_balancer.html) + +* [SSL](#ssl) + * [Application nodes terminate SSL](#application-nodes-terminate-ssl) + * [Load Balancer(s) terminate SSL without backend SSL](#load-balancers-terminate-ssl-without-backend-ssl) + * [Load Balancer(s) terminate SSL with backend SSL](#load-balancers-terminate-ssl-with-backend-ssl) +* [Ports](#ports) + * [Basic ports](#basic-ports) + * [GitLab Pages Ports](#gitlab-pages-ports) + * [Alternate SSH Port](#alternate-ssh-port) +* [Readiness check](#readiness-check) + +# Load Balancer for multi-node GitLab[](#load-balancer-for-multi-node-gitlab "Permalink") + +在多节点 GitLab 配置中,您将需要一个负载平衡器才能将流量路由到应用程序服务器. 有关使用负载均衡器或进行确切配置的细节超出了 GitLab 文档的范围. 我们希望,如果您要管理像 GitLab 这样的 HA 系统,那么已经选择了负载均衡器. 一些示例包括 HAProxy(开源),F5 Big-IP LTM 和 Citrix Net Scaler. 本文档将概述需要在 GitLab 上使用哪些端口和协议. + +## SSL[](#ssl "Permalink") + +您将如何在多节点环境中处理 SSL? 有几种不同的选择: + +* 每个应用程序节点终止 SSL +* 负载平衡器终止 SSL,并且负载平衡器与应用程序节点之间的通信不安全 +* 负载平衡器终止 SSL,并且负载平衡器与应用程序节点之间的通信是*安全*的 + +### Application nodes terminate SSL[](#application-nodes-terminate-ssl "Permalink") + +将您的负载均衡器配置为以" TCP"而不是" HTTP(S)"协议的形式在端口 443 上传递连接. 这会将连接保持不变地传递到应用程序节点 NGINX 服务. NGINX 将具有 SSL 证书并在端口 443 上侦听. + +有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load Balancer(s) terminate SSL without backend SSL[](#load-balancers-terminate-ssl-without-backend-ssl "Permalink") + +将您的负载均衡器配置为使用" HTTP(S)"协议而不是" TCP". 然后,负载均衡器将负责管理 SSL 证书和终止 SSL. + +由于负载均衡器和 GitLab 之间的通信将不安全,因此需要一些其他配置. 有关详细信息,请参见[NGINX 代理的 SSL 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load Balancer(s) terminate SSL with backend SSL[](#load-balancers-terminate-ssl-with-backend-ssl "Permalink") + +将您的负载均衡器配置为使用" HTTP(S)"协议而不是" TCP". 负载平衡器将负责管理最终用户将看到的 SSL 证书. + +在这种情况下,负载均衡器和 NGINX 之间的流量也将是安全的. 无需为代理 SSL 添加配置,因为连接将一直保持安全. 但是,需要将配置添加到 GitLab 来配置 SSL 证书. 有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +## Ports[](#ports "Permalink") + +### Basic ports[](#basic-ports "Permalink") + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 80 | HTTP( *1* ) | +| 443 | 443 | TCP 或 HTTPS( *1* )( *2* ) | +| 22 | 22 | TCP | + +* ( *1* ): [Web 终端](../../ci/environments/index.html#web-terminals)支持要求您的负载平衡器正确处理 WebSocket 连接. 当使用 HTTP 或 HTTPS 代理,这意味着负载平衡器必须被配置为通过`Connection`和`Upgrade`逐跳头. 有关更多详细信息,请参见[Web 终端](../integration/terminal.html)集成指南. +* ( *2* ):当对端口 443 使用 HTTPS 协议时,需要向负载均衡器添加 SSL 证书. 如果您想在 GitLab 应用程序服务器上终止 SSL,请使用 TCP 协议. + +### GitLab Pages Ports[](#gitlab-pages-ports "Permalink") + +如果您使用具有自定义域支持的 GitLab 页面,则将需要一些其他端口配置. GitLab 页面需要一个单独的虚拟 IP 地址. 配置 DNS,将`pages_external_url`的`/etc/gitlab/gitlab.rb`指向新的虚拟 IP 地址. 有关更多信息,请参见[GitLab 页面文档](../pages/index.html) . + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 变化( *1* ) | HTTP | +| 443 | 变化( *1* ) | TCP( *2* ) | + +* ( *1* ):GitLab 页面的后端端口取决于`gitlab_pages['external_http']`和`gitlab_pages['external_https']`设置. 有关更多详细信息,请参见[GitLab Pages 文档](../pages/index.html) . +* ( *2* ):GitLab 页面的端口 443 应该始终使用 TCP 协议. 用户可以使用自定义 SSL 配置自定义域,如果 SSL 在负载均衡器处终止,则不可能. + +### Alternate SSH Port[](#alternate-ssh-port "Permalink") + +某些组织有禁止打开 SSH 端口 22 的策略.在这种情况下,配置允许用户在端口 443 上使用 SSH 的备用 SSH 主机名可能会有所帮助.与其他 GitLab 相比,备用 SSH 主机名将需要一个新的虚拟 IP 地址.上面的 HTTP 配置. + +为备用 SSH 主机名(例如`altssh.gitlab.example.com`配置 DNS. + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 443 | 22 | TCP | + +## Readiness check[](#readiness-check "Permalink") + +强烈建议多节点部署将负载平衡器配置为利用[就绪检查,](../../user/admin_area/monitoring/health_check.html#readiness)以确保在将流量路由到节点之前准备好接受流量. 在使用 Puma 时,这一点尤其重要,因为在重新启动过程中会有短暂的一段时间,Puma 将不接受请求. + +* * * + +阅读更多有关高可用性配置的信息: + +1. [Configure the database](../postgresql/replication_and_failover.html) +2. [Configure Redis](redis.html) +3. [Configure NFS](nfs.html) +4. [Configure the GitLab application servers](gitlab.html) \ No newline at end of file diff --git a/_book/docs/433.md b/_book/docs/433.md new file mode 100644 index 0000000000000000000000000000000000000000..267d104ebe0867a919cd54ac111959b5b0b8b073 --- /dev/null +++ b/_book/docs/433.md @@ -0,0 +1,86 @@ +# Configuring a Monitoring node for Scaling and High Availability + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/monitoring_node.html](https://docs.gitlab.com/ee/administration/high_availability/monitoring_node.html) + +* [Standalone Monitoring node using Omnibus GitLab](#standalone-monitoring-node-using-omnibus-gitlab) +* [Migrating to Service Discovery](#migrating-to-service-discovery) + +# Configuring a Monitoring node for Scaling and High Availability[](#configuring-a-monitoring-node-for-scaling-and-high-availability "Permalink") + +在 GitLab 12.0 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) . + +您可以配置 Prometheus 节点以监视 GitLab. + +## Standalone Monitoring node using Omnibus GitLab[](#standalone-monitoring-node-using-omnibus-gitlab "Permalink") + +Omnibus GitLab 软件包可用于配置运行[Prometheus](../monitoring/prometheus/index.html)和[Grafana](../monitoring/performance/grafana_configuration.html)的独立 Monitoring 节点. 监视节点不是高度可用. 请参阅[缩放和高可用性](../reference_architectures/index.html)的 GitLab 扩展和高可用性选项的概述. + +以下步骤是使用 Omnibus 配置运行 Prometheus 和 Grafana 的 Monitoring 节点的最低必需步骤: + +1. SSH 进入"监视"节点. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 不要完成下载页面上的任何其他步骤. +3. [`CONSUL_SERVER_NODES`](../postgresql/replication_and_failover.html#consul-information) ,请确保收集[`CONSUL_SERVER_NODES`](../postgresql/replication_and_failover.html#consul-information) ,它们是 Consul 服务器节点的 IP 地址或 DNS 记录. 请注意,它们显示为`YYYY consul1.gitlab.example.com ZZZZ` + +4. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + external_url 'http://gitlab.example.com' + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Login form + grafana['disable_login_form'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = 'toomanysecrets' + + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Replace placeholders + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses of the Consul server nodes + consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), + } + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + node_exporter['enable'] = false + gitlab_exporter['enable'] = false + ``` + +5. 运行`sudo gitlab-ctl reconfigure`来编译配置. + +下一步是告诉所有其他节点监视节点在哪里: + +1. 编辑`/etc/gitlab/gitlab.rb` ,然后添加或查找并取消注释以下行: + + ``` + gitlab_rails['prometheus_address'] = '10.0.0.1:9090' + ``` + + 其中`10.0.0.1:9090`是 Prometheus 节点的 IP 地址和端口. + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +## Migrating to Service Discovery[](#migrating-to-service-discovery "Permalink") + +使用`consul['monitoring_service_discovery'] = true`启用使用服务发现进行`consul['monitoring_service_discovery'] = true` ,请确保未在`/etc/gitlab/gitlab.rb`设置`prometheus['scrape_configs']` . 在`/etc/gitlab/gitlab.rb`同时设置`consul['monitoring_service_discovery'] = true`和`prometheus['scrape_configs']`都会导致错误. \ No newline at end of file diff --git a/_book/docs/434.md b/_book/docs/434.md new file mode 100644 index 0000000000000000000000000000000000000000..b134a5f003ae40b70f2e55a83bc41ccbbe2a7b09 --- /dev/null +++ b/_book/docs/434.md @@ -0,0 +1,237 @@ +# NFS + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/nfs.html](https://docs.gitlab.com/ee/administration/high_availability/nfs.html) + +* [Known kernel version incompatibilities](#known-kernel-version-incompatibilities) +* [NFS Server features](#nfs-server-features) + * [Required features](#required-features) + * [Recommended options](#recommended-options) + * [Disable NFS server delegation](#disable-nfs-server-delegation) + * [Important notes](#important-notes) + * [Improving NFS performance with GitLab](#improving-nfs-performance-with-gitlab) + * [Improving NFS performance with Unicorn](#improving-nfs-performance-with-unicorn) + * [Improving NFS performance with Puma](#improving-nfs-performance-with-puma) + * [Known issues](#known-issues) + * [Avoid using AWS’s Elastic File System (EFS)](#avoid-using-awss-elastic-file-system-efs) + * [Avoid using CephFS and GlusterFS](#avoid-using-cephfs-and-glusterfs) + * [Avoid using PostgreSQL with NFS](#avoid-using-postgresql-with-nfs) +* [NFS Client mount options](#nfs-client-mount-options) + * [soft mount option](#soft-mount-option) +* [A single NFS mount](#a-single-nfs-mount) +* [Bind mounts](#bind-mounts) +* [Multiple NFS mounts](#multiple-nfs-mounts) + +# NFS[](#nfs "Permalink") + +您可以通过运行`nfsstat -m`和`cat /etc/fstab`来查看每个已安装的 NFS 文件系统的信息和选项集. + +**注意:**从 GitLab 13.0 开始,不建议将 NFS 用于 Git 存储库. 在 GitLab 14.0 中,计划删除对 Nit for Git 存储库的支持. 尽快升级到[Gitaly Cluster](../gitaly/praefect.html) .**注意:**文件系统的性能对整体 GitLab 的性能有很大的影响,特别是对于读取或写入 Git 存储库的操作. 有关测试文件系统性能的步骤,请参见[文件系统性能基准](../operations/filesystem_benchmarking.html)测试. + +## Known kernel version incompatibilities[](#known-kernel-version-incompatibilities "Permalink") + +RedHat Enterprise Linux(RHEL)和 CentOS v7.7 和 v7.8 附带了内核版本`3.10.0-1127` ,该版本[包含一个错误](https://bugzilla.redhat.com/show_bug.cgi?id=1783554) , [该错误](https://bugzilla.redhat.com/show_bug.cgi?id=1783554)会导致[上传无法通过 NFS 复制](https://gitlab.com/gitlab-org/gitlab/-/issues/218999) . 以下 GitLab 版本包含一个可与该内核版本一起正常使用的修复程序: + +1. [12.10.12](https://about.gitlab.com/releases/2020/06/25/gitlab-12-10-12-released/) +2. [13.0.7](https://about.gitlab.com/releases/2020/06/25/gitlab-13-0-7-released/) +3. [13.1.1](https://about.gitlab.com/releases/2020/06/24/gitlab-13-1-1-released/) +4. 13.2 以上 + +如果使用的是该内核版本,请确保升级 GitLab 以避免错误. + +## NFS Server features[](#nfs-server-features "Permalink") + +### Required features[](#required-features "Permalink") + +**文件锁定** :GitLab **需要**咨询性文件锁定,只有 NFS 版本 4 才支持该功能.只要使用 Linux Kernel 2.6.5 +,NFSv3 还支持锁定. 我们建议使用版本 4,并且不要专门测试 NFSv3. + +### Recommended options[](#recommended-options "Permalink") + +定义 NFS 导出时,建议您还添加以下选项: + +* `no_root_squash` -NFS 通常将`root`用户更改为`nobody` . 当许多不同的用户将访问 NFS 共享时,这是一个很好的安全措施. 但是,在这种情况下,只有 GitLab 会使用 NFS 共享,因此很安全. GitLab 建议使用`no_root_squash`设置,因为我们需要自动管理文件权限. 如果没有该设置,则当 Omnibus 软件包尝试更改权限时,您可能会收到错误消息. 请注意,GitLab 和其他捆绑组件**不是**以`root`用户身份运行,而是以非特权用户身份运行. 对于`no_root_squash`的建议是允许 Omnibus 软件包根据需要设置文件的所有权和权限. 在`no_root_squash`选项不可用的某些情况下, `root`标志可以实现相同的结果. +* `sync`强制同步行为. 默认值是异步的,在某些情况下,如果在同步数据之前发生故障,则可能导致数据丢失. + +由于使用 LDAP 运行 Omnibus 的复杂性和不使用 LDAP 维护 ID 映射的复杂性,在大多数情况下,应启用数字 UID 和 GID(在某些情况下默认情况下处于禁用状态),以简化系统之间的权限管理: + +* [NetApp instructions](https://library.netapp.com/ecmdocs/ECMP1401220/html/GUID-24367A9F-E17B-4725-ADC1-02D86F56F78E.html) +* 对于非 NetApp 设备,请执行与[启用 NFSv4 idmapper](https://wiki.archlinux.org/index.php/NFS#Enabling_NFSv4_idmapping)相反的`idmapping`来禁用[NFSv4 idmapping](https://wiki.archlinux.org/index.php/NFS#Enabling_NFSv4_idmapping) + +### Disable NFS server delegation[](#disable-nfs-server-delegation "Permalink") + +我们建议所有 NFS 用户禁用 NFS 服务器委派功能. 这是为了避免[Linux 内核错误](https://bugzilla.redhat.com/show_bug.cgi?id=1552203) ,该[错误](https://bugzilla.redhat.com/show_bug.cgi?id=1552203)会由于[来自大量`TEST_STATEID` NFS 消息的过多网络流量](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52017)而导致 NFS 客户端急剧减速. + +要禁用 NFS 服务器委派,请执行以下操作: + +1. 在 NFS 服务器上,运行: + + ``` + echo 0 > /proc/sys/fs/leases-enable + sysctl -w fs.leases-enable=0 + ``` + +2. 重新启动 NFS 服务器进程. 例如,在 CentOS 上运行`service nfs restart` . + +#### Important notes[](#important-notes "Permalink") + +[此提交](https://github.com/torvalds/linux/commit/95da1b3a5aded124dd1bda1e3cdb876184813140)可能会在[较新的内核中](https://github.com/torvalds/linux/commit/95da1b3a5aded124dd1bda1e3cdb876184813140)修复内核错误. + +Red Hat Enterprise 7 于 2019 年 8 月 6 日[发布了内核更新](https://access.redhat.com/errata/RHSA-2019:2029) , [该更新](https://access.redhat.com/errata/RHSA-2019:2029)也可能已解决了该问题. + +如果您知道使用的是已修复的 Linux 内核版本,则可能不需要禁用 NFS 服务器委派. 也就是说,GitLab 仍然鼓励实例管理员保持 NFS 服务器委派禁用. + +### Improving NFS performance with GitLab[](#improving-nfs-performance-with-gitlab "Permalink") + +#### Improving NFS performance with Unicorn[](#improving-nfs-performance-with-unicorn "Permalink") + +**注意:**从 GitLab 12.1 开始,如果可以并且应该为每个存储使用 Rugged,它将自动检测到它. + +如果先前使用功能标记启用了 Rugged,则需要使用以下方法取消设置功能标记: + +``` +sudo gitlab-rake gitlab:features:unset_rugged +``` + +如果将 Rugged 功能标志显式设置为 true 或 false,则 GitLab 将使用显式设置的值. + +#### Improving NFS performance with Puma[](#improving-nfs-performance-with-puma "Permalink") + +**注意:**从 GitLab 12.7 开始,如果 Puma 线程数大于 1,则将禁用 Rugged 自动检测. + +如果要将 Rugged 与 Puma 一起使用,建议[将 Puma 线程数设置为 1](https://docs.gitlab.com/omnibus/settings/puma.html) . + +如果您想使用 Rugged 且 Puma 线程数大于 1,则可以使用[功能标志](../../development/gitaly.html#legacy-rugged-code)启用 Rugged + +如果将 Rugged 功能标志显式设置为 true 或 false,则 GitLab 将使用显式设置的值. + +### Known issues[](#known-issues "Permalink") + +#### Avoid using AWS’s Elastic File System (EFS)[](#avoid-using-awss-elastic-file-system-efs "Permalink") + +GitLab 强烈建议您不要使用 AWS Elastic File System(EFS). 我们的支持团队将无法协助解决与文件系统访问相关的性能问题. + +客户和用户报告说,AWS EFS 在 GitLab 的用例中表现不佳. 以串行化方式写入许多小文件的工作负载(例如`git` )不适合 EFS. 顶部带有 NFS 服务器的 EBS 的性能会好得多. + +如果确实选择使用 EFS,请避免在其中存储 GitLab 日志文件(例如`/var/log/gitlab` ),因为这也会影响性能. 我们建议将日志文件存储在本地卷上. + +有关其他人使用 EFS 的经验的更多详细信息,请参阅此[Commit Brooklyn 2019 视频](https://youtu.be/K6OS8WodRBQ?t=313) . + +#### Avoid using CephFS and GlusterFS[](#avoid-using-cephfs-and-glusterfs "Permalink") + +GitLab 强烈建议不要使用 CephFS 和 GlusterFS. 这些分布式文件系统不适用于 GitLab 的输入/输出访问模式,因为 Git 使用许多小文件,并且传播的访问时间和文件锁定时间会使 Git 活动非常缓慢. + +#### Avoid using PostgreSQL with NFS[](#avoid-using-postgresql-with-nfs "Permalink") + +GitLab 强烈建议不要跨 NFS 运行 PostgreSQL 数据库. GitLab 支持团队将无法协助解决与该配置有关的性能问题. + +此外,该配置在[PostgreSQL 文档中](https://s0www0postgresql0org.icopy.site/docs/current/creating-cluster.html)特别警告: + +> PostgreSQL does nothing special for NFS file systems, meaning it assumes NFS behaves exactly like locally-connected drives. If the client or server NFS implementation does not provide standard file system semantics, this can cause reliability problems. Specifically, delayed (asynchronous) writes to the NFS server can cause data corruption problems. + +有关受支持的数据库体系结构,请参阅有关[为 GitLab HA 配置数据库的](../postgresql/replication_and_failover.html)文档. + +## NFS Client mount options[](#nfs-client-mount-options "Permalink") + +这是添加到`/etc/fstab`的示例片段: + +``` + 10.1.0.1:/var/opt/gitlab/.ssh /var/opt/gitlab/.ssh nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 + 10.1.0.1:/var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/uploads nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 + 10.1.0.1:/var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-rails/shared nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 + 10.1.0.1:/var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/gitlab-ci/builds nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 + 10.1.0.1:/var/opt/gitlab/git-data /var/opt/gitlab/git-data nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 +``` + +请注意,您应该考虑使用几个选项: + +| Setting | Description | +| --- | --- | +| `vers=4.1` | 应该使用 NFS v4.1 代替 v4.0,因为 v4.0 中存在一个 Linux [NFS 客户端错误,](https://gitlab.com/gitlab-org/gitaly/-/issues/1339)由于过时的数据可能导致严重的问题. | +| `nofail` | 不要停止启动过程,等待此挂载可用 | +| `lookupcache=positive` | Tells the NFS client to honor `positive` cache results but invalidates any `negative` cache results. Negative cache results cause problems with Git. Specifically, a `git push` can fail to register uniformly across all NFS clients. The negative cache causes the clients to ‘remember’ that the files did not exist previously. | +| `hard` | 而不是`soft` . [进一步的细节](#soft-mount-option) . | + +### soft mount option[](#soft-mount-option "Permalink") + +我们建议您在安装选项中使用`hard` ,除非您出于特殊原因使用`soft` . + +在 GitLab.com,我们使用`soft` ,因为有些时候我们不得不 NFS 服务器重新启动和`soft`改进的可用性,但每个人的基础不同. 例如,如果您的 NFS 由带有冗余控制器的本地存储阵列提供,则无需担心 NFS 服务器的可用性. + +NFS 手册页指出: + +> 在某些情况下,"软"超时可能会导致无提示数据损坏 + +阅读[Linux 手册页](https://linux.die.net/man/5/nfs)以了解它们之间的区别,如果您确实使用`soft` ,请确保已采取步骤减轻风险. + +如果您遇到的问题可能是由于未发生对 NFS 服务器的磁盘写入而导致的,例如丢失了提交,请使用`hard`选项,因为(在手册页中): + +> 仅当客户端响应能力比数据完整性更重要时才使用 soft 选项 + +其他供应商也提出了类似的建议,包括[SAP](http://wiki.scn.sap.com/wiki/x/PARnFQ)和 NetApp 的[知识库](https://kb.netapp.com/Advice_and_Troubleshooting/Data_Storage_Software/ONTAP_OS/What_are_the_differences_between_hard_mount_and_soft_mount) ,他们强调说,如果 NFS 客户端驱动程序缓存数据,则`soft`意味着无法确定 GitLab 的写操作是否确实在磁盘上. + +使用`hard`选项设置的安装点可能无法正常运行,并且如果 NFS 服务器关闭,则`hard`会导致与安装点进行交互时挂起进程. 使用`SIGKILL` ( `kill -9` )处理挂起的进程. `intr`选项[在 2.6 内核中停止工作](https://access.redhat.com/solutions/157873) . + +## A single NFS mount[](#a-single-nfs-mount "Permalink") + +建议将所有 GitLab 数据目录嵌套在一个装载中,这样可以自动还原备份而无需手动移动现有数据. + +``` +mountpoint +└── gitlab-data + ├── builds + ├── git-data + ├── shared + └── uploads +``` + +为此,我们需要使用嵌套在安装点中的每个目录的路径来配置 Omnibus,如下所示: + +然后挂载`/gitlab-nfs`使用以下 Omnibus 配置将每个数据位置移动到子目录: + +``` +git_data_dirs({"default" => { "path" => "/gitlab-nfs/gitlab-data/git-data"} }) +gitlab_rails['uploads_directory'] = '/gitlab-nfs/gitlab-data/uploads' +gitlab_rails['shared_path'] = '/gitlab-nfs/gitlab-data/shared' +gitlab_ci['builds_directory'] = '/gitlab-nfs/gitlab-data/builds' +``` + +运行`sudo gitlab-ctl reconfigure`以开始使用中心位置. 请注意,如果您已有数据,则需要手动将其复制/同步到这些新位置,然后重新启动 GitLab. + +## Bind mounts[](#bind-mounts "Permalink") + +除了更改 Omnibus 中的配置外,绑定挂载还可用于将数据存储在 NFS 挂载上. + +绑定挂载提供一种仅指定一个 NFS 挂载,然后将默认的 GitLab 数据位置绑定到 NFS 挂载的方法. 首先定义您的单个 NFS 挂载点,就像通常在`/etc/fstab` . 假设您的 NFS 挂载点是`/gitlab-nfs` . 然后,在`/etc/fstab`添加以下绑定安装: + +``` +/gitlab-nfs/gitlab-data/git-data /var/opt/gitlab/git-data none bind 0 0 +/gitlab-nfs/gitlab-data/.ssh /var/opt/gitlab/.ssh none bind 0 0 +/gitlab-nfs/gitlab-data/uploads /var/opt/gitlab/gitlab-rails/uploads none bind 0 0 +/gitlab-nfs/gitlab-data/shared /var/opt/gitlab/gitlab-rails/shared none bind 0 0 +/gitlab-nfs/gitlab-data/builds /var/opt/gitlab/gitlab-ci/builds none bind 0 0 +``` + +使用绑定安装将需要手动确保数据目录为空,然后再尝试还原. 阅读有关[还原先决条件的](../../raketasks/backup_restore.html)更多信息. + +## Multiple NFS mounts[](#multiple-nfs-mounts "Permalink") + +使用默认的 Omnibus 配置时,您将需要在所有 GitLab 群集节点之间共享 4 个数据位置. 没有其他位置可以共享. 以下是需要共享的四个位置: + +| Location | Description | 默认配置 | +| --- | --- | --- | +| `/var/opt/gitlab/git-data` | Git 存储库数据. 这将占您数据的很大一部分 | `git_data_dirs({"default" => { "path" => "/var/opt/gitlab/git-data"} })` | +| `/var/opt/gitlab/gitlab-rails/uploads` | 用户上传的附件 | `gitlab_rails['uploads_directory'] = '/var/opt/gitlab/gitlab-rails/uploads'` | +| `/var/opt/gitlab/gitlab-rails/shared` | Build artifacts, GitLab Pages, LFS objects, temp files, etc. If you’re using LFS this may also account for a large portion of your data | `gitlab_rails['shared_path'] = '/var/opt/gitlab/gitlab-rails/shared'` | +| `/var/opt/gitlab/gitlab-ci/builds` | GitLab CI / CD 构建跟踪 | `gitlab_ci['builds_directory'] = '/var/opt/gitlab/gitlab-ci/builds'` | + +其他 GitLab 目录不应在节点之间共享. 它们包含特定于节点的文件和不需要共享的 GitLab 代码. 要将日志发送到中央位置,请考虑使用远程 syslog. Omnibus GitLab 软件包提供了[UDP 日志传送的](https://docs.gitlab.com/omnibus/settings/logs.html)配置. + +具有多个 NFS 挂载将需要手动确保数据目录为空,然后再尝试还原. 阅读有关[还原先决条件的](../../raketasks/backup_restore.html)更多信息. + +* * * + +阅读更多有关高可用性配置的信息: + +1. [Configure the database](../postgresql/replication_and_failover.html) +2. [Configure Redis](redis.html) +3. [Configure the GitLab application servers](gitlab.html) +4. [Configure the load balancers](load_balancer.html) \ No newline at end of file diff --git a/_book/docs/435.md b/_book/docs/435.md new file mode 100644 index 0000000000000000000000000000000000000000..a6c53aa3028a2a554d7ba54a5f45888fd33a05d2 --- /dev/null +++ b/_book/docs/435.md @@ -0,0 +1,176 @@ +# Working with the bundled PgBouncer service + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/pgbouncer.html](https://docs.gitlab.com/ee/administration/high_availability/pgbouncer.html) + +* [Operations](#operations) + * [Running PgBouncer as part of an HA GitLab installation](#running-pgbouncer-as-part-of-an-ha-gitlab-installation) + * [Running PgBouncer as part of a non-HA GitLab installation](#running-pgbouncer-as-part-of-a-non-ha-gitlab-installation) +* [Enable Monitoring](#enable-monitoring) + * [Interacting with PgBouncer](#interacting-with-pgbouncer) + * [Administrative console](#administrative-console) +* [Troubleshooting](#troubleshooting) + * [Message: `LOG: invalid CIDR mask in address`](#message-log--invalid-cidr-mask-in-address) + * [Message: `LOG: invalid IP mask "md5": Name or service not known`](#message-log--invalid-ip-mask-md5-name-or-service-not-known) + +# Working with the bundled PgBouncer service[](#working-with-the-bundled-pgbouncer-service-premium-only "Permalink") + +由于它的高可用性堆栈的一部分,GitLab Premium 包含的捆绑版本[PgBouncer](http://www.pgbouncer.org/)可以通过管理`/etc/gitlab/gitlab.rb` . PgBouncer 用于在故障转移方案中在服务器之间无缝迁移数据库连接. 此外,它可以用于非 HA 设置中以建立连接池,从而加快响​​应时间,同时减少资源使用. + +在高可用性设置中,建议为每个数据库节点分别运行一个 PgBouncer 节点,并使用一个内部负载均衡器(TCP)相应地为其服务. + +## Operations[](#operations "Permalink") + +### Running PgBouncer as part of an HA GitLab installation[](#running-pgbouncer-as-part-of-an-ha-gitlab-installation "Permalink") + +该内容已移至[新位置](../postgresql/replication_and_failover.html#configuring-the-pgbouncer-node) . + +### Running PgBouncer as part of a non-HA GitLab installation[](#running-pgbouncer-as-part-of-a-non-ha-gitlab-installation "Permalink") + +1. 使用命令`gitlab-ctl pg-password-md5 pgbouncer`生成 PGBOUNCER_USER_PASSWORD_HASH + +2. 使用命令`gitlab-ctl pg-password-md5 gitlab` . 稍后我们还需要输入纯文本 SQL_USER_PASSWORD + +3. 在数据库节点上,确保在`/etc/gitlab/gitlab.rb`设置了以下`/etc/gitlab/gitlab.rb` + + ``` + postgresql['pgbouncer_user_password'] = 'PGBOUNCER_USER_PASSWORD_HASH' + postgresql['sql_user_password'] = 'SQL_USER_PASSWORD_HASH' + postgresql['listen_address'] = 'XX.XX.XX.Y' # Where XX.XX.XX.Y is the ip address on the node postgresql should listen on + postgresql['md5_auth_cidr_addresses'] = %w(AA.AA.AA.B/32) # Where AA.AA.AA.B is the IP address of the pgbouncer node + ``` + +4. Run `gitlab-ctl reconfigure` + + **注意:**如果数据库已经在运行,则需要在重新配置后通过运行`gitlab-ctl restart postgresql`来重新启动数据库. + +5. 在运行 PgBouncer 的节点上,确保在`/etc/gitlab/gitlab.rb`设置了以下`/etc/gitlab/gitlab.rb` + + ``` + pgbouncer['enable'] = true + pgbouncer['databases'] = { + gitlabhq_production: { + host: 'DATABASE_HOST', + user: 'pgbouncer', + password: 'PGBOUNCER_USER_PASSWORD_HASH' + } + } + ``` + +6. Run `gitlab-ctl reconfigure` + +7. 在运行 Puma 的节点上,确保在`/etc/gitlab/gitlab.rb`设置了以下`/etc/gitlab/gitlab.rb` + + ``` + gitlab_rails['db_host'] = 'PGBOUNCER_HOST' + gitlab_rails['db_port'] = '6432' + gitlab_rails['db_password'] = 'SQL_USER_PASSWORD' + ``` + +8. Run `gitlab-ctl reconfigure` + +9. 此时,您的实例应通过 PgBouncer 连接到数据库. 如果遇到问题,请参阅" [故障排除"](#troubleshooting)部分 + +## Enable Monitoring[](#enable-monitoring "Permalink") + +在 GitLab 12.0 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) . + +If you enable Monitoring, it must be enabled on **all** PgBouncer servers. + +1. 创建/编辑`/etc/gitlab/gitlab.rb`并添加以下配置: + + ``` + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Replace placeholders + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses of the Consul server nodes + consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + pgbouncer_exporter['listen_address'] = '0.0.0.0:9188' + ``` + +2. 运行`sudo gitlab-ctl reconfigure`来编译配置. + +### Interacting with PgBouncer[](#interacting-with-pgbouncer "Permalink") + +#### Administrative console[](#administrative-console "Permalink") + +作为 Omnibus GitLab 的一部分,我们提供了一个`gitlab-ctl pgb-console`命令,以自动连接到 PgBouncer 管理控制台. 请参阅[PgBouncer 文档](https://www.pgbouncer.org/usage.html#admin-console)以获取有关如何与控制台进行交互的详细说明. + +要开始会话,请运行 + +``` +# gitlab-ctl pgb-console +Password for user pgbouncer: +psql (11.7, server 1.7.2/bouncer) +Type "help" for help. + +pgbouncer=# +``` + +将提示您输入的密码是 PGBOUNCER_USER_PASSWORD + +要获取有关实例的一些基本信息,请运行 + +``` +pgbouncer=# show databases; show clients; show servers; + name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections +---------------------+-----------+------+---------------------+------------+-----------+--------------+-----------+-----------------+--------------------- + gitlabhq_production | 127.0.0.1 | 5432 | gitlabhq_production | | 100 | 5 | | 0 | 1 + pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0 +(2 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link +| remote_pid | tls +------+-----------+---------------------+--------+-----------+-------+------------+------------+---------------------+---------------------+-----------+------ ++------------+----- + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44590 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x12444c0 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44592 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x12447c0 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44594 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x1244940 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44706 | 127.0.0.1 | 6432 | 2018-04-24 22:14:22 | 2018-04-24 22:16:31 | 0x1244ac0 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44708 | 127.0.0.1 | 6432 | 2018-04-24 22:14:22 | 2018-04-24 22:15:15 | 0x1244c40 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44794 | 127.0.0.1 | 6432 | 2018-04-24 22:15:15 | 2018-04-24 22:15:15 | 0x1244dc0 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44798 | 127.0.0.1 | 6432 | 2018-04-24 22:15:15 | 2018-04-24 22:16:31 | 0x1244f40 | +| 0 | + C | pgbouncer | pgbouncer | active | 127.0.0.1 | 44660 | 127.0.0.1 | 6432 | 2018-04-24 22:13:51 | 2018-04-24 22:17:12 | 0x1244640 | +| 0 | +(8 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | rem +ote_pid | tls +------+--------+---------------------+-------+-----------+------+------------+------------+---------------------+---------------------+-----------+------+---- +--------+----- + S | gitlab | gitlabhq_production | idle | 127.0.0.1 | 5432 | 127.0.0.1 | 35646 | 2018-04-24 22:15:15 | 2018-04-24 22:17:10 | 0x124dca0 | | + 19980 | +(1 row) +``` + +## Troubleshooting[](#troubleshooting "Permalink") + +如果您遇到通过 PgBouncer 连接的任何问题,则首先检查的始终是日志: + +``` +# gitlab-ctl tail pgbouncer +``` + +另外,您可以在[管理控制台中](#administrative-console)检查`show databases`的输出. 在输出中,您期望在`gitlabhq_production`数据库的`host`字段中看到值. 此外, `current_connections`应该大于 1. + +### Message: `LOG: invalid CIDR mask in address`[](#message-log--invalid-cidr-mask-in-address "Permalink") + +请参阅[Geo 文档中](../geo/replication/troubleshooting.html#message-log--invalid-cidr-mask-in-address)建议的修复程序. + +### Message: `LOG: invalid IP mask "md5": Name or service not known`[](#message-log--invalid-ip-mask-md5-name-or-service-not-known "Permalink") + +请参阅[Geo 文档中](../geo/replication/troubleshooting.html#message-log--invalid-ip-mask-md5-name-or-service-not-known)建议的修复程序. \ No newline at end of file diff --git a/_book/docs/436.md b/_book/docs/436.md new file mode 100644 index 0000000000000000000000000000000000000000..6402a61010ad48715eaf18e7f706b5d5c5883eea --- /dev/null +++ b/_book/docs/436.md @@ -0,0 +1,33 @@ +# Configuring Redis for scaling + +> 原文:[https://docs.gitlab.com/ee/administration/redis/](https://docs.gitlab.com/ee/administration/redis/) + +* [Redis replication and failover using Omnibus GitLab](#redis-replication-and-failover-using-omnibus-gitlab) +* [Redis replication and failover using the non-bundled Redis](#redis-replication-and-failover-using-the-non-bundled-redis) +* [Standalone Redis using Omnibus GitLab](#standalone-redis-using-omnibus-gitlab) + +# Configuring Redis for scaling[](#configuring-redis-for-scaling "Permalink") + +根据您的基础架构设置以及如何安装 GitLab,有多种方法来配置 Redis. + +您可以选择自己安装和管理 Redis 和 Sentinel,使用托管的云解决方案,也可以使用 Omnibus GitLab 软件包随附的软件包,因此您只需要关注配置. 选择一个适合您的需求. + +## Redis replication and failover using Omnibus GitLab[](#redis-replication-and-failover-using-omnibus-gitlab "Permalink") + +此设置适用于使用[Omnibus GitLab **企业版** (EE)软件包](https://about.gitlab.com/install/?version=ee)安装 GitLab 的情况. + +Redis 和 Sentinel 都捆绑在软件包中,因此您可以使用它来设置整个 Redis 基础架构(主要,副本和哨兵). + +[> Read how to set up Redis replication and failover using Omnibus GitLab](replication_and_failover.html) + +## Redis replication and failover using the non-bundled Redis[](#redis-replication-and-failover-using-the-non-bundled-redis "Permalink") + +此设置适用于使用[Omnibus GitLab 软件包](https://about.gitlab.com/install/) (CE 或 EE)安装 GitLab 或[从源代码](../../install/installation.html)安装 GitLab 的情况,但您想使用自己的外部 Redis 和哨兵服务器. + +[> Read how to set up Redis replication and failover using the non-bundled Redis](replication_and_failover_external.html) + +## Standalone Redis using Omnibus GitLab[](#standalone-redis-using-omnibus-gitlab "Permalink") + +此设置适用于您安装了[Omnibus GitLab **社区版** (CE)软件包](https://about.gitlab.com/install/?version=ce)以使用捆绑的 Redis 的情况,因此您可以在仅启用 Redis 服务的情况下使用该软件包. + +[> Read how to set up a standalone Redis instance using Omnibus GitLab](standalone.html) \ No newline at end of file diff --git a/_book/docs/437.md b/_book/docs/437.md new file mode 100644 index 0000000000000000000000000000000000000000..6f4b2dbb1f1c560d1d2cd2d9d50b9fc11d547ec5 --- /dev/null +++ b/_book/docs/437.md @@ -0,0 +1,188 @@ +# Configuring Sidekiq + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/sidekiq.html](https://docs.gitlab.com/ee/administration/high_availability/sidekiq.html) + +* [Example configuration](#example-configuration) +* [Further reading](#further-reading) + +# Configuring Sidekiq[](#configuring-sidekiq "Permalink") + +本节讨论如何配置外部 Sidekiq 实例. + +Sidekiq 需要连接到 Redis,PostgreSQL 和 Gitaly 实例. 要配置 Sidekiq 节点: + +1. SSH 到 Sidekiq 服务器. + +2. 从 GitLab 下载页面使用步骤 1 和 2 [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. **不要完成下载页面上的任何其他步骤.** + +3. 使用编辑器打开`/etc/gitlab/gitlab.rb` . + +4. 生成 Sidekiq 配置: + + ``` + sidekiq['listen_address'] = "10.10.1.48" + + ## Optional: Enable extra Sidekiq processes + sidekiq_cluster['enable'] = true + sidekiq_cluster['enable'] = true + "elastic_indexer" + ] + ``` + +5. 设置 Sidekiq 与 Redis 的连接: + + ``` + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + ## The same password for Redis authentication you set up for the master node. + redis['master_password'] = 'YOUR_PASSOWORD' + + ## A list of sentinels with `host` and `port` + gitlab_rails['redis_sentinels'] = [ + {'host' => '10.10.1.34', 'port' => 26379}, + {'host' => '10.10.1.35', 'port' => 26379}, + {'host' => '10.10.1.36', 'port' => 26379}, + ] + ``` + +6. 设置 Sidekiq 与 Gitaly 的连接: + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly:8075' }, + }) + gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + ``` + +7. 设置 Sidekiq 与 PostgreSQL 的连接: + + ``` + gitlab_rails['db_host'] = '10.10.1.30' + gitlab_rails['db_password'] = 'YOUR_PASSOWORD' + gitlab_rails['db_port'] = '5432' + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['auto_migrate'] = false + ``` + + 请记住将 Sidekiq 节点添加到 PostgreSQL 的受信任地址中: + + ``` + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32 10.10.1.31/32 10.10.1.32/32 10.10.1.33/32 10.10.1.38/32) + ``` + +8. 禁用其他服务: + + ``` + nginx['enable'] = false + grafana['enable'] = false + prometheus['enable'] = false + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_monitor['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + puma['enable'] = false + gitlab_exporter['enable'] = false + ``` + +9. Run `gitlab-ctl reconfigure`. + +**注意:**发生更新并执行数据库迁移后,您将需要重新启动 Sidekiq 节点. + +## Example configuration[](#example-configuration "Permalink") + +这是结尾的`/etc/gitlab/gitlab.rb`样子: + +``` +######################################## +##### Services Disabled ### +######################################## + +nginx['enable'] = false +grafana['enable'] = false +prometheus['enable'] = false +gitlab_rails['auto_migrate'] = false +alertmanager['enable'] = false +gitaly['enable'] = false +gitlab_monitor['enable'] = false +gitlab_workhorse['enable'] = false +nginx['enable'] = false +postgres_exporter['enable'] = false +postgresql['enable'] = false +redis['enable'] = false +redis_exporter['enable'] = false +puma['enable'] = false +gitlab_exporter['enable'] = false + +######################################## +#### Redis ### +######################################## + +## Must be the same in every sentinel node +redis['master_name'] = 'gitlab-redis' + +## The same password for Redis authentication you set up for the master node. +redis['master_password'] = 'YOUR_PASSOWORD' + +## A list of sentinels with `host` and `port` +gitlab_rails['redis_sentinels'] = [ + {'host' => '10.10.1.34', 'port' => 26379}, + {'host' => '10.10.1.35', 'port' => 26379}, + {'host' => '10.10.1.36', 'port' => 26379}, + ] + +####################################### +### Gitaly ### +####################################### + +git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly:8075' }, +}) +gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + +####################################### +### Postgres ### +####################################### +gitlab_rails['db_host'] = '10.10.1.30' +gitlab_rails['db_password'] = 'YOUR_PASSOWORD' +gitlab_rails['db_port'] = '5432' +gitlab_rails['db_adapter'] = 'postgresql' +gitlab_rails['db_encoding'] = 'unicode' +gitlab_rails['auto_migrate'] = false + +####################################### +### Sidekiq configuration ### +####################################### +sidekiq['listen_address'] = "10.10.1.48" + +####################################### +### Monitoring configuration ### +####################################### +consul['enable'] = true +consul['monitoring_service_discovery'] = true + +consul['configuration'] = { + bind_addr: '10.10.1.48', + retry_join: %w(10.10.1.34 10.10.1.35 10.10.1.36) +} + +# Set the network addresses that the exporters will listen on +node_exporter['listen_address'] = '10.10.1.48:9100' + +# Rails Status for prometheus +gitlab_rails['monitoring_whitelist'] = ['10.10.1.42', '127.0.0.1'] +``` + +## Further reading[](#further-reading "Permalink") + +相关的 Sidekiq 配置: + +1. [Extra Sidekiq processes](../operations/extra_sidekiq_processes.html) +2. [Using the GitLab-Sidekiq chart](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/) \ No newline at end of file diff --git a/_book/docs/438.md b/_book/docs/438.md new file mode 100644 index 0000000000000000000000000000000000000000..6190ae279d6443debe4f3c2511eb1a5e6536121f --- /dev/null +++ b/_book/docs/438.md @@ -0,0 +1,120 @@ +# Admin Area settings + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/settings/](https://docs.gitlab.com/ee/user/admin_area/settings/) + +* [General](#general) +* [Integrations](#integrations) +* [Repository](#repository) +* [Templates](#templates-premium-only) +* [CI/CD](#cicd) +* [Reporting](#reporting) +* [Metrics and profiling](#metrics-and-profiling) +* [Network](#network) +* [Geo](#geo) +* [Preferences](#preferences) + +# Admin Area settings[](#admin-area-settings-core-only "Permalink") + +作为 GitLab 自我管理实例的管理员,您可以管理部署的行为. 为此,请选择 **管理区域>设置** . + +在 GitLab.com 上无法访问管理区域,并且只能由 GitLab.com 管理员更改设置. 有关 GitLab.com 实例上的所有当前设置和限制,请参阅[GitLab.com 设置](../../gitlab_com/index.html)文档. + +## General[](#general "Permalink") + +通过导航到来访问管理区域设置的默认页面 **管理区域>设置>常规** : + +| Option | Description | +| --- | --- | +| [Visibility and access controls](visibility_and_access_controls.html) | 设置默认值并限制可见性级别. 配置导入源和 Git 访问协议. | +| [Account and limit](account_and_limit_settings.html) | 设置项目和最大大小限制,会话持续时间,用户选项,并检查名称空间计划的功能可用性. | +| [Diff limits](../diff_limits.html) | 差异含量限制. | +| [Sign-up restrictions](sign_up_restrictions.html) | 配置用户创建新帐户的方式. | +| [Sign in restrictions](sign_in_restrictions.html) | 设置用户登录要求. 启用强制性两因素身份验证. | +| [Terms of Service and Privacy Policy](terms.html) | 包括所有用户必须接受的服务条款协议和隐私政策. | +| [External Authentication](external_authorization.html#configuration) | 外部分类政策授权 | +| [Web terminal](../../../administration/integration/terminal.html#limiting-websocket-connection-time) | 设置 Web 终端的最大会话时间. | +| [Web IDE](../../project/web_ide/index.html#enabling-live-preview) | 管理 Web IDE 功能. | + +## Integrations[](#integrations "Permalink") + +| Option | Description | +| --- | --- | +| [Elasticsearch](../../../integration/elasticsearch.html#enabling-elasticsearch) | Elasticsearch 集成. Elasticsearch AWS IAM. | +| [PlantUML](../../../administration/integration/plantuml.html#gitlab) | 允许在 AsciiDoc 文档中呈现 PlantUML 图. | +| [Slack application](../../../user/project/integrations/gitlab_slack_application.html#configuration) | Slack 集成使您可以通过聊天窗口中的斜杠命令与 GitLab 进行交互. 此选项仅在 GitLab.com 上可用,尽管[将来](https://gitlab.com/gitlab-org/gitlab/-/issues/28164)可能会[用于自我管理的实例](https://gitlab.com/gitlab-org/gitlab/-/issues/28164) . | +| [Third party offers](third_party_offers.html) | 控制第三方报价的显示. | +| [Snowplow](../../../development/telemetry/snowplow.html) | 配置 Snowplow 集成. | +| [Google GKE](../../project/clusters/add_gke_clusters.html) | Google GKE 集成使您可以从 GitLab 配置 GKE 集群. | +| [Amazon EKS](../../project/clusters/add_eks_clusters.html) | Amazon EKS 集成允许您从 GitLab 预置 EKS 集群. | + +## Repository[](#repository "Permalink") + +| Option | Description | +| --- | --- | +| [Repository’s custom initial branch name](../../project/repository/branches/index.html#custom-initial-branch-name-core-only) | 为您实例中创建的所有新存储库设置一个自定义分支名称而不是 master. | +| [Repository mirror](visibility_and_access_controls.html#allow-mirrors-to-be-set-up-for-projects) | 配置存储库镜像. | +| [Repository storage](../../../administration/repository_storage_types.html) | 配置存储路径设置. | +| 仓库维护 | ( [存储库检查](../../../administration/repository_checks.html)和[内务处理](../../../administration/housekeeping.html) ). 在存储库上配置自动 Git 检查和内务处理. | +| [Repository static objects](../../../administration/static_objects_external_storage.html) | 从外部存储(例如 CDN)提供存储库静态对象(例如,归档文件,blob 等). | + +## Templates[](#templates-premium-only "Permalink") + +| Option | Description | +| --- | --- | +| [Templates](instance_template_repository.html#configuration) | 设置实例范围的模板存储库. | +| [Custom project templates](../custom_project_templates.html) | 选择自定义项目模板源组. | + +## CI/CD[](#cicd "Permalink") + +| Option | Description | +| --- | --- | +| [Continuous Integration and Deployment](continuous_integration.html) | Auto DevOps,跑步者和工作工件. | +| [Required pipeline configuration](continuous_integration.html#required-pipeline-configuration-premium-only) | 设置实例范围的自动包含[管道配置](../../../ci/yaml/README.html) . 该管道配置将在项目自己的配置之后运行. | +| [Package Registry](continuous_integration.html#package-registry-configuration-premium-only) | 与使用 GitLab 的 Package Registry 的使用和体验有关的设置. 请注意,启用其中一些设置会[涉及风险](./../../packages/container_registry/index.html#use-with-external-container-registries) . | + +## Reporting[](#reporting "Permalink") + +| Option | Description | +| --- | --- | +| [Spam and Anti-bot Protection](../../../integration/recaptcha.html) | 启用 reCAPTCHA 或 Akismet 并设置 IP 限制. 对于 reCAPTCHA,我们目前仅支持[v2](https://developers.google.com/recaptcha/docs/versions) . | +| [Abuse reports](../abuse_reports.html) | 为滥用情况报告设置通知电子邮件. | + +## Metrics and profiling[](#metrics-and-profiling "Permalink") + +| Option | Description | +| --- | --- | +| [Metrics - Prometheus](../../../administration/monitoring/prometheus/gitlab_metrics.html) | 启用和配置 Prometheus 指标. | +| [Metrics - Grafana](../../../administration/monitoring/performance/grafana_configuration.html#integration-with-gitlab-ui) | 启用并配置 Grafana. | +| [Profiling - Performance bar](../../../administration/monitoring/performance/performance_bar.html#enable-the-performance-bar-via-the-admin-panel) | 启用对给定组的性能栏的访问. | +| [Self monitoring](../../../administration/monitoring/gitlab_self_monitoring_project/index.html#creating-the-self-monitoring-project) | Enable or disable instance self monitoring. | +| [Usage statistics](usage_statistics.html) | 启用或禁用版本检查和用法 ping. | +| [Pseudonymizer data collection](../../../administration/pseudonymizer.html) | 启用或禁用 Pseudonymizer 数据收集. | + +## Network[](#network "Permalink") + +| Option | Description | +| --- | --- | +| 性能优化 | [写入" authorized_keys"文件,](../../../administration/operations/fast_ssh_key_lookup.html#setting-up-fast-lookup-via-gitlab-shell)并执行[Push 事件活动限制和批量 push 事件](push_event_activities_limit.html) . 影响 GitLab 性能的各种设置. | +| [User and IP rate limits](user_and_ip_rate_limits.html) | 配置 Web 和 API 请求的限制. | +| [Outbound requests](../../../security/webhooks.html) | 允许从挂钩和服务到本地网络的请求. | +| [Protected Paths](protected_paths.html) | 配置路径以受机架攻击保护. | +| [Incident Management](../../incident_management/index.html) Limits | 配置可以发送到项目的入站警报数量的限制. | + +## Geo[](#geo "Permalink") + +| Option | Description | +| --- | --- | +| Geo | Geo 允许您将 GitLab 实例复制到其他地理位置. 重定向到 **管理区>** **地理位置>** **设置** ,并且将不再提供 **管理区>** **设置>** [GitLab 13.0 中的](https://gitlab.com/gitlab-org/gitlab/-/issues/36896) **Geo** . | + +## Preferences[](#preferences "Permalink") + +| Option | Description | +| --- | --- | +| [Email](email.html) | 各种电子邮件设置. | +| [Help page](../../../customization/help_message.html) | 帮助页面文本和支持页面 URL. | +| [Pages](../../../administration/pages/index.html#custom-domain-verification) | 静态网站的大小和域设置 | +| [Real-time features](../../../administration/polling.html) | 更改此值可影响 GitLab UI 轮询更新的频率. | +| [Gitaly timeouts](gitaly_timeouts.html) | 配置 Gitaly 超时. | +| Localization | [Default first day of the week](../../profile/preferences.html) and [Time tracking](../../project/time_tracking.html#limit-displayed-units-to-hours-core-only). | + +**注意:**您可以在**管理区域>设置>首选项**的**本地化**部分中更改整个 GitLab 实例的[默认一周的第一天](../../profile/preferences.html) . \ No newline at end of file diff --git a/_book/docs/439.md b/_book/docs/439.md new file mode 100644 index 0000000000000000000000000000000000000000..bd19b706ee07b8849faff9affab90e5bd74479bd --- /dev/null +++ b/_book/docs/439.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/customization/](https://docs.gitlab.com/ee/customization/) \ No newline at end of file diff --git a/_book/docs/440.md b/_book/docs/440.md new file mode 100644 index 0000000000000000000000000000000000000000..8c27a7c0555f93822b0111dd75e91e4432d3bea7 --- /dev/null +++ b/_book/docs/440.md @@ -0,0 +1,164 @@ +# Continuous Integration and Deployment Admin settings + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html) + +* [Auto DevOps](#auto-devops-core-only) +* [Maximum artifacts size](#maximum-artifacts-size-core-only) +* [Default artifacts expiration](#default-artifacts-expiration-core-only) +* [Shared Runners pipeline minutes quota](#shared-runners-pipeline-minutes-quota-starter-only) +* [Archive jobs](#archive-jobs-core-only) +* [Default CI configuration path](#default-ci-configuration-path) +* [Required pipeline configuration](#required-pipeline-configuration-premium-only) +* [Package Registry configuration](#package-registry-configuration-premium-only) + +# Continuous Integration and Deployment Admin settings[](#continuous-integration-and-deployment-admin-settings-core-only "Permalink") + +在此区域中,您将找到 Auto DevOps,Runners 和作业工件的设置. 您可以在**管理区域>设置> CI / CD 中**找到它. + +[![Admin Area settings button](img/7355fc1627be101cc5ed59387d36b6a3.png)](../img/admin_area_settings_button.png) + +## Auto DevOps[](#auto-devops-core-only "Permalink") + +要为所有项目启用(或禁用) [Auto DevOps](../../../topics/autodevops/index.html) : + +1. 转到**管理区域>设置> CI / CD** . +2. 选中(或取消选中以禁用) **所有项目的默认为 Auto DevOps 管道**的框. +3. (可选)设置将用于 Auto Deploy 和 Auto Review Apps 的[Auto DevOps 基本域](../../../topics/autodevops/index.html#auto-devops-base-domain) . +4. 点击**保存更改**以使更改生效. + +从现在开始,每个不带`.gitlab-ci.yml`现有项目和新创建的项目都将使用 Auto DevOps 管道. + +如果要为特定项目禁用它,可以在[其设置中](../../../topics/autodevops/index.html#enablingdisabling-auto-devops)禁用它. + +## Maximum artifacts size[](#maximum-artifacts-size-core-only "Permalink") + +可以将[作业工件](../../../administration/job_artifacts.html)的最大大小设置为: + +* 实例级别. +* [从 GitLab 12.4 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/21688) ,为项目和组级别. + +值是: + +* 以*MB*为单位,每个作业的默认值为 100MB. +* 在 GitLab.com 上[设置为 1G](../../gitlab_com/index.html#gitlab-cicd) . + +要在以下位置进行更改: + +* 实例级别: + + 1. Go to **管理区域>设置> CI / CD**. + 2. 更改最大工件大小的值(以 MB 为单位). + 3. 单击**保存更改**以使更改生效. +* [组级别](../../group/index.html#group-settings) (这将覆盖实例设置): + + 1. 转到组的**设置> CI / CD>常规管道** . + 2. 更改**最大工件大小**的值**(以 MB 为单位)** . + 3. 单击**保存更改**以使更改生效. +* [项目级别](../../../ci/pipelines/settings.html) (这将覆盖实例和组设置): + + 1. 转到项目的**设置> CI / CD>常规管道** . + 2. 更改**最大工件大小**的值**(以 MB 为单位)** . + 3. 单击**保存更改**以使更改生效. + +**注意:**所有级别的设置仅对 GitLab 管理员可用. + +## Default artifacts expiration[](#default-artifacts-expiration-core-only "Permalink") + +可以在 GitLab 实例的"管理区域"中设置[作业工件](../../../administration/job_artifacts.html)的默认过期时间. 持续时间的语法在[`artifacts:expire_in`](../../../ci/yaml/README.html#artifactsexpire_in)描述,缺省值为`30 days` . + +1. 转到**管理区域>设置> CI / CD** . +2. 更改默认到期时间的值. +3. 单击**保存更改**以使更改生效. + +此设置是[`.gitlab-ci.yml`](../../../ci/yaml/README.html#artifactsexpire_in)每个作业设置的,可以在[`.gitlab-ci.yml`](../../../ci/yaml/README.html#artifactsexpire_in)覆盖. 要禁用到期时间,请将其设置为`0` . 默认单位是秒. + +**注意:**对此设置的任何更改将仅适用于新工件. 更改此设置之前创建的工件的过期时间将不会更新. 管理员可能需要手动搜索并终止先前创建的工件,如[故障排除文档中所述](../../../administration/troubleshooting/gitlab_rails_cheat_sheet.html#remove-artifacts-more-than-a-week-old) . + +## Shared Runners pipeline minutes quota[](#shared-runners-pipeline-minutes-quota-starter-only "Permalink") + +在 GitLab Starter 8.16 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1078) . + +如果已为 GitLab 实例启用共享运行程序,则可以通过设置组每月可以在共享运行程序上使用的最大管道分钟数来限制其使用. 将此设置为`0` (默认值)将授予无限制的管道分钟数. 尽管构建限制以分钟存储,但计数以秒为单位. 使用情况会在每个月的第一天重置. 在 GitLab.com 上,配额是根据您的[订阅计划](https://about.gitlab.com/pricing/#gitlab-com)计算的. + +要更改管道分钟配额: + +1. 转到**管理区域>设置> CI / CD** . +2. Expand **持续集成和部署**. +3. 在" **管道分钟数"配额**框中,输入最大分钟数. +4. 单击**保存更改**以使更改生效. + +* * * + +尽管"管理区域"中的设置具有全局作用,但作为管理员,您也可以更改每个组的管道分钟配额以覆盖全局值. + +1. 导航到" **管理区域">"概述">"组",**然后单击您要更改管道分钟配额的组的" **编辑"**按钮. +2. 在" **管道分钟配额"**框中,输入最大分钟数. +3. 单击**保存更改**以使更改生效. + +保存后,您可以在组管理员视图中查看构建配额. 如果启用了共享运行器,也可以在项目管理视图中查看配额. + +[![Project admin information](img/a33f8dce89b50020e90de33ed9a1e78e.png)](img/admin_project_quota_view.png) + +您可以在组页面设置列表可用的" **使用配额"**页面中查看该组所有项目的管道分钟配额的概述. + +[![Group pipelines quota](img/a9b252d8a3c25b1c5166799c2233c569.png)](img/group_pipelines_quota.png) + +## Archive jobs[](#archive-jobs-core-only "Permalink") + +归档作业通过删除作业的某些功能(运行作业所需的元数据)来减少系统上的 CI / CD 占用空间,但保留迹线和工件以供审核时很有用. + +设置作业将被视为过期和过期的持续时间: + +1. 转到**管理区域>设置> CI / CD** . +2. 展开**持续集成和部署**部分. +3. 设置**存档作业**的值. +4. 点击**保存更改**以使更改生效. + +一旦超过该时间,作业将被存档,并且不再能够重试. 将其设为空以永不过期作业. 它必须不少于 1 天,例如: `15 days` , `1 month` , `2 years` . + +截至 2020 年 6 月 22 日,该[值](../../gitlab_com/index.html#gitlab-cicd)在 GitLab.com 上[设置](../../gitlab_com/index.html#gitlab-cicd)为 3 个月. 在此日期之前创建的作业将在 2020 年 9 月 22 日之后存档. + +## Default CI configuration path[](#default-ci-configuration-path "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18073) . + +可以在您的 GitLab 实例的"管理"区域中设置新项目的默认 CI 配置文件路径(如果未设置, `.gitlab-ci.yml` ): + +1. 转到**管理区域>设置> CI / CD** . +2. 在**默认 CI 配置路径**字段中输入新路径. +3. 点击**保存更改**以使更改生效. + +也可以[为特定项目](../../../ci/pipelines/settings.html#custom-ci-configuration-path)指定[自定义 CI 配置路径](../../../ci/pipelines/settings.html#custom-ci-configuration-path) . + +## Required pipeline configuration[](#required-pipeline-configuration-premium-only "Permalink") + +**警告:**此功能正在重新评估,以支持其他[合规性解决方案](https://gitlab.com/gitlab-org/gitlab/-/issues/34830) . 我们建议尚未实施此功能的用户等待新解决方案. + +GitLab 管理员可以强制管道配置在每个管道上运行. + +该配置适用于 GitLab 实例的所有管道,其来源为: + +* The [instance template repository](instance_template_repository.html). +* GitLab 提供的配置. + +设置所需的管道配置: + +1. 转到**管理区域>设置> CI / CD** . +2. 展开" **所需管道配置"**部分. +3. 从提供的下拉列表中选择所需的配置. +4. Click **保存更改**. + +[![Required pipeline](img/ad8ac82c77beb415e901040df8d93b17.png)](img/admin_required_pipeline.png) + +## Package Registry configuration[](#package-registry-configuration-premium-only "Permalink") + +GitLab 管理员可以禁用将 NPM 请求转发到[npmjs.com](https://s0www0npmjs0com.icopy.site/) . + +To disable it: + +1. 转到**管理区域>设置> CI / CD** . +2. 展开" **程序包注册表"**部分. +3. Uncheck **启用将 NPM 软件包请求转发到 npmjs.org**. +4. Click **保存更改**. + +[![NPM package requests forwarding](img/8e301ace1928e93f6138075596994c18.png)](img/admin_package_registry_npm_package_requests_forward.png) \ No newline at end of file diff --git a/_book/docs/441.md b/_book/docs/441.md new file mode 100644 index 0000000000000000000000000000000000000000..6d00ad8dff9cb846796e2b250a1e33cddf2f1052 --- /dev/null +++ b/_book/docs/441.md @@ -0,0 +1,31 @@ +# Custom instance-level project templates + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/custom_project_templates.html](https://docs.gitlab.com/ee/user/admin_area/custom_project_templates.html) + +* [Configuring](#configuring) + +# Custom instance-level project templates[](#custom-instance-level-project-templates-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6860) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2. + +GitLab 管理员可以配置所有自定义项目模板的来源组. + +如果用户有权访问组命名空间下的每个项目,则它们将对用户可用. 例如: + +* 组中的公共项目将对每个登录用户可用. +* 仅当用户是项目成员时,私有项目才可用. + +复制到每个新项目的存储库和数据库信息与使用[GitLab 的项目导入/导出导出](../project/settings/import_export.html)的数据相同. + +**注意:**要在组级别设置项目模板,请参阅[自定义组级别项目模板](../group/custom_project_templates.html) . + +## Configuring[](#configuring "Permalink") + +GitLab 管理员可以通过以下方式配置一个 GitLab 组作为整个 GitLab 实例的模板源: + +1. 导航到**管理区域>设置>模板** . +2. Expanding **自定义项目模板**. +3. 选择要使用的组. +4. Pressing **保存更改**. + +**注意:** **不**支持模板组子组下的项目. \ No newline at end of file diff --git a/_book/docs/442.md b/_book/docs/442.md new file mode 100644 index 0000000000000000000000000000000000000000..5096c54f1091584f603b92e887bfa962af25ae8c --- /dev/null +++ b/_book/docs/442.md @@ -0,0 +1,24 @@ +# Diff limits administration + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/diff_limits.html](https://docs.gitlab.com/ee/user/admin_area/diff_limits.html) + +* [Maximum diff patch size](#maximum-diff-patch-size) + +# Diff limits administration[](#diff-limits-administration-core-only "Permalink") + +您可以设置差异文件(补丁)显示的最大大小. + +有关差异文件的详细信息,请[查看文件之间的更改](../project/merge_requests/reviewing_and_managing_merge_requests.html#view-changes-between-file-versions) . + +## Maximum diff patch size[](#maximum-diff-patch-size "Permalink") + +超过此值的差异文件将显示为"太大",并且无法扩展. 将显示到斑点视图的链接,而不是展开视图. + +大于此大小的 10%的修补程序将自动折叠,并且将显示扩展差异的链接. + +**注意:**合并请求和分支比较视图将受到影响.**警告:**此设置是实验性的. 增加的最大值将增加实例的资源消耗. 调整最大值时请记住这一点. + +1. 转到**管理区域>设置>常规** . +2. Expand **差异限制**. +3. 输入**最大差异补丁大小**的值,以字节为单位. +4. 点击**保存更改** . \ No newline at end of file diff --git a/_book/docs/443.md b/_book/docs/443.md new file mode 100644 index 0000000000000000000000000000000000000000..5d16b0e9f62716d943a312b88d3c1309154830a9 --- /dev/null +++ b/_book/docs/443.md @@ -0,0 +1,41 @@ +# Email + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/settings/email.html](https://docs.gitlab.com/ee/user/admin_area/settings/email.html) + +* [Custom logo](#custom-logo) +* [Custom additional text](#custom-additional-text-premium-only) +* [Custom hostname for private commit emails](#custom-hostname-for-private-commit-emails) + +# Email[](#email-core-only "Permalink") + +您可以自定义 GitLab 实例发送的电子邮件中的某些内容. + +## Custom logo[](#custom-logo "Permalink") + +可以自定义某些电子邮件标题中的[徽标](../appearance.html#navigation-bar) ,请参阅[徽标自定义部分](../appearance.html#navigation-bar) . + +## Custom additional text[](#custom-additional-text-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5031) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.7. + +附加文本将出现在任何电子邮件的底部,并且可出于法律/审核/合规性原因使用. + +1. 转到**管理区域>设置>首选项** ( `/admin/application_settings/preferences` ). +2. 展开**电子邮件**部分. +3. 在**其他文本**字段中输入您的文本. +4. Click **Save**. + +## Custom hostname for private commit emails[](#custom-hostname-for-private-commit-emails "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22560) . + +此配置选项设置[专用提交电子邮件](../../profile/index.html#private-commit-email)的电子邮件主机名. 默认情况下,它设置为`users.noreply.YOUR_CONFIGURED_HOSTNAME` . + +为了更改此选项: + +1. 转到**管理区域>设置>首选项** ( `/admin/application_settings/preferences` ). +2. 展开**电子邮件**部分. +3. 在" **自定义主机名(用于私人提交电子邮件)"**字段中输入所需的主机**名** . +4. Click **保存更改**. + +**注意:**一旦配置了主机名,GitLab 将无法识别使用先前主机名的每封私人提交电子邮件. 这可能会与某些[Push 规则](../../../push_rules/push_rules.html)直接冲突,例如, `Check whether author is a GitLab user`以及`Check whether committer is the current authenticated user` . \ No newline at end of file diff --git a/_book/docs/444.md b/_book/docs/444.md new file mode 100644 index 0000000000000000000000000000000000000000..ff7ffd6c54fa06618a3ac1d74442a127f631e100 --- /dev/null +++ b/_book/docs/444.md @@ -0,0 +1,117 @@ +# Enable and disable GitLab features deployed behind feature flags + +> 原文:[https://docs.gitlab.com/ee/administration/feature_flags.html](https://docs.gitlab.com/ee/administration/feature_flags.html) + +* [How to enable and disable features behind flags](#how-to-enable-and-disable-features-behind-flags) + * [Start the GitLab Rails console](#start-the-gitlab-rails-console) + * [Enable or disable the feature](#enable-or-disable-the-feature) + +# Enable and disable GitLab features deployed behind feature flags[](#enable-and-disable-gitlab-features-deployed-behind-feature-flags-core-only "Permalink") + +GitLab 采用[功能标记策略](../development/feature_flags/index.html)在开发的早期阶段部署功能,以便可以逐步推出它们. + +在使它们永久可用之前,出于[多种原因](../development/feature_flags/process.html#when-to-use-feature-flags) ,可以将功能部署在标志的后面,例如: + +* 测试功能. +* 在功能开发的早期阶段获得用户和客户的反馈. +* 评估用户采用率. +* 评估它如何影响 GitLab 的性能. +* 在整个发行版中以较小的部分构建它. + +标记后面的功能通常可以逐步推出: + +1. 默认情况下,该功能开始禁用. +2. 该功能默认情况下处于启用状态. +3. 功能标记已删除. + +可以启用和禁用这些功能,以允许或禁止用户使用它们. GitLab 管理员可以访问 GitLab Rails 控制台来完成此操作. + +如果您使用了某个功能并发现了错误,不正常行为或错误,那么尽快向 GitLab [**提供反馈**](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue[title]=Docs - feature flag feedback: Feature Name&issue[description]=Describe the problem you've encountered. + + + +/label ~)非常重要,这样我们就可以在标记后改进或修复它. 当您将 GitLab 升级到早期版本时,功能标志状态可能会更改. + +**注意:请**注意,部署在功能标记后面的功能可能尚未准备好用于生产. 但是,禁用默认情况下已启用的已部署标志后面的功能也可能带来风险. 如果启用了它们,我们建议您保持原样. + +## How to enable and disable features behind flags[](#how-to-enable-and-disable-features-behind-flags "Permalink") + +每个功能都有其自己的标志,应使用该标志来启用和禁用它. 标志后面的每个功能的文档都包括一个部分,通知标志的状态以及启用或禁用标志的命令. + +### Start the GitLab Rails console[](#start-the-gitlab-rails-console "Permalink") + +启用或禁用标志后面的功能的第一件事是在 GitLab Rails 控制台上启动会话. + +对于所有安装; + +``` +sudo gitlab-rails console +``` + +对于源安装: + +``` +sudo -u git -H bundle exec rails console -e production +``` + +有关详细信息,请参见[启动 Rails 控制台会话](troubleshooting/debug.html#starting-a-rails-console-session) . + +### Enable or disable the feature[](#enable-or-disable-the-feature "Permalink") + +一旦启动 Rails 控制台会话,请相应地运行`Feature.enable`或`Feature.disable`命令. 特定标志可以在功能文档中找到. + +要启用功能,请运行: + +``` +Feature.enable(:) +``` + +例如,启用证据收集: + +``` +Feature.enable(:release_evidence_collection) +``` + +要禁用功能,请运行: + +``` +Feature.disable(:) +``` + +Example, to disable Evidence Collection: + +``` +Feature.disable(:release_evidence_collection) +``` + +可以基于每个项目启用或禁用某些功能标志: + +``` +Feature.enable(:, Project.find()) +``` + +例如,要为项目`1234`启用[`:junit_pipeline_view`](../ci/junit_test_reports.html#enabling-the-junit-test-reports-feature-core-only)功能标记: + +``` +Feature.enable(:junit_pipeline_view, Project.find(1234)) +``` + +`Feature.enable`和`Feature.disable`始终返回`nil` ,这并不表示命令失败: + +``` +irb(main):001:0> Feature.enable(:release_evidence_collection) +=> nil +``` + +要检查标志是启用还是禁用,可以使用`Feature.enabled?` 或`Feature.disabled?` : + +``` +Feature.enable(:release_evidence_collection) +=> nil +Feature.enabled?(:release_evidence_collection) +=> true +Feature.disabled?(:release_evidence_collection) +=> false +``` + +功能就绪后,GitLab 将删除功能标志,启用和禁用该功能的选项将不再存在,并且该功能将在所有实例中可用. \ No newline at end of file diff --git a/_book/docs/445.md b/_book/docs/445.md new file mode 100644 index 0000000000000000000000000000000000000000..ac53b49d07cb51103e42f29e6ebc99d37745e0de --- /dev/null +++ b/_book/docs/445.md @@ -0,0 +1,62 @@ +# Geo nodes Admin Area + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/geo_nodes.html](https://docs.gitlab.com/ee/user/admin_area/geo_nodes.html) + +* [Common settings](#common-settings) +* [**Secondary** node settings](#secondary-node-settings) +* [Geo backfill](#geo-backfill) +* [Using a different URL for synchronization](#using-a-different-url-for-synchronization) +* [Multiple secondary nodes behind a load balancer](#multiple-secondary-nodes-behind-a-load-balancer) + +# Geo nodes Admin Area[](#geo-nodes-admin-area-premium-only "Permalink") + +您可以为 GitLab Geo 节点配置各种设置. 有关更多信息,请参阅[地理文档](../../administration/geo/replication/index.html) . + +在主节点上,转到" **管理区域">"地理位置"** . 在辅助节点上,转到" **管理区域">"地理位置">"节点"** . + +## Common settings[](#common-settings "Permalink") + +所有地理节点均具有以下设置: + +| Setting | Description | +| --- | --- | +| Primary | 这会将地理节点标记为**主要**节点. 只能有一个**主**节点. 确保首先添加**主**节点,然后再添加所有其他节点. | +| Name | 地理节点的唯一标识符. 必须与`gitlab_rails['geo_node_name']`中的设置`gitlab_rails['geo_node_name']`相`/etc/gitlab/gitlab.rb` . 该设置默认为`external_url`并带有斜杠. | +| URL | 实例的面向用户的 URL. | + +您正在读取的节点带有绿色的`Current node`标签, **主**节点被赋予蓝色的`Primary`标签. 请记住,您只能在**主**节点上进行更改! + +## **Secondary** node settings[](#secondary-node-settings "Permalink") + +**辅助**节点具有许多可用的其他设置: + +| Setting | Description | +| --- | --- | +| 选择性同步 | 为此**辅助**节点启用地理位置[选择性同步](../../administration/geo/replication/configuration.html#selective-synchronization) . | +| 储存库同步容量 | 回填存储库时,此**辅助**节点将向**主**节点发出的并发请求数. | +| File sync capacity | 回填文件时,此**辅助**节点将向**主**节点发出的并发请求数. | + +## Geo backfill[](#geo-backfill "Permalink") + +**二级**节点通知由**主**节点更改存储库和文件,并总是试图对这些变化尽快同步. + +回填是使用**辅助**节点添加到数据库*之前*存在的存储库和文件填充**辅助**节点的操作. 由于可能存在大量的存储库和文件,因此一次尝试全部下载它们是不可行的,因此,GitLab 对这些操作的并发性设置了上限. + +回填所需的时间是最大并发的函数,但是值越高, **主**节点上的负担就越大. 从[GitLab 10.2 开始](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3107) ,限制是可配置的. 如果**主**节点有很多剩余容量,则可以增加值以在更短的时间内完成回填. 如果它的负载很重,回填会降低其正常请求的可用性,则可以减少这些请求. + +## Using a different URL for synchronization[](#using-a-different-url-for-synchronization "Permalink") + +**次要**节点使用**主**节点的内部 URL 与之联系(例如,同步存储库). 内部 URL 名称将其与用户使用的[外部](https://docs.gitlab.com/omnibus/settings/configuration.html) URL 区别开来. 内部 URL 不必是私有地址. + +内部 URL 默认为外部 URL,但是您可以在**管理区域>地理位置>节点**下对其进行自定义. + +**警告:**我们建议在配置 Geo 节点时使用 HTTPS 连接. 为了避免在使用 HTTPS 时中断**主**节点和**辅助**节点之间的通信,请自定义内部 URL 以指向负载均衡器,且 TLS 终止于负载均衡器. + +## Multiple secondary nodes behind a load balancer[](#multiple-secondary-nodes-behind-a-load-balancer "Permalink") + +在 GitLab 11.11 中,只要为每个地理节点设置了唯一的`name` , **辅助**节点就可以使用相同的外部 URL. `gitlab.rb`设置`gitlab_rails['geo_node_name']`必须: + +* 为每个运行`unicorn` , `sidekiq`或`geo_logcursor` GitLab 实例设置. +* 匹配地理节点名称. + +负载平衡器必须使用粘性会话,以避免身份验证失败和跨站点请求错误. \ No newline at end of file diff --git a/_book/docs/446.md b/_book/docs/446.md new file mode 100644 index 0000000000000000000000000000000000000000..4da770c104a751045349dc9ede48803c15fec437 --- /dev/null +++ b/_book/docs/446.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/administration/lfs/lfs_administration.html](https://docs.gitlab.com/ee/administration/lfs/lfs_administration.html) \ No newline at end of file diff --git a/_book/docs/447.md b/_book/docs/447.md new file mode 100644 index 0000000000000000000000000000000000000000..a893714d0b50214f135043c054c01f124adb7f10 --- /dev/null +++ b/_book/docs/447.md @@ -0,0 +1,566 @@ +# GitLab Pages administration + +> 原文:[https://docs.gitlab.com/ee/administration/pages/](https://docs.gitlab.com/ee/administration/pages/) + +* [Overview](#overview) +* [Prerequisites](#prerequisites) + * [Add the domain to the Public Suffix List](#add-the-domain-to-the-public-suffix-list) + * [DNS configuration](#dns-configuration) +* [Configuration](#configuration) + * [Wildcard domains](#wildcard-domains) + * [Wildcard domains with TLS support](#wildcard-domains-with-tls-support) + * [Additional configuration for Docker container](#additional-configuration-for-docker-container) + * [Global settings](#global-settings) +* [Advanced configuration](#advanced-configuration) + * [Custom domains](#custom-domains) + * [Custom domains with TLS support](#custom-domains-with-tls-support) + * [Custom domain verification](#custom-domain-verification) + * [Let’s Encrypt integration](#lets-encrypt-integration) + * [Access control](#access-control) + * [Disabling public access to all Pages websites](#disabling-public-access-to-all-pages-websites) + * [Running behind a proxy](#running-behind-a-proxy) + * [Using a custom Certificate Authority (CA)](#using-a-custom-certificate-authority-ca) +* [Activate verbose logging for daemon](#activate-verbose-logging-for-daemon) +* [Change storage path](#change-storage-path) +* [Configure listener for reverse proxy requests](#configure-listener-for-reverse-proxy-requests) +* [Set maximum pages size](#set-maximum-pages-size) + * [Override maximum pages size per project or group](#override-maximum-pages-size-per-project-or-group-premium-only) +* [Running GitLab Pages on a separate server](#running-gitlab-pages-on-a-separate-server) +* [Backup](#backup) +* [Security](#security) +* [Troubleshooting](#troubleshooting) + * [`open /etc/ssl/ca-bundle.pem: permission denied`](#open-etcsslca-bundlepem-permission-denied) + * [`dial tcp: lookup gitlab.example.com` and `x509: certificate signed by unknown authority`](#dial-tcp-lookup-gitlabexamplecom-and-x509-certificate-signed-by-unknown-authority) + * [404 error after transferring project to a different group or user](#404-error-after-transferring-project-to-a-different-group-or-user) + +# GitLab Pages administration[](#gitlab-pages-administration "Permalink") + +版本历史 + +* 在 GitLab EE 8.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80) . +* GitLab EE 8.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173)了具有 TLS 支持的自定义 CNAME. +* GitLab 页面[已移植](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14605)到 GitLab 8.17 中的 Community Edition. +* 在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30548)了对子组项目网站的支持. + +GitLab 页面允许托管静态站点. 它必须由管理员配置. 提供了单独的[用户文档](../../user/project/pages/index.html) . + +**注意:**本指南适用于 Omnibus GitLab 安装. 如果您从源代码安装了 GitLab,请参见[GitLab 页面管理以了解源代码安装](source.html) . + +## Overview[](#overview "Permalink") + +GitLab Pages 使用[GitLab Pages 守护程序](https://gitlab.com/gitlab-org/gitlab-pages) ,这是一个用 Go 编写的简单 HTTP 服务器,可以侦听外部 IP 地址并提供对自定义域和自定义证书的支持. 它通过 SNI 支持动态证书,并且默认情况下使用 HTTP2 公开页面. 我们鼓励您阅读其[自述文件](https://gitlab.com/gitlab-org/gitlab-pages/blob/master/README.md)以全面了解其工作原理. + +对于[自定义域](#custom-domains) (而不是[通配符域](#wildcard-domains) ),Pages 守护程序需要在端口`80`和/或`443` . 因此,设置方式具有一定的灵活性: + +* 在与 GitLab 相同的服务器上运行 Pages 守护程序,侦听**辅助 IP** . +* 在[单独的服务器上](#running-gitlab-pages-on-a-separate-server)运行 Pages 守护程序. 在这种情况下, [Pages 路径](#change-storage-path)也必须存在于安装 Pages 守护程序的服务器中,因此您必须通过网络共享它. +* 在与 GitLab 相同的服务器上运行 Pages 守护程序,侦听相同的 IP,但侦听不同的端口. 在这种情况下,您将不得不使用负载平衡器代理流量. 如果选择该路由,请注意,应将 TCP 负载平衡用于 HTTPS. 如果您使用 TLS 终止(HTTPS 负载平衡),则将无法使用用户提供的证书来提供页面. 对于 HTTP,可以使用 HTTP 或 TCP 负载平衡. + +在本文档中,我们将假设第一个选项继续进行. 如果您不支持自定义域,则不需要辅助 IP. + +## Prerequisites[](#prerequisites "Permalink") + +在进行页面配置之前,您需要: + +1. 具有用于服务 GitLab 页面的专有根域. 请注意,您不能使用 GitLab 实例域的子域. +2. 配置**通配符 DNS 记录** . +3. (可选)如果您决定在 HTTPS 下提供 Pages,则具有该域的**通配符证书** . +4. (可选,但建议使用)启用[共享运行器,](../../ci/runners/README.html)以便您的用户不必自己携带. +5. (仅用于自定义域)具有**辅助 IP** . + +**注意:**如果您的 GitLab 实例和 Pages 守护程序部署在专用网络中或防火墙后面,则只有有权访问专用网络的设备/用户才能访问 GitLab Pages 网站. + +### Add the domain to the Public Suffix List[](#add-the-domain-to-the-public-suffix-list "Permalink") + +浏览器使用" [公共后缀列表"](https://publicsuffix.org)来决定如何对待子域. 如果您的 GitLab 实例允许公众创建 GitLab Pages 网站,那么它还允许这些用户在 pages 域( `example.io` )上创建子域. 将域添加到"公共后缀列表"中可防止浏览器接受[超级 cookie](https://en.wikipedia.org/wiki/HTTP_cookie#Supercookie)等. + +请按照[以下说明](https://publicsuffix.org/submit/)提交您的 GitLab 页面子域. 例如,如果您的域是`example.io` ,则应请求将`example.io`添加到公共后缀列表中. `gitlab.io` [在 2016 年](https://gitlab.com/gitlab-com/infrastructure/-/issues/230)添加了`gitlab.io` . + +### DNS configuration[](#dns-configuration "Permalink") + +GitLab 页面期望在其自己的虚拟主机上运行. 在您的 DNS 服务器/提供程序中,您需要添加[通配符 DNS A 记录](https://en.wikipedia.org/wiki/Wildcard_DNS_record) ,该[记录](https://en.wikipedia.org/wiki/Wildcard_DNS_record)指向 GitLab 运行的主机. 例如,条目如下所示: + +``` +*.example.io. 1800 IN A 192.0.2.1 +*.example.io. 1800 IN AAAA 2001::1 +``` + +其中`example.io`是将在其下提供 GitLab 页面的域, `192.0.2.1`是您的 GitLab 实例的 IPv4 地址,而`2001::1`是 IPv6 地址. 如果没有 IPv6,则可以省略 AAAA 记录. + +**注意:**您不应使用 GitLab 域来服务用户页面. 有关更多信息,请参见[安全性部分](#security) . + +## Configuration[](#configuration "Permalink") + +根据您的需要,您可以通过 4 种不同的方式设置 GitLab 页面. + +从最简单的设置到最高级的设置,列出了以下示例. 绝对最低要求是设置通配符 DNS,因为在所有配置中都需要这样做. + +### Wildcard domains[](#wildcard-domains "Permalink") + +**Requirements:** + +* [Wildcard DNS setup](#dns-configuration) + +* * * + +网址方案: `http://page.example.io` : `http://page.example.io` + +这是可以与 Pages 一起使用的最小设置. 如下所述,它是所有其他设置的基础. NGINX 将把所有请求代理到守护程序. Pages 守护程序不收听外界. + +1. Set the external URL for GitLab Pages in `/etc/gitlab/gitlab.rb`: + + ``` + pages_external_url 'http://example.io' + ``` + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +观看[视频教程](https://youtu.be/dD8c7WNcc6s)以了解此配置. + +### Wildcard domains with TLS support[](#wildcard-domains-with-tls-support "Permalink") + +**Requirements:** + +* [Wildcard DNS setup](#dns-configuration) +* 通配 TLS 证书 + +* * * + +网址方案: `https://page.example.io` : `https://page.example.io` + +NGINX 将把所有请求代理到守护程序. Pages 守护程序不收听外界. + +1. 将证书和密钥放在`/etc/gitlab/ssl` +2. 在`/etc/gitlab/gitlab.rb`指定以下配置: + + ``` + pages_external_url 'https://example.io' + + pages_nginx['redirect_http_to_https'] = true + pages_nginx['ssl_certificate'] = "/etc/gitlab/ssl/pages-nginx.crt" + pages_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/pages-nginx.key" + ``` + + 其中`pages-nginx.crt`和`pages-nginx.key`分别是 SSL 证书和密钥. + +3. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +### Additional configuration for Docker container[](#additional-configuration-for-docker-container "Permalink") + +当它在 Docker 容器中运行时,GitLab Pages 守护程序将没有绑定绑定的权限. 要解决此问题,您需要更改 chroot 行为: + +1. Edit `/etc/gitlab/gitlab.rb`. +2. 将 GitLab 页面的`inplace_chroot`设置为`true` : + + ``` + gitlab_pages['inplace_chroot'] = true + ``` + +3. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +**注意:** `inplace_chroot`选项可能不适用于其他功能,例如[Pages Access Control](#access-control) . [GitLab 页面自述文件](https://gitlab.com/gitlab-org/gitlab-pages#caveats)包含有关警告和解决方法的更多信息. + +### Global settings[](#global-settings "Permalink") + +下表是 Omnibus GitLab 中 Pages 已知的所有配置设置及其作用. 这些选项可以在`/etc/gitlab/gitlab.rb`进行调整,并在[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure)之后生效. 这些设置中的大多数不需要手动配置,除非您需要对 Pages 守护程序在环境中如何运行和提供内容的方式进行更精细的控制. + +| Setting | Description | +| --- | --- | +| `pages_external_url` | 可访问 GitLab 页面的 URL,包括协议(HTTP / HTTPS). 如果使用`https://` ,则还必须设置`gitlab_pages['ssl_certificate']`和`gitlab_pages['ssl_certificate_key']` . | +| `gitlab_pages[]` |   | +| `access_control` | 是否启用[访问控制](index.html#access-control) . | +| `api_secret_key` | 具有用于通过 GitLab API 进行身份验证的密钥的文件的完整路径. 未设置时自动生成. | +| `artifacts_server` | 在 GitLab 页面中启用查看[工件](../job_artifacts.html) . | +| `artifacts_server_timeout` | 对工件服务器的代理请求超时(以秒为单位). | +| `artifacts_server_url` | 用于代理工件请求的 API URL. 默认为 GitLab `external URL` + `/api/v4` ,例如`https://gitlab.com/api/v4` . | +| `auth_redirect_uri` | 用于通过 GitLab 进行身份验证的回调 URL. 默认为`pages_external_url` + `/auth`项目子域. | +| `auth_secret` | Secret key for signing authentication requests. Leave blank to pull automatically from GitLab during OAuth registration. | +| `dir` | 配置和机密文件的工作目录. | +| `enable` | 在当前系统上启用或禁用 GitLab 页面. | +| `external_http` | 将页面配置为绑定到一个或多个辅助 IP 地址,以服务 HTTP 请求. 可以将多个地址以及确切的端口作为数组给出,例如`['1.2.3.4', '1.2.3.5:8063']` . 设置`listen_http`值. | +| `external_https` | 将页面配置为绑定到一个或多个辅助 IP 地址,以服务 HTTPS 请求. 可以将多个地址以及确切的端口作为数组给出,例如`['1.2.3.4', '1.2.3.5:8063']` . 设置`listen_https`值. | +| `gitlab_client_http_timeout` | GitLab API HTTP 客户端连接超时(以秒为单位)(默认值:10s). | +| `gitlab_client_jwt_expiry` | JWT 令牌的到期时间,以秒为单位(默认值:30s). | +| `gitlab_id` | OAuth 应用程序公共 ID. 当 Pages 通过 GitLab 进行身份验证时,请保留空白以自动填充. | +| `gitlab_secret` | OAuth 应用程序密码. 当 Pages 通过 GitLab 进行身份验证时,请保留空白以自动填充. | +| `gitlab_server` | 启用访问控制时用于身份验证的服务器; 默认为 GitLab `external_url` . | +| `headers` | 指定应随每个响应发送给客户端的任何其他 http 标头. | +| `inplace_chroot` | 在[不支持 bind-mounts 的系统上](index.html#additional-configuration-for-docker-container) ,这会指示 GitLab Pages chroot 进入其`pages_path`目录. 使用就地 chroot 时,存在一些注意事项; 有关更多信息,请参考 GitLab 页面[自述文件](https://gitlab.com/gitlab-org/gitlab-pages/blob/master/README.md#caveats) . | +| `insecure_ciphers` | 使用默认的密码套件列表,其中可能包含不安全的密码套件,例如 3DES 和 RC4. | +| `internal_gitlab_server` | 内部 GitLab 服务器地址专门用于 API 请求. 如果要通过内部负载均衡器发送该流量,则很有用. 默认为 GitLab `external_url` . | +| `listen_proxy` | 侦听反向代理请求的地址. 页面将绑定到这些地址的网络套接字,并从中接收传入的请求. 在`$nginx-dir/conf/gitlab-pages.conf`设置`proxy_pass`的值. | +| `log_directory` | 日志目录的绝对路径. | +| `log_format` | 日志输出格式: `text`或`json` . | +| `log_verbose` | 详细记录,对/错. | +| `max_connections` | 限制与 HTTP,HTTPS 或代理侦听器的并发连接数. | +| `metrics_address` | 用于监听指标请求的地址. | +| `redirect_http` | 将页面从 HTTP 重定向到 HTTPS,是/否. | +| `sentry_dsn` | 用于发送 Sentry 崩溃报告的地址. | +| `sentry_enabled` | 使用 Sentry(真/假)启用报告和日志记录. | +| `sentry_environment` | Sentry 崩溃报告的环境. | +| `status_uri` | 状态页面的 URL 路径,例如`/@status` . | +| `tls_max_version` | 指定最大 SSL / TLS 版本(" ssl3"," tls1.0"," tls1.1"或" tls1.2"). | +| `tls_min_version` | 指定最低 SSL / TLS 版本(" ssl3"," tls1.0"," tls1.1"或" tls1.2"). | +| `use_http2` | 启用 HTTP2 支持. | +| `gitlab_pages['env'][]` |   | +| `http_proxy` | 配置 GitLab 页面以使用 HTTP 代理来调解页面和 GitLab 之间的流量. 启动 Pages 守护程序时设置环境变量`http_proxy` . | +| `gitlab_rails[]` |   | +| `pages_domain_verification_cron_worker` | 验证自定义 GitLab 页面域的时间表. | +| `pages_domain_ssl_renewal_cron_worker` | 通过 Let's Encrypt for GitLab Pages 域获取和更新 SSL 证书的时间表. | +| `pages_domain_removal_cron_worker` | 删除未验证的自定义 GitLab 页面域的时间表. | +| `pages_path` | 磁盘上存储页面的目录,默认为`GITLAB-RAILS/shared/pages` . | +| `pages_nginx[]` |   | +| `enable` | 在 NGINX 内部包含一个用于页面的虚拟主机`server{}`块. NGINX 需要将流量代理回 Pages 守护程序. 如果 Pages 守护程序应直接接收所有请求(例如在使用[自定义域](index.html#custom-domains)时),则设置为`false` . | + +* * * + +## Advanced configuration[](#advanced-configuration "Permalink") + +除了通配符域,您还可以选择配置 GitLab 页面以与自定义域一起使用. 同样,这里有两个选项:支持带有和不带有 TLS 证书的自定义域. 最简单的设置是没有 TLS 证书. 无论哪种情况,都需要一个**辅助 IP** . 如果同时具有 IPv6 和 IPv4 地址,则可以同时使用它们. + +### Custom domains[](#custom-domains "Permalink") + +**Requirements:** + +* [Wildcard DNS setup](#dns-configuration) +* 次要 IP + +* * * + +URL 方案: `http://page.example.io` : `http://page.example.io`和`http://domain.com` + +在这种情况下,Pages 守护程序正在运行,NGINX 仍将请求代理到该守护程序,但该守护程序也能够接收来自外界的请求. 支持自定义域,但不支持 TLS. + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + pages_external_url "http://example.io" + nginx['listen_addresses'] = ['192.0.2.1'] + pages_nginx['enable'] = false + gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001::2]:80'] + ``` + + 其中`192.0.2.1`是 GitLab 侦听的主要 IP 地址,而`192.0.2.2`和`2001::2`是 GitLab Pages 守护程序侦听的辅助 IP. 如果没有 IPv6,则可以省略 IPv6 地址. + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +### Custom domains with TLS support[](#custom-domains-with-tls-support "Permalink") + +**Requirements:** + +* [Wildcard DNS setup](#dns-configuration) +* 通配 TLS 证书 +* 次要 IP + +* * * + +网址方案: `https://page.example.io` : `https://page.example.io`和`https://domain.com` + +在这种情况下,Pages 守护程序正在运行,NGINX 仍将请求代理到该守护程序,但该守护程序也能够接收来自外界的请求. 支持自定义域和 TLS. + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + pages_external_url "https://example.io" + nginx['listen_addresses'] = ['192.0.2.1'] + pages_nginx['enable'] = false + gitlab_pages['cert'] = "/etc/gitlab/ssl/example.io.crt" + gitlab_pages['cert_key'] = "/etc/gitlab/ssl/example.io.key" + gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001::2]:80'] + gitlab_pages['external_https'] = ['192.0.2.2:443', '[2001::2]:443'] + ``` + + 其中`192.0.2.1`是 GitLab 侦听的主要 IP 地址,而`192.0.2.2`和`2001::2`是 GitLab Pages 守护程序侦听的辅助 IP. 如果没有 IPv6,则可以省略 IPv6 地址. + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +### Custom domain verification[](#custom-domain-verification "Permalink") + +为了防止恶意用户劫持不属于他们的[域](../../user/project/pages/custom_domains_ssl_tls_certification/index.html#steps) ,GitLab 支持[自定义域验证](../../user/project/pages/custom_domains_ssl_tls_certification/index.html#steps) . 添加自定义域时,将要求用户通过在该域的 DNS 记录中添加 GitLab 控制的验证码来证明自己拥有该域. + +如果您的用户群是私有的或受其他方式信任,则可以禁用验证要求. 导航到**管理区域>设置>首选项,**然后在**页面**部分中取消选中**要求用户证明自定义域的所有权** . 默认情况下启用此设置. + +### Let’s Encrypt integration[](#lets-encrypt-integration "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28996) . + +[GitLab Pages 的 Let's Encrypt 集成](../../user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html)允许用户为在自定义域下提供服务的 GitLab Pages 网站添加 Let's Encrypt SSL 证书. + +要启用它,您需要: + +1. 选择一封电子邮件,在该电子邮件上您将收到有关域过期的通知. +2. 导航到实例的" **管理区域">"设置">"首选项",**然后展开" **页面"**设置. +3. 输入用于接收通知的电子邮件,并接受" Let's Encrypt 的服务条款",如下所示. +4. Click **保存更改**. + +[![Let's Encrypt settings](img/cd210f00f72fcb8f7b00750457b0ab2c.png)](img/lets_encrypt_integration_v12_1.png) + +### Access control[](#access-control "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33422) . + +GitLab Pages 访问控制可以针对每个项目进行配置,并允许根据用户对该项目的成员资格来控制对 Pages 站点的访问. + +访问控制通过在 GitLab 上将 Pages 守护程序注册为 OAuth 应用程序来工作. 每当未经身份验证的用户发出访问私有 Pages 站点的请求时,Pages 守护程序都会将该用户重定向到 GitLab. 如果身份验证成功,则使用令牌将用户重定向回 Pages,该令牌将保留在 cookie 中. 这些 Cookie 均用密钥签名,因此可以检测到篡改. + +Pages 使用该令牌对每个查看私有站点中的资源的请求进行身份验证. 对于收到的每个请求,它都会向 GitLab API 发出请求,以检查用户是否有权读取该站点. + +默认情况下,页面访问控制是禁用的. 要启用它: + +1. 在`/etc/gitlab/gitlab.rb`启用它: + + ``` + gitlab_pages['access_control'] = true + ``` + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). +3. 用户现在可以在其[项目的设置](../../user/project/pages/pages_access_control.html)中对其进行[配置](../../user/project/pages/pages_access_control.html) . + +**重要说明:**对于多节点设置,要使此设置生效,必须将其应用于所有 App 节点以及 Sidekiq 节点. + +#### Disabling public access to all Pages websites[](#disabling-public-access-to-all-pages-websites "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32095) . + +您可以对 GitLab 实例上托管的所有 GitLab Pages 网站实施[访问控制](#access-control) . 这样,只有登录用户才能访问它们. 此设置将覆盖用户在单个项目中设置的访问控制. + +这对于将通过 Pages 网站发布的信息仅保留给您实例的用户很有用. 要做到这一点: + +1. 导航到实例的" **管理区域">"设置">"首选项",**然后展开" **页面"**设置. +2. 选中**禁用对页面站点的公共访问**复选框. +3. Click **保存更改**. + +**警告:**此操作将不会重新部署当前所有公开的网站. 通过[更改 GitLab 页面配置机制,](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/282)可以解决此问题. + +### Running behind a proxy[](#running-behind-a-proxy "Permalink") + +与其他 GitLab 一样,Pages 可以用于由代理控制外部 Internet 连接的那些环境. 为了对 GitLab 页面使用代理: + +1. 在`/etc/gitlab/gitlab.rb`配置: + + ``` + gitlab_pages['env']['http_proxy'] = 'http://example:8080' + ``` + +2. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +### Using a custom Certificate Authority (CA)[](#using-a-custom-certificate-authority-ca "Permalink") + +**注意:** [在 13.2 之前](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4289) ,使用 Omnibus 时, [需要](https://docs.gitlab.com/13.1/ee/administration/pages/index.html)一种[解决方法](https://docs.gitlab.com/13.1/ee/administration/pages/index.html) . + +使用自定义 CA 颁发的证书时,如果无法识别自定义 CA,则[访问控制](../../user/project/pages/pages_access_control.html#gitlab-pages-access-control)和[HTML 作业工件](../../ci/pipelines/job_artifacts.html#browsing-artifacts)的[联机视图](../../ci/pipelines/job_artifacts.html#browsing-artifacts)将无法工作. + +这通常会导致以下错误: `Post /oauth/token: x509: certificate signed by unknown authority` . + +对于从源安装,可以通过在系统证书存储中安装自定义证书颁发机构(CA)来解决. + +对于 Omnibus,可以通过[在 Omnibus GitLab 中安装自定义 CA 来解决](https://docs.gitlab.com/omnibus/settings/ssl.html) . + +## Activate verbose logging for daemon[](#activate-verbose-logging-for-daemon "Permalink") + +详细日志记录是在 Omnibus GitLab 11.1 中[引入的](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2533) . + +请按照以下步骤配置 GitLab Pages 守护程序的详细日志记录. + +1. 缺省情况下,守护程序仅记录`INFO`级别的日志. 如果要使其以`DEBUG`级别记录事件,则必须在`/etc/gitlab/gitlab.rb`配置: + + ``` + gitlab_pages['log_verbose'] = true + ``` + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +## Change storage path[](#change-storage-path "Permalink") + +请按照以下步骤更改 GitLab 页面内容的默认存储路径. + +1. 默认情况下,页面存储在`/var/opt/gitlab/gitlab-rails/shared/pages` . 如果要将它们存储在其他位置,则必须在`/etc/gitlab/gitlab.rb`设置: + + ``` + gitlab_rails['pages_path'] = "/mnt/storage/pages" + ``` + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +## Configure listener for reverse proxy requests[](#configure-listener-for-reverse-proxy-requests "Permalink") + +请按照以下步骤配置 GitLab 页面的代理侦听器. 在 Omnibus GitLab 11.1 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2533) . + +1. 默认情况下,侦听器配置为侦听`localhost:8090`上的请求. + + 如果要禁用它,则必须在`/etc/gitlab/gitlab.rb`配置: + + ``` + gitlab_pages['listen_proxy'] = nil + ``` + + 如果您希望它在其他端口上侦听,则必须在`/etc/gitlab/gitlab.rb`也进行`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_pages['listen_proxy'] = "localhost:10080" + ``` + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +## Set maximum pages size[](#set-maximum-pages-size "Permalink") + +您可以在**管理区域>设置>首选项>页面**中的**最大页面大小(MB)中**配置每个项目的解压缩存档的**最大大小** . 默认值为 100MB. + +### Override maximum pages size per project or group[](#override-maximum-pages-size-per-project-or-group-premium-only "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/16610) . + +要覆盖特定项目的全局最大页面大小: + +1. 导航到项目的**"设置">"页面"**页面. +2. 编辑**最大页面大小** . +3. Click **保存更改**. + +覆盖特定组的全局最大页面大小: + +1. 导航至论坛的**"设置">"常规"**页面,然后展开" **页面"** . +2. 编辑**最大页面大小** . +3. Click **保存更改**. + +## Running GitLab Pages on a separate server[](#running-gitlab-pages-on-a-separate-server "Permalink") + +您可以在单独的服务器上运行 GitLab Pages 守护程序,以减少主应用程序服务器上的负载. + +要在单独的服务器上配置 GitLab 页面: + +**危险:**以下过程包括备份和编辑`gitlab-secrets.json`文件的步骤. 此文件包含控制数据库加密的机密. 请谨慎操作. + +1. 在**GitLab 服务器上** ,要启用 Pages,请将以下内容添加到`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_pages['enable'] = true + ``` + +2. (可选)要启用[访问控制](#access-control) ,请将以下内容添加到`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_pages['access_control'] = true + ``` + +3. [重新配置**GitLab 服务器,**](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. `gitlab-secrets.json`文件现在已使用新配置进行更新. + +4. 在**GitLab 服务器**上创建 secrets 文件的备份: + + ``` + cp /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json.bak + ``` + +5. 设置一个新服务器. 这将成为**Pages 服务器** . + +6. 在新服务器上创建一个[NFS 共享](../high_availability/nfs_host_client_setup.html) ,并配置该共享以允许从您的主**GitLab 服务器**进行访问. 在此示例中,我们使用默认的 GitLab Pages 文件夹`/var/opt/gitlab/gitlab-rails/shared/pages`作为新服务器上的共享文件夹,并将其安装到**GitLab 服务器**上的`/mnt/pages` . + +7. 在**Pages 服务器上** ,安装 Omnibus GitLab 并修改`/etc/gitlab/gitlab.rb`以包括: + + ``` + external_url 'http://' + pages_external_url "http://" + postgresql['enable'] = false + redis['enable'] = false + prometheus['enable'] = false + puma['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + gitaly['enable'] = false + alertmanager['enable'] = false + node_exporter['enable'] = false + gitlab_rails['auto_migrate'] = false + ``` + +8. 在**Pages 服务器**上创建 secrets 文件的备份: + + ``` + cp /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json.bak + ``` + +9. 将`/etc/gitlab/gitlab-secrets.json`文件从**GitLab 服务器**复制到**Pages 服务器** . + +10. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +11. 在**GitLab 服务器上** ,对`/etc/gitlab/gitlab.rb`进行以下更改: + + ``` + gitlab_pages['enable'] = false + pages_external_url "http://" + gitlab_rails['pages_path'] = "/mnt/pages" + ``` + +12. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +如果您希望分配负载,则可以在多台服务器上运行 GitLab Pages. 您可以通过标准的负载平衡做法来做到这一点,例如将 DNS 服务器配置为为 Pages 服务器返回多个 IP,将负载平衡器配置为在 IP 级别工作等等. 如果要在多台服务器上设置 GitLab 页面,请对每台 Pages 服务器执行上述过程. + +## Backup[](#backup "Permalink") + +GitLab 页面是[常规备份的](../../raketasks/backup_restore.html)一部分,因此无需配置单独的备份. + +## Security[](#security "Permalink") + +您应该强烈考虑以与 GitLab 不同的主机名运行 GitLab 页面,以防止 XSS 攻击. + +## Troubleshooting[](#troubleshooting "Permalink") + +### `open /etc/ssl/ca-bundle.pem: permission denied`[](#open-etcsslca-bundlepem-permission-denied "Permalink") + +GitLab Pages 在 chroot 监狱中运行,通常在`/tmp/gitlab-pages-*`等唯一编号的目录中. + +在监狱内,/ `/etc/ssl/ca-bundle.pem`提供了`/etc/ssl/ca-bundle.pem`受信任的证书. 作为启动 Pages 的一部分,它从`/opt/gitlab/embedded/ssl/certs/cacert.pem` [复制到那里](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/51) . + +如果源文件上的权限不正确(应为`0644` ),那么 chroot 监狱中的文件也将错误. + +页面将在`/var/log/gitlab/gitlab-pages/current`记录错误,例如: + +``` +x509: failed to load system roots and no roots provided +open /etc/ssl/ca-bundle.pem: permission denied +``` + +使用 chroot 监狱会使此错误产生误导,因为它没有引用根文件系统上的`/etc/ssl` . + +解决方法是更正源文件权限并重新启动 Pages: + +``` +sudo chmod 644 /opt/gitlab/embedded/ssl/certs/cacert.pem +sudo gitlab-ctl restart gitlab-pages +``` + +### `dial tcp: lookup gitlab.example.com` and `x509: certificate signed by unknown authority`[](#dial-tcp-lookup-gitlabexamplecom-and-x509-certificate-signed-by-unknown-authority "Permalink") + +同时设置`inplace_chroot`和`access_control`至`true` ,你可能会遇到类似的错误: + +``` +dial tcp: lookup gitlab.example.com on [::1]:53: dial udp [::1]:53: connect: cannot assign requested address +``` + +Or: + +``` +open /opt/gitlab/embedded/ssl/certs/cacert.pem: no such file or directory +x509: certificate signed by unknown authority +``` + +这些错误的原因是 chroot 中缺少文件`resolv.conf`和`ca-bundle.pem` . 解决方法是在 chroot 中复制主机的`/etc/resolv.conf`和 GitLab 的证书包: + +``` +sudo mkdir -p /var/opt/gitlab/gitlab-rails/shared/pages/etc/ssl +sudo mkdir -p /var/opt/gitlab/gitlab-rails/shared/pages/opt/gitlab/embedded/ssl/certs/ + +sudo cp /etc/resolv.conf /var/opt/gitlab/gitlab-rails/shared/pages/etc +sudo cp /opt/gitlab/embedded/ssl/certs/cacert.pem /var/opt/gitlab/gitlab-rails/shared/pages/opt/gitlab/embedded/ssl/certs/ +sudo cp /opt/gitlab/embedded/ssl/certs/cacert.pem /var/opt/gitlab/gitlab-rails/shared/pages/etc/ssl/ca-bundle.pem +``` + +### 404 error after transferring project to a different group or user[](#404-error-after-transferring-project-to-a-different-group-or-user "Permalink") + +如果在将项目转移到另一个组或用户后在 Pages 网站上遇到`404 Not Found`错误,则必须触发 Pages 的域配置更新. 为此,请在`.update`文件中写一些`.update` . Pages 守护程序监视此文件的更改,并在发生更改时重新加载配置. + +使用以下示例来解决使用 Pages 传输项目后修复`404 Not Found`错误: + +``` +date > /var/opt/gitlab/gitlab-rails/shared/pages/.update +``` + +如果您已自定义 Pages 存储路径,请调整上面的命令以使用自定义路径. \ No newline at end of file diff --git a/_book/docs/448.md b/_book/docs/448.md new file mode 100644 index 0000000000000000000000000000000000000000..5dbe6d6f12267857560f946b6edf2b87e7cb7f72 --- /dev/null +++ b/_book/docs/448.md @@ -0,0 +1,133 @@ +# Health Check + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/monitoring/health_check.html](https://docs.gitlab.com/ee/user/admin_area/monitoring/health_check.html) + +* [IP whitelist](#ip-whitelist) +* [Using the endpoints locally](#using-the-endpoints-locally) +* [Health](#health) +* [Readiness](#readiness) +* [Liveness](#liveness) +* [Access token (Deprecated)](#access-token-deprecated) + +# Health Check[](#health-check-core-only "Permalink") + +版本历史 + +* 在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10416)了活动性和就绪性探针. +* `health_check`端点是在 GitLab 8.8 中[引入的](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3888) ,在 GitLab 9.1 中已弃用. +* 在 GitLab 9.4 中不赞成使用[访问令牌](#access-token-deprecated) ,而推荐使用[IP 白名单](#ip-whitelist) . + +manbetx 客户端打不开提供活跃度和准备情况探针,以指示服务的健康状况和对所需服务的可达性. 这些探针报告数据库连接,Redis 连接和对文件系统的访问状态. [可以将](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)这些端点[提供给 Kubernetes 之类的调度程序](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)以保持流量,直到系统准备就绪或根据需要重新启动容器. + +## IP whitelist[](#ip-whitelist "Permalink") + +要访问监视资源,需要将发出请求的客户端 IP 包含在白名单中. 有关详细信息,请参阅[如何将 IP 添加到监视端点的白名单](../../../administration/monitoring/ip_whitelist.html) . + +## Using the endpoints locally[](#using-the-endpoints-locally "Permalink") + +使用默认白名单设置,可以使用以下 URL 从本地主机访问探针: + +``` +GET http://localhost/-/health +``` + +``` +GET http://localhost/-/readiness +``` + +``` +GET http://localhost/-/liveness +``` + +## Health[](#health "Permalink") + +检查应用服务器是否正在运行. 它不会验证数据库或其他服务是否正在运行. 该端点绕过了 Rails Controller,并在请求处理生命周期的早期就作为附加的中间件`BasicHealthCheck`实现. + +``` +GET /-/health +``` + +请求示例: + +``` +curl 'https://gitlab.example.com/-/health' +``` + +响应示例: + +``` +GitLab OK +``` + +## Readiness[](#readiness "Permalink") + +就绪探针会检查 GitLab 实例是否准备好通过 Rails Controller 接受流量. 默认情况下,该检查仅验证实例检查. + +如果指定了`all=1`参数,则检查还将验证相关服务(数据库,Redis,Gitaly 等)并为每个服务提供状态. + +``` +GET /-/readiness +GET /-/readiness?all=1 +``` + +请求示例: + +``` +curl 'https://gitlab.example.com/-/readiness' +``` + +Example response: + +``` +{ "master_check":[{ "status":"failed", "message": "unexpected Master check result: false" }], ... } +``` + +失败时,端点将返回`503` HTTP 状态代码. + +如果通过`token`身份验证,则此检查确实会命中数据库,并且会重做 Redis. + +此检查不受机架攻击. + +## Liveness[](#liveness "Permalink") + +**警告:**在 GitLab [12.4](https://about.gitlab.com/upcoming-releases/)中,"活动性"检查的响应主体已更改为与以下示例匹配. + +检查应用服务器是否正在运行. 该探针用于了解 Rails 控制器是否不会由于多线程而死锁. + +``` +GET /-/liveness +``` + +请求示例: + +``` +curl 'https://gitlab.example.com/-/liveness' +``` + +响应示例: + +成功后,端点将返回`200` HTTP 状态代码和如下响应. + +``` +{ "status": "ok" } +``` + +失败时,端点将返回`503` HTTP 状态代码. + +此检查不受机架攻击. + +## Access token (Deprecated)[](#access-token-deprecated "Permalink") + +**注意:**在 GitLab 9.4 中不赞成使用访问令牌,而推荐使用[IP 白名单](#ip-whitelist) . + +访问探针端点时需要提供访问令牌. 当前接受的令牌可以在您的 GitLab 实例的**管理区域>监视>运行状况检查** ( `admin/health_check` )页面下找到. + +[![access token](img/f313f74b73573e7a2449aa6d00ae7934.png)](img/health_check_token.png) + +可以将访问令牌作为 URL 参数传递: + +``` +https://gitlab.example.com/-/readiness?token=ACCESS_TOKEN +``` + +**注意:**如果无法访问数据库或 Redis 服务,则不能保证探针端点响应正确. 您应该从已弃用的访问令牌切换到[IP 白名单](#ip-whitelist) ,以避免出现这种情况. \ No newline at end of file diff --git a/_book/docs/449.md b/_book/docs/449.md new file mode 100644 index 0000000000000000000000000000000000000000..52f942412e8c6ba7ea8608c6923b6739872abd46 --- /dev/null +++ b/_book/docs/449.md @@ -0,0 +1,149 @@ +# Job logs + +> 原文:[https://docs.gitlab.com/ee/administration/job_logs.html](https://docs.gitlab.com/ee/administration/job_logs.html) + +* [Data flow](#data-flow) +* [Changing the job logs local location](#changing-the-job-logs-local-location) +* [Uploading logs to object storage](#uploading-logs-to-object-storage) +* [How to remove job logs](#how-to-remove-job-logs) +* [New incremental logging architecture](#new-incremental-logging-architecture) + * [Enabling incremental logging](#enabling-incremental-logging) + * [Potential implications](#potential-implications) + +# Job logs[](#job-logs "Permalink") + +> 在 GitLab 12.5 中[从作业跟踪重命名为作业日志](https://gitlab.com/gitlab-org/gitlab/-/issues/29121) . + +作业日志由 GitLab Runner 在处理作业时发送. 您可以在作业页面,管道,电子邮件通知等中查看日志. + +## Data flow[](#data-flow "Permalink") + +通常,作业日志有两种状态: `log`和`archived log` . 在下表中,您可以看到日志经过的阶段: + +| Phase | State | Condition | 数据流 | 储存路径 | +| --- | --- | --- | --- | --- | +| 1:打补丁 | log | 作业运行时 | GitLab Runner => Puma =>文件存储 | `#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log` | +| 2:覆盖 | log | 工作完成后 | GitLab Runner => Puma =>文件存储 | `#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log` | +| 3:归档 | 存档日志 | 工作完成后 | Sidekiq 将日志移至工件文件夹 | `#{ROOT_PATH}/gitlab-rails/shared/artifacts/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log` | +| 4:上传 | 存档日志 | 归档日志后 | Sidekiq 将存档日志移至[对象存储](#uploading-logs-to-object-storage) (如果已配置) | `#{bucket_name}/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log` | + +`ROOT_PATH`因环境而异. 对于 Omnibus GitLab,它将是`/var/opt/gitlab` ;对于从源代码进行的安装,它将是`/home/git/gitlab` . + +## Changing the job logs local location[](#changing-the-job-logs-local-location "Permalink") + +要更改作业日志的存储位置,请执行以下步骤. + +**在所有安装中;** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加或修改以下行: + + ``` + gitlab_ci['builds_directory'] = '/mnt/to/gitlab-ci/builds' + ``` + +2. 保存文件并[重新配置 GitLab,](restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**在源安装中:** + +1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines: + + ``` + gitlab_ci: + # The location where build logs are stored (default: builds/). + # Relative paths are relative to Rails.root. + builds_path: path/to/builds/ + ``` + +2. 保存文件并[重新启动 GitLab,](restart_gitlab.html#installations-from-source)以使更改生效. + +## Uploading logs to object storage[](#uploading-logs-to-object-storage "Permalink") + +归档日志被视为[作业工件](job_artifacts.html) . 因此,当您[设置对象存储集成时](job_artifacts.html#object-storage-settings) ,作业日志将与其他作业工件一起自动迁移到[该对象](job_artifacts.html#object-storage-settings) . + +请参阅[数据流中的](#data-flow) "阶段 4:上传"以了解该过程. + +## How to remove job logs[](#how-to-remove-job-logs "Permalink") + +没有办法自动使旧的作业日志过期,但是如果它们占用太多空间,可以安全地将其删除. 如果您手动删除日志,则 UI 中的作业输出将为空. + +例如,要删除所有超过 60 天的作业日志,请在您的 GitLab 实例中的 Shell 中运行以下命令: + +**危险:**此命令将永久删除日志文件,并且是不可逆的. + +``` +find /var/opt/gitlab/gitlab-rails/shared/artifacts -name "job.log" -mtime +60 -delete +``` + +## New incremental logging architecture[](#new-incremental-logging-architecture "Permalink") + +版本历史 + +* 在 GitLab 10.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18169) . +* [公布为一般可](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46097)在 GitLab 11.0\. + +**注意:**此功能默认为关闭. 有关如何[启用或禁用](#enabling-incremental-logging)它的信息,请参见下文. + +通过将过程与对象存储设置相结合,我们可以完全绕过本地文件存储. 如果将 GitLab 安装为云原生,例如在 Kubernetes 上,这是一个有用的选项. + +数据流与[数据流部分中](#data-flow)描述的相同,只是有所变化: *前两个阶段的存储路径不同* . 这种增量日志架构将日志块存储在 Redis 中,并将其存储在持久性存储(对象存储或数据库)中,而不是文件存储中. Redis 用作一流的存储,它最多可存储 128KB 数据. 一旦发送了完整的块,就将其刷新到持久性存储(对象存储(临时目录)或数据库). 一段时间后,Redis 和持久性存储中的数据将被归档到[对象存储](#uploading-logs-to-object-storage) . + +数据存储在以下 Redis 命名空间中: `Gitlab::Redis::SharedState` . + +这是详细的数据流: + +1. GitLab Runner 从 GitLab 选择工作 +2. GitLab Runner 向 GitLab 发送一条日志 +3. GitLab 将数据追加到 Redis +4. 一旦 Redis 中的数据达到 128KB,就将数据刷新到持久性存储(对象存储或数据库). +5. 重复上述步骤,直到作业完成. +6. 作业完成后,GitLab 会安排 Sidekiq 工作人员存档日志. +7. Sidekiq worker 将日志归档到对象存储,并在 Redis 和永久存储(对象存储或数据库)中清除日志. + +### Enabling incremental logging[](#enabling-incremental-logging "Permalink") + +在 Rails 控制台中将发出以下命令: + +``` +# Omnibus GitLab +gitlab-rails console + +# Installation from source +cd /home/git/gitlab +sudo -u git -H bin/rails console -e production +``` + +**要检查是否启用了增量日志记录(跟踪):** + +``` +Feature.enabled?(:ci_enable_live_trace) +``` + +**要启用增量日志记录(跟踪):** + +``` +Feature.enable(:ci_enable_live_trace) +``` + +**注意:**过渡期将得到适当处理. 即将到来的日志将使用增量体系结构生成,而正在进行的日志将保留在旧体系结构中,这意味着将不会使用增量体系结构强制重新生成正在进行的日志. + +**要禁用增量日志记录(跟踪):** + +``` +Feature.disable('ci_enable_live_trace') +``` + +**注意:**过渡期将得到适当处理. 即将发生的日志将使用旧体系结构生成,而持续的增量日志将保留在增量体系结构中,这意味着持续的增量日志将不会用旧体系结构强制重新生成. + +### Potential implications[](#potential-implications "Permalink") + +在某些情况下,将数据存储在 Redis 上可能会导致数据丢失: + +1. **情况 1:Redis 中的所有数据被意外刷新** + * 可以通过重新发送日志来恢复增量日志(所有版本的 GitLab Runner 均支持此功能). + * 未归档增量日志的已完成作业将丢失日志数据的最后一部分(〜128KB). +2. **情况 2:当 Sidekiq 工作人员无法归档时(例如,存在一个阻止归档过程,Sidekiq 不一致等的错误)** + * 当前,Redis 中的所有日志数据将在一周后删除. 如果 Sidekiq 工作人员无法在到期日之前完成操作,则部分日志数据将丢失. + +可能出现的另一个问题是,它可能会消耗 Redis 实例上的所有内存. 如果作业数为 1000,则将消耗 128MB(128KB * 1000). + +而且,它可能会给数据库复制带来压力. 生成`INSERT`以表明我们有日志块. 一旦我们收到多个数据块,便发出具有 128KB 数据的`UPDATE` . \ No newline at end of file diff --git a/_book/docs/450.md b/_book/docs/450.md new file mode 100644 index 0000000000000000000000000000000000000000..efa003a63025b768348f45bc8bfc1439fb1869f8 --- /dev/null +++ b/_book/docs/450.md @@ -0,0 +1,15 @@ +# Labels administration + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/labels.html](https://docs.gitlab.com/ee/user/admin_area/labels.html) + +* [Default Labels](#default-labels) + +# Labels administration[](#labels-administration-core-only "Permalink") + +在管理区域中,您可以管理 GitLab 实例的标签. 有关更多详细信息,请参见[标签](../project/labels.html) . + +## Default Labels[](#default-labels "Permalink") + +在管理区域中创建的标签可用于每个*新*项目. + +[![Default label set](img/ba294e1cb39daadf43b81f113e5ef506.png)](img/admin_labels.png) \ No newline at end of file diff --git a/_book/docs/451.md b/_book/docs/451.md new file mode 100644 index 0000000000000000000000000000000000000000..a60fe847cafadd36b208a2ea699059a04f98eef4 --- /dev/null +++ b/_book/docs/451.md @@ -0,0 +1,588 @@ +# Log system + +> 原文:[https://docs.gitlab.com/ee/administration/logs.html](https://docs.gitlab.com/ee/administration/logs.html) + +* [`production_json.log`](#production_jsonlog) +* [`production.log`](#productionlog) +* [`api_json.log`](#api_jsonlog) +* [`application.log`](#applicationlog) +* [`application_json.log`](#application_jsonlog) +* [`integrations_json.log`](#integrations_jsonlog) +* [`kubernetes.log`](#kuberneteslog) +* [`git_json.log`](#git_jsonlog) +* [`audit_json.log`](#audit_jsonlog) +* [Sidekiq Logs](#sidekiq-logs) + * [`sidekiq.log`](#sidekiqlog) + * [`sidekiq_client.log`](#sidekiq_clientlog) +* [`gitlab-shell.log`](#gitlab-shelllog) + * [For GitLab versions 12.10 and up](#for-gitlab-versions-1210-and-up) + * [For GitLab versions 12.5 through 12.9](#for-gitlab-versions-125-through-129) + * [For GitLab 12.5 and earlier](#for-gitlab-125-and-earlier) +* [Gitaly Logs](#gitaly-logs) + * [`grpc.log`](#grpclog) +* [Puma Logs](#puma-logs) + * [`puma_stdout.log`](#puma_stdoutlog) + * [`puma_stderr.log`](#puma_stderrlog) +* [Unicorn Logs](#unicorn-logs) + * [`unicorn_stdout.log`](#unicorn_stdoutlog) + * [`unicorn_stderr.log`](#unicorn_stderrlog) +* [`repocheck.log`](#repochecklog) +* [`importer.log`](#importerlog) +* [`exporter.log`](#exporterlog) +* [`auth.log`](#authlog) +* [`graphql_json.log`](#graphql_jsonlog) +* [`migrations.log`](#migrationslog) +* [`mail_room_json.log` (default)](#mail_room_jsonlog-default) +* [Reconfigure Logs](#reconfigure-logs) +* [`sidekiq_exporter.log` and `web_exporter.log`](#sidekiq_exporterlog-and-web_exporterlog) +* [`database_load_balancing.log`](#database_load_balancinglog-premium-only) +* [`elasticsearch.log`](#elasticsearchlog-starter-only) +* [`exceptions_json.log`](#exceptions_jsonlog) +* [`service_measurement.log`](#service_measurementlog) +* [`geo.log`](#geolog-premium-only) +* [Registry Logs](#registry-logs) +* [NGINX Logs](#nginx-logs) +* [Pages Logs](#pages-logs) +* [Mattermost Logs](#mattermost-logs) +* [Workhorse Logs](#workhorse-logs) +* [PostgreSQL Logs](#postgresql-logs) +* [Prometheus Logs](#prometheus-logs) +* [Redis Logs](#redis-logs) +* [Alertmanager Logs](#alertmanager-logs) +* [Crond Logs](#crond-logs) +* [Grafana Logs](#grafana-logs) +* [LogRotate Logs](#logrotate-logs) +* [GitLab Monitor Logs](#gitlab-monitor-logs) +* [GitLab Exporter](#gitlab-exporter) + +# Log system[](#log-system "Permalink") + +GitLab 具有一个高级日志系统,可以记录所有内容,因此您可以使用各种系统日志文件分析实例. 除了系统日志文件,GitLab 企业版还提供审核事件. [在审核事件文档中](audit_events.html)找到有关它们的更多信息. + +系统日志文件通常是标准日志文件格式的纯文本. 本指南讨论如何读取和使用这些系统日志文件. + +## `production_json.log`[](#production_jsonlog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/production_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/production_json.log`中. 当 GitLab 在生产环境以外的环境中运行时,此处将显示相应的日志文件. + +由于[Lograge](https://github.com/roidrage/lograge/) ,它包含从 GitLab 接收到的 Rails 控制器请求的结构化日志. 请注意,来自 API 的请求将记录到`api_json.log`的单独文件中. + +每行包含一个可以由 Elasticsearch 和 Splunk 之类的服务提取的 JSON 行. 为了便于阅读,在示例中添加了换行符: + +``` +{ "method":"GET", "path":"/gitlab/gitlab-foss/issues/1234", "format":"html", "controller":"Projects::IssuesController", "action":"show", "status":200, "time":"2017-08-08T20:15:54.821Z", "params":[{"key":"param_key","value":"param_value"}], "remote_ip":"18.245.0.1", "user_id":1, "username":"admin", "queue_duration_s":0.0, "gitaly_calls":16, "gitaly_duration_s":0.16, "redis_calls":115, "redis_duration_s":0.13, "redis_read_bytes":1507378, "redis_write_bytes":2920, "correlation_id":"O1SdybnnIq7", "cpu_s":17.50, "db_duration_s":0.08, "view_duration_s":2.39, "duration_s":20.54 } +``` + +此示例是针对特定问题的 GET 请求. 每行还包含性能数据,时间以秒为单位: + +1. `duration_s` :检索请求所花费的总时间 +2. `queue_duration_s` :请求在 GitLab Workhorse 中排队的总时间 +3. `view_duration_s` :在 Rails 视图中`view_duration_s`总时间 +4. `db_duration_s` :从 PostgreSQL 检索数据的总时间 +5. `cpu_s` :在 CPU 上花费的总时间 +6. `gitaly_duration_s` :Gitaly 调用花费的总时间 +7. `gitaly_calls` :拨打 Gitaly 的电话总数 +8. `redis_calls` :对 Redis 的呼叫总数 +9. `redis_duration_s` :从 Redis 检索数据的总时间 +10. `redis_read_bytes` :从 Redis 读取的总字节 +11. `redis_write_bytes` :写入 Redis 的总字节数 +12. `redis__calls`: total number of calls made to a Redis instance +13. `redis__duration_s` :从 Redis 实例检索数据的总时间 +14. `redis__read_bytes` :从 Redis 实例读取的总字节数 +15. `redis__write_bytes` :写入 Redis 实例的总字节数 + +使用 HTTP 传输的用户克隆和获取活动作为`action: git_upload_pack`出现在此日志中`action: git_upload_pack` . + +此外,日志还包含原始 IP 地址( `remote_ip` ),用户 ID( `user_id` )和用户名( `username` ). + +如果使用[Advanced Global Search,](../user/search/advanced_global_search.html)则某些端点(例如`/search`可能会向 Elasticsearch 发出请求. 这些将另外记录`elasticsearch_calls`和`elasticsearch_call_duration_s` ,它们对应于: + +1. `elasticsearch_calls` :对 Elasticsearch 的调用总数 +2. `elasticsearch_duration_s` :Elasticsearch 调用花费的总时间 + +ActionCable 连接和订阅事件也记录到此文件中,它们遵循上面相同的格式. `method` , `path`和`format`字段不适用,并且始终为空. ActionCable 连接或通道类用作`controller` . + +``` +{ "method":{}, "path":{}, "format":{}, "controller":"IssuesChannel", "action":"subscribe", "status":200, "time":"2020-05-14T19:46:22.008Z", "params":[{"key":"project_path","value":"gitlab/gitlab-foss"},{"key":"iid","value":"1"}], "remote_ip":"127.0.0.1", "user_id":1, "username":"admin", "ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:76.0) Gecko/20100101 Firefox/76.0", "correlation_id":"jSOIEynHCUa", "duration_s":0.32566 } +``` + +**注意:**从 GitLab 12.5 开始,如果发生错误,则`class` , `message`和`backtrace`包含一个`exception`字段. 以前的版本包含一个`error`字段,而不是`exception.class`和`exception.message` . 例如: + +``` +{ "method": "GET", "path": "/admin", "format": "html", "controller": "Admin::DashboardController", "action": "index", "status": 500, "time": "2019-11-14T13:12:46.156Z", "params": [], "remote_ip": "127.0.0.1", "user_id": 1, "username": "root", "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:70.0) Gecko/20100101 Firefox/70.0", "queue_duration": 274.35, "correlation_id": "KjDVUhNvvV3", "queue_duration_s":0.0, "gitaly_calls":16, "gitaly_duration_s":0.16, "redis_calls":115, "redis_duration_s":0.13, "correlation_id":"O1SdybnnIq7", "cpu_s":17.50, "db_duration_s":0.08, "view_duration_s":2.39, "duration_s":20.54 "exception.class": "NameError", "exception.message": "undefined local variable or method `adsf' for #", "exception.backtrace": [ "app/controllers/admin/dashboard_controller.rb:11:in `index'", "ee/app/controllers/ee/admin/dashboard_controller.rb:14:in `index'", "ee/lib/gitlab/ip_address_state.rb:10:in `with'", "ee/app/controllers/ee/application_controller.rb:43:in `set_current_ip_address'", "lib/gitlab/session.rb:11:in `with_session'", "app/controllers/application_controller.rb:450:in `set_session_storage'", "app/controllers/application_controller.rb:444:in `set_locale'", "ee/lib/gitlab/jira/middleware.rb:19:in `call'" ] } +``` + +## `production.log`[](#productionlog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/production.log` ,对于从源代码进行安装,该文件位于`/home/git/gitlab/log/production.log`中. (当 GitLab 在生产环境以外的环境中运行时,此处将显示相应的日志文件.) + +它包含有关所有已执行请求的信息. 您可以查看 URL 和请求类型,IP 地址,以及涉及哪些代码部分来满足此特定请求. 此外,您还可以查看所有执行的 SQL 请求以及每个请求花费的时间. 对于 GitLab 贡献者和开发人员来说,此任务更有用. 报告错误时,请使用此日志文件的一部分. 例如: + +``` +Started GET "/gitlabhq/yaml_db/tree/master" for 168.111.56.1 at 2015-02-12 19:34:53 +0200 +Processing by Projects::TreeController#show as HTML + Parameters: {"project_id"=>"gitlabhq/yaml_db", "id"=>"master"} + + ... [CUT OUT] + + Namespaces"."created_at" DESC, "namespaces"."id" DESC LIMIT 1 [["id", 26]] + CACHE (0.0ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $1 AND "members"."source_type" = $2 AND "members"."user_id" = 1 ORDER BY "members"."created_at" DESC, "members"."id" DESC LIMIT 1 [["source_id", 18], ["source_type", "Project"]] + CACHE (0.0ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members". + (1.4ms) SELECT COUNT(*) FROM "merge_requests" WHERE "merge_requests"."target_project_id" = $1 AND ("merge_requests"."state" IN ('opened','reopened')) [["target_project_id", 18]] + Rendered layouts/nav/_project.html.haml (28.0ms) + Rendered layouts/_collapse_button.html.haml (0.2ms) + Rendered layouts/_flash.html.haml (0.1ms) + Rendered layouts/_page.html.haml (32.9ms) +Completed 200 OK in 166ms (Views: 117.4ms | ActiveRecord: 27.2ms) +``` + +在此示例中,服务器在`2015-02-12 19:34:53 +0200`处处理了来自 IP `168.111.56.1` URL `/gitlabhq/yaml_db/tree/master`的 HTTP 请求. 该请求已由`Projects::TreeController` . + +## `api_json.log`[](#api_jsonlog "Permalink") + +在 GitLab 10.0 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/api_json.log`中,对于从源代码进行安装则位于`/home/git/gitlab/log/api_json.log`中. + +它可以帮助您查看直接向 API 发出的请求. 例如: + +``` +{ "time":"2018-10-29T12:49:42.123Z", "severity":"INFO", "duration":709.08, "db":14.59, "view":694.49, "status":200, "method":"GET", "path":"/api/v4/projects", "params":[{"key":"action","value":"git-upload-pack"},{"key":"changes","value":"_any"},{"key":"key_id","value":"secret"},{"key":"secret_token","value":"[FILTERED]"}], "host":"localhost", "remote_ip":"::1", "ua":"Ruby", "route":"/api/:version/projects", "user_id":1, "username":"root", "queue_duration":100.31, "gitaly_calls":30, "gitaly_duration":5.36 } +``` + +此项显示一个内部端点,该端点被访问以检查关联的 SSH 密钥是否可以通过`git fetch`或`git clone`下载有问题的项目. 在此示例中,我们看到: + +1. `duration` :检索请求所花费的总时间(以毫秒为单位) +2. `queue_duration` :请求在 GitLab Workhorse 中排队的总时间(以毫秒为单位) +3. `method` :用于发出请求的 HTTP 方法 +4. `path` :查询的相对路径 +5. `params` :在查询字符串或 HTTP 正文中传递的键/值对. 敏感参数(例如密码和令牌)被过滤掉. +6. `ua` :请求者的用户代理 + +## `application.log`[](#applicationlog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/application.log` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/application.log`中. + +它可以帮助您发现实例中发生的事件,例如用户创建,项目删除等. 例如: + +``` +October 06, 2014 11:56: User "Administrator" (admin@example.com) was created +October 06, 2014 11:56: Documentcloud created a new project "Documentcloud / Underscore" +October 06, 2014 11:56: Gitlab Org created a new project "Gitlab Org / Gitlab Ce" +October 07, 2014 11:25: User "Claudie Hodkiewicz" (nasir_stehr@olson.co.uk) was removed +October 07, 2014 11:25: Project "project133" was removed +``` + +## `application_json.log`[](#application_jsonlog "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22812) . + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/application_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/application_json.log`中. + +它包含`application.log`日志的 JSON 版本,如下例所示: + +``` +{ "severity":"INFO", "time":"2020-01-14T13:35:15.466Z", "correlation_id":"3823a1550b64417f9c9ed8ee0f48087e", "message":"User \"Administrator\" (admin@example.com) was created" } { "severity":"INFO", "time":"2020-01-14T13:35:15.466Z", "correlation_id":"78e3df10c9a18745243d524540bd5be4", "message":"Project \"project133\" was removed" } +``` + +## `integrations_json.log`[](#integrations_jsonlog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/integrations_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/integrations_json.log`中. + +它包含有关[集成](../user/project/integrations/overview.html)活动的信息,例如 Jira,Asana 和 Irker 服务. 它使用 JSON 格式,如下例所示: + +``` +{ "severity":"ERROR", "time":"2018-09-06T14:56:20.439Z", "service_class":"JiraService", "project_id":8, "project_path":"h5bp/html5-boilerplate", "message":"Error sending message", "client_url":"http://jira.gitlap.com:8080", "error":"execution expired" } { "severity":"INFO", "time":"2018-09-06T17:15:16.365Z", "service_class":"JiraService", "project_id":3, "project_path":"namespace2/project2", "message":"Successfully posted", "client_url":"http://jira.example.com" } +``` + +## `kubernetes.log`[](#kuberneteslog "Permalink") + +在 GitLab 11.6 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/kubernetes.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/kubernetes.log`中. + +它记录与 Kubernetes 集成相关的信息,包括在托管的 Kubernetes 集群上安装集群应用程序期间的错误. + +每行包含一个可以由 Elasticsearch 和 Splunk 之类的服务提取的 JSON 行. 为了清楚起见,在以下示例中添加了换行符: + +``` +{ "severity":"ERROR", "time":"2018-11-23T15:14:54.652Z", "exception":"Kubeclient::HttpError", "error_code":401, "service":"Clusters::Applications::CheckInstallationProgressService", "app_id":14, "project_ids":[1], "group_ids":[], "message":"Unauthorized" } { "severity":"ERROR", "time":"2018-11-23T15:42:11.647Z", "exception":"Kubeclient::HttpError", "error_code":null, "service":"Clusters::Applications::InstallService", "app_id":2, "project_ids":[19], "group_ids":[], "message":"SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)" } +``` + +## `git_json.log`[](#git_jsonlog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/git_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/git_json.log`中. + +**注意:**在 12.2 之后,此文件从`githost.log`重命名为`git_json.log`并以 JSON 格式存储. + +GitLab 必须与 Git 存储库进行交互,但是在极少数情况下可能会出问题,在这种情况下,您可能需要知道到底发生了什么. 该日志文件包含从 GitLab 到 Git 存储库的所有失败请求. 在大多数情况下,此文件仅对开发人员有用. 例如: + +``` +{ "severity":"ERROR", "time":"2019-07-19T22:16:12.528Z", "correlation_id":"FeGxww5Hj64", "message":"Command failed [1]: /usr/bin/git --git-dir=/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/group184/gitlabhq/.git --work-tree=/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/group184/gitlabhq merge --no-ff -mMerge branch 'feature_conflict' into 'feature' source/feature_conflict\n\nerror: failed to push some refs to '/Users/vsizov/gitlab-development-kit/repositories/gitlabhq/gitlab_git.git'" } +``` + +## `audit_json.log`[](#audit_jsonlog "Permalink") + +**注意:**大多数日志条目仅存在于[GitLab Starter 中](https://about.gitlab.com/pricing/) ,而少数存在于 GitLab Core 中. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/audit_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/audit_json.log`中. + +组或项目设置的更改将记录到该文件中. 例如: + +``` +{ "severity":"INFO", "time":"2018-10-17T17:38:22.523Z", "author_id":3, "entity_id":2, "entity_type":"Project", "change":"visibility", "from":"Private", "to":"Public", "author_name":"John Doe4", "target_id":2, "target_type":"Project", "target_details":"namespace2/project2" } +``` + +## Sidekiq Logs[](#sidekiq-logs "Permalink") + +对于 Omnibus 安装,一些 Sidekiq 日志位于`/var/log/gitlab/sidekiq/current` ,如下所示. + +### `sidekiq.log`[](#sidekiqlog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/sidekiq.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/sidekiq.log`中. + +GitLab 使用后台作业来处理可能需要很长时间的任务. 有关处理这些作业的所有信息都记录到该文件中. 例如: + +``` +2014-06-10T07:55:20Z 2037 TID-tm504 ERROR: /opt/bitnami/apps/discourse/htdocs/vendor/bundle/ruby/1.9.1/gems/redis-3.0.7/lib/redis/client.rb:228:in `read' +2014-06-10T18:18:26Z 14299 TID-55uqo INFO: Booting Sidekiq 3.0.0 with redis options {:url=>"redis://localhost:6379/0", :namespace=>"sidekiq"} +``` + +除了上面的格式,您可以选择为 Sidekiq 生成 JSON 日志. 例如: + +``` +{ "severity":"INFO", "time":"2018-04-03T22:57:22.071Z", "queue":"cronjob:update_all_mirrors", "args":[], "class":"UpdateAllMirrorsWorker", "retry":false, "queue_namespace":"cronjob", "jid":"06aeaa3b0aadacf9981f368e", "created_at":"2018-04-03T22:57:21.930Z", "enqueued_at":"2018-04-03T22:57:21.931Z", "pid":10077, "message":"UpdateAllMirrorsWorker JID-06aeaa3b0aadacf9981f368e: done: 0.139 sec", "job_status":"done", "duration":0.139, "completed_at":"2018-04-03T22:57:22.071Z", "db_duration":0.05, "db_duration_s":0.0005, "gitaly_duration":0, "gitaly_calls":0 } +``` + +对于 Omnibus GitLab 安装,请添加配置选项: + +``` +sidekiq['log_format'] = 'json' +``` + +对于源代码安装,请编辑`gitlab.yml`并设置 Sidekiq `log_format`配置选项: + +``` + ## Sidekiq + sidekiq: + log_format: json +``` + +### `sidekiq_client.log`[](#sidekiq_clientlog "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26586) . + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/sidekiq_client.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/sidekiq_client.log`中. + +该文件包含有关 Sidekiq 开始处理作业之前(例如,入队前)的日志信息. + +该日志文件采用与[`sidekiq.log`](#sidekiqlog)相同的结构,因此,如果您如上所述为 Sidekiq 配置了此文件,则该文件将构造为 JSON. + +## `gitlab-shell.log`[](#gitlab-shelllog "Permalink") + +GitLab 使用 GitLab Shell 执行 Git 命令,并提供对 Git 存储库的 SSH 访问. + +### For GitLab versions 12.10 and up[](#for-gitlab-versions-1210-and-up "Permalink") + +对于 GitLab 版本 12.10 和更高版本,有 2 个`gitlab-shell.log`文件. 包含`git-{upload-pack,receive-pack}`请求的信息位于`/var/log/gitlab/gitlab-shell/gitlab-shell.log` . 来自 Gitaly 的与 GitLab Shell 挂钩的信息位于`/var/log/gitlab/gitaly/gitlab-shell.log` . + +`/var/log/gitlab/gitlab-shell/gitlab-shell.log`示例日志条目: + +``` +{ "duration_ms": 74.104, "level": "info", "method": "POST", "msg": "Finished HTTP request", "time": "2020-04-17T20:28:46Z", "url": "http://127.0.0.1:8080/api/v4/internal/allowed" } { "command": "git-upload-pack", "git_protocol": "", "gl_project_path": "root/example", "gl_repository": "project-1", "level": "info", "msg": "executing git command", "time": "2020-04-17T20:28:46Z", "user_id": "user-1", "username": "root" } +``` + +`/var/log/gitlab/gitaly/gitlab-shell.log`示例日志条目: + +``` +{ "method": "POST", "url": "http://127.0.0.1:8080/api/v4/internal/allowed", "duration": 0.058012959, "gitaly_embedded": true, "pid": 16636, "level": "info", "msg": "finished HTTP request", "time": "2020-04-17T20:29:08+00:00" } { "method": "POST", "url": "http://127.0.0.1:8080/api/v4/internal/pre_receive", "duration": 0.031022552, "gitaly_embedded": true, "pid": 16636, "level": "info", "msg": "finished HTTP request", "time": "2020-04-17T20:29:08+00:00" } +``` + +### For GitLab versions 12.5 through 12.9[](#for-gitlab-versions-125-through-129 "Permalink") + +对于 GitLab 12.5 至 12.9,对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitaly/gitlab-shell.log` ,对于从源代码进行安装则位于`/home/git/gitaly/gitlab-shell.log`中. + +Example log entries: + +``` +{ "method": "POST", "url": "http://127.0.0.1:8080/api/v4/internal/post_receive", "duration": 0.031809164, "gitaly_embedded": true, "pid": 27056, "level": "info", "msg": "finished HTTP request", "time": "2020-04-17T16:24:38+00:00" } +``` + +### For GitLab 12.5 and earlier[](#for-gitlab-125-and-earlier "Permalink") + +对于 GitLab 12.5 和更早版本,该文件位于`/var/log/gitlab/gitlab-shell/gitlab-shell.log` . + +示例日志条目: + +``` +I, [2015-02-13T06:17:00.671315 #9291] INFO -- : Adding project root/example.git at . +I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory and symlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git. +``` + +`executing git command : worker (pid: 9094) exceeds memory limit (320626688 bytes > 247066940 bytes) +W, [2015-02-13T07:16:01.313000 #9094] WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 9094) alive: 3621 sec (trial 1) +I, [2015-02-13T07:16:01.530733 #9047] INFO -- : reaped # worker=1 +I, [2015-02-13T07:16:01.534501 #13379] INFO -- : worker=1 spawned pid=13379 +I, [2015-02-13T07:16:01.534848 #13379] INFO -- : worker=1 ready +``` + +## `repocheck.log`[](#repochecklog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/repocheck.log` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/repocheck.log`中. + +每当在项目上[运行存储库检查](repository_checks.html)时,它都会记录信息. + +## `importer.log`[](#importerlog "Permalink") + +在 GitLab 11.3 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/importer.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/importer.log`中. + +它记录导入过程的进度. + +## `exporter.log`[](#exporterlog "Permalink") + +在 GitLab 13.1 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/exporter.log` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/exporter.log`中. + +它记录导出过程的进度. + +## `auth.log`[](#authlog "Permalink") + +在 GitLab 12.0 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/auth.log` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/auth.log`中. + +该日志记录: + +* 每当[Rack Attack](../security/rack_attack.html)注册滥用请求时提供的信息. +* 请求超过原始端点上的[速率限制](../user/admin_area/settings/rate_limits_on_raw_endpoints.html) . +* [受保护的路径](../user/admin_area/settings/protected_paths.html)滥用请求. + +**注意:**在 GitLab [12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/29239)和更高版本中,用户 ID 和用户名也会记录在该日志中(如果有). + +## `graphql_json.log`[](#graphql_jsonlog "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/59587) in GitLab 12.0. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/graphql_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/graphql_json.log`中. + +GraphQL 查询记录在该文件中. 例如: + +``` +{"query_string":"query IntrospectionQuery{__schema {queryType { name },mutationType { name }}}...(etc)","variables":{"a":1,"b":2},"complexity":181,"depth":1,"duration_s":7} +``` + +## `migrations.log`[](#migrationslog "Permalink") + +在 GitLab 12.3 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/migrations.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/migrations.log`中. + +## `mail_room_json.log` (default)[](#mail_room_jsonlog-default "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19186) . + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/mailroom/current` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/mail_room_json.log`中. + +这个结构化的日志文件将内部活动记录在`mail_room` gem 中. 它的名称和路径是可配置的,因此名称和路径可能与上面的不匹配. + +## Reconfigure Logs[](#reconfigure-logs "Permalink") + +为 Omnibus GitLab 软件包`/var/log/gitlab/reconfigure`日志文件. 从源安装没有重新配置日志. 每当手动或作为升级的一部分运行`gitlab-ctl reconfigure`时, `gitlab-ctl reconfigure`填充一个重配置日志. + +根据启动重新配置的 UNIX 时间戳记来命名重新配置日志文件,例如`1509705644.log` + +## `sidekiq_exporter.log` and `web_exporter.log`[](#sidekiq_exporterlog-and-web_exporterlog "Permalink") + +如果同时启用了 Prometheus 指标和 Sidekiq 导出器,则 Sidekiq 将启动 Web 服务器并侦听定义的端口(默认值: `8082` ). 对于 Omnibus GitLab 软件包,访问日志将在`/var/log/gitlab/gitlab-rails/sidekiq_exporter.log`中生成,对于从源代码进行的安装,将在`/home/git/gitlab/log/sidekiq_exporter.log`生成. + +如果同时启用了 Prometheus 指标和 Web 导出器,则 Puma / Unicorn 将启动 Web 服务器并侦听定义的端口(默认值: `8083` ). 对于 Omnibus GitLab 软件包,访问日志将在`/var/log/gitlab/gitlab-rails/web_exporter.log`中生成,对于源安装,将在`/home/git/gitlab/log/web_exporter.log`生成. + +## `database_load_balancing.log`[](#database_load_balancinglog-premium-only "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15442) . + +包含 GitLab 的[数据库负载平衡的](database_load_balancing.html)详细信息. 它存储在: + +* `/var/log/gitlab/gitlab-rails/database_load_balancing.log`用于 Omnibus GitLab 软件包. +* `/home/git/gitlab/log/database_load_balancing.log`用于从源代码进行安装. + +## `elasticsearch.log`[](#elasticsearchlog-starter-only "Permalink") + +在 GitLab 12.6 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/elasticsearch.log` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/elasticsearch.log`中. + +它记录与 Elasticsearch Integration 相关的信息,包括在索引或搜索 Elasticsearch 期间发生的错误. + +每行包含一个可以由 Elasticsearch 和 Splunk 之类的服务提取的 JSON 行. 为了清楚起见,在以下示例行中添加了换行符: + +``` +{ "severity":"DEBUG", "time":"2019-10-17T06:23:13.227Z", "correlation_id":null, "message":"redacted_search_result", "class_name":"Milestone", "id":2, "ability":"read_milestone", "current_user_id":2, "query":"project" } +``` + +## `exceptions_json.log`[](#exceptions_jsonlog "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17819) . + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/exceptions_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/exceptions_json.log`中. + +它记录有关`Gitlab::ErrorTracking`跟踪的异常的信息,该信息提供了一种标准且一致的方式来[处理已获救的异常](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/logging.md#exception-handling) . + +每行包含一个可由 Elasticsearch 摄取的 JSON 行. 例如: + +``` +{ "severity": "ERROR", "time": "2019-12-17T11:49:29.485Z", "correlation_id": "AbDVUrrTvM1", "extra.project_id": 55, "extra.relation_key": "milestones", "extra.relation_index": 1, "exception.class": "NoMethodError", "exception.message": "undefined method `strong_memoize' for #", "exception.backtrace": [ "lib/gitlab/import_export/relation_factory.rb:329:in `unique_relation?'", "lib/gitlab/import_export/relation_factory.rb:345:in `find_or_create_object!'" ] } +``` + +## `service_measurement.log`[](#service_measurementlog "Permalink") + +在 GitLab 13.0 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/service_measurement.log` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/service_measurement.log`中. + +它仅包含一个结构化日志,其中包含每个服务执行的度量. 它将包含诸如 SQL 调用数, `execution_time` , `gc_stats`和`memory usage` `gc_stats` . + +例如: + +``` +{ "severity":"INFO", "time":"2020-04-22T16:04:50.691Z","correlation_id":"04f1366e-57a1-45b8-88c1-b00b23dc3616","class":"Projects::ImportExport::ExportService","current_user":"John Doe","project_full_path":"group1/test-export","file_path":"/path/to/archive","gc_stats":{"count":{"before":127,"after":127,"diff":0},"heap_allocated_pages":{"before":10369,"after":10369,"diff":0},"heap_sorted_length":{"before":10369,"after":10369,"diff":0},"heap_allocatable_pages":{"before":0,"after":0,"diff":0},"heap_available_slots":{"before":4226409,"after":4226409,"diff":0},"heap_live_slots":{"before":2542709,"after":2641420,"diff":98711},"heap_free_slots":{"before":1683700,"after":1584989,"diff":-98711},"heap_final_slots":{"before":0,"after":0,"diff":0},"heap_marked_slots":{"before":2542704,"after":2542704,"diff":0},"heap_eden_pages":{"before":10369,"after":10369,"diff":0},"heap_tomb_pages":{"before":0,"after":0,"diff":0},"total_allocated_pages":{"before":10369,"after":10369,"diff":0},"total_freed_pages":{"before":0,"after":0,"diff":0},"total_allocated_objects":{"before":24896308,"after":24995019,"diff":98711},"total_freed_objects":{"before":22353599,"after":22353599,"diff":0},"malloc_increase_bytes":{"before":140032,"after":6650240,"diff":6510208},"malloc_increase_bytes_limit":{"before":25804104,"after":25804104,"diff":0},"minor_gc_count":{"before":94,"after":94,"diff":0},"major_gc_count":{"before":33,"after":33,"diff":0},"remembered_wb_unprotected_objects":{"before":34284,"after":34284,"diff":0},"remembered_wb_unprotected_objects_limit":{"before":68568,"after":68568,"diff":0},"old_objects":{"before":2404725,"after":2404725,"diff":0},"old_objects_limit":{"before":4809450,"after":4809450,"diff":0},"oldmalloc_increase_bytes":{"before":140032,"after":6650240,"diff":6510208},"oldmalloc_increase_bytes_limit":{"before":68537556,"after":68537556,"diff":0}},"time_to_finish":0.12298400001600385,"number_of_sql_calls":70,"memory_usage":"0.0 MiB","label":"process_48616"} +``` + +## `geo.log`[](#geolog-premium-only "Permalink") + +> 在 9.5 中引入. + +Geo 将结构化日志消息存储在`geo.log`文件中. 对于 Omnibus 安装,此文件位于`/var/log/gitlab/gitlab-rails/geo.log` . + +该文件包含有关 Geo 何时尝试同步存储库和文件的信息. 文件中的每一行都包含一个可以提取的单独的 JSON 条目. 例如,Elasticsearch 或 Splunk. + +For example: + +``` +{"severity":"INFO","time":"2017-08-06T05:40:16.104Z","message":"Repository update","project_id":1,"source":"repository","resync_repository":true,"resync_wiki":true,"class":"Gitlab::Geo::LogCursor::Daemon","cursor_delay_s":0.038} +``` + +此消息表明,Geo 检测到项目`1`需要存储库更新. + +## Registry Logs[](#registry-logs "Permalink") + +对于 Omnibus 安装,容器注册表日志位于`/var/log/gitlab/registry/current` . + +## NGINX Logs[](#nginx-logs "Permalink") + +对于 Omnibus 安装,NGINX 日志位于: + +* `/var/log/gitlab/nginx/gitlab_access.log`包含对 GitLab 的请求的日志. +* `/var/log/gitlab/nginx/gitlab_error.log`包含有关 GitLab 的 NGINX 错误的日志. +* `/var/log/gitlab/nginx/gitlab_pages_access.log`包含对 Pages 静态站点的请求的日志. +* `/var/log/gitlab/nginx/gitlab_pages_error.log`包含 Pages 静态站点的 NGINX 错误日志. +* `/var/log/gitlab/nginx/gitlab_registry_access.log`包含对容器注册表进行的请求的日志. +* `/var/log/gitlab/nginx/gitlab_registry_error.log`包含容器注册表的 NGINX 错误日志. +* `/var/log/gitlab/nginx/gitlab_mattermost_access.log`包含对 Mattermost 的请求日志. +* `/var/log/gitlab/nginx/gitlab_mattermost_error.log`包含 Mattermost 的 NGINX 错误日志. + +以下是默认的 GitLab NGINX 访问日志格式: + +``` +$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" +``` + +## Pages Logs[](#pages-logs "Permalink") + +对于 Omnibus 安装,Pages 日志位于`/var/log/gitlab/gitlab-pages/current` . + +例如: + +``` +{ "level": "info", "msg": "GitLab Pages Daemon", "revision": "52b2899", "time": "2020-04-22T17:53:12Z", "version": "1.17.0" } { "level": "info", "msg": "URL: https://gitlab.com/gitlab-org/gitlab-pages", "time": "2020-04-22T17:53:12Z" } { "gid": 998, "in-place": false, "level": "info", "msg": "running the daemon as unprivileged user", "time": "2020-04-22T17:53:12Z", "uid": 998 } +``` + +## Mattermost Logs[](#mattermost-logs "Permalink") + +For Omnibus GitLab installations, Mattermost logs reside in `/var/log/gitlab/mattermost/mattermost.log`. + +## Workhorse Logs[](#workhorse-logs "Permalink") + +对于 Omnibus GitLab 安装,Workhorse 日志位于`/var/log/gitlab/gitlab-workhorse/` . + +## PostgreSQL Logs[](#postgresql-logs "Permalink") + +对于 Omnibus GitLab 安装,PostgreSQL 日志位于`/var/log/gitlab/postgresql/` . + +## Prometheus Logs[](#prometheus-logs "Permalink") + +对于 Omnibus GitLab 安装,Prometheus 日志位于`/var/log/gitlab/prometheus/` . + +## Redis Logs[](#redis-logs "Permalink") + +对于所有安装的 GitLab,它返回的日志位于`/var/log/gitlab/redis/` . + +## Alertmanager Logs[](#alertmanager-logs "Permalink") + +对于 Omnibus GitLab 安装,Alertmanager 日志位于`/var/log/gitlab/alertmanager/` . + +## Crond Logs[](#crond-logs "Permalink") + +对于 Omnibus GitLab 安装,crond 日志位于`/var/log/gitlab/crond/` . + +## Grafana Logs[](#grafana-logs "Permalink") + +对于 Omnibus GitLab 安装,Grafana 日志位于`/var/log/gitlab/grafana/` . + +## LogRotate Logs[](#logrotate-logs "Permalink") + +对于 Omnibus GitLab 安装,logrotate 日志位于`/var/log/gitlab/logrotate/` . + +## GitLab Monitor Logs[](#gitlab-monitor-logs "Permalink") + +对于 Omnibus GitLab 安装,GitLab Monitor 日志位于`/var/log/gitlab/gitlab-monitor/` . + +## GitLab Exporter[](#gitlab-exporter "Permalink") + +对于 Omnibus GitLab 安装,GitLab Exporter 日志位于`/var/log/gitlab/gitlab-exporter/` . \ No newline at end of file diff --git a/_book/docs/452.md b/_book/docs/452.md new file mode 100644 index 0000000000000000000000000000000000000000..e0522df80108620e3f48ac5a8a8b7f723589a0da --- /dev/null +++ b/_book/docs/452.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/administration/auth/README.html](https://docs.gitlab.com/ee/administration/auth/README.html) \ No newline at end of file diff --git a/_book/docs/453.md b/_book/docs/453.md new file mode 100644 index 0000000000000000000000000000000000000000..3afcd0f4097e4f57fd0752944ab411cad6f9d7ef --- /dev/null +++ b/_book/docs/453.md @@ -0,0 +1,186 @@ +# PlantUML & GitLab + +> 原文:[https://docs.gitlab.com/ee/administration/integration/plantuml.html](https://docs.gitlab.com/ee/administration/integration/plantuml.html) + +* [PlantUML Server](#plantuml-server) + * [Docker](#docker) + * [Debian/Ubuntu](#debianubuntu) + * [Making local PlantUML accessible using custom GitLab setup](#making-local-plantuml-accessible-using-custom-gitlab-setup) + * [Security](#security) +* [GitLab](#gitlab) +* [Creating Diagrams](#creating-diagrams) + +# PlantUML & GitLab[](#plantuml--gitlab "Permalink") + +在 GitLab 8.16 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8537) . + +在 GitLab 中启用并配置[PlantUML](https://plantuml.com)集成后,我们便能够在片段,Wiki 和存储库中创建的 AsciiDoc 和 Markdown 文档中创建简单的图表. + +## PlantUML Server[](#plantuml-server "Permalink") + +在 GitLab 中启用 PlantUML 之前; 您需要设置自己的 PlantUML 服务器以生成图表. + +### Docker[](#docker "Permalink") + +使用 Docker,您可以仅运行如下容器: + +``` +docker run -d --name plantuml -p 8080:8080 plantuml/plantuml-server:tomcat +``` + +**PlantUML URL**将是运行容器的服务器的主机名. + +在 Docker 中运行 GitLab 时,它将需要有权访问 PlantUML 容器. 最简单的方法是使用[Docker Compose](https://s0docs0docker0com.icopy.site/compose/) . + +一个简单`docker-compose.yml`文件将是: + +``` +version: "3" +services: + gitlab: + image: 'gitlab/gitlab-ce:12.2.5-ce.0' + environment: + GITLAB_OMNIBUS_CONFIG: | + nginx['custom_gitlab_server_config'] = "location /-/plantuml/ { \n proxy_cache off; \n proxy_pass http://plantuml:8080/; \n}\n" + + plantuml: + image: 'plantuml/plantuml-server:tomcat' + container_name: plantuml +``` + +在这种情况下,可以通过 URL `http://plantuml:8080/`访问 GitLab 的`http://plantuml:8080/` . + +### Debian/Ubuntu[](#debianubuntu "Permalink") + +在使用 Tomcat 的 Debian / Ubuntu 发行版中,安装和配置自己的 PlantUML 服务器非常容易. + +首先,您需要从源代码创建一个`plantuml.war`文件: + +``` +sudo apt-get install graphviz openjdk-8-jdk git-core maven +git clone https://github.com/plantuml/plantuml-server.git +cd plantuml-server +mvn package +``` + +上面的命令序列将生成可以使用 Tomcat 部署的 WAR 文件: + +``` +sudo apt-get install tomcat8 +sudo cp target/plantuml.war /var/lib/tomcat8/webapps/plantuml.war +sudo chown tomcat8:tomcat8 /var/lib/tomcat8/webapps/plantuml.war +sudo service tomcat8 restart +``` + +Tomcat 服务重新启动后,PlantUML 服务将准备就绪,并在端口 8080 上侦听请求: + +``` +http://localhost:8080/plantuml +``` + +您可以通过编辑`/etc/tomcat8/server.xml`文件来更改这些默认值. + +请注意,默认 URL 与使用基于 Docker 的映像时不同,后者在 URL 的根目录中提供服务,而没有相对路径. 相应地调整以下配置. + +### Making local PlantUML accessible using custom GitLab setup[](#making-local-plantuml-accessible-using-custom-gitlab-setup "Permalink") + +PlantUML 服务器在您的服务器上本地运行,因此无法从外部访问. 因此,有必要捕获外部 PlantUML 调用并将其重定向到本地服务器. + +想法是将每次调用`https://gitlab.example.com/-/plantuml/`重定向到本地 PlantUML 服务器`http://plantuml:8080/`或`http://localhost:8080/plantuml/` ,具体取决于您的建立. + +要启用重定向,请在`/etc/gitlab/gitlab.rb`添加以下行: + +``` +# Docker deployment +nginx['custom_gitlab_server_config'] = "location /-/plantuml/ { \n proxy_cache off; \n proxy_pass http://plantuml:8080/; \n}\n" + +# Built from source +nginx['custom_gitlab_server_config'] = "location /-/plantuml { \n rewrite ^/-/(plantuml.*) /$1 break;\n proxy_cache off; \n proxy_pass http://localhost:8080/plantuml; \n}\n" +``` + +要激活更改,请运行以下命令: + +``` +sudo gitlab-ctl reconfigure +``` + +### Security[](#security "Permalink") + +PlantUML 具有允许获取网络资源的功能. + +``` +@startuml +start + ' ... + !include http://localhost/ +stop; +@enduml +``` + +**如果您自行托管 PlantUML 服务器,则应放置网络控件以隔离它.** + +## GitLab[](#gitlab "Permalink") + +您需要从"管理"区域下的"设置"启用 PlantUML 集成. 为此,请使用管理员帐户登录并执行以下操作: + +* 在 GitLab 中,转到**管理区域>设置>集成** . +* 展开**PlantUML**部分. +* Check **启用 PlantUML** checkbox. +* Set the PlantUML instance as `https://gitlab.example.com/-/plantuml/`. + +**注意:**如果使用的是运行 v1.2020.9 及更高版本的 PlantUML 服务器(例如[plantuml.com](https://plantuml.com) ),请设置`PLANTUML_ENCODING`环境变量以启用`deflate`压缩. 在 Omnibus 上,可以在`/etc/gitlab.rb`进行设置: + +``` +gitlab_rails['env'] = { 'PLANTUML_ENCODING' => 'deflate' } +``` + +从 GitLab 13.1 和更高版本开始,PlantUML 集成现在[需要 URL 中的标头前缀](https://github.com/plantuml/plantuml/issues/117#issuecomment-6235450160)来区分不同的编码类型. + +## Creating Diagrams[](#creating-diagrams "Permalink") + +启用并配置 PlantUML 集成后,我们可以开始使用分隔的块向我们的 AsciiDoc 代码片段,Wiki 和存储库添加图表: + +* **Markdown** + + ``` + ```plantuml Bob -> Alice : hello + Alice -> Bob : hi + ``` + ``` + +* **AsciiDoc** + + ``` + [plantuml, format="png", id="myDiagram", width="200px"] + ---- + Bob->Alice : hello + Alice -> Bob : hi + ---- + ``` + +* **reStructuredText** + + ``` + .. plantuml:: + :caption: Caption with **bold** and *italic* + + Bob -> Alice: hello + Alice -> Bob: hi + ``` + + 您也可以使用`uml::`指令与[`sphinxcontrib-plantuml`](https://s0pypi0org.icopy.site/project/sphinxcontrib-plantuml/)兼容,但是请注意,我们目前仅支持`caption`选项. + +上面的块将被转换为 HTML 图像标签,其源指向 PlantUML 实例. 如果已正确配置 PlantUML 服务器,则应呈现一个不错的图而不是块: + +![](img/d19e6203a8567c2d6be7d878dd653654.png) + +在块内,您可以通过 PlantUML 添加任何受支持的图,例如[Sequence](https://plantuml.com/sequence-diagram) , [Use Case](https://plantuml.com/use-case-diagram) , [Class](https://plantuml.com/class-diagram) , [Activity](https://plantuml.com/activity-diagram-legacy) , [Component](https://plantuml.com/component-diagram) , [State](https://plantuml.com/state-diagram)和[Object](https://plantuml.com/object-diagram)图. 您不需要使用 PlantUML 图定界符`@startuml` / `@enduml`因为它们已被 AsciiDoc `plantuml`块替换. + +可以将一些参数添加到 AsciiDoc 块定义中: + +* `format` :可以是`png`或`svg` . 请注意,并非所有浏览器都支持`svg` ,因此请谨慎使用. 默认值为`png` . +* `id` :添加到图 HTML 标记的 CSS ID. +* `width` :宽度属性添加到图像标签. +* `height` :高度属性添加到图像标签. + +Markdown 不支持任何参数,并且将始终使用 PNG 格式. \ No newline at end of file diff --git a/_book/docs/454.md b/_book/docs/454.md new file mode 100644 index 0000000000000000000000000000000000000000..a3b0da4f102e701d5ab7eb7f39fab6b2457959bc --- /dev/null +++ b/_book/docs/454.md @@ -0,0 +1,32 @@ +# Repository checks + +> 原文:[https://docs.gitlab.com/ee/administration/repository_checks.html](https://docs.gitlab.com/ee/administration/repository_checks.html) + +* [Periodic checks](#periodic-checks) +* [Disabling periodic checks](#disabling-periodic-checks) +* [What to do if a check failed](#what-to-do-if-a-check-failed) + +# Repository checks[](#repository-checks "Permalink") + +在 GitLab 8.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3232) . + +Git 具有内置机制[`git fsck`](https://git-scm.com/docs/git-fsck) ,以验证提交到存储库的所有数据的完整性. GitLab 管理员可以通过管理面板下的项目页面触发对项目的检查. 由于检查是异步进行的,因此可能需要几分钟才能在项目管理页面上看到检查结果. 如果检查失败,则可以在[`repocheck.log`文件中](logs.html#repochecklog)看到其输出[.](logs.html#repochecklog) + +**注意:**默认情况下为 OFF,因为它仍然会导致过多的错误警报. + +## Periodic checks[](#periodic-checks "Permalink") + +启用后,GitLab 会定期在所有项目存储库和 Wiki 存储库上运行存储库检查,以检测数据损坏. 一个项目每月检查不超过一次. 如果任何项目未能通过其存储库检查,则所有 GitLab 管理员都将收到有关情况的电子邮件通知. 默认情况下,该通知每周一次发送,默认为星期日开始的午夜. 可以在`/admin/projects?last_repository_check_failed=1`找到具有已知检查失败的存储库. + +## Disabling periodic checks[](#disabling-periodic-checks "Permalink") + +You can disable the periodic checks on the ‘Settings’ page of the admin panel. + +## What to do if a check failed[](#what-to-do-if-a-check-failed "Permalink") + +如果某个存储库的存储库检查失败,则应在磁盘上的[`repocheck.log`文件中](logs.html#repochecklog)查找错误: + +* `/var/log/gitlab/gitlab-rails`用于所有安装 +* `/home/git/gitlab/log`用于从源代码进行安装 + +如果定期的存储库检查导致错误警报,则可以通过导航到" **管理区域">"设置">"存储库"** ( `/admin/application_settings/repository` )并单击" **清除所有存储库检查"**来**清除所有存储库检查状态** . \ No newline at end of file diff --git a/_book/docs/455.md b/_book/docs/455.md new file mode 100644 index 0000000000000000000000000000000000000000..115cfc9cc238c7a3b0fa16679e2939271f5b7e80 --- /dev/null +++ b/_book/docs/455.md @@ -0,0 +1,94 @@ +# Repository storage paths + +> 原文:[https://docs.gitlab.com/ee/administration/repository_storage_paths.html](https://docs.gitlab.com/ee/administration/repository_storage_paths.html) + +* [Configure GitLab](#configure-gitlab) +* [Choose where new repositories will be stored](#choose-where-new-repositories-will-be-stored) + +# Repository storage paths[](#repository-storage-paths "Permalink") + +在 GitLab 8.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4578) . + +GitLab 允许您定义多个存储库存储路径(有时称为存储碎片),以在多个安装点之间分配存储负载. + +> **Notes:** +> +> * 您必须至少有一个名为`default`存储路径. +> * 路径在键值对中定义. 密钥是一个任意名称,您可以选择该名称来命名文件路径. +> * 目标目录及其任何子路径不得为符号链接. +> * 目标目录不能是另一个目录的子目录. 没有嵌套. + +示例:这可以: + +``` +default: + path: /mnt/git-storage-1 +storage2: + path: /mnt/git-storage-2 +``` + +这不行,因为它嵌套了存储路径: + +``` +default: + path: /mnt/git-storage-1 +storage2: + path: /mnt/git-storage-1/git-storage-2 # <- NOT OK because of nesting +``` + +## Configure GitLab[](#configure-gitlab "Permalink") + +> **警告:**为了使[备份](../raketasks/backup_restore.html)正常工作,存储路径**不得**为挂载点,并且 GitLab 用户应对该路径的父目录具有正确的权限. 在 Omnibus GitLab 中,这是自动处理的,但是对于源代码安装,您应该格外小心. +> +> 事实是,出于兼容性原因, `gitlab.yml`与 Omnibus 具有不同的结构. 在`gitlab.yml`您指示存储库的路径,例如`/home/git/repositories` ,而在 Omnibus 中,您指示`git_data_dirs` ,对于上面的示例,它是`/home/git` . 然后,Omnibus 将在该路径下创建一个`repositories`目录,以与`gitlab.yml`一起使用. +> +> 这个小细节很重要,因为在还原备份时, `/home/git/repositories`的当前内容[已移至](https://gitlab.com/gitlab-org/gitlab/blob/033e5423a2594e08a7ebcd2379bd2331f4c39032/lib/backup/repository.rb#L54-56) `/home/git/repositories.old` ,因此,如果`/home/git/repositories`是安装点,则`mv`会移动挂载点之间发生故障,并且可能发生不良情况. 理想情况下, `/home/git`是挂载点,因此事情将在同一挂载点内移动. Omnibus 安装可以保证这一点(因为它们没有指定完整的存储库路径,而是指定父路径),但对于源安装则没有保证. + +现在,您已经阅读了上面的警告提示,让我们编辑配置文件并添加备用存储库存储路径的完整路径. 在下面的示例中,我们添加了另外两个挂载点,分别称为`nfs_1`和`nfs_2` . + +**Note:** This example uses NFS. We do not recommend using EFS for storage as it may impact GitLab’s performance. See the [relevant documentation](high_availability/nfs.html#avoid-using-awss-elastic-file-system-efs) for more details. + +**对于源安装** + +1. 编辑`gitlab.yml`并添加存储路径: + + ``` + repositories: + # Paths where repositories can be stored. Give the canonicalized absolute pathname. + # NOTE: REPOS PATHS MUST NOT CONTAIN ANY SYMLINK!!! + storages: # You must have at least a 'default' storage path. + default: + path: /home/git/repositories + nfs_1: + path: /mnt/nfs1/repositories + nfs_2: + path: /mnt/nfs2/repositories + ``` + +2. [重新启动 GitLab,](restart_gitlab.html#installations-from-source)以使更改生效. + +> **注:** [`gitlab_shell: repos_path`条目](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/8-9-stable/config/gitlab.yml.example#L457)中`gitlab.yml`将被弃用,取而代之的是`repositories: storages`在未来,所以如果你是从之前的版本升级 8.10,确保如在上述步骤中所描述的添加配置. 进行更改并确认它们可以使用之后,可以删除`repos_path`行. + +**对于所有安装** + +1. 通过将其余路径附加到默认路径中来编辑`/etc/gitlab/gitlab.rb` : + + ``` + git_data_dirs({ + "default" => { "path" => "/var/opt/gitlab/git-data" }, + "nfs_1" => { "path" => "/mnt/nfs1/git-data" }, + "nfs_2" => { "path" => "/mnt/nfs2/git-data" } + }) + ``` + + 请注意,Omnibus 将存储库存储在`git-data`目录的`repositories`子目录中. + +## Choose where new repositories will be stored[](#choose-where-new-repositories-will-be-stored "Permalink") + +设置了多个存储路径后,您可以在**管理区域>设置>存储库>存储库存储>新存储库的存储节点下选择新存储库的存储位置** . + +可以为每个存储分配 0 到 100 的权重. 创建新项目时,将使用这些权重来确定将在其上创建存储库的存储位置. + +[![Choose repository storage path in Admin Area](img/fc80ee243381890526471d6fc360f7cf.png)](img/repository_storages_admin_ui_v13_1.png) + +从 GitLab 8.13.4 开始,可以选择多个路径. 新存储库将随机放置在所选路径之一上. \ No newline at end of file diff --git a/_book/docs/456.md b/_book/docs/456.md new file mode 100644 index 0000000000000000000000000000000000000000..c33c9b3cfeee5f0ab0e392d0269b5ffd2bc0fed0 --- /dev/null +++ b/_book/docs/456.md @@ -0,0 +1,166 @@ +# Repository storage types + +> 原文:[https://docs.gitlab.com/ee/administration/repository_storage_types.html](https://docs.gitlab.com/ee/administration/repository_storage_types.html) + +* [Hashed storage](#hashed-storage) + * [Translating hashed storage paths](#translating-hashed-storage-paths) + * [From project name to hashed path](#from-project-name-to-hashed-path) + * [From hashed path to project name](#from-hashed-path-to-project-name) + * [Hashed object pools](#hashed-object-pools) + * [Hashed storage coverage migration](#hashed-storage-coverage-migration) + * [Avatars](#avatars) + * [CI artifacts](#ci-artifacts) + * [LFS objects](#lfs-objects) +* [Legacy storage](#legacy-storage) + +# Repository storage types[](#repository-storage-types-core-only "Permalink") + +版本历史 + +* 在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28283) . +* 静默存储已成为 GitLab 12.0 中新安装的默认存储 +* 默认情况下,在 GitLab 13.0 中为新项目和重命名项目启用了哈希存储. + +可以将 GitLab 配置为使用一个或多个存储库存储路径/碎片位置,它们可以是: + +* 挂载到本地磁盘 +* 公开为 NFS 共享卷 +* 在自己的计算机上通过[Gitaly](gitaly/index.html)访问. + +在 GitLab 中,这是通过`git_data_dirs({})`配置哈希值在`/etc/gitlab/gitlab.rb`进行配置的. 此处讨论的存储布局将适用于其中定义的所有分片. + +在未自定义它的任何安装中可用的`default`存储库碎片指向本地文件夹: `/var/opt/gitlab/git-data` . 下面讨论的所有内容都应属于该文件夹. + +## Hashed storage[](#hashed-storage "Permalink") + +**注意:**在 GitLab 13.0 中,默认情况下启用了哈希存储,并且不建议使用旧存储. 在 GitLab 14.0 中将删除对旧存储的支持. 如果您尚未迁移,请查看[迁移说明](raketasks/storage.html#migrate-to-hashed-storage) . 在管理区域中的哈希存储和旧存储之间进行选择的选项已被禁用. + +哈希存储是我们从 10.0 开始推出的存储行为. 与其耦合项目 URL 和将存储库存储在磁盘上的文件夹结构,不如基于项目 ID 耦合散列. 这使得文件夹结构不可变,因此消除了将状态从 URL 同步到磁盘结构的任何要求. 这意味着重命名组,用户或项目将仅花费数据库事务的费用,并且将立即生效. + +哈希还有助于将存储库更均匀地分布在磁盘上,因此顶层目录包含的文件夹少于顶层命名空间的总数. + +哈希格式基于 SHA256 的十六进制表示形式: `SHA256(project.id)` . 顶级文件夹使用前两个字符,然后是另一个文件夹,其后两个字符. 它们都存储在特殊的`@hashed`文件夹中,以便能够与现有的 Legacy Storage 项目共存: + +``` +# Project's repository: +"@hashed/#{hash[0..1]}/#{hash[2..3]}/#{hash}.git" + +# Wiki's repository: +"@hashed/#{hash[0..1]}/#{hash[2..3]}/#{hash}.wiki.git" +``` + +### Translating hashed storage paths[](#translating-hashed-storage-paths "Permalink") + +对 Git 存储库中的问题进行故障排除,添加挂钩和其他任务,将需要您在人类可读的项目名称和哈希存储路径之间进行转换. + +#### From project name to hashed path[](#from-project-name-to-hashed-path "Permalink") + +哈希路径显示在项目页面的[admin 区域中](../user/admin_area/index.html#administering-projects) . + +要访问"项目"页面,请转到" **管理区域">"概述">"项目"** ,然后打开该项目的页面. + +此处显示" Gitaly 相对路径",例如: + +``` +"@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git" +``` + +这是默认 Omnibus 安装中`/var/opt/gitlab/git-data/repositories/`下的路径. + +在[Rails 控制台中](troubleshooting/debug.html#starting-a-rails-console-session) ,使用数字项目 ID 或完整路径获取此信息: + +``` +Project.find(16).disk_path +Project.find_by_full_path('group/project').disk_path +``` + +#### From hashed path to project name[](#from-hashed-path-to-project-name "Permalink") + +要将哈希存储路径转换为项目名称,请执行以下操作: + +1. 启动[Rails 控制台](troubleshooting/debug.html#starting-a-rails-console-session) . +2. 运行以下命令: + +``` +ProjectRepository.find_by(disk_path: '@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9').project +``` + +该命令中带引号的字符串是您在 GitLab 服务器上找到的目录树. 例如,在默认的 Omnibus 安装上,该`.git`将是`/var/opt/gitlab/git-data/repositories/@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git`从目录名称的末尾删除. + +输出包括项目 ID 和项目名称: + +``` +=> # +``` + +### Hashed object pools[](#hashed-object-pools "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitaly/-/issues/1606) . + +**危险:**不要在池存储库中运行`git prune`或`git gc` ! 这可能会导致依赖于相关池的"实际"存储库中的数据丢失. + +通过创建第三个存储库(对象池)对公共项目的分支进行重复数据删除,其中包含来自源项目的对象. 使用`objects/info/alternates` ,源项目和派生将对象池用于共享对象. 当在源项目上运行内务管理时,会将对象从源项目移动到对象池. + +``` +# object pool paths +"@pools/#{hash[0..1]}/#{hash[2..3]}/#{hash}.git" +``` + +### Hashed storage coverage migration[](#hashed-storage-coverage-migration "Permalink") + +如果存储在 S3 兼容端点中的文件没有前缀`#{namespace}/#{project_name}` (对于 CI Cache 和 LFS 对象是正确的`#{namespace}/#{project_name}` ,则不会有前面提到的缺点. + +在下表中,您可以找到迁移到哈希存储的范围. + +| 可存储对象 | 旧版存储 | 杂物箱 | 兼容 S3 | GitLab 版本 | +| --- | --- | --- | --- | --- | +| Repository | Yes | Yes | - | 10.0 | +| Attachments | Yes | Yes | - | 10.2 | +| Avatars | Yes | No | - | - | +| Pages | Yes | No | - | - | +| Docker 注册表 | Yes | No | - | - | +| CI 构建日志 | No | No | - | - | +| CI Artifacts | No | No | Yes | 9.4 / 10.6 | +| CI 缓存 | No | No | Yes | - | +| LFS 对象 | Yes | Similar | Yes | 10.0 / 10.7 | +| 储存库 | No | Yes | - | 11.6 | + +#### Avatars[](#avatars "Permalink") + +每个文件都以其`id`来自数据库的形式存储在一个文件夹中. 用户头像的文件名始终为`avatar.png` . 替换头像后, `Upload`模型将被销毁,并使用另一个`id`进行替换. + +#### CI artifacts[](#ci-artifacts "Permalink") + +CI Artifacts 从**9.4** (GitLab Premium)开始兼容 S3,从**10.6**开始在 GitLab Core 中可用. + +#### LFS objects[](#lfs-objects "Permalink") + +[GitLab 中的 LFS 对象](../topics/git/lfs/index.html)遵循 Git 自己的实现,使用 2 个字符,2 个级别的文件夹实现了类似的存储模式: + +``` +"shared/lfs-objects/#{oid[0..1}/#{oid[2..3]}/#{oid[4..-1]}" + +# Based on object `oid`: `8909029eb962194cfb326259411b22ae3f4a814b5be4f80651735aeef9f3229c`, path will be: +"shared/lfs-objects/89/09/029eb962194cfb326259411b22ae3f4a814b5be4f80651735aeef9f3229c" +``` + +LFS 对象也与[S3 兼容](lfs/index.html#storing-lfs-objects-in-remote-object-storage) . + +## Legacy storage[](#legacy-storage "Permalink") + +**不建议使用:**在 GitLab 13.0 中,默认情况下启用了哈希存储,并且不建议使用旧存储. 如果您尚未迁移,请查看[迁移说明](raketasks/storage.html#migrate-to-hashed-storage) . 在 GitLab 14.0 中将删除对旧存储的支持. 如果您使用的是 GitLab 13.0 及更高版本,则无法将新项目切换到旧版存储. 在管理区域中的哈希存储和旧存储之间进行选择的选项已被禁用. + +旧版存储是 10.0 版之前的存储行为. 由于历史原因,GitLab 从项目 URL 复制了相同的映射结构: + +* 项目的存储库: `#{namespace}/#{project_name}.git` +* 项目的 Wiki: `#{namespace}/#{project_name}.wiki.git` + +这种结构使从现有解决方案到 GitLab 的迁移变得简单,并且管理员可以轻松找到存储库的存储位置. + +On the other hand this has some drawbacks: + +存储位置将集中大量的顶级名称空间. 可以通过引入[多个存储路径](repository_storage_paths.html)来减少影响. + +由于备份是相同 URL 映射的快照,因此,如果您尝试恢复非常旧的备份,则需要验证是否有任何项目代替了共享相同 URL 的旧项目或已重命名的项目. 这意味着您备份中的`mygroup/myproject`可能与今天使用相同 URL 的原始项目不同. + +URL 的任何更改都需要反映在磁盘上(重命名组/用户或项目时). 在大型安装中,这可能会增加很多负载,尤其是在使用任何类型的基于网络的文件系统时. \ No newline at end of file diff --git a/_book/docs/457.md b/_book/docs/457.md new file mode 100644 index 0000000000000000000000000000000000000000..1d3596689adfe40c420088648d525051dfeb75fd --- /dev/null +++ b/_book/docs/457.md @@ -0,0 +1,167 @@ +# Account and limit settings + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/settings/account_and_limit_settings.html](https://docs.gitlab.com/ee/user/admin_area/settings/account_and_limit_settings.html) + +* [Max attachment size](#max-attachment-size) +* [Max import size](#max-import-size) +* [Maximum namespace storage size](#maximum-namespace-storage-size) +* [Repository size limit](#repository-size-limit-starter-only) + * [How it works](#how-it-works) +* [Troubleshooting](#troubleshooting) + * [413 Request Entity Too Large](#413-request-entity-too-large) +* [Limiting lifetime of personal access tokens](#limiting-lifetime-of-personal-access-tokens-ultimate-only) + * [Setting a limit](#setting-a-limit) +* [Optional enforcement of Personal Access Token expiry](#optional-enforcement-of-personal-access-token-expiry-ultimate-only) + * [Enable or disable optional enforcement of Personal Access Token expiry Feature](#enable-or-disable-optional-enforcement-of-personal-access-token-expiry-feature-core-only) +* [Disabling user profile name changes](#disabling-user-profile-name-changes-premium-only) + +# Account and limit settings[](#account-and-limit-settings-core-only "Permalink") + +## Max attachment size[](#max-attachment-size "Permalink") + +您可以在 GitLab 中更改评论和回复中附件的最大文件大小. 导航至**管理区域(扳手图标)>设置>常规** ,然后展开**帐户和限制** . 在此处,您可以通过更改`Maximum attachment size (MB)`的值来增加或减少. + +**注意:**如果选择的大小大于当前为 Web 服务器配置的大小,则可能会出现错误. 有关更多详细信息,请参见[故障排除部分](#troubleshooting) . + +## Max import size[](#max-import-size "Permalink") + +您可以在 GitLab 中更改导入的最大文件大小. 导航至**管理区域(扳手图标)>设置>常规** ,然后展开**帐户和限制** . 在这里,您可以通过更改`Maximum import size (MB)`的值来增加或减少. + +**注意:**如果选择的大小大于当前为 Web 服务器配置的大小,则可能会出现错误. 有关更多详细信息,请参见[故障排除部分](#troubleshooting) . + +## Maximum namespace storage size[](#maximum-namespace-storage-size "Permalink") + +这为每个名称空间设置了最大大小限制. 名称空间大小包括以下内容: + +* repository +* wiki +* LFS 对象 +* 建立工件 +* packages + +**注意:**此限制当前未实施,但将在将来的版本中使用. + +## Repository size limit[](#repository-size-limit-starter-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/740) in [GitLab Enterprise Edition 8.12](https://about.gitlab.com/releases/2016/09/22/gitlab-8-12-released/#limit-project-size-ee). + +GitLab 实例中的存储库可以快速增长,尤其是在使用 LFS 的情况下. 它们的大小可以成倍增长,迅速消耗可用的存储空间. + +为避免这种情况发生,您可以为存储库的大小设置硬限制. 可以在全局,每个组或每个项目中设置此限制,其中每个项目的限制为最高优先级. + +在许多用例中,您可能会设置存储库大小的限制. 例如,考虑以下工作流程: + +1. 您的团队开发的应用程序需要将大文件存储在应用程序存储库中. +2. 尽管您已为项目启用了[Git LFS](../../../topics/git/lfs/index.html#git-large-file-storage-lfs) ,但您的存储量已显着增长. +3. 在超出可用存储空间之前,每个存储库设置的最大限制为 10 GB. + +### How it works[](#how-it-works "Permalink") + +只有 GitLab 管理员才能设置这些限制. 将限制设置为`0`表示没有限制. + +这些设置可以在以下位置找到: + +* 每个项目的设置: + 1. 在项目的主页上,导航至**"设置">"常规"** . + 2. 在" **命名,主题,头像"**部分中填写" **存储库大小限制(MB)"**字段. + 3. 点击**保存更改** . +* 每个组的设置: + 1. 在网上论坛的主页上,导航至**设置>常规** . + 2. 填写" **命名,可见性"**部分中的" **存储库大小限制(MB)"**字段. + 3. 点击**保存更改** . +* GitLab 的全局设置: + 1. 在控制台中,导航至**管理区域>设置>常规** . + 2. 展开**帐户和限制**部分. + 3. 填写**每个存储库**的**大小限制(MB)**字段. + 4. 点击**保存更改** . + +包括 LFS 对象在内的新项目的第一次推送将进行大小检查,如果它们的大小总和超过允许的最大存储库大小, **则将**拒绝该推送. + +**注意:**存储库大小限制包括存储库文件和 LFS,并且不包括工件. + +有关手动清除文件的详细信息,请参阅[使用 Git 减小存储库大小](../../project/repository/reducing_the_repo_size_using_git.html) . + +**注意:** GitLab.com 存储库大小[由 GitLab 设置](../../gitlab_com/index.html#repository-size-limit) . + +## Troubleshooting[](#troubleshooting "Permalink") + +### 413 Request Entity Too Large[](#413-request-entity-too-large "Permalink") + +如果您在 GitLab 中将文件附加到评论或回复并收到`413 Request Entity Too Large`错误,则可能是由于[最大附件大小](#max-attachment-size)大于 Web 服务器配置允许的[最大附件大小](#max-attachment-size)引起的. + +例如,如果要在 GitLab [Omnibus](https://docs.gitlab.com/omnibus/)安装中将最大附件大小增加到 200m,则可能需要在增加最大附件大小之前`/etc/gitlab/gitlab.rb`添加到`/etc/gitlab/gitlab.rb` : + +``` +nginx['client_max_body_size'] = "200m" +``` + +## Limiting lifetime of personal access tokens[](#limiting-lifetime-of-personal-access-tokens-ultimate-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6. + +用户可以选择指定[个人访问令牌](../../profile/personal_access_tokens.html)的到期日期. 该到期日期不是必需的,可以将其设置为任意日期. + +由于个人访问令牌是通过编程访问 GitLab 所需的唯一令牌,因此具有安全性要求的组织可能希望加强保护,以要求定期循环使用这些令牌. + +### Setting a limit[](#setting-a-limit "Permalink") + +只有 GitLab 管理员才能设置限制. 将其保留为空意味着没有任何限制. + +设置有效的个人访问令牌限制: + +1. 导航到**管理区域>设置>常规** . +2. 展开**帐户和限制**部分. +3. Fill in the **个人访问令牌的最大允许生命周期(天)** field. +4. Click **保存更改**. + +一旦设置了个人访问令牌的生存期,GitLab 将: + +* 将生存期应用于新的个人访问令牌,并要求用户设置到期日期,并且日期不得晚于允许的生存期. +* 三个小时后,请吊销没有过期日期或寿命超过允许寿命的旧令牌. 允许三个小时的时间,以便管理员在撤销之前更改或删除允许的生存期. + +## Optional enforcement of Personal Access Token expiry[](#optional-enforcement-of-personal-access-token-expiry-ultimate-only "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214723) . +* 它部署在功能标志后面,默认情况下处于禁用状态. +* 它在 GitLab.com 上被禁用. +* 不建议将其用于生产. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-optional-enforcement-of-personal-access-token-expiry-feature-core-only) . + +GitLab 管理员可以选择防止个人访问令牌自动过期. 令牌将在到期日期之后可用,除非已将其明确吊销. + +去做这个: + +1. 导航到**管理区域>设置>常规** . +2. 展开**帐户和限制**部分. +3. 取消选中" **强制个人访问令牌到期"**复选框. + +### Enable or disable optional enforcement of Personal Access Token expiry Feature[](#enable-or-disable-optional-enforcement-of-personal-access-token-expiry-feature-core-only "Permalink") + +正在开发可选的"强制执行个人访问令牌到期",尚未准备好用于生产. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以从[rails 控制台](../../../administration/feature_flags.html#start-the-gitlab-rails-console)为您的实例启用它. + +要启用它: + +``` +Feature.enable(:enforce_personal_access_token_expiration) +``` + +禁用它: + +``` +Feature.disable(:enforce_personal_access_token_expiration) +``` + +## Disabling user profile name changes[](#disabling-user-profile-name-changes-premium-only "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/24605) . + +为了维护[Audit Events](../../../administration/audit_events.html)中用户详细信息的完整性,GitLab 管理员可以选择禁用用户更改其配置文件名称的功能. + +去做这个: + +1. 导航到" **管理区域">"设置">"常规"** ,然后展开" **帐户和限制"** . +2. 选中**阻止用户更改其个人资料名称**复选框. + +**注意:**禁用此功能后,GitLab 管理员仍将能够通过[管理界面](../index.html#administering-users)或[API](../../../api/users.html#user-modification)更新其实例中任何用户的名称. \ No newline at end of file diff --git a/_book/docs/458.md b/_book/docs/458.md new file mode 100644 index 0000000000000000000000000000000000000000..c8b69dda7a4865c95530910a3aa24699a43c682b --- /dev/null +++ b/_book/docs/458.md @@ -0,0 +1,26 @@ +# Service templates + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/services_templates.html](https://docs.gitlab.com/ee/user/project/integrations/services_templates.html) + +* [Enable a service template](#enable-a-service-template) +* [Service for external issue trackers](#service-for-external-issue-trackers) + +# Service templates[](#service-templates "Permalink") + +使用服务模板,GitLab 管理员可以提供用于在项目级别配置集成的默认值. + +启用服务模板时,默认值将应用于**所有**尚未启用集成或未保存自定义值的项目. 这些值已预先填充在每个项目的配置页面上,以进行适用的集成. + +如果禁用模板,这些值将不再显示为默认值,而已为集成保存的所有值将保持不变. + +## Enable a service template[](#enable-a-service-template "Permalink") + +导航到**管理区域>服务模板,**然后选择要创建的服务模板. + +## Service for external issue trackers[](#service-for-external-issue-trackers "Permalink") + +下图显示了 Redmine 的示例服务模板. + +[![Redmine service template](img/1b109b486c41c14a03eea4127cec2351.png)](img/services_templates_redmine_example.png) + +对于每个项目,您仍然需要通过将上述屏幕快照中的`:issues_tracker_id`替换为外部问题跟踪器使用的 ID 来配置问题跟踪 URL. \ No newline at end of file diff --git a/_book/docs/459.md b/_book/docs/459.md new file mode 100644 index 0000000000000000000000000000000000000000..0ed3ad03b70ad6fe35f434dab848482f5e7732dc --- /dev/null +++ b/_book/docs/459.md @@ -0,0 +1,247 @@ +# System hooks + +> 原文:[https://docs.gitlab.com/ee/system_hooks/system_hooks.html](https://docs.gitlab.com/ee/system_hooks/system_hooks.html) + +* [Hooks request example](#hooks-request-example) +* [Push events](#push-events) +* [Tag events](#tag-events) + * [Merge request events](#merge-request-events) +* [Repository Update events](#repository-update-events) +* [Local requests in system hooks](#local-requests-in-system-hooks) + +# System hooks[](#system-hooks "Permalink") + +您的 GitLab 实例可以对以下事件执行 HTTP POST 请求: + +* `project_create` +* `project_destroy` +* `project_rename` +* `project_transfer` +* `project_update` +* `user_add_to_team` +* `user_remove_from_team` +* `user_update_for_team` +* `user_create` +* `user_destroy` +* `user_failed_login` +* `user_rename` +* `key_create` +* `key_destroy` +* `group_create` +* `group_destroy` +* `group_rename` +* `user_add_to_group` +* `user_remove_from_group` +* `user_update_for_group` + +这些触发器中的大多数触发器是不言自明的,但是应该澄清一下`project_update`和`project_rename` : `project_update`项目的属性(名称,描述,标签等)发生更改,就会随时触发`project_update` , *除非* `path`属性也发生更改. 在这种情况下,将触发`project_rename` (例如,如果您只关心存储库 URL,则可以只监听`project_rename` ). + +每当**被阻止的**用户尝试登录并拒绝访问时,都会发送`user_failed_login` . + +可以使用系统挂钩,例如,用于在 LDAP 服务器中记录或更改信息. + +**注意:**对于 Push 和 Tag 事件,我们采用与[Webhooks](../user/project/integrations/webhooks.html)相同的结构和弃用方式,但是我们从不显示提交. + +## Hooks request example[](#hooks-request-example "Permalink") + +**请求标头**: + +``` +X-Gitlab-Event: System Hook +``` + +**创建的项目:** + +``` +{ "created_at": "2012-07-21T07:30:54Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "project_create", "name": "StoreCloud", "owner_email": "johnsmith@gmail.com", "owner_name": "John Smith", "path": "storecloud", "path_with_namespace": "jsmith/storecloud", "project_id": 74, "project_visibility": "private" } +``` + +**项目已销毁:** + +``` +{ "created_at": "2012-07-21T07:30:58Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "project_destroy", "name": "Underscore", "owner_email": "johnsmith@gmail.com", "owner_name": "John Smith", "path": "underscore", "path_with_namespace": "jsmith/underscore", "project_id": 73, "project_visibility": "internal" } +``` + +**项目更名:** + +``` +{ "created_at": "2012-07-21T07:30:58Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "project_rename", "name": "Underscore", "path": "underscore", "path_with_namespace": "jsmith/underscore", "project_id": 73, "owner_name": "John Smith", "owner_email": "johnsmith@gmail.com", "project_visibility": "internal", "old_path_with_namespace": "jsmith/overscore" } +``` + +请注意,如果命名空间发生更改,则不会触发`project_rename` . 在这种情况下,请参考`group_rename`和`user_rename` . + +**项目转移:** + +``` +{ "created_at": "2012-07-21T07:30:58Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "project_transfer", "name": "Underscore", "path": "underscore", "path_with_namespace": "scores/underscore", "project_id": 73, "owner_name": "John Smith", "owner_email": "johnsmith@gmail.com", "project_visibility": "internal", "old_path_with_namespace": "jsmith/overscore" } +``` + +**项目已更新:** + +``` +{ "created_at": "2012-07-21T07:30:54Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "project_update", "name": "StoreCloud", "owner_email": "johnsmith@gmail.com", "owner_name": "John Smith", "path": "storecloud", "path_with_namespace": "jsmith/storecloud", "project_id": 74, "project_visibility": "private" } +``` + +**新团队成员:** + +``` +{ "created_at": "2012-07-21T07:30:56Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "user_add_to_team", "access_level": "Maintainer", "project_id": 74, "project_name": "StoreCloud", "project_path": "storecloud", "project_path_with_namespace": "jsmith/storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", "user_username": "johnsmith", "user_id": 41, "project_visibility": "visibilitylevel|private" } +``` + +**团队成员已删除:** + +``` +{ "created_at": "2012-07-21T07:30:56Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "user_remove_from_team", "access_level": "Maintainer", "project_id": 74, "project_name": "StoreCloud", "project_path": "storecloud", "project_path_with_namespace": "jsmith/storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", "user_username": "johnsmith", "user_id": 41, "project_visibility": "visibilitylevel|private" } +``` + +**团队成员已更新:** + +``` +{ "created_at": "2012-07-21T07:30:56Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "user_update_for_team", "access_level": "Maintainer", "project_id": 74, "project_name": "StoreCloud", "project_path": "storecloud", "project_path_with_namespace": "jsmith/storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", "user_username": "johnsmith", "user_id": 41, "project_visibility": "visibilitylevel|private" } +``` + +**用户创建:** + +``` +{ "created_at": "2012-07-21T07:44:07Z", "updated_at": "2012-07-21T07:38:22Z", "email": "js@gitlabhq.com", "event_name": "user_create", "name": "John Smith", "username": "js", "user_id": 41 } +``` + +**用户已删除:** + +``` +{ "created_at": "2012-07-21T07:44:07Z", "updated_at": "2012-07-21T07:38:22Z", "email": "js@gitlabhq.com", "event_name": "user_destroy", "name": "John Smith", "username": "js", "user_id": 41 } +``` + +**用户登录失败:** + +``` +{ "event_name": "user_failed_login", "created_at": "2017-10-03T06:08:48Z", "updated_at": "2018-01-15T04:52:06Z", "name": "John Smith", "email": "user4@example.com", "user_id": 26, "username": "user4", "state": "blocked" } +``` + +如果通过 LDAP 阻止了用户,则`state`将为`ldap_blocked` . + +**用户重命名:** + +``` +{ "event_name": "user_rename", "created_at": "2017-11-01T11:21:04Z", "updated_at": "2017-11-01T14:04:47Z", "name": "new-name", "email": "best-email@example.tld", "user_id": 58, "username": "new-exciting-name", "old_username": "old-boring-name" } +``` + +**密钥已添加** + +``` +{ "event_name": "key_create", "created_at": "2014-08-18 18:45:16 UTC", "updated_at": "2012-07-21T07:38:22Z", "username": "root", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC58FwqHUbebw2SdT7SP4FxZ0w+lAO/erhy2ylhlcW/tZ3GY3mBu9VeeiSGoGz8hCx80Zrz+aQv28xfFfKlC8XQFpCWwsnWnQqO2Lv9bS8V1fIHgMxOHIt5Vs+9CAWGCCvUOAurjsUDoE2ALIXLDMKnJxcxD13XjWdK54j6ZXDB4syLF0C2PnAQSVY9X7MfCYwtuFmhQhKaBussAXpaVMRHltie3UYSBUUuZaB3J4cg/7TxlmxcNd+ppPRIpSZAB0NI6aOnqoBCpimscO/VpQRJMVLr3XiSYeT6HBiDXWHnIVPfQc03OGcaFqOit6p8lYKMaP/iUQLm+pgpZqrXZ9vB john@localhost", "id": 4 } +``` + +**密钥已删除** + +``` +{ "event_name": "key_destroy", "created_at": "2014-08-18 18:45:16 UTC", "updated_at": "2012-07-21T07:38:22Z", "username": "root", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC58FwqHUbebw2SdT7SP4FxZ0w+lAO/erhy2ylhlcW/tZ3GY3mBu9VeeiSGoGz8hCx80Zrz+aQv28xfFfKlC8XQFpCWwsnWnQqO2Lv9bS8V1fIHgMxOHIt5Vs+9CAWGCCvUOAurjsUDoE2ALIXLDMKnJxcxD13XjWdK54j6ZXDB4syLF0C2PnAQSVY9X7MfCYwtuFmhQhKaBussAXpaVMRHltie3UYSBUUuZaB3J4cg/7TxlmxcNd+ppPRIpSZAB0NI6aOnqoBCpimscO/VpQRJMVLr3XiSYeT6HBiDXWHnIVPfQc03OGcaFqOit6p8lYKMaP/iUQLm+pgpZqrXZ9vB john@localhost", "id": 4 } +``` + +**组创建:** + +``` +{ "created_at": "2012-07-21T07:30:54Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "group_create", "name": "StoreCloud", "owner_email": null, "owner_name": null, "path": "storecloud", "group_id": 78 } +``` + +`owner_name`和`owner_email`始终为`null` . 请参阅[https://gitlab.com/gitlab-org/gitlab/-/issues/20011](https://gitlab.com/gitlab-org/gitlab/-/issues/20011) . + +**组已删除:** + +``` +{ "created_at": "2012-07-21T07:30:54Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "group_destroy", "name": "StoreCloud", "owner_email": null, "owner_name": null, "path": "storecloud", "group_id": 78 } +``` + +`owner_name`和`owner_email`始终为`null` . 请参阅[问题#20011](https://gitlab.com/gitlab-org/gitlab/-/issues/20011) . + +**组重命名:** + +``` +{ "event_name": "group_rename", "created_at": "2017-10-30T15:09:00Z", "updated_at": "2017-11-01T10:23:52Z", "name": "Better Name", "path": "better-name", "full_path": "parent-group/better-name", "group_id": 64, "owner_name": null, "owner_email": null, "old_path": "old-name", "old_full_path": "parent-group/old-name" } +``` + +`owner_name`和`owner_email`始终为`null` . 请参阅[https://gitlab.com/gitlab-org/gitlab/-/issues/20011](https://gitlab.com/gitlab-org/gitlab/-/issues/20011) . + +**新组成员:** + +``` +{ "created_at": "2012-07-21T07:30:56Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "user_add_to_group", "group_access": "Maintainer", "group_id": 78, "group_name": "StoreCloud", "group_path": "storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", "user_username": "johnsmith", "user_id": 41 } +``` + +**组成员已删除:** + +``` +{ "created_at": "2012-07-21T07:30:56Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "user_remove_from_group", "group_access": "Maintainer", "group_id": 78, "group_name": "StoreCloud", "group_path": "storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", "user_username": "johnsmith", "user_id": 41 } +``` + +**小组成员已更新:** + +``` +{ "created_at": "2012-07-21T07:30:56Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "user_update_for_group", "group_access": "Maintainer", "group_id": 78, "group_name": "StoreCloud", "group_path": "storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", "user_username": "johnsmith", "user_id": 41 } +``` + +## Push events[](#push-events "Permalink") + +当您推送到存储库时(在推送标签时除外)触发. 它为每个修改的分支生成一个事件. + +**请求标头**: + +``` +X-Gitlab-Event: System Hook +``` + +**要求正文:** + +``` +{ "event_name": "push", "before": "95790bf891e76fee5e1747ab589903a6a1f80f22", "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "ref": "refs/heads/master", "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "user_id": 4, "user_name": "John Smith", "user_email": "john@example.com", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 15, "project":{ "name":"Diaspora", "description":"", "web_url":"http://example.com/mike/diaspora", "avatar_url":null, "git_ssh_url":"git@example.com:mike/diaspora.git", "git_http_url":"http://example.com/mike/diaspora.git", "namespace":"Mike", "visibility_level":0, "path_with_namespace":"mike/diaspora", "default_branch":"master", "homepage":"http://example.com/mike/diaspora", "url":"git@example.com:mike/diaspora.git", "ssh_url":"git@example.com:mike/diaspora.git", "http_url":"http://example.com/mike/diaspora.git" }, "repository":{ "name": "Diaspora", "url": "git@example.com:mike/diaspora.git", "description": "", "homepage": "http://example.com/mike/diaspora", "git_http_url":"http://example.com/mike/diaspora.git", "git_ssh_url":"git@example.com:mike/diaspora.git", "visibility_level":0 }, "commits": [ { "id": "c5feabde2d8cd023215af4d2ceeb7a64839fc428", "message": "Add simple search to projects in public area", "timestamp": "2013-05-13T18:18:08+00:00", "url": "https://dev.gitlab.org/gitlab/gitlabhq/commit/c5feabde2d8cd023215af4d2ceeb7a64839fc428", "author": { "name": "Example User", "email": "user@example.com" } } ], "total_commits_count": 1 } +``` + +## Tag events[](#tag-events "Permalink") + +在创建(或删除)存储库标签时触发. 每个修改后的标签会生成一个事件. + +**请求标头**: + +``` +X-Gitlab-Event: System Hook +``` + +**要求正文:** + +``` +{ "event_name": "tag_push", "before": "0000000000000000000000000000000000000000", "after": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7", "ref": "refs/tags/v1.0.0", "checkout_sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", "user_id": 1, "user_name": "John Smith", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 1, "project":{ "name":"Example", "description":"", "web_url":"http://example.com/jsmith/example", "avatar_url":null, "git_ssh_url":"git@example.com:jsmith/example.git", "git_http_url":"http://example.com/jsmith/example.git", "namespace":"Jsmith", "visibility_level":0, "path_with_namespace":"jsmith/example", "default_branch":"master", "homepage":"http://example.com/jsmith/example", "url":"git@example.com:jsmith/example.git", "ssh_url":"git@example.com:jsmith/example.git", "http_url":"http://example.com/jsmith/example.git" }, "repository":{ "name": "Example", "url": "ssh://git@example.com/jsmith/example.git", "description": "", "homepage": "http://example.com/jsmith/example", "git_http_url":"http://example.com/jsmith/example.git", "git_ssh_url":"git@example.com:jsmith/example.git", "visibility_level":0 }, "commits": [], "total_commits_count": 0 } +``` + +### Merge request events[](#merge-request-events "Permalink") + +在创建新的合并请求,更新/合并/关闭现有合并请求或在源分支中添加提交时触发. + +**请求标头**: + +``` +X-Gitlab-Event: System Hook +``` + +``` +{ "object_kind": "merge_request", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" }, "project": { "name": "Example", "description": "", "web_url": "http://example.com/jsmith/example", "avatar_url": null, "git_ssh_url": "git@example.com:jsmith/example.git", "git_http_url": "http://example.com/jsmith/example.git", "namespace": "Jsmith", "visibility_level": 0, "path_with_namespace": "jsmith/example", "default_branch": "master", "ci_config_path": "", "homepage": "http://example.com/jsmith/example", "url": "git@example.com:jsmith/example.git", "ssh_url": "git@example.com:jsmith/example.git", "http_url": "http://example.com/jsmith/example.git" }, "object_attributes": { "id": 90, "target_branch": "master", "source_branch": "ms-viewport", "source_project_id": 14, "author_id": 51, "assignee_id": 6, "title": "MS-Viewport", "created_at": "2017-09-20T08:31:45.944Z", "updated_at": "2017-09-28T12:23:42.365Z", "milestone_id": null, "state": "opened", "merge_status": "unchecked", "target_project_id": 14, "iid": 1, "description": "", "updated_by_id": 1, "merge_error": null, "merge_params": { "force_remove_source_branch": "0" }, "merge_when_pipeline_succeeds": false, "merge_user_id": null, "merge_commit_sha": null, "deleted_at": null, "in_progress_merge_commit_sha": null, "lock_version": 5, "time_estimate": 0, "last_edited_at": "2017-09-27T12:43:37.558Z", "last_edited_by_id": 1, "head_pipeline_id": 61, "ref_fetched": true, "merge_jid": null, "source": { "name": "Awesome Project", "description": "", "web_url": "http://example.com/awesome_space/awesome_project", "avatar_url": null, "git_ssh_url": "git@example.com:awesome_space/awesome_project.git", "git_http_url": "http://example.com/awesome_space/awesome_project.git", "namespace": "root", "visibility_level": 0, "path_with_namespace": "awesome_space/awesome_project", "default_branch": "master", "ci_config_path": "", "homepage": "http://example.com/awesome_space/awesome_project", "url": "http://example.com/awesome_space/awesome_project.git", "ssh_url": "git@example.com:awesome_space/awesome_project.git", "http_url": "http://example.com/awesome_space/awesome_project.git" }, "target": { "name": "Awesome Project", "description": "Aut reprehenderit ut est.", "web_url": "http://example.com/awesome_space/awesome_project", "avatar_url": null, "git_ssh_url": "git@example.com:awesome_space/awesome_project.git", "git_http_url": "http://example.com/awesome_space/awesome_project.git", "namespace": "Awesome Space", "visibility_level": 0, "path_with_namespace": "awesome_space/awesome_project", "default_branch": "master", "ci_config_path": "", "homepage": "http://example.com/awesome_space/awesome_project", "url": "http://example.com/awesome_space/awesome_project.git", "ssh_url": "git@example.com:awesome_space/awesome_project.git", "http_url": "http://example.com/awesome_space/awesome_project.git" }, "last_commit": { "id": "ba3e0d8ff79c80d5b0bbb4f3e2e343e0aaa662b7", "message": "fixed readme", "timestamp": "2017-09-26T16:12:57Z", "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "author": { "name": "GitLab dev user", "email": "gitlabdev@dv6700.(none)" } }, "work_in_progress": false, "total_time_spent": 0, "human_total_time_spent": null, "human_time_estimate": null }, "labels": null, "repository": { "name": "git-gpg-test", "url": "git@example.com:awesome_space/awesome_project.git", "description": "", "homepage": "http://example.com/awesome_space/awesome_project" } } +``` + +## Repository Update events[](#repository-update-events "Permalink") + +当您推送到存储库(包括标签)时仅触发一次. + +**Request header**: + +``` +X-Gitlab-Event: System Hook +``` + +**要求正文:** + +``` +{ "event_name": "repository_update", "user_id": 1, "user_name": "John Smith", "user_email": "admin@example.com", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 1, "project": { "name":"Example", "description":"", "web_url":"http://example.com/jsmith/example", "avatar_url":null, "git_ssh_url":"git@example.com:jsmith/example.git", "git_http_url":"http://example.com/jsmith/example.git", "namespace":"Jsmith", "visibility_level":0, "path_with_namespace":"jsmith/example", "default_branch":"master", "homepage":"http://example.com/jsmith/example", "url":"git@example.com:jsmith/example.git", "ssh_url":"git@example.com:jsmith/example.git", "http_url":"http://example.com/jsmith/example.git", }, "changes": [ { "before":"8205ea8d81ce0c6b90fbe8280d118cc9fdad6130", "after":"4045ea7a3df38697b3730a20fb73c8bed8a3e69e", "ref":"refs/heads/master" } ], "refs":["refs/heads/master"] } +``` + +## Local requests in system hooks[](#local-requests-in-system-hooks "Permalink") + +管理员可以允许或阻止通过[系统挂钩对本地网络的请求](../security/webhooks.html) . \ No newline at end of file diff --git a/_book/docs/460.md b/_book/docs/460.md new file mode 100644 index 0000000000000000000000000000000000000000..5b1ec9c294e995e11a4d459f41ab246c96972c2b --- /dev/null +++ b/_book/docs/460.md @@ -0,0 +1,43 @@ +# Changing your time zone + +> 原文:[https://docs.gitlab.com/ee/administration/timezone.html](https://docs.gitlab.com/ee/administration/timezone.html) + +* [Viewing available timezones](#viewing-available-timezones) +* [Changing time zone in Omnibus installations](#changing-time-zone-in-omnibus-installations) + +# Changing your time zone[](#changing-your-time-zone "Permalink") + +可以在`config/gitlab.yml`更改全局时区配置参数: + +``` +# time_zone: 'UTC' +``` + +如果要更改 GitLab 应用程序的默认时区,请取消注释并自定义. + +## Viewing available timezones[](#viewing-available-timezones "Permalink") + +要查看所有可用时区,请运行`bundle exec rake time:zones:all` . + +对于 Omnibus 安装,请运行`gitlab-rake time:zones:all` . + +**注意:**当前,此 Rake 任务未列出重新配置过程中 Omnibus GitLab 所需的 TZInfo 格式的时区: [#27209](https://gitlab.com/gitlab-org/gitlab/-/issues/27209) . + +## Changing time zone in Omnibus installations[](#changing-time-zone-in-omnibus-installations "Permalink") + +GitLab 将其时区默认为 UTC. 它在`/etc/gitlab/gitlab.rb`具有全局时区配置参数. + +要获取时区列表,请登录到 GitLab 应用程序服务器并运行一个命令,该命令为服务器生成 TZInfo 格式的时区列表. 例如,安装`timedatectl`并运行`timedatectl list-timezones` . + +要进行更新,请添加最适合您所在位置的时区. 例如: + +``` +gitlab_rails['time_zone'] = 'America/New_York' +``` + +添加配置参数后,重新配置并重新启动您的 GitLab 实例: + +``` +gitlab-ctl reconfigure +gitlab-ctl restart +``` \ No newline at end of file diff --git a/_book/docs/461.md b/_book/docs/461.md new file mode 100644 index 0000000000000000000000000000000000000000..d5766052fc4a6725b98ec924c4aff5091ad34b31 --- /dev/null +++ b/_book/docs/461.md @@ -0,0 +1,185 @@ +# Uploads administration + +> 原文:[https://docs.gitlab.com/ee/administration/uploads.html](https://docs.gitlab.com/ee/administration/uploads.html) + +* [Using local storage](#using-local-storage) +* [Using object storage](#using-object-storage-core-only) +* [Object Storage Settings](#object-storage-settings) + * [Connection settings](#connection-settings) + * [OpenStack example](#openstack-example) + +# Uploads administration[](#uploads-administration "Permalink") + +上传代表可以作为单个文件发送到 GitLab 的所有用户数据. 例如,化身和笔记的附件就是上载. 上传是 GitLab 功能不可或缺的,因此不能被禁用. + +## Using local storage[](#using-local-storage "Permalink") + +**注意:**这是默认配置 + +要更改上传内容在本地存储的位置,请按照以下步骤操作. + +**在所有安装中;** + +**注意:**由于历史原因,上载存储在基本目录中,默认情况下该目录为`uploads/-/system` . 不建议在现有的 GitLab 安装上更改此配置选项. + +*上载默认情况下存储在`/var/opt/gitlab/gitlab-rails/uploads` .* + +1. 要将存储路径更改为例如`/mnt/storage/uploads` ,请编辑`/etc/gitlab/gitlab.rb`并添加以下行: + + ``` + gitlab_rails['uploads_storage_path'] = "/mnt/storage/" + gitlab_rails['uploads_base_dir'] = "uploads" + ``` + +2. 保存文件并[重新配置 GitLab,](restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**在源安装中:** + +*上载默认存储在`/home/git/gitlab/public/uploads/-/system` .* + +1. 要将存储路径更改为例如`/mnt/storage/uploads` ,请编辑`/home/git/gitlab/config/gitlab.yml`并添加或修改以下行: + + ``` + uploads: + storage_path: /mnt/storage + base_dir: uploads + ``` + +2. 保存文件并[重新启动 GitLab,](restart_gitlab.html#installations-from-source)以使更改生效. + +## Using object storage[](#using-object-storage-core-only "Permalink") + +版本历史 + +**笔记:** + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3867) . +* 在[GitLab Core](https://about.gitlab.com/pricing/) 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17358) . +* 从 11.1 版开始,我们支持 direct_upload 到 S3\. + +如果您不想使用安装了 GitLab 的本地磁盘来存储上载,则可以改用 AWS S3 之类的对象存储提供程序. 此配置依赖于已经配置的有效 AWS 凭证. + +[Read more about using object storage with GitLab](object_storage.html). + +**注意:**我们建议使用[统一对象存储设置](object_storage.html#consolidated-object-storage-configuration) . 以下说明适用于原始配置格式. + +## Object Storage Settings[](#object-storage-settings "Permalink") + +对于源安装,以下设置嵌套在`uploads:`下,然后是`object_store:` 在 Omnibus GitLab 安装上,它们的前缀是`uploads_object_store_` . + +| Setting | Description | Default | +| --- | --- | --- | +| `enabled` | 启用/禁用对象存储 | `false` | +| `remote_directory` | 存储上传文件的存储桶名称 |   | +| `direct_upload` | 设置为 true 可从上载路径中删除 Puma. Workhorse 处理实际的工件上传到对象存储,而 Puma 进行最少的处理以跟踪上传. 无需本地共享存储. 如果引入了对所有文件的单一存储类型的支持,则可以删除该选项. 了解更多有关[直接上传的信息](../development/uploads.html#direct-upload) . | `false` | +| `background_upload` | 设置为 false 可禁用自动上传. 一旦直接上传到 S3,就可以删除该选项(如果`direct_upload`设置为`true` ,它将覆盖`background_upload` ) | `true` | +| `proxy_download` | 设置为 true 以启用代理服务的所有文件. Option 可以减少出口流量,因为这允许客户端直接从远程存储下载而不是代理所有数据 | `false` | +| `connection` | 下述各种连接选项 |   | + +### Connection settings[](#connection-settings "Permalink") + +See [the available connection settings for different providers](object_storage.html#connection-settings). + +**在所有安装中;** + +*上载默认情况下存储在`/var/opt/gitlab/gitlab-rails/public/uploads/-/system` .* + +1. 编辑`/etc/gitlab/gitlab.rb`并通过替换为所需的值添加以下行: + + ``` + gitlab_rails['uploads_object_store_enabled'] = true + gitlab_rails['uploads_object_store_remote_directory'] = "uploads" + gitlab_rails['uploads_object_store_connection'] = { + 'provider' => 'AWS', + 'region' => 'eu-central-1', + 'aws_access_key_id' => 'AWS_ACCESS_KEY_ID', + 'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY' + } + ``` + + **注意:**如果您使用的是 AWS IAM 配置文件,请确保省略 AWS 访问密钥和秘密访问密钥/值对. + + ``` + gitlab_rails['uploads_object_store_connection'] = { + 'provider' => 'AWS', + 'region' => 'eu-central-1', + 'use_iam_profile' => true + } + ``` + +2. 保存文件并[重新配置 GitLab,](restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +3. 使用[`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.html)迁移所有现有的本地上传到对象存储. + +**在源安装中:** + +*上载默认存储在`/home/git/gitlab/public/uploads/-/system` .* + +1. 编辑`/home/git/gitlab/config/gitlab.yml`并添加或修改以下行: + + ``` + uploads: + object_store: + enabled: true + remote_directory: "uploads" # The bucket name + connection: + provider: AWS # Only AWS supported at the moment + aws_access_key_id: AWS_ACESS_KEY_ID + aws_secret_access_key: AWS_SECRET_ACCESS_KEY + region: eu-central-1 + ``` + +2. 保存文件并[重新启动 GitLab,](restart_gitlab.html#installations-from-source)以使更改生效. +3. 使用[`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.html)迁移所有现有的本地上传到对象存储. + +### OpenStack example[](#openstack-example "Permalink") + +**在所有安装中;** + +*上载默认情况下存储在`/var/opt/gitlab/gitlab-rails/public/uploads/-/system` .* + +1. Edit `/etc/gitlab/gitlab.rb` and add the following lines by replacing with the values you want: + + ``` + gitlab_rails['uploads_object_store_remote_directory'] = "OPENSTACK_OBJECT_CONTAINER_NAME" + gitlab_rails['uploads_object_store_connection'] = { + 'provider' => 'OpenStack', + 'openstack_username' => 'OPENSTACK_USERNAME', + 'openstack_api_key' => 'OPENSTACK_PASSWORD', + 'openstack_temp_url_key' => 'OPENSTACK_TEMP_URL_KEY', + 'openstack_auth_url' => 'https://auth.cloud.ovh.net/v2.0/', + 'openstack_region' => 'DE1', + 'openstack_tenant' => 'TENANT_ID', + } + ``` + +2. 保存文件并[重新配置 GitLab,](restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +3. 使用[`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.html)迁移所有现有的本地上传到对象存储. + +* * * + +**在源安装中:** + +*上载默认存储在`/home/git/gitlab/public/uploads/-/system` .* + +1. 编辑`/home/git/gitlab/config/gitlab.yml`并添加或修改以下行: + + ``` + uploads: + object_store: + enabled: true + direct_upload: false + background_upload: true + proxy_download: false + remote_directory: OPENSTACK_OBJECT_CONTAINER_NAME + connection: + provider: OpenStack + openstack_username: OPENSTACK_USERNAME + openstack_api_key: OPENSTACK_PASSWORD + openstack_temp_url_key: OPENSTACK_TEMP_URL_KEY + openstack_auth_url: 'https://auth.cloud.ovh.net/v2.0/' + openstack_region: DE1 + openstack_tenant: 'TENANT_ID' + ``` + +2. 保存文件并[重新配置 GitLab,](restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +3. 使用[`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.html)迁移所有现有的本地上传到对象存储. \ No newline at end of file diff --git a/_book/docs/462.md b/_book/docs/462.md new file mode 100644 index 0000000000000000000000000000000000000000..8d5e5cc3a8dbcc89a3725c1cbb4467cde92529b4 --- /dev/null +++ b/_book/docs/462.md @@ -0,0 +1,61 @@ +# Abuse reports + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/abuse_reports.html](https://docs.gitlab.com/ee/user/admin_area/abuse_reports.html) + +* [Reporting abuse](#reporting-abuse) +* [Resolving abuse reports](#resolving-abuse-reports) + * [Blocking users](#blocking-users) + +# Abuse reports[](#abuse-reports-core-only "Permalink") + +查看和解决来自 GitLab 用户的滥用情况报告. + +GitLab 管理员可以在管理区域中查看和[解决](#resolving-abuse-reports)滥用报告. + +## Reporting abuse[](#reporting-abuse "Permalink") + +要了解有关报告滥用情况的更多信息,请参阅[滥用报告用户文档](../abuse_reports.html) . + +## Resolving abuse reports[](#resolving-abuse-reports "Permalink") + +要访问滥用报告,请进入**管理区域>滥用报告** . + +解决滥用情况报告的方法有 3 种,每种方法都有一个按钮: + +* 删除用户和报告. 这将: + * 从实例中[删除报告的用户](../profile/account/delete_account.html) . + * 从列表中删除滥用报告. +* [Block user](#blocking-users). +* 删除报告. 这将: + * 从列表中删除滥用报告. + * 删除报告用户的访问限制. + +以下是" **滥用情况报告"**页面的示例: + +[![abuse-reports-page-image](img/31c7821d41281d527a8ee4f058bafaca.png)](img/abuse_reports_page.png) + +### Blocking users[](#blocking-users "Permalink") + +被阻止的用户无法登录或访问任何存储库,但是保留了他们的所有数据. + +阻止用户: + +* Leaves them in the abuse report list. +* 将**阻止用户**按钮更改为禁用的**已阻止**按钮. + +将通过[以下消息](https://gitlab.com/gitlab-org/gitlab/blob/master/app/workers/email_receiver_worker.rb#L38)通知用户: + +``` +Your account has been blocked. If you believe this is in error, contact a staff member. +``` + +屏蔽后,您仍然可以: + +* 删除用户并在必要时报告. +* 删除报告. + +以下是" **滥用报告"**页面上列出的被阻止用户的示例: + +[![abuse-report-blocked-user-image](img/517f5b10646cf257d0fd0413cb54c3e9.png)](img/abuse_report_blocked_user.png) + +**注意:**用户可以[阻止](../../api/users.html#block-user)和[畅通](../../api/users.html#unblock-user)使用 GitLab API. \ No newline at end of file diff --git a/_book/docs/463.md b/_book/docs/463.md new file mode 100644 index 0000000000000000000000000000000000000000..71b34bb6e44521de71eed786ab1201f6066b7d04 --- /dev/null +++ b/_book/docs/463.md @@ -0,0 +1,61 @@ +# Activating and deactivating users + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/activating_deactivating_users.html](https://docs.gitlab.com/ee/user/admin_area/activating_deactivating_users.html) + +* [Deactivating a user](#deactivating-a-user) +* [Activating a user](#activating-a-user) + +# Activating and deactivating users[](#activating-and-deactivating-users "Permalink") + +GitLab 管理员可以停用和激活用户. + +## Deactivating a user[](#deactivating-a-user "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) . + +为了临时阻止没有最近活动的 GitLab 用户访问,管理员可以选择停用该用户. + +停用用户在功能上与[阻止用户](blocking_unblocking_users.html)相同,但有以下区别: + +* 它不禁止用户通过 UI 重新登录. +* 一旦停用的用户重新登录到 GitLab UI,其帐户将被设置为活动状态. + +停用的用户: + +* 无法访问 Git 存储库或 API. +* 不会从 GitLab 收到任何通知. +* 将无法使用[斜杠命令](../../integration/slash_commands.html) . + +个人项目以及已停用用户的组和用户历史记录将保持不变. + +可以从管理区域中停用用户. 去做这个: + +1. 导航到**管理区域>概述>用户** . +2. 选择一个用户. +3. 在**帐户**标签下,点击**停用用户** . + +请注意,要使停用选项对管理员可见,用户: + +* 必须当前处于活动状态. +* 最近 180 天内不得登录或进行任何活动. + +也可以使用[GitLab API](../../api/users.html#deactivate-user)停用用户. + +**注意:**停用的用户不会消耗[座位](../../subscriptions/index.html#choosing-the-number-of-users) . + +## Activating a user[](#activating-a-user "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) . + +可以从管理区域激活停用的用户. + +去做这个: + +1. 导航到**管理区域>概述>用户** . +2. 单击**停用**选项卡. +3. 选择一个用户. +4. 在**帐户**标签下,点击**激活用户** . + +也可以使用[GitLab API](../../api/users.html#activate-user)激活用户. + +**注意:**激活用户将把用户状态更改为活动状态,这将占用一个[席位](../../subscriptions/index.html#choosing-the-number-of-users) .**提示:**停用的用户还可以通过简单地通过 UI 重新登录来自己激活帐户. \ No newline at end of file diff --git a/_book/docs/464.md b/_book/docs/464.md new file mode 100644 index 0000000000000000000000000000000000000000..d72389e409253fe26057b16ad59c05c27763ac01 --- /dev/null +++ b/_book/docs/464.md @@ -0,0 +1,157 @@ +# Audit Events + +> 原文:[https://docs.gitlab.com/ee/administration/audit_events.html](https://docs.gitlab.com/ee/administration/audit_events.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [List of events](#list-of-events) + * [Impersonation data](#impersonation-data-premium) + * [Group events](#group-events-starter) + * [Project events](#project-events-starter) + * [Instance events](#instance-events-premium-only) + * [Missing events](#missing-events) + * [Disabled events](#disabled-events) + * [Repository push](#repository-push) + +# Audit Events[](#audit-events-starter "Permalink") + +GitLab 为拥有者和管理员提供了一种在[付费计划中](https://about.gitlab.com/pricing/)查看 GitLab 服务器中所做的更改的方法. + +GitLab 系统管理员还可以利用文件系统上的日志. 有关更多详细信息,请参见[日志系统文档](logs.html) . + +## Overview[](#overview "Permalink") + +**审核事件**是 GitLab 所有者和管理员用于跟踪重要事件的工具,例如谁执行了某些操作及其发生的时间. 例如,这些操作可以是更改用户权限级别,添加新用户或删除用户. + +## Use cases[](#use-cases "Permalink") + +* 检查谁更改了 GitLab 项目的特定用户的权限级别. +* 跟踪哪些用户有权访问 GitLab 中的特定项目组,以及谁授予他们该权限级别. + +## List of events[](#list-of-events "Permalink") + +记录了两种事件: + +* 事件范围为组或项目,组和项目经理使用这些事件来查找谁进行了更改. +* 实例事件的范围涵盖整个 GitLab 实例,由合规团队用于执行正式审核. + +### Impersonation data[](#impersonation-data-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/536) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0. + +模拟是管理员使用凭据以其他用户身份执行操作的地方. + +### Group events[](#group-events-starter "Permalink") + +**注意:**您需要拥有者[权限](../user/permissions.html)才能查看组"审核事件"页面. + +要查看组的审核事件,请导航至**组>设置>审核事件** . 从那里,您可以看到以下操作: + +* 组名或路径已更改 +* 组存储库大小限制已更改 +* 创建或删除组 +* 组更改可见性 +* 用户已添加到组中并具有哪些[权限](../user/permissions.html) +* 用户通过[组 SAML](../user/group/saml_sso/index.html)登录 +* 分配给组的用户的权限更改 +* 从群组中删除了用户 +* 项目存储库已导入组 +* [与组共享](../user/project/members/share_project_with_groups.html)并具有[权限的项目](../user/permissions.html) +* 删除项目中先前共享的组 +* 启用或禁用 LFS +* 共享跑步者的分钟数限制已更改 +* 启用或禁用会员锁定 +* 请求访问已启用或已禁用 +* 2FA 执行或宽限期已更改 +* 允许创建项目的角色已更改 + +组事件也可以通过[组审核事件 API](../api/audit_events.html#group-audit-events-starter)访问 + +### Project events[](#project-events-starter "Permalink") + +**注意:**您需要维护者[权限](../user/permissions.html)或更高[权限](../user/permissions.html)才能查看项目"审核事件"页面. + +要查看项目的审核事件,请导航至**项目>设置>审核事件** . 从那里,您可以看到以下操作: + +* 添加或删除了部署密钥 +* 创建,删除,重命名,移动(转移),更改路径的项目 +* 项目更改的可见性级别 +* 用户已添加到项目中并具有哪些[权限](../user/permissions.html) +* 分配给项目的用户的权限更改 +* 用户已从项目中删除 +* 已下载项目导出 +* 项目资源库已下载 +* 项目已存档 +* 项目未归档 +* 添加,删除或更新的受保护分支 +* 版本已添加到项目 +* 版本已更新 +* 发布里程碑关联已更改 +* 更新了批准提交者合并请求的权限(在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) ) +* 更新了批准作者合并请求的权限(在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) ) +* 更新了所需的批准数量(在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) ) +* 在项目批准组中添加或删除用户和组(在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/213603) ) + +也可以通过[Project Audit Events API](../api/audit_events.html#project-audit-events-starter)访问[项目事件](../api/audit_events.html#project-audit-events-starter) + +### Instance events[](#instance-events-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2336) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.3. + +服务器范围的审核日志记录引入了在 GitLab 服务器的整个实例中观察用户操作的功能,从而易于了解谁为审核目的以及何时更改了内容. + +要查看服务器范围的管理日志,请访问**管理区域>监视>审核日志** . + +除了组和项目事件,还记录以下用户操作: + +* 登录失败 +* 登录事件和身份验证类型(例如标准,LDAP 或 OmniAuth) +* 添加了 SSH 密钥 +* 添加或删除电子邮件 +* 修改密码 +* 要求重设密码 +* 授予 OAuth 访问权限 +* 开始或停止模拟用户 +* 更改的用户名(在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7797) ) +* 用户已删除(在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/251) ) +* 添加了用户(在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/251) ) +* 通过管理区(在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/251) )阻止了用户 +* 通过 API(在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25872) )阻止了用户 + +通过从过滤器下拉框中选择审核数据类型,可以过滤特定的操作. 您可以进一步按特定的组,项目或用户筛选(用于身份验证事件). + +[![audit log](img/7151cdf5255313b82b775852ed2aef73.png)](img/audit_log.png) + +实例事件也可以通过[Instance Audit Events API](../api/audit_events.html#instance-audit-events-premium-only)访问 + +### Missing events[](#missing-events "Permalink") + +在审核事件中未跟踪某些事件. 有关未跟踪哪些事件的更多详细信息,以及将这些事件添加到 GitLab 中的进展,请参见以下史诗: + +* [Project settings and activity](https://gitlab.com/groups/gitlab-org/-/epics/474) +* [Group settings and activity](https://gitlab.com/groups/gitlab-org/-/epics/475) +* [Instance-level settings and activity](https://gitlab.com/groups/gitlab-org/-/epics/476) + +### Disabled events[](#disabled-events "Permalink") + +#### Repository push[](#repository-push "Permalink") + +当前的审计事件体系结构不准备接收大量记录. 这可能会使您的项目或审核日志的用户界面非常繁忙,并且`audit_events` PostgreSQL 表占用的磁盘空间将大大增加. 默认情况下禁用它,以防止 GitLab 实例具有很高的 Git 写入流量时性能降低. + +在即将发布的版本中,默认情况下将启用 Git 推送事件的审核日志. 请按照[#7865](https://gitlab.com/gitlab-org/gitlab/-/issues/7865)进行更新. + +如果您仍然希望在实例中启用**存储库推送**事件,请执行以下步骤. + +**在所有安装中;** + +1. 进入 Rails 控制台: + + ``` + sudo gitlab-rails console + ``` + +2. Flip the switch and enable the feature flag: + + ``` + Feature.enable(:repository_push_audit_event) + ``` \ No newline at end of file diff --git a/_book/docs/465.md b/_book/docs/465.md new file mode 100644 index 0000000000000000000000000000000000000000..bcf3f874f403b8cbcf8413ef1a0434d454fa17d5 --- /dev/null +++ b/_book/docs/465.md @@ -0,0 +1,46 @@ +# Blocking and unblocking users + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/blocking_unblocking_users.html](https://docs.gitlab.com/ee/user/admin_area/blocking_unblocking_users.html) + +* [Blocking a user](#blocking-a-user) +* [Unblocking a user](#unblocking-a-user) + +# Blocking and unblocking users[](#blocking-and-unblocking-users "Permalink") + +GitLab 管理员阻止和取消阻止用户. + +## Blocking a user[](#blocking-a-user "Permalink") + +为了完全阻止用户访问 GitLab 实例,管理员可以选择阻止该用户. + +可以[通过滥用报告](abuse_reports.html#blocking-users)或直接从管理区域来阻止用户. 去做这个: + +1. 导航到**管理区域>概述>用户** . +2. 选择一个用户. +3. 在**帐户**标签下,点击**阻止用户** . + +被阻止的用户: + +* 将无法登录. +* 无法访问 Git 存储库或 API. +* 不会从 GitLab 收到任何通知. +* 将无法使用[斜杠命令](../../integration/slash_commands.html) . + +个人项目以及被阻止用户的组和用户历史记录将保持不变. + +也可以使用[GitLab API](../../api/users.html#block-user)阻止用户. + +**注意:**被封锁的用户不会占用[座位](../../subscriptions/index.html#choosing-the-number-of-users) . + +## Unblocking a user[](#unblocking-a-user "Permalink") + +可以从管理区域中取消阻止被阻止的用户. 去做这个: + +1. 导航到**管理区域>概述>用户** . +2. 单击" **阻止"**选项卡. +3. 选择一个用户. +4. 在**帐户**标签下,点击**取消阻止用户** . + +也可以使用[GitLab API](../../api/users.html#unblock-user)解除对用户的阻止. + +**注意:**取消禁止用户进入会将用户状态更改为"活动",这将占用一个[席位](../../subscriptions/index.html#choosing-the-number-of-users) . \ No newline at end of file diff --git a/_book/docs/466.md b/_book/docs/466.md new file mode 100644 index 0000000000000000000000000000000000000000..38833e699b5ae5ffc31157ef1a719e7c4e6d3dd8 --- /dev/null +++ b/_book/docs/466.md @@ -0,0 +1,98 @@ +# Broadcast Messages + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/broadcast_messages.html](https://docs.gitlab.com/ee/user/admin_area/broadcast_messages.html) + +* [Banners](#banners) +* [Notifications](#notifications) +* [Adding a broadcast message](#adding-a-broadcast-message) +* [Editing a broadcast message](#editing-a-broadcast-message) +* [Deleting a broadcast message](#deleting-a-broadcast-message) + +# Broadcast Messages[](#broadcast-messages-core-only "Permalink") + +GitLab 可以向 GitLab 实例的所有用户显示广播消息. 广播消息有两种类型: + +* banners +* notifications + +您可以使用`a`和`br` HTML 标记来设置消息内容的样式. `br`标签插入换行符. `a` HTML 标记接受具有以下 CSS 属性的`class`和`style`属性: + +* `color` +* `border` +* `background` +* `padding` +* `margin` +* `text-decoration` + +## Banners[](#banners "Permalink") + +标语显示在页面顶部和 Git 远程响应中. + +[![Broadcast Message Banner](img/5665233091dd783791b6dd32107e61ec.png)](img/broadcast_messages_banner_v12_10.png) + +``` +$ git push +... +remote: +remote: **Welcome** to GitLab :wave: +remote: +... +``` + +## Notifications[](#notifications "Permalink") + +通知显示在页面的右下角,并且可以包含占位符. 占位符替换为活动用户的属性. 占位符必须用花括号括起来,例如`{{name}}` . 可用的占位符是: + +* `{{email}}` +* `{{name}}` +* `{{user_id}}` +* `{{username}}` +* `{{instance_id}}` + +如果用户未登录,则与用户相关的值将为空. + +[![Broadcast Message Notification](img/eaa74cb66b0dd1b45f9b312af76c23fb.png)](img/broadcast_messages_notification_v12_10.png) + +广播消息可以使用[广播消息 API](../../api/broadcast_messages.html)进行管理. + +**注意:**如果一次激活了多个横幅消息,则会按创建顺序将它们显示在堆栈中. 如果一次激活了多个通知消息,则仅显示最新消息. + +## Adding a broadcast message[](#adding-a-broadcast-message "Permalink") + +要向您的 GitLab 实例上的用户显示消息,请添加广播消息. + +要添加广播消息: + +1. 导航到" **管理区域">"消息"**页面. +2. 将消息的文本添加到" **消息"**字段. 支持 Markdown 和表情符号. +3. 如果需要,请单击" **自定义颜色"**链接以编辑消息的背景颜色和字体颜色. +4. 如果需要,添加**目标路径**以仅在与该路径匹配的 URL 上显示广播消息. 您可以使用通配符`*`来匹配多个 URL,例如`/users/*/issues` . +5. 选择消息的开始日期和结束日期. +6. 单击**添加广播消息**按钮. + +**注意:**广播消息过期后,将不再显示在 UI 中,而是仍列在广播消息列表中. 如果设置了"可**禁用** "选项,则用户还可以关闭广播消息. + +## Editing a broadcast message[](#editing-a-broadcast-message "Permalink") + +如果需要更改广播消息,则可以对其进行编辑. + +要编辑广播消息: + +1. 导航到" **管理区域">"消息"**页面. +2. 从广播消息列表中,单击相应的按钮以编辑消息. +3. 进行所需的更改后,单击" **更新广播消息"**按钮. + +**提示:**过期的邮件可以通过更改其结束日期来再次激活. + +## Deleting a broadcast message[](#deleting-a-broadcast-message "Permalink") + +可以删除不再需要的广播消息. + +要删除广播消息: + +1. 导航到" **管理区域">"消息"**页面. +2. 从广播消息列表中,单击相应的按钮以删除该消息. + +删除后,广播消息将从广播消息列表中删除. + +**注意:**广播消息可以在激活时删除. \ No newline at end of file diff --git a/_book/docs/467.md b/_book/docs/467.md new file mode 100644 index 0000000000000000000000000000000000000000..7efba32686652f753f135729d6b7c94be50aa6c1 --- /dev/null +++ b/_book/docs/467.md @@ -0,0 +1,633 @@ +# Elasticsearch integration + +> 原文:[https://docs.gitlab.com/ee/integration/elasticsearch.html](https://docs.gitlab.com/ee/integration/elasticsearch.html) + +* [Version Requirements](#version-requirements) +* [Installing Elasticsearch](#installing-elasticsearch) +* [Elasticsearch repository indexer](#elasticsearch-repository-indexer) + * [Omnibus GitLab](#omnibus-gitlab) + * [From source](#from-source) + * [Debian / Ubuntu](#debian--ubuntu) + * [CentOS / RHEL](#centos--rhel) + * [Mac OSX](#mac-osx) + * [Building and installing](#building-and-installing) +* [System Requirements](#system-requirements) +* [Enabling Elasticsearch](#enabling-elasticsearch) + * [Limiting namespaces and projects](#limiting-namespaces-and-projects) +* [Disabling Elasticsearch](#disabling-elasticsearch) +* [Adding GitLab’s data to the Elasticsearch index](#adding-gitlabs-data-to-the-elasticsearch-index) + * [Indexing through the administration UI](#indexing-through-the-administration-ui) + * [Indexing through Rake tasks](#indexing-through-rake-tasks) + * [Indexing small instances](#indexing-small-instances) + * [Indexing large instances](#indexing-large-instances) + * [Indexing limitations](#indexing-limitations) +* [GitLab Elasticsearch Rake tasks](#gitlab-elasticsearch-rake-tasks) + * [Environment variables](#environment-variables) + * [Indexing a specific project](#indexing-a-specific-project) +* [Elasticsearch index scopes](#elasticsearch-index-scopes) +* [Tuning](#tuning) + * [Guidance on choosing optimal cluster configuration](#guidance-on-choosing-optimal-cluster-configuration) + * [Elasticsearch integration settings guidance](#elasticsearch-integration-settings-guidance) + * [Deleted documents](#deleted-documents) +* [Troubleshooting](#troubleshooting) + * [Common issues](#common-issues) + * [Low-level troubleshooting](#low-level-troubleshooting) + * [Known Issues](#known-issues) + * [Reverting to basic search](#reverting-to-basic-search) + +# Elasticsearch integration[](#elasticsearch-integration-starter-only "Permalink") + +版本历史 + +* 在 GitLab [Starter](https://about.gitlab.com/pricing/) 8.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109 "Elasticsearch 合并请求") . +* 在 GitLab [Starter](https://about.gitlab.com/pricing/) 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1305)了对[Amazon Elasticsearch 的](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg.html)支持. + +本文档介绍了如何使用 GitLab 设置 Elasticsearch. 启用后,您将受益于快速的搜索响应时间以及两个特殊搜索的优点: + +* [Advanced Global Search](../user/search/advanced_global_search.html) +* [Advanced Syntax Search](../user/search/advanced_search_syntax.html) + +## Version Requirements[](#version-requirements "Permalink") + +| GitLab 版本 | Elasticsearch 版本 | +| --- | --- | +| GitLab 企业版 8.4-8.17 | Elasticsearch 2.4 with [Delete By Query Plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/2.4/plugins-delete-by-query.html) installed | +| GitLab 企业版 9.0-11.4 | 弹性搜索 5.1-5.5 | +| GitLab 企业版 11.5-12.6 | Elasticsearch 5.6-6.x | +| manbetx 客户端打不开企业版 12.7+ | Elasticsearch 6.x-7.x | + +## Installing Elasticsearch[](#installing-elasticsearch "Permalink") + +Omnibus 软件包中*不*包括 Elasticsearch. 无论您使用的是 Omnibus 软件包还是从源代码安装的 GitLab,您都必须[自行安装](https://www.elastic.co/guide/en/elasticsearch/reference/6.8/install-elasticsearch.html "Elasticsearch 6.8 安装文档") . 提供有关安装 Elasticsearch 的详细信息超出了本文档的范围. + +**注意:** Elasticsearch 应该安装在单独的服务器上,无论您自己安装还是使用云托管产品,例如 Elastic 的[Elasticsearch Service](https://www.elastic.co/elasticsearch/service) (在 AWS,GCP 或 Azure 上可用)或[Amazon Elasticsearch](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg.html) Service. 不建议在与 GitLab 相同的服务器上运行 Elasticsearch,这可能会导致 GitLab 实例性能下降.**注意:** **对于单节点 Elasticsearch 集群,功能集群的运行状况为黄色** (永远不会为绿色),因为已分配了主要分片,但副本却无法存在,因为没有其他节点可以为 Elasticsearch 分配副本. + +将数据添加到数据库或存储库中并[在管理区域中启用 Elasticsearch 后](#enabling-elasticsearch) ,搜索索引将自动更新. + +## Elasticsearch repository indexer[](#elasticsearch-repository-indexer "Permalink") + +为了索引 Git 存储库数据,GitLab 使用了[Go 语言编写](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer)的[索引器](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer) . + +Go 索引器的安装方式取决于您的 GitLab 版本: + +* 对于 Omnibus GitLab 11.8 及更高版本,请参见[Omnibus GitLab](#omnibus-gitlab) . +* For installations from source or older versions of Omnibus GitLab, install the indexer [From Source](#from-source). + +### Omnibus GitLab[](#omnibus-gitlab "Permalink") + +从 GitLab 11.8 开始,Omnibus GitLab 中包含了 Go 索引器. 以前的基于 Ruby 的索引器已在[GitLab 12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/6481)中删除. + +### From source[](#from-source "Permalink") + +首先,我们需要安装一些依赖项,然后构建并安装索引器本身. + +该项目依靠[ICU](http://site.icu-project.org/)进行文本编码,因此我们需要确保在运行`make`之前安装了适用于您平台的开发包. + +#### Debian / Ubuntu[](#debian--ubuntu "Permalink") + +要在 Debian 或 Ubuntu 上安装,请运行: + +``` +sudo apt install libicu-dev +``` + +#### CentOS / RHEL[](#centos--rhel "Permalink") + +要在 CentOS 或 RHEL 上安装,请运行: + +``` +sudo yum install libicu-devel +``` + +##### Mac OSX[](#mac-osx "Permalink") + +要在 macOS 上安装,请运行: + +``` +brew install icu4c +export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:$PKG_CONFIG_PATH" +``` + +### Building and installing[](#building-and-installing "Permalink") + +要构建和安装索引器,请运行: + +``` +indexer_path=/home/git/gitlab-elasticsearch-indexer + +# Run the installation task for gitlab-elasticsearch-indexer: +sudo -u git -H bundle exec rake gitlab:indexer:install[$indexer_path] RAILS_ENV=production +cd $indexer_path && sudo make install +``` + +The `gitlab-elasticsearch-indexer` will be installed to `/usr/local/bin`. + +您可以使用`PREFIX` env 变量更改安装路径. 如果这样做,请记住将`-E`标志传递给`sudo` . + +Example: + +``` +PREFIX=/usr sudo -E make install +``` + +安装完成后,请在您实例的 Elasticsearch 设置下启用, [如下所述](#enabling-elasticsearch) . + +## System Requirements[](#system-requirements "Permalink") + +Elasticsearch 需要的资源超出了[GitLab 系统要求中](../install/requirements.html)记录的资源. 这些会因安装大小而异,但是,根据[官方指南](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html) ,您应确保每个 Elasticsearch 节点**至少至少**有**8 GiB RAM** . + +请记住,这是 Elasticsearch 的**最低要求** . 对于生产实例,他们建议使用更多的资源. + +所需的存储空间在很大程度上取决于要存储在 GitLab 中的存储库的大小,但是根据经验,由于所有存储库加起来,您应该至少有 50%的可用空间. + +## Enabling Elasticsearch[](#enabling-elasticsearch "Permalink") + +为了启用 Elasticsearch,您需要具有管理员权限. 导航到**管理区域** (扳手图标),然后导航到**设置>集成**并展开**Elasticsearch**部分. + +单击**保存更改**以使更改生效. + +可以使用以下 Elasticsearch 设置: + +| Parameter | Description | +| --- | --- | +| `Elasticsearch indexing` | 启用/禁用 Elasticsearch 索引编制. 例如,您可能想要启用索引编制但禁用搜索以使索引有时间完全完成. 另外,请记住,此选项对现有数据没有任何影响,仅启用/禁用跟踪数据更改的后台索引器. 因此,通过启用此功能,您将不会为现有数据建立索引,请按照[将 GitLab 的数据添加到 Elasticsearch 索引中所述的](#adding-gitlabs-data-to-the-elasticsearch-index)那样,使用特殊的 Rake 任务. | +| `Elasticsearch pause indexing` | 启用/禁用临时索引暂停. 这对于群集迁移/重新索引很有用. 仍会跟踪所有更改,但是直到未暂停它们才提交给 Elasticsearch 索引. | +| `Search with Elasticsearch enabled` | 在搜索中使用 Elasticsearch 启用/禁用. | +| `URL` | 用于连接到 Elasticsearch 的 URL. 使用逗号分隔的列表来支持群集(例如, `http://host1, https://host2:9200` ). 如果您的 Elasticsearch 实例受密码保护,请在 URL 中传递`username:password` (例如, `http://:@:9200/` ). | +| `Number of Elasticsearch shards` | 出于性能原因,Elasticsearch 索引分为多个碎片. 通常,较大的索引需要具有更多的分片. 在重新创建索引之前,对该值所做的更改才会生效. 您可以在[Elasticsearch 文档中](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html#create-index-settings)阅读有关权衡的更多信息 | +| `Number of Elasticsearch replicas` | 每个 Elasticsearch 分片可以具有多个副本. 这些是分片的完整副本,可以提高查询性能或抵御硬件故障. 增大该值将大大增加索引所需的总磁盘空间. | +| `Limit namespaces and projects that can be indexed` | 启用此选项将允许您选择要索引的名称空间和项目. 所有其他名称空间和项目将改为使用数据库搜索. 请注意,如果启用此选项但未选择任何名称空间或项目,则不会为它们建立索引. [在下面阅读更多内容](#limiting-namespaces-and-projects) . | +| `Using AWS hosted Elasticsearch with IAM credentials` | 使用[AWS IAM 授权](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html)或[AWS EC2 实例配置文件凭证](https://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html#getting-started-create-iam-instance-profile-cli)对 Elasticsearch 请求进行签名. 必须将策略配置为允许`es:*`操作. | +| `AWS Region` | 您的 Elasticsearch 服务所在的 AWS 区域. | +| `AWS Access Key` | AWS 访问密钥. | +| `AWS Secret Access Key` | AWS 秘密访问密钥. | +| `Maximum field length` | See [the explanation in instance limits.](../administration/instance_limits.html#maximum-field-length). | +| `Maximum bulk request size (MiB)` | 最大批量请求大小由 GitLab 基于 Golang 的索引器流程使用,并指示在将有效负载提交给 Elasticsearch 的批量 API 之前,它应在给定的索引过程中收集(并存储在内存中)多少数据. 此设置应与批量请求并发设置一起使用(请参见下文),并且需要通过`gitlab-rake`命令或通过`gitlab-rake`命令来适应 Elasticsearch 主机和运行 GitLab 基于 Golang 的索引器的主机的资源限制. Sidekiq 任务. | +| `Bulk request concurrency` | 批量请求并发指示可以并行运行多少个 GitLab 基于 Golang 的索引器进程(或线程)来收集数据,然后将其提交给 Elasticsearch 的批量 API. 这可以提高索引编制性能,但可以更快地填充 Elasticsearch 批量请求队列. 此设置应与最大批量请求大小设置(请参见上文)一起使用,并且需要容纳`gitlab-rake`的 Elasticsearch 主机和运行 GitLab 基于 Golang 的索引器的主机的资源限制命令或 Sidekiq 任务. | + +### Limiting namespaces and projects[](#limiting-namespaces-and-projects "Permalink") + +如果选择" `Limit namespaces and projects that can be indexed`更多选项可用 [![限制名称空间和项目选项](img/39b4809628ba97edb93621d6eefa5135.png)](img/limit_namespaces_projects_options.png) + +您可以选择名称空间和项目以排他索引. 请注意,如果名称空间是一个组,它将包括所有子组以及属于这些子组的要被索引的项目. + +如果所有名称空间都已建立索引,Elasticsearch 仅提供跨组代码/提交搜索(全局). 在仅对名称空间的子集进行索引的特定情况下,全局搜索将不提供代码或提交范围. 这仅在索引命名空间的范围内才有可能. 当前,无法对多个已索引的名称空间进行编码/提交搜索(当仅对名称空间的子集进行索引时). 例如,如果两个组都已建立索引,则无法在两个组上运行单个代码搜索. 您只能在第一组上然后在第二组上运行代码搜索. + +您可以通过编写感兴趣的部分名称空间或项目名称来过滤选择下拉列表. + +[![limit namespace filter](img/471bcfe6a44b22703662997289b517c9.png)](img/limit_namespace_filter.png) + +**注意:**如果未选择名称空间或项目,则不会进行 Elasticsearch 索引.**警告:**如果您已经为实例建立索引,则必须重新生成索引,才能删除所有现有数据以进行过滤以使其正常工作. 为此,请运行 Rake 任务`gitlab:elastic:recreate_index`和`gitlab:elastic:clear_index_status` . 然后,从列表中删除名称空间或项目将按预期从 Elasticsearch 索引中删除数据. + +## Disabling Elasticsearch[](#disabling-elasticsearch "Permalink") + +要禁用 Elasticsearch 集成: + +1. 导航到**管理区域** (扳手图标),然后导航到**设置>集成** . +2. 展开**Elasticsearch**部分,然后取消选中**Elasticsearch 索引**和**启用** **Elasticsearch 的** **搜索** . +3. 单击**保存更改**以使更改生效. +4. (可选)删除现有索引: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:delete_index + + # Installations from source + bundle exec rake gitlab:elastic:delete_index RAILS_ENV=production + ``` + +## Adding GitLab’s data to the Elasticsearch index[](#adding-gitlabs-data-to-the-elasticsearch-index "Permalink") + +启用 Elasticsearch 索引编制后,您的 GitLab 实例中的新更改将在发生更改时自动进行索引. 要回填现有数据,可以使用以下方法之一在后台作业中对其进行索引. + +### Indexing through the administration UI[](#indexing-through-the-administration-ui "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15390) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +通过管理区域建立索引: + +1. [Configure your Elasticsearch host and port](#enabling-elasticsearch). +2. 创建空索引: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:create_empty_index + + # Installations from source + bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production + ``` + +3. [Enable **Elasticsearch indexing**](#enabling-elasticsearch). +4. Click **索引所有项目** in **管理区域>设置>集成> Elasticsearch**. +5. 单击确认消息中的**检查进度** ,以查看后台作业的状态. +6. 个人摘要需要手动编制索引: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index_snippets + + # Installations from source + bundle exec rake gitlab:elastic:index_snippets RAILS_ENV=production + ``` + +7. 索引完成后,启用[**Search with Elasticsearch**](#enabling-elasticsearch) . + +### Indexing through Rake tasks[](#indexing-through-rake-tasks "Permalink") + +可以使用 Rake 任务执行索引. + +#### Indexing small instances[](#indexing-small-instances "Permalink") + +**警告:**这将删除您现有的索引. + +如果数据库大小小于 500 MiB,并且所有托管存储库的大小小于 5 GiB: + +1. [Configure your Elasticsearch host and port](#enabling-elasticsearch). +2. 索引您的数据: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index + + # Installations from source + bundle exec rake gitlab:elastic:index RAILS_ENV=production + ``` + +3. 索引完成后,启用[**Search with Elasticsearch**](#enabling-elasticsearch) . + +#### Indexing large instances[](#indexing-large-instances "Permalink") + +**警告:**执行异步索引编制将生成很多 Sidekiq 作业. 确保具有[可扩展和高度可用的设置](README.html)或创建[额外的 Sidekiq 进程](../administration/operations/extra_sidekiq_processes.html)以为该任务做准备 + +1. [Configure your Elasticsearch host and port](#enabling-elasticsearch). +2. 创建空索引: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:create_empty_index + + # Installations from source + bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production + ``` + +3. 如果这是您的 GitLab 实例的重新索引,请清除索引状态: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:clear_index_status + + # Installations from source + bundle exec rake gitlab:elastic:clear_index_status RAILS_ENV=production + ``` + +4. [Enable **Elasticsearch indexing**](#enabling-elasticsearch). +5. 索引大型 Git 存储库可能需要一段时间. 为了加快此过程,您可以暂时禁用自动刷新和复制. 根据我们的经验,您可以预期索引编制时间将减少 20%. 索引完成后,我们将启用它们. 此步骤是可选的! + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{ + "index" : { + "refresh_interval" : "-1", + "number_of_replicas" : 0 + } }' + ``` + +6. 索引项目及其相关数据: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index_projects + + # Installations from source + bundle exec rake gitlab:elastic:index_projects RAILS_ENV=production + ``` + + 这为需要索引的每个项目加入了一个 Sidekiq 作业. 您可以在**管理区域>监视>后台作业>队列选项卡中**查看作业,然后单击`elastic_indexer` ,也可以使用 Rake 任务查询索引状态: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index_projects_status + + # Installations from source + bundle exec rake gitlab:elastic:index_projects_status RAILS_ENV=production + + Indexing is 65.55% complete (6555/10000 projects) + ``` + + 如果要将索引限制为一定范围的项目,可以提供`ID_FROM`和`ID_TO`参数: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index_projects ID_FROM=1001 ID_TO=2000 + + # Installations from source + bundle exec rake gitlab:elastic:index_projects ID_FROM=1001 ID_TO=2000 RAILS_ENV=production + ``` + + 其中`ID_FROM`和`ID_TO`是项目 ID. 这两个参数都是可选的. 上面的示例将索引从 ID `1001`到(并包括)ID `2000`所有项目. + + **故障排除:**有时`gitlab:elastic:index_projects`排队的项目索引作业可能会中断. 出于多种原因可能会发生这种情况,但是再次运行索引任务始终是安全的. 它将跳过已经建立索引的存储库. + + 当索引器在数据库中存储每个已索引存储库的最后一次提交 SHA 时,您可以使用特殊参数`UPDATE_INDEX`运行索引器,它将再次检查每个项目存储库以确保对存储库中的每个提交都进行了索引,这很有用.如果您的索引已过时: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index_projects UPDATE_INDEX=true ID_TO=1000 + + # Installations from source + bundle exec rake gitlab:elastic:index_projects UPDATE_INDEX=true ID_TO=1000 RAILS_ENV=production + ``` + + 您还可以使用`gitlab:elastic:clear_index_status` Rake 任务来强制索引器"忘记"所有进度,因此它将从头开始重试索引过程. + +7. 个人代码段与项目无关,需要单独编制索引: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index_snippets + + # Installations from source + bundle exec rake gitlab:elastic:index_snippets RAILS_ENV=production + ``` + +8. 在建立索引后再次启用复制和刷新(仅在您之前禁用它的情况下): + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{ + "index" : { + "number_of_replicas" : 1, + "refresh_interval" : "1s" + } }' + ``` + + 启用上述刷新后,应调用强制合并. + + 对于 Elasticsearch 6.x,在进行强制合并之前,索引应处于只读模式: + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{ + "settings": { + "index.blocks.write": true + } }' + ``` + + 然后,启动强制合并: + + ``` + curl --request POST 'localhost:9200/gitlab-production/_forcemerge?max_num_segments=5' + ``` + + 此后,如果索引处于只读模式,请切换回读写模式: + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{ + "settings": { + "index.blocks.write": false + } }' + ``` + +9. 索引完成后,启用[**Search with Elasticsearch**](#enabling-elasticsearch) . + +### Indexing limitations[](#indexing-limitations "Permalink") + +对于存储库和摘要文件,GitLab 最多只能索引 1 MiB 的内容,以避免索引超时. + +## GitLab Elasticsearch Rake tasks[](#gitlab-elasticsearch-rake-tasks "Permalink") + +耙任务可用于: + +* [生成并安装](#building-and-installing)索引器. +* [禁用 Elasticsearch](#disabling-elasticsearch)时删除索引. +* [将 GitLab 数据添加](#adding-gitlabs-data-to-the-elasticsearch-index)到索引. + +以下是一些可用的 Rake 任务: + +| Task | Description | +| --- | --- | +| [`sudo gitlab-rake gitlab:elastic:index`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 启用 Elasticsearch 索引并运行`gitlab:elastic:create_empty_index` , `gitlab:elastic:clear_index_status` , `gitlab:elastic:index_projects`和`gitlab:elastic:index_snippets` . | +| [`sudo gitlab-rake gitlab:elastic:index_projects`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 遍历所有项目并在 Sidekiq 作业中排队以在后台对它们进行索引. | +| [`sudo gitlab-rake gitlab:elastic:index_projects_status`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 确定索引的总体状态. 通过计算索引项目的总数,除以项目总数,然后乘以 100 即可完成. | +| [`sudo gitlab-rake gitlab:elastic:clear_index_status`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 删除所有项目的 IndexStatus 的所有实例. | +| [`sudo gitlab-rake gitlab:elastic:create_empty_index[]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 生成一个空索引,并为该索引分配一个别名(仅当该索引不存在时). | +| [`sudo gitlab-rake gitlab:elastic:delete_index[]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 删除 Elasticsearch 实例上的 GitLab 索引和别名(如果存在). | +| [`sudo gitlab-rake gitlab:elastic:recreate_index[]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | `gitlab:elastic:delete_index[]`和`gitlab:elastic:create_empty_index[]`包装器任务. | +| [`sudo gitlab-rake gitlab:elastic:index_snippets`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 执行 Elasticsearch 导入,对片段数据进行索引. | +| [`sudo gitlab-rake gitlab:elastic:projects_not_indexed`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 显示未索引的项目. | +| [`sudo gitlab-rake gitlab:elastic:reindex_cluster`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 安排零停机群集重新索引编制任务. 此功能应与在 GitLab 13.0 之后创建的索引一起使用. | + +**注意:** `TARGET_NAME`参数是可选的,如果未设置,它将使用当前`RAILS_ENV`的默认索引/别名. + +### Environment variables[](#environment-variables "Permalink") + +除了 Rake 任务,还有一些环境变量可用于修改过程: + +| 环境变量 | 数据类型 | 它能做什么 | +| --- | --- | --- | +| `UPDATE_INDEX` | Boolean | 告诉索引器覆盖任何现有索引数据(对/错). | +| `ID_TO` | Integer | 告诉索引器仅索引小于或等于该值的项目. | +| `ID_FROM` | Integer | 告诉索引器仅索引大于或等于该值的项目. | + +### Indexing a specific project[](#indexing-a-specific-project "Permalink") + +因为`ID_TO`和`ID_FROM`环境变量使用`or equal to`比较,所以您可以通过使用两个具有相同项目 ID 号的变量来仅索引一个项目: + +``` +root@git:~# sudo gitlab-rake gitlab:elastic:index_projects ID_TO=5 ID_FROM=5 +Indexing project repositories...I, [2019-03-04T21:27:03.083410 #3384] INFO -- : Indexing GitLab User / test (ID=33)... +I, [2019-03-04T21:27:05.215266 #3384] INFO -- : Indexing GitLab User / test (ID=33) is done! +``` + +## Elasticsearch index scopes[](#elasticsearch-index-scopes "Permalink") + +执行搜索时,GitLab 索引将使用以下范围: + +| 范围名称 | What it searches | +| --- | --- | +| `commits` | 提交数据 | +| `projects` | 项目数据(默认) | +| `blobs` | Code | +| `issues` | 发行数据 | +| `merge_requests` | 合并请求数据 | +| `milestones` | 里程碑数据 | +| `notes` | 笔记数据 | +| `snippets` | 片段数据 | +| `wiki_blobs` | 维基内容 | + +## Tuning[](#tuning "Permalink") + +### Guidance on choosing optimal cluster configuration[](#guidance-on-choosing-optimal-cluster-configuration "Permalink") + +有关选择集群配置的基本指导,请参考[Elastic Cloud Calculator](https://cloud.elastic.co/pricing) . 您可以在下面找到更多信息. + +* 通常,您将希望至少将一个 2 节点群集配置与一个副本一起使用,这将使您具有弹性. 如果存储使用量快速增长,则可能需要预先计划水平扩展(添加更多节点). +* 不建议将 HDD 存储与搜索群集一起使用,因为它会影响性能. 最好使用 SSD 存储(例如 NVMe 或 SATA SSD 驱动器). +* 您可以使用[GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance)来对不同搜索集群大小和配置的搜索性能进行基准测试. +* `Heap size`应设置为不超过物理 RAM 的 50%. 此外,不应将其设置为超过基于零的压缩 oop 的阈值. 确切的阈值会有所不同,但是在大多数系统上 26 GB 是安全的,但在某些系统上也可能高达 30 GB. 有关更多详细信息,请参见[设置堆大小](https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html#heap-size) . +* 每个节点的 CPU(CPU 核心)数通常对应于以下所述`Number of Elasticsearch shards`设置. +* 一个好的指导方针是确保每个节点的已配置 GB 堆中的碎片数保持在 20 个以下. 因此,具有 30GB 堆的节点最多应具有 600 个分片,但是越低于此限制,您可以使其越好. 通常,这将有助于群集保持良好的运行状况. +* 小碎片会导致小段,这会增加开销. 旨在将平均分片大小保持在至少几 GB 到几十 GB 之间. 另一个考虑因素是文档数量,您应该针对此简单的分片`number of expected documents / 5M +1`公式: `number of expected documents / 5M +1` . +* `refresh_interval`是每个索引设置. 如果您不需要实时数据,则可能需要将其从默认的`1s`调整为更大的值. 这将改变您看到新结果的时间. 如果这对您很重要,则应使其尽可能接近默认值. +* 如果您有大量繁重的索引操作,则可能需要将[`indices.memory.index_buffer_size`](https://www.elastic.co/guide/en/elasticsearch/reference/current/indexing-buffer.html)提高到 30%或 40%. + +### Elasticsearch integration settings guidance[](#elasticsearch-integration-settings-guidance "Permalink") + +* The `Number of Elasticsearch shards` setting usually corresponds with the number of CPUs available in your cluster. For example, if you have a 3-node cluster with 4 cores each, this means you will benefit from having at least 3*4=12 shards in the cluster. Please note, it’s only possible to change the shards number by using [Split index API](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-split-index.html) or by reindexing to a different index with a changed number of shards. +* `Number of Elasticsearch replicas`设置在大多数情况下应等于`1` (每个分片将具有 1 个副本). 不建议使用`0` ,因为丢失一个节点会破坏索引. + +### Deleted documents[](#deleted-documents "Permalink") + +每当对索引的 GitLab 对象进行更改或删除时(合并请求描述发生更改,从存储库中的 master 分支中删除文件,删除项目等),索引中的文档也会被删除. 但是,由于这些是"软"删除,因此"已删除文档"的总数增加了,因此浪费了空间. Elasticsearch 进行段的智能合并,以删除这些已删除的文档. 但是,根据 GitLab 安装中活动的数量和类型,可能会在索引中看到多达 50%的浪费空间. + +通常,我们建议仅使用默认设置让 Elasticsearch 自动合并和回收空间. 在[Lucene 的"已删除文档处理"中](https://www.elastic.co/blog/lucenes-handling-of-deleted-documents "Lucene 处理已删除文件的方法") , *"总的来说,除了减小最大段大小外,最好将 Lucene 的默认值保持原样,并且不要对回收删除时感到担心."* + +但是,某些较大的安装可能希望调整合并策略设置: + +* 考虑将`index.merge.policy.max_merged_segment`大小从默认的 5 GB 减小到 2 GB 或 3 GB. 仅当段中至少有 50%的删除时才进行合并. 较小的段大小将允许合并更频繁地发生. + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings ---header 'Content-Type: application/json' --data '{ + "index" : { + "merge.policy.max_merged_segment": "2gb" + } + }' + ``` + +* 您还可以调整`index.merge.policy.reclaim_deletes_weight` ,它控制如何积极地定位删除. 但是,这可能会导致代价高昂的合并决策,因此,除非您了解取舍,否则我们建议不要更改此决策. + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings ---header 'Content-Type: application/json' --data '{ + "index" : { + "merge.policy.reclaim_deletes_weight": "3.0" + } + }' + ``` + +* 不要[强制合并](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html "强制合并")以删除已删除的文档. [文档中](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html "强制合并")的警告指出,这可能导致很大的网段,这些网段可能永远都无法收回,并且还可能导致严重的性能或可用性问题. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Common issues[](#common-issues "Permalink") + +以下是一些常见的陷阱以及如何克服它们: + +* **如何验证我的 GitLab 实例正在使用 Elasticsearch?** + + 最简单的方法是通过运行以下`sudo gitlab-rails console`通过 rails 控制台( `sudo gitlab-rails console` ): + + ``` + u = User.find_by_username('your-username') + s = SearchService.new(u, {:search => 'search_term'}) + pp s.search_objects.class.name + ``` + + 如果看到`"ActiveRecord::Relation"` ,则说明您**未**使用 Elasticsearch. + + If you see `"Kaminari::PaginatableArray"` you are using Elasticsearch. + + **注意:**以上说明仅用于在索引所有名称空间时验证 GitLab 是否正在使用 Elasticsearch. 这仅用于仅索引[命名空间子集的](#limiting-namespaces-and-projects)方案. +* **我更新了 GitLab,现在找不到任何东西** + + 我们会不断更新索引策略,并致力于支持新版本的 Elasticsearch. 进行索引更改时,更新 GitLab 后可能需要重新编制[索引](#adding-gitlabs-data-to-the-elasticsearch-index) . + +* **我索引了所有存储库,但找不到任何内容** + + 确保[如上所述对](#adding-gitlabs-data-to-the-elasticsearch-index)所有数据库数据建立索引. + + 除此之外,通过[Elasticsearch Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html)检查数据是否在 Elasticsearch 端显示. + + 如果通过[Elasticsearch Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html)显示,请检查是否通过 rails 控制台( `sudo gitlab-rails console` )显示: + + ``` + u = User.find_by_username('your-username') + s = SearchService.new(u, {:search => 'search_term', :scope => 'blobs'}) + pp s.search_objects.to_a + ``` + + **注意:**以上说明不适用于仅索引[命名空间子集的情况](#limiting-namespaces-and-projects) . + + 有关搜索特定数据类型的更多信息,请参见[Elasticsearch 索引范围](#elasticsearch-index-scopes) . + +* **我索引了所有存储库,但随后切换了 Elasticsearch 服务器,现在什么也找不到** + + 您将需要重新运行所有 Rake 任务,以重新索引数据库,存储库和 Wiki. + +* **索引过程需要很长时间** + + GitLab 实例中存在的数据越多,索引过程花费的时间就越长. + +* **有些项目未编入索引,但我们不知道哪些项目** + + 您可以运行`sudo gitlab-rake gitlab:elastic:projects_not_indexed`以显示未建立索引的项目. + +* **"如果未配置父字段,则无法指定父"** + + 如果您在 GitLab 8.12 之前启用了 Elasticsearch 并且尚未重建索引,则在许多不同情况下,您将获得异常: + + ``` + Elasticsearch::Transport::Transport::Errors::BadRequest([400] { + "error": { + "root_cause": [{ + "type": "illegal_argument_exception", + "reason": "Can't specify parent if no parent field has been configured" + }], + "type": "illegal_argument_exception", + "reason": "Can't specify parent if no parent field has been configured" + }, + "status": 400 + }): + ``` + + 这是因为我们在 GitLab 8.12 中更改了索引映射,并且应该删除旧索引并再次从头开始构建,请参阅[8-11-to-8-12 更新指南中的](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/update/8.11-to-8.12.md#11-elasticsearch-index-update-if-you-currently-use-elasticsearch)详细信息. + +* Exception `Elasticsearch::Transport::Transport::Errors::BadRequest` + + 如果您有此例外情况(就像上面的情况一样,但实际消息有所不同),请检查您是否具有正确的 Elasticsearch 版本并满足其他[要求](#system-requirements) . 还有一种简单的方法可以使用`sudo gitlab-rake gitlab:check`命令自动检查它. + +* Exception `Elasticsearch::Transport::Transport::Errors::RequestEntityTooLarge` + + ``` + [413] {"Message":"Request size exceeded 10485760 bytes"} + ``` + + 当您将 Elasticsearch 集群配置为拒绝某个大小以上的请求(在这种情况下为 10MiB)时,会看到此异常. 这相当于`http.max_content_length`在设置`elasticsearch.yml` . 将其增大到更大的大小,然后重新启动您的 Elasticsearch 集群. + + AWS 根据基础实例的大小对此设置有[固定的限制](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/aes-limits.html) (" HTTP 请求有效负载的最大大小"). + +* **即使一切似乎都正常运行,我的单节点 Elasticsearch 集群状态也从未从`yellow`变为`green`** + + **对于单节点 Elasticsearch 集群,功能集群的运行状况为黄色** (永远不会为绿色),因为已分配了主要分片,但副本却无法存在,因为没有其他节点可为 Elasticsearch 分配副本. 如果您使用的是[Amazon Elasticsearch](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/aes-handling-errors.html#aes-handling-errors-yellow-cluster-status) Service,这也适用. + + **警告:**建议不要将副本数设置为`0` (GitLab Elasticsearch 集成菜单中不允许这样做). 如果您计划添加更多的 Elasticsearch 节点(总共超过 1 个 Elasticsearch 节点),则副本数将需要设置为大于`0`的整数值. 否则,将导致缺乏冗余(丢失一个节点将破坏索引). + + 如果您**对单节点 Elasticsearch 集群有绿色状态**的**严格要求** ,请确保您了解上一段概述的风险,然后只需运行以下查询将副本数设置为`0` (集群将不会再尝试创建任何碎片副本): + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{ + "index" : { + "number_of_replicas" : 0 + } + }' + ``` + +* **我正在`health check timeout: no Elasticsearch node available`索引编制过程中 Sidekiq 中`health check timeout: no Elasticsearch node available`错误** + + ``` + Gitlab::Elastic::Indexer::Error: time="2020-01-23T09:13:00Z" level=fatal msg="health check timeout: no Elasticsearch node available" + ``` + + 您可能没有在 Elasticsearch 集成菜单的**" URL"**字段中使用`http://`或`https://`作为值的一部分. 请确保在此字段中使用`http://`或`https://`作为我们使用的[Go](https://github.com/olivere/elastic)的[Elasticsearch 客户端,](https://github.com/olivere/elastic) [需要将该 URL 的前缀接受为有效](https://github.com/olivere/elastic/commit/a80af35aa41856dc2c986204e2b64eab81ccac3a) . 更正了网址格式后,请删除索引(通过[专用的 Rake 任务](#gitlab-elasticsearch-rake-tasks) ),然后[为实例的内容重新编制索引](#adding-gitlabs-data-to-the-elasticsearch-index) . + +### Low-level troubleshooting[](#low-level-troubleshooting "Permalink") + +当您遇到其他问题(包括性能不佳)时[,](../administration/troubleshooting/elasticsearch.html)可以使用[结构化的低级故障排除文档](../administration/troubleshooting/elasticsearch.html) . + +### Known Issues[](#known-issues "Permalink") + +* **[Elasticsearch `code_analyzer` doesn’t account for all code cases](https://gitlab.com/gitlab-org/gitlab/-/issues/10693)** + + 正在评估`code_analyzer`模式和过滤器配置以进行改进. 我们注意到由于我们的模式和过滤器配置, [一些边缘情况](https://gitlab.com/gitlab-org/gitlab/-/issues/10693#note_158382332)未返回预期的搜索结果. + + 在[问题 29443](https://gitlab.com/gitlab-org/gitlab/-/issues/29443)中,讨论了`code_analyzer`模式和过滤器的改进策略. + +### Reverting to basic search[](#reverting-to-basic-search "Permalink") + +有时,您的 Elasticsearch 索引数据可能存在问题,因此,如果没有搜索结果并且假定该范围内支持基本搜索,则 GitLab 将允许您恢复为"基本搜索". 这种"基本搜索"的行为就像您根本没有为实例启用 Elasticsearch 并使用其他数据源(即 PostgreSQL 数据和 Git 数据)进行搜索一样. \ No newline at end of file diff --git a/_book/docs/468.md b/_book/docs/468.md new file mode 100644 index 0000000000000000000000000000000000000000..b1f732e7445712c4ce6a53931c348fddbce35bce --- /dev/null +++ b/_book/docs/468.md @@ -0,0 +1,1068 @@ +# Gitaly + +> 原文:[https://docs.gitlab.com/ee/administration/gitaly/](https://docs.gitlab.com/ee/administration/gitaly/) + +* [Architecture](#architecture) +* [Configure Gitaly](#configure-gitaly) +* [Run Gitaly on its own server](#run-gitaly-on-its-own-server) + * [Network architecture](#network-architecture) + * [Install Gitaly](#install-gitaly) + * [Configure authentication](#configure-authentication) + * [Configure Gitaly servers](#configure-gitaly-servers) + * [Configure Gitaly clients](#configure-gitaly-clients) + * [Mixed configuration](#mixed-configuration) + * [Disable Gitaly where not required (optional)](#disable-gitaly-where-not-required-optional) +* [Enable TLS support](#enable-tls-support) + * [Observe type of Gitaly connections](#observe-type-of-gitaly-connections) +* [`gitaly-ruby`](#gitaly-ruby) + * [Configure number of `gitaly-ruby` workers](#configure-number-of-gitaly-ruby-workers) +* [Limit RPC concurrency](#limit-rpc-concurrency) +* [Rotate Gitaly authentication token](#rotate-gitaly-authentication-token) + * [Verify authentication monitoring](#verify-authentication-monitoring) + * [Enable “auth transitioning” mode](#enable-auth-transitioning-mode) + * [Update Gitaly authentication token](#update-gitaly-authentication-token) + * [Ensure there are no authentication failures](#ensure-there-are-no-authentication-failures) + * [Disable “auth transitioning” mode](#disable-auth-transitioning-mode) + * [Verify authentication is enforced](#verify-authentication-is-enforced) +* [Direct Git access bypassing Gitaly](#direct-git-access-bypassing-gitaly) +* [Direct access to Git in GitLab](#direct-access-to-git-in-gitlab) + * [History](#history) + * [How it works](#how-it-works) + * [Transition to Gitaly Cluster](#transition-to-gitaly-cluster) +* [Troubleshooting Gitaly](#troubleshooting-gitaly) + * [Checking versions when using standalone Gitaly servers](#checking-versions-when-using-standalone-gitaly-servers) + * [`gitaly-debug`](#gitaly-debug) + * [Commits, pushes, and clones return a 401](#commits-pushes-and-clones-return-a-401) + * [Client side gRPC logs](#client-side-grpc-logs) + * [Observing `gitaly-ruby` traffic](#observing-gitaly-ruby-traffic) + * [Repository changes fail with a `401 Unauthorized` error](#repository-changes-fail-with-a-401-unauthorized-error) + * [Command line tools cannot connect to Gitaly](#command-line-tools-cannot-connect-to-gitaly) + * [Gitaly not listening on new address after reconfiguring](#gitaly-not-listening-on-new-address-after-reconfiguring) + * [Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly server](#permission-denied-errors-appearing-in-gitaly-logs-when-accessing-repositories-from-a-standalone-gitaly-server) + * [Praefect](#praefect) + +# Gitaly[](#gitaly "Permalink") + +[Gitaly](https://gitlab.com/gitlab-org/gitaly)是提供对 Git 存储库的高级 RPC 访问的服务. 没有它,任何 GitLab 组件都无法读取或写入 Git 数据. + +在 Gitaly 文档中: + +* **Gitaly 服务器**是指任何本身运行 Gitaly 的节点. +* **Gitaly 客户端**指的是任何运行向 Gitaly 服务器发出请求的进程的节点. 流程包括但不限于: + * [GitLab Rails 应用程序](https://gitlab.com/gitlab-org/gitlab) . + * [GitLab 外壳](https://gitlab.com/gitlab-org/gitlab-shell) . + * [亚搏体育 app Labhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) . + +GitLab 最终用户无法直接访问 Gitaly. Gitaly 仅管理 GitLab 的 Git 存储库访问. 其他类型的 GitLab 数据无法使用 Gitaly 访问. + +**警告:**从 GitLab 13.0 起,不支持 Gitaly 对 NFS 的支持. 在 GitLab 14.0 中,计划删除对 NFS 的 Gitaly 支持. 尽快升级到[Gitaly Cluster](praefect.html) . + +## Architecture[](#architecture "Permalink") + +以下是有关如何使用 Gitaly 的高级体系结构概述. + +[![Gitaly architecture diagram](img/eb93aca89ce7486ca89aa5a9f4357617.png)](img/architecture_v12_4.png) + +## Configure Gitaly[](#configure-gitaly "Permalink") + +Gitaly 服务本身是通过[TOML 配置文件配置的](reference.html) . + +要更改 Gitaly 设置,请执行以下操作: + +**对于所有 GitLab** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加或更改[Gitaly 设置](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/1dd07197c7e5ae23626aad5a4a070a800b670380/files/gitlab-config-template/gitlab.rb.template#L1622-1676) . +2. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +**对于源安装** + +1. 编辑`/home/git/gitaly/config.toml`并添加或更改[Gitaly 设置](https://gitlab.com/gitlab-org/gitaly/blob/master/config.toml.example) . +2. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . + +以下配置选项也可用: + +* Enabling [TLS support](#enable-tls-support). +* 配置[`gitaly-ruby`工人](#configure-number-of-gitaly-ruby-workers)的[数量](#configure-number-of-gitaly-ruby-workers) . +* Limiting [RPC concurrency](#limit-rpc-concurrency). + +## Run Gitaly on its own server[](#run-gitaly-on-its-own-server "Permalink") + +默认情况下,Gitaly 与 Gitaly 客户端在同一服务器上运行,并按[上述配置](#configure-gitaly) . 单服务器安装最好由以下默认配置使用: + +* [Omnibus GitLab](https://docs.gitlab.com/omnibus/). +* GitLab [源代码安装指南](../../install/installation.html) . + +However, Gitaly can be deployed to its own server, which can benefit GitLab installations that span multiple machines. + +**注意:**配置为在自己的服务器上运行时, [必须先升级](https://docs.gitlab.com/omnibus/update/) Gitaly 服务器,然后才能在群集中的 Gitaly 客户端上[进行升级](https://docs.gitlab.com/omnibus/update/) . + +在自己的服务器上设置 Gitaly 的过程是: + +1. [Install Gitaly](#install-gitaly). +2. [Configure authentication](#configure-authentication). +3. [Configure Gitaly servers](#configure-gitaly-servers). +4. [Configure Gitaly clients](#configure-gitaly-clients). +5. [Disable Gitaly where not required](#disable-gitaly-where-not-required-optional) (optional). + +在自己的服务器上运行 Gitaly 时,请注意有关 GitLab 版本的以下内容: + +* 从 GitLab 11.4 起,除了[Elasticsearch indexer](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer)之外,Gitaly 能够满足所有 Git 请求,而无需为 Git 存储库数据共享 NFS 挂载. +* 从 GitLab 11.8 开始,Elasticsearch 索引器还使用 Gitaly 进行数据访问. NFS 仍可用于块级 Git 数据的冗余,但仅需安装在 Gitaly 服务器上. +* 从 GitLab 11.8 到 12.2,可以在不使用 NFS 的 Gitaly 设置中使用 Elasticsearch. 为了在这些版本中使用 Elasticsearch,必须在您的 GitLab 配置中启用[存储库索引器](../../integration/elasticsearch.html#elasticsearch-repository-indexer) . +* [从 GitLab 12.3 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/6481) ,新的索引器是默认的,不需要任何配置. + +### Network architecture[](#network-architecture "Permalink") + +以下列表描述了 Gitaly 的网络体系结构: + +* GitLab Rails shards repositories into [repository storages](../repository_storage_paths.html). +* `/config/gitlab.yml`包含从存储名称到`(Gitaly address, Gitaly token)`对的`(Gitaly address, Gitaly token)` . +* `/config/gitlab.yml`的`storage name` -> `(Gitaly address, Gitaly token)`映射是 Gitaly 网络拓扑的唯一事实来源. +* `(Gitaly address, Gitaly token)`对应于 Gitaly 服务器. +* Gitaly 服务器托管一个或多个存储. +* 一个 Gitaly 客户端可以使用一个或多个 Gitaly 服务器. +* 必须以对**所有** Gitaly 客户端正确解析的方式指定 Gitaly 地址. +* Gitaly 客户包括: + * 美洲狮或独角兽. + * Sidekiq. + * 亚搏体育 app Labhorse. + * GitLab 外壳. + * Elasticsearch 索引器. + * Gitaly 本身. +* 一个 Gitaly 服务器必须能够通过其自身发出 RPC 调用**本身** `(Gitaly address, Gitaly token)`在指定的一对`/config/gitlab.yml` . +* 认证通过静态令牌完成,该令牌在 Gitaly 和 GitLab Rails 节点之间共享. + +**危险:** Gitaly 服务器不得暴露于公共互联网,因为默认情况下 Gitaly 的网络流量未加密. 强烈建议使用防火墙,以限制对 Gitaly 服务器的访问. 另一种选择是[使用 TLS](#enable-tls-support) . + +在以下各节中,我们描述如何使用秘密令牌`abc123secret`配置两个 Gitaly 服务器: + +* `gitaly1.internal`. +* `gitaly2.internal`. + +我们假设您的 GitLab 安装具有三个存储库存储: + +* `default`. +* `storage1`. +* `storage2`. + +如果需要,一台服务器最多只能使用一个存储库. + +**注意:** Gitaly 文档中引用的令牌只是管理员选择的任意密码. 它与为 GitLab API 创建的令牌或其他类似的 Web API 令牌无关. + +### Install Gitaly[](#install-gitaly "Permalink") + +使用 Omnibus GitLab 在每台 Gitaly 服务器上安装 Gitaly 或从源代码安装它: + +* 对于 Omnibus GitLab,请[下载并安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包,但**不要**提供`EXTERNAL_URL=`值. +* 要从源代码安装,请遵循[Install Gitaly 上](../../install/installation.html#install-gitaly)的步骤. + +### Configure authentication[](#configure-authentication "Permalink") + +Gitaly 和 GitLab 使用两个共享的机密进行身份验证: + +* 一种用于向 Gitaly 验证 gRPC 请求的身份. +* A second for authentication callbacks from GitLab Shell to the GitLab internal API. + +**对于所有 GitLab** + +要配置 Gitaly 令牌: + +1. 在 Gitaly 客户端上,编辑`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_rails['gitaly_token'] = 'abc123secret' + ``` + +2. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +3. 在 Gitaly 服务器上,编辑`/etc/gitlab/gitlab.rb` : + + ``` + gitaly['auth_token'] = 'abc123secret' + ``` + +4. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +有两种方法可以配置 GitLab Shell 令牌. + +方法 1: + +1. 将`/etc/gitlab/gitlab-secrets.json`从 Gitaly 客户端复制到 Gitaly 服务器(和任何其他 Gitaly 客户端)上的相同路径. +2. 在 Gitaly 服务器上[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +方法 2: + +1. 在 Gitaly 客户端上,编辑`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_shell['secret_token'] = 'shellsecret' + ``` + +2. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +3. 在 Gitaly 服务器上,编辑`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_shell['secret_token'] = 'shellsecret' + ``` + +4. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +**对于源安装** + +1. 将`/home/git/gitlab/.gitlab_shell_secret`从 Gitaly 客户端复制到 Gitaly 服务器(和任何其他 Gitaly 客户端)上的相同路径. +2. 在 Gitaly 客户端上,编辑`/home/git/gitlab/config/gitlab.yml` : + + ``` + gitlab: + gitaly: + token: 'abc123secret' + ``` + +3. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . +4. 在 Gitaly 服务器上,编辑`/home/git/gitaly/config.toml` : + + ``` + [auth] + token = 'abc123secret' + ``` + +5. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . + +### Configure Gitaly servers[](#configure-gitaly-servers "Permalink") + +在 Gitaly 服务器上,您必须配置存储路径并启用网络侦听器. + +如果要减少启用身份验证时发生停机的风险,可以暂时禁用强制实施. 有关更多信息,请参阅有关配置[Gitaly 身份验证](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/configuration/README.md#authentication)的文档. + +**对于所有 GitLab** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + # /etc/gitlab/gitlab.rb + + # Avoid running unnecessary services on the Gitaly server + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + puma['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + grafana['enable'] = false + gitlab_exporter['enable'] = false + + # If you run a separate monitoring node you can disable these services + alertmanager['enable'] = false + prometheus['enable'] = false + + # If you don't run a separate monitoring node you can + # enable Prometheus access & disable these extra services. + # This makes Prometheus listen on all interfaces. You must use firewalls to restrict access to this address/port. + # prometheus['listen_address'] = '0.0.0.0:9090' + # prometheus['monitor_kubernetes'] = false + + # If you don't want to run monitoring services uncomment the following (not recommended) + # node_exporter['enable'] = false + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your 'front door' GitLab URL or an internal load + # balancer. + # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from Gitaly client to Gitaly server. + gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' + + # Make Gitaly accept connections on all network interfaces. You must use + # firewalls to restrict access to this address/port. + # Comment out following line if you only want to support TLS connections + gitaly['listen_addr'] = "0.0.0.0:8075" + ``` + +2. 对于每个相应的 Gitaly 服务器,将以下内容附加到`/etc/gitlab/gitlab.rb` : + + On `gitaly1.internal`: + + ``` + git_data_dirs({ + 'default' => { + 'path' => '/var/opt/gitlab/git-data' + }, + 'storage1' => { + 'path' => '/mnt/gitlab/git-data' + }, + }) + ``` + + On `gitaly2.internal`: + + ``` + git_data_dirs({ + 'storage2' => { + 'path' => '/srv/gitlab/git-data' + }, + }) + ``` + +3. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +4. 运行`sudo /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml`以确认 Gitaly 可以执行对 GitLab 内部 API 的回调. + +**对于源安装** + +1. Edit `/home/git/gitaly/config.toml`: + + ``` + listen_addr = '0.0.0.0:8075' + + internal_socket_dir = '/var/opt/gitlab/gitaly' + + [logging] + format = 'json' + level = 'info' + dir = '/var/log/gitaly' + ``` + +2. 对于每个相应的 Gitaly 服务器,将以下内容附加到`/home/git/gitaly/config.toml` : + + On `gitaly1.internal`: + + ``` + [[storage]] + name = 'default' + path = '/var/opt/gitlab/git-data/repositories' + + [[storage]] + name = 'storage1' + path = '/mnt/gitlab/git-data/repositories' + ``` + + On `gitaly2.internal`: + + ``` + [[storage]] + name = 'storage2' + path = '/srv/gitlab/git-data/repositories' + ``` + +3. Edit `/home/git/gitlab-shell/config.yml`: + + ``` + gitlab_url: https://gitlab.example.com + ``` + +4. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . +5. 运行`sudo -u git /home/git/gitlab-shell/bin/check -config /home/git/gitlab-shell/config.yml`以确认 Gitaly 可以执行对 GitLab 内部 API 的回调. + +### Configure Gitaly clients[](#configure-gitaly-clients "Permalink") + +最后一步,您必须更新 Gitaly 客户端,使其从使用本地 Gitaly 服务切换为使用刚配置的 Gitaly 服务器. + +这可能会有风险,因为任何阻止您的 Gitaly 客户端访问 Gitaly 服务器的操作都将导致所有 Gitaly 请求失败. 例如,任何类型的网络,防火墙或名称解析问题. + +此外,如果以前手动启用,则必须[禁用 Rugged](../high_availability/nfs.html#improving-nfs-performance-with-gitlab) . + +Gitaly 作以下假设: + +* 你`gitaly1.internal` Gitaly 服务器可以达到`gitaly1.internal:8075`从 Gitaly 客户端,以及 Gitaly 服务器可以读取和写入`/mnt/gitlab/default`和`/mnt/gitlab/storage1` . +* 你`gitaly2.internal` Gitaly 服务器可以达到`gitaly2.internal:8075`从 Gitaly 客户端,以及 Gitaly 服务器可以读取和写入`/mnt/gitlab/storage2` . +* 您的`gitaly1.internal`和`gitaly2.internal` Gitaly 服务器可以相互访问. + +除非您使用特殊的[混合配置进行](#mixed-configuration)设置,否则不能将 Gitaly 服务器定义为本地 Gitaly 服务器(不带`gitaly_address` ),而`gitaly_address`一些服务器定义为远程服务器(带`gitaly_address` ). + +**对于所有 GitLab** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + ``` + +2. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +3. 运行`sudo gitlab-rake gitlab:gitaly:check`确认 Gitaly 客户端可以连接到 Gitaly 服务器. +4. 拖尾日志以查看请求: + + ``` + sudo gitlab-ctl tail gitaly + ``` + +**对于源安装** + +1. Edit `/home/git/gitlab/config/gitlab.yml`: + + ``` + gitlab: + repositories: + storages: + default: + gitaly_address: tcp://gitaly1.internal:8075 + path: /some/dummy/path + storage1: + gitaly_address: tcp://gitaly1.internal:8075 + path: /some/dummy/path + storage2: + gitaly_address: tcp://gitaly2.internal:8075 + path: /some/dummy/path + ``` + + **注意:** `/some/dummy/path`应该设置为存在的本地文件夹,但是该文件夹中不会存储任何数据. 解决[此问题](https://gitlab.com/gitlab-org/gitaly/-/issues/1282)后,将不再需要[此操作](https://gitlab.com/gitlab-org/gitaly/-/issues/1282) . +2. Save the file and [restart GitLab](../restart_gitlab.html#installations-from-source). +3. 运行`sudo -u git -H bundle exec rake gitlab:gitaly:check RAILS_ENV=production`确认 Gitaly 客户端可以连接到 Gitaly 服务器. +4. 拖尾日志以查看请求: + + ``` + tail -f /home/git/gitlab/log/gitaly.log + ``` + +尾随 Gitaly 服务器上的 Gitaly 登录时,您应该会看到请求进入.触发 Gitaly 请求的一种可靠方法是通过 HTTP 或 HTTPS 从 GitLab 克隆存储库. + +**危险:**如果已针对每个存储库或全局配置了[服务器挂钩](../server_hooks.html) ,则必须将它们移至 Gitaly 服务器. 如果您有多个 Gitaly 服务器,则将服务器挂钩复制到所有 Gitaly 服务器. + +#### Mixed configuration[](#mixed-configuration "Permalink") + +GitLab 可以与许多 Gitaly 服务器之一驻留在同一服务器上,但是不支持混合本地和远程配置的配置. 以下设置不正确,因为: + +* 所有地址都必须可从其他 Gitaly 服务器访问. +* `storage1`分配了一个`gitaly_address` Unix 套接字,该套接字对于某些 Gitaly 服务器无效. + +``` +git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'path' => '/mnt/gitlab/git-data' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, +}) +``` + +要组合本地和远程 Gitaly 服务器,请为本地 Gitaly 服务器使用一个外部地址. 例如: + +``` +git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + # Address of the GitLab server that has Gitaly running on it + 'storage1' => { 'gitaly_address' => 'tcp://gitlab.internal:8075', 'path' => '/mnt/gitlab/git-data' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, +}) +``` + +`path`只能包含在本地 Gitaly 服务器上的存储分片中. 如果不包含,则默认的 Git 存储目录将用于该存储碎片. + +### Disable Gitaly where not required (optional)[](#disable-gitaly-where-not-required-optional "Permalink") + +如果您将 Gitaly [作为远程服务](#run-gitaly-on-its-own-server)运行,则可能要禁用默认情况下在您的 GitLab 服务器上运行的本地 Gitaly 服务,而仅在需要时运行它. + +仅当您在自定义群集配置中运行 GitLab 时,才在 GitLab 实例上禁用 Gitaly 才有意义,在该配置中,Gitaly 在与 GitLab 实例不同的机器上运行. 在群集中的所有计算机上禁用 Gitaly 并不是有效的配置(某些计算机充当 Gitaly 服务器). + +To disable Gitaly on a GitLab server: + +**对于所有 GitLab** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitaly['enable'] = false + ``` + +2. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +**对于源安装** + +1. Edit `/etc/default/gitlab`: + + ``` + gitaly_enabled=false + ``` + +2. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . + +## Enable TLS support[](#enable-tls-support "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22602) . + +Gitaly 支持 TLS 加密. 要与侦听安全连接的 Gitaly 实例进行通信,必须在 GitLab 配置中相应存储条目的`gitaly_address`中使用`tls://` URL 方案. + +您必须提供自己的证书,因为不会自动提供. 与每个 Gitaly 服务器相对应的证书必须安装在该 Gitaly 服务器上. + +此外,证书(或其证书颁发机构)必须安装在所有以下组件上: + +* Gitaly 服务器,包括使用证书的 Gitaly 服务器. +* 与之通信的 Gitaly 客户. + +该过程记录在[GitLab 自定义证书配置中,](https://docs.gitlab.com/omnibus/settings/ssl.html)并在下面重复进行. + +请注意以下几点: + +* 证书必须指定用于访问 Gitaly 服务器的地址. 如果你是: + * 通过主机名寻址 Gitaly 服务器,您可以为此使用"公用名"字段,也可以将其添加为"使用者备用名". + * 通过其 IP 地址寻址 Gitaly 服务器,必须将其作为主题备用名称添加到证书中. [gRPC 不支持在证书中使用 IP 地址作为公用名](https://github.com/grpc/grpc/issues/2691) . +* 您可以同时为 Gitaly 服务器配置未加密的侦听地址`listen_addr`和已加密的侦听地址`tls_listen_addr` . 这使您可以根据需要从未加密的流量逐渐过渡到加密的流量. + +要使用 TLS 配置 Gitaly: + +**对于所有 GitLab** + +1. 为 Gitaly 服务器创建证书. +2. 在 Gitaly 客户端上,将证书(或其证书颁发机构)复制到`/etc/gitlab/trusted-certs` : + + ``` + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +3. 在 Gitaly 客户端上,如下所示在`/etc/gitlab/gitlab.rb`编辑`git_data_dirs` : + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' }, + }) + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 在 Gitaly 服务器上,创建`/etc/gitlab/ssl`目录,然后在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +6. 将所有 Gitaly 服务器证书(或其证书颁发机构)复制到`/etc/gitlab/trusted-certs`以便 Gitaly 服务器在调用自身或其他 Gitaly 服务器时将信任该证书: + + ``` + sudo cp cert1.pem cert2.pem /etc/gitlab/trusted-certs/ + ``` + +7. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + gitaly['tls_listen_addr'] = "0.0.0.0:9999" + gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + gitaly['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +8. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +9. 通过[观察 Gitaly 连接的类型,](#observe-type-of-gitaly-connections)验证通过 TLS 提供服务的 Gitaly 通信. +10. (可选)通过以下方式提高安全性: + 1. 通过注释或删除禁用非 TLS 连接`gitaly['listen_addr']`中`/etc/gitlab/gitlab.rb` . + 2. 保存文件. + 3. [重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +**对于源安装** + +1. 为 Gitaly 服务器创建证书. +2. 在 Gitaly 客户端上,将证书复制到系统受信任的证书中: + + ``` + sudo cp cert.pem /usr/local/share/ca-certificates/gitaly.crt + sudo update-ca-certificates + ``` + +3. 在 Gitaly 客户端上,如下所示在`/home/git/gitlab/config/gitlab.yml`编辑`storages` : + + ``` + gitlab: + repositories: + storages: + default: + gitaly_address: tls://gitaly1.internal:9999 + path: /some/dummy/path + storage1: + gitaly_address: tls://gitaly1.internal:9999 + path: /some/dummy/path + storage2: + gitaly_address: tls://gitaly2.internal:9999 + path: /some/dummy/path + ``` + + **注意:** `/some/dummy/path`应该设置为存在的本地文件夹,但是该文件夹中不会存储任何数据. 解决[Gitaly 问题#1282](https://gitlab.com/gitlab-org/gitaly/-/issues/1282)之后,将不再需要此操作. +4. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . +5. 在 Gitaly 服务器上,创建或编辑`/etc/default/gitlab`并添加: + + ``` + export SSL_CERT_DIR=/etc/gitlab/ssl + ``` + +6. 在 Gitaly 服务器上,创建`/etc/gitlab/ssl`目录,然后在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +7. 将所有 Gitaly 服务器证书(或其证书颁发机构)复制到系统受信任证书文件夹,以便 Gitaly 服务器在调用自身或其他 Gitaly 服务器时将信任该证书. + + ``` + sudo cp cert.pem /usr/local/share/ca-certificates/gitaly.crt + sudo update-ca-certificates + ``` + +8. 编辑`/home/git/gitaly/config.toml`并添加: + + ``` + tls_listen_addr = '0.0.0.0:9999' + + [tls] + certificate_path = '/etc/gitlab/ssl/cert.pem' + key_path = '/etc/gitlab/ssl/key.pem' + ``` + +9. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . +10. 通过[观察 Gitaly 连接的类型,](#observe-type-of-gitaly-connections)验证通过 TLS 提供服务的 Gitaly 通信. +11. (可选)通过以下方式提高安全性: + 1. 通过注释掉或删除`/home/git/gitaly/config.toml` `listen_addr`来禁用非 TLS 连接. + 2. 保存文件. + 3. [重新启动 GitLab](../restart_gitlab.html#installations-from-source) . + +### Observe type of Gitaly connections[](#observe-type-of-gitaly-connections "Permalink") + +可以使用[Prometheus](../monitoring/prometheus/index.html)观察 Gitaly 为生产环境提供服务的连接类型. 使用以下 Prometheus 查询: + +``` +sum(rate(gitaly_connections_total[5m])) by (type) +``` + +## `gitaly-ruby`[](#gitaly-ruby "Permalink") + +开发 Gitaly 是为了替代 GitLab 中的 Ruby 应用程序代码. + +为了节省时间并避免重写现有应用程序逻辑的风险,我们选择将一些应用程序代码从 GitLab 复制到 Gitaly. + +为了能够运行该代码,创建了`gitaly-ruby` ,它是主要 Gitaly Go 流程的" sidecar"流程. 在`gitaly-ruby`中实现的一些示例如下: + +* 处理 Wiki 的 RPC. +* 代表用户创建提交的 RPC,例如合并提交. + +### Configure number of `gitaly-ruby` workers[](#configure-number-of-gitaly-ruby-workers "Permalink") + +`gitaly-ruby`容量比 Go 中实现的 Gitaly 少得多. 如果您的 Gitaly 服务器必须处理大量请求,则仅设置一个活动的`gitaly-ruby`车的默认设置可能不够. + +如果您看到 Gitaly 出现`ResourceExhausted`错误,则很可能是您的`gitaly-ruby`能力不足. + +您可以使用以下设置来增加 Gitaly 服务器上的`gitaly-ruby`进程数: + +**对于所有 GitLab** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + # Default is 2 workers. The minimum is 2; 1 worker is always reserved as + # a passive stand-by. + gitaly['ruby_num_workers'] = 4 + ``` + +2. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +**对于源安装** + +1. Edit `/home/git/gitaly/config.toml`: + + ``` + [gitaly-ruby] + num_workers = 4 + ``` + +2. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . + +## Limit RPC concurrency[](#limit-rpc-concurrency "Permalink") + +克隆流量可能会对您的 Gitaly 服务造成很大的压力. 大部分工作在以下任一 RPC 中完成: + +* `SSHUploadPack` (用于 Git SSH). +* `PostUploadPack` (用于 Git HTTP). + +为了防止此类工作负载使您的 Gitaly 服务器不堪重负,您可以在 Gitaly 的配置文件中设置并发限制. 例如: + +``` +# in /etc/gitlab/gitlab.rb + +gitaly['concurrency'] = [ + { + 'rpc' => "/gitaly.SmartHTTPService/PostUploadPack", + 'max_per_repo' => 20 + }, + { + 'rpc' => "/gitaly.SSHService/SSHUploadPack", + 'max_per_repo' => 20 + } +] +``` + +这限制了给定 RPC 正在进行的 RPC 调用的数量. 该限制适用于每个存储库. 在上面的示例中: + +* Gitaly 服务器提供服务的每个存储库最多可以同时`PostUploadPack` 20 个`PostUploadPack` RPC 调用,而`SSHUploadPack`则相同. +* 如果另一个请求进入了已用完其 20 个插槽的存储库,则该请求将排队. + +您可以使用 Gitaly 日志和 Prometheus 观察此队列的行为: + +* 在 Gitaly 日志中,查找字符串(或结构化日志字段) `acquire_ms` . 具有此字段的消息正在报告有关并发限制器的信息. +* 在 Prometheus 中,查找以下指标: + + * `gitaly_rate_limiting_in_progress`. + * `gitaly_rate_limiting_queued`. + * `gitaly_rate_limiting_seconds`. + +**注意:**尽管 Prometheus 度量标准的名称包含`rate_limiting` ,但它是并发限制器,而不是速率限制器. 如果 Gitaly 客户端非常快地连续发出 1000 个请求,则并发不会超过 1,并且并发限制器无效. + +## Rotate Gitaly authentication token[](#rotate-gitaly-authentication-token "Permalink") + +在生产环境中轮换凭证通常需要停机,导致停机或两者兼而有之. + +但是,您可以旋转 Gitaly 凭据而不会中断服务. 旋转 Gitaly 身份验证令牌涉及: + +* [Verifying authentication monitoring](#verify-authentication-monitoring). +* [Enabling “auth transitioning” mode](#enable-auth-transitioning-mode). +* [Updating Gitaly authentication tokens](#update-gitaly-authentication-token). +* [Ensuring there are no authentication failures](#ensure-there-are-no-authentication-failures). +* [Disabling “auth transitioning” mode](#disable-auth-transitioning-mode). +* [Verifying authentication is enforced](#verify-authentication-is-enforced). + +如果您在单个服务器上运行 GitLab,则此过程也适用. 在这种情况下," Gitaly 服务器"和" Gitaly 客户端"是指同一台计算机. + +### Verify authentication monitoring[](#verify-authentication-monitoring "Permalink") + +旋转 Gitaly 身份验证令牌之前,请验证您可以使用 Prometheus 监视 GitLab 安装的身份验证行为. 使用以下 Prometheus 查询: + +``` +sum(rate(gitaly_authentications_total[5m])) by (enforced, status) +``` + +在正确配置了身份验证并且您拥有实时流量的系统中,您将看到以下内容: + +``` +{enforced="true",status="ok"} 4424.985419441742 +``` + +可能还存在速率为 0 的其他数字.我们只关心非零数字. + +唯一的非零数字应具有`enforced="true",status="ok"` . 如果您还有其他非零数字,则说明您的配置有问题. + +`status="ok"`数字反映您当前的请求率. 在上面的示例中,Gitaly 每秒处理大约 4000 个请求. + +既然您已经确定可以监视 GitLab 安装的 Gitaly 身份验证行为,则可以开始其余过程. + +### Enable “auth transitioning” mode[](#enable-auth-transitioning-mode "Permalink") + +通过将 Gitaly 服务器置于"身份验证过渡"模式,从而暂时禁用 Gitaly 服务器上的 Gitaly 身份验证,如下所示: + +``` +# in /etc/gitlab/gitlab.rb +gitaly['auth_transitioning'] = true +``` + +进行此更改后,您的[Prometheus 查询](#verify-authentication-monitoring)应返回如下内容: + +``` +{enforced="false",status="would be ok"} 4424.985419441742 +``` + +因为`enforced="false"` ,所以可以安全地开始部署新令牌. + +### Update Gitaly authentication token[](#update-gitaly-authentication-token "Permalink") + +要在每个 Gitaly 客户端**和** Gitaly 服务器上更新为新的 Gitaly 身份验证令牌,请执行以下操作: + +1. 更新配置: + + ``` + # in /etc/gitlab/gitlab.rb + + gitaly['auth_token'] = '' + ``` + +2. 重新启动 Gitaly: + + ``` + gitlab-ctl restart gitaly + ``` + +如果在实施此更改的同时运行[Prometheus 查询](#verify-authentication-monitoring) ,您将看到被`enforced="false",status="denied"`计数器的非零值. + +### Ensure there are no authentication failures[](#ensure-there-are-no-authentication-failures "Permalink") + +设置新令牌并重新启动所有涉及的服务之后,您将[临时看到以下内容](#verify-authentication-monitoring)的组合: + +* `status="would be ok"`. +* `status="denied"`. + +在所有 Gitaly 客户端和 Gitaly 服务器获取了新令牌之后,应`enforced="false",status="would be ok"` **唯一的非零费率** `enforced="false",status="would be ok"` . + +### Disable “auth transitioning” mode[](#disable-auth-transitioning-mode "Permalink") + +要重新启用 Gitaly 身份验证,请禁用"身份验证转换"模式. 如下更新您的 Gitaly 服务器上的配置: + +``` +# in /etc/gitlab/gitlab.rb +gitaly['auth_transitioning'] = false +``` + +**警告:**如果不完成此步骤,则**没有 Gitaly 身份验证** . + +### Verify authentication is enforced[](#verify-authentication-is-enforced "Permalink") + +刷新您的[Prometheus 查询](#verify-authentication-monitoring) . 现在,您应该会看到与开始时相似的结果. 例如: + +``` +{enforced="true",status="ok"} 4424.985419441742 +``` + +请注意, `enforced="true"`表示正在执行身份验证. + +## Direct Git access bypassing Gitaly[](#direct-git-access-bypassing-gitaly "Permalink") + +虽然可以使用 Git 客户端直接访问磁盘上存储的 Gitaly 存储库,但由于不断改进和更改 Gitaly,因此不建议这样做. 这些改进可能会使假设无效,从而导致性能下降,不稳定甚至数据丢失. + +Gitaly 进行了优化,例如[`info/refs`广告缓存](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/design_diskcache.md) ,它依赖于 Gitaly 通过官方 gRPC 接口控制和监视对存储库的访问. 同样,Praefect 具有优化功能,例如容错和分布式读取,这些优化取决于 gRPC 接口和数据库来确定存储库状态. + +由于这些原因, **直接访问存储库需要您自担风险,并且不受支持** . + +## Direct access to Git in GitLab[](#direct-access-to-git-in-gitlab "Permalink") + +直接访问 Git 使用 GitLab 中称为" Rugged patch"的代码. + +### History[](#history "Permalink") + +在 Gitaly 存在之前,现在 Gitaly 客户端用来直接访问 Git 存储库的是: + +* 如果是单机 Omnibus GitLab 安装,则在本地磁盘上 +* 如果是水平缩放的 GitLab 安装,请使用 NFS. + +除了运行简单的`git`命令之外,GitLab 还使用了一个名为[Rugged](https://github.com/libgit2/rugged)的 Ruby 库. Rugged 是围绕[libgit2](https://libgit2.org/)的包装, [libgit2](https://libgit2.org/)是 C 库形式的 Git 的独立实现. + +随着时间的流逝,很明显 Rugged(特别是与[Unicorn](https://yhbt.net/unicorn/)结合使用)非常有效. 因为`libgit2`是一个库而不是一个外部进程,所以之间的开销很小: + +* GitLab 应用程序代码试图在 Git 存储库中查找数据. +* Git 实现本身. + +由于 Rugged 和 Unicorn 的组合是如此有效,因此 GitLab 的应用程序代码最终会进行大量重复的 Git 对象查找. 例如,查找`master`在一个请求中提交了十几次. 我们可以编写效率低下的代码而不会降低性能. + +当我们将这些 Git 查找迁移到 Gitaly 调用时,我们突然发现每个 Git 查找的固定成本要高得多. 即使 Gitaly 能够重新使用已经在运行的`git`进程(例如,查找提交),您仍然可以: + +* 往返于 Gitaly 的网络费用. +* 在 Gitaly 中,是将 Gitaly 连接到`git`进程的 Unix 管道上的写入/读取往返. + +使用 GitLab.com 进行测量,我们减少了每个请求的 Gitaly 呼叫次数,直到不再感觉到 Rugged 效率的下降. 这也有助于我们直接在 Git 文件服务器上运行 Gitaly 本身,而不是通过 NFS 挂载. 这给了我们提速,抵消了不再使用 Rugged 带来的负面影响. + +不幸的是,GitLab 的其他部署无法像我们在 GitLab.com 上那样删除 NFS,这两个方面都是最糟糕的: + +* NFS 的速度较慢. +* The increased inherent overhead of Gitaly. + +在 Gitaly 迁移项目期间从 GitLab 中删除的代码影响了这些部署. 作为这些基于 NFS 的部署的性能变通办法,我们重新引入了一些旧的 Rugged 代码. 重新引入的代码被非正式地称为" Rugged patch". + +### How it works[](#how-it-works "Permalink") + +执行直接 Git 访问的 Ruby 方法位于[功能标志的](../../development/gitaly.html#legacy-rugged-code)后面,默认情况下处于禁用状态. 设置功能标记以获得最佳性能并不方便,因此我们添加了一种自动机制,可以直接访问 Git. + +当 GitLab 调用具有"加固补丁"的函数时,它将执行两项检查: + +* 数据库中是否设置了此补丁程序的功能标志? 如果是这样,功能标记设置将控制 GitLab 对"坚固补丁"代码的使用. +* 如果未设置功能标志,则 GitLab 尝试直接访问 Gitaly 服务器下方的文件系统. 如果可以,它将使用" Rugged patch". + +这两个检查的结果都被缓存. + +为了查看 GitLab 是否可以直接访问存储库文件系统,我们使用以下启发式: + +* Gitaly 确保文件系统在其根目录中具有一个带有 UUID 的元数据文件. +* Gitaly 通过`ServerInfo` RPC 将此 UUID 报告给 GitLab. +* GitLab Rails 尝试直接读取元数据文件. 如果存在,并且 UUID 匹配,则假定我们具有直接访问权限. + +默认情况下,在 Omnibus GitLab 中启用直接 Git 访问,因为它会在 GitLab 配置文件`config/gitlab.yml`填写正确的存储库路径. 这满足了 UUID 检查. + +### Transition to Gitaly Cluster[](#transition-to-gitaly-cluster "Permalink") + +为了消除复杂性,我们必须删除 GitLab 中的直接 Git 访问. 但是,只要某些 GitLab 安装需要 NFS 上的 Git 存储库,我们就无法删除它. + +我们在 GitLab 中删除直接 Git 访问的工作有两个方面: + +* 减少 GitLab 进行的低效率 Gitaly 查询的数量. +* 说服容错或水平扩展的 GitLab 实例的管理员从 NFS 迁移. + +第二个方面是唯一真正的解决方案. 为此,我们开发了[Gitaly Cluster](praefect.html) . + +## Troubleshooting Gitaly[](#troubleshooting-gitaly "Permalink") + +### Checking versions when using standalone Gitaly servers[](#checking-versions-when-using-standalone-gitaly-servers "Permalink") + +使用独立的 Gitaly 服务器时,必须确保它们与 GitLab 的版本相同,以确保完全兼容. 检查您的 GitLab 实例上的**管理区域> Gitaly 服务器** ,并确认所有 Gitaly 服务器都是`Up to date` . + +[![Gitaly standalone software versions diagram](img/ba685b05a8bb7c09fe3b58048ac4884e.png)](img/gitlab_gitaly_version_mismatch_v12_4.png) + +### `gitaly-debug`[](#gitaly-debug "Permalink") + +`gitaly-debug`命令提供用于" Gitaly"和" Git"性能的"生产调试"工具. 它旨在帮助生产工程师和支持工程师调查 Gitaly 性能问题. + +如果您使用的是 GitLab 11.6 或更高版本,则此工具应已安装在您的 GitLab / Gitaly 服务器上,位于`/opt/gitlab/embedded/bin/gitaly-debug` . 如果要研究旧版本的 GitLab,可以离线编译此工具,然后将可执行文件复制到服务器: + +``` +git clone https://gitlab.com/gitlab-org/gitaly.git +cd cmd/gitaly-debug +GOOS=linux GOARCH=amd64 go build -o gitaly-debug +``` + +要查看`gitaly-debug`的帮助页面以`gitaly-debug`受支持的子命令列表,请运行: + +``` +gitaly-debug -h +``` + +### Commits, pushes, and clones return a 401[](#commits-pushes-and-clones-return-a-401 "Permalink") + +``` +remote: GitLab: 401 Unauthorized +``` + +您将需要将`gitlab-secrets.json`文件与 Gitaly 客户端(GitLab 应用程序节点)同步. + +### Client side gRPC logs[](#client-side-grpc-logs "Permalink") + +Gitaly 使用[gRPC](https://grpc.io/) RPC 框架. Ruby gRPC 客户端具有自己的日志文件,当您看到 Gitaly 错误时,该文件可能包含有用的信息. 您可以使用`GRPC_LOG_LEVEL`环境变量控制 gRPC 客户端的日志级别. 默认级别为`WARN` . + +您可以使用以下命令运行 gRPC 跟踪: + +``` +sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check +``` + +### Observing `gitaly-ruby` traffic[](#observing-gitaly-ruby-traffic "Permalink") + +[`gitaly-ruby`](#gitaly-ruby)是[`gitaly-ruby`](#gitaly-ruby)的内部实现细节,因此,对`gitaly-ruby`流程内部发生的情况`gitaly-ruby` . + +如果已设置 Prometheus 来抓取 Gitaly 进程,则可以通过查询`grpc_client_handled_total`来`grpc_client_handled_total` `gitaly-ruby`各个 RPC 的请求率和错误代码. 严格来说,此度量标准并未区分`gitaly-ruby`和其他 RPC,但实际上(自 GitLab 11.9 起),Gitaly 本身进行的所有 gRPC 调用都是从 Gitaly 主过程到其`gitaly-ruby`边车之一的内部调用. + +假设您的`grpc_client_handled_total`计数器仅观察到 Gitaly,以下查询将显示 RPC 在内部(最有可能)实现为对`gitaly-ruby`调用: + +``` +sum(rate(grpc_client_handled_total[5m])) by (grpc_method) > 0 +``` + +### Repository changes fail with a `401 Unauthorized` error[](#repository-changes-fail-with-a-401-unauthorized-error "Permalink") + +如果您在自己的服务器上运行 Gitaly,并注意到用户可以成功克隆和获取存储库(通过 SSH 和 HTTPS),但是在未获得`401 Unauthorized`情况下,无法推送到它们或在 Web UI 中对存储库进行更改消息,那么 Gitaly 可能由于拥有[错误的 secrets 文件](#configure-gitaly-servers)而无法通过 Gitaly 客户端进行身份验证. + +确认以下所有内容均正确: + +* When any user performs a `git push` to any repository on this Gitaly server, it fails with the following error (note the `401 Unauthorized`): + + ``` + remote: GitLab: 401 Unauthorized + To + ! [remote rejected] branch-name -> branch-name (pre-receive hook declined) + error: failed to push some refs to '' + ``` + +* 当任何用户使用 GitLab UI 从存储库添加或修改文件时,该文件都会立即失败,并显示红色`401 Unauthorized`横幅. +* 创建一个新项目并[使用 README 对其进行初始化会](../../gitlab-basics/create-project.html#blank-projects)成功创建该项目,但不会创建 README. +* [将日志尾随在](https://docs.gitlab.com/omnibus/settings/logs.html) Gitaly 客户端上并重现该错误时,到达`/api/v4/internal/allowed`端点时会出现`401`错误: + + ``` + # api_json.log + { + "time": "2019-07-18T00:30:14.967Z", + "severity": "INFO", + "duration": 0.57, + "db": 0, + "view": 0.57, + "status": 401, + "method": "POST", + "path": "\/api\/v4\/internal\/allowed", + "params": [ + { + "key": "action", + "value": "git-receive-pack" + }, + { + "key": "changes", + "value": "REDACTED" + }, + { + "key": "gl_repository", + "value": "REDACTED" + }, + { + "key": "project", + "value": "\/path\/to\/project.git" + }, + { + "key": "protocol", + "value": "web" + }, + { + "key": "env", + "value": "{\"GIT_ALTERNATE_OBJECT_DIRECTORIES\":[],\"GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE\":[],\"GIT_OBJECT_DIRECTORY\":null,\"GIT_OBJECT_DIRECTORY_RELATIVE\":null}" + }, + { + "key": "user_id", + "value": "2" + }, + { + "key": "secret_token", + "value": "[FILTERED]" + } + ], + "host": "gitlab.example.com", + "ip": "REDACTED", + "ua": "Ruby", + "route": "\/api\/:version\/internal\/allowed", + "queue_duration": 4.24, + "gitaly_calls": 0, + "gitaly_duration": 0, + "correlation_id": "XPUZqTukaP3" + } + + # nginx_access.log + [IP] - - [18/Jul/2019:00:30:14 +0000] "POST /api/v4/internal/allowed HTTP/1.1" 401 30 "" "Ruby" + ``` + +要解决此问题,请确认 Gitaly 服务器上的 gitlab [`gitlab-secrets.json`文件](#configure-gitaly-servers)与 Gitaly 客户端上的[文件](#configure-gitaly-servers)匹配. 如果不匹配,请更新 Gitaly 服务器上的密码文件以匹配 Gitaly 客户端,然后[重新配置](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +### Command line tools cannot connect to Gitaly[](#command-line-tools-cannot-connect-to-gitaly "Permalink") + +如果使用命令行(CLI)工具连接到 Gitaly 服务器时遇到问题,并且某些操作导致出现`14: Connect Failed`错误消息,则意味着 gRPC 无法访问您的 Gitaly 服务器. + +确认您可以通过 TCP 到达 Gitaly: + +``` +sudo gitlab-rake gitlab:tcp_check[GITALY_SERVER_IP,GITALY_LISTEN_PORT] +``` + +如果 TCP 连接失败,请检查您的网络设置和防火墙规则. 如果 TCP 连接成功,则您的网络和防火墙规则正确. + +如果您在命令行环境(例如 Bash)中使用代理服务器,则这些代理服务器可能会干扰您的 gRPC 通信. + +如果使用 Bash 或兼容的命令行环境,请运行以下命令来确定是否配置了代理服务器: + +``` +echo $http_proxy +echo $https_proxy +``` + +如果这些变量中的任何一个都有值,则您的 Gitaly CLI 连接可能正在通过无法连接到 Gitaly 的代理进行路由. + +要删除代理设置,请运行以下命令(取决于哪些变量具有值): + +``` +unset http_proxy +unset https_proxy +``` + +### Gitaly not listening on new address after reconfiguring[](#gitaly-not-listening-on-new-address-after-reconfiguring "Permalink") + +当更新`gitaly['listen_addr']`或`gitaly['prometheus_listen_addr']`值时,Gitaly 可能会在`sudo gitlab-ctl reconfigure`后继续侦听旧地址. + +发生这种情况时,执行`sudo gitlab-ctl restart`将解决此问题. 解决[此问题](https://gitlab.com/gitlab-org/gitaly/-/issues/2521)后,将不再需要[此操作](https://gitlab.com/gitlab-org/gitaly/-/issues/2521) . + +### Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly server[](#permission-denied-errors-appearing-in-gitaly-logs-when-accessing-repositories-from-a-standalone-gitaly-server "Permalink") + +如果即使文件权限正确也发生此错误,则 Gitaly 服务器可能正在发生[时钟漂移](https://en.wikipedia.org/wiki/Clock_drift) . + +请确保 Gitaly 客户端和服务器已同步,并在可能的情况下使用 NTP 时间服务器保持同步. + +### Praefect[](#praefect "Permalink") + +Praefect 是 Gitaly 的路由器和事务管理器,并且是运行 Gitaly 集群的必需组件. 有关更多信息,请参见[Gitaly Cluster](praefect.html) . \ No newline at end of file diff --git a/_book/docs/469.md b/_book/docs/469.md new file mode 100644 index 0000000000000000000000000000000000000000..bf6c6b3833293c12d84cf719a7d009d5a4342515 --- /dev/null +++ b/_book/docs/469.md @@ -0,0 +1,847 @@ +# Gitaly Cluster + +> 原文:[https://docs.gitlab.com/ee/administration/gitaly/praefect.html](https://docs.gitlab.com/ee/administration/gitaly/praefect.html) + +* [Requirements for configuring a Gitaly Cluster](#requirements-for-configuring-a-gitaly-cluster) +* [Setup Instructions](#setup-instructions) + * [Preparation](#preparation) + * [Secrets](#secrets) + * [PostgreSQL](#postgresql) + * [Praefect](#praefect) +* [Enabling TLS support](#enabling-tls-support) + * [Gitaly](#gitaly) + * [Load Balancer](#load-balancer) + * [GitLab](#gitlab) + * [Grafana](#grafana) +* [Distributed reads](#distributed-reads) +* [Automatic failover and leader election](#automatic-failover-and-leader-election) +* [Primary Node Failure](#primary-node-failure) + * [Checking for data loss](#checking-for-data-loss) + * [Checking repository checksums](#checking-repository-checksums) + * [Recovering lost writes](#recovering-lost-writes) + * [Enabling Writes](#enabling-writes) +* [Backend Node Recovery](#backend-node-recovery) +* [Migrating existing repositories to Praefect](#migrating-existing-repositories-to-praefect) +* [Debugging Praefect](#debugging-praefect) + +# Gitaly Cluster[](#gitaly-cluster "Permalink") + +[Gitaly](index.html) (为 Git 存储库提供存储的服务)可以在群集配置中运行,以提高容错能力. 在这种配置中,每个 Git 存储库都存储在集群中的每个 Gitaly 节点上. 可以配置多个集群(或分片). + +**注意:**可以使用[GitLab Core](https://about.gitlab.com/pricing/#self-managed)和更高层来创建 Gitaly 群集. 但是,技术支持仅限于 GitLab Premium 和 Ultimate 客户. 在 GitLab.com 中不可用. + +Praefect 是 Gitaly 的路由器和事务管理器,并且是运行 Gitaly 集群的必需组件. + +[![Architecture diagram](img/ff949c9ca6d0d99318f68a1784db7950.png)](img/praefect_architecture_v12_10.png) + +使用 Gitaly 群集可通过以下方式提高容错能力: + +* 复制写操作以预热备用 Gitaly 节点. +* 检测 Gitaly 节点故障. +* 自动将 Git 请求路由到可用的 Gitaly 节点. + +Gitaly 群集的可用性目标是: + +* **恢复点目标(RPO):**不到 1 分钟. + + 写入异步复制. 尚未复制到新提升的主数据库的所有写入都将丢失. + + 计划实现[高度一致性,](https://gitlab.com/groups/gitlab-org/-/epics/1189)以将其改进为"无损失". + +* **恢复时间目标(RTO):**少于 10 秒. + + 每秒通过每个 Praefect 节点运行的运行状况检查来检测中断. 故障转移要求每个 Praefect 节点上连续十次失败的运行状况检查. + + 计划进行[更快的中断检测](https://gitlab.com/gitlab-org/gitaly/-/issues/2608) ,以将其[缩短](https://gitlab.com/gitlab-org/gitaly/-/issues/2608)到不到 1 秒. + +当前版本支持: + +* 辅助副本的最终一致性. +* Automatic failover from the primary to the secondary. +* 如果复制队列不为空,则报告可能的数据丢失. +* 仅当检测到可能的数据丢失时,才将新升级的主要读标记为标记. + +遵循[HA Gitaly 史诗](https://gitlab.com/groups/gitlab-org/-/epics/1489)进行的改进,包括[横向分发读取](https://gitlab.com/groups/gitlab-org/-/epics/2013) . + +## Requirements for configuring a Gitaly Cluster[](#requirements-for-configuring-a-gitaly-cluster "Permalink") + +建议的 Gitaly 群集最低配置要求: + +* 1 个负载均衡器 +* 1 个 PostgreSQL 服务器(PostgreSQL 11 或更高版本) +* 节点长官 3 +* 3 个 Gitaly 节点(1 个主要节点,2 个辅助节点) + +有关实现的详细信息,请参见[设计文档](https://gitlab.com/gitlab-org/gitaly/-/blob/master/doc/design_ha.md) . + +## Setup Instructions[](#setup-instructions "Permalink") + +如果使用 Omnibus 软件包[安装了](https://about.gitlab.com/install/) GitLab(强烈建议),请按照以下步骤操作: + +1. [Preparation](#preparation) +2. [Configuring the Praefect database](#postgresql) +3. [Configuring the Praefect proxy/router](#praefect) +4. [配置每个 Gitaly 节点](#gitaly) ( [每个 Gitaly 节点](#gitaly)一次) +5. [Configure the load balancer](#load-balancer) +6. [Updating the GitLab server configuration](#gitlab) +7. [Configure Grafana](#grafana) + +### Preparation[](#preparation "Permalink") + +在开始之前,您应该已经有一个正常的 GitLab 实例. [了解如何安装 GitLab](https://about.gitlab.com/install/) . + +设置 PostgreSQL 服务器(PostgreSQL 11 或更高版本). 尚不支持通过 Omnibus GitLab 发行版进行配置. 请关注此[问题](https://gitlab.com/gitlab-org/gitaly/-/issues/2476)以进行更新. + +通过[安装 GitLab](https://about.gitlab.com/install/)准备所有新节点. + +* 1 个 Praefect 节点(需要最少的存储) +* 3 个 Gitaly 节点(高 CPU,高内存,快速存储) +* 1 个 GitLab 服务器 + +您将需要每个节点的 IP /主机地址. + +1. `LOAD_BALANCER_SERVER_ADDRESS` :负载均衡器的 IP /主机地址 +2. `POSTGRESQL_SERVER_ADDRESS` :PostgreSQL 服务器的 IP /主机地址 +3. `PRAEFECT_HOST` :Praefect 服务器的 IP /主机地址 +4. `GITALY_HOST` :每个 Gitaly 服务器的 IP /主机地址 +5. `GITLAB_HOST` :GitLab 服务器的 IP /主机地址 + +如果使用的是云提供商,则可以通过云提供商的管理控制台查找每个服务器的地址. + +如果您使用的是 Google Cloud Platform,SoftLayer 或提供虚拟私有云(VPC)的任何其他供应商,则可以将每个云实例的私有地址(对应于 Google Cloud Platform 的"内部地址")用于`PRAEFECT_HOST` , `GITALY_HOST` ,和`GITLAB_HOST` . + +#### Secrets[](#secrets "Permalink") + +组件之间的通信由不同的秘密保护,下面将对此进行描述. 在开始之前,请为每个密钥生成一个唯一的秘密,并记录下来. 在完成设置过程时,这将很容易用安全令牌替换这些占位符令牌. + +1. `GITLAB_SHELL_SECRET_TOKEN` :当接受 Git 推送时,Git 挂钩将其用于向 GitLab 发出回调 HTTP API 请求. 出于遗留原因,此秘密已与 GitLab Shell 共享. +2. `PRAEFECT_EXTERNAL_TOKEN` :承载此令牌的 Gitaly 客户端只能访问 Praefect 群集上托管的存储库. +3. `PRAEFECT_INTERNAL_TOKEN` :此令牌用于 Praefect 群集内的复制流量. 这与`PRAEFECT_EXTERNAL_TOKEN`不同,因为 Gitaly 客户端必须不能直接访问 Praefect 群集的内部节点. 可能导致数据丢失. +4. `PRAEFECT_SQL_PASSWORD` :Praefect 使用此密码连接到 PostgreSQL. + +我们将在以下说明中指出需要这些秘密的地方. + +### PostgreSQL[](#postgresql "Permalink") + +**注意:**如果使用[Geo,](../geo/replication/index.html)请勿将 GitLab 应用程序数据库和 Praefect 数据库存储在同一 PostgreSQL 服务器上. 复制状态是每个 GitLab 实例的内部状态,不应复制. + +要完成本节,您将需要: + +* 完美节点 1 +* 1 个 PostgreSQL 服务器(PostgreSQL 11 或更高版本) + * 具有创建数据库权限的 SQL 用户 + +在本节中,我们将使用 Omnibus GitLab 安装的`psql`从 Praefect 节点配置 PostgreSQL 服务器. + +1. SSH 进入**Praefect**节点并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 以管理员权限连接到 PostgreSQL 服务器. 这可能是`postgres`用户. 使用数据库`template1`是因为它默认在所有 PostgreSQL 服务器上创建. + + ``` + /opt/gitlab/embedded/bin/psql -U postgres -d template1 -h POSTGRESQL_SERVER_ADDRESS + ``` + + 创建一个将由 Praefect 使用的新用户`praefect` . 将`PRAEFECT_SQL_PASSWORD`替换为您在准备步骤中生成的强密码. + + ``` + CREATE ROLE praefect WITH LOGIN CREATEDB PASSWORD 'PRAEFECT_SQL_PASSWORD'; + ``` + +3. 这次以`praefect`用户身份重新连接到 PostgreSQL 服务器: + + ``` + /opt/gitlab/embedded/bin/psql -U praefect -d template1 -h POSTGRESQL_SERVER_ADDRESS + ``` + + 创建一个新的数据库`praefect_production` . 通过同时连接为创建数据库`praefect`的用户,我们有信心,他们有机会. + + ``` + CREATE DATABASE praefect_production WITH ENCODING=UTF8; + ``` + +现在已配置 Praefect 使用的数据库. + +### Praefect[](#praefect "Permalink") + +要完成本节,您将需要: + +* [配置的 PostgreSQL 服务器](#postgresql) ,包括: + * IP /主机地址( `POSTGRESQL_SERVER_ADDRESS` ) + * 密码( `PRAEFECT_SQL_PASSWORD` ) + +Praefect 应该在专用节点上运行. 不要在应用程序服务器或 Gitaly 节点上运行 Praefect. + +1. SSH 进入**Praefect**节点并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 通过编辑`/etc/gitlab/gitlab.rb`禁用所有其他服务: + + ``` + # Disable all other services on the Praefect node + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + prometheus['enable'] = false + grafana['enable'] = false + puma['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + gitaly['enable'] = false + + # Enable only the Praefect service + praefect['enable'] = true + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + ``` + +3. 通过编辑`/etc/gitlab/gitlab.rb` **Praefect**配置为侦听网络接口: + + ``` + praefect['listen_addr'] = '0.0.0.0:2305' + + # Enable Prometheus metrics access to Praefect. You must use firewalls + # to restrict access to this address/port. + praefect['prometheus_listen_addr'] = '0.0.0.0:9652' + ``` + +4. 配置强劲`auth_token`通过编辑**提督** `/etc/gitlab/gitlab.rb` . 群集外部的客户端(如 GitLab Shell)将需要与 Praefect 群集进行通信: + + ``` + praefect['auth_token'] = 'PRAEFECT_EXTERNAL_TOKEN' + ``` + +5. 通过编辑`/etc/gitlab/gitlab.rb`将**Praefect**配置为连接到 PostgreSQL 数据库. + + 您将需要用数据库的 IP /主机地址替换`POSTGRESQL_SERVER_ADDRESS` ,并用上面设置的强密码`PRAEFECT_SQL_PASSWORD` . + + ``` + praefect['database_host'] = 'POSTGRESQL_SERVER_ADDRESS' + praefect['database_port'] = 5432 + praefect['database_user'] = 'praefect' + praefect['database_password'] = 'PRAEFECT_SQL_PASSWORD' + praefect['database_dbname'] = 'praefect_production' + ``` + + 如果要使用 TLS 客户端证书,则可以使用以下选项: + + ``` + # Connect to PostreSQL using a TLS client certificate + # praefect['database_sslcert'] = '/path/to/client-cert' + # praefect['database_sslkey'] = '/path/to/client-key' + + # Trust a custom certificate authority + # praefect['database_sslrootcert'] = '/path/to/rootcert' + ``` + + 默认情况下,Praefect 将拒绝与 PostgreSQL 建立未加密的连接. 您可以通过取消注释以下行来覆盖它: + + ``` + # praefect['database_sslmode'] = 'disable' + ``` + +6. 通过编辑`/etc/gitlab/gitlab.rb`将**Praefect**群集配置为连接到群集中的每个 Gitaly 节点. + + 虚拟存储的名称必须与 GitLab 配置中配置的存储名称匹配. 在随后的步骤中,我们将存储名称配置为`default`名称,因此我们也在此处使用`default`名称. 该集群具有三个 Gitaly 节点`gitaly-1` , `gitaly-2`和`gitaly-3` ,它们将是彼此的副本. + + **注意:**如果您已经在名为`default`现有存储上存储了数据,则应使用其他名称配置虚拟存储,然后[将数据迁移到 Praefect 存储](#migrating-existing-repositories-to-praefect) . + + 将`PRAEFECT_INTERNAL_TOKEN`替换为一个强秘密,Praefect 将在与集群中的 Gitaly 节点通信时使用此秘密. 此令牌与`PRAEFECT_EXTERNAL_TOKEN` . + + 将`GITALY_HOST`替换为每个 Gitaly 节点的 IP /主机地址. + + 可以将更多 Gitaly 节点添加到群集以增加副本数. 还可以为大型 GitLab 实例添加更多集群. + + **注意:** `gitaly-1`节点当前称为主要节点. 这可用于从一个节点到另一个节点的手动故障. 这将在被删除[的未来](https://gitlab.com/gitlab-org/gitaly/-/issues/2634) . + + ``` + # Name of storage hash must match storage name in git_data_dirs on GitLab + # server ('praefect') and in git_data_dirs on Gitaly nodes ('gitaly-1') + praefect['virtual_storages'] = { + 'default' => { + 'gitaly-1' => { + 'address' => 'tcp://GITALY_HOST:8075', + 'token' => 'PRAEFECT_INTERNAL_TOKEN', + 'primary' => true + }, + 'gitaly-2' => { + 'address' => 'tcp://GITALY_HOST:8075', + 'token' => 'PRAEFECT_INTERNAL_TOKEN' + }, + 'gitaly-3' => { + 'address' => 'tcp://GITALY_HOST:8075', + 'token' => 'PRAEFECT_INTERNAL_TOKEN' + } + } + } + ``` + +7. 在 GitLab 13.1 和更高版本中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2013) ,启用了 read 的[分发](#distributed-reads) . + +8. 将更改保存到`/etc/gitlab/gitlab.rb`并[重新配置 Praefect](../restart_gitlab.html#omnibus-gitlab-reconfigure) : + + ``` + gitlab-ctl reconfigure + ``` + +9. 为了确保 Praefect [已更新其 Prometheus 监听地址](https://gitlab.com/gitlab-org/gitaly/-/issues/2734) ,请[重新启动 Gitaly](../restart_gitlab.html#omnibus-gitlab-restart) : + + ``` + gitlab-ctl restart praefect + ``` + +10. 验证 Praefect 可以到达 PostgreSQL: + + ``` + sudo -u git /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-ping + ``` + + 如果检查失败,请确保已正确执行了步骤. 如果您编辑`/etc/gitlab/gitlab.rb` ,请记住在尝试`sql-ping`命令之前再次运行`sudo gitlab-ctl reconfigure` . + +**必须为每个 Praefect 节点完成上述步骤!** + +## Enabling TLS support[](#enabling-tls-support "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitaly/-/issues/1698) . + +Praefect 支持 TLS 加密. 要与侦听安全连接的 Praefect 实例进行通信,您必须: + +* 在 GitLab 配置中相应存储条目的`gitaly_address`中使用`tls://` URL 方案. +* 带上您自己的证书,因为这不会自动提供. 与每个 Praefect 服务器相对应的证书必须安装在该 Praefect 服务器上. + +此外,必须按照[GitLab 自定义证书配置中](https://docs.gitlab.com/omnibus/settings/ssl.html)所述的过程(并在下面重复),将证书或其证书颁发机构安装在所有 Gitaly 服务器和与其通信的所有 Praefect 客户端上. + +请注意以下几点: + +* 证书必须指定用于访问 Praefect 服务器的地址. 如果通过以下方式寻址 Praefect 服务器: + + * 主机名,您可以为此使用"公用名"字段,也可以将其添加为"使用者备用名". + * IP 地址,您必须将其添加为证书的使用者备用名称. +* 您可以同时为 Praefect 服务器配置未加密的侦听地址`listen_addr`和已加密的侦听地址`tls_listen_addr` . 如果需要,这使您可以从未加密的流量逐渐过渡到加密的流量. + +要使用 TLS 配置 Praefect: + +**对于所有 GitLab** + +1. Prefect 为服务器创建证书. +2. 在 Praefect 服务器上,创建`/etc/gitlab/ssl`目录,然后在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +3. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + praefect['tls_listen_addr'] = "0.0.0.0:3305" + praefect['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + praefect['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 在 Praefect 客户端(包括每个 Gitaly 服务器)上,将证书或其证书颁发机构复制到`/etc/gitlab/trusted-certs` : + + ``` + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +6. 在 Praefect 客户端(Gitaly 服务器除外)上,在`/etc/gitlab/gitlab.rb`编辑`git_data_dirs` ,如下所示: + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://praefect1.internal:3305' }, + 'storage1' => { 'gitaly_address' => 'tls://praefect2.internal:3305' }, + }) + ``` + +7. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +**对于源安装** + +1. Prefect 为服务器创建证书. +2. 在 Praefect 服务器上,创建`/etc/gitlab/ssl`目录,然后在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +3. 在 Praefect 客户端(包括每个 Gitaly 服务器)上,将证书或其证书颁发机构复制到系统信任的证书中: + + ``` + sudo cp cert.pem /usr/local/share/ca-certificates/praefect.crt + sudo update-ca-certificates + ``` + +4. 在 Praefect 客户端(Gitaly 服务器除外)上,按如下所示编辑`/home/git/gitlab/config/gitlab.yml` `storages` : + + ``` + gitlab: + repositories: + storages: + default: + gitaly_address: tls://praefect1.internal:3305 + path: /some/dummy/path + storage1: + gitaly_address: tls://praefect2.internal:3305 + path: /some/dummy/path + ``` + + **注意:** `/some/dummy/path`应该设置为存在的本地文件夹,但是该文件夹中不会存储任何数据. 解决[此问题](https://gitlab.com/gitlab-org/gitaly/-/issues/1282)后,将不再需要[此操作](https://gitlab.com/gitlab-org/gitaly/-/issues/1282) . +5. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . +6. 将所有 Praefect 服务器证书或其证书颁发机构复制到每台 Gitaly 服务器上的系统受信任证书,以便 Praefect 服务器在被 Gitaly 服务器调用时将信任该证书: + + ``` + sudo cp cert.pem /usr/local/share/ca-certificates/praefect.crt + sudo update-ca-certificates + ``` + +7. 编辑`/home/git/praefect/config.toml`并添加: + + ``` + tls_listen_addr = '0.0.0.0:3305' + + [tls] + certificate_path = '/etc/gitlab/ssl/cert.pem' + key_path = '/etc/gitlab/ssl/key.pem' + ``` + +8. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . + +### Gitaly[](#gitaly "Permalink") + +**注意:**为**每个** Gitaly 节点完成这些步骤. + +要完成本节,您将需要: + +* [Configured Praefect node](#praefect) +* 将 3 个(或更多)安装了 GitLab 的服务器配置为 Gitaly 节点. 这些应该是专用节点,不要在这些节点上运行其他服务. + +分配给 Praefect 群集的每个 Gitaly 服务器都需要配置. 该配置与普通的[独立 Gitaly 服务器相同](index.html) ,除了: + +* 存储名称公开给 Praefect,而不是 GitLab +* 秘密令牌是与 Praefect 共享的,而不是与 GitLab 共享的 + +Praefect 群集中所有 Gitaly 节点的配置可以相同,因为我们依靠 Praefect 正确地路由操作. + +应特别注意: + +* 本节中配置的`gitaly['auth_token']`必须与 Praefect 节点上`praefect['virtual_storages']`下的`token`值匹配. 这是在上[一节中](#praefect)设置的. 本文档始终使用占位符`PRAEFECT_INTERNAL_TOKEN` . +* 本节中配置的`git_data_dirs`中的存储名称必须与 Praefect 节点上`praefect['virtual_storages']`下的存储名称匹配. 这是在上[一节中](#praefect)设置的. 本文档使用`gitaly-1` , `gitaly-2`和`gitaly-3`作为 Gitaly 存储名称. + +有关 Gitaly 服务器配置的更多信息,请参阅我们的[Gitaly 文档](index.html#configure-gitaly-servers) . + +1. SSH 进入**Gitaly**节点并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. Disable all other services by editing `/etc/gitlab/gitlab.rb`: + + ``` + # Disable all other services on the Praefect node + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + grafana['enable'] = false + puma['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + prometheus_monitoring['enable'] = false + + # Enable only the Gitaly service + gitaly['enable'] = true + + # Enable Prometheus if needed + prometheus['enable'] = true + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + ``` + +3. 配置**Gitaly**通过编辑来听网络接口`/etc/gitlab/gitlab.rb` : + + ``` + # Make Gitaly accept connections on all network interfaces. + # Use firewalls to restrict access to this address/port. + gitaly['listen_addr'] = '0.0.0.0:8075' + + # Enable Prometheus metrics access to Gitaly. You must use firewalls + # to restrict access to this address/port. + gitaly['prometheus_listen_addr'] = '0.0.0.0:9236' + ``` + +4. 配置强劲`auth_token`通过编辑**Gitaly** `/etc/gitlab/gitlab.rb` . 客户端将需要与该 Gitaly 节点进行通信. 通常,此令牌对于所有 Gitaly 节点都是相同的. + + ``` + gitaly['auth_token'] = 'PRAEFECT_INTERNAL_TOKEN' + ``` + +5. 配置`git push`操作所需的 GitLab Shell `secret_token`和`internal_api_url` . + + 如果您已经[在自己的服务器上](index.html)配置了[Gitaly](index.html) + + ``` + gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN' + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your front door GitLab URL or an internal load balancer. + # Examples: 'https://example.gitlab.com', 'http://1.2.3.4' + gitlab_rails['internal_api_url'] = 'http://GITLAB_HOST' + ``` + +6. 通过在`/etc/gitlab/gitlab.rb`设置`git_data_dirs`来配置 Git 数据的存储位置. 每个 Gitaly 节点应具有唯一的存储名称(例如`gitaly-1` ). + + 与其为每个 Gitaly 节点唯一地配置`git_data_dirs`将每个 Gitaly 节点上所有 Gitaly 节点的配置都包括在内通常会更容易. 由于 Praefect `virtual_storages`配置将每个存储名称(例如`gitaly-1` )映射到特定节点,并且相应地路由了请求,因此支持此操作. 这意味着舰队中的每个 Gitaly 节点都可以共享相同的配置. + + ``` + # You can include the data dirs for all nodes in the same config, because + # Praefect will only route requests according to the addresses provided in the + # prior step. + git_data_dirs({ + "gitaly-1" => { + "path" => "/var/opt/gitlab/git-data" + }, + "gitaly-2" => { + "path" => "/var/opt/gitlab/git-data" + }, + "gitaly-3" => { + "path" => "/var/opt/gitlab/git-data" + } + }) + ``` + +7. 将更改保存到`/etc/gitlab/gitlab.rb`并[重新配置 Gitaly](../restart_gitlab.html#omnibus-gitlab-reconfigure) : + + ``` + gitlab-ctl reconfigure + ``` + +8. 为了确保 Gitaly [更新了其 Prometheus 监听地址](https://gitlab.com/gitlab-org/gitaly/-/issues/2734) ,请[重新启动 Gitaly](../restart_gitlab.html#omnibus-gitlab-restart) : + + ``` + gitlab-ctl restart gitaly + ``` + +**必须对每个 Gitaly 节点完成上述步骤!** + +配置完所有 Gitaly 节点后,您可以运行 Praefect 连接检查器以验证 Praefect 可以连接到 Praefect 配置中的所有 Gitaly 服务器. + +1. SSH into the **Praefect** node and run the Praefect connection checker: + + ``` + sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes + ``` + +### Load Balancer[](#load-balancer "Permalink") + +在高可用的 Gitaly 配置中,需要一个负载平衡器来将内部流量从 GitLab 应用程序路由到 Praefect 节点. 有关使用负载均衡器或进行确切配置的细节超出了 GitLab 文档的范围. + +我们希望,如果您要管理像 GitLab 这样的 HA 系统,那么您已经选择了负载均衡器. 一些示例包括[HAProxy](https://www.haproxy.org/) (开源), [Google 内部负载均衡器](https://cloud.google.com/load-balancing/docs/internal/) , [AWS Elastic 负载均衡器](https://aws.amazon.com/elasticloadbalancing/) ,F5 Big-IP LTM 和 Citrix Net Scaler. 本文档将概述您需要配置哪些端口和协议. + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 2305 | 2305 | TCP | + +### GitLab[](#gitlab "Permalink") + +要完成本节,您将需要: + +* [Configured Praefect node](#praefect) +* [Configured Gitaly nodes](#gitaly) + +Praefect 集群需要作为存储位置公开给 GitLab 应用程序. 这是通过更新`git_data_dirs`完成的. + +应特别注意: + +* 本节中添加到`git_data_dirs`的存储名称必须与 Praefect 节点上`praefect['virtual_storages']`下的存储名称匹配. 这是在本指南的[Praefect](#praefect)部分中设置的. 本文档使用`storage-1`作为 Praefect 存储名称. + +1. SSH 进入**GitLab**节点并以 root 身份登录: + + ``` + sudo -i + ``` + +2. 配置`external_url`以便可以通过编辑`/etc/gitlab/gitlab.rb`通过适当的端点访问`/etc/gitlab/gitlab.rb` GitLab 提供文件: + + 您需要将`GITLAB_SERVER_URL`替换为当前 GitLab 实例所服务的实际外部 URL: + + ``` + external_url 'GITLAB_SERVER_URL' + ``` + +3. 禁用在 GitLab 主机上运行的默认 Gitaly 服务. 不需要它,因为 GitLab 将连接到配置的集群. + + **注意**如果现有数据存储在默认的 Gitaly 存储中,则应首先[迁移 Praefect 存储中的数据](#migrating-existing-repositories-to-praefect) . + + ``` + gitaly['enable'] = false + ``` + +4. 通过编辑`/etc/gitlab/gitlab.rb`将 Praefect 集群添加为存储位置. + + 您将需要更换: + + * 带有负载均衡器的 IP 地址或主机名的`LOAD_BALANCER_SERVER_ADDRESS` . + * `PRAEFECT_EXTERNAL_TOKEN`带有真正的秘密 + + ``` + git_data_dirs({ + "default" => { + "gitaly_address" => "tcp://LOAD_BALANCER_SERVER_ADDRESS:2305", + "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN' + } + }) + ``` + +5. 配置`gitlab_shell['secret_token']`以便通过编辑`/etc/gitlab/gitlab.rb`正确验证`git push`期间来自 Gitaly 节点的回调: + + 您将需要用真实的机密替换`GITLAB_SHELL_SECRET_TOKEN` . + + ``` + gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN' + ``` + +6. 通过编辑`/etc/gitlab/gitlab.rb`添加 Prometheus 监视设置. + + 您将需要更换: + + * `PRAEFECT_HOST`带有 Praefect 节点的 IP 地址或主机名 + * `GITALY_HOST` ,每个 Gitaly 节点的 IP 地址或主机名 + + ``` + prometheus['scrape_configs'] = [ + { + 'job_name' => 'praefect', + 'static_configs' => [ + 'targets' => [ + 'PRAEFECT_HOST:9652', # praefect-1 + 'PRAEFECT_HOST:9652', # praefect-2 + 'PRAEFECT_HOST:9652', # praefect-3 + ] + ] + }, + { + 'job_name' => 'praefect-gitaly', + 'static_configs' => [ + 'targets' => [ + 'GITALY_HOST:9236', # gitaly-1 + 'GITALY_HOST:9236', # gitaly-2 + 'GITALY_HOST:9236', # gitaly-3 + ] + ] + } + ] + ``` + +7. 将更改保存到`/etc/gitlab/gitlab.rb`并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) : + + ``` + gitlab-ctl reconfigure + ``` + +8. 验证每个`gitlab-shell`实例上的每个`gitlab-shell`都可以到达 GitLab. 在每个 Gitaly 实例上运行: + + ``` + /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml + ``` + +9. 验证 GitLab 是否可以达到 Praefect: + + ``` + gitlab-rake gitlab:gitaly:check + ``` + +10. 在**管理区域>设置>存储库>存储库**中检查 Praefect 存储已配置为存储新存储库. 按照本指南, `default`存储应具有权重 100 以存储所有新存储库. + +11. 通过创建一个新项目来验证一切正常. 选中"使用自述文件初始化存储库"框,以使存储库中包含已查看的内容. 如果项目已创建,并且您可以看到 README 文件,那么它将起作用! + +### Grafana[](#grafana "Permalink") + +Grafana 包含在 GitLab 中,可用于监视您的 Praefect 集群. 有关详细文档,请参见[Grafana 仪表板服务](https://docs.gitlab.com/omnibus/settings/grafana.html) . + +快速入门: + +1. SSH into the **GitLab** node and login as root: + + ``` + sudo -i + ``` + +2. 通过编辑`/etc/gitlab/gitlab.rb`启用 Grafana 登录表单. + + ``` + grafana['disable_login_form'] = false + ``` + +3. 将更改保存到`/etc/gitlab/gitlab.rb`并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) : + + ``` + gitlab-ctl reconfigure + ``` + +4. 设置 Grafana 管理员密码. 此命令将提示您输入新密码: + + ``` + gitlab-ctl set-grafana-password + ``` + +5. 在您的 Web 浏览器中,在您的 GitLab 服务器上打开`/-/grafana` (例如`https://gitlab.example.com/-/grafana` ). + + 使用您设置的密码和用户名`admin`登录. + +6. 转到**浏览**并查询`gitlab_build_info`以验证您是否正在从所有计算机中获取指标. + +恭喜你! 您已经配置了可观察的高可用性 Praefect 集群. + +## Distributed reads[](#distributed-reads "Permalink") + +在[beta 版本的](https://about.gitlab.com/handbook/product/#alpha-beta-ga) GitLab 13.1 中引入,功能标志`gitaly_distributed_reads`设置为禁用. + +Praefect supports distribution of read operations across Gitaly nodes that are configured for the virtual node. + +为了进行[性能测试](https://gitlab.com/gitlab-org/quality/performance/-/issues/231) ,分布式读取当前处于[beta 状态](https://about.gitlab.com/handbook/product/#alpha-beta-ga) ,默认情况下处于禁用状态. 要启用分布式读取,必须在 Ruby 控制台中启用`gitaly_distributed_reads` [功能标志](../feature_flags.html) : + +``` +Feature.enable(:gitaly_distributed_reads) +``` + +如果启用,则所有带有`ACCESSOR`选项(如[GetBlob)的](https://gitlab.com/gitlab-org/gitaly/-/blob/v12.10.6/proto/blob.proto#L16) RPC 都将重定向到最新且运行状况良好的 Gitaly 节点. + +在这种情况下*,最新*意味着: + +* 没有为此节点安排任何复制操作. +* 最后的复制操作处于*完成*状态. + +如果没有这样的节点,或者在选择节点期间发生任何其他错误,那么将选择主节点来处理请求. + +要跟踪读取操作的分布,可以使用`gitaly_praefect_read_distribution` Prometheus 计数器度量. 它有两个标签: + +* `virtual_storage`. +* `storage`. + +它们反映了为此 Praefect 实例定义的配置. + +## Automatic failover and leader election[](#automatic-failover-and-leader-election "Permalink") + +Praefect 会定期检查每个后端 Gitaly 节点的运行状况. 如果发现当前主节点运行状况不佳,此信息可用于自动故障转移到新的主节点. + +* **PostgreSQL(推荐):**默认启用,等效于: `praefect['failover_election_strategy'] = sql` . 此配置选项将允许多个 Praefect 节点通过 PostgreSQL 数据库进行协调,以选择一个主要的 Gitaly 节点. 如果大多数 Praefect 节点在 10 秒内仍无法访问当前主节点,此配置将导致 Praefect 节点选择一个新的主节点,监视其运行状况,并选择一个新的主节点. +* **手动:**禁用自动故障转移. 可以在 Praefect 节点上的`/etc/gitlab/gitlab.rb`重新配置主节点. 通过将`primary = true`移至另一个 Gitaly 节点,将其修改为`praefect['virtual_storages']`字段. 在上述步骤中,将`gitaly-1`设置为主数据库. 在配置中需要`praefect['failover_enabled'] = false` . +* **内存:**通过在 Praefect 节点上的`/etc/gitlab/gitlab.rb`设置`praefect['failover_election_strategy'] = 'local'` `/etc/gitlab/gitlab.rb` . 如果对于当前的主后端 Gitaly 节点,足够数量的运行状况检查失败,则将选择新的主节点. **不要与多个 Praefect 节点一起使用!** 与多个 Praefect 节点一起使用可能会导致大脑分裂. + +将来我们可能会实施对 Consul 的支持以及云原生策略. + +## Primary Node Failure[](#primary-node-failure "Permalink") + +Praefect 通过将健康的辅助节点升级为新的主节点来从发生故障的主 Gitaly 节点中恢复. 为了最大程度地减少数据丢失,Praefect 会选择从主节点进行最少重复写入的辅助节点. 仍然会有一些未复制的写入,从而导致数据丢失. + +故障转移事件发生后,Praefect 会将虚拟存储切换为只读模式. 通过防止对新选举的主数据库进行新的可能冲突的写入,这可以简化数据恢复工作. 这使管理员可以尝试在允许新写入之前恢复丢失的数据. + +如果您更喜欢写可用性而不是一致性,则可以通过在`/etc/gitlab/gitlab.rb`设置`praefect['failover_read_only_after_failover'] = false`并[重新配置 Praefect](../restart_gitlab.html#omnibus-gitlab-reconfigure)来关闭此行为. + +### Checking for data loss[](#checking-for-data-loss "Permalink") + +Praefect `dataloss`子命令可通过检查未完成的复制作业来帮助识别丢失的写操作. 这对于确定故障转移后可能的数据丢失情况很有用. 此命令必须在 Praefect 节点上执行. + +``` +sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage ] +``` + +如果未指定虚拟存储,则将检查每个已配置的虚拟存储的数据丢失. + +``` +sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss +``` + +``` +Virtual storage: default + Current read-only primary: gitaly-2 + Previous write-enabled primary: gitaly-1 + Nodes with data loss from failing over from gitaly-1: + @hashed/2c/62/2c624232cdd221771294dfbb310aca000a0df6ac8b66b696d90ef06fdefb64a3.git: gitaly-0 + @hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.git: gitaly-0, gitaly-2 +``` + +当前,如果已直接从先前启用写操作的主数据库复制到该`dataloss`仅考虑该存储库为最新. 虽然从最新的辅助数据库进行协调可以恢复数据,但在数据丢失报告中不可见. 这是通过[Gitaly#2866](https://gitlab.com/gitlab-org/gitaly/-/issues/2866)进行的改进. + +**注意数据** `dataloss`仍处于 beta 状态,并且输出格式可能会更改. + +### Checking repository checksums[](#checking-repository-checksums "Permalink") + +要在所有 Gitaly 节点上检查项目的存储库校验和,请在主 GitLab 节点上运行[副本 Rake 任务](../raketasks/praefect.html#replica-checksums) . + +### Recovering lost writes[](#recovering-lost-writes "Permalink") + +Praefect `reconcile`子命令可用于恢复先前的主数据库恢复联机后丢失的写入. 仅当虚拟存储仍处于只读模式时才有可能. + +``` +sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual -reference -target -f +``` + +有关`reconcile`子命令的更多详细信息,请参阅" [后端节点恢复"](#backend-node-recovery)部分. + +### Enabling Writes[](#enabling-writes "Permalink") + +在启用写入之前,应该进行任何数据恢复尝试,以消除冲突写入的任何可能性. 可以使用 Praefect `enable-writes`子命令为写入重新启用虚拟存储. + +``` +sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml enable-writes -virtual-storage +``` + +## Backend Node Recovery[](#backend-node-recovery "Permalink") + +当 Praefect 后端节点发生故障并且不再能够复制更改时,后端节点将开始从主节点开始漂移. 如果该节点最终恢复,则需要将其与当前主节点协调. 主节点被视为分片状态的唯一真实来源. Praefect `reconcile`子命令允许在后端节点和当前主节点之间进行手动协调. + +Run the following command on the Praefect server after all placeholders (`` and ``) have been replaced: + +``` +sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual -target +``` + +* 将占位符``替换为包含要检查的后端节点存储的虚拟存储. +* 将占位符``替换为后端存储名称. + +该命令将返回与当前主数据库不一致的存储库列表. 这些不一致性中的每一个还将与随附的复制作业 ID 一起记录. + +## Migrating existing repositories to Praefect[](#migrating-existing-repositories-to-praefect "Permalink") + +如果您的 GitLab 实例已经有存储库,则不会自动迁移它们. + +可以使用[Repository API](../../api/projects.html#edit-project)从一个存储位置移动存储[库](../../api/projects.html#edit-project) : + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --data "repository_storage=praefect" https://example.gitlab.com/api/v4/projects/123 +``` + +## Debugging Praefect[](#debugging-praefect "Permalink") + +如果收到错误,请检查`/var/log/gitlab/gitlab-rails/production.log` . + +以下是常见的错误和潜在原因: + +* 500 响应码 + * **ActionView :: Template :: Error(7:权限被拒绝)** + * `praefect['auth_token']`和`gitlab_rails['gitaly_token']`在 GitLab 服务器上不匹配. + * **无法保存项目.** **错误:7:权限被拒绝** + * GitLab 服务器上的`praefect['storage_nodes']`秘密令牌与一台或多台 Gitaly 服务器上的`gitaly['auth_token']`中的值不匹配. +* 503 响应码 + * **GRPC ::不可用(14:无法连接到所有地址)** + * GitLab 无法到达 Praefect. + * **GRPC ::不可用(14:所有 SubCon 都在 TransientFailure 中...)** + * Praefect 无法到达其一个或多个子 Gitaly 节点. 尝试运行 Praefect 连接检查器进行诊断. \ No newline at end of file diff --git a/_book/docs/470.md b/_book/docs/470.md new file mode 100644 index 0000000000000000000000000000000000000000..5810df2f3a5d2bc0ea8f702b042fb74cd12e61c1 --- /dev/null +++ b/_book/docs/470.md @@ -0,0 +1,234 @@ +# Gitaly reference + +> 原文:[https://docs.gitlab.com/ee/administration/gitaly/reference.html](https://docs.gitlab.com/ee/administration/gitaly/reference.html) + +* [Format](#format) + * [Authentication](#authentication) + * [TLS](#tls) + * [Storage](#storage) + * [Git](#git) + * [`cat-file` cache](#cat-file-cache) + * [`gitaly-ruby`](#gitaly-ruby) + * [GitLab Shell](#gitlab-shell) + * [Prometheus](#prometheus) + * [Logging](#logging) +* [Concurrency](#concurrency) + +# Gitaly reference[](#gitaly-reference "Permalink") + +通过[TOML](https://github.com/toml-lang/toml)配置文件配置 Gitaly. 与源安装不同,在 Omnibus GitLab 中,您不会直接编辑此文件. + +配置文件作为参数传递给`gitaly`可执行文件. 通常由 Omnibus GitLab 或您的[init](https://en.wikipedia.org/wiki/Init)脚本完成. + +可以在 Gitaly 项目中找到[示例配置文件](https://gitlab.com/gitlab-org/gitaly/blob/master/config.toml.example) . + +## Format[](#format "Permalink") + +在顶层, `config.toml`定义下表中描述的项目. + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `socket_path` | string | 是(如果未设置`listen_addr` ) | Gitaly 应该打开 Unix 套接字的路径. | +| `listen_addr` | string | 是(如果未设置`socket_path` ) | Gitaly 侦听的 TCP 地址. | +| `tls_listen_addr` | string | no | TCP over TLS 地址供 Gitaly 侦听. | +| `bin_dir` | string | yes | 包含 Gitaly 可执行文件的目录. | +| `prometheus_listen_addr` | string | no | Prometheus 指标的 TCP 侦听地址. 如果未设置,则不会启动 Prometheus 侦听器. | + +例如: + +``` +socket_path = "/home/git/gitlab/tmp/sockets/private/gitaly.socket" +listen_addr = "localhost:9999" +tls_listen_addr = "localhost:8888" +bin_dir = "/home/git/gitaly" +prometheus_listen_addr = "localhost:9236" +``` + +### Authentication[](#authentication "Permalink") + +可以将 Gitaly 配置为拒绝标头中不包含特定承载令牌的请求. 这是通过 TCP 服务请求时要使用的一种安全措施: + +``` +[auth] +# A non-empty token enables authentication. +token = "the secret token" +``` + +当`config.toml`的令牌设置不存在或为空字符串时,将禁用身份验证. + +可以使用`transitioning`设置暂时禁用身份验证. 这使您可以监视所有客户端是否都在正确认证,而不会导致尚未正确配置的客户端的服务中断: + +``` +[auth] +token = "the secret token" +transitioning = true +``` + +**警告:**完成更改令牌设置后,切记禁用`transitioning` . + +所有身份验证尝试均以`gitaly_authentications_total`指标在 Prometheus 中进行计数. + +### TLS[](#tls "Permalink") + +Gitaly 支持 TLS 加密. 您将需要携带自己的证书,因为该证书不会自动提供. + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `certificate_path` | string | no | 证书的路径. | +| `key_path` | string | no | 密钥的路径. | + +``` +tls_listen_addr = "localhost:8888" + +[tls] +certificate_path = '/home/git/cert.cert' +key_path = '/home/git/key.pem' +``` + +在 Gitaly 中[了解](index.html#enable-tls-support)有关 TLS 的[更多](index.html#enable-tls-support)信息. + +### Storage[](#storage "Permalink") + +GitLab 存储库被分组到称为"存储"的目录中(例如`/home/git/repositories` ),其中包含由 GitLab 管理的裸存储库,其名称(例如`default` ). + +这些名称和路径也在 GitLab 的`gitlab.yml`配置文件中定义. 当你在同一台机器 GitLab,这是默认和推荐的配置上运行 Gitaly,在 Gitaly 的定义存储路径`config.toml`必须与在`gitlab.yml` . + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `storage` | array | yes | 一组存储分片. | +| `path` | string | yes | 存储分片的路径. | +| `name` | string | yes | 存储分片的名称. | + +例如: + +``` +[[storage]] +path = "/path/to/storage/repositories" +name = "my_shard" + +[[storage]] +path = "/path/to/other/repositories" +name = "other_storage" +``` + +### Git[](#git "Permalink") + +可以在配置文件的`[git]`部分中设置以下值. + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `bin_path` | string | no | Git 二进制文件的路径. 如果未设置,将使用`PATH`进行解析. | +| `catfile_cache_size` | integer | no | 缓存的[cat 文件进程的](#cat-file-cache)最大数量. 默认值为`100` . | + +#### `cat-file` cache[](#cat-file-cache "Permalink") + +许多 Gitaly RPC 需要从存储库中查找 Git 对象. 大多数时候,我们使用`git cat-file --batch`进程. 为了获得更好的性能,Gitaly 可以在 RPC 调用之间重用这些`git cat-file`过程. 先前使用的进程保留在[" Git cat-file 缓存"中](https://about.gitlab.com/blog/2019/07/08/git-performance-on-nfs/#enter-cat-file-cache) . 为了控制其使用多少系统资源,我们拥有可进入高速缓存的 cat 文件进程的最大数量. + +默认限制是 100 个`cat-file` ,它们构成了一对`git cat-file --batch`和`git cat-file --batch-check`进程. 如果您看到抱怨"打开的文件太多"或无法创建新进程的错误,则可以降低此限制. + +理想情况下,该数量应该足够大以处理正常流量. 如果提高该限制,则应在前后测量缓存命中率. 如果命中率没有提高,则上限可能不会产生有意义的变化. 这是一个 Prometheus 查询示例,用于查看命中率: + +``` +sum(rate(gitaly_catfile_cache_total{type="hit"}[5m])) / sum(rate(gitaly_catfile_cache_total{type=~"(hit)|(miss)"}[5m])) +``` + +### `gitaly-ruby`[](#gitaly-ruby "Permalink") + +一个 Gitaly 进程使用一个或多个`gitaly-ruby`帮助程序进程来执行在 Ruby 中而非 Go 中实现的 RPC. 配置文件的`[gitaly-ruby]`部分包含这些帮助程序的设置. + +已知这些进程有时会遭受内存泄漏. 当其内存超过`max_rss`限制时,Gitaly 将重新启动其`gitaly-ruby`帮助`max_rss` . + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `dir` | string | yes | 安装`gitaly-ruby`路径(需要引导该进程). | +| `max_rss` | integer | no | 触发`gitaly-ruby`重新启动的驻留集大小限制(以字节为单位). 默认值为`200000000` (200MB). | +| `graceful_restart_timeout` | string | no | 超出`max_rss`后,强制执行`gitaly-ruby`进程之前的`max_rss` . 默认值为`10m` (10 分钟). | +| `restart_delay` | string | no | 重新启动之前, `gitaly-ruby`内存必须保持高电平的时间. 默认值为`5m` (5 分钟). | +| `num_workers` | integer | no | Number of `gitaly-ruby` worker processes. Try increasing this number in case of `ResourceExhausted` errors. Default is `2`, minimum is `2`. | +| `linguist_languages_path` | string | no | 动态`languages.json` .json 发现的替代. 默认为空字符串(使用动态发现). | + +Example: + +``` +[gitaly-ruby] +dir = "/home/git/gitaly/ruby" +max_rss = 200000000 +graceful_restart_timeout = "10m" +restart_delay = "5m" +num_workers = 2 +``` + +### GitLab Shell[](#gitlab-shell "Permalink") + +出于历史原因, [GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell)包含 Git 挂钩,这些挂钩允许 GitLab 验证并响应 Git 推送. 由于 Gitaly 拥有 Git 推送,因此必须在 Gitaly 旁边安装 GitLab Shell. 将来会[简化](https://gitlab.com/gitlab-org/gitaly/-/issues/1226) . + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `dir` | string | yes | 安装 GitLab Shell 的目录. | + +Example: + +``` +[gitlab-shell] +dir = "/home/git/gitlab-shell" +``` + +### Prometheus[](#prometheus "Permalink") + +您可以选择配置 Gitaly 以记录 Prometheus 中 GRPC 方法调用的直方图延迟. + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `grpc_latency_buckets` | array | no | Prometheus 将每个观察值存储在一个存储桶中,这意味着您将获得延迟的近似值. 优化铲斗可更好地控制逼近精度. | + +Example: + +``` +prometheus_listen_addr = "localhost:9236" + +[prometheus] +grpc_latency_buckets = [0.001, 0.005, 0.025, 0.1, 0.5, 1.0, 10.0, 30.0, 60.0, 300.0, 1500.0] +``` + +### Logging[](#logging "Permalink") + +以下值在`[logging]`部分下的 Gitaly 中配置日志`[logging]` . + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `format` | string | no | 日志格式: `text`或`json` . 默认值: `text` . | +| `level` | string | no | 日志级别: `debug` , `info` , `warn` , `error` , `fatal`或`panic` . 默认值: `info` . | +| `sentry_dsn` | string | no | Sentry DSN 用于异常监视. | +| `sentry_environment` | string | no | [Sentry Environment](https://docs.sentry.io/enriching-error-data/environments/)用于异常监视. | +| `ruby_sentry_dsn` | string | no | Sentry DSN 用于`gitaly-ruby`异常监视. | + +While the main Gitaly application logs go to `stdout`, there are some extra log files that go to a configured directory, like the GitLab Shell logs. GitLab Shell does not support `panic` or `trace` level logs. `panic` will fall back to `error`, while `trace` will fall back to `debug`. Any other invalid log levels will default to `info`. + +Example: + +``` +[logging] +level = "warn" +dir = "/home/gitaly/logs" +format = "json" +sentry_dsn = "https://:@sentry.io/" +ruby_sentry_dsn = "https://:@sentry.io/" +``` + +## Concurrency[](#concurrency "Permalink") + +您可以调整每个 RPC 端点的`concurrency`性. + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `concurrency` | array | yes | RPC 端点数组. | +| `rpc` | string | no | RPC 端点的名称( `/gitaly.RepositoryService/GarbageCollect` ). | +| `max_per_repo` | integer | no | 每个存储库的每个 RPC 的并发性. | + +Example: + +``` +[[concurrency]] +rpc = "/gitaly.RepositoryService/GarbageCollect" +max_per_repo = 1 +``` \ No newline at end of file diff --git a/_book/docs/471.md b/_book/docs/471.md new file mode 100644 index 0000000000000000000000000000000000000000..67949d2e08b9e189bea1e0c1a4f06b6e1ce1a32d --- /dev/null +++ b/_book/docs/471.md @@ -0,0 +1,15 @@ +# Monitoring GitLab + +> 原文:[https://docs.gitlab.com/ee/administration/monitoring/](https://docs.gitlab.com/ee/administration/monitoring/) + +# Monitoring GitLab[](#monitoring-gitlab "Permalink") + +探索我们的功能来监视您的 GitLab 实例: + +* [GitLab 自我监视](gitlab_self_monitoring_project/index.html) :GitLab 实例管理项目有助于监视 GitLab 实例并对警报采取措施. +* [性能监视](performance/index.html) :GitLab 性能监视可以测量您实例的各种统计信息. +* [Prometheus](prometheus/index.html) :Prometheus 是一项功能强大的时间序列监视服务,为监视 GitLab 和其他软件产品提供了灵活的平台. +* [GitHub 导入](github_imports.html) :使用各种 Prometheus 指标监控 GitLab [GitHub 导入](github_imports.html)器的运行状况和进度. +* [监视正常运行时间](../../user/admin_area/monitoring/health_check.html) :使用运行状况检查端点检查服务器状态. + * [IP 白名单](ip_whitelist.html) :配置 GitLab 以监视在探测时提供健康检查信息的端点. +* [`nginx_status`](https://docs.gitlab.com/omnibus/settings/nginx.html) :监视您的 NGINX 服务器状态 \ No newline at end of file diff --git a/_book/docs/472.md b/_book/docs/472.md new file mode 100644 index 0000000000000000000000000000000000000000..60802f2e96f5ca6ecc8eec9b8ab1f38e21b03f28 --- /dev/null +++ b/_book/docs/472.md @@ -0,0 +1,302 @@ +# Monitoring GitLab with Prometheus + +> 原文:[https://docs.gitlab.com/ee/administration/monitoring/prometheus/](https://docs.gitlab.com/ee/administration/monitoring/prometheus/) + +* [Overview](#overview) +* [Configuring Prometheus](#configuring-prometheus) + * [Changing the port and address Prometheus listens on](#changing-the-port-and-address-prometheus-listens-on) + * [Adding custom scrape configurations](#adding-custom-scrape-configurations) + * [Using an external Prometheus server](#using-an-external-prometheus-server) +* [Viewing performance metrics](#viewing-performance-metrics) +* [Prometheus as a Grafana data source](#prometheus-as-a-grafana-data-source) +* [GitLab metrics](#gitlab-metrics) +* [Bundled software metrics](#bundled-software-metrics) + * [Node exporter](#node-exporter) + * [Redis exporter](#redis-exporter) + * [PostgreSQL exporter](#postgresql-exporter) + * [PgBouncer exporter](#pgbouncer-exporter) + * [Registry exporter](#registry-exporter) + * [GitLab exporter](#gitlab-exporter) +* [Configuring Prometheus to monitor Kubernetes](#configuring-prometheus-to-monitor-kubernetes) + +# Monitoring GitLab with Prometheus[](#monitoring-gitlab-with-prometheus "Permalink") + +> **Notes:** +> +> * 本页中列出的 Prometheus 和各种出口商都捆绑在 Omnibus GitLab 软件包中. 查看每个出口商的文档以了解添加的时间表. 对于源安装,您必须自己安装. 在后续版本中,将捕获其他的 GitLab 指标. +> * GitLab 9.0 默认情况下会启用 Prometheus 服务. +> * Prometheus 及其出口商不对用户进行身份验证,任何可以访问它们的人都可以使用. + +[Prometheus](https://s0prometheus0io.icopy.site)是一项功能强大的时间序列监视服务,为监视 GitLab 和其他软件产品提供了灵活的平台. GitLab 提供了 Prometheus 的开箱即用监视功能,可轻松访问 GitLab 服务的高质量时间序列监视. + +## Overview[](#overview "Permalink") + +Prometheus 的工作方式是定期连接到数据源,并通过[各种出口商](#bundled-software-metrics)收集其绩效指标. 要查看和使用监视数据,您可以[直接连接到 Prometheus](#viewing-performance-metrics)或使用仪表板工具(例如[Grafana)](https://grafana.com) . + +## Configuring Prometheus[](#configuring-prometheus "Permalink") + +**注意:**对于源安装,您必须自己安装和配置. + +从 GitLab 9.0 开始,Prometheus 及其出口商默认情况下处于打开状态. Prometheus 将以`gitlab-prometheus`用户身份运行,并监听`http://localhost:9090` . 默认情况下,只能从 GitLab 服务器本身访问 Prometheus. 除非单独禁用,否则每个出口商将自动设置为 Prometheus 的监视目标. + +要禁用 Prometheus 及其所有出口商以及将来添加的任何出口商,请执行以下操作: + +1. Edit `/etc/gitlab/gitlab.rb` +2. 添加或查找并取消注释以下行,确保将其设置为`false` : + + ``` + prometheus_monitoring['enable'] = false + ``` + +3. 保存文件并[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +### Changing the port and address Prometheus listens on[](#changing-the-port-and-address-prometheus-listens-on "Permalink") + +**注意:** [Omnibus GitLab 8.17 中](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/1261)添加了以下更改. 尽管可能,但不建议更改 Prometheus 监听的端口,因为这可能会影响 GitLab 服务器上运行的其他服务或与之冲突. 继续需要您自担风险. + +为了从 GitLab 服务器外部访问 Prometheus,您需要在`prometheus['listen_address']`设置 FQDN 或 IP. 更改 Prometheus 监听的地址/端口: + +1. Edit `/etc/gitlab/gitlab.rb` +2. 添加或查找并取消注释以下行: + + ``` + prometheus['listen_address'] = 'localhost:9090' + ``` + + 将`localhost:9090`替换为您希望 Prometheus 监听的地址或端口. 如果要允许除`localhost`以外的其他主机访问 Prometheus,请忽略该主机,或使用`0.0.0.0`允许公共访问: + + ``` + prometheus['listen_address'] = ':9090' + # or + prometheus['listen_address'] = '0.0.0.0:9090' + ``` + +3. 保存文件并[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效 + +### Adding custom scrape configurations[](#adding-custom-scrape-configurations "Permalink") + +您可以使用[Prometheus 刮擦目标配置](https://s0prometheus0io.icopy.site/docs/prometheus/latest/configuration/configuration/)语法在`/etc/gitlab/gitlab.rb`编辑`prometheus['scrape_configs']` , `/etc/gitlab/gitlab.rb`为 Omnibus GitLab 捆绑的 Prometheus 配置其他刮擦目标. + +这是刮取`http://1.1.1.1:8060/probe?param_a=test¶m_b=additional_test`的示例配置: + +``` +prometheus['scrape_configs'] = [ + { + 'job_name': 'custom-scrape', + 'metrics_path': '/probe', + 'params' => { + 'param_a' => ['test'], + 'param_b' => ['additional_test'] + }, + 'static_configs' => [ + 'targets' => ['1.1.1.1:8060'], + ], + }, +] +``` + +### Using an external Prometheus server[](#using-an-external-prometheus-server "Permalink") + +**注意:** Prometheus 和大多数导出器不支持身份验证. 我们不建议将它们公开在本地网络之外. + +需要进行一些配置更改,才能由外部 Prometheus 服务器监视 GitLab. 对于[具有多个节点的 GitLab 部署,](../../reference_architectures/index.html)建议使用外部服务器. + +要使用外部 Prometheus 服务器: + +1. Edit `/etc/gitlab/gitlab.rb`. +2. 禁用捆绑的 Prometheus: + + ``` + prometheus['enable'] = false + ``` + +3. 将每个捆绑服务的[导出器设置](#bundled-software-metrics)为侦听网络地址,例如: + + ``` + gitlab_exporter['listen_address'] = '0.0.0.0' + sidekiq['listen_address'] = '0.0.0.0' + gitlab_exporter['listen_port'] = '9168' + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + gitaly['prometheus_listen_addr'] = "0.0.0.0:9236" + gitlab_workhorse['prometheus_listen_addr'] = "0.0.0.0:9229" + ``` + +4. 如有必要,请使用[官方安装说明](https://s0prometheus0io.icopy.site/docs/prometheus/latest/installation/)安装并设置专用的 Prometheus 实例. +5. 将 Prometheus 服务器 IP 地址添加到[监视 IP 白名单](../ip_whitelist.html) . 例如: + + ``` + gitlab_rails['monitoring_whitelist'] = ['127.0.0.0/8', '192.168.0.1'] + ``` + +6. 在**所有** GitLab Rails(Puma / Unicorn,Sidekiq)服务器上,设置 Prometheus 服务器 IP 地址和监听端口. 例如: + + ``` + gitlab_rails['prometheus_address'] = '192.168.0.1:9090' + ``` + +7. 要抓取 NGINX 指标,您还需要配置 NGINX 以允许 Prometheus 服务器 IP. 例如: + + ``` + nginx['status']['options'] = { + "server_tokens" => "off", + "access_log" => "off", + "allow" => "192.168.0.1", + "deny" => "all", + } + ``` + +8. [重新配置 GitLab](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以应用更改. +9. 编辑 Prometheus 服务器的配置文件. +10. 将每个节点的导出器添加到 Prometheus 服务器的[抓取目标配置中](https://s0prometheus0io.icopy.site/docs/prometheus/latest/configuration/configuration/) . 例如,使用`static_configs`的样本片段: + + ``` + scrape_configs: + - job_name: nginx + static_configs: + - targets: + - 1.1.1.1:8060 + - job_name: redis + static_configs: + - targets: + - 1.1.1.1:9121 + - job_name: postgres + static_configs: + - targets: + - 1.1.1.1:9187 + - job_name: node + static_configs: + - targets: + - 1.1.1.1:9100 + - job_name: gitlab-workhorse + static_configs: + - targets: + - 1.1.1.1:9229 + - job_name: gitlab-rails + metrics_path: "/-/metrics" + static_configs: + - targets: + - 1.1.1.1:8080 + - job_name: gitlab-sidekiq + static_configs: + - targets: + - 1.1.1.1:8082 + - job_name: gitlab_exporter_database + metrics_path: "/database" + static_configs: + - targets: + - 1.1.1.1:9168 + - job_name: gitlab_exporter_sidekiq + metrics_path: "/sidekiq" + static_configs: + - targets: + - 1.1.1.1:9168 + - job_name: gitlab_exporter_process + metrics_path: "/process" + static_configs: + - targets: + - 1.1.1.1:9168 + - job_name: gitaly + static_configs: + - targets: + - 1.1.1.1:9236 + ``` + +11. 重新加载 Prometheus 服务器. + +## Viewing performance metrics[](#viewing-performance-metrics "Permalink") + +您可以访问`http://localhost:9090` ,以获取 Prometheus 默认提供的仪表板. + +> **注意:**如果在您的 GitLab 实例上启用了 SSL,由于[HSTS,](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security)如果使用相同的 FQDN,则可能无法在与 GitLab 相同的浏览器上访问 Prometheus. 我们计划[通过 GitLab 提供访问](https://gitlab.com/gitlab-org/multi-user-prometheus) ,但是在此期间,有一些解决方法:使用单独的 FQDN,使用服务器 IP,使用单独的 Prometheus 浏览器,重置 HSTS 或使用[NGINX 代理](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +Prometheus 收集的性能数据可以在 Prometheus 控制台中直接查看,也可以通过兼容的仪表板工具查看. Prometheus 界面提供了一种[灵活的查询语言](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/basics/) ,可与收集的数据一起使用,您可以在其中可视化输出. 要获得功能更全面的仪表板,可以使用 Grafana 并已[对 Prometheus 进行了官方支持](https://s0prometheus0io.icopy.site/docs/visualization/grafana/) . + +普罗米修斯样本查询: + +* **可用内存百分比:** `((node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) or ((node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes) / node_memory_MemTotal_bytes)) * 100` +* **CPU 使用率百分比:** `1 - avg without (mode,cpu) (rate(node_cpu_seconds_total{mode="idle"}[5m]))` +* **传输的数据:** `rate(node_network_transmit_bytes_total{device!="lo"}[5m])` +* **收到的数据:** `rate(node_network_receive_bytes_total{device!="lo"}[5m])` + +## Prometheus as a Grafana data source[](#prometheus-as-a-grafana-data-source "Permalink") + +Grafana 允许您导入 Prometheus 性能指标作为数据源,并将指标呈现为图形和仪表板,这有助于可视化. + +To add a Prometheus dashboard for a single server GitLab setup: + +1. 在 Grafana 中创建一个新的数据源. +2. 命名您的数据源(如 GitLab). +3. 在类型下拉框中选择`Prometheus` . +4. 将您的 Prometheus 侦听地址添加为 URL,并设置对`Browser`访问权限. +5. 将 HTTP 方法设置为`GET` . +6. 保存并测试您的配置以验证其是否有效. + +## GitLab metrics[](#gitlab-metrics "Permalink") + +在 GitLab 9.3 中引入. + +GitLab 监视其自身的内部服务指标,并使其在`/-/metrics`端点可用. 与其他导出器不同,此终结点需要身份验证,因为它可以在与用户流量相同的 URL 和端口上使用. + +[➔ Read more about the GitLab Metrics.](gitlab_metrics.html) + +## Bundled software metrics[](#bundled-software-metrics "Permalink") + +Omnibus GitLab 中捆绑的许多 GitLab 依赖项都已预先配置为导出 Prometheus 指标. + +### Node exporter[](#node-exporter "Permalink") + +节点导出器允许您测量各种机器资源,例如内存,磁盘和 CPU 利用率. + +[Read more about the node exporter](node_exporter.html). + +### Redis exporter[](#redis-exporter "Permalink") + +Redis 导出器允许您测量各种 Redis 指标. + +[Read more about the Redis exporter](redis_exporter.html). + +### PostgreSQL exporter[](#postgresql-exporter "Permalink") + +PostgreSQL 导出器允许您测量各种 PostgreSQL 指标. + +[Read more about the PostgreSQL exporter](postgres_exporter.html). + +### PgBouncer exporter[](#pgbouncer-exporter "Permalink") + +PgBouncer 导出器允许您测量各种 PgBouncer 指标. + +[Read more about the PgBouncer exporter](pgbouncer_exporter.html). + +### Registry exporter[](#registry-exporter "Permalink") + +注册表导出器允许您测量各种注册表指标. + +[Read more about the Registry exporter](registry_exporter.html). + +### GitLab exporter[](#gitlab-exporter "Permalink") + +GitLab 导出器允许您测量从 Redis 和数据库中提取的各种 GitLab 指标. + +[Read more about the GitLab exporter](gitlab_exporter.html). + +## Configuring Prometheus to monitor Kubernetes[](#configuring-prometheus-to-monitor-kubernetes "Permalink") + +版本历史 + +* 在 GitLab 9.0 中引入. +* 在 GitLab 9.4 中引入了 Pod 监控. + +如果您的 GitLab 服务器在 Kubernetes 中运行,则 Prometheus 将从群集中的节点和带[注释的](https://s0prometheus0io.icopy.site/docs/prometheus/latest/configuration/configuration/) Pod 收集指标,包括每个容器上的性能数据. 如果您的 CI / CD 环境在同一群集中运行,这将特别有用,因为您可以使用[Prometheus 项目集成](../../../user/project/integrations/prometheus.html)来监视它们. + +要禁用对 Kubernetes 的监视: + +1. Edit `/etc/gitlab/gitlab.rb`. +2. 添加(或查找并取消注释)以下行并将其设置为`false` : + + ``` + prometheus['monitor_kubernetes'] = false + ``` + +3. 保存文件并[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. \ No newline at end of file diff --git a/_book/docs/473.md b/_book/docs/473.md new file mode 100644 index 0000000000000000000000000000000000000000..7c8d4242b190b9d3963e8af2c838c7f1b2f15c99 --- /dev/null +++ b/_book/docs/473.md @@ -0,0 +1,60 @@ +# Performance Bar + +> 原文:[https://docs.gitlab.com/ee/administration/monitoring/performance/performance_bar.html](https://docs.gitlab.com/ee/administration/monitoring/performance/performance_bar.html) + +* [Request warnings](#request-warnings) +* [Enable the Performance Bar via the Admin panel](#enable-the-performance-bar-via-the-admin-panel) +* [Keyboard shortcut for the Performance Bar](#keyboard-shortcut-for-the-performance-bar) + +# Performance Bar[](#performance-bar "Permalink") + +您可以显示 GitLab 性能栏以查看页面性能的统计信息. 激活后,其外观如下: + +[![Performance Bar](img/a87cd8265a25e22c9a715c6372ff047a.png)](img/performance_bar.png) + +从左到右,它显示: + +* **当前主机** :服务于该页面的当前主机. +* **数据库查询** :花费的时间(毫秒)和数据库查询的总数,以`00ms / 00pg`的格式显示. 单击以显示更多信息的模式窗口: [![使用性能栏进行 SQL 分析](img/631b8ad9816cfdd87ba106377c86c7a4.png)](img/performance_bar_sql_queries.png) +* **Gitaly 通话** :所花费的时间(以毫秒为单位)和[Gitaly](../../gitaly/index.html)通话的总数. 单击以显示更多信息的模式窗口: [![使用性能栏进行 Gitaly 分析](img/aeccb5cc55fc430d8645e67086388300.png)](img/performance_bar_gitaly_calls.png) +* **坚固通话** :花费的时间(以毫秒为单位)和[坚固](../../high_availability/nfs.html#improving-nfs-performance-with-gitlab)通话的总数. 单击以显示更多信息的模式窗口: [![使用性能栏进行坚固的性能分析](img/35fbd0a23d3b20913cb4490a3957d8b3.png)](img/performance_bar_rugged_calls.png) +* **Redis 呼叫** :花费的时间(以毫秒为单位)和 Redis 呼叫的总数. 单击以显示更多信息的模式窗口: [![使用性能栏进行 Redis 分析](img/b6696ad0d59c74a9a3974493085915f9.png)](img/performance_bar_redis_calls.png) +* **Elasticsearch 调用** :花费的时间(以毫秒为单位)和 Elasticsearch 调用的总数. 单击以显示更多信息的模式窗口. +* 页面的**加载时间** :如果您的浏览器支持加载时间(Chromium 和 Chrome),则以毫秒为单位的多个值(以斜杠分隔). 单击以显示更多信息的模式窗口. 值从左到右: + * **后端** :加载基本页面所需的时间. + * [**First Contentful Paint**](https://s0web0dev.icopy.site/first-contentful-paint/) :直到用户看到某些东西为止的时间. + * [**DomContentLoaded**](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/measure-crp)事件. + * 页面加载**的请求总数** : [![使用性能栏的前端请求](img/ca66569a1f77e8f2d208a42e0fee1794.png)](img/performance_bar_frontend.png) +* **跟踪** :如果集成了 Jaeger,则**Trace**链接到 Jaeger 跟踪页面,其中包含当前请求的`correlation_id` . +* **+** :用于将请求的详细信息添加到性能栏的链接. 可以通过其完整 URL(已认证为当前用户)或其`X-Request-Id`标头的值来添加`X-Request-Id` . +* **下载** :下载用于生成 Performance Bar 报告的原始 JSON 的链接. +* **请求选择器** :显示在性能栏右侧的选择框,通过该选择框,您可以查看当前页面打开时发出的所有请求的这些指标. 每个唯一 URL 仅捕获前两个请求. + +## Request warnings[](#request-warnings "Permalink") + +超出预定义限制的请求显示警告 指标旁边的图标和说明. 在此示例中,Gitaly 通话时间超过了阈值: + +[![Gitaly call duration exceeded threshold](img/dd6b38427a8d14832104464d1603afed.png)](img/performance_bar_gitaly_threshold.png) + +如果当前页面上的任何请求生成警告,则警告图标将显示在" **请求"选择器**旁边: + +[![Request selector showing two requests with warnings](img/874270632cfad28b99af65b5d0275fee.png)](img/performance_bar_request_selector_warning.png) + +带有警告的**请求**在**请求选择器中**的路径后显示`(!)` : + +[![Request selector showing dropdown](img/02f288cad0ff70d293c035d6dc434f34.png)](img/performance_bar_request_selector_warning_expanded.png) + +## Enable the Performance Bar via the Admin panel[](#enable-the-performance-bar-via-the-admin-panel "Permalink") + +默认情况下,GitLab 性能栏是禁用的. 要为给定的组启用它: + +1. 以具有管理员[权限](../../../user/permissions.html)的用户身份登录. +2. 在菜单栏中,单击 **管理区域**图标. +3. 导航 **设置>指标和分析** ( `admin/application_settings/metrics_and_profiling` ),然后展开" **分析-性能栏** "部分. +4. Click **启用对性能栏的访问**. +5. 在**允许的组**字段中,提供允许访问 GitLab 性能栏的组的完整路径. +6. Click **保存更改**. + +## Keyboard shortcut for the Performance Bar[](#keyboard-shortcut-for-the-performance-bar "Permalink") + +启用 GitLab 性能栏后,按[`p` + `b`键盘快捷键](../../../user/shortcuts.html)将其显示,然后再次将其隐藏. \ No newline at end of file diff --git a/_book/docs/474.md b/_book/docs/474.md new file mode 100644 index 0000000000000000000000000000000000000000..cf859f1e9398a108b02c45de3aa075384ad8313b --- /dev/null +++ b/_book/docs/474.md @@ -0,0 +1,53 @@ +# Usage statistics + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/settings/usage_statistics.html](https://docs.gitlab.com/ee/user/admin_area/settings/usage_statistics.html) + +* [Network configuration](#network-configuration) +* [Version Check](#version-check-core-only) + * [Request flow example](#request-flow-example) +* [Usage Ping](#usage-ping-core-only) +* [Instance statistics visibility](#instance-statistics-visibility-core-only) + +# Usage statistics[](#usage-statistics-core-only "Permalink") + +GitLab Inc.将定期收集有关您的实例的信息,以执行各种操作. + +所有统计信息均已退出. 您可以在**管理区域>设置>指标和配置文件** **使用情况统计信息中**启用/禁用它们. + +## Network configuration[](#network-configuration "Permalink") + +允许从您的 GitLab 实例到 IP 地址`104.196.17.203:443`网络流量将使用情况统计信息发送到 GitLab Inc. + +如果您的 GitLab 实例位于代理之后,请设置适当的[代理配置变量](https://docs.gitlab.com/omnibus/settings/environment-variables.html) . + +## Version Check[](#version-check-core-only "Permalink") + +如果启用,版本检查将通过状态通知您是否有新版本以及其重要性. 这显示在所有登录用户的帮助页面(即`/help` )和管理页面上. 状态为: + +* 绿色:您正在运行最新版本的 GitLab. +* 橙色:提供了 GitLab 的更新版本. +* 红色:您正在运行的 GitLab 版本容易受到攻击. 您应该尽快安装具有安全修复程序的最新版本. + +[![Orange version check example](img/aec2abca2644938484258f63a3df71d2.png)](img/update-available.png) + +GitLab Inc.收集您实例的版本和主机名(通过 HTTP 引用),作为版本检查的一部分. 没有收集其他信息. + +除其他事项外,该信息还用于标识需要将补丁反向移植到哪些版本,以确保活动的 GitLab 实例保持安全. + +如果禁用版本检查,则不会收集此信息. 在**管理区域>设置>度量标准和性能分析>使用情况统计信息中**启用或禁用版本检查. + +### Request flow example[](#request-flow-example "Permalink") + +以下示例显示了自我管理的 GitLab 实例与 GitLab 版本应用程序之间的基本请求/响应流: + +sequenceDiagram 参与者 GitLab 实例参与者版本应用程序 GitLab 实例->>版本应用程序:是否有版本更新? 循环版本检查版本应用程序->>版本应用程序:记录版本信息结束版本应用程序->> GitLab 实例:响应(PNG / SVG) + +## Usage Ping[](#usage-ping-core-only "Permalink") + +See [Usage Ping guide](../../../development/telemetry/usage_ping.html). + +## Instance statistics visibility[](#instance-statistics-visibility-core-only "Permalink") + +启用使用情况 ping 后,GitLab 将从其他实例收集数据,并能够向用户显示您实例的[使用情况统计信息](../../instance_statistics/index.html) . + +要使其仅对管理员可见,请进入**管理区域>设置>指标和分析** ,展开**使用情况统计信息** ,然后将**实例统计信息可见性**选项设置为**仅管理员** . \ No newline at end of file diff --git a/_book/docs/475.md b/_book/docs/475.md new file mode 100644 index 0000000000000000000000000000000000000000..1e44b8713c0b0bfec6bfdceead1797cf2473ed97 --- /dev/null +++ b/_book/docs/475.md @@ -0,0 +1,524 @@ +# Object Storage + +> 原文:[https://docs.gitlab.com/ee/administration/object_storage.html](https://docs.gitlab.com/ee/administration/object_storage.html) + +* [Options](#options) +* [Configuration guides](#configuration-guides) + * [Consolidated object storage configuration](#consolidated-object-storage-configuration) + * [Common parameters](#common-parameters) + * [Connection settings](#connection-settings) + * [S3-compatible connection settings](#s3-compatible-connection-settings) + * [Oracle Cloud S3 connection settings](#oracle-cloud-s3-connection-settings) + * [Google Cloud Storage (GCS)](#google-cloud-storage-gcs) + * [Google example (consolidated form)](#google-example-consolidated-form) + * [OpenStack-compatible connection settings](#openstack-compatible-connection-settings) + * [Rackspace Cloud Files](#rackspace-cloud-files) + * [Object-specific configuration](#object-specific-configuration) + * [Selectively disabling object storage](#selectively-disabling-object-storage) + * [Transition to consolidated form](#transition-to-consolidated-form) +* [Storage-specific configuration](#storage-specific-configuration) + * [Other alternatives to filesystem storage](#other-alternatives-to-filesystem-storage) +* [Warnings, limitations, and known issues](#warnings-limitations-and-known-issues) + * [Use separate buckets](#use-separate-buckets) + * [S3 API compatibility issues](#s3-api-compatibility-issues) + * [GitLab Pages requires NFS](#gitlab-pages-requires-nfs) + * [Incremental logging is required for CI to use object storage](#incremental-logging-is-required-for-ci-to-use-object-storage) + * [Proxy Download](#proxy-download) + * [ETag mismatch](#etag-mismatch) + * [Using Amazon instance profiles](#using-amazon-instance-profiles) + * [Encrypted S3 buckets](#encrypted-s3-buckets) + * [Disabling the feature](#disabling-the-feature) + * [IAM Permissions](#iam-permissions) + +# Object Storage[](#object-storage "Permalink") + +GitLab 支持使用对象存储服务来保存多种类型的数据. 建议在 NFS 上使用它,并且通常在较大的设置中更好,因为对象存储通常具有更高的性能,可靠性和可伸缩性. + +## Options[](#options "Permalink") + +GitLab 已在许多对象存储提供程序上进行了测试: + +* [Amazon S3](https://aws.amazon.com/s3/) +* [Google Cloud Storage](https://cloud.google.com/storage) +* [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces) +* [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm) +* [Openstack Swift](https://s0docs0openstack0org.icopy.site/swift/latest/s3_compat.html) +* 来自各种存储供应商的本地硬件和设备. +* MinIO. 我们在 Helm Chart 文档中提供[了有关部署此配置的指南](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) . + +## Configuration guides[](#configuration-guides "Permalink") + +在 GitLab 中有两种指定对象存储配置的方式: + +* [合并形式](#consolidated-object-storage-configuration) :所有支持的对象类型都共享一个凭证. +* [Storage-specific form](#storage-specific-configuration): Every object defines its own object storage [connection and configuration](#connection-settings). + +有关差异以及从一种形式过渡到另一种形式的更多信息,请参见[过渡到合并形式](#transition-to-consolidated-form) . + +### Consolidated object storage configuration[](#consolidated-object-storage-configuration "Permalink") + +在[GitLab 13.2 中](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4368)引入. + +使用合并对象存储配置具有许多优点: + +* 由于连接详细信息在对象类型之间共享,因此可以简化您的 GitLab 配置. +* 它允许使用[加密的 S3 存储桶](#encrypted-s3-buckets) . +* It [uploads files to S3 with proper `Content-MD5` headers](https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/222). + +**注意:**由于必须使用[直接上载模式](../development/uploads.html#direct-upload) ,目前仅支持与 AWS S3 兼容的提供商和 Google. 此模式不支持后台上传. 我们建议直接上传模式,因为它不需要共享文件夹,并且[此设置可能成为默认设置](https://gitlab.com/gitlab-org/gitlab/-/issues/27331) .**注意:**合并对象存储配置不能用于备份或 Mattermost. 有关[完整列表,](#storage-specific-configuration)请参见[完整表](#storage-specific-configuration) . + +通过为具有多个存储桶的对象存储指定单个凭证,可以将大多数类型的对象(例如 CI 工件,LFS 文件,上传附件等)保存在对象存储中. [每种类型必须使用不同的存储桶](#use-separate-buckets) . + +当合并形式为: + +* 通过与 S3 兼容的对象存储一起使用,Workhorse 使用其内部的 S3 客户端上载文件. +* 不与 S3 兼容的对象存储一起使用,Workhorse 退回到使用预签名的 URL. + +有关更多详细信息,请参见" [ETag 不匹配错误](#etag-mismatch) "部分. + +**在所有安装中;** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下行,以替换所需的值: + + ``` + # Consolidated object storage configuration + gitlab_rails['object_store']['enabled'] = true + gitlab_rails['object_store']['proxy_download'] = true + gitlab_rails['object_store']['connection'] = { + 'provider' => 'AWS', + 'region' => '', + 'aws_access_key_id' => '', + 'aws_secret_access_key' => '' + } + gitlab_rails['object_store']['objects']['artifacts']['bucket'] = '' + gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = '' + gitlab_rails['object_store']['objects']['lfs']['bucket'] = '' + gitlab_rails['object_store']['objects']['uploads']['bucket'] = '' + gitlab_rails['object_store']['objects']['packages']['bucket'] = '' + gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = '' + gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = '' + ``` + + 对于 GitLab 9.4 或更高版本,如果您使用的是 AWS IAM 配置文件,请确保省略 AWS 访问密钥和秘密访问密钥/值对. 例如: + + ``` + gitlab_rails['object_store_connection'] = { + 'provider' => 'AWS', + 'region' => '', + 'use_iam_profile' => true + } + ``` + +2. 保存文件并[重新配置 GitLab,](restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**在源安装中:** + +1. 编辑`/home/git/gitlab/config/gitlab.yml`并添加或修改以下行: + + ``` + object_store: + enabled: true + proxy_download: true + connection: + provider: AWS + aws_access_key_id: + aws_secret_access_key: + region: + objects: + artifacts: + bucket: + external_diffs: + bucket: + lfs: + bucket: + uploads: + bucket: + packages: + bucket: + dependency_proxy: + bucket: + terraform_state: + bucket: + ``` + +2. 编辑`/home/git/gitlab-workhorse/config.toml`并添加或修改以下行: + + ``` + [object_storage] + enabled = true + provider = "AWS" + + [object_storage.s3] + aws_access_key_id = "" + aws_secret_access_key = "" + ``` + +3. 保存文件并[重新启动 GitLab,](restart_gitlab.html#installations-from-source)以使更改生效. + +#### Common parameters[](#common-parameters "Permalink") + +在统一配置中, `object_store`部分定义了一组公共参数. 在这里,我们使用源安装中的 YAML,因为它更容易看到继承: + +``` + object_store: + enabled: true + proxy_download: true + connection: + provider: AWS + aws_access_key_id: + aws_secret_access_key: + objects: + ... +``` + +Omnibus 配置直接映射到此: + +``` +gitlab_rails['object_store']['enabled'] = true +gitlab_rails['object_store']['proxy_download'] = true +gitlab_rails['object_store']['connection'] = { + 'provider' => 'AWS', + 'aws_access_key_id' => ' '' +} +``` + +| Setting | Description | +| --- | --- | +| `enabled` | 启用/禁用对象存储 | +| `proxy_download` | 设置为`true`以[启用代理服务的所有文件](#proxy-download) . Option 可以减少出口流量,因为这允许客户端直接从远程存储下载而不是代理所有数据 | +| `connection` | 下述各种连接选项 | +| `objects` | [Object-specific configuration](#object-specific-configuration) | + +### Connection settings[](#connection-settings "Permalink") + +合并配置表单和特定于存储的配置表单都必须配置连接. 以下各节介绍可在`connection`设置中使用的参数. + +#### S3-compatible connection settings[](#s3-compatible-connection-settings "Permalink") + +连接设置与[fog-aws](https://github.com/fog/fog-aws)提供的设置匹配: + +| Setting | Description | Default | +| --- | --- | --- | +| `provider` | 始终适用于兼容主机的`AWS` | `AWS` | +| `aws_access_key_id` | AWS 凭证或兼容 |   | +| `aws_secret_access_key` | AWS 凭证或兼容 |   | +| `aws_signature_version` | 要使用的 AWS 签名版本. `2`或`4`是有效选项. 数字海洋空间和其他提供商可能需要`2` . | `4` | +| `enable_signature_v4_streaming` | 设置为`true`以启用具有[AWS v4 签名的](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html) HTTP 分块传输. Oracle Cloud S3 需要将此设置为`false` . | `true` | +| `region` | AWS 区域 | us-east-1 | +| `host` | 不使用 AWS 时与 S3 兼容的主机,例如`localhost`或`storage.example.com` . 假定使用 HTTPS 和端口 443. | `s3.amazonaws.com` | +| `endpoint` | 在配置 S3 兼容服务(例如[MinIO)时](https://min.io) ,可以通过输入 URL(例如`http://127.0.0.1:9000` . 这优先于`host` . | (optional) | +| `path_style` | 设置为`true`以使用`host/bucket_name/object`样式路径而不是`bucket_name.host/object` . 对于 AWS S3,保留为`false` . | `false` | +| `use_iam_profile` | Set to `true` to use IAM profile instead of access keys | `false` | + +#### Oracle Cloud S3 connection settings[](#oracle-cloud-s3-connection-settings "Permalink") + +请注意,Oracle Cloud S3 必须确保使用以下设置: + +| Setting | Value | +| --- | --- | +| `enable_signature_v4_streaming` | `false` | +| `path_style` | `true` | + +如果将`enable_signature_v4_streaming`设置为`true` ,那么您可能会在`production.log`看到以下错误: + +``` +STREAMING-AWS4-HMAC-SHA256-PAYLOAD is not supported +``` + +#### Google Cloud Storage (GCS)[](#google-cloud-storage-gcs "Permalink") + +这是 GCS 的有效连接参数: + +| Setting | Description | example | +| --- | --- | --- | +| `provider` | 提供者名称 | `Google` | +| `google_project` | GCP 项目名称 | `gcp-project-12345` | +| `google_client_email` | 服务帐户的电子邮件地址 | `foo@gcp-project-12345.iam.gserviceaccount.com` | +| `google_json_key_location` | JSON 密钥路径 | `/path/to/gcp-project-12345-abcde.json` | + +**注意:**服务帐户必须具有访问存储桶的权限. [看更多](https://cloud.google.com/storage/docs/authentication) + +##### Google example (consolidated form)[](#google-example-consolidated-form "Permalink") + +对于 Omnibus 安装,这是`connection`设置的示例: + +``` +gitlab_rails['object_store']['connection'] = { + 'provider' => 'Google', + 'google_project' => '', + 'google_client_email' => '', + 'google_json_key_location' => '' +} +``` + +#### OpenStack-compatible connection settings[](#openstack-compatible-connection-settings "Permalink") + +**注意**这与统一对象存储表单不兼容. 仅特定于存储的表单支持 OpenStack Swift. 如果要使用合并表格,请参阅[S3 设置](#s3-compatible-connection-settings) . + +尽管 OpenStack Swift 提供了 S3 兼容性,但某些用户可能希望使用[Swift API](https://s0docs0openstack0org.icopy.site/swift/latest/api/object_api_v1_overview.html) . 这是以下由[swift-openstack](https://github.com/fog/fog-openstack)提供的 Swift API 的有效连接设置: + +| Setting | Description | Default | +| --- | --- | --- | +| `provider` | 始终使用`OpenStack`兼容主机 | `OpenStack` | +| `openstack_username` | OpenStack 用户名 |   | +| `openstack_api_key` | OpenStack API key |   | +| `openstack_temp_url_key` | 用于生成临时 URL 的 OpenStack 密钥 |   | +| `openstack_auth_url` | OpenStack 身份验证端点 |   | +| `openstack_region` | OpenStack 区域 |   | +| `openstack_tenant` | OpenStack 租户 ID |   | + +#### Rackspace Cloud Files[](#rackspace-cloud-files "Permalink") + +**注意**这与统一对象存储表单不兼容. 仅特定于存储的表单支持 Rackspace Cloud. + +这是[fog-rackspace](https://github.com/fog/fog-rackspace/)提供的 Rackspace Cloud 的有效连接参数: + +| Setting | Description | example | +| --- | --- | --- | +| `provider` | 提供者名称 | `Rackspace` | +| `rackspace_username` | 可访问容器的 Rackspace 帐户的用户名 | `joe.smith` | +| `rackspace_api_key` | 可访问容器的 Rackspace 帐户的 API 密钥 | `ABC123DEF456ABC123DEF456ABC123DE` | +| `rackspace_region` | 要使用的 Rackspace 存储区域,来自[服务访问端点列表的](https://developer.rackspace.com/docs/cloud-files/v1/general-api-info/service-access/)三个字母代码 | `iad` | +| `rackspace_temp_url_key` | 您在 Rackspace API 中为临时 URL 设置的私钥. [在这里](https://developer.rackspace.com/docs/cloud-files/v1/use-cases/public-access-to-your-cloud-files-account/#tempurl)阅读更多 | `ABC123DEF456ABC123DEF456ABC123DE` | + +**注意:**无论容器启用还是禁用了公共访问,Fog 都会使用 TempURL 方法来授予对 LFS 对象的访问权限. 如果您在引用使用`temp-url-key`实例化存储的日志中看到错误,请确保已在 Rackspace API 和`gitlab.rb`正确设置了密钥. 您可以通过将带有令牌标头的 GET 请求发送到服务访问端点 URL 并比较返回的标头的输出,来验证 Rackspace 密钥的设置值. + +### Object-specific configuration[](#object-specific-configuration "Permalink") + +以下 YAML 显示了`object_store`部分如何定义特定于对象的配置块,以及如何覆盖`enabled`和`proxy_download`标志. `bucket`是每种类型中唯一需要的参数: + +``` + object_store: + connection: + ... + objects: + artifacts: + bucket: artifacts + proxy_download: false + external_diffs: + bucket: external-diffs + lfs: + bucket: lfs-objects + uploads: + bucket: uploads + packages: + bucket: packages + dependency_proxy: + enabled: false + bucket: dependency_proxy + terraform_state: + bucket: terraform +``` + +这映射到此 Omnibus GitLab 配置: + +``` +gitlab_rails['object_store']['objects']['artifacts']['bucket'] = 'artifacts' +gitlab_rails['object_store']['objects']['artifacts']['proxy_download'] = false +gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = 'external-diffs' +gitlab_rails['object_store']['objects']['lfs']['bucket'] = 'lfs-objects' +gitlab_rails['object_store']['objects']['uploads']['bucket'] = 'uploads' +gitlab_rails['object_store']['objects']['packages']['bucket'] = 'packages' +gitlab_rails['object_store']['objects']['dependency_proxy']['enabled'] = false +gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = 'dependency-proxy' +gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = 'terraform-state' +``` + +这是可以使用的有效`objects`的列表: + +| Type | Description | +| --- | --- | +| `artifacts` | [CI artifacts](job_artifacts.html) | +| `external_diffs` | [Merge request diffs](merge_request_diffs.html) | +| `uploads` | [User uploads](uploads.html) | +| `lfs` | [Git Large File Storage objects](lfs/index.html) | +| `packages` | [Project packages (e.g. PyPI, Maven, NuGet, etc.)](packages/index.html) | +| `dependency_proxy` | [GitLab Dependency Proxy](packages/dependency_proxy.html) | +| `terraform_state` | [Terraform state files](terraform_state.html) | + +在每种对象类型中,可以定义三个参数: + +| Setting | Required? | Description | +| --- | --- | --- | +| `bucket` | Yes | 对象存储的存储桶名称. | +| `enabled` | No | 覆盖通用参数 | +| `proxy_download` | No | 覆盖通用参数 | + +#### Selectively disabling object storage[](#selectively-disabling-object-storage "Permalink") + +如上所示,可以通过将`enabled`标志设置为`false`来禁用特定类型的对象存储. 例如,要禁用 CI 工件的对象存储: + +``` +gitlab_rails['object_store']['objects']['artifacts']['enabled'] = false +``` + +如果功能完全禁用,则不需要存储桶. 例如,如果使用此设置禁用了 CI 构件,则不需要存储桶: + +``` +gitlab_rails['artifacts_enabled'] = false +``` + +### Transition to consolidated form[](#transition-to-consolidated-form "Permalink") + +在 GitLab 13.2 之前: + +* 所有类型的对象(例如 CI / CD 工件,LFS 文件,上载附件等)的对象存储配置都必须独立配置. +* 对于每种类型,必须复制对象存储连接参数,例如密码和端点 URL. + +例如,Omnibus GitLab 安装可能具有以下配置: + +``` +# Original object storage configuration +gitlab_rails['artifacts_object_store_enabled'] = true +gitlab_rails['artifacts_object_store_direct_upload'] = true +gitlab_rails['artifacts_object_store_proxy_download'] = true +gitlab_rails['artifacts_object_store_remote_directory'] = 'artifacts' +gitlab_rails['artifacts_object_store_connection'] = { 'provider' => 'AWS', 'aws_access_key_id' => 'access_key', 'aws_secret_access_key' => 'secret' } +gitlab_rails['uploads_object_store_enabled'] = true +gitlab_rails['uploads_object_store_direct_upload'] = true +gitlab_rails['uploads_object_store_proxy_download'] = true +gitlab_rails['uploads_object_store_remote_directory'] = 'uploads' +gitlab_rails['uploads_object_store_connection'] = { 'provider' => 'AWS', 'aws_access_key_id' => 'access_key', 'aws_secret_access_key' => 'secret' } +``` + +尽管这样做提供了灵活性,但它使得 GitLab 可以跨不同的云提供商存储对象,但同时也带来了额外的复杂性和不必要的冗余. 由于 GitLab Rails 和 Workhorse 组件都需要访问对象存储,因此合并后的表单避免了过多的凭据重复. + +**注意** **仅**当省略原始表单中的所有行时, **才**使用合并对象存储配置. 要移至合并的表单,请除去原始配置(例如, `artifacts_object_store_enabled` , `uploads_object_store_connection`等). + +## Storage-specific configuration[](#storage-specific-configuration "Permalink") + +有关在 GitLab 13.1 和更早版本中配置对象存储的信息,或对于统一配置表单不支持的存储类型的信息,请参阅以下指南: + +| 对象存储类型 | 支持统一配置吗? | +| --- | --- | +| [Backups](../raketasks/backup_restore.html#uploading-backups-to-a-remote-cloud-storage) | No | +| [Job artifacts](job_artifacts.html#using-object-storage) and [incremental logging](job_logs.html#new-incremental-logging-architecture) | Yes | +| [LFS objects](lfs/index.html#storing-lfs-objects-in-remote-object-storage) | Yes | +| [Uploads](uploads.html#using-object-storage-core-only) | Yes | +| [容器注册表](packages/container_registry.html#container-registry-storage-driver) (可选功能) | No | +| [Merge request diffs](merge_request_diffs.html#using-object-storage) | Yes | +| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage) | No | +| [软件包](packages/index.html#using-object-storage) (可选功能) | Yes | +| [依赖代理](packages/dependency_proxy.html#using-object-storage) (可选功能) | Yes | +| [假名生成器](pseudonymizer.html#configuration) (可选功能) | No | +| [Autoscale Runner 缓存](https://docs.gitlab.com/runner/configuration/autoscale.html) (可选以提高性能) | No | +| [Terraform state files](terraform_state.html#using-object-storage-core-only) | Yes | + +### Other alternatives to filesystem storage[](#other-alternatives-to-filesystem-storage "Permalink") + +如果您正在努力[扩展](reference_architectures/index.html) GitLab 实施,或增加容错能力和冗余性,则可能正在考虑消除对块或网络文件系统的依赖. 请参阅以下指南,并[注意 Pages 需要磁盘存储](#gitlab-pages-requires-nfs) : + +1. 确保[`git`用户主目录](https://docs.gitlab.com/omnibus/settings/configuration.html)位于本地磁盘上. +2. 配置[SSH 密钥的数据库查找,](operations/fast_ssh_key_lookup.html)以消除对共享的`authorized_keys`文件的需要. + +## Warnings, limitations, and known issues[](#warnings-limitations-and-known-issues "Permalink") + +### Use separate buckets[](#use-separate-buckets "Permalink") + +对于 GitLab,建议为每种数据类型使用单独的存储桶. + +我们的配置的局限性是对象存储的每次使用都是单独配置的. [我们有一个需要改进的问题](https://gitlab.com/gitlab-org/gitlab/-/issues/23345) ,轻松地将一个存储桶与单独的文件夹一起使用可能会带来一个改进. + +使用同一个存储桶至少有一个特定的问题:当使用 Helm 图表部署 GitLab 时,除非使用单独的存储桶,否则从备份还原[将无法正常工作](https://docs.gitlab.com/charts/advanced/external-object-storage/) . + +使用单个存储桶的风险之一是,如果您的组织将来决定将 GitLab 迁移到 Helm 部署. GitLab 可以运行,但是直到组织对备份起作用的关键要求之前,备份的情况可能无法实现. + +### S3 API compatibility issues[](#s3-api-compatibility-issues "Permalink") + +并非所有 S3 提供程序[都](../raketasks/backup_restore.html#other-s3-providers)与 GitLab 使用的 Fog 库[完全兼容](../raketasks/backup_restore.html#other-s3-providers) . 症状包括`production.log`的错误: + +``` +411 Length Required +``` + +### GitLab Pages requires NFS[](#gitlab-pages-requires-nfs "Permalink") + +如果您要添加更多的 GitLab 服务器以进行[缩放或容错,](reference_architectures/index.html)并且您的要求之一是[GitLab 页面,](../user/project/pages/index.html)则当前需要 NFS. 有[工作正在进行中](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)去除这种依赖性. 将来,GitLab 页面可能会使用[对象存储](https://gitlab.com/gitlab-org/gitlab/-/issues/208135) . + +对磁盘存储的依赖性还阻止了使用[GitLab Helm 图表](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/37)部署 Pages. + +### Incremental logging is required for CI to use object storage[](#incremental-logging-is-required-for-ci-to-use-object-storage "Permalink") + +如果将 GitLab 配置为将对象存储用于 CI 日志和工件,则[还必须启用增量日志记录](job_artifacts.html#using-object-storage) . + +### Proxy Download[](#proxy-download "Permalink") + +对象存储的许多使用情况都允许将客户端流量重定向到对象存储后端,例如当 Git 客户端通过 LFS 请求大文件时或在下载 CI 工件和日志时. + +When the files are stored on local block storage or NFS, GitLab has to act as a proxy. This is not the default behavior with object storage. + +`proxy_download`设置控制此行为:默认设置通常为`false` . 在每个用例的文档中对此进行验证. 将其设置为`true`以便 GitLab 代理文件. + +当不代理文件时,GitLab 将返回[HTTP 302 重定向,该重定向带有预先签名的有时间限制的对象存储 URL](https://gitlab.com/gitlab-org/gitlab/-/issues/32117#note_218532298) . 这可能会导致以下一些问题: + +* 如果 GitLab 使用非安全的 HTTP 访问对象存储,则客户端可能会生成`https->http`降级错误,并拒绝处理重定向. 解决方案是让 GitLab 使用 HTTPS. 例如,LFS 将产生此错误: + + ``` + LFS: lfsapi/client: refusing insecure redirect, https->http + ``` + +* 客户端将需要信任颁发对象存储证书的证书颁发机构,或者可能返回常见的 TLS 错误,例如: + + ``` + x509: certificate signed by unknown authority + ``` + +* 客户端将需要网络访问对象存储. 如果没有此访问权限,则可能导致的错误包括: + + ``` + Received status code 403 from server: Forbidden + ``` + +[软件包存储库文档中](packages/index.html#using-object-storage)特别注明了获取" `403 Forbidden`响应",这是某些构建工具的工作方式的副作用. + +### ETag mismatch[](#etag-mismatch "Permalink") + +使用默认的 GitLab 设置,某些对象存储后端(例如[MinIO](https://gitlab.com/gitlab-org/gitlab/-/issues/23188)和[Alibaba)](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564)可能会生成`ETag mismatch`错误. + +如果您在 Amazon Web Services S3 中看到此 ETag 不匹配错误,则可能是由于[存储桶上的加密设置](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTCommonResponseHeaders.html)所致. 要解决此问题,您有两种选择: + +* [Use the consolidated object configuration](#consolidated-object-storage-configuration). +* [Use Amazon instance profiles](#using-amazon-instance-profiles). + +对于 MinIO,建议使用第一个选项. 否则, [MinIO](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564#note_244497658)的[解决方法](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564#note_244497658)是在服务器上使用`--compat`参数. + +在未启用统一对象存储配置或实例配置文件的情况下,GitLab Workhorse 将使用没有为它们计算出`Content-MD5` HTTP 标头的预签名 URL 将文件上传到 S3\. 为了确保数据没有损坏,Workhorse 检查发送的数据的 MD5 哈希值是否等于从 S3 服务器返回的 ETag 标头. 启用加密后,情况并非如此,这将导致 Workhorse 在上传期间报告`ETag mismatch`错误. + +通过整合的对象配置和实例配置文件,Workhorse 具有 S3 凭据,因此可以计算`Content-MD5`标头. 这样就无需比较从 S3 服务器返回的 ETag 标头. + +### Using Amazon instance profiles[](#using-amazon-instance-profiles "Permalink") + +可以将 GitLab 配置为使用 IAM 角色来设置[Amazon 实例配置文件](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html) ,而不是在对象存储配置中提供 AWS 访问和秘密密钥. 使用此功能时,每次访问 S3 存储桶时,GitLab 都会获取临时凭证,因此配置中不需要硬编码的值. + +#### Encrypted S3 buckets[](#encrypted-s3-buckets "Permalink") + +版本历史 + +* 在[GitLab 13.1](https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/466)中仅针对实例配置文件引入. +* 使用[整合对象存储配置](#consolidated-object-storage-configuration)时,在[GitLab 13.2 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34460)引入了用于静态证书的功能. + +使用实例概要文件或统一对象配置进行配置时,GitLab Workhorse 可以将文件正确上载到[默认情况下启用 SSE-S3 或 SSE-KMS 加密的](https://docs.aws.amazon.com/kms/latest/developerguide/services-s3.html) S3 存储桶. 请注意, [尚不支持](https://gitlab.com/gitlab-org/gitlab/-/issues/226006)客户主密钥(CMK)和 SSE-C 加密, [因为这需要向 GitLab 配置提供密钥](https://gitlab.com/gitlab-org/gitlab/-/issues/226006) . + +##### Disabling the feature[](#disabling-the-feature "Permalink") + +当[`use_iam_profile`配置选项](#iam-permissions)设置为`true`时,默认情况下启用 Workhorse S3 客户端. + +可以使用`:use_workhorse_s3_client`功能标记禁用该功能. 要禁用该功能,请要求具有[Rails 控制台访问权限](feature_flags.html#how-to-enable-and-disable-features-behind-flags)的 GitLab 管理员运行以下命令: + +``` +Feature.disable(:use_workhorse_s3_client) +``` + +#### IAM Permissions[](#iam-permissions "Permalink") + +设置实例配置文件: + +1. 创建具有必要权限的 Amazon Identity Access and Management(IAM)角色. 以下示例是名为`test-bucket`的 S3 存储桶的角色: + + ``` + { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:AbortMultipartUpload", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::test-bucket/*" } ] } + ``` + +2. [将此角色附加](https://aws.amazon.com/premiumsupport/knowledge-center/attach-replace-ec2-instance-profile/)到托管您的 GitLab 实例的 EC2 实例. +3. 通过`use_iam_profile`配置选项配置 GitLab 以使用它. \ No newline at end of file diff --git a/_book/docs/476.md b/_book/docs/476.md new file mode 100644 index 0000000000000000000000000000000000000000..67b4b03c31ea541e7d196661d8b3f5ba04b346d6 --- /dev/null +++ b/_book/docs/476.md @@ -0,0 +1,17 @@ +# Performing Operations in GitLab + +> 原文:[https://docs.gitlab.com/ee/administration/operations/](https://docs.gitlab.com/ee/administration/operations/) + +# Performing Operations in GitLab[](#performing-operations-in-gitlab "Permalink") + +保持您的 GitLab 实例正常运行. + +* [清理 Redis 会话](cleaning_up_redis_sessions.html) :在 GitLab 7.3 之前,用户会话不会自动从 Redis 过期. 如果从 GitLab 7.3 之前开始就一直在运行大型的 GitLab 服务器(成千上万的用户),我们建议在升级到 GitLab 7.3 之后清理陈旧的会话以压缩 Redis 数据库. +* [移动存储库](moving_repositories.html) :将 GitLab 管理的所有存储[库](moving_repositories.html)移动到另一个文件系统或另一个服务器. +* [Sidekiq MemoryKiller](sidekiq_memory_killer.html) :配置 Sidekiq MemoryKiller 以重新启动 Sidekiq. +* [多个 Sidekiq 进程](extra_sidekiq_processes.html) :配置多个 Sidekiq 进程以确保某些队列始终具有专用的工作程序,而不管需要处理的作业数量如何. +* [美洲狮](puma.html) :了解美洲狮和美洲狮杀手. +* [独角兽](unicorn.html) :了解独角兽和独角兽工人杀手. +* [通过对 GitLab 数据库进行快速的索引查找来授权 SSH 用户](fast_ssh_key_lookup.html) ,和/或通过[完全放弃 SSH 证书而完全放弃存储在 GitLab 上的用户 SSH 密钥](ssh_certificates.html) ,可以加快 SSH 操作. +* [文件系统性能基准测试](filesystem_benchmarking.html) :文件系统性能可能会对 GitLab 性能产生重大影响,尤其是对于读取或写入 Git 存储库的操作. 这些信息将有助于根据已知的好坏系统对基准文件系统的性能进行基准测试. +* [ChatOps 脚本](https://gitlab.com/gitlab-com/chatops) :GitLab.com 基础架构团队使用此存储库来存储常见的 ChatOps 脚本,以用于对 GitLab.com 的生产实例进行故障排除和维护. 这些脚本可能对各种规模的 GitLab 实例的管理员有用. \ No newline at end of file diff --git a/_book/docs/477.md b/_book/docs/477.md new file mode 100644 index 0000000000000000000000000000000000000000..49dab05071ab70feff32c062514d55d8c9d1c9c7 --- /dev/null +++ b/_book/docs/477.md @@ -0,0 +1,42 @@ +# Cleaning up stale Redis sessions + +> 原文:[https://docs.gitlab.com/ee/administration/operations/cleaning_up_redis_sessions.html](https://docs.gitlab.com/ee/administration/operations/cleaning_up_redis_sessions.html) + +# Cleaning up stale Redis sessions[](#cleaning-up-stale-redis-sessions "Permalink") + +从 6.2 版开始,GitLab 将 Web 用户会话存储为 Redis 中的键值对. 在 GitLab 7.3 之前,用户会话不会自动从 Redis 终止. 如果从 GitLab 7.3 之前开始就一直在运行大型的 GitLab 服务器(成千上万的用户),我们建议在升级到 GitLab 7.3 之后清理陈旧的会话以压缩 Redis 数据库. 您还可以在仍运行 GitLab 7.2 或更早版本的情况下执行清理,但是在这种情况下,清理后新的陈旧会话将再次开始建立. + +在 7.3.0 之前的 GitLab 版本中,Redis 中的会话密钥是 16 字节的十六进制值,例如'976aa289e2189b17d7ef525a6702ace9'. 从 GitLab 7.3.0 开始,键的前缀为`session:gitlab:`因此它们看起来像`session:gitlab:976aa289e2189b17d7ef525a6702ace9` . 下面我们描述如何删除旧格式的密钥. + +**注意:**如果您使用了" [配置文件文档"中](https://gitlab.com/gitlab-org/gitlab/blob/master/config/README.md)概述的高级 Redis 设置,则必须根据您的配置设置修改以下说明. + +首先,我们定义具有适当 Redis 连接详细信息的 shell 函数. + +``` +rcli() { + # This example works for Omnibus installations of GitLab 7.3 or newer. For an + # installation from source you will have to change the socket path and the + # path to redis-cli. + sudo /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.shared_state.socket "$@" +} + +# test the new shell function; the response should be PONG +rcli ping +``` + +现在,我们进行搜索以查看是否有旧格式的会话密钥供我们清理. + +``` +# returns the number of old-format session keys in Redis +rcli keys '*' | grep '^[a-f0-9]\{32\}$' | wc -l +``` + +如果数字大于零,则可以使 Redis 的密钥失效. 如果数字为零,则没有任何清理内容. + +``` +# Tell Redis to expire each matched key after 600 seconds. +rcli keys '*' | grep '^[a-f0-9]\{32\}$' | awk '{ print "expire", $0, 600 }' | rcli +# This will print '(integer) 1' for each key that gets expired. +``` + +在接下来的 15 分钟内(10 分钟的到期时间加上 5 分钟的 Redis 后台保存间隔),您的 Redis 数据库将被压缩. 如果您仍在使用 GitLab 7.2,则在 10 分钟的有效期内未在 GitLab 中四处点击的用户将退出 GitLab. \ No newline at end of file diff --git a/_book/docs/478.md b/_book/docs/478.md new file mode 100644 index 0000000000000000000000000000000000000000..acadc967af9c393462fe87c3e9ef1dfdb9a9e14f --- /dev/null +++ b/_book/docs/478.md @@ -0,0 +1,172 @@ +# Fast lookup of authorized SSH keys in the database + +> 原文:[https://docs.gitlab.com/ee/administration/operations/fast_ssh_key_lookup.html](https://docs.gitlab.com/ee/administration/operations/fast_ssh_key_lookup.html) + +* [Fast lookup is required for Geo](#fast-lookup-is-required-for-geo-premium) +* [Setting up fast lookup via GitLab Shell](#setting-up-fast-lookup-via-gitlab-shell) +* [How to go back to using the `authorized_keys` file](#how-to-go-back-to-using-the-authorized_keys-file) +* [Compiling a custom version of OpenSSH for CentOS 6](#compiling-a-custom-version-of-openssh-for-centos-6) +* [SELinux support and limitations](#selinux-support-and-limitations) + +# Fast lookup of authorized SSH keys in the database[](#fast-lookup-of-authorized-ssh-keys-in-the-database "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 9.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/1631) . +* [在](https://gitlab.com/gitlab-org/gitlab/-/issues/3953) GitLab 社区版 10.4 中[可用](https://gitlab.com/gitlab-org/gitlab/-/issues/3953) . + +**注意:**本文档介绍了`authorized_keys`文件的替代品. 对于普通(非部署密钥)用户,请考虑使用[SSH 证书](ssh_certificates.html) . 它们甚至更快,但不是临时替代品. + +随着用户数量的增加,常规的 SSH 操作变得缓慢,这是因为 OpenSSH 通过线性搜索来搜索授权用户的密钥. 在最坏的情况下,例如,当用户无权访问 GitLab 时,OpenSSH 将扫描整个文件以搜索密钥. 这会花费大量时间和磁盘 I / O,这将延迟用户尝试推送或拉到存储库的时间. 更糟糕的是,如果用户频繁添加或删除密钥,则操作系统可能无法缓存`authorized_keys`文件,这将导致磁盘被重复访问. + +GitLab Shell 通过提供一种通过 GitLab 数据库中的快速索引查找来授权 SSH 用户的方法来解决此问题. 本页介绍如何启用快速查找授权的 SSH 密钥. + +> **警告:**由于`AuthorizedKeysCommand`必须能够接受指纹,因此需要 OpenSSH 6.9+版本. 这些说明将中断使用较旧版本的 OpenSSH 的安装,例如截至 2017 年 9 月的 CentOS 6 附带的安装.如果要将此功能用于 CentOS 6,请遵循[有关如何构建和安装自定义 OpenSSH 软件包的说明](#compiling-a-custom-version-of-openssh-for-centos-6) . + +## Fast lookup is required for Geo[](#fast-lookup-is-required-for-geo-premium "Permalink") + +默认情况下,GitLab 管理一个`authorized_keys`文件,其中包含允许访问 GitLab 的用户的所有公共 SSH 密钥. 但是,为了维护单个事实来源,需要将[Geo](../geo/replication/index.html)配置为通过数据库查找执行 SSH 指纹查找. + +作为[设置 Geo 的](../geo/replication/index.html#setup-instructions)一部分,您将需要对主节点和辅助节点都遵循以下概述的步骤,但是请注意,只需在主节点上取消选中`Write to "authorized keys" file`复选框,因为它将被选中.如果数据库复制正在工作,则会自动在辅助服务器上反映出来. + +## Setting up fast lookup via GitLab Shell[](#setting-up-fast-lookup-via-gitlab-shell "Permalink") + +GitLab Shell 提供了一种通过对 GitLab 数据库进行快速索引查找来授权 SSH 用户的方法. GitLab Shell 使用 SSH 密钥的指纹来检查用户是否有权访问 GitLab. + +将以下内容添加到您的`sshd_config`文件中. 通常位于`/etc/ssh/sshd_config` ,但如果使用 Omnibus Docker,它将为`/assets/sshd_config` : + +``` +Match User git # Apply the AuthorizedKeysCommands to the git user only + AuthorizedKeysCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-keys-check git %u %k + AuthorizedKeysCommandUser git +Match all # End match, settings apply to all users again +``` + +重新加载 OpenSSH: + +``` +# Debian or Ubuntu installations +sudo service ssh reload + +# CentOS installations +sudo service sshd reload +``` + +通过注释掉您在`authorized_keys`中的用户密钥(以`#`开头以对其进行注释),并尝试拉出存储库来确认 SSH 是否正常工作. + +A successful pull would mean that GitLab was able to find the key in the database, since it is not present in the file anymore. + +**注意:**对于 Omnibus Docker,默认情况下在 GitLab 11.11 及更高版本中设置了`AuthorizedKeysCommand` .**注意:**对于从源安装,该命令位于`/home/git/gitlab-shell/bin/gitlab-shell-authorized-keys-check`是否遵循[从源安装的](../../install/installation.html#install-gitlab-shell)说明. 您可能要考虑在其他地方创建包装脚本,因为此命令需要由`root`拥有,而不能由 group 或其他用户写入. 您也可以考虑根据需要更改此命令的所有权,但这可能需要在`gitlab-shell`升级期间临时更改所有权.**注意:**在确认 SSH 可以正常工作之前,请不要禁用写操作,因为该文件很快就会过时. + +In the case of lookup failures (which are common), the `authorized_keys` file will still be scanned. So Git SSH performance will still be slow for many users as long as a large file exists. + +您可以通过取消选中 GitLab 安装的`Write to "authorized_keys" file` **管理区域">"设置">"网络">"性能优化** `Write to "authorized_keys" file`中的`Write to "authorized_keys" file`来禁用对`authorized_keys`文件的更多写入. + +[![Write to authorized keys setting](img/f9144e03cf945bcf549c131e2816298f.png)](img/write_to_authorized_keys_setting.png) + +再次,通过在 UI 中删除用户的 SSH 密钥,添加一个新的 SSH 密钥,然后尝试提取存储库来确认 SSH 是否正常工作. + +然后,您可以备份和删除您的`authorized_keys`文件以获得最佳性能. 当前用户的密钥已经存在于数据库中,因此无需迁移或要求用户重新添加其密钥. + +## How to go back to using the `authorized_keys` file[](#how-to-go-back-to-using-the-authorized_keys-file "Permalink") + +这是一个简短的概述. 请参阅以上说明以获取更多上下文. + +1. [Rebuild the `authorized_keys` file](../raketasks/maintenance.html#rebuild-authorized_keys-file) +2. 启用对"应用程序设置"中的`authorized_keys`文件的写入 +3. 如果使用的是 Omnibus Docker,请从`/etc/ssh/sshd_config`或`/assets/sshd_config`删除`AuthorizedKeysCommand`行. +4. Reload `sshd`: `sudo service sshd reload` +5. 删除`/opt/gitlab-shell/authorized_keys`文件 + +## Compiling a custom version of OpenSSH for CentOS 6[](#compiling-a-custom-version-of-openssh-for-centos-6 "Permalink") + +对于 Ubuntu 16.04 用户而言,无需构建自定义版本的 OpenSSH,因为 Ubuntu 16.04 随 OpenSSH 7.2 一起提供. + +CentOS 7.4 用户也不需要,因为该版本随 OpenSSH 7.4 一起提供. 如果您使用的是 CentOS 7.0-7.3,我们强烈建议您升级到 CentOS 7.4,而不要遵循此过程. 这应该和运行`yum update`一样简单. + +CentOS 6 用户必须构建自己的 OpenSSH 软件包才能通过数据库启用 SSH 查找. 以下说明可用于构建 OpenSSH 7.5: + +1. 首先,下载软件包并安装所需的软件包: + + ``` + sudo su - + cd /tmp + curl --remote-name https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-7.5p1.tar.gz + tar xzvf openssh-7.5p1.tar.gz + yum install rpm-build gcc make wget openssl-devel krb5-devel pam-devel libX11-devel xmkmf libXt-devel + ``` + +2. 通过将文件复制到正确的位置来准备构建: + + ``` + mkdir -p /root/rpmbuild/{SOURCES,SPECS} + cp ./openssh-7.5p1/contrib/redhat/openssh.spec /root/rpmbuild/SPECS/ + cp openssh-7.5p1.tar.gz /root/rpmbuild/SOURCES/ + cd /root/rpmbuild/SPECS + ``` + +3. 接下来,正确设置规格设置: + + ``` + sed -i -e "s/%define no_gnome_askpass 0/%define no_gnome_askpass 1/g" openssh.spec + sed -i -e "s/%define no_x11_askpass 0/%define no_x11_askpass 1/g" openssh.spec + sed -i -e "s/BuildPreReq/BuildRequires/g" openssh.spec + ``` + +4. 建立 RPM: + + ``` + rpmbuild -bb openssh.spec + ``` + +5. 确保已构建 RPM: + + ``` + ls -al /root/rpmbuild/RPMS/x86_64/ + ``` + + 您应该看到以下内容: + + ``` + total 1324 + drwxr-xr-x. 2 root root 4096 Jun 20 19:37 . + drwxr-xr-x. 3 root root 19 Jun 20 19:37 .. + -rw-r--r--. 1 root root 470828 Jun 20 19:37 openssh-7.5p1-1.x86_64.rpm + -rw-r--r--. 1 root root 490716 Jun 20 19:37 openssh-clients-7.5p1-1.x86_64.rpm + -rw-r--r--. 1 root root 17020 Jun 20 19:37 openssh-debuginfo-7.5p1-1.x86_64.rpm + -rw-r--r--. 1 root root 367516 Jun 20 19:37 openssh-server-7.5p1-1.x86_64.rpm + ``` + +6. 安装软件包. OpenSSH 软件包将用其自己的版本替换`/etc/pam.d/sshd` ,这可能会阻止用户登录,因此请确保在安装后备份并还原了该文件: + + ``` + timestamp=$(date +%s) + cp /etc/pam.d/sshd pam-ssh-conf-$timestamp + rpm -Uvh /root/rpmbuild/RPMS/x86_64/*.rpm + yes | cp pam-ssh-conf-$timestamp /etc/pam.d/sshd + ``` + +7. 验证安装的版本. 在另一个窗口中,尝试登录到服务器: + + ``` + ssh -v + ``` + + 您应该看到以下一行:" debug1:远程协议版本 2.0,远程软件版本 OpenSSH_7.5" + + 如果没有,则可能需要重新启动`sshd` (例如`systemctl restart sshd.service` ). + +8. *重要!* 退出之前,请打开与服务器的新 SSH 会话,以确保一切正常! 如果您需要降级,只需安装较旧的软件包即可: + + ``` + # Only run this if you run into a problem logging in + yum downgrade openssh-server openssh openssh-clients + ``` + +## SELinux support and limitations[](#selinux-support-and-limitations "Permalink") + +在 GitLab 10.5 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/2855) . + +GitLab 支持[SELinux 的](https://en.wikipedia.org/wiki/Security-Enhanced_Linux) `authorized_keys`数据库查询. + +由于 SELinux 策略是静态的,因此 GitLab 目前不支持更改内部 Unicorn 端口的功能. 管理员必须为环境创建一个特殊的`.te`文件,因为它不是动态生成的. \ No newline at end of file diff --git a/_book/docs/479.md b/_book/docs/479.md new file mode 100644 index 0000000000000000000000000000000000000000..f9439a95d94965a8fe8d15eb64f32733f12b7d8e --- /dev/null +++ b/_book/docs/479.md @@ -0,0 +1,102 @@ +# Filesystem Performance Benchmarking + +> 原文:[https://docs.gitlab.com/ee/administration/operations/filesystem_benchmarking.html](https://docs.gitlab.com/ee/administration/operations/filesystem_benchmarking.html) + +* [Executing benchmarks](#executing-benchmarks) + * [Benchmarking with `fio`](#benchmarking-with-fio) + * [Simple benchmarking](#simple-benchmarking) + +# Filesystem Performance Benchmarking[](#filesystem-performance-benchmarking "Permalink") + +Filesystem performance has a big impact on overall GitLab performance, especially for actions that read or write to Git repositories. This information will help benchmark filesystem performance against known good and bad real-world systems. + +通常,在谈论文件系统性能时,最大的顾虑是网络文件系统(NFS). 但是,即使某些本地磁盘也可能具有缓慢的 I / O. 此页面上的信息可用于两种情况. + +## Executing benchmarks[](#executing-benchmarks "Permalink") + +### Benchmarking with `fio`[](#benchmarking-with-fio "Permalink") + +我们建议使用[Fio](https://fio.readthedocs.io/en/latest/fio_doc.html)测试 I / O 性能. 该测试应该在 NFS 服务器和与 NFS 服务器通信的应用程序节点上都运行. + +安装: + +* 在 Ubuntu 上: `apt install fio` . +* 在`yum`管理的环境中: `yum install fio` . + +然后运行以下命令: + +``` +fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=/path/to/git-data/testfile --bs=4k --iodepth=64 --size=4G --readwrite=randrw --rwmixread=75 +``` + +这将在`/path/to/git-data/testfile`创建一个 4GB 的文件. 它使用文件中的 75%/ 25%的拆分来执行 4KB 读取和写入,一次运行 64 个操作. 测试完成后,请确保删除文件. + +输出将根据所安装的`fio`版本而有所不同. 以下是网络固态驱动器(SSD)上`fio` v2.2.10 的输出示例: + +``` +test: (g=0): rw=randrw, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=64 + fio-2.2.10 + Starting 1 process + test: Laying out IO file(s) (1 file(s) / 1024MB) + Jobs: 1 (f=1): [m(1)] [100.0% done] [131.4MB/44868KB/0KB /s] [33.7K/11.3K/0 iops] [eta 00m:00s] + test: (groupid=0, jobs=1): err= 0: pid=10287: Sat Feb 2 17:40:10 2019 + read : io=784996KB, bw=133662KB/s, iops=33415, runt= 5873msec + write: io=263580KB, bw=44880KB/s, iops=11219, runt= 5873msec + cpu : usr=6.56%, sys=23.11%, ctx=266267, majf=0, minf=8 + IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0% + submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% + complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0% + issued : total=r=196249/w=65895/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0 + latency : target=0, window=0, percentile=100.00%, depth=64 + + Run status group 0 (all jobs): + READ: io=784996KB, aggrb=133661KB/s, minb=133661KB/s, maxb=133661KB/s, mint=5873msec, maxt=5873msec + WRITE: io=263580KB, aggrb=44879KB/s, minb=44879KB/s, maxb=44879KB/s, mint=5873msec, maxt=5873msec +``` + +注意此输出中的`iops`值. 在此示例中,SSD 每秒执行 33,415 次读操作和每秒 11,219 次写操作. 旋转磁盘可能每秒产生 2,000 和 700 的读取和写入操作. + +### Simple benchmarking[](#simple-benchmarking "Permalink") + +**注意:**此测试是幼稚的,但如果系统上没有`fio`可能有用. 在此测试中可能会收到不错的结果,但由于读取速度和其他各种因素,性能仍然很差. + +以下单行命令为文件系统的读写性能提供了快速基准. 这会将 1,000 个小文件写入执行该文件的目录,然后读取相同的 1,000 个文件. + +1. 更改为适当的[存储库存储路径](../repository_storage_paths.html)的根目录. +2. 为测试创建一个临时目录,以便以后轻松删除文件: + + ``` + mkdir test; cd test + ``` + +3. 运行命令: + + ``` + time for i in {0..1000}; do echo 'test' > "test${i}.txt"; done + ``` + +4. 要测试读取性能,请运行以下命令: + + ``` + time for i in {0..1000}; do cat "test${i}.txt" > /dev/null; done + ``` + +5. 删除测试文件: + +``` + cd ../; rm -rf test +``` + +`time for ...`命令的`time for ...`输出将类似于以下内容. 重要指标是`real` . + +``` +$ time for i in {0..1000}; do echo 'test' > "test${i}.txt"; done real 0m0.116s +user 0m0.025s +sys 0m0.091s + +$ time for i in {0..1000}; do cat "test${i}.txt" > /dev/null; done real 0m3.118s +user 0m1.267s +sys 0m1.663s +``` + +根据与多个客户的经验,此任务应花费 10 秒以表明文件系统性能良好. \ No newline at end of file diff --git a/_book/docs/480.md b/_book/docs/480.md new file mode 100644 index 0000000000000000000000000000000000000000..fd99b14e71acd04f42cf820cd7f3a5d3788219f5 --- /dev/null +++ b/_book/docs/480.md @@ -0,0 +1,145 @@ +# Moving repositories managed by GitLab + +> 原文:[https://docs.gitlab.com/ee/administration/operations/moving_repositories.html](https://docs.gitlab.com/ee/administration/operations/moving_repositories.html) + +* [Target directory is empty: use a tar pipe](#target-directory-is-empty-use-a-tar-pipe) + * [Tar pipe to another server](#tar-pipe-to-another-server) +* [The target directory contains an outdated copy of the repositories: use rsync](#the-target-directory-contains-an-outdated-copy-of-the-repositories-use-rsync) + * [Single rsync to another server](#single-rsync-to-another-server) +* [Thousands of Git repositories: use one rsync per repository](#thousands-of-git-repositories-use-one-rsync-per-repository) + * [Parallel rsync for all repositories known to GitLab](#parallel-rsync-for-all-repositories-known-to-gitlab) + * [Parallel rsync only for repositories with recent activity](#parallel-rsync-only-for-repositories-with-recent-activity) + +# Moving repositories managed by GitLab[](#moving-repositories-managed-by-gitlab "Permalink") + +有时,您需要将 GitLab 管理的所有存储库移至另一个文件系统或另一个服务器. 在本文档中,我们将介绍将所有存储库从`/var/opt/gitlab/git-data/repositories` `/mnt/gitlab/repositories`到`/mnt/gitlab/repositories` . + +我们将研究三种情况:目标目录为空,目标目录包含版本库的过时副本,以及如何处理数千个版本库. + +**我们列出的每种方法都可以/将覆盖目标目录`/mnt/gitlab/repositories` . 不要混淆源和目标.** + +## Target directory is empty: use a tar pipe[](#target-directory-is-empty-use-a-tar-pipe "Permalink") + +如果目标目录`/mnt/gitlab/repositories`为空,则最简单的操作是使用 tar 管道. 此方法的开销很低,并且 tar 几乎总是已安装在系统上. 但是,无法恢复中断的 tar 管道:如果发生这种情况,则必须再次复制所有数据. + +``` +sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\ + tar -C /mnt/gitlab/repositories -xf -' +``` + +如果要查看进度,请用`-xvf`替换`-xf` . + +### Tar pipe to another server[](#tar-pipe-to-another-server "Permalink") + +You can also use a tar pipe to copy data to another server. If your `git` user has SSH access to the new server as `git@newserver`, you can pipe the data through SSH. + +``` +sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\ + ssh git@newserver tar -C /mnt/gitlab/repositories -xf -' +``` + +如果您想在数据通过网络之前进行压缩(这将花费您的 CPU 周期),则可以将`ssh`替换为`ssh -C` . + +## The target directory contains an outdated copy of the repositories: use rsync[](#the-target-directory-contains-an-outdated-copy-of-the-repositories-use-rsync "Permalink") + +如果目标目录已经包含部分/过时的存储库副本,那么再次用 tar 复制所有数据可能会很浪费. 在这种情况下,最好使用 rsync. 该实用程序已经安装在系统上,也可以通过 apt,yum 等轻松安装. + +``` +sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \ + /mnt/gitlab/repositories' +``` + +`/.` 在上面的命令中非常重要,没有它,您很容易在目标目录中获得错误的目录结构. 如果要查看进度,请用`-av`替换`-a` . + +### Single rsync to another server[](#single-rsync-to-another-server "Permalink") + +如果源系统上的`git`用户对目标服务器具有 SSH 访问权限,则可以使用 rsync 通过网络发送存储库. + +``` +sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \ + git@newserver:/mnt/gitlab/repositories' +``` + +## Thousands of Git repositories: use one rsync per repository[](#thousands-of-git-repositories-use-one-rsync-per-repository "Permalink") + +每次启动 rsync 作业时,它都必须检查源目录中的所有文件,目标目录中的所有文件,然后确定要复制或不复制哪些文件. 如果源目录或目标目录中包含许多内容,则 rsync 的启动阶段可能会成为您的 GitLab 服务器的负担. 在这种情况下,可以通过将 rsync 的工作分成较小的部分来使 rsync 的工作变得更轻松,并一次同步一个存储库. + +除了 rsync 之外,我们还将使用[GNU Parallel](http://www.gnu.org/software/parallel/) . 该实用程序未包含在 GitLab 中,因此您需要使用 apt 或 yum 自己安装. 还要注意,我们在下面使用的 GitLab 脚本是在 GitLab 8.1 中添加的. + +**此过程不会清理源位置不再存在的目标位置的存储库.** 如果您开始在`/mnt/gitlab/repositories`使用 GitLab 实例,则需要在切换到新的存储库存储目录后运行`gitlab-rake gitlab:cleanup:repos` . + +### Parallel rsync for all repositories known to GitLab[](#parallel-rsync-for-all-repositories-known-to-gitlab "Permalink") + +这将一次将存储库与 10 个 rsync 进程同步. 我们会跟踪进度,以便在必要时可以重新开始传输. + +首先,我们创建一个新目录,由`git`拥有,以保存传输日志. 在开始传输过程之前,我们假定目录为空,并且我们是唯一在其中写入文件的目录. + +``` +# Omnibus +sudo mkdir /var/opt/gitlab/transfer-logs +sudo chown git:git /var/opt/gitlab/transfer-logs + +# Source +sudo -u git -H mkdir /home/git/transfer-logs +``` + +我们使用要复制的目录列表为该过程添加种子. + +``` +# Omnibus +sudo -u git sh -c 'gitlab-rake gitlab:list_repos > /var/opt/gitlab/transfer-logs/all-repos-$(date +%s).txt' + +# Source +cd /home/git/gitlab +sudo -u git -H sh -c 'bundle exec rake gitlab:list_repos > /home/git/transfer-logs/all-repos-$(date +%s).txt' +``` + +现在我们可以开始传输了. 下面的命令是幂等的,并且 GNU Parallel 完成的作业数应收敛为零. 如果不是这样,则`all-repos-1234.txt`列出的某些存储库在被复制之前可能已被删除/重命名. + +``` +# Omnibus +sudo -u git sh -c ' +cat /var/opt/gitlab/transfer-logs/* | sort | uniq -u |\ + /usr/bin/env JOBS=10 \ + /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \ + /var/opt/gitlab/transfer-logs/success-$(date +%s).log \ + /var/opt/gitlab/git-data/repositories \ + /mnt/gitlab/repositories +' + +# Source +cd /home/git/gitlab +sudo -u git -H sh -c ' +cat /home/git/transfer-logs/* | sort | uniq -u |\ + /usr/bin/env JOBS=10 \ + bin/parallel-rsync-repos \ + /home/git/transfer-logs/success-$(date +%s).log \ + /home/git/repositories \ + /mnt/gitlab/repositories +` +``` + +### Parallel rsync only for repositories with recent activity[](#parallel-rsync-only-for-repositories-with-recent-activity "Permalink") + +假设您已经完成了一次在 2015 年 10 月 1 日 12:00 UTC 之后开始的同步. 然后,您可能只想同步*在*那*之后*通过 GitLab 更改的存储库. 您可以使用`SINCE`变量告诉`rake gitlab:list_repos`仅打印具有最近活动的存储库. + +``` +# Omnibus +sudo gitlab-rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\ + sudo -u git \ + /usr/bin/env JOBS=10 \ + /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \ + success-$(date +%s).log \ + /var/opt/gitlab/git-data/repositories \ + /mnt/gitlab/repositories + +# Source +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\ + sudo -u git -H \ + /usr/bin/env JOBS=10 \ + bin/parallel-rsync-repos \ + success-$(date +%s).log \ + /home/git/repositories \ + /mnt/gitlab/repositories +``` \ No newline at end of file diff --git a/_book/docs/481.md b/_book/docs/481.md new file mode 100644 index 0000000000000000000000000000000000000000..2dccfd20a46ffe2e879f82a6518dcceb891e4acc --- /dev/null +++ b/_book/docs/481.md @@ -0,0 +1,365 @@ +# Run multiple Sidekiq processes + +> 原文:[https://docs.gitlab.com/ee/administration/operations/extra_sidekiq_processes.html](https://docs.gitlab.com/ee/administration/operations/extra_sidekiq_processes.html) + +* [Available Sidekiq queues](#available-sidekiq-queues) +* [Start multiple processes](#start-multiple-processes) +* [Negate settings](#negate-settings) +* [Queue selector (experimental)](#queue-selector-experimental) + * [Available attributes](#available-attributes) + * [Available operators](#available-operators) + * [Example queries](#example-queries) + * [Disable Sidekiq cluster](#disable-sidekiq-cluster) +* [Ignore all GitHub import queues](#ignore-all-github-import-queues) +* [Number of threads](#number-of-threads) +* [Manage concurrency](#manage-concurrency) + * [When running Sidekiq cluster (default)](#when-running-sidekiq-cluster-default) + * [When running a single Sidekiq process](#when-running-a-single-sidekiq-process) +* [Modify the check interval](#modify-the-check-interval) +* [Troubleshoot using the CLI](#troubleshoot-using-the-cli) + * [Monitor the `sidekiq-cluster` command](#monitor-the-sidekiq-cluster-command) + * [PID files](#pid-files) + * [Environment](#environment) + +# Run multiple Sidekiq processes[](#run-multiple-sidekiq-processes-core-only "Permalink") + +GitLab 允许您启动多个 Sidekiq 进程. 这些过程可用于消耗一组专用队列. 这可以用来确保某些队列始终具有专用的工作程序,而不管需要处理的作业数量如何. + +**注意:**此页面中的信息仅适用于 Omnibus GitLab. + +## Available Sidekiq queues[](#available-sidekiq-queues "Permalink") + +For a list of the existing Sidekiq queues, check the following files: + +* [Queues for both GitLab Community and Enterprise Editions](https://gitlab.com/gitlab-org/gitlab/blob/master/app/workers/all_queues.yml) +* [Queues for GitLab Enterprise Editions only](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/all_queues.yml) + +以上文件中的每个条目都代表一个队列,可以在其上启动 Sidekiq 进程. + +## Start multiple processes[](#start-multiple-processes "Permalink") + +版本历史 + +* 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4006) ,使用 Sidekiq 集群启动多个进程. +* [Sidekiq 集群移至](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) GitLab 12.10 中的 GitLab [Core](https://about.gitlab.com/pricing/#self-managed) . +* [Sidekiq 集群](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4140)在 GitLab 13.0 中[成为默认设置](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4140) . + +To start multiple processes: + +1. 使用`sidekiq['queue_groups']`数组设置,指定使用`sidekiq-cluster`创建多少个进程以及它们应处理的队列. 数组中的每个项目都相当于一个附加的 Sidekiq 进程,并且每个项目中的值确定了它要处理的队列. + + 例如,以下设置创建三个 Sidekiq 过程,一到上运行`elastic_indexer` ,一到上运行`mailers` ,以及一个进程中运行的所有的队列: + + ``` + sidekiq['queue_groups'] = [ + "elastic_indexer", + "mailers", + "*" + ] + ``` + + 要让附加的 Sidekiq 进程处理多个队列,请将多个队列名称添加到其项目中,并以逗号分隔. 例如: + + ``` + sidekiq['queue_groups'] = [ + "elastic_indexer, elastic_commit_indexer", + "mailers", + "*" + ] + ``` + + [在 GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26594)和更高版本中,特殊队列名称`*`表示所有队列. 这将启动两个进程,每个进程处理所有队列: + + ``` + sidekiq['queue_groups'] = [ + "*", + "*" + ] + ``` + + `*`不能与具体的队列名称结合使用- `*, mailers`将只处理`mailers`队列. + + 当`sidekiq-cluster`仅在单个节点上运行时,请使用`*`确保在所有队列上至少运行一个进程. 这意味着一个进程将自动在将来创建的队列中拾取作业. + + 如果`sidekiq-cluster`在多个节点上运行,则还可以使用[`--negate`](#negate-settings)并列出所有已在处理的队列. + +2. 保存文件并重新配置 GitLab,以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +添加了额外的 Sidekiq 进程后,导航至 GitLab 中的**管理区域>监视>后台作业** ( `/admin/background_jobs` ). + +[![Multiple Sidekiq processes](img/705d87c5c620f8ade251682fceb074e3.png)](img/sidekiq-cluster.png) + +## Negate settings[](#negate-settings "Permalink") + +若要使其他 Sidekiq 进程在您列出的队列**之外**的每个队列上工作: + +1. 在按照步骤[启动额外的流程之后](#start-multiple-processes) ,请编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + sidekiq['negate'] = true + ``` + +2. 保存文件并重新配置 GitLab,以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +## Queue selector (experimental)[](#queue-selector-experimental "Permalink") + +[Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/45) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.8. + +**注意:**由于这被标记为**实验性的** ,因此随时可能更改,包括**破坏向后兼容性** . 这样我们就可以对 GitLab.com 部署所需的更改做出反应. 我们存在一个跟踪问题,希望从此功能中[删除实验性名称](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/147) ; 如果您有兴趣在自己的部署中使用它,请在此处发表评论. + +除了按名称选择队列之外,如上所述, `experimental_queue_selector`选项还允许使用以下组件以更通用的方式选择队列组: + +* 可以选择的属性. +* 用于构造查询的运算符. + +### Available attributes[](#available-attributes "Permalink") + +* 在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/261) , `tags` . + +从[所有可用属性](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml)的[列表中](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml) , `experimental_queue_selector`允许通过以下属性选择队列: + +* `feature_category`队列所属的[GitLab 功能类别](https://about.gitlab.com/direction/maturity/#category-maturity) . 例如, `merge`队列属于`source_code_management`类别. +* `has_external_dependencies`队列是否连接到外部服务. 例如,所有进口商都将此设置为`true` . +* `urgency` -快速运行此队列的重要性. 可以`high` , `low`或`throttled` . 例如, `authorized_projects`队列用于刷新用户权限,并且紧急度很高. +* `name` -队列名. 其他属性通常更有用,因为它们更通用,但这在需要选择特定队列的情况下可用. +* `resource_boundary`如果队列受`cpu` , `memory`或`unknown`绑定. 例如, `project_export`队列受内存限制,因为它必须先将数据加载到内存中,然后再保存以进行导出. +* `tags` -队列的短暂注释. 预计这些版本会在发行版本之间频繁更改,并且可能会完全删除. + +`has_external_dependencies`是布尔值属性:只有确切的字符串`true`才被视为 true,其他所有内容都被视为 false. + +`tags`是一个集合,这意味着`=`检查相交的集合,而`!=`检查不相交的集合. 例如, `tags=a,b`选择具有标签`a` , `b`或两者都有的队列. `tags!=a,b`选择没有这些标签的队列. + +### Available operators[](#available-operators "Permalink") + +`experimental_queue_selector`支持以下运算符,从最高优先级到最低优先级列出: + +* `|` -逻辑或运算符. 例如, `query_a|query_b` (此处的`query_a`和`query_b`是由其他运算符组成的查询)将包括与任一查询匹配的队列. +* `&` -逻辑 AND 运算符. 例如, `query_a&query_b` (此处的`query_a`和`query_b`是由其他运算符组成的查询)将仅包括与两个查询均匹配的队列. +* `!=` -NOT IN 运算符. 例如, `feature_category!=issue_tracking`将所有队列排除在`issue_tracking`功能类别之外. +* `=` -IN 运算符. 例如, `resource_boundary=cpu`包括所有受 CPU 约束的队列. +* `,` -串联集合运算符. 例如, `feature_category=continuous_integration,pages`包含来自`continuous_integration`类别或`pages`类别的所有队列. 使用 OR 运算符也可以使用此示例,但是它具有更高的简洁性,并且具有较低的优先级. + +此语法的运算符优先级是固定的:不可能使 AND 的优先级高于 OR. + +[In GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26594) and later, as with the standard queue group syntax above, a single `*` as the entire queue group selects all queues. + +### Example queries[](#example-queries "Permalink") + +In `/etc/gitlab/gitlab.rb`: + +``` +sidekiq['enable'] = true +sidekiq['experimental_queue_selector'] = true +sidekiq['queue_groups'] = [ + # Run all non-CPU-bound queues that are high urgency + 'resource_boundary!=cpu&urgency=high', + # Run all continuous integration and pages queues that are not high urgency + 'feature_category=continuous_integration,pages&urgency!=high', + # Run all queues + '*' +] +``` + +### Disable Sidekiq cluster[](#disable-sidekiq-cluster "Permalink") + +**警告:**在 GitLab 14.0 中, [计划](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/240)将 Sidekiq 群集作为启动 Sidekiq 的唯一方法. + +默认情况下,Sidekiq 服务将运行`sidekiq-cluster` . 若要禁用此行为,请将以下内容添加到 Sidekiq 配置中: + +``` +sidekiq['enable'] = true +sidekiq['cluster'] = false +``` + +所有上述提及的`sidekiq`配置选项均可用. 默认情况下,它们的配置如下: + +``` +sidekiq['experimental_queue_selector'] = false +sidekiq['interval'] = nil +sidekiq['max_concurrency'] = 50 +sidekiq['min_concurrency'] = nil +sidekiq['negate'] = false +sidekiq['queue_groups'] = ['*'] +sidekiq['shutdown_timeout'] = 25 +``` + +如果您决定如上所述配置集群,则必须禁用`sidekiq_cluster` . + +禁用`sidekiq_cluster` ,必须将`sidekiq_cluster`的配置复制到`sidekiq` . 任何配置成用于`sidekiq_cluster`将被覆盖由用于选项`sidekiq`设定时`sidekiq['cluster'] = true` . + +使用此功能时,名为`sidekiq`的服务现在将在运行`sidekiq-cluster` . + +将遵守为 Sidekiq 配置的[并发](#manage-concurrency)和其他选项. + +默认情况下, `sidekiq-cluster` `/var/log/gitlab/sidekiq`像常规的 Sidekiq 日志一样进入`/var/log/gitlab/sidekiq` . + +## Ignore all GitHub import queues[](#ignore-all-github-import-queues "Permalink") + +[从 GitHub 导入时](../../user/project/import/github.html) ,Sidekiq 可能会使用其所有资源来执行那些操作. 要设置一个单独的`sidekiq-cluster`进程以忽略所有与 GitHub 导入相关的队列: + +1. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + sidekiq['enable'] = true + sidekiq['negate'] = true + sidekiq['queue_groups'] = [ + "github_import_advance_stage", + "github_importer:github_import_import_diff_note", + "github_importer:github_import_import_issue", + "github_importer:github_import_import_note", + "github_importer:github_import_import_lfs_object", + "github_importer:github_import_import_pull_request", + "github_importer:github_import_refresh_import_jid", + "github_importer:github_import_stage_finish_import", + "github_importer:github_import_stage_import_base_data", + "github_importer:github_import_stage_import_issues_and_diff_notes", + "github_importer:github_import_stage_import_notes", + "github_importer:github_import_stage_import_lfs_objects", + "github_importer:github_import_stage_import_pull_requests", + "github_importer:github_import_stage_import_repository" + ] + ``` + +2. 保存文件并重新配置 GitLab,以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +## Number of threads[](#number-of-threads "Permalink") + +在`sidekiq`下定义的每个进程都以等于队列数的线程数开始,再加上一个备用线程. 例如,处理`process_commit`和`post_receive`队列的进程将总共使用三个线程. + +## Manage concurrency[](#manage-concurrency "Permalink") + +设置最大并发数时,请记住,这通常不应超过可用的 CPU 内核数. 以下示例中的值是任意的,不是特别的建议. + +Each thread requires a Redis connection, so adding threads may increase Redis latency and potentially cause client timeouts. See the [Sidekiq documentation about Redis](https://github.com/mperham/sidekiq/wiki/Using-Redis) for more details. + +### When running Sidekiq cluster (default)[](#when-running-sidekiq-cluster-default "Permalink") + +在 GitLab 13.0 和更高版本中,默认运行 Sidekiq 群集. + +1. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + sidekiq['min_concurrency'] = 15 + sidekiq['max_concurrency'] = 25 + ``` + +2. 保存文件并重新配置 GitLab,以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +`min_concurrency`和`max_concurrency`是独立的; 一个可以不设置另一个. 将`min_concurrency`设置为 0 将禁用该限制. + +对于每个队列组,令 N 为队列数多一. 并发因子将设置为: + +1. `N` ,如果它介于`min_concurrency`和`max_concurrency`之间. +2. `max_concurrency` ,如果`N`超过此值. +3. `min_concurrency` ,如果`N`小于此值. + +如果`min_concurrency`等于`max_concurrency` ,那么无论队列数量如何,都将使用此值. + +当`min_concurrency`大于`max_concurrency` ,它将被视为等于`max_concurrency` . + +### When running a single Sidekiq process[](#when-running-a-single-sidekiq-process "Permalink") + +在 GitLab 12.10 及更早版本中,默认运行单个 Sidekiq 进程. + +**警告:**计划在 GitLab [14.0 中](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/240)删除直接运行 Sidekiq. + +1. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + sidekiq['cluster'] = false + sidekiq['concurrency'] = 25 + ``` + +2. 保存文件并重新配置 GitLab,以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +这将设置 Sidekiq 进程的并发性(线程数). + +## Modify the check interval[](#modify-the-check-interval "Permalink") + +修改其他 Sidekiq 进程的检查间隔: + +1. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + sidekiq['interval'] = 5 + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +这告诉其他进程多久检查一次排队的作业. + +## Troubleshoot using the CLI[](#troubleshoot-using-the-cli "Permalink") + +**警告:**建议使用`/etc/gitlab/gitlab.rb`来配置 Sidekiq 进程. 如果遇到问题,应联系 GitLab 支持. 使用命令行需要您自担风险. + +为了进行调试,可以使用命令`/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster`启动额外的 Sidekiq 进程. 此命令使用以下语法获取参数: + +``` +/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster [QUEUE,QUEUE,...] [QUEUE, ...] +``` + +每个单独的参数表示一组必须由 Sidekiq 进程处理的队列. 多个队列可以通过相同的过程来处理,方法是用逗号而不是空格将它们分开. + +除了队列,还可以提供队列名称空间,以使进程自动侦听该名称空间中的所有队列,而无需显式列出所有队列名称. 有关队列名称空间的更多信息,请参见[Sidekiq 样式指南中](../../development/sidekiq_style_guide.html#queue-namespaces)的相关部分. + +例如,假设您要启动两个额外的进程:一个进程处理`process_commit`队列,另一个进程处理`post_receive`队列. 可以按以下步骤完成: + +``` +/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster process_commit post_receive +``` + +如果您想启动一个处理两个队列的进程,则可以使用以下语法: + +``` +/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster process_commit,post_receive +``` + +如果您想让一个 Sidekiq 进程处理`process_commit`和`post_receive`队列,以及一个进程来处理`gitlab_shell`队列,则可以使用以下命令: + +``` +/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster process_commit,post_receive gitlab_shell +``` + +### Monitor the `sidekiq-cluster` command[](#monitor-the-sidekiq-cluster-command "Permalink") + +一旦启动了所需数量的 Sidekiq 进程, `sidekiq-cluster`命令将不会终止. 相反,该进程将继续运行并将所有信号转发到子进程. 这使停止所有 Sidekiq 进程变得容易,因为您只需将信号发送到`sidekiq-cluster`进程即可,而不必将其发送到各个进程. + +如果`sidekiq-cluster`进程崩溃或收到`SIGKILL` ,则子进程将在几秒钟后终止. 这样可以确保您不会遇到僵尸 Sidekiq 进程. + +所有这些使监视过程变得相当容易. 只需将`sidekiq-cluster`到您选择的主管(例如 runit),就可以了. + +如果子进程死亡, `sidekiq-cluster`命令将发出信号通知所有剩余进程终止,然后终止自身. 这样就不需要`sidekiq-cluster`来重新实现复杂的过程监控/重新启动代码. 相反,您应该确保主管在必要时重新启动`sidekiq-cluster`过程. + +### PID files[](#pid-files "Permalink") + +`sidekiq-cluster`命令可以将其 PID 存储在文件中. 默认情况下,不会写入任何 PID 文件,但是可以通过将`--pidfile`选项传递给`sidekiq-cluster`来更改此文件. 例如: + +``` +/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster --pidfile /var/run/gitlab/sidekiq_cluster.pid process_commit +``` + +请记住,PID 文件将包含`sidekiq-cluster`命令的 PID,而不包含已启动的 Sidekiq 进程的 PID. + +### Environment[](#environment "Permalink") + +可以通过将`--environment`标志传递给`sidekiq-cluster`命令或将`RAILS_ENV`设置为非空值来设置 Rails 环境. 可以在`/opt/gitlab/etc/gitlab-rails/env/RAILS_ENV`找到默认值. \ No newline at end of file diff --git a/_book/docs/482.md b/_book/docs/482.md new file mode 100644 index 0000000000000000000000000000000000000000..5ded9bfde0065e6c3b36871245670dd64ef835ad --- /dev/null +++ b/_book/docs/482.md @@ -0,0 +1,47 @@ +# Sidekiq MemoryKiller + +> 原文:[https://docs.gitlab.com/ee/administration/operations/sidekiq_memory_killer.html](https://docs.gitlab.com/ee/administration/operations/sidekiq_memory_killer.html) + +* [Configuring the MemoryKiller](#configuring-the-memorykiller) + +# Sidekiq MemoryKiller[](#sidekiq-memorykiller "Permalink") + +GitLab Rails 应用程序代码遭受内存泄漏. 对于 Web 请求,可以使用[`puma-worker-killer`](https://github.com/schneems/puma_worker_killer)来解决此问题,如果超过内存限制,它将重新启动 Puma worker 进程. Sidekiq MemoryKiller 对 GitLab 用来处理后台作业的 Sidekiq 进程采用相同的方法. + +与 puma-worker-killer(自 GitLab 13.0 起默认对所有 GitLab 安装启用)不同,Sidekiq MemoryKiller 默认*仅对* Omnibus 软件包启用. 这样做的原因是,MemoryKiller 依赖于 runit 在内存引起的关闭之后重新启动 Sidekiq,并且从源头安装 GitLab 并不全部使用 runit 或等效版本. + +使用默认设置,MemoryKiller 将使 Sidekiq 重新启动的频率不超过每 15 分钟一次,并且重新启动会为传入的后台作业造成大约一分钟的延迟. + +一些后台作业依赖于长时间运行的外部流程. 为确保在重启 Sidekiq 时将它们彻底终止,每个 Sidekiq 进程应以进程组负责人的身份运行(例如,使用`chpst -P` ). 如果使用 Omnibus 或安装了`runit`的`bin/background_jobs`脚本, `runit`为您处理. + +## Configuring the MemoryKiller[](#configuring-the-memorykiller "Permalink") + +使用环境变量控制 MemoryKiller. + +* `SIDEKIQ_DAEMON_MEMORY_KILLER` :默认为 0.设置为 1 时,MemoryKiller 在*守护程序*模式下工作. 否则,MemoryKiller 将在*旧*模式下工作. + + 在*传统*模式下,MemoryKiller 在每个作业后检查 Sidekiq 进程 RSS. + + 在*守护程序*模式下,MemoryKiller 每 3 秒检查一次 Sidekiq 进程 RSS(由`SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL`定义). + +* `SIDEKIQ_MEMORY_KILLER_MAX_RSS` (KB):如果设置了此变量,并且其值大于 0,则启用 MemoryKiller. 否则,将禁用 MemoryKiller. + + `SIDEKIQ_MEMORY_KILLER_MAX_RSS`定义了 Sidekiq 进程允许的 RSS. + + 在*传统*模式下,如果 Sidekiq 进程超出允许的 RSS,则将触发不可逆的延迟正常重启. Sidekiq 的重启将在`SIDEKIQ_MEMORY_KILLER_GRACE_TIME`秒后发生. + + 在*守护程序*模式下,如果 Sidekiq 进程超出允许的 RSS 的时间超过`SIDEKIQ_MEMORY_KILLER_GRACE_TIME` ,则将触发正常重启. 如果 Sidekiq 进程在`SIDEKIQ_MEMORY_KILLER_GRACE_TIME`内低于允许的 RSS,则重新启动将被中止. + + Omnibus 软件包的默认值[在 Omnibus GitLab 存储库中设置](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/attributes/default.rb) . + +* `SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS` (KB):由*守护程序*模式使用. 如果 Sidekiq 进程 RSS(以千字节为单位)超过`SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS` ,则会立即立即正常重启 Sidekiq. + +* `SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL` :在*守护程序*模式下用于定义检查进程 RSS 的频率,默认为 3 秒. + +* `SIDEKIQ_MEMORY_KILLER_GRACE_TIME` :默认为 900 秒(15 分钟). 此变量的用法描述为`SIDEKIQ_MEMORY_KILLER_MAX_RSS`一部分. + +* `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT` :默认为 30 秒. 这定义了所有 Sidekiq 作业完成所允许的最长时间. 在此期间将不接受任何新作业,并且所有作业完成后该过程将立即退出. + + 如果作业在此期间未完成,则 MemoryKiller 将通过将`SIGTERM`发送到 Sidekiq 进程来中断所有当前正在运行的作业. + + If the process hard shutdown/restart is not performed by Sidekiq, the Sidekiq process will be forcefully terminated after `Sidekiq.options[:timeout] * 2` seconds. An external supervision mechanism (e.g. runit) must restart Sidekiq afterwards. \ No newline at end of file diff --git a/_book/docs/483.md b/_book/docs/483.md new file mode 100644 index 0000000000000000000000000000000000000000..d086535b5fa5f5ff1af11cb8c61d52c4c9d69a36 --- /dev/null +++ b/_book/docs/483.md @@ -0,0 +1,46 @@ +# Switching to Puma + +> 原文:[https://docs.gitlab.com/ee/administration/operations/puma.html](https://docs.gitlab.com/ee/administration/operations/puma.html) + +* [Why switch to Puma?](#why-switch-to-puma) +* [Configuring Puma to replace Unicorn](#configuring-puma-to-replace-unicorn) +* [Performance caveat when using Puma with Rugged](#performance-caveat-when-using-puma-with-rugged) + +# Switching to Puma[](#switching-to-puma "Permalink") + +从 GitLab 12.9 开始, [Puma](https://github.com/puma/puma)取代了[Unicorn](https://yhbt.net/unicorn/) . 作为默认的 Web 服务器. 在 GitLab 13.0 中,除非明确配置为不运行,否则以下命令将运行 Puma 而不是 Unicorn: + +* 基于软件包的多合一安装. +* 基于舵图的安装. + +## Why switch to Puma?[](#why-switch-to-puma "Permalink") + +Puma 具有多线程体系结构,与像 Unicorn 这样的多进程应用程序服务器相比,它使用的内存更少. 在 GitLab.com 上,我们发现内存消耗减少了 40%. + +大多数 Rails 应用程序请求通常都包含一定比例的 I / O 等待时间. 在 I / O 等待时间内,MRI Ruby 将释放 GVL(全局 VM 锁定)到其他线程. 因此,多线程 Puma 仍然可以处理比单个进程更多的请求. + +## Configuring Puma to replace Unicorn[](#configuring-puma-to-replace-unicorn "Permalink") + +从 GitLab 13.0 开始,Puma 是默认的应用程序服务器. 我们计划在 GitLab 14.0 中删除对 Unicorn 的支持. + +切换到 Puma 时,由于两个应用程序服务器之间的差异,Unicorn 服务器配置将*不会*自动继承. 对于基于 Omnibus 的部署,请参阅" [配置 Puma 设置"](https://docs.gitlab.com/omnibus/settings/puma.html) . 对于基于 Helm 的部署,请参阅[Webservice Chart 文档](https://docs.gitlab.com/charts/charts/gitlab/webservice/index.html) . + +此外,由于 Unicorn 和 Puma 在重新启动服务期间如何处理连接方面存在差异,因此我们强烈建议多节点部署[将其负载平衡器配置为利用就绪检查](../high_availability/load_balancer.html#readiness-check) . + +## Performance caveat when using Puma with Rugged[](#performance-caveat-when-using-puma-with-rugged "Permalink") + +对于使用 NFS 存储 Git 存储库的部署,我们允许 GitLab 使用[直接 Git 访问](../gitaly/index.html#direct-access-to-git-in-gitlab)来使用[Rugged](https://github.com/libgit2/rugged)来提高性能. + +坚固耐用的使用,将自动启用,如果直接 Git 的访问[可用](../gitaly/index.html#how-it-works) ,除非它被禁用[的功能标志](../../development/gitaly.html#legacy-rugged-code) . + +MRI Ruby 使用 GVL. 这使得 MRI Ruby 可以是多线程的,但最多只能在单个内核上运行. 由于 Rugged 可以长时间使用线程(由于 Git 访问的密集 I / O 操作),因此这可能会使可能正在处理请求的其他线程饿死. 对于在单线程模式下运行的 Unicorn 或 Puma 而言,情况并非如此,因为最多同时处理一个请求. + +我们正在积极致力于消除 Rugged 的使用. 即使没有 Rugged 的性能今天已经可以接受,但在某些情况下使用它仍然可能是有益的. + +考虑到使用多线程 Puma 运行 Rugged 的警告,以及 Gitaly 可接受的性能,如果使用 Puma 多线程(当 Puma 配置为使用多个线程运行时),我们将禁用 Rugged 的使用. + +在某些情况下,此默认行为可能不是最佳配置. 如果 Rugged 在您的部署中起着重要作用,我们建议您进行基准测试以找到最佳配置: + +* 最安全的选择是从单线程 Puma 开始. 与 Rugged 一起使用时,单线程 Puma 的工作原理与 Unicorn 相同. + +* 要对多线程 Puma 进行 Rugged 自动检测,可以使用[功能标志](../../development/gitaly.html#legacy-rugged-code) . \ No newline at end of file diff --git a/_book/docs/484.md b/_book/docs/484.md new file mode 100644 index 0000000000000000000000000000000000000000..65d31037ada3159809d0df85da4d518d842230e3 --- /dev/null +++ b/_book/docs/484.md @@ -0,0 +1,70 @@ +# Understanding Unicorn and unicorn-worker-killer + +> 原文:[https://docs.gitlab.com/ee/administration/operations/unicorn.html](https://docs.gitlab.com/ee/administration/operations/unicorn.html) + +* [Unicorn](#unicorn) + * [Tunable options](#tunable-options) +* [unicorn-worker-killer](#unicorn-worker-killer) + +# Understanding Unicorn and unicorn-worker-killer[](#understanding-unicorn-and-unicorn-worker-killer "Permalink") + +**注意:**从 GitLab 13.0 开始,Puma 是基于 GitLab 多合一软件包的安装以及 GitLab Helm 图表部署中使用的默认 Web 服务器. + +## Unicorn[](#unicorn "Permalink") + +GitLab uses [Unicorn](https://yhbt.net/unicorn/), a pre-forking Ruby web server, to handle web requests (web browsers and Git HTTP clients). Unicorn is a daemon written in Ruby and C that can load and run a Ruby on Rails application; in our case the Rails application is GitLab Community Edition or GitLab Enterprise Edition. + +Unicorn 具有多进程架构,可以更好地利用可用的 CPU 内核(进程可以在不同的内核上运行),并具有更强的容错能力(大多数故障仅隔离在一个进程中,无法完全关闭 GitLab). 启动时,Unicorn 的"主"进程使用 GitLab 应用程序代码加载一个干净的 Ruby 环境,然后生成继承此干净的初始环境的"工人". "主人"从不处理任何留给工人的请求. 操作系统网络堆栈将传入的请求排队,并在工作进程之间分配它们. + +在一个理想的世界中,主服务器将生成一个工人池,然后工人依次处理传入的 Web 请求,直到时间结束. 实际上,工作进程可能崩溃或超时:如果主服务器注意到工作时间过长,无法处理请求,它将以 SIGKILL(" kill -9")终止工作进程. 无论工作进程如何结束,主进程都将再次用新的"干净"进程替换它. Unicorn 的设计宗旨是能够替换"崩溃的"工人,而无需放弃用户的要求. + +这就是`unicorn_stderr.log`的 Unicorn worker 超时. 主过程具有下面的 PID 56227. + +``` +[2015-06-05T10:58:08.660325 #56227] ERROR -- : worker=10 PID:53009 timeout (61s > 60s), killing +[2015-06-05T10:58:08.699360 #56227] ERROR -- : reaped # worker=10 +[2015-06-05T10:58:08.708141 #62538] INFO -- : worker=10 spawned pid=62538 +[2015-06-05T10:58:08.708824 #62538] INFO -- : worker=10 ready +``` + +### Tunable options[](#tunable-options "Permalink") + +Unicorn 的主要可调选项是工作进程数和请求超时,之后 Unicorn 主服务器终止工作进程. 如果要调整这些设置,请参见[Omnibus GitLab Unicorn 设置文档](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/unicorn.html) . + +## unicorn-worker-killer[](#unicorn-worker-killer "Permalink") + +GitLab 内存泄漏. 这些内存泄漏在长时间运行的进程(例如 Unicorn 工作者)中表现出来. (不知道 Unicorn 主进程会泄漏内存,可能是因为它无法处理用户请求.) + +为了使这些内存泄漏易于管理,GitLab 随附了[unicorn-worker-killer gem](https://github.com/kzk/unicorn-worker-killer) . 每隔 16 个请求,这只宝石[猴就会](https://en.wikipedia.org/wiki/Monkey_patch)给独角兽工人打[补丁](https://en.wikipedia.org/wiki/Monkey_patch)以进行内存自检. 如果 Unicorn worker 的内存超过预设限制,则退出 worker 进程. 然后,Unicorn 主服务器自动替换工作进程. + +这是处理内存泄漏的可靠方法:Unicorn 旨在处理"崩溃"的工作程序,因此不会丢弃任何用户请求. unicorn-worker-killer gem 被设计为仅*在请求之间*终止工作进程,因此不会影响用户请求. 您可以通过设置以下值`/etc/gitlab/gitlab.rb`来设置 Unicorn worker killer 的最小和最大内存阈值(以字节为单位): + +* 对于 GitLab **12.7**及更高版本: + + ``` + unicorn['worker_memory_limit_min'] = "1024 * 1 << 20" + unicorn['worker_memory_limit_max'] = "1280 * 1 << 20" + ``` + +* 对于 GitLab **12.6**及更高版本: + + ``` + unicorn['worker_memory_limit_min'] = "400 * 1 << 20" + unicorn['worker_memory_limit_max'] = "650 * 1 << 20" + ``` + +否则,您可以设置`GITLAB_UNICORN_MEMORY_MIN`和`GITLAB_UNICORN_MEMORY_MAX` [环境变量](../environment_variables.html) . + +这就是 Unicorn_stderr.log 中的 Unicorn 工作程序内存重新启动的样子. 您看到工作程序 4(PID 125918)正在检查自己并决定退出. 内存阈值是 254802235 字节,大约 250MB. 对于 GitLab,此阈值是 200 到 250 MB 之间的随机值. 然后,主进程(PID 117565)接收工作进程,并生成具有 PID 127549 的新"工作进程 4". + +``` +[2015-06-05T12:07:41.828374 #125918] WARN -- : #: worker (pid: 125918) exceeds memory limit (256413696 bytes > 254802235 bytes) +[2015-06-05T12:07:41.828472 #125918] WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 125918) alive: 23 sec (trial 1) +[2015-06-05T12:07:42.025916 #117565] INFO -- : reaped # worker=4 +[2015-06-05T12:07:42.034527 #127549] INFO -- : worker=4 spawned pid=127549 +[2015-06-05T12:07:42.035217 #127549] INFO -- : worker=4 ready +``` + +从 GitLab.com 上摘录的另一段日志摘要是," worker 4"仅在 23 秒内处理请求. 对于我们当前的 GitLab.com 设置和流量,这是正常值. + +在某些 GitLab 网站上,独角兽内存重新启动的频率很高,可能会使管理员感到困惑. 通常他们是[红鲱鱼](https://en.wikipedia.org/wiki/Red_herring) . \ No newline at end of file diff --git a/_book/docs/485.md b/_book/docs/485.md new file mode 100644 index 0000000000000000000000000000000000000000..54978c3dc9e6c69a9a84712704196f2608050c94 --- /dev/null +++ b/_book/docs/485.md @@ -0,0 +1,119 @@ +# User lookup via OpenSSH's AuthorizedPrincipalsCommand + +> 原文:[https://docs.gitlab.com/ee/administration/operations/ssh_certificates.html](https://docs.gitlab.com/ee/administration/operations/ssh_certificates.html) + +* [Why use OpenSSH certificates?](#why-use-openssh-certificates) +* [Setting up SSH certificate lookup via GitLab Shell](#setting-up-ssh-certificate-lookup-via-gitlab-shell) +* [Principals and security](#principals-and-security) +* [Interaction with the `authorized_keys` file](#interaction-with-the-authorized_keys-file) +* [Other security caveats](#other-security-caveats) +* [Disabling the global warning about users lacking SSH keys](#disabling-the-global-warning-about-users-lacking-ssh-keys) + +# User lookup via OpenSSH’s AuthorizedPrincipalsCommand[](#user-lookup-via-opensshs-authorizedprincipalscommand "Permalink") + +> [在](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19911) GitLab 社区版 11.2 中[可用](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19911) . + +GitLab 的默认 SSH 身份验证要求用户上载 SSH 公钥,然后才能使用 SSH 传输. + +在集中式(例如公司)环境中,这在操作上可能会很麻烦,特别是如果 SSH 密钥是颁发给用户的临时密钥,例如在发行后 24 小时过期的临时密钥. + +在这种设置中,需要一些外部自动化过程来不断将新密钥上载到 GitLab. + +> **警告:需要** OpenSSH 6.9+版本,因为该版本引入了`AuthorizedPrincipalsCommand`配置选项. 如果使用 CentOS 6,则可以[按照以下说明](fast_ssh_key_lookup.html#compiling-a-custom-version-of-openssh-for-centos-6)来编译最新版本. + +## Why use OpenSSH certificates?[](#why-use-openssh-certificates "Permalink") + +通过使用 OpenSSH 证书,有关 GitLab 上用户拥有密钥的所有信息都被编码在密钥本身中,并且 OpenSSH 自身保证用户无法伪造此信息,因为他们需要访问私有 CA 签名密钥. + +正确设置后,就不需要完全将用户 SSH 密钥上传到 GitLab. + +## Setting up SSH certificate lookup via GitLab Shell[](#setting-up-ssh-certificate-lookup-via-gitlab-shell "Permalink") + +如何完全设置 SSH 证书不在本文档的范围之内. 请参阅[OpenSSH 的`PROTOCOL.certkeys`](https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD)了解其工作方式,例如[RedHat 的文档](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/sec-using_openssh_certificate_authentication) . + +我们假设您已经设置了 SSH 证书,并且已经将 CA 的`TrustedUserCAKeys`添加到了`sshd_config` ,例如: + +``` +TrustedUserCAKeys /etc/security/mycompany_user_ca.pub +``` + +通常,在这种设置中, `TrustedUserCAKeys`不会在" `Match User git`范围内,因为它也将用于系统登录到 GitLab 服务器本身,但是您的设置可能会有所不同. 如果 CA 仅用于 GitLab,请考虑将其放在" `Match User git`部分(如下所述). + +由该 CA 颁发的 SSH 证书**务必**具有与该用户在 GitLab 上的用户名相对应的"密钥 ID",例如(为简洁起见,省略了一些输出): + +``` +$ ssh-add -L | grep cert | ssh-keygen -L -f - + +(stdin):1: + Type: ssh-rsa-cert-v01@openssh.com user certificate + Public key: RSA-CERT SHA256:[...] + Signing CA: RSA SHA256:[...] + Key ID: "aearnfjord" + Serial: 8289829611021396489 + Valid: from 2018-07-18T09:49:00 to 2018-07-19T09:50:34 + Principals: + sshUsers + [...] + [...] +``` + +从技术上讲,这不是完全正确,例如,它可以`prod-aearnfjord`如果它是你通常会登录到服务器作为一个 SSH 证书`prod-aearnfjord`用户,但你必须指定自己的`AuthorizedPrincipalsCommand`做映射,而不是使用我们提供的默认. + +重要的是, `AuthorizedPrincipalsCommand`必须能够以某种方式从"密钥 ID"映射到 GitLab 用户名,我们提供的默认命令假设两者之间存在 1 = 1 的映射,因为这样做的重点是允许我们从密钥本身提取 GitLab 用户名,而不是依赖默认的公共密钥到用户名的映射. + +然后,在您的`sshd_config`为`git`用户设置`AuthorizedPrincipalsCommand` . 希望您可以使用 GitLab 随附的默认值: + +``` +Match User git + AuthorizedPrincipalsCommandUser root + AuthorizedPrincipalsCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-principals-check %i sshUsers +``` + +该命令将发出类似于以下内容的输出: + +``` +command="/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell username-{KEY_ID}",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty {PRINCIPAL} +``` + +其中`{KEY_ID}`是传递给脚本的`%i`参数(例如`aeanfjord` ),而`{PRINCIPAL}`是传递给脚本的主体(例如`sshUsers` ). + +您将需要自定义其中的`sshUsers`部分. 对于可以登录到 GitLab 的所有用户,它应该是一定要保证是密钥的一部分的主体,或者您必须提供一个主体列表,其中一个将提供给用户,例如: + +``` + [...] + AuthorizedPrincipalsCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-principals-check %i sshUsers windowsUsers +``` + +## Principals and security[](#principals-and-security "Permalink") + +您可以根据需要提供任意数量的委托人,这些委托人将变成多行`authorized_keys`输出,如`sshd_config(5)`中的`AuthorizedPrincipalsFile`文档中所述. + +通常,将`AuthorizedKeysCommand`与 OpenSSH 一起使用时,主体是允许登录到该服务器的某个"组". 但是,在 GitLab 中,它仅用于满足 OpenSSH 的要求,我们实际上只关心"密钥 ID"的正确性. 一旦解压缩,GitLab 将为该用户强制执行自己的 ACL(例如,用户可以访问哪些项目). + +因此,例如对用户接受的内容过分慷慨是可以的,因为如果用户(例如)根本无法访问 GitLab,它只会出错并显示一条有关该用户无效的消息. + +## Interaction with the `authorized_keys` file[](#interaction-with-the-authorized_keys-file "Permalink") + +SSH 证书可以与`authorized_keys`文件结合使用,并且如果按照上述`authorized_keys`文件的配置进行设置,它仍将作为后备. + +这是因为,如果`AuthorizedPrincipalsCommand`无法对用户进行身份验证,则 OpenSSH 将回退到`~/.ssh/authorized_keys` (或`AuthorizedKeysCommand` )上. + +因此,仍然有理由结合使用["在数据库中快速查找授权的 SSH 密钥"](fast_ssh_key_lookup.html)方法. 由于您将对所有普通用户使用 SSH 证书,并且如果使用密钥,则依靠`~/.ssh/authorized_keys`后备来部署密钥. + +但是您可能会发现没有必要这样做,因为所有普通用户都将使用快速的`AuthorizedPrincipalsCommand`路径,并且只有自动部署密钥访问才会落在`~/.ssh/authorized_keys` ,或者您还有更多的密钥可以使用普通用户(尤其是续订的用户)比您拥有的部署密钥. + +## Other security caveats[](#other-security-caveats "Permalink") + +用户仍然可以通过手动将 SSH 公钥上载到他们的配置文件中来绕过 SSH 证书身份验证,依靠`~/.ssh/authorized_keys`后备来对其进行身份验证. 当前没有阻止它的功能, [但是有一个添加它的公开请求](https://gitlab.com/gitlab-org/gitlab/-/issues/23260) . + +当前,可以通过提供一个自定义的`AuthorizedKeysCommand`来破解这种限制,该命令可检查从`gitlab-shell-authorized-keys-check`返回的已发现密钥 ID `gitlab-shell-authorized-keys-check`为部署密钥(应拒绝所有非部署密钥). + +## Disabling the global warning about users lacking SSH keys[](#disabling-the-global-warning-about-users-lacking-ssh-keys "Permalink") + +默认情况下,GitLab 将向尚未将 SSH 密钥上载到其配置文件的用户显示"您将无法通过 SSH 推送或推送项目代码"警告. + +This is counterproductive when using SSH certificates, since users aren’t expected to upload their own keys. + +要全局禁用此警告,请转到"应用程序设置->帐户和限制设置",然后禁用"显示用户添加 SSH 密钥消息"设置. + +This setting was added specifically for use with SSH certificates, but can be turned off without using them if you’d like to hide the warning for some other reason. \ No newline at end of file diff --git a/_book/docs/486.md b/_book/docs/486.md new file mode 100644 index 0000000000000000000000000000000000000000..9acddd8defebcb8d2c1f77f4266c7aa10e2ddbb2 --- /dev/null +++ b/_book/docs/486.md @@ -0,0 +1,176 @@ +# GitLab Package Registry administration + +> 原文:[https://docs.gitlab.com/ee/administration/packages/](https://docs.gitlab.com/ee/administration/packages/) + +* [Enabling the Packages feature](#enabling-the-packages-feature) +* [Changing the storage path](#changing-the-storage-path) + * [Changing the local storage path](#changing-the-local-storage-path) + * [Using object storage](#using-object-storage) + * [Migrating local packages to object storage](#migrating-local-packages-to-object-storage) + +# GitLab Package Registry administration[](#gitlab-package-registry-administration-premium-only "Permalink") + +GitLab 软件包允许组织将 GitLab 用作各种常见软件包管理器的私有存储库. 用户能够构建和发布程序包,这些程序包可以很容易地作为下游项目中的依赖项使用. + +软件包功能允许 GitLab 充当以下内容的存储库: + +| 软件库 | Description | 在 GitLab 版本中可用 | +| --- | --- | --- | +| [PyPi Repository](../../user/packages/pypi_repository/index.html) | GitLab PyPi 存储库使 GitLab 中的每个项目都有自己的空间来存储[PyPi](https://s0pypi0org.icopy.site/)软件包. | 12.10+ | +| [Composer Repository](../../user/packages/composer_repository/index.html) | GitLab Composer 存储库使 GitLab 中的每个项目都有自己的空间来存储[Composer](https://s0getcomposer0org.icopy.site/)软件包. | 13.1+ | +| [NuGet Repository](../../user/packages/nuget_repository/index.html) | GitLab NuGet 存储库使 GitLab 中的每个项目都有自己的空间来存储[NuGet](https://www.nuget.org/)软件包. | 12.8+ | +| [Conan Repository](../../user/packages/conan_repository/index.html) | GitLab 柯南存储库使 GitLab 中的每个项目都有自己的空间来存储[柯南](https://conan.io/)软件包. | 12.4+ | +| [Maven Repository](../../user/packages/maven_repository/index.html) | GitLab Maven 存储库使 GitLab 中的每个项目都有自己的空间来存储[Maven](https://maven.apache.org/)软件包. | 11.3+ | +| [NPM Registry](../../user/packages/npm_registry/index.html) | GitLab NPM 注册表使 GitLab 中的每个项目都有自己的空间来存储[NPM](https://s0www0npmjs0com.icopy.site/)软件包. | 11.7+ | +| [Go Proxy](../../user/packages/go_proxy/index.html) | GitLab 的 Go 代理使 GitLab 中的每个项目都可以通过[Go 代理协议](https://proxy.golang.org/)获取. | 13.1+ | + +您没有看到您的包裹管理系统受支持吗? 请考虑为 GitLab 做贡献. 此[开发文档](../../development/packages.html)将指导您完成该过程. + +## Enabling the Packages feature[](#enabling-the-packages-feature "Permalink") + +**注意:**启用"软件包"功能后,默认情况下,存储库可用于所有新项目. 要为现有项目启用它,用户将必须在项目的设置中明确启用它. + +要启用包功能: + +**所有装置 GitLab** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下行: + + ``` + gitlab_rails['packages_enabled'] = true + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure "如何重新配置​​Omnibus GitLab")以使更改生效. + +**从源安装** + +1. 安装完成后,您将必须在`config/gitlab.yml`中`config/gitlab.yml` `packages`部分. 设置为`true`以启用它: + + ``` + packages: + enabled: true + ``` + +2. [重新启动 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure "如何重新配置​​Omnibus GitLab")以使更改生效. + +## Changing the storage path[](#changing-the-storage-path "Permalink") + +默认情况下,程序包存储在本地,但是您可以更改默认的本地位置,甚至使用对象存储. + +### Changing the local storage path[](#changing-the-local-storage-path "Permalink") + +用于 Omnibus GitLab 安装的软件包存储在`/var/opt/gitlab/gitlab-rails/shared/packages/`而用于源安装的`shared/packages/`在`shared/packages/` (相对于 Git 主目录). 更改本地存储路径: + +**所有装置 GitLab** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下行: + + ``` + gitlab_rails['packages_storage_path'] = "/mnt/packages" + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 编辑`config/gitlab.yml`的`packages`部分: + + ``` + packages: + enabled: true + storage_path: shared/packages + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +### Using object storage[](#using-object-storage "Permalink") + +您可以使用对象存储来存储程序包,而不必依赖于本地存储. + +[Read more about using object storage with GitLab](../object_storage.html). + +**注意:**我们建议使用[统一对象存储设置](../object_storage.html#consolidated-object-storage-configuration) . 以下说明适用于原始配置格式. + +**Omnibus GitLab installations** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下行(必要时取消注释): + + ``` + gitlab_rails['packages_enabled'] = true + gitlab_rails['packages_storage_path'] = "/var/opt/gitlab/gitlab-rails/shared/packages" + gitlab_rails['packages_object_store_enabled'] = true + gitlab_rails['packages_object_store_remote_directory'] = "packages" # The bucket name. + gitlab_rails['packages_object_store_direct_upload'] = false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false). + gitlab_rails['packages_object_store_background_upload'] = true # Temporary option to limit automatic upload (Default: true). + gitlab_rails['packages_object_store_proxy_download'] = false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage. + gitlab_rails['packages_object_store_connection'] = { + ## + ## If the provider is AWS S3, uncomment the following + ## + #'provider' => 'AWS', + #'region' => 'eu-west-1', + #'aws_access_key_id' => 'AWS_ACCESS_KEY_ID', + #'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY', + ## + ## If the provider is other than AWS (an S3-compatible one), uncomment the following + ## + #'host' => 's3.amazonaws.com', + #'aws_signature_version' => 4 # For creation of signed URLs. Set to 2 if provider does not support v4. + #'endpoint' => 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces. + #'path_style' => false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'. + } + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 编辑`config/gitlab.yml`的`packages`部分(必要时取消注释): + + ``` + packages: + enabled: true + ## + ## The location where build packages are stored (default: shared/packages). + ## + #storage_path: shared/packages + object_store: + enabled: false + remote_directory: packages # The bucket name. + #direct_upload: false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false). + #background_upload: true # Temporary option to limit automatic upload (Default: true). + #proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage. + connection: + ## + ## If the provider is AWS S3, uncomment the following + ## + #provider: AWS + #region: us-east-1 + #aws_access_key_id: AWS_ACCESS_KEY_ID + #aws_secret_access_key: AWS_SECRET_ACCESS_KEY + ## + ## If the provider is other than AWS (an S3-compatible one), uncomment the following + ## + #host: 's3.amazonaws.com' # default: s3.amazonaws.com. + #aws_signature_version: 4 # For creation of signed URLs. Set to 2 if provider does not support v4. + #endpoint: 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces. + #path_style: false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'. + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +### Migrating local packages to object storage[](#migrating-local-packages-to-object-storage "Permalink") + +[配置对象存储后](#using-object-storage) ,您可以使用以下任务将现有程序包从本地存储迁移到远程存储. 该处理将在后台工作人员中完成, **无需停机** . + +对于所有 GitLab; + +``` +sudo gitlab-rake "gitlab:packages:migrate" +``` + +对于源安装: + +``` +RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:packages:migrate +``` \ No newline at end of file diff --git a/_book/docs/487.md b/_book/docs/487.md new file mode 100644 index 0000000000000000000000000000000000000000..0fd5007c876aa1bfa1ba92a74f26c7172d3b8178 --- /dev/null +++ b/_book/docs/487.md @@ -0,0 +1,1041 @@ +# GitLab Container Registry administration + +> 原文:[https://docs.gitlab.com/ee/administration/packages/container_registry.html](https://docs.gitlab.com/ee/administration/packages/container_registry.html) + +* [Enable the Container Registry](#enable-the-container-registry) +* [Container Registry domain configuration](#container-registry-domain-configuration) + * [Configure Container Registry under an existing GitLab domain](#configure-container-registry-under-an-existing-gitlab-domain) + * [Configure Container Registry under its own domain](#configure-container-registry-under-its-own-domain) +* [Disable Container Registry site-wide](#disable-container-registry-site-wide) +* [Disable Container Registry for new projects site-wide](#disable-container-registry-for-new-projects-site-wide) +* [Configure storage for the Container Registry](#configure-storage-for-the-container-registry) + * [Use filesystem](#use-filesystem) + * [Use object storage](#use-object-storage) + * [Migrate to object storage without downtime](#migrate-to-object-storage-without-downtime) + * [Disable redirect for storage driver](#disable-redirect-for-storage-driver) + * [Storage limitations](#storage-limitations) +* [Change the registry’s internal port](#change-the-registrys-internal-port) +* [Disable Container Registry per project](#disable-container-registry-per-project) +* [Use an external container registry with GitLab as an auth endpoint](#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint) +* [Configure Container Registry notifications](#configure-container-registry-notifications) +* [Container Registry garbage collection](#container-registry-garbage-collection) + * [Understanding the content-addressable layers](#understanding-the-content-addressable-layers) + * [Recycling unused tags](#recycling-unused-tags) + * [Removing unused layers not referenced by manifests](#removing-unused-layers-not-referenced-by-manifests) + * [Performing garbage collection without downtime](#performing-garbage-collection-without-downtime) + * [Running the garbage collection on schedule](#running-the-garbage-collection-on-schedule) +* [Troubleshooting](#troubleshooting) + * [Using self-signed certificates with Container Registry](#using-self-signed-certificates-with-container-registry) + * [`unauthorized: authentication required` when pushing large images](#unauthorized-authentication-required-when-pushing-large-images) + * [AWS S3 with the GitLab registry error when pushing large images](#aws-s3-with-the-gitlab-registry-error-when-pushing-large-images) + * [Supporting older Docker clients](#supporting-older-docker-clients) + * [Docker connection error](#docker-connection-error) + * [Image push errors](#image-push-errors) + * [Enable the Registry debug server](#enable-the-registry-debug-server) + * [Advanced Troubleshooting](#advanced-troubleshooting) + * [Unexpected 403 error during push](#unexpected-403-error-during-push) + * [mitmproxy](#mitmproxy) + * [Running the Docker daemon with a proxy](#running-the-docker-daemon-with-a-proxy) + * [Running the Docker client](#running-the-docker-client) + +# GitLab Container Registry administration[](#gitlab-container-registry-administration "Permalink") + +Version history + +* 在 GitLab 8.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4040) . +* 在 GitLab 8.9 中添加了对 Container Registry manifest `v1`支持,以支持 1.10 之前的 Docker 版本. + +**注意:**本文档是管理员指南. 要了解如何使用 GitLab 容器注册表,请参阅[用户文档](../../user/packages/container_registry/index.html) . + +通过将容器注册表集成到 GitLab 中,每个项目都可以拥有自己的空间来存储其 Docker 映像. + +您可以在[https://docs.docker.com/registry/introduction/上](https://s0docs0docker0com.icopy.site/registry/introduction/)了解有关 Docker 注册表的更多信息. + +## Enable the Container Registry[](#enable-the-container-registry "Permalink") + +**所有装置 GitLab** + +如果您使用 Omnibus 安装包安装了 GitLab,则默认情况下容器注册表可能可用或可能不可用. + +如果出现以下情况,容器注册表将自动启用,并在您的 GitLab 域上的端口 5050 上可用: + +* 您正在使用内置的[Let's Encrypt 集成](https://docs.gitlab.com/omnibus/settings/ssl.html) ,并且 +* 您使用的是 GitLab 12.5 或更高版本. + +否则,不会启用容器注册表. 要启用它: + +* 您可以为您的[GitLab 域](#configure-container-registry-under-an-existing-gitlab-domain)配置它,或者 +* 您可以为[其他域](#configure-container-registry-under-its-own-domain)配置它. + +**注意:**默认情况下,容器注册表在 HTTPS 下工作. 您可以使用 HTTP,但不建议使用 HTTP,它不在本文档的讨论范围之内. 如果要实现此目的,请阅读[不安全的注册表文档](https://s0docs0docker0com.icopy.site/registry/insecure/) . + +**从源安装** + +如果您从源代码安装了 GitLab: + +1. 您将必须自己[安装注册表](https://s0docs0docker0com.icopy.site/registry/deploying/) . +2. 安装完成后,您必须在`gitlab.yml`中配置注册表的设置才能启用它. +3. 使用在[`lib/support/nginx/registry-ssl`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/support/nginx/registry-ssl)下找到的示例 NGINX 配置文件,并对其进行编辑以匹配`host` , `port`和 TLS 证书路径. + +`gitlab.yml`的内容是: + +``` +registry: + enabled: true + host: registry.gitlab.example.com + port: 5005 + api_url: http://localhost:5000/ + key: config/registry.key + path: shared/registry + issuer: gitlab-issuer +``` + +where: + +| Parameter | Description | +| --- | --- | +| `enabled` | `true` `false` . 在 GitLab 中启用注册表. 默认情况下为`false` . | +| `host` | 注册表将在其下运行的主机 URL,并且用户将可以使用该 URL. | +| `port` | 外部注册表域将在其上侦听的端口. | +| `api_url` | The internal API URL under which the Registry is exposed to. It defaults to `http://localhost:5000`. | +| `key` | 私钥位置是一对 Registry 的`rootcertbundle` . 阅读[令牌身份验证配置文档](https://s0docs0docker0com.icopy.site/registry/configuration/) . | +| `path` | 该目录应与 Registry 的`rootdirectory`指定的目录相同. 阅读[存储配置文档](https://s0docs0docker0com.icopy.site/registry/configuration/) . GitLab 用户,Web 服务器用户和注册表用户必须可读此路径. 在[#configure-container-for-container-registry 中](#configure-storage-for-the-container-registry)了解更多信息. | +| `issuer` | This should be the same value as configured in Registry’s `issuer`. Read the [token auth configuration documentation](https://s0docs0docker0com.icopy.site/registry/configuration/). | + +**注意:**如果从源代码安装,则 GitLab 不会随附注册表初始化文件. 因此,如果您修改注册表, [重新启动 GitLab](../restart_gitlab.html#installations-from-source)将不会重新启动注册表. 阅读有关如何实现这一目标的上游文档. + +**绝对**要确保您的[注册表配置](https://s0docs0docker0com.icopy.site/registry/configuration/)将`container_registry`作为服务,并将`https://gitlab.example.com/jwt/auth`作为领域: + +``` +auth: + token: + realm: https://gitlab.example.com/jwt/auth + service: container_registry + issuer: gitlab-issuer + rootcertbundle: /root/certs/certbundle +``` + +**注意:**如果未设置`auth` ,则用户无需身份验证即可拉取 Docker 映像. + +## Container Registry domain configuration[](#container-registry-domain-configuration "Permalink") + +There are two ways you can configure the Registry’s external domain. Either: + +* [使用现有的 GitLab 域](#configure-container-registry-under-an-existing-gitlab-domain) ,在这种情况下,注册表将不得不侦听端口并重用 GitLab 的 TLS 证书, +* [将完全独立的域](#configure-container-registry-under-its-own-domain)与该[域](#configure-container-registry-under-its-own-domain)的新 TLS 证书一起使用. + +由于容器注册表需要 TLS 证书,所以最终归结为获得新证书的难易程度或代价. + +在首次配置 Container Registry 之前,请考虑到这一点. + +### Configure Container Registry under an existing GitLab domain[](#configure-container-registry-under-an-existing-gitlab-domain "Permalink") + +如果将注册表配置为使用现有的 GitLab 域,则可以在端口上公开注册表,以便可以重复使用现有的 GitLab TLS 证书. + +假设 GitLab 域是`https://gitlab.example.com` ,注册表暴露给外界的端口是`5050` ,如果您正在使用 Omnibus GitLab,则需要在`gitlab.rb`或`gitlab.yml`进行设置或分别从源代码安装 GitLab. + +**注意:**请小心选择与注册表侦听的端口不同的端口(默认为`5000` ),否则您将遇到冲突. + +**所有装置 GitLab** + +1. 您的`/etc/gitlab/gitlab.rb`应该包含注册表 URL 以及 GitLab 使用的现有 TLS 证书和密钥的路径: + + ``` + registry_external_url 'https://gitlab.example.com:5050' + ``` + + 请注意, `registry_external_url`如何在现有 GitLab URL 下的 HTTPS 上侦听,但在其他端口上. + + 如果您的 TLS 证书不在`/etc/gitlab/ssl/gitlab.example.com.crt`并且密钥不在`/etc/gitlab/ssl/gitlab.example.com.key`取消注释以下行: + + ``` + registry_nginx['ssl_certificate'] = "/path/to/certificate.pem" + registry_nginx['ssl_certificate_key'] = "/path/to/certificate.key" + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +3. 验证使用: + + ``` + openssl s_client -showcerts -servername gitlab.example.com -connect gitlab.example.com:5050 > cacert.pem + ``` + +**注意:**如果您的证书提供者提供了 CA Bundle 证书,则将它们附加到 TLS 证书文件中. + +**从源安装** + +1. 打开`/home/git/gitlab/config/gitlab.yml` ,找到`registry`项,并使用以下设置进行配置: + + ``` + registry: + enabled: true + host: gitlab.example.com + port: 5050 + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. +3. 还要在 NGINX 中进行相关更改(域,端口,TLS 证书路径). + +用户现在应该可以使用以下命令使用其 GitLab 凭据登录到 Container Registry: + +``` +docker login gitlab.example.com:5050 +``` + +### Configure Container Registry under its own domain[](#configure-container-registry-under-its-own-domain "Permalink") + +如果将注册表配置为使用其自己的域,则将需要该特定域的 TLS 证书(例如, `registry.example.com` ),或者如果托管在现有 GitLab 域的子域(例如, `registry.example.com` )下,则可能需要通配符证书`registry.gitlab.example.com` ). + +**注意:**除手动生成的 SSL 证书(在此处说明)外, [Omnibus 安装](https://docs.gitlab.com/omnibus/settings/ssl.html)还[支持](https://docs.gitlab.com/omnibus/settings/ssl.html)由 Let's Encrypt 自动生成的证书. + +假设您希望在`https://registry.gitlab.example.com`上访问容器注册表. + +**所有装置 GitLab** + +1. 将您的 TLS 证书和密钥放在`/etc/gitlab/ssl/registry.gitlab.example.com.crt`和`/etc/gitlab/ssl/registry.gitlab.example.com.key` ,并确保它们具有正确的权限: + + ``` + chmod 600 /etc/gitlab/ssl/registry.gitlab.example.com.* + ``` + +2. TLS 证书到位后,使用以下命令编辑`/etc/gitlab/gitlab.rb` : + + ``` + registry_external_url 'https://registry.gitlab.example.com' + ``` + + 请注意, `registry_external_url`如何在 HTTPS 上进行侦听. + +3. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +如果您具有[通配符证书](https://en.wikipedia.org/wiki/Wildcard_certificate) ,则除了 URL 外,还需要指定证书的路径,在这种情况下,/ `/etc/gitlab/gitlab.rb`将如下所示: + +``` +registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/certificate.pem" +registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/certificate.key" +``` + +**从源安装** + +1. 打开`/home/git/gitlab/config/gitlab.yml` ,找到`registry`项,并使用以下设置进行配置: + + ``` + registry: + enabled: true + host: registry.gitlab.example.com + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. +3. 还要在 NGINX 中进行相关更改(域,端口,TLS 证书路径). + +用户现在应该能够使用其 GitLab 凭据登录到 Container Registry: + +``` +docker login registry.gitlab.example.com +``` + +## Disable Container Registry site-wide[](#disable-container-registry-site-wide "Permalink") + +**注意:**按照以下步骤在 Rails GitLab 应用程序中禁用注册表,不会删除任何现有的 Docker 映像. 这由注册表应用程序本身处理. + +**所有的 GitLab** + +1. 打开`/etc/gitlab/gitlab.rb`并将`registry['enable']`为`false` : + + ``` + registry['enable'] = false + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 打开`/home/git/gitlab/config/gitlab.yml` ,找到`registry`项并将其设置`enabled`以`false` : + + ``` + registry: + enabled: false + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +## Disable Container Registry for new projects site-wide[](#disable-container-registry-for-new-projects-site-wide "Permalink") + +如果启用了容器注册表,那么它将在所有新项目中可用. 要禁用此功能并使项目的所有者自行启用容器注册表,请按照以下步骤操作. + +**所有装置 GitLab** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下行: + + ``` + gitlab_rails['gitlab_default_projects_features_container_registry'] = false + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 打开`/home/git/gitlab/config/gitlab.yml` ,找到`default_projects_features`条目并进行配置,以便`container_registry`设置为`false` : + + ``` + ## Default project features settings + default_projects_features: + issues: true + merge_requests: true + wiki: true + snippets: false + builds: true + container_registry: false + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +## Configure storage for the Container Registry[](#configure-storage-for-the-container-registry "Permalink") + +您可以通过配置存储驱动程序来将 Container Registry 配置为使用各种存储后端. 默认情况下,GitLab 容器注册表配置为使用[文件系统驱动程序](#use-filesystem)配置. + +支持的不同驱动程序是: + +| Driver | Description | +| --- | --- | +| filesystem | 使用本地文件系统上的路径 | +| Azure | Microsoft Azure Blob 存储 | +| gcs | 谷歌云存储 | +| s3 | Amazon Simple Storage Service. 确保使用正确的[S3 权限范围](https://s0docs0docker0com.icopy.site/registry/storage-drivers/s3/)配置存储桶. | +| swift | OpenStack Swift 对象存储 | +| oss | 阿里云 OSS | + +在[Docker Registry 文档中](https://s0docs0docker0com.icopy.site/registry/configuration/)阅读有关单个驱动程序配置选项的更多信息. + +### Use filesystem[](#use-filesystem "Permalink") + +如果要将图像存储在文件系统上,则可以更改 Container Registry 的存储路径,请按照以下步骤操作. + +此路径可用于: + +* 运行容器注册表守护程序的用户. +* 运行 GitLab 的用户. + +**警告:**您应该确认所有的 GitLab,注册表和 Web 服务器用户都可以访问该目录. + +**所有装置 GitLab** + +在 Omnibus 中存储图像的默认位置是`/var/opt/gitlab/gitlab-rails/shared/registry` . 要更改它: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitlab_rails['registry_path'] = "/path/to/registry/storage" + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +在源安装中存储映像的默认位置是`/home/git/gitlab/shared/registry` . 要更改它: + +1. 打开`/home/git/gitlab/config/gitlab.yml` ,找到`registry`项并更改`path`设置: + + ``` + registry: + path: shared/registry + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +### Use object storage[](#use-object-storage "Permalink") + +如果要将图像存储在对象存储中,则可以更改 Container Registry 的存储驱动程序. + +[Read more about using object storage with GitLab](../object_storage.html). + +**警告:** GitLab 不会备份未存储在文件系统上的 Docker 映像. 请记住,如果需要,请与您的对象存储提供程序一起启用备份.**注:** `regionendpoint`配置 S3 兼容的服务,如 MinIO 时才需要. 它采用一个 URL,例如`http://127.0.0.1:9000` . + +**所有装置 GitLab** + +在 Omnibus 中配置`s3`存储驱动程序: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['storage'] = { + 's3' => { + 'accesskey' => 's3-access-key', + 'secretkey' => 's3-secret-key-for-access-key', + 'bucket' => 'your-s3-bucket', + 'region' => 'your-s3-region', + 'regionendpoint' => 'your-s3-regionendpoint' + } + } + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**注意:** `your-s3-bucket`应该仅是存在的存储桶的名称,并且不能包含子目录. + +**从源安装** + +存储驱动程序的配置在[部署 Docker 注册表](https://s0docs0docker0com.icopy.site/registry/deploying/)时创建的注册表配置 YML 文件中完成. + +`s3`存储驱动程序示例: + +``` +storage: + s3: + accesskey: 's3-access-key' + secretkey: 's3-secret-key-for-access-key' + bucket: 'your-s3-bucket' + region: 'your-s3-region' + regionendpoint: 'your-s3-regionendpoint' + cache: + blobdescriptor: inmemory + delete: + enabled: true +``` + +**注意:** `your-s3-bucket`应该仅是存在的存储桶的名称,并且不能包含子目录. + +#### Migrate to object storage without downtime[](#migrate-to-object-storage-without-downtime "Permalink") + +若要在不停止 Container Registry 的情况下迁移存储,请将 Container Registry 设置为只读模式. 在大型实例上,这可能需要将 Container Registry 置于只读模式一段时间. 在此期间,您可以从 Container Registry 中拉出,但不能推送. + +1. 可选:要减少要迁移的数据量,请运行[垃圾收集工具,而无需停机](#performing-garbage-collection-without-downtime) . +2. 例如,使用 AWS CLI [`cp`](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/cp.html)或[`sync`](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/sync.html)命令将初始数据复制到 S3 存储桶. 确保将`docker`文件夹保留为存储桶中的顶级文件夹. + + ``` + aws s3 sync registry s3://mybucket + ``` + +3. 为了使更改生效, [请将 Container Registry 设置为`read-only`模式,](#performing-garbage-collection-without-downtime)然后[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +4. 将自初始数据加载以来的所有更改同步到 S3 存储桶,并删除目标存储桶中存在但源文件中不存在的文件: + + ``` + aws s3 sync registry s3://mybucket --delete + ``` + + **危险:** `--delete`标志将删除存在于目标而不是在源文件中. 确保不交换源和目标,否则您将删除注册表中的所有数据. +5. 将注册表配置为使用 S3 存储桶进行存储. +6. For the changes to take effect, set the Registry back to `read-write` mode and [reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +### Disable redirect for storage driver[](#disable-redirect-for-storage-driver "Permalink") + +默认情况下,访问配置了远程后端的注册表的用户将重定向到存储驱动程序的默认后端. 例如,可以使用`s3`存储驱动程序配置注册表,该驱动程序将请求重定向到远程 S3 存储桶以减轻 GitLab 服务器上的负载. + +但是,对于通常无法访问公共服务器的内部主机使用的注册表,此行为是不希望的. 要禁用重定向和[代理下载](../object_storage.html#proxy-download) ,请按如下所示将`disable`标志设置为 true. 这使得所有流量始终通过注册表服务. 这样可以提高安全性(由于无法公开访问存储后端,从而减少了表面攻击),但性能却较差(所有流量都通过服务重定向). + +**所有装置 GitLab** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['storage'] = { + 's3' => { + 'accesskey' => 's3-access-key', + 'secretkey' => 's3-secret-key-for-access-key', + 'bucket' => 'your-s3-bucket', + 'region' => 'your-s3-region', + 'regionendpoint' => 'your-s3-regionendpoint' + }, + 'redirect' => { + 'disable' => true + } + } + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 将`redirect`标志添加到您的注册表配置 YML 文件中: + + ``` + storage: + s3: + accesskey: 'AKIAKIAKI' + secretkey: 'secret123' + bucket: 'gitlab-registry-bucket-AKIAKIAKI' + region: 'your-s3-region' + regionendpoint: 'your-s3-regionendpoint' + redirect: + disable: true + cache: + blobdescriptor: inmemory + delete: + enabled: true + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +### Storage limitations[](#storage-limitations "Permalink") + +当前,没有存储限制,这意味着用户可以上传无限数量的任意大小的 Docker 映像. 此设置将在以后的版本中进行配置. + +## Change the registry’s internal port[](#change-the-registrys-internal-port "Permalink") + +**注意:**请勿将此与 GitLab 本身用于向世界展示注册表的端口混淆. + +默认情况下,Registry Server 在端口`5000`上的 localhost 上侦听,这是 Registry Server 应接受其连接的地址. 在下面的示例中,我们将注册表的端口设置为`5001` . + +**所有的 GitLab** + +1. 打开`/etc/gitlab/gitlab.rb`并设置`registry['registry_http_addr']` : + + ``` + registry['registry_http_addr'] = "localhost:5001" + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 打开您的注册表服务器的配置文件,然后编辑[`http:addr`](https://s0docs0docker0com.icopy.site/registry/configuration/)值: + + ``` + http + addr: localhost:5001 + ``` + +2. 保存文件并重新启动注册表服务器. + +## Disable Container Registry per project[](#disable-container-registry-per-project "Permalink") + +如果在您的 GitLab 实例中启用了注册表,但是您的项目不需要它,则可以从项目的设置中禁用它. 阅读有关如何实现此目的的用户指南. + +## Use an external container registry with GitLab as an auth endpoint[](#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint "Permalink") + +**注意:**在使用外部容器注册表时,与容器注册表相关联的某些功能可能不可用或存在[固有风险](./../../user/packages/container_registry/index.html#use-with-external-container-registries) + +**所有的 GitLab** + +您可以将 GitLab 用作具有外部容器注册表的身份验证端点. + +1. 打开`/etc/gitlab/gitlab.rb`并设置必要的配置: + + ``` + gitlab_rails['registry_enabled'] = true + gitlab_rails['registry_api_url'] = "http://localhost:5000" + gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer" + ``` + + **注意:**启用 GitLab 的 Container Registry 功能和身份验证端点需要`gitlab_rails['registry_enabled'] = true` . 即使启用了它,也不会启动 GitLab 捆绑的 Container Registry 服务. +2. 证书密钥对是 GitLab 和外部容器注册表进行安全通信所必需的. 您将需要创建一个证书密钥对,使用公共证书配置外部容器注册表,并使用私钥配置 GitLab. 为此,将以下内容添加到`/etc/gitlab/gitlab.rb` : + + ``` + # registry['internal_key'] should contain the contents of the custom key + # file. Line breaks in the key file should be marked using `\n` character + # Example: + registry['internal_key'] = "---BEGIN RSA PRIVATE KEY---\nMIIEpQIBAA\n" + + # Optionally define a custom file for Omnibus GitLab to write the contents + # of registry['internal_key'] to. + gitlab_rails['registry_key_path'] = "/custom/path/to/registry-key.key" + ``` + + **注意:**每次执行重新配置时,都会使用`internal_key`指定的内容填充`registry_key_path`指定的文件. 如果未指定文件,则 Omnibus GitLab 会将其默认设置为`/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key`并将其填充. +3. 要更改在 GitLab 容器注册表页面中显示的容器注册表 URL,请设置以下配置: + + ``` + gitlab_rails['registry_host'] = "registry.gitlab.example.com" + gitlab_rails['registry_port'] = "5005" + ``` + +4. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 打开`/home/git/gitlab/config/gitlab.yml` ,然后在`registry`下编辑配置设置: + + ``` + ## Container Registry + + registry: + enabled: true + host: "registry.gitlab.example.com" + port: "5005" + api_url: "http://localhost:5000" + path: /var/opt/gitlab/gitlab-rails/shared/registry + key: /var/opt/gitlab/gitlab-rails/certificate.key + issuer: omnibus-gitlab-issuer + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +## Configure Container Registry notifications[](#configure-container-registry-notifications "Permalink") + +您可以将 Container Registry 配置为发送 Webhook 通知,以响应注册表中发生的事件. + +在[Docker Registry 通知文档中](https://s0docs0docker0com.icopy.site/registry/notifications/)阅读有关 Container Registry 通知配置选项的更多信息. + +**注意:**可以为 Container Registry 配置多个端点. + +**所有装置 GitLab** + +要在 Omnibus 中配置通知端点: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['notifications'] = [ + { + 'name' => 'test_endpoint', + 'url' => 'https://gitlab.example.com/notify', + 'timeout' => '500ms', + 'threshold' => 5, + 'backoff' => '1s', + 'headers' => { + "Authorization" => ["AUTHORIZATION_EXAMPLE_TOKEN"] + } + } + ] + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +在[部署 Docker 注册表](https://s0docs0docker0com.icopy.site/registry/deploying/)时创建的注册表配置 YML 文件中完成了通知端点的配置. + +Example: + +``` +notifications: + endpoints: + - name: alistener + disabled: false + url: https://my.listener.com/event + headers: + timeout: 500 + threshold: 5 + backoff: 1000 +``` + +## Container Registry garbage collection[](#container-registry-garbage-collection "Permalink") + +**注意:**仅当您通过 Omnibus 软件包或[云本机图表](https://docs.gitlab.com/charts/charts/registry/)安装了 GitLab 时,垃圾收集工具才可用.**危险:**通过运行内置的垃圾收集命令,将导致 Container Registry 停机. 如果在其他实例之一仍在写入注册表存储的环境中的某个实例上运行此命令,则将删除引用的清单. 为避免这种情况,请确保在继续[操作](#performing-garbage-collection-without-downtime)之前将注册表设置为[只读模式](#performing-garbage-collection-without-downtime) . + +容器注册表可以使用大量的磁盘空间. 为了清除一些未使用的层,注册表包括一个垃圾收集命令. + +GitLab 提供了一组 API 来操作 Container Registry 并协助删除未使用标签的过程. 当前,这是使用 API​​公开的,但是将来,这些控件将被迁移到 GitLab 接口. + +项目维护者可以根据自己的标准定期[删除大量的 Container Registry 标签](../../api/container_registry.html#delete-registry-repository-tags-in-bulk) ,但是,这本身并不会回收数据,它只会使清单和图像斑点之间的链接断开. 要在整个 GitLab 实例中回收 Container Registry 数据,可以使用`gitlab-ctl`提供的内置命令. + +### Understanding the content-addressable layers[](#understanding-the-content-addressable-layers "Permalink") + +请考虑以下示例,该示例是您首先构建映像的地方: + +``` +# This builds a image with content of sha256:111111 +docker build -t my.registry.com/my.group/my.project:latest . +docker push my.registry.com/my.group/my.project:latest +``` + +现在,您要使用新版本覆盖`:latest` : + +``` +# This builds a image with content of sha256:222222 +docker build -t my.registry.com/my.group/my.project:latest . +docker push my.registry.com/my.group/my.project:latest +``` + +现在, `:latest`标记指向`sha256:222222` . 但是,由于注册表的体系结构,即使不再通过`:latest`标记也可以直接访问图像`my.registry.com/my.group/my.project@sha256:111111` ,仍可以访问此数据. + +### Recycling unused tags[](#recycling-unused-tags "Permalink") + +> 在所有 GitLab 8.12 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/987) . + +在运行内置命令之前,需要注意一些注意事项: + +* 内置命令将在启动垃圾收集之前停止注册表. +* 垃圾收集命令需要一些时间才能完成,具体取决于存在的数据量. +* 如果更改了注册表配置文件的位置,则需要指定其路径. +* After the garbage collection is done, the registry should start up automatically. + +如果未更改配置文件的默认位置,请运行: + +``` +sudo gitlab-ctl registry-garbage-collect +``` + +该命令将花费一些时间来完成,具体取决于您存储的层数. + +如果更改了 Container Registry `config.yml`的位置: + +``` +sudo gitlab-ctl registry-garbage-collect /path/to/config.yml +``` + +您也可以[删除所有未引用的清单](#removing-unused-layers-not-referenced-by-manifests) ,尽管这是一种更具破坏性的操作,您应该首先了解其含义. + +### Removing unused layers not referenced by manifests[](#removing-unused-layers-not-referenced-by-manifests "Permalink") + +> 在所有 GitLab 11.10 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/3097) . + +**危险:**这是破坏性的操作. + +GitLab 容器注册表遵循与 Docker Distribution 相同的默认工作流程:保留所有层,即使是未直接引用的层也允许使用上下文可寻址标识符访问所有内容. + +但是,在大多数工作流程中,如果注册表标记未直接引用旧层,则您不必在意这些旧层. `registry-garbage-collect`命令支持`-m`开关,以允许您删除所有不能通过`tag`直接访问的未引用清单和层: + +``` +sudo gitlab-ctl registry-garbage-collect -m +``` + +由于这是更具破坏性的操作,因此默认情况下将禁用此行为. 您可能期望这种操作方式,但是在执行此操作之前,请确保已备份所有注册表数据. + +### Performing garbage collection without downtime[](#performing-garbage-collection-without-downtime "Permalink") + +在 GitLab 8.8 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/764) . + +通过将其置于只读模式并且不使用内置命令,可以在不停止 Container Registry 的情况下执行垃圾回收. 在大型实例中,这可能需要 Container Registry 处于只读模式一段时间. 在这段时间中,您将能够从 Container Registry 中拉出,但不能进行推送. + +**注意:**默认情况下, [注册表存储路径](#configure-storage-for-the-container-registry)为`/var/opt/gitlab/gitlab-rails/shared/registry` . + +要启用只读模式: + +1. 在`/etc/gitlab/gitlab.rb` ,指定只读模式: + + ``` + registry['storage'] = { + 'filesystem' => { + 'rootdirectory' => "" + }, + 'maintenance' => { + 'readonly' => { + 'enabled' => true + } + } + } + ``` + +2. 保存并重新配置 GitLab: + + ``` + sudo gitlab-ctl reconfigure + ``` + + 这会将 Container Registry 设置为只读模式. + +3. 接下来,触发垃圾收集命令之一: + + ``` + # Recycling unused tags + sudo /opt/gitlab/embedded/bin/registry garbage-collect /var/opt/gitlab/registry/config.yml + + # Removing unused layers not referenced by manifests + sudo /opt/gitlab/embedded/bin/registry garbage-collect -m /var/opt/gitlab/registry/config.yml + ``` + + 这将开始垃圾收集,这可能需要一些时间才能完成. + +4. 完成后,在`/etc/gitlab/gitlab.rb`更改回读写模式: + + ``` + registry['storage'] = { + 'filesystem' => { + 'rootdirectory' => "" + }, + 'maintenance' => { + 'readonly' => { + 'enabled' => false + } + } + } + ``` + +5. 保存并重新配置 GitLab: + + ``` + sudo gitlab-ctl reconfigure + ``` + +### Running the garbage collection on schedule[](#running-the-garbage-collection-on-schedule "Permalink") + +理想情况下,您希望在不使用注册表的情况下每周定期运行注册表的垃圾回收. 最简单的方法是添加一个新的 crontab 作业,该作业将每周定期运行一次. + +在`/etc/cron.d/registry-garbage-collect`下创建一个文件: + +``` +SHELL=/bin/sh +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +# Run every Sunday at 04:05am +5 4 * * 0 root gitlab-ctl registry-garbage-collect +``` + +## Troubleshooting[](#troubleshooting "Permalink") + +在深入探讨以下部分之前,请先进行一些基本的故障排除: + +1. 检查并确保 Docker 客户端和 GitLab 服务器上的系统时钟已同步(例如,通过 NTP). + +2. 如果使用的是 S3 支持的注册表,请仔细检查 IAM 权限和 S3 凭据(包括区域)是否正确. 有关更多详细信息,请参阅[示例 IAM 策略](https://s0docs0docker0com.icopy.site/registry/storage-drivers/s3/) . + +3. 检查注册表日志(例如`/var/log/gitlab/registry/current` )和 GitLab 生产日志中的错误(例如`/var/log/gitlab/gitlab-rails/production.log` ). 您也许可以在那里找到线索. + +### Using self-signed certificates with Container Registry[](#using-self-signed-certificates-with-container-registry "Permalink") + +如果您在容器注册表中使用自签名证书,则在 CI 作业期间可能会遇到如下问题: + +``` +Error response from daemon: Get registry.example.com/v1/users/: x509: certificate signed by unknown authority +``` + +运行该命令的 Docker 守护程序需要由公认的 CA 签名的证书,因此会出现上述错误. + +虽然 GitLab 不使用自签名的证书与集装箱注册表支持开箱即用,它可以使其工作的[指示多克尔守护信任自签名证书](https://s0docs0docker0com.icopy.site/registry/insecure/) ,安装多克尔守护进程,并设置`privileged = false`的跑步者的`config.toml` . 设置`privileged = true`优先于 Docker 守护程序: + +``` + [runners.docker] + image = "ruby:2.6" + privileged = false + volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"] +``` + +有关此的其他信息: [发行 18239](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/18239) . + +### `unauthorized: authentication required` when pushing large images[](#unauthorized-authentication-required-when-pushing-large-images "Permalink") + +错误示例: + +``` +docker push gitlab.example.com/myproject/docs:latest +The push refers to a repository [gitlab.example.com/myproject/docs] +630816f32edb: Preparing +530d5553aec8: Preparing +... +4b0bab9ff599: Waiting +d1c800db26c7: Waiting +42755cf4ee95: Waiting +unauthorized: authentication required +``` + +GitLab 的注册表默认令牌有效期为 5 分钟. 当推送较大的图像或推送时间超过 5 分钟的图像时,用户可能会遇到此错误. + +管理员可以在**管理区域>设置> CI / CD>容器注册表>授权令牌持续时间(分钟)中增加令牌持续时间** . + +### AWS S3 with the GitLab registry error when pushing large images[](#aws-s3-with-the-gitlab-registry-error-when-pushing-large-images "Permalink") + +将 AWS S3 与 GitLab 注册表一起使用时,推送大图像时可能会发生错误. 在注册表日志中查找以下错误: + +``` +level=error msg="response completed with error" err.code=unknown err.detail="unexpected EOF" err.message="unknown error" +``` + +要解决该错误,请在注册表配置中指定一个`chunksize`值. 从`25000000` (25MB)到`50000000` (50MB)之间的值开始. + +**对于所有安装** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['storage'] = { + 's3' => { + 'accesskey' => 'AKIAKIAKI', + 'secretkey' => 'secret123', + 'bucket' => 'gitlab-registry-bucket-AKIAKIAKI', + 'chunksize' => 25000000 + } + } + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**对于源安装** + +1. Edit `config/gitlab.yml`: + + ``` + storage: + s3: + accesskey: 'AKIAKIAKI' + secretkey: 'secret123' + bucket: 'gitlab-registry-bucket-AKIAKIAKI' + chunksize: 25000000 + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +### Supporting older Docker clients[](#supporting-older-docker-clients "Permalink") + +从 GitLab 11.9 开始,我们开始提供 Docker 容器注册表的 2.7.1 版本,默认情况下会禁用 schema1 清单. 如果您仍在使用较旧的 Docker 客户端(1.9 或更早版本),则在推送映像时可能会遇到错误. 有关更多详细信息,请参见[omn​​ibus-4145](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4145) . + +您可以添加配置选项以实现向后兼容. + +**对于所有安装** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['compatibility_schema1_enabled'] = true + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**对于源安装** + +1. 编辑[部署注册表](https://s0docs0docker0com.icopy.site/registry/deploying/)时创建的 YML 配置文件. 添加以下代码段: + + ``` + compatibility: + schema1: + enabled: true + ``` + +2. 重新启动注册表以使更改生效. + +### Docker connection error[](#docker-connection-error "Permalink") + +当组,项目或分支名​​称中包含特殊字符时,可能会发生 Docker 连接错误. 特殊字符可以包括: + +* Leading underscore +* 尾随连字符/破折号 +* 双连字符/破折号 + +为了解决这个问题,您可以[更改组路径](../../user/group/index.html#changing-a-groups-path) , [更改项目路径](../../user/project/settings/index.html#renaming-a-repository)或更改分支名称. 另一种选择是创建一个[推送规则,](../../push_rules/push_rules.html)以防止在实例级别上发生这种情况. + +### Image push errors[](#image-push-errors "Permalink") + +当遇到错误或"重试"循环以尝试推送映像但`docker login`正常时,NGINX 将标头转发到注册表可能存在问题. 推荐的默认 NGINX 配置应该可以解决此问题,但是它可能发生在将 SSL 卸载到第三方反向代理的自定义设置中. + +在[Docker 项目](https://github.com/docker/distribution/issues/970)问题中讨论了此问题,一个简单的解决方案是在注册表中启用相对 URL. + +**对于所有安装** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['env'] = { + "REGISTRY_HTTP_RELATIVEURLS" => true + } + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**对于源安装** + +1. 编辑[部署注册表](https://s0docs0docker0com.icopy.site/registry/deploying/)时创建的 YML 配置文件. 添加以下代码段: + + ``` + http: + relativeurls: true + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +### Enable the Registry debug server[](#enable-the-registry-debug-server "Permalink") + +可以通过在`gitlab.rb`配置中设置注册表调试地址来启用可选的调试服务器. + +``` +registry['debug_addr'] = "localhost:5001" +``` + +添加设置后, [重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure)以应用更改. + +使用 curl 来请求调试服务器的调试输出: + +``` +curl localhost:5001/debug/health +curl localhost:5001/debug/vars +``` + +### Advanced Troubleshooting[](#advanced-troubleshooting "Permalink") + +**注意:**以下部分仅建议专家使用. + +有时,不清楚什么地方出了问题,您可能需要更深入地研究 Docker 客户端与 Registry 之间的通信,以找出问题所在. 过去我们将使用一个具体示例来说明如何诊断 S3 设置中的问题. + +#### Unexpected 403 error during push[](#unexpected-403-error-during-push "Permalink") + +用户试图启用 S3 支持的注册表. `docker login`步骤很好. 但是,推送图像时,输出显示: + +``` +The push refers to a repository [s3-testing.myregistry.com:5050/root/docker-test/docker-image] +dc5e59c14160: Pushing [==================================================>] 14.85 kB +03c20c1a019a: Pushing [==================================================>] 2.048 kB +a08f14ef632e: Pushing [==================================================>] 2.048 kB +228950524c88: Pushing 2.048 kB +6a8ecde4cc03: Pushing [==> ] 9.901 MB/205.7 MB +5f70bf18a086: Pushing 1.024 kB +737f40e80b7f: Waiting +82b57dbc5385: Waiting +19429b698a22: Waiting +9436069b92a3: Waiting +error parsing HTTP 403 response body: unexpected end of JSON input: "" +``` + +这个错误是模棱两可的,因为尚不清楚 403 是来自 GitLab Rails 应用程序,Docker Registry 还是其他东西. 在这种情况下,由于我们知道自成功登录以来,我们可能需要查看客户端与注册表之间的通信. + +[此处描述](https://s0docs0docker0com.icopy.site/registry/spec/api/)了 Docker 客户端和 Registry 之间的 REST API. 通常,人们只会使用 Wireshark 或 tcpdump 捕获流量并查看问题出在哪里. 但是,由于 Docker 客户端和服务器之间的所有通信都是通过 HTTPS 完成的,因此即使您知道私钥,也很难快速解密流量. 我们该怎么办呢? + +一种方法是通过设置[不安全的注册表](https://s0docs0docker0com.icopy.site/registry/insecure/)来禁用 HTTPS. 这可能会引入安全漏洞,仅建议用于本地测试. 如果您有生产系统并且不能或不想这样做,则可以采用另一种方法:使用 mitmproxy,它代表中间代理. + +#### mitmproxy[](#mitmproxy "Permalink") + +[mitmproxy](https://mitmproxy.org/)允许您在客户端和服务器之间放置代理以检查所有流量. 一种麻烦是您的系统需要信任 mitmproxy SSL 证书才能起作用. + +以下安装说明假定您正在运行 Ubuntu: + +1. [Install mitmproxy](https://docs.mitmproxy.org/stable/overview-installation/). +2. 运行`mitmproxy --port 9000`生成其证书. 输入`CTRL` - `C`退出. +3. 将证书从`~/.mitmproxy`安装到您的系统中: + + ``` + sudo cp ~/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/mitmproxy-ca-cert.crt + sudo update-ca-certificates + ``` + +如果成功,输出应表明已添加证书: + +``` +Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done. +Running hooks in /etc/ca-certificates/update.d....done. +``` + +要验证证书是否正确安装,请运行: + +``` +mitmproxy --port 9000 +``` + +这将在端口`9000`上运行 mitmproxy. 在另一个窗口中,运行: + +``` +curl --proxy http://localhost:9000 https://httpbin.org/status/200 +``` + +如果一切设置正确,您将在 mitmproxy 窗口上看到信息,并且 curl 命令没有错误. + +#### Running the Docker daemon with a proxy[](#running-the-docker-daemon-with-a-proxy "Permalink") + +为了使 Docker 通过代理连接,您必须使用适当的环境变量启动 Docker 守护程序. 最简单的方法是关闭 Docker(例如`sudo initctl stop docker` ),然后手动运行 Docker. 以超级用户身份运行: + +``` +export HTTP_PROXY="http://localhost:9000" +export HTTPS_PROXY="https://localhost:9000" +docker daemon --debug +``` + +这将启动 Docker 守护程序并通过 mitmproxy 代理所有连接. + +#### Running the Docker client[](#running-the-docker-client "Permalink") + +现在我们已经运行了 mitmproxy 和 Docker,我们可以尝试登录并推送容器映像. 您可能需要以 root 身份运行才能执行此操作. 例如: + +``` +docker login s3-testing.myregistry.com:5050 +docker push s3-testing.myregistry.com:5050/root/docker-test/docker-image +``` + +In the example above, we see the following trace on the mitmproxy window: + +[![mitmproxy output from Docker](img/c73475715fce01bf6b51edda84064d67.png)](img/mitmproxy-docker.png) + +上图显示: + +* 初始的 PUT 请求可以顺利通过 201 状态代码. +* 201 将客户端重定向到 S3 存储桶. +* 向 AWS 存储桶的 HEAD 请求报告了 403 未经授权. + +这是什么意思? 这强烈表明 S3 用户没有[执行 HEAD 请求](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html)的正确[权限](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html) . 解决方案: [再次](https://s0docs0docker0com.icopy.site/registry/storage-drivers/s3/)检查[IAM 权限](https://s0docs0docker0com.icopy.site/registry/storage-drivers/s3/) . 设置正确的权限后,错误将消失. \ No newline at end of file diff --git a/_book/docs/488.md b/_book/docs/488.md new file mode 100644 index 0000000000000000000000000000000000000000..636c6329e760944e7a62aeafe3de1f57a5fccec7 --- /dev/null +++ b/_book/docs/488.md @@ -0,0 +1,324 @@ +# Replication (Geo) + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/](https://docs.gitlab.com/ee/administration/geo/replication/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [How it works](#how-it-works) + * [Architecture](#architecture) +* [Requirements for running Geo](#requirements-for-running-geo) + * [Firewall rules](#firewall-rules) + * [LDAP](#ldap) + * [Geo Tracking Database](#geo-tracking-database) + * [Geo Log Cursor](#geo-log-cursor) +* [Setup instructions](#setup-instructions) + * [Using Omnibus GitLab](#using-omnibus-gitlab) +* [Post-installation documentation](#post-installation-documentation) + * [Configuring Geo](#configuring-geo) + * [Updating Geo](#updating-geo) + * [Pausing and resuming replication](#pausing-and-resuming-replication) + * [Configuring Geo for multiple nodes](#configuring-geo-for-multiple-nodes) + * [Configuring Geo with Object Storage](#configuring-geo-with-object-storage) + * [Disaster Recovery](#disaster-recovery) + * [Replicating the Container Registry](#replicating-the-container-registry) + * [Security Review](#security-review) + * [Tuning Geo](#tuning-geo) + * [Set up a location-aware Git URL](#set-up-a-location-aware-git-url) +* [Remove Geo node](#remove-geo-node) +* [Disable Geo](#disable-geo) +* [Current limitations](#current-limitations) + * [Limitations on replication/verification](#limitations-on-replicationverification) +* [Frequently Asked Questions](#frequently-asked-questions) +* [Log files](#log-files) +* [Troubleshooting](#troubleshooting) + +# Replication (Geo)[](#replication-geo-premium-only "Permalink") + +版本历史 + +* 在 GitLab 企业版 8.9 中引入. +* 与组合使用地理[多节点架构](../../reference_architectures/index.html)在考虑**一般可用** (GA) [GitLab 高级](https://about.gitlab.com/pricing/) 10.4\. + +使用 Geo 复制是广泛分布的开发团队的解决方案. + +## Overview[](#overview "Permalink") + +对于远离单个 GitLab 实例的团队而言,获取大型存储库可能需要很长时间. + +Geo 提供您的 GitLab 实例的本地只读实例. 这样可以减少克隆和获取大型存储库所需的时间,从而加快开发速度. + +**注意:**在设置 Geo 之前,请仔细检查[要求](#requirements-for-running-geo) . + +有关 Geo 的视频介绍,请参见[GitLab Geo-GitLab 功能介绍](https://www.youtube.com/watch?v=-HDLxSjEh6w) . + +**注意:**从发布到发布,Geo 进行了重大更改. **支持**升级和[记录](#updating-geo) ,但你应该确保您使用的文件的正确的版本进行安装. + +为确保您使用的文档版本正确,请[在 GitLab.com 上](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/index.md)导航[至此页面的源版本](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/index.md) ,然后从**Switch 分支/标签**下拉列表中选择适当的版本. 例如, [`v11.2.3-ee`](https://gitlab.com/gitlab-org/gitlab/blob/v11.2.3-ee/doc/administration/geo/replication/index.md) . + +## Use cases[](#use-cases "Permalink") + +实施 Geo 具有以下好处: + +* 将分布式开发人员克隆和获取大型存储库和项目所需的时间从几分钟减少到几秒钟. +* 无论您身在何处,都可以使所有开发人员共同贡献想法并并行工作. +* 平衡**主**节点和**辅助**节点之间的只读负载. + +此外,它: + +* 除读取 GitLab Web 界面中可用的任何数据外,还可用于克隆和获取项目(请参阅[当前限制](#current-limitations) ). +* 克服远程办公室之间的慢速连接,通过提高分布式团队的速度来节省时间. +* 帮助减少自动任务,自定义集成和内部工作流程的加载时间. +* 可以在[灾难恢复](../disaster_recovery/index.html)方案中快速故障转移到**辅助**节点. +* 允许[计划的故障转移](../disaster_recovery/planned_failover.html)到**辅助**节点. + +地理位置提供: + +* 只读**辅助**节点:维护一个**主** GitLab 节点,同时仍为每个分布式团队启用只读**辅助**节点. +* 身份验证系统挂钩: **辅助**节点从**主**实例接收所有身份验证数据(例如用户帐户和登录名). +* 直观的用户界面: **辅助**节点使用团队已习惯的相同 Web 界面. 此外,还有可视通知会阻止写操作,并清楚表明用户在**辅助**节点上. + +## How it works[](#how-it-works "Permalink") + +除了读取任何数据外,您的 Geo 实例还可用于克隆和获取项目. 这将使在较大距离上使用大型存储库的速度更快. + +[![Geo overview](img/c17db26d06341055b4834c8be77c604b.png)](img/geo_overview.png) + +启用地理位置后,: + +* 原始实例称为**主要**节点. +* 复制的只读节点称为**辅助**节点. + +请记住: + +* **辅助**节点与**主**节点对话以: + * 获取用于登录的用户数据(API). + * 复制存储库,LFS 对象和附件(HTTPS + JWT). +* 从 GitLab Premium 10.0 开始, **主**节点不再与**辅助**节点对话以通知更改(API). +* [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3 中[引入](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/)了直接推送到**辅助**节点(对于 HTTP 和 SSH,包括 Git LFS). +* 当前的实施存在[局限性](#current-limitations) . + +### Architecture[](#architecture "Permalink") + +下图说明了 Geo 的基础体系结构. + +[![Geo architecture](img/5f13fe556b8940c2e698facdc219d16a.png)](img/geo_architecture.png) + +在此图中: + +* 有**主**节点和一个**辅助**节点的详细信息. +* 只能在**主**节点上执行对数据库的写入. **辅助**节点通过 PostgreSQL 流复制接收数据库更新. +* 如果存在,则应将[LDAP 服务器](#ldap)配置为针对[灾难恢复](../disaster_recovery/index.html)方案进行复制. +* **辅助**节点使用受 JWT 保护的特殊授权对**主要**节点执行不同类型的同步: + * 存储库是通过 HTTPS 上的 Git 克隆/更新的. + * 使用专用 API 端点通过 HTTPS 下载附件,LFS 对象和其他文件. + +从用户执行 Git 操作的角度来看: + +* **主**节点的行为就像一个完整的读写 GitLab 实例. +* **辅助**节点是只读的,但代理 Git 将操作推送到**主**节点. 这使得**辅助**节点似乎本身就支持推送操作. + +为了简化该图,省略了一些必要的组件. 注意: + +* SSH 上的 Git 需要[`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell)和 OpenSSH. +* 通过 HTTPS 进行 Git 时需要[`gitlab-workhorse`](https://gitlab.com/gitlab-org/gitlab-workhorse) . + +请注意, **辅助**节点需要两个不同的 PostgreSQL 数据库: + +* 一个只读数据库实例,用于从 GitLab 主数据库中流式传输数据. +* **辅助**节点在内部使用的[另一个数据库实例](#geo-tracking-database)记录已复制的数据. + +在**辅助**节点中,还有一个附加的守护进程: [Geo Log Cursor](#geo-log-cursor) . + +## Requirements for running Geo[](#requirements-for-running-geo "Permalink") + +要运行 Geo,必须具备以下条件: + +* 支持 OpenSSH 6.9+的操作系统(需要[在数据库中快速查找授权的 SSH 密钥](../../operations/fast_ssh_key_lookup.html) )当前已知版本的 OpenSSH 随附了以下操作系统: + * [CentOS](https://www.centos.org) 7.4 以上 + * [Ubuntu](https://ubuntu.com) 16.04 以上 +* PostgreSQL 11+ with [FDW](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html) support and [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication) +* 转到 2.9+ +* 所有节点必须运行相同的 GitLab 版本. + +此外,请检查 GitLab 的[最低要求](../../../install/requirements.html) ,我们建议您使用: + +* 至少具有 GitLab 企业版 10.0 的基本地理功能. +* 最新版本以获得更好的体验. + +### Firewall rules[](#firewall-rules "Permalink") + +下表列出了在 Geo 的**主**节点和**辅助**节点之间必须打开的基本端口. + +| **Primary** node | **Secondary** node | Protocol | +| --- | --- | --- | +| 80 | 80 | HTTP | +| 443 | 443 | TCP 或 HTTPS | +| 22 | 22 | TCP | +| 5432 |   | PostgreSQL | + +在[Package 默认值中](https://docs.gitlab.com/omnibus/package-information/defaults.html)查看 GitLab 使用的端口的完整列表 + +**注意:** [Web 终端](../../../ci/environments/index.html#web-terminals)支持要求您的负载平衡器正确处理 WebSocket 连接. 当使用 HTTP 或 HTTPS 代理,负载平衡器必须被配置为通过`Connection`和`Upgrade`逐跳头. 有关更多详细信息,请参见[Web 终端](../../integration/terminal.html)集成指南.**注意:**将 HTTPS 协议用于端口 443 时,您需要向负载均衡器添加 SSL 证书. 如果您想在 GitLab 应用程序服务器上终止 SSL,请使用 TCP 协议. + +### LDAP[](#ldap "Permalink") + +We recommend that if you use LDAP on your **primary** node, you also set up secondary LDAP servers on each **secondary** node. Otherwise, users will not be able to perform Git operations over HTTP(s) on the **secondary** node using HTTP Basic Authentication. However, Git via SSH and personal access tokens will still work. + +**注意:**所有**辅助**节点都可以共享 LDAP 服务器,但是额外的延迟可能是一个问题. 另外,如果将**辅助**节点提升为**主要**节点,请考虑在[灾难恢复](../disaster_recovery/index.html)方案中将使用哪些 LDAP 服务器. + +查看有关如何在 LDAP 服务中设置复制的说明. 根据使用的软件或服务,说明会有所不同. 例如,OpenLDAP 提供了[这些说明](https://www.openldap.org/doc/admin24/replication.html) . + +### Geo Tracking Database[](#geo-tracking-database "Permalink") + +跟踪数据库实例用作元数据,以控制需要在本地实例的磁盘上更新的内容. 例如: + +* 下载新资产. +* 提取新的 LFS 对象. +* 从最近更新的存储库中获取更改. + +因为复制的数据库实例是只读的,所以每个**辅助**节点都需要这个额外的数据库实例. 跟踪数据库需要`postgres_fdw`扩展名. + +### Geo Log Cursor[](#geo-log-cursor "Permalink") + +该守护程序: + +* 读取由**主**节点复制到**辅助**数据库实例的事件的日志. +* 使用需要执行的更改更新地理跟踪数据库实例. + +在跟踪数据库实例中将某些内容标记为要更新时,在**辅助**节点上运行的异步作业将执行所需的操作并更新状态. + +这种新的体系结构使 GitLab 能够应对节点之间的连接问题. **辅助**节点与**主**节点断开连接的时间无关紧要,因为它将能够以正确的顺序重放所有事件并再次与**主**节点同步. + +## Setup instructions[](#setup-instructions "Permalink") + +这些说明假定您有一个 GitLab 的工作实例. 他们指导您: + +1. 将现有实例设为**主要**节点. +2. Adding **secondary** nodes. + +**Caution:** The steps below should be followed in the order they appear. **确保所有节点上的 GitLab 版本均相同.** + +### Using Omnibus GitLab[](#using-omnibus-gitlab "Permalink") + +如果您使用 Omnibus 软件包安装了 GitLab(强烈建议): + +1. 在将用作**辅助**节点的服务器上[安装 GitLab 企业版](https://about.gitlab.com/install/) . 不要创建帐户或登录到新的**辅助**节点. +2. 在**主**节点上[载 GitLab 许可](../../../user/admin_area/license.html)以解锁 Geo. 该许可证必须适用于[GitLab Premium](https://about.gitlab.com/pricing/)或更高版本. +3. [Set up the database replication](database.html) (`primary (read-write) <-> secondary (read-only)` topology). +4. [在数据库中配置快速查找授权的 SSH 密钥](../../operations/fast_ssh_key_lookup.html) . 此步骤是必需的,并且必须**同时**在**主**节点和**辅助**节点上完成. +5. [配置 GitLab](configuration.html)以设置**主**节点和**辅助**节点. +6. 可选:为**辅助**节点[配置辅助 LDAP 服务器](../../auth/ldap/index.html) . 请参阅[LDAP 上的注释](#ldap) . +7. [Follow the “Using a Geo Server” guide](using_a_geo_server.html). + +## Post-installation documentation[](#post-installation-documentation "Permalink") + +在**辅助**节点上安装 GitLab 并执行初始配置后,请参阅以下文档以获取安装后信息. + +### Configuring Geo[](#configuring-geo "Permalink") + +有关配置 Geo 的信息,请参见[Geo 配置](configuration.html) . + +### Updating Geo[](#updating-geo "Permalink") + +有关如何将 Geo 节点更新到最新的 GitLab 版本的信息,请参见[更新 Geo 节点](updating_the_geo_nodes.html) . + +### Pausing and resuming replication[](#pausing-and-resuming-replication "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35913) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + +在某些情况下,例如在[升级](updating_the_geo_nodes.html)或[计划的故障转移](../disaster_recovery/planned_failover.html)期间,最好暂停主数据库和辅助数据库之间的复制. + +暂停和恢复复制是通过辅助节点上的命令行工具完成的. + +**暂停:(从中学开始)** + +``` +gitlab-ctl geo-replication-pause +``` + +**恢复:(从中学开始)** + +``` +gitlab-ctl geo-replication-resume +``` + +### Configuring Geo for multiple nodes[](#configuring-geo-for-multiple-nodes "Permalink") + +有关为多个节点配置 Geo 的信息,请参阅[针对多个服务器的 Geo](multiple_servers.html) . + +### Configuring Geo with Object Storage[](#configuring-geo-with-object-storage "Permalink") + +有关配置带对象存储的 Geo 的信息,请参阅[带对象存储的 Geo](object_storage.html) . + +### Disaster Recovery[](#disaster-recovery "Permalink") + +有关在灾难恢复情况下使用 Geo 减轻数据丢失和恢复服务的信息,请参阅[灾难恢复](../disaster_recovery/index.html) . + +### Replicating the Container Registry[](#replicating-the-container-registry "Permalink") + +有关如何复制 Container Registry 的更多信息,请参阅[**辅助**节点的 Docker Registry](docker_registry.html) . + +### Security Review[](#security-review "Permalink") + +有关地理安全的更多信息,请参阅[地理安全审阅](security_review.html) . + +### Tuning Geo[](#tuning-geo "Permalink") + +有关调整 Geo 的更多信息,请参见[调整 Geo](tuning.html) . + +### Set up a location-aware Git URL[](#set-up-a-location-aware-git-url "Permalink") + +有关如何使用 AWS Route53 设置位置感知的 Git 远程 URL 的示例,请参阅使用 AWS Route53 [感知位置的 Git 远程 URL](location_aware_git_url.html) . + +## Remove Geo node[](#remove-geo-node "Permalink") + +For more information on removing a Geo node, see [Removing **secondary** Geo nodes](remove_geo_node.html). + +## Disable Geo[](#disable-geo "Permalink") + +要了解如何禁用地理位置,请参阅[禁用地理位置](disable_geo.html) . + +## Current limitations[](#current-limitations "Permalink") + +**注意:**此限制列表仅反映最新版本的 GitLab. 如果您使用的是旧版本,则可能存在其他限制. + +* 将请求直接推送到**辅助**节点(对于 HTTP)或代理(对于 SSH)​​会将请求重定向到**主要**节点,而不是[直接处理它](https://gitlab.com/gitlab-org/gitlab/-/issues/1381) ,除非在 HTTP 中使用 Git over HTTP 并在 URI 中嵌入凭据. 例如, `https://user:password@secondary.tld` . +* 克隆,拉动或推送存在于**主**节点上但不存在于**辅助**节点上的存储库,这些存储库中的[选择性同步](configuration.html#selective-synchronization)不包括项目,因此不支持通过 SSH 进行, [但已计划进行支持](https://gitlab.com/groups/gitlab-org/-/epics/2562) . 支持 HTTP(S). +* **主**节点必须在线才能进行 OAuth 登录. 现有会话和 Git 均不受影响. [正在计划](https://gitlab.com/gitlab-org/gitlab/-/issues/208465)支持**辅助**节点使用独立于主节点的 OAuth 提供程序. +* 安装过程需要执行多个手动步骤,根据具体情况,总共可能需要一个小时的时间. 我们正在努力改善这种体验. 有关详细信息,请参见[Omnibus GitLab 第 2978](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/2978)期. +* 问题/合并请求的实时更新(例如,通过长轮询)在**辅助**节点上不起作用. +* [选择性同步](configuration.html#selective-synchronization)仅适用于文件和存储库. 其他数据集已完全复制到**辅助**节点,使其不适合用作访问控制机制. +* 用于分支项目重复数据删除的对象池仅在**主**节点上工作,并在**辅助**节点上重复. +* [如果外部合并请求差异](../../merge_request_diffs.html)在磁盘上,则将不会复制它们,并且查看合并请求将失败. 但是,支持对象存储**中的**外部 MR 差异. 默认配置(数据库中)起作用. +* GitLab Runners 无法向**辅助**节点注册. [计划在将来](https://gitlab.com/gitlab-org/gitlab/-/issues/3294)对此提供支持. + +### Limitations on replication/verification[](#limitations-on-replicationverification "Permalink") + +您可以跟踪实现这些史诗/问题中缺少的项目的进度: + +* [Unreplicated Data Types](https://gitlab.com/groups/gitlab-org/-/epics/893) +* [Verify all replicated data](https://gitlab.com/groups/gitlab-org/-/epics/1430) + +这里有所有 GitLab [数据类型](datatypes.html)的完整列表以及[对复制和验证的现有支持](datatypes.html#limitations-on-replicationverification) . + +## Frequently Asked Questions[](#frequently-asked-questions "Permalink") + +有关常见问题的答案,请参见[地理位置常见问题解答](faq.html) . + +## Log files[](#log-files "Permalink") + +自 GitLab 9.5 起,Geo 将结构化日志消息存储在`geo.log`文件中. 对于 Omnibus 安装,此文件位于`/var/log/gitlab/gitlab-rails/geo.log` . + +该文件包含有关 Geo 何时尝试同步存储库和文件的信息. 文件中的每一行都包含一个可以提取的单独的 JSON 条目. 例如,Elasticsearch 或 Splunk. + +例如: + +``` +{"severity":"INFO","time":"2017-08-06T05:40:16.104Z","message":"Repository update","project_id":1,"source":"repository","resync_repository":true,"resync_wiki":true,"class":"Gitlab::Geo::LogCursor::Daemon","cursor_delay_s":0.038} +``` + +此消息表明,Geo 检测到项目`1`需要存储库更新. + +## Troubleshooting[](#troubleshooting "Permalink") + +有关故障排除步骤,请参阅[地理故障排除](troubleshooting.html) . \ No newline at end of file diff --git a/_book/docs/489.md b/_book/docs/489.md new file mode 100644 index 0000000000000000000000000000000000000000..735ab9f87c494fd7465fb5e1090b1321a564d985 --- /dev/null +++ b/_book/docs/489.md @@ -0,0 +1,414 @@ +# Geo database replication + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/database.html](https://docs.gitlab.com/ee/administration/geo/replication/database.html) + +* [PostgreSQL replication](#postgresql-replication) + * [Step 1\. Configure the **primary** server](#step-1-configure-the-primary-server) + * [Step 2\. Configure the **secondary** server](#step-2-configure-the-secondary-server) + * [Step 3\. Initiate the replication process](#step-3-initiate-the-replication-process) +* [PgBouncer support (optional)](#pgbouncer-support-optional) +* [Troubleshooting](#troubleshooting) + +# Geo database replication[](#geo-database-replication-premium-only "Permalink") + +**注意:**如果您的 GitLab 安装使用外部(不受 Omnibus 管理)PostgreSQL 实例,则 Omnibus 角色将无法执行所有必要的配置步骤. 在这种情况下,请[改用 Geo with external PostgreSQL instances 文档](external_database.html) .**Note:** The stages of the setup process must be completed in the documented order. Before attempting the steps in this stage, [complete all prior stages](index.html#using-omnibus-gitlab). + +本文档介绍了将**主** GitLab 数据库复制到**辅助**节点的数据库时必须执行的最少步骤. 您可能需要根据数据库设置,数据库大小等来更改一些值. + +我们鼓励您先阅读所有步骤,然后再在测试/生产环境中执行这些步骤. + +## PostgreSQL replication[](#postgresql-replication "Permalink") + +进行写操作的 GitLab **主**节点将连接到**主**数据库服务器, **辅助**节点将连接到他们自己的数据库服务器(也是只读的). + +我们建议使用[PostgreSQL 复制插槽,](https://medium.com/@tk512/replication-slots-in-postgresql-b4b03d277c75)以确保**主**节点保留恢复**次**节点所需的所有数据. 请参阅下面的更多细节. + +The following guide assumes that: + +* 您使用的是 Omnibus,因此使用的是 PostgreSQL 11 或更高版本,其中包括[`pg_basebackup`工具](https://s0www0postgresql0org.icopy.site/docs/11/app-pgbasebackup.html)和改进的[Foreign Data Wrapper](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html)支持. +* 您已经设置了一个**主**节点(您要从中复制的 GitLab 服务器),并且正在运行 Omnibus 的 PostgreSQL(或等效版本),并且已经设置了一个新的**辅助**服务器,并且具有相同版本的 OS,PostgreSQL 和 GitLab.所有节点. + +**警告:** Geo 可用于流复制. 目前不支持逻辑复制. 在[讨论支持问题](https://gitlab.com/gitlab-org/gitlab/-/issues/7420) . + +### Step 1\. Configure the **primary** server[](#step-1-configure-the-primary-server "Permalink") + +1. SSH 到您的 GitLab **主**服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 编辑`/etc/gitlab/gitlab.rb`并为您的节点添加一个**唯一的**名称: + + ``` + # The unique identifier for the Geo node. + gitlab_rails['geo_node_name'] = '' + ``` + +3. 重新配置**主**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +4. 执行以下命令以将节点定义**为主**节点: + + ``` + gitlab-ctl set-geo-primary-node + ``` + + 该命令将使用您在`/etc/gitlab/gitlab.rb`定义的`external_url` . + +5. 仅限于 GitLab 10.4 及更高版本:执行以下操作以确保`gitlab`数据库用户已定义密码: + + 生成所需密码的 MD5 哈希值: + + ``` + gitlab-ctl pg-password-md5 gitlab + # Enter password: + # Confirm password: + # fca0b89a972d69f00eb3ec98a5838484 + ``` + + Edit `/etc/gitlab/gitlab.rb`: + + ``` + # Fill with the hash generated by `gitlab-ctl pg-password-md5 gitlab` + postgresql['sql_user_password'] = '' + + # Every node that runs Puma or Sidekiq needs to have the database + # password specified as below. If you have a high-availability setup, this + # must be present in all application nodes. + gitlab_rails['db_password'] = '' + ``` + +6. Omnibus GitLab 已经有一个名为`gitlab_replicator`的[复制用户](https://wiki.postgresql.org/wiki/Streaming_Replication) . 您必须手动设置该用户的密码. 系统将提示您输入密码: + + ``` + gitlab-ctl set-replication-password + ``` + + 如果您已将`gitlab_replicator`用户名更改为其他名称,则此命令还将读取`postgresql['sql_replication_user']` Omnibus 设置. + + 如果您使用的不是由 Omnibus GitLab 管理的外部数据库,则需要创建复制器用户并手动为其定义密码: + + ``` + --- Create a new user 'replicator' + CREATE USER gitlab_replicator; + + --- Set/change a password and grants replication privilege + ALTER USER gitlab_replicator WITH REPLICATION ENCRYPTED PASSWORD ''; + ``` + +7. 配置 PostgreSQL 以侦听网络接口: + + 出于安全原因,PostgreSQL 默认情况下不侦听任何网络接口. 但是,Geo 要求**辅助**节点能够连接到**主**节点的数据库. 因此,我们需要每个节点的地址. + + **注意:**对于外部 PostgreSQL 实例,请参见[其他说明](external_database.html) . + + 如果使用的是云提供商,则可以通过云提供商的管理控制台查找每个地理节点的地址. + + 要查找 Geo 节点的地址,请 SSH 到 Geo 节点并执行: + + ``` + ## + ## Private address + ## + ip route get 255.255.255.255 | awk '{print "Private address:", $NF; exit}' + + ## + ## Public address + ## + echo "External address: $(curl --silent ipinfo.io/ip)" + ``` + + 在大多数情况下,以下地址将用于配置 GitLab Geo: + + | Configuration | Address | + | --- | --- | + | `postgresql['listen_address']` | **主**节点的公用或 VPC 专用地址. | + | `postgresql['md5_auth_cidr_addresses']` | **辅助**节点的公用或 VPC 专用地址. | + + 如果您使用的是 Google Cloud Platform,SoftLayer 或提供虚拟私有云(VPC)的任何其他供应商,则可以将**主**节点和**辅助**节点的私有地址(对应于 Google Cloud Platform 的"内部地址")用于`postgresql['md5_auth_cidr_addresses']`和`postgresql['listen_address']` . + + `listen_address`选项打开 PostgreSQL 直至与给定地址对应的接口的网络连接. 有关更多详细信息,请参见[PostgreSQL 文档](https://s0www0postgresql0org.icopy.site/docs/11/runtime-config-connection.html) . + + 根据您的网络配置,建议的地址可能不正确. 如果您的**主**节点和**辅助**节点通过局域网或连接可用性区域的虚拟网络(例如[Amazon 的 VPC](https://aws.amazon.com/vpc/)或[Google 的 VPC)进行连接](https://cloud.google.com/vpc/) ,则应将**辅助**节点的私有地址用于`postgresql['md5_auth_cidr_addresses']` . + + 编辑`/etc/gitlab/gitlab.rb`并添加以下内容,将 IP 地址替换为适合您的网络配置的地址: + + ``` + ## + ## Geo Primary role + ## - configure dependent flags automatically to enable Geo + ## + roles ['geo_primary_role'] + + ## + ## Primary address + ## - replace '' with the public or VPC address of your Geo primary node + ## + postgresql['listen_address'] = '' + + ## + # Allow PostgreSQL client authentication from the primary and secondary IPs. These IPs may be + # public or VPC addresses in CIDR format, for example ['198.51.100.1/32', '198.51.100.2/32'] + ## + postgresql['md5_auth_cidr_addresses'] = ['/32', '/32'] + + ## + ## Replication settings + ## - set this to be the number of Geo secondary nodes you have + ## + postgresql['max_replication_slots'] = 1 + # postgresql['max_wal_senders'] = 10 + # postgresql['wal_keep_segments'] = 10 + + ## + ## Disable automatic database migrations temporarily + ## (until PostgreSQL is restarted and listening on the private address). + ## + gitlab_rails['auto_migrate'] = false + ``` + +8. 可选:如果要添加另一个**辅助**节点,则相关设置应如下所示: + + ``` + postgresql['md5_auth_cidr_addresses'] = ['/32', '/32', '/32'] + ``` + + 您可能还需要编辑`wal_keep_segments`和`max_wal_senders`以匹配您的数据库复制要求. 有关更多信息,请查阅[PostgreSQL-复制文档](https://s0www0postgresql0org.icopy.site/docs/11/runtime-config-replication.html) . + +9. 保存文件并重新配置 GitLab,以进行数据库侦听更改和要应用的复制插槽更改: + + ``` + gitlab-ctl reconfigure + ``` + + 重新启动 PostgreSQL 以使其更改生效: + + ``` + gitlab-ctl restart postgresql + ``` + +10. 现在,重新启动 PostgreSQL 并重新侦听私有地址,即可重新启用迁移. + + 编辑`/etc/gitlab/gitlab.rb`并将配置**更改**为`true` : + + ``` + gitlab_rails['auto_migrate'] = true + ``` + + 保存文件并重新配置 GitLab: + + ``` + gitlab-ctl reconfigure + ``` + +11. 现在,PostgreSQL 服务器已设置为接受远程连接,请运行`netstat -plnt | grep 5432` `netstat -plnt | grep 5432` ,以确保 PostgreSQL 在端口`5432`上侦听**主**服务器的私有地址. + +12. 重新配置 GitLab 时会自动生成一个证书. 这将自动用于保护 PostgreSQL 流量免遭窃听,但是为了防止主动(中间人)攻击者, **辅助**节点需要证书的副本. 通过运行以下命令,在**主**节点上复制 PostgreSQL `server.crt`文件: + + ``` + cat ~gitlab-psql/data/server.crt + ``` + + 将输出复制到剪贴板或本地文件中. 设置**辅助**节点时将需要它! 证书不是敏感数据. + +### Step 2\. Configure the **secondary** server[](#step-2-configure-the-secondary-server "Permalink") + +1. SSH 到您的 GitLab **辅助**服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 停止应用程序服务器和 Sidekiq + + ``` + gitlab-ctl stop puma + gitlab-ctl stop sidekiq + ``` + + **注意:**此步骤很重要,因此在完全配置节点之前,我们不要尝试执行任何操作. +3. [检查](../../raketasks/maintenance.html)与**主**节点的 PostgreSQL 服务器的[TCP 连接](../../raketasks/maintenance.html) : + + ``` + gitlab-rake gitlab:tcp_check[,5432] + ``` + + **注意:**如果此步骤失败,则可能是您使用了错误的 IP 地址,或者防火墙可能阻止了对服务器的访问. 检查 IP 地址,并密切注意公用地址和专用地址之间的区别,并确保(如果存在防火墙)允许**次**节点连接到端口 5432 上的**主**节点. +4. 在**辅助**服务器上创建文件`server.crt` ,其中包含在**主**节点设置的最后一步中获得的内容: + + ``` + editor server.crt + ``` + +5. 在**辅助**节点上设置 PostgreSQL TLS 验证: + + 安装`server.crt`文件: + + ``` + install \ + -D \ + -o gitlab-psql \ + -g gitlab-psql \ + -m 0400 \ + -T server.crt ~gitlab-psql/.postgresql/root.crt + ``` + + 现在,PostgreSQL 将仅在验证 TLS 连接时识别该确切证书. 只能由有权访问私钥的人复制证书,该私钥**仅存**在于**主**节点上. + +6. 测试`gitlab-psql`用户可以连接到**主**节点的数据库(默认的 Omnibus 数据库名称为`gitlabhq_production` ): + + ``` + sudo \ + -u gitlab-psql /opt/gitlab/embedded/bin/psql \ + --list \ + -U gitlab_replicator \ + -d "dbname=gitlabhq_production sslmode=verify-ca" \ + -W \ + -h + ``` + + 出现提示时,输入您在第一步中为`gitlab_replicator`用户设置的密码. 如果所有方法均正常工作,则应该看到**主**节点数据库的列表. + + 此处连接失败表示 TLS 配置不正确. 确保**主**节点上`~gitlab-psql/data/server.crt`的内容与**辅助**节点上`~gitlab-psql/.postgresql/root.crt`的内容匹配. + +7. 配置 PostgreSQL 以启用 FDW 支持: + + 此步骤类似于我们配置**主**实例的方式. 我们需要启用它,以启用 FDW 支持,即使使用单个节点也是如此. + + 编辑`/etc/gitlab/gitlab.rb`并添加以下内容,将 IP 地址替换为适合您的网络配置的地址: + + ``` + ## + ## Geo Secondary role + ## - configure dependent flags automatically to enable Geo + ## + roles ['geo_secondary_role'] + + ## + ## Secondary address + ## - replace '' with the public or VPC address of your Geo secondary node + ## + postgresql['listen_address'] = '' + postgresql['md5_auth_cidr_addresses'] = ['/32'] + + ## + ## Database credentials password (defined previously in primary node) + ## - replicate same values here as defined in primary node + ## + postgresql['sql_user_password'] = '' + gitlab_rails['db_password'] = '' + + ## + ## Enable FDW support for the Geo Tracking Database (improves performance) + ## + geo_secondary['db_fdw'] = true + ``` + + 对于外部 PostgreSQL 实例,请参见[其他说明](external_database.html) . 如果您使以前的**主**节点重新联机以用作**辅助**节点,则还需要删除`roles ['geo_primary_role']`或`geo_primary_role['enable'] = true` . + +8. 重新配置 GitLab,以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +9. 重新启动 PostgreSQL 以使 IP 更改生效并再次重新配置: + + ``` + gitlab-ctl restart postgresql + gitlab-ctl reconfigure + ``` + + 最后的重新配置将提供 FDW 配置并启用它. + +### Step 3\. Initiate the replication process[](#step-3-initiate-the-replication-process "Permalink") + +在下面,我们提供了一个脚本,该脚本将**辅助**节点上的数据库连接到**主要**节点上的数据库,复制数据库,并创建流复制所需的文件. + +使用的目录是在 Omnibus 中设置的默认目录. 如果更改了任何默认值,请根据需要配置它,替换目录和路径. + +**警告:**确保在**辅助**服务器上运行此命令,因为它会在运行`pg_basebackup`之前删除所有 PostgreSQL 的数据. + +1. SSH 到您的 GitLab **辅助**服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 选择一个数据库友好名称,以供您的**辅助**节点用作复制插槽名称. 例如,如果您的域是`secondary.geo.example.com` ,则可以使用`secondary_example`作为插槽名称,如以下命令所示. + +3. 执行以下命令以开始备份/还原并开始复制 + + **警告:**每个 Geo **辅助**节点必须具有自己的唯一复制插槽名称. 在两个辅助节点之间使用相同的插槽名称将破坏 PostgreSQL 复制. + + ``` + gitlab-ctl replicate-geo-database \ + --slot-name= \ + --host= + ``` + + **注意:**复制插槽名称只能包含小写字母,数字和下划线字符. + + 出现提示时,输入第一步中为`gitlab_replicator`用户设置的*纯文本*密码. + + 此命令还带有许多其他选项. 您可以使用`--help`列出所有内容,但是这里有一些提示: + + * 如果 PostgreSQL 在非标准端口上侦听,则还要添加`--port=` . + * 如果数据库太大而无法在 30 分钟内传输,则需要增加超时,例如`--backup-timeout=3600`如果您希望初始复制花费一个小时以下的话. + * 通过`--sslmode=disable`可以完全跳过 PostgreSQL TLS 身份验证(例如,您知道网络路径是安全的,或者您使用的是站点到站点 VPN). 这**不是**通过公共互联网安全! + * 您可以在[PostgreSQL 文档中](https://s0www0postgresql0org.icopy.site/docs/11/libpq-ssl.html)阅读有关每个`sslmode`更多详细信息; 上面的说明均经过精心编写,以确保既能防御被动的窃听者,又能防御主动的"中间人"攻击者. + * 将`--slot-name`更改为要在**主**数据库上使用的复制插槽的名称. 该脚本将尝试自动创建复制插槽(如果不存在). + * If you’re repurposing an old server into a Geo **secondary** node, you’ll need to add `--force` to the command line. + * 如果不在生产机器中,则可以通过添加`--skip-backup`确保确实`--skip-backup`从而禁用备份步骤 + +复制过程现已完成. + +## PgBouncer support (optional)[](#pgbouncer-support-optional "Permalink") + +[PgBouncer](https://www.pgbouncer.org/)可以与 GitLab Geo 一起使用来合并 PostgreSQL 连接. 如果您在高可用性配置中使用 GitLab,且该群集的节点集群支持 Geo **主**节点,而另一个节点集群支持 Geo **辅助**节点,则建议使用 PgBouncer. 有关更多信息,请参见[Omnibus GitLab 的高可用性](../../postgresql/replication_and_failover.html) . + +为了使 Geo **辅助**节点能够与数据库前面的 PgBouncer 一起正常使用,它将需要一个单独的只读用户才能使[PostgreSQL FDW 查询](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html)起作用: + +1. 在**主要的**地理数据库上,以管理员用户身份在控制台上输入 PostgreSQL. 如果使用的是 Omnibus 管理的数据库,请登录到运行 PostgreSQL 数据库的**主**节点(默认的 Omnibus 数据库名称为`gitlabhq_production` ): + + ``` + sudo \ + -u gitlab-psql /opt/gitlab/embedded/bin/psql \ + -h /var/opt/gitlab/postgresql gitlabhq_production + ``` + +2. 然后创建只读用户: + + ``` + -- NOTE: Use the password defined earlier + CREATE USER gitlab_geo_fdw WITH password 'mypassword'; + GRANT CONNECT ON DATABASE gitlabhq_production to gitlab_geo_fdw; + GRANT USAGE ON SCHEMA public TO gitlab_geo_fdw; + GRANT SELECT ON ALL TABLES IN SCHEMA public TO gitlab_geo_fdw; + GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO gitlab_geo_fdw; + + -- Tables created by "gitlab" should be made read-only for "gitlab_geo_fdw" + -- automatically. + ALTER DEFAULT PRIVILEGES FOR USER gitlab IN SCHEMA public GRANT SELECT ON TABLES TO gitlab_geo_fdw; + ALTER DEFAULT PRIVILEGES FOR USER gitlab IN SCHEMA public GRANT SELECT ON SEQUENCES TO gitlab_geo_fdw; + ``` + +3. 在**辅助**节点上,更改`/etc/gitlab/gitlab.rb` : + + ``` + geo_postgresql['fdw_external_user'] = 'gitlab_geo_fdw' + ``` + +4. 保存文件并重新配置 GitLab 以应用更改: + + ``` + gitlab-ctl reconfigure + ``` + +## Troubleshooting[](#troubleshooting "Permalink") + +阅读[故障排除文档](troubleshooting.html) . \ No newline at end of file diff --git a/_book/docs/490.md b/_book/docs/490.md new file mode 100644 index 0000000000000000000000000000000000000000..6be995317e586e585037185cfc008f1e10cfd8f4 --- /dev/null +++ b/_book/docs/490.md @@ -0,0 +1,250 @@ +# Geo with external PostgreSQL instances + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/external_database.html](https://docs.gitlab.com/ee/administration/geo/replication/external_database.html) + +* [**Primary** node](#primary-node) + * [Configure the external database to be replicated](#configure-the-external-database-to-be-replicated) + * [Leverage your cloud provider’s tools to replicate the primary database](#leverage-your-cloud-providers-tools-to-replicate-the-primary-database) + * [Manually configure the primary database for replication](#manually-configure-the-primary-database-for-replication) +* [**Secondary** nodes](#secondary-nodes) + * [Manually configure the replica database](#manually-configure-the-replica-database) + * [Configure **secondary** application nodes to use the external read-replica](#configure-secondary-application-nodes-to-use-the-external-read-replica) + * [Configure the tracking database](#configure-the-tracking-database) + +# Geo with external PostgreSQL instances[](#geo-with-external-postgresql-instances-premium-only "Permalink") + +如果您使用的*不是由 Omnibus 管理*的 PostgreSQL 实例,则此文档很重要. 这包括 AWS RDS 之类的云托管实例,或者手动安装和配置的 PostgreSQL 实例. + +**注意:**我们强烈建议运行 Omnibus 管理的实例,因为它们是积极开发和测试的. 我们的目标是与大多数外部数据库(不受 Omnibus 管理)兼容,但我们不保证兼容性. + +## **Primary** node[](#primary-node "Permalink") + +1. SSH 到 GitLab **主**应用程序服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 编辑`/etc/gitlab/gitlab.rb`并为您的节点添加一个**唯一的** ID(任意值): + + ``` + # The unique identifier for the Geo node. + gitlab_rails['geo_node_name'] = '' + ``` + +3. 重新配置**主**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +4. 执行以下命令以将节点定义**为主**节点: + + ``` + gitlab-ctl set-geo-primary-node + ``` + + 该命令将使用您在`/etc/gitlab/gitlab.rb`定义的`external_url` . + +### Configure the external database to be replicated[](#configure-the-external-database-to-be-replicated "Permalink") + +要设置外部数据库,您可以: + +* 自己设置流复制(例如,在 AWS RDS 中). +* 手动执行 Omnibus 配置,如下所示. + +#### Leverage your cloud provider’s tools to replicate the primary database[](#leverage-your-cloud-providers-tools-to-replicate-the-primary-database "Permalink") + +假设您在使用 RDS 的 AWS EC2 上设置了一个主节点. 现在,您仅可以在其他区域中创建只读副本,复制过程将由 AWS 管理. 确保已根据需要设置了网络 ACL,子网和安全组,以便辅助应用程序节点可以访问数据库. + +以下说明详细说明了如何为常见的云提供程序创建只读副本: + +* Amazon RDS- [创建只读副本](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Create) +* PostgreSQL 的 Azure 数据库-在 PostgreSQL 的 Azure 数据库中[创建和管理只读副本](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal) + +设置只读副本后,您可以跳过以[配置辅助应用程序节点](#configure-secondary-application-nodes-to-use-the-external-read-replica) . + +#### Manually configure the primary database for replication[](#manually-configure-the-primary-database-for-replication "Permalink") + +[`geo_primary_role`](https://docs.gitlab.com/omnibus/roles/)通过更改`pg_hba.conf`和`postgresql.conf`来配置要复制的**主**节点数据库. 手动对外部数据库配置进行以下配置更改,并确保稍后重新启动 PostgreSQL 才能使更改生效: + +``` +## +## Geo Primary Role +## - pg_hba.conf +## +host all all /32 md5 +host replication gitlab_replicator /32 md5 +host all all /32 md5 +host replication gitlab_replicator /32 md5 +``` + +``` +## +## Geo Primary Role +## - postgresql.conf +## +wal_level = hot_standby +max_wal_senders = 10 +wal_keep_segments = 50 +max_replication_slots = 1 # number of secondary instances +hot_standby = on +``` + +## **Secondary** nodes[](#secondary-nodes "Permalink") + +### Manually configure the replica database[](#manually-configure-the-replica-database "Permalink") + +手动对外部副本数据库的`pg_hba.conf`和`postgresql.conf`进行以下配置更改,并确保之后重新启动 PostgreSQL 才能使更改生效: + +``` +## +## Geo Secondary Role +## - pg_hba.conf +## +host all all /32 md5 +host replication gitlab_replicator /32 md5 +host all all /24 md5 +``` + +``` +## +## Geo Secondary Role +## - postgresql.conf +## +wal_level = hot_standby +max_wal_senders = 10 +wal_keep_segments = 10 +hot_standby = on +``` + +### Configure **secondary** application nodes to use the external read-replica[](#configure-secondary-application-nodes-to-use-the-external-read-replica "Permalink") + +对于 Omnibus, [`geo_secondary_role`](https://docs.gitlab.com/omnibus/roles/)具有三个主要功能: + +1. 配置副本数据库. +2. 配置跟踪数据库. +3. 启用[地理日志光标](index.html#geo-log-cursor) (本节未介绍). + +要配置与外部只读副本数据库的连接并启用 Log Cursor,请执行以下操作: + +1. SSH 到 GitLab **辅助**应用程序服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 编辑`/etc/gitlab/gitlab.rb`并添加以下内容 + + ``` + ## + ## Geo Secondary role + ## - configure dependent flags automatically to enable Geo + ## + roles ['geo_secondary_role'] + + # note this is shared between both databases, + # make sure you define the same password in both + gitlab_rails['db_password'] = '' + + gitlab_rails['db_username'] = 'gitlab' + gitlab_rails['db_host'] = '' + + # Disable the bundled Omnibus PostgreSQL, since we are + # using an external PostgreSQL + postgresql['enable'] = false + ``` + +3. 保存文件并[重新配置 GitLab](../../restart_gitlab.html#omnibus-gitlab-reconfigure) + +### Configure the tracking database[](#configure-the-tracking-database "Permalink") + +**辅助**节点使用单独的 PostgreSQL 安装作为跟踪数据库,以跟踪复制状态并自动从潜在的复制问题中恢复. 设置了`roles ['geo_secondary_role']` Omnibus 会自动配置跟踪数据库. 如果要在 Omnibus 外部运行此数据库,请按照以下说明进行操作. + +如果您将云托管服务用于跟踪数据库,则可能需要向跟踪数据库用户授予其他角色(默认情况下,这是`gitlab_geo` ): + +* Amazon RDS 需要[`rds_superuser`](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Roles)角色. +* PostgreSQL 的 Azure 数据库需要[`azure_pg_admin`](https://docs.microsoft.com/en-us/azure/postgresql/howto-create-users#how-to-create-additional-admin-users-in-azure-database-for-postgresql)角色. + +跟踪数据库需要与**辅助**副本数据库建立[FDW](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html)连接以提高性能. + +如果您准备好将外部数据库用作跟踪数据库,请按照以下说明使用它: + +**注意:**如果您要将 AWS RDS 用作跟踪数据库,请确保其有权访问辅助数据库. 不幸的是,仅分配相同的安全组是不够的,因为出站规则不适用于 RDS PostgreSQL 数据库. 因此,您需要将入站规则显式添加到只读副本的安全组,以允许来自跟踪数据库的端口 5432 上的所有 TCP 通信. + +1. 通过手动更改与跟踪数据库关联的`pg_hba.conf` ,确保辅助节点可以与跟踪数据库通信. 请记住,之后要重新启动 PostgreSQL 才能使更改生效: + + ``` + ## + ## Geo Tracking Database Role + ## - pg_hba.conf + ## + host all all /32 md5 + host all all /32 md5 + ``` + +2. SSH 到 GitLab **辅助**服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +3. 使用 PostgreSQL 实例的机器的连接参数和凭据编辑`/etc/gitlab/gitlab.rb` : + + ``` + geo_secondary['db_username'] = 'gitlab_geo' + geo_secondary['db_password'] = '' + + geo_secondary['db_host'] = '' + geo_secondary['db_port'] = # change to the correct port + geo_secondary['db_fdw'] = true # enable FDW + geo_postgresql['enable'] = false # don't use internal managed instance + ``` + +4. 保存文件并[重新配置 GitLab](../../restart_gitlab.html#omnibus-gitlab-reconfigure) + +5. 运行跟踪数据库迁移: + + ``` + gitlab-rake geo:db:create + gitlab-rake geo:db:migrate + ``` + +6. 配置[PostgreSQL FDW](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html)连接和凭据: + + 将下面的脚本保存在一个文件中,例如. `/tmp/geo_fdw.sh`并修改连接参数以匹配您的环境. 执行它以建立 FDW 连接. + + ``` + #!/bin/bash + + # Secondary Database connection params: + DB_HOST="" + DB_NAME="gitlabhq_production" + DB_USER="gitlab" + DB_PASS="" + DB_PORT="5432" + + # Tracking Database connection params: + GEO_DB_HOST="" + GEO_DB_NAME="gitlabhq_geo_production" + GEO_DB_USER="gitlab_geo" + GEO_DB_PORT="5432" + + query_exec () { + gitlab-psql -h $GEO_DB_HOST -U $GEO_DB_USER -d $GEO_DB_NAME -p $GEO_DB_PORT -c "${1}" + } + + query_exec "CREATE EXTENSION postgres_fdw;" + query_exec "CREATE SERVER gitlab_secondary FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '${DB_HOST}', dbname '${DB_NAME}', port '${DB_PORT}');" + query_exec "CREATE USER MAPPING FOR ${GEO_DB_USER} SERVER gitlab_secondary OPTIONS (user '${DB_USER}', password '${DB_PASS}');" + query_exec "CREATE SCHEMA gitlab_secondary;" + query_exec "GRANT USAGE ON FOREIGN SERVER gitlab_secondary TO ${GEO_DB_USER};" + ``` + + **注意:**上面的脚本模板使用`gitlab-psql`因为它打算从 Geo 机器上执行,但是您可以将其更改为`psql`并从任何有权访问数据库的机器上运行. 我们还建议将`psql`用于 AWS RDS. +7. 保存文件并[重新启动 GitLab](../../restart_gitlab.html#omnibus-gitlab-restart) +8. Populate the FDW tables: + + ``` + gitlab-rake geo:db:refresh_foreign_tables + ``` \ No newline at end of file diff --git a/_book/docs/491.md b/_book/docs/491.md new file mode 100644 index 0000000000000000000000000000000000000000..b348e980d3f7811da0cc627dbfd2cb08623beb68 --- /dev/null +++ b/_book/docs/491.md @@ -0,0 +1,291 @@ +# Geo configuration + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/configuration.html](https://docs.gitlab.com/ee/administration/geo/replication/configuration.html) + +* [Configuring a new **secondary** node](#configuring-a-new-secondary-node) + * [Step 1\. Manually replicate secret GitLab values](#step-1-manually-replicate-secret-gitlab-values) + * [Step 2\. Manually replicate the **primary** node’s SSH host keys](#step-2-manually-replicate-the-primary-nodes-ssh-host-keys) + * [Step 3\. Add the **secondary** node](#step-3-add-the-secondary-node) + * [Step 4\. Enabling Hashed Storage](#step-4-enabling-hashed-storage) + * [Step 5\. (Optional) Configuring the **secondary** node to trust the **primary** node](#step-5-optional-configuring-the-secondary-node-to-trust-the-primary-node) + * [Step 6\. Enable Git access over HTTP/HTTPS](#step-6-enable-git-access-over-httphttps) + * [Step 7\. Verify proper functioning of the **secondary** node](#step-7-verify-proper-functioning-of-the-secondary-node) +* [Selective synchronization](#selective-synchronization) + * [Git operations on unreplicated repositories](#git-operations-on-unreplicated-repositories) +* [Upgrading Geo](#upgrading-geo) +* [Troubleshooting](#troubleshooting) + +# Geo configuration[](#geo-configuration-premium-only "Permalink") + +## Configuring a new **secondary** node[](#configuring-a-new-secondary-node "Permalink") + +**注意:**这是设置**辅助**地理节点的最后一步. 设置过程的各个阶段必须按记录的顺序完成. 在尝试此阶段中的步骤之前,请[完成所有之前的阶段](index.html#using-omnibus-gitlab) . + +配置**辅助**节点的基本步骤是: + +* 在**主**节点和**辅助**节点之间复制所需的配置. +* 在每个**辅助**节点上配置跟踪数据库. +* 在每个**辅助**节点上启动 GitLab. + +我们鼓励您先阅读所有步骤,然后再在测试/生产环境中执行这些步骤. + +**注意:** **不要**为**辅助**节点设置任何自定义身份验证. 这将由**主**节点处理. 任何需要访问" **管理区域"的**更改都必须在**主**节点中完成,因为**辅助**节点是只读副本. + +### Step 1\. Manually replicate secret GitLab values[](#step-1-manually-replicate-secret-gitlab-values "Permalink") + +GitLab 在`/etc/gitlab/gitlab-secrets.json`文件中存储了许多秘密值,这些秘密值在所有节点上都*必须*相同. 除非有一种方法可以在节点之间自动复制它们(请参阅[问题#3789](https://gitlab.com/gitlab-org/gitlab/-/issues/3789) ),否则必须将它们手动复制到**辅助**节点. + +1. SSH 进入**主**节点,并执行以下命令: + + ``` + sudo cat /etc/gitlab/gitlab-secrets.json + ``` + + 这将以 JSON 格式显示需要复制的机密. + +2. SSH 进入**辅助**节点并以`root`用户身份登录: + + ``` + sudo -i + ``` + +3. 备份所有现有机密: + + ``` + mv /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json.`date +%F` + ``` + +4. 将`/etc/gitlab/gitlab-secrets.json`从**主**节点复制到**辅助**节点,或在节点之间复制并粘贴文件内容: + + ``` + sudo editor /etc/gitlab/gitlab-secrets.json + + # paste the output of the `cat` command you ran on the primary + # save and exit + ``` + +5. 确保文件权限正确: + + ``` + chown root:root /etc/gitlab/gitlab-secrets.json + chmod 0600 /etc/gitlab/gitlab-secrets.json + ``` + +6. 重新配置**辅助**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + gitlab-ctl restart + ``` + +### Step 2\. Manually replicate the **primary** node’s SSH host keys[](#step-2-manually-replicate-the-primary-nodes-ssh-host-keys "Permalink") + +GitLab 与系统安装的 SSH 守护程序集成,指定一个用户(通常名为`git` )来处理所有访问请求. + +在[灾难恢复](../disaster_recovery/index.html)情况下,GitLab 系统管理员会将**辅助**节点升级为**主要**节点. **主**域的 DNS 记录也应更新为指向新的**主**节点(以前是**辅助**节点). 这样做可以避免更新 Git 遥控器和 API URL 的麻烦. + +由于 SSH 主机密钥不匹配,这将导致对新提升的**主**节点的所有 SSH 请求失败. 为防止这种情况,必须将主 SSH 主机密钥手动复制到**辅助**节点. + +1. SSH 进入**辅助**节点并以`root`用户身份登录: + + ``` + sudo -i + ``` + +2. 备份所有现有的 SSH 主机密钥: + + ``` + find /etc/ssh -iname ssh_host_* -exec cp {} {}.backup.`date +%F` \; + ``` + +3. 从**主**节点复制 OpenSSH 主机密钥: + + 如果可以使用**root**用户访问**主**节点: + + ``` + # Run this from the secondary node, change `` for the IP or FQDN of the server + scp root@:/etc/ssh/ssh_host_*_key* /etc/ssh + ``` + + 如果您只能通过具有`sudo`特权的用户访问: + + ``` + # Run this from your primary node: + sudo tar --transform 's/.*\///g' -zcvf ~/geo-host-key.tar.gz /etc/ssh/ssh_host_*_key* + + # Run this from your secondary node: + scp @:geo-host-key.tar.gz . + tar zxvf ~/geo-host-key.tar.gz -C /etc/ssh + ``` + +4. 在**辅助**节点上,确保文件权限正确: + + ``` + chown root:root /etc/ssh/ssh_host_*_key* + chmod 0600 /etc/ssh/ssh_host_*_key* + ``` + +5. 要验证密钥指纹是否匹配,请在两个节点上执行以下命令: + + ``` + for file in /etc/ssh/ssh_host_*_key; do ssh-keygen -lf $file; done + ``` + + 您应该获得与此输出类似的输出,并且两个节点上的输出应该相同: + + ``` + 1024 SHA256:FEZX2jQa2bcsd/fn/uxBzxhKdx4Imc4raXrHwsbtP0M root@serverhostname (DSA) + 256 SHA256:uw98R35Uf+fYEQ/UnJD9Br4NXUFPv7JAUln5uHlgSeY root@serverhostname (ECDSA) + 256 SHA256:sqOUWcraZQKd89y/QQv/iynPTOGQxcOTIXU/LsoPmnM root@serverhostname (ED25519) + 2048 SHA256:qwa+rgir2Oy86QI+PZi/QVR+MSmrdrpsuH7YyKknC+s root@serverhostname (RSA) + ``` + +6. 验证您对现有的私钥具有正确的公钥: + + ``` + # This will print the fingerprint for private keys: + for file in /etc/ssh/ssh_host_*_key; do ssh-keygen -lf $file; done + + # This will print the fingerprint for public keys: + for file in /etc/ssh/ssh_host_*_key.pub; do ssh-keygen -lf $file; done + ``` + + **注意:**私钥和公钥命令的输出应生成相同的指纹. +7. 在**辅助**节点上重新启动`sshd` : + + ``` + # Debian or Ubuntu installations + sudo service ssh reload + + # CentOS installations + sudo service sshd reload + ``` + +### Step 3\. Add the **secondary** node[](#step-3-add-the-secondary-node "Permalink") + +1. SSH 到您的 GitLab **辅助**服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 编辑`/etc/gitlab/gitlab.rb`并为您的节点添加一个**唯一的**名称. 在接下来的步骤中,您将需要此: + + ``` + # The unique identifier for the Geo node. + gitlab_rails['geo_node_name'] = '' + ``` + +3. 重新配置**辅助**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +4. 访问**主**节点的 **管理区>** 浏览器中的**地理位置** ( `/admin/geo/nodes` ). +5. 单击**新建节点**按钮. [![添加辅助节点](img/ce7d1dd63f95f0330b281fd577aaa8d4.png)](img/adding_a_secondary_node.png) +6. 填写**姓名**与`gitlab_rails['geo_node_name']`在`/etc/gitlab/gitlab.rb` . 这些值必须始终*完全*匹配,一个字符一个字符. +7. 在`/etc/gitlab/gitlab.rb` `external_url`填写**URL** . 这些值必须始终匹配,但是一个以`/`结尾而另一个不以`/`无关紧要. +8. **不要**选中" **这是主节点"**复选框. +9. (可选)选择**辅助**节点应复制的组或存储分片. 保留空白以复制所有内容. 阅读更多有关[选择性同步的信息](#selective-synchronization) . +10. 单击**添加节点**按钮以添加**辅助**节点. +11. SSH 到您的 GitLab **辅助**服务器并重新启动服务: + + ``` + gitlab-ctl restart + ``` + + 通过运行以下命令,检查您的地理设置是否存在任何常见问题: + + ``` + gitlab-rake gitlab:geo:check + ``` + +12. SSH 到您的**主**服务器中,并以 root 用户身份登录以验证**辅助**节点是否可以访问或您的地理设置存在任何常见问题: + + ``` + gitlab-rake gitlab:geo:check + ``` + +一旦添加到管理面板并重新启动, **辅助**节点将在称为**backfill**的过程中自动开始从**主**节点复制丢失的数据. 同时, **主**节点将开始将每个更改通知每个**辅助**节点,以便**辅助**节点可以立即对那些通知进行操作. + +确保**辅助**节点正在运行并且可访问. 您可以使用与**主**节点相同的凭据登录到**辅助**节点. + +### Step 4\. Enabling Hashed Storage[](#step-4-enabling-hashed-storage "Permalink") + +使用哈希存储可显着改善地理复制. 项目和组重命名不再需要节点之间的同步. + +1. 访问**主**节点的 **管理区>** 浏览器中的**设置>存储库** ( `/admin/application_settings/repository` ). +2. 在" **存储库存储"**部分中,选中" **对新创建和重命名的项目使用哈希存储路径"** . + +### Step 5\. (Optional) Configuring the **secondary** node to trust the **primary** node[](#step-5-optional-configuring-the-secondary-node-to-trust-the-primary-node "Permalink") + +如果您的**主**节点使用 CA 颁发的 HTTPS 证书,则可以安全地跳过此步骤. + +如果**主**节点正在使用自签名证书以获得*HTTPS*支持,则需要将该证书添加到**辅助**节点的信任存储中. 从**主**节点上检索证书,然后在**辅助**节点上遵循[这些说明](https://docs.gitlab.com/omnibus/settings/ssl.html) . + +### Step 6\. Enable Git access over HTTP/HTTPS[](#step-6-enable-git-access-over-httphttps "Permalink") + +Geo 通过 HTTP / HTTPS 同步存储库,因此需要启用此克隆方法. 导航 **管理区>** 在**主**节点上进行**设置** ( `/admin/application_settings/general` ),并将`Enabled Git access protocols`设置为`Both SSH and HTTP(S)`或`Only HTTP(S)` . + +### Step 7\. Verify proper functioning of the **secondary** node[](#step-7-verify-proper-functioning-of-the-secondary-node "Permalink") + +现在已配置**辅助**节点! + +您可以使用与**主**节点相同的凭据登录到**辅助**节点. 访问**辅助**节点的 **管理区>** 浏览器中的**Geo** ( `/admin/geo/nodes` ),以检查是否正确地将其标识为**辅助** Geo 节点,以及是否启用了 Geo. + +初始复制或"回填"可能仍在进行中. 您可以从浏览器中**主**节点的" **地理节点"**仪表板监视每个地理节点上的同步过程. + +[![Geo dashboard](img/337891c1885c756f35968127a8050c21.png)](img/geo_node_dashboard.png) + +如果您的安装无法正常工作,请查看[故障排除文档](troubleshooting.html) . + +仪表板中最明显的两个最明显的问题是: + +1. 数据库复制无法正常工作. +2. 实例间实例通知不起作用. 在这种情况下,可能是以下情况: + * 您正在使用自定义证书或自定义 CA(请参阅[故障排除文档](troubleshooting.html) ). + * 该实例已进行防火墙保护(请检查您的防火墙规则). + +请注意,禁用**辅助**节点将停止同步过程. + +请注意,如果在**主**节点上为多个存储库分片定制了`git_data_dirs`则必须在每个**辅助**节点上复制相同的配置. + +将您的用户指向["使用地理服务器"指南](using_a_geo_server.html) . + +当前,这是同步的: + +* Git 存储库. +* Wikis. +* LFS 对象. +* 问题,合并请求,摘要和评论附件. +* 用户,组和项目化身. + +## Selective synchronization[](#selective-synchronization "Permalink") + +Geo 支持选择性同步,这使管理员可以选择**辅助**节点应同步哪些项目. 可以按组或按存储碎片选择项目的子集. 前者是复制属于用户子集的数据的理想选择,而后者更适合将 Geo 逐步推广到大型 GitLab 实例. + +重要的是要注意选择性同步: + +1. 不限制来自**辅助**节点的权限. +2. 不从**辅助**节点隐藏项目元数据. + * 由于 Geo 当前依赖于 PostgreSQL 复制,因此所有项目元数据都将复制到**辅助**节点,但是尚未选择的存储库将为空. +3. 不减少为地理事件日志生成的事件数. + * 只要存在任何**辅助**节点, **主**节点都会生成事件. 选择性同步限制是在**辅助**节点而非**主**节点上实现的. + +### Git operations on unreplicated repositories[](#git-operations-on-unreplicated-repositories "Permalink") + +在 HTTP(S)的 GitLab 12.10 和 SSH 的 GitLab 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2562) . + +存在于**主**节点上但不存在于**辅助**节点上的存储库支持通过 HTTP(S)和 SSH 进行 Git 克隆,拉入和推送操作. 在以下情况下可能会发生这种情况: + +* 选择性同步不包括附加到存储库的项目. +* 存储库正在积极地复制,但尚未完成. + +## Upgrading Geo[](#upgrading-geo "Permalink") + +请参阅[更新地理节点文档](updating_the_geo_nodes.html) . + +## Troubleshooting[](#troubleshooting "Permalink") + +请参阅[故障排除文档](troubleshooting.html) . \ No newline at end of file diff --git a/_book/docs/492.md b/_book/docs/492.md new file mode 100644 index 0000000000000000000000000000000000000000..6dfc116856f45abc33eea8313c1d26ce505d57db --- /dev/null +++ b/_book/docs/492.md @@ -0,0 +1,22 @@ +# Using a Geo Server + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/using_a_geo_server.html](https://docs.gitlab.com/ee/administration/geo/replication/using_a_geo_server.html) + +# Using a Geo Server[](#using-a-geo-server-premium-only "Permalink") + +设置[数据库复制并配置 Geo 节点后](index.html#setup-instructions) ,请像使用普通的独立 GitLab 实例一样使用最近的 GitLab 节点. + +在[GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3 中[引入](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/)了直接推送到**辅助**节点(对于 HTTP,包括 Git LFS 的 SSH). + +推送到**辅助**节点时将看到的输出示例: + +``` +$ git push +remote: +remote: You're pushing to a Geo secondary. We'll help you by proxying this +remote: request to the primary: +remote: +remote: ssh://git@primary.geo/user/repo.git +remote: +Everything up-to-date +``` \ No newline at end of file diff --git a/_book/docs/493.md b/_book/docs/493.md new file mode 100644 index 0000000000000000000000000000000000000000..26cf582636885683777224a1919cafb54fd0d8bf --- /dev/null +++ b/_book/docs/493.md @@ -0,0 +1,63 @@ +# Updating the Geo nodes + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/updating_the_geo_nodes.html](https://docs.gitlab.com/ee/administration/geo/replication/updating_the_geo_nodes.html) + +* [Version specific update steps](#version-specific-update-steps) +* [General update steps](#general-update-steps) + * [Check status after updating](#check-status-after-updating) + +# Updating the Geo nodes[](#updating-the-geo-nodes-premium-only "Permalink") + +更新地理节点涉及执行: + +1. [特定](#version-specific-update-steps)于版本的[更新步骤](#version-specific-update-steps) ,具体取决于要与之进行更新的版本. +2. [常规更新步骤](#general-update-steps) ,适用于所有更新. + +## Version specific update steps[](#version-specific-update-steps "Permalink") + +根据您要更新或更新的 Geo 版本,可能会有不同的步骤. + +* [Updating to GitLab 12.9](version_specific_updates.html#updating-to-gitlab-129) +* [Updating to GitLab 12.7](version_specific_updates.html#updating-to-gitlab-127) +* [Updating to GitLab 12.2](version_specific_updates.html#updating-to-gitlab-122) +* [Updating to GitLab 12.1](version_specific_updates.html#updating-to-gitlab-121) +* [Updating to GitLab 12.0](version_specific_updates.html#updating-to-gitlab-120) +* [Updating to GitLab 11.11](version_specific_updates.html#updating-to-gitlab-1111) +* [Updating to GitLab 10.8](version_specific_updates.html#updating-to-gitlab-108) +* [Updating to GitLab 10.6](version_specific_updates.html#updating-to-gitlab-106) +* [Updating to GitLab 10.5](version_specific_updates.html#updating-to-gitlab-105) +* [Updating to GitLab 10.3](version_specific_updates.html#updating-to-gitlab-103) +* [Updating to GitLab 10.2](version_specific_updates.html#updating-to-gitlab-102) +* [Updating to GitLab 10.1](version_specific_updates.html#updating-to-gitlab-101) +* [Updating to GitLab 10.0](version_specific_updates.html#updating-to-gitlab-100) +* [Updating from GitLab 9.3 or older](version_specific_updates.html#updating-from-gitlab-93-or-older) +* [Updating to GitLab 9.0](version_specific_updates.html#updating-to-gitlab-90) + +## General update steps[](#general-update-steps "Permalink") + +**注意:**这些常规更新步骤不适用于[高可用性部署](https://docs.gitlab.com/omnibus/update/README.html) ,并且会导致停机. 如果要避免停机,请考虑使用[零停机更新](https://docs.gitlab.com/omnibus/update/README.html) . + +要在发布新的 GitLab 版本时更新 Geo 节点,请更新**主**节点和所有**辅助**节点: + +1. **Optional:** [Pause replication on each **secondary** node.](./index.html#pausing-and-resuming-replication) +2. 登录到**主**节点. +3. [Update GitLab on the **primary** node using Omnibus](https://docs.gitlab.com/omnibus/update/README.html). +4. 登录到每个**辅助**节点. +5. [Update GitLab on each **secondary** node using Omnibus](https://docs.gitlab.com/omnibus/update/README.html). +6. 如果您在步骤 1 中暂停了复制,则[在每个**辅助**节点上继续复制](./index.html#pausing-and-resuming-replication) +7. [测试](#check-status-after-updating) **主**节点和**辅助**节点,并检查每个节点的版本. + +### Check status after updating[](#check-status-after-updating "Permalink") + +现在,更新过程已完成,您可能要检查一切是否正常运行: + +1. 在所有节点上运行 Geo Rake 任务,所有内容应为绿色: + + ``` + sudo gitlab-rake gitlab:geo:check + ``` + +2. 检查**主**节点的地理仪表板是否有任何错误. +3. 通过将代码推送到**主**节点来测试数据复制,并查看**辅助**节点是否接收到该复制. + +如果您遇到任何问题,请查阅《 [地理位置疑难解答指南》](troubleshooting.html) . \ No newline at end of file diff --git a/_book/docs/494.md b/_book/docs/494.md new file mode 100644 index 0000000000000000000000000000000000000000..f120b771772d88d699fbe5a1bf649a9fad3b0799 --- /dev/null +++ b/_book/docs/494.md @@ -0,0 +1,64 @@ +# Geo with Object storage + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/object_storage.html](https://docs.gitlab.com/ee/administration/geo/replication/object_storage.html) + +* [Enabling GitLab managed object storage replication](#enabling-gitlab-managed-object-storage-replication) +* [Third-party replication services](#third-party-replication-services) + +# Geo with Object storage[](#geo-with-object-storage-premium-only "Permalink") + +Geo 可与对象存储(AWS S3 或其他兼容的对象存储)结合使用. + +当前, **辅助**节点可以使用以下任一方式: + +* 与**主**节点相同的存储桶. +* 复制的存储桶. + +具有: + +* GitLab 管理复制,遵循[启用 GitLab 复制](#enabling-gitlab-managed-object-storage-replication) . +* 第三方服务管理复制,请遵循[第三方复制服务](#third-party-replication-services) . + +[Read more about using object storage with GitLab](../../object_storage.html). + +## Enabling GitLab managed object storage replication[](#enabling-gitlab-managed-object-storage-replication "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/10586) . + +**警告:**这是[**Beta 版**功能](https://about.gitlab.com/handbook/product/#beta) ,尚未准备好用于任何规模的生产. + +**辅助**节点可以复制存储在**主**节点上的文件,而不管它们是存储在本地文件系统还是对象存储中. + +要启用 GitLab 复制,您必须: + +1. 去 **管理区>** **地理位置** . +2. 在**辅助**节点上按**编辑** . +3. 启用" **允许此辅助节点在对象存储上复制内容"**复选框. + +对于 LFS,请按照文档[设置 LFS 对象存储](../../lfs/index.html#storing-lfs-objects-in-remote-object-storage) . + +对于 CI 作业工件,有类似的文档可以配置[作业工件对象存储](../../job_artifacts.html#using-object-storage) + +对于用户上传,有类似的文档可配置[上传对象存储](../../uploads.html#using-object-storage-core-only) + +如果要将**主**节点的文件迁移到对象存储,则可以通过以下几种方式配置**辅助**节点: + +* 使用完全相同的对象存储. +* 使用单独的对象存储,但可以利用对象存储解决方案的内置复制. +* 使用单独的对象存储,并启用" **允许此辅助节点在对象存储上复制内容"**设置. + +GitLab 当前不支持以下两种情况: + +* **主**节点使用本地存储. +* **辅助**节点使用对象存储. + +## Third-party replication services[](#third-party-replication-services "Permalink") + +使用 Amazon S3 时,您可以使用[CRR](https://docs.aws.amazon.com/AmazonS3/latest/dev/crr.html)在**主**节点使用的存储桶和**辅助**节点使用的存储桶之间进行自动复制. + +如果您使用的是 Google Cloud Storage,请考虑使用[Multi-Regional Storage](https://cloud.google.com/storage/docs/storage-classes#multi-regional) . 或者,您可以使用" [存储传输服务"](https://cloud.google.com/storage-transfer/docs/) ,尽管该[服务](https://cloud.google.com/storage-transfer/docs/)仅支持每日同步. + +对于手动同步,或由`cron`安排,请查看: + +* [`s3cmd sync`](https://s3tools.org/s3cmd-sync) +* [`gsutil rsync`](https://cloud.google.com/storage/docs/gsutil/commands/rsync) \ No newline at end of file diff --git a/_book/docs/495.md b/_book/docs/495.md new file mode 100644 index 0000000000000000000000000000000000000000..8d922f18c840c84f70ce1f016ca9eb5e294c13f6 --- /dev/null +++ b/_book/docs/495.md @@ -0,0 +1,96 @@ +# Docker Registry for a secondary node + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/docker_registry.html](https://docs.gitlab.com/ee/administration/geo/replication/docker_registry.html) + +* [Storage support](#storage-support) +* [Replicating Docker Registry](#replicating-docker-registry) + * [Configure **primary** node](#configure-primary-node) + * [Configure **secondary** node](#configure-secondary-node) + * [Verify replication](#verify-replication) + +# Docker Registry for a secondary node[](#docker-registry-for-a-secondary-node-premium-only "Permalink") + +您可以在**次要** Geo 节点上设置一个[Docker Registry](https://s0docs0docker0com.icopy.site/registry/) ,以镜像**主** Geo 节点上的[Docker Registry](https://s0docs0docker0com.icopy.site/registry/) . + +## Storage support[](#storage-support "Permalink") + +Docker Registry 当前支持几种类型的存储. 如果您在**主**节点上为 Docker 注册表选择分布式存储( `azure` , `gcs` , `s3` , `swift`或`oss` ),则也可以将相同的存储用于**辅助** Docker 注册表. 有关更多信息,请阅读部署注册表时的[负载平衡注意事项](https://s0docs0docker0com.icopy.site/registry/deploying/) ,以及如何为 GitLab 的集成[Container Registry](../../packages/container_registry.html#use-object-storage)设置存储驱动程序. + +## Replicating Docker Registry[](#replicating-docker-registry "Permalink") + +您可以启用与存储无关的复制,以便将其用于云或本地存储. 每当将新映像推送到**主**节点时,每个**辅助**节点都会将其拖到其自己的容器存储库中. + +要配置 Docker Registry 复制: + +1. 配置[**主**节点](#configure-primary-node) . +2. 配置[**辅助**节点](#configure-secondary-node) . +3. 验证 Docker Registry [复制](#verify-replication) . + +### Configure **primary** node[](#configure-primary-node "Permalink") + +在执行下一步之前,请确保已设置 Container Registry 并在**主**节点上工作. + +我们需要使 Docker Registry 将通知事件发送到**主**节点. + +1. SSH 到您的 GitLab **主**服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['notifications'] = [ + { + 'name' => 'geo_event', + 'url' => 'https://example.com/api/v4/container_registry_event/events', + 'timeout' => '500ms', + 'threshold' => 5, + 'backoff' => '1s', + 'headers' => { + 'Authorization' => [''] + } + } + ] + ``` + + **注意:**将``替换为以字母开头的区分大小写的字母数字字符串. 您可以使用`< /dev/urandom tr -dc _A-Zaz-0-9 | head -c 32 | sed "s/^[0-9]*//"; echo`生成一个`< /dev/urandom tr -dc _A-Zaz-0-9 | head -c 32 | sed "s/^[0-9]*//"; echo` `< /dev/urandom tr -dc _A-Zaz-0-9 | head -c 32 | sed "s/^[0-9]*//"; echo`**注意:**如果使用外部注册表(而不是与 GitLab 集成的注册表),则必须将这些设置自己添加到其配置中. 在这种情况下,您还必须在`/etc/gitlab/gitlab.rb`文件的`registry.notification_secret`部分中指定通知密钥.**注意:**如果使用 GitLab HA,则还必须在`/etc/gitlab/gitlab.rb`文件的`registry.notification_secret`部分中为每个 Web 节点指定通知密钥. +3. 重新配置**主**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +### Configure **secondary** node[](#configure-secondary-node "Permalink") + +Make sure you have Container Registry set up and working on the **secondary** node before following the next steps. + +在希望看到复制的 Docker 映像的每个**辅助**节点上,应执行以下步骤. + +因为我们需要允许**辅助**节点与**主**节点容器注册表安全通信,所以我们需要为所有节点使用单个密钥对. **辅助**节点将使用此密钥来生成短暂的 JWT,该 JWT 具有仅拉功能,可以访问**主**节点 Container Registry. + +1. SSH 进入**辅助**节点并以`root`用户身份登录: + + ``` + sudo -i + ``` + +2. 将`/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key`从**主**节点复制到**辅助**节点. + +3. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitlab_rails['geo_registry_replication_enabled'] = true + gitlab_rails['geo_registry_replication_primary_api_url'] = 'https://primary.example.com:5050/' # Primary registry address, it will be used by the secondary node to directly communicate to primary registry + ``` + +4. 重新配置**辅助**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +### Verify replication[](#verify-replication "Permalink") + +要验证 Container Registry 复制是否正常工作,请转到 **管理区>** **辅助**节点上的**地理位置** ( `/admin/geo/nodes` ). 初始复制或"回填"可能仍在进行中. 您可以从浏览器中**主**节点的" **地理节点"**仪表板监视每个地理节点上的同步过程. \ No newline at end of file diff --git a/_book/docs/496.md b/_book/docs/496.md new file mode 100644 index 0000000000000000000000000000000000000000..d9c880ff16c3813c37a5feecbc8ef08864e36ed9 --- /dev/null +++ b/_book/docs/496.md @@ -0,0 +1,404 @@ +# Geo for multiple nodes + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/multiple_servers.html](https://docs.gitlab.com/ee/administration/geo/replication/multiple_servers.html) + +* [Architecture overview](#architecture-overview) +* [Redis and PostgreSQL for multiple nodes](#redis-and-postgresql-for-multiple-nodes) +* [Prerequisites: Two working GitLab multi-node clusters](#prerequisites-two-working-gitlab-multi-node-clusters) +* [Configure the GitLab cluster to be the **primary** node](#configure-the-gitlab-cluster-to-be-the-primary-node) + * [Step 1: Configure the **primary** frontend servers](#step-1-configure-the-primary-frontend-servers) + * [Step 2: Configure the **primary** database](#step-2-configure-the-primary-database) +* [Configure a **secondary** node](#configure-a-secondary-node) + * [Step 1: Configure the Redis and Gitaly services on the **secondary** node](#step-1-configure-the-redis-and-gitaly-services-on-the-secondary-node) + * [Step 2: Configure the main read-only replica PostgreSQL database on the **secondary** node](#step-2-configure-the-main-read-only-replica-postgresql-database-on-the-secondary-node) + * [Step 3: Configure the tracking database on the **secondary** node](#step-3-configure-the-tracking-database-on-the-secondary-node) + * [Step 4: Configure the frontend application servers on the **secondary** node](#step-4-configure-the-frontend-application-servers-on-the-secondary-node) + * [Step 5: Set up the LoadBalancer for the **secondary** node](#step-5-set-up-the-loadbalancer-for-the-secondary-node) + * [Step 6: Configure the backend application servers on the **secondary** node](#step-6-configure-the-backend-application-servers-on-the-secondary-node) + +# Geo for multiple nodes[](#geo-for-multiple-nodes-premium-only "Permalink") + +本文档介绍了用于在多节点配置中运行 Geo 的最小参考架构. 如果您的多节点设置与所描述的不同,则可以根据需要调整这些说明. + +## Architecture overview[](#architecture-overview "Permalink") + +[![Geo multi-node diagram](img/e28a59687a00b33f8174f2bcba18ac5d.png)](../../high_availability/img/geo-ha-diagram.png) + +*[diagram source - GitLab employees only](https://docs.google.com/drawings/d/1z0VlizKiLNXVVVaERFwgsIOuEgjcUqDTWPdQYsE7Z4c/edit)* + +上面的拓扑假定**主要**和**辅助**地理集群位于两个单独的位置,位于它们自己的具有专用 IP 地址的虚拟网络上. 网络配置为使一个地理位置内的所有计算机都可以使用其专用 IP 地址相互通信. 给出的 IP 地址只是示例,可能会因部署的网络拓扑而有所不同. + +在上述示例中,访问这两个 Geo 部署的唯一外部方法是通过 HTTPS 分别位于`gitlab.us.example.com`和`gitlab.eu.example.com` . + +**注意:** **主要**和**辅助** Geo 部署必须能够通过 HTTPS 相互通信. + +## Redis and PostgreSQL for multiple nodes[](#redis-and-postgresql-for-multiple-nodes "Permalink") + +地理位置支持: + +* Redis 和 PostgreSQL 在**为主**节点上配置了多个节点. +* Redis 在为多个节点配置的**辅助**节点上. + +**注意:** [已计划](https://gitlab.com/groups/gitlab-org/-/epics/2536)在多节点配置中在**辅助**节点上支持 PostgreSQL. + +由于为 PostgreSQL 和 Redis 设置此配置涉及额外的复杂性,因此此 Geo 多节点文档未涵盖该配置. + +有关使用 omnibus 软件包设置多节点 PostgreSQL 集群和 Redis 集群的更多信息,请分别参见[PostgreSQL](../../postgresql/replication_and_failover.html)和[Redis](../../redis/replication_and_failover.html)的多节点文档. + +**注意:**可以将云托管服务用于 PostgreSQL 和 Redis,但这不在本文档的范围之内. + +## Prerequisites: Two working GitLab multi-node clusters[](#prerequisites-two-working-gitlab-multi-node-clusters "Permalink") + +一个群集将充当**主**节点. 使用[GitLab 多节点文档](../../reference_architectures/index.html)进行设置. 如果您已经有一个正在使用的工作 GitLab 实例,则可以将其用作**primary** . + +The second cluster will serve as the **secondary** node. Again, use the [GitLab multi-node documentation](../../reference_architectures/index.html) to set this up. It’s a good idea to log in and test it, however, note that its data will be wiped out as part of the process of replicating from the **primary**. + +## Configure the GitLab cluster to be the **primary** node[](#configure-the-gitlab-cluster-to-be-the-primary-node "Permalink") + +通过以下步骤,GitLab 集群可以用**作主**节点. + +### Step 1: Configure the **primary** frontend servers[](#step-1-configure-the-primary-frontend-servers "Permalink") + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下内容: + + ``` + ## + ## Enable the Geo primary role + ## + roles ['geo_primary_role'] + + ## + ## The unique identifier for the Geo node. + ## + gitlab_rails['geo_node_name'] = '' + + ## + ## Disable automatic migrations + ## + gitlab_rails['auto_migrate'] = false + ``` + +进行这些更改后,请[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**注意:**在正常的 GitLab 多节点设置过程中,应已在应用程序服务器上禁用 PostgreSQL 和 Redis,并且已配置从应用程序服务器到后端服务器上的那些服务的连接. 请参阅[PostgreSQL](../../postgresql/replication_and_failover.html#configuring-the-application-nodes)和[Redis 的](../../redis/replication_and_failover.html#example-configuration-for-the-gitlab-application)多节点配置文档. + +### Step 2: Configure the **primary** database[](#step-2-configure-the-primary-database "Permalink") + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下内容: + + ``` + ## + ## Configure the Geo primary role and the PostgreSQL role + ## + roles ['geo_primary_role', 'postgres_role'] + ``` + +## Configure a **secondary** node[](#configure-a-secondary-node "Permalink") + +**辅助**群集与任何其他 GitLab 多节点群集相似,但有两个主要区别: + +* 主 PostgreSQL 数据库是**主**节点的 PostgreSQL 数据库的只读副本. +* **辅助**集群还有一个单独的 PostgreSQL 数据库,称为"跟踪数据库",该数据库跟踪各种资源的同步状态. + +因此,我们将一个接一个地设置多节点组件,并包括与常规多节点设置的偏差. 但是,我们强烈建议您首先配置一个全新的群集,就像它不是地理设置一样,以便可以对其进行测试和验证. 只有这样,才可以对其进行修改以用作 Geo **辅助对象** . 这有助于分离与地理设置无关的问题. + +### Step 1: Configure the Redis and Gitaly services on the **secondary** node[](#step-1-configure-the-redis-and-gitaly-services-on-the-secondary-node "Permalink") + +再次使用非 Geo 多节点文档配置以下服务: + +* 为多个节点[配置 Redis for GitLab](../../redis/replication_and_failover.html#example-configuration-for-the-gitlab-application) . +* [Gitaly](../../high_availability/gitaly.html) ,它将存储从**主**节点同步的数据. + +**注意:** [NFS](../../high_availability/nfs.html)可以代替 Gitaly 使用,但不建议使用. + +### Step 2: Configure the main read-only replica PostgreSQL database on the **secondary** node[](#step-2-configure-the-main-read-only-replica-postgresql-database-on-the-secondary-node "Permalink") + +**注意:**以下文档假定数据库将仅在单个节点上运行. [当前不支持](https://gitlab.com/groups/gitlab-org/-/epics/2536) **辅助**节点上的多节点 PostgreSQL. + +配置[**辅助**数据库](database.html)作为**主**数据库的一个只读副本. 使用以下内容作为指导. + +1. 为数据库用户生成所需密码的 MD5 哈希,GitLab 应用程序将使用该密码来访问只读副本数据库: + + 请注意,用户名(默认情况下为`gitlab` )已合并到哈希中. + + ``` + gitlab-ctl pg-password-md5 gitlab + # Enter password: + # Confirm password: + # fca0b89a972d69f00eb3ec98a5838484 + ``` + + 在下一步中使用此哈希值填写`` . + +2. 在副本数据库计算机中编辑`/etc/gitlab/gitlab.rb` ,并添加以下内容: + + ``` + ## + ## Configure the Geo secondary role and the PostgreSQL role + ## + roles ['geo_secondary_role', 'postgres_role'] + + ## + ## Secondary address + ## - replace '' with the public or VPC address of your Geo secondary node + ## - replace '' with the public or VPC address of your Geo tracking database node + ## + postgresql['listen_address'] = '' + postgresql['md5_auth_cidr_addresses'] = ['/32', '/32'] + + ## + ## Database credentials password (defined previously in primary node) + ## - replicate same values here as defined in primary node + ## + postgresql['sql_user_password'] = '' + gitlab_rails['db_password'] = '' + + ## + ## When running the Geo tracking database on a separate machine, disable it + ## here and allow connections from the tracking database host. And ensure + ## the tracking database IP is in postgresql['md5_auth_cidr_addresses'] above. + ## + geo_postgresql['enable'] = false + + ## + ## Disable `geo_logcursor` service so Rails doesn't get configured here + ## + geo_logcursor['enable'] = false + ``` + +进行这些更改后,请[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +如果使用外部 PostgreSQL 实例,另请参阅使用外部 PostgreSQL 实例的[Geo](external_database.html) . + +### Step 3: Configure the tracking database on the **secondary** node[](#step-3-configure-the-tracking-database-on-the-secondary-node "Permalink") + +**注意:**本文档假定跟踪数据库将仅在一台计算机上运行,​​而不是作为 PostgreSQL 集群运行. + +配置跟踪数据库. + +1. Generate an MD5 hash of the desired password for the database user that the GitLab application will use to access the tracking database: + + 请注意,用户名(默认为`gitlab_geo` )已合并到哈希中. + + ``` + gitlab-ctl pg-password-md5 gitlab_geo + # Enter password: + # Confirm password: + # fca0b89a972d69f00eb3ec98a5838484 + ``` + + 在下一步中,使用此哈希值填写`` . + +2. 在跟踪数据库计算机中编辑`/etc/gitlab/gitlab.rb` ,并添加以下内容: + + ``` + ## + ## Enable the Geo secondary tracking database + ## + geo_postgresql['enable'] = true + geo_postgresql['listen_address'] = '' + geo_postgresql['sql_user_password'] = '' + + ## + ## Configure FDW connection to the replica database + ## + geo_secondary['db_fdw'] = true + geo_postgresql['fdw_external_password'] = '' + geo_postgresql['md5_auth_cidr_addresses'] = ['/32'] + gitlab_rails['db_host'] = '' + + # Prevent reconfigure from attempting to run migrations on the replica DB + gitlab_rails['auto_migrate'] = false + + ## + ## Disable all other services that aren't needed, since we don't have a role + ## that does this. + ## + alertmanager['enable'] = false + consul['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + node_exporter['enable'] = false + pgbouncer_exporter['enable'] = false + postgresql['enable'] = false + prometheus['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + repmgr['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + ``` + +进行这些更改后,请[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +如果使用外部 PostgreSQL 实例,另请参阅使用外部 PostgreSQL 实例的[Geo](external_database.html) . + +### Step 4: Configure the frontend application servers on the **secondary** node[](#step-4-configure-the-frontend-application-servers-on-the-secondary-node "Permalink") + +在体系结构概述中,有两台机器运行 GitLab 应用程序服务. 这些服务在配置中有选择地启用. + +在[为多个节点配置 GitLab](../../high_availability/gitlab.html)之后, [配置](../../high_availability/gitlab.html)应用程序服务器,然后进行以下修改: + +1. 在**辅助**集群中的每个应用程序服务器上编辑`/etc/gitlab/gitlab.rb` ,并添加以下内容: + + ``` + ## + ## Enable the Geo secondary role + ## + roles ['geo_secondary_role', 'application_role'] + + ## + ## The unique identifier for the Geo node. + ## + gitlab_rails['geo_node_name'] = '' + + ## + ## Disable automatic migrations + ## + gitlab_rails['auto_migrate'] = false + + ## + ## Configure the connection to the tracking DB. And disable application + ## servers from running tracking databases. + ## + geo_secondary['db_host'] = '' + geo_secondary['db_password'] = '' + geo_postgresql['enable'] = false + + ## + ## Configure connection to the streaming replica database, if you haven't + ## already + ## + gitlab_rails['db_host'] = '' + gitlab_rails['db_password'] = '' + + ## + ## Configure connection to Redis, if you haven't already + ## + gitlab_rails['redis_host'] = '' + gitlab_rails['redis_password'] = '' + + ## + ## If you are using custom users not managed by Omnibus, you need to specify + ## UIDs and GIDs like below, and ensure they match between servers in a + ## cluster to avoid permissions issues + ## + user['uid'] = 9000 + user['gid'] = 9000 + web_server['uid'] = 9001 + web_server['gid'] = 9001 + registry['uid'] = 9002 + registry['gid'] = 9002 + ``` + +**注意:**如果使用 omnibus 软件包设置了 PostgreSQL 集群,并且设置了`postgresql['sql_user_password'] = 'md5 digest of secret'`设置,请记住`gitlab_rails['db_password']`和`geo_secondary['db_password']`上面提到的包含明文密码. 这用于让 Rails 服务器连接到数据库.**注意:**确保在远程数据库的`postgresql['md5_auth_cidr_addresses']`设置中列出了当前节点 IP. + +进行这些更改后,请[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +在辅助服务器上,将启用以下 GitLab 前端服务: + +* `geo-logcursor` +* `gitlab-pages` +* `gitlab-workhorse` +* `logrotate` +* `nginx` +* `registry` +* `remote-syslog` +* `sidekiq` +* `puma` + +通过在前端应用程序服务器上运行`sudo gitlab-ctl status`来验证这些服务. + +### Step 5: Set up the LoadBalancer for the **secondary** node[](#step-5-set-up-the-loadbalancer-for-the-secondary-node "Permalink") + +在这种拓扑中,每个地理位置都需要一个负载平衡器,以将流量路由到应用程序服务器. + +有关更多信息,请参见[具有多个节点的 GitLab 的 Load Balancer](../../high_availability/load_balancer.html) . + +### Step 6: Configure the backend application servers on the **secondary** node[](#step-6-configure-the-backend-application-servers-on-the-secondary-node "Permalink") + +上面的最小参考体系结构图显示了在同一台计算机上一起运行的所有应用程序服务. 但是,对于多个节点,我们[强烈建议单独运行所有服务](../../reference_architectures/index.html) . + +例如,可以将 Sidekiq 服务器配置为与上面的前端应用程序服务器类似,但要进行一些更改以仅运行`sidekiq`服务: + +1. 在**辅助**群集中的每个 Sidekiq 服务器上编辑`/etc/gitlab/gitlab.rb` ,并添加以下内容: + + ``` + ## + ## Enable the Geo secondary role + ## + roles ['geo_secondary_role'] + + ## + ## Enable the Sidekiq service + ## + sidekiq['enable'] = true + + ## + ## Ensure unnecessary services are disabled + ## + alertmanager['enable'] = false + consul['enable'] = false + geo_logcursor['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + node_exporter['enable'] = false + pgbouncer_exporter['enable'] = false + postgresql['enable'] = false + prometheus['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + repmgr['enable'] = false + puma['enable'] = false + + ## + ## The unique identifier for the Geo node. + ## + gitlab_rails['geo_node_name'] = '' + + ## + ## Disable automatic migrations + ## + gitlab_rails['auto_migrate'] = false + + ## + ## Configure the connection to the tracking DB. And disable application + ## servers from running tracking databases. + ## + geo_secondary['db_host'] = '' + geo_secondary['db_password'] = '' + geo_postgresql['enable'] = false + + ## + ## Configure connection to the streaming replica database, if you haven't + ## already + ## + gitlab_rails['db_host'] = '' + gitlab_rails['db_password'] = '' + + ## + ## Configure connection to Redis, if you haven't already + ## + gitlab_rails['redis_host'] = '' + gitlab_rails['redis_password'] = '' + + ## + ## If you are using custom users not managed by Omnibus, you need to specify + ## UIDs and GIDs like below, and ensure they match between servers in a + ## cluster to avoid permissions issues + ## + user['uid'] = 9000 + user['gid'] = 9000 + web_server['uid'] = 9001 + web_server['gid'] = 9001 + registry['uid'] = 9002 + registry['gid'] = 9002 + ``` + + 您可以类似地将服务器配置为仅运行`geo_logcursor['enable'] = true`的`geo-logcursor`服务,并使用`sidekiq['enable'] = false`禁用 Sidekiq. + + 这些服务器不需要连接到负载平衡器. \ No newline at end of file diff --git a/_book/docs/497.md b/_book/docs/497.md new file mode 100644 index 0000000000000000000000000000000000000000..16372a8b74b6671c838aa4c79771a27894176b30 --- /dev/null +++ b/_book/docs/497.md @@ -0,0 +1,266 @@ +# Geo security review (Q&A) + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/security_review.html](https://docs.gitlab.com/ee/administration/geo/replication/security_review.html) + +* [Business Model](#business-model) + * [What geographic areas does the application service?](#what-geographic-areas-does-the-application-service) +* [Data Essentials](#data-essentials) + * [What data does the application receive, produce, and process?](#what-data-does-the-application-receive-produce-and-process) + * [How can the data be classified into categories according to its sensitivity?](#how-can-the-data-be-classified-into-categories-according-to-its-sensitivity) + * [What data backup and retention requirements have been defined for the application?](#what-data-backup-and-retention-requirements-have-been-defined-for-the-application) +* [End-Users](#end-users) + * [Who are the application’s end‐users?](#who-are-the-applications-endusers) + * [How do the end‐users interact with the application?](#how-do-the-endusers-interact-with-the-application) + * [What security expectations do the end‐users have?](#what-security-expectations-do-the-endusers-have) +* [Administrators](#administrators) + * [Who has administrative capabilities in the application?](#who-has-administrative-capabilities-in-the-application) + * [What administrative capabilities does the application offer?](#what-administrative-capabilities-does-the-application-offer) +* [Network](#network) + * [What details regarding routing, switching, firewalling, and load‐balancing have been defined?](#what-details-regarding-routing-switching-firewalling-and-loadbalancing-have-been-defined) + * [What core network devices support the application?](#what-core-network-devices-support-the-application) + * [What network performance requirements exist?](#what-network-performance-requirements-exist) + * [What private and public network links support the application?](#what-private-and-public-network-links-support-the-application) +* [Systems](#systems) + * [What operating systems support the application?](#what-operating-systems-support-the-application) + * [What details regarding required OS components and lock‐down needs have been defined?](#what-details-regarding-required-os-components-and-lockdown-needs-have-been-defined) +* [Infrastructure Monitoring](#infrastructure-monitoring) + * [What network and system performance monitoring requirements have been defined?](#what-network-and-system-performance-monitoring-requirements-have-been-defined) + * [What mechanisms exist to detect malicious code or compromised application components?](#what-mechanisms-exist-to-detect-malicious-code-or-compromised-application-components) + * [What network and system security monitoring requirements have been defined?](#what-network-and-system-security-monitoring-requirements-have-been-defined) +* [Virtualization and Externalization](#virtualization-and-externalization) + * [What aspects of the application lend themselves to virtualization?](#what-aspects-of-the-application-lend-themselves-to-virtualization) +* [What virtualization requirements have been defined for the application?](#what-virtualization-requirements-have-been-defined-for-the-application) + * [What aspects of the product may or may not be hosted via the cloud computing model?](#what-aspects-of-the-product-may-or-may-not-be-hosted-via-the-cloud-computing-model) +* [If applicable, what approach(es) to cloud computing will be taken (Managed Hosting versus “Pure” Cloud, a “full machine” approach such as AWS-EC2 versus a “hosted database” approach such as AWS-RDS and Azure, etc)?](#if-applicable-what-approaches-to-cloud-computing-will-be-taken-managed-hosting-versus-pure-cloud-a-full-machine-approach-such-as-aws-ec2-versus-a-hosted-database-approach-such-as-aws-rds-and-azure-etc) +* [Environment](#environment) + * [What frameworks and programming languages have been used to create the application?](#what-frameworks-and-programming-languages-have-been-used-to-create-the-application) + * [What process, code, or infrastructure dependencies have been defined for the application?](#what-process-code-or-infrastructure-dependencies-have-been-defined-for-the-application) + * [What databases and application servers support the application?](#what-databases-and-application-servers-support-the-application) + * [How will database connection strings, encryption keys, and other sensitive components be stored, accessed, and protected from unauthorized detection?](#how-will-database-connection-strings-encryption-keys-and-other-sensitive-components-be-stored-accessed-and-protected-from-unauthorized-detection) +* [Data Processing](#data-processing) + * [What data entry paths does the application support?](#what-data-entry-paths-does-the-application-support) + * [What data output paths does the application support?](#what-data-output-paths-does-the-application-support) + * [How does data flow across the application’s internal components?](#how-does-data-flow-across-the-applications-internal-components) + * [What data input validation requirements have been defined?](#what-data-input-validation-requirements-have-been-defined) + * [What data does the application store and how?](#what-data-does-the-application-store-and-how) + * [What data is or may need to be encrypted and what key management requirements have been defined?](#what-data-is-or-may-need-to-be-encrypted-and-what-key-management-requirements-have-been-defined) + * [What capabilities exist to detect the leakage of sensitive data?](#what-capabilities-exist-to-detect-the-leakage-of-sensitive-data) + * [What encryption requirements have been defined for data in transit - including transmission over WAN, LAN, SecureFTP, or publicly accessible protocols such as http: and https:?](#what-encryption-requirements-have-been-defined-for-data-in-transit---including-transmission-over-wan-lan-secureftp-or-publicly-accessible-protocols-such-as-http-and-https) +* [Access](#access) + * [What user privilege levels does the application support?](#what-user-privilege-levels-does-the-application-support) + * [What user identification and authentication requirements have been defined?](#what-user-identification-and-authentication-requirements-have-been-defined) + * [What user authorization requirements have been defined?](#what-user-authorization-requirements-have-been-defined) + * [What session management requirements have been defined?](#what-session-management-requirements-have-been-defined) + * [What access requirements have been defined for URI and Service calls?](#what-access-requirements-have-been-defined-for-uri-and-service-calls) +* [Application Monitoring](#application-monitoring) + * [What application auditing requirements have been defined? How are audit and debug logs accessed, stored, and secured?](#what-application-auditing-requirements-have-been-defined-how-are-audit-and-debug-logs-accessed-stored-and-secured) + +# Geo security review (Q&A)[](#geo-security-review-qa-premium-only "Permalink") + +以下对地理功能集的安全性审查集中于该功能的安全性方面,因为它们适用于运行自己的 GitLab 实例的客户. 复习题部分基于[owasp.org](https://owasp.org/)的[OWASP 应用程序安全验证标准项目](https://owasp.org/www-project-application-security-verification-standard/) . + +## Business Model[](#business-model "Permalink") + +### What geographic areas does the application service?[](#what-geographic-areas-does-the-application-service "Permalink") + +* 这因客户而异. Geo 使客户可以部署到多个区域,然后他们可以选择自己的位置. +* 区域和节点选择完全是手动的. + +## Data Essentials[](#data-essentials "Permalink") + +### What data does the application receive, produce, and process?[](#what-data-does-the-application-receive-produce-and-process "Permalink") + +* Geo 几乎在站点之间流传输 GitLab 实例保存的所有数据. 这包括完整的数据库复制,大多数文件(用户上传的附件等)以及存储库+ Wiki 数据. 在典型的配置中,这将在公共 Internet 上发生,并经过 TLS 加密. +* PostgreSQL 复制是 TLS 加密的. +* 另请参阅: [仅应支持 TLSv1.2](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/2948) + +### How can the data be classified into categories according to its sensitivity?[](#how-can-the-data-be-classified-into-categories-according-to-its-sensitivity "Permalink") + +* GitLab’s model of sensitivity is centered around public vs. internal vs. private projects. Geo replicates them all indiscriminately. “Selective sync” exists for files and repositories (but not database content), which would permit only less-sensitive projects to be replicated to a **secondary** node if desired. +* 另请参阅: [GitLab 数据分类策略](https://about.gitlab.com/handbook/engineering/security/data-classification-policy.html) . + +### What data backup and retention requirements have been defined for the application?[](#what-data-backup-and-retention-requirements-have-been-defined-for-the-application "Permalink") + +* Geo 旨在提供应用程序数据的某些子集的复制. 它是解决方案的一部分,而不是问题的一部分. + +## End-Users[](#end-users "Permalink") + +### Who are the application’s end‐users?[](#who-are-the-applications-endusers "Permalink") + +* **辅助**节点在是遥远(在互联网延迟而言)从主 GitLab 安装( **主**节点)区创建. 打算由通常使用**主**节点的任何人使用它们,他们发现**辅助**节点距离它们更近(就 Internet 延迟而言). + +### How do the end‐users interact with the application?[](#how-do-the-endusers-interact-with-the-application "Permalink") + +* **辅助**节点提供了**主**节点执行的所有接口(特别是 HTTP / HTTPS Web 应用程序以及 HTTP / HTTPS 或 SSH Git 存储库访问),但仅限于只读活动. 设想主要用例是从**辅助**节点克隆 Git 存储库以支持**主**节点,但是最终用户可以使用 GitLab Web 界面查看项目,问题,合并请求,摘要等. + +### What security expectations do the end‐users have?[](#what-security-expectations-do-the-endusers-have "Permalink") + +* 复制过程必须是安全的. 例如,在整个公共 Internet 上以纯文本格式传输整个数据库内容或所有文件和存储库通常是不可接受的. +* **辅助**节点必须对其内容具有与**主**节点相同的访问控制-未经身份验证的用户不能通过查询**辅助**节点来获得对**主**节点上特权信息的访问. +* 攻击者必须不能将**辅助**节点模拟为**主要**节点,从而不能访问特权信息. + +## Administrators[](#administrators "Permalink") + +### Who has administrative capabilities in the application?[](#who-has-administrative-capabilities-in-the-application "Permalink") + +* 没有特定于地理位置的信息. 在数据库中设置了`admin: true`任何用户都被视为具有超级用户特权的 admin. +* 另请参阅: [更详细的访问控制](https://gitlab.com/gitlab-org/gitlab/-/issues/18242) (不是特定于地理位置的). +* Geo 的许多集成(例如,数据库复制)必须由应用程序配置,通常由系统管理员配置. + +### What administrative capabilities does the application offer?[](#what-administrative-capabilities-does-the-application-offer "Permalink") + +* 具有管理访问权限的用户可以添加,修改或删除**辅助**节点. +* 复制过程可以通过 Sidekiq 管理控件进行控制(启动/停止). + +## Network[](#network "Permalink") + +### What details regarding routing, switching, firewalling, and load‐balancing have been defined?[](#what-details-regarding-routing-switching-firewalling-and-loadbalancing-have-been-defined "Permalink") + +* Geo 要求**主要**节点和**次要**节点能够通过 TCP / IP 网络相互通信. 特别是, **辅助**节点必须能够访问**主**节点上的 HTTP / HTTPS 和 PostgreSQL 服务. + +### What core network devices support the application?[](#what-core-network-devices-support-the-application "Permalink") + +* 因客户而异. + +### What network performance requirements exist?[](#what-network-performance-requirements-exist "Permalink") + +* **主**节点和**辅助**节点之间的最大复制速度受到站点之间可用带宽的限制. 没有硬性要求-完成复制的时间(以及跟上**主**节点的更改的能力)取决于数据集的大小,对延迟的容忍度以及可用的网络容量. + +### What private and public network links support the application?[](#what-private-and-public-network-links-support-the-application "Permalink") + +* 客户选择自己的网络. 由于打算将站点在地理位置上分开,因此可以设想,复制流量将在典型部署中通过公共 Internet 传递,但这不是必需的. + +## Systems[](#systems "Permalink") + +### What operating systems support the application?[](#what-operating-systems-support-the-application "Permalink") + +* Geo 对操作系统没有任何其他限制(有关更多详细信息,请参见[GitLab 安装](https://about.gitlab.com/install/)页面),但是我们建议您使用[Geo 文档中](index.html#requirements-for-running-geo)列出的操作系统. + +### What details regarding required OS components and lock‐down needs have been defined?[](#what-details-regarding-required-os-components-and-lockdown-needs-have-been-defined "Permalink") + +* 受支持的安装方法(Omnibus)打包了大多数组件本身. +* 系统安装的 OpenSSH 守护程序(Geo 要求用户设置自定义身份验证方法)和 omnibus 或系统提供的 PostgreSQL 守护程序(必须配置为侦听 TCP,必须添加其他用户和复制插槽)之间存在很大的依赖关系,等等). +* 处理安全更新的过程(例如,如果 OpenSSH 或其他服务中存在重大漏洞,并且客户希望在 OS 上修补这些服务)与非 Geo 情况相同:对 OpenSSH 的安全更新为通过通常的分发渠道提供给用户. Geo 在那里没有延迟. + +## Infrastructure Monitoring[](#infrastructure-monitoring "Permalink") + +### What network and system performance monitoring requirements have been defined?[](#what-network-and-system-performance-monitoring-requirements-have-been-defined "Permalink") + +* 没有特定于 Ge​​o 的内容. + +### What mechanisms exist to detect malicious code or compromised application components?[](#what-mechanisms-exist-to-detect-malicious-code-or-compromised-application-components "Permalink") + +* 没有特定于 Ge​​o 的内容. + +### What network and system security monitoring requirements have been defined?[](#what-network-and-system-security-monitoring-requirements-have-been-defined "Permalink") + +* 没有特定于 Ge​​o 的内容. + +## Virtualization and Externalization[](#virtualization-and-externalization "Permalink") + +### What aspects of the application lend themselves to virtualization?[](#what-aspects-of-the-application-lend-themselves-to-virtualization "Permalink") + +* All. + +## What virtualization requirements have been defined for the application?[](#what-virtualization-requirements-have-been-defined-for-the-application "Permalink") + +* 没有特定于地理位置的信息,但是在这样的环境中,GitLab 中的所有内容都需要具有完整的功能. + +### What aspects of the product may or may not be hosted via the cloud computing model?[](#what-aspects-of-the-product-may-or-may-not-be-hosted-via-the-cloud-computing-model "Permalink") + +* GitLab 是"云原生"的,这不仅适用于 Geo,还适用于产品的其余部分. 在云中进行部署是常见且受支持的方案. + +## If applicable, what approach(es) to cloud computing will be taken (Managed Hosting versus “Pure” Cloud, a “full machine” approach such as AWS-EC2 versus a “hosted database” approach such as AWS-RDS and Azure, etc)?[](#if-applicable-what-approaches-to-cloud-computing-will-be-taken-managed-hosting-versus-pure-cloud-a-full-machine-approach-such-as-aws-ec2-versus-a-hosted-database-approach-such-as-aws-rds-and-azure-etc "Permalink") + +* 由我们的客户根据他们的运营需求来决定. + +## Environment[](#environment "Permalink") + +### What frameworks and programming languages have been used to create the application?[](#what-frameworks-and-programming-languages-have-been-used-to-create-the-application "Permalink") + +* Ruby on Rails,Ruby. + +### What process, code, or infrastructure dependencies have been defined for the application?[](#what-process-code-or-infrastructure-dependencies-have-been-defined-for-the-application "Permalink") + +* 没有特定于 Ge​​o 的内容. + +### What databases and application servers support the application?[](#what-databases-and-application-servers-support-the-application "Permalink") + +* PostgreSQL> = 11,Redis,Sidekiq,Puma. + +### How will database connection strings, encryption keys, and other sensitive components be stored, accessed, and protected from unauthorized detection?[](#how-will-database-connection-strings-encryption-keys-and-other-sensitive-components-be-stored-accessed-and-protected-from-unauthorized-detection "Permalink") + +* 有一些特定于地理位置的值. 有些是共享机密,必须在设置时将其从**主**节点安全地传输到**辅助**节点. 我们的文档建议通过 SSH 将它们从**主**节点传输到系统管理员,然后以相同方式回传到**辅助**节点. 特别是,这包括 PostgreSQL 复制凭证和一个秘密密钥( `db_key_base` ),该密钥用于解密数据库中的某些列. `db_key_base`秘密与其他许多秘密一起未加密地存储在文件系统中的`/etc/gitlab/gitlab-secrets.json` . 他们没有休息保护. + +## Data Processing[](#data-processing "Permalink") + +### What data entry paths does the application support?[](#what-data-entry-paths-does-the-application-support "Permalink") + +* 数据是通过 GitLab 本身公开的 Web 应用程序输入的. 使用 GitLab 服务器上的系统管理命令(例如`gitlab-ctl set-primary-node` )也输入了一些数据. +* **辅助**节点还通过 PostgreSQL 流复制从**主**节点接收输入. + +### What data output paths does the application support?[](#what-data-output-paths-does-the-application-support "Permalink") + +* **主**节点通过 PostgreSQL 流复制输出到**辅助**节点. 否则,主要是通过 GitLab 本身公开的 Web 应用程序以及最终用户启动的 SSH `git clone`操作. + +### How does data flow across the application’s internal components?[](#how-does-data-flow-across-the-applications-internal-components "Permalink") + +* **辅助**节点和**主**节点通过 HTTP / HTTPS(受 JSON Web 令牌保护)和 PostgreSQL 流复制进行交互. +* 在**主**节点或**辅助**节点内,SSOT 是文件系统和数据库(包括**辅助**节点上的 Geo 跟踪数据库). 精心安排了各种内部组件以对这些存储进行更改. + +### What data input validation requirements have been defined?[](#what-data-input-validation-requirements-have-been-defined "Permalink") + +* **辅助**节点必须忠实地复制**主**节点的数据. + +### What data does the application store and how?[](#what-data-does-the-application-store-and-how "Permalink") + +* Git 存储库和文件,与它们相关的跟踪信息以及 GitLab 数据库内容. + +### What data is or may need to be encrypted and what key management requirements have been defined?[](#what-data-is-or-may-need-to-be-encrypted-and-what-key-management-requirements-have-been-defined "Permalink") + +* **主**节点或**辅助**节点都不会加密静态的 Git 存储库或文件系统数据. 数据库列的子集使用`db_otp_key`加密. +* 在 GitLab 部署中的所有主机之间共享的静态机密. +* 在传输过程中,尽管应用程序确实允许通信以未加密的方式进行,但是数据应该被加密. 两个主要过程是 PostgreSQL 和 Git 存储库/文件的**辅助**节点复制过程. 两者均应使用 TLS 保护,并通过现有配置通过 Omnibus 管理该密钥,以供最终用户访问 GitLab. + +### What capabilities exist to detect the leakage of sensitive data?[](#what-capabilities-exist-to-detect-the-leakage-of-sensitive-data "Permalink") + +* 存在全面的系统日志,跟踪与 GitLab 和 PostgreSQL 的每个连接. + +### What encryption requirements have been defined for data in transit - including transmission over WAN, LAN, SecureFTP, or publicly accessible protocols such as http: and https:?[](#what-encryption-requirements-have-been-defined-for-data-in-transit---including-transmission-over-wan-lan-secureftp-or-publicly-accessible-protocols-such-as-http-and-https "Permalink") + +* 数据必须具有在传输过程中进行加密的选项,并且必须能够抵抗被动和主动攻击(例如,不可能进行 MITM 攻击). + +## Access[](#access "Permalink") + +### What user privilege levels does the application support?[](#what-user-privilege-levels-does-the-application-support "Permalink") + +* Geo 添加了一种类型的特权: **辅助**节点可以访问特殊的 Geo API,以通过 HTTP / HTTPS 下载文件,以及使用 HTTP / HTTPS 克隆存储库. + +### What user identification and authentication requirements have been defined?[](#what-user-identification-and-authentication-requirements-have-been-defined "Permalink") + +* **辅助**节点基于共享数据库(HTTP 访问)或 PostgreSQL 复制用户(用于数据库复制)通过 OAuth 或 JWT 身份验证向 Geo **主**节点标识. 数据库复制还需要定义基于 IP 的访问控制. + +### What user authorization requirements have been defined?[](#what-user-authorization-requirements-have-been-defined "Permalink") + +* **辅助**节点只能*读取*数据. 他们当前无法对**主**节点上的数据进行突变. + +### What session management requirements have been defined?[](#what-session-management-requirements-have-been-defined "Permalink") + +* 地理 JWT 被定义为仅持续两分钟,然后需要重新生成. +* Geo JWT 是为以下特定范围之一生成的: + * Geo API 访问. + * Git 访问. + * LFS 和文件 ID. + * 上传和文件 ID. + * 作业工件和文件 ID. + +### What access requirements have been defined for URI and Service calls?[](#what-access-requirements-have-been-defined-for-uri-and-service-calls "Permalink") + +* **辅助**节点对**主**节点的 API 进行了许多调用. 例如,这就是文件复制的进行方式. 只能使用 JWT 令牌访问此端点. +* **主**节点还调用**辅助**节点以获取状态信息. + +## Application Monitoring[](#application-monitoring "Permalink") + +### What application auditing requirements have been defined? How are audit and debug logs accessed, stored, and secured?[](#what-application-auditing-requirements-have-been-defined-how-are-audit-and-debug-logs-accessed-stored-and-secured "Permalink") + +* 结构化 JSON 日志将写入文件系统,也可以将其提取到 Kibana 安装中以进行进一步分析. \ No newline at end of file diff --git a/_book/docs/498.md b/_book/docs/498.md new file mode 100644 index 0000000000000000000000000000000000000000..6ee1fd250d9db21f9017199d1f30996427ad2db1 --- /dev/null +++ b/_book/docs/498.md @@ -0,0 +1,106 @@ +# Location-aware Git remote URL with AWS Route53 + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/location_aware_git_url.html](https://docs.gitlab.com/ee/administration/geo/replication/location_aware_git_url.html) + +* [Prerequisites](#prerequisites) +* [Create a traffic policy](#create-a-traffic-policy) +* [Configure Git clone URLs to use the special Git URL](#configure-git-clone-urls-to-use-the-special-git-url) +* [Example Git request handling behavior](#example-git-request-handling-behavior) + +# Location-aware Git remote URL with AWS Route53[](#location-aware-git-remote-url-with-aws-route53-premium-only "Permalink") + +您可以为 GitLab 用户提供一个远程 URL,该 URL 自动使用距离他们最近的 Geo 节点. 这意味着用户在移动时无需更新其 Git 配置即可利用更近的 Geo 节点. + +这是可能的,因为 Git 推送请求可以从**辅助**节点自动重定向(HTTP)或代理(SSH)到**主**节点. + +尽管这些说明使用[AWS Route53](https://aws.amazon.com/route53/) ,但也可以使用其他服务,例如[Cloudflare](https://www.cloudflare.com/) . + +**注意:**您还可以使用负载平衡器将 Web UI 或 API 流量分配到[多个 Geo **辅助**节点](../../../user/admin_area/geo_nodes.html#multiple-secondary-nodes-behind-a-load-balancer) . 重要的是,尚不能包含**主**节点. 请参阅功能请求. [支持将**主数据库**放置在 Geo 节点负载均衡器之后](https://gitlab.com/gitlab-org/gitlab/-/issues/10888) . + +## Prerequisites[](#prerequisites "Permalink") + +在此示例中,我们已经设置: + +* `primary.example.com`作为地理**主要**节点. +* `secondary.example.com`作为地理**辅助**节点. + +我们将创建一个`git.example.com`子域,该子域将自动定向请求: + +* 从欧洲到**次要**节点. +* 从所有其他位置到**主**节点. + +无论如何,您都需要: + +* 一个可工作的 GitLab **主**节点,可以在其自己的地址访问. +* 运行中的 GitLab **辅助**节点. +* 一个 Route53 托管区域管理您的域. + +如果尚未设置 Geo **主**节点和**辅助**节点,请查阅[Geo 设置说明](index.html#setup-instructions) . + +## Create a traffic policy[](#create-a-traffic-policy "Permalink") + +在 Route53 托管区域中,可以使用流策略来设置各种路由配置. + +1. 导航到[Route53 仪表板](https://console.aws.amazon.com/route53/home) ,然后单击" **流量策略"** . + + [![Traffic policies](img/05dd8439c1da77198297616b4c4f8458.png)](img/single_git_traffic_policies.png) + +2. 单击**创建流量策略**按钮. + + [![Name policy](img/481f18ff2e4575d1c38d4c93631bd23c.png)](img/single_git_name_policy.png) + +3. 在`Single Git Host`填充**Policy Name**字段,然后单击**Next** . + + [![Policy diagram](img/f8c3e75c59db0de2544d73c590e98696.png)](img/single_git_policy_diagram.png) + +4. Leave **DNS 类型** as `A: IP Address in IPv4 format`. +5. 点击**连接到...,**然后选择**地理位置规则** . + + [![Add geolocation rule](img/ec9eebd0b49b9f0b94eb6d12fadd7cf5.png)](img/single_git_add_geolocation_rule.png) + +6. 对于第一个**位置** ,请将其保留为`Default` . +7. 单击" **连接到...",**然后选择" **新建端点"** . +8. 选择**类型** `value`并用``填写. +9. 对于第二个**位置** ,选择" `Europe` . +10. 单击" **连接到...",**然后选择" **新建端点"** . +11. 选择**类型** `value`并用``填写. + + [![Add traffic policy endpoints](img/bb46a964436bb5fa1becb0900b9b0fc3.png)](img/single_git_add_traffic_policy_endpoints.png) + +12. Click **创建流量策略**. + + [![Create policy records with traffic policy](img/d1e835585272f821d777f384eed6a832.png)](img/single_git_create_policy_records_with_traffic_policy.png) + +13. 使用`git`填写**策略记录 DNS 名称** . +14. Click **创建策略记录**. + + [![Created policy record](img/b62968cd49816ab794ddd37a7dcfb7a2.png)](img/single_git_created_policy_record.png) + +您已经成功设置了一个主机,例如`git.example.com` ,它通过地理位置将流量分配到您的 Geo 节点! + +## Configure Git clone URLs to use the special Git URL[](#configure-git-clone-urls-to-use-the-special-git-url "Permalink") + +用户首次克隆存储库时,通常会从项目页面复制 Git 远程 URL. 默认情况下,这些 SSH 和 HTTP URL 基于当前主机的外部 URL. 例如: + +* `git@secondary.example.com:group1/project1.git` +* `https://secondary.example.com/group1/project1.git` + +[![Clone panel](img/8ec36cbe2f746b6b6cc0d28e1620899a.png)](img/single_git_clone_panel.png) + +您可以自定义: + +* SSH 远程 URL 以使用可`git.example.com`位置的`git.example.com` . 为此,通过在 Web 节点的`gitlab.rb`中设置`gitlab_rails['gitlab_ssh_host']`来更改 SSH 远程 URL 的主机. +* HTTP 远程 URL,如[HTTP(S)的 Custom Git 克隆 URL 中](../../../user/admin_area/settings/visibility_and_access_controls.html#custom-git-clone-url-for-https)所示. + +## Example Git request handling behavior[](#example-git-request-handling-behavior "Permalink") + +完成上述配置步骤后,现在可以识别 Git 请求的位置. 要求: + +* 在欧洲以外,所有请求都定向到**主**节点. +* 在欧洲范围内: + * HTTP: + * `git clone http://git.example.com/foo/bar.git`定向到**辅助**节点. + * `git push`最初定向到**辅助服务器** , **辅助服务器**自动重定向到`primary.example.com` . + * SSH: + * `git clone git@git.example.com:foo/bar.git`被定向到**辅助目录** . + * `git push`首先指向**辅助**服务器, **辅助**服务器自动将请求代理到`primary.example.com` . \ No newline at end of file diff --git a/_book/docs/499.md b/_book/docs/499.md new file mode 100644 index 0000000000000000000000000000000000000000..a8b1dd471f04714855e5d2a0dae29160bc772622 --- /dev/null +++ b/_book/docs/499.md @@ -0,0 +1,16 @@ +# Tuning Geo + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/tuning.html](https://docs.gitlab.com/ee/administration/geo/replication/tuning.html) + +* [Changing the sync capacity values](#changing-the-sync-capacity-values) + +# Tuning Geo[](#tuning-geo-premium-only "Permalink") + +## Changing the sync capacity values[](#changing-the-sync-capacity-values "Permalink") + +在以下位置的"地理管理员"页面中 **管理区>** **Geo** ( `/admin/geo/nodes` ),可以调整一些变量来提高 Geo 的性能: + +* 存储库同步容量. +* 文件同步容量. + +增加这些值将增加计划的作业数量. 但是,除非还增加了可用的 Sidekiq 线程数,否则这可能不会导致更多并行下载. 例如,如果存储库同步容量从 25 增加到 50,您可能还希望将 Sidekiq 线程的数量从 25 增加到 50.有关更多详细信息,请参见[Sidekiq 并发文档](../../operations/extra_sidekiq_processes.html#number-of-threads) . \ No newline at end of file diff --git a/_book/docs/500.md b/_book/docs/500.md new file mode 100644 index 0000000000000000000000000000000000000000..2da4d16fafa3078740a1340ed2f19bfb611a4366 --- /dev/null +++ b/_book/docs/500.md @@ -0,0 +1,53 @@ +# Removing secondary Geo nodes + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/remove_geo_node.html](https://docs.gitlab.com/ee/administration/geo/replication/remove_geo_node.html) + +# Removing secondary Geo nodes[](#removing-secondary-geo-nodes-premium-only "Permalink") + +可以使用**主**节点的地理管理页面从地理集群中删除**辅助**节点. 删除**辅助**节点: + +1. 导航 **管理区>** **地理位置** ( `/admin/geo/nodes` ). +2. 单击要**删除**的**辅助**节点的" **删除"**按钮. +3. 出现提示时,单击" **删除"进行**确认. + +从"地理管理员"页面中删除后,您必须停止并卸载**辅助**节点: + +1. 在**辅助**节点上,停止 GitLab: + + ``` + sudo gitlab-ctl stop + ``` + +2. 在**辅助**节点上,卸载 GitLab: + + ``` + # Stop gitlab and remove its supervision process + sudo gitlab-ctl uninstall + + # Debian/Ubuntu + sudo dpkg --remove gitlab-ee + + # Redhat/Centos + sudo rpm --erase gitlab-ee + ``` + +从**辅助**节点上卸载了 GitLab 之后,必须如下所示从**主**节点的数据库中删除复制插槽: + +1. 在**主**节点上,启动 PostgreSQL 控制台会话: + + ``` + sudo gitlab-psql + ``` + + **注意:**使用`gitlab-rails dbconsole`将不起作用,因为管理复制插槽需要超级用户权限. +2. 查找相关复制插槽的名称. 这是运行复制命令`gitlab-ctl replicate-geo-database`时用`--slot-name`指定的插槽. + + ``` + SELECT * FROM pg_replication_slots; + ``` + +3. 删除**辅助**节点的复制插槽: + + ``` + SELECT pg_drop_replication_slot(''); + ``` \ No newline at end of file diff --git a/_book/docs/501.md b/_book/docs/501.md new file mode 100644 index 0000000000000000000000000000000000000000..61711bc1004f6f039aaa673c64c1f965841ef337 --- /dev/null +++ b/_book/docs/501.md @@ -0,0 +1,148 @@ +# Geo data types support + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/datatypes.html](https://docs.gitlab.com/ee/administration/geo/replication/datatypes.html) + +* [Data types](#data-types) + * [Git repositories](#git-repositories) + * [Blobs](#blobs) + * [Database](#database) +* [Limitations on replication/verification](#limitations-on-replicationverification) + +# Geo data types support[](#geo-data-types-support-premium-only "Permalink") + +地理数据类型是一个或多个 GitLab 功能存储相关信息所需的特定数据类别. + +要使用 Geo 复制这些功能生成的数据,我们使用几种策略来访问,传输和验证它们. + +## Data types[](#data-types "Permalink") + +当前,我们区分三种不同的数据类型: + +* [Git repositories](#git-repositories) +* [Blobs](#blobs) +* [Database](#database) + +请参阅下面列出的我们复制的每个功能或组件,其对应的数据类型,复制和验证方法的列表: + +| Type | 功能/组件 | 复制方式 | 验证方式 | +| --- | --- | --- | --- | +| Database | PostgreSQL 中的应用程序数据 | Native | Native | +| Database | Redis | *N/A* (*1*) | *N/A* | +| Database | Elasticsearch | Native | Native | +| Database | 个人摘要 | PostgreSQL 复制 | PostgreSQL 复制 | +| Database | 项目摘要 | PostgreSQL 复制 | PostgreSQL 复制 | +| Database | SSH 公钥 | PostgreSQL 复制 | PostgreSQL 复制 | +| Git | 项目资料库 | 地理与吉塔利 | Gitaly 校验和 | +| Git | 项目 Wiki 资料库 | 地理与吉塔利 | Gitaly 校验和 | +| Git | 项目设计资料库 | 地理与吉塔利 | Gitaly 校验和 | +| Git | 用于分支项目重复数据删除的对象池 | 地理与吉塔利 | *未实现* | +| Blobs | User uploads *(filesystem)* | 带有 API 的地理位置 | *未实现* | +| Blobs | 用户上传*(对象存储)* | 具有 API /托管的地理区域( *2* ) | *未实现* | +| Blobs | LFS 对象*(文件系统)* | 带有 API 的地理位置 | *未实现* | +| Blobs | LFS 对象*(对象存储)* | 具有 API /托管的地理区域( *2* ) | *未实现* | +| Blobs | CI 作业工件*(文件系统)* | 带有 API 的地理位置 | *未实现* | +| Blobs | CI 作业工件*(对象存储)* | 具有 API /托管的地理区域( *2* ) | *未实现* | +| Blobs | 归档的 CI 构建跟踪*(文件系统)* | 带有 API 的地理位置 | *未实现* | +| Blobs | 归档的 CI 构建跟踪*(对象存储)* | 具有 API /托管的地理区域( *2* ) | *未实现* | +| Blobs | 容器注册表*(文件系统)* | 使用 API​​ / Docker API 进行地理定位 | *未实现* | +| Blobs | 容器注册表*(对象存储)* | 带有 API / Managed / Docker API 的 Geo( *2* ) | *未实现* | +| Blobs | 程序包注册表*(文件系统)* | 带有 API 的地理位置 | *未实现* | +| Blobs | 程序包注册表*(对象存储)* | 具有 API /托管的地理区域( *2* ) | *未实现* | + +* ( *1* ):Redis 复制可与 Redis 前哨一起用作 HA 的一部分. 在地理节点之间不使用它. +* ( *2* ):对象存储复制可以通过 Geo 或您的对象存储提供者/设备本机复制功能来执行. + +### Git repositories[](#git-repositories "Permalink") + +一个 GitLab 实例可以具有一个或多个存储库分片. 每个分片都有一个 Gitaly 实例,该实例负责允许对本地存储的 Git 存储库进行访问和操作. 它可以在具有单个磁盘,作为单个安装点安装多个磁盘(如 RAID 阵列)或使用 LVM 的计算机上运行. + +它不需要特殊的文件系统,并且可以与 NFS 或已安装的 Storage Appliance 一起使用(使用远程文件系统时可能会有性能限制). + +通过 Gitaly 自己的 gRPC API 完成通信. 有三种可能的同步方式: + +* 使用常规的 Git 从一个 Geo 节点到另一个 Geo 节点的克隆/获取(具有特殊身份验证). +* 使用存储库快照(用于第一种方法失败或存储库损坏时). +* 从管理界面手动触发(上述两者的组合). + +每个项目最多可以有 3 个不同的存储库: + +* 一个项目存储库,其中存储了源代码. +* Wiki 存储库,用于存储 Wiki 内容. +* 一个设计库,在其中对设计工件进行索引(资产实际上在 LFS 中). + +他们都住在同一个碎片,并用共享相同的基础名称`-wiki`和`-design`用于 Wiki 以及设计资源库的情况下后缀. + +### Blobs[](#blobs "Permalink") + +GitLab 将文件和 Blob(例如 Issue 附件或 LFS 对象)存储到以下任一位置: + +* 特定位置的文件系统. +* [对象存储](../../object_storage.html)解决方案. 对象存储解决方案可以是: + * 像 Amazon S3 Google Cloud Storage 一样基于云. + * 由您托管(如 MinIO). + * 公开与对象存储兼容的 API 的存储设备. + +当使用文件系统存储而不是对象存储时,如果使用多个服务器,则需要使用网络安装的文件系统来运行 GitLab. + +关于复制和验证: + +* 我们使用内部 API 请求传输文件和 Blob. +* 使用对象存储,您可以: + * 使用云提供程序复制功能. + * 让 GitLab 为您复制它. + +### Database[](#database "Permalink") + +对于不同的用例,GitLab 依赖于存储在多个数据库中的数据. PostgreSQL 是 Web 界面中用户生成的内容(例如问题内容,​​注释以及权限和凭据)的唯一事实. + +PostgreSQL 还可以保存某种程度的缓存数据,例如 HTML 呈现的 Markdown,缓存的合并请求差异(也可以配置为卸载到对象存储中). + +我们使用 PostgreSQL 自己的复制功能将数据从**主**节点复制到**辅助**节点. + +我们将 Redis 用作缓存存储并为我们的后台作业系统保留持久性数据. 由于这两个用例都具有同一地理节点专有的数据,因此我们不在节点之间复制它. + +Elasticsearch 是一个可选数据库,可以启用高级搜索功能,例如源代码级别的改进的全局搜索以及"问题/合并请求"和讨论中用户生成的内容. 目前,Geo 不支持此功能. + +## Limitations on replication/verification[](#limitations-on-replicationverification "Permalink") + +下表列出了 GitLab 功能及其在**辅助**节点上的复制和验证状态. + +您可以跟踪实现这些史诗/问题中缺少的项目的进度: + +* [Unreplicated Data Types](https://gitlab.com/groups/gitlab-org/-/epics/893) +* [Verify all replicated data](https://gitlab.com/groups/gitlab-org/-/epics/1430) + +**危险:**不在此列表上或"已**复制"**列中具有" **否"的**功能不会在**辅助**节点上复制. 如果不从这些功能中手动复制数据而进行故障转移,将导致数据**丢失** . 如果希望在**辅助**节点上使用这些功能或成功执行故障转移,则必须使用其他方法复制它们的数据. + +| Feature | 复制(在 GitLab 版本中添加) | 已验证(在 GitLab 版本中添加) | Notes |   | +| --- | --- | --- | --- | --- | +| PostgreSQL 中的应用程序数据 | **Yes** (10.2) | **Yes** (10.2) |   |   | +| 项目资料库 | **Yes** (10.2) | **Yes** (10.7) |   |   | +| 项目 Wiki 资料库 | **Yes** (10.2) | **Yes** (10.7) |   |   | +| 项目设计资料库 | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) |   |   | +| Uploads | **Yes** (10.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | 仅在转移时验证,或手动验证( *1* ) |   | +| LFS 对象 | **Yes** (10.2) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8922) | 仅在转移时验证,或手动验证( *1* ). 在 11.11.x 和 12.0.x( *2* )中的新 LFS 对象不可用. |   | +| CI 作业工件(痕迹除外) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | 仅手动验证( *1* ) |   | +| 存档的痕迹 | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | 仅在转移时验证,或手动验证( *1* ) |   | +| 个人摘要 | **Yes** (10.2) | **Yes** (10.2) |   |   | +| [Versioned snippets](../../../user/snippets.html#versioned-snippets) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2810) |   |   | +| 项目摘要 | **Yes** (10.2) | **Yes** (10.2) |   |   | +| 用于分支项目重复数据删除的对象池 | **Yes** | No |   |   | +| [Server-side Git hooks](../../server_hooks.html) | No | No |   |   | +| [Elasticsearch integration](../../../integration/elasticsearch.html) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No |   |   | +| [GitLab Pages](../../pages/index.html) | [No](https://gitlab.com/groups/gitlab-org/-/epics/589) | No |   |   | +| [Container Registry](../../packages/container_registry.html) | **Yes** (12.3) | No |   |   | +| [NPM Registry](../../../user/packages/npm_registry/index.html) | **Yes** (13.2) | No |   |   | +| [Maven Repository](../../../user/packages/maven_repository/index.html) | **Yes** (13.2) | No |   |   | +| [Conan Repository](../../../user/packages/conan_repository/index.html) | **Yes** (13.2) | No |   |   | +| [NuGet Repository](../../../user/packages/nuget_repository/index.html) | **Yes** (13.2) | No |   |   | +| [PyPi Repository](../../../user/packages/pypi_repository/index.html) | **Yes** (13.2) | No |   |   | +| [Composer Repository](../../../user/packages/composer_repository/index.html) | **Yes** (13.2) | No |   |   | +| [External merge request diffs](../../merge_request_diffs.html) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/33817) | No |   |   | +| [Terraform State](../../terraform_state.html) | [No](https://gitlab.com/groups/gitlab-org/-/epics/3112)(*3*) | No |   |   | +| [Vulnerability Export](../../../user/application_security/security_dashboard/#export-vulnerabilities) | [No](https://gitlab.com/groups/gitlab-org/-/epics/3111)(*3*) | No |   |   | +| 对象存储中的内容 | **Yes** (12.4) | No |   |   | + +* ( *1* ):可以使用两个节点上的[完整性检查瑞克任务](../../raketasks/check.html)并比较它们之间的输出来手动验证[完整性](../../raketasks/check.html) . +* ( *2* ):GitLab 版本 11.11.x 和 12.0.x 受到[一个错误的](https://gitlab.com/gitlab-org/gitlab/-/issues/32696)影响, [该错误阻止了任何新的 LFS 对象的复制](https://gitlab.com/gitlab-org/gitlab/-/issues/32696) . +* ( *3* ):如果使用的是对象存储,则可以通过对象存储提供程序执行复制(如果支持). 请参阅[带有对象存储的地理位置](object_storage.html) \ No newline at end of file diff --git a/_book/docs/502.md b/_book/docs/502.md new file mode 100644 index 0000000000000000000000000000000000000000..95d07b14c2bfcbcf6cec5e97eee64a4e2479683d --- /dev/null +++ b/_book/docs/502.md @@ -0,0 +1,62 @@ +# Geo Frequently Asked Questions + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/faq.html](https://docs.gitlab.com/ee/administration/geo/replication/faq.html) + +* [What are the minimum requirements to run Geo?](#what-are-the-minimum-requirements-to-run-geo) +* [How does Geo know which projects to sync?](#how-does-geo-know-which-projects-to-sync) +* [Can I use Geo in a disaster recovery situation?](#can-i-use-geo-in-a-disaster-recovery-situation) +* [What data is replicated to a **secondary** node?](#what-data-is-replicated-to-a-secondary-node) +* [Can I `git push` to a **secondary** node?](#can-i-git-push-to-a-secondary-node) +* [How long does it take to have a commit replicated to a **secondary** node?](#how-long-does-it-take-to-have-a-commit-replicated-to-a-secondary-node) +* [What if the SSH server runs at a different port?](#what-if-the-ssh-server-runs-at-a-different-port) +* [Is this possible to set up a Docker Registry for a **secondary** node that mirrors the one on the **primary** node?](#is-this-possible-to-set-up-a-docker-registry-for-a-secondary-node-that-mirrors-the-one-on-the-primary-node) + +# Geo Frequently Asked Questions[](#geo-frequently-asked-questions-premium-only "Permalink") + +## What are the minimum requirements to run Geo?[](#what-are-the-minimum-requirements-to-run-geo "Permalink") + +要求[在索引页面](index.html#requirements-for-running-geo)上列出 + +## How does Geo know which projects to sync?[](#how-does-geo-know-which-projects-to-sync "Permalink") + +在每个**辅助**节点上,都有一个 GitLab 数据库的只读复制副本. **辅助**节点还具有跟踪数据库,其中存储了已同步的项目. Geo 比较这两个数据库以查找尚未跟踪的项目. + +首先,此跟踪数据库为空,因此 Geo 将开始尝试从它在 GitLab 数据库中可以看到的每个项目中进行更新. + +对于每个要同步的项目: + +1. Geo 将发出`git fetch geo --mirror`来从**主**节点获取最新信息. 如果没有更改,则同步将很快并快速结束. 否则,它将提取最新的提交. +2. **辅助**节点将更新跟踪数据库,以存储它已同步项目 A,B,C 等的事实. +3. 重复直到所有项目都同步. + +当有人将提交推送到**主**节点时,它将在 GitLab 数据库中生成一个事件,说明存储库已更改. **辅助**节点看到此事件,将有问题的项目标记为脏,并计划重新同步该项目. + +为确保管道问题(例如,同步失败太多或丢失的作业)不会永久停止项目同步,Geo 还会定期检查跟踪数据库中是否有标记为脏的项目. 当并发同步数降到`repos_max_capacity`以下并且没有新的项目等待同步时,将进行此检查. + +Geo 还具有校验和功能,可在所有对 SHA 值的 Git 引用中运行 SHA256 和. 如果**主**节点和**辅助**节点之间的引用不匹配,则**辅助**节点会将项目标记为脏项目,然后尝试重新同步. 因此,即使我们拥有一个过时的跟踪数据库,验证也应激活并找到存储库状态中的差异并重新同步. + +## Can I use Geo in a disaster recovery situation?[](#can-i-use-geo-in-a-disaster-recovery-situation "Permalink") + +是的,但是我们复制的内容有局限性(请参阅将[哪些数据复制到**辅助**节点?](#what-data-is-replicated-to-a-secondary-node) ). + +阅读[灾难恢复](../disaster_recovery/index.html)文档. + +## What data is replicated to a **secondary** node?[](#what-data-is-replicated-to-a-secondary-node "Permalink") + +当前,我们复制项目存储库,LFS 对象,生成的附件/化身以及整个数据库. 这意味着用户帐户,问题,合并请求,组,项目数据等将可用于查询. + +## Can I `git push` to a **secondary** node?[](#can-i-git-push-to-a-secondary-node "Permalink") + +是! [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3 中[引入](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/)了直接推送到**辅助**节点(对于 HTTP 和 SSH,包括 Git LFS). + +## How long does it take to have a commit replicated to a **secondary** node?[](#how-long-does-it-take-to-have-a-commit-replicated-to-a-secondary-node "Permalink") + +所有复制操作都是异步的,并排队等待分派. 因此,这取决于很多因素,包括流量,提交的大小,节点之间的连接,硬件等. + +## What if the SSH server runs at a different port?[](#what-if-the-ssh-server-runs-at-a-different-port "Permalink") + +很好 我们使用 HTTP 来获取从**主**节点到所有**辅助**节点的存储库更改. + +## Is this possible to set up a Docker Registry for a **secondary** node that mirrors the one on the **primary** node?[](#is-this-possible-to-set-up-a-docker-registry-for-a-secondary-node-that-mirrors-the-one-on-the-primary-node "Permalink") + +是. 有关[**辅助**节点,](docker_registry.html)请参见[Docker Registry](docker_registry.html) . \ No newline at end of file diff --git a/_book/docs/503.md b/_book/docs/503.md new file mode 100644 index 0000000000000000000000000000000000000000..c174199326cc56018ba18e963712f29b83381abf --- /dev/null +++ b/_book/docs/503.md @@ -0,0 +1,844 @@ +# Geo Troubleshooting + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/troubleshooting.html](https://docs.gitlab.com/ee/administration/geo/replication/troubleshooting.html) + +* [Basic troubleshooting](#basic-troubleshooting) + * [Check the health of the **secondary** node](#check-the-health-of-the-secondary-node) + * [Check if PostgreSQL replication is working](#check-if-postgresql-replication-is-working) + * [Are nodes pointing to the correct database instance?](#are-nodes-pointing-to-the-correct-database-instance) + * [Can Geo detect the current node correctly?](#can-geo-detect-the-current-node-correctly) +* [Fixing errors found when running the Geo check Rake task](#fixing-errors-found-when-running-the-geo-check-rake-task) +* [Fixing replication errors](#fixing-replication-errors) + * [Message: `ERROR: replication slots can only be used if max_replication_slots > 0`?](#message-error--replication-slots-can-only-be-used-if-max_replication_slots--0) + * [Message: `FATAL: could not start WAL streaming: ERROR: replication slot "geo_secondary_my_domain_com" does not exist`?](#message-fatal--could-not-start-wal-streaming-error--replication-slot-geo_secondary_my_domain_com-does-not-exist) + * [Message: “Command exceeded allowed execution time” when setting up replication?](#message-command-exceeded-allowed-execution-time-when-setting-up-replication) + * [Message: “PANIC: could not write to file `pg_xlog/xlogtemp.123`: No space left on device”](#message-panic-could-not-write-to-file-pg_xlogxlogtemp123-no-space-left-on-device) + * [Message: “ERROR: canceling statement due to conflict with recovery”](#message-error-canceling-statement-due-to-conflict-with-recovery) + * [Message: `LOG: invalid CIDR mask in address`](#message-log--invalid-cidr-mask-in-address) + * [Message: `LOG: invalid IP mask "md5": Name or service not known`](#message-log--invalid-ip-mask-md5-name-or-service-not-known) + * [Very large repositories never successfully synchronize on the **secondary** node](#very-large-repositories-never-successfully-synchronize-on-the-secondary-node) + * [New LFS objects are never replicated](#new-lfs-objects-are-never-replicated) + * [Resetting Geo **secondary** node replication](#resetting-geo-secondary-node-replication) +* [Fixing errors during a failover or when promoting a secondary to a primary node](#fixing-errors-during-a-failover-or-when-promoting-a-secondary-to-a-primary-node) + * [Message: ActiveRecord::RecordInvalid: Validation failed: Name has already been taken](#message-activerecordrecordinvalid-validation-failed-name-has-already-been-taken) + * [Message: `NoMethodError: undefined method `secondary?' for nil:NilClass`](#message-nomethoderror-undefined-method-secondary-for-nilnilclass) + * [Message: `sudo: gitlab-pg-ctl: command not found`](#message-sudo-gitlab-pg-ctl-command-not-found) +* [Fixing Foreign Data Wrapper errors](#fixing-foreign-data-wrapper-errors) + * [“Foreign Data Wrapper (FDW) is not configured” error](#foreign-data-wrapper-fdw-is-not-configured-error) + * [Checking configuration](#checking-configuration) + * [Manual reload of FDW schema](#manual-reload-of-fdw-schema) + * [“Geo database has an outdated FDW remote schema” error](#geo-database-has-an-outdated-fdw-remote-schema-error) +* [Expired artifacts](#expired-artifacts) +* [Fixing sign in errors](#fixing-sign-in-errors) + * [Message: The redirect URI included is not valid](#message-the-redirect-uri-included-is-not-valid) +* [Fixing common errors](#fixing-common-errors) + * [Geo database configuration file is missing](#geo-database-configuration-file-is-missing) + * [An existing tracking database cannot be reused](#an-existing-tracking-database-cannot-be-reused) + * [Geo node has a database that is writable which is an indication it is not configured for replication with the primary node](#geo-node-has-a-database-that-is-writable-which-is-an-indication-it-is-not-configured-for-replication-with-the-primary-node) + * [Geo node does not appear to be replicating the database from the primary node](#geo-node-does-not-appear-to-be-replicating-the-database-from-the-primary-node) + * [Geo database version (…) does not match latest migration (…)](#geo-database-version--does-not-match-latest-migration-) + * [Geo database is not configured to use Foreign Data Wrapper](#geo-database-is-not-configured-to-use-foreign-data-wrapper) + * [GitLab indicates that more than 100% of repositories were synced](#gitlab-indicates-that-more-than-100-of-repositories-were-synced) + * [Geo Admin Area returns 404 error for a secondary node](#geo-admin-area-returns-404-error-for-a-secondary-node) + +# Geo Troubleshooting[](#geo-troubleshooting-premium-only "Permalink") + +设置地理位置需要仔细注意细节,有时很容易错过一个步骤. + +这是您尝试解决问题应采取的步骤的列表: + +* Perform [basic troubleshooting](#basic-troubleshooting). +* 修复所有[复制错误](#fixing-replication-errors) . +* 修复任何[外部数据包装程序](#fixing-foreign-data-wrapper-errors)错误. +* 修复所有[常见](#fixing-common-errors)错误. + +## Basic troubleshooting[](#basic-troubleshooting "Permalink") + +在尝试更高级的故障排除之前: + +* Check [the health of the **secondary** node](#check-the-health-of-the-secondary-node). +* Check [if PostgreSQL replication is working](#check-if-postgresql-replication-is-working). + +### Check the health of the **secondary** node[](#check-the-health-of-the-secondary-node "Permalink") + +访问**主**节点的 **管理区>** 浏览器中的**地理位置** ( `/admin/geo/nodes` ). 我们在每个**辅助**节点上执行以下运行状况检查,以帮助识别是否存在问题: + +* 节点是否在运行? +* 节点的辅助数据库是否已配置用于流复制? +* 是否已配置节点的辅助跟踪数据库? +* 节点的辅助跟踪数据库是否已连接? +* 节点的辅助跟踪数据库是否是最新的? + +[![Geo health check](img/11728974fe5385112311ab02ea56783e.png)](img/geo_node_healthcheck.png) + +有关如何解决从 UI 报告的常见错误的信息,请参阅" [修复常见错误"](#fixing-common-errors) . + +如果用户界面无法正常工作,或者您无法登录,则可以手动运行地理健康检查以获取此信息以及更多详细信息. + +此 Rake 任务可以在**主要**或**辅助** Geo 节点中的应用程序节点上运行: + +``` +sudo gitlab-rake gitlab:geo:check +``` + +输出示例: + +``` +Checking Geo ... + +GitLab Geo is available ... yes +GitLab Geo is enabled ... yes +This machine's Geo node name matches a database record ... yes, found a secondary node named "Shanghai" +GitLab Geo secondary database is correctly configured ... yes +Database replication enabled? ... yes +Database replication working? ... yes +GitLab Geo tracking database is configured to use Foreign Data Wrapper? ... yes +GitLab Geo tracking database Foreign Data Wrapper schema is up-to-date? ... yes +GitLab Geo HTTP(S) connectivity ... +* Can connect to the primary node ... yes +HTTP/HTTPS repository cloning is enabled ... yes +Machine clock is synchronized ... yes +Git user has default SSH configuration? ... yes +OpenSSH configured to use AuthorizedKeysCommand ... yes +GitLab configured to disable writing to authorized_keys file ... yes +GitLab configured to store new projects in hashed storage? ... yes +All projects are in hashed storage? ... yes + +Checking Geo ... Finished +``` + +通过在任何**辅助**应用程序节点上运行以下 Rake 任务,可以手动找到当前同步信息: + +``` +sudo gitlab-rake geo:status +``` + +输出示例: + +``` +http://secondary.example.com/ +----------------------------------------------------- + GitLab Version: 11.10.4-ee + Geo Role: Secondary + Health Status: Healthy + Repositories: 289/289 (100%) + Verified Repositories: 289/289 (100%) + Wikis: 289/289 (100%) + Verified Wikis: 289/289 (100%) + LFS Objects: 8/8 (100%) + Attachments: 5/5 (100%) + CI job artifacts: 0/0 (0%) + Repositories Checked: 0/289 (0%) + Sync Settings: Full + Database replication lag: 0 seconds + Last event ID seen from primary: 10215 (about 2 minutes ago) + Last event ID processed by cursor: 10215 (about 2 minutes ago) + Last status report was: 2 minutes ago +``` + +### Check if PostgreSQL replication is working[](#check-if-postgresql-replication-is-working "Permalink") + +要检查 PostgreSQL 复制是否正常,请检查: + +* [Nodes are pointing to the correct database instance](#are-nodes-pointing-to-the-correct-database-instance). +* [Geo can detect the current node correctly](#can-geo-detect-the-current-node-correctly). + +#### Are nodes pointing to the correct database instance?[](#are-nodes-pointing-to-the-correct-database-instance "Permalink") + +您应确保**主**地理节点指向具有写入权限的实例. + +任何**辅助**节点都应仅指向只读实例. + +#### Can Geo detect the current node correctly?[](#can-geo-detect-the-current-node-correctly "Permalink") + +Geo 通过以下方式在`/etc/gitlab/gitlab.rb`找到当前计算机的 Geo 节点名称: + +* 使用`gitlab_rails['geo_node_name']`设置. +* 如果未定义,请使用`external_url`设置. + +该名称用于在其中查找具有相同**名称**的节点 **管理区>** **地理位置** . + +要检查当前计算机的节点名称是否与数据库中的节点匹配,请运行检查任务: + +``` +sudo gitlab-rake gitlab:geo:check +``` + +它显示当前计算机的节点名称以及匹配的数据库记录是**主**节点还是**辅助**节点. + +``` +This machine's Geo node name matches a database record ... yes, found a secondary node named "Shanghai" +``` + +``` +This machine's Geo node name matches a database record ... no + Try fixing it: + You could add or update a Geo node database record, setting the name to "https://example.com/". + Or you could set this machine's Geo node name to match the name of an existing database record: "London", "Shanghai" + For more information see: + doc/administration/geo/replication/troubleshooting.md#can-geo-detect-the-current-node-correctly +``` + +## Fixing errors found when running the Geo check Rake task[](#fixing-errors-found-when-running-the-geo-check-rake-task "Permalink") + +运行此 Rake 任务时,如果未正确配置节点,则可能会看到错误: + +``` +sudo gitlab-rake gitlab:geo:check +``` + +1. 连接到数据库时,Rails 没有提供密码 + + ``` + Checking Geo ... + + GitLab Geo is available ... Exception: fe_sendauth: no password supplied + GitLab Geo is enabled ... Exception: fe_sendauth: no password supplied + ... + Checking Geo ... Finished + ``` + + * 确保将`gitlab_rails['db_password']`设置为为`postgresql['sql_user_password']`创建哈希时使用的纯文本密码. +2. Rails 无法连接到数据库 + + ``` + Checking Geo ... + + GitLab Geo is available ... Exception: FATAL: no pg_hba.conf entry for host "1.1.1.1", user "gitlab", database "gitlabhq_production", SSL on + FATAL: no pg_hba.conf entry for host "1.1.1.1", user "gitlab", database "gitlabhq_production", SSL off + GitLab Geo is enabled ... Exception: FATAL: no pg_hba.conf entry for host "1.1.1.1", user "gitlab", database "gitlabhq_production", SSL on + FATAL: no pg_hba.conf entry for host "1.1.1.1", user "gitlab", database "gitlabhq_production", SSL off + ... + Checking Geo ... Finished + ``` + + * 确保您具有`postgresql['md5_auth_cidr_addresses']`包含的 rails 节点的 IP 地址. + * 确保在 IP 地址上包括子网掩码: `postgresql['md5_auth_cidr_addresses'] = ['1.1.1.1/32']` . +3. Rails 提供了错误的密码 + + ``` + Checking Geo ... + GitLab Geo is available ... Exception: FATAL: password authentication failed for user "gitlab" + FATAL: password authentication failed for user "gitlab" + GitLab Geo is enabled ... Exception: FATAL: password authentication failed for user "gitlab" + FATAL: password authentication failed for user "gitlab" + ... + Checking Geo ... Finished + ``` + + * 验证正确的密码设置为`gitlab_rails['db_password']`创建中的散列时所使用`postgresql['sql_user_password']`通过运行`gitlab-ctl pg-password-md5 gitlab`并输入密码. +4. 检查返回的不是辅助节点 + + ``` + Checking Geo ... + + GitLab Geo is available ... yes + GitLab Geo is enabled ... yes + GitLab Geo secondary database is correctly configured ... not a secondary node + Database replication enabled? ... not a secondary node + ... + Checking Geo ... Finished + ``` + + * 确保您已在**主**节点的管理区添加辅助节点. + * 在管理节点中添加辅助节点属于**主**节点时,请确保输入了`external_url`或`gitlab_rails['geo_node_name']` . + * 之前 GitLab 12.4,编辑中的**主**节点的管理区的二次节点,并确保有一个尾随`/`在`Name`字段中. +5. 检查返回`Exception: PG::UndefinedTable: ERROR: relation "geo_nodes" does not exist` + + ``` + Checking Geo ... + + GitLab Geo is available ... no + Try fixing it: + Upload a new license that includes the GitLab Geo feature + For more information see: + https://about.gitlab.com/features/gitlab-geo/ + GitLab Geo is enabled ... Exception: PG::UndefinedTable: ERROR: relation "geo_nodes" does not exist + LINE 8: WHERE a.attrelid = '"geo_nodes"'::regclass + ^ + : SELECT a.attname, format_type(a.atttypid, a.atttypmod), + pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod, + c.collname, col_description(a.attrelid, a.attnum) AS comment + FROM pg_attribute a + LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum + LEFT JOIN pg_type t ON a.atttypid = t.oid + LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation + WHERE a.attrelid = '"geo_nodes"'::regclass + AND a.attnum > 0 AND NOT a.attisdropped + ORDER BY a.attnum + ... + Checking Geo ... Finished + ``` + + 在执行 PostgreSQL 主版本(9> 10)时,这是预期的. 跟随: + + * [initiate-the-replication-process](database.html#step-3-initiate-the-replication-process) + * [Geo database has an outdated FDW remote schema](troubleshooting.html#geo-database-has-an-outdated-fdw-remote-schema-error) + +## Fixing replication errors[](#fixing-replication-errors "Permalink") + +以下各节概述了解决复制错误的疑难解答步骤. + +### Message: `ERROR: replication slots can only be used if max_replication_slots > 0`?[](#message-error--replication-slots-can-only-be-used-if-max_replication_slots--0 "Permalink") + +这意味着需要在**主**数据库上设置`max_replication_slots` PostgreSQL 变量. 在 GitLab 9.4 中,我们将此设置默认设置为 1.如果您有更多**辅助**节点,则可能需要增加该值. + +确保重新启动 PostgreSQL 才能生效. 有关更多详细信息,请参见《 [PostgreSQL 复制设置](database.html#postgresql-replication)指南》. + +### Message: `FATAL: could not start WAL streaming: ERROR: replication slot "geo_secondary_my_domain_com" does not exist`?[](#message-fatal--could-not-start-wal-streaming-error--replication-slot-geo_secondary_my_domain_com-does-not-exist "Permalink") + +当 PostgreSQL 没有该名称的**辅助**节点的复制插槽时,会发生这种情况. + +您可能需要在**辅助**节点上重新运行[复制过程](database.html) . + +### Message: “Command exceeded allowed execution time” when setting up replication?[](#message-command-exceeded-allowed-execution-time-when-setting-up-replication "Permalink") + +在**辅助**节点上[启动复制过程](database.html#step-3-initiate-the-replication-process)时可能会发生这种情况,并表明您的初始数据集太大,无法在默认超时(30 分钟)内进行复制. + +重新运行`gitlab-ctl replicate-geo-database` ,但是为`--backup-timeout`包含一个更大的值: + +``` +sudo gitlab-ctl \ + replicate-geo-database \ + --host= \ + --slot-name= \ + --backup-timeout=21600 +``` + +这将使初始复制最多需要六个小时才能完成,而不是默认的三十分钟. 根据安装要求进行调整. + +### Message: “PANIC: could not write to file `pg_xlog/xlogtemp.123`: No space left on device”[](#message-panic-could-not-write-to-file-pg_xlogxlogtemp123-no-space-left-on-device "Permalink") + +确定**主**数据库中是否有未使用的复制插槽. 这可能导致在`pg_xlog`建立大量的日志数据. 删除未使用的插槽可以减少`pg_xlog`使用的空间. + +1. 启动 PostgreSQL 控制台会话: + + ``` + sudo gitlab-psql + ``` + + 注意: **注意:**使用`gitlab-rails dbconsole`无效,因为管理复制插槽需要超级用户权限. + +2. 使用以下方法查看您的复制插槽: + + ``` + SELECT * FROM pg_replication_slots; + ``` + +`active`为`f`插槽不活动. + +* 当该插槽应处于活动状态时,因为您已使用该插槽配置了**辅助**节点,请登录到该**辅助**节点,并检查 PostgreSQL 日志为什么复制未运行. + +* 如果您不再使用该插槽(例如,您不再启用地理位置),则可以在 PostgreSQL 控制台会话中将其删除: + + ``` + SELECT pg_drop_replication_slot(''); + ``` + +### Message: “ERROR: canceling statement due to conflict with recovery”[](#message-error-canceling-statement-due-to-conflict-with-recovery "Permalink") + +在正常使用情况下,此错误很少会发生,并且系统具有足够的恢复能力. + +但是,在某些情况下,辅助数据库上的某些数据库查询可能运行时间过长,从而增加了此错误的发生频率. 在某些时候,其中某些查询由于每次都会被取消而永远无法完成. + +这些长期运行的查询[计划在将来删除](https://gitlab.com/gitlab-org/gitlab/-/issues/34269) ,但作为解决方法,我们建议启用[hot_standby_feedback](https://s0www0postgresql0org.icopy.site/docs/10/hot-standby.html) . 这增加了**主**节点上发生膨胀的可能性,因为它阻止了`VACUUM`删除最近失效的行. 但是,它已在 GitLab.com 上成功用于生产中. + +要启用`hot_standby_feedback` ,请将以下内容添加到**辅助**节点上的`/etc/gitlab/gitlab.rb` : + +``` +postgresql['hot_standby_feedback'] = 'on' +``` + +然后重新配置 GitLab: + +``` +sudo gitlab-ctl reconfigure +``` + +为了帮助我们解决这个问题,可以考虑在评论[这个问题](https://gitlab.com/gitlab-org/gitlab/-/issues/4489) . + +### Message: `LOG: invalid CIDR mask in address`[](#message-log--invalid-cidr-mask-in-address "Permalink") + +这发生在`postgresql['md5_auth_cidr_addresses']`格式错误的地址上. + +``` +2020-03-20_23:59:57.60499 LOG: invalid CIDR mask in address "***" +2020-03-20_23:59:57.60501 CONTEXT: line 74 of configuration file "/var/opt/gitlab/postgresql/data/pg_hba.conf" +``` + +要解决此问题,请更新`postgresql['md5_auth_cidr_addresses']`下`/etc/gitlab/gitlab.rb`的 IP 地址,以遵守 CIDR 格式(即`1.2.3.4/32` ). + +### Message: `LOG: invalid IP mask "md5": Name or service not known`[](#message-log--invalid-ip-mask-md5-name-or-service-not-known "Permalink") + +当您在`postgresql['md5_auth_cidr_addresses']`添加了没有子网掩码的 IP 地址时,就会发生这种情况. + +``` +2020-03-21_00:23:01.97353 LOG: invalid IP mask "md5": Name or service not known +2020-03-21_00:23:01.97354 CONTEXT: line 75 of configuration file "/var/opt/gitlab/postgresql/data/pg_hba.conf" +``` + +要解决此问题, `/etc/gitlab/gitlab.rb`在`postgresql['md5_auth_cidr_addresses']`下`postgresql['md5_auth_cidr_addresses']`添加子网掩码,以遵守 CIDR 格式(即`1.2.3.4/32` ). + +### Very large repositories never successfully synchronize on the **secondary** node[](#very-large-repositories-never-successfully-synchronize-on-the-secondary-node "Permalink") + +GitLab 对所有存储库克隆都设置了超时,包括项目导入和地理同步操作. 如果**主数据库**上的存储库的新`git clone`花费几分钟以上,则您可能会受到此影响. + +要增加超时,请将以下行添加到**辅助**节点上的`/etc/gitlab/gitlab.rb` : + +``` +gitlab_rails['gitlab_shell_git_timeout'] = 10800 +``` + +然后重新配置 GitLab: + +``` +sudo gitlab-ctl reconfigure +``` + +这会将超时增加到三个小时(10800 秒). 选择足够长的时间来容纳您最大的存储库的完整克隆. + +### New LFS objects are never replicated[](#new-lfs-objects-are-never-replicated "Permalink") + +如果新的 LFS 对象永远不会复制到辅助 Geo 节点,请检查您正在运行的 GitLab 版本. GitLab 版本 11.11.x 或 12.0.x 受[错误](https://gitlab.com/gitlab-org/gitlab/-/issues/32696)影响, [该错误导致新的 LFS 对象无法复制到 Geo 辅助节点](https://gitlab.com/gitlab-org/gitlab/-/issues/32696) . + +要解决此问题,请升级到 GitLab 12.1 或更高版本. + +### Resetting Geo **secondary** node replication[](#resetting-geo-secondary-node-replication "Permalink") + +如果您使**辅助**节点处于损坏状态,并且想要重置复制状态(从头开始),那么可以采取以下步骤来帮助您: + +1. 停止 Sidekiq 和 Geo LogCursor + + 可以使 Sidekiq 正常停止,但可以使其停止获取新作业,并等到当前作业完成处理为止. + + 您需要在第一阶段发送**SIGTSTP 终止**信号,并在所有作业完成后向它们发送**SIGTERM** . 否则,只需使用`gitlab-ctl stop`命令. + + ``` + gitlab-ctl status sidekiq + # run: sidekiq: (pid 10180) <- this is the PID you will use + kill -TSTP 10180 # change to the correct PID + + gitlab-ctl stop sidekiq + gitlab-ctl stop geo-logcursor + ``` + + 您可以查看 Sidekiq 日志以了解 Sidekiq 作业处理何时完成: + + ``` + gitlab-ctl tail sidekiq + ``` + +2. 重命名存储库存储文件夹并创建新的. 如果您不担心可能的孤立目录和文件,则只需跳过此步骤. + + ``` + mv /var/opt/gitlab/git-data/repositories /var/opt/gitlab/git-data/repositories.old + mkdir -p /var/opt/gitlab/git-data/repositories + chown git:git /var/opt/gitlab/git-data/repositories + ``` + + **提示**您可能希望将来在确认不再需要`/var/opt/gitlab/git-data/repositories.old`时将其删除,以节省磁盘空间. +3. *(可选)*重命名其他数据文件夹并创建新的 + + **警告** : **辅助**节点上可能仍有文件已从**主**节点中删除,但未反映出删除情况. 如果您跳过此步骤,它们将永远不会从此 Geo 节点中删除. + + 任何上载的内容(如文件附件,化身或 LFS 对象)都存储在以下两个路径之一的子文件夹中: + + * `/var/opt/gitlab/gitlab-rails/shared` + * `/var/opt/gitlab/gitlab-rails/uploads` + + 要重命名它们: + + ``` + gitlab-ctl stop + + mv /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-rails/shared.old + mkdir -p /var/opt/gitlab/gitlab-rails/shared + + mv /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/uploads.old + mkdir -p /var/opt/gitlab/gitlab-rails/uploads + + gitlab-ctl start geo-postgresql + ``` + + 重新配置以便重新创建文件夹并确保权限和所有权正确 + + ``` + gitlab-ctl reconfigure + ``` + +4. 重置跟踪数据库 + + ``` + gitlab-rake geo:db:drop # on a secondary app node + gitlab-ctl reconfigure # on the tracking database node + gitlab-rake geo:db:setup # on a secondary app node + ``` + +5. 重新启动先前停止的服务 + + ``` + gitlab-ctl start + ``` + +6. 刷新外部数据包装器表 + + ``` + gitlab-rake geo:db:refresh_foreign_tables + ``` + +## Fixing errors during a failover or when promoting a secondary to a primary node[](#fixing-errors-during-a-failover-or-when-promoting-a-secondary-to-a-primary-node "Permalink") + +以下是故障转移期间或通过解决策略将辅助节点提升为主节点时可能遇到的错误. + +### Message: ActiveRecord::RecordInvalid: Validation failed: Name has already been taken[](#message-activerecordrecordinvalid-validation-failed-name-has-already-been-taken "Permalink") + +[升级**辅助**节点时](../disaster_recovery/index.html#step-3-promoting-a-secondary-node) ,您可能会遇到以下错误: + +``` +Running gitlab-rake geo:set_secondary_as_primary... + +rake aborted! +ActiveRecord::RecordInvalid: Validation failed: Name has already been taken +/opt/gitlab/embedded/service/gitlab-rails/ee/lib/tasks/geo.rake:236:in `block (3 levels) in ' +/opt/gitlab/embedded/service/gitlab-rails/ee/lib/tasks/geo.rake:221:in `block (2 levels) in ' +/opt/gitlab/embedded/bin/bundle:23:in `load' +/opt/gitlab/embedded/bin/bundle:23:in `
    ' +Tasks: TOP => geo:set_secondary_as_primary +(See full trace by running task with --trace) + +You successfully promoted this node! +``` + +如果您在运行`gitlab-rake geo:set_secondary_as_primary`或`gitlab-ctl promote-to-primary-node`时遇到此消息,请执行`gitlab-rake geo:set_secondary_as_primary`任一操作: + +* 输入 Rails 控制台并运行: + + ``` + Rails.application.load_tasks; nil + Gitlab::Geo.expire_cache! + Rake::Task['geo:set_secondary_as_primary'].invoke + ``` + +* 如果安全的话,升级到 GitLab 12.6.3 或更高版本. 例如,如果故障转移只是一个测试. [缓存相关的错误](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22021)是固定的. + +### Message: `NoMethodError: undefined method `secondary?' for nil:NilClass`[](#message-nomethoderror-undefined-method-secondary-for-nilnilclass "Permalink") + +[升级**辅助**节点时](../disaster_recovery/index.html#step-3-promoting-a-secondary-node) ,您可能会遇到以下错误: + +``` +sudo gitlab-rake geo:set_secondary_as_primary + +rake aborted! +NoMethodError: undefined method `secondary?' for nil:NilClass +/opt/gitlab/embedded/service/gitlab-rails/ee/lib/tasks/geo.rake:232:in `block (3 levels) in ' +/opt/gitlab/embedded/service/gitlab-rails/ee/lib/tasks/geo.rake:221:in `block (2 levels) in ' +/opt/gitlab/embedded/bin/bundle:23:in `load' +/opt/gitlab/embedded/bin/bundle:23:in `
    ' +Tasks: TOP => geo:set_secondary_as_primary +(See full trace by running task with --trace) +``` + +该命令仅应在辅助节点上执行,如果尝试在主节点上运行此命令,则会显示此错误. + +### Message: `sudo: gitlab-pg-ctl: command not found`[](#message-sudo-gitlab-pg-ctl-command-not-found "Permalink") + +When [promoting a **secondary** node with multiple servers](../disaster_recovery/index.html#promoting-a-secondary-node-with-multiple-servers), you need to run the `gitlab-pg-ctl` command to promote the PostgreSQL read-replica database. + +在 GitLab 12.8 和更早版本中,此命令将失败,并显示以下消息: + +``` +sudo: gitlab-pg-ctl: command not found +``` + +在这种情况下,解决方法是使用二进制文件的完整路径,例如: + +``` +sudo /opt/gitlab/embedded/bin/gitlab-pg-ctl promote +``` + +GitLab 12.9 及更高版本[不受此错误影响](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5147) . + +## Fixing Foreign Data Wrapper errors[](#fixing-foreign-data-wrapper-errors "Permalink") + +本节介绍解决潜在的外部数据包装器错误的方法. + +### “Foreign Data Wrapper (FDW) is not configured” error[](#foreign-data-wrapper-fdw-is-not-configured-error "Permalink") + +When setting up Geo, you might see this warning in the `gitlab-rake gitlab:geo:check` output: + +``` +GitLab Geo tracking database Foreign Data Wrapper schema is up-to-date? ... foreign data wrapper is not configured +``` + +有几点要记住: + +1. FDW 设置在地理**跟踪**数据库上配置. +2. 配置的外部服务器允许登录到 Geo **二级**只读数据库. + +默认情况下,Geo 辅助数据库和跟踪数据库在不同端口上的同一主机上运行. 即分别是 5432 和 5431. + +#### Checking configuration[](#checking-configuration "Permalink") + +**注意:**以下步骤仅适用于 Omnibus 安装. 在 GitLab 11.5 中**已不建议**在基于源的安装中使用 Geo. + +要检查配置: + +1. SSH 进入**辅助**节点中的应用程序节点: + + ``` + sudo -i + ``` + + 注意:应用程序节点是指至少运行以下服务之一的任何计算机: + + * `puma` + * `unicorn` + * `sidekiq` + * `geo-logcursor` +2. 输入数据库控制台: + + 如果跟踪数据库在同一节点上运行: + + ``` + gitlab-geo-psql + ``` + + 或者,如果跟踪数据库在其他节点上运行,则在进入数据库控制台时必须指定用户和主机: + + ``` + gitlab-geo-psql -U gitlab_geo -h + ``` + + 系统将提示您输入`gitlab_geo`用户的密码. 您可以在`/etc/gitlab/gitlab.rb`以纯文本`/etc/gitlab/gitlab.rb`找到它: + + ``` + geo_secondary['db_password'] = '' + ``` + + 通常在[步骤 3:在辅助节点上配置跟踪数据库时在跟踪数据库上](multiple_servers.html#step-3-configure-the-tracking-database-on-the-secondary-node)设置此密码,而在[步骤 4:在辅助节点上配置前端应用程序服务器](multiple_servers.html#step-4-configure-the-frontend-application-servers-on-the-secondary-node)期间在应用程序节点上设置该密码. + +3. 使用以下语句检查是否存在任何表: + + ``` + SELECT * from information_schema.foreign_tables; + ``` + + 如果一切正常,您应该看到类似以下内容: + + ``` + gitlabhq_geo_production=# SELECT * from information_schema.foreign_tables; + foreign_table_catalog | foreign_table_schema | foreign_table_name | foreign_server_catalog | foreign_server_name + -------------------------+----------------------+-------------------------------------------------+-------------------------+--------------------- + gitlabhq_geo_production | gitlab_secondary | abuse_reports | gitlabhq_geo_production | gitlab_secondary + gitlabhq_geo_production | gitlab_secondary | appearances | gitlabhq_geo_production | gitlab_secondary + gitlabhq_geo_production | gitlab_secondary | application_setting_terms | gitlabhq_geo_production | gitlab_secondary + gitlabhq_geo_production | gitlab_secondary | application_settings | gitlabhq_geo_production | gitlab_secondary + + ``` + + 但是,如果查询返回`0 rows` ,则继续进行下一步. + +4. 通过`\des+`检查外部服务器映射是否正确. 结果应如下所示: + + ``` + gitlabhq_geo_production=# \des+ + List of foreign servers + -[ RECORD 1 ]--------+------------------------------------------------------------ + Name | gitlab_secondary + Owner | gitlab-psql + Foreign-data wrapper | postgres_fdw + Access privileges | "gitlab-psql"=U/"gitlab-psql" + + | gitlab_geo=U/"gitlab-psql" + Type | + Version | + FDW Options | (host '0.0.0.0', port '5432', dbname 'gitlabhq_production') + Description | + ``` + + **注意:请**特别注意 FDW 选项下的主机和端口. 该配置应指向地理辅助数据库. + + 如果需要尝试更改主机或密码,则以下查询演示了如何: + + ``` + ALTER SERVER gitlab_secondary OPTIONS (SET host ''); + ALTER SERVER gitlab_secondary OPTIONS (SET port 5432); + ``` + + 如果更改主机和/或端口,则还必须在`/etc/gitlab/gitlab.rb`调整以下设置并运行`gitlab-ctl reconfigure` : + + * `gitlab_rails['db_host']` + * `gitlab_rails['db_port']` +5. 检查通过`\deu+`是否正确配置了用户映射: + + ``` + gitlabhq_geo_production=# \deu+ + List of user mappings + Server | User name | FDW Options + ------------------+------------+-------------------------------------------------------------------------------- + gitlab_secondary | gitlab_geo | ("user" 'gitlab', password 'YOUR-PASSWORD-HERE') + (1 row) + ``` + + 确保密码正确. 您可以通过运行`psql`来测试登录是否有效: + + ``` + # Connect to the tracking database as the `gitlab_geo` user + sudo \ + -u git /opt/gitlab/embedded/bin/psql \ + -h /var/opt/gitlab/geo-postgresql \ + -p 5431 \ + -U gitlab_geo \ + -W \ + -d gitlabhq_geo_production + ``` + + 如果需要更正密码,以下查询将显示如何: + + ``` + ALTER USER MAPPING FOR gitlab_geo SERVER gitlab_secondary OPTIONS (SET password ''); + ``` + + 如果更改用户或密码,则还必须在`/etc/gitlab/gitlab.rb`调整以下设置并运行`gitlab-ctl reconfigure` : + + * `gitlab_rails['db_username']` + * `gitlab_rails['db_password']` + + 如果要[在辅助数据库前面](database.html#pgbouncer-support-optional)使用[PgBouncer](database.html#pgbouncer-support-optional) ,请确保更新以下设置: + + * `geo_postgresql['fdw_external_user']` + * `geo_postgresql['fdw_external_password']` + +#### Manual reload of FDW schema[](#manual-reload-of-fdw-schema "Permalink") + +如果仍然无法使 FDW 正常工作,则可能需要尝试手动重新加载 FDW 模式. 手动重新加载 FDW 模式: + +1. 在运行 Geo 跟踪数据库的节点上,通过`gitlab_geo`用户进入 PostgreSQL 控制台: + + ``` + sudo \ + -u git /opt/gitlab/embedded/bin/psql \ + -h /var/opt/gitlab/geo-postgresql \ + -p 5431 \ + -U gitlab_geo \ + -W \ + -d gitlabhq_geo_production + ``` + + 确保为您的配置调整端口和主机名. 可能会要求您输入密码. + +2. 通过以下方式重新加载架构: + + ``` + DROP SCHEMA IF EXISTS gitlab_secondary CASCADE; + CREATE SCHEMA gitlab_secondary; + GRANT USAGE ON FOREIGN SERVER gitlab_secondary TO gitlab_geo; + IMPORT FOREIGN SCHEMA public FROM SERVER gitlab_secondary INTO gitlab_secondary; + ``` + +3. 测试查询是否有效: + + ``` + SELECT * from information_schema.foreign_tables; + SELECT * FROM gitlab_secondary.projects limit 1; + ``` + +### “Geo database has an outdated FDW remote schema” error[](#geo-database-has-an-outdated-fdw-remote-schema-error "Permalink") + +GitLab 可能会因`Geo database has an outdated FDW remote schema`错误`Geo database has an outdated FDW remote schema`消息而出错. + +例如: + +``` +Geo database has an outdated FDW remote schema. It contains 229 of 236 expected tables. Please refer to Geo Troubleshooting. +``` + +要解决此问题,请在**辅助服务器**上运行以下命令: + +``` +sudo gitlab-rake geo:db:refresh_foreign_tables +``` + +## Expired artifacts[](#expired-artifacts "Permalink") + +如果您出于某种原因注意到,地理辅助节点上的工件比地理主节点上的工件更多,则可以使用 Rake 任务来[清理孤立的工件文件](../../../raketasks/cleanup.html#remove-orphan-artifact-files) . + +在 Geo **辅助**节点上,此命令还将清除与磁盘上的孤立文件有关的所有 Geo 注册表记录. + +## Fixing sign in errors[](#fixing-sign-in-errors "Permalink") + +### Message: The redirect URI included is not valid[](#message-the-redirect-uri-included-is-not-valid "Permalink") + +如果您能够登录到**主**节点,但是在尝试登录到**辅助**节点时收到此错误,则应检查 Geo 节点的 URL 是否与其外部 URL 匹配. + +1. 首先,访问 **管理区>** **地理位置** . +2. 找到受影响的**辅助节点** ,然后单击" **编辑"** . +3. 确保**URL**字段与在**辅助**节点的前端服务器上`external_url "https://gitlab.example.com"`中的`/etc/gitlab/gitlab.rb`中找到的值匹配. + +## Fixing common errors[](#fixing-common-errors "Permalink") + +本部分介绍了管理界面中报告的常见错误以及如何修复它们. + +### Geo database configuration file is missing[](#geo-database-configuration-file-is-missing "Permalink") + +GitLab 找不到或没有访问`database_geo.yml`配置文件的权限. + +在 Omnibus GitLab 安装中,该文件应位于`/var/opt/gitlab/gitlab-rails/etc` . 如果它不存在或对其进行了无意的更改,请运行`sudo gitlab-ctl reconfigure`将其恢复到正确的状态. + +如果此路径安装在远程卷上,请检查您的卷配置,并具有正确的权限. + +### An existing tracking database cannot be reused[](#an-existing-tracking-database-cannot-be-reused "Permalink") + +Geo cannot reuse an existing tracking database. + +最安全的方式是使用全新的[辅助节点](#resetting-geo-secondary-node-replication) ,或通过遵循[重置地理辅助节点复制来重置](#resetting-geo-secondary-node-replication)整个[辅助节点](#resetting-geo-secondary-node-replication) . + +### Geo node has a database that is writable which is an indication it is not configured for replication with the primary node[](#geo-node-has-a-database-that-is-writable-which-is-an-indication-it-is-not-configured-for-replication-with-the-primary-node "Permalink") + +此错误是指 Geo 希望**辅助**节点上的数据库副本存在问题. 它通常意味着: + +* 使用了不受支持的复制方法(例如,逻辑复制). +* 设置[地理数据库复制](database.html)的说明未正确遵循. +* 您的数据库连接详细信息不正确,即您在`/etc/gitlab/gitlab.rb`文件中指定了错误的用户. + +与**辅助**节点混淆的一个常见原因是它需要两个单独的 PostgreSQL 实例: + +* **主**节点的只读副本. +* 包含复制元数据的常规可写实例. 即,地理位置跟踪数据库. + +### Geo node does not appear to be replicating the database from the primary node[](#geo-node-does-not-appear-to-be-replicating-the-database-from-the-primary-node "Permalink") + +导致数据库无法正确复制的最常见问题是: + +* **Secondary** nodes cannot reach the **primary** node. Check credentials, firewall rules, etc. +* SSL 证书问题. 确保从**主**节点复制了`/etc/gitlab/gitlab-secrets.json` . +* 数据库存储磁盘已满. +* 数据库复制插槽配置错误. +* 数据库未使用复制插槽或其他替代方法,由于已清除 WAL 文件,因此无法追赶. + +确保按照[地理数据库复制](database.html)说明进行支持的配置. + +### Geo database version (…) does not match latest migration (…)[](#geo-database-version--does-not-match-latest-migration- "Permalink") + +如果您使用的是 Omnibus GitLab 安装,则升级期间可能会失败. 您可以: + +* Run `sudo gitlab-ctl reconfigure`. +* 通过运行以下`sudo gitlab-rake geo:db:migrate`手动触发数据库迁移: `sudo gitlab-rake geo:db:migrate`作为**辅助**节点上的 root 用户. + +### Geo database is not configured to use Foreign Data Wrapper[](#geo-database-is-not-configured-to-use-foreign-data-wrapper "Permalink") + +此错误表示地理位置跟踪数据库未配置 FDW 服务器和凭据. + +See [“Foreign Data Wrapper (FDW) is not configured” error?](#foreign-data-wrapper-fdw-is-not-configured-error). + +### GitLab indicates that more than 100% of repositories were synced[](#gitlab-indicates-that-more-than-100-of-repositories-were-synced "Permalink") + +这可能是由项目注册表中的孤立记录引起的. 您可以[使用 Rake 任务](../../../administration/raketasks/geo.html#remove-orphaned-project-registries)清除它们. + +### Geo Admin Area returns 404 error for a secondary node[](#geo-admin-area-returns-404-error-for-a-secondary-node "Permalink") + +有时`sudo gitlab-rake gitlab:geo:check`指示**辅助**节点运行`sudo gitlab-rake gitlab:geo:check` ,但是在**主**节点的地理管理区域中返回了**辅助**节点 404 错误. + +解决此问题的方法: + +* 尝试使用`sudo gitlab-ctl restart` **辅助** `sudo gitlab-ctl restart` . +* 检查`/var/log/gitlab/gitlab-rails/geo.log`以查看**辅助**节点是否正在使用 IPv6 将其状态发送到**主要**节点. 如果是这样,请使用`/etc/hosts`文件中的 IPv4 将条目添加到**主**节点. 或者,您应该[在**主**节点上启用 IPv6](https://docs.gitlab.com/omnibus/settings/nginx.html) . \ No newline at end of file diff --git a/_book/docs/504.md b/_book/docs/504.md new file mode 100644 index 0000000000000000000000000000000000000000..996418b37d442ff1c13f1202bd813ce4668ae7b4 --- /dev/null +++ b/_book/docs/504.md @@ -0,0 +1,122 @@ +# Geo validation tests + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/geo_validation_tests.html](https://docs.gitlab.com/ee/administration/geo/replication/geo_validation_tests.html) + +* [GitLab upgrades](#gitlab-upgrades) + * [June 2020](#june-2020) + * [February 2020](#february-2020) + * [January 2020](#january-2020) + * [October 2019](#october-2019) +* [PostgreSQL upgrades](#postgresql-upgrades) + * [April 2020](#april-2020) + * [September 2019](#september-2019) + +# Geo validation tests[](#geo-validation-tests "Permalink") + +Geo 团队对常见的部署配置执行手动测试和验证,以确保在次要的 GitLab 版本和主要的 PostgreSQL 数据库版本之间升级时,Geo 可以正常工作. + +本部分包含近期验证测试的日记以及相关问题的链接. + +## GitLab upgrades[](#gitlab-upgrades "Permalink") + +以下是我们执行的 GitLab 升级验证测试. + +### June 2020[](#june-2020 "Permalink") + +[Upgrade Geo multi-server installation](https://gitlab.com/gitlab-org/gitlab/-/issues/223284): + +* 说明:在多服务器配置中测试了从 GitLab 12.9.10 升级到 12.10.12 软件包的过程. 使用循环管道和 HAProxy 统计信息显示板监视停机时间. +* 结果:部分成功,因为我们在主站点和辅助站点的升级过程中观察到停机时间. +* 跟进问题/行动: + * [修复多节点 Geo 部署的零停机升级过程/说明](https://gitlab.com/gitlab-org/gitlab/-/issues/225684) + * [Geo:check Rake 任务:排除 AuthorizedKeysCommand 检查节点是否未运行 Puma / Unicorn](https://gitlab.com/gitlab-org/gitlab/-/issues/225454) + * [在下一个升级问题中更新说明,以包括监视 HAProxy 仪表板](https://gitlab.com/gitlab-org/gitlab/-/issues/225359) + +[Upgrade Geo multi-server installation](https://gitlab.com/gitlab-org/gitlab/-/issues/208104): + +* 描述:在多服务器配置中测试了从 GitLab 12.8.1 到 12.9.10 软件包的升级. +* 结果:部分成功,因为我们在演示过程中没有运行循环管道来验证零停机时间. +* 后续问题: + * [阐明 hup Puma / Unicorn 应该包含部署节点](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5460) + * [升级到 12.9.10 后调查 MR 创建失败](https://gitlab.com/gitlab-org/gitlab/-/issues/223282) . + +### February 2020[](#february-2020 "Permalink") + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/201837): + +* 说明:在多节点配置中测试了从 GitLab 12.7.5 升级到最新的 GitLab 12.8 软件包的过程. +* 结果:部分成功,因为我们在演示过程中没有运行循环管道来监视停机时间. + +### January 2020[](#january-2020 "Permalink") + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/200085): + +* 说明:在多节点配置中测试了从 GitLab 12.6.x 升级到最新的 GitLab 12.7 软件包的过程. +* 结果:升级测试成功. +* 后续问题: + * [调查 Geo 端到端测试失败](https://gitlab.com/gitlab-org/gitlab/-/issues/201823) . + * [将更多日志记录添加到 Geo 端到端测试中](https://gitlab.com/gitlab-org/gitlab/-/issues/201830) . + * [零停机升级期间,多余的服务会重新启动](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5047) . + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/199836): + +* 描述:在多节点配置中测试了从 GitLab 12.5.7 到 GitLab 12.6.6 的升级. +* Outcome: Upgrade test was successful. +* 后续问题: [更新文档以实现零停机时间升级,以确保未使用部署节点](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5046) . + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/37044): + +* 说明:在多节点配置中测试了从 GitLab 12.4.x 升级到最新的 GitLab 12.5 软件包的过程. +* 结果:升级测试成功. +* 后续问题: + * [研究为什么 HTTP 推送规范在主节点上失败](https://gitlab.com/gitlab-org/gitlab/-/issues/199825) . + * [研究是否应修改文档以包括刷新外部表任务](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5041) . + +### October 2019[](#october-2019 "Permalink") + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/35262): + +* 说明:在多节点配置中测试了从 GitLab 12.3.5 升级到 GitLab 12.4.1 的过程. +* 结果:升级测试成功. + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/32437): + +* 说明:已测试从 GitLab 12.2.8 升级到 GitLab 12.3.5. +* 结果:升级测试成功. + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/32435): + +* 说明:已测试从 GitLab 12.1.9 升级到 GitLab 12.2.8 的过程. +* 结果:由于可能的配置错误问题而部分成功. + +## PostgreSQL upgrades[](#postgresql-upgrades "Permalink") + +以下是我们执行的 PostgreSQL 升级验证测试. + +### April 2020[](#april-2020 "Permalink") + +[PostgreSQL 11 upgrade procedure for Geo installations](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4975): + +* 描述:在将 PostgreSQL 11 设为 GitLab 12.10 中的默认 PostgreSQL 版本之前,我们在 GitLab 12.9 的 Geo 部署中测试了升级到 PostgreSQL 11 的能力. +* 结果:部分成功. 在具有单独的跟踪数据库的多节点配置中发现了问题,并提出了在启用 Geo 时允许自动升级的问题. +* 后续问题: + * [`replicate-geo-database`错误地尝试备份存储库](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5241) . + * [`pg-upgrade`无法升级独立的 Geo 跟踪数据库](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5242) . + * [`revert-pg-upgrade`无法降级 Geo Secondary 的独立跟踪数据库的 PostgreSQL 数据](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5243) . + * [`gitlab-ctl pg-upgrade`结束时,Geo 辅助只读副本上的超时错误](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5235) . + +[Verify Geo installation with PostgreSQL 11](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4971): + +* 说明:在将 PostgreSQL 11 设置为 GitLab 12.10 中的 PostgreSQL 的默认版本之前,我们测试了 GitLab 12.9 的全新安装以及在 PostgreSQL 11 中安装了 Geo 的情况. +* 结果:安装测试成功. + +### September 2019[](#september-2019 "Permalink") + +[Test and validate PostgreSQL 10.0 upgrade for Geo](https://gitlab.com/gitlab-org/gitlab/-/issues/12092): + +* 说明:在 12.0 版本中,GitLab 需要升级到 PostgreSQL 10.0\. 我们测试了从 GitLab 11.11.5 到 GitLab 12.1.8 的各种升级方案. +* 结果:升级时发现了多个问题,并在后续问题中得到解决. +* 后续问题: + * [在多节点 Geo 设置中的 Redis 节点上, `gitlab-ctl`重新配置失败](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4706) . + * [从 12.0.9 到 12.1.9 的地理多节点升级不会升级 PostgreSQL](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4705) . + * [升级到 12.1.9 后,在多节点设置中的应用服务器上刷新外部表失败](https://gitlab.com/gitlab-org/gitlab/-/issues/32119) . \ No newline at end of file diff --git a/_book/docs/505.md b/_book/docs/505.md new file mode 100644 index 0000000000000000000000000000000000000000..048df4ebabc67ad132f1b8459a7475da2a3a5b1d --- /dev/null +++ b/_book/docs/505.md @@ -0,0 +1,339 @@ +# Disaster Recovery (Geo) + +> 原文:[https://docs.gitlab.com/ee/administration/geo/disaster_recovery/](https://docs.gitlab.com/ee/administration/geo/disaster_recovery/) + +* [Promoting a **secondary** Geo node in single-secondary configurations](#promoting-a-secondary-geo-node-in-single-secondary-configurations) + * [Step 1\. Allow replication to finish if possible](#step-1-allow-replication-to-finish-if-possible) + * [Step 2\. Permanently disable the **primary** node](#step-2-permanently-disable-the-primary-node) + * [Step 3\. Promoting a **secondary** node](#step-3-promoting-a-secondary-node) + * [Promoting a **secondary** node running on a single machine](#promoting-a-secondary-node-running-on-a-single-machine) + * [Promoting a **secondary** node with multiple servers](#promoting-a-secondary-node-with-multiple-servers) + * [Promoting a **secondary** node with an external PostgreSQL database](#promoting-a-secondary-node-with-an-external-postgresql-database) + * [Step 4\. (Optional) Updating the primary domain DNS record](#step-4-optional-updating-the-primary-domain-dns-record) + * [Step 5\. (Optional) Add **secondary** Geo node to a promoted **primary** node](#step-5-optional-add-secondary-geo-node-to-a-promoted-primary-node) + * [Step 6\. (Optional) Removing the secondary’s tracking database](#step-6-optional-removing-the-secondarys-tracking-database) +* [Promoting secondary Geo replica in multi-secondary configurations](#promoting-secondary-geo-replica-in-multi-secondary-configurations) + * [Step 1\. Prepare the new **primary** node to serve one or more **secondary** nodes](#step-1-prepare-the-new-primary-node-to-serve-one-or-more-secondary-nodes) + * [Step 2\. Initiate the replication process](#step-2-initiate-the-replication-process) +* [Troubleshooting](#troubleshooting) + * [I followed the disaster recovery instructions and now two-factor auth is broken](#i-followed-the-disaster-recovery-instructions-and-now-two-factor-auth-is-broken) + +# Disaster Recovery (Geo)[](#disaster-recovery-geo-premium-only "Permalink") + +Geo 复制您的数据库,Git 存储库和其他少量资产. 将来,我们将支持和复制更多数据,使您能够在灾难情况下以最少的精力进行故障转移. + +有关更多信息,请参见地[电流限制](../replication/index.html#current-limitations) . + +**警告:**多辅助配置的灾难恢复在**Alpha 中** . 有关最新更新,请查看多级[灾难恢复史诗](https://gitlab.com/groups/gitlab-org/-/epics/65) . + +## Promoting a **secondary** Geo node in single-secondary configurations[](#promoting-a-secondary-geo-node-in-single-secondary-configurations "Permalink") + +目前,我们不提供自动方式来升级 Geo 副本并进行故障转移,但是如果您具有对该计算机的`root`访问权,则可以手动进行. + +此过程将**辅助**地理节点升级为**主要**节点. 为了尽快恢复地理冗余,应在遵循这些说明后立即添加新的**辅助**节点. + +### Step 1\. Allow replication to finish if possible[](#step-1-allow-replication-to-finish-if-possible "Permalink") + +如果**辅助**节点仍在从**主**节点复制数据,请尽可能严格遵循[计划的故障转移文档](planned_failover.html) ,以避免不必要的数据丢失. + +### Step 2\. Permanently disable the **primary** node[](#step-2-permanently-disable-the-primary-node "Permalink") + +**警告:**如果**主**节点脱机,则可能是**主**节点上保存的数据尚未复制到**辅助**节点. 如果继续,此数据应视为丢失. + +如果**主**节点发生故障,则应尽一切可能避免发生裂脑情况,即在两个不同的 GitLab 实例中可能发生写操作,从而使恢复工作复杂化. 因此,为故障转移做准备,我们必须禁用**主**节点. + +1. SSH 进入**主**节点以停止并禁用 GitLab,如果可能的话: + + ``` + sudo gitlab-ctl stop + ``` + + 如果服务器意外重启,请阻止 GitLab 重新启动: + + ``` + sudo systemctl disable gitlab-runsvdir + ``` + + **注意:(** **仅 CentOS** )在 CentOS 6 或更旧的版本中,如果没有可用的机器重启,没有简单的方法可以阻止启动[GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3058) (请参阅[Omnibus GitLab 问题#3058](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3058) ). 完全卸载 GitLab 软件包可能是最安全的: + + ``` + yum remove gitlab-ee + ``` + + **注意:** ( **Ubuntu 14.04 LTS** )如果您使用的是较旧版本的 Ubuntu 或基于 Upstart init 系统的任何其他发行版,则可以通过以下操作来阻止 GitLab 在计算机重启时启动: + + ``` + initctl stop gitlab-runsvvdir + echo 'manual' > /etc/init/gitlab-runsvdir.override + initctl reload-configuration + ``` + +2. 如果您没有对**主**节点的 SSH 访问权限,请使计算机脱机并通过任何方式阻止其重启. 由于您可能有很多方法可以完成此操作,因此我们将避免使用单个建议. 您可能需要: + + * 重新配置负载均衡器. + * 更改 DNS 记录(例如,将主要 DNS 记录指向**辅助**节点,以停止使用**主要**节点). + * 停止虚拟服务器. + * 阻止通过防火墙的流量. + * 从**主**节点撤消对象存储权限. + * 物理断开机器连接. +3. 如果您打算[更新主域 DNS 记录](#step-4-optional-updating-the-primary-domain-dns-record) ,则可能希望立即降低 TTL,以加快传播速度. + +### Step 3\. Promoting a **secondary** node[](#step-3-promoting-a-secondary-node "Permalink") + +升级辅助服务器时,请注意以下事项: + +* A new **secondary** should not be added at this time. If you want to add a new **secondary**, do this after you have completed the entire process of promoting the **secondary** to the **primary**. +* 如果遇到`ActiveRecord::RecordInvalid: Validation failed: Name has already been taken`在此过程中, `ActiveRecord::RecordInvalid: Validation failed: Name has already been taken`错误,请阅读[故障排除建议](../replication/troubleshooting.html#fixing-errors-during-a-failover-or-when-promoting-a-secondary-to-a-primary-node) . + +#### Promoting a **secondary** node running on a single machine[](#promoting-a-secondary-node-running-on-a-single-machine "Permalink") + +1. SSH 登录到**辅助**节点并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 编辑`/etc/gitlab/gitlab.rb`以通过删除启用`geo_secondary_role`所有行来反映其新的**主要**状态: + + ``` + ## In pre-11.5 documentation, the role was enabled as follows. Remove this line. + geo_secondary_role['enable'] = true + + ## In 11.5+ documentation, the role was enabled as follows. Remove this line. + roles ['geo_secondary_role'] + ``` + +3. 将**辅助**节点升级为**主要**节点. + + 在将辅助节点升级为主节点之前,应运行飞行前检查. 它们可以单独运行,也可以与升级脚本一起运行. + + 要将辅助节点与预检检查一起提升为主节点: + + ``` + gitlab-ctl promote-to-primary-node + ``` + + **警告:**跳过飞行前检查将把辅助设备升级为主要设备,而无需进一步确认! + + 如果您已经运行了[预检检查,](planned_failover.html#preflight-checks)或者不想运行它们,则可以使用以下方法跳过预检检查: + + ``` + gitlab-ctl promote-to-primary-node --skip-preflight-check + ``` + + 您还可以单独运行飞行前检查: + + ``` + gitlab-ctl promotion-preflight-checks + ``` + +4. 验证您可以使用先前用于**辅助**节点的 URL 连接到新提升的**主**节点. +5. 如果成功,则**辅助**节点现在已提升为**主要**节点. + +#### Promoting a **secondary** node with multiple servers[](#promoting-a-secondary-node-with-multiple-servers "Permalink") + +`gitlab-ctl promote-to-primary-node`命令尚不能与多台服务器一起使用,因为它只能在仅一台机器的**辅助** `gitlab-ctl promote-to-primary-node`上执行更改. 相反,您必须手动执行此操作. + +1. SSH 进入**辅助**数据库中的数据库节点,并触发 PostgreSQL 升级为可读写: + + ``` + sudo gitlab-pg-ctl promote + ``` + + 在 GitLab 12.8 及更早版本中,请参阅[消息: `sudo: gitlab-pg-ctl: command not found`](../replication/troubleshooting.html#message-sudo-gitlab-pg-ctl-command-not-found) . + +2. 在**辅助**计算机上的每台计算机上编辑`/etc/gitlab/gitlab.rb` ,以通过删除启用`geo_secondary_role`所有行来将其新状态反映为**主要** `geo_secondary_role` : + + ``` + ## In pre-11.5 documentation, the role was enabled as follows. Remove this line. + geo_secondary_role['enable'] = true + + ## In 11.5+ documentation, the role was enabled as follows. Remove this line. + roles ['geo_secondary_role'] + ``` + + 进行这些更改后,请在每台机器上[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +3. 将**中学**提升到**小学** . SSH 进入单个应用程序服务器并执行: + + ``` + sudo gitlab-rake geo:set_secondary_as_primary + ``` + +4. 验证您可以使用先前用于**辅助服务器**的 URL 连接到新升级的**主**服务器. +5. 成功! **中学**已升格为**小学** . + +#### Promoting a **secondary** node with an external PostgreSQL database[](#promoting-a-secondary-node-with-an-external-postgresql-database "Permalink") + +`gitlab-ctl promote-to-primary-node`命令不能与外部 PostgreSQL 数据库一起使用,因为它只能在使用 GitLab 的**辅助**节点和数据库在同一台机器上执行更改. 结果,需要手动处理: + +1. 升级与**辅助**站点关联的副本数据库. 这会将数据库设置为可读写: + * Amazon RDS- [将只读副本提升为独立数据库实例](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Promote) + * PostgreSQL 的 Azure 数据库- [停止复制](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal#stop-replication) + * 其他外部 PostgreSQL 数据库-将以下脚本保存在辅助节点中,例如`/tmp/geo_promote.sh` ,然后修改连接参数以匹配您的环境. 然后,执行它以提升副本: + + ``` + #!/bin/bash PG_SUPERUSER = postgres # The path to your pg_ctl binary. You may need to adjust this path to match # your PostgreSQL installation PG_CTL_BINARY = /usr/lib/postgresql/10/bin/pg_ctl # The path to your PostgreSQL data directory. You may need to adjust this # path to match your PostgreSQL installation. You can also run # `SHOW data_directory;` from PostgreSQL to find your data directory PG_DATA_DIRECTORY = /etc/postgresql/10/main # Promote the PostgreSQL database and allow read/write operations sudo -u $PG_SUPERUSER $PG_CTL_BINARY -D $PG_DATA_DIRECTORY promote + ``` + +2. 在**辅助**站点中的每个节点上编辑`/etc/gitlab/gitlab.rb` ,以通过删除启用`geo_secondary_role`所有行来将其新状态反映**为主** `geo_secondary_role` : + + ``` + ## In GitLab 11.4 and earlier, remove this line. + geo_secondary_role['enable'] = true + + ## In GitLab 11.5 and later, remove this line. + roles ['geo_secondary_role'] + ``` + + 进行这些更改后,请在每个节点上[重新配置 GitLab](../../restart_gitlab.html#omnibus-gitlab-reconfigure) ,以使更改生效. + +3. 将**中学**提升到**小学** . SSH 进入单个辅助应用程序节点并执行: + + ``` + sudo gitlab-rake geo:set_secondary_as_primary + ``` + +4. 验证您可以使用先前用于**辅助**站点的 URL 连接到新升级的**主**站点. + +成功! **辅助**站点现在已提升为**主要**站点. + +### Step 4\. (Optional) Updating the primary domain DNS record[](#step-4-optional-updating-the-primary-domain-dns-record "Permalink") + +将主域的 DNS 记录更新为指向**辅助**节点将避免需要将对主域的所有引用更新为辅助域,例如更改 Git 远程服务器和 API URL. + +1. SSH 进入**辅助**节点并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 更新主域的 DNS 记录. 更新主域名的 DNS 记录指向**辅助**节点后,编辑`/etc/gitlab/gitlab.rb` **辅助**节点上,以反映新的网址: + + ``` + # Change the existing external_url configuration + external_url 'https://' + ``` + + **Note:** Changing `external_url` won’t prevent access via the old secondary URL, as long as the secondary DNS records are still intact. +3. 重新配置**辅助**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +4. 执行以下命令以更新新提升的**主**节点 URL: + + ``` + gitlab-rake geo:update_primary_node_url + ``` + + 此命令将使用`/etc/gitlab/gitlab.rb`定义的更改的`external_url`配置. + +5. 仅对于 GitLab 11.11 到 12.7,您可能需要更新数据库中的**主**节点名称. 此错误已在 GitLab 12.8 中修复. + + 要确定是否需要执行此操作,请在`/etc/gitlab/gitlab.rb`文件中搜索`gitlab_rails["geo_node_name"]`设置. 如果用`#`注释掉或根本找不到它,则您将需要更新数据库中**主**节点的名称. 您可以像这样搜索它: + + ``` + grep "geo_node_name" /etc/gitlab/gitlab.rb + ``` + + 要更新数据库中**主**节点的名称: + + ``` + gitlab-rails runner 'Gitlab::Geo.primary_node.update!(name: GeoNode.current_node_name)' + ``` + +6. 验证您可以使用其 URL 连接到新升级的**主数据库** . 如果您更新了主域的 DNS 记录,则这些更改可能尚未传播,具体取决于以前的 DNS 记录 TTL. + +### Step 5\. (Optional) Add **secondary** Geo node to a promoted **primary** node[](#step-5-optional-add-secondary-geo-node-to-a-promoted-primary-node "Permalink") + +使用上述过程将**辅助**节点提升为**主要**节点不会在新的**主要**节点上启用 Geo. + +要使新的**辅助**节点在线,请按照[Geo 设置说明进行操作](../replication/index.html#setup-instructions) . + +### Step 6\. (Optional) Removing the secondary’s tracking database[](#step-6-optional-removing-the-secondarys-tracking-database "Permalink") + +每个**次级**有一个用于保存从**初级**的所有项目的同步状态的特殊的跟踪数据库. 由于**辅助服务器**已经升级,因此不再需要跟踪数据库中的数据. + +可以使用以下命令删除数据: + +``` +sudo rm -rf /var/opt/gitlab/geo-postgresql +``` + +如果您在`gitlab.rb`文件中启用了任何`geo_secondary[]`配置选项,则可以安全地注释掉这些选项或将其删除,然后[重新配置 GitLab](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +## Promoting secondary Geo replica in multi-secondary configurations[](#promoting-secondary-geo-replica-in-multi-secondary-configurations "Permalink") + +如果您有多个**辅助**节点,并且需要升级其中一个,建议您按照[单辅助配置中的"](#promoting-a-secondary-geo-node-in-single-secondary-configurations)升级[**辅助** Geo"节点进行操作](#promoting-a-secondary-geo-node-in-single-secondary-configurations) ,之后还需要执行两个额外步骤. + +### Step 1\. Prepare the new **primary** node to serve one or more **secondary** nodes[](#step-1-prepare-the-new-primary-node-to-serve-one-or-more-secondary-nodes "Permalink") + +1. SSH 进入新的**主**节点并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. Edit `/etc/gitlab/gitlab.rb` + + ``` + ## Enable a Geo Primary role (if you haven't yet) + roles ['geo_primary_role'] + + ## + # Allow PostgreSQL client authentication from the primary and secondary IPs. These IPs may be + # public or VPC addresses in CIDR format, for example ['198.51.100.1/32', '198.51.100.2/32'] + ## + postgresql['md5_auth_cidr_addresses'] = ['/32', '/32'] + + # Every secondary server needs to have its own slot so specify the number of secondary nodes you're going to have + postgresql['max_replication_slots'] = 1 + + ## + ## Disable automatic database migrations temporarily + ## (until PostgreSQL is restarted and listening on the private address). + ## + gitlab_rails['auto_migrate'] = false + ``` + + (有关这些设置的更多详细信息,您可以阅读[配置主服务器](../replication/database.html#step-1-configure-the-primary-server) ) + +3. 保存文件并重新配置 GitLab,以进行数据库侦听更改和要应用的复制插槽更改. + + ``` + gitlab-ctl reconfigure + ``` + + 重新启动 PostgreSQL 以使其更改生效: + + ``` + gitlab-ctl restart postgresql + ``` + +4. 现在,重新启动 PostgreSQL 并重新侦听私有地址,即可重新启用迁移. + + 编辑`/etc/gitlab/gitlab.rb`并将配置**更改**为`true` : + + ``` + gitlab_rails['auto_migrate'] = true + ``` + + 保存文件并重新配置 GitLab: + + ``` + gitlab-ctl reconfigure + ``` + +### Step 2\. Initiate the replication process[](#step-2-initiate-the-replication-process "Permalink") + +现在,我们需要使每个**辅助**节点侦听新的**主要**节点上的更改. 为此,您需要再次[启动复制过程](../replication/database.html#step-3-initiate-the-replication-process) ,但这一次是针对另一个**主**节点. 所有旧的复制设置将被覆盖. + +## Troubleshooting[](#troubleshooting "Permalink") + +### I followed the disaster recovery instructions and now two-factor auth is broken[](#i-followed-the-disaster-recovery-instructions-and-now-two-factor-auth-is-broken "Permalink") + +10.5 之前的 Geo 的安装说明无法复制`otp_key_base`机密,该机密用于加密存储在数据库中的两因素身份验证机密. 如果**主**节点和**辅助**节点之间的设置不同,启用了双重身份验证的用户将无法在故障转移后登录. + +如果您仍然可以访问旧的**主**节点,则可以按照" [升级到 GitLab 10.5"](../replication/version_specific_updates.html#updating-to-gitlab-105)部分中的说明解决错误. 否则,密码将丢失,您需要[为所有用户重置两步验证](../../../security/two_factor_authentication.html#disabling-2fa-for-everyone) . \ No newline at end of file diff --git a/_book/docs/506.md b/_book/docs/506.md new file mode 100644 index 0000000000000000000000000000000000000000..ffdfb3d5bda491e9effd4ba0e469a5889c47b6a2 --- /dev/null +++ b/_book/docs/506.md @@ -0,0 +1,158 @@ +# Disaster recovery for planned failover + +> 原文:[https://docs.gitlab.com/ee/administration/geo/disaster_recovery/planned_failover.html](https://docs.gitlab.com/ee/administration/geo/disaster_recovery/planned_failover.html) + +* [Not all data is automatically replicated](#not-all-data-is-automatically-replicated) +* [Preflight checks](#preflight-checks) + * [Object storage](#object-storage) + * [Review the configuration of each **secondary** node](#review-the-configuration-of-each-secondary-node) + * [Run system checks](#run-system-checks) + * [Check that secrets match between nodes](#check-that-secrets-match-between-nodes) + * [Ensure Geo replication is up-to-date](#ensure-geo-replication-is-up-to-date) + * [Verify the integrity of replicated data](#verify-the-integrity-of-replicated-data) + * [Notify users of scheduled maintenance](#notify-users-of-scheduled-maintenance) +* [Prevent updates to the **primary** node](#prevent-updates-to-the-primary-node) +* [Finish replicating and verifying all data](#finish-replicating-and-verifying-all-data) +* [Promote the **secondary** node](#promote-the-secondary-node) + +# Disaster recovery for planned failover[](#disaster-recovery-for-planned-failover-premium-only "Permalink") + +The primary use-case of Disaster Recovery is to ensure business continuity in the event of unplanned outage, but it can be used in conjunction with a planned failover to migrate your GitLab instance between regions without extended downtime. + +由于 Geo 节点之间的复制是异步的,因此计划中的故障转移需要一个维护窗口,该窗口中阻止了对**主**节点的更新. 该窗口的长度取决于您的复制能力-一旦**辅助**节点与**主**节点完全同步,就可以进行故障转移而不会丢失数据. + +本文档假定您已经具有完整配置的,可以正常使用的 Geo 设置. 在继续之前,请完整阅读它和[Disaster Recovery](index.html)故障转移文档. 计划内的故障转移是一项主要操作,如果执行不正确,则存在很高的数据丢失风险. 考虑对程序进行排练,直到您对必要的步骤感到满意并且对能够准确执行它们有高度的信心. + +## Not all data is automatically replicated[](#not-all-data-is-automatically-replicated "Permalink") + +如果您使用的是 Geo [不支持的](../replication/index.html#current-limitations)任何 GitLab 功能, [则](../replication/index.html#current-limitations)必须单独进行准备,以确保**辅助**节点具有与该功能关联的任何数据的最新副本. 这可能会大大延长所需的计划维护时间. + +使文件中存储的数据的时间尽可能短的常见策略是使用`rsync`传输数据. 可以在维护窗口之前执行初始`rsync` . 随后的`rsync` s(包括维护窗口内的最终传输)将仅传输**主**节点和**辅助**节点之间的*更改* . + +在[移动存储库](../../operations/moving_repositories.html)文档中可以找到有效使用`rsync`的以存储库为中心的策略. 这些策略可以调整为与任何其他基于文件的数据一起使用,例如 GitLab 页面(如果使用 Omnibus,则可在`/var/opt/gitlab/gitlab-rails/shared/pages` ). + +## Preflight checks[](#preflight-checks "Permalink") + +运行此命令以列出所有预检检查,并在计划计划的故障转移之前自动检查复制和验证是否完成,以确保过程顺利进行: + +``` +gitlab-ctl promotion-preflight-checks +``` + +即使预检检查失败,也可以以`force`模式运行此命令以升级为主要命令: + +``` +sudo gitlab-ctl promotion-preflight-checks --force +``` + +每个步骤将在下面更详细地描述. + +### Object storage[](#object-storage "Permalink") + +如果您有大量的 GitLab 安装或无法忍受停机,请**在**计划计划的故障转移**之前**考虑[迁移到对象存储](../replication/object_storage.html) . 这样做既可以减少维护窗口的长度,又可以减少由于计划内故障转移执行不当而导致的数据丢失风险. + +In GitLab 12.4, you can optionally allow GitLab to manage replication of Object Storage for **secondary** nodes. For more information, see [Object Storage replication](../replication/object_storage.html). + +### Review the configuration of each **secondary** node[](#review-the-configuration-of-each-secondary-node "Permalink") + +数据库设置会自动复制到**辅助**节点,但是`/etc/gitlab/gitlab.rb`文件必须手动设置,并且在节点之间有所不同. 如果在**主要**节点上启用了 Mattermost,OAuth 或 LDAP 集成等功能,但在**次要**节点上未启用这些功能,则它们将在故障转移期间丢失. + +查看两个节点的`/etc/gitlab/gitlab.rb`文件,并确保**辅助**节点支持**主**节点**在**计划计划的故障转移**之前**所做的一切. + +### Run system checks[](#run-system-checks "Permalink") + +在**主**节点和**辅助**节点上运行以下命令: + +``` +gitlab-rake gitlab:check +gitlab-rake gitlab:geo:check +``` + +如果在任一节点上报告了任何故障,则应**在**计划计划的故障转移**之前**解决这些故障. + +### Check that secrets match between nodes[](#check-that-secrets-match-between-nodes "Permalink") + +SSH 主机密钥和`/etc/gitlab/gitlab-secrets.json`文件在所有节点上均应相同. 通过在所有节点上运行以下命令并比较输出来进行检查: + +``` +sudo sha256sum /etc/ssh/ssh_host* /etc/gitlab/gitlab-secrets.json +``` + +如果有任何文件不同,请用**主**节点中的内容替换**辅助**节点上的内容. + +### Ensure Geo replication is up-to-date[](#ensure-geo-replication-is-up-to-date "Permalink") + +直到地理复制和验证完成,维护窗口才会结束. 为了使窗口尽可能短,在使用过程中,应确保这些过程尽可能接近 100%. + +导航到 **管理区>** **辅助**节点上的**地理**仪表板以查看状态. 复制的对象(以绿色显示)应接近 100%,并且不应出现故障(以红色显示). 如果尚未复制大量对象(显示为灰色),请考虑给节点更多时间来完成 + +[![Replication status](img/5574e9e4660196e59606fe9d673097b7.png)](img/replication-status.png) + +如果有任何对象无法复制,则应在安排维护窗口之前进行调查. 在计划好的故障转移之后,所有无法复制的内容都会**丢失** . + +您可以使用[地理状态 API](../../../api/geo_nodes.html#retrieve-project-sync-or-verification-failures-that-occurred-on-the-current-node)查看失败的对象以及失败的原因. + +复制失败的常见原因是**主**节点上缺少数据-您可以通过从备份还原数据或删除对丢失数据的引用来解决这些故障. + +### Verify the integrity of replicated data[](#verify-the-integrity-of-replicated-data "Permalink") + +This [content was moved to another location](background_verification.html). + +### Notify users of scheduled maintenance[](#notify-users-of-scheduled-maintenance "Permalink") + +在**主**节点上,导航到 **管理区>** **消息** ,添加广播消息. 你可以检查下 **管理区>** **地理位置,**以估算完成同步需要多长时间. 一个示例消息是: + +> 计划的维护将在世界标准时间 XX:XX 进行. 我们预计将花费不到 1 个小时. + +## Prevent updates to the **primary** node[](#prevent-updates-to-the-primary-node "Permalink") + +在实施[只读模式](https://gitlab.com/gitlab-org/gitlab/-/issues/14609)之前,必须防止手动进行更新. 请注意,在维护窗口期间, **辅助**节点仍需要对**主**节点具有只读访问权限. + +1. 在计划的时间,使用您的云提供商或节点的防火墙,阻止去往/来自**主**节点的所有 HTTP,HTTPS 和 SSH 通信, **但** IP 和**辅助**节点的 IP **除外** . + + 例如,您可能在组成**主**节点的服务器上运行以下命令: + + ``` + sudo iptables -A INPUT -p tcp -s --destination-port 22 -j ACCEPT + sudo iptables -A INPUT -p tcp -s --destination-port 22 -j ACCEPT + sudo iptables -A INPUT --destination-port 22 -j REJECT + + sudo iptables -A INPUT -p tcp -s --destination-port 80 -j ACCEPT + sudo iptables -A INPUT -p tcp -s --destination-port 80 -j ACCEPT + sudo iptables -A INPUT --tcp-dport 80 -j REJECT + + sudo iptables -A INPUT -p tcp -s --destination-port 443 -j ACCEPT + sudo iptables -A INPUT -p tcp -s --destination-port 443 -j ACCEPT + sudo iptables -A INPUT --tcp-dport 443 -j REJECT + ``` + + 从这一点来看,用户将无法查看其数据或在**主**节点上进行更改. 他们也将无法登录到**辅助**节点. 但是,现有的会话将在维护期间的剩余时间内起作用,并且可以在整个维护期间访问公共数据. + +2. 通过使用其他 IP 在浏览器中访问**主**节点,验证**主**节点是否受到 HTTP 流量的阻止. 服务器应拒绝连接. + +3. 尝试通过使用 SSH 远程 URL 提取现有的 Git 存储库,来验证**主**节点是否已通过 SSH 流量阻止 Git. 服务器应拒绝连接. + +4. 通过导航到禁用**主要**节点上的非 Geo 定期后台作业 **管理区>** **监视>后台作业> Cron** ,按`Disable All` ,然后为`geo_sidekiq_cron_config_worker` cron 作业按`Enable` . 该作业将重新启用其他几个 cron 作业,这些作业对于计划的故障转移成功完成至关重要. + +## Finish replicating and verifying all data[](#finish-replicating-and-verifying-all-data "Permalink") + +1. 如果您要手动复制不是由 Geo 管理的任何数据,请立即触发最终复制过程. +2. 在**主**节点上,导航到 **管理区>** **监视>后台作业>队列,**并等待所有队列(名称中带有`geo`的队列降至 0).这些队列包含用户提交的工作; 在完成之前进行故障转移将导致工作丢失. +3. 在**主**节点上,导航到 **管理区>** **地理位置,**并等待您要故障转移到的**辅助**节点满足以下条件: + + * 所有复制计量到 100%复制,0%失败. + * 所有验证仪表均达到 100%验证,0%失败. + * 数据库复制滞后为 0ms. + * 地理日志光标是最新的(落后 0 个事件). +4. 在**辅助**节点上,导航到 **管理区>** **监视>后台作业>队列,**然后等待所有`geo`队列下降到 0 个已排队的作业和 0 个正在运行的作业. +5. 在**辅助**节点上,使用[以下说明](../../raketasks/check.html)来验证 CI 工件,LFS 对象以及文件存储中的上载的完整性. + +此时, **辅助**节点将包含**主**节点拥有的所有内容的最新副本,这意味着在进行故障转移时不会丢失任何内容. + +## Promote the **secondary** node[](#promote-the-secondary-node "Permalink") + +最后,按照[灾难恢复文档](index.html)将**辅助**节点升级为**主要**节点. 此过程将导致**辅助**节点发生短暂中断,并且用户可能需要再次登录. + +一旦完成,维护窗口就结束了! 新的**主**节点现在开始发散,从旧的. 如果确实出现在这一点上的问题,没有回到原来的**主**节点[是可能](bring_primary_back.html)的,但可能会导致在此期间上传到新的**主**任何数据丢失. + +故障转移完成后,请不要忘记删除广播消息. \ No newline at end of file diff --git a/_book/docs/507.md b/_book/docs/507.md new file mode 100644 index 0000000000000000000000000000000000000000..780bc71a71e00b303119e6651d9a94ec611b27ed --- /dev/null +++ b/_book/docs/507.md @@ -0,0 +1,42 @@ +# Bring a demoted primary node back online + +> 原文:[https://docs.gitlab.com/ee/administration/geo/disaster_recovery/bring_primary_back.html](https://docs.gitlab.com/ee/administration/geo/disaster_recovery/bring_primary_back.html) + +* [Configure the former **primary** node to be a **secondary** node](#configure-the-former-primary-node-to-be-a-secondary-node) +* [Promote the **secondary** node to **primary** node](#promote-the-secondary-node-to-primary-node) +* [Restore the **secondary** node](#restore-the-secondary-node) + +# Bring a demoted primary node back online[](#bring-a-demoted-primary-node-back-online-premium-only "Permalink") + +故障转移后,可以故障回复到降级的**主**节点以还原原始配置. 此过程包括两个步骤: + +1. 使旧的**主**节点成为**辅助**节点. +2. 将**辅助**节点提升为**主要**节点. + +**警告:**如果您对该节点上的数据一致性有任何疑问,我们建议从头开始进行设置. + +## Configure the former **primary** node to be a **secondary** node[](#configure-the-former-primary-node-to-be-a-secondary-node "Permalink") + +由于先前的**主要**节点将与当前的**主要**节点不同步,因此第一步是使先前的**主要**节点保持最新. 请注意,将先前的**主**节点重新同步后,不会重播存储在磁盘上的数据(如存储库和上载),这可能会导致磁盘使用率增加. 或者,您可以[设置一个新的**辅助** GitLab 实例](../replication/index.html#setup-instructions)来避免这种情况. + +要使以前的**主**节点保持最新状态: + +1. SSH 进入落后的前**主**节点. +2. 确保所有服务都已启动: + + ``` + sudo gitlab-ctl start + ``` + + **注意:**如果[永久禁用了**主**节点](index.html#step-2-permanently-disable-the-primary-node) ,则需要立即撤消这些步骤. 对于 Debian / Ubuntu,您只需要运行`sudo systemctl enable gitlab-runsvdir` . 对于 CentOS 6,您需要从头开始安装 GitLab 实例,并按照[安装说明](../replication/index.html#setup-instructions)将其设置为**辅助**节点. 在这种情况下,您无需执行下一步.**注意:**如果在灾难恢复过程中[更改了](index.html#step-4-optional-updating-the-primary-domain-dns-record)该节点[的 DNS 记录](index.html#step-4-optional-updating-the-primary-domain-dns-record) ,则可能需要在此过程中[阻止对该节点的所有写操作](planned_failover.html#prevent-updates-to-the-primary-node) . +3. [设置数据库复制](../replication/database.html) . 请注意,在这种情况下, **主**节点是指当前的**主**节点, **辅助**节点是指先前的**主**节点. + +如果丢失了原始**主**节点,请按照[设置说明](../replication/index.html#setup-instructions)设置新的**辅助**节点. + +## Promote the **secondary** node to **primary** node[](#promote-the-secondary-node-to-primary-node "Permalink") + +初始复制完成并且**主**节点和**辅助**节点紧密同步后,您可以执行[计划的故障转移](planned_failover.html) . + +## Restore the **secondary** node[](#restore-the-secondary-node "Permalink") + +如果你的目标是再有两个节点,你需要把你的**辅助**节点重新联机,以及通过重复第一步( [配置前**主**节点是**辅助**节点](#configure-the-former-primary-node-to-be-a-secondary-node) )为**辅助**节点. \ No newline at end of file diff --git a/_book/docs/508.md b/_book/docs/508.md new file mode 100644 index 0000000000000000000000000000000000000000..8c8e4744d404cbc2c5b024412ce5a3b4d0c93cd8 --- /dev/null +++ b/_book/docs/508.md @@ -0,0 +1,149 @@ +# Automatic background verification + +> 原文:[https://docs.gitlab.com/ee/administration/geo/disaster_recovery/background_verification.html](https://docs.gitlab.com/ee/administration/geo/disaster_recovery/background_verification.html) + +* [Disabling or enabling the automatic background verification](#disabling-or-enabling-the-automatic-background-verification) +* [Repository verification](#repository-verification) +* [Using checksums to compare Geo nodes](#using-checksums-to-compare-geo-nodes) +* [Repository re-verification](#repository-re-verification) +* [Reset verification for projects where verification has failed](#reset-verification-for-projects-where-verification-has-failed) +* [Reconcile differences with checksum mismatches](#reconcile-differences-with-checksum-mismatches) +* [Current limitations](#current-limitations) + +# Automatic background verification[](#automatic-background-verification-premium-only "Permalink") + +**注意:**在 GitLab EE 10.6 中添加了存储库和 Wiki 的自动背景验证,但默认情况下仅在 GitLab EE 11.1 上启用了该功能. 您可以按照[以下说明](#disabling-or-enabling-the-automatic-background-verification)手动禁用或启用此功能. + +自动背景验证可确保传输的数据与计算出的校验和匹配. 如果**主**节点上数据的校验和与**辅助**节点上数据的校验和匹配,则数据传输成功. 在计划的故障转移之后,根据损坏的程度,任何损坏的数据都可能**丢失** . + +如果在**主**节点上验证失败,则表明 Geo 正在复制损坏的对象. 您可以从备份中还原它,也可以从**主**节点中将其删除以解决问题. + +如果验证在**主**节点上成功,但在**辅助**节点上失败,则表明在复制过程中对象已损坏. Geo 积极尝试纠正验证失败,将存储库标记为有退避期重新同步. 如果您想重置这些失败的验证,则应遵循[以下说明](background_verification.html#reset-verification-for-projects-where-verification-has-failed) . + +如果验证明显落后于复制,请考虑在安排计划的故障转移之前给节点更多时间. + +## Disabling or enabling the automatic background verification[](#disabling-or-enabling-the-automatic-background-verification "Permalink") + +在**主**节点上的 Rails 控制台中运行以下命令: + +``` +gitlab-rails console +``` + +要检查是否启用了自动背景验证: + +``` +Gitlab::Geo.repository_verification_enabled? +``` + +要禁用自动背景验证: + +``` +Feature.disable('geo_repository_verification') +``` + +要启用自动背景验证: + +``` +Feature.enable('geo_repository_verification') +``` + +## Repository verification[](#repository-verification "Permalink") + +导航到 **管理区>** 在**主**节点上的**地理**仪表板,并展开该节点的" **验证信息"**选项卡以查看存储库和 Wiki 的自动校验和状态. 成功以绿色显示,待处理的工作以灰色显示,失败以红色显示. + +[![Verification status](img/283011f90b0969b60cd202dd293525ca.png)](img/verification-status-primary.png) + +导航到 **管理区>** **辅助**节点上的**地理**仪表板,并展开该节点的" **验证信息"**选项卡,以查看存储库和 Wiki 的自动验证状态. 与校验和一样,成功显示为绿色,待处理工作显示为灰色,失败显示为红色. + +[![Verification status](img/38d4db85b589523cbab105da53e5fb09.png)](img/verification-status-secondary.png) + +## Using checksums to compare Geo nodes[](#using-checksums-to-compare-geo-nodes "Permalink") + +要检查 Geo **辅助**节点的运行状况,我们在 Git 引用及其值的列表上使用校验和. 校验和包括`HEAD` , `heads` , `tags` , `notes`和特定于 GitLab 的引用,以确保真正的一致性. 如果两个节点具有相同的校验和,则它们肯定拥有相同的引用. 我们在每次更新后为每个节点计算校验和,以确保它们都同步. + +## Repository re-verification[](#repository-re-verification "Permalink") + +在 GitLab 企业版 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8550) . 在[GitLab Premium 中](https://about.gitlab.com/pricing/)可用. + +由于错误或临时基础架构故障,Git 存储库可能会发生意外更改,而不会被标记为要进行验证. Geo 会不断重新验证存储库以确保数据的完整性. 尽管可以设置短至 1 天的间隔,但默认和建议的重新验证间隔是 7 天. 较短的时间间隔可以降低风险,但会增加负载,反之亦然. + +导航到 **管理区>** 在**主**节点上**的地理**信息中心,并单击**编辑**按钮为所述**主**节点来定制最小重新验证间隔: + +[![Re-verification interval](img/e3eeb697453d582cf0ec4a746f30ed31.png)](img/reverification-interval.png) + +默认情况下,自动后台重新验证处于启用状态,但是如果需要,您可以将其禁用. 在**主**节点上的 Rails 控制台中运行以下命令: + +``` +gitlab-rails console +``` + +要禁用自动后台重新验证: + +``` +Feature.disable('geo_repository_reverification') +``` + +要启用自动后台重新验证: + +``` +Feature.enable('geo_repository_reverification') +``` + +## Reset verification for projects where verification has failed[](#reset-verification-for-projects-where-verification-has-failed "Permalink") + +Geo 积极尝试纠正验证失败,将存储库标记为有退避期重新同步. 如果要手动重置它们,此 Rake 任务会将项目标记为验证失败或校验和不匹配的项目重新同步而没有退避期: + +对于存储库: + +``` +sudo gitlab-rake geo:verification:repository:reset +``` + +对于 Wiki: + +``` +sudo gitlab-rake geo:verification:wiki:reset +``` + +## Reconcile differences with checksum mismatches[](#reconcile-differences-with-checksum-mismatches "Permalink") + +如果**主**节点和**辅助**节点的校验和验证不匹配,则原因可能不明显. 要查找校验和不匹配的原因: + +1. 导航到 **管理区>** 在**主**节点上的" **概述">"项目"**仪表板中,找到要检查校验和差异的项目,然后单击" **编辑"**按钮: [![项目仪表板](img/655bbae75a3608d2016397c70682f7d4.png)](img/checksum-differences-admin-projects.png) + +2. 在项目管理页面上,获取**Gitaly 存储名称**和**Gitaly 相对路径** : [![项目管理页面](img/43c1d4f646051452c436962222af114b.png)](img/checksum-differences-admin-project-page.png) + +3. 导航到**主**节点和**辅助**节点上的项目的存储库目录(路径通常是`/var/opt/gitlab/git-data/repositories` ). 请注意,如果`git_data_dirs`是自定义的,请确保检查服务器上的目录布局. + + ``` + cd /var/opt/gitlab/git-data/repositories + ``` + +4. 在**主**节点上运行以下命令,将输出重定向到文件: + + ``` + git show-ref --head | grep -E "HEAD|(refs/(heads|tags|keep-around|merge-requests|environments|notes)/)" > primary-node-refs + ``` + +5. 在**辅助**节点上运行以下命令,将输出重定向到文件: + + ``` + git show-ref --head | grep -E "HEAD|(refs/(heads|tags|keep-around|merge-requests|environments|notes)/)" > secondary-node-refs + ``` + +6. 复制同一系统上先前步骤中的文件,并在内容之间进行区分: + + ``` + diff primary-node-refs secondary-node-refs + ``` + +## Current limitations[](#current-limitations "Permalink") + +自动后台验证不包括附件,LFS 对象,作业工件以及文件存储中的用户上传. 您可以跟踪进度,以将其包括在" [地理位置"中:验证所有复制的数据](https://gitlab.com/groups/gitlab-org/-/epics/1430) . + +现在,您可以通过在两个节点上遵循[以下说明](../../raketasks/check.html)并比较它们之间的输出来手动验证其完整性. + +在 GitLab EE 12.1 中,Geo 会在传输后计算辅助节点上的附件,LFS 对象和已归档跟踪的校验和,并将其与存储的校验和进行比较,如果不匹配则拒绝传输. 请注意,如果在 GitLab EE 12.1 之前已经同步了这些数据,Geo 当前不支持自动验证这些数据的方法. + +对象存储中的数据**未经验证** ,因为对象存储负责确保数据的完整性. \ No newline at end of file diff --git a/_book/docs/509.md b/_book/docs/509.md new file mode 100644 index 0000000000000000000000000000000000000000..3810bdd6dfcfc6b37f390f3a3e8e771474a39073 --- /dev/null +++ b/_book/docs/509.md @@ -0,0 +1,45 @@ +# Rake tasks + +> 原文:[https://docs.gitlab.com/ee/raketasks/README.html](https://docs.gitlab.com/ee/raketasks/README.html) + +* [Available Rake tasks](#available-rake-tasks) + +# Rake tasks[](#rake-tasks-core-only "Permalink") + +GitLab 为常见的管理和操作流程提供[Rake](https://ruby.github.io/rake/)任务. + +使用以下命令执行 GitLab Rake 任务: + +* `gitlab-rake ` for [Omnibus GitLab](https://docs.gitlab.com/omnibus/README.html) installations. +* `bundle exec rake ` for [source](../install/installation.html) installations. + +## Available Rake tasks[](#available-rake-tasks "Permalink") + +以下是可用的 Rake 任务: + +| Tasks | Description | +| --- | --- | +| [Back up and restore](backup_restore.html) | 在服务器之间备份,还原和迁移 GitLab 实例. | +| [Clean up](cleanup.html) | 从 GitLab 实例中清除不需要的项目. | +| [Development](../development/rake_tasks.html) | GitLab 贡献者的任务. | +| [Doctor tasks](../administration/raketasks/doctor.html) | 检查数据完整性问题. | +| [Elasticsearch](../integration/elasticsearch.html#gitlab-elasticsearch-rake-tasks) | 在 GitLab 实例中维护 Elasticsearch. | +| [Enable namespaces](features.html) | 为用户项目启用用户名和名称空间. | +| [General maintenance](../administration/raketasks/maintenance.html) | 常规维护和自检任务. | +| [Geo maintenance](../administration/raketasks/geo.html) | [与地理](../administration/geo/replication/index.html)相关的维护. | +| [GitHub import](../administration/raketasks/github_import.html) | 从 GitHub 检索和导入存储库. | +| [Import repositories](import.html) | 将裸仓库导入您的 GitLab 实例. | +| [Import large project exports](../development/import_project.html#importing-via-a-rake-task) | 导入大型 GitLab [项目出口](../user/project/settings/import_export.html) . | +| [Integrity checks](../administration/raketasks/check.html) | 检查存储库,文件和 LDAP 的完整性. | +| [LDAP maintenance](../administration/raketasks/ldap.html) | [LDAP](../administration/auth/ldap/index.html)相关任务. | +| [List repositories](list_repos.html) | 磁盘上所有由 GitLab 管理的 Git 存储库的列表. | +| [Migrate Snippets to Git](migrate_snippets.html) | 将 GitLab 代码片段迁移到 Git 存储库并显示迁移状态 | +| [Praefect Rake tasks](../administration/raketasks/praefect.html) | [与 Praefect](../administration/gitaly/praefect.html)相关的任务. | +| [Project import/export](../administration/raketasks/project_import_export.html) | 准备[项目的进出口](../user/project/settings/import_export.html) . | +| [Sample Prometheus data](generate_sample_prometheus_data.html) | 生成样本 Prometheus 数据. | +| [Repository storage](../administration/raketasks/storage.html) | 列出现有项目和附件并将其从旧存储迁移到哈希存储. | +| [Uploads migrate](../administration/raketasks/uploads/migrate.html) | 在本地存储和对象存储之间迁移上载. | +| [Uploads sanitize](../administration/raketasks/uploads/sanitize.html) | 从上传到早期版本的 GitLab 的图像中删除 EXIF 数据. | +| [User management](user_management.html) | 执行用户管理任务. | +| [Webhooks administration](web_hooks.html) | 维护项目 Webhooks. | +| [X.509 signatures](x509_signatures.html) | 更新 X.509 提交签名,如果证书存储已更改,则很有用. | \ No newline at end of file diff --git a/_book/docs/510.md b/_book/docs/510.md new file mode 100644 index 0000000000000000000000000000000000000000..fc9caefdf88fa78dd7cd673bb7844c7a306ff536 --- /dev/null +++ b/_book/docs/510.md @@ -0,0 +1,904 @@ +# Back up and restore GitLab + +> 原文:[https://docs.gitlab.com/ee/raketasks/backup_restore.html](https://docs.gitlab.com/ee/raketasks/backup_restore.html) + +* [Requirements](#requirements) +* [Backup timestamp](#backup-timestamp) +* [Back up GitLab](#back-up-gitlab) + * [Storing configuration files](#storing-configuration-files) + * [Backup options](#backup-options) + * [Backup strategy option](#backup-strategy-option) + * [Backup filename](#backup-filename) + * [Rsyncable](#rsyncable) + * [Excluding specific directories from the backup](#excluding-specific-directories-from-the-backup) + * [Skipping tar creation](#skipping-tar-creation) + * [Uploading backups to a remote (cloud) storage](#uploading-backups-to-a-remote-cloud-storage) + * [Using Amazon S3](#using-amazon-s3) + * [Digital Ocean Spaces](#digital-ocean-spaces) + * [Other S3 Providers](#other-s3-providers) + * [Using Google Cloud Storage](#using-google-cloud-storage) + * [Specifying a custom directory for backups](#specifying-a-custom-directory-for-backups) + * [Uploading to locally mounted shares](#uploading-to-locally-mounted-shares) + * [Backup archive permissions](#backup-archive-permissions) + * [Configuring cron to make daily backups](#configuring-cron-to-make-daily-backups) + * [Limit backup lifetime for local files (prune old backups)](#limit-backup-lifetime-for-local-files-prune-old-backups) +* [Restore GitLab](#restore-gitlab) + * [Restore prerequisites](#restore-prerequisites) + * [Restore for installation from source](#restore-for-installation-from-source) + * [Restore for Omnibus GitLab installations](#restore-for-omnibus-gitlab-installations) + * [Restore for Docker image and GitLab Helm chart installations](#restore-for-docker-image-and-gitlab-helm-chart-installations) + * [Restoring only one or a few project(s) or group(s) from a backup](#restoring-only-one-or-a-few-projects-or-groups-from-a-backup) +* [Alternative backup strategies](#alternative-backup-strategies) +* [Additional notes](#additional-notes) +* [Troubleshooting](#troubleshooting) + * [Restoring database backup using Omnibus packages outputs warnings](#restoring-database-backup-using-omnibus-packages-outputs-warnings) + * [When the secrets file is lost](#when-the-secrets-file-is-lost) + * [Reset CI/CD variables](#reset-cicd-variables) + * [Reset Runner registration tokens](#reset-runner-registration-tokens) + * [Reset pending pipeline jobs](#reset-pending-pipeline-jobs) + * [Container Registry push failures after restoring from a backup](#container-registry-push-failures-after-restoring-from-a-backup) + * [Backup fails to complete with Gzip error](#backup-fails-to-complete-with-gzip-error) + +# Back up and restore GitLab[](#back-up-and-restore-gitlab-core-only "Permalink") + +GitLab 提供了 Rake 任务来备份和还原 GitLab 实例. + +应用程序数据备份将创建一个包含数据库,所有存储库和所有附件的存档文件. + +您只能将备份还原到与其创建时**完全相同的** GitLab **版本和类型(CE / EE)** . 将存储库从一台服务器迁移到另一台服务器的最佳方法是通过备份还原. + +## Requirements[](#requirements "Permalink") + +为了能够进行备份和还原,您需要在系统上安装两个基本工具. + +* **Rsync** :如果您安装了 GitLab: + * 使用 Omnibus 软件包,您已经准备就绪. + * 从源代码中,确保已安装`rsync` . 例如: + + ``` + # Debian/Ubuntu sudo apt-get install rsync # RHEL/CentOS sudo yum install rsync + ``` + +## Backup timestamp[](#backup-timestamp "Permalink") + +**注意:**在 GitLab 9.2 中,时间戳格式从`EPOCH_YYYY_MM_DD`更改为`EPOCH_YYYY_MM_DD_GitLab_version` ,例如`1493107454_2018_04_25`将变为`1493107454_2018_04_25_10.6.4-ce` . + +备份存档将保存在`config/gitlab.yml`文件中指定的`backup_path`中. 文件名将为`[TIMESTAMP]_gitlab_backup.tar` ,其中`TIMESTAMP`标识创建每个备份的时间以及 GitLab 版本. 如果您需要还原 GitLab 并且有多个备份可用,则需要时间戳. + +例如,如果备份名称为`1493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar` ,则时间戳为`1493107454_2018_04_25_10.6.4-ce` . + +## Back up GitLab[](#back-up-gitlab "Permalink") + +GitLab 提供了一个简单的命令行界面来备份整个实例. 它备份您的: + +* Database +* Attachments +* Git 存储库数据 +* CI / CD 作业输出日志 +* CI / CD 作业工件 +* LFS 对象 +* 容器注册表图像 +* GitLab 页面内容 + +**警告:** GitLab 不会备份任何配置文件,SSL 证书或系统文件. 强烈建议您[阅读有关存储配置文件的信息](#storing-configuration-files) . + +如果您已通过 Omnibus 软件包安装了 GitLab,请使用以下命令: + +``` +sudo gitlab-backup create +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +如果您已经从源代码安装了 GitLab,请使用以下命令: + +``` +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production +``` + +如果您正在 Docker 容器中运行 GitLab,则可以从主机运行备份: + +``` +docker exec -t gitlab-backup create +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +如果您正在 Kubernetes 集群上使用[GitLab Helm 图表](https://gitlab.com/gitlab-org/charts/gitlab) ,则可以通过`kubectl`在 GitLab 任务运行`backup-utility`窗格上使用`backup-utility`脚本运行备份任务. 有关更多详细信息,请参考[备份 GitLab 安装](https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/backup-restore/backup.md#backing-up-a-gitlab-installation) : + +``` +kubectl exec -it backup-utility +``` + +与 Kubernetes 情况类似,如果已扩展 GitLab 集群以使用多个应用程序服务器,则应选择一个指定节点(不会自动扩展)以运行备份 Rake 任务. 由于备份 Rake 任务与主 Rails 应用程序紧密相连,因此通常在该节点上您还运行 Unicorn / Puma 和/或 Sidekiq. + +输出示例: + +``` +Dumping database tables: +- Dumping table events... [DONE] +- Dumping table issues... [DONE] +- Dumping table keys... [DONE] +- Dumping table merge_requests... [DONE] +- Dumping table milestones... [DONE] +- Dumping table namespaces... [DONE] +- Dumping table notes... [DONE] +- Dumping table projects... [DONE] +- Dumping table protected_branches... [DONE] +- Dumping table schema_migrations... [DONE] +- Dumping table services... [DONE] +- Dumping table snippets... [DONE] +- Dumping table taggings... [DONE] +- Dumping table tags... [DONE] +- Dumping table users... [DONE] +- Dumping table users_projects... [DONE] +- Dumping table web_hooks... [DONE] +- Dumping table wikis... [DONE] +Dumping repositories: +- Dumping repository abcd... [DONE] +Creating backup archive: $TIMESTAMP_gitlab_backup.tar [DONE] +Deleting tmp directories...[DONE] +Deleting old backups... [SKIPPING] +``` + +### Storing configuration files[](#storing-configuration-files "Permalink") + +The [backup Rake task](#back-up-gitlab) GitLab provides does **not** store your configuration files. The primary reason for this is that your database contains encrypted information for two-factor authentication, the CI/CD ‘secure variables’, and so on. Storing encrypted information along with its key in the same place defeats the purpose of using encryption in the first place. + +**警告:**机密文件对于保留数据库加密密钥至关重要. + +**至少** ,您必须备份: + +对所有人; + +* `/etc/gitlab/gitlab-secrets.json` +* `/etc/gitlab/gitlab.rb` + +从源安装: + +* `/home/git/gitlab/config/secrets.yml` +* `/home/git/gitlab/config/gitlab.yml` + +For [Docker installations](https://docs.gitlab.com/omnibus/docker/), you must back up the volume where the configuration files are stored. If you have created the GitLab container according to the documentation, it should be under `/srv/gitlab/config`. + +对于 Kubernetes 集群上的[GitLab Helm 图表安装](https://gitlab.com/gitlab-org/charts/gitlab) ,必须遵循[备份机密](https://docs.gitlab.com/charts/backup-restore/backup.html)说明. + +您可能还想备份所有 TLS 密钥和证书以及[SSH 主机密钥](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079) . + +如果您使用 Omnibus GitLab,请参阅一些其他信息[来备份您的配置](https://docs.gitlab.com/omnibus/settings/backups.html) . + +万一机密文件丢失,请参阅[故障排除部分](#when-the-secrets-file-is-lost) . + +### Backup options[](#backup-options "Permalink") + +GitLab 提供的用于备份实例的命令行工具可以使用更多选项. + +#### Backup strategy option[](#backup-strategy-option "Permalink") + +在 GitLab 8.17 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8728) . + +默认的备份策略实际上是使用 Linux 命令`tar`和`gzip`将数据从相应的数据位置流式传输到备份. 在大多数情况下,这可以正常工作,但是在数据快速变化时可能会引起问题. + +当`tar`读取数据时更改数据时,错误`file changed as we read it`可能会`file changed as we read it`发生`file changed as we read it`将导致备份过程失败. 为了解决这个问题,8.17 引入了一种名为`copy`的新备份策略. 该策略在调用`tar`和`gzip`之前将数据文件复制到一个临时位置,从而避免了错误. + +副作用是备份过程将占用额外的 1X 磁盘空间. 该过程尽力在每个阶段清理临时文件,这样问题就不会复杂化,但是对于大型安装而言,这可能是一个相当大的变化. 这就是为什么`copy`策略不是 8.17 中的默认策略的原因. + +要使用`copy`策略而不是默认的流策略,请在 Rake task 命令中指定`STRATEGY=copy` . 例如: + +``` +sudo gitlab-backup create STRATEGY=copy +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +#### Backup filename[](#backup-filename "Permalink") + +**警告:**如果使用自定义备份文件名,则将无法[限制备份的寿命](#limit-backup-lifetime-for-local-files-prune-old-backups) . + +默认情况下,将根据上面["备份时间戳记"](#backup-timestamp)部分中的规范创建一个备份文件. 但是,可以通过设置`BACKUP`环境变量来覆盖文件名的`[TIMESTAMP]`部分. 例如: + +``` +sudo gitlab-backup create BACKUP=dump +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +生成的文件将是`dump_gitlab_backup.tar` . 这对于使用 rsync 和增量备份的系统很有用,并且将导致更快的传输速度. + +#### Rsyncable[](#rsyncable "Permalink") + +为了确保生成的归档文件可以通过 rsync 智能传输,可以设置`GZIP_RSYNCABLE=yes`选项. 这会将`--rsyncable`选项设置为`gzip` . 这仅在与设置["备份文件名"选项](#backup-filename)结合使用时才有用. + +注意,不能保证`gzip`中的`--rsyncable`选项在所有发行版中都可用. 要验证它在您的发行版中是否可用,您可以运行`gzip --help`或查阅手册页. + +``` +sudo gitlab-backup create BACKUP=dump GZIP_RSYNCABLE=yes +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +#### Excluding specific directories from the backup[](#excluding-specific-directories-from-the-backup "Permalink") + +您可以通过添加环境变量`SKIP`选择从备份中免除的内容. 可用的选项有: + +* `db` (database) +* `uploads` (attachments) +* `repositories` (Git 仓库数据) +* `builds` (CI 作业输出日志) +* `artifacts` (CI 作业工件) +* `lfs` (LFS 对象) +* `registry` (容器注册表图像) +* `pages` (页面内容) + +使用逗号同时指定多个选项: + +所有 Wiki 将作为`repositories`组的一部分进行备份. 备份期间将跳过不存在的 Wiki. + +对于 Omnibus GitLab 软件包: + +``` +sudo gitlab-backup create SKIP=db,uploads +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +对于源安装: + +``` +sudo -u git -H bundle exec rake gitlab:backup:create SKIP=db,uploads RAILS_ENV=production +``` + +#### Skipping tar creation[](#skipping-tar-creation "Permalink") + +创建备份的最后一部分是生成包含所有部分的`.tar`文件. 在某些情况下(例如,如果备份是由其他备份软件获取的),创建`.tar`文件可能会浪费精力,甚至直接有害,因此可以通过将`tar`添加到`SKIP`环境变量中来跳过此步骤. + +将`tar`添加到`SKIP`变量`SKIP`包含备份的文件和目录保留在用于中间文件的目录中. 创建新备份时,这些文件将被覆盖,因此您应确保将它们复制到其他位置,因为系统上只能有一个备份. + +对于 Omnibus GitLab 软件包: + +``` +sudo gitlab-backup create SKIP=tar +``` + +对于源安装: + +``` +sudo -u git -H bundle exec rake gitlab:backup:create SKIP=tar RAILS_ENV=production +``` + +#### Uploading backups to a remote (cloud) storage[](#uploading-backups-to-a-remote-cloud-storage "Permalink") + +从 GitLab 7.4 开始,您可以让备份脚本上载它创建的`.tar`文件. 它使用[Fog 库](http://fog.io/)执行上传. 在下面的示例中,我们使用 Amazon S3 进行存储,但是 Fog 还允许您使用[其他存储提供商](http://fog.io/storage/) . GitLab 也为 AWS,Google,OpenStack Swift,Rackspace 和 Aliyun [导入了云驱动程序](https://gitlab.com/gitlab-org/gitlab/blob/30f5b9a5b711b46f1065baf755e413ceced5646b/Gemfile#L88) . [也可以使用](#uploading-to-locally-mounted-shares)本地驱动程序. + +[Read more about using object storage with GitLab](../administration/object_storage.html). + +##### Using Amazon S3[](#using-amazon-s3 "Permalink") + +对于 Omnibus GitLab 软件包: + +1. 将以下内容添加到`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_rails['backup_upload_connection'] = { + 'provider' => 'AWS', + 'region' => 'eu-west-1', + 'aws_access_key_id' => 'AKIAKIAKI', + 'aws_secret_access_key' => 'secret123' + # If using an IAM Profile, don't configure aws_access_key_id & aws_secret_access_key + # 'use_iam_profile' => true + } + gitlab_rails['backup_upload_remote_directory'] = 'my.s3.bucket' + ``` + +2. [Reconfigure GitLab](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure) for the changes to take effect + +##### Digital Ocean Spaces[](#digital-ocean-spaces "Permalink") + +该示例可用于阿姆斯特丹(AMS3)中的存储桶. + +1. 将以下内容添加到`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_rails['backup_upload_connection'] = { + 'provider' => 'AWS', + 'region' => 'ams3', + 'aws_access_key_id' => 'AKIAKIAKI', + 'aws_secret_access_key' => 'secret123', + 'endpoint' => 'https://ams3.digitaloceanspaces.com' + } + gitlab_rails['backup_upload_remote_directory'] = 'my.s3.bucket' + ``` + +2. [重新配置 GitLab](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效 + +**注意:**如果通过使用 Digital Ocean Spaces 看到`400 Bad Request` ,则可能是由于使用了备份加密. 由于 Digital Ocean Spaces 不支持加密,因此删除或注释包含`gitlab_rails['backup_encryption']`的行. + +##### Other S3 Providers[](#other-s3-providers "Permalink") + +并非所有 S3 提供程序都与 Fog 库完全兼容. 例如,如果尝试上传后看到`411 Length Required`错误, `aws_signature_version` [于此问题](https://github.com/fog/fog-aws/issues/428) ,您可能需要将`aws_signature_version`值从默认值降级为 2. + +对于源安装: + +1. Edit `home/git/gitlab/config/gitlab.yml`: + + ``` + backup: + # snip + upload: + # Fog storage connection settings, see http://fog.io/storage/ . + connection: + provider: AWS + region: eu-west-1 + aws_access_key_id: AKIAKIAKI + aws_secret_access_key: 'secret123' + # If using an IAM Profile, leave aws_access_key_id & aws_secret_access_key empty + # ie. aws_access_key_id: '' + # use_iam_profile: 'true' + # The remote 'directory' to store your backups. For S3, this would be the bucket name. + remote_directory: 'my.s3.bucket' + # Turns on AWS Server-Side Encryption with Amazon S3-Managed Keys for backups, this is optional + # encryption: 'AES256' + # Turns on AWS Server-Side Encryption with Amazon Customer-Provided Encryption Keys for backups, this is optional + # This should be set to the encryption key for Amazon S3 to use to encrypt or decrypt your data. + # 'encryption' must also be set in order for this to have any effect. + # To avoid storing the key on disk, the key can also be specified via the `GITLAB_BACKUP_ENCRYPTION_KEY` environment variable. + # encryption_key: '' + # Specifies Amazon S3 storage class to use for backups, this is optional + # storage_class: 'STANDARD' + ``` + +2. [重新启动 GitLab](../administration/restart_gitlab.html#installations-from-source)以使更改生效 + +如果要将备份上传到 S3,则可能需要创建具有受限访问权限的新 IAM 用户. 要使上载用户仅能上载备份,请创建以下 IAM 配置文件,将`my.s3.bucket`替换为存储桶的名称: + +``` +{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1412062044000", "Effect": "Allow", "Action": [ "s3:AbortMultipartUpload", "s3:GetBucketAcl", "s3:GetBucketLocation", "s3:GetObject", "s3:GetObjectAcl", "s3:ListBucketMultipartUploads", "s3:PutObject", "s3:PutObjectAcl" ], "Resource": [ "arn:aws:s3:::my.s3.bucket/*" ] }, { "Sid": "Stmt1412062097000", "Effect": "Allow", "Action": [ "s3:GetBucketLocation", "s3:ListAllMyBuckets" ], "Resource": [ "*" ] }, { "Sid": "Stmt1412062128000", "Effect": "Allow", "Action": [ "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::my.s3.bucket" ] } ] } +``` + +##### Using Google Cloud Storage[](#using-google-cloud-storage "Permalink") + +如果要使用 Google Cloud Storage 保存备份,则必须首先从 Google 控制台创建访问密钥: + +1. 转到存储设置页面[https://console.cloud.google.com/storage/settings](https://console.cloud.google.com/storage/settings) +2. 选择"互操作性"并创建访问密钥 +3. 记下"访问密钥"和"秘密"并将其替换为以下配置 +4. 在存储桶高级设置中,确保选择了访问控制选项"设置对象级别和存储桶级别权限" +5. 确保您已经创建了存储桶 + +对于 Omnibus GitLab 软件包: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitlab_rails['backup_upload_connection'] = { + 'provider' => 'Google', + 'google_storage_access_key_id' => 'Access Key', + 'google_storage_secret_access_key' => 'Secret', + + ## If you have CNAME buckets (foo.example.com), you might run into SSL issues + ## when uploading backups ("hostname foo.example.com.storage.googleapis.com + ## does not match the server certificate"). In that case, uncomnent the following + ## setting. See: https://github.com/fog/fog/issues/2834 + #'path_style' => true + } + gitlab_rails['backup_upload_remote_directory'] = 'my.google.bucket' + ``` + +2. [重新配置 GitLab](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效 + +对于源安装: + +1. Edit `home/git/gitlab/config/gitlab.yml`: + + ``` + backup: + upload: + connection: + provider: 'Google' + google_storage_access_key_id: 'Access Key' + google_storage_secret_access_key: 'Secret' + remote_directory: 'my.google.bucket' + ``` + +2. [重新启动 GitLab](../administration/restart_gitlab.html#installations-from-source)以使更改生效 + +##### Specifying a custom directory for backups[](#specifying-a-custom-directory-for-backups "Permalink") + +Note: This option only works for remote storage. If you want to group your backups you can pass a `DIRECTORY` environment variable: + +``` +sudo gitlab-backup create DIRECTORY=daily +sudo gitlab-backup create DIRECTORY=weekly +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +#### Uploading to locally mounted shares[](#uploading-to-locally-mounted-shares "Permalink") + +You may also send backups to a mounted share (for example, `NFS`,`CIFS`, or `SMB`) by using the Fog [`Local`](https://github.com/fog/fog-local#usage) storage provider. The directory pointed to by the `local_root` key **must** be owned by the `git` user **安装时** (mounting with the `uid=` of the `git` user for `CIFS` and `SMB`) or the user that you are executing the backup tasks under (for Omnibus packages, this is the `git` user). + +除`local_root`密钥外, `backup_upload_remote_directory` **必须**设置`local_root` . 这是已安装目录中的子目录,备份将被复制到该子目录,如果不存在,则会创建备份. 如果要将压缩文件复制到的目录是已安装目录的根目录,请使用`.` 代替. + +**注意:**由于文件系统性能可能会影响 GitLab 的整体性能,因此我们不建议使用 EFS 进行存储. [有关](../administration/high_availability/nfs.html#avoid-using-awss-elastic-file-system-efs)更多详细信息,请参见[相关文档](../administration/high_availability/nfs.html#avoid-using-awss-elastic-file-system-efs) . + +对于 Omnibus GitLab 软件包: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitlab_rails['backup_upload_connection'] = { + :provider => 'Local', + :local_root => '/mnt/backups' + } + + # The directory inside the mounted folder to copy backups to + # Use '.' to store them in the root directory + gitlab_rails['backup_upload_remote_directory'] = 'gitlab_backups' + ``` + +2. [重新配置 GitLab,](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +对于源安装: + +1. Edit `home/git/gitlab/config/gitlab.yml`: + + ``` + backup: + upload: + # Fog storage connection settings, see http://fog.io/storage/ . + connection: + provider: Local + local_root: '/mnt/backups' + # The directory inside the mounted folder to copy backups to + # Use '.' to store them in the root directory + remote_directory: 'gitlab_backups' + ``` + +2. [重新启动 GitLab,](../administration/restart_gitlab.html#installations-from-source)以使更改生效. + +#### Backup archive permissions[](#backup-archive-permissions "Permalink") + +由 GitLab 创建的备份存档( `1393513186_2014_02_27_gitlab_backup.tar` )默认情况下将具有所有者/组`git` / `git`和 0600 权限. 这是为了避免其他系统用户读取 GitLab 的数据. 如果您需要备份存档具有不同的权限,则可以使用" archive_permissions"设置. + +对于 Omnibus GitLab 软件包: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitlab_rails['backup_archive_permissions'] = 0644 # Makes the backup archives world-readable + ``` + +2. [重新配置 GitLab,](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +对于源安装: + +1. Edit `/home/git/gitlab/config/gitlab.yml`: + + ``` + backup: + archive_permissions: 0644 # Makes the backup archives world-readable + ``` + +2. [重新启动 GitLab,](../administration/restart_gitlab.html#installations-from-source)以使更改生效. + +#### Configuring cron to make daily backups[](#configuring-cron-to-make-daily-backups "Permalink") + +**警告:**以下 cron 作业不会[备份您的 GitLab 配置文件](#storing-configuration-files)或[SSH 主机密钥](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079) . + +您可以安排一个 cron 作业来备份您的存储库和 GitLab 元数据. + +对于 Omnibus GitLab 软件包: + +1. 编辑`root`用户的 crontab: + + ``` + sudo su - + crontab -e + ``` + +2. 在那里,添加以下行以安排每天凌晨 2 点进行备份: + + ``` + 0 2 * * * /opt/gitlab/bin/gitlab-backup create CRON=1 + ``` + + **注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +对于源安装: + +1. 编辑`git`用户的 crontab: + + ``` + sudo -u git crontab -e + ``` + +2. 在底部添加以下行: + + ``` + # Create a full backup of the GitLab repositories and SQL database every day at 2am + 0 2 * * * cd /home/git/gitlab && PATH=/usr/local/bin:/usr/bin:/bin bundle exec rake gitlab:backup:create RAILS_ENV=production CRON=1 + ``` + +**注意:**如果没有错误, `CRON=1`环境设置将告诉备份脚本禁止所有进度输出. 建议减少 Cron 垃圾邮件. + +### Limit backup lifetime for local files (prune old backups)[](#limit-backup-lifetime-for-local-files-prune-old-backups "Permalink") + +**警告:**如果您使用[自定义文件名](#backup-filename)进行备份,则此操作将无效.**注意:**此配置选项仅管理本地文件. GitLab 不会自动修剪存储在第三方[对象](#uploading-backups-to-a-remote-cloud-storage)存储中的旧文件,因为用户可能没有列出和删除文件的权限. 建议您为对象存储配置适当的保留策略(例如[AWS S3](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/create-lifecycle.html) ). + +您可能希望为备份设置有限的生命周期,以防止使用所有磁盘空间进行常规备份. 下次运行备份任务时,将修剪早于`backup_keep_time`备份. + +对于 Omnibus GitLab 软件包: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + ## Limit backup lifetime to 7 days - 604800 seconds + gitlab_rails['backup_keep_time'] = 604800 + ``` + +2. [重新配置 GitLab,](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +对于源安装: + +1. Edit `/home/git/gitlab/config/gitlab.yml`: + + ``` + backup: + ## Limit backup lifetime to 7 days - 604800 seconds + keep_time: 604800 + ``` + +2. [重新启动 GitLab,](../administration/restart_gitlab.html#installations-from-source)以使更改生效. + +## Restore GitLab[](#restore-gitlab "Permalink") + +GitLab 提供了一个简单的命令行界面来还原整个安装过程,并且足够灵活,可以满足您的需求. + +[还原先决条件部分](#restore-prerequisites)包括关键信息. 在尝试在生产环境中执行还原过程之前,请确保至少阅读并测试整个还原过程一次. + +您只能将备份还原到**与**您在其上创建备份的 GitLab **版本和类型(CE / EE)完全相同的**备份,例如 CE 9.1.0. + +如果备份的版本与当前安装的版本不同,则在还原备份之前,您需要[降级 GitLab 安装](https://docs.gitlab.com/omnibus/update/README.html) . + +### Restore prerequisites[](#restore-prerequisites "Permalink") + +您需要先进行有效的 GitLab 安装,然后才能执行还原. 这主要是因为通常不允许执行还原操作( `git` )的系统用户创建或删除将数据导入到( `gitlabhq_production` )所需的 SQL 数据库. 所有现有数据将被擦除(SQL)或移动到单独的目录(存储库,上载). + +要还原备份,您还需要还原`/etc/gitlab/gitlab-secrets.json` (对于 Omnibus 软件包)或`/home/git/gitlab/.secret` (对于从源安装). 该文件包含数据库加密密钥, [CI / CD 变量](../ci/variables/README.html#gitlab-cicd-environment-variables)以及用于[两因素身份验证的](../user/profile/account/two_factor_authentication.html)变量. 如果您无法通过应用程序数据备份还原此加密密钥文件,则启用了双重身份验证和 GitLab Runners 的用户将无法访问您的 GitLab 服务器. + +您可能还想还原所有 TLS 密钥,证书或[SSH 主机密钥](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079) . + +从 GitLab 12.9 开始,如果找到了未取消备份(如使用`SKIP=tar`备份),并且未使用`BACKUP=`选择任何备份,则将使用未取消备份. + +根据您的情况,您可能需要使用以下一个或多个选项来运行 restore 命令: + +* `BACKUP=timestamp_of_backup`如果存在多个备份,则为必需. 阅读有关[备份时间戳记的内容](#backup-timestamp) . +* `force=yes` yes-不询问是否应重新生成 authorized_keys 文件,并假设" yes"以警告将删除数据库表,启用"写入 authorized_keys 文件"设置并更新 LDAP 提供程序. + +如果要还原到作为挂载点的目录,则在尝试还原之前,需要确保这些目录为空. 否则,GitLab 将在恢复新数据之前尝试移动这些目录,这将导致错误. + +阅读有关[配置 NFS 挂载的](../administration/high_availability/nfs.html)更多信息 + +### Restore for installation from source[](#restore-for-installation-from-source "Permalink") + +``` +# Stop processes that are connected to the database +sudo service gitlab stop + +bundle exec rake gitlab:backup:restore RAILS_ENV=production +``` + +输出示例: + +``` +Unpacking backup... [DONE] +Restoring database tables: +-- create_table("events", {:force=>true}) + -> 0.2231s +[...] +- Loading fixture events...[DONE] +- Loading fixture issues...[DONE] +- Loading fixture keys...[SKIPPING] +- Loading fixture merge_requests...[DONE] +- Loading fixture milestones...[DONE] +- Loading fixture namespaces...[DONE] +- Loading fixture notes...[DONE] +- Loading fixture projects...[DONE] +- Loading fixture protected_branches...[SKIPPING] +- Loading fixture schema_migrations...[DONE] +- Loading fixture services...[SKIPPING] +- Loading fixture snippets...[SKIPPING] +- Loading fixture taggings...[SKIPPING] +- Loading fixture tags...[SKIPPING] +- Loading fixture users...[DONE] +- Loading fixture users_projects...[DONE] +- Loading fixture web_hooks...[SKIPPING] +- Loading fixture wikis...[SKIPPING] +Restoring repositories: +- Restoring repository abcd... [DONE] +- Object pool 1 ... +Deleting tmp directories...[DONE] +``` + +接下来,如果需要,请如上所述恢复`/home/git/gitlab/.secret` . + +重新启动 GitLab: + +``` +sudo service gitlab restart +``` + +### Restore for Omnibus GitLab installations[](#restore-for-omnibus-gitlab-installations "Permalink") + +此过程假定: + +* 您已经安装了与创建备份**完全相同**的 GitLab Omnibus **版本和类型(CE / EE)** . +* 您已经至少运行过`sudo gitlab-ctl reconfigure`一次. +* GitLab 正在运行. 如果没有,请使用`sudo gitlab-ctl start`启动它. + +首先,请确保您的备份 tar 文件位于`gitlab.rb`配置`gitlab_rails['backup_path']`描述的备份目录中. 默认值为`/var/opt/gitlab/backups` . 它必须由`git`用户拥有. + +``` +sudo cp 11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar /var/opt/gitlab/backups/ +sudo chown git.git /var/opt/gitlab/backups/11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar +``` + +停止连接到数据库的进程. 保持其余的 GitLab 运行: + +``` +sudo gitlab-ctl stop unicorn +sudo gitlab-ctl stop puma +sudo gitlab-ctl stop sidekiq +# Verify +sudo gitlab-ctl status +``` + +接下来,还原备份,并指定要还原的备份的时间戳记: + +``` +# This command will overwrite the contents of your GitLab database! +sudo gitlab-backup restore BACKUP=11493107454_2018_04_25_10.6.4-ce +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:restore` .**警告:** `gitlab-rake gitlab:backup:restore`没有在您的注册表目录上设置正确的文件系统权限. 这是一个[已知问题](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62759) . 在 GitLab 12.2 或更高版本上,您可以使用`gitlab-backup restore`来避免此问题. + +接下来,根据需要如上所述恢复`/etc/gitlab/gitlab-secrets.json` . + +重新配置,重启并检查 GitLab: + +``` +sudo gitlab-ctl reconfigure +sudo gitlab-ctl restart +sudo gitlab-rake gitlab:check SANITIZE=true +``` + +如果您的备份 tar 文件和已安装的 GitLab 版本之间的 GitLab 版本不匹配,则 restore 命令将中止并显示错误. 安装[正确的 GitLab 版本,](https://packages.gitlab.com/gitlab/)然后重试. + +**注意**当前存在一个与`pgbouncer`不兼容的还原[问题](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3470) . 为了解决该问题,Rails 节点将需要绕过`pgbouncer`并直接连接到主数据库节点. 这可以通过设置`gitlab_rails['db_host']`和`gitlab_rails['port']`连接到主数据库节点并[重新配置 GitLab 来完成](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure) . + +### Restore for Docker image and GitLab Helm chart installations[](#restore-for-docker-image-and-gitlab-helm-chart-installations "Permalink") + +对于使用 Kubernetes 集群上的 Docker 映像或 GitLab Helm 图表进行的 GitLab 安装,还原任务期望还原目录为空. 但是,使用 Docker 和 Kubernetes 卷挂载,可能会在卷根目录上创建一些系统级目录,例如 Linux 操作系统中找到的`lost+found`目录. 这些目录通常归`root`拥有,因为 restore Rake 任务以`git`用户身份运行,因此可能导致访问权限错误. 因此,要还原 GitLab 安装,用户必须确认还原目标目录为空. + +对于这两种安装类型,备份 tarball 必须在备份位置(默认位置为`/var/opt/gitlab/backups` )中`/var/opt/gitlab/backups` . + +对于 Docker 安装,可以从主机运行还原任务: + +``` +docker exec -it gitlab-backup restore +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:restore` .**警告:** `gitlab-rake gitlab:backup:restore`没有在您的注册表目录上设置正确的文件系统权限. 这是一个[已知问题](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62759) . 在 GitLab 12.2 或更高版本上,您可以使用`gitlab-backup restore`来避免此问题. + +GitLab Helm 图表使用不同的过程,在[恢复 GitLab Helm 图表安装中](https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/backup-restore/restore.md)记录了该过程. + +### Restoring only one or a few project(s) or group(s) from a backup[](#restoring-only-one-or-a-few-projects-or-groups-from-a-backup "Permalink") + +尽管用于还原 GitLab 实例的 Rake 任务不支持还原单个项目或组,但是您可以使用一种解决方法,将备份还原到单独的临时 GitLab 实例,然后从那里导出您的项目或组: + +1. 以与要还原的备份实例相同的版本[安装新的 GitLab](../install/README.html)实例. +2. [将备份还原](#restore-gitlab)到此新实例中,然后导出您的[项目](../user/project/settings/import_export.html)或[组](../user/group/settings/import_export.html) . 确保阅读任一导出功能文档上的**重要说明** ,以了解将导出什么内容,不导出什么内容. +3. 导出完成后,转到旧实例并导入它. +4. 仅在完成所需的项目或组的导入后,您可以删除新的临时 GitLab 实例. + +**注意**在[问题#17517 中](https://gitlab.com/gitlab-org/gitlab/-/issues/17517)讨论了提供直接还原单个项目或组的功能请求. + +## Alternative backup strategies[](#alternative-backup-strategies "Permalink") + +如果您的 GitLab 服务器包含很多 Git 存储库数据,您可能会发现 GitLab 备份脚本太慢. 在这种情况下,您可以考虑将文件系统快照用作备份策略的一部分. + +示例:Amazon EBS + +> A GitLab server using Omnibus GitLab hosted on Amazon AWS. An EBS drive containing an ext4 filesystem is mounted at `/var/opt/gitlab`. In this case you could make an application backup by taking an EBS snapshot. The backup includes all repositories, uploads and PostgreSQL data. + +示例:LVM 快照+ rsync + +> 使用 Omnibus GitLab 的 GitLab 服务器,其 LVM 逻辑卷安装在`/var/opt/gitlab` . 使用 rsync 复制`/var/opt/gitlab`目录将不可靠,因为运行 rsync 时会更改太多文件. 而不是 rsync-ing `/var/opt/gitlab` ,我们创建一个临时 LVM 快照,将其作为只读文件系统安装在`/mnt/gitlab_backup` . 现在,我们可以运行更长的 rsync 作业,它将在远程服务器上创建一致的副本. 副本包括所有存储库,上载和 PostgreSQL 数据. + +如果您在虚拟服务器上运行 GitLab,则还可以创建整个 GitLab 服务器的 VM 快照. 但是,VM 快照要求您关闭服务器电源的情况并不少见,因此这种方法的实际使用可能受到限制. + +## Additional notes[](#additional-notes "Permalink") + +本文档适用于 GitLab 社区和企业版. 我们备份 GitLab.com 并确保您的数据安全,但是您不能使用这些方法自己从 GitLab.com 导出/备份数据. + +问题存储在数据库中. 它们不能存储在 Git 本身中. + +要使用最新版本的 GitLab 将存储库从一台服务器迁移到另一台服务器,可以使用[import Rake 任务](import.html)来批量导入存储库. 请注意,如果您执行导入 Rake 任务而不是备份还原,则将拥有所有存储库,但没有其他任何数据. + +## Troubleshooting[](#troubleshooting "Permalink") + +以下是可能的解决方案可能遇到的问题. + +### Restoring database backup using Omnibus packages outputs warnings[](#restoring-database-backup-using-omnibus-packages-outputs-warnings "Permalink") + +如果使用备份还原过程,则可能会遇到以下警告: + +``` +psql:/var/opt/gitlab/backups/db/database.sql:22: ERROR: must be owner of extension plpgsql +psql:/var/opt/gitlab/backups/db/database.sql:2931: WARNING: no privileges could be revoked for "public" (two occurrences) +psql:/var/opt/gitlab/backups/db/database.sql:2933: WARNING: no privileges were granted for "public" (two occurrences) +``` + +请注意,尽管有这些警告,备份仍成功还原. + +Rake 任务以`gitlab`用户身份运行,该用户没有对数据库的超级用户访问权限. 启动还原时,它还将以`gitlab`用户身份运行,但也会尝试更改其无权访问的对象. 这些对象对数据库的备份/还原没有影响,但是它们发出此烦人的警告. + +有关更多信息,请参见[此处](https://s0www0postgresql0org.icopy.site/message-id/201110220712.30886.adrian.klaver@gmail.com)和[此处](https://s0www0postgresql0org.icopy.site/message-id/2039.1177339749@sss.pgh.pa.us)有关 PostgreSQL 问题跟踪器的类似问题以及[堆栈溢出](https://stackoverflow.com/questions/4368789/error-must-be-owner-of-language-plpgsql) . + +### When the secrets file is lost[](#when-the-secrets-file-is-lost "Permalink") + +如果您无法[备份 secrets 文件](#storing-configuration-files) ,则启用 2FA 的用户将无法登录 GitLab. 在这种情况下,您需要[为所有人禁用 2FA](../security/two_factor_authentication.html#disabling-2fa-for-everyone) . + +机密文件还负责为包含敏感信息的几列存储加密密钥. 如果密钥丢失,GitLab 将无法解密这些列. 这将破坏广泛的功能,包括(但不限于): + +* [CI/CD variables](../ci/variables/README.html) +* [Kubernetes / GCP integration](../user/project/clusters/index.html) +* [Custom Pages domains](../user/project/pages/custom_domains_ssl_tls_certification/index.html) +* [Project error tracking](../user/project/operations/error_tracking.html) +* [Runner authentication](../ci/runners/README.html) +* [Project mirroring](../user/project/repository/repository_mirroring.html) +* [Web hooks](../user/project/integrations/webhooks.html) + +在 CI / CD 变量和 Runner 身份验证之类的情况下,您可能会遇到一些意外行为,例如: + +* 卡住了工作. +* 500 个错误. + +您可以使用[Secrets Doctor Rake 任务](../administration/raketasks/doctor.html)检查数据库中是否具有不可解密的值. + +在这种情况下,您需要重置 CI / CD 变量和运行程序身份验证的所有令牌,下面将对此进行详细说明. 重置令牌后,您应该能够访问您的项目,并且作业将重新开始运行. + +**警告:**使用以下命令需要您自担风险,并确保事先进行了备份. + +#### Reset CI/CD variables[](#reset-cicd-variables "Permalink") + +1. 输入数据库控制台: + + 对于 Omnibus GitLab 软件包: + + ``` + sudo gitlab-rails dbconsole + ``` + + 对于源安装: + + ``` + sudo -u git -H bundle exec rails dbconsole -e production + ``` + +2. 检查`ci_group_variables`和`ci_variables`表: + + ``` + SELECT * FROM public."ci_group_variables"; + SELECT * FROM public."ci_variables"; + ``` + + 这些是您需要删除的变量. + +3. 放下桌子: + + ``` + DELETE FROM ci_group_variables; + DELETE FROM ci_variables; + ``` + +4. 您可能需要重新配置或重新启动 GitLab 才能使更改生效. + +#### Reset Runner registration tokens[](#reset-runner-registration-tokens "Permalink") + +1. 输入数据库控制台: + + 对于 Omnibus GitLab 软件包: + + ``` + sudo gitlab-rails dbconsole + ``` + + 对于源安装: + + ``` + sudo -u git -H bundle exec rails dbconsole -e production + ``` + +2. 清除项目,组和整个实例的所有令牌: + + **Caution:** The last UPDATE operation will stop the runners being able to pick up new jobs. You must register new runners. + + ``` + -- Clear project tokens + UPDATE projects SET runners_token = null, runners_token_encrypted = null; + -- Clear group tokens + UPDATE namespaces SET runners_token = null, runners_token_encrypted = null; + -- Clear instance tokens + UPDATE application_settings SET runners_registration_token_encrypted = null; + -- Clear runner tokens + UPDATE ci_runners SET token = null, token_encrypted = null; + ``` + +#### Reset pending pipeline jobs[](#reset-pending-pipeline-jobs "Permalink") + +1. 输入数据库控制台: + + 对于 Omnibus GitLab 软件包: + + ``` + sudo gitlab-rails dbconsole + ``` + + 对于源安装: + + ``` + sudo -u git -H bundle exec rails dbconsole -e production + ``` + +2. 清除所有待处理作业的令牌: + + ``` + -- Clear build tokens + UPDATE ci_builds SET token = null, token_encrypted = null; + ``` + +其余功能也可以采用类似的策略-通过删除无法解密的数据,GitLab 可以恢复工作状态,并且可以手动替换丢失的数据. + +### Container Registry push failures after restoring from a backup[](#container-registry-push-failures-after-restoring-from-a-backup "Permalink") + +如果使用[Container Registry](../user/packages/container_registry/index.html) ,则在还原注册表数据后,在 Omnibus GitLab 实例上还原备份后,可能会推送到注册表失败. + +这些失败将在注册表日志中提及权限问题,例如: + +``` +level=error +msg="response completed with error" +err.code=unknown +err.detail="filesystem: mkdir /var/opt/gitlab/gitlab-rails/shared/registry/docker/registry/v2/repositories/...: permission denied" +err.message="unknown error" +``` + +这是由于还原以非特权用户`git`身份运行的,该用户在还原期间无法将正确的所有权分配给注册表文件( [问题 62759](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62759 "还原后对注册表文件系统的权限不正确") ). + +要使您的注册表再次起作用: + +``` +sudo chown -R registry:registry /var/opt/gitlab/gitlab-rails/shared/registry/docker +``` + +**注意:**如果您更改了注册表的默认文件系统位置,则需要对定制位置而不是`/var/opt/gitlab/gitlab-rails/shared/registry/docker`运行`chown` . + +### Backup fails to complete with Gzip error[](#backup-fails-to-complete-with-gzip-error "Permalink") + +运行备份时,您可能会收到 Gzip 错误: + +``` +sudo /opt/gitlab/bin/gitlab-backup create +... +Dumping ... +... +gzip: stdout: Input/output error + +Backup failed +``` + +如果发生这种情况,请检查以下内容: + +1. 确认有足够的磁盘空间用于 Gzip 操作. +2. 如果正在使用 NFS,请检查是否设置了安装选项`timeout` . 默认值为`600` ,并将其更改为较小的值会导致此错误. \ No newline at end of file diff --git a/_book/docs/511.md b/_book/docs/511.md new file mode 100644 index 0000000000000000000000000000000000000000..87e39ad7a1cc48d667a07328bd6698751a1b3333 --- /dev/null +++ b/_book/docs/511.md @@ -0,0 +1,195 @@ +# Clean up + +> 原文:[https://docs.gitlab.com/ee/raketasks/cleanup.html](https://docs.gitlab.com/ee/raketasks/cleanup.html) + +* [Remove unreferenced LFS files](#remove-unreferenced-lfs-files) + * [Remove unreferenced LFS files immediately](#remove-unreferenced-lfs-files-immediately) +* [Clean up project upload files](#clean-up-project-upload-files) + * [Clean up project upload files from filesystem](#clean-up-project-upload-files-from-filesystem) + * [Clean up project upload files from object storage](#clean-up-project-upload-files-from-object-storage) +* [Remove orphan artifact files](#remove-orphan-artifact-files) +* [Remove expired ActiveSession lookup keys](#remove-expired-activesession-lookup-keys) +* [Container Registry garbage collection](#container-registry-garbage-collection) + +# Clean up[](#clean-up-core-only "Permalink") + +GitLab 提供 Rake 任务来清理 GitLab 实例. + +## Remove unreferenced LFS files[](#remove-unreferenced-lfs-files "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36628) . + +**危险:**不要在 GitLab 升级后的 12 小时内运行此程序. 这是为了确保所有后台迁移均已完成,否则可能导致数据丢失. + +当您从存储库的历史记录中删除 LFS 文件时,它们将变成孤立文件并继续占用磁盘空间. 使用此 Rake 任务,您可以从数据库中删除无效的引用,这将允许对 LFS 文件进行垃圾回收. + +例如: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:cleanup:orphan_lfs_file_references PROJECT_PATH="gitlab-org/gitlab-foss" + +# installation from source +bundle exec rake gitlab:cleanup:orphan_lfs_file_references RAILS_ENV=production PROJECT_PATH="gitlab-org/gitlab-foss" +``` + +您也可以使用`PROJECT_ID`而不是`PROJECT_PATH`指定项目. + +例如: + +``` +$ sudo gitlab-rake gitlab:cleanup:orphan_lfs_file_references PROJECT_PATH="gitlab-org/gitlab-foss" +I, [2019-12-13T16:35:31.764962 #82356] INFO -- : Looking for orphan LFS files for project GitLab Org / GitLab Foss +I, [2019-12-13T16:35:31.923659 #82356] INFO -- : Removed invalid references: 12 +``` + +默认情况下,此任务不会删除任何内容,但会显示它可以删除多少个文件引用. 如果您确实要删除引用,请运行`DRY_RUN=false`的命令. 您还可以使用`LIMIT={number}`参数来限制已删除引用的数量. + +请注意,此 Rake 任务仅删除对 LFS 文件的引用. 未引用的 LFS 文件将在以后(每天一次)进行垃圾收集. 如果您需要立即进行垃圾回收,请运行以下描述的`rake gitlab:cleanup:orphan_lfs_files` . + +### Remove unreferenced LFS files immediately[](#remove-unreferenced-lfs-files-immediately "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36628) . + +每天都会删除未引用的 LFS 文件,但是如果需要,您可以立即删除它们. 例如: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:cleanup:orphan_lfs_files + +# installation from source +bundle exec rake gitlab:cleanup:orphan_lfs_files +``` + +输出示例: + +``` +$ sudo gitlab-rake gitlab:cleanup:orphan_lfs_files +I, [2020-01-08T20:51:17.148765 #43765] INFO -- : Removed unreferenced LFS files: 12 +``` + +## Clean up project upload files[](#clean-up-project-upload-files "Permalink") + +如果项目上传文件在 GitLab 数据库中不存在,请清理它们. + +### Clean up project upload files from filesystem[](#clean-up-project-upload-files-from-filesystem "Permalink") + +在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20863) . + +如果本地项目上传文件在 GitLab 数据库中不存在,请清理它们. 如果该任务可以找到其项目,则该任务将尝试修复该文件,否则,它将文件移至丢失并找到的目录. + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:cleanup:project_uploads + +# installation from source +bundle exec rake gitlab:cleanup:project_uploads RAILS_ENV=production +``` + +输出示例: + +``` +$ sudo gitlab-rake gitlab:cleanup:project_uploads + +I, [2018-07-27T12:08:27.671559 #89817] INFO -- : Looking for orphaned project uploads to clean up. Dry run... +D, [2018-07-27T12:08:28.293568 #89817] DEBUG -- : Processing batch of 500 project upload file paths, starting with /opt/gitlab/embedded/service/gitlab-rails/public/uploads/test.out +I, [2018-07-27T12:08:28.689869 #89817] INFO -- : Can move to lost and found /opt/gitlab/embedded/service/gitlab-rails/public/uploads/test.out -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/project-lost-found/test.out +I, [2018-07-27T12:08:28.755624 #89817] INFO -- : Can fix /opt/gitlab/embedded/service/gitlab-rails/public/uploads/foo/bar/89a0f7b0b97008a4a18cedccfdcd93fb/foo.txt -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/qux/foo/bar/89a0f7b0b97008a4a18cedccfdcd93fb/foo.txt +I, [2018-07-27T12:08:28.760257 #89817] INFO -- : Can move to lost and found /opt/gitlab/embedded/service/gitlab-rails/public/uploads/foo/bar/1dd6f0f7eefd2acc4c2233f89a0f7b0b/image.png -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/project-lost-found/foo/bar/1dd6f0f7eefd2acc4c2233f89a0f7b0b/image.png +I, [2018-07-27T12:08:28.764470 #89817] INFO -- : To cleanup these files run this command with DRY_RUN=false + +$ sudo gitlab-rake gitlab:cleanup:project_uploads DRY_RUN=false I, [2018-07-27T12:08:32.944414 #89936] INFO -- : Looking for orphaned project uploads to clean up... +D, [2018-07-27T12:08:33.293568 #89817] DEBUG -- : Processing batch of 500 project upload file paths, starting with /opt/gitlab/embedded/service/gitlab-rails/public/uploads/test.out +I, [2018-07-27T12:08:33.689869 #89817] INFO -- : Did move to lost and found /opt/gitlab/embedded/service/gitlab-rails/public/uploads/test.out -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/project-lost-found/test.out +I, [2018-07-27T12:08:33.755624 #89817] INFO -- : Did fix /opt/gitlab/embedded/service/gitlab-rails/public/uploads/foo/bar/89a0f7b0b97008a4a18cedccfdcd93fb/foo.txt -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/qux/foo/bar/89a0f7b0b97008a4a18cedccfdcd93fb/foo.txt +I, [2018-07-27T12:08:33.760257 #89817] INFO -- : Did move to lost and found /opt/gitlab/embedded/service/gitlab-rails/public/uploads/foo/bar/1dd6f0f7eefd2acc4c2233f89a0f7b0b/image.png -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/project-lost-found/foo/bar/1dd6f0f7eefd2acc4c2233f89a0f7b0b/image.png +``` + +### Clean up project upload files from object storage[](#clean-up-project-upload-files-from-object-storage "Permalink") + +在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20918) . + +如果对象存储库上载文件在 GitLab 数据库中不存在,请将其移动到丢失和找到的目录中. + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:cleanup:remote_upload_files + +# installation from source +bundle exec rake gitlab:cleanup:remote_upload_files RAILS_ENV=production +``` + +Example output: + +``` +$ sudo gitlab-rake gitlab:cleanup:remote_upload_files + +I, [2018-08-02T10:26:13.995978 #45011] INFO -- : Looking for orphaned remote uploads to remove. Dry run... +I, [2018-08-02T10:26:14.120400 #45011] INFO -- : Can be moved to lost and found: @hashed/6b/DSC_6152.JPG +I, [2018-08-02T10:26:14.120482 #45011] INFO -- : Can be moved to lost and found: @hashed/79/02/7902699be42c8a8e46fbbb4501726517e86b22c56a189f7625a6da49081b2451/711491b29d3eb08837798c4909e2aa4d/DSC00314.jpg +I, [2018-08-02T10:26:14.120634 #45011] INFO -- : To cleanup these files run this command with DRY_RUN=false +``` + +``` +$ sudo gitlab-rake gitlab:cleanup:remote_upload_files DRY_RUN=false I, [2018-08-02T10:26:47.598424 #45087] INFO -- : Looking for orphaned remote uploads to remove... +I, [2018-08-02T10:26:47.753131 #45087] INFO -- : Moved to lost and found: @hashed/6b/DSC_6152.JPG -> lost_and_found/@hashed/6b/DSC_6152.JPG +I, [2018-08-02T10:26:47.764356 #45087] INFO -- : Moved to lost and found: @hashed/79/02/7902699be42c8a8e46fbbb4501726517e86b22c56a189f7625a6da49081b2451/711491b29d3eb08837798c4909e2aa4d/DSC00314.jpg -> lost_and_found/@hashed/79/02/7902699be42c8a8e46fbbb4501726517e86b22c56a189f7625a6da49081b2451/711491b29d3eb08837798c4909e2aa4d/DSC00314.jpg +``` + +## Remove orphan artifact files[](#remove-orphan-artifact-files "Permalink") + +版本历史 + +* 在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29681) . +* 在 GitLab 12.10 中[修复](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28023)了[`ionice`支持](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28023) . + +如果发现磁盘上的作业工件文件多于应有的数量,则可以运行: + +``` +sudo gitlab-rake gitlab:cleanup:orphan_job_artifact_files +``` + +该命令: + +* 扫描整个工件文件夹. +* 检查哪些文件在数据库中仍然有记录. +* 如果找不到数据库记录,那么将从磁盘中删除该文件. + +默认情况下,此任务不会删除任何内容,但会显示它可以删除的内容. 如果您实际上要删除文件,请运行`DRY_RUN=false`的命令: + +``` +sudo gitlab-rake gitlab:cleanup:orphan_job_artifact_files DRY_RUN=false +``` + +您还可以使用`LIMIT`要删除的文件数: + +``` +sudo gitlab-rake gitlab:cleanup:orphan_job_artifact_files LIMIT=100 +``` + +这只会从磁盘上删除多达 100 个文件. 您可以使用此功能删除一小集以进行测试. + +如果提供`DEBUG=1` ,则将看到被检测为孤立文件的每个文件的完整路径. + +如果安装了`ionice` ,则任务将使用它来确保命令不会在磁盘上造成太大的负载. 您可以使用`NICENESS`配置`NICENESS`级别. 以下是有效水平,但请务必咨询`man 1 ionice` . + +* `0` or `None` +* `1` or `Realtime` +* `2` or `Best-effort` (default) +* `3` or `Idle` + +## Remove expired ActiveSession lookup keys[](#remove-expired-activesession-lookup-keys "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30668) . + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:cleanup:sessions:active_sessions_lookup_keys + +# installation from source +bundle exec rake gitlab:cleanup:sessions:active_sessions_lookup_keys RAILS_ENV=production +``` + +## Container Registry garbage collection[](#container-registry-garbage-collection "Permalink") + +容器注册表可以使用大量的磁盘空间. 为了清除未使用的层,注册表包括一个[垃圾收集命令](../administration/packages/container_registry.html#container-registry-garbage-collection) . \ No newline at end of file diff --git a/_book/docs/512.md b/_book/docs/512.md new file mode 100644 index 0000000000000000000000000000000000000000..0c1ec48e8b7c8addf89e1b8c7f6c9b0c9e9becbc --- /dev/null +++ b/_book/docs/512.md @@ -0,0 +1,27 @@ +# Namespaces + +> 原文:[https://docs.gitlab.com/ee/raketasks/features.html](https://docs.gitlab.com/ee/raketasks/features.html) + +* [Enable usernames and namespaces for user projects](#enable-usernames-and-namespaces-for-user-projects) + +# Namespaces[](#namespaces-core-only "Permalink") + +此 Rake 任务为项目启用[名称空间](../user/group/index.html#namespaces) . + +## Enable usernames and namespaces for user projects[](#enable-usernames-and-namespaces-for-user-projects "Permalink") + +此命令将启用 GitLab 4.0 中引入的名称空间功能. 它将移动每个项目在其名称空间文件夹中. + +Note: + +* **存储库位置将更改** ,因此您将需要**更新所有 Git URL**以指向新位置. +* 可以在**个人资料>帐户中**更改用户名. + +例如: + +* 旧路径: `git@example.org:myrepo.git` . +* 新路径: `git@example.org:username/myrepo.git`或`git@example.org:groupname/myrepo.git` . + +``` +bundle exec rake gitlab:enable_namespaces RAILS_ENV=production +``` \ No newline at end of file diff --git a/_book/docs/513.md b/_book/docs/513.md new file mode 100644 index 0000000000000000000000000000000000000000..329a902a4c74389359a30fb688f0a2daad9d5dbc --- /dev/null +++ b/_book/docs/513.md @@ -0,0 +1,317 @@ +# Maintenance Rake tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/maintenance.html](https://docs.gitlab.com/ee/administration/raketasks/maintenance.html) + +* [Gather GitLab and system information](#gather-gitlab-and-system-information) +* [Show GitLab license information](#show-gitlab-license-information-starter-only) +* [Check GitLab configuration](#check-gitlab-configuration) +* [Rebuild authorized_keys file](#rebuild-authorized_keys-file) +* [Clear Redis cache](#clear-redis-cache) +* [Precompile the assets](#precompile-the-assets) +* [Check TCP connectivity to a remote site](#check-tcp-connectivity-to-a-remote-site) +* [Clear exclusive lease (DANGER)](#clear-exclusive-lease-danger) +* [Display status of database migrations](#display-status-of-database-migrations) +* [Run incomplete database migrations](#run-incomplete-database-migrations) +* [Import common metrics](#import-common-metrics) + +# Maintenance Rake tasks[](#maintenance-rake-tasks-core-only "Permalink") + +GitLab 提供 Rake 任务进行常规维护. + +## Gather GitLab and system information[](#gather-gitlab-and-system-information "Permalink") + +该命令收集有关您的 GitLab 安装及其运行系统的信息. 这些在寻求帮助或报告问题时可能很有用. + +**全部安装** + +``` +sudo gitlab-rake gitlab:env:info +``` + +**源安装** + +``` +bundle exec rake gitlab:env:info RAILS_ENV=production +``` + +输出示例: + +``` +System information +System: Debian 7.8 +Current User: git +Using RVM: no +Ruby Version: 2.1.5p273 +Gem Version: 2.4.3 +Bundler Version: 1.7.6 +Rake Version: 10.3.2 +Redis Version: 3.2.5 +Sidekiq Version: 2.17.8 + +GitLab information +Version: 7.7.1 +Revision: 41ab9e1 +Directory: /home/git/gitlab +DB Adapter: postgresql +URL: https://gitlab.example.com +HTTP Clone URL: https://gitlab.example.com/some-project.git +SSH Clone URL: git@gitlab.example.com:some-project.git +Using LDAP: no +Using Omniauth: no + +GitLab Shell +Version: 2.4.1 +Repositories: /home/git/repositories/ +Hooks: /home/git/gitlab-shell/hooks/ +Git: /usr/bin/git +``` + +## Show GitLab license information[](#show-gitlab-license-information-starter-only "Permalink") + +在 GitLab Starter 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20501) . + +该命令显示有关您的[GitLab 许可证](../../user/admin_area/license.html)以及使用了多少个席位的信息. 它仅在 GitLab Enterprise 安装中可用:许可证无法安装到 GitLab Community Edition 中. + +当通过支持人员举票或以编程方式检查许可证参数时,这些选项可能很有用. + +**全部安装** + +``` +sudo gitlab-rake gitlab:license:info +``` + +**源安装** + +``` +bundle exec rake gitlab:license:info RAILS_ENV=production +``` + +输出示例: + +``` +Today's Date: 2020-02-29 +Current User Count: 30 +Max Historical Count: 30 +Max Users in License: 40 +License valid from: 2019-11-29 to 2020-11-28 +Email associated with license: user@example.com +``` + +## Check GitLab configuration[](#check-gitlab-configuration "Permalink") + +`gitlab:check` Rake 任务运行以下 Rake 任务: + +* `gitlab:gitlab_shell:check` +* `gitlab:gitaly:check` +* `gitlab:sidekiq:check` +* `gitlab:app:check` + +它将检查是否已根据安装指南设置了每个组件,并针对发现的问题提出了修复建议. 此命令必须从您的应用程序服务器运行,并且在[Gitaly 之](../gitaly/index.html#run-gitaly-on-its-own-server)类的组件服务器上将无法正常运行. + +您还可以查看我们的故障排除指南,以了解: + +* [GitLab](../index.html#troubleshooting) +* [Omnibus GitLab](https://docs.gitlab.com/omnibus/README.html) + +要运行`gitlab:check` ,请运行: + +**全部安装** + +``` +sudo gitlab-rake gitlab:check +``` + +**源安装** + +``` +bundle exec rake gitlab:check RAILS_ENV=production +``` + +**注意:**对`gitlab:check`使用`SANITIZE=true` `gitlab:check`是否要从输出中省略项目名称. + +输出示例: + +``` +Checking Environment ... + +Git configured for git user? ... yes +Has python2? ... yes +python2 is supported version? ... yes + +Checking Environment ... Finished + +Checking GitLab Shell ... + +GitLab Shell version? ... OK (1.2.0) +Repo base directory exists? ... yes +Repo base directory is a symlink? ... no +Repo base owned by git:git? ... yes +Repo base access is drwxrws---? ... yes +post-receive hook up-to-date? ... yes +post-receive hooks in repos are links: ... yes + +Checking GitLab Shell ... Finished + +Checking Sidekiq ... + +Running? ... yes + +Checking Sidekiq ... Finished + +Checking GitLab ... + +Database config exists? ... yes +Database is SQLite ... no +All migrations up? ... yes +GitLab config exists? ... yes +GitLab config outdated? ... no +Log directory writable? ... yes +Tmp directory writable? ... yes +Init script exists? ... yes +Init script up-to-date? ... yes +Redis version >= 2.0.0? ... yes + +Checking GitLab ... Finished +``` + +## Rebuild authorized_keys file[](#rebuild-authorized_keys-file "Permalink") + +在某些情况下,有必要重建`authorized_keys`文件. 为此,请运行: + +**全部安装** + +``` +sudo gitlab-rake gitlab:shell:setup +``` + +**源安装** + +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production +``` + +输出示例: + +``` +This will rebuild an authorized_keys file. +You will lose any data stored in authorized_keys file. +Do you want to continue (yes/no)? yes +``` + +## Clear Redis cache[](#clear-redis-cache "Permalink") + +如果出于某种原因,仪表板显示了错误的信息,则可能需要清除 Redis 的缓存. 为此,请运行: + +**全部安装** + +``` +sudo gitlab-rake cache:clear +``` + +**源安装** + +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production +``` + +## Precompile the assets[](#precompile-the-assets "Permalink") + +有时,在版本升级期间,您可能会遇到一些错误的 CSS 或缺少某些图标的情况. 在这种情况下,请尝试再次重新编译资产. + +这仅适用于源安装,不适用于 Omnibus 软件包. + +**源安装** + +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production +``` + +对于多功能版本,未优化的资产(JavaScript,CSS)在上游 GitLab 发行时被冻结. 多功能版本包括这些资产的优化版本. 除非在安装软件包之后在生产机器上修改 JavaScript / CSS 代码,否则应该没有理由在生产机器上重做`rake gitlab:assets:compile` . 如果您怀疑资产已损坏,则应重新安装 omnibus 软件包. + +## Check TCP connectivity to a remote site[](#check-tcp-connectivity-to-a-remote-site "Permalink") + +有时您需要知道您的 GitLab 安装是否可以连接到另一台机器上的 TCP 服务-也许是 PostgreSQL 或 HTTPS 服务器. 包含一个 Rake 任务可以帮助您: + +**全部安装** + +``` +sudo gitlab-rake gitlab:tcp_check[example.com,80] +``` + +**源安装** + +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:tcp_check[example.com,80] RAILS_ENV=production +``` + +## Clear exclusive lease (DANGER)[](#clear-exclusive-lease-danger "Permalink") + +GitLab 使用共享锁机制: `ExclusiveLease`防止共享资源中的同时操作. 一个示例是在存储库上运行定期垃圾收集. + +在非常特殊的情况下,如果不释放锁定,则由专有租赁锁定的操作可能会失败. 如果您不能等待它过期,可以运行此任务以手动清除它. + +要清除所有专有租赁: + +**危险:**请勿在 GitLab 或 Sidekiq 运行时运行它 + +``` +sudo gitlab-rake gitlab:exclusive_lease:clear +``` + +要指定租约`type`或租约`type + id` ,请指定范围: + +``` +# to clear all leases for repository garbage collection: +sudo gitlab-rake gitlab:exclusive_lease:clear[project_housekeeping:*] + +# to clear a lease for repository garbage collection in a specific project: (id=4) +sudo gitlab-rake gitlab:exclusive_lease:clear[project_housekeeping:4] +``` + +## Display status of database migrations[](#display-status-of-database-migrations "Permalink") + +请参阅[升级文档](../../update/README.html#checking-for-background-migrations-before-upgrading) ,以了解在升级 GitLab 时如何检查迁移是否完成. + +要检查特定迁移的状态,可以使用以下 Rake 任务: + +``` +sudo gitlab-rake db:migrate:status +``` + +这将为每个迁移 ID 输出一个`Status`为`up`或`down`的表. + +``` +database: gitlabhq_production + + Status Migration ID Migration Name +-------------------------------------------------- + up migration_id migration_name +``` + +## Run incomplete database migrations[](#run-incomplete-database-migrations "Permalink") + +数据库迁移可能会停留在不完整的状态. 也就是说,它们在`sudo gitlab-rake db:migrate:status`命令的输出中将处于`down`状态. + +要完成这些迁移,请使用以下 Rake 任务: + +``` +sudo gitlab-rake db:migrate +``` + +命令完成后,运行`sudo gitlab-rake db:migrate:status`来检查是否所有迁移都已完成(具有`up`状态). + +## Import common metrics[](#import-common-metrics "Permalink") + +有时,您可能需要重新导入为"指标"仪表板提供动力的通用指标. + +这可能是由于[更新现有指标](../../development/prometheus_metrics.html#update-existing-metrics)或作为[故障排除措施的结果](../../operations/metrics/dashboards/index.html#troubleshooting) . + +要重新导入指标,可以运行: + +``` +sudo gitlab-rake metrics:setup_common_metrics +``` \ No newline at end of file diff --git a/_book/docs/514.md b/_book/docs/514.md new file mode 100644 index 0000000000000000000000000000000000000000..1fbeffa72eb31537b7e756729638a7fb4326b1ce --- /dev/null +++ b/_book/docs/514.md @@ -0,0 +1,81 @@ +# Geo Rake Tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/geo.html](https://docs.gitlab.com/ee/administration/raketasks/geo.html) + +* [Git housekeeping](#git-housekeeping) + * [Incremental Repack](#incremental-repack) + * [Full Repack](#full-repack) + * [GC](#gc) +* [Remove orphaned project registries](#remove-orphaned-project-registries) + +# Geo Rake Tasks[](#geo-rake-tasks-premium-only "Permalink") + +以下 Rake 任务适用于[Geo 安装](../geo/replication/index.html) . + +## Git housekeeping[](#git-housekeeping "Permalink") + +您可以执行一些任务来调度 Git 内务处理,以从**辅助**节点中的下一个存储库同步开始: + +### Incremental Repack[](#incremental-repack "Permalink") + +这等效于在*裸*仓库上运行`git repack -d` . + +**全部安装** + +``` +sudo gitlab-rake geo:git:housekeeping:incremental_repack +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake geo:git:housekeeping:incremental_repack RAILS_ENV=production +``` + +### Full Repack[](#full-repack "Permalink") + +这等效于在*裸*仓库上运行`git repack -d -A --pack-kept-objects` ,可以选择在 GitLab 中启用它时写入可达性位图索引. + +**全部安装** + +``` +sudo gitlab-rake geo:git:housekeeping:full_repack +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake geo:git:housekeeping:full_repack RAILS_ENV=production +``` + +### GC[](#gc "Permalink") + +这等效于在*裸*仓库上运行`git gc` ,如果在 GitLab 中启用了此功能,则可以选择编写可达性位图索引. + +**全部安装** + +``` +sudo gitlab-rake geo:git:housekeeping:gc +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake geo:git:housekeeping:gc RAILS_ENV=production +``` + +## Remove orphaned project registries[](#remove-orphaned-project-registries "Permalink") + +在某些情况下,您的项目注册表可能包含过时的记录,您可以使用 Rake 任务`geo:run_orphaned_project_registry_cleaner`删除它们: + +**全部安装** + +``` +sudo gitlab-rake geo:run_orphaned_project_registry_cleaner +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake geo:run_orphaned_project_registry_cleaner RAILS_ENV=production +``` \ No newline at end of file diff --git a/_book/docs/515.md b/_book/docs/515.md new file mode 100644 index 0000000000000000000000000000000000000000..fc2b3abf02c0712854caf111dfd8c517054331db --- /dev/null +++ b/_book/docs/515.md @@ -0,0 +1,45 @@ +# GitHub import + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/github_import.html](https://docs.gitlab.com/ee/administration/raketasks/github_import.html) + +* [Caveats](#caveats) +* [Importing multiple projects](#importing-multiple-projects) +* [Importing a single project](#importing-a-single-project) + +# GitHub import[](#github-import-core-only "Permalink") + +在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10308) . + +为了检索和导入 GitHub 存储库,您将需要一个[GitHub 个人访问令牌](https://github.com/settings/tokens) . 用户名应作为 Rake 任务的第二个参数传递,该任务将成为项目的所有者. 您可以使用相同的命令恢复导入. + +请记住,语法非常具体. 删除参数块内以及方括号之前/之后的所有空格. 此外,某些外壳程序(例如`zsh` )可以分别解释开/关括号( `[]` ). 您可能需要转义括号或使用双引号. + +## Caveats[](#caveats "Permalink") + +如果在导入时达到 GitHub [速率限制](https://developer.github.com/v3/#rate-limiting) ,则导入过程将等待( `sleep()` ),直到可以继续导入为止. + +## Importing multiple projects[](#importing-multiple-projects "Permalink") + +要从可用的 GitHub 项目列表中导入项目,请执行以下操作: + +``` +# Omnibus installations +sudo gitlab-rake "import:github[access_token,root,foo/bar]" + +# Installations from source +bundle exec rake "import:github[access_token,root,foo/bar]" RAILS_ENV=production +``` + +在这种情况下, `access_token`是您的 GitHub 个人访问令牌, `root`是您的 GitLab 用户名,而`foo/bar`是将从您的 GitHub 项目创建的新 GitLab 名称空间/项目. 子组也是可能的: `foo/foo/bar` . + +## Importing a single project[](#importing-a-single-project "Permalink") + +要导入特定的 GitHub 项目(在此处名为`foo/github_repo` ): + +``` +# Omnibus installations +sudo gitlab-rake "import:github[access_token,root,foo/bar,foo/github_repo]" + +# Installations from source +bundle exec rake "import:github[access_token,root,foo/bar,foo/github_repo]" RAILS_ENV=production +``` \ No newline at end of file diff --git a/_book/docs/516.md b/_book/docs/516.md new file mode 100644 index 0000000000000000000000000000000000000000..0da21b979c19f2b79babcaa2110dfbc8264c5868 --- /dev/null +++ b/_book/docs/516.md @@ -0,0 +1,132 @@ +# Import bare repositories + +> 原文:[https://docs.gitlab.com/ee/raketasks/import.html](https://docs.gitlab.com/ee/raketasks/import.html) + +* [Example output](#example-output) +* [Importing bare repositories from hashed storage](#importing-bare-repositories-from-hashed-storage) + * [GitLab 10.3 or earlier](#gitlab-103-or-earlier) + * [GitLab 10.4 and later](#gitlab-104-and-later) + +# Import bare repositories[](#import-bare-repositories-core-only "Permalink") + +Rake 任务可用于将裸仓库导入 GitLab 实例. + +注意: + +* 项目的所有者将是第一位管理员. +* 将根据需要创建组,包括子组. +* 组的所有者将是第一位管理员. +* 现有项目将被跳过. +* 散列存储中的项目可能会被跳过. 有关更多信息,请参阅[从哈希存储导入裸存储库](#importing-bare-repositories-from-hashed-storage) . +* 现有的 Git 存储库将从磁盘中移出(从原始路径中移出). + +要将裸仓库导入 GitLab 实例: + +1. 创建一个新文件夹以从中导入您的 Git 存储库. 新文件夹需要具有 Git 用户所有权,并且需要对 Git 用户及其组具有读/写/执行访问权限: + + ``` + sudo -u git mkdir -p /var/opt/gitlab/git-data/repository-import-/new_group + ``` + +2. 将裸存储库复制到此新创建的文件夹中. 注意: + + * 在任何子文件夹中找到的所有`.git`存储库都将作为项目导入. + * 将根据需要创建组,这些组可以是嵌套文件夹. + + 例如,如果我们将存储库复制到`/var/opt/gitlab/git-data/repository-import-` ,并且存储库`A`必须位于组`G1`和`G2` ,则必须在以下文件夹下创建它: `/var/opt/gitlab/git-data/repository-import-/G1/G2/A.git` . + + ``` + sudo cp -r /old/git/foo.git /var/opt/gitlab/git-data/repository-import-/new_group/ + + # Do this once when you are done copying git repositories + sudo chown -R git:git /var/opt/gitlab/git-data/repository-import- + ``` + + `foo.git`必须由`git`用户和`git`用户组拥有. + + 如果您使用源安装,请用`/home/git`替换`/var/opt/gitlab/` . + +3. 根据您的安装类型运行以下命令: + + * 全部安装 + + ``` + sudo gitlab-rake gitlab:import:repos['/var/opt/gitlab/git-data/repository-import-'] + ``` + + * 从源安装. 在运行此命令之前,您需要切换到 GitLab 安装所在的目录: + + ``` + cd /home/git/gitlab + sudo -u git -H bundle exec rake gitlab:import:repos['/var/opt/gitlab/git-data/repository-import-'] RAILS_ENV=production + ``` + +## Example output[](#example-output "Permalink") + +``` +Processing /var/opt/gitlab/git-data/repository-import-1/a/b/c/blah.git + * Using namespace: a/b/c + * Created blah (a/b/c/blah) + * Skipping repo /var/opt/gitlab/git-data/repository-import-1/a/b/c/blah.wiki.git +Processing /var/opt/gitlab/git-data/repository-import-1/abcd.git + * Created abcd (abcd.git) +Processing /var/opt/gitlab/git-data/repository-import-1/group/xyz.git + * Using namespace: group (2) + * Created xyz (group/xyz.git) + * Skipping repo /var/opt/gitlab/git-data/repository-import-1/@shared/a/b/abcd.git +[...] +``` + +## Importing bare repositories from hashed storage[](#importing-bare-repositories-from-hashed-storage "Permalink") + +旧版存储中的项目具有目录结构,该目录结构反映了 GitLab 中完整的项目路径,包括名称空间结构. 裸存储库导入程序将利用此信息将项目导入到正确的位置. 每个项目及其父名称空间均有意义地命名. + +但是,哈希存储中项目的目录结构不包含此信息. 由于多种原因,这是有益的,尤其是改善的性能和数据完整性. 有关更多详细信息,请参见[存储库存储类型](../administration/repository_storage_types.html) . + +可导入的存储库取决于 GitLab 的版本. + +### GitLab 10.3 or earlier[](#gitlab-103-or-earlier "Permalink") + +不支持从哈希存储导入裸存储库. + +### GitLab 10.4 and later[](#gitlab-104-and-later "Permalink") + +为了支持从哈希存储中导入裸存储库,GitLab 10.4 和更高版本将每个存储库的完整项目路径存储在 Git 存储库配置文件的特殊部分. 本节的格式如下: + +``` +[gitlab] + fullpath = gitlab-org/gitlab +``` + +但是,现有存储库并未迁移为包括此路径. + +如果 GitLab 10.4 和更高版本中的存储库发生以下事件,则裸存储库是可导入的: + +* Created +* 迁移到哈希存储 +* Renamed +* 转移到另一个名称空间 +* 祖先更名 +* 祖先转移到另一个名称空间 + +如果仓库满足以下所有条件,则裸仓库**无法**通过 GitLab 10.4 导入到 GitLab 11.6: + +* 它是在 GitLab 10.3 或更早版本中创建的. +* 它没有重命名,传输或迁移到 GitLab 10.4 的[哈希存储](../administration/repository_storage_types.html#hashed-storage)中,也没有迁移到 GitLab 11.6. +* 它的祖先名称空间未在 GitLab 10.4 中重命名或传输到 GitLab 11.6. + +[从 GitLab 11.6 开始](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41776) ,所有裸仓库都可以导入. + +要自己手动迁移存储库(对于从 GitLab 10.4 到 GitLab 11.6 的迁移),可以使用[Rails 控制台](../administration/troubleshooting/debug.html#starting-a-rails-console-session)进行. 在 Rails 控制台会话中,运行以下命令来迁移项目: + +``` +project = Project.find_by_full_path('gitlab-org/gitlab') +project.write_repository_config +``` + +在 Rails 控制台会话中,运行以下命令以迁移名称空间的所有项目(如果名称空间中有数千个项目,则可能需要一段时间): + +``` +namespace = Namespace.find_by_full_path('gitlab-org') +namespace.send(:write_projects_repository_config) +``` \ No newline at end of file diff --git a/_book/docs/517.md b/_book/docs/517.md new file mode 100644 index 0000000000000000000000000000000000000000..34c991764b103ef0007045ccf7ff8101ff763163 --- /dev/null +++ b/_book/docs/517.md @@ -0,0 +1,129 @@ +# Integrity check Rake task + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/check.html](https://docs.gitlab.com/ee/administration/raketasks/check.html) + +* [Repository integrity](#repository-integrity) + * [Check all GitLab repositories](#check-all-gitlab-repositories) +* [Uploaded files integrity](#uploaded-files-integrity) +* [LDAP check](#ldap-check) + +# Integrity check Rake task[](#integrity-check-rake-task-core-only "Permalink") + +GitLab 提供了 Rake 任务来检查各种组件的完整性. + +## Repository integrity[](#repository-integrity "Permalink") + +尽管 Git 非常灵活,并试图防止数据完整性问题,但有时还是会出错. 以下 Rake 任务旨在帮助 GitLab 管理员诊断问题存储库,以便对其进行修复. + +需要检查 3 件事以确定完整性. + +1. Git 存储库文件系统检查( [`git fsck`](https://git-scm.com/docs/git-fsck) ). 此步骤验证存储库中对象的连接性和有效性. +2. 在存储库目录中检查`config.lock` . +3. 检查`refs/heads`是否有任何分支/引用锁定文件. + +重要的是要注意,仅存在`config.lock`或引用锁并不一定表示问题. 当 Git 和 GitLab 在存储库上执行操作时,会定期创建和删除锁定文件. 它们用于防止数据完整性问题. 但是,如果 Git 操作被中断,则这些锁可能无法正确清理. + +以下症状可能表明存储库完整性有问题. 如果用户遇到这些症状,则可以使用下面介绍的 Rake 任务来确定导致问题的确切存储库. + +* 尝试推送代码时收到错误- `remote: error: cannot lock ref` +* 查看 GitLab 仪表板或访问特定项目时出现 500 错误. + +### Check all GitLab repositories[](#check-all-gitlab-repositories "Permalink") + +此任务循环遍历 GitLab 服务器上的所有存储库,并运行前面所述的完整性检查. + +**全部安装** + +``` +sudo gitlab-rake gitlab:git:fsck +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake gitlab:git:fsck RAILS_ENV=production +``` + +## Uploaded files integrity[](#uploaded-files-integrity "Permalink") + +用户可以将各种类型的文件上传到 GitLab 安装. 这些完整性检查可以检测丢失的文件. 此外,对于本地存储的文件,会在上载时生成校验和并将其存储在数据库中,这些校验将针对当前文件进行校验. + +当前,以下类型的文件支持完整性检查: + +* CI 工件(从版本 10.7.0 起可用) +* LFS 对象(从版本 10.6.0 起可用) +* 用户上传(从版本 10.6.0 起可用) + +**全部安装** + +``` +sudo gitlab-rake gitlab:artifacts:check +sudo gitlab-rake gitlab:lfs:check +sudo gitlab-rake gitlab:uploads:check +``` + +**Source Installation** + +``` +sudo -u git -H bundle exec rake gitlab:artifacts:check RAILS_ENV=production +sudo -u git -H bundle exec rake gitlab:lfs:check RAILS_ENV=production +sudo -u git -H bundle exec rake gitlab:uploads:check RAILS_ENV=production +``` + +这些任务还接受一些环境变量,可用于覆盖某些值: + +| Variable | Type | Description | +| --- | --- | --- | +| `BATCH` | integer | 指定批处理的大小. 默认为 200. | +| `ID_FROM` | integer | 指定从其开始的 ID,包括值. | +| `ID_TO` | integer | 指定以 ID 结尾的 ID 值(包括该值). | +| `VERBOSE` | boolean | 导致失败被单独列出,而不是被汇总. | + +``` +sudo gitlab-rake gitlab:artifacts:check BATCH=100 ID_FROM=50 ID_TO=250 +sudo gitlab-rake gitlab:lfs:check BATCH=100 ID_FROM=50 ID_TO=250 +sudo gitlab-rake gitlab:uploads:check BATCH=100 ID_FROM=50 ID_TO=250 +``` + +输出示例: + +``` +$ sudo gitlab-rake gitlab:uploads:check +Checking integrity of Uploads +- 1..1350: Failures: 0 +- 1351..2743: Failures: 0 +- 2745..4349: Failures: 2 +- 4357..5762: Failures: 1 +- 5764..7140: Failures: 2 +- 7142..8651: Failures: 0 +- 8653..10134: Failures: 0 +- 10135..11773: Failures: 0 +- 11777..13315: Failures: 0 +Done! +``` + +详细输出示例: + +``` +$ sudo gitlab-rake gitlab:uploads:check VERBOSE=1 +Checking integrity of Uploads +- 1..1350: Failures: 0 +- 1351..2743: Failures: 0 +- 2745..4349: Failures: 2 + - Upload: 3573: # + - Upload: 3580: # +- 4357..5762: Failures: 1 + - Upload: 4636: # +- 5764..7140: Failures: 2 + - Upload: 5812: # + - Upload: 5837: # +- 7142..8651: Failures: 0 +- 8653..10134: Failures: 0 +- 10135..11773: Failures: 0 +- 11777..13315: Failures: 0 +Done! +``` + +## LDAP check[](#ldap-check "Permalink") + +LDAP 检查 Rake 任务将测试绑定 DN 和密码凭据(如果已配置),并将列出 LDAP 用户的样本. 此任务也作为`gitlab:check`任务的一部分执行,但可以独立运行. 有关详细信息,请参见[LDAP Rake 任务-LDAP 检查](ldap.html#check) . \ No newline at end of file diff --git a/_book/docs/518.md b/_book/docs/518.md new file mode 100644 index 0000000000000000000000000000000000000000..cef49e6f0711b82fb297c2150fd4faeb2e234ee2 --- /dev/null +++ b/_book/docs/518.md @@ -0,0 +1,133 @@ +# LDAP Rake tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/ldap.html](https://docs.gitlab.com/ee/administration/raketasks/ldap.html) + +* [Check](#check) +* [Run a group sync](#run-a-group-sync-starter-only) +* [Rename a provider](#rename-a-provider) + * [Example](#example) + * [Other options](#other-options) + +# LDAP Rake tasks[](#ldap-rake-tasks-core-only "Permalink") + +以下是与 LDAP 相关的 Rake 任务. + +## Check[](#check "Permalink") + +LDAP 检查 Rake 任务将测试`bind_dn`和`password`凭据(如果已配置),并将列出 LDAP 用户的样本. 此任务也作为`gitlab:check`任务的一部分执行,但可以使用以下命令独立运行. + +**全部安装** + +``` +sudo gitlab-rake gitlab:ldap:check +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake gitlab:ldap:check RAILS_ENV=production +``` + +默认情况下,该任务将返回 100 个 LDAP 用户的样本. 通过将数字传递给检查任务来更改此限制: + +``` +rake gitlab:ldap:check[50] +``` + +## Run a group sync[](#run-a-group-sync-starter-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14735) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.2. + +The following task will run a [group sync](../auth/ldap/index.html#group-sync-starter-only) immediately. This is valuable when you’d like to update all configured group memberships against LDAP without waiting for the next scheduled group sync to be run. + +**注意:**如果您想更改执行群组同步的频率,请改为[调整 Cron 时间表](../auth/ldap/index.html#adjusting-ldap-group-sync-schedule-starter-only) . + +**全部安装** + +``` +sudo gitlab-rake gitlab:ldap:group_sync +``` + +**源安装** + +``` +bundle exec rake gitlab:ldap:group_sync +``` + +## Rename a provider[](#rename-a-provider "Permalink") + +如果您在`gitlab.yml`或`gitlab.rb`更改 LDAP 服务器 ID,则将需要更新所有用户身份,否则用户将无法登录.输入新旧提供者,此任务将更新数据库中所有匹配的身份. + +`old_provider`和`new_provider`是从前缀`ldap`加上配置文件中的 LDAP 服务器 ID 派生的. 例如,在`gitlab.yml`或`gitlab.rb`您可能会看到 LDAP 配置,如下所示: + +``` +main: + label: 'LDAP' + host: '_your_ldap_server' + port: 389 + uid: 'sAMAccountName' + ... +``` + +`main`是 LDAP 服务器 ID. 唯一的提供者在一起就是`ldapmain` . + +> **警告** :如果输入了错误的新提供程序,用户将无法登录.如果发生这种情况,请使用错误的提供程序作为`old_provider`并使用正确的提供程序作为`new_provider`再次运行任务. + +**全部安装** + +``` +sudo gitlab-rake gitlab:ldap:rename_provider[old_provider,new_provider] +``` + +**源安装** + +``` +bundle exec rake gitlab:ldap:rename_provider[old_provider,new_provider] RAILS_ENV=production +``` + +### Example[](#example "Permalink") + +考虑从默认服务器 ID `main` (完整提供程序`ldapmain` )开始. 如果将`main`更改为`mycompany` ,则`new_provider`为`ldapmycompany` . 要重命名所有用户身份,请运行以下命令: + +``` +sudo gitlab-rake gitlab:ldap:rename_provider[ldapmain,ldapmycompany] +``` + +输出示例: + +``` +100 users with provider 'ldapmain' will be updated to 'ldapmycompany'. +If the new provider is incorrect, users will be unable to sign in. +Do you want to continue (yes/no)? yes + +User identities were successfully updated +``` + +### Other options[](#other-options "Permalink") + +如果您未指定`old_provider`和`new_provider` ,则会提示您输入它们: + +**全部安装** + +``` +sudo gitlab-rake gitlab:ldap:rename_provider +``` + +**源安装** + +``` +bundle exec rake gitlab:ldap:rename_provider RAILS_ENV=production +``` + +**输出示例:** + +``` +What is the old provider? Ex. 'ldapmain': ldapmain +What is the new provider? Ex. 'ldapcustom': ldapmycompany +``` + +此任务还接受`force`环境变量,该变量将跳过确认对话框: + +``` +sudo gitlab-rake gitlab:ldap:rename_provider[old_provider,new_provider] force=yes +``` \ No newline at end of file diff --git a/_book/docs/519.md b/_book/docs/519.md new file mode 100644 index 0000000000000000000000000000000000000000..be9743f049b4b6b3dc6e54e0294e15b1bcf985f8 --- /dev/null +++ b/_book/docs/519.md @@ -0,0 +1,35 @@ +# Listing repository directories + +> 原文:[https://docs.gitlab.com/ee/raketasks/list_repos.html](https://docs.gitlab.com/ee/raketasks/list_repos.html) + +* [Limit search results](#limit-search-results) + +# Listing repository directories[](#listing-repository-directories-core-only "Permalink") + +您可以在 GitLab 管理的磁盘上打印所有 Git 存储库的列表. + +要打印列表,请运行以下命令: + +``` +# Omnibus +sudo gitlab-rake gitlab:list_repos + +# Source +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:list_repos RAILS_ENV=production +``` + +**注意:**结果使用 GitLab Rails 应用程序的默认顺序. + +## Limit search results[](#limit-search-results "Permalink") + +要仅列出具有最近活动的项目,请传递带有`SINCE`环境变量的日期. 您指定的时间由 Rails [TimeZone#parse 函数解析](https://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html#method-i-parse) . + +``` +# Omnibus +sudo gitlab-rake gitlab:list_repos SINCE='Sep 1 2015' + +# Source +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:list_repos RAILS_ENV=production SINCE='Sep 1 2015' +``` \ No newline at end of file diff --git a/_book/docs/520.md b/_book/docs/520.md new file mode 100644 index 0000000000000000000000000000000000000000..19f0b2bc6b254e2b42a024967e74f04f07c7ada2 --- /dev/null +++ b/_book/docs/520.md @@ -0,0 +1,30 @@ +# Praefect Rake tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/praefect.html](https://docs.gitlab.com/ee/administration/raketasks/praefect.html) + +* [Replica checksums](#replica-checksums) + +# Praefect Rake tasks[](#praefect-rake-tasks-core-only "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28369) . + +瑞克任务可用于在 Praefect 存储上创建的项目. 有关配置 Praefect 的信息,请参见[Praefect 文档](../gitaly/praefect.html) . + +## Replica checksums[](#replica-checksums "Permalink") + +`gitlab:praefect:replicas`打印给定`project_id`的存储库的校验和: + +* 主要的 Gitaly 节点. +* 次要内部 Gitaly 节点. + +**全部安装** + +``` +sudo gitlab-rake "gitlab:praefect:replicas[project_id]" +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake "gitlab:praefect:replicas[project_id]" RAILS_ENV=production +``` \ No newline at end of file diff --git a/_book/docs/521.md b/_book/docs/521.md new file mode 100644 index 0000000000000000000000000000000000000000..a4e07e542782c050661d7a4941bc542b6b3fa6fa --- /dev/null +++ b/_book/docs/521.md @@ -0,0 +1,56 @@ +# Project import/export administration + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/project_import_export.html](https://docs.gitlab.com/ee/administration/raketasks/project_import_export.html) + +* [Project import status](#project-import-status) +* [Import large projects](#import-large-projects) +* [Import/export tasks](#importexport-tasks) + +# Project import/export administration[](#project-importexport-administration-core-only "Permalink") + +版本历史 + +* 在 GitLab 8.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3050) . +* 从 GitLab 11.3 起,导入/导出可以自动使用对象存储. + +GitLab 提供与项目导入和导出有关的 Rake 任务. 有关更多信息,请参见: + +* [Project import/export documentation](../../user/project/settings/import_export.html). +* [Project import/export API](../../api/project_import_export.html). +* [Developer documentation: project import/export](../../development/import_export.html) + +## Project import status[](#project-import-status "Permalink") + +您可以通过[Project import / export API](../../api/project_import_export.html#import-status)查询导入. 如 API 文档中所述,查询可能返回导入错误或异常. + +## Import large projects[](#import-large-projects "Permalink") + +如果您的项目较大,请考虑使用 Rake 任务,如[开发人员文档中所述](../../development/import_project.html#importing-via-a-rake-task) . + +## Import/export tasks[](#importexport-tasks "Permalink") + +可以使用以下命令检查 GitLab 导入/导出版本: + +``` +# Omnibus installations +sudo gitlab-rake gitlab:import_export:version + +# Installations from source +bundle exec rake gitlab:import_export:version RAILS_ENV=production +``` + +可以使用以下命令列出要导出的数据库表的当前列表: + +``` +# Omnibus installations +sudo gitlab-rake gitlab:import_export:data + +# Installations from source +bundle exec rake gitlab:import_export:data RAILS_ENV=production +``` + +请注意以下几点: + +* 仅当导入和导出 GitLab 实例的[版本](../../user/project/settings/import_export.html#version-history)与[版本历史记录中](../../user/project/settings/import_export.html#version-history)描述的[版本](../../user/project/settings/import_export.html#version-history)兼容时,才可以导入. +* 必须在" **导入源"**下的应用程序设置( `/admin/application_settings/general` )中启用项目导入选项. **管理区>** **设置>可见性和访问控制** . +* 导出存储在一个临时[共享目录中](../../development/shared_files.html) ,并由特定工作人员每 24 小时删除一次. \ No newline at end of file diff --git a/_book/docs/522.md b/_book/docs/522.md new file mode 100644 index 0000000000000000000000000000000000000000..0e49312f0dc285e140ec686ef2a5883e3ad2bbf7 --- /dev/null +++ b/_book/docs/522.md @@ -0,0 +1,137 @@ +# Repository storage Rake tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/storage.html](https://docs.gitlab.com/ee/administration/raketasks/storage.html) + +* [List projects and attachments](#list-projects-and-attachments) + * [On legacy storage](#on-legacy-storage) + * [On hashed storage](#on-hashed-storage) +* [Migrate to hashed storage](#migrate-to-hashed-storage) +* [Rollback from hashed storage to legacy storage](#rollback-from-hashed-storage-to-legacy-storage) + +# Repository storage Rake tasks[](#repository-storage-rake-tasks-core-only "Permalink") + +这是 Rake 任务的集合,可帮助您列出现有项目及其附件并将其迁移到新的[哈希存储中](../repository_storage_types.html) ,GitLab 用于组织 Git 数据. + +## List projects and attachments[](#list-projects-and-attachments "Permalink") + +以下 Rake 任务将列出旧版存储和哈希存储上可用的项目和附件. + +### On legacy storage[](#on-legacy-storage "Permalink") + +要使用旧式存储获得摘要,然后列出项目及其附件: + +* **全部安装** + + ``` + # Projects + sudo gitlab-rake gitlab:storage:legacy_projects + sudo gitlab-rake gitlab:storage:list_legacy_projects + + # Attachments + sudo gitlab-rake gitlab:storage:legacy_attachments + sudo gitlab-rake gitlab:storage:list_legacy_attachments + ``` + +* **源码安装** + + ``` + # Projects + sudo -u git -H bundle exec rake gitlab:storage:legacy_projects RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:storage:list_legacy_projects RAILS_ENV=production + + # Attachments + sudo -u git -H bundle exec rake gitlab:storage:legacy_attachments RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:storage:list_legacy_attachments RAILS_ENV=production + ``` + +### On hashed storage[](#on-hashed-storage "Permalink") + +要使用散列存储来获得项目及其附件的摘要和列表,请执行以下操作: + +* **全部安装** + + ``` + # Projects + sudo gitlab-rake gitlab:storage:hashed_projects + sudo gitlab-rake gitlab:storage:list_hashed_projects + + # Attachments + sudo gitlab-rake gitlab:storage:hashed_attachments + sudo gitlab-rake gitlab:storage:list_hashed_attachments + ``` + +* **源码安装** + + ``` + # Projects + sudo -u git -H bundle exec rake gitlab:storage:hashed_projects RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:storage:list_hashed_projects RAILS_ENV=production + + # Attachments + sudo -u git -H bundle exec rake gitlab:storage:hashed_attachments RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:storage:list_hashed_attachments RAILS_ENV=production + ``` + +## Migrate to hashed storage[](#migrate-to-hashed-storage "Permalink") + +**注意:**在 GitLab 13.0 中,默认情况下启用了[哈希存储](../repository_storage_types.html#hashed-storage) ,并且不建议使用旧存储. 在 GitLab 14.0 中将删除对旧存储的支持. 如果您使用的是 GitLab 13.0 及更高版本,则无法将新项目切换到旧版存储. 在管理区域中的哈希存储和旧存储之间进行选择的选项已被禁用. + +此任务将安排您所有与之关联的现有项目和附件,以迁移到**Hashed**存储类型: + +* **全部安装** + + ``` + sudo gitlab-rake gitlab:storage:migrate_to_hashed + ``` + +* **源码安装** + + ``` + sudo -u git -H bundle exec rake gitlab:storage:migrate_to_hashed RAILS_ENV=production + ``` + +如果您有任何现有的集成,则可能需要先进行少量部署以进行验证. 您可以通过使用环境变量`ID_FROM`和`ID_TO`在操作中指定 ID 范围来`ID_TO` . 例如,要在 Omnibus GitLab 安装中将项目 ID 限制为项目 ID 50 到 100: + +``` +sudo gitlab-rake gitlab:storage:migrate_to_hashed ID_FROM=50 ID_TO=100 +``` + +您可以在 **管理区域>监视>后台作业**页面. 您可以观看一个特定的队列,以了解完成需要多长时间: `hashed_storage:hashed_storage_project_migrate` . + +达到零后,您可以通过运行以下命令确认每个项目都已迁移. 如果发现有必要,则可以再次运行此迁移脚本以计划丢失的项目. + +任何错误或警告将记录在 Sidekiq 的日志文件中. + +**注意:**如果启用了" [地理"](../geo/replication/index.html) ,则成功迁移的每个项目都会生成一个事件,以复制任何**辅助**节点上的更改. + +您只需要`gitlab:storage:migrate_to_hashed` Rake 任务即可迁移存储库,但是下面还有其他命令可帮助您检查旧版存储和哈希存储中的项目和附件. + +## Rollback from hashed storage to legacy storage[](#rollback-from-hashed-storage-to-legacy-storage "Permalink") + +**不建议使用:**在 GitLab 13.0 中,默认情况下启用了[哈希存储](../repository_storage_types.html#hashed-storage) ,并且不建议使用旧存储. 在 GitLab 14.0 中将删除对旧存储的支持. 如果您使用的是 GitLab 13.0 及更高版本,则无法将新项目切换到旧版存储. 在管理区域中的哈希存储和旧存储之间进行选择的选项已被禁用. + +This task will schedule all your existing projects and associated attachments to be rolled back to the legacy storage type. + +* **全部安装** + + ``` + sudo gitlab-rake gitlab:storage:rollback_to_legacy + ``` + +* **源码安装** + + ``` + sudo -u git -H bundle exec rake gitlab:storage:rollback_to_legacy RAILS_ENV=production + ``` + +如果您有任何现有的集成,则可能需要先进行少量回滚以进行验证. 您可以通过使用环境变量`ID_FROM`和`ID_TO`在操作中指定 ID 范围来`ID_TO` . 例如,要在 Omnibus GitLab 安装中将项目 ID 限制为项目 ID 50 到 100: + +``` +sudo gitlab-rake gitlab:storage:rollback_to_legacy ID_FROM=50 ID_TO=100 +``` + +您可以在 **管理区域>监视>后台作业**页面. 在" **队列"**选项卡上,您可以查看`hashed_storage:hashed_storage_project_rollback`队列以查看该过程将花费多长时间. + +达到零后,您可以通过以下命令确认每个项目都已回滚. 如果某些项目没有回滚,则可以再次运行此回滚脚本以安排进一步的回滚. 任何错误或警告将记录在 Sidekiq 的日志文件中. + +如果您具有地理设置,则回滚将不会自动反映在**辅助**节点上. 您可能需要等待回填操作才能启动,并手动从特殊的`@hashed/`文件夹中删除剩余的存储库. \ No newline at end of file diff --git a/_book/docs/523.md b/_book/docs/523.md new file mode 100644 index 0000000000000000000000000000000000000000..fbd0f15391b90272251765567b0a0b1e9ca491a5 --- /dev/null +++ b/_book/docs/523.md @@ -0,0 +1,28 @@ +# Generate sample Prometheus data + +> 原文:[https://docs.gitlab.com/ee/raketasks/generate_sample_prometheus_data.html](https://docs.gitlab.com/ee/raketasks/generate_sample_prometheus_data.html) + +* [Example](#example) + +# Generate sample Prometheus data[](#generate-sample-prometheus-data-core-only "Permalink") + +到现在为止,此命令将针对特定环境的每个指标运行 Prometheus 查询,时间间隔为一系列时间: + +* 30 分钟 +* 3 小时 +* 8 小时 +* 24 小时 +* 72 小时 +* 7 天 + +每个查询的结果都存储在`sample_metrics`目录下,作为一个以 metric 的`identifier`命名的 YAML 文件. 设置环境变量`USE_SAMPLE_METRICS` ,Prometheus API 查询将重新路由到`Projects::Environments::SampleMetricsController` ,如果`sample_metrics`目录中存在适当的数据集,则该`sample_metrics`会加载相应的数据集. + +此命令需要安装了 Prometheus 的环境中的 ID. + +## Example[](#example "Permalink") + +下面的示例演示如何运行 Rake 任务: + +``` +bundle exec rake gitlab:generate_sample_prometheus_data[21] +``` \ No newline at end of file diff --git a/_book/docs/524.md b/_book/docs/524.md new file mode 100644 index 0000000000000000000000000000000000000000..62a55836022e7400a644013c897ade71923f8251 --- /dev/null +++ b/_book/docs/524.md @@ -0,0 +1,152 @@ +# Uploads migrate Rake tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/uploads/migrate.html](https://docs.gitlab.com/ee/administration/raketasks/uploads/migrate.html) + +* [Migrate to object storage](#migrate-to-object-storage) + * [All-in-one Rake task](#all-in-one-rake-task) + * [Individual Rake tasks](#individual-rake-tasks) +* [Migrate to local storage](#migrate-to-local-storage) + * [All-in-one Rake task](#all-in-one-rake-task-1) + +# Uploads migrate Rake tasks[](#uploads-migrate-rake-tasks-core-only "Permalink") + +`gitlab:uploads:migrate`在不同的存储类型之间迁移上载. + +## Migrate to object storage[](#migrate-to-object-storage "Permalink") + +在为 GitLab 的上传[配置对象存储](../../uploads.html#using-object-storage-core-only)后,使用此任务将现有的上传从本地存储迁移到远程存储. + +阅读有关[在 GitLab 上](../../object_storage.html)使用[对象存储的](../../object_storage.html)更多信息. + +**注意:**所有处理将在后台工作人员中完成, **无需停机** . + +### All-in-one Rake task[](#all-in-one-rake-task "Permalink") + +GitLab 提供了一个包装 Rake 任务,可将所有上载的文件(例如,头像,徽标,附件和网站图标)迁移到对象存储中. 包装器任务调用各个 Rake 任务来逐一迁移属于这些类别的文件. + +这些[单独的 Rake 任务](#individual-rake-tasks)将在下一部分中介绍. + +要将所有上载从本地存储迁移到对象存储,请运行: + +**全部安装** + +``` +gitlab-rake "gitlab:uploads:migrate:all" +``` + +**源安装** + +``` +sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:migrate:all +``` + +### Individual Rake tasks[](#individual-rake-tasks "Permalink") + +如果您已经运行了[多合一 Rake 任务](#all-in-one-rake-task) ,则无需运行这些单独的任务. + +Rake 任务使用三个参数来查找要迁移的上载: + +| Parameter | Type | Description | +| --- | --- | --- | +| `uploader_class` | string | 要从中迁移的上传者的类型. | +| `model_class` | string | 要迁移的模型的类型. | +| `mount_point` | string/symbol | 上传器安装在其上的模型列的名称. | + +**注意:**这些参数主要是在 GitLab 结构的内部,您可能想参考下面的任务列表. + +此任务还接受一个环境变量,您可以使用它来覆盖默认的批处理大小: + +| Variable | Type | Description | +| --- | --- | --- | +| `BATCH` | integer | 指定批处理的大小. 默认为 200. | + +下面显示了如何针对各种类型的上传运行`gitlab:uploads:migrate` . + +**全部安装** + +``` +# gitlab-rake gitlab:uploads:migrate[uploader_class, model_class, mount_point] + +# Avatars +gitlab-rake "gitlab:uploads:migrate[AvatarUploader, Project, :avatar]" +gitlab-rake "gitlab:uploads:migrate[AvatarUploader, Group, :avatar]" +gitlab-rake "gitlab:uploads:migrate[AvatarUploader, User, :avatar]" + +# Attachments +gitlab-rake "gitlab:uploads:migrate[AttachmentUploader, Note, :attachment]" +gitlab-rake "gitlab:uploads:migrate[AttachmentUploader, Appearance, :logo]" +gitlab-rake "gitlab:uploads:migrate[AttachmentUploader, Appearance, :header_logo]" + +# Favicon +gitlab-rake "gitlab:uploads:migrate[FaviconUploader, Appearance, :favicon]" + +# Markdown +gitlab-rake "gitlab:uploads:migrate[FileUploader, Project]" +gitlab-rake "gitlab:uploads:migrate[PersonalFileUploader, Snippet]" +gitlab-rake "gitlab:uploads:migrate[NamespaceFileUploader, Snippet]" +gitlab-rake "gitlab:uploads:migrate[FileUploader, MergeRequest]" + +# Design Management design thumbnails +gitlab-rake "gitlab:uploads:migrate[DesignManagement::DesignV432x230Uploader, DesignManagement::Action, :image_v432x230]" +``` + +**源安装** + +**注意:**为每个任务使用`RAILS_ENV=production` . + +``` +# sudo -u git -H bundle exec rake gitlab:uploads:migrate + +# Avatars +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AvatarUploader, Project, :avatar]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AvatarUploader, Group, :avatar]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AvatarUploader, User, :avatar]" + +# Attachments +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AttachmentUploader, Note, :attachment]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AttachmentUploader, Appearance, :logo]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AttachmentUploader, Appearance, :header_logo]" + +# Favicon +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[FaviconUploader, Appearance, :favicon]" + +# Markdown +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[FileUploader, Project]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[PersonalFileUploader, Snippet]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[NamespaceFileUploader, Snippet]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[FileUploader, MergeRequest]" + +# Design Management design thumbnails +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[DesignManagement::DesignV432x230Uploader, DesignManagement::Action]" +``` + +## Migrate to local storage[](#migrate-to-local-storage "Permalink") + +如果出于任何原因需要禁用[对象存储](../../object_storage.html) ,则必须首先将数据从对象存储中迁移出来,然后再迁移回本地存储中. + +**Warning:** **需要延长停机时间** so no new files are created in object storage during the migration. A configuration setting will be added soon to allow migrating from object storage to local files with only a brief moment of downtime for configuration changes. To follow progress, see the [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/30979). + +### All-in-one Rake task[](#all-in-one-rake-task-1 "Permalink") + +GitLab 提供了一个包装 Rake 任务,可将所有上载的文件(例如,头像,徽标,附件和网站图标)迁移到本地存储中. 包装器任务调用各个 Rake 任务来逐一迁移属于这些类别的文件. + +有关这些 Rake 任务的详细信息,请参阅" [个人 Rake 任务"](#individual-rake-tasks) ,请记住,在这种情况下,任务名称为`gitlab:uploads:migrate_to_local` . + +要将上传从对象存储迁移到本地存储: + +1. 同时禁用`direct_upload`和`background_upload`下`uploads`的设置`gitlab.rb` . +2. 运行 Rake 任务: + + **全部安装** + + ``` + gitlab-rake "gitlab:uploads:migrate_to_local:all" + ``` + + **源安装** + + ``` + sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:migrate_to_local:all + ``` + +运行 Rake 任务后,您可以通过撤消[配置对象存储](../../uploads.html#using-object-storage-core-only)的说明中所述的更改来禁用[对象存储](../../uploads.html#using-object-storage-core-only) . \ No newline at end of file diff --git a/_book/docs/525.md b/_book/docs/525.md new file mode 100644 index 0000000000000000000000000000000000000000..d02172184da6fbfc3a239aead033f427ba92f762 --- /dev/null +++ b/_book/docs/525.md @@ -0,0 +1,71 @@ +# Uploads sanitize Rake tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/uploads/sanitize.html](https://docs.gitlab.com/ee/administration/raketasks/uploads/sanitize.html) + +* [Requirements](#requirements) +* [Remove EXIF data from existing uploads](#remove-exif-data-from-existing-uploads) + +# Uploads sanitize Rake tasks[](#uploads-sanitize-rake-tasks-core-only "Permalink") + +从 GitLab 11.9 开始,EXIF 数据会自动从 JPG 或 TIFF 图像上传中删除. + +EXIF 数据可能包含敏感信息(例如 GPS 位置),因此您可以从上传到 GitLab 早期版本的现有图像中删除 EXIF 数据. + +## Requirements[](#requirements "Permalink") + +要运行此 Rake 任务,需要在系统上安装`exiftool` . 如果安装了 GitLab: + +* 使用 Omnibus 软件包,您已经准备就绪. +* 从源代码中,确保已安装`exiftool` : + + ``` + # Debian/Ubuntu + sudo apt-get install libimage-exiftool-perl + + # RHEL/CentOS + sudo yum install perl-Image-ExifTool + ``` + +## Remove EXIF data from existing uploads[](#remove-exif-data-from-existing-uploads "Permalink") + +要从现有的上载中删除 EXIF 数据,请运行以下命令: + +``` +sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:sanitize:remove_exif +``` + +默认情况下,此命令以"空运行"模式运行,并且不会删除 EXIF 数据. 它可用于检查是否应清理图像(以及多少). + +Rake 任务接受以下参数. + +| Parameter | Type | Description | +| --- | --- | --- | +| `start_id` | integer | 仅处理 ID 相同或更大的上载 | +| `stop_id` | integer | 仅处理 ID 等于或小于 ID 的上传 | +| `dry_run` | boolean | 不要删除 EXIF 数据,仅检查是否存在 EXIF 数据. 默认为`true` | +| `sleep_time` | float | 处理每个图像后暂停几秒钟. 默认为 0.3 秒 | +| `uploader` | string | 仅对给定上传者的上传运行清理: `FileUploader` , `PersonalFileUploader`或`NamespaceFileUploader` | +| `since` | date | 仅对早于给定日期的上传文件进行清理. 例如`2019-05-01` | + +如果上传的文件过多,则可以通过以下方法加快清理速度: + +* 将`sleep_time`设置为较低的值. +* 并行运行多个 Rake 任务,每个任务都有单独的上传 ID 范围(通过设置`start_id`和`stop_id` ). + +要从所有上传中删除 EXIF 数据,请使用: + +``` +sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:sanitize:remove_exif[,,false,] 2>&1 | tee exif.log +``` + +To remove EXIF data on uploads with an ID between 100 and 5000 and pause for 0.1 second after each file, use: + +``` +sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:sanitize:remove_exif[100,5000,false,0.1] 2>&1 | tee exif.log +``` + +输出将被写入`exif.log`文件,因为它可能很长. + +如果上载的清理失败,则 Rake 任务的输出中将出现一条错误消息. 典型的原因包括文件在存储中丢失或不是有效的映像. + +[报告](https://gitlab.com/gitlab-org/gitlab/-/issues/new)所有问题,并在问题标题中使用前缀" EXIF",以及错误输出和(如果可能)图像. \ No newline at end of file diff --git a/_book/docs/526.md b/_book/docs/526.md new file mode 100644 index 0000000000000000000000000000000000000000..1be56ffc463ba57347a734347f1e27a6818f61aa --- /dev/null +++ b/_book/docs/526.md @@ -0,0 +1,156 @@ +# User management + +> 原文:[https://docs.gitlab.com/ee/raketasks/user_management.html](https://docs.gitlab.com/ee/raketasks/user_management.html) + +* [Add user as a developer to all projects](#add-user-as-a-developer-to-all-projects) +* [Add all users to all projects](#add-all-users-to-all-projects) +* [Add user as a developer to all groups](#add-user-as-a-developer-to-all-groups) +* [Add all users to all groups](#add-all-users-to-all-groups) +* [Control the number of active users](#control-the-number-of-active-users) +* [Disable two-factor authentication for all users](#disable-two-factor-authentication-for-all-users) +* [Rotate two-factor authentication encryption key](#rotate-two-factor-authentication-encryption-key) + +# User management[](#user-management-core-only "Permalink") + +GitLab 提供 Rake 任务用于用户管理. + +## Add user as a developer to all projects[](#add-user-as-a-developer-to-all-projects "Permalink") + +要将用户作为开发人员添加到所有项目中,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:import:user_to_projects[username@domain.tld] + +# installation from source +bundle exec rake gitlab:import:user_to_projects[username@domain.tld] RAILS_ENV=production +``` + +## Add all users to all projects[](#add-all-users-to-all-projects "Permalink") + +要将所有用户添加到所有项目,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:import:all_users_to_all_projects + +# installation from source +bundle exec rake gitlab:import:all_users_to_all_projects RAILS_ENV=production +``` + +**注意:**管理员用户被添加为维护者. + +## Add user as a developer to all groups[](#add-user-as-a-developer-to-all-groups "Permalink") + +要将用户作为开发人员添加到所有组,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:import:user_to_groups[username@domain.tld] + +# installation from source +bundle exec rake gitlab:import:user_to_groups[username@domain.tld] RAILS_ENV=production +``` + +## Add all users to all groups[](#add-all-users-to-all-groups "Permalink") + +要将所有用户添加到所有组,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:import:all_users_to_all_groups + +# installation from source +bundle exec rake gitlab:import:all_users_to_all_groups RAILS_ENV=production +``` + +**注意:**管理员用户被添加为所有者,因此他们可以将其他用户添加到组中. + +## Control the number of active users[](#control-the-number-of-active-users "Permalink") + +启用此设置可以阻止新用户被阻止,直到管理员将其清除为止. 默认为`false` : + +``` +block_auto_created_users: false +``` + +## Disable two-factor authentication for all users[](#disable-two-factor-authentication-for-all-users "Permalink") + +此任务为所有启用了双重身份验证的用户禁用两因素身份验证(2FA). 例如,如果 GitLab 的`config/secrets.yml`文件丢失并且用户无法登录,这将很有用. + +要为所有用户禁用双重身份验证,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:two_factor:disable_for_all_users + +# installation from source +bundle exec rake gitlab:two_factor:disable_for_all_users RAILS_ENV=production +``` + +## Rotate two-factor authentication encryption key[](#rotate-two-factor-authentication-encryption-key "Permalink") + +GitLab 将两因素身份验证(2FA)所需的机密数据存储在加密的数据库列中. 此数据的加密密钥称为`otp_key_base` ,存储在`config/secrets.yml` . + +如果该文件泄漏了,但单个 2FA 机密没有泄漏,则可以使用新的加密密钥重新加密这些机密. 这使您可以更改泄漏的密钥,而不必强制所有用户更改其 2FA 详细信息. + +旋转两因素身份验证加密密钥: + +1. 查找旧密钥. 该文件位于`config/secrets.yml`文件中,但请**确保您正在使用 Production 部分** . 您感兴趣的行将如下所示: + + ``` + production: + otp_key_base: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + ``` + +2. 生成一个新的秘密: + + ``` + # omnibus-gitlab + sudo gitlab-rake secret + + # installation from source + bundle exec rake secret RAILS_ENV=production + ``` + +3. 停止 GitLab 服务器,备份现有的机密文件,然后更新数据库: + + ``` + # omnibus-gitlab + sudo gitlab-ctl stop + sudo cp config/secrets.yml config/secrets.yml.bak + sudo gitlab-rake gitlab:two_factor:rotate_key:apply filename=backup.csv old_key= new_key= + + # installation from source + sudo /etc/init.d/gitlab stop + cp config/secrets.yml config/secrets.yml.bak + bundle exec rake gitlab:two_factor:rotate_key:apply filename=backup.csv old_key= new_key= RAILS_ENV=production + ``` + + 可以从`config/secrets.yml`读取``值( ``是先前生成的). 用户 2FA 机密的**加密**值将被写入指定的`filename` . 如果发生错误,可以使用它进行回滚. + +4. 更改`config/secrets.yml` `otp_key_base`以将`otp_key_base`设置为``并重新启动. 同样,请确保您在**生产**部分中进行操作. + + ``` + # omnibus-gitlab + sudo gitlab-ctl start + + # installation from source + sudo /etc/init.d/gitlab start + ``` + +如果有任何问题(也许为`old_key`使用了错误的值),则可以还原`config/secrets.yml` `old_key`的备份并回滚更改: + +``` +# omnibus-gitlab +sudo gitlab-ctl stop +sudo gitlab-rake gitlab:two_factor:rotate_key:rollback filename=backup.csv +sudo cp config/secrets.yml.bak config/secrets.yml +sudo gitlab-ctl start + +# installation from source +sudo /etc/init.d/gitlab start +bundle exec rake gitlab:two_factor:rotate_key:rollback filename=backup.csv RAILS_ENV=production +cp config/secrets.yml.bak config/secrets.yml +sudo /etc/init.d/gitlab start +``` \ No newline at end of file diff --git a/_book/docs/527.md b/_book/docs/527.md new file mode 100644 index 0000000000000000000000000000000000000000..2a8122f5a3d09ed4b00d7ccd4aad6f5cb450db65 --- /dev/null +++ b/_book/docs/527.md @@ -0,0 +1,88 @@ +# Webhooks administration + +> 原文:[https://docs.gitlab.com/ee/raketasks/web_hooks.html](https://docs.gitlab.com/ee/raketasks/web_hooks.html) + +* [Add a webhook to all projects](#add-a-webhook-to-all-projects) +* [Add a webhook to projects in a namespace](#add-a-webhook-to-projects-in-a-namespace) +* [Remove a webhook from projects](#remove-a-webhook-from-projects) +* [Remove a webhook from projects in a namespace](#remove-a-webhook-from-projects-in-a-namespace) +* [List all webhooks](#list-all-webhooks) +* [List webhooks for projects in a namespace](#list-webhooks-for-projects-in-a-namespace) + +# Webhooks administration[](#webhooks-administration-core-only "Permalink") + +GitLab 提供用于 Webhooks 管理的 Rake 任务. + +[管理员](../security/webhooks.html)可以允许或阻止通过[Webhook](../security/webhooks.html)向[本地网络发出的](../security/webhooks.html)请求. + +## Add a webhook to all projects[](#add-a-webhook-to-all-projects "Permalink") + +要将 webhook 添加到所有项目,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:web_hook:add URL="http://example.com/hook" + +# source installations +bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" RAILS_ENV=production +``` + +## Add a webhook to projects in a namespace[](#add-a-webhook-to-projects-in-a-namespace "Permalink") + +要将 Webhook 添加到特定名称空间中的所有项目,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:web_hook:add URL="http://example.com/hook" NAMESPACE= + +# source installations +bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" NAMESPACE= RAILS_ENV=production +``` + +## Remove a webhook from projects[](#remove-a-webhook-from-projects "Permalink") + +要从所有项目中删除 Webhook,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:web_hook:rm URL="http://example.com/hook" + +# source installations +bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" RAILS_ENV=production +``` + +## Remove a webhook from projects in a namespace[](#remove-a-webhook-from-projects-in-a-namespace "Permalink") + +要从特定名称空间的项目中删除 Webhook,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE= + +# source installations +bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE= RAILS_ENV=production +``` + +## List all webhooks[](#list-all-webhooks "Permalink") + +要列出所有 webhooks,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:web_hook:list + +# source installations +bundle exec rake gitlab:web_hook:list RAILS_ENV=production +``` + +## List webhooks for projects in a namespace[](#list-webhooks-for-projects-in-a-namespace "Permalink") + +要列出指定名称空间中项目的所有 webhook,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:web_hook:list NAMESPACE= + +# source installations +bundle exec rake gitlab:web_hook:list NAMESPACE= RAILS_ENV=production +``` \ No newline at end of file diff --git a/_book/docs/528.md b/_book/docs/528.md new file mode 100644 index 0000000000000000000000000000000000000000..ff6ae73b3ccdf24048078e1971bd6e056cff2dd4 --- /dev/null +++ b/_book/docs/528.md @@ -0,0 +1,29 @@ +# X.509 signatures + +> 原文:[https://docs.gitlab.com/ee/raketasks/x509_signatures.html](https://docs.gitlab.com/ee/raketasks/x509_signatures.html) + +* [Update all X.509 signatures](#update-all-x509-signatures) + +# X.509 signatures[](#x509-signatures-core-only "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/122159) . + +[使用 X.509](../user/project/repository/x509_signed_commits/index.html)对[提交进行签名时](../user/project/repository/x509_signed_commits/index.html) ,信任锚可能会更改,并且必须更新数据库中存储的签名. + +## Update all X.509 signatures[](#update-all-x509-signatures "Permalink") + +此任务遍历所有 X.509 签名的提交,并根据当前证书存储更新其验证. + +要更新所有 X.509 签名,请运行: + +**所有安装:** + +``` +sudo gitlab-rake gitlab:x509:update_signatures +``` + +**源安装:** + +``` +sudo -u git -H bundle exec rake gitlab:x509:update_signatures RAILS_ENV=production +``` \ No newline at end of file diff --git a/_book/docs/529.md b/_book/docs/529.md new file mode 100644 index 0000000000000000000000000000000000000000..6d3c3f078f58520beadee5d8fca9585e69d5c5d5 --- /dev/null +++ b/_book/docs/529.md @@ -0,0 +1,161 @@ +# Server hooks + +> 原文:[https://docs.gitlab.com/ee/administration/server_hooks.html](https://docs.gitlab.com/ee/administration/server_hooks.html) + +* [Create a server hook for a repository](#create-a-server-hook-for-a-repository) +* [Create a global server hook for all repositories](#create-a-global-server-hook-for-all-repositories) +* [Chained hooks](#chained-hooks) +* [Environment Variables](#environment-variables) +* [Transition to Go](#transition-to-go) +* [Custom error messages](#custom-error-messages) + * [Example custom error message](#example-custom-error-message) + +# Server hooks[](#server-hooks-core-only "Permalink") + +在 GitLab 12.8 中[引入,](https://gitlab.com/gitlab-org/gitlab/-/issues/196051)以取代"自定义挂钩". + +Git 支持在不同动作上执行的钩子. 这些挂钩在服务器上运行,可用于执行特定的提交策略或基于存储库的状态执行其他任务. + +Git 支持以下钩子: + +* `pre-receive` +* `post-receive` +* `update` + +有关每种钩子类型的更多信息,请参见[Git 文档](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#_server_side_hooks) . + +服务器端 Git 挂钩可以配置为: + +* [A single repository](#create-a-server-hook-for-a-repository). +* [All repositories](#create-a-global-server-hook-for-all-repositories). + +Note the following about server hooks: + +* 必须在 GitLab 服务器的文件系统上配置服务器挂钩. 只有 GitLab 服务器管理员才能完成这些任务. 如果您没有文件系统访问权限,请参见以下替代方法: + * [Webhooks](../user/project/integrations/webhooks.html) . + * [亚搏体育 app CI / CD](../ci/README.html) . + * [推送规则](../push_rules/push_rules.html) ,用于用户可配置的 Git 挂钩界面. +* 服务器挂钩不会复制到[Geo](geo/replication/index.html)辅助节点. + +## Create a server hook for a repository[](#create-a-server-hook-for-a-repository "Permalink") + +如果您不使用[哈希存储](repository_storage_types.html#hashed-storage) ,则项目的存储库目录可能与以下说明不完全匹配. 在这种情况下: + +* 对于从源进行的安装,路径通常是`/home/git/repositories//.git` . +* 对于 Omnibus GitLab 安装,路径通常为`/var/opt/gitlab/git-data/repositories//.git` . + +请按照以下步骤为存储库设置服务器端挂钩: + +1. 导航到" **管理"区域>"项目"** ,然后单击要向其添加服务器挂钩的项目. +2. 在出现的页面上找到**Gitaly 相对路径** . 这是必须实现服务器挂钩的地方. 有关解释相对路径的信息,请参阅[翻译哈希存储路径](repository_storage_types.html#translating-hashed-storage-paths) . +3. 在文件系统上,在此位置创建一个名为`custom_hooks`的新目录. +4. 在新的`custom_hooks`目录中,创建一个名称与钩子类型匹配的文件. 例如,对于预接收钩子,文件名应该是`pre-receive` ,没有扩展名. +5. 使挂钩文件可执行,并确保它由 Git 用户拥有. +6. 编写代码以使服务器挂钩功能按预期方式运行. 挂钩可以使用任何语言. 确保顶部的[" shebang"](https://en.wikipedia.org/wiki/Shebang_(Unix))正确反映语言类型. 例如,如果脚本在 Ruby 中,则 shebang 可能是`#!/usr/bin/env ruby` . + +假设正确执行了挂钩代码,则将适当地执行挂钩代码. + +## Create a global server hook for all repositories[](#create-a-global-server-hook-for-all-repositories "Permalink") + +要创建适用于您实例中所有存储库的 Git 挂钩,请设置一个全局服务器挂钩. 默认的全局服务器挂钩目录位于 GitLab Shell 目录中. 在那里添加的任何钩子都适用于所有存储库. + +默认目录: + +* 对于从源代码进行的安装,通常是`/home/git/gitlab-shell/hooks` . +* 对于 Omnibus GitLab,安装通常是`/opt/gitlab/embedded/service/gitlab-shell/hooks` . + +要将其他目录用于全局服务器挂钩, `custom_hooks_dir`在 Gitaly 配置中设置`custom_hooks_dir` : + +* 对于 Omnibus 安装,此设置在`gitlab.rb` . +* 对于源代码安装,配置位置取决于 GitLab 版本. 对于: + * GitLab 13.0 及更早版本,在`gitlab-shell/config.yml` . + * GitLab 13.1 及更高版本,在`[hooks]`部分的`gitaly/config.toml`进行设置. + +**注意:** `gitlab-shell/config.yml`的`custom_hooks_dir`值在 GitLab 13.1 和更高版本中仍然被接受,如果`gitaly/config.toml`的值是空白或不存在. + +请按照以下步骤为所有存储库设置全局服务器挂钩: + +1. 在 GitLab 服务器上,导航到配置的全局服务器挂钩目录. +2. 在此位置创建一个新目录. 根据挂钩的类型,它可以是`pre-receive.d` , `post-receive.d`或`update.d`目录. +3. 在这个新目录中,添加您的钩子. 挂钩可以使用任何语言. 确保顶部的[" shebang"](https://en.wikipedia.org/wiki/Shebang_(Unix))正确反映语言类型. 例如,如果脚本在 Ruby 中,则 shebang 可能是`#!/usr/bin/env ruby` . +4. 使挂钩文件可执行,并确保它由 Git 用户拥有. + +现在,测试挂钩以检查其是否正常运行. + +## Chained hooks[](#chained-hooks "Permalink") + +在 GitLab Shell 4.1.0 和 GitLab 8.15 中[引入](https://gitlab.com/gitlab-org/gitlab-shell/-/merge_requests/93) . + +可以按链执行[每个项目](#create-a-server-hook-for-a-repository)或[全局](#create-a-global-server-hook-for-all-repositories)设置的服务器挂钩. + +搜索服务器挂钩并按以下优先级顺序执行: + +* 内置的 GitLab 服务器挂钩. 这些不是用户可定制的. +* `.git/custom_hooks/` :每个项目的挂钩. 保留它是为了向后兼容. +* `.git/custom_hooks/.d/*` :每个项目挂钩的位置. +* `/.d/*` :除编辑器备份文件之外的所有可执行全局挂钩文件的位置. + +在目录中,服务器挂钩: + +* 按字母顺序执行. +* 当钩子以非零值退出时,停止执行. + +Note: + +* `.d`必须为`pre-receive.d` , `post-receive.d`或`update.d`才能正常工作. 其他任何名称都将被忽略. +* `.d`目录中的文件必须是可执行文件,并且与备份文件模式( `*~` )不匹配. +* 对于`.git` ,你需要[翻译](repository_storage_types.html#translating-hashed-storage-paths)你的项目名称为散列存储格式 GitLab 用途. + +## Environment Variables[](#environment-variables "Permalink") + +以下环境变量集可用于服务器挂钩. + +| 环境变量 | Description | +| --- | --- | +| `GL_ID` | 启动推送的用户的 GitLab 标识符. 例如, `user-2234` | +| `GL_PROJECT_PATH` | (GitLab 13.2 和更高版本)GitLab 项目路径 | +| `GL_PROTOCOL` | (GitLab 13.2 和更高版本)与 push 一起使用的协议 | +| `GL_REPOSITORY` | `project-` ,其中`id`是项目的 ID | +| `GL_USERNAME` | 启动推送的用户的 GitLab 用户名 | + +接收前和接收后服务器挂钩也可以访问以下 Git 环境变量. + +| 环境变量 | Description | +| --- | --- | +| `GIT_ALTERNATE_OBJECT_DIRECTORIES` | 隔离环境中的备用对象目录. 请参阅[Git `receive-pack`文档](https://git-scm.com/docs/git-receive-pack#_quarantine_environment) . | +| `GIT_OBJECT_DIRECTORY` | GitLab project path in the quarantine environment. See [Git `receive-pack` documentation](https://git-scm.com/docs/git-receive-pack#_quarantine_environment). | +| `GIT_PUSH_OPTION_COUNT` | 推送选项的数量. 请参阅[Git `pre-receive`文档](https://git-scm.com/docs/githooks#pre-receive) . | +| `GIT_PUSH_OPTION_` | `i`从`0`到`GIT_PUSH_OPTION_COUNT - 1`的推送选项的值. 请参阅[Git `pre-receive`文档](https://git-scm.com/docs/githooks#pre-receive) . | + +**注意:**虽然其他环境变量可以传递给服务器挂钩,但是您的应用程序不应依赖它们,因为它们可以更改. + +## Transition to Go[](#transition-to-go "Permalink") + +在 GitLab 13.2 中使用功能标记引入. + +以下服务器挂钩已在 Go 中重新实现: + +* `pre-receive` ,默认情况下使用 Go 实现. 要改用 Ruby 实现,请[禁用](../operations/feature_flags.html#enable-or-disable-feature-flag-strategies) `:gitaly_go_preceive_hook`功能标记. +* `update` ,默认使用 Go 实现. 要改用 Ruby 实现,请[禁用](../operations/feature_flags.html#enable-or-disable-feature-flag-strategies) `:gitaly_go_update_hook`功能标志. +* `post-receive` ,但是默认情况下使用 Ruby 实现. 要改用 Go 实现,请[启用](../operations/feature_flags.html#enable-or-disable-feature-flag-strategies) `:gitaly_go_postreceive_hook`功能标志. + +## Custom error messages[](#custom-error-messages "Permalink") + +在 GitLab 8.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5073) . + +要在拒绝提交或在 Git 挂钩期间发生错误时在 GitLab 的 UI 中显示自定义错误消息,您的脚本应: + +* 将自定义错误消息发送到脚本的`stdout`或`stderr` . +* 给每条消息加上`GL-HOOK-ERR:`前缀,前缀前没有字符. + +### Example custom error message[](#example-custom-error-message "Permalink") + +用 Bash 编写的该钩子脚本在 GitLab 的 UI 中生成以下消息: + +``` +#!/bin/sh +echo "GL-HOOK-ERR: My custom error message."; +exit 1 +``` + +[![Custom message from custom Git hook](img/4d9fbb6b23cf91f72dd201cf3a52f475.png)](img/custom_hooks_error_msg.png) \ No newline at end of file diff --git a/_book/docs/530.md b/_book/docs/530.md new file mode 100644 index 0000000000000000000000000000000000000000..367c7d4a695611a8d3c42d8a801a684bdf88e91b --- /dev/null +++ b/_book/docs/530.md @@ -0,0 +1,203 @@ +# Static objects external storage + +> 原文:[https://docs.gitlab.com/ee/administration/static_objects_external_storage.html](https://docs.gitlab.com/ee/administration/static_objects_external_storage.html) + +* [Configuring](#configuring) +* [Serving private static objects](#serving-private-static-objects) +* [Requests flow example](#requests-flow-example) +* [Set up external storage](#set-up-external-storage) + +# Static objects external storage[](#static-objects-external-storage "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31025) . + +可以将 GitLab 配置为从外部存储(例如内容交付网络(CDN))为存储库静态对象(例如,存档或原始 Blob)提供服务. + +## Configuring[](#configuring "Permalink") + +要为静态对象配置外部存储,请执行以下操作: + +1. 导航到" **管理区域">"设置">"存储库"** . +2. 展开" **存储库静态对象"**部分. +3. 输入基本 URL 和任意令牌. [设置外部存储时](#set-up-external-storage) ,您将使用一个脚本,将这些值用作`ORIGIN_HOSTNAME`和`STORAGE_TOKEN` . + +需要使用令牌来区分来自外部存储的请求,因此用户无需绕过外部存储就可以直接前往应用程序. 令牌应在来自外部存储的请求中的`X-Gitlab-External-Storage-Token`标头中设置. + +## Serving private static objects[](#serving-private-static-objects "Permalink") + +GitLab 将为属于私有项目的静态对象 URL 附加一个用户特定的令牌,因此可以代表用户对外部存储进行身份验证. 当处理来自外部存储的请求时,GitLab 将在`token`查询参数或`X-Gitlab-Static-Object-Token`标头中查找`X-Gitlab-Static-Object-Token`以检查用户访问所请求对象的能力. + +## Requests flow example[](#requests-flow-example "Permalink") + +以下示例显示了用户,GitLab 和 CDN 之间的一系列请求和响应: + +sequenceDiagram User->> GitLab:GET /project/-/archive/master.zip GitLab->>用户:302 找到有关 User,GitLab 的注释:位置:https://cdn.com/project/-/archive/master. zip?token =安全用户令牌用户->> CDN:GET /project/-/archive/master.zip?token=安全用户令牌替代对象不在缓存 CDN->> GitLab:GET / project /- /archive/master.zip 关于 CDN,GitLab 的说明:X-Gitlab-External-Storage-Token:secure-cdn-token +X-Gitlab-Static-Object-Token:安全用户令牌 GitLab->> CDN:200 OK CDN->>用户:master.zip 其他对象在缓存 CDN->> GitLab:GET / project /-/ a​​rchive / master.zip 关于 CDN,GitLab 的说明:X-Gitlab-External-Storage-Token:secure-cdn-token +X-Gitlab-Static-Object-Token:安全用户令牌 +如果不匹配:etag 值 GitLab->> CDN:304 未修改 CDN->>用户:master.zip 结束 + +## Set up external storage[](#set-up-external-storage "Permalink") + +尽管此过程使用[CloudFlare Workers](https://workers.cloudflare.com)进行外部存储,但其他 CDN 或功能即服务(FaaS)系统应使用相同的原理工作. + +1. 如果还没有,请选择一个 CloudFlare Worker 域. +2. 在以下脚本中,为前两个常量设置以下值: + + * `ORIGIN_HOSTNAME` :GitLab 安装的主机名. + * `STORAGE_TOKEN` :任何任意的安全令牌(例如,您可以通过在 UNIX 计算机上运行`pwgen -cn1 64`来获得一个). 按照[配置](#configuring)部分中的说明将此令牌保存到管理面板. + + ``` + const ORIGIN_HOSTNAME = 'gitlab.installation.com' // FIXME: SET CORRECT VALUE + const STORAGE_TOKEN = 'very-secure-token' // FIXME: SET CORRECT VALUE + const CACHE_PRIVATE_OBJECTS = false + + const CORS_HEADERS = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS', + 'Access-Control-Allow-Headers': 'X-Csrf-Token, X-Requested-With', + } + + self.addEventListener('fetch', event => event.respondWith(handle(event))) + + async function handle(event) { + try { + let response = await verifyAndHandle(event); + + // responses returned from cache are immutable, so we recreate them + // to set CORS headers + response = new Response(response.body, response) + response.headers.set('Access-Control-Allow-Origin', '*') + + return response + } catch (e) { + return new Response('An error occurred!', {status: e.statusCode || 500}) + } + } + + async function verifyAndHandle(event) { + if (!validRequest(event.request)) { + return new Response(null, {status: 400}) + } + + if (event.request.method === 'OPTIONS') { + return handleOptions(event.request) + } + + return handleRequest(event) + } + + function handleOptions(request) { + // Make sure the necessary headers are present + // for this to be a valid pre-flight request + if ( + request.headers.get('Origin') !== null && + request.headers.get('Access-Control-Request-Method') !== null && + request.headers.get('Access-Control-Request-Headers') !== null + ) { + // Handle CORS pre-flight request + return new Response(null, { + headers: CORS_HEADERS, + }) + } else { + // Handle standard OPTIONS request + return new Response(null, { + headers: { + Allow: 'GET, HEAD, OPTIONS', + }, + }) + } + } + + async function handleRequest(event) { + let cache = caches.default + let url = new URL(event.request.url) + let static_object_token = url.searchParams.get('token') + let headers = new Headers(event.request.headers) + + url.host = ORIGIN_HOSTNAME + url = normalizeQuery(url) + + headers.set('X-Gitlab-External-Storage-Token', STORAGE_TOKEN) + if (static_object_token !== null) { + headers.set('X-Gitlab-Static-Object-Token', static_object_token) + } + + let request = new Request(url, { headers: headers }) + let cached_response = await cache.match(request) + let is_conditional_header_set = headers.has('If-None-Match') + + if (cached_response) { + return cached_response + } + + // We don't want to override If-None-Match that is set on the original request + if (cached_response && !is_conditional_header_set) { + headers.set('If-None-Match', cached_response.headers.get('ETag')) + } + + let response = await fetch(request, { + headers: headers, + redirect: 'manual' + }) + + if (response.status == 304) { + if (is_conditional_header_set) { + return response + } else { + return cached_response + } + } else if (response.ok) { + response = new Response(response.body, response) + + // cache.put will never cache any response with a Set-Cookie header + response.headers.delete('Set-Cookie') + + if (CACHE_PRIVATE_OBJECTS) { + response.headers.delete('Cache-Control') + } + + event.waitUntil(cache.put(request, response.clone())) + } + + return response + } + + function normalizeQuery(url) { + let searchParams = url.searchParams + url = new URL(url.toString().split('?')[0]) + + if (url.pathname.includes('/raw/')) { + let inline = searchParams.get('inline') + + if (inline == 'false' || inline == 'true') { + url.searchParams.set('inline', inline) + } + } else if (url.pathname.includes('/-/archive/')) { + let append_sha = searchParams.get('append_sha') + let path = searchParams.get('path') + + if (append_sha == 'false' || append_sha == 'true') { + url.searchParams.set('append_sha', append_sha) + } + if (path) { + url.searchParams.set('path', path) + } + } + + return url + } + + function validRequest(request) { + let url = new URL(request.url) + let path = url.pathname + + if (/^(.+)(\/raw\/|\/-\/archive\/)/.test(path)) { + return true + } + + return false + } + ``` + +3. 使用此脚本创建一个新的工作程序. +4. 复制`ORIGIN_HOSTNAME`和`STORAGE_TOKEN`值. 使用这些值为[静态对象配置外部存储](#configuring) . \ No newline at end of file diff --git a/_book/docs/531.md b/_book/docs/531.md new file mode 100644 index 0000000000000000000000000000000000000000..730eaede8aec3913a2334f9701c53359130586e8 --- /dev/null +++ b/_book/docs/531.md @@ -0,0 +1,225 @@ +# Updating GitLab + +> 原文:[https://docs.gitlab.com/ee/update/README.html](https://docs.gitlab.com/ee/update/README.html) + +* [Omnibus Packages](#omnibus-packages) +* [Installation from source](#installation-from-source) +* [Installation using Docker](#installation-using-docker) +* [Upgrading without downtime](#upgrading-without-downtime) + * [Examples](#examples) + * [Steps](#steps) +* [Checking for background migrations before upgrading](#checking-for-background-migrations-before-upgrading) + * [What do I do if my background migrations are stuck?](#what-do-i-do-if-my-background-migrations-are-stuck) +* [Upgrading to a new major version](#upgrading-to-a-new-major-version) +* [Upgrading between editions](#upgrading-between-editions) + * [Community to Enterprise Edition](#community-to-enterprise-edition) + * [Enterprise to Community Edition](#enterprise-to-community-edition) +* [Version specific upgrading instructions](#version-specific-upgrading-instructions) + * [13.2.0](#1320) + * [13.1.0](#1310) + * [12.2.0](#1220) + * [12.0.0](#1200) +* [Miscellaneous](#miscellaneous) + +# Updating GitLab[](#updating-gitlab "Permalink") + +根据安装方法和您的 GitLab 版本,有多个更新指南. + +当前有 3 种官方方法来安装 GitLab: + +* [Omnibus packages](#omnibus-packages) +* [Source installation](#installation-from-source) +* [Docker installation](#installation-using-docker) + +根据您的安装,在下面选择适合您需要的部分. + +## Omnibus Packages[](#omnibus-packages "Permalink") + +* [Omnibus 更新指南](https://docs.gitlab.com/omnibus/update/README.html)包含更新 Omnibus GitLab 软件包所需的步骤. + +## Installation from source[](#installation-from-source "Permalink") + +* [从源代码升级社区版和企业版-从源代码升级社区版和企业版](upgrading_from_source.html)的指南. +* [修补程序版本](patch_versions.html)指南包括修补程序版本(如 6.2.0 至 6.2.1)所需的步骤,并且适用于社区版和企业版. + +过去,我们使用单独的文档来进行升级说明,但是此后我们切换为使用单个文档. 仍然可以在 Git 存储库中找到旧的升级准则: + +* [Old upgrading guidelines for Community Edition](https://gitlab.com/gitlab-org/gitlab-foss/tree/11-8-stable/doc/update) +* [Old upgrading guidelines for Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/tree/11-8-stable-ee/doc/update) + +## Installation using Docker[](#installation-using-docker "Permalink") + +GitLab 提供了针对社区和企业版的官方 Docker 映像. 它们基于 Omnibus 软件包,有关如何更新它们的说明在[单独的文档中](https://docs.gitlab.com/omnibus/docker/README.html) . + +## Upgrading without downtime[](#upgrading-without-downtime "Permalink") + +从 GitLab 9.1.0 开始,可以升级到较新的主要,次要或补丁版本的 GitLab,而无需使 GitLab 实例脱机. 但是,要使其正常工作,必须满足以下要求: + +* 您一次只能升级 1 个次要版本. 所以从 9.1 到 9.2,而不是 9.3. +* 您必须使用[部署后迁移](../development/post_deployment_migrations.html) (包含在下面的零停机时间更新步骤中). +* 您正在使用 PostgreSQL. 从 GitLab 12.1 开始,不支持 MySQL. +* 多节点 GitLab 实例. 随着服务重启,单节点实例可能会经历短暂的中断. + +大多数情况下,如果该修补程序版本不是最新的,则可以从该修补程序版本安全地升级到下一个次要版本. 例如,即使已发布 9.1.2,从 9.1.1 升级到 9.2.0 也应该是安全的. 我们建议您检查当前版本和目标版本之间的所有发行版本,以防它们包含可能需要一次升级 1 个发行版本的任何迁移. + +一些版本可能还包含所谓的"后台迁移". 这些迁移是由 Sidekiq 在后台执行的,通常用于迁移数据. 仅在每月发行版中添加后台迁移. + +某些主要/次要版本可能需要完成一组后台迁移. 为了保证这一点,此版本将在继续升级过程之前处理所有剩余的作业. 虽然这不需要停机(如果满足上述条件),但我们建议用户在升级主要/次要版本之间至少保留 1 周,以完成后台迁移. 通过增加可以处理`background_migration`队列中的作业的 Sidekiq 工作者的数量,可以减少完成这些迁移所需的时间. 要查看此队列的大小, [请在升级之前检查后台迁移](#checking-for-background-migrations-before-upgrading) . + +根据经验,任何小于 10 GB 的数据库都不会花费太多时间进行升级. 每个次要版本最多可能需要一个小时. 但是,较大的数据库可能需要更多时间,但这在很大程度上取决于数据库的大小和正在执行的迁移. + +### Examples[](#examples "Permalink") + +为了帮助解释这一点,让我们看一些示例. + +**示例 1:**您正在使用版本 9.4.2(这是 9.4 的最新修补程序版本)运行大型的 GitLab 安装. 如果满足上述要求,则在发布 GitLab 9.5.0 时,可以安全地将此安装升级到 9.5.0,而无需停机. 您也可以跳过 9.5.0 并在其发布后升级到 9.5.1,但是**不能**直接升级到 9.6.0\. 您*必须*先升级到 9.5.x 版本. + +**范例 2:** You are running a large GitLab installation using version 9.4.2, which is the latest patch release of 9.4\. GitLab 9.5 includes some background migrations, and 10.0 will require these to be completed (processing any remaining jobs for you). Skipping 9.5 is not possible without downtime, and due to the background migrations would require potentially hours of downtime depending on how long it takes for the background migrations to complete. To work around this you will have to upgrade to 9.5.x first, then wait at least a week before upgrading to 10.0. + +**示例 3:**您将 MySQL 用作 GitLab 的数据库. 对新的主要/次要版本的任何升级都将需要停机. 如果发行版包含任何后台迁移,则可能会导致数小时的停机时间,具体取决于数据库的大小. 要解决此问题,您将必须使用 PostgreSQL 并满足上述其他在线升级要求. + +### Steps[](#steps "Permalink") + +[无需停机](https://docs.gitlab.com/omnibus/update/README.html)即可进行[升级的](https://docs.gitlab.com/omnibus/update/README.html)步骤. + +## Checking for background migrations before upgrading[](#checking-for-background-migrations-before-upgrading "Permalink") + +某些主要/次要版本可能需要完成一组后台迁移. 可以通过运行以下命令找到剩余的迁移作业数: + +**对于所有安装** + +如果使用的是 GitLab 12.9 及更高版本,请运行: + +``` +sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.remaining' +``` + +如果使用的是 GitLab 12.8 及更早版本,请使用[Rails 控制台](../administration/troubleshooting/debug.html#starting-a-rails-console-session)运行以下命令: + +``` +puts Sidekiq::Queue.new("background_migration").size +Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size +``` + +* * * + +**对于源安装** + +如果使用的是 GitLab 12.9 及更高版本,请运行: + +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::BackgroundMigration.remaining' +``` + +如果使用的是 GitLab 12.8 及更早版本,请使用[Rails 控制台](../administration/troubleshooting/debug.html#starting-a-rails-console-session)运行以下命令: + +``` +puts Sidekiq::Queue.new("background_migration").size +Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size +``` + +### What do I do if my background migrations are stuck?[](#what-do-i-do-if-my-background-migrations-are-stuck "Permalink") + +**警告:**以下操作可能会破坏您的 GitLab 性能.**注意:**重新执行这些命令是安全的,尤其是当您有 1000 个以上的挂起作业可能会溢出运行时内存时. + +**对于所有安装** + +``` +# Start the rails console +sudo gitlab-rails c + +# Execute the following in the rails console +scheduled_queue = Sidekiq::ScheduledSet.new +pending_job_classes = scheduled_queue.select { |job| job["class"] == "BackgroundMigrationWorker" }.map { |job| job["args"].first }.uniq +pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) } +``` + +**对于源安装** + +``` +# Start the rails console +sudo -u git -H bundle exec rails RAILS_ENV=production + +# Execute the following in the rails console +scheduled_queue = Sidekiq::ScheduledSet.new +pending_job_classes = scheduled_queue.select { |job| job["class"] == "BackgroundMigrationWorker" }.map { |job| job["args"].first }.uniq +pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) } +``` + +## Upgrading to a new major version[](#upgrading-to-a-new-major-version "Permalink") + +主要版本保留用于向后不兼容的更改. 我们建议您首先升级到主要版本中的最新可用次要版本. 请按照[升级建议](../policy/maintenance.html#upgrade-recommendations)确定支持的升级路径. + +升级到新的主要版本之前,您应确保已完成以前版本的所有后台迁移作业. 要查看`background_migration`队列的当前大小, [请在升级之前检查后台迁移](#checking-for-background-migrations-before-upgrading) . + +## Upgrading between editions[](#upgrading-between-editions "Permalink") + +GitLab 有两个版本: [社区版](https://about.gitlab.com/features/#community)是 MIT 许可,以及[企业版](https://about.gitlab.com/features/#enterprise) ,其基于社区版的顶部,包括额外的功能,主要是针对机构拥有超过 100 个用户. + +您可以在下面找到一些指南,以帮助您轻松更改版本. + +### Community to Enterprise Edition[](#community-to-enterprise-edition "Permalink") + +> **注意:**以下指南仅适用于企业版的订户. + +如果您希望将 GitLab 安装从 Community 升级到 Enterprise Edition,请根据安装方法遵循以下指南: + +* [从 CE 到 EE 的源更新指南](upgrading_from_ce_to_ee.html) -步骤与版本升级非常相似:停止服务器,获取代码,更新新功能的配置文件,安装库并进行迁移,更新初始化脚本,启动应用程序并检查其功能状态. +* [Omnibus CE to EE-](https://docs.gitlab.com/omnibus/update/README.html)按照本指南将您的 Omnibus GitLab 社区版更新为企业版. + +### Enterprise to Community Edition[](#enterprise-to-community-edition "Permalink") + +如果您需要将 Enterprise Edition 安装降级回 Community Edition,则可以按照[本指南](../downgrade_ee_to_ce/README.html)进行操作,以使过程尽可能的顺利. + +## Version specific upgrading instructions[](#version-specific-upgrading-instructions "Permalink") + +### 13.2.0[](#1320 "Permalink") + +由于 Rails 的重大更改可能会导致授权问题,因此具有多个 Web 节点的 GitLab 安装将需要先[升级到 13.1,](#1310)然后再升级到 13.2(及更高版本). + +### 13.1.0[](#1310 "Permalink") + +在 13.1.0 中,您必须升级到以下任一版本: + +* 至少是 Git v2.24(以前,最低要求是 Git v2.22). +* 推荐的 Git v2.26. + +否则,由于使用新的`--end-of-options` Git 标志,某些 RPC 中的 Gitaly 服务将导致内部错误. + +此外,在 GitLab 13.1.0 中, [Rails](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33454)的版本[从 6.0.3 升级到 6.0.3.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33454) . Rails 升级包括对 CSRF 令牌生成的更改,此更改不向后兼容-具有新 Rails 版本的 GitLab 服务器将生成 CSRF 令牌,而具有较旧 Rails 版本的 GitLab 服务器无法识别-这可能导致非 GET 请求失败用于[多节点 GitLab 安装](https://docs.gitlab.com/omnibus/update/) . + +因此,如果您正在使用多个 Rails 服务器,并专门从 13.0 升级,则必须先将所有服务器升级到 13.1.0,然后再升级到更高版本: + +1. 确保所有 GitLab Web 节点都在 GitLab 13.1.0 上. +2. (可选)启用`global_csrf_token`功能标记以启用 CSRF 令牌生成的新方法: + + ``` + Feature.enable(:global_csrf_token) + ``` + +3. 只有这样,才能继续升级到更高版本的 GitLab. + +### 12.2.0[](#1220 "Permalink") + +在 12.2.0 中,我们启用了 Rails 的身份验证 cookie 加密. 旧会话将自动升级. + +但是,不支持会话 cookie 降级. 因此,升级到 12.2.0 后,任何降级都将导致所有会话无效,并且用户将注销. + +### 12.0.0[](#1200 "Permalink") + +在 12.0.0 中,我们进行了各种与数据库相关的更改. 这些更改要求用户首先升级到最新的 11.11 修补程序版本. 升级到 11.11.x 之后,用户可以升级到 12.0.x. 否则可能导致未应用数据库迁移,这可能导致应用程序错误. + +还需要先升级到 12.0.x,然后再升级到 12.x 的更高版本. + +示例 1:您当前正在使用 GitLab 11.11.8,它是 11.11.x 的最新补丁程序版本. 您可以照常升级到 12.0.x. + +示例 2:您当前使用的是 GitLab 10.x 版本. 要升级,请先升级到最新的 10.x 版本(10.8.7),然后再升级到最新的 11.x 版本(11.11.8). 升级到 11.11.8 后,您可以安全地升级到 12.0.x. + +有关更多信息,请参见我们的[升级路径文档](../policy/maintenance.html#upgrade-recommendations) . + +## Miscellaneous[](#miscellaneous "Permalink") + +* [MySQL 到 PostgreSQL](mysql_to_postgresql.html)指导您完成从 MySQL 到 PostgreSQL 的数据库迁移. +* [Restoring from backup after a failed upgrade](restore_after_failure.html) +* [使用 Slony 升级 PostgreSQL](upgrading_postgresql_using_slony.html) ,以最少的停机时间升级 PostgreSQL 数据库. \ No newline at end of file diff --git a/_book/docs/532.md b/_book/docs/532.md new file mode 100644 index 0000000000000000000000000000000000000000..37d4ecb906cf253b38605f3b11ef2366badbb553 --- /dev/null +++ b/_book/docs/532.md @@ -0,0 +1,185 @@ +# GitLab release and maintenance policy + +> 原文:[https://docs.gitlab.com/ee/policy/maintenance.html](https://docs.gitlab.com/ee/policy/maintenance.html) + +* [Versioning](#versioning) +* [Upgrade recommendations](#upgrade-recommendations) + * [Upgrading major versions](#upgrading-major-versions) + * [Version 12 onward: Extra step for major upgrades](#version-12-onward-extra-step-for-major-upgrades) + * [Example upgrade paths](#example-upgrade-paths) + * [Upgrades from versions earlier than 8.12](#upgrades-from-versions-earlier-than-812) + * [Multi-step upgrade paths with GitLab all-in-one Linux package repository](#multi-step-upgrade-paths-with-gitlab-all-in-one-linux-package-repository) +* [Patch releases](#patch-releases) + * [Backporting to older releases](#backporting-to-older-releases) + * [Security releases](#security-releases) +* [More information](#more-information) + +# GitLab release and maintenance policy[](#gitlab-release-and-maintenance-policy "Permalink") + +GitLab 拥有严格的政策来管理版本命名,以及主要,次要,补丁和安全发布的发布速度. 新版本在[GitLab 博客](https://about.gitlab.com/releases/categories/releases/)上宣布. + +我们目前的政策是: + +* 在任何给定时间, **仅针对当前稳定版本**进行向后移植错误修复. (请参阅[修补程序版本](#patch-releases) .) +* **除了当前的稳定版本之外,还将**安全修复程序反向移植**到前两个月的版本中** . (请参阅[安全性发布](#security-releases) .) + +在极少数情况下,版本管理者可能会例外,并向后移植到最近两个月以上的版本. 有关更多信息,请参见[向旧版本的移植](#backporting-to-older-releases) . + +## Versioning[](#versioning "Permalink") + +GitLab 在其发行版中使用了[语义版本控制](https://semver.org/) :( `(Major).(Minor).(Patch)` . + +例如,对于 GitLab 版本 12.10.6: + +* `12`代表主要版本. 主要版本是 12.0.0,但通常称为 12.0. +* `10`代表次要版本. 次要版本为 12.10.0,但通常称为 12.10. +* `6`代表补丁号码. + +版本号的任何部分都可以递增为多个数字,例如 13.10.11. + +下表描述了版本类型及其发布节奏: + +| 版本类型 | Description | Cadence | +| --- | --- | --- | +| Major | 对于重大更改,或向公共 API 引入任何向后不兼容的更改时. | 每年. 下一个主要版本是 2021 年 5 月 22 日的 GitLab 14.0.默认情况下,后续主要版本计划于每年 5 月 22 日发布. | +| Minor | 当将新的向后兼容功能引入公共 API 时,将引入次要功能,或者推出一组较小的功能. | 每月 22 日. | +| Patch | 对于向后兼容的错误修复程序,用于修复错误的行为. 请参阅[修补程序版本](#patch-releases) . | 如所须. | + +## Upgrade recommendations[](#upgrade-recommendations "Permalink") + +我们鼓励所有人运行[最新的稳定版,](https://about.gitlab.com/releases/categories/releases/)以确保您可以轻松升级到最安全,功能最丰富的 GitLab 体验. 为确保您可以轻松运行最新的稳定版本,我们正在努力使更新过程简单可靠. + +如果您无法遵循我们的每月发布周期,则需要考虑几种情况. + +在一个主要版本中的补丁版本和次要版本之间跳转是安全的. 例如,安全的是: + +* 升级*次要*版本. 例如: + + * `12.7.5` -> `12.10.5` + * `11.3.4` -> `11.11.1` + * `10.6.6` -> `10.8.3` + * `11.3.4` -> `11.11.8` + * `10.6.6` -> `10.8.7` + * `9.2.3` -> `9.5.5` + * `8.9.4` -> `8.12.3` +* 升级*补丁程序*版本. 例如: + + * `12.0.4` -> `12.0.12` + * `11.11.1` -> `11.11.8` + * `10.6.3` -> `10.6.6` + * `11.11.1` -> `11.11.8` + * `10.6.3` -> `10.6.6` + * `9.5.5` -> `9.5.9` + * `8.9.2` -> `8.9.6` + +**注意:** Omnibus GitLab Linux 软件包中特定于版本的更改可在[Omnibus GitLab 文档中找到](https://docs.gitlab.com/omnibus/update/README.html) .**注意:**有关在本地下载 Omnibus GitLab Linux 软件包以及[手动安装的](https://docs.gitlab.com/omnibus/manual_install.html)说明. + +### Upgrading major versions[](#upgrading-major-versions "Permalink") + +升级*主要*版本需要更多注意. 向后不兼容的更改和迁移保留用于主要版本. 我们不能保证主要版本之间的升级是无缝的. 我们建议在升级到下一个主要版本之前,先升级到主要版本中的最新可用*次要*版本. 这样做将解决所有向后不兼容的更改或弃用,以帮助确保成功升级到下一个主要版本. + +同样重要的是,在升级到新的主要版本之前,请确保所有后台迁移已完全完成. 要查看`background_migration`队列的当前大小, [请在升级前检查后台迁移](../update/README.html#checking-for-background-migrations-before-upgrading) . + +如果您的 GitLab 实例具有与之关联的任何 GitLab Runner,则升级 GitLab Runners 以匹配已升级到的 GitLab 次要版本非常重要. 这是为了确保[与 GitLab 版本兼容](https://docs.gitlab.com/runner/) . + +### Version 12 onward: Extra step for major upgrades[](#version-12-onward-extra-step-for-major-upgrades "Permalink") + +从版本 12 开始,还需要执行其他步骤. 在主要版本升级期间,可能会发生更重要的迁移. + +为确保这些成功: + +1. 在主要版本跳转期间递增到第一个次要版本( `x.0.x` ). +2. 继续升级到较新的版本. + +**例如: `11.5.x` - > `11.11.x` - > `12.0.x` - > `12.10.x` - > `13.0.x`** + +### Example upgrade paths[](#example-upgrade-paths "Permalink") + +Please see the table below for some examples: + +| 目标版本 | 您的版本 | 推荐升级路径 | Note | +| --- | --- | --- | --- | +| `13.2.0` | `11.5.0` | `11.5.0` -> `11.11.8` -> `12.0.12` -> `12.10.6` -> `13.0.0` -> `13.2.0` | 四个中间版本是必需的:最终的`11.11` , `12.0`和`12.10`的版本,再加上`13.0` . | +| `13.0.1` | `11.10.8` | `11.10.5` -> `11.11.8` -> `12.0.12` -> `12.10.6` -> `13.0.1` | 三个中间版本是必需的: `11.11` , `12.0`和`12.10` . | +| `12.10.6` | `11.3.4` | `11.3.4` -> `11.11.8` -> `12.0.12` -> `12.10.6` | 需要两个中间版本: `11.11`和`12.0` | +| `12.9.5` | `10.4.5` | `10.4.5` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.9.5` | 三个中间版本是必需的: `10.8` , `11.11`和`12.0` ,然后`12.9.5` | +| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.2.5` | 四个中间版本是必需的: `9.5` , `10.8` , `11.11` , `12.0` ,然后`12.2` . | +| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7`是版本 8 的最新版本, `9.5.10`是版本 9 的最新版本, `10.8.7`是版本 10 的最新版本. | + +### Upgrades from versions earlier than 8.12[](#upgrades-from-versions-earlier-than-812 "Permalink") + +* `8.11.x`和更早版本:您可能必须先升级到`8.12.0`然后才能升级到`8.17.7` . 这是[在一个问题](https://gitlab.com/gitlab-org/gitlab/-/issues/207259)中[报道的](https://gitlab.com/gitlab-org/gitlab/-/issues/207259) . +* [将 8.0](https://docs.gitlab.com/omnibus/update/README.html)合并到 GitLab 时, [CI 会在 8.0 版之前更改](https://docs.gitlab.com/omnibus/update/README.html) . + +### Multi-step upgrade paths with GitLab all-in-one Linux package repository[](#multi-step-upgrade-paths-with-gitlab-all-in-one-linux-package-repository "Permalink") + +Linux 软件包管理器默认安装用于安装和升级的软件包的最新可用版本. 对于需要多阶段升级路径的旧版 GitLab 版本,直接升级到最新的主要版本可能会出现问题. + +当遵循跨多个版本的升级路径时,对于每次升级,请在软件包管理器的 install 或 upgrade 命令中指定所需的 GitLab 版本号. + +Examples: + +``` +# apt-get (Ubuntu/Debian) +sudo apt-get upgrade gitlab-ee=12.0.12-ee.0 +# yum (RHEL/CentOS 6 and 7) +yum install gitlab-ee-12.0.12-ee.0.el7 +# dnf (RHEL/CentOS 8) +dnf install gitlab-ee-12.0.12-ee.0.el8 +# zypper (SUSE) +zypper install gitlab-ee=12.0.12-ee.0 +``` + +## Patch releases[](#patch-releases "Permalink") + +补丁程序发行版**仅包含**针对当前稳定发行版 GitLab 的**错误修复** . + +制定这两项政策是因为: + +1. GitLab 拥有社区和企业发行版,使测试/发布软件所需的工作量加倍. +2. 向多个版本进行反向移植会产生很高的开发,质量保证和支持成本. +3. 支持并行版本不鼓励逐步升级,随着时间的推移,升级会越来越复杂,并给所有用户带来升级挑战. manbetx 客户端打不开有一个专门的团队,以确保增量升级(和安装)尽可能简单. +4. 在 GitLab 应用程序中创建的更改数量很多,这有助于将复杂性向后移植到较旧的版本. 在某些情况下,向后移植必须经过相同的审核过程,然后才能进行新的更改. +5. 在某些情况下,确保测试能够通过旧版本是一个相当大的挑战,因此非常耗时. + +无法在补丁程序发行版中包含新功能,因为这会破坏[语义版本控制](https://semver.org/) . 对于必须遵守各种内部要求(例如,组织合规性,验证新功能等)的用户,破坏[语义版本控制](https://semver.org/)具有以下后果: + +1. 无法快速升级以利用补丁程序版本中包含的错误修复程序. +2. 无法快速升级以利用补丁程序版本中包含的安全修复程序. +3. 要求包括对稳定的 GitLab 版本以及每个补丁版本的广泛测试. + +如果战略用户需要在正式发布功能之前对其进行测试,我们可以提供创建包含特定功能的候选发布(RC)版本的功能. 仅在极端情况下才需要这样做,并且可以通过在[发布/任务](https://gitlab.com/gitlab-org/release/tasks/-/issues/new?issuable_template=Backporting-request)问题跟踪器中提出问题来请求考虑. 重要的是要注意,发布候选版本还将包含其他功能和更改,因为无法轻松隔离特定功能(如上所述的类似原因). 候选发布版本与部署到 GitLab.com 或可公开访问的任何代码没有什么不同. + +### Backporting to older releases[](#backporting-to-older-releases "Permalink") + +向后移植到多个稳定版本通常是为[安全版本](#security-releases)保留的. 但是,在某些情况下,我们可能需要将*错误修复程序*回移植到多个稳定版本中,具体取决于错误的严重性. + +[当前版本管理者](https://about.gitlab.com/community/release-managers/)将决定是否执行向后移植更改,这与[管理 bug](https://gitlab.com/gitlab-org/gitlab/blob/master/PROCESS.md#managing-bugs)流程中所述类似,基于以下*所有条件* : + +1. 错误的估计[严重性](../development/contributing/issue_workflow.html#severity-labels) :根据当前的严重性定义,对用户的最大影响. +2. 错误的估计[优先级](../development/contributing/issue_workflow.html#priority-labels) :根据上述估计的严重性,立即对所有受影响的用户产生影响. +3. 潜在的数据丢失和/或安全漏洞. +4. 由于用户证明无法升级到当前的稳定版本,因此可能影响一个或多个战略帐户. + +如果满足以上*所有条件* ,则可以为当前的稳定版本和两个先前的每月版本创建反向版本. 在极少数情况下,发行经理可以授予例外,以向后移植到两个以上的先前每月发行中. 例如,如果我们发布`11.2.1`并包含`11.0.0`引入的严重错误的修复程序,则可以将该修复程序`11.1.x`移植到新的`11.0.x`和`11.1.x`补丁程序版本. + +To request backporting to more than one stable release for consideration, raise an issue in the [release/tasks](https://gitlab.com/gitlab-org/release/tasks/-/issues/new?issuable_template=Backporting-request) issue tracker. + +### Security releases[](#security-releases "Permalink") + +安全版本是一种特殊的修补程序版本,除了当前的稳定版本之外,仅包括前两个月版本的安全修补程序和修补程序(请参见下文). + +对于非常严重的安全问题, [有先例](https://about.gitlab.com/releases/2016/05/02/cve-2016-4340-patches/)将安全修复程序向后移植到 GitLab 的每月发布版本. 该决定是根据具体情况做出的. + +## More information[](#more-information "Permalink") + +Check [our release posts](https://about.gitlab.com/releases/categories/releases/). + +每个月,我们都会发布 GitLab 的主要版本或次要版本. 在这些发行文章的末尾,有三个部分可供查找:弃用,删除和有关升级的重要说明. 这些将包括: + +* 升级过程中需要执行的步骤. 例如, [8.12](https://about.gitlab.com/releases/2016/09/22/gitlab-8-12-released/#upgrade-barometer)需要重新创建 Elasticsearch 索引. 任何较旧版本的 GitLab 升级到 8.12 或更高版本都需要此功能. +* 对我们支持的软件版本的更改,例如[在 GitLab 13 中不再支持 IE11](https://about.gitlab.com/releases/2020/03/22/gitlab-12-9-released/#ending-support-for-internet-explorer-11) . + +You should check all the major and minor versions you’re passing over. + +有关发行过程的更多信息,请参见我们的[发行文档](https://gitlab.com/gitlab-org/release/docs) . 您可能还需要阅读我们的《 [负责任的披露政策》](https://about.gitlab.com/security/disclosure/) . \ No newline at end of file diff --git a/_book/docs/533.md b/_book/docs/533.md new file mode 100644 index 0000000000000000000000000000000000000000..8ecb2facede4830194f06813a5ee0326b3af378e --- /dev/null +++ b/_book/docs/533.md @@ -0,0 +1,27 @@ +# Security + +> 原文:[https://docs.gitlab.com/ee/security/README.html](https://docs.gitlab.com/ee/security/README.html) + +* [Securing your GitLab installation](#securing-your-gitlab-installation) + +# Security[](#security "Permalink") + +* [Password storage](password_storage.html) +* [Password length limits](password_length_limits.html) +* [Restrict SSH key technologies and minimum length](ssh_keys_restrictions.html) +* [Rate limits](rate_limits.html) +* [Webhooks and insecure internal web services](webhooks.html) +* [Information exclusivity](information_exclusivity.html) +* [Reset your root password](reset_root_password.html) +* [Unlock a locked user](unlock_user.html) +* [User File Uploads](user_file_uploads.html) +* [How we manage the CRIME vulnerability](crime_vulnerability.html) +* [Enforce Two-factor authentication](two_factor_authentication.html) +* [Send email confirmation on sign-up](user_email_confirmation.html) +* [Security of running jobs](https://docs.gitlab.com/runner/security/) +* [Proxying images](asset_proxy.html) +* [CI/CD environment variables](cicd_environment_variables.html) + +## Securing your GitLab installation[](#securing-your-gitlab-installation "Permalink") + +考虑使用诸如[注册限制](../user/admin_area/settings/sign_up_restrictions.html)和[身份验证选项之](../topics/authentication/)类的访问控制功能来强化您的 GitLab 实例,并最大程度地减少不必要的用户帐户创建风险. \ No newline at end of file diff --git a/_book/docs/534.md b/_book/docs/534.md new file mode 100644 index 0000000000000000000000000000000000000000..33cc73c1db4b4a3fbefd14d81d77900a051f3142 --- /dev/null +++ b/_book/docs/534.md @@ -0,0 +1,13 @@ +# Password Storage + +> 原文:[https://docs.gitlab.com/ee/security/password_storage.html](https://docs.gitlab.com/ee/security/password_storage.html) + +# Password Storage[](#password-storage "Permalink") + +GitLab 以散列格式存储用户密码,以防止密码可见. + +GitLab 使用[Devise](https://github.com/heartcombo/devise)身份验证库,该库处理用户密码的哈希. 使用以下属性创建密码哈希: + +* **散列** : [bcrypt](https://en.wikipedia.org/wiki/Bcrypt)散列函数用于生成所提供密码的散列. 这是一种强大的,行业标准的加密哈希函数. +* **拉伸** :密码哈希值, [拉伸](https://en.wikipedia.org/wiki/Key_stretching)打击蛮力攻击硬化. GitLab 默认使用 10 的拉伸因子. +* **盐析** :一个[加密盐](https://en.wikipedia.org/wiki/Salt_(cryptography))被添加到每个口令以针对预先计算的散列值和字典攻击硬化. 每个密码都会随机生成一个盐,因此不会有两个密码共享一个盐,以进一步提高安全性. \ No newline at end of file diff --git a/_book/docs/535.md b/_book/docs/535.md new file mode 100644 index 0000000000000000000000000000000000000000..b4f17b13efcdb8b89e037bc3c5b46580f4d68190 --- /dev/null +++ b/_book/docs/535.md @@ -0,0 +1,56 @@ +# Custom password length limits + +> 原文:[https://docs.gitlab.com/ee/security/password_length_limits.html](https://docs.gitlab.com/ee/security/password_length_limits.html) + +* [Modify maximum password length using configuration file](#modify-maximum-password-length-using-configuration-file) +* [Modify minimum password length using GitLab UI](#modify-minimum-password-length-using-gitlab-ui) + +# Custom password length limits[](#custom-password-length-limits "Permalink") + +默认情况下,GitLab 支持以下密码: + +* 最小长度为 8. +* 最大长度为 128. + +GitLab 管理员可以修改密码长度: + +* 使用配置文件. +* [从](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20661) GitLab 12.6 使用 GitLab UI. + +## Modify maximum password length using configuration file[](#modify-maximum-password-length-using-configuration-file "Permalink") + +默认情况下,用户密码长度设置为最多 128 个字符. 要从源代码更改安装: + +1. Edit `devise_password_length.rb`: + + ``` + cd /home/git/gitlab + sudo -u git -H cp config/initializers/devise_password_length.rb.example config/initializers/devise_password_length.rb + sudo -u git -H editor config/initializers/devise_password_length.rb + ``` + +2. 更改新的密码长度限制: + + ``` + config.password_length = 12..135 + ``` + + 在此示例中,最小长度为 12 个字符,最大长度为 135 个字符. + +3. [重新启动 GitLab,](../administration/restart_gitlab.html#installations-from-source)以使更改生效. + +**注意:**从 GitLab 12.6 起,此配置文件中设置的最小密码长度将被忽略. 现在必须通过[GitLab UI](#modify-minimum-password-length-using-gitlab-ui)修改最小密码长度. + +## Modify minimum password length using GitLab UI[](#modify-minimum-password-length-using-gitlab-ui "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20661) + +默认情况下,用户密码长度设置为至少 8 个字符. 要使用 GitLab UI 进行更改,请执行以下操作: + +在**管理区域>设置** ( `/admin/application_settings/general` )中,转到**注册限制部分** . + +[Minimum password length settings](../user/admin_area/img/minimum_password_length_settings_v12_6.png) + +将" **最小密码长度"**设置为大于或等于 8 的值,然后单击" **保存更改"**以保存更改. + +**警告:**更改最小或最大限制不会以任何方式影响现有的用户密码. 将不要求现有用户重设密码以遵守新限制. 新的限制限制仅适用于新用户注册以及现有用户执行密码重置时. \ No newline at end of file diff --git a/_book/docs/536.md b/_book/docs/536.md new file mode 100644 index 0000000000000000000000000000000000000000..18ea2fa2ac867f2e1b411b3af63fc97bf1bfead7 --- /dev/null +++ b/_book/docs/536.md @@ -0,0 +1,23 @@ +# Restrict allowed SSH key technologies and minimum length + +> 原文:[https://docs.gitlab.com/ee/security/ssh_keys_restrictions.html](https://docs.gitlab.com/ee/security/ssh_keys_restrictions.html) + +# Restrict allowed SSH key technologies and minimum length[](#restrict-allowed-ssh-key-technologies-and-minimum-length "Permalink") + +`ssh-keygen`允许用户创建低至 768 位的 RSA 密钥,这远低于某些标准组(例如 US NIST)的建议. 一些部署 GitLab 的组织将需要增强最低密钥强度,以满足内部安全策略或法规遵从性. + +同样,某些标准组建议在较旧的 DSA 上使用 RSA,ECDSA 或 ED25519,并且管理员可能需要限制允许的 SSH 密钥算法. + +GitLab 允许您限制允许的 SSH 密钥技术,并指定每种技术的最小密钥长度. + +在**管理区域>设置** ( `/admin/application_settings/general` )中,展开**可见性和访问控制**部分: + +[![SSH keys restriction admin settings](img/f9be0028bdcfdf495f7fd0f148de5214.png)](img/ssh_keys_restrictions_settings.png) + +如果对任何密钥类型施加了限制,则用户将无法上载不符合要求的新 SSH 密钥. 现有的不符合要求的键将被禁用但不会被删除,用户将无法使用它们来拉入或推入代码. + +用户的个人资料的" SSH 密钥"部分中的受限密钥图标将对用户可见: + +[![Restricted SSH key icon](img/0a8b584e09781bad1c374f8badc0a12c.png)](img/ssh_keys_restricted_key_icon.png) + +将鼠标悬停在此图标上会告诉您为什么限制按键. \ No newline at end of file diff --git a/_book/docs/537.md b/_book/docs/537.md new file mode 100644 index 0000000000000000000000000000000000000000..af02299685ba0eaef5fef5d6101879b233b56e76 --- /dev/null +++ b/_book/docs/537.md @@ -0,0 +1,28 @@ +# Rate limits + +> 原文:[https://docs.gitlab.com/ee/security/rate_limits.html](https://docs.gitlab.com/ee/security/rate_limits.html) + +* [Admin Area settings](#admin-area-settings) +* [Rack Attack initializer](#rack-attack-initializer) + +# Rate limits[](#rate-limits "Permalink") + +**注意:**对于 GitLab.com,请参阅[GitLab.com 特定的速率限制](../user/gitlab_com/index.html#gitlabcom-specific-rate-limits) . + +速率限制是用于提高 Web 应用程序的安全性和耐用性的常用技术. + +例如,一个简单的脚本每秒可以发出数千个 Web 请求. 无论是恶意的,冷漠的还是仅是错误的,您的应用程序和基础架构都可能无法应付负载. 有关更多详细信息,请参阅[拒绝服务攻击](https://en.wikipedia.org/wiki/Denial-of-service_attack) . 通过限制来自单个 IP 地址的请求速率,可以缓解大多数情况. + +速率限制可以缓解大多数[暴力攻击](https://en.wikipedia.org/wiki/Brute-force_attack) . + +## Admin Area settings[](#admin-area-settings "Permalink") + +* [Issues rate limits](../user/admin_area/settings/rate_limit_on_issues_creation.html). +* [User and IP rate limits](../user/admin_area/settings/user_and_ip_rate_limits.html). +* [Raw endpoints rate limits](../user/admin_area/settings/rate_limits_on_raw_endpoints.html). +* [Protected paths](../user/admin_area/settings/protected_paths.html). +* [Import/Export rate limits](../user/admin_area/settings/import_export_rate_limits.html). + +## Rack Attack initializer[](#rack-attack-initializer "Permalink") + +这种限制速率的方法很麻烦,但是具有一些优点. 它允许限制特定路径,并且还集成到 Git 和容器注册表请求中. 请参阅[机架攻击初始化程序](rack_attack.html) . \ No newline at end of file diff --git a/_book/docs/538.md b/_book/docs/538.md new file mode 100644 index 0000000000000000000000000000000000000000..12fe3c5fdcaedb661f8b899d048d53c7b42ae476 --- /dev/null +++ b/_book/docs/538.md @@ -0,0 +1,54 @@ +# Webhooks and insecure internal web services + +> 原文:[https://docs.gitlab.com/ee/security/webhooks.html](https://docs.gitlab.com/ee/security/webhooks.html) + +* [Allowlist for local requests](#allowlist-for-local-requests) + +# Webhooks and insecure internal web services[](#webhooks-and-insecure-internal-web-services "Permalink") + +**注意:**在 GitLab.com 上[,](../user/gitlab_com/index.html#maximum-number-of-webhooks)每个项目的[最大](../user/gitlab_com/index.html#maximum-number-of-webhooks) Webhooks [数量](../user/gitlab_com/index.html#maximum-number-of-webhooks)是有限的. + +如果您在 GitLab 服务器上或其本地网络中运行了非 GitLab Web 服务,则可能容易受到 Webhooks 的利用. + +使用[Webhooks](../user/project/integrations/webhooks.html) ,您以及您的项目维护者和所有者可以设置 URL,以便在项目中发生特定更改时触发该 URL. 通常,这些请求将发送到专门为此目的设置的外部 Web 服务,该服务以某种适当的方式处理该请求及其附加数据. + +但是,当 Webhook 设置的 URL 不是指向外部服务而是指向内部服务时,事情变得很麻烦,当触发 Webhook 和发送 POST 请求时,这可能会做完全不希望的事情. + +Webhook 请求由 GitLab 服务器本身发出,并且每个钩子使用一个(可选)秘密令牌进行授权(而不是用户或特定于仓库的令牌). 结果,它们可能比托管 Webhook 的服务器(可能包括 GitLab 服务器或 API 本身,例如`http://localhost:123` )上运行的所有对象具有更广泛的访问权限. 根据所调用的 Webhook,这也可能导致对该 Webhook 服务器的本地网络(例如, `http://192.168.1.12:345` : `http://192.168.1.12:345` : `http://192.168.1.12:345` )内的其他服务器的网络访问,即使这些服务受到其他保护并且无法从外界访问. + +如果 Web 服务不需要身份验证,则可以通过使 GitLab 服务器向诸如`http://localhost:123/some-resource/delete`类的端点发出 POST 请求,来使用 Webhooks 触发破坏性命令. + +为了防止发生这种类型的攻击,从 GitLab 10.6 开始,默认情况下将禁止对当前 GitLab 实例服务器地址和/或专用网络中的所有 Webhook 请求. 这意味着,所有的请求作出`127.0.0.1` , `::1`和`0.0.0.0` ,以及 IPv4 的`10.0.0.0/8` , `172.16.0.0/12` , `192.168.0.0/16`和 IPv6 站点本地( `ffc0::/10` )地址将不被允许. + +通过在**管理区域>设置** ( `/admin/application_settings/network` )内*"出站请求"*部分中启用选项*"允许从 Web 挂钩和服务到本地网络的请求",*可以覆盖此行为: + +[![Outbound requests admin settings](img/95cf4cb85bf824cf0817d4d93d93934d.png)](img/outbound_requests_section_v12_2.png) + +**注意:由于** *系统挂钩*是由管理员设置的,因此默认情况下启用它们来向本地网络发出请求. 但是,可以通过禁用" **允许从系统挂钩向本地网络发送请求"**选项来关闭此功能. + +## Allowlist for local requests[](#allowlist-for-local-requests "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44496) in GitLab 12.2 + +通过将某些域和 IP 地址添加到允许*列表中,*即使不允许本地请求,也可以允许某些域和 IP 地址可供*系统挂钩*和*Web* *挂钩*访问. 导航到**管理区域>设置>网络** ( `/admin/application_settings/network` )并展开**出站请求** : + +[![Outbound local requests allowlist](img/77a2b247e60ad05b022cfd3f3a62c069.png)](img/allowlist_v13_0.png) + +允许的条目可以用分号,逗号或空格(包括换行符)分隔,并且可以采用不同的格式,例如主机名,IP 地址和/或 IP 范围. 支持 IPv6\. 包含 Unicode 字符的主机名应使用 IDNA 编码. + +允许列表最多可容纳 1000 个条目. 每个条目最多可以包含 255 个字符. + +您可以通过在允许列表条目中指定特定端口来允许它. 例如`127.0.0.1:8080`将仅允许连接到`127.0.0.1`上的端口 8080\. 如果未提及任何端口,则允许该 IP /域上的所有端口. IP 范围将允许该范围内所有 IP 上的所有端口. + +Example: + +``` +example.com;gitlab.example.com +127.0.0.1,1:0:0:0:0:0:0:1 +127.0.0.0/8 1:0:0:0:0:0:0:0/124 +[1:0:0:0:0:0:0:1]:8080 +127.0.0.1:8080 +example.com:8080 +``` + +**注意:**当前不支持通配符( `*.example.com` ). \ No newline at end of file diff --git a/_book/docs/539.md b/_book/docs/539.md new file mode 100644 index 0000000000000000000000000000000000000000..a77061294199389396b9beb1388c54dc1dfb5449 --- /dev/null +++ b/_book/docs/539.md @@ -0,0 +1,15 @@ +# Information exclusivity + +> 原文:[https://docs.gitlab.com/ee/security/information_exclusivity.html](https://docs.gitlab.com/ee/security/information_exclusivity.html) + +# Information exclusivity[](#information-exclusivity "Permalink") + +Git 是一个分布式版本控制系统(DVCS). 这意味着使用源代码的每个人都有完整存储库的本地副本. + +在 GitLab 中,每个不是来宾的项目成员(报告者,开发者和维护者)都可以克隆存储库以创建本地副本. 获取本地副本后,用户可以将完整的存储库上传到任何地方,包括上传到他们控制下的另一个项目或另一个服务器上. + +因此,不可能建立阻止访问源代码的用户有意共享源代码的访问控制. + +这是 DVCS 的固有功能. 所有 Git 管理系统都有此限制. + +您可以采取措施防止意外共享和信息破坏. 此限制是为什么只允许某些人[向项目添加用户,](../user/project/members/index.html)以及为什么只有 GitLab 管理员才能[强制推送受保护的分支的原因](../user/project/protected_branches.html) . \ No newline at end of file diff --git a/_book/docs/540.md b/_book/docs/540.md new file mode 100644 index 0000000000000000000000000000000000000000..9f93e2b0664af1bd1aca73c32962e1a6ca0ba967 --- /dev/null +++ b/_book/docs/540.md @@ -0,0 +1,44 @@ +# How to reset your root password + +> 原文:[https://docs.gitlab.com/ee/security/reset_root_password.html](https://docs.gitlab.com/ee/security/reset_root_password.html) + +# How to reset your root password[](#how-to-reset-your-root-password "Permalink") + +要重置您的 root 密码,请首先使用 root 特权登录到服务器. + +使用以下命令启动 Ruby on Rails 控制台: + +``` +gitlab-rails console -e production +``` + +等待控制台加载完毕. + +有多种找到用户的方法. 您可以搜索电子邮件或用户名. + +``` +user = User.where(id: 1).first +``` + +or + +``` +user = User.find_by(email: 'admin@example.com') +``` + +现在,您可以更改密码: + +``` +user.password = 'secret_pass' +user.password_confirmation = 'secret_pass' +``` + +更改 password 和 password_confirmation 以使其正常工作很重要. + +不要忘记保存更改. + +``` +user.save! +``` + +退出控制台,然后尝试使用新密码登录. \ No newline at end of file diff --git a/_book/docs/541.md b/_book/docs/541.md new file mode 100644 index 0000000000000000000000000000000000000000..f1fa18909a4e2f09686eddfa826e78f3533f8270 --- /dev/null +++ b/_book/docs/541.md @@ -0,0 +1,42 @@ +# How to unlock a locked user from the command line + +> 原文:[https://docs.gitlab.com/ee/security/unlock_user.html](https://docs.gitlab.com/ee/security/unlock_user.html) + +# How to unlock a locked user from the command line[](#how-to-unlock-a-locked-user-from-the-command-line "Permalink") + +十次失败的登录尝试后,用户将进入锁定状态. + +要解锁锁定的用户: + +1. SSH 到您的 GitLab 服务器. +2. 启动 Ruby on Rails 控制台: + + ``` + ## For Omnibus GitLab + sudo gitlab-rails console -e production + + ## For installations from source + sudo -u git -H bundle exec rails console -e production + ``` + +3. 查找要解锁的用户. 您可以通过电子邮件或 ID 进行搜索. + + ``` + user = User.find_by(email: 'admin@local.host') + ``` + + or + + ``` + user = User.where(id: 1).first + ``` + +4. 解锁用户: + + ``` + user.unlock_access! + ``` + +5. 使用`Ctrl` + `d`退出控制台 + +用户现在应该可以登录了. \ No newline at end of file diff --git a/_book/docs/542.md b/_book/docs/542.md new file mode 100644 index 0000000000000000000000000000000000000000..d1aa2e3c0a116d4e611dfe37381d5e24a623fc61 --- /dev/null +++ b/_book/docs/542.md @@ -0,0 +1,11 @@ +# User File Uploads + +> 原文:[https://docs.gitlab.com/ee/security/user_file_uploads.html](https://docs.gitlab.com/ee/security/user_file_uploads.html) + +# User File Uploads[](#user-file-uploads "Permalink") + +如果通过 URL 直接访问附加到问题,合并请求或注释中的图像,则无需查看身份验证. 该直接 URL 包含一个随机的 32 个字符的 ID,该 ID 可以防止未经授权的人员猜测图像的 URL,因此,如果图像包含敏感信息,则可以提供一定的保护. + +未启用身份验证,因为通知电子邮件的正文中必须显示图像,这些电子邮件通常是从未经 GitLab 身份验证的电子邮件客户端读取的,例如 Outlook,Apple Mail 或移动设备上的 Mail 应用程序. + +> **注意:**非图像附件确实需要进行身份验证才能查看. \ No newline at end of file diff --git a/_book/docs/543.md b/_book/docs/543.md new file mode 100644 index 0000000000000000000000000000000000000000..e72359c0b4038eeee89667186f358c81f4ca5cbd --- /dev/null +++ b/_book/docs/543.md @@ -0,0 +1,49 @@ +# How we manage the TLS protocol CRIME vulnerability + +> 原文:[https://docs.gitlab.com/ee/security/crime_vulnerability.html](https://docs.gitlab.com/ee/security/crime_vulnerability.html) + +* [Description](#description) +* [Nessus](#nessus) +* [References](#references) + +# How we manage the TLS protocol CRIME vulnerability[](#how-we-manage-the-tls-protocol-crime-vulnerability "Permalink") + +[CRIME](https://en.wikipedia.org/w/index.php?title=CRIME&oldid=692423806)是利用 HTTPS 和 SPDY 协议(也使用数据压缩)通过连接对秘密 Web Cookie 进行安全性攻击的方法. 当用于恢复秘密身份验证 Cookie 的内容时,它允许攻击者在经过身份验证的 Web 会话上执行会话劫持,从而允许发起进一步的攻击. + +## Description[](#description "Permalink") + +TLS 协议 CRIME 漏洞影响使用 HTTPS 进行数据压缩的系统. 如果使用 SSL 压缩(例如 Gzip)或 SPDY(可以选择使用压缩),则系统可能容易受到 CRIME 漏洞的攻击. + +GitLab 支持 Gzip 和[SPDY,](http://nginx0org.icopy.site/en/docs/http/ngx_http_spdy_module.html)并通过在启用 HTTPS 时禁用 Gzip 来缓解 CRIME 漏洞. 文件的来源在这里: + +* [Source installation NGINX file](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/support/nginx/gitlab-ssl) +* [Omnibus installation NGINX file](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/templates/default/nginx-gitlab-http.conf.erb) + +尽管在 Omnibus 安装中启用了 SPDY,但 CRIME 依赖于压缩(" C"),NGINX 的 SPDY 模块中的默认压缩级别为 0(无压缩). + +## Nessus[](#nessus "Permalink") + +Nessus 扫描仪[报告](https://www.tenable.com/plugins/index.php?view=single&id=62565) GitLab 中[可能存在的 CRIME 漏洞](https://www.tenable.com/plugins/index.php?view=single&id=62565) ,类似于以下格式: + +``` +Description + +This remote service has one of two configurations that are known to be required for the CRIME attack: +SSL/TLS compression is enabled. +TLS advertises the SPDY protocol earlier than version 4. + +... + +Output + +The following configuration indicates that the remote service may be vulnerable to the CRIME attack: +SPDY support earlier than version 4 is advertised. +``` + +从上面的报告中,需要特别注意的是,Nessus 仅检查 TLS 是否在版本 4 之前发布了 SPDY 协议.它不执行攻击,也不检查是否启用了压缩. 仅 Nessus 扫描程序无法告知 SPDY 的压缩已禁用并且不受 CRIME 漏洞的影响. + +## References[](#references "Permalink") + +* NGINX [“Module ngx_http_spdy_module”](http://nginx0org.icopy.site/en/docs/http/ngx_http_spdy_module.html) +* Tenable Network Security,Inc. ["传输层安全性(TLS)协议 CRIME 漏洞"](https://www.tenable.com/plugins/index.php?view=single&id=62565) +* Wikipedia 的贡献者, [" CRIME"](https://en.wikipedia.org/wiki/CRIME) Wikipedia,免费的百科全书 \ No newline at end of file diff --git a/_book/docs/544.md b/_book/docs/544.md new file mode 100644 index 0000000000000000000000000000000000000000..313f52acc10ff03d7d81327b23a9430de7930aae --- /dev/null +++ b/_book/docs/544.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/security/two_factor_authentication.html](https://docs.gitlab.com/ee/security/two_factor_authentication.html) \ No newline at end of file diff --git a/_book/docs/545.md b/_book/docs/545.md new file mode 100644 index 0000000000000000000000000000000000000000..0b602c6e6d2adc5b16d190ded27e5f7b25fb1ed5 --- /dev/null +++ b/_book/docs/545.md @@ -0,0 +1,9 @@ +# User email confirmation at sign-up + +> 原文:[https://docs.gitlab.com/ee/security/user_email_confirmation.html](https://docs.gitlab.com/ee/security/user_email_confirmation.html) + +# User email confirmation at sign-up[](#user-email-confirmation-at-sign-up "Permalink") + +可以将 GitLab 配置为在用户注册时要求确认用户的电子邮件地址. 启用此设置后,用户只有在确认电子邮件地址后才能登录. + +在**管理区域>设置** ( `/admin/application_settings/general` )中,转到" **注册限制** "部分**,**然后查找" **在注册时发送确认电子邮件"**选项. \ No newline at end of file diff --git a/_book/docs/546.md b/_book/docs/546.md new file mode 100644 index 0000000000000000000000000000000000000000..3a29dcbfc9833b764ba96585777acc30ecaa7115 --- /dev/null +++ b/_book/docs/546.md @@ -0,0 +1,66 @@ +# Security of running jobs + +> 原文:[https://docs.gitlab.com/runner/security/](https://docs.gitlab.com/runner/security/) + +* [Usage of Shell executor](#usage-of-shell-executor) +* [Usage of Docker executor](#usage-of-docker-executor) +* [Usage of private Docker images with `if-not-present` pull policy](#usage-of-private-docker-images-with-if-not-present-pull-policy) +* [Systems with Docker installed](#systems-with-docker-installed) +* [Usage of SSH executor](#usage-of-ssh-executor) +* [Usage of Parallels executor](#usage-of-parallels-executor) +* [Cloning a runner](#cloning-a-runner) + +# Security of running jobs[](#security-of-running-jobs "Permalink") + +使用 GitLab Runner 时,您应该在运行作业时意识到潜在的安全隐患. + +## Usage of Shell executor[](#usage-of-shell-executor "Permalink") + +**通常,使用`shell`执行程序运行测试是不安全的.** 这些作业在用户权限(GitLab Runner 的权限)下运行,并且可以从此服务器上运行的其他项目中窃取代码. 仅将其用于运行受信任的构建. + +## Usage of Docker executor[](#usage-of-docker-executor "Permalink") + +**在非特权模式下运行时,可以认为 Docker 是安全的.** 为了使这种设置更加安全,建议在 sudo 禁用或`SETUID`和`SETGID`功能已禁用的 Docker 容器中以用户(非 root 用户)身份运行作业. + +另一方面,存在特权模式,该模式允许对主机系统的完全访问权限,安装和卸载卷的权限以及运行嵌套容器. 不建议在特权模式下运行容器. + +可以通过`cap_add` / `cap_drop`设置在非特权模式下配置更精细的权限. + +## Usage of private Docker images with `if-not-present` pull policy[](#usage-of-private-docker-images-with-if-not-present-pull-policy "Permalink") + +使用[高级配置中](../configuration/advanced-configuration.html#using-a-private-container-registry)描述的私有 Docker 映像支持时[:使用私有容器注册表时](../configuration/advanced-configuration.html#using-a-private-container-registry) ,应`always`将其`pull_policy`值. 尤其是你应该使用`always`拉的政策,如果你正在主持一个公共,共享亚军与泊坞窗或 Kubernetes 执行人. + +让我们来看一个将拉策略设置为`if-not-present`的示例: + +1. 用户 A 在`registry.example.com/image/name`具有私有映像. +2. 用户 A 在共享运行器上启动构建:该构建接收注册表凭据,并在注册表中授权后提取映像. +3. 图像存储在共享的 Runner 主机上. +4. 用户 B 无法访问`registry.example.com/image/name`上的私有映像. +5. 用户 B 在与用户 A 相同的共享 Runner 上启动使用此映像的构建:Runner 找到该映像的本地版本并使用它, **即使由于缺少凭据也无法提取该映像** . + +因此,如果托管的 Runner 可以由不同的用户和不同的项目使用(具有私有和公共访问权限的混合级别),则永远不要使用`if-not-present`作为拉策略值,而应使用: + +* `never` -如果您想限制用户使用您预先下载的唯一图像. +* `always` -如果您想让用户可以从任何注册表下载任何图像. + +`if-not-present`拉策略**仅**应用于受信任的构建和用户使用的特定运行器. + +阅读[拉取策略文档](../executors/docker.html#how-pull-policies-work)以获取更多信息. + +## Systems with Docker installed[](#systems-with-docker-installed "Permalink") + +> **注意:**这适用于低于 0.5.0 的安装或已升级到较新版本的安装. + +在安装了 Docker 的 Linux 系统上安装软件包时, `gitlab-runner`将创建一个有权访问`Docker`守护程序的用户. 这使使用`shell` executor 运行的作业能够以完全权限访问`docker` ,并可能允许对服务器的根访问. + +## Usage of SSH executor[](#usage-of-ssh-executor "Permalink") + +由于缺少`StrictHostKeyChecking`选项, **SSH 执行程序容易受到 MITM 攻击(中间人)** . 这将在将来的版本之一中修复. + +## Usage of Parallels executor[](#usage-of-parallels-executor "Permalink") + +**Parallels executor 是最安全的选择,**因为它使用完整的系统虚拟化,并且配置为在隔离虚拟化中运行的 VM 机器和配置为以隔离模式运行的 VM 机器. 它阻止访问所有外围设备和共享文件夹. + +## Cloning a runner[](#cloning-a-runner "Permalink") + +跑步者使用令牌来标识 GitLab 服务器. 如果克隆一个运行程序,则克隆的运行程序可能正在为该令牌选择相同的作业. 这是"窃取"跑步者工作的一种可能的攻击手段. \ No newline at end of file diff --git a/_book/docs/547.md b/_book/docs/547.md new file mode 100644 index 0000000000000000000000000000000000000000..d8efc2908e4c4a12932c4f4a5a58c304c159da7c --- /dev/null +++ b/_book/docs/547.md @@ -0,0 +1,60 @@ +# Proxying assets + +> 原文:[https://docs.gitlab.com/ee/security/asset_proxy.html](https://docs.gitlab.com/ee/security/asset_proxy.html) + +* [Installing Camo server](#installing-camo-server) +* [Using the Camo server](#using-the-camo-server) + +# Proxying assets[](#proxying-assets "Permalink") + +在管理面向公众的 GitLab 实例时,可能存在的安全隐患是通过引用问题,评论等中的图像来窃取用户 IP 地址的能力. + +例如,在问题描述中添加`![Example image](http://example.com/example.png)`将导致从外部服务器加载图像以便显示. 但是,这也允许外部服务器记录用户的 IP 地址. + +减轻这种情况的一种方法是将所有外部映像代理到您控制的服务器. + +可以将 GitLab 配置为在问题,评论等中请求外部图像/视频/音频时使用资产代理服务器.这有助于确保恶意图像在获取时不会暴露用户的 IP 地址. + +当前,我们建议使用[cactus / go-camo,](https://github.com/cactus/go-camo#how-it-works)因为它支持代理视频,音频并且更可配置. + +## Installing Camo server[](#installing-camo-server "Permalink") + +一台 Camo 服务器用作代理. + +要将 Camo 服务器安装为资产代理,请执行以下操作: + +1. 部署`go-camo`服务器. 有用的说明可以在[建立 catus / go-camo 中找到](https://github.com/cactus/go-camo#building) . + +2. 确保您的 GitLab 实例正在运行,并且您已经创建了私有 API 令牌. 使用 API​​,在您的 GitLab 实例上配置资产代理设置. 例如: + + ``` + curl --request "PUT" "https://gitlab.example.com/api/v4/application/settings?\ asset_proxy_enabled=true&\ asset_proxy_url=https://proxy.gitlab.example.com&\ asset_proxy_secret_key=" \ + --header 'PRIVATE-TOKEN: ' + ``` + + 支持以下设置: + + | Attribute | Description | + | --- | --- | + | `asset_proxy_enabled` | 启用资产代理. 如果启用,则要求: `asset_proxy_url` ). | + | `asset_proxy_secret_key` | 与资产代理服务器共享的机密. | + | `asset_proxy_url` | 资产代理服务器的 URL. | + | `asset_proxy_whitelist` | 与这些域匹配的资产将不会被代理. 允许使用通配符. 您的 GitLab 安装网址会自动列入白名单. | + +3. 重新启动服务器,以使更改生效. 每次更改资产代理的任何值时,都需要重新启动服务器. + +## Using the Camo server[](#using-the-camo-server "Permalink") + +一旦 Camo 服务器运行并且启用了 GitLab 设置,任何引用外部源的图像,视频或音频都将被代理到 Camo 服务器. + +例如,以下是 Markdown 中图像的链接: + +``` +![logo](https://about.gitlab.com/images/press/logo/jpg/gitlab-icon-rgb.jpg) +``` + +以下是可能导致源链接的示例: + +``` +http://proxy.gitlab.example.com/f9dd2b40157757eb82afeedbf1290ffb67a3aeeb/68747470733a2f2f61626f75742e6769746c61622e636f6d2f696d616765732f70726573732f6c6f676f2f6a70672f6769746c61622d69636f6e2d7267622e6a7067 +``` \ No newline at end of file diff --git a/_book/docs/548.md b/_book/docs/548.md new file mode 100644 index 0000000000000000000000000000000000000000..b29777aa618bcaec13634db2c5c41964a5b8058a --- /dev/null +++ b/_book/docs/548.md @@ -0,0 +1,11 @@ +# CI/CD Environment Variables + +> 原文:[https://docs.gitlab.com/ee/security/cicd_environment_variables.html](https://docs.gitlab.com/ee/security/cicd_environment_variables.html) + +# CI/CD Environment Variables[](#cicd-environment-variables "Permalink") + +环境变量通过运行程序应用于环境,可以从项目的**"设置">" CI / CD"**页面进行**设置** . + +这些值使用[aes-256-cbc](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard)加密并存储在数据库中. + +只能使用有效的[机密文件](../raketasks/backup_restore.html#when-the-secrets-file-is-lost)解密此数据. \ No newline at end of file diff --git a/_book/docs/549.md b/_book/docs/549.md new file mode 100644 index 0000000000000000000000000000000000000000..60834619044a42a43b5c3637cc8f63ab930eac8d --- /dev/null +++ b/_book/docs/549.md @@ -0,0 +1,204 @@ +# Contributor and Development Docs + +> 原文:[https://docs.gitlab.com/ee/development/README.html](https://docs.gitlab.com/ee/development/README.html) + +* [Get started](#get-started) +* [Processes](#processes) +* [UX and Frontend guides](#ux-and-frontend-guides) +* [Backend guides](#backend-guides) +* [Performance guides](#performance-guides) +* [Database guides](#database-guides) +* [Integration guides](#integration-guides) +* [Testing guides](#testing-guides) +* [Refactoring guides](#refactoring-guides) +* [Documentation guides](#documentation-guides) +* [Internationalization (i18n) guides](#internationalization-i18n-guides) +* [Telemetry guides](#telemetry-guides) +* [Experiment guide](#experiment-guide) +* [Build guides](#build-guides) +* [Compliance](#compliance) +* [Go guides](#go-guides) +* [Shell Scripting guides](#shell-scripting-guides) +* [Domain-specific guides](#domain-specific-guides) +* [Other Development guides](#other-development-guides) +* [Other GitLab Development Kit (GDK) guides](#other-gitlab-development-kit-gdk-guides) + +# Contributor and Development Docs[](#contributor-and-development-docs "Permalink") + +## Get started[](#get-started "Permalink") + +* 使用[GitLab 开发套件(GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/README.md)设置 GitLab 的开发环境 +* [GitLab contributing guide](contributing/index.html) + * [发出工作流](contributing/issue_workflow.html)以获取有关以下方面的更多信息: + * 问题追踪器指南. + * 分流. + * 标签. + * 功能建议. + * 发行权重. + * 回归问题. + * 技术或用户体验债务. + * [合并请求工作流](contributing/merge_request_workflow.html)以获取有关以下方面的更多信息: + * 合并请求准则. + * 捐款接受标准. + * 完成的定义. + * 依赖关系. + * [Style guides](contributing/style_guides.html) + * [Implement design & UI elements](contributing/design.html) +* [GitLab Architecture Overview](architecture.html) +* [耙](rake_tasks.html)开发[任务](rake_tasks.html) + +## Processes[](#processes "Permalink") + +**Must-reads:** + +* [代码审查指南,](code_review.html)用于审查代码和审查代码 +* [数据库审阅指南,](database_review.html)用于审阅与数据库有关的更改和复杂的 SQL 查询,并进行审阅 +* [Secure coding guidelines](secure_coding_guidelines.html) +* [Pipelines for the GitLab project](pipelines.html) + +互补读物: + +* [GitLab core team & GitLab Inc. contribution process](https://gitlab.com/gitlab-org/gitlab/blob/master/PROCESS.md) +* [Security process for developers](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#security-releases-critical-non-critical-as-a-developer) +* [Guidelines for implementing Enterprise Edition features](ee_features.html) +* [Danger bot](dangerbot.html) +* [Generate a changelog entry with `bin/changelog`](changelog.html) +* [在 GitLab.com 上请求访问 Chatops](chatops_on_gitlabcom.html#requesting-access) (适用于 GitLab 团队成员) + +## UX and Frontend guides[](#ux-and-frontend-guides "Permalink") + +* 用于使用现有 CSS 样式和元素构建 GitLab 的[GitLab 设计系统](https://design.gitlab.com/) +* [Frontend guidelines](fe_guide/index.html) +* [Emoji guide](fe_guide/emojis.html) + +## Backend guides[](#backend-guides "Permalink") + +* [GitLab utilities](utilities.html) +* [Issuable-like Rails models](issuable-like-models.html) +* [Logging](logging.html) +* [API 样式指南,](api_styleguide.html)用于贡献 API +* [GraphQL API 样式指南,](api_graphql_styleguide.html)用于为[GraphQL API](../api/graphql/index.html)做出贡献 +* [Sidekiq guidelines](sidekiq_style_guide.html) for working with Sidekiq workers +* [Working with Gitaly](gitaly.html) +* [Manage feature flags](feature_flags/index.html) +* [Licensed feature availability](licensed_feature_availability.html) +* [Dealing with email/mailers](emails.html) +* GitLab 代码库中的[Shell 命令](shell_commands.html) +* [`Gemfile` guidelines](gemfile.html) +* [Pry debugging](pry_debugging.html) +* [Sidekiq debugging](sidekiq_debugging.html) +* [Accessing session data](session.html) +* 要避免的[陷阱](gotchas.html) +* 尽可能[避免使用带有实例变量的模块](module_with_instance_variables.html) +* [How to dump production data to staging](db_dump.html) +* [Working with the GitHub importer](github_importer.html) +* [Import/Export development documentation](import_export.html) +* [Test Import Project](import_project.html) +* [Elasticsearch integration docs](elasticsearch.html) +* [Working with Merge Request diffs](diffs.html) +* [Kubernetes integration guidelines](kubernetes.html) +* [Permissions](permissions.html) +* [Prometheus](prometheus.html) +* [Guidelines for reusing abstractions](reusing_abstractions.html) +* [DeclarativePolicy framework](policies.html) +* [How Git object deduplication works in GitLab](git_object_deduplication.html) +* [Geo development](geo.html) +* [Routing](routing.html) +* [Repository mirroring](repository_mirroring.html) +* [Git LFS](lfs.html) +* [Developing against interacting components or features](interacting_components.html) +* [File uploads](uploads.html) +* [Auto DevOps development guide](auto_devops.html) +* [Mass Inserting Models](mass_insert.html) +* [Value Stream Analytics development guide](value_stream_analytics.html) +* [Issue types vs first-class types](issue_types.html) +* [Application limits](application_limits.html) +* [Redis guidelines](redis.html) +* [Rails initializers](rails_initializers.html) +* [Code comments](code_comments.html) +* [Renaming features](renaming_features.html) +* [Windows Development on GCP](windows.html) +* [Code Intelligence](code_intelligence/index.html) +* [Approval Rules](approval_rules.html) +* [Feature categorization](feature_categorization/index.html) + +## Performance guides[](#performance-guides "Permalink") + +* [仪器](instrumentation.html)用于 Ruby 代码在生产环境中运行 +* 用于编写代码,基准测试和避免某些模式的[性能准则](performance.html) +* [合并请求性能准则,](merge_request_performance_guidelines.html)以确保合并请求不会对 GitLab 性能产生负面影响 +* [分析](profiling.html) URL,使用 Sherlock 评估性能或使用 Bullet 跟踪 N + 1 查询 + +## Database guides[](#database-guides "Permalink") + +See [database guidelines](database/index.html). + +## Integration guides[](#integration-guides "Permalink") + +* [Jira Connect app](integrations/jira_connect.html) +* [Security Scanners](integrations/secure.html) +* [Secure Partner Integration](integrations/secure_partner_integration.html) +* [How to run Jenkins in development environment](integrations/jenkins.html) + +## Testing guides[](#testing-guides "Permalink") + +* [Testing standards and style guidelines](testing_guide/index.html) +* [Frontend testing standards and style guidelines](testing_guide/frontend_testing.html) + +## Refactoring guides[](#refactoring-guides "Permalink") + +* [Refactoring guidelines](refactoring_guide/index.html) + +## Documentation guides[](#documentation-guides "Permalink") + +* [Writing documentation](documentation/index.html) +* [Documentation style guide](documentation/styleguide.html) +* [Markdown](../user/markdown.html) + +## Internationalization (i18n) guides[](#internationalization-i18n-guides "Permalink") + +* [Introduction](i18n/index.html) +* [Externalization](i18n/externalization.html) +* [Translation](i18n/translation.html) + +## Telemetry guides[](#telemetry-guides "Permalink") + +* [Telemetry guide](telemetry/index.html) +* [Usage Ping guide](telemetry/usage_ping.html) +* [Snowplow guide](telemetry/snowplow.html) + +## Experiment guide[](#experiment-guide "Permalink") + +* [Introduction](experiment_guide/index.html) + +## Build guides[](#build-guides "Permalink") + +* [Building a package for testing purposes](build_test_package.html) + +## Compliance[](#compliance "Permalink") + +* [许可](licensing.html)确保许可证合规性 + +## Go guides[](#go-guides "Permalink") + +* [Go Guidelines](go_guide/index.html) + +## Shell Scripting guides[](#shell-scripting-guides "Permalink") + +* [Shell scripting standards and style guidelines](shell_scripting_guide/index.html) + +## Domain-specific guides[](#domain-specific-guides "Permalink") + +* [CI/CD development documentation](cicd/index.html) + +## Other Development guides[](#other-development-guides "Permalink") + +* [Defining relations between files using projections](projections.html) +* [Reference processing](./reference_processing.html) +* [Compatibility with multiple versions of the application running at the same time](multi_version_compatibility.html) + +## Other GitLab Development Kit (GDK) guides[](#other-gitlab-development-kit-gdk-guides "Permalink") + +* [Run full Auto DevOps cycle in a GDK instance](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/auto_devops.md) +* [Using GitLab Runner with the GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/runner.md) +* [Using the Web IDE terminal with the GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/web_ide_terminal_gdk_setup.md) \ No newline at end of file diff --git a/_book/docs/550.md b/_book/docs/550.md new file mode 100644 index 0000000000000000000000000000000000000000..bdb34695b888d9172f61fe2296d663840047aed0 --- /dev/null +++ b/_book/docs/550.md @@ -0,0 +1,169 @@ +# Contribute to GitLab + +> 原文:[https://docs.gitlab.com/ee/development/contributing/](https://docs.gitlab.com/ee/development/contributing/) + +* [Security vulnerability disclosure](#security-vulnerability-disclosure) +* [Code of conduct](#code-of-conduct) +* [Closing policy for issues and merge requests](#closing-policy-for-issues-and-merge-requests) +* [Helping others](#helping-others) +* [How to contribute](#how-to-contribute) + * [GitLab Development Kit](#gitlab-development-kit) + * [Contribution flow](#contribution-flow) + * [Issues workflow](#issues-workflow) + * [Merge requests workflow](#merge-requests-workflow) +* [Style guides](#style-guides) +* [Implement design & UI elements](#implement-design--ui-elements) +* [Contribute documentation](#contribute-documentation) +* [Getting an Enterprise Edition License](#getting-an-enterprise-edition-license) + +# Contribute to GitLab[](#contribute-to-gitlab "Permalink") + +感谢您有兴趣为 GitLab 做贡献. 本指南详细介绍了如何以每个人都容易的方式为 GitLab 做出贡献. + +For a first-time step-by-step guide to the contribution process, see our [Contributing to GitLab](https://about.gitlab.com/community/contribute/) page. + +寻找工作吗? 有关更多信息,请参见[如何贡献](#how-to-contribute)部分. + +GitLab 有两种口味: + +* GitLab 社区版(CE),我们的免费和开源版本. +* GitLab 企业版(EE),这是我们的商业版. + +在本指南中,您将看到对 CE 和 EE 的缩写的引用. + +要获得 GitLab 社区成员资格的概述,包括那些会审核或合并您的贡献的成员,请访问[社区角色页面](community_roles.html) . + +如果您想知道 GitLab [核心团队的](https://about.gitlab.com/community/core-team/)运作方式,请参阅[GitLab 贡献过程](https://gitlab.com/gitlab-org/gitlab/blob/master/PROCESS.md) . + +GitLab Inc 工程师应参考[工程工作流程文档](https://about.gitlab.com/handbook/engineering/workflow/) . + +## Security vulnerability disclosure[](#security-vulnerability-disclosure "Permalink") + +将可疑的安全漏洞[秘密](https://about.gitlab.com/security/disclosure/)报告给`support@gitlab.com` ,另请参阅[GitLab.com 网站上的](https://about.gitlab.com/security/disclosure/) " [披露"部分](https://about.gitlab.com/security/disclosure/) . + +**危险:** **不要**为疑似安全漏洞公开可见的问题. + +## Code of conduct[](#code-of-conduct "Permalink") + +我们希望为每个有志于贡献的人营造一个温馨的环境. 请访问我们的[《行为准则》页面,](https://about.gitlab.com/community/contribute/code-of-conduct/)以了解有关我们对开放友好环境的承诺的更多信息. + +## Closing policy for issues and merge requests[](#closing-policy-for-issues-and-merge-requests "Permalink") + +GitLab 是一个受欢迎的开源项目,处理问题和合并请求的能力有限. 出于对我们志愿者的尊重,不符合本文档所列准则的问题和合并请求可能会被关闭,恕不另行通知. + +以礼貌和尊重的态度对待我们的志愿者,这将大大有助于您解决问题. + +发行和合并请求应使用英语,并包含适合所有年龄段受众的语言. + +如果贡献者不再主动处理提交的合并请求,我们可以: + +* 决定合并请求将由我们的[合并请求指导者之一完成](https://about.gitlab.com/company/team/) . +* 关闭合并请求. + +我们根据更改对我们的产品愿景的重要性来做出此决定. 如果合并请求教练将要完成合并请求,我们指定`~coach will finish`标签. + +当团队成员选择社区贡献时,我们会通过添加一个记入作者的更改日志条目来记入原始作者,并有选择地将原始作者包括在 MR 中的至少一项提交中. + +## Helping others[](#helping-others "Permalink") + +可以的话,请帮助其他 GitLab 用户. 人们用于寻求帮助的方法可以在" [获得帮助"页面](https://about.gitlab.com/get-help/)上找到. + +注册邮件列表,在 StackOverflow 上回答 GitLab 问题,或在 IRC 频道中回复. + +## How to contribute[](#how-to-contribute "Permalink") + +如果您想为 GitLab 做出贡献: + +* [`~Accepting merge requests`标签的问题](issue_workflow.html#label-for-community-contributors)是一个很好的起点. +* 请查阅" [贡献流"](#contribution-flow)部分以了解该过程. + +如果您有任何疑问或需要帮助,请访问" [获得帮助"](https://about.gitlab.com/get-help/)以了解如何与 GitLab 进行通信. 我们有一个[供参与者](https://gitter.im/gitlab/contributors)使用的[Gitter 通道](https://gitter.im/gitlab/contributors) ,但是相对于实时通信,我们更喜欢[异步](https://about.gitlab.com/handbook/communication/#internal-communication)通信. + +感谢您的贡献! + +### GitLab Development Kit[](#gitlab-development-kit "Permalink") + +GitLab 开发套件(GDK)可帮助贡献者使用所有必需的依赖项来运行本地 GitLab 实例. 在提出合并请求之前,它可以用于测试对 GitLab 和相关项目的更改. + +有关更多信息,请参见[`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit)项目. + +### Contribution flow[](#contribution-flow "Permalink") + +对 GitLab 进行贡献的一般流程是: + +1. [创建一个](../../user/project/repository/forking_workflow.html#creating-a-fork) GitLab [的叉子](../../user/project/repository/forking_workflow.html#creating-a-fork) . 在某些情况下,您将需要设置[GitLab 开发套件](https://gitlab.com/gitlab-org/gitlab-development-kit)以[针对 fork](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/index.md#develop-in-your-own-gitlab-fork)进行[开发](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/index.md#develop-in-your-own-gitlab-fork) . +2. 在叉子上进行更改. +3. 准备就绪后, [创建一个新的合并请求](../../user/project/merge_requests/creating_merge_requests.html) . +4. 在合并请求的描述中: + * 确保您提供完整而准确的信息. + * 查看提供的清单. +5. 将合并请求(如果可能)分配给相关项目的[代码所有者](../../user/project/code_owners.html)之一或`@mention` ,并说明您已准备好进行审查. + +当您向 GitLab 提交代码时,我们真的希望它被合并! 但是,我们始终会仔细审查提交的内容,这需要时间. 合并之前,代码提交通常会由两位[领域专家](../code_review.html#domain-experts)进行审核: + +* A [reviewer](../code_review.html#the-responsibility-of-the-reviewer). +* A [maintainer](../code_review.html#the-responsibility-of-the-maintainer). + +提交合并请求时,请牢记以下几点: + +* 当审阅者阅读合并请求时,他们可能会要求其他审阅者提供指导. +* 如果发现代码质量不符合 GitLab 的标准,则合并请求审阅者将提供指导,并将作者推荐给我们: + * [文档](../documentation/styleguide.html)样式指南. + * 代码样式指南. +* 有时会遵循样式指南,但是代码将缺乏结构完整性,或者审阅者会对​​代码的整体质量有所保留. 如有保留,审阅者将通知作者并提供一些指导. +* 尽管 GitLab 通常允许任何人表明对合并请求的[批准](../../user/project/merge_requests/merge_request_approvals.html) ,但是维护者在合并合并请求之前可能需要[获得某些审阅者的批准](../code_review.html#approval-guidelines) . +* 审核后,可能会要求作者更新合并请求. 合并请求更新并重新分配给审阅者后,他们将再次审阅代码. 在合并之前,此过程可以重复任意次数,以帮助做出最佳的贡献. + +有时,维护者可能会选择关闭合并请求. 他们将充分披露为什么不合并的原因以及一些指导. 维护人员将公开讨论如何更改代码,以便将来可以批准和合并. + +manbetx 客户端打不开将尽其所能尽快审查社区贡献. 专门任命的开发人员每天审查社区贡献. 在[团队页面上](https://about.gitlab.com/company/team/)查看合并请求指导者,他专门研究您编写的代码类型,并在合并请求中提及他们. 例如,如果您编写了一些前端代码,则应`@mention`前端合并请求指导程序. 如果您的代码具有多个学科,则可以`@mention`多个合并请求指导. + +GitLab 收到了很多社区的贡献. 如果您的代码在其初次提交后的两个工作日内仍未得到审查,请`@mention`与`@gitlab-org/coaches`合并的所有请求`@gitlab-org/coaches`引起他们的注意. + +在向 GitLab 提交代码时,您可能会觉得您的贡献需要外部库的帮助. 如果您的代码包含外部库,请提供该库的链接,以及包含该库的原因. + +`@mention`维护者在合并请求中包含: + +* 超过 500 种变化. +* 任何重大变化. +* 外部库. + +如果您不确定要提及谁,则审阅者将在合并请求过程的早期为您完成此操作. + +#### Issues workflow[](#issues-workflow "Permalink") + +This [documentation](issue_workflow.html) outlines the current issue workflow: + +* [Issue tracker guidelines](issue_workflow.html#issue-tracker-guidelines) +* [Issue triaging](issue_workflow.html#issue-triaging) +* [Labels](issue_workflow.html#labels) +* [Feature proposals](issue_workflow.html#feature-proposals) +* [Issue weight](issue_workflow.html#issue-weight) +* [Regression issues](issue_workflow.html#regression-issues) +* [Technical and UX debt](issue_workflow.html#technical-and-ux-debt) +* [Technical debt in follow-up issues](issue_workflow.html#technical-debt-in-follow-up-issues) + +#### Merge requests workflow[](#merge-requests-workflow "Permalink") + +本[文档](merge_request_workflow.html)概述了当前的合并请求过程. + +* [Merge request guidelines](merge_request_workflow.html#merge-request-guidelines) +* [Contribution acceptance criteria](merge_request_workflow.html#contribution-acceptance-criteria) +* [Definition of done](merge_request_workflow.html#definition-of-done) +* [Dependencies](merge_request_workflow.html#dependencies) + +## Style guides[](#style-guides "Permalink") + +本[文档](style_guides.html)概述了当前的样式准则. + +## Implement design & UI elements[](#implement-design--ui-elements "Permalink") + +本[设计文档](design.html)概述了实现设计和 UI 元素的当前过程. + +## Contribute documentation[](#contribute-documentation "Permalink") + +有关如何编写文档的信息,请参见 GitLab [文档指南](../documentation/index.html) . + +## Getting an Enterprise Edition License[](#getting-an-enterprise-edition-license "Permalink") + +如果您需要用于贡献 EE 功能的许可证,请参阅[相关信息](https://about.gitlab.com/handbook/marketing/community-relations/code-contributor-program/#for-contributors-to-the-gitlab-enterprise-edition-ee) . \ No newline at end of file diff --git a/_book/docs/551.md b/_book/docs/551.md new file mode 100644 index 0000000000000000000000000000000000000000..e45d42b60f42831f088ea5fafcfdb31ab8e7160a --- /dev/null +++ b/_book/docs/551.md @@ -0,0 +1,20 @@ +# Community members & roles + +> 原文:[https://docs.gitlab.com/ee/development/contributing/community_roles.html](https://docs.gitlab.com/ee/development/contributing/community_roles.html) + +# Community members & roles[](#community-members--roles "Permalink") + +GitLab 社区成员及其特权/责任. + +| Roles | Responsibilities | Requirements | +| --- | --- | --- | +| Maintainer | 接受多个 GitLab 项目的合并请求 | 添加到[团队页面](https://about.gitlab.com/company/team/) . 代码审查专家并了解产品/代码库 | +| Reviewer | 在 MR 上执行代码审查 | 添加到[团队页面](https://about.gitlab.com/company/team/) | +| Developer | 可以访问 GitLab 内部基础设施和问题(例如与 HR 相关的问题) | GitLab 员工或核心团队成员(具有 NDA) | +| Contributor | 可以为所有 GitLab 公共项目做出贡献 | 有一个 GitLab.com 帐户 | + +[List of current reviewers/maintainers](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce). + +* * * + +[Return to Contributing documentation](index.html) \ No newline at end of file diff --git a/_book/docs/552.md b/_book/docs/552.md new file mode 100644 index 0000000000000000000000000000000000000000..b5fc9831e74a62ba5a7d5d5d6d579c34e6e95d00 --- /dev/null +++ b/_book/docs/552.md @@ -0,0 +1,30 @@ +# Implement design & UI elements + +> 原文:[https://docs.gitlab.com/ee/development/contributing/design.html](https://docs.gitlab.com/ee/development/contributing/design.html) + +# Implement design & UI elements[](#implement-design--ui-elements "Permalink") + +有关在 GitLab 上实现 UX 的指导,请参阅我们的[设计系统](https://design.gitlab.com/) . + +The UX team uses labels to manage their workflow. + +问题上的〜" UX"标签向 UX 团队发出信号,表明它将需要 UX 注意. 为了更好地了解 UX 解决问题的优先级,请参阅手册的[UX 部分](https://about.gitlab.com/handbook/engineering/ux/) . + +解决问题并准备好进行开发后,UXer 会删除〜" UX"标签,并将〜" UX ready"标签应用于该问题. + +有一个特殊类型的标签,称为〜"产品发现",用于 UX,PM,FE 和 BE. 它代表讨论问题和潜在解决方案的发现问题. 该问题的最终输出可能是需求文档,设计工件,甚至是原型. 该解决方案将在随后的里程碑中开发. + +〜"产品发现"问题与其他任何问题一样,并且在当前里程碑中安排时,应包含里程碑标签,〜"可交付成果"或〜"伸展". + +The initial issue should be about the problem we are solving. 最初的问题应该与我们正在解决的问题有关. If a separate [product discovery issue](https://about.gitlab.com/handbook/engineering/ux/ux-department-workflow/#how-we-use-labels) is needed for additional research and design work, it will be created by a PM or UX person. 如果需要其他[产品发现问题](https://about.gitlab.com/handbook/engineering/ux/ux-department-workflow/#how-we-use-labels)来进行其他研究和设计工作,则将由 PM 或 UX 用户创建. Assign the ~UX, ~"product discovery" and ~"Deliverable" labels, add a milestone and use a title that makes it clear that the scheduled issue is product discovery (for example, `Product discovery for XYZ` ). 分配〜UX,〜"产品发现"和〜"可交付成果"标签,添加一个里程碑,并使用标题清楚地表明计划的问题是产品发现(例如, `Product discovery for XYZ` ). + +为了解决发行版中的产品发现问题,您必须完成以下操作: + +1. UXer 删除〜UX 标签,添加〜" UX ready"标签. +2. 修改产品发现问题中的问题描述以包含最终设计. 如果有道理,可以将指示设计需求的原始信息移至下部的"原始信息"部分. +3. 将设计复制到为其创建了产品发现问题的交付问题的描述中. 不要简单地将产品发现问题称为独立的事实来源. +4. 在某些情况下,产品发现问题还标识了将来的增强功能,这些增强功能不会包含在起源产品发现问题的问题中. 对于这些项目,请创建包含设计的新问题,以确保它们不会丢失. 如果这些问题是好的想法,则将这些问题放在待办事项中. 否则,将它们分类. + +* * * + +[Return to Contributing documentation](index.html) \ No newline at end of file diff --git a/_book/docs/553.md b/_book/docs/553.md new file mode 100644 index 0000000000000000000000000000000000000000..f12dd9299a43c8234e74a72caaa2838b572e4095 --- /dev/null +++ b/_book/docs/553.md @@ -0,0 +1 @@ +> 原文:[https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/README.md](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/README.md) \ No newline at end of file diff --git a/_book/docs/554.md b/_book/docs/554.md new file mode 100644 index 0000000000000000000000000000000000000000..7ee906595f646d6539733eeffb0fa41ad2ee4c9b --- /dev/null +++ b/_book/docs/554.md @@ -0,0 +1,338 @@ +# Issues workflow + +> 原文:[https://docs.gitlab.com/ee/development/contributing/issue_workflow.html](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html) + +* [Issue tracker guidelines](#issue-tracker-guidelines) +* [Issue triaging](#issue-triaging) +* [Labels](#labels) + * [Type labels](#type-labels) + * [Facet labels](#facet-labels) + * [Stage labels](#stage-labels) + * [Naming and color convention](#naming-and-color-convention) + * [Group labels](#group-labels) + * [Naming and color convention](#naming-and-color-convention-1) + * [Category labels](#category-labels) + * [Naming and color convention](#naming-and-color-convention-2) + * [Feature labels](#feature-labels) + * [Naming and color convention](#naming-and-color-convention-3) + * [Department labels](#department-labels) + * [Team labels](#team-labels) + * [Naming and color convention](#naming-and-color-convention-4) + * [Specialization labels](#specialization-labels) + * [Release scoping labels](#release-scoping-labels) + * [Priority labels](#priority-labels) + * [Severity labels](#severity-labels) + * [Label for community contributors](#label-for-community-contributors) + * [Stewardship label](#stewardship-label) +* [Feature proposals](#feature-proposals) +* [Issue weight](#issue-weight) +* [Regression issues](#regression-issues) +* [Technical and UX debt](#technical-and-ux-debt) +* [Technical debt in follow-up issues](#technical-debt-in-follow-up-issues) + +# Issues workflow[](#issues-workflow "Permalink") + +## Issue tracker guidelines[](#issue-tracker-guidelines "Permalink") + +在提交您自己**[的问题](https://gitlab.com/gitlab-org/gitlab/-/issues)**之前,请**[在问题跟踪器中](https://gitlab.com/gitlab-org/gitlab/-/issues)**搜索类似的条目,否则很有可能其他人也有相同的问题或功能建议. 通过奖励表情符号显示您的支持和/或参加讨论. + +请使用问题跟踪器提供的["错误"问题模板](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/issue_templates/Bug.md)提交错误. 括号中的文字可以帮助您添加内容. 提交实际问题时将其忽略. 您可以复制粘贴它,然后根据需要进行编辑. + +## Issue triaging[](#issue-triaging "Permalink") + +我们的问题分诊政策[在手册中](https://about.gitlab.com/handbook/engineering/quality/issue-triage/)有所[描述](https://about.gitlab.com/handbook/engineering/quality/issue-triage/) . 非常欢迎您帮助 GitLab 团队分类问题. 我们还每季度组织一次[bash 事件](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/17815) . + +最重要的是确保有效问题得到开发团队的反馈. 因此,优先考虑的是可以为这些问题提供帮助的开发人员. 请从[GitLab 团队中](https://about.gitlab.com/company/team/)选择具有相关经验的[人员](https://about.gitlab.com/company/team/) . 如果没有人提到这种专业知识,请在提交历史中查找受影响的文件以找到某人. + +我们还使用[GitLab Triage](https://gitlab.com/gitlab-org/gitlab-triage)来自动化一些分类策略. 当前已将其设置为在其上运行的计划管道( `https://gitlab.com/gitlab-org/quality/triage-ops/pipeline_schedules/10512/editpipeline_schedules/10512/edit` ,必须至少具有开发人员访问项目的权限) [质量/分类操作](https://gitlab.com/gitlab-org/quality/triage-ops)项目. + +## Labels[](#labels "Permalink") + +To allow for asynchronous issue handling, we use [milestones](https://gitlab.com/groups/gitlab-org/-/milestones) and [labels](https://gitlab.com/gitlab-org/gitlab/-/labels). Leads and product managers handle most of the scheduling into milestones. Labeling is a task for everyone. + +大多数问题的标签至少包含以下之一: + +* 类型: `~feature` , `~bug` , `~backstage` , `~documentation`等. +* 阶段: `~"devops::plan"` , `~"devops::create"`等 +* 组: `~"group::source code"` , `~"group::knowledge"` , `~"group::editor"`等 +* 类别: `~"Category:Code Analytics"` , `~"Category:DevOps Score"` , `~"Category:Templates"`等 +* 特点: `~wiki` , `~ldap` , `~api` , `~issues` , `~"merge requests"` ,等等. +* Department: `~UX`, `~Quality` +* Team: `~"Technical Writing"`, `~Delivery` +* Specialization: `~frontend`, `~backend`, `~documentation` +* 发布范围: `~Deliverable` , `~Stretch` , `~"Next Patch Release"` +* Priority: `~P1`, `~P2`, `~P3`, `~P4` +* 严重性: `S1` , `~S2` , `~S3` , `~S4` + +所有标签,其含义和优先级均在[标签页面](https://gitlab.com/gitlab-org/gitlab/-/labels)上定义. + +如果您遇到的问题都不存在,并且可以设置标签,则可以*随时*添加类型,阶段,组以及类别/功能标签. + +### Type labels[](#type-labels "Permalink") + +类型标签非常重要. 他们定义了这是什么类型的问题. 每个问题都应该只有一个. + +当前的类型标签为: + +* ~feature +* ~bug +* ~backstage +* 〜"支持请求" +* ~meta +* ~documentation + +许多类型标签都分配了优先级,这会根据其重要性自动使它们浮动到顶部. + +类型标签始终是小写字母,并且可以具有除蓝色(已为类别标签保留)以外的任何颜色. + +[标签页面](https://gitlab.com/groups/gitlab-org/-/labels)上的描述说明了每种类型标签下的内容. + +GitLab 手册记录了[什么是错误](https://about.gitlab.com/handbook/product/product-processes/#bug-issues)以及[什么是功能请求](https://about.gitlab.com/handbook/product/product-processes/#feature-issues) . + +### Facet labels[](#facet-labels "Permalink") + +有时,改进问题的类型很有用. 在这种情况下,您可以添加构面标签. + +以下是构面标签的非详尽列表: + +* 增强功能:此标签可以完善具有功能标签的问题. +* 〜" master:broken":此标签可以细化带有〜bug 标签的问题. +* 〜" failure :: flaky-test":此标签可以细化带有〜bug 标签的问题. +* 〜"技术债务":此标签可以完善具有〜后台标签的问题. +* 〜"静态分析":此标签可以细化具有〜backstage 标签的问题. +* 〜" ci-build":此标签可以优化具有〜backstage 标签的问题. +* 〜性能:性能问题可能描述〜错误或〜功能. +* 〜安全性:一个安全性问题可以描述一个 bug 或一个功能. +* 数据库:数据库问题可能描述错误或功能. +* 〜customer:这与客户创建的或客户感兴趣的问题有关. +* 〜" UI 文本":在 UI 内添加或修改任何文本的问题,例如用户辅助显微镜,按钮/菜单标签或错误消息. + +### Stage labels[](#stage-labels "Permalink") + +阶段标签指定问题属于哪个[阶段](https://about.gitlab.com/handbook/product/product-categories/#hierarchy) . + +#### Naming and color convention[](#naming-and-color-convention "Permalink") + +舞台标签遵守`devops::`命名约定. ``是阶段密钥,因为它位于[https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml)的单个真相来源中,其中`_`替换为空间. + +例如," Manage"阶段由`gitlab-org`组中的`~"devops::manage"`标签表示,因为它的关键`stages`是`manage` . + +通过[在标签列表中搜索`devops::`](https://gitlab.com/groups/gitlab-org/-/labels?search=devops::)可以找到当前阶段的标签. + +这些标签是[作用域标签](../../user/project/labels.html#scoped-labels-premium) ,因此是互斥的. + +舞台标签用于自动生成[方向页面](https://about.gitlab.com/direction/) . + +### Group labels[](#group-labels "Permalink") + +组标签指定了问题所属的[组](https://about.gitlab.com/company/team/structure/#product-groups) . + +强烈建议添加一个组标签,因为我们的分类自动化会使用它来[推断正确的舞台标签](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#auto-labelling-of-issues) . + +#### Naming and color convention[](#naming-and-color-convention-1 "Permalink") + +组标签遵循`group::`命名约定,其颜色为`#A8D695` . ``是组密钥,因为它位于[https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml 的](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml)组的单个真实来源中,其中已替换`_`与空间. + +例如," Continuous Integration"组由`gitlab-org`组中的〜" group :: continuous integration"标签表示,因为它的关键在`stages.manage.groups`下是`continuous_integration` . + +通过[在标签列表中搜索`group::`](https://gitlab.com/groups/gitlab-org/-/labels?search=group::)可以找到当前的组标签. + +这些标签是[作用域标签](../../user/project/labels.html#scoped-labels-premium) ,因此是互斥的. + +您可以在" [产品阶段","组"和"类别"](https://about.gitlab.com/handbook/product/product-categories/)页面中找到列出的[组](https://about.gitlab.com/handbook/product/product-categories/) . + +我们使用术语组来映射产品阶段中的产品需求. 当团队需要某种方式来收集其成员计划分配的工作时,我们可以使用`~group::`标签来完成. + +通常,舞台标签和组标签之间存在 1:1 的关系. 本着"人人都可以贡献"的精神,任何问题都可以由任何团体根据当前的优先事项来解决. 拾取属于其他组的问题时,应重新标记. 例如,如果计划阶段的"访问"组中的某人拾取了标有`~"devops::create"`和`~"group::knowledge"`的问题,则应在发布该问题时将其重新标记为`~"group::access"`保持原始`~"devops::create"`不变. + +我们还使用阶段标签和组标签来帮助量化[吞吐量](https://about.gitlab.com/handbook/engineering/management/throughput/) . 请阅读[吞吐量中的阶段和组标签,](https://about.gitlab.com/handbook/engineering/management/throughput/#stage-and-group-labels-in-throughput)以获取有关在这种情况下如何使用标签的更多信息. + +### Category labels[](#category-labels "Permalink") + +在手册的" [产品阶段,组和类别"](https://about.gitlab.com/handbook/product/product-categories/#hierarchy)页面中: + +> 类别是高级功能,可能是另一家公司的独立产品. 例如投资组合管理. + +强烈建议添加类别标签,因为我们的分类自动化会使用它来[推断正确的组和阶段标签](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#auto-labelling-of-issues) . + +如果您是特定领域的专家,则可以更轻松地找到要解决的问题. 您还可以订阅这些标签,以在每次用与您的专业知识相对应的类别标签标记问题时接收电子邮件. + +#### Naming and color convention[](#naming-and-color-convention-2 "Permalink") + +类别标签遵循" `Category:`命名约定,其颜色为`#428BCA` . ``是类别名称,因为它位于[https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml 的](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml)类别的唯一真实来源中. + +例如," DevOps 分数"类别由`gitlab-org`组中的〜" Category:DevOps 分数"标签表示,因为其`devops_score.name`值为" DevOps 分数". + +如果类别的标签不遵守此命名约定,则应在[https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml 中](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml)使用[`label`属性](https://about.gitlab.com/handbook/marketing/website/#category-attributes)指定它. + +### Feature labels[](#feature-labels "Permalink") + +From the handbook’s [Product stages, groups, and categories](https://about.gitlab.com/handbook/product/product-categories/#hierarchy) page: + +> 特点:小型,离散功能. 例如发行权重. 括号中列出了一些常用功能,以帮助通过关键字查找负责任的 PM. + +如果没有类别标签,强烈建议添加功能标签,因为我们的分类自动分类系统会使用该功能标签来[推断正确的组和阶段标签](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#auto-labelling-of-issues) . + +如果您是特定领域的专家,则可以更轻松地找到要解决的问题. 您还可以订阅这些标签,以在每次问题被标记有与您的专业知识相对应的功能标签时接收电子邮件. + +特征标签的例子是`~wiki` , `~ldap` , `~api` , `~issues` , `~"merge requests"`等. + +#### Naming and color convention[](#naming-and-color-convention-3 "Permalink") + +功能标签全部为小写. + +### Department labels[](#department-labels "Permalink") + +当前部门标签为: + +* ~UX +* ~Quality + +### Team labels[](#team-labels "Permalink") + +**重要提示** :现在不推荐使用大多数历史团队标签(例如"管理","计划"等),而推荐使用" [组"标签](#group-labels)和" [阶段"标签](#stage-labels) . + +团队标签指定负责此问题的团队. 分配团队标签可确保问题引起适当人员的注意. + +当前的团队标签为: + +* ~Delivery +* 〜"技术写作" + +#### Naming and color convention[](#naming-and-color-convention-4 "Permalink") + +团队标签始终大写,以便显示为任何问题的第一个标签. + +### Specialization labels[](#specialization-labels "Permalink") + +这些标签缩小了工作单元的[专业](https://about.gitlab.com/company/team/structure/#specialist)范围. + +* ~frontend +* ~backend +* ~documentation + +### Release scoping labels[](#release-scoping-labels "Permalink") + +发布范围界定标签有助于我们清楚地传达对发布工作的期望. 发行范围界定标签分为三个级别: + +* 〜可交付成果:预期在当前里程碑中交付的问题. +* 〜延伸:问题是实现当前里程碑的延伸目标. 如果当前发行版中未解决这些问题,则强烈考虑将它们用于下一个发行版. +* 〜"下一个补丁程序发行版":下一个补丁程序发行版中的问题. 首先进行处理,然后将`~"Pick into XY"`标签添加到合并请求中,并添加适当的里程碑. + +为当前里程碑计划的每个发行都应标记为〜Deliverable 或〜" Stretch". 上一个里程碑的所有未解决问题都应标记为"下一个补丁发布",或以其他方式重新安排到另一个里程碑. + +### Priority labels[](#priority-labels "Permalink") + +我们具有以下优先级标签: + +* ~P1 +* ~P2 +* ~P3 +* ~P4 + +请参阅手册中的问题分类[优先级标签](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#priority)部分,以了解其用法. + +### Severity labels[](#severity-labels "Permalink") + +我们具有以下严重性标签: + +* ~S1 +* ~S2 +* ~S3 +* ~S4 + +请参阅手册中的问题分类[优先级标签](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#severity)部分,以了解其用法. + +### Label for community contributors[](#label-for-community-contributors "Permalink") + +我们目前没有能力或不想给予优先考虑的对用户有益的问题" nice to haves"被标记为"正在接受合并请求",以便社区可以做出贡献. + +社区贡献者可以针对他们想要的任何问题提交合并请求,但是〜"接受合并请求"标签具有特殊含义. 它指出了以下变化: + +1. 我们已经达成共识, +2. 定义明确 +3. 可能会被维护者接受. + +我们希望避免出现以下情况:投稿人选择〜"接受合并请求"问题,然后关闭他们的合并请求,因为我们意识到它不符合我们的愿景,或者我们想以其他方式解决它. + +我们会自动将〜"接受合并请求"标签添加到与[分类策略](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#accepting-merge-requests)匹配的问题. + +我们建议从未参与过任何开源项目的人员寻找标有`~"Accepting merge requests"`且[权重为 1](https://gitlab.com/groups/gitlab-org/-/issues?state=opened&label_name[]=Accepting+merge+requests&assignee_id=None&sort=weight&weight=1)或带有`~"Good for 1st time contributors"` [标签的](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=✓&state=opened&label_name[]=Good for 1st time contributors&assignee_id=None)问题. 我们欢迎更多有经验的贡献者[与他们](https://gitlab.com/groups/gitlab-org/-/issues?state=opened&label_name[]=Accepting+merge+requests&assignee_id=None)一起解决. + +如果您决定要解决某个问题,请@-提及[适当的产品经理](https://about.gitlab.com/handbook/product/#who-to-talk-to-for-what) . 然后,产品经理将邀请适当的 GitLab 团队成员进一步讨论范围,设计和技术注意事项. 这将确保您的贡献与 GitLab 产品保持一致,并最大程度地减少返工和将其合并到 master 中的延迟. + +在问题上贴上"接受合并请求"标签的 GitLab 团队成员应与负责任的产品经理一起更新问题描述,并邀请上述任何潜在的社区贡献者加入@提及. + +### Stewardship label[](#stewardship-label "Permalink") + +对于与 GitLab 的开源管理有关的问题,有〜"管理"标签. + +该标签将用于解决有关 GitLab 管理问题的问题. 例如,如果 GitLab Inc.计划将 GitLab EE 中的功能添加到 GitLab CE 中,则相关问题将标记为"管理". + +最近的一个例子是[将时间跟踪 API 引入 GitLab CE 的问题](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/25517#note_20019084) . + +## Feature proposals[](#feature-proposals "Permalink") + +要创建功能建议,请在[问题跟踪器](https://gitlab.com/gitlab-org/gitlab/-/issues)上打开[问题](https://gitlab.com/gitlab-org/gitlab/-/issues) . + +为了帮助跟踪功能建议,我们创建了[`feature`](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name=feature)标签. 目前,不是项目成员的用户无法添加标签. 您可以改为要求[核心团队](https://about.gitlab.com/community/core-team/)成员之一在问题上添加标签〜feature,或在描述后的新行中添加以下代码段: `~feature` . + +请使功能建议尽可能小而简单,复杂的建议可能会被编辑以使其小而简单. + +请使用问题跟踪器上提供的["功能建议"问题模板](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/issue_templates/Feature proposal.md)提交功能建议. + +For changes in the interface, it is helpful to include a mockup. Issues that add to, or change, the interface should be given the ~”UX” label. This will allow the UX team to provide input and guidance. You may need to ask one of the [core team](https://about.gitlab.com/community/core-team/) members to add the label, if you do not have permissions to do it by yourself. + +如果您想自己创建一些东西,请考虑首先打开一个问题,讨论将其包含在 GitLab 中是否有趣. + +## Issue weight[](#issue-weight "Permalink") + +问题权重使我们对解决一个或多个问题所需的工作量有所了解. 这样可以更准确地安排工作. + +鼓励您设置任何问题的权重. 遵循以下准则将使其易于管理,而没有不必要的开销. + +1. 尽早设置任何问题的权重 +2. 如果您不同意设定的权重,请与其他开发人员讨论,直到就权重达成共识 +3. 问题权重是问题复杂性的抽象度量. 不要将发行权重直接与时间相关. 这称为[锚定](https://en.wikipedia.org/wiki/Anchoring) ,是您要避免的事情. +4. 权重为 1(或无权重)的东西确实很小而简单. 9 表示正在重写 GitLab 的一个很大的基本部分,这可能会导致许多难以解决的问题. 在 GitLab 中更改某些文本可能是 1,添加新的 Git Hook 可能是 4 或 5,大功能是 7-9. +5. 如果某事物非常大,则应将其拆分为多个问题或大块. 您不能简单地设置父问题的权重,而不能设置子问题的权重. + +## Regression issues[](#regression-issues "Permalink") + +每个月度发行版的 CE 问题跟踪器上都有一个相应的发行版,以跟踪该发行版所破坏的功能以及修补程序发行版中需要包含的所有修补程序(请参阅[8.3 回归](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/4127)示例). + +如问题描述中所概述的那样,预期的工作流程是发布一个注释,其中包含对描述回归的问题的引用,然后通过对合并请求的引用来更新该注释,该合并请求将在发布后对其进行修复. + +如果您是贡献者,没有所需的权限来更新其他用户的注释,请发布新注释,同时提及问题和合并请求. + +发布经理将在解决补丁程序后[更新](https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue)回归问题中[的注释](https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue) . + +## Technical and UX debt[](#technical-and-ux-debt "Permalink") + +为了跟踪可以在 GitLab 的代码库中改进的事物,我们在[GitLab 的问题跟踪器中](https://gitlab.com/gitlab-org/gitlab/-/issues)使用〜"技术债务"标签. 对于错过的用户体验要求,我们使用〜" UX 债务"标签. + +这些标签应添加到描述可以改进的问题,已采取的捷径,需要额外注意的功能以及由于高速发展而遗留下来的所有其他事项的问题上. 例如,需要重构的代码应使用〜"技术债务"标签,根据我们的设计系统准则,未交付的某些产品应使用〜" UX 债务"标签. + +每个人都可以创建一个问题,但是如果您没有权限自行添加,则可能需要请求添加特定标签. 可以将其他标签与这些标签结合使用,以更轻松地计划发布的改进. + +用这些标签标记的问题具有与描述要在 GitLab 中引入的新功能的问题相同的优先级,并且应该安排由适当的人员发布. + +请确保在问题的描述中提及与"技术债务"问题或" UX 债务"问题相关的合并请求. + +## Technical debt in follow-up issues[](#technical-debt-in-follow-up-issues "Permalink") + +在开发新功能时通常会发现技术债务. 本着"最小可行的改变"的精神,通常将解决方案推迟到后续问题上. 但是,这不能用作合并劣质代码的借口,否则这些劣质代码将无法通过审阅,或者忽略了琐事,这些琐事不值得单独安排,最好在原始合并请求中解决-否则完全追踪! + +The overheads of scheduling, and rate of change in the GitLab codebase, mean that the cost of a trivial technical debt issue can quickly exceed the value of tracking it. This generally means we should resolve these in the original merge request - or simply not create a follow-up issue at all. + +例如,在文件之间复制的注释中的错字值得在同一 MR 中修复,但不值得为其创建后续问题. 重命名在许多地方使用的方法以使其意图更清晰可能是值得修复的,但是这种方法不应在同一 MR 中发生,并且通常不值得自己解决. 如果我们要创建这些问题,这些问题将始终标记为`~P4 ~S4` . + +更严重的技术债务可能对发展速度产生影响. 如果不能及时解决,那么代码库将变得不必要地难以更改,新功能也将难以添加,并且大量回归. + +应该认真对待此类技术债务的发现,尽管在后续问题中解决问题可能是适当的,但维护人员通常应从原始 MR 的作者或相关领域的工程或产品经理那里获得调度承诺. . 这可以采取在问题上使用适当的优先级/严重性标签的形式,也可以采用明确的里程碑和受让人的形式. + +维护者必须始终同意,以这种方式解决一个悬而未决的讨论,并且它将是引发问题的人. 标题和描述的质量应[与通常](#technical-and-ux-debt)创建的标题和描述的质量相同-特别是,问题标题**不能**以" `Follow-up`开头! 创建维护者还应该期望在后续问题上开始工作时会有所参与. + +* * * + +[Return to Contributing documentation](index.html) \ No newline at end of file diff --git a/_book/docs/555.md b/_book/docs/555.md new file mode 100644 index 0000000000000000000000000000000000000000..85799fc5d4adf37fbda07aa0b7f723e45d165674 --- /dev/null +++ b/_book/docs/555.md @@ -0,0 +1,176 @@ +# Merge requests workflow + +> 原文:[https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html](https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html) + +* [Merge request guidelines](#merge-request-guidelines) + * [Keep it simple](#keep-it-simple) + * [Commit messages guidelines](#commit-messages-guidelines) +* [Contribution acceptance criteria](#contribution-acceptance-criteria) +* [Definition of done](#definition-of-done) +* [Dependencies](#dependencies) +* [Incremental improvements](#incremental-improvements) + +# Merge requests workflow[](#merge-requests-workflow "Permalink") + +We welcome merge requests from everyone, with fixes and improvements to GitLab code, tests, and documentation. The issues that are specifically suitable for community contributions are listed with the [`Accepting merge requests`](issue_workflow.html#label-for-community-contributors) label, but you are free to contribute to any issue you want. + +请注意,如果在任何时候都为当前里程碑标记了一个问题,即使您正在处理它,则 GitLab Inc.团队成员可能会接管合并请求,以确保工作在发布日期之前完成. + +如果要添加未标记的新功能,最好首先创建一个问题(如果还没有一个问题)并发表评论,要求将其标记为" `Accepting Merge Requests` . 如果还可以更改用户界面,请提供建议功能的屏幕截图或线框. + +合并请求应提交到 GitLab.com 上的相应项目,例如[GitLab](https://gitlab.com/gitlab-org/gitlab/-/merge_requests) , [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests) , [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests)等. + +如果您不熟悉 GitLab 开发(或一般而言的 Web 开发),请参阅" [如何做出贡献"](index.html#how-to-contribute)部分,以开始解决一些潜在的简单问题. + +要开始开发 GitLab,请下载[GitLab 开发套件,](https://gitlab.com/gitlab-org/gitlab-development-kit)并参阅" [开发"部分](../../README.html)以获取所需指南. + +## Merge request guidelines[](#merge-request-guidelines "Permalink") + +如果发现问题,请提交包含修复或改进的合并请求(如果可以),并包括测试. 如果您不知道如何解决该问题,但是可以编写暴露该问题的测试,我们也将接受. 通常,包含回归测试的错误修复将快速合并,而没有适当测试的新功能可能会更慢地接收反馈. 进行合并请求的工作流程如下: + +1. [叉](../../user/project/repository/forking_workflow.html)项目插入 GitLab.com 您的个人命名空间(或一组). +2. 在 fork 中创建一个功能分支(不要使用`master` ). +3. 编写[测试](../rake_tasks.html#run-tests)和代码. +4. [Generate a changelog entry with `bin/changelog`](../changelog.html) +5. 如果要编写文档,请确保遵循[文档准则](../documentation/index.html) . +6. 遵循[提交消息准则](#commit-messages-guidelines) . +7. 如果您有多个提交,请通过[压缩它们](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#_squashing)将它们组合为几个逻辑组织的提交,但是如果您正在共享分支上,则不要更改提交历史记录. +8. 将提交推送到 fork 中的工作分支. +9. 向主 GitLab 项目中的`master`分支提交合并请求(MR). + 1. 您的合并请求至少需要 1 个批准,但是根据您的更改,您可能需要其他批准. 请参阅[批准准则](../code_review.html#approval-guidelines) . + 2. 您不必选择任何特定的批准人,但是如果您确实希望特定的人批准您的合并请求,则可以选择. +10. MR 标题应描述您要进行的更改. +11. MR 说明应说明您进行更改的原因. + 1. 如果您要提供代码,请根据"描述"字段中已经提供的默认模板填写描述. + 2. 如果您要提供文档,请从"选择模板"菜单中选择" `Documentation` ",然后根据模板填写说明. + 3. 提及合并请求解决的问题,合并请求合并后,使用" `Solves #XXX`或" `Closes #XXX`语法[自动关闭](../../user/project/issues/managing_issues.html#closing-issues-automatically)问题. +12. 如果允许,请设置相关的里程碑和[标签](issue_workflow.html) . +13. UI 更改应使用 GitLab 设计系统" [睡衣"中的](https://design.gitlab.com/)可用组件. MR 必须包含" *之前*和*之后"*屏幕截图. +14. 如果 MR 更改了 CSS 类,请包括受影响页面的列表,可以通过运行`grep css-class ./app -R`来找到. +15. 如果您的 MR 触摸了执行 Shell 命令,读取或打开文件或处理磁盘上文件路径的代码,请确保它符合[Shell 命令准则](../shell_commands.html) +16. 如果您的代码在磁盘上创建了新文件,请阅读[共享文件准则](../shared_files.html) . +17. 如果您的合并请求添加了一个或多个迁移,请确保在审阅 MR 之前对新数据库执行所有迁移. 如果检查导致 MR 发生较大变化,请在检查完成后再次执行迁移. +18. 为更复杂的迁移编写测试. +19. 合并请求**必须**遵守[合并请求性能准则](../merge_request_performance_guidelines.html) . +20. 对于使用 Capybara 的测试,请阅读[如何编写可靠的异步集成测试](https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara) . +21. 如果从源安装 GitLab 时,合并请求中引入的更改需要其他步骤, `doc/install/installation.md`在同一合并请求中将它们添加到`doc/install/installation.md`中. +22. 如果您的合并请求引入了从源代码升级 GitLab 时需要其他步骤的更改,请在同一合并请求中将它们添加到`doc/update/upgrading_from_source.md`中. 如果这些说明是特定于版本的,请将它们添加到"特定于版本的升级说明"部分. +23. 阅读并遵守[合并请求作者的责任](../code_review.html#the-responsibility-of-the-merge-request-author) . +24. 阅读并关注[审核您的合并请求](../code_review.html#having-your-merge-request-reviewed) . + +如果您想对合并请求提供快速反馈,请随时提及[核心团队](https://about.gitlab.com/community/core-team/)或[合并请求指导者之一](https://about.gitlab.com/company/team/) . 在审查您的代码以及审查合并请求时,请牢记[代码审查准则](../code_review.html) . 并且,如果您的代码也对数据库进行了更改或进行了昂贵的查询,请查看[数据库复审指南](../database_review.html) . + +### Keep it simple[](#keep-it-simple "Permalink") + +*进行较小的迭代.* 请保持单个 MR 中的更改量**尽可能小** . 如果您想提供较大的功能,请仔细考虑[最小的可行更改](https://about.gitlab.com/handbook/product/#the-minimally-viable-change) . 您可以将功能分为两个较小的 MR 吗? 您只能提交后端/ API 代码吗? 您可以从一个非常简单的 UI 开始吗? 您可以只做一部分重构吗? + +小型 MR 更易于查看,从而导致更高的代码质量,对于 GitLab 而言,这比具有最少的提交日志更为重要. MR 越小,合并的可能性就越大. 之后,您可以发送更多 MR,以增强和扩展功能. Kubernetes 团队的《 [如何获得更快的 PR 评论》](https://github.com/kubernetes/kubernetes/blob/release-1.5/docs/devel/faster_reviews.md)文档也对此有一些建议. + +### Commit messages guidelines[](#commit-messages-guidelines "Permalink") + +编写提交消息时,请遵循以下准则: + +* 提交主题必须包含至少 3 个字. +* 提交主题不得超过 72 个字符. +* 提交主题必须以大写字母开头. +* 提交主题不得以句号结尾. +* 提交主题和正文必须用空白行分隔. +* 提交正文每行不得包含超过 72 个字符. +* 在至少 3 个文件中更改 30 行或更多行的提交必须在提交正文中描述这些更改. +* 提交主题或正文不得包含表情符号. +* 使用问题并合并请求的完整 URL 而不是简短参考,因为它们在 GitLab 之外显示为纯文本. +* 合并请求不得包含超过 10 条提交消息. + +如果不符合指导原则,MR 将不会通过[危险检查](https://gitlab.com/gitlab-org/gitlab/blob/master/danger/commit_messages/Dangerfile) . 有关更多信息,请参见[如何编写 Git 提交消息](https://chris.beams.io/posts/git-commit/) . + +可以在您的计算机上使用的体现以上内容的示例提交消息模板(有关[如何应用 template 的](https://codeinthehole.com/tips/a-useful-template-for-commit-messages/)指南): + +``` +# (If applied, this commit will...) (Max 50 char) +# |<---- Using a Maximum Of 50 Characters ---->| + +# Explain why this change is being made +# |<---- Try To Limit Each Line to a Maximum Of 72 Characters ---->| + +# Provide links or keys to any relevant tickets, articles or other resources +# Use issues and merge requests' full URLs instead of short references, +# as they are displayed as plain text outside of GitLab + +# --- COMMIT END --- +# -------------------- +# Remember to +# Capitalize the subject line +# Use the imperative mood in the subject line +# Do not end the subject line with a period +# Subject must contain at least 3 words +# Separate subject from body with a blank line +# Commits that change 30 or more lines across at least 3 files must +# describe these changes in the commit body +# Do not use Emojis +# Use the body to explain what and why vs. how +# Can use multiple lines with "-" for bullet points in body +# For more information: https://chris.beams.io/posts/git-commit/ +# -------------------- +``` + +## Contribution acceptance criteria[](#contribution-acceptance-criteria "Permalink") + +为确保您的合并请求能够获得批准,请确保其符合以下捐款接受标准: + +1. 更改尽可能小. +2. 包括适当的测试并使所有测试通过(除非它包含暴露现有代码中的错误的测试). 每个新类都应具有相应的单元测试,即使该类是在较高级别上进行的,例如功能测试. + * 如果失败的 CI 构建似乎与您的贡献无关,则可以尝试重新启动失败的 CI 作业,从主服务器重新部署以引入可以解决该失败的更新,或者如果尚未解决,请请开发人员来帮助您修复测试. +3. MR 最初包含一些按逻辑组织的提交. +4. 更改可以合并而不会出现问题. 否则,如果您是功能分支上的唯一成员,则应重新设置基准,否则合并`master` . +5. 仅解决了一个特定问题或实现了一个特定功能. 不要结合东西; 针对每个问题或功能发送单独的合并请求. +6. 迁移应仅做一件事(例如,创建表,将数据移动到新表或删除旧表),以帮助重试失败. +7. 包含其他用户将从中受益的功能. +8. 不要添加配置选项或设置选项,因为它们会使进行和测试将来的更改复杂化. +9. 更改不会降低性能: + * 避免重复轮询需要大量开销的端点. + * 通过 SQL 日志或[`QueryRecorder`](../merge_request_performance_guidelines.html)检查 N + 1 个查询. + * 避免重复访问文件系统. + * 如果需要支持实时功能,可将[轮询与 ETag 缓存一起](../polling.html)使用. +10. 如果合并请求添加了任何新库(宝石,JavaScript 库等),则它们应符合我们的[许可准则](../licensing.html) . 如果" license-finder"测试失败,并且`Dependencies that need approval`错误`Dependencies that need approval`请参阅那些说明. 另外,使审阅者了解新库并解释为什么需要它. +11. 合并请求符合下面的 GitLab [对 done](#definition-of-done)的[定义](#definition-of-done) . + +## Definition of done[](#definition-of-done "Permalink") + +如果您为 GitLab 做贡献,请知道更改不仅涉及代码. 我们使用以下[完成的定义](https://www.agilealliance.org/glossary/definition-of-done) . 在您确定满足所有这些要求之前,您的贡献不会*完成* . + +1. 清晰的说明,说明捐款的相关性. +2. 工作并清理需要注释的代码. +3. 所有通过 CI 服务器的[单元测试,集成测试和系统测试](../testing_guide/index.html) . +4. 测试涵盖了回归和错误,可降低问题再次发生的风险. +5. 遵循[性能准则](../merge_request_performance_guidelines.html) . +6. 遵循[安全编码准则](https://gitlab.com/gitlab-com/gl-security/security-guidelines) . +7. [记录](../documentation/index.html)在`/doc`目录中. +8. 如有必要, [添加了 Changelog 条目](../changelog.html) . +9. 由相关(UX / FE / BE /技术写作)审稿人审阅,并解决所有问题. +10. 由项目维护者合并. +11. 在[基础结构问题跟踪器中](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues)创建问题,以在您的文稿更改默认设置或引入新设置(如果相关)时通知基础结构部门. +12. 部署贡献后,确认已在[Canary 阶段](https://about.gitlab.com/handbook/engineering/#canary-testing)或 GitLab.com 上工作. +13. 添加到[发布中](https://about.gitlab.com/handbook/marketing/blog/release-posts/) (如果相关). +14. 添加到[网站](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/features.yml) (如果相关). +15. 如果需要, [可以](../testing_guide/testing_levels.html#black-box-tests-at-the-system-level-aka-end-to-end-tests)添加[黑盒测试/端到端测试](../testing_guide/testing_levels.html#black-box-tests-at-the-system-level-aka-end-to-end-tests) . 如有任何疑问,请联系[质量团队](https://about.gitlab.com/handbook/engineering/quality/#teams) . + +## Dependencies[](#dependencies "Permalink") + +如果您在 GitLab 中添加了一个依赖项(例如操作系统软件包),请考虑更新以下内容,并在合并请求中注意每个依赖项的适用性: + +1. 请注意[发布博客文章中](https://about.gitlab.com/handbook/marketing/blog/release-posts/)的附加内容(如果尚不存在,请创建一个). +2. [The upgrade guide](../../update/upgrading_from_source.html). +3. The [GitLab Installation Guide](../../install/installation.html#1-packages-and-dependencies). +4. The [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit). +5. The [CI environment preparation](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/prepare_build.sh). +6. The [Omnibus package creator](https://gitlab.com/gitlab-org/omnibus-gitlab). + +## Incremental improvements[](#incremental-improvements "Permalink") + +我们会在工程上花费一些时间来解决小问题(有或没有问题),这些小问题是逐步改进的,例如: + +1. 未经优先考虑的错误修复(例如[,到处都显示有关项目移动的横幅警报](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18985) ) +2. 文档改进 +3. Rubocop 或代码质量改进 + +用〜"应该工作的东西"标记合并请求,以跟踪该区域中的工作. \ No newline at end of file diff --git a/_book/docs/556.md b/_book/docs/556.md new file mode 100644 index 0000000000000000000000000000000000000000..ec5783a0b019e7da856e5a5559ebbc8cc5bd20e6 --- /dev/null +++ b/_book/docs/556.md @@ -0,0 +1,346 @@ +# Code Review Guidelines + +> 原文:[https://docs.gitlab.com/ee/development/code_review.html](https://docs.gitlab.com/ee/development/code_review.html) + +* [Getting your merge request reviewed, approved, and merged](#getting-your-merge-request-reviewed-approved-and-merged) + * [Domain experts](#domain-experts) + * [Reviewer roulette](#reviewer-roulette) + * [Approval guidelines](#approval-guidelines) + * [Security requirements](#security-requirements) + * [The responsibility of the merge request author](#the-responsibility-of-the-merge-request-author) + * [The responsibility of the reviewer](#the-responsibility-of-the-reviewer) + * [The responsibility of the maintainer](#the-responsibility-of-the-maintainer) +* [Best practices](#best-practices) + * [Everyone](#everyone) + * [Having your merge request reviewed](#having-your-merge-request-reviewed) + * [Assigning a merge request for a review](#assigning-a-merge-request-for-a-review) + * [List of merge requests ready for review](#list-of-merge-requests-ready-for-review) + * [Reviewing a merge request](#reviewing-a-merge-request) + * [Merging a merge request](#merging-a-merge-request) + * [The right balance](#the-right-balance) + * [GitLab-specific concerns](#gitlab-specific-concerns) + * [Review turnaround time](#review-turnaround-time) + * [Review-response SLO](#review-response-slo) + * [Customer critical merge requests](#customer-critical-merge-requests) +* [Examples](#examples) + * [Credits](#credits) + +# Code Review Guidelines[](#code-review-guidelines "Permalink") + +本指南包含有关执行代码审查和代码审查的建议和最佳实践. + +无论是由 GitLab 团队成员还是志愿者贡献者编写的所有对 GitLab CE 和 EE 的合并请求,都必须经过代码审查流程,以确保代码有效,可理解,可维护和安全. + +## Getting your merge request reviewed, approved, and merged[](#getting-your-merge-request-reviewed-approved-and-merged "Permalink") + +强烈建议您让您的代码通过**审核** [评审](https://about.gitlab.com/handbook/engineering/workflow/code-review/#reviewer) ,一旦有任何代码评审,获得所选择的解决方案和实施,和一个额外的一双眼睛寻找错误,逻辑问题,或裸露边缘的第二意见案件. + +默认方法是从您的小组或团队中选择一名审阅者进行第一次审阅. 这只是一个建议,审阅者可能来自其他团队. 但是,建议选择一个[领域专家](#domain-experts) . + +您可以在下面有关作者责任的部分中详细了解让审稿人参与的重要性. + +如果您需要一些指导(例如,这是您的第一个合并请求),请随时咨询一位[合并请求教练](https://about.gitlab.com/company/team/) . + +如果您需要有关安全扫描或注释的帮助,请随时在评论中包括安全团队( `@gitlab-com/gl-security` ). + +根据您的合并请求涉及的领域,它必须由一个或多个[维护者](https://about.gitlab.com/handbook/engineering/workflow/code-review/#maintainer) **批准** : + +对于批准,我们使用合并请求小部件中的批准功能. 审阅者可以通过[额外](../user/project/merge_requests/merge_request_approvals.html#adding-or-removing-an-approval)批准来添加其批准. + +让您的合并请求也**合并**需要一个维护者. 如果需要多个批准,则最后一个对其进行审核的维护者也会将其合并. + +### Domain experts[](#domain-experts "Permalink") + +领域专家是在特定技术,产品功能或代码库领域具有丰富经验的团队成员. 鼓励团队成员自认是领域专家,并将其添加到他们的[团队资料中](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/team.yml) + +当自我确定为领域专家时,建议分配更改`team.yml`的 MR,以由已经建立的领域专家或相应的工程经理进行合并. + +对于自动被视为领域专家,我们做出以下假设: + +* 在特定阶段/小组中工作的团队成员(例如,创建:源代码)被视为他们所从事的应用程序领域的领域专家 +* 从事特定功能(例如搜索)的团队成员被视为该功能的领域专家 + +我们默认为具有领域专业知识的团队成员分配评论. 如果没有合适的[领域专家](#domain-experts) ,您可以选择任何团队成员来审核 MR,也可以按照" [审核者"轮盘赌的](#reviewer-roulette)建议进行操作. + +可以在[工程项目](https://about.gitlab.com/handbook/engineering/projects/)页面或[GitLab 团队页面](https://about.gitlab.com/company/team/)上查看团队成员的领域专业知识. + +### Reviewer roulette[](#reviewer-roulette "Permalink") + +[Danger 机器人会](dangerbot.html)为您的合并请求似乎接触的每个代码库区域随机选择一个审阅者和一个维护者. 它仅提出**建议** ,如果您认为其他人更适合,则应予以覆盖! + +它从[工程项目](https://about.gitlab.com/handbook/engineering/projects/)页面的列表中选择审阅者和维护者,具有以下行为: + +1. 它不会选择[GitLab 状态](../user/profile/index.html#current-status)包含字符串'OOO'或表情符号为`:palm_tree:`或`:beach:` . +2. [培训生的维护者](https://about.gitlab.com/handbook/engineering/workflow/code-review/#trainee-maintainer)被[选拔的](https://about.gitlab.com/handbook/engineering/workflow/code-review/#trainee-maintainer)可能性是其他审阅者的三倍. +3. 它始终为相同的分支名称选择相同的审阅者和维护者(除非他们的 OOO 状态更改,如第 1 点所示). 它消除导致`ce-`和`ee-`和尾`-ce`和`-ee` ,以便它可以为反向移植分支稳定. + +### Approval guidelines[](#approval-guidelines "Permalink") + +如下面有关维护者职责的部分所述,建议您让合并请求由具有[域专业知识的](#domain-experts)维护者批准并合并. + +1. 如果您的合并请求包含后端更改( *1* ),则必须**由[后端维护者](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_backend)批准** . +2. 如果您的合并请求包括数据库迁移或对昂贵查询的更改( *2* ),则必须得到**[数据库维护者的](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_database)批准** . 阅读[数据库复查指南](database_review.html)以获取更多详细信息. +3. 如果您的合并请求包含前端更改( *1* ),则必须得到**[前端维护者的](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_frontend)批准** . +4. 如果您的合并请求包括用户体验更改( *1* ),则必须得到用户**[体验团队成员的](https://about.gitlab.com/company/team/)批准** . +5. 如果您的合并请求包括添加新的 JavaScript 库( *1* ),则必须得到**[前端领导的](https://about.gitlab.com/company/team/)批准** . +6. 如果您的合并请求包括添加新的 UI / UX 范例( *1* ),则必须**由[UX 主管](https://about.gitlab.com/company/team/)批准** . +7. 如果您的合并请求包含新的依赖项或文件系统更改,则必须得到**[分发团队成员的](https://about.gitlab.com/company/team/)批准** . 有关更多详细信息,请参见如何与[发行团队](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/#how-to-work-with-distribution)合作. +8. 如果您的合并请求中包含文档更改,则必须根据相应的[产品类别](https://about.gitlab.com/handbook/product/product-categories/) **由[技术撰稿人](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers)批准** . +9. 如果您的合并请求包含端到端**和**非端到端更改( *3* ),则必须**经过[测试中](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors)的[软件工程师的](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors)批准** . +10. 如果您的合并请求仅包含端到端更改( *3* ), **或者**如果 MR 作者是[测试中](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors)的[软件工程师](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) ,则必须得到**[质量维护人员的](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa)批准** + +* ( *1* ):请注意,除 JavaScript 规范以外的其他规范均被视为后端代码. +* ( *2* ):如果您的合并请求可能引入昂贵的查询,我们鼓励您从数据库维护者那里寻求指导. 用 SQL 查询在相关代码行中注释是最有效的,这样他们就可以给出建议. +* ( *3* ):端到端更改包括`qa`目录中的所有文件. + +#### Security requirements[](#security-requirements "Permalink") + +View the updated documentation regarding [internal application security reviews](https://about.gitlab.com/handbook/engineering/security/#internal-application-security-reviews) for **when** and **how** to request a security review. + +### The responsibility of the merge request author[](#the-responsibility-of-the-merge-request-author "Permalink") + +找到最佳解决方案并实施该解决方案的责任在于合并请求作者. + +在将合并请求分配给维护者进行批准和合并之前,他们应该确信: + +* 它实际上解决了本应解决的问题. +* 它以最合适的方式这样做. +* 满足所有要求. +* 没有剩余的错误,逻辑问题,未发现的极端情况或已知的漏洞. + +做到这一点并避免与审阅者不必要的来回交流的最佳方法是,按照[代码审阅](#reviewing-a-merge-request)指南对自己的合并请求进行自审. + +为了使他们的解决方案达到所需的置信度,作者应酌情让其他人参与调查和实施过程. + +鼓励他们与[领域专家联系](#domain-experts) ,讨论不同的解决方案或对实现进行审查,与产品经理和 UX 设计师联系,以消除混乱或验证最终结果是否与他们的想法相符,并与数据库专家联系,以获取有关数据模型或特定查询,或者让任何其他开发人员深入了解该解决方案. + +如果作者不确定合并请求是否需要[领域专家的](#domain-experts)意见,这通常是一个很好的信号,因为如果没有合并请求,将无法达到他们对解决方案所要求的置信度. + +在审阅之前,请作者针对合并请求差异提交评论,以提醒审阅者重要的事项以及需要进一步解释或关注的事项. 可能需要发表评论的内容示例包括: + +* 增加了起毛规则(Rubocop,JS 等). +* 增加了一个库(Ruby gem,JS lib 等). +* 如果不明显,则指向父类或方法的链接. +* 进行任何基准测试以补充变更. +* 潜在的不安全代码. + +Avoid: + +* 除非审阅者要求您将注释(上面引用的或 TODO 项)直接添加到源代码中. 如果由于可执行的任务而添加了注释,则必须包含指向问题的链接. +* 将测试失败的合并请求分配给维护人员. 如果测试失败,则必须分配,请确保在评论中留下说明. +* 通过电子邮件或 Slack 过多提及维护者(如果可以通过 Slack 与维护者联系). 如果您不能分配合并请求,则`@`可以在注释中提及维护者,在所有其他情况下,分配合并请求就足够了. + +This [saves reviewers time and helps authors catch mistakes earlier](https://www.ibm.com/developerworks/rational/library/11-proven-practices-for-peer-review/index.html#__RefHeading__97_174136755). + +### The responsibility of the reviewer[](#the-responsibility-of-the-reviewer "Permalink") + +彻底[检查合并请求](#reviewing-a-merge-request) . 当您确信它满足所有要求时,您应该: + +* Click the Approve button. +* 告知作者他们的合并请求已经过审核和批准. +* 将合并请求分配给维护者. 默认情况下,将其分配给具有[领域专业知识](#domain-experts)的维护者,但是,如果不可用,或者您认为合并请求不需要[领域专家](#domain-experts)的审查,请随时遵循" [审阅者"轮盘赌的](#reviewer-roulette)建议. + +### The responsibility of the maintainer[](#the-responsibility-of-the-maintainer "Permalink") + +维护人员负责跨领域和产品领域的 GitLab 代码库的总体运行状况,质量和一致性. + +因此,他们的审查将主要集中在总体架构,代码组织,关注点分离,测试,DRYness,一致性和可读性等方面. + +由于维护人员的工作仅取决于他们对整个 GitLab 代码库的了解,而不取决于任何特定领域的知识,因此他们可以查看,批准和合并来自任何团队和任何产品领域的合并请求. + +维护人员将尽最大努力在合并之前检查所选解决方案的详细信息,但是由于他们不一定是[领域专家](#domain-experts) ,因此他们可能没有太多时间来浪费很多时间. 在这种情况下,他们将服从作者和早期审稿人的判断,而将精力放在他们的主要职责上. + +如果维护者认为 MR 足够重要,足以保证需要由[域专家](#domain-experts)进行审查,并且目前尚不清楚域专家是否参与了审查,则他们可以在合并 MR 之前要求[域专家进行](#domain-experts)审查. + +如果恰好也是维护者的开发人员作为审阅者参与了合并请求,则建议不要同时选择他们作为维护者来最终批准并合并它. + +维护人员应在合并之前检查合并请求是否已被所需批准者批准. + +维护人员必须在合并之前检查合并请求[安全性小部件中](../user/application_security/index.html)的列表,以检查合并请求是否引入了新的漏洞. 如有疑问,可以请[安全工程师](https://about.gitlab.com/company/team/)参与. 检测到的漏洞列表必须为空或包含以下内容: + +* 在出现误报的情况下消除漏洞 +* 漏洞转化为问题 + +维护人员**切勿**在没有适当验证的情况下消除漏洞以"清空"列表. + +请注意,某些合并请求可能会针对稳定分支. 这些是罕见的事件. 维护者无法合并这些类型的合并请求. 相反,这些应该发送到[版本管理器](https://about.gitlab.com/community/release-managers/) . + +## Best practices[](#best-practices "Permalink") + +### Everyone[](#everyone "Permalink") + +* 善待. +* 接受许多编程决策是意见. 讨论您喜欢的折衷方案,并迅速解决. +* 问问题; 不要提出要求. ("您如何命名这个`:user_id` ?") +* 要求澄清. ("我听不懂.您能澄清一下吗?") +* 避免有选择地拥有代码. ("我的","不是我的","您的") +* 避免使用可能被视为涉及个人特质的术语. ("哑巴","愚蠢"). 假设每个人都是有吸引力,聪明和善良的. +* 要明确. 请记住,人们并不总是在线了解您的意图. +* 要谦虚. ("我不确定-让我们看一下.") +* 不要夸张. ("始终","从不","无限","无") +* 使用讽刺时要小心. 我们所做的一切都是公开的; 对于您和长期的同事而言,似乎很老套的话可能会很卑鄙,不欢迎新加入该项目的人. +* 如果"我听不懂"或"替代解决方案:"注释过多,请考虑一对一聊天或视频通话. 发表后续评论,总结一对一的讨论. +* 如果您向特定人员提出问题,请务必先提及他们,然后再开始评论; 如果将通知级别设置为"提及",这将确保他们看到该消息,并且其他人将理解他们不必响应. + +### Having your merge request reviewed[](#having-your-merge-request-reviewed "Permalink") + +请记住,代码审阅是一个可能需要多次迭代的过程,审阅者可能会在以后发现他们第一次看不到的东西. + +* 您的代码的第一位审阅者是*you* . 在对闪亮的新分支进行第一次推送之前,请通读整个差异. 是否有意义? 您是否包含与变更的总体目的无关的内容? 您是否忘记删除任何调试代码? +* 感谢审阅者的建议. ("好电话.我会进行更改.") +* 不要亲自去做. 审阅的是代码,而不是您的. +* 说明代码为何存在. ("由于这些原因就这样.如果重命名这个类/文件/方法/变量,是否更清楚?") +* 将不相关的更改和重构提取到将来的合并请求/问题中. +* 试图了解审稿人的观点. +* 尝试回应每个评论. +* 合并请求作者仅解析他们已完全解决的线程. 如果有公开的答复,公开的话题,建议,问题或其他任何内容,则该话题应留待审阅者解决. +* 不应假定所有反馈都要求在合并之前将其建议的更改合并到 MR 中. 这是 MR 作者和审阅者对是否需要这样做的判断,或者是在合并有问题的 MR 之后是否应创建后续问题以解决将来的反馈. +* 基于较早回馈的推送提交作为对分支的独立提交. 在分支准备好合并之前,请勿压扁. 审阅者应该能够根据他们先前的反馈来阅读各个更新. +* 准备好进行另一轮审核后,将合并请求分配回审核者. 如果您无法分配合并请求,请`@`提及审阅者. + +### Assigning a merge request for a review[](#assigning-a-merge-request-for-a-review "Permalink") + +准备好要审核合并请求时,默认应将其分配给小组或团队中的审阅者以进行第一次审阅,但是,您也可以将其分配给任何审阅者. 审阅者列表可以在" [工程项目"](https://about.gitlab.com/handbook/engineering/projects/)页面上找到. + +You can also use `workflow::ready for review` label. That means that your merge request is ready to be reviewed and any reviewer can pick it. It is recommended to use that label only if there isn’t time pressure and make sure the merge request is assigned to a reviewer. + +在审核合并请求并将其传递给维护者后,您应该默认选择具有[领域专业知识](#domain-experts)的维护者,否则应遵循 Reviewer Roulette 的建议或使用`ready for merge`的标签. + +合并请求的作者有责任审查合并请求. 如果`ready for review`状态太长时间,建议将其分配给特定的审阅者. + +#### List of merge requests ready for review[](#list-of-merge-requests-ready-for-review "Permalink") + +有能力的开发人员可以定期检查[合并请求](https://gitlab.com/groups/gitlab-org/-/merge_requests?state=opened&label_name[]=workflow::ready for review)列表[以进行审核,](https://gitlab.com/groups/gitlab-org/-/merge_requests?state=opened&label_name[]=workflow::ready for review)并分配他们要审核的任何合并请求. + +### Reviewing a merge request[](#reviewing-a-merge-request "Permalink") + +了解为什么需要进行更改(修复错误,改善用户体验,重构现有代码). 然后: + +* 尝试在您的评论中做到周密,以减少迭代次数. +* 交流您对哪些想法有强烈的想法,而哪些想法则没有. +* 确定在解决问题的同时简化代码的方法. +* 提供替代的实现,但是假设作者已经考虑了它们. ("您在这里对使用自定义验证器有何看法?") +* 试图了解作者的观点. +* 如果您不懂一段代码,请*这样说* . 很有可能其他人也会对此感到困惑. +* 确保作者清楚他们需要什么来解决/解决该建议. + * 考虑使用[常规注释格式](https://conventionalcomments.org#format)来传达您的意图. + * 对于非强制性建议,请使用(非阻塞)修饰,以便作者知道可以选择在合并请求中解决该问题,或者在以后进行后续操作. +* 经过几行注释后,发布摘要注释(例如"对我很好"或"仅几件要解决的问题")会很有帮助. +* 如果审阅后需要更改,则将合并请求分配给作者. + +### Merging a merge request[](#merging-a-merge-request "Permalink") + +在决定合并之前: + +* 设置里程碑. +* 考虑来自危险漫游器,代码质量和其他报告的警告和错误. 除非有充分的理由证明违规,否则应在合并前解决这些问题. 如果 MR 与任何失败的作业合并,则必须发布评论. +* 如果 MR 既包含与质量相关的变更,又包含与非质量无关的变更,则应由相关维护人员合并 MR,以便在测试中软件工程师批准与质量相关的变更后,将其面向用户的变更(后端,前端或数据库). + +如果合并请求从根本上准备就绪,但仅需要简单的修正(例如拼写错误),则可以考虑通过直接进行更改而不向作者证明是[对行动](https://about.gitlab.com/handbook/values/#bias-for-action)的[偏见](https://about.gitlab.com/handbook/values/#bias-for-action) . 您可以通过使用" [建议更改"](../user/discussions/index.html#suggest-changes)功能将自己的建议应用于合并请求来实现. 注意: + +* 如果更改不直接,请优先将合并请求分配回作者. +* **在应用建议之前** ,请编辑合并请求以确保启用了[压缩和合并](../user/project/merge_requests/squash_and_merge.html#squash-and-merge) ,否则,管道的"危险"作业将失败. + * 如果合并请求未启用压缩和合并,并且具有多个提交,则请参阅以下有关重写提交历史记录的注释. + +准备合并时: + +* 当合并请求包含大量提交时,请考虑使用[Squash 和合并](../user/project/merge_requests/squash_and_merge.html#squash-and-merge)功能. 合并代码时,维护者仅应在作者已设置此选项或合并请求中明确包含要压缩的混乱提交历史记录时使用 squash 功能. +* **使用合并请求的"管道"选项卡中的" `Run Pipeline`按钮启动新的合并请求管道,并启用"管道成功时合并"(MWPS).** 注意: + * 如果**最新[的合并结果管道](../ci/merge_request_pipelines/pipelines_for_merged_results/#pipelines-for-merged-results-premium)**不到 2 小时前完成,则由于合并请求足够接近`master` ,您可能无需启动新管道就可以合并. + * 如果**合并请求来自 fork** ,则我们不能将[管道用于合并结果](../ci/merge_request_pipelines/pipelines_for_merged_results/index.html#prerequisites) ,因此,它们更容易破坏`master` . 检查源分支在`master` . 如果超过 100 次提交,请在合并之前要求作者重新设置基础. + * 如果[master 已损坏](https://about.gitlab.com/handbook/engineering/workflow/#broken-master) ,除了上述两个规则外,请检查`master`是否也发生任何故障,并在单击红色的" Merge"(合并)按钮之前发布指向〜" master:broken"问题的链接. +* 当将 MR 设置为"管道成功合并时"时,您应该接管后续修订,以应对之后发现的所有问题. + +**注意:**感谢"合并结果管道",由于合并结果管道已经合并了`master`的最新更改,因此作者不必再频繁地重新建立分支基础(仅当发生冲突时). 由于维护人员不必要求最终的重新定基,因此可以加快审核/合并周期:相反,他们只需要启动 MR 管道并设置 MWPS. 通过在创建管道时针对最新`master`测试合并结果,此步骤使我们非常接近实际的合并训练功能. + +### The right balance[](#the-right-balance "Permalink") + +在代码审查期间,最困难的事情之一是在审查者可以干扰作者创建的代码的深度上找到适当的平衡. + +* 学习如何找到合适的平衡点需要花费时间. 这就是为什么我们花了一些时间审核合并请求后使审核员成为维护者的原因. +* 查找错误很重要,但是考虑良好的设计也很重要. 建立抽象和良好的设计可以隐藏复杂性并使将来的更改变得容易. +* 强制和改进[代码样式](contributing/style_guides.html)应主要通过[自动化](https://about.gitlab.com/handbook/values/#cleanup-over-sign-off)而不是评论注释来完成. +* 要求作者更改设计有时意味着完全重写贡献的代码. 通常,在进行此操作之前先询问其他维护者或审阅者是一个好主意,但是当您认为重要时,要有勇气去做. +* 为了[Iteration](https://about.gitlab.com/handbook/values/#iteration)的利益,如果您的审查建议是非阻塞性更改或个人喜好(不是书面或约定的要求),请考虑批准合并请求,然后再将其传递回作者. 如果他们同意,这将使他们能够实施您的建议,或者使他们立即将其传递给维护者以供审核. 这可以帮助减少我们的整体合并时间. +* 做正确的事和立即做事有区别. 理想情况下,我们应该做前者,但在现实世界中,我们也需要后者. 一个很好的例子是安全修复程序,应尽快发布. 应该避免要求作者在合并请求中进行重大重构,这是一个紧急解决方案. +* 今天做好事通常比明天做好事更好. 今天运送垃圾通常比明天做好事更糟. 当您找不到合适的平衡时,请向其他人询问他们的意见. + +### GitLab-specific concerns[](#gitlab-specific-concerns "Permalink") + +GitLab 在很多地方都使用过. 许多用户使用我们的[Omnibus 软件包](https://about.gitlab.com/install/) ,但有些用户使用[Docker 映像](https://docs.gitlab.com/omnibus/docker/) ,有些是[从源代码安装的](../install/installation.html) ,还有其他可用的安装方法. GitLab.com 本身是一个大型企业版实例. 这有一些含义: + +1. 应该对**查询更改**进行测试,以确保在 GitLab.com 规模上不会导致性能下降: + 1. 在本地生成大量数据会有所帮助. + 2. 从 GitLab.com 询问查询计划是验证这些计划的最可靠方法. +2. **数据库迁移**必须是: + 1. 可逆的. + 2. 性能达到 GitLab.com 的规模-如果不确定,请维护人员在登台环境中测试迁移. + 3. 正确分类: + * 常规迁移在新代码在实例上运行之前运行. + * 将实例配置为执行新[部署](post_deployment_migrations.html) *后* ,便会进行部署*后* [迁移](post_deployment_migrations.html) . + * [后台迁移](background_migrations.html)在 Sidekiq 中运行,并且仅应在 GitLab.com 规模上花费大量时间进行迁移. +3. **Sidekiq 工人** [cannot change in a backwards-incompatible way](sidekiq_style_guide.html#sidekiq-compatibility-across-updates): + 1. 在部署发生之前,不会耗尽 Sidekiq 队列,因此队列中会有来自上一版 GitLab 的工作线程. + 2. 如果需要更改方法签名,请尝试在两个版本中进行更改,并在第一个版本中同时接受新旧参数. + 3. 同样,如果您需要删除一个工作程序,请停止在一个版本中计划它,然后在下一个版本中将其删除. 这将允许现有作业执行. + 4. Don’t forget, not every instance will upgrade to every intermediate version (some people may go from X.1.0 to X.10.0, or even try bigger upgrades!), so try to be liberal in accepting the old format if it is cheap to do so. +4. **缓存的值**可能会在各个发行版中持续存在. 如果要更改缓存值返回的类型(例如,从字符串或 nil 到数组),请同时更改缓存键. +5. **设置**应作为[最后的手段](https://about.gitlab.com/handbook/product/#convention-over-configuration)添加. 如果要在`gitlab.yml`添加新设置: + 1. 尝试避免这种情况,而是添加到`ApplicationSetting` . + 2. 确保它也已[添加到 Omnibus 中](https://docs.gitlab.com/omnibus/settings/gitlab.yml.html) . +6. **文件系统访问**可能很慢,因此,在有替代解决方案可用时,请尝试避免[共享文件](shared_files.html) . + +### Review turnaround time[](#review-turnaround-time "Permalink") + +由于[取消阻止其他人始终是头等大事](https://about.gitlab.com/handbook/values/#global-optimization) ,因此,即使这可能会对他们的其他任务和优先事项产生不利影响,审阅者也应及时查看分配的合并请求. + +这样做使合并请求中涉及的每个人都可以在上下文处于内存中新鲜时更快地进行迭代,并显着改善了贡献者的体验. + +#### Review-response SLO[](#review-response-slo "Permalink") + +为了确保快速反馈到准备就绪的代码,我们维护了一个`Review-response`服务级别目标(SLO). SLO 定义为: + +> * 审核响应 SLO =(提供第一次审核响应的时间)-(将 MR 分配给审核者的时间)<2 个工作日 + +如果您认为您无法在" `Review-response` SLO 期限内审阅合并请求,请让作者尽快知道,并尝试帮助他们找到其他能够审阅的审阅者或维护者,因此他们可以畅通无阻,并迅速开始工作. + +如果您认为自己有能力并且在完成一些评论之前无法接受其他评论,请通过设置`:red_circle:`表情符号并在状态文本中提及您有能力,通过 GitLab 状态传达此信息. 这将指导撰稿人选择其他审稿人,从而帮助我们满足 SLO. + +当然,如果您不在办公室并且已通过 GitLab.com 状态[传达了](https://about.gitlab.com/handbook/paid-time-off/#communicating-your-time-off)此信息,则作者应意识到这一点,并自己找一位不同的审稿人. + +当合并请求作者的阻止时间超过`Review-response` SLO 时,他们可以自由地通过 Slack 提醒审阅者或分配其他审阅者. + +### Customer critical merge requests[](#customer-critical-merge-requests "Permalink") + +合并请求可能会因为被视为客户关键优先级而受益,因为这样做会使企业受益匪浅. + +客户关键合并请求的属性: + +* [发展高级总监](https://about.gitlab.com/job-families/engineering/engineering-management/#senior-director-engineering) ( [](https://gitlab.com/clefelhocz1)[@ clefelhocz1](https://gitlab.com/clefelhocz1) )是用于确定合并请求是否对客户至关重要的 DRI. +* DRI 将`customer-critical-merge-request`标签分配给合并请求. +* 要求与客户关键合并请求相关的审阅者和维护者一经做出此决定,便立即参与. +* 需要优先处理涉及客户关键合并请求的人员的工作,以便他们有足够的时间专注于此. +* 在处理客户关键的合并请求时,必须遵守 GitLab 的[价值观](https://about.gitlab.com/handbook/values/)和流程,首先要特别注意家人和朋友,其次要注意,完成的定义,迭代以及准备就绪时发布. +* 需要客户关键的合并请求,以免降低安全性,引入数据丢失风险,降低可用性或破坏每个流程的现有功能,从而[优先考虑技术决策](https://about.gitlab.com/handbook/engineering/#prioritizing-technical-decisions.md) . +* 对于客户的关键请求,如果他们认为这将减少花费的合并时间(即使这*可能*会降低[效率](https://about.gitlab.com/company/culture/all-remote/asynchronous/#evaluating-efficiency.md) ),则*建议*相关人员*考虑*除了异步(合并请求注释)之外,还同步进行协调(Zoom,Slack). +* 合并客户关键合并请求后,必须完成回顾,以减少将来的客户关键合并请求的频率. + +## Examples[](#examples "Permalink") + +如何进行代码审查可能会使新的参与者感到惊讶. 以下是一些代码审查示例,它们可以帮助您确定期望的方向. + +**["修改`DiffNote`以便将其重新用于设计"](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/13703) :**它包含了从换行符转折点到设计版本的推理,如果没有某个文件的先前版本,我们应该如何比较它们的所有内容(父级 vs.空白`sha`空白树) ). + +**["支持多行建议"](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25211)** :MR 本身由 FE 和 BE 之间的协作组成,并记录了作者对审阅者的评论. 有一些缺点,一些有关信息的问题,最后还有一个安全漏洞. + +**["每个项目允许有多个存储库"](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10251)** :ZJ 提到了这可能会影响的其他项目(工作马),并建议进行一些改进以保持一致性. James 的评论帮助我们提高了整体代码质量(使用委派`&.`这些类型的事情),并使代码更加健壮. + +**["支持多个受让人进行合并请求"](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10161)** :MR 接触代码库多个部分的一个很好的示例. 尼克指出了一些有趣的例子,詹姆斯·洛佩兹(James Lopez)也加入了对进出口功能的关注. + +### Credits[](#credits "Permalink") + +很大程度上基于[thinkbot 代码的审查指南](https://github.com/thoughtbot/guides/tree/master/code-review) . + +* * * + +[Return to Development documentation](README.html) \ No newline at end of file diff --git a/_book/docs/557.md b/_book/docs/557.md new file mode 100644 index 0000000000000000000000000000000000000000..1ff98eef09520dba1ae4bebb583c654a15cd25f4 --- /dev/null +++ b/_book/docs/557.md @@ -0,0 +1,104 @@ +# Style guides + +> 原文:[https://docs.gitlab.com/ee/development/contributing/style_guides.html](https://docs.gitlab.com/ee/development/contributing/style_guides.html) + +* [Editor/IDE styling standardization](#editoride-styling-standardization) +* [Pre-commit static analysis](#pre-commit-static-analysis) +* [Ruby, Rails, RSpec](#ruby-rails-rspec) + * [Creating new RuboCop cops](#creating-new-rubocop-cops) +* [Database migrations](#database-migrations) +* [JavaScript](#javascript) +* [SCSS](#scss) +* [Go](#go) +* [Shell commands (Ruby)](#shell-commands-ruby) +* [Shell scripting](#shell-scripting) +* [Markdown](#markdown) +* [Documentation](#documentation) +* [Python](#python) +* [Misc](#misc) + +# Style guides[](#style-guides "Permalink") + +## Editor/IDE styling standardization[](#editoride-styling-standardization "Permalink") + +在将文件保存到本地之前,我们使用[EditorConfig](https://editorconfig.org/)自动应用某些样式标准. 默认情况下,大多数编辑器/ IDE 都会自动接受`.editorconfig`设置. 如果您的编辑器/ IDE 不自动支持`.editorconfig` ,建议您进行调查以查看是否存在插件. 例如,这里是[vim](https://github.com/editorconfig/editorconfig-vim)的[插件](https://github.com/editorconfig/editorconfig-vim) . + +## Pre-commit static analysis[](#pre-commit-static-analysis "Permalink") + +强烈建议您安装[Overcommit](https://github.com/sds/overcommit) ,以便在本地提交之前自动检查静态分析违规. + +在您的 GitLab 源目录中运行: + +``` +make -C tooling/overcommit +``` + +Then before a commit is created, Overcommit will automatically check for RuboCop (and other checks) offenses on every modified file. + +这样可以节省您的时间,因为您不必等待配置项检测到相同的错误. + +过量提交依赖于预提交钩子,以防止违反其规则集的提交. 如果您想覆盖此行为,可以通过传递 ENV 变量`OVERCOMMIT_DISABLE`来完成. 即`OVERCOMMIT_DISABLE=1 git rebase master`在禁用 Git 钩子的同时进行 rebase. + +## Ruby, Rails, RSpec[](#ruby-rails-rspec "Permalink") + +我们的代码库样式由[RuboCop](https://github.com/rubocop-hq/rubocop)定义和执行. + +您可以使用`bundle exec rubocop --parallel`在本地检查任何违规行为. 在配置项上,这将由`static-analysis`作业自动检查. + +对于尚未决定的 RuboCop 规则,我们遵循[Ruby Style Guide](https://github.com/rubocop-hq/ruby-style-guide) , [Rails Style Guide](https://github.com/rubocop-hq/rails-style-guide)和[RSpec Style Guide](https://github.com/rubocop-hq/rspec-style-guide)作为编写惯用 Ruby / Rails / RSpec 的通用准则,但是审阅者/维护者应该宽容而不是太宽容关于风格的书呆子. + +同样,当前已禁用某些 RuboCop 规则,对于这些规则,审阅者/维护者不得要求作者使用一种或另一种样式,因为这两种样式均被接受. 这不是理想的情况,因为这为[骑车](https://en.wiktionary.org/wiki/bikeshedding)留下了空间,并且理想情况下,我们应该启用所有 RuboCop 规则,以避免在评论中进行与样式相关的讨论/挑剔/来回. + +此外,我们还有专门的[换行样式指南](../newlines_styleguide.html) ,以及专门针对[测试的样式指南和最佳实践](../testing_guide/index.html) . + +### Creating new RuboCop cops[](#creating-new-rubocop-cops "Permalink") + +通常,最好通过编程方式执行起毛规则,因为它可以减少前述的[自行车脱落](https://en.wiktionary.org/wiki/bikeshedding) . + +为此,我们鼓励在代码库中创建新的 RuboCop 规则. + +当创建可以应用于多个应用程序的新警察时,我们建议您将其添加到我们的[GitLab Styles](https://gitlab.com/gitlab-org/gitlab-styles)宝石中. + +## Database migrations[](#database-migrations "Permalink") + +请参阅专用的《 [数据库迁移样式指南》](../migration_style_guide.html) . + +## JavaScript[](#javascript "Permalink") + +请参阅专用的[JS 样式指南](../fe_guide/style/javascript.html) . + +## SCSS[](#scss "Permalink") + +请参阅专用的[SCSS 样式指南](../fe_guide/style/scss.html) . + +## Go[](#go "Permalink") + +请参阅专用的[Go 标准和样式指南](../go_guide/index.html) . + +## Shell commands (Ruby)[](#shell-commands-ruby "Permalink") + +请参阅[GitLab 代码库中有关 shell 命令](../shell_commands.html)的专用[准则](../shell_commands.html) . + +## Shell scripting[](#shell-scripting "Permalink") + +请参阅专用的[Shell 脚本标准和样式指南](../shell_scripting_guide/index.html) . + +## Markdown[](#markdown "Permalink") + +我们正在遵循[Ciro Santilli 的 Markdown 样式指南](https://cirosantilli.com/markdown-style-guide/) . + +## Documentation[](#documentation "Permalink") + +请参阅专用的[文档样式指南](../documentation/styleguide.html) . + +## Python[](#python "Permalink") + +请参阅专用的[Python 开发指南](../python_guide/index.html) . + +## Misc[](#misc "Permalink") + +代码应使用[美国英语](https://en.wikipedia.org/wiki/American_English)书写. + +* * * + +[Return to Contributing documentation](index.html) \ No newline at end of file diff --git a/_book/docs/558.md b/_book/docs/558.md new file mode 100644 index 0000000000000000000000000000000000000000..4878c49a0da8812f4b4eedec8ff4c5802e6f6a5d --- /dev/null +++ b/_book/docs/558.md @@ -0,0 +1,799 @@ +# GitLab Architecture Overview + +> 原文:[https://docs.gitlab.com/ee/development/architecture.html](https://docs.gitlab.com/ee/development/architecture.html) + +* [Software delivery](#software-delivery) +* [Components](#components) + * [Simplified Component Overview](#simplified-component-overview) + * [Component diagram](#component-diagram) + * [Component legend](#component-legend) + * [Component list](#component-list) + * [Component details](#component-details) + * [Alertmanager](#alertmanager) + * [Certificate management](#certificate-management) + * [Consul](#consul) + * [Database migrations](#database-migrations) + * [Elasticsearch](#elasticsearch) + * [Gitaly](#gitaly) + * [Praefect](#praefect) + * [GitLab Geo](#gitlab-geo) + * [GitLab Exporter](#gitlab-exporter) + * [GitLab Pages](#gitlab-pages) + * [GitLab Runner](#gitlab-runner) + * [GitLab Shell](#gitlab-shell) + * [GitLab Workhorse](#gitlab-workhorse) + * [Grafana](#grafana) + * [Jaeger](#jaeger) + * [Logrotate](#logrotate) + * [Mattermost](#mattermost) + * [MinIO](#minio) + * [NGINX](#nginx) + * [Node Exporter](#node-exporter) + * [PgBouncer](#pgbouncer) + * [PgBouncer Exporter](#pgbouncer-exporter) + * [PostgreSQL](#postgresql) + * [PostgreSQL Exporter](#postgresql-exporter) + * [Prometheus](#prometheus) + * [Redis](#redis) + * [Redis Exporter](#redis-exporter) + * [Registry](#registry) + * [Sentry](#sentry) + * [Sidekiq](#sidekiq) + * [Unicorn](#unicorn) + * [LDAP Authentication](#ldap-authentication) + * [Outbound Email](#outbound-email) + * [Inbound Email](#inbound-email) + * [GitLab Managed Apps](#gitlab-managed-apps) +* [GitLab by Request Type](#gitlab-by-request-type) + * [GitLab Web HTTP Request Cycle](#gitlab-web-http-request-cycle) + * [GitLab Git Request Cycle](#gitlab-git-request-cycle) + * [Web Request (80/443)](#web-request-80443) + * [SSH Request (22)](#ssh-request-22) +* [System Layout](#system-layout) + * [Installation Folder Summary](#installation-folder-summary) + * [Processes](#processes) + * [Repository access](#repository-access) +* [Troubleshooting](#troubleshooting) + * [Init scripts of the services](#init-scripts-of-the-services) + * [Log locations of the services](#log-locations-of-the-services) + * [GitLab specific configuration files](#gitlab-specific-configuration-files) + * [Maintenance Tasks](#maintenance-tasks) +* [GitLab.com](#gitlabcom) + +# GitLab Architecture Overview[](#gitlab-architecture-overview "Permalink") + +## Software delivery[](#software-delivery "Permalink") + +GitLab 有两种软件发行[版](https://gitlab.com/gitlab-org/gitlab-foss/) :开源[社区版](https://gitlab.com/gitlab-org/gitlab-foss/) (CE)和开放核心[企业版](https://gitlab.com/gitlab-org/gitlab/) (EE). GitLab 在[不同的订阅下](https://about.gitlab.com/pricing/)可用. + +GitLab 的新版本在稳定的分支中发布,而 master 分支则用于前沿开发. + +有关信息,请参见[GitLab 发布过程](https://gitlab.com/gitlab-org/release/docs/-/tree/master#gitlab-release-process) . + +EE 和 CE 都需要一些名为 GitLab Shell 和 Gitaly 的附加组件. 这些组件分别可从[GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell/-/tree/master)和[Gitaly](https://gitlab.com/gitlab-org/gitaly/-/tree/master)存储库中获得. 新版本通常是标签,但是停留在 master 分支上将为您提供最新的稳定版本. 新版本通常与 GitLab CE 发布大约相同的时间,但非正式的安全更新被认为很重要. + +## Components[](#components "Permalink") + +A typical install of GitLab will be on GNU/Linux. It uses NGINX or Apache as a web front end to proxypass the Unicorn web server. By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and pre-compiled assets. GitLab serves web pages and the [GitLab API](../api/README.html) using the Unicorn web server. It uses Sidekiq as a job queue which, in turn, uses Redis as a non-persistent database backend for job information, meta data, and incoming jobs. + +我们还支持使用我们的[GitLab Helm 图表](https://docs.gitlab.com/charts/)在 Kubernetes 上部署 GitLab. + +GitLab Web 应用程序将 PostgreSQL 用于持久数据库信息(例如,用户,权限,问题,其他元数据). GitLab 默认将其服务的裸 Git 存储库存储在`/home/git/repositories` . 它还使用裸存储库保留默认的分支和挂钩信息. + +通过 HTTP / HTTPS 提供存储库时,GitLab 利用 GitLab API 来解析授权和访问以及提供 Git 对象. + +附加组件 GitLab Shell 通过 SSH 提供存储库. 它管理`/home/git/.ssh/authorized_keys`的 SSH 密钥,不应手动对其进行编辑. GitLab Shell 通过 Gitaly 访问裸仓库以提供 Git 对象,并与 Redis 进行通信以将作业提交给 Sidekiq,以供 GitLab 处理. GitLab Shell 查询 GitLab API 以确定授权和访问权限. + +Gitaly 从 GitLab Shell 和 GitLab Web 应用程序执行 Git 操作,并向 GitLab Web 应用程序提供 API,以从 Git 获取属性(例如标题,分支,标签,其他元数据),并获取 Blob(例如 diff,commit,文件). + +您可能也[对 GitLab.com](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/)的[生产体系结构感兴趣](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/) . + +### Simplified Component Overview[](#simplified-component-overview "Permalink") + +这是一个简化的架构图,可用于了解 GitLab 的架构. + +下面的[组件图](#component-diagram)中提供了完整的架构图. + +[![Simplified Component Overview](img/7ddc19b18c20bfa78acb7fe9dd2ede4b.png)](img/architecture_simplified.png) + +### Component diagram[](#component-diagram "Permalink") + +图 TB HTTP [HTTP / HTTPS]-TCP 80、443-> NGINX [NGINX] SSH-TCP 22-> GitLabShell [GitLab Shell] SMTP [SMTP Gateway] Geo [GitLab Geo Node]-TCP 22, 80,443-> NGINX GitLabShell --TCP 8080-> Unicorn [" Unicorn(GitLab Rails)"] GitLabShell-> Praefect GitLabShell-> Redis Unicorn-> PgBouncer [PgBouncer] Unicorn-> Redis Unicorn- -> Praefect Sidekiq-> Redis Sidekiq-> PgBouncer Sidekiq-> Praefect GitLabWorkhorse [GitLab Workhorse]-> Unicorn GitLabWorkhorse-> Redis GitLabWorkhorse-> Praefect Praefect-> Gitaly NGINX-> GitLabWorkhorse NGINX- TCP 8090-> GitLabPages [GitLab 页面] NGINX-> Grafana [Grafana] Grafana-TCP 9090-> Prometheus [Prometheus] Prometheus-TCP 80,443-> Unicorn RedisExporter [Redis Exporter]-> Redis Prometheus-TCP 9121-> RedisExporter PostgreSQLExporter [PostgreSQL 导出器]-> PostgreSQL PgBouncerExporter [PgBouncer 导出器]-> PgBouncer Prometheus-TCP 9187-> PostgreSQLExporter Prometheus-TCP 9100-> NodeExporter [Node Exp orter] Prometheus-TCP 9168-> GitLabExporter [GitLab Exporter] Prometheus-TCP 9127-> PgBouncerExporter GitLabExporter-> PostgreSQL GitLabExporter-> GitLabShell GitLabExporter-> Sidekiq PgBouncer-> Consul PostgreSQL-> Consul PgBouncer -> PostgreSQL NGINX->注册表 Unicorn->注册表 NGINX-> Mattermost Mattermost --- Unicorn Prometheus-> Alertmanager 迁移-> PostgreSQL Runner-TCP 443-> NGINX Unicorn-TCP 9200- > Elasticsearch Sidekiq-TCP 9200-> Elasticsearch Sidekiq-TCP 80,443-> Sentry Unicorn-TCP 80,443-> Sentry Sidekiq-UDP 6831-> Jaeger Unicorn-UDP 6831-> Jaeger Gitaly-UDP 6831-> Jaeger GitLabShell-UDP 6831-> Jaeger GitLabWorkhorse-UDP 6831-> Jaeger Alertmanager-TCP 25-> SMTP Sidekiq-TCP 25-> SMTP Unicorn-TCP 25-> SMTP Unicorn-TCP 369-> LDAP Sidekiq-TCP 369-> LDAP Unicorn-TCP 443-> ObjectStorage [" Object Storage"] Sidekiq-TCP 443-> ObjectStorage GitLabWorkhorse- TCP 协议 443-> ObjectStorage 注册表-TCP 443-> ObjectStorage Geo-TCP 5432-> PostgreSQL + +### Component legend[](#component-legend "Permalink") + +* ✅-默认安装 +* ⚙-需要其他配置或 GitLab 托管应用 +* ⤓-需要手动安装 +* ❌-不支持或无可用说明 +* 不适用-不适用 + +组件状态链接到每个组件的配置文档. + +### Component list[](#component-list "Permalink") + +表描述链接: + +* [Omnibus GitLab](https://docs.gitlab.com/omnibus/) +* [GitLab chart](https://docs.gitlab.com/charts/) +* [Minikube Minimal](https://docs.gitlab.com/charts/development/minikube/) +* [GitLab.com](https://gitlab.com) +* [Source](../install/installation.html) +* [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) + +| Component | Description | 所有的 GitLab | GitLab 图表 | Minikube 最小 | GitLab.com | Source | GDK | CE/EE | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | +| [Certificate Management](#certificate-management) | TLS 设置,让我们加密 | ✅ | ✅ | ⚙ | ✅ | ⚙ | ⚙ | CE 和 EE | +| [Consul](#consul) | 数据库节点发现,故障转移 | ⚙ | ❌ | ❌ | ✅ | ❌ | ❌ | 仅 EE | +| [Database Migrations](#database-migrations) | 数据库迁移 | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE 和 EE | +| [Elasticsearch](#elasticsearch) | 改进了 GitLab 中的搜索 | ⤓ | ⤓ | ⤓ | ❌ | ⤓ | ⤓ | 仅 EE | +| [Gitaly](#gitaly) | Git RPC 服务,用于处理 GitLab 进行的所有 Git 调用 | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE 和 EE | +| [GitLab Exporter](#gitlab-exporter) | 生成各种 GitLab 指标 | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | CE 和 EE | +| [GitLab Geo Node](#gitlab-geo) | 地理分布的 GitLab 节点 | ⚙ | ⚙ | ❌ | ✅ | ❌ | ⚙ | 仅 EE | +| [GitLab Managed Apps](#gitlab-managed-apps) | 将 Helm,Ingress,Cert-Manager,Prometheus,Runner,JupyterHub 或 Knative 部署到集群 | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | CE 和 EE | +| [GitLab Pages](#gitlab-pages) | 托管静态网站 | ⚙ | ❌ | ❌ | ✅ | ⚙ | ⚙ | CE 和 EE | +| [GitLab self-monitoring: Alertmanager](#alertmanager) | 来自 Prometheus 的重复数据删除,分组和路由警报 | ⚙ | ✅ | ⚙ | ✅ | ❌ | ❌ | CE 和 EE | +| [GitLab self-monitoring: Grafana](#grafana) | 指标仪表板 | ✅ | ⚙ | ⤓ | ✅ | ❌ | ❌ | CE & EE | +| [GitLab self-monitoring: Jaeger](#jaeger) | 查看由 GitLab 实例生成的跟踪 | ❌ | ⚙ | ❌ | ❌ | ⤓ | ⚙ | CE 和 EE | +| [GitLab self-monitoring: Prometheus](#prometheus) | 时间序列数据库,指标收集和查询服务 | ✅ | ✅ | ⚙ | ✅ | ❌ | ❌ | CE 和 EE | +| [GitLab self-monitoring: Sentry](#sentry) | 跟踪 GitLab 实例生成的错误 | ⤓ | ⤓ | ❌ | ✅ | ⤓ | ⤓ | CE 和 EE | +| [GitLab Shell](#gitlab-shell) | 通过 SSH 会话处理`git` | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE 和 EE | +| [GitLab Workhorse](#gitlab-workhorse) | 智能反向代理,处理大型 HTTP 请求 | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE | +| [Inbound email (SMTP)](#inbound-email) | 接收消息以更新问题 | ⤓ | ⚙ | ⤓ | ✅ | ⤓ | ⤓ | CE 和 EE | +| [Jaeger integration](#jaeger) | 部署的应用程序的分布式跟踪 | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | 仅 EE | +| [LDAP Authentication](#ldap-authentication) | 根据集中的 LDAP 目录对用户进行身份验证 | ⤓ | ⤓ | ⤓ | ❌ | ⤓ | ⤓ | CE 和 EE | +| [Mattermost](#mattermost) | 开源 Slack 替代方案 | ⚙ | ⤓ | ⤓ | ⤓ | ❌ | ❌ | CE 和 EE | +| [MinIO](#minio) | 对象存储服务 | ⤓ | ✅ | ✅ | ✅ | ❌ | ⚙ | CE 和 EE | +| [NGINX](#nginx) | 将请求路由到适当的组件,终止 SSL | ✅ | ✅ | ⚙ | ✅ | ⤓ | ❌ | CE 和 EE | +| [Node Exporter](#node-exporter) | 具有系统指标的 Prometheus 端点 | ✅ | N/A | N/A | ✅ | ❌ | ❌ | CE 和 EE | +| [Outbound email (SMTP)](#outbound-email) | 向用户发送电子邮件 | ⤓ | ⚙ | ⤓ | ✅ | ⤓ | ⤓ | CE 和 EE | +| [PgBouncer Exporter](#pgbouncer-exporter) | 具有 PgBouncer 指标的 Prometheus 端点 | ⚙ | ❌ | ❌ | ✅ | ❌ | ❌ | CE 和 EE | +| [PgBouncer](#pgbouncer) | 数据库连接池,故障转移 | ⚙ | ❌ | ❌ | ✅ | ❌ | ❌ | 仅 EE | +| [PostgreSQL Exporter](#postgresql-exporter) | 带有 PostgreSQL 指标的 Prometheus 端点 | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | CE 和 EE | +| [PostgreSQL](#postgresql) | Database | ✅ | ✅ | ✅ | ✅ | ⤓ | ✅ | CE 和 EE | +| [Praefect](#praefect) | 任何 Git 客户端和 Gitaly 存储节点之间的透明代理. | ✅ | ⚙ | ❌ | ✅ | ⚙ | ✅ | CE 和 EE | +| [Redis Exporter](#redis-exporter) | 具有 Redis 指标的 Prometheus 端点 | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | CE 和 EE | +| [Redis](#redis) | 缓存服务 | ✅ | ✅ | ✅ | ✅ | ⤓ | ✅ | CE 和 EE | +| [Registry](#registry) | 容器注册表,允许推和拉图像 | ⚙ | ✅ | ✅ | ✅ | ⤓ | ⚙ | CE 和 EE | +| [Runner](#gitlab-runner) | 执行 GitLab CI / CD 作业 | ⤓ | ✅ | ⚙ | ✅ | ⚙ | ⚙ | CE 和 EE | +| [Sentry integration](#sentry) | 跟踪已部署应用程序的错误 | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | CE 和 EE | +| [Sidekiq](#sidekiq) | 后台作业处理器 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | CE 和 EE | +| [Unicorn (GitLab Rails)](#unicorn) | 处理对 Web 界面和 API 的请求 | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE 和 EE | + +### Component details[](#component-details "Permalink") + +本文档供系统管理员和 GitLab 支持工程师使用,他们希望进一步了解 GitLab 的内部结构以及如何协同工作. + +部署后,应将 GitLab 视为以下过程的合并. 在进行故障排除或调试时,请尽可能明确地指出要引用的组件. 那应该增加清晰度并减少混乱. + +**Layers** + +从流程的角度来看,可以认为 GitLab 具有两层: + +* **监视** :不需要任何层来交付 GitLab 应用程序,但是它将允许管理员更深入地了解他们的基础结构以及整个服务在做什么. +* **核心** :对 GitLab 作为平台交付至关重要的任何过程. 如果这些过程中的任何一个停止,都将导致 GitLab 中断. 对于核心层,您可以进一步分为: + * **处理器** :这些进程负责实际执行操作并提供服务. + * **数据** :这些服务为 GitLab 服务存储/公开结构化数据. + +#### Alertmanager[](#alertmanager "Permalink") + +* [Project page](https://github.com/prometheus/alertmanager/blob/master/README.md) +* Configuration: + * [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template) + * [Charts](https://github.com/helm/charts/tree/master/stable/prometheus) +* 层:监控 +* Process: `alertmanager` +* GitLab.com: [Monitoring of GitLab.com](https://about.gitlab.com/handbook/engineering/monitoring/) + +[警报管理器](https://s0prometheus0io.icopy.site/docs/alerting/latest/alertmanager/)是 Prometheus 提供的工具,用于*"处理由客户端应用程序(例如 Prometheus 服务器)发送的警报.* *它负责将重复数据删除,分组和路由到正确的接收者集成,例如电子邮件,PagerDuty 或 Opsgenie.* *它还负责沉默和禁止警报."* 您可以在[问题#45740 中](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45740)阅读更多有关我们将要[发出](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45740)警报的内容. + +#### Certificate management[](#certificate-management "Permalink") + +* 项目页面: + * [综合巴士](https://github.com/certbot/certbot/blob/master/README.rst) + * [图表](https://github.com/jetstack/cert-manager/blob/master/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/ssl.html) + * [Charts](https://docs.gitlab.com/charts/installation/tls.html) + * [Source](../install/installation.html#using-https) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/https.md) +* 层:核心服务(处理器) +* GitLab.com: [Secrets Management](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#secrets-management) + +#### Consul[](#consul "Permalink") + +* [Project page](https://github.com/hashicorp/consul/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/high_availability/consul.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) +* 层:核心服务(数据) +* GitLab.com: [Consul](../user/gitlab_com/index.html#consul) + +Consul 是用于服务发现和配置的工具. Consul 是分布式的,高度可用的,并且具有极高的可伸缩性. + +#### Database migrations[](#database-migrations "Permalink") + +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/database.html) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/migrations/) + * [Source](../update/upgrading_from_source.html#13-install-libraries-migrations-etc) +* Layer: Core Service (Data) + +#### Elasticsearch[](#elasticsearch "Permalink") + +* [Project page](https://github.com/elastic/elasticsearch/) +* Configuration: + * [Omnibus](../integration/elasticsearch.html) + * [Charts](../integration/elasticsearch.html) + * [Source](../integration/elasticsearch.html) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/elasticsearch.md) +* 层:核心服务(数据) +* GitLab.com: [Get Advanced Global Search working on GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/153) epic. + +Elasticsearch 是为云构建的分布式 RESTful 搜索引擎. + +#### Gitaly[](#gitaly "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitaly/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/gitaly/index.html) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/gitaly/) + * [Source](../install/installation.html#install-gitaly) +* 层:核心服务(数据) +* Process: `gitaly` +* GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture) + +Gitaly 是一项由 GitLab 设计的服务,旨在消除我们在 GitLab 的分布式部署(请考虑 GitLab.com 或高可用性部署)中对 Git 存储使用 NFS 的需求. 从 11.3.0 开始,此服务处理 GitLab 中的所有 Git 级别访问. 您可以[在项目的 README 中](https://gitlab.com/gitlab-org/gitaly)阅读有关该项目的更多信息. + +#### Praefect[](#praefect "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitaly/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/gitaly/index.html) + * [Source](../install/installation.html#install-gitaly) +* 层:核心服务(数据) +* Process: `praefect` +* GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture) + +Praefect 是每个 Git 客户端和 Gitaly 之间的透明代理,用于协调将存储库更新复制到辅助节点. + +#### GitLab Geo[](#gitlab-geo "Permalink") + +* Configuration: + * [Omnibus](../administration/geo/replication/index.html#setup-instructions) + * [Charts](https://docs.gitlab.com/charts/advanced/geo/) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/geo.md) +* 层:核心服务(处理器) + +#### GitLab Exporter[](#gitlab-exporter "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitlab-exporter) +* Configuration: + * [Omnibus](../administration/monitoring/prometheus/gitlab_exporter.html) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/gitlab-exporter/index.html) +* 层:监控 +* Process: `gitlab-exporter` +* GitLab.com: [Monitoring of GitLab.com](https://about.gitlab.com/handbook/engineering/monitoring/) + +GitLab Exporter 是一个内部设计的流程,允许我们将有关 GitLab 应用程序内部的度量导出到 Prometheus. 您可以[在项目的 README 中](https://gitlab.com/gitlab-org/gitlab-exporter)阅读更多内容. + +#### GitLab Pages[](#gitlab-pages "Permalink") + +* Configuration: + * [Omnibus](../administration/pages/index.html) + * [Charts](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/37) + * [Source](../install/installation.html#install-gitlab-pages) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/pages.md) +* 层:核心服务(处理器) +* GitLab.com: [GitLab Pages](../user/gitlab_com/index.html#gitlab-pages) + +GitLab 页面是一项功能,可让您直接从 GitLab 中的存储库发布静态网站. + +您可以将其用于个人或企业网站,例如投资组合,文档,清单和业务演示. 您还可以将任何许可证归于您的内容. + +#### GitLab Runner[](#gitlab-runner "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/runner/) + * [Charts](https://docs.gitlab.com/runner/install/kubernetes.html) + * [Source](https://docs.gitlab.com/runner/) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/runner.md) +* 层:核心服务(处理器) +* GitLab.com: [Runner](../user/gitlab_com/index.html#shared-runners) + +GitLab Runner 运行作业并将结果发送到 GitLab. + +GitLab CI / CD 是 GitLab 附带的开源持续集成服务,用于协调测试. 该项目的旧名称是`GitLab CI Multi Runner`但从现在开始,请使用`GitLab Runner` (不带 CI). + +#### GitLab Shell[](#gitlab-shell "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitlab-shell/blob/master/README.md) +* Configuration: + * [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/gitlab-shell/) + * [Source](../install/installation.html#install-gitlab-shell) + * [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) +* 层:核心服务(处理器) +* GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture) + +[GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell)是[GitLab](https://gitlab.com/gitlab-org/gitlab-shell)设计的程序,用于处理基于 SSH 的`git`会话,并修改授权密钥的列表. GitLab Shell 不是 Unix Shell,也不是 Bash 或 Zsh 的替代品. + +#### GitLab Workhorse[](#gitlab-workhorse "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitlab-workhorse/blob/master/README.md) +* Configuration: + * [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/unicorn/) + * [Source](../install/installation.html#install-gitlab-workhorse) +* 层:核心服务(处理器) +* Process: `gitlab-workhorse` +* GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture) + +[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse)是由 GitLab 设计的程序,可帮助缓解 Unicorn 的压力. 您可以阅读有关发展的[历史原因的](https://about.gitlab.com/blog/2016/04/12/a-brief-history-of-gitlab-workhorse/)更多信息. 它旨在充当智能反向代理,以帮助整体上加快 GitLab 的速度. + +#### Grafana[](#grafana "Permalink") + +* [Project page](https://github.com/grafana/grafana/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/monitoring/performance/grafana_configuration.html) + * [Charts](https://docs.gitlab.com/charts/charts/globals) +* 层:监控 +* GitLab.com: [GitLab triage Grafana dashboard](https://dashboards.gitlab.com/d/RZmbBr7mk/gitlab-triage?refresh=30s) + +Grafana 是适用于 Graphite,Elasticsearch,OpenTSDB,Prometheus 和 InfluxDB 的开源,功能丰富的指标仪表板和图形编辑器. + +#### Jaeger[](#jaeger "Permalink") + +* [Project page](https://github.com/jaegertracing/jaeger/blob/master/README.md) +* Configuration: + * [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4104) + * [Charts](https://docs.gitlab.com/charts/charts/globals) + * [Source](../development/distributed_tracing.html#enabling-distributed-tracing) + * [GDK](../development/distributed_tracing.html#using-jaeger-in-the-gitlab-development-kit) +* 层:监控 +* GitLab.com: [Configuration to enable Tracing for a GitLab instance](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4104) issue. + +受到 Dapper 和 OpenZipkin 启发的 Jaeger 是一个分布式跟踪系统. 它可以用于监视基于微服务的分布式系统. + +有关监视已部署的应用程序,请参阅[Jaeger 跟踪文档.](../operations/tracing.html) + +#### Logrotate[](#logrotate "Permalink") + +* [Project page](https://github.com/logrotate/logrotate/blob/master/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/logs.html) +* 层:核心服务 +* Process: `logrotate` + +GitLab 包含大量全部记录的服务. 从 7.4 开始,我们开始捆绑自己的 logrotate,以确保我们负责任地进行日志记录. 这只是普通开源产品的打包版本. + +#### Mattermost[](#mattermost "Permalink") + +* [Project page](https://github.com/mattermost/mattermost-server/blob/master/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/gitlab-mattermost/) + * [Charts](https://docs.mattermost.com/install/install-mmte-helm-gitlab-helm.html) +* 层:核心服务(处理器) +* GitLab.com: [Mattermost](../user/project/integrations/mattermost.html) + +Mattermost 是一种开放源代码的私有云,是[https://mattermost.com 上的](https://mattermost.com) Slack 替代品. + +#### MinIO[](#minio "Permalink") + +* [Project page](https://github.com/minio/minio/blob/master/README.md) +* Configuration: + * [Omnibus](https://min.io/download) + * [Charts](https://docs.gitlab.com/charts/charts/minio/) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/object_storage.md) +* 层:核心服务(数据) +* GitLab.com: [Storage Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#storage-architecture) + +MinIO 是根据 Apache License v2.0 发布的对象存储服务器. 它与 Amazon S3 云存储服务兼容. 它最适合存储非结构化数据,例如照片,视频,日志文件,备份和容器/ VM 映像. 一个对象的大小范围可以从几个 KB 到最大 5TB. + +#### NGINX[](#nginx "Permalink") + +* 项目页面: + * [综合巴士](https://github.com/nginx/nginx) + * [图表](https://github.com/kubernetes/ingress-nginx/blob/master/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/) + * [Charts](https://docs.gitlab.com/charts/charts/nginx/) + * [Source](../install/installation.html#9-nginx) +* 层:核心服务(处理器) +* Process: `nginx` +* GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture) + +NGINX 有一个用于所有 HTTP 请求的 Ingress 端口,并将它们路由到 GitLab 中的相应子系统. 我们捆绑了流行的开源 Web 服务器的未修改版本. + +#### Node Exporter[](#node-exporter "Permalink") + +* [Project page](https://github.com/prometheus/node_exporter/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/monitoring/prometheus/node_exporter.html) + * [Charts](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1332) +* 层:监控 +* Process: `node-exporter` +* GitLab.com: [Monitoring of GitLab.com](https://about.gitlab.com/handbook/engineering/monitoring/) + +[Node Exporter](https://github.com/prometheus/node_exporter)是 Prometheus 工具,可为我们提供底层计算机的指标(以 CPU /磁盘/负载为例). 它只是 Prometheus 项目中常见开源产品的打包版本. + +#### PgBouncer[](#pgbouncer "Permalink") + +* [Project page](https://github.com/pgbouncer/pgbouncer/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/high_availability/pgbouncer.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) +* 层:核心服务(数据) +* GitLab.com: [Database Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#database-architecture) + +PostgreSQL 的轻量级连接池. + +#### PgBouncer Exporter[](#pgbouncer-exporter "Permalink") + +* [Project page](https://github.com/prometheus-community/pgbouncer_exporter/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/monitoring/prometheus/pgbouncer_exporter.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) +* 层:监控 +* GitLab.com: [Monitoring of GitLab.com](https://about.gitlab.com/handbook/engineering/monitoring/) + +Prometheus PgBouncer 的出口商. 导出指标为 9127 / metrics. + +#### PostgreSQL[](#postgresql "Permalink") + +* [Project page](https://github.com/postgres/postgres/blob/master/README) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/database.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) + * [Source](../install/installation.html#6-database) +* 层:核心服务(数据) +* Process: `postgresql` +* GitLab.com: [PostgreSQL](../user/gitlab_com/index.html#postgresql) + +GitLab 打包了流行的数据库,以存储应用程序元数据和用户信息. + +#### PostgreSQL Exporter[](#postgresql-exporter "Permalink") + +* [Project page](https://github.com/wrouesnel/postgres_exporter/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/monitoring/prometheus/postgres_exporter.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) +* 层:监控 +* Process: `postgres-exporter` +* GitLab.com: [Monitoring of GitLab.com](https://about.gitlab.com/handbook/engineering/monitoring/) + +[`postgres_exporter`](https://github.com/wrouesnel/postgres_exporter)是社区提供的 Prometheus 导出器,它将 PostgreSQL 的有关数据传递给 Prometheus,以在 Grafana 仪表板中使用. + +#### Prometheus[](#prometheus "Permalink") + +* [Project page](https://github.com/prometheus/prometheus/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/monitoring/prometheus/index.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) +* 层:监控 +* Process: `prometheus` +* GitLab.com: [Prometheus](../user/gitlab_com/index.html#prometheus) + +Prometheus 是一个时序工具,可帮助 GitLab 管理员公开有关用于向 GitLab 提供服务的各个流程的指标. + +#### Redis[](#redis "Permalink") + +* [Project page](https://github.com/antirez/redis/blob/unstable/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/redis.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) + * [Source](../install/installation.html#7-redis) +* 层:核心服务(数据) +* Process: `redis` +* GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture) + +Redis 被打包以提供存储位置: + +* 会话数据 +* 临时缓存信息 +* 后台作业队列 + +#### Redis Exporter[](#redis-exporter "Permalink") + +* [Project page](https://github.com/oliver006/redis_exporter/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/monitoring/prometheus/redis_exporter.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) +* 层:监控 +* Process: `redis-exporter` +* GitLab.com: [Monitoring of GitLab.com](https://about.gitlab.com/handbook/engineering/monitoring/) + +[Redis Exporter](https://github.com/oliver006/redis_exporter)旨在向 Prometheus 提供有关 Redis 流程的特定指标,以便我们可以在 Grafana 中绘制这些指标. + +#### Registry[](#registry "Permalink") + +* [Project page](https://github.com/docker/distribution/blob/master/README.md) +* Configuration: + * [Omnibus](../update/upgrading_from_source.html#13-install-libraries-migrations-etc) + * [Charts](https://docs.gitlab.com/charts/charts/registry/) + * [Source](../administration/packages/container_registry.html#enable-the-container-registry) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/registry.md) +* 层:核心服务(处理器) +* GitLab.com: [GitLab Container Registry](../user/packages/container_registry/index.html#build-and-push-images-using-gitlab-cicd) + +用户使用注册表来存储自己的 Docker 映像. 捆绑的注册表使用 NGINX 作为负载平衡器,并使用 Gi​​tLab 作为身份验证管理器. 每当客户端请求从注册表中拉出或推送图像时,客户端都会返回`401`响应以及标头,其中详细说明了从何处获取身份验证令牌(在本例中为 GitLab 实例). 然后,客户端将向 GitLab 请求"拉"或"推"身份验证令牌,然后将原始请求重试到注册表. 了解有关[令牌认证的](https://docs.docker.com/registry/spec/auth/token/)更多信息. + +也可以将外部注册表配置为将 GitLab 用作身份验证端点. + +#### Sentry[](#sentry "Permalink") + +* [Project page](https://github.com/getsentry/sentry/) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/configuration.html) + * [Charts](https://docs.gitlab.com/charts/charts/globals) + * [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) + * [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) +* 层:监控 +* GitLab.com: [Searching Sentry](https://about.gitlab.com/handbook/support/workflows/500_errors.html#searching-sentry) + +从根本上说,Sentry 是一项服务,可帮助您实时监视和修复崩溃. 该服务器使用 Python,但是它包含用于在任何应用程序中从任何语言发送事件的完整 API. + +有关监视已部署的应用程序,请参阅[Sentry 集成文档](../user/project/operations/error_tracking.html) + +#### Sidekiq[](#sidekiq "Permalink") + +* [Project page](https://github.com/mperham/sidekiq/blob/master/README.md) +* Configuration: + * [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/) + * [Minikube Minimal](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/index.html) + * [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) + * [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) +* 层:核心服务(处理器) +* Process: `sidekiq` +* GitLab.com: [Sidekiq](../user/gitlab_com/index.html#sidekiq) + +Sidekiq 是 Ruby 后台作业处理器,可从 Redis 队列中提取作业并进行处理. 后台作业使 GitLab 通过将工作移至后台来提供更快的请求/响应周期. + +#### Unicorn[](#unicorn "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitlab/blob/master/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/unicorn.html) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/webservice/) + * [Source](../install/installation.html#configure-it) + * [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) +* 层:核心服务(处理器) +* Process: `unicorn` +* GitLab.com: [Unicorn](../user/gitlab_com/index.html#unicorn) + +[Unicorn](https://yhbt.net/unicorn/)是一个 Ruby 应用程序服务器,用于运行核心的 Rails 应用程序,该应用程序在 GitLab 中提供面向用户的功能. 通常,根据 GitLab 版本,您会看到此输出为`bundle`或`config.ru` . + +#### LDAP Authentication[](#ldap-authentication "Permalink") + +* Configuration: + * [Omnibus](../administration/auth/ldap/index.html) + * [Charts](https://docs.gitlab.com/charts/charts/globals.html) + * [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/ldap.md) +* 层:核心服务(处理器) +* GitLab.com: [Product Tiers](https://about.gitlab.com/pricing/#gitlab-com) + +#### Outbound Email[](#outbound-email "Permalink") + +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/smtp.html) + * [Charts](https://docs.gitlab.com/charts/installation/command-line-options.html) + * [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) + * [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) +* 层:核心服务(处理器) +* GitLab.com: [Mail configuration](../user/gitlab_com/index.html#mail-configuration) + +#### Inbound Email[](#inbound-email "Permalink") + +* Configuration: + * [Omnibus](../administration/incoming_email.html) + * [Charts](https://docs.gitlab.com/charts/installation/command-line-options.html) + * [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) + * [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) +* 层:核心服务(处理器) +* GitLab.com: [Mail configuration](../user/gitlab_com/index.html#mail-configuration) + +#### GitLab Managed Apps[](#gitlab-managed-apps "Permalink") + +* Configuration: + * [Omnibus](../user/project/clusters/index.html#installing-applications) + * [Charts](../user/project/clusters/index.html#installing-applications) + * [Source](../user/project/clusters/index.html#installing-applications) + * [GDK](../user/project/clusters/index.html#installing-applications) +* 层:核心服务(处理器) + +GitLab 提供[GitLab 托管应用程序](../user/project/clusters/index.html#installing-applications) ,一键安装各种应用程序,可以直接将其添加到配置的集群中. 使用 Auto DevOps 时,Review Apps 和部署需要这些应用程序. 您可以在创建集群后安装它们. 这包括: + +* [Helm](https://helm.sh/docs/) +* [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) +* [Cert-Manager](https://cert-manager.io/docs/) +* [Prometheus](https://s0prometheus0io.icopy.site/docs/introduction/overview/) +* a [Runner](https://docs.gitlab.com/runner/) +* [JupyterHub](https://jupyter.org) +* [Knative](https://cloud.google.com/knative/) + +## GitLab by Request Type[](#gitlab-by-request-type "Permalink") + +GitLab 为最终用户提供了两个"接口"来访问服务: + +* Web HTTP 请求(查看 UI / API) +* Git HTTP / SSH 请求(推/拉 Git 数据) + +了解两者之间的区别很重要,因为某些过程在两种过程中都使用,而另一些过程则是特定请求类型所独有的. + +### GitLab Web HTTP Request Cycle[](#gitlab-web-http-request-cycle "Permalink") + +向 HTTP 端点发出请求(认为`/users/sign_in` )时,请求将通过 GitLab 服务采用以下路径: + +* NGINX-充当我们的第一线反向代理. +* GitLab Workhorse-确定是否需要转到 Rails 应用程序或其他地方以减少 Unicorn 上的负载. +* Unicorn-由于这是一个 Web 请求,并且需要访问该应用程序,因此它将转到 Unicorn. +* PostgreSQL / Gitaly / Redis-根据请求的类型,它可能会通过这些服务来存储或检索数据. + +### GitLab Git Request Cycle[](#gitlab-git-request-cycle "Permalink") + +下面我们描述 HTTP 与 SSH Git 请求将采用的不同路径. Web 请求周期有一些重叠,但也有一些差异. + +### Web Request (80/443)[](#web-request-80443 "Permalink") + +通过 HTTP 进行的 Git 操作使用[Git 文档中](https://git-scm.com/docs/http-protocol)描述的无状态"智能"协议,但处理这些操作的职责分散在多个 GitLab 组件中. + +这是`git fetch`的序列图. 请注意,所有请求都会通过 NGINX 以及任何其他 HTTP 负载平衡器传递,但不会以任何方式进行转换. 所有路径都相对于`/namespace/project.git` URL 呈现. + +sequenceDiagram 参与者客户端参与者上的 Git NGINX 参与者 Workhorse 参与者 Rails 参与者 Gitaly 参与者服务器上的 Git 注意客户端上的 Git 左侧:git fetch +客户端上的 info-refs Git->> + Workhorse:GET / info / refs?service = git-upload-pack Workhorse->> + Rails:GET / info / refs?service = git-upload-pack 注意 Rails 的右侧:验证检查 Rails->>-Workhorse:Gitlab :: Workhorse.git_http_ok​​ Workhorse->> + Gitaly:SmartHTTPService.InfoRefsUploadPack 请求服务器上的 Gitaly->> + Git:git upload-pack --stateless-rpc --advertise-refs 服务器上的 Git->>-Gitaly:git upload-pack 响应 Gitaly->>-工作马:SmartHTTPService.InfoRefsUploadPack 响应 Workhorse->>-客户端上的 Git:200 OK 注意客户端上的 Git 左侧:git fetch +在客户端上获取包装 Git->> + Workhorse:POST / git-upload-pack Workhorse->> + Rails:POST / git-upload-pack 注意 Rails 的权利:Auth check Rails->>-Workhorse:Gitlab: :Workhorse.git_http_ok​​ Workhorse->> + Gitaly:SmartHTTPService.PostUploadPack 请求 Gitaly->> + Git 在服务器上:git upload-pack --stateless-rpc 服务器上的 Git->>-Gitaly:git upload-pack 响应 Gitaly- ->>-Workhorse:SmartHTTPService.PostUploadPack 响应 Workhorse->>-客户端上的 Git:200 OK + +该序列与`git push`相似,除了使用`git-receive-pack`代替`git-upload-pack` . + +### SSH Request (22)[](#ssh-request-22 "Permalink") + +通过 SSH 进行的 Git 操作可以使用[Git 文档中](https://git-scm.com/docs/pack-protocol#_ssh_transport)描述的有状态协议,但是处理它们的职责分散在多个 GitLab 组件中. + +没有任何 GitLab 组件直接使用 SSH-所有 SSH 连接都是在客户端计算机上的 Git 与 SSH 服务器之间建立的,从而终止了连接. 对于 SSH 服务器,所有连接均以`git`用户身份进行身份验证; GitLab 用户通过客户端提供的 SSH 密钥来区分. + +这是`git fetch`的序列图,假设启用了[快速 SSH 密钥查找](../administration/operations/fast_ssh_key_lookup.html) . 请注意, `AuthorizedKeysCommand`是[GitLab Shell](#gitlab-shell)提供的可执行文件: + +sequenceDiagram 参与者客户端参与者上的 Git SSH 服务器参与者 AuthorizedKeysCommand 参与者 GitLab Shell 参与者 Rails 参与者 Gitaly 参与者服务器上的 Git 注意客户端上的 Git 左侧:git fetch 客户端上的 Git->> + SSH 服务器:ssh git fetch-pack request SSH 服务器-> > + AuthorizedKeysCommand:gitlab-shell-authorized-keys-check git AAAA ... AuthorizedKeysCommand->> + Rails:GET / internal / api / authorized_keys?key = AAAA ...注意 Rails 的右边:查找密钥 ID Rails-- >>-AuthorizedKeysCommand:200 OK,command =" gitlab-shell upload-pack key_id = 1" AuthorizedKeysCommand->>-SSH 服务器:command =" gitlab-shell upload-pack key_id = 1" SSH 服务器->> + GitLab Shell:gitlab-shell upload-pack key_id = 1 GitLab Shell->> + Rails:GET / internal / api / allowed?action = upload_pack&key_id = 1 注意 Rails 的权利:Auth check Rails->>-GitLab Shell:200 OK ,{gitaly:...} GitLab Shell->> + Gitaly:SSHService.SSHUploadPack 请求服务器上的 Gitaly->> + Git:git upload-pack 请求注意客户端上的 Git,Git on 服务器:Git 客户端和服务器上服务器 Git 之间的双向通信->>-Gitaly:git upload-pack 响应 Gitaly->>-GitLab Shell:SSHService.SSHUploadPack 响应 GitLab Shell->>-SSH 服务器:gitlab-shell 上载 SSH 伺服器的上载回应->>-Git 使用者:ssh git fetch-pack 回应 + +`git push`操作非常相似,除了使用`git receive-pack`代替`git upload-pack` . + +如果未启用快速 SSH 密钥查找,则 SSH 服务器将从`~git/.ssh/authorized_keys`文件读取,以确定为给定的 SSH 会话运行什么命令. 它由 Rails 中的[`AuthorizedKeysWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/workers/authorized_keys_worker.rb)保持最新状态,并计划在用户修改 SSH 密钥时运行. + +可以使用[SSH 证书](../administration/operations/ssh_certificates.html)代替密钥. 在这种情况下, `AuthorizedKeysCommand`替换为`AuthorizedPrincipalsCommand` . 这将从证书中提取用户名,而无需使用 Rails 内部 API,该 API 稍后将代替`/api/internal/allowed`调用中的`key_id`使用. + +GitLab Shell 还具有一些不涉及 Gitaly 的操作,例如重置两因素身份验证代码. 这些操作以相同的方式处理,除了没有往返 Gitaly 的往返-Rails 作为[内部 API](internal_api.html)调用的一部分执行操作,并且 GitLab Shell 将响应直接流回用户. + +## System Layout[](#system-layout "Permalink") + +在图片中引用`~git`时,它表示 Git 用户的主目录,通常是`/home/git` . + +GitLab 主要以`git`用户身份安装在`/home/git`用户主目录中. GitLab 服务器软件以及存储库都位于主目录中(尽管存储库位置是可配置的). + +裸存储库位于`/home/git/repositories` . GitLab 是 Ruby on Rails 应用程序,因此可以通过研究 Ruby on Rails 应用程序的工作方式来了解内部工作的细节. + +为了通过 SSH 提供存储库,有一个名为 GitLab Shell 的附加应用程序,它安装在`/home/git/gitlab-shell` . + +### Installation Folder Summary[](#installation-folder-summary "Permalink") + +总结一下,这里是[`git`用户主目录](../install/structure.html)的[目录结构](../install/structure.html) . + +### Processes[](#processes "Permalink") + +``` +ps aux | grep '^git' +``` + +GitLab 有几个要运行的组件. 它需要一个持久数据库(PostgreSQL)和 Redis 数据库,并使用 Apache `httpd`或 NGINX 代理传递 Unicorn. 所有这些组件都应以与 GitLab 不同的系统用户身份运行(例如, `postgres` , `redis`和`www-data` ,而不是`git` ). + +作为`git`用户,它将启动 Sidekiq 和 Unicorn(默认情况下在端口`8080`上运行的简单 Ruby HTTP 服务器). 在 GitLab 用户下,通常有 4 个进程: `unicorn_rails master` (1 个进程), `unicorn_rails worker` (2 个进程), `sidekiq` (1 个进程). + +### Repository access[](#repository-access "Permalink") + +可以通过 HTTP 或 SSH 访问存储库. HTTP 克隆/推/拉使用 GitLab API,而 SSH 克隆由 GitLab Shell 处理(先前已说明). + +## Troubleshooting[](#troubleshooting "Permalink") + +有关更多信息,请参见自述文件. + +### Init scripts of the services[](#init-scripts-of-the-services "Permalink") + +GitLab 初始化脚本启动和停止 Unicorn 和 Sidekiq: + +``` +/etc/init.d/gitlab +Usage: service gitlab {start|stop|restart|reload|status} +``` + +Redis(键值存储/非持久数据库): + +``` +/etc/init.d/redis +Usage: /etc/init.d/redis {start|stop|status|restart|condrestart|try-restart} +``` + +SSH daemon: + +``` +/etc/init.d/sshd +Usage: /etc/init.d/sshd {start|stop|restart|reload|force-reload|condrestart|try-restart|status} +``` + +Web 服务器(以下之一): + +``` +/etc/init.d/httpd +Usage: httpd {start|stop|restart|condrestart|try-restart|force-reload|reload|status|fullstatus|graceful|help|configtest} + +$ /etc/init.d/nginx +Usage: nginx {start|stop|restart|reload|force-reload|status|configtest} +``` + +永久数据库: + +``` +$ /etc/init.d/postgresql +Usage: /etc/init.d/postgresql {start|stop|restart|reload|force-reload|status} [version ..] +``` + +### Log locations of the services[](#log-locations-of-the-services "Permalink") + +GitLab(包括 Unicorn 和 Sidekiq 日志): + +* `/home/git/gitlab/log/` contains `application.log`, `production.log`, `sidekiq.log`, `unicorn.stdout.log`, `git_json.log` and `unicorn.stderr.log` normally. + +GitLab 外壳: + +* `/home/git/gitlab-shell/gitlab-shell.log` + +SSH: + +* `/var/log/auth.log`身份验证日志(在 Ubuntu 上). +* `/var/log/secure`身份验证日志(在 RHEL 上). + +NGINX: + +* `/var/log/nginx/`包含错误和访问日志. + +Apache `httpd`: + +* [Explanation of Apache logs](https://httpd.apache.org/docs/2.2/logs.html). +* `/var/log/apache2/`包含错误和输出日志(在 Ubuntu 上). +* `/var/log/httpd/`包含错误和输出日志(在 RHEL 上). + +Redis: + +* `/var/log/redis/redis.log`那里还有日志循环日志. + +PostgreSQL: + +* `/var/log/postgresql/*` + +### GitLab specific configuration files[](#gitlab-specific-configuration-files "Permalink") + +GitLab 的配置文件位于`/home/git/gitlab/config/*` . 常用的配置文件包括: + +* `gitlab.yml` -GitLab 配置. +* `unicorn.rb` -Unicorn Web 服务器设置. +* `database.yml`数据库连接设置. + +GitLab Shell 在`/home/git/gitlab-shell/config.yml`有一个配置文件. + +### Maintenance Tasks[](#maintenance-tasks "Permalink") + +[GitLab](https://gitlab.com/gitlab-org/gitlab/tree/master)提供 Rake 任务,您可以在其中查看版本信息,并对配置进行快速检查以确保在应用程序中正确配置了它. 请参阅[维护 Rake 任务](../raketasks/maintenance.html) . 简而言之,请执行以下操作: + +``` +sudo -i -u git +cd gitlab +bundle exec rake gitlab:env:info RAILS_ENV=production +bundle exec rake gitlab:check RAILS_ENV=production +``` + +注意:建议使用`sudo -i -u git`或`sudo su - git`登录`git`用户. 尽管 GitLab 提供的 sudo 命令可在 Ubuntu 中运行,但它们并不总是在 RHEL 中运行. + +## GitLab.com[](#gitlabcom "Permalink") + +我们还详细介绍[了 GitLab.com 的体系结构,](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/)但是除非您拥有数百万的用户,否则这可能是最重要的. \ No newline at end of file diff --git a/_book/docs/559.md b/_book/docs/559.md new file mode 100644 index 0000000000000000000000000000000000000000..bab22d8e7dfa439f21cb846d5c8611c58089eb79 --- /dev/null +++ b/_book/docs/559.md @@ -0,0 +1,111 @@ +# CI/CD development documentation + +> 原文:[https://docs.gitlab.com/ee/development/cicd/](https://docs.gitlab.com/ee/development/cicd/) + +* [CI Architecture overview](#ci-architecture-overview) +* [Job scheduling](#job-scheduling) + * [Communication between Runner and GitLab server](#communication-between-runner-and-gitlab-server) + * [`Ci::RegisterJobService`](#ciregisterjobservice) + +# CI/CD development documentation[](#cicd-development-documentation "Permalink") + +此处列出了特定于 CI / CD 的开发指南. + +如果要创建新的 CI / CD 模板,请阅读[GitLab CI / CD 模板的开发指南](templates.html) . + +## CI Architecture overview[](#ci-architecture-overview "Permalink") + +以下是 CI 体系结构的简化图. 为了集中在主要组件上,省略了一些细节. + +[![CI software architecture](img/8069500bf085102224933129529dfa12.png)](img/ci_architecture.png) + +在左侧,我们有一些事件可以根据各种事件触发管道(由用户或自动化触发): + +* `git push`是触发管道的最常见事件. +* The [Web API](../../api/pipelines.html#create-a-new-pipeline). +* 用户单击 UI 中的"运行管道"按钮. +* [创建或更新合并请求时](../../ci/merge_request_pipelines/index.html#pipelines-for-merge-requests) . +* 将 MR 添加到[合并列车时](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html#merge-trains-premium) . +* A [scheduled pipeline](../../ci/pipelines/schedules.html#pipeline-schedules). +* 当项目被[订阅到上游项目时](../../ci/multi_project_pipelines.html#trigger-a-pipeline-when-an-upstream-project-is-rebuilt) . +* 启用[自动 DevOps 时](../../topics/autodevops/index.html) . +* 当 GitHub 集成用于[外部请求请求时](../../ci/ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests) . +* 当上游管道包含[桥接作业时](../../ci/yaml/README.html#trigger) ,该[作业](../../ci/yaml/README.html#trigger)会触发下游管道. + +触发任何这些事件将调用[`CreatePipelineService`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/ci/create_pipeline_service.rb) ,后者将输入事件数据并触发用户,然后尝试创建管道. + +`CreatePipelineService`很大程度上依赖于[`YAML Processor`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/yaml_processor.rb)组件,该组件负责将 YAML Blob 作为输入并返回管道的抽象数据结构(包括阶段和所有作业). 该组件还可以在处理 YAML 时验证其结构,并返回任何语法或语义错误. 在`YAML Processor`组件中,我们定义了[所有](../../ci/yaml/README.html)可用于构建管道[的关键字](../../ci/yaml/README.html) . + +`CreatePipelineService`接收`YAML Processor`返回的抽象数据结构,然后将其转换为持久化模型(管道,阶段,作业等). 之后,就可以处理管道了. 处理管道意味着按执行顺序(阶段或 DAG)运行作业,直到以下任一情况为止: + +* 所有预期的作业均已执行. +* 故障会中断管道执行. + +处理管道的组件是[`ProcessPipelineService`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/ci/process_pipeline_service.rb) ,它负责将所有管道的作业移至完成状态. 创建管道时,其所有作业最初都处于`created`状态. 该服务根据流水线结构查看在`created`阶段可以处理哪些作业. 然后,它们将它们移到`pending`状态,这意味着它们现在[可以被 Runner 拾取](#job-scheduling) . 执行作业后,它可以成功完成或失败. 管道中作业的每个状态转换都会再次触发此服务,该服务会寻找下一个要转换为完成的作业. 在此过程中, `ProcessPipelineService`更新作业,阶段和整个管道的状态. + +在图的右侧,我们有一个列表[运动员](../../ci/runners/README.html#configuring-gitlab-runners)连接到 GitLab 实例. 这些可以是共享运行者,组运行者或项目特定的运行者. Runners 与 Rails 服务器之间的通信通过一组 API 端点(称为`Runner API Gateway` . + +我们可以注册,删除和验证运行器,这也将导致对数据库的读/写查询. 连接了 Runner 之后,它会继续询问要执行的下一个作业. 这将调用[`RegisterJobService`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/services/ci/register_job_service.rb) ,后者将选择下一个作业并将其分配给 Runner. 此时,作业将转换为`running`状态,由于状态更改,该状态再次触发`ProcessPipelineService` . 有关更多详细信息,请参阅" [作业调度"](#job-scheduling) . + +在执行作业时,运行程序将日志以及任何可能需要存储的工件发送回服务器. 此外,作业可能依赖于先前作业中的工件才能运行. 在这种情况下,Runner 将使用专用的 API 端点下载它们. + +工件存储在对象存储中,而元数据保留在数据库中. 工件的重要示例是报表(JUnit,SAST,DAST 等),这些报表在合并请求中进行了解析和呈现. + +作业状态转换并非全部自动化. 用户可以运行[手动作业](../../ci/yaml/README.html#whenmanual) ,取消管道,重试特定的失败作业或整个管道. 导致作业更改状态的任何事件都将触发`ProcessPipelineService` ,因为它负责跟踪整个管道的状态. + +一种特殊类型的作业是[桥接作业](../../ci/yaml/README.html#trigger) ,当过渡到`pending`状态时,该[作业](../../ci/yaml/README.html#trigger)在服务器端执行. 这项工作负责创建下游管道,例如多项目或子管道. 每次触发下游管道时,工作流程循环都将从`CreatePipelineService`重新开始. + +## Job scheduling[](#job-scheduling "Permalink") + +创建管道时,将为所有阶段一次创建所有作业,初始状态为`created` . 这使得可视化管道的全部内容成为可能. + +跑步者将不会看到具有`created`状态的作业. 为了能够将作业分配给 Runner,该作业必须首先转换为`pending`状态,这在以下情况下可能发生: + +1. 作业是在管道的第一阶段创建的. +2. 该作业需要手动启动,并且已被触发. +3. 前一阶段的所有作业均已成功完成. 在这种情况下,我们将所有工作从下一阶段过渡到`pending` . +4. 该作业使用`needs:`指定了 DAG 依赖项`needs:`并且所有依赖项都已完成. + +连接了 Runner 时,它将通过连续轮询服务器来请求下一个`pending`作业运行. + +**注意:** Runner 用于与 GitLab 交互的 API 端点在[`lib/api/runner.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/runner.rb)中定义 + +服务器收到请求后,将根据[`Ci::RegisterJobService`算法](#ciregisterjobservice)选择`pending`作业,然后将其分配并发送给 Runner. + +在当前阶段完成所有作业后,服务器通过将其状态更改为" `pending` ",从下一阶段"解锁"所有作业. 现在,当 Runner 请求新作业时,可以由调度算法选择这些内容,并像这样继续进行,直到完成所有阶段. + +### Communication between Runner and GitLab server[](#communication-between-runner-and-gitlab-server "Permalink") + +使用注册令牌[注册](https://docs.gitlab.com/runner/register/)了 Runner 之后,服务器便知道其可以执行的作业类型. 这取决于: + +* 它注册的赛跑者类型为: + * 共享跑步者 + * 团体赛跑者 + * 项目特定的跑步者 +* 任何关联的标签. + +跑步者通过请求作业执行`POST /api/v4/jobs/request`来启动通信. 尽管轮询通常每隔几秒钟发生一次,但如果作业队列不变,我们将通过 HTTP 标头利用缓存来减少服务器端的工作量. + +该 API 端点运行[`Ci::RegisterJobService`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/services/ci/register_job_service.rb) ,该命令: + +1. 从`pending`作业池中选择要运行的下一个作业 +2. 分配给跑步者 +3. 通过 API 响应将其呈现给 Runner + +### `Ci::RegisterJobService`[](#ciregisterjobservice "Permalink") + +此服务使用 3 个顶级查询来收集大多数作业,并且根据 Runner 注册到的级别选择它们: + +* 选择共享的 Runner(实例级别)的作业 +* 选择组级别运行器的作业 +* 选择项目亚军的工作 + +This list of jobs is then filtered further by matching tags between job and Runner tags. + +**注意:**如果作业包含标签,则与**所有**标签都不匹配的跑步者将不会选择该作业. 跑步者可能具有比该工作定义的标签更多的标签,但反之则没有. + +最后,如果 Runner 仅能选择带标签的作业,则所有未带标签的作业都会被过滤掉. + +在这一点上,我们遍历剩余的`pending`作业,然后尝试根据其他策略分配"可以选择" Runner 可以选择的第一个作业. 例如,标记为`protected`运行者只能选择针对受保护的分支(例如生产部署)运行的作业. + +当我们增加池中的"奔跑者"数量时,如果将同一工作分配给不同"奔跑者",也会增加发生冲突的机会. 为防止这种情况,我们会适当地挽救冲突错误并在列表中分配下一个作业. \ No newline at end of file diff --git a/_book/docs/560.md b/_book/docs/560.md new file mode 100644 index 0000000000000000000000000000000000000000..10cc66941110f938c882b7cb1bc6d49e968d208c --- /dev/null +++ b/_book/docs/560.md @@ -0,0 +1,67 @@ +# Database guides + +> 原文:[https://docs.gitlab.com/ee/development/database/](https://docs.gitlab.com/ee/development/database/) + +* [Database Reviews](#database-reviews) +* [Tooling](#tooling) +* [Migrations](#migrations) +* [Debugging](#debugging) +* [Best practices](#best-practices) +* [Case studies](#case-studies) + +# Database guides[](#database-guides "Permalink") + +## Database Reviews[](#database-reviews "Permalink") + +* 如果您要创建数据库 MR 进行审查,请查看我们的[数据库审查指南](../database_review.html) . + + 它介绍了与数据库相关的更改,迁移和复杂的 SQL 查询. + +* 如果您是数据库审阅者或想成为一名数据库审阅者,请查看我们的数据库审阅[简介](database_reviewer_guidelines.html) . + +## Tooling[](#tooling "Permalink") + +* [Understanding EXPLAIN plans](../understanding_explain_plans.html) +* [explain.depesz.com](https://explain.depesz.com/)或[explain.dalibo.com,](https://explain.dalibo.com/)用于可视化`EXPLAIN`的输出 +* [pgFormatter](http://sqlformat.darold.net/) PostgreSQL SQL 语法美化器 + +## Migrations[](#migrations "Permalink") + +* [What requires downtime?](../what_requires_downtime.html) +* 用于 SQL 查询的[SQL 准则](../sql.html) +* 用于创建安全的 SQL 迁移的[迁移样式指南](../migration_style_guide.html) +* [Testing Rails migrations](../testing_guide/testing_migrations_guide.html) guide +* [Post deployment migrations](../post_deployment_migrations.html) +* [Background migrations](../background_migrations.html) +* [Swapping tables](../swapping_tables.html) +* [Deleting migrations](../deleting_migrations.html) + +## Debugging[](#debugging "Permalink") + +* 使用带有[Marginalia 的](../database_query_comments.html)查询注释来跟踪 SQL 查询的源 +* 使用[详细查询日志](https://guides.rubyonrails.org/debugging_rails_applications.html#verbose-query-logs)在 Rails 控制台中跟踪 SQL 查询的源 + +## Best practices[](#best-practices "Permalink") + +* [Adding database indexes](../adding_database_indexes.html) +* [Foreign keys & associations](../foreign_keys.html) +* [Adding a foreign key constraint to an existing column](add_foreign_key_to_existing_column.html) +* [`NOT NULL` constraints](not_null_constraints.html) +* [Strings and the Text data type](strings_and_the_text_data_type.html) +* [Single table inheritance](../single_table_inheritance.html) +* [Polymorphic associations](../polymorphic_associations.html) +* [Serializing data](../serializing_data.html) +* [Hash indexes](../hash_indexes.html) +* [Storing SHA1 hashes as binary](../sha1_as_binary.html) +* [Iterating tables in batches](../iterating_tables_in_batches.html) +* [Insert into tables in batches](../insert_into_tables_in_batches.html) +* [Ordering table columns](../ordering_table_columns.html) +* [Verifying database capabilities](../verifying_database_capabilities.html) +* [Database Debugging and Troubleshooting](../database_debugging.html) +* [Query Count Limits](../query_count_limits.html) +* [Creating enums](../creating_enums.html) + +## Case studies[](#case-studies "Permalink") + +* [Database case study: Filtering by label](../filtering_by_label.html) +* [Database case study: Namespaces storage statistics](../namespaces_storage_statistics.html) \ No newline at end of file diff --git a/_book/docs/561.md b/_book/docs/561.md new file mode 100644 index 0000000000000000000000000000000000000000..0765bf894d5b4cc72578c6bf43b7758fa545d328 --- /dev/null +++ b/_book/docs/561.md @@ -0,0 +1,157 @@ +# Database Review Guidelines + +> 原文:[https://docs.gitlab.com/ee/development/database_review.html](https://docs.gitlab.com/ee/development/database_review.html) + +* [General process](#general-process) + * [Roles and process](#roles-and-process) + * [Distributing review workload](#distributing-review-workload) + * [How to prepare the merge request for a database review](#how-to-prepare-the-merge-request-for-a-database-review) + * [Preparation when adding migrations](#preparation-when-adding-migrations) + * [Preparation when adding or modifying queries](#preparation-when-adding-or-modifying-queries) + * [Preparation when adding foreign keys to existing tables](#preparation-when-adding-foreign-keys-to-existing-tables) + * [Preparation when adding tables](#preparation-when-adding-tables) + * [Preparation when removing columns, tables, indexes, or other structures](#preparation-when-removing-columns-tables-indexes-or-other-structures) + * [How to review for database](#how-to-review-for-database) + * [Timing guidelines for migrations](#timing-guidelines-for-migrations) + +# Database Review Guidelines[](#database-review-guidelines "Permalink") + +此页面特定于数据库评论. 请参阅我们的[代码审查指南](code_review.html) ,以获取有关[代码审查](code_review.html)的更广泛建议和最佳实践. + +## General process[](#general-process "Permalink") + +A database review is required for: + +* 涉及数据库架构或执行数据迁移的更改,包括以下文件: + * `db/` + * `lib/gitlab/background_migration/` +* 对数据库工具的更改. 例如: + * `lib/gitlab/database/`迁移或 ActiveRecord 助手 + * 负载均衡 +* 产生 SQL 查询的更改超出了显而易见的范围. 通常由合并请求的作者决定是否引入复杂查询以及是否需要数据库审查. + +期望数据库审阅者在更改中查找明显复杂的查询,并仔细检查那些查询. 如果作者没有指出要审核的特定查询,并且没有明显复杂的查询,那么仅专注于审核迁移就足够了. + +最好以 SQL 形式复审查询,并且通常要求作者翻译 SQL 形式的任何 ActiveRecord 查询以复审. + +### Roles and process[](#roles-and-process "Permalink") + +合并请求**作者**的角色是: + +* 确定是否需要数据库审查. +* 如果需要数据库检查,请添加〜database 标签. +* [Prepare the merge request for a database review](#how-to-prepare-the-merge-request-for-a-database-review). + +数据库**审阅者**的角色是: + +* 对 MR 进行一次初审,并向作者提出改进建议. +* 一旦满意,请用〜" database :: reviewed"重新标记 MR,批准,然后将 MR 重新分配给 Reviewer Roulette 建议的数据库**维护者** . + +数据库**维护者**的作用是: + +* 在 MR 上执行最终数据库审查. +* 与数据库审阅者和 MR 作者讨论进一步的改进或其他相关更改. +* 最后批准 MR,并使用〜" database :: approved"重新标记 MR +* 如果没有其他待批准的批准,则合并 MR,或根据需要将其传递给其他维护者(前端,后端,文档). + +### Distributing review workload[](#distributing-review-workload "Permalink") + +使用[审阅者轮盘](code_review.html#reviewer-roulette) ( [示例](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25181#note_147551725) )分配[审阅](code_review.html#reviewer-roulette)工作量. 然后,MR 作者应共同指派建议的数据库**审阅者** . 当他们批准时,他们将移交给建议的数据库**维护者** . + +如果审阅者轮盘赌没有建议数据库审阅者和维护者,请确保已应用〜database 标签并重新运行`danger-review` CI 作业,或从[`@gl-database`团队中](https://gitlab.com/groups/gl-database/-/group_members)选择某人. + +### How to prepare the merge request for a database review[](#how-to-prepare-the-merge-request-for-a-database-review "Permalink") + +为了使审核更加轻松快捷,请考虑以下准备工作. + +#### Preparation when adding migrations[](#preparation-when-adding-migrations "Permalink") + +* 确保`db/structure.sql`已按照[记录进行](migration_style_guide.html#schema-changes)更新. +* 通过使用`change`方法使迁移可逆,或者在使用`up`时包括`down`方法. + * 包括回滚过程或描述如何回滚更改. +* 将所有迁移的迁移和回滚的输出添加到 MR 描述中. + * 确保 down 方法还原`db/structure.sql`的更改. + * 在查看过程中,只要您修改迁移,就更新迁移输出. +* 如有必要,在`spec/migrations`添加迁移测试. 有关更多详细信息,请参见[在 GitLab 上测试 Rails 迁移](testing_guide/testing_migrations_guide.html) . +* 当迁移中涉及[高流量](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3)表时,请使用[`with_lock_retries`](migration_style_guide.html#retry-mechanism-when-acquiring-database-locks)帮助程序方法. 请查看[我们文档中](migration_style_guide.html#examples)的相关[示例以](migration_style_guide.html#examples)获取用例和解决方案. +* Ensure RuboCop checks are not disabled unless there’s a valid reason to. +* 将索引添加到[大表时](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3) ,请在`#database-lab` Slack 通道中使用`CREATE INDEX CONCURRENTLY`测试其执行,并将执行时间添加到 MR 描述中: + * `#database-lab`和 GitLab.com 之间的执行时间差异很大,但是`#database-lab`执行时间增加,可能暗示 GitLab.com 上的执行量也很高. + * 如果`#database-lab`的执行时间超过`1h` ,则应将索引移至[迁移后](post_deployment_migrations.html) . 请记住,在这种情况下,您可能需要将迁移和应用程序更改分为不同的版本,以确保在部署需要索引的代码时索引就位. + +#### Preparation when adding or modifying queries[](#preparation-when-adding-or-modifying-queries "Permalink") + +* 在 MR 说明中编写原始 SQL. 最好用[pgFormatter](https://sqlformat.darold.net)或[paste.depesz.com](https://paste.depesz.com)很好地格式化. +* 在描述中包括相关查询的`EXPLAIN (ANALYZE, BUFFERS)`输出. 如果输出太长,请将其包装在`
    `块中,将其粘贴到 GitLab 代码片段中,或在以下位置提供指向计划的链接: [explain.depesz.com](https://explain.depesz.com) . +* 提供查询计划时,请确保其命中足够的数据: + * 您可以通过`#database-lab` Slack 通道或[chatops](understanding_explain_plans.html#chatops)使用 GitLab 生产副本大规模测试查询. + * 通常, `gitlab-org`命名空间( `namespace_id = 9970` )和`gitlab-org/gitlab-foss` ( `project_id = 13083` )或`gitlab-org/gitlab` ( `project_id = 278964` )项目提供了足够的数据作为一个很好的例子. +* 对于查询的变化,最好是与*前*和变更*后*的方案一起提供的 SQL 查询. 这有助于快速发现差异. +* 包括显示性能改善的数据,最好以基准形式显示. + +#### Preparation when adding foreign keys to existing tables[](#preparation-when-adding-foreign-keys-to-existing-tables "Permalink") + +* **在**添加外键**之前,**进行迁移以删除源表中的孤立行. +* 删除所有`dependent: ...`实例`dependent: ...`可能不再需要. + +#### Preparation when adding tables[](#preparation-when-adding-tables "Permalink") + +* 根据" [订购表列"](ordering_table_columns.html)准则[订购列](ordering_table_columns.html) . +* 将外键添加到指向其他表中数据的任何列,包括[index](migration_style_guide.html#adding-foreign-key-constraints) . +* 为在诸如`WHERE` , `ORDER BY` , `GROUP BY`和`JOIN`的语句中使用的字段添加索引. + +#### Preparation when removing columns, tables, indexes, or other structures[](#preparation-when-removing-columns-tables-indexes-or-other-structures "Permalink") + +* 遵循[有关删除列](what_requires_downtime.html#dropping-columns)的[准则](what_requires_downtime.html#dropping-columns) . +* 通常,最佳实践(但不是硬性规定)是在部署后迁移中删除索引和外键. + * 例外包括删除小型表的索引和外键. +* 如果要添加复合索引,则另一个索引可能会变得多余,因此请在同一迁移中将其删除. 例如,添加`index(column_A, column_B, column_C)`会使索引`index(column_A, column_B)`和`index(column_A)`冗余. + +### How to review for database[](#how-to-review-for-database "Permalink") + +* 检查迁移 + * 审查关系建模和设计选择 + * 查看迁移遵循[数据库迁移样式指南](migration_style_guide.html) ,例如 + * [检查列的顺序](ordering_table_columns.html) + * [检查索引是否存在外键](migration_style_guide.html#adding-foreign-key-constraints) + * 确保迁移在事务中执行,或仅包含并发索引/外键助手(已禁用事务) + * 如果在`#database-lab`上添加了指向大表的索引,并且其执行时间增加了(超过 1h): + * 确保在迁移后将其添加. + * 维护者:合并请求合并后,在`#f_upcoming_release` Slack 频道`#f_upcoming_release`其通知发布管理器. + * 检查与`db/structure.sql`一致性,并且迁移是[可逆的](migration_style_guide.html#reversibility) + * 检查查询时间(如果有的话):在迁移中执行的查询需要在 GitLab.com 上适应`15s`以内(最好比`15s`少). + * 对于列删除,请确保[在先前版本中](what_requires_downtime.html#dropping-columns)已[忽略](what_requires_downtime.html#dropping-columns)该列 +* Check [background migrations](background_migrations.html): + * 建立在 GitLab.com 上执行的时间估计. 出于历史目的,强烈建议在合并请求描述中包括此估计. + * 如果单个`update`低于`1s` ,则可以将查询直接放入常规迁移中(在`db/migrate`内部). + * 通常使用后台迁移,但不限于: + * 在较大的表中迁移数据. + * 对数据集中的每条记录进行大量 SQL 查询. + * 查看查询(例如,确保批次大小合适) + * 因为执行时间可能比常规迁移要长,所以建议将后台迁移视为后期迁移:将它们放在`db/post_migrate`而不是`db/migrate` . 请记住,后迁移是在生产中的部署后执行的. +* Check [timing guidelines for migrations](#timing-guidelines-for-migrations) +* 检查迁移是可逆的,并实现`#down`方法 +* 检查数据迁移: + * 建立在 GitLab.com 上执行的时间估计. + * 根据时间的不同,可以将数据迁移放在常规,部署后或后台迁移上. + * 数据迁移也应该是可逆的,或者在可能的情况下附带有关如何逆向的描述. 这适用于所有类型的迁移(常规,部署后,后台). +* 查询效果 + * 检查是否有任何明显复杂的查询,以及作者特别指出要进行审查的查询(如果有) + * 如果尚不存在,请要求作者提供 SQL 查询和查询计划(例如,通过使用[chatops](understanding_explain_plans.html#chatops)或直接数据库访问) + * 对于给定的查询,请查看有关数据分配的参数 + * [检查查询计划](understanding_explain_plans.html)并提出对查询的改进建议(更改查询,架构或添加索引等) + * 一般准则是查询执行时间少于 100 毫秒 + * 如果查询依赖于尚未在生产环境中进行的先前迁移(例如,索引,列),则可以使用[还原管道](https://ops.gitlab.net/gitlab-com/gl-infra/gitlab-restore/postgres-gprd)中[的一次性实例](https://ops.gitlab.net/gitlab-com/gl-infra/gitlab-restore/postgres-gprd)来建立适当的测试环境. 如果您无权访问此项目,请访问 Slack 上的#database 以获取有关如何进行的建议. + * 避免 N + 1 问题并最大程度地减少[查询数](merge_request_performance_guidelines.html#query-counts) . + +### Timing guidelines for migrations[](#timing-guidelines-for-migrations "Permalink") + +通常,对于单个部署,GitLab.com 的迁移时间不应超过 1 个小时. 以下准则不是硬性规定,据估计,这些准则可将迁移时间降到最低. + +**注意:**请记住,所有运行时均应根据 GitLab.com 进行测量. + +| 迁移类型 | 建议执行时间 | Notes | +| --- | --- | --- | +| 定期迁移`db/migrate` | `3 minutes` | 一个有效的例外是创建索引,因为这可能需要很长时间. | +| 在`db/post_migrate`上发布迁移 | `10 minutes` |   | +| 后台迁移 |  — | 由于它们适用于较大的表,因此无法设置精确的时序准则,但是,任何单个查询的冷缓存都必须保持在`1 second`以下的执行时间. | \ No newline at end of file diff --git a/_book/docs/562.md b/_book/docs/562.md new file mode 100644 index 0000000000000000000000000000000000000000..0765bf894d5b4cc72578c6bf43b7758fa545d328 --- /dev/null +++ b/_book/docs/562.md @@ -0,0 +1,157 @@ +# Database Review Guidelines + +> 原文:[https://docs.gitlab.com/ee/development/database_review.html](https://docs.gitlab.com/ee/development/database_review.html) + +* [General process](#general-process) + * [Roles and process](#roles-and-process) + * [Distributing review workload](#distributing-review-workload) + * [How to prepare the merge request for a database review](#how-to-prepare-the-merge-request-for-a-database-review) + * [Preparation when adding migrations](#preparation-when-adding-migrations) + * [Preparation when adding or modifying queries](#preparation-when-adding-or-modifying-queries) + * [Preparation when adding foreign keys to existing tables](#preparation-when-adding-foreign-keys-to-existing-tables) + * [Preparation when adding tables](#preparation-when-adding-tables) + * [Preparation when removing columns, tables, indexes, or other structures](#preparation-when-removing-columns-tables-indexes-or-other-structures) + * [How to review for database](#how-to-review-for-database) + * [Timing guidelines for migrations](#timing-guidelines-for-migrations) + +# Database Review Guidelines[](#database-review-guidelines "Permalink") + +此页面特定于数据库评论. 请参阅我们的[代码审查指南](code_review.html) ,以获取有关[代码审查](code_review.html)的更广泛建议和最佳实践. + +## General process[](#general-process "Permalink") + +A database review is required for: + +* 涉及数据库架构或执行数据迁移的更改,包括以下文件: + * `db/` + * `lib/gitlab/background_migration/` +* 对数据库工具的更改. 例如: + * `lib/gitlab/database/`迁移或 ActiveRecord 助手 + * 负载均衡 +* 产生 SQL 查询的更改超出了显而易见的范围. 通常由合并请求的作者决定是否引入复杂查询以及是否需要数据库审查. + +期望数据库审阅者在更改中查找明显复杂的查询,并仔细检查那些查询. 如果作者没有指出要审核的特定查询,并且没有明显复杂的查询,那么仅专注于审核迁移就足够了. + +最好以 SQL 形式复审查询,并且通常要求作者翻译 SQL 形式的任何 ActiveRecord 查询以复审. + +### Roles and process[](#roles-and-process "Permalink") + +合并请求**作者**的角色是: + +* 确定是否需要数据库审查. +* 如果需要数据库检查,请添加〜database 标签. +* [Prepare the merge request for a database review](#how-to-prepare-the-merge-request-for-a-database-review). + +数据库**审阅者**的角色是: + +* 对 MR 进行一次初审,并向作者提出改进建议. +* 一旦满意,请用〜" database :: reviewed"重新标记 MR,批准,然后将 MR 重新分配给 Reviewer Roulette 建议的数据库**维护者** . + +数据库**维护者**的作用是: + +* 在 MR 上执行最终数据库审查. +* 与数据库审阅者和 MR 作者讨论进一步的改进或其他相关更改. +* 最后批准 MR,并使用〜" database :: approved"重新标记 MR +* 如果没有其他待批准的批准,则合并 MR,或根据需要将其传递给其他维护者(前端,后端,文档). + +### Distributing review workload[](#distributing-review-workload "Permalink") + +使用[审阅者轮盘](code_review.html#reviewer-roulette) ( [示例](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25181#note_147551725) )分配[审阅](code_review.html#reviewer-roulette)工作量. 然后,MR 作者应共同指派建议的数据库**审阅者** . 当他们批准时,他们将移交给建议的数据库**维护者** . + +如果审阅者轮盘赌没有建议数据库审阅者和维护者,请确保已应用〜database 标签并重新运行`danger-review` CI 作业,或从[`@gl-database`团队中](https://gitlab.com/groups/gl-database/-/group_members)选择某人. + +### How to prepare the merge request for a database review[](#how-to-prepare-the-merge-request-for-a-database-review "Permalink") + +为了使审核更加轻松快捷,请考虑以下准备工作. + +#### Preparation when adding migrations[](#preparation-when-adding-migrations "Permalink") + +* 确保`db/structure.sql`已按照[记录进行](migration_style_guide.html#schema-changes)更新. +* 通过使用`change`方法使迁移可逆,或者在使用`up`时包括`down`方法. + * 包括回滚过程或描述如何回滚更改. +* 将所有迁移的迁移和回滚的输出添加到 MR 描述中. + * 确保 down 方法还原`db/structure.sql`的更改. + * 在查看过程中,只要您修改迁移,就更新迁移输出. +* 如有必要,在`spec/migrations`添加迁移测试. 有关更多详细信息,请参见[在 GitLab 上测试 Rails 迁移](testing_guide/testing_migrations_guide.html) . +* 当迁移中涉及[高流量](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3)表时,请使用[`with_lock_retries`](migration_style_guide.html#retry-mechanism-when-acquiring-database-locks)帮助程序方法. 请查看[我们文档中](migration_style_guide.html#examples)的相关[示例以](migration_style_guide.html#examples)获取用例和解决方案. +* Ensure RuboCop checks are not disabled unless there’s a valid reason to. +* 将索引添加到[大表时](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3) ,请在`#database-lab` Slack 通道中使用`CREATE INDEX CONCURRENTLY`测试其执行,并将执行时间添加到 MR 描述中: + * `#database-lab`和 GitLab.com 之间的执行时间差异很大,但是`#database-lab`执行时间增加,可能暗示 GitLab.com 上的执行量也很高. + * 如果`#database-lab`的执行时间超过`1h` ,则应将索引移至[迁移后](post_deployment_migrations.html) . 请记住,在这种情况下,您可能需要将迁移和应用程序更改分为不同的版本,以确保在部署需要索引的代码时索引就位. + +#### Preparation when adding or modifying queries[](#preparation-when-adding-or-modifying-queries "Permalink") + +* 在 MR 说明中编写原始 SQL. 最好用[pgFormatter](https://sqlformat.darold.net)或[paste.depesz.com](https://paste.depesz.com)很好地格式化. +* 在描述中包括相关查询的`EXPLAIN (ANALYZE, BUFFERS)`输出. 如果输出太长,请将其包装在`
    `块中,将其粘贴到 GitLab 代码片段中,或在以下位置提供指向计划的链接: [explain.depesz.com](https://explain.depesz.com) . +* 提供查询计划时,请确保其命中足够的数据: + * 您可以通过`#database-lab` Slack 通道或[chatops](understanding_explain_plans.html#chatops)使用 GitLab 生产副本大规模测试查询. + * 通常, `gitlab-org`命名空间( `namespace_id = 9970` )和`gitlab-org/gitlab-foss` ( `project_id = 13083` )或`gitlab-org/gitlab` ( `project_id = 278964` )项目提供了足够的数据作为一个很好的例子. +* 对于查询的变化,最好是与*前*和变更*后*的方案一起提供的 SQL 查询. 这有助于快速发现差异. +* 包括显示性能改善的数据,最好以基准形式显示. + +#### Preparation when adding foreign keys to existing tables[](#preparation-when-adding-foreign-keys-to-existing-tables "Permalink") + +* **在**添加外键**之前,**进行迁移以删除源表中的孤立行. +* 删除所有`dependent: ...`实例`dependent: ...`可能不再需要. + +#### Preparation when adding tables[](#preparation-when-adding-tables "Permalink") + +* 根据" [订购表列"](ordering_table_columns.html)准则[订购列](ordering_table_columns.html) . +* 将外键添加到指向其他表中数据的任何列,包括[index](migration_style_guide.html#adding-foreign-key-constraints) . +* 为在诸如`WHERE` , `ORDER BY` , `GROUP BY`和`JOIN`的语句中使用的字段添加索引. + +#### Preparation when removing columns, tables, indexes, or other structures[](#preparation-when-removing-columns-tables-indexes-or-other-structures "Permalink") + +* 遵循[有关删除列](what_requires_downtime.html#dropping-columns)的[准则](what_requires_downtime.html#dropping-columns) . +* 通常,最佳实践(但不是硬性规定)是在部署后迁移中删除索引和外键. + * 例外包括删除小型表的索引和外键. +* 如果要添加复合索引,则另一个索引可能会变得多余,因此请在同一迁移中将其删除. 例如,添加`index(column_A, column_B, column_C)`会使索引`index(column_A, column_B)`和`index(column_A)`冗余. + +### How to review for database[](#how-to-review-for-database "Permalink") + +* 检查迁移 + * 审查关系建模和设计选择 + * 查看迁移遵循[数据库迁移样式指南](migration_style_guide.html) ,例如 + * [检查列的顺序](ordering_table_columns.html) + * [检查索引是否存在外键](migration_style_guide.html#adding-foreign-key-constraints) + * 确保迁移在事务中执行,或仅包含并发索引/外键助手(已禁用事务) + * 如果在`#database-lab`上添加了指向大表的索引,并且其执行时间增加了(超过 1h): + * 确保在迁移后将其添加. + * 维护者:合并请求合并后,在`#f_upcoming_release` Slack 频道`#f_upcoming_release`其通知发布管理器. + * 检查与`db/structure.sql`一致性,并且迁移是[可逆的](migration_style_guide.html#reversibility) + * 检查查询时间(如果有的话):在迁移中执行的查询需要在 GitLab.com 上适应`15s`以内(最好比`15s`少). + * 对于列删除,请确保[在先前版本中](what_requires_downtime.html#dropping-columns)已[忽略](what_requires_downtime.html#dropping-columns)该列 +* Check [background migrations](background_migrations.html): + * 建立在 GitLab.com 上执行的时间估计. 出于历史目的,强烈建议在合并请求描述中包括此估计. + * 如果单个`update`低于`1s` ,则可以将查询直接放入常规迁移中(在`db/migrate`内部). + * 通常使用后台迁移,但不限于: + * 在较大的表中迁移数据. + * 对数据集中的每条记录进行大量 SQL 查询. + * 查看查询(例如,确保批次大小合适) + * 因为执行时间可能比常规迁移要长,所以建议将后台迁移视为后期迁移:将它们放在`db/post_migrate`而不是`db/migrate` . 请记住,后迁移是在生产中的部署后执行的. +* Check [timing guidelines for migrations](#timing-guidelines-for-migrations) +* 检查迁移是可逆的,并实现`#down`方法 +* 检查数据迁移: + * 建立在 GitLab.com 上执行的时间估计. + * 根据时间的不同,可以将数据迁移放在常规,部署后或后台迁移上. + * 数据迁移也应该是可逆的,或者在可能的情况下附带有关如何逆向的描述. 这适用于所有类型的迁移(常规,部署后,后台). +* 查询效果 + * 检查是否有任何明显复杂的查询,以及作者特别指出要进行审查的查询(如果有) + * 如果尚不存在,请要求作者提供 SQL 查询和查询计划(例如,通过使用[chatops](understanding_explain_plans.html#chatops)或直接数据库访问) + * 对于给定的查询,请查看有关数据分配的参数 + * [检查查询计划](understanding_explain_plans.html)并提出对查询的改进建议(更改查询,架构或添加索引等) + * 一般准则是查询执行时间少于 100 毫秒 + * 如果查询依赖于尚未在生产环境中进行的先前迁移(例如,索引,列),则可以使用[还原管道](https://ops.gitlab.net/gitlab-com/gl-infra/gitlab-restore/postgres-gprd)中[的一次性实例](https://ops.gitlab.net/gitlab-com/gl-infra/gitlab-restore/postgres-gprd)来建立适当的测试环境. 如果您无权访问此项目,请访问 Slack 上的#database 以获取有关如何进行的建议. + * 避免 N + 1 问题并最大程度地减少[查询数](merge_request_performance_guidelines.html#query-counts) . + +### Timing guidelines for migrations[](#timing-guidelines-for-migrations "Permalink") + +通常,对于单个部署,GitLab.com 的迁移时间不应超过 1 个小时. 以下准则不是硬性规定,据估计,这些准则可将迁移时间降到最低. + +**注意:**请记住,所有运行时均应根据 GitLab.com 进行测量. + +| 迁移类型 | 建议执行时间 | Notes | +| --- | --- | --- | +| 定期迁移`db/migrate` | `3 minutes` | 一个有效的例外是创建索引,因为这可能需要很长时间. | +| 在`db/post_migrate`上发布迁移 | `10 minutes` |   | +| 后台迁移 |  — | 由于它们适用于较大的表,因此无法设置精确的时序准则,但是,任何单个查询的冷缓存都必须保持在`1 second`以下的执行时间. | \ No newline at end of file diff --git a/_book/docs/563.md b/_book/docs/563.md new file mode 100644 index 0000000000000000000000000000000000000000..0fb587b4006c16998a56f4cec1f6e7de318d0796 --- /dev/null +++ b/_book/docs/563.md @@ -0,0 +1,769 @@ +# Migration Style Guide + +> 原文:[https://docs.gitlab.com/ee/development/migration_style_guide.html](https://docs.gitlab.com/ee/development/migration_style_guide.html) + +* [Schema Changes](#schema-changes) +* [What Requires Downtime?](#what-requires-downtime) +* [Downtime Tagging](#downtime-tagging) +* [Reversibility](#reversibility) +* [Atomicity](#atomicity) +* [Heavy operations in a single transaction](#heavy-operations-in-a-single-transaction) +* [Retry mechanism when acquiring database locks](#retry-mechanism-when-acquiring-database-locks) + * [Examples](#examples) + * [When to use the helper method](#when-to-use-the-helper-method) + * [How the helper method works](#how-the-helper-method-works) +* [Multi-Threading](#multi-threading) +* [Removing indexes](#removing-indexes) +* [Adding indexes](#adding-indexes) +* [Adding foreign-key constraints](#adding-foreign-key-constraints) +* [`NOT NULL` constraints](#not-null-constraints) +* [Adding Columns With Default Values](#adding-columns-with-default-values) +* [Changing the column default](#changing-the-column-default) +* [Updating an existing column](#updating-an-existing-column) +* [Dropping a database table](#dropping-a-database-table) +* [Integer column type](#integer-column-type) +* [Strings and the Text data type](#strings-and-the-text-data-type) +* [Timestamp column type](#timestamp-column-type) +* [Storing JSON in database](#storing-json-in-database) +* [Testing](#testing) +* [Data migration](#data-migration) + * [Renaming reserved paths](#renaming-reserved-paths) + +# Migration Style Guide[](#migration-style-guide "Permalink") + +在为 GitLab 编写迁移时,必须考虑到这些迁移将由成千上万个各种规模的组织来运行,其中一些组织的数据库中包含多年的数据. + +此外,对于大多数组织来说,必须使服务器脱机以进行较小或较大的升级是一大负担. 因此,重要的是要仔细编写迁移文件,可以在线进行迁移,并遵守下面的样式指南. + +迁移**不准**要求 GitLab 设施采取离线,除非*绝对必要的* . + +如果需要停机,则必须通过以下方式批准迁移: + +1. 工程副总裁 +2. 后端维护者 +3. 数据库维护者 + +可以在[https://about.gitlab.com/company/team/中](https://about.gitlab.com/company/team/)找到持有这些头衔的人员的最新列表. + +When writing your migrations, also consider that databases might have stale data or inconsistencies and guard for that. Try to make as few assumptions as possible about the state of the database. + +请不要依赖特定于 GitLab 的代码,因为它可能会在将来的版本中更改. 如果需要,将 GitLab 代码复制粘贴到迁移中以使其向前兼容. + +对于 GitLab.com,请考虑到在[部署 Canary](https://about.gitlab.com/handbook/engineering/infrastructure/library/canary/#configuration-and-deployment)之前运行常规迁移(在`db/migrate` ),在完成生产部署后运行部署后的迁移( `db/post_migrate` ). + +## Schema Changes[](#schema-changes "Permalink") + +Changes to the schema should be committed to `db/structure.sql`. This file is automatically generated by Rails, so you normally should not edit this file by hand. If your migration is adding a column to a table, that column will be added at the bottom. Please do not reorder columns manually for existing tables as this will cause confusing to other people using `db/structure.sql` generated by Rails. + +当您的 GDK 中的本地数据库与`master`数据库中的模式不同时,可能很难将模式更改完全提交给 Git. 在这种情况下,您可以使用`scripts/regenerate-schema`脚本为要添加的迁移重新生成干净的`db/structure.sql` . 该脚本将应用在`db/migrate`或`db/post_migrate`找到的所有迁移,因此,如果您不想将任何迁移提交到架构,请重命名或删除它们. 如果您的分支不是以`master`为目标,则可以设置`TARGET`环境变量. + +``` +# Regenerate schema against `master` +scripts/regenerate-schema + +# Regenerate schema against `12-9-stable-ee` +TARGET=12-9-stable-ee scripts/regenerate-schema +``` + +## What Requires Downtime?[](#what-requires-downtime "Permalink") + +文档["什么需要停机?"](what_requires_downtime.html) 指定各种数据库操作,例如 + +* [dropping and renaming columns](what_requires_downtime.html#dropping-columns) +* [changing column constraints and types](what_requires_downtime.html#changing-column-constraints) +* [adding and dropping indexes, tables, and foreign keys](what_requires_downtime.html#adding-indexes) + +以及他们是否需要停机,以及如何尽可能地进行停机. + +## Downtime Tagging[](#downtime-tagging "Permalink") + +每个迁移都必须指定是否需要停机,并且如果需要停机,还必须指定原因. 这是即使在迁移的 99%,不需要停机,因为这使得它更容易地发现, *确实*需要停机迁移所需. + +要标记迁移,请在迁移类的主体中添加以下两个常量: + +* `DOWNTIME` :一个布尔值,当设置为`true`指示迁移需要停机时间. +* `DOWNTIME_REASON` :一个字符串,其中包含需要停机的迁移原因. 当`DOWNTIME`设置为`true`时, **必须**设置此常数. + +例如: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + DOWNTIME = true + DOWNTIME_REASON = 'This migration requires downtime because ...' + + def change + ... + end +end +``` + +如果迁移类中缺少`DOWNTIME`常量,则会出现错误(即 CI 将失败). + +## Reversibility[](#reversibility "Permalink") + +您的迁移**必须是**可逆的. 这非常重要,因为在出​​现漏洞或错误的情况下应该可以降级. + +在迁移中,添加一条注释,描述如何测试迁移的可逆性. + +某些迁移无法撤消. 例如,某些数据迁移无法撤消,因为在迁移之前,我们丢失了有关数据库状态的信息. 您仍然应该创建一个带注释的`down`方法,解释为什么不能撤消`up`方法执行的更改,以便即使撤消迁移期间执行的更改也可以撤消迁移本身: + +``` +def down + # no-op + + # comment explaining why changes performed by `up` cannot be reversed. +end +``` + +## Atomicity[](#atomicity "Permalink") + +默认情况下,迁移是单个事务. 即,在迁移开始时打开一个事务,并在处理完所有步骤后提交. + +在单个事务中运行迁移可确保如果其中一个步骤失败,则将不会执行任何步骤,从而使数据库保持有效状态. 因此,要么: + +* 将所有迁移都放在一个单事务迁移中. +* 如有必要,将大多数操作放入一个迁移中,并为无法在单个事务中完成的步骤创建一个单独的迁移. + +例如,如果创建一个空表并需要为其建立索引,则建议使用常规的单事务迁移和默认的 rails schema 语句: [`add_index`](https://api.rubyonrails.org/v5.2/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_index) . 这是一个阻塞操作,但不会引起问题,因为该表尚未使用,因此它还没有任何记录. + +## Heavy operations in a single transaction[](#heavy-operations-in-a-single-transaction "Permalink") + +使用单事务迁移时,事务将在迁移期间保持数据库连接,因此您必须确保迁移中的操作不会花费太多时间:通常,在迁移中执行的查询需要在 GitLab.com 上舒适地放置`15s` . + +如果您需要插入,更新或删除大量数据,请执行以下操作: + +* 必须使用`disable_ddl_transaction!`禁用单个事务`disable_ddl_transaction!` . +* 应该考虑在[后台迁移中](background_migrations.html)这样做. + +## Retry mechanism when acquiring database locks[](#retry-mechanism-when-acquiring-database-locks "Permalink") + +更改数据库架构时,我们使用辅助方法来调用 DDL(数据定义语言)语句. 在某些情况下,这些 DDL 语句需要特定的数据库锁. + +Example: + +``` +def change + remove_column :users, :full_name, :string +end +``` + +要执行此迁移,需要对`users`表进行排他锁定. 当表被其他进程同时访问和修改时,获取锁定可能需要一段时间. 锁定请求正在队列中等待,一旦进入队列,它也可能阻止`users`表上的其他查询. + +有关 PostgresSQL 锁的更多信息: [显式锁定](https://s0www0postgresql0org.icopy.site/docs/current/explicit-locking.html) + +出于稳定性考虑,GitLab.com 设置了特定的[`statement_timeout`](../user/gitlab_com/index.html#postgresql) . 调用迁移时,任何数据库查询都将有固定的执行时间. 在最坏的情况下,请求将坐在锁定队列中,在配置的语句超时时间内阻止其他查询,然后`canceling statement due to statement timeout`错误`canceling statement due to statement timeout`失败. + +此问题可能导致应用程序升级过程失败,甚至导致应用程序稳定性问题,因为该表可能会在短时间内无法访问. + +为了提高数据库迁移的可靠性和稳定性,GitLab 代码库提供了一种辅助方法,以使用不同的`lock_timeout`设置重试操作,并在两次尝试之间等待时间. 为了获得必要的锁定,进行了多次较小的尝试,从而使数据库可以处理其他语句. + +### Examples[](#examples "Permalink") + +**删除列:** + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + remove_column :users, :full_name + end +end + +def down + with_lock_retries do + add_column :users, :full_name, :string + end +end +``` + +**删除外键:** + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + remove_foreign_key :issues, :projects + end +end + +def down + with_lock_retries do + add_foreign_key :issues, :projects + end +end +``` + +**更改列的默认值:** + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + change_column_default :merge_requests, :lock_version, from: nil, to: 0 + end +end + +def down + with_lock_retries do + change_column_default :merge_requests, :lock_version, from: 0, to: nil + end +end +``` + +**用外键创建一个新表:** + +我们可以简单地用`with_lock_retries`包装`create_table`方法: + +``` +def up + with_lock_retries do + create_table :issues do |t| + t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade } + t.string :title, limit: 255 + end + end +end + +def down + drop_table :issues +end +``` + +**当我们有两个外键时创建一个新表:** + +为此,我们需要进行三个迁移: + +1. 创建不带外键(带有索引)的表. +2. 将外键添加到第一个表. +3. 将外键添加到第二个表. + +创建表: + +``` +def up + create_table :imports do |t| + t.bigint :project_id, null: false + t.bigint :user_id, null: false + t.string :jid, limit: 255 + end + + add_index :imports, :project_id + add_index :imports, :user_id +end + +def down + drop_table :imports +end +``` + +在`projects`添加外键: + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + add_foreign_key :imports, :projects, column: :project_id, on_delete: :cascade + end +end + +def down + with_lock_retries do + remove_foreign_key :imports, column: :project_id + end +end +``` + +向`users`添加外键: + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + add_foreign_key :imports, :users, column: :user_id, on_delete: :cascade + end +end + +def down + with_lock_retries do + remove_foreign_key :imports, column: :user_id + end +end +``` + +**与`disable_ddl_transaction!`配合使用`disable_ddl_transaction!`** + +通常, `with_lock_retries`帮助程序应与`disabled_ddl_transaction!` . 定制的 RuboCop 规则可确保只能将允许的方法放在锁重试块中. + +``` +disable_ddl_transaction! + +def up + with_lock_retries do + add_column :users, :name, :text + end + + add_text_limit :users, :name, 255 # Includes constraint validation (full table scan) +end +``` + +RuboCop 规则通常允许使用下面列出的标准 Rails 迁移方法. 此示例将导致 Rubocop 犯罪: + +``` +disabled_ddl_transaction! + +def up + with_lock_retries do + add_concurrent_index :users, :name + end +end +``` + +### When to use the helper method[](#when-to-use-the-helper-method "Permalink") + +通常使用标准的 Rails 迁移帮助器方法时,可以使用`with_lock_retries`帮助器方法. 如果在同一个表上执行多个迁移助手,则调用它们不是问题. + +当数据库迁移涉及高流量表之一时,建议使用`with_lock_retries`帮助程序方法: + +* `users` +* `projects` +* `namespaces` +* `issues` +* `merge_requests` +* `ci_pipelines` +* `ci_builds` +* `notes` + +更改示例: + +* `add_foreign_key` / `remove_foreign_key` +* `add_column` / `remove_column` +* `change_column_default` +* `create_table` / `drop_table` + +**注意:** `with_lock_retries`方法**不能**在`change`方法中使用,必须手动定义`up`和`down`方法以使迁移可逆. + +### How the helper method works[](#how-the-helper-method-works "Permalink") + +1. 重复 50 次. +2. 对于每次迭代,设置一个预配置的`lock_timeout` . +3. 尝试执行给定的块. ( `remove_column` ). +4. 如果出现`LockWaitTimeout`错误,请为预配置的`sleep_time`睡眠,然后重试该块. +5. 如果未引发错误,则当前迭代已成功执行该块. + +有关更多信息,请检查[`Gitlab::Database::WithLockRetries`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/with_lock_retries.rb)类. `with_lock_retries`帮助器方法在[`Gitlab::Database::MigrationHelpers`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/migration_helpers.rb)模块中实现. + +在最坏的情况下,该方法: + +* 在 40 分钟内最多执行 50 次该块. + * 大部分时间都花费在每次迭代后的预先配置的睡眠时段中. +* 第 50 次重试之后,将像标准迁移调用一样在没有`lock_timeout`情况下执行该块. +* 如果无法获取锁,则迁移将失败,并出现`statement timeout`错误. + +如果访问`users`表的事务运行时间很长(超过 40 分钟),则迁移可能会失败. + +## Multi-Threading[](#multi-threading "Permalink") + +有时,迁移可能需要使用多个 Ruby 线程来加快迁移速度. 为此,您的迁移需要包括模块`Gitlab::Database::MultiThreadedMigration` : + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + include Gitlab::Database::MultiThreadedMigration +end +``` + +然后可以使用`with_multiple_threads`方法在单独的线程中执行工作. 例如: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + include Gitlab::Database::MultiThreadedMigration + + def up + with_multiple_threads(4) do + disable_statement_timeout + + # ... + end + end +end +``` + +在这里,对`disable_statement_timeout`的调用将使用`with_multiple_threads`块本地的连接,而不是重新使用全局连接池. 这样可以确保每个线程都有自己的连接对象,并且在尝试获取一个连接对象时不会超时. + +**注意:** PostgreSQL 具有允许的最大连接数. 此限制因安装而异. 因此,建议您一次迁移不要使用超过 32 个线程. 通常,4-8 个线程应该绰绰有余. + +## Removing indexes[](#removing-indexes "Permalink") + +如果删除索引时表不为空,请确保使用方法`remove_concurrent_index`而不是常规的`remove_index`方法. `remove_concurrent_index`方法同时删除索引,因此不需要锁定,也无需停机. 要使用此方法,必须通过调用方法`disable_ddl_transaction!`禁用单交易模式`disable_ddl_transaction!` 在您的迁移类的主体中,如下所示: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + disable_ddl_transaction! + + def up + remove_concurrent_index :table_name, :column_name + end +end +``` + +请注意,在删除索引之前不必检查索引是否存在. + +对于较小的表(例如空表或少于`1,000`条记录的表),建议在单事务迁移中使用`remove_index` ,并将其与不需要`disable_ddl_transaction!`其他操作结合使用`disable_ddl_transaction!` . + +## Adding indexes[](#adding-indexes "Permalink") + +在添加索引之前,请考虑该索引是否必要. 在某些情况下可能不需要索引,例如: + +* 该表很小(少于`1,000`条记录),并且预计大小不会成倍增长. +* 任何现有索引都会过滤掉足够的行. +* 添加索引后查询时间的减少并不明显. + +另外,不需要宽索引来匹配查询的所有过滤条件,我们只需要覆盖足够多的列即可使索引查找具有足够小的选择性. 请查看我们的[添加数据库索引](adding_database_indexes.html)指南以获取更多详细信息. + +将索引添加到非空表时,请确保使用方法`add_concurrent_index`而不是常规的`add_index`方法. 使用 PostgreSQL 时, `add_concurrent_index`方法自动创建并发索引,从而消除了停机时间. + +要使用此方法,必须通过调用方法`disable_ddl_transaction!`禁用单交易模式`disable_ddl_transaction!` 在您的迁移类的主体中,如下所示: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :table, :column + end + + def down + remove_concurrent_index :table, :column + end +end +``` + +如果需要添加唯一索引,请记住,数据库中可能存在现有重复项. 这意味着在添加唯一索引之前,应始终*首先*添加一个删除所有重复项的迁移. + +对于小型表(例如空表或少于`1,000`条记录的表),建议在单事务迁移中使用`add_index` ,并将其与不需要`disable_ddl_transaction!`其他操作结合使用`disable_ddl_transaction!` . + +## Adding foreign-key constraints[](#adding-foreign-key-constraints "Permalink") + +向现有列或新列添加外键约束时,还请记住在该列上添加索引. + +这是所有外键所**必需**的,例如,为了支持有效的级联删除:当删除表中的许多行时,也需要删除引用的记录. 数据库必须在引用的表中查找相应的记录. 没有索引,这将导致对表进行顺序扫描,这可能需要很长时间. + +这是一个示例,其中我们添加了一个带有外键约束的新列. 请注意,它包括`index: true`为其创建索引. + +``` +class Migration < ActiveRecord::Migration[6.0] + + def change + add_reference :model, :other_model, index: true, foreign_key: { on_delete: :cascade } + end +end +``` + +当向非空表中的现有列添加外键约束时,我们必须使用`add_concurrent_foreign_key`和`add_concurrent_index`而不是`add_reference` . + +对于空表(例如新表),建议在单事务迁移中使用`add_reference` ,并将其与不需要`disable_ddl_transaction!`其他操作结合使用`disable_ddl_transaction!` . + +您可以阅读有关将[外键约束](database/add_foreign_key_to_existing_column.html)添加[到现有列的更多信息](database/add_foreign_key_to_existing_column.html) . + +## `NOT NULL` constraints[](#not-null-constraints "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38358) in GitLab 13.0. + +有关更多信息,请参见关于[`NOT NULL`约束](database/not_null_constraints.html)的样式指南. + +## Adding Columns With Default Values[](#adding-columns-with-default-values "Permalink") + +PostgreSQL 11 是自 GitLab 13.0 以来的最低版本,添加具有默认值的列变得更加容易,并且在所有情况下都应使用标准的`add_column`帮助器. + +在 PostgreSQL 11 之前,添加带有默认值的列是有问题的,因为这会导致全表重写. 相应的帮助程序`add_column_with_default`已被弃用,并将在以后的版本中删除. + +**注意:**如果%12.9 或更早版本需要向后端口添加具有默认值的列,则应使用`add_column_with_default`帮助器. 如果涉及[大表](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3) ,则禁止向后移植到%12.9. + +## Changing the column default[](#changing-the-column-default "Permalink") + +可能有人认为,使用`change_column_default`更改默认列对于较大的表来说是一项昂贵且破坏性的操作,但实际上并非如此. + +以以下迁移为例: + +``` +class DefaultRequestAccessGroups < ActiveRecord::Migration[5.2] + DOWNTIME = false + + def change + change_column_default(:namespaces, :request_access_enabled, from: false, to: true) + end +end +``` + +上面的迁移更改了我们最大的表之一的默认列值: `namespaces` . 可以将其翻译为: + +``` +ALTER TABLE namespaces +ALTER COLUMN request_access_enabled +DEFAULT false +``` + +在这种情况下,默认值存在,我们只是更改了`request_access_enabled`列的元数据,这并不意味着重写`namespaces`表中的所有现有记录. 仅当使用默认值创建新列时,所有记录才会被重写. + +**注意:** PostgresSQL 11.0 引入[了](https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/)更快的[ALTER TABLE ADD COLUMN(具有非空默认值](https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/) ),从而消除了在添加具有默认值的新列时重写表的需求. + +由于上述原因,在单事务迁移中使用`change_column_default`是安全的,而不需要`disable_ddl_transaction!` . + +## Updating an existing column[](#updating-an-existing-column "Permalink") + +要将现有列更新为特定值,可以使用`update_column_in_batches` . 这会将更新分为批次,因此我们不会在单个语句中更新太多行. + +这`some_column` `projects`表中的`foo`列更新为 10,其中`some_column`为`'hello'` : + +``` +update_column_in_batches(:projects, :foo, 10) do |table, query| + query.where(table[:some_column].eq('hello')) +end +``` + +如果需要计算的更新,则可以将值包装在`Arel.sql` ,因此 Arel 将其视为 SQL 文字. 这也是[Rails 6](https://gitlab.com/gitlab-org/gitlab/-/issues/28497)的必需弃用. + +下面的示例与上面的示例相同,但是该值设置为`bar`和`baz`列的乘积: + +``` +update_value = Arel.sql('bar * baz') + +update_column_in_batches(:projects, :foo, update_value) do |table, query| + query.where(table[:some_column].eq('hello')) +end +``` + +像`add_column_with_default`一样,有一个 RuboCop cop 可以检测大表上的用法. 在`update_column_in_batches`的情况下,可以在大表上运行,只要它仅更新表中行的一小部分,而在未在 GitLab.com 登台环境上进行验证的情况下不要忽略它-或事先请别人为您这样做. + +## Dropping a database table[](#dropping-a-database-table "Permalink") + +删除数据库表并不常见,Rails 提供的`drop_table`方法通常被认为是安全的. 删除表格之前,请考虑以下因素: + +如果您的表在高流量表上具有外键(如`projects` ),则`DROP TABLE`语句可能会失败,并出现**语句超时**错误. 确定哪些表是高流量可能很困难. 自我管理的实例可能会以不同的使用模式使用 GitLab 的不同功能,因此仅基于 GitLab.com 进行假设是不够的. + +表**没有记录** (功能从未使用过),也**没有外键** : + +* 只需在迁移中使用`drop_table`方法即可. + +``` +def change + drop_table :my_table +end +``` + +Table **有记录** but **没有外键**: + +* 第一版:删除与表相关的应用程序代码,例如模型,控制器和服务. +* 第二版:在迁移中使用`drop_table`方法. + +``` +def up + drop_table :my_table +end + +def down + # create_table ... +end +``` + +Table **有外键**: + +* 第一版:删除与表相关的应用程序代码,例如模型,控制器和服务. +* 第二版:使用`with_lock_retries`帮助器方法删除外键. 在另一个迁移文件中使用`drop_table` . + +**第二个版本的迁移:** + +删除`projects`表上的外键: + +``` +# first migration file + +def up + with_lock_retries do + remove_foreign_key :my_table, :projects + end +end + +def down + with_lock_retries do + add_foreign_key :my_table, :projects + end +end +``` + +放下桌子: + +``` +# second migration file + +def up + drop_table :my_table +end + +def down + # create_table ... +end +``` + +## Integer column type[](#integer-column-type "Permalink") + +默认情况下,整数列最多可容纳 4 个字节(32 位)的数字. 最大值为 2,147,483,647\. 创建一个以字节为单位保存文件大小的列时,请注意这一点. 如果以字节为单位跟踪文件大小,这会将最大文件大小限制为刚好超过 2GB. + +要允许整数列最多容纳 8 个字节(64 位)的数字,请将限制明确设置为 8 个字节. 这将使该列最多`9,223,372,036,854,775,807`个值. + +Rails 迁移示例: + +``` +add_column(:projects, :foo, :integer, default: 10, limit: 8) +``` + +## Strings and the Text data type[](#strings-and-the-text-data-type "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30453) . + +有关更多信息,请参见[文本数据类型](database/strings_and_the_text_data_type.html)样式指南. + +## Timestamp column type[](#timestamp-column-type "Permalink") + +默认情况下,Rails 使用`timestamp`数据类型来存储没有时区信息的时间戳数据. 通过调用`add_timestamps`或`timestamps`方法来使用`timestamp`数据类型. + +另外,Rails 将`:datetime`数据类型转换为`timestamp`一. + +Example: + +``` +# timestamps +create_table :users do |t| + t.timestamps +end + +# add_timestamps +def up + add_timestamps :users +end + +# :datetime +def up + add_column :users, :last_sign_in, :datetime +end +``` + +代替使用这些方法,应该使用以下方法来存储带有时区的时间戳: + +* `add_timestamps_with_timezone` +* `timestamps_with_timezone` +* `datetime_with_timezone` + +这样可以确保所有时间戳都有指定的时区. 反过来,这意味着当系统的时区更改时,现有时间戳不会突然使用其他时区. 这也使得非常清楚,首先使用了哪个时区. + +## Storing JSON in database[](#storing-json-in-database "Permalink") + +Rails 5 本机支持`JSONB` (二进制 JSON)列类型. 添加此列的示例迁移: + +``` +class AddOptionsToBuildMetadata < ActiveRecord::Migration[5.0] + DOWNTIME = false + + def change + add_column :ci_builds_metadata, :config_options, :jsonb + end +end +``` + +您必须使用序列化器来提供翻译层: + +``` +class BuildMetadata + serialize :config_options, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize +end +``` + +使用`JSONB`列时,请使用[JsonSchemaValidator](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/validators/json_schema_validator.rb)来控制随时间推移插入的数据. + +``` +class BuildMetadata + validates :config_options, json_schema: { filename: 'build_metadata_config_option' } +end +``` + +## Testing[](#testing "Permalink") + +请参阅" [测试 Rails 迁移](testing_guide/testing_migrations_guide.html)样式"指南. + +## Data migration[](#data-migration "Permalink") + +请比一般 ActiveRecord 语法更喜欢 Arel 和普通 SQL. 如果使用普通 SQL,则需要使用`quote_string` helper 手动引用所有输入. + +Arel 的示例: + +``` +users = Arel::Table.new(:users) +users.group(users[:user_id]).having(users[:id].count.gt(5)) + +#update other tables with these results +``` + +带有普通 SQL 和`quote_string`帮助器的示例: + +``` +select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(id) > 1").each do |tag| + tag_name = quote_string(tag["name"]) + duplicate_ids = select_all("SELECT id FROM tags WHERE name = '#{tag_name}'").map{|tag| tag["id"]} + origin_tag_id = duplicate_ids.first + duplicate_ids.delete origin_tag_id + + execute("UPDATE taggings SET tag_id = #{origin_tag_id} WHERE tag_id IN(#{duplicate_ids.join(",")})") + execute("DELETE FROM tags WHERE id IN(#{duplicate_ids.join(",")})") +end +``` + +如果需要更复杂的逻辑,则可以定义和使用迁移本地模型. 例如: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + class Project < ActiveRecord::Base + self.table_name = 'projects' + end + + def up + # Reset the column information of all the models that update the database + # to ensure the Active Record's knowledge of the table structure is current + Project.reset_column_information + + # ... ... + end +end +``` + +这样做时,请确保显式设置模型的表名,这样它就不会派生自类名或名称空间. + +最后,对于所有更新数据库的本地模型,请确保在迁移的`up`方法中运行`reset_column_information` . + +这样做的原因是所有迁移类都在开始时加载( `db:migrate`启动时),因此,如果另一个迁移更新了该模式,它们将与它们映射的表模式不同步. 这将导致在尝试插入基础表或对其进行更新时数据迁移失败,因为`ActiveRecord`将新列报告为`unknown attribute` . + +### Renaming reserved paths[](#renaming-reserved-paths "Permalink") + +引入新的项目路线时,它可能与任何现有记录冲突. 这些记录的路径应重命名,并且相关数据应在磁盘上移动. + +由于我们已经必须做几次,因此现在有一些帮助程序可以帮助您. + +要使用此功能,您可以在迁移中包括`Gitlab::Database::RenameReservedPathsMigration::V1` . 这将提供 3 种方法,您可以通过一种或多种需要拒绝的路径. + +**`rename_root_paths`** :这将使用给定名称重命名所有没有`parent_id`名称*空间*的路径. + +**`rename_child_paths`** :这将使用给定名称重命名所有具有`parent_id`名称*空间*的路径. + +**`rename_wildcard_paths`** :这将重命名所有*项目*的路径以及所有具有`project_id` *命名空间* . + +这些行的`path`列将重命名为其先前的值,后跟一个整数. 例如: `users`将变成`users0` \ No newline at end of file diff --git a/_book/docs/564.md b/_book/docs/564.md new file mode 100644 index 0000000000000000000000000000000000000000..8599965b910dbced1444b7316073dbfcd19370dc --- /dev/null +++ b/_book/docs/564.md @@ -0,0 +1,357 @@ +# What requires downtime? + +> 原文:[https://docs.gitlab.com/ee/development/what_requires_downtime.html](https://docs.gitlab.com/ee/development/what_requires_downtime.html) + +* [Dropping Columns](#dropping-columns) + * [Step 1: Ignoring the column (release M)](#step-1-ignoring-the-column-release-m) + * [Step 2: Dropping the column (release M+1)](#step-2-dropping-the-column-release-m1) + * [Step 3: Removing the ignore rule (release M+2)](#step-3-removing-the-ignore-rule-release-m2) +* [Renaming Columns](#renaming-columns) + * [Step 1: Add The Regular Migration](#step-1-add-the-regular-migration) + * [Step 2: Add A Post-Deployment Migration](#step-2-add-a-post-deployment-migration) +* [Changing Column Constraints](#changing-column-constraints) +* [Changing Column Types](#changing-column-types) + * [Step 1: Create A Regular Migration](#step-1-create-a-regular-migration) + * [Step 2: Create A Post Deployment Migration](#step-2-create-a-post-deployment-migration) + * [Casting data to a new type](#casting-data-to-a-new-type) +* [Changing The Schema For Large Tables](#changing-the-schema-for-large-tables) +* [Adding Indexes](#adding-indexes) +* [Dropping Indexes](#dropping-indexes) +* [Adding Tables](#adding-tables) +* [Dropping Tables](#dropping-tables) +* [Renaming Tables](#renaming-tables) +* [Adding Foreign Keys](#adding-foreign-keys) +* [Removing Foreign Keys](#removing-foreign-keys) +* [Data Migrations](#data-migrations) + +# What requires downtime?[](#what-requires-downtime "Permalink") + +使用数据库时,可以在不使 GitLab 脱机的情况下执行某些操作,其他操作确实需要停机时间. 本指南介绍了各种操作,其影响以及如何在不停机的情况下执行这些操作. + +## Dropping Columns[](#dropping-columns "Permalink") + +删除列很棘手,因为正在运行的 GitLab 进程可能仍在使用这些列. 为了安全地解决此问题,您需要在三个版本中执行三个步骤: + +1. 忽略列(版本 M) +2. 删除列(版本 M + 1) +3. 删除忽略规则(版本 M + 2) + +之所以将其分布在三个发行版中,是因为删除列是一种破坏性操作,不易回滚. + +遵循此过程可帮助我们确保没有部署到 GitLab.com 并升级将这些步骤集中在一起的自我管理安装的过程. + +### Step 1: Ignoring the column (release M)[](#step-1-ignoring-the-column-release-m "Permalink") + +第一步是忽略应用程序代码中的列. 这是必要的,因为 Rails 缓存列并在各个地方重复使用此缓存. 这可以通过定义要忽略的列来完成. 例如,要忽略用户模型中的`updated_at` ,请使用以下命令: + +``` +class User < ApplicationRecord + include IgnorableColumns + ignore_column :updated_at, remove_with: '12.7', remove_after: '2019-12-22' +end +``` + +多列也可以忽略: + +``` +ignore_columns %i[updated_at created_at], remove_with: '12.7', remove_after: '2019-12-22' +``` + +我们要求通过以下方式指示何时可以安全地删除列忽略: + +* `remove_with` :设置为 GitLab 版本,通常在添加列忽略后两个版本(M + 2). +* `remove_after` :设置为一个日期,在该日期之后,我们认为通常可以在 M + 2 版本的开发周期内删除列忽略项. + +这些信息使我们能够更好地推理列忽略,并确保对于常规发行版和部署到 GitLab.com 而言,我们都不会过早删除列忽略. 例如,这避免了我们部署大量更改的情况,其中包括同时忽略列的更改和随后删除列忽略的更改(这将导致停机). + +在此示例中,忽略列的更改在 12.5 版中进行. + +### Step 2: Dropping the column (release M+1)[](#step-2-dropping-the-column-release-m1 "Permalink") + +继续我们的示例,删除该列将进入版本 12.6 中*的部署后*迁移: + +``` + remove_column :user, :updated_at +``` + +### Step 3: Removing the ignore rule (release M+2)[](#step-3-removing-the-ignore-rule-release-m2 "Permalink") + +在下一个版本中,在此示例 12.7 中,我们设置了另一个合并请求以删除忽略规则. 这将删除`ignore_column`行,并且如果不再需要,还将`IgnoreableColumns` . + +只有在`remove_after`日期过去之后,才应将其与`remove_with`指示的发行版合并. + +## Renaming Columns[](#renaming-columns "Permalink") + +重命名列通常需要停机,因为在数据库迁移期间/之后,应用程序可能会继续使用旧的列名称. 要在不停机的情况下重命名列,我们需要两个迁移:常规迁移和部署后迁移. 这些迁移都可以在同一版本中进行. + +### Step 1: Add The Regular Migration[](#step-1-add-the-regular-migration "Permalink") + +首先,我们需要创建常规迁移. 此迁移应当前使用`Gitlab::Database::MigrationHelpers#rename_column_concurrently`来执行重命名. 例如 + +``` +# A regular migration in db/migrate +class RenameUsersUpdatedAtToUpdatedAtTimestamp < ActiveRecord::Migration[4.2] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + def up + rename_column_concurrently :users, :updated_at, :updated_at_timestamp + end + + def down + undo_rename_column_concurrently :users, :updated_at, :updated_at_timestamp + end +end +``` + +这将负责重命名列,确保数据保持同步,通过索引和外键进行复制等. + +**注意:**如果一列包含 1 个或多个不包含原始列名称的索引,则上述过程将失败. 在这种情况下,您首先需要重命名这些索引. + +### Step 2: Add A Post-Deployment Migration[](#step-2-add-a-post-deployment-migration "Permalink") + +重命名过程需要在部署后迁移中进行一些清理. 我们可以使用`Gitlab::Database::MigrationHelpers#cleanup_concurrent_column_rename`来执行此清理: + +``` +# A post-deployment migration in db/post_migrate +class CleanupUsersUpdatedAtRename < ActiveRecord::Migration[4.2] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + def up + cleanup_concurrent_column_rename :users, :updated_at, :updated_at_timestamp + end + + def down + undo_cleanup_concurrent_column_rename :users, :updated_at, :updated_at_timestamp + end +end +``` + +**注意:**如果要重命名[大表](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3) ,请仔细考虑第一次迁移已运行但第二次清理迁移尚未运行的状态. 使用[Canary](https://about.gitlab.com/handbook/engineering/infrastructure/library/canary/) ,系统可能会在此状态下运行大量时间. + +## Changing Column Constraints[](#changing-column-constraints "Permalink") + +通常,无需停机即可添加或删除`NOT NULL`子句(或其他约束). 但是,这确实需要*首先*部署所有应用程序更改. 因此,在部署后的迁移中应该发生更改列约束的情况. + +避免使用`change_column`因为它会产生无效查询,因为它会重新定义整个列类型. + +您可以针对每个特定用例查看以下指南: + +* [Adding foreign-key constraints](migration_style_guide.html#adding-foreign-key-constraints) +* [Adding `NOT NULL` constraints](database/not_null_constraints.html) +* [Adding limits to text columns](database/strings_and_the_text_data_type.html) + +## Changing Column Types[](#changing-column-types "Permalink") + +可以使用`Gitlab::Database::MigrationHelpers#change_column_type_concurrently`来更改列的类型. 此方法的工作方式与`rename_column_concurrently`类似. 例如,假设我们要将`users.username`的类型从`string`更改为`text` . + +### Step 1: Create A Regular Migration[](#step-1-create-a-regular-migration "Permalink") + +常规迁移用于创建具有临时名称的新列,并设置一些触发器以使数据保持同步. 这样的迁移如下所示: + +``` +# A regular migration in db/migrate +class ChangeUsersUsernameStringToText < ActiveRecord::Migration[4.2] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + def up + change_column_type_concurrently :users, :username, :text + end + + def down + cleanup_concurrent_column_type_change :users, :username + end +end +``` + +### Step 2: Create A Post Deployment Migration[](#step-2-create-a-post-deployment-migration "Permalink") + +接下来,我们需要使用部署后迁移来清理更改: + +``` +# A post-deployment migration in db/post_migrate +class ChangeUsersUsernameStringToTextCleanup < ActiveRecord::Migration[4.2] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + def up + cleanup_concurrent_column_type_change :users, :username + end + + def down + change_column_type_concurrently :users, :username, :string + end +end +``` + +就是这样,我们完成了! + +### Casting data to a new type[](#casting-data-to-a-new-type "Permalink") + +某些类型更改需要将数据转换为新类型. 例如,从`text`更改为`jsonb` . 在这种情况下,请使用`type_cast_function`选项. 确保没有不良数据,并且投射将始终成功. 您还可以提供一个自定义函数来处理转换错误. + +迁移示例: + +``` + def up + change_column_type_concurrently :users, :settings, :jsonb, type_cast_function: 'jsonb' + end +``` + +## Changing The Schema For Large Tables[](#changing-the-schema-for-large-tables "Permalink") + +虽然`change_column_type_concurrently`和`rename_column_concurrently`可以用于在`rename_column_concurrently`机的情况下更改表的架构,但对于大型表来说,效果并不理想. 由于所有工作都是按顺序进行的,因此迁移可能需要很长时间才能完成,从而阻止了部署的进行. 由于数据库按顺序快速更新许多行,因此它们也可能给数据库带来很大压力. + +为减轻数据库压力,在迁移大表中的列时(例如`issues` ),应改用`change_column_type_using_background_migration`或`rename_column_using_background_migration` . 这些方法的工作方式与并发的类似,但是使用后台迁移将工作/负载分散在更长的时间段内,而不会减慢部署速度. + +例如,要使用后台迁移来更改列类型: + +``` +class ExampleMigration < ActiveRecord::Migration[4.2] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + class Issue < ActiveRecord::Base + self.table_name = 'issues' + + include EachBatch + + def self.to_migrate + where('closed_at IS NOT NULL') + end + end + + def up + change_column_type_using_background_migration( + Issue.to_migrate, + :closed_at, + :datetime_with_timezone + ) + end + + def down + change_column_type_using_background_migration( + Issue.to_migrate, + :closed_at, + :datetime + ) + end +end +``` + +这将将`issues.closed_at`的类型更改为`timestamp with time zone` . + +请记住,传递给`change_column_type_using_background_migration`的关系*必须*包含`EachBatch` ,否则将引发`TypeError` . + +然后,此迁移需要在单独的发行版( *而不是*补丁程序发行版)中进行清除迁移,该清除迁移应从队列中窃取并处理所有剩余的行. 例如: + +``` +class MigrateRemainingIssuesClosedAt < ActiveRecord::Migration[4.2] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + class Issue < ActiveRecord::Base + self.table_name = 'issues' + include EachBatch + end + + def up + Gitlab::BackgroundMigration.steal('CopyColumn') + Gitlab::BackgroundMigration.steal('CleanupConcurrentTypeChange') + + migrate_remaining_rows if migrate_column_type? + end + + def down + # Previous migrations already revert the changes made here. + end + + def migrate_remaining_rows + Issue.where('closed_at_for_type_change IS NULL AND closed_at IS NOT NULL').each_batch do |batch| + batch.update_all('closed_at_for_type_change = closed_at') + end + + cleanup_concurrent_column_type_change(:issues, :closed_at) + end + + def migrate_column_type? + # Some environments may have already executed the previous version of this + # migration, thus we don't need to migrate those environments again. + column_for('issues', 'closed_at').type == :datetime # rubocop:disable Migration/Datetime + end +end +``` + +这同样适用于`rename_column_using_background_migration` : + +1. 使用帮助程序创建迁移,该迁移将安排后台迁移以将写入分散在更长的时间范围内. +2. 在下一个每月发行版中,创建清理迁移以从 Sidekiq 队列中窃取,迁移所有丢失的行并清理重命名. 如果该列已被重命名,则此迁移应在从 Sidekiq 队列中窃取后跳过步骤. + +有关更多信息,请参阅[有关清理后台迁移的文档](background_migrations.html#cleaning-up) . + +## Adding Indexes[](#adding-indexes "Permalink") + +使用`add_concurrent_index`时,添加索引不需要停机. + +另请参阅《 [迁移样式指南》](migration_style_guide.html#adding-indexes) . + +## Dropping Indexes[](#dropping-indexes "Permalink") + +删除索引不需要停机. + +## Adding Tables[](#adding-tables "Permalink") + +此操作是安全的,因为还没有使用该表的代码. + +## Dropping Tables[](#dropping-tables "Permalink") + +使用部署后迁移可以安全地完成删除表的操作,但前提是应用程序不再使用该表. + +## Renaming Tables[](#renaming-tables "Permalink") + +重命名表需要停机,因为在数据库迁移期间/之后,应用程序可能会继续使用旧表名. + +## Adding Foreign Keys[](#adding-foreign-keys "Permalink") + +添加外键通常需要 3 个步骤: + +1. 开始交易 +2. 运行`ALTER TABLE`添加约束 +3. 检查所有现有数据 + +因为`ALTER TABLE`通常会在事务结束之前获取独占锁,所以这意味着该方法将需要停机. + +GitLab allows you to work around this by using `Gitlab::Database::MigrationHelpers#add_concurrent_foreign_key`. This method ensures that no downtime is needed. + +## Removing Foreign Keys[](#removing-foreign-keys "Permalink") + +此操作不需要停机. + +## Data Migrations[](#data-migrations "Permalink") + +数据迁移可能很棘手. 迁移数据的通常方法是采取 3 个步骤: + +1. 迁移初始数据 +2. 部署应用程序代码 +3. 迁移所有剩余数据 + +通常这有效,但并非总是如此. 例如,如果要将字段的格式从 JSON 更改为其他格式,我们会遇到一些问题. 如果我们在部署应用程序代码之前更改现有数据,则很可能会遇到错误. 另一方面,如果我们在部署应用程序代码后进行迁移,则可能会遇到相同的问题. + +如果您只需要更正一些无效数据,则部署后迁移通常就足够了. 如果您需要更改数据格式(例如,从 JSON 更改为其他格式),通常最好为新数据格式添加一个新列,然后让应用程序使用该列. 在这种情况下,程序将是: + +1. 以新格式添加新列 +2. 将现有数据复制到此新列 +3. 部署应用程序代码 +4. In a post-deployment migration, copy over any remaining data + +通常,没有一个万能的解决方案,因此最好在合并请求中讨论此类迁移,以确保以最佳方式实现它们. \ No newline at end of file diff --git a/_book/docs/565.md b/_book/docs/565.md new file mode 100644 index 0000000000000000000000000000000000000000..a01e6aa93ef787f3962a4ea9c6bdd9a75ea10b44 --- /dev/null +++ b/_book/docs/565.md @@ -0,0 +1,647 @@ +# Understanding EXPLAIN plans + +> 原文:[https://docs.gitlab.com/ee/development/understanding_explain_plans.html](https://docs.gitlab.com/ee/development/understanding_explain_plans.html) + +* [Nodes](#nodes) +* [Node statistics](#node-statistics) +* [Node types](#node-types) + * [Seq Scan](#seq-scan) + * [Index Only Scan](#index-only-scan) + * [Index Scan](#index-scan) + * [Bitmap Index Scan and Bitmap Heap scan](#bitmap-index-scan-and-bitmap-heap-scan) + * [Limit](#limit) + * [Sort](#sort) + * [Nested Loop](#nested-loop) +* [Optimising queries](#optimising-queries) +* [Queries that can’t be optimised](#queries-that-cant-be-optimised) + * [Cardinality and selectivity](#cardinality-and-selectivity) +* [Rewriting queries](#rewriting-queries) +* [What makes a bad plan](#what-makes-a-bad-plan) +* [Producing query plans](#producing-query-plans) + * [Rails console](#rails-console) + * [ChatOps](#chatops) + * [`#database-lab`](#database-lab) + * [Tips & Tricks](#tips--tricks) +* [Further reading](#further-reading) + +# Understanding EXPLAIN plans[](#understanding-explain-plans "Permalink") + +PostgreSQL 允许您使用`EXPLAIN`命令获得查询计划. 尝试确定查询的执行方式时,此命令非常有用. 您可以在 SQL 查询中直接使用此命令,只要查询以它开头即可: + +``` +EXPLAIN +SELECT COUNT(*) +FROM projects +WHERE visibility_level IN (0, 20); +``` + +在 GitLab.com 上运行时,将显示以下输出: + +``` +Aggregate (cost=922411.76..922411.77 rows=1 width=8) + -> Seq Scan on projects (cost=0.00..908044.47 rows=5746914 width=0) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) +``` + +当*仅*使用`EXPLAIN` ,PostgreSQL 实际上不会执行我们的查询,而是会根据可用的统计信息生成一个*估计的*执行计划. 这意味着实际计划可能相差很大. 幸运的是,PostgreSQL 还为我们提供了执行查询的选项. 为此,我们需要使用`EXPLAIN ANALYZE`而不是`EXPLAIN` : + +``` +EXPLAIN ANALYZE +SELECT COUNT(*) +FROM projects +WHERE visibility_level IN (0, 20); +``` + +这将产生: + +``` +Aggregate (cost=922420.60..922420.61 rows=1 width=8) (actual time=3428.535..3428.535 rows=1 loops=1) + -> Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) + Rows Removed by Filter: 65677 +Planning time: 2.861 ms +Execution time: 3428.596 ms +``` + +如我们所见,该计划是完全不同的,并且包含许多数据. 让我们逐步讨论一下. + +由于`EXPLAIN ANALYZE`执行查询,因此在使用会写入数据或可能会超时的查询时应`EXPLAIN ANALYZE`小心. 如果查询修改了数据,请考虑将其包装在自动回滚的事务中,如下所示: + +``` +BEGIN; +EXPLAIN ANALYZE +DELETE FROM users WHERE id = 1; +ROLLBACK; +``` + +`EXPLAIN`命令还包含其他选项,例如`BUFFERS` : + +``` +EXPLAIN (ANALYZE, BUFFERS) +SELECT COUNT(*) +FROM projects +WHERE visibility_level IN (0, 20); +``` + +然后将产生: + +``` +Aggregate (cost=922420.60..922420.61 rows=1 width=8) (actual time=3428.535..3428.535 rows=1 loops=1) + Buffers: shared hit=208846 + -> Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) + Rows Removed by Filter: 65677 + Buffers: shared hit=208846 +Planning time: 2.861 ms +Execution time: 3428.596 ms +``` + +有关更多信息,请参阅官方的[`EXPLAIN`文档](https://s0www0postgresql0org.icopy.site/docs/current/sql-explain.html)并[使用`EXPLAIN`指南](https://s0www0postgresql0org.icopy.site/docs/current/using-explain.html) . + +## Nodes[](#nodes "Permalink") + +每个查询计划都由节点组成. 节点可以嵌套,并且可以由内而外执行. 这意味着最内部的节点在外部节点之前执行. 最好将其视为嵌套函数调用,并在展开时返回其结果. 例如,一个计划以`Aggregate`开头,然后是`Nested Loop` ,然后是`Index Only scan`可以认为是以下 Ruby 代码: + +``` +aggregate( + nested_loop( + index_only_scan() + index_only_scan() + ) +) +``` + +节点使用`->`表示,后跟所采用的节点类型. 例如: + +``` +Aggregate (cost=922411.76..922411.77 rows=1 width=8) + -> Seq Scan on projects (cost=0.00..908044.47 rows=5746914 width=0) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) +``` + +这里执行的第一个节点是`Seq scan on projects` . `Filter:`是应用于节点结果的附加过滤器. 过滤器与 Ruby 的`Array#select`非常相似:它接受输入行,应用过滤器,并生成新的行列表. 节点完成后,我们将在其上方执行`Aggregate` . + +嵌套节点将如下所示: + +``` +Aggregate (cost=176.97..176.98 rows=1 width=8) (actual time=0.252..0.252 rows=1 loops=1) + Buffers: shared hit=155 + -> Nested Loop (cost=0.86..176.75 rows=87 width=0) (actual time=0.035..0.249 rows=36 loops=1) + Buffers: shared hit=155 + -> Index Only Scan using users_pkey on users users_1 (cost=0.43..4.95 rows=87 width=4) (actual time=0.029..0.123 rows=36 loops=1) + Index Cond: (id < 100) + Heap Fetches: 0 + -> Index Only Scan using users_pkey on users (cost=0.43..1.96 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=36) + Index Cond: (id = users_1.id) + Heap Fetches: 0 +Planning time: 2.585 ms +Execution time: 0.310 ms +``` + +在这里,我们首先执行两次单独的"仅索引"扫描,然后对这两次扫描的结果执行"嵌套循环". + +## Node statistics[](#node-statistics "Permalink") + +计划中的每个节点都有一组关联的统计信息,例如成本,产生的行数,执行的循环数等等. 例如: + +``` +Seq Scan on projects (cost=0.00..908044.47 rows=5746914 width=0) +``` + +在这里,我们可以看到我们的成本范围为`0.00..908044.47` (稍后我们将对此进行介绍),并且我们估计(因为我们使用的是`EXPLAIN`而不是`EXPLAIN ANALYZE` ),因此此节点将产生总计 5,746,914 行. `width`统计信息描述了每行的估计宽度,以字节为单位. + +`costs`字段指定节点的价格. 成本以查询计划者的成本参数确定的任意单位衡量. 影响成本的因素取决于各种设置,例如`seq_page_cost` , `cpu_tuple_cost`和其他各种设置. 费用字段的格式如下: + +``` +STARTUP COST..TOTAL COST +``` + +The startup cost states how expensive it was to start the node, with the total cost describing how expensive the entire node was. In general: the greater the values, the more expensive the node. + +使用`EXPLAIN ANALYZE` ,这些统计信息还将包括实际花费的时间(以毫秒为单位)以及其他运行时统计信息(例如,产生的行的实际数量): + +``` +Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1) +``` + +在这里我们可以看到估计返回了 5,746,969 行,但实际上,我们返回了 5,746,940 行. 我们还可以看到, *仅*此顺序扫描就花费了 2.98 秒. + +使用`EXPLAIN (ANALYZE, BUFFERS)`还将为我们提供有关由过滤器删除的行数,使用的缓冲区数等信息. 例如: + +``` +Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) + Rows Removed by Filter: 65677 + Buffers: shared hit=208846 +``` + +在这里,我们可以看到我们的过滤器必须删除 65,677 行,并使用 208,846 个缓冲区. PostgreSQL 中的每个缓冲区都是 8 KB(8192 字节),这意味着我们上面的节点使用*1.6 GB 的缓冲区* . 好多啊! + +## Node types[](#node-types "Permalink") + +有很多不同类型的节点,因此我们在这里仅介绍一些较常见的节点. + +可以在[PostgreSQL 源文件`plannodes.h`](https://gitlab.com/postgres/postgres/blob/master/src/include/nodes/plannodes.h)找到所有可用节点及其描述的完整列表. + +### Seq Scan[](#seq-scan "Permalink") + +对数据库表(的一部分)进行顺序扫描. 这类似于使用`Array#each` ,但是在数据库表上. 检索大量行时,顺序扫描可能会非常慢,因此,对于大型表,最好避免使用这些扫描. + +### Index Only Scan[](#index-only-scan "Permalink") + +对不需要从表中获取任何内容的索引进行的扫描. 在某些情况下,仅索引扫描仍可能从表中获取数据,在这种情况下,节点将包含" `Heap Fetches:`统计信息. + +### Index Scan[](#index-scan "Permalink") + +对索引的扫描,该索引需要从表中检索一些数据. + +### Bitmap Index Scan and Bitmap Heap scan[](#bitmap-index-scan-and-bitmap-heap-scan "Permalink") + +位图扫描介于顺序扫描和索引扫描之间. 当我们从索引扫描中读取太多数据但执行顺序扫描时读取的数据太少时,通常会使用它们. 位图扫描使用所谓的[位图索引](https://en.wikipedia.org/wiki/Bitmap_index)来执行其工作. + +[PostgreSQL](https://gitlab.com/postgres/postgres/blob/REL_11_STABLE/src/include/nodes/plannodes.h#L441)的[源代码在位](https://gitlab.com/postgres/postgres/blob/REL_11_STABLE/src/include/nodes/plannodes.h#L441)图扫描中指出以下内容: + +> 位图索引扫描提供潜在元组位置的位图; 它不访问堆本身. 该位图可能由祖先位图堆扫描节点使用,可能是在经过中间位图和和/或位图或节点之后将其与其他位图索引扫描的结果组合在一起的. + +### Limit[](#limit "Permalink") + +在输入行上应用`LIMIT` . + +### Sort[](#sort "Permalink") + +使用`ORDER BY`语句对输入行进行排序. + +### Nested Loop[](#nested-loop "Permalink") + +嵌套循环将针对其前面的节点产生的每一行执行其子节点. 例如: + +``` +-> Nested Loop (cost=0.86..176.75 rows=87 width=0) (actual time=0.035..0.249 rows=36 loops=1) + Buffers: shared hit=155 + -> Index Only Scan using users_pkey on users users_1 (cost=0.43..4.95 rows=87 width=4) (actual time=0.029..0.123 rows=36 loops=1) + Index Cond: (id < 100) + Heap Fetches: 0 + -> Index Only Scan using users_pkey on users (cost=0.43..1.96 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=36) + Index Cond: (id = users_1.id) + Heap Fetches: 0 +``` + +在这里,第一个子节点( `Index Only Scan using users_pkey on users users_1` )产生 36 行,并执行一次( `rows=36 loops=1` ). 下一个节点产生 1 行( `rows=1` ),但重复 36 次( `loops=36` ). 这是因为前一个节点产生了 36 行. + +这意味着,如果各个子节点继续产生许多行,则嵌套循环会迅速降低查询速度. + +## Optimising queries[](#optimising-queries "Permalink") + +顺便说一句,让我们看看如何优化查询. 让我们以以下查询为例: + +``` +SELECT COUNT(*) +FROM users +WHERE twitter != ''; +``` + +该查询仅计算设置了 Twitter 个人资料的用户数. 让我们使用`EXPLAIN (ANALYZE, BUFFERS)`运行它: + +``` +EXPLAIN (ANALYZE, BUFFERS) +SELECT COUNT(*) +FROM users +WHERE twitter != ''; +``` + +这将产生以下计划: + +``` +Aggregate (cost=845110.21..845110.22 rows=1 width=8) (actual time=1271.157..1271.158 rows=1 loops=1) + Buffers: shared hit=202662 + -> Seq Scan on users (cost=0.00..844969.99 rows=56087 width=0) (actual time=0.019..1265.883 rows=51833 loops=1) + Filter: ((twitter)::text <> ''::text) + Rows Removed by Filter: 2487813 + Buffers: shared hit=202662 +Planning time: 0.390 ms +Execution time: 1271.180 ms +``` + +从该查询计划中,我们可以看到以下内容: + +1. 我们需要对`users`表执行顺序扫描. +2. 此顺序扫描使用`Filter`过滤掉 2,487,813 行. +3. 我们使用 202,622 个缓冲区,相当于 1.58 GB 的内存. +4. 完成所有这些操作需要 1.2 秒. + +考虑到我们只是在计算用户,这是相当昂贵的! + +在开始进行任何更改之前,让我们看一下`users`表上是否有可以使用的现有索引. 我们可以通过在`psql`控制台中运行`\d users` ,然后向下滚动至`Indexes:`部分来获取此信息: + +``` +Indexes: + "users_pkey" PRIMARY KEY, btree (id) + "index_users_on_confirmation_token" UNIQUE, btree (confirmation_token) + "index_users_on_email" UNIQUE, btree (email) + "index_users_on_reset_password_token" UNIQUE, btree (reset_password_token) + "index_users_on_static_object_token" UNIQUE, btree (static_object_token) + "index_users_on_unlock_token" UNIQUE, btree (unlock_token) + "index_on_users_name_lower" btree (lower(name::text)) + "index_users_on_accepted_term_id" btree (accepted_term_id) + "index_users_on_admin" btree (admin) + "index_users_on_created_at" btree (created_at) + "index_users_on_email_trigram" gin (email gin_trgm_ops) + "index_users_on_feed_token" btree (feed_token) + "index_users_on_group_view" btree (group_view) + "index_users_on_incoming_email_token" btree (incoming_email_token) + "index_users_on_managing_group_id" btree (managing_group_id) + "index_users_on_name" btree (name) + "index_users_on_name_trigram" gin (name gin_trgm_ops) + "index_users_on_public_email" btree (public_email) WHERE public_email::text <> ''::text + "index_users_on_state" btree (state) + "index_users_on_state_and_user_type" btree (state, user_type) + "index_users_on_unconfirmed_email" btree (unconfirmed_email) WHERE unconfirmed_email IS NOT NULL + "index_users_on_user_type" btree (user_type) + "index_users_on_username" btree (username) + "index_users_on_username_trigram" gin (username gin_trgm_ops) + "tmp_idx_on_user_id_where_bio_is_filled" btree (id) WHERE COALESCE(bio, ''::character varying)::text IS DISTINCT FROM ''::text +``` + +在这里,我们可以看到`twitter`列上没有索引,这意味着 PostgreSQL 在这种情况下必须执行顺序扫描. 让我们尝试通过添加以下索引来解决此问题: + +``` +CREATE INDEX CONCURRENTLY twitter_test ON users (twitter); +``` + +如果现在使用`EXPLAIN (ANALYZE, BUFFERS)`重新运行查询`EXPLAIN (ANALYZE, BUFFERS)`得到以下计划: + +``` +Aggregate (cost=61002.82..61002.83 rows=1 width=8) (actual time=297.311..297.312 rows=1 loops=1) + Buffers: shared hit=51854 dirtied=19 + -> Index Only Scan using twitter_test on users (cost=0.43..60873.13 rows=51877 width=0) (actual time=279.184..293.532 rows=51833 loops=1) + Filter: ((twitter)::text <> ''::text) + Rows Removed by Filter: 2487830 + Heap Fetches: 26037 + Buffers: shared hit=51854 dirtied=19 +Planning time: 0.191 ms +Execution time: 297.334 ms +``` + +现在获取数据只需不到 300 毫秒,而不是 1.2 秒. 但是,我们仍然使用 51,854 个缓冲区,这大约是 400 MB 的内存. 对于这种简单的查询,300 毫秒的速度也很慢. 要了解为什么此查询仍然昂贵,让我们看一下以下内容: + +``` +Index Only Scan using twitter_test on users (cost=0.43..60873.13 rows=51877 width=0) (actual time=279.184..293.532 rows=51833 loops=1) + Filter: ((twitter)::text <> ''::text) + Rows Removed by Filter: 2487830 +``` + +我们从仅对索引进行索引扫描开始,但是我们仍然以某种方式应用了`Filter` ,该过滤`Filter`可过滤掉 2,487,830 行. 这是为什么? 好,让我们看一下如何创建索引: + +``` +CREATE INDEX CONCURRENTLY twitter_test ON users (twitter); +``` + +我们只是简单地告诉 PostgreSQL 索引`twitter`列的所有可能值,甚至是空字符串. 我们的查询反过来使用`WHERE twitter != ''` . 这意味着索引确实可以改善事情,因为我们不需要进行顺序扫描,但是我们仍然可能会遇到空字符串. 这意味着 PostgreSQL *必须*对索引结果应用过滤器以摆脱这些值. + +幸运的是,我们可以使用"部分索引"来进一步改善它. 部分索引是在索引数据时具有`WHERE`条件的索引. 例如: + +``` +CREATE INDEX CONCURRENTLY some_index ON users (email) WHERE id < 100 +``` + +该索引仅索引与`WHERE id < 100`相匹配的行的`email`值. 我们可以使用部分索引将我们的 Twitter 索引更改为以下内容: + +``` +CREATE INDEX CONCURRENTLY twitter_test ON users (twitter) WHERE twitter != ''; +``` + +创建后,如果再次运行查询,将得到以下计划: + +``` +Aggregate (cost=1608.26..1608.27 rows=1 width=8) (actual time=19.821..19.821 rows=1 loops=1) + Buffers: shared hit=44036 + -> Index Only Scan using twitter_test on users (cost=0.41..1479.71 rows=51420 width=0) (actual time=0.023..15.514 rows=51833 loops=1) + Heap Fetches: 1208 + Buffers: shared hit=44036 +Planning time: 0.123 ms +Execution time: 19.848 ms +``` + +*好多了* ! 现在仅需要 20 毫秒即可获取数据,并且我们仅使用约 344 MB 的缓冲区(而不是原始的 1.58 GB). 之所以可行,是因为现在 PostgreSQL 不再需要应用`Filter` ,因为索引仅包含不为空的`twitter`值. + +请记住,每次您要优化查询时,不应该只添加部分索引. 每个索引都必须为每次写入更新,并且它们可能需要相当多的空间,具体取决于索引数据的数量. 结果,首先检查是否存在可以重用的现有索引. 如果没有,请检查是否可以略微更改现有查询以适合现有查询和新查询. 仅当现有索引无法以任何方式使用时,才添加新索引. + +## Queries that can’t be optimised[](#queries-that-cant-be-optimised "Permalink") + +既然我们已经了解了如何优化查询,让我们看一下可能无法优化的另一个查询: + +``` +EXPLAIN (ANALYZE, BUFFERS) +SELECT COUNT(*) +FROM projects +WHERE visibility_level IN (0, 20); +``` + +`EXPLAIN (ANALYZE, BUFFERS)`的输出如下: + +``` +Aggregate (cost=922420.60..922420.61 rows=1 width=8) (actual time=3428.535..3428.535 rows=1 loops=1) + Buffers: shared hit=208846 + -> Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) + Rows Removed by Filter: 65677 + Buffers: shared hit=208846 +Planning time: 2.861 ms +Execution time: 3428.596 ms +``` + +查看输出,我们看到以下过滤器: + +``` +Filter: (visibility_level = ANY ('{0,20}'::integer[])) +Rows Removed by Filter: 65677 +``` + +查看过滤器删除的行数,我们可能会想在`projects.visibility_level`上添加索引,以某种方式将此顺序扫描+过滤器转换为仅索引扫描. + +不幸的是,这样做不可能改善任何事情. 与某些人的看法相反,存在索引*并不能保证* PostgreSQL 会实际使用它. 例如,在执行`SELECT * FROM projects`时,仅扫描整个表而不是使用索引然后从表中获取数据要便宜得多. 在这种情况下,PostgreSQL 可能会决定不使用索引. + +其次,让我们考虑一下查询的作用:它使所有项目的可见性级别为 0 或 20.在上面的计划中,我们可以看到生成了很多行(5,745,940),但相对于总行数是多少? 通过运行以下查询来找出答案: + +``` +SELECT visibility_level, count(*) AS amount +FROM projects +GROUP BY visibility_level +ORDER BY visibility_level ASC; +``` + +对于 GitLab.com,这将产生: + +``` + visibility_level | amount +------------------+--------- + 0 | 5071325 + 10 | 65678 + 20 | 674801 +``` + +这里的项目总数为 5,811,804,其中 5,746,126 为 0 或 20 级.这是整个表的 98%! + +因此,无论我们做什么,此查询都将检索整个表的 98%. 由于大部分时间都花在做到这一点上,因此除了*完全不*运行查询之外,我们几乎没有其他方法可以改进此查询. + +这里重要的是,尽管有些人可能建议您在看到顺序扫描时立即直接添加索引,但*更重要的*是首先了解查询的功能,检索的数据量等等. 毕竟,您无法优化您不了解的内容. + +### Cardinality and selectivity[](#cardinality-and-selectivity "Permalink") + +早先我们看到查询必须检索表中 98%的行. 数据库通常使用两个术语:基数和选择性. 基数是指表中特定列中唯一值的数量. + +选择性是相对于总行数,操作(例如索引扫描或过滤器)产生的唯一值的数量. 选择性越高,PostgreSQL 使用索引的可能性就越大. + +In the above example, there are only 3 unique values: 0, 10, and 20\. This means the cardinality is 3\. The selectivity in turn is also very low: 0.0000003% (2 / 5,811,804), because our `Filter` only filters using two values (`0` and `20`). With such a low selectivity value it’s not surprising that PostgreSQL decides using an index is not worth it, because it would produce almost no unique rows. + +## Rewriting queries[](#rewriting-queries "Permalink") + +因此,上述查询无法真正按原样进行优化,或者至少没有太多优化. 但是,如果我们稍微改变它的目的怎么办? 如果不是检索`visibility_level` 0 或 20 的所有项目,而是检索用户与之交互的那些项目,该怎么办? + +幸运的是,GitLab 对此有一个答案,它是一个名为`user_interacted_projects`的表. 该表具有以下架构: + +``` +Table "public.user_interacted_projects" + Column | Type | Modifiers +------------+---------+----------- + user_id | integer | not null + project_id | integer | not null +Indexes: + "index_user_interacted_projects_on_project_id_and_user_id" UNIQUE, btree (project_id, user_id) + "index_user_interacted_projects_on_user_id" btree (user_id) +Foreign-key constraints: + "fk_rails_0894651f08" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE + "fk_rails_722ceba4f7" FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE +``` + +让我们重写查询以将该表加入到我们的项目中,并获取特定用户的项目: + +``` +EXPLAIN ANALYZE +SELECT COUNT(*) +FROM projects +INNER JOIN user_interacted_projects ON user_interacted_projects.project_id = projects.id +WHERE projects.visibility_level IN (0, 20) +AND user_interacted_projects.user_id = 1; +``` + +我们在这里做的是以下几点: + +1. 获得我们的项目. +2. INNER JOIN `user_interacted_projects` ,这意味着我们只剩下在`user_interacted_projects`中有对应行的`projects`中的行. +3. 将其限制为`visibility_level`为 0 或 20 的项目以及 ID 为 1 的用户与之交互的项目. + +如果运行此查询,则会得到以下计划: + +``` + Aggregate (cost=871.03..871.04 rows=1 width=8) (actual time=9.763..9.763 rows=1 loops=1) + -> Nested Loop (cost=0.86..870.52 rows=203 width=0) (actual time=1.072..9.748 rows=143 loops=1) + -> Index Scan using index_user_interacted_projects_on_user_id on user_interacted_projects (cost=0.43..160.71 rows=205 width=4) (actual time=0.939..2.508 rows=145 loops=1) + Index Cond: (user_id = 1) + -> Index Scan using projects_pkey on projects (cost=0.43..3.45 rows=1 width=4) (actual time=0.049..0.050 rows=1 loops=145) + Index Cond: (id = user_interacted_projects.project_id) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) + Rows Removed by Filter: 0 + Planning time: 2.614 ms + Execution time: 9.809 ms +``` + +在这里,仅花了不到 10 毫秒的时间即可获取数据. 我们还可以看到我们正在检索的项目要少得多: + +``` +Index Scan using projects_pkey on projects (cost=0.43..3.45 rows=1 width=4) (actual time=0.049..0.050 rows=1 loops=145) + Index Cond: (id = user_interacted_projects.project_id) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) + Rows Removed by Filter: 0 +``` + +在这里,我们看到执行了 145 个循环( `loops=145` ),每个循环产生 1 行( `rows=1` ). 这比以前少了很多,我们的查询执行得更好! + +如果我们看一下计划,我们还会发现我们的成本非常低: + +``` +Index Scan using projects_pkey on projects (cost=0.43..3.45 rows=1 width=4) (actual time=0.049..0.050 rows=1 loops=145) +``` + +在这里,我们的成本仅为 3.45,而仅需 0.050 毫秒即可完成. 下一次索引扫描会贵一些: + +``` +Index Scan using index_user_interacted_projects_on_user_id on user_interacted_projects (cost=0.43..160.71 rows=205 width=4) (actual time=0.939..2.508 rows=145 loops=1) +``` + +此处的成本为 160.71( `cost=0.43..160.71` ),大约需要 2.5 毫秒(基于`actual time=....`的输出`actual time=....` ). + +这里最昂贵的部分是对这两个索引扫描的结果起作用的"嵌套循环": + +``` +Nested Loop (cost=0.86..870.52 rows=203 width=0) (actual time=1.072..9.748 rows=143 loops=1) +``` + +在这里,我们必须对 203 行(9.748 毫秒)执行 870.52 磁盘页读取,在单个循环中产生 143 行. + +这里的主要要点是,有时您必须重写(部分)查询以使其更好. 有时,这意味着必须稍微更改功能以适应更好的性能. + +## What makes a bad plan[](#what-makes-a-bad-plan "Permalink") + +这是一个很难回答的问题,因为"坏"的定义与您要解决的问题有关. 但是,在大多数情况下最好避免某些模式,例如: + +* 大表上的顺序扫描 +* 删除大量行的过滤器 +* 执行某个步骤(例如索引扫描)需要*很多*缓冲区(例如,GitLab.com 大于 512 MB). + +作为一般准则,请针对以下查询: + +1. 不超过 10 毫秒. 我们每个请求在 SQL 中花费的目标时间约为 100 毫秒,因此每个查询应尽可能快. +2. 相对于工作负载,不使用过多的缓冲区. 例如,检索十行应该不需要 1 GB 的缓冲区. +3. 不花费大量时间执行磁盘 IO 操作. 必须启用设置`track_io_timing` ,此数据才能包含在`EXPLAIN ANALYZE`的输出中. +4. 在检索行而不对其进行汇总时应用`LIMIT` ,例如`SELECT * FROM users` . +5. 不使用`Filter`过滤掉过多的行,尤其是在查询不使用`LIMIT`限制返回的行数的情况下. 通常可以通过添加(部分)索引来删除过滤器. + +这些是*准则* ,不是硬性要求,因为不同的需求可能需要不同的查询. 唯一的*规则*是,您*必须始终*使用`EXPLAIN (ANALYZE, BUFFERS)`和相关工具*来衡量*您的查询(最好使用类似生产的数据库): + +* [`explain.depesz.com`](https://explain.depesz.com/). +* [`explain.dalibo.com/`](https://explain.dalibo.com/). + +## Producing query plans[](#producing-query-plans "Permalink") + +有几种获取查询计划输出的方法. 当然,您可以直接在`psql`控制台中运行`EXPLAIN`查询,或者可以遵循以下其他选项之一. + +### Rails console[](#rails-console "Permalink") + +Using the [`activerecord-explain-analyze`](https://github.com/6/activerecord-explain-analyze) you can directly generate the query plan from the Rails console: + +``` +pry(main)> require 'activerecord-explain-analyze' +=> true +pry(main)> Project.where('build_timeout > ?', 3600).explain(analyze: true) + Project Load (1.9ms) SELECT "projects".* FROM "projects" WHERE (build_timeout > 3600) + ↳ (pry):12 +=> EXPLAIN for: SELECT "projects".* FROM "projects" WHERE (build_timeout > 3600) +Seq Scan on public.projects (cost=0.00..2.17 rows=1 width=742) (actual time=0.040..0.041 rows=0 loops=1) + Output: id, name, path, description, created_at, updated_at, creator_id, namespace_id, ... + Filter: (projects.build_timeout > 3600) + Rows Removed by Filter: 14 + Buffers: shared hit=2 +Planning time: 0.411 ms +Execution time: 0.113 ms +``` + +### ChatOps[](#chatops "Permalink") + +[GitLab 员工还可以使用`/chatops` slash 命令在 Slack 中使用我们的 ChatOps 解决方案](chatops_on_gitlabcom.html) . 您可以使用 ChatOps 通过运行以下命令来获取查询计划: + +``` +/chatops run explain SELECT COUNT(*) FROM projects WHERE visibility_level IN (0, 20) +``` + +还支持使用[https://explain.depesz.com/](https://explain.depesz.com/)可视化计划: + +``` +/chatops run explain --visual SELECT COUNT(*) FROM projects WHERE visibility_level IN (0, 20) +``` + +不需要查询. + +有关可用选项的更多信息,请运行: + +``` +/chatops run explain --help +``` + +### `#database-lab`[](#database-lab "Permalink") + +GitLab 员工可以使用的另一种工具是由[Joe](https://gitlab.com/postgres-ai/joe)支持的聊天机器人,该机器人使用[Database Lab](https://gitlab.com/postgres-ai/database-lab)立即为开发人员提供他们自己的生产数据库克隆. + +Joe 在 Slack 的[`#database-lab`](https://gitlab.slack.com/archives/CLJMDRD8C)频道中可用. + +与 ChatOps 不同,它为您提供了一种执行 DDL 语句(如创建索引和表)并获取查询计划的方法,该查询计划不仅适用于`SELECT`而且适用于`UPDATE`和`DELETE` . + +例如,为了测试新索引,您可以执行以下操作: + +创建索引: + +``` +exec CREATE INDEX index_projects_last_activity ON projects (last_activity_at) WHERE last_activity_at IS NOT NULL +``` + +分析表以更新其统计信息: + +``` +exec ANALYZE projects +``` + +获取查询计划: + +``` +explain SELECT * FROM projects WHERE last_activity_at < CURRENT_DATE +``` + +完成后,您可以回滚您的更改: + +``` +reset +``` + +有关可用选项的更多信息,请运行: + +``` +help +``` + +#### Tips & Tricks[](#tips--tricks "Permalink") + +现在,在整个会话期间都将维护数据库连接,因此您可以对任何会话变量(例如`enable_seqscan`或`work_mem` )使用`exec set ...` 这些设置将应用于所有后续命令,直到您重置它们. + +也可以使用事务. 当您处理修改数据的语句(例如 INSERT,UPDATE 和 DELETE)时,这可能很有用. `explain`命令将执行`EXPLAIN ANALYZE` ,该语句执行该语句. 为了从干净状态开始运行每个`explain` ,您可以将其包装在事务中,例如: + +``` +exec BEGIN + +explain UPDATE some_table SET some_column = TRUE + +exec ROLLBACK +``` + +## Further reading[](#further-reading "Permalink") + +在[Dalibo.org](https://www.dalibo.com/en/)的[演示中](https://public.dalibo.com/exports/conferences/_archives/_2012/201211_explain/understanding_explain.pdf)可以找到关于理解查询计划的更广泛的指南. \ No newline at end of file diff --git a/_book/docs/566.md b/_book/docs/566.md new file mode 100644 index 0000000000000000000000000000000000000000..d2b099c8e4dfd6f787238efc709cea606cb68868 --- /dev/null +++ b/_book/docs/566.md @@ -0,0 +1,268 @@ +# Rake tasks for developers + +> 原文:[https://docs.gitlab.com/ee/development/rake_tasks.html](https://docs.gitlab.com/ee/development/rake_tasks.html) + +* [Set up database with developer seeds](#set-up-database-with-developer-seeds) + * [Environment variables](#environment-variables) + * [Seeding issues for all or a given project](#seeding-issues-for-all-or-a-given-project) + * [Seeding issues for Insights charts](#seeding-issues-for-insights-charts-ultimate) + * [Seeding groups with sub-groups](#seeding-groups-with-sub-groups) + * [Seeding custom metrics for the monitoring dashboard](#seeding-custom-metrics-for-the-monitoring-dashboard) + * [Automation](#automation) + * [Discard `stdout`](#discard-stdout) + * [Extra Project seed options](#extra-project-seed-options) +* [Run tests](#run-tests) + * [Speed up tests, Rake tasks, and migrations](#speed-up-tests-rake-tasks-and-migrations) +* [Compile Frontend Assets](#compile-frontend-assets) +* [Emoji tasks](#emoji-tasks) +* [Update project templates](#update-project-templates) +* [Generate route lists](#generate-route-lists) +* [Show obsolete `ignored_columns`](#show-obsolete-ignored_columns) +* [Update GraphQL documentation and schema definitions](#update-graphql-documentation-and-schema-definitions) + * [Update machine-readable schema files](#update-machine-readable-schema-files) + +# Rake tasks for developers[](#rake-tasks-for-developers "Permalink") + +Rake 任务适用于开发人员和为 GitLab 做出贡献的其他人员. + +## Set up database with developer seeds[](#set-up-database-with-developer-seeds "Permalink") + +请注意,如果您的数据库用户没有高级特权,则必须在运行此命令之前手动创建数据库. + +``` +bundle exec rake setup +``` + +`setup`任务是`gitlab:setup`的别名. 此任务调用`db:reset`创建数据库,并调用`db:seed_fu`播种数据库. 注意: `db:setup`调用`db:seed`但这没有任何作用. + +### Environment variables[](#environment-variables "Permalink") + +**MASS_INSERT** :创建数百万个用户(2m),项目(5m)及其关系. 强烈建议将种子与种子一起运行,以在开发过程中捕获缓慢的查询. 预计此过程最多可能需要 20 分钟. + +另请参见[批量插入 Rails 模型](mass_insert.html) . + +**LARGE_PROJECTS** :从一组预定义的 URL 创建大型项目(通过导入). + +### Seeding issues for all or a given project[](#seeding-issues-for-all-or-a-given-project "Permalink") + +您可以使用`gitlab:seed:issues`任务为所有项目或给定项目`gitlab:seed:issues` : + +``` +# All projects +bin/rake gitlab:seed:issues + +# A specific project +bin/rake "gitlab:seed:issues[group-path/project-path]" +``` + +默认情况下,每个项目的最近 5 周平均每周播种 2 个问题. + +#### Seeding issues for Insights charts[](#seeding-issues-for-insights-charts-ultimate "Permalink") + +您可以使用`gitlab:seed:insights:issues`任务为专门用于处理[Insights 图表](../user/group/insights/index.html)的`gitlab:seed:insights:issues` : + +``` +# All projects +bin/rake gitlab:seed:insights:issues + +# A specific project +bin/rake "gitlab:seed:insights:issues[group-path/project-path]" +``` + +默认情况下,每个项目在最近 52 周中平均每周播种 10 个问题. 所有问题还将随机标记团队,类型,严重性和优先级. + +#### Seeding groups with sub-groups[](#seeding-groups-with-sub-groups "Permalink") + +您可以使用`gitlab:seed:group_seed`任务为包含里程碑/项目/问题的子组播种组: + +``` +bin/rake "gitlab:seed:group_seed[subgroup_depth, username]" +``` + +如果 GitLab 实例具有可用的史诗功能,则该组还会另外添加史诗. + +#### Seeding custom metrics for the monitoring dashboard[](#seeding-custom-metrics-for-the-monitoring-dashboard "Permalink") + +监视仪表板中支持许多不同类型的指标. + +要导入这些指标,可以运行: + +``` +bundle exec rake 'gitlab:seed:development_metrics[your_project_id]' +``` + +### Automation[](#automation "Permalink") + +If you’re very sure that you want to **清除当前数据库** and refill seeds, you could: + +``` +echo 'yes' | bundle exec rake setup +``` + +使您免于手动回答`yes` . + +### Discard `stdout`[](#discard-stdout "Permalink") + +由于该脚本会打印很多信息,因此可能会减慢您的终端运行速度,并且如果您将其重定向到文件,则会生成 20G 以上的日志. 如果我们不在乎输出,则可以将其重定向到`/dev/null` : + +``` +echo 'yes' | bundle exec rake setup > /dev/null +``` + +请注意,由于您看不到`stdout`的问题,因此您可能只想`echo 'yes'`以使其运行. 它仍然会在`stderr`上打印错误,因此不必担心丢失错误. + +### Extra Project seed options[](#extra-project-seed-options "Permalink") + +您可以传递一些环境标志来更改项目的种子方式 + +* `SIZE` :默认为`8` ,最大为`32` . 要创建的项目数量. +* `LARGE_PROJECTS` :默认为 false. 如果设置,将克隆 6 个大型项目以帮助进行测试. +* `FORK` :默认为 false. 如果设置为`true`将分叉`torvalds/linux`五次. 也可以将其设置为现有项目 full_path,它将代替它. + +## Run tests[](#run-tests "Permalink") + +为了运行测试,您可以使用以下命令: + +* `bin/rake spec`运行 RSpec 套件 +* `bin/rake spec:unit`仅运行单元测试 +* `bin/rake spec:integration`仅运行集成测试 +* `bin/rake spec:system`仅运行系统测试 +* `bin/rake karma`运行 Karma 测试套件 + +`bin/rake spec`需要花费大量时间. 无需在本地运行完整的测试套件,而是可以通过运行与更改相关的单个测试或目录来节省大量时间. 提交合并请求后,CI 将为您运行完整的测试套件. 合并请求中的绿色 CI 状态表示已通过完整的测试套件. + +您不能运行`rspec .` 因为这将尝试运行它可以找到的所有`_spec.rb`文件,以及`/tmp` + +您可以将 RSpec 命令行选项传递给`spec:unit` , `spec:integration`和`spec:system`任务. 例如, `bin/rake "spec:unit[--tag ~geo --dry-run]"` . + +对于 RSpec 测试,要运行一个测试文件,可以运行: + +``` +bin/rspec spec/controllers/commit_controller_spec.rb +``` + +要在一个目录中运行多个测试: + +* 如果仅想测试 API,则对 RSpec 测试使用`bin/rspec spec/requests/api/` + +### Speed up tests, Rake tasks, and migrations[](#speed-up-tests-rake-tasks-and-migrations "Permalink") + +[Spring](https://github.com/rails/spring)是 Rails 应用程序的预加载器. 它通过使应用程序在后台运行来加快开发速度,因此您无需在每次运行测试,Rake 任务或迁移时都启动它. + +如果要使用它,则需要将`ENABLE_SPRING`环境变量导出为`1` : + +``` +export ENABLE_SPRING=1 +``` + +另外,您可以在每次运行规范时使用以下命令, + +``` +bundle exec spring rspec some_spec.rb +``` + +## Compile Frontend Assets[](#compile-frontend-assets "Permalink") + +您永远不需要在开发中手动编译前端资产,但是如果您需要测试在生产环境中如何编译资产,则可以使用以下命令进行: + +``` +RAILS_ENV=production NODE_ENV=production bundle exec rake gitlab:assets:compile +``` + +这将编译并缩小所有 JavaScript 和 CSS 资产,并将它们与所有其他前端资产(图像,字体等)一起复制到`/public/assets`中,以便于对其进行轻松检查. + +## Emoji tasks[](#emoji-tasks "Permalink") + +要更新表情符号别名文件(用于表情符号自动完成),请运行以下命令: + +``` +bundle exec rake gemojione:aliases +``` + +要更新表情符号摘要文件(用于表情符号自动完成),请运行以下命令: + +``` +bundle exec rake gemojione:digests +``` + +这将根据当前可用的表情`fixtures/emojis/digests.json`更新`fixtures/emojis/digests.json`文件. + +要生成包含所有表情符号的 Sprite 文件,请运行: + +``` +bundle exec rake gemojione:sprite +``` + +如果添加了新的表情符号,则子画面可能会更改大小. 为了补偿这种变化,请首先使用上述 Rake 任务生成`emoji.png` Sprite 表,然后检查新 Sprite 表的`SPRITESHEET_WIDTH`并`SPRITESHEET_HEIGHT`地更新`SPRITESHEET_WIDTH`和`SPRITESHEET_HEIGHT`常量. + +## Update project templates[](#update-project-templates "Permalink") + +从模板启动项目需要将该项目导出. 在最新的 master 分支上运行: + +``` +gdk start +bundle exec rake gitlab:update_project_templates +git checkout -b update-project-templates +git add vendor/project_templates +git commit +git push -u origin update-project-templates +``` + +现在创建一个合并请求并将其合并到主请求. + +## Generate route lists[](#generate-route-lists "Permalink") + +要查看 API 路由的完整列表,可以运行: + +``` +bundle exec rake grape:path_helpers +``` + +生成的列表包括 API 端点和功能性 RESTful API 动词的完整列表. + +对于 Rails 控制器,运行: + +``` +bundle exec rake routes +``` + +由于创建这些文件需要一些时间,因此将输出保存到文件以快速参考通常会很有帮助. + +## Show obsolete `ignored_columns`[](#show-obsolete-ignored_columns "Permalink") + +要查看所有已过时的`ignored_columns`的列表, `ignored_columns`运行: + +``` +bundle exec rake db:obsolete_ignored_columns +``` + +随时从自己的`ignored_columns`定义中删除其定义. + +## Update GraphQL documentation and schema definitions[](#update-graphql-documentation-and-schema-definitions "Permalink") + +要基于 GitLab 模式生成 GraphQL 文档,请运行: + +``` +bundle exec rake gitlab:graphql:compile_docs +``` + +在当前状态下,Rake 任务: + +* 生成 GraphQL 对象的输出. +* 将输出放置在`doc/api/graphql/reference/index.md` . + +这使用了来自`graphql-docs` gem 的一些功能,例如其模式解析器和帮助器方法. docs 生成器代码来自于我们,为我们提供了更大的灵活性,例如使用 Haml 模板和生成 Markdown 文件. + +要编辑使用的模板,请查看`lib/gitlab/graphql/docs/templates/default.md.haml` . 实际的渲染器位于`Gitlab::Graphql::Docs::Renderer` . + +`@parsed_schema`是`graphql-docs` gem 期望提供的实例变量. `Gitlab::Graphql::Docs::Helper`定义我们当前使用的`object`方法. 您还应该在这里为要显示的新类型实现任何新方法. + +### Update machine-readable schema files[](#update-machine-readable-schema-files "Permalink") + +要基于 GitLab 模式生成 GraphQL 模式文件,请运行: + +``` +bundle exec rake gitlab:graphql:schema:dump +``` + +它使用 GraphQL Ruby 的内置 Rake 任务来生成[IDL](https://www.prisma.io/blog/graphql-sdl-schema-definition-language-6755bcb9ce51)和 JSON 格式的文件. \ No newline at end of file diff --git a/_book/docs/567.md b/_book/docs/567.md new file mode 100644 index 0000000000000000000000000000000000000000..e5ffb19d79413a758f674deb3018b40c9a8a21e2 --- /dev/null +++ b/_book/docs/567.md @@ -0,0 +1,14 @@ +# Mass inserting Rails models + +> 原文:[https://docs.gitlab.com/ee/development/mass_insert.html](https://docs.gitlab.com/ee/development/mass_insert.html) + +# Mass inserting Rails models[](#mass-inserting-rails-models "Permalink") + +在运行[`rake setup`](rake_tasks.html)时设置环境变量[`MASS_INSERT=1`](rake_tasks.html#environment-variables)将创建数百万条记录,但是默认情况下, `root`用户看不到这些记录. + +要使`root`用户可以看到任意数量的大容量插入项目,请在 rails 控制台中运行以下代码段. + +``` +u = User.find(1) +Project.last(100).each { |p| p.set_timestamps_for_create && p.add_maintainer(u, current_user: u) } # Change 100 to whatever number of projects you need access to +``` \ No newline at end of file diff --git a/_book/docs/568.md b/_book/docs/568.md new file mode 100644 index 0000000000000000000000000000000000000000..e81544b769212f2c6b395778456dc22c5d1a0035 --- /dev/null +++ b/_book/docs/568.md @@ -0,0 +1,548 @@ +# GitLab Documentation guidelines + +> 原文:[https://docs.gitlab.com/ee/development/documentation/](https://docs.gitlab.com/ee/development/documentation/) + +* [Source files and rendered web locations](#source-files-and-rendered-web-locations) + * [Branch naming](#branch-naming) +* [Contributing to docs](#contributing-to-docs) +* [Markdown and styles](#markdown-and-styles) +* [Folder structure and files](#folder-structure-and-files) +* [Metadata](#metadata) + * [Stage and group metadata](#stage-and-group-metadata) + * [Page type metadata](#page-type-metadata) + * [Redirection metadata](#redirection-metadata) + * [Comments metadata](#comments-metadata) + * [Additional page metadata](#additional-page-metadata) +* [Changing document location](#changing-document-location) + * [Redirections for pages with Disqus comments](#redirections-for-pages-with-disqus-comments) +* [Merge requests for GitLab documentation](#merge-requests-for-gitlab-documentation) +* [GitLab `/help`](#gitlab-help) + * [Linking to `/help`](#linking-to-help) + * [GitLab `/help` tests](#gitlab-help-tests) +* [Docs site architecture](#docs-site-architecture) + * [Global navigation](#global-navigation) +* [Previewing the changes live](#previewing-the-changes-live) + * [Troubleshooting review apps](#troubleshooting-review-apps) + * [Technical aspects](#technical-aspects) +* [Testing](#testing) + * [Running tests](#running-tests) + * [Nanoc tests](#nanoc-tests) + * [Lint checks](#lint-checks) + * [Local linters](#local-linters) + * [markdownlint](#markdownlint) + * [Vale](#vale) + * [Install linters](#install-linters) + * [Configure editors](#configure-editors) + * [Disable Vale tests](#disable-vale-tests) +* [Danger Bot](#danger-bot) + +# GitLab Documentation guidelines[](#gitlab-documentation-guidelines "Permalink") + +GitLab 的文档[旨在作为唯一的真实来源(SSOT)](https://about.gitlab.com/handbook/documentation/) ,提供有关如何配置,使用 GitLab 以及对其进行故障排除的信息. 该文档包含按产品领域和主题组织的每个 GitLab 功能的用例和使用说明. 这包括跨多个 GitLab 功能的主题和工作流程,以及将 GitLab 与其他应用程序一起使用. + +除了此页面之外,以下资源还可以帮助您编写文档并做出贡献: + +* [样式指南](styleguide.html) -文档,语言指南,要遵循的 Markdown 标准,链接等内容. +* [结构和模板](structure.html) -了解文档页面的典型部分以及如何编写每一部分. +* [Documentation process](workflow.html). +* [Markdown 指南](../../user/markdown.html) -有关 GitLab 支持的所有 Markdown 语法的参考. +* [网站架构](site_architecture/index.html) -https [://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site)的构建方式. +* [功能标记的文档](feature_flags.html) -如何编写和更新部署在功能标记后面的 GitLab 功能的文档. + +## Source files and rendered web locations[](#source-files-and-rendered-web-locations "Permalink") + +有关 GitLab,GitLab Runner,Omnibus GitLab 和 Charts 的文档已发布到[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site) . GitLab 的文档也发布在 GitLab 实例域的`/help`内的应用程序中. 在`/help` ,仅包含当前版本和版本的帮助. 有关其他版本的帮助,请访问[https://docs.gitlab.com/archives/](https://docs.gitlab.com/archives/) . + +文档的源位于以下仓库位置的每个 GitLab 应用程序的代码库中: + +| Project | Path | +| --- | --- | +| [GitLab](https://gitlab.com/gitlab-org/gitlab/) | [`/doc`](https://gitlab.com/gitlab-org/gitlab/tree/master/doc) | +| [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/) | [`/docs`](https://gitlab.com/gitlab-org/gitlab-runner/tree/master/docs) | +| [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/) | [`/doc`](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc) | +| [Charts](https://gitlab.com/gitlab-org/charts/gitlab) | [`/doc`](https://gitlab.com/gitlab-org/charts/gitlab/tree/master/doc) | + +文档问题和合并请求是它们各自存储库的一部分,都带有标签`Documentation` . + +### Branch naming[](#branch-naming "Permalink") + +[GitLab 主项目](../pipelines.html)的[CI 管道](../pipelines.html)配置为仅自动运行与贡献类型匹配的作业. 如果您的贡献**仅**包含文档更改,那么将仅运行与文档相关的作业,并且管道的完成将比代码贡献更快. + +如果要向 Runner,Omnibus 或 Charts 提交仅文档更改,则不会自动确定快速管道. 相反,请使用以下指南为仅文档合并请求创建分支: + +| 分店名称 | 有效的例子 | +| --- | --- | +| 从`docs/`开始 | `docs/update-api-issues` | +| 从`docs-`开始 | `docs-update-api-issues` | +| 以`-docs` | `123-update-api-issues-docs` | + +## Contributing to docs[](#contributing-to-docs "Permalink") + +整个 GitLab 社区都欢迎[对 GitLab 文档做出贡献](workflow.html) . + +为确保 GitLab 文档是最新的,所有[功能更改](feature-change-workflow.html)都有特殊的流程和职责,即影响功能外观,使用或管理的开发工作. + +但是,任何人都可以贡献与功能更改无关的[文档改进](improvement-workflow.html) . 例如,添加有关如何完成用例的新文档,这可以通过 GitLab 或第三方工具和 GitLab 完成. + +## Markdown and styles[](#markdown-and-styles "Permalink") + +[GitLab 文档](https://gitlab.com/gitlab-org/gitlab-docs)使用[GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown)作为其 Markdown 渲染引擎. 有关完整的 Kramdown 参考,请参阅《 [GitLab Markdown 指南》](https://about.gitlab.com/handbook/markdown-guide/) . + +遵守[文档样式指南](styleguide.html) . 如果缺少样式标准,欢迎您通过合并请求提出建议. + +## Folder structure and files[](#folder-structure-and-files "Permalink") + +请参阅" [文档样式指南"](styleguide.html)的" [结构"](styleguide.html#structure)部分. + +## Metadata[](#metadata "Permalink") + +为了提供其他指令或有用的信息,我们将 YAML 格式的元数据添加到每个产品文档页面的开头(YAML 开头). 所有值均视为字符串,仅用于[docs 网站](site_architecture/index.html) . + +### Stage and group metadata[](#stage-and-group-metadata "Permalink") + +理想情况下,每个页面都应具有与其所属的阶段和组相关的元数据,以及如下所述的信息块: + +* `stage` :页面大部分内容所属的[Stage](https://about.gitlab.com/handbook/product/product-categories/#devops-stages) . +* `group` :页面大部分内容所属的[Group](https://about.gitlab.com/company/team/structure/#product-groups) . +* `info` :下一行,为与该页面的舞台和小组相关的技术作家联系提供指导,以帮助参与者: + + ``` + To determine the technical writer assigned to the Stage/Group + associated with this page, see + https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers + ``` + +例如,以下元数据将位于产品文档页面的开始,其内容主要与"审核事件"功能相关: + +``` +--- +stage: Monitor +group: APM +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- +``` + +### Page type metadata[](#page-type-metadata "Permalink") + +最初在[此史诗中](https://gitlab.com/groups/gitlab-org/-/epics/1280)讨论过,每个页面应该具有`type`元数据. 可以是以下一项或多项: + +* `index` :索引/概述页面. 它们充当其他页面的列表. 不一定意味着页面应命名为`index.md` . [示例页面](../../install/README.html) . +* `concepts` :使用产品之前需要了解的内容. 信息性的,非指导性的. 例如,抽象的想法,解释含义或收益,支持对任务的理解. 阅读它们以获取背景信息,例如"为什么 X 很重要". [示例页面](../../topics/autodevops/index.html) . +* `howto` :特定用例说明. [示例页面](../../ssh/README.html) . +* `tutorial` :边做边学过程/概念. [示例页面](../../gitlab-basics/start-using-git.html) . +* `reference` :介绍什么是/做什么. 诸如特定设置,没有太多解释的事实之类的东西可以阅读以获取详细信息. [示例页面](../../ci/yaml/README.html) . + +### Redirection metadata[](#redirection-metadata "Permalink") + +将页面移到另一个位置时,应添加以下元数据: + +* `redirect_to` :访问者应将移动页面重定向到的相对路径和文件名(扩展名为`.md` ). [了解更多](#changing-document-location) . +* `disqus_identifier` :Disqus 评论系统的标识符. 用于保留已被移至新 URL 的页面的注释. [了解更多](#redirections-for-pages-with-disqus-comments) . + +### Comments metadata[](#comments-metadata "Permalink") + +[docs 网站](site_architecture/index.html)上默认启用了注释(由 Disqus 提供). 如果要禁用它们(例如在索引页面中),请将其设置为`false` : + +``` +--- +comments: false +--- +``` + +### Additional page metadata[](#additional-page-metadata "Permalink") + +每个页面可以具有其他(可选)元数据(在[default.html](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/fc3577921343173d589dfa43d837b4307e4e620f/layouts/default.html#L30-52) Nanoc 布局中设置),如果定义,这些元数据将显示在页面顶部: + +* `author` :页面`author`的名称,通常是教程. 它需要`author_gitlab`才能显示. +* `author_gitlab` :GitLab.com 上作者的用户名. 它需要`author`才能显示. +* `date` :页面的创建日期,通常用于教程. +* `article_type` :文章的类型. 可以是`tutorial`或`user guide` . +* `level` :操作方法或教程的复杂程度. 可以是`beginner` , `advanced`或`intermediate` . +* `last_updated` :页面上次更新时的 ISO 格式日期. 例如`2020-02-14` . +* `reading_time` :如果要添加页面的大概阅读时间的指示,可以将`reading_time`设置为`true` . 这使用简单的[算法](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/lib/helpers/reading_time.rb)根据单词数计算阅读时间. + +## Changing document location[](#changing-document-location "Permalink") + +更改文档的位置需要特定的步骤,以确保用户可以无缝访问新的文档页面,无论他们是通过`/help`还是通过[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site)访问 GitLab 实例域上的内容. 如果您在此过程中有任何疑问(例如是否需要搬迁),请务必指派一名技术作家,并确保在合并之前技术作家会对此更改进行审查. + +如果确实需要更改文档的位置,请不要删除旧文档,而应将所有内容替换为以下内容: + +``` +--- +redirect_to: '../path/to/file/index.md' +--- + +This document was moved to [another location](../path/to/file/index.md). +``` + +其中`../path/to/file/index.md`通常是旧文档的相对路径. + +所述`redirect_to`变量同时支持完整或相对 URL,例如`https://docs.gitlab.com/ee/path/to/file.html` , `../path/to/file.html` , `path/to/file.md` . 它确保重定向将对[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site)起作用,并且任何`*.md`路径都将编译为`*.html` . 前部事项下方的新行通知用户文档已更改位置,对于从存储库浏览该文件的用户而言非常有用. + +例如,如果将`doc/workflow/lfs/index.md`移到`doc/administration/lfs.md` ,则步骤将是: + +1. Copy `doc/workflow/lfs/index.md` to `doc/administration/lfs.md` +2. 将`doc/workflow/lfs/index.md`的内容替换为: + + ``` + --- + redirect_to: '../../administration/lfs.md' + --- + + This document was moved to [another location](../../administration/lfs.md). + ``` + +3. 查找并用新位置替换所有出现的旧位置. 查找它们的快速方法是在将文件从以下位置更改的存储库中使用`git grep` : + + ``` + git grep -n "workflow/lfs/lfs_administration" + git grep -n "lfs/lfs_administration" + ``` + +**注意:**如果要移动的文档上有任何 Disqus 评论,则要执行的其他步骤[如下所示](#redirections-for-pages-with-disqus-comments) . + +注意事项: + +* 由于除了文档本身以外,我们还使用内联文档,因此该文档也可能在访问`/help`时将呈现的 GitLab( `app/` )视图中引用,有时甚至在测试套件( `spec/` )中也会引用. 您必须在这些路径中搜索对文档的引用并进行更新. +* 上面的`git grep`命令将在您在其中运行它的目录中以递归方式搜索`workflow/lfs/lfs_administration`和`lfs/lfs_administration` ,并将打印文件和提及该文件的行. 您可能会问为什么这两次抱怨. 由于[我们使用相对路径链接到文档](styleguide.html#links) ,因此有时更深入地搜索路径可能很有用. +* 当文档链接到 GitLab 的内置帮助页面时,不使用`*.md`扩展名,这就是为什么我们在`git grep`忽略它. +* 使用"更改文档位置" MR 描述模板上的清单. + +### Redirections for pages with Disqus comments[](#redirections-for-pages-with-disqus-comments "Permalink") + +如果要重定位的文档页面已经包含 Disqus 评论,则我们需要保留 Disqus 线程. + +Disqus 使用每页标识符,对于[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site) ,页面标识符被配置为页面 URL. 因此,当我们更改文档位置时,我们需要将旧的 URL 保留为相同的 Disqus 标识符. + +为此,将变量`disqus_identifier`添加到`disqus_identifier` ,使用旧的 URL 作为值. 例如,假设我们将`https://docs.gitlab.com/my-old-location/README.html`下可用的文档移到了新位置`https://docs.gitlab.com/my-new-location/index.html` . + +在**新文档的**开头部分,我们添加了以下内容: + +``` +--- +disqus_identifier: 'https://docs.gitlab.com/my-old-location/README.html' +--- +``` + +注:有必要在文件名中`disqus_identifier` URL,即使它`index.html`或`README.html` . + +## Merge requests for GitLab documentation[](#merge-requests-for-gitlab-documentation "Permalink") + +在开始之前,请确保您已阅读上面的" [为文档做贡献](#contributing-to-docs) "介绍性部分和[文档工作流程](workflow.html) . + +* 使用当前的[合并请求描述模板](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/merge_request_templates/Documentation.md) +* 标记 MR `Documentation` (只能由具有`developer`访问权限的`developer` (例如,GitLab 团队成员)完成) +* 在下面的每个注释中分配正确的里程碑(只能由具有`developer`访问权限的人(例如,GitLab 团队成员)完成) + +如果对现有内容进行了改进,文档将被合并,这代表了遵循模板和样式标准的真诚努力,并且被认为是准确的. + +对于进一步完善文档的进一步需求,应在后续的 MR 或问题中立即解决. + +**注意:**如果要添加文档的发行版已经冻结或发行,请使用标签`~"Pick into XY"`将其合并到正确的发行版中. 尽量避免选择过去的发行版,因为这样做会增加发行版管理器的工作量. + +## GitLab `/help`[](#gitlab-help "Permalink") + +每个 GitLab 实例都包含文档,该文档可从`/help` ( `https://gitlab.example.com/help` )获得. 例如, [https://gitlab.com/help](https://gitlab.com/help) . + +[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site)上在线提供的文档每隔四个小时从 GitLab,Omnibus 和 Runner 的`master`分支进行部署. 因此,合并请求合并后,它将在同一天在线可用. 但是,它将在分配给 MR 的里程碑内发货(并在`/help`上可用). + +例如,假设您的合并请求的里程碑设置为 11.3,该里程碑将于 2018-09-22 发布. 如果在 2018-09-15 合并,它将在 2018-09-15 联机提供,但是,随着功能冻结日期的过去,如果 MR 没有`~"Pick into 11.3"`标签,那么该里程碑必须更改为 11.4,并且仅在 2018-10-22 以及 GitLab 11.4 中将与所有 GitLab 软件包一起提供. 这意味着,它将仅在 GitLab 11.4 及更高版本的`/help`下提供,但在合并的同一天在[https://docs.gitlab.com/](https://docs.gitlab.com/)上提供. + +### Linking to `/help`[](#linking-to-help "Permalink") + +构建新功能时,可能需要从应用程序 GitLab 链接文档. 通常,这是通过`help_page_path` helper 方法在`app/views/`目录内的文件中完成的. + +以最简单的形式,用于生成到`/help`页面的链接的 HAML 代码为: + +``` += link_to 'Help page', help_page_path('user/permissions') +``` + +`help_page_path`使用以下约定包含要链接到的文档的路径: + +* 它相对于 GitLab 存储库中的`doc/`目录 +* `.md`扩展名必须省略 +* 它不能以斜杠( `/` )结尾 + +以下是根据情况应使用的一些特殊情况. 您可以结合以下一项或多项: + +1. **链接到锚链接.** 使用`anchor`作为`help_page_path`方法的一部分: + + ``` + = link_to 'Help page', help_page_path('user/permissions', anchor: 'anchor-link') + ``` + +2. **在新标签页中打开链接.** 这应该是默认行为: + + ``` + = link_to 'Help page', help_page_path('user/permissions'), target: '_blank' + ``` + +3. **链接到圆圈图标.** 通常用于无法使用长描述的设置,例如复选框旁边. 您基本上可以使用任何字体超赞的图标,但更喜欢使用`question-circle` : + + ``` + = link_to icon('question-circle'), help_page_path('user/permissions') + ``` + +4. **使用按钮链接.** 在文本与页面布局其余部分脱离上下文的地方很有用: + + ``` + = link_to 'Help page', help_page_path('user/permissions'), class: 'btn btn-info' + ``` + +5. **使用内联某些文本的链接.** + + ``` + Description to #{link_to 'Help page', help_page_path('user/permissions')}. + ``` + +6. **在句子末尾添加句点.** Useful when you don’t want the period to be part of the link: + + ``` + = succeed '.' do + Learn more in the + = link_to 'Help page', help_page_path('user/permissions') + ``` + +### GitLab `/help` tests[](#gitlab-help-tests "Permalink") + +运行了一些[RSpec 测试](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/features/help_pages_spec.rb)以确保 GitLab 文档能够呈现并正常工作. 特别是,该[主要文档的登录页面](../../README.html)将从`/help`正确运行. 例如, [GitLab.com 的`/help`](https://gitlab.com/help) . + +## Docs site architecture[](#docs-site-architecture "Permalink") + +请参阅" [文档"网站的体系结构](site_architecture/index.html)页面,以了解我们如何在[https://docs.gitlab.com 上](https://s0docs0gitlab0com.icopy.site)构建和部署该网站,并查看所有正在使用的资产和库. + +### Global navigation[](#global-navigation "Permalink") + +有关如何构建和更新左侧导航菜单的信息,请参阅[全局导航](site_architecture/global_nav.html)文档. + +## Previewing the changes live[](#previewing-the-changes-live "Permalink") + +**注意:**要在本地预览对文档的更改,请遵循本[开发指南](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/README.md#development-when-contributing-to-gitlab-documentation)或[GDK 的这些说明](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/gitlab_docs.md) . + +当前为以下项目启用了实时预览: + +* [`gitlab`](https://gitlab.com/gitlab-org/gitlab) +* [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner) + +如果您的合并请求中有 docs 更改,则可以使用手动`review-docs-deploy`作业为合并请求部署 docs review 应用. 您将至少需要维护者权限才能运行它. + +[![Manual trigger a docs build](img/4a007f26d24f09e03b3bb388bd94ae30.png)](img/manual_build_docs.png) + +**注意:**您将需要将分支推送到这些存储库,它不适用于 fork. + +`review-docs-deploy*`工作将: + +1. 在[`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs)项目中创建一个以该方案命名的新分支: `docs-preview-$DOCS_GITLAB_REPO_SUFFIX-$CI_MERGE_REQUEST_IID` ,其中`DOCS_GITLAB_REPO_SUFFIX`是每个产品的后缀,例如`ee`表示 EE, `omnibus`表示 Omnibus `CI_MERGE_REQUEST_IID` , `CI_MERGE_REQUEST_IID`等,相应合并请求的 ID. +2. 触发跨项目管道,并使用您的更改构建文档站点. + +如果评论应用程序 URL 返回 404,则意味着该站点尚未部署,或者远程管道出了点问题. 给它几分钟,它应该在线显示,否则,您可以从合并请求的作业输出中的链接检查远程管道的状态. 如果管道失败或阻塞,请在`#docs`聊天频道中添加一行. + +**提示:**对 GitLab 项目没有合并权限的人(想想贡献者的分支)不能运行手动作业. 在这种情况下,您可以请 GitLab 团队的某人授权为您执行此操作.**注意:**确保始终删除正在处理的合并请求的分支. 如果您不这样做,那么远程 docs 分支也不会被删除,并且承载 Review Apps 的服务器最终将没有磁盘空间. + +### Troubleshooting review apps[](#troubleshooting-review-apps "Permalink") + +如果评论应用程序 URL 返回 404,请按照以下步骤进行调试: + +1. **您是否遵循了合并请求小部件中的 URL?** 如果是,则检查链接是否与作业输出中的链接相同. +2. **您是否遵循作业输出中的 URL?** 如果是,则意味着该站点尚未部署或远程管道出了点问题. 给它几分钟,它应该在线显示,否则,您可以从作业输出中的链接检查远程管道的状态. 如果管道失败或阻塞,请在`#docs`聊天频道中添加一行. + +### Technical aspects[](#technical-aspects "Permalink") + +如果您想了解更深入的细节,这就是实际发生的事情: + +1. 您在合并请求中手动运行`review-docs-deploy`作业. +2. The job runs the [`scripts/trigger-build-docs`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/trigger-build-docs) script with the `deploy` flag, which in turn: + 1. 使用您的分支名称并应用以下内容: + * `docs-preview-`前缀已添加. + * 产品信息用于了解评论应用所源自的项目. + * 添加了合并请求的编号,以便您可以通过`gitlab-docs`分支名称知道其源自的合并请求. + 2. The remote branch is then created if it doesn’t exist (meaning you can re-run the manual job as many times as you want and this step will be skipped). + 3. 在 docs 项目中触发了新的跨项目管道. + 4. 预览 URL 显示在作业输出和合并请求小部件中. 您还将获得到远程管道的链接. +3. 在 docs 项目中,创建了管道,它[跳过了测试作业](https://gitlab.com/gitlab-org/gitlab-docs/blob/8d5d5c750c602a835614b02f9db42ead1c4b2f5e/.gitlab-ci.yml#L50-55)以减少构建时间. +4. 构建了 docs 网站之后,HTML 文件即作为工件上传. +5. 仅与 docs 项目相关联的特定 Runner,运行 Review App 作业,该作业下载工件,并使用`rsync`将文件传输到 NGINX 为它们提供文件的位置. + +The following GitLab features are used among others: + +* [Manual actions](../../ci/yaml/README.html#whenmanual) +* [Multi project pipelines](../../ci/multi_project_pipeline_graphs.html) +* [Review Apps](../../ci/review_apps/index.html) +* [Artifacts](../../ci/yaml/README.html#artifacts) +* [Specific Runner](../../ci/runners/README.html#prevent-a-specific-runner-from-being-enabled-for-other-projects) +* [Pipelines for merge requests](../../ci/merge_request_pipelines/index.html) + +## Testing[](#testing "Permalink") + +我们将文档视为代码,因此在 CI 管道中使用测试来维护文档的标准和质量. 提交带有新文档或更改文档的合并请求时,当前测试在 CI 作业中运行,它们是: + +* [`docs lint`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/docs.gitlab-ci.yml#L48) :对 docs 本身的内容运行一些测试: + * [`lint-doc.sh`脚本](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/lint-doc.sh)运行以下检查和操作: + * 所有 cURL 示例都使用长标记(例如:-- `--header` ,而不是`-H` ). + * `CHANGELOG.md`不包含重复的版本. + * `doc/`中没有文件是可执行文件. + * 没有添加新的`README.md` . + * [markdownlint](#markdownlint) . + * [谷](#vale) + * Nanoc 测试: + * [`internal_links`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/docs.gitlab-ci.yml#L67)检查所有内部链接(例如: `[link](../index.md)` )是否有效. + * [`internal_anchors`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/docs.gitlab-ci.yml#L69)检查所有内部锚点(例如: `[link](../index.md#internal_anchor)` )是否有效. + +### Running tests[](#running-tests "Permalink") + +除了在[本地预览更改](#previewing-the-changes-live)之外,您还可以[在本地](#previewing-the-changes-live)运行所有棉绒检查和 Nanoc 测试. + +#### Nanoc tests[](#nanoc-tests "Permalink") + +要在本地执行 Nanoc 测试: + +1. 导航到[`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs)目录. +2. Run: + + ``` + # Check for broken internal links + bundle exec nanoc check internal_links + + # Check for broken external links (might take a lot of time to complete). + # This test is set to be allowed to fail and is run only in the gitlab-docs project CI + bundle exec nanoc check internal_anchors + ``` + +#### Lint checks[](#lint-checks "Permalink") + +Lint 检查由[`lint-doc.sh`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/lint-doc.sh)脚本执行,可以按以下方式执行: + +1. 导航到`gitlab`目录. +2. Run: + + ``` + MD_DOC_PATH=path/to/my_doc.md scripts/lint-doc.sh + ``` + +`MD_DOC_PATH`指向您要运行 lint 检查的文件或目录的位置. 如果完全省略它,它将默认为`doc/`目录. 输出应类似于: + +``` +=> Linting documents at path /path/to/gitlab as ... +=> Checking for cURL short options... +=> Checking for CHANGELOG.md duplicate entries... +=> Checking /path/to/gitlab/doc for executable permissions... +=> Checking for new README.md files... +=> Linting markdown style... +=> Linting prose... +✔ 0 errors, 0 warnings and 0 suggestions in 1 file. +✔ Linting passed +``` + +请注意,这要求您要么在计算机上安装了必需的 lint 工具,要么在运行的 Docker 安装中,在这种情况下,将使用预安装了这些工具的映像. + +### Local linters[](#local-linters "Permalink") + +为了帮助您遵守[文档样式指南](styleguide.html) ,并改善添加到文档中的内容, [请安装文档短绒](#install-linters) , [并将其与代码编辑器集成](#configure-editors) . + +在 GitLab,我们主要使用: + +* [markdownlint](#markdownlint) +* [Vale](#vale) + +#### markdownlint[](#markdownlint "Permalink") + +[markdownlint](https://github.com/DavidAnson/markdownlint)检查 Markdown 语法是否遵循[某些规则](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#rules) ,并由[`docs-lint`测试使用](#testing) . + +我们的[文档样式指南](styleguide.html#markdown)和[Markdown 指南](https://about.gitlab.com/handbook/markdown-guide/)详细说明了为 GitLab 文档选择 Markdown 语法时必须进行哪些选择. 该工具有助于发现与这些准则的偏差. + +在以下项目中找到 markdownlint 配置: + +* [`gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/.markdownlint.json) +* [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/.markdownlint.json) +* [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/.markdownlint.json) +* [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/.markdownlint.json) +* [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/.markdownlint.json) + +在构建管道中也使用此配置. + +您可以使用 markdownlint: + +* [On the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--). +* [Within a code editor](#configure-editors). + +#### Vale[](#vale "Permalink") + +[淡水河谷](https://errata-ai.gitbook.io/vale/)是英语的语法,样式和单词用法惯用语. Vale 的配置存储在项目根目录下的[`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/blob/master/.vale.ini)文件中. + +Vale 支持创建可扩展多种检查类型的[自定义测试](https://errata-ai.github.io/vale/styles/) ,我们将这些检查存储在项目文档目录的`.linting/vale/styles/gitlab`目录中. + +在以下项目中找到 Vale 配置: + +* [`gitlab`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.vale/gitlab) +* [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/master/docs/.vale/gitlab) +* [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/tree/master/doc/.vale/gitlab) +* [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/tree/master/doc/.vale/gitlab) +* [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/master/doc/.vale/gitlab) + +在构建管道中也使用此配置. + +您可以使用 Vale: + +* [On the command line](https://errata-ai.gitbook.io/vale/getting-started/usage). +* [Within a code editor](#configure-editors). + +#### Install linters[](#install-linters "Permalink") + +至少要安装[markdownlint](#markdownlint)和[Vale](#vale)以匹配在构建管道中运行的检查: + +1. 使用以下任一方法安装`markdownlint-cli` : + + * `npm`: + + ``` + npm install -g markdownlint-cli + ``` + + * `yarn`: + + ``` + yarn global add markdownlint-cli + ``` + + 我们建议安装 linting [Docker image](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/dockerfiles/Dockerfile.gitlab-docs-lint#L38)文档中当前使用的`markdownlint-cli`版本. + +2. 安装[`vale`](https://github.com/errata-ai/vale/releases) . 例如,要使用`brew` for macOS 安装,请运行: + + ``` + brew install vale + ``` + + We recommend installing the version of Vale currently used in the documentation linting [Docker image](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/dockerfiles/Dockerfile.gitlab-docs-lint#L16). + +除了在命令行上使用 markdownlint 和 Vale 之外,这些工具还可以[与代码编辑器集成](#configure-editors) . + +#### Configure editors[](#configure-editors "Permalink") + +要在编辑器中配置 markdownlint,请根据需要安装以下之一: + +* [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint) +* [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint) +* [Atom](https://atom.io/packages/linter-node-markdownlint) + +要在编辑器中配置 Vale,请根据需要安装以下任一程序: + +* Sublime Text [`SublimeLinter-contrib-vale`插件](https://packagecontrol.io/packages/SublimeLinter-contrib-vale) +* Visual Studio Code [`testthedocs.vale`扩展](https://marketplace.visualstudio.com/items?itemName=testthedocs.vale) + +我们不使用[Vale Server](https://errata-ai.github.io/vale/#using-vale-with-a-text-editor-or-another-third-party-application) . + +#### Disable Vale tests[](#disable-vale-tests "Permalink") + +您可以为文档的任何部分禁用特定的 Vale 棉绒规则或所有 Vale 棉绒规则: + +* 要禁用特定规则,添加``文本之前标记和``后的文字标签,更换`rulename`与[GitLab 样式](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.linting/vale/styles/gitlab)目录中测试的文件名. +* 要禁用所有淡水河谷棉绒规则,请在文本前添加``淡水``标签,并在文本后添加``淡水``标签. + +只要有可能,仅排除有问题的规则和行. 在某些情况下,例如列表项,您可能需要禁用整个列表的绒毛,直到[Vale 问题#175](https://github.com/errata-ai/vale/issues/175)得到解决. + +有关更多信息,请参见[Vale 的文档](https://errata-ai.gitbook.io/vale/getting-started/markup#markup-based-configuration) . + +## Danger Bot[](#danger-bot "Permalink") + +GitLab 在代码审查中的某些元素上使用了[Danger](https://github.com/danger/danger) . 对于文档在合并请求中的更改,每当对`/doc`下的文件进行更改时,Danger Bot 都会在注释中留下有关文档处理的进一步说明. 这是在 GitLab 存储库中的`Dangerfile`中[/ danger / documentation /下配置的](https://gitlab.com/gitlab-org/gitlab/tree/master/danger/documentation) . \ No newline at end of file diff --git a/_book/docs/569.md b/_book/docs/569.md new file mode 100644 index 0000000000000000000000000000000000000000..74dc7e0628f9fe89009bb4fdb4b37aa847a6c696 --- /dev/null +++ b/_book/docs/569.md @@ -0,0 +1,1547 @@ +# Documentation Style Guide + +> 原文:[https://docs.gitlab.com/ee/development/documentation/styleguide.html](https://docs.gitlab.com/ee/development/documentation/styleguide.html) + +* [Documentation is the single source of truth (SSOT)](#documentation-is-the-single-source-of-truth-ssot) + * [Why a single source of truth](#why-a-single-source-of-truth) + * [All information](#all-information) + * [All media types](#all-media-types) + * [No special types](#no-special-types) + * [Link instead of summarize](#link-instead-of-summarize) + * [Organize by topic, not by type](#organize-by-topic-not-by-type) + * [Docs-first methodology](#docs-first-methodology) +* [Markdown](#markdown) + * [HTML in Markdown](#html-in-markdown) + * [Markdown Rules](#markdown-rules) + * [Markdown rule `MD044/proper-names` (capitalization)](#markdown-rule-md044proper-names-capitalization) +* [Structure](#structure) + * [Folder structure overview](#folder-structure-overview) + * [Work with directories and files](#work-with-directories-and-files) + * [Avoid duplication](#avoid-duplication) + * [References across documents](#references-across-documents) + * [Structure within documents](#structure-within-documents) +* [Language](#language) + * [Point of view](#point-of-view) + * [Capitalization](#capitalization) + * [Language to avoid](#language-to-avoid) + * [Word usage clarifications](#word-usage-clarifications) + * [Contractions](#contractions) +* [Text](#text) + * [Emphasis](#emphasis) + * [Punctuation](#punctuation) + * [Placeholder text](#placeholder-text) +* [Lists](#lists) + * [Ordered vs. unordered lists](#ordered-vs-unordered-lists) + * [Markup](#markup) + * [Punctuation](#punctuation-1) + * [Nesting inside a list item](#nesting-inside-a-list-item) +* [Tables](#tables) + * [Creation guidelines](#creation-guidelines) + * [Feature tables](#feature-tables) +* [Quotes](#quotes) +* [Headings](#headings) + * [Heading titles](#heading-titles) + * [Anchor links](#anchor-links) +* [Links](#links) + * [Basic link criteria](#basic-link-criteria) + * [Links to internal documentation](#links-to-internal-documentation) + * [Links to external documentation](#links-to-external-documentation) + * [Links requiring permissions](#links-requiring-permissions) + * [Link to specific lines of code](#link-to-specific-lines-of-code) +* [Navigation](#navigation) +* [Images](#images) + * [Capture the image](#capture-the-image) + * [Save the image](#save-the-image) + * [Add the image link to content](#add-the-image-link-to-content) + * [Remove image shadow](#remove-image-shadow) + * [Compress images](#compress-images) +* [Videos](#videos) + * [Link to video](#link-to-video) + * [Embed videos](#embed-videos) +* [Code blocks](#code-blocks) +* [GitLab SVG icons](#gitlab-svg-icons) + * [Use GitLab SVGs to describe UI elements](#use-gitlab-svgs-to-describe-ui-elements) +* [Alert boxes](#alert-boxes) + * [Note](#note) + * [When to use](#when-to-use) + * [Tip](#tip) + * [Caution](#caution) + * [Danger](#danger) +* [Blockquotes](#blockquotes) +* [Terms](#terms) + * [Merge Requests (MRs)](#merge-requests-mrs) + * [Describe UI elements](#describe-ui-elements) + * [Verbs for UI elements](#verbs-for-ui-elements) + * [Other Verbs](#other-verbs) +* [GitLab versions and tiers](#gitlab-versions-and-tiers) + * [Text for documentation requiring version text](#text-for-documentation-requiring-version-text) + * [Versions in the past or future](#versions-in-the-past-or-future) + * [Importance of referencing GitLab versions and tiers](#importance-of-referencing-gitlab-versions-and-tiers) +* [Products and features](#products-and-features) + * [Avoid line breaks in names](#avoid-line-breaks-in-names) + * [Product badges](#product-badges) + * [How it works](#how-it-works) +* [Specific sections](#specific-sections) + * [GitLab restart](#gitlab-restart) + * [Installation guide](#installation-guide) + * [Configuration documentation for source and Omnibus installations](#configuration-documentation-for-source-and-omnibus-installations) + * [Troubleshooting](#troubleshooting) +* [Feature flags](#feature-flags) +* [API](#api) + * [API topic template](#api-topic-template) + * [Fake user information](#fake-user-information) + * [Fake URLs](#fake-urls) + * [Fake tokens](#fake-tokens) + * [Method description](#method-description) + * [cURL commands](#curl-commands) + * [cURL Examples](#curl-examples) + * [Simple cURL command](#simple-curl-command) + * [cURL example with parameters passed in the URL](#curl-example-with-parameters-passed-in-the-url) + * [Post data using cURL’s `--data`](#post-data-using-curls---data) + * [Post data using JSON content](#post-data-using-json-content) + * [Post data using form-data](#post-data-using-form-data) + * [Escape special characters](#escape-special-characters) + * [Pass arrays to API calls](#pass-arrays-to-api-calls) + +# Documentation Style Guide[](#documentation-style-guide "Permalink") + +本文档定义了 GitLab 文档内容和文件的标准. + +有关该文档的更多信息,请参见《 [文档指南》](index.html) . + +有关遵循该准则的编程帮助,请参阅" [测试"](index.html#testing) . + +请参阅 GitLab 手册,以获取适用于所有 GitLab 内容(不仅是文档)的进一步的[写作风格指南](https://about.gitlab.com/handbook/communication/#writing-style-guidelines) . + +## Documentation is the single source of truth (SSOT)[](#documentation-is-the-single-source-of-truth-ssot "Permalink") + +### Why a single source of truth[](#why-a-single-source-of-truth "Permalink") + +GitLab 产品和功能的文档是 SSOT,其中包含与实施,使用和故障排除有关的所有信息. 它与新产品和功能保持一致,并不断改进,以提高清晰度,准确性和完整性. + +该策略可以防止信息孤岛,从而更轻松地查找有关 GitLab 产品的信息. + +它还可以就我们包含在文档中的内容种类提供决策. + +### All information[](#all-information "Permalink") + +只要可以以充分详细的警告和警告的形式提供适当的上下文,就可以包括解决可能很少见或被认为是"危险"的解决问题的措施. 应该包括这类内容,因为它可能对其他人有帮助,并且在正确解释后,其好处大于风险. 如果您认为发现此规则有例外,请与技术写作团队联系. + +无论用户遇到何种情况,我们都会将所有故障排除信息添加到文档中. 对于" [疑难解答"部分](#troubleshooting) ,GitLab 支持人员可以自己合并添加项. + +### All media types[](#all-media-types "Permalink") + +如果内容与读者相关,则包括任何媒体类型/来源. 您可以自由地包含或链接演示文稿,图表,视频等; 不管它最初是为谁创作的,如果对我们的听众有帮助,我们都可以将其包括在内. + +* 如果使用的图像具有单独的源文件(例如,矢量或图表格式),则将该图像链接到源文件,以便任何人都可以重用或更新它. +* 除非从引用来源中引用有限的内容,否则请勿复制和粘贴其他来源的内容. 通常,最好用您自己的话语重述相关信息或链接到其他来源. + +### No special types[](#no-special-types "Permalink") + +在软件行业中,最佳实践是组织不同类型的文档. 例如, [Divio 建议](https://www.divio.com/blog/documentation/) : + +1. Tutorials +2. 入门指南 +3. Explanation +4. 参考(例如,词汇表) + +在 GitLab,我们的月度版本中有太多产品更改,以至于我们无法承受持续更新多种类型的信息的负担. 如果我们有多种类型,则信息将过时. 因此,我们只有一个文档[模板](structure.html) . + +我们目前不区分特定的文档类型,尽管一旦文档达到成熟度和质量的未来阶段,我们可以重新考虑此政策. 如果您正在阅读此书,那么尽管我们不断进行改进,但仍未达到这一点. + +### Link instead of summarize[](#link-instead-of-summarize "Permalink") + +有诱惑力将信息汇总在另一页上. 这将导致信息存在于两个地方. 相反,链接到 SSOT 并解释为什么使用信息很重要. + +### Organize by topic, not by type[](#organize-by-topic-not-by-type "Permalink") + +除了顶级受众类型的文件夹(例如, `administration` )之外,我们还按主题而不是按类型组织内容,因此可以在主题的单一来源(SSOT)部分中尽可能轻松地找到内容物. + +例如,不要创建相似媒体类型的分组. 例如: + +* Glossaries. +* FAQs. +* 所有文章或视频的集合. + +按类型对内容进行这种分组使得难以浏览所需信息,并且难以维护最新内容. 而是按主题组织内容(例如,与 CI 相关的所有内容都放在一起),并在任何相关内容之间进行交叉链接. + +### Docs-first methodology[](#docs-first-methodology "Permalink") + +我们采用**文档优先的方法,**以帮助确保文档保持完整且受信任的资源,并使有关 GitLab 使用的交流更加有效. + +* 如果文档中存在问题的答案,请共享文档链接,而不要改写信息. +* 当您遇到 GitLab 文档中没有的新信息时(例如,在处理支持案例或测试功能时),第一步应该是创建合并请求(MR),以将该信息添加到文档中. 然后,您可以共享 MR 以便传达此信息. + +如上所述,对将来的 GitLab 使用或故障排除有用的新信息不应直接写在论坛或其他消息系统中,而应添加到文档 MR 中,然后再进行引用. 请注意,除其他任何文档更改外,您还可以: + +* 如果不存在,请在文档中添加" [疑难解答"部分](#troubleshooting) . +* 取消注释并使用占位符疑难解答部分,该部分包含在我们的[文档模板中](structure.html#template-for-new-docs) (如果存在). + +我们向文档自如地添加有用信息的次数越多,文档就越会被用来(更成功)有效地完成任务和解决问题. + +如果您在考虑,创作或编辑文档时遇到问题,请提及适用于[DevOps 阶段](https://about.gitlab.com/handbook/product/product-categories/#devops-stages)的编写者,以`#docs`或 GitLab 中的 Slack 的技术写作团队提出. 否则,请尽力而为. 它并不一定是完美的. 团队很乐意审查和改进您的内容. 在开始您的第一个文档 MR 之前,请查阅[文档指南](index.html) . + +具有与文档不同的任何形式的知识库都将违反文档优先方法,因为其内容会与文档重叠. + +## Markdown[](#markdown "Permalink") + +所有的 GitLab 文档都是使用[Markdown](https://en.wikipedia.org/wiki/Markdown)编写的. + +[文档网站](https://s0docs0gitlab0com.icopy.site)使用 GitLab Kramdown 作为 Markdown 渲染引擎. 有关完整的 Kramdown 参考,请参阅《 [GitLab Markdown Kramdown 指南》](https://about.gitlab.com/handbook/markdown-guide/) . + +[`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown) Ruby gem 将来将支持所有[GFM 标记](../../user/markdown.html) . 也就是说,所有标记都支持在 GitLab 应用程序本身中显示. 目前,请按照链接的样式指南中的规则使用常规的 Markdown 标记. + +请注意,特定于 Kramdown 的标记(例如`{:.class}` )不会在[`/help`](index.html#gitlab-help)下的 GitLab 实例上正确呈现. + +### HTML in Markdown[](#html-in-markdown "Permalink") + +硬编码的 HTML 是有效的,尽管在使用`/help`时不建议使用. 只要允许 HTML,就可以: + +* Markdown 中没有等效的标记. +* 高级表是必需的. +* 需要特殊的样式. +* 由技术作家审查和批准. + +### Markdown Rules[](#markdown-rules "Permalink") + +GitLab 通过使用[markdownlint](index.html#markdownlint) [测试文档更改](index.html#testing)来确保所有文档中使用的 Markdown 是一致的,并且易于查看和维护. 当任何文档的 Markdown 格式存在问题时,此棉绒测试将失败,该问题可能导致页面在 GitLab 中无法正确呈现. 当文档使用非标准 Markdown(可以正确显示,但不是 GitLab 文档的当前标准)时,它也会失败. + +#### Markdown rule `MD044/proper-names` (capitalization)[](#markdown-rule-md044proper-names-capitalization "Permalink") + +可能引起混乱的规则是`MD044/proper-names` ,因为可能无法立即弄清是什么导致 markdownlint 失败或如何纠正失败. 此规则检查每个项目的`.markdownlint.json`文件中列出的已知单词的列表,以验证是否正确使用了大写字母和反引号. 反引号中的单词将被 markdownlint 忽略. + +通常,产品名称应紧跟产品,协议等正式名称的大写字母. 请参阅[`.markdownlint.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.markdownlint.json)以获取有关 GitLab 文档中经过适当大写测试的单词. + +如果使用不正确的大小写,则某些示例将失败: + +* MinIO(需要资本`IO` ) +* NGINX(需要所有资金) +* runit(需要小写`r` ) + +此外,反引号中必须包含命令,参数,值,文件名等. 例如: + +* "在您的`.gitlab.yml`更改`needs`关键字……" + * `needs`是一个参数,而`.gitlab.yml`是一个文件,因此两者都需要反引号. 此外, `.gitlab.yml`没有`.gitlab.yml` G 或 L,它将使 markdownlint 失败而没有反引号. +* “Run `git clone` to clone a Git repository…” + * `git clone`是命令,因此它必须是小写字母,而 Git 是乘积,因此它必须具有大写字母 G. + +## Structure[](#structure "Permalink") + +因为我们希望文档成为 SSOT,所以我们应该[按主题(而不是类型)进行组织](#organize-by-topic-not-by-type) . + +### Folder structure overview[](#folder-structure-overview "Permalink") + +该文档由顶级受众文件夹[`user`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/user) , [`administration`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/administration)和[`development`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/development) (贡献)文件夹分开. + +Beyond that, we primarily follow the structure of the GitLab user interface or API. + +我们的目标是要建立一个清晰的层次结构,并包含有意义的 URL,例如`docs.gitlab.com/user/project/merge_requests/` . 使用这种模式,您可以立即知道您正在导航到有关 Project 功能的用户相关文档; 特别是关于合并请求. 我们网站的路径与我们存储库的路径匹配,因此清晰的结构还使文档更易于更新. + +下表显示了什么样的文档. + +| Directory | 这里属于什么 | +| --- | --- | +| `doc/user/` | 与用户相关的文档. 可以在 GitLab UI 中完成的所有操作都在这里进行,包括使用`/admin`界面. | +| `doc/administration/` | 要求用户有权访问安装了 GitLab 的服务器的文档. 可以通过 GitLab 界面访问的管理设置位于`doc/user/admin_area/` . | +| `doc/api/` | API 相关文档. | +| `doc/development/` | 与 GitLab 开发相关的文档,无论是贡献代码还是文档. 相关的流程和样式指南应该在此处. | +| `doc/legal/` | 有关对 GitLab 进行贡献的法律文件. | +| `doc/install/` | 包含有关安装 GitLab 的说明. | +| `doc/update/` | 包含有关更新 GitLab 的说明. | +| `doc/topics/` | 每个主题的索引( `doc/topics/topic-name/index.md` ):该主题的所有资源. | + +### Work with directories and files[](#work-with-directories-and-files "Permalink") + +1. 创建新目录时,请始终以`index.md`文件开头. 不要使用其他文件名, **也不要**创建`README.md`文件. +2. **请勿**在文件名,目录名,分支名和任何会生成路径的文件中使用特殊字符和空格或大写字母. +3. 创建新文档时,如果名称中包含多个单词,请确保使用下划线而不是空格或破折号( `-` ). 例如,正确的命名应为`import_projects_from_github.md` . 相同的规则适用于图像. +4. 对于图像文件,请勿超过 100KB. +5. 不要将视频文件上传到产品存储库. [链接或嵌入视频](#videos) . +6. 有四个主要目录, `user` , `administration` , `api`和`development` . +7. `doc/user/`目录具有五个主要子目录: `project/` , `group/` , `profile/` , `dashboard/`和`admin_area/` . + 1. `doc/user/project/`应包含所有与项目相关的文档. + 2. `doc/user/group/`应包含所有与组有关的文档. + 3. `doc/user/profile/`应包含所有与个人资料相关的文档. 您在`/profile`下导航的每个页面都应该有其自己的文档,例如`account.md` , `applications.md`或`emails.md` . + 4. `doc/user/dashboard/`应包含所有与仪表板相关的文档. + 5. `doc/user/admin_area/`应该包含所有与管理员相关的文档,这些文档描述了通过访问 GitLab 的管理界面可以实现的目的( *不要与需要服务器访问权限的`doc/administration`混淆* ). + 1. `/admin/application_settings/`下的每个类别都应有自己的文档,位于`doc/user/admin_area/settings/` . 例如," **可见性和访问控制"**类别应具有位于`doc/user/admin_area/settings/visibility_and_access_controls.md` . +8. `doc/topics/`目录包含与主题相关的技术内容. 必要时创建`doc/topics/topic-name/subtopic-name/index.md` . 应放置与用户和管理员相关的常规文档. +9. 目录`/workflow/` , `/university/`和`/articles/`已被**弃用** ,并且大多数文档已通过较小的迭代移动到了正确的位置. + +如果您不确定文档或内容添加应该放在哪里,那么这不会阻止您创作和贡献. 您可以根据自己的最佳判断,然后要求 MR 的审阅者确认您的决定,和/或在此过程的任何阶段询问技术作家. 技术写作团队将审查所有文档更改,无论如何,并且如果有合适的位置,可以移动内容. + +### Avoid duplication[](#avoid-duplication "Permalink") + +不要在多个地方包含相同的信息. [链接到 SSOT.](#link-instead-of-summarize) + +### References across documents[](#references-across-documents "Permalink") + +* 给每个文件夹一个 index.md 页面,该页面介绍该主题,介绍其中的页面,并链接到其中的页面(包括任何下一级子路径的索引页面). +* 为确保可发现性,请确保每个新文档或重命名的文档都从其更高级别的索引页面和其他相关页面链接. +* 当引用其他 GitLab 产品和功能时,至少在第一次提及时,链接到它们各自的文档. +* 当引用第三方产品或技术时,请链接到其外部站点,文档和资源. + +### Structure within documents[](#structure-within-documents "Permalink") + +* 包括[结构和模板](structure.html)页面上所述的所有适用小节. +* Structure content in alphabetical order in tables, lists, and so on, unless there is a logical reason not to (for example, when mirroring the UI or an otherwise ordered sequence). + +## Language[](#language "Permalink") + +GitLab 文档应清晰易懂. + +* 清楚,简明并遵守文档的目标. +* 用美国英语和美国语法书写. (在[`British.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/British.yml)测试.) +* 使用包容性语言. + +### Point of view[](#point-of-view "Permalink") + +在大多数情况下,使用第二人称(您自己)的观点是适当的,因为它友好且易于理解. (在[`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml)测试.) + +### Capitalization[](#capitalization "Permalink") + +* 在 GitLab 中大写" G"和" L". +* 句子大小写用于: + * 标题. + * 标签. + * 菜单项. + * 纽扣. + * 标题. 除非标题中提及产品功能,否则请勿在标题中大写其他单词. 例如: + * 大写"问题"在`## What you can do with GitLab Issues` ,但在`## Closing multiple issues`不可接受. +* 引用时使用标题大小写: + * [GitLab 功能](https://about.gitlab.com/features/) . 例如,发行板,地缘和亚军. + * GitLab [产品层](https://about.gitlab.com/pricing/) . 例如,GitLab Core 和 GitLab Ultimate. (在[`BadgeCapitalization.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/BadgeCapitalization.yml)测试.) + * 第三方产品. 例如,Prometheus,Kubernetes 和 Git. + * 方法或方法论. 例如,持续集成,持续部署,Scrum 和敏捷. (在[`.markdownlint.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.markdownlint.json)测试.) + + **注意:**某些功能也是对象. 例如," GitLab 的合并请求支持 X"和"为 Z 创建新的合并请求". + +### Language to avoid[](#language-to-avoid "Permalink") + +创建文档时,请限制或避免使用以下动词时态,单词和短语: + +* 避免行话. +* 避免使用不常见的单词. +* 不要以第一人称单数形式书写. (在[`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml)测试.) + * 代替"我"或"我",而使用"我们","您","我们"或"一个". + * 在可能的情况下,通过写第二人称(" you"或命令式)来保持用户的注意力. +* 不要过度使用" that". 在许多情况下,您可以从句子中删除" that"并提高可读性. +* 避免使用将来时: + * 代替"在执行此命令后,GitLab 将显示结果",而应使用"在执行此命令后,GitLab 显示结果". + * 仅在将来某个时间实际发生动作或结果时,才使用将来时来表达. +* 不要使用斜杠将不同的单词组合在一起,也不要用"或"代替: + * 代替"和/或",可以考虑使用"或",或使用其他明智的结构. + * 其他示例包括"克隆/获取",作者/受让人和"命名空间/存储库名称". 以适当的方式拆分任何此类实例. + * 该规则的例外情况包括公认的技术术语,例如 CI / CD 和 TCP / IP. +* We discourage use of Latin abbreviations, such as “e.g.,” “i.e.,” or “etc.,” as even native users of English might misunderstand them. (Tested in [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml).) + + * 代替"即",使用"即". + * 代替"例如",使用"例如","例如","例如"或"喜欢". + * 代替"等",可以使用"依此类推",也可以考虑对其进行编辑,因为它可能含糊不清. +* 在谈论产品或其功能时,请避免*当前*使用该词. 该文档按原样描述了该产品,而不是将来的某个不确定点. +* 避免在增加 GitLab 为其他用户的性能时使用*可扩展性*一词. 在其他情况下,可以使用" *缩放"*或" *缩放"*一词,但对于其他用户而言,提高 GitLab 性能的参考应将读者引导至 GitLab [参考架构](../../administration/reference_architectures/index.html)页面. +* 避免使用所有形式的短语" *高可用性"*和" *HA"* ,而是将读者引导至 GitLab [参考体系结构,](../../administration/reference_architectures/index.html)以获取有关配置 GitLab 使其随着时间的推移具有更多用户所需的性能的信息. +* 不要使用亵渎或 ob 亵. 这样做可能会对其他用户和贡献者产生负面影响,这与 GitLab 的" [多样性","包容性"和"归属"](https://about.gitlab.com/handbook/values/#diversity-inclusion)的价值背道而驰. +* 避免使用对[种族不敏感的术语或短语](https://www.marketplace.org/2020/06/17/tech-companies-update-language-to-avoid-offensive-terms/) . 例如: + * 将*主*数据库和*辅助*数据库用于数据库和服务器关系. + * 使用*allowlist*和*denylist*来描述访问控制列表. + +### Word usage clarifications[](#word-usage-clarifications "Permalink") + +* 不要互换使用" may"和" might": + * 使用"可能"表示发生某事的可能性. "如果跳过此步骤,则导入过程可能会失败." + * 使用"可能"表示允许某人做某事,或者考虑使用"可以". "您可以在此屏幕上选择一个选项." 或者,"您可以在此屏幕上选择任一选项." + +### Contractions[](#contractions "Permalink") + +* Use common contractions when it helps create a friendly and informal tone, especially in tutorials, instructional documentation, and [UIs](https://design.gitlab.com/content/punctuation/#contractions). (Tested in [`Contractions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Contractions.yml).) + + | Do | Don’t | + | --- | --- | + | it’s | 它是 | + | can’t | cannot | + | wouldn’t | 不会 | + | you’re | 你是 | + | you’ve | 你有 | + | haven’t | 没有 | + | don’t | 不要 | + | we’re | 我们是 | + | that’s | 那是 | + | won’t | 将不会 | + +* 避免少见的宫缩: + + | Do | Don’t | + | --- | --- | + | 他会 | he’d | + | 它会 | it’ll | + | 应该有 | should’ve | + | 那里会 | there’d | + +* 不要使用带有专有名词和动词的缩略词. 例如: + + | Do | Don’t | + | --- | --- | + | GitLab 正在创建 X | manbetx 客户端打不开创建 X | + +* 当您需要强调负面情绪时,不要使用收缩. 例如: + + | Do | Don’t | + | --- | --- | + | **不要**为 Y 安装 X | **不要**将 X 与 Y 一起安装 | + +* 不要在参考文档中使用收缩. 例如: + + | Do | Don’t | + | --- | --- | + | **不要**设置限制大于 1000 | **请勿**将限制设置为大于 1000 | + | 对于`parameter1` ,默认值为 10 | 对于`parameter1` ,默认值为 10 | + +* 避免错误消息中出现收缩. 例子: + + | Do | Don’t | + | --- | --- | + | 不允许对本地主机的请求 | 不允许对本地主机的请求 | + | 指定的 URL 不能使用 | 指定的网址无法使用 | + +## Text[](#text "Permalink") + +* [Write in Markdown](#markdown). +* 分隔长行(最好最多 100 个字符)可以更轻松地提供有关小块文本的反馈. +* 在新段落中插入一个空行. +* 在不同的标记之间插入一个空行(例如,在每个段落,标题,列表等之后). 例: + + ``` + ## Header + + Paragraph. + - List item 1 + - List item 2 + ``` + +### Emphasis[](#emphasis "Permalink") + +* 使用双星号( `**` )将单词或文本标记为粗体( `**bold**` ). +* 下划线( `_` )用于斜体( `_italic_` )文本. +* 块引用使用大于( `>` ). + +### Punctuation[](#punctuation "Permalink") + +检查下表中 GitLab 文档的常规标点规则. 检查以下[列表的](#lists)特定标点规则. + +| Rule | Example | +| --- | --- | +| 总是以句号结束完整的句子. | *有关完整概述,请通读本文档.* | +| 在开始新句子时,请始终在句点之后添加空格. | *有关完整的概述,请查看此文档. 有关其他参考,请查阅本指南.* | +| 不要使用双空格. (在[`SentenceSpacing.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SentenceSpacing.yml)测试.) | — | +| 不要使用制表符进行缩进. 请改用空格. 您可以将代码编辑器配置为在按 Tab 键时输出空格而不是制表符. | — | +| 在列表中最后一个"和/或"之前使用连续逗号("牛津逗号"). (在[`OxfordComma.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/OxfordComma.yml)测试.) | *您可以创建新问题,合并请求和里程碑.* | +| 在句子中使用破折号之前和之后,请始终添加空格(例如,用于替换逗号). | *您应该尝试这样做-还是不可以.* | +| 总是在冒号后面使用小写字母. | *相关问题:一种在问题之间建立关系的方法.* | + +### Placeholder text[](#placeholder-text "Permalink") + +在示例中,编写者通常会提供除特定于阅读者的值之外完整的命令或配置. + +在这些情况下,使用[`<`和`>`](https://en.wikipedia.org/wiki/Usage_message#Pattern)指出读者必须用自己的值替换文本的位置. + +例如: + +``` +cp +``` + +## Lists[](#lists "Permalink") + +* 始终使用大写字母开头列表项,除非它们是反引号或类似的参数或命令. +* 始终在列表前后留空行. +* 以空格(不是制表符)开头的行表示[嵌套的子项](#nesting-inside-a-list-item) . + +### Ordered vs. unordered lists[](#ordered-vs-unordered-lists "Permalink") + +仅当其项目描述要遵循的步骤序列时,才使用有序列表. + +Do: + +``` +These are the steps to do something: + 1. First, do the first step. +1. Then, do the next step. +1. Finally, do the last step. +``` + +Don’t: + +``` +This is a list of available features: + 1. Feature 1 +1. Feature 2 +1. Feature 3 +``` + +### Markup[](#markup "Permalink") + +* 对于无序列表,请使用破折号( `-` )代替星号( `*` ). +* 在有序列表中的每个项目之前添加前缀`1.` .. 呈现后,列表项将自动以顺序编号显示. + +### Punctuation[](#punctuation-1 "Permalink") + +* 不要在列表项的末尾添加逗号( `,` )或分号( `;` ). +* 如果项目由完整的句子组成,则仅在项目的末尾添加句号. [完整句子](https://www2.le.ac.uk/offices/ld/all-resources/writing/grammar/grammar-guides/sentence)的[定义](https://www2.le.ac.uk/offices/ld/all-resources/writing/grammar/grammar-guides/sentence)是: *"完整句子总是包含一个动词,表达一个完整的构想,并且在单独存在时有意义"* . +* Be consistent throughout the list: if the majority of the items do not end in a period, do not end any of the items in a period, even if they consist of a complete sentence. The opposite is also valid: if the majority of the items end with a period, end all with a period. +* 从解释性文字分隔列表项用冒号( `:` ). 例如: + + ``` + The list is as follows: + - First item: this explains the first item. + - Second item: this explains the second item. + ``` + +**Examples:** + +Do: + +* 第一个清单项目 +* 第二个清单项目 +* 第三清单项目 + +Don’t: + +* 第一个清单项目 +* 第二个清单项目 +* 第三列表项. + +Do: + +* 假设这是一个完整的句子. +* 假设这也是一个完整的句子. +* 句子不完整. + +请勿(各种句号的使用;多数规则): + +* 假设这是一个完整的句子. +* 假设这也是一个完整的句子. +* 句子不完整 + +### Nesting inside a list item[](#nesting-inside-a-list-item "Permalink") + +可以将项目嵌套在列表项目下,以便它们呈现与列表项目相同的缩进. 这可以通过以下方式完成: + +* [Code blocks](#code-blocks) +* [Blockquotes](#blockquotes) +* [Alert boxes](#alert-boxes) +* [Images](#images) + +嵌套在列表中的项目应始终与列表项目的第一个字符对齐. 在无序列表(使用`-` )中,这表示每个缩进级别有两个空格: + +``` +- Unordered list item 1 + + A line nested using 2 spaces to align with the `U` above. + - Unordered list item 2 + > A quote block that will nest + > inside list item 2. + - Unordered list item 3 + + ```plaintext + a codeblock that will next inside list item 3 + ``` + - Unordered list item 4 + + ![an image that will nest inside list item 4](image.png) +``` + +对于有序列表,每个缩进级别使用三个空格: + +``` +1. Ordered list item 1 + + A line nested using 3 spaces to align with the `O` above. + 1. Ordered list item 2 + > A quote block that will nest + > inside list item 2. + 1. Ordered list item 3 + + ```plaintext + a codeblock that will next inside list item 3 + ``` + 1. Ordered list item 4 + + ![an image that will nest inside list item 4](image.png) +``` + +您可以使用与上述相同的规则将完整列表嵌套在其他列表中. 如果您希望混合类型,也可以,只要您不混合同一级别的项目即可: + +``` +1. Ordered list item one. +1. Ordered list item two. + - Nested unordered list item one. + - Nested unordered list item two. +1. Ordered list item three. + - Unordered list item one. +- Unordered list item two. + 1. Nested ordered list item one. + 1. Nested ordered list item two. +- Unordered list item three. +``` + +## Tables[](#tables "Permalink") + +应该使用表格以简单的方式描述复杂的信息. 请注意,在许多情况下,无序列表足以描述一个项目列表,而每个项目只有一个简单的描述. 但是,如果您拥有最能用矩阵描述的数据,则表是使用的最佳选择. + +### Creation guidelines[](#creation-guidelines "Permalink") + +由于可访问性和可扫描性要求,表中不应包含任何空白单元格. 如果某个单元格没有其他有意义的值,请考虑输入*N / A* ("不适用")或*不输入* . + +为了使表更易于维护,请考虑在列宽上添加额外的空格以使其一致. 例如: + +``` +| App name | Description | Requirements | +|:---------|:---------------------|:---------------| +| App 1 | Description text 1\. | Requirements 1 | +| App 2 | Description text 2\. | None | +``` + +考虑在编辑器中安装插件或扩展程序以格式化表格: + +* 用于 Visual Studio 代码的[Markdown 表修饰符](https://marketplace.visualstudio.com/items?itemName=darkriszty.markdown-table-prettify) +* 升华文字的[Markdown 表格式化](https://packagecontrol.io/packages/Markdown Table Formatter)程序 +* 用于 Atom 的[Markdown 表格式化](https://atom.io/packages/markdown-table-formatter)程序 + +### Feature tables[](#feature-tables "Permalink") + +创建功能列表时(例如," [权限"](../../user/permissions.html#project-members-permissions)页面上的某些角色是否可以使用功能),请使用以下短语(基于 SVG 图标): + +* *No*: No +* *Yes*: Yes + +## Quotes[](#quotes "Permalink") + +仅适用于 Markdown 内容,不适用于优先事项条目: + +* 标准引号:双引号( `"` ).例如:"这用双引号引起来". +* 用引号引起来:双引号( `"` )包裹单引号( `'` ).例如:"我正在用引号引起来". + +有关其他标点规则,请参考[GitLab UX 指南](https://design.gitlab.com/content/punctuation/) . + +## Headings[](#headings "Permalink") + +* 通过在每个文档的开头添加`#` (在使用 Markdown 时), **仅**在每个文档中添加**一个 H1** . `h1`将是文档`` . +* 从`h2` ( `##` )开始,并遵循`h2` > `h3` > `h4` > `h5` > `h6`的顺序. 切勿跳过层次结构级别,例如`h2` > `h4` +* 避免将数字放在标题中. 数字移动,因此文档锚链接也移动,最终导致死链接. 如果您认为在标题中添加数字非常有必要,请确保至少与"合并请求"中的某人进行讨论. +* [避免](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/84)在标题中[使用符号和特殊字符](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/84) . 只要有可能,它们应为纯文本和简短文本. +* 避免添加显示短暂状态的内容. 例如,如果某个功能被认为是 Beta 或试验性功能,请将此信息放在注释中而不是标题中. +* 引入新文档时,请注意标题在语法和语法上都是正确的. 提及[指定的技术作家(TW)](https://about.gitlab.com/handbook/product/product-categories/)以进行审查. 这是为了确保没有错误标题的文档将在未经审核的情况下生效,从而防止在纠正时出现无效链接和重定向问题. +* 在标题前后只留一个空白行. +* 不要在标题中使用链接. +* 根据功能所属的级别添加相应的[产品徽章](#product-badges) . +* 我们的 docs 网站搜索引擎会区分标题和副标题中使用的单词的优先级. 如[标题标题](#heading-titles)部分所示,使标题标题清晰,描述性且完整,以帮助用户找到正确的示例. +* 有关将标题[大写](#capitalization)的指南,请参见[大写](#capitalization) . + +### Heading titles[](#heading-titles "Permalink") + +保持标题清晰,直接. 使每个单词都重要. 为了适应搜索引擎优化(SEO),请尽可能使用命令. + +| Do | Don’t | +| --- | --- | +| Configure GDK | Configuring GDK | +| GitLab 发布和维护政策 | 本节介绍 GitLab 的发布和维护政策 | +| 向后移植到较旧的版本 | 向后移植到较旧的版本 | +| GitLab 页面示例 | Examples | + +有关大写标题的准则,请参见[大写](#capitalization)部分. + +**注意:**如果更改现有标题,请当心. 任何此类更改可能不仅影响页面内的[链接](#anchor-links) ,而且还可能影响来自 GitLab 本身的链接以及指向 GitLab 文档的外部链接. + +### Anchor links[](#anchor-links "Permalink") + +渲染时,标题会自动生成锚链接. `## This is an example`生成锚点`#this-is-an-example` . + +请记住,GitLab UI 链接到大量文档以及相应的锚链接,以将用户带到正确的位置. 因此,当您更改标题时,请在`doc/*` , `app/views/*`和`ee/app/views/*`搜索旧的锚点,以确保您不会破坏从其他文档或 GitLab UI 链接的锚点. 如果找到旧的锚,请确保将其替换为新的锚. + +Important: + +* 除非需要链接到文档的特定部分,否则请避免将文档交到标题. 如果方向改变,这将避免将来破坏锚. +* 如果可能,请避免更改标题,因为它们不仅是内部链接的. 互联网上有指向 GitLab 文档的各种链接,例如教程,演示文稿,StackOverflow 帖子和其他资源. +* 不要链接到`h1`标题. + +需要注意的是,与 Kramdown,也可以自定义 ID 添加到与降价的标记 HTML 元素,但他们**没有**在 GitLab 的工作`/help` . 因此,除非另行通知,否则不要使用此选项. + +## Links[](#links "Permalink") + +链接在 GitLab 文档中很重要. 它们使您可以[链接而不是进行汇总,](#link-instead-of-summarize)以帮助在 GitLab 文档中保留[SSoT](#why-a-single-source-of-truth) . + +我们提供以下类别的链接指南: + +* 如何设置标题的[锚链接](#anchor-links) . +* 如何设置[标准](#basic-link-criteria)配置的链接. +* [链接到`help`](../documentation/index.html#linking-to-help)页面时要设置的内容. +* 如何设置[指向内部文档的链接以](#links-to-internal-documentation)进行交叉引用. +* 如何建立[指向](#links-to-external-documentation)权威来源的[外部文档的链接](#links-to-external-documentation) . +* 何时使用[需要权限的链接](#links-requiring-permissions) . +* 如何设置[视频链接](#link-to-video) . +* 如何在[版本文本中包含链接](#text-for-documentation-requiring-version-text) . +* 如何[链接到特定的代码行](#link-to-specific-lines-of-code) + +### Basic link criteria[](#basic-link-criteria "Permalink") + +* 使用内联链接 Markdown 标记`[Text](https://example.com)` . 它更易于阅读,查看和维护. **不要**使用`[Text][identifier]` . + +* 使用[有意义的锚文本](https://www.futurehosting.com/blog/links-should-have-meaningful-anchor-text-heres-why/) . 例如, `Read more about GitLab Issue Boards [here](LINK)`编写类似" `Read more about GitLab Issue Boards [here](LINK)` ,而不是撰写`Read more about [GitLab Issue Boards](LINK)` . + +### Links to internal documentation[](#links-to-internal-documentation "Permalink") + +**注意:** *内部*是指同一项目中的文档. 链接到单独项目中的文档时(例如,从 GitLab 文档链接到 Omnibus 文档),必须使用绝对 URL. + +请勿使用`https://docs.gitlab.com/ee/index.html`类的绝对 URL 交叉链接到同一项目中的其他文档. 使用指向文件的相对链接,例如`../index.md` . (在呈现网站时将这些转换为 HTML.) + +相对链接使交叉链接可以正常工作: + +* 在 Review Apps,本地预览和`/help` . +* 在本地处理文档时,您可以在此过程中尽早验证它们是否有效. +* 浏览各自存储库中的文档文件时,可以在 GitLab UI 中使用. 例如,显示在`https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/README.md`的链接. + +链接到内部文档: + +* 使用相对链接指向同一存储库中的 Markdown 文件. +* 不要使用绝对 URL 或`docs.gitlab.com` URL. +* 使用`../`导航到更高级别的目录. +* 不要相对于根链接. 例如,/ `/ee/user/gitlab_com/index.md` . + + Don’t: + + * `https://docs.gitlab.com/ee/administration/geo/replication/troubleshooting.html` + * `/ee/administration/geo/replication/troubleshooting.md` + + Do: `../../geo/replication/troubleshooting.md` + +* 始终在链接末尾添加文件名`file.md` ,扩展名为`.md`而不是`.html` . + + Don’t: + + * `../../merge_requests/` + * `../../issues/tags.html` + * `../../issues/tags.html#stages` + + Do: + + * `../../merge_requests/index.md` + * `../../issues/tags.md` + * `../../issues/tags.md#stages` + +**注意:** GitLab 的[`/help`](index.html#gitlab-help)部分必须使用 Markdown 扩展名. + +### Links to external documentation[](#links-to-external-documentation "Permalink") + +描述与外部软件的交互时,包括指向外部文档的链接通常会很有帮助. 如果可能,请确保您链接到**权威**来源. 例如,如果您要描述 Microsoft Active Directory 中的功能,请包括指向 Microsoft 官方文档的链接. + +### Links requiring permissions[](#links-requiring-permissions "Permalink") + +不要直接链接到: + +* [Confidential issues](../../user/project/issues/confidential_issues.html). +* 需要[特殊权限](../../user/permissions.html)才能查看的项目功能. + +这些将因以下原因而失败: + +* 那些没有足够权限的人. +* 自动链接检查器. + +Instead: + +* 为了减少混乱,请在文本中提及以下信息之一: + * 包含在一个机密问题中. + * 需要项目的特殊权限才能查看. +* 在反勾号( ``` )中提供一个链接,以便那些有权访问该问题的人可以轻松导航到该问题. + +Example: + +``` +For more information, see the [confidential issue](../../user/project/issues/confidential_issues.md) `https://gitlab.com/gitlab-org/gitlab-foss/-/issues/<issue_number>`. +``` + +### Link to specific lines of code[](#link-to-specific-lines-of-code "Permalink") + +链接到文件中的特定行时,请链接到提交而不是分支. 代码行随时间变化,因此,使用 commit 链接链接到一行可确保用户落在您所指的行上. 在查看项目中的文件时,可以使用" **永久链接"**按钮,它可以轻松生成指向给定文件的最新提交的链接. + +* **Do:** `[link to line 3](https://gitlab.com/gitlab-org/gitlab/-/blob/11f17c56d8b7f0b752562d78a4298a3a95b5ce66/.gitlab/issue_templates/Feature%20proposal.md#L3)` +* **Don’t:** `[link to line 3](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal.md#L3).` + +如果由于进一步的提交,该链接的表达式不再在文件的该行中,则您仍然可以在文件中搜索该查询. 在这种情况下,请更新文档以确保其链接到文件的最新版本. + +## Navigation[](#navigation "Permalink") + +指示通过 UI 导航的步骤: + +* 使用界面中显示的确切字词,包括所有大写字母. +* 使用粗体文本显示导航项,并使用字符"大于"( `>` )作为分隔符(例如, `Navigate to your project's **Settings > CI/CD**` ). +* 如果有任何可展开的菜单,请确保提及用户需要展开选项卡以找到您要引用的设置(例如, `Navigate to your project's **Settings > CI/CD** and expand **General pipelines**` ). + +## Images[](#images "Permalink") + +图像(包括屏幕截图)可以帮助读者更好地理解概念. 但是,它们可能难以维护,应谨慎使用. + +在文档中包括图片之前,请确保它为读者提供了价值. + +### Capture the image[](#capture-the-image "Permalink") + +使用图像可以帮助读者了解它们在过程中的位置,或与应用程序进行交互的方式. + +截屏时: + +* *捕获页面中最相关的区域.* 不要包含不必要的空白或页面区域,以免说明您的观点. 另外,如果不需要,不要包括整个页面,而且还要确保图像包含足够的信息以允许用户确定事物的位置. +* *始终如一.* 找到适合您的浏览器窗口大小,该窗口大小还会显示产品的所有区域,包括左侧导航栏(通常> 1200 像素宽). 为了保持一致,请通过安装用于将窗口设置为特定大小的浏览器扩展程序(例如,用于 Google Chrome 的[Window Resizer](https://chrome.google.com/webstore/detail/window-resizer/kkelicaakdanhinjdeammmilcgefonfh/related?hl=en) ),将此浏览器窗口大小用于屏幕截图. + +### Save the image[](#save-the-image "Permalink") + +* 用一个小写的文件名保存该图像,该文件名描述了图像中的功能或概念. 如果该图像属于 GitLab 界面,则根据以下格式将 GitLab 版本附加到文件名: `image_name_vX_Y.png` . 例如,对于从 GitLab 11.1 的管道页面中截取的屏幕截图,有效名称为`pipelines_v11_1.png` . 如果要添加的插图不包含用户界面的各个部分,请添加与添加图像的版本相对应的版本号; 对于添加到 11.1 里程碑中的 MR,插图的有效名称是`devops_diagram_v11_1.png` . +* 将图像放置在名为`img/`的单独目录中,该目录与您正在使用的`.md`文档所在的目录相同. +* 考虑使用 PNG 图像而不是 JPEG. +* [Compress all PNG images](#compress-images). +* 使用[https://ezgif.com/optimize](https://ezgif.com/optimize)或类似工具压缩 gif. +* 应该使用图像(仅在必要时使用)来*说明*过程说明,而不是*替代*过程. +* 图片大小上限:100KB(含 Gif). +* 另请参阅如何链接和嵌入[视频](#videos)以说明文档. + +### Add the image link to content[](#add-the-image-link-to-content "Permalink") + +用于在文档中包含图像的 Markdown 代码为: `![Image description which will be the alt tag](img/document_image_title_vX_Y.png)` + +图像描述是 docs 网站上渲染图像的替代文本. 对于可访问性和 SEO,请使用以下[描述](https://webaim.org/techniques/alttext/) : + +* 准确,简洁且独特. +* 请勿使用*…的图像*或*…的* *图形*来描述图像. + +另外,如果标题紧随图像之后,请确保在图像和标题之间添加三个破折号( `---` ). + +### Remove image shadow[](#remove-image-shadow "Permalink") + +默认情况下,在[GitLab 文档站点](https://s0docs0gitlab0com.icopy.site)上显示的所有图像都有一个阴影框. 要删除框阴影,请使用直接应用于 HTML `img`标签的图像类`.image-noshadow` : + +``` +<img src="path/to/image.jpg" alt="Alt text (required)" class="image-noshadow"> +``` + +### Compress images[](#compress-images "Permalink") + +您应该始终压缩添加到文档中的任何新图像. 一种已知的工具是[`pngquant`](https://pngquant.org/) ,它是跨平台和开源的. 通过访问官方网站并按照您的操作系统说明进行安装. + +GitLab 有一个[Rake 任务](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/tasks/pngquant.rake) ,可用于自动执行该过程. 在本地`https://gitlab.com/gitlab-org/gitlab`副本的根目录中,在终端中运行: + +* 压缩之前,如果需要,请检查是否已压缩所有文档 PNG 图像: + + ``` + bundle exec rake pngquant:lint + ``` + +* 使用`pngquant`压缩所有文档 PNG 图像: + + ``` + bundle exec rake pngquant:compress + ``` + +唯一需要注意的是,该任务将在`doc/`下的所有图像上运行,而不仅仅是您可能包含在合并请求中的图像. 在这种情况下,您可以运行 compress 任务,仅提交与合并请求相关的图像. + +## Videos[](#videos "Permalink") + +强烈建议将 GitLab 的现有 YouTube 视频教程添加到文档中,除非该视频已过时. 视频不应取代文档,而应补充或说明文档. 如果视频中的内容是功能及其关键用例的基础,但是文档中没有对此进行充分介绍,请将此详细信息添加到文档文本中,或者创建问题以查看视频并这样做. + +不要将视频上传到产品存储库. [链接](#link-to-video)或[嵌入](#embed-videos)它们. + +### Link to video[](#link-to-video "Permalink") + +要链接到视频,请添加 YouTube 图标,以便读者在阅读之前可以快速轻松地扫描页面上的视频: + +``` +<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> +For an overview, see [Video Title](link-to-video). +``` + +您可以链接任何对 GitLab 用户有用的最新视频. + +### Embed videos[](#embed-videos "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/472) . + +[GitLab Docs 网站](https://s0docs0gitlab0com.icopy.site)支持嵌入式视频. + +您只能嵌入来自[GitLab 的官方 YouTube 帐户的视频](https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg) . 对于其他来源的视频,请[链接](#link-to-video)它们. + +在大多数情况下,最好[链接到视频](#link-to-video) ,因为嵌入会占用页面上的大量空间,并且可能分散读者的注意力. + +要嵌入视频,请按照以下说明进行操作,并确保您的 MR 已得到技术作家的审查和批准. + +1. 复制下面的代码,并将其粘贴到 Markdown 文件中. 在其上方和下方保留空白行. 请勿编辑代码(请勿删除或添加任何空格). +2. 在 YouTube 上,访问要显示的视频 URL. 从您的浏览器复制常规 URL( `https://www.youtube.com/watch?v=VIDEO-ID` ),然后替换视频标题和`<div class="video-fallback">`行中的链接. +3. 在 YouTube 上,点击**共享** ,然后点击**嵌入** . +4. 仅复制`<iframe>`源( `src` ) **URL** ( `https://www.youtube.com/embed/VIDEO-ID` ),然后粘贴它,替换`iframe`标记中`src`字段的内容. + +``` +leave a blank line here +<div class="video-fallback"> + See the video: <a href="https://www.youtube.com/watch?v=MqL6BMOySIQ">Video title</a>. +</div> +<figure class="video-container"> + <iframe src="https://www.youtube.com/embed/MqL6BMOySIQ" frameborder="0" allowfullscreen="true"> </iframe> +</figure> +leave a blank line here +``` + +它是如何在 GitLab Docs 网站上呈现的: + +观看视频: [什么是 GitLab](https://www.youtube.com/watch?v=enMumwvLAug) . + +<figure class="video-container"><iframe src="https://www.youtube.com/embed/MqL6BMOySIQ" frameborder="0" allowfullscreen=""></iframe></figure> + +> Notes: +> +> * `figure`标记是语义 SEO 所必需的,而`video_container`类是必需的,以确保视频能够响应并在不同的移动设备上很好地显示. +> * `<div class="video-fallback">`是 GitLab 的`/help`必需的后备,因为 GitLab 的 Markdown 处理器不支持 iframe. 它隐藏在 docs 网站上,但将显示在 GitLab 的`/help` . + +## Code blocks[](#code-blocks "Permalink") + +* 始终将添加到句子的代码包装在内联代码块( ``` )中. 例如`.gitlab-ci.yml` , `git add .` , `CODEOWNERS`或`only: [master]` . 文件名,命令,条目以及任何涉及代码的内容都应添加到代码块中. 为了使用户更轻松,请始终为可复制和粘贴的内容添加完整的代码块,因为他们可以使用代码块上的按钮轻松进行操作. +* 在代码块的上方和下方添加一个空行. +* 提供 shell 命令及其输出时,请在 shell 命令前加上`$`前缀,并在命令和输出之间留空行. +* 提供无输出的命令时,请不要在 shell 命令前加上`$`前缀. +* 如果需要在代码块中包括三个反引号,则对代码块围栏使用四个反引号,而不是三个. +* 对于常规的受保护代码块,请始终使用与该语言对应的突出显示类,以提高可读性. 例子: + + ``` + ```ruby Ruby code + ``` + + ```javascript JavaScript code + ``` + + ```markdown [Markdown code example](example.md) + ``` + + ```plaintext Code or text for which no specific highlighting class is available. + ``` + ``` + +加到 GitLab 文档中的受防护代码块要求突出显示语法. 有关最常用的语言类别,请参考下表,或查看可用语言类别的[完整列表](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers) . + +| 首选语言标签 | 语言别名和注释 | +| --- | --- | +| `asciidoc` |   | +| `dockerfile` | Alias: `docker`. | +| `elixir` |   | +| `erb` |   | +| `golang` | Alias: `go`. | +| `graphql` |   | +| `haml` |   | +| `html` |   | +| `ini` | 对于一些非 TOML 格式的简单配置文件. | +| `javascript` | Alias `js`. | +| `json` |   | +| `markdown` | Alias: `md`. | +| `mermaid` |   | +| `nginx` |   | +| `perl` |   | +| `php` |   | +| `plaintext` | 没有定义语言的示例,例如 shell 命令或 API 调用的输出. 如果代码块没有语言,则默认为`plaintext` . 别名: `text` . | +| `prometheus` | Prometheus 配置示例. | +| `python` |   | +| `ruby` | Alias: `rb`. | +| `shell` | Aliases: `bash` or `sh`. | +| `sql` |   | +| `toml` | Runner 配置示例以及其他 TOML 格式的配置文件. | +| `typescript` | Alias: `ts`. | +| `xml` |   | +| `yaml` | Alias: `yml`. | + +有关代码块的完整参考,请参阅《 [Kramdown 指南》](https://about.gitlab.com/handbook/markdown-guide/#code-blocks) . + +## GitLab SVG icons[](#gitlab-svg-icons "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/384) . + +您可以直接在文档中使用来自[GitLab SVG 库的](https://gitlab-org.gitlab.io/gitlab-svgs/)图标. + +This way, you can achieve a consistent look when writing about interacting with GitLab UI elements. + +用法示例: + +* 默认尺寸(16 像素)的`**{icon-name}**` : `**{icon-name}**` + + 示例: `**{tanuki}**`呈现为: . + +* 具有自定义尺寸的`**{icon-name, size}**` : `**{icon-name, size}**` + + 可用尺寸(以像素为单位):8、10、12、14、16、18、24、32、48 和 72 + + 示例: `**{tanuki, 24}**`呈现为: . + +* 具有自定义尺寸和类别的`**{icon-name, size, class-name}**` : `**{icon-name, size, class-name}**` . + + 您可以在 GitLab 文档 CSS 中访问此元素可用的任何类. + + 带有`float-right`示例, [Bootstrap 实用程序类](https://s0getbootstrap0com.icopy.site/docs/4.4/utilities/float/) : `**{tanuki, 32, float-right}**`呈现为: + +### Use GitLab SVGs to describe UI elements[](#use-gitlab-svgs-to-describe-ui-elements "Permalink") + +使用 GitLab SVG 描述屏幕元素时,还应包括该元素的名称或工具提示作为文本. + +例如,对于"管理区"的引用: + +* Correct: `**{admin}** **Admin Area > Settings**` ( **管理区域>设置**) +* Incorrect: `**{admin}** **> Settings**` ( **>设定**) + +这将确保源 Markdown 保持可读性,并应有助于辅助功能. + +以下是菜单项的源 Markdown 示例及其发布的输出: + +``` +1. Go to **{home}** **Project overview > Details** +1. Go to **{doc-text}** **Repository > Branches** +1. Go to **{issues}** **Issues > List** +1. Go to **{merge-request}** **Merge Requests** +1. Go to **{rocket}** **CI/CD > Pipelines** +1. Go to **{shield}** **Security & Compliance > Configuration** +1. Go to **{cloud-gear}** **Operations > Metrics** +1. Go to **{package}** **Packages > Container Registry** +1. Go to **{chart}** **Project Analytics > Code Review** +1. Go to **{book}** **Wiki** +1. Go to **{snippet}** **Snippets** +1. Go to **{users}** **Members** +1. Select the **More actions** **{ellipsis_v}** icon > **Hide stage** +``` + +1. 去 **项目概述>详细信息** +2. Go to **资料库>分支机构** +3. 去 **问题>清单** +4. 去 **合并请求** +5. 去 **CI / CD>管道** +6. 去 **安全与合规>配置** +7. 去 **操作>指标** +8. 去 **包>容器注册表** +9. 去 **项目分析>代码审查** +10. 去 **维基** +11. 去 **片段** +12. 去 **会员** +13. 选择**更多操作** 图标> **隐藏舞台** + +## Alert boxes[](#alert-boxes "Permalink") + +每当您需要特别注意特定句子时,请使用以下标记突出显示. + +请注意,警报框仅适用于一个段落. 多个段落,列表,标题等将无法正确呈现. 对于多行,请改用[blockquotes](#blockquotes) . + +警报框仅在 GitLab Docs 网站( [https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site) )上呈现. 在 GitLab 本身中,它们将显示为纯 Markdown 文本(如下面呈现的版本上方的示例). + +### Note[](#note "Permalink") + +注释引起了大多数读者的注意,因此应谨慎使用. 在大多数情况下,应考虑为便笺考虑的内容: + +* 仅作为上一段或最相关段落中的另一句话. +* 作为其自己的独立段落. +* 作为介绍该主题的新子标题下的内容,使它更明显/更容易找到. + +#### When to use[](#when-to-use "Permalink") + +当出于某种原因,大多数或所有浏览本节的读者都应看到内容时,请使用注释. 就是说,如果错过了它,可能会给少数用户造成重大麻烦,或者对大多数用户造成重大麻烦. + +权衡分散内容无关用户的成本与丢失内容(如果未表示为注释)的用户成本. + +``` +NOTE: **Note:** +This is something to note. +``` + +它如何在 GitLab Docs 网站上呈现: + +**注意:**这是要注意的事情. + +### Tip[](#tip "Permalink") + +``` +TIP: **Tip:** +This is a tip. +``` + +它如何在 GitLab Docs 网站上呈现: + +**提示:**这是一个提示. + +### Caution[](#caution "Permalink") + +``` +CAUTION: **Caution:** +This is something to be cautious about. +``` + +它如何在 GitLab Docs 网站上呈现: + +**注意:**这是要谨慎的事情. + +### Danger[](#danger "Permalink") + +``` +DANGER: **Danger:** +This is a breaking change, a bug, or something very important to note. +``` + +它如何在 GitLab Docs 网站上呈现: + +**危险:**这是一个重大更改,错误或要注意的重要事项. + +## Blockquotes[](#blockquotes "Permalink") + +要突出显示蓝色方框引号内的文本,请使用以下格式: + +``` +> This is a blockquote. +``` + +在[GitLab 文档网站上显示](https://s0docs0gitlab0com.icopy.site)为: + +> 这是一个大引用. + +如果文本跨多行,则可以拆分行. + +对于多个段落,请在每行之前使用符号`>` : + +``` +> This is the first paragraph. +> +> This is the second paragraph. +> +> - This is a list item +> - Second item in the list +``` + +导致: + +> 这是第一段. +> +> 这是第二段. +> +> * 这是一个清单项目 +> * 列表中的第二项 + +## Terms[](#terms "Permalink") + +为了通过 GitLab 文档保持一致性,以下内容将指导文档作者了解一致的样式和术语的用法. + +### Merge Requests (MRs)[](#merge-requests-mrs "Permalink") + +合并请求使您可以交换对源代码所做的更改,并与同一项目中的其他人进行协作. 您将看到此术语以下列方式使用: + +* 如果您要使用此功能,请使用**合并请求** . +* 在任何其他上下文中,请使用**merge request** . + +如我们公司的《 [写作风格指南》所述](https://about.gitlab.com/handbook/communication/#writing-style-guidelines) ,如果您使用**MR**首字母缩写词,请在每个文档页面上至少展开一次. 例如,第一次指定 MR 时,请指定*Merge Request(MR)*或*merge request(MR)* . + +Examples: + +* "我们更喜欢 GitLab 合并请求". +* "打开合并请求以修复断开的链接". +* "打开合并请求(MR)后,将您的 MR 提交以供审核和批准". + +### Describe UI elements[](#describe-ui-elements "Permalink") + +以下是在屏幕上描述 UI 元素时要遵循的样式: + +* 对于带有可见标签的元素,请使用带有匹配大小写的粗体标签. 例如, `the **Cancel** button` . +* 对于带有工具提示或悬停标签的元素,请使用带有匹配大小写的粗体标签. 例如, `the **Add status emoji** button` . + +### Verbs for UI elements[](#verbs-for-ui-elements "Permalink") + +以下是建议用于 UI 元素的特定动词: + +| Recommended | 用于 | Replaces | +| --- | --- | --- | +| *click* | 按钮,链接,菜单项 | "点击","按","选择" | +| *select* or *clear* | checkboxes | "启用","单击","按" | +| *select* | dropdowns | “pick” | +| *expand* | expandable sections | “open” | + +### Other Verbs[](#other-verbs "Permalink") + +| Recommended | 用于 | Replaces | +| --- | --- | --- | +| *去* | 使浏览器定位 | "导航至","打开" | + +## GitLab versions and tiers[](#gitlab-versions-and-tiers "Permalink") + +标记和发布版本的 GitLab 文档可用: + +* 在[文档档案中](https://docs.gitlab.com/archives/) . +* 在任何 GitLab 安装的`/help` URL 中. + +引入新功能的版本已添加到文档主题的顶部,以提供有关该功能开发方式的有用链接. + +### Text for documentation requiring version text[](#text-for-documentation-requiring-version-text "Permalink") + +* For features that need to declare the GitLab version that the feature was introduced. Text similar to the following should be added immediately below the heading as a blockquote: + * `> Introduced in GitLab 11.3.`. +* 只要有可能,版本文本都应具有指向已*完成的*发行,合并请求或引入了该功能的史诗的链接. 问题优先于合并请求,而合并请求优先于史诗. 例如: + * `> [Introduced](<link-to-issue>) in GitLab 11.3.` . +* 如果该功能仅在 GitLab 企业版中可用,请提及该功能在以下位置的[付费层](https://about.gitlab.com/handbook/marketing/product-marketing/#tiers) : + * `> [Introduced](<link-to-issue>) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.3.` . +* 如果随着功能的发展列出了多个版本的信息,请将该信息添加到带引号的项目符号列表中. 例如: + + ``` + > - [Introduced](<link-to-issue>) in GitLab 11.3. + > - Enabled by default in GitLab 11.4. + ``` + +* 如果功能已移至另一层: + + ``` + > - [Introduced](<link-to-issue>) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.5. + > - [Moved](<link-to-issue>) to [GitLab Starter](https://about.gitlab.com/pricing/) in 11.8. + > - [Moved](<link-to-issue>) to GitLab Core in 12.0. + ``` + +* 如果不推荐使用某个功能,请提供替换链接(如果有): + + ``` + > - [Deprecated](<link-to-issue>) in GitLab 11.3\. Replaced by [meaningful text](<link-to-appropriate-documentation>). + ``` + + 如果可以的话,也可以在周围的文字中描述替换内容. + + 如果现有文本中的弃用不明显,则可能需要添加警告,例如: + + ``` + CAUTION: **Warning:** + This feature was [deprecated](link-to-issue) in GitLab 12.3 + and replaced by [Feature name](link-to-feature-documentation). + ``` + +**注意:**版本文本必须在其单独的行上并由空白行包围才能正确呈现. + +### Versions in the past or future[](#versions-in-the-past-or-future "Permalink") + +描述过去或将来版本中可用的功能时,请使用: + +* **较早的** ,不**早** **于之前的** . +* **后来** ,并没有**新的**或**之后** . + +例如: + +* 在 GitLab 12.3 和更早版本中可用. +* 在 GitLab 12.4 和更高版本中可用. +* 如果使用 GitLab 11.4 或更早版本,… +* 如果使用 GitLab 10.6 或更高版本,… + +### Importance of referencing GitLab versions and tiers[](#importance-of-referencing-gitlab-versions-and-tiers "Permalink") + +提及 GitLab 版本和层对所有用户和贡献者来说很重要,以便他们能够快速访问引入变更的发行或合并请求以供参考. 此外,鉴于该注释包含一些关键信息,他们可以轻松了解其 GitLab 实例和版本中具有哪些功能. + +`[Introduced](link-to-issue) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7`链接到引入该功能的问题,说它属于哪个 GitLab 层,GitLab 说该版本可用的版本,并链接到定价页面,以防用户想要升级到付费层以使用该功能. + +例如,如果您是普通用户,并且正在查看以前从未使用过的功能的文档,则可以立即查看该功能是否可用. 另外,如果您长期使用某项功能并且以某种方式进行了更改,那么重要的是要能够发现更改的时间以及该功能的新增功能. + +这一点更为重要,因为我们没有一个完美的文档发布流程. 不幸的是,我们仍然看到没有文档的功能和没有功能的文档. 因此,就目前而言,我们不能 100%依赖 docs 网站版本. + +随着时间的推移,版本文本将引用 GitLab 的逐渐老版本. 如果版本文本引用了 GitLab 的四个或更多个主要版本,您可以考虑删除不相关或令人困惑的文本. + +例如,如果当前的主要版本是 12.x,则在需要更清晰或更干净的文档时,需要引用引用 GitLab 8.x 和更早版本的版本文本. + +## Products and features[](#products-and-features "Permalink") + +在 GitLab 产品文档中描述产品和功能时,请参考本节中的信息. + +### Avoid line breaks in names[](#avoid-line-breaks-in-names "Permalink") + +输入包含空格(例如 GitLab 社区版)或什至其他公司产品(例如 Amazon Web Services)的产品或功能名称时,请确保不要在插入了换行符的行之间拆分产品或功能名称. 跨行拆分产品或功能名称会使搜索这些项目更加困难,并且如果名称更改则可能导致问题. + +例如,以下 Markdown 内容的格式*不*正确: + +``` +When entering a product or feature name that includes a space (such as GitLab +Community Edition), don't split the product or feature name across lines. +``` + +而是,它应类似于以下内容: + +``` +When entering a product or feature name that includes a space (such as +GitLab Community Edition), don't split the product or feature name across lines. +``` + +### Product badges[](#product-badges "Permalink") + +当仅 EE 层中有功能可用时,请根据功能可用性添加相应的层: + +* 对于 GitLab Core 和 GitLab.com 免费: `**(CORE)**` . +* 对于 GitLab Starter 和 GitLab.com 铜牌: `**(STARTER)**` . +* 对于 GitLab Premium 和 GitLab.com 银牌: `**(PREMIUM)**` . +* 对于 GitLab Ultimate 和 GitLab.com Gold: `**(ULTIMATE)**` . + +要排除 GitLab.com 层(当该功能在 GitLab.com 中不可用时),请添加关键字" only": + +* 对于 GitLab Core: `**(CORE ONLY)**` . +* 对于 GitLab Starter: `**(STARTER ONLY)**`适用于`**(STARTER ONLY)**` . +* 对于 GitLab Premium: `**(PREMIUM ONLY)**` . +* 对于 GitLab Ultimate: `**(ULTIMATE ONLY)**` . + +对于 GitLab.com 仅适用于层(当该功能不适用于自我管理实例时): + +* 对于 GitLab 免费和更高级别: `**(FREE ONLY)**` . +* 对于 GitLab 青铜级和更高级别: `**(BRONZE ONLY)**`铜级`**(BRONZE ONLY)**` . +* 对于 GitLab Silver 和更高级别: `**(SILVER ONLY)**` . +* 对于 GitLab Gold: `**(GOLD ONLY)**` . + +理想情况下,应将该层添加到标题中,以便显示完整的徽标. 但是,也可以从段落,列表项和表格单元格中提及. 对于这些情况,层级提及将由橙色的信息图标**(信息)**表示,该图标将显示悬停时的层级. + +即使页面上存在较高级别的层,也应使用页面级别的最低层. 例如,您可能有一个页面标记为 Starter,而一个部分标记为 Premium. + +例如: + +* `**(STARTER)**`呈现为 +* `**(STARTER ONLY)**`呈现为 +* `**(SILVER ONLY)**`呈现为 + +没有提及层意味着该功能可在 GitLab Core,GitLab.com Free 和所有更高层使用. + +#### How it works[](#how-it-works "Permalink") + +由[!244](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/244)引入的特殊标记`**(STARTER)**`将生成一个`span`元素,以触发徽章和工具提示( `<span class="badge-trigger starter">` ). 添加关键字" only"时,将不会显示相应的 GitLab.com 徽章. + +## Specific sections[](#specific-sections "Permalink") + +某些样式应应用于特定部分. 下面概述了特定部分的样式. + +### GitLab restart[](#gitlab-restart "Permalink") + +在许多情况下,需要重新启动/重新配置 GitLab. 为避免重复,请链接到可以在[`doc/administration/restart_gitlab.md`](../../administration/restart_gitlab.html)找到的特殊文档. 通常,文本显示如下: + +``` +Save the file and [reconfigure GitLab](../../administration/restart_gitlab.md) +for the changes to take effect. +``` + +如果您正在编辑的文档位于 GitLab CE / EE `doc/`目录之外的其他位置,请使用完整路径,而不是相对链接: `https://docs.gitlab.com/ce/administration/restart_gitlab.html` : `https://docs.gitlab.com/ce/administration/restart_gitlab.html` . 在适当的地方,将`reconfigure`替换为`reconfigure` `restart` . + +### Installation guide[](#installation-guide "Permalink") + +**Ruby:**在[安装指南的第 2 步中](../../install/installation.html#2-ruby) ,我们从源代码安装 Ruby. 每当有新版本需要更新时,请记住在整个代码块中进行更改,并替换 sha256sum(可在 Ruby 网站的[下载页面](https://www.ruby-lang.org/en/downloads/)中找到). + +### Configuration documentation for source and Omnibus installations[](#configuration-documentation-for-source-and-omnibus-installations "Permalink") + +GitLab currently officially supports two installation methods: installations from source and Omnibus packages installations. + +只要有两种安装方法都可以配置的设置,就最好在 CE 文档中进行记录以避免重复. + +配置设置包括: + +1. 触及`config/`配置文件的设置. +2. NGINX 设置和`lib/support/`中的设置通常. + +如果有要执行的步骤列表,通常需要编辑配置文件并重新配置/重新启动 GitLab. 在这种情况下,请按照以下样式作为指导: + +``` +**For Omnibus installations** + 1. Edit `/etc/gitlab/gitlab.rb`: + + ```ruby + external_url "https://gitlab.example.com" + ``` + 1. Save the file and [reconfigure](path/to/administration/restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab for the changes to take effect. + --- +**For installations from source** + 1. Edit `config/gitlab.yml`: + + ```yaml + gitlab: + host: "gitlab.example.com" + ``` + 1. Save the file and [restart](path/to/administration/restart_gitlab.md#installations-from-source) GitLab for the changes to take effect. +``` + +在这种情况下: + +* 在每个步骤列表之前,安装方法以粗体声明. +* 三个破折号( `---` )用于创建水平线并将两种方法分开. +* 代码块在列表项下缩进一个或多个空格以正确呈现. +* 代码块中的每个配置使用不同的突出显示语言. +* [GitLab 重新启动](#gitlab-restart)部分用于说明 GitLab 所需的重新启动/重新配置. + +### Troubleshooting[](#troubleshooting "Permalink") + +对于疑难解答部分,您应该提供尽可能多的上下文,以便用户可以识别自己面临的问题并自行解决. 您可以通过确保故障排除内容解决以下问题来简化此操作: + +1. 用户需要解决的问题. +2. 用户如何确认他们有问题. +3. 用户可以采取的解决问题的步骤. + +如果可以将所有类别的内容汇总在一行中,并且不需要步骤列表,请考虑设置一个带有" *问题* |标题"的[表](#tables) . *原因* *解决方案* (或*解决方法(*如果此修复程序是临时的))或*错误消息* | *解决方法* . + +## Feature flags[](#feature-flags "Permalink") + +了解如何[记录标记后部署的功能](feature_flags.html) . 有关使用功能标记开发 GitLab 的指导,请参阅[GitLab 开发中的功能标记](../feature_flags/index.html) . + +## API[](#api "Permalink") + +这是必备物品清单. 按照本文档中出现的确切顺序使用它们. 下面给出进一步的解释. + +* Every method must have the REST API request. For example: + + ``` + GET /projects/:id/repository/branches + ``` + +* 每个方法都必须[对参数](#method-description)进行详细[说明](#method-description) . +* 每个方法都必须有一个 cURL 示例. +* 每个方法都必须具有响应主体(JSON 格式). + +### API topic template[](#api-topic-template "Permalink") + +以下内容可以用作入门模板: + +``` +## Descriptive title + +One or two sentence description of what endpoint does. + +```plaintext METHOD /endpoint +``` + +| Attribute | Type | Required | Description | +|:------------|:---------|:---------|:----------------------| +| `attribute` | datatype | yes/no | Detailed description. | +| `attribute` | datatype | yes/no | Detailed description. | + +Example request: + +```shell curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/endpoint?parameters' +``` + +Example response: + +```json [ { } ] +``` +``` + +### Fake user information[](#fake-user-information "Permalink") + +您可能需要演示包含用户名和电子邮件地址的 API 调用或 cURL 命令. 不要在 API 调用中使用真实的用户信息: + +* **电子邮件地址** :使用以`example.com`结尾的电子邮件地址. +* **名称** :使用`Example Username` **名之类的**字符串. 或者,使用具有常用姓氏的各种或非性别名称,例如`Sidney Jones` , `Zhang Wei` . 或`Maria Garcia` . + +### Fake URLs[](#fake-urls "Permalink") + +在文档中包含示例 URL 时,请使用: + +* 域名通用时为`example.com` . +* `gitlab.example.com`指 GitLab 的自我管理的实例时. + +### Fake tokens[](#fake-tokens "Permalink") + +有时可能需要令牌来证明使用 cURL 或 CI 中使用的变量进行 API 调用. 强烈建议不要在文档中使用真实令牌,即使令牌被利用的可能性很低. + +您可以使用以下伪造的令牌作为示例. + +| 代币类型 | 代币价值 | +| --- | --- | +| 私人用户令牌 | `<your_access_token>` | +| 个人访问令牌 | `n671WNGecHugsdEDPsyo` | +| 申请编号 | `2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6` | +| 应用机密 | `04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df` | +| 可变 CI / CD | `Li8j-mLUVA3eZYjPfd_H` | +| 特定跑步者令牌 | `yrnZW46BrtBFqM7xDzE7dddd` | +| 共享亚军令牌 | `6Vk7ZsosqQyfreAxXTZr` | +| 触发令牌 | `be20d8dcc028677c931e04f3871a9b` | +| Webhook 秘密令牌 | `6XhDroRcYPM5by_h-HLY` | +| 健康检查令牌 | `Tu7BgjR9qeZTEyRzGG2P` | +| 请求个人资料令牌 | `7VgpS4Ax5utVD2esNstz` | + +### Method description[](#method-description "Permalink") + +使用下表标题来描述方法. 属性应始终位于使用反引号( ``` )的代码块中. + +``` +| Attribute | Type | Required | Description | +|:----------|:-----|:---------|:------------| +``` + +渲染示例: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user` | string | yes | GitLab 用户名 | + +### cURL commands[](#curl-commands "Permalink") + +* 使用`https://gitlab.example.com/api/v4/`作为端点. +* 在需要的地方使用此个人访问令牌: `<your_access_token>` . +* 始终将请求放在第一位. `GET`是默认设置,因此您不必包含它. +* 将该网址用双引号( `"` )引起来. +* 最好使用使用个人访问令牌的示例,并且不要传递用户名和密码的数据. + +| Methods | Description | +| --- | --- | +| `--header "PRIVATE-TOKEN: <your_access_token>"` | 每当需要身份验证时,请按原样使用此方法 | +| `--request POST` | 创建新对象时使用此方法 | +| `--request PUT` | 更新现有对象时使用此方法 | +| `--request DELETE` | 删除现有对象时使用此方法 | + +### cURL Examples[](#curl-examples "Permalink") + +以下是一组可以在 API 文档中使用的[cURL](https://curl.haxx.se)示例. + +#### Simple cURL command[](#simple-curl-command "Permalink") + +获取组的详细信息: + +``` +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/gitlab-org +``` + +#### cURL example with parameters passed in the URL[](#curl-example-with-parameters-passed-in-the-url "Permalink") + +在经过身份验证的用户的名称空间下创建一个新项目: + +``` +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects?name=foo" +``` + +#### Post data using cURL’s `--data`[](#post-data-using-curls---data "Permalink") + +您可以使用 cURL 的`--data`选项,而不是使用`--request POST`并将参数附加到 URI. 下面的示例将在经过身份验证的用户的名称空间下创建一个新项目`foo` . + +``` +curl --data "name=foo" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects" +``` + +#### Post data using JSON content[](#post-data-using-json-content "Permalink") + +> **注意:**在此示例中,我们创建一个新组. 仔细观察单引号和双引号. + +``` +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"path": "my-group", "name": "My group"}' https://gitlab.example.com/api/v4/groups +``` + +#### Post data using form-data[](#post-data-using-form-data "Permalink") + +除了使用 JSON 或 urlencode 外,您还可以使用 multipart / form-data 来正确处理数据编码: + +``` +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "title=ssh-key" --form "key=ssh-rsa AAAAB3NzaC1yc2EA..." https://gitlab.example.com/api/v4/users/25/keys +``` + +上面的示例由管理员运行,并将向用户帐户添加名为`ssh-key`的 SSH 公共密钥,其 ID 为 25. + +#### Escape special characters[](#escape-special-characters "Permalink") + +空格或斜杠( `/` )有时可能会导致错误,因此建议在可能的情况下转义它们. 在下面的示例中,我们创建了一个新问题,该问题的标题中包含空格. 观察如何使用 ASCII 代码对空格进行转义. + +``` +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/42/issues?title=Hello%20Dude" +``` + +将`/`用作斜杠( `/` ). + +#### Pass arrays to API calls[](#pass-arrays-to-api-calls "Permalink") + +GitLab API 有时会接受字符串或整数数组. 例如,要在请求项目用户列表时排除特定用户,您可以执行以下操作: + +``` +curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "skip_users[]=<user_id>" --data "skip_users[]=<user_id>" https://gitlab.example.com/api/v4/projects/<project_id>/users +``` \ No newline at end of file diff --git a/_book/docs/570.md b/_book/docs/570.md new file mode 100644 index 0000000000000000000000000000000000000000..66b58280a75b5c5bc9b609765b93872083297ab2 --- /dev/null +++ b/_book/docs/570.md @@ -0,0 +1,147 @@ +# Documentation structure and template + +> 原文:[https://docs.gitlab.com/ee/development/documentation/structure.html](https://docs.gitlab.com/ee/development/documentation/structure.html) + +* [Components of a documentation page](#components-of-a-documentation-page) +* [Template for new docs](#template-for-new-docs) +* [Help and feedback section](#help-and-feedback-section) + * [Disqus](#disqus) + +# Documentation structure and template[](#documentation-structure-and-template "Permalink") + +本文档将帮助您确定如何在 GitLab 文档中构建页面以及包含哪些内容. 这些标准有助于确保整个文档的一致性和完整性,并使它们的贡献更加容易. + +在开始之前,请熟悉[GitLab 的文档指南](index.html)和[样式指南中](styleguide.html)有关内容的部分. + +## Components of a documentation page[](#components-of-a-documentation-page "Permalink") + +大多数页面将专用于 GitLab 的特定功能或涉及一个或多个功能的用例(可能与第三方工具结合使用). + +每个功能部件或用例文档应按以下顺序包括以下内容,以下内容和此页面中包含的模板中注明了例外和详细信息. + +* **标题** :具有功能名称或用例名称的顶级标题,该名称应以动词开头,例如" Configure"," Enable"等. +* **简介** :关于此主题以及在此页面上可以找到的内容的简短句子. 描述功能或主题是什么,它做什么,以及在什么情况下应使用它. 无需添加称为"简介"或"概述"的标题,因为人们很少搜索这些术语. 只需将这些信息放在标题之后即可. +* **用例** :描述该功能/配置的实际用例场景. +* **要求** :描述所需的软件,配置,帐户或知识. +* **说明** :遵循一套或多套详细说明. +* **故障排除**指南(推荐但不是必需的). + +有关每个[文档的](#template-for-new-docs)更多详细信息,请参见下面的[新文档模板](#template-for-new-docs) . + +请注意,您可以酌情包括其他小节,例如"工作原理","体系结构"以及其他逻辑划分,例如部署前和部署后步骤. + +## Template for new docs[](#template-for-new-docs "Permalink") + +要开始新文档,请遵守文件树和文件名准则以及样式准则. 使用以下模板: + +``` +<!--Follow the Style Guide when working on this document. https://docs.gitlab.com/ee/development/documentation/styleguide.html +When done, remove all of this commented-out text, except a commented-out Troubleshooting section, +which, if empty, can be left in place to encourage future use.--> +--- description: "Short document description." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here. +stage: "Add the stage name here, and remove the quotation marks" +group: "Add the group name here, and remove the quotation marks" +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- +# Feature Name or Use Case Name **[TIER]** (1) +<!--If writing about a use case, drop the tier, and start with a verb, e.g. "Configure", "Implement", + the goal/scenario--> + +<!--For pages on newly introduced features, add the following line. If only some aspects of the feature have been introduced, specify what parts of the feature.--> +> [Introduced](link_to_issue_or_mr) in GitLab (Tier) X.Y (2). + +An introduction -- without its own additional header -- goes here. +Offer a description of the feature or use case, and what to expect on this page. +(You can reuse this content, or part of it, for the front matter's `description` at the top of this file). + +The introduction should answer the following questions: + - What is this feature or use case? +- Who is it for? +- What is the context in which it is used and are there any prerequisites/requirements? +- What can the audience do with this? (Be sure to consider all applicable audiences, like GitLab admin and developer-user.) +- What are the benefits to using this over any alternatives? + +## Use cases + +Describe some use cases, typically in bulleted form. Include real-life examples for each. + +If the page itself is dedicated to a use case, this section can usually include more specific scenarios +for use (e.g. variations on the main use case), but if that's not applicable, the section can be omitted. + +Examples of use cases on feature pages: +- CE and EE: [Issues](../../user/project/issues/index.md#use-cases) +- CE and EE: [Merge Requests](../../user/project/merge_requests/index.md) +- EE-only: [Geo](../../administration/geo/replication/index.md) +- EE-only: [Jenkins integration](../../integration/jenkins.md) + +## Requirements + +State any requirements for using the feature and/or following along with the instructions. + +These can include both: +- technical requirements (e.g. an account on a third party service, an amount of storage space, prior configuration of another feature) +- prerequisite knowledge (e.g. familiarity with certain GitLab features, cloud technologies) + +Link each one to an appropriate place for more information. + +## Instructions + +"Instructions" is usually not the name of the heading. +This is the part of the document where you can include one or more sets of instructions, each to accomplish a specific task. +Headers should describe the task the reader will achieve by following the instructions within, typically starting with a verb. +Larger instruction sets may have subsections covering specific phases of the process. +Where appropriate, provide examples of code or configuration files to better clarify intended usage. + - Write a step-by-step guide, with no gaps between the steps. +- Include example code or configurations as part of the relevant step. Use appropriate Markdown to [wrap code blocks with syntax highlighting](../../user/markdown.md#colored-code-and-syntax-highlighting). +- Start with an h2 (`##`), break complex steps into small steps using +subheadings h3 > h4 > h5 > h6\. _Never skip a hierarchy level, such +as h2 > h4_, as it will break the TOC and may affect the breadcrumbs. +- Use short and descriptive headings (up to ~50 chars). You can use one +single heading like `## Configure X` for instructions when the feature +is simple and the document is short. + +<!-- ## Troubleshooting + +Include any troubleshooting steps that you can foresee. If you know beforehand what issues +one might have when setting this up, or when something is changed, or on upgrading, it's +important to describe those, too. Think of things that may go wrong and include them here. +This is important to minimize requests for support, and to avoid doc comments with +questions that you know someone might ask. + +Each scenario can be a third-level heading, e.g. `### Getting error message X`. +If you have none to add when creating a doc, leave this section in place +but commented out to help encourage others to add to it in the future. --> + --- +Notes: + - (1): Apply the [tier badges](styleguide.md#product-badges) accordingly +- (2): Apply the correct format for the [GitLab version introducing the feature](styleguide.md#gitlab-versions-and-tiers) +``` + +## Help and feedback section[](#help-and-feedback-section "Permalink") + +通过在文档的开头添加一个键,可以从文档中省略每个文档末尾显示的"帮助和反馈"部分(由[!319](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/319)引入): + +``` +--- +feedback: false +--- +``` + +默认为将其保留在此处. 如果要从文档中忽略它,则必须先咨询技术作家. + +### Disqus[](#disqus "Permalink") + +我们还将 docs 站点与 Disqus 集成在一起(由[!151](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/151)引入),使我们的用户可以发表评论. + +要仅忽略反馈部分中的评论,请在最前面使用以下键: + +``` +--- +comments: false +--- +``` + +We are only hiding comments in main index pages, such as [the main documentation index](../../README.html), since its content is too broad to comment on. Before omitting Disqus, you must check with a technical writer. + +请注意,一旦在前件中添加了" `feedback: false` ,它将自动省略 Disqus,因此,请勿将两个关​​键字都添加到同一文档中. + +Google 跟踪代码管理器会跟踪"反馈"部分中的点击事件. 通过导航至" **行为">"事件">"热门事件">" docs",**可以在 Google Analytics(分析)上查看转化. \ No newline at end of file diff --git a/_book/docs/571.md b/_book/docs/571.md new file mode 100644 index 0000000000000000000000000000000000000000..80f7a5f916aca40aad327e39072cf717e89bfeda --- /dev/null +++ b/_book/docs/571.md @@ -0,0 +1,135 @@ +# Documentation process + +> 原文:[https://docs.gitlab.com/ee/development/documentation/workflow.html](https://docs.gitlab.com/ee/development/documentation/workflow.html) + +* [Who updates the docs?](#who-updates-the-docs) +* [Documentation labels](#documentation-labels) +* [How to update the docs](#how-to-update-the-docs) + * [Reviewing and merging](#reviewing-and-merging) +* [Other ways to help](#other-ways-to-help) +* [Post-merge reviews](#post-merge-reviews) + * [Before merging](#before-merging) + +# Documentation process[](#documentation-process "Permalink") + +创建和维护 GitLab 产品文档的过程允许任何人提交合并请求或为 GitLab 文档创建问题. + +**注意:**与新功能或功能增强相关的文档更新必须使用 GitLab 手册[中](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#for-a-product-change)描述的[功能工作流程](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#for-a-product-change) . + +## Who updates the docs?[](#who-updates-the-docs "Permalink") + +*任何人都*可以贡献力量! 您可以在以下情况下创建文档合并请求: + +* 您发现现有文档中存在错误或其他需要改进的地方. +* 您对全新文档有一个想法,可以帮助 GitLab 用户或管理员完成其与 GitLab 的工作. + +## Documentation labels[](#documentation-labels "Permalink") + +无论发布或合并请求的类型如何,添加或更新文档时都需要某些标签. 发行或合并请求作者添加了以下内容: + +* 适当的[类型标签](../contributing/issue_workflow.html#type-labels) . +* [阶段标签](../contributing/issue_workflow.html#stage-labels)和[组标签](../contributing/issue_workflow.html#group-labels) . 例如, `~devops::create`和`~devops::create` `~group::source code` . +* The `~documentation` [specialization label](../contributing/issue_workflow.html#specialization-labels). + +技术写作团队的成员还添加了以下内容: + +* 具有`docs::`前缀的文档[范围标签](../../user/project/labels.html#scoped-labels-premium) . 例如, `~docs::improvement` . +* The `~Technical Writing` [team label](../contributing/issue_workflow.html#team-labels). + +与新功能或更新功能的发布无关的文档更改不带有`~feature`标签,但仍需要`~documentation`标签. + +它们可能包括: + +* 创建或更新文档以提高准确性,完整性,易用性或[功能更改](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#for-a-product-change)以外的任何其他原因. +* 解决现有文档中的空白,或对现有文档进行改进. +* 处理与文档相关的特殊项目. + +## How to update the docs[](#how-to-update-the-docs "Permalink") + +要更新 GitLab 文档: + +1. Either: + * 单击[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site)上任何页面底部的" **编辑此页面"**链接. + * 导航到[GitLab 文档指南](index.html)页面上列出的存储库和文档路径之一. +2. 请遵循页面上列出的描述的标准和过程,包括: + * [结构和模板](structure.html)页面. + * [样式指南](styleguide.html) . + * [降价指南](https://about.gitlab.com/handbook/markdown-guide/) . +3. 遵循 GitLab 的[合并请求准则](../contributing/merge_request_workflow.html#merge-request-guidelines) . + +**提示:**如果您没有开发人员对 GitLab 项目的访问权限,请分叉工作. + +如果您满足以下条件,请寻求技术写作团队的帮助: + +* 需要帮助选择正确的文档位置. +* 想讨论文档想法或大纲. +* 想要请求其他帮助. + +要寻求帮助: + +1. 找到相关[DevOps 阶段组](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)的技术作家. +2. Either: + * 如果需要紧急帮助,请直接在问题或合并请求中分配技术作家. + * 如果需要非紧急帮助,请在问题或合并请求中 ping 技术作家. + +如果您是 GitLab Slack 工作区的成员,则可以在`#docs`请求帮助. + +### Reviewing and merging[](#reviewing-and-merging "Permalink") + +拥有维护者访问相关 GitLab 项目权限的任何人都可以合并文档更改. 维护者必须认真努力,以确保内容: + +* 清晰易懂,易于目标受众浏览和理解. +* 符合[文档指南](index.html)和[样式指南](styleguide.html) . + +如果作者或审稿人有任何疑问,他们可以提及被分配到相关[DevOps 阶段小组的作者](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments) . + +该过程涉及以下内容: + +* 主要审稿人. 由[代码审阅者](https://about.gitlab.com/handbook/engineering/projects/)或其他适当的同事进行[审阅](https://about.gitlab.com/handbook/engineering/projects/) ,以确认准确性,清晰度和完整性. 对于较小的修订,可以跳过,而无需实质性的内容更改. +* 技术作家(可选). 如果在合并之前未完成合并请求,则必须在合并后安排. 仅在需要紧急合并时才安排合并后审核. 要请求: + * 合并前审查,为适用的[DevOps 阶段组](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)分配列出的技术作家. + * 合并后审核,请参阅[合并后审核](#post-merge-reviews) . +* 维护者. 对于合并请求,维护者: + * 随时可以要求上述任何评论. + * 在技​​术作家审查之前或之后进行审查. + * 确保已设置给定的发布里程碑. + * 确保应用了适当的标签,包括将合并请求选择到版本中所需的标签. + * 确保(如果尚未完成或计划进行技术作家审查) [创建所需的问题](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Doc Review) ,将其分配给给定阶段组的技术作家,并将其与合并请求链接. + +该过程反映在" **文档** [合并请求"模板中](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/merge_request_templates/Documentation.md) . + +## Other ways to help[](#other-ways-to-help "Permalink") + +如果您有更多文档资源的想法,请使用"文档"模板[创建问题](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Documentation) . + +## Post-merge reviews[](#post-merge-reviews "Permalink") + +如果在合并之前未分配给技术作家进行审核,则开发人员或维护人员必须在合并后立即安排审核. 为此,请使用" [文档审阅"描述模板](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Doc Review)创建一个问题,并从引入了文档更改的合并合并请求中链接到该问题. + +可能会跳过常规的合并前技术作家审查的情况包括: + +* 里程碑发布还有很短的时间. 如果还有不到三天的时间,请寻求合并后的审查,并通过 Slack 对作者进行 ping 操作,以确保审查尽快完成. +* The size of the change is small and you have a high degree of confidence that early users of the feature (for example, GitLab.com users) can easily use the documentation as written. + +Remember: + +* 在 GitLab,我们将文档视为代码. 与代码一样,必须检查文档以确保质量. +* 文档是 GitLab [对 done 的定义的](../contributing/merge_request_workflow.html#definition-of-done)一部分. +* 当代码在里程碑发布之前完成得很好并且需要更大的文档更改时,这种合并前的 Technical Writer 审核应该是最常见的. +* 如果重要的是尽快使它附带的代码合并,那么可以要求对文档进行合并后技术审查. 在这种情况下,原始 MR 的作者将在后续 MR 中阐述技术作家提供的反馈. +* 技术作家还可以帮助您确定无需技术作家审查就可以合并文档,而审查将在合并后立即进行. + +### Before merging[](#before-merging "Permalink") + +如果跳过初步的技术作家审查,请确保以下各项: + +* 该[产品徽章](styleguide.html#product-badges)已应用. +* 包含引入该功能的 GitLab [版本](styleguide.html#text-for-documentation-requiring-version-text)已包括在内. +* 标题的更改不会影响应用内超链接. +* 记录了特定的[用户权限](../../user/permissions.html) . +* 为了发现,这些新文档从更高级别的索引链接在一起. +* 遵循样式指南: + * 用于[目录和文件](styleguide.html#work-with-directories-and-files) . + * 对于[图像](styleguide.html#images) . + +**注意:**更改文档位置的合并请求必须在合并之前始终由技术作家审查. \ No newline at end of file diff --git a/_book/docs/572.md b/_book/docs/572.md new file mode 100644 index 0000000000000000000000000000000000000000..22ccf34e74059a938e4836b90f6162e90defc1d8 --- /dev/null +++ b/_book/docs/572.md @@ -0,0 +1,171 @@ +# Documentation site architecture + +> 原文:[https://docs.gitlab.com/ee/development/documentation/site_architecture/](https://docs.gitlab.com/ee/development/documentation/site_architecture/) + +* [Architecture](#architecture) +* [Assets](#assets) + * [Libraries](#libraries) + * [SEO](#seo) +* [Global navigation](#global-navigation) +* [Pipelines](#pipelines) + * [Rebuild the docs site Docker images](#rebuild-the-docs-site-docker-images) + * [Deploy the docs site](#deploy-the-docs-site) +* [Using YAML data files](#using-yaml-data-files) +* [Bumping versions of CSS and JavaScript](#bumping-versions-of-css-and-javascript) +* [Linking to source files](#linking-to-source-files) +* [Algolia search engine](#algolia-search-engine) +* [Monthly release process (versions)](#monthly-release-process-versions) +* [Review Apps for documentation merge requests](#review-apps-for-documentation-merge-requests) + +# Documentation site architecture[](#documentation-site-architecture "Permalink") + +[`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs)项目托管用于生成 GitLab 文档网站的资源库,该资源库已部署到[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site) . 它使用[Nanoc](https://nanoc.ws/)静态站点生成器. + +## Architecture[](#architecture "Permalink") + +文档内容的源存储在 GitLab 的各个产品存储库中,而用于*从该内容*构建文档站点的源位于[https://gitlab.com/gitlab-org/gitlab-docs](https://gitlab.com/gitlab-org/gitlab-docs) . + +下图说明了从中获取内容的存储库, `gitlab-docs`项目和已发布的输出之间的关系. + +图 LR A [gitlab / doc] B [gitlab-runner / docs] C [omnibus-gitlab / doc] D [charts / doc] E [gitlab-docs] A-> EB-> EC-> ED- -> EE-建立管道-> FF [docs.gitlab.com] G [/ ce /] H [/ ee /] I [/ runner /] J [/ omnibus /] K [/ charts /] F- -> HF-> IF-> JF-> KH-symlink-> G + +您不会在`gitlab-docs`存储库中找到任何 GitLab 文档内容. 所有文档文件都托管在每种产品各自的存储库中,并且全部拉在一起以生成 docs 网站: + +* [GitLab](https://gitlab.com/gitlab-org/gitlab/tree/master/doc) +* [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc) +* [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/tree/master/docs) +* [GitLab Chart](https://gitlab.com/charts/gitlab/tree/master/doc) + +**注意:**在 2019 年 9 月,我们[转向了一个单一的代码库](https://gitlab.com/gitlab-org/gitlab/-/issues/2952) ,因此 CE 和 EE 的文档现在完全相同. 出于历史原因,并且为了不破坏整个 Internet 上的任何现有链接,我们仍然维护 CE 文档( `https://docs.gitlab.com/ce/` ),尽管它已从网站中隐藏,现在已成为符号链接到 EE 文档. 如果[Pages 支持重定向](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/24) ,我们将能够彻底删除它. + +## Assets[](#assets "Permalink") + +为了提供优化的网站结构,设计和搜索引擎友好的网站以及可发现的文档,我们在 GitLab 文档网站中使用了一些资产. + +### Libraries[](#libraries "Permalink") + +* [Bootstrap 4.3.1 components](https://s0getbootstrap0com.icopy.site/docs/4.3/components/) +* [Bootstrap 4.3.1 JS](https://s0getbootstrap0com.icopy.site/docs/4.3/getting-started/javascript/) +* [jQuery](https://jquery.com/) 3.3.1 +* [Clipboard JS](https://clipboardjs.com/) +* [Font Awesome 4.7.0](https://fontawesome.com/v4.7.0/icons/) + +### SEO[](#seo "Permalink") + +* [Schema.org](https://schema.org/) +* [Google Analytics](https://marketingplatform.google.com/about/analytics/) +* [Google Tag Manager](https://developers.google.com/tag-manager/) + +## Global navigation[](#global-navigation "Permalink") + +通读[全局导航文档](global_nav.html)以了解: + +* 全局导航的构建方式. +* 如何添加新的导航项. + +## Pipelines[](#pipelines "Permalink") + +`gitlab-docs`项目中的管道: + +* 测试对 docs 站点代码的更改. +* 构建用于各种管道作业的 Docker 映像. +* 构建和部署文档站点本身. +* 触发`review-docs-deploy`作业时生成审阅应用程序. + +### Rebuild the docs site Docker images[](#rebuild-the-docs-site-docker-images "Permalink") + +星期一每周一次,运行预定的管道并重建用于各种管道作业(例如`docs-lint`的 Docker 映像. Docker 映像配置文件位于[Dockerfiles 目录中](https://gitlab.com/gitlab-org/gitlab-docs/-/tree/master/dockerfiles) . + +如果您需要立即重建 Docker 映像(必须具有维护者级别权限): + +**注意:**如果更改 dockerfile 配置并重建映像,则可以在`gitlab`主存储库以及`gitlab-docs`中`gitlab-docs` . 首先创建一个具有不同名称的映像,然后对其进行测试,以确保您不会中断管道. + +1. 在[`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs) ,转到 **CI / CD>管道** . +2. 单击**运行管道**按钮. +3. 看到新的管道正在运行. 构建图像的工作在第一阶段,即`build-images` . 您可以单击管道编号以查看较大的管道​​图,或单击迷你管道图中的第一( `build-images` )阶段以公开构建图像的作业. +4. 点击**播放** ( )按钮旁边的要重建的图像. + * 通常,您不需要重建`image:gitlab-docs-base`映像,因为它很少更改. 如果确实需要重建,请确保仅在重建完成后才运行`image:docs-lint` . + +### Deploy the docs site[](#deploy-the-docs-site "Permalink") + +计划的管道每隔四个小时就会构建和部署一个文档站点. 管道从主项目的 master 分支中获取当前文档,并使用 Nanoc 进行构建并将其部署到[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site) . + +如果您需要立即构建和部署站点(必须具有维护者级别的权限): + +1. 在[`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs) ,转到 **CI / CD>时间表** . +2. For the `Build docs.gitlab.com every 4 hours` scheduled pipeline, click the **play** () button. + +## Using YAML data files[](#using-yaml-data-files "Permalink") + +在 Nanoc 中实现类似于[Jekyll 数据文件](https://jekyllrb.com/docs/datafiles/)的最简单方法是使用[`@items`](https://nanoc.ws/doc/reference/variables/#items-and-layouts)变量. + +数据文件必须放在`content/`目录中,然后可以在 ERB 模板中引用它. + +假设我们有具有`content/_data/versions.yaml`文件: + +``` +versions: + - 10.6 + - 10.5 + - 10.4 +``` + +然后,我们可以像下面这样遍历`versions`数组: + +``` +<% @items['/_data/versions.yaml'][:versions].each do | version | %> + +<h3><%= version %></h3> + +<% end &> +``` + +请注意,数据文件必须具有`yaml`扩展名(而不是`yml` ),并且我们使用符号( `:versions` )引用数组. + +## Bumping versions of CSS and JavaScript[](#bumping-versions-of-css-and-javascript "Permalink") + +每当`content/assets/`下的自定义 CSS 和 JavaScript 文件更改时,请确保在最前面更改其版本. 此方法通过清除先前文件的缓存来确保您的更改将生效. + +始终使用 Nanoc 包含这些文件的方式,不要在布局中对它们进行硬编码. 例如使用: + +``` +<script async type="application/javascript" src="<%= @items['/assets/javascripts/badges.*'].path %>"></script> + +<link rel="stylesheet" href="<%= @items['/assets/stylesheets/toc.*'].path %>"> +``` + +The links pointing to the files should be similar to: + +``` +<%= @items['/path/to/assets/file.*'].path %> +``` + +然后 Nanoc 将根据[`Rules`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/Rules)定义的内容正确构建和呈现这些链接. + +## Linking to source files[](#linking-to-source-files "Permalink") + +可以使用名为[`edit_on_gitlab`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/lib/helpers/edit_on_gitlab.rb)的助手来链接到页面的源文件. 我们可以链接到简单编辑器和 Web IDE. 这是在 Nanoc 布局中使用它的方法: + +* 默认编辑器: `<a href="<%= edit_on_gitlab(@item, editor: :simple) %>">Simple editor</a>` +* Web IDE: `<a href="<%= edit_on_gitlab(@item, editor: :webide) %>">Web IDE</a>` + +如果您未指定`editor:` :,则默认使用简单的一个. + +## Algolia search engine[](#algolia-search-engine "Permalink") + +docs 网站使用[Algolia DocSearch](https://community.algolia.com/docsearch/)进行搜索. 它是这样工作的: + +1. GitLab 是[DocSearch 程序](https://community.algolia.com/docsearch/#join-docsearch-program)的成员,该[程序](https://community.algolia.com/docsearch/#join-docsearch-program)是[Algolia](https://www.algolia.com/)的免费[版](https://www.algolia.com/) . +2. Algolia 为 GitLab docs 网站托管[DocSearch 配置](https://github.com/algolia/docsearch-configs/blob/master/configs/gitlab.json) ,我们已经共同努力对其进行完善. +3. 该[配置](https://community.algolia.com/docsearch/config-file.html)由[爬虫](https://community.algolia.com/docsearch/crawler-overview.html)每 24 小时进行一次解析,并将[DocSearch 索引](https://community.algolia.com/docsearch/how-do-we-build-an-index.html) [存储](https://community.algolia.com/docsearch/inside-the-engine.html)在[Algolia 的服务器上](https://community.algolia.com/docsearch/faq.html#where-is-my-data-hosted?) . +4. 在文档方面,我们使用了[DocSearch 布局](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/docsearch.html) ,除[https://docs.gitlab.com/search/](https://docs.gitlab.com/search/)使用其[自己的布局](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/instantsearch.html)之外,几乎所有页面上都存在该[布局](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/instantsearch.html) . 在这些布局中,有一个 JavaScript 代码段,该代码段使用 Algolia 显示结果所需的 API 密钥和索引名称( `gitlab` )来启动 DocSearch. + +**对于 GitLab 员工:**用于访问 Algolia 仪表板的凭据存储在 1Password 中. 如果要接收有关使用情况的每周报告,请搜索标题为`Email, Slack, and GitLab Groups and Aliases`的 Google 文档,搜索`docsearch` ,并在电子邮件中添加评论,以添加到获取每周报告的别名中. + +## Monthly release process (versions)[](#monthly-release-process-versions "Permalink") + +docs 网站支持版本,每个月我们都会将最新版本添加到列表中. 有关更多信息,请阅读有关[每月发布过程的信息](release_process.html) . + +## Review Apps for documentation merge requests[](#review-apps-for-documentation-merge-requests "Permalink") + +如果您为 GitLab 文档做出了贡献,请阅读如何[使用每个合并请求创建一个 Review App](../index.html#previewing-the-changes-live) . \ No newline at end of file diff --git a/_book/docs/573.md b/_book/docs/573.md new file mode 100644 index 0000000000000000000000000000000000000000..cb54d42c20489a1e47a2ed08809ccc7ee6679a0c --- /dev/null +++ b/_book/docs/573.md @@ -0,0 +1,347 @@ +# Global navigation + +> 原文:[https://docs.gitlab.com/ee/development/documentation/site_architecture/global_nav.html](https://docs.gitlab.com/ee/development/documentation/site_architecture/global_nav.html) + +* [Quick start](#quick-start) +* [Adding new items](#adding-new-items) + * [Where to add](#where-to-add) + * [What to add](#what-to-add) +* [How it works](#how-it-works) +* [Composition](#composition) + * [Data file](#data-file) + * [Sections](#sections) + * [Categories](#categories) + * [Docs](#docs) + * [Syntax](#syntax) + * [Titles](#titles) + * [URLs](#urls) + * [Layout file (logic)](#layout-file-logic) + * [Path](#path) + * [Default URL](#default-url) + * [`ee-only` docs](#ee-only-docs) + * [CSS classes](#css-classes) + +# Global navigation[](#global-navigation "Permalink") + +版本历史 + +* 在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/362) . +* 在 GitLab 12.1 中[更新](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/482) . +* 在 GitLab 12.2 中添加了按[项目](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/498)导航. + +全局导航(三窗格文档中最左侧的窗格)提供: + +* 产品功能的高层分组视图. +* 通过浏览菜单结构发现新功能的能力. +* 一种让读者专注于产品领域的方法. +* 能够优化登录页面的功能,因此他们不必完成覆盖文档中包含的每个页面的所有工作. + +## Quick start[](#quick-start "Permalink") + +要将主题添加到全局导航,请转到包含[导航文件](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/)的目录,然后编辑产品区域的`yaml`文件. 您可以复制现有的导航条目并将其编辑以指向您的主题. + +这些文件是: + +| File | Document | Location | +| --- | --- | --- | +| `charts-nav.yaml` | GitLab 云原生头盔图 | `https://docs.gitlab.com/charts/` | +| `default-nav.yaml` | 亚搏体育 app 文件 | `https://docs.gitlab.com/ee/` | +| `omnibus-nav.yaml` | Omnibus GitLab Docs | `https://docs.gitlab.com/omnibus/` | +| `runner-nav.yaml` | 亚搏体育 app Runner Docs | `https://docs.gitlab.com/runner/` | + +## Adding new items[](#adding-new-items "Permalink") + +所有新页面都需要一个新的导航项. 如果没有导航,页面将变为"孤立". 那是: + +* 打开页面时,导航会关闭,并且阅读器会失去位置. +* 该页面与其他页面不属于同一组. + +这意味着创建新页面的决定就是创建新导航项的决定,反之亦然. + +### Where to add[](#where-to-add "Permalink") + +文档页面可以说属于以下几类: + +* GitLab 用户. 这是用于从 Reporter 到 Owner 拥有任何级别权限的用户日常使用 GitLab 的文档. +* GitLab 管理员. 这往往是自我管理实例的文档,这些实例需要访问托管 GitLab 的基础架构. +* 其他文档. 其中包括针对日常使用 GitLab 的客户以及贡献者的文档. 属于其他组的文档属于此处. + +考虑到这些组,以下是应在何处添加新项目的一般规则. + +* 用户文档: + * 组级别功能属于" **组"** . + * 项目级功能属于" **项目"** . + * 可以将组或项目级别(有时称为"实例级别")之外的功能放在顶层,但是必须注意不要淹没该顶层空间. 如果可能,可以以某种方式对这些功能进行分组. + * 除上述内容外,其他大多数其他用户文档都属于**User** . +* 管理文档属于**Administrator** . +* 其他文档属于顶层文档,但必须注意不要创建冗长的顶层导航,这会违背它的目的. + +**注意:**正在逐步推出使所有文档和导航项目都遵循这些原则的方法. + +### What to add[](#what-to-add "Permalink") + +确定了在哪里添加导航元素之后,下一步就是确定要添加的内容. 需要什么样的机制被[证明以下](#data-file) ,但在原则: + +* 导航项文本(读者看到的文本)应: + * 越短越好. + * 要根据具体情况. 很少需要重复父项中的文本. + * 避免使用行话或艺术术语,除非无处不在. 例如, **CI**是**持续集成**的可接受替代. +* 导航链接必须遵循[数据文件中](#data-file)记录的规则. +* EE 徽章受以下条件限制: + * 链接到仅 EE 的页面时必需. + * 链接到仅包含 CE 和 EE 内容的页面时,不需要. + * 当所有子项目均为 EE 专用时为必填项. 在这种情况下,没有子项目带有 EE 标志. + * 如果子项目是仅包含 CE 和 EE 的项目,则不需要. 在这种情况下,每个项目都将被适当标记. + +## How it works[](#how-it-works "Permalink") + +全局导航具有 3 个组成部分: + +* **Section** + * Category + * Doc + +下表描述了可用的部分: + +| Section | Description | +| --- | --- | +| User | GitLab 用户界面的文档. | +| Administrator | GitLab 管理区域的文档. | +| Contributor | 开发 GitLab 的文档. | + +根据用户界面添加了导航上可用的大多数链接. 匹配并不完美,因为某些 UI 导航项不适用于该文档,并且还有其他链接可帮助新用户发现文档. 为了清楚起见," **管理** "下的文档按字母顺序排列. + +要查看计划中的改进,请查看[全局导航史诗](https://gitlab.com/groups/gitlab-com/-/epics/21) . + +**注意:**未经技术作者之一的同意, **请勿** [将项目添加](#adding-new-items)到全局导航. + +## Composition[](#composition "Permalink") + +全局导航由两个文件构建: + +* [Data](#data-file) +* [Layout](#layout-file-logic) + +数据文件将布局与文档链接一起提供给布局. 该布局在[样式](#css-classes)正确[的](#css-classes)容器中的导航之间组织数据. + +### Data file[](#data-file "Permalink") + +数据文件描述了适用项目的导航结构. 所有数据文件都存储在[https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/中,](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/)并且包含三个组件: + +* Sections +* Categories +* Docs + +#### Sections[](#sections "Permalink") + +每个部分代表较高级别的导航项. 它由标题和 URL 组成: + +``` +sections: + - section_title: Text + section_url: 'link' +``` + +该部分可以单独使用,也可以包含其中的类别. + +#### Categories[](#categories "Permalink") + +部分中的每个类别都构成了导航的第二级. 它包括类别标题和链接. 它可以单独放置在导航栏中,也可以包含第三级子项目. + +具有一个独立类别的部分的示例: + +``` +- section_title: Section title + section_url: 'section-link' + section_categories: + - category_title: Category title + category_url: 'category-link' +``` + +具有两个独立类别的部分的示例: + +``` +- section_title: Section title + section_url: 'section-link' + section_categories: + - category_title: Category 1 title + category_url: 'category-1-link' + + - category_title: Category 2 title + category_url: 'category-2-link' +``` + +为了清楚起见,请**始终**在类别之间添加空白行. + +如果 CE 中没有类别 URL(这是仅 EE 的文档),请在类别链接下方添加属性`ee_only: true` . 例: + +``` +- category_title: Category title + category_url: 'category-link' + ee_only: true +``` + +如果类别链接到外部 URL,例如[GitLab Design System](https://design.gitlab.com) ,则在类别标题下添加属性`external_url: true` . 例: + +``` +- category_title: GitLab Design System + category_url: 'https://design.gitlab.com' + external_url: true +``` + +#### Docs[](#docs "Permalink") + +每个文档代表导航链接的第三级. 必须始终将它们添加到类别中. + +带有一个文档链接的示例: + +``` +- category_title: Category title + category_url: 'category-link' + docs: + - doc_title: Document title + doc_url: 'doc-link' +``` + +A category supports as many docs as necessary, but, for clarity, try to not overpopulate a category. + +多个文档的示例: + +``` +- category_title: Category title + category_url: 'category-link' + docs: + - doc_title: Document 1 title + doc_url: 'doc-1-link' + - doc_title: Document 2 title + doc_url: 'doc-2-link' +``` + +每当仅在 EE 中存在文档时,请在 doc 链接下添加属性`ee-only: true` . 例: + +``` +- doc_title: Document 2 title + doc_url: 'doc-2-link' + ee_only: true +``` + +如果您需要在外部 URL 中添加文档,请在 doc 链接下面添加属性`external_url` : + +``` +- doc_title: Document 2 title + doc_url: 'doc-2-link' + external_url: true +``` + +所有导航链接都是可单击的. 如果上级链接没有自己的链接,则它必须链接到它的第一个子项目链接,模仿 GitLab 的导航. 必须避免这种情况,以便我们不会同时有重复的链接或两个`.active`链接. + +Example: + +``` +- category_title: Operations + category_url: 'user/project/integrations/prometheus_library/' + # until we have a link to operations, the first doc link is + # repeated in the category link + docs: + - doc_title: Metrics + doc_url: 'user/project/integrations/prometheus_library/' +``` + +#### Syntax[](#syntax "Permalink") + +对于所有组件(节,类别和文档),请**遵循缩进**和以下语法规则. + +##### Titles[](#titles "Permalink") + +* 使用句子大小写,将特征名称大写. +* 除非其中有特殊字符,否则无需包装标题. 例如,在`GitLab CI/CD` ,存在`/` ,因此必须将其用引号引起来. 按照惯例,将标题用双引号引起来: `category_title: "GitLab CI/CD"` . + +##### URLs[](#urls "Permalink") + +* 按照惯例,始终将 URL 括在单引号`'url'` . +* 始终在 CE 和 EE 的所在地使用相对路径. 例子: + * 对于`https://docs.gitlab.com/ee/README.html` ,相对 URL 为`README.html` . + * 对于`https://docs.gitlab.com/ee/user/project/cycle_analytics.html` ,相对 URL 是`user/project/cycle_analytics.html` . +* 对于`README.html`文件,添加完整路径`path/to/README.html` . +* 对于`index.html`文件,请使用干净的(规范的)URL: `path/to/` . +* 对于仅限 EE 的文档,请使用相同的相对路径,但在`doc_url`或`category_url`下添加属性`ee_only: true` ,如上所述. 这将在导航上显示一个"信息"图标,以使用户知道该功能仅适用于 EE. + +**警告:**数据文件上存在的所有链接都必须以`.html`而不是`.md`结尾. 不要以斜杠`/`开头任何相对链接. + +Examples: + +``` +- category_title: Issues + category_url: 'user/project/issues/' + # note that the above URL does not start with a slash and + # does not include index.html at the end + + docs: + - doc_title: Service Desk + doc_url: 'user/project/service_desk.html' + ee_only: false + # note that the URL above ends in html and, as the + # document is EE-only, the attribute ee_only is set to true. +``` + +### Layout file (logic)[](#layout-file-logic "Permalink") + +[布局](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/global_nav.html)由[数据文件提供](#data-file) ,构建全局导航,并由[默认](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/default.html)布局呈现. + +为导航创建的逻辑主要考虑三个方面: + +* [路径](#path) : `docs.gitlab.com/`下的第一级目录: + * `https://docs.gitlab.com/ce/` + * `https://docs.gitlab.com/ee/` + * `https://docs.gitlab.com/omnibus/` + * `https://docs.gitlab.com/runner/` + * `https://docs.gitlab.com/debug/` + * `https://docs.gitlab.com/*` +* [仅限 EE](#ee-only-docs) :仅在`/ee/`可用的文档,在`/ce/`不可用,例如: + * `https://docs.gitlab.com/ee/user/group/epics/` + * `https://docs.gitlab.com/ee/user/project/security_dashboard.html` +* [默认 URL](#default-url) :CE 和 EE 文档之间的[默认 URL](#default-url) ,默认值为`ee` ,因此,除非在`/ce/`内部链接到`ce`否则所有文档都应链接到`/ee/` . + +#### Path[](#path "Permalink") + +要在数据文件中使用相对路径,我们从根的第一个子目录定义了变量`dir` ,该目录定义了构建指向其他页面的所有导航链接的路径: + +``` +<% dir = @item.identifier.to_s[%r{(?<=/)[^/]+}] %> +``` + +例如,对于`https://docs.gitlab.com/ce/user/index.html` , `dir` = = `ce` ,和`https://docs.gitlab.com/omnibus/README.html` , `dir` == `omnibus` . + +#### Default URL[](#default-url "Permalink") + +GitLab 文档的默认规范 URL 为`https://docs.gitlab.com/ee/` ,因此,文档站点中的所有链接都应链接至`/ee/`除非在`/ce/`文档本身之间进行链接. + +因此,如果用户正在查看`/ee/` , `/omnibus/` , `/runner/`或任何其他最高级别的目录,则导航栏应指向`/ee/` docs. + +另一方面,如果用户正在查看`/ce/` docs,则 CE 导航中的所有链接都应在内部链接到`/ce/`文件. + +``` +<% if dir != 'ce' %> + <a href="/ee/<%= sec[:section_url] %>">...</a> + <% else %> + <a href="/<%= dir %>/<%= sec[:section_url] %>">...</a> + <% end %> + ... +<% end %> +``` + +这也允许导航显示在其他最高级别的目录( `/omnibus/` , `/runner/`等)上,并将它们链接回`/ee/` . + +相同的逻辑应用于所有节( `sec[:section_url]` ),类别( `cat[:category_url]` )和 docs( `doc[:doc_url]` )URL. + +#### `ee-only` docs[](#ee-only-docs "Permalink") + +仅在 gitLab EE 中存在的功能文档在数据文件中被`ee-only`标记,并且在导航链接上显示一个图标,指示`ee-only`功能在 CE 中不可用. + +`ee-only`属性可用于`categories` ( `<% if cat[:ee_only] %>` )和`docs` ( `<% if doc[:ee_only] %>` ),但不能用于`sections` . + +### CSS classes[](#css-classes "Permalink") + +导航在常规`stylesheet.scss` . 要更改其样式,请将它们分组以在团队中更好地发展. + +URL 组件的独特样式由 CSS 类`.level-0` , `.level-1`和`.level-2` . 要调整链接的字体大小,填充,颜色等,请使用这些类. 这样,我们保证每个链接的规则都不会与样式表中的其他规则冲突. \ No newline at end of file diff --git a/_book/docs/574.md b/_book/docs/574.md new file mode 100644 index 0000000000000000000000000000000000000000..1f33fd4f0fb335bc294a3e5b1465dd7ad49f28b0 --- /dev/null +++ b/_book/docs/574.md @@ -0,0 +1,187 @@ +# GitLab Docs monthly release process + +> 原文:[https://docs.gitlab.com/ee/development/documentation/site_architecture/release_process.html](https://docs.gitlab.com/ee/development/documentation/site_architecture/release_process.html) + +* [How to build the images](#how-to-build-the-images) +* [Monthly release process](#monthly-release-process) + * [1\. Add the chart version](#1-add-the-chart-version) + * [2\. Create an image for a single version](#2-create-an-image-for-a-single-version) + * [3\. Create the release merge request](#3-create-the-release-merge-request) + * [4\. Update the dropdown for all online versions](#4-update-the-dropdown-for-all-online-versions) + * [5\. Merge the release merge request](#5-merge-the-release-merge-request) +* [Update an old Docker image with new upstream docs content](#update-an-old-docker-image-with-new-upstream-docs-content) +* [Porting new website changes to old versions](#porting-new-website-changes-to-old-versions) +* [Troubleshooting](#troubleshooting) + * [`test_internal_links_and_anchors` failing on dropdown merge requests](#test_internal_links_and_anchors-failing-on-dropdown-merge-requests) + +# GitLab Docs monthly release process[](#gitlab-docs-monthly-release-process "Permalink") + +[`dockerfiles`目录](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/)包含构建和部署版本控制网站所需的所有 Dockerfile. 它在很大程度上受到了 Docker 的[Dockerfile 的](https://github.com/docker/docker.github.io/blob/06ed03db13895bfe867761b6fc2ad40acf6026dd/Dockerfile)启发. + +使用以下 Dockerfile. + +| Dockerfile | Docker 镜像 | Description | +| --- | --- | --- | +| [`Dockerfile.bootstrap`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.bootstrap) | `gitlab-docs:bootstrap` | 包含构建网站所需的所有依赖项. 如果宝石已更新且`Gemfile{,.lock}`更改,则必须重建映像. | +| [`Dockerfile.builder.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.builder.onbuild) | `gitlab-docs:builder-onbuild` | 用于建立 docs 网站的基本图片. 它使用`ONBUILD`执行所有步骤,并取决于`gitlab-docs:bootstrap` . | +| [`Dockerfile.nginx.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.nginx.onbuild) | `gitlab-docs:nginx-onbuild` | 用于构建文档档案的基本映像. 它使用`ONBUILD`执行所有必需的步骤来复制档案,并依赖于其父`Dockerfile.builder.onbuild` ,该父文件在构建单个文档档案时被调用(请参阅每个分支的`Dockerfile` . | +| [`Dockerfile.archives`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.archives) | `gitlab-docs:archives` | 在一个档案中包含网站的所有版本. 它从一个位置中的每个版本复制所有生成的 HTML 文件. | + +## How to build the images[](#how-to-build-the-images "Permalink") + +尽管构建映像是通过 GitLab CI / CD 自动构建的,但是您可以在本地构建和标记所有工具映像: + +1. 确保已[安装 Docker](https://s0docs0docker0com.icopy.site/install/) . +2. 确保您位于`gitlab-docs`存储库的`dockerfiles/`目录中. +3. 构建图像: + + ``` + docker build -t registry.gitlab.com/gitlab-org/gitlab-docs:bootstrap -f Dockerfile.bootstrap ../ + docker build -t registry.gitlab.com/gitlab-org/gitlab-docs:builder-onbuild -f Dockerfile.builder.onbuild ../ + docker build -t registry.gitlab.com/gitlab-org/gitlab-docs:nginx-onbuild -f Dockerfile.nginx.onbuild ../ + ``` + +对于每个图像, [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/.gitlab-ci.yml)的`images`阶段下都有一个手动作业,可以随意调用. + +## Monthly release process[](#monthly-release-process "Permalink") + +当 22 日发布新版本的 GitLab 时,我们需要创建相应的单个 Docker 映像,并更新一些文件,以使下拉列表正常工作. + +### 1\. Add the chart version[](#1-add-the-chart-version "Permalink") + +由于图表使用的版本号不同于所有其他 GitLab 产品,因此我们需要添加一个[版本映射](https://docs.gitlab.com/charts/installation/version_mappings.html) : + +1. 检查是否为新的图表版本[创建](https://gitlab.com/gitlab-org/charts/gitlab/-/branches)了[稳定的分支](https://gitlab.com/gitlab-org/charts/gitlab/-/branches) . 如果不确定或找不到,请在`#g_delivery`频道中添加一行. +2. 确保您位于`gitlab-docs`存储库的根路径中. +3. 打开`content/_data/chart_versions.yaml`并使用版本映射添加新的稳定分支版本. 请注意,仅需要`major.minor`版本. +4. 创建一个新的合并请求并将其合并. + +**提示:**创建将来的映射可能很方便,因为它们已广为人知. 在这种情况下,当发布新版本的 GitLab 时,您不必重复此第一步. + +### 2\. Create an image for a single version[](#2-create-an-image-for-a-single-version "Permalink") + +必须在发布合并请求之前创建单个 docs 版本,但这需要在为所有产品创建稳定分支之后发生. + +1. 确保您位于`gitlab-docs`存储库的根路径中. +2. 运行 Rake 任务以创建单个版本: + + ``` + ./bin/rake "release:single[12.0]" + ``` + + 应该已经创建了新的`Dockerfile.12.0`并且`.gitlab-ci.yml`应该将分支变量更新为新的分支. 他们将被自动提交. + +3. 推送新创建的分支,但**不要创建合并请求** . 推送后, `image:docker-singe`作业将创建一个新的 Docker 映像,该映像标记有您在第一步中创建的分支名称. 最后,该图像将被上载到[Container Registry 中](https://gitlab.com/gitlab-org/gitlab-docs/container_registry) ,并且将在位于`https://gitlab.com/gitlab-org/gitlab-docs/-/environments/folders/registry`的`registry`环境文件夹下列出.开发人员访问权限). + +(可选)您可以通过构建映像并运行它来进行本地测试: + +``` +docker build -t docs:12.0 -f Dockerfile.12.0 . +docker run -it --rm -p 4000:4000 docs:12.0 +``` + +访问`http://localhost:4000/12.0/`以查看一切是否正常. + +### 3\. Create the release merge request[](#3-create-the-release-merge-request "Permalink") + +**Note:** To be [automated](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/750). + +现在是时候创建每月发布合并请求,添加新版本并轮换旧版本了: + +1. 确保您位于`gitlab-docs`存储库的根路径中. +2. 创建一个分支`release-XY` : + + ``` + git checkout master + git checkout -b release-12-0 + ``` + +3. **轮换在线和离线版本:** + + 在任何给定时间,都有 4 个可浏览的在线版本:一个是从上游主分支(GitLab.com 的文档)中提取的,另一个是三个最新的稳定版本. + + 编辑`content/_data/versions.yaml`并旋转版本以反映新的更改: + + * `online` :3 个最新的稳定版本. + * `offline` :所有以前的版本都以脱机存档的形式提供. +4. **更新`:latest`和`:archives` Docker 映像:** + + 需要更新以下两个 Dockerfile: + + 1. `dockerfiles/Dockerfile.archives`在列表顶部添加最新版本. + 2. `Dockerfile.master`旋转版本(最旧的被删除,最新的被添加在列表的顶部). +5. 最后,应该总共更改了四个文件. 提交并使用"发布"模板推送以创建合并请求: + + ``` + git add content/ Dockerfile.master dockerfiles/Dockerfile.archives + git commit -m "Release 12.0" + git push origin release-12-0 + ``` + +### 4\. Update the dropdown for all online versions[](#4-update-the-dropdown-for-all-online-versions "Permalink") + +版本下拉列表采用"硬编码"方式. 在构建站点时,它将查看`content/_data/versions.yaml`的内容,并基于此内容填充下拉列表. 因此,较旧的分支将具有不同的内容,这意味着下拉列表将在后面列出一个或多个版本. 请记住,下拉菜单的新更改包含在未合并的`release-XY`分支中. + +The content of `content/_data/versions.yaml` needs to change for all online versions: + +1. 运行 Rake 任务,该任务将创建更新下拉列表所需的所有各个合并请求,并将其设置为在管道成功后自动合并. `release-XY`分支需要在本地存在,并且您需要切换到该分支,否则 Rake 任务将失败: + + ``` + ./bin/rake release:dropdowns + ``` + +2. [访问合并请求页面](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests?label_name[]=release)以检查其管道是否通过,并在所有管道合并后继续进行以下也是最后一步. + +**提示:**万一管道发生故障,请参阅[故障排除](#troubleshooting) . + +### 5\. Merge the release merge request[](#5-merge-the-release-merge-request "Permalink") + +下拉合并请求现在应该已经合并到各自的版本(稳定分支)中,这将触发另一个管道. 在这一点上,您只需要照看管道,并确保它们不会失败: + +1. 检查管道页面: `https://gitlab.com/gitlab-org/gitlab-docs/pipelines` : `https://gitlab.com/gitlab-org/gitlab-docs/pipelines`并确保所有稳定的分支都具有绿色管道. +2. 联机版本的所有管道成功后,请合并发布合并请求. +3. 最后,从`https://gitlab.com/gitlab-org/gitlab-docs/pipeline_schedules`运行`Build docker images weekly` Docker 映像管道,以构建`:latest`和`:archives` Docker 映像. + +一旦计划的管道成功,将在线部署所有新版本的 docs 网站. + +## Update an old Docker image with new upstream docs content[](#update-an-old-docker-image-with-new-upstream-docs-content "Permalink") + +如果对单个 Docker 映像中未包含的产品的任何稳定分支进行了任何更改,只需重新运行管道( `https://gitlab.com/gitlab-org/gitlab-docs/pipelines/new` )有问题的版本. + +## Porting new website changes to old versions[](#porting-new-website-changes-to-old-versions "Permalink") + +**警告:将**更改移植到较旧的分支机构可能会产生意想不到的影响,因为我们不断更改网站的后端. 仅在知道自己在做什么并确保在本地进行测试时使用. + +网站将不断变化和完善. 为了将这些更改合并到稳定分支中,我们需要不时选择某些更改. + +如果这不可能或有很多更改,请将 master 合并到其中: + +``` +git branch 12.0 +git fetch origin master +git merge origin/master +``` + +## Troubleshooting[](#troubleshooting "Permalink") + +发布新版本是一个漫长的过程,涉及许多活动部件. + +### `test_internal_links_and_anchors` failing on dropdown merge requests[](#test_internal_links_and_anchors-failing-on-dropdown-merge-requests "Permalink") + +**注意:**我们现在将版本`.gitlab-ci.yml`在相应分支的`.gitlab-ci.yml`中,因此不建议使用以下步骤. + +当[更新稳定版本的下拉列表时](#4-update-the-dropdown-for-all-online-versions) ,某些链接可能会失败. 创建下拉式 MR 的过程有一个警告,那就是通过拉动所有产品的主分支而不是相应的稳定分支来运行测试. + +在实际情况下,由于[`test_internal_links_and_anchors` test](https://gitlab.com/gitlab-org/gitlab-docs/-/jobs/328042431) [,导致与 12.4](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/604)合并请求[相匹配](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/604)的[Update 12.2 下拉列表](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/604)失败. + +发生这种情况是因为已经对产品进行了重命名( `gitlab-monitor`到`gitlab-exporter` ),而旧名称仍在 12.2 文档中引用. 如果使用了 12.2 的各个稳定分支,则不会失败,但是从[`compile_dev`作业中](https://gitlab.com/gitlab-org/gitlab-docs/-/jobs/328042427)可以看出, `master`分支已被拉出. + +要解决此问题, `https://gitlab.com/gitlab-org/gitlab-docs/pipelines/new`为`update-12-2-for-release-12-4`分支重新运行管道( `https://gitlab.com/gitlab-org/gitlab-docs/pipelines/new` ),以下环境变量: + +* `BRANCH_CE`设置为`12-2-stable` +* `BRANCH_EE`设置为`12-2-stable-ee` +* `BRANCH_OMNIBUS`设置为`12-2-stable` +* `BRANCH_RUNNER`设置为`12-2-stable` +* `BRANCH_CHARTS`设置为`2-2-stable` + +这应该使 MR 通过. \ No newline at end of file diff --git a/_book/docs/575.md b/_book/docs/575.md new file mode 100644 index 0000000000000000000000000000000000000000..fdd2ef2af340b9e1bd60817c25b2c27ba1b05812 --- /dev/null +++ b/_book/docs/575.md @@ -0,0 +1,208 @@ +# Telemetry Guide + +> 原文:[https://docs.gitlab.com/ee/development/telemetry/](https://docs.gitlab.com/ee/development/telemetry/) + +* [Our tracking tools](#our-tracking-tools) + * [Snowplow JS (Frontend)](#snowplow-js-frontend) + * [Snowplow Ruby (Backend)](#snowplow-ruby-backend) + * [Usage Ping](#usage-ping) + * [Database import](#database-import) + * [Log system](#log-system) +* [What data can be tracked](#what-data-can-be-tracked) + * [Database counts](#database-counts) + * [Pageview events](#pageview-events) + * [UI Events](#ui-events) + * [CRUD or API events](#crud-or-api-events) + * [Event funnels](#event-funnels) + * [PostgreSQL data](#postgresql-data) + * [Logs](#logs) + * [External services](#external-services) +* [Telemetry systems overview](#telemetry-systems-overview) + * [GitLab Inc](#gitlab-inc) + * [Self-managed](#self-managed) + * [Differences between GitLab Inc and Self-managed](#differences-between-gitlab-inc-and-self-managed) +* [Snowflake data warehouse](#snowflake-data-warehouse) + * [Data sources](#data-sources) + +# Telemetry Guide[](#telemetry-guide "Permalink") + +在 GitLab,我们收集遥测信息,以帮助我们构建更好的 GitLab. 收集有关如何使用 GitLab 的数据,以更好地了解 GitLab 的哪些部分需要改进以及下一步要构建的功能. 遥测还可以帮助我们的团队更好地理解人们使用 GitLab 的原因,并且借助这一知识,我们能够做出更好的产品决策. + +我们还鼓励用户启用跟踪功能,并且我们的跟踪方法完全透明,因此可以轻松理解和信任它. 通过启用跟踪,用户可以: + +* 回馈更广泛的社区. +* 帮助 GitLab 改进产品. + +本文档包含三个指南,概述了 GitLab 的遥测. + +遥测指南: + +1. [Our tracking tools](#our-tracking-tools) +2. [What data can be tracked](#what-data-can-be-tracked) +3. [Telemetry systems overview](#telemetry-systems-overview) +4. [Snowflake data warehouse](#snowflake-data-warehouse) + +[Usage Ping Guide](usage_ping.html) + +1. [What is Usage Ping](usage_ping.html#what-is-usage-ping) +2. [Usage Ping payload](usage_ping.html#usage-ping-payload) +3. [Disable Usage Ping](usage_ping.html#disable-usage-ping) +4. [Usage Ping request flow](usage_ping.html#usage-ping-request-flow) +5. [How Usage Ping works](usage_ping.html#how-usage-ping-works) +6. [Implementing Usage Ping](usage_ping.html#implementing-usage-ping) +7. [Developing and testing Usage Ping](usage_ping.html#developing-and-testing-usage-ping) + +[Snowplow Guide](snowplow.html) + +1. [What is Snowplow](snowplow.html#what-is-snowplow) +2. [Snowplow schema](snowplow.html#snowplow-schema) +3. [Enabling Snowplow](snowplow.html#enabling-snowplow) +4. [Snowplow request flow](snowplow.html#snowplow-request-flow) +5. [Implementing Snowplow JS (Frontend) tracking](snowplow.html#implementing-snowplow-js-frontend-tracking) +6. [Implementing Snowplow Ruby (Backend) tracking](snowplow.html#implementing-snowplow-ruby-backend-tracking) +7. [Developing and testing Snowplow](snowplow.html#developing-and-testing-snowplow) + +更有用的链接: + +* [Telemetry Direction](https://about.gitlab.com/direction/telemetry/) +* [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/) +* [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/) +* [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) + +## Our tracking tools[](#our-tracking-tools "Permalink") + +我们使用几种不同的技术来收集产品使用数据. + +### Snowplow JS (Frontend)[](#snowplow-js-frontend "Permalink") + +Snowplow 是企业级营销和产品分析平台,可帮助跟踪用户与我们的网站和应用程序互动的方式. [Snowplow JS](https://github.com/snowplow/snowplow/wiki/javascript-tracker)是客户端事件的前端跟踪器. + +### Snowplow Ruby (Backend)[](#snowplow-ruby-backend "Permalink") + +Snowplow 是企业级营销和产品分析平台,可帮助跟踪用户与我们的网站和应用程序互动的方式. [Snowplow Ruby](https://github.com/snowplow/snowplow/wiki/ruby-tracker)是服务器端事件的后端跟踪器. + +### Usage Ping[](#usage-ping "Permalink") + +用法 Ping 是 GitLab Inc 收集 GitLab 实例上的用法数据的一种方法. 用法 Ping 主要由实例数据库中不同表的行数组成. 通过逐月比较这些计数(或逐周比较),我们可以大致了解实例如何使用产品中的不同功能. 这些高级数据用于帮助我们的产品,支持和销售团队. + +有关更多详细信息,请阅读《 [用法](usage_ping.html)说明》指南. + +### Database import[](#database-import "Permalink") + +数据库导入是将数据完全导入到 GitLab 的数据仓库中. 对于 GitLab.com,每 6 小时将 PostgreSQL 数据库加载到 Snowflake 数据仓库中. 有关更多详细信息,请参见[数据团队手册](https://about.gitlab.com/handbook/business-ops/data-team/platform/#extract-and-load) . + +### Log system[](#log-system "Permalink") + +系统日志是通过运行 GitLab Rails 应用程序生成的应用程序日志. 有关更多详细信息,请参阅[日志系统](../../administration/logs.html)和[日志记录基础结构](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#logging-infrastructure-overview) . + +## What data can be tracked[](#what-data-can-be-tracked "Permalink") + +我们不同的跟踪工具使我们能够跟踪不同类型的事件. 下面概述了事件类型和可以跟踪哪些数据的示例. + +| 事件类型 | 扫雪机 JS(前端) | 扫雪机 Ruby(后端) | 使用情况 | 数据库导入 | 日志系统 | +| --- | --- | --- | --- | --- | --- | +| 数据库计数 | | | | | | +| 浏览量事件 | | | | | | +| UI 事件 | | | | | | +| CRUD 和 API 事件 | | | | | | +| 活动渠道 | | | | | | +| PostgreSQL 数据 | | | | | | +| Logs | | | | | | +| 外部服务 | | | | | | + +### Database counts[](#database-counts "Permalink") + +* 唯一用户创建的项目数 +* Number of users logged in the past 28 day + +数据库计数是实例数据库中不同表的行计数. 这些是经过过滤,分组或聚合的 SQL 计数查询,可提供高级使用情况数据. 可用表的完整列表可以在[structure.sql 中](https://gitlab.com/gitlab-org/gitlab/-/blob/master/db/structure.sql)找到. + +### Pageview events[](#pageview-events "Permalink") + +* 访问/ dashboard / groups 页面的会话数 + +### UI Events[](#ui-events "Permalink") + +* 单击按钮或链接的会话数 +* 关闭模式的会话数 + +UI 事件是浏览器中任何界面驱动的动作,包括点击数据. + +### CRUD or API events[](#crud-or-api-events "Permalink") + +* Git 推送次数 +* GraphQL 查询数 +* 对 Rails 操作或控制器的请求数 + +这些是后端事件,包括记录的创建,读取,更新,删除以及其他可能从界面中可用层以外的层触发的事件. + +### Event funnels[](#event-funnels "Permalink") + +* 依次执行操作 A,B 和 C 的会话数 +* 从步骤 A 到步骤 B 的转化率 + +### PostgreSQL data[](#postgresql-data "Permalink") + +这些是原始数据库记录,可使用 Sisense 等商业智能工具进行浏览. 可用表的完整列表可以在[structure.sql 中](https://gitlab.com/gitlab-org/gitlab/-/blob/master/db/structure.sql)找到. + +### Logs[](#logs "Permalink") + +这些是原始日志,例如[生产日志](../../administration/logs.html#production_jsonlog) , [API 日志](../../administration/logs.html#api_jsonlog)或[Sidekiq 日志](../../administration/logs.html#sidekiqlog) . 有关更多详细信息,请参见[日志记录基础结构概述](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#logging-infrastructure-overview) . + +### External services[](#external-services "Permalink") + +这些是 GitLab 实例与之交互的外部服务,例如[外部存储提供程序](../../administration/static_objects_external_storage.html)或[外部容器注册表](../../administration/packages/container_registry.html#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint) . 这些服务必须能够将数据发送回 GitLab 实例,以便跟踪数据. + +## Telemetry systems overview[](#telemetry-systems-overview "Permalink") + +系统概述是一个简化的图,显示了 GitLab Inc 与自我管理实例之间的交互. + +[![Telemetry_Overview](img/1f5aad8fb69a4afb74547a2d31fcbc66.png)](../img/telemetry_system_overview.png) + +[Source file](https://app.diagrams.net/#G13DVpN-XnhWGz9tqReIj8pp1UE4ehk_EC) + +### GitLab Inc[](#gitlab-inc "Permalink") + +为了进行遥测,GitLab Inc 具有三个主要组件: + +1. [数据基础架构](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) :包含我们数据团队管理的所有内容,包括用于可视化的 Sisense 仪表板,用于数据仓库的 Snowflake,传入数据源(例如 PostgreSQL Pipeline 和 S3 Bucket)以及最后是数据收集器[GitLab.com 的 Snowplow Collector](https://about.gitlab.com/handbook/engineering/infrastructure/library/snowplow/)和 GitLab 的 Versions 应用程序. +2. GitLab.com:这是生产的 GitLab 应用程序,由客户端和服务器组成. 在客户端或浏览器端,使用 Snowplow JS 跟踪器(前端)来跟踪客户端事件. 在服务器或应用程序端,使用 Snowplow Ruby 跟踪器(后端)来跟踪服务器端事件. 该服务器还包含使用率 Ping,它利用 PostgreSQL 数据库和 Redis 内存数据存储来报告使用率数据. 最后,服务器还包含通过运行 GitLab 应用程序生成的系统日志. +3. [监视基础结构](https://about.gitlab.com/handbook/engineering/monitoring/) :这是用于确保 GitLab.com 正常运行的基础结构. 系统日志从 GitLab.com 发送到我们的监视基础结构,并由 FluentD 收集器收集. 从 FluentD,日志可以通过 Stackdriver 发送到长期的 Google Cloud Services 冷存储,或者通过 Cloud Pub / Sub 发送到我们的 Elastic Cluster,可以使用 Kibana 进行实时浏览. + +### Self-managed[](#self-managed "Permalink") + +出于遥测目的,自我管理实例具有两个主要组成部分: + +1. 数据基础结构:在自助式实例上,设置数据基础结构是可选的. 如果您想为自己管理的实例收集 Snowplow 跟踪事件,则可以设置自己的自我管理 Snowplow 收集器,并将 Snowplow 事件配置为指向自己的收集器. +2. GitLab:一个自我管理的 GitLab 实例包含与上述 GitLab.com 相同的所有组件. + +### Differences between GitLab Inc and Self-managed[](#differences-between-gitlab-inc-and-self-managed "Permalink") + +如橙色线所示,在 GitLab.com 上,Snowplow JS,Snowplow Ruby,Using Ping 和 PostgreSQL 数据库将所有流导入到 GitLab Inc 的数据基础结构中. 但是,在自我管理上,只有 Usage Ping 流入 GitLab Inc 的数据基础架构. + +如绿线所示,在 GitLab.com 上的系统日志流进入 GitLab Inc 的监视基础结构. 在自我管理下,没有日志发送到 GitLab Inc 的监视基础结构. + +GitLab.com 和自我管理之间的区别总结如下: + +| Environment | 扫雪机 JS(前端) | 扫雪机 Ruby(后端) | 使用情况 | 数据库导入 | 日志系统 | +| --- | --- | --- | --- | --- | --- | +| GitLab.com | | | | | | +| Self-Managed | (1) | (1) | | | | + +注意(1):Snowplow JS 和 Snowplow Ruby 在自我管理上可用,但是,Snowplow Collector 端点设置为 GitLab Inc 无法访问的自我管理 Snowplow Collector. + +## Snowflake data warehouse[](#snowflake-data-warehouse "Permalink") + +Snowflake 数据仓库是我们保存 GitLab Inc 所有数据的地方. + +### Data sources[](#data-sources "Permalink") + +Snowflake 和 Sisense 中有多个数据源可用,每个数据源代表沿转换管道的数据的不同视图. + +| Source | Description | Access | +| --- | --- | --- | +| raw | 这些表是原始数据源 | Access via Snowflake | +| analytics_staging | 这些表几乎没有经过任何数据转换,这意味着它们基本上是原始数据源的克隆. | 通过雪花或 Sisense 访问 | +| analytics | 这些表通常经历了更多的数据转换. 它们通常以`_xf`以表示它们已转换的事实 | 通过雪花或 Sisense 访问 | + +如果您是对原始数据感兴趣的产品经理,则可能会关注于`analytics`和`analytics_staging`源. 原始资源仅限于数据和基础架构团队. 有关更多信息,请参阅[产品经理数据:analytics_staging 和 analytics 之间有什么区别?](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/#whats-the-difference-between-analytics_staging-and-analytics) \ No newline at end of file diff --git a/_book/docs/576.md b/_book/docs/576.md new file mode 100644 index 0000000000000000000000000000000000000000..dbe4ed3fd0f0c044c9e50d6fd10f21c73cca4fb9 --- /dev/null +++ b/_book/docs/576.md @@ -0,0 +1,723 @@ +# Usage Ping Guide + +> 原文:[https://docs.gitlab.com/ee/development/telemetry/usage_ping.html](https://docs.gitlab.com/ee/development/telemetry/usage_ping.html) + +* [What is Usage Ping?](#what-is-usage-ping) + * [Why should we enable Usage Ping?](#why-should-we-enable-usage-ping) + * [Limitations](#limitations) +* [Usage Ping payload](#usage-ping-payload) +* [Disable Usage Ping](#disable-usage-ping) +* [Usage Ping request flow](#usage-ping-request-flow) +* [How Usage Ping works](#how-usage-ping-works) +* [Implementing Usage Ping](#implementing-usage-ping) + * [Why batch counting](#why-batch-counting) + * [Ordinary Batch Counters](#ordinary-batch-counters) + * [Distinct Batch Counters](#distinct-batch-counters) + * [Redis Counters](#redis-counters) + * [Alternative Counters](#alternative-counters) + * [Prometheus Queries](#prometheus-queries) +* [Developing and testing Usage Ping](#developing-and-testing-usage-ping) + * [1\. Use your Rails console to manually test counters](#1-use-your-rails-console-to-manually-test-counters) + * [2\. Generate the SQL query](#2-generate-the-sql-query) + * [3\. Optimize queries with #database-lab](#3-optimize-queries-with-database-lab) + * [4\. Add the metric definition](#4-add-the-metric-definition) + * [5\. Add new metric to Versions Application](#5-add-new-metric-to-versions-application) + * [6\. Add the feature label](#6-add-the-feature-label) + * [7\. Add a changelog file](#7-add-a-changelog-file) + * [8\. Ask for a Telemetry Review](#8-ask-for-a-telemetry-review) + * [Optional: Test Prometheus based Usage Ping](#optional-test-prometheus-based-usage-ping) + * [Test with an Omnibus container](#test-with-an-omnibus-container) + * [Test with GitLab development toolkits](#test-with-gitlab-development-toolkits) +* [Usage Statistics definitions](#usage-statistics-definitions) +* [Example Usage Ping payload](#example-usage-ping-payload) + +# Usage Ping Guide[](#usage-ping-guide "Permalink") + +版本历史 + +* 在 GitLab 企业版 8.10 中引入. +* 在 GitLab 企业版 8.12 中添加了更多统计信息. +* 在 9.1 中移至 GitLab Core. +* 在 GitLab Ultimate 11.2 中添加了更多统计信息. + +本指南介绍了用法 Ping 的用途及其实现方式. + +有关遥测的更多信息,请参见: + +* [Telemetry Guide](index.html) +* [Snowplow Guide](snowplow.html) + +更有用的链接: + +* [Telemetry Direction](https://about.gitlab.com/direction/telemetry/) +* [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/) +* [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/) +* [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) + +## What is Usage Ping?[](#what-is-usage-ping "Permalink") + +* GitLab 每周将包含使用情况数据的有效负载发送到 GitLabInc.用法 Ping 提供高级数据来帮助我们的产品,支持和销售团队. 它不发送任何项目名称,用户名或任何其他特定数据. 使用 ping 中的信息不是匿名的,它链接到实例的主机名. 发送使用情况 ping 是可选的,任何实例都可以禁用分析. +* 使用情况数据主要由实例数据库中不同表的行计数组成. 通过逐月比较这些计数(或逐周比较),我们可以大致了解实例如何使用产品中的不同功能. 除计数外,还收集了其他有助于我们分类和了解 GitLab 安装的事实. +* 使用 ping 对 GitLab 很重要,因为我们使用它来计算阶段每月活跃用户(SMAU),这有助于我们衡量阶段和功能的成功程度. +* 启用使用情况 ping 后,GitLab 将从其他实例收集数据,并能够向用户显示您实例的使用情况统计信息. + +### Why should we enable Usage Ping?[](#why-should-we-enable-usage-ping "Permalink") + +* 使用 Ping 的主要目的是构建更好的 GitLab. 收集有关如何使用 GitLab 的数据,以更好地了解功能/阶段的采用和使用情况,这有助于我们了解 GitLab 如何增加价值,并帮助我们的团队更好地了解人们使用 GitLab 的原因,并且借助这些知识,我们可以做得更好产品决策. +* 作为激活使用 ping 的一项好处,GitLab 可让您分析 GitLab 安装过程中用户的活动. +* 作为激活使用 ping 的一项好处,GitLab 为您提供了 DevOps 得分,它为您提供了从计划到监视整个实例对并发 DevOps 的采用情况的概述. +* 您将获得更好,更主动的支持. (假设我们的 TAM 和支持组织使用这些数据来提供更多价值) +* 您将获得有关如何从 GitLab 的投资中获得最大价值的见识和建议. 您是否不想知道组织中未采用许多功能或价值? +* 您将获得一份报告,说明如何与其他类似组织(匿名)进行比较,并提供有关如何改进 DevOps 流程的具体建议和建议. +* 默认情况下启用用法 Ping. 要禁用它,请参阅[禁用用法 Ping](#disable-usage-ping) . + +### Limitations[](#limitations "Permalink") + +* Usage Ping does not track frontend events things like page views, link clicks, or user sessions, and only focuses on aggregated backend events. +* 由于这些限制,我们建议使用 Snowplow 来对您的产品进行检测,以在 GitLab.com 上进行更详细的分析,并使用 Usage Ping 跟踪自我管理中的汇总后端事件. + +## Usage Ping payload[](#usage-ping-payload "Permalink") + +您可以在管理面板中查看发送到 GitLab Inc.的确切 JSON 有效负载. 要查看有效负载: + +1. 导航到" **管理区域">"设置">"度量标准和性能分析"** . +2. 展开**使用情况统计信息**部分. +3. 单击**预览有效负载**按钮. + +有关有效负载的示例,请参阅[示例用法 Ping 有效负载](#example-usage-ping-payload) . + +## Disable Usage Ping[](#disable-usage-ping "Permalink") + +要在 GitLab UI 中禁用"使用情况 Ping",请转到管理面板的**"设置"**页面,然后取消选中" **使用情况 Ping"**复选框. + +要禁用用法 Ping 并防止日后通过管理面板对其进行配置,Omnibus 安装可以在[`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html)设置以下[`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html) : + +``` +gitlab_rails['usage_ping_enabled'] = false +``` + +源代码安装可以在`gitlab.yml`设置以下`gitlab.yml` : + +``` +production: &base + # ... + gitlab: + # ... + usage_ping_enabled: false +``` + +## Usage Ping request flow[](#usage-ping-request-flow "Permalink") + +The following example shows a basic request/response flow between a GitLab instance, the Versions Application, the License Application, Salesforce, GitLab’s S3 Bucket, GitLab’s Snowflake Data Warehouse, and Sisense: + +sequenceDiagram 参与者 GitLab 实例参与者版本应用程序参与者许可证应用程序参与者 Salesforce 参与者 S3 存储桶参与者 Snowflake DW 参与者 Sisense 仪表板 GitLab 实例->>版本应用程序:发送使用情况 ping 循环流程使用情况数据版本应用程序->>版本应用程序:解析使用情况数据版本应用程序- >>版本应用程序:写入数据库版本应用程序->>版本应用程序:更新许可证 ping 超时循环 Salesforce 版本的过程数据 Application-xLicenses 应用程序:请求 Zuora 订阅 ID 许可证 Application-xVersions 应用程序:Zuora 订阅 ID 版本 Application-xSalesforce:通过 Zuora 订阅 ID 请求 Zuora 帐户 ID Salesforce-xVersions 应用程序:Zuora 帐户 ID 版本 Application-xSalesforce:Zuora 帐户最终版本的使用数据 Application->> S3 存储桶:导出版本数据库 S3 存储桶->>雪花 DW:导入数据 Snowflake DW->>雪花 DW:Trans 使用 dbt Snowflake DW->> Sisense 仪表板的表单数据:可用于查询版本 Application->> GitLab 实例的数据:DevOps 得分(会话开发索引) + +## How Usage Ping works[](#how-usage-ping-works "Permalink") + +1. 在 Sidekiq 中将 Usage Ping [cron 作业](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/gitlab_usage_ping_worker.rb#L30)设置为每周运行. +2. 当 cron 作业运行时,它将调用[`GitLab::UsageData.to_json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L22) . +3. `GitLab::UsageData.to_json` [级联](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L22)到`GitLab::UsageData.to_json` +其他计数器方法调用. +4. 所有方法调用的响应都在`GitLab::UsageData.to_json`中[合并](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L14)为一个 JSON 负载. +5. 然后将 JSON 有效负载[发布到 Versions 应用程序](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L20) . + +## Implementing Usage Ping[](#implementing-usage-ping "Permalink") + +Usage Ping consists of two kinds of data, counters and observations. Counters track how often a certain event happened over time, such as how many CI pipelines have run. They are monotonic and always trend up. Observations are facts collected from one or more GitLab instances and can carry arbitrary data. There are no general guidelines around how to collect those, due to the individual nature of that data. + +在`usage_data.rb`中可以找到四种类型的计数器: + +* **普通批处理计数器:**给定 ActiveRecord_Relation 的简单计数 +* **不同的批次计数器:**给定列上给定 ActiveRecord_Relation 的不同计数 +* **备用计数器:**用于设置和配置 +* **Redis 计数器:**用于内存中计数. 由于数据不正确,此方法已被弃用,并将由持久性方法代替. + +**注意:**仅使用提供的计数器方法. 每个计数器方法都包含一个内置的故障保险柜,用于隔离每个计数器,以避免破坏整个使用情况 Ping. + +### Why batch counting[](#why-batch-counting "Permalink") + +对于大型表,由于 MVCC [(多版本并发控制)](https://en.wikipedia.org/wiki/Multiversion_concurrency_control) ,PostgreSQL 可能需要很长时间才能对行进行计数. 批计数是一种将单个大型查询分解为多个较小查询的计数方法. 例如,您可以执行 100 个每个 10,000 条记录的查询,而不是一个查询 1,000,000 条记录并进行批处理的查询. 批计数对于避免数据库超时很有用,因为每个批查询都比一个长期运行的查询短得多. + +对于 GitLab.com,有非常大的表具有 15 秒的查询超时,因此我们使用批计数来避免遇到超时. 以下是一些 GitLab.com 表的大小: + +| Table | 行数百万 | +| --- | --- | +| `merge_request_diff_commits` | 2280 | +| `ci_build_trace_sections` | 1764 | +| `merge_request_diff_files` | 1082 | +| `events` | 514 | + +提供了两种批处理计数方法:" `Ordinary Batch Counters`和" `Distinct Batch Counters` . 批计数需要列上的索引来计算最大值,最小值和范围查询. 在某些情况下,可能需要在计数器涉及的列上添加专门的索引. + +### Ordinary Batch Counters[](#ordinary-batch-counters "Permalink") + +Handles `ActiveRecord::StatementInvalid` error + +给定 ActiveRecord_Relation 的简单计数 + +Method: `count(relation, column = nil, batch: true, start: nil, finish: nil)` + +Arguments: + +* `relation` ActiveRecord_Relation 以执行计数 +* `column`要执行计数的列,默认情况下是主键 +* `batch` :默认为`true`以便使用批次计数 +* `start` :批处理计数的自定义开始,以避免复杂的最小值计算 +* `end` :批处理计数的自定义结束,以避免复杂的最小值计算 + +Examples: + +``` +count(User.active) +count(::Clusters::Cluster.aws_installed.enabled, :cluster_id) +count(::Clusters::Cluster.aws_installed.enabled, :cluster_id, start: ::Clusters::Cluster.minimum(:id), finish: ::Clusters::Cluster.maximum(:id)) +``` + +### Distinct Batch Counters[](#distinct-batch-counters "Permalink") + +Handles `ActiveRecord::StatementInvalid` error + +给定列上给定 ActiveRecord_Relation 的不重复计数 + +Method: `distinct_count(relation, column = nil, batch: true, start: nil, finish: nil)` + +Arguments: + +* `relation` ActiveRecord_Relation 以执行计数 +* `column`该列执行非重复计数,默认情况下是主键 +* `batch` :默认为`true`以便使用批次计数 +* `start` :批处理计数的自定义开始,以避免复杂的最小值计算 +* `end` :批处理计数的自定义结束,以避免复杂的最小值计算 + +Examples: + +``` +distinct_count(::Project, :creator_id) +distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id)) +distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id') +``` + +### Redis Counters[](#redis-counters "Permalink") + +当发送一个块时,句柄`::Redis::CommandError`和`Gitlab::UsageDataCounters::BaseCounter::UnknownEvent`返回-1,或者在向`counter(Gitlab::UsageDataCounters)`发送不同行为时由于所有 2 个不同而返回具有所有值-1 的哈希 Redis 计数器的实现 + +Method: `redis_usage_data(counter, &block)` + +Arguments: + +* `counter` :来自`Gitlab::UsageDataCounters`的计数器,该计数器已实现`fallback_totals`方法 +* 或`block` :被评估 + +用法示例: + +``` +redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter) +redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] } +``` + +请注意,Redis 计数器正在[被弃用](https://gitlab.com/gitlab-org/gitlab/-/issues/216330) ,您应该改为尝试使用 Snowplow 事件. 我们正在构建[自我管理的事件跟踪](https://gitlab.com/gitlab-org/telemetry/-/issues/373) ,一旦可用,我们会将所有 Redis 计数器转换为 Snowplow 事件. + +### Alternative Counters[](#alternative-counters "Permalink") + +以这种方式处理`StandardError`并将后备值处理为-1,如果遇到一个异常,并非所有度量都会失败. 主要用于设置和配置. + +Method: `alt_usage_data(value = nil, fallback: -1, &block)` + +Arguments: + +* `value` :一个简单的静态值,在这种情况下,仅返回该值. +* 或`block` :被评估 +* `fallback: -1` :用于失败的任何度量的通用值. + +用法示例: + +``` +alt_usage_data { Gitlab::VERSION } +alt_usage_data { Gitlab::CurrentSettings.uuid } +alt_usage_data(999) +``` + +### Prometheus Queries[](#prometheus-queries "Permalink") + +在那些操作指标应成为 Usage Ping 一部分的情况下,数据库或 Redis 查询不太可能提供有用的数据. 取而代之的是,Prometheus 可能更合适,因为大多数 GitLab 的体系结构组件都会向其发布指标,这些指标可以查询,汇总并作为使用数据包含在内. + +**注意:** Prometheus 作为 Usage Ping 的数据源目前仅适用于运行[捆绑的 Prometheus](../../administration/monitoring/prometheus/index.html)实例的单节点 Omnibus 安装. + +为了查询 Prometheus 的度量标准,可以使用一个助手方法,该方法将`yield`一个完整配置的`PrometheusClient` ,前提是可以按照上述说明使用它: + +``` +with_prometheus_client do |client| + response = client.query('<your query>') + ... +end +``` + +请参阅[`PrometheusClient`定义,](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/prometheus_client.rb)以了解如何使用其 API 查询数据. + +## Developing and testing Usage Ping[](#developing-and-testing-usage-ping "Permalink") + +### 1\. Use your Rails console to manually test counters[](#1-use-your-rails-console-to-manually-test-counters "Permalink") + +``` +# count +Gitlab::UsageData.count(User.active) +Gitlab::UsageData.count(::Clusters::Cluster.aws_installed.enabled, :cluster_id) + +# count distinct +Gitlab::UsageData.distinct_count(::Project, :creator_id) +Gitlab::UsageData.distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id)) +``` + +### 2\. Generate the SQL query[](#2-generate-the-sql-query "Permalink") + +您的 Rails 控制台将返回生成的 SQL 查询. + +Example: + +``` +pry(main)> Gitlab::UsageData.count(User.active) + (2.6ms) SELECT "features"."key" FROM "features" + (15.3ms) SELECT MIN("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) + (2.4ms) SELECT MAX("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) + (1.9ms) SELECT COUNT("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) AND "users"."id" BETWEEN 1 AND 100000 +``` + +### 3\. Optimize queries with #database-lab[](#3-optimize-queries-with-database-lab "Permalink") + +将 SQL 查询粘贴到`#database-lab`以查看查询的大规模执行情况. + +* `#database-lab` is a Slack channel which uses a production-sized environment to test your queries. +* GitLab.com 的生产数据库有 15 秒的超时. +* 任何单个查询的冷缓存都必须保持在 1 秒以下的执行时间. +* 在涉及的列上添加专门的索引,以减少执行时间. + +为了了解查询的执行情况,我们在 MR 描述中添加了以下信息: + +* 对于具有`time_period`测试的计数器,我们添加了两种情况的信息: + * 所有时间段的`time_period = {}` + * `time_period = { created_at: 28.days.ago..Time.current }`最近 28 天的时间段 +* 优化前后的执行计划和查询时间 +* 查询生成的索引和时间 +* 上下执行的迁移输出 + +我们还使用`#database-lab`和[explain.depesz.com](https://explain.depesz.com/) . 有关更多详细信息,请参见[数据库查看指南](../database_review.html#preparation-when-adding-or-modifying-queries) . + +查询优化工作的示例: + +* [Example 1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26445) +* [Example 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26871) + +### 4\. Add the metric definition[](#4-add-the-metric-definition "Permalink") + +添加,更改或更新指标时,请更新[使用情况统计信息定义表](#usage-statistics-definitions) . + +### 5\. Add new metric to Versions Application[](#5-add-new-metric-to-versions-application "Permalink") + +检查是否需要将新指标添加到"版本应用程序". 请参见`usage_data` [模式](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L147)和已[接受的](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/app/services/usage_ping.rb)用法数据[参数](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/app/services/usage_ping.rb) . 在`counts`键下添加的所有度量标准都保存在`counts`列中. + +有关更多详细信息,请参见[将其他工具添加到"用法" Ping 的过程](https://about.gitlab.com/handbook/product/product-processes/#process-to-add-additional-instrumentation-to-the-usage-ping) . + +### 6\. Add the feature label[](#6-add-the-feature-label "Permalink") + +将`feature`标签添加到"合并请求"以获取新的"用法 Ping"度量. 这些是面向用户的更改,并且是扩展"用法" Ping 功能的一部分. + +### 7\. Add a changelog file[](#7-add-a-changelog-file "Permalink") + +确保您遵守[Changelog 条目指南](../changelog.html) . + +### 8\. Ask for a Telemetry Review[](#8-ask-for-a-telemetry-review "Permalink") + +在 GitLab.com 上,我们具有 DangerBot 设置来监视遥测相关文件,并且 DangerBot 将建议进行遥测. 在您的 MR 中提及`@gitlab-org/growth/telemetry/engineers`以进行审核. + +### Optional: Test Prometheus based Usage Ping[](#optional-test-prometheus-based-usage-ping "Permalink") + +如果提交的数据包含您要检查和验证的[从 Prometheus 查询的](#prometheus-queries)指标,则需要确保 Prometheus 服务器在本地运行,并且相应的 GitLab 组件正在向其导出指标. 如果您不需要测试来自 Prometheus 的数据,则无需采取任何进一步的措施,因为在没有运行 Prometheus 服务器的情况下,Using Ping 应该会正常降低性能. + +当前,存在三种可以将数据导出到 Prometheus 的组件,这些组件包括在 Useing Ping 中: + +* [`node_exporter`](https://github.com/prometheus/node_exporter)从主机导出节点指标 +* [`gitlab-exporter`](https://gitlab.com/gitlab-org/gitlab-exporter)从各种 GitLab 组件导出过程指标 +* 各种 GitLab 服务(例如 Sidekiq 和 Rails 服务器)可导出自己的指标 + +#### Test with an Omnibus container[](#test-with-an-omnibus-container "Permalink") + +这是测试基于 Prometheus 的用法 Ping 的推荐方法. + +验证更改的最简单方法是通过 CI 从代码分支构建新的 Omnibus 映像,然后下载该映像并运行本地容器实例: + +1. 在合并请求中,单击`qa`阶段,然后触发`package-and-qa`作业. 这项工作将触发[`omnibus-gitlab-mirror`项目](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/-/pipelines)的[下游管道中的](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/-/pipelines) Omnibus 构建. +2. 在下游管道中,等待`gitlab-docker`作业完成. +3. 打开作业日志,然后找到完整的容器名称(包括版本). 它将采用以下形式: `registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>` . +4. 在本地计算机上,确保您已登录到 GitLab Docker 注册表. 您可以在[向 GitLab 容器注册表](../../user/packages/container_registry/index.html#authenticating-to-the-gitlab-container-registry)进行[身份验证中](../../user/packages/container_registry/index.html#authenticating-to-the-gitlab-container-registry)找到有关此操作的说明. +5. 登录后,通过`docker pull registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>`下载新映像`docker pull registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>` +6. 有关在 Docker 中使用和运行 Omnibus GitLab 容器的更多信息,请参阅 Omnibus 文档中的[GitLab Docker 映像](https://docs.gitlab.com/omnibus/docker/README.html) . + +#### Test with GitLab development toolkits[](#test-with-gitlab-development-toolkits "Permalink") + +这是不建议使用的方法,因为在模拟实际的 GitLab 部署时会遇到很多困难. + +当前未将[GDK](https://gitlab.com/gitlab-org/gitlab-development-kit)设置为与其他 GitLab 组件一起运行 Prometheus 服务器或`node_exporter` . 如果您愿意,可以[使用 Prometheus 监控 GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/prometheus/index.md#monitoring-the-gdk-with-prometheus) . + +[GCK](https://gitlab.com/gitlab-org/gitlab-compose-kit)对测试基于 Prometheus 的 Useing Ping 的支持有限. 默认情况下,它已经带有完整配置的 Prometheus 服务,该服务设置为可刮除许多组件,但具有以下限制: + +* 它当前未运行`gitlab-exporter`实例,因此可能缺少诸如 Gitaly 之类的服务中的多个`process_*`指标. +* 当它运行`node_exporter` , `node_exporter` `docker-compose`服务会模拟主机,这意味着它通常会报告自身不与正在运行的任何其他服务关联. 这不是在生产设置中报告节点度量的方式,在生产设置中, `node_exporter`始终作为进程与任何给定节点上的其他 GitLab 组件一起运行. 从用法 Ping 的角度来看,没有节点数据因此似乎与任何正在运行的服务相关联,因为它们似乎都在不同的主机上运行. 为了缓解此问题, `node_exporter` GCK 中的`node_exporter`任意"分配"给了`web`服务,这意味着仅针对该服务的`node_*`指标将出现在"用法" Ping 中. + +## Usage Statistics definitions[](#usage-statistics-definitions "Permalink") + +| Statistic | Section | Stage | Tier | Edition | Description | +| --- | --- | --- | --- | --- | --- | +| `uuid` |   |   |   |   |   | +| `hostname` |   |   |   |   |   | +| `version` |   |   |   |   |   | +| `installation_type` |   |   |   |   |   | +| `active_user_count` |   |   |   |   |   | +| `recorded_at` |   |   |   |   |   | +| `recording_ce_finished_at` |   |   |   | CE+EE | 计算核心特征时 | +| `recording_ee_finished_at` |   |   |   | EE | 计算 EE 特定功能时 | +| `edition` |   |   |   |   |   | +| `license_md5` |   |   |   |   |   | +| `license_id` |   |   |   |   |   | +| `historical_max_users` |   |   |   |   |   | +| `Name` | `licensee` |   |   |   |   | +| `Email` | `licensee` |   |   |   |   | +| `Company` | `licensee` |   |   |   |   | +| `license_user_count` |   |   |   |   |   | +| `license_starts_at` |   |   |   |   |   | +| `license_expires_at` |   |   |   |   |   | +| `license_plan` |   |   |   |   |   | +| `license_trial` |   |   |   |   |   | +| `assignee_lists` | `counts` |   |   |   |   | +| `boards` | `counts` |   |   |   |   | +| `ci_builds` | `counts` | `verify` |   |   | 项目中独特的构建 | +| `ci_internal_pipelines` | `counts` | `verify` |   |   | GitLab 存储库中的管道总数 | +| `ci_external_pipelines` | `counts` | `verify` |   |   | 外部存储库中的总管道 | +| `ci_pipeline_config_auto_devops` | `counts` | `verify` |   |   | Auto DevOps 模板中的管道总数 | +| `ci_pipeline_config_repository` | `counts` | `verify` |   |   | 来自存储库中模板的管道总数 | +| `ci_runners` | `counts` | `verify` |   |   | 项目中已配置的跑步者总数 | +| `ci_triggers` | `counts` | `verify` |   |   | 项目中已配置的触发器总数 | +| `ci_pipeline_schedules` | `counts` | `verify` |   |   | GitLab 中的管道时间表 | +| `auto_devops_enabled` | `counts` | `configure` |   |   | 启用了 Auto DevOps 模板的项目 | +| `auto_devops_disabled` | `counts` | `configure` |   |   | 禁用了 Auto DevOps 模板的项目 | +| `deploy_keys` | `counts` |   |   |   |   | +| `deployments` | `counts` | `release` |   |   | 总部署 | +| `deployments` | `counts_monthly` | `release` |   |   | 最近 28 天的部署总数 | +| `dast_jobs` | `counts` |   |   |   |   | +| `successful_deployments` | `counts` | `release` |   |   | 成功部署总数 | +| `successful_deployments` | `counts_monthly` | `release` |   |   | 最近 28 天成功部署的总数 | +| `failed_deployments` | `counts` | `release` |   |   | 失败的部署总数 | +| `failed_deployments` | `counts_monthly` | `release` |   |   | 最近 28 天失败的部署总数 | +| `environments` | `counts` | `release` |   |   | 可用和停止的环境总数 | +| `clusters` | `counts` | `configure` |   |   | 启用和禁用的 GitLab 托管群集总数 | +| `clusters_enabled` | `counts` | `configure` |   |   | 当前启用的 GitLab 托管群集总数 | +| `project_clusters_enabled` | `counts` | `configure` |   |   | 附加到项目的 GitLab 托管集群总数 | +| `group_clusters_enabled` | `counts` | `configure` |   |   | 附加到组的 GitLab 托管集群总数 | +| `instance_clusters_enabled` | `counts` | `configure` |   |   | 附加到实例的 GitLab 托管群集总数 | +| `clusters_disabled` | `counts` | `configure` |   |   | GitLab 托管的禁用集群总数 | +| `project_clusters_disabled` | `counts` | `configure` |   |   | 以前附加到项目的 GitLab 托管的禁用集群总数 | +| `group_clusters_disabled` | `counts` | `configure` |   |   | 以前附加到组的 GitLab 托管的禁用集群总数 | +| `instance_clusters_disabled` | `counts` | `configure` |   |   | 先前附加到实例的 GitLab 托管的禁用集群总数 | +| `clusters_platforms_eks` | `counts` | `configure` |   |   | 在 AWS EKS 上通过 GitLab 设置的 GitLab 托管群集总数 | +| `clusters_platforms_gke` | `counts` | `configure` |   |   | 在 GCE GKE 上通过 GitLab 设置的 GitLab 托管群集总数 | +| `clusters_platforms_user` | `counts` | `configure` |   |   | 用户配置的 GitLab 托管群集总数 | +| `clusters_applications_helm` | `counts` | `configure` |   |   | 启用 Helm 的 GitLab 托管群集总数 | +| `clusters_applications_ingress` | `counts` | `configure` |   |   | 启用了 Ingress 的 GitLab 托管群集总数 | +| `clusters_applications_cert_managers` | `counts` | `configure` |   |   | 启用了 Cert Manager 的 GitLab 托管群集总数 | +| `clusters_applications_crossplane` | `counts` | `configure` |   |   | 启用了 Crossplane 的 GitLab 托管群集总数 | +| `clusters_applications_prometheus` | `counts` | `configure` |   |   | 启用 Prometheus 的 GitLab 托管群集总数 | +| `clusters_applications_runner` | `counts` | `configure` |   |   | 启用 Runner 的 GitLab 托管群集总数 | +| `clusters_applications_knative` | `counts` | `configure` |   |   | 启用了 Knative 的 GitLab 托管群集总数 | +| `clusters_applications_elastic_stack` | `counts` | `configure` |   |   | 启用了 Elastic Stack 的 GitLab 托管集群总数 | +| `clusters_applications_cilium` | `counts` | `configure` |   |   | 启用 Cilium 的 GitLab 托管群集总数 | +| `clusters_management_project` | `counts` | `configure` |   |   | 定义了集群管理项目的 GitLab 托管集群总数 | +| `in_review_folder` | `counts` |   |   |   |   | +| `grafana_integrated_projects` | `counts` |   |   |   |   | +| `groups` | `counts` |   |   |   |   | +| `issues` | `counts` |   |   |   |   | +| `issues_created_from_gitlab_error_tracking_ui` | `counts` | `monitor` |   |   |   | +| `issues_with_associated_zoom_link` | `counts` | `monitor` |   |   |   | +| `issues_using_zoom_quick_actions` | `counts` | `monitor` |   |   |   | +| `issues_with_embedded_grafana_charts_approx` | `counts` | `monitor` |   |   |   | +| `issues_with_health_status` | `counts` |   |   |   |   | +| `keys` | `counts` |   |   |   |   | +| `label_lists` | `counts` |   |   |   |   | +| `lfs_objects` | `counts` |   |   |   |   | +| `milestone_lists` | `counts` |   |   |   |   | +| `milestones` | `counts` |   |   |   |   | +| `pages_domains` | `counts` | `release` |   |   | GitLab 页面总数 | +| `pool_repositories` | `counts` |   |   |   |   | +| `projects` | `counts` |   |   |   |   | +| `projects_imported_from_github` | `counts` |   |   |   |   | +| `projects_with_repositories_enabled` | `counts` |   |   |   |   | +| `projects_with_error_tracking_enabled` | `counts` | `monitor` |   |   |   | +| `protected_branches` | `counts` |   |   |   |   | +| `releases` | `counts` | `release` |   |   | 独特的发行标签 | +| `remote_mirrors` | `counts` |   |   |   |   | +| `requirements_created` | `counts` |   |   |   |   | +| `snippets` | `counts` | ‘create’ |   | CE+EE |   | +| `snippets` | `counts_monthly` | ‘create’ |   | CE+EE |   | +| `personal_snippets` | `counts` | ‘create’ |   | CE+EE |   | +| `personal_snippets` | `counts_monthly` | ‘create’ |   | CE+EE |   | +| `project_snippets` | `counts` | ‘create’ |   | CE+EE |   | +| `project_snippets` | `counts_monthly` | ‘create’ |   | CE+EE |   | +| `suggestions` | `counts` |   |   |   |   | +| `todos` | `counts` |   |   |   |   | +| `uploads` | `counts` |   |   |   |   | +| `web_hooks` | `counts` |   |   |   |   | +| `projects_alerts_active` | `counts` |   |   |   |   | +| `projects_asana_active` | `counts` |   |   |   |   | +| `projects_assembla_active` | `counts` |   |   |   |   | +| `projects_bamboo_active` | `counts` |   |   |   |   | +| `projects_bugzilla_active` | `counts` |   |   |   |   | +| `projects_buildkite_active` | `counts` |   |   |   |   | +| `projects_campfire_active` | `counts` |   |   |   |   | +| `projects_custom_issue_tracker_active` | `counts` |   |   |   |   | +| `projects_discord_active` | `counts` |   |   |   |   | +| `projects_drone_ci_active` | `counts` |   |   |   |   | +| `projects_emails_on_push_active` | `counts` |   |   |   |   | +| `projects_external_wiki_active` | `counts` |   |   |   |   | +| `projects_flowdock_active` | `counts` |   |   |   |   | +| `projects_github_active` | `counts` |   |   |   |   | +| `projects_hangouts_chat_active` | `counts` |   |   |   |   | +| `projects_hipchat_active` | `counts` |   |   |   |   | +| `projects_irker_active` | `counts` |   |   |   |   | +| `projects_jenkins_active` | `counts` |   |   |   |   | +| `projects_jira_active` | `counts` |   |   |   |   | +| `projects_mattermost_active` | `counts` |   |   |   |   | +| `projects_mattermost_slash_commands_active` | `counts` |   |   |   |   | +| `projects_microsoft_teams_active` | `counts` |   |   |   |   | +| `projects_packagist_active` | `counts` |   |   |   |   | +| `projects_pipelines_email_active` | `counts` |   |   |   |   | +| `projects_pivotaltracker_active` | `counts` |   |   |   |   | +| `projects_prometheus_active` | `counts` |   |   |   |   | +| `projects_pushover_active` | `counts` |   |   |   |   | +| `projects_redmine_active` | `counts` |   |   |   |   | +| `projects_slack_active` | `counts` |   |   |   |   | +| `projects_slack_slash_commands_active` | `counts` |   |   |   |   | +| `projects_teamcity_active` | `counts` |   |   |   |   | +| `projects_unify_circuit_active` | `counts` |   |   |   |   | +| `projects_webex_teams_active` | `counts` |   |   |   |   | +| `projects_youtrack_active` | `counts` |   |   |   |   | +| `projects_jira_server_active` | `counts` |   |   |   |   | +| `projects_jira_cloud_active` | `counts` |   |   |   |   | +| `projects_jira_dvcs_cloud_active` | `counts` |   |   |   |   | +| `projects_jira_dvcs_server_active` | `counts` |   |   |   |   | +| `projects_jira_issuelist_active` | `counts` | `create` |   | EE | 总的 Jira Issue 功能已启用 | +| `labels` | `counts` |   |   |   |   | +| `merge_requests` | `counts` |   |   |   |   | +| `merge_requests_users` | `counts` |   |   |   |   | +| `notes` | `counts` |   |   |   |   | +| `wiki_pages_create` | `counts` |   |   |   |   | +| `wiki_pages_update` | `counts` |   |   |   |   | +| `wiki_pages_delete` | `counts` |   |   |   |   | +| `web_ide_commits` | `counts` |   |   |   |   | +| `web_ide_views` | `counts` |   |   |   |   | +| `web_ide_merge_requests` | `counts` |   |   |   |   | +| `web_ide_previews` | `counts` |   |   |   |   | +| `snippet_comment` | `counts` |   |   |   |   | +| `commit_comment` | `counts` |   |   |   |   | +| `merge_request_comment` | `counts` |   |   |   |   | +| `snippet_create` | `counts` |   |   |   |   | +| `snippet_update` | `counts` |   |   |   |   | +| `navbar_searches` | `counts` |   |   |   |   | +| `cycle_analytics_views` | `counts` |   |   |   |   | +| `productivity_analytics_views` | `counts` |   |   |   |   | +| `source_code_pushes` | `counts` |   |   |   |   | +| `merge_request_create` | `counts` |   |   |   |   | +| `design_management_designs_create` | `counts` |   |   |   |   | +| `design_management_designs_update` | `counts` |   |   |   |   | +| `design_management_designs_delete` | `counts` |   |   |   |   | +| `licenses_list_views` | `counts` |   |   |   |   | +| `user_preferences_group_overview_details` | `counts` |   |   |   |   | +| `user_preferences_group_overview_security_dashboard` | `counts` |   |   |   |   | +| `ingress_modsecurity_logging` | `counts` |   |   |   |   | +| `ingress_modsecurity_blocking` | `counts` |   |   |   |   | +| `ingress_modsecurity_disabled` | `counts` |   |   |   |   | +| `ingress_modsecurity_not_installed` | `counts` |   |   |   |   | +| `dependency_list_usages_total` | `counts` |   |   |   |   | +| `epics` | `counts` |   |   |   |   | +| `feature_flags` | `counts` |   |   |   |   | +| `geo_nodes` | `counts` | `geo` |   |   | 地理部署中的站点数 | +| `geo_event_log_max_id` | `counts` | `geo` |   |   | Geo 主数据库上的复制事件数 | +| `incident_issues` | `counts` | `monitor` |   |   | 警报机器人产生的问题 | +| `alert_bot_incident_issues` | `counts` | `monitor` |   |   | 警报机器人产生的问题 | +| `incident_labeled_issues` | `counts` | `monitor` |   |   | 事件标签有问题 | +| `issues_created_gitlab_alerts` | `counts` | `monitor` |   |   | 非警报机器人用户根据警报创建的问题 | +| `issues_created_manually_from_alerts` | `counts` | `monitor` |   |   | 非警报机器人用户根据警报创建的问题 | +| `issues_created_from_alerts` | `counts` | `monitor` |   |   | 从 Prometheus 和警报管理警报创建的问题 | +| `ldap_group_links` | `counts` |   |   |   |   | +| `ldap_keys` | `counts` |   |   |   |   | +| `ldap_users` | `counts` |   |   |   |   | +| `pod_logs_usages_total` | `counts` |   |   |   |   | +| `projects_enforcing_code_owner_approval` | `counts` |   |   |   |   | +| `projects_mirrored_with_pipelines_enabled` | `counts` | `release` |   |   | 启用了存储库镜像的项目 | +| `projects_reporting_ci_cd_back_to_github` | `counts` | `verify` |   |   | 启用 GitHub 服务管道的项目 | +| `projects_with_packages` | `counts` | `package` |   |   | 配置了程序包注册表的项目 | +| `projects_with_prometheus_alerts` | `counts` | `monitor` |   |   | 启用 Prometheus 警报的项目 | +| `projects_with_tracing_enabled` | `counts` | `monitor` |   |   | 启用了跟踪的项目 | +| `projects_with_alerts_service_enabled` | `counts` | `monitor` |   |   | 启用了警报服务的项目 | +| `template_repositories` | `counts` |   |   |   |   | +| `container_scanning_jobs` | `counts` |   |   |   |   | +| `dependency_scanning_jobs` | `counts` |   |   |   |   | +| `license_management_jobs` | `counts` |   |   |   |   | +| `sast_jobs` | `counts` |   |   |   |   | +| `status_page_projects` | `counts` | `monitor` |   |   | 启用状态页的项目 | +| `status_page_issues` | `counts` | `monitor` |   |   | 发布到状态页面的问题 | +| `status_page_incident_publishes` | `counts` | `monitor` |   |   | 发布操作的使用累计次数 | +| `status_page_incident_unpublishes` | `counts` | `monitor` |   |   | 未发布操作的累计使用次数 | +| `epics_deepest_relationship_level` | `counts` |   |   |   |   | +| `operations_dashboard_default_dashboard` | `counts` | `monitor` |   |   | 启用了操作面板的活跃用户 | +| `operations_dashboard_users_with_projects_added` | `counts` | `monitor` |   |   | 在操作仪表板上具有项目的活跃用户 | +| `container_registry_enabled` |   |   |   |   |   | +| `dependency_proxy_enabled` |   |   |   |   |   | +| `gitlab_shared_runners_enabled` |   |   |   |   |   | +| `gravatar_enabled` |   |   |   |   |   | +| `ldap_enabled` |   |   |   |   |   | +| `mattermost_enabled` |   |   |   |   |   | +| `omniauth_enabled` |   |   |   |   |   | +| `prometheus_enabled` |   |   |   |   | 捆绑的 Prometheus 是否已启用 | +| `prometheus_metrics_enabled` |   |   |   |   |   | +| `reply_by_email_enabled` |   |   |   |   |   | +| `average` | `avg_cycle_analytics - code` |   |   |   |   | +| `sd` | `avg_cycle_analytics - code` |   |   |   |   | +| `missing` | `avg_cycle_analytics - code` |   |   |   |   | +| `average` | `avg_cycle_analytics - test` |   |   |   |   | +| `sd` | `avg_cycle_analytics - test` |   |   |   |   | +| `missing` | `avg_cycle_analytics - test` |   |   |   |   | +| `average` | `avg_cycle_analytics - review` |   |   |   |   | +| `sd` | `avg_cycle_analytics - review` |   |   |   |   | +| `missing` | `avg_cycle_analytics - review` |   |   |   |   | +| `average` | `avg_cycle_analytics - staging` |   |   |   |   | +| `sd` | `avg_cycle_analytics - staging` |   |   |   |   | +| `missing` | `avg_cycle_analytics - staging` |   |   |   |   | +| `average` | `avg_cycle_analytics - production` |   |   |   |   | +| `sd` | `avg_cycle_analytics - production` |   |   |   |   | +| `missing` | `avg_cycle_analytics - production` |   |   |   |   | +| `total` | `avg_cycle_analytics` |   |   |   |   | +| `g_analytics_contribution` | `analytics_unique_visits` | `manage` |   |   | 访问/ groups /:group /-/ contribution_analytics | +| `g_analytics_insights` | `analytics_unique_visits` | `manage` |   |   | 访问/ groups /:group /-/ insights | +| `g_analytics_issues` | `analytics_unique_visits` | `manage` |   |   | 访问/ groups /:group /-/ issues_analytics | +| `g_analytics_productivity` | `analytics_unique_visits` | `manage` |   |   | 访问/ groups /:group /-/ a​​nalytics / productivity_analytics | +| `g_analytics_valuestream` | `analytics_unique_visits` | `manage` |   |   | 访问/ groups /:group /-/ a​​nalytics / value_stream_analytics | +| `p_analytics_pipelines` | `analytics_unique_visits` | `manage` |   |   | 访问/:group /:project / pipelines / chart | +| `p_analytics_code_reviews` | `analytics_unique_visits` | `manage` |   |   | 访问/:group /:project /-/ a​​nalytics / code_reviews | +| `p_analytics_valuestream` | `analytics_unique_visits` | `manage` |   |   | 访问/:group /:project /-/ value_stream_analytics | +| `p_analytics_insights` | `analytics_unique_visits` | `manage` |   |   | 访问/:group /:project / insights | +| `p_analytics_issues` | `analytics_unique_visits` | `manage` |   |   | 访问/:group /:project /-/ a​​nalytics / issues_analytics | +| `p_analytics_repo` | `analytics_unique_visits` | `manage` |   |   | 访问/:group /:project /-/ graphs / master / charts | +| `u_analytics_todos` | `analytics_unique_visits` | `manage` |   |   | 访问/ dashboard / todos | +| `i_analytics_cohorts` | `analytics_unique_visits` | `manage` |   |   | 访问/-/ instance_statistics /群组 | +| `i_analytics_dev_ops_score` | `analytics_unique_visits` | `manage` |   |   | 访问/-/ instance_statistics / dev_ops_score | +| `analytics_unique_visits_for_any_target` | `analytics_unique_visits` | `manage` |   |   | 访问上面列出的任何页面 | +| `clusters_applications_cert_managers` | `usage_activity_by_stage` | `configure` |   | CE+EE | 启用了证书管理器的唯一集群 | +| `clusters_applications_helm` | `usage_activity_by_stage` | `configure` |   | CE+EE | 启用 Helm 的独特集群 | +| `clusters_applications_ingress` | `usage_activity_by_stage` | `configure` |   | CE+EE | 启用了 Ingress 的唯一集群 | +| `clusters_applications_knative` | `usage_activity_by_stage` | `configure` |   | CE+EE | 启用 Knative 的唯一集群 | +| `clusters_management_project` | `usage_activity_by_stage` | `configure` |   | CE+EE | 启用项目管理的独特集群 | +| `clusters_disabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 非" GitLab 托管群集"总数 | +| `clusters_enabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | GitLab 托管群集总数 | +| `clusters_platforms_gke` | `usage_activity_by_stage` | `configure` |   | CE+EE | 安装了 Google Cloud 的独特集群 | +| `clusters_platforms_eks` | `usage_activity_by_stage` | `configure` |   | CE+EE | 安装了 AWS 的唯一集群 | +| `clusters_platforms_user` | `usage_activity_by_stage` | `configure` |   | CE+EE | 用户提供的唯一集群 | +| `instance_clusters_disabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 实例上禁用了唯一集群 | +| `instance_clusters_enabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 在实例上启用了唯一集群 | +| `group_clusters_disabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 组上禁用了唯一集群 | +| `group_clusters_enabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 在组上启用了唯一集群 | +| `project_clusters_disabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 项目上禁用了唯一集群 | +| `project_clusters_enabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 在项目上启用了唯一集群 | +| `projects_slack_notifications_active` | `usage_activity_by_stage` | `configure` |   | EE | 启用了 Slack 服务的独特项目 | +| `projects_slack_slash_active` | `usage_activity_by_stage` | `configure` |   | EE | 启用了 Slack'/'命令的独特项目 | +| `projects_with_prometheus_alerts` | `usage_activity_by_stage` | `configure` |   | EE | 启用 Prometheus 且没有警报的项目 | +| `deploy_keys` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `keys` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `merge_requests` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `projects_with_disable_overriding_approvers_per_merge_request` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `projects_without_disable_overriding_approvers_per_merge_request` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `remote_mirrors` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `snippets` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `merge_requests_users` | `usage_activity_by_stage_monthly` | `create` |   | CE+EE | 使用合并请求的唯一用户数 | +| `action_monthly_active_users_project_repo` | `usage_activity_by_stage_monthly` | `create` |   | CE+EE | 推送到项目存储库的唯一用户数 | +| `action_monthly_active_users_design_management` | `usage_activity_by_stage_monthly` | `create` |   | CE+EE | 与设计系统管理进行交互的唯一用户数 | +| `action_monthly_active_users_wiki_repo` | `usage_activity_by_stage_monthly` | `create` |   | CE+EE | 创建或更新 Wiki 存储库的用户的唯一数量 | +| `projects_enforcing_code_owner_approval` | `usage_activity_by_stage` | `create` |   | EE |   | +| `merge_requests_with_optional_codeowners` | `usage_activity_by_stage` | `create` |   | EE |   | +| `merge_requests_with_required_codeowners` | `usage_activity_by_stage` | `create` |   | EE |   | +| `projects_imported_from_github` | `usage_activity_by_stage` | `create` |   | EE |   | +| `projects_with_repositories_enabled` | `usage_activity_by_stage` | `create` |   | EE |   | +| `protected_branches` | `usage_activity_by_stage` | `create` |   | EE |   | +| `suggestions` | `usage_activity_by_stage` | `create` |   | EE |   | +| `approval_project_rules` | `usage_activity_by_stage` | `create` |   | EE | 项目批准规则数 | +| `approval_project_rules_with_target_branch` | `usage_activity_by_stage` | `create` |   | EE | 具有非默认目标分支的项目批准规则的数量 | +| `merge_requests_with_added_rules` | `usage_activity_by_stage` | `create` |   | EE | 合并带有附加规则的请求 | +| `clusters` | `usage_activity_by_stage` | `monitor` |   | CE+EE |   | +| `clusters_applications_prometheus` | `usage_activity_by_stage` | `monitor` |   | CE+EE |   | +| `operations_dashboard_default_dashboard` | `usage_activity_by_stage` | `monitor` |   | CE+EE |   | +| `operations_dashboard_users_with_projects_added` | `usage_activity_by_stage` | `monitor` |   | EE |   | +| `projects_prometheus_active` | `usage_activity_by_stage` | `monitor` |   | EE |   | +| `projects_with_error_tracking_enabled` | `usage_activity_by_stage` | `monitor` |   | EE |   | +| `projects_with_tracing_enabled` | `usage_activity_by_stage` | `monitor` |   | EE |   | +| `events` | `usage_activity_by_stage` | `manage` |   | CE+EE |   | +| `groups` | `usage_activity_by_stage` | `manage` |   | CE+EE |   | +| `users_created_at` | `usage_activity_by_stage` | `manage` |   | CE+EE |   | +| `omniauth_providers` | `usage_activity_by_stage` | `manage` |   | CE+EE |   | +| `ldap_keys` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `ldap_users` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `value_stream_management_customized_group_stages` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `projects_with_compliance_framework` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `ldap_servers` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `ldap_group_sync_enabled` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `ldap_admin_sync_enabled` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `group_saml_enabled` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `issues` | `usage_activity_by_stage` | `plan` |   | CE+EE |   | +| `notes` | `usage_activity_by_stage` | `plan` |   | CE+EE |   | +| `projects` | `usage_activity_by_stage` | `plan` |   | CE+EE |   | +| `todos` | `usage_activity_by_stage` | `plan` |   | CE+EE |   | +| `assignee_lists` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `epics` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `label_lists` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `milestone_lists` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `projects_jira_active` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `projects_jira_dvcs_server_active` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `projects_jira_dvcs_server_active` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `service_desk_enabled_projects` | `usage_activity_by_stage` | `plan` |   | CE+EE |   | +| `service_desk_issues` | `usage_activity_by_stage` | `plan` |   | CE+EE |   | +| `deployments` | `usage_activity_by_stage` | `release` |   | CE+EE | 总部署 | +| `failed_deployments` | `usage_activity_by_stage` | `release` |   | CE+EE | 失败的部署总数 | +| `projects_mirrored_with_pipelines_enabled` | `usage_activity_by_stage` | `release` |   | EE | 启用了存储库镜像的项目 | +| `releases` | `usage_activity_by_stage` | `release` |   | CE+EE | 项目中的唯一发行标签 | +| `successful_deployments` | `usage_activity_by_stage` | `release` |   | CE+EE | 成功部署总数 | +| `user_preferences_group_overview_security_dashboard` | `usage_activity_by_stage` | `secure` |   |   |   | +| `ci_builds` | `usage_activity_by_stage` | `verify` |   | CE+EE | 项目中独特的构建 | +| `ci_external_pipelines` | `usage_activity_by_stage` | `verify` |   | CE+EE | 外部存储库中的总管道 | +| `ci_internal_pipelines` | `usage_activity_by_stage` | `verify` |   | CE+EE | GitLab 存储库中的管道总数 | +| `ci_pipeline_config_auto_devops` | `usage_activity_by_stage` | `verify` |   | CE+EE | Auto DevOps 模板中的管道总数 | +| `ci_pipeline_config_repository` | `usage_activity_by_stage` | `verify` |   | CE+EE | 来自存储库中模板的管道 | +| `ci_pipeline_schedules` | `usage_activity_by_stage` | `verify` |   | CE+EE | GitLab 中的管道时间表 | +| `ci_pipelines` | `usage_activity_by_stage` | `verify` |   | CE+EE | 总管道 | +| `ci_triggers` | `usage_activity_by_stage` | `verify` |   | CE+EE | 触发已启用 | +| `clusters_applications_runner` | `usage_activity_by_stage` | `verify` |   | CE+EE | 启用 Runner 的独特集群 | +| `projects_reporting_ci_cd_back_to_github` | `usage_activity_by_stage` | `verify` |   | EE | 启用 GitHub 管道的独特项目 | +| `merge_requests_users` | `usage_activity_by_stage_monthly` | `create` |   |   | 使用合并请求的唯一用户数 | +| `duration_s` | `topology` | `enablement` |   |   | 收集拓扑数据所需的时间 | +| `application_requests_per_hour` | `topology` | `enablement` |   |   | 每小时对 Web 应用程序的请求数 | +| `failures` | `topology` | `enablement` |   |   | 包含有关失败查询的信息 | +| `nodes` | `topology` | `enablement` |   |   | 运行 GitLab 组件的服务器节点列表 | +| `node_memory_total_bytes` | `topology > nodes` | `enablement` |   |   | 该节点的总可用内存 | +| `node_cpus` | `topology > nodes` | `enablement` |   |   | 该节点的 CPU 核心数 | +| `node_uname_info` | `topology > nodes` | `enablement` |   |   | 有关此节点的基本硬件体系结构和 OS 发行信息 | +| `node_services` | `topology > nodes` | `enablement` |   |   | 在此节点上运行的 GitLab 服务列表 | +| `name` | `topology > nodes > node_services` | `enablement` |   |   | 在此节点上运行的 GitLab 服务的名称 | +| `process_count` | `topology > nodes > node_services` | `enablement` |   |   | 为此服务运行的进程数 | +| `process_memory_rss` | `topology > nodes > node_services` | `enablement` |   |   | 服务流程的平均居民集大小 | +| `process_memory_uss` | `topology > nodes > node_services` | `enablement` |   |   | 服务流程的平均唯一集大小 | +| `process_memory_pss` | `topology > nodes > node_services` | `enablement` |   |   | 服务流程的平均比例集大小 | +| `server` | `topology > nodes > node_services` | `enablement` |   |   | 使用的 Web 服务器类型(Unicorn 或 Puma) | +| `network_policy_forwards` | `counts` | `defend` |   | EE | 容器网络转发的数据包的累积计数 | +| `network_policy_drops` | `counts` | `defend` |   | EE | 容器网络丢弃的数据包的累积计数 | + +## Example Usage Ping payload[](#example-usage-ping-payload "Permalink") + +以下是用法 Ping 有效内容的示例内容. + +``` +{ "uuid": "0000000-0000-0000-0000-000000000000", "hostname": "example.com", "version": "12.10.0-pre", "installation_type": "omnibus-gitlab", "active_user_count": 999, "recorded_at": "2020-04-17T07:43:54.162+00:00", "edition": "EEU", "license_md5": "00000000000000000000000000000000", "license_id": null, "historical_max_users": 999, "licensee": { "Name": "ABC, Inc.", "Email": "email@example.com", "Company": "ABC, Inc." }, "license_user_count": 999, "license_starts_at": "2020-01-01", "license_expires_at": "2021-01-01", "license_plan": "ultimate", "license_add_ons": { }, "license_trial": false, "counts": { "assignee_lists": 999, "boards": 999, "ci_builds": 999, ... }, "container_registry_enabled": true, "dependency_proxy_enabled": false, "gitlab_shared_runners_enabled": true, "gravatar_enabled": true, "influxdb_metrics_enabled": true, "ldap_enabled": false, "mattermost_enabled": false, "omniauth_enabled": true, "prometheus_enabled": false, "prometheus_metrics_enabled": false, "reply_by_email_enabled": "incoming+%{key}@incoming.gitlab.com", "signup_enabled": true, "web_ide_clientside_preview_enabled": true, "ingress_modsecurity_enabled": true, "projects_with_expiration_policy_disabled": 999, "projects_with_expiration_policy_enabled": 999, ... "elasticsearch_enabled": true, "license_trial_ends_on": null, "geo_enabled": false, "git": { "version": { "major": 2, "minor": 26, "patch": 1 } }, "gitaly": { "version": "12.10.0-rc1-93-g40980d40", "servers": 56, "clusters": 14, "filesystems": [ "EXT_2_3_4" ] }, "gitlab_pages": { "enabled": true, "version": "1.17.0" }, "database": { "adapter": "postgresql", "version": "9.6.15" }, "app_server": { "type": "console" }, "avg_cycle_analytics": { "issue": { "average": 999, "sd": 999, "missing": 999 }, "plan": { "average": null, "sd": 999, "missing": 999 }, "code": { "average": null, "sd": 999, "missing": 999 }, "test": { "average": null, "sd": 999, "missing": 999 }, "review": { "average": null, "sd": 999, "missing": 999 }, "staging": { "average": null, "sd": 999, "missing": 999 }, "production": { "average": null, "sd": 999, "missing": 999 }, "total": 999 }, "analytics_unique_visits": { "g_analytics_contribution": 999, ... }, "usage_activity_by_stage": { "configure": { "project_clusters_enabled": 999, ... }, "create": { "merge_requests": 999, ... }, "manage": { "events": 999, ... }, "monitor": { "clusters": 999, ... }, "package": { "projects_with_packages": 999 }, "plan": { "issues": 999, ... }, "release": { "deployments": 999, ... }, "secure": { "user_container_scanning_jobs": 999, ... }, "verify": { "ci_builds": 999, ... } }, "usage_activity_by_stage_monthly": { "configure": { "project_clusters_enabled": 999, ... }, "create": { "merge_requests": 999, ... }, "manage": { "events": 999, ... }, "monitor": { "clusters": 999, ... }, "package": { "projects_with_packages": 999 }, "plan": { "issues": 999, ... }, "release": { "deployments": 999, ... }, "secure": { "user_container_scanning_jobs": 999, ... }, "verify": { "ci_builds": 999, ... } }, "topology": { "duration_s": 0.013836685999194742, "application_requests_per_hour": 4224, "failures": [], "nodes": [ { "node_memory_total_bytes": 33269903360, "node_cpus": 16, "node_uname_info": { "machine": "x86_64", "sysname": "Linux", "release": "4.19.76-linuxkit" }, "node_services": [ { "name": "web", "process_count": 16, "process_memory_pss": 233349888, "process_memory_rss": 788220927, "process_memory_uss": 195295487, "server": "puma" }, { "name": "sidekiq", "process_count": 1, "process_memory_pss": 734080000, "process_memory_rss": 750051328, "process_memory_uss": 731533312 }, ... ], ... }, ... ] } } +``` \ No newline at end of file diff --git a/_book/docs/577.md b/_book/docs/577.md new file mode 100644 index 0000000000000000000000000000000000000000..988544aff998db9dafc1b006d218bbacd5d24671 --- /dev/null +++ b/_book/docs/577.md @@ -0,0 +1,396 @@ +# Snowplow Guide + +> 原文:[https://docs.gitlab.com/ee/development/telemetry/snowplow.html](https://docs.gitlab.com/ee/development/telemetry/snowplow.html) + +* [What is Snowplow](#what-is-snowplow) +* [Snowplow schema](#snowplow-schema) +* [Enabling Snowplow](#enabling-snowplow) +* [Snowplow request flow](#snowplow-request-flow) +* [Implementing Snowplow JS (Frontend) tracking](#implementing-snowplow-js-frontend-tracking) + * [Tracking in HAML (or Vue Templates)](#tracking-in-haml-or-vue-templates) + * [Tracking within Vue components](#tracking-within-vue-components) + * [Tracking in raw JavaScript](#tracking-in-raw-javascript) + * [Tests and test helpers](#tests-and-test-helpers) +* [Implementing Snowplow Ruby (Backend) tracking](#implementing-snowplow-ruby-backend-tracking) + * [Performance](#performance) +* [Developing and testing Snowplow](#developing-and-testing-snowplow) + * [Snowplow Analytics Debugger Chrome Extension](#snowplow-analytics-debugger-chrome-extension) + * [Snowplow Inspector Chrome Extension](#snowplow-inspector-chrome-extension) + * [Snowplow Micro](#snowplow-micro) + * [Snowplow Mini](#snowplow-mini) + +# Snowplow Guide[](#snowplow-guide "Permalink") + +本指南概述了 Snowplow 的工作原理以及实施细节. + +有关遥测的更多信息,请参见: + +* [Telemetry Guide](index.html) +* [Usage Ping Guide](usage_ping.html) + +更有用的链接: + +* [Telemetry Direction](https://about.gitlab.com/direction/telemetry/) +* [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/) +* [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/) +* [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) + +## What is Snowplow[](#what-is-snowplow "Permalink") + +Snowplow 是企业级营销和产品分析平台,可帮助跟踪用户与我们的网站和应用程序互动的方式. + +[扫雪机](https://github.com/snowplow/snowplow)由以下松耦合子系统组成: + +* **Trackers** fire Snowplow events. Snowplow has 12 trackers, covering web, mobile, desktop, server, and IoT. +* **收集器**从跟踪**器**接收 Snowplow 事件. 我们有三个不同的事件收集器,可将事件同步到 Amazon S3,Apache Kafka 或 Amazon Kinesis. +* **Enrich**清理原始的 Snowplow 事件,丰富它们并将其存储. 我们有一个基于 Hadoop 的扩充流程,以及一个基于 Kinesis 或基于 Kafka 的流程. +* 扫雪机事件所在的位置是**存储** . 我们将 Snowplow 事件存储在 S3 上的平面文件结构中以及 Redshift 和 PostgreSQL 数据库中. +* **数据建模**是将事件级别的数据与其他数据集合并在一起,并聚合为较小的数据集,然后应用业务逻辑. 这将产生一组干净的表,从而使对数据的分析更加容易. 我们有 Redshift 和 Looker 的数据模型. +* 在 Snowplow 事件或汇总表上执行**分析** . + +[![snowplow_flow](img/d366ea5b34fa89da8adbcbd7ec51bc2a.png)](../img/snowplow_flow.png) + +## Snowplow schema[](#snowplow-schema "Permalink") + +我们有 Snowplow 模式的许多定义. 我们有一个积极的问题要[对此模式](https://gitlab.com/gitlab-org/gitlab/-/issues/207930)进行[标准化,](https://gitlab.com/gitlab-org/gitlab/-/issues/207930)包括以下定义: + +* 前端和后端分类法如下所示 +* [Feature instrumentation taxonomy](https://about.gitlab.com/handbook/product/product-processes/#taxonomy) +* [Self describing events](https://github.com/snowplow/snowplow/wiki/Custom-events#self-describing-events) +* [Iglu schema](https://gitlab.com/gitlab-org/iglu/) +* [Snowplow authored events](https://github.com/snowplow/snowplow/wiki/Snowplow-authored-events) + +## Enabling Snowplow[](#enabling-snowplow "Permalink") + +可以在以下位置启用跟踪: + +* 实例级别,可以在前端层和后端层上进行跟踪. +* 用户级别,尽管可以按用户禁用用户跟踪. GitLab 跟踪遵循["不跟踪"](https://www.eff.org/issues/do-not-track)标准,因此不会在用户级别跟踪浏览器中启用了"不跟踪"选项的任何用户. + +我们将 Snowplow 用作大多数跟踪策略,并且已在 GitLab.com 上启用了它. 在自我管理的实例上,可以通过导航到以下地址来启用 Snowplow: + +* 用户界面中的**管理区域>设置>集成** . +* 浏览器中的`admin/application_settings/integrations` . + +需要以下配置: + +| Name | Value | +| --- | --- | +| Collector | `snowplow.trx.gitlab.net` | +| Site ID | `gitlab` | +| Cookie 域 | `.gitlab.com` | + +## Snowplow request flow[](#snowplow-request-flow "Permalink") + +下面的示例显示以下组件之间的基本请求/响应流: + +* GitLab.com 上的 Snowplow JS / Ruby Trackers +* [GitLab.com Snowplow Collector](https://gitlab.com/gitlab-com/gl-infra/readiness/-/blob/master/library/snowplow/index.md) +* 亚搏体育 app 的 S3 桶 +* GitLab 的 Snowflake 数据仓库 +* Sisense: + +sequenceDiagram 参与者 Snowplow JS(前端)参与者 Snowplow Ruby(后端)参与者 GitLab.com Snowplow Collector 参与者 S3 Bucket 参与者 Snowflake DW 参与者 Sisense Dashboards Snowplow JS(前端)->> GitLab.com Snowplow Collector:FE 跟踪事件 Snowplow Ruby(后端) ->> GitLab.com Snowplow 收集器:使用 Kinesis Stream 跟踪事件循环过程 GitLab.com Snowplow 收集器->> GitLab.com Snowplow 收集器:记录原始事件 GitLab.com Snowplow 收集器->> GitLab.com Snowplow 收集器:丰富事件 GitLab.com 扫雪机-> GitLab.com 扫雪机:写入磁盘端 GitLab.com 扫雪机->> S3 桶:K​​inesis Firehose S3 桶->>雪花 DW:导入数据 Snowflake DW->> Snowflake DW:转换 dbt Snowflake DW->> Sisense 仪表盘获取数据:可用于查询的数据 + +## Implementing Snowplow JS (Frontend) tracking[](#implementing-snowplow-js-frontend-tracking "Permalink") + +GitLab 提供了`Tracking` ,该接口包装了[Snowplow JavaScript Tracker](https://github.com/snowplow/snowplow/wiki/javascript-tracker)以跟踪自定义事件. 有几种利用跟踪的方法,但是每种方法通常至少需要一个`category`和一个`action` . 可以提供符合我们[功能仪表分类法的](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)其他数据. + +| field | type | 默认值 | description | +| --- | --- | --- | --- | +| `category` | string | document.body.dataset.page | 在其中捕获事件的页面或页面的子部分. | +| `action` | string | ‘generic’ | 用户正在采取的行动. 单击应该是`click` ,应该`activate` ,因此,例如,聚焦表单字段将是`activate_form_input` ,单击按钮将是`click_button` . | +| `data` | object | {} | 如[我们的功能仪表分类法中](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)所述的其他数据,例如`label` , `property` , `value`和`context` . | + +### Tracking in HAML (or Vue Templates)[](#tracking-in-haml-or-vue-templates "Permalink") + +在 HAML(或 Vue 模板)中工作时,我们可以向感兴趣的元素添加`data-track-*`属性. 具有`data-track-event`属性的所有元素都会自动对点击绑定事件跟踪. + +以下是分配给按钮的`data-track-*`属性的示例: + +``` +%button.btn{ data: { track: { event: "click_button", label: "template_preview", property: "my-template" } } } +``` + +``` +<button class="btn" + data-track-event="click_button" + data-track-label="template_preview" + data-track-property="my-template" +/> +``` + +事件侦听器在文档级别绑定,以处理具有这些数据属性的元素上或元素内的单击事件. 这样可以在重新渲染和更改 DOM 时正确处理它们. 请注意,由于绑定了这些事件的方式,不应阻止 click 事件传播 DOM 树. 如果出于某种原因阻止了点击事件的传播,则需要实现自己的侦听器,并按照[原始 JavaScript](#tracking-in-raw-javascript)中的[跟踪中](#tracking-in-raw-javascript)的说明进行操作. + +Below is a list of supported `data-track-*` attributes: + +| attribute | required | description | +| --- | --- | --- | +| `data-track-event` | true | 用户正在采取的行动. 点击次数必须预先考虑`click`并激活必须预先考虑`activate` . 例如,聚焦表单字段将是`activate_form_input` ,单击按钮将是`click_button` . | +| `data-track-label` | false | 如[我们的功能仪表分类中](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)所述的`label` . | +| `data-track-property` | false | 如[我们的功能仪表分类中](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)所述的`property` . | +| `data-track-value` | false | [我们的功能仪表分类法中](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)描述的`value` . 如果省略,则为元素的`value`属性或空字符串. 对于复选框,默认值为元素的选中属性,否则为`false` . | +| `data-track-context` | false | [我们的功能仪表分类法中](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)描述的`context` . | + +### Tracking within Vue components[](#tracking-within-vue-components "Permalink") + +如果需要更复杂的跟踪,可以在组件中使用跟踪 Vue mixin. 要使用它,请首先导入`Tracking`库并请求一个混合. + +``` +import Tracking from '~/tracking'; +const trackingMixin = Tracking.mixin({ label: 'right_sidebar' }); +``` + +您可以提供在组件中跟踪事件时都会传递的默认选项. 例如,如果应使用给定`label`跟踪组件中的所有事件,则此时可以提供一个. 可用的默认值是`category` , `label` , `property`和`value` . 如果未指定类别,则将`document.body.dataset.page`用作默认值. + +然后,您可以通过`mixin` Vue 声明在组件中正常使用 mixin. mixin 还提供了在`data`或`computed`指定跟踪选项的`data` . 这些将覆盖所有默认值,并允许这些值从 props 或基于状态是动态的. + +``` +export default { + mixins: [trackingMixin], + // ...[component implementation]... + data() { + return { + expanded: false, + tracking: { + label: 'left_sidebar' + } + }; + }, +} +``` + +mixin 提供了可以在模板中或从组件方法中调用的`track`方法. 整个实现的示例可能如下所示. + +``` +export default { + mixins: [Tracking.mixin({ label: 'right_sidebar' })], + data() { + return { + expanded: false, + }; + }, + methods: { + toggle() { + this.expanded = !this.expanded; + this.track('click_toggle', { value: this.expanded }) + } + } +}; +``` + +而且,如果需要模板中的内容,也可以直接使用`track`方法. + +``` +<template> + <div> + <a class="toggle" @click.prevent="toggle">Toggle</a> + <div v-if="expanded"> + <p>Hello world!</p> + <a @click.prevent="track('click_action')">Track an event</a> + </div> + </div> +</template> +``` + +### Tracking in raw JavaScript[](#tracking-in-raw-javascript "Permalink") + +可以通过直接调用`Tracking.event`静态函数来添加自定义事件跟踪和检测. 下面的示例演示如何通过手动调用`Tracking.event`按钮的单击. + +``` +import Tracking from '~/tracking'; + +const button = document.getElementById('create_from_template_button'); +button.addEventListener('click', () => { + Tracking.event('dashboard:projects:index', 'click_button', { + label: 'create_from_template', + property: 'template_preview', + value: 'rails', + }); +}) +``` + +### Tests and test helpers[](#tests-and-test-helpers "Permalink") + +在 Jest 中,尤其是在 Vue 测试中,可以使用以下命令: + +``` +import { mockTracking } from 'helpers/tracking_helper'; + +describe('MyTracking', () => { + let spy; + + beforeEach(() => { + spy = mockTracking('_category_', wrapper.element, jest.spyOn); + }); + + it('tracks an event when clicked on feedback', () => { + wrapper.find('.discover-feedback-icon').trigger('click'); + + expect(spy).toHaveBeenCalledWith('_category_', 'click_button', { + label: 'security-discover-feedback-cta', + property: '0', + }); + }); +}); +``` + +在过时的 Karma 测试中,其用法如下: + +``` +import { mockTracking, triggerEvent } from 'spec/helpers/tracking_helper'; + +describe('my component', () => { + let trackingSpy; + + beforeEach(() => { + trackingSpy = mockTracking('_category_', vm.$el, spyOn); + }); + + const triggerEvent = () => { + // action which should trigger a event + }; + + it('tracks an event when toggled', () => { + expect(trackingSpy).not.toHaveBeenCalled(); + + triggerEvent('a.toggle'); + + expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_edit_button', { + label: 'right_sidebar', + property: 'confidentiality', + }); + }); +}); +``` + +## Implementing Snowplow Ruby (Backend) tracking[](#implementing-snowplow-ruby-backend-tracking "Permalink") + +GitLab 提供`Gitlab::Tracking` ,该接口包装[Snowplow Ruby Tracker](https://github.com/snowplow/snowplow/wiki/ruby-tracker)以跟踪自定义事件. + +可以通过直接调用`GitLab::Tracking.event`类方法来添加自定义事件跟踪和检测,该方法接受以下参数: + +| argument | type | 默认值 | description | +| --- | --- | --- | --- | +| `category` | string | ‘application’ | 应用程序的区域或方面. 例如,这可以是`HealthCheckController`或`Lfs::FileTransformer` . | +| `action` | string | ‘generic’ | 正在执行的操作,可以是从控制器操作(如`create`到 Active Record 回调之类的任何内容. | +| `data` | object | {} | 如[我们的功能仪表分类法中](https://about.gitlab.com/handbook/product/feature-instrumentation/#taxonomy)所述的其他数据,例如`label` , `property` , `value`和`context` . 如果不提供,则将它们设置为空字符串. | + +跟踪既可以看作是跟踪用户的行为,也可以用于检测和监视代码区域或方面随时间变化的性能. + +例如: + +``` +class Projects::CreateService < BaseService + def execute + project = Project.create(params) + + Gitlab::Tracking.event('Projects::CreateService', 'create_project', + label: project.errors.full_messages.to_sentence, + value: project.valid? + ) + end +end +``` + +### Performance[](#performance "Permalink") + +跟踪事件时,我们使用[AsyncEmitter](https://github.com/snowplow/snowplow/wiki/Ruby-Tracker#52-the-asyncemitter-class) ,它允许在后台线程中运行检测调用. 这仍然是一个活跃的发展领域. + +## Developing and testing Snowplow[](#developing-and-testing-snowplow "Permalink") + +有几种工具可以开发和测试 Snowplow Event + +| 测试工具 | 前端追踪 | 后端追踪 | 当地发展环境 | 生产环境 | +| --- | --- | --- | --- | --- | +| Snowplow Analytics 调试器 Chrome 扩展 | | | | | +| Snowplow Inspector Chrome 扩展程序 | | | | | +| 扫雪机 | | | | | +| 扫雪机 Mini | | | | | + +### Snowplow Analytics Debugger Chrome Extension[](#snowplow-analytics-debugger-chrome-extension "Permalink") + +Snowplow Analytics Debugger 是用于测试前端事件的浏览器扩展. 这适用于生产,暂存和本地开发环境. + +1. 安装[Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome 浏览器扩展程序. +2. 将 Chrome DevTools 打开到 Snowplow Analytics 调试器选项卡. +3. 在[Igloo Analytics 上](https://www.iglooanalytics.com/blog/snowplow-analytics-debugger-chrome-extension.html)了解更多信息. + +### Snowplow Inspector Chrome Extension[](#snowplow-inspector-chrome-extension "Permalink") + +Snowplow Inspector Chrome 扩展程序是用于测试前端事件的浏览器扩展程序. 这适用于生产,暂存和本地开发环境. + +1. Install [Snowplow Inspector](https://chrome.google.com/webstore/detail/snowplow-inspector/maplkdomeamdlngconidoefjpogkmljm?hl=en). +2. 按下地址栏旁边的 Snowplow Inspector 图标,打开 Chrome 扩展程序. +3. 单击带有 Snowplow 的网页,您应该会在检查器窗口中看到触发 JavaScript 事件. + +### Snowplow Micro[](#snowplow-micro "Permalink") + +Snowplow Micro 是完整 Snowplow 数据收集管道的非常小版本:足够小,可以由测试套件启动. 就像完整的 Snowplow 管道一样,事件可以记录到 Snowplow Micro 中. Micro 然后公开了可以查询的 API. + +Snowplow Micro 是基于 Docker 的解决方案,用于在本地开发环境中测试前端和后端事件. 您需要按照以下说明修改 GDK 进行设置. + +* Read [Introducing Snowplow Micro](https://snowplowanalytics.com/blog/2019/07/17/introducing-snowplow-micro/) +* 查看[Snowplow Micro 存储库](https://github.com/snowplow-incubator/snowplow-micro) +* 观看我们的[安装指南记录](https://www.youtube.com/watch?v=OX46fo_A0Ag) + +1. Install [Snowplow Micro](https://github.com/snowplow-incubator/snowplow-micro): + + ``` + docker run --mount type=bind,source=$(pwd)/example,destination=/config -p 9090:9090 snowplow/snowplow-micro:latest --collector-config /config/micro.conf --iglu /config/iglu.json + ``` + +2. 通过克隆[此项目中](https://gitlab.com/a_akgun/snowplow-micro)的设置来安装 Snowplow micro: + + ``` + git clone git@gitlab.com:a_akgun/snowplow-micro.git + ./snowplow-micro.sh + ``` + +3. 在 SQL 中更新端口以设置`9090` : + + ``` + gdk psql -d gitlabhq_development + update application_settings set snowplow_collector_hostname='localhost:9090', snowplow_enabled=true, snowplow_cookie_domain='.gitlab.com'; + ``` + +4. Update `app/assets/javascripts/tracking.js` to [remove this line](https://gitlab.com/snippets/1918635): + + ``` + forceSecureTracker: true + ``` + +5. Update `lib/gitlab/tracking.rb` to [add these lines](https://gitlab.com/snippets/1918635): + + ``` + protocol: 'http', + port: 9090, + ``` + +6. Update `lib/gitlab/tracking.rb` to [change async emitter from https to http](https://gitlab.com/snippets/1918635): + + ``` + SnowplowTracker::AsyncEmitter.new(Gitlab::CurrentSettings.snowplow_collector_hostname, protocol: 'http'), + ``` + +7. 在管理区域 Settings :: Integrations :: Snowplow 中启用 Snowplow,以指向: `http://localhost:3000/admin/application_settings/integrations#js-snowplow-settings` . + +8. 重新启动 GDK: + + ``` + `gdk restart` + ``` + +9. 从 Rails 控制台发送测试 Snowplow 事件: + + ``` + Gitlab::Tracking.self_describing_event('iglu:com.gitlab/pageview_context/jsonschema/1-0-0', { page_type: ‘MY_TYPE' }, context: nil ) + ``` + +### Snowplow Mini[](#snowplow-mini "Permalink") + +[Snowplow Mini](https://github.com/snowplow/snowplow-mini)是[Snowplow](https://github.com/snowplow/snowplow-mini)的易于部署的单实例版本. + +Snowplow Mini 可用于在生产,暂存和本地开发环境上测试前端和后端事件. + +对于 GitLab.com,我们正在使用 Snowplow Mini 设置[质量检查和测试环境](https://gitlab.com/gitlab-org/telemetry/-/issues/266) . \ No newline at end of file diff --git a/_book/docs/578.md b/_book/docs/578.md new file mode 100644 index 0000000000000000000000000000000000000000..8bd7d89b8f073f8558a329b68b0d0c753010ea83 --- /dev/null +++ b/_book/docs/578.md @@ -0,0 +1,73 @@ +# Experiment Guide + +> 原文:[https://docs.gitlab.com/ee/development/experiment_guide/](https://docs.gitlab.com/ee/development/experiment_guide/) + +* [Experiment tracking issue](#experiment-tracking-issue) +* [Code reviews](#code-reviews) +* [How to create an A/B test](#how-to-create-an-ab-test) + +# Experiment Guide[](#experiment-guide "Permalink") + +任何 GitLab 小组都可以进行实验,大多数情况下是来自[成长子部门的小组](https://about.gitlab.com/handbook/engineering/development/growth/) . 实验与发布无关,因为它们主要针对 GitLab.com. + +实验将作为 A / B 测试运行,并且位于功能标记后面以打开或关闭测试. 根据实验产生的数据,团队将决定实验是否产生了积极影响,并将其设置为新的默认值或回滚. + +## Experiment tracking issue[](#experiment-tracking-issue "Permalink") + +每个实验都应有一个[实验跟踪](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=✓&state=opened&label_name[]=growth experiment&search=)问题,以跟踪从推出到清除/删除的实验. 部署实验后,应立即设置问题的到期日期(这取决于实验,但最多可能需要几周的时间). 在截止日期之后,该问题需要解决,并且可以: + +* 成功,实验将成为新的默认设置. +* 它不成功,与实验相关的所有代码都将被删除. + +无论哪种情况,都应将实验结果与决策依据一起发布到问题上. + +## Code reviews[](#code-reviews "Permalink") + +由于实验代码在很长一段时间内都不会成为代码库的一部分,并且我们想快速迭代以检索数据,因此实验的代码质量有时可能无法满足我们的标准,但无论实验是否为 GitLab 都不会对其产生负面影响运行与否. 最初,实验仅会部署到一小部分用户,但我们仍希望为这些用户提供完美的体验. 因此,实验仍然需要测试. + +对于审阅者和维护者:如果您发现通常无法通过审阅但暂时可以接受的代码,请提及您的疑虑,但请注意,无需进行更改. 然后,作者在这段代码中添加注释,并添加指向该问题的链接以解决该实验. 如果实验成功并成为产品的一部分,则应解决这些后续问题. + +## How to create an A/B test[](#how-to-create-an-ab-test "Permalink") + +* 实验添加到`Gitlab::Experimentation::EXPERIMENTS`中的散列[`experimentation.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/experimentation.rb) : + + ``` + EXPERIMENTS = { + other_experiment: { + #... + }, + # Add your experiment here: + signup_flow: { + environment: ::Gitlab.dev_env_or_com?, # Target environment, defaults to enabled for development and GitLab.com + tracking_category: 'Growth::Acquisition::Experiment::SignUpFlow' # Used for providing the category when setting up tracking data + } + }.freeze + ``` + +* 在控制器中使用实验: + + ``` + class RegistrationController < ApplicationController + def show + # experiment_enabled?(:feature_name) is also available in views and helpers + if experiment_enabled?(:signup_flow) + # render the experiment + else + # render the original version + end + end + end + ``` + +* 跟踪必要的事件. 有关详细信息,请参见[遥测指南](../telemetry/index.html) . +* 合并请求合并后, [`chatops`](../../ci/chatops/README.html)在[适当的通道中](../feature_flags/controls.html#communicate-the-change)使用[`chatops`](../../ci/chatops/README.html)来为 10%的用户启动实验. 功能标记应带有附加了`_experiment_percentage`后缀的实验名称. 为了提高可视性,请在`#s_growth`通道中共享对生产运行的所有命令: + + ``` + /chatops run feature set signup_flow_experiment_percentage 10 + ``` + + 如果发现实验存在问题,则可以通过删除功能标记来禁用实验: + + ``` + /chatops run feature delete signup_flow_experiment_percentage + ``` \ No newline at end of file diff --git a/_book/docs/579.md b/_book/docs/579.md new file mode 100644 index 0000000000000000000000000000000000000000..f67a4c630424eeb73dbebcb8060cd9222083f422 --- /dev/null +++ b/_book/docs/579.md @@ -0,0 +1,15 @@ +# Feature flags in development of GitLab + +> 原文:[https://docs.gitlab.com/ee/development/feature_flags/](https://docs.gitlab.com/ee/development/feature_flags/) + +# Feature flags in development of GitLab[](#feature-flags-in-development-of-gitlab "Permalink") + +[功能标记](../../operations/feature_flags.html)可用于逐步推出更改,无论是新功能还是性能改进. 通过使用功能标志,我们可以轻松地衡量更改的影响,同时仍然能够轻松禁用这些更改,而不必还原整个发行版. + +在使用功能标记进行 GitLab 开发之前,请通读以下内容: + +* [Process for using features flags](process.html). +* [Developing with feature flags](development.html). +* [Controlling feature flags](controls.html). +* [Documenting features deployed behind feature flags](../documentation/feature_flags.html). +* [How GitLab administrators can enable and disable features behind flags](../../administration/feature_flags.html). \ No newline at end of file diff --git a/_book/docs/580.md b/_book/docs/580.md new file mode 100644 index 0000000000000000000000000000000000000000..8a04285ff6f295459ed0430b7101fdfd05a70e67 --- /dev/null +++ b/_book/docs/580.md @@ -0,0 +1,93 @@ +# Feature flags process + +> 原文:[https://docs.gitlab.com/ee/development/feature_flags/process.html](https://docs.gitlab.com/ee/development/feature_flags/process.html) + +* [Feature flags for user applications](#feature-flags-for-user-applications) +* [Feature flags in GitLab development](#feature-flags-in-gitlab-development) + * [When to use feature flags](#when-to-use-feature-flags) + * [Including a feature behind feature flag in the final release](#including-a-feature-behind-feature-flag-in-the-final-release) + * [The cost of feature flags](#the-cost-of-feature-flags) + +# Feature flags process[](#feature-flags-process "Permalink") + +## Feature flags for user applications[](#feature-flags-for-user-applications "Permalink") + +本文档仅涵盖在 GitLab 本身的开发中使用的功能标志. 可以在[功能标志功能文档中](../../user/project/operations/feature_flags.html)找到已部署的用户应用程序中的[功能标志](../../user/project/operations/feature_flags.html) . + +## Feature flags in GitLab development[](#feature-flags-in-gitlab-development "Permalink") + +在决定是否应利用功能标志时,应考虑以下重点: + +* 默认情况下,功能标志应为**off** . +* 功能标记应在代码库中保留尽可能短的时间,以减少对功能标记记帐的需求. +* 使用功能标记的人员负责与负责的利益相关者清楚地传达功能标记后面的功能状态. 应该使用功能标记名称以及明显需要功能标记的默认状态打开或关闭更新问题描述. +* 合并进行更改以隐藏在功能标记后的请求,或删除现有功能标记(因为认为功能稳定),必须分配〜" feature flag"标签. +* 当功能开发将分散在多个合并请求中时,可以使用以下工作流程: + + 1. 在第一个合并请求中引入默认情况下**关闭**的功能标志. + 2. 通过一个或多个合并请求提交增量更改,以确保只有在功能标记为**on 时**才能访问添加的任何新代码. 您可以在开发过程中在本地 GDK 上保持启用功能标志. + 3. When the feature is ready to be tested, enable the feature flag for a specific project and ensure that there are no issues with the implementation. + 4. 准备宣布该功能时,创建一个合并请求,以添加有关该功能的[文档](../documentation/feature_flags.html) ,包括[有关功能标志本身的文档](../documentation/feature_flags.html)以及一个 changelog 条目. 在同一合并请求中,要么将功能标记翻转为**默认状态,**要么将其完全删除以启用新行为. + +可能会想起功能标记将功能的发布延迟至少一个月(=一个发布). 不是这种情况. 功能标记不必在特定时间段内停留(例如,至少一个版本),而是应该一直停留到功能被认为稳定为止. 稳定意味着它可以在 GitLab.com 上运行,而不会引起任何问题,例如中断. + +另请阅读[功能标记](development.html)的[开发指南](development.html) . + +### When to use feature flags[](#when-to-use-feature-flags "Permalink") + +从 GitLab 11.4 开始,开发人员必须使用功能标志进行不重要的更改. 此类更改包括: + +* 新功能(例如,新的合并请求小部件,史诗等). +* 复杂的性能改进,可能需要在生产中进行其他测试,例如重写复杂的查询. +* 对用户界面的侵入性更改,例如新的导航栏或侧边栏的删除. +* 添加了对从第三方服务导入项目的支持. + +在所有情况下,进行更改的人员都可以最好地决定是否需要功能标记. 例如,更改按钮的颜色不需要功能标记,而更改导航栏则绝对需要一个功能标记. 如果您不确定是否需要功能部件标志,只需在合并请求中询问一下,那些查看更改的人员可能会为您提供答案. + +对 UI 元素使用功能标记时,请确保对基础后端代码*也*使用功能标记(如果有). 这样可以确保在启用该功能之前绝对无法使用该功能. + +### Including a feature behind feature flag in the final release[](#including-a-feature-behind-feature-flag-in-the-final-release "Permalink") + +为了构建最终版本并向自我管理的用户展示功能,功能标志至少应默认为**on** . 如果认为该功能稳定并且确信删除该功能标志是安全的,请考虑完全删除该功能标志. *强烈*建议在做出此决定之前**,至少在一天的** [**生产中** **全局**启用](./controls.html#enabling-a-feature-for-gitlabcom)功能标志. 在此期间,有时会发现意外的错误. + +从首次审查合并请求到将更改部署到 GitLab.com 的过程中,启用默认情况下禁用的功能的过程可能需要 5 到 6 天. 但是,建议将此活动留出 10 到 14 天的时间,以解决无法预料的问题. + +功能标记必须[根据其状态(启用/禁用)进行记录](../documentation/feature_flags.html) ,并且当状态更改时, **必须相应**地更新文档. + +**注意:**请注意,合并功能标记的更改后不久,此类操作可使功能在 GitLab.com 上可用. + +更改默认状态或删除功能标志必须在每月的 22 号之前*(至少在* 3-4 个工作日之前)进行,以便将更改包含在最终的自我管理版本中. + +除此之外,功能标志后面的功能应: + +* 在所有 GitLab.com 环境中运行足够长的时间. 该时间段取决于功能标志后面的功能,但是通常经验法则是 2-4 个工作日应该足以收集足够的反馈. +* 在上述时间段内,该功能应向 GitLab.com 计划内的所有用户公开. 将功能暴露给较小的百分比或仅将一组用户公开可能不会暴露出足够多的信息来帮助您确定功能稳定性. + +尽管很少使用,但即使使用了功能标志,发行经理也可能决定拒绝选择或还原稳定分支中的更改. 如果更改被认为是有问题的,过于侵入性的,或者只是没有足够的时间来正确衡量更改在 GitLab.com 上的行为,则可能有必要. + +### The cost of feature flags[](#the-cost-of-feature-flags "Permalink") + +阅读以上内容时,可能会想起此过程会增加很多工作. 幸运的是,事实并非如此,我们将说明原因. 在此示例中,我们将工作成本指定为一个数字,范围从 0 到无穷大. 数量越大,工作越昂贵. 成本并*没有*转化时间,这只是相对于另一个测量一个变化的复杂性的一种方式. + +假设我们正在构建一个新功能,并确定此功能的成本为 10.我们还确定,在不同位置添加功能标志检查的成本为 1.如果不使用功能标志,并且我们的功能按预期工作,我们的总费用为 10.这是最好的情况. 最佳情况下的优化肯定会导致麻烦,而最坏情况下的优化几乎总是更好. + +为了说明这一点,假设我们的功能导致停机,并且没有立即解决的方法. 这意味着我们必须采取以下步骤来解决停机问题: + +1. 还原发行版. +2. 根据所做的更改,执行可能需要的所有清理. +3. 恢复提交,确保" master"分支保持稳定. 如果解决问题可能需要几天甚至几周的时间,那么这尤其必要. +4. 选择还原提交到适当的稳定分支中,以确保在问题解决之前我们不会阻止任何将来的发行. + +如历史所示,这些步骤耗时,复杂,通常涉及许多开发人员,而且最糟糕的是:在解决问题之前,我们的用户使用 GitLab.com 的体验将很糟糕. + +现在,我们假设所有这些的关联成本为 10.这意味着在最坏的情况下(我们应该对其进行优化),我们的总成本现在为 20. + +如果我们使用了功能标记,情况将会大不相同. 我们不需要还原版本,并且由于默认情况下功能标记是禁用的,因此我们不需要还原并选择任何 Git 提交. 实际上,我们要做的就是禁用该功能,在最坏的情况下,执行清理. 假设这是 2 的成本.在这种情况下,我们的最佳案例成本是 11:构建功能部件的成本为 10:添加功能标志的成本为 1\. 现在最坏的情况是 13: + +* 10 构建功能. +* 1 添加功能标志. +* 2 禁用并清理. + +在这里,我们可以看到,在最佳情况下,与不使用功能标记相比,所需的工作仅多一点. 同时,还原变更的过程已大大便宜了. + +In other words, feature flags do not slow down the development process. Instead, they speed up the process as managing incidents now becomes *much* easier. Once continuous deployments are easier to perform, the time to iterate on a feature is reduced even further, as you no longer need to wait weeks before your changes are available on GitLab.com. \ No newline at end of file diff --git a/_book/docs/581.md b/_book/docs/581.md new file mode 100644 index 0000000000000000000000000000000000000000..27d4890b539081f8bcab0a88c0882fb3577bd2c0 --- /dev/null +++ b/_book/docs/581.md @@ -0,0 +1,132 @@ +# Developing with feature flags + +> 原文:[https://docs.gitlab.com/ee/development/feature_flags/development.html](https://docs.gitlab.com/ee/development/feature_flags/development.html) + +* [Feature groups](#feature-groups) + * [Frontend](#frontend) + * [Specs](#specs) + * [`stub_feature_flags: true` (default and preferred)](#stub_feature_flags-true-default-and-preferred) + * [`stub_feature_flags: false`](#stub_feature_flags-false) + * [Enabling a feature flag (in development)](#enabling-a-feature-flag-in-development) + +# Developing with feature flags[](#developing-with-feature-flags "Permalink") + +通常,最好有一个基于组或基于用户的门,并且您应该比使用百分比门更好. 这将使调试更加容易,因为您也可以根据参与者过滤示例日志和错误. 此外,这允许首先启用`gitlab-org`或`gitlab-com`组,而其余用户则`gitlab-com` . + +``` +# Good +Feature.enabled?(:feature_flag, project) + +# Avoid, if possible +Feature.enabled?(:feature_flag) +``` + +要使用基于角色的特征门,模型需要响应`flipper_id` . 例如,要启用 Foo 模型: + +``` +class Foo < ActiveRecord::Base + include FeatureGate +end +``` + +只有`include FeatureGate`或公开的`flipper_id`方法的模型才能用作`Feature.enabled?` `flipper_id` `Feature.enabled?` . + +已开发并打算在功能标记后合并的功能不应包含变更日志条目. 该条目应添加到删除功能部件标记的合并请求中,或在功能部件标记的默认值设置为 true 的合并请求中添加. 如果功能包含任何数据库迁移,则该功能应包括数据库更改的更改日志条目. + +如果您需要功能标记自动打开,请在检查以下内容时使用`default_enabled: true` : + +``` +Feature.enabled?(:feature_flag, project, default_enabled: true) +``` + +[`Project#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/app/models/project_feature.rb#L63-68) , [`Namespace#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/ee/namespace.rb#L71-85) (EE)和[`License.feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/license.rb#L293-300) (EE)方法都隐式检查默认情况下启用的功能标志,该标志与提供的参数同名. + +例如,如果某个功能是许可门控的,则无需添加其他显式功能标志检查,因为该标志将作为`License.feature_available?`一部分进行检查`License.feature_available?` 呼叫. 同样,功能达到通用状态后,也无需"清理"功能标志. + +您是否仍想使用显式`Feature.enabled?` 检查您的新功能是否不受许可或计划的限制. + +**上面提到的隐式功能标志的一个重要副作用是,除非功能被明确禁用或限制为一定比例的用户,否则功能标志检查将默认为`true` .** + +当使用[几个较小的合并请求](https://about.gitlab.com/handbook/values/#make-small-merge-requests)开发功能时,或者当该功能被视为[alpha 或 beta 时](https://about.gitlab.com/handbook/product/#alpha-beta-ga) ,这是相关的,并且默认情况下不可用. + +例如,如果要交付功能的前端一半而没有后端,则希望完全禁用该功能,直到也可以交付后端一半. 要确保 GitLab.com 和自我管理实例均禁用此功能,应使用[`Namespace#alpha_feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/458749872f4a8f27abe8add930dbb958044cb926/ee/app/models/ee/namespace.rb#L113) 或[`Namespace#beta_feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/458749872f4a8f27abe8add930dbb958044cb926/ee/app/models/ee/namespace.rb#L100-112) 方法,根据我们的[定义](https://about.gitlab.com/handbook/product/#alpha-beta-ga) . 这样可以确保禁用功能,除非*明确*启用了功能标志. + +## Feature groups[](#feature-groups "Permalink") + +从 GitLab 9.4 开始,我们通过[Flipper 组](https://github.com/jnunemaker/flipper/blob/v0.10.2/docs/Gates.md#2-group)支持功能[组](https://github.com/jnunemaker/flipper/blob/v0.10.2/docs/Gates.md#2-group) . + +功能组必须在`lib/feature.rb` (在`.register_feature_groups`方法中)静态定义,但是它们的实现显然可以是动态的(查询数据库等). + +在`lib/feature.rb`定义后,您将能够通过[features API](../../api/features.html#set-or-create-a-feature)的[`feature_group`参数](../../api/features.html#set-or-create-a-feature)激活给定功能组[的功能](../../api/features.html#set-or-create-a-feature) + +### Frontend[](#frontend "Permalink") + +对于前端代码,可以使用方法`push_frontend_feature_flag` ,该方法适用于所有从`ApplicationController`继承的控制器. 使用此方法,可以按如下所示公开功能部件标志的状态: + +``` +before_action do + # Prefer to scope it per project or user e.g. + push_frontend_feature_flag(:vim_bindings, project) + + # Avoid, if possible + push_frontend_feature_flag(:vim_bindings) +end + +def index + # ... +end + +def edit + # ... +end +``` + +然后,您可以按照以下步骤检查 JavaScript 中功能部件标志的状态: + +``` +if ( gon.features.vimBindings ) { + // ... +} +``` + +JavaScript 中的功能标志的名称将始终为 camelCased,这意味着检查`gon.features.vim_bindings`将不起作用. + +有关如何访问 Vue 组件中的功能标志的详细信息,请参见[Vue 指南](../fe_guide/vue.html#accessing-feature-flags) . + +### Specs[](#specs "Permalink") + +我们在测试环境中的 Flipper 引擎以`Flipper::Adapters::Memory`的内存模式工作. `production`和`development`模式使用`Flipper::Adapters::ActiveRecord` . + +### `stub_feature_flags: true` (default and preferred)[](#stub_feature_flags-true-default-and-preferred "Permalink") + +在此模式下,将 Flipper 配置为使用`Flipper::Adapters::Memory`并将所有功能标志标记为默认状态,并在首次使用时保持不变. 这将覆盖`Feature.enabled?`的`default_enabled:` `Feature.enabled?` 和`Feature.disabled?` 除非功能标记持续存在,否则始终返回`true` . + +Make sure behavior under feature flag doesn’t go untested in some non-specific contexts. + +有关如何在测试中添加功能标志的信息和示例,请参见[测试指南](../testing_guide/best_practices.html#feature-flags-in-tests) . + +### `stub_feature_flags: false`[](#stub_feature_flags-false "Permalink") + +这将禁用存储在内存中的鳍状肢,并使用`Flipper::Adapters::ActiveRecord`一种`production`和`development`所使用的模式. + +仅当您确实想测试 Flipper 的各个方面及其与`ActiveRecord`交互方式时,才应使用此模式. + +### Enabling a feature flag (in development)[](#enabling-a-feature-flag-in-development "Permalink") + +在 rails 控制台( `rails c` )中,输入以下命令以启用功能部件标志 + +``` +Feature.enable(:feature_flag_name) +``` + +同样,以下命令将禁用功能部件标志: + +``` +Feature.disable(:feature_flag_name) +``` + +您也可以为给定的门启用功能标志: + +``` +Feature.enable(:feature_flag_name, Project.find_by_full_path("root/my-project")) +``` \ No newline at end of file diff --git a/_book/docs/582.md b/_book/docs/582.md new file mode 100644 index 0000000000000000000000000000000000000000..606a8fb1f609c84c178a0d98ef04b95e09ad4e2e --- /dev/null +++ b/_book/docs/582.md @@ -0,0 +1,195 @@ +# Feature flag controls + +> 原文:[https://docs.gitlab.com/ee/development/feature_flags/controls.html](https://docs.gitlab.com/ee/development/feature_flags/controls.html) + +* [Access](#access) +* [Rolling out changes](#rolling-out-changes) + * [Enabling a feature for preproduction testing](#enabling-a-feature-for-preproduction-testing) + * [Enabling a feature for GitLab.com](#enabling-a-feature-for-gitlabcom) + * [Communicate the change](#communicate-the-change) + * [Process](#process) + * [Feature flag change logging](#feature-flag-change-logging) +* [Cleaning up](#cleaning-up) + +# Feature flag controls[](#feature-flag-controls "Permalink") + +## Access[](#access "Permalink") + +为了能够在 GitLab Inc.提供的任何环境(例如分期和生产)中打开/关闭功能标记后面的功能,您需要访问[Chatops](../chatops_on_gitlabcom.html)机器人. Chatops 机器人当前在 ops 实例上运行,该实例不同于[https://gitlab.com](https://gitlab.com)或[https://dev.gitlab.org](https://dev.gitlab.org) . + +按照 Chatops 文档[请求访问权限](../chatops_on_gitlabcom.html#requesting-access) . + +一旦您将访问权限传播到项目测试中,请运行: + +``` +/chatops run feature --help +``` + +## Rolling out changes[](#rolling-out-changes "Permalink") + +将更改部署到环境后,就该开始向我们的用户推出该功能了. 没有具体说明发布更改的确切过程,因为更改之间可能会有所不同. 但是,总的来说,我们建议逐步推出更改,而不是立即为所有人启用更改. 我们还建议您在部署代码*之前* *不要*启用功能. 这使您可以将部署的功能与部署分开,从而更容易分别衡量两者的影响. + +GitLab 的功能库(使用[Flipper](https://github.com/jnunemaker/flipper) ,并在[功能标志过程](process.html)指南中进行了介绍)支持向用户发布更改的时间百分比. 依次可以使用[GitLab Chatops](../../ci/chatops/README.html)进行控制. + +有关功能标志命令的最新列表,请参见[源代码](https://gitlab.com/gitlab-com/chatops/blob/master/lib/chatops/commands/feature.rb) . 请注意,该文件中的所有示例都必须在`/chatops run`之前. + +如果收到错误消息"糟糕! 不允许执行此操作. 该事件将得到报告." 这意味着您的 Slack 帐户不允许更改功能标志,或者您没有[访问权限](#access) . + +### Enabling a feature for preproduction testing[](#enabling-a-feature-for-preproduction-testing "Permalink") + +作为功​​能推出的第一步,您应该在[https://staging.gitlab.com](https://staging.gitlab.com)和[https://dev.gitlab.org](https://dev.gitlab.org)上启用功能. + +这两个环境具有不同的范围. `dev.gitlab.org`是具有内部 GitLab Inc.流量的生产 CE 环境,用于某些开发和其他相关工作. `staging.gitlab.com`有 GitLab.com 数据库和知识库的较小的子集,并没有正常的交通. 登台是 EE 实例,可以(非常)粗略估计您的功能在 GitLab.com 上的外观/行为. 这两个实例都已连接到 Sentry,因此请确保在启用功能标志后测试功能时,检查那里的项目是否存在异常. + +对于这些预生产环境,应在功能相关的阶段在 Slack 通道中运行命令. 例如,将`#s_monitor`通道用于 Monitor 阶段"运行状况"组开发的功能. + +To enable a feature for 25% of all users, run the following in Slack: + +``` +/chatops run feature set new_navigation_bar 25 --dev +/chatops run feature set new_navigation_bar 25 --staging +``` + +### Enabling a feature for GitLab.com[](#enabling-a-feature-for-gitlabcom "Permalink") + +在[预生产](#enabling-a-feature-for-preproduction-testing)环境中成功[启用功能](#enabling-a-feature-for-preproduction-testing)并验证其安全性和正常工作后,您可以将更改发布到 GitLab.com(生产). + +#### Communicate the change[](#communicate-the-change "Permalink") + +GitLab.com 上的某些功能标志更改应与公司部分进行沟通. 负责开发的人员需要确定这是否必要以及适当的通信级别. 这取决于功能及其可能产生的影响. + +作为指导: + +* 对于低风险且易于回滚的简单功能,只需继续[在`#production`启用该功能](#process) . +* 对于将影响用户体验的功能,请考虑事先通知`#support_gitlab-com` . +* 对于具有重大下游影响的功能(例如:打开/关闭 Elasticsearch 索引`#production` ),请考虑事先与`#production`协调. + +#### Process[](#process "Permalink") + +在切换任何功能标志之前,请检查 GitLab.com 上是否没有正在进行的重大事件. 您可以通过检查`#production`和`#incident-management` Slack 通道,或查找[未解决的事件问题](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/?scope=all&utf8=✓&state=opened&label_name[]=incident) (尽管检查日期和时间)来执行此操作. + +我们不想在事件发生时进行更改,因为它会使实现事件的诊断和解决变得更加困难,并且由于无法评估发布是否没有问题,因此在很大程度上会使发布过程无效. + +如有疑问,请在`#production`中`#production` . + +以下`/chatops`命令应在 Slack `#production`通道中执行. + +当您开始启用该功能时,请在您执行的第一个`/chatops`命令的 Slack 线程中链接到相关的功能标志发布问题,以便人们可以根据需要了解更改. + +要在 25%的时间内启用功能,请在 Slack 中运行以下命令: + +``` +/chatops run feature set new_navigation_bar 25 +``` + +这将根据以下公式将功能标记设置为`true` : + +``` +feature_flag_state = rand < (25 / 100.0) +``` + +这将为 GitLab.com 启用该功能,其中`new_navigation_bar`为该功能的名称. 此命令*不*启用用户总量的 25%的功能. 而是在`enabled?`该功能时进行检查`enabled?` ,它将在 25%的时间内返回`true` . + +要为 25%的参与者(例如用户,项目或组)启用功能,请在 Slack 中运行以下命令: + +``` +/chatops run feature set some_feature 25 --actors +``` + +这将根据以下公式将功能标记设置为`true` : + +``` +feature_flag_state = Zlib.crc32("some_feature<Actor>:#{actor.id}") % (100 * 1_000) < 25 * 1_000] +# where <Actor>: is a `User`, `Group`, `Project` and actor is an instance +``` + +在开发过程中,应根据功能的性质来选择演员. + +对于以用户为中心的功能: + +``` +Feature.enabled?(:feature_cool_avatars, current_user) +``` + +对于组或名称空间级别的功能: + +``` +Feature.enabled?(:feature_cooler_groups, group) +``` + +对于项目级别的功能: + +``` +Feature.enabled?(:feature_ice_cold_projects, project) +``` + +如果不确定要使用什么百分比,只需使用以下步骤: + +1. 25% +2. 50% +3. 75% +4. 100% + +在每个步骤之间,您都需要稍等片刻,并在[https://dashboards.gitlab.net](https://dashboards.gitlab.net)上监视适当的图形. 等待的确切时间可能有所不同. 对于某些功能,几分钟就足够了,而对于其他功能,您可能要等待几个小时甚至几天. 这完全取决于您,只要确保将其清楚地传达给您的团队和生产团队即可,如果您预计任何潜在的问题. + +功能门也可以基于`gitlab` ,例如,可以首先仅对`gitlab`项目启用功能. 通过提供`--project`标志来传递项目: + +``` +/chatops run feature set --project=gitlab-org/gitlab some_feature true +``` + +对于组, `--group`标志可用: + +``` +/chatops run feature set --group=gitlab-org some_feature true +``` + +请注意,基于角色的门适用于百分比. 例如,如果您运行以下两个命令,则将`group/project`视为`gitlab-org/gitlab`并将给定的示例功能视为`some_feature` : + +``` +/chatops run feature set --project=gitlab-org/gitlab some_feature true +/chatops run feature set some_feature 25 --actors +``` + +然后将为 25%的参与者同时启用`some_feature` ,并且始终在与`gitlab-org/gitlab`交互时`gitlab-org/gitlab` . 如果特征标记开发使用组参与者,这是一个好主意. + +``` +Feature.enabled?(:some_feature, group) +``` + +**注意:**如果要确保用户始终开启或关闭某项功能,则**时间百分比分布**不是一个好主意. 在这种情况下, **"参与者百分比"**展示是一种更好的方法. + +最后,要在尽可能多的情况下验证该功能被认为是稳定的,您应该通过运行以下命令**全局**启用该标志来全面推出该功能: + +``` +/chatops run feature set some_feature true +``` + +这会将功能标志状态更改为始终**启用** ,从而覆盖上述过程中现有的门(例如`--group=gitlab-org` ). + +### Feature flag change logging[](#feature-flag-change-logging "Permalink") + +任何影响 GitLab.com(生产)的功能标志更改都会自动记录在问题中. + +该问题是在[gl-infra / feature-flag-log](https://gitlab.com/gitlab-com/gl-infra/feature-flag-log/-/issues?scope=all&utf8=✓&state=closed)项目中创建的,它将至少记录启用功能标志的人员的 Slack 句柄,更改的时间和标志的名称. + +然后,该问题还将作为注释标记发布到 GitLab 的内部[Grafana 仪表板上](https://dashboards.gitlab.net/) ,以使更改更加明显. + +问题格式的更改可以在[Chatops 项目中](https://gitlab.com/gitlab-com/chatops)提交. + +## Cleaning up[](#cleaning-up "Permalink") + +更改被视为稳定后,请提交新的合并请求以删除功能标记. 这样可以确保所有用户和自我管理实例都可以使用该更改. 确保在此合并请求中添加〜" feature flag"标签,以便发行经理意识到更改隐藏在 feature 标志的后面. 如果必须将合并请求放入一个稳定的分支中,请确保还添加适当的`~"Pick into XY"`标签(例如`~"Pick into 13.0"` ). 有关更多详细信息,请参见[过程文档](process.html#including-a-feature-behind-feature-flag-in-the-final-release) . + +从代码库中删除功能门后,数据库中仍然存在该标志也已部署的功能记录. 将 MR 部署到每个环境后,可以删除该记录: + +``` +/chatops run feature delete some_feature --dev +/chatops run feature delete some_feature --staging +``` + +Then, you can delete it from production after the MR is deployed to prod: + +``` +/chatops run feature delete some_feature +``` \ No newline at end of file diff --git a/_book/docs/583.md b/_book/docs/583.md new file mode 100644 index 0000000000000000000000000000000000000000..3c839ad39e72801906fea1d8dc1e325264f4b208 --- /dev/null +++ b/_book/docs/583.md @@ -0,0 +1,180 @@ +# Document features deployed behind feature flags + +> 原文:[https://docs.gitlab.com/ee/development/documentation/feature_flags.html](https://docs.gitlab.com/ee/development/documentation/feature_flags.html) + +* [Criteria](#criteria) + * [Features disabled by default](#features-disabled-by-default) + * [Features that became enabled by default](#features-that-became-enabled-by-default) + * [Features directly enabled by default](#features-directly-enabled-by-default) + * [Features with flag removed](#features-with-flag-removed) + +# Document features deployed behind feature flags[](#document-features-deployed-behind-feature-flags "Permalink") + +manbetx 客户端打不开使用[功能标志](../feature_flags/index.html)来战略性地推出自己的功能的部署. 我们在功能标记后面记录功能的方式取决于其状态(启用或禁用). 状态更改时,进行更改的开发人员**必须相应地更新文档** . + +## Criteria[](#criteria "Permalink") + +根据[部署功能标记后的 GitLab 功能](../feature_flags/process.html)的过程: + +> * *默认情况下,功能标志应处于关闭状态.* +> * *功能标记应尽可能短地保留在代码库中,以减少对功能标记记帐的需求.* +> * *为了构建最终版本并为自我管理的用户提供功能,功能标志至少应至少默认为 on.* + +根据标志的状态,请参阅下面的文档说明: + +* [Features disabled by default](#features-disabled-by-default). +* [Features that became enabled by default](#features-that-became-enabled-by-default). +* [Features directly enabled by default](#features-directly-enabled-by-default). +* [Features with the feature flag removed](#features-with-flag-removed). + +**注意:**功能级别的[`**(CORE ONLY)**`](styleguide.html#product-badges)徽标或等效标记应添加到以下行和标题中,即启用/禁用功能标志,因为这样做需要管理员访问权限,因此,它表示不能由 GitLab.com 的普通用户完成. + +### Features disabled by default[](#features-disabled-by-default "Permalink") + +对于默认情况下禁用的功能,如果由于缺乏完整性而无法使用它们,或者仍在内部评估中(例如,出于性能方面的考虑),请**不要对其进行文档化** :仅在以下情况下添加(或合并)文档:该功能是安全的,可供最终用户使用和测试. + +对于默认情况下禁用的功能标志,如果最终用户可以使用它们: + +* 说默认情况下它是禁用的. +* 说是否在 GitLab.com 上启用了它. +* 说说是否可以针对每个项目启用或禁用它. +* 说出是否建议将其用于生产. +* 记录如何启用和禁用它. + +例如,对于默认情况下禁用的功能,可以在每个项目上启用或禁用 GitLab.com 上禁用的功能,并且不准备用于生产环境: + +``` +# Feature Name + > - [Introduced](link-to-issue) in GitLab 12.0. +> - It's deployed behind a feature flag, disabled by default. +> - It's disabled on GitLab.com. +> - It's able to be enabled or disabled per-project +> - It's not recommended for production use. +> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#anchor-to-section). **(CORE ONLY)** + +(...) + +### Enable or disable <Feature Name> **(CORE ONLY)** + +<Feature Name> is under development and not ready for production use. It is +deployed behind a feature flag that is **disabled by default**. +[GitLab administrators with access to the GitLab Rails console](../path/to/administration/feature_flags.md) +can enable it for your instance. <Feature Name> can be enabled or disabled per-project + +To enable it: + +```ruby # Instance-wide +Feature.enable(:<feature flag>) +# or by project +Feature.enable(:<feature flag>, Project.find(<project id>)) +``` + +To disable it: + +```ruby # Instance-wide +Feature.disable(:<feature flag>) +# or by project +Feature.disable(:<feature flag>, Project.find(<project id>)) +``` +``` + +根据要记录的功能的状态来调整 Blur. + +### Features that became enabled by default[](#features-that-became-enabled-by-default "Permalink") + +对于默认启用的功能: + +* 假设默认情况下已启用它. +* 说是否在 GitLab.com 上启用了它. +* 说说是否可以针对每个项目启用或禁用它. +* 说出是否建议将其用于生产. +* 记录如何禁用和启用它. + +例如,对于最初部署时默认情况下禁用的功能,默认情况下已启用,在 GitLab.com 上启用了该功能,该功能无法按项目启用或禁用,并且可以用于生产环境: + +``` +# Feature Name + > - [Introduced](link-to-issue) in GitLab 12.0. +> - It was deployed behind a feature flag, disabled by default. +> - [Became enabled by default](link-to-issue) on GitLab 12.1. +> - It's enabled on GitLab.com. +> - It's not able to be enabled or disabled per-project +> - It's recommended for production use. +> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(CORE ONLY)** + +(...) + +### Enable or disable <Feature Name> **(CORE ONLY)** + +<Feature Name> is under development but ready for production use. +It is deployed behind a feature flag that is **enabled by default**. +[GitLab administrators with access to the GitLab Rails console](..path/to/administration/feature_flags.md) +can opt to disable it for your instance it cannot be enabled or disabled per-project. + +To disable it: + +```ruby Feature.disable(:<feature flag>) +``` + +To enable it: + +```ruby Feature.enable(:<feature flag>) +``` +``` + +根据要记录的功能的状态来调整 Blur. + +### Features directly enabled by default[](#features-directly-enabled-by-default "Permalink") + +对于默认启用的功能: + +* 说默认情况下已启用. +* 说是否在 GitLab.com 上启用了它. +* 说说是否可以针对每个项目启用或禁用它. +* 说出是否建议将其用于生产. +* 记录如何禁用和启用它. + +For example, for a feature enabled by default, enabled on GitLab.com, cannot be enabled or disabled per-project, and ready for production use: + +``` +# Feature Name + > - [Introduced](link-to-issue) in GitLab 12.0. +> - It's deployed behind a feature flag, enabled by default. +> - It's enabled on GitLab.com. +> - It's not able to be enabled or disabled per-project +> - It's recommended for production use. +> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(CORE ONLY)** + +(...) + +### Enable or disable <Feature Name> **(CORE ONLY)** + +<Feature Name> is under development but ready for production use. +It is deployed behind a feature flag that is **enabled by default**. +[GitLab administrators with access to the GitLab Rails console](..path/to/administration/feature_flags.md) +can opt to disable it for your instance. + +To disable it: + +```ruby Feature.disable(:<feature flag>) +``` + +To enable it: + +```ruby Feature.enable(:<feature flag>) +``` +``` + +根据要记录的功能的状态来调整 Blur. + +### Features with flag removed[](#features-with-flag-removed "Permalink") + +功能准备就绪并且标记已删除后,请清理文档. 删除功能标记的提及,只保留一个在版本历史记录注释中提及该标记的注释: + +``` +# Feature Name + > - [Introduced](link-to-issue) in GitLab 12.0. +> - [Feature flag removed](link-to-issue) in GitLab 12.2. + +(...) +``` \ No newline at end of file diff --git a/_book/docs/584.md b/_book/docs/584.md new file mode 100644 index 0000000000000000000000000000000000000000..e78ef7dc7103378837914bc0c11d4c52b317a5af --- /dev/null +++ b/_book/docs/584.md @@ -0,0 +1,127 @@ +# Frontend Development Guidelines + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/](https://docs.gitlab.com/ee/development/fe_guide/) + +* [Overview](#overview) + * [Browser Support](#browser-support) +* [Initiatives](#initiatives) +* [Principles](#principles) +* [Development Process](#development-process) +* [Architecture](#architecture) +* [Testing](#testing) +* [Pajamas Design System](#pajamas-design-system) +* [Design Patterns](#design-patterns) +* [Vue.js Best Practices](#vuejs-best-practices) +* [Vuex](#vuex) +* [Axios](#axios) +* [GraphQL](#graphql) +* [Icons and Illustrations](#icons-and-illustrations) +* [Dependencies](#dependencies) +* [Frontend FAQ](#frontend-faq) +* [Style Guides](#style-guides) +* [Tooling](#tooling) +* [Performance](#performance) +* [Security](#security) +* [Accessibility](#accessibility) +* [Internationalization (i18n) and Translations](#internationalization-i18n-and-translations) + +# Frontend Development Guidelines[](#frontend-development-guidelines "Permalink") + +本文档介绍了各种指南,以确保整个 GitLab 前端团队的一致性和质量. + +## Overview[](#overview "Permalink") + +GitLab 使用[Haml](http://haml.info/)在[Ruby on Rails 的](https://rubyonrails.org)基础上构建,并且还基于[Vue.js](https://vuejs.org)基于 JavaScript 的 Frontend. 注意[使用 Hamlit 所](https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md#limitations)带来[的限制](https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md#limitations) . 我们还将[SCSS](https://sass-lang.com)和普通 JavaScript 与通过[Babel](https://babeljs.io/)支持的现代 ECMAScript 标准一起使用,并通过[webpack](https://webpack.js.org/)支持 ES 模块. + +使用我们的前端资产需要使用 Node(v10.13.0 或更高版本)和 Yarn(v1.10.0 或更高版本). 您可以在我们的[安装指南中](../../install/installation.html#4-node)找到有关如何安装它们的信息. + +### Browser Support[](#browser-support "Permalink") + +对于我们当前支持的浏览器,请参阅我们的[要求](../../install/requirements.html#supported-web-browsers) . + +使用[BrowserStack](https://www.browserstack.com/)来测试我们支持的浏览器. 使用保存在 GitLab [共享 1Password 帐户](https://about.gitlab.com/handbook/security/#1password-guide)的**Engineering**库中的凭据登录到 BrowserStack. + +## Initiatives[](#initiatives "Permalink") + +当前的高级前端目标列在" [前端史诗"中](https://gitlab.com/groups/gitlab-org/-/epics?label_name[]=frontend) . + +## Principles[](#principles "Permalink") + +对 GitLab 做出贡献[的高级指南](principles.html) . + +## Development Process[](#development-process "Permalink") + +我们如何[计划和执行](development_process.html)前端工作. + +## Architecture[](#architecture "Permalink") + +我们如何在 GitLab 的前端团队中[做出基本的设计决策](architecture.html) ,或者对我们的前端开发准则进行更改. + +## Testing[](#testing "Permalink") + +我们如何编写[前端测试](../testing_guide/frontend_testing.html) ,运行 GitLab 测试套件以及调试与测试相关的问题. + +## Pajamas Design System[](#pajamas-design-system "Permalink") + +在我们的[睡衣设计系统中](https://design.gitlab.com/)可以找到具有技术和使用指南的可重复使用组件. + +## Design Patterns[](#design-patterns "Permalink") + +GitLab 代码库中的常见 JavaScript [设计模式](design_patterns.html) . + +## Vue.js Best Practices[](#vuejs-best-practices "Permalink") + +明确具体的[设计模式和实践](vue.html) . + +## Vuex[](#vuex "Permalink") + +[Vuex](vuex.html)特定的设计模式和实践. + +## Axios[](#axios "Permalink") + +[Axios](axios.html)特定的实践和陷阱. + +## GraphQL[](#graphql "Permalink") + +如何使用[GraphQL](graphql.html) . + +## Icons and Illustrations[](#icons-and-illustrations "Permalink") + +我们如何将 SVG 用于我们的[图标和插图](icons.html) . + +## Dependencies[](#dependencies "Permalink") + +有关前端[依赖关系](dependencies.html)以及我们如何管理它们的常规信息. + +## Frontend FAQ[](#frontend-faq "Permalink") + +阅读[前端的常见问题](frontend_faq.html) ,以获取有用的常见小信息. + +## Style Guides[](#style-guides "Permalink") + +请参阅相关的样式指南以获取我们的准则以及有关棉绒的信息: + +* [JavaScript](style/javascript.html) . 我们的指南基于出色的[Airbnb](https://github.com/airbnb/javascript)样式指南,并做了一些小改动. +* [SCSS](style/scss.html) :我们的 SCSS 约定,通过[`scss-lint`](https://github.com/sds/scss-lint) . +* [HTML](style/html.html) . 与其余代码库一致的编写 HTML 代码的准则. +* [Vue](style/vue.html) . 有关 Vue 代码的准则和约定,请参见此处. + +## [Tooling](tooling.html)[](#tooling "Permalink") + +我们的代码会自动使用[Prettier](https://prettier.io)格式化,以遵循我们的准则. 阅读我们的[工具指南](tooling.html)以获取更多详细信息. + +## [Performance](performance.html)[](#performance "Permalink") + +监视和最大化前端性能的最佳实践. + +## [Security](security.html)[](#security "Permalink") + +前端安全实践. + +## [Accessibility](accessibility.html)[](#accessibility "Permalink") + +我们的无障碍标准和资源. + +## [Internationalization (i18n) and Translations](../i18n/externalization.html)[](#internationalization-i18n-and-translations "Permalink") + +[本文档](../i18n/)介绍了前端国际化支持. [指南](../i18n/externalization.html)的[外部化部分](../i18n/externalization.html)介绍了可用的帮助程序/方法. \ No newline at end of file diff --git a/_book/docs/585.md b/_book/docs/585.md new file mode 100644 index 0000000000000000000000000000000000000000..c06d4b613570e455f0d6668906cd0f12943e75ef --- /dev/null +++ b/_book/docs/585.md @@ -0,0 +1,15 @@ +# Accessibility & Readability + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/accessibility.html](https://docs.gitlab.com/ee/development/fe_guide/accessibility.html) + +* [Resources](#resources) + +# Accessibility & Readability[](#accessibility--readability "Permalink") + +## Resources[](#resources "Permalink") + +[Chrome 可访问性开发人员工具](https://github.com/GoogleChrome/accessibility-developer-tools)对于在 GitLab 中测试潜在的可访问性问题很有用. + +[斧头](https://www.deque.com/axe/)浏览器扩展程序(适用于[Firefox](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/)和[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd) )也是一种便捷的工具,可用于运行审核并获取有关标记,CSS 甚至可能存在问题的颜色使用情况的反馈. + +可访问性最佳做法和更深入的信息可在 Chrome 可访问性开发人员工具[的"审核规则"页面上](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules)找到. " [超棒可访问性"](https://github.com/brunopulis/awesome-a11y)列表也是可访问性相关材料的有用汇编. \ No newline at end of file diff --git a/_book/docs/586.md b/_book/docs/586.md new file mode 100644 index 0000000000000000000000000000000000000000..8205dab976fbf8962b0e5544b4b26c02bd3c17ff --- /dev/null +++ b/_book/docs/586.md @@ -0,0 +1,43 @@ +# Ajax + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/droplab/plugins/ajax.html](https://docs.gitlab.com/ee/development/fe_guide/droplab/plugins/ajax.html) + +* [Usage](#usage) + +# Ajax[](#ajax "Permalink") + +`Ajax`是一个 droplab 插件,允许从服务器检索和呈现列表数据. + +## Usage[](#usage "Permalink") + +将`Ajax`对象添加到`DropLab.prototype.init`或`DropLab.prototype.addHook`调用的 plugins 数组中. + +`Ajax`需要 2 个配置值, `endpoint`和`method` . + +* `endpoint`应该是请求端点的 URL. +* `method`应为`setData`或`addData` . +* `setData`将下拉列表完全替换为响应数据. +* `addData`将响应数据追加到当前下拉列表中. + +``` +<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a> +<ul id="list" data-dropdown><!-- ... --><ul> +``` + +``` +const droplab = new DropLab(); + +const trigger = document.getElementById('trigger'); +const list = document.getElementById('list'); + +droplab.addHook(trigger, list, [Ajax], { + Ajax: { + endpoint: '/some-endpoint', + method: 'setData', + }, +}); +``` + +(可选)您可以将`loadingTemplate`设置为 HTML 字符串. 请求待处理时,此 HTML 字符串将替换下拉列表. + +此外,您可以将`onError`设置为捕获任何 XHR 错误的函数. \ No newline at end of file diff --git a/_book/docs/587.md b/_book/docs/587.md new file mode 100644 index 0000000000000000000000000000000000000000..4996a0843761fb38bc0c38ba48114d5892d6e7d8 --- /dev/null +++ b/_book/docs/587.md @@ -0,0 +1,19 @@ +# Architecture + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/architecture.html](https://docs.gitlab.com/ee/development/fe_guide/architecture.html) + +* [Examples](#examples) + +# Architecture[](#architecture "Permalink") + +在开发需要架构设计的新功能时,或者在更改现有功能的基本设计时,请确保与前端​​架构专家之一进行了讨论. + +前端架构师是一位专家,负责制定高层的前端设计决策并决定技术标准,包括编码标准和框架. + +每个人都应该可以了解体系结构决策,因此请在相关的"合并请求"讨论中记录它们,或者在适当时更新我们的文档. + +您可以在[团队页面](https://about.gitlab.com/company/team/)上找到 Frontend Architecture 专家. + +## Examples[](#examples "Permalink") + +您可以[在此处](vue.html)找到有关使用 Vue.js 构建的新功能所需架构的文档. \ No newline at end of file diff --git a/_book/docs/588.md b/_book/docs/588.md new file mode 100644 index 0000000000000000000000000000000000000000..2e3331b6a235c8d0a6a8b1fd582706564d571ebf --- /dev/null +++ b/_book/docs/588.md @@ -0,0 +1,85 @@ +# Axios + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/axios.html](https://docs.gitlab.com/ee/development/fe_guide/axios.html) + +* [CSRF token](#csrf-token) +* [Usage](#usage) +* [Mock Axios response in tests](#mock-axios-response-in-tests) + * [Example](#example) + * [Mock poll requests in tests with Axios](#mock-poll-requests-in-tests-with-axios) + +# Axios[](#axios "Permalink") + +我们使用[Axios](https://github.com/axios/axios)在 Vue 应用程序和大多数新代码中与服务器进行通信. + +为了确保设置了所有默认值,您不应*直接使用 Axios* ,而应从`axios_utils`导入 Axios. + +## CSRF token[](#csrf-token "Permalink") + +我们所有的请求都需要 CSRF 令牌. 为了确保设置此令牌,我们将导入[Axios](https://github.com/axios/axios) ,设置令牌并导出`axios` . + +应该使用此导出模块,而不是直接使用 Axios 以确保已设置令牌. + +## Usage[](#usage "Permalink") + +``` + import axios from './lib/utils/axios_utils'; + + axios.get(url) + .then((response) => { + // `data` is the response that was provided by the server + const data = response.data; + + // `headers` the headers that the server responded with + // All header names are lower cased + const paginationData = response.headers; + }) + .catch(() => { + //handle the error + }); +``` + +## Mock Axios response in tests[](#mock-axios-response-in-tests "Permalink") + +为了帮助我们模拟响应,我们使用[axios-mock-adapter](https://github.com/ctimmerm/axios-mock-adapter) . + +比[`spyOn()`](https://jasmine.github.io/api/edge/global.html#spyOn)优势: + +* 无需创建响应对象 +* 不允许通话(我们要避免) +* 简单的 API 来测试错误情况 +* 提供`replyOnce()`以允许不同的响应 + +我们还决定不使用[Axios 拦截器,](https://github.com/axios/axios#interceptors)因为它们不适合模拟. + +### Example[](#example "Permalink") + +``` + import axios from '~/lib/utils/axios_utils'; + import MockAdapter from 'axios-mock-adapter'; + + let mock; + beforeEach(() => { + // This sets the mock adapter on the default instance + mock = new MockAdapter(axios); + // Mock any GET request to /users + // arguments for reply are (status, data, headers) + mock.onGet('/users').reply(200, { + users: [ + { id: 1, name: 'John Smith' } + ] + }); + }); + + afterEach(() => { + mock.restore(); + }); +``` + +### Mock poll requests in tests with Axios[](#mock-poll-requests-in-tests-with-axios "Permalink") + +因为轮询功能需要一个标头对象,所以我们需要始终包含一个对象作为第三个参数: + +``` + mock.onGet('/users').reply(200, { foo: 'bar' }, {}); +``` \ No newline at end of file diff --git a/_book/docs/589.md b/_book/docs/589.md new file mode 100644 index 0000000000000000000000000000000000000000..a96005fac39f4556d02d30c7461f42b0208f4088 --- /dev/null +++ b/_book/docs/589.md @@ -0,0 +1,81 @@ +# Design Patterns + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/design_patterns.html](https://docs.gitlab.com/ee/development/fe_guide/design_patterns.html) + +* [Singletons](#singletons) +* [Manipulating the DOM in a JS Class](#manipulating-the-dom-in-a-js-class) + +# Design Patterns[](#design-patterns "Permalink") + +## Singletons[](#singletons "Permalink") + +当给定任务仅需要一个对象时,最好将其定义为`class`而不是对象文字. 除非灵活性很重要(例如,对于测试),否则也最好明确限制实例化. + +``` +// bad + +const MyThing = { + prop1: 'hello', + method1: () => {} +}; + +export default MyThing; + +// good + +class MyThing { + constructor() { + this.prop1 = 'hello'; + } + method1() {} +} + +export default new MyThing(); + +// best + +export default class MyThing { + constructor() { + if (!MyThing.prototype.singleton) { + this.init(); + MyThing.prototype.singleton = this; + } + return MyThing.prototype.singleton; + } + + init() { + this.prop1 = 'hello'; + } + + method1() {} +} +``` + +## Manipulating the DOM in a JS Class[](#manipulating-the-dom-in-a-js-class "Permalink") + +在编写需要处理 DOM 的类时,请确保提供了一个容器选项. 当我们需要在同一页面中多次实例化该类时,这很有用. + +Bad: + +``` +class Foo { + constructor() { + document.querySelector('.bar'); + } +} +new Foo(); +``` + +Good: + +``` +class Foo { + constructor(opts) { + document.querySelector(`${opts.container} .bar`); + } +} + +new Foo({ container: '.my-element' }); +``` + +您可以在这上面的例子[类](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/javascripts/mini_pipeline_graph_dropdown.js) ; \ No newline at end of file diff --git a/_book/docs/590.md b/_book/docs/590.md new file mode 100644 index 0000000000000000000000000000000000000000..adf7e20d3ac3a3e4383cff22eda647db47a73dc7 --- /dev/null +++ b/_book/docs/590.md @@ -0,0 +1,98 @@ +# Frontend Development Process + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/development_process.html](https://docs.gitlab.com/ee/development/fe_guide/development_process.html) + +* [Development Checklist](#development-checklist) + * [Merge Request Review](#merge-request-review) + * [Share your work early](#share-your-work-early) + * [Vue features](#vue-features) + +# Frontend Development Process[](#frontend-development-process "Permalink") + +您可以在[手册中](https://about.gitlab.com/handbook/engineering/frontend/)找到有关前端团队组织的更多信息. + +## Development Checklist[](#development-checklist "Permalink") + +这个想法是在构建新功能或启动某些东西时提醒我们有关特定主题的信息. 这是其他行业(如飞行员)的常见做法,这些行业也使用标准化清单来尽早减少问题. + +将内容复制到您的问题或合并请求中,如果不适用,则将其从当前列表中删除. + +此清单旨在在开发更大的功能/重构时为我们提供帮助,而不是"始终使用它,并且每个点始终匹配"列表. + +请在使用时做出最好的判断,如果有想法请通过合并请求贡献新的积分. + +``` +### Frontend development + +#### Planning development + - [ ] Check the current set weight of the issue, does it fit your estimate? +- [ ] Are all [departments](https://about.gitlab.com/handbook/engineering/#engineering-teams) that are needed from your perspective already involved in the issue? (For example is UX missing?) +- [ ] Is the specification complete? Are you missing decisions? How about error handling/defaults/edge cases? Take your time to understand the needed implementation and go through its flow. +- [ ] Are all necessary UX specifications available that you will need in order to implement? Are there new UX components/patterns in the designs? Then contact the UI component team early on. How should error messages or validation be handled? +- [ ] **Library usage** Use Vuex as soon as you have even a medium state to manage, use Vue router if you need to have different views internally and want to link from the outside. Check what libraries we already have for which occasions. +- [ ] **Plan your implementation:** + - [ ] **Architecture plan:** Create a plan aligned with GitLab's architecture, how you are going to do the implementation, for example Vue application setup and its components (through [onion skinning](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35873#note_39994091)), Store structure and data flow, which existing Vue components can you reuse. It's a good idea to go through your plan with another engineer to refine it. + - [ ] **Backend:** The best way is to kickoff the implementation in a call and discuss with the assigned Backend engineer what you will need from the backend and also when. Can you reuse existing API's? How is the performance with the planned architecture? Maybe create together a JSON mock object to already start with development. + - [ ] **Communication:** It also makes sense to have for bigger features an own slack channel (normally called #f_{feature_name}) and even weekly demo calls with all people involved. + - [ ] **Dependency Plan:** Are there big dependencies in the plan between you and others, then maybe create an execution diagram to show what is blocking which part and the order of the different parts. + - [ ] **Task list:** Create a simple checklist of the subtasks that are needed for the implementation, also consider creating even sub issues. (for example show a comment, delete a comment, update a comment, etc.). This helps you and also everyone else following the implementation +- [ ] **Keep it small** To make it easier for you and also all reviewers try to keep merge requests small and merge into a feature branch if needed. To accomplish that you need to plan that from the start. Different methods are: + - [ ] **Skeleton based plan** Start with an MR that has the skeleton of the components with placeholder content. In following MRs you can fill the components with interactivity. This also makes it easier to spread out development on multiple people. + - [ ] **Cookie Mode** Think about hiding the feature behind a cookie flag if the implementation is on top of existing features + - [ ] **New route** Are you refactoring something big then you might consider adding a new route where you implement the new feature and when finished delete the current route and rename the new one. (for example 'merge_request' and 'new_merge_request') +- [ ] **Setup** Is there any specific setup needed for your implementation (for example a kubernetes cluster)? Then let everyone know if it is not already mentioned where they can find documentation (if it doesn't exist - create it) +- [ ] **Security** Are there any new security relevant implementations? Then please contact the security team for an app security review. If you are not sure ask our [domain expert](https://about.gitlab.com/handbook/engineering/frontend/#frontend-domain-experts) + +#### During development + - [ ] Check off tasks on your created task list to keep everyone updated on the progress +- [ ] [Share your work early with reviewers/maintainers](#share-your-work-early) +- [ ] Share your work with UXer and Product Manager with Screenshots and/or [GIF's](https://about.gitlab.com/handbook/product/making-gifs/). They are easy to create for you and keep them up to date. +- [ ] If you are blocked on something let everyone on the issue know through a comment. +- [ ] Are you unable to work on this issue for a longer period of time, also let everyone know. +- [ ] **Documentation** Update/add docs for the new feature, see `docs/`. Ping one of the documentation experts/reviewers + +#### Finishing development + Review + - [ ] **Keep it in the scope** Try to focus on the actual scope and avoid a scope creep during review and keep new things to new issues. +- [ ] **Performance** Have you checked performance? For example do the same thing with 500 comments instead of 1\. Document the tests and possible findings in the MR so a reviewer can directly see it. +- [ ] Have you tested with a variety of our [supported browsers](../../install/requirements.md#supported-web-browsers)? You can use [browserstack](https://www.browserstack.com/) to be able to access a wide variety of browsers and operating systems. +- [ ] Did you check the mobile view? +- [ ] Check the built webpack bundle (For the report run `WEBPACK_REPORT=true gdk run`, then open `webpack-report/index.html`) if we have unnecessary bloat due to wrong references, including libraries multiple times, etc.. If you need help contact the webpack [domain expert](https://about.gitlab.com/handbook/engineering/frontend/#frontend-domain-experts) +- [ ] **Tests** Not only greenfield tests - Test also all bad cases that come to your mind. +- [ ] If you have multiple MR's then also smoke test against the final merge. +- [ ] Are there any big changes on how and especially how frequently we use the API then let production know about it +- [ ] Smoke test of the RC on dev., staging., canary deployments and .com +- [ ] Follow up on issues that came out of the review. Create issues for discovered edge cases that should be covered in future iterations. +``` + +### Merge Request Review[](#merge-request-review "Permalink") + +为了[尊重他人的时间,](https://about.gitlab.com/handbook/values/#be-respectful-of-others-time)在进行审核[时,](https://about.gitlab.com/handbook/values/#be-respectful-of-others-time)请遵循以下准则: + +* 确保您的合并请求: + * 里程碑已设定 + * 至少设置了危险机器人建议的标签 + * 有清晰的描述 + * 如果 UI 发生更改,则包括屏幕截图之前/之后 + * 管道是绿色的 + * 包括测试 + * 包括变更日志条目(必要时) +* 在分配给维护者之前,请分配给审阅者. +* 如果您分配了合并请求或直接对某人执行 ping 操作,请耐心等待,因为我们在不同时区且异步工作. 除非紧急合并请求(例如修复损坏的主服务器),否则请不要 DM 或重新分配合并请求,然后再等待 24 小时窗口. +* 如果您对合并请求/问题有疑问,请在合并请求/问题中提出. 当我们彼此进行 DM 交流时,我们将不再拥有 SSOT,并且[其他人也无法做出贡献](https://about.gitlab.com/handbook/values/#public-by-default) . +* 如果您有一个包含许多更改的大型**Draft**合并请求,建议您在添加/删除重要代码之前开始审阅. 确保在发布截止日期之前就已对其进行了分配,因为审阅者/维护者将始终优先于**草稿中**优先审阅已完成的 MR. +* 确保在上一轮审核之前删除" `Draft:`标题. + +### Share your work early[](#share-your-work-early "Permalink") + +1. 在编写代码之前,请确保您对体系结构的了解与 GitLab 的体系结构保持一致. +2. Add a diagram to the issue and ask a frontend maintainer in the Slack channel `#frontend_maintainers` about it. + + [![Diagram of Issue Boards Architecture](img/11b32b9624ee5e827950dd6f126127d6.png)](img/boards_diagram.png) + +3. 从开始一项功能到与审阅者或维护者共享"合并请求"之间的时间不要超过一周. + +### Vue features[](#vue-features "Permalink") + +1. 请遵循[Vue.js 最佳做法中](vue.html)的步骤 +2. 遵循样式指南. +3. 仅有少数几个人可以合并 Vue 相关功能. 在此过程的早期,请一位 Vue 专家联系. \ No newline at end of file diff --git a/_book/docs/591.md b/_book/docs/591.md new file mode 100644 index 0000000000000000000000000000000000000000..e4ce82cba6f914a3595249841cdf1bc0ab6f74e5 --- /dev/null +++ b/_book/docs/591.md @@ -0,0 +1,259 @@ +# DropLab + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/droplab/droplab.html](https://docs.gitlab.com/ee/development/fe_guide/droplab/droplab.html) + +* [Usage](#usage) + * [Static data](#static-data) + * [Explicit instantiation](#explicit-instantiation) + * [Dynamic data](#dynamic-data) +* [Internal selectors](#internal-selectors) +* [Internal events](#internal-events) +* [Plugins](#plugins) + * [Usage](#usage-1) + * [Documentation](#documentation) + * [Development](#development) + +# DropLab[](#droplab "Permalink") + +满足您所有自定义下拉菜单需求的通用下拉菜单. + +## Usage[](#usage "Permalink") + +只需添加`data-dropdown-trigger` HTML 属性即可使用 DropLab. 此属性使我们能够找到下拉菜单的"触发" *(切换)* ,无论是按钮,链接还是输入. + +`data-dropdown-trigger`应该是 DropLab 可以用来查找触发器的下拉列表的 CSS 选择器. + +您还应该添加`data-dropdown`属性以声明下拉列表. 该值无关紧要. + +DropLab 类没有副作用,因此在 DOM 准备就绪时,必须始终调用`.init` . `DropLab.prototype.init`的参数与`DropLab.prototype.addHook`相同. 如果不提供任何参数,它将全局查询并实例化所有与 droplab 兼容的下拉菜单. + +``` +<a href="#" data-dropdown-trigger="#list">Toggle</a> + +<ul id="list" data-dropdown> + <!-- ... --> +<ul> +``` + +``` +const droplab = new DropLab(); +droplab.init(); +``` + +As you can see, we have a “Toggle” link, that is declared as a trigger. It provides a selector to find the dropdown list it should control. + +### Static data[](#static-data "Permalink") + +您可以添加静态列表项. + +``` +<a href="#" data-dropdown-trigger="#list">Toggle</a> + +<ul id="list" data-dropdown> + <li>Static value 1</li> + <li>Static value 2</li> +<ul> +``` + +``` +const droplab = new DropLab(); +droplab.init(); +``` + +### Explicit instantiation[](#explicit-instantiation "Permalink") + +您可以使用`DropLab.prototype.init`方法将 trigger 和 list 元素作为构造函数参数传递,以返回 DropLab 的非全局实例. + +``` +<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a> + +<ul id="list" data-dropdown> + <!-- ... --> +<ul> +``` + +``` +const trigger = document.getElementById('trigger'); +const list = document.getElementById('list'); + +const droplab = new DropLab(); +droplab.init(trigger, list); +``` + +您还可以使用`DropLab.prototype.addHook`将挂钩添加到现有的 DropLab 实例. + +``` +<a href="#" data-dropdown-trigger="#auto-dropdown">Toggle</a> +<ul id="auto-dropdown" data-dropdown><!-- ... --><ul> + +<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a> +<ul id="list" data-dropdown><!-- ... --><ul> +``` + +``` +const droplab = new DropLab(); + +droplab.init(); + +const trigger = document.getElementById('trigger'); +const list = document.getElementById('list'); + +droplab.addHook(trigger, list); +``` + +### Dynamic data[](#dynamic-data "Permalink") + +将`data-dynamic`添加到下拉元素将启用动态列表呈现. + +您可以使用提供的数据对象的键对列表项进行模板化. 使用车把语法`{{ value }}`使 HTML 转义该值. 使用`<%= value %>`语法可以简单地插值. 使用`<%= value %>`语法评估该值. + +将对象数组传递给`DropLab.prototype.addData`将为该 DropLab 实例跟踪的所有`data-dynamic`下拉列表呈现该数据. + +``` +<a href="#" data-dropdown-trigger="#list">Toggle</a> + +<ul id="list" data-dropdown data-dynamic> + <li><a href="#" data-id="{{id}}">{{text}}</a></li> +</ul> +``` + +``` +const droplab = new DropLab(); + +droplab.init().addData([{ + id: 0, + text: 'Jacob', +}, { + id: 1, + text: 'Jeff', +}]); +``` + +或者,您可以指定一个特定的下拉菜单,以将数据添加到该数据,但将数据作为第二个参数传递,并将 trigger 元素的`id`作为第一个参数传递. + +``` +<a href="#" data-dropdown-trigger="#list" id="trigger">Toggle</a> + +<ul id="list" data-dropdown data-dynamic> + <li><a href="#" data-id="{{id}}">{{text}}</a></li> +</ul> +``` + +``` +const droplab = new DropLab(); + +droplab.init().addData('trigger', [{ + id: 0, + text: 'Jacob', +}, { + id: 1, + text: 'Jeff', +}]); +``` + +这使您可以轻松混合静态和动态内容,即使使用一个触发器也是如此. + +请注意,在有关`data-dropdown`属性的范围内使用范围来捕获两个下拉列表,其中之一是动态的. + +``` +<input id="trigger" data-dropdown-trigger="#list"> +<div id="list" data-dropdown> + <ul> + <li><a href="#">Static item 1</a></li> + <li><a href="#">Static item 2</a></li> + </ul> + <ul data-dynamic> + <li><a href="#" data-id="{{id}}">{{text}}</a></li> + </ul> +</div> +``` + +``` +const droplab = new DropLab(); + +droplab.init().addData('trigger', [{ + id: 0, + text: 'Jacob', +}, { + id: 1, + text: 'Jeff', +}]); +``` + +## Internal selectors[](#internal-selectors "Permalink") + +DropLab 添加了一些 CSS 类,以帮助降低集成的障碍. + +例如: + +* 将`droplab-item-selected` CSS 类添加到通过单击鼠标或 Enter 键选择的项目中. +* 将`droplab-item-active` CSS 类添加到使用箭头键导航选择的项目中. +* 您可以将`droplab-item-ignore` CSS 类添加到您不想选择的任何项目中. 例如,一个不应为交互式的`<li class="divider"></li>`列表分隔符元素. + +## Internal events[](#internal-events "Permalink") + +DropLab 使用一些自定义事件来帮助降低集成障碍. + +例如: + +* 单击`li`列表项时会触发`click.dl`事件. 当使用键盘选择了列表项时,也会触发该事件. 当它也烧`HookButton`按键(注册`button`标签或`a`标签触发). +* 所述`input.dl`当事件被触发`HookInput` (注册`input`标签触发)触发`input`事件. +* 该`mousedown.dl`当事件被触发`HookInput`触发`mousedown`事件. +* 该`keyup.dl`当事件被触发`HookInput`触发`keyup`事件. +* 该`keydown.dl`当事件被触发`HookInput`触发`keydown`事件. + +这些自定义事件将`detail`对象添加到提供一些潜在有用数据的原始`Event`对象. + +## Plugins[](#plugins "Permalink") + +插件是添加钩子后被注册为要执行的对象(实例化 droplab 触发器和下拉菜单时). + +如果未检测到模块 API,则该库将像使用`window.DropLab`那样回退,并添加`window.DropLab.plugins.PluginName` . + +### Usage[](#usage-1 "Permalink") + +要使用插件,您可以将它们作为`DropLab.prototype.init`或`DropLab.prototype.addHook`的第三个参数传递给数组. 一些插件需要配置值,可以将 config 对象作为第四个参数传递. + +``` +<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a> +<ul id="list" data-dropdown><!-- ... --><ul> +``` + +``` +const droplab = new DropLab(); + +const trigger = document.getElementById('trigger'); +const list = document.getElementById('list'); + +droplab.init(trigger, list, [droplabAjax], { + droplabAjax: { + endpoint: '/some-endpoint', + method: 'setData', + }, +}); +``` + +### Documentation[](#documentation "Permalink") + +* [Ajax plugin](plugins/ajax.html) +* [Filter plugin](plugins/filter.html) +* [InputSetter plugin](plugins/input_setter.html) + +### Development[](#development "Permalink") + +当为 droplab 触发器+下拉菜单初始化插件时,DropLab 将调用插件的`init`函数,因此必须在插件中实现. + +``` +class MyPlugin { + static init() { + this.someProp = 'someProp'; + this.someMethod(); + } + + static someMethod() { + this.otherProp = 'otherProp'; + } +} + +export default MyPlugin; +``` \ No newline at end of file diff --git a/_book/docs/592.md b/_book/docs/592.md new file mode 100644 index 0000000000000000000000000000000000000000..34771b9fee35acf1a38e7e061da9869b52c0e774 --- /dev/null +++ b/_book/docs/592.md @@ -0,0 +1,25 @@ +# Emojis + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/emojis.html](https://docs.gitlab.com/ee/development/fe_guide/emojis.html) + +* [How to update Emojis](#how-to-update-emojis) + +# Emojis[](#emojis "Permalink") + +GitLab 支持本机 Unicode 表情符号,当您的平台不支持它时,它有选择地回退到基于图像的表情符号. + +## How to update Emojis[](#how-to-update-emojis "Permalink") + +1. 更新`gemojione`宝石 +2. 从[Gemojione](https://github.com/bonusly/gemojione/blob/master/config/index.json)更新`fixtures/emojis/index.json` [emojis](https://github.com/bonusly/gemojione/blob/master/config/index.json) `fixtures/emojis/index.json` . 将来,我们可以直接从 gem 获取文件. 我们可能应该对 Gemojione 项目进行 PR,以在解析后获得对所有表情符号的访问权,或者仅获取`json`文件本身的原始路径. +3. 确保[`emoji-unicode-version`](https://s0www0npmjs0com.icopy.site/package/emoji-unicode-version)是最新版本. +4. Run `bundle exec rake gemojione:aliases` +5. Run `bundle exec rake gemojione:digests` +6. Run `bundle exec rake gemojione:sprite` +7. 确保为 1x 和 2x 生成新的 Sprite 表 + * `app/assets/images/emoji.png` + * `app/assets/images/emoji@2x.png` +8. 确保您看到新的单个图像复制到`app/assets/images/emoji/` +9. 确保您可以在 GFM 自动完成功能中看到新的表情符号及其别名 +10. 确保您可以在奖励表情符号菜单中看到新的表情符号及其别名 +11. 您可能需要为不支持某些表情符号的平台添加新的表情符号 Unicode 支持检查和规则,我们需要回退到图像. 请参阅`app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js`和`app/assets/javascripts/emoji/support/unicode_support_map.js` \ No newline at end of file diff --git a/_book/docs/593.md b/_book/docs/593.md new file mode 100644 index 0000000000000000000000000000000000000000..a58e40f63e4b6843e2386f898df169a1333f71d5 --- /dev/null +++ b/_book/docs/593.md @@ -0,0 +1,48 @@ +# Filter + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/droplab/plugins/filter.html](https://docs.gitlab.com/ee/development/fe_guide/droplab/plugins/filter.html) + +* [Usage](#usage) + +# Filter[](#filter "Permalink") + +`Filter`是一个插件,它允许使用简单的模糊字符串搜索输入值来过滤已添加到下拉列表中的数据. + +## Usage[](#usage "Permalink") + +将`Filter`对象添加到`DropLab.prototype.init`或`DropLab.prototype.addHook`调用的插件数组中. + +* `Filter`需要`template`的配置值. +* `template`应该是要与用户输入字符串进行比较以进行过滤的数据数组中对象的键. + +``` +<input href="#" id="trigger" data-dropdown-trigger="#list"> +<ul id="list" data-dropdown data-dynamic> + <li><a href="#" data-id="{{id}}">{{text}}</a></li> +<ul> +``` + +``` +const droplab = new DropLab(); + +const trigger = document.getElementById('trigger'); +const list = document.getElementById('list'); + +droplab.init(trigger, list, [Filter], { + Filter: { + template: 'text', + }, +}); + +droplab.addData('trigger', [{ + id: 0, + text: 'Jacob', +}, { + id: 1, + text: 'Jeff', +}]); +``` + +上面,输入字符串将与传递的数据对象的`test`键进行比较. + +您可以选择将`filterFunction`设置为一个函数. 将使用此函数代替`Filter`的内置字符串搜索. `filterFunction`传递了 2 个参数,第一个是数据对象之一,第二个是当前输入值. \ No newline at end of file diff --git a/_book/docs/594.md b/_book/docs/594.md new file mode 100644 index 0000000000000000000000000000000000000000..e67f4113a5a7ea80a61e3c76c0a776bf214fc9ce --- /dev/null +++ b/_book/docs/594.md @@ -0,0 +1,146 @@ +# Frontend FAQ + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/frontend_faq.html](https://docs.gitlab.com/ee/development/fe_guide/frontend_faq.html) + +* [Rules of Frontend FAQ](#rules-of-frontend-faq) +* [FAQ](#faq) + * [1\. How do I find the Rails route for a page?](#1-how-do-i-find-the-rails-route-for-a-page) + * [Check the ‘page’ data attribute](#check-the-page-data-attribute) + * [Rails routes](#rails-routes) + * [2\. `modal_copy_button` vs `clipboard_button`](#2-modal_copy_button-vs-clipboard_button) + * [3\. A `gitlab-ui` component not conforming to Pajamas Design System](#3-a-gitlab-ui-component-not-conforming-to-pajamas-design-system) + * [4\. My submit form button becomes disabled after submitting](#4-my-submit-form-button-becomes-disabled-after-submitting) + * [5\. Should I use a full URL (i.e. `gon.gitlab_url`) or a full path (i.e. `gon.relative_url_root`) when referencing backend endpoints?](#5-should-i-use-a-full-url-ie-gongitlab_url-or-a-full-path-ie-gonrelative_url_root-when-referencing-backend-endpoints) + * [6\. How should the Frontend reference Backend paths?](#6-how-should-the-frontend-reference-backend-paths) + * [7\. How can I test the production build locally?](#7-how-can-i-test-the-production-build-locally) + +# Frontend FAQ[](#frontend-faq "Permalink") + +## Rules of Frontend FAQ[](#rules-of-frontend-faq "Permalink") + +1. **您谈论前端常见问题解答.** 请在适当的情况下共享指向它的链接,以便在内容过时时引起更多关注. +2. **保持简短和简单.** 只要答案需要两个以上的句子,它就不属于这里. +3. **尽可能提供背景.** 链接到相关的源代码,问题/史诗或其他文档有助于理解答案. +4. **如果您看到某些内容,请执行某些操作.** 看到后,请删除或更新任何过时的内容. + +## FAQ[](#faq "Permalink") + +### 1\. How do I find the Rails route for a page?[](#1-how-do-i-find-the-rails-route-for-a-page "Permalink") + +#### Check the ‘page’ data attribute[](#check-the-page-data-attribute "Permalink") + +最简单的方法是在相关页面上的浏览器中键入以下内容: + +``` +document.body.dataset.page +``` + +在此处找到[设置属性](https://gitlab.com/gitlab-org/gitlab/blob/cc5095edfce2b4d4083a4fb1cdc7c0a1898b9921/app/views/layouts/application.html.haml#L4)的[源代码](https://gitlab.com/gitlab-org/gitlab/blob/cc5095edfce2b4d4083a4fb1cdc7c0a1898b9921/app/views/layouts/application.html.haml#L4) . + +#### Rails routes[](#rails-routes "Permalink") + +The `rake routes` command can be used to list all the routes available in the application, piping the output into `grep`, we can perform a search through the list of available routes. The output includes the request types available, route parameters and the relevant controller. + +``` +bundle exec rake routes | grep "issues" +``` + +### 2\. `modal_copy_button` vs `clipboard_button`[](#2-modal_copy_button-vs-clipboard_button "Permalink") + +该`clipboard_button`使用`copy_to_clipboard.js`行为,这是在页面加载初始化,所以如果有不会在页面加载存在(如那些在基于 VUE 剪贴板按钮`GlModal` ),他们没有相关的点击处理程序与剪贴板包. + +添加了`modal_copy_button` ,用于管理特定于该组件实例的[`clipboard`插件](https://s0www0npmjs0com.icopy.site/package/clipboard)的实例,这意味着剪贴板事件在安装时绑定并在按钮按下时销毁,从而减轻了上述问题. 它还具有绑定到可用的特定容器或模式 ID 的功能,以与我们的 GlModal 创建的焦点陷阱一起使用. + +### 3\. A `gitlab-ui` component not conforming to [Pajamas Design System](https://design.gitlab.com/)[](#3-a-gitlab-ui-component-not-conforming-to-pajamas-design-system "Permalink") + +`gitlab-ui`实现的某些[睡衣设计系统](https://design.gitlab.com/)组件不符合设计系统规范,因为它们缺少某些计划的功能或样式尚未正确. 在睡衣网站上,组件示例顶部的标语指示: + +> 该组件尚未符合我们设计系统中定义的正确样式. 引用此组件的外观时,请参考 Design System 文档. + +例如,在撰写本文时,可以针对[所有表单组件](https://design.gitlab.com/components/forms/)观察到这种类型的警告. 但是,这并不意味着不应使用该组件. + +只要有合适的组件,GitLab 都会要求使用`<gl-*>`组件. 它使代码库变得统一,并且将来可以更轻松地进行维护/重构. + +确保[产品设计师](https://about.gitlab.com/company/team/?department=ux-department)在 MR 审查中审查不合格组件的使用. 提出后续问题,并将其附加到" [睡衣设计系统组件"](https://gitlab.com/groups/gitlab-org/-/epics/973)史诗中的组件实现[史诗中](https://gitlab.com/groups/gitlab-org/-/epics/973) . + +### 4\. My submit form button becomes disabled after submitting[](#4-my-submit-form-button-becomes-disabled-after-submitting "Permalink") + +如果在表单内使用提交按钮,并且在表单元素上附加了`onSubmit`事件侦听器,则[这段代码](https://gitlab.com/gitlab-org/gitlab/blob/794c247a910e2759ce9b401356432a38a4535d49/app/assets/javascripts/main.js#L225)将在提交表单时向提交按钮添加一个`disabled`类选择器. 为避免这种情况,请将`js-no-auto-disable`类添加到按钮. + +### 5\. Should I use a full URL (i.e. `gon.gitlab_url`) or a full path (i.e. `gon.relative_url_root`) when referencing backend endpoints?[](#5-should-i-use-a-full-url-ie-gongitlab_url-or-a-full-path-ie-gonrelative_url_root-when-referencing-backend-endpoints "Permalink") + +最好在**完整 URL**上使用**完整路径** ,因为 URL 将使用通过 GitLab 配置的主机名,该主机名可能与请求不匹配. 这将导致[像 Web IDE 这样的 CORS 问题](https://gitlab.com/gitlab-org/gitlab/-/issues/36810) . + +Example: + +``` +// bad :( +// If gitlab is configured with hostname `0.0.0.0` +// This will cause CORS issues if I request from `localhost` +axios.get(joinPaths(gon.gitlab_url, '-', 'foo')) + +// good :) +axios.get(joinPaths(gon.relative_url_root, '-', 'foo')) +``` + +另外,请尽量不要在前端中对路径进行硬编码,而应从后端接收它们(请参阅下一节). 引用后端导轨路径时,请避免使用`*_url` ,而应使用`*_path` . + +Example: + +``` +-# Bad :( #js-foo{ data: { foo_url: some_rails_foo_url } } + +-# Good :) #js-foo{ data: { foo_path: some_rails_foo_path } } +``` + +### 6\. How should the Frontend reference Backend paths?[](#6-how-should-the-frontend-reference-backend-paths "Permalink") + +我们不希望通过硬编码路径添加额外的耦合. 如果可能,请将这些路径作为数据属性添加到 JavaScript 中引用的 DOM 元素. + +Example: + +``` +// Bad :( +// Here's a Vuex action that hardcodes a path :( +export const fetchFoos = ({ state }) => { + return axios.get(joinPaths(gon.relative_url_root, '-', 'foo')); +}; + +// Good :) +function initFoo() { + const el = document.getElementById('js-foo'); + + // Path comes from our root element's data which is used to initialize the store :) + const store = createStore({ + fooPath: el.dataset.fooPath + }); + + Vue.extend({ + store, + el, + render(h) { + return h(Component); + }, + }); +} + +// Vuex action can now reference the path from its state :) +export const fetchFoos = ({ state }) => { + return axios.get(state.settings.fooPath); +}; +``` + +### 7\. How can I test the production build locally?[](#7-how-can-i-test-the-production-build-locally "Permalink") + +有时有必要在本地测试前端生产版本将产生什么,为此,步骤如下: + +1. 停止 webpack: `gdk stop webpack` . +2. 打开`gitlab.yaml`位于您`gitlab`安装文件夹,向下滚动到`webpack`部分和变化`dev_server`到`enabled: false` . +3. Run `yarn webpack-prod && gdk restart rails-web`. + +生产构建需要几分钟才能完成; 仅在再次执行上面的第 3 项后,此时才会显示任何代码更改. 要返回正常的开发模式: + +1. 打开`gitlab.yaml`位于您`gitlab`安装文件夹,向下滚动到`webpack`部分和变回`dev_server`到`enabled: true` . +2. `yarn clean`以除去生产资产并释放一些空间(可选). +3. 重新启动 webpack: `gdk start webpack` . +4. 重新启动 GDK: `gdk-restart rails-web` . \ No newline at end of file diff --git a/_book/docs/595.md b/_book/docs/595.md new file mode 100644 index 0000000000000000000000000000000000000000..97b88ecb4178108952ae67df1ce67e3a8005c30c --- /dev/null +++ b/_book/docs/595.md @@ -0,0 +1,653 @@ +# GraphQL + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/graphql.html](https://docs.gitlab.com/ee/development/fe_guide/graphql.html) + +* [Getting Started](#getting-started) + * [Helpful Resources](#helpful-resources) + * [Libraries](#libraries) + * [Tooling](#tooling) + * [Apollo GraphQL VS Code extension](#apollo-graphql-vs-code-extension) + * [Exploring the GraphQL API](#exploring-the-graphql-api) +* [Apollo Client](#apollo-client) +* [GraphQL Queries](#graphql-queries) + * [Fragments](#fragments) +* [Usage in Vue](#usage-in-vue) + * [Local state with Apollo](#local-state-with-apollo) + * [Mocking API response with local Apollo cache](#mocking-api-response-with-local-apollo-cache) + * [Using with Vuex](#using-with-vuex) + * [Feature flags in queries](#feature-flags-in-queries) + * [Manually triggering queries](#manually-triggering-queries) + * [Working with pagination](#working-with-pagination) + * [Using `fetchMore` method in components](#using-fetchmore-method-in-components) + * [Testing](#testing) + * [Mocking response as component data](#mocking-response-as-component-data) + * [Testing loading state](#testing-loading-state) + * [Testing Apollo components](#testing-apollo-components) +* [Handling errors](#handling-errors) + * [Top-level errors](#top-level-errors) + * [Handling top-level errors](#handling-top-level-errors) + * [Errors-as-data](#errors-as-data) + * [Handling errors-as-data](#handling-errors-as-data) +* [Usage outside of Vue](#usage-outside-of-vue) + +# GraphQL[](#graphql "Permalink") + +## Getting Started[](#getting-started "Permalink") + +### Helpful Resources[](#helpful-resources "Permalink") + +**一般资源**: + +* [📚 Official Introduction to GraphQL](https://s0graphql0org.icopy.site/learn/) +* [📚 Official Introduction to Apollo](https://www.apollographql.com/docs/tutorial/introduction/) + +**GitLab 上的 GraphQL**: + +* [🎬 GitLab Unfiltered GraphQL playlist](https://www.youtube.com/watch?v=wHPKZBDMfxE&list=PL05JrBw4t0KpcjeHjaRMB7IGB2oDWyJzv) +* [GitLab 上的 GraphQL:深潜](../api_graphql_styleguide.html#deep-dive) (视频)作者 Nick Thomas + * GitLab 上 GraphQL 的历史概述(不是特定于前端的) +* [使用 GraphQL 和 Vue Apollo 进行 GitLab 功能演练](https://www.youtube.com/watch?v=6yYp2zB7FrM) (视频),作者 Natalia Tepluhina + * 使用 GraphQL 在 GitLab 中实现前端功能的真实示例 +* [GitLab 上的客户端 GraphQL 的历史](https://www.youtube.com/watch?v=mCKRJxvMnf0) (视频)Illya Klymov 和 Natalia Tepluhina +* Natalia Tepluhina [从 Vuex 到 Apollo](https://www.youtube.com/watch?v=9knwu87IfU8) (视频) + * 关于何时阿波罗可能比 Vuex 更好的选择以及如何进行过渡的有用概述 +* [🛠 Vuex -> Apollo Migration: a proof-of-concept project](https://gitlab.com/ntepluhina/vuex-to-apollo/blob/master/README.md) + * 一系列示例展示了使用 Vue + GraphQL +(Vuex 或 Apollo)应用进行状态管理的可能方法 + +### Libraries[](#libraries "Permalink") + +当使用 GraphQL 进行前端开发时,我们使用[Apollo](https://www.apollographql.com/) (特别是[Apollo Client](https://www.apollographql.com/docs/react/) )和[Vue Apollo](https://github.com/vuejs/vue-apollo) . + +如果在 Vue 应用程序中使用 GraphQL,则" Vue 中的[用法"](#usage-in-vue)部分可以帮助您学习如何集成 Vue Apollo. + +对于其他用例,请查看[Vue 外部](#usage-outside-of-vue)的[用法](#usage-outside-of-vue)部分. + +### Tooling[](#tooling "Permalink") + +* [Apollo Client Devtools](https://github.com/apollographql/apollo-client-devtools) + +#### [Apollo GraphQL VS Code extension](https://marketplace.visualstudio.com/items?itemName=apollographql.vscode-apollo)[](#apollo-graphql-vs-code-extension "Permalink") + +如果使用 VS Code,则 Apollo GraphQL 扩展名支持`.graphql`文件中的自动完成. 若要设置 GraphQL 扩展,请按照下列步骤操作: + +1. 将`apollo.config.js`文件添加到`gitlab`本地目录的根目录中. +2. 用以下内容填充文件: + + ``` + module.exports = { + client: { + includes: ['./app/assets/javascripts/**/*.graphql', './ee/app/assets/javascripts/**/*.graphql'], + service: { + name: 'GitLab', + localSchemaFile: './doc/api/graphql/reference/gitlab_schema.graphql', + }, + }, + }; + ``` + +3. 重新启动 VS Code. + +### Exploring the GraphQL API[](#exploring-the-graphql-api "Permalink") + +我们 GraphQL API 可以通过 GraphiQL 在您的实例的探索`/-/graphql-explorer`或[GitLab.com](https://gitlab.com/-/graphql-explorer) . 如有需要,请查阅《 [GitLab GraphQL API 参考》文档](../../api/graphql/reference) . + +您可以在 GraphiQL 的**文档浏览器**的右侧检查所有现有的查询和变异. 也可以直接在左选项卡上编写查询和变异,然后单击左上角的**执行查询**按钮来检查其执行情况: + +[![GraphiQL interface](img/40cd53294c496a4d049d735386c16649.png)](img/graphiql_explorer_v12_4.png) + +## Apollo Client[](#apollo-client "Permalink") + +为了保存在不同的应用程序中创建的重复客户端,我们使用[默认客户端](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/javascripts/lib/graphql.js) . 这将使用正确的 URL 设置 Apollo 客户端,并设置 CSRF 标头. + +默认客户端接受两个参数: `resolvers`和`config` . + +* 创建`resolvers`参数以接受用于[本地状态管理](#local-state-with-apollo)查询和突变的 resolvers 对象 +* `config`参数采用配置设置的对象: + * `cacheConfig`字段接受设置的可选对象以[自定义 Apollo 缓存](https://www.apollographql.com/docs/react/caching/cache-configuration/#configuring-the-cache) + * `baseUrl`允许我们传递与主端点不同的 GraphQL 端点的 URL(即`${gon.relative_url_root}/api/graphql` ) + * `assumeImmutableResults` (默认设置为`false` )-此设置为`true` ,将假定更新 Apollo Cache 时的每个操作都是不可变的. 它还将`freezeResults`设置为`true` ,因此任何尝试`freezeResults` Apollo Cache 的尝试都会在开发环境中引发控制台警告. 在将此选项设置为`true`之前,请确保在缓存更新操作中遵循不变性模式. + +## GraphQL Queries[](#graphql-queries "Permalink") + +为了在运行时保存查询编译,webpack 可以直接导入`.graphql`文件. 这使 webpack 可以在编译时对查询进行预处理,而不是由客户端进行查询的编译. + +为了将查询与突变和片段区分开来,建议使用以下命名约定: + +* `all_users.query.graphql`用于查询; +* `add_user.mutation.graphql`进行突变; +* 片段的`basic_user.fragment.graphql` . + +### Fragments[](#fragments "Permalink") + +[片段](https://s0graphql0org.icopy.site/learn/queries/)是使复杂的 GraphQL 查询更具可读性和可重用性的一种方式. 这是 GraphQL 片段的示例: + +``` +fragment DesignListItem on Design { + id + image + event + filename + notesCount +} +``` + +片段可以存储在单独的文件中,可以导入并用于查询,突变或其他片段. + +``` +#import "./design_list.fragment.graphql" +#import "./diff_refs.fragment.graphql" + +fragment DesignItem on Design { + ...DesignListItem + fullPath + diffRefs { + ...DesignDiffRefs + } +} +``` + +有关片段的更多信息: [GraphQL Docs](https://s0graphql0org.icopy.site/learn/queries/) + +## Usage in Vue[](#usage-in-vue "Permalink") + +要使用 Vue Apollo,请导入[Vue Apollo](https://github.com/vuejs/vue-apollo)插件以及默认客户端. 这应该在安装 Vue 应用程序的同一时间创建. + +``` +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; +Vue.use(VueApollo); + +const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient(), +}); + +new Vue({ + ..., + apolloProvider, + ... +}); +``` + +在[Vue Apollo 文档中](https://vue-apollo.netlify.app/guide/)阅读有关[Vue Apollo 的](https://github.com/vuejs/vue-apollo)更多信息. + +### Local state with Apollo[](#local-state-with-apollo "Permalink") + +创建默认客户端时,可以通过传入 resolvers 对象来使用 Apollo 管理应用程序状态. 设置默认客户端后,可以通过写入缓存来设置默认状态. + +``` +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; +Vue.use(VueApollo); + +const defaultClient = createDefaultClient({ + resolvers: {} +}); + +defaultClient.cache.writeData({ + data: { + user: { + name: 'John', + surname: 'Doe', + age: 30 + }, + }, +}); + +const apolloProvider = new VueApollo({ + defaultClient, +}); +``` + +我们可以使用`@client` Apollo 指令查询本地数据: + +``` +// user.query.graphql + +query User { + user @client { + name + surname + age + } +} +``` + +除了创建本地数据,我们还可以使用`@client`字段扩展现有的 GraphQL 类型. 当我们需要为尚未添加到 GraphQL API 中的字段模拟 API 响应时,这非常有用. + +#### Mocking API response with local Apollo cache[](#mocking-api-response-with-local-apollo-cache "Permalink") + +当我们需要在本地模拟某些 GraphQL API 响应,查询或变异时(例如,当它们仍未添加到我们的实际 API 中时),使用本地 Apollo 缓存非常方便. + +例如,我们在查询中使用了有关`DesignVersion`的[片段](#fragments) : + +``` +fragment VersionListItem on DesignVersion { + id + sha +} +``` + +我们还需要获取版本作者和'created at'属性,以在版本下拉列表中显示它们,但这些更改仍未在我们的 API 中实现. 我们可以更改现有片段,以针对这些新字段获得模拟的响应: + +``` +fragment VersionListItem on DesignVersion { + id + sha + author @client { + avatarUrl + name + } + createdAt @client +} +``` + +现在,Apollo 将尝试为每个标有`@client`指令的字段查找*解析器* . 让我们为`DesignVersion`类型创建一个解析器(为什么要使用`DesignVersion` ?,因为我们的片段是在这种类型上创建的). + +``` +// resolvers.js + +const resolvers = { + DesignVersion: { + author: () => ({ + avatarUrl: + 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon', + name: 'Administrator', + __typename: 'User', + }), + createdAt: () => '2019-11-13T16:08:11Z', + }, +}; + +export default resolvers; +``` + +我们需要将解析器对象传递给我们现有的 Apollo Client: + +``` +// graphql.js + +import createDefaultClient from '~/lib/graphql'; +import resolvers from './graphql/resolvers'; + +const defaultClient = createDefaultClient( + {}, + resolvers, +); +``` + +现在,每次尝试获取版本时,我们的客户端都会从远程 API 端点获取`id`和`sha` ,并将我们的硬编码值分配给`author`和`createdAt`版本属性. 有了这些数据,前端开发人员就可以在 UI 部件上工作,而不会被后端阻塞. 将实际响应添加到 API 后,可以快速删除自定义本地解析器,并且对查询/片段的唯一更改是`@client`指令删除. + +在[Vue Apollo 文档中](https://vue-apollo.netlify.app/guide/local-state.html#local-state)阅读有关使用 Apollo 进行本地状态管理的更多信息. + +### Using with Vuex[](#using-with-vuex "Permalink") + +When Apollo Client is used within Vuex and fetched data is stored in the Vuex store, there is no need in keeping Apollo Client cache enabled. Otherwise we would have data from the API stored in two places - Vuex store and Apollo Client cache. More to say, with Apollo’s default settings, a subsequent fetch from the GraphQL API could result in fetching data from Apollo cache (in the case where we have the same query and variables). To prevent this behavior, we need to disable Apollo Client cache passing a valid `fetchPolicy` option to its constructor: + +``` +import fetchPolicies from '~/graphql_shared/fetch_policy_constants'; + +export const gqClient = createGqClient( + {}, + { + fetchPolicy: fetchPolicies.NO_CACHE, + }, +); +``` + +### Feature flags in queries[](#feature-flags-in-queries "Permalink") + +有时在 GraphQL 查询中的功能标志后面放置一个实体可能会很有用. 例如,当处理后端已经合并但前端没有合并的功能时,您可能希望将 GraphQL 实体放在功能标记后面,以允许创建和合并较小的合并请求. + +为此, `if`语句通过,我们可以使用`@include`指令排除实体. + +``` +query getAuthorData($authorNameEnabled: Boolean = false) { username name @include(if: $authorNameEnabled) } +``` + +然后,在对查询的 Vue(或 JavaScript)调用中,我们可以传递功能标记. 此功能标志将需要已经正确设置. 有关正确方法,请参阅[功能部件标志文档](../feature_flags/development.html) . + +``` +export default { + apollo: { + user: { + query: QUERY_IMPORT, + variables() { + return { + authorNameEnabled: gon?.features?.authorNameEnabled, + }; + }, + } + }, +}; +``` + +### Manually triggering queries[](#manually-triggering-queries "Permalink") + +创建组件时,将自动对组件的`apollo`属性进行查询. 某些组件反而希望按需发出网络请求,例如,带有延迟加载项的下拉列表. + +有两种方法可以做到这一点: + +1. Use the `skip` property + +``` +export default { + apollo: { + user: { + query: QUERY_IMPORT, + skip() { + // only make the query when dropdown is open + return !this.isOpen; + }, + } + }, +}; +``` + +1. Using `addSmartQuery` + +您可以在您的方法中手动创建智能查询. + +``` +handleClick() { + this.$apollo.addSmartQuery('user', { + // this takes the same values as you'd have in the `apollo` section + query: QUERY_IMPORT, + }), +}; +``` + +### Working with pagination[](#working-with-pagination "Permalink") + +GitLab 的 GraphQL API 对连接类型使用[中继样式的游标分页](https://www.apollographql.com/docs/react/data/pagination/#cursor-based) . 这意味着使用"游标"来跟踪应从中提取下一项的数据集中的位置. [GraphQL Ruby Connection Concepts](https://graphql-ruby.org/pagination/connection_concepts.html)是对连接的良好概述和介绍. + +每个连接类型(例如`DesignConnection`和`DiscussionConnection` )都有一个字段`pageInfo` ,其中包含分页所需的信息: + +``` +pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor +} +``` + +Here: + +* `startCursor`和`endCursor`显示第一项和最后一项的光标. +* `hasPreviousPage`和`hasNextPage`允许我们检查当前页面之前或之后是否还有更多页面可用. + +当我们以连接类型获取数据时,我们可以`before`参数的`after`或`before`传递游标,以指示分页的起点或终点. 应该分别在它们的后跟`first`或`last`参数,以指示我们要在给定端点之后或之前获取*多少个*项目. + +例如,这里我们在光标之后获取 10 个设计: + +``` +query { + project(fullPath: "root/my-project") { + id + issue(iid: "42") { + designCollection { + designs(atVersion: null, after: "Ihwffmde0i", first: 10) { + edges { + node { + id + } + } + } + } + } + } +} +``` + +#### Using `fetchMore` method in components[](#using-fetchmore-method-in-components "Permalink") + +进行初始抓取时,我们通常希望从头开始进行分页. 在这种情况下,我们可以: + +* 跳过传递光标. +* 将`null`明确传递给`after` . + +提取数据后,我们应该保存一个`pageInfo`对象. 假设我们将其存储到 Vue 组件`data` : + +``` +data() { + return { + pageInfo: null, + } +}, +apollo: { + designs: { + query: projectQuery, + variables() { + return { + // rest of design variables + ... + first: 10, + }; + }, + result(res) { + this.pageInfo = res.data?.project?.issue?.designCollection?.designs?.pageInfo; + }, + }, +}, +``` + +当我们想移至下一页时,我们使用 Apollo `fetchMore`方法,在该方法中传递一个新的游标(以及可选的新变量). 在`updateQuery`挂钩中,我们必须在获取下一页之后返回要在 Apollo 缓存中看到的结果. + +``` +fetchNextPage() { + // as a first step, we're checking if we have more pages to move forward + if (this.pageInfo?.hasNextPage) { + this.$apollo.queries.designs.fetchMore({ + variables: { + // rest of design variables + ... + first: 10, + after: this.pageInfo?.endCursor, + }, + updateQuery(previousResult, { fetchMoreResult }) { + // here we can implement the logic of adding new designs to fetched one (for example, if we use infinite scroll) + // or replacing old result with the new one if we use numbered pages + + const newDesigns = fetchMoreResult.project.issue.designCollection.designs; + previousResult.project.issue.designCollection.designs.push(...newDesigns) + + return previousResult; + }, + }); + } +} +``` + +请注意,我们不必再保存`pageInfo`了; `fetchMore`触发查询`result`挂钩. + +### Testing[](#testing "Permalink") + +#### Mocking response as component data[](#mocking-response-as-component-data "Permalink") + +使用[Vue 测试工具](https://vue-test-utils.vuejs.org/) ,可以轻松快速地测试获取 GraphQL 查询的组件. 最简单的方法是使用`shallowMount` ,然后在组件上设置数据 + +``` +it('tests apollo component', () => { + const vm = shallowMount(App); + + vm.setData({ + ...mock data + }); +}); +``` + +#### Testing loading state[](#testing-loading-state "Permalink") + +如果需要测试当 GraphQL API 的结果仍在加载时组件的呈现方式,我们可以将加载状态模拟到相应的 Apollo 查询/突变中: + +``` + function createComponent({ + loading = false, + } = {}) { + const $apollo = { + queries: { + designs: { + loading, + }, + }; + + wrapper = shallowMount(Index, { + sync: false, + mocks: { $apollo } + }); + } + + it('renders loading icon', () => { + createComponent({ loading: true }); + + expect(wrapper.element).toMatchSnapshot(); +}) +``` + +#### Testing Apollo components[](#testing-apollo-components "Permalink") + +如果我们在组件中使用`ApolloQuery`或`ApolloMutation` ,为了测试其功能,我们需要先添加一个存根: + +``` +import { ApolloMutation } from 'vue-apollo'; + +function createComponent(props = {}) { + wrapper = shallowMount(MyComponent, { + sync: false, + propsData: { + ...props, + }, + stubs: { + ApolloMutation, + }, + }); +} +``` + +`ApolloMutation`组件通过作用域插槽公开了`mutate`方法. 如果要测试此方法,则需要将其添加到模拟中: + +``` +const mutate = jest.fn().mockResolvedValue(); +const $apollo = { + mutate, +}; + +function createComponent(props = {}) { + wrapper = shallowMount(MyComponent, { + sync: false, + propsData: { + ...props, + }, + stubs: { + ApolloMutation, + }, + mocks: { + $apollo: + } + }); +} +``` + +然后我们可以检查是否使用正确的变量调用了`mutate` : + +``` +const mutationVariables = { + mutation: createNoteMutation, + update: expect.anything(), + variables: { + input: { + noteableId: 'noteable-id', + body: 'test', + discussionId: '0', + }, + }, +}; + +it('calls mutation on submitting form ', () => { + createComponent() + findReplyForm().vm.$emit('submitForm'); + + expect(mutate).toHaveBeenCalledWith(mutationVariables); +}); +``` + +## Handling errors[](#handling-errors "Permalink") + +目前,GitLab 的 GraphQL 突变具有两种不同的错误模式: [顶级](#top-level-errors)和[数据错误](#errors-as-data) . + +利用 GraphQL 突变时,我们必须考虑处理**这两种错误模式,**以确保用户在发生错误时能够收到适当的反馈. + +### Top-level errors[](#top-level-errors "Permalink") + +这些错误位于 GraphQL 响应的"顶级". 这些是不可恢复的错误,包括参数错误和语法错误,因此不应直接呈现给用户. + +#### Handling top-level errors[](#handling-top-level-errors "Permalink") + +Apollo 意识到顶级错误,因此我们能够利用 Apollo 的各种错误处理机制来处理这些错误(例如,在调用[`mutate`](https://www.apollographql.com/docs/react/api/apollo-client/#ApolloClient.mutate)方法之后处理 Promise 拒绝,或处理从[`ApolloMutation`](https://apollo.vuejs.org/api/apollo-mutation.html#events)组件发出的`error`事件). + +由于这些错误不是针对用户的,因此应在客户端定义顶级错误的错误消息. + +### Errors-as-data[](#errors-as-data "Permalink") + +这些错误嵌套在 GraphQL 响应的`data`对象中. 这些是可恢复的错误,理想情况下,可以直接向用户显示. + +#### Handling errors-as-data[](#handling-errors-as-data "Permalink") + +首先,我们必须向我们的变异对象添加`errors` : + +``` +mutation createNoteMutation($input: String!) { + createNoteMutation(input: $input) { + note { + id ++ errors + } + } +``` + +现在,当我们提交此突变并发生错误时,响应中将包含`errors`供我们处理: + +``` +{ + data: { + mutationName: { + errors: ["Sorry, we were not able to update the note."] + } + } +} +``` + +处理数据错误时,请根据您的最佳判断来确定是将错误消息显示在响应中,还是将另一条客户端定义的消息显示给用户. + +## Usage outside of Vue[](#usage-outside-of-vue "Permalink") + +通过直接导入默认客户端并将其与查询一起使用,还可以在 Vue 之外使用 GraphQL. + +``` +import createDefaultClient from '~/lib/graphql'; +import query from './query.graphql'; + +const defaultClient = createDefaultClient(); + +defaultClient.query({ query }) + .then(result => console.log(result)); +``` + +[使用 Vuex 时](#Using-with-Vuex) ,在以下情况下禁用缓存: + +* 数据正在其他地方缓存 +* 如果数据正在其他地方缓存,或者对于给定的用例完全不需要,则用例不需要缓存. + +``` +import createDefaultClient from '~/lib/graphql'; +import fetchPolicies from '~/graphql_shared/fetch_policy_constants'; + +const defaultClient = createDefaultClient( + {}, + { + fetchPolicy: fetchPolicies.NO_CACHE, + }, +); +``` \ No newline at end of file diff --git a/_book/docs/596.md b/_book/docs/596.md new file mode 100644 index 0000000000000000000000000000000000000000..872580ecc12252fe728ac07a30c1ac1382dbeee5 --- /dev/null +++ b/_book/docs/596.md @@ -0,0 +1,117 @@ +# Icons and SVG Illustrations + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/icons.html](https://docs.gitlab.com/ee/development/fe_guide/icons.html) + +* [Icons](#icons) + * [Usage in HAML/Rails](#usage-in-hamlrails) + * [Usage in Vue](#usage-in-vue) + * [Usage in HTML/JS](#usage-in-htmljs) +* [SVG Illustrations](#svg-illustrations) + * [Usage in HAML/Rails](#usage-in-hamlrails-1) + * [Usage in Vue](#usage-in-vue-1) + +# Icons and SVG Illustrations[](#icons-and-svg-illustrations "Permalink") + +我们在[`gitlab-svgs`](https://gitlab.com/gitlab-org/gitlab-svgs)存储库中管理自己的图标和插图库. 该存储库在[npm](https://s0www0npmjs0com.icopy.site/package/@gitlab/svgs)上发布,并通过 yarn 作为依赖项进行管理. 您可以[在此处](https://gitlab-org.gitlab.io/gitlab-svgs)浏览所有可用的图标和插图. 要升级到新版本,请运行`yarn upgrade @gitlab/svgs` . + +## Icons[](#icons "Permalink") + +我们正在 GitLab 中使用 SVG Sprite 使用 SVG 图标. 这意味着图标仅加载一次,并通过 ID 进行引用. 子画面 SVG 位于`/assets/icons.svg`下. + +我们的目标是一一替换所有内联 SVG 图标(如目前已膨胀的 HTML)以及所有 Font Awesome 图标. + +### Usage in HAML/Rails[](#usage-in-hamlrails "Permalink") + +要在 HAML 或 Rails 中使用精灵图标,我们使用特定的辅助函数: + +``` +sprite_icon(icon_name, size: nil, css_class: '') +``` + +* **icon_name**使用可以在 SVG Sprite 中找到的 icon_name( [此处提供概述](https://gitlab-org.gitlab.io/gitlab-svgs) ). +* **size(可选)**使用以下大小之一: `s16` (将被翻译成`s16`类) +* **css_class(可选)**如果要添加其他 CSS 类 + +**Example** + +``` += sprite_icon('issues', size: 72, css_class: 'icon-danger') +``` + +**上面示例的输出** + +``` +<svg class="s72 icon-danger"> + <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/assets/icons.svg#issues"></use> +</svg> +``` + +### Usage in Vue[](#usage-in-vue "Permalink") + +我们的组件库[GitLab UI](https://gitlab-org.gitlab.io/gitlab-ui/)提供了一个用于显示精灵图标的组件. + +样品用法: + +``` +<script> +import { GlIcon } from "@gitlab/ui"; + +export default { + components: { + GlIcon, + }, +}; +<script> + +<template> + <gl-icon + name="issues" + :size="24" + class="class-name" + /> +</template> +``` + +* **name** SVG Sprite 中图标的名称( [此处提供概述](https://gitlab-org.gitlab.io/gitlab-svgs) ). +* **size(可选)** ,然后将大小的数字值映射到特定的 CSS 类(可用大小: `sXX`映射到`sXX` CSS 类) +* **class(可选)**要添加到 SVG 标签的其他 CSS 类. + +### Usage in HTML/JS[](#usage-in-htmljs "Permalink") + +请在 JS 中使用以下函数来呈现图标: `gl.utils.spriteIcon(iconName)` + +## SVG Illustrations[](#svg-illustrations "Permalink") + +从现在开始,对于任何基于 SVG 的插图,请使用简单的`img`标签来显示插图,只需使用`image_tag`或`image_path`帮助器即可. 请使用周围的`svg-content`类,以确保呈现效果良好. + +### Usage in HAML/Rails[](#usage-in-hamlrails-1 "Permalink") + +**Example** + +``` +.svg-content + = image_tag 'illustrations/merge_requests.svg' +``` + +### Usage in Vue[](#usage-in-vue-1 "Permalink") + +要在模板中使用 SVG 插图,请将路径作为属性提供,并通过标准`img`标签显示它. + +Component: + +``` +<script> +export default { + props: { + svgIllustrationPath: { + type: String, + required: true, + }, + }, +}; +<script> + +<template> + <img :src="svgIllustrationPath" /> +</template> +``` \ No newline at end of file diff --git a/_book/docs/597.md b/_book/docs/597.md new file mode 100644 index 0000000000000000000000000000000000000000..4c175906c92f24118534d1e643cd26ff5cea2a40 --- /dev/null +++ b/_book/docs/597.md @@ -0,0 +1,62 @@ +# InputSetter + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/droplab/plugins/input_setter.html](https://docs.gitlab.com/ee/development/fe_guide/droplab/plugins/input_setter.html) + +* [Usage](#usage) + +# InputSetter[](#inputsetter "Permalink") + +`InputSetter`是一个插件,当单击列表项时,该插件允许在 droplab 范围之外更新 DOM. + +## Usage[](#usage "Permalink") + +将`InputSetter`对象添加到`DropLab.prototype.init`或`DropLab.prototype.addHook`调用的插件数组中. + +* `InputSetter`需要`input`和`valueAttribute`的配置值. +* `input`应该是要操作的 DOM 元素. +* `valueAttribute`应该是一个字符串,它是列表项上属性的名称,用于获取用于更新`input`元素的值. + +您还可以将`InputSetter`配置设置为对象数组,这将允许您更新多个元素. + +``` +<input id="input" value=""> +<div id="div" data-selected-id=""></div> + +<input href="#" id="trigger" data-dropdown-trigger="#list"> +<ul id="list" data-dropdown data-dynamic> + <li><a href="#" data-id="{{id}}">{{text}}</a></li> +<ul> +``` + +``` +const droplab = new DropLab(); + +const trigger = document.getElementById('trigger'); +const list = document.getElementById('list'); + +const input = document.getElementById('input'); +const div = document.getElementById('div'); + +droplab.init(trigger, list, [InputSetter], { + InputSetter: [{ + input: input, + valueAttribute: 'data-id', + } { + input: div, + valueAttribute: 'data-id', + inputAttribute: 'data-selected-id', + }], +}); + +droplab.addData('trigger', [{ + id: 0, + text: 'Jacob', +}, { + id: 1, + text: 'Jeff', +}]); +``` + +上方,如果第二个列表项被单击,它将更新`#input`元素的`value` `1` ,还将更新`#div`元素的`data-selected-id`到`1` . + +(可选)您可以将`inputAttribute`设置为一个字符串,该字符串是您要更新的`input`元素上的属性的名称. 如果你不提供`inputAttribute` , `InputSetter`将更新`value`的的`input` ,如果它是一个元素`INPUT`元素,或者`textContent`的的`input`因素,如果它不是一个`INPUT`元素. \ No newline at end of file diff --git a/_book/docs/598.md b/_book/docs/598.md new file mode 100644 index 0000000000000000000000000000000000000000..f1e2cc8a8ac66464f650d175ecd3b1a983940f37 --- /dev/null +++ b/_book/docs/598.md @@ -0,0 +1,120 @@ +# Performance + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/performance.html](https://docs.gitlab.com/ee/development/fe_guide/performance.html) + +* [Best Practices](#best-practices) + * [Realtime Components](#realtime-components) + * [Lazy Loading Images](#lazy-loading-images) + * [Animations](#animations) +* [Reducing Asset Footprint](#reducing-asset-footprint) + * [Universal code](#universal-code) + * [Page-specific JavaScript](#page-specific-javascript) + * [Important Considerations](#important-considerations) + * [Code Splitting](#code-splitting) + * [Minimizing page size](#minimizing-page-size) +* [Additional Resources](#additional-resources) + +# Performance[](#performance "Permalink") + +## Best Practices[](#best-practices "Permalink") + +### Realtime Components[](#realtime-components "Permalink") + +在为实时功能编写代码时,我们必须牢记以下几点: + +1. 不要使服务器超载请求. +2. 它应该是实时的. + +因此,我们必须在发送请求和实时感之间取得平衡. 创建实时解决方案时,请使用以下规则. + +1. 服务器将通过在标头中发送`Poll-Interval`来告诉您要轮询多少. 使用它作为轮询间隔. 这样[,系统管理员](../../administration/polling.html)就可以[轻松更改轮询速率](../../administration/polling.html) . `Poll-Interval: -1`表示您应禁用轮询,并且必须实施轮询. +2. HTTP 状态不同于 2XX 的响应也应禁用轮询. +3. 使用公共库进行轮询. +4. 仅对活动的选项卡进行轮询. 请使用" [可见性"](https://github.com/ai/visibilityjs) . +5. 使用常规的轮询间隔,不要使用退避轮询或抖动,因为间隔将由服务器控制. +6. 后端代码很可能将使用 etags. 您不会也不应检查状态`304 Not Modified` . 浏览器将为您进行转换. + +### Lazy Loading Images[](#lazy-loading-images "Permalink") + +为了缩短首次渲染的时间,我们对图像使用了延迟加载. 这是通过在`data-src`属性上设置实际图像源来实现的. 渲染 HTML 并加载 JavaScript 后,如果图像在当前视口中,则`data-src`的值将自动移至`src` . + +* 通过将`src`属性重命名为`data-src`并添加类`lazy`来准备 HTML 中的图像以进行延迟加载. +* 如果您使用的是 Rails `image_tag`帮助器,则默认情况下将延迟加载所有图像,除非提供了`lazy: false` . + +如果要异步添加包含惰性图像的内容,则需要调用函数`gl.lazyLoader.searchLazyImages()` ,它将搜索惰性图像并在需要时加载它们. 但通常应通过延迟加载功能中的`MutationObserver`自动处理它. + +### Animations[](#animations "Permalink") + +仅设置动画`opacity`和`transform`属性. 其他属性(例如`top` , `left` , `margin`和`padding` )都导致重新计算 Layout,这要昂贵得多. 有关详细信息,请参见《 [高性能动画](https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/) 》中的"影响布局的样式". + +如果*确实*需要更改布局(例如,将主要内容压入的侧边栏),则最好使用[FLIP](https://aerotwist.com/blog/flip-your-animations/)一次更改昂贵的属性,并使用转换处理实际动画. + +## Reducing Asset Footprint[](#reducing-asset-footprint "Permalink") + +### Universal code[](#universal-code "Permalink") + +`main.js`和`commons/index.js`中包含的代码将加载并在*所有*页面上运行. 除非*在任何地方*确实需要,否则**请勿**在这些文件中**添加**任何内容. 这些捆绑软件包括无处不在的库,例如`vue` , `axios`和`jQuery` ,以及用于主导航和侧边栏的代码. 我们应该尽可能地从这些捆绑软件中删除模块,以减少代码占用量. + +### Page-specific JavaScript[](#page-specific-javascript "Permalink") + +Webpack 已配置为根据`app/assets/javascripts/pages/*`的文件结构自动生成入口点捆绑包. `pages`目录中的目录对应于 Rails 控制器和操作. 这些自动生成的捆绑包将自动包含在相应的页面中. + +例如,如果要访问[https://gitlab.com/gitlab-org/gitlab/-/issues](https://gitlab.com/gitlab-org/gitlab/-/issues) ,则将使用`index`操作访问`app/controllers/projects/issues_controller.rb`控制器. 如果相应的文件位于`pages/projects/issues/index/index.js` ,它将被编译成一个 webpack 包并包含在页面中. + +**注意:**以前我们鼓励在 haml 文件中使用`content_for :page_specific_javascripts`以及手动生成的 webpack 捆绑包. 但是,在此新系统下,您永远不需要手动将入口点添加到`webpack.config.js`文件中.**提示:**如果不确定与给定页面对应的控制器和动作,可以通过在 GitLab 内任何页面上的浏览器开发人员控制台中检查`document.body.dataset.page`来找到. + +#### Important Considerations[](#important-considerations "Permalink") + +* **保持精简入口点:**页面专用的 JavaScript 入口点应尽可能精简. 这些文件免于单元测试,应主要用于实例化和依赖项,这些类和方法驻留在入口点脚本之外的模块中. 只需导入,读取 DOM,实例化,仅此而已. + +* **入口点可能是异步的:** *不要*假设运行入口点脚本时 DOM 已完全加载并且可用. 如果需要在 DOM 加载后运行某些代码,则应使用以下命令将事件处理程序附加到`DOMContentLoaded`事件: + + ``` + import initMyWidget from './my_widget'; + + document.addEventListener('DOMContentLoaded', () => { + initMyWidget(); + }); + ``` + +* **支持模块放置:** + * 如果类或模块*特定于特定路由* ,请尝试将其定位在将要使用的入口点附近. 例如,如果`my_widget.js`仅在`pages/widget/show/index.js`导入,则应将模块放在`pages/widget/show/my_widget.js` ,并使用相对路径`import initMyWidget from './my_widget';` (例如, `import initMyWidget from './my_widget';` ). + * 如果一个类或模块被*多个路由使用* ,请将其放置在最接近的公共父目录的共享目录中,以作为导入它的入口点. 例如,如果将`my_widget.js`导入到`pages/widget/show/index.js`和`pages/widget/run/index.js`两者中,则将模块放置在`pages/widget/shared/my_widget.js` ,并使用相对路径(例如`../shared/my_widget` ). +* **企业版警告:**对于 GitLab 企业版,特定于页面的入口点将覆盖具有相同名称的社区版对应点,因此,如果存在`ee/app/assets/javascripts/pages/foo/bar/index.js` ,它将具有优先权在`app/assets/javascripts/pages/foo/bar/index.js` . 如果要减少重复的代码,可以从另一个导入一个入口点. 不会自动完成此操作,以允许在覆盖功能方面具有灵活性. + +### Code Splitting[](#code-splitting "Permalink") + +对于不需要在页面加载后立即运行的任何代码(例如,模态,下拉列表和其他可以延迟加载的行为),您可以使用动态 import 语句将模块拆分为异步块. 这些导入返回一个 Promise,一旦脚本被加载,它将被解决: + +``` +import(/* webpackChunkName: 'emoji' */ '~/emoji') + .then(/* do something */) + .catch(/* report error */) +``` + +生成这些动态导入时,请尝试使用`webpackChunkName` ,因为它将为块提供确定性的文件名,然后可以将其缓存在 GitLab 版本中的浏览器中. + +更多信息,请参见[webpack 的代码拆分文档](https://webpack.js.org/guides/code-splitting/#dynamic-imports) . + +### Minimizing page size[](#minimizing-page-size "Permalink") + +较小的页面大小意味着页面加载速度更快(在移动连接和连接不良时尤其重要),浏览器可以更快地解析页面,并且数据流量上限的用户使用的数据更少. + +一般提示: + +* 不要添加新字体. +* Prefer font formats with better compression, e.g. WOFF2 is better than WOFF, which is better than TTF. +* 尽可能压缩和缩小资产(对于 CSS / JS,Sprockets 和 webpack 可以为我们完成此工作). +* 如果可以在不添加额外库的情况下合理地实现某些功能,请避免使用它们. +* 如上所述,使用特定于页面的 JavaScript 加载仅在某些页面上需要的库. +* 尽可能使用代码拆分动态导入来延迟加载最初不需要的代码. +* [High Performance Animations](https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/) + +* * * + +## Additional Resources[](#additional-resources "Permalink") + +* [WebPage Test,](https://www.webpagetest.org)用于测试网站的加载时间和大小. +* [Google PageSpeed Insights 对](https://developers.google.com/speed/pagespeed/insights/)网页进行评分,并提供反馈意见以改善网页. +* [Profiling with Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/) +* [Browser Diet](https://browserdiet.com/)是社区构建的指南,其中列出了一些实用技巧,以提高网页性能. \ No newline at end of file diff --git a/_book/docs/599.md b/_book/docs/599.md new file mode 100644 index 0000000000000000000000000000000000000000..49eaf1509ddf649c905ffe1b3b23f4ac7bacea47 --- /dev/null +++ b/_book/docs/599.md @@ -0,0 +1,23 @@ +# Principles + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/principles.html](https://docs.gitlab.com/ee/development/fe_guide/principles.html) + +* [Discuss architecture before implementation](#discuss-architecture-before-implementation) +* [Be consistent](#be-consistent) +* [Improve code iteratively](#improve-code-iteratively) + +# Principles[](#principles "Permalink") + +这些原则将确保您的前端贡献从正确的方向开始. + +## Discuss architecture before implementation[](#discuss-architecture-before-implementation "Permalink") + +在编写代码之前,请先讨论您的体系结构设计问题. 这有助于减少审阅时间,也为编写和思考系统设计提供了良好的实践. + +## Be consistent[](#be-consistent "Permalink") + +有多种编写代码以实现相同结果的方法. 我们应该在代码库中编写代码的方式尽可能保持一致. 这将使我们更轻松地在整个 GitLab 中维护代码. + +## Improve code [iteratively](https://about.gitlab.com/handbook/values/#iteration)[](#improve-code-iteratively "Permalink") + +每当您看到不符合我们当前样式指南的现有代码时,请主动进行更新. 您不需要修复所有问题,但是每个合并请求都应迭代地改进我们的代码库,并在可能的情况下减少技术负担. \ No newline at end of file diff --git a/_book/docs/600.md b/_book/docs/600.md new file mode 100644 index 0000000000000000000000000000000000000000..fb2864fc07200f84d605829b7fa0d02391e59c84 --- /dev/null +++ b/_book/docs/600.md @@ -0,0 +1,25 @@ +# Security + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/security.html](https://docs.gitlab.com/ee/development/fe_guide/security.html) + +* [Resources](#resources) +* [Including external resources](#including-external-resources) +* [Avoiding inline scripts and styles](#avoiding-inline-scripts-and-styles) + +# Security[](#security "Permalink") + +## Resources[](#resources "Permalink") + +[Mozilla 的 HTTP Observatory CLI](https://github.com/mozilla/http-observatory-cli)和[Qualys SSL Labs Server Test](https://www.ssllabs.com/ssltest/analyze.html)是发现潜在问题并确保遵守安全最佳实践的良好资源. + +## Including external resources[](#including-external-resources "Permalink") + +除 Google Analytics(分析)和 Piwik 外,切勿使用外部字体,CSS 和 JavaScript-仅在实例启用它时才可以使用. 资产应始终从 GitLab 实例本地托管和服务. 威盛嵌入式资源`iframes`不应该只是在某些情况下,如与验证码,不能没有使用使用`iframe` . + +## Avoiding inline scripts and styles[](#avoiding-inline-scripts-and-styles "Permalink") + +为了保护用户免受[XSS 漏洞的侵害](https://en.wikipedia.org/wiki/Cross-site_scripting) ,将来我们将使用内容安全策略禁用内联脚本. + +尽管内联脚本可能很有用,但它们也是安全问题. 如果无意中对用户提供的内容进行了未经消毒的处理,则恶意用户可以将脚本注入 Web 应用程序. + +几乎在所有情况下都应避免使用内联样式,只有在找不到替代方法时才应使用内联样式. 这允许样式的可重用性以及可读性. \ No newline at end of file diff --git a/_book/docs/601.md b/_book/docs/601.md new file mode 100644 index 0000000000000000000000000000000000000000..65facede54d4f7a7804f93ef85f80689b97c3a55 --- /dev/null +++ b/_book/docs/601.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/testing.html](https://docs.gitlab.com/ee/development/fe_guide/testing.html) \ No newline at end of file diff --git a/_book/docs/602.md b/_book/docs/602.md new file mode 100644 index 0000000000000000000000000000000000000000..7498f0f00f06bf95a2ee392f564313b973e6e9b7 --- /dev/null +++ b/_book/docs/602.md @@ -0,0 +1,210 @@ +# Tooling + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/tooling.html](https://docs.gitlab.com/ee/development/fe_guide/tooling.html) + +* [ESLint](#eslint) + * [Yarn Script](#yarn-script) + * [Disabling ESLint in new files](#disabling-eslint-in-new-files) + * [Disabling ESLint for a single violation](#disabling-eslint-for-a-single-violation) + * [The `no-undef` rule and declaring globals](#the-no-undef-rule-and-declaring-globals) +* [Formatting with Prettier](#formatting-with-prettier) + * [Editor](#editor) + * [Yarn Script](#yarn-script-1) + * [Scripts during Conversion period](#scripts-during-conversion-period) + * [VSCode Settings](#vscode-settings) + * [Select Prettier as default formatter](#select-prettier-as-default-formatter) + * [Format on Save](#format-on-save) + +# Tooling[](#tooling "Permalink") + +## ESLint[](#eslint "Permalink") + +我们使用 ESLint 封装和执行前端代码标准. 我们的配置可以在[`gitlab-eslint-config`](https://gitlab.com/gitlab-org/gitlab-eslint-config)项目中找到. + +### Yarn Script[](#yarn-script "Permalink") + +本节介绍可用于验证的脚本,并使用 ESLint 将自动修复应用于文件. + +要使用 ESLint 检查所有当前暂存的文件(基于`git diff` ),请运行以下脚本: + +``` +yarn eslint-staged +``` + +*找到的问题列表将记录到控制台.* + +要将自动 ESLint 修复应用于所有当前暂存的文件(基于`git diff` ),请运行以下脚本: + +``` +yarn eslint-staged-fix +``` + +*If manual changes are required, a list of changes will be sent to the console.* + +要使用 ESLint 检查存储库中的**所有**文件,请运行以下脚本: + +``` +yarn eslint +``` + +*找到的问题列表将记录到控制台.* + +要将自动 ESLint 修复应用于存储库中的**所有**文件,请运行以下脚本: + +``` +yarn eslint-fix +``` + +*如果需要手动更改,则会将更改列表发送到控制台.* + +**警告:**限制使用全局规则更新. 否则,更改可能导致巨大的合并请求. + +### Disabling ESLint in new files[](#disabling-eslint-in-new-files "Permalink") + +创建新文件时,请不要禁用 ESLint. 由于遗留兼容性的原因,现有文件可能已禁用现有规则,但是它们正在重构中. + +不要禁用特定的 ESLint 规则. 为避免引入技术债务,只有在调用/实例化现有代码模块时,才可以禁用以下规则. + +* [`no-new`](https://eslint.org/docs/rules/no-new) +* [`class-method-use-this`](https://eslint.org/docs/rules/class-methods-use-this) + +**注意:**逐行禁用这些规则. 这使得将来更容易重构. 例如,使用`eslint-disable-next-line`或`eslint-disable-line` . + +### Disabling ESLint for a single violation[](#disabling-eslint-for-a-single-violation "Permalink") + +如果确实需要为单个违规禁用规则,请以所需的最少代码量禁用它: + +``` +// bad +/* eslint-disable no-new */ + +import Foo from 'foo'; + +new Foo(); + +// better +import Foo from 'foo'; + +// eslint-disable-next-line no-new +new Foo(); +``` + +### The `no-undef` rule and declaring globals[](#the-no-undef-rule-and-declaring-globals "Permalink") + +**切勿**禁用`no-undef`规则. 用`/* global Foo */`代替声明 globals. + +声明多个全局变量时,请始终为每个变量使用一个`/* global [name] */`行. + +``` +// bad +/* globals Flash, Cookies, jQuery */ + +// good +/* global Flash */ +/* global Cookies */ +/* global jQuery */ +``` + +## Formatting with Prettier[](#formatting-with-prettier "Permalink") + +对 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/227280)的`.graphql`支持. + +我们的代码会自动使用[Prettier](https://prettier.io)格式化,以遵循我们的样式指南. 漂亮正在格式化的护理`.js` , `.vue` , `.graphql`和`.scss`基于标准的漂亮规则文件. 您可以在`.prettierrc`找到`.prettierrc`所有设置. + +### Editor[](#editor "Permalink") + +在工作流程中包括更漂亮的最简单方法是相应地设置您的首选编辑器(支持所有主要编辑器). 我们建议将漂亮的文件设置为在保存每个文件时自动运行. [在此处](https://prettier.io/docs/en/editors.html)找到[在](https://prettier.io/docs/en/editors.html)首选编辑器中进行设置的最佳方法. + +请小心,你只能让更漂亮的格式相同的文件类型,全球纱线脚本执行( `.js` , `.vue` , `.graphql`和`.scss` ). 以 VSCode 为例,您可以轻松地在设置文件中排除文件格式: + +``` + "prettier.disableLanguages": [ "json", "markdown" ] +``` + +### Yarn Script[](#yarn-script-1 "Permalink") + +以下纱线脚本可用于进行全局格式化: + +``` +yarn prettier-staged-save +``` + +使用 Prettier 更新所有当前暂存的文件(基于`git diff` )并保存所需的更改. + +``` +yarn prettier-staged +``` + +使用 Prettier 检查所有当前暂存的文件(基于`git diff` ),并记录哪些文件需要手动更新到控制台. + +``` +yarn prettier-all +``` + +使用 Prettier 检查所有文件,并记录哪些文件需要手动更新到控制台. + +``` +yarn prettier-all-save +``` + +使用 Prettier 格式化存储库中的所有文件. (这仅应用于测试全局规则更新,否则您将获得巨大的 MR). + +这些 Yarn 脚本的来源可以在`/scripts/frontend/prettier.js`找到. + +#### Scripts during Conversion period[](#scripts-during-conversion-period "Permalink") + +``` +node ./scripts/frontend/prettier.js check-all ./vendor/ +``` + +这将遍历特定文件夹中的所有文件并进行检查. + +``` +node ./scripts/frontend/prettier.js save-all ./vendor/ +``` + +这将遍历特定文件夹中的所有文件并将其保存. + +### VSCode Settings[](#vscode-settings "Permalink") + +#### Select Prettier as default formatter[](#select-prettier-as-default-formatter "Permalink") + +要将" Prettier"选择为格式器,请在"用户或工作区设置"中添加以下属性: + +``` +{ + "[html]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[vue]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[graphql]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } +} +``` + +#### Format on Save[](#format-on-save "Permalink") + +要使用 Prettier 自动设置文件格式,请在"用户或工作区设置"中添加以下属性: + +``` +{ + "[html]": { + "editor.formatOnSave": true + }, + "[javascript]": { + "editor.formatOnSave": true + }, + "[vue]": { + "editor.formatOnSave": true + }, + "[graphql]": { + "editor.formatOnSave": true + }, +} +``` \ No newline at end of file diff --git a/_book/docs/603.md b/_book/docs/603.md new file mode 100644 index 0000000000000000000000000000000000000000..2383058b5e6e8cf9e0dc3c980f9562c748eb48b2 --- /dev/null +++ b/_book/docs/603.md @@ -0,0 +1,618 @@ +# Vuex + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/vuex.html](https://docs.gitlab.com/ee/development/fe_guide/vuex.html) + +* [Separation of concerns](#separation-of-concerns) +* [File structure](#file-structure) + * [`index.js`](#indexjs) + * [`state.js`](#statejs) + * [Access `state` properties](#access-state-properties) + * [`actions.js`](#actionsjs) + * [Dispatching actions](#dispatching-actions) + * [`mutations.js`](#mutationsjs) + * [Naming Pattern: `REQUEST` and `RECEIVE` namespaces](#naming-pattern-request-and-receive-namespaces) + * [Updating complex state](#updating-complex-state) + * [`getters.js`](#gettersjs) + * [`mutation_types.js`](#mutation_typesjs) + * [Initializing a store’s state](#initializing-a-stores-state) + * [Why not just …spread the initial state?](#why-not-just-spread-the-initial-state) + * [Communicating with the Store](#communicating-with-the-store) + * [Vuex Gotchas](#vuex-gotchas) + * [Testing Vuex](#testing-vuex) + * [Testing Vuex concerns](#testing-vuex-concerns) + * [Testing components that need a store](#testing-components-that-need-a-store) + * [Two way data binding](#two-way-data-binding) + +# Vuex[](#vuex "Permalink") + +如果将状态管理与组件分离有明显的好处(例如,由于状态复杂性),我们建议使用[Vuex 而](https://vuex.vuejs.org)不是其他任何 Flux 模式. 否则,请随时管理组件中的状态. + +在以下情况下,应强烈考虑 Vuex: + +* 您期望应用程序的多个部分对状态变化做出反应 +* 需要在多个组件之间共享数据 +* 与后端的交互非常复杂,例如多个 API 调用 +* 该应用程序涉及通过传统 REST API 和 GraphQL 与后端进行交互(尤其是将 REST API 移至 GraphQL 时,这是一项待处理的后端任务) + +*注意:以下*所有内容在[Vuex](https://vuex.vuejs.org)官方[文档](https://vuex.vuejs.org)中有更详细的[说明](https://vuex.vuejs.org) . + +## Separation of concerns[](#separation-of-concerns "Permalink") + +Vuex 由状态,获取器,变异,动作和模块组成. + +当用户点击一个动作时,我们需要`dispatch`它. 此操作将`commit`将更改状态的突变. *注意:*动作本身不会更新状态,只有突变可以更新状态. + +## File structure[](#file-structure "Permalink") + +在 GitLab 上使用 Vuex 时,请将这些问题分为不同的文件以提高可读性: + +``` +└── store + ├── index.js # where we assemble modules and export the store + ├── actions.js # actions + ├── mutations.js # mutations + ├── getters.js # getters + ├── state.js # state + └── mutation_types.js # mutation types +``` + +下例显示了一个列出用户并将其添加到状态的应用程序. (有关更复杂的示例实现,请查看[此处](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/app/assets/javascripts/vue_shared/security_reports/store)的安全应用程序商店) + +### `index.js`[](#indexjs "Permalink") + +这是我们商店的入口点. 您可以使用以下内容作为指导: + +``` +import Vuex from 'vuex'; +import * as actions from './actions'; +import * as getters from './getters'; +import mutations from './mutations'; +import state from './state'; + +export const createStore = () => + new Vuex.Store({ + actions, + getters, + mutations, + state, + }); +``` + +*注意:*在实施此[RFC](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/20)之前,以上内容将需要禁用`import/prefer-default-export` ESLint 规则. + +### `state.js`[](#statejs "Permalink") + +在编写任何代码之前,您应该做的第一件事就是设计状态. + +通常,我们需要将数据从 haml 提供给 Vue 应用程序. 让我们将其存储在状态中以便更好地访问. + +``` + export default () => ({ + endpoint: null, + + isLoading: false, + error: null, + + isAddingUser: false, + errorAddingUser: false, + + users: [], + }); +``` + +#### Access `state` properties[](#access-state-properties "Permalink") + +您可以使用`mapState`访问组件中的状态属性. + +### `actions.js`[](#actionsjs "Permalink") + +An action is a payload of information to send data from our application to our store. + +动作通常由`type`和`payload` ,它们描述发生了什么. 与[变种](#mutationsjs)不同,动作可以包含异步操作-这就是为什么我们始终需要在动作中处理异步逻辑. + +在此文件中,我们将编写将调用突变的操作以处理用户列表: + +``` + import * as types from './mutation_types'; + import axios from '~/lib/utils/axios_utils'; + import createFlash from '~/flash'; + + export const fetchUsers = ({ state, dispatch }) => { + commit(types.REQUEST_USERS); + + axios.get(state.endpoint) + .then(({ data }) => commit(types.RECEIVE_USERS_SUCCESS, data)) + .catch((error) => { + commit(types.RECEIVE_USERS_ERROR, error) + createFlash('There was an error') + }); + } + + export const addUser = ({ state, dispatch }, user) => { + commit(types.REQUEST_ADD_USER); + + axios.post(state.endpoint, user) + .then(({ data }) => commit(types.RECEIVE_ADD_USER_SUCCESS, data)) + .catch((error) => commit(types.REQUEST_ADD_USER_ERROR, error)); + } +``` + +#### Dispatching actions[](#dispatching-actions "Permalink") + +要从组件调度动作,请使用`mapActions`帮助器: + +``` +import { mapActions } from 'vuex'; + +{ + methods: { + ...mapActions([ + 'addUser', + ]), + onClickUser(user) { + this.addUser(user); + }, + }, +}; +``` + +### `mutations.js`[](#mutationsjs "Permalink") + +变异指定应用程序状态如何响应发送到商店的操作而改变. 更改 Vuex 存储中状态的唯一方法应该是通过提交突变. + +**在编写任何代码之前先考虑状态是一个好主意.** + +请记住,动作仅描述发生了某些事情,而没有描述应用程序状态如何变化. + +**切勿直接从组件提交突变** + +相反,您应该创建一个将导致突变的动作. + +``` + import * as types from './mutation_types'; + + export default { + [types.REQUEST_USERS](state) { + state.isLoading = true; + }, + [types.RECEIVE_USERS_SUCCESS](state, data) { + // Do any needed data transformation to the received payload here + state.users = data; + state.isLoading = false; + }, + [types.RECEIVE_USERS_ERROR](state, error) { + state.isLoading = false; + }, + [types.REQUEST_ADD_USER](state, user) { + state.isAddingUser = true; + }, + [types.RECEIVE_ADD_USER_SUCCESS](state, user) { + state.isAddingUser = false; + state.users.push(user); + }, + [types.REQUEST_ADD_USER_ERROR](state, error) { + state.isAddingUser = false; + state.errorAddingUser = error; + }, + }; +``` + +#### Naming Pattern: `REQUEST` and `RECEIVE` namespaces[](#naming-pattern-request-and-receive-namespaces "Permalink") + +发出请求时,我们通常希望向用户显示加载状态. + +与其创建一个突变来切换加载状态,不如: + +1. 类型为`REQUEST_SOMETHING`的突变,以切换加载状态 +2. 类型为`RECEIVE_SOMETHING_SUCCESS`的突变,用于处理成功回调 +3. 类型为`RECEIVE_SOMETHING_ERROR`的突变,用于处理错误回调 +4. 动作`fetchSomething`发出请求并在提到的情况下提交突变 + 1. 如果您的应用程序执行的不是`GET`请求,则可以使用以下示例: + * `POST` : `createSomething` + * `PUT` : `updateSomething` + * `DELETE` : `deleteSomething` + +结果,我们可以从该组件调度`fetchNamespace`操作,它将负责提交`REQUEST_NAMESPACE` , `RECEIVE_NAMESPACE_SUCCESS`和`RECEIVE_NAMESPACE_ERROR`突变. + +> 以前,我们是从`fetchNamespace`操作中调度操作,而不是提交突变,所以如果您在代码库的较早部分中找到了不同的模式,请不要感到困惑. 但是,无论何时您编写新的 Vuex 商店,我们都鼓励利用新模式 + +通过遵循这种模式,我们保证: + +1. 所有应用程序都遵循相同的模式,从而使任何人都更容易维护代码 +2. 应用程序中的所有数据都遵循相同的生命周期模式 +3. 单元测试更容易 + +#### Updating complex state[](#updating-complex-state "Permalink") + +有时,尤其是当状态复杂时,实际上很难遍历该状态以精确更新突变需要更新的内容. 理想情况下, `vuex`状态应尽可能标准化/解耦,但这并非总是如此. + +重要的是要记住,当在突变本身中选择`portion of the mutated state`并对其进行突变时,代码更易于阅读和维护. + +给定此状态: + +``` + export default () => ({ + items: [ + { + id: 1, + name: 'my_issue', + closed: false, + }, + { + id: 2, + name: 'another_issue', + closed: false, + } + ] +}); +``` + +像这样写一个突变可能很诱人: + +``` +// Bad +export default { + [types.MARK_AS_CLOSED](state, item) { + Object.assign(item, {closed: true}) + } +} +``` + +尽管此方法有效,但它具有以下依赖性: + +* 正确的选择`item`中的组件/动作. +* `item`属性已经在`closed`状态下声明. + * 新的`confidential`财产将不会产生反应. +* 他指出, `item`是通过引用`items` + +这样写的突变更难维护,更容易出错. 我们宁可这样写一个变异: + +``` +// Good +export default { + [types.MARK_AS_CLOSED](state, itemId) { + const item = state.items.find(i => i.id == itemId); + Vue.set(item, 'closed', true) + + state.items.splice(index, 1, item) + } +} +``` + +这种方法更好,因为: + +* 它选择并更新突变中的状态,这种状态更易于维护. +* 它没有外部依赖性,如果传递了正确的`itemId`则状态将正确更新. +* 它没有反应性警告,因为我们生成了一个新`item`以避免耦合到初始状态. + +这样写的变异更容易维护. 另外,我们避免了由于反应系统的限制而导致的错误. + +### `getters.js`[](#gettersjs "Permalink") + +有时我们可能需要根据存储状态获取派生状态,例如针对特定道具进行过滤. 使用 getter 还将由于依赖关系而缓存结果,这取决于[计算的 props 的工作方式.](https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods)这可以通过`getters`来完成: + +``` +// get all the users with pets +export const getUsersWithPets = (state, getters) => { + return state.users.filter(user => user.pet !== undefined); +}; +``` + +要从组件访问吸气剂,请使用`mapGetters`帮助器: + +``` +import { mapGetters } from 'vuex'; + +{ + computed: { + ...mapGetters([ + 'getUsersWithPets', + ]), + }, +}; +``` + +### `mutation_types.js`[](#mutation_typesjs "Permalink") + +来自[vuex 突变文档](https://vuex.vuejs.org/guide/mutations.html) :>在各种 Flux 实现中,将常数用于突变类型是一种常见的模式. 这使代码可以利用像 linters 这样的工具,并将所有常量放在一个文件中,使您的协作者可以快速了解整个应用程序中可能发生的变异. + +``` +export const ADD_USER = 'ADD_USER'; +``` + +### Initializing a store’s state[](#initializing-a-stores-state "Permalink") + +Vuex 存储通常需要一些初始状态才能使用其`action` . 通常,这些数据包括 API 端点,文档 URL 或 ID 之类的数据. + +要设置此初始状态,请在安装 Vue 组件时将其作为参数传递给商店的创建函数: + +``` +// in the Vue app's initialization script (e.g. mount_show.js) + +import Vue from 'vue'; +import Vuex from 'vuex'; +import { createStore } from './stores'; +import AwesomeVueApp from './components/awesome_vue_app.vue' + +Vue.use(Vuex); + +export default () => { + const el = document.getElementById('js-awesome-vue-app'); + + return new Vue({ + el, + store: createStore(el.dataset), + render: h => h(AwesomeVueApp) + }); +}; +``` + +然后,存储功能可以将此数据传递给州的创建功能: + +``` +// in store/index.js + +import * as actions from './actions'; +import mutations from './mutations'; +import createState from './state'; + +export default initialState => ({ + actions, + mutations, + state: createState(initialState), +}); +``` + +状态函数可以接受此初始数据作为参数并将其烘焙到返回的`state`对象中: + +``` +// in store/state.js + +export default ({ + projectId, + documentationPath, + anOptionalProperty = true +}) => ({ + projectId, + documentationPath, + anOptionalProperty, + + // other state properties here +}); +``` + +#### Why not just …spread the initial state?[](#why-not-just-spread-the-initial-state "Permalink") + +精明的读者将从上面的示例中看到切出几行代码的机会: + +``` +// Don't do this! + +export default initialState => ({ + ...initialState, + + // other state properties here +}); +``` + +我们已经做出有意识的决定,避免使用这种模式,以帮助我们的前端代码库实现可发现性和可搜索性. 在[此讨论中](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/56#note_302514865)描述了[这样做的原因](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/56#note_302514865) : + +> 考虑在存储状态中使用了`someStateKey` . 如果仅由`el.dataset`提供,则*可能*无法直接对其进行 grep. 相反,您必须 grep 以获得`some_state_key` ,因为它可能来自 rails 模板. 反之亦然:如果您正在查看 Rails 模板,您可能想知道是什么使用了`some_state_key` ,但是您*必须* grep 为`someStateKey` + +### Communicating with the Store[](#communicating-with-the-store "Permalink") + +``` +<script> +import { mapActions, mapState, mapGetters } from 'vuex'; + +export default { + computed: { + ...mapGetters([ + 'getUsersWithPets' + ]), + ...mapState([ + 'isLoading', + 'users', + 'error', + ]), + }, + methods: { + ...mapActions([ + 'fetchUsers', + 'addUser', + ]), + onClickAddUser(data) { + this.addUser(data); + } + }, + created() { + this.fetchUsers() + } +} +</script> <template> + <ul> + <li v-if="isLoading"> + Loading... + </li> + <li v-else-if="error"> + {{ error }} + </li> + <template v-else> + <li + v-for="user in users" + :key="user.id" + > + {{ user }} + </li> + </template> + </ul> </template> +``` + +### Vuex Gotchas[](#vuex-gotchas "Permalink") + +1. 不要直接调用突变. 始终使用动作进行突变. 这样做将在整个应用程序中保持一致性. 从 Vuex 文档: + + > Why don’t we just call store.commit(‘action’) directly? Well, remember that mutations must be synchronous? Actions aren’t. We can perform asynchronous operations inside an action. + + ``` + // component.vue + + // bad + created() { + this.$store.commit('mutation'); + } + + // good + created() { + this.$store.dispatch('action'); + } + ``` + +2. 使用变异类型而不是对字符串进行硬编码. 这将减少出错的可能性. +3. 在实例化商店的用途之后的所有组件中,都可以访问 State. + +### Testing Vuex[](#testing-vuex "Permalink") + +#### Testing Vuex concerns[](#testing-vuex-concerns "Permalink") + +有关测试操作,获取器和突变的信息,请参考[vuex 文档](https://vuex.vuejs.org/guide/testing.html) . + +#### Testing components that need a store[](#testing-components-that-need-a-store "Permalink") + +较小的组件可能会使用`store`属性来访问数据. 为了编写这些组件的单元测试,我们需要包括商店并提供正确的状态: + +``` +//component_spec.js +import Vue from 'vue'; +import Vuex from 'vuex'; +import { mount, createLocalVue } from '@vue/test-utils'; +import { createStore } from './store'; +import Component from './component.vue' + +const localVue = createLocalVue(); +localVue.use(Vuex); + +describe('component', () => { + let store; + let wrapper; + + const createComponent = () => { + store = createStore(); + + wrapper = mount(Component, { + localVue, + store, + }); + }; + + beforeEach(() => { + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('should show a user', async () => { + const user = { + name: 'Foo', + age: '30', + }; + + // populate the store + await store.dispatch('addUser', user); + + expect(wrapper.text()).toContain(user.name); + }); +}); +``` + +### Two way data binding[](#two-way-data-binding "Permalink") + +在 Vuex 中存储表单数据时,有时需要更新存储的值. 绝对不应直接更改存储,而应使用操作. 为了在我们的代码中仍然使用`v-model` ,我们需要以这种形式创建计算属性: + +``` +export default { + computed: { + someValue: { + get() { + return this.$store.state.someValue; + }, + set(value) { + this.$store.dispatch("setSomeValue", value); + } + } + } +}; +``` + +另一种方法是使用`mapState`和`mapActions` : + +``` +export default { + computed: { + ...mapState(['someValue']), + localSomeValue: { + get() { + return this.someValue; + }, + set(value) { + this.setSomeValue(value) + } + } + }, + methods: { + ...mapActions(['setSomeValue']) + } +}; +``` + +添加其中一些属性变得很麻烦,并使代码重复性更高,并需要编写更多的测试. 为了简化此操作, `~/vuex_shared/bindings.js`有一个帮助器. + +可以像这样使用助手: + +``` +// this store is non-functional and only used to give context to the example +export default { + state: { + baz: '', + bar: '', + foo: '' + }, + actions: { + updateBar() {...} + updateAll() {...} + }, + getters: { + getFoo() {...} + } +} +``` + +``` +import { mapComputed } from '~/vuex_shared/bindings' +export default { + computed: { + /** + * @param {(string[]|Object[])} list - list of string matching state keys or list objects + * @param {string} list[].key - the key matching the key present in the vuex state + * @param {string} list[].getter - the name of the getter, leave it empty to not use a getter + * @param {string} list[].updateFn - the name of the action, leave it empty to use the default action + * @param {string} defaultUpdateFn - the default function to dispatch + * @param {string} root - optional key of the state where to search fo they keys described in list + * @returns {Object} a dictionary with all the computed properties generated + */ + ...mapComputed( + [ + 'baz', + { key: 'bar', updateFn: 'updateBar' } + { key: 'foo', getter: 'getFoo' }, + ], + 'updateAll', + ), + } +} +``` + +然后, `mapComputed`将生成适当的计算属性,这些属性从存储中获取数据并在更新时调度正确的操作. \ No newline at end of file diff --git a/_book/docs/604.md b/_book/docs/604.md new file mode 100644 index 0000000000000000000000000000000000000000..5d71fd0bfbced603ef5bcb36a478113eb6bf1ce4 --- /dev/null +++ b/_book/docs/604.md @@ -0,0 +1,372 @@ +# Vue + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/vue.html](https://docs.gitlab.com/ee/development/fe_guide/vue.html) + +* [Examples](#examples) +* [Vue architecture](#vue-architecture) + * [Components and Store](#components-and-store) + * [An `index.js` file](#an-indexjs-file) + * [Bootstrapping Gotchas](#bootstrapping-gotchas) + * [Providing data from HAML to JavaScript](#providing-data-from-haml-to-javascript) + * [Accessing the `gl` object](#accessing-the-gl-object) + * [Accessing feature flags](#accessing-feature-flags) + * [A folder for Components](#a-folder-for-components) + * [A folder for the Store](#a-folder-for-the-store) + * [Vuex](#vuex) + * [Mixing Vue and jQuery](#mixing-vue-and-jquery) +* [Style guide](#style-guide) +* [Testing Vue Components](#testing-vue-components) + * [Test the component’s output](#test-the-components-output) + * [Events](#events) +* [Vue.js Expert Role](#vuejs-expert-role) +* [Vue 2 -> Vue 3 Migration](#vue-2---vue-3-migration) +* [Appendix - Vue component subject under test](#appendix---vue-component-subject-under-test) + +# Vue[](#vue "Permalink") + +要开始使用 Vue,请通读[其文档](https://vuejs.org/v2/guide/) . + +## Examples[](#examples "Permalink") + +在以下示例中可以找到以下各节中描述的内容: + +* [Web IDE](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/ide/stores) +* [Security products](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/app/assets/javascripts/vue_shared/security_reports) +* [Registry](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/registry/stores) + +## Vue architecture[](#vue-architecture "Permalink") + +用 Vue.js 构建的所有新功能都必须遵循[Flux 架构](https://facebook.github.io/flux/) . 我们试图实现的主要目标是只有一个数据流和一个数据条目. 为了实现此目标,我们使用[vuex](#vuex) . + +您还可以在 Vue 文档中了解有关[状态管理](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch)和[数据流的一种方式的](https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow)此体系结构. + +### Components and Store[](#components-and-store "Permalink") + +在使用 Vue.js 实现的某些功能(例如[问题](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/boards)公告[板](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/boards)或[环境表)中,](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/environments)您可以找到明确的关注点分离: + +``` +new_feature +├── components +│ └── component.vue +│ └── ... +├── store +│ └── new_feature_store.js +├── index.js +``` + +*为了保持一致性,我们建议您采用相同的结构.* + +Let’s look into each of them: + +### An `index.js` file[](#an-indexjs-file "Permalink") + +这是新功能的索引文件. 这是新功能的根 Vue 实例所在的位置. + +应在此文件中导入和初始化商店和服务,并作为主要组件的道具提供. + +请务必阅读[特定](./performance.html#page-specific-javascript)于[页面的 JavaScript](./performance.html#page-specific-javascript) . + +### Bootstrapping Gotchas[](#bootstrapping-gotchas "Permalink") + +#### Providing data from HAML to JavaScript[](#providing-data-from-haml-to-javascript "Permalink") + +挂载 Vue 应用程序时,可能需要从 Rails 向 JavaScript 提供数据. 为此,您可以使用 HTML 元素中的`data`属性,并在安装应用程序时查询它们. + +*Note:* You should only do this while initializing the application, because the mounted element will be replaced with Vue-generated DOM. + +通过`render`函数中的`props`将数据从 DOM 提供给 Vue 实例而不是查询主 Vue 组件内部的 DOM 的好处是避免了在单元测试中创建固定装置或 HTML 元素的需要,因为它将进行测试更轻松. 请参见以下示例: + +``` +// haml +.js-vue-app{ data: { endpoint: 'foo' }} + +// index.js +document.addEventListener('DOMContentLoaded', () => new Vue({ + el: '.js-vue-app', + data() { + const dataset = this.$options.el.dataset; + return { + endpoint: dataset.endpoint, + }; + }, + render(createElement) { + return createElement('my-component', { + props: { + endpoint: this.endpoint, + }, + }); + }, +})); +``` + +#### Accessing the `gl` object[](#accessing-the-gl-object "Permalink") + +当我们需要查询`gl`对象以获取在应用程序生命周期内不会更改的数据时,我们应该在查询 DOM 的同一位置进行处理. 通过遵循这种做法,我们可以避免模拟`gl`对象的需求,这将使测试更加容易. 应该在初始化我们的 Vue 实例时完成,并且数据应作为主要组件的`props`提供: + +``` +document.addEventListener('DOMContentLoaded', () => new Vue({ + el: '.js-vue-app', + render(createElement) { + return createElement('my-component', { + props: { + username: gon.current_username, + }, + }); + }, +})); +``` + +#### Accessing feature flags[](#accessing-feature-flags "Permalink") + +使用 Vue 的[提供/注入](https://vuejs.org/v2/api/#provide-inject)机制使功能标志可用于 Vue 应用程序中的任何后代组件. `glFeatures`对象已经在`commons/vue.js` ,因此仅需要 mixin 即可使用这些标志: + +``` +// An arbitrary descendant component + +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; + +export default { + // ... + mixins: [glFeatureFlagsMixin()], + // ... + created() { + if (this.glFeatures.myFlag) { + // ... + } + }, +} +``` + +这种方法有一些好处: + +* 任意深度嵌套的组件都可以选择加入并访问该标志,而中间组件则不知道(例如,通过 prop 将标志向下传递). +* 良好的可测试性,因为可以从`vue-test-utils`将该标志提供给`mount` / `shallowMount` ,只是作为一个道具. + + ``` + import { shallowMount } from '@vue/test-utils'; + + shallowMount(component, { + provide: { + glFeatures: { myFlag: true }, + }, + }); + ``` + +* 除了在应用程序的[入口点](#accessing-the-gl-object)之外,无需访问全局变量. + +### A folder for Components[](#a-folder-for-components "Permalink") + +此文件夹包含此新功能特定的所有组件. 如果您需要使用或创建可能在其他地方使用的组件,请参考`vue_shared/components` . + +了解何时创建组件的一个很好的经验法则是考虑它是否可以在其他地方重用. + +例如,表在整个 GitLab 中被大量使用,表非常适合组件. 另一方面,仅在一个表中使用的表单元格不能很好地利用此模式. + +您可以在 Vue.js 网站[Component System 中](https://vuejs.org/v2/guide/#Composing-with-Components)阅读有关组件的更多信息. + +### A folder for the Store[](#a-folder-for-the-store "Permalink") + +#### Vuex[](#vuex "Permalink") + +检查此[页面](vuex.html)以获取更多详细信息. + +### Mixing Vue and jQuery[](#mixing-vue-and-jquery "Permalink") + +* 不建议将 Vue 和 jQuery 混合使用. +* 如果您需要在 Vue 中使用特定的 jQuery 插件,请[围绕它创建一个包装器](https://vuejs.org/v2/examples/select2.html) . +* Vue 使用 jQuery 事件侦听器侦听现有的 jQuery 事件是可以接受的. +* 不建议为 Vue 添加新的 jQuery 事件以与 jQuery 交互. + +## Style guide[](#style-guide "Permalink") + +在编写 Vue 组件和模板时,请参考我们的[样式指南](style/vue.html)的 Vue 部分以获取最佳实践. + +## Testing Vue Components[](#testing-vue-components "Permalink") + +每个 Vue 组件都有一个唯一的输出. 此输出始终存在于 render 函数中. + +尽管我们可以分别测试 Vue 组件的每种方法,但我们的目标必须是测试 render / template 函数的输出,该输出始终代表状态. + +这是[此 Vue 组件](#appendix---vue-component-subject-under-test)结构良好的单元测试的示例: + +``` +import { shallowMount } from '@vue/test-utils'; +import { GlLoadingIcon } from '@gitlab/ui'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; +import App from '~/todos/app.vue'; + +const TEST_TODOS = [ + { text: 'Lorem ipsum test text' }, + { text: 'Lorem ipsum 2' }, +]; +const TEST_NEW_TODO = 'New todo title'; +const TEST_TODO_PATH = '/todos'; + +describe('~/todos/app.vue', () => { + let wrapper; + let mock; + + beforeEach(() => { + // IMPORTANT: Use axios-mock-adapter for stubbing axios API requests + mock = new MockAdapter(axios); + mock.onGet(TEST_TODO_PATH).reply(200, TEST_TODOS); + mock.onPost(TEST_TODO_PATH).reply(200); + }); + + afterEach(() => { + // IMPORTANT: Clean up the component instance and axios mock adapter + wrapper.destroy(); + wrapper = null; + + mock.restore(); + }); + + // NOTE: It is very helpful to separate setting up the component from + // its collaborators (i.e. Vuex, axios, etc.) + const createWrapper = (props = {}) => { + wrapper = shallowMount(App, { + propsData: { + path: TEST_TODO_PATH, + ...props, + }, + }); + }; + // NOTE: Helper methods greatly help test maintainability and readability. + const findLoader = () => wrapper.find(GlLoadingIcon); + const findAddButton = () => wrapper.find('[data-testid="add-button"]'); + const findTextInput = () => wrapper.find('[data-testid="text-input"]'); + const findTodoData = () => wrapper.findAll('[data-testid="todo-item"]').wrappers.map(wrapper => ({ text: wrapper.text() })); + + describe('when mounted and loading', () => { + beforeEach(() => { + // Create request which will never resolve + mock.onGet(TEST_TODO_PATH).reply(() => new Promise(() => {})); + createWrapper(); + }); + + it('should render the loading state', () => { + expect(findLoader().exists()).toBe(true); + }); + }); + + describe('when todos are loaded', () => { + beforeEach(() => { + createWrapper(); + // IMPORTANT: This component fetches data asynchronously on mount, so let's wait for the Vue template to update + return wrapper.vm.$nextTick(); + }); + + it('should not show loading', () => { + expect(findLoader().exists()).toBe(false); + }); + + it('should render todos', () => { + expect(findTodoData()).toEqual(TEST_TODOS); + }); + + it('when todo is added, should post new todo', () => { + findTextInput().vm.$emit('update', TEST_NEW_TODO) + findAddButton().vm.$emit('click'); + + return wrapper.vm.$nextTick() + .then(() => { + expect(mock.history.post.map(x => JSON.parse(x.data))).toEqual([{ text: TEST_NEW_TODO }]); + }); + }); + }); +}); +``` + +### Test the component’s output[](#test-the-components-output "Permalink") + +Vue 组件的主要返回值是渲染的输出. 为了测试组件,我们需要测试渲染的输出. [Vue](https://vuejs.org/v2/guide/unit-testing.html)指南的单元测试向我们确切地表明: + +### Events[](#events "Permalink") + +我们应该测试响应组件中的操作而发出的事件,这对于验证是否使用正确的参数触发了正确的事件很有用. + +对于任何 DOM 事件,我们都应使用[`trigger`](https://vue-test-utils.vuejs.org/api/wrapper/#trigger)来触发事件. + +``` +// Assuming SomeButton renders: <button>Some button</button> +wrapper = mount(SomeButton); + +... +it('should fire the click event', () => { + const btn = wrapper.find('button') + + btn.trigger('click'); + ... +}) +``` + +当我们需要触发 Vue 事件时,我们应该使用[`emit`](https://vuejs.org/v2/guide/components-custom-events.html)事件来触发事件. + +``` +wrapper = shallowMount(DropdownItem); + +... + +it('should fire the itemClicked event', () => { + DropdownItem.vm.$emit('itemClicked'); + ... +}) +``` + +我们应该通过对[`emitted()`](https://vue-test-utils.vuejs.org/api/wrapper/#emitted)方法的结果进行断言来验证事件已被触发 + +## Vue.js Expert Role[](#vuejs-expert-role "Permalink") + +仅当您自己的合并请求并且您的评论显示时,您才应该申请成为 Vue.js 专家: + +* 对 Vue 和 Vuex 反应性的深入了解 +* Vue 和 Vuex 代码是根据官方规范和我们的准则构建的 +* 全面了解测试 Vue 和 Vuex 应用程序 +* Vuex 代码遵循[记录的模式](vuex.html#naming-pattern-request-and-receive-namespaces) +* 有关现有 Vue 和 Vuex 应用程序以及现有可重用组件的知识 + +## Vue 2 -> Vue 3 Migration[](#vue-2---vue-3-migration "Permalink") + +> 暂时添加此部分是为了支持将代码库从 Vue 2.x 迁移到 Vue 3.x 的工作. + +当前,我们建议尽量减少向代码库中添加某些功能,以防止增加最终迁移的技​​术负担: + +* filters; +* 活动巴士; +* 功能模板化 +* `slot` attributes + +您可以找到有关[迁移到 Vue 3 的](vue3_migration.html)更多详细信息 + +## Appendix - Vue component subject under test[](#appendix---vue-component-subject-under-test "Permalink") + +这是示例组件的模板,已在" [测试 Vue 组件"](#testing-vue-components)部分中进行了[测试](#testing-vue-components) : + +``` +<template> + <div class="content"> + <gl-loading-icon v-if="isLoading" /> + <template v-else> + <div + v-for="todo in todos" + :key="todo.id" + :class="{ 'gl-strike': todo.isDone }" + data-testid="todo-item" + >{{ toddo.text }}</div> + <footer class="gl-border-t-1 gl-mt-3 gl-pt-3"> + <gl-form-input + type="text" + v-model="todoText" + data-testid="text-input" + > + <gl-button + variant="success" + data-testid="add-button" + @click="addTodo" + >Add</gl-button> + </footer> + </template> + </div> +</template> +``` \ No newline at end of file diff --git a/_book/docs/605.md b/_book/docs/605.md new file mode 100644 index 0000000000000000000000000000000000000000..324bc30ba62337bd22cb76da5986e53caf4d98d7 --- /dev/null +++ b/_book/docs/605.md @@ -0,0 +1,443 @@ +# Geo (development) + +> 原文:[https://docs.gitlab.com/ee/development/geo.html](https://docs.gitlab.com/ee/development/geo.html) + +* [Replication layer](#replication-layer) + * [Geo Log Cursor daemon](#geo-log-cursor-daemon) + * [Database replication](#database-replication) + * [Repository replication](#repository-replication) + * [Project Registry](#project-registry) + * [Repository Sync worker](#repository-sync-worker) + * [Uploads replication](#uploads-replication) + * [Upload Registry](#upload-registry) + * [File Download Dispatch worker](#file-download-dispatch-worker) +* [Authentication](#authentication) +* [Git Push to Geo secondary](#git-push-to-geo-secondary) +* [Using the Tracking Database](#using-the-tracking-database) + * [Configuration](#configuration) + * [Foreign Data Wrapper](#foreign-data-wrapper) + * [Refreshing the Foreign Tables](#refreshing-the-foreign-tables) + * [Accessing data from a Foreign Table](#accessing-data-from-a-foreign-table) +* [Finders](#finders) + * [Finders Performance](#finders-performance) +* [Redis](#redis) +* [Object Storage](#object-storage) +* [Verification](#verification) + * [Repository verification](#repository-verification) +* [Glossary](#glossary) + * [Primary node](#primary-node) + * [Secondary node](#secondary-node) + * [Streaming replication](#streaming-replication) + * [Tracking database](#tracking-database) + * [FDW](#fdw) +* [Geo Event Log](#geo-event-log) + * [Geo Log Cursor](#geo-log-cursor) +* [Code features](#code-features) + * [`Gitlab::Geo` utilities](#gitlabgeo-utilities) + * [Current node](#current-node) + * [Primary or secondary](#primary-or-secondary) + * [Geo Database configured?](#geo-database-configured) + * [Enablement](#enablement) + * [Read-only](#read-only) +* [Steps needed to replicate a new data type](#steps-needed-to-replicate-a-new-data-type) + * [Geo self-service framework (alpha)](#geo-self-service-framework-alpha) +* [History of communication channel](#history-of-communication-channel) + * [Custom code (GitLab 8.6 and earlier)](#custom-code-gitlab-86-and-earlier) + * [System hooks (GitLab 8.7 to 9.5)](#system-hooks-gitlab-87-to-95) + * [Geo Log Cursor (GitLab 10.0 and up)](#geo-log-cursor-gitlab-100-and-up) +* [Self-service framework](#self-service-framework) + +# Geo (development)[](#geo-development-premium-only "Permalink") + +Geo 将 GitLab 实例连接在一起. 一个 GitLab 实例被指定**为主**节点,并且可以与多个**辅助**节点一起运行. Geo 精心策划了很多组件,这些组件可以在下图中看到,并在本文档中进行了更详细的描述. + +[![Geo Architecture Diagram](img/5f13fe556b8940c2e698facdc219d16a.png)](../administration/geo/replication/img/geo_architecture.png) + +## Replication layer[](#replication-layer "Permalink") + +Geo 处理不同组件的复制: + +* [数据库](#database-replication) :包括整个应用程序,缓存和作业除外. +* [Git 存储库](#repository-replication) :包括项目和 Wiki. +* [上载的 Blob](#uploads-replication) :包括从问题附带的图像到 CI 的原始日志和资产的所有内容. + +除数据库复制外,在*辅助*节点上,所有内容均由[Geo Log Cursor](#geo-log-cursor)协调. + +### Geo Log Cursor daemon[](#geo-log-cursor-daemon "Permalink") + +[Geo Log Cursor 守护程序](#geo-log-cursor-daemon)是在每个**辅助**节点上运行的单独进程. 它监视[地理事件日志中](#geo-event-log)是否有新事件,并为每种特定事件类型创建后台作业. + +例如,当更新存储库时,Geo **主**节点会创建一个带有关联的存储库更新事件的 Geo 事件. Geo Log Cursor 守护程序接收事件并安排一个`Geo::ProjectSyncWorker`作业,该作业将使用`Geo::RepositorySyncService`和`Geo::WikiSyncService`类分别更新存储库和 Wiki. + +Geo Log Cursor 守护程序可以自动在高可用性模式下运行. 守护程序将不时尝试获取锁,一旦获得锁定,它将充当*活动*守护程序. + +在同一节点上的所有其他正在运行的守护程序都将处于待机模式,如果*活动*守护程序释放其锁定,则可以恢复工作. + +We use the [`ExclusiveLease`](https://www.rubydoc.info/github/gitlabhq/gitlabhq/Gitlab/ExclusiveLease) lock type with a small TTL, that is renewed at every pooling cycle. That allows us to implement this global lock with a timeout. + +在池化周期结束时,如果守护程序无法更新和/或重新获得锁定,它将切换到待机模式. + +### Database replication[](#database-replication "Permalink") + +Geo 使用[流复制](#streaming-replication)将数据库从**主**节点[复制](#streaming-replication)到**辅助**节点. 通过此复制, **辅助**节点可以访问数据库中保存的所有数据. 因此,用户可以登录**次级**和读取所有的问题,合并请求等**辅助**节点上. + +### Repository replication[](#repository-replication "Permalink") + +Geo 还复制存储库. 每个**辅助**节点都[跟踪跟踪数据库](#tracking-database)中每个存储库的状态. + +存在以下几种方式来复制存储库: + +* [Repository Sync worker](#repository-sync-worker). +* [Geo Log Cursor](#geo-log-cursor). + +#### Project Registry[](#project-registry "Permalink") + +`Geo::ProjectRegistry`类定义用于跟踪存储库复制状态的模型. 对于主数据库中的每个项目,在跟踪数据库中保留一个记录. + +它记录有关存储库的以下内容: + +* 他们上次同步的时间. +* 上一次成功同步它们. +* 是否需要重新同步. +* 重试的时间. +* 重试次数. +* 是否以及何时进行验证. + +它还将项目 Wiki 的这些属性存储在专用列中. + +#### Repository Sync worker[](#repository-sync-worker "Permalink") + +The `Geo::RepositorySyncWorker` class runs periodically in the background and it searches the `Geo::ProjectRegistry` model for projects that need updating. Those projects can be: + +* 未同步:从未在**辅助**节点上同步过的项目,因此尚不存在. +* 最近更新:项目的`last_repository_updated_at`时间戳比`Geo::ProjectRegistry`模型中的`last_repository_successful_sync_at`时间戳更新. +* 手动:管理员可以在[地理管理面板中](../user/admin_area/geo_nodes.html)手动标记存储库以重新同步. + +当我们在次要`RETRIES_BEFORE_REDOWNLOAD`时间内无法获取存储库时,Geo 会进行所谓的*重新下载* . 它将干净地克隆到存储根目录中的`@geo-temporary`目录中. 成功后,我们用新克隆的仓库替换主仓库. + +### Uploads replication[](#uploads-replication "Permalink") + +文件上传也被复制到**辅助**节点. 为了跟踪同步状态,使用了`Geo::UploadRegistry`模型. + +#### Upload Registry[](#upload-registry "Permalink") + +与[项目注册表](#project-registry)类似,有一个`Geo::UploadRegistry`模型可以跟踪同步的上传. + +CI Job Artifacts and LFS objects are synced in a similar way as uploads, but they are tracked by `Geo::JobArtifactRegistry`, and `Geo::LfsObjectRegistry` models respectively. + +#### File Download Dispatch worker[](#file-download-dispatch-worker "Permalink") + +还类似于[Repository Sync 工作器](#repository-sync-worker) ,有一个`Geo::FileDownloadDispatchWorker`类,该类定期运行以同步所有尚未同步到 Geo **辅助**节点的上载. + +通过 HTTP 复制文件,并通过`/api/v4/geo/transfers/:type/:id`端点(例如`/api/v4/geo/transfers/lfs/123` . + +## Authentication[](#authentication "Permalink") + +为了验证文件传输,每个`GeoNode`记录都有两个字段: + +* 公共访问密钥( `access_key`字段). +* 秘密访问密钥( `secret_access_key`字段). + +**次要**节点通过[JWT 请求进行](https://jwt.io/)身份验证. 当**辅助**节点希望下载文件时,它将发送带有`Authorization`标头的 HTTP 请求: + +``` +Authorization: GL-Geo <access_key>:<JWT payload> +``` + +**主**节点使用`access_key`字段查找相应的**辅助**节点并解密 JWT 有效负载,该负载包含用于标识文件请求的其他信息. 这样可以确保**辅助**节点为正确的数据库 ID 下载正确的文件. 例如,对于 LFS 对象,请求还必须包含文件的 SHA256 和. JWT 有效负载示例如下所示: + +``` +{ "data": { sha256: "31806bb23580caab78040f8c45d329f5016b0115" }, iat: "1234567890" } +``` + +如果请求的文件与请求的 SHA256 总和匹配,则 Geo **主**节点将通过[X-Sendfile](https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/)功能发送数据,这使 NGINX 可以处理文件传输而不会占用 Rails 或 Workhorse. + +**注意:** JWT 需要在所涉及的机器之间同步时钟,否则它可能会因加密错误而失败. + +## Git Push to Geo secondary[](#git-push-to-geo-secondary "Permalink") + +Git Push Proxy 作为`gitlab-shell`组件内置的功能存在. 它仅在**辅助**节点上处于活动状态. 它允许从辅助节点克隆存储库的用户推送到相同的 URL. + +定向到**次**节点的 Git `push`请求将发送到**主**节点,而`pull`请求将继续由**次**节点服务,以实现最大效率. + +HTTPS 和 SSH 请求的处理方式不同: + +* 使用 HTTPS,我们将为用户提供指向**主**节点上项目的`HTTP 302 Redirect` . Git 客户端足够聪明,可以理解该状态码并处理重定向. +* 使用 SSH,因为没有等效的方法来执行重定向,所以我们必须代理请求. 这是在[`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell)内部[`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell) ,方法是先将请求转换为 HTTP 协议,然后将其代理到**主**节点. + +[`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell)守护程序根据`/api/v4/allowed`的响应知道何时进行代理. 返回一个特殊的`HTTP 300`状态代码,我们执行在响应正文中指定的"自定义操作". 该响应包含允许代理`push`操作在**主**节点上发生的其他数据. + +## Using the Tracking Database[](#using-the-tracking-database "Permalink") + +除了要复制的主数据库外,Geo **辅助**节点还具有自己的单独的[跟踪数据库](#tracking-database) . + +跟踪数据库包含**辅助**节点的状态. + +任何需要在升级过程中运行的数据库迁移都需要应用于每个**辅助**节点上的跟踪数据库. + +### Configuration[](#configuration "Permalink") + +数据库配置在[`config/database_geo.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/config/database_geo.yml.postgresql)设置. [`ee/db/geo`](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/db/geo)目录包含此数据库的架构和迁移. + +要为数据库编写迁移,请使用`GeoMigrationGenerator` : + +``` +rails g geo_migration [args] [options] +``` + +要迁移跟踪数据库,请运行: + +``` +bundle exec rake geo:db:migrate +``` + +### Foreign Data Wrapper[](#foreign-data-wrapper "Permalink") + +在 GitLab 10.1 中引入. + +[地理日志游标](#geo-log-cursor)使用了外部数据包装器( [FDW](#fdw) ),并提高了许多同步操作的性能. + +FDW 是 PostgreSQL 扩展( [`postgres_fdw`](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html) ),已在 Geo Tracking 数据库中(在**辅助**节点上)启用,它允许它连接到只读数据库副本并执行查询和过滤来自两个实例的数据. + +该持久连接被配置为名为`gitlab_secondary`的 FDW 服务器. 此配置仅存在于数据库的用户上下文中. 要访问`gitlab_secondary` ,GitLab 需要使用先前配置的同一数据库用户. + +地理跟踪数据库以常规用户身份通过​​FDW 访问只读数据库副本,受其自身限制的限制. 凭据被配置为与先前映射的`SERVER` ( `gitlab_secondary` )相关联的`USER MAPPING` . + +FDW 配置和凭据定义由 Omnibus GitLab `gitlab-ctl reconfigure`命令自动管理. + +#### Refreshing the Foreign Tables[](#refreshing-the-foreign-tables "Permalink") + +每当在**主**节点上配置了新的地理节点或数据库架构更改时,都必须通过运行以下命令来刷新**辅助**节点上的外部表: + +``` +bundle exec rake geo:db:refresh_foreign_tables +``` + +否则,将阻止**辅助**节点正常运行. **辅助**节点将生成错误消息,如以下 PostgreSQL 错误所示: + +``` +ERROR: relation "gitlab_secondary.ci_job_artifacts" does not exist at character 323 +STATEMENT: SELECT a.attname, format_type(a.atttypid, a.atttypmod), + pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod + FROM pg_attribute a LEFT JOIN pg_attrdef d + ON a.attrelid = d.adrelid AND a.attnum = d.adnum + WHERE a.attrelid = '"gitlab_secondary"."ci_job_artifacts"'::regclass + AND a.attnum > 0 AND NOT a.attisdropped + ORDER BY a.attnum +``` + +#### Accessing data from a Foreign Table[](#accessing-data-from-a-foreign-table "Permalink") + +在 SQL 级别,您要做的就是从`gitlab_secondary.*` `SELECT`数据. + +这是一个如何从地理跟踪数据库的 FDW 访问所有项目的示例: + +``` +SELECT * FROM gitlab_secondary.projects; +``` + +作为一个更真实的示例,这是在"跟踪数据库"中过滤未归档项目的方式: + +``` +SELECT project_registry.* + FROM project_registry + JOIN gitlab_secondary.projects + ON (project_registry.project_id = gitlab_secondary.projects.id + AND gitlab_secondary.projects.archived IS FALSE) +``` + +在 ActiveRecord 级别,我们还有其他表示外部表的模型. 必须以稍微不同的方式映射它们,并且它们是只读的. + +检查`ee/app/models/geo/fdw`现有的 FDW 模型以供参考. + +从开发人员的角度来看,这与创建代表数据库视图的模型没有什么不同. + +通过上面的示例,您可以通过以下方式访问项目: + +``` +Geo::Fdw::Project.all +``` + +并通过未归档的项目访问`ProjectRegistry`过滤: + +``` +# We have to use Arel here: +project_registry_table = Geo::ProjectRegistry.arel_table +fdw_project_table = Geo::Fdw::Project.arel_table + +project_registry_table.join(fdw_project_table) + .on(project_registry_table[:project_id].eq(fdw_project_table[:id])) + .where((fdw_project_table[:archived]).eq(true)) # if you append `.to_sql` you can check generated query +``` + +## Finders[](#finders "Permalink") + +Geo 使用[Finders](https://gitlab.com/gitlab-org/gitlab/tree/master/app/finders) ,这是一些类,可以帮助您轻松查找项目/附件/等. 在跟踪数据库和主数据库中. + +### Finders Performance[](#finders-performance "Permalink") + +查找者需要将主数据库中的数据与跟踪数据库中的数据进行比较. 例如,计算已同步项目的数量通常涉及从一个数据库中检索项目 ID,并检查它们在另一个数据库中的状态. 这很慢并且需要大量内存. + +为了克服这个问题,查找器使用[FDW](#fdw)或外部数据包装器. 这允许在主数据库和跟踪数据库之间进行常规的`JOIN` . + +## Redis[](#redis "Permalink") + +Redis 的**辅助**节点上的工作方式相同的**主**节点上. 它用于缓存,存储会话和其他持久性数据. + +不使用**主**节点和**辅助**节点之间的 Redis 数据复制,因此会话等不在节点之间共享. + +## Object Storage[](#object-storage "Permalink") + +GitLab 可以选择使用对象存储来存储否则将存储在磁盘上的数据. 这些事情可以是: + +* LFS Objects +* CI 工作工件 +* Uploads + +Geo 不处理存储在对象存储中的对象. Geo 会忽略对象存储中的项目. 要么: + +* 对象存储层应注意其自身的地理复制. +* 所有辅助节点应使用相同的存储节点. + +## Verification[](#verification "Permalink") + +### Repository verification[](#repository-verification "Permalink") + +存储库将通过校验和进行验证. + +**主**节点在存储库上计算校验和. 它基本上将所有 Git 引用散列在一起,并将该散列存储在数据库的`project_repository_states`表中. + +**次**节点执行相同操作以计算其克隆的哈希,然后将哈希与**主**节点计算出的值进行比较. 如果存在不匹配,Geo 会将其标记为不匹配,管理员可以在[Geo 管理面板中](../user/admin_area/geo_nodes.html)看到此不匹配. + +## Glossary[](#glossary "Permalink") + +### Primary node[](#primary-node "Permalink") + +**主**节点是地理设置中具有读写功能的单个节点. 这是事实的唯一来源,Geo **次要**节点从那里复制数据. + +在地理位置设置中,只能有一个**主**节点. 所有**辅助**节点都连接到该**主**节点. + +### Secondary node[](#secondary-node "Permalink") + +**辅助**节点是在不同地理位置运行的**主要**节点的只读副本. + +### Streaming replication[](#streaming-replication "Permalink") + +Geo 取决于 PostgreSQL 的流复制功能. 它完全复制数据库数据和数据库模式. 数据库副本是只读副本. + +流复制取决于预写日志或 WAL. 这些日志将复制到副本并在此处重放. + +由于流复制还可以复制架构,因此数据库迁移不需要在辅助节点上运行. + +### Tracking database[](#tracking-database "Permalink") + +每个 Geo **辅助**节点上的数据库,该数据库保留其所在节点的状态. 在[使用跟踪数据库中](#using-the-tracking-database)阅读更多[信息](#using-the-tracking-database) . + +### FDW[](#fdw "Permalink") + +外部数据包装程序(FDW)是 PostgreSQL 内置的功能. 它允许从不同的数据源查询数据. 在 Geo 中,它用于查询来自不同 PostgreSQL 实例的数据. + +## Geo Event Log[](#geo-event-log "Permalink") + +Geo **主数据库**将事件存储在`geo_event_log`表中. 日志中的每个条目都包含特定类型的事件. 这些类型的事件包括: + +* 存储库已删除事件 +* 存储库重命名事件 +* 存储库更改事件 +* 存储库创建事件 +* 哈希存储迁移事件 +* Lfs 对象已删除事件 +* 哈希存储附件事件 +* Job Artifact Deleted 事件 +* 上载已删除的活动 + +### Geo Log Cursor[](#geo-log-cursor "Permalink") + +在寻找新的`Geo::EventLog`行的**辅助**节点上运行的进程. + +## Code features[](#code-features "Permalink") + +### `Gitlab::Geo` utilities[](#gitlabgeo-utilities "Permalink") + +与 Geo 相关的小型实用工具方法进入[`ee/lib/gitlab/geo.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/gitlab/geo.rb)文件. + +其中许多方法都使用`RequestStore`类进行缓存,以减少在整个代码库中使用这些方法对性能的影响. + +#### Current node[](#current-node "Permalink") + +类方法`.current_node`返回当前节点的`GeoNode`记录. + +我们使用`gitlab.yml`的`host` , `port`和`relative_url_root`值,并在数据库中搜索以标识我们所在的节点(请参见`GeoNode.current_node` ). + +#### Primary or secondary[](#primary-or-secondary "Permalink") + +要确定当前节点是**主**节点还是**辅助**节点,请使用`.primary?` 和`.secondary?` 类方法. + +当未启用节点时,这些方法都可能在节点上都返回`false` . 请参阅[启用](#enablement) . + +#### Geo Database configured?[](#geo-database-configured "Permalink") + +处理初始化期间发生的事情时,还有一个附加的陷阱. 在一些地方,我们使用`Gitlab::Geo.geo_database_configured?` 检查节点是否具有跟踪数据库的方法,该数据库仅存在于**辅助**节点上. 这克服了在引导新节点期间可能发生的竞争条件. + +#### Enablement[](#enablement "Permalink") + +当用户拥有包括功能的有效许可证,并且在"地理节点"屏幕上定义了至少一个节点时,我们认为地理功能已启用. + +See `Gitlab::Geo.enabled?` and `Gitlab::Geo.license_allows?` methods. + +#### Read-only[](#read-only "Permalink") + +所有地理**辅助**节点均为只读. + +[只读数据库](verifying_database_capabilities.html#read-only-database)的一般原则适用于所有 Geo **辅助**节点. 那么`Gitlab::Database.read_only?` 方法将始终在**辅助**节点上返回`true` . + +当由于节点是**辅助**节点而不允许某些写操作时,请考虑添加`Gitlab::Database.read_only?` 还是`Gitlab::Database.read_write?` 后卫,而不是`Gitlab::Geo.secondary?` . + +在复制的设置中,数据库本身已经是只读的,因此我们无需为此采取任何额外的步骤. + +## Steps needed to replicate a new data type[](#steps-needed-to-replicate-a-new-data-type "Permalink") + +随着 GitLab 的发展,我们不断需要向 Geo 复制系统添加新资源. 具体实现取决于资源的具体情况,但是需要注意以下几点: + +* 主站点上的事件生成. 每当更改/更新新资源时,我们都需要为 Log Cursor 创建一个任务. +* 事件处理. 日志游标需要为主站点生成的每种事件类型都有一个处理程序. +* 派遣工人(临时工). 确保回填条件良好. +* 同步工作者. +* 注册所有可能的状态. +* Verification. +* 清洁器. 更改辅助站点的同步设置后,需要清理一些资源. +* 地理节点状态. 我们需要在 GitLab 管理区域中提供 API 端点以及一些演示. +* 健康检查. 如果我们可以执行一些预检查并在出现问题时使节点不正常,则应该这样做. `rake gitlab:geo:check`命令也必须更新. + +### Geo self-service framework (alpha)[](#geo-self-service-framework-alpha "Permalink") + +我们开始开发新的[Geo 自助服务框架(alpha)](geo/framework.html) ,这使添加新数据类型变得容易得多. + +## History of communication channel[](#history-of-communication-channel "Permalink") + +自从第一次迭代以来,沟通渠道已经发生了变化,您可以在此处查看历史性决策以及我们为何迁移到新实现的原因. + +### Custom code (GitLab 8.6 and earlier)[](#custom-code-gitlab-86-and-earlier "Permalink") + +在 8.6 之前的 GitLab 版本中,自定义代码用于处理 HTTP 请求从**主**节点到**辅助**节点的通知. + +### System hooks (GitLab 8.7 to 9.5)[](#system-hooks-gitlab-87-to-95 "Permalink") + +后来,决定放弃自定义代码,开始使用系统挂钩. 使用它们的人越来越多,因此许多人将从对该通信层进行的改进中受益. + +我们的 API 代码(Grape)中有一个特定的**内部**端点,该端点接收来自此系统挂钩的所有请求: `/api/v4/geo/receive_events` . + +我们通过`event_name`字段切换和过滤每个事件. + +### Geo Log Cursor (GitLab 10.0 and up)[](#geo-log-cursor-gitlab-100-and-up "Permalink") + +从 GitLab 10.0 开始,不再使用[系统 Webhooks](#system-hooks-gitlab-87-to-95) , [而是](#system-hooks-gitlab-87-to-95)使用 Geo Log Cursor. 日志光标遍历`Geo::EventLog`行以查看自上次检查日志以来是否有更改,并将处理存储库更新,删除,更改和重命名. + +该表位于复制的数据库中. 与旧方法相比,它具有两个优点: + +* 复制是同步的,我们保留事件的顺序. +* 事件的复制与数据库中的更改同时发生. + +## Self-service framework[](#self-service-framework "Permalink") + +如果您想为正在处理的资源添加简单的地理复制,请查看我们的[自助服务框架](geo/framework.html) . \ No newline at end of file diff --git a/_book/docs/606.md b/_book/docs/606.md new file mode 100644 index 0000000000000000000000000000000000000000..d5d26fe00d62df05b5b16f0f789a12c2070d8dc7 --- /dev/null +++ b/_book/docs/606.md @@ -0,0 +1,512 @@ +# Geo self-service framework (alpha) + +> 原文:[https://docs.gitlab.com/ee/development/geo/framework.html](https://docs.gitlab.com/ee/development/geo/framework.html) + +* [Nomenclature](#nomenclature) +* [Geo Domain-Specific Language](#geo-domain-specific-language) + * [The replicator](#the-replicator) + * [Linking to a model](#linking-to-a-model) + * [API](#api) + * [Library](#library) +* [Existing Replicator Strategies](#existing-replicator-strategies) + * [Blob Replicator Strategy](#blob-replicator-strategy) + * [Replication](#replication) + * [Verification](#verification) + * [Metrics](#metrics) + * [GraphQL API](#graphql-api) + * [Admin UI](#admin-ui) + +# Geo self-service framework (alpha)[](#geo-self-service-framework-alpha "Permalink") + +**注意:**本文档可能会随时更改. 这是我们正在研究的建议,一旦实施完成,此文档将得到更新. 跟随[史诗般的](https://gitlab.com/groups/gitlab-org/-/epics/2161)进度.**注意:** Geo 自助服务框架当前处于 Alpha 状态. 如果您需要复制新的数据类型,请与 Geo 小组联系以讨论选项. 您可以在 Slack 的`#g_geo`与他们联系,或在问题或合并请求中提及`@geo-team` . + +Geo 提供了一个 API,使跨 Geo 节点轻松复制数据类型成为可能. 该 API 以 Ruby 域特定语言(DSL)的形式呈现,旨在使创建数据类型的工程师只需花费很少的精力即可复制数据. + +## Nomenclature[](#nomenclature "Permalink") + +在深入研究 API 之前,开发人员需要了解一些特定于地理位置的命名约定. + +Model + +模型是活动模型,在整个 Rails 代码库中都是如此. 它通常与数据库表绑定. 从地理角度来看,模型可以具有一个或多个资源. + +Resource + +资源是属于模型的一条数据,由 GitLab 功能生成. 使用存储机制将其持久化. 默认情况下,资源不可复制. + +Data type + +Data type is how a resource is stored. Each resource should fit in one of the data types Geo supports: :- Git repository :- Blob :- Database + +有关更多详细信息,请参见[数据类型](../../administration/geo/replication/datatypes.html) . + +Geo Replicable + +可复制资源是 Geo 希望在 Geo 节点之间同步的资源. 受支持的可复制数据类型有限. 实现属于已知数据类型之一的资源的复制所需的工作量很小. + +Geo Replicator + +地理复制器是知道如何复制可复制对象的对象. 它负责::-触发事件(生产者):-消费事件(消费者) + +它与 Geo Replicable 数据类型相关. 所有复制器都有一个公共接口,可用于处理(即产生和使用)事件. 它负责主节点(产生事件的地方)和次节点(消耗事件的地方)之间的通信. 想要将 Geo 纳入其功能的工程师将使用复制器的 API 来实现这一目标. + +Geo Domain-Specific Language + +语法糖使工程师可以轻松指定应复制哪些资源以及如何复制. + +## Geo Domain-Specific Language[](#geo-domain-specific-language "Permalink") + +### The replicator[](#the-replicator "Permalink") + +首先,您需要编写一个复制器. 复制器位于[`ee/app/replicators/geo`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/app/replicators/geo) . 对于每个需要复制的资源,即使多个资源绑定到同一模型,也应指定一个单独的复制器. + +例如,以下复制器复制软件包文件: + +``` +module Geo + class PackageFileReplicator < Gitlab::Geo::Replicator + # Include one of the strategies your resource needs + include ::Geo::BlobReplicatorStrategy + + # Specify the CarrierWave uploader needed by the used strategy + def carrierwave_uploader + model_record.file + end + + # Specify the model this replicator belongs to + def self.model + ::Packages::PackageFile + end + end +end +``` + +类名应该是唯一的. 它还与注册表的表名紧密相关,因此在此示例中,注册表表将为`package_file_registry` . + +对于不同的数据类型,Geo 支持包括不同的策略. 选择一个适合您的需求. + +### Linking to a model[](#linking-to-a-model "Permalink") + +要将此复制器绑定到模型,需要在模型代码中添加以下内容: + +``` +class Packages::PackageFile < ApplicationRecord + include ::Gitlab::Geo::ReplicableModel + + with_replicator Geo::PackageFileReplicator +end +``` + +### API[](#api "Permalink") + +设置好后,可以通过模型轻松访问复制器: + +``` +package_file = Packages::PackageFile.find(4) # just a random id as example +replicator = package_file.replicator +``` + +或者从复制器取回模型: + +``` +replicator.model_record +=> <Packages::PackageFile id:4> +``` + +复制器可用于生成事件,例如在 ActiveRecord 挂钩中: + +``` + after_create_commit -> { replicator.publish_created_event } +``` + +#### Library[](#library "Permalink") + +所有这些背后的框架位于[`ee/lib/gitlab/geo/`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/lib/gitlab/geo) . + +## Existing Replicator Strategies[](#existing-replicator-strategies "Permalink") + +在编写一种新的复制器策略之前,请检查以下内容,以查看现有策略之一是否已经可以处理您的资源. 如果不确定,请咨询地理团队. + +### Blob Replicator Strategy[](#blob-replicator-strategy "Permalink") + +使用`Geo::BlobReplicatorStrategy`模块,Geo 可以轻松支持使用[CarrierWave 的](https://github.com/carrierwaveuploader/carrierwave) `Uploader::Base`模型. + +首先,每个文件应具有其自己的主要 ID 和模型. Geo 强烈建议将*每个文件都*视为头等公民,因为根据我们的经验,这大大简化了跟踪复制和验证状态. + +例如,要添加对具有`Widget` `widgets`表的`Widget`模型引用的文件的支持,您将执行以下步骤: + +#### Replication[](#replication "Permalink") + +1. 在`Widget`类中包含`Gitlab::Geo::ReplicableModel` ,并使用`with_replicator Geo::WidgetReplicator`指定 Replicator 类. + + 此时, `Widget`类应如下所示: + + ``` + # frozen_string_literal: true + + class Widget < ApplicationRecord + include ::Gitlab::Geo::ReplicableModel + + with_replicator Geo::WidgetReplicator + + mount_uploader :file, WidgetUploader + + def self.replicables_for_geo_node + # Should be implemented. The idea of the method is to restrict + # the set of synced items depending on synchronization settings + end + ... + end + ``` + +2. 创建`ee/app/replicators/geo/widget_replicator.rb` . 实现`#carrierwave_uploader`方法,该方法应返回`CarrierWave::Uploader` . 并实现类方法`.model`以返回`Widget`类. + + ``` + # frozen_string_literal: true + + module Geo + class WidgetReplicator < Gitlab::Geo::Replicator + include ::Geo::BlobReplicatorStrategy + + def self.model + ::Widget + end + + def carrierwave_uploader + model_record.file + end + end + end + ``` + +3. 创建`ee/spec/replicators/geo/widget_replicator_spec.rb`并执行必要的设置,以定义共享示例的`model_record`变量. + + ``` + # frozen_string_literal: true + + require 'spec_helper' + + RSpec.describe Geo::WidgetReplicator do + let(:model_record) { build(:widget) } + + it_behaves_like 'a blob replicator' + end + ``` + +4. 创建`widget_registry`表,以便 Geo 次要对象可以跟踪每个 Widget 文件的同步和验证状态: + + ``` + # frozen_string_literal: true + + class CreateWidgetRegistry < ActiveRecord::Migration[6.0] + DOWNTIME = false + + disable_ddl_transaction! + + def up + unless table_exists?(:widget_registry) + ActiveRecord::Base.transaction do + create_table :widget_registry, id: :bigserial, force: :cascade do |t| + t.integer :widget_id, null: false + t.integer :state, default: 0, null: false, limit: 2 + t.integer :retry_count, default: 0, limit: 2 + t.text :last_sync_failure + t.datetime_with_timezone :retry_at + t.datetime_with_timezone :last_synced_at + t.datetime_with_timezone :created_at, null: false + + t.index :widget_id + t.index :retry_at + t.index :state + end + end + end + + add_text_limit :widget_registry, :last_sync_failure, 255 + end + + def down + drop_table :widget_registry + end + end + ``` + +5. Create `ee/app/models/geo/widget_registry.rb`: + + ``` + # frozen_string_literal: true + + class Geo::WidgetRegistry < Geo::BaseRegistry + include Geo::ReplicableRegistry + + MODEL_CLASS = ::Widget + MODEL_FOREIGN_KEY = :widget_id + + belongs_to :widget, class_name: 'Widget' + end + ``` + + 方法`has_create_events?` 在大多数情况下应该返回`true` . 但是,如果您添加的实体没有创建事件,则根本不要添加该方法. + +6. Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`. + +7. Create `ee/spec/factories/geo/widget_registry.rb`: + + ``` + # frozen_string_literal: true + + FactoryBot.define do + factory :geo_widget_registry, class: 'Geo::WidgetRegistry' do + widget + state { Geo::WidgetRegistry.state_value(:pending) } + + trait :synced do + state { Geo::WidgetRegistry.state_value(:synced) } + last_synced_at { 5.days.ago } + end + + trait :failed do + state { Geo::WidgetRegistry.state_value(:failed) } + last_synced_at { 1.day.ago } + retry_count { 2 } + last_sync_failure { 'Random error' } + end + + trait :started do + state { Geo::WidgetRegistry.state_value(:started) } + last_synced_at { 1.day.ago } + retry_count { 0 } + end + end + end + ``` + +8. Create `ee/spec/models/geo/widget_registry_spec.rb`: + + ``` + # frozen_string_literal: true + + require 'spec_helper' + + RSpec.describe Geo::WidgetRegistry, :geo, type: :model do + let_it_be(:registry) { create(:geo_widget_registry) } + + specify 'factory is valid' do + expect(registry).to be_valid + end + + include_examples 'a Geo framework registry' + + describe '.find_registry_differences' do + ... # To be implemented + end + end + ``` + +小部件现在应该由 Geo 复制! + +#### Verification[](#verification "Permalink") + +1. 将验证状态字段添加到`widgets`表中,以便 Geo 主数据库可以跟踪验证状态: + + ``` + # frozen_string_literal: true + + class AddVerificationStateToWidgets < ActiveRecord::Migration[6.0] + DOWNTIME = false + + def change + add_column :widgets, :verification_retry_at, :datetime_with_timezone + add_column :widgets, :verified_at, :datetime_with_timezone + add_column :widgets, :verification_checksum, :binary, using: 'verification_checksum::bytea' + add_column :widgets, :verification_failure, :string + add_column :widgets, :verification_retry_count, :integer + end + end + ``` + +2. 在`verification_failure`和`verification_checksum`上添加部分索引,以确保可以高效执行重新验证: + + ``` + # frozen_string_literal: true + + class AddVerificationFailureIndexToWidgets < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :widgets, :verification_failure, where: "(verification_failure IS NOT NULL)", name: "widgets_verification_failure_partial" + add_concurrent_index :widgets, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: "widgets_verification_checksum_partial" + end + + def down + remove_concurrent_index :widgets, :verification_failure + remove_concurrent_index :widgets, :verification_checksum + end + end + ``` + +要做的事情:在二级服务器上添加验证. 这应作为以下内容的一部分完成[:Geo:自助服务框架-包文件验证的首次实现](https://gitlab.com/groups/gitlab-org/-/epics/1817) + +小部件现在应由 Geo 验证! + +#### Metrics[](#metrics "Permalink") + +指标由`Geo::MetricsUpdateWorker`收集,保存在`GeoNodeStatus`以显示在 UI 中,然后发送给 Prometheus. + +1. 将字段`widget_count` , `widget_checksummed_count` , `widget_checksum_failed_count` , `widget_synced_count` , `widget_failed_count`和`widget_registry_count`到`ee/app/models/geo_node_status.rb` `GeoNodeStatus#RESOURCE_STATUS_FIELDS`数组中. +2. 将相同的字段添加到`ee/app/models/geo_node_status.rb` `GeoNodeStatus#PROMETHEUS_METRICS`哈希中. +3. 将相同字段添加到`doc/administration/monitoring/prometheus/gitlab_metrics.md` `Sidekiq metrics`表中. +4. 将相同的字段添加到`doc/api/geo_nodes.md` `GET /geo_nodes/status`示例响应中. +5. 将相同的字段添加到`ee/spec/models/geo_node_status_spec.rb`和`ee/spec/factories/geo_node_statuses.rb` . +6. Set `widget_count` in `GeoNodeStatus#load_data_from_current_node`: + + ``` + self.widget_count = Geo::WidgetReplicator.primary_total_count + ``` + +7. 添加`GeoNodeStatus#load_widgets_data`来设置`widget_synced_count` , `widget_failed_count`和`widget_registry_count` : + + ``` + def load_widget_data + self.widget_synced_count = Geo::WidgetReplicator.synced_count + self.widget_failed_count = Geo::WidgetReplicator.failed_count + self.widget_registry_count = Geo::WidgetReplicator.registry_count + end + ``` + +8. Call `GeoNodeStatus#load_widgets_data` in `GeoNodeStatus#load_secondary_data`. + +9. Set `widget_checksummed_count` and `widget_checksum_failed_count` in `GeoNodeStatus#load_verification_data`: + + ``` + self.widget_checksummed_count = Geo::WidgetReplicator.checksummed_count self.widget_checksum_failed_count = Geo::WidgetReplicator.checksum_failed_count + ``` + +小部件复制和验证指标现在应该可以在 API,管理区域 UI 和 Prometheus 中使用! + +#### GraphQL API[](#graphql-api "Permalink") + +1. 在`ee/app/graphql/types/geo/geo_node_type.rb`向`GeoNodeType`添加一个新字段: + + ``` + field :widget_registries, ::Types::Geo::WidgetRegistryType.connection_type, + null: true, + resolver: ::Resolvers::Geo::WidgetRegistriesResolver, + description: 'Find widget registries on this Geo node', + feature_flag: :geo_self_service_framework + ``` + +2. 新添加`widget_registries`字段名的`expected_fields`在阵列`ee/spec/graphql/types/geo/geo_node_type_spec.rb` . + +3. Create `ee/app/graphql/resolvers/geo/widget_registries_resolver.rb`: + + ``` + # frozen_string_literal: true + + module Resolvers + module Geo + class WidgetRegistriesResolver < BaseResolver + include RegistriesResolver + end + end + end + ``` + +4. Create `ee/spec/graphql/resolvers/geo/widget_registries_resolver_spec.rb`: + + ``` + # frozen_string_literal: true + + require 'spec_helper' + + RSpec.describe Resolvers::Geo::WidgetRegistriesResolver do + it_behaves_like 'a Geo registries resolver', :geo_widget_registry + end + ``` + +5. Create `ee/app/finders/geo/widget_registry_finder.rb`: + + ``` + # frozen_string_literal: true + + module Geo + class WidgetRegistryFinder + include FrameworkRegistryFinder + end + end + ``` + +6. Create `ee/spec/finders/geo/widget_registry_finder_spec.rb`: + + ``` + # frozen_string_literal: true + + require 'spec_helper' + + RSpec.describe Geo::WidgetRegistryFinder do + it_behaves_like 'a framework registry finder', :geo_widget_registry + end + ``` + +7. Create `ee/app/graphql/types/geo/widget_registry_type.rb`: + + ``` + # frozen_string_literal: true + + module Types + module Geo + # rubocop:disable Graphql/AuthorizeTypes because it is included + class WidgetRegistryType < BaseObject + include ::Types::Geo::RegistryType + + graphql_name 'WidgetRegistry' + description 'Represents the sync and verification state of a widget' + + field :widget_id, GraphQL::ID_TYPE, null: false, description: 'ID of the Widget' + end + end + end + ``` + +8. Create `ee/spec/graphql/types/geo/widget_registry_type_spec.rb`: + + ``` + # frozen_string_literal: true + + require 'spec_helper' + + RSpec.describe GitlabSchema.types['WidgetRegistry'] do + it_behaves_like 'a Geo registry type' + + it 'has the expected fields (other than those included in RegistryType)' do + expected_fields = %i[widget_id] + + expect(described_class).to have_graphql_fields(*expected_fields).at_least + end + end + ``` + +9. Add integration tests for providing Widget registry data to the frontend via the GraphQL API, by duplicating and modifying the following shared examples in `ee/spec/requests/api/graphql/geo/registries_spec.rb`: + + ``` + it_behaves_like 'gets registries for', { + field_name: 'widgetRegistries', + registry_class_name: 'WidgetRegistry', + registry_factory: :geo_widget_registry, + registry_foreign_key_field_name: 'widgetId' + } + ``` + +现在应该可以通过 GraphQL API 获得各个小部件同步和验证数据! + +1. 注意复制"更新"事件. Geo Framework 目前不支持复制"更新"事件,因为此时添加到框架的所有实体都是不可变的. 如果您要添加的实体属于这种情况,请遵循[https://gitlab.com/gitlab-org/gitlab/-/issues/118743](https://gitlab.com/gitlab-org/gitlab/-/issues/118743)和[https://gitlab.com/gitlab-org/gitlab /// issues / 118745](https://gitlab.com/gitlab-org/gitlab/-/issues/118745)作为添加新事件类型的示例. 添加通知后,请同时删除它. + +#### Admin UI[](#admin-ui "Permalink") + +要做的事情:这应该作为《 [地理手册》的](https://gitlab.com/groups/gitlab-org/-/epics/2525)一部分完成[:实现自助服务框架可复制的前端](https://gitlab.com/groups/gitlab-org/-/epics/2525) + +窗口小部件同步和验证数据(总计和个人)现在应该在管理界面中可用! \ No newline at end of file diff --git a/_book/docs/607.md b/_book/docs/607.md new file mode 100644 index 0000000000000000000000000000000000000000..3c3a4441909167e62f561a2156875dda8af65245 --- /dev/null +++ b/_book/docs/607.md @@ -0,0 +1,311 @@ +# Gitaly developers guide + +> 原文:[https://docs.gitlab.com/ee/development/gitaly.html](https://docs.gitlab.com/ee/development/gitaly.html) + +* [Deep Dive](#deep-dive) +* [Beginner’s guide](#beginners-guide) +* [Developing new Git features](#developing-new-git-features) + * [`gitaly-ruby`](#gitaly-ruby) +* [Gitaly-Related Test Failures](#gitaly-related-test-failures) +* [Legacy Rugged code](#legacy-rugged-code) +* [`TooManyInvocationsError` errors](#toomanyinvocationserror-errors) +* [Request counts](#request-counts) +* [Running tests with a locally modified version of Gitaly](#running-tests-with-a-locally-modified-version-of-gitaly) + * [Use a locally modified version of Gitaly RPC client](#use-a-locally-modified-version-of-gitaly-rpc-client) +* [Wrapping RPCs in Feature Flags](#wrapping-rpcs-in-feature-flags) + * [Gitaly](#gitaly) + * [GitLab Rails](#gitlab-rails) + * [Testing with GDK](#testing-with-gdk) + +# Gitaly developers guide[](#gitaly-developers-guide "Permalink") + +[Gitaly](https://gitlab.com/gitlab-org/gitaly)是 GitLab Rails,Workhorse 和 GitLab Shell 使用的高级 Git RPC 服务. + +## Deep Dive[](#deep-dive "Permalink") + +在 2019 年 5 月,Bob Van Landuyt 主持了有关 GitLab 的[Gitaly 项目](https://gitlab.com/gitlab-org/gitaly)以及如何以 Ruby 的形式进行的 Deep Dive(仅限 GitLab 团队成员: `https://gitlab.com/gitlab-org/create-stage/issues/1` : [//gitlab.com/gitlab-org/create-stage/issues/1](https://gitlab.com/gitlab-org/gitaly) )开发人员,以便与将来可能在代码库这一部分工作的任何人共享他的特定领域知识. + +您可以[在 YouTube 上](https://www.youtube.com/watch?v=BmlEWFS8ORo)找到[录音](https://www.youtube.com/watch?v=BmlEWFS8ORo) ,在[Google 幻灯片](https://docs.google.com/presentation/d/1VgRbiYih9ODhcPnL8dS0W98EwFYpJ7GXMPpX-1TM6YE/edit)和[PDF 中](https://gitlab.com/gitlab-org/create-stage/uploads/a4fdb1026278bda5c1c5bb574379cf80/Create_Deep_Dive__Gitaly_for_Create_Ruby_Devs.pdf)找到[幻灯片](https://docs.google.com/presentation/d/1VgRbiYih9ODhcPnL8dS0W98EwFYpJ7GXMPpX-1TM6YE/edit) . + +截至 GitLab 11.11 为止,本次深入介绍中涉及的所有内容都是准确的,尽管自那时以来特定细节可能有所更改,但它仍应作为一个很好的介绍. + +## Beginner’s guide[](#beginners-guide "Permalink") + +首先阅读 Gitaly 存储库的[Gitaly 贡献初学者指南](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/beginners_guide.md) . 它描述了如何设置 Gitaly,Gitaly 的各个组件以及它们的作用以及如何运行其测试套件. + +## Developing new Git features[](#developing-new-git-features "Permalink") + +要读取或写入 Git 数据,必须向 Gitaly 发出请求. 这意味着如果您要开发一项新功能,则需要`lib/gitlab/git`尚不可用的数据,则必须对 Gitaly 进行更改. + +> 这是一个尚未明确定义的新过程. 如果您想提供 Git 功能,但遇到困难,请与 Gitaly 团队或`@jacobvosmaer-gitlab` . + +"新功能"是指`lib/gitlab/git`中从`lib/gitlab/git`外部调用的任何方法或类. 有关从`lib/gitlab/git`内部调用的新方法,请参见下面的"修改现有 Git 功能". + +在`lib/gitlab/git`之外的任何地方,都不应有任何通过磁盘访问(例如 Rugged, `git` , `rm -rf` )接触 Git 存储库的新代码. + +添加新的 Gitaly 功能的过程是: + +* 探索/原型制作 +* 在[`gitaly-proto`](https://gitlab.com/gitlab-org/gitaly-proto)设计和创建新的 Gitaly RPC +* 发行新版本的`gitaly-proto` +* 用 Go 或 Ruby [在 Gitaly 中](https://gitlab.com/gitlab-org/gitaly)编写 RPC 的实现和测试 +* release a new version of Gitaly +* 在调用新 Gitaly RPC 的 GitLab CE / EE,GitLab Workhorse 或 GitLab Shell 中编写客户端代码 + +这些步骤经常重叠. 在测试和开发过程中,可以使用未发行的 Gitaly 和`gitaly-proto`版本. + +* 有关使用未发布的协议编写服务器端代码的说明,请参见[Gitaly 存储库](https://gitlab.com/gitlab-org/gitaly/blob/master/CONTRIBUTING.md#development-and-testing-with-a-custom-gitaly-proto) . +* 有关使用修改后的 Gitaly 版本运行 GitLab CE 测试的说明,请参见[下文](#running-tests-with-a-locally-modified-version-of-gitaly) . +* 在 GDK 中运行`gdk install`并重新启动`gdk run` (或`gdk run app` )以使用本地修改的 Gitaly 版本进行开发 + +### `gitaly-ruby`[](#gitaly-ruby "Permalink") + +可以在[`gitaly-ruby`](https://gitlab.com/gitlab-org/gitaly/tree/master/ruby)使用 Ruby 代码在[`gitaly-ruby`](https://gitlab.com/gitlab-org/gitaly/tree/master/ruby)实现和测试 RPC. 这应该使对不喜欢编写 Go 代码的开发人员的贡献更加容易. + +[Gitaly 存储库](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/ruby_endpoint.md)中提供[了](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/ruby_endpoint.md)有关此方法[的文档](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/ruby_endpoint.md) . + +## Gitaly-Related Test Failures[](#gitaly-related-test-failures "Permalink") + +如果您的测试套件因 Gitaly 问题而失败,请首先尝试运行: + +``` +rm -rf tmp/tests/gitaly +``` + +在 RSpec 测试期间,Gitaly 实例会将日志写入`gitlab/log/gitaly-test.log` . + +## Legacy Rugged code[](#legacy-rugged-code "Permalink") + +尽管 Gitaly 可以处理所有 Git 访问,但许多 GitLab 客户仍在 NFS 上运行 Gitaly. 由于 N + 1 个 Gitaly 调用和其他原因,用于 Git 调用的传统 Rugged 实现可能比 Gitaly RPC 更快. 有关更多详细信息,请参见[问题](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/57317) . + +在 GitLab 消除了大多数这些低效率问题或对 Git 数据停止使用 NFS 之前,可以通过功能标志启用某些最常用 RPC 的 Rugged 实现: + +* `rugged_find_commit` +* `rugged_get_tree_entries` +* `rugged_tree_entry` +* `rugged_commit_is_ancestor` +* `rugged_commit_tree_entry` +* `rugged_list_commits_by_oid` + +方便的 Rake 任务可用于一起启用或禁用这些标志. 启用: + +``` +bundle exec rake gitlab:features:enable_rugged +``` + +禁用: + +``` +bundle exec rake gitlab:features:disable_rugged +``` + +此代码大部分存在于`lib/gitlab/git/rugged_impl`目录中. + +**注意:**除非与[Gitaly Team](https://gitlab.com/groups/gl-gitaly/group_members)明确讨论,否则您无需添加或修改与 Rugged 相关的代码. 此代码不适用于 GitLab.com 或其他不使用 NFS 的 GitLab 实例. + +## `TooManyInvocationsError` errors[](#toomanyinvocationserror-errors "Permalink") + +在开发和测试过程中,您可能会遇到`Gitlab::GitalyClient::TooManyInvocationsError`故障. 该`GitalyClient`将试图通过时 Gitaly 被称为 30 倍以上在单个的 Rails 请求或 Sidekiq 执行提高此错误来阻止对潜在的 n + 1 点的问题. + +作为临时措施,导出`GITALY_DISABLE_REQUEST_LIMITS=1`以消除该错误. 这将在开发环境中禁用 n + 1 检测. + +请在 GitLab CE 或 EE 存储库中提出问题,以报告该问题. 包括标签〜Gitaly〜性能〜"技术债务". 请确保问题包含完整的堆栈跟踪和`TooManyInvocationsError`错误消息. 如果可能,还包括任何已知的失败测试. + +找出 n + 1 问题的根源. 通常,这将是一个循环,导致对数组中的每个元素调用 Gitaly. 如果您无法找出问题所在,请与[Gitaly 小组](https://gitlab.com/groups/gl-gitaly/group_members)成员联系以寻求帮助. + +找到源之后,将其包装在`allow_n_plus_1_calls`块中,如下所示: + +``` +# n+1: link to n+1 issue +Gitlab::GitalyClient.allow_n_plus_1_calls do + # original code + commits.each { |commit| ... } +end +``` + +一旦将代码包装在此块中,将从 n + 1 检测中排除此代码路径. + +## Request counts[](#request-counts "Permalink") + +提交和其他 Git 数据现在通过 Gitaly 获取. 可以像数据库一样批处理这些提取. 这样可以提高客户端以及 Gitaly 本身以及用户的性能. 为了保持性能稳定并防止性能下降,可以对 Gitaly 通话进行计数,并可以对通话计数进行测试. 这需要设置`:request_store`标志. + +``` +describe 'Gitaly Request count tests' do + context 'when the request store is activated', :request_store do + it 'correctly counts the gitaly requests made' do + expect { subject }.to change { Gitlab::GitalyClient.get_request_count }.by(10) + end + end +end +``` + +## Running tests with a locally modified version of Gitaly[](#running-tests-with-a-locally-modified-version-of-gitaly "Permalink") + +通常,GitLab CE / EE 测试在`tmp/tests/gitaly`使用 Gitaly 的本地克隆,固定在`GITALY_SERVER_VERSION`指定的版本上. `GITALY_SERVER_VERSION`文件还支持分支和 SHA,以在[https://gitlab.com/gitlab-org/gitaly 中](https://gitlab.com/gitlab-org/gitaly)使用自定义提交. + +**注:**通过引入自动部署 Gitaly 的,格式`GITALY_SERVER_VERSION`用总括的语法一致. 它不再支持`=revision` ,它将评估文件内容作为 Git 引用(分支或 SHA),仅当它与 semver 匹配时才在`v` . + +如果要针对修改后的 Gitaly 版本在本地运行测试,则可以用符号链接替换`tmp/tests/gitaly` . 这要快得多,因为这样可以避免每次运行`rspec`时都重新安装 Gitaly. + +``` +rm -rf tmp/tests/gitaly +ln -s /path/to/gitaly tmp/tests/gitaly +``` + +在运行测试之前,请确保在本地 Gitaly 目录中运行`make` . 否则,Gitaly 将无法启动. + +如果您在两次测试之间更改了本地 Gitaly,则需要再次手动运行`make` . + +请注意,CI 测试不会使用您本地修改的 Gitaly 版本. 要在 CI 中使用自定义 Gitaly 版本,您需要按照本段开头所述更新 GITALY_SERVER_VERSION. + +要使用其他 Gitaly 存储库(例如,如果您的更改出现在 fork 上),则可以在运行测试时指定`GITALY_REPO_URL`环境变量: + +``` +GITALY_REPO_URL=https://gitlab.com/nick.thomas/gitaly bundle exec rspec spec/lib/gitlab/git/repository_spec.rb +``` + +如果您的 Gitaly 分支是私有的,则可以生成一个[Deploy Token](../user/project/deploy_tokens/index.html)并在 URL 中指定它: + +``` +GITALY_REPO_URL=https://gitlab+deploy-token-1000:token-here@gitlab.com/nick.thomas/gitaly bundle exec rspec spec/lib/gitlab/git/repository_spec.rb +``` + +要在 CI 中使用自定义的 Gitaly 存储库,例如,如果您希望 GitLab 分支始终使用自己的 Gitaly 分支,请将`GITALY_REPO_URL`设置为[CI 环境变量](../ci/variables/README.html#gitlab-cicd-environment-variables) . + +### Use a locally modified version of Gitaly RPC client[](#use-a-locally-modified-version-of-gitaly-rpc-client "Permalink") + +如果要对 RPC 客户端进行更改,例如添加新端点或向现有端点添加新参数,请遵循[Gitaly proto](https://gitlab.com/gitlab-org/gitaly/blob/master/proto/README.md)指南. 在推送具有更改的分支(例如`new-feature-branch` )之后: + +1. 将 Rails 的`Gemfile`的`gitaly`行更改为: + + ``` + gem 'gitaly', git: 'https://gitlab.com/gitlab-org/gitaly.git', branch: 'new-feature-branch' + ``` + +2. 运行`bundle install`以使用修改后的 RPC 客户端. + +* * * + +[Return to Development documentation](README.html) + +## Wrapping RPCs in Feature Flags[](#wrapping-rpcs-in-feature-flags "Permalink") + +以下是在功能标记后在 Gitaly 中选通新功能的步骤. + +### Gitaly[](#gitaly "Permalink") + +1. 创建一个包范围的标志名: + + ``` + var findAllTagsFeatureFlag = "go-find-all-tags" + ``` + +2. 使用`featureflag`包在代码中创建一个开关: + + ``` + if featureflag.IsEnabled(ctx, findAllTagsFeatureFlag) { + // go implementation + } else { + // ruby implementation + } + ``` + +3. 创建 Prometheus 指标: + + ``` + var findAllTagsRequests = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "gitaly_find_all_tags_requests_total", + Help: "Counter of go vs ruby implementation of FindAllTags", + }, + []string{"implementation"}, + ) + + func init() { + prometheus.Register(findAllTagsRequests) + } + + if featureflag.IsEnabled(ctx, findAllTagsFeatureFlag) { + findAllTagsRequests.WithLabelValues("go").Inc() + // go implementation + } else { + findAllTagsRequests.WithLabelValues("ruby").Inc() + // ruby implementation + } + ``` + +4. Set headers in tests: + + ``` + import ( + "google.golang.org/grpc/metadata" + + "gitlab.com/gitlab-org/gitaly/internal/featureflag" + ) + + //... + + md := metadata.New(map[string]string{featureflag.HeaderKey(findAllTagsFeatureFlag): "true"}) + ctx = metadata.NewOutgoingContext(context.Background(), md) + + c, err = client.FindAllTags(ctx, rpcRequest) + require.NoError(t, err) + ``` + +### GitLab Rails[](#gitlab-rails "Permalink") + +1. 通过设置功能标记在 Rails 控制台中进行测试: + + **注意:请**注意标志的名称以及在 Rails 控制台中使用的标志的名称. 它们之间是有区别的(用下划线代替短划线,并且更改了名称前缀). 确保在所有标志`gitaly_`加上`gitaly_` . + + ``` + Feature.enable('gitaly_go_find_all_tags') + ``` + +### Testing with GDK[](#testing-with-gdk "Permalink") + +为确保正确设置该标志并将其放入 Gitaly 中,可以使用 GDK 检查集成: + +1. 标志的状态必须是可观察的. 要检查它,您需要通过获取 Prometheus 指标来启用它: + 1. 导航到 GDK 的根目录. + 2. 确保您已经为 Gitaly 签出了正确的分支. + 3. 使用`make gitaly-setup`重新编译它,并使用`gdk restart gitaly`重新启动服务. + 4. 确保您的设置正在运行: `gdk status | grep praefect` `gdk status | grep praefect` . + 5. 检查使用了什么配置文件: `cat ./services/praefect/run | grep praefect` `-config`标志的`cat ./services/praefect/run | grep praefect`值 + 6. 在配置文件中取消注释`prometheus_listen_addr`并运行`gdk restart gitaly` . +2. Make sure that the flag is not enabled yet: + 1. 执行触发更改所需的任何操作(项目创建,提交提交,观察历史记录等). + 2. 检查当前指标列表是否具有新的功能标记计数器: + + ``` + curl --silent http://localhost:9236/metrics | grep go_find_all_tags + ``` + +3. 一旦观察到新功能标志的度量标准并递增,就可以启用新功能: + 1. 导航到 GDK 的根目录. + 2. 启动一个 Rails 控制台: + + ``` + bundle install && bundle exec rails console + ``` + + 3. 检查功能标志列表: + + ``` + Feature :: Gitaly . server_feature_flags + ``` + + 应该禁用`"gitaly-feature-go-find-all-tags"=>"false"` . + + 4. 启用它: + + ``` + Feature . enable ( 'gitaly_go_find_all_tags' ) + ``` + + 5. 退出 Rails 控制台并执行触发更改所需的任何操作(项目创建,提交提交,观察历史记录等). + 6. 通过观察该功能的度量来确认该功能已启用: + + ``` + curl --silent http://localhost:9236/metrics | grep go_find_all_tags + ``` \ No newline at end of file diff --git a/_book/docs/608.md b/_book/docs/608.md new file mode 100644 index 0000000000000000000000000000000000000000..bae58bf95bcbb7ba748b298b9404cff2358df1cb --- /dev/null +++ b/_book/docs/608.md @@ -0,0 +1 @@ +> 原文:[https://design.gitlab.com/](https://design.gitlab.com/) \ No newline at end of file diff --git a/_book/docs/609.md b/_book/docs/609.md new file mode 100644 index 0000000000000000000000000000000000000000..23efcd30f9d7a28e57cc8544fd5f3fc0aabd0759 --- /dev/null +++ b/_book/docs/609.md @@ -0,0 +1,28 @@ +# GitLab development style guides + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/style/](https://docs.gitlab.com/ee/development/fe_guide/style/) + +* [JavaScript style guide](#javascript-style-guide) +* [SCSS style guide](#scss-style-guide) +* [HTML style guide](#html-style-guide) +* [Vue style guide](#vue-style-guide) + +# GitLab development style guides[](#gitlab-development-style-guides "Permalink") + +请参阅下面有关开发 GitLab 的相关样式指南,指南,棉绒和其他信息. + +## JavaScript style guide[](#javascript-style-guide "Permalink") + +我们使用`eslint`来实施我们的[JavaScript 样式指南](javascript.html) . 我们的指南基于出色的[AirBnB](https://github.com/airbnb/javascript)样式指南,并做了一些小改动. + +## SCSS style guide[](#scss-style-guide "Permalink") + +我们的[SCSS 约定](scss.html)通过[`scss-lint`](https://github.com/sds/scss-lint)强制执行. + +## HTML style guide[](#html-style-guide "Permalink") + +与其余代码库一致的编写[HTML 代码的](html.html)准则. + +## Vue style guide[](#vue-style-guide "Permalink") + +在[Vue 样式指南中](vue.html)可以找到有关 Vue 代码的准则和约定. \ No newline at end of file diff --git a/_book/docs/610.md b/_book/docs/610.md new file mode 100644 index 0000000000000000000000000000000000000000..3b538151a2165db464d5fa14a821eebec8fd0780 --- /dev/null +++ b/_book/docs/610.md @@ -0,0 +1,244 @@ +# API style guide + +> 原文:[https://docs.gitlab.com/ee/development/api_styleguide.html](https://docs.gitlab.com/ee/development/api_styleguide.html) + +* [Instance variables](#instance-variables) +* [Entities](#entities) +* [Documentation](#documentation) +* [Methods and parameters description](#methods-and-parameters-description) +* [Declared parameters](#declared-parameters) + * [Exclude parameters from parent namespaces](#exclude-parameters-from-parent-namespaces) + * [When to use `declared(params)`](#when-to-use-declaredparams) +* [Array types](#array-types) + * [Automatic coercion of nil inputs](#automatic-coercion-of-nil-inputs) +* [Using HTTP status helpers](#using-http-status-helpers) +* [Using API path helpers in GitLab Rails codebase](#using-api-path-helpers-in-gitlab-rails-codebase) +* [Custom Validators](#custom-validators) + * [Using custom validators](#using-custom-validators) + * [Adding a new custom validator](#adding-a-new-custom-validator) +* [Internal API](#internal-api) +* [Avoiding N+1 problems](#avoiding-n1-problems) + * [Verifying with tests](#verifying-with-tests) +* [Testing](#testing) + +# API style guide[](#api-style-guide "Permalink") + +该样式指南建议 API 开发的最佳做法. + +## Instance variables[](#instance-variables "Permalink") + +请不要使用实例变量,不需要它们(我们不需要像在 Rails 视图中那样访问它们),可以使用局部变量. + +## Entities[](#entities "Permalink") + +始终使用[实体](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/entities)来呈现端点的有效负载. + +## Documentation[](#documentation "Permalink") + +API 端点必须随附[文档](documentation/styleguide.html#api) ,除非[文档](documentation/styleguide.html#api)在内部或在功能标志后面. 这些文档应位于同一合并请求中,或者在严格必要的情况下,应与原始合并请求具有相同的里程碑. + +## Methods and parameters description[](#methods-and-parameters-description "Permalink") + +每种方法都必须使用[Grape DSL](https://github.com/ruby-grape/grape#describing-methods)进行描述(有关示例,请参见[https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/environments.rb](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/environments.rb) ): + +* `desc`的方法的总结. 您应该将其传递给其他细节,例如: + * 添加端点时的 GitLab 版本. 如果它在功能标志后面,请提及: *该功能由:feature_flag_symbol 功能标志控制.* + * 如果不赞成使用端点,那么,何时删除它 +* `params`方法参数. 这充当[参数的](https://github.com/ruby-grape/grape#parameter-validation-and-coercion)描述, [验证和强制](https://github.com/ruby-grape/grape#parameter-validation-and-coercion) + +一个很好的例子如下: + +``` +desc 'Get all broadcast messages' do + detail 'This feature was introduced in GitLab 8.12.' + success Entities::BroadcastMessage +end +params do + optional :page, type: Integer, desc: 'Current page number' + optional :per_page, type: Integer, desc: 'Number of messages per page' +end +get do + messages = BroadcastMessage.all + + present paginate(messages), with: Entities::BroadcastMessage +end +``` + +## Declared parameters[](#declared-parameters "Permalink") + +> Grape 允许您仅访问由`params`块声明的`params` . 它过滤掉已传递但不允许的参数. + +– [https://github.com/ruby-grape/grape#declared](https://github.com/ruby-grape/grape#declared) + +### Exclude parameters from parent namespaces[](#exclude-parameters-from-parent-namespaces "Permalink") + +> 默认情况下, `declared(params)`包括在所有父名称空间中定义的参数. + +– [https://github.com/ruby-grape/grape#include-parent-namespaces](https://github.com/ruby-grape/grape#include-parent-namespaces) + +在大多数情况下,您将希望从父名称空间中排除参数: + +``` +declared(params, include_parent_namespaces: false) +``` + +### When to use `declared(params)`[](#when-to-use-declaredparams "Permalink") + +You should always use `declared(params)` when you pass the parameters hash as arguments to a method call. + +例如: + +``` +# bad +User.create(params) # imagine the user submitted `admin=1`... :) + +# good +User.create(declared(params, include_parent_namespaces: false).to_h) +``` + +> **注意:** `Hashie::Mash` `declared(params)`返回一个`Hashie::Mash`对象,您必须在其上调用`.to_h` . + +但是,当我们访问单个元素时,可以直接使用`params[key]` . + +例如: + +``` +# good +Model.create(foo: params[:foo]) +``` + +## Array types[](#array-types "Permalink") + +在 Grape v1.3 +中,必须使用`coerce_with`块定义数组类型,否则当从 API 请求传递字符串时,参数将无法验证. 有关更多详细信息,请参见[Grape 升级文档](https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#ensure-that-array-types-have-explicit-coercions) . + +### Automatic coercion of nil inputs[](#automatic-coercion-of-nil-inputs "Permalink") + +在 Grape v1.3.3 之前,具有`nil`值的 Array 参数将自动强制为空 Array. 但是,由于[v1.3.3 中的拉取请求,](https://github.com/ruby-grape/grape/pull/2040)情况不再如此. 例如,假设您定义一个具有可选参数的 PUT `/test`请求: + +``` +optional :user_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The user ids for this rule' +``` + +通常情况下,把一个请求`/test?user_ids`会导致葡萄传递`params`的`{ user_ids: nil }` . + +这可能会导致端点期望为空数组且无法正确处理`nil`输入的错误. 为了保留以前的行为,有一个辅助方法`coerce_nil_params_to_array!` 在所有 API 调用的`before`块中使用的代码: + +``` +before do + coerce_nil_params_to_array! +end +``` + +进行此更改后,对 PUT `/test?user_ids`的请求将使 Grape 传递的`params`为`{ user_ids: [] }` . + +[Grape Tracker 中](https://github.com/ruby-grape/grape/issues/2068)存在[一个未解决的问题,](https://github.com/ruby-grape/grape/issues/2068)可以使此操作更容易. + +## Using HTTP status helpers[](#using-http-status-helpers "Permalink") + +对于非 200 HTTP 响应,请使用`lib/api/helpers.rb`提供的帮助`lib/api/helpers.rb`以确保行为正确( `not_found!` , `no_content!`等). 这些将`throw` Grape 并中止端点的执行. + +对于`DELETE`请求,通常还应该`destroy_conditionally!`地使用`destroy_conditionally!` 默认情况下,helper 会在成功时返回`204 No Content`响应,或者在给定的`If-Unmodified-Since`标头超出范围时返回`412 Precondition Failed` . 该助手在传递的资源上调用`#destroy` ,但是您也可以通过传递一个块来实现自定义删除方法. + +## Using API path helpers in GitLab Rails codebase[](#using-api-path-helpers-in-gitlab-rails-codebase "Permalink") + +因为我们支持[在相对 URL 下安装 GitLab](../install/relative_url.html) ,所以在使用 Grape 生成的 API 路径帮助程序时必须考虑到这一点. 任何此类 API 路径帮助程序用法都必须包装在`expose_path`帮助程序调用中. + +例如: + +``` +- endpoint = expose_path(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid)) +``` + +## Custom Validators[](#custom-validators "Permalink") + +为了验证 API 请求中的某些参数,我们先验证它们,然后再进一步发送它们(例如 Gitaly). 以下是[自定义验证器](https://GitLab.com/gitlab-org/gitlab/-/tree/master/lib/api/validations/validators) ,到目前为止,我们已经添加了它们以及如何使用它们. 我们还编写了有关如何添加新的自定义验证器的指南. + +### Using custom validators[](#using-custom-validators "Permalink") + +* `FilePath`: + + GitLab 支持我们需要遍历文件路径的各种功能. [`FilePath`验证器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators/file_path.rb)针对不同情况验证参数值. 主要是,它使用`File::Separator`检查路径是否是相对路径,是否包含`../../`相对遍历,以及路径是否是绝对路径,例如`/etc/passwd/` . + +* `Git SHA`: + + [`Git SHA`验证器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators/git_sha.rb)检查 Git SHA 参数是否为有效的 SHA. 它通过使用[`commit.rb`](https://gitlab.com/gitlab-org/gitlab/-/commit/b9857d8b662a2dbbf54f46ecdcecb44702affe55#d1c10892daedb4d4dd3d4b12b6d071091eea83df_30_30)文件中提到的正则表达式进行检查. + +* `Absence`: + + [`Absence`验证器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators/absence.rb)检查给定参数哈希中是否缺少特定参数. + +* `IntegerNoneAny`: + + [`IntegerNoneAny`验证器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators/integer_none_any.rb)检查给定参数的值是`Integer` , `None`还是`Any` . 它仅允许上述任何一个值在请求中前进. + +* `ArrayNoneAny`: + + [`ArrayNoneAny`验证器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators/array_none_any.rb)检查给定参数的值是`Array` , `None`还是`Any` . 它仅允许上述任何一个值在请求中前进. + +### Adding a new custom validator[](#adding-a-new-custom-validator "Permalink") + +自定义验证器是在将参数发送到平台进行进一步处理之前对其进行验证的好方法. 如果我们在一开始就识别出无效的参数,它将在服务器和平台之间来回保存一些时间. + +如果您需要添加自定义验证器,它将被添加到[`validators`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators)目录中自己的文件中. 由于我们使用[Grape](https://github.com/ruby-grape/grape)添加 API,因此我们继承了`Grape::Validations::Base`类中的`Grape::Validations::Base`类. 现在,您要做的就是定义`validate_param!` 该方法具有两个参数: `params`哈希和要验证的`param`名称. + +该方法的主体进行了验证参数值的艰苦工作,并将适当的错误消息返回给调用方方法. + +最后,我们使用以下行注册验证器: + +``` +Grape::Validations.register_validator(<validator name as symbol>, ::API::Helpers::CustomValidators::<YourCustomValidatorClassName>) +``` + +添加验证器后,请确保将其`rspec`添加到其在[`validators`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/lib/api/validations/validators)目录中的自己的文件中. + +## Internal API[](#internal-api "Permalink") + +[内部 API](./internal_api.html)已记录供内部使用. 请保持最新状态,以便我们了解不同组件正在使用哪些端点. + +## Avoiding N+1 problems[](#avoiding-n1-problems "Permalink") + +为了避免在 API 端点中返回记录集合时常见的 N + 1 问题,我们应该使用预先加载. + +在 API 中执行此操作的标准方法是让模型实现一个名为`with_api_entity_associations`的范围,该范围将预加载 API 中返回的关联和数据. 在[`Issue`模型中](https://gitlab.com/gitlab-org/gitlab/blob/2fedc47b97837ea08c3016cf2fb773a0300a4a25/app/models/issue.rb#L62)可以看到此范围的示例. + +在同一个模型的 API 中有多个实体的情况下(例如`UserBasic` , `User`和`UserPublic` ),您应谨慎使用此范围. 可能是您针对最基本的实体进行了优化,并在该范围上建立了连续的实体. + +当在 Todos API 中返回时, `with_api_entity_associations`范围还将[自动](https://gitlab.com/gitlab-org/gitlab/blob/19f74903240e209736c7668132e6a5a735954e7c/app/models/todo.rb#L34)为`Todo` *目标* [预先加载数据](https://gitlab.com/gitlab-org/gitlab/blob/19f74903240e209736c7668132e6a5a735954e7c/app/models/todo.rb#L34) . + +有关预加载的更多上下文和讨论,请参阅[此合并请求](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25711) , [该合并请求](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25711)引入了作用域. + +### Verifying with tests[](#verifying-with-tests "Permalink") + +当 API 端点返回集合时,无论现在还是将来,始终添加一个测试以验证 API 端点没有 N + 1 问题. 我们可以使用[`ActiveRecord::QueryRecorder`](query_recorder.html)做到这一点. + +Example: + +``` +def make_api_request + get api('/foo', personal_access_token: pat) +end + +it 'avoids N+1 queries', :request_store do + # Firstly, record how many PostgreSQL queries the endpoint will make + # when it returns a single record + create_record + + control = ActiveRecord::QueryRecorder.new { make_api_request } + + # Now create a second record and ensure that the API does not execute + # any more queries than before + create_record + + expect { make_api_request }.not_to exceed_query_limit(control) +end +``` + +## Testing[](#testing "Permalink") + +在编写新的 API 端点的测试,可以考虑使用模式[夹具](./testing_guide/best_practices.html#fixtures)位于`/spec/fixtures/api/schemas` . 您可以`expect`响应匹配给定的架构: + +``` +expect(response).to match_response_schema('merge_requests') +``` + +另请参阅在测试中[验证 N + 1 性能](#verifying-with-tests) . \ No newline at end of file diff --git a/_book/docs/611.md b/_book/docs/611.md new file mode 100644 index 0000000000000000000000000000000000000000..5f8ad5f11f232aede3f7fb101f609daf7c34a15e --- /dev/null +++ b/_book/docs/611.md @@ -0,0 +1,353 @@ +# Go standards and style guidelines + +> 原文:[https://docs.gitlab.com/ee/development/go_guide/](https://docs.gitlab.com/ee/development/go_guide/) + +* [Overview](#overview) +* [Dependency Management](#dependency-management) +* [Code Review](#code-review) + * [Security](#security) + * [Finding a reviewer](#finding-a-reviewer) +* [Code style and format](#code-style-and-format) + * [Automatic linting](#automatic-linting) +* [Dependencies](#dependencies) + * [Modules](#modules) + * [ORM](#orm) + * [Migrations](#migrations) +* [Testing](#testing) + * [Testing frameworks](#testing-frameworks) + * [Subtests](#subtests) + * [Better output in tests](#better-output-in-tests) + * [Table-Driven Tests](#table-driven-tests) + * [Defining test cases](#defining-test-cases) + * [Contents of the test case](#contents-of-the-test-case) + * [Variable names](#variable-names) + * [Benchmarks](#benchmarks) +* [Error handling](#error-handling) + * [Adding context](#adding-context) + * [Naming](#naming) + * [Checking Error types](#checking-error-types) + * [References for working with errors](#references-for-working-with-errors) +* [CLIs](#clis) +* [Daemons](#daemons) + * [Logging](#logging) + * [Structured (JSON) logging](#structured-json-logging) + * [How to use Logrus](#how-to-use-logrus) + * [Tracing and Correlation](#tracing-and-correlation) + * [Context](#context) +* [Dockerfiles](#dockerfiles) +* [Distributing Go binaries](#distributing-go-binaries) + * [Updating Go version](#updating-go-version) + * [Supporting multiple Go versions](#supporting-multiple-go-versions) +* [Secure Team standards and style guidelines](#secure-team-standards-and-style-guidelines) + * [Code style and format](#code-style-and-format-1) + +# Go standards and style guidelines[](#go-standards-and-style-guidelines "Permalink") + +本文档介绍了使用[Go 语言的](https://s0golang0org.icopy.site) GitLab 项目的各种指南和最佳实践. + +## Overview[](#overview "Permalink") + +GitLab 构建在[Ruby on Rails](https://rubyonrails.org/)之上,但我们还在有意义的项目中使用 Go. Go 是一种非常强大的语言,具有许多优点,最适合具有大量 IO(磁盘/网络访问),HTTP 请求,并行处理等的项目.由于我们在 git 上都有 Ruby on Rails 和 Go,因此我们应该仔细评估两者中哪一个最适合工作. + +该页面旨在根据我们的各种经验来定义和组织我们的 Go 准则. 几个项目是从不同的标准开始的,但仍然可以有一些具体说明. 它们将在各自的`README.md`或`PROCESS.md`文件中进行描述. + +## Dependency Management[](#dependency-management "Permalink") + +Go 使用基于源的策略进行依赖性管理. 依赖项从其源存储库中下载为源. 这不同于更常见的基于工件的策略,在后者中,依赖项是从与依赖项源存储库分开的程序包存储库中作为工件下载的. + +Go 在 1.11 之前没有对版本管理的一流支持. 该版本引入了 Go 模块和语义版本控制的使用. Go 1.12 引入了模块代理,它们可以用作客户端和源版本控制系统之间的中介,以及校验和数据库,可以用于验证依赖项下载的完整性. + +有关更多详细信息,请参见[Go 中的依赖管理](dependencies.html) . + +## Code Review[](#code-review "Permalink") + +我们遵循[Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)的通用原则. + +审阅者和维护者应注意: + +* `defer`功能:在需要时以及在`err`检查之后确保存在. +* 注入依赖项作为参数. +* 封送至 JSON 时,其 Void 结构(生成`null`而不是`[]` ). + +### Security[](#security "Permalink") + +安全是我们在 GitLab 的首要任务. 在代码审查期间,我们必须注意代码中可能存在的安全漏洞: + +* 使用文字/模板时的 XSS +* 使用大猩猩的 CSRF 保护 +* 使用没有已知漏洞的 Go 版本 +* 不要泄漏秘密令牌 +* SQL 注入 + +记住要运行[SAST](../../user/application_security/sast/index.html)和[依赖项扫描](../../user/application_security/dependency_scanning/index.html) 在您的项目(或至少是[gosec 分析器](https://gitlab.com/gitlab-org/security-products/analyzers/gosec) )上,并遵守我们的[安全要求](../code_review.html#security-requirements) . + +Web 服务器可以利用[Secure](https://github.com/unrolled/secure)等中间件的优势. + +### Finding a reviewer[](#finding-a-reviewer "Permalink") + +我们的许多项目规模太小,无法拥有专职维护人员. 这就是为什么我们在 GitLab 有一个共享的 Go 评论者池. 要查找审阅者,请使用手册"工程项目"页面上" GitLab"项目的["执行"部分](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_go) . + +要将您自己添加到此列表中,请将以下内容添加到[team.yml](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/team.yml)文件中的个人资料中,并请您的经理进行审核和合并. + +``` +projects: + gitlab: reviewer go +``` + +## Code style and format[](#code-style-and-format "Permalink") + +* 避免全局变量,即使在软件包中也是如此. 这样,如果多次包含该软件包,您将产生副作用. +* 在提交之前使用`goimports` . [goimports](https://s0godoc0org.icopy.site/golang.org/x/tools/cmd/goimports)是一个工具,除了格式化导入行,添加缺少的行和删除未引用的行之外, [它还可以](https://s0golang0org.icopy.site/cmd/gofmt/)使用[Gofmt](https://s0golang0org.icopy.site/cmd/gofmt/)自动格式化 Go 源代码. + + 大多数编辑器/ IDE 允许您在保存文件之前/之后运行命令,您可以将其设置为运行`goimports`以便在保存时将其应用于每个文件. + +* 将私有方法放在源文件中第一个调用方方法的下面. + +### Automatic linting[](#automatic-linting "Permalink") + +所有 Go 项目均应包括以下 GitLab CI / CD 作业: + +``` +lint: + image: registry.gitlab.com/gitlab-org/gitlab-build-images:golangci-lint-alpine + stage: test + script: + # Use default .golangci.yml file from the image if one is not present in the project root. + - '[ -e .golangci.yml ] || cp /golangci/.golangci.yml .' + # Write the code coverage report to gl-code-quality-report.json + # and print linting issues to stdout in the format: path/to/file:line description + - golangci-lint run --out-format code-climate | tee gl-code-quality-report.json | jq -r '.[] | "\(.location.path):\(.location.lines.begin) \(.description)"' + artifacts: + reports: + codequality: gl-code-quality-report.json + paths: + - gl-code-quality-report.json + allow_failure: true +``` + +在项目的根目录中包含`.golangci.yml`可以配置`golangci-lint` . 此[示例](https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml)中列出了`golangci-lint`所有选项. + +[递归包含](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/56836)可用后,您就可以共享作业模板,例如此[分析器](https://gitlab.com/gitlab-org/security-products/ci-templates/raw/master/includes-dev/analyzer.yml) . + +## Dependencies[](#dependencies "Permalink") + +依赖性应保持最小. 根据我们的[批准指南](../code_review.html#approval-guidelines) ,应在合并请求中对引入新的依赖项进行争论. 两种[许可证管理](../../user/compliance/license_compliance/index.html) 和[依赖项扫描](../../user/application_security/dependency_scanning/index.html) 应该在所有项目上激活,以确保新的依赖项安全状态和许可证兼容性. + +### Modules[](#modules "Permalink") + +从 Go 1.11 开始,名称[Go 的模块](https://github.com/golang/go/wiki/Modules)后面提供了一个标准的依赖系统. 它提供了一种方法来定义和锁定可复制构建的依赖关系. 应尽可能使用它. + +当使用 Go Modules 时,不应有`vendor/`目录. 相反,Go 会在需要构建项目时自动下载依赖项. 这与 Ruby 项目中 Bundler 处理依赖关系的方式一致,并使合并请求更易于查看. + +在某些情况下,例如构建一个 Go 项目以充当另一个项目的 CI 运行的依赖项,删除`vendor/`目录意味着必须重复下载代码,这可能由于速率限制或网络而导致间歇性问题.失败. 在这种情况下,您应该[在之间缓存下载的代码](../../ci/caching/index.html#caching-go-dependencies) . + +Go <v1.11.4 中的[模块校验和](https://github.com/golang/go/issues/29278)存在一个[错误](https://github.com/golang/go/issues/29278) ,因此请确保至少使用此版本,以避免`checksum mismatch`错误. + +### ORM[](#orm "Permalink") + +我们不在 GitLab 上使用对象关系映射库(ORM)(Ruby on Rails 中的[ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html)除外). 可以使用服务来结构化项目以避免它们. [PQ](https://github.com/lib/pq)应该足以与 PostgreSQL 数据库进行交互. + +### Migrations[](#migrations "Permalink") + +在极少数情况下,如果管理托管数据库,则必须使用 ActiveRecord 提供的迁移系统. 像[Journey](https://github.com/db-journey/journey)这样的简单库,可以在`postgres`容器中使用,可以部署为长期运行的 pod. 新版本将部署新的 Pod,并自动迁移数据. + +## Testing[](#testing "Permalink") + +### Testing frameworks[](#testing-frameworks "Permalink") + +我们不应该使用任何特定的库或框架来进行测试,因为[标准库](https://s0golang0org.icopy.site/pkg/)已经提供了入门所需的一切. 如果需要更复杂的测试工具,则在我们决定使用特定的库或框架时,以下外部依赖项可能值得考虑: + +* [Testify](https://github.com/stretchr/testify) +* [httpexpect](https://github.com/gavv/httpexpect) + +### Subtests[](#subtests "Permalink") + +尽可能使用[子测试,](https://blog.golang.org/subtests)以提高代码的可读性和测试输出. + +### Better output in tests[](#better-output-in-tests "Permalink") + +When comparing expected and actual values in tests, use [`testify/require.Equal`](https://s0godoc0org.icopy.site/github.com/stretchr/testify/require), [`testify/require.EqualError`](https://s0godoc0org.icopy.site/github.com/stretchr/testify/require), [`testify/require.EqualValues`](https://s0godoc0org.icopy.site/github.com/stretchr/testify/require), and others to improve readability when comparing structs, errors, large portions of text, or JSON documents: + +``` +type TestData struct { + // ... +} + +func FuncUnderTest() TestData { + // ... +} + +func Test(t *testing.T) { + t.Run("FuncUnderTest", func(t *testing.T) { + want := TestData{} + got := FuncUnderTest() + + require.Equal(t, want, got) // note that expected value comes first, then comes the actual one ("diff" semantics) + }) +} +``` + +### Table-Driven Tests[](#table-driven-tests "Permalink") + +当您为同一功能输入/输出有多个条目时,使用[表驱动测试](https://github.com/golang/go/wiki/TableDrivenTests)通常是一个好习惯. 以下是编写表驱动测试时可以遵循的一些准则. 这些准则主要是从 Go 标准库源代码中提取的. 请记住,在合理的时候不要遵循这些准则. + +#### Defining test cases[](#defining-test-cases "Permalink") + +每个表条目都是一个完整的测试用例,其中包含输入和预期结果,有时还包含其他信息(例如测试名称),以使测试输出易于阅读. + +* 在测试内部[定义一片匿名结构](https://github.com/golang/go/blob/50bd1c4d4eb4fac8ddeb5f063c099daccfb71b26/src/encoding/csv/reader_test.go#L16) . +* 在测试之外[定义一片匿名结构](https://github.com/golang/go/blob/55d31e16c12c38d36811bdee65ac1f7772148250/src/cmd/go/internal/module/module_test.go#L9-L66) . +* 用于代码重用的[命名结构](https://github.com/golang/go/blob/2e0cd2aef5924e48e1ceb74e3d52e76c56dd34cc/src/cmd/go/internal/modfetch/coderepo_test.go#L54-L69) . +* [Using `map[string]struct{}`](https://github.com/golang/go/blob/6d5caf38e37bf9aeba3291f1f0b0081f934b1187/src/cmd/trace/annotations_test.go#L180-L235). + +#### Contents of the test case[](#contents-of-the-test-case "Permalink") + +* 理想情况下,每个测试用例都应具有一个带有唯一标识符的字段,以用于命名子测试. 在 Go 标准库中,这通常是`name string`字段. +* 当您在测试用例中指定将用于断言的内容时,请使用`want` / `expect` / `actual` . + +#### Variable names[](#variable-names "Permalink") + +* 每个表驱动的测试映射/结构片段都可以命名为`tests` . +* 遍历`tests` ,匿名结构可以称为`tt`或`tc` . +* 测试的描述可以称为`name` / `testName` / `tn` . + +### Benchmarks[](#benchmarks "Permalink") + +处理大量 IO 或复杂操作的程序应始终包含[基准测试](https://s0golang0org.icopy.site/pkg/testing/) ,以确保随时间推移的性能一致性. + +## Error handling[](#error-handling "Permalink") + +### Adding context[](#adding-context "Permalink") + +在返回错误之前添加上下文可能会有所帮助,而不仅仅是返回错误. 这使开发人员可以了解程序进入错误状态时试图做什么,从而使调试更加容易. + +例如: + +``` +// Wrap the error +return nil, fmt.Errorf("get cache %s: %w", f.Name, err) + +// Just add context +return nil, fmt.Errorf("saving cache %s: %v", f.Name, err) +``` + +A few things to keep in mind when adding context: + +* 确定是否要向调用者公开潜在的错误. 如果是这样,请使用`%w` ,否则请使用`%v` . +* 不要使用`failed` , `error` , `didn't` . 因为这是一个错误,所以用户已经知道某件事失败了,这可能导致出现诸如`failed xx failed xx failed xx`类的字符串. 解释*什么* ,而不是失败. +* 错误字符串不应大写或以标点符号或换行符结尾. 您可以使用`golint`进行检查. + +### Naming[](#naming "Permalink") + +* 使用哨兵错误时,应始终将它们命名为`ErrXxx` . +* 创建新的错误类型时,应始终将其命名为`XxxError` . + +### Checking Error types[](#checking-error-types "Permalink") + +* 要检查错误是否相等,请不要使用`==` . 使用[`errors.Is`](https://pkg.go.dev/errors?tab=doc#Is)代替(对于围棋版本> = 1.13). +* 要检查错误是否属于某种类型,请不要使用类型断言,而应使用[`errors.As`](https://pkg.go.dev/errors?tab=doc#As) (对于 Go 版本> = 1.13). + +### References for working with errors[](#references-for-working-with-errors "Permalink") + +* [Go 1.13 errors](https://blog.golang.org/go1.13-errors). +* [Programing with errors](https://peter.bourgon.org/blog/2019/09/11/programming-with-errors.html). +* [Don’t just check errors, handle them gracefully](https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully). + +## CLIs[](#clis "Permalink") + +每个 Go 程序都是从命令行启动的. [cli](https://github.com/urfave/cli)是用于创建命令行应用程序的便捷软件包. 无论项目是守护程序还是简单的 cli 工具,都应使用它. 可以将标志直接映射到[环境变量](https://github.com/urfave/cli#values-from-the-environment) ,这些[变量](https://github.com/urfave/cli#values-from-the-environment)同时记录和集中与程序的所有可能的命令行交互. 不要使用`os.GetEnv` ,它会将变量隐藏在代码深处. + +## Daemons[](#daemons "Permalink") + +### Logging[](#logging "Permalink") + +强烈建议为守护程序使用日志记录库. 即使标准库中有一个`log`包,我们通常也使用[Logrus](https://github.com/sirupsen/logrus) . 它的插件("挂钩")系统使其成为功能强大的日志记录库,并能够直接在记录器级别添加通知程序和格式化程序. + +#### Structured (JSON) logging[](#structured-json-logging "Permalink") + +理想情况下,每个二进制文件都必须具有结构化(JSON)日志记录,因为它有助于搜索和过滤日志. 在 GitLab,我们使用 JSON 格式的结构化日志记录,因为我们所有的基础架构都假定这样做. 使用[Logrus 时](https://github.com/sirupsen/logrus) ,只需使用[JSON 格式化程序中](https://github.com/sirupsen/logrus#formatters)的构建即可打开结构化日志记录. 这遵循我们在[Ruby 应用程序中](../logging.html#use-structured-json-logging)使用的相同日志记录类型. + +#### How to use Logrus[](#how-to-use-logrus "Permalink") + +使用[Logrus](https://github.com/sirupsen/logrus)软件包时,应遵循一些准则: + +* 打印错误时,请使用[WithError](https://s0godoc0org.icopy.site/github.com/sirupsen/logrus) . 例如, `logrus.WithError(err).Error("Failed to do something")` . +* 由于我们使用[结构化日志记录](#structured-json-logging) ,因此可以在该代码路径的上下文中记录字段,例如使用[`WithField`](https://s0godoc0org.icopy.site/github.com/sirupsen/logrus)或[`WithFields`](https://s0godoc0org.icopy.site/github.com/sirupsen/logrus)的请求的 URI. 例如, `logrus.WithField("file", "/app/go").Info("Opening dir")` . 如果必须记录多个键,请始终使用`WithFields`而不是多次调用`WithField` . + +### Tracing and Correlation[](#tracing-and-correlation "Permalink") + +[LabKit](https://gitlab.com/gitlab-org/labkit)是为 Go 服务保留通用库的地方. 目前,它已销售到两个项目:Workhorse 和 Gitaly,并且导出了两个主要(但相关)功能: + +* [`gitlab.com/gitlab-org/labkit/correlation`](https://gitlab.com/gitlab-org/labkit/tree/master/correlation) :用于传播和提取服务之间的相关 ID. +* [`gitlab.com/gitlab-org/labkit/tracing`](https://gitlab.com/gitlab-org/labkit/tree/master/tracing): for instrumenting Go libraries for distributed tracing. + +这为我们提供了对底层实现的精简抽象,该抽象实现在 Workhorse,Gitaly 以及将来的其他 Go 服务器之间保持一致. 例如,对于`gitlab.com/gitlab-org/labkit/tracing`我们可以从直接使用`gitlab.com/gitlab-org/labkit/tracing`切换为使用 Zipkin 或 Gokit 自己的跟踪包装器,而无需更改应用程序代码,同时仍保持相同的一致配置机制(即`GITLAB_TRACING`环境变量). + +### Context[](#context "Permalink") + +由于守护程序是长期运行的应用程序,因此它们应具有管理取消的机制,并避免不必要的资源消耗(这可能导致 DDOS 漏洞). [Go Context](https://github.com/golang/go/wiki/CodeReviewComments#contexts)应该在可以阻塞并作为第一个参数传递的函数中使用. + +## Dockerfiles[](#dockerfiles "Permalink") + +每个项目都应在其存储库的根目录中具有一个`Dockerfile` ,以构建和运行该项目. 由于 Go 程序是静态二进制文件,因此它们不需要任何外部依赖关系,并且最终映像中的 shell 无用. 我们鼓励进行[多阶段构建](https://s0docs0docker0com.icopy.site/develop/develop-images/multistage-build/) : + +* 他们使用户可以使用正确的 Go 版本和依赖项来构建项目. +* 它们生成一个小的,自包含的图像,该图像取自`Scratch` . + +生成的 Docker 映像应在其`Entrypoint`处具有程序以创建可移植命令. 这样,任何人都可以运行该映像,并且没有参数就可以显示其帮助消息(如果已使用`cli` ). + +## Distributing Go binaries[](#distributing-go-binaries "Permalink") + +除了发布自己的二进制文件的[GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner)之外,我们的 Go 二进制文件都是由" [分发"组](https://about.gitlab.com/handbook/product/product-categories/#distribution-group)管理的项目创建的. + +[Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab)项目创建一个包含所有二进制文件的单一的操作系统软件包,而[Cloud-Native GitLab(CNG)](https://gitlab.com/gitlab-org/build/CNG)项目发布一组 Docker 映像和 Helm 图表以将它们粘合在一起. + +两种方法对所有项目都使用相同版本的 Go,因此确保我们所有使用 Go 的项目在其测试矩阵中至少具有一个相同的 Go 版本非常重要. 您可以检查[Omnibus](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/blob/master/docker/Dockerfile_debian_10#L59)当前正在使用的 Go 版本以及[CNG](https://gitlab.com/gitlab-org/build/cng/blob/master/ci_files/variables.yml#L12)正在使用的版本. + +### Updating Go version[](#updating-go-version "Permalink") + +我们应该始终使用[受支持](https://s0golang0org.icopy.site/doc/devel/release.html)的 Go [版本](https://s0golang0org.icopy.site/doc/devel/release.html) ,即三个最新的次要版本之一,并且应该始终使用该版本的最新补丁程序级别,因为它可能包含安全修复程序. + +更改版本会影响正在编译的每个项目,因此在更改程序包构建器以使用它之前,请确保已更新所有项目以针对新的 Go 版本进行测试非常重要. 尽管[Go 保证了兼容性](https://s0golang0org.icopy.site/doc/go1compat) ,但次要版本之间的更改可能会暴露错误或在我们的项目中引起问题. + +选择要使用的新 Go 版本之后,更新 Omnibus 和 CNG 的步骤如下: + +* [创建于 CNG 项目的合并请求](https://gitlab.com/gitlab-org/build/CNG/edit/master/ci_files/variables.yml?branch_name=update-go-version) ,更新`GO_VERSION`在`ci_files/variables.yml` . +* 在[`gitlab-omnibus-builder`项目中](https://gitlab.com/gitlab-org/gitlab-omnibus-builder)创建合并请求,更新`GO_VERSION` `docker/`目录中的每个文件,以便`GO_VERSION`设置`GO_VERSION` . [这是一个例子](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/125/diffs) . +* 标记包含更改的`gitlab-omnibus-builder`的新版本. +* [在`omnibus-gitlab`项目中创建合并请求](https://gitlab.com/gitlab-org/omnibus-gitlab/edit/master/.gitlab-ci.yml?branch_name=update-gitlab-omnibus-builder-version) ,更新`BUILDER_IMAGE_REVISION`以匹配新创建的标记. + +为了减少两种分发方法之间不必要的差异,Omnibus 和 CNG **应该始终使用相同的 Go 版本** . + +### Supporting multiple Go versions[](#supporting-multiple-go-versions "Permalink") + +出于以下原因,各个 Golang 项目需要支持多个 Go 版本: + +1. 当新的 Go 版本发布时,我们应该开始将其集成到 CI 管道中,以验证与新编译器的兼容性. +2. 我们必须支持[Omnibus 官方的 Go 版本](#updating-go-version) ,该[版本](#updating-go-version)可能在最新的次要版本之后. +3. 当 Omnibus 切换为 Go 版本时,我们仍可能需要支持旧版本进行安全反向移植. + +保持对 Go 的 3 个最新次要版本的支持,可以轻松满足这 3 个要求. + +可以放弃对最旧的 Go 版本的支持,并且仅支持 2 个最新版本,如果这足以支持向后 3 个 GitLab 次要版本的反向移植. + +Example: + +如果我们要丢弃的支持`go 1.11`在 GitLab `12.10` ,我们需要验证我们使用哪去版本`12.9` , `12.8`和`12.7` . + +我们将不考虑活动的里程碑`12.10` ,因为在关键安全发布的情况下将需要`12.7`的反向端口. + +1. 如果从 GitLab `12.7`开始[Omnibus 和 CNG](#updating-go-version)都在使用 Go `1.12` ,那么我们可以放心地放弃对`1.11`支持. +2. 如果 Omnibus 或 CNG 在 GitLab `12.7`中使用`1.11` ,那么我们仍然需要保持对 Go `1.11`支持,以便更轻松地向后移植安全修复程序. + +## Secure Team standards and style guidelines[](#secure-team-standards-and-style-guidelines "Permalink") + +以下是一些特定于安全团队的样式准则. + +### Code style and format[](#code-style-and-format-1 "Permalink") + +在提交之前,请使用`goimports -local gitlab.com/gitlab-org` . [goimports](https://s0godoc0org.icopy.site/golang.org/x/tools/cmd/goimports)是一个工具,除了格式化导入行,添加缺少的行和删除未引用的行之外, [它还可以](https://s0golang0org.icopy.site/cmd/gofmt/)使用[Gofmt](https://s0golang0org.icopy.site/cmd/gofmt/)自动格式化 Go 源代码. 通过使用`-local gitlab.com/gitlab-org`选项, `goimports`会将本地引用的软件包与外部软件包分开分组. 有关更多详细信息,请参见 Go Wiki 上"代码审查注释"页面[的导入部分](https://github.com/golang/go/wiki/CodeReviewComments#imports) . 大多数编辑器/ IDE 允许您在保存文件之前/之后运行命令,您可以将其设置为运行`goimports -local gitlab.com/gitlab-org`以便在保存时将其应用于每个文件. + +* * * + +[Return to Development documentation](../README.html). \ No newline at end of file diff --git a/_book/docs/612.md b/_book/docs/612.md new file mode 100644 index 0000000000000000000000000000000000000000..038c94410e90284cf62cc4b2ce4398ba33055247 --- /dev/null +++ b/_book/docs/612.md @@ -0,0 +1,937 @@ +# GraphQL API style guide + +> 原文:[https://docs.gitlab.com/ee/development/api_graphql_styleguide.html](https://docs.gitlab.com/ee/development/api_graphql_styleguide.html) + +* [How GitLab implements GraphQL](#how-gitlab-implements-graphql) +* [Deep Dive](#deep-dive) +* [GraphiQL](#graphiql) +* [Authentication](#authentication) +* [Types](#types) + * [Nullable fields](#nullable-fields) + * [Exposing Global IDs](#exposing-global-ids) + * [Connection Types](#connection-types) + * [Shortcut fields](#shortcut-fields) + * [Exposing permissions for a type](#exposing-permissions-for-a-type) +* [Feature flags](#feature-flags) + * [`feature_flag` property](#feature_flag-property) + * [Toggle the value of a field](#toggle-the-value-of-a-field) +* [Deprecating fields](#deprecating-fields) + * [Deprecation reason style guide](#deprecation-reason-style-guide) +* [Enums](#enums) +* [Descriptions](#descriptions) + * [Description style guide](#description-style-guide) + * [`copy_field_description` helper](#copy_field_description-helper) +* [Authorization](#authorization) + * [Type authorization](#type-authorization) + * [Field authorization](#field-authorization) + * [Type and Field authorizations together](#type-and-field-authorizations-together) +* [Resolvers](#resolvers) + * [Correct use of `Resolver#ready?`](#correct-use-of-resolverready) + * [Look-Ahead](#look-ahead) +* [Mutations](#mutations) + * [Building Mutations](#building-mutations) + * [Naming conventions](#naming-conventions) + * [Arguments](#arguments) + * [Fields](#fields) + * [The `resolve` method](#the-resolve-method) + * [Mounting the mutation](#mounting-the-mutation) + * [Authorizing resources](#authorizing-resources) + * [Errors in mutations](#errors-in-mutations) + * [Success](#success) + * [Failure (relevant to the user)](#failure-relevant-to-the-user) + * [Failure (irrelevant to the user)](#failure-irrelevant-to-the-user) + * [Categorizing errors](#categorizing-errors) + * [Aliasing and deprecating mutations](#aliasing-and-deprecating-mutations) +* [Validating arguments](#validating-arguments) +* [GitLab’s custom scalars](#gitlabs-custom-scalars) + * [`Types::TimeType`](#typestimetype) +* [Testing](#testing) +* [Notes about Query flow and GraphQL infrastructure](#notes-about-query-flow-and-graphql-infrastructure) + * [Query limits](#query-limits) +* [Documentation and Schema](#documentation-and-schema) + +# GraphQL API style guide[](#graphql-api-style-guide "Permalink") + +本文档概述了 GitLab 的[GraphQL API](../api/graphql/index.html)的样式指南. + +## How GitLab implements GraphQL[](#how-gitlab-implements-graphql "Permalink") + +我们使用[Robert Mosolgo](https://github.com/rmosolgo/)编写的[GraphQL Ruby 宝石](https://graphql-ruby.org/) . + +所有 GraphQL 查询都定向到单个端点( [`app/controllers/graphql_controller.rb#execute`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/controllers/graphql_controller.rb) ),该端点在`/api/graphql`处作为 API 端点`/api/graphql` . + +## Deep Dive[](#deep-dive "Permalink") + +在 2019 年 3 月,尼克·托马斯(Nick Thomas)在 GitLab 的[GraphQL API 上](../api/graphql/index.html)进行了一次深潜(仅限 GitLab 团队成员: `https://gitlab.com/gitlab-org/create-stage/issues/1` : [//gitlab.com/gitlab-org/create-stage/issues/1](../api/graphql/index.html) ),以与可能将来会在代码库的这一部分中工作. 您可以[在 YouTube 上](https://www.youtube.com/watch?v=-9L_1MWrjkg)找到[录音](https://www.youtube.com/watch?v=-9L_1MWrjkg) ,在[Google 幻灯片](https://docs.google.com/presentation/d/1qOTxpkTdHIp1CRjuTvO-aXg0_rUtzE3ETfLUdnBB5uQ/edit)和[PDF 中](https://gitlab.com/gitlab-org/create-stage/uploads/8e78ea7f326b2ef649e7d7d569c26d56/GraphQL_Deep_Dive__Create_.pdf)找到[幻灯片](https://docs.google.com/presentation/d/1qOTxpkTdHIp1CRjuTvO-aXg0_rUtzE3ETfLUdnBB5uQ/edit) . 自 GitLab 11.9 起,本次深入学习中涉及的所有内容都是准确的,尽管自那时以来特定细节可能有所更改,但它仍应作为一个很好的介绍. + +## GraphiQL[](#graphiql "Permalink") + +GraphiQL 是一个交互式 GraphQL API 资源管理器,您可以在其中使用现有查询. 您可以在`https://<your-gitlab-site.com>/-/graphql-explorer`任何 GitLab 环境中访问它. 例如,用于[GitLab.com 的那个](https://gitlab.com/-/graphql-explorer) . + +## Authentication[](#authentication "Permalink") + +认证通过`GraphqlController` ,现在,它使用与 Rails 应用程序相同的认证. 因此可以共享会话. + +也可以将`private_token`添加到查询字符串,或添加`HTTP_PRIVATE_TOKEN`标头. + +## Types[](#types "Permalink") + +我们使用代码优先模式,并声明 Ruby 中所有内容的类型. + +例如, `app/graphql/types/issue_type.rb` : + +``` +graphql_name 'Issue' + +field :iid, GraphQL::ID_TYPE, null: true +field :title, GraphQL::STRING_TYPE, null: true + +# we also have a method here that we've defined, that extends `field` +markdown_field :title_html, null: true +field :description, GraphQL::STRING_TYPE, null: true +markdown_field :description_html, null: true +``` + +We give each type a name (in this case `Issue`). + +`iid` , `title`和`description`是*标量* GraphQL 类型. `iid`是`GraphQL::ID_TYPE` ,这是一种特殊的字符串类型,表示唯一的 ID. `title`和`description`是常规的`GraphQL::STRING_TYPE`类型. + +When exposing a model through the GraphQL API, we do so by creating a new type in `app/graphql/types`. You can also declare custom GraphQL data types for scalar data types (e.g. `TimeType`). + +公开类型中的属性时,请确保将定义内的逻辑保持尽可能小. 相反,请考虑将任何逻辑转移到演示者中: + +``` +class Types::MergeRequestType < BaseObject + present_using MergeRequestPresenter + + name 'MergeRequest' +end +``` + +可以使用现有的演示者,但是也可以专门为 GraphQL 创建一个新的演示者. + +使用由字段解析的对象和上下文初始化演示者. + +### Nullable fields[](#nullable-fields "Permalink") + +GraphQL 允许字段为"可为空"或"不可为空". 前者意味着可以返回`null`而不是指定类型的值. **通常** ,出于以下原因,您应该首选使用可空字段而不是不可空字段: + +* 数据从必需切换到不需要,然后再次返回是很常见的 +* 即使没有可能成为可选字段的前景,在查询时它也可能不可**用** + * 例如,可能需要从 Gitaly 查找 blob 的`content` + * 如果`content`可为空,我们可以返回**部分**响应,而不是使整个查询失败 +* 对于无版本模式,很难从不可为空的字段更改为可为空的字段 + +非空字段仅应在需要字段时使用,将来不太可能成为可选字段,并且非常容易计算. 一个示例是`id`字段. + +进一步阅读: + +* [GraphQL Best Practices Guide](https://s0graphql0org.icopy.site/learn/best-practices/) +* [Using nullability in GraphQL](https://www.apollographql.com/blog/using-nullability-in-graphql-2254f84c4ed7) + +### Exposing Global IDs[](#exposing-global-ids "Permalink") + +在类型上公开`ID`字段时,默认情况下,我们将通过在要渲染的资源上调用`to_global_id`来公开全局 ID. + +要覆盖此行为,可以在要公开其 ID 的类型上实现`id`方法. 请确保在使用自定义方法公开`GraphQL::ID_TYPE` ,它是全局唯一的. + +被曝光的记录`full_path`作为`ID_TYPE`是这些例外之一. 由于完整路径是`Project`或`Namespace`的唯一标识符. + +### Connection Types[](#connection-types "Permalink") + +GraphQL 使用[基于光标的分页](https://s0graphql0org.icopy.site/learn/pagination/)来公开项目的集合. 这为客户提供了很大的灵活性,同时还允许后端使用不同的分页模型. + +为了公开资源的集合,我们可以使用连接类型. 这将使用默认的分页字段包装数组. 例如,对项目管道的查询可能如下所示: + +``` +query($project_path: ID!) { project(fullPath: $project_path) { pipelines(first: 2) { pageInfo { hasNextPage hasPreviousPage } edges { cursor node { id status } } } } } +``` + +这将返回项目的前两个管道和相关的分页信息,按降序 ID 排序. 返回的数据如下所示: + +``` +{ "data": { "project": { "pipelines": { "pageInfo": { "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "cursor": "Nzc=", "node": { "id": "gid://gitlab/Pipeline/77", "status": "FAILED" } }, { "cursor": "Njc=", "node": { "id": "gid://gitlab/Pipeline/67", "status": "FAILED" } } ] } } } } +``` + +要获取下一页,可以传递最后一个已知元素的光标: + +``` +query($project_path: ID!) { project(fullPath: $project_path) { pipelines(first: 2, after: "Njc=") { pageInfo { hasNextPage hasPreviousPage } edges { cursor node { id status } } } } } +``` + +为了确保获得一致的顺序,我们将在主键上按降序附加顺序. 这通常是`id` ,因此基本上我们将在关系的末尾添加`order(id: :desc)` . 基础表上*必须*有主键. + +#### Shortcut fields[](#shortcut-fields "Permalink") + +有时似乎很容易实现"快捷字段",如果没有传递任何参数,则让解析程序返回集合的第一个. 不鼓励使用这些"快捷字段",因为它们会增加维护开销. 它们需要与规范字段保持同步,并且如果规范字段发生更改,则不建议使用或修改它们. 除非有充分的理由,否则请使用框架提供的功能. + +例如,不要使用`latest_pipeline` ,而应使用`pipelines(last: 1)` . + +### Exposing permissions for a type[](#exposing-permissions-for-a-type "Permalink") + +若要公开当前用户对资源的权限,可以调用以单独的类型传递的`expose_permissions` ,该类型表示资源的权限. + +例如: + +``` +module Types + class MergeRequestType < BaseObject + expose_permissions Types::MergeRequestPermissionsType + end +end +``` + +权限类型继承自`BasePermissionType` ,其中包括一些帮助程序方法,这些方法允许将权限公开为不可为 null 的布尔值: + +``` +class MergeRequestPermissionsType < BasePermissionType + present_using MergeRequestPresenter + + graphql_name 'MergeRequestPermissions' + + abilities :admin_merge_request, :update_merge_request, :create_note + + ability_field :resolve_note, + description: 'Indicates the user can resolve discussions on the merge request' + permission_field :push_to_source_branch, method: :can_push_to_source_branch? +end +``` + +* **`permission_field`** :其作用与`graphql-ruby`的`field`方法相同,但设置默认描述和类型,并使它们不可为空. 通过将它们添加为参数,仍然可以覆盖这些选项. +* **`ability_field`** :公开我们政策中定义的能力. 此行为与`permission_field`相同,并且可以覆盖相同的参数. +* **`abilities`** :允许一次暴露我们政策中定义的几种能力. 这些字段都将是带有默认说明的非空布尔值. + +## Feature flags[](#feature-flags "Permalink") + +开发人员可以通过以下方式将[功能标志](../development/feature_flags/index.html)添加到 GraphQL 字段: + +* 将`feature_flag`属性添加到字段. 当禁用该标志时,这将允许从 GraphQL 模式中*隐藏*该字段. +* 解析字段时切换返回值. + +您可以参考以下准则来决定使用哪种方法: + +* 如果您的字段是实验性的,并且其名称或类型可能会发生变化,请使用`feature_flag`属性. +* 如果您的字段是稳定的,并且即使删除了标志,其定义也不会更改,请改为切换字段的返回值. 请注意, [所有字段](#nullable-fields)无论如何[都应该为空](#nullable-fields) . + +### `feature_flag` property[](#feature_flag-property "Permalink") + +`feature_flag`属性允许您在 GraphQL 模式中切换字段的[可见性](https://graphql-ruby.org/authorization/visibility.html) . 禁用该标志后,将从架构中删除该字段. + +字段后[附有](https://gitlab.com/gitlab-org/gitlab/-/blob/497b556/app/graphql/types/base_field.rb#L44-53)说明,表示该说明位于功能标志的后面. + +**警告:**如果在禁用功能标志时客户端查询该字段,则查询将失败. 在生产中打开或关闭功能的可见性时,请考虑此问题. + +`feature_flag`属性不允许使用[基于 actor](../development/feature_flags/development.html)的[特征门](../development/feature_flags/development.html) . 这意味着功能标记不能仅针对特定的项目,组或用户进行切换,而只能针对所有人进行全局切换. + +Example: + +``` +field :test_field, type: GraphQL::STRING_TYPE, + null: true, + description: 'Some test field', + feature_flag: :my_feature_flag +``` + +### Toggle the value of a field[](#toggle-the-value-of-a-field "Permalink") + +对字段使用特征标记的这种方法是切换字段的返回值. 这可以在解析器中,在类型中甚至在模型方法中完成,具体取决于您的偏好和情况. + +当应用功能标记来切换字段的值时,该字段的`description`必须: + +* 说明该字段的值可以通过功能标记切换. +* 命名功能标志. +* 说明禁用(或启用,如果更合适的话)功能标志时字段将返回的内容. + +Example: + +``` +field :foo, GraphQL::STRING_TYPE, + null: true, + description: 'Some test field. Will always return `null`' \ + 'if `my_feature_flag` feature flag is disabled' + +def foo + object.foo unless Feature.enabled?(:my_feature_flag, object) +end +``` + +## Deprecating fields[](#deprecating-fields "Permalink") + +GitLab 的 GraphQL API 是无版本的,这意味着我们会与 API 的旧版本保持向下兼容性. 除了删除字段,我们还需要*弃用*该字段. 将来,GitLab [可能会删除不推荐使用的字段](https://gitlab.com/gitlab-org/gitlab/-/issues/32292) . + +使用`deprecated`推荐使用的属性不推荐使用字段. 该属性的值是以下各项的`Hash`值: + +* `reason` -弃用的原因. +* `milestone` -已弃用该字段的里程碑. + +Example: + +``` +field :token, GraphQL::STRING_TYPE, null: true, + deprecated: { reason: 'Login via token has been removed', milestone: '10.0' }, + description: 'Token for login' +``` + +最初的`description:`现场应保持,并且*不*应该更新提折旧. + +### Deprecation reason style guide[](#deprecation-reason-style-guide "Permalink") + +如果弃用的原因是该字段被另一个字段替换,则`reason`必须是: + +``` +Use `otherFieldName` +``` + +Example: + +``` +field :designs, ::Types::DesignManagement::DesignCollectionType, null: true, + deprecated: { reason: 'Use `designCollection`', milestone: '10.0' }, + description: 'The designs associated with this issue', +``` + +如果该字段没有被另一个字段替换,则应给出描述性的弃用`reason` . + +## Enums[](#enums "Permalink") + +GitLab GraphQL enums are defined in `app/graphql/types`. When defining new enums, the following rules apply: + +* 值必须为大写. +* 类名必须以字符串`Enum`结尾. +* `graphql_name`不得包含字符串`Enum` . + +例如: + +``` +module Types + class TrafficLightStateEnum < BaseEnum + graphql_name 'TrafficLightState' + description 'State of a traffic light' + + value 'RED', description: 'Drivers must stop' + value 'YELLOW', description: 'Drivers must stop when it is safe to' + value 'GREEN', description: 'Drivers can start or keep driving' + end +end +``` + +If the enum will be used for a class property in Ruby that is not an uppercase string, you can provide a `value:` option that will adapt the uppercase value. + +在以下示例中: + +* GraphQL inputs of `OPENED` will be converted to `'opened'`. +* Ruby 的`'opened'`值将在 GraphQL 响应中转换为`"OPENED"` . + +``` +module Types + class EpicStateEnum < BaseEnum + graphql_name 'EpicState' + description 'State of a GitLab epic' + + value 'OPENED', value: 'opened', description: 'An open Epic' + value 'CLOSED', value: 'closed', description: 'An closed Epic' + end +end +``` + +## Descriptions[](#descriptions "Permalink") + +所有字段和参数都[必须具有描述](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16438) . + +使用`description:`关键字给出字段或自变量的`description:` . 例如: + +``` +field :id, GraphQL::ID_TYPE, description: 'ID of the resource' +``` + +用户可以通过以下方式查看字段和参数的描述: + +* The [GraphiQL explorer](#graphiql). +* The [static GraphQL API reference](../api/graphql/#reference). + +### Description style guide[](#description-style-guide "Permalink") + +为确保一致性,每次添加或更新描述时都应遵循以下规定: + +* 在描述中提及资源的名称. 示例: `'Labels of the issue'` (问题就是资源). +* 尽可能`"{x} of the {y}"` . 示例: `'Title of the issue'` . 不要下手描述`The` . +* `GraphQL::BOOLEAN_TYPE`字段的描述应回答以下问题:"此字段的作用是什么?". 示例: `'Indicates project has a Git repository'` . +* 描述类型为`Types::TimeType`的参数或字段时,请始终包含单词`"timestamp"` . 这使读者知道该属性的格式将是`Time` ,而不仅仅是`Date` . +* 没有`.` 在字符串末尾. + +Example: + +``` +field :id, GraphQL::ID_TYPE, description: 'ID of the Issue' +field :confidential, GraphQL::BOOLEAN_TYPE, description: 'Indicates the issue is confidential' +field :closed_at, Types::TimeType, description: 'Timestamp of when the issue was closed' +``` + +### `copy_field_description` helper[](#copy_field_description-helper "Permalink") + +有时我们希望确保两个描述始终相同. 例如,当两个类型字段描述都表示相同的属性时,它们要与突变参数保持相同. + +除了提供描述之外,我们还可以使用`copy_field_description`帮助器,将其类型和字段名称传递给它,以复制其描述. + +Example: + +``` +argument :title, GraphQL::STRING_TYPE, + required: false, + description: copy_field_description(Types::MergeRequestType, :title) +``` + +## Authorization[](#authorization "Permalink") + +可以使用与 Rails 应用程序中相同的功能将授权应用于类型和字段. + +如果: + +* 当前经过身份验证的用户未通过授权,授权资源将返回`null` . +* 资源是集合的一部分,该集合将被过滤以排除用户授权检查失败的对象. + +另请参见[在变异中授权资源](#authorizing-resources) . + +**提示:**尝试仅先加载允许当前已认证用户使用我们现有的查找器查看的内容,而不依赖于授权来过滤记录. 这样可以最大程度地减少数据库查询和对已加载记录的不必要的授权检查. + +### Type authorization[](#type-authorization "Permalink") + +通过将能力传递给`authorize`方法来`authorize`类型. 通过检查当前经过身份验证的用户是否具有所需的能力,将对所有具有相同类型的字段进行授权. + +例如,以下授权可确保当前经过身份验证的用户只能看到其具有`read_project`能力的项目(只要在使用`Types::ProjectType`的字段中返回该`Types::ProjectType` ): + +``` +module Types + class ProjectType < BaseObject + authorize :read_project + end +end +``` + +您还可以授权多个能力,在这种情况下,所有能力检查都必须通过. + +例如,以下授权可确保当前经过身份验证的用户必须具有`read_project`和`another_ability`能力才能查看项目: + +``` +module Types + class ProjectType < BaseObject + authorize [:read_project, :another_ability] + end +end +``` + +### Field authorization[](#field-authorization "Permalink") + +可以使用`authorize`选项对字段进行授权. + +例如,以下授权可确保当前经过身份验证的用户必须具有`owner_access`功能才能查看项目: + +``` +module Types + class MyType < BaseObject + field :project, Types::ProjectType, null: true, resolver: Resolvers::ProjectResolver, authorize: :owner_access + end +end +``` + +还可以针对多个能力授权字段,在这种情况下,所有能力检查都必须通过. **注意:**这需要显式地将一个块传递给`field` : + +``` +module Types + class MyType < BaseObject + field :project, Types::ProjectType, null: true, resolver: Resolvers::ProjectResolver do + authorize [:owner_access, :another_ability] + end + end +end +``` + +**注意:**如果字段的类型已经[具有特定的授权,](#type-authorization)则无需将该相同的授权添加到字段中. + +### Type and Field authorizations together[](#type-and-field-authorizations-together "Permalink") + +授权是累积性的,因此,在一个字段以及该字段的类型上定义了授权的情况下,当前经过身份验证的用户将需要通过所有能力检查. + +在下面的简化示例中,当前经过身份验证的用户将需要`first_permission`和`second_permission`能力,才能看到问题的作者. + +``` +class UserType + authorize :first_permission +end +``` + +``` +class IssueType + field :author, UserType, authorize: :second_permission +end +``` + +## Resolvers[](#resolvers "Permalink") + +我们使用存储在`app/graphql/resolvers`目录中的*解析器*定义应用程序如何响应. 解析器提供了用于检索相关对象的实际实现逻辑. + +要查找要显示在字段中的对象,我们可以将解析器添加到`app/graphql/resolvers` . + +可以在解析程序中定义参数,这些参数将通过解析程序提供给字段. 公开具有内部 ID( `iid` )的模型时,最好将其与名称空间路径结合使用,作为解析器中的参数,而不是数据库 ID. 否则,请使用[全局唯一 ID](#exposing-global-ids) . + +我们已经有一个`FullPathLoader` ,可以将其包含在其他解析器中,以快速查找将有很多依赖对象的项目和命名空间. + +为了限制执行的查询数量,我们可以使用`BatchLoader` . + +### Correct use of `Resolver#ready?`[](#correct-use-of-resolverready "Permalink") + +解析器有两个公共 API 方法作为框架的一部分: `#ready?(**args)`和`#resolve(**args)` . 我们可以使用`#ready?` 无需调用`#resolve`即可执行设置,验证或提前退货. + +有充分理由使用`#ready?` 包括: + +* 验证互斥参数(请参阅[验证参数](#validating-arguments) ) +* 如果事先知道没有结果,则返回`Relation.none` +* 执行诸如初始化实例变量的设置(尽管为此考虑了延迟初始化的方法) + +[`Resolver#ready?(**args)`](https://graphql-ruby.org/api-doc/1.10.9/GraphQL/Schema/Resolver#ready?-instance_method)应返回`(Boolean, early_return_data)` ,如下所示: + +``` +def ready?(**args) + [false, 'have this instead'] +end +``` + +因此,无论何时调用解析器(主要是在测试中-作为框架抽象,不应将解析器视为可重用的,最好使用查找器),还记得调用`ready?` 方法,并在调用`resolve`之前检查布尔值标志! 在我们的[`GraphQLHelpers`](https://gitlab.com/gitlab-org/gitlab/-/blob/2d395f32d2efbb713f7bc861f96147a2a67e92f2/spec/support/helpers/graphql_helpers.rb#L20-27)可以看到一个示例. + +### Look-Ahead[](#look-ahead "Permalink") + +完整查询是在执行期间预先知道的,这意味着我们可以利用[超前](https://graphql-ruby.org/queries/lookahead.html)查询来优化查询,并知道我们将需要的批处理负载关联. 考虑在解析器中添加前瞻性支持,以避免`N+1`性能问题. + +为了支持常见的前瞻用例(在请求子字段时预加载关联),可以包含[`LooksAhead`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/resolvers/concerns/looks_ahead.rb) . 例如: + +``` +# Assuming a model `MyThing` with attributes `[child_attribute, other_attribute, nested]`, +# where nested has an attribute named `included_attribute`. +class MyThingResolver < BaseResolver + include LooksAhead + + # Rather than defining `resolve(**args)`, we implement: `resolve_with_lookahead(**args)` + def resolve_with_lookahead(**args) + apply_lookahead(MyThingFinder.new(current_user).execute) + end + + # We list things that should always be preloaded: + # For example, if child_attribute is always needed (during authorization + # perhaps), then we can include it here. + def unconditional_includes + [:child_attribute] + end + + # We list things that should be included if a certain field is selected: + def preloads + { + field_one: [:other_attribute], + field_two: [{ nested: [:included_attribute] }] + } + end +end +``` + +需要做的最后一件事是,使用此解析器的每个字段都需要公告提前查询的需求: + +``` + # in ParentType + field :my_things, MyThingType.connection_type, null: true, + extras: [:lookahead], # Necessary + resolver: MyThingResolver, + description: 'My things' +``` + +有关实际使用的示例,请参见[`ResolvesMergeRequests`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/resolvers/concerns/resolves_merge_requests.rb) . + +## Mutations[](#mutations "Permalink") + +变异用于更改任何存储的值或触发动作. 与 GET 请求不应修改数据的方式相同,我们无法在常规 GraphQL 查询中修改数据. 但是我们可以突变. + +要查找突变的对象,需要指定参数. 与[解析程序一样](#resolvers) ,最好使用内部 ID 或全局 ID(而不是数据库 ID)(如果需要). + +### Building Mutations[](#building-mutations "Permalink") + +突变存在于`app/graphql/mutations`理想情况下,突变是根据它们正在突变的资源进行分组的,类似于我们的服务. 他们应该继承`Mutations::BaseMutation` . 突变的结果将返回在突变上定义的字段. + +### Naming conventions[](#naming-conventions "Permalink") + +每个突变都必须定义一个`graphql_name` ,这是 GraphQL 模式中的突变名称. + +Example: + +``` +class UserUpdateMutation < BaseMutation + graphql_name 'UserUpdate' +end +``` + +我们的 GraphQL 突变名称在历史上是不一致的,但是新的突变名称应遵循约定`'{Resource}{Action}'`或`'{Resource}{Action}{Attribute}'` . + +**创建**新资源的变异应使用动词`Create` . + +Example: + +* `CommitCreate` + +**更新**数据的突变应使用: + +* 动词`Update` . +* 特定于域的动词,例如`Set` , `Add`或`Toggle`如果更合适). + +Examples: + +* `EpicTreeReorder` +* `IssueSetWeight` +* `IssueUpdate` +* `TodoMarkDone` + +**删除**数据的突变应使用: + +* 动词`Delete`而不是`Destroy` . +* 特定于域的动词,例如" `Remove`如果更合适). + +Examples: + +* `AwardEmojiRemove` +* `NoteDelete` + +如果您需要有关突变命名的建议,请查看 Slack `#graphql`渠道以获取反馈. + +### Arguments[](#arguments "Permalink") + +突变所需的参数可以定义为字段所需的参数. 这些将被包装为突变的输入类型. 例如,带有 GraphQL 名称`MergeRequestSetWip`的`Mutations::MergeRequests::SetWip` `MergeRequestSetWip`定义了以下参数: + +``` +argument :project_path, GraphQL::ID_TYPE, + required: true, + description: "The project the merge request to mutate is in" + +argument :iid, GraphQL::STRING_TYPE, + required: true, + description: "The iid of the merge request to mutate" + +argument :wip, + GraphQL::BOOLEAN_TYPE, + required: false, + description: <<~DESC Whether or not to set the merge request as a WIP. + If not passed, the value will be toggled. DESC +``` + +这将自动生成一个名为`MergeRequestSetWipInput`的输入类型, `MergeRequestSetWipInput`包含我们指定的 3 个参数和`clientMutationId` . + +然后将这些参数作为关键字参数传递给突变的`resolve`方法. + +### Fields[](#fields "Permalink") + +在最常见的情况下,变异会返回 2 个字段: + +* 正在修改的资源 +* 错误列表,说明无法执行该操作的原因. 如果突变成功,此列表将为空. + +通过从`Mutations::BaseMutation`继承任何新的突变, `errors`字段将自动添加. 还添加了一个`clientMutationId`字段,当在单个请求中执行多个变异时,客户端可以使用它来标识单个变异的结果. + +### The `resolve` method[](#the-resolve-method "Permalink") + +`resolve`方法接收变异的参数作为关键字参数. 从这里,我们可以调用将修改资源的服务. + +然后, `resolve`方法应返回一个哈希,该哈希具有与在突变上定义的字段名称相同的字段名称,包括`errors`数组. 例如, `Mutations::MergeRequests::SetWip`定义了`merge_request`字段: + +``` +field :merge_request, + Types::MergeRequestType, + null: true, + description: "The merge request after mutation" +``` + +这意味着在此突变中从`resolve`返回的哈希应如下所示: + +``` +{ + # The merge request modified, this will be wrapped in the type + # defined on the field + merge_request: merge_request, + # An array of strings if the mutation failed after authorization. + # The `errors_on_object` helper collects `errors.full_messages` + errors: errors_on_object(merge_request) +} +``` + +### Mounting the mutation[](#mounting-the-mutation "Permalink") + +为了使变异可用,必须在存在于`graphql/types/mutation_types`的变异类型上进行定义. `mount_mutation`帮助器方法将基于突变的 GraphQL 名称定义一个字段: + +``` +module Types + class MutationType < BaseObject + include Gitlab::Graphql::MountMutation + + graphql_name "Mutation" + + mount_mutation Mutations::MergeRequests::SetWip + end +end +``` + +将生成一个名为`mergeRequestSetWip`的字段, `Mutations::MergeRequests::SetWip`字段将要解决的`Mutations::MergeRequests::SetWip` . + +### Authorizing resources[](#authorizing-resources "Permalink") + +要授权某个变异内的资源,我们首先要提供所需的变异能力,如下所示: + +``` +module Mutations + module MergeRequests + class SetWip < Base + graphql_name 'MergeRequestSetWip' + + authorize :update_merge_request + end + end +end +``` + +然后,我们可以致电`authorize!` 在`resolve`方法中,传入我们要验证其功能的资源. + +或者,我们可以添加一个`find_object`方法,该方法将在突变上加载对象. 这将允许您使用`authorized_find!` 辅助方法. + +当不允许用户执行该操作或找不到对象时,我们应该引发`Gitlab::Graphql::Errors::ResourceNotAvailable`错误. 哪些将正确呈现给客户端. + +### Errors in mutations[](#errors-in-mutations "Permalink") + +我们鼓励遵循[错误](https://graphql-ruby.org/mutations/mutation_errors)的做法,将其[作为](https://graphql-ruby.org/mutations/mutation_errors)突变的[数据](https://graphql-ruby.org/mutations/mutation_errors) ,从而根据错误的相关者,定义的错误处理者来区分错误. + +关键点: + +* 所有突变响应都有一个`errors`字段. 如果失败,则应填充此文件;如果成功,则应填充该文件. +* 考虑谁需要看到错误: **用户**还是**开发人员** . +* 客户在执行突变时应始终请求`errors`字段. +* 错误可能会以`$root.errors` (顶级错误)或`$root.data.mutationName.errors` (变异错误)的形式报告给用户. 位置取决于这是什么类型的错误以及它所包含的信息. + +考虑一个示例变体`doTheThing` ,该变`doTheThing`返回带有两个字段的响应: `errors: [String]`和`thing: ThingType` . 由于我们正在考虑错误,因此`thing`本身的特定性质与这些示例无关. + +突变响应可以处于三种状态: + +* [Success](#success) +* [Failure (relevant to the user)](#failure-relevant-to-the-user) +* [Failure (irrelevant to the user)](#failure-irrelevant-to-the-user) + +#### Success[](#success "Permalink") + +在快乐的道路上, *可能*会返回错误以及预期的有效负载,但是如果一切成功,则`errors`应该是一个空数组,因为没有任何问题需要通知用户. + +``` +{ + data: { + doTheThing: { + errors: [] // if successful, this array will generally be empty. + thing: { .. } + } + } +} +``` + +#### Failure (relevant to the user)[](#failure-relevant-to-the-user "Permalink") + +发生了影响**用户**的错误. 我们将这些称为*突变错误* . 在这种情况下通常没有`thing`来回报: + +``` +{ + data: { + doTheThing: { + errors: ["you cannot touch the thing"], + thing: null + } + } +} +``` + +例如: + +* Model validation errors: the user may need to change the inputs. +* 权限错误:用户需要知道他们不能执行此操作,他们可能需要请求权限或登录. +* 应用程序状态问题阻止了用户的操作,例如:合并冲突,资源被锁定等等. + +理想情况下,我们应该防止用户走得太远,但是如果这样做了,则需要告诉他们出了什么问题,以便他们了解失败的原因以及可以实现其意图的方法,即使那很简单重试请求. + +可以与变异数据一起返回*可恢复的*错误. 例如,如果用户上载 10 个文件,而其中 3 个失败,其余文件成功,则可以将失败的错误以及有关成功的信息与用户一起使用. + +#### Failure (irrelevant to the user)[](#failure-irrelevant-to-the-user "Permalink") + +可以在*顶层*返回一个或多个*不可恢复的*错误. 这些是**用户**几乎无法控制的事情,主要应该是**开发人员**需要了解的系统或编程问题. 在这种情况下,没有`data` : + +``` +{ + errors: [ + {"message": "argument error: expected an integer, got null"}, + ] +} +``` + +这是在突变过程中引发错误的结果. 在我们的实现中,参数错误和验证错误的消息将返回给客户端,所有其他`StandardError`实例将被捕获,记录并呈现给客户端,并将消息设置为`"Internal server error"` . 有关详细信息,请参见[`GraphqlController`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/controllers/graphql_controller.rb) . + +这些代表编程错误,例如: + +* A GraphQL syntax error, where an `Int` was passed instead of a `String`, or a required argument was not present. +* 我们架构中的错误,例如无法为不可为空的字段提供值. +* 系统错误:例如,Git 存储异常或数据库不可用. + +用户在常规使用中不应导致此类错误. 此类错误应视为内部错误,并且不向用户详细显示. + +我们需要在突变失败时通知用户,但是我们不必告诉他们原因,因为他们不可能造成突变,尽管我们可以提供重试突变的方法,但他们无能为力. + +#### Categorizing errors[](#categorizing-errors "Permalink") + +当我们编写突变时,我们需要意识到错误状态属于这两个类别中的哪一个(并与前端开发人员进行沟通以验证我们的假设). 这意味着将*用户*的需求与*客户*的需求区分开. + +> *除非用户需要了解错误,否则切勿捕获错误.* + +如果用户确实需要了解它,请与前端开发人员进行交流,以确保我们传回的错误信息有用. + +另请参见[前端 GraphQL 指南](../development/fe_guide/graphql.html#handling-errors) . + +### Aliasing and deprecating mutations[](#aliasing-and-deprecating-mutations "Permalink") + +`#mount_aliased_mutation`帮助器允许我们将突变别名作为`MutationType`另一个名称. + +例如,将名为`FooMutation`的突变别名为`BarMutation` : + +``` +mount_aliased_mutation 'BarMutation', Mutations::FooMutation +``` + +结合[`deprecated`](#deprecating-fields)参数,这使我们可以重命名突变并继续支持旧名称. + +Example: + +``` +mount_aliased_mutation 'UpdateFoo', + Mutations::Foo::Update, + deprecated: { reason: 'Use fooUpdate', milestone: '13.2' } +``` + +不赞成使用的突变应添加到`Types::DeprecatedMutations`并在`Types::MutationType`的单元测试中进行测试. 合并请求[!34798](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34798)可以称为此示例,包括测试已弃用的别名突变的方法. + +## Validating arguments[](#validating-arguments "Permalink") + +要验证单个参数,请照常使用[`prepare`选项](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/fields/arguments.md) . + +有时,变异或解析器可以接受许多可选参数,但是我们仍然要验证是否至少提供了一个可选参数. 在这种情况下,请考虑使用`#ready?` 突变或解析器中提供验证的方法. `#ready?` 在`#resolve`方法中完成任何工作之前,将调用方法. + +Example: + +``` +def ready?(**args) + if args.values_at(:body, :position).compact.blank? + raise Gitlab::Graphql::Errors::ArgumentError, + 'body or position arguments are required' + end + + # Always remember to call `#super` + super +end +``` + +如果将来将此[RFC](https://github.com/graphql/graphql-spec/blob/master/rfcs/InputUnion.md)合并,则可以使用`InputUnions`完成. + +## GitLab’s custom scalars[](#gitlabs-custom-scalars "Permalink") + +### `Types::TimeType`[](#typestimetype "Permalink") + +[`Types::TimeType`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/graphql/types/time_type.rb)必须用作处理 Ruby `Time`和`DateTime`对象的所有字段和参数的类型. + +该类型是[一个自定义标量](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/scalars.md#custom-scalars) : + +* 当用作 GraphQL 字段的类型时,将 Ruby 的`Time`和`DateTime`对象转换为标准化的 ISO-8601 格式的字符串. +* 当用作 GraphQL 参数的类型时,将 ISO-8601 格式的时间字符串转换为 Ruby `Time`对象. + +这使我们的 GraphQL API 具有标准化的方式来表示时间并处理时间输入. + +Example: + +``` +field :created_at, Types::TimeType, null: true, description: 'Timestamp of when the issue was created' +``` + +## Testing[](#testing "Permalink") + +在`spec/requests/api/graphql`实时进行针对 graphql 查询或突变的*全栈*测试. + +添加查询时,可以使用`a working graphql query`共享示例来测试该查询是否呈现有效结果. + +使用`GraphqlHelpers#all_graphql_fields_for` -helper,可以构造一个包含所有可用字段的查询. 这使得添加测试渲染所有可能的查询字段变得容易. + +为了测试 GraphQL 突变请求, `GraphqlHelpers`提供了 2 个助手: `graphql_mutation` ,它使用突变的名称;以及带有该突变输入的哈希. 这将返回带有变异查询和预备变量的结构. + +然后可以将此结构传递给`post_graphql_mutation`帮助器,该帮助器将使用正确的参数发布请求,就像 GraphQL 客户端所做的那样. + +要访问突变的响应,可以使用`graphql_mutation_response`帮助器. + +使用这些帮助器,我们可以建立如下规格: + +``` +let(:mutation) do + graphql_mutation( + :merge_request_set_wip, + project_path: 'gitlab-org/gitlab-foss', + iid: '1', + wip: true + ) +end + +it 'returns a successful response' do + post_graphql_mutation(mutation, current_user: user) + + expect(response).to have_gitlab_http_status(:success) + expect(graphql_mutation_response(:merge_request_set_wip)['errors']).to be_empty +end +``` + +## Notes about Query flow and GraphQL infrastructure[](#notes-about-query-flow-and-graphql-infrastructure "Permalink") + +可以在`lib/gitlab/graphql`找到 GitLab 的 GraphQL 基础架构. + +[检测](https://graphql-ruby.org/queries/instrumentation.html)是环绕正在执行的查询的功能. 它被实现为使用`Instrumentation`类的模块. + +Example: `Present` + +``` +module Gitlab + module Graphql + module Present + #... some code above... + + def self.use(schema_definition) + schema_definition.instrument(:field, ::Gitlab::Graphql::Present::Instrumentation.new) + end + end + end +end +``` + +[查询分析器](https://graphql-ruby.org/queries/ast_analysis.html#analyzer-api)包含一系列回调,以在执行查询之前对其进行验证. 每个字段都可以通过分析仪,最终值也可供您使用. + +[多重查询](https://graphql-ruby.org/queries/multiplex.html)使多个查询可以在单个请求中发送. 这减少了发送到服务器的请求数量. (GraphQL Ruby 提供了自定义的 Multiplex 查询分析器和 Multiplex 工具). + +### Query limits[](#query-limits "Permalink") + +查询和变异受到深度,复杂性和递归的限制,以保护服务器资源免受过度野心或恶意查询的侵害. 这些值可以设置为默认值,并根据需要在特定查询中覆盖. 也可以为每个对象设置复杂度值,并根据返回的对象数来评估最终查询的复杂度. 这对于昂贵的对象(例如需要 Gitaly 调用)很有用. + +例如,解析器中的条件复杂度方法: + +``` +def self.resolver_complexity(args, child_complexity:) + complexity = super + complexity += 2 if args[:labelName] + + complexity +end +``` + +有关复杂性的更多信息: [GraphQL Ruby 文档](https://graphql-ruby.org/queries/complexity_and_depth.html) . + +## Documentation and Schema[](#documentation-and-schema "Permalink") + +我们的模式位于`app/graphql/gitlab_schema.rb` . 有关详细信息,请参见[架构参考](../api/graphql/reference/index.html) . + +模式更改时,需要更新此生成的 GraphQL 文档. 有关生成 GraphQL 文档和架构文件的信息,请参阅[更新架构文档](rake_tasks.html#update-graphql-documentation-and-schema-definitions) . \ No newline at end of file diff --git a/_book/docs/613.md b/_book/docs/613.md new file mode 100644 index 0000000000000000000000000000000000000000..00e7d9ea5f6285734d118939a08625035824e3f0 --- /dev/null +++ b/_book/docs/613.md @@ -0,0 +1,223 @@ +# Guidelines for shell commands in the GitLab codebase + +> 原文:[https://docs.gitlab.com/ee/development/shell_commands.html](https://docs.gitlab.com/ee/development/shell_commands.html) + +* [References](#references) +* [Use File and FileUtils instead of shell commands](#use-file-and-fileutils-instead-of-shell-commands) +* [Always use the configurable Git binary path for Git commands](#always-use-the-configurable-git-binary-path-for-git-commands) +* [Bypass the shell by splitting commands into separate tokens](#bypass-the-shell-by-splitting-commands-into-separate-tokens) +* [Separate options from arguments with –](#separate-options-from-arguments-with---) +* [Do not use the backticks](#do-not-use-the-backticks) +* [Avoid user input at the start of path strings](#avoid-user-input-at-the-start-of-path-strings) +* [Guard against path traversal](#guard-against-path-traversal) +* [Properly anchor regular expressions to the start and end of strings](#properly-anchor-regular-expressions-to-the-start-and-end-of-strings) + +# Guidelines for shell commands in the GitLab codebase[](#guidelines-for-shell-commands-in-the-gitlab-codebase "Permalink") + +本文档包含使用 GitLab 代码库中的进程和文件的准则. 这些准则旨在使您的代码更加可靠*和*安全. + +## References[](#references "Permalink") + +* [Google Ruby Security Reviewer’s Guide](https://code.google.com/archive/p/ruby-security/wikis/Guide.wiki) +* [OWASP Command Injection](https://wiki.owasp.org/index.php/Command_Injection) +* [Ruby on Rails Security Guide Command Line Injection](https://guides.rubyonrails.org/security.html#command-line-injection) + +## Use File and FileUtils instead of shell commands[](#use-file-and-fileutils-instead-of-shell-commands "Permalink") + +有时,当还有 Ruby API 可以通过外壳调用基本的 Unix 命令时. 使用 Ruby API(如果存在). [http://www.ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html#module-FileUtils-label-Module+Functions](http://www.ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html#module-FileUtils-label-Module+Functions) + +``` +# Wrong +system "mkdir -p tmp/special/directory" +# Better (separate tokens) +system *%W(mkdir -p tmp/special/directory) +# Best (do not use a shell command) +FileUtils.mkdir_p "tmp/special/directory" + +# Wrong +contents = `cat #{filename}` +# Correct +contents = File.read(filename) + +# Sometimes a shell command is just the best solution. The example below has no +# user input, and is hard to implement correctly in Ruby: delete all files and +# directories older than 120 minutes under /some/path, but not /some/path +# itself. +Gitlab::Popen.popen(%W(find /some/path -not -path /some/path -mmin +120 -delete)) +``` + +这种编码风格可能阻止了 CVE-2013-4490. + +## Always use the configurable Git binary path for Git commands[](#always-use-the-configurable-git-binary-path-for-git-commands "Permalink") + +``` +# Wrong +system(*%W(git branch -d -- #{branch_name})) + +# Correct +system(*%W(#{Gitlab.config.git.bin_path} branch -d -- #{branch_name})) +``` + +## Bypass the shell by splitting commands into separate tokens[](#bypass-the-shell-by-splitting-commands-into-separate-tokens "Permalink") + +当我们将 shell 命令作为单个字符串传递给 Ruby 时,Ruby 将让`/bin/sh`评估整个字符串. 本质上,我们要求外壳程序评估单行脚本. 这会造成外壳注入攻击的风险. 最好自己将 shell 命令拆分为令牌. 有时,我们使用外壳程序的脚本功能来更改工作目录或设置环境变量. 所有这些都可以直接从 Ruby 安全地实现 + +``` +# Wrong +system "cd /home/git/gitlab && bundle exec rake db:#{something} RAILS_ENV=production" +# Correct +system({'RAILS_ENV' => 'production'}, *%W(bundle exec rake db:#{something}), chdir: '/home/git/gitlab') + +# Wrong +system "touch #{myfile}" +# Better +system "touch", myfile +# Best (do not run a shell command at all) +FileUtils.touch myfile +``` + +这种编码风格可能阻止了 CVE-2013-4546. + +## Separate options from arguments with –[](#separate-options-from-arguments-with--- "Permalink") + +使用`--`使系统命令的参数解析器可以清楚了解选项和参数之间的区别. 许多但并非所有 Unix 命令都支持此功能. + +要了解什么`--`不,请考虑以下问题. + +``` +# Example +$ echo hello > -l +$ cat -l + +cat: illegal option -- l +usage: cat [-benstuv] [file ...] +``` + +在上面的示例中, `cat`的参数解析器假定`-l`是一个选项. 在上面的例子中的解决方案是明确告诉`cat`那`-l`实在是一个论点,不是一种选择. 许多 Unix 命令行工具都遵循用`--`分隔选项和参数的约定. + +``` +# Example (continued) +$ cat -- -l + +hello +``` + +在 GitLab 代码库中,我们*总是*通过对支持它的命令使用`--`来避免选项/参数的歧义. + +``` +# Wrong +system(*%W(#{Gitlab.config.git.bin_path} branch -d #{branch_name})) +# Correct +system(*%W(#{Gitlab.config.git.bin_path} branch -d -- #{branch_name})) +``` + +这种编码风格可能阻止了 CVE-2013-4582. + +## Do not use the backticks[](#do-not-use-the-backticks "Permalink") + +用反引号捕获 shell 命令的输出很不错,但是您不得不将命令作为一个字符串传递给 shell. 上面我们解释了这是不安全的. 在主要的 GitLab 代码库中,解决方案是改用`Gitlab::Popen.popen` . + +``` +# Wrong +logs = `cd #{repo_dir} && #{Gitlab.config.git.bin_path} log` +# Correct +logs, exit_status = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} log), repo_dir) + +# Wrong +user = `whoami` +# Correct +user, exit_status = Gitlab::Popen.popen(%W(whoami)) +``` + +在其他存储库(如 GitLab Shell)中,您也可以使用`IO.popen` . + +``` +# Safe IO.popen example +logs = IO.popen(%W(#{Gitlab.config.git.bin_path} log), chdir: repo_dir) { |p| p.read } +``` + +请注意,与`Gitlab::Popen.popen`不同, `IO.popen`不会捕获标准错误. + +## Avoid user input at the start of path strings[](#avoid-user-input-at-the-start-of-path-strings "Permalink") + +可以使用各种在 Ruby 中打开和读取文件的方法来读取进程的标准输出而不是文件. 以下两个命令大致相同: + +``` +`touch /tmp/pawned-by-backticks` +File.read('|touch /tmp/pawned-by-file-read') +``` + +关键是打开一个以" `|` "开头的"文件" `|` . 受影响的方法包括 Kernel#open,File :: read,File :: open,IO :: open 和 IO :: read. + +您可以通过确保攻击者无法控制要打开的文件名字符串的开头来防止"打开"和"读取"这种行为. 例如,下面的内容足以防止意外地使用`|`启动 shell 命令`|` : + +``` +# we assume repo_path is not controlled by the attacker (user) +path = File.join(repo_path, user_input) +# path cannot start with '|' now. +File.read(path) +``` + +如果必须使用用户输入的相对路径,请在路径前添加`./` . + +前缀用户提供的路径还提供了针对以`-`开头的路径的额外保护(请参阅上面有关使用`--`的讨论). + +## Guard against path traversal[](#guard-against-path-traversal "Permalink") + +路径遍历是一种安全措施,程序(GitLab)试图限制用户对磁盘上某个目录的访问,但用户设法利用`../`路径符号来打开该目录之外的文件. + +``` +# Suppose the user gave us a path and they are trying to trick us +user_input = '../other-repo.git/other-file' + +# We look up the repo path somewhere +repo_path = 'repositories/user-repo.git' + +# The intention of the code below is to open a file under repo_path, but +# because the user used '..' they can 'break out' into +# 'repositories/other-repo.git' +full_path = File.join(repo_path, user_input) +File.open(full_path) do # Oops! +``` + +防止这种情况发生的好方法是根据 Ruby 的`File.absolute_path`将完整路径与其"绝对路径"进行`File.absolute_path` . + +``` +full_path = File.join(repo_path, user_input) +if full_path != File.absolute_path(full_path) + raise "Invalid path: #{full_path.inspect}" +end + +File.open(full_path) do # Etc. +``` + +这样的检查可以避免 CVE-2013-4583. + +## Properly anchor regular expressions to the start and end of strings[](#properly-anchor-regular-expressions-to-the-start-and-end-of-strings "Permalink") + +当使用正则表达式来验证作为参数传递给 shell 命令的用户输入时,请确保使用`\A`和`\z`定位符来指定字符串的开头和结尾,而不是`^`和`$` ,或者不要使用定位符所有. + +如果您不这样做,攻击者可能会使用它来执行具有潜在有害影响的命令. + +例如,当如下所示验证项目的`import_url`时,用户可以诱使 GitLab 从本地文件系统上的 Git 存储`import_url` . + +``` +validates :import_url, format: { with: URI.regexp(%w(ssh git http https)) } +# URI.regexp(%w(ssh git http https)) roughly evaluates to /(ssh|git|http|https):(something_that_looks_like_a_url)/ +``` + +假设用户提交以下内容作为其导入 URL: + +``` +file://git:/tmp/lol +``` + +由于使用的正则表达式中没有锚,因此值中的`git:/tmp/lol`将匹配,并且验证将通过. + +导入时,GitLab 将执行以下命令,将`import_url`作为参数传递: + +``` +git clone file://git:/tmp/lol +``` + +Git 只会忽略`git:`部分,将路径解释为`file:///tmp/lol` ,然后将存储库导入到新项目中. 此操作可能使攻击者可以访问系统中的任何存储库(无论是否私有). \ No newline at end of file diff --git a/_book/docs/614.md b/_book/docs/614.md new file mode 100644 index 0000000000000000000000000000000000000000..b98b72d86fe38bdc1f523f2e2478cb89c6570bf7 --- /dev/null +++ b/_book/docs/614.md @@ -0,0 +1,64 @@ +# HTML style guide + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/style/html.html](https://docs.gitlab.com/ee/development/fe_guide/style/html.html) + +* [Buttons](#buttons) + * [Button type](#button-type) + * [Button role](#button-role) +* [Links](#links) + * [Blank target](#blank-target) + * [Fake links](#fake-links) + +# HTML style guide[](#html-style-guide "Permalink") + +## Buttons[](#buttons "Permalink") + +### Button type[](#button-type "Permalink") + +按钮标记需要根据[W3C HTML 规范](https://www.w3.org/TR/2011/WD-html5-20110525/the-button-element.html#dom-button-type)的`type`属性. + +``` +// bad +<button></button> + +// good +<button type="button"></button> +``` + +### Button role[](#button-role "Permalink") + +如果 HTML 元素具有`onClick`处理程序但不是按钮,则应具有`role="button"` . 这[更容易访问](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/Accessibility/ARIA/Roles/button_role) . + +``` +// bad +<div onClick="doSomething"></div> + +// good +<div role="button" onClick="doSomething"></div> +``` + +## Links[](#links "Permalink") + +### Blank target[](#blank-target "Permalink") + +每当您的链接在新窗口中打开时,即使用`target="_blank"` ,请使用`rel="noopener noreferrer"` `target="_blank"` . 这可以防止[JitBit 记录](https://www.jitbit.com/alexblog/256-targetblank---the-most-underestimated-vulnerability-ever/)的安全漏洞. + +``` +// bad +<a href="url" target="_blank"></a> + +// good +<a href="url" target="_blank" rel="noopener noreferrer"></a> +``` + +### Fake links[](#fake-links "Permalink") + +**不要使用虚假链接.** 如果链接仅调用 JavaScript click 事件处理程序,则使用按钮标签,这更具语义. + +``` +// bad +<a class="js-do-something" href="#"></a> + +// good +<button class="js-do-something" type="button"></button> +``` \ No newline at end of file diff --git a/_book/docs/615.md b/_book/docs/615.md new file mode 100644 index 0000000000000000000000000000000000000000..a84609801d0771b586df38c800df280e058b950f --- /dev/null +++ b/_book/docs/615.md @@ -0,0 +1,294 @@ +# JavaScript style guide + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/style/javascript.html](https://docs.gitlab.com/ee/development/fe_guide/style/javascript.html) + +* [Avoid forEach](#avoid-foreach) +* [Limit number of parameters](#limit-number-of-parameters) +* [Avoid classes to handle DOM events](#avoid-classes-to-handle-dom-events) +* [Pass element container to constructor](#pass-element-container-to-constructor) +* [Use ParseInt](#use-parseint) +* [CSS Selectors - Use `js-` prefix](#css-selectors---use-js--prefix) +* [ES Module Syntax](#es-module-syntax) +* [Absolute vs relative paths for modules](#absolute-vs-relative-paths-for-modules) +* [Do not use `DOMContentLoaded` in non-page modules](#do-not-use-domcontentloaded-in-non-page-modules) +* [Avoid XSS](#avoid-xss) +* [Avoid single-line conditional statements](#avoid-single-line-conditional-statements) +* [ESLint](#eslint) +* [IIFEs](#iifes) +* [Global namespace](#global-namespace) +* [Side effects](#side-effects) + * [Top-level side effects](#top-level-side-effects) + * [Avoid side effects in constructors](#avoid-side-effects-in-constructors) +* [Pure Functions and Data Mutation](#pure-functions-and-data-mutation) + +# JavaScript style guide[](#javascript-style-guide "Permalink") + +我们使用[Airbnb 的 JavaScript 样式指南](https://github.com/airbnb/javascript)及其附带的 linter 来管理我们的大多数 JavaScript 样式指南. + +除了由 Airbnb 设置的样式准则之外,我们还列出了以下一些特定规则. + +> **提示:**您可以通过运行`yarn eslint`在本地运行`yarn eslint` + +## Avoid forEach[](#avoid-foreach "Permalink") + +变异数据时避免 forEach. 更改数据时,请使用`map` , `reduce`或`filter`而不是`forEach` . 这样可以最大程度地减少功能上的变化,从而与[Airbnb 的风格指南](https://github.com/airbnb/javascript#testing--for-real)保持一致. + +``` +// bad +users.forEach((user, index) => { + user.id = index; +}); + +// good +const usersWithId = users.map((user, index) => { + return Object.assign({}, user, { id: index }); +}); +``` + +## Limit number of parameters[](#limit-number-of-parameters "Permalink") + +如果您的函数或方法具有三个以上的参数,请改为使用对象作为参数. + +``` +// bad +function a(p1, p2, p3) { + // ... +}; + +// good +function a(p) { + // ... +}; +``` + +## Avoid classes to handle DOM events[](#avoid-classes-to-handle-dom-events "Permalink") + +如果该类的唯一目的是绑定 DOM 事件并处理回调,则最好使用函数. + +``` +// bad +class myClass { + constructor(config) { + this.config = config; + } + + init() { + document.addEventListener('click', () => {}); + } +} + +// good + +const myFunction = () => { + document.addEventListener('click', () => { + // handle callback here + }); +} +``` + +## Pass element container to constructor[](#pass-element-container-to-constructor "Permalink") + +当您的类操作 DOM 时,将元素容器作为参数接收. 这样更易于维护和执行. + +``` +// bad +class a { + constructor() { + document.querySelector('.b'); + } +} + +// good +class a { + constructor(options) { + options.container.querySelector('.b'); + } +} +``` + +## Use ParseInt[](#use-parseint "Permalink") + +将数字字符串转换为数字时,请使用`ParseInt` . + +``` +// bad +Number('10') + +// good +parseInt('10', 10); +``` + +## CSS Selectors - Use `js-` prefix[](#css-selectors---use-js--prefix "Permalink") + +如果仅在 JavaScript 中使用 CSS 类作为对元素的引用,则使用`js-`作为类名的前缀. + +``` +// bad +<button class="add-user"></button> + +// good +<button class="js-add-user"></button> +``` + +## ES Module Syntax[](#es-module-syntax "Permalink") + +使用 ES 模块语法导入模块: + +``` +// bad +const SomeClass = require('some_class'); + +// good +import SomeClass from 'some_class'; + +// bad +module.exports = SomeClass; + +// good +export default SomeClass; +``` + +*注意:*我们仍然在`scripts/`和`config/`文件中使用`require` . + +## Absolute vs relative paths for modules[](#absolute-vs-relative-paths-for-modules "Permalink") + +如果要导入的模块少于两个级别,请使用相对路径. + +``` +// bad +import GitLabStyleGuide from '~/guides/GitLabStyleGuide'; + +// good +import GitLabStyleGuide from '../GitLabStyleGuide'; +``` + +如果要导入的模块为两个或两个以上级别,请改用绝对路径: + +``` +// bad +import GitLabStyleGuide from '../../../guides/GitLabStyleGuide'; + +// good +import GitLabStyleGuide from '~/GitLabStyleGuide'; +``` + +Additionally, **不添加到全局名称空间**. + +## Do not use `DOMContentLoaded` in non-page modules[](#do-not-use-domcontentloaded-in-non-page-modules "Permalink") + +导入的模块每次加载时都应发挥相同的作用. `DOMContentLoaded`事件仅允许在`/pages/*`目录中加载的模块上使用,因为这些事件是通过 webpack 动态加载的. + +## Avoid XSS[](#avoid-xss "Permalink") + +不要使用`innerHTML` , `append()`或`html()`设置内容. 它打开了太多的漏洞. + +## Avoid single-line conditional statements[](#avoid-single-line-conditional-statements "Permalink") + +缩进在扫描代码时很重要,因为它可以快速指示分支,循环和返回点的存在. 这可以帮助快速了解控制流程. + +``` +// bad +if (isThingNull) return ''; + +if (isThingNull) + return ''; + +// good +if (isThingNull) { + return ''; +} +``` + +## ESLint[](#eslint "Permalink") + +ESLint 行为可以在我们的[工具指南中](../tooling.html)找到. + +## IIFEs[](#iifes "Permalink") + +避免使用 IIFE(立即调用函数表达式). 尽管我们有很多将其内容包装在 IIFE 中的文件示例,但是从 Sprockets 过渡到 Webpack 之后,这不再是必需的. 重构遗留代码时,请不要再使用它们,并随时将其删除. + +## Global namespace[](#global-namespace "Permalink") + +避免添加到全局名称空间. + +``` +// bad +window.MyClass = class { /* ... */ }; + +// good +export default class MyClass { /* ... */ } +``` + +## Side effects[](#side-effects "Permalink") + +### Top-level side effects[](#top-level-side-effects "Permalink") + +在任何包含`export`脚本中都禁止顶级副作用: + +``` +// bad +export default class MyClass { /* ... */ } + +document.addEventListener("DOMContentLoaded", function(event) { + new MyClass(); +} +``` + +### Avoid side effects in constructors[](#avoid-side-effects-in-constructors "Permalink") + +避免在`constructor`进行异步调用,API 请求或 DOM 操作. 而是将它们移动到单独的函数中. 这将使测试更易于编写,并且避免违反[单一职责原则](https://en.wikipedia.org/wiki/Single_responsibility_principle) . + +``` +// bad +class myClass { + constructor(config) { + this.config = config; + axios.get(this.config.endpoint) + } +} + +// good +class myClass { + constructor(config) { + this.config = config; + } + + makeRequest() { + axios.get(this.config.endpoint) + } +} +const instance = new myClass(); +instance.makeRequest(); +``` + +## Pure Functions and Data Mutation[](#pure-functions-and-data-mutation "Permalink") + +努力编写许多小的纯函数,并尽量减少发生突变的地方 + +``` + // bad + const values = {foo: 1}; + + function impureFunction(items) { + const bar = 1; + + items.foo = items.a * bar + 2; + + return items.a; + } + + const c = impureFunction(values); + + // good + var values = {foo: 1}; + + function pureFunction (foo) { + var bar = 1; + + foo = foo * bar + 2; + + return foo; + } + + var c = pureFunction(values.foo); +``` \ No newline at end of file diff --git a/_book/docs/616.md b/_book/docs/616.md new file mode 100644 index 0000000000000000000000000000000000000000..0fb587b4006c16998a56f4cec1f6e7de318d0796 --- /dev/null +++ b/_book/docs/616.md @@ -0,0 +1,769 @@ +# Migration Style Guide + +> 原文:[https://docs.gitlab.com/ee/development/migration_style_guide.html](https://docs.gitlab.com/ee/development/migration_style_guide.html) + +* [Schema Changes](#schema-changes) +* [What Requires Downtime?](#what-requires-downtime) +* [Downtime Tagging](#downtime-tagging) +* [Reversibility](#reversibility) +* [Atomicity](#atomicity) +* [Heavy operations in a single transaction](#heavy-operations-in-a-single-transaction) +* [Retry mechanism when acquiring database locks](#retry-mechanism-when-acquiring-database-locks) + * [Examples](#examples) + * [When to use the helper method](#when-to-use-the-helper-method) + * [How the helper method works](#how-the-helper-method-works) +* [Multi-Threading](#multi-threading) +* [Removing indexes](#removing-indexes) +* [Adding indexes](#adding-indexes) +* [Adding foreign-key constraints](#adding-foreign-key-constraints) +* [`NOT NULL` constraints](#not-null-constraints) +* [Adding Columns With Default Values](#adding-columns-with-default-values) +* [Changing the column default](#changing-the-column-default) +* [Updating an existing column](#updating-an-existing-column) +* [Dropping a database table](#dropping-a-database-table) +* [Integer column type](#integer-column-type) +* [Strings and the Text data type](#strings-and-the-text-data-type) +* [Timestamp column type](#timestamp-column-type) +* [Storing JSON in database](#storing-json-in-database) +* [Testing](#testing) +* [Data migration](#data-migration) + * [Renaming reserved paths](#renaming-reserved-paths) + +# Migration Style Guide[](#migration-style-guide "Permalink") + +在为 GitLab 编写迁移时,必须考虑到这些迁移将由成千上万个各种规模的组织来运行,其中一些组织的数据库中包含多年的数据. + +此外,对于大多数组织来说,必须使服务器脱机以进行较小或较大的升级是一大负担. 因此,重要的是要仔细编写迁移文件,可以在线进行迁移,并遵守下面的样式指南. + +迁移**不准**要求 GitLab 设施采取离线,除非*绝对必要的* . + +如果需要停机,则必须通过以下方式批准迁移: + +1. 工程副总裁 +2. 后端维护者 +3. 数据库维护者 + +可以在[https://about.gitlab.com/company/team/中](https://about.gitlab.com/company/team/)找到持有这些头衔的人员的最新列表. + +When writing your migrations, also consider that databases might have stale data or inconsistencies and guard for that. Try to make as few assumptions as possible about the state of the database. + +请不要依赖特定于 GitLab 的代码,因为它可能会在将来的版本中更改. 如果需要,将 GitLab 代码复制粘贴到迁移中以使其向前兼容. + +对于 GitLab.com,请考虑到在[部署 Canary](https://about.gitlab.com/handbook/engineering/infrastructure/library/canary/#configuration-and-deployment)之前运行常规迁移(在`db/migrate` ),在完成生产部署后运行部署后的迁移( `db/post_migrate` ). + +## Schema Changes[](#schema-changes "Permalink") + +Changes to the schema should be committed to `db/structure.sql`. This file is automatically generated by Rails, so you normally should not edit this file by hand. If your migration is adding a column to a table, that column will be added at the bottom. Please do not reorder columns manually for existing tables as this will cause confusing to other people using `db/structure.sql` generated by Rails. + +当您的 GDK 中的本地数据库与`master`数据库中的模式不同时,可能很难将模式更改完全提交给 Git. 在这种情况下,您可以使用`scripts/regenerate-schema`脚本为要添加的迁移重新生成干净的`db/structure.sql` . 该脚本将应用在`db/migrate`或`db/post_migrate`找到的所有迁移,因此,如果您不想将任何迁移提交到架构,请重命名或删除它们. 如果您的分支不是以`master`为目标,则可以设置`TARGET`环境变量. + +``` +# Regenerate schema against `master` +scripts/regenerate-schema + +# Regenerate schema against `12-9-stable-ee` +TARGET=12-9-stable-ee scripts/regenerate-schema +``` + +## What Requires Downtime?[](#what-requires-downtime "Permalink") + +文档["什么需要停机?"](what_requires_downtime.html) 指定各种数据库操作,例如 + +* [dropping and renaming columns](what_requires_downtime.html#dropping-columns) +* [changing column constraints and types](what_requires_downtime.html#changing-column-constraints) +* [adding and dropping indexes, tables, and foreign keys](what_requires_downtime.html#adding-indexes) + +以及他们是否需要停机,以及如何尽可能地进行停机. + +## Downtime Tagging[](#downtime-tagging "Permalink") + +每个迁移都必须指定是否需要停机,并且如果需要停机,还必须指定原因. 这是即使在迁移的 99%,不需要停机,因为这使得它更容易地发现, *确实*需要停机迁移所需. + +要标记迁移,请在迁移类的主体中添加以下两个常量: + +* `DOWNTIME` :一个布尔值,当设置为`true`指示迁移需要停机时间. +* `DOWNTIME_REASON` :一个字符串,其中包含需要停机的迁移原因. 当`DOWNTIME`设置为`true`时, **必须**设置此常数. + +例如: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + DOWNTIME = true + DOWNTIME_REASON = 'This migration requires downtime because ...' + + def change + ... + end +end +``` + +如果迁移类中缺少`DOWNTIME`常量,则会出现错误(即 CI 将失败). + +## Reversibility[](#reversibility "Permalink") + +您的迁移**必须是**可逆的. 这非常重要,因为在出​​现漏洞或错误的情况下应该可以降级. + +在迁移中,添加一条注释,描述如何测试迁移的可逆性. + +某些迁移无法撤消. 例如,某些数据迁移无法撤消,因为在迁移之前,我们丢失了有关数据库状态的信息. 您仍然应该创建一个带注释的`down`方法,解释为什么不能撤消`up`方法执行的更改,以便即使撤消迁移期间执行的更改也可以撤消迁移本身: + +``` +def down + # no-op + + # comment explaining why changes performed by `up` cannot be reversed. +end +``` + +## Atomicity[](#atomicity "Permalink") + +默认情况下,迁移是单个事务. 即,在迁移开始时打开一个事务,并在处理完所有步骤后提交. + +在单个事务中运行迁移可确保如果其中一个步骤失败,则将不会执行任何步骤,从而使数据库保持有效状态. 因此,要么: + +* 将所有迁移都放在一个单事务迁移中. +* 如有必要,将大多数操作放入一个迁移中,并为无法在单个事务中完成的步骤创建一个单独的迁移. + +例如,如果创建一个空表并需要为其建立索引,则建议使用常规的单事务迁移和默认的 rails schema 语句: [`add_index`](https://api.rubyonrails.org/v5.2/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_index) . 这是一个阻塞操作,但不会引起问题,因为该表尚未使用,因此它还没有任何记录. + +## Heavy operations in a single transaction[](#heavy-operations-in-a-single-transaction "Permalink") + +使用单事务迁移时,事务将在迁移期间保持数据库连接,因此您必须确保迁移中的操作不会花费太多时间:通常,在迁移中执行的查询需要在 GitLab.com 上舒适地放置`15s` . + +如果您需要插入,更新或删除大量数据,请执行以下操作: + +* 必须使用`disable_ddl_transaction!`禁用单个事务`disable_ddl_transaction!` . +* 应该考虑在[后台迁移中](background_migrations.html)这样做. + +## Retry mechanism when acquiring database locks[](#retry-mechanism-when-acquiring-database-locks "Permalink") + +更改数据库架构时,我们使用辅助方法来调用 DDL(数据定义语言)语句. 在某些情况下,这些 DDL 语句需要特定的数据库锁. + +Example: + +``` +def change + remove_column :users, :full_name, :string +end +``` + +要执行此迁移,需要对`users`表进行排他锁定. 当表被其他进程同时访问和修改时,获取锁定可能需要一段时间. 锁定请求正在队列中等待,一旦进入队列,它也可能阻止`users`表上的其他查询. + +有关 PostgresSQL 锁的更多信息: [显式锁定](https://s0www0postgresql0org.icopy.site/docs/current/explicit-locking.html) + +出于稳定性考虑,GitLab.com 设置了特定的[`statement_timeout`](../user/gitlab_com/index.html#postgresql) . 调用迁移时,任何数据库查询都将有固定的执行时间. 在最坏的情况下,请求将坐在锁定队列中,在配置的语句超时时间内阻止其他查询,然后`canceling statement due to statement timeout`错误`canceling statement due to statement timeout`失败. + +此问题可能导致应用程序升级过程失败,甚至导致应用程序稳定性问题,因为该表可能会在短时间内无法访问. + +为了提高数据库迁移的可靠性和稳定性,GitLab 代码库提供了一种辅助方法,以使用不同的`lock_timeout`设置重试操作,并在两次尝试之间等待时间. 为了获得必要的锁定,进行了多次较小的尝试,从而使数据库可以处理其他语句. + +### Examples[](#examples "Permalink") + +**删除列:** + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + remove_column :users, :full_name + end +end + +def down + with_lock_retries do + add_column :users, :full_name, :string + end +end +``` + +**删除外键:** + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + remove_foreign_key :issues, :projects + end +end + +def down + with_lock_retries do + add_foreign_key :issues, :projects + end +end +``` + +**更改列的默认值:** + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + change_column_default :merge_requests, :lock_version, from: nil, to: 0 + end +end + +def down + with_lock_retries do + change_column_default :merge_requests, :lock_version, from: 0, to: nil + end +end +``` + +**用外键创建一个新表:** + +我们可以简单地用`with_lock_retries`包装`create_table`方法: + +``` +def up + with_lock_retries do + create_table :issues do |t| + t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade } + t.string :title, limit: 255 + end + end +end + +def down + drop_table :issues +end +``` + +**当我们有两个外键时创建一个新表:** + +为此,我们需要进行三个迁移: + +1. 创建不带外键(带有索引)的表. +2. 将外键添加到第一个表. +3. 将外键添加到第二个表. + +创建表: + +``` +def up + create_table :imports do |t| + t.bigint :project_id, null: false + t.bigint :user_id, null: false + t.string :jid, limit: 255 + end + + add_index :imports, :project_id + add_index :imports, :user_id +end + +def down + drop_table :imports +end +``` + +在`projects`添加外键: + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + add_foreign_key :imports, :projects, column: :project_id, on_delete: :cascade + end +end + +def down + with_lock_retries do + remove_foreign_key :imports, column: :project_id + end +end +``` + +向`users`添加外键: + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + add_foreign_key :imports, :users, column: :user_id, on_delete: :cascade + end +end + +def down + with_lock_retries do + remove_foreign_key :imports, column: :user_id + end +end +``` + +**与`disable_ddl_transaction!`配合使用`disable_ddl_transaction!`** + +通常, `with_lock_retries`帮助程序应与`disabled_ddl_transaction!` . 定制的 RuboCop 规则可确保只能将允许的方法放在锁重试块中. + +``` +disable_ddl_transaction! + +def up + with_lock_retries do + add_column :users, :name, :text + end + + add_text_limit :users, :name, 255 # Includes constraint validation (full table scan) +end +``` + +RuboCop 规则通常允许使用下面列出的标准 Rails 迁移方法. 此示例将导致 Rubocop 犯罪: + +``` +disabled_ddl_transaction! + +def up + with_lock_retries do + add_concurrent_index :users, :name + end +end +``` + +### When to use the helper method[](#when-to-use-the-helper-method "Permalink") + +通常使用标准的 Rails 迁移帮助器方法时,可以使用`with_lock_retries`帮助器方法. 如果在同一个表上执行多个迁移助手,则调用它们不是问题. + +当数据库迁移涉及高流量表之一时,建议使用`with_lock_retries`帮助程序方法: + +* `users` +* `projects` +* `namespaces` +* `issues` +* `merge_requests` +* `ci_pipelines` +* `ci_builds` +* `notes` + +更改示例: + +* `add_foreign_key` / `remove_foreign_key` +* `add_column` / `remove_column` +* `change_column_default` +* `create_table` / `drop_table` + +**注意:** `with_lock_retries`方法**不能**在`change`方法中使用,必须手动定义`up`和`down`方法以使迁移可逆. + +### How the helper method works[](#how-the-helper-method-works "Permalink") + +1. 重复 50 次. +2. 对于每次迭代,设置一个预配置的`lock_timeout` . +3. 尝试执行给定的块. ( `remove_column` ). +4. 如果出现`LockWaitTimeout`错误,请为预配置的`sleep_time`睡眠,然后重试该块. +5. 如果未引发错误,则当前迭代已成功执行该块. + +有关更多信息,请检查[`Gitlab::Database::WithLockRetries`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/with_lock_retries.rb)类. `with_lock_retries`帮助器方法在[`Gitlab::Database::MigrationHelpers`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/migration_helpers.rb)模块中实现. + +在最坏的情况下,该方法: + +* 在 40 分钟内最多执行 50 次该块. + * 大部分时间都花费在每次迭代后的预先配置的睡眠时段中. +* 第 50 次重试之后,将像标准迁移调用一样在没有`lock_timeout`情况下执行该块. +* 如果无法获取锁,则迁移将失败,并出现`statement timeout`错误. + +如果访问`users`表的事务运行时间很长(超过 40 分钟),则迁移可能会失败. + +## Multi-Threading[](#multi-threading "Permalink") + +有时,迁移可能需要使用多个 Ruby 线程来加快迁移速度. 为此,您的迁移需要包括模块`Gitlab::Database::MultiThreadedMigration` : + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + include Gitlab::Database::MultiThreadedMigration +end +``` + +然后可以使用`with_multiple_threads`方法在单独的线程中执行工作. 例如: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + include Gitlab::Database::MultiThreadedMigration + + def up + with_multiple_threads(4) do + disable_statement_timeout + + # ... + end + end +end +``` + +在这里,对`disable_statement_timeout`的调用将使用`with_multiple_threads`块本地的连接,而不是重新使用全局连接池. 这样可以确保每个线程都有自己的连接对象,并且在尝试获取一个连接对象时不会超时. + +**注意:** PostgreSQL 具有允许的最大连接数. 此限制因安装而异. 因此,建议您一次迁移不要使用超过 32 个线程. 通常,4-8 个线程应该绰绰有余. + +## Removing indexes[](#removing-indexes "Permalink") + +如果删除索引时表不为空,请确保使用方法`remove_concurrent_index`而不是常规的`remove_index`方法. `remove_concurrent_index`方法同时删除索引,因此不需要锁定,也无需停机. 要使用此方法,必须通过调用方法`disable_ddl_transaction!`禁用单交易模式`disable_ddl_transaction!` 在您的迁移类的主体中,如下所示: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + disable_ddl_transaction! + + def up + remove_concurrent_index :table_name, :column_name + end +end +``` + +请注意,在删除索引之前不必检查索引是否存在. + +对于较小的表(例如空表或少于`1,000`条记录的表),建议在单事务迁移中使用`remove_index` ,并将其与不需要`disable_ddl_transaction!`其他操作结合使用`disable_ddl_transaction!` . + +## Adding indexes[](#adding-indexes "Permalink") + +在添加索引之前,请考虑该索引是否必要. 在某些情况下可能不需要索引,例如: + +* 该表很小(少于`1,000`条记录),并且预计大小不会成倍增长. +* 任何现有索引都会过滤掉足够的行. +* 添加索引后查询时间的减少并不明显. + +另外,不需要宽索引来匹配查询的所有过滤条件,我们只需要覆盖足够多的列即可使索引查找具有足够小的选择性. 请查看我们的[添加数据库索引](adding_database_indexes.html)指南以获取更多详细信息. + +将索引添加到非空表时,请确保使用方法`add_concurrent_index`而不是常规的`add_index`方法. 使用 PostgreSQL 时, `add_concurrent_index`方法自动创建并发索引,从而消除了停机时间. + +要使用此方法,必须通过调用方法`disable_ddl_transaction!`禁用单交易模式`disable_ddl_transaction!` 在您的迁移类的主体中,如下所示: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :table, :column + end + + def down + remove_concurrent_index :table, :column + end +end +``` + +如果需要添加唯一索引,请记住,数据库中可能存在现有重复项. 这意味着在添加唯一索引之前,应始终*首先*添加一个删除所有重复项的迁移. + +对于小型表(例如空表或少于`1,000`条记录的表),建议在单事务迁移中使用`add_index` ,并将其与不需要`disable_ddl_transaction!`其他操作结合使用`disable_ddl_transaction!` . + +## Adding foreign-key constraints[](#adding-foreign-key-constraints "Permalink") + +向现有列或新列添加外键约束时,还请记住在该列上添加索引. + +这是所有外键所**必需**的,例如,为了支持有效的级联删除:当删除表中的许多行时,也需要删除引用的记录. 数据库必须在引用的表中查找相应的记录. 没有索引,这将导致对表进行顺序扫描,这可能需要很长时间. + +这是一个示例,其中我们添加了一个带有外键约束的新列. 请注意,它包括`index: true`为其创建索引. + +``` +class Migration < ActiveRecord::Migration[6.0] + + def change + add_reference :model, :other_model, index: true, foreign_key: { on_delete: :cascade } + end +end +``` + +当向非空表中的现有列添加外键约束时,我们必须使用`add_concurrent_foreign_key`和`add_concurrent_index`而不是`add_reference` . + +对于空表(例如新表),建议在单事务迁移中使用`add_reference` ,并将其与不需要`disable_ddl_transaction!`其他操作结合使用`disable_ddl_transaction!` . + +您可以阅读有关将[外键约束](database/add_foreign_key_to_existing_column.html)添加[到现有列的更多信息](database/add_foreign_key_to_existing_column.html) . + +## `NOT NULL` constraints[](#not-null-constraints "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38358) in GitLab 13.0. + +有关更多信息,请参见关于[`NOT NULL`约束](database/not_null_constraints.html)的样式指南. + +## Adding Columns With Default Values[](#adding-columns-with-default-values "Permalink") + +PostgreSQL 11 是自 GitLab 13.0 以来的最低版本,添加具有默认值的列变得更加容易,并且在所有情况下都应使用标准的`add_column`帮助器. + +在 PostgreSQL 11 之前,添加带有默认值的列是有问题的,因为这会导致全表重写. 相应的帮助程序`add_column_with_default`已被弃用,并将在以后的版本中删除. + +**注意:**如果%12.9 或更早版本需要向后端口添加具有默认值的列,则应使用`add_column_with_default`帮助器. 如果涉及[大表](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3) ,则禁止向后移植到%12.9. + +## Changing the column default[](#changing-the-column-default "Permalink") + +可能有人认为,使用`change_column_default`更改默认列对于较大的表来说是一项昂贵且破坏性的操作,但实际上并非如此. + +以以下迁移为例: + +``` +class DefaultRequestAccessGroups < ActiveRecord::Migration[5.2] + DOWNTIME = false + + def change + change_column_default(:namespaces, :request_access_enabled, from: false, to: true) + end +end +``` + +上面的迁移更改了我们最大的表之一的默认列值: `namespaces` . 可以将其翻译为: + +``` +ALTER TABLE namespaces +ALTER COLUMN request_access_enabled +DEFAULT false +``` + +在这种情况下,默认值存在,我们只是更改了`request_access_enabled`列的元数据,这并不意味着重写`namespaces`表中的所有现有记录. 仅当使用默认值创建新列时,所有记录才会被重写. + +**注意:** PostgresSQL 11.0 引入[了](https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/)更快的[ALTER TABLE ADD COLUMN(具有非空默认值](https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/) ),从而消除了在添加具有默认值的新列时重写表的需求. + +由于上述原因,在单事务迁移中使用`change_column_default`是安全的,而不需要`disable_ddl_transaction!` . + +## Updating an existing column[](#updating-an-existing-column "Permalink") + +要将现有列更新为特定值,可以使用`update_column_in_batches` . 这会将更新分为批次,因此我们不会在单个语句中更新太多行. + +这`some_column` `projects`表中的`foo`列更新为 10,其中`some_column`为`'hello'` : + +``` +update_column_in_batches(:projects, :foo, 10) do |table, query| + query.where(table[:some_column].eq('hello')) +end +``` + +如果需要计算的更新,则可以将值包装在`Arel.sql` ,因此 Arel 将其视为 SQL 文字. 这也是[Rails 6](https://gitlab.com/gitlab-org/gitlab/-/issues/28497)的必需弃用. + +下面的示例与上面的示例相同,但是该值设置为`bar`和`baz`列的乘积: + +``` +update_value = Arel.sql('bar * baz') + +update_column_in_batches(:projects, :foo, update_value) do |table, query| + query.where(table[:some_column].eq('hello')) +end +``` + +像`add_column_with_default`一样,有一个 RuboCop cop 可以检测大表上的用法. 在`update_column_in_batches`的情况下,可以在大表上运行,只要它仅更新表中行的一小部分,而在未在 GitLab.com 登台环境上进行验证的情况下不要忽略它-或事先请别人为您这样做. + +## Dropping a database table[](#dropping-a-database-table "Permalink") + +删除数据库表并不常见,Rails 提供的`drop_table`方法通常被认为是安全的. 删除表格之前,请考虑以下因素: + +如果您的表在高流量表上具有外键(如`projects` ),则`DROP TABLE`语句可能会失败,并出现**语句超时**错误. 确定哪些表是高流量可能很困难. 自我管理的实例可能会以不同的使用模式使用 GitLab 的不同功能,因此仅基于 GitLab.com 进行假设是不够的. + +表**没有记录** (功能从未使用过),也**没有外键** : + +* 只需在迁移中使用`drop_table`方法即可. + +``` +def change + drop_table :my_table +end +``` + +Table **有记录** but **没有外键**: + +* 第一版:删除与表相关的应用程序代码,例如模型,控制器和服务. +* 第二版:在迁移中使用`drop_table`方法. + +``` +def up + drop_table :my_table +end + +def down + # create_table ... +end +``` + +Table **有外键**: + +* 第一版:删除与表相关的应用程序代码,例如模型,控制器和服务. +* 第二版:使用`with_lock_retries`帮助器方法删除外键. 在另一个迁移文件中使用`drop_table` . + +**第二个版本的迁移:** + +删除`projects`表上的外键: + +``` +# first migration file + +def up + with_lock_retries do + remove_foreign_key :my_table, :projects + end +end + +def down + with_lock_retries do + add_foreign_key :my_table, :projects + end +end +``` + +放下桌子: + +``` +# second migration file + +def up + drop_table :my_table +end + +def down + # create_table ... +end +``` + +## Integer column type[](#integer-column-type "Permalink") + +默认情况下,整数列最多可容纳 4 个字节(32 位)的数字. 最大值为 2,147,483,647\. 创建一个以字节为单位保存文件大小的列时,请注意这一点. 如果以字节为单位跟踪文件大小,这会将最大文件大小限制为刚好超过 2GB. + +要允许整数列最多容纳 8 个字节(64 位)的数字,请将限制明确设置为 8 个字节. 这将使该列最多`9,223,372,036,854,775,807`个值. + +Rails 迁移示例: + +``` +add_column(:projects, :foo, :integer, default: 10, limit: 8) +``` + +## Strings and the Text data type[](#strings-and-the-text-data-type "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30453) . + +有关更多信息,请参见[文本数据类型](database/strings_and_the_text_data_type.html)样式指南. + +## Timestamp column type[](#timestamp-column-type "Permalink") + +默认情况下,Rails 使用`timestamp`数据类型来存储没有时区信息的时间戳数据. 通过调用`add_timestamps`或`timestamps`方法来使用`timestamp`数据类型. + +另外,Rails 将`:datetime`数据类型转换为`timestamp`一. + +Example: + +``` +# timestamps +create_table :users do |t| + t.timestamps +end + +# add_timestamps +def up + add_timestamps :users +end + +# :datetime +def up + add_column :users, :last_sign_in, :datetime +end +``` + +代替使用这些方法,应该使用以下方法来存储带有时区的时间戳: + +* `add_timestamps_with_timezone` +* `timestamps_with_timezone` +* `datetime_with_timezone` + +这样可以确保所有时间戳都有指定的时区. 反过来,这意味着当系统的时区更改时,现有时间戳不会突然使用其他时区. 这也使得非常清楚,首先使用了哪个时区. + +## Storing JSON in database[](#storing-json-in-database "Permalink") + +Rails 5 本机支持`JSONB` (二进制 JSON)列类型. 添加此列的示例迁移: + +``` +class AddOptionsToBuildMetadata < ActiveRecord::Migration[5.0] + DOWNTIME = false + + def change + add_column :ci_builds_metadata, :config_options, :jsonb + end +end +``` + +您必须使用序列化器来提供翻译层: + +``` +class BuildMetadata + serialize :config_options, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize +end +``` + +使用`JSONB`列时,请使用[JsonSchemaValidator](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/validators/json_schema_validator.rb)来控制随时间推移插入的数据. + +``` +class BuildMetadata + validates :config_options, json_schema: { filename: 'build_metadata_config_option' } +end +``` + +## Testing[](#testing "Permalink") + +请参阅" [测试 Rails 迁移](testing_guide/testing_migrations_guide.html)样式"指南. + +## Data migration[](#data-migration "Permalink") + +请比一般 ActiveRecord 语法更喜欢 Arel 和普通 SQL. 如果使用普通 SQL,则需要使用`quote_string` helper 手动引用所有输入. + +Arel 的示例: + +``` +users = Arel::Table.new(:users) +users.group(users[:user_id]).having(users[:id].count.gt(5)) + +#update other tables with these results +``` + +带有普通 SQL 和`quote_string`帮助器的示例: + +``` +select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(id) > 1").each do |tag| + tag_name = quote_string(tag["name"]) + duplicate_ids = select_all("SELECT id FROM tags WHERE name = '#{tag_name}'").map{|tag| tag["id"]} + origin_tag_id = duplicate_ids.first + duplicate_ids.delete origin_tag_id + + execute("UPDATE taggings SET tag_id = #{origin_tag_id} WHERE tag_id IN(#{duplicate_ids.join(",")})") + execute("DELETE FROM tags WHERE id IN(#{duplicate_ids.join(",")})") +end +``` + +如果需要更复杂的逻辑,则可以定义和使用迁移本地模型. 例如: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + class Project < ActiveRecord::Base + self.table_name = 'projects' + end + + def up + # Reset the column information of all the models that update the database + # to ensure the Active Record's knowledge of the table structure is current + Project.reset_column_information + + # ... ... + end +end +``` + +这样做时,请确保显式设置模型的表名,这样它就不会派生自类名或名称空间. + +最后,对于所有更新数据库的本地模型,请确保在迁移的`up`方法中运行`reset_column_information` . + +这样做的原因是所有迁移类都在开始时加载( `db:migrate`启动时),因此,如果另一个迁移更新了该模式,它们将与它们映射的表模式不同步. 这将导致在尝试插入基础表或对其进行更新时数据迁移失败,因为`ActiveRecord`将新列报告为`unknown attribute` . + +### Renaming reserved paths[](#renaming-reserved-paths "Permalink") + +引入新的项目路线时,它可能与任何现有记录冲突. 这些记录的路径应重命名,并且相关数据应在磁盘上移动. + +由于我们已经必须做几次,因此现在有一些帮助程序可以帮助您. + +要使用此功能,您可以在迁移中包括`Gitlab::Database::RenameReservedPathsMigration::V1` . 这将提供 3 种方法,您可以通过一种或多种需要拒绝的路径. + +**`rename_root_paths`** :这将使用给定名称重命名所有没有`parent_id`名称*空间*的路径. + +**`rename_child_paths`** :这将使用给定名称重命名所有具有`parent_id`名称*空间*的路径. + +**`rename_wildcard_paths`** :这将重命名所有*项目*的路径以及所有具有`project_id` *命名空间* . + +这些行的`path`列将重命名为其先前的值,后跟一个整数. 例如: `users`将变成`users0` \ No newline at end of file diff --git a/_book/docs/617.md b/_book/docs/617.md new file mode 100644 index 0000000000000000000000000000000000000000..9410954bb21c0199c71c7aeff1d429252b46e68d --- /dev/null +++ b/_book/docs/617.md @@ -0,0 +1,112 @@ +# Newlines style guide + +> 原文:[https://docs.gitlab.com/ee/development/newlines_styleguide.html](https://docs.gitlab.com/ee/development/newlines_styleguide.html) + +* [Rule: separate code with newlines only to group together related logic](#rule-separate-code-with-newlines-only-to-group-together-related-logic) +* [Rule: separate code and block with newlines](#rule-separate-code-and-block-with-newlines) + * [Newline before block](#newline-before-block) +* [Newline after block](#newline-after-block) + * [Exception: no need for newline when code block starts or ends right inside another code block](#exception-no-need-for-newline-when-code-block-starts-or-ends-right-inside-another-code-block) + +# Newlines style guide[](#newlines-style-guide "Permalink") + +该样式指南为 Ruby 代码中的换行符推荐了最佳做法. + +## Rule: separate code with newlines only to group together related logic[](#rule-separate-code-with-newlines-only-to-group-together-related-logic "Permalink") + +``` +# bad +def method + issue = Issue.new + + issue.save + + render json: issue +end +``` + +``` +# good +def method + issue = Issue.new + issue.save + + render json: issue +end +``` + +## Rule: separate code and block with newlines[](#rule-separate-code-and-block-with-newlines "Permalink") + +### Newline before block[](#newline-before-block "Permalink") + +``` +# bad +def method + issue = Issue.new + if issue.save + render json: issue + end +end +``` + +``` +# good +def method + issue = Issue.new + + if issue.save + render json: issue + end +end +``` + +## Newline after block[](#newline-after-block "Permalink") + +``` +# bad +def method + if issue.save + issue.send_email + end + render json: issue +end +``` + +``` +# good +def method + if issue.save + issue.send_email + end + + render json: issue +end +``` + +### Exception: no need for newline when code block starts or ends right inside another code block[](#exception-no-need-for-newline-when-code-block-starts-or-ends-right-inside-another-code-block "Permalink") + +``` +# bad +def method + + if issue + + if issue.valid? + issue.save + end + + end + +end +``` + +``` +# good +def method + if issue + if issue.valid? + issue.save + end + end +end +``` \ No newline at end of file diff --git a/_book/docs/618.md b/_book/docs/618.md new file mode 100644 index 0000000000000000000000000000000000000000..41162259b3186fa6f2ef172bc87b8ebcec67ddd1 --- /dev/null +++ b/_book/docs/618.md @@ -0,0 +1,80 @@ +# Python Development Guidelines + +> 原文:[https://docs.gitlab.com/ee/development/python_guide/](https://docs.gitlab.com/ee/development/python_guide/) + +* [Installation](#installation) + * [macOS](#macos) + * [Linux](#linux) + * [Shell integration](#shell-integration) +* [Dependency management](#dependency-management) +* [Use instructions](#use-instructions) + +# Python Development Guidelines[](#python-development-guidelines "Permalink") + +GitLab requires Python as a dependency for [reStructuredText](https://docutils.sourceforge.io/rst.html) markup rendering. + +从 GitLab 11.10 开始,我们需要 Python 3. + +## Installation[](#installation "Permalink") + +有几种方法可以在系统上安装 Python. 为了能够使用生产中使用的相同版本,建议您使用[pyenv](https://github.com/pyenv/pyenv) . 它的工作方式和行为与 Ruby 世界中的[同类产品 rbenv 相似](https://github.com/rbenv/rbenv) . + +### macOS[](#macos "Permalink") + +要在 macOS 上安装`pyenv` ,可以将[Homebrew](https://brew.sh/)与以下软件配合使用: + +``` +brew install pyenv +``` + +### Linux[](#linux "Permalink") + +要在 Linux 上安装`pyenv` ,您可以运行以下命令: + +``` +curl https://pyenv.run | bash +``` + +另外,您可以通过发行版软件包管理器找到`pyenv`作为系统软件包. + +您可以在以下[网址](https://github.com/pyenv/pyenv-installer#prerequisites)了解更多信息: [https](https://github.com/pyenv/pyenv-installer#prerequisites) : [//github.com/pyenv/pyenv-installer#prerequisites](https://github.com/pyenv/pyenv-installer#prerequisites) . + +### Shell integration[](#shell-integration "Permalink") + +Pyenv 安装会将必需的更改添加到 Bash. 如果使用其他外壳,请检查是否需要其他步骤. + +对于 Fish,您可以为[Fisher](https://github.com/jorgebucaran/fisher)安装插件: + +``` +fisher add fisherman/pyenv +``` + +还是为了[我的鱼](https://github.com/oh-my-fish/oh-my-fish) : + +``` +omf install pyenv +``` + +## Dependency management[](#dependency-management "Permalink") + +尽管 GitLab 不直接包含任何 Python 脚本,但是由于我们依赖 Python 来呈现[reStructuredText](https://docutils.sourceforge.io/rst.html)标记,因此我们需要在主项目级别上跟踪依赖项,以便可以在开发机器上运行它. + +最近,Python 引入了与`Gemfile`和[Bundler](https://bundler.io/)项目等效的项目: `Pipfile`和[Pipenv](https://pipenv.readthedocs.io/en/latest/) . + +现在,您将在根文件夹中找到具有相关性的`Pipfile` . 要安装它们,请运行: + +``` +pipenv install +``` + +运行此命令将安装所需的 Python 版本以及所需的 pip 依赖项. + +## Use instructions[](#use-instructions "Permalink") + +要在 Pipenv 环境下运行任何 Python 代码,您需要首先根据应用程序的依赖关系启动`virtualenv` . 使用 Pipenv,运行起来很简单: + +``` +pipenv shell +``` + +运行该命令后,您可以在同一外壳上运行 GitLab,它将使用从`pipenv install`命令安装的 Python 和依赖项. \ No newline at end of file diff --git a/_book/docs/619.md b/_book/docs/619.md new file mode 100644 index 0000000000000000000000000000000000000000..ce8cd8a70b009bffb8e0f6dd03f15fa567642723 --- /dev/null +++ b/_book/docs/619.md @@ -0,0 +1,285 @@ +# SCSS style guide + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/style/scss.html](https://docs.gitlab.com/ee/development/fe_guide/style/scss.html) + +* [Rules](#rules) + * [Utility Classes](#utility-classes) + * [Where are utility classes defined?](#where-are-utility-classes-defined) + * [Where should I put new utility classes?](#where-should-i-put-new-utility-classes) + * [When should I create component classes?](#when-should-i-create-component-classes) + * [Naming](#naming) + * [Formatting](#formatting) + * [Colors](#colors) + * [Indentation](#indentation) + * [Semicolons](#semicolons) + * [Shorthand](#shorthand) + * [Zero Units](#zero-units) + * [Selectors with a `js-` Prefix](#selectors-with-a-js--prefix) + * [IDs](#ids) + * [Variables](#variables) +* [Linting](#linting) + * [Fixing issues](#fixing-issues) + * [Ignoring issues](#ignoring-issues) + +# SCSS style guide[](#scss-style-guide "Permalink") + +本样式指南为 SCSS 推荐了最佳做法,以使样式易于阅读,易于维护并为最终用户提供高性能. + +## Rules[](#rules "Permalink") + +我们的 CSS 是现有方法和旧方法的结合. 这意味着有时可能难以按照本指南进行操作. 这意味着您肯定会遇到例外,在这种情况下,如果不付出巨大的努力,很难甚至不可能遵循该指南. 在这种情况下,您可以与审核者和维护者一起确定不符合这些规则的方法. 请努力限制这些情况. + +### Utility Classes[](#utility-classes "Permalink") + +为了减少随着站点的增加而产生更多 CSS 的可能性,与添加新 CSS 相比,更喜欢使用实用程序类. 在复杂的情况下,可以通过添加组件类来解决 CSS. + +#### Where are utility classes defined?[](#where-are-utility-classes-defined "Permalink") + +优先使用[在 GitLab UI 中定义](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/doc/css.md#utilities)的[实用程序类](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/doc/css.md#utilities) . [在 Unpkg 上](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss)也可以[看到](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss)一个简单的类列表. + +在类[`utilities.scss`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/stylesheets/utilities.scss)和[`common.scss`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/stylesheets/framework/common.scss)被弃用. 应该避免使用[`common.scss`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/stylesheets/framework/common.scss)中的非设计系统值的类,而采用一致的值. + +Avoid [Bootstrap’s Utility Classes](https://s0getbootstrap0com.icopy.site/docs/4.3/utilities/). + +#### Where should I put new utility classes?[](#where-should-i-put-new-utility-classes "Permalink") + +如果尚未将所需的类添加到 GitLab UI,则可以添加它! 请遵循[实用程序文件中](https://gitlab.com/gitlab-org/gitlab-ui/-/tree/master/src/scss/utility-mixins)记录的命名模式,并参阅[GitLab UI 的 CSS 文档](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/doc/contributing/adding_css.md#adding-utility-mixins)以获取更多详细信息,尤其是有关添加响应式和有状态规则的信息. + +如果它是不可能等待 GitLab UI 更新(通常一天),将该类添加到[`utilities.scss`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/stylesheets/utilities.scss)按照 GitLab UI 文件相同的命名约定. 应该解决将类反向移植到 GitLab UI 并将其从 GitLab 中删除的后续问题. + +#### When should I create component classes?[](#when-should-i-create-component-classes "Permalink") + +我们建议采用"效用至上"的方法. + +1. 从实用程序类开始. +2. 如果将实用程序类组合到组件类中可以消除代码重复并封装明确的职责,请执行此操作. + +这鼓励了组件类的有机增长,并防止创建一次性不可重用的类. 而且,从"效用优先"产生的类的种类倾向于以设计为中心(例如`.button` , `.alert` , `.card` )而不是以领域为中心(例如`.security-report-widget` , `.commit-header-icon` ). + +使用"效用优先"创建的组件类的示例包括: + +* [`.circle-icon-container`](https://gitlab.com/gitlab-org/gitlab/blob/579fa8b8ec7eb38d40c96521f517c9dab8c3b97a/app/assets/stylesheets/framework/icons.scss#L85) +* [`.d-flex-center`](https://gitlab.com/gitlab-org/gitlab/blob/900083d89cd6af391d26ab7922b3f64fa2839bef/app/assets/stylesheets/framework/common.scss#L425) + +Inspiration: + +* [https://tailwindcss.com/docs/utility-first/](https://tailwindcss.com/docs/utility-first/) +* [https://tailwindcss.com/docs/extracting-components/](https://tailwindcss.com/docs/extracting-components/) + +### Naming[](#naming "Permalink") + +文件名应使用`snake_case` . + +CSS 类应使用`lowercase-hyphenated`格式,而不是`snake_case`或`camelCase` . + +``` +// Bad +.class_name { + color: #fff; +} + +// Bad +.className { + color: #fff; +} + +// Good +.class-name { + color: #fff; +} +``` + +应该使用类名代替标记名选择器. 在 CSS 中不建议使用标记名称选择器,因为它们会影响层次结构中的意外元素. 另外,由于它们不是有意义的名称,因此不会在代码中添加含义. + +``` +// Bad +ul { + color: #fff; +} + +// Good +.class-name { + color: #fff; +} +``` + +### Formatting[](#formatting "Permalink") + +大括号前应始终使用空格,大括号应位于同一行上,每个属性都应具有自己的行,并且属性与其值之间应有一个空格. + +``` +// Bad +.container-item { + width: 100px; height: 100px; + margin-top: 0; +} + +// Bad +.container-item +{ + width: 100px; + height: 100px; + margin-top: 0; +} + +// Bad +.container-item{ + width:100px; + height:100px; + margin-top:0; +} + +// Good +.container-item { + width: 100px; + height: 100px; + margin-top: 0; +} +``` + +请注意,单行规则集是一个例外,尽管通常不建议使用这些规则集. + +``` +p { margin: 0; padding: 0; } +``` + +### Colors[](#colors "Permalink") + +十六进制(十六进制)颜色应尽可能使用简写形式,并应使用小写字母区分字母和数字,例如`#E3E3E3`与`#e3e3e3` . + +``` +// Bad +p { + color: #ffffff; +} + +// Bad +p { + color: #FFFFFF; +} + +// Good +p { + color: #fff; +} +``` + +### Indentation[](#indentation "Permalink") + +缩进应始终为每个缩进级别使用两个空格. + +``` +// Bad, four spaces +p { + color: #f00; +} + +// Good +p { + color: #f00; +} +``` + +### Semicolons[](#semicolons "Permalink") + +在每个属性后面都应始终包含分号. 缩小样式表后,分号将自动删除. + +``` +// Bad +.container-item { + width: 100px; + height: 100px +} + +// Good +.container-item { + width: 100px; + height: 100px; +} +``` + +### Shorthand[](#shorthand "Permalink") + +简写形式应用于支持它的属性. + +``` +// Bad +margin: 10px 15px 10px 15px; +padding: 10px 10px 10px 10px; + +// Good +margin: 10px 15px; +padding: 10px; +``` + +### Zero Units[](#zero-units "Permalink") + +省略长度单位为零的值,这是不必要的,不包括长度单位的性能更高. + +``` +// Bad +.item-with-padding { + padding: 0px; +} + +// Good +.item-with-padding { + padding: 0; +} +``` + +### Selectors with a `js-` Prefix[](#selectors-with-a-js--prefix "Permalink") + +不要将任何以`js-`选择器用于样式目的. 这些选择器仅可与 JavaScript 一起使用,以便在不破坏样式的情况下进行删除或重命名. + +### IDs[](#ids "Permalink") + +不要在 CSS 中使用 ID 选择器. + +``` +// Bad +#my-element { + padding: 0; +} + +// Good +.my-element { + padding: 0; +} +``` + +### Variables[](#variables "Permalink") + +在为颜色或尺寸添加新变量之前,请确保: + +* 还没有一个 +* 我们没有类似的替代方法. + +## Linting[](#linting "Permalink") + +我们使用[SCSS Lint](https://github.com/sds/scss-lint)检查样式指南的一致性. 它使用`.scss-lint.yml`的规则集,该规则集位于项目的主目录中. + +要检查您的更改是否会产生任何警告,您可以在 GitLab 目录中运行`rake scss_lint` . SCSS Lint 也将在 GitLab CI / CD 中运行以捕获任何警告. + +如果 Rake 任务发出了您不了解的警告,SCSS Lint 的文档将包含[其](https://github.com/sds/scss-lint/blob/master/lib/scss_lint/linter/README.md)短毛绒的[完整列表](https://github.com/sds/scss-lint/blob/master/lib/scss_lint/linter/README.md) . + +### Fixing issues[](#fixing-issues "Permalink") + +如果要自动更改大部分代码库以符合 SCSS 样式指南,则可以使用[CSSComb](https://github.com/csscomb/csscomb.js) . 首先安装[Node](https://github.com/nodejs/node)和[NPM](https://s0www0npmjs0com.icopy.site/) ,然后运行`npm install csscomb -g`全局(系统范围)安装 CSSComb. 使用`csscomb app/assets/stylesheets`在 GitLab 目录中运行它,以自动修复 CSS / SCSS 问题. + +请注意,这并不能解决所有问题,但应该可以解决大多数问题. + +### Ignoring issues[](#ignoring-issues "Permalink") + +如果您希望`// scss-lint:disable RuleName`忽略一条线或一组线,则可以使用`// scss-lint:disable RuleName` ( [更多信息](https://github.com/sds/scss-lint#disabling-linters-via-source) ): + +``` +// This lint rule is disabled because it is supported only in Chrome/Safari +// scss-lint:disable PropertySpelling +body { + text-decoration-skip: ink; +} +// scss-lint:enable PropertySpelling +``` + +确保在`disable`规则上方的行上添加了注释,否则短绒棉绒将抛出警告. 已启用`DisableLinterReason`以确保不忽略样式指南,并与其他人交流为什么在这种情况下忽略样式指南. \ No newline at end of file diff --git a/_book/docs/620.md b/_book/docs/620.md new file mode 100644 index 0000000000000000000000000000000000000000..52d76d2da10d0be516e4248f9c391e5de98c6430 --- /dev/null +++ b/_book/docs/620.md @@ -0,0 +1,105 @@ +# Shell scripting standards and style guidelines + +> 原文:[https://docs.gitlab.com/ee/development/shell_scripting_guide/](https://docs.gitlab.com/ee/development/shell_scripting_guide/) + +* [Overview](#overview) + * [Avoid using shell scripts](#avoid-using-shell-scripts) +* [Scope of this guide](#scope-of-this-guide) +* [Shell language choice](#shell-language-choice) +* [Code style and format](#code-style-and-format) + * [Linting](#linting) + * [Formatting](#formatting) +* [Testing](#testing) +* [Code Review](#code-review) + +# Shell scripting standards and style guidelines[](#shell-scripting-standards-and-style-guidelines "Permalink") + +## Overview[](#overview "Permalink") + +GitLab 由许多不同的服务和子项目组成. 他们的大多数后端代码都是用[Ruby](https://www.ruby-lang.org)和[Go](https://s0golang0org.icopy.site)编写的. 但是,其中一些使用 shell 脚本来自动化日常系统管理任务,例如部署,安装等.之所以这样做是出于历史原因,或者是为了最大程度地减少对 Docker 映像的依赖性. + +该页面旨在根据我们的各种经验来定义和组织我们的 Shell 脚本编写准则. GitLab 项目中的所有 Shell 脚本最终都应与本指南保持一致. 如果每个项目与本指南存在差异,则应在此类项目的`README.md`或`PROCESS.md`文件中进行说明. + +### Avoid using shell scripts[](#avoid-using-shell-scripts "Permalink") + +**注意:**这是必读部分. + +综上所述,我们建议尽可能远离 Shell 脚本. 像 Ruby 或 Python 这样的语言(如果需要与我们利用的代码库保持一致),几乎总是一个更好的选择. 高级解释语言具有更易读的语法,为单元测试,整理和错误报告提供了更成熟的功能. + +仅在对项目的依赖项大小有严格限制或在特定情况下更重要的任何其他要求时,才使用 Shell 脚本. + +## Scope of this guide[](#scope-of-this-guide "Permalink") + +根据[GitLab 安装要求](../../install/requirements.html) ,本指南仅涵盖受[支持的 Linux 发行版](../../install/requirements.html#supported-linux-distributions)使用的那些 shell,即: + +* [POSIX Shell](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html) +* [Bash](https://www.gnu.org/software/bash/) + +## Shell language choice[](#shell-language-choice "Permalink") + +* 当您需要减少依赖关系列表时,请使用环境提供的内容. 例如,对于泊坞图片是`sh`从`alpine`这是基本的图像对于大多数我们的工具的图像. +* 如果可能,请在其他任何地方使用`bash` . 它比`sh`更强大,但仍然是广泛使用的 shell. + +## Code style and format[](#code-style-and-format "Permalink") + +本节描述了包含外壳程序脚本的工具,这些工具应成为项目 CI 管道的必需部分. 这些工具可自动执行 Shell 代码格式化,检查错误或漏洞等. + +### Linting[](#linting "Permalink") + +我们在默认配置中使用[ShellCheck](https://www.shellcheck.net/)实用程序来[整理](https://www.shellcheck.net/)我们的 Shell 脚本. + +所有带有 shell 脚本的项目都应使用此 GitLab CI / CD 作业: + +``` +shell check: + image: koalaman/shellcheck-alpine:stable + stage: test + before_script: + - shellcheck --version + script: + - shellcheck scripts/**/*.sh # path to your shell scripts +``` + +**提示:**默认情况下,ShellCheck 将使用[外壳检测](https://github.com/koalaman/shellcheck/wiki/SC2148#rationale)来确定使用中的外壳方言. 如果 shell 文件不在您的控制范围内,并且 ShellCheck 无法检测到方言,请使用`-s`标志指定它: `-s sh`或`-s bash` . + +### Formatting[](#formatting "Permalink") + +建议使用[shfmt](https://github.com/mvdan/sh#shfmt)工具来保持一致的格式. 我们根据《 [Google Shell 样式指南》设置](https://google.github.io/styleguide/shell.xml)外壳脚本的格式,因此以下`shfmt`调用应应用于项目的脚本文件: + +``` +shfmt -i 2 -ci -w scripts/**/*.sh +``` + +除了[Linting](#linting) GitLab CI / CD 作业外,所有带有 shell 脚本的项目也应使用此作业: + +``` +shfmt: + image: mvdan/shfmt:v3.1.0-alpine + stage: test + before_script: + - shfmt -version + script: + - shfmt -i 2 -ci -d scripts # path to your shell scripts +``` + +**提示:**默认情况下,shfmt 将使用类似于 ShellCheck 之一的[shell 检测](https://github.com/mvdan/sh#shfmt) ,并忽略以句点开头的文件. 要覆盖它,请使用`-ln`标志来指定 shell 方言: `-ln posix`或`-ln bash` . + +## Testing[](#testing "Permalink") + +**注意:**这是一项正在进行的工作. + +评估各种工具以自动测试 Shell 脚本(例如[BATS](https://github.com/bats-core/bats-core) )是一项[持续的工作](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64016) . + +## Code Review[](#code-review "Permalink") + +代码审查应根据以下条件执行: + +* [ShellCheck Checks list](https://github.com/koalaman/shellcheck/wiki/Checks) +* [Google Shell Style Guide](https://google.github.io/styleguide/shell.xml) +* [Shfmt formatting caveats](https://github.com/mvdan/sh#caveats) + +但是,建议采取的措施是使用上述工具并处理报告的违法行为. 这应该消除对代码审查的需要. + +* * * + +[Return to Development documentation](../README.html). \ No newline at end of file diff --git a/_book/docs/621.md b/_book/docs/621.md new file mode 100644 index 0000000000000000000000000000000000000000..f77b9e9c4bec190f0cdbe7756cfa8d45be8c7155 --- /dev/null +++ b/_book/docs/621.md @@ -0,0 +1,11 @@ +# Sidekiq debugging + +> 原文:[https://docs.gitlab.com/ee/development/sidekiq_debugging.html](https://docs.gitlab.com/ee/development/sidekiq_debugging.html) + +* [Log arguments to Sidekiq jobs](#log-arguments-to-sidekiq-jobs) + +# Sidekiq debugging[](#sidekiq-debugging "Permalink") + +## Log arguments to Sidekiq jobs[](#log-arguments-to-sidekiq-jobs "Permalink") + +此内容已移至[故障排除 Sidekiq 文档](../administration/troubleshooting/sidekiq.html) . \ No newline at end of file diff --git a/_book/docs/622.md b/_book/docs/622.md new file mode 100644 index 0000000000000000000000000000000000000000..05db0d7e7b118bb9db4271d62d022a870e867d48 --- /dev/null +++ b/_book/docs/622.md @@ -0,0 +1,509 @@ +# Sidekiq Style Guide + +> 原文:[https://docs.gitlab.com/ee/development/sidekiq_style_guide.html](https://docs.gitlab.com/ee/development/sidekiq_style_guide.html) + +* [ApplicationWorker](#applicationworker) +* [Dedicated Queues](#dedicated-queues) +* [Queue Namespaces](#queue-namespaces) +* [Idempotent Jobs](#idempotent-jobs) + * [Ensuring a worker is idempotent](#ensuring-a-worker-is-idempotent) + * [Declaring a worker as idempotent](#declaring-a-worker-as-idempotent) + * [Deduplication](#deduplication) +* [Job urgency](#job-urgency) + * [Latency sensitive jobs](#latency-sensitive-jobs) + * [Changing a queue’s urgency](#changing-a-queues-urgency) +* [Jobs with External Dependencies](#jobs-with-external-dependencies) +* [CPU-bound and Memory-bound Workers](#cpu-bound-and-memory-bound-workers) +* [Declaring a Job as CPU-bound](#declaring-a-job-as-cpu-bound) +* [Determining whether a worker is CPU-bound](#determining-whether-a-worker-is-cpu-bound) +* [Feature category](#feature-category) +* [Job weights](#job-weights) +* [Worker context](#worker-context) + * [Cron workers](#cron-workers) + * [Jobs scheduled in bulk](#jobs-scheduled-in-bulk) +* [Arguments logging](#arguments-logging) +* [Tests](#tests) +* [Sidekiq Compatibility across Updates](#sidekiq-compatibility-across-updates) + * [Changing the arguments for a worker](#changing-the-arguments-for-a-worker) + * [Remove an argument](#remove-an-argument) + * [Add an argument](#add-an-argument) + * [Multi-step deployment](#multi-step-deployment) + * [Parameter hash](#parameter-hash) + * [Removing workers](#removing-workers) + * [Renaming queues](#renaming-queues) + +# Sidekiq Style Guide[](#sidekiq-style-guide "Permalink") + +本文档概述了添加或修改 Sidekiq 工作程序时应遵循的各种准则. + +## ApplicationWorker[](#applicationworker "Permalink") + +All workers should include `ApplicationWorker` instead of `Sidekiq::Worker`, which adds some convenience methods and automatically sets the queue based on the worker’s name. + +## Dedicated Queues[](#dedicated-queues "Permalink") + +所有工作程序都应使用自己的队列,该队列将根据工作程序类名称自动设置. 对于名为`ProcessSomethingWorker`的工作程序,队列名称将为`process_something` . 如果不确定工人使用什么队列,可以使用`SomeWorker.queue`找到它. 几乎没有理由使用`sidekiq_options queue: :some_queue`手动覆盖队列名称. + +添加新队列后,运行`bin/rake gitlab:sidekiq:all_queues_yml:generate`来重新生成`app/workers/all_queues.yml`或`ee/app/workers/all_queues.yml`以便可以由[`sidekiq-cluster`](../administration/operations/extra_sidekiq_processes.html)拾取. + +## Queue Namespaces[](#queue-namespaces "Permalink") + +虽然不同的工作人员无法共享队列,但是他们可以共享队列名称空间. + +为工作程序定义队列名称空间可以启动 Sidekiq 进程,该进程自动为该工作空间中的所有工作程序处理作业,而无需显式列出其所有队列名称. 例如,如果由`sidekiq-cron`管理的所有工作人员都使用`cronjob`队列名称空间,那么我们可以专门针对此类计划的作业启动 Sidekiq 进程. 如果稍后添加使用`cronjob`命名空间的新工作程序,则 Sidekiq 进程也将自动为该工作程序选择作业(重新启动后),而无需更改任何配置. + +可以使用`queue_namespace` DSL 类方法设置队列名称空间: + +``` +class SomeScheduledTaskWorker + include ApplicationWorker + + queue_namespace :cronjob + + # ... +end +``` + +在后台,这会将`SomeScheduledTaskWorker.queue`设置为`cronjob:some_scheduled_task` . 常用的名称空间将具有自己的关注模块,可以轻松地将其包含在 worker 类中,并且可以设置队列名称空间以外的其他 Sidekiq 选项. 例如, `CronjobQueue`设置名称空间,但也禁用重试. + +`bundle exec sidekiq`是可感知名称空间的,当提供名称空间而不是`--queue` ( `-q` )选项中的简单队列名称时,它将自动侦听名称空间中的所有队列(技术上:所有以名称空间名称为前缀的队列) ,或`config/sidekiq_queues.yml`中的`:queues:`部分. + +请注意,应谨慎执行将工作程序添加到现有命名空间的操作,因为如果没有适当调整可用于处理命名空间的 Sidekiq 进程可用的资源,则额外的作业将占用已经存在的工作程序的资源. + +## Idempotent Jobs[](#idempotent-jobs "Permalink") + +众所周知,一项作业可能由于多种原因而失败. 例如,网络中断或错误. 为了解决此问题,Sidekiq 具有内置的重试机制,GitLab 中的大多数工作人员默认使用该机制. + +期望作业在失败后可以再次运行,而不会给应用程序或用户带来重大副作用,这就是 Sidekiq 鼓励作业具有[幂等性和事务性的原因](https://github.com/mperham/sidekiq/wiki/Best-Practices#2-make-your-job-idempotent-and-transactional) . + +通常,在以下情况下,可以将工人视为等幂的: + +* 它可以使用相同的参数安全地运行多次. +* 预期应用程序副作用仅发生一次(或第二次运行的副作用无效). + +一个很好的例子是缓存过期工作器. + +**注意:**如果队列中已经存在具有相同参数的未启动作业,则为等幂工作器调度的作业将自动进行[重复数据删除](#deduplication) . + +### Ensuring a worker is idempotent[](#ensuring-a-worker-is-idempotent "Permalink") + +确保使用以下共享示例通过工作程序测试: + +``` +include_examples 'an idempotent worker' do + it 'marks the MR as merged' do + # Using subject inside this block will process the job multiple times + subject + + expect(merge_request.state).to eq('merged') + end +end +``` + +直接使用`perform_multiple`方法而不是`job.perform` (此辅助方法将自动包含在 worker 中). + +### Declaring a worker as idempotent[](#declaring-a-worker-as-idempotent "Permalink") + +``` +class IdempotentWorker + include ApplicationWorker + + # Declares a worker is idempotent and can + # safely run multiple times. + idempotent! + + # ... +end +``` + +鼓励只具有`idempotent!` 即使在另一个类或模块中定义了`perform`方法,也要在最顶层的 worker 类中调用. + +**注意:**如果工人阶级没有被标记为幂等,那么警察将失败. 如果您不确定自己的工作可以安全地多次运行,请考虑跳过警察. + +### Deduplication[](#deduplication "Permalink") + +当队列中有另一个幂函数的作业入队而另一个未启动的作业时,GitLab 会删除第二个作业. 之所以跳过该工作,是因为首先安排的工作将完成相同的工作; 到第二个作业执行时,第一个作业什么也做不了. + +例如, `AuthorizedProjectsWorker`需要一个用户 ID. 当工作程序运行时,它将重新计算用户的授权. 每当操作有可能更改用户的授权时,GitLab 都会计划此作业. 如果将同一用户同时添加到两个项目,则如果第一个作业尚未开始,则可以跳过第二个作业,因为当第一个作业运行时,它将为两个项目创建授权. + +GitLab 不会跳过将来计划的作业,因为我们假设在计划执行作业时状态将已更改. + +[已经提出了](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/195)更多的[重复数据删除策略](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/195) . 如果您正在部署的员工可能会从其他策略中受益,请在问题中发表评论. + +如果自动重复数据删除会导致某些队列出现问题. 可以通过启用名为`disable_<queue name>_deduplication`的功能标志来暂时禁用此功能. 例如,要禁用`AuthorizedProjectsWorker`重复数据删除,我们将启用功能标记`disable_authorized_projects_deduplication` . + +从 ChatOps: + +``` +/chatops run feature set disable_authorized_projects_deduplication true +``` + +从 rails 控制台: + +``` +Feature.enable!(:disable_authorized_projects_deduplication) +``` + +## Job urgency[](#job-urgency "Permalink") + +作业可以设置一个`urgency`属性,可以是`:high` , `:low`或`:throttled` . 这些目标如下: + +| **Urgency** | **队列调度目标** | **执行延迟要求** | +| --- | --- | --- | +| `:high` | 10 秒 | 1 秒的 p50、10 秒的 p99 | +| `:low` | 1 分钟 | 最长运行时间为 5 分钟 | +| `:throttled` | None | 最长运行时间为 5 分钟 | + +要设置作业的紧急程度,请使用`urgency`类方法: + +``` +class HighUrgencyWorker + include ApplicationWorker + + urgency :high + + # ... +end +``` + +### Latency sensitive jobs[](#latency-sensitive-jobs "Permalink") + +如果立即安排大量后台作业,则在作业等待辅助节点可用时,可能会出现作业排队. 这是正常现象,它可以通过系统地处理流量高峰来赋予系统弹性. 但是,某些作业比其他作业对延迟更敏感. 这些工作的示例包括: + +1. 在推送到分支之后更新合并请求的作业. +2. 在推送到分支之后,该任务会使项目的已知分支的缓存无效. +3. 更改权限后,用户可以看到重新计算组和项目的作业. +4. 在状态更改为管道中的作业之后更新 CI 管道状态的作业. + +当这些作业被延迟时,用户可能会将延迟视为错误:例如,他们可以推送分支,然后尝试为该分支创建合并请求,但在 UI 中被告知该分支不存在. 我们认为这些工作很`urgency :high` + +做出额外的努力以确保这些作业在计划后的很短时间内启动. 但是,为了确保吞吐量,这些作业还具有非常严格的执行持续时间要求: + +1. 中位作业执行时间应少于 1 秒. +2. 99%的工作应在 10 秒内完成. + +如果一个工作人员不能满足这些期望,那么就不能将其视为`urgency :high`工作人员:考虑重新设计该工作人员,或在两个不同的工作人员之间拆分工作,其中一个工作`urgency :high`执行快速的`urgency :high`代码,另一个工作`urgency :low` ,它没有执行延迟要求(但也有较低的调度目标). + +### Changing a queue’s urgency[](#changing-a-queues-urgency "Permalink") + +在 GitLab.com,我们几个跑 Sidekiq [碎片](https://dashboards.gitlab.net/d/sidekiq-shard-detail/sidekiq-shard-detail) ,其中每一个代表一个特定类型的工作负载. + +更改队列的紧急性或添加新队列时,我们需要考虑新分片上的预期工作量. 请注意,如果我们要更改现有队列,那么也会对旧分片产生影响,但这始终会减少工作量. + +为此,我们要计算新分片的总执行时间和 RPS(吞吐量)的预期增长. 我们可以从以下获得这些值: + +* " [队列详细信息"仪表板](https://dashboards.gitlab.net/d/sidekiq-queue-detail/sidekiq-queue-detail)具有队列本身的值. 对于新队列,我们​​可以查找具有类似模式或在类似情况下安排的队列. +* [碎片详细信息仪表板](https://dashboards.gitlab.net/d/sidekiq-shard-detail/sidekiq-shard-detail)具有总执行时间和吞吐量(RPS). "分片利用率"面板将显示该分片当前是否有多余的容量. + +然后,我们可以计算我们要更改的队列的 RPS *平均运行时间(针对新作业的估算值),以查看新分片期望的 RPS 和执行时间的相对增加: + +``` +new_queue_consumption = queue_rps * queue_duration_avg +shard_consumption = shard_rps * shard_duration_avg + +(new_queue_consumption / shard_consumption) * 100 +``` + +如果我们预期增加**幅度小于 5%** ,则无需采取进一步措施. + +否则,请对合并请求 ping `@gitlab-org/scalability`并要求进行审查. + +## Jobs with External Dependencies[](#jobs-with-external-dependencies "Permalink") + +GitLab 应用程序中的大多数后台作业都与其他 GitLab 服务进行通信. 例如,PostgreSQL,Redis,Gitaly 和对象存储. 这些被视为作业的"内部"依赖性. + +但是,某些作业将依赖于外部服务才能成功完成. 一些示例包括: + +1. 调用用户配置的 Web 钩子的作业. +2. 将应用程序部署到用户配置的 k8s 集群的作业. + +这些作业具有"外部依赖性". 这对于后台处理群集的运行有多种重要的作用: + +1. 大多数外部依赖项(例如 Web 钩子)都不提供 SLO,因此我们不能保证这些作业的执行延迟. 由于我们无法保证执行延迟,因此无法确保吞吐量,因此,在高流量环境中,我们需要确保将具有外部依赖关系的作业与高紧急性作业分开,以确保这些队列上的吞吐量. +2. Errors in jobs with external dependencies have higher alerting thresholds as there is a likelihood that the cause of the error is external. + +``` +class ExternalDependencyWorker + include ApplicationWorker + + # Declares that this worker depends on + # third-party, external services in order + # to complete successfully + worker_has_external_dependencies! + + # ... +end +``` + +**注意:**请注意,一项工作既不能具有很高的紧迫性,又不能具有外部依赖性. + +## CPU-bound and Memory-bound Workers[](#cpu-bound-and-memory-bound-workers "Permalink") + +受 CPU 或内存资源限制约束的工作程序应使用`worker_resource_boundary`方法进行注释. + +大多数工作人员倾向于将大部分时间都花在阻止时间上,等待来自 Redis,PostgreSQL 和 Gitaly 等其他服务的网络响应. 由于 Sidekiq 是多线程环境,因此可以高并发地调度这些作业. + +但是,有些工人在 Ruby 中花费大量时间*在 CPU*运行逻辑上. Ruby MRI 不支持真正的多线程-它依赖[GIL](https://thoughtbot.com/blog/untangling-ruby-threads#the-global-interpreter-lock)来极大简化应用程序开发,无论托管该进程的计算机有多少核,一次仅允许一个进程中的一部分 Ruby 代码运行一次. 对于受 IO 约束的工作人员,这不是问题,因为大多数线程在基础库(位于 GIL 之外)中被阻止. + +如果许多线程试图同时运行 Ruby 代码,则将导致 GIL 争用,这将减慢所有进程的速度. + +在高流量的环境中,知道一个工作人员受 CPU 限制,可以使我们在具有较低并发性的其他队列中运行它. 这样可以确保最佳性能. + +同样,如果工作人员使用大量内存,则可以在定制的低并发,高内存队列上运行这些内存. + +请注意,受内存限制的工作程序会创建大量的 GC 工作负载,暂停时间为 10-50ms. 这将对工作人员的延迟要求产生影响. 因此, `memory`限制, `urgency :high`作业是不允许的,并且将使 CI 失败. 通常,不鼓励受`memory`限制的工作人员,应考虑处理工作的替代方法. + +如果工作程序需要大量的内存和 CPU 时间,则由于上述对高紧急性的内存绑定工作程序的限制,应将其标记为内存绑定. + +## Declaring a Job as CPU-bound[](#declaring-a-job-as-cpu-bound "Permalink") + +本示例说明如何将作业声明为受 CPU 约束. + +``` +class CPUIntensiveWorker + include ApplicationWorker + + # Declares that this worker will perform a lot of + # calculations on-CPU. + worker_resource_boundary :cpu + + # ... +end +``` + +## Determining whether a worker is CPU-bound[](#determining-whether-a-worker-is-cpu-bound "Permalink") + +我们使用以下方法来确定工作程序是否受 CPU 限制: + +* 在 Sidekiq 结构化 JSON 日志中,汇总工作`duration`和`cpu_s`字段. +* `duration` refers to the total job execution duration, in seconds +* `cpu_s`是从[`Process::CLOCK_THREAD_CPUTIME_ID`](https://www.rubydoc.info/stdlib/core/Process:clock_gettime)计数器派生的,它是作业在 CPU 上花费的时间的度量. +* 将`cpu_s`除以`duration`即可得到在 CPU 上花费的`duration`百分比. +* 如果该比例超过 33%,则认为该工作线程受 CPU 限制,因此应进行注释. +* 请注意,这些值不应用于较小的样本量,而应用于相当大的汇总. + +## Feature category[](#feature-category "Permalink") + +所有 Sidekiq 工作人员都必须定义一个已知的[特征类别](feature_categorization/index.html#sidekiq-workers) . + +## Job weights[](#job-weights "Permalink") + +某些作业的重量已声明. 仅在默认执行模式下运行 Sidekiq 时才使用此选项-使用[`sidekiq-cluster`](../administration/operations/extra_sidekiq_processes.html)不能计算权重. + +随着我们[朝在 Core 中使用`sidekiq-cluster`迈进](https://gitlab.com/gitlab-org/gitlab/-/issues/34396) ,新增加的工作人员无需指定权重. 他们可以简单地使用默认权重 1. + +## Worker context[](#worker-context "Permalink") + +版本历史 + +* 在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/9) . + +为了在日志中获得有关工作程序的更多信息,我们[以`ApplicationContext`的形式向工作](logging.html#logging-context-metadata-through-rails-or-grape-requests)添加[元数据](logging.html#logging-context-metadata-through-rails-or-grape-requests) . 在大多数情况下,从请求计划作业时,该上下文已经从请求中扣除并添加到计划的作业中. + +运行作业时,将还原计划时处于活动状态的上下文. 这会使上下文传播到正在运行的作业中计划的任何作业. + +所有这些意味着在大多数情况下,要将上下文添加到作业中,我们无需执行任何操作. + +但是,在某些情况下,计划作业时将不存在任何上下文,或者存在的上下文很可能不正确. 对于这些实例,我们添加了 Rubocop 规则以引起注意并避免日志中的元数据不正确. + +与大多数警察一样,有完全正当的理由禁用它们. 在这种情况下,可能来自请求的上下文是正确的. 或者,您可能已经以警察无法接受的方式指定了上下文. 无论如何,请在禁用警察时留下指向将使用哪个上下文的代码注释. + +当确实为上下文提供对象时,请确保已预先加载名称空间和项目的路由. 这可以通过使用来完成`.with_route`上所有定义范围`Routable`秒. + +### Cron workers[](#cron-workers "Permalink") + +对于 Cronjob 队列( `include CronjobQueue` )中的工作人员,将自动清除上下文,即使从请求中安排工作人员时也是如此. 我们这样做是为了避免从 cron worker 安排其他作业时出现不正确的元数据. + +Cron 工作人员自己在实例范围内运行,因此它们的作用域不限于应添加到上下文中的用户,名称空间,项目或其他资源. + +然而,他们往往安排*确实*需要方面的其他工作. + +这就是为什么需要在工作人员中某处显示上下文的原因. 可以通过在工作器内的某些位置使用以下方法之一来完成此操作: + +1. 在`with_context`帮助器中包装用于调度作业的代码: + + ``` + def perform + deletion_cutoff = Gitlab::CurrentSettings + .deletion_adjourned_period.days.ago.to_date + projects = Project.with_route.with_namespace + .aimed_for_deletion(deletion_cutoff) + + projects.find_each(batch_size: 100).with_index do |project, index| + delay = index * INTERVAL + + with_context(project: project) do + AdjournedProjectDeletionWorker.perform_in(delay, project.id) + end + end + end + ``` + +2. 使用提供上下文的批处理调度方法: + + ``` + def schedule_projects_in_batch(projects) + ProjectImportScheduleWorker.bulk_perform_async_with_contexts( + projects, + arguments_proc: -> (project) { project.id }, + context_proc: -> (project) { { project: project } } + ) + end + ``` + + 或者,在延迟调度时: + + ``` + diffs.each_batch(of: BATCH_SIZE) do |diffs, index| + DeleteDiffFilesWorker + .bulk_perform_in_with_contexts(index * 5.minutes, + diffs, + arguments_proc: -> (diff) { diff.id }, + context_proc: -> (diff) { { project: diff.merge_request.target_project } }) + end + ``` + +### Jobs scheduled in bulk[](#jobs-scheduled-in-bulk "Permalink") + +通常,在批量调度作业时,这些作业应具有单独的上下文而不是总体上下文. + +如果是这样的话, `bulk_perform_async`可以通过更换`bulk_perform_async_with_context`帮手,而不是`bulk_perform_in`使用`bulk_perform_in_with_context` . + +例如: + +``` + ProjectImportScheduleWorker.bulk_perform_async_with_contexts( + projects, + arguments_proc: -> (project) { project.id }, + context_proc: -> (project) { { project: project } } + ) +``` + +第一个参数中可枚举的每个对象分为两个块: + +* `arguments_proc` ,它需要返回作业需要调度的参数列表. + +* 需要返回带有作业上下文信息的哈希值的`context_proc` . + +## Arguments logging[](#arguments-logging "Permalink") + +当[`SIDEKIQ_LOG_ARGUMENTS`](../administration/troubleshooting/sidekiq.html#log-arguments-to-sidekiq-jobs)启用,Sidekiq 作业参数将被记录. + +默认情况下,记录的唯一参数是数字参数,因为其他类型的参数可能包含敏感信息. 要覆盖此参数,请在工作程序内部使用`loggable_arguments`并记录要记录的参数的索引. (此处不需要指定数字参数.) + +例如: + +``` +class MyWorker + include ApplicationWorker + + loggable_arguments 1, 3 + + # object_id will be logged as it's numeric + # string_a will be logged due to the loggable_arguments call + # string_b will be filtered from logs + # string_c will be logged due to the loggable_arguments call + def perform(object_id, string_a, string_b, string_c) + end +end +``` + +## Tests[](#tests "Permalink") + +与其他任何类一样,每个 Sidekiq 工作者都必须使用 RSpec 进行测试. 这些测试应放在`spec/workers` . + +## Sidekiq Compatibility across Updates[](#sidekiq-compatibility-across-updates "Permalink") + +请记住,Sidekiq 作业的参数在计划执行时存储在队列中. 在线更新期间,这可能会导致几种可能的情况: + +1. 该应用程序的较旧版本发布作业,该作业由升级的 Sidekiq 节点执行. +2. 作业在升级之前排队,但在升级之后执行. +3. 作业由运行较新版本应用程序的节点排队,但在运行较旧版本应用程序的节点上执行. + +### Changing the arguments for a worker[](#changing-the-arguments-for-a-worker "Permalink") + +作业需要在应用程序的连续版本之间向后和向前兼容. 在所有 Rails 和 Sidekiq 节点都具有更新的代码之前,添加或删除参数可能会在部署期间引起问题. + +#### Remove an argument[](#remove-an-argument "Permalink") + +**不要从`perform`函数中删除参数.** . 而是,使用以下方法: + +1. 提供默认值(通常为`nil` )并使用注释将参数标记为已弃用 +2. 停止在`perform_async`使用该参数. +3. 忽略 worker 类中的值,但是直到下一个主要版本才将其删除. + +在以下示例中,如果要删除`arg2` ,请首先设置`nil`默认值,然后更新调用`ExampleWorker.perform_async`位置. + +``` +class ExampleWorker + def perform(object_id, arg1, arg2 = nil) + # ... + end +end +``` + +#### Add an argument[](#add-an-argument "Permalink") + +有两种方法可以安全地向 Sidekiq 工作者添加新参数: + +1. Set up a [multi-step deployment](#multi-step-deployment) in which the new argument is first added to the worker +2. 将[参数哈希](#parameter-hash)用于其他参数. 这也许是最灵活的选择. + +##### Multi-step deployment[](#multi-step-deployment "Permalink") + +这种方法需要多个合并请求,并且在合并其他更改之前,要合并和部署第一个合并请求. + +1. 在初始合并请求中,使用默认值将参数添加到 worker 中: + + ``` + class ExampleWorker + def perform(object_id, new_arg = nil) + # ... + end + end + ``` + +2. 使用新参数合并和部署工作程序. +3. 在另一个合并请求中,更新`ExampleWorker.perform_async`调用以使用新参数. + +##### Parameter hash[](#parameter-hash "Permalink") + +如果现有工作人员已经利用参数哈希,则此方法将不需要多次部署. + +1. 在 worker 中使用参数散列以实现将来的灵活性: + + ``` + class ExampleWorker + def perform(object_id, params = {}) + # ... + end + end + ``` + +### Removing workers[](#removing-workers "Permalink") + +尽量避免在次要版本和修补程序版本中删除工作人员及其队列. + +在联机更新期间,实例可能有待处理的作业,而删除队列可能导致这些作业永远卡住. 如果您无法为这些 Sidekiq 作业编写迁移,请考虑仅在主要版本中删除该工作程序. + +### Renaming queues[](#renaming-queues "Permalink") + +出于同样的原因,遣散工人也很危险,因此在重命名队列时应格外小心. + +重命名队列时,请使用`sidekiq_queue_migrate`帮助程序迁移方法,如本示例所示: + +``` +class MigrateTheRenamedSidekiqQueue < ActiveRecord::Migration[5.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + sidekiq_queue_migrate 'old_queue_name', to: 'new_queue_name' + end + + def down + sidekiq_queue_migrate 'new_queue_name', to: 'old_queue_name' + end +end +``` \ No newline at end of file diff --git a/_book/docs/623.md b/_book/docs/623.md new file mode 100644 index 0000000000000000000000000000000000000000..d44367c4a82ef7d0c2d421048501fe7628c2e5f4 --- /dev/null +++ b/_book/docs/623.md @@ -0,0 +1,317 @@ +# SQL Query Guidelines + +> 原文:[https://docs.gitlab.com/ee/development/sql.html](https://docs.gitlab.com/ee/development/sql.html) + +* [Using LIKE Statements](#using-like-statements) +* [LIKE & Indexes](#like--indexes) +* [Reliably referencing database columns](#reliably-referencing-database-columns) + * [Good (prefer)](#good-prefer) + * [Bad (avoid)](#bad-avoid) +* [Plucking IDs](#plucking-ids) +* [Inherit from ApplicationRecord](#inherit-from-applicationrecord) +* [Use UNIONs](#use-unions) +* [Ordering by Creation Date](#ordering-by-creation-date) +* [Use WHERE EXISTS instead of WHERE IN](#use-where-exists-instead-of-where-in) +* [`.find_or_create_by` is not atomic](#find_or_create_by-is-not-atomic) + +# SQL Query Guidelines[](#sql-query-guidelines "Permalink") + +本文档介绍了使用 ActiveRecord / Arel 或原始 SQL 查询编写 SQL 查询时要遵循的各种准则. + +## Using LIKE Statements[](#using-like-statements "Permalink") + +搜索数据的最常见方法是使用`LIKE`语句. 例如,要获取标题以" WIP:"开头的所有问题,您可以编写以下查询: + +``` +SELECT * +FROM issues +WHERE title LIKE 'WIP:%'; +``` + +在 PostgreSQL 上, `LIKE`语句区分大小写. 要执行不区分大小写的`LIKE` ,必须改为使用`ILIKE` . + +要自动处理此问题,您应该使用 Arel 而不是原始 SQL 片段使用`LIKE`查询,因为 Arel 在 PostgreSQL 上自动使用`ILIKE` . + +``` +Issue.where('title LIKE ?', 'WIP:%') +``` + +您可以这样写: + +``` +Issue.where(Issue.arel_table[:title].matches('WIP:%')) +``` + +根据所使用的数据库,此处的`matches`生成正确的`LIKE` / `ILIKE`语句. + +如果您需要链接多个`OR`条件,也可以使用 Arel 进行此操作: + +``` +table = Issue.arel_table + +Issue.where(table[:title].matches('WIP:%').or(table[:foo].matches('WIP:%'))) +``` + +在 PostgreSQL 上,这将产生: + +``` +SELECT * +FROM issues +WHERE (title ILIKE 'WIP:%' OR foo ILIKE 'WIP:%') +``` + +## LIKE & Indexes[](#like--indexes "Permalink") + +在一开始使用带有通配符的`LIKE` / `ILIKE`时,PostgreSQL 将不使用任何索引. 例如,这将不使用任何索引: + +``` +SELECT * +FROM issues +WHERE title ILIKE '%WIP:%'; +``` + +因为`ILIKE`的值以通配符开头,所以数据库无法使用索引,因为它不知道从何处开始扫描索引. + +幸运的是,PostgreSQL *确实*提供了一种解决方案:trigram GIN 索引. 可以如下创建这些索引: + +``` +CREATE INDEX [CONCURRENTLY] index_name_here +ON table_name +USING GIN(column_name gin_trgm_ops); +``` + +这里的关键是`GIN(column_name gin_trgm_ops)`部分. 这将创建一个[GIN 索引](https://s0www0postgresql0org.icopy.site/docs/current/gin.html) ,并将操作符类设置为`gin_trgm_ops` . 这些索引*可*通过使用`ILIKE` / `LIKE` ,并可能导致大大改进的性能. 这些索引的缺点之一是它们很容易变大(取决于索引的数据量). + +为了使这些索引的命名保持一致,请使用以下命名模式: + +``` +index_TABLE_on_COLUMN_trigram +``` + +例如,一个`issues.title`的 GIN / `issues.title`索引将称为`index_issues_on_title_trigram` . + +Due to these indexes taking quite some time to be built they should be built concurrently. This can be done by using `CREATE INDEX CONCURRENTLY` instead of just `CREATE INDEX`. Concurrent indexes can *not* be created inside a transaction. Transactions for migrations can be disabled using the following pattern: + +``` +class MigrationName < ActiveRecord::Migration[4.2] + disable_ddl_transaction! +end +``` + +例如: + +``` +class AddUsersLowerUsernameEmailIndexes < ActiveRecord::Migration[4.2] + disable_ddl_transaction! + + def up + execute 'CREATE INDEX CONCURRENTLY index_on_users_lower_username ON users (LOWER(username));' + execute 'CREATE INDEX CONCURRENTLY index_on_users_lower_email ON users (LOWER(email));' + end + + def down + remove_index :users, :index_on_users_lower_username + remove_index :users, :index_on_users_lower_email + end +end +``` + +## Reliably referencing database columns[](#reliably-referencing-database-columns "Permalink") + +默认情况下,ActiveRecord 返回查询的数据库表中的所有列. 在某些情况下,可能需要自定义返回的行,例如: + +* 仅指定几列以减少从数据库返回的数据量. +* 包括`JOIN`关系中的列. +* 执行计算( `SUM` , `COUNT` ). + +在此示例中,我们指定列,但不指定其表: + +* `projects`表的`path` +* `merge_requests`表中的`user_id` + +查询: + +``` +# bad, avoid +Project.select("path, user_id").joins(:merge_requests) # SELECT path, user_id FROM "projects" ... +``` + +稍后,一项新功能将一个额外的列添加到`projects`表: `user_id` . 在部署期间,可能会在很短的时间范围内执行数据库迁移,但是尚未部署新版本的应用程序代码. 当上述查询在此期间执行时,查询将失败,并显示以下错误消息: `PG::AmbiguousColumn: ERROR: column reference "user_id" is ambiguous` + +问题是由从数据库中选择属性的方式引起的. 的`user_id`列存在于两个`users`和`merge_requests`表. 查询计划者无法确定在查找`user_id`列时要使用哪个表. + +在编写自定义的`SELECT`语句时,最好**使用表名明确指定列** . + +### Good (prefer)[](#good-prefer "Permalink") + +``` +Project.select(:path, 'merge_requests.user_id').joins(:merge_requests) + +# SELECT "projects"."path", merge_requests.user_id as user_id FROM "projects" ... +``` + +``` +Project.select(:path, :'merge_requests.user_id').joins(:merge_requests) + +# SELECT "projects"."path", "merge_requests"."id" as user_id FROM "projects" ... +``` + +使用 Arel( `arel_table` )的示例: + +``` +Project.select(:path, MergeRequest.arel_table[:user_id]).joins(:merge_requests) + +# SELECT "projects"."path", "merge_requests"."user_id" FROM "projects" ... +``` + +编写原始 SQL 查询时: + +``` +SELECT projects.path, merge_requests.user_id FROM "projects"... +``` + +When the raw SQL query is parameterized (needs escaping): + +``` +include ActiveRecord::ConnectionAdapters::Quoting + +""" +SELECT #{quote_table_name('projects')}.#{quote_column_name('path')}, #{quote_table_name('merge_requests')}.#{quote_column_name('user_id')} FROM ... +""" +``` + +### Bad (avoid)[](#bad-avoid "Permalink") + +``` +Project.select('id, path, user_id').joins(:merge_requests).to_sql + +# SELECT id, path, user_id FROM "projects" ... +``` + +``` +Project.select("path", "user_id").joins(:merge_requests) +# SELECT "projects"."path", "user_id" FROM "projects" ... + +# or + +Project.select(:path, :user_id).joins(:merge_requests) +# SELECT "projects"."path", "user_id" FROM "projects" ... +``` + +给定列列表后,ActiveRecord 尝试将参数与`projects`表中定义的列进行匹配,并自动在表名前添加前缀. 在这种情况下, `id`列不会有问题,但是`user_id`列可能返回意外数据: + +``` +Project.select(:id, :user_id).joins(:merge_requests) + +# Before deployment (user_id is taken from the merge_requests table): +# SELECT "projects"."id", "user_id" FROM "projects" ... + +# After deployment (user_id is taken from the projects table): +# SELECT "projects"."id", "projects"."user_id" FROM "projects" ... +``` + +## Plucking IDs[](#plucking-ids "Permalink") + +这还不够强调: **永远不要**使用 ActiveRecord 的`pluck`将一组值插入内存中,而只是将它们用作另一个查询的参数. 例如,这将使数据库**非常**悲伤: + +``` +projects = Project.all.pluck(:id) + +MergeRequest.where(source_project_id: projects) +``` + +相反,您可以只使用性能更好的子查询: + +``` +MergeRequest.where(source_project_id: Project.all.select(:id)) +``` + +*唯一*应该使用`pluck`时间是您实际上需要对 Ruby 本身中的值进行操作(例如,将它们写入文件中)时. 在几乎所有其他情况下,您都应该问自己"我不仅可以使用子查询吗?". + +根据我们的`CodeReuse/ActiveRecord`缔约方会议,您应仅在模型代码中使用诸如`pluck(:id)`或`pluck(:user_id)`之类的形式. 在前一种情况下,可以改用`ApplicationRecord` `.pluck_primary_key`帮助器方法. 在后者中,您应该在相关模型中添加一个小的辅助方法. + +## Inherit from ApplicationRecord[](#inherit-from-applicationrecord "Permalink") + +GitLab 代码库中的大多数模型应继承自`ApplicationRecord` ,而不是`ActiveRecord::Base` . 这样可以轻松添加辅助方法. + +在数据库迁移中创建的模型存在此规则的例外. 由于这些应与应用程序代码隔离,因此它们应继续从`ActiveRecord::Base`继承子类. + +## Use UNIONs[](#use-unions "Permalink") + +UNION 在大多数 Rails 应用程序中并不是很常用,但是它们非常强大且有用. 在大多数应用程序中,查询倾向于使用大量 JOIN 来获取相关数据或基于特定条件的数据,但是 JOIN 性能会随着所涉及数据的增长而迅速恶化. + +例如,如果要获取名称包含值*或*名称空间名称包含值的项目列表,大多数人会编写以下查询: + +``` +SELECT * +FROM projects +JOIN namespaces ON namespaces.id = projects.namespace_id +WHERE projects.name ILIKE '%gitlab%' +OR namespaces.name ILIKE '%gitlab%'; +``` + +使用大型数据库,此查询可能很容易花费大约 800 毫秒来运行. 使用 UNION,我们改为编写以下内容: + +``` +SELECT projects.* +FROM projects +WHERE projects.name ILIKE '%gitlab%' + +UNION + +SELECT projects.* +FROM projects +JOIN namespaces ON namespaces.id = projects.namespace_id +WHERE namespaces.name ILIKE '%gitlab%'; +``` + +反过来,此查询只需要 15 毫秒即可完成,同时返回完全相同的记录. + +这并不意味着您应该在所有地方开始使用 UNION,但是在查询中使用大量 JOIN 并根据联接的数据过滤掉记录时要牢记这一点. + +GitLab 带有一个`Gitlab::SQL::Union`类,可用于构建多个`ActiveRecord::Relation`对象的 UNION. 您可以按如下方式使用此类: + +``` +union = Gitlab::SQL::Union.new([projects, more_projects, ...]) + +Project.from("(#{union.to_sql}) projects") +``` + +## Ordering by Creation Date[](#ordering-by-creation-date "Permalink") + +根据记录的创建时间对记录进行排序时,只需按`id`列进行排序即可,而不必按`created_at`进行排序. 因为 ID 始终是唯一的,并且按照创建行的顺序递增,所以这将产生完全相同的结果. 这也意味着,由于默认情况下已经对`id`进行了索引,因此无需在`created_at`上添加索引以确保一致的性能. + +## Use WHERE EXISTS instead of WHERE IN[](#use-where-exists-instead-of-where-in "Permalink") + +虽然可以使用`WHERE IN`和`WHERE EXISTS`来生成相同的数据,但建议尽可能使用`WHERE EXISTS` . 尽管在许多情况下 PostgreSQL 可以很好地优化`WHERE IN`但在许多情况下`WHERE EXISTS`会好得多. + +在 Rails 中,您必须通过创建 SQL 片段来使用它: + +``` +Project.where('EXISTS (?)', User.select(1).where('projects.creator_id = users.id AND users.foo = X')) +``` + +然后,将按照以下内容生成查询: + +``` +SELECT * +FROM projects +WHERE EXISTS ( + SELECT 1 + FROM users + WHERE projects.creator_id = users.id + AND users.foo = X +) +``` + +## `.find_or_create_by` is not atomic[](#find_or_create_by-is-not-atomic "Permalink") + +`.find_or_create_by`和`.first_or_create`等方法的固有模式是它们不是原子的. 这意味着,它首先运行`SELECT` ,如果没有结果,则执行`INSERT` . 考虑到并发过程,因此存在竞争条件,这可能导致尝试插入两个相似的记录. 例如,这可能是不希望的,或者可能由于约束冲突而导致查询之一失败. + +使用事务不能解决此问题. + +为了解决这个问题,我们添加了`ApplicationRecord.safe_find_or_create_by` . + +可以像平常的`find_or_create_by`一样使用此方法,但是它将调用包装在*新*事务中,如果由于`ActiveRecord::RecordNotUnique`错误而失败,则将重试. + +为了能够使用此方法,请确保要在其上使用的模型继承自`ApplicationRecord` . \ No newline at end of file diff --git a/_book/docs/624.md b/_book/docs/624.md new file mode 100644 index 0000000000000000000000000000000000000000..fd065b1d6fd0c826a8634cc2013b0e14264b7e64 --- /dev/null +++ b/_book/docs/624.md @@ -0,0 +1,431 @@ +# Vue.js style guide + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/style/vue.html](https://docs.gitlab.com/ee/development/fe_guide/style/vue.html) + +* [Linting](#linting) +* [Basic Rules](#basic-rules) +* [Naming](#naming) +* [Alignment](#alignment) +* [Quotes](#quotes) +* [Props](#props) +* [Data](#data) +* [Directives](#directives) +* [Closing tags](#closing-tags) +* [Component usage within templates](#component-usage-within-templates) +* [Ordering](#ordering) +* [`:key`](#key) +* [Vue and Bootstrap](#vue-and-bootstrap) +* [The JavaScript/Vue Accord](#the-javascriptvue-accord) + +# Vue.js style guide[](#vuejs-style-guide "Permalink") + +## Linting[](#linting "Permalink") + +我们默认为[eslint-vue-plugin](https://github.com/vuejs/eslint-plugin-vue) ,其`plugin:vue/recommended` . 请检查此[规则](https://github.com/vuejs/eslint-plugin-vue#bulb-rules)以获取更多文档. + +## Basic Rules[](#basic-rules "Permalink") + +1. 该服务具有自己的文件 +2. 商店有自己的文件 +3. 使用捆绑文件中的函数实例化 Vue 组件: + + ``` + // bad + class { + init() { + new Component({}) + } + } + + // good + document.addEventListener('DOMContentLoaded', () => new Vue({ + el: '#element', + components: { + componentName + }, + render: createElement => createElement('component-name'), + })); + ``` + +4. 不要将单例用于服务或商店 + + ``` + // bad + class Store { + constructor() { + if (!this.prototype.singleton) { + // do something + } + } + } + + // good + class Store { + constructor() { + // do something + } + } + ``` + +5. 将`.vue`用于 Vue 模板. 不要在 HAML 中使用`%template` . + +## Naming[](#naming "Permalink") + +1. **扩展名** :对 Vue 组件使用`.vue`扩展名. 不要将`.js`用作文件扩展名( [#34371](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34371) ). +2. **参考命名** :将 PascalCase 用于其实例: + + ``` + // bad + import cardBoard from 'cardBoard.vue' + + components: { + cardBoard, + }; + + // good + import CardBoard from 'cardBoard.vue' + + components: { + CardBoard, + }; + ``` + +3. **道具命名:**避免使用 DOM 组件道具名称. +4. **道具命名:**使用 kebab-case 代替 camelCase 在模板中提供道具. + + ``` + // bad + <component class="btn"> + + // good + <component css-class="btn"> + + // bad + <component myProp="prop" /> + + // good + <component my-prop="prop" /> + ``` + +## Alignment[](#alignment "Permalink") + +1. 对于模板方法,请遵循以下对齐方式: + + 1. 具有多个属性,所有属性都应换行: + + ``` + // bad + <component v-if="bar" + param="baz" /> + + <button class="btn">Click me</button> + + // good + <component + v-if="bar" + param="baz" + /> + + <button class="btn"> + Click me + </button> + ``` + + 2. 如果只有一个属性,则标签可以是内联的: + + ``` + // good + <component bar="bar" /> + + // good + <component + bar="bar" + /> + + // bad + <component + bar="bar" /> + ``` + +## Quotes[](#quotes "Permalink") + +1. 对于所有其他 JS,请始终在模板内使用双引号`"`在模板内使用单引号`'` . + + ``` + // bad + template: ` + <button :class='style'>Button</button> + ` + + // good + template: ` + <button :class="style">Button</button> + ` + ``` + +## Props[](#props "Permalink") + +1. 道具应声明为对象 + + ``` + // bad + props: ['foo'] + + // good + props: { + foo: { + type: String, + required: false, + default: 'bar' + } + } + ``` + +2. 声明道具时应始终提供必需的钥匙 + + ``` + // bad + props: { + foo: { + type: String, + } + } + + // good + props: { + foo: { + type: String, + required: false, + default: 'bar' + } + } + ``` + +3. 如果不需要道具,则应提供默认密钥. *注意:*在某些情况下,我们需要检查属性的存在. 在这些上,不应提供默认密钥. + + ``` + // good + props: { + foo: { + type: String, + required: false, + } + } + + // good + props: { + foo: { + type: String, + required: false, + default: 'bar' + } + } + + // good + props: { + foo: { + type: String, + required: true + } + } + ``` + +## Data[](#data "Permalink") + +1. `data`方法应始终是一个函数 + + ``` + // bad + data: { + foo: 'foo' + } + + // good + data() { + return { + foo: 'foo' + }; + } + ``` + +## Directives[](#directives "Permalink") + +1. 速记`@`优先于`v-on` + + ``` + // bad + <component v-on:click="eventHandler"/> + + // good + <component @click="eventHandler"/> + ``` + +2. 速记`:`优于`v-bind` + + ``` + // bad + <component v-bind:class="btn"/> + + // good + <component :class="btn"/> + ``` + +3. Shorthand `#` is preferable over `v-slot` + + ``` + // bad + <template v-slot:header></template> + + // good + <template #header></template> + ``` + +## Closing tags[](#closing-tags "Permalink") + +1. 首选自闭合组件标签 + + ``` + // bad + <component></component> + + // good + <component /> + ``` + +## Component usage within templates[](#component-usage-within-templates "Permalink") + +1. 在模板中使用组件时,将组件的 kebab 命名的名称优先于其他样式 + + ``` + // bad + <MyComponent /> + + // good + <my-component /> + ``` + +## Ordering[](#ordering "Permalink") + +1. `.vue`文件中的标记顺序 + + ``` + <script> + // ... + </script> + + <template> + // ... + </template> + + // We don't use scoped styles but there are few instances of this + <style> + // ... + </style> + ``` + +2. Vue 组件中[的属性](https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/order-in-components.md) :检查[组件 rule 中的属性顺序](https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/order-in-components.md) . + +## `:key`[](#key "Permalink") + +使用`v-for`您需要为每个项目提供*唯一的* `:key`属性. + +1. 如果要迭代的数组元素具有唯一的`id` ,则建议使用它: + + ``` + <div + v-for="item in items" + :key="item.id" + > + <!-- content --> + </div> + ``` + +2. 当要迭代的元素没有唯一 ID 时,可以将数组索引用作`:key`属性 + + ``` + <div + v-for="(item, index) in items" + :key="index" + > + <!-- content --> + </div> + ``` + +3. 当将`v-for`与`template`并且有多个子元素时, `:key`值必须唯一. 建议使用`kebab-case`名称空间. + + ``` + <template v-for="(item, index) in items"> + <span :key="`span-${index}`"></span> + <button :key="`button-${index}`"></button> + </template> + ``` + +4. 处理嵌套`v-for`使用与上述相同的准则. + + ``` + <div + v-for="item in items" + :key="item.id" + > + <span + v-for="element in array" + :key="element.id" + > + <!-- content --> + </span> + </div> + ``` + +有用的链接: + +1. [`key`](https://vuejs.org/v2/guide/list.html#key) +2. [Vue Style Guide: Keyed v-for](https://vuejs.org/v2/style-guide/#Keyed-v-for-essential) + +## Vue and Bootstrap[](#vue-and-bootstrap "Permalink") + +1. 工具提示:请勿依赖 Vue 组件的`has-tooltip`类名称 + + ``` + // bad + <span + class="has-tooltip" + title="Some tooltip text"> + Text + </span> + + // good + <span + v-tooltip + title="Some tooltip text"> + Text + </span> + ``` + +2. 工具提示:使用工具提示时,请包含工具提示指令`./app/assets/javascripts/vue_shared/directives/tooltip.js` + +3. 不要更改`data-original-title` . + + ``` + // bad + <span data-original-title="tooltip text">Foo</span> + + // good + <span title="tooltip text">Foo</span> + + $('span').tooltip('_fixTitle'); + ``` + +## The JavaScript/Vue Accord[](#the-javascriptvue-accord "Permalink") + +该协议的目的是确保我们都在同一页面上. + +1. 编写 Vue 时,您可能无法在应用程序中使用 jQuery. + 1. 如果您需要从 DOM 抓取数据,则可以在引导应用程序以使用`dataset`抓取数据属性时查询 DOM 1 次. 您可以在没有 jQuery 的情况下执行此操作. + 2. 您可以[按照 docs 中的此示例](https://vuejs.org/v2/examples/select2.html)在 Vue.js 中使用 jQuery 依赖关系. + 3. 如果需要在 Vue 应用程序内部侦听外部 jQuery 事件,则可以使用 jQuery 事件侦听器. + 4. 我们将避免在不需要时添加新的 jQuery 事件. 与其添加新的 jQuery 事件,不如看看[执行相同任务的不同方法](https://vuejs.org/v2/api/#vm-emit) . +2. 您可以一次引导`window`对象,同时引导您的应用程序以获取应用程序特定的数据(例如, `scrollTo`可以随时访问). 在应用程序引导期间执行此访问. +3. 您可能会临时需要立即但不符合我们标准的代码来编写技术债,以备以后重构. 维护人员首先要对技术债务保持满意. 应该为该技术债务创建一个问题,以便对其进行进一步评估和讨论. 在接下来的几个月中,您应该解决该技术债务,其优先级由维护者确定. +4. 在产生技术债务时,您必须事先为该代码编写测试,并且这些测试可能不会被重写. 例如,将 jQuery 测试重写为 Vue 测试. +5. 您可以选择将 VueX 用作集中式状态管理. 如果选择不使用 VueX,则必须使用可以在[Vue.js 文档中](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch)找到的*存储模式* . +6. 选择集中式状态管理解决方案后,必须将其用于整个应用程序. 即不要混淆并匹配您的状态管理解决方案. \ No newline at end of file diff --git a/_book/docs/625.md b/_book/docs/625.md new file mode 100644 index 0000000000000000000000000000000000000000..68e84e913b731dad9bb98ef0e0304cd36cb5228a --- /dev/null +++ b/_book/docs/625.md @@ -0,0 +1,141 @@ +# Instrumenting Ruby code + +> 原文:[https://docs.gitlab.com/ee/development/instrumentation.html](https://docs.gitlab.com/ee/development/instrumentation.html) + +* [Instrumenting Methods](#instrumenting-methods) + * [Examples](#examples) + * [Checking Instrumented Methods](#checking-instrumented-methods) +* [Instrumenting Ruby Blocks](#instrumenting-ruby-blocks) +* [Tracking Custom Events](#tracking-custom-events) + +# Instrumenting Ruby code[](#instrumenting-ruby-code "Permalink") + +[GitLab Performance Monitoring](../administration/monitoring/performance/index.html)可以检测 Ruby 代码的方法和自定义块. 方法检测是基于块的检测的主要检测形式,仅当我们想深入到方法中特定代码区域时才使用. + +如果要跟踪产品使用模式,请参考[遥测](telemetry/index.html) . + +## Instrumenting Methods[](#instrumenting-methods "Permalink") + +使用`Gitlab::Metrics::Instrumentation`模块可以完成检测方法. 该模块提供了几种可用于检测代码的方法: + +* `instrument_method` :检测单个类方法. +* `instrument_instance_method` :检测单个实例方法. +* `instrument_class_hierarchy` :给定一个 Class,此方法将递归地检测所有子类(类方法和实例方法). +* `instrument_methods` :检测模块的所有公共和私有类方法. +* `instrument_instance_methods` :检测模块的所有公共和私有实例方法. + +为了消除键入完整的`Gitlab::Metrics::Instrumentation`命名空间的需要,您可以使用`configure`类方法. 通过传递`Gitlab::Metrics::Instrumentation`作为其参数时,此方法仅产生提供的块. 一个例子: + +``` +Gitlab::Metrics::Instrumentation.configure do |conf| + conf.instrument_method(Foo, :bar) + conf.instrument_method(Foo, :baz) +end +``` + +通常,使用此方法优于直接调用各种检测方法. + +方法检测应添加到初始化程序`config/initializers/zz_metrics.rb` . + +### Examples[](#examples "Permalink") + +检测单个方法: + +``` +Gitlab::Metrics::Instrumentation.configure do |conf| + conf.instrument_method(User, :find_by) +end +``` + +检测整个类的层次结构: + +``` +Gitlab::Metrics::Instrumentation.configure do |conf| + conf.instrument_class_hierarchy(ActiveRecord::Base) +end +``` + +检测所有公共类方法: + +``` +Gitlab::Metrics::Instrumentation.configure do |conf| + conf.instrument_methods(User) +end +``` + +### Checking Instrumented Methods[](#checking-instrumented-methods "Permalink") + +检查一种方法是否已被检测的最简单方法是检查其源位置. 例如: + +``` +method = Banzai::Renderer.method(:render) + +method.source_location +``` + +如果源位置指向`lib/gitlab/metrics/instrumentation.rb` ,则说明该方法已经过检测. + +如果使用的是 Pry,则可以使用`$`命令显示方法的源代码(及其源位置),这比运行上面的 Ruby 代码容易. 如果是上述片段,请运行以下代码: + +* `$ Banzai::Renderer.render` + +这将打印出以下内容: + +``` +From: /path/to/your/gitlab/lib/gitlab/metrics/instrumentation.rb @ line 148: +Owner: #<Module:0x0055f0865c6d50> +Visibility: public +Number of lines: 21 + +def #{name}(#{args_signature}) + if trans = Gitlab::Metrics::Instrumentation.transaction + trans.measure_method(#{label.inspect}) { super } + else + super + end +end +``` + +## Instrumenting Ruby Blocks[](#instrumenting-ruby-blocks "Permalink") + +通过调用`Gitlab::Metrics.measure`并将其传递给块来完成对 Ruby 代码块的测量. 例如: + +``` +Gitlab::Metrics.measure(:foo) do + ... +end +``` + +执行该块并将执行时间存储为当前运行的事务中的一组字段. 如果不存在事务,则不进行任何测量就产生该块. + +测量一个块的三个值: + +* 经过的实时时间,存储在`NAME_real_time` . +* The CPU time elapsed, stored in `NAME_cpu_time`. +* 通话次数,存储在`NAME_call_count` . + +实时和 CPU 计时均以毫秒为单位. + +多次调用同一块将导致最终值是所有单个值的总和. 以下面的代码为例: + +``` +3.times do + Gitlab::Metrics.measure(:sleep) do + sleep 1 + end +end +``` + +在这里, `sleep_real_time`的最终值为`3` , *而不是* `1` . + +## Tracking Custom Events[](#tracking-custom-events "Permalink") + +除了检测代码,GitLab Performance Monitoring 还支持跟踪自定义事件. 这主要用于跟踪业务指标,例如 Git 推送数,存储库导入等. + +要跟踪自定义事件,只需调用`Gitlab::Metrics.add_event`传递事件名称和一组自定义(可选)标签. 例如: + +``` +Gitlab::Metrics.add_event(:user_login, email: current_user.email) +``` + +事件名称应为动词,例如`push_repository`和`remove_branch` . \ No newline at end of file diff --git a/_book/docs/626.md b/_book/docs/626.md new file mode 100644 index 0000000000000000000000000000000000000000..2102163cbf7bf16eb747524235ab39e7a3270be7 --- /dev/null +++ b/_book/docs/626.md @@ -0,0 +1,67 @@ +# Testing standards and style guidelines + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/](https://docs.gitlab.com/ee/development/testing_guide/) + +* [Overview](#overview) +* [Testing levels](#testing-levels) +* [Testing best practices](#testing-best-practices) +* [Frontend testing standards and style guidelines](#frontend-testing-standards-and-style-guidelines) +* [Flaky tests](#flaky-tests) +* [GitLab tests in the Continuous Integration (CI) context](#gitlab-tests-in-the-continuous-integration-ci-context) +* [Review apps](#review-apps) +* [Testing Rake tasks](#testing-rake-tasks) +* [End-to-end tests](#end-to-end-tests) +* [Migrations tests](#migrations-tests) + +# Testing standards and style guidelines[](#testing-standards-and-style-guidelines "Permalink") + +本文档介绍了自动测试 GitLab 项目的各种指南和最佳实践. + +它是对[Thoughtbot 测试风格指南](https://github.com/thoughtbot/guides/tree/master/style/testing)的*扩展* . 如果本指南定义的规则与 Thoughtbot 指南相抵触,则以本指南为准. 可能会逐字重复某些准则以强调其重要性. + +## Overview[](#overview "Permalink") + +GitLab 建立在[Ruby on Rails](https://rubyonrails.org/)之上,并且我们将[RSpec](https://github.com/rspec/rspec-rails#feature-specs)用于所有后端测试,而[Capybara](https://github.com/teamcapybara/capybara)用于端到端集成测试. 在前端,我们将[Jest](https://jestjs.io/)和[Karma](http://karma-runner.github.io/) / [Jasmine](https://jasmine.github.io/)用于 JavaScript 单元和集成测试. + +以下是两篇很棒的文章,每个人都应该阅读它们,以了解自动化测试的含义以及其原理是什么: + +* [五因素测试](https://madeintandem.com/blog/five-factor-testing/) :为什么我们需要测试? +* [自动化测试的原则:测试](https://www.lihaoyi.com/post/PrinciplesofAutomatedTesting.html)级别. 确定测试的优先级. 测试费用. + +## [Testing levels](testing_levels.html)[](#testing-levels "Permalink") + +Learn about the different testing levels, and how to decide at what level your changes should be tested. + +## [Testing best practices](best_practices.html)[](#testing-best-practices "Permalink") + +关于编写良好测试的所有知识,包括:测试设计,RSpec,FactoryBot,系统测试,参数化测试等. + +## [Frontend testing standards and style guidelines](frontend_testing.html)[](#frontend-testing-standards-and-style-guidelines "Permalink") + +您应该知道的有关如何编写良好的前端测试的所有知识:业力,测试承诺,存根等. + +## [Flaky tests](flaky_tests.html)[](#flaky-tests "Permalink") + +什么是片状测试,我们遇到的不同类型的片状测试,以及我们如何处理它们. + +## [GitLab tests in the Continuous Integration (CI) context](ci.html)[](#gitlab-tests-in-the-continuous-integration-ci-context "Permalink") + +GitLab 测试套件如何在 CI 上下文中运行:设置,缓存,工件,并行化,监视. + +## [Review apps](review_apps.html)[](#review-apps "Permalink") + +如何为 GitLab CE / EE 设置评论应用程序以及如何使用它们. + +## [Testing Rake tasks](testing_rake_tasks.html)[](#testing-rake-tasks "Permalink") + +您应该了解的有关如何测试 Rake 任务的所有知识. + +## [End-to-end tests](end_to_end/index.html)[](#end-to-end-tests "Permalink") + +您应该了解有关如何使用[GitLab QA](https://gitlab.com/gitlab-org/gitlab-qa)测试框架进行端到端测试的所有知识. + +## [Migrations tests](testing_migrations_guide.html)[](#migrations-tests "Permalink") + +您应该了解的有关如何测试迁移的一切. + +[Return to Development documentation](../README.html) \ No newline at end of file diff --git a/_book/docs/627.md b/_book/docs/627.md new file mode 100644 index 0000000000000000000000000000000000000000..cda06bf92e420dc71d74fdd4d315c939bfe39b1f --- /dev/null +++ b/_book/docs/627.md @@ -0,0 +1,120 @@ +# Flaky tests + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/flaky_tests.html](https://docs.gitlab.com/ee/development/testing_guide/flaky_tests.html) + +* [What’s a flaky test?](#whats-a-flaky-test) +* [Quarantined tests](#quarantined-tests) + * [Quarantine tests on the CI](#quarantine-tests-on-the-ci) +* [Automatic retries and flaky tests detection](#automatic-retries-and-flaky-tests-detection) +* [Problems we had in the past at GitLab](#problems-we-had-in-the-past-at-gitlab) + * [Time-sensitive flaky tests](#time-sensitive-flaky-tests) + * [Array order expectation](#array-order-expectation) + * [Feature tests](#feature-tests) + * [Capybara viewport size related issues](#capybara-viewport-size-related-issues) + * [Capybara JS driver related issues](#capybara-js-driver-related-issues) + * [PhantomJS / WebKit related issues](#phantomjs--webkit-related-issues) + * [Capybara expectation times out](#capybara-expectation-times-out) +* [Resources](#resources) + +# Flaky tests[](#flaky-tests "Permalink") + +## What’s a flaky test?[](#whats-a-flaky-test "Permalink") + +这个测试有时会失败,但是如果您重试了多次,它最终会通过. + +## Quarantined tests[](#quarantined-tests "Permalink") + +当`master`的测试频繁失败时,应创建[〜" master:broken"问题](https://about.gitlab.com/handbook/engineering/workflow/#broken-master) . 如果无法及时修复测试,则会影响所有开发人员的工作效率,因此应通过分配`:quarantine`元数据将其放入隔离`:quarantine` . + +这意味着除非使用`--tag quarantine`运行,否则它将被跳过: + +``` +bin/rspec --tag quarantine +``` + +**在对隔离进行测试之前,应确保存在〜" master:broken"问题,这样它才不会永远留在隔离区.** + +Once a test is in quarantine, there are 3 choices: + +* 测试应该固定(即摆脱其脆弱性)吗? +* 是否应将测试移至较低级别的测试? +* 是否应该完全删除该测试(例如,因为已经有一个较低级别的测试,或者它正在复制另一个相同级别的测试,或者它测试的太多等等)? + +### Quarantine tests on the CI[](#quarantine-tests-on-the-ci "Permalink") + +隔离测试在允许失败的专用作业中在 CI 上运行: + +* `rspec-pg-quarantine` (CE 和 EE) +* `rspec-pg-quarantine-ee` (仅适用于 EE) + +## Automatic retries and flaky tests detection[](#automatic-retries-and-flaky-tests-detection "Permalink") + +在 CI 上,我们使用[RSpec :: Retry](https://github.com/NoRedInk/rspec-retry)自动重试失败的示例几次(有关准确的重试次数,请参阅[`spec/spec_helper.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/spec_helper.rb) ). + +我们还使用自制的`RspecFlaky::Listener`侦听`RspecFlaky::Listener` ,该`RspecFlaky::Listener`将`RspecFlaky::Listener`示例记录在`master`上的 JSON 报告文件中( `retrieve-tests-metadata`和`update-tests-metadata`作业). + +这最初是在以下[网址中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13021)实现的: [https](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13021) : [//gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13021](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13021) . + +如果要在本地启用重试,则可以使用`RETRIES`环境变量. 例如`RETRIES=1 bin/rspec ...`将重试失败的示例一次. + +## Problems we had in the past at GitLab[](#problems-we-had-in-the-past-at-gitlab "Permalink") + +* [`rspec-retry` is biting us when some API specs fail](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29242): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9825](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9825) +* [Sporadic RSpec failures due to `PG::UniqueViolation`](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28307#note_24958837): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9846](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9846) + * Follow-up: [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10688](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10688) + * [Capybara.reset_session! should be called before requests are blocked](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33779): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12224](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12224) +* FFaker 生成测试尚未准备就绪的时髦数据(测试应该是可预测的,所以很糟糕!): + * [使`spec/mailers/notify_spec.rb`更加健壮](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20121) : [https](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10015) : [`spec/mailers/notify_spec.rb`](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20121) + * [`spec/requests/api/commits_spec.rb`暂时失败](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/27988#note_25342521) : [https](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9944) : [`spec/requests/api/commits_spec.rb`](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/27988#note_25342521) + * [用序列替换 FFaker 工厂数据](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29643) : [https](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10184) : [//gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10184](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29643) + * [spec / finders / issues_finder_spec.rb 中的暂时失败](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30211#note_26707685) : [https](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10404) : [//gitlab.com/gitlab-org/gitlab-foss/-//merge_requests/10404](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30211#note_26707685) + +### Time-sensitive flaky tests[](#time-sensitive-flaky-tests "Permalink") + +* [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10046](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10046) +* [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10306](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10306) + +### Array order expectation[](#array-order-expectation "Permalink") + +* [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10148](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10148) + +### Feature tests[](#feature-tests "Permalink") + +* [Be sure to create all the data the test need before starting exercise](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/32622#note_31128195): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12059](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12059) +* [Bis](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34609#note_34048715): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12604](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12604) +* [Bis](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34698#note_34276286): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12664](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12664) +* [Assert against the underlying database state instead of against a page’s content](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/31437): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10934](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10934) +* 在 JS 测试中,当元素在 Capybara 发送点击的确切时间移动时,移动元素会导致 Capybara 误点击 + * [由于窗口大小和滚动位置,下拉菜单向上或向下渲染](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17660) + * [延迟加载的图像可能导致水豚误点击](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18713) +* [Triggering JS events before the event handlers are set up](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18742) +* [Wait for the image to be lazy-loaded when asserting on a Markdown image’s `src` attribute](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25408) + +#### Capybara viewport size related issues[](#capybara-viewport-size-related-issues "Permalink") + +* [Transient failure of spec/features/issues/filtered_search/filter_issues_spec.rb](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29241#note_26743936): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10411](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10411) + +#### Capybara JS driver related issues[](#capybara-js-driver-related-issues "Permalink") + +* [Don’t wait for AJAX when no AJAX request is fired](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30461): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10454](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10454) +* [Bis](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34647): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12626](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12626) + +#### PhantomJS / WebKit related issues[](#phantomjs--webkit-related-issues "Permalink") + +* 记忆在屋顶! (TL; DR:加载图像但阻止图像请求!): [https](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12003) : [//gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12003](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12003) + +#### Capybara expectation times out[](#capybara-expectation-times-out "Permalink") + +* [Test imports a project (via Sidekiq) that is growing over time, leading to timeouts when the import takes longer than 60 seconds](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22599) + +## Resources[](#resources "Permalink") + +* [Flaky Tests: Are You Sure You Want to Rerun Them?](https://semaphoreci.com/blog/2017/04/20/flaky-tests.html) +* [How to Deal With and Eliminate Flaky Tests](https://semaphoreci.com/community/tutorials/how-to-deal-with-and-eliminate-flaky-tests) +* [Tips on Treating Flakiness in your Rails Test Suite](https://semaphoreci.com/blog/2017/08/03/tips-on-treating-flakiness-in-your-test-suite.html) +* [‘Flaky’ tests: a short story](https://www.ombulabs.com/blog/rspec/continuous-integration/how-to-track-down-a-flaky-test.html) +* [Using Insights to Discover Flaky, Slow, and Failed Tests](https://s0circleci0com.icopy.site/blog/using-insights-to-discover-flaky-slow-and-failed-tests/) + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/_book/docs/628.md b/_book/docs/628.md new file mode 100644 index 0000000000000000000000000000000000000000..a2976829b0350daa727a26cde2ad7c96eddea853 --- /dev/null +++ b/_book/docs/628.md @@ -0,0 +1,940 @@ +# Frontend testing standards and style guidelines + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/frontend_testing.html](https://docs.gitlab.com/ee/development/testing_guide/frontend_testing.html) + +* [Vue.js testing](#vuejs-testing) +* [Jest](#jest) +* [Karma test suite](#karma-test-suite) + * [When should I use Jest over Karma?](#when-should-i-use-jest-over-karma) + * [Differences to Karma](#differences-to-karma) + * [Limitations of jsdom](#limitations-of-jsdom) + * [Debugging Jest tests](#debugging-jest-tests) + * [Timeout error](#timeout-error) +* [What and how to test](#what-and-how-to-test) + * [Don’t test the library](#dont-test-the-library) + * [Don’t test your mock](#dont-test-your-mock) + * [Follow the user](#follow-the-user) +* [Common practices](#common-practices) + * [How to query DOM elements](#how-to-query-dom-elements) + * [Naming unit tests](#naming-unit-tests) + * [Testing promises](#testing-promises) + * [Manipulating Time](#manipulating-time) + * [`setTimeout()` / `setInterval()` in application](#settimeout--setinterval-in-application) + * [Waiting in tests](#waiting-in-tests) + * [Promises and Ajax calls](#promises-and-ajax-calls) + * [Vue rendering](#vue-rendering) + * [Events](#events) + * [Ensuring that tests are isolated](#ensuring-that-tests-are-isolated) + * [Jest best practices](#jest-best-practices) + * [Prefer `toBe` over `toEqual` when comparing primitive values](#prefer-tobe-over-toequal-when-comparing-primitive-values) + * [Prefer more befitting matchers](#prefer-more-befitting-matchers) + * [Avoid using `toBeTruthy` or `toBeFalsy`](#avoid-using-tobetruthy-or-tobefalsy) + * [Tricky `toBeDefined` matcher](#tricky-tobedefined-matcher) + * [Avoid using `setImmediate`](#avoid-using-setimmediate) +* [Factories](#factories) +* [Mocking Strategies with Jest](#mocking-strategies-with-jest) + * [Stubbing and Mocking](#stubbing-and-mocking) + * [Manual module mocks](#manual-module-mocks) + * [Where should I put manual mocks?](#where-should-i-put-manual-mocks) + * [Manual mock examples](#manual-mock-examples) + * [Keep mocks light](#keep-mocks-light) + * [Additional mocking techniques](#additional-mocking-techniques) +* [Running Frontend Tests](#running-frontend-tests) + * [Live testing and focused testing – Jest](#live-testing-and-focused-testing----jest) + * [Live testing and focused testing – Karma](#live-testing-and-focused-testing----karma) +* [Frontend test fixtures](#frontend-test-fixtures) +* [Data-driven tests](#data-driven-tests) +* [Gotchas](#gotchas) + * [RSpec errors due to JavaScript](#rspec-errors-due-to-javascript) +* [Overview of Frontend Testing Levels](#overview-of-frontend-testing-levels) +* [Test helpers](#test-helpers) + * [Vuex Helper: `testAction`](#vuex-helper-testaction) + * [Wait until Axios requests finish](#wait-until-axios-requests-finish) +* [Testing with older browsers](#testing-with-older-browsers) + * [BrowserStack](#browserstack) + * [Firefox](#firefox) + * [macOS](#macos) + +# Frontend testing standards and style guidelines[](#frontend-testing-standards-and-style-guidelines "Permalink") + +在 GitLab 上开发前端代码时,会遇到两种测试套件. 我们将 Karma 与 Jasmine 和 Jest 一起用于 JavaScript 单元和集成测试,将 RSpec 功能测试与 Capybara 一起用于 e2e(端对端)集成测试. + +需要为所有新功能编写单元和功能测试. 大多数时候,您应该使用[RSpec](https://github.com/rspec/rspec-rails#feature-specs)进行功能测试. + +应该编写回归测试来修复错误,以防止将来再次发生. + +See the [Testing Standards and Style Guidelines](index.html) page for more information on general testing practices at GitLab. + +## Vue.js testing[](#vuejs-testing "Permalink") + +如果您正在寻找有关 Vue 组件测试的指南,则可以立即跳至本[部分](../fe_guide/vue.html#testing-vue-components) . + +## Jest[](#jest "Permalink") + +我们已经开始将前端测试迁移到[Jest](https://jestjs.io)测试框架(另请参见相应的[epic](https://gitlab.com/groups/gitlab-org/-/epics/895) ). + +开玩笑的测试可以在 EE 的`/spec/frontend`和`/ee/spec/frontend`中找到. + +> **Note:** +> +> 大多数示例都有 Jest 和 Karma 示例. 如果您在发现过程中偶然发现了一些用例,请仅参阅 Karma 示例以解释代码中发生的事情. 开玩笑的例子是您应该遵循的例子. + +## Karma test suite[](#karma-test-suite "Permalink") + +当 GitLab 切换到[Jest 时,](https://jestjs.io)您仍然会在我们的应用程序中找到 Karma 测试. [Karma](http://karma-runner.github.io/)是使用[Jasmine](https://jasmine.github.io/)作为测试框架的测试运行程序. Jest 还使用 Jasmine 作为基础,这就是为什么它看起来非常相似的原因. + +业力测试存在于`/ee/spec/javascripts`中的`spec/javascripts/`和`/ee/spec/javascripts`中. + +`app/assets/javascripts/behaviors/autosize.js`可能具有相应的`spec/javascripts/behaviors/autosize_spec.js`文件. + +请记住,在 CI 环境中,这些测试是在无头浏览器中运行的,您将无权访问某些必须进行存根的 API,例如[`Notification`](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/API/notification) . + +### When should I use Jest over Karma?[](#when-should-i-use-jest-over-karma "Permalink") + +如果您需要更新现有的 Karma 测试文件(可在`spec/javascripts`找到),则无需将整个规范迁移到 Jest. 只需更新 Karma 规范以测试您的更改就可以了. 在单独的合并请求中迁移到 Jest 可能更合适. + +如果创建新的测试文件,则需要在 Jest 中创建它. 这将有助于支持我们的迁移,我们认为您会喜欢使用 Jest. + +与往常一样,请谨慎使用. Jest 解决了我们在 Karma 中遇到的许多问题,并提供了更好的开发人员体验,但是可能会出现潜在的意外问题(尤其是针对浏览器特定功能进行测试). + +### Differences to Karma[](#differences-to-karma "Permalink") + +* Jest 在 Node.js 环境中运行,而不是在浏览器中. 运行在浏览器中测试玩笑支持[计划](https://gitlab.com/gitlab-org/gitlab/-/issues/26982) . +* 由于 Jest 在 Node.js 环境中运行,因此默认情况下它使用[jsdom](https://github.com/jsdom/jsdom) . 另请参见下面的[限制](#limitations-of-jsdom) . +* Jest 无权访问 Webpack 加载程序或别名. Jest 使用的别名是在其[自己的配置](https://gitlab.com/gitlab-org/gitlab/blob/master/jest.config.js)中定义的. +* 对`setTimeout`和`setInterval`所有调用都被模拟掉了. 另请参阅[Jest Timer Mocks](https://jestjs.io/docs/en/timer-mocks) . +* `rewire`不需要因为玩笑支撑嘲笑模块. 另请参见" [手动模拟"](https://jestjs.io/docs/en/manual-mocks) . +* 没有[上下文对象](https://jasmine.github.io/tutorials/your_first_suite#section-The_<code>this</code>_keyword)传递给 Jest 中的测试. 这意味着`this.something`在`beforeEach()`和`it()`之间共享`this.something`不起作用. 相反,您应该在需要共享变量的上下文中声明它们(通过`const` / `let` ). +* 以下将导致测试在 Jest 中失败: + * 未模拟的请求. + * 未处理的承诺拒绝. + * 调用`console.warn` ,包括来自 Vue 之类的库的警告. + +### Limitations of jsdom[](#limitations-of-jsdom "Permalink") + +[如上所述](#differences-to-karma) ,Jest 使用 jsdom 而不是浏览器来运行测试. 这有很多限制,即: + +* [No scrolling support](https://github.com/jsdom/jsdom/blob/15.1.1/lib/jsdom/browser/Window.js#L623-L625) +* [No element sizes or positions](https://github.com/jsdom/jsdom/blob/15.1.1/lib/jsdom/living/nodes/Element-impl.js#L334-L371) +* 一般[没有版面设计引擎](https://github.com/jsdom/jsdom/issues/1322) + +另请参阅有关[在浏览器中运行 Jest 测试的支持](https://gitlab.com/gitlab-org/gitlab/-/issues/26982)问题. + +### Debugging Jest tests[](#debugging-jest-tests "Permalink") + +运行`yarn jest-debug`将在调试模式下运行 Jest,从而允许您按照[Jest docs](https://jestjs.io/docs/en/troubleshooting#tests-are-failing-and-you-don-t-know-why)中的说明进行调试/检查. + +### Timeout error[](#timeout-error "Permalink") + +Jest 的默认超时是在[`/spec/frontend/test_setup.js`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/test_setup.js)设置的. + +如果您的测试超过该时间,它将失败. + +如果无法提高测试性能,则可以使用[`setTestTimeout`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/helpers/timeout.js)来增加特定测试的超时时间. + +``` +import { setTestTimeout } from 'helpers/timeout'; + +describe('Component', () => { + it('does something amazing', () => { + setTestTimeout(500); + // ... + }); +}); +``` + +请记住,每个测试的性能取决于环境. + +## What and how to test[](#what-and-how-to-test "Permalink") + +在深入了解有关 Jest 特定工作流程(如模拟和间谍)的更具体细节之前,我们应该简要介绍一下使用 Jest 测试的内容. + +### Don’t test the library[](#dont-test-the-library "Permalink") + +库是任何 JavaScript 开发人员生活中不可或缺的一部分. 一般建议是不要测试库的内部,但是希望库知道它应该做什么并且自己进行测试覆盖. 一个一般的例子可能是这样的 + +``` +import { convertToFahrenheit } from 'temperatureLibrary' + +function getFahrenheit(celsius) { + return convertToFahrenheit(celsius) +} +``` + +测试我们的`getFahrenheit`函数没有任何意义,因为在其下面除了调用库函数外,什么都没有做,而且我们可以预期它正在按预期工作. (简化,我知道) + +让我们看一下 Vue 领域. Vue 是 GitLab JavaScript 代码库的关键部分. 在编写 Vue 组件规范时,通常的陷阱是最终测试 Vue 提供的功能,因为这似乎是最容易测试的事情. 这是取自我们代码库的示例. + +``` +// Component +{ + computed: { + hasMetricTypes() { + return this.metricTypes.length; + }, +} +``` + +这是相应的规格 + +``` + describe('computed', () => { + describe('hasMetricTypes', () => { + it('returns true if metricTypes exist', () => { + factory({ metricTypes }); + expect(wrapper.vm.hasMetricTypes).toBe(2); + }); + + it('returns true if no metricTypes exist', () => { + factory(); + expect(wrapper.vm.hasMetricTypes).toBe(0); + }); + }); +}); +``` + +测试`hasMetricTypes`计算的道具似乎是给定的,但是要测试所计算的属性是否返回`metricTypes`的长度, `metricTypes`测试 Vue 库本身. 除了将其添加到测试套件之外,这没有任何价值. 最好以用户与之交互的方式对其进行测试. 大概通过模板. + +请注意这些测试,因为它们只会使更新逻辑变得比所需的更加脆弱和乏味. 其他库也是如此. + +在[前端单元测试部分中](testing_levels.html#frontend-unit-tests)可以找到更多示例. + +### Don’t test your mock[](#dont-test-your-mock "Permalink") + +另一个常见的陷阱是规范最终验证了该模拟程序是否正常运行. 如果使用模拟,则模拟应支持测试,但不应成为测试的目标. + +**Bad:** + +``` +const spy = jest.spyOn(idGenerator, 'create') +spy.mockImplementation = () = '1234' + +expect(idGenerator.create()).toBe('1234') +``` + +**Good:** + +``` +const spy = jest.spyOn(idGenerator, 'create') +spy.mockImplementation = () = '1234' + +// Actually focusing on the logic of your component and just leverage the controllable mocks output +expect(wrapper.find('div').html()).toBe('<div id="1234">...</div>') +``` + +### Follow the user[](#follow-the-user "Permalink") + +在繁重的组件环境中,单元测试和集成测试之间的界限可能非常模糊. 最重要的准则如下: + +* 编写干净的单元测试,以孤立的方式测试复杂的逻辑部分是否具有实际价值,以防止将来被破坏 +* 否则,请尝试将规格写得尽可能接近用户的需求 + +例如,与手动调用方法并验证数据结构或计算的属性相比,使用生成的标记来触发按钮单击并验证相应更改的标记更好. 在测试通过并提供错误的安全感的同时,总是有偶然破坏用户流的机会. + +## Common practices[](#common-practices "Permalink") + +接下来,您会发现一些通用的常规做法,它们将作为我们测试套件的一部分. 如果您发现不遵循本指南的内容,最好立即进行修复. + +### How to query DOM elements[](#how-to-query-dom-elements "Permalink") + +当涉及到测试中的 DOM 元素查询时,最好以唯一且语义上为目标的元素. 有时这无法切实可行. 在这些情况下,添加测试属性以简化选择器可能是最佳选择. + +优选地,在使用`@vue/test-utils`进行组件测试时,您应该使用组件本身来查询子组件. 这有助于强制执行该组件的各个单元测试可以涵盖的特定行为. 否则,请尝试使用: + +* 语义属性(例如`name` (还验证`name`是否正确设置) +* 一个`data-testid`属性( [由`@vue/test-utils`维护者推荐](https://github.com/vuejs/vue-test-utils/issues/1498#issuecomment-610133465) ) +* Vue `ref` (如果使用`@vue/test-utils` ) + +Examples: + +``` +it('exists', () => { + // Good + wrapper.find(FooComponent); + wrapper.find('input[name=foo]'); + wrapper.find('[data-testid="foo"]'); + wrapper.find({ ref: 'foo'}); + + // Bad + wrapper.find('.js-foo'); + wrapper.find('.btn-primary'); + wrapper.find('.qa-foo-component'); + wrapper.find('[data-qa-selector="foo"]'); +}); +``` + +不建议您仅添加`.js-*`类用于测试目的. 仅当没有其他可行的选择时才这样做. + +除 QA 端到端测试外,请勿将`.qa-*`类或`data-qa-selector`属性用于任何测试. + +### Naming unit tests[](#naming-unit-tests "Permalink") + +在编写描述测试块以测试特定功能/方法时,请使用方法名称作为描述块名称. + +``` +// Good +describe('methodName', () => { + it('passes', () => { + expect(true).toEqual(true); + }); +}); + +// Bad +describe('#methodName', () => { + it('passes', () => { + expect(true).toEqual(true); + }); +}); + +// Bad +describe('.methodName', () => { + it('passes', () => { + expect(true).toEqual(true); + }); +}); +``` + +### Testing promises[](#testing-promises "Permalink") + +在测试 Promises 时,应始终确保测试是异步的并且拒绝被处理. 现在可以在测试套件中使用`async/await`语法: + +``` +it('tests a promise', async () => { + const users = await fetchUsers() + expect(users.length).toBe(42) +}); + +it('tests a promise rejection', async () => { + expect.assertions(1); + try { + await user.getUserName(1); + } catch (e) { + expect(e).toEqual({ + error: 'User with 1 not found.', + }); + } +}); +``` + +您也可以使用 Promise 链. 在这种情况下,您可以利用`done`回调和`done.fail`发生错误. 以下是一些示例: + +``` +// Good +it('tests a promise', done => { + promise + .then(data => { + expect(data).toBe(asExpected); + }) + .then(done) + .catch(done.fail); +}); + +// Good +it('tests a promise rejection', done => { + promise + .then(done.fail) + .catch(error => { + expect(error).toBe(expectedError); + }) + .then(done) + .catch(done.fail); +}); + +// Bad (missing done callback) +it('tests a promise', () => { + promise.then(data => { + expect(data).toBe(asExpected); + }); +}); + +// Bad (missing catch) +it('tests a promise', done => { + promise + .then(data => { + expect(data).toBe(asExpected); + }) + .then(done); +}); + +// Bad (use done.fail in asynchronous tests) +it('tests a promise', done => { + promise + .then(data => { + expect(data).toBe(asExpected); + }) + .then(done) + .catch(fail); +}); + +// Bad (missing catch) +it('tests a promise rejection', done => { + promise + .catch(error => { + expect(error).toBe(expectedError); + }) + .then(done); +}); +``` + +### Manipulating Time[](#manipulating-time "Permalink") + +有时我们必须测试时间敏感的代码. 例如,每隔 X 秒或类似的时间运行一次重复发生的事件. 在这里,您将找到一些应对策略: + +#### `setTimeout()` / `setInterval()` in application[](#settimeout--setinterval-in-application "Permalink") + +如果应用程序本身正在等待一段时间,请模拟等待. 在 Jest 中[,默认情况下](https://gitlab.com/gitlab-org/gitlab/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47)已[完成](https://gitlab.com/gitlab-org/gitlab/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47)此[操作](https://gitlab.com/gitlab-org/gitlab/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47) (另请参见[Jest Timer Mocks](https://jestjs.io/docs/en/timer-mocks) ). 在 Karma 中,您可以使用[Jasmine 模拟时钟](https://jasmine.github.io/api/2.9/Clock.html) . + +``` +const doSomethingLater = () => { + setTimeout(() => { + // do something + }, 4000); +}; +``` + +**在:** + +``` +it('does something', () => { + doSomethingLater(); + jest.runAllTimers(); + + expect(something).toBe('done'); +}); +``` + +**在业力中:** + +``` +it('does something', () => { + jasmine.clock().install(); + + doSomethingLater(); + jasmine.clock().tick(4000); + + expect(something).toBe('done'); + jasmine.clock().uninstall(); +}); +``` + +### Waiting in tests[](#waiting-in-tests "Permalink") + +有时,测试需要等待应用程序中的某些事情发生后才能继续. 避免使用[`setTimeout`](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)因为它会使等待的原因不清楚,如果在 Karma 中使用的时间大于零,则会减慢我们的测试套件的速度. 而是使用以下方法之一. + +#### Promises and Ajax calls[](#promises-and-ajax-calls "Permalink") + +注册处理程序函数以等待`Promise`被解决. + +``` +const askTheServer = () => { + return axios + .get('/endpoint') + .then(response => { + // do something + }) + .catch(error => { + // do something else + }); +}; +``` + +**在:** + +``` +it('waits for an Ajax call', async () => { + await askTheServer() + expect(something).toBe('done'); +}); +``` + +**在业力中:** + +``` +it('waits for an Ajax call', done => { + askTheServer() + .then(() => { + expect(something).toBe('done'); + }) + .then(done) + .catch(done.fail); +}); +``` + +如果您无法将处理程序注册到`Promise` ,例如因为它是在同步 Vue 生命周期挂钩中执行的,请查看[waitFor](#wait-until-axios-requests-finish)帮助器,或者您可以刷新所有待处理的`Promise` : + +**在:** + +``` +it('waits for an Ajax call', () => { + synchronousFunction(); + jest.runAllTicks(); + + expect(something).toBe('done'); +}); +``` + +#### Vue rendering[](#vue-rendering "Permalink") + +要等到重新渲染 Vue 组件后,请使用等效的[`Vue.nextTick()`](https://vuejs.org/v2/api/#Vue-nextTick)或`vm.$nextTick()` . + +**在:** + +``` +it('renders something', () => { + wrapper.setProps({ value: 'new value' }); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.text()).toBe('new value'); + }); +}); +``` + +**in Karma:** + +``` +it('renders something', done => { + wrapper.setProps({ value: 'new value' }); + + wrapper.vm + .$nextTick() + .then(() => { + expect(wrapper.text()).toBe('new value'); + }) + .then(done) + .catch(done.fail); +}); +``` + +#### Events[](#events "Permalink") + +如果应用程序触发了您需要在测试中等待的事件,请注册一个包含断言的事件处理程序: + +``` +it('waits for an event', done => { + eventHub.$once('someEvent', eventHandler); + + someFunction(); + + function eventHandler() { + expect(something).toBe('done'); + done(); + } +}); +``` + +在 Jest 中,您还可以使用`Promise` : + +``` +it('waits for an event', () => { + const eventTriggered = new Promise(resolve => eventHub.$once('someEvent', resolve)); + + someFunction(); + + return eventTriggered.then(() => { + expect(something).toBe('done'); + }); +}); +``` + +### Ensuring that tests are isolated[](#ensuring-that-tests-are-isolated "Permalink") + +测试通常以一种模式进行架构,该模式要求重复设置并破坏被测组件. 这是通过使用`beforeEach`和`afterEach`挂钩完成的. + +Example + +``` + let wrapper; + + beforeEach(() => { + wrapper = mount(Component); + }); + + afterEach(() => { + wrapper.destroy(); + }); +``` + +最初查看此内容时,您会怀疑该组件是在每次测试之前设置的,然后在以后进行了细分,从而在测试之间提供了隔离. + +但是,这并不是完全正确的,因为`destroy`方法不会删除`wrapper`对象上所有已突变的东西. 对于功能组件,destroy 仅从文档中删除呈现的 DOM 元素. + +In order to ensure that a clean wrapper object and DOM are being used in each test, the breakdown of the component should rather be performed as follows: + +``` + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); +``` + +另请参见[有关`destroy`](https://vue-test-utils.vuejs.org/api/wrapper/#destroy)的[Vue Test Utils 文档](https://vue-test-utils.vuejs.org/api/wrapper/#destroy) . + +### Jest best practices[](#jest-best-practices "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34209) . + +#### Prefer `toBe` over `toEqual` when comparing primitive values[](#prefer-tobe-over-toequal-when-comparing-primitive-values "Permalink") + +[`toBe`](https://jestjs.io/docs/en/expect#tobevalue) [`toEqual`](https://jestjs.io/docs/en/expect#toequalvalue)匹配者. 由于[`toBe`](https://jestjs.io/docs/en/expect#tobevalue)使用[`Object.is`](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)比较值,因此(默认情况下)比使用`toEqual` . 尽管后者最终将回退以利用[`Object.is`](https://github.com/facebook/jest/blob/master/packages/expect/src/jasmineUtils.ts#L91)获得原始值,但仅应在需要比较复杂对象的情况下使用它. + +Examples: + +``` +const foo = 1; + +// good +expect(foo).toBe(1); + +// bad +expect(foo).toEqual(1); +``` + +#### Prefer more befitting matchers[](#prefer-more-befitting-matchers "Permalink") + +Jest 提供了有用的匹配器,例如`toHaveLength`或`toBeUndefined`以使您的测试更具可读性并产生更易理解的错误消息. 查看他们的文档以获取[匹配器](https://jestjs.io/docs/en/expect#methods)的[完整列表](https://jestjs.io/docs/en/expect#methods) . + +Examples: + +``` +const arr = [1, 2]; + +// prints: +// Expected length: 1 +// Received length: 2 +expect(arr).toHaveLength(1); + +// prints: +// Expected: 1 +// Received: 2 +expect(arr.length).toBe(1); + +// prints: +// expect(received).toBe(expected) // Object.is equality +// Expected: undefined +// Received: "bar" +const foo = 'bar'; +expect(foo).toBe(undefined); + +// prints: +// expect(received).toBeUndefined() +// Received: "bar" +const foo = 'bar'; +expect(foo).toBeUndefined(); +``` + +#### Avoid using `toBeTruthy` or `toBeFalsy`[](#avoid-using-tobetruthy-or-tobefalsy "Permalink") + +Jest 还提供以下匹配器: `toBeTruthy`和`toBeFalsy` . 我们不应该使用它们,因为它们会使测试变弱并产生假阳性结果. + +例如,当`someBoolean === null`以及`someBoolean === false`时,会通过`expect(someBoolean).toBeFalsy()` . + +#### Tricky `toBeDefined` matcher[](#tricky-tobedefined-matcher "Permalink") + +Jest 有一个棘手的`toBeDefined`匹配器,它可能会产生假阳性测试. 因为它仅[验证](https://github.com/facebook/jest/blob/master/packages/expect/src/matchers.ts#L204) `undefined`的给定值. + +``` +// good +expect(wrapper.find('foo').exists()).toBe(true); + +// bad +// if finder returns null, the test will pass +expect(wrapper.find('foo')).toBeDefined(); +``` + +#### Avoid using `setImmediate`[](#avoid-using-setimmediate "Permalink") + +尝试避免使用`setImmediate` . `setImmediate`是一个临时解决方案,可在 I / O 完成后运行您的回调. 而且它不是 Web API 的一部分,因此,我们在单元测试中以 NodeJS 环境为目标. + +代替`setImmediate` ,使用`jest.runAllTimers`或`jest.runOnlyPendingTimers`来运行暂挂计时器. 当代码中有`setInterval`时,后者很有用. **请记住:**我们的 Jest 配置使用假计时器. + +## Factories[](#factories "Permalink") + +TBU + +## Mocking Strategies with Jest[](#mocking-strategies-with-jest "Permalink") + +### Stubbing and Mocking[](#stubbing-and-mocking "Permalink") + +Jasmine 提供存根和模拟功能. 在 Karma 和 Jest 中,如何使用它有一些细微的差异. + +存根或间谍通常是同义词. 在 Jest 中,使用`.spyOn`方法非常容易. [官方文档](https://jestjs.io/docs/en/jest-object#jestspyonobject-methodname)更具挑战性的部分是模拟,可用于功能甚至依赖项. + +### Manual module mocks[](#manual-module-mocks "Permalink") + +手动模拟用于模拟整个 Jest 环境中的模块. 这是一个功能非常强大的测试工具,它通过模拟出在我们的测试环境中不容易使用的模块来帮助简化单元测试. + +> **警告:**如果不应在每个规范中始终采用模拟,则不要使用手动模拟(即,仅少数规范需要使用). 而是考虑在相关规范文件中使用[`jest.mock(..)`](https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options) (或类似的[`jest.mock(..)`](https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options)功能). + +#### Where should I put manual mocks?[](#where-should-i-put-manual-mocks "Permalink") + +Jest 通过将模拟放置在源模块旁边的`__mocks__/`目录(例如`app/assets/javascripts/ide/__mocks__` )中来支持[手动模块](https://jestjs.io/docs/en/manual-mocks)模拟. **不要这样** 我们希望将所有与测试相关的代码保存在一个地方( `spec/`文件夹). + +如果`node_modules`软件包需要手动模拟,请使用`spec/frontend/__mocks__`文件夹. 这是[`monaco-editor`软件包](https://gitlab.com/gitlab-org/gitlab/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js#L1)的[Jest 模拟](https://gitlab.com/gitlab-org/gitlab/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js#L1)示例. + +如果 CE 模块需要手动模拟,请将其放在`spec/frontend/mocks/ce` . + +* `spec/frontend/mocks/ce`文件将从`app/assets/javascripts`模拟相应的 CE 模块,从而镜像源模块的路径. + * 示例: `spec/frontend/mocks/ce/lib/utils/axios_utils`将模拟模块`~/lib/utils/axios_utils` . +* 我们尚不支持模拟 EE 模块. +* 如果找到了不存在源模块的模拟,则测试套件将失败. 目前尚不支持"虚拟"模拟或与源模块没有 1 对 1 关联的模拟. + +#### Manual mock examples[](#manual-mock-examples "Permalink") + +* 模拟[`mocks/axios_utils`](https://gitlab.com/gitlab-org/gitlab/blob/bd20aeb64c4eed117831556c54b40ff4aee9bfd1/spec/frontend/mocks/ce/lib/utils/axios_utils.js#L1)此模拟很有用,因为我们不希望任何未经模拟的请求通过任何测试. 另外,我们能够注入一些测试助手,例如`axios.waitForAll` . +* [`__mocks__/mousetrap/index.js`](https://gitlab.com/gitlab-org/gitlab/blob/cd4c086d894226445be9d18294a060ba46572435/spec/frontend/__mocks__/mousetrap/index.js#L1)此模拟很有用,因为该模块本身使用 webpack 可以理解的 AMD 格式,但与玩笑的环境不兼容. 该模拟不会删除任何行为,仅提供与 es6 兼容的包装器. +* [`__mocks__/monaco-editor/index.js`](https://gitlab.com/gitlab-org/gitlab/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js) - This mock is helpful because the Monaco package is completely incompatible in a Jest environment. In fact, webpack requires a special loader to make it work. This mock simply makes this package consumable by Jest. + +### Keep mocks light[](#keep-mocks-light "Permalink") + +全局模拟会引入魔术,并且从技术上讲可以减少测试的覆盖范围. 当嘲笑被视为有利可图时: + +* 保持模拟简短而集中. +* 请在模拟中留下为什么有必要的顶级评论. + +### Additional mocking techniques[](#additional-mocking-techniques "Permalink") + +请查阅[官方的 Jest 文档](https://jestjs.io/docs/en/jest-object#mock-modules) ,以获取有关可用模拟功能的完整概述. + +## Running Frontend Tests[](#running-frontend-tests "Permalink") + +要运行前端测试,您需要以下命令: + +* `rake frontend:fixtures` (re-)generates [fixtures](#frontend-test-fixtures). +* `yarn test`执行测试. +* `yarn jest`执行 Jest 测试. + +只要固定装置不变, `yarn test`就足够了(并节省了一些时间). + +### Live testing and focused testing – Jest[](#live-testing-and-focused-testing----jest "Permalink") + +在测试套件上工作时,您可能希望以监视模式运行这些规范,因此它们会在每次保存时自动重新运行. + +``` +# Watch and rerun all specs matching the name icon +yarn jest --watch icon + +# Watch and rerun one specifc file +yarn jest --watch path/to/spec/file.spec.js +``` + +您也可以在不使用`--watch`标志的情况下运行一些重点测试 + +``` +# Run specific jest file +yarn jest ./path/to/local_spec.js +# Run specific jest folder +yarn jest ./path/to/folder/ +# Run all jest files which path contain term +yarn jest term +``` + +### Live testing and focused testing – Karma[](#live-testing-and-focused-testing----karma "Permalink") + +业力允许类似的东西,但是成本更高. + +用`yarn run karma-start`运行 Karma 将编译 JavaScript 资产并在`http://localhost:9876/`上运行服务器,在该服务器上它将自动在连接到它的任何浏览器上运行测试. 您可以一次在多个浏览器上输入该 URL,以使其在每个浏览器上并行运行测试. + +当 Karma 运行时,您所做的任何更改都会立即触发**整个测试套件**的重新编译和重新**测试** ,因此您可以立即查看是否使用所做的更改破坏了测试. 您可以使用[针对 Jasmine 的](https://jasmine.github.io/2.5/focused_specs.html)测试或排除测试(使用`fdescribe`或`xdescribe` )来使 Karma 仅在您使用特定功能时运行所需的测试,但是请确保在提交代码时删除这些指令. + +通过使用参数`--filter-spec`或 short `-f`过滤运行测试,也可以仅在特定的文件夹或文件上运行 Karma: + +``` +# Run all files +yarn karma-start +# Run specific spec files +yarn karma-start --filter-spec profile/account/components/update_username_spec.js +# Run specific spec folder +yarn karma-start --filter-spec profile/account/components/ +# Run all specs which path contain vue_shared or vie +yarn karma-start -f vue_shared -f vue_mr_widget +``` + +您还可以使用 glob 语法来匹配文件. 请记住在引号周围加上引号,否则您的 shell 可能会将其拆分为多个参数: + +``` +# Run all specs named `file_spec` within the IDE subdirectory +yarn karma -f 'spec/javascripts/ide/**/file_spec.js' +``` + +## Frontend test fixtures[](#frontend-test-fixtures "Permalink") + +添加到 HAML 模板(在`app/views/` )或向后端发出 Ajax 请求的代码具有要求后端提供 HTML 或 JSON 的测试. 这些测试的夹具位于: + +* `spec/frontend/fixtures/` ,用于在 CE 中运行测试. +* `ee/spec/frontend/fixtures/` ,用于在 EE 中运行测试. + +灯具文件位于: + +* Karma 测试套件由[jasmine-jquery 提供](https://github.com/velesin/jasmine-jquery) . +* 开玩笑地使用`spec/frontend/helpers/fixtures.js` . + +以下是适用于 Karma 和 Jest 的测试示例: + +``` +it('makes a request', () => { + const responseBody = getJSONFixture('some/fixture.json'); // loads spec/frontend/fixtures/some/fixture.json + axiosMock.onGet(endpoint).reply(200, responseBody); + + myButton.click(); + + // ... +}); + +it('uses some HTML element', () => { + loadFixtures('some/page.html'); // loads spec/frontend/fixtures/some/page.html and adds it to the DOM + + const element = document.getElementById('#my-id'); + + // ... +}); +``` + +HTML 和 JSON 固定装置是使用 RSpec 从后端视图和控制器生成的(请参阅`spec/frontend/fixtures/*.rb` ). + +对于每个灯具, `response`变量的内容存储在输出文件中. 如果测试标记为`type: :request`或`type: :controller`则此变量将自动设置. 可以使用`bin/rake frontend:fixtures`命令来重新生成`bin/rake frontend:fixtures`但是您也可以单独生成它们,例如`bin/rspec spec/frontend/fixtures/merge_requests.rb` . 创建新的固定装置时,通常有必要在`(ee/)spec/controllers/`或`(ee/)spec/requests/`查看端点的相应测试. + +## Data-driven tests[](#data-driven-tests "Permalink") + +与[RSpec 的参数化测试](best_practices.html#table-based--parameterized-tests)类似,Jest 支持以下数据驱动的测试: + +* 使用[`test.each`](https://jestjs.io/docs/en/api#testeachtable-name-fn-timeout)单独测试(别名为`it.each` ). +* 使用[`describe.each`](https://jestjs.io/docs/en/api#describeeachtable-name-fn-timeout)的测试组. + +这些对于减少测试中的重复很有用. 每个选项都可以采用数据值数组或带标签的模板文字. + +例如: + +``` +// function to test +const icon = status => status ? 'pipeline-passed' : 'pipeline-failed' +const message = status => status ? 'pipeline-passed' : 'pipeline-failed' + +// test with array block +it.each([ + [false, 'pipeline-failed'], + [true, 'pipeline-passed'] +])('icon with %s will return %s', + (status, icon) => { + expect(renderPipeline(status)).toEqual(icon) + } +); +``` + +``` +// test suite with tagged template literal block +describe.each` + status | icon | message ${false} | ${'pipeline-failed'} | ${'Pipeline failed - boo-urns'} ${true} | ${'pipeline-passed'} | ${'Pipeline succeeded - win!'} `('pipeline component', ({ status, icon, message }) => { + it(`returns icon ${icon} with status ${status}`, () => { + expect(icon(status)).toEqual(message) + }) + + it(`returns message ${message} with status ${status}`, () => { + expect(message(status)).toEqual(message) + }) +}); +``` + +## Gotchas[](#gotchas "Permalink") + +### RSpec errors due to JavaScript[](#rspec-errors-due-to-javascript "Permalink") + +默认情况下,RSpec 单元测试不会在无头浏览器中运行 JavaScript,而仅依赖于检查 rails 生成的 HTML. + +如果集成测试依赖 JavaScript 才能正确运行,则需要确保将规范配置为在运行测试时启用 JavaScript. 如果不这样做,您会看到规范运行器发出的模糊错误消息. + +To enable a JavaScript driver in an `rspec` test, add `:js` to the individual spec or the context block containing multiple specs that need JavaScript enabled: + +``` +# For one spec +it 'presents information about abuse report', :js do + # assertions... +end + +describe "Admin::AbuseReports", :js do + it 'presents information about abuse report' do + # assertions... + end + it 'shows buttons for adding to abuse report' do + # assertions... + end +end +``` + +## Overview of Frontend Testing Levels[](#overview-of-frontend-testing-levels "Permalink") + +有关前端测试级别的主要信息,请参见" [测试级别"页面](testing_levels.html) . + +与前端开发相关的测试可以在以下位置找到: + +* `spec/javascripts/` ,用于业力测试 +* `spec/frontend/` ,用于 Is 测试 +* `spec/features/` ,用于 RSpec 测试 + +RSpec 运行完整的[功能测试](testing_levels.html#frontend-feature-tests) ,而 Jest 和 Karma 目录包含[前端单元测试](testing_levels.html#frontend-unit-tests) , [前端组件测试](testing_levels.html#frontend-component-tests)和[前端集成测试](testing_levels.html#frontend-integration-tests) . + +`spec/javascripts/`所有测试最终都将迁移到`spec/frontend/` (另请参见[#52483](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52483) ). + +在 2018 年 5 月之前, `features/`还包含 Spinach 运行的功能测试. 这些测试已于 2018 年 5 月从代码库中删除( [#23036](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/23036) ). + +另请参阅[有关测试 Vue 组件的说明](../fe_guide/vue.html#testing-vue-components) . + +## Test helpers[](#test-helpers "Permalink") + +### Vuex Helper: `testAction`[](#vuex-helper-testaction "Permalink") + +根据[官方文档](https://vuex.vuejs.org/guide/testing.html) ,我们提供了一个帮助程序,可以简化测试操作: + +``` +testAction( + actions.actionName, // action + { }, // params to be passed to action + state, // state + [ + { type: types.MUTATION}, + { type: types.MUTATION_1, payload: {}}, + ], // mutations committed + [ + { type: 'actionName', payload: {}}, + { type: 'actionName1', payload: {}}, + ] // actions dispatched + done, +); +``` + +在[`spec/javascripts/ide/stores/actions_spec.jsspec/javascripts/ide/stores/actions_spec.js`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/javascripts/ide/stores/actions_spec.js) . + +### Wait until Axios requests finish[](#wait-until-axios-requests-finish "Permalink") + +The Axios Utils mock module located in `spec/frontend/mocks/ce/lib/utils/axios_utils.js` contains two helper methods for Jest tests that spawn HTTP requests. These are very useful if you don’t have a handle to the request’s Promise, for example when a Vue component does a request as part of its life cycle. + +* `waitFor(url, callback)` :对`url`的请求完成后(成功或失败)运行`callback` . +* `waitForAll(callback)` :所有未完成的请求完成后,运行`callback` . 如果没有待处理的请求,则在下一个刻度上运行`callback` . + +这两个函数运行`callback` (使用请求结束后的下一个滴答`setImmediate()`以允许任何`.then()`或`.catch()`处理程序来运行. + +## Testing with older browsers[](#testing-with-older-browsers "Permalink") + +某些回归仅影响特定的浏览器版本. 我们可以按照以下步骤使用 Firefox 或 BrowserStack 在特定的浏览器中安装和测试: + +### BrowserStack[](#browserstack "Permalink") + +[BrowserStack](https://www.browserstack.com/)可以测试 1200 多种移动设备和浏览器. 您可以直接通过[实时应用程序](https://www.browserstack.com/live)使用它,也可以安装[chrome 扩展程序](https://chrome.google.com/webstore/detail/browserstack/nkihdmlheodkdfojglpcjjmioefjahjb)以便于访问. 使用保存在 GitLab [共享 1Password 帐户](https://about.gitlab.com/handbook/security/#1password-guide)的**Engineering**库中的凭据登录到 BrowserStack. + +### Firefox[](#firefox "Permalink") + +#### macOS[](#macos "Permalink") + +您可以从发布的 FTP 服务器[https://ftp.mozilla.org/pub/firefox/releases/](https://ftp.mozilla.org/pub/firefox/releases/)下载任何较旧版本的 Firefox: + +1. 从网站上选择一个版本,在本例中为`50.0.1` . +2. 转到 mac 文件夹. +3. 选择您喜欢的语言,您将在其中找到 DMG 软件包并下载. +4. 将应用程序拖放到"应用`Applications`文件夹以外的任何其他文件夹中. +5. 将应用程序重命名为`Firefox_Old` . +6. 将应用程序移至"应用`Applications`文件夹. +7. 打开终端,然后运行`/Applications/Firefox_Old.app/Contents/MacOS/firefox-bin -profilemanager`以创建特定于该 Firefox 版本的新配置文件. +8. 创建配置文件后,请退出应用程序,然后像平常一样再次运行它. 现在,您可以使用较旧的 Firefox 版本. + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/_book/docs/629.md b/_book/docs/629.md new file mode 100644 index 0000000000000000000000000000000000000000..15161cce7e05d5229b89748174e8c46db609398c --- /dev/null +++ b/_book/docs/629.md @@ -0,0 +1,37 @@ +# GitLab tests in the Continuous Integration (CI) context + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/ci.html](https://docs.gitlab.com/ee/development/testing_guide/ci.html) + +* [Test suite parallelization on the CI](#test-suite-parallelization-on-the-ci) +* [Monitoring](#monitoring) +* [CI setup](#ci-setup) + +# GitLab tests in the Continuous Integration (CI) context[](#gitlab-tests-in-the-continuous-integration-ci-context "Permalink") + +## Test suite parallelization on the CI[](#test-suite-parallelization-on-the-ci "Permalink") + +我们当前的 CI 并行化设置如下: + +1. 在`prepare`阶段的`retrieve-tests-metadata`作业可确保我们有一个`knapsack/report-master.json`文件: + * 从 S3 提取`knapsack/report-master.json`文件,如果不在此处,则使用`{}`初始化文件. +2. 每个`[rspec|rspec-ee] [unit|integration|system|geo] nm`作业均使用`knapsack rspec`运行,并且应具有均匀分布的测试份额: + * 之所以起作用,是因为"默认情况下传递了所有先前阶段的工件"以来,作业可以访问`knapsack/report-master.json` . + * 作业将自己的报告路径设置为`"knapsack/${TEST_TOOL}_${TEST_LEVEL}_${DATABASE}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json"` . + * 如果背包正在执行任务,则运行的测试文件应列在`Report specs` ,而不是" `Leftover specs` . +3. `update-tests-metadata`作业(仅[在规范项目的](https://gitlab.com/gitlab-org/gitlab)预定管道上运行)将所有`knapsack/rspec*_pg_*.json`文件合并在一起,然后将它们全部合并为一个`knapsack/report-master.json`文件,然后将其上传到 S3. + +之后,下一个管道将使用最新的`knapsack/report-master.json`文件. + +## Monitoring[](#monitoring "Permalink") + +[监视](../performance.html#rspec-profiling) GitLab 测试套件的`master`分支以及名称中包含`rspec-profile`任何分支. + +[公共仪表板](https://redash.gitlab.com/public/dashboards/l1WhHXaxrCWM5Ai9D7YDqHKehq6OU3bx5gssaiWe?org_slug=default)可供所有人查看. 随意查看最慢的测试文件并尝试对其进行改进. + +## CI setup[](#ci-setup "Permalink") + +* [由于性能原因](https://jtway.co/speed-up-your-rails-test-suite-by-6-in-1-line-13fedb869ec4) ,CI 中默认情况下禁用 Rails 日志到`log/test.log` . 要覆盖此设置,请提供`RAILS_ENABLE_TEST_LOG`环境变量. + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/_book/docs/630.md b/_book/docs/630.md new file mode 100644 index 0000000000000000000000000000000000000000..02f0c01438ba4fbf65ef377e75d1efcb6e55b91b --- /dev/null +++ b/_book/docs/630.md @@ -0,0 +1,337 @@ +# Review Apps + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/review_apps.html](https://docs.gitlab.com/ee/development/testing_guide/review_apps.html) + +* [How does it work?](#how-does-it-work) + * [CI/CD architecture diagram](#cicd-architecture-diagram) + * [Detailed explanation](#detailed-explanation) + * [Auto-stopping of Review Apps](#auto-stopping-of-review-apps) +* [QA runs](#qa-runs) +* [Performance Metrics](#performance-metrics) +* [Cluster configuration](#cluster-configuration) + * [Node pools](#node-pools) + * [Helm](#helm) +* [How to](#how-to) + * [Get access to the GCP Review Apps cluster](#get-access-to-the-gcp-review-apps-cluster) + * [Log into my Review App](#log-into-my-review-app) + * [Enable a feature flag for my Review App](#enable-a-feature-flag-for-my-review-app) + * [Find my Review App slug](#find-my-review-app-slug) + * [Run a Rails console](#run-a-rails-console) + * [Dig into a Pod’s logs](#dig-into-a-pods-logs) +* [Diagnosing unhealthy Review App releases](#diagnosing-unhealthy-review-app-releases) + * [Release failed with `ImagePullBackOff`](#release-failed-with-imagepullbackoff) + * [Node count is always increasing (i.e. never stabilizing or decreasing)](#node-count-is-always-increasing-ie-never-stabilizing-or-decreasing) + * [p99 CPU utilization is at 100% for most of the nodes and/or many components](#p99-cpu-utilization-is-at-100-for-most-of-the-nodes-andor-many-components) + * [The `logging/user/events/FailedMount` chart is going up](#the-loggingusereventsfailedmount-chart-is-going-up) + * [Using K9s](#using-k9s) + * [Troubleshoot a pending `dns-gitlab-review-app-external-dns` Deployment](#troubleshoot-a-pending-dns-gitlab-review-app-external-dns-deployment) + * [Finding the problem](#finding-the-problem) + * [Solving the problem](#solving-the-problem) + * [Mitigation steps taken to avoid this problem in the future](#mitigation-steps-taken-to-avoid-this-problem-in-the-future) +* [Frequently Asked Questions](#frequently-asked-questions) +* [Other resources](#other-resources) + * [Helpful command line tools](#helpful-command-line-tools) + +# Review Apps[](#review-apps "Permalink") + +Review Apps 由[管道](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6665)自动部署. + +## How does it work?[](#how-does-it-work "Permalink") + +### CI/CD architecture diagram[](#cicd-architecture-diagram "Permalink") + +图 TD A [" build-qa-image,编译生产资产 +(仅适用于规范的默认参考)"]; B [review-build-cng]; C [review-deploy]; D [CNG-mirror]; E [review-qa-smoke]; A-> |一旦准备`阶段已完成| BB -.-> |触发 CNG 镜像管道并等待其完成| DD -.-> |轮询直到完成| BB-> |一旦完成`view-build-cng`工作完成| CC-> |完成"审查-部署"工作| E 子图" 1\. gitlab`prepare` stage"结束子图" 2\. gitlab`review-prepare`阶段" B 结束子图" 3\. gitlab`review` stage" C [" review-deploy + +Helm 使用云部署 Review App +由 CNG 镜像管道构建的本机映像. + +Cloud Native 映像已部署到" review-apps" +Kubernetes(GKE)集群,位于 GCP`gitlab-review-apps`项目中."]结束子图" 4\. gitlab`qa` stage" E [review-qa-smoke + +gitlab-qa 对 Review App 运行冒烟套件.]结束子图" CNG 镜像管道" D>构建了 Cloud Native 图像]; 结束 + +### Detailed explanation[](#detailed-explanation "Permalink") + +1. 在`prepare`阶段的每个[管道](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730)上,都会自动启动[`compile-production-assets`](https://gitlab.com/gitlab-org/gitlab/-/jobs/641770154)作业. + * 完成后, [`review-build-cng`](https://gitlab.com/gitlab-org/gitlab/-/jobs/467724808)作业开始,因为在后续步骤中触发的[`CNG-mirror`](https://gitlab.com/gitlab-org/build/CNG-mirror)管道依赖[`review-build-cng`](https://gitlab.com/gitlab-org/gitlab/-/jobs/467724808) . +2. 完成`compile-production-assets`后, [`review-build-cng`](https://gitlab.com/gitlab-org/gitlab/-/jobs/467724808)作业[将触发](https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/44364657) [`CNG-mirror`](https://gitlab.com/gitlab-org/build/CNG-mirror)项目中[的管道](https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/44364657) . + * 仅当您的 MR 包括[CI 或前端更改时](../pipelines.html#changes-patterns) , `review-build-cng`作业才会自动开始. 在其他情况下,该工作是手动的. + * [`CNG-mirror`](https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/44364657)管道基于[GitLab 管道](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730)的提交创建每个组件(例如`gitlab-rails-ee` , `gitlab-shell` , `gitaly`等)的 Docker 映像,并将它们存储在其[注册表中](https://gitlab.com/gitlab-org/build/CNG-mirror/container_registry) . + * 我们使用[`CNG-mirror`](https://gitlab.com/gitlab-org/build/CNG-mirror)项目,以便`CNG` (Cloud Native GitLab)项目的注册表不会因大量临时 Docker 映像而过载. + * 请注意,官方的 CNG 图像是由`cloud-native-image`作业构建的,该作业仅针对标签运行,并自身触发[`CNG`](https://gitlab.com/gitlab-org/build/CNG)管道. +3. 完成`review-build-cng`后, [`review-deploy`](https://gitlab.com/gitlab-org/gitlab/-/jobs/467724810)作业使用[官方的 GitLab Helm 图表](https://gitlab.com/gitlab-org/charts/gitlab/)将 Review App 部署到 GCP 上的[`review-apps`](https://console.cloud.google.com/kubernetes/clusters/details/us-central1-b/review-apps?project=gitlab-review-apps) Kubernetes 集群. + * 可以在[`scripts/review_apps/review-apps.sh`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/review_apps/review-apps.sh)找到用于部署 Review App 的实际脚本. + * 这些脚本基本上是[我们的官方 Auto DevOps 脚本](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml) ,其中默认的 CNG 映像会被构建并存储在[`CNG-mirror`项目注册表中](https://gitlab.com/gitlab-org/build/CNG-mirror/container_registry)的映像覆盖. + * 由于我们使用的[是官方的 GitLab Helm 图表](https://gitlab.com/gitlab-org/charts/gitlab/) ,这意味着您将为分支机构获得一个专用的环境,该环境非常接近生产环境. +4. 一旦[`review-deploy`](https://gitlab.com/gitlab-org/gitlab/-/jobs/467724810)作业成功,您应该可以使用您的 Review App,这要归功于 MR 小部件与它的直接链接. 要登录 Review App,请参阅"登录我的 Review App?". 下面. + +**补充笔记:** + +* 如果`review-deploy`工作持续失败(请注意,我们已经试了两次),请在发布消息`#g_qe_engineering_productivity`通道和/或创建`~"Engineering Productivity"` `~"ep::review apps"` `~bug`的问题有链接到您的合并请求. 请注意,部署失败可能会揭示合并请求中引入的实际问题(即,这不一定是暂时性失败)! +* 如果`review-qa-smoke`作业仍然失败(请注意,我们已经重试了两次),请检查该作业的日志:您可能会发现合并请求中引入的实际问题. 您也可以下载工件,以查看发生故障时页面的屏幕截图. 如果您找不到失败的原因,或者看起来与更改无关,请在`#quality`频道中发布一条消息和/或创建`#quality`问题,并带有指向合并请求的链接. +* 手动`review-stop`可用于手动停止复查应用,一旦合并请求的分支在合并后被删除,GitLab 也将启动手动`review-stop` . +* 使用[GitLab 的 Kubernetes 集成](../../user/project/clusters/index.html)将 Kubernetes 集群连接到`gitlab`项目. 这基本上允许直接从合并请求窗口小部件链接到 Review App. + +### Auto-stopping of Review Apps[](#auto-stopping-of-review-apps "Permalink") + +借助[环境自动停止](../../ci/environments/index.html#environments-auto-stop)功能,Review Apps 在上次部署后 2 天会自动停止. + +If you need your Review App to stay up for a longer time, you can [pin its environment](../../ci/environments/index.html#auto-stop-example) or retry the `review-deploy` job to update the “latest deployed at” time. + +The `review-cleanup` job that automatically runs in scheduled pipelines (and is manual in merge request) stops stale Review Apps after 5 days, deletes their environment after 6 days, and cleans up any dangling Helm releases and Kubernetes resources after 7 days. + +自动在计划的管道中运行的`review-gcp-cleanup`作业(在合并请求中手动执行)将删除所有未与 Kubernetes 资源一起删除的悬空 GCP 网络资源. + +## QA runs[](#qa-runs "Permalink") + +在`qa`阶段(在`review`阶段之后)的每个[管道](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730)上, `review-qa-smoke`作业都会自动启动,并运行 QA 烟雾套件. + +您也可以手动启动`review-qa-all` :它运行完整的质量检查套件. + +## Performance Metrics[](#performance-metrics "Permalink") + +在每一个[管道](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730)在`qa`阶段, `review-performance`作业自动启动:这项工作确实使用基本的浏览器性能测试[Sitespeed.io 集装箱](../../user/project/merge_requests/browser_performance_testing.html) . + +## Cluster configuration[](#cluster-configuration "Permalink") + +### Node pools[](#node-pools "Permalink") + +目前, `review-apps`集群使用以下节点池进行设置: + +* 具有自动`e2-highcpu-16` (16 vCPU,16 GB 内存)可抢占节点 + +### Helm[](#helm "Permalink") + +使用的 Helm 版本在[`registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-helm3-kubectl1.14`映像中](https://gitlab.com/gitlab-org/gitlab-build-images/-/blob/master/Dockerfile.gitlab-helm3-kubectl1.14#L7)定义,由`review-deploy`和`review-stop`作业使用. + +## How to[](#how-to "Permalink") + +### Get access to the GCP Review Apps cluster[](#get-access-to-the-gcp-review-apps-cluster "Permalink") + +您需要[打开](https://gitlab.com/gitlab-com/access-requests/-/issues/new) `gcp-review-apps-sg` GCP 组[的访问请求(内部链接)](https://gitlab.com/gitlab-com/access-requests/-/issues/new) . 为了加入群组,您必须在访问请求中指定所需的 GCP 角色. 该角色将授予您特定的权限,以便与 Review App 容器进行交互. + +Here are some permissions you may want to have, and the roles that grant them: + +* `container.pods.getLogs` [检索 pod 日志所](#dig-into-a-pods-logs)必需. 由[查看者( `roles/viewer` )](https://cloud.google.com/iam/docs/understanding-roles#kubernetes-engine-roles)授予. +* `container.pods.exec` [运行 Rails 控制台](#run-a-rails-console)所需. 由[Kubernetes Engine 开发人员( `roles/container.developer` )](https://cloud.google.com/iam/docs/understanding-roles#kubernetes-engine-roles)授予. + +### Log into my Review App[](#log-into-my-review-app "Permalink") + +默认用户名是`root` ,其密码可以在名为`gitlab-{ce,ee} Review App's root password`的 1Password 安全注释中找到. + +### Enable a feature flag for my Review App[](#enable-a-feature-flag-for-my-review-app "Permalink") + +1. 打开您的 Review App 并按照上述说明登录. +2. 创建一个个人访问令牌. +3. 使用[Feature 标志 API](../../api/features.html)启用[功能标志](../../api/features.html) . + +### Find my Review App slug[](#find-my-review-app-slug "Permalink") + +1. 打开`review-deploy`作业. +2. 查找" `Checking for previous deployment of review-*` . +3. 例如,对于`Checking for previous deployment of review-qa-raise-e-12chm0`在这种情况下,您的 Review App `Checking for previous deployment of review-qa-raise-e-12chm0`将为`review-qa-raise-e-12chm0` . + +### Run a Rails console[](#run-a-rails-console "Permalink") + +1. 确保首先[具有访问群集](#get-access-to-the-gcp-review-apps-cluster)和`container.pods.exec`权限的权限. +2. [根据您的 Review App](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps) `review-qa-raise-e-12chm0` [过滤工作量](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps) ,例如`review-qa-raise-e-12chm0` . +3. 查找并打开`task-runner`部署,例如`review-qa-raise-e-12chm0-task-runner` . +4. 单击"托管窗格"部分中的 Pod,例如`review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz` . +5. 点击`KUBECTL`下拉菜单,然后`Exec` - > `task-runner` . +6. 从默认命令`-it -- gitlab-rails console` `-c task-runner -- ls`替换为`-it -- gitlab-rails console` ,或者 + * 运行`kubectl exec --namespace review-apps review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz -it -- gitlab-rails console`和 + * 用您的 Pod 名称替换`review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz` . + +### Dig into a Pod’s logs[](#dig-into-a-pods-logs "Permalink") + +1. 确保首先[有权访问集群](#get-access-to-the-gcp-review-apps-cluster)和`container.pods.getLogs`权限. +2. [根据您的 Review App](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps) `review-qa-raise-e-12chm0` [过滤工作量](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps) ,例如`review-qa-raise-e-12chm0` . +3. 查找并打开`migrations`部署,例如`review-qa-raise-e-12chm0-migrations.1` . +4. 单击"托管窗格"部分中的 Pod,例如`review-qa-raise-e-12chm0-migrations.1-nqwtx` . +5. 单击`Container logs`链接. + +## Diagnosing unhealthy Review App releases[](#diagnosing-unhealthy-review-app-releases "Permalink") + +如果[Review App Stability](https://app.periscopedata.com/app/gitlab/496118/Engineering-Productivity-Sandbox?widget=6690556&udv=785399)下降,则可能表明[Review](https://app.periscopedata.com/app/gitlab/496118/Engineering-Productivity-Sandbox?widget=6690556&udv=785399) `review-apps-ce/ee`集群不健康. 领先的指标可能是导致重新启动的运行状况检查失败或 Review App 部署的多数失败. + +[Review Apps Overview 仪表板可](https://console.cloud.google.com/monitoring/classic/dashboards/6798952013815386466?project=gitlab-review-apps&timeDomain=1d)帮助确定群集上的负载峰值,以及节点是否有问题或整个群集是否趋于不正常. + +### Release failed with `ImagePullBackOff`[](#release-failed-with-imagepullbackoff "Permalink") + +**潜在原因:** + +如果看到`ImagePullBackoff`状态,请检查缺少的 Docker 映像. + +**在哪里寻找进一步的调试:** + +要检查是否已创建 Docker 映像,请运行以下 Docker 命令: + +``` +`DOCKER_CLI_EXPERIMENTAL=enabled docker manifest repository:tag` +``` + +此命令的输出指示 Docker 映像是否存在. 例如: + +``` +DOCKER_CLI_EXPERIMENTAL=enabled docker manifest inspect registry.gitlab.com/gitlab-org/build/cng-mirror/gitlab-rails-ee:39467-allow-a-release-s-associated-milestones-to-be-edited-thro +``` + +如果 Docker 映像不存在: + +* 验证`helm upgrade --install`命令中的`image.repository`和`image.tag`选项是否与 CNG-mirror 管道使用的存储库名称匹配. +* 在`review-build-cng`作业中进一步查看相应的下游 CNG 镜像管道. + +### Node count is always increasing (i.e. never stabilizing or decreasing)[](#node-count-is-always-increasing-ie-never-stabilizing-or-decreasing "Permalink") + +**潜在原因:** + +这可能表明`review-cleanup`作业未能清除过时的审查应用和 Kubernetes 资源. + +**在哪里寻找进一步的调试:** + +查看最新的`review-cleanup`作业日志,并确定是否存在任何意外故障. + +### p99 CPU utilization is at 100% for most of the nodes and/or many components[](#p99-cpu-utilization-is-at-100-for-most-of-the-nodes-andor-many-components "Permalink") + +**潜在原因:** + +这可能表明 Helm 无法部署 Review Apps. 当 Helm 有很多`FAILED`版本发布时,CPU 利用率似乎正在增加,这可能是由于 Helm 或 Kubernetes 试图重新创建组件所致. + +**在哪里寻找进一步的调试:** + +查看最近的`review-deploy`作业日志. + +**有用的命令:** + +``` +# Identify if node spikes are common or load on specific nodes which may get rebalanced by the Kubernetes scheduler +kubectl top nodes | sort --key 3 --numeric + +# Identify pods under heavy CPU load +kubectl top pods | sort --key 2 --numeric +``` + +### The `logging/user/events/FailedMount` chart is going up[](#the-loggingusereventsfailedmount-chart-is-going-up "Permalink") + +**潜在原因:** + +这可能表明存在太多过时的机密和/或配置图. + +**在哪里寻找进一步的调试:** + +查看[配置列表](https://console.cloud.google.com/kubernetes/config?project=gitlab-review-apps)或`kubectl get secret,cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-'` `kubectl get secret,cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-'` . + +怀疑任何超过 5 天的机密或配置图,应将其删除. + +**有用的命令:** + +``` +# List secrets and config maps ordered by created date +kubectl get secret,cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-' + +# Delete all secrets that are 5 to 9 days old +kubectl get secret --sort-by='{.metadata.creationTimestamp}' | grep '^review-' | grep '[5-9]d$' | cut -d' ' -f1 | xargs kubectl delete secret + +# Delete all secrets that are 10 to 99 days old +kubectl get secret --sort-by='{.metadata.creationTimestamp}' | grep '^review-' | grep '[1-9][0-9]d$' | cut -d' ' -f1 | xargs kubectl delete secret + +# Delete all config maps that are 5 to 9 days old +kubectl get cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-' | grep -v 'dns-gitlab-review-app' | grep '[5-9]d$' | cut -d' ' -f1 | xargs kubectl delete cm + +# Delete all config maps that are 10 to 99 days old +kubectl get cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-' | grep -v 'dns-gitlab-review-app' | grep '[1-9][0-9]d$' | cut -d' ' -f1 | xargs kubectl delete cm +``` + +### Using K9s[](#using-k9s "Permalink") + +[K9s](https://github.com/derailed/k9s)是功能强大的命令行仪表板,可让您按标签过滤. 这可以帮助确定趋势超过[审阅应用程序资源请求的应用程序](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/review_apps/base-config.yaml) . Kubernetes 将根据资源请求将 Pod 调度到节点,并允许 CPU 使用量达到上限. + +* 在 K9s 中,您可以通过输入`/`字符来排序或添加过滤器 + * `-lrelease=<review-app-slug>` -过滤所有发布的 Pod. 这有助于确定单个部署中存在的问题 + * `-lapp=<app>` -筛选特定应用程序的所有 pod. 这有助于确定应用程序的资源使用情况. +* 您可以滚动到 Kubernetes 资源并按`d` (描述), `s` (shell), `l` (日志)进行更深入的检查 + +[![K9s](img/281606a988de9b8e23469c0de4e22062.png)](img/k9s.png) + +### Troubleshoot a pending `dns-gitlab-review-app-external-dns` Deployment[](#troubleshoot-a-pending-dns-gitlab-review-app-external-dns-deployment "Permalink") + +#### Finding the problem[](#finding-the-problem "Permalink") + +[过去](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62834) ,发生了`dns-gitlab-review-app-external-dns`部署处于挂起状态的情况,有效地阻止了所有 Review App 分配 DNS 记录,从而使它们无法通过域名访问. + +反过来,这阻止了 Review App 的其他组件正常启动(例如`gitlab-runner` ). + +经过一番挖掘后,我们发现在使用`systemd-mount`瞬时作用域(例如 pod)执行新安装时,新安装失败: + +``` +MountVolume.SetUp failed for volume "dns-gitlab-review-app-external-dns-token-sj5jm" : mount failed: exit status 1 +Mounting command: systemd-run +Mounting arguments: --description=Kubernetes transient mount for /var/lib/kubelet/pods/06add1c3-87b4-11e9-80a9-42010a800107/volumes/kubernetes.io~secret/dns-gitlab-review-app-external-dns-token-sj5jm --scope -- mount -t tmpfs tmpfs /var/lib/kubelet/pods/06add1c3-87b4-11e9-80a9-42010a800107/volumes/kubernetes.io~secret/dns-gitlab-review-app-external-dns-token-sj5jm +Output: Failed to start transient scope unit: Connection timed out +``` + +这可能是因为 GitLab 图表创建了 67 个资源,导致在基础 GCP 节点上创建了许多安装点. + +在[根本的问题似乎是一个`systemd`错误](https://github.com/kubernetes/kubernetes/issues/57345#issuecomment-359068048)是固定在`systemd` `v237` . 不幸的是,我们的 GCP 节点当前正在使用`v232` . + +记录下来,找出此问题的调试步骤是: + +1. 将 kubectl 上下文切换到 review-apps-ce(我们建议使用[kubectx](https://github.com/ahmetb/kubectx/) ) +2. `kubectl get pods | grep dns` +3. `kubectl describe pod <pod name>`并确认确切的错误消息 +4. 在兔子洞中找到[相关的 Kubernetes 错误报告后](https://github.com/kubernetes/kubernetes/issues/57345) ,在网上搜索确切的错误消息 +5. 通过 GCP 控制台通过 SSH 访问节点( **计算机引擎> VM 实例,**然后单击`dns-gitlab-review-app-external-dns` pod 运行的节点的" SSH"按钮) +6. In the node: `systemctl --version` => `systemd 232` +7. 收集更多信息: + * `mount | grep kube | wc -l` `mount | grep kube | wc -l` =>例如 290 + * `systemctl list-units --all | grep -i var-lib-kube | wc -l` `systemctl list-units --all | grep -i var-lib-kube | wc -l` =>例如 142 +8. 检查多少个 Pod 处于不良状态: + * 获取运行给定节点的所有 Pod: `kubectl get pods --field-selector=spec.nodeName=NODE_NAME` + * 获取给定节点上的所有`Running` pods: `kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep Running` `kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep Running` + * 在给定节点上获取所有处于不良状态的 Pod: `kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep -v 'Running' | grep -v 'Completed'` `kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep -v 'Running' | grep -v 'Completed'` + +#### Solving the problem[](#solving-the-problem "Permalink") + +为了解决该问题,我们需要(强制)耗尽一些节点: + +1. 在运行`dns-gitlab-review-app-external-dns` pod 的节点上尝试正常排水,以使 Kubernetes 自动将其移动到另一个节点: `kubectl drain NODE_NAME` +2. 如果那不起作用,您还可以通过删除所有吊舱来强制"排水"节点: `kubectl delete pods --field-selector=spec.nodeName=NODE_NAME` +3. 在节点中: + * 执行`systemctl daemon-reload`以删除无效/无效的单元 + * 如果那不能解决问题,请执行硬重启: `sudo systemctl reboot` +4. 取消封锁所有封锁的节点: `kubectl uncordon NODE_NAME`封锁`kubectl uncordon NODE_NAME` + +同时,由于大多数 Review App 处于损坏状态,因此我们将其删除以清理非`Running` Pod 列表. 以下是一个命令,用于根据其上次部署日期(当前日期为当时的 6 月 6 日)删除 Review Apps, + +``` +helm ls -d | grep "Jun 4" | cut -f1 | xargs helm delete --purge +``` + +#### Mitigation steps taken to avoid this problem in the future[](#mitigation-steps-taken-to-avoid-this-problem-in-the-future "Permalink") + +我们用较小的计算机创建了一个新的节点池,这样一来,将来计算机就不太可能遇到"装载点过多"的问题. + +## Frequently Asked Questions[](#frequently-asked-questions "Permalink") + +**在每次测试运行时触发 CNG 映像生成是否过多? 这将创建数千个未使用的 Docker 映像.** + +> 我们必须从某个地方开始,以后再改进. 另外,我们正在使用 CNG-mirror 项目来存储这些 Docker 映像,以便我们可以在某个时候清除注册表,并使用一个新的,空的注册表. + +**我们如何确保它免受滥用? 应用程序向世界开放,因此我们需要找到一种方法将其限制为仅限我们自己.** + +> This isn’t enabled for forks. + +## Other resources[](#other-resources "Permalink") + +* [Review Apps integration for CE/EE (presentation)](https://docs.google.com/presentation/d/1QPLr6FO4LduROU8pQIPkX1yfGvD13GEJIBOenqoKxR8/edit?usp=sharing) +* [Stability issues](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/212) + +### Helpful command line tools[](#helpful-command-line-tools "Permalink") + +* [K9s-](https://github.com/derailed/k9s)启用跨 Pod 的 CLI 仪表板并启用按标签过滤 +* [船尾](https://github.com/wercker/stern) -基于标签/字段选择器启用跨 Pod 日志拖尾 + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/_book/docs/631.md b/_book/docs/631.md new file mode 100644 index 0000000000000000000000000000000000000000..ad7d6df2cdba98cdcba5fa417e322dd23b1b48dd --- /dev/null +++ b/_book/docs/631.md @@ -0,0 +1,26 @@ +# Smoke Tests + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/smoke.html](https://docs.gitlab.com/ee/development/testing_guide/smoke.html) + +# Smoke Tests[](#smoke-tests "Permalink") + +在任何测试套件中,必须有烟雾测试. 简而言之,冒烟测试将运行来自 GitLab QA 的快速端到端功能测试,旨在针对指定环境运行以确保基本功能正常运行. + +当前,我们的套件包括以下基本功能: + +* 用户标准认证 +* SSH 密钥创建和添加到用户 +* 项目简单创建 +* 启用 Auto-DevOps 的项目创建 +* 问题创建 +* 问题用户提及 +* 合并请求创建 +* 片段创建 + +冒烟测试具有`:smoke` RSpec 元数据. + +有关[端到端测试](end_to_end/index.html)的更多详细信息,请参见[端到端](end_to_end/index.html)测试. + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/_book/docs/632.md b/_book/docs/632.md new file mode 100644 index 0000000000000000000000000000000000000000..0a6a912c7a058549923ef70f90257d64ab1920e9 --- /dev/null +++ b/_book/docs/632.md @@ -0,0 +1,665 @@ +# Testing best practices + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/best_practices.html](https://docs.gitlab.com/ee/development/testing_guide/best_practices.html) + +* [Test Design](#test-design) +* [Test speed](#test-speed) +* [RSpec](#rspec) + * [General guidelines](#general-guidelines) + * [Coverage](#coverage) + * [System / Feature tests](#system--feature-tests) + * [Debugging Capybara](#debugging-capybara) + * [Live debug](#live-debug) + * [Run `:js` spec in a visible browser](#run-js-spec-in-a-visible-browser) + * [Screenshots](#screenshots) + * [Fast unit tests](#fast-unit-tests) + * [`let` variables](#let-variables) + * [Common test setup](#common-test-setup) + * [Time-sensitive tests](#time-sensitive-tests) + * [Feature flags in tests](#feature-flags-in-tests) + * [`stub_feature_flags` vs `Feature.enable*`](#stub_feature_flags-vs-featureenable) + * [Stubbing gate](#stubbing-gate) + * [Pristine test environments](#pristine-test-environments) + * [SQL database](#sql-database) + * [Redis](#redis) + * [Background jobs / Sidekiq](#background-jobs--sidekiq) + * [DNS](#dns) + * [Filesystem](#filesystem) + * [Persistent in-memory application state](#persistent-in-memory-application-state) + * [Table-based / Parameterized tests](#table-based--parameterized-tests) + * [Prometheus tests](#prometheus-tests) + * [Matchers](#matchers) + * [`be_like_time`](#be_like_time) + * [`have_gitlab_http_status`](#have_gitlab_http_status) + * [Testing query performance](#testing-query-performance) + * [QueryRecorder](#queryrecorder) + * [GitalyClient](#gitalyclient) + * [Shared contexts](#shared-contexts) + * [Shared examples](#shared-examples) + * [Helpers](#helpers) + * [Factories](#factories) + * [Fixtures](#fixtures) + * [Repositories](#repositories) + * [Configuration](#configuration) + * [Test environment logging](#test-environment-logging) + +# Testing best practices[](#testing-best-practices "Permalink") + +## Test Design[](#test-design "Permalink") + +在 manbetx 客户端打不开的测试是头等公民,而不是事后的想法. 在设计功能时,必须考虑测试的设计,这一点很重要. + +在实现功能时,我们考虑以正确的方式开发正确的功能,这有助于我们将范围缩小到可管理的水平. 在对功能进行测试时,我们必须考虑开发正确的测试,然后涵盖测试可能失败的*所有*重要方式,这可能很快将我们的范围扩大到难以管理的水平. + +测试启发法可以帮助解决此问题. 它们简明地解决了错误在我们的代码中表现出来的许多常见方式. 在设计测试时,请花一些时间来回顾已知的测试启发法,以告知我们的测试设计. 我们可以在" [测试工程"](https://about.gitlab.com/handbook/engineering/quality/test-engineering/#test-heuristics)部分的"手册"中找到一些有用的启发式方法. + +## Test speed[](#test-speed "Permalink") + +GitLab has a massive test suite that, without [parallelization](ci.html#test-suite-parallelization-on-the-ci), can take hours to run. It’s important that we make an effort to write tests that are accurate and effective *以及* fast. + +关于测试性能,需要牢记以下几点: + +* `instance_double`和`spy`比`FactoryBot.build(...)`快 +* `FactoryBot.build(...)`和`.build_stubbed`比`.create`更快. +* 当`build` , `build_stubbed` , `attributes_for` , `spy`或`instance_double`可以使用时,不要`create`对象. 数据库持久性很慢! +* 除非*实际*需要测试有效,否则不要将功能标记为需要 JavaScript(通过 RSpec 中的`:js` ). 无头浏览器测试很慢! + +## RSpec[](#rspec "Permalink") + +要运行 RSpec 测试: + +``` +# run test for a file +bin/rspec spec/models/project_spec.rb + +# run test for the example on line 10 on that file +bin/rspec spec/models/project_spec.rb:10 + +# run tests matching the example name has that string +bin/rspec spec/models/project_spec.rb -e associations + +# run all tests, will take hours for GitLab codebase! +bin/rspec +``` + +使用[Guard](https://github.com/guard/guard)连续监视更改,并仅运行匹配的测试: + +``` +bundle exec guard +``` + +一起使用 spring 和 guard 时,请改用`SPRING=1 bundle exec guard`来使用 spring. + +使用[Factory Doctor](https://test-prof.evilmartians.io/#/factory_doctor.md)查找不必要的数据库操作案例,这可能会导致测试缓慢. + +``` +# run test for path +FDOC=1 bin/rspec spec/[path]/[to]/[spec].rb +``` + +### General guidelines[](#general-guidelines "Permalink") + +* 使用单个顶级`RSpec.describe ClassName`块. +* 使用`.method`来描述类方法,并使用`#method`来描述实例方法. +* 使用`context`测试分支逻辑. +* 尝试使测试的顺序与类中的顺序匹配. +* 尝试遵循[四阶段测试](https://thoughtbot.com/blog/four-phase-test)模式,使用换行符分隔各个阶段. +* 使用`Gitlab.config.gitlab.host`而不是硬编码`'localhost'` +* 不要断言序列生成的属性的绝对值(请参见[Gotchas](../gotchas.html#do-not-assert-against-the-absolute-value-of-a-sequence-generated-attribute) ). +* 避免使用`expect_any_instance_of`或`allow_any_instance_of` (见[陷阱](../gotchas.html#do-not-assert-against-the-absolute-value-of-a-sequence-generated-attribute) ). +* 不要将`:each`参数提供给钩子,因为它是默认值. +* 在钩子`before`和`after` ,最好将它的作用域设置为`:context`不是`:all` +* 当使用作用在给定元素上的`execute_script` `evaluate_script("$('.js-foo').testSomething()")` (或`execute_script` )时,请事先使用 Capybara 匹配器(例如`find('.js-foo')` )以确保该元素实际存在. +* 使用`focus: true`可以隔离要运行的部分规范. +* 如果测试中有多个期望,请使用[`:aggregate_failures`](https://relishapp.com/rspec/rspec-core/docs/expectation-framework-integration/aggregating-failures) . +* 对于[空的测试描述块](https://github.com/rubocop-hq/rspec-style-guide#it-and-specify) ,如果测试是不言自明的,请使用`specify`而不是`it do` . +* 当您需要一个实际上不存在的 ID / IID /访问级别时,请使用`non_existing_record_id` / `non_existing_record_iid` / `non_existing_record_access_level` . 使用 123、1234 甚至 999 都很容易,因为在 CI 运行的情况下,这些 ID 实际上可能存在于数据库中. + +### Coverage[](#coverage "Permalink") + +[`simplecov`](https://github.com/colszowka/simplecov)用于生成代码测试覆盖率报告. 它们是在 CI 上自动生成的,但在本地运行测试时不会自动生成. 要在计算机上运行规格文件时生成部分报告,请设置`SIMPLECOV`环境变量: + +``` +SIMPLECOV=1 bundle exec rspec spec/models/repository_spec.rb +``` + +覆盖率报告会生成到应用程序根目录下的`coverage`文件夹中,您可以在浏览器中打开这些报告,例如: + +``` +firefox coverage/index.html +``` + +使用覆盖率报告来确保您的测试覆盖 100%的代码. + +### System / Feature tests[](#system--feature-tests "Permalink") + +**注意:**在编写新的系统测试之前, [请考虑**不要**编写一个](testing_levels.html#consider-not-writing-a-system-test) ! + +* Feature specs should be named `ROLE_ACTION_spec.rb`, such as `user_changes_password_spec.rb`. +* 使用描述成功和失败路径的方案标题. +* 避免方案标题未添加任何信息,例如"成功". +* 避免场景标题重复功能标题. +* Create only the necessary records in the database +* 测试一条幸福的道路和一条不太幸福的道路,仅此而已 +* 所有其他可能的路径均应通过单元测试或集成测试进行测试 +* 测试页面上显示的内容,而不是 ActiveRecord 模型的内部. 例如,如果您要验证是否已创建记录,请添加期望其记录显示在页面上的期望,而不是`Model.count`增加一. +* 可以查找 DOM 元素,但不要滥用它,因为它会使测试更加脆弱 + +#### Debugging Capybara[](#debugging-capybara "Permalink") + +有时您可能需要通过观察浏览器行为来调试 Capybara 测试. + +#### Live debug[](#live-debug "Permalink") + +您可以使用规范中的`live_debug`方法暂停 Capybara 并在浏览器中查看网站. 当前页面将在默认浏览器中自动打开. 您可能需要先登录(当前用户的凭据显示在终端中). + +要恢复测试运行,请按任意键. + +例如: + +``` +$ bin/rspec spec/features/auto_deploy_spec.rb:34 +Running via Spring preloader in process 8999 +Run options: include {:locations=>{"./spec/features/auto_deploy_spec.rb"=>[34]}} + +Current example is paused for live debugging +The current user credentials are: user2 / 12345678 +Press any key to resume the execution of the example! +Back to the example! +. + +Finished in 34.51 seconds (files took 0.76702 seconds to load) +1 example, 0 failures +``` + +注意: `live_debug`仅在启用 JavaScript 的规范上起作用. + +#### Run `:js` spec in a visible browser[](#run-js-spec-in-a-visible-browser "Permalink") + +使用`CHROME_HEADLESS=0`运行规范,例如: + +``` +CHROME_HEADLESS=0 bin/rspec some_spec.rb +``` + +测试将很快进行,但这将使您对正在发生的事情有所了解. 对`CHROME_HEADLESS=0`使用`live_debug`暂停打开的浏览器,并且不会再次打开该页面. 这可用于调试和检查元素. + +您还可以添加`byebug`或`binding.pry`暂停执行,并[步通过](../pry_debugging.html#stepping)测试. + +#### Screenshots[](#screenshots "Permalink") + +我们使用`capybara-screenshot` gem 在失败时自动截屏. 在 CI 中,您可以下载这些文件作为作业工件. + +另外,您可以通过添加以下方法在测试中的任何时候手动获取屏幕截图. 请确保在不再需要它们时将其删除! 有关更多信息,请参见[https://github.com/mattheworiordan/capybara-screenshot#manual-screenshots](https://github.com/mattheworiordan/capybara-screenshot#manual-screenshots) . + +在`:js`规范中添加`screenshot_and_save_page`以截图 Capybara 看到的内容,并保存页面源代码. + +在`:js`规范中添加`screenshot_and_open_image`以截图 Capybara 看到的内容,并自动打开图像. + +由此创建的 HTML 转储缺少 CSS. 这导致它们看起来与实际应用程序截然不同. 有一个添加 CSS 的[小技巧](https://gitlab.com/gitlab-org/gitlab-foss/snippets/1718469) ,可简化调试过程. + +### Fast unit tests[](#fast-unit-tests "Permalink") + +某些类与 Rails 完全隔离,您应该能够测试它们,而不会因 Rails 环境和 Bundler 的`:default`组的 gem 加载而增加开销. 在这些情况下,您可以在测试文件中`require 'fast_spec_helper'`而不是`require 'spec_helper'` ,并且由于以下原因,测试应该运行得非常快: + +* 宝石加载被跳过 +* Rails 应用启动被跳过 +* 跳过了 GitLab Shell 和 Gitaly 设置 +* 测试存储库设置被跳过 + +`fast_spec_helper`还支持`lib/`目录中的自动加载类. 这意味着只要您的类/模块仅使用`lib/`目录中的代码,就无需显式加载任何依赖项. `fast_spec_helper`还将加载所有 ActiveSupport 扩展,包括 Rails 环境中常用的核心扩展. + +请注意,在某些情况下,当代码使用 gems 或`lib/`没有依赖项时,您可能仍必须使用`require_dependency`加载某些依赖项. + +例如,如果要测试调用`Gitlab::UntrustedRegexp`类的代码,该类在`Gitlab::UntrustedRegexp`使用`re2`库,则应将`require_dependency 're2'`添加到需要`re2` gem 的库文件中,以达到此要求明确,也可以将其添加到规范本身中,但最好使用前者. + +加载使用`fast_spec_helper`测试大约需要一秒钟,而不是常规`spec_helper`的 30+秒. + +### `let` variables[](#let-variables "Permalink") + +GitLab 的 RSpec 套件广泛使用`let` (以及严格的非延迟版本`let!` )变量来减少重复. 但是,有时这有时要以[清楚为代价](https://thoughtbot.com/blog/lets-not) ,因此我们需要为以后的使用设置一些准则: + +* `let!` 变量优于实例变量. `let`变量比`let!`可取`let!` 变量. 局部变量比`let`变量更可取. +* 使用`let`可以减少整个规格文件中的重复项. +* 不要使用`let`定义单个测试使用的变量; 在测试的`it`块中将它们定义为局部变量. +* 不要在顶层`describe`块中定义只用于更深层嵌套`context`或`describe`块的`let`变量. 使定义尽可能靠近使用位置. +* 尽量避免将一个`let`变量的定义覆盖另一个. +* 不要定义只供另一个定义使用的`let`变量. 请改用辅助方法. +* `let!` 变量应该只在需要与定义为了严格评估的情况下使用,否则`let`就足够了. 请记住, `let`是惰性的,在被引用之前不会被评估. + +### Common test setup[](#common-test-setup "Permalink") + +在某些情况下,无需为每个示例再次创建相同的对象以进行测试. 例如,需要一个项目和该项目的访客来测试同一项目上的问题,一个项目和一个用户将对整个文件进行测试. + +尽可能不要使用`before(:all)`或`before(:context)`实现此目的. 如果这样做,您将需要手动清理数据,因为这些挂钩在数据库事务外部运行. + +相反,这可以通过使用来实现[`let_it_be`](https://test-prof.evilmartians.io/#/let_it_be)变量和[`before_all`](https://test-prof.evilmartians.io/#/before_all)钩从[`test-prof`的宝石](https://rubygems.org/gems/test-prof) . + +``` +let_it_be(:project) { create(:project) } +let_it_be(:user) { create(:user) } + +before_all do + project.add_guest(user) +end +``` + +这将仅为此上下文创建一个`Project` , `User`和`ProjectMember` . + +`let_it_be`和`before_all`在嵌套上下文中也可用. 使用事务回滚自动处理上下文后进行清理. + +Note that if you modify an object defined inside a `let_it_be` block, then you will need to reload the object as needed, or specify the `reload` option to reload for every example. + +``` +let_it_be(:project, reload: true) { create(:project) } +``` + +您还可以指定`refind`选项以完全加载新对象. + +``` +let_it_be(:project, refind: true) { create(:project) } +``` + +### Time-sensitive tests[](#time-sensitive-tests "Permalink") + +在基于 Ruby 的测试中可以使用[Timecop](https://github.com/travisjeffery/timecop)来验证对时间敏感的事物. 任何锻炼或验证时间敏感的测试都应使用 Timecop 来防止瞬态测试失败. + +Example: + +``` +it 'is overdue' do + issue = build(:issue, due_date: Date.tomorrow) + + Timecop.freeze(3.days.from_now) do + expect(issue).to be_overdue + end +end +``` + +### Feature flags in tests[](#feature-flags-in-tests "Permalink") + +在基于 Ruby 的测试中,默认情况下所有功能标志都已启用. + +要在测试中禁用功能标记,请使用`stub_feature_flags`帮助器. 例如,要在测试中全局禁用`ci_live_trace`功能标志: + +``` +stub_feature_flags(ci_live_trace: false) + +Feature.enabled?(:ci_live_trace) # => false +``` + +如果您希望设置一个仅对某些角色而不对其他角色启用功能标志的测试,则可以在传递给助手的选项中指定此功能. 例如,要为特定项目启用`ci_live_trace`功能标记: + +``` +project1, project2 = build_list(:project, 2) + +# Feature will only be enabled for project1 +stub_feature_flags(ci_live_trace: project1) + +Feature.enabled?(:ci_live_trace) # => false +Feature.enabled?(:ci_live_trace, project1) # => true +Feature.enabled?(:ci_live_trace, project2) # => false +``` + +这代表了 FlipperGate 的实际行为: + +1. 您可以启用要启用的指定角色的替代 +2. 您可以禁用(删除)指定角色的替代,并还原为默认状态 +3. 无法建模您明确禁用指定的参与者 + +``` +Feature.enable(:my_feature) +Feature.disable(:my_feature, project1) +Feature.enabled?(:my_feature) # => true +Feature.enabled?(:my_feature, project1) # => true +``` + +``` +Feature.disable(:my_feature2) +Feature.enable(:my_feature2, project1) +Feature.enabled?(:my_feature2) # => false +Feature.enabled?(:my_feature2, project1) # => true +``` + +#### `stub_feature_flags` vs `Feature.enable*`[](#stub_feature_flags-vs-featureenable "Permalink") + +最好使用`stub_feature_flags`在测试环境中启用功能标志. 该方法为简单的用例提供了一个简单且描述良好的界面. + +但是,在某些情况下,需要测试更复杂的行为,例如功能标志百分比展示. 这可以使用`.enable_percentage_of_time`和`.enable_percentage_of_actors`来实现 + +``` +# Good: feature needs to be explicitly disabled, as it is enabled by default if not defined +stub_feature_flags(my_feature: false) +stub_feature_flags(my_feature: true) +stub_feature_flags(my_feature: project) +stub_feature_flags(my_feature: [project, project2]) + +# Bad +Feature.enable(:my_feature_2) + +# Good: enable my_feature for 50% of time +Feature.enable_percentage_of_time(:my_feature_3, 50) + +# Good: enable my_feature for 50% of actors/gates/things +Feature.enable_percentage_of_actors(:my_feature_4, 50) +``` + +具有定义状态的每个功能标志将在测试执行时间内保留: + +``` +Feature.persisted_names.include?('my_feature') => true +Feature.persisted_names.include?('my_feature_2') => true +Feature.persisted_names.include?('my_feature_3') => true +Feature.persisted_names.include?('my_feature_4') => true +``` + +#### Stubbing gate[](#stubbing-gate "Permalink") + +要求将作为参数传递给`Feature.enabled?` 和`Feature.disabled?` 是包含`FeatureGate`的对象. + +在规范中,您可以使用`stub_feature_flag_gate`方法,该方法可让您快速使用自定义门: + +``` +gate = stub_feature_flag_gate('CustomActor') + +stub_feature_flags(ci_live_trace: gate) + +Feature.enabled?(:ci_live_trace) # => false +Feature.enabled?(:ci_live_trace, gate) # => true +``` + +### Pristine test environments[](#pristine-test-environments "Permalink") + +单个 GitLab 测试执行的代码可以访问和修改许多数据项. 无需在测试运行之前进行仔细的准备,然后再进行清理,则测试可以更改数据,从而影响后续测试的行为. 应不惜一切代价避免这种情况! 幸运的是,现有的测试框架已经可以处理大多数情况. + +当测试环境确实受到污染时,常见的结果就是[不稳定的测试](flaky_tests.html) . 污染通常表现为顺序依赖性:运行规格 A,然后运行规格 B 会可靠地失败,但是运行规格 B,然后运行规格 A 将可靠地成功. 在这些情况下,可以使用`rspec --bisect` (或规格文件的手动成对二`rspec --bisect` )来确定哪个规格有问题. 要解决此问题,需要对测试套件如何确保原始环境有一些了解. 继续阅读以发现有关每个数据存储的更多信息! + +#### SQL database[](#sql-database "Permalink") + +这是由`database_cleaner` gem 为我们管理的. 每个规范都包含在一个事务中,一旦测试完成,该事务将回滚. 某些规范将在完成后针对每个表发出`DELETE FROM`查询; 这样可以从多个数据库连接中查看创建的行,这对于在浏览器中运行的规范或迁移规范等非常重要. + +使用这些策略而不是众所周知的`TRUNCATE TABLES`方法的结果是,主键和其他序列**不会**在整个规范中重置. 因此,如果您在规范 A 中创建一个项目,然后在规范 B 中创建一个项目,则第一个将具有`id=1` ,而第二个将具有`id=2` . + +这意味着规范**永远**不应依赖 ID 或任何其他序列生成的列的值. 为避免意外冲突,规范还应避免手动指定此类列中的任何值. 而是将它们保留为未指定状态,并在创建行后查找值. + +#### Redis[](#redis "Permalink") + +GitLab 在 Redis 中存储了两个主要的数据类别:缓存项和 Sidekiq 作业. + +在大多数规范中,Rails 缓存实际上是一个内存存储. 规格之间已替换了该代码,因此对`Rails.cache.read`和`Rails.cache.write`调用是安全的. 但是,如果某个规范直接进行 Redis 调用,则应适当地使用`:clean_gitlab_redis_cache` , `:clean_gitlab_redis_shared_state`或`:clean_gitlab_redis_queues`特征对其进行标记. + +#### Background jobs / Sidekiq[](#background-jobs--sidekiq "Permalink") + +默认情况下,Sidekiq 作业会排队到作业数组中,并且不会进行处理. 如果测试将 Sidekiq 作业排入队列并需要对其进行处理,则可以使用`:sidekiq_inline`特性. + +The `:sidekiq_might_not_need_inline` trait was added when [Sidekiq inline mode was changed to fake mode](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15479) to all the tests that needed Sidekiq to actually process jobs. Tests with this trait should be either fixed to not rely on Sidekiq processing jobs, or their `:sidekiq_might_not_need_inline` trait should be updated to `:sidekiq_inline` if the processing of background jobs is needed/expected. + +**注意:** `perform_enqueued_jobs`的用法仅对测试延迟的邮件传递有用,因为我们的 Sidekiq 工作者不是从`ApplicationJob` / `ActiveJob::Base`继承. + +#### DNS[](#dns "Permalink") + +DNS 请求在测试套件中普遍存在(截至[!22368](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22368) ),因为 DNS 可能会导致问题,具体取决于开发人员的本地网络. 在`spec/support/dns.rb`有可用的 RSpec 标签,如果您需要绕过 DNS 存根,则可以将其应用于测试,例如: + +``` +it "really connects to Prometheus", :permit_dns do +``` + +而且,如果需要更具体的控制,则可以在`spec/support/helpers/dns_helpers.rb`实现 DNS 阻止,并且可以在其他地方调用这些方法. + +#### Filesystem[](#filesystem "Permalink") + +文件系统数据可以大致分为"存储库"和"其他所有内容". 存储库存储在`tmp/tests/repositories` . 在测试运行开始之前和测试运行结束之后,将清空此目录. 在规格之间不清空它,因此在过程的整个生命周期中,创建的存储库都在此目录中累积. 删除它们很昂贵,但是除非精心管理,否则可能会导致污染. + +为避免这种情况,在测试套件中启用了[哈希存储](../../administration/repository_storage_types.html) . 这意味着将为存储库提供一个唯一的路径,该路径取决于其项目的 ID. 由于在规范之间未重置项目 ID,因此可以确保每个规范在磁盘上获得自己的存储库,并防止在规范之间可见更改. + +如果规范手动指定了项目 ID,或直接检查`tmp/tests/repositories/`目录的状态,则它应该在运行之前和之后清理该目录. 通常,应完全避免这些模式. + +链接到数据库对象的其他文件类别(例如上载)通常以相同的方式进行管理. 在规范中启用了散列存储后,它们将在 ID 确定的位置写入磁盘,因此不会发生冲突. + +一些规范通过将`:legacy_storage`特征传递给`projects`工厂来禁用哈希存储. 执行此操作的规范绝**不能**覆盖项目或其任何组的`path` . 默认路径包含项目 ID,因此不会发生冲突. 但是,如果两个规范创建具有相同路径的`:legacy_storage`项目,则它们将使用磁盘上的相同存储库并导致测试环境污染. + +其他文件必须由规范手动管理. 例如,如果运行创建`tmp/test-file.csv`文件的代码,则规范必须确保在清理过程中删除了该文件. + +#### Persistent in-memory application state[](#persistent-in-memory-application-state "Permalink") + +给定`rspec`运行中的所有规范共享相同的 Ruby 进程,这意味着它们可以通过修改规范之间可访问的 Ruby 对象相互影响. 实际上,这意味着全局变量和常量(包括 Ruby 类,模块等). + +全局变量通常不应修改. 如果绝对必要,则可以使用如下所示的块来确保更改被回滚: + +``` +around(:each) do |example| + old_value = $0 + + begin + $0 = "new-value" + example.run + ensure + $0 = old_value + end +end +``` + +如果规范需要修改常量,则应使用`stub_const`帮助器以确保更改被回滚. + +如果需要修改`ENV`常量的内容,则可以改用`stub_env`帮助器方法. + +虽然大多数 Ruby **实例**不在规范之间共享,但**类**和**模块**通常是共享的. 类和模块实例变量,访问器,类变量和其他有状态习语应与全局变量一样对待-除非必须修改,否则请勿对其进行修改! 特别是,最好使用期望值或依赖项注入以及存根,以避免进行修改. 如果没有其他选择,可以使用类似于上面的全局变量示例的`around`块,但应尽可能避免这种情况. + +### Table-based / Parameterized tests[](#table-based--parameterized-tests "Permalink") + +这种测试风格用于执行一段具有广泛输入范围的代码. 通过一次指定测试用例,并在每个输入和预期输出表的旁边,可以使您的测试更易于阅读和紧凑. + +我们使用[RSpec :: Parameterized](https://github.com/tomykaira/rspec-parameterized) gem. 一个简短的示例,使用表语法并检查 Ruby 相等性是否为一系列输入,可能看起来像这样: + +``` +describe "#==" do + using RSpec::Parameterized::TableSyntax + + where(:a, :b, :result) do + 1 | 1 | true + 1 | 2 | false + true | true | true + true | false | false + end + + with_them do + it { expect(a == b).to eq(result) } + + it 'is isomorphic' do + expect(b == a).to eq(result) + end + end +end +``` + +**注意:**仅将简单值用作`where`块中的输入. 使用 proc,有状态对象,FactoryBot 创建的对象等可能导致[意外结果](https://github.com/tomykaira/rspec-parameterized/issues/8) . + +### Prometheus tests[](#prometheus-tests "Permalink") + +可以将 Prometheus 度量从一次测试运行保存到另一次测试. 为了确保在每个示例之前重置指标,请在 RSpec 测试中添加`:prometheus`标记. + +### Matchers[](#matchers "Permalink") + +应该创建自定义匹配器以阐明意图和/或隐藏 RSpec 期望的复杂性. 它们应放在`spec/support/matchers/` . 如果匹配器仅适用于某种类型的规范(例如功能,请求等),则可以放在子文件夹中,但如果它们适用于多种类型的规范,则不应该放在子文件夹中. + +#### `be_like_time`[](#be_like_time "Permalink") + +从数据库返回的时间的精度可能与 Ruby 中的时间对象不同,因此在规格比较时我们需要灵活的容差. 我们可以使用`be_like_time`来比较时间在彼此之间一秒之内. + +Example: + +``` +expect(metrics.merged_at).to be_like_time(time) +``` + +#### `have_gitlab_http_status`[](#have_gitlab_http_status "Permalink") + +`have_gitlab_http_status`使用`have_http_status`而不是`have_http_status`和`have_http_status` `expect(response.status).to` `have_http_status` ,因为只要状态不匹配,前者还可以显示响应主体. 每当某些测试开始中断时,这将非常有用,我们很想知道为什么不编辑源代码并重新运行测试. + +每当它显示 500 内部服务器错误时,此功能特别有用. + +在数字表示形式`206` `:no_content`命名为 HTTP 的状态,如`:no_content` . 请参阅[支持的状态代码](https://github.com/rack/rack/blob/f2d2df4016a906beec755b63b4edfcc07b58ee05/lib/rack/utils.rb#L490)列表. + +Example: + +``` +expect(response).to have_gitlab_http_status(:ok) +``` + +### Testing query performance[](#testing-query-performance "Permalink") + +测试查询性能使我们能够: + +* 断言代码块中不存在 N + 1 个问题. +* 确保代码块中的查询数量不会被忽略. + +#### QueryRecorder[](#queryrecorder "Permalink") + +`QueryRecorder`允许分析和测试在给定代码块中执行的数据库查询的数量. + +有关更多详细信息,请参见[`QueryRecorder`](../query_recorder.html)部分. + +#### GitalyClient[](#gitalyclient "Permalink") + +`Gitlab::GitalyClient.get_request_count` allows tests of the number of Gitaly queries made by a given block of code: + +有关更多详细信息,请参见[`Gitaly Request Counts`](../gitaly.html#request-counts)部分. + +### Shared contexts[](#shared-contexts "Permalink") + +可以内联声明仅在一个规范文件中使用的共享上下文. 一个以上规范文件使用的任何共享上下文: + +* 应该放在`spec/support/shared_contexts/` . +* 如果它们仅适用于某种类型的规范(例如功能,请求等),则可以放在子文件夹中,但如果它们适用于多种类型的规范,则不应放在子文件夹中. + +每个文件应仅包含一个上下文并具有描述性名称,例如`spec/support/shared_contexts/controllers/githubish_import_controller_shared_context.rb` . + +### Shared examples[](#shared-examples "Permalink") + +可以内联声明仅在一个规范文件中使用的共享示例. 多个规范文件使用的任何共享示例: + +* 应该放在`spec/support/shared_examples/` . +* 如果它们仅适用于某种类型的规范(例如功能,请求等),则可以放在子文件夹中,但如果它们适用于多种类型的规范,则不应放在子文件夹中. + +每个文件应仅包含一个上下文并具有描述性名称,例如`spec/support/shared_examples/controllers/githubish_import_controller_shared_example.rb` . + +### Helpers[](#helpers "Permalink") + +帮助程序通常是提供一些隐藏特定 RSpec 示例复杂性的方法的模块. 如果不希望与其他规范共享,则可以在 RSpec 文件中定义帮助程序. 否则,应将它们放在`spec/support/helpers/` . 如果助手仅适用于某种类型的规范(例如功能,请求等),则可以放在子文件夹中,但如果它们适用于多种类型的规范,则不应放在子文件夹中. + +助手应遵循 Rails 的命名/命名空间约定. 例如`spec/support/helpers/cycle_analytics_helpers.rb`应该定义: + +``` +module Spec + module Support + module Helpers + module CycleAnalyticsHelpers + def create_commit_referencing_issue(issue, branch_name: random_git_name) + project.repository.add_branch(user, branch_name, 'master') + create_commit("Commit for ##{issue.iid}", issue.project, user, branch_name) + end + end + end + end +end +``` + +助手不应更改 RSpec 配置. 例如,上述帮助器模块不应包括: + +``` +RSpec.configure do |config| + config.include Spec::Support::Helpers::CycleAnalyticsHelpers +end +``` + +### Factories[](#factories "Permalink") + +GitLab 使用[factory_bot](https://github.com/thoughtbot/factory_bot)替代测试夹具. + +* 工厂定义存在于`spec/factories/` ,使用其对应模型的复数形式命名( `User`工厂在`users.rb`中定义). +* 每个文件应该只有一个顶级工厂定义. +* FactoryBot 方法混入了所有 RSpec 组. 这意味着您可以(并且应该)调用`create(...)`而不是`FactoryBot.create(...)` . +* 利用[特征](https://www.rubydoc.info/gems/factory_bot/file/GETTING_STARTED.md#traits)来清理定义和用法. +* 定义工厂时,请勿定义结果记录通过验证不需要的属性. +* 从工厂实例化时,不要提供测试不需要的属性. +* 工厂不必仅限于`ActiveRecord`对象. [参见示例](https://gitlab.com/gitlab-org/gitlab-foss/commit/0b8cefd3b2385a21cfed779bd659978c0402766d) . + +### Fixtures[](#fixtures "Permalink") + +所有固定装置应放置在`spec/fixtures/` . + +### Repositories[](#repositories "Permalink") + +测试某些功能(例如,合并合并请求)需要在测试环境中具有某种状态的 Git 存储库. GitLab 在某些常见情况下会维护[`gitlab-test`](https://gitlab.com/gitlab-org/gitlab-test)存储库-您可以确保该存储库的副本与`:repository`特性一起用于项目工厂: + +``` +let(:project) { create(:project, :repository) } +``` + +可以的话,请考虑使用`:custom_repo`特性而不是`:repository` . 这使您可以精确地指定哪些文件将出现在项目存储库的`master`分支中. 例如: + +``` +let(:project) do + create( + :project, :custom_repo, + files: { + 'README.md' => 'Content here', + 'foo/bar/baz.txt' => 'More content here' + } + ) +end +``` + +这将创建一个包含两个文件的存储库,这两个文件具有默认权限和指定的内容. + +### Configuration[](#configuration "Permalink") + +RSpec 配置文件是更改 RSpec 配置的文件(即`RSpec.configure do |config|`块). 它们应放在`spec/support/` . + +每个文件都应与特定域相关,例如`spec/support/capybara.rb` , `spec/support/carrierwave.rb`等. + +如果 helpers 模块仅适用于某种规格,则应在`config.include`调用中添加修饰符. 例如,如果`spec/support/helpers/cycle_analytics_helpers.rb`仅适用于`:lib`和`type: :model` specs,则应编写以下内容: + +``` +RSpec.configure do |config| + config.include Spec::Support::Helpers::CycleAnalyticsHelpers, :lib + config.include Spec::Support::Helpers::CycleAnalyticsHelpers, type: :model +end +``` + +If a configuration file only consists of `config.include`, you can add these `config.include` directly in `spec/spec_helper.rb`. + +对于非常通用的帮助程序,请考虑将它们包括在`spec/support/rspec.rb`文件使用的`spec/fast_spec_helper.rb`文件中. 有关`spec/fast_spec_helper.rb`文件的更多详细信息,请参见[快速单元测试](#fast-unit-tests) . + +### Test environment logging[](#test-environment-logging "Permalink") + +在运行测试时,会自动配置并启动用于测试环境的服务,包括 Gitaly,Workhorse,Elasticsearch 和 Capybara. 在 CI 中运行时,或者如果需要安装服务,则测试环境将记录有关设置时间的信息,并产生如下日志消息: + +``` +==> Setting up Gitaly... + Gitaly set up in 31.459649 seconds... + +==> Setting up GitLab Workhorse... + GitLab Workhorse set up in 29.695619 seconds... +fatal: update refs/heads/diff-files-symlink-to-image: invalid <newvalue>: 8cfca84 +From https://gitlab.com/gitlab-org/gitlab-test + * [new branch] diff-files-image-to-symlink -> origin/diff-files-image-to-symlink + * [new branch] diff-files-symlink-to-image -> origin/diff-files-symlink-to-image + * [new branch] diff-files-symlink-to-text -> origin/diff-files-symlink-to-text + * [new branch] diff-files-text-to-symlink -> origin/diff-files-text-to-symlink + b80faa8..40232f7 snippet/multiple-files -> origin/snippet/multiple-files + * [new branch] testing/branch-with-#-hash -> origin/testing/branch-with-#-hash + +==> Setting up GitLab Elasticsearch Indexer... + GitLab Elasticsearch Indexer set up in 26.514623 seconds... +``` + +当在本地运行并且不需要执行任何操作时,将忽略此信息. 如果您始终希望看到这些消息,请设置以下环境变量: + +``` +GITLAB_TESTING_LOG_LEVEL=debug +``` + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/_book/docs/633.md b/_book/docs/633.md new file mode 100644 index 0000000000000000000000000000000000000000..24dcb4a14533192b21f5a10cba738d1302ec46d4 --- /dev/null +++ b/_book/docs/633.md @@ -0,0 +1,342 @@ +# Testing levels + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/testing_levels.html](https://docs.gitlab.com/ee/development/testing_guide/testing_levels.html) + +* [Unit tests](#unit-tests) + * [Frontend unit tests](#frontend-unit-tests) + * [When to use unit tests](#when-to-use-unit-tests) + * [When *not* to use unit tests](#when-not-to-use-unit-tests) + * [What to mock in unit tests](#what-to-mock-in-unit-tests) + * [What *not* to mock in unit tests](#what-not-to-mock-in-unit-tests) + * [Frontend component tests](#frontend-component-tests) + * [When to use component tests](#when-to-use-component-tests) + * [When *not* to use component tests](#when-not-to-use-component-tests) + * [What to mock in component tests](#what-to-mock-in-component-tests) + * [What *not* to mock in component tests](#what-not-to-mock-in-component-tests) +* [Integration tests](#integration-tests) + * [Frontend integration tests](#frontend-integration-tests) + * [When to use integration tests](#when-to-use-integration-tests) + * [What to mock in integration tests](#what-to-mock-in-integration-tests) + * [What *not* to mock in integration tests](#what-not-to-mock-in-integration-tests) + * [About controller tests](#about-controller-tests) + * [About Karma](#about-karma) +* [White-box tests at the system level (formerly known as System / Feature tests)](#white-box-tests-at-the-system-level-formerly-known-as-system--feature-tests) + * [Frontend feature tests](#frontend-feature-tests) + * [When to use feature tests](#when-to-use-feature-tests) + * [Relevant notes](#relevant-notes) + * [Consider **not** writing a system test](#consider-not-writing-a-system-test) +* [Black-box tests at the system level, aka end-to-end tests](#black-box-tests-at-the-system-level-aka-end-to-end-tests) + * [Smoke tests](#smoke-tests) + * [GitLab QA orchestrator](#gitlab-qa-orchestrator) +* [EE-specific tests](#ee-specific-tests) +* [How to test at the correct level?](#how-to-test-at-the-correct-level) + * [Frontend-related tests](#frontend-related-tests) + +# Testing levels[](#testing-levels "Permalink") + +[![Testing priority triangle](img/35460a8c847cde5f9e477c80231d7f8b.png)](img/testing_triangle.png) + +*此图说明了我们使用的每种测试类型的相对优先级. `e2e`代表端到端.* + +截至 2019-05-01,我们每个级别的测试分布如下: + +| 测试等级 | 社区版 | 企业版 | 社区+企业版 | +| --- | --- | --- | --- | +| 系统级别的黑盒测试(也称为端到端或 QA 测试) | 68 (0.14%) | 31 (0.2%) | 99 (0.17%) | +| 系统级别的白盒测试(也称为系统或功能测试) | 5,471 (11.9%) | 969 (7.4%) | 6440 (10.9%) | +| 整合测试 | 8,333 (18.2%) | 2,244 (17.2%) | 10,577 (17.9%) | +| 单元测试 | 32,031 (69.7%) | 9,778 (75.1%) | 41,809 (71%) | + +## Unit tests[](#unit-tests "Permalink") + +正式定义: [https](https://en.wikipedia.org/wiki/Unit_testing) : [//en.wikipedia.org/wiki/Unit_testing](https://en.wikipedia.org/wiki/Unit_testing) + +这类测试可确保单个代码单元(一种方法)按预期工作(给定输入,它具有可预测的输出). 这些测试应尽可能隔离. 例如,对数据库不做任何事情的模型方法不需要数据库记录. 不需要数据库记录的类应尽可能使用存根/双精度数. + +| 代码路径 | 测试路径 | 测试引擎 | Notes | +| --- | --- | --- | --- | +| `app/assets/javascripts/` | `spec/javascripts/`, `spec/frontend/` | 因果 | " [前端测试指南"](frontend_testing.html)部分中的更多详细信息. | +| `app/finders/` | `spec/finders/` | RSpec |   | +| `app/graphql/` | `spec/graphql/` | RSpec |   | +| `app/helpers/` | `spec/helpers/` | RSpec |   | +| `app/models/` | `spec/models/` | RSpec |   | +| `app/policies/` | `spec/policies/` | RSpec |   | +| `app/presenters/` | `spec/presenters/` | RSpec |   | +| `app/serializers/` | `spec/serializers/` | RSpec |   | +| `app/services/` | `spec/services/` | RSpec |   | +| `app/uploaders/` | `spec/uploaders/` | RSpec |   | +| `app/validators/` | `spec/validators/` | RSpec |   | +| `app/views/` | `spec/views/` | RSpec |   | +| `app/workers/` | `spec/workers/` | RSpec |   | +| `bin/` | `spec/bin/` | RSpec |   | +| `config/` | `spec/config/` | RSpec |   | +| `config/initializers/` | `spec/initializers/` | RSpec |   | +| `config/routes.rb`, `config/routes/` | `spec/routing/` | RSpec |   | +| `config/puma.example.development.rb`, `config/unicorn.rb.example` | `spec/rack_servers/` | RSpec |   | +| `db/` | `spec/db/` | RSpec |   | +| `db/{post_,}migrate/` | `spec/migrations/` | RSpec | 更多信息,请参见《 [Testing Rails 迁移指南》](testing_migrations_guide.html) . | +| `Gemfile` | `spec/dependencies/`, `spec/sidekiq/` | RSpec |   | +| `lib/` | `spec/lib/` | RSpec |   | +| `lib/tasks/` | `spec/tasks/` | RSpec |   | +| `rubocop/` | `spec/rubocop/` | RSpec |   | +| `spec/factories` | `spec/factories_spec.rb` | RSpec |   | + +### Frontend unit tests[](#frontend-unit-tests "Permalink") + +Unit tests are on the lowest abstraction level and typically test functionality that is not directly perceivable by a user. + +图 RL plain [普通 JavaScript]; Vue [Vue 组件]; feature-flags [功能标志]; 许可证检查[许可证检查]; 普通--Vuex; 普通--GraphQL; Vue--简单 Vue --- Vuex; Vue--GraphQL; 浏览器-普通 浏览器--- Vue; 普通-后端; Vuex-后端; GraphQL--后端; Vue-后端; 后端-数据库 后端-功能标记; 后端-许可证检查; 普通测试 经过 Vuex 类测试; classDef 节点颜色:#909090,填充:#f0f0f0,笔划宽度:2px,笔划:#909090 classDef 标签 stroke-width:0; classDef 测试的颜色:#000000,填充:#a0c0ff,笔划:#6666ff,笔划宽度:2px,笔划数组:5、5; 经过测试的子图; 嘲笑 等级测试 结束 + +#### When to use unit tests[](#when-to-use-unit-tests "Permalink") + +* **导出的函数和类** :导出的所有内容都可以以您无法控制的方式在各个地方重复使用. 您应该用测试记录公共接口的预期行为. +* **Vuex 操作** :任何 Vuex 操作都必须以一致的方式工作,而不依赖于触发它的组件. +* **Vuex 突变** :对于复杂的 Vuex 突变,您应该将测试与 Vuex 存储的其他部分分开,以简化问题解决的过程. + +#### When *not* to use unit tests[](#when-not-to-use-unit-tests "Permalink") + +* **非导出的函数或类** :任何未从模块导出的东西都可以视为私有或实现细节,不需要进行测试. +* **常量** :测试**常量**的值意味着将其复制,从而导致额外的工作,而又没有信心确保该值正确. +* **Vue 组件** :计算出的属性,方法和生命周期挂钩可被视为组件的实现细节,它们被组件测试隐式涵盖,并且不需要进行测试. 有关更多信息,请参见[官方 Vue 指南](https://vue-test-utils.vuejs.org/guides/#getting-started) . + +#### What to mock in unit tests[](#what-to-mock-in-unit-tests "Permalink") + +* **被测类**的状态:直接修改**被测类**的状态而不是使用类的方法可以避免测试设置中的副作用. +* **其他导出的类** :必须隔离测试每个类,以防止测试方案成倍增长. +* **如果将单个 DOM 元素作为参数传递** :对于仅在单个 DOM 元素而不是整个页面上运行的测试,创建这些元素比加载整个 HTML 固定工具便宜. +* **所有服务器请求** :在运行前端单元测试时,后端可能无法访问,因此需要模拟所有传出的请求. +* **异步后台操作** :后台操作无法停止或等待,因此它们将在以下测试中继续运行并产生副作用. + +#### What *not* to mock in unit tests[](#what-not-to-mock-in-unit-tests "Permalink") + +* **非导出的函数或类** :可以将未导出的所有内容视为该模块的私有内容,并将通过导出的类和函数进行隐式测试. +* **被测类的方法** :通过模拟**被测类的**方法,将对模拟进行测试,而不是对实际方法进行测试. +* **实用程序功能(纯功能或仅修改参数**的功能**)** :如果某个功能由于没有状态而没有副作用,则可以在测试中不对其进行模拟. +* **完整的 HTML 页面** :避免在单元测试中加载整个页面的 HTML,因为这会减慢测试速度. + +### Frontend component tests[](#frontend-component-tests "Permalink") + +组件测试涵盖了用户可以根据外部信号(例如用户输入,从其他组件触发的事件或应用程序状态)感知到的单个组件的状态. + +图 RL plain [普通 JavaScript]; Vue [Vue 组件]; feature-flags [功能标志]; 许可证检查[许可证检查]; 普通--Vuex; 普通--GraphQL; Vue--简单 Vue --- Vuex; Vue--GraphQL; 浏览器-普通 浏览器--- Vue; 普通-后端; Vuex-后端; GraphQL--后端; Vue-后端; 后端-数据库 后端-功能标记; 后端-许可证检查; 经过 Vue 测试; classDef 节点颜色:#909090,填充:#f0f0f0,笔划宽度:2px,笔划:#909090 classDef 标签 stroke-width:0; classDef 测试的颜色:#000000,填充:#a0c0ff,笔划:#6666ff,笔划宽度:2px,笔划数组:5、5; 经过测试的子图; 嘲笑 等级测试 结束 + +#### When to use component tests[](#when-to-use-component-tests "Permalink") + +* **组件视图** + +#### When *not* to use component tests[](#when-not-to-use-component-tests "Permalink") + +* **Vue 应用程序** :Vue 应用程序可能包含许多组件. 在组件级别测试它们需要太多的工作. 因此,它们在前端集成级别进行了测试. +* **HAML 模板** :HAML 模板仅包含标记,不包含前端逻辑. 因此,它们不是完整的组件. + +#### What to mock in component tests[](#what-to-mock-in-component-tests "Permalink") + +* **DOM** :在真实 DOM 上操作要比在虚拟 DOM 上慢得多. +* **被测组件的属性和状态** :与测试类类似,直接修改属性(而不是依赖组件的方法)可以避免副作用. +* **Vuex 存储库** :为了避免副作用并简化组件测试,Vuex 存储库被模拟代替. +* **所有服务器请求** :与单元测试类似,在运行组件测试时,后端可能无法访问,因此需要模拟所有传出的请求. +* **异步后台操作** :与单元测试类似,后台操作无法停止或等待. 这意味着它们将在以下测试中继续运行并产生副作用. +* **子组件** :每个组件都经过单独测试,因此要模拟子组件. 另请参见[`shallowMount()`](https://vue-test-utils.vuejs.org/api/#shallowmount) + +#### What *not* to mock in component tests[](#what-not-to-mock-in-component-tests "Permalink") + +* **被测组件的方法或计算属性** :通过模拟**被测组件的**一部分,将对模拟进行测试,而不是实际组件. +* **独立于 Vue 的函数和类** :单元测试已经涵盖了所有普通的 JavaScript 代码,无需在组件测试中进行模拟. + +## Integration tests[](#integration-tests "Permalink") + +正式定义: [https](https://en.wikipedia.org/wiki/Integration_testing) : [//en.wikipedia.org/wiki/Integration_testing](https://en.wikipedia.org/wiki/Integration_testing) + +这些测试可确保应用程序的各个部分可以很好地协同工作,而不会造成实际应用程序环境(即浏览器)的开销. 这些测试应在请求/响应级别进行声明:状态码,标头,正文. 它们对于测试权限,重定向,呈现的视图等很有用. + +| Code path | 测试路径 | 测试引擎 | Notes | +| --- | --- | --- | --- | +| `app/controllers/` | `spec/controllers/` | RSpec | 对于 N + 1 测试,请使用[请求规范](../query_recorder.html#use-request-specs-instead-of-controller-specs) | +| `app/mailers/` | `spec/mailers/` | RSpec |   | +| `lib/api/` | `spec/requests/api/` | RSpec |   | +| `app/assets/javascripts/` | `spec/javascripts/`, `spec/frontend/` | 因果 | [More details below](#frontend-integration-tests) | + +### Frontend integration tests[](#frontend-integration-tests "Permalink") + +集成测试涵盖单个页面上所有组件之间的交互. 它们的抽象级别可与用户与 UI 交互的方式进行比较. + +图 RL plain [普通 JavaScript]; Vue [Vue 组件]; feature-flags [功能标志]; 许可证检查[许可证检查]; 普通--Vuex; 普通--GraphQL; Vue--简单 Vue --- Vuex; Vue--GraphQL; 浏览器-普通 浏览器--- Vue; 普通-后端; Vuex-后端; GraphQL--后端; Vue-后端; 后端-数据库 后端-功能标记; 后端-许可证检查; 普通测试 经过 Vue 测试; 经过 Vuex 类测试; 经过 GraphQL 类测试; 经过类浏览器测试; linkStyle 0、1、2、3、4、5、6 笔画:#6666ff,笔画宽度:2px,笔划数组:5、5; classDef 节点颜色:#909090,填充:#f0f0f0,笔划宽度:2px,笔划:#909090 classDef 标签 stroke-width:0; classDef 测试的颜色:#000000,填充:#a0c0ff,笔划:#6666ff,笔划宽度:2px,笔划数组:5、5; 经过测试的子图; 嘲笑 等级测试 结束 + +#### When to use integration tests[](#when-to-use-integration-tests "Permalink") + +* **页面捆绑包( `app/assets/javascripts/pages/` `index.js`文件)** :测试页面捆绑包可确保相应的前端组件很好地集成. +* **页面捆绑之外的 Vue 应用程序** :对 Vue 应用程序进行整体测试可确保相应的前端组件很好地集成. + +#### What to mock in integration tests[](#what-to-mock-in-integration-tests "Permalink") + +* **HAML 视图(改为使用夹具)** :渲染 HAML 视图需要一个 Rails 环境,其中包括一个正在运行的数据库,您不能在前端测试中依赖它. +* **所有服务器请求** :类似于单元测试和组件测试,在运行组件测试时,后端可能无法访问,因此必须模拟所有传出的请求. +* **页面上无法感知的异步后台操作** :影响页面的后台操作必须在此级别上进行测试. 所有其他后台操作都无法停止或等待,因此它们将在以下测试中继续运行并产生副作用. + +#### What *not* to mock in integration tests[](#what-not-to-mock-in-integration-tests "Permalink") + +* **DOM** :在真实的 DOM 上进行测试可确保您的组件在预期的环境中工作. DOM 测试的一部分委托给[跨浏览器测试](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/45) . +* **组件的属性或状态** :在此级别上,所有测试只能执行用户将要执行的操作. 例如:要更改组件的状态,将触发 click 事件. +* **Vuex 存储** :整体上测试页面的前端代码时,还将涵盖 Vue 组件与 Vuex 存储之间的交互. + +### About controller tests[](#about-controller-tests "Permalink") + +在理想的世界中,控制器应该很薄. 但是,如果不是这种情况,则可以编写不使用 JavaScript 而不是控制器测试的系统或功能测试. 测试胖控制器通常涉及很多桩工作,例如: + +``` +controller.instance_variable_set(:@user, user) +``` + +并使用 Rails 5( [#23768](https://gitlab.com/gitlab-org/gitlab/-/issues/16260) )中不推荐使用的方法. + +### About Karma[](#about-karma "Permalink") + +业力同时在单元测试和集成测试类别中. 业力提供了运行 JavaScript 测试的环境,因此您可以运行单元测试(例如,测试单个 JavaScript 方法)或集成测试(例如,测试由多个组件组成的组件). + +## White-box tests at the system level (formerly known as System / Feature tests)[](#white-box-tests-at-the-system-level-formerly-known-as-system--feature-tests "Permalink") + +正式定义: + +* [https://en.wikipedia.org/wiki/System_testing](https://en.wikipedia.org/wiki/System_testing) +* [https://en.wikipedia.org/wiki/White-box_testing](https://en.wikipedia.org/wiki/White-box_testing) + +这些测试可确保 GitLab *Rails*应用程序(例如`gitlab-foss` / `gitlab` )从*浏览器的*角度正常工作. + +注意: + +* 仍需要了解应用程序内部的知识 +* 测试所需的数据通常是使用 RSpec 工厂直接创建的 +* 期望通常在数据库或对象状态上设置 + +这些测试仅在以下情况下使用: + +* 被测试的功能/组件很小 +* 对象/数据库的内部状态*需要*测试 +* 它不能在较低的水平上进行测试 + +例如,要测试给定页面上的面包屑,编写系统测试很有意义,因为它是一个很小的组件,无法在单元或控制器级别进行测试. + +仅测试幸福的道路,但要确保为使用更好的测试无法在较低级别上捕获到的任何回归添加测试用例(例如,如果找到了回归,则应在可能的最低级别上添加回归测试). + +| 测试路径 | 测试引擎 | Notes | +| --- | --- | --- | +| `spec/features/` | [Capybara](https://github.com/teamcapybara/capybara) + [RSpec](https://github.com/rspec/rspec-rails#feature-specs) | If your test has the `:js` metadata, the browser driver will be [Poltergeist](https://github.com/teamcapybara/capybara#poltergeist), otherwise it’s using [RackTest](https://github.com/teamcapybara/capybara#racktest). | + +### Frontend feature tests[](#frontend-feature-tests "Permalink") + +与[前端集成测试](#frontend-integration-tests)相反,功能测试针对真正的后端而不是使用固定装置发出请求. 这也意味着将执行数据库查询,这将大大降低该类别的速度. + +也可以看看: + +* The [RSpec testing guidelines](../testing_guide/best_practices.html#rspec). +* [测试最佳实践](best_practices.html#system--feature-tests)中的系统/功能测试. +* [第 26159 期](https://gitlab.com/gitlab-org/gitlab/-/issues/26159) ,旨在将这些准则与本页面结合在一起. + +图 RL plain [普通 JavaScript]; Vue [Vue 组件]; feature-flags [功能标志]; 许可证检查[许可证检查]; 普通--Vuex; 普通--GraphQL; Vue--简单 Vue --- Vuex; Vue--GraphQL; 浏览器-普通 浏览器--- Vue; 普通-后端; Vuex-后端; GraphQL--后端; Vue-后端; 后端-数据库 后端-功能标记; 后端-许可证检查; 经过类后端测试; 普通测试 经过 Vue 测试; 经过 Vuex 类测试; 经过 GraphQL 类测试; 经过类浏览器测试; linkStyle 0、1、2、3、4、5、6、7、8、9、10 笔画:#6666ff,笔划宽度:2px,笔划数组:5、5; classDef 节点颜色:#909090,填充:#f0f0f0,笔划宽度:2px,笔划:#909090 classDef 标签 stroke-width:0; classDef 测试的颜色:#000000,填充:#a0c0ff,笔划:#6666ff,笔划宽度:2px,笔划数组:5、5; 经过测试的子图; 嘲笑 等级测试 结束 + +#### When to use feature tests[](#when-to-use-feature-tests "Permalink") + +* 需要后端并且无法使用固定装置进行测试的用例. +* 行为不是页面捆绑的一部分,而是全局定义的. + +#### Relevant notes[](#relevant-notes "Permalink") + +`:js`标志已添加到测试中,以确保已加载完整环境: + +``` +scenario 'successfully', :js do + sign_in(create(:admin)) +end +``` + +每个测试的步骤都是使用( [水豚法](https://www.rubydoc.info/gems/capybara) )编写的. + +XHR(XMLHttpRequest)调用可能要求您在步骤之间使用`wait_for_requests` ,例如: + +``` +find('.form-control').native.send_keys(:enter) + +wait_for_requests + +expect(page).not_to have_selector('.card') +``` + +### Consider **not** writing a system test[](#consider-not-writing-a-system-test "Permalink") + +如果我们有信心低级组件可以正常工作(如果我们有足够的单元和集成测试,那就应该如此),我们就不需要在系统测试级别重复它们的全面测试. + +添加测试非常容易,但是删除或改进测试却要困难得多,因此应该注意不要引入太多(缓慢和重复的)测试. + +我们遵循这些最佳做法的原因如下: + +* 系统测试运行缓慢,因为它们会在无头浏览器中启动整个应用程序堆栈,而在集成 JS 驱动程序时甚至会更慢 +* 当系统测试使用 JavaScript 驱动程序运行时,测试将在与应用程序不同的线程中运行. 这意味着它不共享数据库连接,并且您的测试将必须提交事务才能使正在运行的应用程序看到数据(反之亦然). 在那种情况下,我们需要在每个规范之后截断数据库,而不是简单地回滚事务(用于其他类型测试的更快策略). 但是,这比事务处理要慢,因此我们只想在必要时使用截断. + +## Black-box tests at the system level, aka end-to-end tests[](#black-box-tests-at-the-system-level-aka-end-to-end-tests "Permalink") + +正式定义: + +* [https://en.wikipedia.org/wiki/System_testing](https://en.wikipedia.org/wiki/System_testing) +* [https://en.wikipedia.org/wiki/Black-box_testing](https://en.wikipedia.org/wiki/Black-box_testing) + +GitLab 由[多个组件](../architecture.html#components)组成,例如[GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell) , [GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) , [Gitaly](https://gitlab.com/gitlab-org/gitaly) , [GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages) , [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner)和 GitLab Rails. 所有这些部件均由[Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab)进行配置和包装. + +QA 框架和实例级场景是[GitLab Rails 的一部分,](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa)因此它们始终与代码库(尤其是视图)保持同步. + +注意: + +* 不需要了解应用程序内部 +* 测试所需的数据只能使用 GUI 或 API 创建 +* 只能针对浏览器页面和 API 响应做出期望 + +每个新功能都应附带[测试计划](https://gitlab.com/gitlab-org/gitlab/tree/master/.gitlab/issue_templates/Test plan.md) . + +| 测试路径 | 测试引擎 | Notes | +| --- | --- | --- | +| `qa/qa/specs/features/` | [Capybara](https://github.com/teamcapybara/capybara) + [RSpec](https://github.com/rspec/rspec-rails#feature-specs) +自定义质量检查框架 | 测试应放在相应的[产品类别下](https://about.gitlab.com/handbook/product/product-categories/) | + +> 有关更多信息,请参见[端对端测试](end_to_end/index.html) . + +请注意, `qa/spec`包含 QA 框架本身的[单元测试](#unit-tests) ,请勿与应用程序的[单元测试](#unit-tests)或[端到端](#black-box-tests-at-the-system-level-aka-end-to-end-tests) [测试](#unit-tests)相混淆. + +### Smoke tests[](#smoke-tests "Permalink") + +冒烟测试是可以随时运行的快速测试(尤其是在部署前迁移之后). + +这些测试针对 UI 运行,并确保基本功能正常运行. + +> 有关更多信息,请参见[烟雾测试](smoke.html) . + +### GitLab QA orchestrator[](#gitlab-qa-orchestrator "Permalink") + +[GitLab QA 协调器](https://gitlab.com/gitlab-org/gitlab-qa)是一种工具,可以通过为给定版本的 GitLab Rails 构建 Docker 映像并对其进行端到端测试(即使用 Capybara)来测试所有这些部分是否集成良好. + +在[GitLab 质量检查协调器自述文件中](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md)了解更多信息. + +## EE-specific tests[](#ee-specific-tests "Permalink") + +特定于 EE 的测试遵循相同的组织,但位于`ee/spec`文件夹下. + +## How to test at the correct level?[](#how-to-test-at-the-correct-level "Permalink") + +与生活中的许多事情一样,决定在每个测试级别上测试什么是一个权衡: + +* 单元测试通常很便宜,您应该将它们视为房子的地下室:您需要它们来确保您的代码行为正确. 但是,如果仅运行单元测试而不进行集成/系统测试,则可能会[错过](https://twitter.com/ThePracticalDev/status/850748070698651649) [大局](https://twitter.com/timbray/status/822470746773409794) / [大局](https://twitter.com/withzombies/status/829716565834752000) ! +* 集成测试要贵一些,但是请不要滥用它们. 系统测试通常比集成测试要好得多. +* 系统测试非常昂贵(与单元测试相比),如果它们需要 JavaScript 驱动程序,则价格甚至更高. 确保遵循" [速度"](best_practices.html#test-speed)部分中的准则. + +另一种看待它的方式是考虑"测试成本",本文对此进行了很好的解释[,](https://medium.com/table-xi/high-cost-tests-and-high-value-tests-a86e27a54df#.2ulyh3a4e)基本思想是测试成本包括: + +* 编写测试所需的时间 +* 套件每次运行都需要运行测试的时间 +* 了解测试所需的时间 +* 如果测试失败并且基础代码正常,则修复测试所花费的时间 +* 也许,更改代码以使其可测试所需的时间. + +### Frontend-related tests[](#frontend-related-tests "Permalink") + +在某些情况下,要测试的行为不值得花时间运行整个应用程序,例如,如果要测试样式,动画,边缘情况或不涉及后端的小动作,则应编写集成测试使用茉莉花. + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/_book/docs/634.md b/_book/docs/634.md new file mode 100644 index 0000000000000000000000000000000000000000..3b4263899d26f9838e102beddfd6e67db9e5b6cb --- /dev/null +++ b/_book/docs/634.md @@ -0,0 +1,198 @@ +# Testing Rails migrations at GitLab + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/testing_migrations_guide.html](https://docs.gitlab.com/ee/development/testing_guide/testing_migrations_guide.html) + +* [When to write a migration test](#when-to-write-a-migration-test) +* [How does it work?](#how-does-it-work) +* [Testing an `ActiveRecord::Migration` class](#testing-an-activerecordmigration-class) + * [Test helpers](#test-helpers) + * [`table`](#table) + * [`migrate!`](#migrate) + * [`reversible_migration`](#reversible_migration) + * [Example database migration test](#example-database-migration-test) +* [Testing a non-`ActiveRecord::Migration` class](#testing-a-non-activerecordmigration-class) + * [Example background migration test](#example-background-migration-test) + +# Testing Rails migrations at GitLab[](#testing-rails-migrations-at-gitlab "Permalink") + +为了可靠地检查 Rails 迁移,我们需要针对数据库架构对其进行测试. + +## When to write a migration test[](#when-to-write-a-migration-test "Permalink") + +* 后期迁移( `/db/post_migrate` )和后台迁移( `lib/gitlab/background_migration` ) **必须**执行迁移测试. +* 如果您的迁移是数据迁移,那么它**必须**具有迁移测试. +* 如有必要,其他迁移可能会进行迁移测试. + +## How does it work?[](#how-does-it-work "Permalink") + +在测试签名中添加`:migration`标记,可以在[`spec/support/migration.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/f81fa6ab1dd788b70ef44b85aaba1f31ffafae7d/spec/support/migration.rb)挂钩`before`和`after`运行一些自定义 RSpec. + +`before`钩子会将所有迁移还原到尚未迁移被测试的迁移点. + +换句话说,我们的自定义 RSpec 挂钩将找到以前的迁移,并将数据库**向下**迁移到以前的迁移版本. + +使用这种方法,您可以针对数据库架构测试迁移. + +一个`after`钩子将数据库迁移**并** reinstitute 最新的架构版本,因此该方法不会影响后续的规格,并确保适当的隔离. + +## Testing an `ActiveRecord::Migration` class[](#testing-an-activerecordmigration-class "Permalink") + +要测试`ActiveRecord::Migration`类(即常规迁移`db/migrate`或迁移后`db/post_migrate` ),您将需要手动`require`迁移文件,因为它不会随 Rails 自动加载. 例: + +``` +require Rails.root.join('db', 'post_migrate', '20170526185842_migrate_pipeline_stages.rb') +``` + +### Test helpers[](#test-helpers "Permalink") + +#### `table`[](#table "Permalink") + +使用`table`助手为`table`创建一个临时的`ActiveRecord::Base`派生模型. [FactoryBot](best_practices.html#factories) **不**应用于为迁移规范创建数据. 例如,要在`projects`表中创建一条记录: + +``` +project = table(:projects).create!(id: 1, name: 'gitlab1', path: 'gitlab1') +``` + +#### `migrate!`[](#migrate "Permalink") + +使用`migrate!` 帮助程序来运行正在测试的迁移. 它不仅将运行迁移,还将在`schema_migrations`表中增加模式版本. 这是必要的,因为在`after`钩中,我们会触发其余的迁移,并且我们需要知道从哪里开始. 例: + +``` +it 'migrates successfully' do + # ... pre-migration expectations + + migrate! + + # ... post-migration expectations +end +``` + +#### `reversible_migration`[](#reversible_migration "Permalink") + +Use the `reversible_migration` helper to test migrations with either a `change` or both `up` and `down` hooks. This will test that the state of the application and its data after the migration becomes reversed is the same as it was before the migration ran in the first place. The helper: + +1. 在**向上**迁移之前运行`before`期望. +2. Migrates **up**. +3. 运行`after`期望. +4. Migrates **down**. +5. `before`运行`before`期望. + +Example: + +``` +reversible_migration do |migration| + migration.before -> { + # ... pre-migration expectations + } + + migration.after -> { + # ... post-migration expectations + } +end +``` + +### Example database migration test[](#example-database-migration-test "Permalink") + +该规范测试了[`db/post_migrate/20170526185842_migrate_pipeline_stages.rb`](https://gitlab.com/gitlab-org/gitlab-foss/blob/v11.6.5/db/post_migrate/20170526185842_migrate_pipeline_stages.rb)迁移. 您可以在[`spec/migrations/migrate_pipeline_stages_spec.rb`](https://gitlab.com/gitlab-org/gitlab-foss/blob/v11.6.5/spec/migrations/migrate_pipeline_stages_spec.rb)找到完整的规范. + +``` +require 'spec_helper' +require Rails.root.join('db', 'post_migrate', '20170526185842_migrate_pipeline_stages.rb') + +RSpec.describe MigratePipelineStages do + # Create test data - pipeline and CI/CD jobs. + let(:jobs) { table(:ci_builds) } + let(:stages) { table(:ci_stages) } + let(:pipelines) { table(:ci_pipelines) } + let(:projects) { table(:projects) } + + before do + projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1') + pipelines.create!(id: 1, project_id: 123, ref: 'master', sha: 'adf43c3a') + jobs.create!(id: 1, commit_id: 1, project_id: 123, stage_idx: 2, stage: 'build') + jobs.create!(id: 2, commit_id: 1, project_id: 123, stage_idx: 1, stage: 'test') + end + + # Test just the up migration. + it 'correctly migrates pipeline stages' do + expect(stages.count).to be_zero + + migrate! + + expect(stages.count).to eq 2 + expect(stages.all.pluck(:name)).to match_array %w[test build] + end + + # Test a reversible migration. + it 'correctly migrates up and down pipeline stages' do + reversible_migration do |migration| + # Expectations will run before the up migration, + # and then again after the down migration + migration.before -> { + expect(stages.count).to be_zero + } + + # Expectations will run after the up migration. + migration.after -> { + expect(stages.count).to eq 2 + expect(stages.all.pluck(:name)).to match_array %w[test build] + } + end +end +``` + +## Testing a non-`ActiveRecord::Migration` class[](#testing-a-non-activerecordmigration-class "Permalink") + +要测试非`ActiveRecord::Migration`测试(后台迁移),您将需要手动提供所需的架构版本. 请向要在其中切换数据库架构的上下文中添加`schema`标签. + +如果未设置,则`schema`默认为`:latest` . + +Example: + +``` +describe SomeClass, schema: 20170608152748 do + # ... +end +``` + +### Example background migration test[](#example-background-migration-test "Permalink") + +该规范测试了[`lib/gitlab/background_migration/archive_legacy_traces.rb`](https://gitlab.com/gitlab-org/gitlab-foss/blob/v11.6.5/lib/gitlab/background_migration/archive_legacy_traces.rb)背景迁移. 您可以在[`spec/lib/gitlab/background_migration/archive_legacy_traces_spec.rb`](https://gitlab.com/gitlab-org/gitlab-foss/blob/v11.6.5/spec/lib/gitlab/background_migration/archive_legacy_traces_spec.rb)找到完整的规范 + +``` +require 'spec_helper' + +describe Gitlab::BackgroundMigration::ArchiveLegacyTraces, schema: 20180529152628 do + include TraceHelpers + + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:builds) { table(:ci_builds) } + let(:job_artifacts) { table(:ci_job_artifacts) } + + before do + namespaces.create!(id: 123, name: 'gitlab1', path: 'gitlab1') + projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1', namespace_id: 123) + @build = builds.create!(id: 1, project_id: 123, status: 'success', type: 'Ci::Build') + end + + context 'when trace file exists at the right place' do + before do + create_legacy_trace(@build, 'trace in file') + end + + it 'correctly archive legacy traces' do + expect(job_artifacts.count).to eq(0) + expect(File.exist?(legacy_trace_path(@build))).to be_truthy + + described_class.new.perform(1, 1) + + expect(job_artifacts.count).to eq(1) + expect(File.exist?(legacy_trace_path(@build))).to be_falsy + expect(File.read(archived_trace_path(job_artifacts.first))).to eq('trace in file') + end + end +end +``` + +**注意:**由于我们使用删除数据库清除策略,因此这些测试不在数据库事务中运行. 不要依赖存在的事务. \ No newline at end of file diff --git a/_book/docs/635.md b/_book/docs/635.md new file mode 100644 index 0000000000000000000000000000000000000000..c3d5210c1902c8d19f32e5694539acdd34268203 --- /dev/null +++ b/_book/docs/635.md @@ -0,0 +1,37 @@ +# Testing Rake tasks + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/testing_rake_tasks.html](https://docs.gitlab.com/ee/development/testing_guide/testing_rake_tasks.html) + +# Testing Rake tasks[](#testing-rake-tasks "Permalink") + +为了使测试 Rake 任务更容易一些,可以使用一个辅助程序来代替标准 Spec 辅助程序. 代替`require 'spec_helper'` ,使用`require 'rake_helper'` . 该帮助程序包括为您提供的`spec_helper` ,并配置了一些其他内容以使测试 Rake 任务更加容易. + +至少需要 Rake 帮助程序重定向`stdout` ,包括运行时任务帮助程序,并包括`RakeHelpers` Spec 支持模块. + +`RakeHelpers`模块公开了`run_rake_task(<task>)`方法以简化执行任务. 有关所有可用方法,请参见`spec/support/helpers/rake_helpers.rb` . + +Example: + +``` +require 'rake_helper' + +describe 'gitlab:shell rake tasks' do + before do + Rake.application.rake_require 'tasks/gitlab/shell' + + stub_warn_user_is_not_gitlab + end + + describe 'install task' do + it 'invokes create_hooks task' do + expect(Rake::Task['gitlab:shell:create_hooks']).to receive(:invoke) + + run_rake_task('gitlab:shell:install') + end + end +end +``` + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/_book/docs/636.md b/_book/docs/636.md new file mode 100644 index 0000000000000000000000000000000000000000..69261b63437eb7ae1adbf6273f83d80bce03aea4 --- /dev/null +++ b/_book/docs/636.md @@ -0,0 +1,133 @@ +# End-to-end Testing + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/) + +* [What is end-to-end testing?](#what-is-end-to-end-testing) +* [How do we test GitLab?](#how-do-we-test-gitlab) + * [Testing nightly builds](#testing-nightly-builds) + * [Testing staging](#testing-staging) + * [Testing code in merge requests](#testing-code-in-merge-requests) + * [Using the `package-and-qa` job](#using-the-package-and-qa-job) + * [How does it work?](#how-does-it-work) + * [With Pipeline for Merged Results](#with-pipeline-for-merged-results) + * [Running custom tests](#running-custom-tests) + * [Using the `review-qa-all` jobs](#using-the-review-qa-all-jobs) +* [How do I run the tests?](#how-do-i-run-the-tests) + * [Running tests that require special setup](#running-tests-that-require-special-setup) +* [How do I write tests?](#how-do-i-write-tests) +* [Where can I ask for help?](#where-can-i-ask-for-help) + +# End-to-end Testing[](#end-to-end-testing "Permalink") + +## What is end-to-end testing?[](#what-is-end-to-end-testing "Permalink") + +端到端测试是一种策略,用于检查您的应用程序在整个软件堆栈和体系结构中是否按预期工作,包括应该协同工作的所有微服务和组件的集成. + +## How do we test GitLab?[](#how-do-we-test-gitlab "Permalink") + +我们使用[Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab)构建 GitLab 程序包,然后使用[GitLab QA 协调器](https://gitlab.com/gitlab-org/gitlab-qa)工具测试这些程序包,该工具是 API 和 UI 的黑盒测试框架. + +### Testing nightly builds[](#testing-nightly-builds "Permalink") + +我们每天晚上运行预定的管道,以测试 Omnibus 创建的每晚构建. 您可以在`https://gitlab.com/gitlab-org/quality/nightly/pipelines` (需要开发人员访问权限)中找到这些夜间管道. 结果在`#qa-nightly` Slack 频道中报告. + +### Testing staging[](#testing-staging "Permalink") + +我们每天晚上运行预定的管道以测试阶段. 您可以在`https://gitlab.com/gitlab-org/quality/staging/pipelines` (需要开发人员访问权限)中找到这些夜间管道. 结果在`#qa-staging` Slack 频道中报告. + +### Testing code in merge requests[](#testing-code-in-merge-requests "Permalink") + +#### Using the `package-and-qa` job[](#using-the-package-and-qa-job "Permalink") + +通过在`test`阶段触发`package-and-qa`手动操作,可以对合并请求运行端到端测试,最终在[`gitlab-qa-mirror`](https://gitlab.com/gitlab-org/gitlab-qa-mirror/)项目的管道中运行(不适用于 fork) ). + +**这将针对根据合并请求的更改构建的自定义 CE 和 EE(具有终极许可证)Omnibus 程序包进行端到端测试.** + +[Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab)中的合并请求中也提供了启动端到端测试的手动操作. + +您可以在下面阅读有关如何使用它以及如何工作的更多信息. + +#### How does it work?[](#how-does-it-work "Permalink") + +当前,我们正在使用类似*多项目管道*的方法来运行质量检查管道. + +图 LR A1 -.-> | 1\. 触发 omnibus-gitlab-mirror 管道并等待它完成| A2 B2 [`Trigger-qa`阶段 +`Trigger:qa-test`工作] -.-> | 2\. 触发 gitlab-qa-mirror 管道并等待它完成| A3 子图" gitlab-foss / gitlab 管道" A1 [`test`阶段 +"打包和质量检查"工作]结束子图" omnibus-gitlab 管道" A2 [`Trigger-docker`阶段 +`Trigger:gitlab-docker`作业]-> |一旦完成| B2 结束子图" gitlab-qa-镜像管道" A3> QA 作业运行] -.-> | 3\. 将管道结果报告给"打包和质量检查"作业 +并将结果发布到经过测试的原始提交| A1 端 + +1. 开发人员触发手动操作,可以在 GitLab 合并请求中找到该操作. 这将启动多个项目中的一系列管道. + +2. 正在执行的脚本触发[Omnibus GitLab Mirror 中](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror)的管道,并等待结果状态. 我们将此称为*状态归因* . + +3. 在[Omnibus GitLab Mirror](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror)管道中正在构建 GitLab 软件包. 然后将程序包推送到其容器注册表. + +4. 当软件包准备就绪并在注册表中可用时, [Omnibus GitLab Mirror](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror)管道的最后一步将触发新的 GitLab QA 管道(具有访问权限的人可以在`https://gitlab.com/gitlab-org/gitlab-qa-mirror/pipelines`查看它们) `https://gitlab.com/gitlab-org/gitlab-qa-mirror/pipelines` ). 它还等待结果状态. + +5. GitLab QA 从注册表中提取图像,旋转容器,并针对刚刚由`gitlab-qa`工具精心策划的测试环境运行测试. + +6. GitLab QA 管道的结果正在通过 Omnibus 上游传播回 GitLab 合并请求. + +请注意,我们计划[添加](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/156)有关`gitlab-qa-mirror`中运行的每个作业/场景中包含的测试的[更多特定信息](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/156) . + +#### With Pipeline for Merged Results[](#with-pipeline-for-merged-results "Permalink") + +在"合并结果的管道"中,管道在包含源分支和目标分支的合并结果的新引用上运行. 但是,此参考不适用于`gitlab-qa-mirror`管道. + +因此,在"合并结果"管道上的端到端测试将使用合并请求源分支的头部. + +graph LR A["a1b1c1 - branch HEAD (CI_MERGE_REQUEST_SOURCE_BRANCH_SHA)"] B["x1y1z1 - master HEAD"] C["d1e1f1 - merged results (CI_COMMIT_SHA)"] A --> C B --> C A --> E["E2E tests"] C --> D["Pipeline for merged results"] + +##### Running custom tests[](#running-custom-tests "Permalink") + +在下游`gitlab-qa-mirror`管道中运行的[现有场景](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md)包括许多测试,但是有时您可能想要运行一个测试或一组与任何现有场景中的组不同的测试. + +例如,当我们[对](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#dequarantining-tests)一个薄片状测试进行[隔离](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#dequarantining-tests)时,我们首先要确保它不再是薄片状的. 我们可以使用`ce:custom-parallel`和`ee:custom-parallel`作业来做到这一点. 两者都是手动作业,您可以使用自定义变量进行配置. 单击并行作业之一的名称(而不是播放图标)时,系统将提示您输入变量. 您可以使用[`gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables)可以使用的任何[变量](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables)以及这些[变量](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables) : + +| Variable | Description | +| --- | --- | +| `QA_SCENARIO` | 要运行的方案(默认`Test::Instance::Image` ) | +| `QA_TESTS` | 要运行的测试(没有默认设置,这意味着运行方案中的所有测试). 通过 RSpec 运行测试时,请使用文件路径,例如, `qa/specs/features/ee/browser_ui`将包括所有`EE` UI 测试. | +| `QA_RSPEC_TAGS` | 要添加的 RSpec 标记(无默认值) | + +现在, [具有自定义变量的手动作业在重试时将不会使用相同的变量](https://gitlab.com/gitlab-org/gitlab/-/issues/31367) ,因此,如果要多次运行相同的测试,请在每个`custom-parallel`作业中指定相同的变量(最多可使用 10 个变量)您要运行的作业). + +#### Using the `review-qa-all` jobs[](#using-the-review-qa-all-jobs "Permalink") + +在`test`阶段的每个管道上,都会自动启动`review-qa-smoke`作业:它将针对[Review App](../review_apps.html)运行 QA 烟雾套件. + +您还可以手动启动`review-qa-all` :它针对[Review App](../review_apps.html)运行完整的质量检查套件. + +**This runs end-to-end tests against a Review App based on [the official GitLab Helm chart](https://gitlab.com/gitlab-org/charts/gitlab/), itself deployed with custom [Cloud Native components](https://gitlab.com/gitlab-org/build/CNG) built from your merge request’s changes.** + +有关[审阅应用程序](../review_apps.html)的更多详细信息,请参见[审阅应用](../review_apps.html)程序. + +## How do I run the tests?[](#how-do-i-run-the-tests "Permalink") + +如果您不是[在合并请求中测试代码](#testing-code-in-merge-requests) ,则有两个主要选项可用于运行测试. 如果您只想对一个实时的 GitLab 实例或一个预先构建的 Docker 映像运行现有测试,则可以使用[GitLab QA 协调器](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md) . 另请参见[可以通过 Orchestrator 运行的测试方案示例](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#examples) . + +另一方面,如果您想在本地开发的 GitLab 环境中运行,则可以使用[GitLab 开发工具包(GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/) . 请参考[质量检查自述文件](https://gitlab.com/gitlab-org/gitlab/tree/master/qa/README.md#how-can-i-use-it)和以下部分中的说明. + +### Running tests that require special setup[](#running-tests-that-require-special-setup "Permalink") + +了解如何执行[需要特殊设置或考虑才能在本地环境上运行的测试](running_tests_that_require_special_setup.html) . + +## How do I write tests?[](#how-do-i-write-tests "Permalink") + +为了编写新的测试,您首先需要了解有关 GitLab QA 体系结构的更多信息. 请参阅有关[文档](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/architecture.md) . + +一旦决定了将[测试环境业务流程场景](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/lib/gitlab/qa/scenario)和[实例级场景](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features)放置在何处,请查看[GitLab QA 自述文件](https://gitlab.com/gitlab-org/gitlab/tree/master/qa/README.md) , [GitLab QA Orchestrator 自述文件](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md)和[已经存在的实例级场景](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features) . + +继续阅读: + +* [Beginner’s Guide](beginners_guide.html) +* [Style Guide](style_guide.html) +* [Best Practices](best_practices.html) +* [Testing with feature flags](feature_flags.html) +* [Flows](flows.html) +* [RSpec metadata/tags](rspec_metadata_tests.html) + +## Where can I ask for help?[](#where-can-i-ask-for-help "Permalink") + +您可以在 Slack 上的`#quality`频道(GitLab 内部)上[`gitlab`](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name[]=QA&label_name[]=test) ,或者[在`gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/-/issues?label_name[]=new+scenario) [问题跟踪器](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name[]=QA&label_name[]=test)或[`gitlab-qa`问题跟踪器中](https://gitlab.com/gitlab-org/gitlab-qa/-/issues?label_name[]=new+scenario)找到您要[`gitlab-qa`问题](https://gitlab.com/gitlab-org/gitlab-qa/-/issues?label_name[]=new+scenario) . \ No newline at end of file diff --git a/_book/docs/637.md b/_book/docs/637.md new file mode 100644 index 0000000000000000000000000000000000000000..9c78d707286ab1b598aab67a5b2a80383e040407 --- /dev/null +++ b/_book/docs/637.md @@ -0,0 +1,314 @@ +# Beginner's guide to writing end-to-end tests + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/beginners_guide.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/beginners_guide.html) + +* [Before you write a test](#before-you-write-a-test) +* [Determine if end-to-end tests are needed](#determine-if-end-to-end-tests-are-needed) +* [Identify the DevOps stage](#identify-the-devops-stage) +* [Create a skeleton test](#create-a-skeleton-test) + * [The outer `context` block](#the-outer-context-block) + * [The outer `RSpec.describe` block](#the-outer-rspecdescribe-block) + * [The `describe` block](#the-describe-block) + * [The `it` blocks (examples)](#the-it-blocks-examples) +* [Write the test](#write-the-test) +* [De-duplicate your code](#de-duplicate-your-code) +* [Test setup using resources and page objects](#test-setup-using-resources-and-page-objects) +* [Write the page object](#write-the-page-object) +* [Run the spec](#run-the-spec) + +# Beginner’s guide to writing end-to-end tests[](#beginners-guide-to-writing-end-to-end-tests "Permalink") + +在本教程中,您将学习如何为[GitLab 社区版](https://about.gitlab.com/install/?version=ce)和[GitLab 企业版](https://about.gitlab.com/install/)创建端到端( *e2e* )测试. + +在本教程结束时,您将能够: + +* 确定是否需要端到端测试. +* Understand the directory structure within `qa/`. +* 编写一个基本的端到端测试,以验证登录功能. +* 开发任何缺少的[页面对象](page_objects.html)库. + +## Before you write a test[](#before-you-write-a-test "Permalink") + +在编写测试之前,必须将您的[GitLab 开发套件(GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit)配置为运行规范. 端到端测试: + +* 包含在`qa/`目录中. +* 应该是独立和[幂等的](https://en.wikipedia.org/wiki/Idempotence#Computer_science_meaning) . +* 临时创建[资源](resources.html) (例如项目,问题,用户). +* Test the UI and API interfaces, and use the API to efficiently set up the UI tests. + +**提示:**有关更多信息,请参阅[端到端测试最佳实践](best_practices.html) . + +## Determine if end-to-end tests are needed[](#determine-if-end-to-end-tests-are-needed "Permalink") + +在编写端到端测试之前,请为[GitLab 社区版](https://gitlab-org.gitlab.io/gitlab-foss/coverage-ruby/#_AllFiles)和[GitLab 企业版](https://gitlab-org.gitlab.io/gitlab/coverage-ruby/#_AllFiles)项目检查特定功能的代码覆盖率. 在单元,功能或集成级别上是否存在足够的测试范围? 如果回答*是肯定的* ,那么你*就*需要一个终端到终端的测试. + +有关 GitLab 中每个级别的测试分布的信息,请参见[测试级别](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/testing_guide/testing_levels.md) . + +* 请参阅[如何以正确的级别进行测试?](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/testing_guide/testing_levels.md#how-to-test-at-the-correct-level) " [测试级别"](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/testing_guide/testing_levels.md)文档的"部分". +* 查看功能更改的频率. 如果较低级别的测试中已经包含了稳定的特性,那么这些特性不会经常更改,那么端到端测试可能就不值得考虑. +* 最后,与参与实现功能和较低级别测试的开发人员讨论建议的测试. + +**注意:**检查[GitLab 社区版](https://gitlab-org.gitlab.io/gitlab-foss/coverage-ruby/#_AllFiles)和[GitLab 企业版](https://gitlab-org.gitlab.io/gitlab/coverage-ruby/#_AllFiles)覆盖率项目,以检查是否为此功能编写了以前的测试. 为了分析代码覆盖率,您必须了解哪些应用程序文件实现了特定功能.**注意:**在本教程中,我们将编写一个登录端到端测试,即使它已经被较低级别的测试所覆盖,因为这是大多数端到端流的第一步,并且最容易理解. + +## Identify the DevOps stage[](#identify-the-devops-stage "Permalink") + +GitLab QA 端到端测试是由[DevOps 生命周期](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features/browser_ui)的不同[阶段](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features/browser_ui)组织的. 确定应按[阶段](https://about.gitlab.com/handbook/product/product-categories/#devops-stages)放置测试的位置,确定该测试属于哪个功能,然后将其放置在该阶段下的子目录中. + +[![DevOps lifecycle by stages](img/31396caea61831939862213abb8dd10c.png)](img/gl-devops-lifecycle-by-stage-numbers_V12_10.png) + +**注意:**如果该测试仅是企业版,则将在`features/ee`目录中创建该测试,但遵循相同的 DevOps 生命周期格式. + +## Create a skeleton test[](#create-a-skeleton-test "Permalink") + +在本教程的第一部分中,我们将测试由 Manage 阶段拥有的登录名. 在`qa/specs/features/browser_ui/1_manage/login` ,创建文件`basic_login_spec.rb` . + +### The outer `context` block[](#the-outer-context-block "Permalink") + +参见[`RSpec.describe`外部块](#the-outer-rspecdescribe-block) + +**弃用声明:**遵循 RSpec 4.0 规范在`13.2`中[弃用](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/550)了外部`context` . 请改用`RSpec.describe` . + +### The outer `RSpec.describe` block[](#the-outer-rspecdescribe-block "Permalink") + +规格具有外部`RSpec.describe`指示 DevOps 阶段. + +``` +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + + end +end +``` + +### The `describe` block[](#the-describe-block "Permalink") + +在我们的外部`RSpec.describe`内部,描述要测试的功能. 在这种情况下,请`Login` . + +``` +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + describe 'Login' do + + end + end +end +``` + +### The `it` blocks (examples)[](#the-it-blocks-examples "Permalink") + +每个测试套件包含至少一个`it`阻断(实施例). 一个好方法,开始写终端到终端的测试是编写测试用例描述为`it`块: + +``` +module QA + RSpec.describe 'Manage' do + describe 'Login' do + it 'can login' do + + end + + it 'can logout' do + + end + end + end +end +``` + +## Write the test[](#write-the-test "Permalink") + +一个重要的问题是"我们要测试什么?" 更重要的是,"我们如何测试?" + +首先登录. + +``` +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + describe 'Login' do + it 'can login' do + Flow::Login.sign_in + + end + + it 'can logout' do + Flow::Login.sign_in + + end + end + end +end +``` + +[运行规范后](#run-the-spec) ,我们的测试应登录并结束; 那么我们应该回答"我们要测试什么?"这个问题. + +``` +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + describe 'Login' do + it 'can login' do + Flow::Login.sign_in + + Page::Main::Menu.perform do |menu| + expect(menu).to be_signed_in + end + end + + it 'can logout' do + Flow::Login.sign_in + + Page::Main::Menu.perform do |menu| + menu.sign_out + + expect(menu).not_to be_signed_in + end + end + end + end +end +``` + +**我们要测试什么?** + +1. 我们可以登录吗? +2. 我们可以注销吗? + +**我们如何测试?** + +1. 检查用户头像是否出现在顶部导航中. +2. 检查用户头像*是否未*出现在顶部导航中. + +**注意:**在幕后, `be_signed_in`是一个[谓词匹配器](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/built-in-matchers/predicate-matchers) ,可[实现对用户头像的检查](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/page/main/menu.rb#L74) . + +## De-duplicate your code[](#de-duplicate-your-code "Permalink") + +将测试重构为使用`before`块进行测试设置,因为它复制了对`sign_in`的调用. + +``` +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + describe 'Login' do + before do + Flow::Login.sign_in + end + + it 'can login' do + Page::Main::Menu.perform do |menu| + expect(menu).to be_signed_in + end + end + + it 'can logout' do + Page::Main::Menu.perform do |menu| + menu.sign_out + + expect(menu).not_to be_signed_in + end + end + end + end +end +``` + +`before`块本质上是一个`before(:each)`并且在每个示例之前运行,确保我们现在在每个测试的开始处登录. + +## Test setup using resources and page objects[](#test-setup-using-resources-and-page-objects "Permalink") + +接下来,让我们测试登录以外的其他功能. 让我们测试"计划"阶段拥有的"问题",因此在`qa/specs/features/browser_ui/3_create/issues` [创建一个](#identify-the-devops-stage)名为`issues_spec.rb` . + +``` +# frozen_string_literal: true + +module QA + RSpec.describe 'Plan' do + describe 'Issues' do + let(:issue) do + Resource::Issue.fabricate_via_api! do |issue| + issue.title = 'My issue' + issue.description = 'This is an issue specific to this test' + end + end + + before do + Flow::Login.sign_in + issue.visit! + end + + it 'can close an issue' do + Page::Project::Issue::Show.perform do |show| + show.click_close_issue_button + + expect(show).to be_closed + end + end + end + end +end +``` + +请注意以下要点: + +* 在我们的示例开始时,我们将在`page/issue/show.rb` [页面](page_objects.html) . +* 我们的测试仅在需要时制造需要的东西. +* 该问题是通过 API 伪造的,以节省时间. +* GitLab 更喜欢`let()`不是实例变量. 查看[最佳做法](../best_practices.html#let-variables) . +* `be_closed`尚未在`page/project/issue/show.rb`中实现,但将在下一步中实现. + +该问题被伪装成[Resource](resources.html) ,它是您可以通过 UI 或 API 创建的 GitLab 实体. 其他示例包括: + +* A [Merge Request](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/resource/merge_request.rb). +* A [User](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/resource/user.rb). +* A [Project](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/resource/project.rb). +* A [Group](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/resource/group.rb). + +## Write the page object[](#write-the-page-object "Permalink") + +[Page Object](page_objects.html)是我们套件中的一个类,代表 GitLab 中的一个页面. **登录**页面就是一个例子. 由于我们的" **问题显示"**页面的页面对象已经存在,请添加`closed?` 方法. + +``` +module Page::Project::Issue + class Show + view 'app/views/projects/issues/show.html.haml' do + element :closed_status_box + end + + def closed? + has_element?(:closed_status_box) + end + end +end +``` + +接下来,在视图中定义元素`closed_status_box` ,以便页面对象可以看到它. + +``` +-#=> app/views/projects/issues/show.html.haml .issuable-status-box.status-box.status-box-issue-closed{ ..., data: { qa_selector: 'closed_status_box' } } +``` + +## Run the spec[](#run-the-spec "Permalink") + +在运行规范之前,请确认: + +* GDK 已安装. +* GDK 在本地 3000 端口上运行. +* 尚未应用其他[RSpec 元数据标签](rspec_metadata_tests.html) . +* 您的工作目录是 GDK GitLab 安装中的`qa/` . + +要运行该规范,请运行以下命令: + +``` +bundle exec bin/qa Test::Instance::All http://localhost:3000 -- <test_file> +``` + +Where `<test_file>` is: + +* 运行"登录"示例时,请输入`qa/specs/features/browser_ui/1_manage/login/login_spec.rb` . +* 运行"问题"示例时,请执行`qa/specs/features/browser_ui/2_plan/issues/issue_spec.rb` . \ No newline at end of file diff --git a/_book/docs/638.md b/_book/docs/638.md new file mode 100644 index 0000000000000000000000000000000000000000..aed4287200aa5384830e525a8f6fe3c240077d68 --- /dev/null +++ b/_book/docs/638.md @@ -0,0 +1,144 @@ +# End-to-end testing Best Practices + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html) + +* [Prefer API over UI](#prefer-api-over-ui) +* [Avoid superfluous expectations](#avoid-superfluous-expectations) +* [Prefer to split tests across multiple files](#prefer-to-split-tests-across-multiple-files) +* [Limit the use of the UI in `before(:context)` and `after` hooks](#limit-the-use-of-the-ui-in-beforecontext-and-after-hooks) +* [Ensure tests do not leave the browser logged in](#ensure-tests-do-not-leave-the-browser-logged-in) +* [Tag tests that require Administrator access](#tag-tests-that-require-administrator-access) +* [Prefer `Commit` resource over `ProjectPush`](#prefer-commit-resource-over-projectpush) + +# End-to-end testing Best Practices[](#end-to-end-testing-best-practices "Permalink") + +**注意:**这是[测试指南中](../best_practices.html)最佳实践的量身定制的扩展. + +## Prefer API over UI[](#prefer-api-over-ui "Permalink") + +端到端测试框架能够根据具体情况来构造其资源. 应尽可能通过 API 来构造资源. + +通过 API 构造测试所需的资源,我们可以节省时间和金钱. + +[Learn more](resources.html) about resources. + +## Avoid superfluous expectations[](#avoid-superfluous-expectations "Permalink") + +为了使测试保持精简,重要的是我们仅测试需要测试的内容. + +确保不添加任何与需要测试的内容无关的`expect()`语句. + +例如: + +``` +#=> Good +Flow::Login.sign_in +Page::Main::Menu.perform do |menu| + expect(menu).to be_signed_in +end + +#=> Bad +Flow::Login.sign_in(as: user) +Page::Main::Menu.perform do |menu| + expect(menu).to be_signed_in + expect(page).to have_content(user.name) #=> we already validated being signed in. redundant. + expect(menu).to have_element(:nav_bar) #=> likely unnecessary. already validated in lower-level. test doesn't call for validating this. +end + +#=> Good +issue = Resource::Issue.fabricate_via_api! do |issue| + issue.name = 'issue-name' +end + +Project::Issues::Index.perform do |index| + expect(index).to have_issue(issue) +end + +#=> Bad +issue = Resource::Issue.fabricate_via_api! do |issue| + issue.name = 'issue-name' +end + +Project::Issues::Index.perform do |index| + expect(index).to have_issue(issue) + expect(page).to have_content(issue.name) #=> page content check is redundant as the issue was already validated in the line above. +end +``` + +## Prefer to split tests across multiple files[](#prefer-to-split-tests-across-multiple-files "Permalink") + +我们的框架包括几个并行化机制,这些机制通过并行执行 spec 文件来工作. + +但是,由于测试是通过 spec *文件*而不是通过 test / example 并行化的,因此如果将新测试添加到现有文件中,我们将无法实现更大的并行化. + +尽管如此,可能还有其他原因要向现有文件添加新测试. + +例如,如果测试共享状态的设置成本很高,则即使执行一次使用该设置的测试无法并行化,执行一次设置可能会更有效. + +综上所述: + +* **可以** :将测试拆分到单独的文件中,除非测试共享昂贵的设置. +* **不要** :在不考虑对并行化的影响的情况下,将新测试放在现有文件中. + +## Limit the use of the UI in `before(:context)` and `after` hooks[](#limit-the-use-of-the-ui-in-beforecontext-and-after-hooks "Permalink") + +限制使用`before(:context)`挂钩仅通过 API 调用,非 UI 操作或基本 UI 操作(例如登录`before(:context)`来执行设置任务. + +我们使用[`capybara-screenshot`](https://github.com/mattheworiordan/capybara-screenshot)库自动保存失败时的屏幕截图. + +`capybara-screenshot` [将屏幕](https://github.com/mattheworiordan/capybara-screenshot/blob/master/lib/capybara-screenshot/rspec.rb#L97) `capybara-screenshot` [保存在 RSpec 的`after` hook 中](https://github.com/mattheworiordan/capybara-screenshot/blob/master/lib/capybara-screenshot/rspec.rb#L97) . [如果`before(:context)`失败,则不会调用`after`挂钩](https://github.com/rspec/rspec-core/pull/2652/files#diff-5e04af96d5156e787f28d519a8c99615R148) ,因此不会保存屏幕截图. + +鉴于这一事实,我们应该将`before(:context)`使用仅限于不需要屏幕快照的那些操作. + +同样, `after`钩子仅应用于非 UI 操作. 测试文件中`after` hook 中的任何 UI 操作都将在获取屏幕快照的`after` hook 之前执行. 这将导致 UI 状态从故障点移开,因此无法在正确的时刻捕获屏幕截图. + +## Ensure tests do not leave the browser logged in[](#ensure-tests-do-not-leave-the-browser-logged-in "Permalink") + +所有测试都希望能够在测试开始时登录. + +有关示例,请参见: [https](https://gitlab.com/gitlab-org/gitlab/-/issues/34736) : [//gitlab.com/gitlab-org/gitlab/-/issues/34736](https://gitlab.com/gitlab-org/gitlab/-/issues/34736) + +理想情况下,在`after(:context)` (或[`before(:context)`](#limit-the-use-of-the-ui-in-beforecontext-and-after-hooks) )块中执行的任何动作都可以通过 API 执行. 但是,如果有必要通过 UI 进行操作(例如,如果不存在 API 功能),请确保在该块的末尾注销. + +``` +after(:all) do + login unless Page::Main::Menu.perform(&:signed_in?) + + # Do something while logged in + + Page::Main::Menu.perform(&:sign_out) +end +``` + +## Tag tests that require Administrator access[](#tag-tests-that-require-administrator-access "Permalink") + +我们不会运行需要管理员对生产环境进行访问的测试. + +当您添加需要管理员访问权限的新测试时,请应用 RSpec 元数据`:requires_admin`以使该测试不会包含在针对生产环境和我们不想在其上运行这些测试的其他环境执行的测试套件中. + +注意:在本地运行测试或配置管道时,可以将环境变量`QA_CAN_TEST_ADMIN_FEATURES`设置为`false`以跳过带有`:requires_admin`标记的测试. + +## Prefer `Commit` resource over `ProjectPush`[](#prefer-commit-resource-over-projectpush "Permalink") + +与[使用 API​​一致](#prefer-api-over-ui) ,请尽可能使用`Commit`资源. + +`ProjectPush`通过 Git 命令行界面(CLI)使用原始 Shell 命令,而`Commit`资源则发出 HTTP 请求. + +``` +# Using a commit resource +Resource::Commit.fabricate_via_api! do |commit| + commit.commit_message = 'Initial commit' + commit.add_files([ + {file_path: 'README.md', content: 'Hello, GitLab'} + ]) +end + +# Using a ProjectPush +Resource::Repository::ProjectPush.fabricate! do |push| + push.commit_message = 'Initial commit' + push.file_name = 'README.md' + push.file_content = 'Hello, GitLab' +end +``` + +**注意:**当您的测试要求测试 SSH 集成或使用 Git CLI 时,使用`ProjectPush`会出现一些例外. \ No newline at end of file diff --git a/_book/docs/639.md b/_book/docs/639.md new file mode 100644 index 0000000000000000000000000000000000000000..6f7fe72bb00981e7cf7619eecd83d9cb27df8548 --- /dev/null +++ b/_book/docs/639.md @@ -0,0 +1,122 @@ +# Dynamic Element Validation + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/dynamic_element_validation.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/dynamic_element_validation.html) + +* [How it works](#how-it-works) + * [Navigation](#navigation) + * [Clicks](#clicks) + * [Required Elements](#required-elements) + * [Definition](#definition) + * [Application](#application) +* [Examples](#examples) + * [Navigating](#navigating) + * [Clicking](#clicking) + +# Dynamic Element Validation[](#dynamic-element-validation "Permalink") + +我们设计了一种解决方案来解决常见的测试自动化问题,例如可怕的`NoSuchElementException` . + +动态元素验证解决的其他问题是… + +* 当我们用鼠标执行操作时,我们期望会发生一些事情. +* 当我们的测试导航到页面(或从页面导航)时,我们确保在继续测试之前我们位于期望的页面上. + +## How it works[](#how-it-works "Permalink") + +我们将页面上的用户操作解释为具有某种效果. 这些动作是 + +* [Navigation](#navigation) +* [Clicks](#clicks) + +### Navigation[](#navigation "Permalink") + +导航到页面时,有些元素将始终无条件地出现在页面上. + +使用时进行动态元素验证 + +``` +Runtime::Browser.visit(:gitlab, Some::Page) +``` + +### Clicks[](#clicks "Permalink") + +当我们在测试中执行单击时,我们期望会发生一些事情. 那可能是现在要出现在网页上的组件,或者是完全离开该页面的测试. + +使用时进行动态元素验证 + +``` +click_element :my_element, Some::Page +``` + +### Required Elements[](#required-elements "Permalink") + +#### Definition[](#definition "Permalink") + +First it is important to define what a “required element” is. + +简而言之,必填元素是可见的 HTML 元素,它无需任何用户输入即可出现在 UI 组件上. + +"可见"可以定义为 + +* 没有任何 CSS 阻止其显示. 例如: `display: none`或`width: 0px; height: 0px;` `width: 0px; height: 0px;` +* 能够与用户互动 + +" UI 组件"可以定义为 + +* 用户看到的任何内容 +* 一个按钮,一个文本字段 +* 位于页面上方的图层 + +#### Application[](#application "Permalink") + +要求元素非常容易. 通过将`required: true`作为`element`的参数添加,您现在已经要求该元素在导航时显示在页面上. + +## Examples[](#examples "Permalink") + +鉴于... + +``` +class MyPage < Page::Base + view 'app/views/view.html.haml' do + element :my_element, required: true + element :another_element, required: true + element :conditional_element + end + + def open_layer + click_element :my_element, Layer::MyLayer + end +end + +class Layer < Page::Component + view 'app/views/mylayer/layer.html.haml' do + element :message_content, required: true + end +end +``` + +### Navigating[](#navigating "Permalink") + +给定[来源](#examples) ... + +``` +Runtime::Browser.visit(:gitlab, Page::MyPage) + +execute_stuff +``` + +在继续`execute_stuff`之前,将调用 GitLab 质量检查人员在`MyPage`上扫描`my_element`和`another_element`在页面上 + +### Clicking[](#clicking "Permalink") + +给定[来源](#examples) ... + +``` +def open_layer + click_element :my_element, Layer::MyLayer +end +``` + +将在单击`my_element`时调用 GitLab 质量检查以确保`message_content`出现在 Layer 上. + +这意味着在继续测试之前确实已渲染了 Layer. \ No newline at end of file diff --git a/_book/docs/640.md b/_book/docs/640.md new file mode 100644 index 0000000000000000000000000000000000000000..7576d82ec3e15a644ded328fbd2a66731e670744 --- /dev/null +++ b/_book/docs/640.md @@ -0,0 +1,57 @@ +# Flows in GitLab QA + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/flows.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/flows.html) + +# Flows in GitLab QA[](#flows-in-gitlab-qa "Permalink") + +流是经常使用的动作序列. 它们是比页面对象更高的抽象级别. 流可以包含多个页面对象或任何其他相关代码. + +例如,登录流封装了每个浏览器 UI 测试中包含的两个步骤. + +``` +# QA::Flow::Login + +def sign_in(as: nil) + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.perform { |login| login.sign_in_using_credentials(user: as) } +end + +# When used in a test + +it 'performs a test after signing in as the default user' do + Flow::Login.sign_in + + # Perform the test +end +``` + +`QA::Flow::Login`提供了更有用的流程,使测试可以轻松切换用户. + +``` +# QA::Flow::Login + +def while_signed_in(as: nil) + Page::Main::Menu.perform(&:sign_out_if_signed_in) + + sign_in(as: as) + + yield + + Page::Main::Menu.perform(&:sign_out) +end + +# When used in a test + +it 'performs a test as one user and verifies as another' do + user1 = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) + user2 = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_2, Runtime::Env.gitlab_qa_password_2) + + Flow::Login.while_signed_in(as: user1) do + # Perform some setup as user1 + end + + Flow::Login.sign_in(as: user2) + + # Perform the rest of the test as user2 +end +``` \ No newline at end of file diff --git a/_book/docs/641.md b/_book/docs/641.md new file mode 100644 index 0000000000000000000000000000000000000000..950e22231d225d7f3730bd4fbe81d732104680c2 --- /dev/null +++ b/_book/docs/641.md @@ -0,0 +1,275 @@ +# Page objects in GitLab QA + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/page_objects.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/page_objects.html) + +* [Why do we need that?](#why-do-we-need-that) +* [What problems did we have in the past?](#what-problems-did-we-have-in-the-past) +* [How did we solve fragile tests problem?](#how-did-we-solve-fragile-tests-problem) +* [How to properly implement a page object?](#how-to-properly-implement-a-page-object) + * [Defining Elements](#defining-elements) + * [Adding Elements to a View](#adding-elements-to-a-view) + * [`data-qa-selector` vs `.qa-selector`](#data-qa-selector-vs-qa-selector) + * [Dynamic element selection](#dynamic-element-selection) + * [Examples](#examples) + * [Exceptions](#exceptions) + * [Define Page concerns](#define-page-concerns) +* [Running the test locally](#running-the-test-locally) +* [Where to ask for help?](#where-to-ask-for-help) + +# Page objects in GitLab QA[](#page-objects-in-gitlab-qa "Permalink") + +在 GitLab 质量检查中,我们使用一种称为*Page Objects*的已知模式. + +这意味着我们已经为用于驱动 GitLab 质量检查方案的 GitLab 中的所有页面建立了抽象. 每当我们在页面上执行某项操作(例如填写表单或单击按钮)时,我们仅通过与该 GitLab 区域相关联的页面对象来执行此操作. + +例如,当 GitLab QA 测试工具登录到 GitLab 时,它需要填写用户登录名和用户密码. 为此,我们有一个名为`Page::Main::Login`和`sign_in_using_credentials`方法的类,这是代码中仅有的一部分,它具有有关`user_login`和`user_password`字段的知识. + +## Why do we need that?[](#why-do-we-need-that "Permalink") + +我们需要页面对象,因为只要有人在 GitLab 的源代码中更改某些选择器,我们就需要减少重复并避免出现问题. + +想象一下,我们在 GitLab 质量检查中有 100 个规格,并且在每次声明之前我们都需要登录 GitLab. 如果没有页面对象,则需要依靠易失性助手或直接调用 Capybara 方法. 想象一下在每个`*_spec.rb`文件/测试示例中调用`fill_in :user_login` . + +以后有人在与此页面关联的视图`t.text_field :login`更改为`t.text_field :username` ,它将生成一个不同的字段标识符,这将有效地破坏所有测试. + +因为我们到处都在使用`Page::Main::Login.perform(&:sign_in_using_credentials)` ,所以当我们要登录到 GitLab 时,页面对象是唯一的事实来源,我们需要将`fill_in :user_login`更新为`fill_in :user_username`只能放在一个位置. + +## What problems did we have in the past?[](#what-problems-did-we-have-in-the-past "Permalink") + +由于性能原因以及构建软件包和测试所有内容所花费的时间,我们不会针对每次提交都运行 QA 测试. + +这就是为什么当有人在*新的会话*视图中将`t.text_field :login`更改为`t.text_field :username` ,直到我们的 GitLab QA 夜间管道失败或有人触发了他们的`package-and-qa`操作,我们才知道这一更改.合并请求. + +显然,这样的更改将破坏所有测试. 我们称这个问题为*脆弱的测试问题* . + +为了使 GitLab QA 更加可靠和健壮,我们必须通过在 GitLab CE / EE 视图与 GitLab QA 之间引入耦合来解决此问题. + +## How did we solve fragile tests problem?[](#how-did-we-solve-fragile-tests-problem "Permalink") + +当前,当您添加新的`Page::Base`派生类时,还需要定义页面对象所依赖的所有选择器. + +Whenever you push your code to CE / EE repository, `qa:selectors` sanity test job is going to be run as a part of a CI pipeline. + +此测试将验证我们在`qa/page`目录中实现的所有页面对象. 失败时,将通知您有关丢失的或无效的视图/选择器定义的信息. + +## How to properly implement a page object?[](#how-to-properly-implement-a-page-object "Permalink") + +我们建立了一个 DSL 来定义页面对象和它实际实现的 GitLab 视图之间的耦合. 请参阅下面的示例. + +``` +module Page + module Main + class Login < Page::Base + view 'app/views/devise/passwords/edit.html.haml' do + element :password_field + element :password_confirmation + element :change_password_button + end + + view 'app/views/devise/sessions/_new_base.html.haml' do + element :login_field + element :password_field + element :sign_in_button + end + + # ... + end + end +end +``` + +### Defining Elements[](#defining-elements "Permalink") + +`view` DSL 方法将对应于渲染元素的 rails View,partial 或 Vue 组件. + +`element` DSL 方法依次声明一个元素,需要将其相应的`data-qa-selector=element_name_snaked`数据属性添加到视图文件中. + +您还可以定义一个值(字符串或正则表达式)以匹配实际的视图代码,但是出于两个原因, **不**建议使用上述方法,建议使用该值: + +* 一致性:只有一种定义元素的方法 +* 关注点分离:QA 使用专用的`data-qa-*`属性,而不是重用其他组件使用的代码或类(例如`js-*`类等) + +``` +view 'app/views/my/view.html.haml' do + + ### Good ### + + # Implicitly require the CSS selector `[data-qa-selector="logout_button"]` to be present in the view + element :logout_button + + ### Bad ### + + ## This is deprecated and forbidden by the `QA/ElementWithPattern` RuboCop cop. + # Require `f.submit "Sign in"` to be present in `my/view.html.haml + element :my_button, 'f.submit "Sign in"' # rubocop:disable QA/ElementWithPattern + + ## This is deprecated and forbidden by the `QA/ElementWithPattern` RuboCop cop. + # Match every line in `my/view.html.haml` against + # `/link_to .* "My Profile"/` regexp. + element :profile_link, /link_to .* "My Profile"/ # rubocop:disable QA/ElementWithPattern +end +``` + +### Adding Elements to a View[](#adding-elements-to-a-view "Permalink") + +鉴于以下要素... + +``` +view 'app/views/my/view.html.haml' do + element :login_field + element :password_field + element :sign_in_button +end +``` + +要将这些元素添加到视图,必须通过为定义的每个元素添加`data-qa-selector`属性来更改 rails View,Partial 或 Vue 组件. + +在我们的示例中, `data-qa-selector="login_field"` , `data-qa-selector="password_field"`和`data-qa-selector="sign_in_button"` + +**app/views/my/view.html.haml** + +``` += f.text_field :login, class: "form-control top", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off", required: true, title: "This field is required.", data: { qa_selector: 'login_field' } += f.password_field :password, class: "form-control bottom", required: true, title: "This field is required.", data: { qa_selector: 'password_field' } += f.submit "Sign in", class: "btn btn-success", data: { qa_selector: 'sign_in_button' } +``` + +注意事项: + +* 元素的名称和`qa_selector`必须匹配并使用 snake_cased +* 如果该元素无条件显示在页面上,请向该元素添加`required: true` . 请参阅[动态元素验证](dynamic_element_validation.html) +* 您可能会在现有的页面对象中看到`.qa-selector`类. 我们应该使用[`data-qa-selector`](#data-qa-selector-vs-qa-selector)定义方法,而不是`.qa-selector` CSS 类. + +### `data-qa-selector` vs `.qa-selector`[](#data-qa-selector-vs-qa-selector "Permalink") + +在 GitLab 12.1 中引入 + +在视图中定义元素有两种支持的方法. + +1. `data-qa-selector` attribute +2. `.qa-selector` class + +任何现有的`.qa-selector`类都应视为已弃用,我们应该更喜欢`data-qa-selector`定义方法. + +### Dynamic element selection[](#dynamic-element-selection "Permalink") + +在 GitLab 12.5 中引入 + +自动化测试中常见的一种情况是选择一个"多对多"元素. 在几个项目的列表中,如何区分选择的内容? 最常见的解决方法是通过文本匹配. 相反,更好的做法是通过唯一标识符而不是文本来匹配该特定元素. + +我们通过添加`data-qa-*`可扩展选择机制来解决此问题. + +#### Examples[](#examples "Permalink") + +**例子 1** + +给出以下 Rails 视图(以 GitLab Issues 为例): + +``` +%ul.issues-list + - @issues.each do |issue| + %li.issue{data: { qa_selector: 'issue', qa_issue_title: issue.title } }= link_to issue +``` + +我们可以通过在 Rails 模型上进行匹配来选择特定的问题. + +``` +class Page::Project::Issues::Index < Page::Base + def has_issue?(issue) + has_element? :issue, issue_title: issue + end +end +``` + +在我们的测试中,我们可以验证此特定问题的存在. + +``` +describe 'Issue' do + it 'has an issue titled "hello"' do + Page::Project::Issues::Index.perform do |index| + expect(index).to have_issue('hello') + end + end +end +``` + +**例子 2** + +*通过索引…* + +``` +%ol + - @some_model.each_with_index do |model, idx| + %li.model{ data: { qa_selector: 'model', qa_index: idx } } +``` + +``` +expect(the_page).to have_element(:model, index: 1) #=> select on the first model that appears in the list +``` + +### Exceptions[](#exceptions "Permalink") + +在某些情况下,可能无法或不值得添加选择器. + +一些 UI 组件使用外部库,包括一些第三方维护的库. 即使 GitLab 维护了一个库,选择器的健全性测试也只能在 GitLab 项目中的代码上运行,因此无法为库中的代码指定视图的路径. + +在这种罕见的情况下,在页面对象方法中使用 CSS 选择器是合理的,并带有注释说明为什么不能添加`element`原因. + +### Define Page concerns[](#define-page-concerns "Permalink") + +某些页面具有共同的行为,并且/或者在特定于 EE 的模块之前添加了特定于 EE 的方法. + +These modules must: + +1. 从`QA::Page::PageConcern`模块`extend QA::Page::PageConcern` ,并`extend QA::Page::PageConcern` . +2. 重写`self.prepended`方法,如果他们需要`include` / `prepend`其他模块本身,和/或定义`view`或`elements` . +3. 将`super`称为`self.prepended`的第一件事. +4. 包含/添加其他模块,并在`base.class_eval`块中定义其`view` / `elements` ,以确保在添加模块的类中定义了它们. + +这些步骤确保健全性选择器检查将正确检测到问题. + +例如, `qa/qa/ee/page/merge_request/show.rb`将 EE 特定方法添加到`qa/qa/page/merge_request/show.rb` (带有`QA::Page::MergeRequest::Show.prepend_if_ee('QA::EE::Page::MergeRequest::Show')` ),其实现方式如下(仅显示相关部分,并使用内嵌注释引用上述 4 个步骤): + +``` +module QA + module EE + module Page + module MergeRequest + module Show + extend QA::Page::PageConcern # 1. + + def self.prepended(base) # 2. + super # 3. + + base.class_eval do # 4. + prepend Page::Component::LicenseManagement + + view 'app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue' do + element :head_mismatch, "The source branch HEAD has recently changed." + end + + [...] + end + end + end + end + end + end +end +``` + +## Running the test locally[](#running-the-test-locally "Permalink") + +在开发过程中,您可以运行以下命令来运行`qa:selectors`测试 + +``` +bin/qa Test::Sanity::Selectors +``` + +从`qa`目录中. + +## Where to ask for help?[](#where-to-ask-for-help "Permalink") + +如果您需要更多信息,请在 Slack 上的`#quality`频道(仅限内部,GitLab 团队)上寻求帮助. + +如果你不是一个团队成员,你仍然需要帮助的贡献,请打开 GitLab CE 问题追踪的一个问题`~QA`标签. \ No newline at end of file diff --git a/_book/docs/642.md b/_book/docs/642.md new file mode 100644 index 0000000000000000000000000000000000000000..a492e6c0a4f71ba7da5bf7ead0731d17b0af9cb6 --- /dev/null +++ b/_book/docs/642.md @@ -0,0 +1,362 @@ +# Resource class in GitLab QA + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/resources.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/resources.html) + +* [How to properly implement a resource class?](#how-to-properly-implement-a-resource-class) + * [Define API implementation](#define-api-implementation) + * [Resource attributes](#resource-attributes) + * [Product data attributes](#product-data-attributes) + * [Define an attribute based on an API response](#define-an-attribute-based-on-an-api-response) +* [Creating resources in your tests](#creating-resources-in-your-tests) +* [Where to ask for help?](#where-to-ask-for-help) + +# Resource class in GitLab QA[](#resource-class-in-gitlab-qa "Permalink") + +资源主要是使用浏览器 UI 步骤创建的,但也可以通过 API 或 CLI 创建的. + +## How to properly implement a resource class?[](#how-to-properly-implement-a-resource-class "Permalink") + +所有资源类都应继承自`Resource::Base` . + +只有一种强制性方法可以实现以定义资源类. 这是`#fabricate!` 方法,用于通过浏览器 UI 构建资源. 请注意,在此方法中,您仅应使用[Page 对象](page_objects.html)与网页进行交互. + +这是一个假想的例子: + +``` +module QA + module Resource + class Shirt < Base + attr_accessor :name + + def fabricate! + Page::Dashboard::Index.perform do |dashboard_index| + dashboard_index.go_to_new_shirt + end + + Page::Shirt::New.perform do |shirt_new| + shirt_new.set_name(name) + shirt_new.create_shirt! + end + end + end + end +end +``` + +### Define API implementation[](#define-api-implementation "Permalink") + +资源类还可以实现以下三种方法,以便能够通过公共 GitLab API 创建资源: + +* `#api_get_path` :获取现有资源的`GET`路径. +* `#api_post_path` :用于创建新资源的`POST`路径. +* `#api_post_body` :用于创建新资源的`POST`正文(作为 Ruby 哈希). + +> 请注意,许多 API 资源都是[分页的](../../../api/README.html#pagination) . 如果找不到期望的结果,请检查是否有超过一页的结果. + +让我们使用`Shirt`资源类,并添加以下三个 API 方法: + +``` +module QA + module Resource + class Shirt < Base + attr_accessor :name + + def fabricate! + # ... same as before + end + + def api_get_path + "/shirt/#{name}" + end + + def api_post_path + "/shirts" + end + + def api_post_body + { + name: name + } + end + end + end +end +``` + +`Project`资源是浏览器 UI 和 API 实现的一个很好的真实示例. + +#### Resource attributes[](#resource-attributes "Permalink") + +一个资源可能首先需要另一个资源. 例如,一个项目需要在其中创建一个组. + +要定义资源属性,可以将`attribute`方法与使用其他资源类的块一起使用以构造资源. + +这将允许从资源对象的方法访问其他资源. 您通常会在`#fabricate!`使用它`#fabricate!` , `#api_get_path` , `#api_post_path` , `#api_post_body` . + +让我们使用`Shirt`资源类,并向其添加一个`project`属性: + +``` +module QA + module Resource + class Shirt < Base + attr_accessor :name + + attribute :project do + Project.fabricate! do |resource| + resource.name = 'project-to-create-a-shirt' + end + end + + def fabricate! + project.visit! + + Page::Project::Show.perform do |project_show| + project_show.go_to_new_shirt + end + + Page::Shirt::New.perform do |shirt_new| + shirt_new.set_name(name) + shirt_new.create_shirt! + end + end + + def api_get_path + "/project/#{project.path}/shirt/#{name}" + end + + def api_post_path + "/project/#{project.path}/shirts" + end + + def api_post_body + { + name: name + } + end + end + end +end +``` + +**请注意,所有属性都是延迟构造的. 这意味着,如果您要首先构造特定的属性,则即使不使用它,也需要首先调用 attribute 方法.** + +#### Product data attributes[](#product-data-attributes "Permalink") + +创建后,您可能希望使用可在网页或 API 响应中找到的属性填充资源. 例如,创建项目后,您可能希望将其存储库 SSH URL 存储为属性. + +同样,我们可以将`attribute`方法与块一起使用,使用页面对象来检索页面上的数据. + +让我们以`Shirt`资源类`Shirt` ,并定义一个`:brand`属性: + +``` +module QA + module Resource + class Shirt < Base + attr_accessor :name + + attribute :project do + Project.fabricate! do |resource| + resource.name = 'project-to-create-a-shirt' + end + end + + # Attribute populated from the Browser UI (using the block) + attribute :brand do + Page::Shirt::Show.perform do |shirt_show| + shirt_show.fetch_brand_from_page + end + end + + # ... same as before + end + end +end +``` + +**再次注意,所有属性都是延迟构造的. 这意味着,如果您`shirt.brand`另一页面后再调用`shirt.brand` ,则由于我们不在预期的页面上,因此将无法正确检索数据.** + +考虑一下: + +``` +shirt = + QA::Resource::Shirt.fabricate! do |resource| + resource.name = "GitLab QA" + end + +shirt.project.visit! + +shirt.brand # => FAIL! +``` + +上面的示例将失败,因为现在我们在项目页面上,试图从衬衫页面构造品牌数据,但是我们已经移至项目页面. 有两种解决方法,一种是我们可以在再次访问该项目之前尝试检索该品牌: + +``` +shirt = + QA::Resource::Shirt.fabricate! do |resource| + resource.name = "GitLab QA" + end + +shirt.brand # => OK! + +shirt.project.visit! + +shirt.brand # => OK! +``` + +The attribute will be stored in the instance therefore all the following calls will be fine, using the data previously constructed. If we think that this might be too brittle, we could eagerly construct the data right before ending fabrication: + +``` +module QA + module Resource + class Shirt < Base + # ... same as before + + def fabricate! + project.visit! + + Page::Project::Show.perform do |project_show| + project_show.go_to_new_shirt + end + + Page::Shirt::New.perform do |shirt_new| + shirt_new.set_name(name) + shirt_new.create_shirt! + end + + populate(:brand) # Eagerly construct the data + end + end + end +end +``` + +`populate`方法将遍历其参数并分别调用每个属性. 这里`populate(:brand)`有像刚才一样的效果`brand` . 使用填充方法使意图更清晰. + +这样,将确保我们在创建衬衫后立即构造数据. 缺点是,即使我们不需要使用数据,也总是在构造资源时构造数据. + +另外,我们可以在构建品牌数据之前确保在正确的页面上: + +``` +module QA + module Resource + class Shirt < Base + attr_accessor :name + + attribute :project do + Project.fabricate! do |resource| + resource.name = 'project-to-create-a-shirt' + end + end + + # Attribute populated from the Browser UI (using the block) + attribute :brand do + back_url = current_url + visit! + + Page::Shirt::Show.perform do |shirt_show| + shirt_show.fetch_brand_from_page + end + + visit(back_url) + end + + # ... same as before + end + end +end +``` + +这将确保在构建品牌之前,它在衬衫页面上,并返回到上一页以避免破坏状态. + +#### Define an attribute based on an API response[](#define-an-attribute-based-on-an-api-response "Permalink") + +有时,您想基于来自其`GET`或`POST`请求的 API 响应来定义资源属性. 例如,如果通过 API 创建衬衫的返回 + +``` +{ + brand: 'a-brand-new-brand', + style: 't-shirt', + materials: [[:cotton, 80], [:polyamide, 20]] +} +``` + +您可能希望将`style` `main_fabric`在资源中,并在`main_fabric`属性中获取第一个`materials`项的第一个值. + +让我们以`Shirt`资源类`:main_fabric` ,并定义一个`:style`和`:main_fabric`属性: + +``` +module QA + module Resource + class Shirt < Base + # ... same as before + + # @style from the instance if present, + # or fetched from the API response if present, + # or a QA::Resource::Base::NoValueError is raised otherwise + attribute :style + + # If @main_fabric is not present, + # and if the API does not contain this field, this block will be + # used to construct the value based on the API response, and + # store the result in @main_fabric + attribute :main_fabric do + api_response.&dig(:materials, 0, 0) + end + + # ... same as before + end + end +end +``` + +**有关属性优先级的说明:** + +* 资源实例变量具有最高优先级 +* API 响应中的属性优先于块中的属性(通常是来自浏览器用户界面) +* 没有值的属性将引发`QA::Resource::Base::NoValueError`错误 + +## Creating resources in your tests[](#creating-resources-in-your-tests "Permalink") + +要在测试中创建资源,可以调用`.fabricate!` 资源类上的方法. 请注意,如果资源类支持 API 构造,则默认情况下将使用该构造. + +这是一个示例,由于`Shirt`资源类支持该方法,因此将在后台使用 API​​构造方法: + +``` +my_shirt = Resource::Shirt.fabricate! do |shirt| + shirt.name = 'my-shirt' +end + +expect(page).to have_text(my_shirt.name) # => "my-shirt" from the resource's instance variable +expect(page).to have_text(my_shirt.brand) # => "a-brand-new-brand" from the API response +expect(page).to have_text(my_shirt.style) # => "t-shirt" from the API response +expect(page).to have_text(my_shirt.main_fabric) # => "cotton" from the API response via the block +``` + +如果您明确希望使用浏览器 UI 的制作方法,则可以调用`.fabricate_via_browser_ui!` 方法: + +``` +my_shirt = Resource::Shirt.fabricate_via_browser_ui! do |shirt| + shirt.name = 'my-shirt' +end + +expect(page).to have_text(my_shirt.name) # => "my-shirt" from the resource's instance variable +expect(page).to have_text(my_shirt.brand) # => the brand name fetched from the `Page::Shirt::Show` page via the block +expect(page).to have_text(my_shirt.style) # => QA::Resource::Base::NoValueError will be raised because no API response nor a block is provided +expect(page).to have_text(my_shirt.main_fabric) # => QA::Resource::Base::NoValueError will be raised because no API response and the block didn't provide a value (because it's also based on the API response) +``` + +您还可以通过调用`.fabricate_via_api!`来显式使用 API `.fabricate_via_api!` 方法: + +``` +my_shirt = Resource::Shirt.fabricate_via_api! do |shirt| + shirt.name = 'my-shirt' +end +``` + +在这种情况下,结果将类似于调用`Resource::Shirt.fabricate!` . + +## Where to ask for help?[](#where-to-ask-for-help "Permalink") + +如果您需要更多信息,请在 Slack 上的`#quality`频道(仅限内部,GitLab 团队)上寻求帮助. + +如果你不是一个团队成员,你仍然需要帮助的贡献,请打开 GitLab CE 问题追踪的一个问题`~QA`标签. \ No newline at end of file diff --git a/_book/docs/643.md b/_book/docs/643.md new file mode 100644 index 0000000000000000000000000000000000000000..4efaaa9ce24a19ee3121fa67f037d4e678da236d --- /dev/null +++ b/_book/docs/643.md @@ -0,0 +1,167 @@ +# Style guide for writing end-to-end tests + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/style_guide.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/style_guide.html) + +* [`click_` versus `go_to_`](#click_-versus-go_to_) + * [When to use `click_`?](#when-to-use-click_) + * [When to use `go_to_`?](#when-to-use-go_to_) +* [Element naming convention](#element-naming-convention) + * [Examples](#examples) +* [Block argument naming](#block-argument-naming) + * [Examples](#examples-1) + +# Style guide for writing end-to-end tests[](#style-guide-for-writing-end-to-end-tests "Permalink") + +本文档介绍了在 GitLab 上使用 GitLab QA 项目编写端到端(E2E)测试所使用的约定. + +## `click_` versus `go_to_`[](#click_-versus-go_to_ "Permalink") + +### When to use `click_`?[](#when-to-use-click_ "Permalink") + +单击单个链接进行导航时,请使用`click_` . + +E.g.: + +``` +def click_ci_cd_pipelines + within_sidebar do + click_element :link_pipelines + end +end +``` + +从测试的角度来看,如果我们要检查单击链接或按钮(单个交互)是否按预期工作,我们希望测试的内容为: + +* 点击某个元素 +* 验证操作是否发生 + +### When to use `go_to_`?[](#when-to-use-go_to_ "Permalink") + +与多个元素进行交互以转到页面时,请使用`go_to_` . + +E.g.: + +``` +def go_to_operations_environments + hover_operations do + within_submenu do + click_element(:operations_environments_link) + end + end +end +``` + +`go_to_`适合与多个元素进行交互的定义,因为它更多的是包含多个交互的元导航操作. + +请注意,在上面的示例中,在单击`:operations_environments_link`之前,将鼠标悬停在另一个元素上. + +> 我们可以创建这些方法作为抽象多步导航的助手. + +## Element naming convention[](#element-naming-convention "Permalink") + +在页面上添加新元素时,重要的是要有统一的元素命名约定. + +我们遵循一个基于匈牙利表示法的简单公式. + +*Formula*: `element :<descriptor>_<type>` + +* `descriptor` :元素是什么的自然语言描述. 在登录页面上,可以是`username`或`password` . +* `type` :用户可以在页面上看到的通用控件. + * `_button` + * `_checkbox` + * `_container` :包含其他元素但本身不显示可见内容的元素. 例如,其中具有第三方编辑器的元素,但它本身不是编辑器,因此不包含编辑器的内容. + * `_content` :包含文本,图像或显示给用户的任何其他内容的任何元素. + * `_dropdown` + * `_field` :文本输入元素. + * `_link` + * `_modal` :弹出的模式对话框,例如确认提示. + * `_placeholder` :加载内容时出现的临时元素. 例如,在获取讨论时显示的元素而不是讨论. + * `_radio` + * `_tab` + * `_menu_item` + +*注意:如果列出的类型都不适合,请打开合并请求以将适当的类型添加到列表中.* + +### Examples[](#examples "Permalink") + +**Good** + +``` +view '...' do + element :edit_button + element :notes_tab + element :squash_checkbox + element :username_field + element :issue_title_content +end +``` + +**Bad** + +``` +view '...' do + # `_confirmation` should be `_field`. what sort of confirmation? a checkbox confirmation? no real way to disambiguate. + # an appropriate replacement would be `element :password_confirmation_field` + element :password_confirmation + + # `clone_options` is too vague. If it's a dropdown menu, it should be `clone_dropdown`. + # If it's a checkbox, it should be `clone_checkbox` + element :clone_options + + # how is this url being displayed? is it a textbox? a simple span? + # If it is content on the page, it should be `ssh_clone_url_content` + element :ssh_clone_url +end +``` + +## Block argument naming[](#block-argument-naming "Permalink") + +为了对使用`.perform`方法时调用的页面和资源有一个标准,我们在`.perform`使用页面对象的[名称](https://en.wikipedia.org/wiki/Snake_case) (全部小写,单词之间用下划线分隔). 请参阅下面的好与坏示例. + +尽管在大多数情况下我们倾向于遵循该标准,但是只要名称不明确,也可以使用常见缩写(例如`mr` )或其他替代方式. 如果有助于避免混淆或使代码更具可读性,则可以包括附加`_page` . 例如,如果一个页面对象被命名为`New` ,也可能是混淆命名块论点`new` ,因为这是用来实例化对象,所以`new_page`是可以接受的. + +我们选择不只是使用`page`因为这会遮盖 Capybara DSL,从而可能导致混乱和错误. + +### Examples[](#examples-1 "Permalink") + +**Good** + +``` +Page::Project::Members.perform do |members| + members.do_something +end +``` + +``` +Resource::MergeRequest.fabricate! do |merge_request| + merge_request.do_something_else +end +``` + +``` +Resource::MergeRequest.fabricate! do |mr| + mr.do_something_else +end +``` + +``` +Page::Project::New.peform do |new_page| + new_page.do_something +end +``` + +**Bad** + +``` +Page::Project::Members.perform do |project_settings_members_page| + project_settings_members_page.do_something +end +``` + +``` +Page::Project::New.peform do |page| + page.do_something +end +``` + +> 除了采用标准的优点之外,通过遵循该标准,我们还编写了较短的代码行. \ No newline at end of file diff --git a/_book/docs/644.md b/_book/docs/644.md new file mode 100644 index 0000000000000000000000000000000000000000..dbe7c0ab11660946162fccaa1a7760bb91ef2210 --- /dev/null +++ b/_book/docs/644.md @@ -0,0 +1,35 @@ +# Testing with feature flags + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/feature_flags.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/feature_flags.html) + +* [Running a scenario with a feature flag enabled](#running-a-scenario-with-a-feature-flag-enabled) + +# Testing with feature flags[](#testing-with-feature-flags "Permalink") + +要在启用了功能标志的情况下运行特定的测试,可以使用`QA::Runtime::Feature`类来启用和禁用功能标志( [通过 API](../../../api/features.html) ). + +请注意,更改功能标志需要管理员授权. 只要您通过`GITLAB_QA_ADMIN_ACCESS_TOKEN` (推荐)提供适当的访问令牌,或者提供`GITLAB_ADMIN_USERNAME`和`GITLAB_ADMIN_PASSWORD` , `QA::Runtime::Feature`将自动以管理员身份进行身份验证. + +请确保包含标签`:requires_admin`以便在没有管理员权限的环境中可以跳过测试. + +``` +RSpec.describe "with feature flag enabled", :requires_admin do + before do + Runtime::Feature.enable('feature_flag_name') + end + + it "feature flag test" do + # Execute a test with a feature flag enabled + end + + after do + Runtime::Feature.disable('feature_flag_name') + end +end +``` + +## Running a scenario with a feature flag enabled[](#running-a-scenario-with-a-feature-flag-enabled "Permalink") + +也可以在启用功能标记的情况下运行整个方案,而无需编辑现有测试或编写新测试. + +有关详细信息,请参见[质量检查自述文件](https://gitlab.com/gitlab-org/gitlab/tree/master/qa#running-tests-with-a-feature-flag-enabled) . \ No newline at end of file diff --git a/_book/docs/645.md b/_book/docs/645.md new file mode 100644 index 0000000000000000000000000000000000000000..ce7e7285f182f439bc458d6bc154138a507535a6 --- /dev/null +++ b/_book/docs/645.md @@ -0,0 +1,47 @@ +# Translate GitLab to your language + +> 原文:[https://docs.gitlab.com/ee/development/i18n/](https://docs.gitlab.com/ee/development/i18n/) + +* [How to contribute](#how-to-contribute) + * [Externalize strings](#externalize-strings) + * [Translate strings](#translate-strings) + * [Proof reading](#proof-reading) +* [Release](#release) + +# Translate GitLab to your language[](#translate-gitlab-to-your-language "Permalink") + +默认情况下,GitLab 用户界面中的文本为美式英语. 每个字符串都可以翻译成其他语言. 在翻译每个字符串时,会将其添加到语言翻译文件中,并将在以后的 GitLab 版本中提供. + +始终需要为翻译做出贡献. 许多字符串尚未转换,因为它们尚未被外部化. 帮助外部化字符串有益于所有语言. 某些翻译不完整或不一致. 翻译字符串将有助于完成和改进每种语言. + +## How to contribute[](#how-to-contribute "Permalink") + +您可以通过多种方式来翻译 GitLab. + +### Externalize strings[](#externalize-strings "Permalink") + +在翻译字符串之前,必须将其外部化. 在此过程中,GitLab 源代码中的英文字符串被包装到一个函数中,该函数检索用户语言的翻译后的字符串. + +随着新功能的添加和现有功能的更新,周围的字符串也被外部化,但是,GitLab 的许多部分仍需要更多的工作来外部化所有字符串. + +See [Externalization for GitLab](externalization.html). + +### Translate strings[](#translate-strings "Permalink") + +使用[CrowdIn](https://crowdin.com/)在[https://translate.gitlab.com](https://translate.gitlab.com)上管理翻译过程. 您需要先创建一个帐户,然后才能提交翻译. 登录后,选择您想要贡献翻译的语言. + +对翻译进行投票也很有价值,有助于确认良好的翻译并标记不正确的翻译. + +See [Translation guidelines](translation.html). + +### Proof reading[](#proof-reading "Permalink") + +校对有助于确保翻译的准确性和一致性. 在接受所有翻译之前,请先进行校对. 如果翻译需要更改,则会通过注释告知您原因. + +有关谁可以校对的更多信息以及您自己成为校对者的说明,请参见[校对译文](proofreader.html) . + +## Release[](#release "Permalink") + +翻译通常包含在下一个主要或次要版本中. + +See [Merging translations from CrowdIn](merging_translations.html). \ No newline at end of file diff --git a/_book/docs/646.md b/_book/docs/646.md new file mode 100644 index 0000000000000000000000000000000000000000..cfec390610ba6aa58b3c827f4ba1fe5c1345a354 --- /dev/null +++ b/_book/docs/646.md @@ -0,0 +1,584 @@ +# Internationalization for GitLab + +> 原文:[https://docs.gitlab.com/ee/development/i18n/externalization.html](https://docs.gitlab.com/ee/development/i18n/externalization.html) + +* [Setting up GitLab Development Kit (GDK)](#setting-up-gitlab-development-kit-gdk) +* [Tools](#tools) +* [Preparing a page for translation](#preparing-a-page-for-translation) + * [Ruby files](#ruby-files) + * [HAML files](#haml-files) + * [ERB files](#erb-files) + * [JavaScript files](#javascript-files) + * [Dynamic translations](#dynamic-translations) +* [Working with special content](#working-with-special-content) + * [Interpolation](#interpolation) + * [Plurals](#plurals) + * [Namespaces](#namespaces) + * [Dates / times](#dates--times) +* [Best practices](#best-practices) + * [Keep translations dynamic](#keep-translations-dynamic) + * [Splitting sentences](#splitting-sentences) + * [Avoid splitting sentences when adding links](#avoid-splitting-sentences-when-adding-links) + * [Vue components interpolation](#vue-components-interpolation) +* [Updating the PO files with the new content](#updating-the-po-files-with-the-new-content) + * [Validating PO files](#validating-po-files) +* [Adding a new language](#adding-a-new-language) + +# Internationalization for GitLab[](#internationalization-for-gitlab "Permalink") + +在 GitLab 9.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10669) . + +为了使用国际化(i18n),使用了[GNU gettext](https://www.gnu.org/software/gettext/) ,因为它是该任务最常用的工具,并且有许多应用程序可以帮助我们使用它. + +## Setting up GitLab Development Kit (GDK)[](#setting-up-gitlab-development-kit-gdk "Permalink") + +为了能够在[GitLab 社区版](https://gitlab.com/gitlab-org/gitlab-foss)项目上工作,您必须通过[GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/set-up-gdk.md)下载并配置它. + +准备好 GitLab 项目后,就可以开始进行翻译了. + +## Tools[](#tools "Permalink") + +使用以下工具: + +1. [`gettext_i18n_rails`](https://github.com/grosser/gettext_i18n_rails) :这个 gem 使我们可以转换模型,视图和控制器中的内容. 此外,它还使我们可以访问以下 Rake 任务: + * `rake gettext:find` :解析 Rails 应用程序中的几乎所有文件,以查找已标记为要翻译的内容. 最后,它将使用找到的新内容更新 PO 文件. + * `rake gettext:pack` :处理 PO 文件并生成二进制的 MO 文件,最终由应用程序使用. +2. [`gettext_i18n_rails_js`](https://github.com/webhippie/gettext_i18n_rails_js) :此 gem 对于使翻译在 JavaScript 中可用非常有用. 它提供以下 Rake 任务: + * `rake gettext:po_to_json` :从 PO 文件中读取内容,并生成包含所有可用翻译的 JSON 文件. +3. PO 编辑器:有多个应用程序可以帮助我们处理 PO 文件, [Poedit](https://poedit.net/download)是一个不错的选择,可用于 macOS,GNU / Linux 和 Windows. + +## Preparing a page for translation[](#preparing-a-page-for-translation "Permalink") + +我们基本上有 4 种类型的文件: + +1. Ruby 文件:基本上是模型和控制器. +2. HAML 文件:这些是视图文件. +3. ERB 文件:用于电子邮件模板. +4. JavaScript 文件:我们主要需要使用 Vue 模板. + +### Ruby files[](#ruby-files "Permalink") + +例如,如果存在使用原始字符串的方法或变量,则: + +``` +def hello + "Hello world!" +end +``` + +Or: + +``` +hello = "Hello world!" +``` + +您可以轻松地将该内容标记为要翻译的内容: + +``` +def hello + _("Hello world!") +end +``` + +Or: + +``` +hello = _("Hello world!") +``` + +在类或模块级别转换字符串时要小心,因为在类加载时它们只会被评估一次. + +例如: + +``` +validates :group_id, uniqueness: { scope: [:project_id], message: _("already shared with this group") } +``` + +当加载该类时,这将被翻译,并导致错误消息始终位于默认语言环境中. + +Active Record’s `:message` option accepts a `Proc`, so we can do this instead: + +``` +validates :group_id, uniqueness: { scope: [:project_id], message: -> (object, data) { _("already shared with this group") } } +``` + +**注意:** API( `lib/api/`或`app/graphql` )中的消息无需外部化. + +### HAML files[](#haml-files "Permalink") + +考虑到 HAML 中的以下内容: + +``` +%h1 Hello world! +``` + +您可以使用以下方式将该内容标记为要翻译的内容: + +``` +%h1= _("Hello world!") +``` + +### ERB files[](#erb-files "Permalink") + +考虑到 ERB 中的以下内容: + +``` +<h1>Hello world!</h1> +``` + +您可以使用以下方式将该内容标记为要翻译的内容: + +``` +<h1><%= _("Hello world!") %></h1> +``` + +### JavaScript files[](#javascript-files "Permalink") + +在 JavaScript 中,我们添加了`__()` (双下划线括号)函数,您可以从`~/locale`文件中导入该函数. 例如: + +``` +import { __ } from '~/locale'; +const label = __('Subscribe'); +``` + +为了测试 JavaScript 翻译,您必须将 GitLab 本地化更改为英语以外的其他语言,并且必须使用`bin/rake gettext:po_to_json`或`bin/rake gettext:compile`生成 JSON 文件. + +### Dynamic translations[](#dynamic-translations "Permalink") + +有时,运行`bin/rake gettext:find`时,解析器无法找到一些动态转换. 对于这些情况,可以使用[`N_`方法](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#unfound-translations-with-rake-gettextfind) . + +还有另一种方法可以[转换来自验证错误的消息](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#option-a) . + +## Working with special content[](#working-with-special-content "Permalink") + +### Interpolation[](#interpolation "Permalink") + +翻译后的文字中的占位符应与相应源文件的代码样式匹配. 例如使用`%{created_at}`在 Ruby,但`%{createdAt}`在 JavaScript. [添加链接时,](#avoid-splitting-sentences-when-adding-links)请确保[避免拆分句子](#avoid-splitting-sentences-when-adding-links) . + +* 在 Ruby / HAML 中: + + ``` + _("Hello %{name}") % { name: 'Joe' } => 'Hello Joe' + ``` + +* 在 Vue 中: + + 请参见有关[Vue 分量插值](#vue-components-interpolation)的部分. + +* 在 JavaScript 中(无法使用 Vue 时): + + ``` + import { __, sprintf } from '~/locale'; + + sprintf(__('Hello %{username}'), { username: 'Joe' }); // => 'Hello Joe' + ``` + + 如果要在翻译中使用标记并且正在使用 Vue,则**必须**使用[`gl-sprintf`](#vue-components-interpolation)组件. 如果由于某种原因您不能使用 Vue,请使用`sprintf`并通过将`false`用作第三个参数来阻止其转义占位符值. 您**必须**使用自己逃避任何插值动态值,例如`escape`从`lodash` . + + ``` + import { escape } from 'lodash'; + import { __, sprintf } from '~/locale'; + + let someDynamicValue = '<script>alert("evil")</script>'; + + // Dangerous: + sprintf(__('This is %{value}'), { value: `<strong>${someDynamicValue}</strong>`, false); + // => 'This is <strong><script>alert('evil')</script></strong>' + + // Incorrect: + sprintf(__('This is %{value}'), { value: `<strong>${someDynamicValue}</strong>` }); + // => 'This is <strong><script>alert('evil')</script></strong>' + + // OK: + sprintf(__('This is %{value}'), { value: `<strong>${escape(someDynamicValue)}</strong>`, false); + // => 'This is <strong><script>alert('evil')</script></strong>' + ``` + +### Plurals[](#plurals "Permalink") + +* 在 Ruby / HAML 中: + + ``` + n_('Apple', 'Apples', 3) + # => 'Apples' + ``` + + 使用插值: + + ``` + n_("There is a mouse.", "There are %d mice.", size) % size + # => When size == 1: 'There is a mouse.' + # => When size == 2: 'There are 2 mice.' + ``` + + 避免在单个字符串中使用`%d`或计数变量. 这样可以更自然地翻译某些语言. + +* 在 JavaScript 中: + + ``` + n__('Apple', 'Apples', 3) + // => 'Apples' + ``` + + 使用插值: + + ``` + n__('Last day', 'Last %d days', x) + // => When x == 1: 'Last day' + // => When x == 2: 'Last 2 days' + ``` + +`n_`方法仅应用于获取同一字符串的多个转换,而不能控制针对不同数量显示不同字符串的逻辑. 某些语言具有不同数量的目标复数形式-例如,中文(简体)在我们的翻译工具中仅具有一种目标复数形式. 这意味着翻译者将不得不选择只翻译一个字符串,而翻译在另一种情况下的表现将不符合预期. + +例如,更喜欢使用: + +``` +if selected_projects.one? + selected_projects.first.name +else + n__("Project selected", "%d projects selected", selected_projects.count) +end +``` + +而不是: + +``` +# incorrect usage example +n_("%{project_name}", "%d projects selected", count) % { project_name: 'GitLab' } +``` + +### Namespaces[](#namespaces "Permalink") + +命名空间是一种将属于在一起的翻译进行分组的方法. 它们通过在前缀后面加上条形符号( `|` )为我们的翻译人员提供上下文. 例如: + +``` +'Namespace|Translated string' +``` + +命名空间具有以下优点: + +* 它解决了词义上的歧义,例如: `Promotions|Promote` vs `Epic|Promote` +* 它使翻译人员可以专注于翻译属于相同产品区域而不是任意产品区域的外部化字符串. +* 它提供了语言环境以帮助翻译. + +在某些情况下,例如,对于无处不在的 UI 单词和短语(如"取消")或短语(如"保存更改")而言,名称空间可能会适得其反. + +命名空间应为 PascalCase. + +* 在 Ruby / HAML 中: + + ``` + s_('OpenedNDaysAgo|Opened') + ``` + + 如果找不到翻译,它将返回`Opened` . + +* 在 JavaScript 中: + + ``` + s__('OpenedNDaysAgo|Opened') + ``` + +注意:应从转换中删除名称空间. 有关[更多详细信息,](translation.html#namespaced-strings)请参见[翻译指南](translation.html#namespaced-strings) . + +### Dates / times[](#dates--times "Permalink") + +* 在 JavaScript 中: + +``` +import { createDateTimeFormat } from '~/locale'; + +const dateFormat = createDateTimeFormat({ year: 'numeric', month: 'long', day: 'numeric' }); +console.log(dateFormat.format(new Date('2063-04-05'))) // April 5, 2063 +``` + +这利用了[`Intl.DateTimeFormat`](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat) . + +* 在 Ruby / HAML 中,我们有两种向日期和时间添加格式的方法: + + 1. **通过`l`帮助器** ,即`l(active_session.created_at, format: :short)` . 我们有一些预定义的[日期](https://gitlab.com/gitlab-org/gitlab/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/config/locales/en.yml#L54)和[时间](https://gitlab.com/gitlab-org/gitlab/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/config/locales/en.yml#L262)格式. 如果您需要添加新格式,因为代码的其他部分可能会从中受益,则需要将其添加到[en.yml](https://gitlab.com/gitlab-org/gitlab/blob/master/config/locales/en.yml)文件中. + 2. **通过`strftime`** ,即`milestone.start_date.strftime('%b %-d')` . 如果在[en.yml 上](https://gitlab.com/gitlab-org/gitlab/blob/master/config/locales/en.yml)定义的格式[均不](https://gitlab.com/gitlab-org/gitlab/blob/master/config/locales/en.yml)符合我们所需的日期/时间规范,并且由于非常特殊而无需将其添加为新格式的情况(例如,仅在单个视图中使用),则我们将使用`strftime` . . + +## Best practices[](#best-practices "Permalink") + +### Keep translations dynamic[](#keep-translations-dynamic "Permalink") + +在某些情况下,将翻译内容保持在数组或哈希中是有意义的. + +Examples: + +* 下拉列表的映射 +* 错误讯息 + +要存储此类数据,使用常数似乎是最佳选择,但这不适用于翻译. + +不好,请避免: + +``` +class MyPresenter + MY_LIST = { + key_1: _('item 1'), + key_2: _('item 2'), + key_3: _('item 3') + } +end +``` + +首次加载该类时,将调用翻译方法( `_` ),并将文本翻译为默认语言环境. 无论用户的语言环境是什么,这些值都不会再次转换. + +将类方法与备注一起使用时,也会发生类似的情况. + +不好,请避免: + +``` +class MyModel + def self.list + @list ||= { + key_1: _('item 1'), + key_2: _('item 2'), + key_3: _('item 3') + } + end +end +``` + +此方法将使用用户的语言环境来记住翻译,该用户首先"调用"此方法. + +为避免这些问题,请保持翻译动态. + +Good: + +``` +class MyPresenter + def self.my_list + { + key_1: _('item 1'), + key_2: _('item 2'), + key_3: _('item 3') + }.freeze + end +end +``` + +### Splitting sentences[](#splitting-sentences "Permalink") + +请不要拆分句子,因为这会假定句子的语法和结构在所有语言中都是相同的. + +例如,以下内容: + +``` +{{ s__("mrWidget|Set by") }} +{{ author.name }} +{{ s__("mrWidget|to be merged automatically when the pipeline succeeds") }} +``` + +应该外部化如下: + +``` +{{ sprintf(s__("mrWidget|Set by %{author} to be merged automatically when the pipeline succeeds"), { author: author.name }) }} +``` + +#### Avoid splitting sentences when adding links[](#avoid-splitting-sentences-when-adding-links "Permalink") + +当在翻译的句子之间使用链接时,这也适用,否则这些文本在某些语言中不可翻译. + +* 在 Ruby / HAML 中,而不是: + + ``` + - zones_link = link_to(s_('ClusterIntegration|zones'), 'https://cloud.google.com/compute/docs/regions-zones/regions-zones', target: '_blank', rel: 'noopener noreferrer') + = s_('ClusterIntegration|Learn more about %{zones_link}').html_safe % { zones_link: zones_link } + ``` + + 将链接的开始和结束 HTML 片段设置为变量,如下所示: + + ``` + - zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones' + - zones_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: zones_link_url } + = s_('ClusterIntegration|Learn more about %{zones_link_start}zones%{zones_link_end}').html_safe % { zones_link_start: zones_link_start, zones_link_end: '</a>'.html_safe } + ``` + +* 在 Vue 中,而不是: + + ``` + <template> + <div> + <gl-sprintf :message="s__('ClusterIntegration|Learn more about %{link}')"> + <template #link> + <gl-link + href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" + target="_blank" + >zones</gl-link> + </template> + </gl-sprintf> + </div> + </template> + ``` + + 将链接的开始和结束 HTML 片段设置为占位符,如下所示: + + ``` + <template> + <div> + <gl-sprintf :message="s__('ClusterIntegration|Learn more about %{linkStart}zones%{linkEnd}')"> + <template #link="{ content }"> + <gl-link + href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" + target="_blank" + >{{ content }}</gl-link> + </template> + </gl-sprintf> + </div> + </template> + ``` + +* 在 JavaScript 中(无法使用 Vue 时),而不是: + + ``` + {{ + sprintf(s__("ClusterIntegration|Learn more about %{link}"), { + link: '<a href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" target="_blank" rel="noopener noreferrer">zones</a>' + }) + }} + ``` + + 将链接的开始和结束 HTML 片段设置为占位符,如下所示: + + ``` + {{ + sprintf(s__("ClusterIntegration|Learn more about %{linkStart}zones%{linkEnd}"), { + linkStart: '<a href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" target="_blank" rel="noopener noreferrer">', + linkEnd: '</a>', + }) + }} + ``` + +其背后的原因是,在某些语言中,单词会根据上下文而变化. 例如,日语将は添加到句子的主语中,将を添加到宾语的主语中. 如果我们从句子中提取单个单词,则无法正确翻译. + +如有疑问,请尝试遵循此[Mozilla Developer 文档中](https://s0developer0mozilla0org.icopy.site/en-US/docs/Mozilla/Localization/Localization_content_best_practices)描述的最佳做法. + +##### Vue components interpolation[](#vue-components-interpolation "Permalink") + +在 Vue 组件中翻译 UI 文本时,您可能希望在转换字符串中包括子组件. 您不能使用仅 JavaScript 的解决方案来呈现翻译,因为 Vue 不会意识到子组件并将其呈现为纯文本. + +对于此用例,应使用在**GitLab UI 中**维护的`gl-sprintf`组件. + +`gl-sprintf`组件接受`message`属性,该属性是可翻译的字符串,并且为字符串中的每个占位符公开一个命名的插槽,这使您可以轻松地包含 Vue 组件. + +假设您要打印`Pipeline %{pipelineId} triggered %{timeago} by %{author}`的可翻译字符串`Pipeline %{pipelineId} triggered %{timeago} by %{author}` . 要将`%{timeago}`和`%{author}`占位符替换为 Vue 组件,以下是使用`gl-sprintf` : + +``` +<template> + <div> + <gl-sprintf :message="__('Pipeline %{pipelineId} triggered %{timeago} by %{author}')"> + <template #pipelineId>{{ pipeline.id }}</template> + <template #timeago> + <timeago :time="pipeline.triggerTime" /> + </template> + <template #author> + <gl-avatar-labeled + :src="pipeline.triggeredBy.avatarPath" + :label="pipeline.triggeredBy.name" + /> + </template> + </gl-sprintf> + </div> +</template> +``` + +有关更多信息,请参见[`gl-sprintf`](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-sprintf--default)文档. + +## Updating the PO files with the new content[](#updating-the-po-files-with-the-new-content "Permalink") + +现在,新内容已标记为要翻译,我们需要使用以下命令更新`locale/gitlab.pot`文件: + +``` +bin/rake gettext:regenerate +``` + +该命令将使用新外部化的字符串更新`locale/gitlab.pot`文件,并删除不再使用的任何字符串. 您应该检入此文件.一旦将更改保存在主文件中,它们将由[CrowdIn 提取](https://translate.gitlab.com)并显示以进行翻译. + +我们不需要签入对`locale/[language]/gitlab.po`文件的任何更改. 当[来自 CrowdIn 的翻译合并](merging_translations.html)时,它们会自动更新. + +如果`gitlab.pot`文件中存在合并冲突,则可以删除该文件并使用同一命令重新生成它. + +### Validating PO files[](#validating-po-files "Permalink") + +为了确保我们的翻译文件保持最新, `static-analysis`工作中有一个运行在 CI 上的 lint. + +要在本地`rake gettext:lint` PO 文件中的调整,可以运行`rake gettext:lint` . + +短绒将考虑以下因素: + +* 有效的 PO 文件语法 +* 可变用法 + * 仅一个未命名( `%d` )变量,因为变量的顺序可能会以不同的语言更改 + * 消息 ID 中使用的所有变量都在转换中使用 + * 转换中不应使用消息 ID 中没有的变量 +* 翻译时出错. + +错误按文件和消息 ID 分组: + +``` +Errors in `locale/zh_HK/gitlab.po`: + PO-syntax errors + SimplePoParser::ParserErrorSyntax error in lines + Syntax error in msgctxt + Syntax error in msgid + Syntax error in msgstr + Syntax error in message_line + There should be only whitespace until the end of line after the double quote character of a message text. + Parsing result before error: '{:msgid=>["", "You are going to remove %{project_name_with_namespace}.\\n", "Removed project CANNOT be restored!\\n", "Are you ABSOLUTELY sure?"]}' + SimplePoParser filtered backtrace: SimplePoParser::ParserError +Errors in `locale/zh_TW/gitlab.po`: + 1 pipeline + <%d 條流水線> is using unknown variables: [%d] + Failure translating to zh_TW with []: too few arguments +``` + +在此输出中, `locale/zh_HK/gitlab.po`具有语法错误. `locale/zh_TW/gitlab.po`具有转换中使用的变量,这些变量不在 ID `1 pipeline`的消息中. + +## Adding a new language[](#adding-a-new-language "Permalink") + +假设您想添加一种新语言的翻译,例如法语. + +1. 第一步是在`lib/gitlab/i18n.rb`注册新语言: + + ``` + ... + AVAILABLE_LANGUAGES = { + ..., + 'fr' => 'Français' + }.freeze + ... + ``` + +2. 接下来,您需要添加语言: + + ``` + bin/rake gettext:add_language[fr] + ``` + + 如果要为特定区域添加新语言,则命令类似,您只需要用下划线( `_` )分隔区域即可. 例如: + + ``` + bin/rake gettext:add_language[en_GB] + ``` + + 请注意,您需要在大写字母中指定地区部分. + +3. 现在已经添加了该语言,已经在以下路径下创建了一个新目录: `locale/fr/` . 现在,您可以开始使用 PO 编辑器来编辑位于`locale/fr/gitlab.edit.po`的 PO 文件. + +4. 更新完翻译后,您需要处理 PO 文件以生成二进制 MO 文件,最后更新包含翻译的 JSON 文件: + + ``` + bin/rake gettext:compile + ``` + +5. 为了查看翻译后的内容,我们需要更改首选语言,该语言可以在用户的**设置** ( `/profile` )下找到. + +6. 在确认更改没问题之后,您可以继续提交新文件. 例如: + + ``` + git add locale/fr/ app/assets/javascripts/locale/fr/ + git commit -m "Add French translations for Value Stream Analytics page" + ``` \ No newline at end of file diff --git a/_book/docs/647.md b/_book/docs/647.md new file mode 100644 index 0000000000000000000000000000000000000000..008820abe88e6856175c670009df84c50bd1702f --- /dev/null +++ b/_book/docs/647.md @@ -0,0 +1,91 @@ +# Translating GitLab + +> 原文:[https://docs.gitlab.com/ee/development/i18n/translation.html](https://docs.gitlab.com/ee/development/i18n/translation.html) + +* [Using CrowdIn](#using-crowdin) + * [Sign In](#sign-in) + * [Language Selections](#language-selections) + * [Translation Editor](#translation-editor) +* [General Translation Guidelines](#general-translation-guidelines) + * [Namespaced strings](#namespaced-strings) + * [Technical terms](#technical-terms) + * [Formality](#formality) + * [Inclusive language](#inclusive-language) + * [Updating the glossary](#updating-the-glossary) +* [French Translation Guidelines](#french-translation-guidelines) + * [Inclusive language in French](#inclusive-language-in-french) + +# Translating GitLab[](#translating-gitlab "Permalink") + +为了管理翻译过程,我们使用[CrowdIn](https://crowdin.com) . + +## Using CrowdIn[](#using-crowdin "Permalink") + +第一步是熟悉 CrowdIn. + +### Sign In[](#sign-in "Permalink") + +要在[https://translate.gitlab.com 上](https://translate.gitlab.com)提供翻译,您必须创建一个 CrowdIn 帐户. 您可以创建一个新帐户或使用其任何受支持的登录服务. + +### Language Selections[](#language-selections "Permalink") + +manbetx 客户端打不开被翻译成多种语言. + +1. 通过单击标志来选择您想要贡献翻译的语言 +2. 您将看到文件和文件夹的列表. 单击`gitlab.pot`打开翻译编辑器. + +### Translation Editor[](#translation-editor "Permalink") + +The online translation editor is the easiest way to contribute translations. + +[![CrowdIn Editor](img/6314765d395236bbba1552cc65c1228c.png)](img/crowdin-editor.png) + +1. 用于翻译的字符串列在左侧面板中 +2. 翻译输入到中央面板中. 包含复数的字符串将需要多次翻译. 上面显示了要翻译的字符串,并突出显示了词汇表术语. 如果要翻译的字符串不清楚,则可以"请求上下文" + +单击右侧的术语,可以在右侧面板中找到常用术语的词汇表. 可以添加评论以与社区讨论翻译. + +记住要**保存**每个翻译. + +## General Translation Guidelines[](#general-translation-guidelines "Permalink") + +转换任何字符串之前,请务必检查以下准则. + +### Namespaced strings[](#namespaced-strings "Permalink") + +当外部字符串带有名称空间(例如`s_('OpenedNDaysAgo|Opened')` ,应从最终转换中删除该名称空间. 例如,用法语`OpenedNDaysAgo|Opened`将被翻译为`Ouvert•e` ,而不是`OpenedNDaysAgo|Ouvert•e` . + +### Technical terms[](#technical-terms "Permalink") + +某些技术术语应像专有名词一样对待,不要翻译. + +使用[https://translate.gitlab.com](https://translate.gitlab.com)时,在词汇表中会注明应始终为英语的技术术语. + +这有助于维护工具(例如`git`客户端)和 GitLab 之间的逻辑连接和一致性. + +### Formality[](#formality "Permalink") + +软件中使用的形式级别因语言而异: + +| Language | Formality | Example | +| --- | --- | --- | +| French | formal | `vous` for `you` | +| German | informal | `du` for `you` | + +您可以参考词汇表中其他翻译的字符串和注释,以帮助确定适当的形式水平. + +### Inclusive language[](#inclusive-language "Permalink") + +[多样性](https://about.gitlab.com/handbook/values/#diversity)是 GitLab 的价值之一. 我们要求您避免翻译将性别或族裔排除在外的人. 在区分男女形式的语言中,请同时使用或选择中性的表述. + +例如,德语中的"用户"一词可以翻译成" Benutzer"(男性)或" Benutzerin"(女性). 因此,"创建新用户"将翻译为" Benutzer(in)anlegen". + +### Updating the glossary[](#updating-the-glossary "Permalink") + +要提出对词汇表的补充,请[打开一期](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=✓&state=all&label_name[]=Category:Internationalization) . + +## French Translation Guidelines[](#french-translation-guidelines "Permalink") + +### Inclusive language in French[](#inclusive-language-in-french "Permalink") + +在法语中,"包容所有法律"已结束(请参见[Legifrance](https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000036068906&categorieLien=id) ). 因此,要包括两个性别,请写上" Utilisateurs et utilisatrices",而不是" Utilisateur·rice·s". 如果缺少空间,则应单独使用男性. \ No newline at end of file diff --git a/_book/docs/648.md b/_book/docs/648.md new file mode 100644 index 0000000000000000000000000000000000000000..41a694a211754e8b3e68706865045420203d2207 --- /dev/null +++ b/_book/docs/648.md @@ -0,0 +1,138 @@ +# Proofread Translations + +> 原文:[https://docs.gitlab.com/ee/development/i18n/proofreader.html](https://docs.gitlab.com/ee/development/i18n/proofreader.html) + +* [Proofreaders](#proofreaders) +* [Become a proofreader](#become-a-proofreader) + +# Proofread Translations[](#proofread-translations "Permalink") + +大多数翻译是由社区贡献,审查和接受的. 我们非常感谢翻译人员和校对人员所做的工作! + +## Proofreaders[](#proofreaders "Permalink") + +* Albanian + * 需要校对者. +* Amharic + * Tsegaselassie Tadesse - [GitLab](https://gitlab.com/tsega), [CrowdIn](https://crowdin.com/profile/tsegaselassi/activity) +* Arabic + * 需要校对者. +* Bosnian + * 需要校对者. +* Bulgarian + * Lyubomir Vasilev- [CrowdIn](https://crowdin.com/profile/lyubomirv) +* Catalan + * 大卫 Planella - [GitLab](https://gitlab.com/dplanella) , [CrowdIn](https://crowdin.com/profile/dplanella) +* 简体中文简体中文 + * 黄涛- [GitLab](https://gitlab.com/htve) , [CrowdIn](https://crowdin.com/profile/htve) + * 维克多武- [GitLab](https://gitlab.com/victorwuky) , [CrowdIn](https://crowdin.com/profile/victorwu) + * 小刚文- [GitLab](https://gitlab.com/xiaogang_gitlab) , [CrowdIn](https://crowdin.com/profile/xiaogang_gitlab) +* Chinese Traditional 繁体中文 + * Weizhe Ding - [GitLab](https://gitlab.com/d.weizhe) , [CrowdIn](https://crowdin.com/profile/d.weizhe) + * Yi-Jyun Pan - [GitLab](https://gitlab.com/pan93412) , [CrowdIn](https://crowdin.com/profile/pan93412) + * Victor Wu - [GitLab](https://gitlab.com/victorwuky) , [CrowdIn](https://crowdin.com/profile/victorwu) +* Chinese Traditional, Hong Kong 繁体中文(香港) + * Victor Wu - [GitLab](https://gitlab.com/victorwuky) , [CrowdIn](https://crowdin.com/profile/victorwu) + * Ivan Ip - [GitLab](https://gitlab.com/lifehome) , [CrowdIn](https://crowdin.com/profile/lifehome) +* Croatian + * 需要校对者. +* Czech + * 一月 Urbanec - [GitLab](https://gitlab.com/TatranskyMedved) , [CrowdIn](https://crowdin.com/profile/Tatranskymedved) +* Danish + * Saederup92- [GitLab](https://gitlab.com/Saederup92) , [人群进入](https://crowdin.com/profile/Saederup92) +* Dutch + * 艾米丽 Hendle - [GitLab](https://gitlab.com/pundachan) , [CrowdIn](https://crowdin.com/profile/pandachan) +* Esperanto + * Lyubomir Vasilev- [CrowdIn](https://crowdin.com/profile/lyubomirv) +* Estonian + * 需要校对者. +* Filipino + * Andrei Jiroh Halili- [GitLab](https://gitlab.com/AJHalili2006DevPH) , [克劳丁](https://crowdin.com/profile/AndreiJirohHaliliDev2006) +* French + * Davy Defaud- [GitLab](https://gitlab.com/DevDef) , [人群](https://crowdin.com/profile/DevDef) +* Galician + * AntónMéixome- [群众](https://crowdin.com/profile/meixome) + * 佩德罗·加西亚- [GitLab](https://gitlab.com/pedgarrod) , [CrowdIn](https://crowdin.com/profile/breaking_pitt) +* German + * 迈克尔 Hahnle - [GitLab](https://gitlab.com/mhah) , [CrowdIn](https://crowdin.com/profile/mhah) + * 卡特琳 Leinweber - [GitLab](https://gitlab.com/katrinleinweber/) , [CrowdIn](https://crowdin.com/profile/katrinleinweber) +* Greek + * 需要校对者. +* Hebrew + * Yaron Shahrabani- [GitLab](https://gitlab.com/yarons) , [人群](https://crowdin.com/profile/YaronSh) +* Hindi + * 需要校对者. +* Hungarian + * 需要校对者. +* Indonesian + * 阿迪 Ferdian - [GitLab](https://gitlab.com/adiferd) , [CrowdIn](https://crowdin.com/profile/adiferd) + * Ahmad Naufal Mukhtar- [GitLab](https://gitlab.com/anaufalm) , [CrowdIn](https://crowdin.com/profile/anaufalm) +* Italian + * Massimiliano Cuttini- [GitLab](https://gitlab.com/maxcuttins) , [人群](https://crowdin.com/profile/maxcuttins) + * 保罗 Falomo - [GitLab](https://gitlab.com/paolofalomo) , [CrowdIn](https://crowdin.com/profile/paolo.falomo) +* Japanese + * 佐藤博之- [GitLab](https://gitlab.com/hiroponz) , [CrowdIn](https://crowdin.com/profile/hiroponz) + * Tomo Dote- [GitLab](https://gitlab.com/fu7mu4) , [人群](https://crowdin.com/profile/fu7mu4) + * 博美 Nozawa- [GitLab](https://gitlab.com/hir0mi) , [CrowdIn](https://crowdin.com/profile/hir0mi) + * 木村拓哉 Noguchi- [GitLab](https://gitlab.com/tnir) , [CrowdIn](https://crowdin.com/profile/tnir) +* Korean + * Chang-Ho Cha- [GitLab](https://gitlab.com/changho-cha) , [人群](https://crowdin.com/profile/zzazang) + * Ji Hun Oh- [GitLab](https://gitlab.com/Baw-Appie) , [CrowdIn](https://crowdin.com/profile/BawAppie) + * Jeongwhan 彩- [GitLab](https://gitlab.com/jeongwhanchoi) , [CrowdIn](https://crowdin.com/profile/jeongwhanchoi) +* Mongolian + * 需要校对者. +* 挪威博克马尔 + * 需要校对者. +* Polish + * 菲利普机甲- [GitLab](https://gitlab.com/mehenz) , [CrowdIn](https://crowdin.com/profile/mehenz) + * Maksymilian 罗马- [GitLab](https://gitlab.com/villaincandle) , [CrowdIn](https://crowdin.com/profile/villaincandle) +* Portuguese + * Diogo Trindade- [GitLab](https://gitlab.com/luisdiogo2071317) , [人群](https://crowdin.com/profile/ldiogotrindade) +* 葡萄牙语,巴西语 + * 保罗乔治·戈麦斯贝泽拉- [GitLab](https://gitlab.com/paulobezerra) , [CrowdIn](https://crowdin.com/profile/paulogomes.rep) + * [AndréGama](https://crowdin.com/profile/ToeOficial) - [GitLab](https://gitlab.com/andregamma) , [众筹](https://crowdin.com/profile/ToeOficial) +* Romanian + * 需要校对者. +* Russian + * 尼基塔 Grylov - [GitLab](https://gitlab.com/nixel2007) , [Crowdin](https://crowdin.com/profile/nixel2007) + * 阿列克西 Lustin - [GitLab](https://gitlab.com/allustin) , [Crowdin](https://crowdin.com/profile/lustin) + * 马克 Minakou - [GitLab](https://gitlab.com/sandzhaj) , [Crowdin](https://crowdin.com/profile/sandzhaj) + * 尼克·沃伦金- [克劳丁](https://crowdin.com/profile/NickVolynkin) + * 安德烈·科马洛夫- [GitLab](https://gitlab.com/elkamarado) , [Crowdin](https://crowdin.com/profile/kamarado) + * Iaroslav Postovalov- [GitLab](https://gitlab.com/CMDR_Tvis) , [克劳丁](https://crowdin.com/profile/CMDR_Tvis) +* 塞尔维亚文(拉丁文和西里尔文) + * 需要校对者. +* Slovak + * 需要校对者. +* Spanish + * 佩德罗·加西亚- [GitLab](https://gitlab.com/pedgarrod) , [CrowdIn](https://crowdin.com/profile/breaking_pitt) +* Swedish + * 需要校对者. +* Turkish + * AliDemirtaş- [GitLab](https://gitlab.com/alidemirtas) , [CrowdIn](https://crowdin.com/profile/alidemirtas) + * 瑞法特Ünalmış(瑞法特 Unalmis) - [GitLab](https://gitlab.com/runalmis) , [CrowdIn](https://crowdin.com/profile/runalmis) +* Ukrainian + * Volodymyr Sobotovych- [GitLab](https://gitlab.com/wheleph) , [人群](https://crowdin.com/profile/wheleph) + * Andrew Vityuk- [GitLab](https://gitlab.com/3_1_3_u) , [人群](https://crowdin.com/profile/andruwa13) +* Welsh + * Delyth 价格- [GitLab](https://gitlab.com/Delyth) , [CrowdIn](https://crowdin.com/profile/DelythPrys) + +## Become a proofreader[](#become-a-proofreader "Permalink") + +> **注意:**在 CrowdIn 中请求校对者权限之前,请确保您具有向 GitLab 项目提供翻译的历史. + +1. 向 GitLab 提供翻译. 请参阅有关[翻译 GitLab 的说明](translation.html) . + + 转换 GitLab 是一项社区工作,需要团队合作并注重细节. 校对人员在帮助新撰稿人,确保翻译的一致性和质量方面发挥着重要作用. 您作为翻译的行为和贡献应在要求成为校对之前反映出这一点. + +2. 通过打开将自己添加到校对者列表的合并请求来请求校对者权限. + + 打开[proofreader.md 源文件](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/i18n/proofreader.md) ,然后单击" **编辑"** . + + 按字母顺序添加您的语言,并将您自己添加到列表中,包括:-名称-链接到 GitLab 配置文件-链接到 CrowdIn 配置文件 + + 在合并请求说明中,请包含指向您之前翻译过的所有项目的链接. + +3. 熟练使用该语言的[GitLab 团队成员](https://about.gitlab.com/company/team/)或[核心团队成员](https://about.gitlab.com/community/core-team/)或当前的校对者,将考虑您以前作为校对者的要求. + + * 当要求使用某种语言的第一校对者时,并且没有使用该语言的[GitLab 团队成员](https://about.gitlab.com/company/team/)或[Core 团队成员](https://about.gitlab.com/community/core-team/) ,我们将请求指向其他社区或项目中先前翻译工作的链接. \ No newline at end of file diff --git a/_book/docs/649.md b/_book/docs/649.md new file mode 100644 index 0000000000000000000000000000000000000000..3a80a5c7de28ea716ce295062b370aea7699fea2 --- /dev/null +++ b/_book/docs/649.md @@ -0,0 +1,49 @@ +# Merging translations from CrowdIn + +> 原文:[https://docs.gitlab.com/ee/development/i18n/merging_translations.html](https://docs.gitlab.com/ee/development/i18n/merging_translations.html) + +* [Validation](#validation) +* [Merging translations](#merging-translations) +* [Recreate the merge request](#recreate-the-merge-request) +* [Recreate the GitLab integration in CrowdIn](#recreate-the-gitlab-integration-in-crowdin) + +# Merging translations from CrowdIn[](#merging-translations-from-crowdin "Permalink") + +CrowdIn 自动将`gitlab.pot`文件与 CrowdIn 服务同步,将新添加的外部化字符串呈现给翻译者社区. + +[GitLab CrowdIn Bot](https://gitlab.com/gitlab-crowdin-bot)还会创建合并请求,以接受新批准的翻译提交并将其合并到`locale/<language>/gitlab.po`文件中. 检查[`gitlab-crowdin-bot`创建](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&utf8=✓&state=opened&author_username=gitlab-crowdin-bot)的[合并请求,](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&utf8=✓&state=opened&author_username=gitlab-crowdin-bot)以查看新的和合并的合并请求. + +## Validation[](#validation "Permalink") + +默认情况下,CrowdIn 使用提交消息中的`[skip ci]`提交翻译. 这样做是为了避免运行一堆管道. 在合并翻译之前,请确保触发管道以验证翻译,我们进行了静态分析,以验证 CrowdIn 不执行的操作. 为`master-i18n`分支在`https://gitlab.com/gitlab-org/gitlab/pipelines/new` (需要开发人员访问权限)处创建一个新管道. + +如果存在验证错误,最简单的解决方案是拒绝 CrowdIn 中有问题的字符串,并在注释中注明解决该问题所需的内容. 有一个[问题](https://gitlab.com/gitlab-org/gitlab/-/issues/23256)提示自动完成这一过程. 拒登将排除无效翻译,合并请求将在几分钟内更新. + +将 CrowdIn 端的集成暂停一会可能很方便,因此翻译不会持续进行. 这可以通过在[CrowdIn 集成设置页面](https://translate.gitlab.com/project/gitlab-ee/settings#integration)上单击" `Pause sync`来完成. + +解决所有故障后,需要再次检查翻译,如[机密问题](../../user/project/issues/confidential_issues.html) `https://gitlab.com/gitlab-org/gitlab/-/issues/19485` . + +## Merging translations[](#merging-translations "Permalink") + +当发现所有翻译都很好并且流水线通过时,这些翻译可以合并到 master 分支中. 合并翻译时,请确保选中" **删除源分支"**复选框,以便 CrowdIn 在合并新翻译后从 master 重新创建`master-i18n` . + +我们正在讨论使[整个过程自动化](https://gitlab.com/gitlab-org/gitlab/-/issues/19896) . + +## Recreate the merge request[](#recreate-the-merge-request "Permalink") + +一旦关闭或合并旧的 CrowdIn,它就会创建一个新的合并请求. 但是它不会每次都重新创建`master-i18n`分支. 要强制 CrowdIn 重新创建分支,请关闭所有[打开的合并请求](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&utf8=✓&state=opened&author_username=gitlab-crowdin-bot)并删除[`master-18n`](https://gitlab.com/gitlab-org/gitlab/-/branches/all?utf8=✓&search=master-i18n) . + +当合并请求包含已在主服务器上修复的故障时,可能需要这样做. + +## Recreate the GitLab integration in CrowdIn[](#recreate-the-gitlab-integration-in-crowdin "Permalink") + +***注意:**这些说明仅适用于 GitLab 团队成员. + +If for some reason the GitLab integration in CrowdIn does not exist, it can be recreated by the following steps: + +1. 以`gitlab-crowdin-bot`身份登录到 GitLab(如果您是 GitLab 团队成员,请在 GitLab 共享的[1Password 帐户中](https://about.gitlab.com/handbook/security/#1password-for-teams)找到凭据 +2. 使用 GitLab 集成登录 Crowdin +3. 导航到设置>集成> GitLab>设置集成 +4. Select `gitlab-org/gitlab` repository +5. 在" `Select Branches for Translation` ,选择" `master` +6. 确保`Service Branch Name`为`master-i18n` \ No newline at end of file diff --git a/_book/docs/650.md b/_book/docs/650.md new file mode 100644 index 0000000000000000000000000000000000000000..dbeaf92e5723e4baf6800a043f8c85d79c652e43 --- /dev/null +++ b/_book/docs/650.md @@ -0,0 +1,186 @@ +# Value Stream Analytics development guide + +> 原文:[https://docs.gitlab.com/ee/development/value_stream_analytics.html](https://docs.gitlab.com/ee/development/value_stream_analytics.html) + +* [Stage](#stage) + * [Events](#events) + * [Implementing an `Event` class](#implementing-an-event-class) + * [Validating start and end events](#validating-start-and-end-events) + * [Parent](#parent) + * [How parent relationship it work](#how-parent-relationship-it-work) + * [Default stages](#default-stages) +* [Data Collector](#data-collector) +* [Database query](#database-query) +* [High-level overview](#high-level-overview) +* [Testing](#testing) + +# Value Stream Analytics development guide[](#value-stream-analytics-development-guide "Permalink") + +值流分析计算域对象上记录的两个任意事件之间的时间,并提供有关持续时间的汇总统计信息. + +有关如何在 GitLab 中配置 Value Stream Analytics 的信息,请参阅我们的[分析文档](../user/analytics/value_stream_analytics.html) . + +## Stage[](#stage "Permalink") + +在开发过程中,会发生一些事件,这些事件会移动问题并在不同的进展阶段合并请求,直到认为它们完成为止. 这些阶段可以用`Stage`模型表示. + +示例阶段: + +* Name: Development +* 开始事件:问题已创建 +* 结束事件:在提交中首先提到的问题 +* Parent: `Group: gitlab-org` + +### Events[](#events "Permalink") + +事件是价值流分析功能的最小构建块. 一个阶段包括两个事件: + +* Start +* End + +这些事件在持续时间计算中起关键作用. + +Formula: `duration = end_event_time - start_event_time` + +为了使持续时间计算更加灵活,每个`Event`都实现为一个单独的类. 他们负责定义将在计算查询中使用的时间戳表达式. + +#### Implementing an `Event` class[](#implementing-an-event-class "Permalink") + +有一些方法需要实现, `StageEvent`基类非常详细地描述了它们. 最重要的是: + +* `object_type` +* `timestamp_projection` + +`object_type`方法定义将查询哪个域对象以进行计算. 当前允许两种模型: + +* `Issue` +* `MergeRequest` + +对于持续时间计算,将使用`timestamp_projection`方法. + +``` +def timestamp_projection + # your timestamp expression comes here +end + +# event will use the issue creation time in the duration calculation +def timestamp_projection + Issue.arel_table[:created_at] +end +``` + +**注意:**也可以使用更复杂的表达式(例如,使用`COALESCE` ). 查看现有事件类作为示例. + +在某些情况下,仅定义`timestamp_projection`方法是不够的. 计算查询应该知道哪个表包含时间戳表达式. 每个`Event`类负责修改计算查询,以使`timestamp_projection`起作用. 这通常意味着加入一个附加表. + +连接`issue_metrics`表并使用`first_mentioned_in_commit_at`列作为时间戳表达式的`first_mentioned_in_commit_at` : + +``` +def object_type + Issue +end + +def timestamp_projection + IssueMetrics.arel_table[:first_mentioned_in_commit_at] +end + +def apply_query_customization(query) + # in this case the query attribute will be based on the Issue model: `Issue.where(...)` + query.joins(:metrics) +end +``` + +### Validating start and end events[](#validating-start-and-end-events "Permalink") + +某些开始/结束事件对彼此不"兼容". 例如: + +* 从"已创建问题"到"已合并请求":事件类在不同的域模型上定义, `object_type`方法不同. +* "问题已关闭"到"问题已创建":必须先创建问题,然后才能将其关闭. +* 从"问题已关闭"到"问题已关闭":持续时间始终为 0. + +`StageEvents`模块描述了允许的`start_event`和`end_event`配对( `PAIRING_RULES`常数). 如果添加了新事件,则需要在该模块中注册它. 要添加新事件: + +1. 在`ENUM_MAPPING`添加一个具有唯一编号的条目,该条目将在`Stage`模型中用作`enum` . +2. 在`PAIRING_RULES`哈希中定义哪些事件与该事件兼容. + +支持的开始/结束事件配对: + +图 LR; IssueCreated-> IssueClosed; IssueCreated-> IssueFirstAddedToBoard; IssueCreated-> IssueFirstAssociatedWithMilestone; IssueCreated-> IssueFirstMentionedInCommit; IssueCreated-> IssueLastEdited; IssueCreated-> IssueLabelAdded; IssueCreated-> IssueLabelRemoved; MergeRequestCreated-> MergeRequestMerged; MergeRequestCreated-> MergeRequestClosed; MergeRequestCreated-> MergeRequestFirstDeployedToProduction; MergeRequestCreated-> MergeRequestLastBuildStarted; MergeRequestCreated-> MergeRequestLastBuildFinished; MergeRequestCreated-> MergeRequestLastEdited; MergeRequestCreated-> MergeRequestLabelAdded; MergeRequestCreated-> MergeRequestLabelRemoved; MergeRequestLastBuildStarted-> MergeRequestLastBuildFinished; MergeRequestLastBuildStarted-> MergeRequestClosed; MergeRequestLastBuildStarted-> MergeRequestFirstDeployedToProduction; MergeRequestLastBuildStarted-> MergeRequestLastEdited; MergeRequestLastBuildStarted-> MergeRequestMerged; MergeRequestLastBuildStarted-> MergeRequestLabelAdded; MergeRequestLastBuildStarted-> MergeRequestLabelRemoved; MergeRequestMerged-> MergeRequestFirstDeployedToProduction; MergeRequestMerged-> MergeRequestClosed; MergeRequestMerged-> MergeRequestFirstDeployedToProduction; MergeRequestMerged-> MergeRequestLastEdited; MergeRequestMerged-> MergeRequestLabelAdded; MergeRequestMerged-> MergeRequestLabelRemoved; IssueLabelAdded-> IssueLabelAdded; IssueLabelAdded-> IssueLabelRemoved; IssueLabelAdded-> IssueClosed; IssueLabelRemoved-> IssueClosed; IssueFirstAddedToBoard-> IssueClosed; IssueFirstAddedToBoard-> IssueFirstAssociatedWithMilestone; IssueFirstAddedToBoard-> IssueFirstMentionedInCommit; IssueFirstAddedToBoard-> IssueLastEdited; IssueFirstAddedToBoard-> IssueLabelAdded; IssueFirstAddedToBoard-> IssueLabelRemoved; IssueFirstAssociatedWithMilestone-> IssueClosed; IssueFirstAssociatedWithMilestone-> IssueFirstAddedToBoard; IssueFirstAssociatedWithMilestone-> IssueFirstMentionedInCommit; IssueFirstAssociatedWithMilestone-> IssueLastEdited; IssueFirstAssociatedWithMilestone-> IssueLabelAdded; IssueFirstAssociatedWithMilestone-> IssueLabelRemoved; IssueFirstMentionedInCommit-> IssueClosed; IssueFirstMentionedInCommit-> IssueFirstAssociatedWithMilestone; IssueFirstMentionedInCommit-> IssueFirstAddedToBoard; IssueFirstMentionedInCommit-> IssueLastEdited; IssueFirstMentionedInCommit-> IssueLabelAdded; IssueFirstMentionedInCommit->已删除 IssueLabel; IssueClosed-> IssueLastEdited; IssueClosed-> IssueLabelAdded; IssueClosed-> IssueLabelRemoved; MergeRequestClosed-> MergeRequestFirstDeployedToProduction; MergeRequestClosed-> MergeRequestLastEdited; MergeRequestClosed-> MergeRequestLabelAdded; MergeRequestClosed-> MergeRequestLabelRemoved; MergeRequestFirstDeployedToProduction-> MergeRequestLastEdited; MergeRequestFirstDeployedToProduction-> MergeRequestLabelAdded; MergeRequestFirstDeployedToProduction-> MergeRequestLabelRemoved; MergeRequestLastBuildFinished-> MergeRequestClosed; MergeRequestLastBuildFinished-> MergeRequestFirstDeployedToProduction; MergeRequestLastBuildFinished-> MergeRequestLastEdited; MergeRequestLastBuildFinished-> MergeRequestMerged; MergeRequestLastBuildFinished-> MergeRequestLabelAdded; MergeRequestLastBuildFinished-> MergeRequestLabelRemoved; MergeRequestLabelAdded-> MergeRequestLabelAdded; MergeRequestLabelAdded-> MergeRequestLabelRemoved; MergeRequestLabelRemoved-> MergeRequestLabelAdded; MergeRequestLabelRemoved-> MergeRequestLabelRemoved; + +### Parent[](#parent "Permalink") + +团队和组织可能会定义自己的软件构建方式,因此阶段可能完全不同. 对于每个阶段,都需要定义一个父对象. + +目前支持的父母: + +* `Project` +* `Group` + +#### How parent relationship it work[](#how-parent-relationship-it-work "Permalink") + +1. 用户导航到价值流分析页面. +2. 用户选择一个组. +3. 后端将加载选定组的已定义阶段. +4. 对阶段的添加和修改将仅保留在所选组中. + +### Default stages[](#default-stages "Permalink") + +价值流分析的[原始实施](https://gitlab.com/gitlab-org/gitlab/-/issues/847)定义了 7 个阶段. 每个父母都可以使用这些阶段,但是无法更改这些阶段. 为了提高效率并减少创建的记录数,默认阶段被表示为内存中对象(不持久). 当用户首次创建自定义阶段时,所有阶段都将保留. 此行为在价值流分析服务对象中实现. 这样做的原因是我们希望稍后添加隐藏和订购阶段的功能. + +## Data Collector[](#data-collector "Permalink") + +`DataCollector`是从数据库查询数据的中心点. 该类始终在单个阶段上运行,并且由以下组件组成: + +* `BaseQueryBuilder`: + * 负责编写初始查询. + * 处理特定于`Stage`配置:事件及其查询自定义. + * 来自用户界面的参数:日期范围. +* `Median` :使用`BaseQueryBuilder`的查询计算一个阶段的中位数持续时间. +* `RecordsFetcher` :使用来自`BaseQueryBuilder`的查询和特定的`Finder`类加载阶段的相关记录,以应用可见性规则. +* `DataForDurationChart` :加载散点图的带有完成时间(结束事件时间戳)的计算的持续时间. + +对于新的计算或查询,可将其实现为`DataCollector`类中的新方法调用. + +## Database query[](#database-query "Permalink") + +数据库查询的结构: + +``` +SELECT (customized by: Median or RecordsFetcher or DataForDurationChart) +FROM OBJECT_TYPE (Issue or MergeRequest) +INNER JOIN (several JOIN statements, depending on the events) +WHERE + (Filter by the PARENT model, example: filter Issues from Project A) + (Date range filter based on the OBJECT_TYPE.created_at) + (Check if the START_EVENT is earlier than END_EVENT, preventing negative duration) +``` + +`Median`的`SELECT`语句的结构: + +``` +SELECT (calculate median from START_EVENT_TIME-END_EVENT_TIME) +``` + +用于`DataForDurationChart`的`SELECT`语句的`DataForDurationChart` : + +``` +SELECT (START_EVENT_TIME-END_EVENT_TIME) as duration, END_EVENT.timestamp +``` + +## High-level overview[](#high-level-overview "Permalink") + +* Rails 控制器( `Analytics::CycleAnalytics`模块):值流分析通过 JSON 端点公开其数据,该端点在`analytics`工作区中实现. 配置阶段还实现 JSON 端点(CRUD). +* 服务( `Analytics::CycleAnalytics`模块):所有与`Stage`相关的操作都将委派给相应的服务对象. +* 模型( `Analytics::CycleAnalytics`模块):模型用于持久化`Stage`对象`ProjectStage`和`GroupStage` . +* 要素类( `Gitlab::Analytics::CycleAnalytics`模块): + * 负责撰写查询并定义特定于功能的业务逻辑. + * `DataCollector` , `Event` , `StageEvents`等. + +## Testing[](#testing "Permalink") + +由于我们有很多事件和可能的配对,因此无法测试每个配对. 规则是至少要有一个使用`Event`类的测试用例. + +使用新`Event`为阶段编写测试用例可能会遇到挑战,因为必须为两个事件都创建数据. 为了使此过程更简单,必须在`data_collector_spec.rb`中实现每个测试用例,在该`data_collector_spec.rb`中,通过`DataCollector`对该阶段进行测试. 每个测试用例都将变成多个测试,涵盖以下情况: + +* 不同的父母: `Group`或`Project` +* 不同的计算方式: `Median` , `RecordsFetcher`或`DataForDurationChart` \ No newline at end of file diff --git a/_book/docs/651.md b/_book/docs/651.md new file mode 100644 index 0000000000000000000000000000000000000000..26849b9f9964611b7fd2290d6bef1465a8523898 --- /dev/null +++ b/_book/docs/651.md @@ -0,0 +1,542 @@ +# GitLab subscription + +> 原文:[https://docs.gitlab.com/ee/subscriptions/](https://docs.gitlab.com/ee/subscriptions/) + +* [Choosing a GitLab subscription](#choosing-a-gitlab-subscription) + * [Choosing a GitLab tier](#choosing-a-gitlab-tier) + * [Choosing between GitLab.com or self-managed](#choosing-between-gitlabcom-or-self-managed) + * [Choosing a GitLab.com group or personal subscription](#choosing-a-gitlabcom-group-or-personal-subscription) + * [Choosing the number of users](#choosing-the-number-of-users) + * [GitLab.com](#gitlabcom) + * [Self-managed](#self-managed) + * [Users statistics](#users-statistics) +* [Obtain a GitLab subscription](#obtain-a-gitlab-subscription) + * [Subscribe to GitLab.com](#subscribe-to-gitlabcom) + * [Subscribe through GitLab self-managed](#subscribe-through-gitlab-self-managed) +* [Manage your GitLab account](#manage-your-gitlab-account) + * [Change billing information](#change-billing-information) + * [Change payment method](#change-payment-method) + * [Change the linked account](#change-the-linked-account) + * [Change the associated namespace](#change-the-associated-namespace) + * [Change customer portal account password](#change-customer-portal-account-password) +* [View your subscription](#view-your-subscription) + * [View your GitLab.com subscription](#view-your-gitlabcom-subscription) + * [View your self-managed subscription](#view-your-self-managed-subscription) +* [Renew your subscription](#renew-your-subscription) + * [Prepare for renewal by reviewing your account](#prepare-for-renewal-by-reviewing-your-account) + * [Users over License](#users-over-license) + * [Purchase additional seats for GitLab.com](#purchase-additional-seats-for-gitlabcom) + * [Purchase additional users for self-managed](#purchase-additional-users-for-self-managed) + * [Seat Link](#seat-link) + * [Disable Seat Link](#disable-seat-link) + * [Renew or change a GitLab.com subscription](#renew-or-change-a-gitlabcom-subscription) + * [Automatic renewal](#automatic-renewal) + * [Renew a self-managed subscription](#renew-a-self-managed-subscription) +* [Upgrade your subscription tier](#upgrade-your-subscription-tier) + * [Upgrade your GitLab.com subscription tier](#upgrade-your-gitlabcom-subscription-tier) + * [Upgrade your self-managed subscription tier](#upgrade-your-self-managed-subscription-tier) +* [Subscription expiry](#subscription-expiry) + * [Self-managed GitLab data](#self-managed-gitlab-data) +* [CI pipeline minutes](#ci-pipeline-minutes) + * [Purchasing additional CI minutes](#purchasing-additional-ci-minutes) +* [Contact Support](#contact-support) +* [GitLab for Education subscriptions](#gitlab-for-education-subscriptions) +* [GitLab for Open Source subscriptions](#gitlab-for-open-source-subscriptions) + +# GitLab subscription[](#gitlab-subscription "Permalink") + +GitLab 提供了多层功能. 您的订阅决定了您有权访问的层. 订阅有效期为 12 个月. + +GitLab 为[GitLab 教育计划](https://about.gitlab.com/solutions/education/)和[GitLab 开源计划的](https://about.gitlab.com/solutions/open-source/)参与者提供特殊订阅. 有关获取和续订这些订阅的详细信息,请参阅: + +* [GitLab for Education subscriptions](#gitlab-for-education-subscriptions) +* [GitLab for Open Source subscriptions](#gitlab-for-open-source-subscriptions) + +## Choosing a GitLab subscription[](#choosing-a-gitlab-subscription "Permalink") + +选择订阅时,请考虑以下因素: + +* [GitLab tier](#choosing-a-gitlab-tier) +* [GitLab.com or self-managed](#choosing-between-gitlabcom-or-self-managed) +* [Group or personal subscription (GitLab.com only)](#choosing-a-gitlabcom-group-or-personal-subscription) +* [Number of users](#choosing-the-number-of-users) + +### Choosing a GitLab tier[](#choosing-a-gitlab-tier "Permalink") + +定价[基于层级](https://about.gitlab.com/pricing/) ,使您可以选择适合预算的功能. 请参阅[GitLab.com 功能比较](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/)和[自我管理功能比较,](https://about.gitlab.com/pricing/self-managed/feature-comparison/)以获取有关每种产品在每个层上可用的[功能](https://about.gitlab.com/pricing/self-managed/feature-comparison/)的信息. + +### Choosing between GitLab.com or self-managed[](#choosing-between-gitlabcom-or-self-managed "Permalink") + +订阅的应用方式有所不同,具体取决于您使用的是 GitLab.com 还是自我管理的实例. + +* [GitLab.com:GitLab](#gitlabcom)的软件即服务产品. 您无需安装任何程序即可使用 GitLab.com,只需[注册](https://gitlab.com/users/sign_up)并立即开始使用 GitLab. +* [GitLab 自我管理](#self-managed) :安装,管理和维护自己的 GitLab 实例. + +在自我管理的实例上,GitLab 订阅为所有用户提供了相同的功能集. 在 GitLab.com 上,您可以将订阅应用于组或个人名称空间. + +**注意:**订阅不能在 GitLab.com 和 GitLab 自我管理之间转移. 必须购买新订阅并根据需要应用. + +### Choosing a GitLab.com group or personal subscription[](#choosing-a-gitlabcom-group-or-personal-subscription "Permalink") + +在 GitLab.com 上,您可以将订阅应用于组或个人名称空间. + +适用于: + +* GitLab.com 上的**组** ,组,所有子组以及所选组下的所有项目将具有关联层的功能. GitLab 建议在管理组织的项目和用户时选择一个小组计划. +* 作为**个人用户空间** ,所有项目都将具有应用了订阅的功能,但是由于它不是一个组,因此将无法使用组功能. + +### Choosing the number of users[](#choosing-the-number-of-users "Permalink") + +订阅中的计数对象之间有一些不同,具体取决于您使用的是 GitLab.com 还是自我管理的实例. + +#### GitLab.com[](#gitlabcom "Permalink") + +GitLab.com 订阅使用并发( *座位* )模型. 您需要根据一次启用的最大用户数来支付订阅费用. 您可以在订阅期间添加和删除用户,只要在任何给定时间的总用户数都在订阅数之内即可. + +预订中将计算每个已占用的席位,无论是按人员,职位还是漫游器,但以下情况除外: + +* 具有金牌订阅的访客权限的成员. + +**提示:**为了支持开源社区并鼓励开发开源项目,GitLab 授予所有 GitLab.com **公共**项目访问**金牌**功能的权限,无论其订阅如何. + +#### Self-managed[](#self-managed "Permalink") + +自我管理的订阅使用混合模型. 您需要根据订阅期内启用的最大用户数来支付订阅费用. 对于非脱机或封闭网络上的实例,每季度使用[Seat Link](#seat-link)检查一次自我管理安装中的最大同时用户数. + +预订中将计算每个已占用的席位,无论是按人员,工作还是漫游方式,但以下情况除外: + +* 在订阅续订之前受到限制的[停用](../user/admin_area/activating_deactivating_users.html#deactivating-a-user)和[阻止的](../user/admin_area/blocking_unblocking_users.html)用户不会被视为续订订阅的活动用户. 在最初添加他们的订阅期内,他们可以算作活动用户. +* 具有 Ultimate 订阅的 Guest 权限的成员. +* GitLab 创建的服务帐户: `Ghost User`和`Support Bot` . + +##### Users statistics[](#users-statistics "Permalink") + +要查看实例中用户的细分,包括活动,计费和已阻止,请转至**管理区域>概述>仪表板,**然后在" **用户"**部分中选择" **用户统计信息** ". 有关更多详细信息,请参阅[用户统计信息](../user/admin_area/index.html#users-statistics) . + +**注意:**如果启用了 LDAP 集成,则配置域中的任何人都可以注册一个 GitLab 帐户. 续订时可能会导致意外的账单. 考虑[禁用新注册](../user/admin_area/settings/sign_up_restrictions.html)并改为手动管理新用户. + +## Obtain a GitLab subscription[](#obtain-a-gitlab-subscription "Permalink") + +### Subscribe to GitLab.com[](#subscribe-to-gitlabcom "Permalink") + +订阅 GitLab.com: + +1. 使用我们的[注册页面](https://gitlab.com/users/sign_in#register-pane)为您自己创建一个用户帐户. +2. 创建一个[组](../user/group/index.html) . GitLab 组帮助将相关项目组合在一起,使您可以一次授予成员访问多个项目的权限. 如果您计划在个人名称空间中包含项目,则不需要组. +3. 创建其他用户并将其[添加到组中](../user/group/index.html#add-users-to-a-group) . +4. 通过[客户门户](https://customers.gitlab.com/)选择**青铜** , **银**或**金** GitLab.com 计划. +5. 将您的 GitLab.com 帐户与客户门户帐户关联. 选择计划后,如果尚未链接您的帐户,系统将提示您使用" **登录到 GitLab.com"**按钮来链接您的帐户. +6. 从下拉列表中选择名称空间以关联预订. +7. 进行结算. + +**提示:**您也可以转到" [**我的帐户"**](https://customers.gitlab.com/customers/edit)页面来添加或更改 GitLab.com 帐户链接. + +### Subscribe through GitLab self-managed[](#subscribe-through-gitlab-self-managed "Permalink") + +要通过自我管理安装订阅 GitLab: + +1. 转到[客户门户](https://customers.gitlab.com/)并购买**Starter** , **Premium**或**Ultimate**自我管理计划. +2. 购买后,许可证文件将发送到与客户门户帐户关联的电子邮件地址,该电子邮件地址必须[上传到您的 GitLab 实例](../user/admin_area/license.html#uploading-your-license) . + +**提示:**如果您要购买现有**Core**自管实例的订阅,请确保购买的席位足以[覆盖您的用户](../user/admin_area/index.html#administering-users) . + +## Manage your GitLab account[](#manage-your-gitlab-account "Permalink") + +使用[客户门户,](https://customers.gitlab.com/)您可以: + +* [Change billing and company information](#change-billing-information) +* [Change the payment method](#change-payment-method) +* [Change the linked account](#change-the-linked-account) +* [Change the associated namespace](#change-the-associated-namespace) +* [Change customers portal account password](#change-customer-portal-account-password) + +### Change billing information[](#change-billing-information "Permalink") + +要更改帐单信息: + +1. 登录到[客户门户](https://customers.gitlab.com/customers/sign_in) . +2. 选择**我的帐户**下拉菜单,然后点击**付款方式** . +3. 对" **帐户详细**信息"进行必要的更改. +4. Click **保存更改**. + +**注意:**将来的购买将使用此部分中的信息. 本节中列出的电子邮件用于客户门户登录以及与许可证相关的电子邮件通信. + +### Change payment method[](#change-payment-method "Permalink") + +要更改付款方式或更新信用卡信息: + +1. 登录到[客户门户](https://customers.gitlab.com/customers/sign_in) . +2. 选择**我的帐户**下拉菜单,然后点击**付款方式** . +3. **编辑**现有的付款方式信息或**添加新的付款方式** . +4. 保存更改. + +### Change the linked account[](#change-the-linked-account "Permalink") + +要更改与您的客户门户帐户关联的 GitLab.com 帐户: + +1. 登录到[客户门户](https://customers.gitlab.com/customers/sign_in) . +2. 在单独的浏览器选项卡中,转到[GitLab.com,](https://gitlab.com)并确保您尚未登录. +3. 在"客户门户"页面上,单击**我的帐户>帐户详细信息** . +4. 在**您的 GitLab.com 帐户下** ,单击" **更改关联的帐户"** . +5. 登录到要链接到"客户门户"帐户的[GitLab.com](https://gitlab.com)帐户. + +### Change the associated namespace[](#change-the-associated-namespace "Permalink") + +使用关联的 GitLab.com 帐户: + +1. 登录到[客户门户](https://customers.gitlab.com/customers/sign_in) . +2. 导航到" **管理购买"**页面. +3. Click **更改链接的名称空间**. +4. 从" **此订阅用于"**下拉列表中选择所需的组. +5. Click **进行结算**. + +订阅费用是根据一个组中的用户总数(包括其子组和嵌套项目)来计算的. 如果用户总数超过了订阅中的席位数,则将向您收取额外的用户费用. + +### Change customer portal account password[](#change-customer-portal-account-password "Permalink") + +要更改此客户门户帐户的密码: + +1. 登录到[客户门户](https://customers.gitlab.com/customers/sign_in) . +2. 选择**我的帐户**下拉菜单,然后点击**帐户详细信息** . +3. 对**您的密码**部分进行必要的更改. +4. Click **保存更改**. + +## View your subscription[](#view-your-subscription "Permalink") + +### View your GitLab.com subscription[](#view-your-gitlabcom-subscription "Permalink") + +要查看您的 GitLab.com 订阅状态,请登录 GitLab.com 并转到相关名称空间的**Billing**部分: + +* 对于个人: + 1. 转到**用户头像>设置** . + 2. 点击**结算** . +* 对于团体: + 1. 在群组页面( *而不是*群组中的项目)中,转到**设置>结算** . + +下表描述了您的组订阅详细信息: + +| Field | Description | +| --- | --- | +| 订阅席 | 如果这是付费计划,则表示您已支付支持该组座位的数量. | +| 当前使用的座椅 | 当前正在使用的活动座位数. | +| 最多使用的座位 | 您使用过的最高座位数. 如果这超出了订阅的席位,则您可能欠其他用户额外的费用. | +| 欠座位 | 如果您使用的最大席位超出了订阅中的席位,您将为已添加的用户欠额外的费用. | +| 订阅开始日期 | 订阅开始的日期. 如果这是免费计划,则是您从组的付费计划过渡的日期. | +| 订阅结束日期 | 当前订阅的终止日期. 不适用于免费计划. | + +### View your self-managed subscription[](#view-your-self-managed-subscription "Permalink") + +要查看您的自我管理订阅的状态,请登录到自我管理实例,然后转到" **许可证"**页面. + +1. 去 **管理区** . +2. 从左侧菜单中选择**许可证** . + +## Renew your subscription[](#renew-your-subscription "Permalink") + +要续订您的订阅,请[通过查看您的帐户来准备续订](#prepare-for-renewal-by-reviewing-your-account) ,然后执行以下一项操作: + +* [Renew a GitLab.com subscription](#renew-or-change-a-gitlabcom-subscription). +* [Renew a self-managed subscription](#renew-a-self-managed-subscription). + +### Prepare for renewal by reviewing your account[](#prepare-for-renewal-by-reviewing-your-account "Permalink") + +[客户门户](https://customers.gitlab.com/customers/sign_in)是您续订和修改订阅的工具. 在进行续订之前,请登录并验证或更新: + +* **帐户详细信息**页面上的发票联系方式. +* 在" **付款方式"**页面上存档的信用卡. + +**提示:**如果您需要访问客户门户的帮助或需要更改管理您的订阅的联系人,请与我们的[支持团队](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293)联系. + +定期检查您的用户帐户很重要,因为: + +* GitLab 订阅基于用户数量. 如果为太多的用户续订,则您将支付比应支付的更多的费用,而如果您尝试为太少的用户续订订阅,则续订将失败. +* 过时的用户帐户可能会带来安全风险. 定期检查有助于降低这种风险. + +#### Users over License[](#users-over-license "Permalink") + +GitLab 订阅对特定数量的用户有效. 有关详细信息,请参阅[选择用户数](#choosing-the-number-of-users) . 如果活动用户数超过了订阅中包含的数量,即*超过许可证*的*用户*数,则必须在续订之前或续订时为超出的用户数付费. 这也称为*真正的升级*过程. + +##### Purchase additional seats for GitLab.com[](#purchase-additional-seats-for-gitlabcom "Permalink") + +没有自助服务选项可以购买额外的座位. 您必须从 GitLab 销售处索取报价. 为此,请通过我们的[支持表格](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293)联系 GitLab. + +每个座位收取的费用是通过以下方法之一计算的: + +* 如果在续订前付费,则每个座位的数量将按比例计算. 例如,如果在订阅期结束前 3 个月添加了用户,则应付款额的计算方式为:(3/12)x 年费. +* 如果在续签时支付,则每个席位的金额为标准年费. + +##### Purchase additional users for self-managed[](#purchase-additional-users-for-self-managed "Permalink") + +自我管理实例可以在订阅期间的任何时间将用户添加到订阅中. 订阅期内添加的其他用户的成本是从购买之日起到订阅期结束之间按比例分配的. + +要将用户添加到订阅中: + +1. 登录到[客户门户](https://customers.gitlab.com/) . +2. 导航到" **管理购买"**页面. +3. 选择相关订阅卡上的**添加更多席位** . +4. 输入其他用户数. +5. Select **进行结算**. +6. 查看**订阅升级详细信息** . 系统会列出系统上所有用户的总价,以及您已支付的款项的信用额. 您只需要支付零钱. +7. Select **确认升级**. + +以下内容将通过电子邮件发送给您: + +* 付款收据. 您也可以在客户门户的" [**查看发票"**](https://customers.gitlab.com/receipts)下访问此信息. +* A new license. [Upload this license](../user/admin_area/license.html#uploading-your-license) to your instance to use it. + +### Seat Link[](#seat-link "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208832) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.9. + +利用 Seat Link,我们可以使用季度对帐流程为自助客户提供按比例分配的费用,用于全年增加用户. + +Seat Link 每天将连接的自我管理实例中的所有用户计数发送到 GitLab. 该信息用于自动按比例分配对帐. 数据通过加密的 HTTPS 连接安全地发送. + +Seat Link **仅**向 GitLab 提供以下信息: + +* Date +* License key +* 历史最大用户数 +* 活动用户数 + +对于离线或封闭网络客户,将使用现有[的调整模型](#users-over-license) . 如果没有用户计数数据,则无法按比例收取费用. + +<details><summary title="Click here to view example content of a Seat Link POST request.">单击此处查看 Seat Link POST 请求的示例内容.</summary> + +``` + { + date: '2020-01-29', + license_key: 'ZXlKa1lYUmhJam9pWm5WNmVsTjVZekZ2YTJoV2NucDBh +RXRxTTA5amQxcG1VMVZqDQpXR3RwZEc5SGIyMVhibmxuZDJ0NWFrNXJTVzVH +UzFCT1hHNVRiVFIyT0ZaUFlVSm1OV1ZGV0VObE1uVk4NCk4xY3ZkM1F4Y2to +MFFuVklXSFJvUWpSM01VdE9SVE5rYkVjclZrdDJORkpOTlhka01qaE5aalpj +YmxSMg0KWVd3MFNFTldTRmRtV1ZGSGRDOUhPR05oUVZvNUsxVnRXRUZIZFU1 +U1VqUm5aVFZGZUdwTWIxbDFZV1EyDQphV1JTY1V4c1ZYSjNPVGhrYVZ4dVlu +TkpWMHRJZUU5dmF6ZEJRVVkxTlVWdFUwMTNSMGRHWm5SNlJFcFYNClQyVkJl +VXc0UzA0NWFFb3ZlSFJrZW0xbVRqUlZabkZ4U1hWcWNXRnZYRzVaTm5GSmVW +UnJVR1JQYTJKdA0KU0ZZclRHTmFPRTVhZEVKMUt6UjRkSE15WkRCT1UyNWlS +MGRJZDFCdmRFWk5Za2h4Tm5sT1VsSktlVlYyDQpXRmhjYmxSeU4wRnRNMU5q +THpCVWFGTmpTMnh3UWpOWVkyc3pkbXBST1dnelZHY3hUV3hxVDIwdlZYRlQN +Ck9EWTJSVWx4WlVOT01EQXhVRlZ3ZGs1Rk0xeHVSVEJTTDFkMWJUQTVhV1ZK +WjBORFdWUktaRXNyVnpsTw0KTldkWWQwWTNZa05VWlZBMmRUVk9kVUpxT1hV +Mk5VdDFTUzk0TUU5V05XbFJhWGh0WEc1cVkyWnhaeTlXDQpTMEpyZWt0cmVY +bzBOVGhFVG1oU1oxSm5WRFprY0Uwck0wZEdhVUpEV1d4a1RXZFRjVU5tYTB0 +a2RteEQNCmNWTlFSbFpuWlZWY2JpdFVVbXhIV0d4MFRuUnRWbkJKTkhwSFJt +TnRaMGsyV0U1MFFUUXJWMUJVTWtOSA0KTVhKUWVGTkxPVTkzV1VsMlVUUldk +R3hNTWswNU1USlNjRnh1U1UxTGJTdHRRM1l5YTFWaWJtSlBTMkUxDQplRkpL +SzJSckszaG1hVXB1ZVRWT1UwdHZXV0ZOVG1WamMyVjRPV0pSUlZkUU9UUnpU +VWh2Wlc5cFhHNUgNClNtRkdVMDUyY1RGMWNGTnhVbU5JUkZkeGVWcHVRMnBh +VTBSUGR6VnRNVGhvWTFBM00zVkZlVzFOU0djMA0KY1ZFM1FWSlplSFZ5UzFS +aGIxTmNia3BSUFQxY2JpSXNJbxRsZVNJNkltZFhiVzFGVkRZNWNFWndiV2Rt +DQpNWEIyY21SbFFrdFNZamxaYURCdVVHcHhiRlV3Tm1WQ2JGSlFaSFJ3Y0Rs +cFMybGhSMnRPTkZOMWNVNU0NClVGeHVTa3N6TUUxcldVOTVWREl6WVVWdk5U +ZGhWM1ZvVjJkSFRtZFBZVXRJTkVGcE55dE1NRE5dWnpWeQ0KWlV0aWJsVk9T +RmRzVVROUGRHVXdWR3hEWEc1MWjWaEtRMGQ2YTAxWFpUZHJURTVET0doV00w +ODRWM0V2DQphV2M1YWs5cWFFWk9aR3BYTm1aVmJXNUNaazlXVUVRMWRrMXpj +bTFDV0V4dldtRmNibFpTTWpWU05VeFMNClEwTjRNMWxWCUtSVGEzTTJaV2xE +V0hKTFRGQmpURXRsZFVaQlNtRnJTbkpPZGtKdlUyUmlNVWxNWWpKaQ0KT0dw +c05YbE1kVnh1YzFWbk5VZDFhbU56ZUM5Tk16TXZUakZOVW05cVpsVTNObEo0 +TjJ4eVlVUkdkWEJtDQpkSHByYWpreVJrcG9UVlo0Y0hKSU9URndiV2RzVFdO +VlhHNXRhVmszTkV0SVEzcEpNMWRyZEVoRU4ydHINCmRIRnFRVTlCVUVVM1pV +SlRORE4xUjFaYVJGb3JlWGM5UFZ4dUlpd2lhWFlpt2lKV00yRnNVbk5RTjJk +Sg0KU1hNMGExaE9SVGR2V2pKQlBUMWNiaUo5DQo=', + max_historical_user_count: 10, + active_users: 6 +} +```</details> + +您可以在管理面板中查看确切的 JSON 有效负载. 要查看有效负载: + +1. 导航到" **管理区域">"设置">"度量和分析",**然后展开" **Seat Link"** . +2. Click **预览有效载荷**. + +#### Disable Seat Link[](#disable-seat-link "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212375) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.10. + +默认情况下,Seat Link 已启用. + +要禁用此功能,请转到 **在管理区域>设置>指标和配置文件中** ,取消选中" **启用座椅链接"**复选框>" **保存更改"** . + +要在 Omnibus GitLab 安装中禁用 Seat Link,并防止日后通过管理面板对其进行配置,请在[`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html)设置以下[`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html) : + +``` +gitlab_rails['seat_link_enabled'] = false +``` + +要在 GitLab 源代码安装中禁用 Seat Link,并防止日后通过管理面板对其进行配置,请在`gitlab.yml`进行以下设置: + +``` +production: &base + # ... + gitlab: + # ... + seat_link_enabled: false +``` + +### Renew or change a GitLab.com subscription[](#renew-or-change-a-gitlabcom-subscription "Permalink") + +要更新为更多的用户比你们 GitLab.com 系统目前正在积极,请联系我们通过销售团队`renewals@gitlab.com`寻求帮助,因为这不能在客户门户网站来完成. + +For details on upgrading your subscription tier, see [Upgrade your GitLab.com subscription tier](#upgrade-your-gitlabcom-subscription-tier). + +#### Automatic renewal[](#automatic-renewal "Permalink") + +要查看或更改自动订阅续订(与上一周期位于同一层),请登录到[客户门户](https://customers.gitlab.com/customers/sign_in) ,然后: + +* 如果您看到" **恢复订阅"**按钮,则您的订阅先前已被取消. 单击它可以恢复自动续订. +* 如果看到" **取消订阅"** ,则您的订阅将设置为在订阅期结束时自动续订. 单击它可以取消自动续订. + +启用自动续订后,订阅将在到期日期自动续订,并且可用服务之间不会有任何差距. 将会生成一张用于续订的发票,并且可以在" [查看发票"](https://customers.gitlab.com/receipts)页面中查看或下载. 如果您在续订过程中遇到困难,请联系我们的[支持团队](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293)以寻求帮助. + +### Renew a self-managed subscription[](#renew-a-self-managed-subscription "Permalink") + +从订阅到期前 30 天开始,GitLab 会在 GitLab 用户界面中用标语通知管理员到期日期. + +我们建议您在续订期间执行以下步骤: + +1. 通过[阻止](../user/admin_area/blocking_unblocking_users.html#blocking-a-user)任何不活跃或不需要的用户来修剪[它们](../user/admin_area/blocking_unblocking_users.html#blocking-a-user) . +2. 确定在即将到来的订阅中是否需要增加用户. +3. 登录到[客户门户,](https://customers.gitlab.com/customers/sign_in)然后选择现有订阅下的" **续订"**按钮. + + **提示:**如果您需要更改您的[GitLab 层](https://about.gitlab.com/pricing/) ,请通过`renewals@gitlab.com`与我们的销售团队联系以寻求帮助,因为这不能在客户门户中完成. +4. 在第一个框中,输入来年需要的用户许可总数. 确保此数目至少**等于或大于**执行更新时系统中的活动用户数. +5. 在第二个框中,输入上一个订购期限内发生的用户超额[使用的许可证超用户](#users-over-license)数. + + **提示:**您可以*通过以下方式*在实例的**管理**控制台中找到获得*许可*的*用户* **:** (顶部)中的( **管理区域** ),或转到`/admin` . + + 下表介绍了管理控制台和续订条款的详细信息: + + | Field | Description | + | --- | --- | + | 许可中的用户 | 您在系统上加载的当前许可证中已付费的用户数. 这不包括您在续订期间`Users over license`向`Users over license`支付的金额. | + | 活跃用户 | 系统上当前的活动用户数. | + | 最大用户 | 在已加载许可证有效期内,系统上活动用户数最多. 如果此数字在任何时候都超出了许可数量的用户,则会使用户蒙受许可数量的困扰. | + | 超过许可的用户 | 在当前许可期限内,超出`Users in License`用户数量的用户数量. 此数量的用户将在下次续订时付费. | + +6. 查看您的续订详细信息并完成付款过程. +7. 可以在相关订阅卡上的" [管理购买"](https://customers.gitlab.com/subscriptions)页面上下载续订期限的许可证. 选择**将许可证复制到剪贴板**或选择**下载许可证**以获取副本. +8. 将新许可证[上载到](../user/admin_area/license.html#uploading-your-license)您的实例. + +将会生成一张用于续订的发票,并且可以在" [查看发票"](https://customers.gitlab.com/receipts)页面上查看或下载. 如果您在续订过程中遇到困难,请联系我们的[支持团队](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293)以寻求帮助. + +## Upgrade your subscription tier[](#upgrade-your-subscription-tier "Permalink") + +升级过程因您是 GitLab.com 还是自我管理的客户而异. + +### Upgrade your GitLab.com subscription tier[](#upgrade-your-gitlabcom-subscription-tier "Permalink") + +要升级您的[GitLab 层](https://about.gitlab.com/pricing/) : + +1. 登录到[客户门户](https://customers.gitlab.com/customers/sign_in) . +2. 在" [管理购买"](https://customers.gitlab.com/subscriptions)页面上,选择相关订阅卡上的" **升级"**按钮. +3. 选择所需的升级. +4. 确认有效的付款方式,或添加新的付款方式. +5. 选中**我接受隐私政策和服务条款**复选框. +6. Select **确认购买**. + +处理完购买后,您将收到新订阅等级的确认. + +### Upgrade your self-managed subscription tier[](#upgrade-your-self-managed-subscription-tier "Permalink") + +要升级您的[GitLab 层](https://about.gitlab.com/pricing/) ,请联系我们的销售团队,因为这不能在客户门户中完成. 您可以发送电子邮件至`renewals@gitlab.com`或填写" [**联系销售"**](https://about.gitlab.com/sales/)表单. 在消息中包括要升级的订阅的详细信息以及所需的层. + +After messaging the sales team, the workflow is as follows: + +1. 收到销售团队的答复,要求确认升级. +2. 回复销售团队,确认升级细节. +3. 收到销售团队的报价. +4. 签名并返回报价. +5. 收到新许可证. +6. 上载新许可证. 有关详细信息,请参阅上[载许可证](../user/admin_area/license.html#uploading-your-license) . + +上载许可证文件后,新的订阅层将处于活动状态. + +## Subscription expiry[](#subscription-expiry "Permalink") + +当您的订阅或试用版到期时,GitLab 不会删除您的数据,但是根据到期时的层级,它可能变得不可访问. 如果您没有准备好到期,则某些功能可能无法达到预期的效果. 例如, [未传递特定](https://gitlab.com/gitlab-org/gitlab/-/issues/24759)于[环境的变量](https://gitlab.com/gitlab-org/gitlab/-/issues/24759) . + +如果您续订或升级,您的数据将再次可访问. + +### Self-managed GitLab data[](#self-managed-gitlab-data "Permalink") + +对于自我管理的客户,有 14 天的宽限期,您的功能将继续按原样运行,此后整个实例将变为只读状态. + +但是,如果删除许可证,您将立即恢复为核心功能,并且实例将再次被读取/写入. + +## CI pipeline minutes[](#ci-pipeline-minutes "Permalink") + +CI 管道分钟数是您在 GitLab 共享运行程序上的[管道](../ci/pipelines/index.html)的执行时间. 每个[GitLab.com 层均](https://about.gitlab.com/pricing/)包含 CI 管道分钟的每月配额: + +* 免费:2,000 分钟 +* 青铜:2,000 分钟 +* Silver: 10,000 minutes +* 金牌:50,000 分钟 + +配额适用于: + +* 组,其中在组的所有成员,其子组和嵌套项目之间共享分钟. 要查看该组的使用情况,请导航至该组,然后 **设置** > **使用配额** . +* 您的个人帐户,其中可用于您的个人项目的纪要. 要查看和购买个人会议记录,请点击您的头像,然后 **设置** > **[使用配额](https://gitlab.com/profile/usage_quotas#pipelines-quota-tab)** . + +只有 GitLab 共享运行程序的管道时间受到限制. 如果您为项目设置了特定的运行器,则在 GitLab.com 上的构建时间没有限制. + +可用配额在每个日历月的第一个 UTC 午夜重置. + +CI 分钟数用完后,会自动发送一封电子邮件以通知名称空间的所有者. 您可以[购买其他 CI 分钟](#purchasing-additional-ci-minutes) ,或者将帐户升级为[Silver 或 Gold](https://about.gitlab.com/pricing/) . 即使您达到极限,仍然可以使用您自己的跑步者. + +### Purchasing additional CI minutes[](#purchasing-additional-ci-minutes "Permalink") + +如果您使用的是 GitLab.com,则可以购买额外的 CI 分钟,这样在使用完您的主要配额中的所有 CI 分钟后,管道不会被阻塞. 您可以在[GitLab 客户门户中](https://customers.gitlab.com/plans)找到其他 CI / CD 分钟的价格. 其他分钟: + +* 仅在订阅中包含的共享配额用完后才使用. +* 逐月滚动. + +要在 GitLab.com 上为您的小组购买更多时间: + +1. 在您的小组中,转到 **设置>使用配额** . +2. 选择**购买其他分钟** ,您将被带到客户门户. +3. 在 GitLab.com 上找到与您的小组链接的订阅卡,单击" **购买更多 CI 分钟"** ,然后完成有关交易的详细信息. +4. 处理完您的付款后,多余的 CI 分钟将同步到您的组名称空间. +5. 要确认可用的 CI 分钟,请转到您的小组,然后 **设置>使用配额** . + + The **额外的分钟** displayed now includes the purchased additional CI minutes, plus any minutes rolled over from last month. + +要为您的个人命名空间购买更多分钟,请执行以下操作: + +1. 单击您的头像,然后转到**设置>使用配额** . +2. 选择**购买其他分钟** ,您将被带到客户门户. +3. 在 GitLab.com 上找到链接到您的个人命名空间的订阅卡,单击" **购买更多 CI 分钟"** ,然后完成有关交易的详细信息. 我们处理完您的付款后,多余的 CI 分钟将同步到您的个人名称空间. +4. 要确认您的个人项目可用的 CI 分钟,请单击您的头像,然后转到**设置>使用配额** . + + 现在显示的" **其他分钟"**包括已购买的其他配置项分钟,以及上个月结转的所有分钟. + +意识到: + +* 如果您在购买付费计划之前购买了额外的 CI 分钟数,我们将为您的付费计划按比例计算费用. 这意味着您可能需要不到一年的费用,因为您之前是使用额外的 CI 分钟创建订阅的. +* 一旦将额外的 CI 分钟分配给一个组,就无法将其转移到另一个组. +* 如果您使用的分钟数超出了默认配额,则这些分钟数将在您购买额外的分钟数后立即从"其他分钟数"配额中扣除. + +## Contact Support[](#contact-support "Permalink") + +我们还鼓励所有用户在项目跟踪器中搜索[GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/)项目中的已知问题和现有功能要求. + +这些问题是获取特定产品计划的更新以及直接与相关 GitLab 团队成员进行沟通的最佳途径. + +学习更多关于: + +* [GitLab 支持](https://about.gitlab.com/support/)的层次. +* [Submit a request via the Support Portal](https://support.gitlab.com/hc/en-us/requests/new). + +## GitLab for Education subscriptions[](#gitlab-for-education-subscriptions "Permalink") + +要续订[GitLab for Education](https://about.gitlab.com/solutions/education/)订阅,请发送电子邮件至`education@gitlab.com`其中包含以下信息: + +1. 续订的座位数. 您可以根据需要添加座位. +2. 许可证的用例. 具体来说,我们需要验证其使用是否符合《 [最终用户许可协议》](https://about.gitlab.com/terms/#edu-oss)的条件. 请注意,大学的基础设施运营和信息技术运营不在教育计划的规定范围之内. 有关详细信息,请参见" [教育常见问题解答"](https://about.gitlab.com/solutions/education/#FAQ) . +3. 要签署续订报价的主要联系人的全名,电子邮件地址和电话号码. 只有代表大学的具有适当签署权的教职员工签署才能被接受. + +收到上述信息后,我们将处理请求并返回续签以供签名. 请至少等待 2 个工作日才能退货. 如有任何问题,请发送电子邮件至`education@gitlab.com` . + +## GitLab for Open Source subscriptions[](#gitlab-for-open-source-subscriptions "Permalink") + +所有的[GitLab for Open Source](https://about.gitlab.com/solutions/open-source/program/)请求(包括订阅续订)都必须通过应用程序进行. 如有任何疑问,请发送电子邮件至`opensource@gitlab.com`寻求帮助. \ No newline at end of file diff --git a/_book/docs/652.md b/_book/docs/652.md new file mode 100644 index 0000000000000000000000000000000000000000..f8ffc762fbdb32f0cdb0908fbb58326cb1648dcc --- /dev/null +++ b/_book/docs/652.md @@ -0,0 +1,94 @@ +# Activate GitLab EE with a license + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/license.html](https://docs.gitlab.com/ee/user/admin_area/license.html) + +* [Uploading your license](#uploading-your-license) +* [Add your license at install time](#add-your-license-at-install-time) +* [Notification before the license expires](#notification-before-the-license-expires) +* [What happens when your license expires](#what-happens-when-your-license-expires) +* [License history](#license-history) +* [Troubleshooting](#troubleshooting) + * [There is no License tab in the Admin Area](#there-is-no-license-tab-in-the-admin-area) + * [Users exceed license limit upon renewal](#users-exceed-license-limit-upon-renewal) + +# Activate GitLab EE with a license[](#activate-gitlab-ee-with-a-license-starter-only "Permalink") + +要激活所有 GitLab 企业版(EE)功能,您需要上传许可证. 从 GitLab Inc.获得许可证后,您可以通过**以管理员身份登录到 GitLab 实例**或在安装时添加许可证来上载许可证. + +许可证的形式为 base64 编码的 ASCII 文本,扩展名为`.gitlab-license` ,可以在[购买](https://about.gitlab.com/pricing/) `.gitlab-license`或注册[免费试用时获得](https://about.gitlab.com/free-trial/) . + +**注意:**从 GitLab Enterprise Edition 9.4.0 开始,没有上载许可证的新安装实例将仅具有核心功能. 试用许可证将激活所有 Ultimate 功能,但是[试用期满后](#what-happens-when-your-license-expires) ,某些功能将被锁定. + +## Uploading your license[](#uploading-your-license "Permalink") + +首次访问以 admin 身份登录的 GitLab EE 安装时,您会看到一条注释,敦促您上传许可证,并带有一个链接,该链接可直接转到**Admin Area> License** . + +否则,您可以: + +1. 通过单击菜单栏中的扳手图标,手动导航到**管理区域** . + + [![Admin Area icon](img/53056397d59c4378696296d359f20adc.png)](img/admin_wrench.png) + +2. 然后转到" **许可证"**选项卡,然后单击"上**载新许可证"** . + + [![License Admin Area](img/b132b9b00d4641da41d2cb7dca5ea55c.png)](img/license_admin_area.png) + +3. 如果您收到`.gitlab-license`文件,则应该已经将其下载到本地计算机中. 然后,您可以通过选择许可证文件并单击"上**载许可证"**按钮直接上载它. 在下图中,您可以看到所选的许可证文件名为`GitLab.gitlab-license` . + + [![Upload license](img/5016b6014148674f85d6fdba7bc5bb5e.png)](img/license_upload.png) + + 如果您以纯文本格式收到许可证,则需要选择"输入许可证密钥"选项,复制许可证,将其粘贴到"许可证密钥"字段中,然后点击**上传许可证** . + +## Add your license at install time[](#add-your-license-at-install-time "Permalink") + +通过将名为`Gitlab.gitlab-license`的文件放置在`/etc/gitlab/`对于 Omnibus)或`config/`对于源代码安装,可以在安装时自动导入`Gitlab.gitlab-license` . + +还可以为许可证指定自定义位置和文件名. + +源代码安装应使用有效的 GitLab Enterprise Edition 许可证的路径设置`GITLAB_LICENSE_FILE`环境变量. + +``` +export GITLAB_LICENSE_FILE="/path/to/license/file" +``` + +Omnibus 安装应将此条目添加到`gitlab.rb` : + +``` +gitlab_rails['initial_license_file'] = "/path/to/license/file" +``` + +**警告:**这些方法只会在安装时添加许可证. 使用 Web 用户界面中的"管理区域"来续订或升级许可证. + +* * * + +许可证上载后,所有 GitLab 企业版功能都将处于激活状态,直到许可证期结束. 该时间段结束后,该实例将[恢复](#what-happens-when-your-license-expires)为仅 Core 功能. + +您可以随时在"管理区域"的"许可证"部分中查看许可证详细信息. + +[![License details](img/181ef05617eae83f93df5db5884cb3f2.png)](img/license_details.png) + +## Notification before the license expires[](#notification-before-the-license-expires "Permalink") + +许可证到期前一个月,GitLab 管理员将开始看到一条消息,通知到期时间. 确保您更新了许可证,否则,如果许可证过期,您将错过所有付费功能. + +## What happens when your license expires[](#what-happens-when-your-license-expires "Permalink") + +万一您的许可证过期,GitLab 将锁定某些功能,如 Git 推送,问题创建等,并且将向所有管理员显示一条消息,告知已过期的许可证. + +为了恢复所有以前的功能,必须上载新的许可证. 要退回到仅激活核心功能,您需要删除过期的许可证. + +## License history[](#license-history "Permalink") + +可以上传和查看多个许可证,但是只有最新的许可证将用作活动许可证. + +## Troubleshooting[](#troubleshooting "Permalink") + +### There is no License tab in the Admin Area[](#there-is-no-license-tab-in-the-admin-area "Permalink") + +如果您最初安装的是 Community Edition,而不是 Enterprise Edition,则需要在[升级](../../update/README.html#community-to-enterprise-edition)许可证之前[升级到 Enterprise Edition](../../update/README.html#community-to-enterprise-edition) . + +GitLab.com 用户无法上传和使用自我管理的许可证. 如果您希望在 GitLab.com 上使用付费功能,则可以[购买](../../subscriptions/index.html#subscribe-to-gitlabcom)单独的订阅. + +### Users exceed license limit upon renewal[](#users-exceed-license-limit-upon-renewal "Permalink") + +如果您在续订之前将新用户添加到您的 GitLab 实例中,则可能需要购买额外的席位来覆盖这些用户. 如果是这种情况,并且上传了没有足够用户的许可证,则会显示一条消息,提示您购买其他用户. 有关如何确定所需用户数以及如何增加其他席位的更多信息,请参见[许可常见问题解答](https://about.gitlab.com/pricing/licensing-faq/) . \ No newline at end of file diff --git a/_book/docs/img/000b14e609fee563642c55e238caca88.png b/_book/docs/img/000b14e609fee563642c55e238caca88.png new file mode 100644 index 0000000000000000000000000000000000000000..eb0619b840ef4c96a97694d61aab9a24a6c66b94 Binary files /dev/null and b/_book/docs/img/000b14e609fee563642c55e238caca88.png differ diff --git a/_book/docs/img/0050abd936ad2e13e4ad057a58611cc9.png b/_book/docs/img/0050abd936ad2e13e4ad057a58611cc9.png new file mode 100644 index 0000000000000000000000000000000000000000..8aa3192eb970101327c88261485c7e0ab500cfa4 Binary files /dev/null and b/_book/docs/img/0050abd936ad2e13e4ad057a58611cc9.png differ diff --git a/_book/docs/img/00cb101eb824b3ede4fa4a3914f95c09.png b/_book/docs/img/00cb101eb824b3ede4fa4a3914f95c09.png new file mode 100644 index 0000000000000000000000000000000000000000..3b615b594ea3c5989cdc8c2549307c7ff0b2f0c4 Binary files /dev/null and b/_book/docs/img/00cb101eb824b3ede4fa4a3914f95c09.png differ diff --git a/_book/docs/img/00fd9bca0c7bdc64f74a24b691e0adac.png b/_book/docs/img/00fd9bca0c7bdc64f74a24b691e0adac.png new file mode 100644 index 0000000000000000000000000000000000000000..671fd2253d279d0066dd200e796d978e12d48404 Binary files /dev/null and b/_book/docs/img/00fd9bca0c7bdc64f74a24b691e0adac.png differ diff --git a/_book/docs/img/0124687ca256ab68d34dd0918f1e1a8d.png b/_book/docs/img/0124687ca256ab68d34dd0918f1e1a8d.png new file mode 100644 index 0000000000000000000000000000000000000000..a2b9e2e90e75255644735b39b53d64e9b9832b78 Binary files /dev/null and b/_book/docs/img/0124687ca256ab68d34dd0918f1e1a8d.png differ diff --git a/_book/docs/img/01df5698e4465e052dcb7bf0ed6a55ae.png b/_book/docs/img/01df5698e4465e052dcb7bf0ed6a55ae.png new file mode 100644 index 0000000000000000000000000000000000000000..4c0b8147f57afc20a71af50a744be26a5cb2a3f1 Binary files /dev/null and b/_book/docs/img/01df5698e4465e052dcb7bf0ed6a55ae.png differ diff --git a/_book/docs/img/0290c1013dba1b07f226f1548c8b6fd2.png b/_book/docs/img/0290c1013dba1b07f226f1548c8b6fd2.png new file mode 100644 index 0000000000000000000000000000000000000000..cf225c91f8dadecabf811f0a08899d8538f7a2fb Binary files /dev/null and b/_book/docs/img/0290c1013dba1b07f226f1548c8b6fd2.png differ diff --git a/_book/docs/img/02f288cad0ff70d293c035d6dc434f34.png b/_book/docs/img/02f288cad0ff70d293c035d6dc434f34.png new file mode 100644 index 0000000000000000000000000000000000000000..1ff3bd975bbebd5cabbd076a3734244e6e1b34dc Binary files /dev/null and b/_book/docs/img/02f288cad0ff70d293c035d6dc434f34.png differ diff --git a/_book/docs/img/033c41dc1122d52872dcb67228037524.png b/_book/docs/img/033c41dc1122d52872dcb67228037524.png new file mode 100644 index 0000000000000000000000000000000000000000..f9ea1c7fd1d0d29bd493a4ef0dd1ef5e036834d0 Binary files /dev/null and b/_book/docs/img/033c41dc1122d52872dcb67228037524.png differ diff --git a/_book/docs/img/0370f6d6a289b9e8237fcad4c7672e78.png b/_book/docs/img/0370f6d6a289b9e8237fcad4c7672e78.png new file mode 100644 index 0000000000000000000000000000000000000000..eb6ec77e1f8ec80a6939577ebd7d29b7826c46ef Binary files /dev/null and b/_book/docs/img/0370f6d6a289b9e8237fcad4c7672e78.png differ diff --git a/_book/docs/img/0387751ed4b8717777ebac2706c2d637.png b/_book/docs/img/0387751ed4b8717777ebac2706c2d637.png new file mode 100644 index 0000000000000000000000000000000000000000..387b5ccd7cb45a388c9c6007fe72d3e2cbc62b9b Binary files /dev/null and b/_book/docs/img/0387751ed4b8717777ebac2706c2d637.png differ diff --git a/_book/docs/img/03d3f984ea7608322b1fd6a7feba47c0.png b/_book/docs/img/03d3f984ea7608322b1fd6a7feba47c0.png new file mode 100644 index 0000000000000000000000000000000000000000..d8e269f86f9fe046ac92b0b8fa19344cd6657a14 Binary files /dev/null and b/_book/docs/img/03d3f984ea7608322b1fd6a7feba47c0.png differ diff --git a/_book/docs/img/04b61606f38fddf21d194ee3e13abaa3.png b/_book/docs/img/04b61606f38fddf21d194ee3e13abaa3.png new file mode 100644 index 0000000000000000000000000000000000000000..40d57044d43a2d03d10436bd382f7d3c60458011 Binary files /dev/null and b/_book/docs/img/04b61606f38fddf21d194ee3e13abaa3.png differ diff --git a/_book/docs/img/0574a3e535157d8b9c5744214f19f7c7.png b/_book/docs/img/0574a3e535157d8b9c5744214f19f7c7.png new file mode 100644 index 0000000000000000000000000000000000000000..3076cd6edff029ff05a588c6307fcf7dccf32ef6 Binary files /dev/null and b/_book/docs/img/0574a3e535157d8b9c5744214f19f7c7.png differ diff --git a/_book/docs/img/05a0790512923394006a9c3face18d58.png b/_book/docs/img/05a0790512923394006a9c3face18d58.png new file mode 100644 index 0000000000000000000000000000000000000000..6f78ff359e0b87c9e40227a27802d5297b130f17 Binary files /dev/null and b/_book/docs/img/05a0790512923394006a9c3face18d58.png differ diff --git a/_book/docs/img/05dd8439c1da77198297616b4c4f8458.png b/_book/docs/img/05dd8439c1da77198297616b4c4f8458.png new file mode 100644 index 0000000000000000000000000000000000000000..5f482eecab97853a4776bef0e22dc1e83bc15109 Binary files /dev/null and b/_book/docs/img/05dd8439c1da77198297616b4c4f8458.png differ diff --git a/_book/docs/img/061d5d0d60fdf019ad696860942563af.png b/_book/docs/img/061d5d0d60fdf019ad696860942563af.png new file mode 100644 index 0000000000000000000000000000000000000000..57004dd4f549a1f9c9cc0eabf182fc2d6f9b680b Binary files /dev/null and b/_book/docs/img/061d5d0d60fdf019ad696860942563af.png differ diff --git a/_book/docs/img/0748208b938145b0cf688cc0a3cb7b09.png b/_book/docs/img/0748208b938145b0cf688cc0a3cb7b09.png new file mode 100644 index 0000000000000000000000000000000000000000..951f7374352baa81221ae6948bb3113c5b35deb8 Binary files /dev/null and b/_book/docs/img/0748208b938145b0cf688cc0a3cb7b09.png differ diff --git a/_book/docs/img/074834195e0c24213cffeef5ef08a9e1.png b/_book/docs/img/074834195e0c24213cffeef5ef08a9e1.png new file mode 100644 index 0000000000000000000000000000000000000000..bdea937f04cc498136bc286848955e9187262bc1 Binary files /dev/null and b/_book/docs/img/074834195e0c24213cffeef5ef08a9e1.png differ diff --git a/_book/docs/img/079efbfe641967c936be8ed9b033bca6.png b/_book/docs/img/079efbfe641967c936be8ed9b033bca6.png new file mode 100644 index 0000000000000000000000000000000000000000..14355dca0e7cf644f0ae8856b02b5ce380406030 Binary files /dev/null and b/_book/docs/img/079efbfe641967c936be8ed9b033bca6.png differ diff --git a/_book/docs/img/07c2c84efb64460dfa2373f1f75645ab.png b/_book/docs/img/07c2c84efb64460dfa2373f1f75645ab.png new file mode 100644 index 0000000000000000000000000000000000000000..4669fb5e6d55b8e73ae251ade310fd97b38680ac Binary files /dev/null and b/_book/docs/img/07c2c84efb64460dfa2373f1f75645ab.png differ diff --git a/_book/docs/img/07e4663db45be7313a205a17ec342edb.png b/_book/docs/img/07e4663db45be7313a205a17ec342edb.png new file mode 100644 index 0000000000000000000000000000000000000000..7eacb23acc712246070a63ebe84855b3dc50518d Binary files /dev/null and b/_book/docs/img/07e4663db45be7313a205a17ec342edb.png differ diff --git a/_book/docs/img/083580c1827d40263d500a21f072249f.png b/_book/docs/img/083580c1827d40263d500a21f072249f.png new file mode 100644 index 0000000000000000000000000000000000000000..7b3732beafa2e2ccc2b37268ed85347281522b12 Binary files /dev/null and b/_book/docs/img/083580c1827d40263d500a21f072249f.png differ diff --git a/_book/docs/img/097706015c4d2abaaf34d0782cfac635.png b/_book/docs/img/097706015c4d2abaaf34d0782cfac635.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba581a1e2e99449a88cb74ff0932f7960b50f71 Binary files /dev/null and b/_book/docs/img/097706015c4d2abaaf34d0782cfac635.png differ diff --git a/_book/docs/img/09870a42c6e3e94e7553f338a65c0b6d.png b/_book/docs/img/09870a42c6e3e94e7553f338a65c0b6d.png new file mode 100644 index 0000000000000000000000000000000000000000..c07d64ddf91c0b2a4974b7eebc6c81094da588e9 Binary files /dev/null and b/_book/docs/img/09870a42c6e3e94e7553f338a65c0b6d.png differ diff --git a/_book/docs/img/098a5864447e44da06b72051af59b294.png b/_book/docs/img/098a5864447e44da06b72051af59b294.png new file mode 100644 index 0000000000000000000000000000000000000000..54b8c2fbf34179cf4833f51420025d9eaad9db3e Binary files /dev/null and b/_book/docs/img/098a5864447e44da06b72051af59b294.png differ diff --git a/_book/docs/img/0991c603daeaefcd2df14e098fa66ea4.png b/_book/docs/img/0991c603daeaefcd2df14e098fa66ea4.png new file mode 100644 index 0000000000000000000000000000000000000000..d63ddfb2a4f382e6b171102fb15ac08d057119fb Binary files /dev/null and b/_book/docs/img/0991c603daeaefcd2df14e098fa66ea4.png differ diff --git a/_book/docs/img/09a583a4343d2359d87040afc14139dd.png b/_book/docs/img/09a583a4343d2359d87040afc14139dd.png new file mode 100644 index 0000000000000000000000000000000000000000..315f78237a13916fa31b655b49513bb1652928cd Binary files /dev/null and b/_book/docs/img/09a583a4343d2359d87040afc14139dd.png differ diff --git a/_book/docs/img/09b8263a3534de004ff180005a876b4a.png b/_book/docs/img/09b8263a3534de004ff180005a876b4a.png new file mode 100644 index 0000000000000000000000000000000000000000..fe128cda6f868901ead87a8a4c6378c4ed02ea06 Binary files /dev/null and b/_book/docs/img/09b8263a3534de004ff180005a876b4a.png differ diff --git a/_book/docs/img/09e1824644c088dfbd0f2f9710fc7d77.png b/_book/docs/img/09e1824644c088dfbd0f2f9710fc7d77.png new file mode 100644 index 0000000000000000000000000000000000000000..dab477be4618b18f64f7cd791ec8b267a1bf96cc Binary files /dev/null and b/_book/docs/img/09e1824644c088dfbd0f2f9710fc7d77.png differ diff --git a/_book/docs/img/0a61445809db70ca6bf85d986bf52223.png b/_book/docs/img/0a61445809db70ca6bf85d986bf52223.png new file mode 100644 index 0000000000000000000000000000000000000000..9c9b3825ab9504a24f45f455efc109d3b7040c82 Binary files /dev/null and b/_book/docs/img/0a61445809db70ca6bf85d986bf52223.png differ diff --git a/_book/docs/img/0a64287e1feef55413a5a906d02ec8ea.png b/_book/docs/img/0a64287e1feef55413a5a906d02ec8ea.png new file mode 100644 index 0000000000000000000000000000000000000000..da392c83a18d9ba87bc57bd594f8eed28d043fe8 Binary files /dev/null and b/_book/docs/img/0a64287e1feef55413a5a906d02ec8ea.png differ diff --git a/_book/docs/img/0a8b584e09781bad1c374f8badc0a12c.png b/_book/docs/img/0a8b584e09781bad1c374f8badc0a12c.png new file mode 100644 index 0000000000000000000000000000000000000000..0d1e5c1379a16ee4d352551d25231bd565b8474b Binary files /dev/null and b/_book/docs/img/0a8b584e09781bad1c374f8badc0a12c.png differ diff --git a/_book/docs/img/0a8c15f1fa2c2e0a210d9baae9fff372.png b/_book/docs/img/0a8c15f1fa2c2e0a210d9baae9fff372.png new file mode 100644 index 0000000000000000000000000000000000000000..7defe270352f2e05eac7f1ae56844d1716ce96f5 Binary files /dev/null and b/_book/docs/img/0a8c15f1fa2c2e0a210d9baae9fff372.png differ diff --git a/_book/docs/img/0b5158f524983df0ee4e4aa152abcc86.png b/_book/docs/img/0b5158f524983df0ee4e4aa152abcc86.png new file mode 100644 index 0000000000000000000000000000000000000000..f69d7eef345c58ef9c0b5adf861080804e8b80b4 Binary files /dev/null and b/_book/docs/img/0b5158f524983df0ee4e4aa152abcc86.png differ diff --git a/_book/docs/img/0b804819bf30ce8e657ad538d376ecc5.png b/_book/docs/img/0b804819bf30ce8e657ad538d376ecc5.png new file mode 100644 index 0000000000000000000000000000000000000000..0f622411d6edba03c140ad4f44b5e77bc191882b Binary files /dev/null and b/_book/docs/img/0b804819bf30ce8e657ad538d376ecc5.png differ diff --git a/_book/docs/img/0bc8de7b7d20af897fb8b38bb48663e8.png b/_book/docs/img/0bc8de7b7d20af897fb8b38bb48663e8.png new file mode 100644 index 0000000000000000000000000000000000000000..771a355ce45e2afd0e659d0bd3f5bbaa997d55dd Binary files /dev/null and b/_book/docs/img/0bc8de7b7d20af897fb8b38bb48663e8.png differ diff --git a/_book/docs/img/0bef311ef1713ebb246577aeaaa012c3.png b/_book/docs/img/0bef311ef1713ebb246577aeaaa012c3.png new file mode 100644 index 0000000000000000000000000000000000000000..60e4557e72fd3f7ddb0a84a7b75a06bf75c632c1 Binary files /dev/null and b/_book/docs/img/0bef311ef1713ebb246577aeaaa012c3.png differ diff --git a/_book/docs/img/0c549416181d6e18eb1dd34825b00425.png b/_book/docs/img/0c549416181d6e18eb1dd34825b00425.png new file mode 100644 index 0000000000000000000000000000000000000000..ec29faa14b25ca9c5ebd23999f5cacc12a6d6703 Binary files /dev/null and b/_book/docs/img/0c549416181d6e18eb1dd34825b00425.png differ diff --git a/_book/docs/img/0d0a16295f0edf554f921ffda49ff421.png b/_book/docs/img/0d0a16295f0edf554f921ffda49ff421.png new file mode 100644 index 0000000000000000000000000000000000000000..7ba901418e8d6ff36c4fe312233bc5456273102f Binary files /dev/null and b/_book/docs/img/0d0a16295f0edf554f921ffda49ff421.png differ diff --git a/_book/docs/img/0d1089161431c5f21751458027d84535.png b/_book/docs/img/0d1089161431c5f21751458027d84535.png new file mode 100644 index 0000000000000000000000000000000000000000..456bb0c7e1080206bbda3246ea932a4d2bcd01f3 Binary files /dev/null and b/_book/docs/img/0d1089161431c5f21751458027d84535.png differ diff --git a/_book/docs/img/0d1c10a8d14f11dd831b96878fc521e5.png b/_book/docs/img/0d1c10a8d14f11dd831b96878fc521e5.png new file mode 100644 index 0000000000000000000000000000000000000000..0a1fa8576c8ebb34d2efeeabaed01b28dc739bf8 Binary files /dev/null and b/_book/docs/img/0d1c10a8d14f11dd831b96878fc521e5.png differ diff --git a/_book/docs/img/0d2f752f5d8c7352da5333f4f0d27835.png b/_book/docs/img/0d2f752f5d8c7352da5333f4f0d27835.png new file mode 100644 index 0000000000000000000000000000000000000000..b19f2962d169588765b9c2b174d17af169b7c1ee Binary files /dev/null and b/_book/docs/img/0d2f752f5d8c7352da5333f4f0d27835.png differ diff --git a/_book/docs/img/0d3f7491de96f0f5d1d30a594ec42739.png b/_book/docs/img/0d3f7491de96f0f5d1d30a594ec42739.png new file mode 100644 index 0000000000000000000000000000000000000000..abdd6188d46eb88edcdadb72f9695b76065f2a32 Binary files /dev/null and b/_book/docs/img/0d3f7491de96f0f5d1d30a594ec42739.png differ diff --git a/_book/docs/img/0d59f9135c1fed79a51921909516ef69.png b/_book/docs/img/0d59f9135c1fed79a51921909516ef69.png new file mode 100644 index 0000000000000000000000000000000000000000..554a2ae40ee928088d8fe9cfd667e8c21bac4a72 Binary files /dev/null and b/_book/docs/img/0d59f9135c1fed79a51921909516ef69.png differ diff --git a/_book/docs/img/0d6a90afbcbb1f9414d4a9a8437e49f8.png b/_book/docs/img/0d6a90afbcbb1f9414d4a9a8437e49f8.png new file mode 100644 index 0000000000000000000000000000000000000000..e16ee6df04e8ae24448064a2f13ac89ed47d02c4 Binary files /dev/null and b/_book/docs/img/0d6a90afbcbb1f9414d4a9a8437e49f8.png differ diff --git a/_book/docs/img/0dad61d266449688c931d1703509bca3.png b/_book/docs/img/0dad61d266449688c931d1703509bca3.png new file mode 100644 index 0000000000000000000000000000000000000000..77d82ea2c7943559205ba81e1a28d0a124f380cb Binary files /dev/null and b/_book/docs/img/0dad61d266449688c931d1703509bca3.png differ diff --git a/_book/docs/img/0dd0fc53dcaa34b76a16be18538c1a35.png b/_book/docs/img/0dd0fc53dcaa34b76a16be18538c1a35.png new file mode 100644 index 0000000000000000000000000000000000000000..3b2814f9e4194b563fdaa16d067ded004233fb75 Binary files /dev/null and b/_book/docs/img/0dd0fc53dcaa34b76a16be18538c1a35.png differ diff --git a/_book/docs/img/0df7602f630bb279bdd6d7dc6a5dcf2f.png b/_book/docs/img/0df7602f630bb279bdd6d7dc6a5dcf2f.png new file mode 100644 index 0000000000000000000000000000000000000000..e80f95a8e94e5238c913045395e3a7c446b15647 Binary files /dev/null and b/_book/docs/img/0df7602f630bb279bdd6d7dc6a5dcf2f.png differ diff --git a/_book/docs/img/0e0e78d03e98ec2ac04952defaba83ff.png b/_book/docs/img/0e0e78d03e98ec2ac04952defaba83ff.png new file mode 100644 index 0000000000000000000000000000000000000000..c6096f09c507c8142839e6e88fdc4ed389cf1e5e Binary files /dev/null and b/_book/docs/img/0e0e78d03e98ec2ac04952defaba83ff.png differ diff --git a/_book/docs/img/0e2287fb4b32bf9dff45f3255ddd45fe.png b/_book/docs/img/0e2287fb4b32bf9dff45f3255ddd45fe.png new file mode 100644 index 0000000000000000000000000000000000000000..2a5e67660bfc56dfa483977d52c0e5b3ea530bf5 Binary files /dev/null and b/_book/docs/img/0e2287fb4b32bf9dff45f3255ddd45fe.png differ diff --git a/_book/docs/img/0e27f7f7b1dd7b6748365d5ea985238a.png b/_book/docs/img/0e27f7f7b1dd7b6748365d5ea985238a.png new file mode 100644 index 0000000000000000000000000000000000000000..49f920b8917ff9a1a5010ea439c08a51fb16d196 Binary files /dev/null and b/_book/docs/img/0e27f7f7b1dd7b6748365d5ea985238a.png differ diff --git a/_book/docs/img/0f7aab3f307e6b54ebe4d00d94f1da0a.png b/_book/docs/img/0f7aab3f307e6b54ebe4d00d94f1da0a.png new file mode 100644 index 0000000000000000000000000000000000000000..649c3d6d78d028b55a71bd3e82e65b9f1f304f31 Binary files /dev/null and b/_book/docs/img/0f7aab3f307e6b54ebe4d00d94f1da0a.png differ diff --git a/_book/docs/img/0f88b0e1a49600472f2922218cec1ed7.png b/_book/docs/img/0f88b0e1a49600472f2922218cec1ed7.png new file mode 100644 index 0000000000000000000000000000000000000000..370ec4c0354bb499e3dc6f086dcff1e7abe8650a Binary files /dev/null and b/_book/docs/img/0f88b0e1a49600472f2922218cec1ed7.png differ diff --git a/_book/docs/img/0fdd144a1493e4d21226f1b04a5d336a.png b/_book/docs/img/0fdd144a1493e4d21226f1b04a5d336a.png new file mode 100644 index 0000000000000000000000000000000000000000..52c337db9bc37a03146f6c14904396c821d09f16 Binary files /dev/null and b/_book/docs/img/0fdd144a1493e4d21226f1b04a5d336a.png differ diff --git a/_book/docs/img/0ff1ac0799b3b8867f4ebefa4e22d786.png b/_book/docs/img/0ff1ac0799b3b8867f4ebefa4e22d786.png new file mode 100644 index 0000000000000000000000000000000000000000..630bf35e4ebc4cca62c744f81b5f9f527b33956d Binary files /dev/null and b/_book/docs/img/0ff1ac0799b3b8867f4ebefa4e22d786.png differ diff --git a/_book/docs/img/104374dd85800b346ef75734f6fd0b38.png b/_book/docs/img/104374dd85800b346ef75734f6fd0b38.png new file mode 100644 index 0000000000000000000000000000000000000000..3228c8a50912d8368e8c269356dd06117a77382b Binary files /dev/null and b/_book/docs/img/104374dd85800b346ef75734f6fd0b38.png differ diff --git a/_book/docs/img/10fd27d874d8e6ace6b74801909782ae.png b/_book/docs/img/10fd27d874d8e6ace6b74801909782ae.png new file mode 100644 index 0000000000000000000000000000000000000000..df0130d12ac56af8ca71baf1921fdc9cc09a5c11 Binary files /dev/null and b/_book/docs/img/10fd27d874d8e6ace6b74801909782ae.png differ diff --git a/_book/docs/img/114dc1abb6412aca14f3c3b6ad3048dc.png b/_book/docs/img/114dc1abb6412aca14f3c3b6ad3048dc.png new file mode 100644 index 0000000000000000000000000000000000000000..5612a9ed9c893ba3b7a80285b7afdb901d627231 Binary files /dev/null and b/_book/docs/img/114dc1abb6412aca14f3c3b6ad3048dc.png differ diff --git a/_book/docs/img/1162f64da937aa1ef37877c6b8930e1e.png b/_book/docs/img/1162f64da937aa1ef37877c6b8930e1e.png new file mode 100644 index 0000000000000000000000000000000000000000..77c6ee8fd4cc19d228796742829df100e0543bfc Binary files /dev/null and b/_book/docs/img/1162f64da937aa1ef37877c6b8930e1e.png differ diff --git a/_book/docs/img/1165fee2238c55848aeb09d59c76cf7b.png b/_book/docs/img/1165fee2238c55848aeb09d59c76cf7b.png new file mode 100644 index 0000000000000000000000000000000000000000..e7318320a0f006d210dc153c4ef0e82d51cb42d1 Binary files /dev/null and b/_book/docs/img/1165fee2238c55848aeb09d59c76cf7b.png differ diff --git a/_book/docs/img/11728974fe5385112311ab02ea56783e.png b/_book/docs/img/11728974fe5385112311ab02ea56783e.png new file mode 100644 index 0000000000000000000000000000000000000000..7bf908e2f2417218092d1a1ac1228b33519f322f Binary files /dev/null and b/_book/docs/img/11728974fe5385112311ab02ea56783e.png differ diff --git a/_book/docs/img/11b32b9624ee5e827950dd6f126127d6.png b/_book/docs/img/11b32b9624ee5e827950dd6f126127d6.png new file mode 100644 index 0000000000000000000000000000000000000000..dbb95e771a08491ed9db5bb83ea7f57b52d41173 Binary files /dev/null and b/_book/docs/img/11b32b9624ee5e827950dd6f126127d6.png differ diff --git a/_book/docs/img/11f64bd49fd604a4644dd54ed7e423e8.png b/_book/docs/img/11f64bd49fd604a4644dd54ed7e423e8.png new file mode 100644 index 0000000000000000000000000000000000000000..3ffbcf14cb4847af46206b64d592ce24bfdd6ebe Binary files /dev/null and b/_book/docs/img/11f64bd49fd604a4644dd54ed7e423e8.png differ diff --git a/_book/docs/img/12208c7d040cd738d51605b7fcb55237.png b/_book/docs/img/12208c7d040cd738d51605b7fcb55237.png new file mode 100644 index 0000000000000000000000000000000000000000..82c975df531ce7d3610ea1201da300ca97c67e80 Binary files /dev/null and b/_book/docs/img/12208c7d040cd738d51605b7fcb55237.png differ diff --git a/_book/docs/img/12e557e74666b1c90827cdd5bfe4d87a.png b/_book/docs/img/12e557e74666b1c90827cdd5bfe4d87a.png new file mode 100644 index 0000000000000000000000000000000000000000..ec02aad32ce5e8c29f6b7e64b660c56f62179e27 Binary files /dev/null and b/_book/docs/img/12e557e74666b1c90827cdd5bfe4d87a.png differ diff --git a/_book/docs/img/136df5416c67f2d80606b4849658e289.png b/_book/docs/img/136df5416c67f2d80606b4849658e289.png new file mode 100644 index 0000000000000000000000000000000000000000..d7a71c08b2474fa25c46f8f771dc4677289a736b Binary files /dev/null and b/_book/docs/img/136df5416c67f2d80606b4849658e289.png differ diff --git a/_book/docs/img/137ac74ffc45b0c50cf354baa972ca89.png b/_book/docs/img/137ac74ffc45b0c50cf354baa972ca89.png new file mode 100644 index 0000000000000000000000000000000000000000..051d660e8bbc5f93dd909fa6e984aa262754fe46 Binary files /dev/null and b/_book/docs/img/137ac74ffc45b0c50cf354baa972ca89.png differ diff --git a/_book/docs/img/13b2b9b44dbf46de0243edc068ecab42.png b/_book/docs/img/13b2b9b44dbf46de0243edc068ecab42.png new file mode 100644 index 0000000000000000000000000000000000000000..825cac669030588a0138f4f0bf7caea63d1dfc4e Binary files /dev/null and b/_book/docs/img/13b2b9b44dbf46de0243edc068ecab42.png differ diff --git a/_book/docs/img/13c910771ce7fad76e82ba7b8bdd440b.png b/_book/docs/img/13c910771ce7fad76e82ba7b8bdd440b.png new file mode 100644 index 0000000000000000000000000000000000000000..11e2c98a84eae322af0f8d4894099f5e1cba3030 Binary files /dev/null and b/_book/docs/img/13c910771ce7fad76e82ba7b8bdd440b.png differ diff --git a/_book/docs/img/14110c067c5c98646bcad82dbd3be10b.png b/_book/docs/img/14110c067c5c98646bcad82dbd3be10b.png new file mode 100644 index 0000000000000000000000000000000000000000..b3be73a5c864aee43bc02c775ab06a1bf3e1ca24 Binary files /dev/null and b/_book/docs/img/14110c067c5c98646bcad82dbd3be10b.png differ diff --git a/_book/docs/img/1427a32ce32914c8100f7563817e3d64.png b/_book/docs/img/1427a32ce32914c8100f7563817e3d64.png new file mode 100644 index 0000000000000000000000000000000000000000..edadad37cba80ff392e8a8fff946ed09fbb958d1 Binary files /dev/null and b/_book/docs/img/1427a32ce32914c8100f7563817e3d64.png differ diff --git a/_book/docs/img/149fa515778bea7ce86903f0c8d9b31f.png b/_book/docs/img/149fa515778bea7ce86903f0c8d9b31f.png new file mode 100644 index 0000000000000000000000000000000000000000..02612e925812ed64abd2caf364cf4cc65446d326 Binary files /dev/null and b/_book/docs/img/149fa515778bea7ce86903f0c8d9b31f.png differ diff --git a/_book/docs/img/14b1dcd13ed2d776e5cab726504e2df9.png b/_book/docs/img/14b1dcd13ed2d776e5cab726504e2df9.png new file mode 100644 index 0000000000000000000000000000000000000000..f9b1685bb48a623c105bca7885aeac338041b7e8 Binary files /dev/null and b/_book/docs/img/14b1dcd13ed2d776e5cab726504e2df9.png differ diff --git a/_book/docs/img/15b455cffa86c3a9234ad8c30082a4df.png b/_book/docs/img/15b455cffa86c3a9234ad8c30082a4df.png new file mode 100644 index 0000000000000000000000000000000000000000..d81e29bb512d7a941545236f9f9c4f211b64bf9d Binary files /dev/null and b/_book/docs/img/15b455cffa86c3a9234ad8c30082a4df.png differ diff --git a/_book/docs/img/161780e2fab1ff78247b22985553ba96.png b/_book/docs/img/161780e2fab1ff78247b22985553ba96.png new file mode 100644 index 0000000000000000000000000000000000000000..3337df4bf2a4b0864a18405d0bdfe909211c52be Binary files /dev/null and b/_book/docs/img/161780e2fab1ff78247b22985553ba96.png differ diff --git a/_book/docs/img/169af1eb67d287048e2bd4de1d3a178a.png b/_book/docs/img/169af1eb67d287048e2bd4de1d3a178a.png new file mode 100644 index 0000000000000000000000000000000000000000..60ae66c23391666d2d703b479df229e971a969fc Binary files /dev/null and b/_book/docs/img/169af1eb67d287048e2bd4de1d3a178a.png differ diff --git a/_book/docs/img/16db6a809ddf03cf101fdbec905d41a2.png b/_book/docs/img/16db6a809ddf03cf101fdbec905d41a2.png new file mode 100644 index 0000000000000000000000000000000000000000..cb58d4a31b41b0191fa874c6752f3e3af78df94b Binary files /dev/null and b/_book/docs/img/16db6a809ddf03cf101fdbec905d41a2.png differ diff --git a/_book/docs/img/16f0d7c3d19700b0e30aa6c1528acb91.png b/_book/docs/img/16f0d7c3d19700b0e30aa6c1528acb91.png new file mode 100644 index 0000000000000000000000000000000000000000..48a212b6dad87af6630565d1e293f4bfc6d216fb Binary files /dev/null and b/_book/docs/img/16f0d7c3d19700b0e30aa6c1528acb91.png differ diff --git a/_book/docs/img/1780684b75826fc70c4f9d6a00cd9984.png b/_book/docs/img/1780684b75826fc70c4f9d6a00cd9984.png new file mode 100644 index 0000000000000000000000000000000000000000..ab566831623543117b9eb9ab8bac0fabfab2cef2 Binary files /dev/null and b/_book/docs/img/1780684b75826fc70c4f9d6a00cd9984.png differ diff --git a/_book/docs/img/17abb300a15db5073a41bf8a13e53bc7.png b/_book/docs/img/17abb300a15db5073a41bf8a13e53bc7.png new file mode 100644 index 0000000000000000000000000000000000000000..0cf3afd441fafb718eff65d3fe2596a1d8dfbce4 Binary files /dev/null and b/_book/docs/img/17abb300a15db5073a41bf8a13e53bc7.png differ diff --git a/_book/docs/img/17d0ef7b105be8069a4258a758bd25bb.png b/_book/docs/img/17d0ef7b105be8069a4258a758bd25bb.png new file mode 100644 index 0000000000000000000000000000000000000000..12ed0d74698ea73d38cbe870dd140c2279b59a67 Binary files /dev/null and b/_book/docs/img/17d0ef7b105be8069a4258a758bd25bb.png differ diff --git a/_book/docs/img/17e23e08ff33b405e039adae1f73cb83.png b/_book/docs/img/17e23e08ff33b405e039adae1f73cb83.png new file mode 100644 index 0000000000000000000000000000000000000000..fdada3feff124e2326de96a65588840b0b9a0c34 Binary files /dev/null and b/_book/docs/img/17e23e08ff33b405e039adae1f73cb83.png differ diff --git a/_book/docs/img/181ef05617eae83f93df5db5884cb3f2.png b/_book/docs/img/181ef05617eae83f93df5db5884cb3f2.png new file mode 100644 index 0000000000000000000000000000000000000000..889effdbd786e226a99411b46530470d41a46037 Binary files /dev/null and b/_book/docs/img/181ef05617eae83f93df5db5884cb3f2.png differ diff --git a/_book/docs/img/182928c540d17ccf275438850fc7592d.png b/_book/docs/img/182928c540d17ccf275438850fc7592d.png new file mode 100644 index 0000000000000000000000000000000000000000..3b7f74cc6bfa885370bcefccd5e31138700414f2 Binary files /dev/null and b/_book/docs/img/182928c540d17ccf275438850fc7592d.png differ diff --git a/_book/docs/img/184e7323733c8aa9331e3fbef102e17c.png b/_book/docs/img/184e7323733c8aa9331e3fbef102e17c.png new file mode 100644 index 0000000000000000000000000000000000000000..84658aa5104a439ed312b9545e623aef3c8c74e1 Binary files /dev/null and b/_book/docs/img/184e7323733c8aa9331e3fbef102e17c.png differ diff --git a/_book/docs/img/185cfb126a59b17e7d802717876f8725.png b/_book/docs/img/185cfb126a59b17e7d802717876f8725.png new file mode 100644 index 0000000000000000000000000000000000000000..03c43e8fcc67fcf8bfe292b059d777dd36d83ea6 Binary files /dev/null and b/_book/docs/img/185cfb126a59b17e7d802717876f8725.png differ diff --git a/_book/docs/img/1864a1996bbb1636d65648dd8b0857df.png b/_book/docs/img/1864a1996bbb1636d65648dd8b0857df.png new file mode 100644 index 0000000000000000000000000000000000000000..d29a1aefbc14f5c0850be3a6a4ec07ff8f022002 Binary files /dev/null and b/_book/docs/img/1864a1996bbb1636d65648dd8b0857df.png differ diff --git a/_book/docs/img/18f2b22b7daf0beab9074c6695c99960.png b/_book/docs/img/18f2b22b7daf0beab9074c6695c99960.png new file mode 100644 index 0000000000000000000000000000000000000000..6ce5a3c3a60bb8e62e7912c5dadec92bfceaed05 Binary files /dev/null and b/_book/docs/img/18f2b22b7daf0beab9074c6695c99960.png differ diff --git a/_book/docs/img/191e4984d9e1aa615a86fec2b6d42dcd.png b/_book/docs/img/191e4984d9e1aa615a86fec2b6d42dcd.png new file mode 100644 index 0000000000000000000000000000000000000000..d22d76eaedb0dd4aff443c363cf42c66d72bcad6 Binary files /dev/null and b/_book/docs/img/191e4984d9e1aa615a86fec2b6d42dcd.png differ diff --git a/_book/docs/img/1a097c142decf7d516165322a0f7b880.png b/_book/docs/img/1a097c142decf7d516165322a0f7b880.png new file mode 100644 index 0000000000000000000000000000000000000000..d9a5db4e0a98789e0eb04f942b30cbfc4d59b166 Binary files /dev/null and b/_book/docs/img/1a097c142decf7d516165322a0f7b880.png differ diff --git a/_book/docs/img/1a1b871d7e874d4f8e2ab4905d000509.png b/_book/docs/img/1a1b871d7e874d4f8e2ab4905d000509.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c7565370b115c2edc39e54cf84203885039ca1 Binary files /dev/null and b/_book/docs/img/1a1b871d7e874d4f8e2ab4905d000509.png differ diff --git a/_book/docs/img/1a3371a11e14e221f5c8e0e75e327d08.png b/_book/docs/img/1a3371a11e14e221f5c8e0e75e327d08.png new file mode 100644 index 0000000000000000000000000000000000000000..f48d0bfb9d6e02717098f07cbe3552cf9c073699 Binary files /dev/null and b/_book/docs/img/1a3371a11e14e221f5c8e0e75e327d08.png differ diff --git a/_book/docs/img/1a3f578f317c266ca4b5d61eb91d025b.png b/_book/docs/img/1a3f578f317c266ca4b5d61eb91d025b.png new file mode 100644 index 0000000000000000000000000000000000000000..c3c88c4aa8ee8ecb3d1e761f15346dba8a5d4392 Binary files /dev/null and b/_book/docs/img/1a3f578f317c266ca4b5d61eb91d025b.png differ diff --git a/_book/docs/img/1a5840885de676ed33d7cdb688b26a12.png b/_book/docs/img/1a5840885de676ed33d7cdb688b26a12.png new file mode 100644 index 0000000000000000000000000000000000000000..80c0478b58a67bc355f348e312330be62b8fbe53 Binary files /dev/null and b/_book/docs/img/1a5840885de676ed33d7cdb688b26a12.png differ diff --git a/_book/docs/img/1ab2181cd0be5aa7d8e96f16a1348ef9.png b/_book/docs/img/1ab2181cd0be5aa7d8e96f16a1348ef9.png new file mode 100644 index 0000000000000000000000000000000000000000..6ea70960e7b1c9b7a8d04cf568f4b8cf4b875c78 Binary files /dev/null and b/_book/docs/img/1ab2181cd0be5aa7d8e96f16a1348ef9.png differ diff --git a/_book/docs/img/1b109b486c41c14a03eea4127cec2351.png b/_book/docs/img/1b109b486c41c14a03eea4127cec2351.png new file mode 100644 index 0000000000000000000000000000000000000000..1c6baf9d648ae1f62832322ef63477a77407ced2 Binary files /dev/null and b/_book/docs/img/1b109b486c41c14a03eea4127cec2351.png differ diff --git a/_book/docs/img/1b69e9fcb692fa835e9b7e06fa856aee.png b/_book/docs/img/1b69e9fcb692fa835e9b7e06fa856aee.png new file mode 100644 index 0000000000000000000000000000000000000000..e8bde94d7c795639f8d3b3e1f3194a3f89542fac Binary files /dev/null and b/_book/docs/img/1b69e9fcb692fa835e9b7e06fa856aee.png differ diff --git a/_book/docs/img/1b984d904256e7a325a4cc30bcf71ee1.png b/_book/docs/img/1b984d904256e7a325a4cc30bcf71ee1.png new file mode 100644 index 0000000000000000000000000000000000000000..130d5ccc03b294324770c0e691d159a6d51c88ac Binary files /dev/null and b/_book/docs/img/1b984d904256e7a325a4cc30bcf71ee1.png differ diff --git a/_book/docs/img/1bb73cd8d699dd8fa617c328abafb76b.png b/_book/docs/img/1bb73cd8d699dd8fa617c328abafb76b.png new file mode 100644 index 0000000000000000000000000000000000000000..9cd62c8e9f94f0d7102102b93c5b8fb1d693e3d3 Binary files /dev/null and b/_book/docs/img/1bb73cd8d699dd8fa617c328abafb76b.png differ diff --git a/_book/docs/img/1bc92f79d9645e6ae51aff10100e5c0d.png b/_book/docs/img/1bc92f79d9645e6ae51aff10100e5c0d.png new file mode 100644 index 0000000000000000000000000000000000000000..1a1bb82c612670151a8b18cf04e92e6fcdf94eb5 Binary files /dev/null and b/_book/docs/img/1bc92f79d9645e6ae51aff10100e5c0d.png differ diff --git a/_book/docs/img/1bce7244cd585ee6d059a7aa1903f194.png b/_book/docs/img/1bce7244cd585ee6d059a7aa1903f194.png new file mode 100644 index 0000000000000000000000000000000000000000..e7d2b80c8c63adf2d1c61962d3ddafe8e169f412 Binary files /dev/null and b/_book/docs/img/1bce7244cd585ee6d059a7aa1903f194.png differ diff --git a/_book/docs/img/1be5fea51b824b103e9b5bac12136a90.png b/_book/docs/img/1be5fea51b824b103e9b5bac12136a90.png new file mode 100644 index 0000000000000000000000000000000000000000..1cdc02a389bfc8999b512f6efb121491f4dc7541 Binary files /dev/null and b/_book/docs/img/1be5fea51b824b103e9b5bac12136a90.png differ diff --git a/_book/docs/img/1c1c9ba40bbb3c1ab789e70a4c4d42e6.png b/_book/docs/img/1c1c9ba40bbb3c1ab789e70a4c4d42e6.png new file mode 100644 index 0000000000000000000000000000000000000000..0f35a62ff3b4e0f9099adbb8abc6a0db8180240f Binary files /dev/null and b/_book/docs/img/1c1c9ba40bbb3c1ab789e70a4c4d42e6.png differ diff --git a/_book/docs/img/1c4eef7cdb82fd840a9facad4ee93d6b.png b/_book/docs/img/1c4eef7cdb82fd840a9facad4ee93d6b.png new file mode 100644 index 0000000000000000000000000000000000000000..9ebe002a85d4cbc40e8e3af64259d27c4675f802 Binary files /dev/null and b/_book/docs/img/1c4eef7cdb82fd840a9facad4ee93d6b.png differ diff --git a/_book/docs/img/1c78b1078232f166ee3d03d64f2b3907.png b/_book/docs/img/1c78b1078232f166ee3d03d64f2b3907.png new file mode 100644 index 0000000000000000000000000000000000000000..a8cfd35269a967f53a15b66e4332484e60382473 Binary files /dev/null and b/_book/docs/img/1c78b1078232f166ee3d03d64f2b3907.png differ diff --git a/_book/docs/img/1c96e8d94988240b7dc68ae02dbea405.png b/_book/docs/img/1c96e8d94988240b7dc68ae02dbea405.png new file mode 100644 index 0000000000000000000000000000000000000000..06faad869874f493d9eaef75e6658595c146ddc1 Binary files /dev/null and b/_book/docs/img/1c96e8d94988240b7dc68ae02dbea405.png differ diff --git a/_book/docs/img/1d54aa31264e3f3b98ebf2049669f910.png b/_book/docs/img/1d54aa31264e3f3b98ebf2049669f910.png new file mode 100644 index 0000000000000000000000000000000000000000..d3f5631fa1b1838abee9ba2069c8fc4be6e22c15 Binary files /dev/null and b/_book/docs/img/1d54aa31264e3f3b98ebf2049669f910.png differ diff --git a/_book/docs/img/1d8faac0ce4cf1206b5c2745df725ca6.png b/_book/docs/img/1d8faac0ce4cf1206b5c2745df725ca6.png new file mode 100644 index 0000000000000000000000000000000000000000..434fb1b25e655802df3c79feb6f71fc80fa29f95 Binary files /dev/null and b/_book/docs/img/1d8faac0ce4cf1206b5c2745df725ca6.png differ diff --git a/_book/docs/img/1d9bd6ef20c22f103a6d120b8c673b06.png b/_book/docs/img/1d9bd6ef20c22f103a6d120b8c673b06.png new file mode 100644 index 0000000000000000000000000000000000000000..c9c932108db67f46c961ee6dce72eeb19a46e091 Binary files /dev/null and b/_book/docs/img/1d9bd6ef20c22f103a6d120b8c673b06.png differ diff --git a/_book/docs/img/1dcfd40d9306c4cfb80013c0cebdcac0.png b/_book/docs/img/1dcfd40d9306c4cfb80013c0cebdcac0.png new file mode 100644 index 0000000000000000000000000000000000000000..221115c8dfcacc97a7c825f948bb8adce8736911 Binary files /dev/null and b/_book/docs/img/1dcfd40d9306c4cfb80013c0cebdcac0.png differ diff --git a/_book/docs/img/1e0213e85ced3ac9dcc079f0e1831068.png b/_book/docs/img/1e0213e85ced3ac9dcc079f0e1831068.png new file mode 100644 index 0000000000000000000000000000000000000000..fcf79604e283ab7f24d4d68e310a03b6cde81b28 Binary files /dev/null and b/_book/docs/img/1e0213e85ced3ac9dcc079f0e1831068.png differ diff --git a/_book/docs/img/1e1a93a55568355165c7529b5326427b.png b/_book/docs/img/1e1a93a55568355165c7529b5326427b.png new file mode 100644 index 0000000000000000000000000000000000000000..1dacb5dc1abfe4b0a7b46af9ffd0748c5f10df0f Binary files /dev/null and b/_book/docs/img/1e1a93a55568355165c7529b5326427b.png differ diff --git a/_book/docs/img/1f5aad8fb69a4afb74547a2d31fcbc66.png b/_book/docs/img/1f5aad8fb69a4afb74547a2d31fcbc66.png new file mode 100644 index 0000000000000000000000000000000000000000..63e4c57fb16ba58aabfb259048f48b282b116075 Binary files /dev/null and b/_book/docs/img/1f5aad8fb69a4afb74547a2d31fcbc66.png differ diff --git a/_book/docs/img/1fa927abbc0d78f64822dcc6c7295cd4.png b/_book/docs/img/1fa927abbc0d78f64822dcc6c7295cd4.png new file mode 100644 index 0000000000000000000000000000000000000000..24e40e88cf63bf2152f36909290c10f60ae11a63 Binary files /dev/null and b/_book/docs/img/1fa927abbc0d78f64822dcc6c7295cd4.png differ diff --git a/_book/docs/img/1fdfdef058a3092e25352089de97fee6.png b/_book/docs/img/1fdfdef058a3092e25352089de97fee6.png new file mode 100644 index 0000000000000000000000000000000000000000..e563a48ba8807d6a3b872b60b833431c4a69183e Binary files /dev/null and b/_book/docs/img/1fdfdef058a3092e25352089de97fee6.png differ diff --git a/_book/docs/img/1ff79a3af1496b3e864efbcf5f93307f.png b/_book/docs/img/1ff79a3af1496b3e864efbcf5f93307f.png new file mode 100644 index 0000000000000000000000000000000000000000..1a3328be136ea9a5efa06ec40b5b9f7487670f6c Binary files /dev/null and b/_book/docs/img/1ff79a3af1496b3e864efbcf5f93307f.png differ diff --git a/_book/docs/img/2066156f84e498acec96cdfb63d2d2a4.png b/_book/docs/img/2066156f84e498acec96cdfb63d2d2a4.png new file mode 100644 index 0000000000000000000000000000000000000000..b0d6880f84cfc93dbc3f20ccca3cff9bc5d4dfee Binary files /dev/null and b/_book/docs/img/2066156f84e498acec96cdfb63d2d2a4.png differ diff --git a/_book/docs/img/206da14c2b9fd76390be58e7103b69c7.png b/_book/docs/img/206da14c2b9fd76390be58e7103b69c7.png new file mode 100644 index 0000000000000000000000000000000000000000..e30751e1271dc1d5034b2e3616cf9d01d6dc9e2c Binary files /dev/null and b/_book/docs/img/206da14c2b9fd76390be58e7103b69c7.png differ diff --git a/_book/docs/img/20bba5f798131b98df30aaa9202ccfd5.png b/_book/docs/img/20bba5f798131b98df30aaa9202ccfd5.png new file mode 100644 index 0000000000000000000000000000000000000000..301a5727e4a0e90cff67804c3529a083600661cd Binary files /dev/null and b/_book/docs/img/20bba5f798131b98df30aaa9202ccfd5.png differ diff --git a/_book/docs/img/210e34a4dbdbe21aba5083c6f7dac9cb.png b/_book/docs/img/210e34a4dbdbe21aba5083c6f7dac9cb.png new file mode 100644 index 0000000000000000000000000000000000000000..fb70dec5262560a26b923cd4a597ed6ffe73c1af Binary files /dev/null and b/_book/docs/img/210e34a4dbdbe21aba5083c6f7dac9cb.png differ diff --git a/_book/docs/img/212946086e16f591c716728308d49ca3.png b/_book/docs/img/212946086e16f591c716728308d49ca3.png new file mode 100644 index 0000000000000000000000000000000000000000..3d9c01aae9304f43a297e682bd6bf5149c176934 Binary files /dev/null and b/_book/docs/img/212946086e16f591c716728308d49ca3.png differ diff --git a/_book/docs/img/21967843cf3a12bcfa5e39a39b1b3f69.png b/_book/docs/img/21967843cf3a12bcfa5e39a39b1b3f69.png new file mode 100644 index 0000000000000000000000000000000000000000..54324df41ddf7dd53a4b58eb43e941804a943ada Binary files /dev/null and b/_book/docs/img/21967843cf3a12bcfa5e39a39b1b3f69.png differ diff --git a/_book/docs/img/222aa4a1e09c2312446d0aa324c6f193.png b/_book/docs/img/222aa4a1e09c2312446d0aa324c6f193.png new file mode 100644 index 0000000000000000000000000000000000000000..d40e041cc8429378eb5f8d5d9ef508e414b7f5e5 Binary files /dev/null and b/_book/docs/img/222aa4a1e09c2312446d0aa324c6f193.png differ diff --git a/_book/docs/img/2257f7989872604ba6ce6506ba811b15.png b/_book/docs/img/2257f7989872604ba6ce6506ba811b15.png new file mode 100644 index 0000000000000000000000000000000000000000..a1859df48955c6f64c49232695b47ad29e032e87 Binary files /dev/null and b/_book/docs/img/2257f7989872604ba6ce6506ba811b15.png differ diff --git a/_book/docs/img/2279c6b38c41208a2726d04b0df15c37.png b/_book/docs/img/2279c6b38c41208a2726d04b0df15c37.png new file mode 100644 index 0000000000000000000000000000000000000000..9ff313fb6c07f4a6fd588692ce649e5be8223037 Binary files /dev/null and b/_book/docs/img/2279c6b38c41208a2726d04b0df15c37.png differ diff --git a/_book/docs/img/2310ec0a03905adc0774d21079604b57.png b/_book/docs/img/2310ec0a03905adc0774d21079604b57.png new file mode 100644 index 0000000000000000000000000000000000000000..aa37927b8236b1a74140f7037c6574224acb5c07 Binary files /dev/null and b/_book/docs/img/2310ec0a03905adc0774d21079604b57.png differ diff --git a/_book/docs/img/235fdd047e32990019bc08c92ced8299.png b/_book/docs/img/235fdd047e32990019bc08c92ced8299.png new file mode 100644 index 0000000000000000000000000000000000000000..1145bf0b207e41a5c6269cb58e6a99dd79e12f6c Binary files /dev/null and b/_book/docs/img/235fdd047e32990019bc08c92ced8299.png differ diff --git a/_book/docs/img/23b032de89e1f1056b75bd7ad55823ea.png b/_book/docs/img/23b032de89e1f1056b75bd7ad55823ea.png new file mode 100644 index 0000000000000000000000000000000000000000..847166f384ab4d5366640d4043fb5207ceeca4b0 Binary files /dev/null and b/_book/docs/img/23b032de89e1f1056b75bd7ad55823ea.png differ diff --git a/_book/docs/img/243c1a9fc7dab75d6576c27470e73bf0.png b/_book/docs/img/243c1a9fc7dab75d6576c27470e73bf0.png new file mode 100644 index 0000000000000000000000000000000000000000..0fe2b87e8d30a1b49b9277ba085dc05fb082174d Binary files /dev/null and b/_book/docs/img/243c1a9fc7dab75d6576c27470e73bf0.png differ diff --git a/_book/docs/img/24ea9a3635dc27668b899d6785917b1b.png b/_book/docs/img/24ea9a3635dc27668b899d6785917b1b.png new file mode 100644 index 0000000000000000000000000000000000000000..b8af583951ed282d3928d8fd5d2b8cc2934b894b Binary files /dev/null and b/_book/docs/img/24ea9a3635dc27668b899d6785917b1b.png differ diff --git a/_book/docs/img/252e40c4dc029a21eb939cb40f715d34.png b/_book/docs/img/252e40c4dc029a21eb939cb40f715d34.png new file mode 100644 index 0000000000000000000000000000000000000000..c6d35b60762697ec954ea318486567c7ed4987f8 Binary files /dev/null and b/_book/docs/img/252e40c4dc029a21eb939cb40f715d34.png differ diff --git a/_book/docs/img/25892ec4aa99429a91c30ac3395379e0.png b/_book/docs/img/25892ec4aa99429a91c30ac3395379e0.png new file mode 100644 index 0000000000000000000000000000000000000000..20bbe25e8762d21320cd0a5d11dd6a5b6f02c983 Binary files /dev/null and b/_book/docs/img/25892ec4aa99429a91c30ac3395379e0.png differ diff --git a/_book/docs/img/261e6c6422bccbb978c24c0728f3a593.png b/_book/docs/img/261e6c6422bccbb978c24c0728f3a593.png new file mode 100644 index 0000000000000000000000000000000000000000..577dc4812829880cab0a98d34d27a184c909aad6 Binary files /dev/null and b/_book/docs/img/261e6c6422bccbb978c24c0728f3a593.png differ diff --git a/_book/docs/img/2629e4ef9252e4970d626ca424e88dd2.png b/_book/docs/img/2629e4ef9252e4970d626ca424e88dd2.png new file mode 100644 index 0000000000000000000000000000000000000000..0642c1caa2964d84818ec0b483349c4f8e53161d Binary files /dev/null and b/_book/docs/img/2629e4ef9252e4970d626ca424e88dd2.png differ diff --git a/_book/docs/img/262e648fe4e99ca02b386ebade539097.png b/_book/docs/img/262e648fe4e99ca02b386ebade539097.png new file mode 100644 index 0000000000000000000000000000000000000000..15570c619a8e5f2f2026f864e4a451f2db726726 Binary files /dev/null and b/_book/docs/img/262e648fe4e99ca02b386ebade539097.png differ diff --git a/_book/docs/img/264ee345c8d001f9b7cabf52e10f47bf.png b/_book/docs/img/264ee345c8d001f9b7cabf52e10f47bf.png new file mode 100644 index 0000000000000000000000000000000000000000..1042fd3dc067b765017e4e36edf8b6b941cd6075 Binary files /dev/null and b/_book/docs/img/264ee345c8d001f9b7cabf52e10f47bf.png differ diff --git a/_book/docs/img/265f035427185c0998b05886114d104b.png b/_book/docs/img/265f035427185c0998b05886114d104b.png new file mode 100644 index 0000000000000000000000000000000000000000..7bc218af356d10f3bfed49e7eed5c6f774599bbf Binary files /dev/null and b/_book/docs/img/265f035427185c0998b05886114d104b.png differ diff --git a/_book/docs/img/26b5d3ef6b515c199d6c860ac62a4671.png b/_book/docs/img/26b5d3ef6b515c199d6c860ac62a4671.png new file mode 100644 index 0000000000000000000000000000000000000000..68143805c0a8fdb5b3fb527e4bedf8468bde8953 Binary files /dev/null and b/_book/docs/img/26b5d3ef6b515c199d6c860ac62a4671.png differ diff --git a/_book/docs/img/276614fbc4ef7b7b9f7a445dffbc5691.png b/_book/docs/img/276614fbc4ef7b7b9f7a445dffbc5691.png new file mode 100644 index 0000000000000000000000000000000000000000..2c64b681dfba44b42de4b4df30520548ac160a32 Binary files /dev/null and b/_book/docs/img/276614fbc4ef7b7b9f7a445dffbc5691.png differ diff --git a/_book/docs/img/27858125d0f3461e373b06413f40e616.png b/_book/docs/img/27858125d0f3461e373b06413f40e616.png new file mode 100644 index 0000000000000000000000000000000000000000..861bba650361792d1ae6851dd732ea558701000a Binary files /dev/null and b/_book/docs/img/27858125d0f3461e373b06413f40e616.png differ diff --git a/_book/docs/img/279650b9e9c3ec26a7d6f0493bd5af7c.png b/_book/docs/img/279650b9e9c3ec26a7d6f0493bd5af7c.png new file mode 100644 index 0000000000000000000000000000000000000000..fed4b3030aed026538b04b588b260a9d2dec566d Binary files /dev/null and b/_book/docs/img/279650b9e9c3ec26a7d6f0493bd5af7c.png differ diff --git a/_book/docs/img/27b77c1cf5861234d7e06b742e7cbf58.png b/_book/docs/img/27b77c1cf5861234d7e06b742e7cbf58.png new file mode 100644 index 0000000000000000000000000000000000000000..0e394d63a1b4496f0e359e712a78952f9b38af90 Binary files /dev/null and b/_book/docs/img/27b77c1cf5861234d7e06b742e7cbf58.png differ diff --git a/_book/docs/img/27d6bf9eb64fd8e4298e7a2a8ae64983.png b/_book/docs/img/27d6bf9eb64fd8e4298e7a2a8ae64983.png new file mode 100644 index 0000000000000000000000000000000000000000..35d4828dd55dd0dc6ba840ddd651a27b0afa7d9c Binary files /dev/null and b/_book/docs/img/27d6bf9eb64fd8e4298e7a2a8ae64983.png differ diff --git a/_book/docs/img/27f5db1ffe5c715ccd311bccf93665f2.png b/_book/docs/img/27f5db1ffe5c715ccd311bccf93665f2.png new file mode 100644 index 0000000000000000000000000000000000000000..209bec6356901650c16cbc5b7d6fee2e29190eb4 Binary files /dev/null and b/_book/docs/img/27f5db1ffe5c715ccd311bccf93665f2.png differ diff --git a/_book/docs/img/281606a988de9b8e23469c0de4e22062.png b/_book/docs/img/281606a988de9b8e23469c0de4e22062.png new file mode 100644 index 0000000000000000000000000000000000000000..912d3266426e8197c1f51acf6b56a4f7cb3801bc Binary files /dev/null and b/_book/docs/img/281606a988de9b8e23469c0de4e22062.png differ diff --git a/_book/docs/img/2823aaef9502e47fb72734606099a98a.png b/_book/docs/img/2823aaef9502e47fb72734606099a98a.png new file mode 100644 index 0000000000000000000000000000000000000000..3bb926c684a522502c6b5c697566c18341751ebc Binary files /dev/null and b/_book/docs/img/2823aaef9502e47fb72734606099a98a.png differ diff --git a/_book/docs/img/28300ad671ab6b5aec8525cb2a7af157.png b/_book/docs/img/28300ad671ab6b5aec8525cb2a7af157.png new file mode 100644 index 0000000000000000000000000000000000000000..1b6f902e9958e5d30456ed541bc28d77c776e91b Binary files /dev/null and b/_book/docs/img/28300ad671ab6b5aec8525cb2a7af157.png differ diff --git a/_book/docs/img/283011f90b0969b60cd202dd293525ca.png b/_book/docs/img/283011f90b0969b60cd202dd293525ca.png new file mode 100644 index 0000000000000000000000000000000000000000..fedf36e1476f1e66320da0748c74e1051c337744 Binary files /dev/null and b/_book/docs/img/283011f90b0969b60cd202dd293525ca.png differ diff --git a/_book/docs/img/284b72b1bfc8d5679fdaa384932b3b8c.png b/_book/docs/img/284b72b1bfc8d5679fdaa384932b3b8c.png new file mode 100644 index 0000000000000000000000000000000000000000..343cc5a3116249723f50407a042f28d8d376550a Binary files /dev/null and b/_book/docs/img/284b72b1bfc8d5679fdaa384932b3b8c.png differ diff --git a/_book/docs/img/28ba73ced40f830058c21c46c8291bfe.png b/_book/docs/img/28ba73ced40f830058c21c46c8291bfe.png new file mode 100644 index 0000000000000000000000000000000000000000..686c4191307a49437f2366eadcda31bef5fdb976 Binary files /dev/null and b/_book/docs/img/28ba73ced40f830058c21c46c8291bfe.png differ diff --git a/_book/docs/img/28e0f270ca5b3b728207d80c19a82d71.png b/_book/docs/img/28e0f270ca5b3b728207d80c19a82d71.png new file mode 100644 index 0000000000000000000000000000000000000000..b3ac97b273bdfcfb82f881bc4e42e6ca27d02132 Binary files /dev/null and b/_book/docs/img/28e0f270ca5b3b728207d80c19a82d71.png differ diff --git a/_book/docs/img/28ec7a2f016b77873dfadd5ab59c447b.png b/_book/docs/img/28ec7a2f016b77873dfadd5ab59c447b.png new file mode 100644 index 0000000000000000000000000000000000000000..167832ad29e19f46cefe1e3c91b43e44c9b5f4fc Binary files /dev/null and b/_book/docs/img/28ec7a2f016b77873dfadd5ab59c447b.png differ diff --git a/_book/docs/img/2927b047cacec2945671ab2484aafe9d.png b/_book/docs/img/2927b047cacec2945671ab2484aafe9d.png new file mode 100644 index 0000000000000000000000000000000000000000..9228e2464ed72bb1c22266945646cf98419aa7bc Binary files /dev/null and b/_book/docs/img/2927b047cacec2945671ab2484aafe9d.png differ diff --git a/_book/docs/img/2a301148b56e04c50113445dc7280c15.png b/_book/docs/img/2a301148b56e04c50113445dc7280c15.png new file mode 100644 index 0000000000000000000000000000000000000000..461fe295303c46f92a4225ae7e8bd7bf07871c67 Binary files /dev/null and b/_book/docs/img/2a301148b56e04c50113445dc7280c15.png differ diff --git a/_book/docs/img/2a62cf1a17a5306e4d6cd91c30149941.png b/_book/docs/img/2a62cf1a17a5306e4d6cd91c30149941.png new file mode 100644 index 0000000000000000000000000000000000000000..3adf7276ed6bb0ca4b10311a56445fb0f73fc15d Binary files /dev/null and b/_book/docs/img/2a62cf1a17a5306e4d6cd91c30149941.png differ diff --git a/_book/docs/img/2ae8145aa44498bcadafa3451ee343b1.png b/_book/docs/img/2ae8145aa44498bcadafa3451ee343b1.png new file mode 100644 index 0000000000000000000000000000000000000000..91f93becd33ee240eb25985db21e387b08722d8b Binary files /dev/null and b/_book/docs/img/2ae8145aa44498bcadafa3451ee343b1.png differ diff --git a/_book/docs/img/2b38faa6a2c817e4d1b8b32f803db372.png b/_book/docs/img/2b38faa6a2c817e4d1b8b32f803db372.png new file mode 100644 index 0000000000000000000000000000000000000000..60f091a0e5e1f99ab04e78ca9638626efa5d3a7c Binary files /dev/null and b/_book/docs/img/2b38faa6a2c817e4d1b8b32f803db372.png differ diff --git a/_book/docs/img/2b49f82a2ff96781b55685367813e6c9.png b/_book/docs/img/2b49f82a2ff96781b55685367813e6c9.png new file mode 100644 index 0000000000000000000000000000000000000000..ea847a5cdd9e884665188b106209ec91569ace81 Binary files /dev/null and b/_book/docs/img/2b49f82a2ff96781b55685367813e6c9.png differ diff --git a/_book/docs/img/2b66844a710706131349b467b399b449.png b/_book/docs/img/2b66844a710706131349b467b399b449.png new file mode 100644 index 0000000000000000000000000000000000000000..b3a5029444ef8e294ba9f7fe833510e528ba19e7 Binary files /dev/null and b/_book/docs/img/2b66844a710706131349b467b399b449.png differ diff --git a/_book/docs/img/2bb7640bbe66bec0d43070f6f4053758.png b/_book/docs/img/2bb7640bbe66bec0d43070f6f4053758.png new file mode 100644 index 0000000000000000000000000000000000000000..70ebf6e70d7692bd6fda9ee93d9a722c5e6ef935 Binary files /dev/null and b/_book/docs/img/2bb7640bbe66bec0d43070f6f4053758.png differ diff --git a/_book/docs/img/2c7964b63403cf1f03ea9bdbfeee96cf.png b/_book/docs/img/2c7964b63403cf1f03ea9bdbfeee96cf.png new file mode 100644 index 0000000000000000000000000000000000000000..ac35818c8568e55bc7aa923bcfd261cc17576b70 Binary files /dev/null and b/_book/docs/img/2c7964b63403cf1f03ea9bdbfeee96cf.png differ diff --git a/_book/docs/img/2c8994d4c86769ec5151192ff555b261.png b/_book/docs/img/2c8994d4c86769ec5151192ff555b261.png new file mode 100644 index 0000000000000000000000000000000000000000..81e5f6f7fa28d8030a99c82a59a3d0817513a52c Binary files /dev/null and b/_book/docs/img/2c8994d4c86769ec5151192ff555b261.png differ diff --git a/_book/docs/img/2d13f3059b88ccaf448646ed61f70d47.png b/_book/docs/img/2d13f3059b88ccaf448646ed61f70d47.png new file mode 100644 index 0000000000000000000000000000000000000000..b5b4391905f23e6f03988e025c013c1b21d125c3 Binary files /dev/null and b/_book/docs/img/2d13f3059b88ccaf448646ed61f70d47.png differ diff --git a/_book/docs/img/2d1845503f8ff90d4dc71459313e4e62.png b/_book/docs/img/2d1845503f8ff90d4dc71459313e4e62.png new file mode 100644 index 0000000000000000000000000000000000000000..b32f3d1d04aaef7a24ac0739b427bca423a20f04 Binary files /dev/null and b/_book/docs/img/2d1845503f8ff90d4dc71459313e4e62.png differ diff --git a/_book/docs/img/2dde5152cc249727c2d1016051d52131.png b/_book/docs/img/2dde5152cc249727c2d1016051d52131.png new file mode 100644 index 0000000000000000000000000000000000000000..2e88cc041a0ccbf9c3eaeba86f6572a9825664ee Binary files /dev/null and b/_book/docs/img/2dde5152cc249727c2d1016051d52131.png differ diff --git a/_book/docs/img/2e1001a11cd343049b87ebf60a315e9f.png b/_book/docs/img/2e1001a11cd343049b87ebf60a315e9f.png new file mode 100644 index 0000000000000000000000000000000000000000..c4e3bfe3e9432a12fffd6211cb5dc9930ff0f916 Binary files /dev/null and b/_book/docs/img/2e1001a11cd343049b87ebf60a315e9f.png differ diff --git a/_book/docs/img/2e2c36f66667fc52b3fb3681533dcef7.png b/_book/docs/img/2e2c36f66667fc52b3fb3681533dcef7.png new file mode 100644 index 0000000000000000000000000000000000000000..10fbe41d6f6f476a4c057bfd8a27baf152632165 Binary files /dev/null and b/_book/docs/img/2e2c36f66667fc52b3fb3681533dcef7.png differ diff --git a/_book/docs/img/2ed1719eefb651778ccd248f0bbe577c.png b/_book/docs/img/2ed1719eefb651778ccd248f0bbe577c.png new file mode 100644 index 0000000000000000000000000000000000000000..dc7f37b2b774abed028a6b84ac6f857fc0db22db Binary files /dev/null and b/_book/docs/img/2ed1719eefb651778ccd248f0bbe577c.png differ diff --git a/_book/docs/img/2f78c411d32ee05e95a1984ef90b2356.png b/_book/docs/img/2f78c411d32ee05e95a1984ef90b2356.png new file mode 100644 index 0000000000000000000000000000000000000000..1b85f599493c2d074b2e3c0152df3b830f87a02d Binary files /dev/null and b/_book/docs/img/2f78c411d32ee05e95a1984ef90b2356.png differ diff --git a/_book/docs/img/2f8e418a69825e31935272d55cceae7f.png b/_book/docs/img/2f8e418a69825e31935272d55cceae7f.png new file mode 100644 index 0000000000000000000000000000000000000000..cf2b436579426581f0b2e281cc57a7265dda59b6 Binary files /dev/null and b/_book/docs/img/2f8e418a69825e31935272d55cceae7f.png differ diff --git a/_book/docs/img/2fdc2024eee83764328fb015ffd4e392.png b/_book/docs/img/2fdc2024eee83764328fb015ffd4e392.png new file mode 100644 index 0000000000000000000000000000000000000000..9bb64605cbe9d6289d57bfa6d80a07f2c011003c Binary files /dev/null and b/_book/docs/img/2fdc2024eee83764328fb015ffd4e392.png differ diff --git a/_book/docs/img/2fe480e26b1b89b82607729986e5b13a.png b/_book/docs/img/2fe480e26b1b89b82607729986e5b13a.png new file mode 100644 index 0000000000000000000000000000000000000000..8db70c71febaf3523981c7aaabe911a9658bf3d9 Binary files /dev/null and b/_book/docs/img/2fe480e26b1b89b82607729986e5b13a.png differ diff --git a/_book/docs/img/2fed535a429569e1ae792fb3960bcdd5.png b/_book/docs/img/2fed535a429569e1ae792fb3960bcdd5.png new file mode 100644 index 0000000000000000000000000000000000000000..cc8f7fba523501c283eb081f563837c2592d1383 Binary files /dev/null and b/_book/docs/img/2fed535a429569e1ae792fb3960bcdd5.png differ diff --git a/_book/docs/img/3001efd4ffb849af0c15eb8dda4d4050.png b/_book/docs/img/3001efd4ffb849af0c15eb8dda4d4050.png new file mode 100644 index 0000000000000000000000000000000000000000..abe345be14581776cf0baa2408b85ae44ae3c012 Binary files /dev/null and b/_book/docs/img/3001efd4ffb849af0c15eb8dda4d4050.png differ diff --git a/_book/docs/img/30152366655be1543f687603c8d34d96.png b/_book/docs/img/30152366655be1543f687603c8d34d96.png new file mode 100644 index 0000000000000000000000000000000000000000..02427f1ef6ed1fe01f9bdcf696254a8ddaa563b2 Binary files /dev/null and b/_book/docs/img/30152366655be1543f687603c8d34d96.png differ diff --git a/_book/docs/img/30460bec4b16c49e4f5d5ccc7ac92601.png b/_book/docs/img/30460bec4b16c49e4f5d5ccc7ac92601.png new file mode 100644 index 0000000000000000000000000000000000000000..7608284e7e2aa2e26066fc20a06bfc80afa65179 Binary files /dev/null and b/_book/docs/img/30460bec4b16c49e4f5d5ccc7ac92601.png differ diff --git a/_book/docs/img/31396caea61831939862213abb8dd10c.png b/_book/docs/img/31396caea61831939862213abb8dd10c.png new file mode 100644 index 0000000000000000000000000000000000000000..e317ebb6336ba513a948d2d009f0cc79230daab0 Binary files /dev/null and b/_book/docs/img/31396caea61831939862213abb8dd10c.png differ diff --git a/_book/docs/img/317167b85f9604b741e71e57b1702b6c.png b/_book/docs/img/317167b85f9604b741e71e57b1702b6c.png new file mode 100644 index 0000000000000000000000000000000000000000..a7344eae866b9d622aa48039e131270bba6fe841 Binary files /dev/null and b/_book/docs/img/317167b85f9604b741e71e57b1702b6c.png differ diff --git a/_book/docs/img/31c7821d41281d527a8ee4f058bafaca.png b/_book/docs/img/31c7821d41281d527a8ee4f058bafaca.png new file mode 100644 index 0000000000000000000000000000000000000000..5fc353914478992c82178061d8f978f44df9774b Binary files /dev/null and b/_book/docs/img/31c7821d41281d527a8ee4f058bafaca.png differ diff --git a/_book/docs/img/31d242e54217fe005ee1481fbb81c786.png b/_book/docs/img/31d242e54217fe005ee1481fbb81c786.png new file mode 100644 index 0000000000000000000000000000000000000000..fec656ce3902ff7576d9002fb1582238b13bebac Binary files /dev/null and b/_book/docs/img/31d242e54217fe005ee1481fbb81c786.png differ diff --git a/_book/docs/img/31f0a42465a379e152ef6c0c7a6395e9.png b/_book/docs/img/31f0a42465a379e152ef6c0c7a6395e9.png new file mode 100644 index 0000000000000000000000000000000000000000..fdd7985491e9f294d07b54b515adeee0420480d6 Binary files /dev/null and b/_book/docs/img/31f0a42465a379e152ef6c0c7a6395e9.png differ diff --git a/_book/docs/img/31f8f986b27020e646540b9595d026cd.png b/_book/docs/img/31f8f986b27020e646540b9595d026cd.png new file mode 100644 index 0000000000000000000000000000000000000000..72846c2b4f3425a60fc73ed27711a7708ce102cb Binary files /dev/null and b/_book/docs/img/31f8f986b27020e646540b9595d026cd.png differ diff --git a/_book/docs/img/3252759837ced64a222db48c62becdd3.png b/_book/docs/img/3252759837ced64a222db48c62becdd3.png new file mode 100644 index 0000000000000000000000000000000000000000..29ddb119aca16e16f255380dc90085a31a3155f1 Binary files /dev/null and b/_book/docs/img/3252759837ced64a222db48c62becdd3.png differ diff --git a/_book/docs/img/3281ef5fea53e2f0a57bb3c648aa7fa4.png b/_book/docs/img/3281ef5fea53e2f0a57bb3c648aa7fa4.png new file mode 100644 index 0000000000000000000000000000000000000000..f8ffa92a76062874828f06b0939d7f87d4e49439 Binary files /dev/null and b/_book/docs/img/3281ef5fea53e2f0a57bb3c648aa7fa4.png differ diff --git a/_book/docs/img/337891c1885c756f35968127a8050c21.png b/_book/docs/img/337891c1885c756f35968127a8050c21.png new file mode 100644 index 0000000000000000000000000000000000000000..0f01bf03dd7b5e242e5fc3a37c7b3ea13df7e754 Binary files /dev/null and b/_book/docs/img/337891c1885c756f35968127a8050c21.png differ diff --git a/_book/docs/img/33ae5f16a8ad7c683e894a2a3032cfa9.png b/_book/docs/img/33ae5f16a8ad7c683e894a2a3032cfa9.png new file mode 100644 index 0000000000000000000000000000000000000000..2d797aff8cf1008d769a672891031a16c322535b Binary files /dev/null and b/_book/docs/img/33ae5f16a8ad7c683e894a2a3032cfa9.png differ diff --git a/_book/docs/img/33c514aefa1ff87fe18907b27d473e03.png b/_book/docs/img/33c514aefa1ff87fe18907b27d473e03.png new file mode 100644 index 0000000000000000000000000000000000000000..85c4ba8513104d3bf9b949129c7d1a767f12fb8a Binary files /dev/null and b/_book/docs/img/33c514aefa1ff87fe18907b27d473e03.png differ diff --git a/_book/docs/img/33cc6d96a283a4f1b3cc5b27da9fd1c4.png b/_book/docs/img/33cc6d96a283a4f1b3cc5b27da9fd1c4.png new file mode 100644 index 0000000000000000000000000000000000000000..3536265100983f7e67620b6b594a8bbfede6aa49 Binary files /dev/null and b/_book/docs/img/33cc6d96a283a4f1b3cc5b27da9fd1c4.png differ diff --git a/_book/docs/img/33da6433c882c8bcc4c699a4e0008b7c.png b/_book/docs/img/33da6433c882c8bcc4c699a4e0008b7c.png new file mode 100644 index 0000000000000000000000000000000000000000..8c0e15ee0bb2b9c03c36d6236417f087d75eb198 Binary files /dev/null and b/_book/docs/img/33da6433c882c8bcc4c699a4e0008b7c.png differ diff --git a/_book/docs/img/3444bd33319e0b2d996233cf9e1103c5.png b/_book/docs/img/3444bd33319e0b2d996233cf9e1103c5.png new file mode 100644 index 0000000000000000000000000000000000000000..b6bfd6d3e94d81f3ebbd3f19b577f223ec662906 Binary files /dev/null and b/_book/docs/img/3444bd33319e0b2d996233cf9e1103c5.png differ diff --git a/_book/docs/img/3478cae6da4e529f7c9cf2f4e71dd462.png b/_book/docs/img/3478cae6da4e529f7c9cf2f4e71dd462.png new file mode 100644 index 0000000000000000000000000000000000000000..602803119a6c765864114a59fb95d29023f47911 Binary files /dev/null and b/_book/docs/img/3478cae6da4e529f7c9cf2f4e71dd462.png differ diff --git a/_book/docs/img/35460a8c847cde5f9e477c80231d7f8b.png b/_book/docs/img/35460a8c847cde5f9e477c80231d7f8b.png new file mode 100644 index 0000000000000000000000000000000000000000..54b0bd865dd8918bdb03ac476deb83ee743d9570 Binary files /dev/null and b/_book/docs/img/35460a8c847cde5f9e477c80231d7f8b.png differ diff --git a/_book/docs/img/35b66299a79c8b3212bf8fbb00e9c903.png b/_book/docs/img/35b66299a79c8b3212bf8fbb00e9c903.png new file mode 100644 index 0000000000000000000000000000000000000000..f1bec233632ff00b4c31c4e9170faa6f8f83375e Binary files /dev/null and b/_book/docs/img/35b66299a79c8b3212bf8fbb00e9c903.png differ diff --git a/_book/docs/img/35e89eba4dfc37f409cb295b0c8b13d1.png b/_book/docs/img/35e89eba4dfc37f409cb295b0c8b13d1.png new file mode 100644 index 0000000000000000000000000000000000000000..80a8f648b670473108d214a41a9a08d9b3f06945 Binary files /dev/null and b/_book/docs/img/35e89eba4dfc37f409cb295b0c8b13d1.png differ diff --git a/_book/docs/img/35fbd0a23d3b20913cb4490a3957d8b3.png b/_book/docs/img/35fbd0a23d3b20913cb4490a3957d8b3.png new file mode 100644 index 0000000000000000000000000000000000000000..861eb0aba619820884a63dfd9b738979bb53ef23 Binary files /dev/null and b/_book/docs/img/35fbd0a23d3b20913cb4490a3957d8b3.png differ diff --git a/_book/docs/img/3601605e24186a1976e7aff09112bb7e.png b/_book/docs/img/3601605e24186a1976e7aff09112bb7e.png new file mode 100644 index 0000000000000000000000000000000000000000..b5cecadbb2ed5ebc45645b6393add18f8c4ee4b6 Binary files /dev/null and b/_book/docs/img/3601605e24186a1976e7aff09112bb7e.png differ diff --git a/_book/docs/img/3636c78ef6cb3ccc1462dd451c7f3efc.png b/_book/docs/img/3636c78ef6cb3ccc1462dd451c7f3efc.png new file mode 100644 index 0000000000000000000000000000000000000000..26d4426a1161887c53b1b26b40594808b00d89bf Binary files /dev/null and b/_book/docs/img/3636c78ef6cb3ccc1462dd451c7f3efc.png differ diff --git a/_book/docs/img/3667bc1901823963df25df8a2458047a.png b/_book/docs/img/3667bc1901823963df25df8a2458047a.png new file mode 100644 index 0000000000000000000000000000000000000000..a17bb4d89ce073a4152a36f1a873a9a129fa5f34 Binary files /dev/null and b/_book/docs/img/3667bc1901823963df25df8a2458047a.png differ diff --git a/_book/docs/img/366832d79f753b4e66470fa923fa7acf.png b/_book/docs/img/366832d79f753b4e66470fa923fa7acf.png new file mode 100644 index 0000000000000000000000000000000000000000..fa0f797b00a516c61d43897a6741669f18a03b07 Binary files /dev/null and b/_book/docs/img/366832d79f753b4e66470fa923fa7acf.png differ diff --git a/_book/docs/img/3694fc45636610ba5fb4e24d7a9eb3b9.png b/_book/docs/img/3694fc45636610ba5fb4e24d7a9eb3b9.png new file mode 100644 index 0000000000000000000000000000000000000000..95ae04db34819d72a1a1b64656a9c21a3a786db1 Binary files /dev/null and b/_book/docs/img/3694fc45636610ba5fb4e24d7a9eb3b9.png differ diff --git a/_book/docs/img/36aa502eb297ed552d82e3b015053e9e.png b/_book/docs/img/36aa502eb297ed552d82e3b015053e9e.png new file mode 100644 index 0000000000000000000000000000000000000000..bf02d33a3c0ce06423a84f3afdcd378c18506648 Binary files /dev/null and b/_book/docs/img/36aa502eb297ed552d82e3b015053e9e.png differ diff --git a/_book/docs/img/36abd47af07b3b82f814e74be4619b4d.png b/_book/docs/img/36abd47af07b3b82f814e74be4619b4d.png new file mode 100644 index 0000000000000000000000000000000000000000..7c4e7b98375de43b34b0d63ea3932920d4c3adeb Binary files /dev/null and b/_book/docs/img/36abd47af07b3b82f814e74be4619b4d.png differ diff --git a/_book/docs/img/36d97eaa1e64c3f6d5b78d205d1ce881.png b/_book/docs/img/36d97eaa1e64c3f6d5b78d205d1ce881.png new file mode 100644 index 0000000000000000000000000000000000000000..19678b9eca43b4d7074728385a3b95a950aa384b Binary files /dev/null and b/_book/docs/img/36d97eaa1e64c3f6d5b78d205d1ce881.png differ diff --git a/_book/docs/img/370ac43323901b08b905644b04f6a802.png b/_book/docs/img/370ac43323901b08b905644b04f6a802.png new file mode 100644 index 0000000000000000000000000000000000000000..42004b0e4af4744918033f65463b78c9d884afee Binary files /dev/null and b/_book/docs/img/370ac43323901b08b905644b04f6a802.png differ diff --git a/_book/docs/img/371d1ca1640afbd824acc19b18bc40c9.png b/_book/docs/img/371d1ca1640afbd824acc19b18bc40c9.png new file mode 100644 index 0000000000000000000000000000000000000000..73560de7cc40d1134ff72d7263ed25528e1264b4 Binary files /dev/null and b/_book/docs/img/371d1ca1640afbd824acc19b18bc40c9.png differ diff --git a/_book/docs/img/37238acd557de0d61f0c3be198c56e00.png b/_book/docs/img/37238acd557de0d61f0c3be198c56e00.png new file mode 100644 index 0000000000000000000000000000000000000000..e341b0f77e04b0957b65db19ea8d067f8286f73b Binary files /dev/null and b/_book/docs/img/37238acd557de0d61f0c3be198c56e00.png differ diff --git a/_book/docs/img/3794ce06aeeb9528fa1a66915cc69072.png b/_book/docs/img/3794ce06aeeb9528fa1a66915cc69072.png new file mode 100644 index 0000000000000000000000000000000000000000..9aaa5b706eb91613c1106a375f042f5c878f01d5 Binary files /dev/null and b/_book/docs/img/3794ce06aeeb9528fa1a66915cc69072.png differ diff --git a/_book/docs/img/379bd77b46dd7f0617bc273a203c9a29.png b/_book/docs/img/379bd77b46dd7f0617bc273a203c9a29.png new file mode 100644 index 0000000000000000000000000000000000000000..6450710ce821284eee7e3c9afe6575179543bf5e Binary files /dev/null and b/_book/docs/img/379bd77b46dd7f0617bc273a203c9a29.png differ diff --git a/_book/docs/img/37cb6e38ded4ec606f9bc7776f765e70.png b/_book/docs/img/37cb6e38ded4ec606f9bc7776f765e70.png new file mode 100644 index 0000000000000000000000000000000000000000..fd65a3239b0d2115daf1a864d37fdc22a4d2e0ae Binary files /dev/null and b/_book/docs/img/37cb6e38ded4ec606f9bc7776f765e70.png differ diff --git a/_book/docs/img/381000c5f5c6ad01300dfcc889f7fb0f.png b/_book/docs/img/381000c5f5c6ad01300dfcc889f7fb0f.png new file mode 100644 index 0000000000000000000000000000000000000000..a181912af9fe3aa360e512a8d8ce0a383c5f26c8 Binary files /dev/null and b/_book/docs/img/381000c5f5c6ad01300dfcc889f7fb0f.png differ diff --git a/_book/docs/img/381cb6fd4ceed7b2a8b3642926cb8cf2.png b/_book/docs/img/381cb6fd4ceed7b2a8b3642926cb8cf2.png new file mode 100644 index 0000000000000000000000000000000000000000..9ca4ae0df687f40a0a4f8fa91c23c38ad38cfb57 Binary files /dev/null and b/_book/docs/img/381cb6fd4ceed7b2a8b3642926cb8cf2.png differ diff --git a/_book/docs/img/3863add8513c90ad786112f7a200a568.png b/_book/docs/img/3863add8513c90ad786112f7a200a568.png new file mode 100644 index 0000000000000000000000000000000000000000..5bbf935b3eaf0253399bd26f34128b8b1f432634 Binary files /dev/null and b/_book/docs/img/3863add8513c90ad786112f7a200a568.png differ diff --git a/_book/docs/img/3887423740965d20eecf9471bc1b3061.png b/_book/docs/img/3887423740965d20eecf9471bc1b3061.png new file mode 100644 index 0000000000000000000000000000000000000000..dd8f69b624f4627101f9e0be00d1388c0c0153e4 Binary files /dev/null and b/_book/docs/img/3887423740965d20eecf9471bc1b3061.png differ diff --git a/_book/docs/img/38c073cc1c78dc88bf317e878e9995cc.png b/_book/docs/img/38c073cc1c78dc88bf317e878e9995cc.png new file mode 100644 index 0000000000000000000000000000000000000000..05982c8a4b0b660c92556a918425973ea5a9f03e Binary files /dev/null and b/_book/docs/img/38c073cc1c78dc88bf317e878e9995cc.png differ diff --git a/_book/docs/img/38d4db85b589523cbab105da53e5fb09.png b/_book/docs/img/38d4db85b589523cbab105da53e5fb09.png new file mode 100644 index 0000000000000000000000000000000000000000..b8ca0aa9b4ca631fc3904a5e3abc1b0612c6f9b7 Binary files /dev/null and b/_book/docs/img/38d4db85b589523cbab105da53e5fb09.png differ diff --git a/_book/docs/img/38ef5bf427869fe9b1050db6eacd2972.png b/_book/docs/img/38ef5bf427869fe9b1050db6eacd2972.png new file mode 100644 index 0000000000000000000000000000000000000000..29b0ff1e55a0bda29f8d3b49ad76330f000e3ed1 Binary files /dev/null and b/_book/docs/img/38ef5bf427869fe9b1050db6eacd2972.png differ diff --git a/_book/docs/img/393dab24a6c8be1031a4cf469f3039e9.png b/_book/docs/img/393dab24a6c8be1031a4cf469f3039e9.png new file mode 100644 index 0000000000000000000000000000000000000000..96fd20332578bac20636ab8d15343d1d4886d687 Binary files /dev/null and b/_book/docs/img/393dab24a6c8be1031a4cf469f3039e9.png differ diff --git a/_book/docs/img/39b4809628ba97edb93621d6eefa5135.png b/_book/docs/img/39b4809628ba97edb93621d6eefa5135.png new file mode 100644 index 0000000000000000000000000000000000000000..472fbc63083eacaa443a70364615140d1f8c5103 Binary files /dev/null and b/_book/docs/img/39b4809628ba97edb93621d6eefa5135.png differ diff --git a/_book/docs/img/3a328cbf9c83e567fa5921d3580a84cb.png b/_book/docs/img/3a328cbf9c83e567fa5921d3580a84cb.png new file mode 100644 index 0000000000000000000000000000000000000000..da7c9c006208efed4f144b511871a9b43e074f59 Binary files /dev/null and b/_book/docs/img/3a328cbf9c83e567fa5921d3580a84cb.png differ diff --git a/_book/docs/img/3b13f587681dd3391c82eb9b650ff6cf.png b/_book/docs/img/3b13f587681dd3391c82eb9b650ff6cf.png new file mode 100644 index 0000000000000000000000000000000000000000..2c9f40ec7d093cde98a5c833c4055c8ff21a8951 Binary files /dev/null and b/_book/docs/img/3b13f587681dd3391c82eb9b650ff6cf.png differ diff --git a/_book/docs/img/3b33bfa40900241891ce4c916e441a22.png b/_book/docs/img/3b33bfa40900241891ce4c916e441a22.png new file mode 100644 index 0000000000000000000000000000000000000000..9e5c8a8406049ae9c89ddb2f9cb8ca19ed99f698 Binary files /dev/null and b/_book/docs/img/3b33bfa40900241891ce4c916e441a22.png differ diff --git a/_book/docs/img/3b3e644f832753a09f245236299e74b2.png b/_book/docs/img/3b3e644f832753a09f245236299e74b2.png new file mode 100644 index 0000000000000000000000000000000000000000..35a42ddd164a41c56172c244d9b0c13b8b8bc121 Binary files /dev/null and b/_book/docs/img/3b3e644f832753a09f245236299e74b2.png differ diff --git a/_book/docs/img/3b8b0bcac599d7207d90ed8194bed83e.png b/_book/docs/img/3b8b0bcac599d7207d90ed8194bed83e.png new file mode 100644 index 0000000000000000000000000000000000000000..c804c7e4253f9de349dfe0d79e0e98fc854a81fd Binary files /dev/null and b/_book/docs/img/3b8b0bcac599d7207d90ed8194bed83e.png differ diff --git a/_book/docs/img/3c9cb466046f19c70255f0de753a307c.png b/_book/docs/img/3c9cb466046f19c70255f0de753a307c.png new file mode 100644 index 0000000000000000000000000000000000000000..6e40db206ad9095cfeda5278d6fde39cea477703 Binary files /dev/null and b/_book/docs/img/3c9cb466046f19c70255f0de753a307c.png differ diff --git a/_book/docs/img/3ca3bc9234ff248b19d9555bb5f1cff4.png b/_book/docs/img/3ca3bc9234ff248b19d9555bb5f1cff4.png new file mode 100644 index 0000000000000000000000000000000000000000..6ce63e5e1a18b1e472b251e02385a650cc07b13d Binary files /dev/null and b/_book/docs/img/3ca3bc9234ff248b19d9555bb5f1cff4.png differ diff --git a/_book/docs/img/3d8b21038a5aa14baa75dc65de55d728.png b/_book/docs/img/3d8b21038a5aa14baa75dc65de55d728.png new file mode 100644 index 0000000000000000000000000000000000000000..468a61588e6a0435ee5bcb0f0114f937845c0cc6 Binary files /dev/null and b/_book/docs/img/3d8b21038a5aa14baa75dc65de55d728.png differ diff --git a/_book/docs/img/3da5d65194b00f9dc3ffde2ac5f8473b.png b/_book/docs/img/3da5d65194b00f9dc3ffde2ac5f8473b.png new file mode 100644 index 0000000000000000000000000000000000000000..590e7e732848ca92d436cd5c329e9235b9f29179 Binary files /dev/null and b/_book/docs/img/3da5d65194b00f9dc3ffde2ac5f8473b.png differ diff --git a/_book/docs/img/3e0f74f35030a15b593a12090d5c0daf.png b/_book/docs/img/3e0f74f35030a15b593a12090d5c0daf.png new file mode 100644 index 0000000000000000000000000000000000000000..9994bb1c1e21c2bbf2c899bec94bb14ada590b84 Binary files /dev/null and b/_book/docs/img/3e0f74f35030a15b593a12090d5c0daf.png differ diff --git a/_book/docs/img/3e903eab58c2b1ac777ef30adf3bd44e.png b/_book/docs/img/3e903eab58c2b1ac777ef30adf3bd44e.png new file mode 100644 index 0000000000000000000000000000000000000000..afb7c9dc6fdb021afdccf979a97a4c905902f3ff Binary files /dev/null and b/_book/docs/img/3e903eab58c2b1ac777ef30adf3bd44e.png differ diff --git a/_book/docs/img/3ed7ccf7499687536cf254fc6f47d5e7.png b/_book/docs/img/3ed7ccf7499687536cf254fc6f47d5e7.png new file mode 100644 index 0000000000000000000000000000000000000000..2ff325ce930d69b20cd5b5b3f1c5da797574aeef Binary files /dev/null and b/_book/docs/img/3ed7ccf7499687536cf254fc6f47d5e7.png differ diff --git a/_book/docs/img/3f64ac42c5324a759f292fa0f7e4d991.png b/_book/docs/img/3f64ac42c5324a759f292fa0f7e4d991.png new file mode 100644 index 0000000000000000000000000000000000000000..e7eb30292573aa947599ceb45944e0a7e24e9af9 Binary files /dev/null and b/_book/docs/img/3f64ac42c5324a759f292fa0f7e4d991.png differ diff --git a/_book/docs/img/40834a63780a362f429e1902450a4a7a.png b/_book/docs/img/40834a63780a362f429e1902450a4a7a.png new file mode 100644 index 0000000000000000000000000000000000000000..048ae91c8aa8a292e7a378b792d735f4ac3c134c Binary files /dev/null and b/_book/docs/img/40834a63780a362f429e1902450a4a7a.png differ diff --git a/_book/docs/img/40cd53294c496a4d049d735386c16649.png b/_book/docs/img/40cd53294c496a4d049d735386c16649.png new file mode 100644 index 0000000000000000000000000000000000000000..ff399e26e73ff2e7cc8dcdac352c10426b6cfda6 Binary files /dev/null and b/_book/docs/img/40cd53294c496a4d049d735386c16649.png differ diff --git a/_book/docs/img/40dbd9d2f1f965f42a1c417a258da575.png b/_book/docs/img/40dbd9d2f1f965f42a1c417a258da575.png new file mode 100644 index 0000000000000000000000000000000000000000..b812d331538353d6214a60a297145b1792b6d012 Binary files /dev/null and b/_book/docs/img/40dbd9d2f1f965f42a1c417a258da575.png differ diff --git a/_book/docs/img/41371f9efeaf03eb888ba8e19a486185.png b/_book/docs/img/41371f9efeaf03eb888ba8e19a486185.png new file mode 100644 index 0000000000000000000000000000000000000000..65629737050a6e8ee31ceecc50337ea97bc59526 Binary files /dev/null and b/_book/docs/img/41371f9efeaf03eb888ba8e19a486185.png differ diff --git a/_book/docs/img/41571e3a155c671e6ff9f259f20fdeed.png b/_book/docs/img/41571e3a155c671e6ff9f259f20fdeed.png new file mode 100644 index 0000000000000000000000000000000000000000..701e46d8e30c0fa2b6888286394bbb4758393008 Binary files /dev/null and b/_book/docs/img/41571e3a155c671e6ff9f259f20fdeed.png differ diff --git a/_book/docs/img/423e566cce1da11ef163c69219f870aa.png b/_book/docs/img/423e566cce1da11ef163c69219f870aa.png new file mode 100644 index 0000000000000000000000000000000000000000..0733c5a6f159860628dbf3ce8a15faf82213fff1 Binary files /dev/null and b/_book/docs/img/423e566cce1da11ef163c69219f870aa.png differ diff --git a/_book/docs/img/423fb353db83bd90502f2f029c398e43.png b/_book/docs/img/423fb353db83bd90502f2f029c398e43.png new file mode 100644 index 0000000000000000000000000000000000000000..4c1d25258fc6ed99ee8144d92b6f460f64160776 Binary files /dev/null and b/_book/docs/img/423fb353db83bd90502f2f029c398e43.png differ diff --git a/_book/docs/img/429e9751a8b0336bb8b7e3faab15a373.png b/_book/docs/img/429e9751a8b0336bb8b7e3faab15a373.png new file mode 100644 index 0000000000000000000000000000000000000000..7947c534408383f8452c4be4a86bffa0a7b480a2 Binary files /dev/null and b/_book/docs/img/429e9751a8b0336bb8b7e3faab15a373.png differ diff --git a/_book/docs/img/439a9c21f68de25b8a16d0d0a28d19be.png b/_book/docs/img/439a9c21f68de25b8a16d0d0a28d19be.png new file mode 100644 index 0000000000000000000000000000000000000000..46830b65782e2e0aaf4ad03b583ad2cb77a161ad Binary files /dev/null and b/_book/docs/img/439a9c21f68de25b8a16d0d0a28d19be.png differ diff --git a/_book/docs/img/43a1d5a081bb166e1d43d6e671f250e1.png b/_book/docs/img/43a1d5a081bb166e1d43d6e671f250e1.png new file mode 100644 index 0000000000000000000000000000000000000000..8ce373b96c3272728188b87087c562b1fb284913 Binary files /dev/null and b/_book/docs/img/43a1d5a081bb166e1d43d6e671f250e1.png differ diff --git a/_book/docs/img/43c1d4f646051452c436962222af114b.png b/_book/docs/img/43c1d4f646051452c436962222af114b.png new file mode 100644 index 0000000000000000000000000000000000000000..1501a74a429981334cc1b2a99842a5c5ee95d724 Binary files /dev/null and b/_book/docs/img/43c1d4f646051452c436962222af114b.png differ diff --git a/_book/docs/img/4401376aa4e3f3764851b2dbb25f6f2e.png b/_book/docs/img/4401376aa4e3f3764851b2dbb25f6f2e.png new file mode 100644 index 0000000000000000000000000000000000000000..704264fc13925dcf1a4d4c9c58d4f23ba8025fda Binary files /dev/null and b/_book/docs/img/4401376aa4e3f3764851b2dbb25f6f2e.png differ diff --git a/_book/docs/img/441419241245b159818b469c6508f227.png b/_book/docs/img/441419241245b159818b469c6508f227.png new file mode 100644 index 0000000000000000000000000000000000000000..f41e0b9750581f49a5763839fc859852b8ac1ec1 Binary files /dev/null and b/_book/docs/img/441419241245b159818b469c6508f227.png differ diff --git a/_book/docs/img/44be1cce97f886ea1f1c93950d764041.png b/_book/docs/img/44be1cce97f886ea1f1c93950d764041.png new file mode 100644 index 0000000000000000000000000000000000000000..f332b2c6c3887b2ba033ed93093739d941a43870 Binary files /dev/null and b/_book/docs/img/44be1cce97f886ea1f1c93950d764041.png differ diff --git a/_book/docs/img/44cad341f814ae94da18480c3dc1d2be.png b/_book/docs/img/44cad341f814ae94da18480c3dc1d2be.png new file mode 100644 index 0000000000000000000000000000000000000000..952cdda943097316d7a7964916aec1f1f75cd70b Binary files /dev/null and b/_book/docs/img/44cad341f814ae94da18480c3dc1d2be.png differ diff --git a/_book/docs/img/44dfa1e85103f88c82598a4ef9f8d0ae.png b/_book/docs/img/44dfa1e85103f88c82598a4ef9f8d0ae.png new file mode 100644 index 0000000000000000000000000000000000000000..fc9d98adc4d60019d16a879e1cf217e6da4933cb Binary files /dev/null and b/_book/docs/img/44dfa1e85103f88c82598a4ef9f8d0ae.png differ diff --git a/_book/docs/img/45586bacf83042f9bfcdb01d5576fe3c.png b/_book/docs/img/45586bacf83042f9bfcdb01d5576fe3c.png new file mode 100644 index 0000000000000000000000000000000000000000..244beddcaf634bf7ca68eed4c3a008e4449a9c9e --- /dev/null +++ b/_book/docs/img/45586bacf83042f9bfcdb01d5576fe3c.png @@ -0,0 +1 @@ +<svg width="1170" height="638" viewBox="0 0 1170 638" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>review-apps-CD-outlinedCreated with Sketch. \ No newline at end of file diff --git a/_book/docs/img/45974f94466502ace734ecc3473a0d58.png b/_book/docs/img/45974f94466502ace734ecc3473a0d58.png new file mode 100644 index 0000000000000000000000000000000000000000..355e140c0307c46f05c33c67f84d77d417a11a00 Binary files /dev/null and b/_book/docs/img/45974f94466502ace734ecc3473a0d58.png differ diff --git a/_book/docs/img/45c66aeb387e650cfe717047d1b78263.png b/_book/docs/img/45c66aeb387e650cfe717047d1b78263.png new file mode 100644 index 0000000000000000000000000000000000000000..0d7a1886fa7152c80e1e9fbc6f95278cb61f23a4 Binary files /dev/null and b/_book/docs/img/45c66aeb387e650cfe717047d1b78263.png differ diff --git a/_book/docs/img/45cb073d466ec4a6fcb5a09d7f5f204c.png b/_book/docs/img/45cb073d466ec4a6fcb5a09d7f5f204c.png new file mode 100644 index 0000000000000000000000000000000000000000..97d39d07c116ad04a150e39935d5d115f9c6ae75 Binary files /dev/null and b/_book/docs/img/45cb073d466ec4a6fcb5a09d7f5f204c.png differ diff --git a/_book/docs/img/45cc34490ebcb0a656d7c57d3dcbbb00.png b/_book/docs/img/45cc34490ebcb0a656d7c57d3dcbbb00.png new file mode 100644 index 0000000000000000000000000000000000000000..c0728e037be73c3faa1bb3987d15dd51efa8d22b Binary files /dev/null and b/_book/docs/img/45cc34490ebcb0a656d7c57d3dcbbb00.png differ diff --git a/_book/docs/img/46322215ec68c4896b6b622f9f1ad11e.png b/_book/docs/img/46322215ec68c4896b6b622f9f1ad11e.png new file mode 100644 index 0000000000000000000000000000000000000000..7b1eff620521af7c6d85ad1b905439c55643c4f6 Binary files /dev/null and b/_book/docs/img/46322215ec68c4896b6b622f9f1ad11e.png differ diff --git a/_book/docs/img/4635aba96009dfb3ab93ab6f4b92ee4c.png b/_book/docs/img/4635aba96009dfb3ab93ab6f4b92ee4c.png new file mode 100644 index 0000000000000000000000000000000000000000..cc70962d2301ec8b4ed97d2ba23c47b84c0d9ed2 Binary files /dev/null and b/_book/docs/img/4635aba96009dfb3ab93ab6f4b92ee4c.png differ diff --git a/_book/docs/img/468eb44e935f615292705e2fc013ddb7.png b/_book/docs/img/468eb44e935f615292705e2fc013ddb7.png new file mode 100644 index 0000000000000000000000000000000000000000..107dbef7e22b9ce82db416213e610f12904845a9 Binary files /dev/null and b/_book/docs/img/468eb44e935f615292705e2fc013ddb7.png differ diff --git a/_book/docs/img/471bcfe6a44b22703662997289b517c9.png b/_book/docs/img/471bcfe6a44b22703662997289b517c9.png new file mode 100644 index 0000000000000000000000000000000000000000..81dbe1345cab372bc3a6c7181c8524cec2e5fbb0 Binary files /dev/null and b/_book/docs/img/471bcfe6a44b22703662997289b517c9.png differ diff --git a/_book/docs/img/47c6e09feffe93d1d9f758d50837b31b.png b/_book/docs/img/47c6e09feffe93d1d9f758d50837b31b.png new file mode 100644 index 0000000000000000000000000000000000000000..f4654eb8202f15128d6d66dc031f99661764fe0d Binary files /dev/null and b/_book/docs/img/47c6e09feffe93d1d9f758d50837b31b.png differ diff --git a/_book/docs/img/481f18ff2e4575d1c38d4c93631bd23c.png b/_book/docs/img/481f18ff2e4575d1c38d4c93631bd23c.png new file mode 100644 index 0000000000000000000000000000000000000000..c589ba482f4b7bbc80005484480113fdb87e3083 Binary files /dev/null and b/_book/docs/img/481f18ff2e4575d1c38d4c93631bd23c.png differ diff --git a/_book/docs/img/482b8e23d226428516ae20fae41ca7cf.png b/_book/docs/img/482b8e23d226428516ae20fae41ca7cf.png new file mode 100644 index 0000000000000000000000000000000000000000..48ac0114732df1fb528c383dc4307c07a16f82fe Binary files /dev/null and b/_book/docs/img/482b8e23d226428516ae20fae41ca7cf.png differ diff --git a/_book/docs/img/48482b1410caf250f0257d772e55c544.png b/_book/docs/img/48482b1410caf250f0257d772e55c544.png new file mode 100644 index 0000000000000000000000000000000000000000..82049a741f5916c0653096cbc352cf8dae67f19e Binary files /dev/null and b/_book/docs/img/48482b1410caf250f0257d772e55c544.png differ diff --git a/_book/docs/img/486761bb835c9408dac03956a04b3a53.png b/_book/docs/img/486761bb835c9408dac03956a04b3a53.png new file mode 100644 index 0000000000000000000000000000000000000000..1e5363eb1cd6e9b96c40cc2a2e576ad4bf773956 Binary files /dev/null and b/_book/docs/img/486761bb835c9408dac03956a04b3a53.png differ diff --git a/_book/docs/img/49588b733704d134418744f910f7809b.png b/_book/docs/img/49588b733704d134418744f910f7809b.png new file mode 100644 index 0000000000000000000000000000000000000000..296afe63b76a03890a657532232f3fc4476626dd Binary files /dev/null and b/_book/docs/img/49588b733704d134418744f910f7809b.png differ diff --git a/_book/docs/img/49d46d08d1ca6c3cd3d0b0ef98472512.png b/_book/docs/img/49d46d08d1ca6c3cd3d0b0ef98472512.png new file mode 100644 index 0000000000000000000000000000000000000000..274cff5c80ad087f8f53c56f678e2d9035039d3f Binary files /dev/null and b/_book/docs/img/49d46d08d1ca6c3cd3d0b0ef98472512.png differ diff --git a/_book/docs/img/4a007f26d24f09e03b3bb388bd94ae30.png b/_book/docs/img/4a007f26d24f09e03b3bb388bd94ae30.png new file mode 100644 index 0000000000000000000000000000000000000000..5d51855da45212cc1f43d79af3c4207ed3e89c93 Binary files /dev/null and b/_book/docs/img/4a007f26d24f09e03b3bb388bd94ae30.png differ diff --git a/_book/docs/img/4a3c28657f884da12667bc861ea60e0c.png b/_book/docs/img/4a3c28657f884da12667bc861ea60e0c.png new file mode 100644 index 0000000000000000000000000000000000000000..83942b4fe6b308a85d2fbc8aad4c6d7ce240d65c Binary files /dev/null and b/_book/docs/img/4a3c28657f884da12667bc861ea60e0c.png differ diff --git a/_book/docs/img/4a7c845c8d7b28d90af5923b08fb1e1d.png b/_book/docs/img/4a7c845c8d7b28d90af5923b08fb1e1d.png new file mode 100644 index 0000000000000000000000000000000000000000..3f407a5288dab5d4dbc71f6c34386c649d2650ff Binary files /dev/null and b/_book/docs/img/4a7c845c8d7b28d90af5923b08fb1e1d.png differ diff --git a/_book/docs/img/4ab2d185d65e76a0d58ad6564dff777a.png b/_book/docs/img/4ab2d185d65e76a0d58ad6564dff777a.png new file mode 100644 index 0000000000000000000000000000000000000000..d25041658866379d42f100f6cd9272a20b662139 Binary files /dev/null and b/_book/docs/img/4ab2d185d65e76a0d58ad6564dff777a.png differ diff --git a/_book/docs/img/4b690260474eb340f7b3f6d25b0568d2.png b/_book/docs/img/4b690260474eb340f7b3f6d25b0568d2.png new file mode 100644 index 0000000000000000000000000000000000000000..34b07412474b4022a3220baf450e977d2b516df3 Binary files /dev/null and b/_book/docs/img/4b690260474eb340f7b3f6d25b0568d2.png differ diff --git a/_book/docs/img/4b803fd891a7ec7f422522d2ff185864.png b/_book/docs/img/4b803fd891a7ec7f422522d2ff185864.png new file mode 100644 index 0000000000000000000000000000000000000000..edadad37cba80ff392e8a8fff946ed09fbb958d1 Binary files /dev/null and b/_book/docs/img/4b803fd891a7ec7f422522d2ff185864.png differ diff --git a/_book/docs/img/4c0cef07da8190af4f517bd8d336cb5b.png b/_book/docs/img/4c0cef07da8190af4f517bd8d336cb5b.png new file mode 100644 index 0000000000000000000000000000000000000000..2810ad6f3029211062c3a0452bf58c6321c33396 Binary files /dev/null and b/_book/docs/img/4c0cef07da8190af4f517bd8d336cb5b.png differ diff --git a/_book/docs/img/4c34240e5c09caa62a018e3d109c1ba3.png b/_book/docs/img/4c34240e5c09caa62a018e3d109c1ba3.png new file mode 100644 index 0000000000000000000000000000000000000000..e735937348aa610e2e468166b28d449ab15776b0 Binary files /dev/null and b/_book/docs/img/4c34240e5c09caa62a018e3d109c1ba3.png differ diff --git a/_book/docs/img/4c6172d095020a91bcf8d48c85ee4d1d.png b/_book/docs/img/4c6172d095020a91bcf8d48c85ee4d1d.png new file mode 100644 index 0000000000000000000000000000000000000000..f4c9d21982672113dcbdef752c1bccd7cb177ac6 Binary files /dev/null and b/_book/docs/img/4c6172d095020a91bcf8d48c85ee4d1d.png differ diff --git a/_book/docs/img/4ceccc7ae590a56e8b135fa8baaafabe.png b/_book/docs/img/4ceccc7ae590a56e8b135fa8baaafabe.png new file mode 100644 index 0000000000000000000000000000000000000000..e9b8c9588ed05cffe8fc79b3424f47eced97575c Binary files /dev/null and b/_book/docs/img/4ceccc7ae590a56e8b135fa8baaafabe.png differ diff --git a/_book/docs/img/4d2f841f1dee2bdbbdcd14bd5518c000.png b/_book/docs/img/4d2f841f1dee2bdbbdcd14bd5518c000.png new file mode 100644 index 0000000000000000000000000000000000000000..82d6e46bd52b599d4d86982552edfd65f38b3594 Binary files /dev/null and b/_book/docs/img/4d2f841f1dee2bdbbdcd14bd5518c000.png differ diff --git a/_book/docs/img/4d5fab6dd3f65351ba798d87517db0bd.png b/_book/docs/img/4d5fab6dd3f65351ba798d87517db0bd.png new file mode 100644 index 0000000000000000000000000000000000000000..3dea589160bdb4ba364fb7a6e0c15066932c754d Binary files /dev/null and b/_book/docs/img/4d5fab6dd3f65351ba798d87517db0bd.png differ diff --git a/_book/docs/img/4d9fbb6b23cf91f72dd201cf3a52f475.png b/_book/docs/img/4d9fbb6b23cf91f72dd201cf3a52f475.png new file mode 100644 index 0000000000000000000000000000000000000000..4ce6be22a002fa19c8f7d0cf01c1cecfacbdfb82 Binary files /dev/null and b/_book/docs/img/4d9fbb6b23cf91f72dd201cf3a52f475.png differ diff --git a/_book/docs/img/4e0797b4100df465293bf0c8f24a097b.png b/_book/docs/img/4e0797b4100df465293bf0c8f24a097b.png new file mode 100644 index 0000000000000000000000000000000000000000..b0c1400ee28b3d6da29c1ecdba61669d11eb65d4 Binary files /dev/null and b/_book/docs/img/4e0797b4100df465293bf0c8f24a097b.png differ diff --git a/_book/docs/img/4e480a29eb679b62ed97f748fc9acdd7.png b/_book/docs/img/4e480a29eb679b62ed97f748fc9acdd7.png new file mode 100644 index 0000000000000000000000000000000000000000..d1b1e575663a37a18dcfad7e076abac6846ad844 Binary files /dev/null and b/_book/docs/img/4e480a29eb679b62ed97f748fc9acdd7.png differ diff --git a/_book/docs/img/4e86bb665dcf8b8997d807441dbd60cd.png b/_book/docs/img/4e86bb665dcf8b8997d807441dbd60cd.png new file mode 100644 index 0000000000000000000000000000000000000000..32fe50d985b88ae8b237ec36ce64529d5b7fbf1a Binary files /dev/null and b/_book/docs/img/4e86bb665dcf8b8997d807441dbd60cd.png differ diff --git a/_book/docs/img/4e980984ef171e4c624f56ebeb3277c7.png b/_book/docs/img/4e980984ef171e4c624f56ebeb3277c7.png new file mode 100644 index 0000000000000000000000000000000000000000..3ec7cba088d0fd1b79e713221dadbfa55deeab65 Binary files /dev/null and b/_book/docs/img/4e980984ef171e4c624f56ebeb3277c7.png differ diff --git a/_book/docs/img/4f0a47acf91c1135738d76e1c06eec3a.png b/_book/docs/img/4f0a47acf91c1135738d76e1c06eec3a.png new file mode 100644 index 0000000000000000000000000000000000000000..024ca50a098db419eead35d0ea679ec7098cadb3 Binary files /dev/null and b/_book/docs/img/4f0a47acf91c1135738d76e1c06eec3a.png differ diff --git a/_book/docs/img/4f9a7d54cb4f539c606eaef8fd65b8ed.png b/_book/docs/img/4f9a7d54cb4f539c606eaef8fd65b8ed.png new file mode 100644 index 0000000000000000000000000000000000000000..9ecad83db4b5184b6c94598b3d41b783e6a838f0 Binary files /dev/null and b/_book/docs/img/4f9a7d54cb4f539c606eaef8fd65b8ed.png differ diff --git a/_book/docs/img/4feb8b1885ea3a6c0945d7d32d15e8ff.png b/_book/docs/img/4feb8b1885ea3a6c0945d7d32d15e8ff.png new file mode 100644 index 0000000000000000000000000000000000000000..bd7a68351d5c4c07accfd056e98f41d66afba514 Binary files /dev/null and b/_book/docs/img/4feb8b1885ea3a6c0945d7d32d15e8ff.png differ diff --git a/_book/docs/img/4ffe26c8f949643669a5c295958616cf.png b/_book/docs/img/4ffe26c8f949643669a5c295958616cf.png new file mode 100644 index 0000000000000000000000000000000000000000..09c92c333a0c3656b89df03208ca75104dfb7a30 Binary files /dev/null and b/_book/docs/img/4ffe26c8f949643669a5c295958616cf.png differ diff --git a/_book/docs/img/5016b6014148674f85d6fdba7bc5bb5e.png b/_book/docs/img/5016b6014148674f85d6fdba7bc5bb5e.png new file mode 100644 index 0000000000000000000000000000000000000000..9d2c0e45da15f3a5c47fcda3aef00f385be6a2ef Binary files /dev/null and b/_book/docs/img/5016b6014148674f85d6fdba7bc5bb5e.png differ diff --git a/_book/docs/img/50ab118d473b61d3d08773d6ea65a8ac.png b/_book/docs/img/50ab118d473b61d3d08773d6ea65a8ac.png new file mode 100644 index 0000000000000000000000000000000000000000..384dbd88dd2267200b26dc81bb0136135a2a432e Binary files /dev/null and b/_book/docs/img/50ab118d473b61d3d08773d6ea65a8ac.png differ diff --git a/_book/docs/img/50ffc4ae0babeef44a73e82cfe49bb30.png b/_book/docs/img/50ffc4ae0babeef44a73e82cfe49bb30.png new file mode 100644 index 0000000000000000000000000000000000000000..1504f0712c917e8ebd97d2cab6a0c15694dc71b6 Binary files /dev/null and b/_book/docs/img/50ffc4ae0babeef44a73e82cfe49bb30.png differ diff --git a/_book/docs/img/510cd4b11aa5f23be76d594a9ad782d6.png b/_book/docs/img/510cd4b11aa5f23be76d594a9ad782d6.png new file mode 100644 index 0000000000000000000000000000000000000000..c907e65f59f78319c7416f289bd3a394aab8a814 Binary files /dev/null and b/_book/docs/img/510cd4b11aa5f23be76d594a9ad782d6.png differ diff --git a/_book/docs/img/5113c12752dd029f29a28c6f0660cde1.png b/_book/docs/img/5113c12752dd029f29a28c6f0660cde1.png new file mode 100644 index 0000000000000000000000000000000000000000..8db5d2e0416895c68b358b927531ef5a658b9ccc Binary files /dev/null and b/_book/docs/img/5113c12752dd029f29a28c6f0660cde1.png differ diff --git a/_book/docs/img/51192310b3785dec5f60b6d59717a7a6.png b/_book/docs/img/51192310b3785dec5f60b6d59717a7a6.png new file mode 100644 index 0000000000000000000000000000000000000000..300be9cce286c5e12bb493edced4251b091d7b58 Binary files /dev/null and b/_book/docs/img/51192310b3785dec5f60b6d59717a7a6.png differ diff --git a/_book/docs/img/517f5b10646cf257d0fd0413cb54c3e9.png b/_book/docs/img/517f5b10646cf257d0fd0413cb54c3e9.png new file mode 100644 index 0000000000000000000000000000000000000000..52fc966bb33432537ecf368144464e5353a0c2bb Binary files /dev/null and b/_book/docs/img/517f5b10646cf257d0fd0413cb54c3e9.png differ diff --git a/_book/docs/img/51902d01ed097ad499a4e6eb984d3e86.png b/_book/docs/img/51902d01ed097ad499a4e6eb984d3e86.png new file mode 100644 index 0000000000000000000000000000000000000000..21ddda0d370302bcad2646b1866aa2b7b09e0d6a Binary files /dev/null and b/_book/docs/img/51902d01ed097ad499a4e6eb984d3e86.png differ diff --git a/_book/docs/img/51e7561422b1e74237ea14e916cffc78.png b/_book/docs/img/51e7561422b1e74237ea14e916cffc78.png new file mode 100644 index 0000000000000000000000000000000000000000..216fe176c405480562a31c5cec62dbb76daa6d85 Binary files /dev/null and b/_book/docs/img/51e7561422b1e74237ea14e916cffc78.png differ diff --git a/_book/docs/img/5262199c26e59a11bfa467901c29122a.png b/_book/docs/img/5262199c26e59a11bfa467901c29122a.png new file mode 100644 index 0000000000000000000000000000000000000000..fad3ae5c6cc674e951d298491e05aa8b1bd2b55e Binary files /dev/null and b/_book/docs/img/5262199c26e59a11bfa467901c29122a.png differ diff --git a/_book/docs/img/529405d6cc5cbeb813be69b57b0e45b1.png b/_book/docs/img/529405d6cc5cbeb813be69b57b0e45b1.png new file mode 100644 index 0000000000000000000000000000000000000000..e2737b77dcf26f671567e6cdccd963ecf195b188 Binary files /dev/null and b/_book/docs/img/529405d6cc5cbeb813be69b57b0e45b1.png differ diff --git a/_book/docs/img/52c8f25cfabbe64b4ed7e579d9a27e4a.png b/_book/docs/img/52c8f25cfabbe64b4ed7e579d9a27e4a.png new file mode 100644 index 0000000000000000000000000000000000000000..184e714a14109a58d490b016e295250500f431ae Binary files /dev/null and b/_book/docs/img/52c8f25cfabbe64b4ed7e579d9a27e4a.png differ diff --git a/_book/docs/img/52f1314a06269a0dc317f758c8e8cdab.png b/_book/docs/img/52f1314a06269a0dc317f758c8e8cdab.png new file mode 100644 index 0000000000000000000000000000000000000000..eedc20587bc138b551ceefdb14822bebd727c5af Binary files /dev/null and b/_book/docs/img/52f1314a06269a0dc317f758c8e8cdab.png differ diff --git a/_book/docs/img/52fecb33c2f168630e9a8f7c95aaf517.png b/_book/docs/img/52fecb33c2f168630e9a8f7c95aaf517.png new file mode 100644 index 0000000000000000000000000000000000000000..ce88b751e9430c5e24b545ed6c063fbe7c96c13a Binary files /dev/null and b/_book/docs/img/52fecb33c2f168630e9a8f7c95aaf517.png differ diff --git a/_book/docs/img/53056397d59c4378696296d359f20adc.png b/_book/docs/img/53056397d59c4378696296d359f20adc.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec0d2cefea8de2add9c215c5d2714914bfc55a7 Binary files /dev/null and b/_book/docs/img/53056397d59c4378696296d359f20adc.png differ diff --git a/_book/docs/img/53bcd8c2d2c69aceb7db6677802be6b1.png b/_book/docs/img/53bcd8c2d2c69aceb7db6677802be6b1.png new file mode 100644 index 0000000000000000000000000000000000000000..f6b1c1561b0dd9e540a700e2865ed690f4fee79e Binary files /dev/null and b/_book/docs/img/53bcd8c2d2c69aceb7db6677802be6b1.png differ diff --git a/_book/docs/img/53dc09446080b42329a76d4ecbb64aa3.png b/_book/docs/img/53dc09446080b42329a76d4ecbb64aa3.png new file mode 100644 index 0000000000000000000000000000000000000000..bd94dc363d18b78f1b103cfcf9cc147bb653c7b6 Binary files /dev/null and b/_book/docs/img/53dc09446080b42329a76d4ecbb64aa3.png differ diff --git a/_book/docs/img/544adf1331ba8dc0c6391bf07ba6df8c.png b/_book/docs/img/544adf1331ba8dc0c6391bf07ba6df8c.png new file mode 100644 index 0000000000000000000000000000000000000000..e23cb1aa931eb91e5e392fd63a7fc46c2da35efb Binary files /dev/null and b/_book/docs/img/544adf1331ba8dc0c6391bf07ba6df8c.png differ diff --git a/_book/docs/img/5460742929164e737a1b4c1990b75fc3.png b/_book/docs/img/5460742929164e737a1b4c1990b75fc3.png new file mode 100644 index 0000000000000000000000000000000000000000..a32f4814387e77cc2bf1d7aa0da55f87ab08cc35 Binary files /dev/null and b/_book/docs/img/5460742929164e737a1b4c1990b75fc3.png differ diff --git a/_book/docs/img/5574e9e4660196e59606fe9d673097b7.png b/_book/docs/img/5574e9e4660196e59606fe9d673097b7.png new file mode 100644 index 0000000000000000000000000000000000000000..777a4bfa595d6b668ab6d6d4874f93a1f629a940 Binary files /dev/null and b/_book/docs/img/5574e9e4660196e59606fe9d673097b7.png differ diff --git a/_book/docs/img/557f2cc00416c6f64286e93532f50121.png b/_book/docs/img/557f2cc00416c6f64286e93532f50121.png new file mode 100644 index 0000000000000000000000000000000000000000..78e7a8f2bb4744453596d956c153982b7e16bb2b Binary files /dev/null and b/_book/docs/img/557f2cc00416c6f64286e93532f50121.png differ diff --git a/_book/docs/img/55c6a94e74c9a00da3a400ae60e3bf41.png b/_book/docs/img/55c6a94e74c9a00da3a400ae60e3bf41.png new file mode 100644 index 0000000000000000000000000000000000000000..f436c146d54075101c2695e08c96c4eaf92982dc Binary files /dev/null and b/_book/docs/img/55c6a94e74c9a00da3a400ae60e3bf41.png differ diff --git a/_book/docs/img/56321b27a391110651e26fae3d93064e.png b/_book/docs/img/56321b27a391110651e26fae3d93064e.png new file mode 100644 index 0000000000000000000000000000000000000000..b1fd1c77db1ac18a03b5e0e1aadc7387048923f7 Binary files /dev/null and b/_book/docs/img/56321b27a391110651e26fae3d93064e.png differ diff --git a/_book/docs/img/5653420f4acd0e8a49be80d5d413bd10.png b/_book/docs/img/5653420f4acd0e8a49be80d5d413bd10.png new file mode 100644 index 0000000000000000000000000000000000000000..9007d265bc82dc2bf2b3ecf0ae7e66eb4b1dad10 Binary files /dev/null and b/_book/docs/img/5653420f4acd0e8a49be80d5d413bd10.png differ diff --git a/_book/docs/img/5665233091dd783791b6dd32107e61ec.png b/_book/docs/img/5665233091dd783791b6dd32107e61ec.png new file mode 100644 index 0000000000000000000000000000000000000000..c3c7d2b6ede6ca3c3ce4d696b9533656c0b4379f Binary files /dev/null and b/_book/docs/img/5665233091dd783791b6dd32107e61ec.png differ diff --git a/_book/docs/img/56b25600afa13ee05e76062ab09ee470.png b/_book/docs/img/56b25600afa13ee05e76062ab09ee470.png new file mode 100644 index 0000000000000000000000000000000000000000..3909146b7226874ff3466fa025bf192547312523 Binary files /dev/null and b/_book/docs/img/56b25600afa13ee05e76062ab09ee470.png differ diff --git a/_book/docs/img/56c21932bdeb67b5407d18238e8ec7f3.png b/_book/docs/img/56c21932bdeb67b5407d18238e8ec7f3.png new file mode 100644 index 0000000000000000000000000000000000000000..8cd20c069ff5e9a4348039f39420b3b925e8a501 Binary files /dev/null and b/_book/docs/img/56c21932bdeb67b5407d18238e8ec7f3.png differ diff --git a/_book/docs/img/56d89ff1e02ecf30404a57092adae96d.png b/_book/docs/img/56d89ff1e02ecf30404a57092adae96d.png new file mode 100644 index 0000000000000000000000000000000000000000..853725b7522656243060f7f4141e36ef050ef5f9 Binary files /dev/null and b/_book/docs/img/56d89ff1e02ecf30404a57092adae96d.png differ diff --git a/_book/docs/img/56eeecad0f9627fae21bc6b196391ba7.png b/_book/docs/img/56eeecad0f9627fae21bc6b196391ba7.png new file mode 100644 index 0000000000000000000000000000000000000000..a1f055abdc8bf32a46915a76cfda1b10f15b8f89 Binary files /dev/null and b/_book/docs/img/56eeecad0f9627fae21bc6b196391ba7.png differ diff --git a/_book/docs/img/572645049ee5ab43733f62fc45312843.png b/_book/docs/img/572645049ee5ab43733f62fc45312843.png new file mode 100644 index 0000000000000000000000000000000000000000..65e8914b0d2274876fe310149ab772e87fcb0c55 Binary files /dev/null and b/_book/docs/img/572645049ee5ab43733f62fc45312843.png differ diff --git a/_book/docs/img/57b0d20488fb6cdd9ed2e8f573fcb7bb.png b/_book/docs/img/57b0d20488fb6cdd9ed2e8f573fcb7bb.png new file mode 100644 index 0000000000000000000000000000000000000000..f756f0edb44aa18a3695a7025c2649c63cc60260 Binary files /dev/null and b/_book/docs/img/57b0d20488fb6cdd9ed2e8f573fcb7bb.png differ diff --git a/_book/docs/img/5844f1567aec337f6ba990bc855c348a.png b/_book/docs/img/5844f1567aec337f6ba990bc855c348a.png new file mode 100644 index 0000000000000000000000000000000000000000..95c06ec89ce7732a3fe29a587163cec6c97d99c3 Binary files /dev/null and b/_book/docs/img/5844f1567aec337f6ba990bc855c348a.png differ diff --git a/_book/docs/img/5881da97228cb042e5934f836edfd06c.png b/_book/docs/img/5881da97228cb042e5934f836edfd06c.png new file mode 100644 index 0000000000000000000000000000000000000000..22fe637226a6fcdfe2a20e29d282dd006d60ca03 Binary files /dev/null and b/_book/docs/img/5881da97228cb042e5934f836edfd06c.png differ diff --git a/_book/docs/img/590715bab1c8704d5a4c16437c011ed5.png b/_book/docs/img/590715bab1c8704d5a4c16437c011ed5.png new file mode 100644 index 0000000000000000000000000000000000000000..4533bdff99c22a6561f4d9f308d8ab41a5e1547b Binary files /dev/null and b/_book/docs/img/590715bab1c8704d5a4c16437c011ed5.png differ diff --git a/_book/docs/img/596a395127f6b3d5c9d1deac3f676680.png b/_book/docs/img/596a395127f6b3d5c9d1deac3f676680.png new file mode 100644 index 0000000000000000000000000000000000000000..4511f6b40eba46aff565602a2844037398a04354 Binary files /dev/null and b/_book/docs/img/596a395127f6b3d5c9d1deac3f676680.png differ diff --git a/_book/docs/img/599297cd25b4f282b1340e8e61e2e087.png b/_book/docs/img/599297cd25b4f282b1340e8e61e2e087.png new file mode 100644 index 0000000000000000000000000000000000000000..f9eb98ccafdc16148d173de2d210253bc160d516 Binary files /dev/null and b/_book/docs/img/599297cd25b4f282b1340e8e61e2e087.png differ diff --git a/_book/docs/img/5a2430ba8091036f8e9e3308aa845de8.png b/_book/docs/img/5a2430ba8091036f8e9e3308aa845de8.png new file mode 100644 index 0000000000000000000000000000000000000000..a1514ea19581a767ef92d6410d294398d9b2655c Binary files /dev/null and b/_book/docs/img/5a2430ba8091036f8e9e3308aa845de8.png differ diff --git a/_book/docs/img/5a26f77375b52645c2387aec1f77a777.png b/_book/docs/img/5a26f77375b52645c2387aec1f77a777.png new file mode 100644 index 0000000000000000000000000000000000000000..8cdcac6a7e94460b1d7b30a1febb757dfa132f94 Binary files /dev/null and b/_book/docs/img/5a26f77375b52645c2387aec1f77a777.png differ diff --git a/_book/docs/img/5b2694c5d35f9fdb42b43bb1f38ec29c.png b/_book/docs/img/5b2694c5d35f9fdb42b43bb1f38ec29c.png new file mode 100644 index 0000000000000000000000000000000000000000..8f6f3ee0a609e1ec88da611d0cbeaf7690eb6dc0 Binary files /dev/null and b/_book/docs/img/5b2694c5d35f9fdb42b43bb1f38ec29c.png differ diff --git a/_book/docs/img/5b8558c08a5996468dcd0d1a119ac76b.png b/_book/docs/img/5b8558c08a5996468dcd0d1a119ac76b.png new file mode 100644 index 0000000000000000000000000000000000000000..155c6bfb32bb8648407aa11b9b0a4cd8b1f840a8 Binary files /dev/null and b/_book/docs/img/5b8558c08a5996468dcd0d1a119ac76b.png differ diff --git a/_book/docs/img/5bf127e31dfc7f61e3134780f75114ff.png b/_book/docs/img/5bf127e31dfc7f61e3134780f75114ff.png new file mode 100644 index 0000000000000000000000000000000000000000..b30961f5942a87114e0a38d0f57029c175e023f4 Binary files /dev/null and b/_book/docs/img/5bf127e31dfc7f61e3134780f75114ff.png differ diff --git a/_book/docs/img/5c0acf7979c7bc1e89dc413017b70870.png b/_book/docs/img/5c0acf7979c7bc1e89dc413017b70870.png new file mode 100644 index 0000000000000000000000000000000000000000..933e257f56ae490974a683d131d64dd1cf97df35 Binary files /dev/null and b/_book/docs/img/5c0acf7979c7bc1e89dc413017b70870.png differ diff --git a/_book/docs/img/5d1d35707b32fd37e1e218e8b1df1771.png b/_book/docs/img/5d1d35707b32fd37e1e218e8b1df1771.png new file mode 100644 index 0000000000000000000000000000000000000000..95e465d3c591c6bdd352c8595d397692a3883b27 Binary files /dev/null and b/_book/docs/img/5d1d35707b32fd37e1e218e8b1df1771.png differ diff --git a/_book/docs/img/5d200a6bcc883fcfa57dac51301bc2e3.png b/_book/docs/img/5d200a6bcc883fcfa57dac51301bc2e3.png new file mode 100644 index 0000000000000000000000000000000000000000..dd7d6a22a17b7d5a67a259e86f0be3d48ddad78a Binary files /dev/null and b/_book/docs/img/5d200a6bcc883fcfa57dac51301bc2e3.png differ diff --git a/_book/docs/img/5d98850d2ad30c43029645c8c0486059.png b/_book/docs/img/5d98850d2ad30c43029645c8c0486059.png new file mode 100644 index 0000000000000000000000000000000000000000..979006b7dd1a5ee1f93fe742364d23d70df834dc Binary files /dev/null and b/_book/docs/img/5d98850d2ad30c43029645c8c0486059.png differ diff --git a/_book/docs/img/5dd66b504685d06e7b88c8f8a71d39ba.png b/_book/docs/img/5dd66b504685d06e7b88c8f8a71d39ba.png new file mode 100644 index 0000000000000000000000000000000000000000..9737d2f48a39de0664e045c283cbc2775c8edb5c Binary files /dev/null and b/_book/docs/img/5dd66b504685d06e7b88c8f8a71d39ba.png differ diff --git a/_book/docs/img/5e2e81b44d67af322056491cf32bb8da.png b/_book/docs/img/5e2e81b44d67af322056491cf32bb8da.png new file mode 100644 index 0000000000000000000000000000000000000000..c2a1f0fcef890a437165dd919e608c5f4bde23d0 Binary files /dev/null and b/_book/docs/img/5e2e81b44d67af322056491cf32bb8da.png differ diff --git a/_book/docs/img/5e3cf2019e5c2c58b6dd5868fffb9e81.png b/_book/docs/img/5e3cf2019e5c2c58b6dd5868fffb9e81.png new file mode 100644 index 0000000000000000000000000000000000000000..9ccb37f11b6773dd0fc7eb4ec65d325d4914820f Binary files /dev/null and b/_book/docs/img/5e3cf2019e5c2c58b6dd5868fffb9e81.png differ diff --git a/_book/docs/img/5e63fee9a28bb3e02eb772646de82b5c.png b/_book/docs/img/5e63fee9a28bb3e02eb772646de82b5c.png new file mode 100644 index 0000000000000000000000000000000000000000..c38e5f1950cbfe8ddcf8b523fe3c41657d0da3f4 Binary files /dev/null and b/_book/docs/img/5e63fee9a28bb3e02eb772646de82b5c.png differ diff --git a/_book/docs/img/5e9b34b344fc5f08d74d5156c419f471.png b/_book/docs/img/5e9b34b344fc5f08d74d5156c419f471.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec839c13c52c0c0a5c460e66efd50b048c9496b Binary files /dev/null and b/_book/docs/img/5e9b34b344fc5f08d74d5156c419f471.png differ diff --git a/_book/docs/img/5ec08a62b534de16956701e85c41e6b5.png b/_book/docs/img/5ec08a62b534de16956701e85c41e6b5.png new file mode 100644 index 0000000000000000000000000000000000000000..d0be4ecb1b9c92f960933e60b3f2a99f618e4e4a Binary files /dev/null and b/_book/docs/img/5ec08a62b534de16956701e85c41e6b5.png differ diff --git a/_book/docs/img/5f13fe556b8940c2e698facdc219d16a.png b/_book/docs/img/5f13fe556b8940c2e698facdc219d16a.png new file mode 100644 index 0000000000000000000000000000000000000000..4661f5a84e989e03ee216770401c0383dd1e3048 Binary files /dev/null and b/_book/docs/img/5f13fe556b8940c2e698facdc219d16a.png differ diff --git a/_book/docs/img/5f3552f35a06cac8dfa02c21fd48c852.png b/_book/docs/img/5f3552f35a06cac8dfa02c21fd48c852.png new file mode 100644 index 0000000000000000000000000000000000000000..3782a5ffd5bdda57d50db155982a968735c515ef Binary files /dev/null and b/_book/docs/img/5f3552f35a06cac8dfa02c21fd48c852.png differ diff --git a/_book/docs/img/5f6c85f0240f3ec56519dde74a715dba.png b/_book/docs/img/5f6c85f0240f3ec56519dde74a715dba.png new file mode 100644 index 0000000000000000000000000000000000000000..e00b3cb05344e5263e57568d47f6fa66b892ef6d Binary files /dev/null and b/_book/docs/img/5f6c85f0240f3ec56519dde74a715dba.png differ diff --git a/_book/docs/img/5f87ce250e2ea1a803a3aeda446eca15.png b/_book/docs/img/5f87ce250e2ea1a803a3aeda446eca15.png new file mode 100644 index 0000000000000000000000000000000000000000..83bff45db9ddd03752b5b735aa3df33effb7b4f9 Binary files /dev/null and b/_book/docs/img/5f87ce250e2ea1a803a3aeda446eca15.png differ diff --git a/_book/docs/img/604dc2f6326d049dca30995958a84ad2.png b/_book/docs/img/604dc2f6326d049dca30995958a84ad2.png new file mode 100644 index 0000000000000000000000000000000000000000..47454e3695f1af043fb50dee1118d04e827f1a1f Binary files /dev/null and b/_book/docs/img/604dc2f6326d049dca30995958a84ad2.png differ diff --git a/_book/docs/img/60958029f56e4c49c6a21082ea151191.png b/_book/docs/img/60958029f56e4c49c6a21082ea151191.png new file mode 100644 index 0000000000000000000000000000000000000000..8e7f4510bf8f7ed3cc0f99abaf8a0fe50351d3cd Binary files /dev/null and b/_book/docs/img/60958029f56e4c49c6a21082ea151191.png differ diff --git a/_book/docs/img/611650a65dd2baf63b32d99fbe8e4a8a.png b/_book/docs/img/611650a65dd2baf63b32d99fbe8e4a8a.png new file mode 100644 index 0000000000000000000000000000000000000000..61ef9ab09b97d26a37a69da3e30a2257a46f3718 Binary files /dev/null and b/_book/docs/img/611650a65dd2baf63b32d99fbe8e4a8a.png differ diff --git a/_book/docs/img/618ce3d47266d9b45262489065b68cf7.png b/_book/docs/img/618ce3d47266d9b45262489065b68cf7.png new file mode 100644 index 0000000000000000000000000000000000000000..b0eebf0c7c53be5c41169de74f0943739fc0e232 Binary files /dev/null and b/_book/docs/img/618ce3d47266d9b45262489065b68cf7.png differ diff --git a/_book/docs/img/618f6f4ba2a434609a1a9de7a9725e49.png b/_book/docs/img/618f6f4ba2a434609a1a9de7a9725e49.png new file mode 100644 index 0000000000000000000000000000000000000000..4cb5166817f387be4b8ef18366c8b94ae0128c69 Binary files /dev/null and b/_book/docs/img/618f6f4ba2a434609a1a9de7a9725e49.png differ diff --git a/_book/docs/img/61dd95f1efb048c48f6ab843e79120d0.png b/_book/docs/img/61dd95f1efb048c48f6ab843e79120d0.png new file mode 100644 index 0000000000000000000000000000000000000000..49bfa2816ff514a9dcc89b1e4e9665f0f050aec9 Binary files /dev/null and b/_book/docs/img/61dd95f1efb048c48f6ab843e79120d0.png differ diff --git a/_book/docs/img/62073039b38c0dfa370251cfe07ca5e5.png b/_book/docs/img/62073039b38c0dfa370251cfe07ca5e5.png new file mode 100644 index 0000000000000000000000000000000000000000..74c886fa7ed07a2796ec2dbfccb5c8a5077c0838 Binary files /dev/null and b/_book/docs/img/62073039b38c0dfa370251cfe07ca5e5.png differ diff --git a/_book/docs/img/6224c1a367d53cc7bb5c5536af96ec6e.png b/_book/docs/img/6224c1a367d53cc7bb5c5536af96ec6e.png new file mode 100644 index 0000000000000000000000000000000000000000..4df75ad33585ee9658cc9268247e79ef5d1d8365 Binary files /dev/null and b/_book/docs/img/6224c1a367d53cc7bb5c5536af96ec6e.png differ diff --git a/_book/docs/img/62313a9f27e05c60c700ec9625e27d02.png b/_book/docs/img/62313a9f27e05c60c700ec9625e27d02.png new file mode 100644 index 0000000000000000000000000000000000000000..421a559c4e24013962003d99381b1f04f49b078b Binary files /dev/null and b/_book/docs/img/62313a9f27e05c60c700ec9625e27d02.png differ diff --git a/_book/docs/img/6261dd255633edf09ab3d7245ccaf2c1.png b/_book/docs/img/6261dd255633edf09ab3d7245ccaf2c1.png new file mode 100644 index 0000000000000000000000000000000000000000..9e8edb4f24c7e1eb6723910fb2c6db15f9801eb7 Binary files /dev/null and b/_book/docs/img/6261dd255633edf09ab3d7245ccaf2c1.png differ diff --git a/_book/docs/img/62b879dea0345cb8767d9cd4fb041f97.png b/_book/docs/img/62b879dea0345cb8767d9cd4fb041f97.png new file mode 100644 index 0000000000000000000000000000000000000000..7890d458e72945391941e5bc1026ba6b7b5f272f Binary files /dev/null and b/_book/docs/img/62b879dea0345cb8767d9cd4fb041f97.png differ diff --git a/_book/docs/img/62d2b5c8435d31dff0a7fc689c288e8c.png b/_book/docs/img/62d2b5c8435d31dff0a7fc689c288e8c.png new file mode 100644 index 0000000000000000000000000000000000000000..9e39ca3f861dcbf9cdb4afaea81e07fa3fdc8f35 Binary files /dev/null and b/_book/docs/img/62d2b5c8435d31dff0a7fc689c288e8c.png differ diff --git a/_book/docs/img/6314765d395236bbba1552cc65c1228c.png b/_book/docs/img/6314765d395236bbba1552cc65c1228c.png new file mode 100644 index 0000000000000000000000000000000000000000..4eeff1aea23f26404fd95ba20033584e667f686a Binary files /dev/null and b/_book/docs/img/6314765d395236bbba1552cc65c1228c.png differ diff --git a/_book/docs/img/631b8ad9816cfdd87ba106377c86c7a4.png b/_book/docs/img/631b8ad9816cfdd87ba106377c86c7a4.png new file mode 100644 index 0000000000000000000000000000000000000000..077e15c35b2cf863915b7c80cfddb09857669bf0 Binary files /dev/null and b/_book/docs/img/631b8ad9816cfdd87ba106377c86c7a4.png differ diff --git a/_book/docs/img/640bc8c28d8cd3035fbe0c4c1018d2d1.png b/_book/docs/img/640bc8c28d8cd3035fbe0c4c1018d2d1.png new file mode 100644 index 0000000000000000000000000000000000000000..f175ffe7bc58f30409e0d75f6a888bdb56e0a0ed Binary files /dev/null and b/_book/docs/img/640bc8c28d8cd3035fbe0c4c1018d2d1.png differ diff --git a/_book/docs/img/6427e1b107996a8eb9c401e1aa76bf87.png b/_book/docs/img/6427e1b107996a8eb9c401e1aa76bf87.png new file mode 100644 index 0000000000000000000000000000000000000000..6046611953ce4e17ec8469d53750db6def7a1f2a Binary files /dev/null and b/_book/docs/img/6427e1b107996a8eb9c401e1aa76bf87.png differ diff --git a/_book/docs/img/645965e7ebb61697ff42cc06214ca5af.png b/_book/docs/img/645965e7ebb61697ff42cc06214ca5af.png new file mode 100644 index 0000000000000000000000000000000000000000..eb598083963b6a1281bec0d527e0a1b677b1f3b6 Binary files /dev/null and b/_book/docs/img/645965e7ebb61697ff42cc06214ca5af.png differ diff --git a/_book/docs/img/64d10619e1633359be63480f18d60b90.png b/_book/docs/img/64d10619e1633359be63480f18d60b90.png new file mode 100644 index 0000000000000000000000000000000000000000..a548f5acbfad2aa44736a54713a7b7f4bd59a900 Binary files /dev/null and b/_book/docs/img/64d10619e1633359be63480f18d60b90.png differ diff --git a/_book/docs/img/655bbae75a3608d2016397c70682f7d4.png b/_book/docs/img/655bbae75a3608d2016397c70682f7d4.png new file mode 100644 index 0000000000000000000000000000000000000000..47a618ea3628fff8720de9cd7d5fa42fd77cce05 Binary files /dev/null and b/_book/docs/img/655bbae75a3608d2016397c70682f7d4.png differ diff --git a/_book/docs/img/6564cc179b8bafb5577b9762c905010c.png b/_book/docs/img/6564cc179b8bafb5577b9762c905010c.png new file mode 100644 index 0000000000000000000000000000000000000000..19560bffef2d905302c148c4fcedfdd6bf2d1f08 Binary files /dev/null and b/_book/docs/img/6564cc179b8bafb5577b9762c905010c.png differ diff --git a/_book/docs/img/65770b50cd2119e84c6a852b44cf403d.png b/_book/docs/img/65770b50cd2119e84c6a852b44cf403d.png new file mode 100644 index 0000000000000000000000000000000000000000..50fab030a41c7b2206e86563c4f1f6d2fe75009a Binary files /dev/null and b/_book/docs/img/65770b50cd2119e84c6a852b44cf403d.png differ diff --git a/_book/docs/img/659964d0e0d080d80881d6eb74aaaf7e.png b/_book/docs/img/659964d0e0d080d80881d6eb74aaaf7e.png new file mode 100644 index 0000000000000000000000000000000000000000..378e38fc6da9d1cd5e3cf1865fe331eeb0ed6229 Binary files /dev/null and b/_book/docs/img/659964d0e0d080d80881d6eb74aaaf7e.png differ diff --git a/_book/docs/img/662e9b0c090a4f28c82eb779aabdc9c8.png b/_book/docs/img/662e9b0c090a4f28c82eb779aabdc9c8.png new file mode 100644 index 0000000000000000000000000000000000000000..afd2f2700a3073f4be36d6ceb9544fed49b72c86 Binary files /dev/null and b/_book/docs/img/662e9b0c090a4f28c82eb779aabdc9c8.png differ diff --git a/_book/docs/img/669c2de32e70a30ad93c28d4afd41491.png b/_book/docs/img/669c2de32e70a30ad93c28d4afd41491.png new file mode 100644 index 0000000000000000000000000000000000000000..6a234607e27ec22c11a7b63f117ff8a8c73db1b1 Binary files /dev/null and b/_book/docs/img/669c2de32e70a30ad93c28d4afd41491.png differ diff --git a/_book/docs/img/66a70133eaa2327dce4cd61c485afcdb.png b/_book/docs/img/66a70133eaa2327dce4cd61c485afcdb.png new file mode 100644 index 0000000000000000000000000000000000000000..6fd449abfb80b6cbae5422d8e9e85e890eceb6b4 Binary files /dev/null and b/_book/docs/img/66a70133eaa2327dce4cd61c485afcdb.png differ diff --git a/_book/docs/img/66e7cbbe98ed69a6154c1adcd7ec4f6e.png b/_book/docs/img/66e7cbbe98ed69a6154c1adcd7ec4f6e.png new file mode 100644 index 0000000000000000000000000000000000000000..307c3304b44671f0e51c85dba1bde03137b0539a Binary files /dev/null and b/_book/docs/img/66e7cbbe98ed69a6154c1adcd7ec4f6e.png differ diff --git a/_book/docs/img/671787cdf6cd1dde3e748fae72d46779.png b/_book/docs/img/671787cdf6cd1dde3e748fae72d46779.png new file mode 100644 index 0000000000000000000000000000000000000000..cb898e5ad549a742a8e8a0f9245dc8edb47f3193 Binary files /dev/null and b/_book/docs/img/671787cdf6cd1dde3e748fae72d46779.png differ diff --git a/_book/docs/img/674c1579957cca4a644bc90fb8fbb2f3.png b/_book/docs/img/674c1579957cca4a644bc90fb8fbb2f3.png new file mode 100644 index 0000000000000000000000000000000000000000..567263c8fad8701b9b727ce30e27d1ddfe6bfb6e Binary files /dev/null and b/_book/docs/img/674c1579957cca4a644bc90fb8fbb2f3.png differ diff --git a/_book/docs/img/676537e7ead1101c5c0668a2adbc08d5.png b/_book/docs/img/676537e7ead1101c5c0668a2adbc08d5.png new file mode 100644 index 0000000000000000000000000000000000000000..29759b5112f7c9da924b0757842cbca2c0e83585 Binary files /dev/null and b/_book/docs/img/676537e7ead1101c5c0668a2adbc08d5.png differ diff --git a/_book/docs/img/677d8f883392679f3fba97024a259665.png b/_book/docs/img/677d8f883392679f3fba97024a259665.png new file mode 100644 index 0000000000000000000000000000000000000000..737ab0b6ccff5beaa0b3659ea112448738e45423 Binary files /dev/null and b/_book/docs/img/677d8f883392679f3fba97024a259665.png differ diff --git a/_book/docs/img/67f7d8117f3d6bf60fe4d5e03bca7b6e.png b/_book/docs/img/67f7d8117f3d6bf60fe4d5e03bca7b6e.png new file mode 100644 index 0000000000000000000000000000000000000000..898351f9e270d79492780f875146de366d5766cb Binary files /dev/null and b/_book/docs/img/67f7d8117f3d6bf60fe4d5e03bca7b6e.png differ diff --git a/_book/docs/img/6809ef73be513357f41ebe6d325265d5.png b/_book/docs/img/6809ef73be513357f41ebe6d325265d5.png new file mode 100644 index 0000000000000000000000000000000000000000..a69613768f83098ed5b5ae78dff4118f1203a2e0 Binary files /dev/null and b/_book/docs/img/6809ef73be513357f41ebe6d325265d5.png differ diff --git a/_book/docs/img/6867e53bf251ef0cb0e190c2e702d188.png b/_book/docs/img/6867e53bf251ef0cb0e190c2e702d188.png new file mode 100644 index 0000000000000000000000000000000000000000..10d6c281fcd3cc38caf79aca9be8430c55053619 Binary files /dev/null and b/_book/docs/img/6867e53bf251ef0cb0e190c2e702d188.png differ diff --git a/_book/docs/img/69a8b09a09599e563d1796eac13f945e.png b/_book/docs/img/69a8b09a09599e563d1796eac13f945e.png new file mode 100644 index 0000000000000000000000000000000000000000..0ea21fd0d76ae9541d07b74504752d1b86ad9039 --- /dev/null +++ b/_book/docs/img/69a8b09a09599e563d1796eac13f945e.png @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + coverage + + + coverage + + + unknown + + + unknown + + + + diff --git a/_book/docs/img/6a23362ee367dd144c2c8ea315b8dde0.png b/_book/docs/img/6a23362ee367dd144c2c8ea315b8dde0.png new file mode 100644 index 0000000000000000000000000000000000000000..34bd845f0a543cdda300e7a5a44de971bf5be5ec Binary files /dev/null and b/_book/docs/img/6a23362ee367dd144c2c8ea315b8dde0.png differ diff --git a/_book/docs/img/6a2d24148988c584ff47ac7c526b48ff.png b/_book/docs/img/6a2d24148988c584ff47ac7c526b48ff.png new file mode 100644 index 0000000000000000000000000000000000000000..42772878fe5a7d38cec0d5d6d87aaa0e6b3e16e4 Binary files /dev/null and b/_book/docs/img/6a2d24148988c584ff47ac7c526b48ff.png differ diff --git a/_book/docs/img/6a33d33154553990ed15338a6f9c7b35.png b/_book/docs/img/6a33d33154553990ed15338a6f9c7b35.png new file mode 100644 index 0000000000000000000000000000000000000000..f70b0a6843a83528020eabae3692c6982f54d2aa Binary files /dev/null and b/_book/docs/img/6a33d33154553990ed15338a6f9c7b35.png differ diff --git a/_book/docs/img/6ad15d363481e18f443e6709fc8d1368.png b/_book/docs/img/6ad15d363481e18f443e6709fc8d1368.png new file mode 100644 index 0000000000000000000000000000000000000000..641f917a572ffe5aa55e4990e5d11db8ae740cc1 Binary files /dev/null and b/_book/docs/img/6ad15d363481e18f443e6709fc8d1368.png differ diff --git a/_book/docs/img/6b48060a3ef4c055e75a74e6a396ebb9.png b/_book/docs/img/6b48060a3ef4c055e75a74e6a396ebb9.png new file mode 100644 index 0000000000000000000000000000000000000000..fa7a2ab7e86cc484b37d9ca17b53fae3b0c9d7ac Binary files /dev/null and b/_book/docs/img/6b48060a3ef4c055e75a74e6a396ebb9.png differ diff --git a/_book/docs/img/6b5837eb8878551d4881e94247d957e9.png b/_book/docs/img/6b5837eb8878551d4881e94247d957e9.png new file mode 100644 index 0000000000000000000000000000000000000000..d526409f76b434e35698d3e60c62749e5cf8f80b Binary files /dev/null and b/_book/docs/img/6b5837eb8878551d4881e94247d957e9.png differ diff --git a/_book/docs/img/6c431eb1e4bc729eceb4a6a36f0ea6b0.png b/_book/docs/img/6c431eb1e4bc729eceb4a6a36f0ea6b0.png new file mode 100644 index 0000000000000000000000000000000000000000..1cd97355cf04b1448e82f94e3b272c7ab3fefb47 Binary files /dev/null and b/_book/docs/img/6c431eb1e4bc729eceb4a6a36f0ea6b0.png differ diff --git a/_book/docs/img/6cad1c326921f33ce6d53e7f2ebd1158.png b/_book/docs/img/6cad1c326921f33ce6d53e7f2ebd1158.png new file mode 100644 index 0000000000000000000000000000000000000000..949158b9c0e1776e4a2d1abd36bd239d5f5f926c Binary files /dev/null and b/_book/docs/img/6cad1c326921f33ce6d53e7f2ebd1158.png differ diff --git a/_book/docs/img/6d49650d7eab0173612011fa6d81dc4e.png b/_book/docs/img/6d49650d7eab0173612011fa6d81dc4e.png new file mode 100644 index 0000000000000000000000000000000000000000..9a0c4f909e8613a36c3ac665dc5cb79429aae619 Binary files /dev/null and b/_book/docs/img/6d49650d7eab0173612011fa6d81dc4e.png differ diff --git a/_book/docs/img/6de450be845a1f48a3feae9ce8e7be6e.png b/_book/docs/img/6de450be845a1f48a3feae9ce8e7be6e.png new file mode 100644 index 0000000000000000000000000000000000000000..a22b6c72475d81bad072105fc71f33a64cf34c4d Binary files /dev/null and b/_book/docs/img/6de450be845a1f48a3feae9ce8e7be6e.png differ diff --git a/_book/docs/img/6deba2d9890a294d17564cce39fcbaef.png b/_book/docs/img/6deba2d9890a294d17564cce39fcbaef.png new file mode 100644 index 0000000000000000000000000000000000000000..3883afb5f01ccd5ef6fcb4b57623d8b3eee19e46 Binary files /dev/null and b/_book/docs/img/6deba2d9890a294d17564cce39fcbaef.png differ diff --git a/_book/docs/img/6dffd31bb67148d85ebfccbfc20abfd8.png b/_book/docs/img/6dffd31bb67148d85ebfccbfc20abfd8.png new file mode 100644 index 0000000000000000000000000000000000000000..042d04070db5675f69d789eb1f03bddfcaec59ee Binary files /dev/null and b/_book/docs/img/6dffd31bb67148d85ebfccbfc20abfd8.png differ diff --git a/_book/docs/img/6e17896087b8446f53400a1c8d39c0d6.png b/_book/docs/img/6e17896087b8446f53400a1c8d39c0d6.png new file mode 100644 index 0000000000000000000000000000000000000000..1b3cf1d11da71c7189791be52bbc5d7656cf5c31 Binary files /dev/null and b/_book/docs/img/6e17896087b8446f53400a1c8d39c0d6.png differ diff --git a/_book/docs/img/6e3e1e9c7013cd330bcb6380ef19ddf9.png b/_book/docs/img/6e3e1e9c7013cd330bcb6380ef19ddf9.png new file mode 100644 index 0000000000000000000000000000000000000000..e257602577047de608c6641be7b9f5fe470ed110 Binary files /dev/null and b/_book/docs/img/6e3e1e9c7013cd330bcb6380ef19ddf9.png differ diff --git a/_book/docs/img/6ea99225391da160a92dd9fd1fb01cd7.png b/_book/docs/img/6ea99225391da160a92dd9fd1fb01cd7.png new file mode 100644 index 0000000000000000000000000000000000000000..9abdfc0338b15ff7e60f7a25214a712fca5257dc Binary files /dev/null and b/_book/docs/img/6ea99225391da160a92dd9fd1fb01cd7.png differ diff --git a/_book/docs/img/6f52527c138db466f7fba27994ad67f8.png b/_book/docs/img/6f52527c138db466f7fba27994ad67f8.png new file mode 100644 index 0000000000000000000000000000000000000000..f187f24f7b5fc7ca8a66605ec0cacafb1a65148e Binary files /dev/null and b/_book/docs/img/6f52527c138db466f7fba27994ad67f8.png differ diff --git a/_book/docs/img/70117ebf119dd375e0def463921cc363.png b/_book/docs/img/70117ebf119dd375e0def463921cc363.png new file mode 100644 index 0000000000000000000000000000000000000000..4dc6e1779c04d609881e5f8888aeb30903fe188b Binary files /dev/null and b/_book/docs/img/70117ebf119dd375e0def463921cc363.png differ diff --git a/_book/docs/img/7042e9f430cefb3a9c62194cec839692.png b/_book/docs/img/7042e9f430cefb3a9c62194cec839692.png new file mode 100644 index 0000000000000000000000000000000000000000..fd3d092e3745753acf8c77830dbc33bdcb684f7c Binary files /dev/null and b/_book/docs/img/7042e9f430cefb3a9c62194cec839692.png differ diff --git a/_book/docs/img/705d87c5c620f8ade251682fceb074e3.png b/_book/docs/img/705d87c5c620f8ade251682fceb074e3.png new file mode 100644 index 0000000000000000000000000000000000000000..da9f825c19a55cee612c44695adbe9c096ba08e3 Binary files /dev/null and b/_book/docs/img/705d87c5c620f8ade251682fceb074e3.png differ diff --git a/_book/docs/img/70c613da170fdfd7665282f16becad56.png b/_book/docs/img/70c613da170fdfd7665282f16becad56.png new file mode 100644 index 0000000000000000000000000000000000000000..b4d3f764a20d02ce029c5e89c166246b9c84e6ef Binary files /dev/null and b/_book/docs/img/70c613da170fdfd7665282f16becad56.png differ diff --git a/_book/docs/img/7151cdf5255313b82b775852ed2aef73.png b/_book/docs/img/7151cdf5255313b82b775852ed2aef73.png new file mode 100644 index 0000000000000000000000000000000000000000..04b10453c6a97c78e154bf4e4097bbc9581f0bc6 Binary files /dev/null and b/_book/docs/img/7151cdf5255313b82b775852ed2aef73.png differ diff --git a/_book/docs/img/71c2f22b2aef83c58870637723d6f7ef.png b/_book/docs/img/71c2f22b2aef83c58870637723d6f7ef.png new file mode 100644 index 0000000000000000000000000000000000000000..10c3d9914a3c0a8255773ec6aab2c59b4a3721ce Binary files /dev/null and b/_book/docs/img/71c2f22b2aef83c58870637723d6f7ef.png differ diff --git a/_book/docs/img/72431eb6b6fe2dd27e2f6f9be7d91672.png b/_book/docs/img/72431eb6b6fe2dd27e2f6f9be7d91672.png new file mode 100644 index 0000000000000000000000000000000000000000..4b9e42d5a3cf9885ca0280d79339b92f35eb189b Binary files /dev/null and b/_book/docs/img/72431eb6b6fe2dd27e2f6f9be7d91672.png differ diff --git a/_book/docs/img/729f4c6815c7118c098b6925f2375918.png b/_book/docs/img/729f4c6815c7118c098b6925f2375918.png new file mode 100644 index 0000000000000000000000000000000000000000..75ed57e8a55b1260b2dd27361da3563a9c4f0a33 Binary files /dev/null and b/_book/docs/img/729f4c6815c7118c098b6925f2375918.png differ diff --git a/_book/docs/img/72a8c3cb5bafa1e02d93f68a624b6094.png b/_book/docs/img/72a8c3cb5bafa1e02d93f68a624b6094.png new file mode 100644 index 0000000000000000000000000000000000000000..f26025fe7a4353b0df3f272b4edf86761a9796d1 Binary files /dev/null and b/_book/docs/img/72a8c3cb5bafa1e02d93f68a624b6094.png differ diff --git a/_book/docs/img/72befe6a3da1a58465dbf55200aefd26.png b/_book/docs/img/72befe6a3da1a58465dbf55200aefd26.png new file mode 100644 index 0000000000000000000000000000000000000000..2f7aa2224f4566a487243dc501e79cec3c67d154 Binary files /dev/null and b/_book/docs/img/72befe6a3da1a58465dbf55200aefd26.png differ diff --git a/_book/docs/img/731943edb4428a3eb27c86d8d454d0e0.png b/_book/docs/img/731943edb4428a3eb27c86d8d454d0e0.png new file mode 100644 index 0000000000000000000000000000000000000000..bf17b1f97cc1f9d9cf3d3f65f2f105ea365c3cd8 Binary files /dev/null and b/_book/docs/img/731943edb4428a3eb27c86d8d454d0e0.png differ diff --git a/_book/docs/img/7355fc1627be101cc5ed59387d36b6a3.png b/_book/docs/img/7355fc1627be101cc5ed59387d36b6a3.png new file mode 100644 index 0000000000000000000000000000000000000000..a82c41818fa783280260e8388561166b851affc6 Binary files /dev/null and b/_book/docs/img/7355fc1627be101cc5ed59387d36b6a3.png differ diff --git a/_book/docs/img/7356a350b6fac674fc341d110380f723.png b/_book/docs/img/7356a350b6fac674fc341d110380f723.png new file mode 100644 index 0000000000000000000000000000000000000000..8a597b86c2deec58890ec7514236fee9a0c63e89 Binary files /dev/null and b/_book/docs/img/7356a350b6fac674fc341d110380f723.png differ diff --git a/_book/docs/img/738413ec37e13f47706eeda5de3b9dfb.png b/_book/docs/img/738413ec37e13f47706eeda5de3b9dfb.png new file mode 100644 index 0000000000000000000000000000000000000000..07e35638b48d0c0cb1843679764d2829e10625f6 Binary files /dev/null and b/_book/docs/img/738413ec37e13f47706eeda5de3b9dfb.png differ diff --git a/_book/docs/img/74017afb9b6459aed36b4c4a53df62e9.png b/_book/docs/img/74017afb9b6459aed36b4c4a53df62e9.png new file mode 100644 index 0000000000000000000000000000000000000000..9dba1c76f08e1463a4cb1b40560a67c24f7ff106 Binary files /dev/null and b/_book/docs/img/74017afb9b6459aed36b4c4a53df62e9.png differ diff --git a/_book/docs/img/743ce9a40d40e900e957589a9024f116.png b/_book/docs/img/743ce9a40d40e900e957589a9024f116.png new file mode 100644 index 0000000000000000000000000000000000000000..8181be88a0de350d6301e11a69fb3bde14449d64 Binary files /dev/null and b/_book/docs/img/743ce9a40d40e900e957589a9024f116.png differ diff --git a/_book/docs/img/74f87e79779a102e82a644227e50a2e4.png b/_book/docs/img/74f87e79779a102e82a644227e50a2e4.png new file mode 100644 index 0000000000000000000000000000000000000000..e42050d3e42fa18c97aa46e38d19dabc16fa6bc4 Binary files /dev/null and b/_book/docs/img/74f87e79779a102e82a644227e50a2e4.png differ diff --git a/_book/docs/img/75ca9285f50e058d4d85796b4d0b8e69.png b/_book/docs/img/75ca9285f50e058d4d85796b4d0b8e69.png new file mode 100644 index 0000000000000000000000000000000000000000..8f43c40df6bc86fe0b1bb5c31264db633745b776 Binary files /dev/null and b/_book/docs/img/75ca9285f50e058d4d85796b4d0b8e69.png differ diff --git a/_book/docs/img/75ff7ad133721fa954b7960ba4edc025.png b/_book/docs/img/75ff7ad133721fa954b7960ba4edc025.png new file mode 100644 index 0000000000000000000000000000000000000000..3c7c1d06b47d1e3c50cf52b713d78c480a274b81 Binary files /dev/null and b/_book/docs/img/75ff7ad133721fa954b7960ba4edc025.png differ diff --git a/_book/docs/img/75ffde23ab0100e58532632d19b84db0.png b/_book/docs/img/75ffde23ab0100e58532632d19b84db0.png new file mode 100644 index 0000000000000000000000000000000000000000..7da1ffe8ffa78c377faef665ec41870fdce05543 Binary files /dev/null and b/_book/docs/img/75ffde23ab0100e58532632d19b84db0.png differ diff --git a/_book/docs/img/768ab05f8c35931c200b6da1f8d92352.png b/_book/docs/img/768ab05f8c35931c200b6da1f8d92352.png new file mode 100644 index 0000000000000000000000000000000000000000..b2a4c178383072e963d80a050a0db0d1bae7e6ed Binary files /dev/null and b/_book/docs/img/768ab05f8c35931c200b6da1f8d92352.png differ diff --git a/_book/docs/img/7710cb575c3aefd0769c3f6aadb6e879.png b/_book/docs/img/7710cb575c3aefd0769c3f6aadb6e879.png new file mode 100644 index 0000000000000000000000000000000000000000..9d3dcd5d4a2b1ae555141c2fb6323289ce765558 Binary files /dev/null and b/_book/docs/img/7710cb575c3aefd0769c3f6aadb6e879.png differ diff --git a/_book/docs/img/771e5d2c3cbeba5811f78938b976dfdf.png b/_book/docs/img/771e5d2c3cbeba5811f78938b976dfdf.png new file mode 100644 index 0000000000000000000000000000000000000000..46c3dc28b7953248ea1ac7a5ba6cac5317afa488 Binary files /dev/null and b/_book/docs/img/771e5d2c3cbeba5811f78938b976dfdf.png differ diff --git a/_book/docs/img/7727ed12caef6b761b73e4bd379c7839.png b/_book/docs/img/7727ed12caef6b761b73e4bd379c7839.png new file mode 100644 index 0000000000000000000000000000000000000000..6b4e0d28fb042f9f36948d6c6e8e7f32fb3becc6 Binary files /dev/null and b/_book/docs/img/7727ed12caef6b761b73e4bd379c7839.png differ diff --git a/_book/docs/img/773702223af81c9872bccd88d63ad3a5.png b/_book/docs/img/773702223af81c9872bccd88d63ad3a5.png new file mode 100644 index 0000000000000000000000000000000000000000..85298df4ab63cac86741ee974b511fbc35080bcd Binary files /dev/null and b/_book/docs/img/773702223af81c9872bccd88d63ad3a5.png differ diff --git a/_book/docs/img/77707dedee5c3b669fd992a327698362.png b/_book/docs/img/77707dedee5c3b669fd992a327698362.png new file mode 100644 index 0000000000000000000000000000000000000000..6efbc5679aee95e0e342cd9e40c722e27715f620 Binary files /dev/null and b/_book/docs/img/77707dedee5c3b669fd992a327698362.png differ diff --git a/_book/docs/img/7775f0c2ba5f85e61aae351b9939cdf2.png b/_book/docs/img/7775f0c2ba5f85e61aae351b9939cdf2.png new file mode 100644 index 0000000000000000000000000000000000000000..ff026e2d27dca8750fc9345e4548f45336409a57 Binary files /dev/null and b/_book/docs/img/7775f0c2ba5f85e61aae351b9939cdf2.png differ diff --git a/_book/docs/img/77a2b247e60ad05b022cfd3f3a62c069.png b/_book/docs/img/77a2b247e60ad05b022cfd3f3a62c069.png new file mode 100644 index 0000000000000000000000000000000000000000..ebcc5fede484137e217b4a5203bab885be1b85dd Binary files /dev/null and b/_book/docs/img/77a2b247e60ad05b022cfd3f3a62c069.png differ diff --git a/_book/docs/img/78801b2f265bdecdb7a5ff7e8be47802.png b/_book/docs/img/78801b2f265bdecdb7a5ff7e8be47802.png new file mode 100644 index 0000000000000000000000000000000000000000..04f6e927221d49f8bc6a9a7248712285d2f6cc3f Binary files /dev/null and b/_book/docs/img/78801b2f265bdecdb7a5ff7e8be47802.png differ diff --git a/_book/docs/img/7887f58c141f9c2e749a75158e430ac6.png b/_book/docs/img/7887f58c141f9c2e749a75158e430ac6.png new file mode 100644 index 0000000000000000000000000000000000000000..0dc625cfd932148615c5e47ce40d799d6d575b8d Binary files /dev/null and b/_book/docs/img/7887f58c141f9c2e749a75158e430ac6.png differ diff --git a/_book/docs/img/788efc08015bf62f608d47f16b49b4d7.png b/_book/docs/img/788efc08015bf62f608d47f16b49b4d7.png new file mode 100644 index 0000000000000000000000000000000000000000..a6e922147f5fe2a4368c5a1e5ee1fb30377e02ba Binary files /dev/null and b/_book/docs/img/788efc08015bf62f608d47f16b49b4d7.png differ diff --git a/_book/docs/img/7896b9b275d92d4b9cb2001cc464e509.png b/_book/docs/img/7896b9b275d92d4b9cb2001cc464e509.png new file mode 100644 index 0000000000000000000000000000000000000000..5da697fa240cec7723dfab832037bbe5ff40fd15 Binary files /dev/null and b/_book/docs/img/7896b9b275d92d4b9cb2001cc464e509.png differ diff --git a/_book/docs/img/78dac22706dcca5ce3855d23987289ea.png b/_book/docs/img/78dac22706dcca5ce3855d23987289ea.png new file mode 100644 index 0000000000000000000000000000000000000000..1896c579211f0827a07a7a4fed5419ad2f7534ed Binary files /dev/null and b/_book/docs/img/78dac22706dcca5ce3855d23987289ea.png differ diff --git a/_book/docs/img/793399d61e9710ebd809bd4c52901d68.png b/_book/docs/img/793399d61e9710ebd809bd4c52901d68.png new file mode 100644 index 0000000000000000000000000000000000000000..de5ae27dbb06619017349063c7082e86f207ad76 Binary files /dev/null and b/_book/docs/img/793399d61e9710ebd809bd4c52901d68.png differ diff --git a/_book/docs/img/7a0180479e056fe1c4aa11c3e8684906.png b/_book/docs/img/7a0180479e056fe1c4aa11c3e8684906.png new file mode 100644 index 0000000000000000000000000000000000000000..81655fb37468ae117113b49189baaf351e6173b6 Binary files /dev/null and b/_book/docs/img/7a0180479e056fe1c4aa11c3e8684906.png differ diff --git a/_book/docs/img/7a0b5b2ee322d8676753d89561c1d3cb.png b/_book/docs/img/7a0b5b2ee322d8676753d89561c1d3cb.png new file mode 100644 index 0000000000000000000000000000000000000000..37bc9e1790baee991fdafe0a07adc67744dba4f9 Binary files /dev/null and b/_book/docs/img/7a0b5b2ee322d8676753d89561c1d3cb.png differ diff --git a/_book/docs/img/7a1046341466c144b96bc573f0a16114.png b/_book/docs/img/7a1046341466c144b96bc573f0a16114.png new file mode 100644 index 0000000000000000000000000000000000000000..5d0dc7e63f8d5a82ce67c7c7fa9de170b2727d87 Binary files /dev/null and b/_book/docs/img/7a1046341466c144b96bc573f0a16114.png differ diff --git a/_book/docs/img/7a4195dce33a791e39b721499e4137ad.png b/_book/docs/img/7a4195dce33a791e39b721499e4137ad.png new file mode 100644 index 0000000000000000000000000000000000000000..0c9a22f54c81f91272ce3adea42b9d0e6e4acb1f Binary files /dev/null and b/_book/docs/img/7a4195dce33a791e39b721499e4137ad.png differ diff --git a/_book/docs/img/7a5996be0f8e75beb29e443470d79ee6.png b/_book/docs/img/7a5996be0f8e75beb29e443470d79ee6.png new file mode 100644 index 0000000000000000000000000000000000000000..408f8223bbbb87d53f1a5364a830c1976740609f Binary files /dev/null and b/_book/docs/img/7a5996be0f8e75beb29e443470d79ee6.png differ diff --git a/_book/docs/img/7a5c28bfcfa2942d75aaace7ccb281ce.png b/_book/docs/img/7a5c28bfcfa2942d75aaace7ccb281ce.png new file mode 100644 index 0000000000000000000000000000000000000000..6370442a82dd45a585528075165975179bfa6fa6 Binary files /dev/null and b/_book/docs/img/7a5c28bfcfa2942d75aaace7ccb281ce.png differ diff --git a/_book/docs/img/7a612dcc3c18a6e6433eb5a57a99368d.png b/_book/docs/img/7a612dcc3c18a6e6433eb5a57a99368d.png new file mode 100644 index 0000000000000000000000000000000000000000..95b2b45c5874f73343ddc026fd03e80ba7e7adda Binary files /dev/null and b/_book/docs/img/7a612dcc3c18a6e6433eb5a57a99368d.png differ diff --git a/_book/docs/img/7a9e6a406ba2eb40638f2b43024b368b.png b/_book/docs/img/7a9e6a406ba2eb40638f2b43024b368b.png new file mode 100644 index 0000000000000000000000000000000000000000..fb14288704080745e74d3aad4ffa7a034d799da6 Binary files /dev/null and b/_book/docs/img/7a9e6a406ba2eb40638f2b43024b368b.png differ diff --git a/_book/docs/img/7ac2e224cec000f3932b1186bc1d643f.png b/_book/docs/img/7ac2e224cec000f3932b1186bc1d643f.png new file mode 100644 index 0000000000000000000000000000000000000000..eb046ca1ad21d4739465aea83e4b11b60a0a74f9 Binary files /dev/null and b/_book/docs/img/7ac2e224cec000f3932b1186bc1d643f.png differ diff --git a/_book/docs/img/7b1af71091089deb54dbd357d9679d9c.png b/_book/docs/img/7b1af71091089deb54dbd357d9679d9c.png new file mode 100644 index 0000000000000000000000000000000000000000..f95331a810c22b650f6fbd7d31610d840a9be9c3 Binary files /dev/null and b/_book/docs/img/7b1af71091089deb54dbd357d9679d9c.png differ diff --git a/_book/docs/img/7b7c08f411e1307c05a834071bccb610.png b/_book/docs/img/7b7c08f411e1307c05a834071bccb610.png new file mode 100644 index 0000000000000000000000000000000000000000..0c6996e3d0b488dcd0a44bef48878a5b78863c37 Binary files /dev/null and b/_book/docs/img/7b7c08f411e1307c05a834071bccb610.png differ diff --git a/_book/docs/img/7bcf8d15daa1fb25935d7638acd8eb43.png b/_book/docs/img/7bcf8d15daa1fb25935d7638acd8eb43.png new file mode 100644 index 0000000000000000000000000000000000000000..4da3204aebf77b43c5907889474c0ab738fa4f95 Binary files /dev/null and b/_book/docs/img/7bcf8d15daa1fb25935d7638acd8eb43.png differ diff --git a/_book/docs/img/7cc97c84798f08bc78608f1afa423aa2.png b/_book/docs/img/7cc97c84798f08bc78608f1afa423aa2.png new file mode 100644 index 0000000000000000000000000000000000000000..94b6dcb1b63121005177303ca5511501c2eb380f Binary files /dev/null and b/_book/docs/img/7cc97c84798f08bc78608f1afa423aa2.png differ diff --git a/_book/docs/img/7cfe14b5f606095866af7260c844d4e2.png b/_book/docs/img/7cfe14b5f606095866af7260c844d4e2.png new file mode 100644 index 0000000000000000000000000000000000000000..d04101bd97f7e02446c49cd4a20210061c5b23c6 Binary files /dev/null and b/_book/docs/img/7cfe14b5f606095866af7260c844d4e2.png differ diff --git a/_book/docs/img/7d05273dffbd24f67285426b02a19ddc.png b/_book/docs/img/7d05273dffbd24f67285426b02a19ddc.png new file mode 100644 index 0000000000000000000000000000000000000000..51e640b648f7cdb533d7cf34501faee86e3d1b39 Binary files /dev/null and b/_book/docs/img/7d05273dffbd24f67285426b02a19ddc.png differ diff --git a/_book/docs/img/7d08a10bdee492162fdb554fb3033f0d.png b/_book/docs/img/7d08a10bdee492162fdb554fb3033f0d.png new file mode 100644 index 0000000000000000000000000000000000000000..4ea903691677c21c655db89811a29824dd11b910 Binary files /dev/null and b/_book/docs/img/7d08a10bdee492162fdb554fb3033f0d.png differ diff --git a/_book/docs/img/7dc58177067caac48605788b7932d846.png b/_book/docs/img/7dc58177067caac48605788b7932d846.png new file mode 100644 index 0000000000000000000000000000000000000000..2698626f5592fc6e4713787751a1e3b2350c4bff Binary files /dev/null and b/_book/docs/img/7dc58177067caac48605788b7932d846.png differ diff --git a/_book/docs/img/7ddc19b18c20bfa78acb7fe9dd2ede4b.png b/_book/docs/img/7ddc19b18c20bfa78acb7fe9dd2ede4b.png new file mode 100644 index 0000000000000000000000000000000000000000..f927104262dbefc02e3120e321720d2d20b53ba7 Binary files /dev/null and b/_book/docs/img/7ddc19b18c20bfa78acb7fe9dd2ede4b.png differ diff --git a/_book/docs/img/7e5039b0d8fb74c5ea813e354f23493e.png b/_book/docs/img/7e5039b0d8fb74c5ea813e354f23493e.png new file mode 100644 index 0000000000000000000000000000000000000000..a138ba1e4abc9585981cec4cf4429450bf416c18 Binary files /dev/null and b/_book/docs/img/7e5039b0d8fb74c5ea813e354f23493e.png differ diff --git a/_book/docs/img/7ebc386f852ada24782fd3b7e5dd226e.png b/_book/docs/img/7ebc386f852ada24782fd3b7e5dd226e.png new file mode 100644 index 0000000000000000000000000000000000000000..8e97f831404b3282077e93cbc1d2e2b7840fd9ec Binary files /dev/null and b/_book/docs/img/7ebc386f852ada24782fd3b7e5dd226e.png differ diff --git a/_book/docs/img/7efae901a0febb2a8e969415dced271a.png b/_book/docs/img/7efae901a0febb2a8e969415dced271a.png new file mode 100644 index 0000000000000000000000000000000000000000..7761319c37991d0fb9b69da2b02902c196a5aec3 Binary files /dev/null and b/_book/docs/img/7efae901a0febb2a8e969415dced271a.png differ diff --git a/_book/docs/img/7f1a1847005ab07ba8259a9e67005213.png b/_book/docs/img/7f1a1847005ab07ba8259a9e67005213.png new file mode 100644 index 0000000000000000000000000000000000000000..8f5f63bf83b84e6ae0703d92c6d05300964db8fd Binary files /dev/null and b/_book/docs/img/7f1a1847005ab07ba8259a9e67005213.png differ diff --git a/_book/docs/img/7f8f5e942a32629817a87b08e33d9071.png b/_book/docs/img/7f8f5e942a32629817a87b08e33d9071.png new file mode 100644 index 0000000000000000000000000000000000000000..aabf65e1ae346142d35e056ea3eb5cc9a7cc071e Binary files /dev/null and b/_book/docs/img/7f8f5e942a32629817a87b08e33d9071.png differ diff --git a/_book/docs/img/7fb24fed9f39dcdabb530523bcb8dc08.png b/_book/docs/img/7fb24fed9f39dcdabb530523bcb8dc08.png new file mode 100644 index 0000000000000000000000000000000000000000..ae578d8d0a16bf657fc7cd9cf2c118d127275f93 Binary files /dev/null and b/_book/docs/img/7fb24fed9f39dcdabb530523bcb8dc08.png differ diff --git a/_book/docs/img/7ff67c276870da733a9bc04b2aa9d969.png b/_book/docs/img/7ff67c276870da733a9bc04b2aa9d969.png new file mode 100644 index 0000000000000000000000000000000000000000..c3ed48957331c3e6dce00ea5eb900024bdc9e415 Binary files /dev/null and b/_book/docs/img/7ff67c276870da733a9bc04b2aa9d969.png differ diff --git a/_book/docs/img/8013884e699eb543397343ba53b7f107.png b/_book/docs/img/8013884e699eb543397343ba53b7f107.png new file mode 100644 index 0000000000000000000000000000000000000000..f33004d590c5522c31fad2450fed92d0e3940426 Binary files /dev/null and b/_book/docs/img/8013884e699eb543397343ba53b7f107.png differ diff --git a/_book/docs/img/801adc20d157f18e08adbd379180f3c7.png b/_book/docs/img/801adc20d157f18e08adbd379180f3c7.png new file mode 100644 index 0000000000000000000000000000000000000000..4a051e5aabcfd8d57b6a91013e7e5fa9372de4c0 Binary files /dev/null and b/_book/docs/img/801adc20d157f18e08adbd379180f3c7.png differ diff --git a/_book/docs/img/8069500bf085102224933129529dfa12.png b/_book/docs/img/8069500bf085102224933129529dfa12.png new file mode 100644 index 0000000000000000000000000000000000000000..216ec28c67be58b73ae7518f4c8a537f10e74b71 Binary files /dev/null and b/_book/docs/img/8069500bf085102224933129529dfa12.png differ diff --git a/_book/docs/img/806d03909b4b194f095b4c69e175868d.png b/_book/docs/img/806d03909b4b194f095b4c69e175868d.png new file mode 100644 index 0000000000000000000000000000000000000000..789128b4aafb4d9d60f22b0060e6c8d3b88789e5 Binary files /dev/null and b/_book/docs/img/806d03909b4b194f095b4c69e175868d.png differ diff --git a/_book/docs/img/8095440bd29d634de897ae56f76a4969.png b/_book/docs/img/8095440bd29d634de897ae56f76a4969.png new file mode 100644 index 0000000000000000000000000000000000000000..8946c3b3b1008c97b9282955d8985e0ab2a54371 Binary files /dev/null and b/_book/docs/img/8095440bd29d634de897ae56f76a4969.png differ diff --git a/_book/docs/img/80a62bce7846a67c7743ef7324a58757.png b/_book/docs/img/80a62bce7846a67c7743ef7324a58757.png new file mode 100644 index 0000000000000000000000000000000000000000..b3e227ab5fe30abf735d9d9652b8c2ad5b98e115 Binary files /dev/null and b/_book/docs/img/80a62bce7846a67c7743ef7324a58757.png differ diff --git a/_book/docs/img/80a9fe0374f84134fa2b40172431604d.png b/_book/docs/img/80a9fe0374f84134fa2b40172431604d.png new file mode 100644 index 0000000000000000000000000000000000000000..a9c76bc158d6151125bc33d09d6a0f6ca92679f0 Binary files /dev/null and b/_book/docs/img/80a9fe0374f84134fa2b40172431604d.png differ diff --git a/_book/docs/img/813cda0881e353d15eed9ca9417104f1.png b/_book/docs/img/813cda0881e353d15eed9ca9417104f1.png new file mode 100644 index 0000000000000000000000000000000000000000..fd6d3b3fb492718b56baf074ac3013b36001b1fc Binary files /dev/null and b/_book/docs/img/813cda0881e353d15eed9ca9417104f1.png differ diff --git a/_book/docs/img/813e077e7aa22bb747b5f237984f1b22.png b/_book/docs/img/813e077e7aa22bb747b5f237984f1b22.png new file mode 100644 index 0000000000000000000000000000000000000000..d2237fa602977d0d24cf0a640db07e09ba58588c Binary files /dev/null and b/_book/docs/img/813e077e7aa22bb747b5f237984f1b22.png differ diff --git a/_book/docs/img/81b83780f68abcbb32edb1eb48002a4d.png b/_book/docs/img/81b83780f68abcbb32edb1eb48002a4d.png new file mode 100644 index 0000000000000000000000000000000000000000..1538700b7db8ced089bbf6249b047778125713d3 Binary files /dev/null and b/_book/docs/img/81b83780f68abcbb32edb1eb48002a4d.png differ diff --git a/_book/docs/img/81c888ba61ab652f9505d5b51406ed22.png b/_book/docs/img/81c888ba61ab652f9505d5b51406ed22.png new file mode 100644 index 0000000000000000000000000000000000000000..0d55b392a20b7e3084d0644dfe5f931358ea12b2 Binary files /dev/null and b/_book/docs/img/81c888ba61ab652f9505d5b51406ed22.png differ diff --git a/_book/docs/img/81cb03504811f2ae5f008de13366a1db.png b/_book/docs/img/81cb03504811f2ae5f008de13366a1db.png new file mode 100644 index 0000000000000000000000000000000000000000..4bf124d8732da09fb77711f5ea8cc1bf8cf6735e Binary files /dev/null and b/_book/docs/img/81cb03504811f2ae5f008de13366a1db.png differ diff --git a/_book/docs/img/81fe297de1dccaedd3340735454273bc.png b/_book/docs/img/81fe297de1dccaedd3340735454273bc.png new file mode 100644 index 0000000000000000000000000000000000000000..eeb97c26b674f4945b2fad3e5e08f541b69e4f38 Binary files /dev/null and b/_book/docs/img/81fe297de1dccaedd3340735454273bc.png differ diff --git a/_book/docs/img/8201105b83669750c4d60036b41f6c6d.png b/_book/docs/img/8201105b83669750c4d60036b41f6c6d.png new file mode 100644 index 0000000000000000000000000000000000000000..9e15c82ffaaab2fb64c69c766ad51ad99a0eeba3 Binary files /dev/null and b/_book/docs/img/8201105b83669750c4d60036b41f6c6d.png differ diff --git a/_book/docs/img/8215c374294289cd2bd24399439403fd.png b/_book/docs/img/8215c374294289cd2bd24399439403fd.png new file mode 100644 index 0000000000000000000000000000000000000000..3dea589160bdb4ba364fb7a6e0c15066932c754d Binary files /dev/null and b/_book/docs/img/8215c374294289cd2bd24399439403fd.png differ diff --git a/_book/docs/img/82c2caa32c2aff60b744c3ede8725ac9.png b/_book/docs/img/82c2caa32c2aff60b744c3ede8725ac9.png new file mode 100644 index 0000000000000000000000000000000000000000..a625f142341369f39c0397b7c16c6f322b868bbb Binary files /dev/null and b/_book/docs/img/82c2caa32c2aff60b744c3ede8725ac9.png differ diff --git a/_book/docs/img/8308fbab7a41e24cad0bf6c358863ae3.png b/_book/docs/img/8308fbab7a41e24cad0bf6c358863ae3.png new file mode 100644 index 0000000000000000000000000000000000000000..a538e55ad6b0edc2ab1a983939536e301797fe5d Binary files /dev/null and b/_book/docs/img/8308fbab7a41e24cad0bf6c358863ae3.png differ diff --git a/_book/docs/img/8375b8805ee35febb22389954e463cb3.png b/_book/docs/img/8375b8805ee35febb22389954e463cb3.png new file mode 100644 index 0000000000000000000000000000000000000000..c8fad0ac9430a9c10884371d30600252415a788f Binary files /dev/null and b/_book/docs/img/8375b8805ee35febb22389954e463cb3.png differ diff --git a/_book/docs/img/838245c530d1afaf54929d9edd3f6a24.png b/_book/docs/img/838245c530d1afaf54929d9edd3f6a24.png new file mode 100644 index 0000000000000000000000000000000000000000..ea36b83c43dd5dd2d707be92dc367778a151f56e Binary files /dev/null and b/_book/docs/img/838245c530d1afaf54929d9edd3f6a24.png differ diff --git a/_book/docs/img/83a4859fc1c1d9fc2ea68819a53eaea8.png b/_book/docs/img/83a4859fc1c1d9fc2ea68819a53eaea8.png new file mode 100644 index 0000000000000000000000000000000000000000..33877d9fa94579eca3c7d6b71d0eee32f678bd25 Binary files /dev/null and b/_book/docs/img/83a4859fc1c1d9fc2ea68819a53eaea8.png differ diff --git a/_book/docs/img/83da8fe833233875ee4fe28fa21eb1dd.png b/_book/docs/img/83da8fe833233875ee4fe28fa21eb1dd.png new file mode 100644 index 0000000000000000000000000000000000000000..1374e3093d2331527b9cec14a4b4c2fda50b83a8 Binary files /dev/null and b/_book/docs/img/83da8fe833233875ee4fe28fa21eb1dd.png differ diff --git a/_book/docs/img/8465cc4b8bf68fad2a64c9fc838c7939.png b/_book/docs/img/8465cc4b8bf68fad2a64c9fc838c7939.png new file mode 100644 index 0000000000000000000000000000000000000000..2c24a5a46a000296c648380d5e9ae67024b35d58 Binary files /dev/null and b/_book/docs/img/8465cc4b8bf68fad2a64c9fc838c7939.png differ diff --git a/_book/docs/img/8489a6c45ad75964ea7b4b54b9d9fcaa.png b/_book/docs/img/8489a6c45ad75964ea7b4b54b9d9fcaa.png new file mode 100644 index 0000000000000000000000000000000000000000..4eebb382b28bae807c42399c538e03f5a38dcee5 Binary files /dev/null and b/_book/docs/img/8489a6c45ad75964ea7b4b54b9d9fcaa.png differ diff --git a/_book/docs/img/85055487485aff8bd5dc0cf97f711d52.png b/_book/docs/img/85055487485aff8bd5dc0cf97f711d52.png new file mode 100644 index 0000000000000000000000000000000000000000..a3de5a934f534c9ef127f3801b45299e50c8dc8a Binary files /dev/null and b/_book/docs/img/85055487485aff8bd5dc0cf97f711d52.png differ diff --git a/_book/docs/img/854d722d9976d5b36956ddbe41ceae48.png b/_book/docs/img/854d722d9976d5b36956ddbe41ceae48.png new file mode 100644 index 0000000000000000000000000000000000000000..08cb1c640c74ec821fde93cbcaad62f00c6d7ddd Binary files /dev/null and b/_book/docs/img/854d722d9976d5b36956ddbe41ceae48.png differ diff --git a/_book/docs/img/85b07bb9804f9dd3c4e3edfc1e562f31.png b/_book/docs/img/85b07bb9804f9dd3c4e3edfc1e562f31.png new file mode 100644 index 0000000000000000000000000000000000000000..240c9b6f3b6d2243c1827bfbace2775372244ab6 Binary files /dev/null and b/_book/docs/img/85b07bb9804f9dd3c4e3edfc1e562f31.png differ diff --git a/_book/docs/img/865329b4b113d6de44cf382bd77178fa.png b/_book/docs/img/865329b4b113d6de44cf382bd77178fa.png new file mode 100644 index 0000000000000000000000000000000000000000..7dab3d5a83ff7a1a7d48f36cd23cefe982f767cb Binary files /dev/null and b/_book/docs/img/865329b4b113d6de44cf382bd77178fa.png differ diff --git a/_book/docs/img/865915f0e39a0035ffc91de736f5a047.png b/_book/docs/img/865915f0e39a0035ffc91de736f5a047.png new file mode 100644 index 0000000000000000000000000000000000000000..344f4191752d2fa0f885b93c50b04ffcb9b62026 Binary files /dev/null and b/_book/docs/img/865915f0e39a0035ffc91de736f5a047.png differ diff --git a/_book/docs/img/86614ecfb76f8a91344d98d3effa7d2a.png b/_book/docs/img/86614ecfb76f8a91344d98d3effa7d2a.png new file mode 100644 index 0000000000000000000000000000000000000000..f962cc4a4687aa3e76d2c010d4c11e62492c11f1 Binary files /dev/null and b/_book/docs/img/86614ecfb76f8a91344d98d3effa7d2a.png differ diff --git a/_book/docs/img/86738432aa05c0c68fffb68c00788fa4.png b/_book/docs/img/86738432aa05c0c68fffb68c00788fa4.png new file mode 100644 index 0000000000000000000000000000000000000000..8c88a72d600a9bb0d9060e1f876594269cf0f63c Binary files /dev/null and b/_book/docs/img/86738432aa05c0c68fffb68c00788fa4.png differ diff --git a/_book/docs/img/86b62f200c6aa129ed945d20ec0fbfa2.png b/_book/docs/img/86b62f200c6aa129ed945d20ec0fbfa2.png new file mode 100644 index 0000000000000000000000000000000000000000..20b7c7e40776fe0dd817fb440dc37c89bbaa77b2 Binary files /dev/null and b/_book/docs/img/86b62f200c6aa129ed945d20ec0fbfa2.png differ diff --git a/_book/docs/img/86c94810add9e77037bd8a135ef2b972.png b/_book/docs/img/86c94810add9e77037bd8a135ef2b972.png new file mode 100644 index 0000000000000000000000000000000000000000..5dad2a06ad21f85d0adc19652c797868125fdf82 Binary files /dev/null and b/_book/docs/img/86c94810add9e77037bd8a135ef2b972.png differ diff --git a/_book/docs/img/874270632cfad28b99af65b5d0275fee.png b/_book/docs/img/874270632cfad28b99af65b5d0275fee.png new file mode 100644 index 0000000000000000000000000000000000000000..8531365e51bcba091818ee069efc473f5db33c32 Binary files /dev/null and b/_book/docs/img/874270632cfad28b99af65b5d0275fee.png differ diff --git a/_book/docs/img/878c3488cf7403499b80fcd402198e32.png b/_book/docs/img/878c3488cf7403499b80fcd402198e32.png new file mode 100644 index 0000000000000000000000000000000000000000..2b05b8e67814ed8315cfb85cbb5e01536e68a8c6 Binary files /dev/null and b/_book/docs/img/878c3488cf7403499b80fcd402198e32.png differ diff --git a/_book/docs/img/87be547831d2207399009a0f9dd4b91a.png b/_book/docs/img/87be547831d2207399009a0f9dd4b91a.png new file mode 100644 index 0000000000000000000000000000000000000000..03025f156ea587e9898c17f2b63ba61df98521be Binary files /dev/null and b/_book/docs/img/87be547831d2207399009a0f9dd4b91a.png differ diff --git a/_book/docs/img/8855ae33dbb80420649c523afdf3fe8b.png b/_book/docs/img/8855ae33dbb80420649c523afdf3fe8b.png new file mode 100644 index 0000000000000000000000000000000000000000..2d42314141e23968e906e9cbaaa19453f8c11f76 Binary files /dev/null and b/_book/docs/img/8855ae33dbb80420649c523afdf3fe8b.png differ diff --git a/_book/docs/img/89c2a0a388333182ff39563629933a87.png b/_book/docs/img/89c2a0a388333182ff39563629933a87.png new file mode 100644 index 0000000000000000000000000000000000000000..fb63d1db918d9719f4190010b9a7874adc2a0965 Binary files /dev/null and b/_book/docs/img/89c2a0a388333182ff39563629933a87.png differ diff --git a/_book/docs/img/8a05f3552d23f56607411f613a5ceb05.png b/_book/docs/img/8a05f3552d23f56607411f613a5ceb05.png new file mode 100644 index 0000000000000000000000000000000000000000..b7727e9ad8a669a0f6e74820feae975d474aa3cb Binary files /dev/null and b/_book/docs/img/8a05f3552d23f56607411f613a5ceb05.png differ diff --git a/_book/docs/img/8a2c3991978374372fe0370f27f4fad4.png b/_book/docs/img/8a2c3991978374372fe0370f27f4fad4.png new file mode 100644 index 0000000000000000000000000000000000000000..a7181b9e5ba19d76d4cbf0ce57f2081344fb3bef Binary files /dev/null and b/_book/docs/img/8a2c3991978374372fe0370f27f4fad4.png differ diff --git a/_book/docs/img/8a4af39c416005af074623092e32d782.png b/_book/docs/img/8a4af39c416005af074623092e32d782.png new file mode 100644 index 0000000000000000000000000000000000000000..e69dd08f4a08bb1584fb0b74c046b94b50106253 Binary files /dev/null and b/_book/docs/img/8a4af39c416005af074623092e32d782.png differ diff --git a/_book/docs/img/8a56e678752a9bd9def98422dee92f3e.png b/_book/docs/img/8a56e678752a9bd9def98422dee92f3e.png new file mode 100644 index 0000000000000000000000000000000000000000..1e7aebb8fad7c6a2a63e3c00e9104f0eee00571f Binary files /dev/null and b/_book/docs/img/8a56e678752a9bd9def98422dee92f3e.png differ diff --git a/_book/docs/img/8a6c0fc733a099005b7f7f9bcfbfe2ff.png b/_book/docs/img/8a6c0fc733a099005b7f7f9bcfbfe2ff.png new file mode 100644 index 0000000000000000000000000000000000000000..cf8112c09bde702d1541703fc8aabefa924efc0e Binary files /dev/null and b/_book/docs/img/8a6c0fc733a099005b7f7f9bcfbfe2ff.png differ diff --git a/_book/docs/img/8ab62c2dee9f26abae9b7f794b4f5fae.png b/_book/docs/img/8ab62c2dee9f26abae9b7f794b4f5fae.png new file mode 100644 index 0000000000000000000000000000000000000000..f04d77f4ee2d216f6f2dfddf9bb71900ffdeadb5 Binary files /dev/null and b/_book/docs/img/8ab62c2dee9f26abae9b7f794b4f5fae.png differ diff --git a/_book/docs/img/8c47dc71d95554edf7da34adb5acc575.png b/_book/docs/img/8c47dc71d95554edf7da34adb5acc575.png new file mode 100644 index 0000000000000000000000000000000000000000..4dd276abe23f7ad29021e6a703c9da160cd70bf4 Binary files /dev/null and b/_book/docs/img/8c47dc71d95554edf7da34adb5acc575.png differ diff --git a/_book/docs/img/8c80632a58ede646cb8f2046924a504a.png b/_book/docs/img/8c80632a58ede646cb8f2046924a504a.png new file mode 100644 index 0000000000000000000000000000000000000000..6e373e67fa6eb0d9f3bd27b4e2d48ec970361b06 Binary files /dev/null and b/_book/docs/img/8c80632a58ede646cb8f2046924a504a.png differ diff --git a/_book/docs/img/8cebf5d928a8666adcfc25eccfeec89e.png b/_book/docs/img/8cebf5d928a8666adcfc25eccfeec89e.png new file mode 100644 index 0000000000000000000000000000000000000000..01825cc8fd9bf50c4a00eb08e87c8d834dcfdb90 Binary files /dev/null and b/_book/docs/img/8cebf5d928a8666adcfc25eccfeec89e.png differ diff --git a/_book/docs/img/8d249dc6a1ff208c520bfc8cad423a4a.png b/_book/docs/img/8d249dc6a1ff208c520bfc8cad423a4a.png new file mode 100644 index 0000000000000000000000000000000000000000..63c807d19973afe9f79cef67350a298b8999df2a Binary files /dev/null and b/_book/docs/img/8d249dc6a1ff208c520bfc8cad423a4a.png differ diff --git a/_book/docs/img/8d66587fae4dab1dca05f85389caa499.png b/_book/docs/img/8d66587fae4dab1dca05f85389caa499.png new file mode 100644 index 0000000000000000000000000000000000000000..25be05639dda8ee12eb4798217d8e8ac7f63a110 Binary files /dev/null and b/_book/docs/img/8d66587fae4dab1dca05f85389caa499.png differ diff --git a/_book/docs/img/8db9ef3ba0d1153ab46b990e98372677.png b/_book/docs/img/8db9ef3ba0d1153ab46b990e98372677.png new file mode 100644 index 0000000000000000000000000000000000000000..e3a36133a623653e6e9dae7dc58bb72199b1e0be Binary files /dev/null and b/_book/docs/img/8db9ef3ba0d1153ab46b990e98372677.png differ diff --git a/_book/docs/img/8e301ace1928e93f6138075596994c18.png b/_book/docs/img/8e301ace1928e93f6138075596994c18.png new file mode 100644 index 0000000000000000000000000000000000000000..fe03578d4a09f64c7412ed345a139a4c5fb995fc Binary files /dev/null and b/_book/docs/img/8e301ace1928e93f6138075596994c18.png differ diff --git a/_book/docs/img/8e5585152d153d9f1f4073f0cddba269.png b/_book/docs/img/8e5585152d153d9f1f4073f0cddba269.png new file mode 100644 index 0000000000000000000000000000000000000000..0258d8c68f88937ef59d0dda6fe406842d1c0601 --- /dev/null +++ b/_book/docs/img/8e5585152d153d9f1f4073f0cddba269.png @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + Frontend Coverage + + + Frontend Coverage + + + 39.78% + + + 39.78% + + + + diff --git a/_book/docs/img/8ec36cbe2f746b6b6cc0d28e1620899a.png b/_book/docs/img/8ec36cbe2f746b6b6cc0d28e1620899a.png new file mode 100644 index 0000000000000000000000000000000000000000..2a3024c398a7a108ae3b277ba9877d29dd7b3373 Binary files /dev/null and b/_book/docs/img/8ec36cbe2f746b6b6cc0d28e1620899a.png differ diff --git a/_book/docs/img/8edd1cbf476ddc76f3df25fdeff8b55c.png b/_book/docs/img/8edd1cbf476ddc76f3df25fdeff8b55c.png new file mode 100644 index 0000000000000000000000000000000000000000..c21ebbbc3f4294a95a5cbccda44338866756a5d7 Binary files /dev/null and b/_book/docs/img/8edd1cbf476ddc76f3df25fdeff8b55c.png differ diff --git a/_book/docs/img/8f07bae8fce74cd6b8276b7dd9e59c2e.png b/_book/docs/img/8f07bae8fce74cd6b8276b7dd9e59c2e.png new file mode 100644 index 0000000000000000000000000000000000000000..5136f5d0477e49d0e7c28e98d5b80f7a8d3f95c9 Binary files /dev/null and b/_book/docs/img/8f07bae8fce74cd6b8276b7dd9e59c2e.png differ diff --git a/_book/docs/img/8f8d204a16e9c896b01a62220529b921.png b/_book/docs/img/8f8d204a16e9c896b01a62220529b921.png new file mode 100644 index 0000000000000000000000000000000000000000..e24457030045f6c98c87927e15826ed25b436b53 Binary files /dev/null and b/_book/docs/img/8f8d204a16e9c896b01a62220529b921.png differ diff --git a/_book/docs/img/8fc9989164e038f62ee1015c2f477d84.png b/_book/docs/img/8fc9989164e038f62ee1015c2f477d84.png new file mode 100644 index 0000000000000000000000000000000000000000..f2beb6c1c0a71a2fde2c3e43400d31ecb9559b5e Binary files /dev/null and b/_book/docs/img/8fc9989164e038f62ee1015c2f477d84.png differ diff --git a/_book/docs/img/906ca69aaf7c7a7f53479eb595f83ec0.png b/_book/docs/img/906ca69aaf7c7a7f53479eb595f83ec0.png new file mode 100644 index 0000000000000000000000000000000000000000..e54bc3434bd62c36316fb17abc8e91456147fe58 Binary files /dev/null and b/_book/docs/img/906ca69aaf7c7a7f53479eb595f83ec0.png differ diff --git a/_book/docs/img/9079254cc7f9fbc13ee5005765608b59.png b/_book/docs/img/9079254cc7f9fbc13ee5005765608b59.png new file mode 100644 index 0000000000000000000000000000000000000000..d8173eaea89d94238ae0409347ad5f471361fd38 Binary files /dev/null and b/_book/docs/img/9079254cc7f9fbc13ee5005765608b59.png differ diff --git a/_book/docs/img/909d20c0dd57155c8ac404a81c2a30cb.png b/_book/docs/img/909d20c0dd57155c8ac404a81c2a30cb.png new file mode 100644 index 0000000000000000000000000000000000000000..e8351a2db33d28abc8f35656d333a4e7cd93c55f Binary files /dev/null and b/_book/docs/img/909d20c0dd57155c8ac404a81c2a30cb.png differ diff --git a/_book/docs/img/90bcd1f29936328bfb5d344868b8bb81.png b/_book/docs/img/90bcd1f29936328bfb5d344868b8bb81.png new file mode 100644 index 0000000000000000000000000000000000000000..3bc06c49ba50b8a3a77ce8ea5e3decafbc5df4b3 Binary files /dev/null and b/_book/docs/img/90bcd1f29936328bfb5d344868b8bb81.png differ diff --git a/_book/docs/img/9101937463fa0be989f93d09d9f54d7a.png b/_book/docs/img/9101937463fa0be989f93d09d9f54d7a.png new file mode 100644 index 0000000000000000000000000000000000000000..5e908eaed5ecbd76209cb21147d7a79cbe609faa Binary files /dev/null and b/_book/docs/img/9101937463fa0be989f93d09d9f54d7a.png differ diff --git a/_book/docs/img/911c6aa51b9202fc3dc3bdc143b30f82.png b/_book/docs/img/911c6aa51b9202fc3dc3bdc143b30f82.png new file mode 100644 index 0000000000000000000000000000000000000000..b7da623ddc6e29a978c75fa45e4138ec6b9dc442 Binary files /dev/null and b/_book/docs/img/911c6aa51b9202fc3dc3bdc143b30f82.png differ diff --git a/_book/docs/img/9121e1772146daa5a3259be82cde8902.png b/_book/docs/img/9121e1772146daa5a3259be82cde8902.png new file mode 100644 index 0000000000000000000000000000000000000000..fc7f7e9c14c210c966b36e7fdf6a41898b7f6252 Binary files /dev/null and b/_book/docs/img/9121e1772146daa5a3259be82cde8902.png differ diff --git a/_book/docs/img/9149638f26311ced385bcc879401a8fd.png b/_book/docs/img/9149638f26311ced385bcc879401a8fd.png new file mode 100644 index 0000000000000000000000000000000000000000..55d23448f888adfbc61526f133fbd8a3ce6f23a7 Binary files /dev/null and b/_book/docs/img/9149638f26311ced385bcc879401a8fd.png differ diff --git a/_book/docs/img/91abd5be225ec3a5c131075cce857fb8.png b/_book/docs/img/91abd5be225ec3a5c131075cce857fb8.png new file mode 100644 index 0000000000000000000000000000000000000000..9c0dc541896b9cac603731e533b25a7bca362553 Binary files /dev/null and b/_book/docs/img/91abd5be225ec3a5c131075cce857fb8.png differ diff --git a/_book/docs/img/9246e597493024c10e4f678f7de7318e.png b/_book/docs/img/9246e597493024c10e4f678f7de7318e.png new file mode 100644 index 0000000000000000000000000000000000000000..9ffbecd33110288647379e33f28978acd0598997 Binary files /dev/null and b/_book/docs/img/9246e597493024c10e4f678f7de7318e.png differ diff --git a/_book/docs/img/9255a795b62eb0bbe1c91eab2f85c149.png b/_book/docs/img/9255a795b62eb0bbe1c91eab2f85c149.png new file mode 100644 index 0000000000000000000000000000000000000000..8a69bdcc41c02e6144776ee0e179c16fc8a74175 Binary files /dev/null and b/_book/docs/img/9255a795b62eb0bbe1c91eab2f85c149.png differ diff --git a/_book/docs/img/92601175945fcac1aee644fd449e9adf.png b/_book/docs/img/92601175945fcac1aee644fd449e9adf.png new file mode 100644 index 0000000000000000000000000000000000000000..a4975605d2f0a9f474155858205ea6cc153b9532 Binary files /dev/null and b/_book/docs/img/92601175945fcac1aee644fd449e9adf.png differ diff --git a/_book/docs/img/9443fbb9f077bc7be6beb1486c392c96.png b/_book/docs/img/9443fbb9f077bc7be6beb1486c392c96.png new file mode 100644 index 0000000000000000000000000000000000000000..69d05e3b572b5bc63fa38658f6fb3f0bdc4fd106 Binary files /dev/null and b/_book/docs/img/9443fbb9f077bc7be6beb1486c392c96.png differ diff --git a/_book/docs/img/94675a32947787d4e216a44e3047d0b5.png b/_book/docs/img/94675a32947787d4e216a44e3047d0b5.png new file mode 100644 index 0000000000000000000000000000000000000000..163d36cd86ecbe6249ba4d32cb67a9e3f34ff8da Binary files /dev/null and b/_book/docs/img/94675a32947787d4e216a44e3047d0b5.png differ diff --git a/_book/docs/img/94b9b90ebfb15979835f3e48d710cb45.png b/_book/docs/img/94b9b90ebfb15979835f3e48d710cb45.png new file mode 100644 index 0000000000000000000000000000000000000000..1d1a99ad8bd54cc19a618010e9dc459ad69cb117 Binary files /dev/null and b/_book/docs/img/94b9b90ebfb15979835f3e48d710cb45.png differ diff --git a/_book/docs/img/94be136c7407855701b88eaded7db929.png b/_book/docs/img/94be136c7407855701b88eaded7db929.png new file mode 100644 index 0000000000000000000000000000000000000000..aeb7a87a4070d681a9dfc05ffd3e2d969e7bcef7 Binary files /dev/null and b/_book/docs/img/94be136c7407855701b88eaded7db929.png differ diff --git a/_book/docs/img/9570df3750a76ee8a88eddb48512daa3.png b/_book/docs/img/9570df3750a76ee8a88eddb48512daa3.png new file mode 100644 index 0000000000000000000000000000000000000000..05a49bb224b445f40d8200d5853fd6f923734201 Binary files /dev/null and b/_book/docs/img/9570df3750a76ee8a88eddb48512daa3.png differ diff --git a/_book/docs/img/95882a4976be6b95971ad0011fcd7617.png b/_book/docs/img/95882a4976be6b95971ad0011fcd7617.png new file mode 100644 index 0000000000000000000000000000000000000000..d86bfecc748598ea82f127244f3db2c55784cd8a Binary files /dev/null and b/_book/docs/img/95882a4976be6b95971ad0011fcd7617.png differ diff --git a/_book/docs/img/95c0b87af108caee2a239482aec61675.png b/_book/docs/img/95c0b87af108caee2a239482aec61675.png new file mode 100644 index 0000000000000000000000000000000000000000..3308fc37f525e50502b6360c3ee49936be24d44a Binary files /dev/null and b/_book/docs/img/95c0b87af108caee2a239482aec61675.png differ diff --git a/_book/docs/img/95cf4cb85bf824cf0817d4d93d93934d.png b/_book/docs/img/95cf4cb85bf824cf0817d4d93d93934d.png new file mode 100644 index 0000000000000000000000000000000000000000..93abd4cb804cf5aa4381a08a2bf45a9e68a9448d Binary files /dev/null and b/_book/docs/img/95cf4cb85bf824cf0817d4d93d93934d.png differ diff --git a/_book/docs/img/96aa3b50d60a091349e8d39c74877a5d.png b/_book/docs/img/96aa3b50d60a091349e8d39c74877a5d.png new file mode 100644 index 0000000000000000000000000000000000000000..9f7455e9c8205ec266497f1908977494040ea197 Binary files /dev/null and b/_book/docs/img/96aa3b50d60a091349e8d39c74877a5d.png differ diff --git a/_book/docs/img/96c6ce839dca0e2ef2d69b8fbc0cff56.png b/_book/docs/img/96c6ce839dca0e2ef2d69b8fbc0cff56.png new file mode 100644 index 0000000000000000000000000000000000000000..fd98a4987a1e925254e93145bff236e2b09bf119 Binary files /dev/null and b/_book/docs/img/96c6ce839dca0e2ef2d69b8fbc0cff56.png differ diff --git a/_book/docs/img/97acbf99c97921ca9e5837c4c70cfa4c.png b/_book/docs/img/97acbf99c97921ca9e5837c4c70cfa4c.png new file mode 100644 index 0000000000000000000000000000000000000000..b76e70d3c315b259b90b6befa0d930764191fb49 Binary files /dev/null and b/_book/docs/img/97acbf99c97921ca9e5837c4c70cfa4c.png differ diff --git a/_book/docs/img/97c7baeb5e993264f4619e443bdacebc.png b/_book/docs/img/97c7baeb5e993264f4619e443bdacebc.png new file mode 100644 index 0000000000000000000000000000000000000000..d172c780e2a02c2b0a802594830676034508bc9b Binary files /dev/null and b/_book/docs/img/97c7baeb5e993264f4619e443bdacebc.png differ diff --git a/_book/docs/img/9807a6b10b783af2ed7c8703958f017a.png b/_book/docs/img/9807a6b10b783af2ed7c8703958f017a.png new file mode 100644 index 0000000000000000000000000000000000000000..57388926ce1e215c08cf20f4e44d5b52eb18a80b Binary files /dev/null and b/_book/docs/img/9807a6b10b783af2ed7c8703958f017a.png differ diff --git a/_book/docs/img/987208c515a3f2627904cc38b355dc15.png b/_book/docs/img/987208c515a3f2627904cc38b355dc15.png new file mode 100644 index 0000000000000000000000000000000000000000..b7bcaa672b06431d210394760c1ac9e6436fb66f Binary files /dev/null and b/_book/docs/img/987208c515a3f2627904cc38b355dc15.png differ diff --git a/_book/docs/img/98f7e80b6f738f9886082aeec3955fd5.png b/_book/docs/img/98f7e80b6f738f9886082aeec3955fd5.png new file mode 100644 index 0000000000000000000000000000000000000000..b99da0fd3d3a0f2eadfa5c98b95a339af78e9117 Binary files /dev/null and b/_book/docs/img/98f7e80b6f738f9886082aeec3955fd5.png differ diff --git a/_book/docs/img/993315f2d7b2aa15b2f3faa03d14705c.png b/_book/docs/img/993315f2d7b2aa15b2f3faa03d14705c.png new file mode 100644 index 0000000000000000000000000000000000000000..a9383d232435068292a52336e20a44635a9fb36a Binary files /dev/null and b/_book/docs/img/993315f2d7b2aa15b2f3faa03d14705c.png differ diff --git a/_book/docs/img/9950340e3b641e3f63d70fb29b2b05bb.png b/_book/docs/img/9950340e3b641e3f63d70fb29b2b05bb.png new file mode 100644 index 0000000000000000000000000000000000000000..a242da8cdd8d731a26e4078cdee3c49a6cf8e1ea Binary files /dev/null and b/_book/docs/img/9950340e3b641e3f63d70fb29b2b05bb.png differ diff --git a/_book/docs/img/996ea860188e6458fe761cf86b2b72b1.png b/_book/docs/img/996ea860188e6458fe761cf86b2b72b1.png new file mode 100644 index 0000000000000000000000000000000000000000..ffe75604b231a134ee06dd3207ec4788cd5af7c0 Binary files /dev/null and b/_book/docs/img/996ea860188e6458fe761cf86b2b72b1.png differ diff --git a/_book/docs/img/9a002df90c6ed1d01c8ae3a9817242df.png b/_book/docs/img/9a002df90c6ed1d01c8ae3a9817242df.png new file mode 100644 index 0000000000000000000000000000000000000000..bcc242173bbe34c756865912a58de6f7a63eabc6 Binary files /dev/null and b/_book/docs/img/9a002df90c6ed1d01c8ae3a9817242df.png differ diff --git a/_book/docs/img/9a996b513114d1fe39fa67c75e54df46.png b/_book/docs/img/9a996b513114d1fe39fa67c75e54df46.png new file mode 100644 index 0000000000000000000000000000000000000000..7a9424eb0de9acd872081424b6b38570122b80f9 Binary files /dev/null and b/_book/docs/img/9a996b513114d1fe39fa67c75e54df46.png differ diff --git a/_book/docs/img/9aa51957855aec8590e352694fe75d5d.png b/_book/docs/img/9aa51957855aec8590e352694fe75d5d.png new file mode 100644 index 0000000000000000000000000000000000000000..7c5531c1603c3a41cdd98ad2e13705a69d666a88 Binary files /dev/null and b/_book/docs/img/9aa51957855aec8590e352694fe75d5d.png differ diff --git a/_book/docs/img/9abb23a34d42854b307382ef64d9a013.png b/_book/docs/img/9abb23a34d42854b307382ef64d9a013.png new file mode 100644 index 0000000000000000000000000000000000000000..aa63c6ea67a6fe50443d5e6883e7db70e5200031 Binary files /dev/null and b/_book/docs/img/9abb23a34d42854b307382ef64d9a013.png differ diff --git a/_book/docs/img/9b6a8d0d96113fcaadd766cecfbecdbc.png b/_book/docs/img/9b6a8d0d96113fcaadd766cecfbecdbc.png new file mode 100644 index 0000000000000000000000000000000000000000..2964219482bbdfb75b51116d8ba5fe8598805eaa Binary files /dev/null and b/_book/docs/img/9b6a8d0d96113fcaadd766cecfbecdbc.png differ diff --git a/_book/docs/img/9bc04e4a71e5ed3917efabdca45725c7.png b/_book/docs/img/9bc04e4a71e5ed3917efabdca45725c7.png new file mode 100644 index 0000000000000000000000000000000000000000..e4661bd012ddb2b790f319a9be2f9bfab3380674 Binary files /dev/null and b/_book/docs/img/9bc04e4a71e5ed3917efabdca45725c7.png differ diff --git a/_book/docs/img/9bf0c7423d5735ccdfbdfe250f9a5452.png b/_book/docs/img/9bf0c7423d5735ccdfbdfe250f9a5452.png new file mode 100644 index 0000000000000000000000000000000000000000..548879d32967becfd210d487f3f6434d9fefa085 Binary files /dev/null and b/_book/docs/img/9bf0c7423d5735ccdfbdfe250f9a5452.png differ diff --git a/_book/docs/img/9cb5bb737c82aad68bc28e2a7357e05c.png b/_book/docs/img/9cb5bb737c82aad68bc28e2a7357e05c.png new file mode 100644 index 0000000000000000000000000000000000000000..8358c7bcd00c4778a1bd79231f053e9c587e48c9 Binary files /dev/null and b/_book/docs/img/9cb5bb737c82aad68bc28e2a7357e05c.png differ diff --git a/_book/docs/img/9cc2ca9eb5afc113cacfbc529374fe3b.png b/_book/docs/img/9cc2ca9eb5afc113cacfbc529374fe3b.png new file mode 100644 index 0000000000000000000000000000000000000000..9511a76fa2634875ef75f017d819701b5c9bb72e Binary files /dev/null and b/_book/docs/img/9cc2ca9eb5afc113cacfbc529374fe3b.png differ diff --git a/_book/docs/img/9d0b2e21b9be06d263674db132420176.png b/_book/docs/img/9d0b2e21b9be06d263674db132420176.png new file mode 100644 index 0000000000000000000000000000000000000000..d5daff1a91098657c12ad2fb5d7240c16936fd36 Binary files /dev/null and b/_book/docs/img/9d0b2e21b9be06d263674db132420176.png differ diff --git a/_book/docs/img/9d8d2ee20801484a30509d79022ce53c.png b/_book/docs/img/9d8d2ee20801484a30509d79022ce53c.png new file mode 100644 index 0000000000000000000000000000000000000000..4a0ab0fbf79d54dd777748431ac6ea9dbfc83059 Binary files /dev/null and b/_book/docs/img/9d8d2ee20801484a30509d79022ce53c.png differ diff --git a/_book/docs/img/9d9a196fe723b5afc79e2d7b29fd0f4d.png b/_book/docs/img/9d9a196fe723b5afc79e2d7b29fd0f4d.png new file mode 100644 index 0000000000000000000000000000000000000000..05f8d96ad6d69f037eec88ac4c6450b7fa61d4a2 Binary files /dev/null and b/_book/docs/img/9d9a196fe723b5afc79e2d7b29fd0f4d.png differ diff --git a/_book/docs/img/9e7b70cdf92b88509713225035e8e964.png b/_book/docs/img/9e7b70cdf92b88509713225035e8e964.png new file mode 100644 index 0000000000000000000000000000000000000000..905a7568ed31e0efb1496b3fe20d279eda62fc63 Binary files /dev/null and b/_book/docs/img/9e7b70cdf92b88509713225035e8e964.png differ diff --git a/_book/docs/img/9e837ca8522bced4f7b219416c893fe4.png b/_book/docs/img/9e837ca8522bced4f7b219416c893fe4.png new file mode 100644 index 0000000000000000000000000000000000000000..e022c55547856040b709786fa9f126e1c52563f2 Binary files /dev/null and b/_book/docs/img/9e837ca8522bced4f7b219416c893fe4.png differ diff --git a/_book/docs/img/9e8d2b5134e62de656bff96c60c04e10.png b/_book/docs/img/9e8d2b5134e62de656bff96c60c04e10.png new file mode 100644 index 0000000000000000000000000000000000000000..f9fd91e8b82900a5ad34708e355f640236f2ae29 Binary files /dev/null and b/_book/docs/img/9e8d2b5134e62de656bff96c60c04e10.png differ diff --git a/_book/docs/img/9f29552692cfb04d323dc62cc4bc1d1e.png b/_book/docs/img/9f29552692cfb04d323dc62cc4bc1d1e.png new file mode 100644 index 0000000000000000000000000000000000000000..d4165b2f6678d7bfae094c300f0f68601ee3a4d1 Binary files /dev/null and b/_book/docs/img/9f29552692cfb04d323dc62cc4bc1d1e.png differ diff --git a/_book/docs/img/9f4a21c247f193621ddd2f709c4536d7.png b/_book/docs/img/9f4a21c247f193621ddd2f709c4536d7.png new file mode 100644 index 0000000000000000000000000000000000000000..514065291c757a1b88c6c102d6cc78601103bb54 Binary files /dev/null and b/_book/docs/img/9f4a21c247f193621ddd2f709c4536d7.png differ diff --git a/_book/docs/img/9f6da2599274d0db274d6aa19a27fcfc.png b/_book/docs/img/9f6da2599274d0db274d6aa19a27fcfc.png new file mode 100644 index 0000000000000000000000000000000000000000..7bea75c9a31653211eead96517c199877a1fcde7 Binary files /dev/null and b/_book/docs/img/9f6da2599274d0db274d6aa19a27fcfc.png differ diff --git a/_book/docs/img/9f6f0b27f8e7df6c95a3262de502b39f.png b/_book/docs/img/9f6f0b27f8e7df6c95a3262de502b39f.png new file mode 100644 index 0000000000000000000000000000000000000000..cbed54dda354028313af2f40b91154a9c00ff1ea Binary files /dev/null and b/_book/docs/img/9f6f0b27f8e7df6c95a3262de502b39f.png differ diff --git a/_book/docs/img/9fa8173be554c09a1397ae7e064f24e5.png b/_book/docs/img/9fa8173be554c09a1397ae7e064f24e5.png new file mode 100644 index 0000000000000000000000000000000000000000..1358a4e7db05da3d8ca14a59515a0951a25b171f Binary files /dev/null and b/_book/docs/img/9fa8173be554c09a1397ae7e064f24e5.png differ diff --git a/_book/docs/img/9fa9d16dd2302ab20167b7ff1ca62575.png b/_book/docs/img/9fa9d16dd2302ab20167b7ff1ca62575.png new file mode 100644 index 0000000000000000000000000000000000000000..499fabf3ece8eeaf949f1ab703d10ec5546aeebb Binary files /dev/null and b/_book/docs/img/9fa9d16dd2302ab20167b7ff1ca62575.png differ diff --git a/_book/docs/img/9fd7b49e564d04c79644e7fb8c7d7d5d.png b/_book/docs/img/9fd7b49e564d04c79644e7fb8c7d7d5d.png new file mode 100644 index 0000000000000000000000000000000000000000..97c585ca676bc84aed2de286d010310a22e6c747 Binary files /dev/null and b/_book/docs/img/9fd7b49e564d04c79644e7fb8c7d7d5d.png differ diff --git a/_book/docs/img/a0ea9fb503066a9bed377bc4dadb0d59.png b/_book/docs/img/a0ea9fb503066a9bed377bc4dadb0d59.png new file mode 100644 index 0000000000000000000000000000000000000000..4c7e36efef6f487783919fa6e420cf98d2b3ca16 Binary files /dev/null and b/_book/docs/img/a0ea9fb503066a9bed377bc4dadb0d59.png differ diff --git a/_book/docs/img/a102a1abbf4c760dba4b8b3daef8fe26.png b/_book/docs/img/a102a1abbf4c760dba4b8b3daef8fe26.png new file mode 100644 index 0000000000000000000000000000000000000000..2912a66ec6b9e12316cd7c740a0b861f0dd29b04 Binary files /dev/null and b/_book/docs/img/a102a1abbf4c760dba4b8b3daef8fe26.png differ diff --git a/_book/docs/img/a14ce4f4a816ce9ceea3133c64b5f328.png b/_book/docs/img/a14ce4f4a816ce9ceea3133c64b5f328.png new file mode 100644 index 0000000000000000000000000000000000000000..7f33003d7013323e620cafaefab138a55ab2975d Binary files /dev/null and b/_book/docs/img/a14ce4f4a816ce9ceea3133c64b5f328.png differ diff --git a/_book/docs/img/a15f0b2964d7094b019c5c33425ba75b.png b/_book/docs/img/a15f0b2964d7094b019c5c33425ba75b.png new file mode 100644 index 0000000000000000000000000000000000000000..759ab0f27882f1c545cbf7a645330dc880c9fea5 Binary files /dev/null and b/_book/docs/img/a15f0b2964d7094b019c5c33425ba75b.png differ diff --git a/_book/docs/img/a198157b454aaa7b52001592ed46dc03.png b/_book/docs/img/a198157b454aaa7b52001592ed46dc03.png new file mode 100644 index 0000000000000000000000000000000000000000..d428c51824415a41242811c472927b5eda5e79ef Binary files /dev/null and b/_book/docs/img/a198157b454aaa7b52001592ed46dc03.png differ diff --git a/_book/docs/img/a19f68ae0d29248e1f28009bfb10a89a.png b/_book/docs/img/a19f68ae0d29248e1f28009bfb10a89a.png new file mode 100644 index 0000000000000000000000000000000000000000..b64866a24e7b211721fd0010bccb6718c82ff4a7 Binary files /dev/null and b/_book/docs/img/a19f68ae0d29248e1f28009bfb10a89a.png differ diff --git a/_book/docs/img/a1efb7c23a97e2901852465c9168914f.png b/_book/docs/img/a1efb7c23a97e2901852465c9168914f.png new file mode 100644 index 0000000000000000000000000000000000000000..0c246896d06e7c8b3104660b4f906b8f65a43ec2 Binary files /dev/null and b/_book/docs/img/a1efb7c23a97e2901852465c9168914f.png differ diff --git a/_book/docs/img/a1f2874d536bbec36fba8132d424e066.png b/_book/docs/img/a1f2874d536bbec36fba8132d424e066.png new file mode 100644 index 0000000000000000000000000000000000000000..3b27fc95801a148a6fdae396d975ec2bd7571d28 Binary files /dev/null and b/_book/docs/img/a1f2874d536bbec36fba8132d424e066.png differ diff --git a/_book/docs/img/a223e320ef570ec303a4e7346a899af7.png b/_book/docs/img/a223e320ef570ec303a4e7346a899af7.png new file mode 100644 index 0000000000000000000000000000000000000000..ee4680727425b30fdde14e9909939fb14d0d5b89 Binary files /dev/null and b/_book/docs/img/a223e320ef570ec303a4e7346a899af7.png differ diff --git a/_book/docs/img/a272933779dc7642aed4eb4acde12df9.png b/_book/docs/img/a272933779dc7642aed4eb4acde12df9.png new file mode 100644 index 0000000000000000000000000000000000000000..706472f77ae85b7c4a5233bcea51f7031e4bacdf Binary files /dev/null and b/_book/docs/img/a272933779dc7642aed4eb4acde12df9.png differ diff --git a/_book/docs/img/a283d966822ac6a760d1a650273fbb3b.png b/_book/docs/img/a283d966822ac6a760d1a650273fbb3b.png new file mode 100644 index 0000000000000000000000000000000000000000..d73bec47477cbf5d0d791e26eabcee94893ee030 Binary files /dev/null and b/_book/docs/img/a283d966822ac6a760d1a650273fbb3b.png differ diff --git a/_book/docs/img/a33f8dce89b50020e90de33ed9a1e78e.png b/_book/docs/img/a33f8dce89b50020e90de33ed9a1e78e.png new file mode 100644 index 0000000000000000000000000000000000000000..cadfa7e6bb6bdf38cc5fcf85ed849b02d4294817 Binary files /dev/null and b/_book/docs/img/a33f8dce89b50020e90de33ed9a1e78e.png differ diff --git a/_book/docs/img/a3626522e1409168b7c977ecebbaee6e.png b/_book/docs/img/a3626522e1409168b7c977ecebbaee6e.png new file mode 100644 index 0000000000000000000000000000000000000000..aead2fe2a47ac9fd9d0f128774384805926e0297 Binary files /dev/null and b/_book/docs/img/a3626522e1409168b7c977ecebbaee6e.png differ diff --git a/_book/docs/img/a3802569c81d8f8dd179fd218322a4ca.png b/_book/docs/img/a3802569c81d8f8dd179fd218322a4ca.png new file mode 100644 index 0000000000000000000000000000000000000000..cf7268c3bb4f054b5e12efd877ab3d8d7caa34ce Binary files /dev/null and b/_book/docs/img/a3802569c81d8f8dd179fd218322a4ca.png differ diff --git a/_book/docs/img/a3964b6d91003c90a72b5ca689b9e0c5.png b/_book/docs/img/a3964b6d91003c90a72b5ca689b9e0c5.png new file mode 100644 index 0000000000000000000000000000000000000000..add03bde76b04b552cc9763ee30cb0df654fe30b Binary files /dev/null and b/_book/docs/img/a3964b6d91003c90a72b5ca689b9e0c5.png differ diff --git a/_book/docs/img/a3acce71246e984986cedc7a1cece8f9.png b/_book/docs/img/a3acce71246e984986cedc7a1cece8f9.png new file mode 100644 index 0000000000000000000000000000000000000000..5a81bf46aa36bddead1a442feea6aa7c4b8c6421 Binary files /dev/null and b/_book/docs/img/a3acce71246e984986cedc7a1cece8f9.png differ diff --git a/_book/docs/img/a3b1935e9fe6f6222ef3200715c2f595.png b/_book/docs/img/a3b1935e9fe6f6222ef3200715c2f595.png new file mode 100644 index 0000000000000000000000000000000000000000..b54e7392d4a1dd891c8d3ff939fabd0c6f884fdd Binary files /dev/null and b/_book/docs/img/a3b1935e9fe6f6222ef3200715c2f595.png differ diff --git a/_book/docs/img/a48fc7b7ef95b54bd7ec66c17cad7dbb.png b/_book/docs/img/a48fc7b7ef95b54bd7ec66c17cad7dbb.png new file mode 100644 index 0000000000000000000000000000000000000000..4cac0ff109c1a31804e34dfab1ecda401c683126 Binary files /dev/null and b/_book/docs/img/a48fc7b7ef95b54bd7ec66c17cad7dbb.png differ diff --git a/_book/docs/img/a4e7c4f55411323814dd3b9cb30ab9f8.png b/_book/docs/img/a4e7c4f55411323814dd3b9cb30ab9f8.png new file mode 100644 index 0000000000000000000000000000000000000000..8929b8646dc33d5dd7eb56fc71b98c818d001c8f Binary files /dev/null and b/_book/docs/img/a4e7c4f55411323814dd3b9cb30ab9f8.png differ diff --git a/_book/docs/img/a5023ba03c96276e989dc4dbff1ca8dd.png b/_book/docs/img/a5023ba03c96276e989dc4dbff1ca8dd.png new file mode 100644 index 0000000000000000000000000000000000000000..bafa95e6d870332a2b86c3e72782e798e03cc312 Binary files /dev/null and b/_book/docs/img/a5023ba03c96276e989dc4dbff1ca8dd.png differ diff --git a/_book/docs/img/a51fbcc597a6bc32e35c13c31799e36c.png b/_book/docs/img/a51fbcc597a6bc32e35c13c31799e36c.png new file mode 100644 index 0000000000000000000000000000000000000000..153c048fd06d301b753d40d1ac5b682d1fd0dc1d Binary files /dev/null and b/_book/docs/img/a51fbcc597a6bc32e35c13c31799e36c.png differ diff --git a/_book/docs/img/a68a3a59d914e3b3ef4b3cd56a67c1e1.png b/_book/docs/img/a68a3a59d914e3b3ef4b3cd56a67c1e1.png new file mode 100644 index 0000000000000000000000000000000000000000..6c5db33e288ecb85b4e510d2ae0606b9e75347d5 Binary files /dev/null and b/_book/docs/img/a68a3a59d914e3b3ef4b3cd56a67c1e1.png differ diff --git a/_book/docs/img/a6d06d0c4a54ff34856e0fbc07a50a60.png b/_book/docs/img/a6d06d0c4a54ff34856e0fbc07a50a60.png new file mode 100644 index 0000000000000000000000000000000000000000..27d3f048c5edff6612537aab3134c5c4f3210447 Binary files /dev/null and b/_book/docs/img/a6d06d0c4a54ff34856e0fbc07a50a60.png differ diff --git a/_book/docs/img/a6d5e94df0d5d50038a0909603d69933.png b/_book/docs/img/a6d5e94df0d5d50038a0909603d69933.png new file mode 100644 index 0000000000000000000000000000000000000000..8ab3f6dfe7d19a238a1be80c99d9fc73711c365d Binary files /dev/null and b/_book/docs/img/a6d5e94df0d5d50038a0909603d69933.png differ diff --git a/_book/docs/img/a6e9b62f94c53cd2f37f7300362137a9.png b/_book/docs/img/a6e9b62f94c53cd2f37f7300362137a9.png new file mode 100644 index 0000000000000000000000000000000000000000..f56472eec79547058fc1f23efeb79bc880b8f21d Binary files /dev/null and b/_book/docs/img/a6e9b62f94c53cd2f37f7300362137a9.png differ diff --git a/_book/docs/img/a792de1a5441a31253d7a939dfd2de54.png b/_book/docs/img/a792de1a5441a31253d7a939dfd2de54.png new file mode 100644 index 0000000000000000000000000000000000000000..0f03bf3b29aea6fa73d656e784562d259d99523d Binary files /dev/null and b/_book/docs/img/a792de1a5441a31253d7a939dfd2de54.png differ diff --git a/_book/docs/img/a7a0c433c6f01281a584ba08db57d159.png b/_book/docs/img/a7a0c433c6f01281a584ba08db57d159.png new file mode 100644 index 0000000000000000000000000000000000000000..49af76d8360c35fee63e3b43595830ab3c2a5956 Binary files /dev/null and b/_book/docs/img/a7a0c433c6f01281a584ba08db57d159.png differ diff --git a/_book/docs/img/a87cd8265a25e22c9a715c6372ff047a.png b/_book/docs/img/a87cd8265a25e22c9a715c6372ff047a.png new file mode 100644 index 0000000000000000000000000000000000000000..839e8222965d0056b017424eb1f825537d0f255b Binary files /dev/null and b/_book/docs/img/a87cd8265a25e22c9a715c6372ff047a.png differ diff --git a/_book/docs/img/a88692f85b1b05ca94199204a3cc1f00.png b/_book/docs/img/a88692f85b1b05ca94199204a3cc1f00.png new file mode 100644 index 0000000000000000000000000000000000000000..559b39dae063895069501d66efa0a6579ed4d2ad Binary files /dev/null and b/_book/docs/img/a88692f85b1b05ca94199204a3cc1f00.png differ diff --git a/_book/docs/img/a8ac57717b491533848b3ebca40aae86.png b/_book/docs/img/a8ac57717b491533848b3ebca40aae86.png new file mode 100644 index 0000000000000000000000000000000000000000..c1c3908f093e9dc9b3639724abde30970939b9fe Binary files /dev/null and b/_book/docs/img/a8ac57717b491533848b3ebca40aae86.png differ diff --git a/_book/docs/img/a9325984eddfbb907563c5bf5003f704.png b/_book/docs/img/a9325984eddfbb907563c5bf5003f704.png new file mode 100644 index 0000000000000000000000000000000000000000..20118b018f4792fd03c4658a5474e34c59e688e5 Binary files /dev/null and b/_book/docs/img/a9325984eddfbb907563c5bf5003f704.png differ diff --git a/_book/docs/img/a93d26d68bbc1f4954a7038e601ba3b6.png b/_book/docs/img/a93d26d68bbc1f4954a7038e601ba3b6.png new file mode 100644 index 0000000000000000000000000000000000000000..1b5a619c08ce1a96a736428e0eb6659e5615f73b Binary files /dev/null and b/_book/docs/img/a93d26d68bbc1f4954a7038e601ba3b6.png differ diff --git a/_book/docs/img/a94b1f6b20cc665168a8d8359d195f78.png b/_book/docs/img/a94b1f6b20cc665168a8d8359d195f78.png new file mode 100644 index 0000000000000000000000000000000000000000..ab33e2a01f50e017e200581857b516f1c6b18077 Binary files /dev/null and b/_book/docs/img/a94b1f6b20cc665168a8d8359d195f78.png differ diff --git a/_book/docs/img/a9880855e171e225a4b6c73ae1790538.png b/_book/docs/img/a9880855e171e225a4b6c73ae1790538.png new file mode 100644 index 0000000000000000000000000000000000000000..42d708786e75e1658b88c83e9050cbef796ce2e3 Binary files /dev/null and b/_book/docs/img/a9880855e171e225a4b6c73ae1790538.png differ diff --git a/_book/docs/img/a9b252d8a3c25b1c5166799c2233c569.png b/_book/docs/img/a9b252d8a3c25b1c5166799c2233c569.png new file mode 100644 index 0000000000000000000000000000000000000000..27c3fb776aca5fe460ed1a3e37717e79909fd742 Binary files /dev/null and b/_book/docs/img/a9b252d8a3c25b1c5166799c2233c569.png differ diff --git a/_book/docs/img/aa2dd1694d7e1573bbd49200ed1ccb04.png b/_book/docs/img/aa2dd1694d7e1573bbd49200ed1ccb04.png new file mode 100644 index 0000000000000000000000000000000000000000..218b8281245915eb85f73b72529c02550d647bef Binary files /dev/null and b/_book/docs/img/aa2dd1694d7e1573bbd49200ed1ccb04.png differ diff --git a/_book/docs/img/aabf40f234d995e031a5a1a0f66b5905.png b/_book/docs/img/aabf40f234d995e031a5a1a0f66b5905.png new file mode 100644 index 0000000000000000000000000000000000000000..2fd16f55526288e45a5e64645766da642f36214c Binary files /dev/null and b/_book/docs/img/aabf40f234d995e031a5a1a0f66b5905.png differ diff --git a/_book/docs/img/aafa273009fd04415444f040f8b4c6cc.png b/_book/docs/img/aafa273009fd04415444f040f8b4c6cc.png new file mode 100644 index 0000000000000000000000000000000000000000..ae744c8c43926be42dff1491c2625f8eb658625d Binary files /dev/null and b/_book/docs/img/aafa273009fd04415444f040f8b4c6cc.png differ diff --git a/_book/docs/img/ab48b86f7a0dfe92d4358f705bf938a8.png b/_book/docs/img/ab48b86f7a0dfe92d4358f705bf938a8.png new file mode 100644 index 0000000000000000000000000000000000000000..6ce494e995e32ef5567d85229f66714f62535f9a Binary files /dev/null and b/_book/docs/img/ab48b86f7a0dfe92d4358f705bf938a8.png differ diff --git a/_book/docs/img/abdf7941c6dc575d115b24d74a80a68b.png b/_book/docs/img/abdf7941c6dc575d115b24d74a80a68b.png new file mode 100644 index 0000000000000000000000000000000000000000..48cb84b22a9346656e56f5da3def9a562df29c16 Binary files /dev/null and b/_book/docs/img/abdf7941c6dc575d115b24d74a80a68b.png differ diff --git a/_book/docs/img/ac3623994213ad815a95e7826a3cfc3e.png b/_book/docs/img/ac3623994213ad815a95e7826a3cfc3e.png new file mode 100644 index 0000000000000000000000000000000000000000..ee00cc9bd62c174e9b5a4ce6ef75f1597369c532 Binary files /dev/null and b/_book/docs/img/ac3623994213ad815a95e7826a3cfc3e.png differ diff --git a/_book/docs/img/ad2cdacdd36348cddf7d5c19d8940d5b.png b/_book/docs/img/ad2cdacdd36348cddf7d5c19d8940d5b.png new file mode 100644 index 0000000000000000000000000000000000000000..ccf6173f96cd807cbca78dc21d59015149db0226 Binary files /dev/null and b/_book/docs/img/ad2cdacdd36348cddf7d5c19d8940d5b.png differ diff --git a/_book/docs/img/ad33446e7ba7897d31835424ce5e1feb.png b/_book/docs/img/ad33446e7ba7897d31835424ce5e1feb.png new file mode 100644 index 0000000000000000000000000000000000000000..8ba6922f114936b8948fdd03ed9169f748eded99 Binary files /dev/null and b/_book/docs/img/ad33446e7ba7897d31835424ce5e1feb.png differ diff --git a/_book/docs/img/ad8ac82c77beb415e901040df8d93b17.png b/_book/docs/img/ad8ac82c77beb415e901040df8d93b17.png new file mode 100644 index 0000000000000000000000000000000000000000..8de97ab4d0dcce89063c576be8448e2fa0ddfa1b Binary files /dev/null and b/_book/docs/img/ad8ac82c77beb415e901040df8d93b17.png differ diff --git a/_book/docs/img/adc0d64a6c4c1979d43d8bf1d8d485e8.png b/_book/docs/img/adc0d64a6c4c1979d43d8bf1d8d485e8.png new file mode 100644 index 0000000000000000000000000000000000000000..a62fd57f2b02ab604bcf3885794cb598a0975870 Binary files /dev/null and b/_book/docs/img/adc0d64a6c4c1979d43d8bf1d8d485e8.png differ diff --git a/_book/docs/img/adf6de6d0c4125be4e7a25119c0193e1.png b/_book/docs/img/adf6de6d0c4125be4e7a25119c0193e1.png new file mode 100644 index 0000000000000000000000000000000000000000..81227650adac335954dfcc2a47c3b00885061f12 Binary files /dev/null and b/_book/docs/img/adf6de6d0c4125be4e7a25119c0193e1.png differ diff --git a/_book/docs/img/ae307552914d8ff018365bbde4d23479.png b/_book/docs/img/ae307552914d8ff018365bbde4d23479.png new file mode 100644 index 0000000000000000000000000000000000000000..0bdf664946b86acac6c9e0c3482ae00c07bbb43d Binary files /dev/null and b/_book/docs/img/ae307552914d8ff018365bbde4d23479.png differ diff --git a/_book/docs/img/ae54430a80c08d51c51659ac1a4dd8b9.png b/_book/docs/img/ae54430a80c08d51c51659ac1a4dd8b9.png new file mode 100644 index 0000000000000000000000000000000000000000..ba72fe3f41ea641985f5c1e7a81bda728517f4ae Binary files /dev/null and b/_book/docs/img/ae54430a80c08d51c51659ac1a4dd8b9.png differ diff --git a/_book/docs/img/ae5a500e2333874603b33328b017eb35.png b/_book/docs/img/ae5a500e2333874603b33328b017eb35.png new file mode 100644 index 0000000000000000000000000000000000000000..c63975ff5de98c7fc068928043358c1cb172c984 Binary files /dev/null and b/_book/docs/img/ae5a500e2333874603b33328b017eb35.png differ diff --git a/_book/docs/img/ae9e67c8841e45007cf186891963198f.png b/_book/docs/img/ae9e67c8841e45007cf186891963198f.png new file mode 100644 index 0000000000000000000000000000000000000000..c8e2e9fb3800b7c01fccc35205797f2b9f71e7ef Binary files /dev/null and b/_book/docs/img/ae9e67c8841e45007cf186891963198f.png differ diff --git a/_book/docs/img/aec2abca2644938484258f63a3df71d2.png b/_book/docs/img/aec2abca2644938484258f63a3df71d2.png new file mode 100644 index 0000000000000000000000000000000000000000..d99590be8c25f872c5ea4476bac5110964fb2337 Binary files /dev/null and b/_book/docs/img/aec2abca2644938484258f63a3df71d2.png differ diff --git a/_book/docs/img/aeccb5cc55fc430d8645e67086388300.png b/_book/docs/img/aeccb5cc55fc430d8645e67086388300.png new file mode 100644 index 0000000000000000000000000000000000000000..c7d457e58c0be01a3ce30a95db6f2a6900dd0115 Binary files /dev/null and b/_book/docs/img/aeccb5cc55fc430d8645e67086388300.png differ diff --git a/_book/docs/img/afdb4890858bdb916f8a393b22b8ef96.png b/_book/docs/img/afdb4890858bdb916f8a393b22b8ef96.png new file mode 100644 index 0000000000000000000000000000000000000000..57995b05db7764d197488dfc2005a24d77d45156 Binary files /dev/null and b/_book/docs/img/afdb4890858bdb916f8a393b22b8ef96.png differ diff --git a/_book/docs/img/afe1906c0ba8e9c44277342a20a48db6.png b/_book/docs/img/afe1906c0ba8e9c44277342a20a48db6.png new file mode 100644 index 0000000000000000000000000000000000000000..a19fad9620c93b9bbec2e479dfa920c8a71b3280 Binary files /dev/null and b/_book/docs/img/afe1906c0ba8e9c44277342a20a48db6.png differ diff --git a/_book/docs/img/afec6ffec0973dba40a3e3bc2c244bad.png b/_book/docs/img/afec6ffec0973dba40a3e3bc2c244bad.png new file mode 100644 index 0000000000000000000000000000000000000000..d3773361ffde392ecc8a538723eef55d28954f23 Binary files /dev/null and b/_book/docs/img/afec6ffec0973dba40a3e3bc2c244bad.png differ diff --git a/_book/docs/img/b061980557a1e04fe2a2f3836b8dd9c1.png b/_book/docs/img/b061980557a1e04fe2a2f3836b8dd9c1.png new file mode 100644 index 0000000000000000000000000000000000000000..3b14141416953d983010bb4cc566c2f489f80ff6 Binary files /dev/null and b/_book/docs/img/b061980557a1e04fe2a2f3836b8dd9c1.png differ diff --git a/_book/docs/img/b12f4326b7cccf6e82c375163842f58e.png b/_book/docs/img/b12f4326b7cccf6e82c375163842f58e.png new file mode 100644 index 0000000000000000000000000000000000000000..2bec00864fe3a8619b1f45ffac1dc89888579b23 Binary files /dev/null and b/_book/docs/img/b12f4326b7cccf6e82c375163842f58e.png differ diff --git a/_book/docs/img/b132b9b00d4641da41d2cb7dca5ea55c.png b/_book/docs/img/b132b9b00d4641da41d2cb7dca5ea55c.png new file mode 100644 index 0000000000000000000000000000000000000000..eb0a0ff49b0ef41332144934896544eca741f962 Binary files /dev/null and b/_book/docs/img/b132b9b00d4641da41d2cb7dca5ea55c.png differ diff --git a/_book/docs/img/b15b2918f982a43ce2379b4f2ec765a9.png b/_book/docs/img/b15b2918f982a43ce2379b4f2ec765a9.png new file mode 100644 index 0000000000000000000000000000000000000000..2b7be1136039bec35bc804b50460ed833fb13bed Binary files /dev/null and b/_book/docs/img/b15b2918f982a43ce2379b4f2ec765a9.png differ diff --git a/_book/docs/img/b1b6eda7a121cb284375e6c83317263d.png b/_book/docs/img/b1b6eda7a121cb284375e6c83317263d.png new file mode 100644 index 0000000000000000000000000000000000000000..12b6f2ac2fc41bb659138ba40651fca4a5ed681d Binary files /dev/null and b/_book/docs/img/b1b6eda7a121cb284375e6c83317263d.png differ diff --git a/_book/docs/img/b1edf28a1aa5c59ffa779a574c4fc548.png b/_book/docs/img/b1edf28a1aa5c59ffa779a574c4fc548.png new file mode 100644 index 0000000000000000000000000000000000000000..5db30e2c20eba2a1e58370521e1f323b289ae504 Binary files /dev/null and b/_book/docs/img/b1edf28a1aa5c59ffa779a574c4fc548.png differ diff --git a/_book/docs/img/b203ae7a973815c03ea680032d1e75eb.png b/_book/docs/img/b203ae7a973815c03ea680032d1e75eb.png new file mode 100644 index 0000000000000000000000000000000000000000..6e5f6ffe9d2489a4a09e422e298f78fc8d7433ad Binary files /dev/null and b/_book/docs/img/b203ae7a973815c03ea680032d1e75eb.png differ diff --git a/_book/docs/img/b22d9654d7ad1868d2368d7e3f82e9a3.png b/_book/docs/img/b22d9654d7ad1868d2368d7e3f82e9a3.png new file mode 100644 index 0000000000000000000000000000000000000000..765ec4a2616c83809f9d0ff034aa3a07e60211b9 Binary files /dev/null and b/_book/docs/img/b22d9654d7ad1868d2368d7e3f82e9a3.png differ diff --git a/_book/docs/img/b2499f834ff0e8252829dd96bad93d97.png b/_book/docs/img/b2499f834ff0e8252829dd96bad93d97.png new file mode 100644 index 0000000000000000000000000000000000000000..bee411f26e8aba678638c5bfc4fda1e2bcbef840 Binary files /dev/null and b/_book/docs/img/b2499f834ff0e8252829dd96bad93d97.png differ diff --git a/_book/docs/img/b24c623173b50fdf9cd2676f1f311580.png b/_book/docs/img/b24c623173b50fdf9cd2676f1f311580.png new file mode 100644 index 0000000000000000000000000000000000000000..352e6ddaad0646f748a2148d22641a1be6a4607d Binary files /dev/null and b/_book/docs/img/b24c623173b50fdf9cd2676f1f311580.png differ diff --git a/_book/docs/img/b36e59e0da065f17e34891efef2ee0a1.png b/_book/docs/img/b36e59e0da065f17e34891efef2ee0a1.png new file mode 100644 index 0000000000000000000000000000000000000000..f117a230e175adcc0dc9f4b3df03d53877979b98 Binary files /dev/null and b/_book/docs/img/b36e59e0da065f17e34891efef2ee0a1.png differ diff --git a/_book/docs/img/b379b1821f4b3d10ab0be61a59bcd491.png b/_book/docs/img/b379b1821f4b3d10ab0be61a59bcd491.png new file mode 100644 index 0000000000000000000000000000000000000000..7780e3331837ee25ce8be65be61c290ab5ec4fd7 Binary files /dev/null and b/_book/docs/img/b379b1821f4b3d10ab0be61a59bcd491.png differ diff --git a/_book/docs/img/b44c56313892b2d78da86b3f64519a98.png b/_book/docs/img/b44c56313892b2d78da86b3f64519a98.png new file mode 100644 index 0000000000000000000000000000000000000000..56551e85e5723ce3b3c8304928ac48aa272747c9 Binary files /dev/null and b/_book/docs/img/b44c56313892b2d78da86b3f64519a98.png differ diff --git a/_book/docs/img/b452a194fd7fbbdd22f73a1dda9b236a.png b/_book/docs/img/b452a194fd7fbbdd22f73a1dda9b236a.png new file mode 100644 index 0000000000000000000000000000000000000000..ff22790dfd9b6698add0b33b2c058fc020ec5204 Binary files /dev/null and b/_book/docs/img/b452a194fd7fbbdd22f73a1dda9b236a.png differ diff --git a/_book/docs/img/b46359f55df1f2affc4fe493965ebd0a.png b/_book/docs/img/b46359f55df1f2affc4fe493965ebd0a.png new file mode 100644 index 0000000000000000000000000000000000000000..8a48deca8b626134e3c2e72d4d55c08b8586bdb9 Binary files /dev/null and b/_book/docs/img/b46359f55df1f2affc4fe493965ebd0a.png differ diff --git a/_book/docs/img/b4a1ffd094e753d655825c1385561991.png b/_book/docs/img/b4a1ffd094e753d655825c1385561991.png new file mode 100644 index 0000000000000000000000000000000000000000..97c2da4bd72008263abdd0c62f59a6108b4b1d13 Binary files /dev/null and b/_book/docs/img/b4a1ffd094e753d655825c1385561991.png differ diff --git a/_book/docs/img/b4e4d114d9b2244a7848961617e05a95.png b/_book/docs/img/b4e4d114d9b2244a7848961617e05a95.png new file mode 100644 index 0000000000000000000000000000000000000000..79c081880e15e905b18b2ebcda140671c92c6d2b Binary files /dev/null and b/_book/docs/img/b4e4d114d9b2244a7848961617e05a95.png differ diff --git a/_book/docs/img/b4e821b8b83e29e837f01f4620e557b7.png b/_book/docs/img/b4e821b8b83e29e837f01f4620e557b7.png new file mode 100644 index 0000000000000000000000000000000000000000..dc724aa6e8ecbf235608905f92197255ef127fa0 Binary files /dev/null and b/_book/docs/img/b4e821b8b83e29e837f01f4620e557b7.png differ diff --git a/_book/docs/img/b51efc1bf28d2363ac0b4e95c4318fbe.png b/_book/docs/img/b51efc1bf28d2363ac0b4e95c4318fbe.png new file mode 100644 index 0000000000000000000000000000000000000000..04697a910ebd1ccf1038bc587b3e63a506d86bd2 Binary files /dev/null and b/_book/docs/img/b51efc1bf28d2363ac0b4e95c4318fbe.png differ diff --git a/_book/docs/img/b6069220bf06467d1d434d3652c5d82a.png b/_book/docs/img/b6069220bf06467d1d434d3652c5d82a.png new file mode 100644 index 0000000000000000000000000000000000000000..638bf431f8f46a8635e7952de82adeffec2e8a2a Binary files /dev/null and b/_book/docs/img/b6069220bf06467d1d434d3652c5d82a.png differ diff --git a/_book/docs/img/b62968cd49816ab794ddd37a7dcfb7a2.png b/_book/docs/img/b62968cd49816ab794ddd37a7dcfb7a2.png new file mode 100644 index 0000000000000000000000000000000000000000..da7ab5eb5a02f846e4272b7345cfb47ae952c873 Binary files /dev/null and b/_book/docs/img/b62968cd49816ab794ddd37a7dcfb7a2.png differ diff --git a/_book/docs/img/b64907bafa7c740c069ec7395a5c5471.png b/_book/docs/img/b64907bafa7c740c069ec7395a5c5471.png new file mode 100644 index 0000000000000000000000000000000000000000..a3f6631dab9c8138337c29475d5d0cedbb5357ae Binary files /dev/null and b/_book/docs/img/b64907bafa7c740c069ec7395a5c5471.png differ diff --git a/_book/docs/img/b6662e0dd306cb7949bbfd70db9b384c.png b/_book/docs/img/b6662e0dd306cb7949bbfd70db9b384c.png new file mode 100644 index 0000000000000000000000000000000000000000..6b306ecea8bb478c70f2254a7a7218105bf7b6f6 Binary files /dev/null and b/_book/docs/img/b6662e0dd306cb7949bbfd70db9b384c.png differ diff --git a/_book/docs/img/b6696ad0d59c74a9a3974493085915f9.png b/_book/docs/img/b6696ad0d59c74a9a3974493085915f9.png new file mode 100644 index 0000000000000000000000000000000000000000..68e6c595f7a4b968634f76486218e08519d0e7a8 Binary files /dev/null and b/_book/docs/img/b6696ad0d59c74a9a3974493085915f9.png differ diff --git a/_book/docs/img/b66dc4137ac73e81c66e408cf9fcf391.png b/_book/docs/img/b66dc4137ac73e81c66e408cf9fcf391.png new file mode 100644 index 0000000000000000000000000000000000000000..ad84c63c80e96567f87f0476041e5fd97e2fc0b6 Binary files /dev/null and b/_book/docs/img/b66dc4137ac73e81c66e408cf9fcf391.png differ diff --git a/_book/docs/img/b6a9c5aa2e348263baf61cb961ac802f.png b/_book/docs/img/b6a9c5aa2e348263baf61cb961ac802f.png new file mode 100644 index 0000000000000000000000000000000000000000..06d66c59ce12017613e2289da62547b6ec646096 Binary files /dev/null and b/_book/docs/img/b6a9c5aa2e348263baf61cb961ac802f.png differ diff --git a/_book/docs/img/b6c59d6785a7941658315a7e8e148751.png b/_book/docs/img/b6c59d6785a7941658315a7e8e148751.png new file mode 100644 index 0000000000000000000000000000000000000000..71c083d6f3540e311c898a801f8ab14740757627 Binary files /dev/null and b/_book/docs/img/b6c59d6785a7941658315a7e8e148751.png differ diff --git a/_book/docs/img/b6d33f6e98bcf842659df9a637bbaeb9.png b/_book/docs/img/b6d33f6e98bcf842659df9a637bbaeb9.png new file mode 100644 index 0000000000000000000000000000000000000000..d6146377fa6715d7ef1521d75766912cce7ad839 Binary files /dev/null and b/_book/docs/img/b6d33f6e98bcf842659df9a637bbaeb9.png differ diff --git a/_book/docs/img/b6f3d1302a444a29689905582d97eb84.png b/_book/docs/img/b6f3d1302a444a29689905582d97eb84.png new file mode 100644 index 0000000000000000000000000000000000000000..2b406ae27c830fbe0439db2073fa1c8f537dc6f8 Binary files /dev/null and b/_book/docs/img/b6f3d1302a444a29689905582d97eb84.png differ diff --git a/_book/docs/img/b7658a174f8b110251a289f5276dc822.png b/_book/docs/img/b7658a174f8b110251a289f5276dc822.png new file mode 100644 index 0000000000000000000000000000000000000000..2d0432673698fdb20b2c967df8550e96f0d01e24 Binary files /dev/null and b/_book/docs/img/b7658a174f8b110251a289f5276dc822.png differ diff --git a/_book/docs/img/b786322ea49fe7840203db128b72a5e0.png b/_book/docs/img/b786322ea49fe7840203db128b72a5e0.png new file mode 100644 index 0000000000000000000000000000000000000000..b5ae858a0c5b72ed3ca8b3b722cc7587a5f8fa2e Binary files /dev/null and b/_book/docs/img/b786322ea49fe7840203db128b72a5e0.png differ diff --git a/_book/docs/img/b820c73810583190a0b1697c813fdda8.png b/_book/docs/img/b820c73810583190a0b1697c813fdda8.png new file mode 100644 index 0000000000000000000000000000000000000000..78ad0a1ea62cc56b72736f9c143bd696faa0dac2 Binary files /dev/null and b/_book/docs/img/b820c73810583190a0b1697c813fdda8.png differ diff --git a/_book/docs/img/b962444c71ad27ba05dfc6bfc69269f4.png b/_book/docs/img/b962444c71ad27ba05dfc6bfc69269f4.png new file mode 100644 index 0000000000000000000000000000000000000000..71c3d8d44d05ae13d88c4213dc7b6a1030452761 Binary files /dev/null and b/_book/docs/img/b962444c71ad27ba05dfc6bfc69269f4.png differ diff --git a/_book/docs/img/b96e754d4dd8ba06065aac231327e160.png b/_book/docs/img/b96e754d4dd8ba06065aac231327e160.png new file mode 100644 index 0000000000000000000000000000000000000000..3861d687ef7a1147353ec0003bfabfd106bea6d8 Binary files /dev/null and b/_book/docs/img/b96e754d4dd8ba06065aac231327e160.png differ diff --git a/_book/docs/img/b98f1bb6205ce5c692946b81e8c78003.png b/_book/docs/img/b98f1bb6205ce5c692946b81e8c78003.png new file mode 100644 index 0000000000000000000000000000000000000000..949143c71358790f643d49429ab174de9587de5b Binary files /dev/null and b/_book/docs/img/b98f1bb6205ce5c692946b81e8c78003.png differ diff --git a/_book/docs/img/ba294e1cb39daadf43b81f113e5ef506.png b/_book/docs/img/ba294e1cb39daadf43b81f113e5ef506.png new file mode 100644 index 0000000000000000000000000000000000000000..d4351aeaec93607a65b4ff10278f979df06db625 Binary files /dev/null and b/_book/docs/img/ba294e1cb39daadf43b81f113e5ef506.png differ diff --git a/_book/docs/img/ba685b05a8bb7c09fe3b58048ac4884e.png b/_book/docs/img/ba685b05a8bb7c09fe3b58048ac4884e.png new file mode 100644 index 0000000000000000000000000000000000000000..b756d55ed873b184dd6c8d07f510b155d9cd92c0 Binary files /dev/null and b/_book/docs/img/ba685b05a8bb7c09fe3b58048ac4884e.png differ diff --git a/_book/docs/img/baa29e50412ef4acd25e287681ad9e9e.png b/_book/docs/img/baa29e50412ef4acd25e287681ad9e9e.png new file mode 100644 index 0000000000000000000000000000000000000000..e6e6f139e50c84ab3537b12ec95bf6eff8f59801 Binary files /dev/null and b/_book/docs/img/baa29e50412ef4acd25e287681ad9e9e.png differ diff --git a/_book/docs/img/bab81ba0a915cec8b039166d2defc074.png b/_book/docs/img/bab81ba0a915cec8b039166d2defc074.png new file mode 100644 index 0000000000000000000000000000000000000000..d1bf838bfaddb841804bd45fb6225b6046f57290 Binary files /dev/null and b/_book/docs/img/bab81ba0a915cec8b039166d2defc074.png differ diff --git a/_book/docs/img/bab86c57be5bd24c1329a7de56df456a.png b/_book/docs/img/bab86c57be5bd24c1329a7de56df456a.png new file mode 100644 index 0000000000000000000000000000000000000000..c32f7cbd24c265d2b2b3cc959371327626915af5 Binary files /dev/null and b/_book/docs/img/bab86c57be5bd24c1329a7de56df456a.png differ diff --git a/_book/docs/img/bad584bc95c83e26be6c67a2b54b26ae.png b/_book/docs/img/bad584bc95c83e26be6c67a2b54b26ae.png new file mode 100644 index 0000000000000000000000000000000000000000..8547e102032b27d7c600fe30c99736db9ba7f258 Binary files /dev/null and b/_book/docs/img/bad584bc95c83e26be6c67a2b54b26ae.png differ diff --git a/_book/docs/img/bad7cd1d32a4bbf53fc1d27dcb3dd211.png b/_book/docs/img/bad7cd1d32a4bbf53fc1d27dcb3dd211.png new file mode 100644 index 0000000000000000000000000000000000000000..0a6d821bc02b81d60ed9dabc96cb53653d3ee81c --- /dev/null +++ b/_book/docs/img/bad7cd1d32a4bbf53fc1d27dcb3dd211.png @@ -0,0 +1,265 @@ + + + +Page Not Found | GitLab Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    +
    +
    +
    +
    +404 +
    +
    +
    +
    +
    + + + + + + + +
    +
    +
    + +
    +
    +
    +
    + +
    +
    + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_book/docs/img/bb46a964436bb5fa1becb0900b9b0fc3.png b/_book/docs/img/bb46a964436bb5fa1becb0900b9b0fc3.png new file mode 100644 index 0000000000000000000000000000000000000000..c7c4fa75cf5879731178e811d84d407866f4b3b6 Binary files /dev/null and b/_book/docs/img/bb46a964436bb5fa1becb0900b9b0fc3.png differ diff --git a/_book/docs/img/bb7ff3b17ad66e05a64ee12def63524b.png b/_book/docs/img/bb7ff3b17ad66e05a64ee12def63524b.png new file mode 100644 index 0000000000000000000000000000000000000000..144019279484cfda29567a8e3dc12f0f25d0df57 Binary files /dev/null and b/_book/docs/img/bb7ff3b17ad66e05a64ee12def63524b.png differ diff --git a/_book/docs/img/bba7007707d548d73c9b6f0efad3c50b.png b/_book/docs/img/bba7007707d548d73c9b6f0efad3c50b.png new file mode 100644 index 0000000000000000000000000000000000000000..a2350c299094af4a2b2ed8a615371206c788ebc1 Binary files /dev/null and b/_book/docs/img/bba7007707d548d73c9b6f0efad3c50b.png differ diff --git a/_book/docs/img/bc03121106ba9696b67a617d6aeb3878.png b/_book/docs/img/bc03121106ba9696b67a617d6aeb3878.png new file mode 100644 index 0000000000000000000000000000000000000000..93855662ceb2f3243cba6716bfb099ed897e4440 Binary files /dev/null and b/_book/docs/img/bc03121106ba9696b67a617d6aeb3878.png differ diff --git a/_book/docs/img/bcbedbd56c50879eb35c2fc2f534d693.png b/_book/docs/img/bcbedbd56c50879eb35c2fc2f534d693.png new file mode 100644 index 0000000000000000000000000000000000000000..f0786ad45f344649df274f6653c5cea86ab49a0e Binary files /dev/null and b/_book/docs/img/bcbedbd56c50879eb35c2fc2f534d693.png differ diff --git a/_book/docs/img/bccfe6e36a18f67a038a8d90f2a6499f.png b/_book/docs/img/bccfe6e36a18f67a038a8d90f2a6499f.png new file mode 100644 index 0000000000000000000000000000000000000000..3952c9ca5360d3a5d913ddd55b33450a1edd7d45 Binary files /dev/null and b/_book/docs/img/bccfe6e36a18f67a038a8d90f2a6499f.png differ diff --git a/_book/docs/img/bd8c2bfd77b1834503e87e4dc5b58420.png b/_book/docs/img/bd8c2bfd77b1834503e87e4dc5b58420.png new file mode 100644 index 0000000000000000000000000000000000000000..28e9b47ef10a70699090cc282e0153bcbeb12ea8 Binary files /dev/null and b/_book/docs/img/bd8c2bfd77b1834503e87e4dc5b58420.png differ diff --git a/_book/docs/img/bde796b0c195045db9849eef2842bd0e.png b/_book/docs/img/bde796b0c195045db9849eef2842bd0e.png new file mode 100644 index 0000000000000000000000000000000000000000..a8f2687dc03ee89ed21953b28475780562623a28 Binary files /dev/null and b/_book/docs/img/bde796b0c195045db9849eef2842bd0e.png differ diff --git a/_book/docs/img/be1eaf723e0603b081c01aa4310c304c.png b/_book/docs/img/be1eaf723e0603b081c01aa4310c304c.png new file mode 100644 index 0000000000000000000000000000000000000000..9ec46ca556f97be9741defc28442a5b4085ccb2b Binary files /dev/null and b/_book/docs/img/be1eaf723e0603b081c01aa4310c304c.png differ diff --git a/_book/docs/img/be7e963d6561756bb87f6fea0cd245fa.png b/_book/docs/img/be7e963d6561756bb87f6fea0cd245fa.png new file mode 100644 index 0000000000000000000000000000000000000000..5a102a9587a6bc1f8be4c279b2c95d13fe4e54c9 Binary files /dev/null and b/_book/docs/img/be7e963d6561756bb87f6fea0cd245fa.png differ diff --git a/_book/docs/img/bec396562e8fe025cb7009de091ff2aa.png b/_book/docs/img/bec396562e8fe025cb7009de091ff2aa.png new file mode 100644 index 0000000000000000000000000000000000000000..7443c06c52bf4b774d9b008b8fc7e5946a5d68a6 Binary files /dev/null and b/_book/docs/img/bec396562e8fe025cb7009de091ff2aa.png differ diff --git a/_book/docs/img/bed33522d3ca08c8f5c920ba11fa05d4.png b/_book/docs/img/bed33522d3ca08c8f5c920ba11fa05d4.png new file mode 100644 index 0000000000000000000000000000000000000000..670586a92df42b954c99e85b642a819f3a600193 Binary files /dev/null and b/_book/docs/img/bed33522d3ca08c8f5c920ba11fa05d4.png differ diff --git a/_book/docs/img/bf46825f18b4b1998d719dffeab0c45c.png b/_book/docs/img/bf46825f18b4b1998d719dffeab0c45c.png new file mode 100644 index 0000000000000000000000000000000000000000..b113bb56cb986f6506c765e82645fae3f0fff5e8 Binary files /dev/null and b/_book/docs/img/bf46825f18b4b1998d719dffeab0c45c.png differ diff --git a/_book/docs/img/bf99e217a01388f7c11df39626ab9e22.png b/_book/docs/img/bf99e217a01388f7c11df39626ab9e22.png new file mode 100644 index 0000000000000000000000000000000000000000..1fc478842f51e7519866f474a02ad605235bc6a6 Binary files /dev/null and b/_book/docs/img/bf99e217a01388f7c11df39626ab9e22.png differ diff --git a/_book/docs/img/c01efbb34a741e385a7089a6799e9b59.png b/_book/docs/img/c01efbb34a741e385a7089a6799e9b59.png new file mode 100644 index 0000000000000000000000000000000000000000..6f40bf22159402d7515e1d32af40f22b0febae8b Binary files /dev/null and b/_book/docs/img/c01efbb34a741e385a7089a6799e9b59.png differ diff --git a/_book/docs/img/c07889c4060a55eccd0e5dde9cb54f74.png b/_book/docs/img/c07889c4060a55eccd0e5dde9cb54f74.png new file mode 100644 index 0000000000000000000000000000000000000000..b055f8e7a8595e8830394ebbd4a11a128c9dedf1 Binary files /dev/null and b/_book/docs/img/c07889c4060a55eccd0e5dde9cb54f74.png differ diff --git a/_book/docs/img/c0fd76908cea66a75fbd88aeb1ccec31.png b/_book/docs/img/c0fd76908cea66a75fbd88aeb1ccec31.png new file mode 100644 index 0000000000000000000000000000000000000000..144eac7b1ed984878167ba36a617204ba35a21c4 Binary files /dev/null and b/_book/docs/img/c0fd76908cea66a75fbd88aeb1ccec31.png differ diff --git a/_book/docs/img/c10c0f19a1d0076044db1057cfb19875.png b/_book/docs/img/c10c0f19a1d0076044db1057cfb19875.png new file mode 100644 index 0000000000000000000000000000000000000000..f95fbc9027c108809d096a174b3ca2a921ae1e30 Binary files /dev/null and b/_book/docs/img/c10c0f19a1d0076044db1057cfb19875.png differ diff --git a/_book/docs/img/c154238c63e38411889c5647b2cdf20e.png b/_book/docs/img/c154238c63e38411889c5647b2cdf20e.png new file mode 100644 index 0000000000000000000000000000000000000000..74c93a6238c574dc4a5b330b4bae07f3925e2cca Binary files /dev/null and b/_book/docs/img/c154238c63e38411889c5647b2cdf20e.png differ diff --git a/_book/docs/img/c17db26d06341055b4834c8be77c604b.png b/_book/docs/img/c17db26d06341055b4834c8be77c604b.png new file mode 100644 index 0000000000000000000000000000000000000000..7005fb039ae313bd7198f9092b82348d675576d4 Binary files /dev/null and b/_book/docs/img/c17db26d06341055b4834c8be77c604b.png differ diff --git a/_book/docs/img/c187176d6b8d40e19db360c4c68ffb46.png b/_book/docs/img/c187176d6b8d40e19db360c4c68ffb46.png new file mode 100644 index 0000000000000000000000000000000000000000..bda4bb03e089ddef0aad1e71eb4a04c51034a2f2 Binary files /dev/null and b/_book/docs/img/c187176d6b8d40e19db360c4c68ffb46.png differ diff --git a/_book/docs/img/c187de65e481b5598b110fee5310776c.png b/_book/docs/img/c187de65e481b5598b110fee5310776c.png new file mode 100644 index 0000000000000000000000000000000000000000..5b38f138428421b90790b095d0487e0535acf222 Binary files /dev/null and b/_book/docs/img/c187de65e481b5598b110fee5310776c.png differ diff --git a/_book/docs/img/c1e086b58ff99dd5c5684a4571e568e3.png b/_book/docs/img/c1e086b58ff99dd5c5684a4571e568e3.png new file mode 100644 index 0000000000000000000000000000000000000000..1ee416d3ce9993cd5973e8b47c79d3fe89470eed Binary files /dev/null and b/_book/docs/img/c1e086b58ff99dd5c5684a4571e568e3.png differ diff --git a/_book/docs/img/c1ff864dc0ff6749087bc64b4781d767.png b/_book/docs/img/c1ff864dc0ff6749087bc64b4781d767.png new file mode 100644 index 0000000000000000000000000000000000000000..604b2e31f05d8c99cd3228a474bc87a9c52e2bc0 Binary files /dev/null and b/_book/docs/img/c1ff864dc0ff6749087bc64b4781d767.png differ diff --git a/_book/docs/img/c29b503c10922622f8ec612bd5168b10.png b/_book/docs/img/c29b503c10922622f8ec612bd5168b10.png new file mode 100644 index 0000000000000000000000000000000000000000..e4be6e19addd9076d1d4910fe3e925c898cd85e5 Binary files /dev/null and b/_book/docs/img/c29b503c10922622f8ec612bd5168b10.png differ diff --git a/_book/docs/img/c2b9039967ef1a229c8db9d7542591fb.png b/_book/docs/img/c2b9039967ef1a229c8db9d7542591fb.png new file mode 100644 index 0000000000000000000000000000000000000000..bf723ef20c5cb99e7af02f417733a1db2e2428a6 Binary files /dev/null and b/_book/docs/img/c2b9039967ef1a229c8db9d7542591fb.png differ diff --git a/_book/docs/img/c2f9cb2f2c88244b3dbf094572214a02.png b/_book/docs/img/c2f9cb2f2c88244b3dbf094572214a02.png new file mode 100644 index 0000000000000000000000000000000000000000..6c73667aebb2282e9fb0b128dba843ae2e21a628 Binary files /dev/null and b/_book/docs/img/c2f9cb2f2c88244b3dbf094572214a02.png differ diff --git a/_book/docs/img/c3174e54aed82ba15686b58fc97068f1.png b/_book/docs/img/c3174e54aed82ba15686b58fc97068f1.png new file mode 100644 index 0000000000000000000000000000000000000000..51fecf27daaa0ed6c6c677a5c1b54c61be3f58d1 Binary files /dev/null and b/_book/docs/img/c3174e54aed82ba15686b58fc97068f1.png differ diff --git a/_book/docs/img/c380b8ddd78f1d3281d0eeea7f19971c.png b/_book/docs/img/c380b8ddd78f1d3281d0eeea7f19971c.png new file mode 100644 index 0000000000000000000000000000000000000000..40a432914f6e888aaf41dbba4ab1ef112188a1fc Binary files /dev/null and b/_book/docs/img/c380b8ddd78f1d3281d0eeea7f19971c.png differ diff --git a/_book/docs/img/c3948ae724d699cf1ec0da64ab3e6a14.png b/_book/docs/img/c3948ae724d699cf1ec0da64ab3e6a14.png new file mode 100644 index 0000000000000000000000000000000000000000..804a4451b69fb83c81c8fd3664240d454cacf75a Binary files /dev/null and b/_book/docs/img/c3948ae724d699cf1ec0da64ab3e6a14.png differ diff --git a/_book/docs/img/c39dc466882289b42ad827dbbc05b39f.png b/_book/docs/img/c39dc466882289b42ad827dbbc05b39f.png new file mode 100644 index 0000000000000000000000000000000000000000..ededdd5a6319fdab381fc439824301a4cc9be4b0 Binary files /dev/null and b/_book/docs/img/c39dc466882289b42ad827dbbc05b39f.png differ diff --git a/_book/docs/img/c3c27ff673c33bcd50004c2adb617d5f.png b/_book/docs/img/c3c27ff673c33bcd50004c2adb617d5f.png new file mode 100644 index 0000000000000000000000000000000000000000..1345a00e3f4473a179e72695883500777da76687 Binary files /dev/null and b/_book/docs/img/c3c27ff673c33bcd50004c2adb617d5f.png differ diff --git a/_book/docs/img/c3c7ade0ae9c901a64dedf780f4efdaf.png b/_book/docs/img/c3c7ade0ae9c901a64dedf780f4efdaf.png new file mode 100644 index 0000000000000000000000000000000000000000..6f15f32e6ac15e3e0da9fb25efa1e5c28296e123 Binary files /dev/null and b/_book/docs/img/c3c7ade0ae9c901a64dedf780f4efdaf.png differ diff --git a/_book/docs/img/c3f7298c5f6d1b4dbd0a120ce98b9d06.png b/_book/docs/img/c3f7298c5f6d1b4dbd0a120ce98b9d06.png new file mode 100644 index 0000000000000000000000000000000000000000..85387b2d3cd4e74a67e5f92787b1c5bc834dee99 Binary files /dev/null and b/_book/docs/img/c3f7298c5f6d1b4dbd0a120ce98b9d06.png differ diff --git a/_book/docs/img/c42e6852cdd2c45b0a814f7a659ee5d2.png b/_book/docs/img/c42e6852cdd2c45b0a814f7a659ee5d2.png new file mode 100644 index 0000000000000000000000000000000000000000..902267b2db7076a2ce4cf164690d98d811bf40ee Binary files /dev/null and b/_book/docs/img/c42e6852cdd2c45b0a814f7a659ee5d2.png differ diff --git a/_book/docs/img/c43432893b48081561609f3667b7d497.png b/_book/docs/img/c43432893b48081561609f3667b7d497.png new file mode 100644 index 0000000000000000000000000000000000000000..485db733cec7ccc099dddfcc76cb6e4696ba90b3 Binary files /dev/null and b/_book/docs/img/c43432893b48081561609f3667b7d497.png differ diff --git a/_book/docs/img/c4c2d27f307636160d5773556cb14345.png b/_book/docs/img/c4c2d27f307636160d5773556cb14345.png new file mode 100644 index 0000000000000000000000000000000000000000..67c6ced6f27ec8b435d2af2d216e4e2c7e306135 Binary files /dev/null and b/_book/docs/img/c4c2d27f307636160d5773556cb14345.png differ diff --git a/_book/docs/img/c5c16791538bd6838d6196a0b4ec5bb7.png b/_book/docs/img/c5c16791538bd6838d6196a0b4ec5bb7.png new file mode 100644 index 0000000000000000000000000000000000000000..db9ed6b8eeca6cbb71fbda6b75fba0f2a9c5530e Binary files /dev/null and b/_book/docs/img/c5c16791538bd6838d6196a0b4ec5bb7.png differ diff --git a/_book/docs/img/c5d0cec2b61194796c06f7c2c5294294.png b/_book/docs/img/c5d0cec2b61194796c06f7c2c5294294.png new file mode 100644 index 0000000000000000000000000000000000000000..80eec768f81c65e85ebf8b165a3eb0d8bcde6e31 Binary files /dev/null and b/_book/docs/img/c5d0cec2b61194796c06f7c2c5294294.png differ diff --git a/_book/docs/img/c5fbd1d44b70c599ae2cc8751ccfca14.png b/_book/docs/img/c5fbd1d44b70c599ae2cc8751ccfca14.png new file mode 100644 index 0000000000000000000000000000000000000000..40239d6874a1b61b338620a1ed557c2e87701f62 Binary files /dev/null and b/_book/docs/img/c5fbd1d44b70c599ae2cc8751ccfca14.png differ diff --git a/_book/docs/img/c61ac95a0fe55d92ab3c711ea814a8c8.png b/_book/docs/img/c61ac95a0fe55d92ab3c711ea814a8c8.png new file mode 100644 index 0000000000000000000000000000000000000000..2554c975d7171d2cff1a76004deb6be9f1377f63 Binary files /dev/null and b/_book/docs/img/c61ac95a0fe55d92ab3c711ea814a8c8.png differ diff --git a/_book/docs/img/c6273de0eb8e4c8e7750113a7a66e7d6.png b/_book/docs/img/c6273de0eb8e4c8e7750113a7a66e7d6.png new file mode 100644 index 0000000000000000000000000000000000000000..e088f4c632e90b83039f3ee3f4bbbb8164bb4f74 Binary files /dev/null and b/_book/docs/img/c6273de0eb8e4c8e7750113a7a66e7d6.png differ diff --git a/_book/docs/img/c65afb6da67de7dea9950e2b151cca40.png b/_book/docs/img/c65afb6da67de7dea9950e2b151cca40.png new file mode 100644 index 0000000000000000000000000000000000000000..62436ca7d1b75e859c922e8f17643c4d9fa81c8c Binary files /dev/null and b/_book/docs/img/c65afb6da67de7dea9950e2b151cca40.png differ diff --git a/_book/docs/img/c67bf60334fcbd1f63dc0a6515d02eca.png b/_book/docs/img/c67bf60334fcbd1f63dc0a6515d02eca.png new file mode 100644 index 0000000000000000000000000000000000000000..d70adcb6d432776b17191acc3c7d1e77529a819d Binary files /dev/null and b/_book/docs/img/c67bf60334fcbd1f63dc0a6515d02eca.png differ diff --git a/_book/docs/img/c67faf1fb34407861ed68b426e46da72.png b/_book/docs/img/c67faf1fb34407861ed68b426e46da72.png new file mode 100644 index 0000000000000000000000000000000000000000..0d12a66a8eb71d6275ca7dfcfb1d8d926afcb5be Binary files /dev/null and b/_book/docs/img/c67faf1fb34407861ed68b426e46da72.png differ diff --git a/_book/docs/img/c6a214b87abe3ccc6a5287ea1d256834.png b/_book/docs/img/c6a214b87abe3ccc6a5287ea1d256834.png new file mode 100644 index 0000000000000000000000000000000000000000..9c964b08bb75bc6a5872349f0d06fc0ffe49de8d Binary files /dev/null and b/_book/docs/img/c6a214b87abe3ccc6a5287ea1d256834.png differ diff --git a/_book/docs/img/c6c38f70c273cc4412f6d3bd29af3829.png b/_book/docs/img/c6c38f70c273cc4412f6d3bd29af3829.png new file mode 100644 index 0000000000000000000000000000000000000000..35d7389883b60a8b8a46e9f2e5b0b08e78b12eb2 Binary files /dev/null and b/_book/docs/img/c6c38f70c273cc4412f6d3bd29af3829.png differ diff --git a/_book/docs/img/c6daa1e81d653cfd0b476144f1f71874.png b/_book/docs/img/c6daa1e81d653cfd0b476144f1f71874.png new file mode 100644 index 0000000000000000000000000000000000000000..5c9da6b107b8b77f66af491f065215d313f6519d Binary files /dev/null and b/_book/docs/img/c6daa1e81d653cfd0b476144f1f71874.png differ diff --git a/_book/docs/img/c7126ad3e897b95ff53bc9300bce4d43.png b/_book/docs/img/c7126ad3e897b95ff53bc9300bce4d43.png new file mode 100644 index 0000000000000000000000000000000000000000..d00c640be9395a755ff2408254324d84c7dc91fc Binary files /dev/null and b/_book/docs/img/c7126ad3e897b95ff53bc9300bce4d43.png differ diff --git a/_book/docs/img/c73475715fce01bf6b51edda84064d67.png b/_book/docs/img/c73475715fce01bf6b51edda84064d67.png new file mode 100644 index 0000000000000000000000000000000000000000..76e824ea96bb82332eadba9dbaf976c2e39e6727 Binary files /dev/null and b/_book/docs/img/c73475715fce01bf6b51edda84064d67.png differ diff --git a/_book/docs/img/c736ba09ab7186102250ad9e624d79c1.png b/_book/docs/img/c736ba09ab7186102250ad9e624d79c1.png new file mode 100644 index 0000000000000000000000000000000000000000..83206cf6717b38e76aea9475527c656f89f3394e Binary files /dev/null and b/_book/docs/img/c736ba09ab7186102250ad9e624d79c1.png differ diff --git a/_book/docs/img/c7562ae46b8ec150661af0c88f1a5aad.png b/_book/docs/img/c7562ae46b8ec150661af0c88f1a5aad.png new file mode 100644 index 0000000000000000000000000000000000000000..0416097fc40994a531b478b6e1af8c7c9dc0f2a2 Binary files /dev/null and b/_book/docs/img/c7562ae46b8ec150661af0c88f1a5aad.png differ diff --git a/_book/docs/img/c77b45147112088b7940cb4ebcc5f4a6.png b/_book/docs/img/c77b45147112088b7940cb4ebcc5f4a6.png new file mode 100644 index 0000000000000000000000000000000000000000..ef438fb7739ae10c814ca9aeb33a2655977f2628 Binary files /dev/null and b/_book/docs/img/c77b45147112088b7940cb4ebcc5f4a6.png differ diff --git a/_book/docs/img/c7918abdac813cb6d0b57bb682269b93.png b/_book/docs/img/c7918abdac813cb6d0b57bb682269b93.png new file mode 100644 index 0000000000000000000000000000000000000000..1c019afac8efd17513b817cb843a3c7057d2020a --- /dev/null +++ b/_book/docs/img/c7918abdac813cb6d0b57bb682269b93.png @@ -0,0 +1,17 @@ + + + + + + + + + + coverage + + + unknown + + + + diff --git a/_book/docs/img/c79ebe6e2611f151d42f879eaee753fe.png b/_book/docs/img/c79ebe6e2611f151d42f879eaee753fe.png new file mode 100644 index 0000000000000000000000000000000000000000..6d0f4975db730818b46aba75f3fa41e29db0b39f Binary files /dev/null and b/_book/docs/img/c79ebe6e2611f151d42f879eaee753fe.png differ diff --git a/_book/docs/img/c7a5bc700a43a5880572c7f8cc0acdc7.png b/_book/docs/img/c7a5bc700a43a5880572c7f8cc0acdc7.png new file mode 100644 index 0000000000000000000000000000000000000000..b10e672983ebb917b445af587552cb808af97d2e Binary files /dev/null and b/_book/docs/img/c7a5bc700a43a5880572c7f8cc0acdc7.png differ diff --git a/_book/docs/img/c7b2f6ed12531da21a4512becdf843af.png b/_book/docs/img/c7b2f6ed12531da21a4512becdf843af.png new file mode 100644 index 0000000000000000000000000000000000000000..34860464b0379fcdf6a23e1a3fb3837a42dea9fc Binary files /dev/null and b/_book/docs/img/c7b2f6ed12531da21a4512becdf843af.png differ diff --git a/_book/docs/img/c7ee3e55c50a5f7d0e3faceda16e2dc2.png b/_book/docs/img/c7ee3e55c50a5f7d0e3faceda16e2dc2.png new file mode 100644 index 0000000000000000000000000000000000000000..6b75dc997971100556327e66290a17c59d3dbc9d Binary files /dev/null and b/_book/docs/img/c7ee3e55c50a5f7d0e3faceda16e2dc2.png differ diff --git a/_book/docs/img/c89e56a24555efe89bb446cf31b5f764.png b/_book/docs/img/c89e56a24555efe89bb446cf31b5f764.png new file mode 100644 index 0000000000000000000000000000000000000000..d3249d5d715897d94ca290ee4ee2c71666cf14c4 Binary files /dev/null and b/_book/docs/img/c89e56a24555efe89bb446cf31b5f764.png differ diff --git a/_book/docs/img/c932281f198053757ebfaf5a9b99b335.png b/_book/docs/img/c932281f198053757ebfaf5a9b99b335.png new file mode 100644 index 0000000000000000000000000000000000000000..ac208fa2170ce32e8da1a2523301bb7a85bff9f7 Binary files /dev/null and b/_book/docs/img/c932281f198053757ebfaf5a9b99b335.png differ diff --git a/_book/docs/img/c9d2a45b5906d81d1118b63a832bbcd4.png b/_book/docs/img/c9d2a45b5906d81d1118b63a832bbcd4.png new file mode 100644 index 0000000000000000000000000000000000000000..4abb872a8d6c2af6c3b2f55707d6fe5a584d681d Binary files /dev/null and b/_book/docs/img/c9d2a45b5906d81d1118b63a832bbcd4.png differ diff --git a/_book/docs/img/c9fb44f57074dc166ca07353bd7d31c7.png b/_book/docs/img/c9fb44f57074dc166ca07353bd7d31c7.png new file mode 100644 index 0000000000000000000000000000000000000000..01b99d21fdd36c6530f7d24c317da6bbc6a31b96 Binary files /dev/null and b/_book/docs/img/c9fb44f57074dc166ca07353bd7d31c7.png differ diff --git a/_book/docs/img/ca33b4a75b3a1bc207dd2eddae8c3949.png b/_book/docs/img/ca33b4a75b3a1bc207dd2eddae8c3949.png new file mode 100644 index 0000000000000000000000000000000000000000..bb16bdd21550985520157fa718ea10c29e75f684 Binary files /dev/null and b/_book/docs/img/ca33b4a75b3a1bc207dd2eddae8c3949.png differ diff --git a/_book/docs/img/ca66569a1f77e8f2d208a42e0fee1794.png b/_book/docs/img/ca66569a1f77e8f2d208a42e0fee1794.png new file mode 100644 index 0000000000000000000000000000000000000000..a22c91ae13602e4764d0bdfd9d1039371bc4c91c Binary files /dev/null and b/_book/docs/img/ca66569a1f77e8f2d208a42e0fee1794.png differ diff --git a/_book/docs/img/cb3829e4d0ca25082e0f52f135a9d1de.png b/_book/docs/img/cb3829e4d0ca25082e0f52f135a9d1de.png new file mode 100644 index 0000000000000000000000000000000000000000..7e9ddbee645a834e0423f1ef52a02dac6c48b529 Binary files /dev/null and b/_book/docs/img/cb3829e4d0ca25082e0f52f135a9d1de.png differ diff --git a/_book/docs/img/cb4ff59b46134d4c61caedcf5a66a74f.png b/_book/docs/img/cb4ff59b46134d4c61caedcf5a66a74f.png new file mode 100644 index 0000000000000000000000000000000000000000..549a155702d95a8105b0851c5765e0d8a31f2a69 Binary files /dev/null and b/_book/docs/img/cb4ff59b46134d4c61caedcf5a66a74f.png differ diff --git a/_book/docs/img/cbd0470f26aadc25ca385447ade97392.png b/_book/docs/img/cbd0470f26aadc25ca385447ade97392.png new file mode 100644 index 0000000000000000000000000000000000000000..a5b193d4d0d4f26e78d1a7b8bee342fdce5ff250 Binary files /dev/null and b/_book/docs/img/cbd0470f26aadc25ca385447ade97392.png differ diff --git a/_book/docs/img/cbf589a2c41bb518f8f2da56b76a59dc.png b/_book/docs/img/cbf589a2c41bb518f8f2da56b76a59dc.png new file mode 100644 index 0000000000000000000000000000000000000000..f414c89d2626fac041ee325b7f7c95ac4a3fc90c Binary files /dev/null and b/_book/docs/img/cbf589a2c41bb518f8f2da56b76a59dc.png differ diff --git a/_book/docs/img/cc52a99e48b72695add0c3e8efab158f.png b/_book/docs/img/cc52a99e48b72695add0c3e8efab158f.png new file mode 100644 index 0000000000000000000000000000000000000000..43fe705c45abb72ae7d5993613446d69bd0f0d04 Binary files /dev/null and b/_book/docs/img/cc52a99e48b72695add0c3e8efab158f.png differ diff --git a/_book/docs/img/cc6935399d2235840119ad00eb778fc9.png b/_book/docs/img/cc6935399d2235840119ad00eb778fc9.png new file mode 100644 index 0000000000000000000000000000000000000000..a2b2514fd445c8748f25cb18273645fd767af981 Binary files /dev/null and b/_book/docs/img/cc6935399d2235840119ad00eb778fc9.png differ diff --git a/_book/docs/img/cca5497f42d0f0512126392deb81fa3e.png b/_book/docs/img/cca5497f42d0f0512126392deb81fa3e.png new file mode 100644 index 0000000000000000000000000000000000000000..bcbd2cdf29cd2b54dc2d56291f5938328db870f6 Binary files /dev/null and b/_book/docs/img/cca5497f42d0f0512126392deb81fa3e.png differ diff --git a/_book/docs/img/cd210f00f72fcb8f7b00750457b0ab2c.png b/_book/docs/img/cd210f00f72fcb8f7b00750457b0ab2c.png new file mode 100644 index 0000000000000000000000000000000000000000..f336cb8363894ea78568a85ac24d837b47d1f93c Binary files /dev/null and b/_book/docs/img/cd210f00f72fcb8f7b00750457b0ab2c.png differ diff --git a/_book/docs/img/cdce9b0515678bb30cdd0e1173a30749.png b/_book/docs/img/cdce9b0515678bb30cdd0e1173a30749.png new file mode 100644 index 0000000000000000000000000000000000000000..26251ed46947e35835fe6c784668c398f9595aa2 Binary files /dev/null and b/_book/docs/img/cdce9b0515678bb30cdd0e1173a30749.png differ diff --git a/_book/docs/img/ce119917ec56b195b909d4371bb994aa.png b/_book/docs/img/ce119917ec56b195b909d4371bb994aa.png new file mode 100644 index 0000000000000000000000000000000000000000..b90d9882a3979bd5cbf4e49fdf4f6ed7bf1f5583 Binary files /dev/null and b/_book/docs/img/ce119917ec56b195b909d4371bb994aa.png differ diff --git a/_book/docs/img/ce2f28e687df2b322895dbfb6c48d389.png b/_book/docs/img/ce2f28e687df2b322895dbfb6c48d389.png new file mode 100644 index 0000000000000000000000000000000000000000..294ced1c3e7f9fd9b38d02360fae80e51071f113 Binary files /dev/null and b/_book/docs/img/ce2f28e687df2b322895dbfb6c48d389.png differ diff --git a/_book/docs/img/ce6315abe3d0bf8a315febe4ab497312.png b/_book/docs/img/ce6315abe3d0bf8a315febe4ab497312.png new file mode 100644 index 0000000000000000000000000000000000000000..6ff5131b916de5631880e97a8495ebcbfa3d9dd6 Binary files /dev/null and b/_book/docs/img/ce6315abe3d0bf8a315febe4ab497312.png differ diff --git a/_book/docs/img/ce7d1dd63f95f0330b281fd577aaa8d4.png b/_book/docs/img/ce7d1dd63f95f0330b281fd577aaa8d4.png new file mode 100644 index 0000000000000000000000000000000000000000..e18067cebbbe318474b3056546aa3033b7aa9888 Binary files /dev/null and b/_book/docs/img/ce7d1dd63f95f0330b281fd577aaa8d4.png differ diff --git a/_book/docs/img/ce9e5e0a216a3a51d412bcb3cb11f420.png b/_book/docs/img/ce9e5e0a216a3a51d412bcb3cb11f420.png new file mode 100644 index 0000000000000000000000000000000000000000..22d66c364fd80ae232f669917a48dc57361f9e7b Binary files /dev/null and b/_book/docs/img/ce9e5e0a216a3a51d412bcb3cb11f420.png differ diff --git a/_book/docs/img/ceb135d0071e5591ba58f5d2820e8f4b.png b/_book/docs/img/ceb135d0071e5591ba58f5d2820e8f4b.png new file mode 100644 index 0000000000000000000000000000000000000000..fd267c4d3113a8ce434c3b902e5f3ef63ca5b6ee Binary files /dev/null and b/_book/docs/img/ceb135d0071e5591ba58f5d2820e8f4b.png differ diff --git a/_book/docs/img/ced764ccc10657c7f37a1ffe8a7e338a.png b/_book/docs/img/ced764ccc10657c7f37a1ffe8a7e338a.png new file mode 100644 index 0000000000000000000000000000000000000000..83e5711132c244261cef10e27c8aeb0ac9469131 Binary files /dev/null and b/_book/docs/img/ced764ccc10657c7f37a1ffe8a7e338a.png differ diff --git a/_book/docs/img/cee9b8bcba36170c0ae5df4747bb8c44.png b/_book/docs/img/cee9b8bcba36170c0ae5df4747bb8c44.png new file mode 100644 index 0000000000000000000000000000000000000000..96ec83f3fa814414587590f0332182f17627f0b1 Binary files /dev/null and b/_book/docs/img/cee9b8bcba36170c0ae5df4747bb8c44.png differ diff --git a/_book/docs/img/cf0c5e15a3b44eb89d7513b961d6a274.png b/_book/docs/img/cf0c5e15a3b44eb89d7513b961d6a274.png new file mode 100644 index 0000000000000000000000000000000000000000..29bd7b2a529a6e5b7f3cad09ee18e0928b4a3ccc Binary files /dev/null and b/_book/docs/img/cf0c5e15a3b44eb89d7513b961d6a274.png differ diff --git a/_book/docs/img/cff0e046ac8eca2d9fde8f13a3365d66.png b/_book/docs/img/cff0e046ac8eca2d9fde8f13a3365d66.png new file mode 100644 index 0000000000000000000000000000000000000000..17439ac5747a89ed6b9265e88893824981b12dad Binary files /dev/null and b/_book/docs/img/cff0e046ac8eca2d9fde8f13a3365d66.png differ diff --git a/_book/docs/img/d0143a44aad793332527a786d79524f7.png b/_book/docs/img/d0143a44aad793332527a786d79524f7.png new file mode 100644 index 0000000000000000000000000000000000000000..45e480a602fce8e8e554497c09937d2c6591dd6e Binary files /dev/null and b/_book/docs/img/d0143a44aad793332527a786d79524f7.png differ diff --git a/_book/docs/img/d04d999de9102632af46c867821c47c3.png b/_book/docs/img/d04d999de9102632af46c867821c47c3.png new file mode 100644 index 0000000000000000000000000000000000000000..aab7332269e368cc2f9448140471925fc6fd5c65 Binary files /dev/null and b/_book/docs/img/d04d999de9102632af46c867821c47c3.png differ diff --git a/_book/docs/img/d0707d7a1f822105efb120e442c32246.png b/_book/docs/img/d0707d7a1f822105efb120e442c32246.png new file mode 100644 index 0000000000000000000000000000000000000000..1fa24fddf6396df121cc80b2f34b56e517dde987 Binary files /dev/null and b/_book/docs/img/d0707d7a1f822105efb120e442c32246.png differ diff --git a/_book/docs/img/d0b0b1ad83988d76ef9c42281782f961.png b/_book/docs/img/d0b0b1ad83988d76ef9c42281782f961.png new file mode 100644 index 0000000000000000000000000000000000000000..e05cb22930e6ca851e81d60bf5d3638f9a893dc0 Binary files /dev/null and b/_book/docs/img/d0b0b1ad83988d76ef9c42281782f961.png differ diff --git a/_book/docs/img/d0b9fcc8669d772a04d7d72ccb5a82cc.png b/_book/docs/img/d0b9fcc8669d772a04d7d72ccb5a82cc.png new file mode 100644 index 0000000000000000000000000000000000000000..5df268318c8373dad7b4dd98a0c497601cde6482 Binary files /dev/null and b/_book/docs/img/d0b9fcc8669d772a04d7d72ccb5a82cc.png differ diff --git a/_book/docs/img/d0e9aaf43b9e19912342dddfb4b6be13.png b/_book/docs/img/d0e9aaf43b9e19912342dddfb4b6be13.png new file mode 100644 index 0000000000000000000000000000000000000000..95e728219bd597a8e5c114c9540015a4aed54956 Binary files /dev/null and b/_book/docs/img/d0e9aaf43b9e19912342dddfb4b6be13.png differ diff --git a/_book/docs/img/d15d948fc7d1b6e5c8dabacbe7c2fcc9.png b/_book/docs/img/d15d948fc7d1b6e5c8dabacbe7c2fcc9.png new file mode 100644 index 0000000000000000000000000000000000000000..d24d808fd73673f06c9330dbfcefff3494fa42c4 Binary files /dev/null and b/_book/docs/img/d15d948fc7d1b6e5c8dabacbe7c2fcc9.png differ diff --git a/_book/docs/img/d198d958fcf8be60727c232ff69b9713.png b/_book/docs/img/d198d958fcf8be60727c232ff69b9713.png new file mode 100644 index 0000000000000000000000000000000000000000..ef6d2879e416deddd26026de55e9c232c5a36090 Binary files /dev/null and b/_book/docs/img/d198d958fcf8be60727c232ff69b9713.png differ diff --git a/_book/docs/img/d19e6203a8567c2d6be7d878dd653654.png b/_book/docs/img/d19e6203a8567c2d6be7d878dd653654.png new file mode 100644 index 0000000000000000000000000000000000000000..ea83b183e391de849c1440d52f129f7481a651e6 Binary files /dev/null and b/_book/docs/img/d19e6203a8567c2d6be7d878dd653654.png differ diff --git a/_book/docs/img/d1c47110b6092ce9cec04ff22addfaa4.png b/_book/docs/img/d1c47110b6092ce9cec04ff22addfaa4.png new file mode 100644 index 0000000000000000000000000000000000000000..a80fefb492a7cf047e168d61a9933441509dbeca Binary files /dev/null and b/_book/docs/img/d1c47110b6092ce9cec04ff22addfaa4.png differ diff --git a/_book/docs/img/d1e835585272f821d777f384eed6a832.png b/_book/docs/img/d1e835585272f821d777f384eed6a832.png new file mode 100644 index 0000000000000000000000000000000000000000..4c4119dfd715a5ec06480c297f45862513667a80 Binary files /dev/null and b/_book/docs/img/d1e835585272f821d777f384eed6a832.png differ diff --git a/_book/docs/img/d241e2868510cfa5755170c1f02c78f3.png b/_book/docs/img/d241e2868510cfa5755170c1f02c78f3.png new file mode 100644 index 0000000000000000000000000000000000000000..0182a8226bbfc7b964f13533b8c0fe08d830ad10 Binary files /dev/null and b/_book/docs/img/d241e2868510cfa5755170c1f02c78f3.png differ diff --git a/_book/docs/img/d25fe780083ad8adbc24cf5fcc4feaf8.png b/_book/docs/img/d25fe780083ad8adbc24cf5fcc4feaf8.png new file mode 100644 index 0000000000000000000000000000000000000000..8b00820dd3728a2522c35bf74c950d1f0f7c3edf Binary files /dev/null and b/_book/docs/img/d25fe780083ad8adbc24cf5fcc4feaf8.png differ diff --git a/_book/docs/img/d277485e75207494ed3529dfcc7a6395.png b/_book/docs/img/d277485e75207494ed3529dfcc7a6395.png new file mode 100644 index 0000000000000000000000000000000000000000..29edb7f70b076cfdf199fa60b7c938c472a487da Binary files /dev/null and b/_book/docs/img/d277485e75207494ed3529dfcc7a6395.png differ diff --git a/_book/docs/img/d2f0725099f8a66ed235d537ea6592a4.png b/_book/docs/img/d2f0725099f8a66ed235d537ea6592a4.png new file mode 100644 index 0000000000000000000000000000000000000000..25992feca9f3534c7567986fc58841e19623681e Binary files /dev/null and b/_book/docs/img/d2f0725099f8a66ed235d537ea6592a4.png differ diff --git a/_book/docs/img/d32d8400522e9b5c9dd295fba00e1255.png b/_book/docs/img/d32d8400522e9b5c9dd295fba00e1255.png new file mode 100644 index 0000000000000000000000000000000000000000..840a0d91ae943999d3d24836fcd556eee3e3d8b4 Binary files /dev/null and b/_book/docs/img/d32d8400522e9b5c9dd295fba00e1255.png differ diff --git a/_book/docs/img/d345ea7938f401127d9471442b27eb27.png b/_book/docs/img/d345ea7938f401127d9471442b27eb27.png new file mode 100644 index 0000000000000000000000000000000000000000..2735c7a8d2af437c2d51424cac9100293428bd05 Binary files /dev/null and b/_book/docs/img/d345ea7938f401127d9471442b27eb27.png differ diff --git a/_book/docs/img/d366ea5b34fa89da8adbcbd7ec51bc2a.png b/_book/docs/img/d366ea5b34fa89da8adbcbd7ec51bc2a.png new file mode 100644 index 0000000000000000000000000000000000000000..79dd5a4c6135aecee7c08b6dbda8d28624b12122 Binary files /dev/null and b/_book/docs/img/d366ea5b34fa89da8adbcbd7ec51bc2a.png differ diff --git a/_book/docs/img/d3cc00bf5599be56b0b3154ca2751cbc.png b/_book/docs/img/d3cc00bf5599be56b0b3154ca2751cbc.png new file mode 100644 index 0000000000000000000000000000000000000000..c7e1530d8e2cb8dd6b5288b53ab5d45f34e4198a Binary files /dev/null and b/_book/docs/img/d3cc00bf5599be56b0b3154ca2751cbc.png differ diff --git a/_book/docs/img/d4a6279fcd73fa0a1dc68761261f4854.png b/_book/docs/img/d4a6279fcd73fa0a1dc68761261f4854.png new file mode 100644 index 0000000000000000000000000000000000000000..d1ee6980b4623caa6b550996a8489c136a77743e Binary files /dev/null and b/_book/docs/img/d4a6279fcd73fa0a1dc68761261f4854.png differ diff --git a/_book/docs/img/d4fcdfd2497a9936b17469dbafbd320e.png b/_book/docs/img/d4fcdfd2497a9936b17469dbafbd320e.png new file mode 100644 index 0000000000000000000000000000000000000000..66a2fcb999e76eeb1faed14cdddac5a225fdd9d9 Binary files /dev/null and b/_book/docs/img/d4fcdfd2497a9936b17469dbafbd320e.png differ diff --git a/_book/docs/img/d5171d012a8ff616032035f890d8dbd5.png b/_book/docs/img/d5171d012a8ff616032035f890d8dbd5.png new file mode 100644 index 0000000000000000000000000000000000000000..96eaa1d5d1f5f154d0ee29bd4f12064edab6c78d Binary files /dev/null and b/_book/docs/img/d5171d012a8ff616032035f890d8dbd5.png differ diff --git a/_book/docs/img/d5a5a91fe5e2b490b9388b43801b6a39.png b/_book/docs/img/d5a5a91fe5e2b490b9388b43801b6a39.png new file mode 100644 index 0000000000000000000000000000000000000000..74e75a7c4c6c16c06be7e372bca9a4cbc3749f07 Binary files /dev/null and b/_book/docs/img/d5a5a91fe5e2b490b9388b43801b6a39.png differ diff --git a/_book/docs/img/d5df9e77d389b58908ef235600ccc61c.png b/_book/docs/img/d5df9e77d389b58908ef235600ccc61c.png new file mode 100644 index 0000000000000000000000000000000000000000..bbaa4c66717f6fc7eed9970a033f2dcbd46a5dd2 Binary files /dev/null and b/_book/docs/img/d5df9e77d389b58908ef235600ccc61c.png differ diff --git a/_book/docs/img/d677bbf1d2f77fd7394cddab976e6f67.png b/_book/docs/img/d677bbf1d2f77fd7394cddab976e6f67.png new file mode 100644 index 0000000000000000000000000000000000000000..314447565d123168f7edd738fd215eedf41698c1 Binary files /dev/null and b/_book/docs/img/d677bbf1d2f77fd7394cddab976e6f67.png differ diff --git a/_book/docs/img/d67d5681f30c4769c6d92232eada26e4.png b/_book/docs/img/d67d5681f30c4769c6d92232eada26e4.png new file mode 100644 index 0000000000000000000000000000000000000000..35b07bb5172cc2383eff92b4f2b802ca525179a8 Binary files /dev/null and b/_book/docs/img/d67d5681f30c4769c6d92232eada26e4.png differ diff --git a/_book/docs/img/d69ab181c07176aa054b0ceac08b702c.png b/_book/docs/img/d69ab181c07176aa054b0ceac08b702c.png new file mode 100644 index 0000000000000000000000000000000000000000..68ed53c896b80706a60191d9878076d4f85534ac Binary files /dev/null and b/_book/docs/img/d69ab181c07176aa054b0ceac08b702c.png differ diff --git a/_book/docs/img/d79207e6e4f140448c9dd5e6ebe5e380.png b/_book/docs/img/d79207e6e4f140448c9dd5e6ebe5e380.png new file mode 100644 index 0000000000000000000000000000000000000000..c0de3c431a8709f0c3acb5f5d930eab16be54b19 Binary files /dev/null and b/_book/docs/img/d79207e6e4f140448c9dd5e6ebe5e380.png differ diff --git a/_book/docs/img/d7b0c4003d725d7125fdfb9c24aae17e.png b/_book/docs/img/d7b0c4003d725d7125fdfb9c24aae17e.png new file mode 100644 index 0000000000000000000000000000000000000000..ab3c1b02cb1620da020432cb9853aac5c7db37ed Binary files /dev/null and b/_book/docs/img/d7b0c4003d725d7125fdfb9c24aae17e.png differ diff --git a/_book/docs/img/d7b5490ec5cb26ce71f19d5c56f003f3.png b/_book/docs/img/d7b5490ec5cb26ce71f19d5c56f003f3.png new file mode 100644 index 0000000000000000000000000000000000000000..53ae48aa0cfdf1b96cd73ea2bf42a2e8ce361e2e Binary files /dev/null and b/_book/docs/img/d7b5490ec5cb26ce71f19d5c56f003f3.png differ diff --git a/_book/docs/img/d7cb226977bb46d9aaa1c1d7e195025a.png b/_book/docs/img/d7cb226977bb46d9aaa1c1d7e195025a.png new file mode 100644 index 0000000000000000000000000000000000000000..7bb9204fb06100c40294b64d1506875caee263f0 Binary files /dev/null and b/_book/docs/img/d7cb226977bb46d9aaa1c1d7e195025a.png differ diff --git a/_book/docs/img/d8baae909b3683bffff327402580132f.png b/_book/docs/img/d8baae909b3683bffff327402580132f.png new file mode 100644 index 0000000000000000000000000000000000000000..378507a6b9c96c7ca8a84e7834ab1cff19589e43 Binary files /dev/null and b/_book/docs/img/d8baae909b3683bffff327402580132f.png differ diff --git a/_book/docs/img/da13575f699b92fa864c2d3fae1fae9e.png b/_book/docs/img/da13575f699b92fa864c2d3fae1fae9e.png new file mode 100644 index 0000000000000000000000000000000000000000..9458cd2e77eb86475e3781a5097df791c18ab4ea Binary files /dev/null and b/_book/docs/img/da13575f699b92fa864c2d3fae1fae9e.png differ diff --git a/_book/docs/img/da1fdf492cc3f883353bb1997795a4a5.png b/_book/docs/img/da1fdf492cc3f883353bb1997795a4a5.png new file mode 100644 index 0000000000000000000000000000000000000000..45a919b8ed676f03b0904ace40707206269be2e2 Binary files /dev/null and b/_book/docs/img/da1fdf492cc3f883353bb1997795a4a5.png differ diff --git a/_book/docs/img/da60a36cf66e162640faa1f6cddaacdc.png b/_book/docs/img/da60a36cf66e162640faa1f6cddaacdc.png new file mode 100644 index 0000000000000000000000000000000000000000..af7c554f1c848073498090281b4373338dabd9f1 Binary files /dev/null and b/_book/docs/img/da60a36cf66e162640faa1f6cddaacdc.png differ diff --git a/_book/docs/img/da827bb1926cf748cff537fec6ecc954.png b/_book/docs/img/da827bb1926cf748cff537fec6ecc954.png new file mode 100644 index 0000000000000000000000000000000000000000..c69fece9597f9fd43a0eef25e2a7a847a036113b Binary files /dev/null and b/_book/docs/img/da827bb1926cf748cff537fec6ecc954.png differ diff --git a/_book/docs/img/daa9468beb587bb748cbb9ec37bbb43f.png b/_book/docs/img/daa9468beb587bb748cbb9ec37bbb43f.png new file mode 100644 index 0000000000000000000000000000000000000000..63c0ce25e4a323123a1bdd5e686fbdbb3e01f91a Binary files /dev/null and b/_book/docs/img/daa9468beb587bb748cbb9ec37bbb43f.png differ diff --git a/_book/docs/img/db0182b2e43670178e35b1a3485ca25e.png b/_book/docs/img/db0182b2e43670178e35b1a3485ca25e.png new file mode 100644 index 0000000000000000000000000000000000000000..51115559e51e74689c04291f6359eecf97626043 Binary files /dev/null and b/_book/docs/img/db0182b2e43670178e35b1a3485ca25e.png differ diff --git a/_book/docs/img/db0b9c2164464a7b2e1772c54232681a.png b/_book/docs/img/db0b9c2164464a7b2e1772c54232681a.png new file mode 100644 index 0000000000000000000000000000000000000000..d63cd87915f77371bbcbdb6167db653690f57000 Binary files /dev/null and b/_book/docs/img/db0b9c2164464a7b2e1772c54232681a.png differ diff --git a/_book/docs/img/db92110fba2588fed57b9af6bb2a381c.png b/_book/docs/img/db92110fba2588fed57b9af6bb2a381c.png new file mode 100644 index 0000000000000000000000000000000000000000..249e669385a6b64ccf349797161b3dc7267d2e2e Binary files /dev/null and b/_book/docs/img/db92110fba2588fed57b9af6bb2a381c.png differ diff --git a/_book/docs/img/dbae11f07630ae759b8156031d0c496d.png b/_book/docs/img/dbae11f07630ae759b8156031d0c496d.png new file mode 100644 index 0000000000000000000000000000000000000000..8a259a3b0f868c5be0993440850d883334389476 Binary files /dev/null and b/_book/docs/img/dbae11f07630ae759b8156031d0c496d.png differ diff --git a/_book/docs/img/dbb80511727781129d638c6d3413a45f.png b/_book/docs/img/dbb80511727781129d638c6d3413a45f.png new file mode 100644 index 0000000000000000000000000000000000000000..0c76dc680fe798f9ce48a5fe2c809d7cf9c01560 Binary files /dev/null and b/_book/docs/img/dbb80511727781129d638c6d3413a45f.png differ diff --git a/_book/docs/img/dbb89cfb3c7539310a17d809c65c34a5.png b/_book/docs/img/dbb89cfb3c7539310a17d809c65c34a5.png new file mode 100644 index 0000000000000000000000000000000000000000..36817ede83d124e1e7731f6ab13e2815ac304ff4 Binary files /dev/null and b/_book/docs/img/dbb89cfb3c7539310a17d809c65c34a5.png differ diff --git a/_book/docs/img/dc12d72310a7e06d2981fd6774b0903d.png b/_book/docs/img/dc12d72310a7e06d2981fd6774b0903d.png new file mode 100644 index 0000000000000000000000000000000000000000..f2710d29ec3730d1be6a70f96152c37fd6d8108a Binary files /dev/null and b/_book/docs/img/dc12d72310a7e06d2981fd6774b0903d.png differ diff --git a/_book/docs/img/dc47374cec4da1de3e6476346ecf738e.png b/_book/docs/img/dc47374cec4da1de3e6476346ecf738e.png new file mode 100644 index 0000000000000000000000000000000000000000..98ff87785f5baf08dcecf6b6faa3be1aef034538 Binary files /dev/null and b/_book/docs/img/dc47374cec4da1de3e6476346ecf738e.png differ diff --git a/_book/docs/img/dc5fe88e82dc925a618598e1ac284f39.png b/_book/docs/img/dc5fe88e82dc925a618598e1ac284f39.png new file mode 100644 index 0000000000000000000000000000000000000000..0148e4db367791fb63a2a53162666f75fde16413 Binary files /dev/null and b/_book/docs/img/dc5fe88e82dc925a618598e1ac284f39.png differ diff --git a/_book/docs/img/dc75662feab34ea9fa5cb187a2d77739.png b/_book/docs/img/dc75662feab34ea9fa5cb187a2d77739.png new file mode 100644 index 0000000000000000000000000000000000000000..d0dd28b0fa7c51ec03c8f67bf8203a40b493794e Binary files /dev/null and b/_book/docs/img/dc75662feab34ea9fa5cb187a2d77739.png differ diff --git a/_book/docs/img/dce9a8c36e06896553bd80f313c3a756.png b/_book/docs/img/dce9a8c36e06896553bd80f313c3a756.png new file mode 100644 index 0000000000000000000000000000000000000000..babcddd5801415e42889f30938b3e4913326c332 Binary files /dev/null and b/_book/docs/img/dce9a8c36e06896553bd80f313c3a756.png differ diff --git a/_book/docs/img/dd6b38427a8d14832104464d1603afed.png b/_book/docs/img/dd6b38427a8d14832104464d1603afed.png new file mode 100644 index 0000000000000000000000000000000000000000..7c94c05483405d479a4b07e1b84afd1fb0e5cd9d Binary files /dev/null and b/_book/docs/img/dd6b38427a8d14832104464d1603afed.png differ diff --git a/_book/docs/img/ddc1b7f5f622e5c8f6581738b42964cb.png b/_book/docs/img/ddc1b7f5f622e5c8f6581738b42964cb.png new file mode 100644 index 0000000000000000000000000000000000000000..f29cc24db3c65e3b8db1aeb8eb2162fd6842081a Binary files /dev/null and b/_book/docs/img/ddc1b7f5f622e5c8f6581738b42964cb.png differ diff --git a/_book/docs/img/de408a3a079dceb2e72d044abac21ac3.png b/_book/docs/img/de408a3a079dceb2e72d044abac21ac3.png new file mode 100644 index 0000000000000000000000000000000000000000..45922a9917742bf0d57fd5d2c25c459bd25b6263 Binary files /dev/null and b/_book/docs/img/de408a3a079dceb2e72d044abac21ac3.png differ diff --git a/_book/docs/img/de608fa9aefa963f38d0d95043413679.png b/_book/docs/img/de608fa9aefa963f38d0d95043413679.png new file mode 100644 index 0000000000000000000000000000000000000000..dcb6a5a0bfd3d79cc8924acd12de7981860f2df9 Binary files /dev/null and b/_book/docs/img/de608fa9aefa963f38d0d95043413679.png differ diff --git a/_book/docs/img/def845e9e4d65228469b73dbc625c6cd.png b/_book/docs/img/def845e9e4d65228469b73dbc625c6cd.png new file mode 100644 index 0000000000000000000000000000000000000000..286d7b7716c00064548a55a09018ab38795a22d3 Binary files /dev/null and b/_book/docs/img/def845e9e4d65228469b73dbc625c6cd.png differ diff --git a/_book/docs/img/defc257dc0219b95ed3f3065afcaff94.png b/_book/docs/img/defc257dc0219b95ed3f3065afcaff94.png new file mode 100644 index 0000000000000000000000000000000000000000..a6badbe62325e02174c3ab2a73a7bab1a741ea9f Binary files /dev/null and b/_book/docs/img/defc257dc0219b95ed3f3065afcaff94.png differ diff --git a/_book/docs/img/e006fccde54b694d8c0f506a675942e0.png b/_book/docs/img/e006fccde54b694d8c0f506a675942e0.png new file mode 100644 index 0000000000000000000000000000000000000000..13582e55eeac1038bfa9640eb6217e338359cc0b Binary files /dev/null and b/_book/docs/img/e006fccde54b694d8c0f506a675942e0.png differ diff --git a/_book/docs/img/e0fb1b28f653637edd64e072798f2385.png b/_book/docs/img/e0fb1b28f653637edd64e072798f2385.png new file mode 100644 index 0000000000000000000000000000000000000000..90542ee2ed009eb97ed1f65582a3c223c255f707 Binary files /dev/null and b/_book/docs/img/e0fb1b28f653637edd64e072798f2385.png differ diff --git a/_book/docs/img/e14dc9ee9528f343daf09a4dd5340b99.png b/_book/docs/img/e14dc9ee9528f343daf09a4dd5340b99.png new file mode 100644 index 0000000000000000000000000000000000000000..e6a73f291f965c7eaefcd3bcd7cbe5517c303401 Binary files /dev/null and b/_book/docs/img/e14dc9ee9528f343daf09a4dd5340b99.png differ diff --git a/_book/docs/img/e18ff80d06980688066f9ec9404bd2da.png b/_book/docs/img/e18ff80d06980688066f9ec9404bd2da.png new file mode 100644 index 0000000000000000000000000000000000000000..5c85169a13a32b2a2879bc7d7cb0653b5face16a Binary files /dev/null and b/_book/docs/img/e18ff80d06980688066f9ec9404bd2da.png differ diff --git a/_book/docs/img/e1f4f357a93d9362f282810a575d73e3.png b/_book/docs/img/e1f4f357a93d9362f282810a575d73e3.png new file mode 100644 index 0000000000000000000000000000000000000000..abeb6db9733a89e4ded2d53253e05e3ca9f35ed4 Binary files /dev/null and b/_book/docs/img/e1f4f357a93d9362f282810a575d73e3.png differ diff --git a/_book/docs/img/e20aec7ab33bbd61bae4825e6c9e35f1.png b/_book/docs/img/e20aec7ab33bbd61bae4825e6c9e35f1.png new file mode 100644 index 0000000000000000000000000000000000000000..efc69387d86d3d1b255d17afc9260c0847849ee9 Binary files /dev/null and b/_book/docs/img/e20aec7ab33bbd61bae4825e6c9e35f1.png differ diff --git a/_book/docs/img/e255c03f63cd814a974b54b2a9eb6b02.png b/_book/docs/img/e255c03f63cd814a974b54b2a9eb6b02.png new file mode 100644 index 0000000000000000000000000000000000000000..fbd66cc158395f1c3a17d1cf264e0cf76ef83710 Binary files /dev/null and b/_book/docs/img/e255c03f63cd814a974b54b2a9eb6b02.png differ diff --git a/_book/docs/img/e28a59687a00b33f8174f2bcba18ac5d.png b/_book/docs/img/e28a59687a00b33f8174f2bcba18ac5d.png new file mode 100644 index 0000000000000000000000000000000000000000..6f5382d70fa3ba641cb8b2999fe81948049dc58e Binary files /dev/null and b/_book/docs/img/e28a59687a00b33f8174f2bcba18ac5d.png differ diff --git a/_book/docs/img/e28a69b4996ee400ca3df4431df0ab13.png b/_book/docs/img/e28a69b4996ee400ca3df4431df0ab13.png new file mode 100644 index 0000000000000000000000000000000000000000..13e6edef7ed3a0cf89b7064ba797b6dcb6300ad9 Binary files /dev/null and b/_book/docs/img/e28a69b4996ee400ca3df4431df0ab13.png differ diff --git a/_book/docs/img/e2a52ca7a089fcbd9b17f94875cba0ca.png b/_book/docs/img/e2a52ca7a089fcbd9b17f94875cba0ca.png new file mode 100644 index 0000000000000000000000000000000000000000..aa3210cc3eff162cb34698fba2f1641a8c10626e Binary files /dev/null and b/_book/docs/img/e2a52ca7a089fcbd9b17f94875cba0ca.png differ diff --git a/_book/docs/img/e2e1d44121ea24d32b388b9b84bd7ea5.png b/_book/docs/img/e2e1d44121ea24d32b388b9b84bd7ea5.png new file mode 100644 index 0000000000000000000000000000000000000000..c9b9caf1cfefaf44b1c9134e0130e4307f1d0a76 Binary files /dev/null and b/_book/docs/img/e2e1d44121ea24d32b388b9b84bd7ea5.png differ diff --git a/_book/docs/img/e2e835cd5cd1be1afaa876fde2475fe5.png b/_book/docs/img/e2e835cd5cd1be1afaa876fde2475fe5.png new file mode 100644 index 0000000000000000000000000000000000000000..031dd8a4b2a0f7dd51d32055ad18901ee1e44228 Binary files /dev/null and b/_book/docs/img/e2e835cd5cd1be1afaa876fde2475fe5.png differ diff --git a/_book/docs/img/e336833accfac93c8ed18718b667dab5.png b/_book/docs/img/e336833accfac93c8ed18718b667dab5.png new file mode 100644 index 0000000000000000000000000000000000000000..907b6bf93629f4716c951a9cc8872aa5a7d6b0e5 Binary files /dev/null and b/_book/docs/img/e336833accfac93c8ed18718b667dab5.png differ diff --git a/_book/docs/img/e3439aafb873fb6b7cdb3a5c6d51c3b9.png b/_book/docs/img/e3439aafb873fb6b7cdb3a5c6d51c3b9.png new file mode 100644 index 0000000000000000000000000000000000000000..39685c685b24e5e41364b5f0aaac6d6f5cbda3ba Binary files /dev/null and b/_book/docs/img/e3439aafb873fb6b7cdb3a5c6d51c3b9.png differ diff --git a/_book/docs/img/e3489f723615b369a1abec41ebe9dea2.png b/_book/docs/img/e3489f723615b369a1abec41ebe9dea2.png new file mode 100644 index 0000000000000000000000000000000000000000..1df0b6da8c6919a67c294a7dba74fdd1a313dd36 Binary files /dev/null and b/_book/docs/img/e3489f723615b369a1abec41ebe9dea2.png differ diff --git a/_book/docs/img/e392f78e991a2b0865f4a2fe825fd7fc.png b/_book/docs/img/e392f78e991a2b0865f4a2fe825fd7fc.png new file mode 100644 index 0000000000000000000000000000000000000000..ffc389881374d0c5ef08b42035e9255fc14d00b9 Binary files /dev/null and b/_book/docs/img/e392f78e991a2b0865f4a2fe825fd7fc.png differ diff --git a/_book/docs/img/e3e09b090e6c8612f71f6dbd7244cbb2.png b/_book/docs/img/e3e09b090e6c8612f71f6dbd7244cbb2.png new file mode 100644 index 0000000000000000000000000000000000000000..5d2d0a9f7c0636f9b0ea58ed45dcff9029ac7a65 Binary files /dev/null and b/_book/docs/img/e3e09b090e6c8612f71f6dbd7244cbb2.png differ diff --git a/_book/docs/img/e3eeb697453d582cf0ec4a746f30ed31.png b/_book/docs/img/e3eeb697453d582cf0ec4a746f30ed31.png new file mode 100644 index 0000000000000000000000000000000000000000..52872dc1ea5d10d8385161e1319bad476f589ef2 Binary files /dev/null and b/_book/docs/img/e3eeb697453d582cf0ec4a746f30ed31.png differ diff --git a/_book/docs/img/e3feca46add6d42b1afc92fcf120dbfb.png b/_book/docs/img/e3feca46add6d42b1afc92fcf120dbfb.png new file mode 100644 index 0000000000000000000000000000000000000000..a2eeb07a2ff1f006f246f39466992b83787ce272 Binary files /dev/null and b/_book/docs/img/e3feca46add6d42b1afc92fcf120dbfb.png differ diff --git a/_book/docs/img/e41f9ac1eea140d12bc83ea9312e71d0.png b/_book/docs/img/e41f9ac1eea140d12bc83ea9312e71d0.png new file mode 100644 index 0000000000000000000000000000000000000000..9ce1ae8ad80c403b2ec1f2f445a05fe752850a3e Binary files /dev/null and b/_book/docs/img/e41f9ac1eea140d12bc83ea9312e71d0.png differ diff --git a/_book/docs/img/e4581843d51522e972a6bb6716aa4b05.png b/_book/docs/img/e4581843d51522e972a6bb6716aa4b05.png new file mode 100644 index 0000000000000000000000000000000000000000..c280c236f15aa3ddd8258d70f65b1a68af07d980 Binary files /dev/null and b/_book/docs/img/e4581843d51522e972a6bb6716aa4b05.png differ diff --git a/_book/docs/img/e470cb0eb6198f35d2db011704471fce.png b/_book/docs/img/e470cb0eb6198f35d2db011704471fce.png new file mode 100644 index 0000000000000000000000000000000000000000..6acf3049416812ef941804e5a2bbaa045b52bd5a Binary files /dev/null and b/_book/docs/img/e470cb0eb6198f35d2db011704471fce.png differ diff --git a/_book/docs/img/e4b88f4d9d317b9a38522ce9c63f84bc.png b/_book/docs/img/e4b88f4d9d317b9a38522ce9c63f84bc.png new file mode 100644 index 0000000000000000000000000000000000000000..de7dfaf2e6dc24fadb32ec1eae306a2130e8abf1 Binary files /dev/null and b/_book/docs/img/e4b88f4d9d317b9a38522ce9c63f84bc.png differ diff --git a/_book/docs/img/e4fa52f4d522392d049bf73b1bb065a5.png b/_book/docs/img/e4fa52f4d522392d049bf73b1bb065a5.png new file mode 100644 index 0000000000000000000000000000000000000000..d6c330e4a7727c2746bab0c5827dd855e05f69df Binary files /dev/null and b/_book/docs/img/e4fa52f4d522392d049bf73b1bb065a5.png differ diff --git a/_book/docs/img/e545dd77cf453f5a97873da4f0083ebb.png b/_book/docs/img/e545dd77cf453f5a97873da4f0083ebb.png new file mode 100644 index 0000000000000000000000000000000000000000..5b6a59705cef1d62479d996c2587f647303ee071 Binary files /dev/null and b/_book/docs/img/e545dd77cf453f5a97873da4f0083ebb.png differ diff --git a/_book/docs/img/e57526dd100a1b0a33bdae55e3bf32c7.png b/_book/docs/img/e57526dd100a1b0a33bdae55e3bf32c7.png new file mode 100644 index 0000000000000000000000000000000000000000..5f16fdb3ab3a38f99d68e5d63a81a9e202966dd6 Binary files /dev/null and b/_book/docs/img/e57526dd100a1b0a33bdae55e3bf32c7.png differ diff --git a/_book/docs/img/e5d9c1be329fa86c36614dea613f69a3.png b/_book/docs/img/e5d9c1be329fa86c36614dea613f69a3.png new file mode 100644 index 0000000000000000000000000000000000000000..3dd9c677935280cf2e5f4a158c0098d38472c04a Binary files /dev/null and b/_book/docs/img/e5d9c1be329fa86c36614dea613f69a3.png differ diff --git a/_book/docs/img/e5f179b25c2db023892b0a5f559b67d5.png b/_book/docs/img/e5f179b25c2db023892b0a5f559b67d5.png new file mode 100644 index 0000000000000000000000000000000000000000..4627bf02954da67ab4584b89c6fc7354b08f78c9 Binary files /dev/null and b/_book/docs/img/e5f179b25c2db023892b0a5f559b67d5.png differ diff --git a/_book/docs/img/e6522f2cefe000bb17275b2a0451bf82.png b/_book/docs/img/e6522f2cefe000bb17275b2a0451bf82.png new file mode 100644 index 0000000000000000000000000000000000000000..d3a2d825ff25f9275867df791957a511675079d6 Binary files /dev/null and b/_book/docs/img/e6522f2cefe000bb17275b2a0451bf82.png differ diff --git a/_book/docs/img/e661a6c6931c39f12f5b6833566b8947.png b/_book/docs/img/e661a6c6931c39f12f5b6833566b8947.png new file mode 100644 index 0000000000000000000000000000000000000000..77b48b7189acb0f8e5997371c8e516697bdf924e Binary files /dev/null and b/_book/docs/img/e661a6c6931c39f12f5b6833566b8947.png differ diff --git a/_book/docs/img/e6ef8c883764c13967c9c9fcc5617980.png b/_book/docs/img/e6ef8c883764c13967c9c9fcc5617980.png new file mode 100644 index 0000000000000000000000000000000000000000..961112c995525ae8fc32503c5c2e1d525656173e Binary files /dev/null and b/_book/docs/img/e6ef8c883764c13967c9c9fcc5617980.png differ diff --git a/_book/docs/img/e71e8b254fc758ab1a18ac4373e14344.png b/_book/docs/img/e71e8b254fc758ab1a18ac4373e14344.png new file mode 100644 index 0000000000000000000000000000000000000000..0872d3ae2295d7538e5a7fe9ec25f70250a9ee8a Binary files /dev/null and b/_book/docs/img/e71e8b254fc758ab1a18ac4373e14344.png differ diff --git a/_book/docs/img/e75b1239d806589f91c4a40aba7fdc05.png b/_book/docs/img/e75b1239d806589f91c4a40aba7fdc05.png new file mode 100644 index 0000000000000000000000000000000000000000..aa1e7807b1e70e9a85f20e1d1924405325ecf341 Binary files /dev/null and b/_book/docs/img/e75b1239d806589f91c4a40aba7fdc05.png differ diff --git a/_book/docs/img/e7acd74bc1dc7f0103e1b107aac74f84.png b/_book/docs/img/e7acd74bc1dc7f0103e1b107aac74f84.png new file mode 100644 index 0000000000000000000000000000000000000000..797b65ae063bee8bc4c79dda233b0c647dcf6db0 Binary files /dev/null and b/_book/docs/img/e7acd74bc1dc7f0103e1b107aac74f84.png differ diff --git a/_book/docs/img/e7d35854d0a726fbc4756cca4de4bf77.png b/_book/docs/img/e7d35854d0a726fbc4756cca4de4bf77.png new file mode 100644 index 0000000000000000000000000000000000000000..7e4084d7ec102bf29697e23bd00d09281b3a7a21 Binary files /dev/null and b/_book/docs/img/e7d35854d0a726fbc4756cca4de4bf77.png differ diff --git a/_book/docs/img/e7d7b1c5ccf121da6fcfbbc1eb78bbcd.png b/_book/docs/img/e7d7b1c5ccf121da6fcfbbc1eb78bbcd.png new file mode 100644 index 0000000000000000000000000000000000000000..a98a73348524e1b65f066fbf891d0dbbba18700d Binary files /dev/null and b/_book/docs/img/e7d7b1c5ccf121da6fcfbbc1eb78bbcd.png differ diff --git a/_book/docs/img/e80fdda43c295fbc39611b3d918d4b75.png b/_book/docs/img/e80fdda43c295fbc39611b3d918d4b75.png new file mode 100644 index 0000000000000000000000000000000000000000..8a55677a56ff1131a47a521caefdf7f9c3455ebb Binary files /dev/null and b/_book/docs/img/e80fdda43c295fbc39611b3d918d4b75.png differ diff --git a/_book/docs/img/e81fe926a5b379f37dfc5af80b8f83f3.png b/_book/docs/img/e81fe926a5b379f37dfc5af80b8f83f3.png new file mode 100644 index 0000000000000000000000000000000000000000..d0e6d7adfcec88b97acef5a242011ba54d5a0a92 Binary files /dev/null and b/_book/docs/img/e81fe926a5b379f37dfc5af80b8f83f3.png differ diff --git a/_book/docs/img/e8c78799e0967a32ee1efeaea30f6213.png b/_book/docs/img/e8c78799e0967a32ee1efeaea30f6213.png new file mode 100644 index 0000000000000000000000000000000000000000..65a377568d3f9f48307cd5109ab39c53f58df384 Binary files /dev/null and b/_book/docs/img/e8c78799e0967a32ee1efeaea30f6213.png differ diff --git a/_book/docs/img/e9dbc908a405f57008dbb80d1b8a9a70.png b/_book/docs/img/e9dbc908a405f57008dbb80d1b8a9a70.png new file mode 100644 index 0000000000000000000000000000000000000000..213c5ed75450eca18c707010cc75ee2fa1bdf218 Binary files /dev/null and b/_book/docs/img/e9dbc908a405f57008dbb80d1b8a9a70.png differ diff --git a/_book/docs/img/e9fe43924bd4226e7b819104bcc8b8c1.png b/_book/docs/img/e9fe43924bd4226e7b819104bcc8b8c1.png new file mode 100644 index 0000000000000000000000000000000000000000..450cc70b9ba13a79de4eec6fafc8f8e3e58a72fa Binary files /dev/null and b/_book/docs/img/e9fe43924bd4226e7b819104bcc8b8c1.png differ diff --git a/_book/docs/img/ea01744c06eb8853392bfd840dc1517d.png b/_book/docs/img/ea01744c06eb8853392bfd840dc1517d.png new file mode 100644 index 0000000000000000000000000000000000000000..6ef1ed0f1b27d1195c8fa05d728ff0d2a619f1eb Binary files /dev/null and b/_book/docs/img/ea01744c06eb8853392bfd840dc1517d.png differ diff --git a/_book/docs/img/ea0e34b1e4e7a7a6379bc52995143bf9.png b/_book/docs/img/ea0e34b1e4e7a7a6379bc52995143bf9.png new file mode 100644 index 0000000000000000000000000000000000000000..36b7c732de9a5712fdc61707148276183e88022a Binary files /dev/null and b/_book/docs/img/ea0e34b1e4e7a7a6379bc52995143bf9.png differ diff --git a/_book/docs/img/ea665ae1d507d66f5a44d05ff9e32613.png b/_book/docs/img/ea665ae1d507d66f5a44d05ff9e32613.png new file mode 100644 index 0000000000000000000000000000000000000000..034187445c6f0005520031e03e598210f15f7a75 Binary files /dev/null and b/_book/docs/img/ea665ae1d507d66f5a44d05ff9e32613.png differ diff --git a/_book/docs/img/ea804dce7429c547bcf0703446150f59.png b/_book/docs/img/ea804dce7429c547bcf0703446150f59.png new file mode 100644 index 0000000000000000000000000000000000000000..7a40b049f6500eabe8431cfc045517d823ae439d Binary files /dev/null and b/_book/docs/img/ea804dce7429c547bcf0703446150f59.png differ diff --git a/_book/docs/img/eaa74cb66b0dd1b45f9b312af76c23fb.png b/_book/docs/img/eaa74cb66b0dd1b45f9b312af76c23fb.png new file mode 100644 index 0000000000000000000000000000000000000000..733b4168f28dbdc9a1341fc32005775e82b1bfc7 Binary files /dev/null and b/_book/docs/img/eaa74cb66b0dd1b45f9b312af76c23fb.png differ diff --git a/_book/docs/img/eac2240244a4d3fb9f3d16c19760ea53.png b/_book/docs/img/eac2240244a4d3fb9f3d16c19760ea53.png new file mode 100644 index 0000000000000000000000000000000000000000..48ba055cf80259c93d7128bfb7812f4ec4bbc9e9 Binary files /dev/null and b/_book/docs/img/eac2240244a4d3fb9f3d16c19760ea53.png differ diff --git a/_book/docs/img/ead8d62e426d9309f25a82da77770f59.png b/_book/docs/img/ead8d62e426d9309f25a82da77770f59.png new file mode 100644 index 0000000000000000000000000000000000000000..27857a4bda81d2507fce27e61ea8809d67d04973 Binary files /dev/null and b/_book/docs/img/ead8d62e426d9309f25a82da77770f59.png differ diff --git a/_book/docs/img/eb191fa059117d5fb30958d7f6241704.png b/_book/docs/img/eb191fa059117d5fb30958d7f6241704.png new file mode 100644 index 0000000000000000000000000000000000000000..e4161dbc6e3a961f810b7b998b833ff418ec98a6 Binary files /dev/null and b/_book/docs/img/eb191fa059117d5fb30958d7f6241704.png differ diff --git a/_book/docs/img/eb36e4acf26c49641689d1a05dd8fa8a.png b/_book/docs/img/eb36e4acf26c49641689d1a05dd8fa8a.png new file mode 100644 index 0000000000000000000000000000000000000000..c6f69f98baaf962055e356ced11f840d33d4e0d8 Binary files /dev/null and b/_book/docs/img/eb36e4acf26c49641689d1a05dd8fa8a.png differ diff --git a/_book/docs/img/eb851fa4a367081c86d0a2eac3bdca65.png b/_book/docs/img/eb851fa4a367081c86d0a2eac3bdca65.png new file mode 100644 index 0000000000000000000000000000000000000000..790f55fb2aef96782ca90cbeab03f8a527d502be Binary files /dev/null and b/_book/docs/img/eb851fa4a367081c86d0a2eac3bdca65.png differ diff --git a/_book/docs/img/eb93aca89ce7486ca89aa5a9f4357617.png b/_book/docs/img/eb93aca89ce7486ca89aa5a9f4357617.png new file mode 100644 index 0000000000000000000000000000000000000000..fda2b72c510589901869abd205191fd7d36af913 Binary files /dev/null and b/_book/docs/img/eb93aca89ce7486ca89aa5a9f4357617.png differ diff --git a/_book/docs/img/ebaf329b1a5a45f2d451e4574f3d7857.png b/_book/docs/img/ebaf329b1a5a45f2d451e4574f3d7857.png new file mode 100644 index 0000000000000000000000000000000000000000..0a6d821bc02b81d60ed9dabc96cb53653d3ee81c --- /dev/null +++ b/_book/docs/img/ebaf329b1a5a45f2d451e4574f3d7857.png @@ -0,0 +1,265 @@ + + + +Page Not Found | GitLab Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    +
    +
    +
    +
    +404 +
    +
    +
    +
    +
    + + + + + + + +
    +
    +
    + +
    +
    +
    +
    + +
    +
    + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_book/docs/img/ebc54b5fdcb529ff40d6d097098188ae.png b/_book/docs/img/ebc54b5fdcb529ff40d6d097098188ae.png new file mode 100644 index 0000000000000000000000000000000000000000..bd9c2ae9f71fa119e6137d486e97ba60fb207304 Binary files /dev/null and b/_book/docs/img/ebc54b5fdcb529ff40d6d097098188ae.png differ diff --git a/_book/docs/img/ec9eebd0b49b9f0b94eb6d12fadd7cf5.png b/_book/docs/img/ec9eebd0b49b9f0b94eb6d12fadd7cf5.png new file mode 100644 index 0000000000000000000000000000000000000000..b03c585bd3f70bb3e27a231148709605884bfac9 Binary files /dev/null and b/_book/docs/img/ec9eebd0b49b9f0b94eb6d12fadd7cf5.png differ diff --git a/_book/docs/img/eca0c9ec85c6dfc8dbde06c368a9d94d.png b/_book/docs/img/eca0c9ec85c6dfc8dbde06c368a9d94d.png new file mode 100644 index 0000000000000000000000000000000000000000..a9e3343b396499fbcce2b625ebaadf0f01732a8f Binary files /dev/null and b/_book/docs/img/eca0c9ec85c6dfc8dbde06c368a9d94d.png differ diff --git a/_book/docs/img/ecb561241f5fcf0f0695ee4e29069b11.png b/_book/docs/img/ecb561241f5fcf0f0695ee4e29069b11.png new file mode 100644 index 0000000000000000000000000000000000000000..14c84825b19c1a7b143239a8e79f65f4d273d276 Binary files /dev/null and b/_book/docs/img/ecb561241f5fcf0f0695ee4e29069b11.png differ diff --git a/_book/docs/img/ecb68ae545435c5eb9229937635a5aee.png b/_book/docs/img/ecb68ae545435c5eb9229937635a5aee.png new file mode 100644 index 0000000000000000000000000000000000000000..891b21f4f766ea3fc3a1c4be62e1ee4c92f311b7 Binary files /dev/null and b/_book/docs/img/ecb68ae545435c5eb9229937635a5aee.png differ diff --git a/_book/docs/img/ece990045e1a7ae1237b5f2912a2df3e.png b/_book/docs/img/ece990045e1a7ae1237b5f2912a2df3e.png new file mode 100644 index 0000000000000000000000000000000000000000..8091f290afe453c3629255f49590db7ab6297410 Binary files /dev/null and b/_book/docs/img/ece990045e1a7ae1237b5f2912a2df3e.png differ diff --git a/_book/docs/img/ed5a96971ab453e6d33b3ad9079bd47c.png b/_book/docs/img/ed5a96971ab453e6d33b3ad9079bd47c.png new file mode 100644 index 0000000000000000000000000000000000000000..1d9bae148566b23a5d2d27f54994c25ba8a6e216 Binary files /dev/null and b/_book/docs/img/ed5a96971ab453e6d33b3ad9079bd47c.png differ diff --git a/_book/docs/img/ed70f998a438f30a2762829a3cc5b5b6.png b/_book/docs/img/ed70f998a438f30a2762829a3cc5b5b6.png new file mode 100644 index 0000000000000000000000000000000000000000..7d4f4a24cf80652c03b0bcfd3f347f26e943069f Binary files /dev/null and b/_book/docs/img/ed70f998a438f30a2762829a3cc5b5b6.png differ diff --git a/_book/docs/img/ed7d654fa8271709dfa6c567b48c5de6.png b/_book/docs/img/ed7d654fa8271709dfa6c567b48c5de6.png new file mode 100644 index 0000000000000000000000000000000000000000..71f773b4a6b07125ab6a2466d00e59248ad33b71 Binary files /dev/null and b/_book/docs/img/ed7d654fa8271709dfa6c567b48c5de6.png differ diff --git a/_book/docs/img/ed8bdb5d349320bc1d470f096578dfe7.png b/_book/docs/img/ed8bdb5d349320bc1d470f096578dfe7.png new file mode 100644 index 0000000000000000000000000000000000000000..1a70c4041fc648ec5105af96bef67ffcdbb63417 Binary files /dev/null and b/_book/docs/img/ed8bdb5d349320bc1d470f096578dfe7.png differ diff --git a/_book/docs/img/ed8e7e034537074afe857aa208bd315c.png b/_book/docs/img/ed8e7e034537074afe857aa208bd315c.png new file mode 100644 index 0000000000000000000000000000000000000000..d7193d25bec814e1e8e719630f1e5e44217b7ce0 Binary files /dev/null and b/_book/docs/img/ed8e7e034537074afe857aa208bd315c.png differ diff --git a/_book/docs/img/ee0396a1cb32367d7ba7c6f4a7262c7f.png b/_book/docs/img/ee0396a1cb32367d7ba7c6f4a7262c7f.png new file mode 100644 index 0000000000000000000000000000000000000000..b120099391faca900fb1de5575ea4d30c91514ae Binary files /dev/null and b/_book/docs/img/ee0396a1cb32367d7ba7c6f4a7262c7f.png differ diff --git a/_book/docs/img/ee04e8247fff074d8b122d6b5ec848f4.png b/_book/docs/img/ee04e8247fff074d8b122d6b5ec848f4.png new file mode 100644 index 0000000000000000000000000000000000000000..3a495fe407b76e6fbe497026a05273d1268faef5 Binary files /dev/null and b/_book/docs/img/ee04e8247fff074d8b122d6b5ec848f4.png differ diff --git a/_book/docs/img/ee8ead7652026dd03a75e2551122350f.png b/_book/docs/img/ee8ead7652026dd03a75e2551122350f.png new file mode 100644 index 0000000000000000000000000000000000000000..2e1abf75bf7939db4bab30835801d4b3ea55bc37 Binary files /dev/null and b/_book/docs/img/ee8ead7652026dd03a75e2551122350f.png differ diff --git a/_book/docs/img/eeadc0bb054ceec8f09d2c44982f4103.png b/_book/docs/img/eeadc0bb054ceec8f09d2c44982f4103.png new file mode 100644 index 0000000000000000000000000000000000000000..26a8b91c3ef65551938fb6d836e18198006ef262 Binary files /dev/null and b/_book/docs/img/eeadc0bb054ceec8f09d2c44982f4103.png differ diff --git a/_book/docs/img/eec4d73b57835f2caa3ad88d45260b49.png b/_book/docs/img/eec4d73b57835f2caa3ad88d45260b49.png new file mode 100644 index 0000000000000000000000000000000000000000..d88e9037a388e78039c1fbb955536a6526f8b392 Binary files /dev/null and b/_book/docs/img/eec4d73b57835f2caa3ad88d45260b49.png differ diff --git a/_book/docs/img/ef26fe9cbbfc0c1f060c6e7c578bd450.png b/_book/docs/img/ef26fe9cbbfc0c1f060c6e7c578bd450.png new file mode 100644 index 0000000000000000000000000000000000000000..eefa7f43469943ae576021ef12aabd9f1bd7e29c Binary files /dev/null and b/_book/docs/img/ef26fe9cbbfc0c1f060c6e7c578bd450.png differ diff --git a/_book/docs/img/ef67d77909a856277f9f2821fa0c18ea.png b/_book/docs/img/ef67d77909a856277f9f2821fa0c18ea.png new file mode 100644 index 0000000000000000000000000000000000000000..2d723d21d28f8e5f3fbaee7055858496d3f6dc1b Binary files /dev/null and b/_book/docs/img/ef67d77909a856277f9f2821fa0c18ea.png differ diff --git a/_book/docs/img/ef8ff296b4a28ddcd52a6c4fd3ded454.png b/_book/docs/img/ef8ff296b4a28ddcd52a6c4fd3ded454.png new file mode 100644 index 0000000000000000000000000000000000000000..018ad66f4807d701751f05c15047f1ce123d738f Binary files /dev/null and b/_book/docs/img/ef8ff296b4a28ddcd52a6c4fd3ded454.png differ diff --git a/_book/docs/img/f08e838598cbf1f61321a510bb24c6a1.png b/_book/docs/img/f08e838598cbf1f61321a510bb24c6a1.png new file mode 100644 index 0000000000000000000000000000000000000000..47744d767cafc78b60ef755e7341ea3ac422e9f3 Binary files /dev/null and b/_book/docs/img/f08e838598cbf1f61321a510bb24c6a1.png differ diff --git a/_book/docs/img/f0a8b71ac0a74f03724937e45e8782b9.png b/_book/docs/img/f0a8b71ac0a74f03724937e45e8782b9.png new file mode 100644 index 0000000000000000000000000000000000000000..5528a9bb4d9d05edefd2ab94f40a6578cf72a6fb Binary files /dev/null and b/_book/docs/img/f0a8b71ac0a74f03724937e45e8782b9.png differ diff --git a/_book/docs/img/f0d4bcbd75dfae1dbbc867343090a4ca.png b/_book/docs/img/f0d4bcbd75dfae1dbbc867343090a4ca.png new file mode 100644 index 0000000000000000000000000000000000000000..48820f5a3d390fe6cb4f3c0a23ad078bc127e80e Binary files /dev/null and b/_book/docs/img/f0d4bcbd75dfae1dbbc867343090a4ca.png differ diff --git a/_book/docs/img/f0d8585fb8235b36b1464ed1d142a4c0.png b/_book/docs/img/f0d8585fb8235b36b1464ed1d142a4c0.png new file mode 100644 index 0000000000000000000000000000000000000000..c20e5cd70231df16da0eb2f0123677dc30a33617 Binary files /dev/null and b/_book/docs/img/f0d8585fb8235b36b1464ed1d142a4c0.png differ diff --git a/_book/docs/img/f12701028e6548c505318ef2d4e378db.png b/_book/docs/img/f12701028e6548c505318ef2d4e378db.png new file mode 100644 index 0000000000000000000000000000000000000000..7422a121841e499a6cd6e79b827505310b8cbcf2 Binary files /dev/null and b/_book/docs/img/f12701028e6548c505318ef2d4e378db.png differ diff --git a/_book/docs/img/f1e26381a4d60fa929a9285e04721656.png b/_book/docs/img/f1e26381a4d60fa929a9285e04721656.png new file mode 100644 index 0000000000000000000000000000000000000000..a86dd6e374963a4c468b41a7e0fd22d8f6ede71b Binary files /dev/null and b/_book/docs/img/f1e26381a4d60fa929a9285e04721656.png differ diff --git a/_book/docs/img/f293e9e73b2cf8c4ef278104fbd068d5.png b/_book/docs/img/f293e9e73b2cf8c4ef278104fbd068d5.png new file mode 100644 index 0000000000000000000000000000000000000000..0a7bc01310f435ee28a891b62c26a2d3c0c2721e Binary files /dev/null and b/_book/docs/img/f293e9e73b2cf8c4ef278104fbd068d5.png differ diff --git a/_book/docs/img/f2d420adddd87cc8087fea62246e7b67.png b/_book/docs/img/f2d420adddd87cc8087fea62246e7b67.png new file mode 100644 index 0000000000000000000000000000000000000000..9749a791e030bf72a76724aa0840911e9ed10b16 Binary files /dev/null and b/_book/docs/img/f2d420adddd87cc8087fea62246e7b67.png differ diff --git a/_book/docs/img/f313f74b73573e7a2449aa6d00ae7934.png b/_book/docs/img/f313f74b73573e7a2449aa6d00ae7934.png new file mode 100644 index 0000000000000000000000000000000000000000..78b810e200e4dde279be2a1114527746519d600c Binary files /dev/null and b/_book/docs/img/f313f74b73573e7a2449aa6d00ae7934.png differ diff --git a/_book/docs/img/f3550bb5a4a6074ef46ae27848adc308.png b/_book/docs/img/f3550bb5a4a6074ef46ae27848adc308.png new file mode 100644 index 0000000000000000000000000000000000000000..608959f8d821d26713da96d45c7181635c15303b Binary files /dev/null and b/_book/docs/img/f3550bb5a4a6074ef46ae27848adc308.png differ diff --git a/_book/docs/img/f36631c8d1fd9cb42fb7c58a495c24be.png b/_book/docs/img/f36631c8d1fd9cb42fb7c58a495c24be.png new file mode 100644 index 0000000000000000000000000000000000000000..4231c353c59c997dac90b9f3c3e15b0b65610af6 Binary files /dev/null and b/_book/docs/img/f36631c8d1fd9cb42fb7c58a495c24be.png differ diff --git a/_book/docs/img/f380fbb3646558d8becf561df5894c38.png b/_book/docs/img/f380fbb3646558d8becf561df5894c38.png new file mode 100644 index 0000000000000000000000000000000000000000..c69ef2499032d756ccdd89dce84b84d14358159f Binary files /dev/null and b/_book/docs/img/f380fbb3646558d8becf561df5894c38.png differ diff --git a/_book/docs/img/f406b88682259abab36d343539b1664c.png b/_book/docs/img/f406b88682259abab36d343539b1664c.png new file mode 100644 index 0000000000000000000000000000000000000000..5129573a3c1ba13628eb0e4a701364afe8565501 Binary files /dev/null and b/_book/docs/img/f406b88682259abab36d343539b1664c.png differ diff --git a/_book/docs/img/f44886a0dc98ed48e0854c7d2ac6a220.png b/_book/docs/img/f44886a0dc98ed48e0854c7d2ac6a220.png new file mode 100644 index 0000000000000000000000000000000000000000..6368c6e82b0be5479f35b72bf2f96f89ea943c0a Binary files /dev/null and b/_book/docs/img/f44886a0dc98ed48e0854c7d2ac6a220.png differ diff --git a/_book/docs/img/f4a6d7020c73bd402fc6428d02a4e550.png b/_book/docs/img/f4a6d7020c73bd402fc6428d02a4e550.png new file mode 100644 index 0000000000000000000000000000000000000000..f7242dd5c50539546cd8b1825ef24b8df80afd22 Binary files /dev/null and b/_book/docs/img/f4a6d7020c73bd402fc6428d02a4e550.png differ diff --git a/_book/docs/img/f52fe1b4788045a510a1783bfb546b6f.png b/_book/docs/img/f52fe1b4788045a510a1783bfb546b6f.png new file mode 100644 index 0000000000000000000000000000000000000000..88f25e9fe236b30a9309b6ea69754520cdb8c0ba Binary files /dev/null and b/_book/docs/img/f52fe1b4788045a510a1783bfb546b6f.png differ diff --git a/_book/docs/img/f5739c1b278ddd91c915c534514b4235.png b/_book/docs/img/f5739c1b278ddd91c915c534514b4235.png new file mode 100644 index 0000000000000000000000000000000000000000..a1d7bc2878d3f66a38350315857b794fff497f7b Binary files /dev/null and b/_book/docs/img/f5739c1b278ddd91c915c534514b4235.png differ diff --git a/_book/docs/img/f5f57e5e3d074f574a5b26d23eb0b721.png b/_book/docs/img/f5f57e5e3d074f574a5b26d23eb0b721.png new file mode 100644 index 0000000000000000000000000000000000000000..374de715ab46f139a6c35a2c456ae63d221e14b5 Binary files /dev/null and b/_book/docs/img/f5f57e5e3d074f574a5b26d23eb0b721.png differ diff --git a/_book/docs/img/f60803ec89d6ae84310e181507eb2ad8.png b/_book/docs/img/f60803ec89d6ae84310e181507eb2ad8.png new file mode 100644 index 0000000000000000000000000000000000000000..c1aa44669a873fc61b55e3cf4f635240cd04b0f1 Binary files /dev/null and b/_book/docs/img/f60803ec89d6ae84310e181507eb2ad8.png differ diff --git a/_book/docs/img/f652f5dac5bec0bb81edc08cbfd7a01b.png b/_book/docs/img/f652f5dac5bec0bb81edc08cbfd7a01b.png new file mode 100644 index 0000000000000000000000000000000000000000..48a88fedc8d9d38f2340e5015e4cf78394e01de6 Binary files /dev/null and b/_book/docs/img/f652f5dac5bec0bb81edc08cbfd7a01b.png differ diff --git a/_book/docs/img/f6b1fbcae610d7e8b04ec117e32573f3.png b/_book/docs/img/f6b1fbcae610d7e8b04ec117e32573f3.png new file mode 100644 index 0000000000000000000000000000000000000000..ca9882d2902fc80f4abe3addad66db2b851cadc0 Binary files /dev/null and b/_book/docs/img/f6b1fbcae610d7e8b04ec117e32573f3.png differ diff --git a/_book/docs/img/f6e26efd0e5206a2e9d1bf43865b9f4a.png b/_book/docs/img/f6e26efd0e5206a2e9d1bf43865b9f4a.png new file mode 100644 index 0000000000000000000000000000000000000000..c4f392553bba74d680656aed3c65c990767b12e5 Binary files /dev/null and b/_book/docs/img/f6e26efd0e5206a2e9d1bf43865b9f4a.png differ diff --git a/_book/docs/img/f7050ce0aa3559c639befc2fe3d7aacb.png b/_book/docs/img/f7050ce0aa3559c639befc2fe3d7aacb.png new file mode 100644 index 0000000000000000000000000000000000000000..fe057773f62136fd59232126e0377b48f15c61b8 Binary files /dev/null and b/_book/docs/img/f7050ce0aa3559c639befc2fe3d7aacb.png differ diff --git a/_book/docs/img/f7ae6b6be5d2dd02010825234555fee6.png b/_book/docs/img/f7ae6b6be5d2dd02010825234555fee6.png new file mode 100644 index 0000000000000000000000000000000000000000..df7e89862834fc0227453945ec11743ff4abbb62 Binary files /dev/null and b/_book/docs/img/f7ae6b6be5d2dd02010825234555fee6.png differ diff --git a/_book/docs/img/f7bf9b7c134eb4ee2629082be8992d5a.png b/_book/docs/img/f7bf9b7c134eb4ee2629082be8992d5a.png new file mode 100644 index 0000000000000000000000000000000000000000..c3cb7f7cceae1f71ac0c81004c7879235c6b7015 Binary files /dev/null and b/_book/docs/img/f7bf9b7c134eb4ee2629082be8992d5a.png differ diff --git a/_book/docs/img/f81ccf2ef168880473496ad46b2d991f.png b/_book/docs/img/f81ccf2ef168880473496ad46b2d991f.png new file mode 100644 index 0000000000000000000000000000000000000000..5d1e2fe43eb3a716a8a9b5512213e852a25733b1 Binary files /dev/null and b/_book/docs/img/f81ccf2ef168880473496ad46b2d991f.png differ diff --git a/_book/docs/img/f8c3e75c59db0de2544d73c590e98696.png b/_book/docs/img/f8c3e75c59db0de2544d73c590e98696.png new file mode 100644 index 0000000000000000000000000000000000000000..313c88a666529f01c31983845aef1cac6b5bba88 Binary files /dev/null and b/_book/docs/img/f8c3e75c59db0de2544d73c590e98696.png differ diff --git a/_book/docs/img/f8c421bf7dd271d1aeee39c15aab183d.png b/_book/docs/img/f8c421bf7dd271d1aeee39c15aab183d.png new file mode 100644 index 0000000000000000000000000000000000000000..91afff16ba50d9af08bb4492a94a8e3f0065a99f Binary files /dev/null and b/_book/docs/img/f8c421bf7dd271d1aeee39c15aab183d.png differ diff --git a/_book/docs/img/f8cfebdbd362ba809375c8d9c38416ba.png b/_book/docs/img/f8cfebdbd362ba809375c8d9c38416ba.png new file mode 100644 index 0000000000000000000000000000000000000000..a84f0c4b86983ed2fa99b8a8fd809f330dad44c8 Binary files /dev/null and b/_book/docs/img/f8cfebdbd362ba809375c8d9c38416ba.png differ diff --git a/_book/docs/img/f9144e03cf945bcf549c131e2816298f.png b/_book/docs/img/f9144e03cf945bcf549c131e2816298f.png new file mode 100644 index 0000000000000000000000000000000000000000..8b1a7e6890a9352e38f526e56dd6932538abf498 Binary files /dev/null and b/_book/docs/img/f9144e03cf945bcf549c131e2816298f.png differ diff --git a/_book/docs/img/f94efd219528f7641e29dbca3bc215ad.png b/_book/docs/img/f94efd219528f7641e29dbca3bc215ad.png new file mode 100644 index 0000000000000000000000000000000000000000..a92a3362eee67d783b140b9d558afe378a51912a Binary files /dev/null and b/_book/docs/img/f94efd219528f7641e29dbca3bc215ad.png differ diff --git a/_book/docs/img/f9a1ce8fe1042543bc2355950f642a05.png b/_book/docs/img/f9a1ce8fe1042543bc2355950f642a05.png new file mode 100644 index 0000000000000000000000000000000000000000..aa030517803ea8c5ced744019967a1960647a4fe Binary files /dev/null and b/_book/docs/img/f9a1ce8fe1042543bc2355950f642a05.png differ diff --git a/_book/docs/img/f9be0028bdcfdf495f7fd0f148de5214.png b/_book/docs/img/f9be0028bdcfdf495f7fd0f148de5214.png new file mode 100644 index 0000000000000000000000000000000000000000..944bd3045109705afbe8d6381a95b566596ff945 Binary files /dev/null and b/_book/docs/img/f9be0028bdcfdf495f7fd0f148de5214.png differ diff --git a/_book/docs/img/fa591f90dc1e8840fe7fd692f24dcffe.png b/_book/docs/img/fa591f90dc1e8840fe7fd692f24dcffe.png new file mode 100644 index 0000000000000000000000000000000000000000..acb0ed243428adf45d0627b21df26767451d6f14 Binary files /dev/null and b/_book/docs/img/fa591f90dc1e8840fe7fd692f24dcffe.png differ diff --git a/_book/docs/img/fad2df1fa4371b39b3ea1032a8ad236c.png b/_book/docs/img/fad2df1fa4371b39b3ea1032a8ad236c.png new file mode 100644 index 0000000000000000000000000000000000000000..58bdb855fb7418196421f1ee32af03a91b763599 Binary files /dev/null and b/_book/docs/img/fad2df1fa4371b39b3ea1032a8ad236c.png differ diff --git a/_book/docs/img/fb0d67715160a5a049ca0b8e7d7af698.png b/_book/docs/img/fb0d67715160a5a049ca0b8e7d7af698.png new file mode 100644 index 0000000000000000000000000000000000000000..827e16a712fe77d9996dcf100cc345171bebcdd2 Binary files /dev/null and b/_book/docs/img/fb0d67715160a5a049ca0b8e7d7af698.png differ diff --git a/_book/docs/img/fb8ded1bb07112b49dc42dff02fe01f7.png b/_book/docs/img/fb8ded1bb07112b49dc42dff02fe01f7.png new file mode 100644 index 0000000000000000000000000000000000000000..42685867e0e965c1c9a5f7862ac06bc47561174f Binary files /dev/null and b/_book/docs/img/fb8ded1bb07112b49dc42dff02fe01f7.png differ diff --git a/_book/docs/img/fc09af9303f629aff49a9a4dc5327e65.png b/_book/docs/img/fc09af9303f629aff49a9a4dc5327e65.png new file mode 100644 index 0000000000000000000000000000000000000000..117797d615a8eae14d26245a0c3d617d3be60540 Binary files /dev/null and b/_book/docs/img/fc09af9303f629aff49a9a4dc5327e65.png differ diff --git a/_book/docs/img/fc692dde7a0c9ce30f0036b1a05b2768.png b/_book/docs/img/fc692dde7a0c9ce30f0036b1a05b2768.png new file mode 100644 index 0000000000000000000000000000000000000000..b37c819bbcaf382b3b38b76f192650936d2a7425 Binary files /dev/null and b/_book/docs/img/fc692dde7a0c9ce30f0036b1a05b2768.png differ diff --git a/_book/docs/img/fc80ee243381890526471d6fc360f7cf.png b/_book/docs/img/fc80ee243381890526471d6fc360f7cf.png new file mode 100644 index 0000000000000000000000000000000000000000..4af65360d1df88921ee7e5d8caa3fb675ece0055 Binary files /dev/null and b/_book/docs/img/fc80ee243381890526471d6fc360f7cf.png differ diff --git a/_book/docs/img/fd0991d7941fed77c4d82bd219ec713b.png b/_book/docs/img/fd0991d7941fed77c4d82bd219ec713b.png new file mode 100644 index 0000000000000000000000000000000000000000..832d0c0709e83125df05fae0015cf0bd792f4915 Binary files /dev/null and b/_book/docs/img/fd0991d7941fed77c4d82bd219ec713b.png differ diff --git a/_book/docs/img/fd15df8f9a5a46582845610e8b5881bb.png b/_book/docs/img/fd15df8f9a5a46582845610e8b5881bb.png new file mode 100644 index 0000000000000000000000000000000000000000..ce37bda0b23aa910c951f86dbc4db8e0b3f27dc8 Binary files /dev/null and b/_book/docs/img/fd15df8f9a5a46582845610e8b5881bb.png differ diff --git a/_book/docs/img/fd1e35952a7538923376d54325798b24.png b/_book/docs/img/fd1e35952a7538923376d54325798b24.png new file mode 100644 index 0000000000000000000000000000000000000000..d5a3143fdd44b781b907a99e64a353f8ac30d906 Binary files /dev/null and b/_book/docs/img/fd1e35952a7538923376d54325798b24.png differ diff --git a/_book/docs/img/fd24d5842b589870b2063edaca149511.png b/_book/docs/img/fd24d5842b589870b2063edaca149511.png new file mode 100644 index 0000000000000000000000000000000000000000..d09aa966f780acc2e3bc40e504acd63725f72f7a Binary files /dev/null and b/_book/docs/img/fd24d5842b589870b2063edaca149511.png differ diff --git a/_book/docs/img/fd54213f0e98a4b2f6482ab98d497410.png b/_book/docs/img/fd54213f0e98a4b2f6482ab98d497410.png new file mode 100644 index 0000000000000000000000000000000000000000..6bcd55962d4ecd643fd84be907bbc06b2e643093 Binary files /dev/null and b/_book/docs/img/fd54213f0e98a4b2f6482ab98d497410.png differ diff --git a/_book/docs/img/fd7124974fcca5463d2ce7385bfb700e.png b/_book/docs/img/fd7124974fcca5463d2ce7385bfb700e.png new file mode 100644 index 0000000000000000000000000000000000000000..dc7be55b6c2bab3b3674273a7f42cb2bf9b4246f Binary files /dev/null and b/_book/docs/img/fd7124974fcca5463d2ce7385bfb700e.png differ diff --git a/_book/docs/img/fd79e7dae86040d6e1249793ae0b1502.png b/_book/docs/img/fd79e7dae86040d6e1249793ae0b1502.png new file mode 100644 index 0000000000000000000000000000000000000000..6737bf27193ea50ef94f2a302eef7d48f133e605 Binary files /dev/null and b/_book/docs/img/fd79e7dae86040d6e1249793ae0b1502.png differ diff --git a/_book/docs/img/fe213f080418c1bd6d92faa7e49770d3.png b/_book/docs/img/fe213f080418c1bd6d92faa7e49770d3.png new file mode 100644 index 0000000000000000000000000000000000000000..e55e664b31065692a4d0fd6be07f6c48c6250ce9 Binary files /dev/null and b/_book/docs/img/fe213f080418c1bd6d92faa7e49770d3.png differ diff --git a/_book/docs/img/fe601ff47f99f0fd5220742f61007450.png b/_book/docs/img/fe601ff47f99f0fd5220742f61007450.png new file mode 100644 index 0000000000000000000000000000000000000000..53c10121e84c072e964d94702c83d4f9d9972fdb Binary files /dev/null and b/_book/docs/img/fe601ff47f99f0fd5220742f61007450.png differ diff --git a/_book/docs/img/fe7d77556848be98a93c7b6516b0e6f8.png b/_book/docs/img/fe7d77556848be98a93c7b6516b0e6f8.png new file mode 100644 index 0000000000000000000000000000000000000000..ae8248f93e09655a412c3d77b2fa17b8d5e9cc2f Binary files /dev/null and b/_book/docs/img/fe7d77556848be98a93c7b6516b0e6f8.png differ diff --git a/_book/docs/img/fe827d4bc97b90c3a250af05fd988fc4.png b/_book/docs/img/fe827d4bc97b90c3a250af05fd988fc4.png new file mode 100644 index 0000000000000000000000000000000000000000..9a378656b68d126a84c5e58a4583d92e0e9ea48a Binary files /dev/null and b/_book/docs/img/fe827d4bc97b90c3a250af05fd988fc4.png differ diff --git a/_book/docs/img/fee3cc5116f884089066af3908605cbe.png b/_book/docs/img/fee3cc5116f884089066af3908605cbe.png new file mode 100644 index 0000000000000000000000000000000000000000..d8224ec40ea73af042268142723ee62fc76c4dbe Binary files /dev/null and b/_book/docs/img/fee3cc5116f884089066af3908605cbe.png differ diff --git a/_book/docs/img/fef11068ab5cc264b208a4bd3addb7fa.png b/_book/docs/img/fef11068ab5cc264b208a4bd3addb7fa.png new file mode 100644 index 0000000000000000000000000000000000000000..7c260a6d968ee31bb616ca8bb04ee29f2d17dbb9 Binary files /dev/null and b/_book/docs/img/fef11068ab5cc264b208a4bd3addb7fa.png differ diff --git a/_book/docs/img/ff2558c68f4e646052a0c39a7d3f8710.png b/_book/docs/img/ff2558c68f4e646052a0c39a7d3f8710.png new file mode 100644 index 0000000000000000000000000000000000000000..664d095bdbfecbb28746f7574b9df916a90631dc Binary files /dev/null and b/_book/docs/img/ff2558c68f4e646052a0c39a7d3f8710.png differ diff --git a/_book/docs/img/ff949c9ca6d0d99318f68a1784db7950.png b/_book/docs/img/ff949c9ca6d0d99318f68a1784db7950.png new file mode 100644 index 0000000000000000000000000000000000000000..12bbe6fcfe2657ee19663fe324f344d622123c87 Binary files /dev/null and b/_book/docs/img/ff949c9ca6d0d99318f68a1784db7950.png differ diff --git a/_book/docs/img/logo-s.png b/_book/docs/img/logo-s.png new file mode 100644 index 0000000000000000000000000000000000000000..0fcb701b78f7c3e8d3963c7f1d80aab429347f60 Binary files /dev/null and b/_book/docs/img/logo-s.png differ diff --git a/_book/docs/img/logo.png b/_book/docs/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8ef04aca0f633c9a1c7075681ef1db4b8e03c7f9 Binary files /dev/null and b/_book/docs/img/logo.png differ diff --git a/_book/gitbook/fonts/fontawesome/FontAwesome.otf b/_book/gitbook/fonts/fontawesome/FontAwesome.otf new file mode 100644 index 0000000000000000000000000000000000000000..d4de13e832d567ff29c5b4e9561b8c370348cc9c Binary files /dev/null and b/_book/gitbook/fonts/fontawesome/FontAwesome.otf differ diff --git a/_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..c7b00d2ba8896fd29de846b19f89fcf0d56ad152 Binary files /dev/null and b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot differ diff --git a/_book/gitbook/fonts/fontawesome/fontawesome-webfont.svg b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.svg new file mode 100644 index 0000000000000000000000000000000000000000..8b66187fe067c3aa389ce8c98108f349ceae159c --- /dev/null +++ b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.svg @@ -0,0 +1,685 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f221e50a2ef60738ba30932d834530cdfe55cb3e Binary files /dev/null and b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf differ diff --git a/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..6e7483cf61b490c08ed644d6ef802c69472eb247 Binary files /dev/null and b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff differ diff --git a/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff2 b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..7eb74fd127ee5eddf3b95fee6a20dc1684b0963b Binary files /dev/null and b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff2 differ diff --git a/_book/gitbook/gitbook-plugin-back-to-top-button/plugin.css b/_book/gitbook/gitbook-plugin-back-to-top-button/plugin.css new file mode 100644 index 0000000000000000000000000000000000000000..a418cbb57052d052ff4b2a63b8de1cf63ff9189a --- /dev/null +++ b/_book/gitbook/gitbook-plugin-back-to-top-button/plugin.css @@ -0,0 +1,55 @@ +.back-to-top { + position: fixed; + bottom: 25px; + right: 25px; + background: rgba(0, 0, 0, 0.5); + width: 50px; + height: 50px; + display: block; + text-decoration: none; + -webkit-border-radius: 35px; + -moz-border-radius: 35px; + border-radius: 35px; + display: none; +} +.back-to-top i { + color: #fff; + margin: 0; + position: relative; + left: 15px; + top: 14px; + font-size: 22px; +} +.back-to-top:hover { + background: rgba(0, 0, 0, 0.9); + cursor: pointer; +} +.book.color-theme-1 .back-to-top { + background: rgba(112, 66, 20, 0.5); +} +.book.color-theme-1 .back-to-top i { + color: #f3eacb; +} +.book.color-theme-1 .back-to-top:hover { + background: rgba(112, 66, 20, 0.9); +} +.book.color-theme-2 .back-to-top { + background: rgba(189, 202, 219, 0.5); +} +.book.color-theme-2 .back-to-top i { + color: #1C1F2B; +} +.book.color-theme-2 .back-to-top:hover { + background: rgba(189, 202, 219, 0.9); +} + +@media only screen + and (min-device-width: 320px) + and (max-device-width: 480px) + and (-webkit-min-device-pixel-ratio: 2) + and (orientation: portrait) { + .back-to-top { + bottom: 10px; + right: 10px; + } +} \ No newline at end of file diff --git a/_book/gitbook/gitbook-plugin-back-to-top-button/plugin.js b/_book/gitbook/gitbook-plugin-back-to-top-button/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..abd35237d1344234bf109e26729ddbc11a0040a6 --- /dev/null +++ b/_book/gitbook/gitbook-plugin-back-to-top-button/plugin.js @@ -0,0 +1,25 @@ +var gitbook = window.gitbook; + +gitbook.events.on('page.change', function() { + + var back_to_top_button = ['
    '].join(""); + $(".book").append(back_to_top_button) + + $(".back-to-top").hide(); + + $('.book-body,.body-inner').on('scroll', function () { + if ($(this).scrollTop() > 100) { + $('.back-to-top').fadeIn(); + } else { + $('.back-to-top').fadeOut(); + } + }); + + $('.back-to-top').click(function () { + $('.book-body,.body-inner').animate({ + scrollTop: 0 + }, 800); + return false; + }); + +}); diff --git a/_book/gitbook/gitbook-plugin-fontsettings/fontsettings.js b/_book/gitbook/gitbook-plugin-fontsettings/fontsettings.js new file mode 100644 index 0000000000000000000000000000000000000000..ff7be7141364d4fbd6efa92cf03f3028b38f2809 --- /dev/null +++ b/_book/gitbook/gitbook-plugin-fontsettings/fontsettings.js @@ -0,0 +1,240 @@ +require(['gitbook', 'jquery'], function(gitbook, $) { + // Configuration + var MAX_SIZE = 4, + MIN_SIZE = 0, + BUTTON_ID; + + // Current fontsettings state + var fontState; + + // Default themes + var THEMES = [ + { + config: 'white', + text: 'White', + id: 0 + }, + { + config: 'sepia', + text: 'Sepia', + id: 1 + }, + { + config: 'night', + text: 'Night', + id: 2 + } + ]; + + // Default font families + var FAMILIES = [ + { + config: 'serif', + text: 'Serif', + id: 0 + }, + { + config: 'sans', + text: 'Sans', + id: 1 + } + ]; + + // Return configured themes + function getThemes() { + return THEMES; + } + + // Modify configured themes + function setThemes(themes) { + THEMES = themes; + updateButtons(); + } + + // Return configured font families + function getFamilies() { + return FAMILIES; + } + + // Modify configured font families + function setFamilies(families) { + FAMILIES = families; + updateButtons(); + } + + // Save current font settings + function saveFontSettings() { + gitbook.storage.set('fontState', fontState); + update(); + } + + // Increase font size + function enlargeFontSize(e) { + e.preventDefault(); + if (fontState.size >= MAX_SIZE) return; + + fontState.size++; + saveFontSettings(); + } + + // Decrease font size + function reduceFontSize(e) { + e.preventDefault(); + if (fontState.size <= MIN_SIZE) return; + + fontState.size--; + saveFontSettings(); + } + + // Change font family + function changeFontFamily(configName, e) { + if (e && e instanceof Event) { + e.preventDefault(); + } + + var familyId = getFontFamilyId(configName); + fontState.family = familyId; + saveFontSettings(); + } + + // Change type of color theme + function changeColorTheme(configName, e) { + if (e && e instanceof Event) { + e.preventDefault(); + } + + var $book = gitbook.state.$book; + + // Remove currently applied color theme + if (fontState.theme !== 0) + $book.removeClass('color-theme-'+fontState.theme); + + // Set new color theme + var themeId = getThemeId(configName); + fontState.theme = themeId; + if (fontState.theme !== 0) + $book.addClass('color-theme-'+fontState.theme); + + saveFontSettings(); + } + + // Return the correct id for a font-family config key + // Default to first font-family + function getFontFamilyId(configName) { + // Search for plugin configured font family + var configFamily = $.grep(FAMILIES, function(family) { + return family.config == configName; + })[0]; + // Fallback to default font family + return (!!configFamily)? configFamily.id : 0; + } + + // Return the correct id for a theme config key + // Default to first theme + function getThemeId(configName) { + // Search for plugin configured theme + var configTheme = $.grep(THEMES, function(theme) { + return theme.config == configName; + })[0]; + // Fallback to default theme + return (!!configTheme)? configTheme.id : 0; + } + + function update() { + var $book = gitbook.state.$book; + + $('.font-settings .font-family-list li').removeClass('active'); + $('.font-settings .font-family-list li:nth-child('+(fontState.family+1)+')').addClass('active'); + + $book[0].className = $book[0].className.replace(/\bfont-\S+/g, ''); + $book.addClass('font-size-'+fontState.size); + $book.addClass('font-family-'+fontState.family); + + if(fontState.theme !== 0) { + $book[0].className = $book[0].className.replace(/\bcolor-theme-\S+/g, ''); + $book.addClass('color-theme-'+fontState.theme); + } + } + + function init(config) { + // Search for plugin configured font family + var configFamily = getFontFamilyId(config.family), + configTheme = getThemeId(config.theme); + + // Instantiate font state object + fontState = gitbook.storage.get('fontState', { + size: config.size || 2, + family: configFamily, + theme: configTheme + }); + + update(); + } + + function updateButtons() { + // Remove existing fontsettings buttons + if (!!BUTTON_ID) { + gitbook.toolbar.removeButton(BUTTON_ID); + } + + // Create buttons in toolbar + BUTTON_ID = gitbook.toolbar.createButton({ + icon: 'fa fa-font', + label: 'Font Settings', + className: 'font-settings', + dropdown: [ + [ + { + text: 'A', + className: 'font-reduce', + onClick: reduceFontSize + }, + { + text: 'A', + className: 'font-enlarge', + onClick: enlargeFontSize + } + ], + $.map(FAMILIES, function(family) { + family.onClick = function(e) { + return changeFontFamily(family.config, e); + }; + + return family; + }), + $.map(THEMES, function(theme) { + theme.onClick = function(e) { + return changeColorTheme(theme.config, e); + }; + + return theme; + }) + ] + }); + } + + // Init configuration at start + gitbook.events.bind('start', function(e, config) { + var opts = config.fontsettings; + + // Generate buttons at start + updateButtons(); + + // Init current settings + init(opts); + }); + + // Expose API + gitbook.fontsettings = { + enlargeFontSize: enlargeFontSize, + reduceFontSize: reduceFontSize, + setTheme: changeColorTheme, + setFamily: changeFontFamily, + getThemes: getThemes, + setThemes: setThemes, + getFamilies: getFamilies, + setFamilies: setFamilies + }; +}); + + diff --git a/_book/gitbook/gitbook-plugin-fontsettings/website.css b/_book/gitbook/gitbook-plugin-fontsettings/website.css new file mode 100644 index 0000000000000000000000000000000000000000..26591fe8112a6e3f1de9855312574e9604a490f0 --- /dev/null +++ b/_book/gitbook/gitbook-plugin-fontsettings/website.css @@ -0,0 +1,291 @@ +/* + * Theme 1 + */ +.color-theme-1 .dropdown-menu { + background-color: #111111; + border-color: #7e888b; +} +.color-theme-1 .dropdown-menu .dropdown-caret .caret-inner { + border-bottom: 9px solid #111111; +} +.color-theme-1 .dropdown-menu .buttons { + border-color: #7e888b; +} +.color-theme-1 .dropdown-menu .button { + color: #afa790; +} +.color-theme-1 .dropdown-menu .button:hover { + color: #73553c; +} +/* + * Theme 2 + */ +.color-theme-2 .dropdown-menu { + background-color: #2d3143; + border-color: #272a3a; +} +.color-theme-2 .dropdown-menu .dropdown-caret .caret-inner { + border-bottom: 9px solid #2d3143; +} +.color-theme-2 .dropdown-menu .buttons { + border-color: #272a3a; +} +.color-theme-2 .dropdown-menu .button { + color: #62677f; +} +.color-theme-2 .dropdown-menu .button:hover { + color: #f4f4f5; +} +.book .book-header .font-settings .font-enlarge { + line-height: 30px; + font-size: 1.4em; +} +.book .book-header .font-settings .font-reduce { + line-height: 30px; + font-size: 1em; +} +.book.color-theme-1 .book-body { + color: #704214; + background: #f3eacb; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section { + background: #f3eacb; +} +.book.color-theme-2 .book-body { + color: #bdcadb; + background: #1c1f2b; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section { + background: #1c1f2b; +} +.book.font-size-0 .book-body .page-inner section { + font-size: 1.2rem; +} +.book.font-size-1 .book-body .page-inner section { + font-size: 1.4rem; +} +.book.font-size-2 .book-body .page-inner section { + font-size: 1.6rem; +} +.book.font-size-3 .book-body .page-inner section { + font-size: 2.2rem; +} +.book.font-size-4 .book-body .page-inner section { + font-size: 4rem; +} +.book.font-family-0 { + font-family: Georgia, serif; +} +.book.font-family-1 { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal { + color: #704214; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal a { + color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h3, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h4, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h5, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { + color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2 { + border-color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { + color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal hr { + background-color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal blockquote { + border-color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code { + background: #fdf6e3; + color: #657b83; + border-color: #f8df9c; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal .highlight { + background-color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table th, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table td { + border-color: #f5d06c; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr { + color: inherit; + background-color: #fdf6e3; + border-color: #444444; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { + background-color: #fbeecb; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal { + color: #bdcadb; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal a { + color: #3eb1d0; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h3, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h4, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h5, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { + color: #fffffa; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2 { + border-color: #373b4e; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { + color: #373b4e; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal hr { + background-color: #373b4e; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal blockquote { + border-color: #373b4e; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code { + color: #9dbed8; + background: #2d3143; + border-color: #2d3143; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal .highlight { + background-color: #282a39; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table th, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table td { + border-color: #3b3f54; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr { + color: #b6c2d2; + background-color: #2d3143; + border-color: #3b3f54; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { + background-color: #35394b; +} +.book.color-theme-1 .book-header { + color: #afa790; + background: transparent; +} +.book.color-theme-1 .book-header .btn { + color: #afa790; +} +.book.color-theme-1 .book-header .btn:hover { + color: #73553c; + background: none; +} +.book.color-theme-1 .book-header h1 { + color: #704214; +} +.book.color-theme-2 .book-header { + color: #7e888b; + background: transparent; +} +.book.color-theme-2 .book-header .btn { + color: #3b3f54; +} +.book.color-theme-2 .book-header .btn:hover { + color: #fffff5; + background: none; +} +.book.color-theme-2 .book-header h1 { + color: #bdcadb; +} +.book.color-theme-1 .book-body .navigation { + color: #afa790; +} +.book.color-theme-1 .book-body .navigation:hover { + color: #73553c; +} +.book.color-theme-2 .book-body .navigation { + color: #383f52; +} +.book.color-theme-2 .book-body .navigation:hover { + color: #fffff5; +} +/* + * Theme 1 + */ +.book.color-theme-1 .book-summary { + color: #afa790; + background: #111111; + border-right: 1px solid rgba(0, 0, 0, 0.07); +} +.book.color-theme-1 .book-summary .book-search { + background: transparent; +} +.book.color-theme-1 .book-summary .book-search input, +.book.color-theme-1 .book-summary .book-search input:focus { + border: 1px solid transparent; +} +.book.color-theme-1 .book-summary ul.summary li.divider { + background: #7e888b; + box-shadow: none; +} +.book.color-theme-1 .book-summary ul.summary li i.fa-check { + color: #33cc33; +} +.book.color-theme-1 .book-summary ul.summary li.done > a { + color: #877f6a; +} +.book.color-theme-1 .book-summary ul.summary li a, +.book.color-theme-1 .book-summary ul.summary li span { + color: #877f6a; + background: transparent; + font-weight: normal; +} +.book.color-theme-1 .book-summary ul.summary li.active > a, +.book.color-theme-1 .book-summary ul.summary li a:hover { + color: #704214; + background: transparent; + font-weight: normal; +} +/* + * Theme 2 + */ +.book.color-theme-2 .book-summary { + color: #bcc1d2; + background: #2d3143; + border-right: none; +} +.book.color-theme-2 .book-summary .book-search { + background: transparent; +} +.book.color-theme-2 .book-summary .book-search input, +.book.color-theme-2 .book-summary .book-search input:focus { + border: 1px solid transparent; +} +.book.color-theme-2 .book-summary ul.summary li.divider { + background: #272a3a; + box-shadow: none; +} +.book.color-theme-2 .book-summary ul.summary li i.fa-check { + color: #33cc33; +} +.book.color-theme-2 .book-summary ul.summary li.done > a { + color: #62687f; +} +.book.color-theme-2 .book-summary ul.summary li a, +.book.color-theme-2 .book-summary ul.summary li span { + color: #c1c6d7; + background: transparent; + font-weight: 600; +} +.book.color-theme-2 .book-summary ul.summary li.active > a, +.book.color-theme-2 .book-summary ul.summary li a:hover { + color: #f4f4f5; + background: #252737; + font-weight: 600; +} diff --git a/_book/gitbook/gitbook-plugin-highlight/ebook.css b/_book/gitbook/gitbook-plugin-highlight/ebook.css new file mode 100644 index 0000000000000000000000000000000000000000..cecaaab5a6e3bdbbbd531e8e5a9d2737a077eef9 --- /dev/null +++ b/_book/gitbook/gitbook-plugin-highlight/ebook.css @@ -0,0 +1,135 @@ +pre, +code { + /* http://jmblog.github.io/color-themes-for-highlightjs */ + /* Tomorrow Comment */ + /* Tomorrow Red */ + /* Tomorrow Orange */ + /* Tomorrow Yellow */ + /* Tomorrow Green */ + /* Tomorrow Aqua */ + /* Tomorrow Blue */ + /* Tomorrow Purple */ +} +pre .hljs-comment, +code .hljs-comment, +pre .hljs-title, +code .hljs-title { + color: #8e908c; +} +pre .hljs-variable, +code .hljs-variable, +pre .hljs-attribute, +code .hljs-attribute, +pre .hljs-tag, +code .hljs-tag, +pre .hljs-regexp, +code .hljs-regexp, +pre .hljs-deletion, +code .hljs-deletion, +pre .ruby .hljs-constant, +code .ruby .hljs-constant, +pre .xml .hljs-tag .hljs-title, +code .xml .hljs-tag .hljs-title, +pre .xml .hljs-pi, +code .xml .hljs-pi, +pre .xml .hljs-doctype, +code .xml .hljs-doctype, +pre .html .hljs-doctype, +code .html .hljs-doctype, +pre .css .hljs-id, +code .css .hljs-id, +pre .css .hljs-class, +code .css .hljs-class, +pre .css .hljs-pseudo, +code .css .hljs-pseudo { + color: #c82829; +} +pre .hljs-number, +code .hljs-number, +pre .hljs-preprocessor, +code .hljs-preprocessor, +pre .hljs-pragma, +code .hljs-pragma, +pre .hljs-built_in, +code .hljs-built_in, +pre .hljs-literal, +code .hljs-literal, +pre .hljs-params, +code .hljs-params, +pre .hljs-constant, +code .hljs-constant { + color: #f5871f; +} +pre .ruby .hljs-class .hljs-title, +code .ruby .hljs-class .hljs-title, +pre .css .hljs-rules .hljs-attribute, +code .css .hljs-rules .hljs-attribute { + color: #eab700; +} +pre .hljs-string, +code .hljs-string, +pre .hljs-value, +code .hljs-value, +pre .hljs-inheritance, +code .hljs-inheritance, +pre .hljs-header, +code .hljs-header, +pre .hljs-addition, +code .hljs-addition, +pre .ruby .hljs-symbol, +code .ruby .hljs-symbol, +pre .xml .hljs-cdata, +code .xml .hljs-cdata { + color: #718c00; +} +pre .css .hljs-hexcolor, +code .css .hljs-hexcolor { + color: #3e999f; +} +pre .hljs-function, +code .hljs-function, +pre .python .hljs-decorator, +code .python .hljs-decorator, +pre .python .hljs-title, +code .python .hljs-title, +pre .ruby .hljs-function .hljs-title, +code .ruby .hljs-function .hljs-title, +pre .ruby .hljs-title .hljs-keyword, +code .ruby .hljs-title .hljs-keyword, +pre .perl .hljs-sub, +code .perl .hljs-sub, +pre .javascript .hljs-title, +code .javascript .hljs-title, +pre .coffeescript .hljs-title, +code .coffeescript .hljs-title { + color: #4271ae; +} +pre .hljs-keyword, +code .hljs-keyword, +pre .javascript .hljs-function, +code .javascript .hljs-function { + color: #8959a8; +} +pre .hljs, +code .hljs { + display: block; + background: white; + color: #4d4d4c; + padding: 0.5em; +} +pre .coffeescript .javascript, +code .coffeescript .javascript, +pre .javascript .xml, +code .javascript .xml, +pre .tex .hljs-formula, +code .tex .hljs-formula, +pre .xml .javascript, +code .xml .javascript, +pre .xml .vbscript, +code .xml .vbscript, +pre .xml .css, +code .xml .css, +pre .xml .hljs-cdata, +code .xml .hljs-cdata { + opacity: 0.5; +} diff --git a/_book/gitbook/gitbook-plugin-highlight/website.css b/_book/gitbook/gitbook-plugin-highlight/website.css new file mode 100644 index 0000000000000000000000000000000000000000..6674448f7cadd76ce242d0253be6269394a10978 --- /dev/null +++ b/_book/gitbook/gitbook-plugin-highlight/website.css @@ -0,0 +1,434 @@ +.book .book-body .page-wrapper .page-inner section.normal pre, +.book .book-body .page-wrapper .page-inner section.normal code { + /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ + /* Tomorrow Comment */ + /* Tomorrow Red */ + /* Tomorrow Orange */ + /* Tomorrow Yellow */ + /* Tomorrow Green */ + /* Tomorrow Aqua */ + /* Tomorrow Blue */ + /* Tomorrow Purple */ +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-comment, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-title { + color: #8e908c; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-variable, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-tag, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-tag, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-deletion, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-deletion, +.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-constant, +.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-constant, +.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-tag .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-tag .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-pi, +.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-pi, +.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-doctype, +.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-doctype, +.book .book-body .page-wrapper .page-inner section.normal pre .html .hljs-doctype, +.book .book-body .page-wrapper .page-inner section.normal code .html .hljs-doctype, +.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-id, +.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-id, +.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-class, +.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-class, +.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo, +.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo { + color: #c82829; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-number, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-number, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-pragma, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-literal, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-literal, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-params, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-params, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-constant, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-constant { + color: #f5871f; +} +.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-class .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-class .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-rules .hljs-attribute, +.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-rules .hljs-attribute { + color: #eab700; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-string, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-string, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-value, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-value, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-inheritance, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-inheritance, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-header, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-header, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-addition, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-addition, +.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-symbol, +.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-symbol, +.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, +.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { + color: #718c00; +} +.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-hexcolor, +.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-hexcolor { + color: #3e999f; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-function, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-function, +.book .book-body .page-wrapper .page-inner section.normal pre .python .hljs-decorator, +.book .book-body .page-wrapper .page-inner section.normal code .python .hljs-decorator, +.book .book-body .page-wrapper .page-inner section.normal pre .python .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal code .python .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-function .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-function .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-title .hljs-keyword, +.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-title .hljs-keyword, +.book .book-body .page-wrapper .page-inner section.normal pre .perl .hljs-sub, +.book .book-body .page-wrapper .page-inner section.normal code .perl .hljs-sub, +.book .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal pre .coffeescript .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal code .coffeescript .hljs-title { + color: #4271ae; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, +.book .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-function, +.book .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-function { + color: #8959a8; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs, +.book .book-body .page-wrapper .page-inner section.normal code .hljs { + display: block; + background: white; + color: #4d4d4c; + padding: 0.5em; +} +.book .book-body .page-wrapper .page-inner section.normal pre .coffeescript .javascript, +.book .book-body .page-wrapper .page-inner section.normal code .coffeescript .javascript, +.book .book-body .page-wrapper .page-inner section.normal pre .javascript .xml, +.book .book-body .page-wrapper .page-inner section.normal code .javascript .xml, +.book .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, +.book .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula, +.book .book-body .page-wrapper .page-inner section.normal pre .xml .javascript, +.book .book-body .page-wrapper .page-inner section.normal code .xml .javascript, +.book .book-body .page-wrapper .page-inner section.normal pre .xml .vbscript, +.book .book-body .page-wrapper .page-inner section.normal code .xml .vbscript, +.book .book-body .page-wrapper .page-inner section.normal pre .xml .css, +.book .book-body .page-wrapper .page-inner section.normal code .xml .css, +.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, +.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { + opacity: 0.5; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code { + /* + +Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull + +*/ + /* Solarized Green */ + /* Solarized Cyan */ + /* Solarized Blue */ + /* Solarized Yellow */ + /* Solarized Orange */ + /* Solarized Red */ + /* Solarized Violet */ +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs { + display: block; + padding: 0.5em; + background: #fdf6e3; + color: #657b83; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-comment, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-template_comment, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-template_comment, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .diff .hljs-header, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .diff .hljs-header, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-doctype, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-doctype, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-pi, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-pi, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .lisp .hljs-string, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .lisp .hljs-string, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-javadoc, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-javadoc { + color: #93a1a1; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-winutils, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-winutils, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .method, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .method, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-addition, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-addition, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-tag, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-tag, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-request, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-request, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-status, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-status, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .nginx .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .nginx .hljs-title { + color: #859900; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-number, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-number, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-command, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-command, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-string, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-string, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-tag .hljs-value, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-tag .hljs-value, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-rules .hljs-value, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-rules .hljs-value, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-phpdoc, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-phpdoc, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-hexcolor, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-hexcolor, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_url, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_url { + color: #2aa198; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-localvars, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-localvars, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-chunk, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-chunk, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-decorator, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-decorator, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-identifier, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-identifier, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .vhdl .hljs-literal, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .vhdl .hljs-literal, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-id, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-id, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-function, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-function { + color: #268bd2; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-variable, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .lisp .hljs-body, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .lisp .hljs-body, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .smalltalk .hljs-number, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .smalltalk .hljs-number, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-constant, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-constant, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-class .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-class .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-parent, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-parent, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .haskell .hljs-type, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .haskell .hljs-type, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_reference, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_reference { + color: #b58900; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor .hljs-keyword, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor .hljs-keyword, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-pragma, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-shebang, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-shebang, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-symbol, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol .hljs-string, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-symbol .hljs-string, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .diff .hljs-change, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .diff .hljs-change, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-special, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-special, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-attr_selector, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-attr_selector, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-subst, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-subst, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-cdata, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-cdata, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .clojure .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .clojure .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-header, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-header { + color: #cb4b16; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-deletion, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-deletion, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-important, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-important { + color: #dc322f; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_label, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_label { + color: #6c71c4; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula { + background: #eee8d5; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code { + /* Tomorrow Night Bright Theme */ + /* Original theme - https://github.com/chriskempson/tomorrow-theme */ + /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ + /* Tomorrow Comment */ + /* Tomorrow Red */ + /* Tomorrow Orange */ + /* Tomorrow Yellow */ + /* Tomorrow Green */ + /* Tomorrow Aqua */ + /* Tomorrow Blue */ + /* Tomorrow Purple */ +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-comment, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-title { + color: #969896; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-variable, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-tag, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-tag, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-deletion, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-deletion, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-constant, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-constant, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-tag .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-tag .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-pi, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-pi, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-doctype, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-doctype, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .html .hljs-doctype, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .html .hljs-doctype, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-id, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-id, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-class, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-class, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo { + color: #d54e53; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-number, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-number, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-pragma, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-literal, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-literal, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-params, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-params, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-constant, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-constant { + color: #e78c45; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-class .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-class .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-rules .hljs-attribute, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-rules .hljs-attribute { + color: #e7c547; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-string, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-string, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-value, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-value, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-inheritance, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-inheritance, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-header, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-header, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-addition, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-addition, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-symbol, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-symbol, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { + color: #b9ca4a; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-hexcolor, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-hexcolor { + color: #70c0b1; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-function, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-function, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .python .hljs-decorator, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .python .hljs-decorator, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .python .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .python .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-function .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-function .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-title .hljs-keyword, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-title .hljs-keyword, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .perl .hljs-sub, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .perl .hljs-sub, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .coffeescript .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .coffeescript .hljs-title { + color: #7aa6da; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-function, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-function { + color: #c397d8; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs { + display: block; + background: black; + color: #eaeaea; + padding: 0.5em; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .coffeescript .javascript, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .coffeescript .javascript, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .xml, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .xml, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .javascript, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .javascript, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .vbscript, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .vbscript, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .css, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .css, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { + opacity: 0.5; +} diff --git a/_book/gitbook/gitbook-plugin-livereload/plugin.js b/_book/gitbook/gitbook-plugin-livereload/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..923b3aed5ccf50313d40ecfcf700fcaf615c4e8b --- /dev/null +++ b/_book/gitbook/gitbook-plugin-livereload/plugin.js @@ -0,0 +1,11 @@ +(function() { + var newEl = document.createElement('script'), + firstScriptTag = document.getElementsByTagName('script')[0]; + + if (firstScriptTag) { + newEl.async = 1; + newEl.src = '//' + window.location.hostname + ':35729/livereload.js'; + firstScriptTag.parentNode.insertBefore(newEl, firstScriptTag); + } + +})(); diff --git a/_book/gitbook/gitbook-plugin-lunr/lunr.min.js b/_book/gitbook/gitbook-plugin-lunr/lunr.min.js new file mode 100644 index 0000000000000000000000000000000000000000..6aa6bc7d69cf8ff165a544f87b4af73aed9bdf64 --- /dev/null +++ b/_book/gitbook/gitbook-plugin-lunr/lunr.min.js @@ -0,0 +1,7 @@ +/** + * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 0.5.12 + * Copyright (C) 2015 Oliver Nightingale + * MIT Licensed + * @license + */ +!function(){var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.5.12",t.utils={},t.utils.warn=function(t){return function(e){t.console&&console.warn&&console.warn(e)}}(this),t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var t=Array.prototype.slice.call(arguments),e=t.pop(),n=t;if("function"!=typeof e)throw new TypeError("last argument must be a function");n.forEach(function(t){this.hasHandler(t)||(this.events[t]=[]),this.events[t].push(e)},this)},t.EventEmitter.prototype.removeListener=function(t,e){if(this.hasHandler(t)){var n=this.events[t].indexOf(e);this.events[t].splice(n,1),this.events[t].length||delete this.events[t]}},t.EventEmitter.prototype.emit=function(t){if(this.hasHandler(t)){var e=Array.prototype.slice.call(arguments,1);this.events[t].forEach(function(t){t.apply(void 0,e)})}},t.EventEmitter.prototype.hasHandler=function(t){return t in this.events},t.tokenizer=function(t){return arguments.length&&null!=t&&void 0!=t?Array.isArray(t)?t.map(function(t){return t.toLowerCase()}):t.toString().trim().toLowerCase().split(/[\s\-]+/):[]},t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.registeredFunctions[e];if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(e);if(-1==i)throw new Error("Cannot find existingFn");i+=1,this._stack.splice(i,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(e);if(-1==i)throw new Error("Cannot find existingFn");this._stack.splice(i,0,n)},t.Pipeline.prototype.remove=function(t){var e=this._stack.indexOf(t);-1!=e&&this._stack.splice(e,1)},t.Pipeline.prototype.run=function(t){for(var e=[],n=t.length,i=this._stack.length,o=0;n>o;o++){for(var r=t[o],s=0;i>s&&(r=this._stack[s](r,o,t),void 0!==r);s++);void 0!==r&&e.push(r)}return e},t.Pipeline.prototype.reset=function(){this._stack=[]},t.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Vector=function(){this._magnitude=null,this.list=void 0,this.length=0},t.Vector.Node=function(t,e,n){this.idx=t,this.val=e,this.next=n},t.Vector.prototype.insert=function(e,n){this._magnitude=void 0;var i=this.list;if(!i)return this.list=new t.Vector.Node(e,n,i),this.length++;if(en.idx?n=n.next:(i+=e.val*n.val,e=e.next,n=n.next);return i},t.Vector.prototype.similarity=function(t){return this.dot(t)/(this.magnitude()*t.magnitude())},t.SortedSet=function(){this.length=0,this.elements=[]},t.SortedSet.load=function(t){var e=new this;return e.elements=t,e.length=t.length,e},t.SortedSet.prototype.add=function(){var t,e;for(t=0;t1;){if(r===t)return o;t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o]}return r===t?o:-1},t.SortedSet.prototype.locationFor=function(t){for(var e=0,n=this.elements.length,i=n-e,o=e+Math.floor(i/2),r=this.elements[o];i>1;)t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o];return r>t?o:t>r?o+1:void 0},t.SortedSet.prototype.intersect=function(e){for(var n=new t.SortedSet,i=0,o=0,r=this.length,s=e.length,a=this.elements,h=e.elements;;){if(i>r-1||o>s-1)break;a[i]!==h[o]?a[i]h[o]&&o++:(n.add(a[i]),i++,o++)}return n},t.SortedSet.prototype.clone=function(){var e=new t.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},t.SortedSet.prototype.union=function(t){var e,n,i;return this.length>=t.length?(e=this,n=t):(e=t,n=this),i=e.clone(),i.add.apply(i,n.toArray()),i},t.SortedSet.prototype.toJSON=function(){return this.toArray()},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.Store,this.tokenStore=new t.TokenStore,this.corpusTokens=new t.SortedSet,this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var t=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,t)},t.Index.prototype.off=function(t,e){return this.eventEmitter.removeListener(t,e)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;return n._fields=e.fields,n._ref=e.ref,n.documentStore=t.Store.load(e.documentStore),n.tokenStore=t.TokenStore.load(e.tokenStore),n.corpusTokens=t.SortedSet.load(e.corpusTokens),n.pipeline=t.Pipeline.load(e.pipeline),n},t.Index.prototype.field=function(t,e){var e=e||{},n={name:t,boost:e.boost||1};return this._fields.push(n),this},t.Index.prototype.ref=function(t){return this._ref=t,this},t.Index.prototype.add=function(e,n){var i={},o=new t.SortedSet,r=e[this._ref],n=void 0===n?!0:n;this._fields.forEach(function(n){var r=this.pipeline.run(t.tokenizer(e[n.name]));i[n.name]=r,t.SortedSet.prototype.add.apply(o,r)},this),this.documentStore.set(r,o),t.SortedSet.prototype.add.apply(this.corpusTokens,o.toArray());for(var s=0;s0&&(i=1+Math.log(this.documentStore.length/n)),this._idfCache[e]=i},t.Index.prototype.search=function(e){var n=this.pipeline.run(t.tokenizer(e)),i=new t.Vector,o=[],r=this._fields.reduce(function(t,e){return t+e.boost},0),s=n.some(function(t){return this.tokenStore.has(t)},this);if(!s)return[];n.forEach(function(e,n,s){var a=1/s.length*this._fields.length*r,h=this,l=this.tokenStore.expand(e).reduce(function(n,o){var r=h.corpusTokens.indexOf(o),s=h.idf(o),l=1,u=new t.SortedSet;if(o!==e){var c=Math.max(3,o.length-e.length);l=1/Math.log(c)}return r>-1&&i.insert(r,a*s*l),Object.keys(h.tokenStore.get(o)).forEach(function(t){u.add(t)}),n.union(u)},new t.SortedSet);o.push(l)},this);var a=o.reduce(function(t,e){return t.intersect(e)});return a.map(function(t){return{ref:t,score:i.similarity(this.documentVector(t))}},this).sort(function(t,e){return e.score-t.score})},t.Index.prototype.documentVector=function(e){for(var n=this.documentStore.get(e),i=n.length,o=new t.Vector,r=0;i>r;r++){var s=n.elements[r],a=this.tokenStore.get(s)[e].tf,h=this.idf(s);o.insert(this.corpusTokens.indexOf(s),a*h)}return o},t.Index.prototype.toJSON=function(){return{version:t.version,fields:this._fields,ref:this._ref,documentStore:this.documentStore.toJSON(),tokenStore:this.tokenStore.toJSON(),corpusTokens:this.corpusTokens.toJSON(),pipeline:this.pipeline.toJSON()}},t.Index.prototype.use=function(t){var e=Array.prototype.slice.call(arguments,1);e.unshift(this),t.apply(this,e)},t.Store=function(){this.store={},this.length=0},t.Store.load=function(e){var n=new this;return n.length=e.length,n.store=Object.keys(e.store).reduce(function(n,i){return n[i]=t.SortedSet.load(e.store[i]),n},{}),n},t.Store.prototype.set=function(t,e){this.has(t)||this.length++,this.store[t]=e},t.Store.prototype.get=function(t){return this.store[t]},t.Store.prototype.has=function(t){return t in this.store},t.Store.prototype.remove=function(t){this.has(t)&&(delete this.store[t],this.length--)},t.Store.prototype.toJSON=function(){return{store:this.store,length:this.length}},t.stemmer=function(){var t={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},e={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",o=n+"[^aeiouy]*",r=i+"[aeiou]*",s="^("+o+")?"+r+o,a="^("+o+")?"+r+o+"("+r+")?$",h="^("+o+")?"+r+o+r+o,l="^("+o+")?"+i,u=new RegExp(s),c=new RegExp(h),f=new RegExp(a),d=new RegExp(l),p=/^(.+?)(ss|i)es$/,m=/^(.+?)([^s])s$/,v=/^(.+?)eed$/,y=/^(.+?)(ed|ing)$/,g=/.$/,S=/(at|bl|iz)$/,w=new RegExp("([^aeiouylsz])\\1$"),x=new RegExp("^"+o+i+"[^aeiouwxy]$"),k=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,E=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,_=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,F=/^(.+?)(s|t)(ion)$/,O=/^(.+?)e$/,P=/ll$/,N=new RegExp("^"+o+i+"[^aeiouwxy]$"),T=function(n){var i,o,r,s,a,h,l;if(n.length<3)return n;if(r=n.substr(0,1),"y"==r&&(n=r.toUpperCase()+n.substr(1)),s=p,a=m,s.test(n)?n=n.replace(s,"$1$2"):a.test(n)&&(n=n.replace(a,"$1$2")),s=v,a=y,s.test(n)){var T=s.exec(n);s=u,s.test(T[1])&&(s=g,n=n.replace(s,""))}else if(a.test(n)){var T=a.exec(n);i=T[1],a=d,a.test(i)&&(n=i,a=S,h=w,l=x,a.test(n)?n+="e":h.test(n)?(s=g,n=n.replace(s,"")):l.test(n)&&(n+="e"))}if(s=k,s.test(n)){var T=s.exec(n);i=T[1],n=i+"i"}if(s=b,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+t[o])}if(s=E,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+e[o])}if(s=_,a=F,s.test(n)){var T=s.exec(n);i=T[1],s=c,s.test(i)&&(n=i)}else if(a.test(n)){var T=a.exec(n);i=T[1]+T[2],a=c,a.test(i)&&(n=i)}if(s=O,s.test(n)){var T=s.exec(n);i=T[1],s=c,a=f,h=N,(s.test(i)||a.test(i)&&!h.test(i))&&(n=i)}return s=P,a=c,s.test(n)&&a.test(n)&&(s=g,n=n.replace(s,"")),"y"==r&&(n=r.toLowerCase()+n.substr(1)),n};return T}(),t.Pipeline.registerFunction(t.stemmer,"stemmer"),t.stopWordFilter=function(e){return e&&t.stopWordFilter.stopWords[e]!==e?e:void 0},t.stopWordFilter.stopWords={a:"a",able:"able",about:"about",across:"across",after:"after",all:"all",almost:"almost",also:"also",am:"am",among:"among",an:"an",and:"and",any:"any",are:"are",as:"as",at:"at",be:"be",because:"because",been:"been",but:"but",by:"by",can:"can",cannot:"cannot",could:"could",dear:"dear",did:"did","do":"do",does:"does",either:"either","else":"else",ever:"ever",every:"every","for":"for",from:"from",get:"get",got:"got",had:"had",has:"has",have:"have",he:"he",her:"her",hers:"hers",him:"him",his:"his",how:"how",however:"however",i:"i","if":"if","in":"in",into:"into",is:"is",it:"it",its:"its",just:"just",least:"least",let:"let",like:"like",likely:"likely",may:"may",me:"me",might:"might",most:"most",must:"must",my:"my",neither:"neither",no:"no",nor:"nor",not:"not",of:"of",off:"off",often:"often",on:"on",only:"only",or:"or",other:"other",our:"our",own:"own",rather:"rather",said:"said",say:"say",says:"says",she:"she",should:"should",since:"since",so:"so",some:"some",than:"than",that:"that",the:"the",their:"their",them:"them",then:"then",there:"there",these:"these",they:"they","this":"this",tis:"tis",to:"to",too:"too",twas:"twas",us:"us",wants:"wants",was:"was",we:"we",were:"were",what:"what",when:"when",where:"where",which:"which","while":"while",who:"who",whom:"whom",why:"why",will:"will","with":"with",would:"would",yet:"yet",you:"you",your:"your"},t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter"),t.trimmer=function(t){var e=t.replace(/^\W+/,"").replace(/\W+$/,"");return""===e?void 0:e},t.Pipeline.registerFunction(t.trimmer,"trimmer"),t.TokenStore=function(){this.root={docs:{}},this.length=0},t.TokenStore.load=function(t){var e=new this;return e.root=t.root,e.length=t.length,e},t.TokenStore.prototype.add=function(t,e,n){var n=n||this.root,i=t[0],o=t.slice(1);return i in n||(n[i]={docs:{}}),0===o.length?(n[i].docs[e.ref]=e,void(this.length+=1)):this.add(o,e,n[i])},t.TokenStore.prototype.has=function(t){if(!t)return!1;for(var e=this.root,n=0;no;o++){for(var r=t[o],s=0;i>s&&(r=this._stack[s](r,o,t),void 0!==r);s++);void 0!==r&&e.push(r)}return e},t.Pipeline.prototype.reset=function(){this._stack=[]},t.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Vector=function(){this._magnitude=null,this.list=void 0,this.length=0},t.Vector.Node=function(t,e,n){this.idx=t,this.val=e,this.next=n},t.Vector.prototype.insert=function(e,n){this._magnitude=void 0;var i=this.list;if(!i)return this.list=new t.Vector.Node(e,n,i),this.length++;if(en.idx?n=n.next:(i+=e.val*n.val,e=e.next,n=n.next);return i},t.Vector.prototype.similarity=function(t){return this.dot(t)/(this.magnitude()*t.magnitude())},t.SortedSet=function(){this.length=0,this.elements=[]},t.SortedSet.load=function(t){var e=new this;return e.elements=t,e.length=t.length,e},t.SortedSet.prototype.add=function(){var t,e;for(t=0;t1;){if(r===t)return o;t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o]}return r===t?o:-1},t.SortedSet.prototype.locationFor=function(t){for(var e=0,n=this.elements.length,i=n-e,o=e+Math.floor(i/2),r=this.elements[o];i>1;)t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o];return r>t?o:t>r?o+1:void 0},t.SortedSet.prototype.intersect=function(e){for(var n=new t.SortedSet,i=0,o=0,r=this.length,s=e.length,a=this.elements,h=e.elements;;){if(i>r-1||o>s-1)break;a[i]!==h[o]?a[i]h[o]&&o++:(n.add(a[i]),i++,o++)}return n},t.SortedSet.prototype.clone=function(){var e=new t.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},t.SortedSet.prototype.union=function(t){var e,n,i;return this.length>=t.length?(e=this,n=t):(e=t,n=this),i=e.clone(),i.add.apply(i,n.toArray()),i},t.SortedSet.prototype.toJSON=function(){return this.toArray()},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.Store,this.tokenStore=new t.TokenStore,this.corpusTokens=new t.SortedSet,this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var t=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,t)},t.Index.prototype.off=function(t,e){return this.eventEmitter.removeListener(t,e)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;return n._fields=e.fields,n._ref=e.ref,n.documentStore=t.Store.load(e.documentStore),n.tokenStore=t.TokenStore.load(e.tokenStore),n.corpusTokens=t.SortedSet.load(e.corpusTokens),n.pipeline=t.Pipeline.load(e.pipeline),n},t.Index.prototype.field=function(t,e){var e=e||{},n={name:t,boost:e.boost||1};return this._fields.push(n),this},t.Index.prototype.ref=function(t){return this._ref=t,this},t.Index.prototype.add=function(e,n){var i={},o=new t.SortedSet,r=e[this._ref],n=void 0===n?!0:n;this._fields.forEach(function(n){var r=this.pipeline.run(t.tokenizer(e[n.name]));i[n.name]=r,t.SortedSet.prototype.add.apply(o,r)},this),this.documentStore.set(r,o),t.SortedSet.prototype.add.apply(this.corpusTokens,o.toArray());for(var s=0;s0&&(i=1+Math.log(this.documentStore.length/n)),this._idfCache[e]=i},t.Index.prototype.search=function(e){var n=this.pipeline.run(t.tokenizer(e)),i=new t.Vector,o=[],r=this._fields.reduce(function(t,e){return t+e.boost},0),s=n.some(function(t){return this.tokenStore.has(t)},this);if(!s)return[];n.forEach(function(e,n,s){var a=1/s.length*this._fields.length*r,h=this,l=this.tokenStore.expand(e).reduce(function(n,o){var r=h.corpusTokens.indexOf(o),s=h.idf(o),l=1,u=new t.SortedSet;if(o!==e){var c=Math.max(3,o.length-e.length);l=1/Math.log(c)}return r>-1&&i.insert(r,a*s*l),Object.keys(h.tokenStore.get(o)).forEach(function(t){u.add(t)}),n.union(u)},new t.SortedSet);o.push(l)},this);var a=o.reduce(function(t,e){return t.intersect(e)});return a.map(function(t){return{ref:t,score:i.similarity(this.documentVector(t))}},this).sort(function(t,e){return e.score-t.score})},t.Index.prototype.documentVector=function(e){for(var n=this.documentStore.get(e),i=n.length,o=new t.Vector,r=0;i>r;r++){var s=n.elements[r],a=this.tokenStore.get(s)[e].tf,h=this.idf(s);o.insert(this.corpusTokens.indexOf(s),a*h)}return o},t.Index.prototype.toJSON=function(){return{version:t.version,fields:this._fields,ref:this._ref,documentStore:this.documentStore.toJSON(),tokenStore:this.tokenStore.toJSON(),corpusTokens:this.corpusTokens.toJSON(),pipeline:this.pipeline.toJSON()}},t.Index.prototype.use=function(t){var e=Array.prototype.slice.call(arguments,1);e.unshift(this),t.apply(this,e)},t.Store=function(){this.store={},this.length=0},t.Store.load=function(e){var n=new this;return n.length=e.length,n.store=Object.keys(e.store).reduce(function(n,i){return n[i]=t.SortedSet.load(e.store[i]),n},{}),n},t.Store.prototype.set=function(t,e){this.has(t)||this.length++,this.store[t]=e},t.Store.prototype.get=function(t){return this.store[t]},t.Store.prototype.has=function(t){return t in this.store},t.Store.prototype.remove=function(t){this.has(t)&&(delete this.store[t],this.length--)},t.Store.prototype.toJSON=function(){return{store:this.store,length:this.length}},t.stemmer=function(){var t={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},e={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",o=n+"[^aeiouy]*",r=i+"[aeiou]*",s="^("+o+")?"+r+o,a="^("+o+")?"+r+o+"("+r+")?$",h="^("+o+")?"+r+o+r+o,l="^("+o+")?"+i,u=new RegExp(s),c=new RegExp(h),f=new RegExp(a),d=new RegExp(l),p=/^(.+?)(ss|i)es$/,m=/^(.+?)([^s])s$/,v=/^(.+?)eed$/,y=/^(.+?)(ed|ing)$/,g=/.$/,S=/(at|bl|iz)$/,w=new RegExp("([^aeiouylsz])\\1$"),x=new RegExp("^"+o+i+"[^aeiouwxy]$"),k=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,E=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,_=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,F=/^(.+?)(s|t)(ion)$/,O=/^(.+?)e$/,P=/ll$/,N=new RegExp("^"+o+i+"[^aeiouwxy]$"),T=function(n){var i,o,r,s,a,h,l;if(n.length<3)return n;if(r=n.substr(0,1),"y"==r&&(n=r.toUpperCase()+n.substr(1)),s=p,a=m,s.test(n)?n=n.replace(s,"$1$2"):a.test(n)&&(n=n.replace(a,"$1$2")),s=v,a=y,s.test(n)){var T=s.exec(n);s=u,s.test(T[1])&&(s=g,n=n.replace(s,""))}else if(a.test(n)){var T=a.exec(n);i=T[1],a=d,a.test(i)&&(n=i,a=S,h=w,l=x,a.test(n)?n+="e":h.test(n)?(s=g,n=n.replace(s,"")):l.test(n)&&(n+="e"))}if(s=k,s.test(n)){var T=s.exec(n);i=T[1],n=i+"i"}if(s=b,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+t[o])}if(s=E,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+e[o])}if(s=_,a=F,s.test(n)){var T=s.exec(n);i=T[1],s=c,s.test(i)&&(n=i)}else if(a.test(n)){var T=a.exec(n);i=T[1]+T[2],a=c,a.test(i)&&(n=i)}if(s=O,s.test(n)){var T=s.exec(n);i=T[1],s=c,a=f,h=N,(s.test(i)||a.test(i)&&!h.test(i))&&(n=i)}return s=P,a=c,s.test(n)&&a.test(n)&&(s=g,n=n.replace(s,"")),"y"==r&&(n=r.toLowerCase()+n.substr(1)),n};return T}(),t.Pipeline.registerFunction(t.stemmer,"stemmer"),t.stopWordFilter=function(e){return e&&t.stopWordFilter.stopWords[e]!==e?e:void 0},t.stopWordFilter.stopWords={a:"a",able:"able",about:"about",across:"across",after:"after",all:"all",almost:"almost",also:"also",am:"am",among:"among",an:"an",and:"and",any:"any",are:"are",as:"as",at:"at",be:"be",because:"because",been:"been",but:"but",by:"by",can:"can",cannot:"cannot",could:"could",dear:"dear",did:"did","do":"do",does:"does",either:"either","else":"else",ever:"ever",every:"every","for":"for",from:"from",get:"get",got:"got",had:"had",has:"has",have:"have",he:"he",her:"her",hers:"hers",him:"him",his:"his",how:"how",however:"however",i:"i","if":"if","in":"in",into:"into",is:"is",it:"it",its:"its",just:"just",least:"least",let:"let",like:"like",likely:"likely",may:"may",me:"me",might:"might",most:"most",must:"must",my:"my",neither:"neither",no:"no",nor:"nor",not:"not",of:"of",off:"off",often:"often",on:"on",only:"only",or:"or",other:"other",our:"our",own:"own",rather:"rather",said:"said",say:"say",says:"says",she:"she",should:"should",since:"since",so:"so",some:"some",than:"than",that:"that",the:"the",their:"their",them:"them",then:"then",there:"there",these:"these",they:"they","this":"this",tis:"tis",to:"to",too:"too",twas:"twas",us:"us",wants:"wants",was:"was",we:"we",were:"were",what:"what",when:"when",where:"where",which:"which","while":"while",who:"who",whom:"whom",why:"why",will:"will","with":"with",would:"would",yet:"yet",you:"you",your:"your"},t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter"),t.trimmer=function(t){var e=t.replace(/^\W+/,"").replace(/\W+$/,"");return""===e?void 0:e},t.Pipeline.registerFunction(t.trimmer,"trimmer"),t.TokenStore=function(){this.root={docs:{}},this.length=0},t.TokenStore.load=function(t){var e=new this;return e.root=t.root,e.length=t.length,e},t.TokenStore.prototype.add=function(t,e,n){var n=n||this.root,i=t[0],o=t.slice(1);return i in n||(n[i]={docs:{}}),0===o.length?(n[i].docs[e.ref]=e,void(this.length+=1)):this.add(o,e,n[i])},t.TokenStore.prototype.has=function(t){if(!t)return!1;for(var e=this.root,n=0;n element for each result + res.results.forEach(function(res) { + var $li = $('
  • ', { + 'class': 'search-results-item' + }); + + var $title = $('

    '); + + var $link = $('', { + 'href': gitbook.state.basePath + '/' + res.url, + 'text': res.title + }); + + var content = res.body.trim(); + if (content.length > MAX_DESCRIPTION_SIZE) { + content = content.slice(0, MAX_DESCRIPTION_SIZE).trim()+'...'; + } + var $content = $('

    ').html(content); + + $link.appendTo($title); + $title.appendTo($li); + $content.appendTo($li); + $li.appendTo($searchList); + }); + } + + function launchSearch(q) { + // Add class for loading + $body.addClass('with-search'); + $body.addClass('search-loading'); + + // Launch search query + throttle(gitbook.search.query(q, 0, MAX_RESULTS) + .then(function(results) { + displayResults(results); + }) + .always(function() { + $body.removeClass('search-loading'); + }), 1000); + } + + function closeSearch() { + $body.removeClass('with-search'); + $bookSearchResults.removeClass('open'); + } + + function launchSearchFromQueryString() { + var q = getParameterByName('q'); + if (q && q.length > 0) { + // Update search input + $searchInput.val(q); + + // Launch search + launchSearch(q); + } + } + + function bindSearch() { + // Bind DOM + $searchInput = $('#book-search-input input'); + $bookSearchResults = $('#book-search-results'); + $searchList = $bookSearchResults.find('.search-results-list'); + $searchTitle = $bookSearchResults.find('.search-results-title'); + $searchResultsCount = $searchTitle.find('.search-results-count'); + $searchQuery = $searchTitle.find('.search-query'); + + // Launch query based on input content + function handleUpdate() { + var q = $searchInput.val(); + + if (q.length == 0) { + closeSearch(); + } + else { + launchSearch(q); + } + } + + // Detect true content change in search input + // Workaround for IE < 9 + var propertyChangeUnbound = false; + $searchInput.on('propertychange', function(e) { + if (e.originalEvent.propertyName == 'value') { + handleUpdate(); + } + }); + + // HTML5 (IE9 & others) + $searchInput.on('input', function(e) { + // Unbind propertychange event for IE9+ + if (!propertyChangeUnbound) { + $(this).unbind('propertychange'); + propertyChangeUnbound = true; + } + + handleUpdate(); + }); + + // Push to history on blur + $searchInput.on('blur', function(e) { + // Update history state + if (usePushState) { + var uri = updateQueryString('q', $(this).val()); + history.pushState({ path: uri }, null, uri); + } + }); + } + + gitbook.events.on('page.change', function() { + bindSearch(); + closeSearch(); + + // Launch search based on query parameter + if (gitbook.search.isInitialized()) { + launchSearchFromQueryString(); + } + }); + + gitbook.events.on('search.ready', function() { + bindSearch(); + + // Launch search from query param at start + launchSearchFromQueryString(); + }); + + function getParameterByName(name) { + var url = window.location.href; + name = name.replace(/[\[\]]/g, '\\$&'); + var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)', 'i'), + results = regex.exec(url); + if (!results) return null; + if (!results[2]) return ''; + return decodeURIComponent(results[2].replace(/\+/g, ' ')); + } + + function updateQueryString(key, value) { + value = encodeURIComponent(value); + + var url = window.location.href; + var re = new RegExp('([?&])' + key + '=.*?(&|#|$)(.*)', 'gi'), + hash; + + if (re.test(url)) { + if (typeof value !== 'undefined' && value !== null) + return url.replace(re, '$1' + key + '=' + value + '$2$3'); + else { + hash = url.split('#'); + url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, ''); + if (typeof hash[1] !== 'undefined' && hash[1] !== null) + url += '#' + hash[1]; + return url; + } + } + else { + if (typeof value !== 'undefined' && value !== null) { + var separator = url.indexOf('?') !== -1 ? '&' : '?'; + hash = url.split('#'); + url = hash[0] + separator + key + '=' + value; + if (typeof hash[1] !== 'undefined' && hash[1] !== null) + url += '#' + hash[1]; + return url; + } + else + return url; + } + } +}); diff --git a/_book/gitbook/gitbook-plugin-sharing/buttons.js b/_book/gitbook/gitbook-plugin-sharing/buttons.js new file mode 100644 index 0000000000000000000000000000000000000000..709a4e4c023c775e048b9afd7ca4ba9abd215601 --- /dev/null +++ b/_book/gitbook/gitbook-plugin-sharing/buttons.js @@ -0,0 +1,90 @@ +require(['gitbook', 'jquery'], function(gitbook, $) { + var SITES = { + 'facebook': { + 'label': 'Facebook', + 'icon': 'fa fa-facebook', + 'onClick': function(e) { + e.preventDefault(); + window.open('http://www.facebook.com/sharer/sharer.php?s=100&p[url]='+encodeURIComponent(location.href)); + } + }, + 'twitter': { + 'label': 'Twitter', + 'icon': 'fa fa-twitter', + 'onClick': function(e) { + e.preventDefault(); + window.open('http://twitter.com/home?status='+encodeURIComponent(document.title+' '+location.href)); + } + }, + 'google': { + 'label': 'Google+', + 'icon': 'fa fa-google-plus', + 'onClick': function(e) { + e.preventDefault(); + window.open('https://plus.google.com/share?url='+encodeURIComponent(location.href)); + } + }, + 'weibo': { + 'label': 'Weibo', + 'icon': 'fa fa-weibo', + 'onClick': function(e) { + e.preventDefault(); + window.open('http://service.weibo.com/share/share.php?content=utf-8&url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)); + } + }, + 'instapaper': { + 'label': 'Instapaper', + 'icon': 'fa fa-instapaper', + 'onClick': function(e) { + e.preventDefault(); + window.open('http://www.instapaper.com/text?u='+encodeURIComponent(location.href)); + } + }, + 'vk': { + 'label': 'VK', + 'icon': 'fa fa-vk', + 'onClick': function(e) { + e.preventDefault(); + window.open('http://vkontakte.ru/share.php?url='+encodeURIComponent(location.href)); + } + } + }; + + + + gitbook.events.bind('start', function(e, config) { + var opts = config.sharing; + + // Create dropdown menu + var menu = $.map(opts.all, function(id) { + var site = SITES[id]; + + return { + text: site.label, + onClick: site.onClick + }; + }); + + // Create main button with dropdown + if (menu.length > 0) { + gitbook.toolbar.createButton({ + icon: 'fa fa-share-alt', + label: 'Share', + position: 'right', + dropdown: [menu] + }); + } + + // Direct actions to share + $.each(SITES, function(sideId, site) { + if (!opts[sideId]) return; + + gitbook.toolbar.createButton({ + icon: site.icon, + label: site.text, + position: 'right', + onClick: site.onClick + }); + }); + }); +}); diff --git a/_book/gitbook/gitbook-plugin-theme-fexa/fexa.css b/_book/gitbook/gitbook-plugin-theme-fexa/fexa.css new file mode 100644 index 0000000000000000000000000000000000000000..5c8731b8775949c215f908f38efad825e987f185 --- /dev/null +++ b/_book/gitbook/gitbook-plugin-theme-fexa/fexa.css @@ -0,0 +1,224 @@ +body { + font-family: "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei", "\9ED1\4F53", Arial, sans-serif; + letter-spacing: .2px; + text-rendering: optimizeLegibility; +} +.markdown-section h1, +.markdown-section h2, +.markdown-section h3, +.markdown-section h4, +.markdown-section h5, +.markdown-section h6 { + margin-bottom: .5em; + font-weight: 400; +} +.markdown-section p { + line-height: 2; +} +.markdown-section img { + padding: 8px; + background: #e4e4e478; + transition: all 1s; + box-sizing: border-box; + box-shadow: 0 0 4px #dcdcdc; + margin-left: 10px; + margin-right: 10px; + max-width: 95%; +} +.markdown-section img:hover { + box-shadow: 0 0 10px #bbb +} + +.exc-trigger { + color: #333333; +} + +.navigation { + display: none; +} + +/*Book inner page*/ + +.book-summary-title { + height: 50px; + line-height: 50px; + padding-left: 30px; + font-size: 16px; + color: #adadad; +} + +.book-summary, +.book-body { + top: 80px; +} + +.book-summary ul.summary li.active { + border-right: 3px solid #f34d4d; + background: #f3f1f1; +} + +.book-summary ul.summary li.active>a { + color: #f34d4d; + text-decoration: none; +} + +.book-summary ul.summary li a:hover { + text-decoration: none; +} + +.page-inner { + max-width: none; + padding: 20px 270px 40px 40px; +} + +.header-inner #book-search-input { + float: right; + width: 300px; + margin: 10px 0; + padding: 0; + border: none; + background: #f34d4d; + user-select: none; +} + +.header-inner #book-search-input input[type="text"] { + width: 80%; + background: #e4e4e4; +} + +.header-inner #book-search-input #searchBtn { + color: #ffffff; + margin-left: 10px; + cursor: pointer; +} + +.header-inner #book-search-input #searchBtn:hover { + color: #eae8e8; +} + +.header-inner { + width: 100%; + padding: 10px 30px; + border-bottom: 1px solid #dededede; + margin: auto; + *zoom: 1; + height: 80px; +} + +.header-inner:before, +.header-inner:after { + content: " "; + display: table; + line-height: 0; +} + +.header-inner:after { + clear: both; +} + +.header-inner .logo { + float: left; + height: 50px; + width: 120px; + background: url('./logo.png'); + background-size: 120px 50px; + background-repeat: no-repeat; +} + +.header-inner .logo img { + display: block; + height: inherit; + padding: 5px 0; +} + +.header-inner .title { + float: left; + font-size: 20px; + line-height: 60px; + margin-left: 10px; + color: #575656; +} + +/* 导航 */ +.header-inner .header-nav { + list-style: none; + margin: 10px 20px 0 0; + padding: 0; + float: right; + display: table; +} + +.header-inner .header-nav li { + display: table-cell; + vertical-align: middle; + min-width: 50px; + margin-right: 20px; + padding: 8px 10px 8px 10px; +} + +.header-inner .header-nav li a { + color: #333333; +} + +.header-inner .header-nav li a:hover, +.header-inner .header-nav li a.active { + color: #f34d4d; +} + +.header-inner .header-nav li a.active:hover { + cursor: #f34d4d; +} + +@media (max-width: 768px) { + .book-summary, + .book-body { + top: 101px; + } + .header-inner #book-search-input { + clear: both; + width: 100%; + } +} +/*Book inner page end*/ + +/* Book anchor*/ +.book-anchor { + width: 180px; + position: absolute; + top: 130px; + right: 30px; + padding: 0 10px 10px 10px; + z-index: 999; + user-select: none; + border-left: 2px solid #ececec; +} +.book-anchor-title { + line-height: 38px; + font-weight: 400; + cursor: pointer; +} +.book-anchor a { + display: block; + line-height: 25px; + color: #656565; + font-size: 13px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.book-anchor a:hover { + color: #f34d4d; + text-decoration: none; +} +.book-anchor .selected { + color: #f34d4d; + text-decoration: none; + font-weight: bold; +} +.book-anchor .anchor-h1 {} +.book-anchor .anchor-h2 { + padding-left: 20px; +} +.book-anchor .anchor-h3{ + padding-left: 30px; +} \ No newline at end of file diff --git a/_book/gitbook/gitbook-plugin-theme-fexa/fexa.js b/_book/gitbook/gitbook-plugin-theme-fexa/fexa.js new file mode 100644 index 0000000000000000000000000000000000000000..85a20cb26ff031b3e3885fb90b6e2dfbdbe0ab2e --- /dev/null +++ b/_book/gitbook/gitbook-plugin-theme-fexa/fexa.js @@ -0,0 +1,74 @@ +require(['gitbook', 'jquery'], function(gitbook, $) { + + function getRootPath() { + var pathName = window.location.pathname.substring(1); + var webName = pathName == '' ? '' : pathName.substring(0, pathName.indexOf('/')); + if (webName == "") { + return window.location.protocol + '//' + window.location.host; + } + else { + return window.location.protocol + '//' + window.location.host + '/' + webName; + } + } + + //生成内容导航 + function generateSectionNavigator(){ + $(".page-inner .markdown-section").find("h1,h2,h3").each(function(){ + var cls="anchor-h1"; + if($(this).is("h2")){ + cls="anchor-h2"; + } + if($(this).is("h3")){ + cls="anchor-h3"; + } + var text = $(this).text(); + var href = $(this).attr("id"); + $(".book-anchor-body").append(""+text+"") + }); + + $(".book-anchor-title").click(function () { + // $(".book-anchor-body").toggle(); + }); + + $(".book-anchor-body>a").click(function(){ + $(".book-anchor-body>a").removeClass("selected"); + $(this).addClass("selected"); + }); + + //获取hash值定向到指定位置 + var hash = decodeURIComponent(location.hash); + if(hash){ + hash = hash.substring(1); + $("#an_"+hash).addClass("selected"); + } + + } + + //基础设置 + function setBase(){ + //标题 + var $title = $(".header-inner .title"); + $title.text(gitbook.state.config.title); + + //搜索框 + var $search = $('#book-search-input'); + var placeholder = gitbook.state.config.pluginsConfig["theme-fexa"]["search-placeholder"] || "输入关键字搜索" + $search.find("input").attr("placeholder",placeholder); + $search.append("搜索"); + $search.focus(); + $("#searchBtn").click(function(e){}); + + //去掉gitbook-link + $(".summary .gitbook-link").hide(); + $(".summary .divider").hide(); + } + + gitbook.events.on('start', function() { + + }); + + gitbook.events.on('page.change', function() { + setBase(); + generateSectionNavigator(); + }); +}); diff --git a/_book/gitbook/gitbook-plugin-theme-fexa/logo.png b/_book/gitbook/gitbook-plugin-theme-fexa/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8ef04aca0f633c9a1c7075681ef1db4b8e03c7f9 Binary files /dev/null and b/_book/gitbook/gitbook-plugin-theme-fexa/logo.png differ diff --git a/_book/gitbook/gitbook.js b/_book/gitbook/gitbook.js new file mode 100644 index 0000000000000000000000000000000000000000..10000c790bdc164ce9a2c76434443a72f130f9af --- /dev/null +++ b/_book/gitbook/gitbook.js @@ -0,0 +1,4 @@ +!function e(t,n,r){function o(s,a){if(!n[s]){if(!t[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[s]={exports:{}};t[s][0].call(l.exports,function(e){var n=t[s][1][e];return o(n?n:e)},l,l.exports,e,t,n,r)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;s0&&t-1 in e)}function o(e,t,n){return de.isFunction(t)?de.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?de.grep(e,function(e){return e===t!==n}):"string"!=typeof t?de.grep(e,function(e){return se.call(t,e)>-1!==n}):je.test(t)?de.filter(t,e,n):(t=de.filter(t,e),de.grep(e,function(e){return se.call(t,e)>-1!==n&&1===e.nodeType}))}function i(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}function s(e){var t={};return de.each(e.match(qe)||[],function(e,n){t[n]=!0}),t}function a(e){return e}function u(e){throw e}function c(e,t,n){var r;try{e&&de.isFunction(r=e.promise)?r.call(e).done(t).fail(n):e&&de.isFunction(r=e.then)?r.call(e,t,n):t.call(void 0,e)}catch(e){n.call(void 0,e)}}function l(){te.removeEventListener("DOMContentLoaded",l),e.removeEventListener("load",l),de.ready()}function f(){this.expando=de.expando+f.uid++}function p(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:Ie.test(e)?JSON.parse(e):e)}function h(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Pe,"-$&").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n=p(n)}catch(e){}Re.set(e,t,n)}else n=void 0;return n}function d(e,t,n,r){var o,i=1,s=20,a=r?function(){return r.cur()}:function(){return de.css(e,t,"")},u=a(),c=n&&n[3]||(de.cssNumber[t]?"":"px"),l=(de.cssNumber[t]||"px"!==c&&+u)&&$e.exec(de.css(e,t));if(l&&l[3]!==c){c=c||l[3],n=n||[],l=+u||1;do i=i||".5",l/=i,de.style(e,t,l+c);while(i!==(i=a()/u)&&1!==i&&--s)}return n&&(l=+l||+u||0,o=n[1]?l+(n[1]+1)*n[2]:+n[2],r&&(r.unit=c,r.start=l,r.end=o)),o}function g(e){var t,n=e.ownerDocument,r=e.nodeName,o=Ue[r];return o?o:(t=n.body.appendChild(n.createElement(r)),o=de.css(t,"display"),t.parentNode.removeChild(t),"none"===o&&(o="block"),Ue[r]=o,o)}function m(e,t){for(var n,r,o=[],i=0,s=e.length;i-1)o&&o.push(i);else if(c=de.contains(i.ownerDocument,i),s=v(f.appendChild(i),"script"),c&&y(s),n)for(l=0;i=s[l++];)Ve.test(i.type||"")&&n.push(i);return f}function b(){return!0}function w(){return!1}function T(){try{return te.activeElement}catch(e){}}function C(e,t,n,r,o,i){var s,a;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(a in t)C(e,a,n,r,t[a],i);return e}if(null==r&&null==o?(o=n,r=n=void 0):null==o&&("string"==typeof n?(o=r,r=void 0):(o=r,r=n,n=void 0)),o===!1)o=w;else if(!o)return e;return 1===i&&(s=o,o=function(e){return de().off(e),s.apply(this,arguments)},o.guid=s.guid||(s.guid=de.guid++)),e.each(function(){de.event.add(this,t,o,r,n)})}function j(e,t){return de.nodeName(e,"table")&&de.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e:e}function k(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function E(e){var t=rt.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function S(e,t){var n,r,o,i,s,a,u,c;if(1===t.nodeType){if(Fe.hasData(e)&&(i=Fe.access(e),s=Fe.set(t,i),c=i.events)){delete s.handle,s.events={};for(o in c)for(n=0,r=c[o].length;n1&&"string"==typeof d&&!pe.checkClone&&nt.test(d))return e.each(function(n){var i=e.eq(n);g&&(t[0]=d.call(this,n,i.html())),A(i,t,r,o)});if(p&&(i=x(t,e[0].ownerDocument,!1,e,o),s=i.firstChild,1===i.childNodes.length&&(i=s),s||o)){for(a=de.map(v(i,"script"),k),u=a.length;f=0&&nC.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[$]=!0,e}function o(e){var t=L.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function i(e,t){for(var n=e.split("|"),r=n.length;r--;)C.attrHandle[n[r]]=t}function s(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function a(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function c(e){return function(t){return"form"in t?t.parentNode&&t.disabled===!1?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&je(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var o,i=e([],n.length,t),s=i.length;s--;)n[o=i[s]]&&(n[o]=!(r[o]=n[o]))})})}function f(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function p(){}function h(e){for(var t=0,n=e.length,r="";t1?function(t,n,r){for(var o=e.length;o--;)if(!e[o](t,n,r))return!1;return!0}:e[0]}function m(e,n,r){for(var o=0,i=n.length;o-1&&(r[c]=!(s[c]=f))}}else x=v(x===s?x.splice(d,x.length):x),i?i(null,s,x,u):K.apply(s,x)})}function x(e){for(var t,n,r,o=e.length,i=C.relative[e[0].type],s=i||C.relative[" "],a=i?1:0,u=d(function(e){return e===t},s,!0),c=d(function(e){return ee(t,e)>-1},s,!0),l=[function(e,n,r){var o=!i&&(r||n!==A)||((t=n).nodeType?u(e,n,r):c(e,n,r));return t=null,o}];a1&&g(l),a>1&&h(e.slice(0,a-1).concat({value:" "===e[a-2].type?"*":""})).replace(ae,"$1"),n,a0,i=e.length>0,s=function(r,s,a,u,c){var l,f,p,h=0,d="0",g=r&&[],m=[],y=A,x=r||i&&C.find.TAG("*",c),b=B+=null==y?1:Math.random()||.1,w=x.length;for(c&&(A=s===L||s||c);d!==w&&null!=(l=x[d]);d++){if(i&&l){for(f=0,s||l.ownerDocument===L||(O(l),a=!F);p=e[f++];)if(p(l,s||L,a)){u.push(l);break}c&&(B=b)}o&&((l=!p&&l)&&h--,r&&g.push(l))}if(h+=d,o&&d!==h){for(f=0;p=n[f++];)p(g,m,s,a);if(r){if(h>0)for(;d--;)g[d]||m[d]||(m[d]=Q.call(u));m=v(m)}K.apply(u,m),c&&!r&&m.length>0&&h+n.length>1&&t.uniqueSort(u)}return c&&(B=b,A=y),g};return o?r(s):s}var w,T,C,j,k,E,S,N,A,q,D,O,L,H,F,R,I,P,M,$="sizzle"+1*new Date,W=e.document,B=0,_=0,U=n(),z=n(),X=n(),V=function(e,t){return e===t&&(D=!0),0},G={}.hasOwnProperty,Y=[],Q=Y.pop,J=Y.push,K=Y.push,Z=Y.slice,ee=function(e,t){for(var n=0,r=e.length;n+~]|"+ne+")"+ne+"*"),le=new RegExp("="+ne+"*([^\\]'\"]*?)"+ne+"*\\]","g"),fe=new RegExp(ie),pe=new RegExp("^"+re+"$"),he={ID:new RegExp("^#("+re+")"),CLASS:new RegExp("^\\.("+re+")"),TAG:new RegExp("^("+re+"|[*])"),ATTR:new RegExp("^"+oe),PSEUDO:new RegExp("^"+ie),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ne+"*(even|odd|(([+-]|)(\\d*)n|)"+ne+"*(?:([+-]|)"+ne+"*(\\d+)|))"+ne+"*\\)|)","i"),bool:new RegExp("^(?:"+te+")$","i"),needsContext:new RegExp("^"+ne+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ne+"*((?:-\\d)?\\d*)"+ne+"*\\)|)(?=[^-]|$)","i")},de=/^(?:input|select|textarea|button)$/i,ge=/^h\d$/i,me=/^[^{]+\{\s*\[native \w/,ve=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ye=/[+~]/,xe=new RegExp("\\\\([\\da-f]{1,6}"+ne+"?|("+ne+")|.)","ig"),be=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},we=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,Te=function(e,t){return t?"\0"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},Ce=function(){O()},je=d(function(e){return e.disabled===!0&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{K.apply(Y=Z.call(W.childNodes),W.childNodes),Y[W.childNodes.length].nodeType}catch(e){K={apply:Y.length?function(e,t){J.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}T=t.support={},k=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},O=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:W;return r!==L&&9===r.nodeType&&r.documentElement?(L=r,H=L.documentElement,F=!k(L),W!==L&&(n=L.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",Ce,!1):n.attachEvent&&n.attachEvent("onunload",Ce)),T.attributes=o(function(e){return e.className="i",!e.getAttribute("className")}),T.getElementsByTagName=o(function(e){return e.appendChild(L.createComment("")),!e.getElementsByTagName("*").length}),T.getElementsByClassName=me.test(L.getElementsByClassName),T.getById=o(function(e){return H.appendChild(e).id=$,!L.getElementsByName||!L.getElementsByName($).length}),T.getById?(C.filter.ID=function(e){var t=e.replace(xe,be);return function(e){return e.getAttribute("id")===t}},C.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&F){var n=t.getElementById(e);return n?[n]:[]}}):(C.filter.ID=function(e){var t=e.replace(xe,be);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},C.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&F){var n,r,o,i=t.getElementById(e);if(i){if(n=i.getAttributeNode("id"),n&&n.value===e)return[i];for(o=t.getElementsByName(e),r=0;i=o[r++];)if(n=i.getAttributeNode("id"),n&&n.value===e)return[i]}return[]}}),C.find.TAG=T.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):T.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],o=0,i=t.getElementsByTagName(e);if("*"===e){for(;n=i[o++];)1===n.nodeType&&r.push(n);return r}return i},C.find.CLASS=T.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&F)return t.getElementsByClassName(e)},I=[],R=[],(T.qsa=me.test(L.querySelectorAll))&&(o(function(e){H.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&R.push("[*^$]="+ne+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||R.push("\\["+ne+"*(?:value|"+te+")"),e.querySelectorAll("[id~="+$+"-]").length||R.push("~="),e.querySelectorAll(":checked").length||R.push(":checked"),e.querySelectorAll("a#"+$+"+*").length||R.push(".#.+[+~]")}),o(function(e){e.innerHTML="";var t=L.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&R.push("name"+ne+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&R.push(":enabled",":disabled"),H.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&R.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),R.push(",.*:")})),(T.matchesSelector=me.test(P=H.matches||H.webkitMatchesSelector||H.mozMatchesSelector||H.oMatchesSelector||H.msMatchesSelector))&&o(function(e){T.disconnectedMatch=P.call(e,"*"),P.call(e,"[s!='']:x"),I.push("!=",ie)}),R=R.length&&new RegExp(R.join("|")),I=I.length&&new RegExp(I.join("|")),t=me.test(H.compareDocumentPosition),M=t||me.test(H.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},V=t?function(e,t){if(e===t)return D=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!T.sortDetached&&t.compareDocumentPosition(e)===n?e===L||e.ownerDocument===W&&M(W,e)?-1:t===L||t.ownerDocument===W&&M(W,t)?1:q?ee(q,e)-ee(q,t):0:4&n?-1:1)}:function(e,t){if(e===t)return D=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],u=[t];if(!o||!i)return e===L?-1:t===L?1:o?-1:i?1:q?ee(q,e)-ee(q,t):0;if(o===i)return s(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;a[r]===u[r];)r++;return r?s(a[r],u[r]):a[r]===W?-1:u[r]===W?1:0},L):L},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==L&&O(e),n=n.replace(le,"='$1']"),T.matchesSelector&&F&&!X[n+" "]&&(!I||!I.test(n))&&(!R||!R.test(n)))try{var r=P.call(e,n);if(r||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return t(n,L,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==L&&O(e),M(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==L&&O(e);var n=C.attrHandle[t.toLowerCase()],r=n&&G.call(C.attrHandle,t.toLowerCase())?n(e,t,!F):void 0;return void 0!==r?r:T.attributes||!F?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.escape=function(e){return(e+"").replace(we,Te)},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,n=[],r=0,o=0;if(D=!T.detectDuplicates,q=!T.sortStable&&e.slice(0),e.sort(V),D){for(;t=e[o++];)t===e[o]&&(r=n.push(o));for(;r--;)e.splice(n[r],1)}return q=null,e},j=t.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=j(e)}else if(3===o||4===o)return e.nodeValue}else for(;t=e[r++];)n+=j(t);return n},C=t.selectors={cacheLength:50,createPseudo:r,match:he,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(xe,be),e[3]=(e[3]||e[4]||e[5]||"").replace(xe,be),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return he.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&fe.test(n)&&(t=E(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(xe,be).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=U[e+" "];return t||(t=new RegExp("(^|"+ne+")"+e+"("+ne+"|$)"))&&U(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,n,r){return function(o){var i=t.attr(o,e);return null==i?"!="===n:!n||(i+="","="===n?i===r:"!="===n?i!==r:"^="===n?r&&0===i.indexOf(r):"*="===n?r&&i.indexOf(r)>-1:"$="===n?r&&i.slice(-r.length)===r:"~="===n?(" "+i.replace(se," ")+" ").indexOf(r)>-1:"|="===n&&(i===r||i.slice(0,r.length+1)===r+"-"))}},CHILD:function(e,t,n,r,o){var i="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===o?function(e){return!!e.parentNode}:function(t,n,u){var c,l,f,p,h,d,g=i!==s?"nextSibling":"previousSibling",m=t.parentNode,v=a&&t.nodeName.toLowerCase(),y=!u&&!a,x=!1;if(m){if(i){for(;g;){for(p=t;p=p[g];)if(a?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&y){for(p=m,f=p[$]||(p[$]={}),l=f[p.uniqueID]||(f[p.uniqueID]={}),c=l[e]||[],h=c[0]===B&&c[1],x=h&&c[2],p=h&&m.childNodes[h];p=++h&&p&&p[g]||(x=h=0)||d.pop();)if(1===p.nodeType&&++x&&p===t){l[e]=[B,h,x];break}}else if(y&&(p=t,f=p[$]||(p[$]={}),l=f[p.uniqueID]||(f[p.uniqueID]={}),c=l[e]||[],h=c[0]===B&&c[1],x=h),x===!1)for(;(p=++h&&p&&p[g]||(x=h=0)||d.pop())&&((a?p.nodeName.toLowerCase()!==v:1!==p.nodeType)||!++x||(y&&(f=p[$]||(p[$]={}),l=f[p.uniqueID]||(f[p.uniqueID]={}),l[e]=[B,x]),p!==t)););return x-=o,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var o,i=C.pseudos[e]||C.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return i[$]?i(n):i.length>1?(o=[e,e,"",n],C.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,o=i(e,n),s=o.length;s--;)r=ee(e,o[s]),e[r]=!(t[r]=o[s])}):function(e){return i(e,0,o)}):i}},pseudos:{not:r(function(e){var t=[],n=[],o=S(e.replace(ae,"$1"));return o[$]?r(function(e,t,n,r){for(var i,s=o(e,null,r,[]),a=e.length;a--;)(i=s[a])&&(e[a]=!(t[a]=i))}):function(e,r,i){return t[0]=e,o(t,null,i,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){ +return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(xe,be),function(t){return(t.textContent||t.innerText||j(t)).indexOf(e)>-1}}),lang:r(function(e){return pe.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(xe,be).toLowerCase(),function(t){var n;do if(n=F?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===H},focus:function(e){return e===L.activeElement&&(!L.hasFocus||L.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:c(!1),disabled:c(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!C.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return de.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r2&&"ID"===(s=i[0]).type&&9===t.nodeType&&F&&C.relative[i[1].type]){if(t=(C.find.ID(s.matches[0].replace(xe,be),t)||[])[0],!t)return n;c&&(t=t.parentNode),e=e.slice(i.shift().value.length)}for(o=he.needsContext.test(e)?0:i.length;o--&&(s=i[o],!C.relative[a=s.type]);)if((u=C.find[a])&&(r=u(s.matches[0].replace(xe,be),ye.test(i[0].type)&&f(t.parentNode)||t))){if(i.splice(o,1),e=r.length&&h(i),!e)return K.apply(n,r),n;break}}return(c||S(e,l))(r,t,!F,n,!t||ye.test(e)&&f(t.parentNode)||t),n},T.sortStable=$.split("").sort(V).join("")===$,T.detectDuplicates=!!D,O(),T.sortDetached=o(function(e){return 1&e.compareDocumentPosition(L.createElement("fieldset"))}),o(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||i("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),T.attributes&&o(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||i("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),o(function(e){return null==e.getAttribute("disabled")})||i(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);de.find=xe,de.expr=xe.selectors,de.expr[":"]=de.expr.pseudos,de.uniqueSort=de.unique=xe.uniqueSort,de.text=xe.getText,de.isXMLDoc=xe.isXML,de.contains=xe.contains,de.escapeSelector=xe.escape;var be=function(e,t,n){for(var r=[],o=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(o&&de(e).is(n))break;r.push(e)}return r},we=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},Te=de.expr.match.needsContext,Ce=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,je=/^.[^:#\[\.,]*$/;de.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?de.find.matchesSelector(r,e)?[r]:[]:de.find.matches(e,de.grep(t,function(e){return 1===e.nodeType}))},de.fn.extend({find:function(e){var t,n,r=this.length,o=this;if("string"!=typeof e)return this.pushStack(de(e).filter(function(){for(t=0;t1?de.uniqueSort(n):n},filter:function(e){return this.pushStack(o(this,e||[],!1))},not:function(e){return this.pushStack(o(this,e||[],!0))},is:function(e){return!!o(this,"string"==typeof e&&Te.test(e)?de(e):e||[],!1).length}});var ke,Ee=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,Se=de.fn.init=function(e,t,n){var r,o;if(!e)return this;if(n=n||ke,"string"==typeof e){if(r="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:Ee.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof de?t[0]:t,de.merge(this,de.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:te,!0)),Ce.test(r[1])&&de.isPlainObject(t))for(r in t)de.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return o=te.getElementById(r[2]),o&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):de.isFunction(e)?void 0!==n.ready?n.ready(e):e(de):de.makeArray(e,this)};Se.prototype=de.fn,ke=de(te);var Ne=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};de.fn.extend({has:function(e){var t=de(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&de.find.matchesSelector(n,e))){i.push(n);break}return this.pushStack(i.length>1?de.uniqueSort(i):i)},index:function(e){return e?"string"==typeof e?se.call(de(e),this[0]):se.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(de.uniqueSort(de.merge(this.get(),de(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),de.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return be(e,"parentNode")},parentsUntil:function(e,t,n){return be(e,"parentNode",n)},next:function(e){return i(e,"nextSibling")},prev:function(e){return i(e,"previousSibling")},nextAll:function(e){return be(e,"nextSibling")},prevAll:function(e){return be(e,"previousSibling")},nextUntil:function(e,t,n){return be(e,"nextSibling",n)},prevUntil:function(e,t,n){return be(e,"previousSibling",n)},siblings:function(e){return we((e.parentNode||{}).firstChild,e)},children:function(e){return we(e.firstChild)},contents:function(e){return e.contentDocument||de.merge([],e.childNodes)}},function(e,t){de.fn[e]=function(n,r){var o=de.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(o=de.filter(r,o)),this.length>1&&(Ae[e]||de.uniqueSort(o),Ne.test(e)&&o.reverse()),this.pushStack(o)}});var qe=/[^\x20\t\r\n\f]+/g;de.Callbacks=function(e){e="string"==typeof e?s(e):de.extend({},e);var t,n,r,o,i=[],a=[],u=-1,c=function(){for(o=e.once,r=t=!0;a.length;u=-1)for(n=a.shift();++u-1;)i.splice(n,1),n<=u&&u--}),this},has:function(e){return e?de.inArray(e,i)>-1:i.length>0},empty:function(){return i&&(i=[]),this},disable:function(){return o=a=[],i=n="",this},disabled:function(){return!i},lock:function(){return o=a=[],n||t||(i=n=""),this},locked:function(){return!!o},fireWith:function(e,n){return o||(n=n||[],n=[e,n.slice?n.slice():n],a.push(n),t||c()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l},de.extend({Deferred:function(t){var n=[["notify","progress",de.Callbacks("memory"),de.Callbacks("memory"),2],["resolve","done",de.Callbacks("once memory"),de.Callbacks("once memory"),0,"resolved"],["reject","fail",de.Callbacks("once memory"),de.Callbacks("once memory"),1,"rejected"]],r="pending",o={state:function(){return r},always:function(){return i.done(arguments).fail(arguments),this},catch:function(e){return o.then(null,e)},pipe:function(){var e=arguments;return de.Deferred(function(t){de.each(n,function(n,r){var o=de.isFunction(e[r[4]])&&e[r[4]];i[r[1]](function(){var e=o&&o.apply(this,arguments);e&&de.isFunction(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,o?[e]:arguments)})}),e=null}).promise()},then:function(t,r,o){function i(t,n,r,o){return function(){var c=this,l=arguments,f=function(){var e,f;if(!(t=s&&(r!==u&&(c=void 0,l=[e]),n.rejectWith(c,l))}};t?p():(de.Deferred.getStackHook&&(p.stackTrace=de.Deferred.getStackHook()),e.setTimeout(p))}}var s=0;return de.Deferred(function(e){n[0][3].add(i(0,e,de.isFunction(o)?o:a,e.notifyWith)),n[1][3].add(i(0,e,de.isFunction(t)?t:a)),n[2][3].add(i(0,e,de.isFunction(r)?r:u))}).promise()},promise:function(e){return null!=e?de.extend(e,o):o}},i={};return de.each(n,function(e,t){var s=t[2],a=t[5];o[t[1]]=s.add,a&&s.add(function(){r=a},n[3-e][2].disable,n[0][2].lock),s.add(t[3].fire),i[t[0]]=function(){return i[t[0]+"With"](this===i?void 0:this,arguments),this},i[t[0]+"With"]=s.fireWith}),o.promise(i),t&&t.call(i,i),i},when:function(e){var t=arguments.length,n=t,r=Array(n),o=re.call(arguments),i=de.Deferred(),s=function(e){return function(n){r[e]=this,o[e]=arguments.length>1?re.call(arguments):n,--t||i.resolveWith(r,o)}};if(t<=1&&(c(e,i.done(s(n)).resolve,i.reject),"pending"===i.state()||de.isFunction(o[n]&&o[n].then)))return i.then();for(;n--;)c(o[n],s(n),i.reject);return i.promise()}});var De=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;de.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&De.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},de.readyException=function(t){e.setTimeout(function(){throw t})};var Oe=de.Deferred();de.fn.ready=function(e){return Oe.then(e).catch(function(e){de.readyException(e)}),this},de.extend({isReady:!1,readyWait:1,holdReady:function(e){e?de.readyWait++:de.ready(!0)},ready:function(e){(e===!0?--de.readyWait:de.isReady)||(de.isReady=!0,e!==!0&&--de.readyWait>0||Oe.resolveWith(te,[de]))}}),de.ready.then=Oe.then,"complete"===te.readyState||"loading"!==te.readyState&&!te.documentElement.doScroll?e.setTimeout(de.ready):(te.addEventListener("DOMContentLoaded",l),e.addEventListener("load",l));var Le=function(e,t,n,r,o,i,s){var a=0,u=e.length,c=null==n;if("object"===de.type(n)){o=!0;for(a in n)Le(e,t,a,n[a],!0,i,s)}else if(void 0!==r&&(o=!0,de.isFunction(r)||(s=!0),c&&(s?(t.call(e,r),t=null):(c=t,t=function(e,t,n){return c.call(de(e),n)})),t))for(;a1,null,!0)},removeData:function(e){return this.each(function(){Re.remove(this,e)})}}),de.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Fe.get(e,t),n&&(!r||de.isArray(n)?r=Fe.access(e,t,de.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=de.queue(e,t),r=n.length,o=n.shift(),i=de._queueHooks(e,t),s=function(){de.dequeue(e,t)};"inprogress"===o&&(o=n.shift(),r--),o&&("fx"===t&&n.unshift("inprogress"),delete i.stop,o.call(e,s,i)),!r&&i&&i.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Fe.get(e,n)||Fe.access(e,n,{empty:de.Callbacks("once memory").add(function(){Fe.remove(e,[t+"queue",n])})})}}),de.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]+)/i,Ve=/^$|\/(?:java|ecma)script/i,Ge={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};Ge.optgroup=Ge.option,Ge.tbody=Ge.tfoot=Ge.colgroup=Ge.caption=Ge.thead,Ge.th=Ge.td;var Ye=/<|&#?\w+;/;!function(){var e=te.createDocumentFragment(),t=e.appendChild(te.createElement("div")),n=te.createElement("input");n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),t.appendChild(n),pe.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,t.innerHTML="",pe.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue}();var Qe=te.documentElement,Je=/^key/,Ke=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ze=/^([^.]*)(?:\.(.+)|)/;de.event={global:{},add:function(e,t,n,r,o){var i,s,a,u,c,l,f,p,h,d,g,m=Fe.get(e);if(m)for(n.handler&&(i=n,n=i.handler,o=i.selector),o&&de.find.matchesSelector(Qe,o),n.guid||(n.guid=de.guid++),(u=m.events)||(u=m.events={}),(s=m.handle)||(s=m.handle=function(t){return"undefined"!=typeof de&&de.event.triggered!==t.type?de.event.dispatch.apply(e,arguments):void 0}),t=(t||"").match(qe)||[""],c=t.length;c--;)a=Ze.exec(t[c])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h&&(f=de.event.special[h]||{},h=(o?f.delegateType:f.bindType)||h,f=de.event.special[h]||{},l=de.extend({type:h,origType:g,data:r,handler:n,guid:n.guid,selector:o,needsContext:o&&de.expr.match.needsContext.test(o),namespace:d.join(".")},i),(p=u[h])||(p=u[h]=[],p.delegateCount=0,f.setup&&f.setup.call(e,r,d,s)!==!1||e.addEventListener&&e.addEventListener(h,s)),f.add&&(f.add.call(e,l),l.handler.guid||(l.handler.guid=n.guid)),o?p.splice(p.delegateCount++,0,l):p.push(l),de.event.global[h]=!0)},remove:function(e,t,n,r,o){var i,s,a,u,c,l,f,p,h,d,g,m=Fe.hasData(e)&&Fe.get(e);if(m&&(u=m.events)){for(t=(t||"").match(qe)||[""],c=t.length;c--;)if(a=Ze.exec(t[c])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){for(f=de.event.special[h]||{},h=(r?f.delegateType:f.bindType)||h,p=u[h]||[],a=a[2]&&new RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=i=p.length;i--;)l=p[i],!o&&g!==l.origType||n&&n.guid!==l.guid||a&&!a.test(l.namespace)||r&&r!==l.selector&&("**"!==r||!l.selector)||(p.splice(i,1),l.selector&&p.delegateCount--,f.remove&&f.remove.call(e,l));s&&!p.length&&(f.teardown&&f.teardown.call(e,d,m.handle)!==!1||de.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)de.event.remove(e,h+t[c],n,r,!0);de.isEmptyObject(u)&&Fe.remove(e,"handle events")}},dispatch:function(e){var t,n,r,o,i,s,a=de.event.fix(e),u=new Array(arguments.length),c=(Fe.get(this,"events")||{})[a.type]||[],l=de.event.special[a.type]||{};for(u[0]=a,t=1;t=1))for(;c!==this;c=c.parentNode||this)if(1===c.nodeType&&("click"!==e.type||c.disabled!==!0)){for(i=[],s={},n=0;n-1:de.find(o,this,null,[c]).length),s[o]&&i.push(r);i.length&&a.push({elem:c,handlers:i})}return c=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,tt=/\s*$/g;de.extend({htmlPrefilter:function(e){return e.replace(et,"<$1>")},clone:function(e,t,n){var r,o,i,s,a=e.cloneNode(!0),u=de.contains(e.ownerDocument,e);if(!(pe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||de.isXMLDoc(e)))for(s=v(a),i=v(e),r=0,o=i.length;r0&&y(s,!u&&v(e,"script")),a},cleanData:function(e){for(var t,n,r,o=de.event.special,i=0;void 0!==(n=e[i]);i++)if(He(n)){if(t=n[Fe.expando]){if(t.events)for(r in t.events)o[r]?de.event.remove(n,r):de.removeEvent(n,r,t.handle);n[Fe.expando]=void 0}n[Re.expando]&&(n[Re.expando]=void 0)}}}),de.fn.extend({detach:function(e){return q(this,e,!0)},remove:function(e){return q(this,e)},text:function(e){return Le(this,function(e){return void 0===e?de.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return A(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=j(this,e);t.appendChild(e)}})},prepend:function(){return A(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=j(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return A(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return A(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(de.cleanData(v(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return de.clone(this,e,t)})},html:function(e){return Le(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!tt.test(e)&&!Ge[(Xe.exec(e)||["",""])[1].toLowerCase()]){e=de.htmlPrefilter(e);try{for(;n1)}}),de.Tween=I,I.prototype={constructor:I,init:function(e,t,n,r,o,i){this.elem=e,this.prop=n,this.easing=o||de.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=i||(de.cssNumber[n]?"":"px")},cur:function(){var e=I.propHooks[this.prop];return e&&e.get?e.get(this):I.propHooks._default.get(this)},run:function(e){var t,n=I.propHooks[this.prop];return this.options.duration?this.pos=t=de.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):I.propHooks._default.set(this),this}},I.prototype.init.prototype=I.prototype,I.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=de.css(e.elem,e.prop,""),t&&"auto"!==t?t:0)},set:function(e){de.fx.step[e.prop]?de.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[de.cssProps[e.prop]]&&!de.cssHooks[e.prop]?e.elem[e.prop]=e.now:de.style(e.elem,e.prop,e.now+e.unit)}}},I.propHooks.scrollTop=I.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},de.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},de.fx=I.prototype.init,de.fx.step={};var ht,dt,gt=/^(?:toggle|show|hide)$/,mt=/queueHooks$/;de.Animation=de.extend(U,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return d(n.elem,e,$e.exec(t),n),n}]},tweener:function(e,t){de.isFunction(e)?(t=e,e=["*"]):e=e.match(qe);for(var n,r=0,o=e.length;r1)},removeAttr:function(e){return this.each(function(){de.removeAttr(this,e)})}}),de.extend({attr:function(e,t,n){var r,o,i=e.nodeType;if(3!==i&&8!==i&&2!==i)return"undefined"==typeof e.getAttribute?de.prop(e,t,n):(1===i&&de.isXMLDoc(e)||(o=de.attrHooks[t.toLowerCase()]||(de.expr.match.bool.test(t)?vt:void 0)),void 0!==n?null===n?void de.removeAttr(e,t):o&&"set"in o&&void 0!==(r=o.set(e,n,t))?r:(e.setAttribute(t,n+""),n):o&&"get"in o&&null!==(r=o.get(e,t))?r:(r=de.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!pe.radioValue&&"radio"===t&&de.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,o=t&&t.match(qe);if(o&&1===e.nodeType)for(;n=o[r++];)e.removeAttribute(n)}}),vt={set:function(e,t,n){return t===!1?de.removeAttr(e,n):e.setAttribute(n,n),n}},de.each(de.expr.match.bool.source.match(/\w+/g),function(e,t){var n=yt[t]||de.find.attr;yt[t]=function(e,t,r){var o,i,s=t.toLowerCase();return r||(i=yt[s],yt[s]=o,o=null!=n(e,t,r)?s:null,yt[s]=i),o}});var xt=/^(?:input|select|textarea|button)$/i,bt=/^(?:a|area)$/i;de.fn.extend({prop:function(e,t){return Le(this,de.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[de.propFix[e]||e]})}}),de.extend({prop:function(e,t,n){var r,o,i=e.nodeType;if(3!==i&&8!==i&&2!==i)return 1===i&&de.isXMLDoc(e)||(t=de.propFix[t]||t,o=de.propHooks[t]),void 0!==n?o&&"set"in o&&void 0!==(r=o.set(e,n,t))?r:e[t]=n:o&&"get"in o&&null!==(r=o.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=de.find.attr(e,"tabindex");return t?parseInt(t,10):xt.test(e.nodeName)||bt.test(e.nodeName)&&e.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),pe.optSelected||(de.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),de.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){de.propFix[this.toLowerCase()]=this}),de.fn.extend({addClass:function(e){var t,n,r,o,i,s,a,u=0;if(de.isFunction(e))return this.each(function(t){de(this).addClass(e.call(this,t,X(this)))});if("string"==typeof e&&e)for(t=e.match(qe)||[];n=this[u++];)if(o=X(n),r=1===n.nodeType&&" "+z(o)+" "){for(s=0;i=t[s++];)r.indexOf(" "+i+" ")<0&&(r+=i+" ");a=z(r),o!==a&&n.setAttribute("class",a)}return this},removeClass:function(e){var t,n,r,o,i,s,a,u=0;if(de.isFunction(e))return this.each(function(t){de(this).removeClass(e.call(this,t,X(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof e&&e)for(t=e.match(qe)||[];n=this[u++];)if(o=X(n),r=1===n.nodeType&&" "+z(o)+" "){for(s=0;i=t[s++];)for(;r.indexOf(" "+i+" ")>-1;)r=r.replace(" "+i+" "," ");a=z(r),o!==a&&n.setAttribute("class",a)}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):de.isFunction(e)?this.each(function(n){de(this).toggleClass(e.call(this,n,X(this),t),t)}):this.each(function(){var t,r,o,i;if("string"===n)for(r=0,o=de(this),i=e.match(qe)||[];t=i[r++];)o.hasClass(t)?o.removeClass(t):o.addClass(t);else void 0!==e&&"boolean"!==n||(t=X(this),t&&Fe.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||e===!1?"":Fe.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];)if(1===n.nodeType&&(" "+z(X(n))+" ").indexOf(t)>-1)return!0;return!1}});var wt=/\r/g;de.fn.extend({val:function(e){var t,n,r,o=this[0];{if(arguments.length)return r=de.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=r?e.call(this,n,de(this).val()):e,null==o?o="":"number"==typeof o?o+="":de.isArray(o)&&(o=de.map(o,function(e){return null==e?"":e+""})),t=de.valHooks[this.type]||de.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&void 0!==t.set(this,o,"value")||(this.value=o))});if(o)return t=de.valHooks[o.type]||de.valHooks[o.nodeName.toLowerCase()],t&&"get"in t&&void 0!==(n=t.get(o,"value"))?n:(n=o.value,"string"==typeof n?n.replace(wt,""):null==n?"":n)}}}),de.extend({valHooks:{option:{get:function(e){var t=de.find.attr(e,"value");return null!=t?t:z(de.text(e))}},select:{get:function(e){var t,n,r,o=e.options,i=e.selectedIndex,s="select-one"===e.type,a=s?null:[],u=s?i+1:o.length;for(r=i<0?u:s?i:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),i}}}}),de.each(["radio","checkbox"],function(){de.valHooks[this]={set:function(e,t){if(de.isArray(t))return e.checked=de.inArray(de(e).val(),t)>-1}},pe.checkOn||(de.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Tt=/^(?:focusinfocus|focusoutblur)$/;de.extend(de.event,{trigger:function(t,n,r,o){var i,s,a,u,c,l,f,p=[r||te],h=ce.call(t,"type")?t.type:t,d=ce.call(t,"namespace")?t.namespace.split("."):[];if(s=a=r=r||te,3!==r.nodeType&&8!==r.nodeType&&!Tt.test(h+de.event.triggered)&&(h.indexOf(".")>-1&&(d=h.split("."),h=d.shift(),d.sort()),c=h.indexOf(":")<0&&"on"+h,t=t[de.expando]?t:new de.Event(h,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=d.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:de.makeArray(n,[t]),f=de.event.special[h]||{},o||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!o&&!f.noBubble&&!de.isWindow(r)){for(u=f.delegateType||h,Tt.test(u+h)||(s=s.parentNode);s;s=s.parentNode)p.push(s),a=s;a===(r.ownerDocument||te)&&p.push(a.defaultView||a.parentWindow||e)}for(i=0;(s=p[i++])&&!t.isPropagationStopped();)t.type=i>1?u:f.bindType||h,l=(Fe.get(s,"events")||{})[t.type]&&Fe.get(s,"handle"),l&&l.apply(s,n),l=c&&s[c],l&&l.apply&&He(s)&&(t.result=l.apply(s,n),t.result===!1&&t.preventDefault());return t.type=h,o||t.isDefaultPrevented()||f._default&&f._default.apply(p.pop(),n)!==!1||!He(r)||c&&de.isFunction(r[h])&&!de.isWindow(r)&&(a=r[c],a&&(r[c]=null),de.event.triggered=h,r[h](),de.event.triggered=void 0,a&&(r[c]=a)),t.result}},simulate:function(e,t,n){var r=de.extend(new de.Event,n,{type:e,isSimulated:!0});de.event.trigger(r,null,t)}}),de.fn.extend({trigger:function(e,t){return this.each(function(){de.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return de.event.trigger(e,t,n,!0)}}),de.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){de.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),de.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),pe.focusin="onfocusin"in e,pe.focusin||de.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){de.event.simulate(t,e.target,de.event.fix(e))};de.event.special[t]={setup:function(){var r=this.ownerDocument||this,o=Fe.access(r,t);o||r.addEventListener(e,n,!0),Fe.access(r,t,(o||0)+1)},teardown:function(){var r=this.ownerDocument||this,o=Fe.access(r,t)-1;o?Fe.access(r,t,o):(r.removeEventListener(e,n,!0),Fe.remove(r,t))}}});var Ct=e.location,jt=de.now(),kt=/\?/;de.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||de.error("Invalid XML: "+t),n};var Et=/\[\]$/,St=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;de.param=function(e,t){var n,r=[],o=function(e,t){var n=de.isFunction(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(de.isArray(e)||e.jquery&&!de.isPlainObject(e))de.each(e,function(){o(this.name,this.value)});else for(n in e)V(n,e[n],t,o);return r.join("&")},de.fn.extend({serialize:function(){return de.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=de.prop(this,"elements");return e?de.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!de(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!ze.test(e))}).map(function(e,t){var n=de(this).val();return null==n?null:de.isArray(n)?de.map(n,function(e){return{name:t.name,value:e.replace(St,"\r\n")}}):{name:t.name,value:n.replace(St,"\r\n")}}).get()}});var qt=/%20/g,Dt=/#.*$/,Ot=/([?&])_=[^&]*/,Lt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Ht=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Ft=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Pt={},Mt="*/".concat("*"),$t=te.createElement("a");$t.href=Ct.href,de.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Ht.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Mt,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":de.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Q(Q(e,de.ajaxSettings),t):Q(de.ajaxSettings,e)},ajaxPrefilter:G(It),ajaxTransport:G(Pt),ajax:function(t,n){function r(t,n,r,a){var c,p,h,b,w,T=n;l||(l=!0,u&&e.clearTimeout(u),o=void 0,s=a||"",C.readyState=t>0?4:0,c=t>=200&&t<300||304===t,r&&(b=J(d,C,r)),b=K(d,b,C,c),c?(d.ifModified&&(w=C.getResponseHeader("Last-Modified"),w&&(de.lastModified[i]=w),w=C.getResponseHeader("etag"),w&&(de.etag[i]=w)),204===t||"HEAD"===d.type?T="nocontent":304===t?T="notmodified":(T=b.state,p=b.data,h=b.error,c=!h)):(h=T,!t&&T||(T="error",t<0&&(t=0))),C.status=t,C.statusText=(n||T)+"",c?v.resolveWith(g,[p,T,C]):v.rejectWith(g,[C,T,h]),C.statusCode(x),x=void 0,f&&m.trigger(c?"ajaxSuccess":"ajaxError",[C,d,c?p:h]),y.fireWith(g,[C,T]),f&&(m.trigger("ajaxComplete",[C,d]),--de.active||de.event.trigger("ajaxStop")))}"object"==typeof t&&(n=t,t=void 0),n=n||{};var o,i,s,a,u,c,l,f,p,h,d=de.ajaxSetup({},n),g=d.context||d,m=d.context&&(g.nodeType||g.jquery)?de(g):de.event,v=de.Deferred(),y=de.Callbacks("once memory"),x=d.statusCode||{},b={},w={},T="canceled",C={readyState:0,getResponseHeader:function(e){var t;if(l){if(!a)for(a={};t=Lt.exec(s);)a[t[1].toLowerCase()]=t[2];t=a[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return l?s:null},setRequestHeader:function(e,t){return null==l&&(e=w[e.toLowerCase()]=w[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==l&&(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(l)C.always(e[C.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||T;return o&&o.abort(t),r(0,t),this}};if(v.promise(C),d.url=((t||d.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=(d.dataType||"*").toLowerCase().match(qe)||[""],null==d.crossDomain){c=te.createElement("a");try{c.href=d.url,c.href=c.href,d.crossDomain=$t.protocol+"//"+$t.host!=c.protocol+"//"+c.host}catch(e){d.crossDomain=!0}}if(d.data&&d.processData&&"string"!=typeof d.data&&(d.data=de.param(d.data,d.traditional)),Y(It,d,n,C),l)return C;f=de.event&&d.global,f&&0===de.active++&&de.event.trigger("ajaxStart"),d.type=d.type.toUpperCase(),d.hasContent=!Ft.test(d.type),i=d.url.replace(Dt,""),d.hasContent?d.data&&d.processData&&0===(d.contentType||"").indexOf("application/x-www-form-urlencoded")&&(d.data=d.data.replace(qt,"+")):(h=d.url.slice(i.length),d.data&&(i+=(kt.test(i)?"&":"?")+d.data,delete d.data),d.cache===!1&&(i=i.replace(Ot,"$1"),h=(kt.test(i)?"&":"?")+"_="+jt++ +h),d.url=i+h),d.ifModified&&(de.lastModified[i]&&C.setRequestHeader("If-Modified-Since",de.lastModified[i]),de.etag[i]&&C.setRequestHeader("If-None-Match",de.etag[i])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&C.setRequestHeader("Content-Type",d.contentType),C.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+("*"!==d.dataTypes[0]?", "+Mt+"; q=0.01":""):d.accepts["*"]);for(p in d.headers)C.setRequestHeader(p,d.headers[p]);if(d.beforeSend&&(d.beforeSend.call(g,C,d)===!1||l))return C.abort();if(T="abort",y.add(d.complete),C.done(d.success),C.fail(d.error),o=Y(Pt,d,n,C)){if(C.readyState=1,f&&m.trigger("ajaxSend",[C,d]),l)return C;d.async&&d.timeout>0&&(u=e.setTimeout(function(){C.abort("timeout")},d.timeout));try{l=!1,o.send(b,r)}catch(e){if(l)throw e;r(-1,e)}}else r(-1,"No Transport");return C},getJSON:function(e,t,n){return de.get(e,t,n,"json")},getScript:function(e,t){return de.get(e,void 0,t,"script")}}),de.each(["get","post"],function(e,t){de[t]=function(e,n,r,o){return de.isFunction(n)&&(o=o||r,r=n,n=void 0),de.ajax(de.extend({url:e,type:t,dataType:o,data:n,success:r},de.isPlainObject(e)&&e))}}),de._evalUrl=function(e){return de.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,throws:!0})},de.fn.extend({wrapAll:function(e){var t;return this[0]&&(de.isFunction(e)&&(e=e.call(this[0])),t=de(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstElementChild;)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return de.isFunction(e)?this.each(function(t){de(this).wrapInner(e.call(this,t))}):this.each(function(){var t=de(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=de.isFunction(e);return this.each(function(n){de(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){de(this).replaceWith(this.childNodes)}),this}}),de.expr.pseudos.hidden=function(e){return!de.expr.pseudos.visible(e)},de.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},de.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Wt={0:200,1223:204},Bt=de.ajaxSettings.xhr();pe.cors=!!Bt&&"withCredentials"in Bt,pe.ajax=Bt=!!Bt,de.ajaxTransport(function(t){var n,r;if(pe.cors||Bt&&!t.crossDomain)return{send:function(o,i){var s,a=t.xhr();if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(s in t.xhrFields)a[s]=t.xhrFields[s];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||o["X-Requested-With"]||(o["X-Requested-With"]="XMLHttpRequest");for(s in o)a.setRequestHeader(s,o[s]);n=function(e){return function(){n&&(n=r=a.onload=a.onerror=a.onabort=a.onreadystatechange=null,"abort"===e?a.abort():"error"===e?"number"!=typeof a.status?i(0,"error"):i(a.status,a.statusText):i(Wt[a.status]||a.status,a.statusText,"text"!==(a.responseType||"text")||"string"!=typeof a.responseText?{binary:a.response}:{text:a.responseText},a.getAllResponseHeaders()))}},a.onload=n(),r=a.onerror=n("error"),void 0!==a.onabort?a.onabort=r:a.onreadystatechange=function(){4===a.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{a.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),de.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),de.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return de.globalEval(e),e}}}),de.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),de.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(r,o){t=de(" + + + + +

    +
    + +

    results matching ""

    +
      + +
      +
      + +

      No results matching ""

      + +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/search_index.json b/_book/search_index.json new file mode 100644 index 0000000000000000000000000000000000000000..08f417f84ffed6531127d00afcd183b1555cb0e5 --- /dev/null +++ b/_book/search_index.json @@ -0,0 +1 @@ +{"index":{"version":"0.5.12","fields":[{"name":"title","boost":10},{"name":"keywords","boost":15},{"name":"body","boost":1}],"ref":"url","documentStore":{"store":{"./":["\"img\"","&&","(13.2","/","=","===","ce","codechina","codechina微信群(1)","codechina微信群(2)","codechina观察员(1)","codechina观察员(2)","console.log(\"plugin","e.target.tagnam","function(e){","gitlab","introduct","issu","popup....\");document.onclick","qq","stable)","wechat","window.open(e.target.src,e.target.src)}img{cursor:pointer}","产品提交","体验使用过程中如果遇到任何问题,请与我们联系。","开发并,目前版本提供了代码仓库管理、组织管理等基本功能,欢迎体验使用。","欢迎使用codechina代码托管平台,本产品基于","点此向","版本","联系方式"],"docs/002.html":["\"img\"","&&","=","===","analyt","basic","burndown","chart","cheat","cherri","codechina","codechina.","codechina。如果您熟悉以上两个产品中的一个或多个,您可以直接开始","codechina,您会发现以下有用信息:","codechina?","codechina?请查阅我们的便捷指南.","console.log(\"plugin","contribut","devop","e.target.tagnam","elasticsearch","epic","flow","function(e){","git","github","github,bitbucket,gitlab.com,fogbugz","gitlab","gitlab/github","gpg","guid","id","issu","jupyt","lf","markdown","merg","notebook","overview","pdf.","pick","pick.","popup....\");document.onclick","request","resolut","roadmap","scrum","search","sheet","ssh","svn","thread","through","waterfall,敏捷还是会话开发,codechina","web","webid","wiki","window.open(e.target.src,e.target.src)}img{cursor:pointer}","work","workflow","上工作.","下载描述最常用的","与","中使用分支.","中的功能和概念.","中编辑文件.","为","为codechina开源做贡献","主题","了解有关使用","了解有关帐户管理的更多信息:","了解项目中的每个角色可以做什么.","产品,在产品中我们也会为您设置帮助提示,您可以随时回来查看我们的产品文档。","从","从svn迁移","从另一个平台进入","代办事项","代码仓库","以下文档与","以下是我们推荐的一些主题:","以及将","使用","使用内置的","使用受保护的分支.","使用新系统可能让您觉得难以入手,我们有以下文档可快速提升您的相关知识:","使用高级查询获得更具针对性的搜索结果.","保护分支","做贡献为codechina开源贡献力量!","入门,分支策略,git","全局搜索","关联","具有两因素身份验证的帐户安全性,设置您的","分支和默认分支","分析","分类问题或使用描述性标签合并请求.","分组组织您的项目.","刚开始使用git/codechina/gitlab/github?","创建主题","创建分支","创建分支,创建和上传文件以及创建目录.","创建并fork项目,以及导入项目","创建并上传文件,并创建目录","创建,复制和移动项目.","删除已合并的分支","利用","利用最佳的工作流程增强您的工作流程.","协议","可视化史诗般的时间表.","合并更改后的批量删除分支.","合并请求","合并请求管理.","和","和高级用法.","在","在提交时启动合并请求.","在整个","在本地处理合并请求","在本地处理合并请求的提示.","在特定的里程碑中观察项目的进度.","在网页中管理源代码仓库.","在问题之间建立关系.","均可简化您的协作工作流程.","基本入门","基础入门","处理合并请求","处理提交,并使用","如何在","如何在开发上做贡献.","如何在文档上做贡献.","如果您是从另一个平台进入","子组织","存储库转换为","存储库随附分支工具和访问控制,可为项目和代码的协作提供可扩展的单一事实来源.","实例上进行更快,更高级的代码搜索.","实例之间","密钥,并部署密钥以安全地访问您的项目.","对.ipynb文件的支持.","对您的提交进行签名.","对更改进行","对项目推送的附加控制.","导入项目","导入项目.","将","将源代码整合到一个易于管理和控制的分布式版本控制系统中","帮助文档","开发","开始在命令行和","快捷方式","或","或看板上显示问题.","截止日期]","托管源代码,并控制项目的可见性和设置配置.","推入或拉出外部的代码仓库","推送规则","描述","提交","搜索问题,合并请求,项目,组和待办事项.","操作的","文件","文件模板","文件管理.","文档","新建","新建阶段有关:","无论您使用","时间跟踪","是","是开源的,您可以通过以下方式为我们的开源社区做出贡献:","来管理您的文档.","标签","检查每月创建了多少个问题.","概览","欢迎您使用codechina,如果您是","此外,在项目之间转移问题.","灵活的项目管理工具可视化,确定优先级,协调和跟踪进度.","热门话题","用户文件熟悉codechina","用户权限","用户账号","的初级用户,我们建议您从查看本文档开始学习如何使用","的新手吗?我们有资源可以帮助您入门.","的精华.","看板","策略探索","管理员文件管理员入门.","管理您的帐户.","组织","结合使用的更多信息:","署名提交","草稿合并请求","解析线程,将合并请求中的线程移至问题,并且仅在解决所有线程后才允许合并请求.","计划","计划主题","计划阶段有关:","讨论","设置发布问题和合并请求的里程碑,并带有可选的截止日期.","访问codechina.csdn.net/docs,以获得优化的导航,可发现性和可读性.","语法检索","请参阅小组贡献者的详细统计信息.","贡献者许可协议.","账号验证","账户管理","跟踪共享主题的问题组.","跟踪发行期限.","跟踪花费在问题和合并请求上的时间.","返回概览","通用文件的文件模板.","通过在简单仪表板上显示的时间顺序列表,跟踪需要注意的工作.","里程碑","针对问题或合并请求的常见操作的快捷方式,而无需单击按钮或在web界面中使用下拉菜单.","锁定文件","锁定文件以避免合并冲突.","镜像代码仓库","问题","问题,提交和合并请求中的线程,注释和可解决线程.","防止合并草稿合并请求.","项目","项目和组","项目和组织","项目问题并限制对问题的访问,并创建用于提交新问题和合并请求的模板.","高级格式化系统(markdown)",",",",包括机密问题",",包括项目访问和设置",",发布和合并请求模板",",和移动的问题",",而不会中断您的工作流程."]},"length":2},"tokenStore":{"root":{"docs":{},"\"":{"docs":{},"i":{"docs":{},"m":{"docs":{},"g":{"docs":{},"\"":{"docs":{"./":{"ref":"./","tf":0.030303030303030304},"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}},"&":{"docs":{},"&":{"docs":{"./":{"ref":"./","tf":0.030303030303030304},"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"(":{"1":{"3":{"docs":{},".":{"2":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}},"docs":{}}},"docs":{}},"docs":{}},"/":{"docs":{"./":{"ref":"./","tf":0.06060606060606061}}},"=":{"docs":{"./":{"ref":"./","tf":0.030303030303030304},"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"=":{"docs":{},"=":{"docs":{"./":{"ref":"./","tf":0.030303030303030304},"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"c":{"docs":{},"e":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}},"o":{"docs":{},"d":{"docs":{},"e":{"docs":{},"c":{"docs":{},"h":{"docs":{},"i":{"docs":{},"n":{"docs":{},"a":{"docs":{"./":{"ref":"./","tf":0.06060606060606061},"docs/002.html":{"ref":"docs/002.html","tf":0.03832752613240418}},"微":{"docs":{},"信":{"docs":{},"群":{"docs":{},"(":{"1":{"docs":{},")":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}}},"2":{"docs":{},")":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}}},"docs":{}}}}},"观":{"docs":{},"察":{"docs":{},"员":{"docs":{},"(":{"1":{"docs":{},")":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}}},"2":{"docs":{},")":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}}},"docs":{}}}}},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}},"。":{"docs":{},"如":{"docs":{},"果":{"docs":{},"您":{"docs":{},"熟":{"docs":{},"悉":{"docs":{},"以":{"docs":{},"上":{"docs":{},"两":{"docs":{},"个":{"docs":{},"产":{"docs":{},"品":{"docs":{},"中":{"docs":{},"的":{"docs":{},"一":{"docs":{},"个":{"docs":{},"或":{"docs":{},"多":{"docs":{},"个":{"docs":{},",":{"docs":{},"您":{"docs":{},"可":{"docs":{},"以":{"docs":{},"直":{"docs":{},"接":{"docs":{},"开":{"docs":{},"始":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}},",":{"docs":{},"您":{"docs":{},"会":{"docs":{},"发":{"docs":{},"现":{"docs":{},"以":{"docs":{},"下":{"docs":{},"有":{"docs":{},"用":{"docs":{},"信":{"docs":{},"息":{"docs":{},":":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}},"?":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"请":{"docs":{},"查":{"docs":{},"阅":{"docs":{},"我":{"docs":{},"们":{"docs":{},"的":{"docs":{},"便":{"docs":{},"捷":{"docs":{},"指":{"docs":{},"南":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}},"n":{"docs":{},"s":{"docs":{},"o":{"docs":{},"l":{"docs":{},"e":{"docs":{},".":{"docs":{},"l":{"docs":{},"o":{"docs":{},"g":{"docs":{},"(":{"docs":{},"\"":{"docs":{},"p":{"docs":{},"l":{"docs":{},"u":{"docs":{},"g":{"docs":{},"i":{"docs":{},"n":{"docs":{"./":{"ref":"./","tf":0.030303030303030304},"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}},"t":{"docs":{},"r":{"docs":{},"i":{"docs":{},"b":{"docs":{},"u":{"docs":{},"t":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}},"h":{"docs":{},"a":{"docs":{},"r":{"docs":{},"t":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"e":{"docs":{},"a":{"docs":{},"t":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"r":{"docs":{},"r":{"docs":{},"i":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.006968641114982578}}}}}}}},"e":{"docs":{},".":{"docs":{},"t":{"docs":{},"a":{"docs":{},"r":{"docs":{},"g":{"docs":{},"e":{"docs":{},"t":{"docs":{},".":{"docs":{},"t":{"docs":{},"a":{"docs":{},"g":{"docs":{},"n":{"docs":{},"a":{"docs":{},"m":{"docs":{"./":{"ref":"./","tf":0.030303030303030304},"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}},"l":{"docs":{},"a":{"docs":{},"s":{"docs":{},"t":{"docs":{},"i":{"docs":{},"c":{"docs":{},"s":{"docs":{},"e":{"docs":{},"a":{"docs":{},"r":{"docs":{},"c":{"docs":{},"h":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}},"p":{"docs":{},"i":{"docs":{},"c":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"f":{"docs":{},"u":{"docs":{},"n":{"docs":{},"c":{"docs":{},"t":{"docs":{},"i":{"docs":{},"o":{"docs":{},"n":{"docs":{},"(":{"docs":{},"e":{"docs":{},")":{"docs":{},"{":{"docs":{"./":{"ref":"./","tf":0.030303030303030304},"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}},"l":{"docs":{},"o":{"docs":{},"w":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.006968641114982578}}}}}},"g":{"docs":{},"i":{"docs":{},"t":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.03484320557491289}},"l":{"docs":{},"a":{"docs":{},"b":{"docs":{"./":{"ref":"./","tf":0.030303030303030304},"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"/":{"docs":{},"g":{"docs":{},"i":{"docs":{},"t":{"docs":{},"h":{"docs":{},"u":{"docs":{},"b":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}},"h":{"docs":{},"u":{"docs":{},"b":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},",":{"docs":{},"b":{"docs":{},"i":{"docs":{},"t":{"docs":{},"b":{"docs":{},"u":{"docs":{},"c":{"docs":{},"k":{"docs":{},"e":{"docs":{},"t":{"docs":{},",":{"docs":{},"g":{"docs":{},"i":{"docs":{},"t":{"docs":{},"l":{"docs":{},"a":{"docs":{},"b":{"docs":{},".":{"docs":{},"c":{"docs":{},"o":{"docs":{},"m":{"docs":{},",":{"docs":{},"f":{"docs":{},"o":{"docs":{},"g":{"docs":{},"b":{"docs":{},"u":{"docs":{},"g":{"docs":{},"z":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"p":{"docs":{},"g":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"u":{"docs":{},"i":{"docs":{},"d":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"i":{"docs":{},"n":{"docs":{},"t":{"docs":{},"r":{"docs":{},"o":{"docs":{},"d":{"docs":{},"u":{"docs":{},"c":{"docs":{},"t":{"docs":{"./":{"ref":"./","tf":10}}}}}}}}}},"s":{"docs":{},"s":{"docs":{},"u":{"docs":{"./":{"ref":"./","tf":0.030303030303030304},"docs/002.html":{"ref":"docs/002.html","tf":0.006968641114982578}}}}},"d":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"p":{"docs":{},"o":{"docs":{},"p":{"docs":{},"u":{"docs":{},"p":{"docs":{},".":{"docs":{},".":{"docs":{},".":{"docs":{},".":{"docs":{},"\"":{"docs":{},")":{"docs":{},";":{"docs":{},"d":{"docs":{},"o":{"docs":{},"c":{"docs":{},"u":{"docs":{},"m":{"docs":{},"e":{"docs":{},"n":{"docs":{},"t":{"docs":{},".":{"docs":{},"o":{"docs":{},"n":{"docs":{},"c":{"docs":{},"l":{"docs":{},"i":{"docs":{},"c":{"docs":{},"k":{"docs":{"./":{"ref":"./","tf":0.030303030303030304},"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"d":{"docs":{},"f":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"i":{"docs":{},"c":{"docs":{},"k":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}},"q":{"docs":{},"q":{"docs":{"./":{"ref":"./","tf":0.06060606060606061}}}},"s":{"docs":{},"t":{"docs":{},"a":{"docs":{},"b":{"docs":{},"l":{"docs":{},"e":{"docs":{},")":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}}}}}}},"c":{"docs":{},"r":{"docs":{},"u":{"docs":{},"m":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"e":{"docs":{},"a":{"docs":{},"r":{"docs":{},"c":{"docs":{},"h":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}},"h":{"docs":{},"e":{"docs":{},"e":{"docs":{},"t":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"s":{"docs":{},"h":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"v":{"docs":{},"n":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.006968641114982578}}}}},"w":{"docs":{},"e":{"docs":{},"c":{"docs":{},"h":{"docs":{},"a":{"docs":{},"t":{"docs":{"./":{"ref":"./","tf":0.06060606060606061}}}}}},"b":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"i":{"docs":{},"d":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"i":{"docs":{},"n":{"docs":{},"d":{"docs":{},"o":{"docs":{},"w":{"docs":{},".":{"docs":{},"o":{"docs":{},"p":{"docs":{},"e":{"docs":{},"n":{"docs":{},"(":{"docs":{},"e":{"docs":{},".":{"docs":{},"t":{"docs":{},"a":{"docs":{},"r":{"docs":{},"g":{"docs":{},"e":{"docs":{},"t":{"docs":{},".":{"docs":{},"s":{"docs":{},"r":{"docs":{},"c":{"docs":{},",":{"docs":{},"e":{"docs":{},".":{"docs":{},"t":{"docs":{},"a":{"docs":{},"r":{"docs":{},"g":{"docs":{},"e":{"docs":{},"t":{"docs":{},".":{"docs":{},"s":{"docs":{},"r":{"docs":{},"c":{"docs":{},")":{"docs":{},"}":{"docs":{},"i":{"docs":{},"m":{"docs":{},"g":{"docs":{},"{":{"docs":{},"c":{"docs":{},"u":{"docs":{},"r":{"docs":{},"s":{"docs":{},"o":{"docs":{},"r":{"docs":{},":":{"docs":{},"p":{"docs":{},"o":{"docs":{},"i":{"docs":{},"n":{"docs":{},"t":{"docs":{},"e":{"docs":{},"r":{"docs":{},"}":{"docs":{"./":{"ref":"./","tf":0.030303030303030304},"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"k":{"docs":{},"i":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.006968641114982578}}}}},"a":{"docs":{},"t":{"docs":{},"e":{"docs":{},"r":{"docs":{},"f":{"docs":{},"a":{"docs":{},"l":{"docs":{},"l":{"docs":{},",":{"docs":{},"敏":{"docs":{},"捷":{"docs":{},"还":{"docs":{},"是":{"docs":{},"会":{"docs":{},"话":{"docs":{},"开":{"docs":{},"发":{"docs":{},",":{"docs":{},"c":{"docs":{},"o":{"docs":{},"d":{"docs":{},"e":{"docs":{},"c":{"docs":{},"h":{"docs":{},"i":{"docs":{},"n":{"docs":{},"a":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"o":{"docs":{},"r":{"docs":{},"k":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.006968641114982578}},"f":{"docs":{},"l":{"docs":{},"o":{"docs":{},"w":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}},"产":{"docs":{},"品":{"docs":{},"提":{"docs":{},"交":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}}},",":{"docs":{},"在":{"docs":{},"产":{"docs":{},"品":{"docs":{},"中":{"docs":{},"我":{"docs":{},"们":{"docs":{},"也":{"docs":{},"会":{"docs":{},"为":{"docs":{},"您":{"docs":{},"设":{"docs":{},"置":{"docs":{},"帮":{"docs":{},"助":{"docs":{},"提":{"docs":{},"示":{"docs":{},",":{"docs":{},"您":{"docs":{},"可":{"docs":{},"以":{"docs":{},"随":{"docs":{},"时":{"docs":{},"回":{"docs":{},"来":{"docs":{},"查":{"docs":{},"看":{"docs":{},"我":{"docs":{},"们":{"docs":{},"的":{"docs":{},"产":{"docs":{},"品":{"docs":{},"文":{"docs":{},"档":{"docs":{},"。":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"体":{"docs":{},"验":{"docs":{},"使":{"docs":{},"用":{"docs":{},"过":{"docs":{},"程":{"docs":{},"中":{"docs":{},"如":{"docs":{},"果":{"docs":{},"遇":{"docs":{},"到":{"docs":{},"任":{"docs":{},"何":{"docs":{},"问":{"docs":{},"题":{"docs":{},",":{"docs":{},"请":{"docs":{},"与":{"docs":{},"我":{"docs":{},"们":{"docs":{},"联":{"docs":{},"系":{"docs":{},"。":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}}}}}}}}}}}}}}}}}}}}}}}},"开":{"docs":{},"发":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"并":{"docs":{},",":{"docs":{},"目":{"docs":{},"前":{"docs":{},"版":{"docs":{},"本":{"docs":{},"提":{"docs":{},"供":{"docs":{},"了":{"docs":{},"代":{"docs":{},"码":{"docs":{},"仓":{"docs":{},"库":{"docs":{},"管":{"docs":{},"理":{"docs":{},"、":{"docs":{},"组":{"docs":{},"织":{"docs":{},"管":{"docs":{},"理":{"docs":{},"等":{"docs":{},"基":{"docs":{},"本":{"docs":{},"功":{"docs":{},"能":{"docs":{},",":{"docs":{},"欢":{"docs":{},"迎":{"docs":{},"体":{"docs":{},"验":{"docs":{},"使":{"docs":{},"用":{"docs":{},"。":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"始":{"docs":{},"在":{"docs":{},"命":{"docs":{},"令":{"docs":{},"行":{"docs":{},"和":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}},"欢":{"docs":{},"迎":{"docs":{},"使":{"docs":{},"用":{"docs":{},"c":{"docs":{},"o":{"docs":{},"d":{"docs":{},"e":{"docs":{},"c":{"docs":{},"h":{"docs":{},"i":{"docs":{},"n":{"docs":{},"a":{"docs":{},"代":{"docs":{},"码":{"docs":{},"托":{"docs":{},"管":{"docs":{},"平":{"docs":{},"台":{"docs":{},",":{"docs":{},"本":{"docs":{},"产":{"docs":{},"品":{"docs":{},"基":{"docs":{},"于":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}}}}}}}}}}}}}}}}}}}}}}}},"您":{"docs":{},"使":{"docs":{},"用":{"docs":{},"c":{"docs":{},"o":{"docs":{},"d":{"docs":{},"e":{"docs":{},"c":{"docs":{},"h":{"docs":{},"i":{"docs":{},"n":{"docs":{},"a":{"docs":{},",":{"docs":{},"如":{"docs":{},"果":{"docs":{},"您":{"docs":{},"是":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}},"点":{"docs":{},"此":{"docs":{},"向":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}}}},"版":{"docs":{},"本":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}}},"联":{"docs":{},"系":{"docs":{},"方":{"docs":{},"式":{"docs":{"./":{"ref":"./","tf":0.030303030303030304}}}}}},"a":{"docs":{},"n":{"docs":{},"a":{"docs":{},"l":{"docs":{},"y":{"docs":{},"t":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}},"b":{"docs":{},"a":{"docs":{},"s":{"docs":{},"i":{"docs":{},"c":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"u":{"docs":{},"r":{"docs":{},"n":{"docs":{},"d":{"docs":{},"o":{"docs":{},"w":{"docs":{},"n":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}},"d":{"docs":{},"e":{"docs":{},"v":{"docs":{},"o":{"docs":{},"p":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.006968641114982578}}}}}}},"j":{"docs":{},"u":{"docs":{},"p":{"docs":{},"y":{"docs":{},"t":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}},"l":{"docs":{},"f":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"m":{"docs":{},"a":{"docs":{},"r":{"docs":{},"k":{"docs":{},"d":{"docs":{},"o":{"docs":{},"w":{"docs":{},"n":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}},"e":{"docs":{},"r":{"docs":{},"g":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"n":{"docs":{},"o":{"docs":{},"t":{"docs":{},"e":{"docs":{},"b":{"docs":{},"o":{"docs":{},"o":{"docs":{},"k":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}},"o":{"docs":{},"v":{"docs":{},"e":{"docs":{},"r":{"docs":{},"v":{"docs":{},"i":{"docs":{},"e":{"docs":{},"w":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}},"r":{"docs":{},"e":{"docs":{},"q":{"docs":{},"u":{"docs":{},"e":{"docs":{},"s":{"docs":{},"t":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}},"s":{"docs":{},"o":{"docs":{},"l":{"docs":{},"u":{"docs":{},"t":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}},"o":{"docs":{},"a":{"docs":{},"d":{"docs":{},"m":{"docs":{},"a":{"docs":{},"p":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}},"t":{"docs":{},"h":{"docs":{},"r":{"docs":{},"e":{"docs":{},"a":{"docs":{},"d":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"o":{"docs":{},"u":{"docs":{},"g":{"docs":{},"h":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}},"上":{"docs":{},"工":{"docs":{},"作":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"下":{"docs":{},"载":{"docs":{},"描":{"docs":{},"述":{"docs":{},"最":{"docs":{},"常":{"docs":{},"用":{"docs":{},"的":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}},"与":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}},"中":{"docs":{},"使":{"docs":{},"用":{"docs":{},"分":{"docs":{},"支":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}},"的":{"docs":{},"功":{"docs":{},"能":{"docs":{},"和":{"docs":{},"概":{"docs":{},"念":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}},"编":{"docs":{},"辑":{"docs":{},"文":{"docs":{},"件":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}},"为":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"c":{"docs":{},"o":{"docs":{},"d":{"docs":{},"e":{"docs":{},"c":{"docs":{},"h":{"docs":{},"i":{"docs":{},"n":{"docs":{},"a":{"docs":{},"开":{"docs":{},"源":{"docs":{},"做":{"docs":{},"贡":{"docs":{},"献":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}},"主":{"docs":{},"题":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.017421602787456445}}}},"了":{"docs":{},"解":{"docs":{},"有":{"docs":{},"关":{"docs":{},"使":{"docs":{},"用":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"帐":{"docs":{},"户":{"docs":{},"管":{"docs":{},"理":{"docs":{},"的":{"docs":{},"更":{"docs":{},"多":{"docs":{},"信":{"docs":{},"息":{"docs":{},":":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}},"项":{"docs":{},"目":{"docs":{},"中":{"docs":{},"的":{"docs":{},"每":{"docs":{},"个":{"docs":{},"角":{"docs":{},"色":{"docs":{},"可":{"docs":{},"以":{"docs":{},"做":{"docs":{},"什":{"docs":{},"么":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}},"从":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"s":{"docs":{},"v":{"docs":{},"n":{"docs":{},"迁":{"docs":{},"移":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}},"另":{"docs":{},"一":{"docs":{},"个":{"docs":{},"平":{"docs":{},"台":{"docs":{},"进":{"docs":{},"入":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.006968641114982578}}}}}}}}}},"代":{"docs":{},"办":{"docs":{},"事":{"docs":{},"项":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"码":{"docs":{},"仓":{"docs":{},"库":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.010452961672473868}}}}}},"以":{"docs":{},"下":{"docs":{},"文":{"docs":{},"档":{"docs":{},"与":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.006968641114982578}}}}},"是":{"docs":{},"我":{"docs":{},"们":{"docs":{},"推":{"docs":{},"荐":{"docs":{},"的":{"docs":{},"一":{"docs":{},"些":{"docs":{},"主":{"docs":{},"题":{"docs":{},":":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}},"及":{"docs":{},"将":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"使":{"docs":{},"用":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.006968641114982578}},"内":{"docs":{},"置":{"docs":{},"的":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"受":{"docs":{},"保":{"docs":{},"护":{"docs":{},"的":{"docs":{},"分":{"docs":{},"支":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}},"新":{"docs":{},"系":{"docs":{},"统":{"docs":{},"可":{"docs":{},"能":{"docs":{},"让":{"docs":{},"您":{"docs":{},"觉":{"docs":{},"得":{"docs":{},"难":{"docs":{},"以":{"docs":{},"入":{"docs":{},"手":{"docs":{},",":{"docs":{},"我":{"docs":{},"们":{"docs":{},"有":{"docs":{},"以":{"docs":{},"下":{"docs":{},"文":{"docs":{},"档":{"docs":{},"可":{"docs":{},"快":{"docs":{},"速":{"docs":{},"提":{"docs":{},"升":{"docs":{},"您":{"docs":{},"的":{"docs":{},"相":{"docs":{},"关":{"docs":{},"知":{"docs":{},"识":{"docs":{},":":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"高":{"docs":{},"级":{"docs":{},"查":{"docs":{},"询":{"docs":{},"获":{"docs":{},"得":{"docs":{},"更":{"docs":{},"具":{"docs":{},"针":{"docs":{},"对":{"docs":{},"性":{"docs":{},"的":{"docs":{},"搜":{"docs":{},"索":{"docs":{},"结":{"docs":{},"果":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}},"保":{"docs":{},"护":{"docs":{},"分":{"docs":{},"支":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"做":{"docs":{},"贡":{"docs":{},"献":{"docs":{},"为":{"docs":{},"c":{"docs":{},"o":{"docs":{},"d":{"docs":{},"e":{"docs":{},"c":{"docs":{},"h":{"docs":{},"i":{"docs":{},"n":{"docs":{},"a":{"docs":{},"开":{"docs":{},"源":{"docs":{},"贡":{"docs":{},"献":{"docs":{},"力":{"docs":{},"量":{"docs":{},"!":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}},"入":{"docs":{},"门":{"docs":{},",":{"docs":{},"分":{"docs":{},"支":{"docs":{},"策":{"docs":{},"略":{"docs":{},",":{"docs":{},"g":{"docs":{},"i":{"docs":{},"t":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}},"全":{"docs":{},"局":{"docs":{},"搜":{"docs":{},"索":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"关":{"docs":{},"联":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"具":{"docs":{},"有":{"docs":{},"两":{"docs":{},"因":{"docs":{},"素":{"docs":{},"身":{"docs":{},"份":{"docs":{},"验":{"docs":{},"证":{"docs":{},"的":{"docs":{},"帐":{"docs":{},"户":{"docs":{},"安":{"docs":{},"全":{"docs":{},"性":{"docs":{},",":{"docs":{},"设":{"docs":{},"置":{"docs":{},"您":{"docs":{},"的":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}},"分":{"docs":{},"支":{"docs":{},"和":{"docs":{},"默":{"docs":{},"认":{"docs":{},"分":{"docs":{},"支":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}},"析":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}},"类":{"docs":{},"问":{"docs":{},"题":{"docs":{},"或":{"docs":{},"使":{"docs":{},"用":{"docs":{},"描":{"docs":{},"述":{"docs":{},"性":{"docs":{},"标":{"docs":{},"签":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}},"组":{"docs":{},"组":{"docs":{},"织":{"docs":{},"您":{"docs":{},"的":{"docs":{},"项":{"docs":{},"目":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}},"刚":{"docs":{},"开":{"docs":{},"始":{"docs":{},"使":{"docs":{},"用":{"docs":{},"g":{"docs":{},"i":{"docs":{},"t":{"docs":{},"/":{"docs":{},"c":{"docs":{},"o":{"docs":{},"d":{"docs":{},"e":{"docs":{},"c":{"docs":{},"h":{"docs":{},"i":{"docs":{},"n":{"docs":{},"a":{"docs":{},"/":{"docs":{},"g":{"docs":{},"i":{"docs":{},"t":{"docs":{},"l":{"docs":{},"a":{"docs":{},"b":{"docs":{},"/":{"docs":{},"g":{"docs":{},"i":{"docs":{},"t":{"docs":{},"h":{"docs":{},"u":{"docs":{},"b":{"docs":{},"?":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"创":{"docs":{},"建":{"docs":{},"主":{"docs":{},"题":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.010452961672473868}}}},"分":{"docs":{},"支":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},",":{"docs":{},"创":{"docs":{},"建":{"docs":{},"和":{"docs":{},"上":{"docs":{},"传":{"docs":{},"文":{"docs":{},"件":{"docs":{},"以":{"docs":{},"及":{"docs":{},"创":{"docs":{},"建":{"docs":{},"目":{"docs":{},"录":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}},"并":{"docs":{},"f":{"docs":{},"o":{"docs":{},"r":{"docs":{},"k":{"docs":{},"项":{"docs":{},"目":{"docs":{},",":{"docs":{},"以":{"docs":{},"及":{"docs":{},"导":{"docs":{},"入":{"docs":{},"项":{"docs":{},"目":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}},"上":{"docs":{},"传":{"docs":{},"文":{"docs":{},"件":{"docs":{},",":{"docs":{},"并":{"docs":{},"创":{"docs":{},"建":{"docs":{},"目":{"docs":{},"录":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}},",":{"docs":{},"复":{"docs":{},"制":{"docs":{},"和":{"docs":{},"移":{"docs":{},"动":{"docs":{},"项":{"docs":{},"目":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}},"删":{"docs":{},"除":{"docs":{},"已":{"docs":{},"合":{"docs":{},"并":{"docs":{},"的":{"docs":{},"分":{"docs":{},"支":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}},"利":{"docs":{},"用":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"最":{"docs":{},"佳":{"docs":{},"的":{"docs":{},"工":{"docs":{},"作":{"docs":{},"流":{"docs":{},"程":{"docs":{},"增":{"docs":{},"强":{"docs":{},"您":{"docs":{},"的":{"docs":{},"工":{"docs":{},"作":{"docs":{},"流":{"docs":{},"程":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}},"协":{"docs":{},"议":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"可":{"docs":{},"视":{"docs":{},"化":{"docs":{},"史":{"docs":{},"诗":{"docs":{},"般":{"docs":{},"的":{"docs":{},"时":{"docs":{},"间":{"docs":{},"表":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}},"合":{"docs":{},"并":{"docs":{},"更":{"docs":{},"改":{"docs":{},"后":{"docs":{},"的":{"docs":{},"批":{"docs":{},"量":{"docs":{},"删":{"docs":{},"除":{"docs":{},"分":{"docs":{},"支":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}},"请":{"docs":{},"求":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.010452961672473868}},"管":{"docs":{},"理":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}},"和":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.013937282229965157}},"高":{"docs":{},"级":{"docs":{},"用":{"docs":{},"法":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}},"在":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.006968641114982578}},"提":{"docs":{},"交":{"docs":{},"时":{"docs":{},"启":{"docs":{},"动":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}},"整":{"docs":{},"个":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"本":{"docs":{},"地":{"docs":{},"处":{"docs":{},"理":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"的":{"docs":{},"提":{"docs":{},"示":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}},"特":{"docs":{},"定":{"docs":{},"的":{"docs":{},"里":{"docs":{},"程":{"docs":{},"碑":{"docs":{},"中":{"docs":{},"观":{"docs":{},"察":{"docs":{},"项":{"docs":{},"目":{"docs":{},"的":{"docs":{},"进":{"docs":{},"度":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}},"网":{"docs":{},"页":{"docs":{},"中":{"docs":{},"管":{"docs":{},"理":{"docs":{},"源":{"docs":{},"代":{"docs":{},"码":{"docs":{},"仓":{"docs":{},"库":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}},"问":{"docs":{},"题":{"docs":{},"之":{"docs":{},"间":{"docs":{},"建":{"docs":{},"立":{"docs":{},"关":{"docs":{},"系":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}},"均":{"docs":{},"可":{"docs":{},"简":{"docs":{},"化":{"docs":{},"您":{"docs":{},"的":{"docs":{},"协":{"docs":{},"作":{"docs":{},"工":{"docs":{},"作":{"docs":{},"流":{"docs":{},"程":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}},"基":{"docs":{},"本":{"docs":{},"入":{"docs":{},"门":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"础":{"docs":{},"入":{"docs":{},"门":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"处":{"docs":{},"理":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"提":{"docs":{},"交":{"docs":{},",":{"docs":{},"并":{"docs":{},"使":{"docs":{},"用":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}},"如":{"docs":{},"何":{"docs":{},"在":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"开":{"docs":{},"发":{"docs":{},"上":{"docs":{},"做":{"docs":{},"贡":{"docs":{},"献":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}},"文":{"docs":{},"档":{"docs":{},"上":{"docs":{},"做":{"docs":{},"贡":{"docs":{},"献":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}},"果":{"docs":{},"您":{"docs":{},"是":{"docs":{},"从":{"docs":{},"另":{"docs":{},"一":{"docs":{},"个":{"docs":{},"平":{"docs":{},"台":{"docs":{},"进":{"docs":{},"入":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}},"子":{"docs":{},"组":{"docs":{},"织":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"存":{"docs":{},"储":{"docs":{},"库":{"docs":{},"转":{"docs":{},"换":{"docs":{},"为":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"随":{"docs":{},"附":{"docs":{},"分":{"docs":{},"支":{"docs":{},"工":{"docs":{},"具":{"docs":{},"和":{"docs":{},"访":{"docs":{},"问":{"docs":{},"控":{"docs":{},"制":{"docs":{},",":{"docs":{},"可":{"docs":{},"为":{"docs":{},"项":{"docs":{},"目":{"docs":{},"和":{"docs":{},"代":{"docs":{},"码":{"docs":{},"的":{"docs":{},"协":{"docs":{},"作":{"docs":{},"提":{"docs":{},"供":{"docs":{},"可":{"docs":{},"扩":{"docs":{},"展":{"docs":{},"的":{"docs":{},"单":{"docs":{},"一":{"docs":{},"事":{"docs":{},"实":{"docs":{},"来":{"docs":{},"源":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"实":{"docs":{},"例":{"docs":{},"上":{"docs":{},"进":{"docs":{},"行":{"docs":{},"更":{"docs":{},"快":{"docs":{},",":{"docs":{},"更":{"docs":{},"高":{"docs":{},"级":{"docs":{},"的":{"docs":{},"代":{"docs":{},"码":{"docs":{},"搜":{"docs":{},"索":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}},"之":{"docs":{},"间":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"密":{"docs":{},"钥":{"docs":{},",":{"docs":{},"并":{"docs":{},"部":{"docs":{},"署":{"docs":{},"密":{"docs":{},"钥":{"docs":{},"以":{"docs":{},"安":{"docs":{},"全":{"docs":{},"地":{"docs":{},"访":{"docs":{},"问":{"docs":{},"您":{"docs":{},"的":{"docs":{},"项":{"docs":{},"目":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}},"对":{"docs":{},".":{"docs":{},"i":{"docs":{},"p":{"docs":{},"y":{"docs":{},"n":{"docs":{},"b":{"docs":{},"文":{"docs":{},"件":{"docs":{},"的":{"docs":{},"支":{"docs":{},"持":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}},"您":{"docs":{},"的":{"docs":{},"提":{"docs":{},"交":{"docs":{},"进":{"docs":{},"行":{"docs":{},"签":{"docs":{},"名":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}},"更":{"docs":{},"改":{"docs":{},"进":{"docs":{},"行":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"项":{"docs":{},"目":{"docs":{},"推":{"docs":{},"送":{"docs":{},"的":{"docs":{},"附":{"docs":{},"加":{"docs":{},"控":{"docs":{},"制":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}},"导":{"docs":{},"入":{"docs":{},"项":{"docs":{},"目":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}},"将":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"源":{"docs":{},"代":{"docs":{},"码":{"docs":{},"整":{"docs":{},"合":{"docs":{},"到":{"docs":{},"一":{"docs":{},"个":{"docs":{},"易":{"docs":{},"于":{"docs":{},"管":{"docs":{},"理":{"docs":{},"和":{"docs":{},"控":{"docs":{},"制":{"docs":{},"的":{"docs":{},"分":{"docs":{},"布":{"docs":{},"式":{"docs":{},"版":{"docs":{},"本":{"docs":{},"控":{"docs":{},"制":{"docs":{},"系":{"docs":{},"统":{"docs":{},"中":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"帮":{"docs":{},"助":{"docs":{},"文":{"docs":{},"档":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"快":{"docs":{},"捷":{"docs":{},"方":{"docs":{},"式":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"或":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"看":{"docs":{},"板":{"docs":{},"上":{"docs":{},"显":{"docs":{},"示":{"docs":{},"问":{"docs":{},"题":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}},"截":{"docs":{},"止":{"docs":{},"日":{"docs":{},"期":{"docs":{},"]":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}},"托":{"docs":{},"管":{"docs":{},"源":{"docs":{},"代":{"docs":{},"码":{"docs":{},",":{"docs":{},"并":{"docs":{},"控":{"docs":{},"制":{"docs":{},"项":{"docs":{},"目":{"docs":{},"的":{"docs":{},"可":{"docs":{},"见":{"docs":{},"性":{"docs":{},"和":{"docs":{},"设":{"docs":{},"置":{"docs":{},"配":{"docs":{},"置":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}},"推":{"docs":{},"入":{"docs":{},"或":{"docs":{},"拉":{"docs":{},"出":{"docs":{},"外":{"docs":{},"部":{"docs":{},"的":{"docs":{},"代":{"docs":{},"码":{"docs":{},"仓":{"docs":{},"库":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}},"送":{"docs":{},"规":{"docs":{},"则":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"描":{"docs":{},"述":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.0313588850174216}}}},"提":{"docs":{},"交":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"搜":{"docs":{},"索":{"docs":{},"问":{"docs":{},"题":{"docs":{},",":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{},",":{"docs":{},"项":{"docs":{},"目":{"docs":{},",":{"docs":{},"组":{"docs":{},"和":{"docs":{},"待":{"docs":{},"办":{"docs":{},"事":{"docs":{},"项":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}},"操":{"docs":{},"作":{"docs":{},"的":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"文":{"docs":{},"件":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.006968641114982578}},"模":{"docs":{},"板":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"管":{"docs":{},"理":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"档":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"新":{"docs":{},"建":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"阶":{"docs":{},"段":{"docs":{},"有":{"docs":{},"关":{"docs":{},":":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}},"无":{"docs":{},"论":{"docs":{},"您":{"docs":{},"使":{"docs":{},"用":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}},"时":{"docs":{},"间":{"docs":{},"跟":{"docs":{},"踪":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"是":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"开":{"docs":{},"源":{"docs":{},"的":{"docs":{},",":{"docs":{},"您":{"docs":{},"可":{"docs":{},"以":{"docs":{},"通":{"docs":{},"过":{"docs":{},"以":{"docs":{},"下":{"docs":{},"方":{"docs":{},"式":{"docs":{},"为":{"docs":{},"我":{"docs":{},"们":{"docs":{},"的":{"docs":{},"开":{"docs":{},"源":{"docs":{},"社":{"docs":{},"区":{"docs":{},"做":{"docs":{},"出":{"docs":{},"贡":{"docs":{},"献":{"docs":{},":":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"来":{"docs":{},"管":{"docs":{},"理":{"docs":{},"您":{"docs":{},"的":{"docs":{},"文":{"docs":{},"档":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}},"标":{"docs":{},"签":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"检":{"docs":{},"查":{"docs":{},"每":{"docs":{},"月":{"docs":{},"创":{"docs":{},"建":{"docs":{},"了":{"docs":{},"多":{"docs":{},"少":{"docs":{},"个":{"docs":{},"问":{"docs":{},"题":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}},"概":{"docs":{},"览":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":10.003484320557492}}}},"此":{"docs":{},"外":{"docs":{},",":{"docs":{},"在":{"docs":{},"项":{"docs":{},"目":{"docs":{},"之":{"docs":{},"间":{"docs":{},"转":{"docs":{},"移":{"docs":{},"问":{"docs":{},"题":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}},"灵":{"docs":{},"活":{"docs":{},"的":{"docs":{},"项":{"docs":{},"目":{"docs":{},"管":{"docs":{},"理":{"docs":{},"工":{"docs":{},"具":{"docs":{},"可":{"docs":{},"视":{"docs":{},"化":{"docs":{},",":{"docs":{},"确":{"docs":{},"定":{"docs":{},"优":{"docs":{},"先":{"docs":{},"级":{"docs":{},",":{"docs":{},"协":{"docs":{},"调":{"docs":{},"和":{"docs":{},"跟":{"docs":{},"踪":{"docs":{},"进":{"docs":{},"度":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"热":{"docs":{},"门":{"docs":{},"话":{"docs":{},"题":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"用":{"docs":{},"户":{"docs":{},"文":{"docs":{},"件":{"docs":{},"熟":{"docs":{},"悉":{"docs":{},"c":{"docs":{},"o":{"docs":{},"d":{"docs":{},"e":{"docs":{},"c":{"docs":{},"h":{"docs":{},"i":{"docs":{},"n":{"docs":{},"a":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}},"权":{"docs":{},"限":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"账":{"docs":{},"号":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"的":{"docs":{},"初":{"docs":{},"级":{"docs":{},"用":{"docs":{},"户":{"docs":{},",":{"docs":{},"我":{"docs":{},"们":{"docs":{},"建":{"docs":{},"议":{"docs":{},"您":{"docs":{},"从":{"docs":{},"查":{"docs":{},"看":{"docs":{},"本":{"docs":{},"文":{"docs":{},"档":{"docs":{},"开":{"docs":{},"始":{"docs":{},"学":{"docs":{},"习":{"docs":{},"如":{"docs":{},"何":{"docs":{},"使":{"docs":{},"用":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}},"新":{"docs":{},"手":{"docs":{},"吗":{"docs":{},"?":{"docs":{},"我":{"docs":{},"们":{"docs":{},"有":{"docs":{},"资":{"docs":{},"源":{"docs":{},"可":{"docs":{},"以":{"docs":{},"帮":{"docs":{},"助":{"docs":{},"您":{"docs":{},"入":{"docs":{},"门":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}},"精":{"docs":{},"华":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"看":{"docs":{},"板":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"策":{"docs":{},"略":{"docs":{},"探":{"docs":{},"索":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"管":{"docs":{},"理":{"docs":{},"员":{"docs":{},"文":{"docs":{},"件":{"docs":{},"管":{"docs":{},"理":{"docs":{},"员":{"docs":{},"入":{"docs":{},"门":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}},"您":{"docs":{},"的":{"docs":{},"帐":{"docs":{},"户":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}},"组":{"docs":{},"织":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"结":{"docs":{},"合":{"docs":{},"使":{"docs":{},"用":{"docs":{},"的":{"docs":{},"更":{"docs":{},"多":{"docs":{},"信":{"docs":{},"息":{"docs":{},":":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}},"署":{"docs":{},"名":{"docs":{},"提":{"docs":{},"交":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"草":{"docs":{},"稿":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}},"解":{"docs":{},"析":{"docs":{},"线":{"docs":{},"程":{"docs":{},",":{"docs":{},"将":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{},"中":{"docs":{},"的":{"docs":{},"线":{"docs":{},"程":{"docs":{},"移":{"docs":{},"至":{"docs":{},"问":{"docs":{},"题":{"docs":{},",":{"docs":{},"并":{"docs":{},"且":{"docs":{},"仅":{"docs":{},"在":{"docs":{},"解":{"docs":{},"决":{"docs":{},"所":{"docs":{},"有":{"docs":{},"线":{"docs":{},"程":{"docs":{},"后":{"docs":{},"才":{"docs":{},"允":{"docs":{},"许":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"计":{"docs":{},"划":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"主":{"docs":{},"题":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"阶":{"docs":{},"段":{"docs":{},"有":{"docs":{},"关":{"docs":{},":":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}},"讨":{"docs":{},"论":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}},"设":{"docs":{},"置":{"docs":{},"发":{"docs":{},"布":{"docs":{},"问":{"docs":{},"题":{"docs":{},"和":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{},"的":{"docs":{},"里":{"docs":{},"程":{"docs":{},"碑":{"docs":{},",":{"docs":{},"并":{"docs":{},"带":{"docs":{},"有":{"docs":{},"可":{"docs":{},"选":{"docs":{},"的":{"docs":{},"截":{"docs":{},"止":{"docs":{},"日":{"docs":{},"期":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"访":{"docs":{},"问":{"docs":{},"c":{"docs":{},"o":{"docs":{},"d":{"docs":{},"e":{"docs":{},"c":{"docs":{},"h":{"docs":{},"i":{"docs":{},"n":{"docs":{},"a":{"docs":{},".":{"docs":{},"c":{"docs":{},"s":{"docs":{},"d":{"docs":{},"n":{"docs":{},".":{"docs":{},"n":{"docs":{},"e":{"docs":{},"t":{"docs":{},"/":{"docs":{},"d":{"docs":{},"o":{"docs":{},"c":{"docs":{},"s":{"docs":{},",":{"docs":{},"以":{"docs":{},"获":{"docs":{},"得":{"docs":{},"优":{"docs":{},"化":{"docs":{},"的":{"docs":{},"导":{"docs":{},"航":{"docs":{},",":{"docs":{},"可":{"docs":{},"发":{"docs":{},"现":{"docs":{},"性":{"docs":{},"和":{"docs":{},"可":{"docs":{},"读":{"docs":{},"性":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"语":{"docs":{},"法":{"docs":{},"检":{"docs":{},"索":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"请":{"docs":{},"参":{"docs":{},"阅":{"docs":{},"小":{"docs":{},"组":{"docs":{},"贡":{"docs":{},"献":{"docs":{},"者":{"docs":{},"的":{"docs":{},"详":{"docs":{},"细":{"docs":{},"统":{"docs":{},"计":{"docs":{},"信":{"docs":{},"息":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}},"贡":{"docs":{},"献":{"docs":{},"者":{"docs":{},"许":{"docs":{},"可":{"docs":{},"协":{"docs":{},"议":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}},"账":{"docs":{},"号":{"docs":{},"验":{"docs":{},"证":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"户":{"docs":{},"管":{"docs":{},"理":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"跟":{"docs":{},"踪":{"docs":{},"共":{"docs":{},"享":{"docs":{},"主":{"docs":{},"题":{"docs":{},"的":{"docs":{},"问":{"docs":{},"题":{"docs":{},"组":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}},"发":{"docs":{},"行":{"docs":{},"期":{"docs":{},"限":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}},"花":{"docs":{},"费":{"docs":{},"在":{"docs":{},"问":{"docs":{},"题":{"docs":{},"和":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{},"上":{"docs":{},"的":{"docs":{},"时":{"docs":{},"间":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}},"返":{"docs":{},"回":{"docs":{},"概":{"docs":{},"览":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.0313588850174216}}}}}},"通":{"docs":{},"用":{"docs":{},"文":{"docs":{},"件":{"docs":{},"的":{"docs":{},"文":{"docs":{},"件":{"docs":{},"模":{"docs":{},"板":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}},"过":{"docs":{},"在":{"docs":{},"简":{"docs":{},"单":{"docs":{},"仪":{"docs":{},"表":{"docs":{},"板":{"docs":{},"上":{"docs":{},"显":{"docs":{},"示":{"docs":{},"的":{"docs":{},"时":{"docs":{},"间":{"docs":{},"顺":{"docs":{},"序":{"docs":{},"列":{"docs":{},"表":{"docs":{},",":{"docs":{},"跟":{"docs":{},"踪":{"docs":{},"需":{"docs":{},"要":{"docs":{},"注":{"docs":{},"意":{"docs":{},"的":{"docs":{},"工":{"docs":{},"作":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"里":{"docs":{},"程":{"docs":{},"碑":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"针":{"docs":{},"对":{"docs":{},"问":{"docs":{},"题":{"docs":{},"或":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{},"的":{"docs":{},"常":{"docs":{},"见":{"docs":{},"操":{"docs":{},"作":{"docs":{},"的":{"docs":{},"快":{"docs":{},"捷":{"docs":{},"方":{"docs":{},"式":{"docs":{},",":{"docs":{},"而":{"docs":{},"无":{"docs":{},"需":{"docs":{},"单":{"docs":{},"击":{"docs":{},"按":{"docs":{},"钮":{"docs":{},"或":{"docs":{},"在":{"docs":{},"w":{"docs":{},"e":{"docs":{},"b":{"docs":{},"界":{"docs":{},"面":{"docs":{},"中":{"docs":{},"使":{"docs":{},"用":{"docs":{},"下":{"docs":{},"拉":{"docs":{},"菜":{"docs":{},"单":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"锁":{"docs":{},"定":{"docs":{},"文":{"docs":{},"件":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"以":{"docs":{},"避":{"docs":{},"免":{"docs":{},"合":{"docs":{},"并":{"docs":{},"冲":{"docs":{},"突":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}},"镜":{"docs":{},"像":{"docs":{},"代":{"docs":{},"码":{"docs":{},"仓":{"docs":{},"库":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}},"问":{"docs":{},"题":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},",":{"docs":{},"提":{"docs":{},"交":{"docs":{},"和":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{},"中":{"docs":{},"的":{"docs":{},"线":{"docs":{},"程":{"docs":{},",":{"docs":{},"注":{"docs":{},"释":{"docs":{},"和":{"docs":{},"可":{"docs":{},"解":{"docs":{},"决":{"docs":{},"线":{"docs":{},"程":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}},"防":{"docs":{},"止":{"docs":{},"合":{"docs":{},"并":{"docs":{},"草":{"docs":{},"稿":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}},"项":{"docs":{},"目":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"和":{"docs":{},"组":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"织":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}},"问":{"docs":{},"题":{"docs":{},"并":{"docs":{},"限":{"docs":{},"制":{"docs":{},"对":{"docs":{},"问":{"docs":{},"题":{"docs":{},"的":{"docs":{},"访":{"docs":{},"问":{"docs":{},",":{"docs":{},"并":{"docs":{},"创":{"docs":{},"建":{"docs":{},"用":{"docs":{},"于":{"docs":{},"提":{"docs":{},"交":{"docs":{},"新":{"docs":{},"问":{"docs":{},"题":{"docs":{},"和":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{},"的":{"docs":{},"模":{"docs":{},"板":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"高":{"docs":{},"级":{"docs":{},"格":{"docs":{},"式":{"docs":{},"化":{"docs":{},"系":{"docs":{},"统":{"docs":{},"(":{"docs":{},"m":{"docs":{},"a":{"docs":{},"r":{"docs":{},"k":{"docs":{},"d":{"docs":{},"o":{"docs":{},"w":{"docs":{},"n":{"docs":{},")":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}}}}},",":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}},"包":{"docs":{},"括":{"docs":{},"机":{"docs":{},"密":{"docs":{},"问":{"docs":{},"题":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}},"项":{"docs":{},"目":{"docs":{},"访":{"docs":{},"问":{"docs":{},"和":{"docs":{},"设":{"docs":{},"置":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}},"发":{"docs":{},"布":{"docs":{},"和":{"docs":{},"合":{"docs":{},"并":{"docs":{},"请":{"docs":{},"求":{"docs":{},"模":{"docs":{},"板":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}},"和":{"docs":{},"移":{"docs":{},"动":{"docs":{},"的":{"docs":{},"问":{"docs":{},"题":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}},"而":{"docs":{},"不":{"docs":{},"会":{"docs":{},"中":{"docs":{},"断":{"docs":{},"您":{"docs":{},"的":{"docs":{},"工":{"docs":{},"作":{"docs":{},"流":{"docs":{},"程":{"docs":{},".":{"docs":{"docs/002.html":{"ref":"docs/002.html","tf":0.003484320557491289}}}}}}}}}}}}}}}},"length":514},"corpusTokens":["\"img\"","&&","(13.2","/","=","===","analyt","basic","burndown","ce","chart","cheat","cherri","codechina","codechina.","codechina。如果您熟悉以上两个产品中的一个或多个,您可以直接开始","codechina微信群(1)","codechina微信群(2)","codechina观察员(1)","codechina观察员(2)","codechina,您会发现以下有用信息:","codechina?","codechina?请查阅我们的便捷指南.","console.log(\"plugin","contribut","devop","e.target.tagnam","elasticsearch","epic","flow","function(e){","git","github","github,bitbucket,gitlab.com,fogbugz","gitlab","gitlab/github","gpg","guid","id","introduct","issu","jupyt","lf","markdown","merg","notebook","overview","pdf.","pick","pick.","popup....\");document.onclick","qq","request","resolut","roadmap","scrum","search","sheet","ssh","stable)","svn","thread","through","waterfall,敏捷还是会话开发,codechina","web","webid","wechat","wiki","window.open(e.target.src,e.target.src)}img{cursor:pointer}","work","workflow","上工作.","下载描述最常用的","与","中使用分支.","中的功能和概念.","中编辑文件.","为","为codechina开源做贡献","主题","了解有关使用","了解有关帐户管理的更多信息:","了解项目中的每个角色可以做什么.","产品提交","产品,在产品中我们也会为您设置帮助提示,您可以随时回来查看我们的产品文档。","从","从svn迁移","从另一个平台进入","代办事项","代码仓库","以下文档与","以下是我们推荐的一些主题:","以及将","体验使用过程中如果遇到任何问题,请与我们联系。","使用","使用内置的","使用受保护的分支.","使用新系统可能让您觉得难以入手,我们有以下文档可快速提升您的相关知识:","使用高级查询获得更具针对性的搜索结果.","保护分支","做贡献为codechina开源贡献力量!","入门,分支策略,git","全局搜索","关联","具有两因素身份验证的帐户安全性,设置您的","分支和默认分支","分析","分类问题或使用描述性标签合并请求.","分组组织您的项目.","刚开始使用git/codechina/gitlab/github?","创建主题","创建分支","创建分支,创建和上传文件以及创建目录.","创建并fork项目,以及导入项目","创建并上传文件,并创建目录","创建,复制和移动项目.","删除已合并的分支","利用","利用最佳的工作流程增强您的工作流程.","协议","可视化史诗般的时间表.","合并更改后的批量删除分支.","合并请求","合并请求管理.","和","和高级用法.","在","在提交时启动合并请求.","在整个","在本地处理合并请求","在本地处理合并请求的提示.","在特定的里程碑中观察项目的进度.","在网页中管理源代码仓库.","在问题之间建立关系.","均可简化您的协作工作流程.","基本入门","基础入门","处理合并请求","处理提交,并使用","如何在","如何在开发上做贡献.","如何在文档上做贡献.","如果您是从另一个平台进入","子组织","存储库转换为","存储库随附分支工具和访问控制,可为项目和代码的协作提供可扩展的单一事实来源.","实例上进行更快,更高级的代码搜索.","实例之间","密钥,并部署密钥以安全地访问您的项目.","对.ipynb文件的支持.","对您的提交进行签名.","对更改进行","对项目推送的附加控制.","导入项目","导入项目.","将","将源代码整合到一个易于管理和控制的分布式版本控制系统中","帮助文档","开发","开发并,目前版本提供了代码仓库管理、组织管理等基本功能,欢迎体验使用。","开始在命令行和","快捷方式","或","或看板上显示问题.","截止日期]","托管源代码,并控制项目的可见性和设置配置.","推入或拉出外部的代码仓库","推送规则","描述","提交","搜索问题,合并请求,项目,组和待办事项.","操作的","文件","文件模板","文件管理.","文档","新建","新建阶段有关:","无论您使用","时间跟踪","是","是开源的,您可以通过以下方式为我们的开源社区做出贡献:","来管理您的文档.","标签","检查每月创建了多少个问题.","概览","欢迎使用codechina代码托管平台,本产品基于","欢迎您使用codechina,如果您是","此外,在项目之间转移问题.","灵活的项目管理工具可视化,确定优先级,协调和跟踪进度.","点此向","热门话题","版本","用户文件熟悉codechina","用户权限","用户账号","的初级用户,我们建议您从查看本文档开始学习如何使用","的新手吗?我们有资源可以帮助您入门.","的精华.","看板","策略探索","管理员文件管理员入门.","管理您的帐户.","组织","结合使用的更多信息:","署名提交","联系方式","草稿合并请求","解析线程,将合并请求中的线程移至问题,并且仅在解决所有线程后才允许合并请求.","计划","计划主题","计划阶段有关:","讨论","设置发布问题和合并请求的里程碑,并带有可选的截止日期.","访问codechina.csdn.net/docs,以获得优化的导航,可发现性和可读性.","语法检索","请参阅小组贡献者的详细统计信息.","贡献者许可协议.","账号验证","账户管理","跟踪共享主题的问题组.","跟踪发行期限.","跟踪花费在问题和合并请求上的时间.","返回概览","通用文件的文件模板.","通过在简单仪表板上显示的时间顺序列表,跟踪需要注意的工作.","里程碑","针对问题或合并请求的常见操作的快捷方式,而无需单击按钮或在web界面中使用下拉菜单.","锁定文件","锁定文件以避免合并冲突.","镜像代码仓库","问题","问题,提交和合并请求中的线程,注释和可解决线程.","防止合并草稿合并请求.","项目","项目和组","项目和组织","项目问题并限制对问题的访问,并创建用于提交新问题和合并请求的模板.","高级格式化系统(markdown)",",",",包括机密问题",",包括项目访问和设置",",发布和合并请求模板",",和移动的问题",",而不会中断您的工作流程."],"pipeline":["stopWordFilter","stemmer"]},"store":{"./":{"url":"./","title":"Introduction","keywords":"","body":"CODEChina\n欢迎使用CodeChina代码托管平台,本产品基于 Gitlab CE 版本 (13.2 stable) 开发并,目前版本提供了代码仓库管理、组织管理等基本功能,欢迎体验使用。\n体验使用过程中如果遇到任何问题,请与我们联系。\n联系方式\n\n点此向 CODEChina 产品提交 issue\n\nCODEChina微信群(1)\n\nCODEChina微信群(2)\n\nCODEChina观察员(1) Wechat / QQ\n\nCODEChina观察员(2) Wechat / QQ\n\n\n\nconsole.log(\"plugin-popup....\");document.onclick = function(e){ e.target.tagName === \"IMG\" && window.open(e.target.src,e.target.src)}img{cursor:pointer}"},"docs/002.html":{"url":"docs/002.html","title":"概览","keywords":"","body":"帮助文档\n访问codechina.csdn.net/docs,以获得优化的导航,可发现性和可读性.\n概览\n欢迎您使用CODEChina,如果您是 Github 或 GitLab 的初级用户,我们建议您从查看本文档开始学习如何使用 CODEChina。如果您熟悉以上两个产品中的一个或多个,您可以直接开始 CODEChina 产品,在产品中我们也会为您设置帮助提示,您可以随时回来查看我们的产品文档。\n\n\n\n基础入门\n基本入门\n\n\n\n\n用户文件熟悉CODEChina 中的功能和概念.\n管理员文件管理员入门.\n\n\n为 CODEChina 做贡献为CODEChina开源贡献力量!\n是 Git 和 GitLab/GitHub 的新手吗?我们有资源可以帮助您入门.\n\n\n从另一个平台进入 CODEChina?请查阅我们的便捷指南.\n \n\n\n\n热门话题\n以下是我们推荐的一些主题:\n计划\n无论您使用 Waterfall,敏捷还是会话开发,CODEChina 均可简化您的协作工作流程.\n使用 CODEChina 灵活的项目管理工具可视化,确定优先级,协调和跟踪进度.\n以下文档与 DevOps 计划阶段有关:\n\n\n\n计划主题\n描述\n\n\n\n\nBurndown Charts\n在特定的里程碑中观察项目的进度.\n\n\n讨论\n问题,提交和合并请求中的线程,注释和可解决线程.\n\n\n截止日期]\n跟踪发行期限.\n\n\nEpics\n跟踪共享主题的问题组.\n\n\n问题 ,包括机密问题 ,发布和合并请求模板 ,和移动的问题\n项目问题并限制对问题的访问,并创建用于提交新问题和合并请求的模板. 此外,在项目之间转移问题.\n\n\n标签\n分类问题或使用描述性标签合并请求.\n\n\n里程碑\n设置发布问题和合并请求的里程碑,并带有可选的截止日期.\n\n\n看板\n在 Scrum 或看板上显示问题.\n\n\n快捷方式\n针对问题或合并请求的常见操作的快捷方式,而无需单击按钮或在WEB界面中使用下拉菜单.\n\n\n关联 Issue\n在问题之间建立关系.\n\n\nRoadmap\n可视化史诗般的时间表.\n\n\n时间跟踪\n跟踪花费在问题和合并请求上的时间.\n\n\n代办事项\n通过在简单仪表板上显示的时间顺序列表,跟踪需要注意的工作.\n\n\n\n返回概览\n新建\n将源代码整合到一个易于管理和控制的分布式版本控制系统中 ,而不会中断您的工作流程.\nCODEChina 存储库随附分支工具和访问控制,可为项目和代码的协作提供可扩展的单一事实来源.\n以下文档与 DevOps 新建阶段有关:\n项目和组织\n\n\n\n创建主题-项目和组\n描述\n\n\n\n\n全局搜索\n利用 Elasticsearch 在整个 CODEChina 实例上进行更快,更高级的代码搜索.\n\n\n语法检索\n使用高级查询获得更具针对性的搜索结果.\n\n\nContribution analytics\n请参阅小组贡献者的详细统计信息.\n\n\n创建并fork项目,以及导入项目 实例之间\n创建,复制和移动项目.\n\n\n锁定文件\n锁定文件以避免合并冲突.\n\n\n组织 and 子组织\n分组组织您的项目.\n\n\nIssue 分析\n检查每月创建了多少个问题.\n\n\n项目 ,包括项目访问和设置\n托管源代码,并控制项目的可见性和设置配置.\n\n\nSearch through CODEChina\n搜索问题,合并请求,项目,组和待办事项.\n\n\nWeb IDE\n在 WebIDE 中编辑文件.\n\n\nWikis\n使用内置的 Wiki 来管理您的文档.\n\n\n\n返回概览\n代码仓库\n\n\n\n创建主题-代码仓库\n描述\n\n\n\n\n分支和默认分支\n如何在 CODEChina 中使用分支.\n\n\n提交 and 署名提交\n处理提交,并使用 GPG 对您的提交进行签名.\n\n\n创建分支 , 创建并上传文件,并创建目录\n创建分支,创建和上传文件以及创建目录.\n\n\n删除已合并的分支\n合并更改后的批量删除分支.\n\n\n文件模板\n通用文件的文件模板.\n\n\n文件\n文件管理.\n\n\nJupyter Notebook 文件\n对.ipynb文件的支持.\n\n\n保护分支\n使用受保护的分支.\n\n\n推送规则\n对项目推送的附加控制.\n\n\n代码仓库\n在网页中管理源代码仓库.\n\n\n镜像代码仓库\n推入或拉出外部的代码仓库\n\n\n处理合并请求\n在提交时启动合并请求.\n\n\n\n返回概览\n合并请求\n\n\n\n创建主题-合并请求\n描述\n\n\n\n\n在本地处理合并请求\n在本地处理合并请求的提示.\n\n\nCherry-pick\n对更改进行 Cherry Pick.\n\n\nMerge request thread resolution\n解析线程,将合并请求中的线程移至问题,并且仅在解决所有线程后才允许合并请求.\n\n\n合并请求\n合并请求管理.\n\n\n草稿合并请求\n防止合并草稿合并请求.\n\n\n\n返回概览\n刚开始使用Git/CODEChina/GitLab/Github?\n使用新系统可能让您觉得难以入手,我们有以下文档可快速提升您的相关知识:\n\n\n\n主题\n描述\n\n\n\n\nBasics guides\n开始在命令行和 CODEChina 上工作.\n\n\nWorkflow overview\n利用最佳的工作流程增强您的工作流程.\n\n\nMarkdown\n高级格式化系统(Markdown)\n\n\n\n返回概览\n账户管理\n了解有关帐户管理的更多信息:\n\n\n\n主题\n描述\n\n\n\n\n用户账号\n管理您的帐户.\n\n\n账号验证\n具有两因素身份验证的帐户安全性,设置您的 SSH 密钥,并部署密钥以安全地访问您的项目.\n\n\n用户权限\n了解项目中的每个角色可以做什么.\n\n\n\n返回概览\nGit 和 CODEChina\n了解有关使用 Git 以及将 Git 与 CODEChina 结合使用的更多信息:\n\n\n\n主题\n描述\n\n\n\n\nGit\nGit 入门,分支策略,Git LFS 和高级用法.\n\n\nGit cheat sheet\n下载描述最常用的 Git 操作的 PDF.\n\n\nWork Flow\n使用 Work Flow 策略探索 Git 的精华.\n\n\n\n返回概览\n从另一个平台进入 CODEChina?\n如果您是从另一个平台进入 CODEChina,您会发现以下有用信息:\n\n\n\n主题\n描述\n\n\n\n\n导入项目\n从 GitHub,Bitbucket,GitLab.com,FogBugz 和 SVN 导入项目.\n\n\n从SVN迁移\n将 SVN 存储库转换为 Git 和 CODEChina.\n\n\n\n返回概览\n为CODEChina开源做贡献\nCODEChina 是开源的,您可以通过以下方式为我们的开源社区做出贡献:\n\n\n\n主题\n描述\n\n\n\n\n开发\n如何在开发上做贡献.\n\n\n协议\n贡献者许可协议.\n\n\n文档\n如何在文档上做贡献.\n\n\n\n返回概览\n\nconsole.log(\"plugin-popup....\");document.onclick = function(e){ e.target.tagName === \"IMG\" && window.open(e.target.src,e.target.src)}img{cursor:pointer}"}}} \ No newline at end of file diff --git a/book.json b/book.json new file mode 100644 index 0000000000000000000000000000000000000000..74a38998245d36197bba6c653dc3e5fab4a305ad --- /dev/null +++ b/book.json @@ -0,0 +1,35 @@ +{ +"plugins" : [ + "favicon", + "back-to-top-button", + "popup", + "theme-fexa" + ], + "variables": { + "themeFexa":{ + "nav":[ + { + "url":".", + "target":"_blank", + "name": "CODEChina Issue" + } + ] + } + }, + "pluginsConfig": { + "favicon": { + "shortcut": "/docs/img/logo-s.png", + "bookmark": "/docs/img/logo-s.png", + "appleTouch": "/docs/img/logo-s.png", + "appleTouchMore": { + "120x120": "", + "180x180": "/docs/img/logo-s.png" + } + }, + "theme-fexa":{ + "search-placeholder":"输入关键字搜索", + "logo":"/docs/img/logo.png", + "favicon": "" + } + } +} \ No newline at end of file diff --git a/docs/002.md b/docs/002.md index 1122695d8740b4b3e1e6d5b60e9510dc9b1156ed..e213b1693683f2f446dd821b9d56abb67745a9b6 100644 --- a/docs/002.md +++ b/docs/002.md @@ -1,397 +1,163 @@ # 帮助文档 - - -* [概览](#概览) -* [热门话题](#热门话题) -* [The entire DevOps Lifecycle](#the-entire-devops-lifecycle) - * [Manage](#manage) - * [Plan](#plan) - * [Create](#create) - * [Projects and Groups](#projects-and-groups) - * [Repositories](#repositories) - * [Merge Requests](#merge-requests) - * [Integration and Automation](#integration-and-automation) - * [Verify](#verify) - * [Package](#package) - * [Release](#release) - * [Configure](#configure) - * [Monitor](#monitor) - * [Secure](#secure) -* [New to Git and GitLab?](#new-to-git-and-gitlab) - * [User account](#user-account) - * [Git and GitLab](#git-and-gitlab) -* [Coming to GitLab from another platform](#coming-to-gitlab-from-another-platform) -* [Build an integration with GitLab](#build-an-integration-with-gitlab) -* [Contributing to GitLab](#contributing-to-gitlab) - -*访问[docs.gitlab.com,](https://docs.gitlab.com/ee/)以获得优化的导航,可发现性和可读性.* +*访问[codechina.csdn.net/docs,](codechina.csdn.net/docs)以获得优化的导航,可发现性和可读性.* ## 概览[](#overview "Permalink") -无论您如何使用 GitLab,我们都会为您提供文档. +欢迎您使用CODEChina,如果您是 Github 或 GitLab 的初级用户,我们建议您从查看本文档开始学习如何使用 CODEChina。如果您熟悉以上两个产品中的一个或多个,您可以直接开始 CODEChina 产品,在产品中我们也会为您设置帮助提示,您可以随时回来查看我们的产品文档。 -| 基本文件 | Essential documentation | +| 基础入门 | 基本入门 | | --- | --- | -| [**用户文件**](user/index.html)探索适用于 GitLab 用户的功能和概念. | [**管理员文件**](administration/index.html)GitLab 自我管理管理员需要知道的一切. | -| [**为 GitLab 做贡献**](#contributing-to-gitlab)在 GitLab,每个人都可以贡献力量! | [**是 Git 和 GitLab 的新手吗?**](#new-to-git-and-gitlab)我们有资源可以帮助您入门. | -| [**与 GitLab 建立整合?**](#build-an-integration-with-gitlab)请查阅我们的自动化和集成文档. | [**从另一个平台进入 GitLab?**](#coming-to-gitlab-from-another-platform)请查阅我们的便捷指南. | -| [**安装 GitLab**](https://about.gitlab.com/install/)不同平台的安装选项. | [**顾客**](subscriptions/index.html)给新老客户的信息. | -| [**更新 GitLab**](update/README.html)将您的 GitLab 自我管理实例更新到最新版本. | [**参考架构**](administration/reference_architectures/index.html)GitLab 的参考架构 | -| [**GitLab 发布**](https://about.gitlab.com/releases/)GitLab 的新功能. |    | +| [**用户文件**](#user/index.html)熟悉CODEChina 中的功能和概念. | [**管理员文件**](#administration/index.html)管理员入门. | +| [**为 CODEChina 做贡献**](#contributing-to-codechina)为CODEChina开源贡献力量! | [**是 Git 和 GitLab/GitHub 的新手吗?**](#new-to-git-and-gitlab-or-github)我们有资源可以帮助您入门. | +| [**从另一个平台进入 CODEChina?**](#coming-to-codechina-from-another-platform)请查阅我们的便捷指南. |  | -## 热门话题[](#popular-topics "Permalink") - -看看我们一些最受欢迎的主题: - -| 热门话题 | Description | -| --- | --- | -| [Two-factor authentication](user/profile/account/two_factor_authentication.html) | 提高您的 GitLab 帐户的安全性. | -| [GitLab groups](user/group/index.html) | 一起管理项目. | - -| [Activate GitLab EE with a license](user/admin_area/license.html) | 使用许可证激活 GitLab 企业版功能. | -| [Back up and restore GitLab](raketasks/backup_restore.html) | 用于备份和还原 GitLab 自管理实例的耙任务. | -| [GitLab release and maintenance policy](policy/maintenance.html) | 版本命名和节奏策略以及升级建议. | -| [Elasticsearch integration](integration/elasticsearch.html) | 将 Elasticsearch 与 GitLab 集成以启用高级搜索. | -| [Omnibus GitLab database settings](https://docs.gitlab.com/omnibus/settings/database.html) | Omnibus GitLab 自我管理实例的数据库设置. | -| [Omnibus GitLab NGINX settings](https://docs.gitlab.com/omnibus/settings/nginx.html) | Omnibus GitLab 自我管理实例的 NGINX 设置. | -| [Omnibus GitLab SSL configuration](https://docs.gitlab.com/omnibus/settings/ssl.html) | Omnibus GitLab 自我管理实例的 SSL 设置. | -| [GitLab.com settings](user/gitlab_com/index.html) | 用于 GitLab.com 的设置. | - - +以下是我们推荐的一些主题: -### Plan[](#plan "Permalink") +### 计划[](#plan "Permalink") -无论您使用 Waterfall,敏捷还是会话开发,GitLab 均可简化您的协作工作流程. +无论您使用 Waterfall,敏捷还是会话开发,CODEChina 均可简化您的协作工作流程. -使用 GitLab 灵活的项目管理工具可视化,确定优先级,协调和跟踪进度. +使用 CODEChina 灵活的项目管理工具可视化,确定优先级,协调和跟踪进度. 以下文档与 DevOps **计划**阶段有关: -| 计划主题 | Description | +| 计划主题 | 描述 | | --- | --- | | [Burndown Charts](user/project/milestones/burndown_charts.html) | 在特定的里程碑中观察项目的进度. | -| [Discussions](user/discussions/index.html) | 问题,提交和合并请求中的线程,注释和可解决线程. | -| [Due Dates](user/project/issues/due_dates.html) | 跟踪发行期限. | +| [讨论](user/discussions/index.html) | 问题,提交和合并请求中的线程,注释和可解决线程. | +| [截止日期]](user/project/issues/due_dates.html) | 跟踪发行期限. | | [Epics](user/group/epics/index.html) | 跟踪共享主题的问题组. | | [问题](user/project/issues/index.html) ,包括[机密问题](user/project/issues/confidential_issues.html) ,[发布和合并请求模板](user/project/description_templates.html) ,和[移动的问题](user/project/issues/managing_issues.html#moving-issues) | 项目问题并限制对问题的访问,并创建用于提交新问题和合并请求的模板. 此外,在项目之间转移问题. | -| [Labels](user/project/labels.html) | 分类问题或使用描述性标签合并请求. | -| [Milestones](user/project/milestones/index.html) | 设置发布问题和合并请求的里程碑,并带有可选的截止日期. | -| [Project Issue Board](user/project/issue_board.html) | 在 Scrum 或看板上显示问题. | -| [Quick Actions](user/project/quick_actions.html) | 针对问题或合并请求的常见操作的快捷方式,而无需单击按钮或在 GitLab 的 UI 中使用下拉菜单. | -| [Related Issues](user/project/issues/related_issues.html) | 在问题之间建立关系. | -| [Requirements Management](user/project/requirements/index.html) | Check your products against a set of criteria. | +| [标签](user/project/labels.html) | 分类问题或使用描述性标签合并请求. | +| [里程碑](user/project/milestones/index.html) | 设置发布问题和合并请求的里程碑,并带有可选的截止日期. | +| [看板](user/project/issue_board.html) | 在 Scrum 或看板上显示问题. | +| [快捷方式](user/project/quick_actions.html) | 针对问题或合并请求的常见操作的快捷方式,而无需单击按钮或在WEB界面中使用下拉菜单. | +| [关联 Issue](user/project/issues/related_issues.html) | 在问题之间建立关系. | | [Roadmap](user/group/roadmap/index.html) | 可视化史诗般的时间表. | -| [Service Desk](user/project/service_desk.html) | 一种允许人们在不需要自己的用户帐户的情况下在您的 GitLab 实例中创建问题的简单方法. | -| [Time Tracking](user/project/time_tracking.html) | 跟踪花费在问题和合并请求上的时间. | -| [Todos](user/todos.html) | 通过在简单仪表板上显示的时间顺序列表,跟踪需要注意的工作. | +| [时间跟踪](user/project/time_tracking.html) | 跟踪花费在问题和合并请求上的时间. | +| [代办事项](user/todos.html) | 通过在简单仪表板上显示的时间顺序列表,跟踪需要注意的工作. | -[Back to Overview](#overview) +[返回概览](#概览) -### Create[](#create "Permalink") +### 新建[](#create "Permalink") 将源代码整合到一个易于管理和控制的[分布式版本控制系统中](https://en.wikipedia.org/wiki/Distributed_version_control) ,而不会中断您的工作流程. -GitLab 存储库随附分支工具和访问控制,可为项目和代码的协作提供可扩展的单一事实来源. +CODEChina 存储库随附分支工具和访问控制,可为项目和代码的协作提供可扩展的单一事实来源. -以下文档与 DevOps **Create**阶段有关: +以下文档与 DevOps **新建**阶段有关: -#### Projects and Groups[](#projects-and-groups "Permalink") +#### 项目和组织[](#projects-and-groups "Permalink") -| 创建主题-项目和组 | Description | +| 创建主题-项目和组 | 描述 | | --- | --- | -| [Advanced global search](user/search/advanced_global_search.html) | 利用 Elasticsearch 在整个 GitLab 实例上进行更快,更高级的代码搜索. | -| [Advanced syntax search](user/search/advanced_search_syntax.html) | 使用高级查询获得更具针对性的搜索结果. | +| [全局搜索](user/search/advanced_global_search.html) | 利用 Elasticsearch 在整个 CODEChina 实例上进行更快,更高级的代码搜索. | +| [语法检索](user/search/advanced_search_syntax.html) | 使用高级查询获得更具针对性的搜索结果. | | [Contribution analytics](user/group/contribution_analytics/index.html) | 请参阅小组贡献者的详细统计信息. | -| [创建](gitlab-basics/create-project.html)并[派生](gitlab-basics/fork-project.html)项目,以及 -[进出口项目](user/project/settings/import_export.html) [](user/project/settings/import_export.html) [实例之间](user/project/settings/import_export.html) | 创建,复制和移动项目. | -| [File locking](user/project/file_lock.html) | 锁定文件以避免合并冲突. | -| [GitLab Pages](user/project/pages/index.html) | 使用 GitLab Pages 构建,测试和部署您的静态网站. | -| [Groups](user/group/index.html) and [Subgroups](user/group/subgroups/index.html) | 分组组织您的项目. | -| [Issues Analytics](user/group/issues_analytics/index.html) | 检查每月创建了多少个问题. | -| [项目](user/project/index.html) ,包括[项目访问](public_access/public_access.html) -和[设置](user/project/settings/index.html) | 托管源代码,并控制项目的可见性和设置配置. | -| [Search through GitLab](user/search/index.html) | 搜索问题,合并请求,项目,组和待办事项. | -| [Snippets](user/snippets.html) | 片段使您可以创建一些代码. | -| [Web IDE](user/project/web_ide/index.html) | 在 GitLab 的用户界面中编辑文件. | -| [Static Site Editor](user/project/static_site_editor/index.html) | 在静态网站上编辑内容. | -| [Wikis](user/project/wiki/index.html) | 使用内置的 Wiki 增强您的存储库文档. | - -[Back to Overview](#overview) - -#### Repositories[](#repositories "Permalink") - -| 创建主题-存储库 | Description | -| --- | --- | -| [分支](user/project/repository/branches/index.html)和[默认分支](user/project/repository/branches/index.html#default-branch) | 如何在 GitLab 中使用分支. | -| [Commits](user/project/repository/index.html#commits) and [signing commits](user/project/repository/gpg_signed_commits/index.html) | 处理提交,并使用 GPG 对您的提交进行签名. | -| [创建分支](user/project/repository/web_editor.html#create-a-new-branch) , [创建](user/project/repository/web_editor.html#create-a-file) -并[上传](user/project/repository/web_editor.html#upload-a-file)文件,并[创建目录](user/project/repository/web_editor.html#create-a-directory) | 在 GitLab 中创建分支,创建和上传文件以及创建目录. | -| [Delete merged branches](user/project/repository/branches/index.html#delete-merged-branches) | 合并更改后的批量删除分支. | -| [File templates](user/project/repository/web_editor.html#template-dropdowns) | 通用文件的文件模板. | -| [Files](user/project/repository/index.html#files) | 文件管理. | -| [Jupyter Notebook files](user/project/repository/jupyter_notebooks/index.html#jupyter-notebook-files) | GitLab 对`.ipynb`文件的支持. | -| [Protected branches](user/project/protected_branches.html) | 使用受保护的分支. | -| [Push rules](push_rules/push_rules.html) | 对项目推送的附加控制. | -| [Repositories](user/project/repository/index.html) | 在 GitLab 的用户界面中管理源代码存储库. | -| [Repository mirroring](user/project/repository/repository_mirroring.html) | 推入或拉出 GitLab 外部的存储库 | -| [Start a merge request](user/project/repository/web_editor.html#tips) | 通过 GitLab 的用户界面提交时启动合并请求. | - -[Back to Overview](#overview) - -#### Merge Requests[](#merge-requests "Permalink") - -| 创建主题-合并请求 | Description | -| --- | --- | -| [Checking out merge requests locally](user/project/merge_requests/reviewing_and_managing_merge_requests.html#checkout-merge-requests-locally) | 在本地处理合并请求的提示. | -| [Cherry-picking](user/project/merge_requests/cherry_pick_changes.html) | 使用 GitLab 进行挑剔的更改. | +| [创建](basics/create-project.html)并[fork](basics/fork-project.html)项目,以及[导入项目](user/project/settings/import_export.html) [](user/project/settings/import_export.html) [实例之间](user/project/settings/import_export.html) | 创建,复制和移动项目. | +| [锁定文件](user/project/file_lock.html) | 锁定文件以避免合并冲突. | +| [组织](user/group/index.html) and [子组织](user/group/subgroups/index.html) | 分组组织您的项目. | +| [Issue 分析](user/group/issues_analytics/index.html) | 检查每月创建了多少个问题. | +| [项目](user/project/index.html) ,包括[项目访问](public_access/public_access.html)和[设置](user/project/settings/index.html) | 托管源代码,并控制项目的可见性和设置配置. | +| [Search through CODEChina](user/search/index.html) | 搜索问题,合并请求,项目,组和待办事项. | +| [Web IDE](user/project/web_ide/index.html) | 在 WebIDE 中编辑文件. | +| [Wikis](user/project/wiki/index.html) | 使用内置的 Wiki 来管理您的文档. | + +[返回概览](#概览) + +#### 代码仓库[](#repositories "Permalink") + +| 创建主题-代码仓库 | 描述 | +| --- | --- | +| [分支](user/project/repository/branches/index.html)和[默认分支](user/project/repository/branches/index.html#default-branch) | 如何在 CODEChina 中使用分支. | +| [提交](user/project/repository/index.html#commits) and [署名提交](user/project/repository/gpg_signed_commits/index.html) | 处理提交,并使用 GPG 对您的提交进行签名. | +| [创建分支](user/project/repository/web_editor.html#create-a-new-branch) , [创建](user/project/repository/web_editor.html#create-a-file)并[上传](user/project/repository/web_editor.html#upload-a-file)文件,并[创建目录](user/project/repository/web_editor.html#create-a-directory) | 创建分支,创建和上传文件以及创建目录. | +| [删除已合并的分支](user/project/repository/branches/index.html#delete-merged-branches) | 合并更改后的批量删除分支. | +| [文件模板](user/project/repository/web_editor.html#template-dropdowns) | 通用文件的文件模板. | +| [文件](user/project/repository/index.html#files) | 文件管理. | +| [Jupyter Notebook 文件](user/project/repository/jupyter_notebooks/index.html#jupyter-notebook-files) | 对`.ipynb`文件的支持. | +| [保护分支](user/project/protected_branches.html) | 使用受保护的分支. | +| [推送规则](push_rules/push_rules.html) | 对项目推送的附加控制. | +| [代码仓库](user/project/repository/index.html) | 在网页中管理源代码仓库. | +| [镜像代码仓库](user/project/repository/repository_mirroring.html) | 推入或拉出外部的代码仓库 | +| [处理合并请求](user/project/repository/web_editor.html#tips) | 在提交时启动合并请求. | + +[返回概览](#概览) + +#### 合并请求[](#merge-requests "Permalink") + +| 创建主题-合并请求 | 描述 | +| --- | --- | +| [在本地处理合并请求](user/project/merge_requests/reviewing_and_managing_merge_requests.html#checkout-merge-requests-locally) | 在本地处理合并请求的提示. | +| [Cherry-pick](user/project/merge_requests/cherry_pick_changes.html) | 对更改进行 Cherry Pick. | | [Merge request thread resolution](user/discussions/index.html#moving-a-single-thread-to-a-new-issue) | 解析线程,将合并请求中的线程移至问题,并且仅在解决所有线程后才允许合并请求. | -| [Merge requests](user/project/merge_requests/index.html) | 合并请求管理. | -| [**Draft** merge requests](user/project/merge_requests/work_in_progress_merge_requests.html) | 防止合并草稿合并请求. | - -[Back to Overview](#overview) - -#### Integration and Automation[](#integration-and-automation "Permalink") - -| 创建主题-集成和自动化 | Description | -| --- | --- | -| [GitLab API](api/README.html) | 通过简单而强大的 API 集成 GitLab. | -| [GitLab Integration](integration/README.html) | 与 GitLab 集成多个第三方服务,以允许外部问题跟踪器和外部身份验证. | -| [GitLab Webhooks](user/project/integrations/webhooks.html) | 当新代码被推送到您的项目时,让 GitLab 通知您. | -| [Jira Development Panel](integration/jira_development_panel.html) | 请参阅 Jira 开发面板中的 GitLab 信息. | -| [Integrations](user/project/integrations/overview.html) | 将项目与外部服务(例如 CI 和聊天)集成. | -| [Trello Power-Up](integration/trello_power_up.html) | 与 GitLab 的 Trello 上电集成. | - -[Back to Overview](#overview) - -### Verify[](#verify "Permalink") - -内置的静态代码分析,代码测试,代码质量,依赖项检查和 Review Apps 可以更快地发现错误,提高安全性并缩短反馈周期. 自定义您的批准工作流控件,自动测试代码质量,并为每个代码更改启动过渡环境. - -GitLab 持续集成是最受欢迎的下一代测试系统,可以扩展以更快地运行测试. - -以下文档与 DevOps **验证**阶段有关: - -| 验证主题 | Description | -| --- | --- | -| [Code Quality reports](user/project/merge_requests/code_quality.html) | 分析源代码质量. | -| [GitLab CI/CD](ci/README.html) | 探索与 GitLab 持续集成的特​​性和功能. | -| [JUnit test reports](ci/junit_test_reports.html) | 显示有关合并请求的 JUnit 测试报告. | -| [Multi-project pipelines](ci/multi_project_pipelines.html) | 可视化跨越多个项目的整个管道,包括所有跨项目的相互依赖关系. | -| [Pipeline Graphs](ci/pipelines/index.html#visualize-pipelines) | 可视化构建. | -| [Review Apps](ci/review_apps/index.html) | 直接从合并请求预览对应用程序的更改. | - -[Back to Overview](#overview) +| [合并请求](user/project/merge_requests/index.html) | 合并请求管理. | +| [草稿合并请求](user/project/merge_requests/work_in_progress_merge_requests.html) | 防止合并草稿合并请求. | -### Package[](#package "Permalink") +[返回概览](#概览) -GitLab 软件包允许组织将 GitLab 用作各种常见软件包管理器的私有存储库. 用户能够构建和发布程序包,这些程序包可以很容易地作为下游项目中的依赖项使用. -以下文档与 DevOps **Package**阶段有关: +## 刚开始使用Git/CODEChina/GitLab/Github?[](#new-to-git-and-gitlab-or-github "Permalink") -| 套餐主题 | Description | -| --- | --- | -| [Container Registry](user/packages/container_registry/index.html) | GitLab 容器注册表使 GitLab 中的每个项目都有自己的空间来存储[Docker](https://www.docker.com/)映像. | -| [Dependency Proxy](user/packages/dependency_proxy/index.html) | GitLab 依赖代理为经常使用的上游映像/软件包设置了本地代理. | -| [Conan Repository](user/packages/conan_repository/index.html) | GitLab 柯南存储库使 GitLab 中的每个项目都有自己的空间来存储[柯南](https://conan.io/)软件包. | -| [Maven Repository](user/packages/maven_repository/index.html) | GitLab Maven 存储库使 GitLab 中的每个项目都有自己的空间来存储[Maven](https://maven.apache.org/)软件包. | -| [NPM Registry](user/packages/npm_registry/index.html) | GitLab NPM 注册表使 GitLab 中的每个项目都有自己的空间来存储[NPM](https://s0www0npmjs0com.icopy.site/)软件包. | - -[Back to Overview](#overview) - -### Release[](#release "Permalink") - -花更少的时间配置工具,而花更多的时间创建. 无论您要部署到一台服务器还是数千台服务器,都可以通过 GitLab 内置的持续交付和部署来自信,安全地构建,测试和发布代码. - -以下文档与 DevOps **发布**阶段有关: +使用新系统可能让您觉得难以入手,我们有以下文档可快速提升您的相关知识: -| 发布主题 | Description | +| 主题 | 描述 | | --- | --- | -| [Auto Deploy](topics/autodevops/stages.html#auto-deploy) | 配置 GitLab 以部署应用程序. | -| [Canary Deployments](user/project/canary_deployments.html) | 采用流行的 CI 策略,首先将机队的一小部分更新为新版本. | -| [Deploy Boards](user/project/deploy_boards.html) | 查看 Kubernetes 上运行的每个 CI 环境的当前运行状况和状态,显示部署中 Pod 的状态. | -| [Environments and deployments](ci/environments/index.html) | 借助环境,您可以控制 GitLab 中软件的连续部署. | -| [Environment-specific variables](ci/variables/README.html#limit-the-environment-scopes-of-environment-variables) | 将变量的范围限制为特定的环境. | -| [GitLab CI/CD](ci/README.html) | 探索使用 GitLab 进行持续部署和交付的功能. | -| [GitLab Pages](user/project/pages/index.html) | 直接从 GitLab 构建,测试和部署静态站点. | -| [Protected Runners](ci/runners/README.html#prevent-runners-from-revealing-sensitive-information) | 选择"运行程序"仅选择受保护的分支和标签的作业. | -| [Scheduled Pipelines](ci/pipelines/schedules.html) | 按计划执行管道. | +| [Basics guides](basics/README.html) | 开始在命令行和 CODEChina 上工作. | +| [Workflow overview]() | 利用最佳的工作流程增强您的工作流程. | +| [Markdown](user/markdown.html) | 高级格式化系统(Markdown) | -[Back to Overview](#overview) +[返回概览](#概览) -### Configure[](#configure "Permalink") +### 账户管理[](#user-account "Permalink") -使用 GitLab Auto DevOps 自动执行从构建到部署和监视的整个工作流程. 最佳实践模板可帮助您从最小到零的配置开始. 然后自定义所有内容,从构建包到 CI / CD. +了解有关帐户管理的更多信息: -以下文档与 DevOps **配置**阶段有关: - -| 配置主题 | Description | +| 主题 | 描述 | | --- | --- | -| [Auto DevOps](topics/autodevops/index.html) | 自动采用完整的 DevOps 生命周期. | -| [Create Kubernetes clusters](user/project/clusters/add_remove_clusters.html#create-new-cluster) | 使用 Kubernetes 和 GitLab | -| [Executable Runbooks](user/project/clusters/runbooks/index.html) | 记录了说明如何执行特定过程的过程. | -| [GitLab ChatOps](ci/chatops/README.html) | 通过聊天服务与 CI / CD 作业进行交互. | -| [Installing Applications](user/project/clusters/index.html#installing-applications) | 在 Kubernetes 上安装 Helm 图表,例如 Ingress 和 Prometheus. | -| [Mattermost slash commands](user/project/integrations/mattermost_slash_commands.html) | 从 Mattermost 内部启用和使用斜杠命令. | -| [Multiple Kubernetes Clusters](user/project/clusters/index.html#multiple-kubernetes-clusters) | 将多个 Kubernetes 集群关联到您的项目. | -| [Protected variables](ci/variables/README.html#protect-a-custom-variable) | 将变量限制为受保护的分支和标签. | -| [Serverless](user/project/clusters/serverless/index.html) | 在 Kubernetes 上运行无服务器工作负载. | -| [Slack slash commands](user/project/integrations/slack_slash_commands.html) | 在 Slack 中启用和使用斜杠命令. | -| [Manage your infrastructure with Terraform](user/infrastructure/index.html) | 运行 CI / CD 管道时管理基础结构. | - -[Back to Overview](#overview) +| [用户账号](user/profile/index.html) | 管理您的帐户. | +| [账号验证](topics/authentication/index.html) | 具有两因素身份验证的帐户安全性,设置您的 SSH 密钥,并部署密钥以安全地访问您的项目. | +| [用户权限](user/permissions.html) | 了解项目中的每个角色可以做什么. | -### Monitor[](#monitor "Permalink") +[返回概览](#概览) -确保您的应用程序始终响应并可用. +### Git 和 CODEChina[](#git-and-codechina "Permalink") -GitLab 收集并显示已部署应用程序的性能指标,因此您可以立即知道代码更改如何影响您的生产环境. +了解有关使用 Git 以及将 Git 与 CODEChina 结合使用的更多信息: -以下文档与 DevOps **Monitor**阶段有关: - -| 监控主题 | Description | -| --- | --- | -| [GitLab Performance Monitoring](administration/monitoring/performance/index.html) | 使用 Prometheus 和 Grafana 监视您的 GitLab 实例的性能. | -| [GitLab Prometheus](administration/monitoring/prometheus/index.html) | 配置捆绑的 Prometheus,以从您的 GitLab 实例收集各种指标. | -| [Health check](user/admin_area/monitoring/health_check.html) | GitLab provides liveness and readiness probes to indicate service health and reachability to required services. | -| [Prometheus project integration](user/project/integrations/prometheus.html) | 配置每个项目的 Prometheus 集成并监视您的 CI / CD 环境. | -| [Prometheus metrics](user/project/integrations/prometheus_library/index.html) | 让 Prometheus 从各种服务中收集指标,例如 Kubernetes,NGINX,NGINX Ingress 控制器,HAProxy 和 Amazon Cloud Watch. | -| [Incident management](user/incident_management/index.html) | 使用 GitLab 可以帮助您更好地响应系统中可能发生的事件. | - -[Back to Overview](#overview) - -### Secure[](#secure "Permalink") - -检查您的应用程序是否存在安全漏洞,这些漏洞可能导致未经授权的访问,数据泄漏和服务拒绝. GitLab 将对您的应用程序代码执行静态和动态测试,查找已知缺陷并在合并请求中报告这些缺陷,以便您可以在合并之前修复它们. 安全团队可以使用仪表板来获得项目和组的高级视图,并在需要时启动补救过程. - -以下文档与 DevOps **Secure**阶段有关: - -| 安全主题 | Description | -| --- | --- | -| [Compliance Dashboard](user/compliance/compliance_dashboard/index.html) | 查看组中的最新"合并请求"活动. | -| [Container Scanning](user/application_security/container_scanning/index.html) | 使用 Clair 扫描 Docker 映像中的已知漏洞. | -| [Dependency List](user/application_security/dependency_list/index.html) | 查看项目的依存关系及其已知漏洞. | -| [Dependency Scanning](user/application_security/dependency_scanning/index.html) | 分析您的依赖项是否存在已知漏洞. | -| [Dynamic Application Security Testing (DAST)](user/application_security/dast/index.html) | 分析运行中的 Web 应用程序是否存在已知漏洞. | -| [Group Security Dashboard](user/application_security/security_dashboard/index.html#group-security-dashboard) | 查看组及其子组中所有项目中的漏洞. | -| [Instance Security Dashboard](user/application_security/security_dashboard/index.html#instance-security-dashboard) | 查看您感兴趣的所有项目中的漏洞. | -| [License Compliance](user/compliance/license_compliance/index.html) | 在项目的依赖项中搜索其许可证. | -| [Pipeline Security](user/application_security/security_dashboard/index.html#pipeline-security) | 查看项目管道的安全报告. | -| [Project Security Dashboard](user/application_security/security_dashboard/index.html#project-security-dashboard) | 查看项目的最新安全报告. | -| [Static Application Security Testing (SAST)](user/application_security/sast/index.html) | 分析源代码中的已知漏洞. | - -## New to Git and GitLab?[](#new-to-git-and-gitlab "Permalink") - -使用新系统可能会令人生畏. - -我们有以下文档可快速提升您的 GitLab 知识: - -| Topic | Description | -| --- | --- | -| [GitLab basics guides](gitlab-basics/README.html) | 开始在命令行和 GitLab 上工作. | -| [GitLab workflow overview](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/) | 利用最佳的 GitLab 工作流程增强您的工作流程. | -| [Get started with GitLab CI/CD](ci/quick_start/README.html) | 快速实施 GitLab CI / CD. | -| [Auto DevOps](topics/autodevops/index.html) | 了解有关 GitLab Auto DevOps 的更多信息. | -| [GitLab Markdown](user/markdown.html) | GitLab 的高级格式化系统(GitLab Flavored Markdown) | - -[Back to Overview](#overview) - -### User account[](#user-account "Permalink") - -了解有关 GitLab 帐户管理的更多信息: - -| Topic | Description | -| --- | --- | -| [User account](user/profile/index.html) | 管理您的帐户. | -| [Authentication](topics/authentication/index.html) | 具有两因素身份验证的帐户安全性,设置您的 SSH 密钥,并部署密钥以安全地访问您的项目. | -| [Profile settings](user/profile/index.html#profile-settings) | 管理您的个人资料设置,两因素身份验证等. | -| [User permissions](user/permissions.html) | 了解项目中的每个角色可以做什么. | - -[Back to Overview](#overview) - -### Git and GitLab[](#git-and-gitlab "Permalink") - -了解有关使用 Git 以及将 Git 与 GitLab 结合使用的更多信息: - -| Topic | Description | +| 主题 | 描述 | | --- | --- | | [Git](topics/git/index.html) | Git 入门,分支策略,Git LFS 和高级用法. | | [Git cheat sheet](https://about.gitlab.com/images/press/git-cheat-sheet.pdf) | 下载描述最常用的 Git 操作的 PDF. | -| [GitLab Flow](topics/gitlab_flow.html) | 使用 GitLab Flow 策略探索 Git 的精华. | +| [Work Flow](topics/flow.html) | 使用 Work Flow 策略探索 Git 的精华. | -[Back to Overview](#overview) +[返回概览](#概览) -## Coming to GitLab from another platform[](#coming-to-gitlab-from-another-platform "Permalink") +## 从另一个平台进入 CODEChina?[](#coming-to-codechina-from-another-platform "Permalink") -如果您是从另一个平台进入 GitLab,您会发现以下有用信息: +如果您是从另一个平台进入 CODEChina,您会发现以下有用信息: -| Topic | Description | +| 主题 | 描述 | | --- | --- | -| [Importing to GitLab](user/project/import/index.html) | 从 GitHub,Bitbucket,GitLab.com,FogBugz 和 SVN 导入项目到 GitLab. | -| [Migrating from SVN](user/project/import/svn.html) | 将 SVN 存储库转换为 Git 和 GitLab. | +| [导入项目](user/project/import/index.html) | 从 GitHub,Bitbucket,GitLab.com,FogBugz 和 SVN 导入项目. | +| [从SVN迁移](user/project/import/svn.html) | 将 SVN 存储库转换为 Git 和 CODEChina. | -[Back to Overview](#overview) - -## Build an integration with GitLab[](#build-an-integration-with-gitlab "Permalink") - -与 GitLab 集成的方法很多,包括: - -| Topic | Description | -| --- | --- | -| [GitLab API](api/README.html) | 通过简单而强大的 API 集成 GitLab. | -| [Integrations and automation](#integration-and-automation) | 所有的 GitLab 集成和自动化选项. | +[返回概览](#概览) -[Back to Overview](#overview) -## Contributing to GitLab[](#contributing-to-gitlab "Permalink") +## 为CODEChina开源做贡献[](#contributing-to-codechina "Permalink") -GitLab 社区版是[开源的,](https://gitlab.com/gitlab-org/gitlab-foss/)而 GitLab 企业版是[开放核的](https://gitlab.com/gitlab-org/gitlab/) . +CODEChina 是开源的,您可以通过以下方式为我们的开源社区做出贡献: -了解如何通过以下资源为 GitLab 做出贡献: -| Topic | Description | +| 主题 | 描述 | | --- | --- | -| [Development](development/README.html) | 如何为 GitLab 开发做出贡献. | -| [Legal](legal/README.html) | 贡献者许可协议. | -| [Writing documentation](development/documentation/index.html) | 如何为 GitLab 文档做出贡献. | +| [开发](development/README.html) | 如何在开发上做贡献. | +| [协议](legal/README.html) | 贡献者许可协议. | +| [文档](development/documentation/index.html) | 如何在文档上做贡献. | -[Back to Overview](#overview) \ No newline at end of file +[返回概览](#概览) \ No newline at end of file diff --git a/docs/003.md b/docs/003.md new file mode 100644 index 0000000000000000000000000000000000000000..1ff4afc6e9be8753b25555b544d10175642d4abd --- /dev/null +++ b/docs/003.md @@ -0,0 +1,76 @@ +# Installation + +> 原文:[https://docs.gitlab.com/ee/install/README.html](https://docs.gitlab.com/ee/install/README.html) + +* [Requirements](#requirements) +* [Installing GitLab using the Omnibus GitLab package (recommended)](#installing-gitlab-using-the-omnibus-gitlab-package-recommended) +* [Installing GitLab on Kubernetes via the GitLab Helm charts](#installing-gitlab-on-kubernetes-via-the-gitlab-helm-charts) +* [Installing GitLab with Docker](#installing-gitlab-with-docker) +* [Installing GitLab from source](#installing-gitlab-from-source) +* [Installing GitLab on cloud providers](#installing-gitlab-on-cloud-providers) +* [Securing your GitLab installation](#securing-your-gitlab-installation) + +# Installation[](#installation-core-only "Permalink") + +GitLab 可以安装在大多数 GNU / Linux 发行版以及许多云提供商中. 为了从 GitLab 获得最佳体验,您需要在性能,可靠性,易于管理(备份,升级和故障排除)以及托管成本之间取得平衡. + +根据平台的不同,可以通过多种方式安装 GitLab: + +1. **Omnibus GitLab** :官方的 deb / rpm 软件包,包含捆绑的 GitLab 及其依赖的各种组件,例如 PostgreSQL,Redis,Sidekiq 等. +2. **GitLab Helm 图表** :用于在 Kubernetes 上安装 GitLab 及其所有组件的云原生 Helm 图表. +3. **码头**工人:Omnibus GitLab 软件包码头化. +4. **来源** :从头开始安装 GitLab 及其所有组件. + +**如有疑问,请选择 Omnibus:** Omnibus GitLab 软件包已经成熟, [可扩展,](../administration/reference_architectures/index.html)并且已在 GitLab.com 上使用. 建议向熟悉 Kubernetes 的人使用 Helm 图表. + +## Requirements[](#requirements "Permalink") + +在安装 GitLab 之前,查看系统[要求](requirements.html)至关重要. 系统要求包括有关最低硬件,软件,数据库以及支持 GitLab 的其他要求的详细信息. + +## Installing GitLab using the Omnibus GitLab package (recommended)[](#installing-gitlab-using-the-omnibus-gitlab-package-recommended "Permalink") + +Omnibus GitLab 软件包使用我们的官方 deb / rpm 存储库. 建议大多数用户使用. + +如果您需要更多的灵活性和弹性,我们建议按照[参考架构文档](../administration/reference_architectures/index.html)中的[说明](../administration/reference_architectures/index.html)部署 GitLab. + +[**> Install GitLab using the Omnibus GitLab package.**](https://about.gitlab.com/install/) + +## Installing GitLab on Kubernetes via the GitLab Helm charts[](#installing-gitlab-on-kubernetes-via-the-gitlab-helm-charts "Permalink") + +**需要 Kubernetes 经验:**我们建议您先熟悉 Kubernetes,然后再使用 Kubernetes 在生产中部署 GitLab. 管理,可观察性和某些概念的方法与传统部署不同. + +在 Kubernetes 上安装 GitLab 时,需要注意一些折衷: + +* 管理和故障排除需要 Kubernetes 知识. +* 对于较小的安装,它可能会更昂贵. 默认安装比单节点 Omnibus 部署需要更多的资源,因为大多数服务都是以冗余方式部署的. +* 有一些功能[限制需要注意](https://docs.gitlab.com/charts/) . + +[**> Install GitLab on Kubernetes using the GitLab Helm charts.**](https://docs.gitlab.com/charts/) + +## Installing GitLab with Docker[](#installing-gitlab-with-docker "Permalink") + +GitLab 基于 Omnibus GitLab 软件包维护一组正式的 Docker 映像. + +[**> Install GitLab using the official GitLab Docker images.**](docker.html) + +## Installing GitLab from source[](#installing-gitlab-from-source "Permalink") + +如果您的发行版中没有 Omnibus GitLab 软件包,则可以从源代码安装 GitLab:对于* BSD 等不受支持的系统很有用. 有关目录结构的概述,请阅读[结构文档](structure.html) . + +[**> Install GitLab from source.**](installation.html) + +## Installing GitLab on cloud providers[](#installing-gitlab-on-cloud-providers "Permalink") + +只要有云提供商支持,就可以使用上述任何一种方法将 GitLab 安装在各种云提供商上. + +* [在 AWS 上](aws/index.html)安装:使用 GitLab 提供的社区 AMI 在 AWS [上](aws/index.html)安装 Omnibus GitLab. +* [在 Google Cloud Platform 上安装 GitLab](google_cloud_platform/index.html) :在 GCP 中的 VM 上安装 Omnibus GitLab. +* [在 Azure 上](azure/index.html)安装 GitLab:从 Azure 市场安装 Omnibus GitLab. +* [在 OpenShift 上](https://docs.gitlab.com/charts/installation/cloud/openshift.html)安装 GitLab:通过使用 GitLab 的 Helm 图表在 OpenShift [上](https://docs.gitlab.com/charts/installation/cloud/openshift.html)安装 GitLab. +* [在 DC / OS 上](https://d2iq.com/blog/gitlab-dcos)安装 GitLab:通过[GitLab-Mesosphere 集成](https://about.gitlab.com/blog/2016/09/16/announcing-gitlab-and-mesosphere/)在 Mesosphere DC / OS 上安装 GitLab. +* [在 DigitalOcean 上安装 GitLab:在 DigitalOcean 上](https://about.gitlab.com/blog/2016/04/27/getting-started-with-gitlab-and-digitalocean/)安装 Omnibus GitLab. +* *仅测试!* [DigitalOcean 和 Docker Machine](digitaloceandocker.html) :使用 Docker Machine 在 DigitalOcean 上快速测试任何版本的 GitLab. + +## Securing your GitLab installation[](#securing-your-gitlab-installation "Permalink") + +完成安装后,请查看我们[建议的做法以保护您的 GitLab 实例](../security/README.html#securing-your-gitlab-installation) . \ No newline at end of file diff --git a/docs/004.md b/docs/004.md new file mode 100644 index 0000000000000000000000000000000000000000..195670cc6a4867e74e3110db9019017296083cef --- /dev/null +++ b/docs/004.md @@ -0,0 +1,245 @@ +# Requirements + +> 原文:[https://docs.gitlab.com/ee/install/requirements.html](https://docs.gitlab.com/ee/install/requirements.html) + +* [Operating Systems](#operating-systems) + * [Supported Linux distributions](#supported-linux-distributions) + * [Unsupported Linux distributions and Unix-like operating systems](#unsupported-linux-distributions-and-unix-like-operating-systems) + * [Microsoft Windows](#microsoft-windows) +* [Software requirements](#software-requirements) + * [Ruby versions](#ruby-versions) + * [Go versions](#go-versions) + * [Git versions](#git-versions) + * [Node.js versions](#nodejs-versions) +* [Redis versions](#redis-versions) +* [Hardware requirements](#hardware-requirements) + * [Storage](#storage) + * [CPU](#cpu) + * [Memory](#memory) +* [Database](#database) + * [PostgreSQL Requirements](#postgresql-requirements) + * [Additional requirements for GitLab Geo](#additional-requirements-for-gitlab-geo) +* [Puma settings](#puma-settings) + * [Puma workers](#puma-workers) + * [Puma threads](#puma-threads) +* [Unicorn Workers](#unicorn-workers) +* [Redis and Sidekiq](#redis-and-sidekiq) +* [Prometheus and its exporters](#prometheus-and-its-exporters) +* [GitLab Runner](#gitlab-runner) +* [Supported web browsers](#supported-web-browsers) + +# Requirements[](#requirements "Permalink") + +该页面包含有关受支持的操作系统以及安装和使用 GitLab 所需的硬件要求的有用信息. + +## Operating Systems[](#operating-systems "Permalink") + +### Supported Linux distributions[](#supported-linux-distributions "Permalink") + +* Ubuntu(16.04 / 18.04) +* Debian(8/9/10) +* CentOS 的(6/7/8) +* openSUSE(Leap 15.1 / Enterprise Server 12.2) +* 红帽企业版 Linux(请使用 CentOS 软件包和说明) +* 科学版 Linux(请使用 CentOS 软件包和说明) +* Oracle Linux(请使用 CentOS 软件包和说明) + +有关安装选项,请参见[主要安装页面](README.html) . + +### Unsupported Linux distributions and Unix-like operating systems[](#unsupported-linux-distributions-and-unix-like-operating-systems "Permalink") + +* Arch Linux +* Fedora +* FreeBSD +* Gentoo +* macOS + +可以在这些操作系统上安装 GitLab,但不支持. 请参阅[源安装指南](installation.html)和[安装指南](https://about.gitlab.com/install/)以获取更多信息. + +### Microsoft Windows[](#microsoft-windows "Permalink") + +GitLab 是针对基于 Linux 的操作系统开发的. 它**不能**在 Microsoft Windows 上运行,并且我们没有计划在不久的将来支持它. 有关最新的开发状态,请查看此[问题](https://gitlab.com/gitlab-org/gitlab/-/issues/22337) . 请考虑使用虚拟机运行 GitLab. + +## Software requirements[](#software-requirements "Permalink") + +### Ruby versions[](#ruby-versions "Permalink") + +GitLab 需要 Ruby(MRI)2.6\. 从 GitLab 12.2 开始,我们不再支持 Ruby 2.5 及更低版本. + +您必须使用 Ruby 的标准 MRI 实现. 我们喜欢[JRuby](https://www.jruby.org/)和[Rubinius](https://github.com/rubinius/rubinius#the-rubinius-language-platform) ,但是 GitLab 需要几个具有本机扩展的 Gems. + +### Go versions[](#go-versions "Permalink") + +所需的最低 Go 版本为 1.13. + +### Git versions[](#git-versions "Permalink") + +从 GitLab 13.1: + +* 需要 Git 2.25.x 及更高版本. +* [建议使用](https://gitlab.com/gitlab-org/gitaly/-/issues/2829) Git 2.27.x 及更高版本. + +### Node.js versions[](#nodejs-versions "Permalink") + +从 GitLab 12.9 开始,我们仅支持 node.js 10.13.0 或更高版本,并且我们放弃了对 node.js 8 的支持.(在 GitLab 11.8 中取消了对 node.js 6 的支持). + +我们建议使用 Node 12.x,因为它速度更快. + +GitLab 使用[Webpack](https://webpack.js.org/)编译前端资产,这需要最低版本的 Node.js 10.13.0. + +您可以使用`node -v`检查您正在运行哪个版本. 如果您运行的版本低于`v10.13.0` ,则需要将其更新为较新的版本. 您可以在[Node.js 网站上](https://s0nodejs0org.icopy.site/en/download/)找到从社区维护的软件包安装或从源代码进行编译的[说明](https://s0nodejs0org.icopy.site/en/download/) . + +## Redis versions[](#redis-versions "Permalink") + +GitLab 需要 Redis 5.0+. 从 GitLab 13.0 开始,不支持较低版本. + +## Hardware requirements[](#hardware-requirements "Permalink") + +### Storage[](#storage "Permalink") + +所需的硬盘空间在很大程度上取决于要存储在 GitLab 中的存储库的大小,但是根据*经验,*您应该至少具有与所有存储库加起来一样大的可用空间. + +如果您将来想灵活地增加硬盘驱动器空间,请考虑使用[逻辑卷管理(LVM)进行](https://en.wikipedia.org/wiki/Logical_volume_management)安装,以便在需要时可以添加更多硬盘驱动器. + +除本地硬盘驱动器外,您还可以安装支持网络文件系统(NFS)协议的卷. 该卷可能位于文件服务器,网络连接存储(NAS)设备,存储区域网络(SAN)或 Amazon Web Services(AWS)弹性块存储(EBS)卷上. + +如果您有足够的 RAM 和最新的 CPU,则 GitLab 的速度主要受硬盘搜索时间限制. 具有快速驱动器(7200 RPM 及更高版本)或固态驱动器(SSD)将提高 GitLab 的响应速度. + +**注意:**由于文件系统性能可能会影响 GitLab 的整体性能,因此[我们不建议使用 AWS EFS 进行存储](../administration/high_availability/nfs.html#avoid-using-awss-elastic-file-system-efs) . + +### CPU[](#cpu "Permalink") + +CPU 需求取决于用户数量和预期的工作量. 您的确切需求可能更多,具体取决于您的工作量. 您的工作负载受以下因素影响,这些因素包括但不限于:用户的活跃程度,使用的自动化程度,镜像和回购/更改大小. + +以下是一些示例 GitLab 用户库大小的建议最低 CPU 硬件指南. + +* **4 芯**是核心的**推荐**最小数目和多达 500 个用户支持 +* 8 个内核最多支持 1000 个用户 +* 更多用户? 查阅[参考架构页面](../administration/reference_architectures/index.html) + +### Memory[](#memory "Permalink") + +内存需求取决于用户数量和预期的工作量. 您的确切需求可能更多,具体取决于您的工作量. 您的工作负载受以下因素影响,这些因素包括但不限于:用户的活跃程度,使用的自动化程度,镜像和回购/更改大小. + +以下是一些示例 GitLab 用户库大小的建议最低内存硬件指南. + +* **4GB RAM**是**必需的**最小内存大小,最多可支持 500 个用户 + * 我们的[内存团队](https://about.gitlab.com/handbook/engineering/development/enablement/memory/)正在努力减少内存需求. +* 8GB RAM 最多支持 1000 个用户 +* 更多用户? 查阅[参考架构页面](../administration/reference_architectures/index.html) + +除上述之外,即使您当前有足够的可用 RAM,我们通常也建议在服务器上至少有 2GB 的交换空间. 如果您的可用内存发生更改,那么进行交换将有助于减少发生错误的机会. 我们还建议将内核的 swappiness 设置配置为较低的值(例如`10`以充分利用您的 RAM,同时在需要时仍可使用交换功能. + +## Database[](#database "Permalink") + +PostgreSQL 是唯一受支持的数据库,与 Omnibus GitLab 软件包捆绑在一起. 您也可以使用[外部 PostgreSQL 数据库](https://docs.gitlab.com/omnibus/settings/database.html) . 在 GitLab 12.1 中删除了对 MySQL 的支持. 建议在 MySQL / MariaDB 上使用 GitLab 的现有用户在升级之前[迁移到 PostgreSQL](../update/mysql_to_postgresql.html) . + +### PostgreSQL Requirements[](#postgresql-requirements "Permalink") + +运行 PostgreSQL 的服务器应*至少有* 5-10 GB 的可用存储空间,尽管确切的要求[取决于用户数量](../administration/reference_architectures/index.html) . + +我们强烈建议用户使用下面指定的最低 PostgreSQL 版本,因为这些是用于开发和测试的版本. + +| GitLab 版本 | 最低 PostgreSQL 版本 | +| --- | --- | +| 10.0 | 9.6 | +| 12.10 | 11 | +| 13.0 | 11 | + +您还必须确保将`pg_trgm`扩展加载到每个 GitLab 数据库中. [可以](https://s0www0postgresql0org.icopy.site/docs/11/sql-createextension.html)使用 PostgreSQL 超级用户[启用](https://s0www0postgresql0org.icopy.site/docs/11/sql-createextension.html)此扩展. + +在某些系统上,您可能需要安装一个附加软件包(例如`postgresql-contrib` ),此扩展才可以使用. + +**注意:** [在 GitLab 13.0 中已删除了](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#postgresql-11-is-now-the-minimum-required-version-to-install-gitlab)对[PostgreSQL 9.6 和 10 的](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#postgresql-11-is-now-the-minimum-required-version-to-install-gitlab)支持,因此 GitLab 可以从 PostgreSQL 11 的改进(例如分区)中受益. 有关过渡到 PostgreSQL 12 的时间表,请参阅[相关的 epic](https://gitlab.com/groups/gitlab-org/-/epics/2184) . + +#### Additional requirements for GitLab Geo[](#additional-requirements-for-gitlab-geo "Permalink") + +如果您使用的是[GitLab Geo](../administration/geo/replication/index.html) : + +* 我们强烈建议您在积极开发和测试的情况下运行由 Omnibus 管理的实例. 我们的目标是与大多数外部数据库(不由 Omnibus 管理)兼容(例如, [AWS Relational Database Service(RDS)](https://aws.amazon.com/rds/) ),但我们不保证兼容性. +* 您还必须确保将`postgres_fdw`扩展加载到每个 GitLab 数据库中. [可以](https://s0www0postgresql0org.icopy.site/docs/11/sql-createextension.html)使用 PostgreSQL 超级用户[启用](https://s0www0postgresql0org.icopy.site/docs/11/sql-createextension.html)此扩展. + +## Puma settings[](#puma-settings "Permalink") + +建议的 Puma 设置取决于运行它的基础结构. Omnibus GitLab 默认为建议的 Puma 设置. 无论安装方法如何,都可以调整 Puma 设置. + +如果您使用的是 Omnibus GitLab,请参阅[Puma 设置](https://docs.gitlab.com/omnibus/settings/puma.html)以获取有关更改 Puma 设置的说明. 如果您使用的是 GitLab Helm 图表,请参阅[Webservice 图表](https://docs.gitlab.com/charts/charts/gitlab/webservice/index.html) . + +### Puma workers[](#puma-workers "Permalink") + +推荐的工人人数是根据以下最高者计算得出的: + +* `2` +* CPU 核心数-1 + +例如,一个具有 4 个核心的节点应配置 3 个 Puma Worker. + +如果可以提供足够的 CPU 和内存容量,则可以增加 Puma worker 的数量. 数量更多的 Puma 工作人员通常将有助于减少应用程序的响应时间并提高处理并行请求的能力. 您必须执行测试以验证基础架构的最佳设置. + +### Puma threads[](#puma-threads "Permalink") + +推荐的线程数取决于几个因素,包括总内存和[传统 Rugged 代码的使用](../development/gitaly.html#legacy-rugged-code) . + +* 如果操作系统最多具有 2 GB 的内存,则建议的线程数为`1` . 较高的值将导致过多的交换,并降低性能. +* If legacy Rugged code is in use, the recommended number of threads is `1`. +* 在所有其他情况下,建议的线程数为`4` . 由于[Ruby MRI 多线程的](https://en.wikipedia.org/wiki/Global_interpreter_lock)工作方式,我们不建议设置更高的值. + +## Unicorn Workers[](#unicorn-workers "Permalink") + +对于大多数情况,我们建议使用:(CPU 内核* 1.5)+ 1 = Unicorn worker. 例如,一个具有 4 个核心的节点将有 7 个 Unicorn worker. + +对于所有 2GB 以上的计算机,我们建议至少三名 Unicorn 工人. 如果您有一台 1GB 的计算机,我们建议仅配置两个 Unicorn worker,以防止过度交换. + +只要您有足够的可用 CPU 和内存容量,就可以增加 Unicorn worker 的数量,这通常将有助于减少应用程序的响应时间并提高处理并行请求的能力. + +要在拥有 Omnibus 软件包(默认为上述建议)时更改 Unicorn worker,请参阅[Omnibus GitLab 文档中的 Unicorn 设置](https://docs.gitlab.com/omnibus/settings/unicorn.html) . + +## Redis and Sidekiq[](#redis-and-sidekiq "Permalink") + +Redis 存储所有用户会话和后台任务队列. Redis 的存储要求极低,每个用户大约 25kB. Sidekiq 使用多线程进程来处理后台作业. 此过程从整个 Rails 堆栈(200MB +)开始,但是由于内存泄漏,它可能随着时间的推移而增长. 在非常活跃的服务器(10,000 个活跃用户)上,Sidekiq 进程可以使用 1GB +的内存. + +## Prometheus and its exporters[](#prometheus-and-its-exporters "Permalink") + +从 Omnibus GitLab 9.0 起,默认启用[Prometheus](https://s0prometheus0io.icopy.site)及其相关出口商,以实现对 GitLab 的轻松和深度监控. 使用默认设置,这些进程将消耗大约 200MB 的内存. + +如果您想禁用 Prometheus 及其出口商或阅读有关它的更多信息,请查阅[Prometheus 文档](../administration/monitoring/prometheus/index.html) . + +## GitLab Runner[](#gitlab-runner "Permalink") + +强烈建议不要在打算安装 GitLab 的同一台计算机上安装 GitLab Runner. 根据您决定配置 GitLab Runner 的方式以及用于在 CI 环境中运行应用程序的工具的不同,GitLab Runner 会消耗大量可用内存. + +如果您决定在同一台计算机上运行 GitLab Runner 和 GitLab Rails 应用程序,则上面提供的内存消耗计算将无效. + +由于[安全原因](https://docs.gitlab.com/runner/security/) ,将所有内容都安装在一台机器上也不安全,尤其是当您计划将 Shell executor 与 GitLab Runner 一起使用时. + +如果您打算使用 CI 功能,我们建议为每个 GitLab Runner 使用单独的机器. GitLab Runner 服务器要求取决于: + +* 您在 GitLab Runner 上配置的[执行程序](https://docs.gitlab.com/runner/executors/)的类型. +* 运行构建作业所需的资源. +* 作业并发设置. + +由于作业的性质因每个用例而异,因此您将需要通过调整作业并发来进行实验以获得最佳设置. + +作为参考,对 GitLab.com 的[自动缩放共享](../user/gitlab_com/index.html#shared-runners)运行器进行了配置,以便**单个作业**将在**单个实例中**运行,并具有: + +* 1vCPU. +* 3.75GB 的 RAM. + +## Supported web browsers[](#supported-web-browsers "Permalink") + +**警告:**在 GitLab 13.0(2020 年 5 月)中,我们删除了对 Internet Explorer 11 的官方支持.在 GitLab 13.4 发行版(2020 年 9 月)中,我们将删除了所有支持 Internet Explorer 11 的代码.您可以提供[有关此问题的](https://gitlab.com/gitlab-org/gitlab/-/issues/197987)反馈[,](https://gitlab.com/gitlab-org/gitlab/-/issues/197987)也可以通过通常的支持渠道. + +GitLab supports the following web browsers: + +* [Mozilla Firefox](https://www.mozilla.org/en-US/firefox/new/) +* [Google Chrome](https://www.google.com/chrome/) +* [Chromium](https://www.chromium.org/getting-involved/dev-channel) +* [Apple Safari](https://www.apple.com/safari/) +* [Microsoft Edge](https://www.microsoft.com/en-us/edge) + +对于列出的 Web 浏览器,GitLab 支持: + +* 当前和以前的主要浏览器版本(Internet Explorer 除外). +* 受支持的主要版本的当前次要版本. + +**注意:**我们不支持在浏览器中禁用 JavaScript 的情况下运行 GitLab,并且将来也没有支持该计划的计划,因为我们具有诸如 Issue Boards 之类的功能,这些功能广泛需要 JavaScript. \ No newline at end of file diff --git a/docs/005.md b/docs/005.md new file mode 100644 index 0000000000000000000000000000000000000000..0b8423e6516d336a1fee5bc0b1837fdb766a6dc5 --- /dev/null +++ b/docs/005.md @@ -0,0 +1 @@ +> 原文:[https://about.gitlab.com/install/](https://about.gitlab.com/install/) \ No newline at end of file diff --git a/docs/006.md b/docs/006.md new file mode 100644 index 0000000000000000000000000000000000000000..f9d6aa3fc2263d2d747eeecfbbe0b4d004d4ed61 --- /dev/null +++ b/docs/006.md @@ -0,0 +1,181 @@ +# GitLab cloud native Helm Chart + +> 原文:[https://docs.gitlab.com/charts/](https://docs.gitlab.com/charts/) + +* [Introduction](#introduction) +* [Limitations](#limitations) +* [GitLab Helm chart quick start guide](#gitlab-helm-chart-quick-start-guide) +* [Troubleshooting](#troubleshooting) +* [Installation](#installation) + * [Global settings](#global-settings) + * [Complete properties list](#complete-properties-list) +* [Upgrading](#upgrading) +* [Uninstall](#uninstall) +* [Advanced](#advanced) + * [Advanced Configuration](#advanced-configuration) + * [Migrate from Omnibus GitLab to Kubernetes](#migrate-from-omnibus-gitlab-to-kubernetes) +* [Architecture](#architecture) +* [Development](#development) + * [GitLab version mappings](#gitlab-version-mappings) + * [Contributing](#contributing) + +# GitLab cloud native Helm Chart[](#gitlab-cloud-native-helm-chart "Permalink") + +这是在云本机环境上安装 GitLab 的官方,推荐和受支持的方法. + +**注意:**不必在 Kubernetes 上安装 GitLab 即可使用[GitLab Kubernetes 集成](https://docs.gitlab.com/ee/user/project/clusters/) . + +## Introduction[](#introduction "Permalink") + +The `gitlab/gitlab` chart is the best way to operate GitLab on Kubernetes. This chart contains all the required components to get started, and can scale to large deployments. + +该图表包括完整的体验所需的所有组件,但是每个部分都可以单独安装. + +* GitLab 核心组件: + * [NGINX 入口](charts/nginx/index.html) + * [登记处](charts/registry/index.html) + * [亚搏体育 app](charts/gitlab/gitaly/index.html) / [Gitaly](charts/gitlab/gitaly/index.html) + * GitLab / [GitLab 出口商](charts/gitlab/gitlab-exporter/index.html) + * GitLab / [GitLab Grafana](charts/gitlab/gitlab-grafana/index.html) + * GitLab / [GitLab 外壳](charts/gitlab/gitlab-shell/index.html) + * GitLab / [迁移](charts/gitlab/migrations/index.html) + * [亚搏体育 app](charts/gitlab/sidekiq/index.html) / [Sidekiq](charts/gitlab/sidekiq/index.html) + * GitLab / [web 服务](charts/gitlab/webservice/index.html) +* 可选依赖项: + * [PostgreSQL 的](https://hub.helm.sh/charts/bitnami/postgresql) + * [雷迪斯](https://hub.helm.sh/charts/bitnami/redis) + * [MinIO](charts/minio/index.html) +* 可选的补充: + * [普罗米修斯](https://hub.helm.sh/charts/stable/prometheus) + * [格拉法纳](https://hub.helm.sh/charts/stable/grafana) + * 使用 Kubernetes 执行器的[*非特权*](https://docs.gitlab.com/runner/install/kubernetes.html) [GitLab Runner](https://docs.gitlab.com/runner/) + * 使用[Jetstack](https://www.jetstack.io/)的[cert-manager](https://cert-manager.io/docs/)通过[Let's Encrypt](https://letsencrypt.org/)自动提供 SSL + +## Limitations[](#limitations "Permalink") + +使用 Helm 图表当前无法使用 GitLab 的某些功能: + +* [GitLab Pages](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/37) +* [Smartcard authentication](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/988) + +数据库限制: + +* GitLab Geo 功能[需要使用外部数据库服务](installation/deployment.html#postgresql) . + +## GitLab Helm chart quick start guide[](#gitlab-helm-chart-quick-start-guide "Permalink") + +对于那些希望在*非生产*用例中尽快建立并运行这些图表的人,我们提供了概念验证(PoC)部署[快速入门指南](quickstart/index.html) . + +本指南将通过部署这些图表使用默认值和功能引导用户,但*不*符合生产做好准备的要求. 如果希望在持续负载下将这些图表部署到生产中,则应遵循以下完整的[安装指南](#installation) . + +## Troubleshooting[](#troubleshooting "Permalink") + +我们已尽力使这些图表尽可能地无缝,但偶尔也会出现无法控制的问题. 我们已收集了一些常见问题的疑难解答技巧. 在提出[问题](https://gitlab.com/gitlab-org/charts/gitlab/-/issues)之前,请先检查这些内容,并通过提出[合并请求](https://gitlab.com/gitlab-org/charts/gitlab/-/merge_requests)随意添加它们! + +See [Troubleshooting](troubleshooting/index.html). + +## Installation[](#installation "Permalink") + +`gitlab/gitlab`图表包含所有必需的依赖项. 在生产中,您可能需要启用可选功能或[高级配置](#advanced-configuration) . 本指南深入介绍了这些图表的所有选项和功能. + +如果您只是想部署概念验证进行测试,我们强烈建议您遵循我们的[快速入门](#gitlab-helm-chart-quick-start-guide)进行第一次迭代. + +1. [Preparation](installation/index.html) +2. [Deployment](installation/deployment.html) + +### Global settings[](#global-settings "Permalink") + +这些图表的复杂性使其可以使用全局属性. 有许多通用全局设置适用于多个图表. 有关不同的全局配置值及其应用程序的详细信息,请参见[Globals 文档](charts/globals.html) . + +### Complete properties list[](#complete-properties-list "Permalink") + +经常要求我们将所有可能的属性表直接放入此索引. 这些图表是规模*庞大* ,并作为属性的这种数量超过背景的量,我们在这里很舒服配售. 请参阅我们(几乎) [全面的属性和默认值列表](installation/command-line-options.html) . + +## Upgrading[](#upgrading "Permalink") + +安装了 GitLab 图表后,应使用`helm upgrade`完成配置更改和图表更新: + +``` +helm repo add gitlab https://charts.gitlab.io/ +helm repo update +helm get values gitlab > gitlab.yaml +helm upgrade gitlab gitlab/gitlab -f gitlab.yaml +``` + +有关更多详细信息,请参阅[升级](installation/upgrade.html) . + +## Uninstall[](#uninstall "Permalink") + +要卸载 GitLab Chart,请运行以下命令: + +``` +helm uninstall gitlab +``` + +**注意:**在 Helm v2 中,您需要使用`helm delete --purge gitlab`命令. + +为了连续起见,这些图表具有一些在执行`helm uninstall`时不会删除的 Kubernetes 对象. 这些是我们要求您有*意识地*删除的项目,因为它们会影响您应选择的重新部署. + +* 用于状态数据的 PVC,必须*自觉*删除 + * Gitaly:这是您的存储库数据. + * PostgreSQL(如果内部):这是您的元数据. + * Redis(如果内部):这是缓存和作业队列,可以安全地将其删除. +* 机密(如果由我们的共享机密工作生成). 这些图表旨在避免直接通过 Helm 生成 Kubernetes 秘密. 因此,Helm 无法删除它们. 它们包含密码,加密机密等.它们不应被恶意破坏. +* ConfigMaps + * `ingress-controller-leader-RELEASE-nginx` :这是由 NGINX Ingress 控制器本身生成的,不在我们图表的控制范围内. 可以安全地将其删除. + +PVC 和秘密将设置`release`标签,因此您可以通过以下方式找到它们: + +``` +kubectl get pvc,secret -lrelease=gitlab +``` + +## Advanced[](#advanced "Permalink") + +除了在云本机环境中进行 GitLab 的基本部署以外,还可以进行更复杂的配置. 本节为需要进一步计划的任务提供指导,例如大规模部署或从 Omnibus GitLab 迁移. + +### Advanced Configuration[](#advanced-configuration "Permalink") + +高级和大规模部署具有利用外部服务,扩展功能和备用提供程序的能力. + +高级配置示例: + +* 亚搏体育 app Geo +* 外部对象存储提供者 +* 外部 PostgreSQL,Redis,Gitaly +* 外部入口提供商 + +See [Advanced Configuration](advanced/index.html). + +### Migrate from Omnibus GitLab to Kubernetes[](#migrate-from-omnibus-gitlab-to-kubernetes "Permalink") + +可以从[Omnibus GitLab](https://docs.gitlab.com/omnibus/)迁移到这些图表. 这样做通常需要将现有数据迁移到对象存储,因此是[高级配置](advanced/index.html) . + +要将现有的 Omnibus GitLab 实例迁移到这些图表,请遵循[迁移文档](installation/migration/index.html) . + +## Architecture[](#architecture "Permalink") + +这些图表非常复杂,因为它们可以协调整个应用程序套件的部署. 我们提供有关目标,结构,设计决策和资源消耗的[文档](architecture/index.html) . + +## Development[](#development "Permalink") + +对于那些有兴趣为这些图表做出贡献的人,我们提供了涵盖该项目工作范围的开发指南. 它们可以在[开发中](development/index.html) . + +### GitLab version mappings[](#gitlab-version-mappings "Permalink") + +GitLab 图表与 GitLab 本身的版本号不同. 预计可能需要在图表中引入一些重大更改,这些更改可能会导致重大版本颠簸,而对这些更改的要求可能会完全阻止这些图表上的其他开发,直到完成为止. + +要快速查看它们映射到的`gitlab`图表版本和 GitLab 版本的完整列表,请对[Helm](installation/tools.html#helm)发出以下命令: + +``` +helm repo add gitlab https://charts.gitlab.io/ +helm search repo -l gitlab/gitlab +``` + +**注意**对于 Helm v2,搜索命令将为`helm search -l gitlab/gitlab` + +有关更多信息,请访问[版本映射 docs](installation/version_mappings.html) . + +### Contributing[](#contributing "Permalink") + +除了我们的[贡献准则](https://gitlab.com/gitlab-org/charts/gitlab/tree/master/CONTRIBUTING.md)之外,请参阅[开发者文档](development/index.html)以了解如何对 GitLab 图表[做出贡献](https://gitlab.com/gitlab-org/charts/gitlab/tree/master/CONTRIBUTING.md) . \ No newline at end of file diff --git a/docs/007.md b/docs/007.md new file mode 100644 index 0000000000000000000000000000000000000000..1465da9585ee471ca3bd3eaed42a06e3ea53ff7d --- /dev/null +++ b/docs/007.md @@ -0,0 +1,26 @@ +# Install GitLab with Docker + +> 原文:[https://docs.gitlab.com/ee/install/docker.html](https://docs.gitlab.com/ee/install/docker.html) + +* [Omnibus GitLab based images](#omnibus-gitlab-based-images) +* [Cloud native images](#cloud-native-images) + +# Install GitLab with Docker[](#install-gitlab-with-docker "Permalink") + +在过去的几年中, [Docker](https://www.docker.com)和容器技术一直在改变软件世界. 它们将本地执行的性能和效率与虚拟化的抽象性,安全性和不变性结合在一起. + +GitLab 提供了官方的 Docker 映像,使您可以在操作 GitLab 实例时轻松利用容器化的优势. + +## Omnibus GitLab based images[](#omnibus-gitlab-based-images "Permalink") + +GitLab 基于我们的[Omnibus GitLab 软件包](https://docs.gitlab.com/omnibus/README.html)维护了一组[正式的 Docker 映像](https://hub.docker.com/u/gitlab) . 这些图像包括: + +* [GitLab Community Edition](https://hub.docker.com/r/gitlab/gitlab-ce/) +* [GitLab Enterprise Edition](https://hub.docker.com/r/gitlab/gitlab-ee/) +* [GitLab Runner](https://hub.docker.com/r/gitlab/gitlab-runner/) + +提供了有关这些映像的[完整用法指南](https://docs.gitlab.com/omnibus/docker/) ,以及[用于构建映像](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/docker)的[Dockerfile](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/docker) . + +## Cloud native images[](#cloud-native-images "Permalink") + +manbetx 客户端打不开也正在努力向[容器](https://docs.gitlab.com/charts/)的[云本机集,](https://docs.gitlab.com/charts/)每个组件服务具有单个映像. 我们打算将这些图像最终替换为[基于 Omnibus GitLab 的图像](#omnibus-gitlab-based-images) . \ No newline at end of file diff --git a/docs/008.md b/docs/008.md new file mode 100644 index 0000000000000000000000000000000000000000..6d91a29ea7ca76107f3c10e1534839edf4189a68 --- /dev/null +++ b/docs/008.md @@ -0,0 +1,1010 @@ +# Installation from source + +> 原文:[https://docs.gitlab.com/ee/install/installation.html](https://docs.gitlab.com/ee/install/installation.html) + +* [Consider the Omnibus package installation](#consider-the-omnibus-package-installation) +* [Select a version to install](#select-a-version-to-install) +* [GitLab directory structure](#gitlab-directory-structure) +* [Overview](#overview) +* [1\. Packages and dependencies](#1-packages-and-dependencies) +* [2\. Ruby](#2-ruby) +* [3\. Go](#3-go) +* [4\. Node](#4-node) +* [5\. System users](#5-system-users) +* [6\. Database](#6-database) +* [7\. Redis](#7-redis) +* [8\. GitLab](#8-gitlab) + * [Clone the Source](#clone-the-source) + * [Configure It](#configure-it) + * [Configure GitLab DB Settings](#configure-gitlab-db-settings) + * [Install Gems](#install-gems) + * [Install GitLab Shell](#install-gitlab-shell) + * [Install GitLab Workhorse](#install-gitlab-workhorse) + * [Install GitLab-Elasticsearch-indexer on Enterprise Edition](#install-gitlab-elasticsearch-indexer-on-enterprise-edition) + * [Install GitLab Pages](#install-gitlab-pages) + * [Install Gitaly](#install-gitaly) + * [Start Gitaly](#start-gitaly) + * [Initialize Database and Activate Advanced Features](#initialize-database-and-activate-advanced-features) + * [Secure secrets.yml](#secure-secretsyml) + * [Install Init Script](#install-init-script) + * [Set up Logrotate](#set-up-logrotate) + * [Check Application Status](#check-application-status) + * [Compile GetText PO files](#compile-gettext-po-files) + * [Compile Assets](#compile-assets) + * [Start Your GitLab Instance](#start-your-gitlab-instance) +* [9\. NGINX](#9-nginx) + * [Installation](#installation) + * [Site Configuration](#site-configuration) + * [Test Configuration](#test-configuration) + * [Restart](#restart) +* [Post-install](#post-install) + * [Double-check Application Status](#double-check-application-status) + * [Initial Login](#initial-login) +* [Advanced Setup Tips](#advanced-setup-tips) + * [Relative URL support](#relative-url-support) + * [Using HTTPS](#using-https) + * [Enable Reply by email](#enable-reply-by-email) + * [LDAP Authentication](#ldap-authentication) + * [Using Custom OmniAuth Providers](#using-custom-omniauth-providers) + * [Build your projects](#build-your-projects) + * [Adding your Trusted Proxies](#adding-your-trusted-proxies) + * [Custom Redis Connection](#custom-redis-connection) + * [Custom SSH Connection](#custom-ssh-connection) + * [Additional Markup Styles](#additional-markup-styles) + * [Using Unicorn](#using-unicorn) + * [Using Sidekiq instead of Sidekiq Cluster](#using-sidekiq-instead-of-sidekiq-cluster) +* [Troubleshooting](#troubleshooting) + * [“You appear to have cloned an empty repository.”](#you-appear-to-have-cloned-an-empty-repository) + * [`google-protobuf` “LoadError: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14’ not found”](#google-protobuf-loaderror-libx86_64-linux-gnulibcso6-version-glibc_214-not-found) + +# Installation from source[](#installation-from-source "Permalink") + +这是使用源文件设置生产 GitLab 服务器的官方安装指南. 要设置**开发安装**或许多其他安装选项,请参见[主要安装页面](README.html) . 它是为**Debian / Ubuntu**操作系统创建并经过测试的. 有关硬件和操作系统[要求](requirements.html) ,请阅读 requirements.md. 如果要在 RHEL / CentOS 上安装,我们建议使用[Omnibus 软件包](https://about.gitlab.com/install/) . + +本指南之所以冗长,是因为它涵盖了许多情况,并且包括您需要的所有命令,这是[实际上可以立即使用的少数安装脚本之一](https://twitter.com/robinvdvleuten/status/424163226532986880) . 已知以下步骤有效. **偏离**本指南**时请多加注意** . 确保您没有违反任何有关 GitLab 对其环境的假设. 例如,许多人遇到权限问题,因为他们更改了目录的位置或以错误的用户身份运行服务. + +如果您在本指南中发现错误/错误, **请**按照[提供帮助的指南](https://gitlab.com/gitlab-org/gitlab/blob/master/CONTRIBUTING.md) **提交合并请求** . + +## Consider the Omnibus package installation[](#consider-the-omnibus-package-installation "Permalink") + +由于从源头进行安装需要大量工作并且容易出错,因此我们强烈建议您快速,可靠地[安装 Omnibus 软件包](https://about.gitlab.com/install/) (deb / rpm). + +Omnibus 软件包更可靠的原因之一是它使用 runit 来重新启动任何 GitLab 进程,以防万一崩溃. 在频繁使用的 GitLab 实例上,Sidekiq 后台工作程序的内存使用量会随着时间增长. + +Omnibus 软件包通过[使 Sidekiq](../administration/operations/sidekiq_memory_killer.html)在使用过多内存的情况下[正常终止来](../administration/operations/sidekiq_memory_killer.html)解决此问题. 在此终止后,runit 将检测到 Sidekiq 没有运行并启动它. 由于从源头进行的安装不使用 runit 进行过程监视,因此 Sidekiq 无法终止,并且其内存使用量会随着时间的推移而增长. + +## Select a version to install[](#select-a-version-to-install "Permalink") + +确保从您要安装的 GitLab 的分支(版本)中查看[此安装指南](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/install/installation.md) (例如`11-7-stable` ). 您可以在 GitLab 左上角的版本下拉菜单中选择分支(位于菜单栏下方). + +如果不清楚最高数目的稳定分支,请查看[GitLab 博客](https://about.gitlab.com/blog/)以获取版本信息. + +## GitLab directory structure[](#gitlab-directory-structure "Permalink") + +这是主要的目录结构,您将按照此页面的说明进行操作: + +``` +|-- home +| |-- git +| |-- .ssh +| |-- gitlab +| |-- gitlab-shell +| |-- repositories +``` + +* `/home/git/.ssh`包含 OpenSSH 设置. 具体来说,由 GitLab Shell 管理的`authorized_keys`文件. +* `/home/git/gitlab` -GitLab 核心软件. +* `/home/git/gitlab-shell` -GitLab 的核心附加组件. 维护 SSH 克隆和其他功能. +* `/home/git/repositories`按名称空间组织的所有项目的裸存储库. 这是为所有项目维护推/拉的 Git 存储库的地方. **该区域包含项目的关键数据.** **[保持备份](../raketasks/backup_restore.html) .** + +**注意:**可以在 GitLab 的`config/gitlab.yml`和 GitLab Shell 的`config.yml`中`config/gitlab.yml`存储库的默认位置. + +有关更深入的概述,请参阅[GitLab 体系结构文档](../development/architecture.html) . + +## Overview[](#overview "Permalink") + +GitLab 安装包括设置以下组件: + +1. [Packages and dependencies](#1-packages-and-dependencies). +2. [Ruby](#2-ruby). +3. [Go](#3-go). +4. [Node](#4-node). +5. [System users](#5-system-users). +6. [Database](#6-database). +7. [Redis](#7-redis). +8. [GitLab](#8-gitlab). +9. [NGINX](#9-nginx). + +## 1\. Packages and dependencies[](#1-packages-and-dependencies "Permalink") + +默认情况下,Debian 上未安装`sudo` . 确保您的系统是最新的并安装. + +``` +# run as root! +apt-get update -y +apt-get upgrade -y +apt-get install sudo -y +``` + +**注意:**在此安装过程中,将需要手动编辑某些文件. 如果您熟悉 vim,请使用以下命令将其设置为默认编辑器. 如果您不熟悉 vim,请跳过此步骤并继续使用默认编辑器. + +``` +# Install vim and set as default editor +sudo apt-get install -y vim +sudo update-alternatives --set editor /usr/bin/vim.basic +``` + +安装所需的软件包(需要编译 Ruby 和 Ruby gem 的本机扩展): + +``` +sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libre2-dev \ + libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev \ + libxslt-dev libcurl4-openssl-dev libicu-dev logrotate rsync python-docutils pkg-config cmake \ + runit +``` + +Ubuntu 14.04(Trusty `libre2-dev` )没有可用的`libre2-dev`软件包,但您可以[手动安装 re2](https://github.com/google/re2/wiki/Install) . + +如果要使用 Kerberos 进行用户身份验证,请安装`libkrb5-dev` : + +``` +sudo apt-get install libkrb5-dev +``` + +**注意:**如果您不知道 Kerberos 是什么,则可以假定您不需要它. + +确保您安装了正确的 Git 版本: + +``` +# Install Git +sudo apt-get install -y git-core + +# Make sure Git is version 2.27.0 or higher (minimal supported version is 2.25.0) +git --version +``` + +从 GitLab 12.0 开始,需要使用`libpcre2`编译 Git. 找出是否是这种情况: + +``` +ldd $(command -v git) | grep pcre2 +``` + +输出应包含`libpcre2-8.so.0` . + +系统打包的 Git 是否过旧,或者未使用 pcre2 编译? 去掉它: + +``` +sudo apt-get remove git-core +``` + +在 Ubuntu 上, [从其官方 PPA](https://git-scm.com/download/linux)安装 Git: + +``` +# run as root! +add-apt-repository ppa:git-core/ppa +apt update +apt install git +# repeat libpcre2 check as above +``` + +在 Debian 上,使用以下编译说明: + +``` +# Install dependencies +sudo apt-get install -y libcurl4-openssl-dev libexpat1-dev gettext libz-dev libssl-dev build-essential + +# Download and compile pcre2 from source +curl --silent --show-error --location https://ftp.pcre.org/pub/pcre/pcre2-10.33.tar.gz --output pcre2.tar.gz +tar -xzf pcre2.tar.gz +cd pcre2-10.33 +chmod +x configure +./configure --prefix=/usr --enable-jit +make +sudo make install + +# Download and compile from source +cd /tmp +curl --remote-name --location --progress https://www.kernel.org/pub/software/scm/git/git-2.27.0.tar.gz +echo '77ded85cbe42b1ffdc2578b460a1ef5d23bcbc6683eabcafbb0d394dffe2e787 git-2.27.0.tar.gz' | shasum -a256 -c - && tar -xzf git-2.27.0.tar.gz +cd git-2.27.0/ +./configure --with-libpcre +make prefix=/usr/local all + +# Install into /usr/local/bin +sudo make prefix=/usr/local install + +# When editing config/gitlab.yml later, change the git -> bin_path to /usr/local/bin/git +``` + +为了使[自定义图标](../user/admin_area/appearance.html#favicon)能够正常工作,需要安装 GraphicsMagick. + +``` +sudo apt-get install -y graphicsmagick +``` + +**注意:**为了接收邮件通知,请确保安装邮件服务器. 默认情况下,Debian 随 exim4 一起提供,但这[会带来问题,](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/12754)而 Ubuntu 则没有. 推荐的邮件服务器是 postfix,您可以使用以下命令进行安装: + +``` +sudo apt-get install -y postfix +``` + +然后选择" Internet Site",然后按 Enter 确认主机名. + +[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse#dependencies)需要使用`exiftool`才能从上传的图像中删除 EXIF 数据. + +``` +sudo apt-get install -y libimage-exiftool-perl +``` + +## 2\. Ruby[](#2-ruby "Permalink") + +运行 GitLab 需要使用 Ruby 解释器. + +**注意:**当前支持的 Ruby(MRI)版本是 2.6.x. GitLab 12.2 放弃了对 Ruby 2.5.x 的支持. + +在生产环境[中将](https://github.com/rbenv/rbenv) Ruby 版本管理器(如[RVM](https://rvm.io/) , [rbenv](https://github.com/rbenv/rbenv)或[chruby)](https://github.com/postmodern/chruby)与 GitLab [一起](https://github.com/postmodern/chruby)使用通常会导致难以诊断问题. 不支持版本管理器,我们强烈建议所有人按照以下说明使用系统 Ruby. + +Linux 发行版通常提供较旧版本的 Ruby,因此这些说明旨在从官方源代码安装 Ruby. + +删除旧的 Ruby 1.8(如果存在): + +``` +sudo apt-get remove ruby1.8 +``` + +下载 Ruby 并进行编译: + +``` +mkdir /tmp/ruby && cd /tmp/ruby +curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.6.tar.gz +echo '2d78048e293817f38d4ede4ebc7873013e97bb0b ruby-2.6.6.tar.gz' | shasum -c - && tar xzf ruby-2.6.6.tar.gz +cd ruby-2.6.6 + +./configure --disable-install-rdoc +make +sudo make install +``` + +然后安装 Bundler gem(低于 2.x 的版本): + +``` +sudo gem install bundler --no-document --version '< 2' +``` + +## 3\. Go[](#3-go "Permalink") + +从 GitLab 8.0 开始,GitLab 有几个用 Go 编写的守护程序. 要安装 GitLab,我们需要一个 Go 编译器. 以下说明假定您使用 64 位 Linux. 您可以在[Go 下载页面上](https://s0golang0org.icopy.site/dl)找到其他平台的[下载](https://s0golang0org.icopy.site/dl) . + +``` +# Remove former Go installation folder +sudo rm -rf /usr/local/go + +curl --remote-name --progress https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz +echo '512103d7ad296467814a6e3f635631bd35574cab3369a97a323c9a585ccaa569 go1.13.5.linux-amd64.tar.gz' | shasum -a256 -c - && \ + sudo tar -C /usr/local -xzf go1.13.5.linux-amd64.tar.gz +sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/ +rm go1.13.5.linux-amd64.tar.gz +``` + +## 4\. Node[](#4-node "Permalink") + +从 GitLab 8.17 开始,GitLab 需要使用 Node 来编译 JavaScript 资产,并使用 Yarn 来管理 JavaScript 依赖项. 当前的最低要求是: + +* `node` > = v10.13.0\. (我们建议使用节点 12.x,因为它速度更快) +* `yarn` > = v1.10.0. + +在许多发行版中,官方软件包存储库提供的版本已经过时,因此我们需要通过以下命令进行安装: + +``` +# install node v12.x +curl --location https://deb.nodesource.com/setup_12.x | sudo bash - +sudo apt-get install -y nodejs + +curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list +sudo apt-get update +sudo apt-get install yarn +``` + +如果您对这些步骤有任何疑问,请访问[node](https://s0nodejs0org.icopy.site/en/download/package-manager/)和[yarn](https://classic.yarnpkg.com/en/docs/install/)的官方网站. + +## 5\. System users[](#5-system-users "Permalink") + +为 GitLab 创建一个`git`用户: + +``` +sudo adduser --disabled-login --gecos 'GitLab' git +``` + +## 6\. Database[](#6-database "Permalink") + +**注意:**从 GitLab 12.1 开始,仅支持 PostgreSQL. 从 GitLab 13.0 开始,我们需要 PostgreSQL 11+. + +1. 安装数据库软件包: + + ``` + sudo apt-get install -y postgresql postgresql-client libpq-dev postgresql-contrib + ``` + +2. 启动 PostgreSQL 服务并确认该服务正在运行: + + ``` + sudo service postgresql start + sudo service postgresql status + ``` + +3. 为 GitLab 创建数据库用户: + + ``` + sudo -u postgres psql -d template1 -c "CREATE USER git CREATEDB;" + ``` + +4. 创建`pg_trgm`扩展(GitLab 8.6+必需): + + ``` + sudo -u postgres psql -d template1 -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;" + ``` + +5. 创建 GitLab 生产数据库并授予该数据库的所有特权: + + ``` + sudo -u postgres psql -d template1 -c "CREATE DATABASE gitlabhq_production OWNER git;" + ``` + +6. 尝试使用新用户连接到新数据库: + + ``` + sudo -u git -H psql -d gitlabhq_production + ``` + +7. 检查是否启用了`pg_trgm`扩展名: + + ``` + SELECT true AS enabled + FROM pg_available_extensions + WHERE name = 'pg_trgm' + AND installed_version IS NOT NULL; + ``` + + 如果启用了扩展名,将产生以下输出: + + ``` + enabled + --------- + t + (1 row) + ``` + +8. 退出数据库会话: + + ``` + gitlabhq_production> \q + ``` + +## 7\. Redis[](#7-redis "Permalink") + +GitLab 至少需要 Redis 5.0. + +如果您使用的是 Debian 10 或 Ubuntu 20.04 及更高版本,则可以使用以下命令安装 Redis 5.0: + +``` +sudo apt-get install redis-server +``` + +完成后,您可以配置 Redis: + +``` +# Configure redis to use sockets +sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.orig + +# Disable Redis listening on TCP by setting 'port' to 0 +sudo sed 's/^port .*/port 0/' /etc/redis/redis.conf.orig | sudo tee /etc/redis/redis.conf + +# Enable Redis socket for default Debian / Ubuntu path +echo 'unixsocket /var/run/redis/redis.sock' | sudo tee -a /etc/redis/redis.conf + +# Grant permission to the socket to all members of the redis group +echo 'unixsocketperm 770' | sudo tee -a /etc/redis/redis.conf + +# Create the directory which contains the socket +sudo mkdir -p /var/run/redis +sudo chown redis:redis /var/run/redis +sudo chmod 755 /var/run/redis + +# Persist the directory which contains the socket, if applicable +if [ -d /etc/tmpfiles.d ]; then echo 'd /var/run/redis 0755 redis redis 10d -' | sudo tee -a /etc/tmpfiles.d/redis.conf +fi + +# Activate the changes to redis.conf +sudo service redis-server restart + +# Add git to the redis group +sudo usermod -aG redis git +``` + +## 8\. GitLab[](#8-gitlab "Permalink") + +``` +# We'll install GitLab into the home directory of the user "git" +cd /home/git +``` + +### Clone the Source[](#clone-the-source "Permalink") + +克隆社区版: + +``` +# Clone GitLab repository +sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-foss.git -b X-Y-stable gitlab +``` + +克隆企业版: + +``` +# Clone GitLab repository +sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ee.git -b X-Y-stable gitlab +``` + +确保用与要安装的版本匹配的稳定分支替换`XY-stable` . 例如,如果要安装 11.8,则可以使用分支名称`11-8-stable` . + +**注意:**您可以更改`XY-stable` ,以`master` ,如果你想最*前沿*的版本,但从来没有安装`master`在生产服务器上! + +### Configure It[](#configure-it "Permalink") + +``` +# Go to GitLab installation folder +cd /home/git/gitlab + +# Copy the example GitLab config +sudo -u git -H cp config/gitlab.yml.example config/gitlab.yml + +# Update GitLab config file, follow the directions at top of the file +sudo -u git -H editor config/gitlab.yml + +# Copy the example secrets file +sudo -u git -H cp config/secrets.yml.example config/secrets.yml +sudo -u git -H chmod 0600 config/secrets.yml + +# Make sure GitLab can write to the log/ and tmp/ directories +sudo chown -R git log/ +sudo chown -R git tmp/ +sudo chmod -R u+rwX,go-w log/ +sudo chmod -R u+rwX tmp/ + +# Make sure GitLab can write to the tmp/pids/ and tmp/sockets/ directories +sudo chmod -R u+rwX tmp/pids/ +sudo chmod -R u+rwX tmp/sockets/ + +# Create the public/uploads/ directory +sudo -u git -H mkdir -p public/uploads/ + +# Make sure only the GitLab user has access to the public/uploads/ directory +# now that files in public/uploads are served by gitlab-workhorse +sudo chmod 0700 public/uploads + +# Change the permissions of the directory where CI job logs are stored +sudo chmod -R u+rwX builds/ + +# Change the permissions of the directory where CI artifacts are stored +sudo chmod -R u+rwX shared/artifacts/ + +# Change the permissions of the directory where GitLab Pages are stored +sudo chmod -R ug+rwX shared/pages/ + +# Copy the example Puma config +sudo -u git -H cp config/puma.rb.example config/puma.rb + +# Refer to https://github.com/puma/puma#configuration for more information. +# You should scale Puma workers and threads based on the number of CPU +# cores you have available. You can get that number via the `nproc` command. +sudo -u git -H editor config/puma.rb + +# Copy the example Rack attack config +sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb + +# Configure Git global settings for git user +# 'autocrlf' is needed for the web editor +sudo -u git -H git config --global core.autocrlf input + +# Disable 'git gc --auto' because GitLab already runs 'git gc' when needed +sudo -u git -H git config --global gc.auto 0 + +# Enable packfile bitmaps +sudo -u git -H git config --global repack.writeBitmaps true + +# Enable push options +sudo -u git -H git config --global receive.advertisePushOptions true + +# Enable fsyncObjectFiles to reduce risk of repository corruption if the server crashes +sudo -u git -H git config --global core.fsyncObjectFiles true + +# Configure Redis connection settings +sudo -u git -H cp config/resque.yml.example config/resque.yml + +# Change the Redis socket path if you are not using the default Debian / Ubuntu configuration +sudo -u git -H editor config/resque.yml +``` + +**注意:**请确保同时编辑`gitlab.yml`和`puma.rb`以匹配您的设置. 如果要使用 Unicorn Web 服务器,请参阅" [使用 Unicorn"](#using-unicorn)以了解其他步骤.**注意:**如果要使用 HTTPS,请参阅" [使用 HTTPS"](#using-https)以了解其他步骤. + +### Configure GitLab DB Settings[](#configure-gitlab-db-settings "Permalink") + +``` +sudo -u git cp config/database.yml.postgresql config/database.yml + +# Remove host, username, and password lines from config/database.yml. +# Once modified, the `production` settings will be as follows: +# +# production: +# adapter: postgresql +# encoding: unicode +# database: gitlabhq_production +# pool: 10 +# +sudo -u git -H editor config/database.yml + +# Remote PostgreSQL only: +# Update username/password in config/database.yml. +# You only need to adapt the production settings (first part). +# If you followed the database guide then please do as follows: +# Change 'secure password' with the value you have given to $password +# You can keep the double quotes around the password +sudo -u git -H editor config/database.yml + +# Make config/database.yml readable to git only +sudo -u git -H chmod o-rwx config/database.yml +``` + +### Install Gems[](#install-gems "Permalink") + +**注意:**从 Bundler 1.5.2 开始,您可以调用`bundle install -jN` (其中`N`是您的处理器内核数)并享受并行 gem 的安装,其完成时间有可衡量的差异(快 60%). 使用`nproc`检查您的内核数. 有关更多信息,请参见这篇[文章](https://thoughtbot.com/blog/parallel-gem-installing-using-bundler) . + +确保您有`bundle` (运行`bundle -v` ): + +* `>= 1.5.2` ,因为某些[问题](https://devcenter.heroku.com/changelog-items/411)已在 1.5.2 中[修复](https://github.com/rubygems/bundler/pull/2817) . +* `< 2.x`. + +``` +sudo -u git -H bundle install --deployment --without development test mysql aws kerberos +``` + +**注意:**如果要使用 Kerberos 进行用户身份验证,请在上面的`--without`选项中省略`kerberos` . + +### Install GitLab Shell[](#install-gitlab-shell "Permalink") + +GitLab Shell 是专门为 GitLab 开发的 SSH 访问和存储库管理软件. + +``` +# Run the installation task for gitlab-shell: +sudo -u git -H bundle exec rake gitlab:shell:install RAILS_ENV=production + +# By default, the gitlab-shell config is generated from your main GitLab config. +# You can review (and modify) the gitlab-shell config as follows: +sudo -u git -H editor /home/git/gitlab-shell/config.yml +``` + +**注意:**如果要使用 HTTPS,请参阅" [使用 HTTPS"](#using-https)以了解其他步骤.**注意:**确保您的主机名可以通过正确的 DNS 记录或`/etc/hosts`的其他行(" 127.0.0.1 主机名")在计算机上解析. 例如,如果您在反向代理后面设置了 GitLab,则可能有必要. 如果无法解析主机名,则最终安装检查将失败,并具有`Check GitLab API access: FAILED. code: 401` `Check GitLab API access: FAILED. code: 401`和推送提交将通过`[remote rejected] master -> master (hook declined)` . + +### Install GitLab Workhorse[](#install-gitlab-workhorse "Permalink") + +GitLab-Workhorse 使用[GNU Make](https://www.gnu.org/software/make/) . 以下命令行将在建议的位置`/home/git/gitlab-workhorse`安装 GitLab-Workhorse. + +``` +sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production +``` + +您可以通过提供其他参数来指定其他 Git 存储库: + +``` +sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse,https://example.com/gitlab-workhorse.git]" RAILS_ENV=production +``` + +### Install GitLab-Elasticsearch-indexer on Enterprise Edition[](#install-gitlab-elasticsearch-indexer-on-enterprise-edition "Permalink") + +GitLab-Elasticsearch-Indexer 使用[GNU Make](https://www.gnu.org/software/make/) . 以下命令行将在推荐位置`/home/git/gitlab-elasticsearch-indexer`中安装 GitLab-Elasticsearch-Indexer. + +``` +sudo -u git -H bundle exec rake "gitlab:indexer:install[/home/git/gitlab-elasticsearch-indexer]" RAILS_ENV=production +``` + +您可以通过提供其他参数来指定其他 Git 存储库: + +``` +sudo -u git -H bundle exec rake "gitlab:indexer:install[/home/git/gitlab-elasticsearch-indexer,https://example.com/gitlab-elasticsearch-indexer.git]" RAILS_ENV=production +``` + +首先将源代码提取到第一个参数指定的路径. 然后,将在其`bin`目录下构建一个二进制文件. 然后,您将需要更新`gitlab.yml`的`production -> elasticsearch -> indexer_path`设置以指向该二进制文件. + +**注意:** Elasticsearch 是 GitLab 企业版的一项功能,不包含在 GitLab 社区版中. + +### Install GitLab Pages[](#install-gitlab-pages "Permalink") + +GitLab Pages 使用[GNU Make](https://www.gnu.org/software/make/) . 此步骤是可选的,仅当您希望在 GitLab 中托管静态站点时才需要. 以下命令将在`/home/git/gitlab-pages`安装 GitLab `/home/git/gitlab-pages` . 有关其他设置步骤,请查阅适用于您的 GitLab 版本的[管理指南](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/pages/source.md) ,因为 GitLab Pages 守护程序可以通过几种不同的方式运行. + +``` +cd /home/git +sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-pages.git +cd gitlab-pages +sudo -u git -H git checkout v$(> $gitlab_path/log/gitaly.log 2>&1 &" +``` + +### Initialize Database and Activate Advanced Features[](#initialize-database-and-activate-advanced-features "Permalink") + +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production +# Type 'yes' to create the database tables. + +# or you can skip the question by adding force=yes +sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production force=yes + +# When done, you see 'Administrator account created:' +``` + +**注意:**您可以通过分别在环境变量`GITLAB_ROOT_PASSWORD`和`GITLAB_ROOT_EMAIL`提供管理员/ root 密码和电子邮件来设置它们,如下所示. 如果您未设置密码(并且密码已设置为默认密码),请等待 GitLab 暴露在公共互联网上,直到安装完成并且您已首次登录服务器. 首次登录时,将被迫更改默认密码. 通过在`GITLAB_LICENSE_FILE`环境变量中提供完整路径,此时也可以安装 Enterprise Edition 许可证. + +``` +sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=yourpassword GITLAB_ROOT_EMAIL=youremail GITLAB_LICENSE_FILE="/path/to/license" +``` + +### Secure secrets.yml[](#secure-secretsyml "Permalink") + +`secrets.yml`文件存储会话和安全变量的加密密钥. 备份`secrets.yml`安全保存,但是请不要将其与数据库备份存储在同一位置. 否则,如果其中一个备份遭到破坏,您的秘密就会暴露出来. + +### Install Init Script[](#install-init-script "Permalink") + +下载初始化脚本(将为`/etc/init.d/gitlab` ): + +``` +sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab +``` + +而且,如果要使用非默认文件夹或用户安装,请复制并编辑默认文件: + +``` +sudo cp lib/support/init.d/gitlab.default.example /etc/default/gitlab +``` + +如果将 GitLab 安装在其他目录中或以默认用户以外的用户身份安装,则应在`/etc/default/gitlab`更改这些设置. 不要编辑`/etc/init.d/gitlab`因为它将在升级时更改. + +使 GitLab 在启动时启动: + +``` +sudo update-rc.d gitlab defaults 21 +``` + +### Set up Logrotate[](#set-up-logrotate "Permalink") + +``` +sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab +``` + +### Check Application Status[](#check-application-status "Permalink") + +检查 GitLab 及其环境是否配置正确: + +``` +sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production +``` + +### Compile GetText PO files[](#compile-gettext-po-files "Permalink") + +``` +sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production +``` + +### Compile Assets[](#compile-assets "Permalink") + +``` +sudo -u git -H yarn install --production --pure-lockfile +sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production +``` + +如果`rake`因`JavaScript heap out of memory`不足错误而失败,请尝试按如下所示设置`NODE_OPTIONS`来运行它. + +``` +sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production NODE_OPTIONS="--max_old_space_size=4096" +``` + +### Start Your GitLab Instance[](#start-your-gitlab-instance "Permalink") + +``` +sudo service gitlab start +# or +sudo /etc/init.d/gitlab restart +``` + +## 9\. NGINX[](#9-nginx "Permalink") + +**注意:** NGINX 是 GitLab 官方支持的 Web 服务器. 如果您不能或不想将 NGINX 用作 Web 服务器,请参阅[GitLab 配方](https://gitlab.com/gitlab-org/gitlab-recipes/) . + +### Installation[](#installation "Permalink") + +``` +sudo apt-get install -y nginx +``` + +### Site Configuration[](#site-configuration "Permalink") + +复制示例站点配置: + +``` +sudo cp lib/support/nginx/gitlab /etc/nginx/sites-available/gitlab +sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab +``` + +确保编辑配置文件以匹配您的设置. 另外,请确保您与 GitLab 的路径匹配,尤其是在为`git`用户以外的用户安装时: + +``` +# Change YOUR_SERVER_FQDN to the fully-qualified +# domain name of your host serving GitLab. +# +# Remember to match your paths to GitLab, especially +# if installing for a user other than 'git'. +# +# If using Ubuntu default nginx install: +# either remove the default_server from the listen line +# or else sudo rm -f /etc/nginx/sites-enabled/default +sudo editor /etc/nginx/sites-available/gitlab +``` + +如果您打算启用 GitLab 页面,则需要使用一个单独的 NGINX 配置. 在[GitLab 页面管理指南中](../administration/pages/index.html)阅读有关所需配置的所有信息. + +**注意:**如果要使用 HTTPS,请将`gitlab` NGINX 配置替换为`gitlab-ssl` . 有关 HTTPS 配置的详细信息,请参见[使用 HTTPS](#using-https) . + +### Test Configuration[](#test-configuration "Permalink") + +使用以下命令验证`gitlab`或`gitlab-ssl` NGINX 配置文件: + +``` +sudo nginx -t +``` + +您应该会收到`syntax is okay`并且`test is successful`消息. 如果收到错误,请按照给出的错误消息中的说明检查`gitlab`或`gitlab-ssl` NGINX 配置文件是否有错别字等. + +**注意:**通过运行`nginx -v`验证安装的版本是否大于 1.12.1\. 如果它较低,您可能会收到以下错误: `nginx: [emerg] unknown "start$temp=[filtered]$rest" variable nginx: configuration file /etc/nginx/nginx.conf test failed` + +### Restart[](#restart "Permalink") + +``` +sudo service nginx restart +``` + +## Post-install[](#post-install "Permalink") + +### Double-check Application Status[](#double-check-application-status "Permalink") + +为了确保您不会错过任何东西,请使用以下命令进行更彻底的检查: + +``` +sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production +``` + +如果所有项目均为绿色,则恭喜您成功安装了 GitLab! + +向`gitlab:check`提供`SANITIZE=true`环境变量,以从 check 命令的输出中省略项目名称. + +### Initial Login[](#initial-login "Permalink") + +在您的 Web 浏览器中访问 YOUR_SERVER 进行首次 GitLab 登录. + +如果[在设置过程中](#initialize-database-and-activate-advanced-features)未[提供 root 密码,](#initialize-database-and-activate-advanced-features)则将重定向到密码重置屏幕,以提供初始管理员帐户的密码. 输入所需的密码,您将被重定向回登录屏幕. + +默认帐户的用户名是**root** . 提供您先前创建的密码并登录. 登录后,您可以根据需要更改用户名. + +**Enjoy!** + +You can use `sudo service gitlab start` and `sudo service gitlab stop` to start and stop GitLab. + +## Advanced Setup Tips[](#advanced-setup-tips "Permalink") + +### Relative URL support[](#relative-url-support "Permalink") + +有关如何使用相对 URL 配置 GitLab 的更多信息,请参见[相对 URL 文档](relative_url.html) . + +### Using HTTPS[](#using-https "Permalink") + +要将 GitLab 与 HTTPS 一起使用: + +1. In `gitlab.yml`: + 1. 将第 1 节中的`port`选项设置为`443` . + 2. 将第 1 节中的`https`选项设置为`true` . +2. 在 GitLab Shell 的`config.yml`中: + 1. 将`gitlab_url`选项设置为 GitLab 的 HTTPS 端点(例如`https://git.example.com` ). + 2. 使用`ca_file`或`ca_path`选项设置证书. +3. 使用`gitlab-ssl` NGINX 示例配置,而不是`gitlab`配置. + 1. 更新`YOUR_SERVER_FQDN` . + 2. 更新`ssl_certificate`和`ssl_certificate_key` . + 3. 查看配置文件,并考虑应用其他安全性和性能增强功能. + +不鼓励使用自签名证书,但如果必须使用它,请遵循正常说明. 然后: + +1. 生成自签名 SSL 证书: + + ``` + mkdir -p /etc/nginx/ssl/ + cd /etc/nginx/ssl/ + sudo openssl req -newkey rsa:2048 -x509 -nodes -days 3560 -out gitlab.crt -keyout gitlab.key + sudo chmod o-r gitlab.key + ``` + +2. 在 GitLab Shell 的`config.yml` ,将`self_signed_cert`设置为`true` . + +### Enable Reply by email[](#enable-reply-by-email "Permalink") + +有关如何进行此设置的更多信息,请参见["通过电子邮件答复"文档](../administration/reply_by_email.html) . + +### LDAP Authentication[](#ldap-authentication "Permalink") + +您可以在`config/gitlab.yml`配置 LDAP 身份验证. 编辑此文件后,重新启动 GitLab. + +### Using Custom OmniAuth Providers[](#using-custom-omniauth-providers "Permalink") + +请参阅[OmniAuth 集成文档](../integration/omniauth.html) . + +### Build your projects[](#build-your-projects "Permalink") + +GitLab 可以构建您的项目. 要启用该功能,您需要 GitLab Runners 为您执行此操作. 请参阅[GitLab Runner 部分](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/#gitlab-runner)进行安装. + +### Adding your Trusted Proxies[](#adding-your-trusted-proxies "Permalink") + +如果要在单独的计算机上使用反向代理,则可能要将代理添加到"受信任的代理"列表中. 否则,用户将显示为从代理的 IP 地址登录. + +您可以通过自定义第 1 节中的`trusted_proxies`选项在`config/gitlab.yml`添加受信任的代理.保存文件并[重新配置 GitLab,](../administration/restart_gitlab.html)以使更改生效. + +### Custom Redis Connection[](#custom-redis-connection "Permalink") + +如果您想通过非标准端口或其他主机连接到 Redis 服务器,则可以通过`config/resque.yml`文件配置其连接字符串. + +``` +# example +production: + url: redis://redis.example.tld:6379 +``` + +如果要通过套接字连接 Redis 服务器,请使用" unix:" URL 方案以及`config/resque.yml`文件中 Redis 套接字文件的路径. + +``` +# example +production: + url: unix:/path/to/redis/socket +``` + +另外,您可以在`config/resque.yml`文件中使用环境变量: + +``` +# example +production: + url: <%= ENV.fetch('GITLAB_REDIS_URL') %> +``` + +### Custom SSH Connection[](#custom-ssh-connection "Permalink") + +如果您在非标准端口上运行 SSH,则必须更改 GitLab 用户的 SSH 配置. + +``` +# Add to /home/git/.ssh/config +host localhost # Give your setup a name (here: override localhost) + user git # Your remote git user + port 2222 # Your port number + hostname 127.0.0.1; # Your server name or IP +``` + +您还需要在`config\gitlab.yml`文件中更改相应的选项(例如`ssh_user` , `ssh_host` , `admin_uri` ). + +### Additional Markup Styles[](#additional-markup-styles "Permalink") + +除了始终支持的 Markdown 样式外,GitLab 还可以显示其他富文本文件. 但是您可能必须安装依赖项才能这样做. 有关更多信息,请参见[`github-markup` gem 自述文件](https://github.com/gitlabhq/markup#markups) . + +### Using Unicorn[](#using-unicorn "Permalink") + +从 GitLab 12.9 开始, [Puma](https://github.com/puma/puma)已取代 Unicorn 成为默认源安装 Web 服务器. 如果要切换回独角兽,请按照下列步骤操作: + +1. 完成 GitLab 设置,以使其启动并运行. +2. 将提供的示例 Unicorn 配置文件复制到位: + + ``` + cd /home/git/gitlab + + # Copy config file for the web server + sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb + ``` + +3. 编辑系统`init.d`脚本并设置`USE_WEB_SERVER="unicorn"` . 如果您有`/etc/default/gitlab` ,那么您应该对其进行编辑. +4. Restart GitLab. + +### Using Sidekiq instead of Sidekiq Cluster[](#using-sidekiq-instead-of-sidekiq-cluster "Permalink") + +从 GitLab 12.10 开始,Source 安装使用`bin/sidekiq-cluster`来管理 Sidekiq 进程. 在 14.0 之前,仍支持直接使用 Sidekiq. 因此,如果您遇到问题,请: + +1. 编辑系统`init.d`脚本以删除`SIDEKIQ_WORKERS`标志. 如果您有`/etc/default/gitlab` ,那么您应该对其进行编辑. +2. 重新启动 GitLab. +3. [创建一个](https://gitlab.com/gitlab-org/gitlab/-/issues/-/new)描述问题的问题. + +## Troubleshooting[](#troubleshooting "Permalink") + +### “You appear to have cloned an empty repository.”[](#you-appear-to-have-cloned-an-empty-repository "Permalink") + +如果在尝试克隆由 GitLab 托管的存储库时看到此消息,则可能是由于 NGINX 或 Apache 配置过时,或者缺少或配置了错误的 GitLab Workhorse 实例. 仔细检查您是否已[安装 Go](#3-go) , [已安装 GitLab Workhorse](#install-gitlab-workhorse)并已正确[配置 NGINX](#site-configuration) . + +### `google-protobuf` “LoadError: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14’ not found”[](#google-protobuf-loaderror-libx86_64-linux-gnulibcso6-version-glibc_214-not-found "Permalink") + +对于某些版本的`google-protobuf` gem,这可能会在某些平台上发生. 解决方法是安装此 gem 的仅源版本. + +首先,您必须找到 GitLab 安装所需的`google-protobuf`确切版本: + +``` +cd /home/git/gitlab + +# Only one of the following two commands will print something. It +# will look like: * google-protobuf (3.2.0) +bundle list | grep google-protobuf +bundle check | grep google-protobuf +``` + +下面以`3.2.0`为例. 将其替换为您在上面找到的版本号: + +``` +cd /home/git/gitlab +sudo -u git -H gem install google-protobuf --version 3.2.0 --platform ruby +``` + +最后,您可以测试`google-protobuf`是否正确加载. 以下应打印"确定". + +``` +sudo -u git -H bundle exec ruby -rgoogle/protobuf -e 'puts :OK' +``` + +如果`gem install`命令失败,则可能需要安装操作系统的开发人员工具. + +在 Debian / Ubuntu 上: + +``` +sudo apt-get install build-essential libgmp-dev +``` + +在 RedHat / CentOS 上: + +``` +sudo yum groupinstall 'Development Tools' +``` \ No newline at end of file diff --git a/docs/009.md b/docs/009.md new file mode 100644 index 0000000000000000000000000000000000000000..9d598f33ac273490e9dbaa468678d3d7e6b46394 --- /dev/null +++ b/docs/009.md @@ -0,0 +1,345 @@ +# Install GitLab on Microsoft Azure + +> 原文:[https://docs.gitlab.com/ee/install/azure/](https://docs.gitlab.com/ee/install/azure/) + +* [Getting started](#getting-started) +* [Working with Azure](#working-with-azure) +* [Create New VM](#create-new-vm) +* [Basics](#basics) +* [Size](#size) +* [Settings](#settings) +* [Purchase](#purchase) +* [Deployment](#deployment) +* [Set up a domain name](#set-up-a-domain-name) +* [Let’s open some ports](#lets-open-some-ports) + * [Which ports to open?](#which-ports-to-open) + * [Open HTTP on Port 80](#open-http-on-port-80) + * [Open SSH on Port 22](#open-ssh-on-port-22) +* [Connecting to GitLab](#connecting-to-gitlab) + * [Success?](#success) +* [Creating your first GitLab project](#creating-your-first-gitlab-project) +* [Maintaining your GitLab instance](#maintaining-your-gitlab-instance) + * [Checking our current version](#checking-our-current-version) + * [Connect via SSH](#connect-via-ssh) + * [SSH from the command-line](#ssh-from-the-command-line) + * [SSH from Windows (PuTTY)](#ssh-from-windows-putty) + * [Updating GitLab](#updating-gitlab) + * [Check out your updated GitLab](#check-out-your-updated-gitlab) +* [Conclusion](#conclusion) +* [Where to next?](#where-to-next) + * [Useful links](#useful-links) + +# Install GitLab on Microsoft Azure[](#install-gitlab-on-microsoft-azure "Permalink") + +Azure 是 Microsoft 的业务云,GitLab 是 Azure 市场上的预配置产品. 希望您不会惊讶地听到 Microsoft 和 Azure 接受了开源软件,例如 Ubuntu,Red Hat Enterprise Linux,当然还有 GitLab! 这意味着您可以启动预配置的 GitLab VM,并在 30 分钟左右启动并运行自己的私有 GitLab. 让我们开始吧. + +## Getting started[](#getting-started "Permalink") + +首先,您需要在 Azure 上拥有一个帐户. 有三种方法可以做到这一点: + +* 如果您的公司(或您)已经有一个帐户,那么您就可以开始了! +* 您还可以免费打开自己的 Azure 帐户. *在撰写本文时* ,您将获得 200 美元的信用额度,可用于 30 天的 Azure 服务支出. 您可以使用此信用额度试用付费的 Azure 服务,免费浏览 Microsoft 的云. 即使在开始的 30 天之后,您也无需支付任何费用,除非您决定转换为使用"按需付费" Azure 订阅的付费服务. 这是试用 Azure 和云计算的好方法,您可以[在其全面的 FAQ 中阅读更多内容](https://azure.microsoft.com/en-us/free/free-account-faq/) . +* 如果您具有 MSDN 订阅,则可以激活 Azure 订阅者权益. 您的 MSDN 订阅每月为您提供经常性的 Azure 信用,那么为什么不立即使用这些信用并尝试 GitLab 呢? + +## Working with Azure[](#working-with-azure "Permalink") + +Once you have an Azure account, you can get started. [Log in to Azure](https://portal.azure.com) and the first thing you will see is the Dashboard: + +[![Azure Dashboard](img/27f5db1ffe5c715ccd311bccf93665f2.png)](img/azure-dashboard.png) + +仪表板为您提供了 Azure 资源的快速概述,从这里您可以构建 VM,创建 SQL 数据库,创建网站以及执行许多其他云任务. + +## Create New VM[](#create-new-vm "Permalink") + +[Azure 市场](https://azuremarketplace.microsoft.com/en-us/marketplace/)是一个在线商店,用于存储预配置的应用程序和服务,这些软件和服务已由 GitLab 等软件供应商针对云进行了优化,可以在 Azure 市场上作为预配置的解决方案使用. 在本教程中,我们将安装 GitLab 社区版,但是对于 GitLab 企业版,您可以遵循相同的过程. + +要开始创建新的 GitLab VM,请单击**+新建**图标,在搜索框中键入" GitLab",然后单击**" GitLab Community Edition"**搜索结果: + +[![Azure - New - Search for 'GitLab'](img/3e0f74f35030a15b593a12090d5c0daf.png)](img/azure-new-search-gitlab.png) + +将会弹出一个新的"刀片"窗口,您可以在其中阅读有关 MIT Expat 许可免费提供的**" GitLab 社区版"**产品的更多信息: + +[![Azure - New - Select 'GitLab Community Edition'](img/0290c1013dba1b07f226f1548c8b6fd2.png)](img/azure-new-gitlab-ce.png) + +单击**"创建"** ,将显示"创建虚拟机"刀片: + +[![Azure - Create Virtual Machine - Basics](img/e4581843d51522e972a6bb6716aa4b05.png)](img/azure-create-virtual-machine-basics.png) + +## Basics[](#basics "Permalink") + +我们需要配置的第一项是基础虚拟机的基本设置: + +1. 输入虚拟机的`Name` -例如**" GitLab-CE"** +2. 选择一个`VM disk type` -无论是***HDD(**慢,成本更低)*或***SSD(**更快,更高成本)* +3. 输入`User name` -例如`gitlab-admin` +4. 选择一种`Authentication type` , **SSH 公钥**或**密码** : + + > **注意:**如果不确定要使用哪种身份验证类型,请选择**密码** + + 1. 如果您选择**SSH 公钥** -在提供的字段中输入`SSH public key` *(请阅读[SSH 文档,](../../ssh/README.html)以了解有关如何设置 SSH 公钥的更多信息)* + 2. 如果选择了**密码** -输入要使用*的密码(这是本教程后面将用于[SSH](https://en.wikipedia.org/wiki/Secure_Shell)到 VM 的密码,因此请确保它是一个强密码/密码)* +5. 为您的 Azure 帐户选择适当的`Subscription`层 +6. 选择一个现有的`Resource Group`或创建一个新的`Resource Group` -例如**" GitLab-CE-Azure"** + + > **注意:** "资源组"是一种将相关资源分组在一起以简化管理的方法. 我们选择了" GitLab-CE-Azure",但是您的资源组可以与 VM 具有相同的名称. + +7. 选择一个`Location` -如果不确定,请选择默认位置 + +这是我们使用的设置: + +[![Azure - Create Virtual Machine - Basics Completed](img/defc257dc0219b95ed3f3065afcaff94.png)](img/azure-create-virtual-machine-basics-password.png) + +检查您输入的设置,然后在准备好继续时单击**"确定"** . + +## Size[](#size "Permalink") + +接下来,您需要选择 VM 的大小-选择功能,例如 CPU 内核数,RAM 数量,存储大小(及其速度)等. + +> **注意:**与其他云供应商一样,Azure 运行资源/使用定价模型,即,VM 消耗的资源越多,运行成本就越高,因此请谨慎选择. 您会看到,Azure 提供了每个 VM 大小以下的*估计*每月费用,以帮助指导选择. + +默认大小-成本最低的**" DS1_V2 标准" VM-**满足运行测试和评估目的小型 GitLab 环境的最低系统要求,因此我们将继续选择该大小,但请选择大小最能满足您的要求: + +[![Azure - Create Virtual Machine - Size](img/f7bf9b7c134eb4ee2629082be8992d5a.png)](img/azure-create-virtual-machine-size.png) + +> **注意:请**注意,当您的 VM 处于活动状态(称为"已分配")时,将产生"计算费用",最终将向您收费. 因此,即使您使用的是免费试用版信用,您也可能想学习[如何正确关闭 Azure VM 以节省资金](https://build5nines.com/properly-shutdown-azure-vm-to-save-money/) . + +继续并单击您选择的大小,然后在准备进行下一步时单击**"选择"** . + +## Settings[](#settings "Permalink") + +在下一个刀片服务器上,要求您配置存储,网络和扩展设置. 我们保留了默认设置,因为它们足以进行 GitLab 的测试驾驶,但是请选择最能满足您自己要求的设置: + +[![Azure - Create Virtual Machine - Settings](img/e470cb0eb6198f35d2db011704471fce.png)](img/azure-create-virtual-machine-settings.png) + +检查设置,然后在准备好进行最后一步时单击**"确定"** . + +## Purchase[](#purchase "Permalink") + +"购买"页面是最后一步,在这里将为您显示新 VM 的每小时价格. 您只需要为 VM 本身付费(例如" Standard DS1 v2"),因为**" GitLab 社区版"**市场解决方案可以以 0 美元/小时的价格免费使用: + +[![Azure - Create Virtual Machine - Purchase](img/ed70f998a438f30a2762829a3cc5b5b6.png)](img/azure-create-virtual-machine-purchase.png) + +> **注意:**在此阶段,您可以查看和修改在之前所有步骤中所做的任何设置,只需单击四个步骤中的任何一个即可重新打开它们. + +阅读并同意使用条款并准备进行时,请单击**"购买"** . + +## Deployment[](#deployment "Permalink") + +此时,Azure 将开始部署您的新 VM. 部署过程将需要几分钟才能完成,进度显示在**"部署"**刀片上: + +[![Azure - Create Virtual Machine - Deployment](img/c9fb44f57074dc166ca07353bd7d31c7.png)](img/azure-create-virtual-machine-deployment.png) + +部署过程完成后,新的 VM 及其相关资源将显示在 Azure 仪表板上(您可能需要刷新页面): + +[![Azure - Dashboard - All resources](img/12208c7d040cd738d51605b7fcb55237.png)](img/azure-dashboard-running-resources.png) + +也可以通过单击 Azure Portal 侧栏导航菜单中的" `All resources`或" `Virtual machines`图标来访问新 VM. + +## Set up a domain name[](#set-up-a-domain-name "Permalink") + +该虚拟机将具有一个公共 IP 地址(默认情况下为静态),但是 Azure 允许我们为该虚拟机分配一个友好的 DNS 名称,所以让我们继续吧. + +在控制面板中,单击**" GitLab-CE"**图块以打开新 VM 的管理刀片. VM 使用的公共 IP 地址在"基本"部分中显示: + +[![Azure - VM - Management - Public IP Address](img/f08e838598cbf1f61321a510bb24c6a1.png)](img/azure-vm-management-public-ip.png) + +单击公共 IP 地址-这将打开**"公共 IP 地址-配置"**刀片,然后单击**"配置"** (在"设置"下). 现在,在" `DNS name label`字段中为您的实例输入一个友好的 DNS 名称: + +[![Azure - VM - Domain Name](img/bccfe6e36a18f67a038a8d90f2a6499f.png)](img/azure-vm-domain-name.png) + +In the screenshot above, you’ll see that we’ve set the `DNS name label` to `gitlab-ce-test`. This will make our VM accessible at `gitlab-ce-test.centralus.cloudapp.azure.com` *(当然,您自己的 VM 的完整域名将有所不同)*. + +单击**"保存"**以使更改生效. + +> **注意:**如果要使用自己的域名,则需要在域注册商处添加 DNS `A`记录, `A`记录指向 Azure VM 的公共 IP 地址. 如果这样做,则需要确保将 VM 配置为使用*静态的*公共 IP 地址(即不是*动态的* IP 地址),否则每次 Azure 重新为 VM 分配新的公共 IP 时,都必须重新配置 DNS `A`记录.地址. 阅读[公共 IP 地址](https://docs.microsoft.com/en-us/azure/virtual-network/public-ip-addresses)以了解更多信息. + +## Let’s open some ports[](#lets-open-some-ports "Permalink") + +在此阶段,您应该拥有一个正在运行且完全可运行的 VM. 但是,在您打开必要的端口以启用对这些服务的访问之前,将无法通过 Internet 公开访问 VM 上的任何服务(例如 GitLab). + +通过将*安全规则*添加到已分配了我们的 VM 的**"网络安全组"** (NSG),可以打开端口. 如果按照上述过程进行操作,则 Azure 将自动创建一个名为`GitLab-CE-nsg`的 NSG 并将`GitLab-CE` VM 分配给它. + +> **注意:**如果给虚拟机命名不同,则 Azure 自动创建的 NSG 也将具有不同的名称-您拥有虚拟机的名称,并附加`-nsg` . + +您可以通过 Azure 门户中的许多不同路径导航到 NSG 设置,但是最简单的方法之一是转到 Azure 仪表板,然后单击**"所有资源"**图块中列出的 Network Security 组: + +[![Azure - Dashboard - All resources - Network security group](img/c380b8ddd78f1d3281d0eeea7f19971c.png)](img/azure-dashboard-highlight-nsg.png) + +在打开**"网络安全组"**刀片的情况下,单击**"设置"**下的**"** **入站安全规则** **"** : + +[![Azure - Network security group - Inbound security rules](img/3b13f587681dd3391c82eb9b650ff6cf.png)](img/azure-nsg-inbound-sec-rules-highlight.png) + +接下来,点击**"添加"** : + +[![Azure - Network security group - Inbound security rules - Add](img/f6e26efd0e5206a2e9d1bf43865b9f4a.png)](img/azure-nsg-inbound-sec-rules-add-highlight.png) + +### Which ports to open?[](#which-ports-to-open "Permalink") + +像所有服务器一样,我们的 VM 将运行许多服务. 但是,我们要打开正确的端口,以使公共互联网特别能够访问两种服务: + +1. **HTTP** (端口 80)-打开端口 80 将使我们的 VM 能够响应 HTTP 请求,从而允许公众访问在我们的 VM 上运行的 GitLab 实例. +2. **SSH** (端口 22)-打开端口 22 将使我们的 VM 能够响应 SSH 连接请求,允许对远程终端会话进行公共访问(带有身份验证) *(您将[在本教程的后面部分](#maintaining-your-gitlab-instance)看到为什么我们需要对 VM 进行[SSH](https://en.wikipedia.org/wiki/Secure_Shell)访问)* + +### Open HTTP on Port 80[](#open-http-on-port-80 "Permalink") + +在**"添加入站安全规则"**刀片中,让我们打开端口 80,以便我们的 VM 可以接受 HTTP 连接: + +[![Azure - Add inbound security rules - HTTP](img/7d05273dffbd24f67285426b02a19ddc.png)](img/azure-add-inbound-sec-rule-http.png) + +1. 在`Name`字段中输入**" HTTP"** +2. 从`Service`下拉列表中的选项中选择**HTTP** +3. 确保将`Action`设置为**允许** +4. Click **“OK”** + +### Open SSH on Port 22[](#open-ssh-on-port-22 "Permalink") + +重复上述过程,添加第二个入站安全规则以打开端口 22,使我们的 VM 能够接受[SSH](https://en.wikipedia.org/wiki/Secure_Shell)连接: + +[![Azure - Add inbound security rules - SSH](img/fb8ded1bb07112b49dc42dff02fe01f7.png)](img/azure-add-inbound-sec-rule-ssh.png) + +1. 在" `Name`字段中输入**" SSH"** +2. 从`Service`下拉列表中的选项中选择**SSH** +3. 确保将`Action`设置为**允许** +4. Click **“OK”** + +Azure 将花一点时间来添加每个新的入站安全规则(您可能需要单击**"入站安全规则"**以刷新列表),但是一旦完成,您应该在列表中看到两个新规则: + +[![Azure - Inbound security rules - List](img/72431eb6b6fe2dd27e2f6f9be7d91672.png)](img/azure-inbound-sec-rules-list.png) + +## Connecting to GitLab[](#connecting-to-gitlab "Permalink") + +使用您先前设置的域名(或公共 IP 地址)在浏览器中访问新的 GitLab 实例. 如果一切都按计划进行,则应显示以下页面,要求您为 GitLab 自动创建的管理员帐户设置*新*密码: + +[![GitLab - Change Password](img/b786322ea49fe7840203db128b72a5e0.png)](img/gitlab-change-password.png) + +在两个表单字段中输入您的*新*密码,然后单击**"更改密码"** . + +更改密码后,您将被重定向到 GitLab 登录页面. 使用`root`作为用户名,输入在上一步中设置的新密码,然后单击**"登录"** : + +[![GitLab - Login](img/56b25600afa13ee05e76062ab09ee470.png)](img/gitlab-login.png) + +### Success?[](#success "Permalink") + +成功登录后,您应该看到 GitLab 项目页面显示**"欢迎使用 GitLab!".** 信息: + +[![GitLab - Projects Page](img/96c6ce839dca0e2ef2d69b8fbc0cff56.png)](img/gitlab-home.png) + +如果是这样,您现在可以在自己的私有 Azure VM 上拥有一个正常的 GitLab 实例. **恭喜你!** + +## Creating your first GitLab project[](#creating-your-first-gitlab-project "Permalink") + +如果您熟悉 Git 和 GitLab,则可以跳过本节. 否则,让我们创建第一个项目. 在"欢迎"页面上,单击**"新建项目"** . + +让我们给项目命名和描述,然后接受其他所有内容的默认值: + +1. 在`Project path`项目名称字段中输入**" demo"** +2. 输入`description` ,例如**"我的真棒演示项目!"** +3. Click **"创建项目"** + +[![GitLab - New Project](img/c7562ae46b8ec150661af0c88f1a5aad.png)](img/gitlab-new-project.png) + +一旦创建了新项目(只需要一点时间),您将被重定向到该项目的主页: + +[![GitLab - Empty Project](img/669c2de32e70a30ad93c28d4afd41491.png)](img/gitlab-project-home-empty.png) + +If you scroll further down the project’s home page, you’ll see some basic instructions on how to set up a local clone of your new repository and push and pull from it: + +[![GitLab - Empty Project - Basic Instructions](img/3281ef5fea53e2f0a57bb3c648aa7fa4.png)](img/gitlab-project-home-instructions.png) + +**而已! 现在,您已经在云中安装并运行了自己的私有 GitLab 环境!** + +## Maintaining your GitLab instance[](#maintaining-your-gitlab-instance "Permalink") + +保持最新的 GitLab 环境非常重要. GitLab 团队会不断进行增强,出于安全原因,有时您可能需要进行更新. 因此,让我们回顾一下如何更新 GitLab. + +### Checking our current version[](#checking-our-current-version "Permalink") + +要检查我们当前正在运行的 GitLab 版本,请单击"管理区域"链接-它是显示在搜索框旁边的右上角的扳手图标. + +在以下屏幕截图中,您可以在右上角看到**"尽快更新"**通知消息. 此特定消息表明存在可用的较新版本的 GitLab,其中包含一个或多个安全修复程序: + +[![GitLab - update asap](img/8465cc4b8bf68fad2a64c9fc838c7939.png)](img/gitlab-admin-area.png) + +在**"组件"**部分下,我们可以看到我们的 VM 当前正在运行 GitLab 的`8.6.5`版本. 这是 GitLab 的版本,包含在 Azure 市场**" GitLab 社区版"中,该**产品在编写本教程时曾用来构建 VM. + +> **注意:**您自己的 VM 实例中的 GitLab 版本可能会有所不同,但是更新过程仍然相同. + +### Connect via SSH[](#connect-via-ssh "Permalink") + +要执行更新,我们需要直接连接到我们的 Azure VM 实例并从终端运行一些命令. 我们的 Azure VM 实际上是运行 Linux(Ubuntu)的服务器,因此我们需要使用 SSH( [Secure Shell](https://en.wikipedia.org/wiki/Secure_Shell) )连接到它. + +如果您正在运行 Windows,则需要使用[PuTTY](https://www.putty.org)或等效的 Windows SSH 客户端进行连接. 如果您正在运行 Linux 或 macOS,则说明您已经安装了 SSH 客户端. + +> **Note:** +> +> * 请记住,您将需要使用[创建](#basics) Azure VM [时](#basics)指定的用户名和密码登录 +> * 如果需要重置虚拟机密码,请阅读[如何为 Azure VM 上的用户重置 SSH 凭据](https://docs.microsoft.com/en-us/azure/virtual-machines/troubleshooting/troubleshoot-ssh-connection) . + +#### SSH from the command-line[](#ssh-from-the-command-line "Permalink") + +如果您从命令行(终端)运行[SSH](https://en.wikipedia.org/wiki/Secure_Shell) ,则键入以下命令以连接到您的 VM,用`username`和`your-azure-domain-name.com`替换正确的值. + +再次提醒您,您的 Azure VM 域名将是您[先前在本教程中设置的](#set-up-a-domain-name)域名. 如果未为 VM 设置域名,则可以在以下命令中使用其 IP 地址: + +``` +ssh username@your-azure-domain-name.com +``` + +在提示时提供密码以进行身份​​验证. + +#### SSH from Windows (PuTTY)[](#ssh-from-windows-putty "Permalink") + +如果您将 Windows 中的[PuTTY](https://www.putty.org)用作[SSH](https://en.wikipedia.org/wiki/Secure_Shell)客户端,那么您可能想快速阅读[Windows 中的 PuTTY](https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty-) . + +### Updating GitLab[](#updating-gitlab "Permalink") + +通过 SSH 登录后,输入以下命令将 GitLab 更新到最新版本: + +``` +sudo apt-get update && sudo apt-get install gitlab-ce +``` + +此命令会将 GitLab 及其关联的组件更新为最新版本,因此需要一些时间才能完成. 您将在 SSH 终端窗口中看到各种更新任务正在完成: + +[![GitLab updating](img/dbae11f07630ae759b8156031d0c496d.png)](img/gitlab-ssh-update-in-progress.png) + +更新过程完成后,您将看到以下消息: + +``` +Upgrade complete! If your GitLab server is misbehaving try running + + sudo gitlab-ctl restart + +before anything else. +``` + +#### Check out your updated GitLab[](#check-out-your-updated-gitlab "Permalink") + +在浏览器中刷新您的 GitLab 实例,然后导航到"管理区域". 您现在应该具有最新的 GitLab 实例. + +在编写本教程时,我们的 Azure VM GitLab 实例在撰写本文时已更新为最新版本( `9.4.0` ). 您可以看到以前显示**" update asap"**的消息现在显示为**"最新"** : + +[![GitLab up to date](img/80a9fe0374f84134fa2b40172431604d.png)](img/gitlab-admin-area-9.4.0.png) + +## Conclusion[](#conclusion "Permalink") + +自然地,我们认为 GitLab 是一个很棒的 Git 存储库工具. 但是,GitLab 的功能远不止于此. GitLab 将问题,代码审查,CI 和 CD 统一到一个 UI 中,可帮助您从构思到生产更快地迁移,并且在本教程中,我们向您展示了在 Azure 上设置和运行自己的 GitLab 实例是多么快速和容易. ,微软的云服务. + +Azure 是尝试 GitLab 的好方法,如果您决定(如我们所愿)GitLab 适合您,则可以继续使用 Azure 作为您的安全,可扩展的云提供商,当然也可以在您选择的任何云服务上运行 GitLab. + +## Where to next?[](#where-to-next "Permalink") + +查看其他[技术文章](../../articles/index.html)或浏览[GitLab 文档](../../README.html)以了解有关 GitLab 的更多信息. + +### Useful links[](#useful-links "Permalink") + +* [GitLab Community Edition](https://about.gitlab.com/features/) +* [GitLab Enterprise Edition](https://about.gitlab.com/features/#ee-starter) +* [Microsoft Azure](https://azure.microsoft.com/en-us/) + * [Azure - Free Account FAQ](https://azure.microsoft.com/en-us/free/free-account-faq/) + * [Azure - Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/) + * [Azure Portal](https://portal.azure.com) + * [Azure - Pricing Calculator](https://azure.microsoft.com/en-us/pricing/calculator/) + * [Azure - Troubleshoot SSH Connections to an Azure Linux VM](https://docs.microsoft.com/en-us/azure/virtual-machines/troubleshooting/troubleshoot-ssh-connection) + * [Azure - Properly Shutdown an Azure VM](https://build5nines.com/properly-shutdown-azure-vm-to-save-money/) +* [SSH](https://en.wikipedia.org/wiki/Secure_Shell), [PuTTY](https://www.putty.org) and [Using SSH in PuTTY](https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty-) \ No newline at end of file diff --git a/docs/010.md b/docs/010.md new file mode 100644 index 0000000000000000000000000000000000000000..f3fad8a66bd72e139804011598deb4618d1a8a71 --- /dev/null +++ b/docs/010.md @@ -0,0 +1,122 @@ +# Installing GitLab on Google Cloud Platform + +> 原文:[https://docs.gitlab.com/ee/install/google_cloud_platform/](https://docs.gitlab.com/ee/install/google_cloud_platform/) + +* [Prerequisites](#prerequisites) +* [Creating the VM](#creating-the-vm) +* [Installing GitLab](#installing-gitlab) +* [Next steps](#next-steps) + * [Assigning a static IP](#assigning-a-static-ip) + * [Using a domain name](#using-a-domain-name) + * [Configuring HTTPS with the domain name](#configuring-https-with-the-domain-name) + * [Configuring the email SMTP settings](#configuring-the-email-smtp-settings) +* [Further reading](#further-reading) + +# Installing GitLab on Google Cloud Platform[](#installing-gitlab-on-google-cloud-platform "Permalink") + +本指南将帮助您在[Google Cloud Platform(GCP)](https://cloud.google.com/)实例上安装 GitLab. + +**替代安装方法:** Google 提供了一份白皮书,用于[在 Google Kubernetes Engine 上部署可投入生产的 GitLab](https://cloud.google.com/solutions/deploying-production-ready-gitlab-on-gke) ,包括所有步骤和外部资源配置. 这些是使用 GCP VM 的替代方法,并使用[Cloud native GitLab Helm chart](https://docs.gitlab.com/charts/) . + +## Prerequisites[](#prerequisites "Permalink") + +在 GCP 上安装 GitLab 的前提条件只有两个: + +1. 您需要有一个 Google 帐户. +2. 您需要注册 GCP 计划. 如果您是第一次,Google 会为您提供[$ 300 的信用额,](https://console.cloud.google.com/freetrial)可在 60 天内[免费](https://console.cloud.google.com/freetrial)使用. + +完成这两个步骤后,就可以[创建 VM 了](#creating-the-vm) . + +## Creating the VM[](#creating-the-vm "Permalink") + +要在 GCP 上部署 GitLab,您首先需要创建一个虚拟机: + +1. 转到[https://console.cloud.google.com/compute/instances](https://console.cloud.google.com/compute/instances)并使用您的 Google 凭据登录. +2. 点击**创建** + + [![Search for GitLab](img/9f6f0b27f8e7df6c95a3262de502b39f.png)](img/launch_vm.png) + +3. On the next page, you can select the type of VM as well as the estimated costs. Provide the name of the instance, desired datacenter, and machine type. Note our [hardware requirements for different user base sizes](../requirements.html#hardware-requirements). + + [![Launch on Compute Engine](img/d345ea7938f401127d9471442b27eb27.png)](img/vm_details.png) + +4. 要选择大小,类型和所需的[操作系统](../requirements.html#supported-linux-distributions) ,请在" `Boot disk` **"**下单击" **更改** ". 完成后单击" **选择"** . + +5. 最后,允许 HTTP 和 HTTPS 通信,然后点击**创建** . 该过程将在几秒钟内完成. + +## Installing GitLab[](#installing-gitlab "Permalink") + +几秒钟后,实例将被创建并可以登录.下一步是将 GitLab 安装到实例上. + +[![Deploy settings](img/ad33446e7ba7897d31835424ce5e1feb.png)](img/vm_created.png) + +1. 记下实例的 IP 地址,因为在后续步骤中将需要使用该 IP 地址. +2. 单击 SSH 按钮以连接到实例. +3. 登录到实例后,将出现一个新窗口. + + [![GitLab first sign in](img/e2a52ca7a089fcbd9b17f94875cba0ca.png)](img/ssh_terminal.png) + +4. 接下来,在[https://about.gitlab.com/install/上](https://about.gitlab.com/install/)按照说明为您选择的操作系统安装 GitLab. 您可以将上述步骤中的 IP 地址用作主机名. + +5. 恭喜你! GitLab 现在已安装,您可以通过浏览器访问它. 要完成安装,请在浏览器中打开 URL 并提供初始管理员密码. 该帐户的用户名是`root` . + + [![GitLab first sign in](img/279650b9e9c3ec26a7d6f0493bd5af7c.png)](img/first_signin.png) + +## Next steps[](#next-steps "Permalink") + +这些是首次安装 GitLab 之后要执行的最重要的后续步骤. + +### Assigning a static IP[](#assigning-a-static-ip "Permalink") + +默认情况下,Google 会为您的实例分配一个临时 IP. 如果您要在生产中使用 GitLab 并使用域名,则强烈建议分配一个静态 IP,如下所示. + +阅读 Google 有关如何[提升临时 IP 地址](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address#promote_ephemeral_ip)的文档. + +### Using a domain name[](#using-a-domain-name "Permalink") + +假设您拥有一个域名,并且已正确设置 DNS 以指向在上一步中配置的静态 IP,则可以通过以下方法配置 GitLab 以了解更改: + +1. SSH 进入虚拟机. 您可以轻松使用 Google 控制台中的**SSH**按钮,然后会弹出一个新窗口. + + [![SSH button](img/ad33446e7ba7897d31835424ce5e1feb.png)](img/vm_created.png) + + 将来,您可能想设置[使用 SSH 密钥的连接](https://cloud.google.com/compute/docs/instances/connecting-to-instance) . + +2. 使用您喜欢的文本编辑器编辑 Omnibus GitLab 的配置文件: + + ``` + sudo vim /etc/gitlab/gitlab.rb + ``` + +3. 将`external_url`值设置为您希望 GitLab 在**不使用** `https` **情况下**拥有的域名: + + ``` + external_url 'http://gitlab.example.com' + ``` + + 我们将在下一步中设置 HTTPS,而现在无需这样做. + +4. 重新配置 GitLab,以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +5. 您现在可以使用域名访问 GitLab. + +### Configuring HTTPS with the domain name[](#configuring-https-with-the-domain-name "Permalink") + +尽管不需要,但强烈建议使用 TLS 证书保护 GitLab. 请遵循[Omnibus 文档中](https://docs.gitlab.com/omnibus/settings/nginx.html)的步骤. + +### Configuring the email SMTP settings[](#configuring-the-email-smtp-settings "Permalink") + +您需要正确配置电子邮件 SMTP 设置,否则 GitLab 将无法发送通知电子邮件,例如注释和密码更改. 检查[Omnibus 文档的](https://docs.gitlab.com/omnibus/settings/smtp.html)操作方法. + +## Further reading[](#further-reading "Permalink") + +可以将 GitLab 配置为与其他 OAuth 提供程序,LDAP,SAML,Kerberos 等进行身份验证.以下是您可能感兴趣阅读的一些文档: + +* [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/) +* [Integration documentation](../../integration/README.html) +* [GitLab Pages configuration](../../administration/pages/index.html) +* [GitLab Container Registry configuration](../../administration/packages/container_registry.html) \ No newline at end of file diff --git a/docs/011.md b/docs/011.md new file mode 100644 index 0000000000000000000000000000000000000000..97920a2c475f285239d9eb4f496cf2ab0b5256cc --- /dev/null +++ b/docs/011.md @@ -0,0 +1,754 @@ +# Installing GitLab on Amazon Web Services (AWS) + +> 原文:[https://docs.gitlab.com/ee/install/aws/](https://docs.gitlab.com/ee/install/aws/) + +* [Introduction](#introduction) +* [Requirements](#requirements) +* [Architecture](#architecture) +* [AWS costs](#aws-costs) +* [Create an IAM EC2 instance role and profile](#create-an-iam-ec2-instance-role-and-profile) + * [Create an IAM Policy](#create-an-iam-policy) + * [Create an IAM Role](#create-an-iam-role) +* [Configuring the network](#configuring-the-network) + * [Creating the Virtual Private Cloud (VPC)](#creating-the-virtual-private-cloud-vpc) + * [Subnets](#subnets) + * [Internet Gateway](#internet-gateway) + * [Create NAT Gateways](#create-nat-gateways) + * [Route Tables](#route-tables) + * [Public Route Table](#public-route-table) + * [Private Route Tables](#private-route-tables) +* [Load Balancer](#load-balancer) + * [Configure DNS for Load Balancer](#configure-dns-for-load-balancer) +* [PostgreSQL with RDS](#postgresql-with-rds) + * [RDS Security Group](#rds-security-group) + * [RDS Subnet Group](#rds-subnet-group) + * [Create the database](#create-the-database) +* [Redis with ElastiCache](#redis-with-elasticache) + * [Create a Redis Security Group](#create-a-redis-security-group) + * [Redis Subnet Group](#redis-subnet-group) + * [Create the Redis Cluster](#create-the-redis-cluster) +* [Setting up Bastion Hosts](#setting-up-bastion-hosts) + * [Create Bastion Host A](#create-bastion-host-a) + * [Create Bastion Host B](#create-bastion-host-b) + * [Use SSH Agent Forwarding](#use-ssh-agent-forwarding) +* [Install GitLab and create custom AMI](#install-gitlab-and-create-custom-ami) + * [Install GitLab](#install-gitlab) + * [Add custom configuration](#add-custom-configuration) + * [Disable Let’s Encrypt](#disable-lets-encrypt) + * [Install the `pg_trgm` extension for PostgreSQL](#install-the-pg_trgm-extension-for-postgresql) + * [Configure GitLab to connect to PostgreSQL and Redis](#configure-gitlab-to-connect-to-postgresql-and-redis) + * [Set up Gitaly](#set-up-gitaly) + * [Add Support for Proxied SSL](#add-support-for-proxied-ssl) + * [Fast lookup of authorized SSH keys](#fast-lookup-of-authorized-ssh-keys) + * [Configure host keys](#configure-host-keys) + * [Amazon S3 object storage](#amazon-s3-object-storage) + * [Create custom AMI](#create-custom-ami) +* [Deploy GitLab inside an auto scaling group](#deploy-gitlab-inside-an-auto-scaling-group) + * [Create a launch configuration](#create-a-launch-configuration) + * [Create an auto scaling group](#create-an-auto-scaling-group) + * [Log in for the first time](#log-in-for-the-first-time) +* [Health check and monitoring with Prometheus](#health-check-and-monitoring-with-prometheus) +* [GitLab Runners](#gitlab-runners) +* [Backup and restore](#backup-and-restore) + * [Backing up GitLab](#backing-up-gitlab) + * [Restoring GitLab from a backup](#restoring-gitlab-from-a-backup) +* [Updating GitLab](#updating-gitlab) +* [Conclusion](#conclusion) +* [Troubleshooting](#troubleshooting) + * [Instances are failing health checks](#instances-are-failing-health-checks) + * [“The change you requested was rejected (422)”](#the-change-you-requested-was-rejected-422) + +# Installing GitLab on Amazon Web Services (AWS)[](#installing-gitlab-on-amazon-web-services-aws "Permalink") + +该页面提供了 AWS 上 GitLab 通用配置的演练. 您应该对其进行自定义以满足您的需求. + +**注意:**对于拥有 1,000 个或更少用户的组织,建议的 AWS 安装方法是启动 EC2 单框[Omnibus 安装](https://about.gitlab.com/install/)并实施快照策略以备份数据. 有关更多信息,请参见[1,000 个用户参考体系结构](../../administration/reference_architectures/1k_users.html) . + +## Introduction[](#introduction "Permalink") + +在大多数情况下,我们将在我们的设置中使用 Omnibus GitLab,但我们还将利用本机 AWS 服务. 代替使用 Omnibus 捆绑的 PostgreSQL 和 Redis,我们将使用 AWS RDS 和 ElastiCache. + +在本指南中,我们将进行多节点设置,首先将配置虚拟私有云和子网,以稍后集成服务(例如用于数据库服务器的 RDS 和作为 Redis 集群的 ElastiCache)以最终在一个具有自定义缩放策略的自动缩放组. + +## Requirements[](#requirements "Permalink") + +除了基本了解[AWS](https://docs.aws.amazon.com/)和[Amazon EC2 之外](https://docs.aws.amazon.com/ec2/) ,您还需要: + +* [An AWS account](https://console.aws.amazon.com/console/home) +* [To create or upload an SSH key](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) to connect to the instance via SSH +* GitLab 实例的域名 +* SSL / TLS 证书以保护您的域. 如果您还不拥有该证书,则可以通过[AWS Certificate Manager](https://aws.amazon.com/certificate-manager/) (ACM)设置免费的公共 SSL / TLS 证书,以与我们将创建的[Elastic Load Balancer](#load-balancer)一起使用. + +**注意:**验证通过 ACM 设置的证书可能需要几个小时. 为避免以后出现延迟,请尽快申请您的证书. + +## Architecture[](#architecture "Permalink") + +下面是推荐架构的示意图. + +[![AWS architecture diagram](img/20bba5f798131b98df30aaa9202ccfd5.png)](img/aws_ha_architecture_diagram.png) + +## AWS costs[](#aws-costs "Permalink") + +以下是我们将使用的 AWS 服务的列表,以及指向定价信息的链接: + +* **EC2** :GitLab 将部署在共享硬件上,这意味着将[按需定价](https://aws.amazon.com/ec2/pricing/on-demand/) . 如果要在专用或保留实例上运行它,请参阅[EC2 定价页面](https://aws.amazon.com/ec2/pricing/)以获取有关费用的更多信息. +* **S3** :我们将使用 S3 来存储备份,工件,LFS 对象等.请参阅[Amazon S3 定价](https://aws.amazon.com/s3/pricing/) . +* **ELB** :经典负载均衡器将用于将请求路由到 GitLab 实例. 请参阅[Amazon ELB 定价](https://aws.amazon.com/elasticloadbalancing/pricing/) . +* **RDS** :将使用使用 PostgreSQL 的 Amazon Relational Database Service. 请参阅[Amazon RDS 定价](https://aws.amazon.com/rds/postgresql/pricing/) . +* **ElastiCache** :内存缓存环境将用于提供 Redis 配置. 请参阅[Amazon ElastiCache 定价](https://aws.amazon.com/elasticache/pricing/) . + +## Create an IAM EC2 instance role and profile[](#create-an-iam-ec2-instance-role-and-profile "Permalink") + +由于我们将使用[Amazon S3 对象存储](#amazon-s3-object-storage) ,因此我们的 EC2 实例需要具有对 S3 存储桶的读取,写入和列出权限. 为了避免将 AWS Key 嵌入我们的 GitLab 配置中,我们将利用[IAM 角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)允许 GitLab 实例具有此访问权限. 我们需要创建一个 IAM 策略以附加到我们的 IAM 角色: + +### Create an IAM Policy[](#create-an-iam-policy "Permalink") + +1. 导航到 IAM 仪表板,然后单击左侧菜单中的" **策略** ". +2. 单击**创建策略** ,选择`JSON`选项卡,然后添加策略. 我们希望[遵循安全最佳实践并授予*最少的特权*](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege) ,仅向我们的角色授予执行所需操作所需的权限. + 1. 假设如图所示,在 S3 存储桶名称前添加`gl-`作为前缀,请添加以下策略: + +``` +{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:AbortMultipartUpload", "s3:CompleteMultipartUpload", "s3:ListBucket", "s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:PutObjectAcl" ], "Resource": [ "arn:aws:s3:::gl-*/*" ] } ] } +``` + +1. 点击**审核政策** ,为您的政策命名(我们将使用`gl-s3-policy` ),然后点击**创建政策** . + +### Create an IAM Role[](#create-an-iam-role "Permalink") + +1. 仍在 IAM 仪表板上,单击左侧菜单中的**角色** ,然后单击**创建角色** . +2. 通过选择**AWS 服务> EC2**来创建新角色,然后单击**下一步:权限** . +3. 在策略过滤器中,搜索我们在上面创建的`gl-s3-policy` ,选择它,然后点击**标签** . +4. 根据需要添加标签,然后单击" **查看"** . +5. 为角色命名(我们将使用`GitLabS3Access` ),然后点击**创建角色** . + +稍后[创建启动配置](#create-a-launch-configuration)时,将使用此角色. + +## Configuring the network[](#configuring-the-network "Permalink") + +我们将从为 GitLab 云基础架构创建 VPC 开始,然后我们可以创建子网以在至少两个[可用区(AZ)中](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html)具有公共实例和私有实例. 公共子网将需要保留路由表和关联的 Internet 网关. + +### Creating the Virtual Private Cloud (VPC)[](#creating-the-virtual-private-cloud-vpc "Permalink") + +现在,我们将创建一个 VPC,一个您可以控制的虚拟网络环境: + +1. 导航至[https://console.aws.amazon.com/vpc/home](https://console.aws.amazon.com/vpc/home) . +2. 从左侧菜单中选择**您的 VPC** ,然后单击**创建 VPC** . 在"名称标签"中输入`gitlab-vpc` ,在" IPv4 CIDR 块"中输入`10.0.0.0/16` . 如果不需要专用硬件,则可以将" Tenancy"保留为默认设置. 单击**是,**准备好后**创建** . + + [![Create VPC](img/7cfe14b5f606095866af7260c844d4e2.png)](img/create_vpc.png) + +3. 选择 VPC,单击" **操作"** ,单击" **编辑 DNS 解析"** ,然后启用 DNS 解析. 完成后点击**保存** . + +### Subnets[](#subnets "Permalink") + +现在,让我们在不同的可用区中创建一些子网. 确保每个子网都与我们刚刚创建的 VPC 相关联,并且 CIDR 块不会重叠. 这也将使我们能够启用多可用区以实现冗余. + +我们还将创建专用和公用子网以匹配负载均衡器和 RDS 实例: + +1. 从左侧菜单中选择**子网** . +2. 单击**创建子网** . 给它一个基于 IP 的描述性名称标签,例如`gitlab-public-10.0.0.0` ,选择我们之前创建的 VPC,选择一个可用区(我们将使用`us-west-2a` ),并在 IPv4 CIDR 块上让我们给它一个 24 个子网`10.0.0.0/24` : + + [![Create subnet](img/48482b1410caf250f0257d772e55c544.png)](img/create_subnet.png) + +3. 请按照相同的步骤创建所有子网: + + | 名称标签 | Type | 可用区 | CIDR 块 | + | --- | --- | --- | --- | + | `gitlab-public-10.0.0.0` | public | `us-west-2a` | `10.0.0.0/24` | + | `gitlab-private-10.0.1.0` | private | `us-west-2a` | `10.0.1.0/24` | + | `gitlab-public-10.0.2.0` | public | `us-west-2b` | `10.0.2.0/24` | + | `gitlab-private-10.0.3.0` | private | `us-west-2b` | `10.0.3.0/24` | + +4. 创建所有子网后,请为两个公共子网启用**自动分配 IPv4** : + 1. 依次选择每个公共子网,单击" **操作"** ,然后单击" **修改自动分配 IP 设置"** . 启用该选项并保存. + +### Internet Gateway[](#internet-gateway "Permalink") + +现在,仍然在同一仪表板上,转到 Internet 网关并创建一个新的网关: + +1. 从左侧菜单中选择" **Internet 网关** ". +2. 单击**创建互联网网关** ,为其命名为`gitlab-gateway` ,然后单击**创建** . +3. 从表中选择它,然后在" **操作"**下拉菜单下选择"附加到 VPC". + + [![Create gateway](img/104374dd85800b346ef75734f6fd0b38.png)](img/create_gateway.png) + +4. 从列表中选择`gitlab-vpc` ,然后点击**Attach** . + +### Create NAT Gateways[](#create-nat-gateways "Permalink") + +部署在我们专用子网中的实例需要连接到 Internet 进行更新,但不能从公共 Internet 到达. 为此,我们将利用部署在每个公共子网中的[NAT 网关](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html) : + +1. 导航到 VPC 仪表板,然后单击左侧菜单栏中的**NAT 网关** . +2. 单击**创建 NAT 网关,**然后完成以下操作: + 1. **子网** :从下拉列表中选择`gitlab-public-10.0.0.0` . + 2. **弹性 IP 分配 ID** :输入现有的弹性 IP 或单击**分配弹性 IP 地址,**以将新 IP 分配给您的 NAT 网关. + 3. 如果需要,添加标签. + 4. 单击**创建 NAT 网关** . + +创建第二个 NAT 网关,但这一次将其放置在第二个公共子网`gitlab-public-10.0.2.0` . + +### Route Tables[](#route-tables "Permalink") + +#### Public Route Table[](#public-route-table "Permalink") + +我们需要为公共子网创建路由表,以通过上一步中创建的 Internet 网关访问 Internet. + +在 VPC 仪表板上: + +1. 从左侧菜单中选择**路由表** . +2. Click **创建路由表**. +3. 在"名称标签"中,输入`gitlab-public` , `gitlab-vpc`在" VPC"下选择`gitlab-vpc` . +4. Click **Create**. + +现在,我们需要将我们的 Internet 网关添加为新目标,并使其接收来自任何目的地的流量. + +1. 从左侧菜单中选择" **路由表"** ,然后选择`gitlab-public`路由以在底部显示选项. +2. 选择" **路线"**选项卡,单击" **编辑路线">"添加路线",**然后将`0.0.0.0/0`设置为目的地. 在目标列中,选择我们之前创建的`gitlab-gateway` . 完成后,点击**保存路线** . + +接下来,我们必须将**公共**子网关联到路由表: + +1. Select the **子网关联** tab and click **编辑子网关联**. +2. 仅检查公共子网,然后单击" **保存"** . + +#### Private Route Tables[](#private-route-tables "Permalink") + +我们还需要创建两个私有路由表,以便每个私有子网中的实例都可以通过同一可用性区域中相应公共子网中的 NAT 网关到达 Internet. + +1. 请按照与上述相同的步骤创建两个专用路由表. 将它们`gitlab-private-a`命名为`gitlab-private-a`和`gitlab-private-b` . +2. Next, add a new route to each of the private route tables where the destination is `0.0.0.0/0` and the target is one of the NAT gateways we created earlier. + 1. 将我们在`gitlab-public-10.0.0.0`创建的 NAT 网关添加为`gitlab-private-a`路由表中新路由的目标. + 2. 同样,在`gitlab-public-10.0.2.0`添加 NAT 网关作为`gitlab-private-b`新路由的目标. +3. 最后,将每个专用子网与专用路由表相关联. + 1. 将`gitlab-private-10.0.1.0` `gitlab-private-a`与`gitlab-private-a` . + 2. 将`gitlab-private-10.0.3.0`与`gitlab-private-b` . + +## Load Balancer[](#load-balancer "Permalink") + +我们将创建一个负载平衡器,以在我们的 GitLab 应用程序服务器之间平均分配端口`80`和`443`上的入站流量. 根据我们稍后将创建的[扩展策略](#create-an-auto-scaling-group) ,实例将根据需要添加到负载均衡器中或从负载均衡器中删除. 此外,负载平衡将对我们的实例执行运行状况检查. + +在 EC2 仪表板上,在左侧导航栏中查找 Load Balancer: + +1. 单击**创建负载均衡器**按钮. + 1. 选择**经典负载均衡器** . + 2. 给它`gitlab-loadbalancer` (我们将使用`gitlab-loadbalancer` ),并在**Create LB Inside**选项中,从下拉菜单中选择`gitlab-vpc` . + 3. 在" **侦听器"**部分中,设置以下侦听器: + * 负载均衡器和实例协议以及端口的 HTTP 端口 80 + * 负载均衡器和实例协议以及端口的 TCP 端口 22 + * HTTPS 端口 443(用于负载均衡器协议和端口),转发到实例上的 HTTP 端口 80(我们将[在指南](#add-support-for-proxied-ssl)中将 GitLab 配置为侦听端口 80) + 4. 在" **选择子网"**部分中,从列表中选择两个公共子网,以便负载均衡器可以将流量路由到两个可用区域. +2. 我们将为负载均衡器添加一个安全组,以充当防火墙来控制允许通过的流量. 单击**分配安全组,**然后选择**创建新的安全组** ,为其命名(我们将使用`gitlab-loadbalancer-sec-group` )和说明,并允许来自任何地方的 HTTP 和 HTTPS 通信( `0.0.0.0/0, ::/0` ). 还允许 SSH 流量,选择自定义来源,并以 CIDR 表示法添加单个受信任的 IP 地址或 IP 地址范围. 这将允许用户通过 SSH 执行 Git 操作. +3. 单击**配置安全设置,**然后进行以下设置: + 1. 从 ACM 中选择一个 SSL / TLS 证书或将一个证书上传到 IAM. + 2. 在" **选择密码"下** ,从下拉列表中选择预定义的安全策略. 您可以在 AWS 文档中[查看 Classic Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html)的[预定义 SSL 安全策略](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html)明细. 检查 GitLab 代码库以获取[受支持的 SSL 密码和协议](https://gitlab.com/gitlab-org/gitlab/-/blob/9ee7ad433269b37251e0dd5b5e00a0f00d8126b4/lib/support/nginx/gitlab-ssl#L97-99)的列表. +4. 单击" **配置**运行状况检查",然后为您的 EC2 实例设置运行状况检查. + 1. 对于" **Ping 协议"** ,选择" HTTP". + 2. 对于**Ping 端口** ,输入 80\. + 3. 对于**Ping Path** ,输入`/users/sign_in` . (我们使用`/users/sign_in`因为它是不需要授权的公共端点.) + 4. 保留默认的" **高级详细信息"**或根据需要进行调整. +5. 单击**添加 EC2 实例** -不要添加任何内容,因为稍后我们将创建一个 Auto Scaling 组来为我们管理实例. +6. 单击**添加标签,**然后添加您需要的任何标签. +7. 单击" **查看并创建"** ,查看所有设置,如果满意,请单击" **创建"** . + +在负载均衡器启动并运行后,您可以重新访问安全组以仅通过 ELB 和您可能具有的任何其他要求来完善访问. + +### Configure DNS for Load Balancer[](#configure-dns-for-load-balancer "Permalink") + +在 Route 53 仪表板上,单击左侧导航栏中的" **托管区域** ": + +1. 选择一个现有的托管区域,或者,如果您的域还没有一个,请单击**创建托管区域** ,输入您的域名,然后单击**创建** . +2. 单击**创建记录集,**并提供以下值: + 1. **名称:**使用域名(默认值)或输入一个子域. + 2. **类型:**选择**A-IPv4 地址** . + 3. **别名:**默认为**No.** 选择**是** . + 4. **别名目标:**找到" **ELB 经典负载均衡器"**部分,然后选择我们之前创建的经典负载均衡器. + 5. **路由策略:**我们将使用" **简单",**但您可以根据用例选择其他策略. + 6. **评估目标健康状况:**我们将其设置为" **否",**但是您可以选择让负载均衡器根据目标健康状况来路由流量. + 7. 点击**创建** . +3. 如果您通过 Route 53 注册了域,那么您就完成了. 如果您使用了其他域名注册商,则需要使用域名注册商更新 DNS 记录. 您需要: + 1. 单击**托管区域,**然后选择您在上面添加的域. + 2. 您将看到`NS`记录列表. 在您的域名注册商的管理面板中,将每一个作为`NS`记录添加到您域的 DNS 记录中. 这些步骤在域注册商之间可能会有所不同. 如果您陷入困境,则 Google **"您的注册商名称"会添加 dns 记录** ,您应该会找到针对您的域名注册商的帮助文章. + +根据您使用的注册商的不同,执行此操作的步骤也有所不同,这超出了本指南的范围. + +## PostgreSQL with RDS[](#postgresql-with-rds "Permalink") + +对于我们的数据库服务器,我们将使用提供多可用区以实现冗余的 Amazon RDS. 首先,我们将创建一个安全组和子网组,然后将创建实际的 RDS 实例. + +### RDS Security Group[](#rds-security-group "Permalink") + +我们需要一个用于数据库的安全组,该安全组将允许稍后将在`gitlab-loadbalancer-sec-group`部署的实例的入站流量: + +1. 在 EC2 仪表板中,从左侧菜单栏中选择" **安全组** ". +2. Click **创建安全组**. +3. 给它起一个名字(我们将使用`gitlab-rds-sec-group` ),一个描述,并从**VPC**下拉列表中选择`gitlab-vpc` . +4. 在" **入站规则"**部分中,单击" **添加规则"**并进行以下设置: + 1. **键入:**搜索并选择**PostgreSQL**规则. + 2. **来源类型:**设置为"自定义". + 3. **来源:**选择我们之前创建的`gitlab-loadbalancer-sec-group` . +5. 完成后,点击**创建安全组** . + +### RDS Subnet Group[](#rds-subnet-group "Permalink") + +1. 导航到 RDS 仪表板,然后从左侧菜单中选择" **子网组** ". +2. 单击**创建数据库子网组** . +3. 在" **子网组详细信息"下** ,输入名称(我们将使用`gitlab-rds-group` ),描述,然后从 VPC 下拉列表中选择`gitlab-vpc` . +4. 从" **可用区"**下拉列表中,选择包括您已配置的子网的可用区. 在本例中,我们将添加`eu-west-2a`和`eu-west-2b` . +5. 从**子网**下拉列表中,选择两个专用子网( `10.0.1.0/24`和`10.0.3.0/24` ,因为我们在定义它们) [的子网部分](#subnets) . +6. 准备好后,单击**创建** . + +### Create the database[](#create-the-database "Permalink") + +**危险:**避免对数据库使用易爆实例(t 类实例),因为由于 CPU 信用在持续的高负载期间用尽而可能导致性能问题. + +现在,该创建数据库了: + +1. 导航到 RDS 仪表板,从左侧菜单中选择" **数据库** ",然后单击" **创建数据库"** . +2. 选择**标准创建**作为数据库创建方法. +3. 选择**PostgreSQL**作为数据库引擎,然后选择在[数据库要求中](../../install/requirements.html#postgresql-requirements)为您的 GitLab 版本定义的最低 PostgreSQL 版本. +4. 由于这是生产服务器,因此我们从" **模板"**部分中选择" **生产** ". +5. 在**"设置"下** ,设置数据库实例标识符,主用户名和主密码. 我们将分别使用`gitlab-db-ha` , `gitlab`和一个非常安全的密码. 记下这些内容,稍后我们将需要它们. +6. 对于数据库实例大小,请选择" **标准类",**然后从下拉菜单中选择一个满足您要求的实例大小. 我们将使用`db.m4.large`实例. +7. 在" **存储"下** ,配置以下内容: + 1. 从存储类型下拉菜单中选择" **Provisioned IOPS(SSD)** ". 预置 IOPS(SSD)存储最适合此用途(尽管您可以选择 General Purpose(SSD)来降低成本). 在[Amazon RDS 的存储中](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html)阅读有关它的更多信息. + 2. 分配存储并设置预配置的 IOPS. 我们将分别使用最小值`100`和`1000` . + 3. 启用存储自动缩放(可选)并设置最大存储阈值. +8. 在" **可用性和持久性"下** ,选择" **创建备用实例"**以在另一个可用[区中](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html)配置备用 RDS 实例. +9. 在" **连接性"下** ,配置以下内容: + 1. 从**虚拟私有云(VPC)**下拉菜单中选择我们之前创建的 VPC( `gitlab-vpc` ). + 2. 展开**其他连接配置**部分,然后选择我们之前创建的子网组( `gitlab-rds-group` ). + 3. 设置公众了解**没有** . + 4. 在**VPC 安全组下** ,选择**选择现有,**然后从下拉列表中选择我们在上面创建的`gitlab-rds-sec-group` . + 5. 将数据库端口保留为默认值`5432` . +10. 对于**数据库身份验证** ,选择**密码身份验证** . +11. 展开**其他配置**部分,并完成以下操作: + 1. 初始数据库名称. 我们将使用`gitlabhq_production` . + 2. 配置您的首选备份设置. + 3. 我们将在此处进行的唯一其他更改是禁用" **维护"**下的自动次要版本更新. + 4. 保留所有其他设置不变或根据需要进行调整. + 5. 满意后,点击**创建数据库** . + +现在已经创建了数据库,让我们继续使用 ElastiCache 设置 Redis. + +## Redis with ElastiCache[](#redis-with-elasticache "Permalink") + +ElastiCache 是​​一个内存托管的缓存解决方案. Redis 保持其自身的持久性,并用于为 GitLab 应用程序存储会话数据,临时缓存信息和后台作业队列. + +### Create a Redis Security Group[](#create-a-redis-security-group "Permalink") + +1. 导航到 EC2 仪表板. +2. 从左侧菜单中选择" **安全组** ". +3. 单击**创建安全组,**然后填写详细信息. 给它`gitlab-redis-sec-group` (我们将使用`gitlab-redis-sec-group` ),添加描述,然后选择我们之前创建的 VPC +4. 在" **入站规则"**部分中,单击" **添加规则"**并添加一个" **自定义 TCP"**规则,设置端口`6379` ,并将"自定义"源设置为我们之前创建的`gitlab-loadbalancer-sec-group` . +5. 完成后,点击**创建安全组** . + +### Redis Subnet Group[](#redis-subnet-group "Permalink") + +1. 从您的 AWS 控制台导航到 ElastiCache 仪表板. +2. 转到左侧菜单中的" **子网组** ",然后创建一个新的子网组(我们将其命名为`gitlab-redis-group` ). 确保选择我们的 VPC 及其[专用子网](#subnets) . 准备好后,单击**创建** . + + [![ElastiCache subnet](img/98f7e80b6f738f9886082aeec3955fd5.png)](img/ec_subnet.png) + +### Create the Redis Cluster[](#create-the-redis-cluster "Permalink") + +1. 导航回到 ElastiCache 仪表板. +2. 在左侧菜单上选择**Redis** ,然后单击**创建**以创建新的 Redis 集群. 不要启用**集群模式,**因为它[不受支持](../../administration/redis/replication_and_failover_external.html#requirements) . 即使没有启用群集模式,您仍然有机会在多个可用性区域中部署 Redis. +3. 在设置部分: + 1. 为集群命名( `gitlab-redis` )和描述. + 2. 对于版本,选择最新的`5.0`系列(例如`5.0.6` ). + 3. 将端口保留为`6379`因为这是我们在上面的 Redis 安全组中使用的端口. + 4. 选择节点类型(至少为`cache.t3.medium` ,但根据需要进行调整)和副本数. +4. 在高级设置部分: + 1. 选择多可用区自动故障转移选项. + 2. 选择我们之前创建的子网组. + 3. 手动选择首选的可用区域,然后在"副本 2"下选择与其他两个区域不同的区域. + + [![Redis 可用区](img/38ef5bf427869fe9b1050db6eacd2972.png)](img/ec_az.png) + +5. 在安全设置中,编辑安全组,然后选择我们之前创建的`gitlab-redis-sec-group` . +6. 将其余设置保留为默认值,或根据自己的喜好进行编辑. +7. 完成后,点击**创建** . + +## Setting up Bastion Hosts[](#setting-up-bastion-hosts "Permalink") + +由于我们的 GitLab 实例将位于专用子网中,因此我们需要一种通过 SSH 连接到这些实例以进行配置更改,执行升级等的方法.一种方法是通过[堡垒主机](https://en.wikipedia.org/wiki/Bastion_host) ,有时也称为跳转框. + +**提示:**如果您不想维护堡垒主机,则可以设置[AWS Systems Manager Session Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html)来访问实例. 这超出了本文档的范围. + +### Create Bastion Host A[](#create-bastion-host-a "Permalink") + +1. 导航到 EC2 仪表板,然后单击**Launch instance** . +2. 选择**Ubuntu Server 18.04 LTS(HVM)** AMI. +3. 选择一个实例类型. 我们将使用`t2.micro`因为我们仅使用堡垒主机将 SSH SSH 到我们的其他实例中. +4. Click **配置实例详细信息**. + 1. 在" **网络"下** ,从下拉菜单中选择`gitlab-vpc` . + 2. 在" **子网"下** ,选择我们之前创建的公共子网( `gitlab-public-10.0.0.0` ). + 3. 仔细检查是否在" **自动分配公用 IP"下**选择了" **使用子网设置"("启用")** . + 4. 将其他所有内容保留为默认值,然后单击" **添加存储"** . +5. 对于存储,我们将所有内容保留为默认设置,仅添加 8GB 根卷. 我们不会在此实例上存储任何内容. +6. 单击**添加标签** ,然后在下一个屏幕上单击**添加标签** . + 1. 我们只设置`Key: Name`和`Value: Bastion Host A` +7. Click **配置安全组**. + 1. 选择**创建新的安全组** ,输入**安全组名称** (我们将使用`bastion-sec-group` ),然后添加描述. + 2. 我们将从任何地方( `0.0.0.0/0` )启用 SSH 访问. 如果需要更严格的安全性,请以 CIDR 表示法指定单个 IP 地址或 IP 地址范围. + 3. Click **审查并启动** +8. Review all your settings and, if you’re happy, click **Launch**. +9. 确认您有权访问现有的密钥对或创建一个新的密钥对. 单击**启动实例** . + +确认您可以通过 SSH 进入实例: + +1. 在 EC2 仪表板上,单击左侧菜单中的**Instances** . +2. 从实例列表中选择**Bastion HostA** . +3. 单击**连接,**然后按照连接说明进行操作. +4. 如果能够成功连接,让我们继续设置第二个堡垒主机以实现冗余. + +### Create Bastion Host B[](#create-bastion-host-b "Permalink") + +1. 按照与上述相同的步骤创建 EC2 实例,并进行以下更改: + 1. 对于**Subnet** ,选择我们之前创建的第二个公共子网( `gitlab-public-10.0.2.0` ). + 2. 在" **添加标签"**部分下,我们将设置" `Key: Name`和`Value: Bastion Host B`以便我们可以轻松识别两个实例. + 3. 对于安全组,选择我们上面创建的现有`bastion-sec-group` . + +### Use SSH Agent Forwarding[](#use-ssh-agent-forwarding "Permalink") + +运行 Linux 的 EC2 实例使用私钥文件进行 SSH 身份验证. 您将使用 SSH 客户端和存储在客户端上的私钥文件连接到堡垒主机. 由于私有密钥文件不存在于堡垒主机上,因此您将无法连接到私有子网中的实例. + +在堡垒主机上存储私钥文件是一个坏主意. 要解决此问题,请在客户端上使用 SSH 代理转发. 有关如何使用 SSH 代理转发的分步指南,请参阅[安全连接到在私有 Amazon VPC 中运行的 Linux 实例](https://aws.amazon.com/blogs/security/securely-connect-to-linux-instances-running-in-a-private-amazon-vpc/) . + +## Install GitLab and create custom AMI[](#install-gitlab-and-create-custom-ami "Permalink") + +我们将需要预先配置的自定义 GitLab AMI,以便稍后在我们的启动配置中使用. 首先,我们将使用官方的 GitLab AMI 创建 GitLab 实例. 然后,我们将为 PostgreSQL,Redis 和 Gitaly 添加自定义配置. 如果愿意,您也可以使用自己选择的 EC2 实例启动并[手动安装 GitLab](https://about.gitlab.com/install/) ,而不是使用官方的 GitLab AMI. + +### Install GitLab[](#install-gitlab "Permalink") + +从 EC2 仪表板: + +1. 单击**启动实例,**然后从左侧菜单中选择**社区 AMI** . +2. 在搜索栏中,搜索`GitLab EE ` ,其中``是[发行页面](https://about.gitlab.com/releases/)上显示的最新版本. 选择最新的补丁程序版本,例如`GitLab EE 12.9.2` . +3. 根据您的工作量选择一个实例类型. 请查阅[硬件要求,](../../install/requirements.html#hardware-requirements)以选择适合您需求的[硬件](../../install/requirements.html#hardware-requirements) (至少`c5.xlarge` ,足以容纳 100 位用户). +4. Click **配置实例详细信息**: + 1. 在" **网络"**下拉列表中,选择`gitlab-vpc` ,这是我们之前创建的 VPC. + 2. 在" **子网"**下拉列表中,从我们先前创建的**子网**列表中选择`gitlab-private-10.0.1.0` . + 3. 仔细检查是否将" **自动分配公用 IP"**设置为" `Use subnet setting (Disable)` . + 4. Click **添加存储**. + 5. 默认情况下,根卷为 8GiB,并且在我们不会在其中存储任何数据的情况下,根卷应该足够. +5. 单击**添加标签,**然后添加您可能需要的任何标签. 在本例中,我们将仅设置`Key: Name`和`Value: GitLab` . +6. 单击**配置安全组** . 选中**选择现有安全组,**然后选择我们之前创建的`gitlab-loadbalancer-sec-group` . +7. 如果对设置满意,请单击**查看并启动,**然后单击**启动** . +8. 最后,确认您有权访问所选的私钥文件或创建一个新的私钥文件. 单击**启动实例** . + +### Add custom configuration[](#add-custom-configuration "Permalink") + +使用[SSH 代理转发](#use-ssh-agent-forwarding)通过**Bastion Host A**连接到您的 GitLab 实例. 连接后,添加以下自定义配置: + +#### Disable Let’s Encrypt[](#disable-lets-encrypt "Permalink") + +由于我们要在负载均衡器中添加 SSL 证书,因此我们不需要 GitLab 对 Let's Encrypt 的内置支持. 自 GitLab 10.7 起,使用`https`域时[,默认情况下启用](https://docs.gitlab.com/omnibus/settings/ssl.html)加密[功能](https://docs.gitlab.com/omnibus/settings/ssl.html) ,因此我们需要显式禁用它: + +1. 打开`/etc/gitlab/gitlab.rb`并禁用它: + + ``` + letsencrypt['enable'] = false + ``` + +2. 保存文件并重新配置以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +#### Install the `pg_trgm` extension for PostgreSQL[](#install-the-pg_trgm-extension-for-postgresql "Permalink") + +在您的 GitLab 实例中,连接到 RDS 实例以验证访问权限并安装所需的`pg_trgm`扩展. + +要查找主机或终端节点,请导航至**Amazon RDS>数据库** ,然后单击您之前创建的数据库. 在" **连接性和安全性"**选项卡下查找端点. + +不要包括冒号和端口号: + +``` +sudo /opt/gitlab/embedded/bin/psql -U gitlab -h -d gitlabhq_production +``` + +在`psql`提示符下,创建扩展,然后退出会话: + +``` +psql (10.9) +Type "help" for help. + +gitlab=# CREATE EXTENSION pg_trgm; +gitlab=# \q +``` + +#### Configure GitLab to connect to PostgreSQL and Redis[](#configure-gitlab-to-connect-to-postgresql-and-redis "Permalink") + +1. 编辑`/etc/gitlab/gitlab.rb` ,找到`external_url 'http://'`选项并将其更改为您将使用的`https`域. + +2. 查找 GitLab 数据库设置,并根据需要取消注释. 在当前情况下,我们将指定数据库适配器,编码,主机,名称,用户名和密码: + + ``` + # Disable the built-in Postgres + postgresql['enable'] = false + + # Fill in the connection details + gitlab_rails['db_adapter'] = "postgresql" + gitlab_rails['db_encoding'] = "unicode" + gitlab_rails['db_database'] = "gitlabhq_production" + gitlab_rails['db_username'] = "gitlab" + gitlab_rails['db_password'] = "mypassword" + gitlab_rails['db_host'] = "" + ``` + +3. 接下来,我们需要通过添加主机并取消注释端口来配置 Redis 部分: + + ``` + # Disable the built-in Redis + redis['enable'] = false + + # Fill in the connection details + gitlab_rails['redis_host'] = "" + gitlab_rails['redis_port'] = 6379 + ``` + +4. 最后,重新配置 GitLab 以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +5. 您可能还会发现运行检查和服务状态以确保一切均已正确设置很有用: + + ``` + sudo gitlab-rake gitlab:check + sudo gitlab-ctl status + ``` + +#### Set up Gitaly[](#set-up-gitaly "Permalink") + +**注意:**在这种体系结构中,只有一台 Gitaly 服务器会造成单点故障. 使用[Gitaly Cluster](../../administration/gitaly/praefect.html)可以消除此限制. + +Gitaly 是一项服务,它提供对 Git 存储库的高级 RPC 访问. 应该在我们之前配置的[专用子网](#subnets)之一中的单独 EC2 实例上启用和配置它. + +让我们创建一个安装 Gitaly 的 EC2 实例: + +1. 在 EC2 仪表板中,单击**启动实例** . +2. 选择一个 AMI. 在此示例中,我们将选择**Ubuntu Server 18.04 LTS(HVM),SSD Volume Type** . +3. Choose an instance type. We’ll pick a **c5.xlarge**. +4. Click **配置实例详细信息**. + 1. 在" **网络"**下拉列表中,选择`gitlab-vpc` ,这是我们之前创建的 VPC. + 2. 在" **子网"**下拉列表中,从我们先前创建的**子网**列表中选择`gitlab-private-10.0.1.0` . + 3. 仔细检查是否将" **自动分配公用 IP"**设置为" `Use subnet setting (Disable)` . + 4. Click **添加存储**. +5. 将根卷大小增加到`20 GiB` ,并将**卷类型**更改为`Provisoned IOPS SSD (io1)` . (这是一个任意大小.创建一个足以满足您的存储库存储需求的卷.) + 1. 对于**IOPS**设置`1000` (20 GiB x 50 IOPS). 每个 GiB 最多可以配置 50 IOPS. 如果选择更大的音量,请相应地增加 IOPS. 以串行方式写入许多小文件的工作负载(如`git` )需要高性能的存储,因此选择`Provisoned IOPS SSD (io1)` . +6. 单击**添加标签**并添加您的标签. 在本例中,我们将仅设置`Key: Name`和`Value: Gitaly` . +7. 单击" **配置安全组",**然后**创建一个新的安全组** . + 1. 给您的安全组一个名称和描述. 我们将同时使用`gitlab-gitaly-sec-group` . + 2. 创建一个**自定义 TCP**规则,并将端口`8075`添加到" **端口范围"中** . 对于**Source** ,选择`gitlab-loadbalancer-sec-group` . + 3. 还要从`bastion-sec-group`添加 SSH 的入站规则,以便我们可以使用来自堡垒主机的[SSH 代理转发](#use-ssh-agent-forwarding)进行连接. +8. 如果对设置满意,请单击**查看并启动,**然后单击**启动** . +9. 最后,确认您有权访问所选的私钥文件或创建一个新的私钥文件. 单击**启动实例** . + +**注意:**除了将配置*和*存储库数据存储在根卷上之外,您还可以选择添加其他 EBS 卷用于存储库存储. 请遵循上述相同的指导. 请参阅[Amazon EBS 定价](https://aws.amazon.com/ebs/pricing/) . 我们不建议使用 EFS,因为它可能会对 GitLab 的性能产生负面影响. 您可以查看[相关文档](../../administration/high_availability/nfs.html#avoid-using-awss-elastic-file-system-efs)以了解更多详细信息. + +现在我们已经准备好我们的 EC2 实例,请按照[文档安装 GitLab 并在其自己的服务器上设置 Gitaly](../../administration/gitaly/index.html#run-gitaly-on-its-own-server) . 在[我们](#install-gitlab)上面[创建](#install-gitlab)的[GitLab 实例](#install-gitlab)上,从该文档执行客户端设置步骤. + +#### Add Support for Proxied SSL[](#add-support-for-proxied-ssl "Permalink") + +当我们在[负载均衡器](#load-balancer)处终止 SSL 时,请按照[支持代理的 SSL 中](https://docs.gitlab.com/omnibus/settings/nginx.html)的步骤在`/etc/gitlab/gitlab.rb`进行配置. + +将更改保存到`gitlab.rb`文件后,切记要运行`sudo gitlab-ctl reconfigure` . + +#### Fast lookup of authorized SSH keys[](#fast-lookup-of-authorized-ssh-keys "Permalink") + +允许访问 GitLab 的用户的公共 SSH 密钥存储在`/var/opt/gitlab/.ssh/authorized_keys` . 通常,我们会使用共享存储,以便当用户通过 SSH 执行 Git 操作时,所有实例都能够访问该文件. 由于我们的设置中没有共享存储,因此我们将更新配置,以通过 GitLab 数据库中的索引查找来授权 SSH 用户. + +按照[通过 GitLab Shell 设置快速查找中](../../administration/operations/fast_ssh_key_lookup.html#setting-up-fast-lookup-via-gitlab-shell)的说明,从使用`authorized_keys`文件切换到数据库. + +如果不配置快速查找,则通过 SSH 进行的 Git 操作将导致以下错误: + +``` +Permission denied (publickey). +fatal: Could not read from remote repository. + +Please make sure you have the correct access rights +and the repository exists. +``` + +#### Configure host keys[](#configure-host-keys "Permalink") + +通常,我们将手动将主应用程序服务器上`/etc/ssh/`的内容(主密钥和公共密钥)复制到所有辅助服务器上的`/etc/ssh` . 这样可以防止在访问负载均衡器后面的群集中的服务器时出现虚假的中间人攻击警报. + +我们将通过创建静态主机密钥作为自定义 AMI 的一部分来自动执行此操作. 由于每次 EC2 实例启动时也会旋转这些主机密钥,因此将它们"硬编码"到我们的自定义 AMI 中是一种方便的解决方法. + +在您的 GitLab 实例上运行以下命令: + +``` +sudo mkdir /etc/ssh_static +sudo cp -R /etc/ssh/* /etc/ssh_static +``` + +在`/etc/ssh/sshd_config`更新以下内容: + +``` +# HostKeys for protocol version 2 +HostKey /etc/ssh_static/ssh_host_rsa_key +HostKey /etc/ssh_static/ssh_host_dsa_key +HostKey /etc/ssh_static/ssh_host_ecdsa_key +HostKey /etc/ssh_static/ssh_host_ed25519_key +``` + +#### Amazon S3 object storage[](#amazon-s3-object-storage "Permalink") + +由于我们不使用 NFS 进行共享存储,因此我们将使用[Amazon S3](https://aws.amazon.com/s3/)存储桶来存储备份,工件,LFS 对象,上传,合并请求差异,容器注册表映像等等. 我们的文档包括[有关如何](../../administration/object_storage.html)为每种数据类型[配置对象存储的说明](../../administration/object_storage.html) ,以及有关在 GitLab 中使用对象存储的其他信息. + +**注意:**由于我们使用的是之前创建的[AWS IAM 配置文件](#create-an-iam-role) ,因此在配置对象存储时,请确保省略 AWS 访问密钥和秘密访问密钥/值对. 而是在您的配置中使用`'use_iam_profile' => true` ,如上面链接的对象存储文档中所示. + +将更改保存到`gitlab.rb`文件后,切记要运行`sudo gitlab-ctl reconfigure` . + +**注意:** GitLab 的当前一项功能仍需要共享目录(NFS),即[GitLab Pages](../../user/project/pages/index.html) . 目前[正在进行的工作](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196) ,以消除支持 GitLab 页面需要 NFS. + +* * * + +到此,我们的 GitLab 实例的配置更改结束了. 接下来,我们将基于该实例创建自定义 AMI,以用于我们的启动配置和自动缩放组. + +### Create custom AMI[](#create-custom-ami "Permalink") + +在 EC2 仪表板上: + +1. 选择我们[之前创建](#install-gitlab)的`GitLab`实例. +2. 单击" **操作"** ,向下滚动到" **图像"** ,然后单击" **创建图像"** . +3. 给您的图像起一个名称和描述(我们将同时使用`GitLab-Source` ). +4. 将其他所有内容保留为默认值,然后单击**创建图像** + +现在,我们有了一个定制的 AMI,将用于下一步创建启动配置. + +## Deploy GitLab inside an auto scaling group[](#deploy-gitlab-inside-an-auto-scaling-group "Permalink") + +### Create a launch configuration[](#create-a-launch-configuration "Permalink") + +从 EC2 仪表板: + +1. 从左侧菜单中选择**启动配置** ,然后单击**创建启动配置** . +2. 从左侧菜单中选择**我的 AMI** ,然后选择我们在上面创建的`GitLab`自定义 AMI. +3. 选择最适合您需求的实例类型(至少为`c5.xlarge` ),然后单击**配置详细信息** . +4. 输入启动配置的名称(我们将使用`gitlab-ha-launch-config` ). +5. **不要** check **请求竞价型实例**. +6. 从**IAM 角色**下拉列表中,选择我们[之前创建](#create-an-iam-ec2-instance-role-and-profile)的`GitLabAdmin`实例角色. +7. 将其余的保留为默认值,然后单击" **添加存储"** . +8. 默认情况下,根卷为 8GiB,并且在我们不会在其中存储任何数据的情况下,根卷应该足够. 单击**配置安全组** . +9. 选中**选择和现有安全组,**然后选择我们之前创建的`gitlab-loadbalancer-sec-group` . +10. 点击**查看** ,查看您的更改,然后点击**创建启动配置** . +11. 确认您有权访问私钥或创建一个新私钥. 单击**创建启动配置** . + +### Create an auto scaling group[](#create-an-auto-scaling-group "Permalink") + +1. 创建启动配置后,您将看到一个**使用此启动配置创建 Auto Scaling 组**的选项. 单击以开始创建自动缩放组. +2. 输入一个**组名** (我们将使用`gitlab-auto-scaling-group` ). +3. 对于**Group size** ,输入您要开始的实例数(我们将输入`2` ). +4. 从" **网络"**下拉列表中选择`gitlab-vpc` . +5. 添加[我们先前创建的](#subnets)两个专用[子网](#subnets) . +6. 展开" **高级详细信息"**部分,然后选中" **从一个或多个负载平衡器接收流量"**选项. +7. 从**经典负载均衡器**下拉列表中,选择我们之前创建的负载均衡器. +8. For **健康检查类型**, select **ELB**. +9. 我们将" **健康检查宽限期"**保留为默认的`300`秒. 单击" **配置扩展策略"** . +10. Check **使用扩展策略来调整该组的容量**. +11. 对于该组,我们将在 2 到 4 个实例之间扩展,如果 CPU 利用率大于 60%将添加一个实例,如果 CPU 利用率小于 45%则删除一个实例. + +[![Auto scaling group policies](img/36aa502eb297ed552d82e3b015053e9e.png)](img/policies.png) + +1. 最后,根据需要配置通知和标签,查看更改并创建自动缩放组. + +创建自动伸缩组后,您将在 EC2 仪表板中看到新实例. 您还将看到新实例添加到您的负载均衡器. 一旦实例通过健康检查,它们就准备开始从负载平衡器接收流量. + +由于我们的实例是由自动缩放组创建的,因此请返回您的实例并终止[我们在上面手动创建](#install-gitlab)的[实例](#install-gitlab) . 我们只需要该实例即可创建我们的自定义 AMI. + +### Log in for the first time[](#log-in-for-the-first-time "Permalink") + +现在,使用[为负载均衡器](#configure-dns-for-load-balancer)设置[DNS](#configure-dns-for-load-balancer)时使用的域名,您现在应该能够在浏览器中访问 GitLab. 首次要求您为在 GitLab 实例上具有管理员权限的`root`用户设置密码. + +设置后,使用用户名`root`和新创建的密码登录. + +## Health check and monitoring with Prometheus[](#health-check-and-monitoring-with-prometheus "Permalink") + +除了可以在各种服务上启用的 Amazon Cloudwatch 之外,GitLab 还提供了自己的基于 Prometheus 的集成监控解决方案. 有关如何设置的更多信息,请访问[GitLab Prometheus 文档.](../../administration/monitoring/prometheus/index.html) + +GitLab 还具有各种[运行状况检查端点](../../user/admin_area/monitoring/health_check.html) ,您可以对其进行 ping 操作并获取报告. + +## GitLab Runners[](#gitlab-runners "Permalink") + +如果要利用[GitLab CI / CD](../../ci/README.html) ,则必须至少设置一个[GitLab Runner](https://docs.gitlab.com/runner/) . + +阅读有关[在 AWS](https://docs.gitlab.com/runner/configuration/runner_autoscale_aws/)上配置[自动缩放 GitLab Runner 的](https://docs.gitlab.com/runner/configuration/runner_autoscale_aws/)更多信息. + +## Backup and restore[](#backup-and-restore "Permalink") + +GitLab 提供[了一个备份](../../raketasks/backup_restore.html#back-up-gitlab)和还原其 Git 数据,数据库,附件,LFS 对象等的工具. + +一些重要的事情要知道: + +* 备份/还原工具**不**存储某些配置文件,例如机密. 您需要[自己配置](../../raketasks/backup_restore.html#storing-configuration-files) . +* 默认情况下,备份文件存储在本地,但是您可以[使用 S3 备份 GitLab](../../raketasks/backup_restore.html#using-amazon-s3) . +* 您可以[从备份中排除特定目录](../../raketasks/backup_restore.html#excluding-specific-directories-from-the-backup) . + +### Backing up GitLab[](#backing-up-gitlab "Permalink") + +备份 GitLab: + +1. SSH 进入您的实例. +2. 备份: + + ``` + sudo gitlab-backup create + ``` + +**注意:**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +### Restoring GitLab from a backup[](#restoring-gitlab-from-a-backup "Permalink") + +To restore GitLab, first review the [restore documentation](../../raketasks/backup_restore.html#restore-gitlab), and primarily the restore prerequisites. Then, follow the steps under the [Omnibus installations section](../../raketasks/backup_restore.html#restore-for-omnibus-gitlab-installations). + +## Updating GitLab[](#updating-gitlab "Permalink") + +GitLab 于 22 日每月发布一个新版本. 每当发布新版本时,您都可以更新您的 GitLab 实例: + +1. SSH 进入您的实例 +2. 备份: + + ``` + sudo gitlab-backup create + ``` + +**注意:**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +1. 更新存储库并安装 GitLab: + + ``` + sudo apt update + sudo apt install gitlab-ee + ``` + +几分钟后,新版本应已启动并正在运行. + +## Conclusion[](#conclusion "Permalink") + +在本指南中,我们主要进行了缩放和一些冗余选项,您的里程可能会有所不同. + +请记住,所有解决方案都需要在成本/复杂性和正常运行时间之间进行权衡. 您想要的正常运行时间越长,解决方案就越复杂. 解决方案越复杂,设置和维护该解决方案所涉及的工作就越多. + +通读以下其他资源,并随时[提出问题](https://gitlab.com/gitlab-org/gitlab/-/issues/new)以请求其他材料: + +* [扩展 GitLab](../../administration/reference_architectures/index.html) :GitLab 支持几种不同类型的集群. +* [Geo 复制](../../administration/geo/replication/index.html) :Geo 是面向广泛分布的开发团队的解决方案. +* [Omnibus GitLab-](https://docs.gitlab.com/omnibus/)您需要了解的有关管理 GitLab 实例的所有信息. +* [上载许可证](../../user/admin_area/license.html) : [使用许可证](../../user/admin_area/license.html)激活所有的 GitLab Enterprise Edition 功能. +* [定价](https://about.gitlab.com/pricing/) :不同层级的定价. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Instances are failing health checks[](#instances-are-failing-health-checks "Permalink") + +如果您的实例未通过负载均衡器的运行状况检查,请验证它们是否从我们之前配置的运行状况检查终结点返回状态`200` . 任何其他状态,包括重定向(例如状态`302` ),都会导致运行状况检查失败. + +您可能必须在`root`用户上设置密码,以防止在运行状况检查通过之前在登录端点上进行自动重定向. + +### “The change you requested was rejected (422)”[](#the-change-you-requested-was-rejected-422 "Permalink") + +如果你看到这个页面,试图设置通过网络界面输入密码时,请确保`external_url`在`gitlab.rb`你正在从一个请求域,并运行匹配`sudo gitlab-ctl reconfigure`进行任何更改之后. \ No newline at end of file diff --git a/docs/012.md b/docs/012.md new file mode 100644 index 0000000000000000000000000000000000000000..a2446ee93c4059a4196535aa608014b207485b1b --- /dev/null +++ b/docs/012.md @@ -0,0 +1,40 @@ +# Analytics + +> 原文:[https://docs.gitlab.com/ee/user/analytics/](https://docs.gitlab.com/ee/user/analytics/) + +* [Analytics workspace](#analytics-workspace) +* [Group-level analytics](#group-level-analytics) +* [Project-level analytics](#project-level-analytics) + +# Analytics[](#analytics "Permalink") + +## Analytics workspace[](#analytics-workspace "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12077) . + +通过 Analytics(分析)工作区,可以跨 GitLab 汇总分析,以便用户可以在一个地方查看多个项目和组中的信息. + +要访问 Google Analytics(分析)工作区,请单击顶部导航栏中的**更多>分析** . + +## Group-level analytics[](#group-level-analytics "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/195979) . + +在组级别可以使用以下分析功能: + +* [Contribution](../group/contribution_analytics/index.html). +* [Insights](../group/insights/index.html). +* [Issues](../group/issues_analytics/index.html). +* [生产力](productivity_analytics.html) (通过`productivity_analytics` [功能标记](../../development/feature_flags/development.html#enabling-a-feature-flag-in-development)启用). +* [值流](value_stream_analytics.html) ,通过`cycle_analytics` [功能标记](../../development/feature_flags/development.html#enabling-a-feature-flag-in-development)启用. + +## Project-level analytics[](#project-level-analytics "Permalink") + +在项目级别可以使用以下分析功能: + +* [CI/CD](../../ci/pipelines/index.html#pipeline-success-and-duration-charts). +* [Code Review](code_review_analytics.html). +* [Insights](../group/insights/index.html). +* [Issues](../group/issues_analytics/index.html). +* [Repository](repository_analytics.html). +* [值流](value_stream_analytics.html) ,通过`cycle_analytics` [功能标记](../../development/feature_flags/development.html#enabling-a-feature-flag-in-development)启用. \ No newline at end of file diff --git a/docs/013.md b/docs/013.md new file mode 100644 index 0000000000000000000000000000000000000000..8743ce152e598a049b28436eb559af5e5cd70437 --- /dev/null +++ b/docs/013.md @@ -0,0 +1,49 @@ +# Code Review Analytics + +> 原文:[https://docs.gitlab.com/ee/user/analytics/code_review_analytics.html](https://docs.gitlab.com/ee/user/analytics/code_review_analytics.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Permissions](#permissions) + +# Code Review Analytics[](#code-review-analytics-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38062) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.7. + +通过 Code Review Analytics,可以轻松地查看打开的合并请求中运行时间最长的审查,从而使您可以对单个合并请求采取措施,并缩短总体周期. + +**注意:**最初,不会显示任何数据. 用户在打开的合并请求中发表评论时,将填充数据. + +## Overview[](#overview "Permalink") + +Code Review Analytics 显示一个打开的合并请求表,该请求至少具有一个非作者注释. 审阅时间从提交第一个非作者评论的时间开始计算. 合并请求的代码审阅时间自动标识为自第一个非作者评论以来的时间. + +要访问 Code Review Analytics,请从您项目的菜单中转到 **项目分析>代码审查** . + +[![Code Review Analytics](img/0124687ca256ab68d34dd0918f1e1a8d.png "List of code reviews; oldest review first.")](img/code_review_analytics_v12_8.png) + +* 该表格按评论时长排序,可帮助您快速找到运行时间最长的评论,这可能需要干预或分解成较小的部分. +* 您可以按里程碑和标签过滤 MR 列表. +* 用于显示作者,批准者,评论数和行更改(-/ +)数的列. + +## Use cases[](#use-cases "Permalink") + +此功能专为[开发团队负责](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#delaney-development-team-lead)人和其他想了解广泛的代码审查动态并确定模式以对其进行解释的人员而设计. + +您可以使用 Code Review Analytics 通过代码审查来揭露团队的独特挑战,并确定可能会大大加快开发周期的改进. + +在以下情况下可以使用代码审查分析: + +* 您的团队同意代码审查进度太慢. +* [价值流分析功能](value_stream_analytics.html)表明,审核是您团队最耗时的步骤. + +您可以使用 Code Review Analytics 查看当前运行最慢的工作类型,并分析它们之间的模式和趋势. 例如: + +* 很多评论或承诺? 也许代码太复杂了. +* 涉及特定作者吗? 也许需要更多的培训. +* 评论和批准者很少? 也许您的团队人手不足. + +## Permissions[](#permissions "Permalink") + +* 在[简化版或青铜级](https://about.gitlab.com/pricing/)上. +* 由具有 Reporter 访问权限及以上权限的用户组成. \ No newline at end of file diff --git a/docs/014.md b/docs/014.md new file mode 100644 index 0000000000000000000000000000000000000000..1c80f2ec3f6019d2b886758914547fdc914c5fbd --- /dev/null +++ b/docs/014.md @@ -0,0 +1,91 @@ +# Productivity Analytics + +> 原文:[https://docs.gitlab.com/ee/user/analytics/productivity_analytics.html](https://docs.gitlab.com/ee/user/analytics/productivity_analytics.html) + +* [Supported features](#supported-features) +* [Accessing metrics and visualizations](#accessing-metrics-and-visualizations) +* [Date ranges](#date-ranges) +* [Permissions](#permissions) +* [Enabling and disabling using feature flags](#enabling-and-disabling-using-feature-flags) + +# Productivity Analytics[](#productivity-analytics-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12079) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3. + +使用 Productivity Analytics 追踪发展速度. + +For many companies, the development cycle is a black box and getting an estimate of how long, on average, it takes to deliver features is an enormous endeavor. + +虽然[价值流分析](../project/cycle_analytics.html)专注于整个软件开发生命周期(SDLC)流程,但生产力分析为工程管理提供了一种以系统的方式向下钻取的方法,以揭示在个人,项目或团队级别上的模式以及成败的原因. + +生产力降低的原因很多,从降低代码库到快速成长的团队. 为了进行调查,部门或团队负责人可以从可视化合并请求所花费的时间开始. + +## Supported features[](#supported-features "Permalink") + +生产力分析允许 GitLab 用户执行以下操作: + +* 可视化典型的合并请求(MR)生存期和统计信息. 使用直方图显示创建和合并合并请求之间经过的时间分布. +* 深入研究最耗时的合并请求,选择一些异常值,然后筛选所有后续图表以调查潜在原因. +* 按组,项目,作者,标签,里程碑或特定日期范围过滤. 例如,在里程碑或特定日期范围内,筛选出组或项目中特定作者的合并请求. +* 测量随时间变化的速度. 随时间推移可视化以上图表中每个指标的趋势,以观察进度. 如果发现异常值,请放大特定的日期范围. + +## Accessing metrics and visualizations[](#accessing-metrics-and-visualizations "Permalink") + +要访问该图表,请导航至组的侧边栏,然后选择**Analytics(分析)> Productivity Analytics(生产力分析)** . + +以下度量标准和可视化在项目或组级别可用-当前仅涵盖**合并的**合并请求: + +* 直方图,显示创建后经过指定天数进行合并的合并请求数. 选择一个特定的列以筛选后续的图表. +* 直方图显示了合并合并请求所花费的时间(以小时为单位)的细目. 可以使用以下间隔: + * 从第一次提交到第一次评论的时间. + * 从第一次评论到最后一次提交的时间. + * 从上次提交到合并的时间. +* 使用以下内容显示合并请求的大小或复杂度的直方图: + * 每个合并请求的提交数. + * 每次提交的代码行数. + * 触摸的文件数. +* 散点图显示所有 MR 在特定日期合并,以及完成操作所需的天数和 30 天的滚动中位数. +* 该表显示了合并请求的列表及其各自的持续时间指标. + * 用户可以按上述任何指标进行排序. + +## Date ranges[](#date-ranges "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13188) . + +GitLab 能够根据日期范围过滤分析. 要过滤结果: + +1. 选择一个组. +2. (可选)选择一个项目. +3. 使用可用的日期选择器选择日期范围. + +## Permissions[](#permissions "Permalink") + +只能访问**Productivity Analytics**仪表板: + +* 在[高级或银级](https://about.gitlab.com/pricing/)以上. +* 由具有[Reporter 访问权限](../permissions.html)及以上[权限的](../permissions.html)用户组成. + +## Enabling and disabling using feature flags[](#enabling-and-disabling-using-feature-flags "Permalink") + +生产力分析是: + +* [默认情况下](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18754)从 GitLab 12.4 [启用](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18754) ,但可以使用以下功能标志禁用: + * `productivity_analytics` . + * `productivity_analytics_scatterplot_enabled` . +* 在 GitLab 12.3 中默认为禁用,但可以使用以下功能标志启用: + * `productivity_analytics` . + +GitLab 管理员可以: + +* 通过在 Rails 控制台中运行以下命令,从 GitLab 12.4 禁用此功能: + + ``` + Feature.disable(:productivity_analytics) + Feature.disable(:productivity_analytics_scatterplot_enabled) + ``` + +* 通过在 Rails 控制台中运行以下命令,在 GitLab 12.3 中启用此功能: + + ``` + Feature.enable(:productivity_analytics) + ``` \ No newline at end of file diff --git a/docs/015.md b/docs/015.md new file mode 100644 index 0000000000000000000000000000000000000000..571c1984e5848d74a125a4302a5f3284f97814bd --- /dev/null +++ b/docs/015.md @@ -0,0 +1,298 @@ +# Value Stream Analytics + +> 原文:[https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html](https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html) + +* [Overview](#overview) +* [Date ranges](#date-ranges) +* [How Time metrics are measured](#how-time-metrics-are-measured) +* [How the stages are measured](#how-the-stages-are-measured) +* [Example workflow](#example-workflow) +* [Customizable Value Stream Analytics](#customizable-value-stream-analytics) + * [Stage path](#stage-path) + * [Adding a stage](#adding-a-stage) + * [Re-ordering stages](#re-ordering-stages) + * [Label based stages](#label-based-stages) + * [Hiding unused stages](#hiding-unused-stages) +* [Days to completion chart](#days-to-completion-chart) + * [Chart median line](#chart-median-line) + * [Disabling chart](#disabling-chart) + * [Disabling chart median line](#disabling-chart-median-line) +* [Type of work - Tasks by type chart](#type-of-work---tasks-by-type-chart) +* [Permissions](#permissions) +* [More resources](#more-resources) + +# Value Stream Analytics[](#value-stream-analytics "Permalink") + +版本历史 + +* 在项目级别在 GitLab 12.3 之前作为 Cycle Analytics 引入. +* 在小组级别的[GitLab Premium](https://about.gitlab.com/pricing/) 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12077) . +* 在 GitLab 12.8 中从 Cycle Analytics [重命名](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23427)为 Value Stream Analytics. + +Value Stream Analytics measures the time spent to go from an [idea to production](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab) (also known as cycle time) for each of your projects. Value Stream Analytics displays the median time spent in each stage defined in the process. + +有关如何为 Value Stream Analytics 的发展做出贡献的信息,请参阅我们的[贡献者文档](../../development/value_stream_analytics.html) . + +值流分析有助于快速确定给定项目的速度. 它指出了开发过程中的瓶颈,从而使管理层能够发现,分类和识别软件开发生命周期中速度下降的根本原因. + +Value Stream Analytics 与[GitLab 流程](../../topics/gitlab_flow.html)紧密结合,并为每个阶段计算单独的中位数. + +## Overview[](#overview "Permalink") + +价值流分析可用: + +* 在 GitLab 12.9 中,通过**组>分析>值流**在组级别. +* 在项目级别,通过" **项目">"分析">"价值流"** . + +作为"价值流分析"计算的一部分,将跟踪七个阶段. + +* **Issue** (Tracker) + * 安排问题的时间(按里程碑或通过将其添加到问题板) +* **Plan** (Board) + * 第一次提交的时间 +* **Code** (IDE) + * 是时候创建合并请求了 +* **Test** (CI) + * GitLab CI / CD 测试代码所需的时间 +* **审核** (合并请求/ MR) + * 花在代码审查上的时间 +* **暂存** (连续部署) + * 合并和部署到生产之间的时间 +* **Total** (Total) + * 总生命周期时间. 也就是说,项目或团队的速度. [以前称为](https://gitlab.com/gitlab-org/gitlab/-/issues/38317) **Production** . + +## Date ranges[](#date-ranges "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13216) . + +GitLab 提供了根据日期范围过滤分析的功能. 要过滤结果: + +1. 选择一个组. +2. (可选)选择一个项目. +3. 使用可用的日期选择器选择日期范围. + +## How Time metrics are measured[](#how-time-metrics-are-measured "Permalink") + +页面顶部附近的"时间"指标的测量方法如下: + +* **提前期** :从创建问题到关闭问题的平均时间. +* **周期时间** :从第一次提交到发布完成的中值时间. + +注意:通过在提交消息中进行[交联](../project/issues/crosslinking_issues.html)或通过手动链接包含提交的合并请求,将提交与问题相关[联](../project/issues/crosslinking_issues.html) . + +[![Value stream analytics time metrics](img/f7050ce0aa3559c639befc2fe3d7aacb.png "Time metrics for value stream analytics")](img/vsa_time_metrics_v13_0.png) + +## How the stages are measured[](#how-the-stages-are-measured "Permalink") + +Value Stream Analytics 根据项目问题记录阶段时间和数据,但阶段和总阶段除外,在阶段和总阶段中,仅测量部署到生产中的数据. + +具体而言,如果未设置 CI 且尚未定义`production`或`production/*` [环境](../../ci/yaml/README.html#environment) ,则此阶段将没有任何数据. + +下表进一步描述了价值流分析的每个阶段. + +| **Stage** | **Description** | +| --- | --- | +| Issue | 通过标记问题或将其添加到里程碑中,以先发生的为准,来衡量从创建问题到采取行动解决问题之间的平均时间. 仅在标签已经为其创建了[发行委员会列表的](../project/issue_board.html)情况下,才会跟踪该标签. | +| Plan | 测量您在上一阶段采取的操作与将第一次提交推入分支之间的平均时间. 分支的第一个提交是触发**计划**和**代码**之间分离的提交,并且分支中的至少一个提交需要包含相关的发行编号(例如`#42` ). 如果分支中的所有提交都未提及相关的发行号,则不会考虑该阶段的度量时间. | +| Code | 测量推入第一个提交(上一阶段)与创建与该提交相关的合并请求(MR)之间的平均时间. 保持流程跟踪的关键是在合并请求的描述中包括[问题关闭模式](../project/issues/managing_issues.html#closing-issues-automatically) (例如, `Closes #xxx` ,其中`xxx`是与此合并请求相关的问题编号). 如果合并请求描述中不存在问题结束模式,则不会将 MR 视为平台的测量时间. | +| Test | 测量运行该项目的整个管道的中值时间. 这与 GitLab CI / CD 为推送到上一阶段中定义的合并请求的提交运行每个作业所花费的时间有关. 基本上,这是所有管道的开始->完成时间. | +| Review | 测量从创建到合并之间,审核具有结束问题模式的合并请求所需的平均时间. | +| Staging | 测量从合并合并请求到结束发布模式到首次部署到生产之间的平均时间. 在您的 GitLab CI / CD 配置中,通过设置为`production`或匹配`production/*` (区分大小写, `Production`将不起作用)的环境进行跟踪. 如果没有生产环境,则不会进行跟踪. | +| Total | 从问题创建到将代码部署到生产中,运行整个过程所需的所有时间(中位数)之和. [以前称为](https://gitlab.com/gitlab-org/gitlab/-/issues/38317) **Production** . | + +幕后工作原理: + +1. 问题和合并请求成对地分组在一起,这样对于每个``对,合并请求都具有对应问题的[问题关闭模式](../project/issues/managing_issues.html#closing-issues-automatically) . **不**考虑所有其他问题和合并请求. +2. 然后,在最近的 XX 天(由 UI 指定-默认为 90 天)中过滤出``对. 因此,它禁止考虑这些对. +3. 对于其余的``对,我们检查阶段所需的信息,例如发行日期,合并请求合并时间等. + +综上所述,不会跟踪任何未遵循[GitLab 流程的](../../workflow/gitlab_flow.html)内容,并且 Value Stream Analytics 仪表板将不会显示以下任何数据: + +* 合并不会解决问题的请求. +* 未在发行委员会中贴有标签的问题或未分配里程碑的问题. +* 如果项目没有`production`或`production/*`环境,则为阶段和生产阶段. + +## Example workflow[](#example-workflow "Permalink") + +以下是一个简单的虚拟周期工作流,它在一天中经历了所有七个阶段后,才发生. 请注意,如果一个阶段没有开始和结束标记,则不会对其进行测量,因此不会在中位时间中进行计算. 假定已创建里程碑并配置了用于测试和设置环境的 CI. + +1. 在 09:00( **发行**阶段开始)创建**发行** . +2. 在 11:00( **发行**阶段停止/ **计划**阶段开始)将发行添加到里程碑. +3. 开始解决此问题,在本地创建一个分支,并在 12:00 提交一次. +4. 对分支进行第二次提交,该分支在 12.30( **计划**阶段的停止/ **代码**阶段的开始)中提及发行号. +5. 推送分支并创建一个合并请求,该请求的描述在 14:00( **代码**阶段停止/ **测试**和**复审**阶段开始)中包含[问题关闭模式](../project/issues/managing_issues.html#closing-issues-automatically) . +6. CI 将开始运行您在[`.gitlab-ci.yml`](../../ci/yaml/README.html)定义的脚本,并需要 5 分钟( **测试**阶段停止). +7. 查看合并请求,确保一切正常,然后在 19:00 合并合并请求. ( **复习**阶段的停止/启动**分期**阶段). +8. 现在,合并请求合并,部署到`production`环境中开始和结束日 19:30( **分期**阶段停止). +9. 循环完成,并且先前阶段的中位数时间总和记录到" **总计"**阶段. 这是从创建问题到将其相关合并请求部署到生产之间的时间. + +从上面的示例中,您可以得出每个阶段完成所需的时间,只要达到其总时间即可: + +* **问题** :2 小时(11:00-09:00) +* **计划** :1 小时(12:00-11:00) +* **编码** :2h(14:00-12:00) +* **测试时间** :5 分钟 +* **评论** :5 小时(19:00-14:00) +* **演出时间** :30 分钟(19:30-19:00) +* **总计** :由于此阶段测量的是之前所有阶段的中位时间之和,因此如果我们不知道之前各阶段的状态,则无法计算. 如果这是项目中运行的第一个周期,则**总**时间为 10h 30min(19:30-09:00) + +一些注意事项: + +* 在上面的示例中,我们演示了您的第一次提交没有提到发行号也没关系,您可以稍后在正在处理的分支的任何提交中进行此操作. +* 您可以看到,由于未将" **测试"**阶段计算为整个周期的时间,因此" **检查"**阶段已包含在" **审查"**过程中(应测试每个 MR). +* 上面的示例只是七个阶段中的**一个循环** . 添加多个周期,计算它们的中值时间,结果就是 Value Stream Analytics 仪表板显示的内容. + +## Customizable Value Stream Analytics[](#customizable-value-stream-analytics "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12196) . + +默认阶段旨在直接使用,但是可能并不适合所有团队. 不同的团队使用不同的方法来构建软件,因此一些团队可能想要自定义其 Value Stream Analytics. + +GitLab 允许用户隐藏默认阶段并创建自定义阶段,使其更适合其开发工作流程. + +**注意:**自定义性[仅适用于组级别的](https://gitlab.com/gitlab-org/gitlab/-/issues/35823#note_272558950)价值流分析. + +### Stage path[](#stage-path "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/210315) . + +从视觉上将阶段描绘为水平过程流. 选择一个阶段将更新值流下方的内容. + +默认情况下禁用. 如果您具有自我管理的实例,则管理员可以[打开 Rails 控制台](../../administration/troubleshooting/navigating_gitlab_via_rails_console.html)并使用以下命令启用它: + +``` +Feature.enable(:value_stream_analytics_path_navigation) +``` + +### Adding a stage[](#adding-a-stage "Permalink") + +在下面的示例中,我们将创建一个新阶段,该阶段可以衡量和跟踪从创建到关闭的所有问题. + +1. 导航到您组的" **分析">"价值流"** . +2. 单击**添加阶段**按钮. +3. 填写新的舞台表格: + * 名称:问题开始完成. + * 开始事件:已创建问题. + * 结束事件:问题已关闭. +4. 单击**添加阶段**按钮. + +[![New Value Stream Analytics Stage](img/d1c47110b6092ce9cec04ff22addfaa4.png "Form for creating a new stage")](img/new_vsm_stage_v12_9.png) + +新阶段将保持不变,并将始终显示在您组的"价值流分析"页面上. + +如果要更改或删除阶段,可以通过以下方法轻松地针对自定义阶段进行操作: + +1. Hovering over the stage. +2. 单击垂直省略号( )出现的按钮. + +[![Value Stream Analytics Stages](img/d277485e75207494ed3529dfcc7a6395.png)](img/vsm_stage_list_v12_9.png) + +创建自定义阶段需要指定两个事件: + +* 开始. +* 结束. + +请小心选择*在*结束事件*之前*发生的开始事件. 例如,考虑一个阶段: + +* 在将问题添加到板上时开始. +* 创建问题时结束. + +此阶段将不起作用,因为开始事件发生时,结束事件已经发生. 为防止此类无效阶段,UI 禁止出现不兼容的开始和结束事件. 选择开始事件后,停止事件下拉列表将仅列出兼容事件. + +### Re-ordering stages[](#re-ordering-stages "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/196698) . + +添加自定义阶段后,您可以"拖放"阶段以重新排列其顺序. 这些更改将自动保存到系统中. + +### Label based stages[](#label-based-stages "Permalink") + +预定义的开始和结束事件可以涵盖涉及问题和合并请求的许多用例. + +为了支持更复杂的工作流程,请使用基于组标签的阶段. 这些事件基于添加或删除的标签. 特别是, [范围标签](../project/labels.html#scoped-labels-premium)对于复杂的工作流程很有用. + +在此示例中,我们希望测量更准确的代码检查时间. 工作流程如下: + +* 代码审阅开始时,审阅者将`workflow::code_review_start`标签添加到合并请求中. +* 代码检查完成后,检查者将`workflow::code_review_complete`标签添加到合并请求中. + +创建一个称为"代码审查"的新阶段: + +[![New Label Based Value Stream Analytics Stage](img/ea01744c06eb8853392bfd840dc1517d.png "Creating a label based Value Stream Analytics Stage")](img/label_based_stage_vsm_v12_9.png) + +### Hiding unused stages[](#hiding-unused-stages "Permalink") + +有时某些默认阶段与团队无关. 在这种情况下,您可以轻松隐藏阶段,使它们不再出现在列表中. 隐藏阶段: + +1. 添加定制阶段以激活可定制性. +2. 将鼠标悬停在要隐藏的默认阶段上. +3. 单击垂直省略号( )按钮出现,然后选择" **隐藏舞台"** . + +要恢复以前隐藏的默认阶段: + +1. Click **添加一个阶段** button. +2. 在右上角打开" **恢复隐藏的阶段"**下拉列表. +3. 选择一个阶段. + +## Days to completion chart[](#days-to-completion-chart "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21631) . + +该图表直观地描述了完成周期所需的总天数. + +该图表使用全局页面过滤器来基于选定的组,项目和时间范围显示数据. 此外,可以从图表本身内选择特定阶段. + +### Chart median line[](#chart-median-line "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36675) . + +图表上的中间线显示的数据偏移了所选的天数. 例如,如果选择了 30 天的数据(例如 2019-12-16 至 2020-01-15),则中线将代表前 30 天的数据(2019-11-16 至 2019-12 -16)作为要比较的指标. + +### Disabling chart[](#disabling-chart "Permalink") + +This chart is enabled by default. If you have a self-managed instance, an administrator can open a Rails console and disable it with the following command: + +``` +Feature.disable(:cycle_analytics_scatterplot_enabled) +``` + +### Disabling chart median line[](#disabling-chart-median-line "Permalink") + +默认情况下,此图表的中线是启用的. 如果您具有自我管理的实例,则管理员可以打开 Rails 控制台并使用以下命令将其禁用: + +``` +Feature.disable(:cycle_analytics_scatterplot_median_enabled) +``` + +## Type of work - Tasks by type chart[](#type-of-work---tasks-by-type-chart "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32421) . + +此图表显示每天的问题和合并请求的累积计数. + +该图表使用全局页面过滤器来基于选定的组,项目和时间范围显示数据. 该图表默认为显示问题计数,但可以切换为显示合并请求数据,并进一步细化为特定的组级标签. + +默认情况下,预先选择了最高的组级别标签(最多 10 个),最多可以选择 15 个标签. + +## Permissions[](#permissions "Permalink") + +Project Value Stream Analytics 仪表板上的当前权限为: + +* 公共项目-任何人都可以访问. +* 内部项目-任何经过身份验证的用户都可以访问. +* 私人项目-访客及以上的任何成员都可以访问. + +您通常可以[阅读有关权限的更多信息](../../ci/yaml/README.html) . + +对于 GitLab 12.3 和更高版本中引入的 Value Stream Analytics 功能: + +* 用户必须具有 Reporter 或更高权限. +* 仅在[Premium 或 Silver 等级](https://about.gitlab.com/pricing/)及更高[级别](https://about.gitlab.com/pricing/)上可用. + +## More resources[](#more-resources "Permalink") + +Learn more about Value Stream Analytics in the following resources: + +* [Value Stream Analytics feature page](https://about.gitlab.com/stages-devops-lifecycle/value-stream-analytics/). +* [Value Stream Analytics feature preview](https://about.gitlab.com/blog/2016/09/16/feature-preview-introducing-cycle-analytics/). +* [Value Stream Analytics feature highlight](https://about.gitlab.com/blog/2016/09/21/cycle-analytics-feature-highlight/). \ No newline at end of file diff --git a/docs/016.md b/docs/016.md new file mode 100644 index 0000000000000000000000000000000000000000..4ce588b0d0e27519d83261314aa935773d7e0fea --- /dev/null +++ b/docs/016.md @@ -0,0 +1,309 @@ +# Kubernetes clusters + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/](https://docs.gitlab.com/ee/user/project/clusters/) + +* [Overview](#overview) +* [Setting up](#setting-up) + * [Supported cluster versions](#supported-cluster-versions) + * [Adding and removing clusters](#adding-and-removing-clusters) + * [Multiple Kubernetes clusters](#multiple-kubernetes-clusters) + * [Setting the environment scope](#setting-the-environment-scope-premium) +* [Configuring your Kubernetes cluster](#configuring-your-kubernetes-cluster) + * [Security implications](#security-implications) + * [GitLab-managed clusters](#gitlab-managed-clusters) + * [Important notes](#important-notes) + * [Clearing the cluster cache](#clearing-the-cluster-cache) + * [Base domain](#base-domain) +* [Installing applications](#installing-applications) +* [Auto DevOps](#auto-devops) +* [Deploying to a Kubernetes cluster](#deploying-to-a-kubernetes-cluster) + * [Deployment variables](#deployment-variables) + * [Custom namespace](#custom-namespace) + * [Integrations](#integrations) + * [Canary Deployments](#canary-deployments-premium) + * [Deploy Boards](#deploy-boards-premium) + * [Viewing pod logs](#viewing-pod-logs) + * [Web terminals](#web-terminals) + * [Troubleshooting](#troubleshooting) +* [Monitoring your Kubernetes cluster](#monitoring-your-kubernetes-cluster) + * [Visualizing cluster health](#visualizing-cluster-health) + +# Kubernetes clusters[](#kubernetes-clusters "Permalink") + +版本历史 + +* 在项目的 GitLab 10.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35954) . +* 在 GitLab 11.6 中针对[组](../../group/clusters/index.html) [引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34758) . +* 在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39840)了[实例](../../instance/clusters/index.html) . + +## Overview[](#overview "Permalink") + +使用 GitLab 项目 Kubernetes 集成,您可以: + +* Use [Review Apps](../../../ci/review_apps/index.html). +* Run [pipelines](../../../ci/pipelines/index.html). +* [部署](#deploying-to-a-kubernetes-cluster)您的应用程序. +* 检测和[监控 Kubernetes](#monitoring-your-kubernetes-cluster) . +* 与[Auto DevOps](#auto-devops)一起使用. +* Use [Web terminals](#web-terminals). +* Use [Deploy Boards](#deploy-boards-premium). +* Use [Canary Deployments](#canary-deployments-premium). +* View [Logs](#viewing-pod-logs). +* [使用 Knative](serverless/index.html)在[Kubernetes 上](serverless/index.html)运行无服务器工作负载. + +除了在项目级别进行集成之外,Kubernetes 集群还可以在[组级别](../../group/clusters/index.html)或[GitLab 实例级别](../../instance/clusters/index.html)进行集成. + +## Setting up[](#setting-up "Permalink") + +### Supported cluster versions[](#supported-cluster-versions "Permalink") + +GitLab 承诺在任何给定时间至少支持两个生产就绪的 Kubernetes 次要版本. 我们会定期审查我们支持的版本,并提供四个月的弃用期,然后再删除特定版本的支持. 支持的版本范围基于以下方面的评估: + +* 我们自己的需求. +* 主要托管 Kubernetes 提供商支持的版本. +* [Kubernetes 社区支持](https://kubernetes.io/docs/setup/release/version-skew-policy/#supported-versions)的版本. + +当前,GitLab 支持以下 Kubernetes 版本: + +* 1.16 +* 1.15 +* 1.14 +* 1.13(不建议使用,支持终止于 2020 年 11 月 22 日) +* 1.12(不建议使用,支持终止于 2020 年 9 月 22 日) + +**注意:**某些 GitLab 功能可能支持此处提供的范围之外的版本. + +### Adding and removing clusters[](#adding-and-removing-clusters "Permalink") + +有关如何执行以下操作的详细信息,请参见[添加和删​​除 Kubernetes 集群](add_remove_clusters.html) : + +* 使用 GitLab 的 UI 在 Google Cloud Platform(GCP)或 Amazon Elastic Kubernetes Service(EKS)中创建集群. +* 从任何 Kubernetes 平台向现有集群添加集成. + +### Multiple Kubernetes clusters[](#multiple-kubernetes-clusters "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 10.3 中引入 +* 在 13.2 中[移至](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094) GitLab 核心. + +您可以将多个 Kubernetes 集群关联到您的项目. 这样,您可以为不同的环境(例如开发,登台,生产等)使用不同的集群. + +就像您第一次一样,只需添加另一个集群,并确保[设置一个环境范围即可](#setting-the-environment-scope-premium)将新集群与其他集群区分开. + +#### Setting the environment scope[](#setting-the-environment-scope-premium "Permalink") + +将多个 Kubernetes 集群添加到您的项目时,您需要通过环境范围来区分它们. 环境范围将群集与[环境](../../../ci/environments/index.html)相关联,类似于[特定](../../../ci/variables/README.html#limit-the-environment-scopes-of-environment-variables)于[环境的变量的](../../../ci/variables/README.html#limit-the-environment-scopes-of-environment-variables)工作方式. + +默认环境范围是`*` ,这意味着所有作业,无论其环境如何,都将使用该群集. 每个作用域只能由项目中的单个群集使用,否则将发生验证错误. 另外,没有设置环境关键字的作业将无法访问任何群集. + +例如,假设项目中存在以下 Kubernetes 集群: + +| Cluster | 环境范围 | +| --- | --- | +| Development | `*` | +| Production | `production` | + +[`.gitlab-ci.yml`](../../../ci/yaml/README.html)中设置了以下环境: + +``` +stages: + - test + - deploy + +test: + stage: test + script: sh test + +deploy to staging: + stage: deploy + script: make deploy + environment: + name: staging + url: https://staging.example.com/ + +deploy to production: + stage: deploy + script: make deploy + environment: + name: production + url: https://example.com/ +``` + +结果将是: + +* The Development cluster details will be available in the `deploy to staging` job. +* 生产集群详细信息将在`deploy to production`作业中提供. +* `test`作业中没有可用的群集详细信息,因为它没有定义任何环境. + +## Configuring your Kubernetes cluster[](#configuring-your-kubernetes-cluster "Permalink") + +[将 Kubernetes 群集添加](add_remove_clusters.html)到 GitLab 之后,请阅读本节,其中涵盖了使用 GitLab 配置 Kubernetes 群集的重要注意事项. + +### Security implications[](#security-implications "Permalink") + +**Important:** The whole cluster security is based on a model where [developers](../../permissions.html) are trusted, so **仅允许受信任的用户控制您的集群**. + +默认的群集配置授予对成功构建和部署容器化应用程序所需的广泛功能的访问权限. 请记住,群集上运行的所有应用程序都使用相同的凭据. + +### GitLab-managed clusters[](#gitlab-managed-clusters "Permalink") + +版本历史 + +* 在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22011) . +* 在 GitLab 11.11 中成为[可选](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26565) . + +您可以选择允许 GitLab 为您管理集群. 如果您的集群由 GitLab 管理,则将自动创建项目资源. 有关创建哪些资源的详细信息,请参见" [访问控制"](add_remove_clusters.html#access-controls)部分. + +如果选择管理自己的群集,则不会自动创建特定于项目的资源. 如果使用的是[Auto DevOps](../../../topics/autodevops/index.html) ,则需要显式提供部署作业将使用的`KUBE_NAMESPACE` [部署变量](#deployment-variables) ,否则将为您创建一个名称空间. + +#### Important notes[](#important-notes "Permalink") + +在 GitLab 和集群上注意以下几点: + +* 如果您在群集上[安装应用程序](#installing-applications) ,即使您选择管理自己的群集,GitLab 也会创建运行这些资源所需的资源. +* 请注意,手动管理由 GitLab 创建的资源(例如名称空间和服务帐户)可能会导致意外错误. 如果发生这种情况,请尝试[清除集群缓存](#clearing-the-cluster-cache) . + +#### Clearing the cluster cache[](#clearing-the-cluster-cache "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31759) . + +如果您选择允许 GitLab 为您管理集群,则 GitLab 将存储它为项目创建的名称空间和服务帐户的缓存版本. 如果在群集中手动修改这些资源,则此缓存可能与群集不同步,这可能导致部署作业失败. + +清除缓存: + +1. 导航到项目的" **操作">" Kubernetes"**页面,然后选择您的集群. +2. 展开**高级设置**部分. +3. Click **Clear cluster cache**. + +### Base domain[](#base-domain "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24580) . + +**注意:**使用 GitLab Serverless 时,无需在群集设置上指定基本域. 在这种情况下,域将被指定为 Knative 安装的一部分. 请参阅[安装应用程序](#installing-applications) . + +指定基本域将自动将`KUBE_INGRESS_BASE_DOMAIN`设置为环境变量. 如果您使用的是[Auto DevOps](../../../topics/autodevops/index.html) ,则此域将用于不同的阶段. 例如,"自动查看应用程序"和"自动部署". + +该域应将通配符 DNS 配置为入口 IP 地址. 安装 Ingress 之后(请参阅[安装应用程序](#installing-applications) ),您可以: + +* 创建一个指向您的域提供商指向入口 IP 地址的`A`记录. +* 使用 nip.io 或 xip.io 之类的服务输入通配符 DNS 地址. 例如, `192.168.1.1.xip.io` . + +## Installing applications[](#installing-applications "Permalink") + +GitLab 可以在项目级集群中安装和管理一些应用程序,例如 Helm,GitLab Runner,Ingress,Prometheus 等. 有关为项目集群安装,升级,卸载和故障排除应用程序的更多信息,请参阅[GitLab 托管应用程序](../../clusters/applications.html) . + +## Auto DevOps[](#auto-devops "Permalink") + +Auto DevOps 自动检测,构建,测试,部署和监视您的应用程序. + +要充分利用 Auto DevOps(自动部署,自动查看应用程序和自动监控),您需要启用 Kubernetes 项目集成. + +[Read more about Auto DevOps](../../../topics/autodevops/index.html) + +**注意** Kubernetes 群集可以在没有 Auto DevOps 的情况下使用. + +## Deploying to a Kubernetes cluster[](#deploying-to-a-kubernetes-cluster "Permalink") + +Kubernetes 集群可以作为部署作业的目标. 如果 + +* 该集群与 GitLab 集成在一起,特殊的[部署变量](#deployment-variables)可用于您的工作,并且不需要配置. 您可以使用诸如`kubectl`或`helm`工具立即开始从作业中与集群进行交互. +* 您无需使用 GitLab 的集群集成,仍然可以将其部署到集群中. 但是,您需要自己使用[环境变量](../../../ci/variables/README.html#custom-environment-variables)配置 Kubernetes 工具,然后才能通过作业与集群进行交互. + +### Deployment variables[](#deployment-variables "Permalink") + +Kubernetes 集群集成在 GitLab CI / CD 构建环境中公开了以下[部署变量](../../../ci/variables/README.html#deployment-environment-variables) . + +| Variable | Description | +| --- | --- | +| `KUBE_URL` | 等于 API URL. | +| `KUBE_TOKEN` | [环境服务帐户](add_remove_clusters.html#access-controls)的 Kubernetes 令牌. | +| `KUBE_NAMESPACE` | 与项目的部署服务帐户关联的名称空间. 格式为`--` . 对于由 GitLab 管理的集群,GitLab 会在集群中自动创建一个匹配的名称空间. | +| `KUBE_CA_PEM_FILE` | 包含 PEM 数据的文件的路径. 仅当指定了自定义 CA 捆绑包时才存在. | +| `KUBE_CA_PEM` | ( **已弃用** )原始 PEM 数据. 仅当指定了自定义 CA 捆绑包时. | +| `KUBECONFIG` | 包含用于此部署的`kubeconfig`的文件的路径. 如果指定,则将嵌入 CA 捆绑软件. 此配置还嵌入了在`KUBE_TOKEN`定义的相同令牌,因此您可能只需要此变量. 该变量名也会由`kubectl`自动选择,因此,如果使用`kubectl`则实际上不需要显式引用它. | +| `KUBE_INGRESS_BASE_DOMAIN` | 从 GitLab 11.8 开始,此变量可用于为每个群集设置一个域. 有关更多信息,请参见[群集域](#base-domain) . | + +**注意:**在 GitLab 11.5 之前, `KUBE_TOKEN`是集群集成的主要服务帐户的 Kubernetes 令牌.**注意:**如果您的集群是在 GitLab 12.2 之前创建的,则默认`KUBE_NAMESPACE`将设置为`-` . + +### Custom namespace[](#custom-namespace "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) . + +Kubernetes 集成默认为格式为`--`的特定于项目环境的名称空间(请参阅[部署变量](#deployment-variables) ). + +对于**非** GitLab 管理的集群,可以使用`.gitlab-ci.yml` [`environment:kubernetes:namespace`](../../../ci/environments/index.html#configuring-kubernetes-deployments)来定制[`environment:kubernetes:namespace`](../../../ci/environments/index.html#configuring-kubernetes-deployments) . + +**注意:**使用[GitLab 管理的集群时](#gitlab-managed-clusters) ,名称空间是在部署之前自动创建的, [无法自定义](https://gitlab.com/gitlab-org/gitlab/-/issues/38054) . + +### Integrations[](#integrations "Permalink") + +#### Canary Deployments[](#canary-deployments-premium "Permalink") + +利用[Kubernetes 的 Canary 部署,](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments)并在部署板内部可视化您的 Canary 部署,而无需离开 GitLab. + +[Read more about Canary Deployments](../canary_deployments.html) + +#### Deploy Boards[](#deploy-boards-premium "Permalink") + +GitLab 的部署板提供了 Kubernetes 上运行的每个 CI [环境](../../../ci/environments/index.html)的当前运行状况和状态的合并视图,显示了部署中 Pod 的状态. 开发人员和其他团队成员可以在已经使用的工作流程中逐个窗格地查看发布的进度和状态,而无需访问 Kubernetes. + +[Read more about Deploy Boards](../deploy_boards.html) + +#### Viewing pod logs[](#viewing-pod-logs "Permalink") + +使用 GitLab 可以轻松查看连接的 Kubernetes 集群中正在运行的 Pod 的日志. 通过直接在 GitLab 中显示日志,开发人员可以避免管理控制台工具或跳转到其他界面. + +[Read more about Kubernetes logs](kubernetes_pod_logs.html) + +#### Web terminals[](#web-terminals "Permalink") + +在 GitLab 8.15 中引入. + +启用后,Kubernetes 集成将为您的[环境](../../../ci/environments/index.html)添加[Web 终端](../../../ci/environments/index.html#web-terminals)支持. 这基于 Docker 和 Kubernetes 中的`exec`功能,因此您可以在现有容器中获得一个新的 Shell 会话. 要使用此集成,您应该使用上面的部署变量将其部署到 Kubernetes,并确保对所有部署,副本集和 Pod 进行注释: + +* `app.gitlab.com/env: $CI_ENVIRONMENT_SLUG` +* `app.gitlab.com/app: $CI_PROJECT_PATH_SLUG` + +`$CI_ENVIRONMENT_SLUG`和`$CI_PROJECT_PATH_SLUG`是 CI 变量的值. + +您必须是项目所有者或拥有`maintainer`权限才能使用终端. 支持仅限于环境中第一个容器中的第一个容器. + +### Troubleshooting[](#troubleshooting "Permalink") + +在开始部署作业之前,GitLab 将为部署作业专门创建以下内容: + +* 命名空间. +* A service account. + +但是,有时 GitLab 无法创建它们. 在这种情况下,您的工作将失败,并显示以下消息: + +``` +This job failed because the necessary resources were not successfully created. +``` + +要在创建名称空间和服务帐户时查找导致此错误的原因,请检查[日志](../../../administration/logs.html#kuberneteslog) . + +失败的原因包括: + +* 您为 GitLab 提供的令牌没有 GitLab 所需的[`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)特权. +* 缺少`KUBECONFIG`或`KUBE_TOKEN`变量. 要传递给您的工作,他们必须具有匹配的[`environment:name`](../../../ci/environments/index.html#defining-environments) . 如果您的作业没有设置`environment:name` ,则不会通过 Kubernetes 凭据. + +**注意:**从 GitLab 12.0 或更早版本升级的项目级群集可能以导致此错误的方式进行配置. 如果要自己管理名称空间和服务帐户,请确保取消选择由[GitLab 管理的群集](#gitlab-managed-clusters)选项. + +## Monitoring your Kubernetes cluster[](#monitoring-your-kubernetes-cluster "Permalink") + +自动检测和监控 Kubernetes 指标. 还支持[NGINX Ingress 的](../integrations/prometheus_library/nginx.html)自动监视. + +[Read more about Kubernetes monitoring](../integrations/prometheus_library/kubernetes.html) + +### Visualizing cluster health[](#visualizing-cluster-health "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4701) . +* 在 13.2 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/208224) GitLab 核心. + +[部署 Prometheus 后](#installing-applications) ,GitLab 将自动监视群集的运行状况. 在群集设置页面的顶部,显示 CPU 和内存利用率以及可用总量. 如果群集的内存不足,则监视群集资源可能很重要,可能会关闭或无法启动. + +[![Cluster Monitoring](img/0e27f7f7b1dd7b6748365d5ea985238a.png)](img/k8s_cluster_monitoring.png) \ No newline at end of file diff --git a/docs/017.md b/docs/017.md new file mode 100644 index 0000000000000000000000000000000000000000..44149203201a8e84ffd6b29e0d80e99ab486a7da --- /dev/null +++ b/docs/017.md @@ -0,0 +1,256 @@ +# Adding and removing Kubernetes clusters + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/add_remove_clusters.html](https://docs.gitlab.com/ee/user/project/clusters/add_remove_clusters.html) + +* [Before you begin](#before-you-begin) +* [Access controls](#access-controls) + * [Important notes](#important-notes) + * [RBAC cluster resources](#rbac-cluster-resources) + * [ABAC cluster resources](#abac-cluster-resources) + * [Security of GitLab Runners](#security-of-gitlab-runners) +* [Create new cluster](#create-new-cluster) +* [Add existing cluster](#add-existing-cluster) + * [Existing Kubernetes cluster](#existing-kubernetes-cluster) + * [Disable Role-Based Access Control (RBAC) (optional)](#disable-role-based-access-control-rbac-optional) +* [Enabling or disabling integration](#enabling-or-disabling-integration) +* [Removing integration](#removing-integration) +* [Learn more](#learn-more) + +# Adding and removing Kubernetes clusters[](#adding-and-removing-kubernetes-clusters "Permalink") + +GitLab 为以下 Kubernetes 提供者提供了集成的集群创建功能: + +* Google Kubernetes 引擎(GKE). +* Amazon Elastic Kubernetes 服务(EKS). + +GitLab 还可以与本地或托管的任何标准 Kubernetes 提供程序集成. + +**注意:**观看[使用 GitLab 和 Google Cloud Platform 进行](https://about.gitlab.com/webcast/scalable-app-deploy/)的网络广播[可扩展应用程序部署,](https://about.gitlab.com/webcast/scalable-app-deploy/)并了解如何通过单击几下加速由 Google Cloud Platform(GCP)管理的 Kubernetes 集群.**提示:**每个新的 Google Cloud Platform(GCP)帐户[在注册后](https://console.cloud.google.com/freetrial)都会获得[$ 300 的信用额](https://console.cloud.google.com/freetrial) ,并且与 Google 合作,GitLab 能够为新的 GCP 帐户提供额外的$ 200,以开始使用 GitLab 的 Google Kubernetes Engine Integration. 您所要做的就是[点击此链接](https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form)并申请信贷. + +## Before you begin[](#before-you-begin "Permalink") + +在使用 GitLab [添加 Kubernetes 集群](#create-new-cluster)之前,您需要: + +* GitLab 本身. 要么: + * 一个[GitLab.com 帐户](https://about.gitlab.com/pricing/#gitlab-com) . + * 使用 GitLab 12.5 或更高版本的[自我管理安装](https://about.gitlab.com/pricing/#self-managed) . 这将确保 GitLab UI 可用于创建集群. +* 以下 GitLab 访问: + * [维护者](../../permissions.html#project-members-permissions)对项目级集群的项目[访问](../../permissions.html#project-members-permissions) . + * [维护者](../../permissions.html#group-members-permissions)对组级别集群的[访问权限](../../permissions.html#group-members-permissions) . + * 自我管理的实例级别群集的管理[区域访问](../../admin_area/index.html) . + +## Access controls[](#access-controls "Permalink") + +在 GitLab 中创建集群时,系统会询问您是否要创建以下任一集群: + +* A [Role-based access control (RBAC)](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) cluster. +* An [Attribute-based access control (ABAC)](https://kubernetes.io/docs/reference/access-authn-authz/abac/) cluster. + +**注意:**建议使用[RBAC](#rbac-cluster-resources) ,GitLab 为默认值. + +GitLab 创建必要的服务帐户和特权,以安装和运行[GitLab 托管的应用程序](index.html#installing-applications) . 当 GitLab 创建集群时,将在`default`名称空间中创建具有`cluster-admin`特权的`gitlab`服务帐户,以管理新创建的集群. + +**注意:**用于部署的受限服务帐户是在 GitLab 11.5 中[引入的](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51716) . + +The first time you install an application into your cluster, the `tiller` service account is created with `cluster-admin` privileges in the `gitlab-managed-apps` namespace. This service account will be used by Helm to install and run [GitLab managed applications](index.html#installing-applications). + +Helm 还将为每个已安装的应用程序创建其他服务帐户和其他资源. 有关每个应用程序,请查阅 Helm 图表的文档. + +如果要[添加现有的 Kubernetes 集群](add_remove_clusters.html#add-existing-cluster) ,请确保该帐户的令牌具有该集群的管理员特权. + +GitLab 创建的资源取决于集群的类型. + +### Important notes[](#important-notes "Permalink") + +请注意以下有关访问控制的内容: + +* 仅当集群[由 GitLab 管理时,](index.html#gitlab-managed-clusters)才会创建特定于环境的资源. +* 如果您的集群是在 GitLab 12.2 之前创建的,它将为所有项目环境使用单个名称空间. + +### RBAC cluster resources[](#rbac-cluster-resources "Permalink") + +GitLab 为 RBAC 集群创建以下资源. + +| Name | Type | Details | 创建时间 | +| --- | --- | --- | --- | +| `gitlab` | `ServiceAccount` | `default` namespace | 创建一个新集群 | +| `gitlab-admin` | `ClusterRoleBinding` | [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | 创建一个新集群 | +| `gitlab-token` | `Secret` | `gitlab` ServiceAccount 的令牌 | 创建一个新集群 | +| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | 安装舵图 | +| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | 安装舵图 | +| 环境名称空间 | `Namespace` | 包含所有特定于环境的资源 | 部署到集群 | +| 环境名称空间 | `ServiceAccount` | 使用环境的名称空间 | 部署到集群 | +| 环境名称空间 | `Secret` | 环境 ServiceAccount 的令牌 | 部署到集群 | +| 环境名称空间 | `RoleBinding` | [`edit`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | 部署到集群 | + +### ABAC cluster resources[](#abac-cluster-resources "Permalink") + +GitLab 为 ABAC 群集创建以下资源. + +| Name | Type | Details | 创建时间 | +| --- | --- | --- | --- | +| `gitlab` | `ServiceAccount` | `default` namespace | 创建一个新集群 | +| `gitlab-token` | `Secret` | `gitlab` ServiceAccount 的令牌 | 创建一个新集群 | +| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | 安装舵图 | +| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | 安装舵图 | +| 环境名称空间 | `Namespace` | 包含所有特定于环境的资源 | 部署到集群 | +| 环境名称空间 | `ServiceAccount` | 使用环境的名称空间 | 部署到集群 | +| 环境名称空间 | `Secret` | 环境 ServiceAccount 的令牌 | 部署到集群 | + +### Security of GitLab Runners[](#security-of-gitlab-runners "Permalink") + +GitLab Runners 默认情况[下](https://docs.gitlab.com/runner/executors/docker.html)启用了[特权模式](https://docs.gitlab.com/runner/executors/docker.html) ,这使他们可以执行特殊命令并在 Docker 中运行 Docker. 运行某些[Auto DevOps](../../../topics/autodevops/index.html)作业需要此功能. 这意味着容器正在特权模式下运行,因此,您应该注意一些重要的细节. + +特权标志为正在运行的容器提供了所有功能,而容器又可以执行主机可以执行的几乎所有操作. 请注意与对任意映像执行`docker run`操作相关的固有安全风险,因为它们有效地具有 root 用户访问权限. + +如果您不想在特权模式下使用 GitLab Runner,请执行以下任一操作: + +* 在 GitLab.com 上使用共享的跑步者. 他们没有这个安全问题. +* 使用[Shared Runners 中](../../gitlab_com/index.html#shared-runners)描述的配置来设置自己的[Runners](../../gitlab_com/index.html#shared-runners) . 这涉及: + 1. 确保您没有通过[应用程序](index.html#installing-applications)安装它. + 2. [使用`docker+machine`](https://docs.gitlab.com/runner/executors/docker_machine.html)安装 Runner. + +## Create new cluster[](#create-new-cluster "Permalink") + +可以使用 Google Kubernetes Engine(GKE)上的 GitLab 或 Amazon Elastic Kubernetes Service(EKS)在项目,组或实例级别上创建新集群: + +1. 导航到您的: + * 项目的 **操作> Kubernetes**页面,用于项目级集群. + * 组的 **Kubernetes**页面,用于组级别集群. + * **管理区>** **Kubernetes**页面,用于实例级集群. +2. Click **添加 Kubernetes 集群**. +3. 单击**创建新集群**选项卡. +4. 单击**Amazon EKS**或**Google GKE** ,然后按照说明提供所需的服务: + * [亚马逊 EKS](add_eks_clusters.html#new-eks-cluster) . + * [Google GKE](add_gke_clusters.html#creating-the-cluster-on-gke) . + +## Add existing cluster[](#add-existing-cluster "Permalink") + +如果您已有 Kubernetes 集群,则可以将其添加到项目,组或实例中. + +**注意:** arm64 集群不支持 Kubernetes 集成. 有关详细信息,请参阅问题[Helm Tiller 无法在 arm64 群集上安装](https://gitlab.com/gitlab-org/gitlab/-/issues/29838) . + +### Existing Kubernetes cluster[](#existing-kubernetes-cluster "Permalink") + +要将 Kubernetes 集群添加到您的项目,组或实例: + +1. 导航到您的: + 1. 项目的 **操作> Kubernetes**页面,用于项目级集群. + 2. 组的 **Kubernetes**页面,用于组级别集群. + 3. **管理区>** **Kubernetes**页面,用于实例级集群. +2. Click **添加 Kubernetes 集群**. +3. 单击**添加现有集群**选项卡,然后填写详细信息: + 1. **Kubernetes 集群名称** (必填)-您希望为**集群指定**的名称. + 2. **环境范围** (必需)- [与](index.html#setting-the-environment-scope-premium)此集群[相关的环境](index.html#setting-the-environment-scope-premium) . + 3. **API URL** (必填)-这是 GitLab 用于访问 Kubernetes API 的 URL. Kubernetes 公开了几个 API,我们想要所有这些 API 通用的"基本" URL. 例如, `https://kubernetes.example.com`而不是`https://kubernetes.example.com/api/v1` . + + 通过运行以下命令获取 API URL: + + ``` + kubectl cluster-info | grep 'Kubernetes master' | awk '/http/ {print $NF}' + ``` + + 4. **CA 证书** (必需)-需要有效的 Kubernetes 证书才能对集群进行身份验证. 我们将使用默认创建的证书. + 1. 列出带有`kubectl get secrets` ,并且应将其命名类似于`default-token-xxxxx` . 复制该令牌名称以在下面使用. + 2. 通过运行以下命令获取证书: + + ``` + kubectl get secret -o jsonpath = "{['data']['ca \. crt']}" | base64 --decode + ``` + + **注意:**如果命令返回整个证书链,则需要在证书链的底部复制*根 ca*证书. + 5. **令牌** -GitLab 使用服务令牌对 Kubernetes 进行身份验证,服务令牌的作用域是特定的`namespace` . **使用的令牌应属于具有[`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)特权的服务帐户.** 要创建此服务帐户: + 1. 创建一个名为`gitlab-admin-service-account.yaml` ,其内容为: + + ``` + apiVersion : v1 kind : ServiceAccount metadata : name : gitlab-admin namespace : kube-system --- apiVersion : rbac.authorization.k8s.io/v1beta1 kind : ClusterRoleBinding metadata : name : gitlab-admin roleRef : apiGroup : rbac.authorization.k8s.io kind : ClusterRole name : cluster-admin subjects : - kind : ServiceAccount name : gitlab-admin namespace : kube-system + ``` + + 2. 将服务帐户和群集角色绑定应用于您的群集: + + ``` + kubectl apply -f gitlab-admin-service-account.yaml + ``` + + 您将需要`container.clusterRoleBindings.create`权限来创建集群级角色. 如果您没有此权限,则可以选择启用基本身份验证,然后以管理员身份运行`kubectl apply`命令: + + ``` + kubectl apply -f gitlab-admin-service-account.yaml --username = admin --password = + ``` + + **注意:**可以打开基本身份验证,并可以使用 Google Cloud Console 获取密码凭据. + + 输出: + + ``` + serviceaccount "gitlab-admin" created clusterrolebinding "gitlab-admin" created + ``` + + 3. 检索`gitlab-admin`服务帐户的令牌: + + ``` + kubectl -n kube-system describe secret $( kubectl -n kube-system get secret | grep gitlab-admin | awk '{print $1}' ) + ``` + + 从输出中复制``值: + + ``` + Name : gitlab-admin-token-b5zv4 Namespace : kube-system Labels : Annotations : kubernetes.io/service-account.name=gitlab-admin kubernetes.io/service-account.uid=bcfe66ac-39be-11e8-97e8-026dce96b6e8 Type : kubernetes.io/service-account-token Data ==== ca.crt : 1025 bytes namespace : 11 bytes token : + ``` + + **注意:**对于 GKE 群集,您将需要`container.clusterRoleBindings.create`权限来创建群集角色绑定. 您可以按照[Google Cloud 文档](https://cloud.google.com/iam/docs/granting-changing-revoking-access)授予访问权限. + 6. **由 GitLab 管理的群集** -如果要让 GitLab 管理该群集的名称空间和服务帐户,请选中此复选框. 有关更多信息,请参见[托管集群部分](index.html#gitlab-managed-clusters) . + 7. **项目名称空间** (可选)-您不必填写它; 将其保留为空白,GitLab 将为您创建一个. 也: + * 每个项目应具有唯一的名称空间. + * 如果您正在使用具有更广泛权限的机密(例如`default`的机密),则项目名称空间不一定是机密的名称空间. + * 你**不**应该使用`default`为项目命名空间. + * 如果您或某人为项目专门创建了一个秘密(通常具有有限的权限),则该秘密的名称空间和项目名称空间可能是相同的. +4. 最后,单击**创建 Kubernetes 集群**按钮. + +几分钟后,您的集群将准备就绪. 现在,您可以继续安装一些[预定义的应用程序](index.html#installing-applications) . + +#### Disable Role-Based Access Control (RBAC) (optional)[](#disable-role-based-access-control-rbac-optional "Permalink") + +通过 GitLab 集成连接集群时,您可以指定集群是否支持 RBAC. 这将影响 GitLab 如何与集群进行某些操作的交互. 如果您在创建时*未*选中**启用 RBAC 的群集**复选框,则 GitLab 将假定与群集进行交互时禁用了 RBAC. 如果是这样,则必须在群集上禁用 RBAC 才能使集成正常工作. + +[![rbac](img/9d9a196fe723b5afc79e2d7b29fd0f4d.png)](img/rbac_v13_1.png) + +**注意:**禁用 RBAC 意味着群集中运行的任何应用程序或可以向群集进行身份验证的用户都具有完全的 API 访问权限. 这是一个[安全问题](index.html#security-implications) ,可能不是所希望的. + +为了有效地禁用 RBAC,可以应用全局权限来授予完全访问权限: + +``` +kubectl create clusterrolebinding permissive-binding \ + --clusterrole=cluster-admin \ + --user=admin \ + --user=kubelet \ + --group=system:serviceaccounts +``` + +## Enabling or disabling integration[](#enabling-or-disabling-integration "Permalink") + +成功创建新集群或添加现有集群后,即可启用 Kubernetes 集群集成. 要禁用 Kubernetes 集群集成: + +1. 导航到您的: + * 项目的 **操作> Kubernetes**页面,用于项目级集群. + * 组的 **Kubernetes**页面,用于组级别集群. + * **管理区>** **Kubernetes**页面,用于实例级集群. +2. 单击群集的名称. +3. 单击**GitLab 集成**切换. +4. Click **保存更改**. + +## Removing integration[](#removing-integration "Permalink") + +要从您的项目中删除 Kubernetes 集群集成,请首先导航到集群详细信息页面的**Advanced Settings**选项卡,然后执行以下任一操作: + +* 选择**删除集成** ,仅删除 Kubernetes 集成. +* [从 GitLab 12.6 中](https://gitlab.com/gitlab-org/gitlab/-/issues/26815) ,选择**删除集成和资源** ,以在**删除集成时**也删除所有相关的 GitLab 集群资源(例如,名称空间,角色和绑定). + +删除集群集成时,请注意: + +* 您需要具有维护人员及以上[权限](../../permissions.html)才能删除 Kubernetes 集群集成. +* 删除集群时,只删除其与 GitLab 的关系,而不删除集群本身. 要删除集群,可以通过访问 GKE 或 EKS 仪表板或使用`kubectl`来`kubectl` . + +## Learn more[](#learn-more "Permalink") + +要了解有关自动部署应用程序的更多信息,请阅读有关[Auto DevOps](../../../topics/autodevops/index.html) . \ No newline at end of file diff --git a/docs/018.md b/docs/018.md new file mode 100644 index 0000000000000000000000000000000000000000..ed361cb7d4b5f8794d573c41a2c6ff1ffa94548e --- /dev/null +++ b/docs/018.md @@ -0,0 +1,190 @@ +# Adding EKS clusters + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/add_eks_clusters.html](https://docs.gitlab.com/ee/user/project/clusters/add_eks_clusters.html) + +* [EKS requirements](#eks-requirements) + * [Additional requirements for self-managed instances](#additional-requirements-for-self-managed-instances-core-only) +* [New EKS cluster](#new-eks-cluster) + * [Troubleshooting creating a new cluster](#troubleshooting-creating-a-new-cluster) + * [Error: Request failed with status code 422](#error-request-failed-with-status-code-422) + * [Could not load Security Groups for this VPC](#could-not-load-security-groups-for-this-vpc) + * [`ROLLBACK_FAILED` during cluster creation](#rollback_failed-during-cluster-creation) +* [Existing EKS cluster](#existing-eks-cluster) + * [Create a default Storage Class](#create-a-default-storage-class) + * [Deploy the app to EKS](#deploy-the-app-to-eks) + +# Adding EKS clusters[](#adding-eks-clusters "Permalink") + +GitLab 支持添加新的和现有的 EKS 集群. + +## EKS requirements[](#eks-requirements "Permalink") + +在通过 GitLab 集成在 Amazon EKS 上创建第一个集群之前,请确保满足以下要求: + +* 设置了[Amazon Web Services](https://aws.amazon.com/)帐户,您就可以登录. +* 您有权管理 IAM 资源. +* 如果要使用[现有的 EKS 集群](#existing-eks-cluster) : + * 已正确配置工作节点的 Amazon EKS 集群. + * [安装并配置](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html#get-started-kubectl)了`kubectl`以访问 EKS 集群. + +### Additional requirements for self-managed instances[](#additional-requirements-for-self-managed-instances-core-only "Permalink") + +如果您使用自我管理的 GitLab 实例,则必须首先使用一组 Amazon 凭证配置 GitLab. 这些凭证将用于承担创建集群的用户提供的 Amazon IAM 角色. 创建一个 IAM 用户,并确保其有权承担您的用户将用来创建 EKS 群集的角色. + +例如,以下策略文档允许在帐户`123456789012`假设一个角色的名称以`gitlab-eks-` : + +``` +{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::123456789012:role/gitlab-eks-*" } } +``` + +为 IAM 用户生成访问密钥,并使用凭据配置 GitLab: + +1. 导航至**管理区域>设置>集成,**然后展开**Amazon EKS**部分. +2. Check **启用 Amazon EKS 集成**. +3. 在相应的`Account ID` , `Access key ID`和`Secret access key`字段中输入帐户 ID 和访问密钥凭据. +4. Click **保存更改**. + +## New EKS cluster[](#new-eks-cluster "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22392) . + +要创建新的 Kubernetes 集群并将其添加到您的项目,组或实例: + +1. 导航到您的: + * 项目的 **操作> Kubernetes**页面,用于项目级集群. + * 组的 **Kubernetes**页面,用于组级别集群. + * **管理区>** **Kubernetes** ,用于实例级集群. +2. Click **添加 Kubernetes 集群**. +3. 在" **创建新集群"**选项卡下,单击**Amazon EKS** . 将为您提供一个`Account ID`和`External ID` ,供下一步使用. +4. 在[IAM 管理控制台中](https://console.aws.amazon.com/iam/home) ,创建一个 IAM 角色: + 1. 在左侧面板中,选择**角色** . + 2. 单击**创建角色** . + 3. 在`Select type of trusted entity` ,选择**另一个 AWS 账户** . + 4. 在 GitLab 中的`Account ID`字段中输入`Account ID` . + 5. 选中**需要外部 ID** . + 6. 在 GitLab 中将`External ID`输入到`External ID`字段中. + 7. 单击**下一步:权限** . + 8. 点击**创建策略** ,这将打开一个新窗口. + 9. 选择**JSON**标签,然后粘贴以下代码段代替现有内容: + + ``` + { + "Version" : "2012-10-17" , + "Statement" : [ + { + "Effect" : "Allow" , + "Action" : [ + "autoscaling:CreateAutoScalingGroup" , + "autoscaling:DescribeAutoScalingGroups" , + "autoscaling:DescribeScalingActivities" , + "autoscaling:UpdateAutoScalingGroup" , + "autoscaling:CreateLaunchConfiguration" , + "autoscaling:DescribeLaunchConfigurations" , + "cloudformation:CreateStack" , + "cloudformation:DescribeStacks" , + "ec2:AuthorizeSecurityGroupEgress" , + "ec2:AuthorizeSecurityGroupIngress" , + "ec2:RevokeSecurityGroupEgress" , + "ec2:RevokeSecurityGroupIngress" , + "ec2:CreateSecurityGroup" , + "ec2:createTags" , + "ec2:DescribeImages" , + "ec2:DescribeKeyPairs" , + "ec2:DescribeRegions" , + "ec2:DescribeSecurityGroups" , + "ec2:DescribeSubnets" , + "ec2:DescribeVpcs" , + "eks:CreateCluster" , + "eks:DescribeCluster" , + "iam:AddRoleToInstanceProfile" , + "iam:AttachRolePolicy" , + "iam:CreateRole" , + "iam:CreateInstanceProfile" , + "iam:CreateServiceLinkedRole" , + "iam:GetRole" , + "iam:ListRoles" , + "iam:PassRole" , + "ssm:GetParameters" + ], + "Resource" : "*" + } + ] + } + ``` + + **注意:**这些权限使 GitLab 能够创建资源,但不能删除它们. 这意味着,如果在创建过程中遇到错误,更改将不会回滚,您必须手动删除资源. 您可以通过删除相关的[CloudFormation 堆栈](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html)来做到这一点 + 10. 点击**审核政策** . + 11. 为此策略输入合适的名称,然后点击**创建策略** . 您现在可以关闭此窗口. + 12. 切换回"创建角色"窗口,然后选择刚创建的策略. + 13. 单击**下一步:标签** ,并选择输入您希望与此角色关联的任何标签. + 14. 单击**下一步:查看** . + 15. 在提供的字段中输入角色名称和可选描述. + 16. 点击**创建角色** ,新角色名称将显示在顶部. 单击其名称,然后从新创建的角色复制`Role ARN` . +5. 在 GitLab 中,将复制的角色 ARN 输入到`Role ARN`字段中. +6. Click **使用 AWS 进行身份验证**. +7. 选择集群的设置: + * **Kubernetes 集群名称** -您希望赋予集群的名称. + * **环境范围** -该集群的[关联环境](index.html#setting-the-environment-scope-premium) . + * **Kubernetes 版本** -要使用的 Kubernetes 版本. 当前唯一支持的版本是 1.14\. + * **角色名称** -选择[IAM 角色](https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html)以允许 Amazon EKS 和 Kubernetes 控制平面代表您管理 AWS 资源. 此 IAM 角色与上面创建的 IAM 角色是分开的,如果尚不存在,则需要创建它. + * **区域** -将在其中创建群集的[区域](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html) . + * **密钥对名称** -如果需要,选择可用于连接到工作节点的[密钥对](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) . + * **VPC-**选择要用于 EKS 群集资源的[VPC](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html) . + * **子网** -在您的 VPC 中选择运行工作节点的[子网](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html) . 您必须至少选择两个. + * **安全组** -选择[安全组](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html)以应用到在工作节点子网中创建的 EKS 管理的弹性网络接口. + * **实例类型** -工作节点的[实例类型](https://aws.amazon.com/ec2/instance-types/) . + * **节点数** -工作节点数. + * **由 GitLab 管理的群集** -如果要让 GitLab 管理该群集的名称空间和服务帐户,请选中此复选框. 有关更多信息,请参见[托管集群部分](index.html#gitlab-managed-clusters) . +8. 最后,单击**创建 Kubernetes 集群**按钮. + +大约 10 分钟后,您的集群便可以使用了. 现在,您可以继续安装一些[预定义的应用程序](index.html#installing-applications) . + +**注意:**您需要将 AWS 外部 ID 添加到[AWS CLI 中](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html#cli-configure-role-xaccount)的[IAM 角色,](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html#cli-configure-role-xaccount)才能使用`kubectl`管理集群. + +### Troubleshooting creating a new cluster[](#troubleshooting-creating-a-new-cluster "Permalink") + +创建新集群时,通常会遇到以下错误. + +#### Error: Request failed with status code 422[](#error-request-failed-with-status-code-422 "Permalink") + +提交初始身份验证表单时,如果无法确定您提供的角色,则 GitLab 会返回状态码 422 错误. 确保已使用 GitLab 提供的**帐户 ID**和**外部 ID**正确配置了角色. 在 GitLab 中,确保输入正确的**Role ARN** . + +#### Could not load Security Groups for this VPC[](#could-not-load-security-groups-for-this-vpc "Permalink") + +当在配置表单中填充选项时,GitLab 将返回此错误,因为 GitLab 已成功承担了您提供的角色,但是该角色没有足够的权限来检索表单所需的资源. 确保已为角色分配了正确的权限. + +#### `ROLLBACK_FAILED` during cluster creation[](#rollback_failed-during-cluster-creation "Permalink") + +由于 GitLab 在创建一个或多个资源时遇到错误,因此创建过程停止. 您可以检查关联的[CloudFormation 堆栈](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-view-stack-data-resources.html)以查找创建失败的特定资源. + +如果`Cluster`资源因错误`The provided role doesn't have the Amazon EKS Managed Policies associated with it.`失败,则`The provided role doesn't have the Amazon EKS Managed Policies associated with it.` , **角色名称**中指定的**角色**配置不正确. + +**注意:**此角色不应与上面创建的角色相同. 如果您没有现有的[EKS 群集 IAM 角色](https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html) ,则必须创建一个. + +## Existing EKS cluster[](#existing-eks-cluster "Permalink") + +有关添加现有 EKS 群集的信息,请参阅" [现有 Kubernetes 群集"](add_remove_clusters.html#existing-kubernetes-cluster) . + +### Create a default Storage Class[](#create-a-default-storage-class "Permalink") + +Amazon EKS 没有开箱即用的默认存储类,这意味着对持久卷的请求将不会自动满足. 作为 Auto DevOps 的一部分,已部署的 PostgreSQL 实例将请求持久存储,并且如果没有默认存储类,它将无法启动. + +如果默认的存储类尚不存在并且需要使用,请按照 Amazon 的[存储类指南](https://docs.aws.amazon.com/eks/latest/userguide/storage-classes.html)创建一个. + +或者,通过将项目变量[`POSTGRES_ENABLED`](../../../topics/autodevops/customize.html#environment-variables)设置为`false`来禁用 PostgreSQL. + +### Deploy the app to EKS[](#deploy-the-app-to-eks "Permalink") + +在禁用 RBAC 和部署服务的情况下,现在可以利用[Auto DevOps](../../../topics/autodevops/index.html)构建,测试和部署应用程序. + +如果尚未启用,则[启用 Auto DevOps](../../../topics/autodevops/index.html#at-the-project-level) . 如果创建了通配符 DNS 条目以解析到负载均衡器,请在"自动 DevOps"设置下的" `domain`字段中输入它. 否则,已部署的应用程序将无法在群集外部从外部获得. + +[![Deploy Pipeline](img/de608fa9aefa963f38d0d95043413679.png)](img/pipeline.png) + +将自动创建一个新管道,该管道将开始构建,测试和部署该应用程序. + +管道完成后,您的应用将在 EKS 中运行,并可供用户使用. 单击**CI / CD>环境** . + +[![Deployed Environment](img/dc47374cec4da1de3e6476346ecf738e.png)](img/environment.png) + +您将看到环境及其部署状态的列表,以及浏览到应用程序,查看监视指标甚至访问正在运行的 Pod 上的 Shell 的选项. \ No newline at end of file diff --git a/docs/019.md b/docs/019.md new file mode 100644 index 0000000000000000000000000000000000000000..fa763920987d9effd3c7fdadfe55e25f7149dc67 --- /dev/null +++ b/docs/019.md @@ -0,0 +1,65 @@ +# Adding GKE clusters + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/add_gke_clusters.html](https://docs.gitlab.com/ee/user/project/clusters/add_gke_clusters.html) + +* [GKE requirements](#gke-requirements) +* [New GKE cluster](#new-gke-cluster) + * [Creating the cluster on GKE](#creating-the-cluster-on-gke) + * [Cloud Run for Anthos](#cloud-run-for-anthos) +* [Existing GKE cluster](#existing-gke-cluster) + +# Adding GKE clusters[](#adding-gke-clusters "Permalink") + +GitLab 支持添加新的和现有的 GKE 集群. + +## GKE requirements[](#gke-requirements "Permalink") + +在通过 GitLab 集成在 Google GKE 上创建第一个集群之前,请确保满足以下要求: + +* 设置了具有访问权限的[结算帐户](https://cloud.google.com/billing/docs/how-to/manage-billing-account) . +* 启用了 Kubernetes Engine API 和相关服务. 它应该可以立即工作,但是创建项目后最多可能需要 10 分钟. 有关更多信息,请参见[Kubernetes Engine 文档](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin)的["开始之前"部分](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin) . + +## New GKE cluster[](#new-gke-cluster "Permalink") + +从[GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/issues/25925)开始, [GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/25925)提供的所有 GKE 群集均为[VPC 本地的](https://cloud.google.com/kubernetes-engine/docs/how-to/alias-ips) . + +请注意以下几点: + +* 必须在实例级别的 GitLab 中启用[Google 身份验证集成](../../../integration/google.html) . 如果不是这种情况,请要求您的 GitLab 管理员启用它. 在 GitLab.com 上启用了此功能. +* 从[GitLab 12.1](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55902)开始,由[GitLab](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55902)创建的所有 GKE 集群都启用了 RBAC. 请参阅[RBAC 部分](add_remove_clusters.html#rbac-cluster-resources)以获取更多信息. +* 从[GitLab 12.5](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18341)开始,群集的 Pod 地址 IP 范围将设置为/ 16,而不是常规的/ 14\. / 16 是 CIDR 表示法. +* GitLab 要求启用基本身份验证并为集群颁发客户端证书,以设置[初始服务帐户](add_remove_clusters.html#access-controls) . 在[GitLab 11.10 及更高版本中](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/58208) ,集群创建过程明确要求 GKE 创建启用了基本身份验证和客户端证书的集群. + +### Creating the cluster on GKE[](#creating-the-cluster-on-gke "Permalink") + +要创建新的 Kubernetes 集群并将其添加到您的项目,组或实例: + +1. 导航到您的: + * 项目的 **操作> Kubernetes**页面,用于项目级集群. + * 组的 **Kubernetes**页面,用于组级别集群. + * **管理区>** **Kubernetes**页面,用于实例级集群. +2. Click **添加 Kubernetes 集群**. +3. 在[ **建立新丛集]**标签下,按一下[ **Google GKE]** . +4. 如果尚未连接 Google 帐户,请单击" **使用 Google 登录"**按钮. +5. 选择集群的设置: + * **Kubernetes 集群名称** -您希望赋予集群的名称. + * **环境范围** -该集群的[关联环境](index.html#setting-the-environment-scope-premium) . + * **Google Cloud Platform 项目** -选择您在 GCP 控制台中创建的将托管 Kubernetes 集群的项目. 了解有关[Google Cloud Platform 项目的](https://cloud.google.com/resource-manager/docs/creating-managing-projects)更多信息. + * **区域** -选择将在其下创建群集的[区域区域](https://cloud.google.com/compute/docs/regions-zones/) . + * **节点数** -输入希望群集具有的节点数. + * **计算机类型** -群集将基于的虚拟机实例的[计算机类型](https://cloud.google.com/compute/docs/machine-types) . + * **为 Anthos 启用 Cloud Run-**如果要对此集群使用 Cloud Run for Anthos,请选中此复选框. 有关更多信息,请参见[Anthos](#cloud-run-for-anthos)的[Cloud Run 部分](#cloud-run-for-anthos) . + * **由 GitLab 管理的群集** -如果要让 GitLab 管理该群集的名称空间和服务帐户,请选中此复选框. 有关更多信息,请参见[托管集群部分](index.html#gitlab-managed-clusters) . +6. 最后,单击**创建 Kubernetes 集群**按钮. + +几分钟后,您的集群将准备就绪. 现在,您可以继续安装一些[预定义的应用程序](index.html#installing-applications) . + +### Cloud Run for Anthos[](#cloud-run-for-anthos "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16566) . + +创建群集后,可以选择使用 Cloud Run for Anthos 代替分别安装 Knative 和 Istio. 这意味着将在创建时在集群上启用 Cloud Run(Knative),Istio 和 HTTP Load Balancing,并且不能单独[安装或卸载](../../clusters/applications.html) . + +## Existing GKE cluster[](#existing-gke-cluster "Permalink") + +有关添加现有 GKE 群集的信息,请参阅" [现有 Kubernetes 群集"](add_remove_clusters.html#existing-kubernetes-cluster) . \ No newline at end of file diff --git a/docs/020.md b/docs/020.md new file mode 100644 index 0000000000000000000000000000000000000000..e00a05647fd42a90e2515b47ea7136bf641168d0 --- /dev/null +++ b/docs/020.md @@ -0,0 +1,144 @@ +# Group-level Kubernetes clusters + +> 原文:[https://docs.gitlab.com/ee/user/group/clusters/](https://docs.gitlab.com/ee/user/group/clusters/) + +* [Installing applications](#installing-applications) +* [RBAC compatibility](#rbac-compatibility) +* [Cluster precedence](#cluster-precedence) +* [Multiple Kubernetes clusters](#multiple-kubernetes-clusters) +* [GitLab-managed clusters](#gitlab-managed-clusters) + * [Clearing the cluster cache](#clearing-the-cluster-cache) +* [Base domain](#base-domain) +* [Environment scopes](#environment-scopes-premium) +* [Cluster environments](#cluster-environments-premium) +* [Security of Runners](#security-of-runners) +* [More information](#more-information) + +# Group-level Kubernetes clusters[](#group-level-kubernetes-clusters "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34758) . + +与[项目级](../../project/clusters/index.html)和[实例级](../../instance/clusters/index.html) Kubernetes 集群类似,组级 Kubernetes 集群允许您将 Kubernetes 集群连接到您的组,从而使您可以在多个项目中使用同一集群. + +## Installing applications[](#installing-applications "Permalink") + +GitLab 可以在您的组级别集群中安装和管理某些应用程序. 有关为您的组集群安装,升级,卸载和故障排除应用程序的更多信息,请参阅[GitLab 托管应用程序](../../clusters/applications.html) . + +## RBAC compatibility[](#rbac-compatibility "Permalink") + +版本历史 + +* 在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29398) . +* [项目名称空间限制](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51716)是在 GitLab 11.5 中引入的. + +对于具有 Kubernetes 集群的组中的每个项目,GitLab 都会在项目名称空间中创建具有[`edit`权限](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)的受限服务帐户. + +## Cluster precedence[](#cluster-precedence "Permalink") + +如果项目的群集可用且未禁用,则 GitLab 在使用属于包含该项目的组的任何群集之前,先使用项目的群集. 对于子组,如果未禁用该组,则 GitLab 将使用与项目最接近的祖先组的集群. + +## Multiple Kubernetes clusters[](#multiple-kubernetes-clusters "Permalink") + +版本历史 + +* 在 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094)了 GitLab Core. + +您可以将多个 Kubernetes 集群关联到您的组,并为不同的环境(例如开发,登台和生产)维护不同的集群. + +添加另一个群集时,请[设置环境范围](#environment-scopes-premium)以帮助区分新群集和其他群集. + +## GitLab-managed clusters[](#gitlab-managed-clusters "Permalink") + +版本历史 + +* 在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22011) . +* 在 GitLab 11.11 中成为[可选](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26565) . + +You can choose to allow GitLab to manage your cluster for you. If GitLab manages your cluster, resources for your projects will be automatically created. See the [Access controls](../../project/clusters/add_remove_clusters.html#access-controls) section for details on which resources GitLab creates for you. + +对于不受 GitLab 管理的集群,将不会自动创建特定于项目的资源. 如果将[Auto DevOps](../../../topics/autodevops/index.html)用于具有不受 GitLab 管理的群集的部署,则必须确保: + +* 项目的部署服务帐户有权部署到[`KUBE_NAMESPACE`](../../project/clusters/index.html#deployment-variables) . +* `KUBECONFIG`正确反映了对`KUBE_NAMESPACE`任何更改(这[不是自动的](https://gitlab.com/gitlab-org/gitlab/-/issues/31519) ). 不建议直接编辑`KUBE_NAMESPACE` . + +**注意:**如果您在群集上[安装应用程序](#installing-applications) ,即使您选择管理自己的群集,GitLab 也会创建运行它们所需的资源. + +### Clearing the cluster cache[](#clearing-the-cluster-cache "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31759) . + +如果您选择允许 GitLab 为您管理集群,则 GitLab 将存储它为项目创建的名称空间和服务帐户的缓存版本. 如果在群集中手动修改这些资源,则此缓存可能与群集不同步,这可能导致部署作业失败. + +清除缓存: + +1. 导航到您小组的 **Kubernetes**页面,然后选择您的集群. +2. 展开**高级设置**部分. +3. Click **清除集群缓存**. + +## Base domain[](#base-domain "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24580) . + +集群级别的域允许每个[多个 Kubernetes 集群](#multiple-kubernetes-clusters)支持多个域.指定域时,这将在[Auto DevOps](../../../topics/autodevops/index.html)阶段自动设置为环境变量( `KUBE_INGRESS_BASE_DOMAIN` ). + +该域应将通配符 DNS 配置为入口 IP 地址. + +## Environment scopes[](#environment-scopes-premium "Permalink") + +将多个 Kubernetes 集群添加到您的项目时,您需要通过环境范围来区分它们. 环境范围将群集与[环境](../../../ci/environments/index.html)相关联,类似于[特定](../../../ci/variables/README.html#limit-the-environment-scopes-of-environment-variables)于[环境的变量的](../../../ci/variables/README.html#limit-the-environment-scopes-of-environment-variables)工作方式. + +在评估哪个环境与群集的环境范围匹配时, [群集优先级](#cluster-precedence)将生效. 项目级别的集群优先,其次是最接近的祖先组,然后是该组的父级,依此类推. + +例如,如果您的项目具有以下 Kubernetes 集群: + +| Cluster | 环境范围 | Where | +| --- | --- | --- | +| Project | `*` | Project | +| Staging | `staging/*` | Project | +| Production | `production/*` | Project | +| Test | `test` | Group | +| Development | `*` | Group | + +[`.gitlab-ci.yml`](../../../ci/yaml/README.html)中设置了以下环境: + +``` +stages: + - test + - deploy + +test: + stage: test + script: sh test + +deploy to staging: + stage: deploy + script: make deploy + environment: + name: staging/$CI_COMMIT_REF_NAME + url: https://staging.example.com/ + +deploy to production: + stage: deploy + script: make deploy + environment: + name: production/$CI_COMMIT_REF_NAME + url: https://example.com/ +``` + +结果是: + +* 项目集群用于`test`作业. +* 分段群集用于`deploy to staging`作业. +* 生产集群用于`deploy to production`作业. + +## Cluster environments[](#cluster-environments-premium "Permalink") + +有关将哪种 CI [环境](../../../ci/environments/index.html)部署到 Kubernetes 集群的统一视图,请参阅[集群环境](../../clusters/environments.html)文档. + +## Security of Runners[](#security-of-runners "Permalink") + +有关安全配置 GitLab Runners 的重要信息,请参阅项目级集群[的 Runners 安全性](../../project/clusters/add_remove_clusters.html#security-of-gitlab-runners)文档. + +## More information[](#more-information "Permalink") + +For information on integrating GitLab and Kubernetes, see [Kubernetes clusters](../../project/clusters/index.html). \ No newline at end of file diff --git a/docs/021.md b/docs/021.md new file mode 100644 index 0000000000000000000000000000000000000000..a9f066f1278ddb6dc5e8a5cb06ccf07cf17d1858 --- /dev/null +++ b/docs/021.md @@ -0,0 +1,34 @@ +# Instance-level Kubernetes clusters + +> 原文:[https://docs.gitlab.com/ee/user/instance/clusters/](https://docs.gitlab.com/ee/user/instance/clusters/) + +* [Overview](#overview) +* [Cluster precedence](#cluster-precedence) +* [Cluster environments](#cluster-environments-premium) +* [More information](#more-information) + +# Instance-level Kubernetes clusters[](#instance-level-kubernetes-clusters "Permalink") + +在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39840) . + +## Overview[](#overview "Permalink") + +与[项目级](../../project/clusters/index.html)和[组级](../../group/clusters/index.html) Kubernetes 集群类似,实例级 Kubernetes 集群允许您将 Kubernetes 集群连接到 GitLab 实例,这使您可以在多个项目中使用同一集群. + +## Cluster precedence[](#cluster-precedence "Permalink") + +GitLab 将尝试按以下顺序匹配集群: + +* 项目级集群. +* 组级别群集. +* 实例级集群. + +要选择集群,必须启用集群并使其与[环境选择器](../../../ci/environments/index.html#scoping-environments-with-specs)匹配. + +## Cluster environments[](#cluster-environments-premium "Permalink") + +有关将哪种 CI [环境](../../../ci/environments/index.html)部署到 Kubernetes 集群的统一视图,请参阅[集群环境](../../clusters/environments.html)文档. + +## More information[](#more-information "Permalink") + +有关集成 GitLab 和 Kubernetes 的信息,此[Kubernetes 集群](../../project/clusters/index.html) . \ No newline at end of file diff --git a/docs/022.md b/docs/022.md new file mode 100644 index 0000000000000000000000000000000000000000..5a0961c34fd6d09c041f896aa2b37619333e2e79 --- /dev/null +++ b/docs/022.md @@ -0,0 +1,42 @@ +# Canary Deployments + +> 原文:[https://docs.gitlab.com/ee/user/project/canary_deployments.html](https://docs.gitlab.com/ee/user/project/canary_deployments.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Enabling Canary Deployments](#enabling-canary-deployments) + +# Canary Deployments[](#canary-deployments-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1659) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.1. + +一种流行的[持续部署](https://en.wikipedia.org/wiki/Continuous_deployment)策略,其中将一小部分机队更新为应用程序的新版本. + +## Overview[](#overview "Permalink") + +在采用[持续交付时](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) ,公司需要决定要使用哪种部署策略. 最受欢迎的策略之一是金丝雀部署,首先将一小部分机队更新为新版本. 金丝雀的这个子集,然后在煤矿中成为众所周知的[金丝雀](https://en.wiktionary.org/wiki/canary_in_a_coal_mine) . + +如果应用程序的新版本存在问题,则仅会影响一小部分用户,并且可以固定更改或快速还原更改. + +利用[Kubernetes 的 Canary 部署](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments) ,无需离开 GitLab,即可在[Deploy Board](deploy_boards.html)内部可视化您的 Canary 部署. + +## Use cases[](#use-cases "Permalink") + +当您只想向部分 Pod 舰队提供功能并观看其行为时,可以使用 Canary 部署. 如果一切正常,您可以将该功能部署到生产中,因为它不会造成任何问题. + +Canary 部署对于后端重构,性能改进或用户界面不变的其他更改也特别有用,但是您要确保性能保持不变或有所提高. 开发人员在使用面向用户的更改的 Canary 时需要谨慎,因为默认情况下,来自同一用户的请求将随机分布在 Canary 和非 Canary Pod 之间,这可能导致混乱甚至错误. 如果需要,您可能需要考虑[在 Kubernetes 服务定义中将`service.spec.sessionAffinity`设置为`ClientIP`](https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies) ,但这超出了本文档的范围. + +## Enabling Canary Deployments[](#enabling-canary-deployments "Permalink") + +Canary 部署要求您正确配置 Deploy Boards: + +1. 请按照以下步骤[启用 Deploy Boards](deploy_boards.html#enabling-deploy-boards) . +2. 要跟踪 canary 部署,您需要使用`track: canary`标记 Kubernetes 部署和 Pod. 为了快速入门,您可以将[自动部署](../../topics/autodevops/stages.html#auto-deploy)模板用于 GitLab 提供的金丝雀部署. + +根据部署情况,标签应该是`stable`或`canary` . 通常, `stable`且空白或丢失的标签表示同一件事,而`canary`或任何其他轨道表示金丝雀/临时. 这使 GitLab 能够发现部署是稳定的还是金丝雀(临时)的. + +完成以上所有设置并且管道至少运行了一次之后,导航至" **管道">"环境"**下的环境页面. 随着管道的执行,部署委员会将清楚地标记金丝雀荚,从而可以快速,轻松地洞察每种环境和部署的状态. + +Canary deployments are marked with a yellow dot in the Deploy Board so that you can easily notice them. + +[![Canary deployments on Deploy Board](img/9a002df90c6ed1d01c8ae3a9817242df.png)](img/deploy_boards_canary_deployments.png) \ No newline at end of file diff --git a/docs/023.md b/docs/023.md new file mode 100644 index 0000000000000000000000000000000000000000..9a11616616052d0777d2aa9e4218d2ab88ef726d --- /dev/null +++ b/docs/023.md @@ -0,0 +1,42 @@ +# Cluster Environments + +> 原文:[https://docs.gitlab.com/ee/user/clusters/environments.html](https://docs.gitlab.com/ee/user/clusters/environments.html) + +* [Overview](#overview) +* [Usage](#usage) + +# Cluster Environments[](#cluster-environments-premium "Permalink") + +> * 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.3 中针对组级集群[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13392) . +> * 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.4 中针对实例级集群进行了[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/14809) . + +群集环境提供了一个统一的视图,用于说明将哪些 CI [环境](../../ci/environments/index.html)部署到 Kubernetes 群集及其: + +* 显示项目和与部署相关的相关环境. +* 显示该环境的窗格的状态. + +## Overview[](#overview "Permalink") + +使用集群环境,您可以深入了解: + +* 哪些项目已部署到集群. +* 每个项目的环境使用了多少个 Pod. +* 用于部署到该环境的 CI 作业. + +[![Cluster environments page](img/662e9b0c090a4f28c82eb779aabdc9c8.png)](img/cluster_environments_table_v12_3.png) + +仅限集群[维护者和所有者](../permissions.html#group-members-permissions)访问集群环境 + +## Usage[](#usage "Permalink") + +为了: + +* 跟踪集群的环境,您必须成功[部署到 Kubernetes 集群](../project/clusters/index.html#deploying-to-a-kubernetes-cluster) . +* 正确显示容器使用情况,必须[启用 Deploy Boards](../project/deploy_boards.html#enabling-deploy-boards) . + +成功部署到组级或实例级集群后: + +1. 导航到您组的**Kubernetes**页面. +2. 单击**环境**选项卡. + +**注意:**此页面仅包含成功部署到群集的信息. 非群集环境将不包括在内. \ No newline at end of file diff --git a/docs/024.md b/docs/024.md new file mode 100644 index 0000000000000000000000000000000000000000..0fc69a277907a6d55e4970d65c873902713cfdb5 --- /dev/null +++ b/docs/024.md @@ -0,0 +1,113 @@ +# Deploy Boards + +> 原文:[https://docs.gitlab.com/ee/user/project/deploy_boards.html](https://docs.gitlab.com/ee/user/project/deploy_boards.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Enabling Deploy Boards](#enabling-deploy-boards) + * [Example manifest file](#example-manifest-file) +* [Canary Deployments](#canary-deployments) +* [Further reading](#further-reading) + +# Deploy Boards[](#deploy-boards-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1589) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0. + +GitLab 的部署板提供了[Kubernetes](https://kubernetes.io)上运行的每个 CI [环境](../../ci/environments/index.html)的当前运行状况和状态的综合视图,显示了部署中 Pod 的状态. 开发人员和其他团队成员可以在已经使用的工作流程中逐个窗格地查看发布的进度和状态,而无需访问 Kubernetes. + +## Overview[](#overview "Permalink") + +使用部署板,您可以通过以下优势对部署进行更多了解: + +* 从头开始进行部署,而不仅仅是完成之后 +* 监视跨多个服务器的构建的推出 +* 更详细的状态详细信息(成功,正在运行,失败,待处理,未知) +* See [Canary Deployments](canary_deployments.html) + +这是生产环境的部署板的示例. + +[![Deploy Boards landing page](img/4ceccc7ae590a56e8b135fa8baaafabe.png)](img/deploy_boards_landing_page.png) + +正方形表示与给定环境关联的 Kubernetes 集群中的 Pod. 将鼠标悬停在每个方块上方,可以看到部署的状态. 百分比是已更新到最新版本的 Pod 的百分比. + +由于部署板与 Kubernetes 紧密结合,因此需要一些知识. 特别是,您应该熟悉: + +* [Kubernetes pods](https://kubernetes.io/docs/concepts/workloads/pods/pod/) +* [Kubernetes labels](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) +* [Kubernetes namespaces](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) +* [Kubernetes canary deployments](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments) + +**注意:**包含多个部署的应用程序在部署板上显示为重复项. 有关详细信息,请关注[此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/8463) . + +## Use cases[](#use-cases "Permalink") + +由于部署板是针对特定环境的 Kubernetes 吊舱的直观表示,因此存在许多用例. 仅举几例: + +* 您想将分阶段运行的产品推广到生产环境. 您转到环境列表,验证阶段运行的是您认为正在运行的,然后单击[手动操作](../../ci/yaml/README.html#whenmanual)以部署到生产环境. +* 您触发了部署,并且有很多容器需要升级,因此您将花费一段时间(您也限制了部署,一次只能删除 X 个容器). 但是您需要告诉某人何时部署,因此您可以转到环境列表,查看生产环境,以了解每个 Pod 滚动时的实时进度. +* 您会得到一份报告,说明生产中有些异常,因此您可以查看生产环境以查看正在运行什么,以及部署是否正在进行,是否停止或失败. +* 您的 MR 看起来不错,但是您希望在登台上运行它,因为登台是在某种程度上更接近生产环境进行设置的. 您转到环境列表,找到您感兴趣的[Review App](../../ci/review_apps/index.html) ,然后单击手动操作将其部署到登台. + +## Enabling Deploy Boards[](#enabling-deploy-boards "Permalink") + +要显示特定[环境](../../ci/environments/index.html)的部署板,您应该: + +1. 用部署阶段[定义了一个环境](../../ci/environments/index.html#defining-environments) . + +2. 使 Kubernetes 集群启动并运行. + + **在 OpenShift 上运行:**如果使用的是 OpenShift,请确保使用的是`Deployment`资源而不是`DeploymentConfiguration` . 否则,部署板将无法正确渲染. 有关更多信息,请阅读[OpenShift docs](https://docs.openshift.com/container-platform/3.7/dev_guide/deployments/kubernetes_deployments.html#kubernetes-deployments-vs-deployment-configurations)和[GitLab 问题#4584](https://gitlab.com/gitlab-org/gitlab/-/issues/4584) . +3. 使用[Docker](https://docs.gitlab.com/runner/executors/docker.html)或[Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html)执行器[配置 GitLab Runner](../../ci/runners/README.html) . +4. 在您的项目中为集群配置[Kubernetes 集成](clusters/index.html) . 特别注意 Kubernetes 命名空间,因为部署脚本(由`KUBE_NAMESPACE` env 变量公开)将需要它. +5. 确保将 app.gitlab.com/env:$ `app.gitlab.com/env: $CI_ENVIRONMENT_SLUG`和`app.gitlab.com/app: $CI_PROJECT_PATH_SLUG` CI_PROJECT_PATH_SLUG 的 Kubernetes 注释应用于部署,副本集和 Pod,其中`$CI_ENVIRONMENT_SLUG`和`$CI_PROJECT_PATH_SLUG`是 CI 变量的值. 这样一来,我们便可以在可能有多个的群集/命名空间中查找适当的环境. 这些资源应包含在 Kubernetes 服务设置中定义的名称空间中. 您可以使用[Autodeploy](../../topics/autodevops/stages.html#auto-deploy) `.gitlab-ci.yml`模板,该模板具有要使用的预定义阶段和命令,并自动应用注释. 每个项目还需要在 Kubernetes 中具有唯一的名称空间. 下图演示了如何在 Kubernetes 中显示此内容. + + **注意:**在[GitLab 12.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14020)中删除了基于 Kubernetes `app`标签的匹配. 要迁移,请应用所需的注释(请参见上文),然后重新部署您的应用程序. 如果您使用的是 Auto DevOps,这将自动完成,无需采取任何措施. + + [![Deploy Boards Kubernetes Label](img/f5739c1b278ddd91c915c534514b4235.png)](img/deploy_boards_kubernetes_label.png) + +完成以上所有设置并且管道至少运行了一次之后,导航至**Operations> Environments**下的 environment 页面. + +默认情况下,部署板是可见的. 您可以显式单击相应环境名称旁边的三角形以隐藏它们. + +### Example manifest file[](#example-manifest-file "Permalink") + +以下示例是使用两个注释`app.gitlab.com/env`和`app.gitlab.com/app`启用 Kubernetes 清单部署文件的`app.gitlab.com/env` ,以启用**Deploy Boards** : + +``` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: "APPLICATION_NAME" + annotations: + app.gitlab.com/app: ${CI_PROJECT_PATH_SLUG} + app.gitlab.com/env: ${CI_ENVIRONMENT_SLUG} +spec: + replicas: 1 + selector: + matchLabels: + app: "APPLICATION_NAME" + template: + metadata: + labels: + app: "APPLICATION_NAME" + annotations: + app.gitlab.com/app: ${CI_PROJECT_PATH_SLUG} + app.gitlab.com/env: ${CI_ENVIRONMENT_SLUG} +``` + +注释将应用于部署,副本集和 Pod. 通过更改副本数量,例如`kubectl scale --replicas=3 deploy APPLICATION_NAME -n ${KUBE_NAMESPACE}` ,您可以从开发板上跟踪实例的 pod. + +**注意:** YAML 文件是静态的. 如果使用`kubectl apply` ,则必须在`kubectl apply`之前手动提供项目和环境段,或者创建脚本来替换 YAML 中的变量. + +## Canary Deployments[](#canary-deployments "Permalink") + +一种流行的 CI 策略,其中将一小部分车队更新为应用程序的新版本. + +[Read more about Canary Deployments.](canary_deployments.html) + +## Further reading[](#further-reading "Permalink") + +* [GitLab Autodeploy](../../topics/autodevops/stages.html#auto-deploy) +* [GitLab CI/CD environment variables](../../ci/variables/README.html) +* [Environments and deployments](../../ci/environments/index.html) +* [Kubernetes deploy example](https://gitlab.com/gitlab-examples/kubernetes-deploy) \ No newline at end of file diff --git a/docs/025.md b/docs/025.md new file mode 100644 index 0000000000000000000000000000000000000000..ba3543f75b3deba1b090b905b7b9ef53348754cb --- /dev/null +++ b/docs/025.md @@ -0,0 +1,1220 @@ +# GitLab Managed Apps + +> 原文:[https://docs.gitlab.com/ee/user/clusters/applications.html](https://docs.gitlab.com/ee/user/clusters/applications.html) + +* [Installing applications](#installing-applications) + * [Helm](#helm) + * [Enable or disable local Tiller](#enable-or-disable-local-tiller-core-only) + * [cert-manager](#cert-manager) + * [GitLab Runner](#gitlab-runner) + * [Ingress](#ingress) + * [Determining the external endpoint automatically](#determining-the-external-endpoint-automatically) + * [Determining the external endpoint manually](#determining-the-external-endpoint-manually) + * [Using a static IP](#using-a-static-ip) + * [Pointing your DNS at the external endpoint](#pointing-your-dns-at-the-external-endpoint) + * [Web Application Firewall (ModSecurity)](#web-application-firewall-modsecurity) + * [Logging and blocking modes](#logging-and-blocking-modes) + * [WAF version updates](#waf-version-updates) + * [Viewing Web Application Firewall traffic](#viewing-web-application-firewall-traffic) + * [JupyterHub](#jupyterhub) + * [Jupyter Git Integration](#jupyter-git-integration) + * [Knative](#knative) + * [Prometheus](#prometheus) + * [Crossplane](#crossplane) + * [Elastic Stack](#elastic-stack) + * [Optional: deploy Kibana to perform advanced queries](#optional-deploy-kibana-to-perform-advanced-queries) + * [Fluentd](#fluentd) + * [Future apps](#future-apps) +* [Install using GitLab CI/CD (alpha)](#install-using-gitlab-cicd-alpha) + * [Usage](#usage) + * [Important notes](#important-notes) + * [Install Ingress using GitLab CI/CD](#install-ingress-using-gitlab-cicd) + * [Install cert-manager using GitLab CI/CD](#install-cert-manager-using-gitlab-cicd) + * [Install Sentry using GitLab CI/CD](#install-sentry-using-gitlab-cicd) + * [Install PostHog using GitLab CI/CD](#install-posthog-using-gitlab-cicd) + * [Install Prometheus using GitLab CI/CD](#install-prometheus-using-gitlab-cicd) + * [Install GitLab Runner using GitLab CI/CD](#install-gitlab-runner-using-gitlab-cicd) + * [Install Cilium using GitLab CI/CD](#install-cilium-using-gitlab-cicd) + * [Install Falco using GitLab CI/CD](#install-falco-using-gitlab-cicd) + * [Install Vault using GitLab CI/CD](#install-vault-using-gitlab-cicd) + * [Install JupyterHub using GitLab CI/CD](#install-jupyterhub-using-gitlab-cicd) + * [Install Elastic Stack using GitLab CI/CD](#install-elastic-stack-using-gitlab-cicd) + * [Install Crossplane using GitLab CI/CD](#install-crossplane-using-gitlab-cicd) + * [Install Fluentd using GitLab CI/CD](#install-fluentd-using-gitlab-cicd) + * [Install Knative using GitLab CI/CD](#install-knative-using-gitlab-cicd) + * [Knative Metrics](#knative-metrics) + * [Uninstall Knative](#uninstall-knative) + * [Install AppArmor using GitLab CI/CD](#install-apparmor-using-gitlab-cicd) + * [Using AppArmor profiles in your deployments](#using-apparmor-profiles-in-your-deployments) +* [Upgrading applications](#upgrading-applications) +* [Uninstalling applications](#uninstalling-applications) +* [Troubleshooting applications](#troubleshooting-applications) + * [Error installing managed apps on EKS cluster](#error-installing-managed-apps-on-eks-cluster) + * [Unable to install Prometheus](#unable-to-install-prometheus) + +# GitLab Managed Apps[](#gitlab-managed-apps "Permalink") + +GitLab 提供**GitLab 托管应用程序** ,一键安装各种应用程序,可以直接将其添加到配置的集群中. + +使用[Auto DevOps](../../topics/autodevops/index.html)时, [Review Apps](../../ci/review_apps/index.html)和[部署](../../ci/environments/index.html)需要这些应用程序. + +您可以在[创建集群](../project/clusters/add_remove_clusters.html)后安装它们. + +## Installing applications[](#installing-applications "Permalink") + +由 GitLab `gitlab-managed-apps`将安装到`gitlab-managed-apps`命名空间中. + +该名称空间: + +* 与用于项目部署的名称空间不同. +* 创建一次. +* 具有不可配置的名称. + +查看可用安装的应用程序列表. 为一个: + +* [项目级集群](../project/clusters/index.html) ,导航到项目的 **运营> Kubernetes** . +* [小组级别的集群](../group/clusters/index.html) ,导航到您小组的 **Kubernetes**页面. + +**注意:**从 GitLab 11.6 开始,Helm 将在安装任何应用程序之前升级到 GitLab 支持的最新版本. + +可以安装以下应用程序: + +* [Helm](#helm) +* [Ingress](#ingress) +* [cert-manager](#cert-manager) +* [Prometheus](#prometheus) +* [GitLab Runner](#gitlab-runner) +* [JupyterHub](#jupyterhub) +* [Knative](#knative) +* [Crossplane](#crossplane) +* [Elastic Stack](#elastic-stack) +* [Fluentd](#fluentd) + +除 Knative 外,这些应用程序将安装在名为`gitlab-managed-apps`的专用命名空间中. + +**注意:**某些应用程序仅可用于项目级集群安装. 计划在将来的发行版中支持在组级群集中安装这些应用程序. 有关更新,请参阅[问题跟踪进度](https://gitlab.com/gitlab-org/gitlab/-/issues/24411) .**注意:**如果您现有的 Kubernetes 集群已安装 Helm,则应谨慎使用,因为 GitLab 无法检测到它. 在这种情况下,通过应用程序安装 Helm 将导致集群对其进行两次配置,这可能导致部署期间的混乱. + +### Helm[](#helm "Permalink") + +版本历史 + +* 在 GitLab 10.2 中针对项目级集群引入. +* 在 GitLab 11.6 中针对组级集群引入. +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/209736)了本地 Tiller 选项,该选项在功能标记后(默认情况下启用). +* 在 GitLab.com 上启用了本地 Tiller 的功能标志. + +[Helm](https://helm.sh/docs/)是 Kubernetes 的软件包管理器,用于安装 GitLab 管理的应用程序. GitLab 在集群内`gitlab-managed-apps`命名空间内的 pod 中运行每个`helm`命令. + +从 GitLab 13.2 开始,集成默认使用本地[Tiller](https://v2.helm.sh/docs/glossary/#tiller) . 使用本地 Tiller 时,不需要安装 Helm 应用程序,也不会显示在应用程序列表中. + +**注意:** GitLab 的 Helm 集成不支持在代理后面安装应用程序,但是可以使用一种[解决方法](../../topics/autodevops/index.html#install-applications-behind-a-proxy) . + +### Enable or disable local Tiller[](#enable-or-disable-local-tiller-core-only "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/209736) +* [计划](https://gitlab.com/gitlab-org/gitlab/-/issues/209736)在 GitLab 13.3 中[删除](https://gitlab.com/gitlab-org/gitlab/-/issues/209736)禁用本地 Tiller 的选项 + +本地分 iller 正在开发中,但已准备好用于生产. 它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../administration/feature_flags.html)可以为您的实例启用它. + +要启用它: + +``` +# Instance-wide +Feature.enable(:managed_apps_local_tiller) +``` + +禁用它: + +``` +# Instance-wide +Feature.disable(:managed_apps_local_tiller) +``` + +### cert-manager[](#cert-manager "Permalink") + +在 GitLab 11.6 中针对项目级和组级集群引入. + +[cert-manager](https://cert-manager.io/docs/)是本地 Kubernetes 证书管理控制器,可帮助颁发证书. 在群集上安装 cert-manager 将通过[Let's Encrypt](https://letsencrypt.org/)颁发证书,并确保证书有效和最新. + +用于安装此应用程序的图表取决于所使用的 GitLab 版本. 在: + +* 在 GitLab 12.3 及更高版本中, [jetstack / cert-manager](https://github.com/jetstack/cert-manager)图表与[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/cert_manager/values.yaml)文件一起使用. +* 在 GitLab 12.2 和更早版本中,使用了[稳定/证书管理器](https://github.com/helm/charts/tree/master/stable/cert-manager)图表. + +如果您在 GitLab 12.3 之前安装了 cert-manager,那么我们加密将[阻止来自较早版本 cert-manager 的请求](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753) . + +要解决此问题: + +1. 卸载 cert-manager(考虑[备份任何其他配置](https://cert-manager.io/docs/tutorials/backup/) ). +2. 再次安装 cert-manager. + +### GitLab Runner[](#gitlab-runner "Permalink") + +版本历史 + +* 在 GitLab 10.6 中针对项目级集群引入. +* 在 GitLab 11.10 中针对组级集群引入. + +[GitLab Runner](https://docs.gitlab.com/runner/)是一个开源项目,用于运行您的作业并将结果发送回 GitLab. 它与[GitLab CI / CD](../../ci/README.html)结合使用, [GitLab CI / CD](../../ci/README.html)是 GitLab 随附的用于协调作业的开源持续集成服务. + +如果该项目在 GitLab.com 上,则可以使用共享的 Runners(前 2000 分钟是免费的,以后您可以[购买更多](../../subscriptions/index.html#purchasing-additional-ci-minutes) ),并且如果它们足以满足您的需求,则不必部署它. 如果需要特定于项目的运行器,或者没有共享的运行器,则部署它很容易. + +请注意,已部署的 Runner 将设置为**privileged** ,这意味着它实际上将具有对基础计算机的 root 访问权限. 这是构建 Docker 映像所必需的,因此它是默认设置. 在部署前,请确保已阅读[安全隐患](../project/clusters/index.html#security-implications) . + +**注意:** [`runner/gitlab-runner`](https://gitlab.com/gitlab-org/charts/gitlab-runner)图表用于使用[预先配置的`values.yaml`](https://gitlab.com/gitlab-org/charts/gitlab-runner/-/blob/master/values.yaml)文件安装此应用程序. 不支持通过修改此文件来自定义安装. + +### Ingress[](#ingress "Permalink") + +版本历史 + +* 在 GitLab 10.2 中针对项目级集群引入. +* 在 GitLab 11.6 中针对组级集群引入. + +[Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)提供开箱即用的负载平衡,SSL 终止和基于名称的虚拟主机. 它充当应用程序的 Web 代理,如果要使用[Auto DevOps](../../topics/autodevops/index.html)或部署自己的 Web 应用程序,则很有用. + +安装的 Ingress Controller 是[Ingress-NGINX](https://kubernetes.io/docs/concepts/services-networking/ingress/) ,由 Kubernetes 社区支持. + +**注意:**通过以下过程,必须在群集中安装负载均衡器才能获取端点. 如果使用 Knative,则可以使用 Ingress 或 Knative 自己的负载平衡器( [Istio](https://istio.io) ). + +In order to publish your web application, you first need to find the endpoint which will be either an IP address or a hostname associated with your load balancer. + +要安装它,请点击 Ingress 的**安装**按钮. GitLab 将尝试确定外部端点,并且它应在几分钟之内可用. + +#### Determining the external endpoint automatically[](#determining-the-external-endpoint-automatically "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17052) . + +安装 Ingress 之后,外部端点应在几分钟之内可用. + +**提示:**可以使用`KUBE_INGRESS_BASE_DOMAIN`环境变量将此端点用于[Auto DevOps 基础域](../../topics/autodevops/index.html#auto-devops-base-domain) . + +如果没有出现端点,并且您的集群在 Google Kubernetes Engine 上运行: + +1. [在 Google Kubernetes Engine 上](https://console.cloud.google.com/kubernetes)检查您的[Kubernetes 集群,](https://console.cloud.google.com/kubernetes)以确保其节点上没有错误. +2. 确保您在 Google Kubernetes Engine 上有足够的[配额](https://console.cloud.google.com/iam-admin/quotas) . 有关更多信息,请参见[资源配额](https://cloud.google.com/compute/quotas) . +3. 检查[Google Cloud 的状态,](https://status.cloud.google.com/)以确保它们没有任何中断. + +安装后,您可能会看到一个`?` 取决于云提供商的"入口 IP 地址". 特别是对于 EKS,这是因为 ELB 是使用 DNS 名称而不是 IP 地址创建的. 如果 GitLab 仍然无法确定您的 Ingress 或 Knative 应用程序的端点,则可以[手动确定它](#determining-the-external-endpoint-manually) . + +**注意:** [`stable/nginx-ingress`](https://github.com/helm/charts/tree/master/stable/nginx-ingress)图表用于通过[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/ingress/values.yaml)文件安装此应用程序. + +#### Determining the external endpoint manually[](#determining-the-external-endpoint-manually "Permalink") + +如果群集位于 GKE 上,请单击" **高级设置"中**的**Google Kubernetes Engine**链接,或直接转到[Google Kubernetes Engine 仪表板,](https://console.cloud.google.com/kubernetes/)然后选择适当的项目和群集. 然后单击" **连接"** ,然后在本地终端或使用**Cloud Shell**执行`gcloud`命令. + +如果集群不在 GKE 上,请按照 Kubernetes 提供程序的特定说明使用正确的凭据配置`kubectl` . 以下示例的输出将显示集群的外部端点. 然后,可以使用此信息来设置 DNS 条目和转发规则,以允许外部访问已部署的应用程序. + +If you installed Ingress via the **Applications**, run the following command: + +``` +kubectl get service --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}' +``` + +有些 Kubernetes 集群会返回主机名,例如[Amazon EKS](https://aws.amazon.com/eks/) . 对于这些平台,运行: + +``` +kubectl get service --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' +``` + +对于 Istio / Knative,命令将有所不同: + +``` +kubectl get svc --namespace=istio-system istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} ' +``` + +否则,您可以列出所有负载均衡器的 IP 地址: + +``` +kubectl get svc --all-namespaces -o jsonpath='{range.items[?(@.status.loadBalancer.ingress)]}{.status.loadBalancer.ingress[*].ip} ' +``` + +**注意:**如果使用 EKS,还将创建一个[Elastic Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/) ,这将产生额外的 AWS 成本.**注意:**在某些 Kubernetes 版本上,您可能会看到尾随`%` , **但不要包括它** . + +入口现在在此地址可用,并将基于请求中的 DNS 名称将传入请求路由到适当的服务. 为此,应为所需的域名创建通配符 DNS CNAME 记录. 例如, `*.myekscluster.com`将指向之前获得的 Ingress 主机名. + +#### Using a static IP[](#using-a-static-ip "Permalink") + +默认情况下,临时外部 IP 地址与群集的负载平衡器关联. 如果您将临时 IP 与 DNS 关联,并且 IP 更改,则将无法访问您的应用程序,因此您必须再次更改 DNS 记录. 为了避免这种情况,您应该将其更改为静态保留的 IP. + +阅读如何[在 GKE 中提升临时外部 IP 地址](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address#promote_ephemeral_ip) . + +#### Pointing your DNS at the external endpoint[](#pointing-your-dns-at-the-external-endpoint "Permalink") + +设置外部终结点后,应将其与[通配符 DNS 记录(](https://en.wikipedia.org/wiki/Wildcard_DNS_record)例如`*.example.com.`相关联`*.example.com.` 为了能够访问您的应用. 如果您的外部端点是 IP 地址,请使用 A 记录. 如果您的外部端点是主机名,请使用 CNAME 记录. + +#### Web Application Firewall (ModSecurity)[](#web-application-firewall-modsecurity "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21966) . + +Web 应用程序防火墙(WAF)可以检查正在发送或接收的流量,并可以在恶意流量到达您的应用程序之前对其进行阻止. WAF 的好处是: + +* 实时监控您的应用程序 +* 将所有 HTTP 通信记录到应用程序 +* 您的应用程序的访问控制 +* 高度可配置的日志记录和阻止规则 + +开箱即用,GitLab 为您提供了一个称为[`ModSecurity`](https://www.modsecurity.org/)的 WAF. + +ModSecurity 是用于实时 Web 应用程序监视,日志记录和访问控制的工具包. 借助 GitLab 的产品,将自动应用[OWASP 的 Core Rule Set](https://www.modsecurity.org/CRS/Documentation/) (提供通用的攻击检测功能). + +此功能: + +* 除非另有配置,否则以"仅检测模式"运行. +* 通过检查您的 Ingress 控制器的`modsec`日志中是否有违反规则可以查看. 例如: + + ``` + kubectl logs -n gitlab-managed-apps $(kubectl get pod -n gitlab-managed-apps -l app=nginx-ingress,component=controller --no-headers=true -o custom-columns=:metadata.name) modsecurity-log -f + ``` + +要启用 WAF,请在安装或更新[Ingress 应用程序](#ingress)时将其相应的切换开关切换到启用位置. + +如果这是您首次使用 GitLab 的 WAF,我们建议您遵循[快速入门指南](../../topics/web_application_firewall/quick_start_guide.html) . + +通过启用 ModSecurity,性能开销很小. 如果这对于您的应用程序而言很重要,则可以通过以下任何一种方式为已部署的应用程序禁用 ModSecurity 的规则引擎: + +1. Setting [the deployment variable](../../topics/autodevops/index.html) `AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE` to `Off`. This will prevent ModSecurity from processing any requests for the given application or environment. + +2. 将其各自的切换开关切换到禁用位置,然后通过" **保存更改"**按钮应用更改. 这将使用最新更改重新安装 Ingress. + +[![Disabling WAF](img/74f87e79779a102e82a644227e50a2e4.png)](../../topics/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png) + +##### Logging and blocking modes[](#logging-and-blocking-modes "Permalink") + +为了帮助您调整 WAF 规则,可以将 WAF 全局设置为" **日志记录"**或" **阻止"**模式: + +* **日志记录模式** -允许符合规则的流量通过并记录事件. +* **阻止模式** -阻止符合规则的流量通过,并记录事件. + +更改 WAF 的模式: + +1. 如果尚未[安装 ModSecurity](../../topics/web_application_firewall/quick_start_guide.html) ,请[安装它](../../topics/web_application_firewall/quick_start_guide.html) . +2. 导航 **运营>州长** . +3. In **Applications**, scroll to **Ingress**. +4. 在" **全局默认值"下** ,选择所需的模式. +5. Click **保存更改**. + +##### WAF version updates[](#waf-version-updates "Permalink") + +由于[Helm 的](https://helm.sh/)限制,在以后的发行版中可能会克服这些问题,因此仅在同一版本的[Ingress 中](#ingress)才允许启用,禁用或更改**ModSecurity**的日志记录模式. + +如果所部署的版本与 GitLab 中可用的版本不同,则将禁用**ModSecurity** UI 控件,而仍可以执行[Ingress](#ingress)级别的操作,例如卸载: + +[![WAF settings disabled](img/27858125d0f3461e373b06413f40e616.png)](../../topics/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png) + +将[Ingress](#ingress)更新到最新版本使您能够利用错误修复,安全修复和性能改进. 要更新[Ingress 应用程序](#ingress) ,您必须首先将其卸载,然后按照[Install ModSecurity 中的说明](../../topics/web_application_firewall/quick_start_guide.html)进行重新[安装](../../topics/web_application_firewall/quick_start_guide.html) . + +##### Viewing Web Application Firewall traffic[](#viewing-web-application-firewall-traffic "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14707) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9. + +您可以通过导航到项目的" **安全性和合规性">"威胁监视"**页面来查看 Web 应用程序防火墙的流量. + +从那里,您可以看到随着时间的推移进行跟踪: + +* 您的应用程序的总流量. +* Web 应用程序防火墙的默认[OWASP 规则集](https://www.modsecurity.org/CRS/Documentation/)认为异常的流量比例. + +如果很大一部分流量是异常的,则应[检查](#web-application-firewall-modsecurity)潜在的威胁,这可以通过[检查 Web 应用程序防火墙日志](#web-application-firewall-modsecurity)来完成. + +[![Threat Monitoring](img/a3964b6d91003c90a72b5ca689b9e0c5.png)](img/threat_monitoring_v12_9.png) + +### JupyterHub[](#jupyterhub "Permalink") + +版本历史 + +* 在 GitLab 11.0 中针对项目级集群引入. +* 在 GitLab 12.3 中针对组和实例级集群引入. + +[JupyterHub](https://jupyterhub.readthedocs.io/en/stable/)是用于在团队中管理笔记本的多用户服务. [Jupyter Notebook](https://jupyter-notebook.readthedocs.io/en/latest/)提供了一个基于 Web 的交互式编程环境,用于数据分析,可视化和机器学习. + +Authentication will be enabled only for [project members](../project/members/index.html) for project-level clusters and group members for group-level clusters with [Developer or higher](../permissions.html) access to the associated project or group. + +我们使用一个[自定义的 Jupyter 映像](https://gitlab.com/gitlab-org/jupyterhub-user-image/blob/master/Dockerfile) ,该[映像](https://gitlab.com/gitlab-org/jupyterhub-user-image/blob/master/Dockerfile)将在基础 Jupyter 之上安装其他有用的软件包. 您还将看到使用 Nurtch 的[Rubix 库](https://github.com/Nurtch/rubix)构建的即用型 DevOps Runbook. + +有关创建可执行运行本的更多信息,请参见[我们的运行本文档](../project/clusters/runbooks/index.html#configure-an-executable-runbook-with-gitlab) . 请注意,必须先安装 Ingress 并分配 IP 地址,然后才能安装 JupyterHub. + +**注意:** [`jupyter/jupyterhub`](https://jupyterhub.github.io/helm-chart/)图表用于通过[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/jupyter/values.yaml)文件安装此应用程序. + +#### Jupyter Git Integration[](#jupyter-git-integration "Permalink") + +版本历史 + +* 在 GitLab 12.0 中针对项目级集群[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28783) . +* 在 GitLab 12.3 中针对组和实例级集群[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/32512) . + +将 JupyterHub 安装到 Kubernetes 集群上时,将使用已验证用户的身份自动配置和配置[JupyterLab 的 Git 扩展](https://github.com/jupyterlab/jupyterlab-git) : + +* Name. +* Email. +* 新创建的访问令牌. + +JupyterLab 的 Git 扩展使您能够对笔记本进行完整版本控制,并在 Jupyter 中发布 Git 命令. Git 命令可以通过左侧面板上的**Git**选项卡或 Jupyter 的命令行提示符发出. + +**注意:** JupyterLab 的 Git 扩展将用户令牌以加密格式存储在 JupyterHub DB 中,并以纯文本形式存储在单个用户 Jupyter 实例中. 这是因为[Git 要求将凭据存储为纯文本](https://git-scm.com/docs/git-credential-store) . 潜在地,如果一个邪恶的用户在单用户 Jupyter 实例中找到一种从文件系统读取的方法,则他们可以检索令牌. + +[![Jupyter's Git Extension](img/993315f2d7b2aa15b2f3faa03d14705c.png)](img/jupyter-git-extension.gif) + +您可以从 Jupyter 的"文件"选项卡中克隆存储库: + +[![Jupyter clone repository](img/bed33522d3ca08c8f5c920ba11fa05d4.png)](img/jupyter-gitclone.png) + +### Knative[](#knative "Permalink") + +版本历史 + +* 在 GitLab 11.5 中针对项目级集群引入. +* 在 GitLab 12.3 中针对组和实例级集群引入. + +[Knative](https://cloud.google.com/knative/)提供了一个平台,用于从 Kubernetes 集群创建,部署和管理无服务器工作负载. 它与[Istio](https://istio.io)结合使用并包括在内, [以为 Knative](https://istio.io)托管的所有程序提供外部 IP 地址. + +系统将提示您输入一个通配符域,您的应用程序将在该域中公开. 配置您的 DNS 服务器以使用该域的外部 IP 地址. 对于创建和安装的任何应用程序,可以通过`..` . 这将要求您的 Kubernetes 群集[启用 RBAC](../project/clusters/add_remove_clusters.html#rbac-cluster-resources) . + +**Note:** The [`knative/knative`](https://storage.googleapis.com/triggermesh-charts) chart is used to install this application. + +### Prometheus[](#prometheus "Permalink") + +版本历史 + +* 在 GitLab 10.4 中针对项目级集群引入. +* 在 GitLab 11.11 中针对组级集群引入. + +[Prometheus](https://s0prometheus0io.icopy.site/docs/introduction/overview/)是一个开源监视和警报系统,可用于监督已部署的应用程序. + +GitLab 能够使用[Prometheus 集成](../project/integrations/prometheus.html)自动监视应用程序. Kubernetes 容器的 CPU 和内存指标将自动收集,响应指标也将从 NGINX Ingress 检索. + +要启用监视,只需使用" **安装"**按钮将 Prometheus 安装到群集中. + +**注意:** [`stable/prometheus`](https://github.com/helm/charts/tree/master/stable/prometheus)图表用于通过[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/prometheus/values.yaml)文件安装此应用程序. + +### Crossplane[](#crossplane "Permalink") + +版本历史 + +* 在 GitLab 12.5 中针对项目级集群[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34702) . + +[Crossplane](https://crossplane.github.io/docs/v0.9/)是一种多云控制平面,可用于跨多个云管理应用程序和基础架构. 它使用以下方法扩展了 Kubernetes API: + +* 自定义资源. +* 监视那些自定义资源的控制器. + +Crossplane 通过抽象特定于云提供商的配置,以统一的方式允许跨云提供商进行基础架构组件的供应和生命周期管理. + +Crossplane GitLab 管理的应用程序: + +* 在连接到项目存储库的 Kubernetes 集群上使用选择的提供程序安装 Crossplane. +* 然后可以用于通过 Auto DevOps 管道来配置基础结构或托管应用程序,例如 PostgreSQL(例如,来自 GCP 的 CloudSQL 或来自 AWS 的 RDS)以及该应用程序所需的其他服务. + +有关配置群集上安装的 Crossplane 的信息,请参阅[Crossplane 配置](crossplane.html) . + +**注意:** [`alpha/crossplane`](https://github.com/crossplane/crossplane/tree/v0.4.1/cluster/charts/crossplane) crossplane 图表 v0.4.1 用于通过[`values.yaml`](https://github.com/crossplane/crossplane/blob/master/cluster/charts/crossplane/values.yaml.tmpl)文件安装 Crossplane. + +### Elastic Stack[](#elastic-stack "Permalink") + +在 GitLab 12.7 中针对项目级和组级集群引入. + +[Elastic Stack](https://www.elastic.co/elastic-stack)是一个完整的端到端日志分析解决方案,可帮助深入搜索,分析和可视化从不同计算机生成的日志. + +GitLab 能够自动从集群中的 Pod 收集日志. Filebeat 将在集群中的每个节点上作为 DaemonSet 运行,并将容器日志发送到 Elasticsearch 进行查询. 然后,GitLab 将连接到 Elasticsearch 以获取日志而不是 Kubernetes API,您将可以使用更高级的查询功能. + +使用[Curator](https://www.elastic.co/guide/en/elasticsearch/client/curator/5.5/about.html)在 30 天后会自动删除日志数据. + +要启用日志传送: + +1. 确保您的集群至少包含 3 个实例类型大于`f1-micro` , `g1-small`或`n1-standard-1`节点. +2. 导航 **运营>州长** . +3. 在**Kubernetes Cluster 中** ,选择一个集群. +4. 在" **应用程序"**部分中,找到" **Elastic Stack"** ,然后单击" **安装"** . + +**注意:** [`gitlab/elastic-stack`](https://gitlab.com/gitlab-org/charts/elastic-stack)图用于通过[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/elastic_stack/values.yaml)文件安装此应用程序.**注意:**该图表部署了 3 个相同的 Elasticsearch Pod,这些 Pod 无法共置,每个 Pod 需要 1 个 CPU 和 2 GB RAM,从而使其与包含少于 3 个节点或由`f1-micro` , `g1-small` , `n1-standard-1`组成的集群不兼容`n1-standard-1`或`*-highcpu-2`实例类型.**注意:** Elastic Stack 群集应用程序旨在用作日志聚合解决方案,并且与我们的[Advanced Global Search](../search/advanced_global_search.html)功能无关,后者使用单独的 Elasticsearch 群集. + +#### Optional: deploy Kibana to perform advanced queries[](#optional-deploy-kibana-to-perform-advanced-queries "Permalink") + +如果您是高级用户,并且可以使用`kubectl`和`helm`直接访问 Kubernetes 集群,则可以手动部署 Kibana. + +下面假设`helm`已经[初始化](https://v2.helm.sh/docs/helm/)与`helm init` . + +将以下内容保存到`kibana.yml` : + +``` +elasticsearch: + enabled: false + +filebeat: + enabled: false + +kibana: + enabled: true + elasticsearchHosts: http://elastic-stack-elasticsearch-master.gitlab-managed-apps.svc.cluster.local:9200 +``` + +然后将其安装在您的集群上: + +``` +helm repo add gitlab https://charts.gitlab.io +helm install --name kibana gitlab/elastic-stack --values kibana.yml +``` + +要访问 Kibana,请将端口转发到本地计算机: + +``` +kubectl port-forward svc/kibana-kibana 5601:5601 +``` + +然后,您可以通过`http://localhost:5601`访问 Kibana. + +### Fluentd[](#fluentd "Permalink") + +在 GitLab 12.10 中针对项目级和组级集群引入. + +[Fluentd](https://www.fluentd.org/)是一个开源数据收集器,它使您能够统一数据收集和使用以更好地使用和理解数据. Fluentd 以 syslog 格式发送日志. + +To enable Fluentd: + +1. 导航 **操作> Kubernetes** ,然后单击**应用程序** . 系统将提示您输入主机,端口和协议,WAF 日志将通过 syslog 发送到该主机,端口和协议. +2. 在**SIEM Hostname 中**提供主机域名或 URL. +3. 在**SIEM Port 中**提供主机端口号. +4. 选择一个**SIEM 协议** . +5. 选择至少一个可用日志(例如 WAF 或 Cilium). +6. Click **保存更改**. + +[![Fluentd input fields](img/f52fe1b4788045a510a1783bfb546b6f.png)](img/fluentd_v13_0.png) + +### Future apps[](#future-apps "Permalink") + +有兴趣贡献一个新的 GitLab 托管应用程序吗? 访问[开发指南页面](../../development/kubernetes.html#gitlab-managed-apps)以开始使用. + +## Install using GitLab CI/CD (alpha)[](#install-using-gitlab-cicd-alpha "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20822) in GitLab 12.6. + +**警告:**这是*Alpha 版*功能,如有更改,恕不另行通知. + +这种替代方法允许用户使用 GitLab CI / CD 安装由 GitLab 管理的应用程序. 它还允许使用 Helm `values.yaml`文件来自定义安装. + +支持的应用程序: + +* [Ingress](#install-ingress-using-gitlab-cicd) +* [cert-manager](#install-cert-manager-using-gitlab-cicd) +* [Sentry](#install-sentry-using-gitlab-cicd) +* [GitLab Runner](#install-gitlab-runner-using-gitlab-cicd) +* [Cilium](#install-cilium-using-gitlab-cicd) +* [Falco](#install-falco-using-gitlab-cicd) +* [Vault](#install-vault-using-gitlab-cicd) +* [JupyterHub](#install-jupyterhub-using-gitlab-cicd) +* [Elastic Stack](#install-elastic-stack-using-gitlab-cicd) +* [Crossplane](#install-crossplane-using-gitlab-cicd) +* [Fluentd](#install-fluentd-using-gitlab-cicd) +* [Knative](#install-knative-using-gitlab-cicd) +* [PostHog](#install-posthog-using-gitlab-cicd) +* [Prometheus](#install-prometheus-using-gitlab-cicd) + +### Usage[](#usage "Permalink") + +您可以在[示例集群应用程序项目中](https://gitlab.com/gitlab-org/cluster-integration/example-cluster-applications/)找到并导入下面引用的所有文件. + +要使用 GitLab CI / CD 安装应用程序: + +1. 将集群连接到[集群管理项目](management_project.html) . +2. 在该项目中,添加具有以下内容的`.gitlab-ci.yml`文件: + + ``` + include: + - template: Managed-Cluster-Applications.gitlab-ci.yml + ``` + + **注意:**此模板提供的作业使用自定义 Docker 映像中提供的工具连接到集群. 它要求您具有在 Docker,Kubernetes 或 Docker Machine 执行器上注册的运行程序. +3. 添加`.gitlab/managed-apps/config.yaml`文件,以定义要安装的应用程序. 将已`installed`密钥定义为`true`以安装应用程序,将`false`为卸载应用程序. 例如,要安装 Ingress: + + ``` + ingress: + installed: true + ``` + +4. (可选)定义`.gitlab/managed-apps//values.yaml`文件,以自定义已安装应用程序的值. + +然后,一个 GitLab CI / CD 管道将在`master`分支上运行,以安装您配置的应用程序. 万一管道发生故障, [Helm Tiller](https://v2.helm.sh/docs/install/#running-tiller-locally)二进制文件的输出将另存为[CI 作业工件](../../ci/pipelines/job_artifacts.html) . + +### Important notes[](#important-notes "Permalink") + +请注意以下几点: + +* 我们建议仅使用集群管理项目来管理集群的部署. 不要将应用程序的源代码添加到此类项目中. +* 当您将`installed`密钥的值`installed`回`false` ,将从群集中取消配置该应用程序. +* 如果使用新值更新`.gitlab/managed-apps//values.yaml` ,则将重新部署该应用程序. + +### Install Ingress using GitLab CI/CD[](#install-ingress-using-gitlab-cicd "Permalink") + +要安装 Ingress,请使用以下命令定义`.gitlab/managed-apps/config.yaml`文件: + +``` +ingress: + installed: true +``` + +然后,Ingress 将安装到集群的`gitlab-managed-apps`命名空间中. + +You can customize the installation of Ingress by defining a `.gitlab/managed-apps/ingress/values.yaml` file in your cluster management project. Refer to the [chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress) for the available configuration options. + +**注意:** GitLab 配置组提供了对安装 Ingress 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并从[Configure 组中](https://about.gitlab.com/handbook/product/categories/#configure-group) ping 通至少 2 个人. + +### Install cert-manager using GitLab CI/CD[](#install-cert-manager-using-gitlab-cicd "Permalink") + +通过在`.gitlab/managed-apps/config.yaml`定义配置,使用 GitLab CI / CD 安装了 cert-manager. + +cert-manager: + +* 已安装到集群的`gitlab-managed-apps`命名空间中. +* Can be installed with or without a default [Let’s Encrypt `ClusterIssuer`](https://cert-manager.io/docs/configuration/acme/), which requires an email address to be specified. The email address is used by Let’s Encrypt to contact you about expiring certificates and issues related to your account. + +使用 GitLab CI / CD 安装证书管理器需要以下配置: + +``` +certManager: + installed: true + letsEncryptClusterIssuer: + installed: true + email: "user@example.com" +``` + +以下使用 GitLab CI / CD 安装 cert-manager,而没有默认的`ClusterIssuer` : + +``` +certManager: + installed: true + letsEncryptClusterIssuer: + installed: false +``` + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/cert-manager/values.yaml`文件来自定义 cert-manager 的安装. 请参阅[图表](https://hub.helm.sh/charts/jetstack/cert-manager)以获取可用的配置选项. + +**注意:** GitLab 配置组提供了对安装 Cert Manager 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并从[Configure 组中](https://about.gitlab.com/handbook/product/categories/#configure-group) ping 通至少 2 个人. + +### Install Sentry using GitLab CI/CD[](#install-sentry-using-gitlab-cicd "Permalink") + +**注意:** Sentry Helm 图表[建议](https://github.com/helm/charts/blob/f6e5784f265dd459c5a77430185d0302ed372665/stable/sentry/values.yaml#L284-L285)至少 3GB 的可用 RAM 用于数据库迁移. + +To install Sentry, define the `.gitlab/managed-apps/config.yaml` file with: + +``` +sentry: + installed: true +``` + +然后,将 Sentry 安装到集群的`gitlab-managed-apps`命名空间中. + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/sentry/values.yaml`文件来自定义 Sentry 的安装. 请参阅[图表](https://github.com/helm/charts/tree/master/stable/sentry)以获取可用的配置选项. + +我们建议您密切注意以下配置选项: + +* `email` . 需要邀请用户加入您的 Sentry 实例并发送错误电子邮件. +* `user` . 您可以在其中设置默认管理员用户的登录凭据. +* `postgresql` . 有关在将来运行更新时可以使用的 PostgreSQL 密码. + +**注意:**升级时,重要的是提供现有的 PostgreSQL 密码(使用`postgresql.postgresqlPassword`密钥提供),否则您将收到认证错误. 有关更多信息,请参见[PostgreSQL 图表文档](https://github.com/helm/charts/tree/master/stable/postgresql#upgrade) . + +这是 Sentry 的示例配置: + +``` +# Admin user to create +user: + # Indicated to create the admin user or not, + # Default is true as the initial installation. + create: true + email: "" + password: "" + +email: + from_address: "" + host: smtp + port: 25 + use_tls: false + user: "" + password: "" + enable_replies: false + +ingress: + enabled: true + hostname: "" + +# Needs to be here between runs. +# See https://github.com/helm/charts/tree/master/stable/postgresql#upgrade for more info +postgresql: + postgresqlPassword: example-postgresql-password +``` + +**注意:** GitLab Health 组为安装 Sentry 托管应用程序提供支持. 如果您遇到未知问题,请[打开一个新的问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并从[健康小组](https://about.gitlab.com/handbook/product/product-categories/#health-group) ping 至少 2 个人. + +### Install PostHog using GitLab CI/CD[](#install-posthog-using-gitlab-cicd "Permalink") + +[PostHog](https://www.posthog.com)是开发人员友好的开源产品分析平台. + +要将 PostHog 安装到群集的`gitlab-managed-apps`命名空间中,请使用以下`.gitlab/managed-apps/config.yaml`定义`.gitlab/managed-apps/config.yaml`文件: + +``` +posthog: + installed: true +``` + +您可以通过在群集管理项目中定义`.gitlab/managed-apps/posthog/values.yaml`来自定义`.gitlab/managed-apps/posthog/values.yaml`的安装. 有关可用的配置选项,请参阅[PostHog 图表的自述文件](https://github.com/PostHog/charts/tree/master/charts/posthog)的" [配置"部分](https://github.com/PostHog/charts/tree/master/charts/posthog) . + +**注意:**您必须在`postgresql.postgresqlPassword`提供 PostgreSQL 密码,否则将收到身份验证错误. 有关更多信息,请参见[PostgreSQL 图表文档](https://github.com/helm/charts/tree/master/stable/postgresql#upgrade) . + +Redis Pod 在升级之间重新启动. 为防止停机,请使用`redis.password`键提供 Redis 密码. 这样可以防止在每次重新启动时生成新密码. + +这是 PostHog 的示例配置: + +``` +ingress: + enabled: true + hostname: "" + +# This will be autogenerated if you skip it. Include if you have 2 or more web replicas +posthogSecret: 'long-secret-key-used-to-sign-cookies' + +# Needs to be here between runs. +# See https://github.com/helm/charts/tree/master/stable/postgresql#upgrade for more info +postgresql: + postgresqlPassword: example-postgresql-password + +# Recommended to set this to a value to redis prevent downtime between upgrades +redis: + password: example-redis-password +``` + +**注意:** PostHog 团队对 PostHog 托管应用程序提供支持. 如果遇到问题,请直接[打开支持凭单](https://github.com/PostHog/posthog/issues/new/choose) . + +### Install Prometheus using GitLab CI/CD[](#install-prometheus-using-gitlab-cicd "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25138) . + +[Prometheus](https://s0prometheus0io.icopy.site/docs/introduction/overview/)是用于监视已部署应用程序的开源监视和警报系统. + +要将 Prometheus 安装到群集的`gitlab-managed-apps`命名空间中,请使用以下`.gitlab/managed-apps/config.yaml`定义`.gitlab/managed-apps/config.yaml`文件: + +``` +prometheus: + installed: true +``` + +您可以通过在群集管理项目中定义`.gitlab/managed-apps/prometheus/values.yaml`来定制 Prometheus 的安装. 有关可用的配置选项,请参阅[Prometheus 图的 README](https://github.com/helm/charts/tree/master/stable/prometheus#configuration)的[Configuration(配置)部分](https://github.com/helm/charts/tree/master/stable/prometheus#configuration) . + +**注意:** GitLab APM 组提供了对安装 Prometheus 托管应用程序的支持. 如果遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping [APM 组中的](https://about.gitlab.com/handbook/product/product-categories/#apm-group)至少 2 个人. + +### Install GitLab Runner using GitLab CI/CD[](#install-gitlab-runner-using-gitlab-cicd "Permalink") + +通过在`.gitlab/managed-apps/config.yaml`定义配置,使用 GitLab CI / CD 安装了 GitLab Runner. + +使用 GitLab CI / CD 安装 GitLab Runner 需要以下配置: + +``` +gitlabRunner: + installed: true +``` + +GitLab Runner 已安装到集群的`gitlab-managed-apps`命名空间中. + +为了使 GitLab Runner 运行, **必须**指定以下内容: + +* `gitlabUrl`用于注册 Runner 的 GitLab 服务器完整 URL(例如, `https://example.gitlab.com` `gitlabUrl` ). +* `runnerRegistrationToken`用于将新的`runnerRegistrationToken`添加到 GitLab 的注册令牌. 这必须[从您的 GitLab 实例中检索](../../ci/runners/README.html) . + +这些值可以使用[CI 变量](../../ci/variables/README.html)指定: + +* `GITLAB_RUNNER_GITLAB_URL`将用于`gitlabUrl` . +* `GITLAB_RUNNER_REGISTRATION_TOKEN`将用于`runnerRegistrationToken` + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/gitlab-runner/values.yaml`文件来自定义 GitLab Runner 的安装. 请参阅[图表](https://gitlab.com/gitlab-org/charts/gitlab-runner)以获取可用的配置选项. + +**注意:** GitLab Runner 组提供了对安装 Runner 管理的应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping [Runner 组中的](https://about.gitlab.com/handbook/product/product-categories/#runner-group)至少 2 个人. + +### Install Cilium using GitLab CI/CD[](#install-cilium-using-gitlab-cicd "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/merge_requests/22) in GitLab 12.8. + +[Cilium](https://cilium.io/)是[Kubernetes](https://cilium.io/)的网络插件,可用于实现对[NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/)资源的支持. 有关更多信息,请参阅[网络策略](../../topics/autodevops/stages.html#network-policy) . + +有关概述,请参见[GitLab 12.8](https://www.youtube.com/watch?v=pgUEdhdhoUI)的[容器网络安全演示](https://www.youtube.com/watch?v=pgUEdhdhoUI) . + +在`.gitlab/managed-apps/config.yaml`文件中启用 Cilium 进行安装: + +``` +# possible values are gke, eks or you can leave it blank +clusterType: gke + +cilium: + installed: true +``` + +`clusterType`变量为相应的群集类型启用建议的 Helm 变量. 默认值为空白. 您可以在官方文档中检查每种群集类型的建议变量: + +* [Google GKE](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-gke/#deploy-cilium) +* [AWS EKS](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-eks/#deploy-cilium) + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/cilium/values.yaml`文件来自定义 Cilium 的 Helm 变量. 有关可用的配置选项,请参阅[Cilium 图表](https://github.com/cilium/cilium/tree/master/install/kubernetes/cilium) . + +**注意:**安装和拆卸纤毛的需要**手动** [重新启动](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-gke/#restart-unmanaged-pods)在所有命名空间所有受影响的吊舱,以确保它们[管理](https://docs.cilium.io/en/stable/troubleshooting/#ensure-pod-is-managed-by-cilium)由正确的网络插件.**注意:**主要升级可能需要其他设置步骤,请查阅官方[升级指南](https://docs.cilium.io/en/stable/install/upgrade/)以获取更多信息. + +默认情况下,Cilium 会在策略部署时丢弃所有不允许的数据包. 但是,在[auditmode](https://docs.cilium.io/en/v1.8/gettingstarted/policy-creation/?highlight=policy-audit#enable-policy-audit-mode)中,Cilium 不会丢弃不允许的数据包. 您可以使用`policy-verdict`日志来观察与策略相关的决策. 您可以通过将以下内容添加到`.gitlab/managed-apps/cilium/values.yaml`来启用审核模式: + +``` +config: + policyAuditMode: true + +agent: + monitor: + eventTypes: ["drop", "policy-verdict"] +``` + +用于流量的 Cilium 监视器日志由`cilium-monitor`边车容器注销. 您可以使用以下命令检查这些日志: + +``` +kubectl -n gitlab-managed-apps logs cilium-XXXX cilium-monitor +``` + +您可以在`.gitlab/managed-apps/cilium/values.yaml`禁用监视器日志: + +``` +agent: + monitor: + enabled: false +``` + +默认情况下,启用了[Hubble](https://github.com/cilium/hubble)监视守护程序,并将其设置为收集每个命名空间流指标. 可在" [威胁监控"](../application_security/threat_monitoring/index.html)仪表板上访问此指标. 您可以通过将以下内容添加到`.gitlab/managed-apps/cilium/values.yaml`来禁用 Hubble: + +``` +global: + hubble: + enabled: false +``` + +您还可以通过`.gitlab/managed-apps/cilium/values.yaml`来为哈勃调整 Helm 值: + +``` +global: + hubble: + enabled: true + metrics: + enabled: + - 'flow:sourceContext=namespace;destinationContext=namespace' +``` + +**注意:** GitLab Container Security 组提供了对安装 Cilium 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping 通至少来自[Container Security 组的](https://about.gitlab.com/handbook/product/product-categories/#container-security-group) 2 个人. + +### Install Falco using GitLab CI/CD[](#install-falco-using-gitlab-cicd "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/merge_requests/91) . + +GitLab 容器主机安全监视使用[Falco](https://falco.org/)作为运行时安全工具,该工具使用 eBPF 侦听 Linux 内核. Falco 实时解析系统调用并针对可配置的规则引擎声明流. 有关更多信息,请参见[Falco 的文档](https://falco.org/docs/) . + +您可以在`.gitlab/managed-apps/config.yaml`文件中启用 Falco: + +``` +falco: + installed: true +``` + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/falco/values.yaml`文件来自定义 Falco 的 Helm 变量. 有关可用的配置选项,请参考[Falco 图表](https://github.com/falcosecurity/charts/tree/master/falco) . + +**警告:**默认情况下,eBPF 支持已启用,Falco 将使用[eBPF 探针](https://falco.org/docs/event-sources/drivers/#using-the-ebpf-probe)将系统调用传递到用户空间. 如果您的群集不支持此功能,则可以通过将以下内容添加到`.gitlab/managed-apps/falco/values.yaml` ,将其配置为使用 Falco 内核模块: + +``` +ebpf: + enabled: false +``` + +在极少数情况下,无法在群集上自动安装探针并且未预编译内核/探针,您可能需要手动准备带有[driverkit](https://github.com/falcosecurity/driverkit#against-a-kubernetes-cluster)的内核模块或 eBPF 探针,并将其安装在每个群集节点上. + +默认情况下,Falco 部署的规则有限. 要添加更多规则,请将以下内容添加到`.gitlab/managed-apps/falco/values.yaml` (您可以从[Cloud Native Security Hub 中](https://securityhub.dev/)获取示例): + +``` +customRules: + file-integrity.yaml: |- + - rule: Detect New File + desc: detect new file created + condition: > + evt.type = chmod or evt.type = fchmod + output: > + File below a known directory opened for writing (user=%user.name + command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2]) + priority: ERROR + tags: [filesystem] + - rule: Detect New Directory + desc: detect new directory created + condition: > + mkdir + output: > + File below a known directory opened for writing (user=%user.name + command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2]) + priority: ERROR + tags: [filesystem] +``` + +默认情况下,Falco 仅将安全事件作为 JSON 对象输出到日志. 要将其设置为输出到[外部 API](https://falco.org/docs/alerts/#https-output-send-alerts-to-an-https-end-point)或[应用程序](https://falco.org/docs/alerts/#program-output) ,请将以下内容添加到`.gitlab/managed-apps/falco/values.yaml` : + +``` +falco: + programOutput: + enabled: true + keepAlive: false + program: mail -s "Falco Notification" someone@example.com + + httpOutput: + enabled: true + url: http://some.url +``` + +您可以使用以下命令检查这些日志: + +``` +kubectl logs -l app=falco -n gitlab-managed-apps +``` + +**注意:** GitLab Container Security 组提供了对安装 Falco 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping 通至少来自[Container Security 组的](https://about.gitlab.com/handbook/product/product-categories/#container-security-group) 2 个人. + +### Install Vault using GitLab CI/CD[](#install-vault-using-gitlab-cicd "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9982) . + +[Hashicorp Vault](https://www.vaultproject.io/)是一个秘密管理解决方案,可用于安全地管理和存储密码,凭据,证书等. 可以利用 Vault 安装为应用程序,GitLab CI / CD 作业等中使用的凭据提供一个安全的数据存储. 它还可以用作向基础结构中的系统和部署提供 SSL / TLS 证书的方式. 通过将 Vault 作为所有这些凭据的单一来源,可以通过对所有敏感凭据和证书具有单一的访问,控制和可审核性来源,从而提高安全性. + +To install Vault, enable it in the `.gitlab/managed-apps/config.yaml` file: + +``` +vault: + installed: true +``` + +默认情况下,您将获得基本的保险柜设置,没有可扩展的存储后端. 这对于简单的测试和小规模部署就足够了,尽管限制了它可以扩展的规模,并且由于它是单实例部署,因此在升级 Vault 应用程序时会遇到停机时间. + +为了在生产环境中最佳地使用 Vault,理想的是充分了解 Vault 的内部结构以及如何配置它. 这可以通过阅读[Vault 文档](https://www.vaultproject.io/docs/internals)以及 Vault Helm 图表[`values.yaml`文件来完成](https://github.com/hashicorp/vault-helm/blob/v0.3.3/values.yaml) . + +至少您可能会设置: + +* 用于对主密钥进行额外加密的[印章](https://www.vaultproject.io/docs/configuration/seal) . +* 适合于环境和存储安全性要求的[存储后端](https://www.vaultproject.io/docs/configuration/storage) . +* [HA Mode](https://www.vaultproject.io/docs/concepts/ha). +* [The Vault UI](https://www.vaultproject.io/docs/configuration/ui). + +以下是一个示例值文件( `.gitlab/managed-apps/vault/values.yaml` ),该文件使用 Google Cloud Storage 后端,启用 Vault UI 并启用具有 3 个 pod 的 HA,将 Google 密钥管理服务配置为自动`.gitlab/managed-apps/vault/values.yaml`副本. 下面的`storage`和`seal`节是示例,应替换为特定于您的环境的设置. + +``` +# Enable the Vault WebUI +ui: + enabled: true +server: + # Disable the built in data storage volume as it's not safe for Hight Availability mode + dataStorage: + enabled: false + # Enable High Availability Mode + ha: + enabled: true + # Configure Vault to listen on port 8200 for normal traffic and port 8201 for inter-cluster traffic + config: | + listener "tcp" { + tls_disable = 1 + address = "[::]:8200" + cluster_address = "[::]:8201" + } + # Configure Vault to store its data in a GCS Bucket backend + storage "gcs" { + path = "gcs://my-vault-storage/vault-bucket" + ha_enabled = "true" + } + # Configure Vault to automatically unseal storage using a GKMS key + seal "gcpckms" { + project = "vault-helm-dev-246514" + region = "global" + key_ring = "vault-helm-unseal-kr" + crypto_key = "vault-helm-unseal-key" + } +``` + +成功安装保险柜后,您将需要[初始化保险柜](https://learn.hashicorp.com/vault/getting-started/deploy#initializing-the-vault)并获取初始根令牌. 为此,您将需要访问已将 Vault 部署到的 Kubernetes 群集. 要初始化 Vault,请在 Kubernetes 内部运行的一个 Vault 容器中安装一个外壳(通常是通过使用`kubectl`命令行工具来完成). 将外壳放入吊舱后,运行`vault operator init`命令: + +``` +kubectl -n gitlab-managed-apps exec -it vault-0 sh +/ $ vault operator init +``` + +这应该为您提供解封密钥和初始根令牌. 确保记下这些内容并保持安全,因为您将需要它们在保险柜的整个生命周期内将其解封. + +**注意:** GitLab 版本管理组提供了对安装 Vault 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并从" [发行管理"组](https://about.gitlab.com/handbook/product/product-categories/#release-management-group) ping 至少 2 个人. + +### Install JupyterHub using GitLab CI/CD[](#install-jupyterhub-using-gitlab-cicd "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/merge_requests/40) . + +通过在`.gitlab/managed-apps/config.yaml`定义配置,使用 GitLab CI / CD 安装`.gitlab/managed-apps/config.yaml` ,如下所示: + +``` +jupyterhub: + installed: true + gitlabProjectIdWhitelist: [] + gitlabGroupWhitelist: [] +``` + +在配置中: + +* `gitlabProjectIdWhitelist`将 GitLab 身份验证限制为仅指定项目的成员. +* `gitlabGroupWhitelist`将 GitLab 身份验证限制为仅指定组的成员. +* 为两者指定一个空数组将允许 GitLab 实例上的任何用户登录. + +JupyterHub 已安装到集群的`gitlab-managed-apps`命名空间中. + +为了使 JupyterHub 正常运行,您必须设置一个[OAuth 应用程序](../../integration/oauth_provider.html) . 组: + +* “Redirect URI” to `http:///hub/oauth_callback`. +* `api read_repository write_repository` "范围". + +此外,必须使用[CI 变量](../../ci/variables/README.html)指定以下[变量](../../ci/variables/README.html) : + +| 可变 CI | Description | +| --- | --- | +| `JUPYTERHUB_PROXY_SECRET_TOKEN` | 用于签名来自集线器的通信的安全字符串. 请参阅[`proxy.secretToken`](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference/reference.html#proxy-secrettoken) . | +| `JUPYTERHUB_COOKIE_SECRET` | 用于签署安全 cookie 的安全字符串. 参见[`hub.cookieSecret`](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference/reference.html#hub-cookiesecret) . | +| `JUPYTERHUB_HOST` | 用于安装的主机名. 例如, `jupyter.gitlab.example.com` . | +| `JUPYTERHUB_GITLAB_HOST` | 用于身份验证的 GitLab 实例的主机名. 例如, `gitlab.example.com` . | +| `JUPYTERHUB_AUTH_CRYPTO_KEY` | 一个 32 字节的加密密钥,用于设置[`auth.state.cryptoKey`](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference/reference.html#auth-state-cryptokey) . | +| `JUPYTERHUB_AUTH_GITLAB_CLIENT_ID` | OAuth 应用程序的"应用程序 ID". | +| `JUPYTERHUB_AUTH_GITLAB_CLIENT_SECRET` | OAuth 应用程序的"秘密". | + +默认情况下,将使用[默认值文件](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/blob/master/src/default-data/jupyterhub/values.yaml.gotmpl)安装 JupyterHub. 您可以通过在群集管理项目中定义`.gitlab/managed-apps/jupyterhub/values.yaml`文件来自定义`.gitlab/managed-apps/jupyterhub/values.yaml`的安装. + +有关可用的配置选项,请参考[图表参考](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference/reference.html) . + +**注意:** GitLab 配置组提供了对安装 JupyterHub 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并从[Configure 组中](https://about.gitlab.com/handbook/product/categories/#configure-group) ping 通至少 2 个人. + +### Install Elastic Stack using GitLab CI/CD[](#install-elastic-stack-using-gitlab-cicd "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25138) . + +通过在`.gitlab/managed-apps/config.yaml`定义配置,使用 GitLab CI / CD 安装 Elastic Stack. + +使用 GitLab CI / CD 安装 Elastic Stack 需要以下配置: + +``` +elasticStack: + installed: true +``` + +Elastic Stack 已安装到集群的`gitlab-managed-apps`命名空间中. + +您可以检查默认[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/vendor/elastic_stack/values.yaml)我们此图表设置. + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/elastic-stack/values.yaml`文件来自定义 Elastic Stack 的安装. 请参阅[图表](https://gitlab.com/gitlab-org/charts/elastic-stack)以获取可用的配置选项. + +**注意:**在通过 CI 安装 Elastic Stack 的 alpha 实现中,不支持通过 Elasticsearch 读取环境日志. 如果[通过 UI 安装,](#elastic-stack)则支持此功能.**注意:** GitLab APM 组提供了对安装 Elastic Stack 托管应用程序的支持. 如果遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping [APM 组中的](https://about.gitlab.com/handbook/product/product-categories/#apm-group)至少 2 个人. + +### Install Crossplane using GitLab CI/CD[](#install-crossplane-using-gitlab-cicd "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/35675) . + +通过在`.gitlab/managed-apps/config.yaml`定义配置,使用 GitLab CI / CD 安装 Crossplane. + +使用 GitLab CI / CD 安装 Crossplane 需要以下配置: + +``` +Crossplane: + installed: true +``` + +Crossplane 已安装到集群的`gitlab-managed-apps`命名空间中. + +您可以检查默认[`values.yaml`](https://github.com/crossplane/crossplane/blob/master/cluster/charts/crossplane/values.yaml.tmpl)我们此图表设置. + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/crossplane/values.yaml`文件来自定义 Crossplane 的安装. 请参阅[图表](https://github.com/crossplane/crossplane/tree/master/cluster/charts/crossplane#configuration)以获取可用的配置选项. 请注意,此链接指向当前开发版本的文档,该文档可能与您安装的版本不同. + +**注意:** Crossplane 团队提供对 Crossplane 托管应用程序的支持. 如果遇到问题,请直接[打开支持凭单](https://github.com/crossplane/crossplane/issues/new/choose) . + +### Install Fluentd using GitLab CI/CD[](#install-fluentd-using-gitlab-cicd "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/merge_requests/76) . + +要使用 GitLab CI / CD 将`gitlab-managed-apps`安装到群集的`gitlab-managed-apps`命名空间中,请在`.gitlab/managed-apps/config.yaml`定义以下配置: + +``` +Fluentd: + installed: true +``` + +您也可以在[`values.yaml`](https://github.com/helm/charts/blob/master/stable/fluentd/values.yaml)文件中查看为此图表设置的默认值. + +您可以通过在群集管理项目中定义`.gitlab/managed-apps/fluentd/values.yaml`文件来自定义`.gitlab/managed-apps/fluentd/values.yaml`的安装. 有关可用的配置选项,请参阅[Fluentd 当前开发版本](https://github.com/helm/charts/tree/master/stable/fluentd#configuration)的[配置表](https://github.com/helm/charts/tree/master/stable/fluentd#configuration) . + +**注意:**配置图表链接指向当前的开发版本,该版本可能与您安装的版本不同. 为了确保兼容性,请切换到您正在使用的特定分支或标签.**注意:** GitLab Container Security 组提供了对安装 Fluentd 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping 通至少来自[Container Security 组的](https://about.gitlab.com/handbook/product/product-categories/#container-security-group) 2 个人. + +### Install Knative using GitLab CI/CD[](#install-knative-using-gitlab-cicd "Permalink") + +要安装 Knative,请使用以下命令定义`.gitlab/managed-apps/config.yaml`文件: + +``` +knative: + installed: true +``` + +您可以通过在集群管理项目中定义`.gitlab/managed-apps/knative/values.yaml`文件来自定义`.gitlab/managed-apps/knative/values.yaml`的安装. 请参阅[图表](https://gitlab.com/gitlab-org/charts/knative)以获取可用的配置选项. + +这是 Knative 的示例配置: + +``` +domain: 'my.wildcard.A.record.dns' +``` + +如果计划使用 GitLab 无服务器功能,请确保在自定义配置上设置 A 记录通配符域. + +**注意:** GitLab 配置组提供了对安装 Knative 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并从[Configure 组中](https://about.gitlab.com/handbook/product/categories/#configure-group) ping 通至少 2 个人. + +#### Knative Metrics[](#knative-metrics "Permalink") + +GitLab 为您的函数提供了[调用指标](../project/clusters/serverless/index.html#invocation-metrics) . 要收集这些指标,您必须具有: + +1. 在群集上安装了 Knative 和 Prometheus 托管的应用程序. +2. 通过运行以下命令在群集上手动应用自定义指标: + + ``` + kubectl apply -f https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/raw/02c8231e30ef5b6725e6ba368bc63863ceb3c07d/src/default-data/knative/istio-metrics.yaml + ``` + +#### Uninstall Knative[](#uninstall-knative "Permalink") + +要卸载 Knative,必须首先通过运行以下命令手动删除已添加的所有自定义指标: + +``` +kubectl delete -f https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/raw/02c8231e30ef5b6725e6ba368bc63863ceb3c07d/src/default-data/knative/istio-metrics.yaml +``` + +### Install AppArmor using GitLab CI/CD[](#install-apparmor-using-gitlab-cicd "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications/-/merge_requests/100) . + +要使用 GitLab CI / CD 将 AppArmor 安装到群集的`gitlab-managed-apps`命名空间中,请在`.gitlab/managed-apps/config.yaml`定义以下配置: + +``` +apparmor: + installed: true +``` + +您可以通过将它们添加到`.gitlab/managed-apps/apparmor/values.yaml`来定义一个或多个 AppArmor 配置文件,如下所示: + +``` +profiles: + profile-one: |- + profile profile-one { + file, + } +``` + +有关此图表的更多信息,请参考[AppArmor](https://gitlab.com/gitlab-org/charts/apparmor)图表. + +#### Using AppArmor profiles in your deployments[](#using-apparmor-profiles-in-your-deployments "Permalink") + +安装 AppAmor 之后,您可以通过添加 Pod 注释来使用配置文件. 如果您使用的是 Auto DevOps,则可以[自定义`auto-deploy-values.yaml`](../../topics/autodevops/customize.html#customize-values-for-helm-chart)来注释您的 Pod. 尽管了解[自定义属性列表](https://gitlab.com/gitlab-org/charts/auto-deploy-app#gitlabs-auto-deploy-helm-chart)会有所帮助,但只需`podAnnotations`如下所示设置`podAnnotations` : + +``` +podAnnotations: + container.apparmor.security.beta.kubernetes.io/auto-deploy-app: localhost/profile-one +``` + +此处唯一要更改的信息是配置文件名称,在本示例中为`profile-one` . 有关如何在 Kubernetes 中集成[AppArmor](https://kubernetes.io/docs/tutorials/clusters/apparmor/#securing-a-pod)的更多信息,请参考[AppArmor 教程](https://kubernetes.io/docs/tutorials/clusters/apparmor/#securing-a-pod) . + +**注意:** GitLab Container Security 组提供了对安装 AppArmor 托管应用程序的支持. 如果您遇到未知问题,请[打开一个新问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/new)并 ping 通至少来自[Container Security 组的](https://about.gitlab.com/handbook/product/product-categories/#container-security-group) 2 个人. + +## Upgrading applications[](#upgrading-applications "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24789) . + +以下应用程序可以升级. + +| Application | GitLab 版本 | +| --- | --- | +| Runner | 11.8+ | + +升级应用程序: + +1. 为一个: + * [在项目级别的集群中](../project/clusters/index.html) ,导航到项目的**Operations> Kubernetes** . + * [组级别集群](../group/clusters/index.html) ,导航到您组的**Kubernetes**页面. +2. 选择您的集群. +3. 如果有升级,将显示" **升级"**按钮. 单击按钮进行升级. + +**注意:**升级会将值重置为`runner`图表中内置的值, [`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/runner/values.yaml)设置的值. + +## Uninstalling applications[](#uninstalling-applications "Permalink") + +在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/60665) . + +可以卸载以下应用程序. + +| Application | GitLab 版本 | Notes | +| --- | --- | --- | +| cert-manager | 12.2+ | 关联的私钥将被删除,并且无法还原. 部署的应用程序将继续使用 HTTPS,但是不会续订证书. 卸载之前,您可能希望[备份配置](https://cert-manager.io/docs/tutorials/backup/)或[吊销证书](https://letsencrypt.org/docs/revoking/) . | +| 亚搏体育 app Runner | 12.2+ | 任何正在运行的管道将被取消. | +| Helm | 12.2+ | 关联的 Tiller 容器, `gitlab-managed-apps`命名空间及其所有资源将被删除,并且无法还原. | +| Ingress | 12.1+ | 关联的负载均衡器和 IP 将被删除,并且无法还原. 此外,仅当未安装 JupyterHub 时才能将其卸载. | +| JupyterHub | 12.1+ | 所有未提交到 GitLab 的数据将被删除,并且无法还原. | +| Knative | 12.1+ | 关联的 IP 将被删除,无法恢复. | +| Prometheus | 11.11+ | 所有数据将被删除,无法还原. | +| Crossplane | 12.5+ | 所有数据将被删除,无法还原. | +| 弹性堆叠 | 12.7+ | 所有数据将被删除,无法还原. | +| Sentry | 12.6+ | PostgreSQL 永久卷将保留,应手动删除以完全卸载. | + +卸载应用程序: + +1. 为一个: + * [在项目级别的集群中](../project/clusters/index.html) ,导航到项目的**Operations> Kubernetes** . + * [组级别集群](../group/clusters/index.html) ,导航到您组的**Kubernetes**页面. +2. 选择您的集群. +3. 单击该应用程序的" **卸载"**按钮. + +支持逐步卸载所有支持的应用程序. 要了解进度,请参阅[相关的史诗](https://gitlab.com/groups/gitlab-org/-/epics/1201) . + +## Troubleshooting applications[](#troubleshooting-applications "Permalink") + +应用程序可能因以下错误而失败: + +``` +Error: remote error: tls: bad certificate +``` + +为避免安装错误: + +* 在开始安装应用程序之前,请确保您的 GitLab 服务器和 Kubernetes 集群之间的时间已同步. +* 确保证书不同步. 在安装应用程序时,GitLab 需要一个没有先前安装的 Helm 的新集群. + + 您可以通过`kubectl`确认证书匹配: + + ``` + kubectl get configmaps/values-content-configuration-ingress -n gitlab-managed-apps -o \ + "jsonpath={.data['cert\.pem']}" | base64 -d > a.pem + kubectl get secrets/tiller-secret -n gitlab-managed-apps -o "jsonpath={.data['ca\.crt']}" | base64 -d > b.pem + diff a.pem b.pem + ``` + +### Error installing managed apps on EKS cluster[](#error-installing-managed-apps-on-eks-cluster "Permalink") + +如果您在 AWS EKS 上使用托管集群,但无法安装某些托管应用程序,请考虑检查日志. + +您可以通过运行以下命令来检查日志: + +``` +kubectl get pods --all-namespaces +kubectl get services --all-namespaces +``` + +如果遇到`Failed to assign an IP address to container`错误,则可能是由于您在 AWS 配置中指定的实例类型. 节点的数量和大小可能没有足够的 IP 地址来运行或安装这些 Pod. + +作为参考,可以[在 GitHub 上的此 AWS 存储库](https://github.com/aws/amazon-vpc-cni-k8s/blob/master/pkg/awsutils/vpc_ip_resource_limit.go)中找到所有 AWS 实例 IP 限制(搜索`InstanceENIsAvailable` ). + +### Unable to install Prometheus[](#unable-to-install-prometheus "Permalink") + +Prometheus 安装失败,出现以下错误: + +``` +# kubectl -n gitlab-managed-apps logs install-prometheus +... +Error: Could not get apiVersions from Kubernetes: unable to retrieve the complete list of server APIs: admission.certmanager.k8s.io/v1beta1: the server is currently unable to handle the request +``` + +这是在 Helm `2.15`中引入并在`3.0.2`修复的错误. 解决方法是,在安装 Prometheus 之前,需要确保已成功安装[`cert-manager`](#cert-manager) . \ No newline at end of file diff --git a/docs/026.md b/docs/026.md new file mode 100644 index 0000000000000000000000000000000000000000..7adc85bef91ade83593af0abc823335be5b3c842 --- /dev/null +++ b/docs/026.md @@ -0,0 +1,264 @@ +# Crossplane configuration + +> 原文:[https://docs.gitlab.com/ee/user/clusters/crossplane.html](https://docs.gitlab.com/ee/user/clusters/crossplane.html) + +* [Configure RBAC permissions](#configure-rbac-permissions) +* [Configure Crossplane with a cloud provider](#configure-crossplane-with-a-cloud-provider) +* [Configure Managed Service Access](#configure-managed-service-access) +* [Setting up Resource classes](#setting-up-resource-classes) +* [Auto DevOps Configuration Options](#auto-devops-configuration-options) +* [Connect to the PostgreSQL instance](#connect-to-the-postgresql-instance) + +# Crossplane configuration[](#crossplane-configuration "Permalink") + +[安装](applications.html#crossplane) Crossplane 后,必须对其进行配置以供使用. 配置 Crossplane 的过程包括: + +1. [Configure RBAC permissions](#configure-rbac-permissions). +2. [Configure Crossplane with a cloud provider](#configure-crossplane-with-a-cloud-provider). +3. [Configure managed service access](#configure-managed-service-access). +4. [Set up Resource classes](#setting-up-resource-classes). +5. Use [Auto DevOps configuration options](#auto-devops-configuration-options). +6. [Connect to the PostgreSQL instance](#connect-to-the-postgresql-instance). + +为了允许 Crossplane 设置诸如 PostgreSQL 之类的云服务,必须使用用户帐户配置云提供商堆栈. 例如: + +* GCP 的服务帐户. +* AWS 的 IAM 用户. + +一些重要的注意事项: + +* 本指南以 GCP 为例,但 AWS 和 Azure 的过程相似. +* Crossplane 要求 Kubernetes 集群是启用了 Alias IP 的 VPC 本机,因此可以在 GCP 网络内路由 Pod 的 IP 地址. + +首先,使用配置声明一些环境变量以供本指南使用: + +``` +export PROJECT_ID=crossplane-playground # the GCP project where all resources reside. +export NETWORK_NAME=default # the GCP network where your GKE is provisioned. +export REGION=us-central1 # the GCP region where the GKE cluster is provisioned. +``` + +## Configure RBAC permissions[](#configure-rbac-permissions "Permalink") + +对于由 GitLab 管理的群集,将自动配置基于角色的访问控制(RBAC). + +对于非 GitLab 管理的群集,请确保提供的令牌的服务帐户可以管理`database.crossplane.io` API 组中的资源: + +1. 将以下 YAML 保存为`crossplane-database-role.yaml` : + + ``` + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + name: crossplane-database-role + labels: + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rules: + - apiGroups: + - database.crossplane.io + resources: + - postgresqlinstances + verbs: + - get + - list + - create + - update + - delete + - patch + - watch + ``` + +2. 将集群角色应用于集群: + + ``` + kubectl apply -f crossplane-database-role.yaml + ``` + +## Configure Crossplane with a cloud provider[](#configure-crossplane-with-a-cloud-provider "Permalink") + +请参阅[配置您的云提供商帐户](https://crossplane.github.io/docs/v0.4/cloud-providers.html)以使用用户帐户配置已安装的云提供商堆栈. + +**注意:必须**将 Secret 和引用该 Secret 的 Provider 资源应用于指南中的`gitlab-managed-apps`命名空间. 请确保在执行该过程时进行更改. + +## Configure Managed Service Access[](#configure-managed-service-access "Permalink") + +接下来,通过以下任一方法配置 PostgreSQL 数据库和 GKE 集群之间的连接: + +* 如下所示使用 Crossplane. +* Directly in the GCP console by [configuring private services access](https://cloud.google.com/vpc/docs/configure-private-services-access). + +1. 运行以下命令,这将创建一个`network.yaml`文件,并配置`GlobalAddress`和连接资源: + + ``` + cat > network.yaml < gcp-postgres-standard.yaml < +Annotations: crossplane.io/propagate-from-name: 108e460e-06c7-11ea-b907-42010a8000bd + crossplane.io/propagate-from-namespace: gitlab-managed-apps + crossplane.io/propagate-from-uid: 10c79605-06c7-11ea-b907-42010a8000bd + +Type: Opaque + +Data +==== +privateIP: 8 bytes +publicIP: 13 bytes +serverCACertificateCert: 1272 bytes +serverCACertificateCertSerialNumber: 1 bytes +serverCACertificateCreateTime: 24 bytes +serverCACertificateExpirationTime: 24 bytes +username: 8 bytes +endpoint: 8 bytes +password: 27 bytes +serverCACertificateCommonName: 98 bytes +serverCACertificateInstance: 41 bytes +serverCACertificateSha1Fingerprint: 40 bytes +``` + +## Connect to the PostgreSQL instance[](#connect-to-the-postgresql-instance "Permalink") + +如果您想连接到 CloudSQL 上新配置的 PostgreSQL 数据库实例,请遵循此[GCP 指南](https://cloud.google.com/sql/docs/postgres/connect-kubernetes-engine) . \ No newline at end of file diff --git a/docs/027.md b/docs/027.md new file mode 100644 index 0000000000000000000000000000000000000000..267cdcd9578a0721596624b7b57e6a1cbe5ca77c --- /dev/null +++ b/docs/027.md @@ -0,0 +1,103 @@ +# Cluster management project (alpha) + +> 原文:[https://docs.gitlab.com/ee/user/clusters/management_project.html](https://docs.gitlab.com/ee/user/clusters/management_project.html) + +* [Permissions](#permissions) +* [Usage](#usage) + * [Selecting a cluster management project](#selecting-a-cluster-management-project) + * [Configuring your pipeline](#configuring-your-pipeline) + * [Setting the environment scope](#setting-the-environment-scope-premium) + +# Cluster management project (alpha)[](#cluster-management-project-alpha "Permalink") + +**警告:**这是*Alpha 版*功能,如有更改,恕不另行通知. + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32810) + +可以将一个项目指定为集群的管理项目. 管理项目可用于以 Kubernetes [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)权限运行部署作业. + +这对以下情况很有用: + +* 创建管道以将群集范围的应用程序安装到群集中,有关详细信息,请参见[使用 GitLab CI / CD(alpha)](applications.html#install-using-gitlab-cicd-alpha)安装. +* 需要`cluster-admin`权限的所有作业. + +## Permissions[](#permissions "Permalink") + +仅管理项目将获得`cluster-admin`权限. 所有其他项目将继续获得[命名空间范围的`edit`级别特权](../project/clusters/add_remove_clusters.html#rbac-cluster-resources) . + +管理项目仅限于以下内容: + +* 对于项目级集群,管理项目必须与集群项目位于相同的名称空间(或子代)中. +* 对于组级集群,管理项目必须与集群的组位于同一组(或子孙)中. +* 对于实例级群集,没有此类限制. + +## Usage[](#usage "Permalink") + +要将群集管理项目用于群集: + +1. 选择项目. +2. 配置管道. +3. 设置环境范围. + +### Selecting a cluster management project[](#selecting-a-cluster-management-project "Permalink") + +选择要使用的集群管理项目: + +1. 导航到适当的配置页面. 为一个: + * [项目级集群](../project/clusters/index.html) ,导航到项目的**Operations> Kubernetes**页面. + * [组级别集群](../group/clusters/index.html) ,导航到您组的**Kubernetes**页面. + * [实例级集群](../instance/clusters/index.html) ,导航到管理区域的**Kubernetes**页面. +2. 在" **高级设置"**部分中的"使用**集群管理项目"字段**中选择项目. + +[![Selecting a cluster management project under Advanced settings](img/838245c530d1afaf54929d9edd3f6a24.png)](img/advanced-settings-cluster-management-project-v12_5.png) + +### Configuring your pipeline[](#configuring-your-pipeline "Permalink") + +将项目指定为集群的管理项目后,在该项目中编写[`.gitlab-ci.yml`](../../ci/yaml/README.html) . 例如: + +``` +configure cluster: + stage: deploy + script: kubectl get namespaces + environment: + name: production +``` + +### Setting the environment scope[](#setting-the-environment-scope-premium "Permalink") + +将多个群集与同一管理项目关联时,可以使用[环境范围](../project/clusters/index.html#setting-the-environment-scope-premium) . + +每个作用域只能由单个群集用于管理项目. + +例如,假设以下 Kubernetes 集群与管理项目相关联: + +| Cluster | 环境范围 | +| --- | --- | +| Development | `*` | +| Staging | `staging` | +| Production | `production` | + +[`.gitlab-ci.yml`](../../ci/yaml/README.html)设置的以下环境将分别部署到 Development,Staging 和 Production 集群. + +``` +stages: + - deploy + +configure development cluster: + stage: deploy + script: kubectl get namespaces + environment: + name: development + +configure staging cluster: + stage: deploy + script: kubectl get namespaces + environment: + name: staging + +configure production cluster: + stage: deploy + script: kubectl get namespaces + environment: + name: production +``` \ No newline at end of file diff --git a/docs/028.md b/docs/028.md new file mode 100644 index 0000000000000000000000000000000000000000..72b89b4e4b654a3acd84f965ee24cc57fbcf96d3 --- /dev/null +++ b/docs/028.md @@ -0,0 +1,100 @@ +# Kubernetes Logs + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/kubernetes_pod_logs.html](https://docs.gitlab.com/ee/user/project/clusters/kubernetes_pod_logs.html) + +* [Overview](#overview) +* [Requirements](#requirements) +* [Usage](#usage) + * [From the project sidebar](#from-the-project-sidebar) + * [From Deploy Boards](#from-deploy-boards) + * [Logs view](#logs-view) + * [Filter by date](#filter-by-date) + * [Full text search](#full-text-search) + +# Kubernetes Logs[](#kubernetes-logs "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4752) . +* [移至](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26383) [GitLab Core](https://about.gitlab.com/pricing/) 12.9\. + +使用 GitLab 可以轻松查看[连接的 Kubernetes 集群](index.html)中正在运行的 Pod 的日志. 通过直接在**Log Explorer 的** GitLab 中显示**日志** ,开发人员可以避免管理控制台工具或跳转到其他界面. + +**注意:** [了解有关 Kubernetes + GitLab 的更多信息](https://about.gitlab.com/solutions/kubernetes/) . 大规模构建,测试,部署和运行应用程序所需的一切. + +## Overview[](#overview "Permalink") + +[Kubernetes](https://kubernetes.io)日志可以使用**Log Explorer**在 GitLab 中直接查看. + +[![Pod logs](img/0370f6d6a289b9e8237fcad4c7672e78.png)](img/kubernetes_pod_logs_v12_10.png) + +要了解更多信息,请参阅[APM-Log Explorer](https://www.youtube.com/watch?v=hWclZHA7Dgw) . + +## Requirements[](#requirements "Permalink") + +要使用日志,需要[部署到 Kubernetes 环境](../deploy_boards.html#enabling-deploy-boards) . + +## Usage[](#usage "Permalink") + +要访问日志,您必须具有正确的[权限](../../permissions.html#project-members-permissions) . + +您可以通过两种方式访问​​它们. + +### From the project sidebar[](#from-the-project-sidebar "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22011) . + +去 侧栏菜单上的" **操作">"舱位日志** "以显示" **日志资源管理器"** . + +[![Sidebar menu](img/0050abd936ad2e13e4ad057a58611cc9.png)](img/sidebar_menu_pod_logs_v12_10.png) + +### From Deploy Boards[](#from-deploy-boards "Permalink") + +可以通过单击[Deploy Boards 中](../deploy_boards.html)的特定窗格来显示日志: + +1. 去 **操作>环境,**然后找到包含所需 pod 的环境,例如`production` . +2. 在" **环境"**页面上,您应该通过[Deploy Boards](../deploy_boards.html)看到环境容器的状态. +3. 将鼠标悬停在窗格列表上时,将显示一个工具提示,其中包含确切的窗格名称和状态. [![部署板窗格列表](img/81c888ba61ab652f9505d5b51406ed22.png)](img/pod_logs_deploy_board.png) +4. 单击所需的窗格以显示**Log Explorer** . + +### Logs view[](#logs-view "Permalink") + +**日志浏览**器使您可以通过以下方式过滤日志: + +* Pods. +* [从 GitLab 12.4 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/5769) ,环境. +* [From GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21656), [full text search](#full-text-search). +* [从 GitLab 12.8 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/197879) ,日期. + +从[GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/198050)起可以加载 500 条以上的日志行. + +[在将来的版本中将](https://gitlab.com/gitlab-org/gitlab/-/issues/13404)支持具有多个容器的 Pod. + +[在将来的版本中将](https://gitlab.com/gitlab-org/gitlab/-/issues/196191)支持历史数据. + +### Filter by date[](#filter-by-date "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/197879) . + +在集群上启用[Elastic Stack](../../clusters/applications.html#elastic-stack)时,您可以按日期过滤" **日志浏览**器"中显示的**日志** . + +单击" **日志资源管理器"**中的" **显示最后一个** "以查看可用选项. + +### Full text search[](#full-text-search "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21656) . + +在集群上启用[Elastic Stack](../../clusters/applications.html#elastic-stack)时,可以通过搜索栏搜索日志的内容. + +搜索通过使用[simple_query_string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html) Elasticsearch 函数传递给 Elasticsearch,该函数支持以下运算符: + +| Operator | Description | +| --- | --- | +| `\|` | 或运算. | +| `-` | 取反单个令牌. | +| `+` | AND 运算. | +| `"` | 包装许多标记以表示要搜索的短语. | +| `*` (每学期末) | 前缀查询. | +| `(` and `)` | Precedence. | +| `~N` (一个字之后) | 编辑距离(模糊性). | +| `~N` (在短语之后) | 斜率. | \ No newline at end of file diff --git a/docs/029.md b/docs/029.md new file mode 100644 index 0000000000000000000000000000000000000000..695ccf7100dfe06c457b0f23654abdd5166b0968 --- /dev/null +++ b/docs/029.md @@ -0,0 +1,104 @@ +# Runbooks + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/runbooks/](https://docs.gitlab.com/ee/user/project/clusters/runbooks/) + +* [Executable Runbooks](#executable-runbooks) +* [Requirements](#requirements) +* [Nurtch](#nurtch) +* [Configure an executable runbook with GitLab](#configure-an-executable-runbook-with-gitlab) + +# Runbooks[](#runbooks "Permalink") + +Runbooks 是记录在案的过程的集合,这些过程解释了如何执行特定过程,包括启动,停止,调试特定系统或对特定系统进行故障排除. + +使用[Jupyter Notebook](https://jupyter.org/)和[Rubix 库](https://github.com/Nurtch/rubix) ,用户可以开始编写自己的可执行运行手册. + +从历史上看,运行手册根据情况或系统采用决策树或详细的分步指南的形式. + +现代的实现方式引入了"可执行的运行手册"的概念,其中,操作员可以结合定义良好的流程在给定的环境中执行预写的代码块或数据库查询. + +## Executable Runbooks[](#executable-runbooks "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45912) . + +通过 GitLab 的 Kubernetes 集成提供的 JupyterHub 应用程序现在随 Nurtch 的 Rubix 库一起提供,提供了一种创建 DevOps Runbook 的简单方法. 提供了一个样本运行手册,其中展示了常见的操作. 虽然 Rubix 使创建常见的 Kubernetes 和 AWS 工作流变得简单,但是您也可以不使用 Rubix 手动创建它们. + +观看此[视频](https://www.youtube.com/watch?v=Q_OqHIIUPjE) ,了解如何在 GitLab 中完成此操作! + +## Requirements[](#requirements "Permalink") + +要创建可执行的运行本,您将需要: + +* **Kubernetes-**需要 Kubernetes 集群才能部署其余应用程序. 最简单的入门方法是使用[GitLab 的集成](../add_remove_clusters.html#create-new-cluster)之一添加集群. +* **入口** -入口可以提供负载平衡,SSL 终止和基于名称的虚拟主机. 它充当您的应用程序的 Web 代理. +* **JupyterHub** - [JupyterHub](https://jupyterhub.readthedocs.io/)是用于在团队中管理笔记本的多用户服务. Jupyter Notebook 提供了一个基于 Web 的交互式编程环境,用于数据分析,可视化和机器学习. + +## Nurtch[](#nurtch "Permalink") + +Nurtch 是[Rubix 库](https://github.com/Nurtch/rubix)背后的公司. Rubix 是一个开源 Python 库,可轻松在 Jupyter Notebooks 中执行常见的 DevOps 任务. 绘制 Cloudwatch 指标和滚动 ECS / Kubernetes 应用之类的任务将简化为几行代码. 有关更多信息,请参见[Nurtch 文档](http://docs.nurtch.com/en/latest/) . + +## Configure an executable runbook with GitLab[](#configure-an-executable-runbook-with-gitlab "Permalink") + +遵循此分步指南,使用上述组件和预加载的演示运行本在 GitLab 中配置可执行运行本. + +1. 遵循[创建新集群中](../add_remove_clusters.html#create-new-cluster)概述的步骤,将 Kubernetes 集群添加到您的项目中. + +2. 单击**Ingress**应用程序旁边的" **安装"**按钮以安装 Ingress. + + [![install ingress](img/5a2430ba8091036f8e9e3308aa845de8.png)](img/ingress-install.png) + +3. 成功安装 Ingress 后,单击**JupyterHub**应用程序旁边的" **安装"**按钮. **下一步,**您将需要此处提供的**Jupyter 主机名** . + + [![install JupyterHub](img/00fd9bca0c7bdc64f74a24b691e0adac.png)](img/jupyterhub-install.png) + +4. 成功安装**JupyterHub 后** ,在浏览器中打开**Jupyter 主机名** . 单击" **使用 GitLab 登录"**按钮登录到 JupyterHub 并启动服务器. 使用 OAuth2 为 GitLab 实例的任何用户启用身份验证. 此按钮将您重定向到 GitLab 上的页面,请求 JupyterHub 授权使用您的 GitLab 帐户. + + [![authorize Jupyter](img/9950340e3b641e3f63d70fb29b2b05bb.png)](img/authorize-jupyter.png) + +5. 单击**Authorize** ,您将被重定向到 JupyterHub 应用程序. +6. 单击" **启动我的服务器"** ,服务器将在几秒钟后启动. +7. 要配置 Runbook 对 GitLab 项目的访问,必须在演示 Runbook 的" **设置"**部分中输入您的[GitLab 访问令牌](../../../profile/personal_access_tokens.html)和项目 ID: + + 1. 双击左侧面板上的**DevOps-Runbook-Demo**文件夹. + + [![demo runbook](img/6809ef73be513357f41ebe6d325265d5.png)](img/demo-runbook.png) + + 2. 双击`Nurtch-DevOps-Demo.ipynb` . + + [![sample runbook](img/ae5a500e2333874603b33328b017eb35.png)](img/sample-runbook.png) + + Jupyter 在屏幕右侧显示 Runbook 的内容. **设置**部分显示您的`PRIVATE_TOKEN`和您的`PROJECT_ID` . 输入这些值,并保持单引号如下: + + ``` + PRIVATE_TOKEN = 'n671WNGecHugsdEDPsyo' + PROJECT_ID = '1234567' + ``` + + 3. Update the `VARIABLE_NAME` on the last line of this section to match the name of the variable you’re using for your access token. In this example, our variable name is `PRIVATE_TOKEN`. + + ``` + VARIABLE_VALUE = project.variables.get('PRIVATE_TOKEN').value + ``` + +8. 要配置运行手册的操作,请创建和配置变量: + + **注意:**对于此示例,我们使用示例**运行簿**中的**笔记本中**的**"运行 SQL 查询"**部分来查询 PostgreSQL 数据库. 以下代码块的前四行定义了此查询运行所需的变量: + + ``` + %env DB_USER={project.variables.get('DB_USER').value} + %env DB_PASSWORD={project.variables.get('DB_PASSWORD').value} + %env DB_ENDPOINT={project.variables.get('DB_ENDPOINT').value} + %env DB_NAME={project.variables.get('DB_NAME').value} + ``` + + 1. 导航 **设置»CI / CD»变量**以在项目中创建变量. + + [![GitLab variables](img/15b455cffa86c3a9234ad8c30082a4df.png)](img/gitlab-variables.png) + + 2. Click **保存变量**. + + 3. 在 Jupyter 中,单击**"笔记本"**标题中的**"运行 SQL 查询"** ,然后单击**"运行"** . 结果以内联方式显示如下: + + [![PostgreSQL query](img/1a1b871d7e874d4f8e2ab4905d000509.png)](img/postgres-query.png) + +您可以尝试其他操作,例如运行 Shell 脚本或与 Kubernetes 集群进行交互. 有关更多信息,请访问[Nurtch 文档](http://docs.nurtch.com/) . \ No newline at end of file diff --git a/docs/030.md b/docs/030.md new file mode 100644 index 0000000000000000000000000000000000000000..84e2f128a8540c042191d922cfa21706a323ea2b --- /dev/null +++ b/docs/030.md @@ -0,0 +1,734 @@ +# Serverless + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/serverless/](https://docs.gitlab.com/ee/user/project/clusters/serverless/) + +* [Overview](#overview) +* [Knative](#knative) +* [Prerequisites](#prerequisites) +* [Installing Knative via GitLab’s Kubernetes integration](#installing-knative-via-gitlabs-kubernetes-integration) +* [Using an existing installation of Knative](#using-an-existing-installation-of-knative) +* [Supported runtimes](#supported-runtimes) + * [GitLab-managed runtimes](#gitlab-managed-runtimes) + * [OpenFaaS runtimes](#openfaas-runtimes) +* [Deploying functions](#deploying-functions) + * [`service`](#service) + * [`provider`](#provider) + * [`functions`](#functions) + * [Deployment](#deployment) + * [Runtime aliases](#runtime-aliases) + * [Secrets](#secrets) + * [CLI example](#cli-example) + * [Part of deployment job](#part-of-deployment-job) + * [Running functions locally](#running-functions-locally) +* [Deploying Serverless applications](#deploying-serverless-applications) + * [Deploy the application with Knative](#deploy-the-application-with-knative) + * [Function details](#function-details) + * [Invocation metrics](#invocation-metrics) +* [Configuring logging](#configuring-logging) + * [Prerequisites](#prerequisites-1) + * [Enable request log template](#enable-request-log-template) + * [Enable request logs](#enable-request-logs) + * [Viewing request logs](#viewing-request-logs) +* [Enabling TLS for Knative services](#enabling-tls-for-knative-services) +* [Using an older version of `gitlabktl`](#using-an-older-version-of-gitlabktl) + +# Serverless[](#serverless "Permalink") + +在 GitLab 11.5 中引入. + +**警告:** Serverless 目前处于[alpha 状态](https://about.gitlab.com/handbook/product/#alpha) . + +## Overview[](#overview "Permalink") + +无服务器架构为运营商和开发人员提供了在不配置单个服务器的情况下编写高度可扩展的应用程序的能力. + +GitLab 支持在 Kubernetes 环境和主要的云 FAAS 环境中部署无服务器应用程序的几种方法. + +目前,我们支持: + +* [Knative](#knative) :在 GKE 和 EKS 上使用 Knative 和`gitlabktl`构建 Knative 应用程序. +* [AWS Lambda](aws.html) :通过无服务器框架和 GitLab CI / CD 创建无服务器应用程序. + +## Knative[](#knative "Permalink") + +使用[Knative](https://cloud.google.com/knative/)在 Kubernetes 上运行无服务器工作负载. + +Knative 扩展了 Kubernetes 以提供一组中间件组件,这些组件对于构建现代的,以源为中心的,基于容器的应用程序很有用. Knative 通过其主要组件带来了一些明显的好处: + +* [服务](https://github.com/knative/serving) :请求驱动的计算,可扩展为零. +* [事件](https://github.com/knative/eventing) : [事件的](https://github.com/knative/eventing)管理和交付. + +有关 Knative 的更多信息,请访问[Knative docs 资源库](https://github.com/knative/docs) . + +借助 GitLab Serverless,您可以部署功能即服务(FaaS)和无服务器应用程序. + +## Prerequisites[](#prerequisites "Permalink") + +要在 GitLab 上运行 Knative,您需要: + +1. **现有的 GitLab 项目:**您将需要一个 GitLab 项目来关联所有资源. 最简单的入门方法: + * 如果您打算[部署功能](#deploying-functions) ,请克隆[功能示例项目](https://gitlab.com/knative-examples/functions)以开始使用. + * 如果您打算[部署无服务器应用程序](#deploying-serverless-applications) ,请克隆示例[Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app)以开始使用. +2. **Kubernetes 集群:**部署 Knative 需要启用 RBAC 的 Kubernetes 集群. 最简单的入门方法是使用 GitLab 的[GKE 集成](../add_remove_clusters.html)添加集群. 建议的运行 Knative 的最低建议群集规格为 3 个节点,6 个 vCPU 和 22.50 GB 内存. +3. **GitLab 运行程序:**运行 CI 作业需要运行程序,该作业会将无服务器的应用程序或功能部署到您的集群上. 您可以将 GitLab Runner 安装到现有的 Kubernetes 集群上. 有关更多信息,请参见[安装应用程序](../index.html#installing-applications) . +4. **域名:** Knative 将使用 Istio 提供自己的负载平衡器. 它将为 Knative 服务的所有应用程序提供一个外部 IP 地址或主机名. 系统将提示您输入一个通配符域,将在其中提供您的应用程序. 配置您的 DNS 服务器以使用该域的外部 IP 地址或主机名. +5. **`.gitlab-ci.yml` :** GitLab 使用[Kaniko](https://github.com/GoogleContainerTools/kaniko)来构建应用程序. 我们还使用[GitLab Knative 工具](https://gitlab.com/gitlab-org/gitlabktl) CLI 来简化向 Knative 部署服务和功能. +6. **`serverless.yml`** ( [仅](#deploying-functions)适用于[功能](#deploying-functions) ):使用 lessserver 部署功能时, `serverless.yml`文件将包含存储库中托管的所有功能的信息以及所使用的运行时的引用. +7. **`Dockerfile`** ( [仅](#deploying-serverless-applications)适用于[应用程序](#deploying-serverless-applications) ):Knative 需要`Dockerfile`才能构建您的应用程序. 它应该包含在项目存储库的根目录中,并公开端口`8080` . 如果您打算使用我们的[运行时](https://gitlab.com/gitlab-org/serverless/runtimes)来构建无服务器功能,则不需要`Dockerfile` . +8. **Prometheus** (可选):安装 Prometheus 可使您监视无服务器功能/应用程序的规模和流量. 有关更多信息,请参见[安装应用程序](../index.html#installing-applications) . +9. **日志记录** (可选):配置日志记录可让您查看和搜索无服务器功能/应用程序的请求日志. 有关更多信息,请参见[配置日志记录](#configuring-logging) . + +## Installing Knative via GitLab’s Kubernetes integration[](#installing-knative-via-gitlabs-kubernetes-integration "Permalink") + +**注意:**运行 Knative 的最小建议群集大小是 3 节点,6 vCPU 和 22.50 GB 内存. **必须启用 RBAC.** + +1. [Add a Kubernetes cluster](../add_remove_clusters.html). +2. 选择" **应用程序"**选项卡,然后向下滚动到" Knative 应用程序"部分. 输入要用于您的应用程序/功能的域(例如`example.com` ),然后单击**Install** . + + [![install-knative](img/a93d26d68bbc1f4954a7038e601ba3b6.png)](img/install-knative.png) + +3. Knative 安装完成后,您可以等待 IP 地址或主机名显示在**Knative Endpoint**字段中,或[手动检索 Istio Ingress 端点](../../../clusters/applications.html#determining-the-external-endpoint-manually) . + + **注意:**在集群上运行`kubectl`命令需要首先设置对集群的访问. 对于在 GKE 上创建的集群,请参见[GKE 集群访问](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl) ,对于其他平台,请[安装 kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) . +4. 入口现在在此地址可用,并将基于请求中的 DNS 名称将传入请求路由到适当的服务. 为此,应为所需的域名创建通配符 DNS 记录. 例如,如果您的 Knative 基础域是`knative.info`则需要创建一个 A 记录或 CNAME 记录,其域`*.knative.info`指向 Ingress 的 IP 地址或主机名. + + [![DNS entry](img/e7acd74bc1dc7f0103e1b107aac74f84.png)](img/dns-entry.png) + +**注意:**可以在给定项目上部署[功能](#deploying-functions)或[无服务器应用程序](#deploying-serverless-applications) ,但不能两者都部署. 当前实现利用了的`serverless.yml`文件发信号 FAAS 项目. + +## Using an existing installation of Knative[](#using-an-existing-installation-of-knative "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/58941) in GitLab 12.0. + +**注意:**添加现有的 Knative 安装时,GitLabless server 的"调用"监视功能将不起作用. + +也可以将 GitLab Serverless 与已经安装 Knative 的现有 Kubernetes 集群一起使用. + +您必须执行以下操作: + +1. 按照步骤[添加现有的 Kubernetes 集群](../add_remove_clusters.html#add-existing-cluster) . + +2. 确保 GitLab 可以管理 Knative: + * 对于非 GitLab 托管群集,请确保提供的令牌的服务帐户可以管理`serving.knative.dev` API 组中的资源. + * 对于 GitLab 托管群集,如果您在[GitLab 12.1 或更高版本中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30235)添加了群集,则 GitLab 将已经具有所需的访问权限,您可以继续进行下一步. + + 否则,您需要手动授权 GitLab 的服务帐户具有管理`serving.knative.dev` API 组中资源的能力. 由于每个 GitLab 服务帐户都具有`edit`集群角色,因此最简单的方法是通过将默认规则添加到默认`edit`集群角色的[聚合 ClusterRole](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles) :首先,将以下 YAML 保存为`knative-serving-only-role.yaml` : + + ``` + apiVersion : rbac.authorization.k8s.io/v1 kind : ClusterRole metadata : name : knative-serving-only-role labels : rbac.authorization.k8s.io/aggregate-to-edit : " true" rules : - apiGroups : - serving.knative.dev resources : - configurations - configurationgenerations - routes - revisions - revisionuids - autoscalers - services verbs : - get - list - create - update - delete - patch - watch + ``` + + 然后运行以下命令: + + ``` + kubectl apply -f knative-serving-only-role.yaml + ``` + + 如果您希望基于每个服务帐户授予权限,则可以使用特定于服务帐户和名称空间的`Role`和`RoleBinding`来执行此操作. + +3. 请按照以下步骤将[功能](#deploying-functions)或[无服务器应用程序](#deploying-serverless-applications)部署到群集上. + +## Supported runtimes[](#supported-runtimes "Permalink") + +GitLab 的无服务器功能可以使用以下命令运行: + +* [GitLab-managed](#gitlab-managed-runtimes) runtimes. +* [OpenFaaS](#openfaas-runtimes) runtimes. + +如果所需的编程语言无法使用运行时,请考虑部署[无服务器应用程序](#deploying-serverless-applications) . + +### GitLab-managed runtimes[](#gitlab-managed-runtimes "Permalink") + +当前,以下 GitLab 管理的[运行时](https://gitlab.com/gitlab-org/serverless/runtimes)可用: + +* `go` (概念证明) +* `nodejs` +* `ruby` + +如果未指定运行时,则必须提供一个`Dockerfile`来运行无服务器功能. + +### OpenFaaS runtimes[](#openfaas-runtimes "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/29253) . + +[OpenFaaS 经典运行时](https://github.com/openfaas/templates#templates-in-store)可与 GitLab 无服务器一起使用. + +OpenFaas 运行时可用于以下语言: + +* C# +* Go +* NodeJS +* PHP +* Python +* Ruby + +使用以下模式指定运行时: `openfaas/classic/` . 下面的示例示出了如何定义一个函数`serverless.yml`使用 OpenFaaS 运行时: + +``` +hello: + source: ./hello + runtime: openfaas/classic/ruby + description: "Ruby function using OpenFaaS classic runtime" +``` + +`handler` is not needed for OpenFaaS functions. The location of the handler is defined by the conventions of the runtime. + +有关使用 OpenFaaS 运行时的函数示例,请参见[`ruby-openfaas-function`](https://gitlab.com/knative-examples/ruby-openfaas-function)项目. + +## Deploying functions[](#deploying-functions "Permalink") + +在 GitLab 11.6 中引入. + +您可以在**[功能示例项目中](https://gitlab.com/knative-examples/functions)**找到并导入此文档中引用的所有文件. + +请按照以下步骤将使用 Node.js 运行时的功能部署到您的 Knative 实例(如果您已克隆示例项目,则可以跳过以下步骤): + +1. 创建一个目录来容纳该函数. 在此示例中,我们将在项目的根目录创建一个名为`echo`的目录. + +2. 创建将包含功能代码的文件. 在此示例中,我们的文件名为`echo.js` ,位于`echo`目录中. 如果您的项目是: + * 公开,继续下一步. + * 私有的,您将需要使用`gitlab-deploy-token`作为名称和`read_registry`范围[创建一个 GitLab 部署令牌](../../deploy_tokens/index.html#creating-a-deploy-token) . +3. `.gitlab-ci.yml` :这定义了用于部署功能的管道. 它必须包含在存储库的根目录中: + + ``` + include: + - template: Serverless.gitlab-ci.yml + + functions:build: + extends: .serverless:build:functions + environment: production + + functions:deploy: + extends: .serverless:deploy:functions + environment: production + ``` + + 这个`.gitlab-ci.yml`创建的作业会调用一些预定义的命令来构建功能并将其部署到集群中. + + `Serverless.gitlab-ci.yml` is a template that allows customization. You can either import it with `include` parameter and use `extends` to customize your jobs, or you can inline the entire template by choosing it from **套用范本** dropdown when editing the `.gitlab-ci.yml` file through the user interface. + +4. `serverless.yml` :此文件包含您的功能的元数据,例如名称,运行时和环境. + + 它必须包含在存储库的根目录中. 下面是一个示例`echo`函数,它显示了文件所需的结构. + + 您可以在[功能示例项目中](https://gitlab.com/knative-examples/functions)找到该项目的相关文件. + + ``` + service: functions + description: "GitLab Serverless functions using Knative" + + provider: + name: triggermesh + envs: + FOO: value + secrets: + - my-secrets + + functions: + echo-js: + handler: echo-js + source: ./echo-js + runtime: gitlab/runtimes/nodejs + description: "node.js runtime function" + envs: + MY_FUNCTION: echo-js + secrets: + - my-secrets + ``` + +上面使用的字段的说明: + +### `service`[](#service "Permalink") + +| Parameter | Description | +| --- | --- | +| `service` | 服务该功能的 Knative 服务的名称. | +| `description` | 在的简短描述`service` . | + +### `provider`[](#provider "Permalink") + +| Parameter | Description | +| --- | --- | +| `name` | 指示使用哪个提供程序来执行`serverless.yml`文件. 在这种情况下,使用 TriggerMesh 中间件. | +| `envs` | 包括要在文件中**所有**函数的函数执行过程中传递的环境变量,其中`FOO`是变量名, `BAR`是变量内容. 您可以将其替换为自己的变量. | +| `secrets` | 包含 Kubernetes 机密的内容作为环境变量,可访问该变量作为文件中**所有**函数的函数执行的一部分进行传递. 机密应采用 INI 格式. | + +### `functions`[](#functions "Permalink") + +在上面的`serverless.yml`示例中,函数名称为`echo` ,随后的行包含函数属性. + +| Parameter | Description | +| --- | --- | +| `handler` | 函数的名称. | +| `source` | 具有功能源的目录. | +| `runtime` (optional) | 用于执行功能的运行时. 这可以是运行时别名(请参阅[运行时别名](#runtime-aliases) ),也可以是自定义运行时存储库的完整 URL. 当未指定运行`Dockerfile` ,我们假定`Dockerfile`存在于`source`指定的函数目录中. | +| `description` | 功能的简短描述. | +| `envs` | 仅为特定功能设置环境变量. | +| `secrets` | 将 Kubernetes 机密的内容作为环境变量包含在内,这些变量只能作为特定函数的函数执行的一部分进行传递. 机密应采用 INI 格式. | + +### Deployment[](#deployment "Permalink") + +#### Runtime aliases[](#runtime-aliases "Permalink") + +可选的`runtime`参数可以引用以下运行时别名之一(另请参阅[受支持的运行时](#supported-runtimes) ): + +| 运行时别名 | 维护者 | +| --- | --- | +| `gitlab/runtimes/go` | GitLab | +| `gitlab/runtimes/nodejs` | GitLab | +| `gitlab/runtimes/ruby` | GitLab | +| `openfaas/classic/csharp` | OpenFaaS | +| `openfaas/classic/go` | OpenFaaS | +| `openfaas/classic/node` | OpenFaaS | +| `openfaas/classic/php7` | OpenFaaS | +| `openfaas/classic/python` | OpenFaaS | +| `openfaas/classic/python3` | OpenFaaS | +| `openfaas/classic/ruby` | OpenFaaS | + +经过`gitlab-ci.yml`模板已添加和`serverless.yml`文件被创建,推动提交到您的项目将导致 CI 管道被执行,而部署的每个功能的 Knative 服务. 部署阶段完成后,该功能的其他详细信息将显示在" **操作">"无服务器"下** . + +[![serverless page](img/e8c78799e0967a32ee1efeaea30f6213.png)](img/serverless-page.png) + +该页面包含可用于项目的所有功能,访问功能的描述以及(如果有)功能的运行时信息. 详细信息来自于项目的每个 Kubernetes 集群中的 Knative 安装. 单击每个功能以获得详细的规模和调用数据. + +可以从集群上的 Knative 直接检索函数详细信息: + +``` +kubectl -n "$KUBE_NAMESPACE" get services.serving.knative.dev +``` + +现在可以使用任何简单的`POST`调用从任何 HTTP 客户端触发示例函数: + +1. 使用 curl(将最后一行的 URL 替换为应用程序的 URL): + + ``` + curl \ + --header "Content-Type: application/json" \ + --request POST \ + --data '{"GitLab":"FaaS"}' \ + http://functions-echo.functions-1.functions.example.com/ + ``` + +2. 使用基于 Web 的工具(例如 Postman 或 Restlet) + + [![function execution](img/676537e7ead1101c5c0668a2adbc08d5.png)](img/function-execution.png) + +### Secrets[](#secrets "Permalink") + +要从函数内部访问 Kubernetes 机密,应在无服务器部署的名称空间下创建该机密,并在上述`serverless.yml`文件中指定这些机密. 您可以通过多种方式创建机密. 以下各节显示了一些示例. + +#### CLI example[](#cli-example "Permalink") + +``` +kubectl create secret generic my-secrets -n "$KUBE_NAMESPACE" --from-literal MY_SECRET=imverysecure +``` + +#### Part of deployment job[](#part-of-deployment-job "Permalink") + +您可以扩展`.gitlab-ci.yml`以在部署期间使用安全存储在 GitLab 项目下的[环境变量](../../../../ci/variables/README.html)来创建秘密. + +``` +deploy:function: + stage: deploy + environment: production + extends: .serverless:deploy:functions + before_script: + - kubectl create secret generic my-secret + --from-literal MY_SECRET="$GITLAB_SECRET_VARIABLE" + --namespace "$KUBE_NAMESPACE" + --dry-run -o yaml | kubectl apply -f - +``` + +### Running functions locally[](#running-functions-locally "Permalink") + +在本地运行功能是在开发过程中快速验证行为的好方法. + +在本地运行功能需要: + +* 转到 1.12 或更高版本. +* Docker Engine 已安装并正在运行. +* 使用 Go 软件包管理器安装的`gitlabktl` : + + ``` + GO111MODULE=on go get gitlab.com/gitlab-org/gitlabktl + ``` + +要在本地运行功能: + +1. 导航到您的 GitLab 无服务器项目的根目录. +2. 将功能构建到 Docker 映像中: + + ``` + gitlabktl serverless build + ``` + +3. 在 Docker 中运行您的函数: + + ``` + docker run -itp 8080:8080 + ``` + +4. 调用您的功能: + + ``` + curl http://localhost:8080 + ``` + +## Deploying Serverless applications[](#deploying-serverless-applications "Permalink") + +在 GitLab 11.5 中引入. + +无服务器应用程序是[无服务器功能](#deploying-functions)的替代[方法](#deploying-functions) . 它们在现有运行时不能满足应用程序需求的情况下很有用,例如以一种没有可用运行时的语言编写的应用程序. 请注意,尽管无服务器应用程序应该是无状态的! + +**注意:**您可以参考并导入示例[Knative Ruby 应用程序](https://gitlab.com/knative-examples/knative-ruby-app)以开始使用. + +将以下`.gitlab-ci.yml`添加到存储库的根目录中(如果您先前已经克隆了上述示例[Knative Ruby App,](https://gitlab.com/knative-examples/knative-ruby-app)则可以跳过此步骤): + +``` +include: + - template: Serverless.gitlab-ci.yml + +build: + extends: .serverless:build:image + +deploy: + extends: .serverless:deploy:image +``` + +`Serverless.gitlab-ci.yml`是允许自定义的模板. 您可以使用`include`参数导入它,并使用`extends`来自定义作业,或者可以通过在通过用户界面编辑`.gitlab-ci.yml`文件时从**Apply a template**下拉列表中选择它来内联整个模板. + +部署无服务器应用程序时,不需要`serverless.yml`文件. + +### Deploy the application with Knative[](#deploy-the-application-with-knative "Permalink") + +一切就绪后,下次运行 CI 管道时,将部署 Knative 应用程序. 导航到**CI / CD>管道** ,然后单击最新的管道. + +### Function details[](#function-details "Permalink") + +转到**操作>无服务器**页面以查看功能的最终 URL. + +[![function_details](img/4e0797b4100df465293bf0c8f24a097b.png)](img/function-list_v12_7.png) + +### Invocation metrics[](#invocation-metrics "Permalink") + +On the same page as above, click on one of the function rows to bring up the function details page. + +[![function_details](img/a0ea9fb503066a9bed377bc4dadb0d59.png)](img/function-details-loaded.png) + +容器数将为您提供在给定集群上运行无服务器功能实例的容器数. + +为了显示 Knative 函数调用, [必须安装 Prometheus](../index.html#installing-applications) . + +一旦安装了 Prometheus,可能会出现一条消息,指示度量标准数据*正在加载或当前不可用.* 它会在首次访问该页面时显示,但应在几秒钟后消失. 如果该消息没有消失,则可能是 GitLab 无法连接到集群上运行的 Prometheus 实例. + +## Configuring logging[](#configuring-logging "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33330) . + +### Prerequisites[](#prerequisites-1 "Permalink") + +* 由 GitLab 管理的集群. +* `kubectl`已安装并正在运行. + +在集群上运行`kubectl`命令需要首先设置对集群的访问权限. 对于在以下位置创建的集群: + +* GKE,请参阅[GKE 群集访问](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl) +* 其他平台,请参阅[安装和设置 kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) . + +### Enable request log template[](#enable-request-log-template "Permalink") + +运行以下命令以启用请求日志: + +``` +kubectl edit cm -n knative-serving config-observability +``` + +将`logging.request-log-template`从`data._example`字段复制到层次结构中上一层的数据字段. + +### Enable request logs[](#enable-request-logs "Permalink") + +运行以下命令以将 Elasticsearch,Kibana 和 Filebeat 安装到`kube-logging`命名空间中,并配置所有节点以使用 Filebeat 转发日志: + +``` +kubectl apply -f https://gitlab.com/gitlab-org/serverless/configurations/knative/raw/v0.7.0/kube-logging-filebeat.yaml +kubectl label nodes --all beta.kubernetes.io/filebeat-ready="true" +``` + +### Viewing request logs[](#viewing-request-logs "Permalink") + +要查看请求日志: + +1. Run `kubectl proxy`. +2. 导航到[Kibana UI](http://localhost:8001/api/v1/namespaces/kube-logging/services/kibana/proxy/app/kibana) . + +Or: + +1. 打开[Kibana UI](http://localhost:8001/api/v1/namespaces/kube-logging/services/kibana/proxy/app/kibana) . +2. 单击" **发现"** ,然后从左侧的下拉列表中选择`filebeat-*` . +3. 在搜索框中输入`kubernetes.container.name:"queue-proxy" AND message:/httpRequest/` . + +## Enabling TLS for Knative services[](#enabling-tls-for-knative-services "Permalink") + +默认情况下,将通过`http`提供 GitLab 无服务器部署. 为了通过`https`提供服务,您必须手动获取并安装 TLS 证书. + +完成此操作的最简单方法是使用[Certbot 手动获取 Let's Encrypt 证书](https://knative.dev/docs/serving/using-a-tls-cert/#using-certbot-to-manually-obtain-let-s-encrypt-certificates) . Certbot 是一个免费的开源软件工具,可用于在手动管理的网站上自动使用 Let's Encrypt 证书来启用 HTTPS. + +**注意:**以下说明与在安装了 Python 3 且不能在其他操作系统或其他版本的 Python 上运行的 Linux 服务器上安装和运行 Certbot 有关. + +1. 通过运行[`certbot-auto` wrapper 脚本](https://certbot.eff.org/docs/install.html#certbot-auto)安装 Certbot. 在服务器的命令行上,运行以下命令: + + ``` + wget https://dl.eff.org/certbot-auto + sudo mv certbot-auto /usr/local/bin/certbot-auto + sudo chown root /usr/local/bin/certbot-auto + sudo chmod 0755 /usr/local/bin/certbot-auto + /usr/local/bin/certbot-auto --help + ``` + + 要检查`certbot-auto`脚本的完整性,请运行: + + ``` + wget -N https://dl.eff.org/certbot-auto.asc + gpg2 --keyserver ipv4.pool.sks-keyservers.net --recv-key A2CFB51FA275A7286234E7B24D17C995CD9775F2 + gpg2 --trusted-key 4D17C995CD9775F2 --verify certbot-auto.asc /usr/local/bin/certbot-auto + ``` + + The output of the last command should look something like: + + ``` + gpg: Signature made Mon 10 Jun 2019 06:24:40 PM EDT + gpg: using RSA key A2CFB51FA275A7286234E7B24D17C995CD9775F2 + gpg: key 4D17C995CD9775F2 marked as ultimately trusted + gpg: checking the trustdb + gpg: marginals needed: 3 completes needed: 1 trust model: pgp + gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u + gpg: next trustdb check due at 2027-11-22 + gpg: Good signature from "Let's Encrypt Client Team " [ultimate] + ``` + +2. 运行以下命令以使用 Certbot 在授权过程中使用 DNS 质询来请求证书: + + ``` + /usr/local/bin/certbot-auto certonly --manual --preferred-challenges dns -d '*..example.com' + ``` + + 其中``是 GitLab 为您的无服务器项目创建的名称空间(由`--` ),而`example.com`是用于项目的域. 如果不确定项目的名称空间是什么,请导航至项目的" **操作">"无服务器"**页面,然后检查为功能/应用程序提供的端点. + + [![function_endpoint](img/70c613da170fdfd7665282f16becad56.png)](img/function-endpoint.png) + + 在上图中,项目的名称空间为`node-function-11909507` ,域为`knative.info` ,因此证书申请行如下所示: + + ``` + ./certbot-auto certonly --manual --preferred-challenges dns -d '*.node-function-11909507.knative.info' + ``` + + Certbot 工具将引导您完成通过在这些域中创建 TXT 记录来验证您拥有的每个域的步骤. 此过程完成后,输出应如下所示: + + ``` + IMPORTANT NOTES: + - Congratulations! Your certificate and chain have been saved at: + /etc/letsencrypt/live/namespace.example.com/fullchain.pem + Your key file has been saved at: + /etc/letsencrypt/live/namespace.example/privkey.pem + Your cert will expire on 2019-09-19\. To obtain a new or tweaked + version of this certificate in the future, simply run certbot-auto + again. To non-interactively renew *all* of your certificates, run + "certbot-auto renew" + -----BEGIN PRIVATE KEY----- + - Your account credentials have been saved in your Certbot + configuration directory at /etc/letsencrypt. You should make a + secure backup of this folder now. This configuration directory will + also contain certificates and private keys obtained by Certbot so + making regular backups of this folder is ideal. + ``` + +3. 创建证书和私钥文件. 使用 Certbot 返回的文件的内容,我们将创建两个文件以创建 Kubernetes 机密: + + 运行以下命令以查看`fullchain.pem`的内容: + + ``` + sudo cat /etc/letsencrypt/live/node-function-11909507.knative.info/fullchain.pem + ``` + + 输出应如下所示: + + ``` + -----BEGIN CERTIFICATE----- + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b4ag== + -----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + K2fcb195768c39e9a94cec2c2e30Qg== + -----END CERTIFICATE----- + ``` + + 创建一个名称为`cert.pem`的文件,其中包含整个输出的内容. + + 创建`cert.pem` ,运行以下命令以查看`privkey.pem`的内容: + + ``` + sudo cat /etc/letsencrypt/live/namespace.example/privkey.pem + ``` + + 输出应如下所示: + + ``` + -----BEGIN PRIVATE KEY----- + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + 2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df + -----BEGIN CERTIFICATE----- + fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6 + 4f294d1eaca42b8692017b4262== + -----END PRIVATE KEY----- + ``` + + 使用整个输出的内容创建一个名称为`cert.pk`的新文件. + +4. 创建一个 Kubernetes 机密以保存您的 TLS 证书`cert.pem`和私钥`cert.pk` : + + **注意:**在集群上运行`kubectl`命令需要首先设置对集群的访问. 对于在 GKE 上创建的集群,请参阅[GKE 集群访问](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl) . 对于其他平台, [请安装`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/) . + + ``` + kubectl create --namespace istio-system secret tls istio-ingressgateway-certs \ + --key cert.pk \ + --cert cert.pem + ``` + + 其中`cert.pem`和`cert.pk`是您的证书和私钥文件. 请注意, `istio-ingressgateway-certs`秘密名称是必需的. + +5. 配置 Knative 以使用为 HTTPS 连接创建的新密码. 运行以下命令以编辑方式打开 Knative 共享`gateway` : + + ``` + kubectl edit gateway knative-ingress-gateway --namespace knative-serving + ``` + + 更新网关以包括以下 tls:部分和配置: + + ``` + tls: + mode: SIMPLE + privateKey: /etc/istio/ingressgateway-certs/tls.key + serverCertificate: /etc/istio/ingressgateway-certs/tls.crt + ``` + + Example: + + ``` + apiVersion: networking.istio.io/v1alpha3 + kind: Gateway + metadata: + # ... skipped ... + spec: + selector: + istio: ingressgateway + servers: + - hosts: + - "*" + port: + name: http + number: 80 + protocol: HTTP + - hosts: + - "*" + port: + name: https + number: 443 + protocol: HTTPS + tls: + mode: SIMPLE + privateKey: /etc/istio/ingressgateway-certs/tls.key + serverCertificate: /etc/istio/ingressgateway-certs/tls.crt + ``` + + After your changes are running on your Knative cluster, you can begin using the HTTPS protocol for secure access your deployed Knative services. In the event a mistake is made during this process and you need to update the cert, you will need to edit the gateway `knative-ingress-gateway` to switch back to `PASSTHROUGH` mode. Once corrections are made, edit the file again so the gateway will use the new certificates. + +## Using an older version of `gitlabktl`[](#using-an-older-version-of-gitlabktl "Permalink") + +在某些情况下,您想运行旧版本的`gitlabktl` . 这需要在`.gitlab-ci.yml`文件中设置较旧版本的`gitlabktl`映像. + +要设置较旧的版本,请将`image:`添加到`functions:deploy`块中. 例如: + +``` +functions:deploy: + extends: .serverless:deploy:functions + environment: production + image: registry.gitlab.com/gitlab-org/gitlabktl:0.5.0 +``` + +通过更改注册表 URL 末尾的版本标签(格式为`registry.gitlab.com/gitlab-org/gitlabktl:`可以使用不同的版本. + +有关可用`gitlabktl`版本的完整清单,请参见`gitlabktl`项目的[容器注册表](https://gitlab.com/gitlab-org/gitlabktl/container_registry) . \ No newline at end of file diff --git a/docs/031.md b/docs/031.md new file mode 100644 index 0000000000000000000000000000000000000000..79a6a450c6dc9236e4416d505f47aa430d2839ab --- /dev/null +++ b/docs/031.md @@ -0,0 +1,488 @@ +# Deploying AWS Lambda function using GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/serverless/aws.html](https://docs.gitlab.com/ee/user/project/clusters/serverless/aws.html) + +* [Serverless Framework](#serverless-framework) + * [Example](#example) + * [Steps](#steps) + * [Creating a Lambda handler function](#creating-a-lambda-handler-function) + * [Creating a `serverless.yml` file](#creating-a-serverlessyml-file) + * [Crafting the `.gitlab-ci.yml` file](#crafting-the-gitlab-ciyml-file) + * [Setting up your AWS credentials with your GitLab account](#setting-up-your-aws-credentials-with-your-gitlab-account) + * [Deploying your function](#deploying-your-function) + * [Manually testing your function](#manually-testing-your-function) + * [How To](#how-to) + * [Running function locally](#running-function-locally) + * [Secret variables](#secret-variables) + * [Setting up CORS](#setting-up-cors) + * [Writing automated tests](#writing-automated-tests) + * [Examples and template](#examples-and-template) +* [AWS Serverless Application Model](#aws-serverless-application-model) + * [Deploying AWS Lambda function using AWS SAM and GitLab CI/CD](#deploying-aws-lambda-function-using-aws-sam-and-gitlab-cicd) + * [Example](#example-1) + * [Steps](#steps-1) + * [Installing SAM CLI](#installing-sam-cli) + * [Creating an AWS SAM application using SAM CLI](#creating-an-aws-sam-application-using-sam-cli) + * [Setting up your AWS credentials with your GitLab account](#setting-up-your-aws-credentials-with-your-gitlab-account-1) + * [Crafting the `.gitlab-ci.yml` file](#crafting-the-gitlab-ciyml-file-1) + * [Deploying your application](#deploying-your-application) + * [Testing the deployed application](#testing-the-deployed-application) + * [Testing Locally](#testing-locally) + +# Deploying AWS Lambda function using GitLab CI/CD[](#deploying-aws-lambda-function-using-gitlab-cicd "Permalink") + +GitLab 允许用户轻松部署 AWS Lambda 函数并创建丰富的无服务器应用程序. + +GitLab 支持使用以下无服务器框架通过 GitLab CI / CD 部署 AWS Lambda 功能: + +* [Serverless Framework with AWS](#serverless-framework) +* [AWS’ Serverless Application Model (SAM)](#aws-serverless-application-model) + +## Serverless Framework[](#serverless-framework "Permalink") + +The [Serverless Framework can deploy to AWS](https://www.serverless.com/framework/docs/providers/aws/). + +我们准备了一个包含分步指南的示例,以创建一个简单功能并将其部署在 AWS 上. + +此外,在"操作方法["部分中](#how-to) ,您可以了解不同的用例,例如: + +* 在本地运行功能. +* 处理秘密. +* 设置 CORS. + +或者,您可以[使用 template](../../../../gitlab-basics/create-project.html#project-templates)快速[创建一个新项目](../../../../gitlab-basics/create-project.html#project-templates) . [`Serverless Framework/JS`模板](https://gitlab.com/gitlab-org/project-templates/serverless-framework/)已经包括下面描述的所有部分. + +### Example[](#example "Permalink") + +在以下示例中,您将: + +1. 创建一个基本的 AWS Lambda Node.js 函数. +2. 将该函数链接到 API Gateway `GET`端点. + +#### Steps[](#steps "Permalink") + +该示例包括以下步骤: + +1. 创建 Lambda 处理函数. +2. 创建一个`serverless.yml`文件. +3. 制作`.gitlab-ci.yml`文件. +4. 使用 GitLab 账户设置 AWS 凭证. +5. 部署您的功能. +6. 测试已部署的功能. + +让我们一步一步来. + +#### Creating a Lambda handler function[](#creating-a-lambda-handler-function "Permalink") + +您的 Lambda 函数将是请求的主要处理程序. 在这种情况下,我们将创建一个非常简单的 Node.js `hello`函数: + +``` +'use strict'; + +module.exports.hello = async event => { + return { + statusCode: 200, + body: JSON.stringify( + { + message: 'Your function executed successfully!' + }, + null, + 2 + ), + }; +}; +``` + +将此代码放在文件`src/handler.js` . + +`src`是无服务器功能的标准位置,但是您可以根据需要进行自定义. + +在我们的例子中, `module.exports.hello`定义了`hello` ,这将在以后的引用处理器`serverless.yml` + +您可以在此处了解有关 AWS Lambda Node.js 函数处理程序及其所有各种选项的更多信息: [https](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html) : [//docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html) + +#### Creating a `serverless.yml` file[](#creating-a-serverlessyml-file "Permalink") + +在项目的根目录中,创建一个`serverless.yml`文件,其中将包含 Serverless Framework 的配置详细信息. + +将以下代码放入文件中: + +``` +service: gitlab-example +provider: + name: aws + runtime: nodejs10.x + +functions: + hello: + handler: src/handler.hello + events: + - http: GET hello +``` + +我们的函数包含一个处理程序和一个事件. + +处理程序定义将使用位于`src/handler.hello`的源代码提供 Lambda 函数. + +`events`声明将创建一个 AWS API Gateway `GET`终端节点,以接收外部请求并将其通过服务集成传递给 Lambda 函数. + +您可以阅读有关无服务器框架的[可用属性和其他配置可能性](https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml/)的更多信息. + +#### Crafting the `.gitlab-ci.yml` file[](#crafting-the-gitlab-ciyml-file "Permalink") + +在项目根目录下的`.gitlab-ci.yml`文件中,放置以下代码: + +``` +image: node:latest + +stages: + - deploy + +production: + stage: deploy + before_script: + - npm config set prefix /usr/local + - npm install -g serverless + script: + - serverless deploy --stage production --verbose + environment: production +``` + +此示例代码执行以下操作: + +1. 对所有 GitLab CI / CD 版本使用`node:latest`映像 +2. The `deploy` stage: + * 安装无服务器框架. + * 使用上面定义的 AWS 凭证将无服务器功能部署到您的 AWS 账户. + +#### Setting up your AWS credentials with your GitLab account[](#setting-up-your-aws-credentials-with-your-gitlab-account "Permalink") + +为了与您的 AWS 账户进行交互,GitLab CI / CD 管道要求在您的 GitLab 设置中的**设置> CI / CD>变量**下定义`AWS_ACCESS_KEY_ID`和`AWS_SECRET_ACCESS_KEY` . 有关更多信息,请参见[在 UI 中创建自定义变量](../../../../ci/variables/README.html#create-a-custom-variable-in-the-ui) . + +**注意:**您提供的 AWS 凭证必须包括 IAM 策略,以提供对 AWS Lambda,API 网关,CloudFormation 和 IAM 资源的正确访问控制. + +#### Deploying your function[](#deploying-your-function "Permalink") + +`git push` the changes to your GitLab repository and the GitLab build pipeline will automatically deploy your function. + +在您的 GitLab 部署阶段日志中,将包含您的 AWS Lambda 端点 URL 的输出. 日志行将类似于以下内容: + +``` +endpoints: + GET - https://u768nzby1j.execute-api.us-east-1.amazonaws.com/production/hello +``` + +#### Manually testing your function[](#manually-testing-your-function "Permalink") + +运行以下`curl`命令将触发您的功能. + +**注意:**您的 URL 应该是从 GitLab 部署阶段日志中检索到的 URL. + +``` +curl https://u768nzby1j.execute-api.us-east-1.amazonaws.com/production/hello +``` + +那应该输出: + +``` +{ "message": "Your function executed successfully!" } +``` + +万岁! 现在,您已经通过 GitLab CI / CD 部署了 AWS Lambda 函数. + +干得好! + +### How To[](#how-to "Permalink") + +在本节中,我们向您展示如何在基本示例上构建以下内容: + +* 在本地运行该功能. +* 设置秘密变量. +* 设置 CORS. + +#### Running function locally[](#running-function-locally "Permalink") + +`serverless-offline`插件允许在本地运行代码. 要在本地运行代码: + +1. 将以下内容添加到您的`serverless.yml` : + + ``` + plugins: + - serverless-offline + ``` + +2. 通过运行以下命令来启动服务: + + ``` + serverless offline + ``` + +运行以下`curl`命令将触发您的功能. + +``` +curl http://localhost:3000/hello +``` + +它应该输出: + +``` +{ "message": "Your function executed successfully!" } +``` + +#### Secret variables[](#secret-variables "Permalink") + +Secrets are injected into your functions using environment variables. + +通过在`serverless.yml`的 provider 部分中定义变量,可以将它们添加到已部署函数的环境中: + +``` +provider: + ... + environment: + A_VARIABLE: ${env:A_VARIABLE} +``` + +从那里,您也可以在函数中引用它们. 请记住,在**设置> CI / CD>**变量下,将`A_VARIABLE`添加到您的 GitLab CI / CD 变量中,它将随您的函数一起被拾取和部署. + +**注意:**有权访问 AWS 环境的任何人都可以查看 lambda 定义中保留的那些变量的值. + +#### Setting up CORS[](#setting-up-cors "Permalink") + +如果您想要建立一个调用函数的网页,就像我们在[模板中](https://gitlab.com/gitlab-org/project-templates/serverless-framework/)所做的那样,则需要处理跨域资源共享(CORS). + +快速的方法来做到这一点是添加`cors: true`标志的 HTTP 端点在你`serverless.yml` : + +``` +functions: + hello: + handler: src/handler.hello + events: + - http: # Rewrite this part to enable CORS + path: hello + method: get + cors: true # <-- CORS here +``` + +您还需要在函数响应中返回 CORS 特定的标头: + +``` +'use strict'; + +module.exports.hello = async event => { + return { + statusCode: 200, + headers: { + // Uncomment the line below if you need access to cookies or authentication + // 'Access-Control-Allow-Credentials': true, + 'Access-Control-Allow-Origin': '*' + }, + body: JSON.stringify( + { + message: 'Your function executed successfully!' + }, + null, + 2 + ), + }; +}; +``` + +有关更多信息,请参阅由无服务器框架团队撰写的《 [您的 CORS 和 API 网关生存指南》](https://www.serverless.com/blog/cors-api-gateway-survival-guide/)博客文章. + +#### Writing automated tests[](#writing-automated-tests "Permalink") + +[无服务器框架](https://gitlab.com/gitlab-org/project-templates/serverless-framework/)示例项目展示了如何使用 Jest,Axios 和`serverless-offline`插件对本地和已部署的无服务器功能进行自动化测试. + +### Examples and template[](#examples-and-template "Permalink") + +示例代码可用: + +* 作为[可克隆的存储库](https://gitlab.com/gitlab-org/serverless/examples/serverless-framework-js) . +* 在带有[测试和秘密变量](https://gitlab.com/gitlab-org/project-templates/serverless-framework/)的版本中. + +您还可以在 GitLab UI 中使用[模板](../../../../gitlab-basics/create-project.html#project-templates) (基于带有测试和秘密变量的版本)(请参阅`Serverless Framework/JS`模板). + +## AWS Serverless Application Model[](#aws-serverless-application-model "Permalink") + +AWS 无服务器应用程序模型是用于构建无服务器应用程序的开源框架. 它使构建和部署无服务器应用程序变得更加容易. 有关更多详细信息,请参阅有关[AWS 无服务器应用程序模型的](https://docs.aws.amazon.com/serverless-application-model/) AWS 文档. + +### Deploying AWS Lambda function using AWS SAM and GitLab CI/CD[](#deploying-aws-lambda-function-using-aws-sam-and-gitlab-cicd "Permalink") + +GitLab 允许开发人员使用以下组合来构建和部署无服务器应用程序: + +* [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/). +* 亚搏体育 app CI / CD. + +### Example[](#example-1 "Permalink") + +在以下示例中,您将: + +* 安装 SAM CLI. +* 创建一个示例 SAM 应用程序,其中包括 Lambda 函数和 API 网关. +* 使用 GitLab CI / CD 将应用程序构建并部署到您的 AWS 账户. + +### Steps[](#steps-1 "Permalink") + +该示例包括以下步骤: + +1. 安装 SAM CLI. +2. 使用 SAM CLI 创建 AWS SAM 应用程序. +3. 制作`.gitlab-ci.yml`文件. +4. 使用 GitLab 账户设置 AWS 凭证. +5. 部署您的应用程序. +6. 测试已部署的功能. + +### Installing SAM CLI[](#installing-sam-cli "Permalink") + +AWS SAM 提供了一个称为 AWS SAM CLI 的 CLI,可简化创建和管理应用程序的过程. + +本文档中的某些步骤使用 SAM CLI. 请按照说明[安装 SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)来安装和配置 SAM CLI. + +如果您将[AWS Cloud9](https://aws.amazon.com/cloud9/)用作集成开发环境(IDE),则会为您安装以下软件: + +* [AWS Command Line Interface](https://docs.aws.amazon.com/en_pv/cli/latest/userguide/cli-chap-install.html) +* [SAM CLI](https://docs.aws.amazon.com/en_pv/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) +* [Docker](https://s0docs0docker0com.icopy.site/install/)和必要的 Docker 映像 + +### Creating an AWS SAM application using SAM CLI[](#creating-an-aws-sam-application-using-sam-cli "Permalink") + +要创建新的 AWS SAM 应用程序: + +1. 创建一个新的 GitLab 项目. +2. `git clone`将项目`git clone`到您的本地环境中. +3. 更改为新克隆的项目,并使用以下命令创建新的 SAM 应用程序: + + ``` + sam init -r python3.8 -n gitlabpoc --app-template "hello-world" + ``` + +4. `git push`应用程序`git push`回到 GitLab 项目. + +这将使用默认配置创建一个名为`gitlabpoc`的 SAM 应用程序,该配置是[Amazon API Gateway](https://aws.amazon.com/api-gateway/)端点调用的单个 Python 3.8 函数. 要查看 SAM 支持的其他运行时以及`sam init`选项,请运行: + +``` +sam init -h +``` + +### Setting up your AWS credentials with your GitLab account[](#setting-up-your-aws-credentials-with-your-gitlab-account-1 "Permalink") + +为了与您的 AWS 账户进行交互,GitLab CI / CD 管道要求在项目的 CI / CD 变量中同时设置`AWS_ACCESS_KEY_ID`和`AWS_SECRET_ACCESS_KEY` . + +设置这些: + +1. 导航到项目的 **设置> CI / CD** . +2. 展开**变量**部分,并为`AWS_ACCESS_KEY_ID`和`AWS_SECRET_ACCESS_KEY`创建条目. +3. 屏蔽凭据,以免使用"已**屏蔽"**切换将其显示在日志中. + +**注意:**您提供的 AWS 凭证必须包括 IAM 策略,以提供对 AWS Lambda,API 网关,CloudFormation 和 IAM 资源的正确访问控制. + +### Crafting the `.gitlab-ci.yml` file[](#crafting-the-gitlab-ciyml-file-1 "Permalink") + +在项目根目录中的[`.gitlab-ci.yml`](../../../../ci/yaml/README.html)文件中,添加以下内容,并将``替换为要在其中存储软件包的 S3 存储桶的名称: + +``` +image: python:latest + +stages: + - deploy + +production: + stage: deploy + before_script: + - pip3 install awscli --upgrade + - pip3 install aws-sam-cli --upgrade + script: + - sam build + - sam package --output-template-file packaged.yaml --s3-bucket + - sam deploy --template-file packaged.yaml --stack-name gitlabpoc --s3-bucket --capabilities CAPABILITY_IAM --region us-east-1 + environment: production +``` + +让我们更仔细地检查配置文件: + +* `image`指定用于此构建的 Docker 映像. 由于示例应用程序是用 Python 编写的,因此这是最新的 Python 图像. +* AWS CLI 和 AWS SAM CLI 安装在`before_script`部分中. +* SAM 构建,打包和部署命令用于构建,打包和部署应用程序. + +### Deploying your application[](#deploying-your-application "Permalink") + +Push changes to your GitLab repository and the GitLab build pipeline will automatically deploy your application. If your: + +* 构建和部署成功, [测试已部署的应用程序](#testing-the-deployed-application) . +* 生成失败,请查看生成日志以查看生成失败的原因. 构建可能会失败的一些常见原因是: + + * 不兼容的软件版本. 例如,Python 运行时版本可能与构建计算机上的 Python 不同. 通过安装所需的软件版本来解决此问题. + * 您可能无法从 GitLab 访问您的 AWS 账户. 检查您使用 AWS 凭证设置的环境变量. + * 您可能没有权限部署无服务器应用程序. 确保提供了部署无服务器应用程序所需的所有权限. + +### Testing the deployed application[](#testing-the-deployed-application "Permalink") + +要测试您部署的应用程序,请转到构建日志,然后执行以下步骤: + +1. 点击右上角的"显示完整的原始数据": + + [![sam-complete-raw](img/fd24d5842b589870b2063edaca149511.png)](img/sam-complete-raw.png) + +2. 查找 HelloWorldApi –与以下所示类似的 API 网关端点: + + [![sam-api-endpoint](img/5dd66b504685d06e7b88c8f8a71d39ba.png)](img/sam-api-endpoint.png) + +3. 使用 curl 测试 API. 例如: + + ``` + curl https://py4rg7qtlg.execute-api.us-east-1.amazonaws.com/Prod/hello/ + ``` + +输出应为: + +``` +{"message": "hello world"} +``` + +### Testing Locally[](#testing-locally "Permalink") + +AWS SAM 提供了在本地测试应用程序的功能. 您必须在本地安装 AWS SAM CLI,才能在本地进行测试. + +首先,测试功能. + +SAM 在`events/event.json`中提供一个默认事件,其中包括以下消息主体: + +``` +{\"message\": \"hello world\"} +``` + +如果您将该事件传递给`HelloWorldFunction` ,则它应该以相同的主体响应. + +通过运行以下命令来调用该函数: + +``` +sam local invoke HelloWorldFunction -e events/event.json +``` + +输出应为: + +``` +{"message": "hello world"} +``` + +确认 Lambda 函数按预期工作后,请按照以下步骤测试 API 网关. + +通过运行以下命令在本地启动 API: + +``` +sam local start-api +``` + +SAM 再次启动 Docker 容器,这一次是在`localhost:3000`上侦听的模拟 Amazon API Gateway. + +通过运行以下命令来调用`hello` API: + +``` +curl http://127.0.0.1:3000/hello +``` + +再次输出应为: + +``` +{"message": "hello world"} +``` \ No newline at end of file diff --git a/docs/032.md b/docs/032.md new file mode 100644 index 0000000000000000000000000000000000000000..172ec4d47766aaccad586bd350b46920483bb91a --- /dev/null +++ b/docs/032.md @@ -0,0 +1,101 @@ +# Securing your deployed applications + +> 原文:[https://docs.gitlab.com/ee/user/project/clusters/securing.html](https://docs.gitlab.com/ee/user/project/clusters/securing.html) + +* [Overview](#overview) + * [Requirements](#requirements) + * [Understanding how GitLab Managed Apps are installed](#understanding-how-gitlab-managed-apps-are-installed) +* [Connect the cluster to GitLab](#connect-the-cluster-to-gitlab) +* [Set up a GitLab Runner](#set-up-a-gitlab-runner) +* [Create a Cluster Management Project](#create-a-cluster-management-project) +* [Install GitLab Container Network Policy](#install-gitlab-container-network-policy) +* [Install GitLab Container Host Security](#install-gitlab-container-host-security) + +# Securing your deployed applications[](#securing-your-deployed-applications "Permalink") + +使用 GitLab 可以轻松保护在[连接的 Kubernetes 集群中](index.html)部署的应用程序的安全. 您可以从[Web 应用程序防火墙](../../../topics/web_application_firewall/quick_start_guide.html) , [网络策略](../../../topics/autodevops/stages.html#network-policy)甚至[容器主机安全性](../../clusters/applications.html#install-falco-using-gitlab-cicd)的保护中受益. + +无论您的应用程序是否通过 GitLab CI / CD 进行部署,此页面均包含将群集连接到 GitLab 并安装这些功能的完整的端到端步骤和说明. 如果您使用[Auto DevOps](../../../topics/autodevops/index.html)与 GitLab 一起构建和部署您的应用程序,请参见上面有关[GitLab 托管应用程序](../../clusters/applications.html)的文档. + +## Overview[](#overview "Permalink") + +在较高级别,所需步骤包括以下步骤: + +* 将集群连接到 GitLab. +* 设置一个或多个跑步者. +* 设置集群管理项目. +* 安装 Web 应用程序防火墙,网络策略和/或容器主机安全性. +* 安装 Prometheus,以在[威胁监视](../../application_security/threat_monitoring/)仪表板中获取统计信息和指标. + +### Requirements[](#requirements "Permalink") + +最低要求(取决于您要安装的 GitLab 管理应用程序): + +* 您的群集已连接到 GitLab(ModSecurity,Cilium 和 Falco). +* 至少安装了一个 GitLab Runner(仅限 Cilium 和 Falco). + +### Understanding how GitLab Managed Apps are installed[](#understanding-how-gitlab-managed-apps-are-installed "Permalink") + +**注意:**为简单起见,这些图使用术语*Kubernetes* . 实际上,Sidekiq 连接到在集群中的 Pod 中运行的 Helm Tiller 守护程序. + +您可以通过一键式安装过程从 GitLab Web 界面安装 GitLab 托管应用程序. GitLab 使用 Sidekiq(后台处理服务)来简化此过程. + +sequenceDiagram 自动编号 GitLab->> + Sidekiq:安装 GitLab 托管应用程序 Sidekiq->> + Kubernetes:Helm 安装 Kubernetes->>-Sidekiq:安装完成 Sidekiq->>-GitLab:刷新 UI + +尽管此安装方法比较容易,因为它是用户界面中的"点击"操作,但它不灵活且难以调试. 当出现问题时,您将看不到部署日志. Web 应用程序防火墙功能使用此安装方法. + +但是,下一代的 GitLab 托管应用程序 V2( [基于 CI / CD 的 GitLab 托管应用程序](https://gitlab.com/groups/gitlab-org/-/epics/2103) )不使用 Sidekiq 进行部署. 所有应用程序都使用 GitLab CI / CD 管道以及因此使用的 GitLab Runners 进行部署. + +sequenceDiagram 自动编号 GitLab->> + GitLab:触发管道 GitLab->> + Runner:运行部署作业 Runner->> + Kubernetes:Helm 安装 Kubernetes->>-Runner:安装完成 Runner->>-GitLab:报告工作状态和更新流程 + +调试更容易,因为您可以访问这些作业的原始日志(在失败的情况下,可以将 Helm Tiller 输出作为工件使用),并且灵活性要好得多. 由于这些部署仅在管道正在运行时触发(很可能在集群管理存储库中有新提交时才触发),因此每个操作都具有书面记录,并遵循经典的合并请求工作流程(批准,合并,部署). 网络模型(Cilium)托管的应用程序和容器主机安全性(Falco)都使用此模型进行部署. + +## Connect the cluster to GitLab[](#connect-the-cluster-to-gitlab "Permalink") + +要将 GitLab 托管应用程序部署到群集,必须首先[将群集添加](add_remove_clusters.html)到 GitLab. 然后从项目或组 Kubernetes 页面[安装](../../clusters/applications.html#installing-applications) Web 应用程序防火墙. + +请注意,您的项目不必通过 GitLab 托管或部署. 您可以独立于使用群集的应用程序来管理群集. + +## Set up a GitLab Runner[](#set-up-a-gitlab-runner "Permalink") + +要安装基于 CI / CD 的 GitLab 托管应用程序,必须在 GitLab 中运行使用 GitLab Runner 的管道. 您可以在上一步中添加的 Kubernetes 集群中[安装 GitLab 运行程序](../../clusters/applications.html#gitlab-runner) ,或者如果使用的是 GitLab.com,则可以使用 GitLab 提供的共享运行程序之一. + +将群集连接到 GitLab 并安装好 GitLab Runner 之后,您可以继续执行下一步,并开始安装 Cilium 和 Falco GitLab 托管应用程序以保护托管在此群集上的应用程序. + +## Create a Cluster Management Project[](#create-a-cluster-management-project "Permalink") + +[群集管理项目](../../clusters/management_project.html)是一个 GitLab 项目,其中包含一个`.gitlab-ci.yml`文件,用于将 GitLab 托管应用程序部署到您的群集中. 该项目使用 Kubernetes [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)特权运行所需的图表. + +该项目的创建与其他任何 GitLab 项目一样开始. 使用一个空项目,并在根目录下添加一个`gitlab-ci.yml`文件,其中包含以下模板: + +``` +include: + - template: Managed-Cluster-Applications.gitlab-ci.yml +``` + +要使该项目成为集群管理项目,请遵循以下[说明](../../clusters/management_project.html#selecting-a-cluster-management-project) . 即使您的应用程序未托管在 GitLab 上,也可以这样指定该项目. 在这种情况下,请创建一个新的空项目,您可以在其中选择新创建的集群管理项目. + +## Install GitLab Container Network Policy[](#install-gitlab-container-network-policy "Permalink") + +GitLab 容器网络策略基于[Cilium](https://cilium.io/) . 要安装 Cilium GitLab 托管应用程序,请将`.gitlab/managed-apps/config.yaml`文件添加到群集管理项目中: + +``` +# possible values are gke, eks or you can leave it blank +clusterType: gke + +cilium: + installed: true +``` + +您的应用程序不必由 GitLab 进行管理或部署即可利用此功能. [阅读](../../clusters/applications.html#install-cilium-using-gitlab-cicd)有关配置容器网络策略的[更多](../../clusters/applications.html#install-cilium-using-gitlab-cicd)信息. + +## Install GitLab Container Host Security[](#install-gitlab-container-host-security "Permalink") + +同样,您可以在`.gitlab/managed-apps/config.yaml`基于[Falco](https://falco.org/)安装 Container Host Security: + +``` +falco: + installed: true +``` + +[阅读](../../clusters/applications.html#install-falco-using-gitlab-cicd)有关配置容器主机安全性的[更多](../../clusters/applications.html#install-falco-using-gitlab-cicd)信息. \ No newline at end of file diff --git a/docs/033.md b/docs/033.md new file mode 100644 index 0000000000000000000000000000000000000000..1d21fad79812ce8e6179ba1acb3cd4a78abd23e3 --- /dev/null +++ b/docs/033.md @@ -0,0 +1,687 @@ +# Groups + +> 原文:[https://docs.gitlab.com/ee/user/group/](https://docs.gitlab.com/ee/user/group/) + +* [Use cases](#use-cases) +* [Namespaces](#namespaces) +* [Issues and merge requests within a group](#issues-and-merge-requests-within-a-group) + * [Bulk editing issues and merge requests](#bulk-editing-issues-and-merge-requests) +* [Create a new group](#create-a-new-group) +* [Add users to a group](#add-users-to-a-group) +* [Request access to a group](#request-access-to-a-group) +* [Changing the owner of a group](#changing-the-owner-of-a-group) +* [Remove a member from the group](#remove-a-member-from-the-group) +* [Changing the default branch protection of a group](#changing-the-default-branch-protection-of-a-group) +* [Add projects to a group](#add-projects-to-a-group) + * [Default project-creation level](#default-project-creation-level) +* [View group details](#view-group-details) + * [Group activity analytics overview](#group-activity-analytics-overview) +* [View group activity](#view-group-activity) +* [Transfer projects into groups](#transfer-projects-into-groups) +* [Sharing a project with a group](#sharing-a-project-with-a-group) +* [Sharing a group with another group](#sharing-a-group-with-another-group) +* [Manage group memberships via LDAP](#manage-group-memberships-via-ldap) + * [Creating group links via CN](#creating-group-links-via-cn-starter-only) + * [Creating group links via filter](#creating-group-links-via-filter-premium-only) + * [Overriding user permissions](#overriding-user-permissions-starter-only) +* [Epics](#epics-ultimate) +* [Group Security Dashboard](#group-security-dashboard-ultimate) +* [Insights](#insights-ultimate) +* [Transferring groups](#transferring-groups) +* [Group settings](#group-settings) + * [General settings](#general-settings) + * [Changing a group’s path](#changing-a-groups-path) + * [Remove a group](#remove-a-group) + * [Restore a group](#restore-a-group-premium) + * [Enforce 2FA to group members](#enforce-2fa-to-group-members) + * [Share with group lock](#share-with-group-lock) + * [Member Lock](#member-lock-starter) + * [IP access restriction](#ip-access-restriction-premium) + * [Allowed domain restriction](#allowed-domain-restriction-premium) + * [Group file templates](#group-file-templates-premium) + * [Group-level project templates](#group-level-project-templates-premium) + * [Disabling email notifications](#disabling-email-notifications) + * [Disabling group mentions](#disabling-group-mentions) + * [Enabling delayed Project removal](#enabling-delayed-project-removal-premium) + * [Advanced settings](#advanced-settings) + * [Storage usage quota](#storage-usage-quota-starter) + * [Group push rules](#group-push-rules-starter) + * [Enabling the feature](#enabling-the-feature) + * [Maximum artifacts size](#maximum-artifacts-size-core-only) +* [User contribution analysis](#user-contribution-analysis-starter) +* [Issues analytics](#issues-analytics-premium) +* [Dependency Proxy](#dependency-proxy-premium) + +# Groups[](#groups "Permalink") + +使用 GitLab 组,您可以: + +* 将相关项目组装在一起. +* 授予成员一次访问多个项目的权限. + +有关 GitLab 组的视频介绍,请参见[GitLab 大学:存储库,项目和组](https://www.youtube.com/watch?v=4TWfh1aKHHw) . + +组也可以嵌套在[子组中](subgroups/index.html) . + +通过单击顶部导航中的**组>您的组**来找到您的组. + +[![GitLab Groups](img/53bcd8c2d2c69aceb7db6677802be6b1.png)](img/groups.png) + +[GitLab 11.1](https://about.gitlab.com/releases/2018/07/22/gitlab-11-1-released/#groups-dropdown-in-navigation)中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36234)了顶部导航中的" **组"**下拉列表. + +" **组"**页面显示: + +* 选择**您的组**后, **您将**是**您**所属的所有组. +* 选中" **浏览公共组"**时的公共组列表. + +" **组"**页面上的每个组都列出了: + +* 它有多少个子组. +* 它包含多少个项目. +* 该组有多少个成员,不包括从父组继承的成员. +* 小组的知名度. +* 如果您具有足够的权限,则指向组设置的链接. +* 如果您是成员,则退出该组的链接. + +## Use cases[](#use-cases "Permalink") + +您可以出于多种原因创建组. 列举几个: + +* 通过在同一[名称空间](#namespaces)下组织相关项目并将成员添加到顶级组,可以以较少的步骤授予对多个项目和多个团队成员的访问权限. +* 通过创建小组并包括适当的成员,可以轻松地`@mention`所有团队中的问题并合并请求. + +例如,您可以为公司成员创建一个[组](subgroups/index.html) ,并为每个单独的团队创建一个[子](subgroups/index.html)组. 假设您创建了一个名为`company-team` ,并且在该组中为各个团队`backend-team` , `frontend-team`和`production-team`创建了子组. + +* 从问题开始新的实现时,请添加评论: *" `@company-team` ,让我们开始吧!* *`@company-team/backend-team`您很高兴!"* +* 当您的后端团队需要前端提供帮助时,他们会添加一条评论: *" `@company-team/frontend-team`您能在这里帮助我们吗?"* +* 前端团队完成实施后,他们会评论: *" `@company-team/backend-team` ,它已经完成!* *让我们将其运送到`@company-team/production-team` !* + +## Namespaces[](#namespaces "Permalink") + +在 GitLab 中,名称空间是用作用户名,组名或子组名的唯一名称. + +* `http://gitlab.example.com/username` +* `http://gitlab.example.com/groupname` +* `http://gitlab.example.com/groupname/subgroup_name` + +例如,考虑一个名为 Alex 的用户: + +1. Alex 在 GitLab.com 上使用用户名`alex`创建了一个帐户; 他们的个人资料将在`https://gitlab.example.com/alex`下访问 +2. Alex 为他们的团队创建了一个小组,小组名称为`alex-team` ; 该小组及其项目将在`https://gitlab.example.com/alex-team`下访问 +3. 亚历克斯(Alex)创建了一个亚历克斯小组( `alex-team`子`alex-team` ,其子小组名称为`marketing` ; 该子小组及其项目将在`https://gitlab.example.com/alex-team/marketing`下访问 + +通过这样做: + +* 任何团队成员都使用`@alex`提及 Alex +* 亚历克斯通过`@alex-team`提及了团队中的每个人 +* 亚历克斯只提及`@alex-team/marketing` + +## Issues and merge requests within a group[](#issues-and-merge-requests-within-a-group "Permalink") + +问题和合并请求是项目的一部分. 对于给定的组,您可以在单个列表视图中查看所有[问题](../project/issues/index.html#issues-list)并将该组中所有项目的[请求合并](../project/merge_requests/reviewing_and_managing_merge_requests.html#view-merge-requests-for-all-projects-in-a-group)在一起. + +### Bulk editing issues and merge requests[](#bulk-editing-issues-and-merge-requests "Permalink") + +有关详细信息,请参阅[批量编辑问题和合并请求](../group/bulk_editing/index.html) . + +## Create a new group[](#create-a-new-group "Permalink") + +> 有关不允许用作组名的单词列表,请参见[保留名称](../reserved_names.html) . + +要创建新组,请执行以下任一操作: + +* 在顶部菜单中,依次单击" **组"**和" **您的组"** ,然后单击绿色按钮" **新建组"** . + + [![new group from groups page](img/7e5039b0d8fb74c5ea813e354f23493e.png)](img/new_group_from_groups.png) + +* 或者,在顶部菜单中,展开`plus`号并选择**新建组** . + + [![new group from elsewhere](img/ee8ead7652026dd03a75e2551122350f.png)](img/new_group_from_other_pages.png) + +添加以下信息: + +[![new group information](img/ad2cdacdd36348cddf7d5c19d8940d5b.png)](img/create_new_group_info.png) + +1. **组名将**自动填充 URL. (可选)您可以更改它. 这是在组视图中显示的名称. 该名称只能包含: + * 字母数字字符 + * 下划线 + * 划线和点 + * 空间 +2. **组 URL**是将托管项目的名称空间. 该网址只能包含: + * 字母数字字符 + * 下划线 + * 破折号和点(不能以破折号开头或以点结尾) +3. (可选)您可以添加简短说明,以告诉其他人该组的内容. +4. (可选)为您的群组选择一个头像. +5. Choose the [visibility level](../../public_access/public_access.html). + +有关创建组的更多详细信息,请观看视频[GitLab 命名空间(用户,组和子组)](https://youtu.be/r0sJgjR2f5A) . + +## Add users to a group[](#add-users-to-a-group "Permalink") + +将多个项目放在一个组中的好处是,您可以通过一个操作就授予用户访问该组中所有项目的权限. + +通过导航到组的仪表板并单击**Members**将成员添加到组. + +[![add members to group](img/ece990045e1a7ae1237b5f2912a2df3e.png)](img/add_new_members.png) + +选择[权限级别](../permissions.html#permissions) ,然后添加新成员. 您还可以设置该用户的到期日期. 这是他们将不再有权访问您的网上论坛的日期. + +考虑一个有两个项目的小组: + +* 现在,在" **组成员"**页面上,可以将新用户添加到组中. +* 现在,由于该用户是该组的**开发人员**成员,因此他们自动获得**开发人员**对该组内**所有项目的**访问权限. + +要提高特定项目的现有用户的访问级别,请将其作为新成员再次添加到具有所需权限级别的项目中. + +## Request access to a group[](#request-access-to-a-group "Permalink") + +作为论坛所有者,您可以启用或禁用非会员请求访问您论坛的功能. 转到组设置,然后单击**允许用户请求访问权限** . + +作为用户,如果启用了该设置,则可以请求成为组的成员. 转到您要加入的组,然后单击屏幕右侧的" **请求访问**权"按钮. + +[![Request access button](img/aa2dd1694d7e1573bbd49200ed1ccb04.png)](img/request_access_button.png) + +请求访问后: + +* 通过电子邮件将多达十个群组所有者的通知通知您. 电子邮件将发送给最近活动的组所有者. +* 任何论坛所有者都可以在会员页面上批准或拒绝您的请求. + +[![Manage access requests](img/fd0991d7941fed77c4d82bd219ec713b.png)](img/access_requests_management.png) + +如果您在批准请求之前改变主意,只需单击" **撤回访问请求"**按钮. + +[![Withdraw access request button](img/a6d5e94df0d5d50038a0909603d69933.png)](img/withdraw_access_request_button.png) + +## Changing the owner of a group[](#changing-the-owner-of-a-group "Permalink") + +Ownership of a group means at least one of its members has [Owner permission](../permissions.html#group-members-permissions). Groups must have at least one owner. + +可以只更改一个所有者的组所有者. 更改组的唯一所有者: + +* 作为管理员: + 1. 前往小组的 **成员**选项卡. + 2. 赋予其他成员**所有者**权限. + 3. 刷新页面. 现在,您可以从原始所有者中删除**所有者**权限. +* 作为当前组的所有者: + 1. 前往小组的 **成员**选项卡. + 2. 赋予其他成员**所有者**权限. + 3. 让新的所有者登录并从您中删除**所有者**权限. + +## Remove a member from the group[](#remove-a-member-from-the-group "Permalink") + +只有[拥有所有者](../permissions.html#group-members-permissions)权限的[用户](../permissions.html#group-members-permissions)才能管理组成员. + +如果给定成员在该组中具有直接成员资格,则可以从该组中删除该成员. 如果成员资格是从父组继承的,则该成员只能从父组本身中删除. + +删除成员时,您可以决定是从所有问题中取消分配用户,还是合并当前已分配的请求,还是保留分配. + +* 当用户离开私人组并且您希望撤消他们对所有问题的访问并分配他们的合并请求时,从所有问题和合并请求中**取消分配已删除的成员**可能会有所帮助. +* **保留问题和合并请求的分配**可能对于接受公共贡献的组很有帮助,在这些组中,用户不必是成员就可以为问题和合并请求做出贡献. + +要从组中删除成员: + +1. 在一个小组中,转到 **成员们** . +2. 点击**删除** 要删除的群组成员旁边的按钮. 出现" **删除成员"**模态. +3. (可选)选中" **也从相关问题中取消分配此用户并合并请求"**复选框. +4. Click **删除会员**. + +## Changing the default branch protection of a group[](#changing-the-default-branch-protection-of-a-group "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7583) . + +默认情况下,每个组都继承全局级别的分支保护集. + +要为特定组更改此设置: + +1. 前往小组的 **设置>常规**页面. +2. 展开" **权限,LFS,2FA"**部分. +3. 在" **默认分支保护"**下拉列表中选择所需的选项. +4. Click **保存更改**. + +要全局更改此设置,请参阅[默认分支保护](../admin_area/settings/visibility_and_access_controls.html#default-branch-protection) . + +**注意:**在[GitLab Premium 或更高版本中](https://about.gitlab.com/pricing/) ,GitLab 管理员可以选择[禁止组所有者更新默认的分支保护](../admin_area/settings/visibility_and_access_controls.html#disable-group-owners-from-updating-default-branch-protection-premium-only) . + +## Add projects to a group[](#add-projects-to-a-group "Permalink") + +有两种方法可以将新项目添加到组中: + +* 选择一个组,然后单击" **新建项目"** . 然后,您可以继续[创建您的项目](../../gitlab-basics/create-project.html) . + + [![New project](img/ef67d77909a856277f9f2821fa0c18ea.png)](img/create_new_project_from_group.png) + +* 在创建项目时,请从下拉菜单中选择已经创建的组名称空间. + + [![Select group](img/674c1579957cca4a644bc90fb8fbb2f3.png)](img/select_group_dropdown.png) + +### Default project-creation level[](#default-project-creation-level "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/2534) . +* 在 10.7 中带到[GitLab Starter](https://about.gitlab.com/pricing/) . +* 在 11.10 中[移至](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25975) [GitLab Core](https://about.gitlab.com/pricing/) . + +默认情况下, [开发人员和维护人员](../permissions.html#group-members-permissions)可以在一个组下创建项目. + +要为特定组更改此设置: + +1. 转到论坛的**设置>常规**页面. +2. 展开" **权限,LFS,2FA"**部分. +3. 在" **允许创建项目"**下拉列表中选择所需的选项. +4. Click **保存更改**. + +要全局更改此设置,请参阅[默认项目创建保护](../admin_area/settings/visibility_and_access_controls.html#default-project-creation-protection) . + +## View group details[](#view-group-details "Permalink") + +组的" **详细信息"**页面包含以下选项卡: + +* 小组和项目. +* 共享的项目. +* 存档的项目. + +### Group activity analytics overview[](#group-activity-analytics-overview "Permalink") + +版本历史 + +* 在 GitLab [Starter](https://about.gitlab.com/pricing/) 12.10 中作为[测试版功能](https://about.gitlab.com/handbook/product/#beta) [引入](https://gitlab.com/gitlab-org/gitlab/-/issues/207164) + +组详细信息视图还显示最近 90 天内创建的以下项目数: + +* 合并请求. +* Issues. +* Members. + +可以使用`group_activity_analytics` [功能标记](../../development/feature_flags/development.html#enabling-a-feature-flag-in-development)启用这些组活动分析. + +[![Recent Group Activity](img/645965e7ebb61697ff42cc06214ca5af.png)](img/group_activity_analytics_v12_10.png) + +有关详细信息,请参阅有关如何[查看组活动的部分](#view-group-activity) . + +## View group activity[](#view-group-activity "Permalink") + +群组的" **活动"**页面显示群组中最近执行的操作,包括: + +* **推送事件** :最近推送到分支. +* **合并事件** :最近合并. +* **发行事件** :已发行或已关闭的发行. +* **史诗般的事件** :史诗集开启或关闭. +* **评论** :评论已打开或关闭. +* **小组** :已加入或离开小组的小组成员. +* **Wiki** :创建,删除或更新的 Wiki. + +单击**RSS**图标,还可以 Atom 格式获得整个活动供稿. + +要查看论坛的" **活动"**页面,请执行以下操作: + +1. 转到论坛的页面. +2. 在左侧导航菜单中,转到" **组概述",**然后选择" **活动"** . + +## Transfer projects into groups[](#transfer-projects-into-groups "Permalink") + +了解如何[将项目转移到小组中](../project/settings/index.html#transferring-an-existing-project-into-another-namespace) . + +## Sharing a project with a group[](#sharing-a-project-with-a-group "Permalink") + +您可以[与一个小组共享您的项目,](../project/members/share_project_with_groups.html)并向所有小组成员立即授予对该项目的访问权限. + +或者,您可以[锁定共享与组功能](#share-with-group-lock) . + +## Sharing a group with another group[](#sharing-a-group-with-another-group "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/18328) . + +与[与组共享项目](#sharing-a-project-with-a-group)类似,您可以与另一个组共享一个组,以使直接的组成员可以访问共享的组. 这对于继承的成员无效. + +要将给定的组(例如"前端")与另一个组(例如"工程")共享: + +1. 导航到"前端"群组页面,然后使用左侧的导航菜单转到群组" **成员"** . +2. Select the **邀请小组** tab. +3. 以您选择的最大访问权限级别添加"工程". +4. Click **Invite**. + +"工程"组的所有成员将被添加到"前端". + +## Manage group memberships via LDAP[](#manage-group-memberships-via-ldap "Permalink") + +组同步允许将 LDAP 组映射到 GitLab 组. 这样可以更好地控制每组用户的管理. 要配置组同步,请编辑`group_base` **DN** ( `'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org'` ). 该**OU**包含将与 GitLab 组关联的所有组. + +可以使用 CN 或过滤器创建组链接. 这些组链接在**组设置-> LDAP 同步**页面上创建. 配置链接后,用户可能需要一个多小时才能与 GitLab 组进行同步. + +有关 LDAP 和组同步管理的更多信息,请参阅[LDAP 主文档](../../administration/auth/ldap/index.html#group-sync-starter-only) . + +**注意:**如果在添加 LDAP 同步时 LDAP 用户是组成员,并且它们不属于 LDAP 组,则将从该组中将其删除. + +### Creating group links via CN[](#creating-group-links-via-cn-starter-only "Permalink") + +通过 CN 创建群组链接: + +1. 选择**LDAP 服务器**作为链接. +2. 选择`LDAP Group cn`作为**同步方法** . +3. 在" **LDAP 组 cn"**文本输入框中,开始输入组的 CN. 在配置的`group_base`中将有一个带有匹配 CN 的下拉菜单. 从此列表中选择您的 CN. +4. 在" **LDAP 访问"**部分中,选择在该组中同步的用户的[权限级别](../permissions.html) . +5. 单击`Add Synchronization`按钮以保存该组链接. + +[![Creating group links via CN](img/5d200a6bcc883fcfa57dac51301bc2e3.png)](img/ldap_sync_cn_v13_1.png) + +### Creating group links via filter[](#creating-group-links-via-filter-premium-only "Permalink") + +通过过滤器创建组链接: + +1. 选择**LDAP 服务器**作为链接. +2. 选择`LDAP user filter`作为**Sync 方法** . +3. 在" **LDAP 用户"过滤器**框中输入过滤**器** . 请遵循[有关用户过滤器](../../administration/auth/ldap/index.html#set-up-ldap-user-filter-core-only)的[文档](../../administration/auth/ldap/index.html#set-up-ldap-user-filter-core-only) . +4. 在" **LDAP 访问"**部分中,选择在该组中同步的用户的[权限级别](../permissions.html) . +5. 单击`Add Synchronization`按钮以保存该组链接. + +[![Creating group links via filter](img/5b8558c08a5996468dcd0d1a119ac76b.png)](img/ldap_sync_filter_v13_1.png) + +### Overriding user permissions[](#overriding-user-permissions-starter-only "Permalink") + +从 GitLab [v8.15 开始,](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/822) LDAP 用户权限现在可以由管理员用户手动覆盖. 覆盖用户的权限: + +1. 转到您小组的" **成员"**页面. +2. 在您要编辑的用户的行中选择铅笔图标. +3. 选择橙色的`Change permissions`按钮. + +[![Setting manual permissions](img/c6273de0eb8e4c8e7750113a7a66e7d6.png)](img/manual_permissions_v13_1.png) + +现在,您将能够从" **成员"**页面编辑用户的权限. + +## Epics[](#epics-ultimate "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.2 中引入. + +Epics 通过跟踪跨项目和里程碑共享主题的问题组,使您可以更有效,更轻松地管理项目组合. + +[Learn more about Epics.](epics/index.html) + +## Group Security Dashboard[](#group-security-dashboard-ultimate "Permalink") + +概述组及其子组中所有项目的漏洞. + +[Learn more about the Group Security Dashboard.](security_dashboard/index.html) + +## Insights[](#insights-ultimate "Permalink") + +[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. + +配置对您的组或项目重要的见解,使用户可以浏览以下数据: + +* 分诊卫生 +* 在给定期间内创建/关闭的问题 +* 合并请求的平均合并时间 +* 多得多 + +[Learn more about Insights](insights/index.html). + +## Transferring groups[](#transferring-groups "Permalink") + +在 GitLab 10.5 中,您可以通过以下方式转移组: + +* 将子组转移到新的父组. +* 通过将顶级组转移到所需的组,将其转换为子组. +* Convert a subgroup into a top-level group by transferring it out of its current group. + +转移群组时,请注意: + +* 更改组的父母可能会产生意想不到的副作用. 请参阅[更改存储库路径时的重定向](../project/index.html#redirects-when-changing-repository-paths) . +* 您只能将群组转移到您管理的群组中. +* 您必须更新本地存储库以指向新位置. +* If the immediate parent group’s visibility is lower than the group’s current visibility, visibility levels for subgroups and projects will change to match the new parent group’s visibility. +* 仅传输显式组成员身份,不继承继承成员身份. 如果组的所有者仅继承了成员身份,则该组将没有所有者. 在这种情况下,转移组的用户将成为该组的所有者. + +## Group settings[](#group-settings "Permalink") + +创建群组后,您可以导航至该群组的信息中心,然后点击**设置**来管理其设置. + +[![group settings](img/b98f1bb6205ce5c692946b81e8c78003.png)](img/group_settings.png) + +### General settings[](#general-settings "Permalink") + +除了编辑您在[创建组](#create-a-new-group)时先前设置的任何设置之外,您还可以访问[该组的](#create-a-new-group)其他配置. + +#### Changing a group’s path[](#changing-a-groups-path "Permalink") + +更改组的路径可能会有意想不到的副作用. 在继续之前,请阅读[重定向的行为](../project/index.html#redirects-when-changing-repository-paths) . + +如果您要腾出路径,以便其他组或用户可以声明该路径,则由于名称和路径都必须是唯一的,因此您可能也需要重命名该组. + +更改组路径: + +1. 导航到论坛的**"设置">"常规"**页面. +2. 展开**路径,传输,删除**部分. +3. 在" **更改组路径"**下输入新名称. +4. Click **变更群组路径**. + +**注意:**如果命名空间包含带有[Container Registry](../packages/container_registry/index.html)标记的项目,则当前无法重命名该命名空间,因为该项目无法移动.**提示:**如果要保留对原始名称空间的所有权并保护 URL 重定向,则可以更改一个组并向其传输项目,而无需更改组的路径或重命名用户名. + +### Remove a group[](#remove-a-group "Permalink") + +删除组及其内容: + +1. 导航到您小组的 **设置>常规**页面. +2. 展开**路径,传输,删除**部分. +3. 在"删除组"部分中,单击" **删除组"**按钮. +4. 根据要求确认操作. + +此操作要么: + +* 删除组,并且将后台作业排队以删除该组中的所有项目. +* 从[GitLab 12.8 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/33257) ,在[Premium 或 Silver](https://about.gitlab.com/pricing/premium/)或更高级别上,将一个组标记为删除. 默认情况下,删除将在 7 天后进行,但是可以在[实例设置中](../admin_area/settings/visibility_and_access_controls.html#default-deletion-adjourned-period-premium-only)进行更改. + +### Restore a group[](#restore-a-group-premium "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33257) . + +要还原标记为删除的组: + +1. 导航到您小组的 **设置>常规**页面. +2. 展开**路径,传输,删除**部分. +3. 在"还原组"部分中,单击" **还原组"**按钮. + +#### Enforce 2FA to group members[](#enforce-2fa-to-group-members "Permalink") + +通过对所有组成员[强制执行两因素身份验证(2FA)](../../security/two_factor_authentication.html#enforcing-2fa-for-all-users-in-a-group) ,将安全层添加到您的组中. + +#### Share with group lock[](#share-with-group-lock "Permalink") + +防止一个组中[的项目与另一个组共享项目,](../project/members/share_project_with_groups.html)以便对项目访问进行更严格的控制. + +例如,假设您有两个不同的团队(A 组和 B 组)在一个项目中一起工作,并且要继承该组成员身份,您可以在 A 组和 B 组之间共享项目. **使用组锁共享**可以防止其中的任何项目该群组不会与其他群组共享,从而确保只有合适的群组成员才能访问这些项目. + +要启用此功能,请导航至组设置页面. 选择" **使用组锁定共享"**并**保存组** . + +[![Checkbox for share with group lock](img/788efc08015bf62f608d47f16b49b4d7.png)](img/share_with_group_lock.png) + +#### Member Lock[](#member-lock-starter "Permalink") + +成员锁定使组所有者可以阻止组中所有项目的任何新项目成员资格,从而可以更严格地控​​制项目成员资格. + +例如,如果要为" [审核事件"](../../administration/audit_events.html)锁定组,请启用"成员锁定"以确保在该审核期间不能修改项目成员身份. + +要启用此功能: + +1. 导航到组的**"设置">"常规"**页面. +2. 展开" **权限,LFS,2FA"**部分,然后选择" **成员锁"** . +3. Click **保存更改**. + +[![Checkbox for membership lock](img/5460742929164e737a1b4c1990b75fc3.png)](img/member_lock.png) + +这将对以前有权操作项目成员资格的所有用户禁用该选项,因此无法添加新用户. 此外,将无法通过 API 向项目添加新用户的任何请求. + +#### IP access restriction[](#ip-access-restriction-premium "Permalink") + +版本历史 + +* 在[GitLab Ultimate 和 Gold](https://about.gitlab.com/pricing/) 12.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/1985) . +* 在 13.1 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/215410) [GitLab Premium 和 Silver](https://about.gitlab.com/pricing/) . + +为了确保只有组织内的人员可以访问特定资源,您可以选择通过 IP 地址限制对组及其基础项目,问题等的访问. 这可以帮助确保特定内容不会离开场所,同时又不会阻止对整个实例的访问. + +使用 CIDR 表示法将一个或多个允许的 IP 子网添加到组设置中,并且来自其他 IP 地址的任何人将无法访问受限制的内容. + +目前限制适用于: + +* UI. +* [从 GitLab 12.3 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/12874) ,可以访问 API. +* [从 GitLab 12.4 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/32113) ,Git 通过 SSH 进行操作. + +为了避免意外锁定,管理员和组所有者可以访问组,而不受 IP 限制. + +要启用此功能: + +1. 导航到组的**"设置">"常规"**页面. +2. 展开" **权限,LFS,2FA"**部分,然后在" **允许访问以下 IP 地址"**字段中输入 IP 地址范围. +3. Click **保存更改**. + +#### Allowed domain restriction[](#allowed-domain-restriction-premium "Permalink") + +版本历史 + +* 在[GitLab Premium 和 Silver](https://about.gitlab.com/pricing/) 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7297) . +* 支持指定 GitLab 13.1 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/33143)多个电子邮件域 + +通过仅将具有特定域中电子邮件地址的用户添加到组中,可以限制对组的访问. + +添加您要允许的电子邮件域,并且不允许来自不同域的电子邮件用户添加到该组. + +某些域不能被限制. 这些是最受欢迎的公共电子邮件域,例如: + +* `gmail.com` +* `yahoo.com` +* `hotmail.com` +* `aol.com` +* `msn.com` +* `hotmail.co.uk` +* `hotmail.fr` +* `live.com` +* `outlook.com` +* `icloud.com` + +要启用此功能: + +1. 导航到组的**"设置">"常规"**页面. +2. 展开" **权限,LFS,2FA"**部分,然后在" **通过电子邮件限制成员身份"**字段中输入域名. +3. Click **保存更改**. + +此后,将对所有添加到组中的新用户启用域检查. + +#### Group file templates[](#group-file-templates-premium "Permalink") + +组文件模板使您可以与组中的每个项目共享一组通用文件类型的模板. 它类似于[实例模板存储库](../admin_area/settings/instance_template_repository.html)功能,所选项目应遵循该页面上记录的相同命名约定. + +您只能在组中选择项目作为模板源. 这包括与该组共享的项目,但**不包括**正在配置的组的子组或父组中的项目. + +您可以为子组和直接父组配置此功能. 子组中的项目将有权访问该子组以及任何直接父组的模板. + +[![Group file template dropdown](img/6c431eb1e4bc729eceb4a6a36f0ea6b0.png)](img/group_file_template_dropdown.png) + +要启用此功能,请导航至组设置页面,展开" **模板"**部分,选择一个项目作为模板存储库,然后选择" **保存组"** . + +[![Group file template settings](img/09e1824644c088dfbd0f2f9710fc7d77.png)](img/group_file_template_settings.png) + +#### Group-level project templates[](#group-level-project-templates-premium "Permalink") + +通过将组设置为模板源,在组级别定义项目模板. [了解有关组级项目模板的更多信息](custom_project_templates.html) . + +#### Disabling email notifications[](#disabling-email-notifications "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/23585) . + +您可以禁用与该组相关的所有电子邮件通知,其中包括其子组和项目. + +要启用此功能: + +1. 导航到组的**"设置">"常规"**页面. +2. 展开**权限,LFS,2FA**部分,然后选择**禁用电子邮件通知** . +3. Click **保存更改**. + +#### Disabling group mentions[](#disabling-group-mentions "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/21301) . + +您可以防止将用户添加到对话中,并且在任何人提及这些用户所属的组时通知他们. + +自动完成下拉列表中会相应地显示提及被禁用的组. + +这对于具有大量用户的组特别有用. + +要启用此功能: + +1. 导航到组的**"设置">"常规"**页面. +2. 展开" **权限"," LFS,2FA"**部分,然后选择" **禁用组提及"** . +3. Click **保存更改**. + +#### Enabling delayed Project removal[](#enabling-delayed-project-removal-premium "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) . + +默认情况下,组中的项目会立即删除. (可选)在[Premium 或 Silver](https://about.gitlab.com/pricing/)或更高级别上,您可以将组内的项目配置为在延迟间隔后删除. + +在此间隔期间,项目将处于只读状态,并且可以根据需要还原. 间隔时间默认为 7 天,可以由管理员在[实例设置中](../admin_area/settings/visibility_and_access_controls.html#default-deletion-adjourned-period-premium-only)进行修改. + +要启用延迟删除项目: + +1. 导航到组的**"设置">"常规"**页面. +2. 展开" **权限"," LFS,2FA"**部分,然后选中" **启用延迟的项目删除"** . +3. Click **保存更改**. + +### Advanced settings[](#advanced-settings "Permalink") + +* **项目** :查看该组中的所有项目,将成员添加到每个项目,访问每个项目的设置,以及删除任何项目,所有操作均在同一屏幕上进行. +* **Webhooks** :为您的组配置[webhooks](../project/integrations/webhooks.html) . +* **Kubernetes 集群集成** :将您的 GitLab 组与[Kubernetes 集群连接](clusters/index.html) . +* **审核事件** :查看该组的[审核事件](../../administration/audit_events.html) . +* **管道配额** :跟踪组的[管道配额](../admin_area/settings/continuous_integration.html) . + +#### Storage usage quota[](#storage-usage-quota-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/13294) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.0. + +组所有者可以在组页面设置列表可用的" **使用配额"**页面的" **存储"**选项卡中,查看一个组(包括子组)中所有项目的聚合存储使用情况. + +[![Group storage usage quota](img/7042e9f430cefb3a9c62194cec839692.png)](img/group_storage_usage_quota.png) + +如果触发了任何会影响其值的相关事件(例如,提交推送),则将更新存储的总使用量. 出于性能原因,我们可能会将更新延迟最多 1 小时 30 分钟. + +如果您的名称空间显示`N/A`作为总存储使用量,则可以通过将提交推送到该名称空间中的任何项目来触发重新计算. + +#### Group push rules[](#group-push-rules-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34370) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.8. + +组推送规则允许组维护者为特定组内的新创建项目设置[推送规则](../../push_rules/push_rules.html) . + +要为组配置推送规则,请导航至 在小组的侧边栏上. + +设置后,新的子组将根据以下任一条件为其设置推送规则: + +* 定义了推送规则的最接近的父组. +* 如果没有父组定义推送规则,则在实例级别设置推送规则. + +##### Enabling the feature[](#enabling-the-feature "Permalink") + +默认情况下,此功能带有`:group_push_rules`功能标记. 可以使用功能标记[API 端点](../../api/features.html#set-or-create-a-feature)或通过具有 Rails 控制台访问权限的 GitLab 管理员为特定组启用它,方法是运行: + +``` +Feature.enable(:group_push_rules) +``` + +### Maximum artifacts size[](#maximum-artifacts-size-core-only "Permalink") + +有关为组设置最大工件大小的信息,请参见[最大工件大小](../admin_area/settings/continuous_integration.html#maximum-artifacts-size-core-only) . + +## User contribution analysis[](#user-contribution-analysis-starter "Permalink") + +使用[GitLab Contribution Analytics](contribution_analytics/index.html) ,您可以概述组成员执行的贡献(推送,合并请求和问题). + +## Issues analytics[](#issues-analytics-premium "Permalink") + +使用[GitLab Issues Analytics](issues_analytics/index.html) ,您可以查看组中每个月创建的问题数量的条形图. + +## Dependency Proxy[](#dependency-proxy-premium "Permalink") + +使用 GitLab 作为上游 Docker 映像的[依赖项代理](../packages/dependency_proxy/index.html) . \ No newline at end of file diff --git a/docs/034.md b/docs/034.md new file mode 100644 index 0000000000000000000000000000000000000000..0bb10091cf5f191ca38b2c13b3f3f49fce74681f --- /dev/null +++ b/docs/034.md @@ -0,0 +1,69 @@ +# Contribution Analytics + +> 原文:[https://docs.gitlab.com/ee/user/group/contribution_analytics/](https://docs.gitlab.com/ee/user/group/contribution_analytics/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Using Contribution Analytics](#using-contribution-analytics) +* [Changing the period time](#changing-the-period-time) +* [Sorting by different factors](#sorting-by-different-factors) + +# Contribution Analytics[](#contribution-analytics-starter "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 8.3 中引入. +* 在 GitLab 12.2 中针对子组进行了[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/3090) . + +## Overview[](#overview "Permalink") + +借助 Contribution Analytics,您可以大致了解小组中的以下活动: + +* Issues +* 合并要求 +* 推送事件 + +要查看贡献分析,请转至小组的" **分析">"贡献分析"**页面. + +## Use cases[](#use-cases "Permalink") + +* 分析您的团队在一段时间内的贡献,并为杰出贡献者提供奖金. +* 与可以从其他支持中受益的小组成员一起确定改进的机会. + +## Using Contribution Analytics[](#using-contribution-analytics "Permalink") + +以下是三个主要的条形图,它们说明了每个组成员的贡献数量: + +* 推送事件 +* 合并要求 +* 已解决的问题 + +将鼠标悬停在每个栏上可以显示特定组成员的事件数. + +[![Contribution analytics bar graphs](img/52f1314a06269a0dc317f758c8e8cdab.png)](img/group_stats_graph.png) + +## Changing the period time[](#changing-the-period-time "Permalink") + +您可以从以下三个期间中选择: + +* 上周(默认) +* 上个月 +* 最近三个月 + +从日历下拉列表中选择所需的时间段. + +[![Contribution analytics choose period](img/0bc8de7b7d20af897fb8b38bb48663e8.png)](img/group_stats_cal.png) + +## Sorting by different factors[](#sorting-by-different-factors "Permalink") + +每个小组成员的贡献也以表格形式显示. 单击列标题以按该列对表进行排序: + +* 成员名字 +* 推送事件数 +* 未解决的问题数 +* 已解决的问题数 +* 已打开的 MR 数 +* 合并的 MR 数 +* 总捐款数 + +[![Contribution analytics contributions table](img/0a64287e1feef55413a5a906d02ec8ea.png)](img/group_stats_table.png) \ No newline at end of file diff --git a/docs/035.md b/docs/035.md new file mode 100644 index 0000000000000000000000000000000000000000..ea71ab10dc35940dbd6e790781ba94b2503d8aa6 --- /dev/null +++ b/docs/035.md @@ -0,0 +1,21 @@ +# Custom group-level project templates + +> 原文:[https://docs.gitlab.com/ee/user/group/custom_project_templates.html](https://docs.gitlab.com/ee/user/group/custom_project_templates.html) + +# Custom group-level project templates[](#custom-group-level-project-templates-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6861) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.6. + +创建新[项目时](../project/index.html) ,基于自定义项目模板创建它是一个方便的选择. + +用户可以在组的**"设置">"常规">"自定义项目模板"**下配置一个用作模板源的 GitLab 组. + +**注意:** GitLab 管理员可以[为整个 GitLab 实例设置项目模板](../admin_area/custom_project_templates.html) . + +在本部分中,您可以配置所有自定义项目模板的来源组. 如果用户有权访问组命名空间下的每个项目,则它们将对用户可用. 例如,组中的每个公共项目将对每个登录用户可用. + +但是,仅当用户是项目成员时,私人项目才可用. + +**注意:**只能将直接子组设置为模板源. 不能使用所选模板源的嵌套子组项目. + +复制到每个新项目的存储库和数据库信息与使用[GitLab 的项目导入/导出导出](../project/settings/import_export.html)的数据相同. \ No newline at end of file diff --git a/docs/036.md b/docs/036.md new file mode 100644 index 0000000000000000000000000000000000000000..c23acbabf862fe7d9ff5be19018a5e785959b379 --- /dev/null +++ b/docs/036.md @@ -0,0 +1,170 @@ +# Epics + +> 原文:[https://docs.gitlab.com/ee/user/group/epics/](https://docs.gitlab.com/ee/user/group/epics/) + +* [Use cases](#use-cases) +* [Manage epics](#manage-epics) +* [Relationships between epics and issues](#relationships-between-epics-and-issues) +* [Issue health status in Epic tree](#issue-health-status-in-epic-tree-ultimate) + * [Disable Issue health status in Epic tree](#disable-issue-health-status-in-epic-tree) +* [Multi-level child epics](#multi-level-child-epics-ultimate) +* [Start date and due date](#start-date-and-due-date) + * [From milestones](#from-milestones) + * [Inherited](#inherited) +* [Roadmap in epics](#roadmap-in-epics) +* [Permissions](#permissions) +* [Thread](#thread) +* [Comment or start a thread](#comment-or-start-a-thread) + * [Activity sort order](#activity-sort-order) +* [Award emoji](#award-emoji) +* [Notifications](#notifications) + +# Epics[](#epics-premium "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.2 中引入. +* 单级史诗在 12.8 [中移至](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) [GitLab Premium](https://about.gitlab.com/pricing/) . + +Epics 通过跟踪跨项目和里程碑共享主题的问题组,使您可以更有效,更轻松地管理项目组合. + +[![epics list view](img/bad7cd1d32a4bbf53fc1d27dcb3dd211.png)](img/epics_list_view_v12.5.png) + +## Use cases[](#use-cases "Permalink") + +* 假设您的团队正在研究一项大型功能,其中涉及在一个[小组](../index.html)内不同项目中创建的不同问题的多个讨论. 借助 Epics,您可以跟踪所有有助于该单一功能的相关活动. +* 跟踪何时针对该组问题开始工作,以及何时结束目标工作. +* 深入讨论和协作功能思想和范围. + +## Manage epics[](#manage-epics "Permalink") + +要了解您可以使用史诗功能,请参阅[管理史诗](manage_epics.html) . 可能的动作包括: + +* [Create an epic](manage_epics.html#create-an-epic) +* [Bulk-edit epics](../bulk_editing/index.html#bulk-edit-epics) +* [Delete an epic](manage_epics.html#delete-an-epic) +* [Close an epic](manage_epics.html#close-an-epic) +* [Reopen a closed epic](manage_epics.html#reopen-a-closed-epic) +* [Go to an epic from an issue](manage_epics.html#go-to-an-epic-from-an-issue) +* [Search for an epic from epics list page](manage_epics.html#search-for-an-epic-from-epics-list-page) +* [Make an epic confidential](manage_epics.html#make-an-epic-confidential) +* [Manage issues assigned to an epic](manage_epics.html#manage-issues-assigned-to-an-epic) +* [Manage multi-level child epics](manage_epics.html#manage-multi-level-child-epics-ultimate) + +## Relationships between epics and issues[](#relationships-between-epics-and-issues "Permalink") + +史诗与问题之间的可能关系是: + +* 史诗是一个或多个问题的父代. +* 史诗是一个或多个子史诗的父代. 有关详细信息,请参见[多级子史诗](#multi-level-child-epics-ultimate) . + +图 TD Parent_epic-> Issue1 Parent_epic-> Child_epic Child_epic-> Issue2 + +请参阅[管理分配给史诗](manage_epics.html#manage-issues-assigned-to-an-epic)的问题以获取将事件添加到史诗,重新排序问题,在史诗之间移动问题或将问题升级到史诗的步骤. + +## Issue health status in Epic tree[](#issue-health-status-in-epic-tree-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199184) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. + +您可以通过在问题上设置红色,琥珀色或绿色的[健康状态](../../project/issues/index.html#health-status-ultimate)来报告并快速响应单个问题和史诗的[健康](../../project/issues/index.html#health-status-ultimate) ,该状态将显示在史诗树上. + +### Disable Issue health status in Epic tree[](#disable-issue-health-status-in-epic-tree "Permalink") + +此功能带有默认情况下启用的功能标志. 有关禁用它的步骤,请参阅[禁用问题运行状况](../../project/issues/index.html#disable-issue-health-status) . + +## Multi-level child epics[](#multi-level-child-epics-ultimate "Permalink") + +在 GitLab Ultimate 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/8333) . + +属于父史诗组的一个组或子组的任何史诗都可以添加. 新的儿童史诗出现在" **史诗和问题"**选项卡中史诗列表的顶部. + +当您添加已链接到父级史诗的史诗时,到其当前父级的链接将被删除. + +An epic can have multiple child epics up to the maximum depth of five. + +请参阅[管理多级子级史诗](manage_epics.html#manage-multi-level-child-epics-ultimate) ,以了解创建,移动,重新排序或删除子[级史诗](manage_epics.html#manage-multi-level-child-epics-ultimate)的步骤. + +## Start date and due date[](#start-date-and-due-date "Permalink") + +要设置史诗的**开始日期**和**截止日期** ,请选择以下选项之一: + +* **固定** :输入固定值. +* **从里程碑** :从当前分配给史诗问题的里程碑继承动态值. 请注意,GitLab 12.5 用**Inherited**替换了此选项. +* **继承** :从史诗的问题,子史诗和里程碑继承动态值(在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7332) ,以代替**From 里程碑** ). + +### From milestones[](#from-milestones "Permalink") + +> 在 GitLab 12.5 中由**Inherited** [取代](https://gitlab.com/gitlab-org/gitlab/-/issues/7332) . + +如果您选择" **从里程碑**开始"作为开始日期,则 GitLab 会自动将日期设置为当前分配给添加到史诗中的问题的所有里程碑中最早的开始日期. 同样,如果您选择" **从里程碑** "作为截止日期,则 GitLab 会将其设置为当前分配给这些问题的所有里程碑中的最新截止日期. + +这些是动态日期,如果发生以下任何情况,将重新计算这些日期: + +* 将里程碑重新分配给这些问题. +* 里程碑日期更改. +* 从史诗中添加或删除问题. + +### Inherited[](#inherited "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7332)以替换**From 里程碑** . + +如果选择: + +* GitLab **继承**了开始日期,它将扫描所有子史诗和分配给该史诗的问题,并将开始日期设置为与找到的最早开始日期或里程碑相匹配. +* GitLab **继承**了截止日期,它将设置截止日期以匹配在其子史诗和问题中发现的最新截止日期或里程碑. + +这些是动态日期,如果发生以下任何情况,则重新计算: + +* 儿童史诗的日期发生了变化. +* 将里程碑重新分配给问题. +* 里程碑的日期会更改. +* 问题被添加到史诗中或从史诗中删除. + +由于史诗的日期可以从其子级继承日期,因此开始日期和到期日期从底部传播到顶部. 如果最低级别的子级史诗的开始日期发生更改(成为其父级史诗最早的开始日期),则父级史诗的开始日期将反映该更改,并将向上传播到顶部的史诗级. + +## Roadmap in epics[](#roadmap-in-epics "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7327) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.10. + +如果你的史诗包含一个或多个[孩子史诗](#multi-level-child-epics-ultimate)其中有一个[开始或到期日](#start-date-and-due-date) ,一个[路线图,](../roadmap/index.html)孩子史诗的观点是父史诗中列出. + +[![Child epics roadmap](img/35e89eba4dfc37f409cb295b0c8b13d1.png)](img/epic_view_roadmap_v12_9.png) + +## Permissions[](#permissions "Permalink") + +如果您有权查看史诗,并且有权查看已添加到该史诗的问题,则可以在史诗问题列表中查看该问题. + +如果您有权编辑史诗并且有权编辑问题,则可以将问题添加到史诗中或从史诗中删除. + +请注意,对于给定的组,所有项目的可见性必须与该组相同,或限制较少. 这意味着,如果您有权访问某个小组的史诗,那么您已经可以访问该小组的项目. + +您也可以查阅[组权限表](../../permissions.html#group-members-permissions) . + +## Thread[](#thread "Permalink") + +* 评论:通过在该史诗中的评论中发布评论来协作. 这些文本字段也完全支持[GitLab Flavored Markdown](../../markdown.html#gitlab-flavored-markdown-gfm) . + +## Comment or start a thread[](#comment-or-start-a-thread "Permalink") + +写下评论后,您可以: + +* 点击**评论** ,您的评论将被发布. +* 单击" **开始主题"** ,您将在该史诗般的讨论中开始一个主题. + +### Activity sort order[](#activity-sort-order "Permalink") + +[Introduced](https://https://gitlab.com/gitlab-org/gitlab/-/issues/214364) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + +您可以颠倒默认顺序,并与按顶部的最新项目排序的活动供稿进行交互. 您的首选项通过本地存储保存,并自动应用于您查看的每个问题. + +要更改活动排序顺序,请单击**最旧的第一个**下拉菜单,然后选择最旧或最新的项目以首先显示. + +[![Issue activity sort order dropdown button](img/806d03909b4b194f095b4c69e175868d.png)](img/epic_activity_sort_order_v13_2.png) + +## Award emoji[](#award-emoji "Permalink") + +您可以为该史诗或其评论[授予表情符号](../../award_emojis.html) . + +## Notifications[](#notifications "Permalink") + +您可以[打开通知](../../profile/notifications.html)以[通知](../../profile/notifications.html)史诗事件. \ No newline at end of file diff --git a/docs/037.md b/docs/037.md new file mode 100644 index 0000000000000000000000000000000000000000..d6a4bfbea536ececb2f63abc6e375043efda76cf --- /dev/null +++ b/docs/037.md @@ -0,0 +1,313 @@ +# Manage epics + +> 原文:[https://docs.gitlab.com/ee/user/group/epics/manage_epics.html](https://docs.gitlab.com/ee/user/group/epics/manage_epics.html) + +* [Create an epic](#create-an-epic) + * [Create an epic from the epic list](#create-an-epic-from-the-epic-list) + * [Access the New Epic form](#access-the-new-epic-form) + * [Elements of the New Epic form](#elements-of-the-new-epic-form) +* [Edit an epic](#edit-an-epic) +* [Bulk-edit epics](#bulk-edit-epics) +* [Delete an epic](#delete-an-epic) +* [Close an epic](#close-an-epic) +* [Reopen a closed epic](#reopen-a-closed-epic) +* [Go to an epic from an issue](#go-to-an-epic-from-an-issue) +* [Search for an epic from epics list page](#search-for-an-epic-from-epics-list-page) +* [Make an epic confidential](#make-an-epic-confidential) + * [Disable confidential epics](#disable-confidential-epics-premium-only) +* [Manage issues assigned to an epic](#manage-issues-assigned-to-an-epic) + * [Add an issue to an epic](#add-an-issue-to-an-epic) + * [Add an existing issue to an epic](#add-an-existing-issue-to-an-epic) + * [Create an issue from an epic](#create-an-issue-from-an-epic) + * [Remove an issue from an epic](#remove-an-issue-from-an-epic) + * [Reorder issues assigned to an epic](#reorder-issues-assigned-to-an-epic) + * [Move issues between epics](#move-issues-between-epics-ultimate) + * [Promote an issue to an epic](#promote-an-issue-to-an-epic) +* [Manage multi-level child epics](#manage-multi-level-child-epics-ultimate) + * [Add a child epic to an epic](#add-a-child-epic-to-an-epic) + * [Move child epics between epics](#move-child-epics-between-epics) + * [Reorder child epics assigned to an epic](#reorder-child-epics-assigned-to-an-epic) + * [Remove a child epic from a parent epic](#remove-a-child-epic-from-a-parent-epic) + +# Manage epics[](#manage-epics-premium "Permalink") + +该页面收集了有关[史诗](index.html)或与[史诗](index.html)有关的所有操作的说明. + +## Create an epic[](#create-an-epic "Permalink") + +每个组中都有史诗的分页列表,您可以从中创建新的史诗. 史诗列表还包括所选组中所有子组的史诗. 在您的论坛页面中: + +### Create an epic from the epic list[](#create-an-epic-from-the-epic-list "Permalink") + +要从史诗列表中创建史诗,请分组: + +1. 去 **史诗** . +2. Click **新史诗**. +3. 输入描述性标题. +4. Click **创造史诗**. + +### Access the New Epic form[](#access-the-new-epic-form "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211533) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + +有两种方法可以进入"新史诗"表格并在您所在的小组中创建史诗: + +* 在您小组的史诗中,点击**新建史诗** . +* 在任何地方的顶部菜单中,单击**加号** ( ) **>新史诗** . + + [![New epic from an open epic](img/4c0cef07da8190af4f517bd8d336cb5b.png)](img/new_epic_from_groups_v13.2.png) + +### Elements of the New Epic form[](#elements-of-the-new-epic-form "Permalink") + +在创建新的史诗时,您可以填写以下字段: + +* Title +* Description +* 保密性复选框 +* Labels +* 开始日期 +* 截止日期 + +[![New epic form](img/a48fc7b7ef95b54bd7ec66c17cad7dbb.png)](img/new_epic_form_v13.2.png) + +## Edit an epic[](#edit-an-epic "Permalink") + +创建史诗之后,可以编辑更改以下详细信息: + +* Title +* Description +* 开始日期 +* 截止日期 +* Labels + +编辑史诗的标题或说明: + +1. 点击**修改标题和说明** 按钮. +2. 进行更改. +3. Click **保存更改**. + +要编辑史诗的开始日期,截止日期或标签,请执行以下操作: + +1. 单击史诗侧边栏中每个部分旁边的" **编辑"** . +2. 选择日期或标签为您的史诗. + +## Bulk-edit epics[](#bulk-edit-epics "Permalink") + +您可以一次编辑多个史诗. 要了解操作方法,请访问[批量编辑问题,史诗和在组级别合并请求](../bulk_editing/index.html#bulk-edit-epics) . + +## Delete an epic[](#delete-an-epic "Permalink") + +**注意:**要删除史诗,您需要成为组/子组的[所有者](../../permissions.html#group-members-permissions) . + +编辑史诗的描述时,单击" **删除"**按钮以删除史诗. 出现一个模态来确认您的动作. + +删除史诗会从系统中与其关联的史诗中释放所有现有问题. + +## Close an epic[](#close-an-epic "Permalink") + +每当您决定不再需要该史诗时,请通过以下方法关闭该史诗: + +* 单击**关闭史诗**按钮. + + [![close epic - button](img/dce9a8c36e06896553bd80f313c3a756.png)](img/button_close_epic.png) + +* 使用[快速动作](../../project/quick_actions.html) . + +## Reopen a closed epic[](#reopen-a-closed-epic "Permalink") + +您可以重新打开因以下原因而关闭的史诗: + +* 单击**重新打开史诗**按钮. + + [![reopen epic - button](img/ed7d654fa8271709dfa6c567b48c5de6.png)](img/button_reopen_epic.png) + +* 使用[快速动作](../../project/quick_actions.html) . + +## Go to an epic from an issue[](#go-to-an-epic-from-an-issue "Permalink") + +如果问题属于史诗,则可以使用问题侧栏中的链接导航到包含该史诗. + +[![containing epic](img/8edd1cbf476ddc76f3df25fdeff8b55c.png)](img/containing_epic.png) + +## Search for an epic from epics list page[](#search-for-an-epic-from-epics-list-page "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.5 中引入. +* [已移至](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) GitLab 12.8 中的[Premium](https://about.gitlab.com/pricing/)层. + +您可以根据以下参数,使用过滤的搜索栏(类似于"问题和合并请求"的搜索栏)从史诗列表中搜索史诗: + +* 标题或说明 +* 作者名称/用户名 +* Labels + +[![epics search](img/c77b45147112088b7940cb4ebcc5f4a6.png)](img/epics_search.png) + +要进行搜索,请转到史诗列表,然后单击" **搜索或过滤结果** "字段. 它将显示一个下拉菜单,您可以从中添加一个作者. 您也可以输入纯文本以按史诗标题或描述进行搜索. 完成后,按键盘上的`Enter`键过滤列表. + +您还可以按以下方式对史诗列表进行排序: + +* 创建日期 +* 最近更新时间 +* 开始日期 +* 截止日期 + +每个选项都包含一个按钮,可以在**升序**和**降序**之间切换顺序. 无论您浏览史诗,包括" [路线图"](../roadmap/index.html) ,都可以保存和使用排序选项和顺序. + +[![epics sort](img/57b0d20488fb6cdd9ed2e8f573fcb7bb.png)](img/epics_sort.png) + +## Make an epic confidential[](#make-an-epic-confidential "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 13.0 中在功能标志后面[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/213068) ,默认情况下禁用. +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 13.2 中[默认启用](https://gitlab.com/gitlab-org/gitlab/-/issues/224513) . + +创建史诗时,可以选中**"将此史诗设为机密"**复选框,使其成为机密文件. + +### Disable confidential epics[](#disable-confidential-epics-premium-only "Permalink") + +机密史诗功能部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以为您的自我管理实例禁用它. + +禁用它: + +``` +Feature.disable(:confidential_epics) +``` + +## Manage issues assigned to an epic[](#manage-issues-assigned-to-an-epic "Permalink") + +### Add an issue to an epic[](#add-an-issue-to-an-epic "Permalink") + +您可以将现有问题添加到史诗中,也可以创建一个自动添加到史诗中的新问题. + +#### Add an existing issue to an epic[](#add-an-existing-issue-to-an-epic "Permalink") + +属于史诗组或史诗子组中任何项目的现有问题都可以添加到史诗中. 新添加的问题显示在" **史诗和问题"**选项卡中问题列表的顶部. + +史诗包含一个问题列表,一个问题最多可以与一个史诗相关联. 当您添加已链接到史诗的问题时,该问题会自动与其当前父级取消链接. + +要将问题添加到史诗中: + +1. 点击**添加**下拉按钮. +2. Click **添加问题**. +3. 使用以下两种方法之一确定要添加的问题: + * 粘贴问题的链接. + * 通过输入问题标题的一部分来搜索所需的问题,然后选择所需的匹配项(在[GitLab 12.5 中](https://gitlab.com/gitlab-org/gitlab/-/issues/9126)引入). + + 如果要添加多个问题,请按`空格键` ,然后重复此步骤. + +4. Click **Add**. + +#### Create an issue from an epic[](#create-an-issue-from-an-epic "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/5419) . + +从史诗中创建问题使您可以将注意力集中在史诗的更广泛的上下文上,同时将工作划分成较小的部分. + +要从史诗中创建问题: + +1. 在史诗页面上的" **史诗和问题"下** ,点击**添加**下拉按钮,然后选择**创建新问题** . +2. 在**标题下** ,输入新期刊的标题. +3. 从**项目**下拉列表中,选择应在其中创建问题的项目. +4. Click **创建问题**. + +### Remove an issue from an epic[](#remove-an-issue-from-an-epic "Permalink") + +在史诗的详细信息页面上时,可以从史诗中删除问题. 从史诗中删除问题后,该问题将不再与此史诗相关联. + +要从史诗中删除问题: + +1. 点击**删除** ( )按钮旁边要删除的问题. 出现**删除问题**警告. +2. Click **Remove**. + +[![List of issues assigned to an epic](img/8c47dc71d95554edf7da34adb5acc575.png)](img/issue_list_v13_1.png) + +### Reorder issues assigned to an epic[](#reorder-issues-assigned-to-an-epic "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9367) . + +新问题出现在" **史诗和问题"**选项卡中的列表顶部. 您可以通过拖动来重新排列问题列表. + +要重新分配分配给史诗的问题: + +1. 转到" **史诗和问题"**标签. +2. 将问题拖到所需的顺序. + +### Move issues between epics[](#move-issues-between-epics-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0. + +新问题出现在" **史诗和问题"**选项卡中的列表顶部. 您可以将问题从一部史诗转移到另一部史诗. + +要将问题移至另一个史诗: + +1. 转到" **史诗和问题"**标签. +2. 将问题拖到所需的父级史诗中. + +### Promote an issue to an epic[](#promote-an-issue-to-an-epic "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/3777) . +* 在 12.8 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) [GitLab Premium](https://about.gitlab.com/pricing/) . + +如果您具有关闭问题并在直接父组中创建史诗的必要[权限](../../permissions.html) ,则可以使用`/promote` [快速操作](../../project/quick_actions.html#quick-actions-for-issues-merge-requests-and-epics)将问题升级为史诗. 仅可以促进小组项目中的问题. 尝试提出机密问题时,将显示警告. 向史诗宣传机密问题将使与该问题相关的所有信息公开,因为史诗对小组成员是公开的. + +执行快速操作时: + +* 在与问题项目所在的组中创建一个史诗. +* 通知该问题的订户该史诗已创建. + +以下问题元数据将被复制到史诗中: + +* 标题,描述,活动/评论主题. +* Upvotes/downvotes. +* Participants. +* Group labels that the issue already has. + +## Manage multi-level child epics[](#manage-multi-level-child-epics-ultimate "Permalink") + +### Add a child epic to an epic[](#add-a-child-epic-to-an-epic "Permalink") + +要将儿童史诗添加到史诗中: + +1. 点击**添加**下拉按钮. +2. Click **添加史诗**. +3. 使用以下两种方法之一确定要添加的史诗: + * 粘贴史诗的链接. + * 通过输入史诗标题的一部分来搜索所需的问题,然后选择所需的匹配项(在[GitLab 12.5 中](https://gitlab.com/gitlab-org/gitlab/-/issues/9126)引入). + + 如果要添加多个史诗,请按`空格键`并重复此步骤. + +4. Click **Add**. + +### Move child epics between epics[](#move-child-epics-between-epics "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0. + +新的儿童史诗出现在" **史诗和问题"**选项卡中的列表顶部. 您可以将儿童史诗从一个史诗转移到另一个史诗. 当您添加已链接到父级史诗的史诗时,到其当前父级的链接将被删除. 问题和儿童史诗不能混在一起. + +要将儿童史诗移至另一史诗: + +1. 转到" **史诗和问题"**标签. +2. 将史诗拖到所需的父史诗中. + +### Reorder child epics assigned to an epic[](#reorder-child-epics-assigned-to-an-epic "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9367) . + +新的儿童史诗出现在" **史诗和问题"**选项卡中的列表顶部. 您可以对子史诗列表进行重新排序. + +要重新分配分配给史诗的子史诗: + +1. 转到" **史诗和问题"**标签. +2. 将史诗拖到所需的顺序. + +### Remove a child epic from a parent epic[](#remove-a-child-epic-from-a-parent-epic "Permalink") + +要从父级史诗中删除子级史诗: + +1. 单击父级史诗列表中的`x`按钮. +2. 在**删除史诗**警告消息,请单击**删除** . \ No newline at end of file diff --git a/docs/038.md b/docs/038.md new file mode 100644 index 0000000000000000000000000000000000000000..7fc538ab6cd4eacdc8ec641882de0be71e51269b --- /dev/null +++ b/docs/038.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/user/group/dependency_proxy/](https://docs.gitlab.com/ee/user/group/dependency_proxy/) \ No newline at end of file diff --git a/docs/039.md b/docs/039.md new file mode 100644 index 0000000000000000000000000000000000000000..06fa17a1ad60a16eb839d12a0c12542bcd4e9fb1 --- /dev/null +++ b/docs/039.md @@ -0,0 +1,126 @@ +# Group Import/Export + +> 原文:[https://docs.gitlab.com/ee/user/group/settings/import_export.html](https://docs.gitlab.com/ee/user/group/settings/import_export.html) + +* [Important Notes](#important-notes) + * [Exported Contents](#exported-contents) +* [Exporting a Group](#exporting-a-group) + * [Between CE and EE](#between-ce-and-ee) +* [Importing the group](#importing-the-group) +* [Version history](#version-history) +* [Rate Limits](#rate-limits) + +# Group Import/Export[](#group-importexport "Permalink") + +版本历史 + +* 在 GitLab 13.0 中作为实验功能[引入](https://gitlab.com/groups/gitlab-org/-/epics/2888) . 在将来的版本中可能会更改. + +可以将在任何 GitLab 实例或 GitLab.com 上运行的现有组及其所有相关数据导出,并移至新的 GitLab 实例. + +如果启用了组导入选项,则会显示**GitLab 导入/导出**按钮. + +也可以看看: + +* [Group Import/Export API](../../../api/group_import_export.html) +* [Project Import/Export](../../project/settings/import_export.html) +* [Project Import/Export API](../../../api/project_import_export.html) + +要启用 GitLab 导入/导出: + +1. 导航 **管理区>** **设置>可见性和访问控制** . +2. 滚动到**导入源** +3. 启用所需的**导入源** + +## Important Notes[](#important-notes "Permalink") + +请注意以下几点: + +* 导出存储在一个临时[共享目录中](../../../development/shared_files.html) ,并由特定工作人员每 24 小时删除一次. +* 要保留导入项目中的组级关系,请首先运行"组导入/导出",以允许将项目导入所需的组结构中. +* 除非导入到父组,否则将为导入的组提供`private`可见性级别. +* 如果导入父组,则除非另有限制,否则子组将继承相同级别的可见性. +* 若要保留成员列表及其对导入组的各自权限,请查看这些组中的用户. 在导入所需的组之前,请确保这些用户存在. + +### Exported Contents[](#exported-contents "Permalink") + +将导出以下项目: + +* Milestones +* Labels +* 董事会和董事会名单 +* Badges +* 子组(包括所有上述数据) +* Epics +* Events + +以下项目将不会导出: + +* Projects +* 跑步者令牌 +* SAML 发现令牌 + +**注意:**有关在组导出中[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/import_export/group/import_export.yml)的特定数据的更多详细信息,请参阅[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/import_export/group/import_export.yml)文件. + +## Exporting a Group[](#exporting-a-group "Permalink") + +1. 导航到您的论坛的主页. + +2. 请点击 侧栏中的**设置** . + +3. 在" **高级"**部分中,单击" **导出组"**按钮. + + [![Export group panel](img/222aa4a1e09c2312446d0aa324c6f193.png)](img/export_panel_v13_0.png) + +4. 生成导出后,您应该会收到一封电子邮件,其中包含指向压缩的 tar 存档中[导出内容](#exported-contents)的链接,其中的内容为 JSON 格式. + +5. 或者,您可以返回项目设置,然后点击**下载导出**从那里下载文件,或者点击**重新**生成导出来生成一个新文件. + +**注意:**可以由管理员设置最大导入文件大小,默认为 50MB. 作为管理员,您可以修改最大导入文件大小. 为此,请在" [应用程序设置" API](../../../api/settings.html#change-application-settings)或" [管理界面"中](../../admin_area/settings/account_and_limit_settings.html)使用`max_import_size`选项. + +### Between CE and EE[](#between-ce-and-ee "Permalink") + +您可以将组从[Community Edition](https://about.gitlab.com/install/ce-or-ee/)导出[到 Enterprise Edition](https://about.gitlab.com/install/ce-or-ee/) ,反之亦然. + +如果要将组从企业版导出到社区版,则可能会丢失仅保留在企业版中的数据. 有关更多信息,请参阅[从 EE 降级为 CE](../../../README.html) . + +## Importing the group[](#importing-the-group "Permalink") + +1. 通过顶部导航栏中的`+`按钮或现有组页面上的" **新建子组"**按钮导航到" **新建**组"页面. + + [![Navigation paths to create a new group](img/fad2df1fa4371b39b3ea1032a8ad236c.png)](img/new_group_navigation_v13_1.png) + +2. 在"新建组"页面上,选择" **导入组"**选项卡. + + [![Fill in group details](img/d15d948fc7d1b6e5c8dabacbe7c2fcc9.png)](img/import_panel_v13_1.png) + +3. 输入您的群组名称. + +4. 接受或修改关联的组 URL. + +5. Click **选择文件** + +6. 在" [导出组"](#exporting-a-group)部分中选择您导出的文件. + +7. 单击**导入组**开始导入. 您新导入的组页面将很快出现. + +## Version history[](#version-history "Permalink") + +GitLab 可以导入从其他 GitLab 部署导出的捆绑软件. 此功能仅限于之前的两个 GitLab [次要](../../../policy/maintenance.html#versioning)发行版,这与我们的[安全发布](../../../policy/maintenance.html#security-releases)流程类似. + +例如: + +| 当前版本 | 可以导入从 | +| --- | --- | +| 13.0 | 13.0, 12.10, 12.9 | +| 13.1 | 13.1, 13.0, 12.10 | + +## Rate Limits[](#rate-limits "Permalink") + +为了避免滥用,用户的速率仅限于: + +| 请求类型 | Limit | +| --- | --- | +| Export | 每 5 分钟 30 个小组 | +| 下载导出 | 每 10 分钟每组 10 次下载 | +| Import | 每 5 分钟 30 个小组 | \ No newline at end of file diff --git a/docs/040.md b/docs/040.md new file mode 100644 index 0000000000000000000000000000000000000000..54e39bd604217296cb2057b060bb627611933db5 --- /dev/null +++ b/docs/040.md @@ -0,0 +1,39 @@ +# Insights + +> 原文:[https://docs.gitlab.com/ee/user/group/insights/](https://docs.gitlab.com/ee/user/group/insights/) + +* [View your group’s Insights](#view-your-groups-insights) +* [Configure your Insights](#configure-your-insights) +* [Permissions](#permissions) + +# Insights[](#insights-ultimate "Permalink") + +[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. + +配置对您的团队重要的洞察力,以探索数据,例如分类诊断,在给定时间段内创建/关闭的问题,合并请求的平均时间等. + +[![Insights example stacked bar chart](img/9f4a21c247f193621ddd2f709c4536d7.png)](img/insights_example_stacked_bar_chart.png) + +## View your group’s Insights[](#view-your-groups-insights "Permalink") + +您可以通过点击左侧边栏中的**Analytics(分析)> Insights**链接来访问组的 Insights: + +[![Insights sidebar link](img/098a5864447e44da06b72051af59b294.png)](img/insights_sidebar_link_v12_8.png) + +## Configure your Insights[](#configure-your-insights "Permalink") + +导航到组的**"设置">"常规"** ,展开" **Insights"** ,然后选择包含`.gitlab/insights.yml`配置文件的项目: + +[![group insights configuration](img/6e3e1e9c7013cd330bcb6380ef19ddf9.png)](img/insights_group_configuration.png) + +如果未设置任何配置,将使用[默认配置文件](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/fixtures/insights/default.yml) . + +有关`.gitlab/insights.yml`配置文件的更多详细信息,请参见[Project 的 Insights 文档](../../project/insights/index.html) . + +## Permissions[](#permissions "Permalink") + +如果您有权查看组,则可以查看其见解. + +**注意:**您无法访问的问题或合并请求(因为您无法访问它们所属的项目,或者因为它们是机密的)会从 Insights 图表中过滤掉. + +您也可以查阅[组权限表](../../permissions.html#group-members-permissions) . \ No newline at end of file diff --git a/docs/041.md b/docs/041.md new file mode 100644 index 0000000000000000000000000000000000000000..584bc07c7d4c6615f2e6a02c184267c558919e5a --- /dev/null +++ b/docs/041.md @@ -0,0 +1,41 @@ +# Issues Analytics + +> 原文:[https://docs.gitlab.com/ee/user/group/issues_analytics/](https://docs.gitlab.com/ee/user/group/issues_analytics/) + +* [Drill into the information](#drill-into-the-information) + +# Issues Analytics[](#issues-analytics-premium "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7478) . +* 在项目级别的[GitLab Premium](https://about.gitlab.com/pricing/) 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/196561) . + +问题分析是一个条形图,用于说明每月创建的问题数. 默认时间跨度为 13 个月,其中包括当月以及之前的 12 个月. + +要访问图表,请导航至您的组或项目侧边栏,然后选择 **分析>问题分析** . + +将鼠标悬停在每个栏上可以查看总数. + +要缩小图中包含的问题的范围,请在" **搜索或过滤结果..."**字段中输入您的条件. 可以在以下列表中输入条件或从菜单中选择条件: + +* Author +* Assignee +* Milestone +* Label +* 我的反应 +* Weight + +您可以通过设置 URL 参数来更改显示的总月数. 例如, `https://gitlab.com/groups/gitlab-org/-/issues_analytics?months_back=15` //gitlab.com/groups/gitlab-org/-/issues_analytics?months_back `https://gitlab.com/groups/gitlab-org/-/issues_analytics?months_back=15` 15 显示 GitLab.org 组中图表的总计 15 个月. + +[![Issues created per month](img/7a1046341466c144b96bc573f0a16114.png)](img/issues_created_per_month_v12_8.png) + +## Drill into the information[](#drill-into-the-information "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/196547) . + +您可以通过浏览图表下方的表格来检查各个问题的详细信息. + +该图表显示基于全局页面筛选器的前 100 个问题. + +[![Issues table](img/c07889c4060a55eccd0e5dde9cb54f74.png)](img/issues_table_v13_1.png) \ No newline at end of file diff --git a/docs/042.md b/docs/042.md new file mode 100644 index 0000000000000000000000000000000000000000..97e3436b195b83a46bcb0e498eeb8881f14a7933 --- /dev/null +++ b/docs/042.md @@ -0,0 +1,80 @@ +# Iterations + +> 原文:[https://docs.gitlab.com/ee/user/group/iterations/](https://docs.gitlab.com/ee/user/group/iterations/) + +* [View the iterations list](#view-the-iterations-list) +* [Create an iteration](#create-an-iteration) +* [Edit an iteration](#edit-an-iteration) +* [Enable Iterations](#enable-iterations-core-only) + +# Iterations[](#iterations-starter "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214713) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上已禁用. +* 可以按组启用或禁用 +* 不建议将其用于生产. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-iterations-core-only) . + +迭代是跟踪一段时间内问题的一种方法. 这使团队可以跟踪速度和波动性指标. 迭代可与[里程碑](../../project/milestones/index.html)一起使用,以在不同时间段内进行跟踪. + +例如,您可以使用: + +* 计划递增的里程碑,跨越 8 到 12 周. +* Sprint 的迭代,历时 2 周. + +在 GitLab 中,迭代类似于里程碑,但有一些区别: + +* 迭代仅适用于组. +* 一组一次只能有一个活动的迭代. +* 迭代需要开始日期和结束日期. +* 迭代日期范围不能重叠. + +## View the iterations list[](#view-the-iterations-list "Permalink") + +要查看迭代列表,请分组访问 **问题>迭代** . 从那里您可以创建一个新的迭代或单击一个迭代以获得更详细的视图. + +## Create an iteration[](#create-an-iteration "Permalink") + +**注意:**您需要具有开发人员[权限](../../permissions.html)或更高[权限](../../permissions.html)才能创建迭代. + +要创建迭代: + +1. 在一个小组中,转到 **问题>迭代** . +2. Click **新迭代**. +3. 输入标题,描述(可选),开始日期和截止日期. +4. 单击**创建迭代** . 将打开"迭代详细信息"页面. + +## Edit an iteration[](#edit-an-iteration "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/218277) . + +**注意:**您需要开发者[权限](../../permissions.html)或更高[权限](../../permissions.html)才能编辑迭代. + +要编辑迭代,请点击三点菜单( )> **编辑迭代** . + +## Enable Iterations[](#enable-iterations-core-only "Permalink") + +GitLab 迭代功能正在开发中,尚未准备好用于生产. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以为您的实例启用它. `:group_iterations`可以按组启用或禁用. + +要启用它: + +``` +# Instance-wide +Feature.enable(:group_iterations) +# or by group +Feature.enable(:group_iterations, Group.find()) +``` + +禁用它: + +``` +# Instance-wide +Feature.disable(:group_iterations) +# or by group +Feature.disable(:group_iterations, Group.find()) +``` \ No newline at end of file diff --git a/docs/043.md b/docs/043.md new file mode 100644 index 0000000000000000000000000000000000000000..96a59ace35118b558e42f468376c894322c387bf --- /dev/null +++ b/docs/043.md @@ -0,0 +1,89 @@ +# Public access + +> 原文:[https://docs.gitlab.com/ee/public_access/public_access.html](https://docs.gitlab.com/ee/public_access/public_access.html) + +* [Visibility of projects](#visibility-of-projects) + * [Public projects](#public-projects) + * [Internal projects](#internal-projects) + * [Private projects](#private-projects) + * [How to change project visibility](#how-to-change-project-visibility) +* [Visibility of groups](#visibility-of-groups) +* [Visibility of users](#visibility-of-users) +* [Visibility of pages](#visibility-of-pages) +* [Restricting the use of public or internal projects](#restricting-the-use-of-public-or-internal-projects) +* [Reducing visibility](#reducing-visibility) + +# Public access[](#public-access "Permalink") + +GitLab 允许[所有者](../user/permissions.html)将项目的可见性设置为**public** , **internal**或**private** . 这些可见性级别会影响谁可以在公共访问目录(GitLab 实例下的`/public` )中查看项目,例如[https://gitlab.com/public](https://gitlab.com/public) + +## Visibility of projects[](#visibility-of-projects "Permalink") + +### Public projects[](#public-projects "Permalink") + +可以克隆公共项目, **而无需**通过 HTTPS **进行任何**身份验证. + +它们将在所有用户的公共访问目录( `/public` )中列出. + +**任何登录的用户**都将对存储库具有[来宾权限](../user/permissions.html) . + +### Internal projects[](#internal-projects "Permalink") + +任何登录用户都可以克隆内部项目. + +它们也将列在公共访问目录( `/public` )中,但仅适用于登录用户. + +任何登录的用户都将对存储库具有[来宾权限](../user/permissions.html) . + +**注意:**从 2019 年 7 月开始,GitLab.com 上的新项目,组和摘要的`` `Internal`可见性''设置被禁用. 使用" `Internal`可见性"设置的现有项目,组和摘录保留此设置. 您可以在[相关问题中](https://gitlab.com/gitlab-org/gitlab/-/issues/12388)阅读有关更改的更多信息. + +### Private projects[](#private-projects "Permalink") + +私人项目只能由项目成员(来宾除外)克隆和查看. + +它们将仅出现在项目成员的公共访问目录( `/public` )中. + +### How to change project visibility[](#how-to-change-project-visibility "Permalink") + +1. 转到项目的**"设置"** . +2. 将**可见性级别**更改为公共,内部或私有. + +## Visibility of groups[](#visibility-of-groups "Permalink") + +**注意:** [从](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3323) GitLab 8.6 [开始](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3323) ,组的可见性已更改,并且可以与项目相同的方式进行配置. 在以前的版本中,组页面始终对所有用户可见. + +与项目一样,可以设置组的可见性来决定匿名用户,所有登录用户还是仅显式组成员可以查看它. 应用程序设置级别对可见性级别的限制也适用于组,因此,如果将其设置为内部,则匿名用户的浏览页面将为空. 现在,组页面上有一个可见性级别图标. + +管理员用户不能创建具有比直接父组更高的可见性级别的子组或项目. + +## Visibility of users[](#visibility-of-users "Permalink") + +无论您是否登录,位于`/username`的用户公共页面始终可见. + +当访问用户的公共页面时,您只能看到您有权访问的项目. + +如果公共级别受到限制,则用户配置文件仅对登录用户可见. + +## Visibility of pages[](#visibility-of-pages "Permalink") + +默认情况下,以下目录对未经身份验证的用户可见: + +* 公共访问( `/public` ). +* 探索( `/explore` ). +* 帮助( `/help` ). + +但是,如果`/public`目录的访问级别受到限制,则这些目录仅对登录用户可见. + +## Restricting the use of public or internal projects[](#restricting-the-use-of-public-or-internal-projects "Permalink") + +您可以限制用户在创建项目或代码段时对可见性级别的使用. 这有助于防止用户意外公开其存储库. 受限的可见性设置不适用于管理员用户. + +有关详细信息,请参阅[受限可见性级别](../user/admin_area/settings/visibility_and_access_controls.html#restricted-visibility-levels) . + +## Reducing visibility[](#reducing-visibility "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33358) . + +降低项目的可见性级别将删除该项目与任何分叉项目之间的派生关系. 这是一种潜在的破坏性操作,需要先确认才能保存. + +[![Project visibility change confirmation](img/17abb300a15db5073a41bf8a13e53bc7.png)](img/project_visibility_confirmation_v12_6.png) \ No newline at end of file diff --git a/docs/044.md b/docs/044.md new file mode 100644 index 0000000000000000000000000000000000000000..9c2048ad575dc9ae3be87b64b9860c7fe77f04f3 --- /dev/null +++ b/docs/044.md @@ -0,0 +1,403 @@ +# SAML SSO for GitLab.com groups + +> 原文:[https://docs.gitlab.com/ee/user/group/saml_sso/](https://docs.gitlab.com/ee/user/group/saml_sso/) + +* [Configuring your Identity Provider](#configuring-your-identity-provider) + * [NameID](#nameid) + * [NameID Format](#nameid-format) + * [Metadata configuration](#metadata-configuration) +* [Configuring GitLab](#configuring-gitlab) + * [SSO enforcement](#sso-enforcement) +* [Providers](#providers) + * [Azure setup notes](#azure-setup-notes) + * [Okta setup notes](#okta-setup-notes) + * [OneLogin setup notes](#onelogin-setup-notes) + * [Additional providers and setup options](#additional-providers-and-setup-options) +* [User access and management](#user-access-and-management) + * [Linking SAML to your existing GitLab.com account](#linking-saml-to-your-existing-gitlabcom-account) + * [Signing in to GitLab.com with SAML](#signing-in-to-gitlabcom-with-saml) + * [Role](#role) + * [Blocking access](#blocking-access) + * [Unlinking accounts](#unlinking-accounts) +* [Glossary](#glossary) +* [Configuring on a self-managed GitLab instance](#configuring-on-a-self-managed-gitlab-instance-premium-only) + * [Limitations](#limitations) + * [Omnibus installations](#omnibus-installations) + * [Source installations](#source-installations) +* [Troubleshooting](#troubleshooting) + * [SAML debugging tools](#saml-debugging-tools) + * [Verifying configuration](#verifying-configuration) + * [Verifying NameID](#verifying-nameid) + * [Message: “SAML authentication failed: Extern uid has already been taken”](#message-saml-authentication-failed-extern-uid-has-already-been-taken) + * [Message: “SAML authentication failed: User has already been taken”](#message-saml-authentication-failed-user-has-already-been-taken) + * [Message: “SAML authentication failed: Email has already been taken”](#message-saml-authentication-failed-email-has-already-been-taken) + * [Message: “SAML authentication failed: Extern uid has already been taken, User has already been taken”](#message-saml-authentication-failed-extern-uid-has-already-been-taken-user-has-already-been-taken) + * [Message: “Request to link SAML account must be authorized”](#message-request-to-link-saml-account-must-be-authorized) + * [Stuck in a login “loop”](#stuck-in-a-login-loop) + * [The NameID has changed](#the-nameid-has-changed) + * [I need to change my SAML app](#i-need-to-change-my-saml-app) + * [I need additional information to configure my identity provider](#i-need-additional-information-to-configure-my-identity-provider) + +# SAML SSO for GitLab.com groups[](#saml-sso-for-gitlabcom-groups-premium "Permalink") + +在 GitLab 11.0 中引入. + +此页面描述了组的 SAML. 有关自我管理的 GitLab 实例上的实例范围内的 SAML,请参阅[SAML OmniAuth Provider](../../../integration/saml.html) . + +GitLab.com 上的 SAML 允许用户通过其 SAML 身份提供商进行登录. 如果用户还不是成员,则登录过程会自动将用户添加到适当的组. + +如果您遵循我们的指导以使用[SCIM](scim_setup.html)或[组管理的帐户](group_managed_accounts.html)自动执行用户配置,则无需手动创建此类帐户. + +通过[SCIM](scim_setup.html)支持 SAML SSO 组的用户同步. SCIM 支持在 GitLab 组中添加和删除用户. 例如,如果您从 SCIM 应用程序中删除用户,则 SCIM 将从 GitLab 组中删除该用户. + +## Configuring your Identity Provider[](#configuring-your-identity-provider "Permalink") + +1. 导航到该组,然后单击**设置> SAML SSO** . +2. 使用**Assertion 使用者服务 URL** , **Identifier**和**GitLab 单一登录** **URL**来配置 SAML 服务器. 另外,GitLab 还提供[元数据 XML 配置](#metadata-configuration) . 有关更多详细信息,请参见[特定的身份提供者文档](#providers) . +3. 配置 SAML 响应以包括唯一标识每个用户的 NameID. +4. 如果使用[组托管帐户,请](group_managed_accounts.html)配置[必需的断言](group_managed_accounts.html#assertions) . +5. 设置身份提供者后,继续[配置 GitLab](#configuring-gitlab) . + +[![Issuer and callback for configuring SAML identity provider with GitLab.com](img/ebc54b5fdcb529ff40d6d097098188ae.png)](img/group_saml_configuration_information.png) + +### NameID[](#nameid "Permalink") + +GitLab.com 使用 SAML NameID 来识别用户. NameID 元素: + +* 是 SAML 响应中的必填字段. +* 每个用户必须唯一. +* 必须是永久不变的值,例如随机生成的唯一用户 ID. +* 区分大小写. NameID 必须在随后的登录尝试中完全匹配,因此不应依赖可能在大小写之间变化的用户输入. +* 不应是电子邮件地址或用户名. 我们强烈建议您反对这些,因为很难保证它们永远不会改变,例如当一个人的名字改变时. 电子邮件地址也不区分大小写,这可能导致用户无法登录. + +支持的提供程序的相关字段名称和建议值在[提供程序特定的注释中](#providers) . 适当的相应字段. + +**警告:**用户使用 SSO SAML 设置登录到 GitLab 后,更改`NameID`将破坏配置,并有可能将用户锁定在 GitLab 组之外. + +#### NameID Format[](#nameid-format "Permalink") + +我们建议将 NameID 格式设置为`Persistent`除非使用要求其他格式的字段(例如电子邮件). + +### Metadata configuration[](#metadata-configuration "Permalink") + +GitLab 提供了可用于配置身份提供者的元数据 XML. + +1. 导航到该组,然后单击**设置> SAML SSO** . +2. 复制提供的**GitLab 元数据 URL** . +3. 请遵循身份提供者的文档,并在请求时粘贴元数据 URL. + +## Configuring GitLab[](#configuring-gitlab "Permalink") + +设置好身份提供程序以与 GitLab 一起使用后,您需要配置 GitLab 以使用它进行身份验证: + +1. 导航到组的**"设置">" SAML SSO"** . +2. 从您的身份提供者中找到 SSO URL,然后在**身份提供者单点登录 URL**字段中输入 SSO URL. +3. 在" **证书"**字段中找到并输入 SAML 令牌签名证书的指纹. +4. 单击" **为此组启用 SAML 身份验证"**切换开关. +5. 点击**保存更改**按钮. + +[![Group SAML Settings for GitLab.com](img/6ea99225391da160a92dd9fd1fb01cd7.png)](img/group_saml_settings.png) + +**注意:**请注意,证书[指纹算法](#additional-providers-and-setup-options)必须在 SHA1 中. 配置身份提供者时,请使用安全签名算法. + +### SSO enforcement[](#sso-enforcement "Permalink") + +* 在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/5291) . +* 在 GitLab 11.11 中进行了[改进](https://gitlab.com/gitlab-org/gitlab/-/issues/9255) ,并在 GitLab UI 中不断实施. + +启用此选项后,用户必须浏览您组的 GitLab 单一登录 URL. 如果已配置,也可以通过 SCIM 添加它们. 无法手动添加用户,只能通过 UI 通过 SSO URL 登录来访问项目/组资源. + +但是,每次访问时都不会提示用户通过 SSO 登录. GitLab 将检查用户是否已通过 SSO 进行身份验证,并且仅在会话过期时提示用户通过 SSO 登录. + +我们打算为[Git 和 API 活动](https://gitlab.com/gitlab-org/gitlab/-/issues/9152)添加类似的 SSO 要求. + +为组启用 SSO 强制后,即使分叉了项目,用户也无法在顶级组之外的组中共享项目. + +要禁止用户在顶级组之外进行贡献,请参阅" [组管理帐户"](group_managed_accounts.html) . + +## Providers[](#providers "Permalink") + +**注意:** GitLab 无法为未在此处列出的 IdP 提供支持. + +| Provider | Documentation | +| --- | --- | +| ADFS(Active Directory 联合身份验证服务) | [Create a Relying Party Trust](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust) | +| Azure | [Configuring single sign-on to applications](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/configure-single-sign-on-non-gallery-applications) | +| Okta | [Setting up a SAML application in Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/) | +| OneLogin | [Use the OneLogin SAML Test Connector](https://onelogin.service-now.com/support?id=kb_article&sys_id=93f95543db109700d5505eea4b96198f) | + +在[配置标识提供程序时](#configuring-your-identity-provider) ,请考虑以下有关特定提供程序的注意事项,以帮助避免常见问题,并作为所用术语的指南. + +### Azure setup notes[](#azure-setup-notes "Permalink") + +有关包括 SCIM 在内的 Azure SAML 设置的演示,请参阅《 [使用针对组的 SAML SSO 的 Azure 上的 SCIM 置备》演示](https://youtu.be/24-ZxmTeEBU) . + +| 亚搏体育 app 设置 | 蔚蓝领域 | +| --- | --- | +| Identifier | 标识符(实体 ID) | +| 断言消费者服务 URL | 回复 URL(断言消费者服务 URL) | +| GitLab 单一登录 URL | 登录 URL | +| 身份提供者单点登录 URL | 登录网址 | +| 证书指纹 | Thumbprint | + +我们推荐: + +* **唯一用户标识符(名称标识符)**设置为`user.objectID` . +* **nameid-format**设置为持久. + +### Okta setup notes[](#okta-setup-notes "Permalink") + +有关 Okta SAML 设置(包括 SCIM)的[演示](https://youtu.be/0ES9HsZq0AQ) ,请参见[演示:Okta Group SAML 和 SCIM 设置](https://youtu.be/0ES9HsZq0AQ) . + +| 亚搏体育 app 设置 | Okta 场 | +| --- | --- | +| Identifier | 目标对象 URI | +| 断言消费者服务 URL | 单一登录网址 | +| GitLab 单一登录 URL | 登录页面 URL(在" **应用程序登录页面"**设置下) | +| 身份提供者单点登录 URL | 身份提供者单一登录 URL | + +在 Okta 的" **单一登录 URL"**字段下,选中" **将此用于收件人 URL 和目标 URL** "选项. + +我们推荐: + +* **应用程序用户名** (NameID)设置为**Custom** `user.getInternalProperty("id")` . +* **名称 ID 格式**设置为**Persistent** . + +### OneLogin setup notes[](#onelogin-setup-notes "Permalink") + +OneLogin 应用目录中列出的 GitLab 应用适用于自我管理的 GitLab 实例. 对于 GitLab.com,请使用通用 SAML 测试连接器,例如 SAML 测试连接器(高级). + +| 亚搏体育 app 设置 | OneLogin Field | +| --- | --- | +| Identifier | Audience | +| 断言消费者服务 URL | Recipient | +| 断言消费者服务 URL | ACS(消费者)网址 | +| 断言消费者服务 URL(转义版本) | ACS(消费者)URL 验证器 | +| GitLab 单一登录 URL | 登录网址 | +| 身份提供者单点登录 URL | SAML 2.0 端点 | + +Recommended `NameID` value: `OneLogin ID`. + +### Additional providers and setup options[](#additional-providers-and-setup-options "Permalink") + +SAML 标准意味着广泛的身份提供者将与 GitLab 一起使用. 不幸的是,我们尚未验证与所有 SAML 提供程序的连接. 有关更多信息,请参见[关于提供程序](#providers)的[讨论](#providers) . + +您的身份提供者可能具有相关的文档. 它可能是通用的 SAML 文档,也可能是专门针对 GitLab 的. 例子: + +* [Auth0](https://auth0.com/docs/protocols/saml/saml-idp-generic) +* [G Suite](https://support.google.com/a/answer/6087519?hl=en) +* [JumpCloud](https://support.jumpcloud.com/support/s/article/single-sign-on-sso-with-gitlab-2019-08-21-10-36-47) +* [PingOne by Ping Identity](https://docs.pingidentity.com/bundle/pingone/page/xsh1564020480660-1.html) + +您的身份提供商可能需要其他配置,例如: + +| Field | Value | Notes | +| --- | --- | --- | +| SAML 配置文件 | Web 浏览器 SSO 配置文件 | GitLab 使用 SAML 通过用户的浏览器登录. 我们不会直接向身份提供者发出请求. | +| SAML 请求绑定 | HTTP 重定向 | GitLab(服务提供商)使用 base64 编码的`SAMLRequest` HTTP 参数将用户重定向到您的身份提供商. | +| SAML 响应绑定 | HTTP POST | 您的身份提供者使用 HTTP 表单(包括`SAMLResponse`响应用户,该表单由用户的浏览器提交回 GitLab. | +| 签署 SAML 回应 | Yes | 我们要求这样做以防止篡改. | +| X.509 证书作为回应 | Yes | 这用于签署响应并对照提供的指纹进行检查. | +| 指纹算法 | SHA-1 | 我们需要用于签名 SAML 响应的证书的 SHA-1 哈希. | +| 签名算法 | SHA-1/SHA-256/SHA-384/SHA-512 | 也称为摘要方法,可以在 SAML 响应中指定此方法. 它确定响应的签名方式. | +| 加密 SAML 断言 | No | 在您的身份提供者,用户的浏览器和 GitLab 之间使用 TLS. | +| 签署 SAML 声明 | Optional | 我们不需要签署声明. 我们要求签署完整的回复以验证其完整性. | +| 检查 SAML 请求签名 | No | GitLab 不会对 SAML 请求进行签名,但是会检查 SAML 响应上的签名. | +| 默认 RelayState | Optional | 通过身份提供者上的按钮登录后,URL 用户应最终打开. | +| NameID 格式 | `Persistent` | See [details above](#nameid-format). | +| 其他网址 |   | 您可能需要在某些提供程序的其他字段中使用" `Identifier`或" `Assertion consumer service URL` . | +| 单一登出网址 |   | 不支持 | + +如果上面没有列出您需要的信息,则不妨查看[下面](#i-need-additional-information-to-configure-my-identity-provider)的[故障排除文档](#i-need-additional-information-to-configure-my-identity-provider) . + +## User access and management[](#user-access-and-management "Permalink") + +一旦配置并启用了 Group SSO,用户就可以通过身份提供商的仪表板访问 GitLab.com 组. 如果配置了[SCIM](scim_setup.html) ,请参阅[SCIM 页面上的](scim_setup.html#user-access-and-linking-setup) " [用户访问和链接设置"部分](scim_setup.html#user-access-and-linking-setup) . + +当用户尝试使用 Group SSO 登录时,他们将需要一个配置了以下内容之一的帐户: + +* [SCIM](scim_setup.html). +* [Group-managed accounts](group_managed_accounts.html). +* 一个 GitLab.com 帐户. + +### Linking SAML to your existing GitLab.com account[](#linking-saml-to-your-existing-gitlabcom-account "Permalink") + +要将 SAML 链接到您现有的 GitLab.com 帐户: + +1. 登录到您的 GitLab.com 帐户. +2. 找到并访问您要登录的组的**GitLab 单一登录 URL** . 群组管理员可以在群组的**"设置">" SAML SSO"**页面上找到此内容. 如果配置了登录 URL,则用户可以从身份提供者连接到 GitLab 应用. +3. Click **Authorize**. +4. 如果出现提示,请在身份提供者上输入您的凭据. +5. 您将被重定向回 GitLab.com,现在应该可以访问该组了. 将来,您可以使用 SAML 登录到 GitLab.com. + +在随后的访问中,您应该能够[使用 SAML](#signing-in-to-gitlabcom-with-saml)或直接访问链接来[登录 GitLab.com](#signing-in-to-gitlabcom-with-saml) . 如果**强制 SSO**选项已打开,您将被重定向到通过身份提供者登录. + +### Signing in to GitLab.com with SAML[](#signing-in-to-gitlabcom-with-saml "Permalink") + +1. 登录到您的身份提供商. +2. 从应用程序列表中,单击" GitLab.com"应用程序(名称由身份提供者的管理员设置). +3. 您将登录到 GitLab.com,并重定向到该组. + +### Role[](#role "Permalink") + +首次登录时,GitLab 会将您添加到具有 Guest 角色的顶级父组中. 具有适当特权的现有成员可以提升该新用户. + +如果用户已经是组的成员,则链接 SAML 身份不会更改其角色. + +### Blocking access[](#blocking-access "Permalink") + +要取消对该组的访问,请按顺序执行以下步骤: + +1. 从身份提供者上的用户数据存储中删除用户,或从特定应用程序上的用户列表中删除用户. +2. 从 GitLab.com 组中删除用户. + +### Unlinking accounts[](#unlinking-accounts "Permalink") + +用户可以从其个人资料页面取消链接组的 SAML. 在以下情况下这可能会有所帮助: + +* 您不再希望某个群组能够登录 GitLab.com. +* 您的 SAML NameID 已更改,因此 GitLab 无法再找到您的用户. + +例如,要取消链接`MyOrg`帐户,以下" **断开连接"**按钮将在" **配置文件">"帐户"**下可用: + +[![Unlink Group SAML](img/b203ae7a973815c03ea680032d1e75eb.png)](img/unlink_group_saml.png) + +## Glossary[](#glossary "Permalink") + +| Term | Description | +| --- | --- | +| 身份提供者 | 管理您的用户身份的服务,例如 ADFS,Okta,Onelogin 或 Ping 身份. | +| 服务提供者 | SAML 认为 GitLab 是服务提供商. | +| Assertion | 有关用户身份的一条信息,例如他们的姓名或角色. 也称为声明或属性. | +| SSO | 单一登录. | +| 断言消费者服务 URL | 在 GitLab 上的回调,在通过身份提供商成功进行身份验证后,将重定向用户. | +| Issuer | manbetx 客户端打不开如何向身份提供商识别自己. 也称为"信赖方信任标识符". | +| 证书指纹 | 用于通过检查服务器是否使用正确的证书对通信进行签名来确认通过 SAML 进行的通信是否安全. 也称为证书指纹. | + +## Configuring on a self-managed GitLab instance[](#configuring-on-a-self-managed-gitlab-instance-premium-only "Permalink") + +对于自我管理的 GitLab 实例,我们强烈建议改用[实例范围的 SAML OmniAuth Provider](../../../integration/saml.html) . + +如果您需要允许通过多个 SAML 身份提供者进行访问,Group SAML SSO 可以提供帮助,但是作为多租户解决方案,它不太适合您管理自己的 GitLab 实例的情况. + +要改为继续配置 Group SAML SSO,您需要启用`group_saml` OmniAuth 提供程序. 这可以通过以下方式完成: + +* `gitlab.rb`用于 GitLab [Omnibus 安装](#omnibus-installations) . +* `gitlab/config/gitlab.yml` for [source installations](#source-installations). + +### Limitations[](#limitations "Permalink") + +与建议的[实例范围的 SAML](../../../integration/saml.html)相比,自管理实例上的组 SAML 受到限制. 推荐的解决方案使您可以利用: + +* [LDAP compatibility](../../../administration/auth/ldap/index.html). +* [LDAP Group Sync](../index.html#manage-group-memberships-via-ldap). +* [Required groups](../../../integration/saml.html#required-groups-starter-only). +* [Admin groups](../../../integration/saml.html#admin-groups-starter-only). +* [Auditor groups](../../../integration/saml.html#auditor-groups-starter-only). + +### Omnibus installations[](#omnibus-installations "Permalink") + +1. 确保为 GitLab [配置了 HTTPS](../../../install/installation.html#using-https) . +2. 启用 OmniAuth 和`group_saml`在提供`gitlab.rb` : + + ``` + gitlab_rails['omniauth_enabled'] = true + gitlab_rails['omniauth_providers'] = [{ name: 'group_saml' }] + ``` + +### Source installations[](#source-installations "Permalink") + +1. 确保为 GitLab [配置了 HTTPS](../../../install/installation.html#using-https) . +2. 在`gitlab/config/gitlab.yml`启用 OmniAuth 和`group_saml`提供程序: + + ``` + omniauth: + enabled: true + providers: + - { name: 'group_saml' } + ``` + +## Troubleshooting[](#troubleshooting "Permalink") + +本节包含可能遇到的问题的可能解决方案. + +### SAML debugging tools[](#saml-debugging-tools "Permalink") + +SAML 响应是 base64 编码的,因此我们建议使用以下浏览器插件即时对其进行解码: + +* [SAML tracer for Firefox](https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/) +* [Chrome SAML Panel](https://chrome.google.com/webstore/detail/saml-chrome-panel/paijfdbeoenhembfhkhllainmocckace?hl=en) + +应特别注意: + +* [NameID](#nameid) (我们用来标识正在登录的用户).如果该用户先前已登录,则该[ID 必须与我们存储的值匹配](#verifying-nameid) . +* `X509Certificate`的存在,我们需要使用它来验证响应签名. +* `SubjectConfirmation`和`Conditions` ,如果配置错误,可能会导致错误. + +### Verifying configuration[](#verifying-configuration "Permalink") + +For convenience, we’ve included some [example resources](../../../administration/troubleshooting/group_saml_scim.html) used by our Support Team. While they may help you verify the SAML app configuration, they are not guaranteed to reflect the current state of third-party products. + +### Verifying NameID[](#verifying-nameid "Permalink") + +在对组 SAML 设置进行故障排除时,任何经过身份验证的用户都可以通过访问[https://gitlab.com/api/v4/user](https://gitlab.com/api/v4/user)并检查身份下的`extern_uid`来使用 API​​来验证 NameID GitLab 是否已链接到该用户. + +同样,具有适当权限的角色的组成员可以使用[成员 API](../../../api/members.html)来查看该组成员的组 SAML 身份信息. + +然后可以通过使用[SAML 调试工具](#saml-debugging-tools)解码消息,将其与身份提供者发送的[NameID](#nameid)进行比较. 我们要求这些匹配项以识别用户. + +### Message: “SAML authentication failed: Extern uid has already been taken”[](#message-saml-authentication-failed-extern-uid-has-already-been-taken "Permalink") + +此错误表明您已以 GitLab 用户身份登录,但已将 SAML 身份链接到其他 GitLab 用户. 退出,然后尝试使用 SSO SAML 链接再次登录,该链接应使用链接的用户帐户将您登录到 GitLab. + +如果您不希望通过 SAML 登录使用该 GitLab 用户,则可以[取消 GitLab 帐户与该组的 SAML 的链接](#unlinking-accounts) . + +### Message: “SAML authentication failed: User has already been taken”[](#message-saml-authentication-failed-user-has-already-been-taken "Permalink") + +与您登录的用户已经将 SAML 链接到另一个身份. 以下是可能的原因和解决方案: + +| Cause | Solution | +| --- | --- | +| You’ve tried to link multiple SAML identities to the same user, for a given Identity Provider. | 更改用于登录的身份. 为此,请先从此 GitLab 帐户[取消链接先前的 SAML 身份](#unlinking-accounts) ,然后再尝试登录. | + +### Message: “SAML authentication failed: Email has already been taken”[](#message-saml-authentication-failed-email-has-already-been-taken "Permalink") + +| Cause | Solution | +| --- | --- | +| 当具有电子邮件地址的用户帐户已经存在于 GitLab 中时,但该用户没有绑定到其帐户的 SAML 身份. | 用户将需要[链接他们的帐户](#user-access-and-management) . | + +### Message: “SAML authentication failed: Extern uid has already been taken, User has already been taken”[](#message-saml-authentication-failed-extern-uid-has-already-been-taken-user-has-already-been-taken "Permalink") + +同时获得这两个错误表明,身份提供者提供的 NameID 大写字母与该用户的先前值不完全匹配. + +可以通过配置[NameID](#nameid)返回一致的值来防止这种情况. 为单个用户解决此问题涉及[取消 GitLab 帐户中的 SAML 链接](#unlinking-accounts) ,尽管这将导致组成员身份和 Todos 丢失. + +### Message: “Request to link SAML account must be authorized”[](#message-request-to-link-saml-account-must-be-authorized "Permalink") + +确保尝试链接其 GitLab 帐户的用户已添加为身份提供者的 SAML 应用中的用户. + +### Stuck in a login “loop”[](#stuck-in-a-login-loop "Permalink") + +确保在身份提供者的 SAML 应用中将**GitLab 单一登录 URL**配置为"登录 URL"(或类似命名的字段). + +另外,当用户需要[将 SAML 链接到其现有的 GitLab.com 帐户时](#linking-saml-to-your-existing-gitlabcom-account) ,请提供**GitLab 单一登录 URL,**并指示用户不要在首次登录时使用 SAML 应用. + +### The NameID has changed[](#the-nameid-has-changed "Permalink") + +| Cause | Solution | +| --- | --- | +| 如[NameID](#nameid)部分所述,如果 NameID 对于任何用户都发生了更改,则可以将用户锁定. 当电子邮件地址用作标识符时,这是一个常见问题. | 请按照[" SAML 身份验证失败:用户已被使用"](#message-saml-authentication-failed-user-has-already-been-taken)部分中概述的步骤进行操作. 如果许多用户受到影响,建议您使用适当的 API. | + +### I need to change my SAML app[](#i-need-to-change-my-saml-app "Permalink") + +用户将需要[取消链接当前的 SAML 身份](#unlinking-accounts) , [并将其身份链接](#user-access-and-management)到新的 SAML 应用. + +### I need additional information to configure my identity provider[](#i-need-additional-information-to-configure-my-identity-provider "Permalink") + +提供商之间的许多 SAML 术语可能会有所不同. 您正在查找的信息可能以其他名称列出. + +有关更多信息,请从您的身份提供商的文档开始. 查找他们的选项和示例,以了解他们如何配置 SAML. 这可以提供有关配置 GitLab 以便与这些提供程序一起使用所需的提示. + +它也有助于查看我们[有关自管理 GitLab 的更详细的文档](../../../integration/saml.html) . GitLab.com 的 SAML 配置与自我管理实例的 SAML 配置基本相同. 但是,自我管理的 GitLab 实例使用支持更多选项的配置文件,如外部[OmniAuth SAML 文档中所述](https://github.com/omniauth/omniauth-saml/) . 在内部使用[`ruby-saml`库](https://github.com/onelogin/ruby-saml) ,因此我们有时在此处检查以验证不常用选项的低级详细信息. + +它还可以帮助将提供商的 XML 响应与我们[用于内部测试的 XML 示例进行比较](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/spec/fixtures/saml/response.xml) . \ No newline at end of file diff --git a/docs/045.md b/docs/045.md new file mode 100644 index 0000000000000000000000000000000000000000..0217c80a46763c70f823cf0eb5d2a6d850aefc25 --- /dev/null +++ b/docs/045.md @@ -0,0 +1,254 @@ +# SCIM provisioning using SAML SSO for GitLab.com groups + +> 原文:[https://docs.gitlab.com/ee/user/group/saml_sso/scim_setup.html](https://docs.gitlab.com/ee/user/group/saml_sso/scim_setup.html) + +* [Features](#features) +* [Requirements](#requirements) +* [GitLab configuration](#gitlab-configuration) +* [Identity Provider configuration](#identity-provider-configuration) + * [Azure configuration steps](#azure-configuration-steps) + * [Configure attribute mapping](#configure-attribute-mapping) + * [Okta configuration steps](#okta-configuration-steps) + * [Okta Known Issues](#okta-known-issues) +* [User access and linking setup](#user-access-and-linking-setup) + * [Blocking access](#blocking-access) +* [Troubleshooting](#troubleshooting) + * [Azure](#azure) + * [How do I verify my SCIM configuration is correct?](#how-do-i-verify-my-scim-configuration-is-correct) + * [Testing Azure connection: invalid credentials](#testing-azure-connection-invalid-credentials) + * [Azure: (Field) can’t be blank sync error](#azure-field-cant-be-blank-sync-error) + * [How do I diagnose why a user is unable to sign in](#how-do-i-diagnose-why-a-user-is-unable-to-sign-in) + * [How do I verify user’s SAML NameId matches the SCIM externalId](#how-do-i-verify-users-saml-nameid-matches-the-scim-externalid) + * [Update or fix mismatched SCIM externalId and SAML NameId](#update-or-fix-mismatched-scim-externalid-and-saml-nameid) + * [I need to change my SCIM app](#i-need-to-change-my-scim-app) + +# SCIM provisioning using SAML SSO for GitLab.com groups[](#scim-provisioning-using-saml-sso-for-gitlabcom-groups-silver-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in [GitLab.com Silver](https://about.gitlab.com/pricing/) 11.10. + +跨域身份管理系统(SCIM)是一种开放标准,可实现用户自动配置. 当为 GitLab 组配置 SCIM 时,该组的成员资格将在 GitLab 和身份提供者之间同步. + +GitLab 的[SCIM API](../../../api/scim.html)实现[了 RFC7644 协议的](https://tools.ietf.org/html/rfc7644)一部分. + +## Features[](#features "Permalink") + +当前,可以执行以下操作: + +* 建立使用者 +* 更新用户(仅限 Azure) +* 停用用户 + +支持以下身份提供者: + +* Azure +* Okta + +## Requirements[](#requirements "Permalink") + +* 必须配置[组单一登录](index.html) . + +## GitLab configuration[](#gitlab-configuration "Permalink") + +配置[组单一登录后](index.html) ,我们可以: + +1. 导航到该组,然后单击**管理> SAML SSO** . +2. 单击**生成 SCIM 令牌**按钮. +3. 保存令牌和 URL,以便可以在下一步中使用它们. + +[![SCIM token configuration](img/c187de65e481b5598b110fee5310776c.png)](img/scim_token.png) + +## Identity Provider configuration[](#identity-provider-configuration "Permalink") + +* [Azure](#azure-configuration-steps) +* [Okta](#okta-configuration-steps) + +### Azure configuration steps[](#azure-configuration-steps "Permalink") + +现在需要为 SCIM 设置在[Azure 的](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/configure-single-sign-on-non-gallery-applications) [单点登录](index.html)安装过程中创建的 SAML 应用程序. + +1. 检查您的 GitLab SAML 应用程序的配置,并确保**名称标识符值** (NameID)指向`user.objectid`或另一个唯一标识符. 这将与 GitLab 上使用的`extern_uid`匹配. + + [![Name identifier value mapping](img/fe827d4bc97b90c3a250af05fd988fc4.png)](img/scim_name_identifier_mapping.png) + +2. 通过遵循针对 Azure [支持](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#provisioning-users-and-groups-to-applications-that-support-scim)的 SCIM 安装文档[中支持 SCIM 的应用程序](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#provisioning-users-and-groups-to-applications-that-support-scim)的[供应用户和组,来](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#provisioning-users-and-groups-to-applications-that-support-scim)设置自动供应和管理凭据. + +During this configuration, note the following: + +* `Tenant URL`和`secret token`是在[上一步中](#gitlab-configuration)检索到的. +* 如果 GitLab 的可用性有任何问题或类似错误,则通知电子邮件集将获得这些信息. +* 建议设置通知电子邮件并选中**发生故障时发送电子邮件通知**复选框. +* 对于映射,我们将仅启用"将`Synchronize Azure Active Directory Users to AppName`启用状态. + +然后,您可以通过单击" **测试连接"**来**测试连接** . 如果连接成功,请确保在继续操作之前保存配置. 请参阅下面的[疑难解答](#troubleshooting) . + +#### Configure attribute mapping[](#configure-attribute-mapping "Permalink") + +1. 单击"将`Synchronize Azure Active Directory Users to AppName`以配置属性映射. +2. 单击`mail`映射旁边的**删除** . +3. 将`userPrincipalName`映射到`emails[type eq "work"].value`并将其**Matching 优先级**更改为`2` . +4. Map `mailNickname` to `userName`. +5. 确定 GitLab 如何唯一标识用户. + + * 除非用户已经为您的组链接了 SAML,否则请使用`objectId` . + * 如果已经有链接 SAML 的用户,则使用[SAML 配置中](#azure)的" `Name ID`值. 使用其他值可能会导致用户重复并阻止用户访问 GitLab 组. +6. 创建一个新的映射: + 1. 单击**添加新映射** . + 2. 组: + * 上面确定的唯一标识符的**Source 属性** ,通常是`objectId` . + * **目标属性**为`externalId` . + * **使用此属性**将**对象匹配**为`Yes` . + * **匹配优先级**为`1` . +7. 单击`userPrincipalName`映射,然后**使用此属性**将**Match 对象**更改为`No` + +8. 保存您的更改. 作为参考,您可以[在故障排除参考中](../../../administration/troubleshooting/group_saml_scim.html#azure-active-directory)查看[示例配置](../../../administration/troubleshooting/group_saml_scim.html#azure-active-directory) . + + **注意:**如果您使用**除** `objectId` **之外**的唯一标识符,请确保将其映射到`externalId` . +9. 在映射列表下,单击**显示高级选项>编辑 AppName 的属性列表** . + +10. 确保`id`是主要字段和必填字段,并且还需要`externalId` . + + **注意:** `username`既不是主要`username`也不是必需的,因为我们尚不支持 GitLab SCIM 上的该字段. +11. 保存所有屏幕,然后在**Provisioning**步骤中将`Provisioning Status`设置为`On` . + + [![Provisioning status toggle switch](img/4c6172d095020a91bcf8d48c85ee4d1d.png)](img/scim_provisioning_status.png) + + **注意:**您可以通过选择`Scope`来控制实际同步的内容. 例如, `Sync only assigned users and groups`将仅同步分配给应用程序的`Users and groups` ( `Users and groups` ),否则,它将同步整个 Active Directory. + +一旦启用,同步细节的任何错误都出现在**供应**屏幕的底部,有一个链接到审计日志在一起. + +**警告:**同步后,将映射到`id`和`externalId`的字段更改可能会导致配置错误,用户重复,并阻止现有用户访问 GitLab 组. + +### Okta configuration steps[](#okta-configuration-steps "Permalink") + +现在需要为 SCIM 设置在[Okta 的](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/) [单点登录](index.html#okta-setup-notes)安装过程中创建的 SAML 应用程序. 在继续之前,请确保完成[GitLab 配置](#gitlab-configuration)过程. + +1. 登录到 Okta. +2. 如果您在右上角看到一个**管理**按钮,请单击该按钮. 这将确保您位于"管理"区域. + + **提示:**如果您在使用开发者控制台,点击**开发者控制台**顶部栏并选择**经典的 UI.** 否则,您可能看不到以下步骤中描述的按钮: +3. 在" **应用程序"**选项卡中,单击" **添加应用程序"** . +4. Search for **GitLab**, find and click on the ‘GitLab’ application. +5. 在 GitLab 应用程序概述页面上,单击**添加** . +6. 在" **应用程序可见性"下,**选中两个复选框. 当前,GitLab 应用程序不支持 SAML 身份验证,因此不应向用户显示该图标. +7. 单击**"完成"**以完成添加应用程序. +8. 在**供应**标签中,点击**配置 API 集成** . +9. Select **启用 API 集成**. + * 对于**基本 URL,**输入从 GitLab SCIM 配置页面获得的 URL. + * 对于**API 令牌,**输入从 GitLab SCIM 配置页面获得的 SCIM 令牌. +10. 点击"测试 API 凭据"以验证配置. +11. 单击**保存**以应用设置. +12. After saving the API integration details, new settings tabs will appear on the left. Choose **到应用**. +13. Click **Edit**. +14. 选中"为**创建用户**和**停用用户** **启用** "复选框. +15. Click **Save**. +16. 在" **分配"**选项卡中分配用户. 分配的用户将在您的 GitLab 组中创建和管理. + +#### Okta Known Issues[](#okta-known-issues "Permalink") + +Okta GitLab 应用程序当前仅支持 SCIM. 继续使用单独的 Okta [SAML SSO](index.html)配置以及上述新的 SCIM 应用程序. + +## User access and linking setup[](#user-access-and-linking-setup "Permalink") + +只要已经配置了[Group SAML](index.html) ,就可以在启用同步之前,在激活同步之前,现有的 GitLab.com 用户可以通过以下方式之一链接到其帐户: + +* 通过更新其 GitLab.com 用户帐户中的*主要*电子邮件地址以匹配其身份提供商的用户个人资料电子邮件地址. +* 通过执行以下步骤: + + 1. 如果需要,登录到 GitLab.com. + 2. 在身份提供商的仪表板上单击 GitLab 应用程序,或访问**GitLab 单一登录 URL** . + 3. 单击**授权**按钮. + +后续访问中的新用户和现有用户可以通过身份提供商的仪表板或直接访问链接来访问组. + +有关角色信息,请参阅[组 SAML 页面](index.html#user-access-and-management) + +### Blocking access[](#blocking-access "Permalink") + +要取消对该组的访问,我们建议从身份提供商或特定应用程序的用户列表中删除该用户. + +在下一次同步时,将取消提供该用户,这意味着该用户将从组中删除. 除非使用[组托管帐户,](group_managed_accounts.html)否则不会删除该用户帐户. + +## Troubleshooting[](#troubleshooting "Permalink") + +本节包含可能遇到的问题的可能解决方案. + +### Azure[](#azure "Permalink") + +#### How do I verify my SCIM configuration is correct?[](#how-do-i-verify-my-scim-configuration-is-correct "Permalink") + +查看以下内容: + +* 确保`id`的 SCIM 值与`NameId`的 SAML 值匹配. +* 确保`externalId`的 SCIM 值与`NameId`的 SAML 值匹配. + +查看以下 SCIM 参数以获取合理的值: + +* `userName` +* `displayName` +* `emails[type eq "work"].value` + +#### Testing Azure connection: invalid credentials[](#testing-azure-connection-invalid-credentials "Permalink") + +测试连接时,您可能会遇到错误: **您似乎输入了无效的凭据.** **请确认您使用的管理帐户信息正确** . 如果`Tenant URL`和`secret token`正确,请检查您的组路径中是否包含可能被视为无效 JSON 原语的字符(例如`.` ). 从组路径中删除此类字符通常可以解决该错误. + +#### Azure: (Field) can’t be blank sync error[](#azure-field-cant-be-blank-sync-error "Permalink") + +在检查供应的审核日志时,有时您会看到错误`Namespace can't be blank, Name can't be blank, and User can't be blank.` + +这可能是由于没有为所有要映射的用户提供所有必填字段(例如名字和姓氏). + +作为解决方法,请尝试其他映射: + +1. 请按照上面的 Azure 映射说明进行操作. +2. 删除`name.formatted`目标属性条目. +3. 将`displayName`源属性更改为具有`name.formatted`目标属性. + +#### How do I diagnose why a user is unable to sign in[](#how-do-i-diagnose-why-a-user-is-unable-to-sign-in "Permalink") + +每当`id`或`externalId`更改时,SCIM 都会更新 GitLab 存储的**Identity** ( `extern_uid` )值. 除非 GitLab 标识( `extern_uid` )值与 SAML 发送的`NameId`匹配,否则用户将无法登录. + +SCIM 还将使用此值来匹配`id`上的用户,并且只要`id`或`externalId`值发生更改,SCIM 就会更新此值. + +将此 SCIM `id`和 SCIM `externalId`配置为与 SAML `NameId`相同的值很重要. 可以使用[调试工具](./index.html#saml-debugging-tools)跟踪 SAML 响应,并且可以根据我们的[SAML 故障排除文档](./index.html#troubleshooting)检查任何错误. + +#### How do I verify user’s SAML NameId matches the SCIM externalId[](#how-do-i-verify-users-saml-nameid-matches-the-scim-externalid "Permalink") + +组所有者可以在组 SAML SSO 设置页面中查看用户列表和为每个用户存储的`externalId` . + +另外,在[SCIM API](../../../api/scim.html#get-a-list-of-saml-users)可用于手动检索`externalId` ,我们已经存储了用户,也被称为`external_uid`或`NameId` . + +例如: + +``` +curl 'https://example.gitlab.com/api/scim/v2/groups/GROUP_NAME/Users?startIndex=1"' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +要查看它与作为 SAML NameId 返回的值的比较,可以让用户使用[SAML Tracer](index.html#saml-debugging-tools) . + +#### Update or fix mismatched SCIM externalId and SAML NameId[](#update-or-fix-mismatched-scim-externalid-and-saml-nameid "Permalink") + +无论是更改值还是需要映射到其他字段,请确保`id` , `externalId`和`NameId`都映射到同一字段. + +如果 GitLab 的`externalId`与 SAML NameId 不匹配,则需要对其进行更新才能使用户登录.理想情况下,将身份标识提供者配置为进行此类更新,但是在某些情况下,它可能无法这样做. ,例如在查找用户时由于 ID 更改而失败. + +如果您修改 SCIM 身份提供程序使用的字段,请务必谨慎,通常为`id`和`externalId` . 我们使用这些 ID 查找用户. 如果身份提供者不知道这些字段的当前值,则该提供者可以创建重复的用户. + +如果用户的`externalId`不正确,并且也与 SAML NameID 不匹配,则可以通过以下方式解决该问题: + +* 您可以根据[" SAML 身份验证失败:用户已被使用"](./index.html#message-saml-authentication-failed-user-has-already-been-taken)部分,使用户取消链接并重新链接自己. +* 通过在启用预配置的同时从 SAML 应用中删除所有用户,可以同时取消所有用户的链接. +* 您可以使用[SCIM API](../../../api/scim.html#update-a-single-saml-user)手动更正为用户存储的`externalId`以匹配 SAML `NameId` . 要查找用户,您需要知道与`NameId`以及当前`externalId`匹配的`NameId` . + +然后可以发出手动 SCIM#update 请求,例如: + +``` +curl --verbose --request PATCH 'https://gitlab.com/api/scim/v2/groups/YOUR_GROUP/Users/OLD_EXTERNAL_UID' --data '{ "Operations": [{"op":"Replace","path":"externalId","value":"NEW_EXTERNAL_UID"}] }' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +重要的是不要将这些值更新为不正确的值,因为这将导致用户无法登录.也不要将值分配给错误的用户,这也很重要,因为这将导致用户登录到错误的帐户. + +#### I need to change my SCIM app[](#i-need-to-change-my-scim-app "Permalink") + +各个用户可以按照[" SAML 身份验证失败:用户已被使用"](./index.html#i-need-to-change-my-saml-app)部分中的说明进行操作. + +或者,可以从 SCIM 应用程序中删除用户,这将取消所有已删除用户的链接. 然后可以为新的 SCIM 应用打开同步,以[链接现有用户](#user-access-and-linking-setup) . \ No newline at end of file diff --git a/docs/046.md b/docs/046.md new file mode 100644 index 0000000000000000000000000000000000000000..31e89420729d95a6f9dc4be60ce3c7ac7886901f --- /dev/null +++ b/docs/046.md @@ -0,0 +1,149 @@ +# Subgroups + +> 原文:[https://docs.gitlab.com/ee/user/group/subgroups/](https://docs.gitlab.com/ee/user/group/subgroups/) + +* [Overview](#overview) +* [Creating a subgroup](#creating-a-subgroup) +* [Membership](#membership) + * [Overriding the ancestor group membership](#overriding-the-ancestor-group-membership) +* [Mentioning subgroups](#mentioning-subgroups) +* [Limitations](#limitations) + +# Subgroups[](#subgroups "Permalink") + +在 GitLab 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/2772) . + +GitLab 支持多达 20 个级别的子组,也称为嵌套组或层次结构组. 组的级别. + +通过使用子组,您可以执行以下操作: + +* **独立的内部/外部组织.** 由于每个组都有自己的可见性级别,因此您可以在同一保护范围内为不同目的托管组. +* **组织大型项目.** 对于大型项目,子组可能会更容易分隔部分源代码的权限. +* **使管理人员和控制可见性变得更加容易.** 根据人们的组[成员身份,](#membership)赋予他们不同的[权限](../../permissions.html#group-members-permissions) . + +有关组和项目中允许的权限的更多信息,请参见[可见性级别](../../../development/permissions.html#general-permissions) . + +## Overview[](#overview "Permalink") + +一个组中可以有许多子组,而同一组中只能有一个直接父组. 它类似于目录行为或嵌套项目列表: + +* 第一组 + * 1.1 组 + * 1.2 组 + * 1.2.1 组 + * 1.2.2 组 + * 组 1.2.2.1 + +在一个真实的示例中,设想维护一个 GNU / Linux 发行版,其中第一个组是发行版的名称,随后的组按如下所示拆分: + +* Organization Group - GNU/Linux distro + * 类别子组-包 + * (项目)配套 01 + * (项目)配套 02 + * 类别子组-软件 + * (项目)核心 + * (项目)CLI + * (项目)Android 应用 + * (项目)iOS 应用 + * 类别子组-红外线工具 + * (项目)Ansible 剧本 + +Another example of GitLab as a company would be the following: + +* 组织组-GitLab + * 类别子组-市场营销 + * (项目)设计 + * (项目)一般 + * 类别子组-软件 + * (项目)GitLab CE + * (项目)GitLab EE + * (项目)Omnibus GitLab + * (项目)GitLab Runner + * (项目)GitLab Pages 守护程序 + * 类别子组-红外线工具 + * (项目)厨师食谱 + * 类别子组-执行团队 + +* * * + +当执行诸如在子组之间转移或导入项目的操作时,其行为与在`group/project`级别执行这些操作时的行为相同. + +## Creating a subgroup[](#creating-a-subgroup "Permalink") + +要创建子组,您必须是该组的所有者或维护者,具体取决于该组的设置. + +默认情况下,在以下位置创建的组: + +* GitLab 12.2 或更高版本允许所有者和维护者创建子组. +* GitLab 12.1 或更早版本仅允许所有者创建子组. + +此设置可以是所有者或管理员的任何组. + +有关更多信息,请检查[权限表](../../permissions.html#group-members-permissions) . 有关不允许用作组名的单词列表,请参见[保留名称](../../reserved_names.html) . + +如果将子组明确地作为所有者(或维护者,如果启用了此设置)添加到直接父组,则用户始终可以创建子组,即使管理员在其设置中禁用了组创建也是如此. + +要创建一个子组: + +1. 在组的仪表板中,展开" **新建项目**拆分"按钮,选择" **新建子组"** ,然后单击" **新建子组"**按钮. + + [![Subgroups page](img/c3c27ff673c33bcd50004c2adb617d5f.png)](img/create_subgroup_button.png) + +2. 像平常一样创建一个新组. 请注意,直接父组名称空间在" **组路径"**下是固定的. 可见性级别可以与直接父组不同. + + [![Subgroups page](img/7fb24fed9f39dcdabb530523bcb8dc08.png)](img/create_new_group.png) + +3. 单击**创建组**按钮,您将被带到新组的仪表板页面. + +按照相同的过程创建任何后续组. + +## Membership[](#membership "Permalink") + +将成员添加到子组时,它们将从父组继承成员资格和权限级别. 如果您是其父级成员之一,则该模型允许访问嵌套组. + +在亚组可以用乔布斯的管道[运动员](../../../ci/runners/README.html)注册到父组(S). 这意味着为父组配置的机密可用于子组作业. + +此外,属于子组的项目的维护者可以查看注册到父组的 Runner 的详细信息. + +成员的组权限只能由所有者更改,并且只能在添加成员的组的" **成员"**页面上进行. + +您可以通过查看组的" **成员"**页面来确定成员是否从父组继承了权限. + +[![Group members page](img/e18ff80d06980688066f9ec9404bd2da.png)](img/group_members.png) + +从上图可以得出以下几点: + +* 有 5 位成员可以访问第`four`组. +* User0 是一个 Reporter,已从组`four`的层次结构上方的组`one`继承了其权限. +* 用户 1 是一个开发并已继承组他们的权限`one/two`其是组的层级以上`four` . +* 用户 2 是一个开发并已继承组他们的权限`one/two/three`这是组的层级以上`four` . +* 对于 User3,没有任何父组的指示,因此它们属于`four`组,即我们正在检查的组. +* 管理员是**所有**子组的所有者和成员,因此,与 User3 一样,没有任何祖先组的迹象. + +[在](https://gitlab.com/gitlab-org/gitlab/-/issues/21727) GitLab 12.6 中,您可以使用右侧的下拉列表过滤此列表: + +[![Group members filter](img/8215c374294289cd2bd24399439403fd.png)](img/group_members_filter_v12_6.png) + +* **仅显示直接成员**仅显示 Administrator 和 User3,因为这是属于`four`组的唯一用户,这是我们正在检查的用户. +* **仅显示继承的成员将**显示 User0,User1 和 User2,无论层次结构上方的哪个组都是继承权限的来源. + +### Overriding the ancestor group membership[](#overriding-the-ancestor-group-membership "Permalink") + +**注意:**您必须是网上论坛的所有者,才能向其中添加成员.**注意:**子组中的用户权限不能低于其任何祖先组中的权限. 因此,您不能针对子组的祖先组减少用户的权限. + +要覆盖用户的祖先组(他们被添加到的第一个组)的成员资格,请将该用户再次以更高的权限集添加到新的子组中. + +例如,如果首先使用具有开发者权限将 User0 添加到组`group-1/group-1-1` ,则它们将在组`group-1/group-1-1`每个其他子`group-1/group-1-1`继承这些权限. 要为他们提供维护者访问`group-1/group-1-1/group1-1-1` ,您可以将他们再次添加为该维护者. 从该组中删除它们,权限将回退到祖先组的权限. + +## Mentioning subgroups[](#mentioning-subgroups "Permalink") + +在问题,提交和合并请求中提及组( `@group` )将通知该组的所有成员. 现在有了子组,如果您想拆分组的结构,将有更精细的支持. 提及方式与以前一样,您可以选择要通知的人群. + +[![Mentioning subgroups](img/0d1089161431c5f21751458027d84535.png)](img/mention_subgroups.png) + +## Limitations[](#limitations "Permalink") + +以下是您无法对子组进行操作的列表: + +* [GitLab 页面](../../project/pages/index.html)支持在一个子组下托管的项目,但不支持子组网站下的项目. 这意味着,尽管您可以在子组下拥有项目网站,但是只有最高级别的组才支持[组网站](../../project/pages/getting_started_part_one.html#gitlab-pages-default-domain-names) . +* 不能与作为该项目所属组的祖先的组共享项目.这意味着您只能在沿层次结构走时共享. 例如, `group/subgroup01/project` **不能**与`group`共享,但是可以与`group/subgroup02`或`group/subgroup01/subgroup03`共享. \ No newline at end of file diff --git a/docs/047.md b/docs/047.md new file mode 100644 index 0000000000000000000000000000000000000000..ddb56143267ac8aa9a4343d63d0877122cee9dff --- /dev/null +++ b/docs/047.md @@ -0,0 +1,81 @@ +# Roadmap + +> 原文:[https://docs.gitlab.com/ee/user/group/roadmap/](https://docs.gitlab.com/ee/user/group/roadmap/) + +* [Timeline duration](#timeline-duration) + * [Quarters](#quarters) + * [Months](#months) + * [Weeks](#weeks) +* [Roadmap timeline bar](#roadmap-timeline-bar) + +# Roadmap[](#roadmap-premium "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.5 中引入. +* 在[GitLab 12.9 中](https://gitlab.com/gitlab-org/gitlab/-/issues/198062) ,路线图已移至高级层. +* 在[GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/5164)及更高版本中,史诗条显示史诗的标题,进度和完成的重量百分比. +* 里程碑出现在[GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/issues/6802)及更高版本的路线图中. +* 在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29641)删除的路线图中可见的里程碑的功能标志. +* 在[GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/214375)和更高版本中,该路线图还显示了组中项目的里程碑. +* 在[GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/212494)和更高版本中,里程碑栏可以折叠和展开. + +可以以时间轴(即甘特图)的形式显示包含开始日期或截止日期的组中的史诗和里程碑. "路线图"页面显示了一个组,一个子组或一个组中的一个项目的史诗和里程碑. + +在史诗栏上,您可以看到每个史诗的标题,进度和完成的重量百分比. 当您将鼠标悬停在史诗栏上时,将显示一个弹出框,其中包含史诗的标题,开始日期,到期日和完成的权重. + +您可以展开包含子级史诗的史诗,以在路线图中显示其子级史诗. 您可以单击人字形( )旁边的史诗标题,以展开和折叠子史诗. + +在里程碑栏的顶部,您可以看到其标题. 当您将鼠标悬停在里程碑栏或标题上时,将显示一个带有其标题,开始日期和截止日期的弹出窗口. 您也可以点击 V 形符号( )旁边的" **里程碑"**标题以切换里程碑栏的列表. + +[![roadmap view](img/b44c56313892b2d78da86b3f64519a98.png)](img/roadmap_view_v13_2.png) + +下拉菜单允许您仅显示打开或关闭的史诗. 默认情况下,显示所有史诗. + +[![epics state dropdown](img/9fa8173be554c09a1397ae7e064f24e5.png)](img/epics_state_dropdown_v12_10.png) + +您可以通过以下方式在"路线图"视图中对史诗进行排序: + +* 创建日期 +* 最近更新时间 +* 开始日期 +* 截止日期 + +每个选项都包含一个按钮,可在**升序**和**降序**之间切换排序顺序. 浏览史诗(包括[史诗列表视图)](../epics/index.html)时,排序选项和顺序仍然存在. + +路线图也可以[在史诗内部可视化](../epics/index.html#roadmap-in-epics) . + +## Timeline duration[](#timeline-duration "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0 中引入. +* 在[GitLab 12.9 中](https://gitlab.com/gitlab-org/gitlab/-/issues/198062) ,时间轴已移至高级层. + +路线图支持以下日期范围: + +* Quarters +* 月(默认) +* Weeks + +### Quarters[](#quarters "Permalink") + +[![roadmap date range in quarters](img/ecb561241f5fcf0f0695ee4e29069b11.png)](img/roadmap_timeline_quarters.png) + +在" **季度"**预设中,路线图显示史诗和里程碑,其开始或到期日期**在**过去的季度,当前季度和接下来的四个季度**之内**或**经过**过去的季度,当前季度和接下来的四个季度,其中**今天**由时间轴中的垂直红线显示. 时间轴标题上季度名称下方的子标题代表季度的月份. + +### Months[](#months "Permalink") + +[![roadmap date range in months](img/e255c03f63cd814a974b54b2a9eb6b02.png)](img/roadmap_timeline_months.png) + +在" **月份"**预设中,路线图显示史诗和里程碑,这些史诗和里程碑的开始或到期日期**在**过去一个月,当前月份以及接下来的五个月**之内**或**经历**过去或六个月,其中**今天**由时间轴中的垂直红线显示. 时间轴标题上月份名称下方的子标题表示一周中开始日期(星期日)的日期. 默认情况下选择此预设. + +### Weeks[](#weeks "Permalink") + +[![roadmap date range in weeks](img/26b5d3ef6b515c199d6c860ac62a4671.png)](img/roadmap_timeline_weeks.png) + +在" **周"**预设中,路线图显示史诗和里程碑,这些史诗和里程碑的开始日期或到期日期**在**过去一周,当前星期和接下来的四个星期**之内**或**经过**过去一周,当前星期和接下来的四个星期,其中**今天**由时间轴中的垂直红线显示. 时间轴标题上星期名称下方的子标题代表星期几. + +## Roadmap timeline bar[](#roadmap-timeline-bar "Permalink") + +时间线栏根据史诗或里程碑的开始日期和到期日期指示其大概位置. \ No newline at end of file diff --git a/docs/048.md b/docs/048.md new file mode 100644 index 0000000000000000000000000000000000000000..57fe3d28ad1e2ae70050f99a243562be01a85960 --- /dev/null +++ b/docs/048.md @@ -0,0 +1,303 @@ +# Projects + +> 原文:[https://docs.gitlab.com/ee/user/project/](https://docs.gitlab.com/ee/user/project/) + +* [Project features](#project-features) + * [Project integrations](#project-integrations) +* [New project](#new-project) + * [Fork a project](#fork-a-project) + * [Star a project](#star-a-project) + * [Explore projects](#explore-projects) +* [Project settings](#project-settings) +* [Import or export a project](#import-or-export-a-project) +* [Remove a project](#remove-a-project) + * [Delayed removal](#delayed-removal-premium) +* [CI/CD for external repositories](#cicd-for-external-repositories-premium) +* [Project members](#project-members) +* [Project activity](#project-activity) + * [Leave a project](#leave-a-project) +* [Project’s landing page](#projects-landing-page) +* [Redirects when changing repository paths](#redirects-when-changing-repository-paths) +* [Use your project as a Go package](#use-your-project-as-a-go-package) + * [Disable Go module features for private projects](#disable-go-module-features-for-private-projects) + * [Authenticate Go requests](#authenticate-go-requests) + * [Authenticate Git fetches](#authenticate-git-fetches) +* [Access project page with project ID](#access-project-page-with-project-id) +* [Project aliases](#project-aliases-premium-only) +* [Project APIs](#project-apis) + +# Projects[](#projects "Permalink") + +在 GitLab 中,您可以创建用于托管代码库的项目,将其用作问题跟踪器,在代码上进行协作,并使用内置的 GitLab CI / CD 持续构建,测试和部署应用程序. + +您可以[选择](../../public_access/public_access.html)公开,内部或私有[使用](../../public_access/public_access.html)您的项目. GitLab 不限制您创建的私人项目的数量. + +## Project features[](#project-features "Permalink") + +在 GitLab 中创建项目时,您将可以使用大量[功能](https://about.gitlab.com/features/) : + +**Repositories:** + +* [问题跟踪器](issues/index.html) :与您的团队讨论问题内的实现 + * [发行板](issue_board.html) :组织工作流程并确定其优先级 + * [多个发行板](issue_board.html#multiple-issue-boards) :允许您的团队为同一项目创建自己的工作流(发行板) +* [存储库](repository/index.html) :将代码托管在完全集成的平台中 + * [分支](repository/branches/index.html) :使用 Git 分支策略在代码上进行协作 + * [受保护的分支机构](protected_branches.html) :防止协作者弄乱历史记录或在未经审查的情况下推送代码 + * [受保护的标签](protected_tags.html) :控制谁有权创建标签,并防止意外更新或删除 + * [储存库镜​​像](repository/repository_mirroring.html) + * [签署提交](gpg_signed_commits/index.html) :使用 GPG 签署您的提交 + * [部署令牌](deploy_tokens/index.html) :管理基于项目的部署令牌,这些令牌允许永久访问存储库和 Container Registry. +* [Web IDE](web_ide/index.html) + +**发出和合并请求:** + +* [问题跟踪器](issues/index.html) :与您的团队讨论问题内的实现 + * [发行板](issue_board.html) :组织工作流程并确定其优先级 + * [多个发行板](issue_board.html#multiple-issue-boards) :允许您的团队为同一项目创建自己的工作流(发行板) +* [合并请求](merge_requests/index.html) :应用您的分支策略并获得团队的审查 + * [合并请求批准](merge_requests/merge_request_approvals.html) :实施更改之前[请求批准](merge_requests/merge_request_approvals.html) + * [修复 UI 中的合并冲突](merge_requests/resolve_conflicts.html) :直接从 GitLab UI 中使用 Git diff 工具 + * [审查应用程序](../../ci/review_apps/index.html) :按分支实时预览合并请求中建议的更改结果 +* [标签](labels.html) :按标签整理问题并合并请求 +* [时间跟踪](time_tracking.html) :跟踪估计在完成问题或合并请求上花费的时间和时间 +* [里程碑](milestones/index.html) :朝着目标日期迈进 +* [描述模板](description_templates.html) :为项目定义特定于上下文的模板,并为您的项目合并请求描述字段 +* [斜杠命令(快速操作)](quick_actions.html) :针对问题或合并请求的常见操作的文本快捷方式 +* [自动完成字符](autocomplete_characters.html) :自动完成对用户,组,问题,合并请求和其他 GitLab 元素的引用. +* [Web IDE](web_ide/index.html) + +**亚搏体育 app CI / CD:** + +* [GitLab CI / CD](../../ci/README.html) :GitLab 内置的[持续集成,交付和部署](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/)工具 + * [容器注册表](../packages/container_registry/index.html) :开箱即用地构建和推送 Docker 映像 + * [自动部署](../../topics/autodevops/stages.html#auto-deploy) :配置 GitLab CI / CD 以自动设置应用程序的部署 + * [启用和禁用 GitLab CI / CD](../../ci/enable_or_disable_ci.html) + * [管道](../../ci/pipelines/index.html) :从 UI 配置和可视化 GitLab CI / CD 管道 + * [计划的管道](../../ci/pipelines/schedules.html) :计划管道以在选定的时间开始 + * [管道图](../../ci/pipelines/index.html#visualize-pipelines) :通过 UI 查看整个管道 + * [作业工件](../../ci/pipelines/job_artifacts.html) :定义,浏览和下载作业工件 + * [管道设置](../../ci/pipelines/settings.html) :设置 Git 策略(选择从作业中的 GitLab 提取存储库的默认方式),超时(定义可以运行作业的最长时间(以分钟为`.gitlab-ci.yml` )) `.gitlab-ci.yml`自定义路径,测试覆盖率分析,管道的可见性等 + * [Kubernetes 集群集成](clusters/index.html) :将您的 GitLab 项目与 Kubernetes 集群连接 + * [功能标志](../../operations/feature_flags.html) :功能标志允许您通过动态切换某些功能来以不同的方式发布项目 +* [GitLab Pages](pages/index.html) :使用[GitLab Pages](pages/index.html)构建,测试和部署您的静态网站 + +**其他特性:** + +* [Wiki](wiki/index.html) :在集成的 Wiki 中记录您的 GitLab 项目. +* [片段](../snippets.html) :存储,共享和协作代码片段. +* [价值流分析](cycle_analytics.html) :查看您的开发生命周期. +* [见解](insights/index.html) :配置对您的项目至关重要的见解. +* [安全仪表板](security_dashboard.html) :安全仪表板. +* [语法突出显示](highlighting.html) :一种自定义代码块的替代方法,它替代了 GitLab 的默认语言选择. +* [徽章](badges.html) :项目概述的徽章. +* [发行版](releases/index.html) :一种跟踪项目中可交付成果的方式,可作为源,构建输出,其他元数据和与代码的发行版本相关的其他工件的快照. +* [Conan 软件包](../packages/conan_repository/index.html) :您在 GitLab 中的私人 Conan 存储库. +* [Maven 软件包](../packages/maven_repository/index.html) :您在 GitLab 中的私有 Maven 存储库. +* [NPM 软件包](../packages/npm_registry/index.html) :您在 GitLab 中的私有 NPM 软件包注册表. +* [代码所有者](code_owners.html) :为某些文件指定代码所有者 +* [许可证合规性](../compliance/license_compliance/index.html) :批准和拒绝项目的许可证. +* [依赖项列表](../application_security/dependency_list/index.html) :查看项目依赖项. +* [要求](requirements/index.html) :要求使您可以创建标准来检查产品. +* [静态站点编辑器](static_site_editor/index.html) :无需事先了解代码库或 Git 命令,即可在静态网站上快速编辑内容. +* [代码智能](code_intelligence.html) :代码导航功能. + +### Project integrations[](#project-integrations "Permalink") + +[将您的项目](integrations/index.html)与 Jira,Mattermost,Kubernetes,Slack 等进行[集成](integrations/index.html) . + +## New project[](#new-project "Permalink") + +了解如何在 GitLab 中[创建一个新项目](../../gitlab-basics/create-project.html) . + +### Fork a project[](#fork-a-project "Permalink") + +您可以[派生一个项目](repository/forking_workflow.html) ,以便: + +* 通过分叉项目并创建从分支到上游项目的合并请求来进行代码协作 +* 分叉一个示例项目以在其顶部工作 + +### Star a project[](#star-a-project "Permalink") + +您可以为项目加注星标,以使其更容易找到您经常使用的项目. 项目拥有的明星数量可以表明其受欢迎程度. + +为项目加注星标: + +1. 转到要加注星标的项目的主页. +2. 在页面的右上角,点击**星标** . + +要查看已加星标的项目,请执行以下操作: + +1. 单击导航栏中的**项目** . +2. Click **已加星标的项目**. +3. GitLab 显示有关已加星标项目的信息,包括: + + * 项目描述,包括名称,描述和图标 + * 已为该项目加注星标的次数 + * Number of times this project has been forked + * 打开的合并请求数 + * 未解决问题的数量 + +### Explore projects[](#explore-projects "Permalink") + +您可以探索 GitLab 上可用的其他流行项目. 探索项目: + +1. 单击导航栏中的**项目** . +2. Click **探索项目**. + +GitLab 显示一个项目列表,按上次更新日期排序. 要查看具有最多[星星的](#star-a-project)项目,请单击" **最多星星"** . 要查看过去一个月中评论数量最多的项目,请点击**趋势** . + +## Project settings[](#project-settings "Permalink") + +将项目的可见性级别和访问级别设置为各个页面,并执行诸如归档,重命名或传输项目的操作. + +通读有关[项目设置](settings/index.html)的文档. + +## Import or export a project[](#import-or-export-a-project "Permalink") + +* [Import a project](import/index.html) from: + * [GitHub to GitLab](import/github.html) + * [Bitbucket to GitLab](import/bitbucket.html) + * [Gitea to GitLab](import/gitea.html) + * [FogBugz to GitLab](import/fogbugz.html) +* [Export a project from GitLab](settings/import_export.html#exporting-a-project-and-its-data) +* [Importing and exporting projects between GitLab instances](settings/import_export.html) + +## Remove a project[](#remove-a-project "Permalink") + +要删除项目,请首先导航到该项目的主页. + +1. 导航至**设置>常规** . +2. 展开**高级**部分. +3. 向下滚动到" **删除项目"**部分. +4. Click **移除专案** +5. 通过输入所需的文本来确认此操作. + +### Delayed removal[](#delayed-removal-premium "Permalink") + +默认情况下,单击以删除项目后会延迟 7 天. 管理员可以在这段时间内恢复项目. [管理员可以更改](../admin_area/settings/visibility_and_access_controls.html#default-deletion-adjourned-period-premium-only)此延迟. + +管理员可以查看所有待删除项目. 如果您是管理员,请转到顶部导航栏,单击" **项目">"您的项目"** ,然后选择"已**删除的项目"**选项卡. 管理员可以从此选项卡还原任何项目. + +## CI/CD for external repositories[](#cicd-for-external-repositories-premium "Permalink") + +您可以将存储库作为 CI / CD 项目连接,而不是将存储库直接导入到 GitLab. + +通读[CI / CD 上有关外部存储库](../../ci/ci_cd_for_external_repos/index.html)的文档. + +## Project members[](#project-members "Permalink") + +了解如何[将成员添加到您的项目中](members/index.html) . + +## Project activity[](#project-activity "Permalink") + +要查看项目的活动,请导航至**项目概述>活动** . 在此处,您可以单击选项卡以查看**所有**活动,或查看按**Push 事件** , **Merge 事件** , **Issue 事件** , **Comment** , **Team**和**Wiki**过滤的**活动** . + +### Leave a project[](#leave-a-project "Permalink") + +当项目属于组时(在[组命名空间下](../group/index.html#namespaces) ), **离开项目**将仅显示在项目的仪表板上. 如果您选择退出项目,那么您将不再是项目成员,因此无法参与. + +## Project’s landing page[](#projects-landing-page "Permalink") + +项目的登录页面根据项目的可见性设置和用户权限显示不同的信息. + +对于公共项目以及[有权查看该项目代码](../permissions.html#project-members-permissions)的内部和私有项目的成员: + +* 显示[`README`文件或索引文件的](repository/#repository-readme-and-index-files)内容(如果有),然后显示项目存储库中的目录列表. +* 如果项目不包含这些文件中的任何一个,则访问者将看到存储库的文件和目录列表. + +对于没有权限查看项目代码的用户: + +* 显示维基主页(如果有). +* 显示项目中的问题列表. + +## Redirects when changing repository paths[](#redirects-when-changing-repository-paths "Permalink") + +当存储库路径更改时,从旧位置平稳过渡到新位置至关重要. GitLab 提供两种重定向:Web UI 和 Git 推/拉重定向. + +根据情况,可能会有所不同. + +When [renaming a user](../profile/index.html#changing-your-username), [changing a group path](../group/index.html#changing-a-groups-path) or [renaming a repository](settings/index.html#renaming-a-repository): + +* 名称空间及其下的任何内容(例如项目)的现有 Web URL 将重定向到新 URL. +* 从 GitLab 10.3 开始,命名空间下项目的现有 Git 远程 URL 将重定向到新的远程 URL. 每次将其推/拉到更改位置的存储库时,都会显示一条警告消息,提示您更新遥控器,而不是拒绝操作. 这意味着在重命名后,任何自动化脚本或 Git 客户端将继续工作,从而使任何过渡都更加顺畅. +* The redirects will be available as long as the original path is not claimed by another group, user or project. + +## Use your project as a Go package[](#use-your-project-as-a-go-package "Permalink") + +任何项目都可以用作 Go 包. GitLab 会正确响应`go get`和`godoc.org`发现请求,包括[`go-import`](https://s0golang0org.icopy.site/cmd/go/)和[`go-source`](https://github.com/golang/gddo/wiki/Source-Code-Links)元标记. + +私有项目(包括子组中的项目)可以用作 Go 包,但可能需要进行配置才能正常工作. 无论身份验证或授权如何,GitLab 都会正确响应以`go get` *不在*子组中的项目的发现请求. 要使用子组中的私有项目作为 Go 包,必须进行[身份验证](#authenticate-go-requests) . 否则,GitLab 会将子组中私有项目的路径截断到前两个段,从而导致`go get`失败. + +GitLab 实现了自己的 Go 代理. 此功能必须由管理员启用,并且需要其他配置. 请参阅[GitLab Go 代理](../packages/go_proxy/index.html) . + +### Disable Go module features for private projects[](#disable-go-module-features-for-private-projects "Permalink") + +In Go 1.12 and later, Go queries module proxies and checksum databases in the process of [fetching a module](../../development/go_guide/dependencies.html#fetching). This can be selectively disabled with `GOPRIVATE` (disable both), [`GONOPROXY`](../../development/go_guide/dependencies.html#proxies) (disable proxy queries), and [`GONOSUMDB`](../../development/go_guide/dependencies.html#fetching) (disable checksum queries). + +`GOPRIVATE` , `GONOPROXY`和`GONOSUMDB`是 Go 模块和 Go 模块前缀的逗号分隔列表. 例如, `GOPRIVATE=gitlab.example.com/my/private/project`将禁用对该项目的查询,而`GOPRIVATE=gitlab.example.com`将禁用`GOPRIVATE=gitlab.example.com` *所有*项目的查询. 如果模块名称或其前缀出现在`GOPRIVATE`或`GONOPROXY` ,则 Go 不会查询模块代理. 如果模块名称或其前缀出现在`GONOPRIVATE`或`GONOSUMDB` ,则 Go 不会查询校验和数据库. + +### Authenticate Go requests[](#authenticate-go-requests "Permalink") + +要验证对 Go 私有项目的请求,请在密码字段中使用[`.netrc`文件](https://ec.haxx.se/usingcurl-netrc.html)和[个人访问令牌](../profile/personal_access_tokens.html) . **仅当可以通过 HTTPS 访问您的 GitLab 实例时,此方法才有效.** `go`命令不会通过不安全的连接传输凭据. 这将验证 Go 直接发出的所有 HTTPS 请求,但不会验证通过 Git 发出的请求. + +例如: + +``` +machine example.gitlab.com +login +password +``` + +**注意:**在 Windows 上,Go 读取`~/_netrc`而不是`~/.netrc` . + +### Authenticate Git fetches[](#authenticate-git-fetches "Permalink") + +如果无法从代理中获取模块,Go 将退回到使用 Git(对于 GitLab 项目). Git 将使用`.netrc`来认证请求. 另外,可以将 Git 配置为在请求 URL 中嵌入特定的凭据,或者使用 SSH 代替 HTTPS(因为 Go 始终使用 HTTPS 来获取 Git 存储库): + +``` +# embed credentials in any request to GitLab.com: +git config --global url."https://${user}:${personal_access_token}@gitlab.example.com".insteadOf "https://gitlab.example.com" + +# use SSH instead of HTTPS: +git config --global url."git@gitlab.example.com".insteadOf "https://gitlab.example.com" +``` + +## Access project page with project ID[](#access-project-page-with-project-id "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53671) . + +要使用项目 ID 从 GitLab UI 快速访问项目,请在浏览器或其他访问项目的工具中访问`/projects/:id` URL. + +## Project aliases[](#project-aliases-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3264) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.1. + +将存储库迁移到 GitLab 并被其他系统访问时,能够使用相同的名称访问它们非常有用,尤其是当它们很多时. 它降低了在大量系统中更改大量 Git URL 的风险. + +manbetx 客户端打不开提供了功能来帮助这一点. 在 GitLab 中,通常使用名称空间和项目名称访问存储库. 也可以通过项目别名访问它们. 此功能仅在通过 SSH 的 Git 上可用. + +项目别名只能通过 API 创建,并且只能由 GitLab 管理员创建. 有关更多详细信息,请遵循[Project Aliases API 文档](../../api/project_aliases.html) . + +一旦为项目创建了别名(例如,项目`https://gitlab.com/gitlab-org/gitlab`的别名`gitlab` ),就可以使用别名(例如`git clone git@gitlab.com:gitlab.git` )来克隆存储库. `git clone git@gitlab.com:gitlab.git`而不是`git clone git@gitlab.com:gitlab-org/gitlab.git` ). + +## Project APIs[](#project-apis "Permalink") + +您的项目可以使用许多[API](../../api/README.html) : + +* [Badges](../../api/project_badges.html) +* [Clusters](../../api/project_clusters.html) +* [Threads](../../api/discussions.html) +* [General](../../api/projects.html) +* [Import/export](../../api/project_import_export.html) +* [Issue Board](../../api/boards.html) +* [Labels](../../api/labels.html) +* [Markdown](../../api/markdown.html) +* [Merge Requests](../../api/merge_requests.html) +* [Milestones](../../api/milestones.html) +* [Services](../../api/services.html) +* [Snippets](../../api/project_snippets.html) +* [Templates](../../api/project_templates.html) +* [Traffic](../../api/project_statistics.html) +* [Variables](../../api/project_level_variables.html) +* [Aliases](../../api/project_aliases.html) \ No newline at end of file diff --git a/docs/049.md b/docs/049.md new file mode 100644 index 0000000000000000000000000000000000000000..cfa11449866c3285a60461d5c1efcfb3d511dca6 --- /dev/null +++ b/docs/049.md @@ -0,0 +1,459 @@ +# GitLab Secure + +> 原文:[https://docs.gitlab.com/ee/user/application_security/](https://docs.gitlab.com/ee/user/application_security/) + +* [Quick start](#quick-start) + * [Override the default registry base address](#override-the-default-registry-base-address) +* [Security scanning tools](#security-scanning-tools) +* [Security Scanning with Auto DevOps](#security-scanning-with-auto-devops) +* [Maintenance and update of the vulnerabilities database](#maintenance-and-update-of-the-vulnerabilities-database) +* [Interacting with the vulnerabilities](#interacting-with-the-vulnerabilities) + * [View details of a DAST vulnerability](#view-details-of-a-dast-vulnerability) + * [Hide sensitive information in headers](#hide-sensitive-information-in-headers) + * [Dismissing a vulnerability](#dismissing-a-vulnerability) + * [Adding a dismissal reason](#adding-a-dismissal-reason) + * [Dismissing multiple vulnerabilities](#dismissing-multiple-vulnerabilities) + * [Creating an issue for a vulnerability](#creating-an-issue-for-a-vulnerability) + * [Solutions for vulnerabilities (auto-remediation)](#solutions-for-vulnerabilities-auto-remediation) + * [Manually applying the suggested patch](#manually-applying-the-suggested-patch) + * [Creating a merge request from a vulnerability](#creating-a-merge-request-from-a-vulnerability) +* [Security approvals in merge requests](#security-approvals-in-merge-requests) + * [Enabling Security Approvals within a project](#enabling-security-approvals-within-a-project) +* [Enabling License Approvals within a project](#enabling-license-approvals-within-a-project) +* [Working in an offline environment](#working-in-an-offline-environment) +* [Using private Maven repos](#using-private-maven-repos) +* [Outdated security reports](#outdated-security-reports) + * [Source branch is behind the target branch](#source-branch-is-behind-the-target-branch) + * [Target branch security report is out of date](#target-branch-security-report-is-out-of-date) +* [Troubleshooting](#troubleshooting) + * [Getting error message `sast job: stage parameter should be [some stage name here]`](#getting-error-message-sast-job-stage-parameter-should-be-some-stage-name-here) + * [Getting error message `sast job: config key may not be used with 'rules': only/except`](#getting-error-message-sast-job-config-key-may-not-be-used-with-rules-onlyexcept) + * [Transitioning your `only/except` syntax to `rules`](#transitioning-your-onlyexcept-syntax-to-rules) + * [Pin your templates to the deprecated versions](#pin-your-templates-to-the-deprecated-versions) + +# GitLab Secure[](#gitlab-secure-ultimate "Permalink") + +GitLab 可以检查您的应用程序是否存在安全漏洞,这些漏洞可能导致未经授权的访问,数据泄漏,服务拒绝等. GitLab 在合并请求中报告漏洞,因此您可以在合并之前修复它们. [安全仪表板](security_dashboard/index.html)提供了在项目,管道和组中检测到的漏洞的高级视图. " [威胁监视"](threat_monitoring/index.html)页面提供了应用程序环境的运行时安全性度量. 使用提供的信息,您可以立即开始风险分析和补救. + +有关 GitLab 的应用程序安全性的概述,请参阅[Security Deep Dive](https://www.youtube.com/watch?v=k4vEJnGYy84) . + +## Quick start[](#quick-start "Permalink") + +通过将以下内容添加到`.gitlab-ci.yml` ,可以快速开始进行依赖项扫描,许可证扫描,静态应用程序安全测试(SAST)和秘密检测. + +``` +include: + - template: Dependency-Scanning.gitlab-ci.yml + - template: License-Scanning.gitlab-ci.yml + - template: SAST.gitlab-ci.yml + - template: Secret-Detection.gitlab-ci.yml +``` + +要添加动态应用程序安全测试(DAST)扫描,请将以下内容添加到`.gitlab-ci.yml` ,并将`https://staging.example.com`替换为登台服务器的网址: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_WEBSITE: https://staging.example.com +``` + +为确保 DAST 扫描程序*在*将应用程序部署到登台服务器*之后*运行,请查阅[DAST 完整文档](dast/index.html) . + +要添加容器扫描,请遵循[容器扫描文档中](container_scanning/index.html#requirements)列出的步骤. + +要进一步配置任何其他扫描仪,请参阅每个扫描仪的文档. + +### Override the default registry base address[](#override-the-default-registry-base-address "Permalink") + +默认情况下,GitLab 安全扫描程序使用`registry.gitlab.com/gitlab-org/security-products/analyzers`作为 Docker 映像的基址. 您可以通过将变量`SECURE_ANALYZERS_PREFIX`设置到另一个位置来全局覆盖此位置. 请注意,这会同时影响所有扫描仪. + +## Security scanning tools[](#security-scanning-tools "Permalink") + +GitLab 使用以下工具来扫描和报告项目中发现的已知漏洞. + +| 安全扫描工具 | Description | +| --- | --- | +| [Container Scanning](container_scanning/index.html) | 扫描 Docker 容器中的已知漏洞. | +| [Dependency List](dependency_list/index.html) | 查看项目的依存关系及其已知漏洞. | +| [Dependency Scanning](dependency_scanning/index.html) | 分析您的依赖项是否存在已知漏洞. | +| [Dynamic Application Security Testing (DAST)](dast/index.html) | 分析运行中的 Web 应用程序是否存在已知漏洞. | +| [Secret Detection](secret_detection/index.html) | 分析 Git 历史记录以了解泄露的机密. | +| [Security Dashboard](security_dashboard/index.html) | 查看所有项目和组中的漏洞. | +| [Static Application Security Testing (SAST)](sast/index.html) | Analyze source code for known vulnerabilities. | + +## Security Scanning with Auto DevOps[](#security-scanning-with-auto-devops "Permalink") + +启用[自动 DevOps 时](../../topics/autodevops/) ,将使用默认设置配置所有 GitLab 安全扫描工具. + +* [Auto SAST](../../topics/autodevops/stages.html#auto-sast-ultimate) +* [Auto Secret Detection](../../topics/autodevops/stages.html#auto-secret-detection-ultimate) +* [Auto DAST](../../topics/autodevops/stages.html#auto-dast-ultimate) +* [Auto Dependency Scanning](../../topics/autodevops/stages.html#auto-dependency-scanning-ultimate) +* [Auto License Compliance](../../topics/autodevops/stages.html#auto-license-compliance-ultimate) +* [Auto Container Scanning](../../topics/autodevops/stages.html#auto-container-scanning-ultimate) + +虽然您无法直接自定义 Auto DevOps,但可以[在项目的`.gitlab-ci.yml`文件中包括 Auto DevOps 模板](../../topics/autodevops/customize.html#customizing-gitlab-ciyml) . + +## Maintenance and update of the vulnerabilities database[](#maintenance-and-update-of-the-vulnerabilities-database "Permalink") + +扫描工具和漏洞数据库会定期更新. + +| 安全扫描工具 | 漏洞数据库更新 | +| --- | --- | +| [Container Scanning](container_scanning/index.html) | 使用`clair` . 通过运行[`latest` Docker image 标签](https://gitlab.com/gitlab-org/gitlab/blob/438a0a56dc0882f22bdd82e700554525f552d91b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L37) ,每个作业都使用最新的`clair-db`版本. [根据作者的说法,](https://github.com/arminc/clair-local-scan#clair-server-or-local) `clair-db`数据库[每天进行更新](https://github.com/arminc/clair-local-scan#clair-server-or-local) . | +| [Dependency Scanning](dependency_scanning/index.html) | 依赖于`bundler-audit` (对于 Ruby gems), `retire.js` (对于 NPM 软件包)和`gemnasium` (GitLab 自己的所有库工具). `bundler-audit`和`retire.js`从 GitHub 存储库中获取漏洞数据,因此添加到`ruby-advisory-db`和`retire.js`立即可用. 如果有新版本,工具本身每月更新一次. [Gemnasium 数据库](https://gitlab.com/gitlab-org/security-products/gemnasium-db)至少每周更新一次. 请参阅我们[当前从发布 CVE 到更新我们产品的时间度量](https://about.gitlab.com/handbook/engineering/development/performance-indicators/#cve-issue-to-update) . | +| [Dynamic Application Security Testing (DAST)](dast/index.html) | 扫描引擎会定期更新. 请参阅[基础工具`zaproxy`](https://gitlab.com/gitlab-org/security-products/dast/blob/master/Dockerfile#L1)的[版本](https://gitlab.com/gitlab-org/security-products/dast/blob/master/Dockerfile#L1) . 扫描规则在扫描运行时下载. | +| [Static Application Security Testing (SAST)](sast/index.html) | Relies exclusively on [the tools GitLab wraps](sast/index.html#supported-languages-and-frameworks). The underlying analyzers are updated at least once per month if a relevant update is available. The vulnerabilities database is updated by the upstream tools. | + +当前,您不必更新 GitLab 即可从最新的漏洞定义中受益. 安全工具作为 Docker 映像发布. 供应商的职位定义使他们能够使用根据[语义版本控制的](https://semver.org/)主要发行标签. 工具的每个新版本都会覆盖这些标签. Docker 映像已更新为与以前的 GitLab 版本匹配,因此用户无需执行任何操作即可自动获取最新版本的扫描工具. 但是,这种方法存在一些已知问题,并且有[解决这些问题](https://gitlab.com/gitlab-org/gitlab/-/issues/9725)的[计划](https://gitlab.com/gitlab-org/gitlab/-/issues/9725) . + +## Interacting with the vulnerabilities[](#interacting-with-the-vulnerabilities "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.8 中引入. + +合并请求报告或" [安全仪表板"](security_dashboard/index.html)中的每个安全漏洞都是可操作的. 单击一个条目以查看具有多个选项的详细信息: + +* 消除[漏洞](#dismissing-a-vulnerability) :消除漏洞可在删除线中设置样式. +* [创建问题](#creating-an-issue-for-a-vulnerability) :创建一个新问题,其标题和说明已预先填充了漏洞报告中的信息. 默认情况下,此类问题是[机密的](../project/issues/confidential_issues.html) . +* [解决方案](#solutions-for-vulnerabilities-auto-remediation) :对于某些漏洞,提供了有关如何修复该漏洞的解决方案. + +[![Interacting with security reports](img/079efbfe641967c936be8ed9b033bca6.png)](img/interacting_with_vulnerability_v13_0.png) + +### View details of a DAST vulnerability[](#view-details-of-a-dast-vulnerability "Permalink") + +DAST 检测到的漏洞在实时 Web 应用程序中发生. 纠正这些类型的漏洞需要特定的信息. DAST 提供了调查和纠正根本原因所需的信息. + +要查看 DAST 漏洞的详细信息,请执行以下操作: + +1. 要查看检测到的所有漏洞: + + * 在一个项目中,转到该项目的 **安全和合规性**页面. + * 仅在合并请求中,转到合并请求的" **安全性"**选项卡. +2. 单击漏洞的描述. 提供以下详细信息: + + | Field | Description | + | --- | --- | + | Description | Description of the vulnerability. | + | Project | 检测到漏洞的名称空间和项目. | + | Method | 用于检测漏洞的 HTTP 方法. | + | URL | 检测到漏洞的 URL. | + | 请求标题 | 请求的标题. | + | 回应状态 | 从应用程序收到的响应状态. | + | 响应标题 | 从应用程序收到的响应的标头. | + | Evidence | 数据证据证明该漏洞. 通常是请求或响应的摘要,可以用来帮助验证发现是否为漏洞. | + | Identifiers | 漏洞的标识符. | + | Severity | 漏洞的严重性. | + | 扫描仪类型 | 漏洞报告的类型. | + | Links | 链接到检测到的漏洞的更多详细信息. | + | Solution | 推荐的漏洞解决方案的详细信息(可选). | + +#### Hide sensitive information in headers[](#hide-sensitive-information-in-headers "Permalink") + +HTTP 请求和响应标头可能包含敏感信息,包括 cookie 和授权凭证. 默认情况下,特定标头的内容在 DAST 漏洞报告中被屏蔽. 您可以指定要屏蔽的所有标题的列表. 有关详细信息,请参阅[隐藏敏感信息](dast/index.html#hide-sensitive-information) . + +### Dismissing a vulnerability[](#dismissing-a-vulnerability "Permalink") + +要消除漏洞,必须将其状态设置为"消除". 请按照以下步骤操作: + +1. 在"安全仪表板"中选择漏洞. +2. 从右上方的**状态**选择器菜单中选择"已**关闭"** . + +您可以通过从同一菜单中选择其他状态来撤消此操作. + +#### Adding a dismissal reason[](#adding-a-dismissal-reason "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0 中引入. + +消除漏洞时,提供这样做的理由通常很有帮助. 将漏洞的状态设置为"已撤消"后,将出现一个文本框,供您添加有关撤消的评论. 添加后,您可以对其进行编辑或删除. 随着时间的推移,这使您可以添加和更新漏洞的上下文. + +[![Dismissed vulnerability comment](img/cb3829e4d0ca25082e0f52f135a9d1de.png)](img/adding_a_dismissal_reason_v13_0.png) + +#### Dismissing multiple vulnerabilities[](#dismissing-multiple-vulnerabilities "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9 中引入. + +您可以提供多个可选原因,一次消除多个漏洞. 选中列表中每个漏洞旁边的复选框,将选择该单个漏洞. 或者,您可以通过选择表标题中的复选框来选择列表中的所有漏洞. 取消选中标题中的复选框将取消选择列表中的所有漏洞. 选择了某些漏洞后,表格顶部会显示一个菜单,您可以通过该菜单选择解雇原因. 按下"关闭选定的漏洞"按钮将立即消除所有选定的漏洞,并说明您选择的原因. + +[![Multiple vulnerability dismissal](img/fef11068ab5cc264b208a4bd3addb7fa.png)](img/multi_select_v12_9.png) + +### Creating an issue for a vulnerability[](#creating-an-issue-for-a-vulnerability "Permalink") + +您可以通过从漏洞模式中选择" **创建问题"**按钮,或使用组安全性仪表板中漏洞行右侧的"操作"按钮来创建漏洞问题. + +这在漏洞来自的项目中创建了一个[机密问题](../project/issues/confidential_issues.html) ,并使用从漏洞报告中获取的一些有用信息对其进行了预填充. 创建问题后,您将重定向到该问题,以便您可以对其进行编辑,分配或评论. + +返回组安全性仪表板后,该漏洞现在在名称旁边具有一个关联的问题. + +[![Linked issue in the group security dashboard](img/557f2cc00416c6f64286e93532f50121.png)](img/issue.png) + +### Solutions for vulnerabilities (auto-remediation)[](#solutions-for-vulnerabilities-auto-remediation "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5656) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.7. + +可以通过应用 GitLab 自动生成的解决方案来修复某些漏洞. 支持以下扫描仪: + +* [依赖项扫描](dependency_scanning/index.html) :自动补丁创建仅适用于使用`yarn`管理的 Node.js 项目. +* [Container Scanning](container_scanning/index.html) + +#### Manually applying the suggested patch[](#manually-applying-the-suggested-patch "Permalink") + +可以通过应用由 GitLab 自动生成的补丁来修复某些漏洞. 要应用此修复程序: + +1. 单击漏洞. +2. 下载并查看补丁文件`remediation.patch` . +3. 确保本地项目的签出提交与生成补丁的提交相同. +4. Run `git apply remediation.patch`. +5. 验证并将更改提交到您的分支. + +[![Apply patch for dependency scanning](img/2e2c36f66667fc52b3fb3681533dcef7.png)](img/vulnerability_solution.png) + +#### Creating a merge request from a vulnerability[](#creating-a-merge-request-from-a-vulnerability "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9224) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9. + +在某些情况下,GitLab 允许您创建一个合并请求以自动修复漏洞. 具有[解决方案的](#solutions-for-vulnerabilities-auto-remediation)任何漏洞都可以创建合并请求以自动解决问题. + +如果可以使用此操作,则漏洞模式将包含" **创建合并请求"**按钮. 单击此按钮创建合并请求,以将解决方案应用于源分支. + +[![Create merge request from vulnerability](img/6dffd31bb67148d85ebfccbfc20abfd8.png)](img/create_issue_with_list_hover.png) + +## Security approvals in merge requests[](#security-approvals-in-merge-requests "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9928) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.2. + +可以将合并请求批准配置为在合并请求引入以下安全问题之一时,需要安全团队成员的批准: + +* 一个安全漏洞 +* 违反软件许可证规定 + +安全漏洞阈值定义为`high` , `critical`或`unknown`严重性. `Vulnerability-Check`批准者组必须批准包含漏洞的合并请求. + +当 GitLab 可以评估漏洞的严重性时,等级可以是以下之一: + +* `unknown` +* `low` +* `medium` +* `high` +* `critical` + +`unknown`等级表明基础扫描仪不包含或没有提供严重等级. + +### Enabling Security Approvals within a project[](#enabling-security-approvals-within-a-project "Permalink") + +要启用安全批准,必须使用区分大小写的名称`Vulnerability-Check`创建[项目批准规则](../project/merge_requests/merge_request_approvals.html#adding--editing-a-default-approval-rule) . 该批准组必须设置为所需的批准数量大于零. 您必须具有维护者或所有者[权限](../permissions.html#project-members-permissions)才能管理批准规则. + +1. 导航到您项目的 **设置>常规,**然后展开**合并请求批准** . +2. 单击**添加批准规则** ,或单击**编辑** . + * 将**规则名称**添加或更改为`Vulnerability-Check` (区分大小写). + +[![Vulnerability Check Approver Rule](img/2c7964b63403cf1f03ea9bdbfeee96cf.png)](img/vulnerability-check_v13_0.png) + +将这个组添加到您的项目后,将为所有合并请求启用批准规则. + +任何代码更改都会导致重置所需的批准. + +当安全报告: + +* 包含`high` , `critical`或`unknown`严重性的新漏洞,无论被解雇如何. +* 在管道执行期间未生成. + +在安全报告中,批准是可选的: + +* 不包含任何新漏洞. +* 仅包含严重程度`low`或`medium`新漏洞. + +## Enabling License Approvals within a project[](#enabling-license-approvals-within-a-project "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13067) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.3. + +`License-Check`是一个批准规则,您可以启用它来允许个人或组批准包含`denied`许可证的合并请求. + +您可以启用`License-Check`的两种方式之一: + +* 使用区分大小写的名称`License-Check`创建[项目批准规则](../project/merge_requests/merge_request_approvals.html#multiple-approval-rules-premium) . +* 在[项目策略部分中为许可合规](../compliance/license_compliance/index.html#policies)创建批准组. 您必须将此批准组的所需批准数量设置为大于零. 在项目中启用该组后,将为所有合并请求启用批准规则. + +任何代码更改都会导致重置所需的批准. + +许可证报告如下时,需要批准: + +* 包含包含被`denied`的软件许可证的依赖项. +* 在管道执行期间未生成. + +许可证报告如下时,批准是可选的: + +* 不包含任何违反软件许可证的行为. +* 仅包含`allowed`或未知的新许可证. + +## Working in an offline environment[](#working-in-an-offline-environment "Permalink") + +当未连接到 Internet 时,有时会在脱机,受限连接,局域网(LAN),Intranet 或"气隙"环境中运行大多数 GitLab 安全扫描程序. + +阅读如何[在离线环境中操作安全扫描仪](offline_deployments/index.html) . + +## Using private Maven repos[](#using-private-maven-repos "Permalink") + +如果您有需要登录凭据的私有 Apache Maven 存储库,则可以使用`MAVEN_CLI_OPTS`环境变量来传递用户名和密码. 您可以在项目的设置下进行设置,以免凭据在`.gitlab-ci.yml` . + +如果用户名是`myuser`并且密码非常`verysecret`则可以在项目的设置下[设置以下变量](../../ci/variables/README.html#create-a-custom-variable-in-the-ui) : + +| Type | Key | Value | +| --- | --- | --- | +| Variable | `MAVEN_CLI_OPTS` | `--settings mysettings.xml -Drepository.password=verysecret -Drepository.user=myuser` | + +``` + + + ... + + + private_server + ${private.username} + ${private.password} + + + +``` + +## Outdated security reports[](#outdated-security-reports "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4913) . + +当为合并请求生成的安全报告过时时,合并请求会在安全小部件中显示警告消息,并提示您采取适当的措施. + +这可能在两种情况下发生: + +1. Your [source branch is behind the target branch](#source-branch-is-behind-the-target-branch). +2. The [target branch security report is out of date](#target-branch-security-report-is-out-of-date). + +### Source branch is behind the target branch[](#source-branch-is-behind-the-target-branch "Permalink") + +这意味着目标分支和源分支之间的最新公共祖先提交不是目标分支上的最新提交. 到目前为止,这是最常见的情况. + +在这种情况下,您必须重新设置基础或合并以合并来自目标分支的更改. + +[![Incorporate target branch changes](img/6564cc179b8bafb5577b9762c905010c.png)](img/outdated_report_branch_v12_9.png) + +### Target branch security report is out of date[](#target-branch-security-report-is-out-of-date "Permalink") + +发生这种情况的原因有很多,包括工作失败或新的咨询. 当合并请求显示安全报告已过期时,必须在目标分支上运行新管道. 您可以按照提供的超链接运行新管道来快速完成此操作. + +[![Run a new pipeline](img/66a70133eaa2327dce4cd61c485afcdb.png)](img/outdated_report_pipeline_v12_9.png) + +## Troubleshooting[](#troubleshooting "Permalink") + +### Getting error message `sast job: stage parameter should be [some stage name here]`[](#getting-error-message-sast-job-stage-parameter-should-be-some-stage-name-here "Permalink") + +当[包括](../../ci/yaml/README.html#includetemplate)诸如[`SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml)的`.gitlab-ci.yml`模板时,根据您的 GitLab CI / CD 配置,可能会发生以下错误: + +``` +Found errors in your .gitlab-ci.yml: + +* sast job: stage parameter should be unit-tests +``` + +如果未在`.gitlab-ci.yml`声明包含作业的阶段(名为`test` ),则会出现此错误. 要解决此问题,您可以: + +* 在`.gitlab-ci.yml`添加一个`test`阶段. +* 更改包含的安全作业的默认阶段. 例如,使用 SpotBugs(SAST): + + ``` + include: + template: SAST.gitlab-ci.yml + + spotbugs-sast: + stage: unit-tests + ``` + +[了解有关覆盖 SAST 作业的更多信息](sast/index.html#overriding-sast-jobs) . 所有安全扫描工具都定义了它们的阶段,因此,所有这些工具都可能发生此错误. + +### Getting error message `sast job: config key may not be used with 'rules': only/except`[](#getting-error-message-sast-job-config-key-may-not-be-used-with-rules-onlyexcept "Permalink") + +当[包括](../../ci/yaml/README.html#includetemplate)诸如[`SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml)的`.gitlab-ci.yml`模板时,根据您的 GitLab CI / CD 配置,可能会发生以下错误: + +``` +Found errors in your .gitlab-ci.yml: + + jobs:sast config key may not be used with `rules`: only/except +``` + +当[`only`使用已弃用的或`except`语法`except`](../../ci/yaml/README.html#onlyexcept-basic) [覆盖](sast/index.html#overriding-sast-jobs)了包含作业的`rules`配置时,将出现此错误[.](../../ci/yaml/README.html#onlyexcept-basic) 若要解决此问题,您必须: + +* [Transition your `only/except` syntax to `rules`](#transitioning-your-onlyexcept-syntax-to-rules). +* (Temporarily) [Pin your templates to the deprecated versions](#pin-your-templates-to-the-deprecated-versions) + +[Learn more on overriding SAST jobs](sast/index.html#overriding-sast-jobs). + +#### Transitioning your `only/except` syntax to `rules`[](#transitioning-your-onlyexcept-syntax-to-rules "Permalink") + +覆盖模板以控制作业执行时, [`only`或`except`](../../ci/yaml/README.html#onlyexcept-basic)先前实例不再兼容,必须转换为[`rules`语法](../../ci/yaml/README.html#rules) . + +如果您的替代旨在将作业限制为仅在`master`运行,则先前的语法类似于: + +``` +include: + - template: SAST.gitlab-ci.yml + +# Ensure that the scanning is only executed on master or merge requests +spotbugs-sast: + only: + refs: + - master + - merge_requests +``` + +要将上面的配置转换为新的`rules`语法,重写将如下编写: + +``` +include: + - template: SAST.gitlab-ci.yml + +# Ensure that the scanning is only executed on master or merge requests +spotbugs-sast: + rules: + - if: $CI_COMMIT_BRANCH == "master" + - if: $CI_MERGE_REQUEST_ID +``` + +如果您的覆盖旨在限制作业仅在分支而不是标签上运行,则其外观类似于: + +``` +include: + - template: SAST.gitlab-ci.yml + +# Ensure that the scanning is not executed on tags +spotbugs-sast: + except: + - tags +``` + +为了过渡到新的`rules`语法,重写将被重写为: + +``` +include: + - template: SAST.gitlab-ci.yml + +# Ensure that the scanning is not executed on tags +spotbugs-sast: + rules: + - if: $CI_COMMIT_TAG == null +``` + +[Learn more on the usage of `rules`](../../ci/yaml/README.html#rules). + +#### Pin your templates to the deprecated versions[](#pin-your-templates-to-the-deprecated-versions "Permalink") + +为了确保获得最新支持,我们**强烈**建议您迁移到[`rules`](../../ci/yaml/README.html#rules) . + +如果您无法立即更新 CI 配置,则有几种解决方法,其中涉及固定到以前的模板版本,例如: + +``` + include: + remote: 'https://gitlab.com/gitlab-org/gitlab/-/raw/12-10-stable-ee/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml' +``` + +此外,我们提供了一个专用项目,其中包含版本控制的旧版模板. 这对于脱机设置或希望使用[Auto DevOps 的](../../topics/autodevops/index.html)任何人很有用. + +[旧版模板项目](https://gitlab.com/gitlab-org/auto-devops-v12-10)中提供了说明. \ No newline at end of file diff --git a/docs/050.md b/docs/050.md new file mode 100644 index 0000000000000000000000000000000000000000..0afab18f910a62a81685fdc8e6f150ca065e560f --- /dev/null +++ b/docs/050.md @@ -0,0 +1,26 @@ +# Security Configuration + +> 原文:[https://docs.gitlab.com/ee/user/application_security/configuration/](https://docs.gitlab.com/ee/user/application_security/configuration/) + +* [Overview](#overview) +* [Limitations](#limitations) + +# Security Configuration[](#security-configuration-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20711) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6. + +## Overview[](#overview "Permalink") + +安全配置页面显示每个安全功能的配置状态,可以通过项目的侧边栏导航来访问. + +[![Screenshot of security configuration page](img/c5fbd1d44b70c599ae2cc8751ccfca14.png)](../img/security_configuration_page_v13_2.png) + +该页面使用项目的最新默认分支[CI 管道](../../../ci/pipelines/index.html)来确定每个功能部件的配置状态. 如果管道中存在具有预期安全报告工件的作业,则认为该功能已配置. + +**注意:**如果最新的管道使用了[Auto DevOps](../../../topics/autodevops/index.html) ,则默认情况下将配置所有安全功能. + +## Limitations[](#limitations "Permalink") + +尚无法使用配置页启用或禁用大多数功能. 但是,可以通过该页面上每个功能旁边的链接找到有关如何启用或禁用功能的说明. + +如果项目没有现有的 CI 配置,则可以通过单击"管理"列下的"启用合并请求"按钮来启用 SAST 功能. 将来的工作会将其扩展到编辑*现有* CI 配置以及其他安全功能. \ No newline at end of file diff --git a/docs/051.md b/docs/051.md new file mode 100644 index 0000000000000000000000000000000000000000..13125b0ab37d72d3c70c14c3c4f4b3f669f5e7b5 --- /dev/null +++ b/docs/051.md @@ -0,0 +1,321 @@ +# Container Scanning + +> 原文:[https://docs.gitlab.com/ee/user/application_security/container_scanning/](https://docs.gitlab.com/ee/user/application_security/container_scanning/) + +* [Overview](#overview) +* [Requirements](#requirements) +* [Configuration](#configuration) + * [Customizing the Container Scanning settings](#customizing-the-container-scanning-settings) + * [Available variables](#available-variables) + * [Overriding the Container Scanning template](#overriding-the-container-scanning-template) + * [Vulnerability allowlisting](#vulnerability-allowlisting) + * [Running Container Scanning in an offline environment](#running-container-scanning-in-an-offline-environment) + * [Requirements for offline Container Scanning](#requirements-for-offline-container-scanning) + * [Make GitLab Container Scanning analyzer images available inside your Docker registry](#make-gitlab-container-scanning-analyzer-images-available-inside-your-docker-registry) + * [Set Container Scanning CI job variables to use local Container Scanner analyzers](#set-container-scanning-ci-job-variables-to-use-local-container-scanner-analyzers) + * [Automating Container Scanning vulnerability database updates with a pipeline](#automating-container-scanning-vulnerability-database-updates-with-a-pipeline) +* [Running the standalone Container Scanning Tool](#running-the-standalone-container-scanning-tool) +* [Reports JSON format](#reports-json-format) +* [Security Dashboard](#security-dashboard) +* [Vulnerabilities database update](#vulnerabilities-database-update) +* [Interacting with the vulnerabilities](#interacting-with-the-vulnerabilities) +* [Solutions for vulnerabilities (auto-remediation)](#solutions-for-vulnerabilities-auto-remediation) +* [Troubleshooting](#troubleshooting) + * [`docker: Error response from daemon: failed to copy xattrs`](#docker-error-response-from-daemon-failed-to-copy-xattrs) + +# Container Scanning[](#container-scanning-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4. + +## Overview[](#overview "Permalink") + +应用程序的 Docker 映像本身可能基于包含已知漏洞的 Docker 映像. 通过在管道中包含一个额外的作业来扫描这些漏洞并将其显示在合并请求中,您可以使用 GitLab 来审核基于 Docker 的应用程序. 默认情况下,GitLab 中的容器扫描基于[Clair](https://github.com/quay/clair)和[Klar](https://github.com/optiopay/klar) ,这是用于对容器中的漏洞进行静态分析的开源工具. [GitLab 的 Klar 分析仪](https://gitlab.com/gitlab-org/security-products/analyzers/klar/)扫描容器并用作 Clair 的包装纸. + +**注意:**要将除 Clair 和 Klar 以外的其他[安全扫描器集成](../../../development/integrations/secure.html)到 GitLab 中,请参阅" [安全扫描器集成"](../../../development/integrations/secure.html) . + +您可以通过执行以下任一操作来启用容器扫描: + +* 在现有的`.gitlab-ci.yml`文件中[包括 CI 作业](#configuration) . +* 隐式使用[Auto DevOps](../../../topics/autodevops/index.html)提供的[自动](../../../topics/autodevops/index.html) [容器扫描](../../../topics/autodevops/stages.html#auto-container-scanning-ultimate) . + +GitLab 比较发现的源分支与目标分支之间的漏洞,并在合并请求中直接显示信息. + +[![Container Scanning Widget](img/81b83780f68abcbb32edb1eb48002a4d.png)](img/container_scanning_v13_2.png) + +## Requirements[](#requirements "Permalink") + +要在管道中启用容器扫描,您需要以下内容: + +* 带有[Docker](https://docs.gitlab.com/runner/executors/docker.html)或[Kubernetes](https://docs.gitlab.com/runner/install/kubernetes.html)执行器的[GitLab Runner](https://docs.gitlab.com/runner/) . +* Docker `18.09.03`或更高版本与 Runner 安装在同一台计算机上. 如果您在 GitLab.com 上使用共享的 Runners,那么情况已经如此. +* [构建](../../packages/container_registry/index.html#container-registry-examples-with-gitlab-cicd) Docker 镜像[并将其推](../../packages/container_registry/index.html#container-registry-examples-with-gitlab-cicd)送到项目的容器注册表中. Docker 映像的名称应使用以下[预定义的环境变量](../../../ci/variables/predefined_variables.html) : + + ``` + $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA + ``` + + 您可以在`.gitlab-ci.yml`文件中直接使用它们: + + ``` + build: + image: docker:19.03.12 + stage: build + services: + - docker:19.03.12-dind + variables: + IMAGE_TAG: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA + script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker build -t $IMAGE_TAG . + - docker push $IMAGE_TAG + ``` + +## Configuration[](#configuration "Permalink") + +启用容器扫描的方式取决于您的 GitLab 版本: + +* GitLab 11.9 及更高版本: [包括](../../../ci/yaml/README.html#includetemplate) GitLab 安装随附的[`Container-Scanning.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml) . +* 11.9 之前的 GitLab 版本:从[`Container-Scanning.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml)复制并使用作业. + +要包括`Container-Scanning.gitlab-ci.yml`模板(GitLab 11.9 及更高版本),请将以下内容添加到您的`.gitlab-ci.yml`文件中: + +``` +include: + - template: Container-Scanning.gitlab-ci.yml +``` + +包含的模板: + +* 在 CI / CD 管道中创建`container_scanning`作业. +* 从项目的[Container Registry 中](../../packages/container_registry/index.html)拉出已构建的 Docker 映像(请参阅[要求](#requirements) ),并扫描其可能的漏洞. + +GitLab 将结果保存为" [容器扫描"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportscontainer_scanning-ultimate) ,您可以稍后下载和分析. 下载时,您始终会收到最新的工件. + +以下是一个示例`.gitlab-ci.yml` ,用于构建您的 Docker 映像,将其推送到 Container Registry 并扫描容器: + +``` +variables: + DOCKER_DRIVER: overlay2 + +stages: + - build + - test + +build: + image: docker:stable + stage: build + services: + - docker:19.03.12-dind + variables: + IMAGE: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA + script: + - docker info + - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY + - docker build -t $IMAGE . + - docker push $IMAGE + +include: + - template: Container-Scanning.gitlab-ci.yml +``` + +### Customizing the Container Scanning settings[](#customizing-the-container-scanning-settings "Permalink") + +There may be cases where you want to customize how GitLab scans your containers. For example, you may want to enable more verbose output from Clair or Klar, access a Docker registry that requires authentication, and more. To change such settings, use the [`variables`](../../../ci/yaml/README.html#variables) parameter in your `.gitlab-ci.yml` to set [environment variables](#available-variables). The environment variables you set in your `.gitlab-ci.yml` overwrite those in `Container-Scanning.gitlab-ci.yml`. + +此示例[包括](../../../ci/yaml/README.html#include)容器扫描模板,并通过将`CLAIR_OUTPUT`环境变量设置为`High`来启用 Clair 的详细输出: + +``` +include: + - template: Container-Scanning.gitlab-ci.yml + +variables: + CLAIR_OUTPUT: High +``` + +#### Available variables[](#available-variables "Permalink") + +可以使用环境变量[配置](#customizing-the-container-scanning-settings)容器扫描. + +| 环境变量 | Description | Default | +| --- | --- | --- | +| `SECURE_ANALYZERS_PREFIX` | 设置用于下载分析器的 Docker 注册表基地址. | `"registry.gitlab.com/gitlab-org/security-products/analyzers"` | +| `KLAR_TRACE` | 设置为 true 可启用 klar 的更多详细输出. | `"false"` | +| `CLAIR_TRACE` | 设置为 true 可启用 clair 服务器进程的更多详细输出. | `"false"` | +| `DOCKER_USER` | 用于访问需要身份验证的 Docker 注册表的用户名. | `$CI_REGISTRY_USER` | +| `DOCKER_PASSWORD` | 访问需要身份验证的 Docker 注册表的密码. | `$CI_REGISTRY_PASSWORD` | +| `CLAIR_OUTPUT` | 严重级别阈值. 严重级别高于或等于此阈值的漏洞将被输出. 支持的级别为`Unknown` , `Negligible` , `Low` , `Medium` , `High` , `Critical`和`Defcon1` . | `Unknown` | +| `REGISTRY_INSECURE` | 允许[Klar](https://github.com/optiopay/klar)访问不安全的注册表(仅 HTTP). 仅应在本地测试图像时设置为`true` . | `"false"` | +| `DOCKER_INSECURE` | 允许[Klar](https://github.com/optiopay/klar)使用带有错误(或自签名)SSL 证书的 HTTPS 访问安全的 Docker 注册表. | `"false"` | +| `CLAIR_VULNERABILITIES_DB_URL` | (不推荐**使用-改为使用`CLAIR_DB_CONNECTION_STRING`** )此变量在`Container-Scanning.gitlab-ci.yml`文件的[services 部分](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23)中显式设置,并且默认为`Container-Scanning.gitlab-ci.yml` `clair-vulnerabilities-db` . 该值表示[托管漏洞定义](https://hub.docker.com/r/arminc/clair-db)的[PostgreSQL 服务器](https://hub.docker.com/r/arminc/clair-db)正在运行的地址,除非您按照" [运行独立容器扫描工具"](#running-the-standalone-container-scanning-tool)部分中的说明在本地运行映像,否则**不应更改**该地址. | `clair-vulnerabilities-db` | +| `CLAIR_DB_CONNECTION_STRING` | 该变量表示[托管漏洞定义](https://hub.docker.com/r/arminc/clair-db)数据库的[PostgreSQL 服务器](https://hub.docker.com/r/arminc/clair-db)的[连接字符串](https://s0www0postgresql0org.icopy.site/docs/9.3/libpq-connect.html) ,除非您按照" [运行独立容器扫描工具"](#running-the-standalone-container-scanning-tool)部分中的说明在本地运行映像,否则**不应更改**该变量. 连接字符串的主机值必须与`Container-Scanning.gitlab-ci.yml`模板文件的[别名](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23)值匹配,该[别名](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23)默认为`clair-vulnerabilities-db` . | `postgresql://postgres:password@clair-vulnerabilities-db:5432/postgres?sslmode=disable&statement_timeout=60000` | +| `CI_APPLICATION_REPOSITORY` | Docker repository URL for the image to be scanned. | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` | +| `CI_APPLICATION_TAG` | 待扫描图像的 Docker 存储库标签. | `$CI_COMMIT_SHA` | +| `CLAIR_DB_IMAGE` | [托管漏洞定义](https://hub.docker.com/r/arminc/clair-db)的[PostgreSQL 服务器](https://hub.docker.com/r/arminc/clair-db)的 Docker 映像名称和标记. 使用特定版本覆盖此值可能很有用,例如,为了进行集成测试而提供一致的漏洞集,或在本地进行脱机安装时引用本地托管的漏洞数据库. | `arminc/clair-db:latest` | +| `CLAIR_DB_IMAGE_TAG` | (不推荐**使用-改为使用`CLAIR_DB_IMAGE`** ) [托管漏洞定义](https://hub.docker.com/r/arminc/clair-db)的[PostgreSQL 服务器](https://hub.docker.com/r/arminc/clair-db)的 Docker 映像标记. 可以使用特定版本覆盖此值,例如,为集成测试目的提供一致的漏洞集很有用. | `latest` | +| `DOCKERFILE_PATH` | 用于生成补救的`Dockerfile`的路径. 默认情况下,扫描程序将在项目的根目录中查找名为`Dockerfile`的文件,因此仅当您的`Dockerfile`位于非标准位置(例如子目录)时,才应配置此变量. 有关更多详细信息,请参见[漏洞解决方案](#solutions-for-vulnerabilities-auto-remediation) . | `Dockerfile` | +| `ADDITIONAL_CA_CERT_BUNDLE` | 您要信任的 CA 证书捆绑包. | ”” | +| `SECURE_LOG_LEVEL` | 可用的日志级别为: `fatal` , `error` , `warn` , `info` , `debug` | `info` | + +### Overriding the Container Scanning template[](#overriding-the-container-scanning-template "Permalink") + +如果要覆盖作业定义(例如,更改诸如`variables`属性),则必须在`container_scanning`模板之后声明一个`container_scanning`作业,然后指定任何其他键. 例如: + +``` +include: + - template: Container-Scanning.gitlab-ci.yml + +container_scanning: + variables: + GIT_STRATEGY: fetch +``` + +**Deprecated:** GitLab 13.0 and later doesn’t support [`only` and `except`](../../../ci/yaml/README.html#onlyexcept-basic). When overriding the template, you must use [`rules`](../../../ci/yaml/README.html#rules) instead. + +### Vulnerability allowlisting[](#vulnerability-allowlisting "Permalink") + +要允许列表特定漏洞,请按照下列步骤操作: + +1. 设置`GIT_STRATEGY: fetch`按照[覆盖容器扫描模板中](#overriding-the-container-scanning-template)的说明, `GIT_STRATEGY: fetch` `.gitlab-ci.yml`文件. +2. 在名为`vulnerability-allowlist.yml`的 YAML 文件中定义允许列出的漏洞. 这必须使用[许可清单示例文件中](https://gitlab.com/gitlab-org/security-products/analyzers/klar/-/raw/master/testdata/vulnerability-allowlist.yml)描述的格式. +3. 将`vulnerability-allowlist.yml`文件添加到项目的 Git 存储库中. + +### Running Container Scanning in an offline environment[](#running-container-scanning-in-an-offline-environment "Permalink") + +对于在通过互联网有限,受限或间歇性访问外部资源的环境中进行自我管理的 GitLab 实例,需要进行一些调整才能使容器扫描作业成功运行. 有关更多信息,请参阅[脱机环境](../offline_deployments/index.html) . + +#### Requirements for offline Container Scanning[](#requirements-for-offline-container-scanning "Permalink") + +要在脱机环境中使用容器扫描,您需要: + +* GitLab 亚军与[`docker`或`kubernetes`执行](#requirements) . +* 要使用 Container Scanning [分析器](https://gitlab.com/gitlab-org/security-products/analyzers/klar)映像的副本配置本地 Docker Container Registry,请在[Container Scanning 容器注册表中找到](https://gitlab.com/gitlab-org/security-products/analyzers/klar/container_registry) . + +**注意:** GitLab Runner 的[默认`pull policy`为`always`](https://docs.gitlab.com/runner/executors/docker.html) ,这意味着即使本地副本可用,Runner 也会尝试从 GitLab 容器注册表中拉取 Docker 映像. 如果您只喜欢使用本地可用的 Docker 映像,则可以在离线环境[`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html) GitLab Runner 的[`pull_policy`设置为`if-not-present`](https://docs.gitlab.com/runner/executors/docker.html) . 但是,如果不在离线环境中,我们建议将拉取策略设置保持为`always` ,因为这样可以在 CI / CD 管道中使用更新的扫描仪. + +#### Make GitLab Container Scanning analyzer images available inside your Docker registry[](#make-gitlab-container-scanning-analyzer-images-available-inside-your-docker-registry "Permalink") + +对于容器扫描,将以下默认图像从`registry.gitlab.com`导入[本地 Docker 容器注册表](../../packages/container_registry/index.html) : + +``` +registry.gitlab.com/gitlab-org/security-products/analyzers/klar +https://hub.docker.com/r/arminc/clair-db +``` + +将 Docker 映像导入本地脱机 Docker 注册表的过程取决于**您的网络安全策略** . 请咨询您的 IT 员工,以找到可以导入或临时访问外部资源的已接受和批准的流程. 请注意,这些扫描程序会[定期](../index.html#maintenance-and-update-of-the-vulnerabilities-database)使用新定义进行[更新](../index.html#maintenance-and-update-of-the-vulnerabilities-database) ,因此请考虑您是否能够自己进行定期更新. + +有关更多信息,请参见[有关如何使用管道更新映像的特定步骤](#automating-container-scanning-vulnerability-database-updates-with-a-pipeline) . + +有关将 Docker 映像保存和传输为文件的详细信息,请参阅 Docker 有关[`docker save`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/save/) , [`docker load`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/load/) , [`docker export`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/export/)和[`docker import`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/import/)的文档. + +#### Set Container Scanning CI job variables to use local Container Scanner analyzers[](#set-container-scanning-ci-job-variables-to-use-local-container-scanner-analyzers "Permalink") + +1. [覆盖](#overriding-the-container-scanning-template) `.gitlab-ci.yml`文件中[的容器扫描模板](#overriding-the-container-scanning-template) ,以引用本地 Docker 容器注册表中托管的 Docker 映像: + + ``` + include: + - template: Container-Scanning.gitlab-ci.yml + + container_scanning: + image: $CI_REGISTRY/namespace/gitlab-klar-analyzer + variables: + CLAIR_DB_IMAGE: $CI_REGISTRY/namespace/clair-vulnerabilities-db + ``` + +2. 如果您的本地 Docker 容器注册表正在通过`HTTPS`安全运行,但是您使用的是自签名证书,则必须在`.gitlab-ci.yml`的上述`container_scanning`部分中将`DOCKER_INSECURE: "true"`设置为. + +#### Automating Container Scanning vulnerability database updates with a pipeline[](#automating-container-scanning-vulnerability-database-updates-with-a-pipeline "Permalink") + +设置[计划的管道](../../../ci/pipelines/schedules.html)以按照预设的计划自动构建漏洞数据库的新版本可能是值得的. 使用管道自动执行此操作意味着您不必每次都手动进行操作. 您可以使用以下`.gitlab-yml.ci`作为模板: + +``` +image: docker:stable + +stages: + - build + +build_latest_vulnerabilities: + stage: build + services: + - docker:19.03.12-dind + script: + - docker pull arminc/clair-db:latest + - docker tag arminc/clair-db:latest $CI_REGISTRY/namespace/clair-vulnerabilities-db + - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY + - docker push $CI_REGISTRY/namespace/clair-vulnerabilities-db +``` + +上面的模板适用于在本地安装上运行的 GitLab Docker 注册表,但是,如果您使用的是非 GitLab Docker 注册表,则需要更改`$CI_REGISTRY`值和 Docker `docker login`凭据以匹配以下内容:您的本地注册表. + +## Running the standalone Container Scanning Tool[](#running-the-standalone-container-scanning-tool "Permalink") + +可以对 Docker 容器运行[GitLab 容器扫描工具](https://gitlab.com/gitlab-org/security-products/analyzers/klar) ,而无需在 CI 作业的上下文中运行它. 要直接扫描图像,请按照下列步骤操作: + +1. Run [Docker Desktop](https://www.docker.com/products/docker-desktop) or [Docker Machine](https://github.com/docker/machine). +2. 运行最新的[预填充漏洞数据库](https://hub.docker.com/repository/docker/arminc/clair-db) Docker 映像: + + ``` + docker run -p 5432:5432 -d --name clair-db arminc/clair-db:latest + ``` + +3. Configure an environment variable to point to your local machine’s IP address (or insert your IP address instead of the `LOCAL_MACHINE_IP_ADDRESS` variable in the `CLAIR_DB_CONNECTION_STRING` in the next step): + + ``` + export LOCAL_MACHINE_IP_ADDRESS=your.local.ip.address + ``` + +4. 运行分析器的 Docker 映像,并在`CI_APPLICATION_REPOSITORY`和`CI_APPLICATION_TAG`环境变量中传递要分析的映像和标签: + + ``` + docker run \ + --interactive --rm \ + --volume "$PWD":/tmp/app \ + -e CI_PROJECT_DIR=/tmp/app \ + -e CLAIR_DB_CONNECTION_STRING="postgresql://postgres:password@${LOCAL_MACHINE_IP_ADDRESS}:5432/postgres?sslmode=disable&statement_timeout=60000" \ + -e CI_APPLICATION_REPOSITORY=registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256 \ + -e CI_APPLICATION_TAG=bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e \ + registry.gitlab.com/gitlab-org/security-products/analyzers/klar + ``` + +结果存储在`gl-container-scanning-report.json` . + +## Reports JSON format[](#reports-json-format "Permalink") + +容器扫描工具会发出 JSON 报告文件. 有关更多信息,请参见此[报告](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json)的[架构](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json) . + +这是示例容器扫描报告: + +``` +{ "version": "2.3", "vulnerabilities": [ { "id": "ac0997ad-1006-4c81-81fb-ee2bbe6e78e3", "category": "container_scanning", "message": "CVE-2019-3462 in apt", "description": "Incorrect sanitation of the 302 redirect field in HTTP transport method of apt versions 1.4.8 and earlier can lead to content injection by a MITM attacker, potentially leading to remote code execution on the target machine.", "severity": "High", "confidence": "Unknown", "solution": "Upgrade apt from 1.4.8 to 1.4.9", "scanner": { "id": "klar", "name": "klar" }, "location": { "dependency": { "package": { "name": "apt" }, "version": "1.4.8" }, "operating_system": "debian:9", "image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e" }, "identifiers": [ { "type": "cve", "name": "CVE-2019-3462", "value": "CVE-2019-3462", "url": "https://security-tracker.debian.org/tracker/CVE-2019-3462" } ], "links": [ { "url": "https://security-tracker.debian.org/tracker/CVE-2019-3462" } ] } ], "remediations": [ { "fixes": [ { "id": "c0997ad-1006-4c81-81fb-ee2bbe6e78e3" } ], "summary": "Upgrade apt from 1.4.8 to 1.4.9", "diff": "YXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCB1cGdyYWRlIC15IGFwdA==" } ] } +``` + +## Security Dashboard[](#security-dashboard "Permalink") + +[安全仪表板](../security_dashboard/index.html)向您显示组,项目和管道中所有安全漏洞的概述. + +## Vulnerabilities database update[](#vulnerabilities-database-update "Permalink") + +有关漏洞数据库更新的更多信息,请查看[维护表](../index.html#maintenance-and-update-of-the-vulnerabilities-database) . + +## Interacting with the vulnerabilities[](#interacting-with-the-vulnerabilities "Permalink") + +一旦发现漏洞,便可以[与其进行交互](../index.html#interacting-with-the-vulnerabilities) . + +## Solutions for vulnerabilities (auto-remediation)[](#solutions-for-vulnerabilities-auto-remediation "Permalink") + +可以通过应用 GitLab 自动生成的解决方案来修复某些漏洞. + +为了使整治的支持,对扫描工具*必须*能够访问`Dockerfile`指定由[`DOCKERFILE_PATH`](#available-variables)环境变量. 为确保扫描工具可以访问此文件,有必要设置[`GIT_STRATEGY: fetch`](../../../ci/yaml/README.html#git-strategy)按照本文档中" [覆盖容器扫描模板"](#overriding-the-container-scanning-template)部分中介绍的说明,在`.gitlab-ci.yml`文件中进行[`GIT_STRATEGY: fetch`](../../../ci/yaml/README.html#git-strategy) . + +阅读有关[漏洞解决方案的](../index.html#solutions-for-vulnerabilities-auto-remediation)更多信息. + +## Troubleshooting[](#troubleshooting "Permalink") + +### `docker: Error response from daemon: failed to copy xattrs`[](#docker-error-response-from-daemon-failed-to-copy-xattrs "Permalink") + +当 GitLab Runner 使用 Docker 执行程序并使用 NFS 时(例如, `/var/lib/docker`在 NFS 挂载上),容器扫描可能会失败,并显示以下错误: + +``` +docker: Error response from daemon: failed to copy xattrs: failed to set xattr "security.selinux" on /path/to/file: operation not supported. +``` + +这是由于 Docker 中的一个错误而导致的,该错误现已[修复](https://github.com/containerd/continuity/pull/138 "fs:添加 WithAllowXAttrErrors CopyOpt") . 为避免该错误,请确保 Runner 使用的 Docker 版本为`18.09.03`或更高. 有关更多信息,请参见[问题#10241](https://gitlab.com/gitlab-org/gitlab/-/issues/10241 "调查为什么容器扫描不适用于 NFS 挂载") . \ No newline at end of file diff --git a/docs/052.md b/docs/052.md new file mode 100644 index 0000000000000000000000000000000000000000..4c8515bb49211c2eb62332dba94676452a06748f --- /dev/null +++ b/docs/052.md @@ -0,0 +1,370 @@ +# Dependency Scanning + +> 原文:[https://docs.gitlab.com/ee/user/application_security/dependency_scanning/](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) + +* [Overview](#overview) +* [Requirements](#requirements) +* [Supported languages and package managers](#supported-languages-and-package-managers) +* [Contribute your scanner](#contribute-your-scanner) +* [Configuration](#configuration) + * [Customizing the Dependency Scanning settings](#customizing-the-dependency-scanning-settings) + * [Overriding Dependency Scanning jobs](#overriding-dependency-scanning-jobs) + * [Available variables](#available-variables) + * [Configuring Dependency Scanning](#configuring-dependency-scanning) + * [Configuring Docker-in-Docker orchestrator](#configuring-docker-in-docker-orchestrator) + * [Configuring specific analyzers used by Dependency Scanning](#configuring-specific-analyzers-used-by-dependency-scanning) + * [Using private Maven repos](#using-private-maven-repos) + * [Enabling Docker-in-Docker](#enabling-docker-in-docker) +* [Interacting with the vulnerabilities](#interacting-with-the-vulnerabilities) +* [Solutions for vulnerabilities (auto-remediation)](#solutions-for-vulnerabilities-auto-remediation) +* [Security Dashboard](#security-dashboard) +* [Vulnerabilities database update](#vulnerabilities-database-update) +* [Dependency List](#dependency-list) +* [Reports JSON format](#reports-json-format) +* [Versioning and release process](#versioning-and-release-process) +* [Contributing to the vulnerability database](#contributing-to-the-vulnerability-database) +* [Running Dependency Scanning in an offline environment](#running-dependency-scanning-in-an-offline-environment) + * [Requirements for offline Dependency Scanning](#requirements-for-offline-dependency-scanning) + * [Make GitLab Dependency Scanning analyzer images available inside your Docker registry](#make-gitlab-dependency-scanning-analyzer-images-available-inside-your-docker-registry) + * [Set Dependency Scanning CI job variables to use local Dependency Scanning analyzers](#set-dependency-scanning-ci-job-variables-to-use-local-dependency-scanning-analyzers) + * [Specific settings for languages and package managers](#specific-settings-for-languages-and-package-managers) + * [JavaScript (npm and yarn) projects](#javascript-npm-and-yarn-projects) + * [Ruby (gem) projects](#ruby-gem-projects) + * [Python (setuptools)](#python-setuptools) +* [Limitations](#limitations) + * [Referencing local dependencies using a path in JavaScript projects](#referencing-local-dependencies-using-a-path-in-javascript-projects) +* [Troubleshooting](#troubleshooting) + * [`Error response from daemon: error processing tar file: docker-tar: relocation error`](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) + +# Dependency Scanning[](#dependency-scanning-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5105) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.7. + +在开发和测试应用程序时,例如当应用程序使用已知的易受攻击的外部(开源)库时,"依赖关系扫描"有助于自动在依赖项中查找安全漏洞. + +## Overview[](#overview "Permalink") + +如果您使用的是[GitLab CI / CD](../../../ci/README.html) ,则可以使用"依赖关系扫描"来分析依赖关系中的已知漏洞. 扫描所有依赖项,包括传递性依赖项(也称为嵌套依赖项). 您可以通过在现有`.gitlab-ci.yml`文件中[包括依赖扫描模板](#configuration) ,或通过隐式使用[Auto DevOps](../../../topics/autodevops/index.html)提供的[自动依赖扫描](../../../topics/autodevops/stages.html#auto-dependency-scanning-ultimate)来利用[依赖扫描](../../../topics/autodevops/stages.html#auto-dependency-scanning-ultimate) . + +GitLab 检查"依赖性扫描"报告,比较发现的源分支和目标分支之间的漏洞,并显示有关合并请求的信息. + +[![Dependency Scanning Widget](img/6d49650d7eab0173612011fa6d81dc4e.png)](img/dependency_scanning_v13_2.png) + +结果按漏洞的严重性排序: + +1. Critical +2. High +3. Medium +4. Low +5. Unknown +6. 其他一切 + +## Requirements[](#requirements "Permalink") + +要运行依赖扫描作业,默认情况下,你需要 GitLab 亚军与[`docker`](https://docs.gitlab.com/runner/executors/docker.html)或[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html)执行. 如果您在 GitLab.com 上使用共享的 Runners,则默认启用该功能. + +**注意:**如果使用自己的 Runners,请确保已安装的 Docker 版本**不是** `19.03.0` . 有关详细[信息](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) ,请参见[故障排除信息](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) . + +从 GitLab 13.0 开始,仅当您已[启用 Docker-in-Docker 进行依赖项扫描](#enabling-docker-in-docker)时,才需要 Docker 特权模式. + +## Supported languages and package managers[](#supported-languages-and-package-managers "Permalink") + +GitLab 依赖于[`rules`](../../../ci/yaml/README.html#rules)来启动相关分析器,具体取决于存储库中检测到的语言. 当前的检测逻辑将最大搜索深度限制为两个级别. 例如,如果存储库包含`Gemfile`或`api/Gemfile`文件,则启用`gemnasium-dependency_scanning`作业,但如果唯一受支持的依赖性文件是`api/client/Gemfile` . + +支持以下语言和依赖项管理器: + +| 语言(程序包管理器) | 支援的档案 | 扫描工具 | +| --- | --- | --- | +| Java ([Gradle](https://s0gradle0org.icopy.site/), [Maven](https://maven.apache.org/)) | `build.gradle`, `build.gradle.kts`, `pom.xml` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | +| JavaScript( [npm](https://s0www0npmjs0com.icopy.site/) , [yarn](https://classic.yarnpkg.com/en/) ) | `package-lock.json`, `npm-shrinkwrap.json`, `yarn.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium), [Retire.js](https://retirejs.github.io/retire.js/) | +| 去( [Golang](https://s0golang0org.icopy.site/) ) | `go.sum` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | +| PHP( [作曲家](https://s0getcomposer0org.icopy.site/) ) | `composer.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | +| Python( [setuptools](https://setuptools.readthedocs.io/en/latest/) , [pip](https://pip.pypa.io/en/stable/) , [Pipenv](https://pipenv.pypa.io/en/latest/) ) | `setup.py`, `requirements.txt`, `requirements.pip`, `requires.txt`, `Pipfile` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | +| 红宝石( [Bundler](https://bundler.io/) ) | `Gemfile.lock`, `gems.locked` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium), [bundler-audit](https://github.com/rubysec/bundler-audit) | +| Scala( [sbt](https://www.scala-sbt.org/) ) | `build.sbt` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | + +正在制定支持以下语言,依赖性管理器和依赖性文件的计划. 有关详细信息,请参见每个的问题链接. + +| 语言(程序包管理器) | 支援的档案 | 扫描工具 | Issue | +| --- | --- | --- | --- | +| Python( [诗歌](https://python-poetry.org/) ) | `poetry.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#7006](https://gitlab.com/gitlab-org/gitlab/-/issues/7006) | +| Python( [Pipenv](https://pipenv.pypa.io/en/latest/) ) | `Pipfile.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#11756](https://gitlab.com/gitlab-org/gitlab/-/issues/11756) | + +## Contribute your scanner[](#contribute-your-scanner "Permalink") + +[安全扫描程序集成](../../../development/integrations/secure.html)文档说明了如何将其他安全扫描[程序集成](../../../development/integrations/secure.html)到 GitLab 中. + +## Configuration[](#configuration "Permalink") + +To enable Dependency Scanning for GitLab 11.9 and later, you must [include](../../../ci/yaml/README.html#includetemplate) the [`Dependency-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml) that’s provided as a part of your GitLab installation. For GitLab versions earlier than 11.9, you can copy and use the job as defined that template. + +将以下内容添加到您的`.gitlab-ci.yml`文件中: + +``` +include: + - template: Dependency-Scanning.gitlab-ci.yml +``` + +随附的模板将在 CI / CD 管道中创建"依赖关系扫描"作业,并扫描项目的源代码以查找可能的漏洞. 结果将保存为" [依赖关系扫描"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsdependency_scanning-ultimate) ,您以后可以下载和分析该[工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsdependency_scanning-ultimate) . 由于实施限制,我们始终采用最新的"依赖关系扫描"工件. + +### Customizing the Dependency Scanning settings[](#customizing-the-dependency-scanning-settings "Permalink") + +可以使用`.gitlab-ci.yml`的[`variables`](../../../ci/yaml/README.html#variables)参数通过[环境变量](#available-variables)来更改"依赖项扫描"设置. 例如: + +``` +include: + - template: Dependency-Scanning.gitlab-ci.yml + +variables: + DS_PYTHON_VERSION: 2 +``` + +因为模板是[在](../../../ci/yaml/README.html#include)管道配置[之前评估](../../../ci/yaml/README.html#include)的,所以最后提到的变量将具有优先权. + +### Overriding Dependency Scanning jobs[](#overriding-dependency-scanning-jobs "Permalink") + +**弃用:**从 GitLab 13.0 开始,不再支持[`only`和`except`](../../../ci/yaml/README.html#onlyexcept-basic)的使用. 覆盖模板时,必须使用[`rules`](../../../ci/yaml/README.html#rules) . + +要覆盖作业定义(例如,更改诸如`variables`或`dependencies`类的属性),请声明一个与要覆盖的作业同名的新作业. 将此新作业放置在包含模板之后,并在其下指定其他任何键. 例如,这将禁用`DS_REMEDIATE`为`gemnasium`分析器: + +``` +include: + - template: Dependency-Scanning.gitlab-ci.yml + +gemnasium-dependency_scanning: + variables: + DS_REMEDIATE: "false" +``` + +### Available variables[](#available-variables "Permalink") + +可以使用环境变量[配置](#customizing-the-dependency-scanning-settings)依赖性扫描. + +#### Configuring Dependency Scanning[](#configuring-dependency-scanning "Permalink") + +以下变量允许配置全局依赖项扫描设置. + +| 环境变量 | Description | +| --- | --- | +| `SECURE_ANALYZERS_PREFIX` | 覆盖提供正式默认映像(代理)的 Docker 注册表名称. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `DS_DEFAULT_ANALYZERS` | 覆盖正式默认图像的名称. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `DS_DISABLE_DIND` | 禁用 Docker-in-Docker 并[单独](#enabling-docker-in-docker)运行分析器. 默认情况下,此变量为`true` . | +| `ADDITIONAL_CA_CERT_BUNDLE` | 捆绑的 CA 证书可信任. | +| `DS_EXCLUDED_PATHS` | 根据路径从输出中排除漏洞. 以逗号分隔的模式列表. 模式可以是全局变量,也可以是文件或文件夹路径(例如`doc,spec` ). 父目录也匹配模式. 默认值: `"spec, test, tests, tmp"` | +| `SECURE_LOG_LEVEL` | 默认日志级别为`info` ,您可以将其设置为以下任意字符串: `fatal` , `error` , `warn` , `info` , `debug` . | + +#### Configuring Docker-in-Docker orchestrator[](#configuring-docker-in-docker-orchestrator "Permalink") + +以下变量配置 Docker-in-Docker 协调器,因此仅在[启用](#enabling-docker-in-docker) Docker-in-Docker 模式时才使用. + +| 环境变量 | Default | Description | +| --- | --- | --- | +| `DS_ANALYZER_IMAGES` |   | 以逗号分隔的自定义图像列表. 官方默认图像仍处于启用状态. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `DS_ANALYZER_IMAGE_TAG` |   | 覆盖官方默认映像的 Docker 标签. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `DS_PULL_ANALYZER_IMAGES` |   | 从 Docker 注册表中提取映像(设置为`0`以禁用). | +| `DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT` | 2m | Docker 客户端协商的时间限制. 使用 Go 的[`ParseDuration`](https://s0golang0org.icopy.site/pkg/time/)解析超时. 有效时间单位为`ns` , `us` (或`µs` ), `ms` , `s` , `m`或`h` . 例如`300ms` , `1.5h`或`2h45m` . | +| `DS_PULL_ANALYZER_IMAGE_TIMEOUT` | 5m | 拉取分析仪图像的时间限制. 使用 Go 的[`ParseDuration`](https://s0golang0org.icopy.site/pkg/time/)解析超时. 有效时间单位为`ns` , `us` (或`µs` ), `ms` , `s` , `m`或`h` . 例如`300ms` , `1.5h`或`2h45m` . | +| `DS_RUN_ANALYZER_TIMEOUT` | 20m | 运行分析仪的时间限制. 使用 Go 的[`ParseDuration`](https://s0golang0org.icopy.site/pkg/time/)解析超时. 有效时间单位为`ns` , `us` (或`µs` ), `ms` , `s` , `m`或`h` . 例如`300ms` , `1.5h`或`2h45m` . | + +#### Configuring specific analyzers used by Dependency Scanning[](#configuring-specific-analyzers-used-by-dependency-scanning "Permalink") + +以下变量用于配置特定的分析器(用于特定的语言/框架). + +| Environment variable | Analyzer | Default | Description | +| --- | --- | --- | --- | +| `GEMNASIUM_DB_LOCAL_PATH` | `gemnasium` | `/gemnasium-db` | 本地 Gemnasium 数据库的路径. | +| `GEMNASIUM_DB_REMOTE_URL` | `gemnasium` | `https://gitlab.com/gitlab-org/security-products/gemnasium-db.git` | 用于获取 Gemnasium 数据库的存储库 URL. | +| `GEMNASIUM_DB_REF_NAME` | `gemnasium` | `master` | 远程存储库数据库的分支名称. 需要`GEMNASIUM_DB_REMOTE_URL` . | +| `DS_REMEDIATE` | `gemnasium` | `"true"` | 启用对弱势依赖项的自动修复. | +| `PIP_INDEX_URL` | `gemnasium-python` | `https://pypi.org/simple` | Python 软件包索引的基本 URL. | +| `PIP_EXTRA_INDEX_URL` | `gemnasium-python` |   | 除`PIP_INDEX_URL`之外, `PIP_INDEX_URL`使用包索引的其他[URL](https://pip.pypa.io/en/stable/reference/pip_install/#cmdoption-extra-index-url)数组. 以逗号分隔. | +| `PIP_REQUIREMENTS_FILE` | `gemnasium-python` |   | 要扫描的点子要求文件. | +| `DS_PIP_VERSION` | `gemnasium-python` |   | 强制安装特定的 pip 版本(例如: `"19.3"` ),否则将使用 Docker 映像中安装的 pip. (在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12811) ) | +| `DS_PIP_DEPENDENCY_PATH` | `gemnasium-python` |   | 从中加载 Python pip 依赖项的路径. (在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12412) ) | +| `DS_PYTHON_VERSION` | `retire.js` |   | Python 版本. 如果设置为 2,则将使用 Python 2.7 而非 Python 3.6 安装依赖项. (在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12296) ) | +| `DS_JAVA_VERSION` | `gemnasium-maven` | `11` | Java 版本. 可用版本: `8` , `11` , `13` , `14` . Maven 和 Gradle 将使用此值指定的 Java 版本. | +| `MAVEN_CLI_OPTS` | `gemnasium-maven` | `"-DskipTests --batch-mode"` | 分析器将传递给`maven`的命令行参数列表. 请参阅[使用私有存储库](../index.html#using-private-maven-repos)的示例. | +| `GRADLE_CLI_OPTS` | `gemnasium-maven` |   | 分析器将传递给`gradle`的命令行参数列表. | +| `SBT_CLI_OPTS` | `gemnasium-maven` |   | 分析器将传递给`sbt`的命令行参数列表. | +| `BUNDLER_AUDIT_UPDATE_DISABLED` | `bundler-audit` | `"false"` | 禁用`bundler-audit`分析器的自动更新. 如果您在脱机的空白环境中运行"依赖性扫描",则很有用. | +| `BUNDLER_AUDIT_ADVISORY_DB_URL` | `bundler-audit` | `https://github.com/rubysec/ruby-advisory-db` | bundler-audit 使用的咨询数据库的 URL. | +| `BUNDLER_AUDIT_ADVISORY_DB_REF_NAME` | `bundler-audit` | `master` | `BUNDLER_AUDIT_ADVISORY_DB_URL`指定的咨询数据库的 Git ref. | +| `RETIREJS_JS_ADVISORY_DB` | `retire.js` | `https://raw.githubusercontent.com/RetireJS/retire.js/master/repository/jsrepository.json` | `retire.js` JS 漏洞数据文件的路径或 URL. 请注意,如果托管数据文件的 URL 使用自定义 SSL 证书(例如在脱机安装中),则可以在`ADDITIONAL_CA_CERT_BUNDLE`环境变量中传递证书. | +| `RETIREJS_NODE_ADVISORY_DB` | `retire.js` | `https://raw.githubusercontent.com/RetireJS/retire.js/master/repository/npmrepository.json` | `retire.js`节点漏洞数据文件的路径或 URL. 请注意,如果托管数据文件的 URL 使用自定义 SSL 证书(例如在脱机安装中),则可以在`ADDITIONAL_CA_CERT_BUNDLE`环境变量中传递证书. | +| `RETIREJS_ADVISORY_DB_INSECURE` | `retire.js` | `false` | 启用使用不安全或自签名 SSL(TLS)证书从主机获取远程 JS 和 Node 漏洞数据文件(由`RETIREJS_JS_ADVISORY_DB`和`RETIREJS_NODE_ADVISORY_DB`变量定义)的功能. | + +### Using private Maven repos[](#using-private-maven-repos "Permalink") + +如果您的私有 Maven 存储库需要登录凭据,则可以使用`MAVEN_CLI_OPTS`环境变量. + +阅读有关[如何使用私有 Maven 存储库的](../index.html#using-private-maven-repos)更多[信息](../index.html#using-private-maven-repos) . + +### Enabling Docker-in-Docker[](#enabling-docker-in-docker "Permalink") + +在 GitLab Ultimate 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12487) . + +如果需要,可以启用 Docker-in-Docker 来还原 GitLab 13.0 之前存在的 Dependency Scanning 行为. 请按照以下步骤操作: + +1. 在[特权模式下](https://docs.gitlab.com/runner/executors/docker.html)使用 Docker-in-Docker 配置 GitLab Runner. +2. Set the `DS_DISABLE_DIND` variable to `false`: + + ``` + include: + - template: Dependency-Scanning.gitlab-ci.yml + + variables: + DS_DISABLE_DIND: "false" + ``` + +这将在您的 CI / CD 管道中创建一个`dependency_scanning`作业,而不是多个`-dependency_scanning`作业. + +## Interacting with the vulnerabilities[](#interacting-with-the-vulnerabilities "Permalink") + +一旦发现漏洞,便可以与其进行交互. 阅读有关如何[与漏洞](../index.html#interacting-with-the-vulnerabilities)进行[交互的](../index.html#interacting-with-the-vulnerabilities)更多信息. + +## Solutions for vulnerabilities (auto-remediation)[](#solutions-for-vulnerabilities-auto-remediation "Permalink") + +可以通过应用 GitLab 自动生成的解决方案来修复某些漏洞. 阅读有关[漏洞解决方案的](../index.html#solutions-for-vulnerabilities-auto-remediation)更多信息. + +## Security Dashboard[](#security-dashboard "Permalink") + +在"安全仪表板"中,您可以概览您的组,项目和管道中的所有安全漏洞. 阅读有关[安全仪表板的](../security_dashboard/index.html)更多[信息](../security_dashboard/index.html) . + +## Vulnerabilities database update[](#vulnerabilities-database-update "Permalink") + +有关漏洞数据库更新的更多信息,请查看[维护表](../index.html#maintenance-and-update-of-the-vulnerabilities-database) . + +## Dependency List[](#dependency-list "Permalink") + +依赖项扫描的另一个好处是能够查看项目的依赖项及其已知漏洞. 阅读有关[依赖列表的](../dependency_list/index.html)更多信息. + +## Reports JSON format[](#reports-json-format "Permalink") + +依赖关系扫描工具将发出 JSON 报告文件. 有关更多信息,请参见此[报告](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/dependency-scanning-report-format.json)的[架构](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/dependency-scanning-report-format.json) . + +这是一个示例依赖性扫描报告: + +``` +{ "version": "2.0", "vulnerabilities": [ { "id": "51e83874-0ff6-4677-a4c5-249060554eae", "category": "dependency_scanning", "name": "Regular Expression Denial of Service", "message": "Regular Expression Denial of Service in debug", "description": "The debug module is vulnerable to regular expression denial of service when untrusted user input is passed into the `o` formatter. It takes around 50k characters to block for 2 seconds making this a low severity issue.", "severity": "Unknown", "solution": "Upgrade to latest versions.", "scanner": { "id": "gemnasium", "name": "Gemnasium" }, "location": { "file": "yarn.lock", "dependency": { "package": { "name": "debug" }, "version": "1.0.5" } }, "identifiers": [ { "type": "gemnasium", "name": "Gemnasium-37283ed4-0380-40d7-ada7-2d994afcc62a", "value": "37283ed4-0380-40d7-ada7-2d994afcc62a", "url": "https://deps.sec.gitlab.com/packages/npm/debug/versions/1.0.5/advisories" } ], "links": [ { "url": "https://nodesecurity.io/advisories/534" }, { "url": "https://github.com/visionmedia/debug/issues/501" }, { "url": "https://github.com/visionmedia/debug/pull/504" } ] }, { "id": "5d681b13-e8fa-4668-957e-8d88f932ddc7", "category": "dependency_scanning", "name": "Authentication bypass via incorrect DOM traversal and canonicalization", "message": "Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js", "description": "Some XML DOM traversal and canonicalization APIs may be inconsistent in handling of comments within XML nodes. Incorrect use of these APIs by some SAML libraries results in incorrect parsing of the inner text of XML nodes such that any inner text after the comment is lost prior to cryptographically signing the SAML message. Text after the comment therefore has no impact on the signature on the SAML message.\r\n\r\nA remote attacker can modify SAML content for a SAML service provider without invalidating the cryptographic signature, which may allow attackers to bypass primary authentication for the affected SAML service provider.", "severity": "Unknown", "solution": "Upgrade to fixed version.\r\n", "scanner": { "id": "gemnasium", "name": "Gemnasium" }, "location": { "file": "yarn.lock", "dependency": { "package": { "name": "saml2-js" }, "version": "1.5.0" } }, "identifiers": [ { "type": "gemnasium", "name": "Gemnasium-9952e574-7b5b-46fa-a270-aeb694198a98", "value": "9952e574-7b5b-46fa-a270-aeb694198a98", "url": "https://deps.sec.gitlab.com/packages/npm/saml2-js/versions/1.5.0/advisories" }, { "type": "cve", "name": "CVE-2017-11429", "value": "CVE-2017-11429", "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429" } ], "links": [ { "url": "https://github.com/Clever/saml2/commit/3546cb61fd541f219abda364c5b919633609ef3d#diff-af730f9f738de1c9ad87596df3f6de84R279" }, { "url": "https://github.com/Clever/saml2/issues/127" }, { "url": "https://www.kb.cert.org/vuls/id/475445" } ] } ], "remediations": [ { "fixes": [ { "id": "5d681b13-e8fa-4668-957e-8d88f932ddc7", } ], "summary": "Upgrade saml2-js", "diff": "ZGlmZiAtLWdpdCBhL...OR0d1ZUc2THh3UT09Cg==" // some content is omitted for brevity } ] } +``` + +## Versioning and release process[](#versioning-and-release-process "Permalink") + +请检查[发布过程文档](https://gitlab.com/gitlab-org/security-products/release/blob/master/docs/release_process.md) . + +## Contributing to the vulnerability database[](#contributing-to-the-vulnerability-database "Permalink") + +您可以搜索[gemnasium-db](https://gitlab.com/gitlab-org/security-products/gemnasium-db)项目,以在 Gemnasium 数据库中找到漏洞. 您还可以[提交新漏洞](https://gitlab.com/gitlab-org/security-products/gemnasium-db/blob/master/CONTRIBUTING.md) . + +## Running Dependency Scanning in an offline environment[](#running-dependency-scanning-in-an-offline-environment "Permalink") + +对于在通过 Internet 限制,限制或间歇性访问外部资源的环境中进行自我管理的 GitLab 实例,需要进行一些调整才能使"依赖关系扫描"作业成功运行. 有关更多信息,请参阅[脱机环境](../offline_deployments/index.html) . + +### Requirements for offline Dependency Scanning[](#requirements-for-offline-dependency-scanning "Permalink") + +以下是在脱机环境中使用依赖关系扫描的要求: + +* Keep Docker-In-Docker disabled (default). +* GitLab 亚军与[`docker`或`kubernetes`执行](#requirements) . +* Docker 容器注册表以及 Dependency Scanning [分析器](https://gitlab.com/gitlab-org/security-products/analyzers)映像的本地可用副本. +* 托管[gemnasium-db 咨询数据库](https://gitlab.com/gitlab-org/security-products/gemnasium-db/)的脱机 Git 副本 +* *仅在扫描 Ruby 项目时* :托管[咨询数据库](https://github.com/rubysec/ruby-advisory-db)的脱机 Git 副本. +* *仅在扫描 npm / yarn 项目时* :托管[retire.js](https://github.com/RetireJS/retire.js/) [节点](https://github.com/RetireJS/retire.js/blob/master/repository/npmrepository.json)和[js](https://github.com/RetireJS/retire.js/blob/master/repository/jsrepository.json)咨询数据库的脱机副本. + +**注意:** GitLab Runner 的[默认`pull policy`为`always`](https://docs.gitlab.com/runner/executors/docker.html) ,这意味着即使本地副本可用,Runner 也会尝试从 GitLab 容器注册表中拉取 Docker 映像. 如果您只喜欢使用本地可用的 Docker 映像,则可以在离线环境[`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html) GitLab Runner 的[`pull_policy`设置为`if-not-present`](https://docs.gitlab.com/runner/executors/docker.html) . 但是,如果不在离线环境中,我们建议将拉取策略设置保持为`always` ,因为这样可以在 CI / CD 管道中使用更新的扫描仪. + +### Make GitLab Dependency Scanning analyzer images available inside your Docker registry[](#make-gitlab-dependency-scanning-analyzer-images-available-inside-your-docker-registry "Permalink") + +对于具有所有[受支持的语言和框架的](#supported-languages-and-package-managers)依赖关系扫描,请将以下默认的依赖关系扫描分析器映像从`registry.gitlab.com`导入[本地 Docker 容器注册表](../../packages/container_registry/index.html) : + +``` +registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/retire.js:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/bundler-audit:2 +``` + +将 Docker 映像导入本地脱机 Docker 注册表的过程取决于**您的网络安全策略** . 请咨询您的 IT 员工,以找到可以导入或临时访问外部资源的已接受和批准的流程. 请注意,这些扫描程序会[定期](../index.html#maintenance-and-update-of-the-vulnerabilities-database)使用新定义进行[更新](../index.html#maintenance-and-update-of-the-vulnerabilities-database) ,因此请考虑是否可以自己进行定期更新. + +有关将 Docker 映像保存和传输为文件的详细信息,请参阅 Docker 有关[`docker save`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/save/) , [`docker load`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/load/) , [`docker export`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/export/)和[`docker import`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/import/)的文档. + +### Set Dependency Scanning CI job variables to use local Dependency Scanning analyzers[](#set-dependency-scanning-ci-job-variables-to-use-local-dependency-scanning-analyzers "Permalink") + +将以下配置添加到您的`.gitlab-ci.yml`文件. 您必须替换`SECURE_ANALYZERS_PREFIX`才能引用本地 Docker 容器注册表: + +``` +include: + - template: Dependency-Scanning.gitlab-ci.yml + +variables: + SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers" + GEMNASIUM_DB_REMOTE_URL: "gitlab.example.com/gemnasium-db.git" + GIT_SSL_NO_VERIFY: "true" +``` + +请参阅[配置部分中](#configuration)以上变量的说明. + +### Specific settings for languages and package managers[](#specific-settings-for-languages-and-package-managers "Permalink") + +请参阅以下各节,以配置特定的语言和程序包管理器. + +#### JavaScript (npm and yarn) projects[](#javascript-npm-and-yarn-projects "Permalink") + +将以下内容添加到`.gitlab-ci.yml`的变量部分: + +``` +RETIREJS_JS_ADVISORY_DB: "example.com/jsrepository.json" +RETIREJS_NODE_ADVISORY_DB: "example.com/npmrepository.json" +``` + +#### Ruby (gem) projects[](#ruby-gem-projects "Permalink") + +将以下内容添加到`.gitlab-ci.yml`的变量部分: + +``` +BUNDLER_AUDIT_ADVISORY_DB_REF_NAME: "master" +BUNDLER_AUDIT_ADVISORY_DB_URL: "gitlab.example.com/ruby-advisory-db.git" +``` + +#### Python (setuptools)[](#python-setuptools "Permalink") + +当为私有 PyPi 存储库使用自签名证书时,不需要额外的作业配置(除了上面的模板`.gitlab-ci.yml` ). 但是,您必须更新`setup.py`以确保它可以到达您的私有存储库. 这是一个示例配置: + +1. 更新`setup.py` ,以为`install_requires`列表中的每个依赖项创建一个指向您的私有存储库的`dependency_links`属性: + + ``` + install_requires=['pyparsing>=2.0.3'], + dependency_links=['https://pypi.example.com/simple/pyparsing'], + ``` + +2. 从存储库 URL 中获取证书并将其添加到项目中: + + ``` + echo -n | openssl s_client -connect pypi.example.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > internal.crt + ``` + +3. 将`setup.py`指向新下载的证书: + + ``` + import setuptools.ssl_support + setuptools.ssl_support.cert_paths = ['internal.crt'] + ``` + +## Limitations[](#limitations "Permalink") + +### Referencing local dependencies using a path in JavaScript projects[](#referencing-local-dependencies-using-a-path-in-javascript-projects "Permalink") + +[Retire.js](https://gitlab.com/gitlab-org/security-products/analyzers/retire.js)分析器不支持使用 JavaScript 项目的`package.json`的[本地路径](https://s0docs0npmjs0com.icopy.site/files/package.json)进行的依赖项引用. 依赖项扫描针对此类引用输出以下错误: + +``` +ERROR: Could not find dependencies: . You may need to run npm install +``` + +解决方法是,从[DS_DEFAULT_ANALYZERS](#configuring-dependency-scanning)删除[`retire.js`](analyzers.html#selecting-specific-analyzers)分析器. + +## Troubleshooting[](#troubleshooting "Permalink") + +### `Error response from daemon: error processing tar file: docker-tar: relocation error`[](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error "Permalink") + +当运行 Dependency Scanning 作业的 Docker 版本为`19.03.00`时,会发生此错误. 考虑更新到 Docker `19.03.1`或更高版本. 旧版本不受影响. 阅读[本期的](https://gitlab.com/gitlab-org/gitlab/-/issues/13830#note_211354992 "当前的 SAST 容器失败")更多内容. \ No newline at end of file diff --git a/docs/053.md b/docs/053.md new file mode 100644 index 0000000000000000000000000000000000000000..fc4e34c7e2fc3426ca8445f8fe42444707e02d2a --- /dev/null +++ b/docs/053.md @@ -0,0 +1,49 @@ +# Dependency List + +> 原文:[https://docs.gitlab.com/ee/user/application_security/dependency_list/](https://docs.gitlab.com/ee/user/application_security/dependency_list/) + +* [Requirements](#requirements) +* [Viewing dependencies](#viewing-dependencies) + * [Vulnerabilities](#vulnerabilities) +* [Licenses](#licenses) +* [Downloading the Dependency List](#downloading-the-dependency-list) + +# Dependency List[](#dependency-list-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10075) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. + +"依赖关系"列表使您可以查看项目的依赖关系以及有关它们的关键详细信息,包括已知漏洞. 要查看它,请导航至项目侧栏中的" **安全性和合规性">"依赖项列表"** . 该信息有时被称为软件物料清单或 SBoM / BOM. + +## Requirements[](#requirements "Permalink") + +1. 必须为您的项目配置" [依赖项扫描](../dependency_scanning/index.html) CI"作业. +2. 您的项目至少使用 Gemnasium 支持的一种[语言和包管理器](../dependency_scanning/index.html#supported-languages-and-package-managers) . + +## Viewing dependencies[](#viewing-dependencies "Permalink") + +[![Dependency List](img/e4fa52f4d522392d049bf73b1bb065a5.png)](img/dependency_list_v12_10.png) + +依存关系显示以下信息: + +| Field | Description | +| --- | --- | +| Component | 依赖项的名称和版本 | +| Packager | 打包程序用于安装依赖项 | +| Location | 指向项目中特定于包装程序的锁定文件的链接,该文件声明了依赖性 | +| License | 链接到依赖项的软件许可证 | + +最初显示的依赖项是按其已知漏洞的严重性(如果有)进行排序的. 也可以按名称或安装它们的打包程序对它们进行排序. + +### Vulnerabilities[](#vulnerabilities "Permalink") + +如果依赖项具有已知漏洞,则可以通过单击依赖项名称旁边的箭头或指示存在多少已知漏洞的标志来查看它们. 对于每个漏洞,其严重性和描述将显示在其下方. + +## Licenses[](#licenses "Permalink") + +在 GitLab Ultimate 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/10536) . + +如果配置了" [许可证合规性](../../compliance/license_compliance/index.html) CI"作业,则[发现的许可证](../../compliance/license_compliance/index.html#supported-languages-and-package-managers)将显示在此页面上. + +## Downloading the Dependency List[](#downloading-the-dependency-list "Permalink") + +您可以通过单击下载按钮以`JSON`格式下载项目的依赖关系及其详细信息的完整列表. \ No newline at end of file diff --git a/docs/054.md b/docs/054.md new file mode 100644 index 0000000000000000000000000000000000000000..8c1123b479f7b99a402ff21fcfa7fccaa2dd5b68 --- /dev/null +++ b/docs/054.md @@ -0,0 +1,437 @@ +# Static Application Security Testing (SAST) + +> 原文:[https://docs.gitlab.com/ee/user/application_security/sast/](https://docs.gitlab.com/ee/user/application_security/sast/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Requirements](#requirements) +* [Supported languages and frameworks](#supported-languages-and-frameworks) + * [Making SAST analyzers available to all GitLab tiers](#making-sast-analyzers-available-to-all-gitlab-tiers) + * [Summary of features per tier](#summary-of-features-per-tier) +* [Contribute your scanner](#contribute-your-scanner) +* [Configuration](#configuration) + * [Customizing the SAST settings](#customizing-the-sast-settings) + * [Overriding SAST jobs](#overriding-sast-jobs) + * [Using environment variables to pass credentials for private repositories](#using-environment-variables-to-pass-credentials-for-private-repositories) + * [Using a variable to pass username and password to a private Maven repository](#using-a-variable-to-pass-username-and-password-to-a-private-maven-repository) + * [Enabling Docker-in-Docker](#enabling-docker-in-docker) + * [Enabling Kubesec analyzer](#enabling-kubesec-analyzer) + * [Pre-compilation](#pre-compilation) + * [Available variables](#available-variables) + * [Logging Level](#logging-level) + * [Custom Certificate Authority](#custom-certificate-authority) + * [Docker images](#docker-images) + * [Vulnerability filters](#vulnerability-filters) + * [Docker-in-Docker orchestrator](#docker-in-docker-orchestrator) + * [Analyzer settings](#analyzer-settings) + * [Custom environment variables](#custom-environment-variables) +* [Reports JSON format](#reports-json-format) +* [Secret detection](#secret-detection) +* [Security Dashboard](#security-dashboard) +* [Interacting with the vulnerabilities](#interacting-with-the-vulnerabilities) +* [Vulnerabilities database](#vulnerabilities-database) + * [Vulnerabilities database update](#vulnerabilities-database-update) +* [Running SAST in an offline environment](#running-sast-in-an-offline-environment) + * [Requirements for offline SAST](#requirements-for-offline-sast) + * [Make GitLab SAST analyzer images available inside your Docker registry](#make-gitlab-sast-analyzer-images-available-inside-your-docker-registry) + * [Set SAST CI job variables to use local SAST analyzers](#set-sast-ci-job-variables-to-use-local-sast-analyzers) +* [Troubleshooting](#troubleshooting) + * [`Error response from daemon: error processing tar file: docker-tar: relocation error`](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) + +# Static Application Security Testing (SAST)[](#static-application-security-testing-sast-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3775) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.3. + +**注意:**白皮书["应用程序安全性发生](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)了[地震变化"](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)说明**了前 6 种攻击中有 4 种是基于应用程序的** . 下载它以了解如何保护您的组织. + +## Overview[](#overview "Permalink") + +如果您使用的是[GitLab CI / CD](../../../ci/README.html) ,则可以使用静态应用程序安全性测试(SAST)分析源代码中的已知漏洞. + +您可以通过执行以下任一操作来利用 SAST: + +* 在现有的`.gitlab-ci.yml`文件中[包括 SAST 模板](#configuration) . +* 隐式使用[Auto DevOps](../../../topics/autodevops/stages.html#auto-sast-ultimate)提供的[Auto](../../../topics/autodevops/index.html) [SAST](../../../topics/autodevops/stages.html#auto-sast-ultimate) . + +GitLab 检查 SAST 报告,比较发现的源分支和目标分支之间的漏洞,并在合并请求中显示信息. + +[![SAST Widget](img/5e9b34b344fc5f08d74d5156c419f471.png)](img/sast_v13_2.png) + +结果按漏洞的优先级排序: + +1. Critical +2. High +3. Medium +4. Low +5. Unknown +6. 其他一切 + +**注意:**管道包含多个作业,包括 SAST 和 DAST 扫描. 如果任何作业由于任何原因未能完成,则安全信息中心将不会显示 SAST 扫描仪输出. 例如,如果 SAST 作业完成但 DAST 作业失败,则安全性仪表板将不会显示 SAST 结果. 分析器将在失败时输出[退出代码](../../../development/integrations/secure.html#exit-code) . + +## Use cases[](#use-cases "Permalink") + +* 您的代码在类中具有潜在的危险属性,或者不安全的代码可能导致意外的代码执行. +* 您的应用程序容易受到跨站点脚本(XSS)攻击的攻击,这些攻击可用于未经授权访问会话数据. + +## Requirements[](#requirements "Permalink") + +要运行 SAST 工作,默认情况下,你需要 GitLab 亚军与[`docker`](https://docs.gitlab.com/runner/executors/docker.html)或[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html)执行. 如果您在 GitLab.com 上使用共享的 Runners,则默认启用该功能. + +从 GitLab 13.0 开始,仅当您已[为 SAST 启用 Docker-in-Docker 时,才](#enabling-docker-in-docker)需要 Docker 特权模式. + +**警告:**目前,我们的 SAST 作业需要 Linux 容器类型. Windows 容器尚不支持.**注意:**如果使用自己的 Runners,请确保安装的 Docker 版本**不是** `19.03.0` . 有关详细[信息](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) ,请参见[故障排除信息](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) . + +## Supported languages and frameworks[](#supported-languages-and-frameworks "Permalink") + +下表显示了支持的语言,程序包管理器和框架以及使用了哪些工具. + +| 语言(包管理器)/框架 | 扫描工具 | 在 GitLab 版本中引入 | +| --- | --- | --- | +| .NET Core | [Security Code Scan](https://security-code-scan.github.io) | 11.0 | +| .NET Framework | [Security Code Scan](https://security-code-scan.github.io) | 13.0 | +| Any | [Gitleaks](https://github.com/zricethezav/gitleaks) and [TruffleHog](https://github.com/dxa4481/truffleHog) | 11.9 | +| Apex(Salesforce) | [PMD](https://pmd.github.io/pmd/index.html) | 12.1 | +| C/C++ | [Flawfinder](https://github.com/david-a-wheeler/flawfinder) | 10.7 | +| 长生不老药(凤凰城) | [Sobelow](https://github.com/nccgroup/sobelow) | 11.10 | +| Go | [Gosec](https://github.com/securego/gosec) | 10.7 | +| Groovy( [Ant](https://ant.apache.org/) , [Gradle](https://s0gradle0org.icopy.site/) , [Maven](https://maven.apache.org/)和[SBT](https://www.scala-sbt.org/) ) | 带有[find-sec-bugs](https://find-sec-bugs.github.io/)插件的[SpotBugs](https://spotbugs.github.io/) | 11.3(Gradle)和 11.9(Ant,Maven,SBT) | +| 头盔图 | [Kubesec](https://github.com/controlplaneio/kubesec) | 13.1 | +| Java( [Ant](https://ant.apache.org/) , [Gradle](https://s0gradle0org.icopy.site/) , [Maven](https://maven.apache.org/)和[SBT](https://www.scala-sbt.org/) ) | 带有[find-sec-bugs](https://find-sec-bugs.github.io/)插件的[SpotBugs](https://spotbugs.github.io/) | 10.6(Maven),10.8(Grade)和 11.9(Ant,SBT) | +| JavaScript | [ESLint security plugin](https://github.com/nodesecurity/eslint-plugin-security) | 11.8,在 13.2 中移至[GitLab Core](https://about.gitlab.com/pricing/) | +| 州长宣言 | [Kubesec](https://github.com/controlplaneio/kubesec) | 12.6 | +| Node.js | [NodeJsScan](https://github.com/ajinabraham/NodeJsScan) | 11.1 | +| PHP | [phpcs-security-audit](https://github.com/FloeDesignTechnologies/phpcs-security-audit) | 10.8 | +| Python( [点子](https://pip.pypa.io/en/stable/) ) | [bandit](https://github.com/PyCQA/bandit) | 10.3 | +| React | [ESLint react plugin](https://github.com/yannickcr/eslint-plugin-react) | 12.5 | +| Ruby on Rails | [brakeman](https://brakemanscanner.org) | 10.3,于 13.1 中移至[GitLab Core](https://about.gitlab.com/pricing/) | +| Scala( [Ant](https://ant.apache.org/) , [Gradle](https://s0gradle0org.icopy.site/) , [Maven](https://maven.apache.org/)和[SBT](https://www.scala-sbt.org/) ) | 带有[find-sec-bugs](https://find-sec-bugs.github.io/)插件的[SpotBugs](https://spotbugs.github.io/) | 11.0(SBT)和 11.9(Ant,Gradle,Maven) | +| TypeScript | [ESLint security plugin](https://github.com/nodesecurity/eslint-plugin-security) | 11.9,在 13.2 中与 ESLint 合并 | + +**注意:** Java 分析器还可以用于[Gradle 包装器](https://s0docs0gradle0org.icopy.site/current/userguide/gradle_wrapper.html) , [Grails](https://grails.org/)和[Maven 包装器](https://github.com/takari/maven-wrapper)等变体. + +### Making SAST analyzers available to all GitLab tiers[](#making-sast-analyzers-available-to-all-gitlab-tiers "Permalink") + +所有开放源代码(OSS)分析器都正在接受审核,并有可能移至 GitLab 核心层. 可以在相应的[史诗中](https://gitlab.com/groups/gitlab-org/-/epics/2098)跟踪进度. + +请注意,对[Docker-in-Docker 的](#enabling-docker-in-docker)支持不会扩展到 GitLab 核心层. + +#### Summary of features per tier[](#summary-of-features-per-tier "Permalink") + +下表列出了在不同的[GitLab 层](https://about.gitlab.com/pricing/)中可用的不同功能: + +| Capability | 在核心 | 终极 | +| --- | --- | --- | +| [Configure SAST Scanners](#configuration) | | | +| [Customize SAST Settings](#customizing-the-sast-settings) | | | +| View [JSON Report](#reports-json-format) | | | +| [Presentation of JSON Report in Merge Request](#overview) | | | +| [Interaction with Vulnerabilities](#interacting-with-the-vulnerabilities) | | | +| [Access to Security Dashboard](#security-dashboard) | | | + +## Contribute your scanner[](#contribute-your-scanner "Permalink") + +[安全扫描程序集成](../../../development/integrations/secure.html)文档说明了如何将其他安全扫描[程序集成](../../../development/integrations/secure.html)到 GitLab 中. + +## Configuration[](#configuration "Permalink") + +**注意:**如果您使用的是[Auto DevOps](../../../topics/autodevops/index.html)提供的[Auto](../../../topics/autodevops/index.html) [SAST,则不必](../../../topics/autodevops/stages.html#auto-sast-ultimate)按照本节中的说明手动配置 SAST. + +对于 GitLab 11.9 和更高版本,要启用 SAST,您必须[包括](../../../ci/yaml/README.html#includetemplate)作为 GitLab 安装的一部分提供的[`SAST.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml) . 对于 11.9 之前的 GitLab 版本,您可以复制和使用该模板中定义的作业. + +将以下内容添加到您的`.gitlab-ci.yml`文件中: + +``` +include: + - template: SAST.gitlab-ci.yml +``` + +随附的模板将在 CI / CD 管道中创建 SAST 作业,并扫描项目的源代码以查找可能的漏洞. + +结果将保存为[SAST 报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportssast-ultimate) ,您可以稍后下载和分析. 由于实施限制,我们始终采用最新的 SAST 工件. + +### Customizing the SAST settings[](#customizing-the-sast-settings "Permalink") + +可以使用`.gitlab-ci.yml`的[`variables`](../../../ci/yaml/README.html#variables)参数通过[环境变量](#available-variables)更改 SAST 设置. 在下面的示例中,我们包括 SAST 模板,同时将`SAST_GOSEC_LEVEL`变量设置为`2` : + +``` +include: + - template: SAST.gitlab-ci.yml + +variables: + SAST_GOSEC_LEVEL: 2 +``` + +因为模板是[在](../../../ci/yaml/README.html#include)管道配置[之前进行评估](../../../ci/yaml/README.html#include)的,所以最后提到的变量优先. + +### Overriding SAST jobs[](#overriding-sast-jobs "Permalink") + +**弃用:**从 GitLab 13.0 开始,不再支持[`only`和`except`](../../../ci/yaml/README.html#onlyexcept-basic)的使用. 覆盖模板时,必须使用[`rules`](../../../ci/yaml/README.html#rules) . + +要覆盖作业定义(例如,更改`variables`或`dependencies`类的属性),请声明与要覆盖的 SAST 作业同名的作业. 将此新作业放置在包含模板之后,并在其下指定其他任何键. 例如,这使得能够`FAIL_NEVER`为`spotbugs`分析器: + +``` +include: + - template: SAST.gitlab-ci.yml + +spotbugs-sast: + variables: + FAIL_NEVER: 1 +``` + +### Using environment variables to pass credentials for private repositories[](#using-environment-variables-to-pass-credentials-for-private-repositories "Permalink") + +一些分析器需要下载项目的依赖项才能执行分析. 反过来,此类依赖项可能存在于私有 Git 存储库中,因此需要诸如用户名和密码之类的凭据才能下载它们. 根据分析器的不同,可以通过[自定义环境变量](#custom-environment-variables)向其提供此类凭据. + +#### Using a variable to pass username and password to a private Maven repository[](#using-a-variable-to-pass-username-and-password-to-a-private-maven-repository "Permalink") + +如果您的私有 Maven 存储库需要登录凭据,则可以使用`MAVEN_CLI_OPTS`环境变量. + +阅读有关[如何使用私有 Maven 存储库的](../index.html#using-private-maven-repos)更多[信息](../index.html#using-private-maven-repos) . + +### Enabling Docker-in-Docker[](#enabling-docker-in-docker "Permalink") + +如果需要,您可以启用 Docker-in-Docker 来还原 GitLab 13.0 之前存在的 SAST 行为. 请按照以下步骤操作: + +1. 在[特权模式下](https://docs.gitlab.com/runner/executors/docker.html)使用 Docker-inDocker 配置 GitLab Runner. +2. 将变量`SAST_DISABLE_DIND`设置为`false` : + + ``` + include: + - template: SAST.gitlab-ci.yml + + variables: + SAST_DISABLE_DIND: "false" + ``` + +这将创建一个单一的`sast`在你的 CI / CD 管道,而不是多个作业`-sast`工作. + +#### Enabling Kubesec analyzer[](#enabling-kubesec-analyzer "Permalink") + +在 GitLab Ultimate 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/12752) . + +您需要将`SCAN_KUBERNETES_MANIFESTS`设置为`"true"`才能启用 Kubesec 分析器. 在`.gitlab-ci.yml` ,定义: + +``` +include: + - template: SAST.gitlab-ci.yml + +variables: + SCAN_KUBERNETES_MANIFESTS: "true" +``` + +#### Pre-compilation[](#pre-compilation "Permalink") + +如果您的项目需要自定义构建配置,则最好避免在 SAST 执行期间进行编译,而应将管道中较早阶段的所有作业工件传递出去. 当需要执行`before_script`来准备扫描作业时,这是当前的策略. + +要将项目的依赖项作为工件传递,这些依赖项必须包含在项目的工作目录中,并使用`artifacts:path`配置进行指定. 如果存在所有依赖项,则可以将`COMPILE=false`变量提供给分析器,并且将跳过编译: + +``` +image: maven:3.6-jdk-8-alpine + +stages: + - build + - test + +include: + - template: SAST.gitlab-ci.yml + +build: + stage: build + script: + - mvn package -Dmaven.repo.local=./.m2/repository + artifacts: + paths: + - .m2/ + - target/ + +spotbugs-sast: + dependencies: + - build + variables: + MAVEN_REPO_PATH: ./.m2/repository + COMPILE: false + artifacts: + reports: + sast: gl-sast-report.json +``` + +**注意:**必须显式指定供应商目录的路径,以允许分析器识别已编译的工件. 每个分析器的配置可能有所不同,但在上述 Java 的情况下,可以使用`MAVEN_REPO_PATH` . 有关可用选项的完整列表,请参见[分析器设置](#analyzer-settings) . + +### Available variables[](#available-variables "Permalink") + +可以使用环境变量[配置](#customizing-the-sast-settings) SAST. + +#### Logging Level[](#logging-level "Permalink") + +您可以通过设置`SECURE_LOG_LEVEL` env var 来控制日志的详细程度. 默认设置为`info` ,您可以将其设置为以下任意级别: + +* `fatal` +* `error` +* `warn` +* `info` +* `debug` + +#### Custom Certificate Authority[](#custom-certificate-authority "Permalink") + +要信任自定义证书颁发机构,请将`ADDITIONAL_CA_CERT_BUNDLE`变量设置为要在 SAST 环境中信任的 CA 证书包. + +#### Docker images[](#docker-images "Permalink") + +以下是与 Docker 映像相关的变量. + +| Environment variable | Description | +| --- | --- | +| `SECURE_ANALYZERS_PREFIX` | 覆盖提供默认映像(代理)的 Docker 注册表名称. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `SAST_ANALYZER_IMAGE_TAG` | **已弃用:**覆盖默认映像的 Docker 标签. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `SAST_DEFAULT_ANALYZERS` | 覆盖默认图像的名称. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `SAST_DISABLE_DIND` | 禁用 Docker-in-Docker 并[单独](#enabling-docker-in-docker)运行分析器. 默认情况下,此变量为`true` . | + +#### Vulnerability filters[](#vulnerability-filters "Permalink") + +一些分析器可以过滤掉给定阈值以下的漏洞. + +| 环境变量 | 默认值 | Description | +| --- | --- | --- | +| `SAST_EXCLUDED_PATHS` | `spec, test, tests, tmp` | 根据路径从输出中排除漏洞. 这是逗号分隔的模式列表. 模式可以是全局变量,也可以是文件或文件夹路径(例如`doc,spec` ). 父目录也将匹配模式. | +| `SAST_BANDIT_EXCLUDED_PATHS` |   | 逗号分隔的路径列表,可从扫描中排除. 使用 Python 的[`fnmatch`语法](https://s0docs0python0org.icopy.site/2/library/fnmatch.html) ; 例如: `'*/tests/*, */venv/*'` | +| `SAST_BRAKEMAN_LEVEL` | 1 | 在给定的置信度下忽略 Brakeman 漏洞. 整数,1 =低 3 =高. | +| `SAST_DISABLE_BABEL` | `false` | 禁用 NodeJsScan 扫描仪的 Babel 处理. 设置为`true`将禁用 Babel 处理. 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33065) . | +| `SAST_FLAWFINDER_LEVEL` | 1 | 在给定风险级别下忽略 Flawfinder 漏洞. 整数,0 =无风险,5 =高风险. | +| `SAST_GITLEAKS_ENTROPY_LEVEL` | 8.0 | 秘密检测的最小熵. 浮动,0.0 =低,8.0 =高. | +| `SAST_GOSEC_LEVEL` | 0 | 在给定的置信度下忽略 Gosec 漏洞. 整数,0 =未定义,1 =低,2 =中,3 =高. | +| `SAST_GITLEAKS_COMMIT_FROM` |   | 提交 Gitleaks 扫描始于. | +| `SAST_GITLEAKS_COMMIT_TO` |   | Gitleaks 扫描的提交结束于. | +| `SAST_GITLEAKS_HISTORIC_SCAN` | `false` | 标记以启用历史性的 Gitleaks 扫描. | + +#### Docker-in-Docker orchestrator[](#docker-in-docker-orchestrator "Permalink") + +以下变量配置 Docker-in-Docker 协调器,因此仅在[启用](#enabling-docker-in-docker) Docker-in-Docker 模式时才使用. + +| 环境变量 | 默认值 | Description | +| --- | --- | --- | +| `SAST_ANALYZER_IMAGES` |   | 以逗号分隔的自定义图像列表. 默认图像仍处于启用状态. 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `SAST_PULL_ANALYZER_IMAGES` | 1 | 从 Docker 注册表中提取映像(设置为 0 以禁用). 阅读有关[自定义分析器的](analyzers.html)更多信息. | +| `SAST_DOCKER_CLIENT_NEGOTIATION_TIMEOUT` | 2m | Docker 客户端协商的时间限制. 使用 Go 的[`ParseDuration`](https://s0golang0org.icopy.site/pkg/time/)解析超时. 有效时间单位为`ns` , `us` (或`µs` ), `ms` , `s` , `m` , `h` . 例如`300ms` , `1.5h`或`2h45m` . | +| `SAST_PULL_ANALYZER_IMAGE_TIMEOUT` | 5m | Time limit when pulling the image of an analyzer. Timeouts are parsed using Go’s [`ParseDuration`](https://s0golang0org.icopy.site/pkg/time/). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. For example, `300ms`, `1.5h` or `2h45m`. | +| `SAST_RUN_ANALYZER_TIMEOUT` | 20m | 运行分析仪的时间限制. 使用 Go 的[`ParseDuration`](https://s0golang0org.icopy.site/pkg/time/)解析超时. 有效时间单位为`ns` , `us` (或`µs` ), `ms` , `s` , `m` , `h` . 例如`300ms` , `1.5h`或`2h45m` . | + +#### Analyzer settings[](#analyzer-settings "Permalink") + +某些分析仪可以使用环境变量进行自定义. + +| Environment variable | Analyzer | Description | +| --- | --- | --- | +| `SCAN_KUBERNETES_MANIFESTS` | Kubesec | 设置为`"true"`以扫描 Kubernetes 清单. | +| `KUBESEC_HELM_CHARTS_PATH` | Kubesec | `helm`将用于生成`kubesec`将扫描的 Kubernetes 清单的舵图的可选路径. 如果定义了`helm dependency build`则应在`before_script`运行`helm dependency build`以获取必要的依赖关系. | +| `KUBESEC_HELM_OPTIONS` | Kubesec | `helm`可执行文件的其他参数. | +| `COMPILE` | SpotBugs | 设置为`false`可禁用项目编译和依赖项获取. 在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/195252) . | +| `ANT_HOME` | SpotBugs | `ANT_HOME`环境变量. | +| `ANT_PATH` | SpotBugs | `ant`可执行文件的路径. | +| `GRADLE_PATH` | SpotBugs | `gradle`可执行文件的路径. | +| `JAVA_OPTS` | SpotBugs | `java`可执行文件的附加参数. | +| `JAVA_PATH` | SpotBugs | `java`可执行文件的路径. | +| `SAST_JAVA_VERSION` | SpotBugs | 使用哪个 Java 版本. 支持的版本是`8`和`11` . 默认为`8` . | +| `MAVEN_CLI_OPTS` | SpotBugs | `mvn`或`mvnw`可执行文件的其他参数. | +| `MAVEN_PATH` | SpotBugs | `mvn`可执行文件的路径. | +| `MAVEN_REPO_PATH` | SpotBugs | Maven 本地存储库的路径( `maven.repo.local`属性的快捷方式). | +| `SBT_PATH` | SpotBugs | `sbt`可执行文件的路径. | +| `FAIL_NEVER` | SpotBugs | 设置为`1`可忽略编译失败. | +| `SAST_GOSEC_CONFIG` | Gosec | Gosec 的配置路径(可选). | +| `PHPCS_SECURITY_AUDIT_PHP_EXTENSIONS` | phpcs-security-audit | 以逗号分隔的其他 PHP 扩展列表. | +| `SEARCH_MAX_DEPTH` | any | 搜索源代码文件时遍历的最大目录数. 默认值: `4` . | + +#### Custom environment variables[](#custom-environment-variables "Permalink") + +在 GitLab Ultimate 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18193) . + +除上述 SAST 配置变量外,如果[使用 SAST 供应商模板](#configuration) ,则所有[自定义环境变量](../../../ci/variables/README.html#custom-environment-variables)都将传播到基础 SAST 分析器映像. + +**警告:**名称以这些前缀开头的变量将**不会**传播到 SAST Docker 容器和/或分析器容器: `DOCKER_` , `CI` , `GITLAB_` , `FF_` , `HOME` , `PWD` , `OLDPWD` , `PATH` , `SHLVL` , `HOSTNAME` . + +## Reports JSON format[](#reports-json-format "Permalink") + +SAST 工具会发出 JSON 报告文件. 有关更多信息,请参见此[报告](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/sast-report-format.json)的[架构](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/sast-report-format.json) . + +这是一个示例 SAST 报告: + +``` +{ "version": "2.0", "vulnerabilities": [ { "id": "9e96e0ab-23da-4d7d-a09e-0acbaa5e83ca", "category": "sast", "name": "Predictable pseudorandom number generator", "message": "Predictable pseudorandom number generator", "description": "The use of java.util.Random is predictable", "severity": "Medium", "confidence": "Medium", "scanner": { "id": "find_sec_bugs", "name": "Find Security Bugs" }, "location": { "file": "groovy/src/main/groovy/com/gitlab/security_products/tests/App.groovy", "start_line": 47, "end_line": 47, "class": "com.gitlab.security_products.tests.App", "method": "generateSecretToken2", "dependency": { "package": {} } }, "identifiers": [ { "type": "find_sec_bugs_type", "name": "Find Security Bugs-PREDICTABLE_RANDOM", "value": "PREDICTABLE_RANDOM", "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM" }, { "type": "cwe", "name": "CWE-330", "value": "330", "url": "https://cwe.mitre.org/data/definitions/330.html" } ] }, { "id": "e6dbf91f-4c07-46f7-a365-0169489c27d1", "category": "sast", "message": "Probable insecure usage of temp file/directory.", "severity": "Medium", "confidence": "Medium", "scanner": { "id": "bandit", "name": "Bandit" }, "location": { "file": "python/hardcoded/hardcoded-tmp.py", "start_line": 10, "end_line": 10, "dependency": { "package": {} } }, "identifiers": [ { "type": "bandit_test_id", "name": "Bandit Test ID B108", "value": "B108", "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html" } ] }, ], "remediations": [] } +``` + +## Secret detection[](#secret-detection "Permalink") + +了解有关[秘密检测的](../secret_detection)更多信息. + +## Security Dashboard[](#security-dashboard "Permalink") + +在"安全仪表板"中,您可以概览您的组,项目和管道中的所有安全漏洞. 阅读有关[安全仪表板的](../security_dashboard/index.html)更多[信息](../security_dashboard/index.html) . + +## Interacting with the vulnerabilities[](#interacting-with-the-vulnerabilities "Permalink") + +一旦发现漏洞,便可以与其进行交互. 阅读有关如何[与漏洞](../index.html#interacting-with-the-vulnerabilities)进行[交互的](../index.html#interacting-with-the-vulnerabilities)更多信息. + +## Vulnerabilities database[](#vulnerabilities-database "Permalink") + +Vulnerabilities contained within the vulnerability database can be searched and viewed at the [GitLab vulnerability advisory database](https://advisories.gitlab.com). + +### Vulnerabilities database update[](#vulnerabilities-database-update "Permalink") + +有关漏洞数据库更新的更多信息,请查看[维护表](../index.html#maintenance-and-update-of-the-vulnerabilities-database) . + +## Running SAST in an offline environment[](#running-sast-in-an-offline-environment "Permalink") + +对于在通过 Internet 限制,限制或间歇性访问外部资源的环境中进行自我管理的 GitLab 实例,需要进行一些调整才能使 SAST 作业成功运行. 有关更多信息,请参阅[脱机环境](../offline_deployments/index.html) . + +### Requirements for offline SAST[](#requirements-for-offline-sast "Permalink") + +要在离线环境中使用 SAST,您需要: + +* 保持 Docker-In-Docker 禁用(默认). +* GitLab 亚军与[`docker`或`kubernetes`执行](#requirements) . +* Docker Container Registry,带有本地可用的 SAST [分析器](https://gitlab.com/gitlab-org/security-products/analyzers)映像副本. + +**注意:** GitLab Runner 的[默认`pull policy`为`always`](https://docs.gitlab.com/runner/executors/docker.html) ,这意味着即使本地副本可用,Runner 也会尝试从 GitLab 容器注册表中拉取 Docker 映像. 如果您只喜欢使用本地可用的 Docker 映像,则可以在离线环境[`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html) GitLab Runner 的[`pull_policy`设置为`if-not-present`](https://docs.gitlab.com/runner/executors/docker.html) . 但是,如果不在离线环境中,我们建议将拉取策略设置保持为`always` ,因为这样可以在 CI / CD 管道中使用更新的扫描仪. + +### Make GitLab SAST analyzer images available inside your Docker registry[](#make-gitlab-sast-analyzer-images-available-inside-your-docker-registry "Permalink") + +对于具有所有[受支持的语言和框架的](#supported-languages-and-frameworks) SAST,请将以下默认 SAST 分析器图像从`registry.gitlab.com`导入[本地 Docker 容器注册表](../../packages/container_registry/index.html) : + +``` +registry.gitlab.com/gitlab-org/security-products/analyzers/bandit:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/brakeman:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/eslint:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/flawfinder:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/gosec:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/kubesec:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/nodejs-scan:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/pmd-apex:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/secrets:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/security-code-scan:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/sobelow:2 +registry.gitlab.com/gitlab-org/security-products/analyzers/spotbugs:2 +``` + +将 Docker 映像导入本地脱机 Docker 注册表的过程取决于**您的网络安全策略** . 请咨询您的 IT 员工,以找到可以导入或临时访问外部资源的已接受和批准的流程. 请注意,这些扫描程序会[定期](../index.html#maintenance-and-update-of-the-vulnerabilities-database)使用新定义进行[更新](../index.html#maintenance-and-update-of-the-vulnerabilities-database) ,因此请考虑您是否能够自己进行定期更新. + +有关将 Docker 映像保存和传输为文件的详细信息,请参阅 Docker 有关[`docker save`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/save/) , [`docker load`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/load/) , [`docker export`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/export/)和[`docker import`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/import/)的文档. + +### Set SAST CI job variables to use local SAST analyzers[](#set-sast-ci-job-variables-to-use-local-sast-analyzers "Permalink") + +将以下配置添加到您的`.gitlab-ci.yml`文件. 您必须替换`SECURE_ANALYZERS_PREFIX`才能引用本地 Docker 容器注册表: + +``` +include: + - template: SAST.gitlab-ci.yml + +variables: + SECURE_ANALYZERS_PREFIX: "localhost:5000/analyzers" +``` + +现在,SAST 作业应使用 SAST 分析器的本地副本来扫描您的代码并生成安全报告,而无需访问 Internet. + +## Troubleshooting[](#troubleshooting "Permalink") + +### `Error response from daemon: error processing tar file: docker-tar: relocation error`[](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error "Permalink") + +当运行 SAST 作业的码头工人的版本是出现此错误`19.03.0` . 考虑更新到 Docker `19.03.1`或更高版本. 旧版本不受影响. 阅读[本期的](https://gitlab.com/gitlab-org/gitlab/-/issues/13830#note_211354992 "当前的 SAST 容器失败")更多内容. \ No newline at end of file diff --git a/docs/055.md b/docs/055.md new file mode 100644 index 0000000000000000000000000000000000000000..5ea01fbd0812b161c686ba62e853c9c82b6fe34f --- /dev/null +++ b/docs/055.md @@ -0,0 +1,128 @@ +# Secret Detection + +> 原文:[https://docs.gitlab.com/ee/user/application_security/secret_detection/](https://docs.gitlab.com/ee/user/application_security/secret_detection/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Requirements](#requirements) +* [Configuration](#configuration) + * [Using the SAST Template](#using-the-sast-template) + * [Customizing settings](#customizing-settings) + * [Available variables](#available-variables) + * [Logging Level](#logging-level) +* [Full History Secret Scan](#full-history-secret-scan) + +# Secret Detection[](#secret-detection-ultimate "Permalink") + +[Introduced](https://about.gitlab.com/releases/2019/03/22/gitlab-11-9-released/#detect-secrets-and-credentials-in-the-repository) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9. + +## Overview[](#overview "Permalink") + +开发应用程序时经常出现的问题是,开发人员可能会无意间将秘密和凭据提交到其远程存储库. 如果其他人可以访问源,或者项目是公开的,则敏感信息将被公开,恶意用户可以利用这些信息来访问诸如部署环境之类的资源. + +GitLab 11.9 包含一个称为"秘密检测"的新检查. 它扫描存储库的内容以查找 API 密钥和其他不应存在的信息. + +manbetx 客户端打不开显示识别的秘密作为 SAST 报告的一部分在几个地方: + +* [Security Dashboard](../security_dashboard/) +* Pipelines’ **Security** tab +* 合并请求小部件中的报告 + +[![Secret Detection in merge request widget](img/56321b27a391110651e26fae3d93064e.png)](img/secret_detection_v13_2.png) + +## Use cases[](#use-cases "Permalink") + +* 检测密钥,密码和 API 令牌等机密信息的意外提交. +* 对存储库的完整历史记录执行一次或重复扫描以查找机密信息. + +## Requirements[](#requirements "Permalink") + +要运行检测的秘密工作,默认情况下,你需要 GitLab 亚军与[`docker`](https://docs.gitlab.com/runner/executors/docker.html)或[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html)执行. 如果您在 GitLab.com 上使用共享的 Runners,则默认启用该功能. + +**注意:**目前我们的秘密检测作业需要 Linux 容器类型. Windows 容器尚不支持.**注意:**如果使用自己的 Runners,请确保安装的 Docker 版本**不是** `19.03.0` . 有关详细[信息](../sast#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) ,请参见[故障排除信息](../sast#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) . + +## Configuration[](#configuration "Permalink") + +**注意:**在 GitLab 13.1 中,秘密检测被拆分为自己的 CI / CD 模板. + +秘密检测是在`secret-detection`作业期间由[特定的分析器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml)执行的. 无论您的应用程序使用哪种编程语言,它都可以运行. + +秘密检测分析器包括[Gitleaks](https://github.com/zricethezav/gitleaks)和[TruffleHog](https://github.com/dxa4481/truffleHog)检查. + +***Note:** The Secret Detection analyzer will ignore "Password in URL" vulnerabilities if the password begins with a dollar sign ( `$` ) as this likely indicates the password being used is an environment variable. **注意:**如果密码以美元符号( `$` )开头,则秘密检测分析器将忽略" URL 中的密码"漏洞,因为这很可能表明所使用的密码是环境变量. For example, `https://username:$password@example.com/path/to/repo` won't be detected, whereas `https://username:password@example.com/path/to/repo` would be detected. 例如,将不会检测到`https://username:$password@example.com/path/to/repo` ,而将检测到`https://username:password@example.com/path/to/repo` .***注意:**如果您使用的是[Auto DevOps](../../../topics/autodevops/index.html)提供的[自动](../../../topics/autodevops/index.html) [秘密检测,](../../../topics/autodevops/stages.html#auto-secret-detection-ultimate)则不必按照本节中的说明手动配置秘密检测. + +要为 GitLab 13.1 和更高版本启用 Secret Detection,您必须包括`Secret-Detection.gitlab-ci.yml`模板,该模板作为 GitLab 安装的一部分提供. 对于 11.9 之前的 GitLab 版本,您可以复制和使用该模板中定义的作业. + +将以下内容添加到您的`.gitlab-ci.yml`文件中: + +``` +include: + - template: Secret-Detection.gitlab-ci.yml +``` + +包含的模板在 CI / CD 管道中创建"秘密检测"作业,并扫描项目的源代码中的秘密. + +结果将保存为" [秘密检测"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportssecret_detection-ultimate) ,您以后可以下载和分析该[工件](../../../ci/pipelines/job_artifacts.html#artifactsreportssecret_detection-ultimate) . 由于实施限制,我们始终采用最新的秘密检测工件. + +### Using the SAST Template[](#using-the-sast-template "Permalink") + +在 GitLab 13.1 之前,秘密检测是[SAST 配置的](../sast#configuration)一部分. 如果您已经在 GitLab 13.1 之前为您的应用配置了启用 SAST,则无需手动配置它. + +**计划的弃用:**在以后的 GitLab 版本中,将不建议使用 SAST 模板配置秘密检测. 请开始使用`Secret-Detection.gitlab-ci.yml`以防止将来出现问题. 我们制作了一个[视频,指导您完成过渡](https://www.youtube.com/watch?v=W2tjcQreDwQ)到此新模板的过程.观看视频: [历史秘密扫描演练](https://www.youtube.com/watch?v=W2tjcQreDwQ) . + +
      + +使用 SAST 模板时,秘密检测由[特定分析器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml#L180)在`sast`作业期间执行. 它的运行与应用程序的编程语言无关,并且您无需更改 CI / CD 配置文件即可启用它. 结果可在 SAST 报告中获得. + +### Customizing settings[](#customizing-settings "Permalink") + +可以使用`.gitlab-ci.yml`的[`variables`](../../../ci/yaml/README.html#variables)参数通过[环境变量](#available-variables)更改秘密检测扫描设置. + +要覆盖作业定义(例如,更改`variables`或`dependencies`类的属性),请声明与要覆盖的 SAST 作业同名的作业. 将此新作业放置在包含模板之后,并在其下指定其他任何键. + +在下面的示例中,我们包括"秘密检测"模板,同时使用`SECRET_DETECTION_HISTORIC_SCAN`变量将`secret_detection`作业覆盖为`true` : + +``` +include: + - template: Secret-Detection.gitlab-ci.yml + +secret_detection: + variables: + SECRET_DETECTION_HISTORIC_SCAN: "true" +``` + +因为模板是[在](../../../ci/yaml/README.html#include)管道配置[之前进行评估](../../../ci/yaml/README.html#include)的,所以最后提到的变量优先. + +**弃用:**从 GitLab 13.0 开始,不再支持[`only`和`except`](../../../ci/yaml/README.html#onlyexcept-basic)的使用. 覆盖模板时,必须使用[`rules`](../../../ci/yaml/README.html#rules) . + +#### Available variables[](#available-variables "Permalink") + +可以通过定义可用变量来自定义秘密检测: + +| 环境变量 | 默认值 | Description | +| --- | --- | --- | +| `SECRET_DETECTION_COMMIT_FROM` | - | 提交 Gitleaks 扫描始于. | +| `SECRET_DETECTION_COMMIT_TO` | - | Gitleaks 扫描的提交结束于. | +| `SECRET_DETECTION_HISTORIC_SCAN` | false | 标记以启用历史性的 Gitleaks 扫描. | + +### Logging Level[](#logging-level "Permalink") + +您可以通过设置`SECURE_LOG_LEVEL` env var 来控制日志的详细程度. 默认设置为`info` ,您可以将其设置为以下任意级别: + +* `fatal` +* `error` +* `warn` +* `info` +* `debug` + +## Full History Secret Scan[](#full-history-secret-scan "Permalink") + +GitLab 12.11 引入了对扫描存储库完整历史记录的支持. 当您首次在存储库中启用秘密检测并且想要执行完整的秘密扫描时,此新功能特别有用. 对整个历史记录进行秘密扫描可能会花费很长时间,尤其是对于 Git 历史记录较长的大型存储库. 我们建议不要将此变量设置为常规作业定义的一部分. + +可以设置一个新的配置变量( [`SECRET_DETECTION_HISTORIC_SCAN`](../sast/#vulnerability-filters) )来更改 GitLab 秘密检测扫描的行为,使其在存储库的整个 Git 历史记录上运行. + +我们创建了一个[简短的视频演练,](https://youtu.be/wDtc_K00Y0A)展示了如何执行完整的历史秘密扫描. + +观看视频: [历史秘密扫描演练](https://www.youtube.com/watch?v=wDtc_K00Y0A) . + +
      \ No newline at end of file diff --git a/docs/056.md b/docs/056.md new file mode 100644 index 0000000000000000000000000000000000000000..3fb2e6ef22124f03b88408a143ea11bdfd8da58c --- /dev/null +++ b/docs/056.md @@ -0,0 +1,642 @@ +# Dynamic Application Security Testing (DAST) + +> 原文:[https://docs.gitlab.com/ee/user/application_security/dast/](https://docs.gitlab.com/ee/user/application_security/dast/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Requirements](#requirements) +* [Configuration](#configuration) + * [When DAST scans run](#when-dast-scans-run) + * [Hide sensitive information](#hide-sensitive-information) + * [Authentication](#authentication) + * [Full scan](#full-scan) + * [Domain validation](#domain-validation) + * [Ruby on Rails](#ruby-on-rails) + * [Django](#django) + * [Node (with Express)](#node-with-express) + * [Domain validation header via a proxy](#domain-validation-header-via-a-proxy) + * [API scan](#api-scan) + * [Specification format](#specification-format) + * [Import API specification from a URL](#import-api-specification-from-a-url) + * [Import API specification from a file](#import-api-specification-from-a-file) + * [Full scan](#full-scan-1) + * [Host override](#host-override) + * [Authentication using headers](#authentication-using-headers) + * [Customizing the DAST settings](#customizing-the-dast-settings) + * [Available variables](#available-variables) + * [DAST command-line options](#dast-command-line-options) + * [Custom ZAProxy configuration](#custom-zaproxy-configuration) + * [Cloning the project’s repository](#cloning-the-projects-repository) + * [Debugging DAST jobs](#debugging-dast-jobs) +* [Running DAST in an offline environment](#running-dast-in-an-offline-environment) + * [Requirements for offline DAST support](#requirements-for-offline-dast-support) + * [Make GitLab DAST analyzer images available inside your Docker registry](#make-gitlab-dast-analyzer-images-available-inside-your-docker-registry) + * [Set DAST CI job variables to use local DAST analyzers](#set-dast-ci-job-variables-to-use-local-dast-analyzers) +* [On-Demand Scans](#on-demand-scans) + * [Enable or disable On-Demand Scans](#enable-or-disable-on-demand-scans) +* [Reports](#reports) + * [List of URLs scanned](#list-of-urls-scanned) + * [JSON](#json) + * [Other formats](#other-formats) +* [Security Dashboard](#security-dashboard) +* [Bleeding-edge vulnerability definitions](#bleeding-edge-vulnerability-definitions) +* [Interacting with the vulnerabilities](#interacting-with-the-vulnerabilities) +* [Vulnerabilities database update](#vulnerabilities-database-update) +* [Optimizing DAST](#optimizing-dast) +* [Troubleshooting](#troubleshooting) + * [Running out of memory](#running-out-of-memory) + +# Dynamic Application Security Testing (DAST)[](#dynamic-application-security-testing-dast-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4348) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4. + +**注意:**白皮书["应用程序安全性发生](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)了[地震变化"](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)说明**了前 6 种攻击中有 4 种是基于应用程序的** . 下载它以了解如何保护您的组织. + +对代码运行[静态检查](../sast/index.html)是检测可能使代码安全性受到威胁的漏洞的第一步. 但是,一旦部署,您的应用程序将面临一类新的可能的攻击,例如跨站点脚本或损坏的身份验证缺陷. 这是动态应用程序安全性测试(DAST)实施的地方. + +## Overview[](#overview "Permalink") + +如果您使用的是[GitLab CI / CD](../../../ci/README.html) ,则可以使用动态应用程序安全性测试(DAST)分析运行中的 Web 应用程序是否存在已知漏洞. 您可以通过在现有`.gitlab-ci.yml`文件中[包含 CI 作业](#configuration) ,或通过隐式使用[Auto DevOps](../../../topics/autodevops/index.html)提供的[Auto](../../../topics/autodevops/index.html) [DAST](../../../topics/autodevops/stages.html#auto-dast-ultimate)来利用[DAST](../../../topics/autodevops/stages.html#auto-dast-ultimate) . + +GitLab 检查 DAST 报告,比较发现的源分支和目标分支之间的漏洞,并显示有关合并请求的信息. + +**注意:**此比较逻辑仅使用针对目标分支的基本提交执行的最新管道. 在任何其他提交上运行管道对合并请求没有影响. + +[![DAST Widget](img/ae9e67c8841e45007cf186891963198f.png)](img/dast_v13_2.png) + +通过单击检测到的链接漏洞之一,您可以查看详细信息和受影响的 URL. + +[![DAST Widget Clicked](img/7a612dcc3c18a6e6433eb5a57a99368d.png)](img/dast_single_v13_0.png) + +[动态应用程序安全测试(DAST)](https://en.wikipedia.org/wiki/Dynamic_Application_Security_Testing)使用流行的开源工具[OWASP Zed Attack Proxy](https://www.zaproxy.org/)对运行中的 Web 应用程序执行分析. + +默认情况下,DAST 执行[ZAP 基准扫描](https://www.zaproxy.org/docs/docker/baseline-scan/)并仅执行被动扫描. 它不会主动攻击您的应用程序. 但是,可以将 DAST [配置](#full-scan)为还执行*主动扫描* :攻击您的应用程序并生成更广泛的安全报告. 与[Review Apps](../../../ci/review_apps/index.html)结合使用可能非常有用. + +**注意:**管道可能包含多个作业,包括 SAST 和 DAST 扫描. 如果任何作业由于任何原因未能完成,则安全信息中心将不会显示 DAST 扫描仪输出. 例如,如果 DAST 作业完成但 SAST 作业失败,则安全性仪表板将不会显示 DAST 结果. 分析器将在失败时输出[退出代码](../../../development/integrations/secure.html#exit-code) . + +## Use cases[](#use-cases "Permalink") + +它可以帮助您在开发和测试应用程序时自动查找正在运行的 Web 应用程序中的安全漏洞. + +## Requirements[](#requirements "Permalink") + +要运行 DAST 作业,您需要具有[`docker` executor 的](https://docs.gitlab.com/runner/executors/docker.html) GitLab Runner. + +## Configuration[](#configuration "Permalink") + +对于 GitLab 11.9 和更高版本,要启用 DAST,您必须[包含](../../../ci/yaml/README.html#includetemplate) [`DAST.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml) ,该[模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml)作为 GitLab 安装的一部分提供. 对于 11.9 之前的 GitLab 版本,您可以复制和使用该模板中定义的作业. + +将以下内容添加到您的`.gitlab-ci.yml`文件中: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_WEBSITE: https://example.com +``` + +有两种方法来定义要由 DAST 扫描的 URL: + +1. 设置`DAST_WEBSITE` [变量](../../../ci/yaml/README.html#variables) . + +2. 将其添加到项目根目录的`environment_url.txt`文件中. 这非常适合在动态环境中进行测试. 为了针对在 GitLab CI / CD 管道中动态创建的应用程序运行 DAST,请让该应用程序将其域保留在`environment_url.txt`文件中,然后 DAST 自动解析该文件以找到其扫描目标. 您可以在我们的 Auto DevOps CI YAML 中看到一个[示例](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml) . + +如果同时设置了两个值,则`DAST_WEBSITE`值优先. + +随附的模板会在 CI / CD 管道中创建`dast`工作,并扫描项目的源代码中可能存在的漏洞. + +结果将保存为[DAST 报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsdast-ultimate) ,您可以稍后下载和分析. 由于实施限制,我们始终采用最新的 DAST 工件. 在后台, [GitLab DAST Docker 映像](https://gitlab.com/gitlab-org/security-products/dast)用于在指定的 URL 上运行测试并扫描它是否存在漏洞. + +默认情况下,DAST 模板将使用 DAST Docker 映像的最新主版本. 使用`DAST_VERSION`变量,您可以选择 DAST 更新的方式: + +* 通过固定到主要版本(例如`1` )自动更新具有新功能和修复程序的 DAST. +* 仅通过固定到次要版本(例如`1.6` )来更新修补程序. +* 通过固定到特定版本(例如`1.6.4` )来防止所有更新. + +在" [发行"](https://gitlab.com/gitlab-org/security-products/dast/-/releases)页面上找到最新的 DAST 版本. + +### When DAST scans run[](#when-dast-scans-run "Permalink") + +使用`DAST.gitlab-ci.yml`模板时, `dast`作业最后运行,如下例所示. 为确保 DAST 正在扫描最新代码,您的 CI 管道应在`dast`作业之前的`dast`作业`dast`更改部署到 Web 服务器. + +``` +stages: + - build + - test + - deploy + - dast +``` + +请注意,如果您将管道配置为在每次运行中都部署到同一 Web 服务器,则在另一个管道仍在运行时运行管道可能会导致争用情况,其中一个管道会覆盖另一个管道的代码. 在 DAST 扫描期间,应从更改中排除要扫描的站点. 对该站点的唯一更改应来自 DAST 扫描仪. 请注意,在扫描过程中,用户,计划任务,数据库更改,代码更改,其他管道或其他扫描程序对站点所做的任何更改都可能导致结果不准确. + +### Hide sensitive information[](#hide-sensitive-information "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36332) . + +HTTP 请求和响应标头可能包含敏感信息,包括 cookie 和授权凭证. 默认情况下,以下标头被屏蔽: + +* `Authorization`. +* `Proxy-Authorization`. +* `Set-Cookie` (仅值). +* `Cookie` (values only). + +使用[`DAST_MASK_HTTP_HEADERS`变量](#available-variables) ,可以列出要屏蔽其值的标头. 有关如何屏蔽标题的详细信息,请参阅" [自定义 DAST 设置"](#customizing-the-dast-settings) . + +### Authentication[](#authentication "Permalink") + +在执行 DAST 检查之前,还可以对用户进行身份验证. + +创建掩码变量以传递 DAST 将使用的凭据. 要为用户名和密码创建掩码变量,请参阅[在 UI 中创建自定义变量](../../../ci/variables/README.html#create-a-custom-variable-in-the-ui) . 请注意,username 变量的密钥必须为`DAST_USERNAME` ,而 password 变量的密钥必须为`DAST_PASSWORD` . + +与认证扫描相关的其他变量是: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_WEBSITE: https://example.com + DAST_AUTH_URL: https://example.com/sign-in + DAST_USERNAME_FIELD: session[user] # the name of username field at the sign-in HTML form + DAST_PASSWORD_FIELD: session[password] # the name of password field at the sign-in HTML form + DAST_AUTH_EXCLUDE_URLS: http://example.com/sign-out,http://example.com/sign-out-2 # optional, URLs to skip during the authenticated scan; comma-separated, no spaces in between +``` + +结果将保存为[DAST 报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsdast-ultimate) ,您以后可以下载和分析. 由于实施限制,我们始终采用最新的 DAST 工件. + +**危险:** **切勿**对生产服务器运行经过身份验证的扫描. 运行经过身份验证的扫描时,它可以执行经过身份验证的用户可以执行的*任何*功能. 这包括修改和删除数据,提交表单以及跟随链接之类的操作. 仅对测试服务器运行经过身份验证的扫描. + +### Full scan[](#full-scan "Permalink") + +可以将 DAST 配置为执行[ZAP 全面扫描](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) ,其中包括针对同一目标网站的被动扫描和主动扫描: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_FULL_SCAN_ENABLED: "true" +``` + +#### Domain validation[](#domain-validation "Permalink") + +DAST 作业可以在任何地方运行,这意味着您可能会意外击中实时 Web 服务器并可能损坏它们. 您甚至可以减少生产环境. 因此,您应该使用域验证. + +默认情况下,不需要域验证. 通过将[环境变量](#available-variables) `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED`设置为`"true"`可能需要它. + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_FULL_SCAN_ENABLED: "true" + DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED: "true" +``` + +由于 ZAP 全面扫描会主动攻击目标应用程序,因此 DAST 会事先向目标(通常在`DAST_WEBSITE`或`environment_url.txt`定义)发送 ping 命令. + +* 如果`DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED`为`false`或未设置,则将继续进行扫描,除非对 ping 的响应包含值为`deny`的`Gitlab-DAST-Permission`标头. +* 如果`DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED`是`true` ,则扫描将退出除非对 ping 响应包括一个`Gitlab-DAST-Permission`用的头值`allow` . + +以下是在 Rails,Django 和 Node(使用 Express)中向响应添加`Gitlab-DAST-Permission`标头的一些示例. + +##### Ruby on Rails[](#ruby-on-rails "Permalink") + +这是[在 Ruby on Rails 中](https://guides.rubyonrails.org/action_controller_overview.html#setting-custom-headers)添加[自定义标头的方法](https://guides.rubyonrails.org/action_controller_overview.html#setting-custom-headers) : + +``` +class DastWebsiteTargetController < ActionController::Base + def dast_website_target + response.headers['Gitlab-DAST-Permission'] = 'allow' + + head :ok + end +end +``` + +##### Django[](#django "Permalink") + +Here’s how you would add a [custom header in Django](https://docs.djangoproject.com/en/2.2/ref/request-response/#setting-header-fields): + +``` +class DastWebsiteTargetView(View): + def head(self, *args, **kwargs): + response = HttpResponse() + response['Gitlab-Dast-Permission'] = 'allow' + + return response +``` + +##### Node (with Express)[](#node-with-express "Permalink") + +这是[在 Node(使用 Express)中](http://expressjs0com.icopy.site/en/5x/api.html)添加[自定义标头的方法](http://expressjs0com.icopy.site/en/5x/api.html) : + +``` +app.get('/dast-website-target', function(req, res) { + res.append('Gitlab-DAST-Permission', 'allow') + res.send('Respond to DAST ping') +}) +``` + +##### Domain validation header via a proxy[](#domain-validation-header-via-a-proxy "Permalink") + +也可以通过代理添加`Gitlab-DAST-Permission`标头. + +###### NGINX[](#nginx "Permalink") + +以下配置允许 NGINX 充当反向代理并添加`Gitlab-DAST-Permission` [标头](http://nginx0org.icopy.site/en/docs/http/ngx_http_headers_module.html) : + +``` +# default.conf +server { + listen 80; + server_name localhost; + + location / { + proxy_pass http://test-application; + add_header Gitlab-DAST-Permission allow; + } +} +``` + +###### Apache[](#apache "Permalink") + +Apache 还可以用作[反向代理,](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html)以添加`Gitlab-DAST-Permission` [标头](https://httpd.apache.org/docs/current/mod/mod_headers.html) . + +为此, `httpd.conf`添加到`httpd.conf` : + +``` +# httpd.conf +LoadModule proxy_module modules/mod_proxy.so +LoadModule proxy_connect_module modules/mod_proxy_connect.so +LoadModule proxy_http_module modules/mod_proxy_http.so + + + ProxyPass "/" "http://test-application.com/" + ProxyPassReverse "/" "http://test-application.com/" + Header set Gitlab-DAST-Permission "allow" + +``` + +[此代码段](https://gitlab.com/gitlab-org/security-products/dast/snippets/1894732)包含完整的`httpd.conf`文件,该文件配置为充当远程代理并添加`Gitlab-DAST-Permission`标头. + +### API scan[](#api-scan "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10928) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. + +使用 API​​规范作为扫描目标是一种为 URL 注入用于扫描 API 的有用方法. API 扫描中的漏洞规则与普通网站扫描中的漏洞规则不同. + +#### Specification format[](#specification-format "Permalink") + +API 扫描支持 OpenAPI V2 和 OpenAPI V3 规范. 您可以使用`JSON`或`YAML`定义这些规范. + +#### Import API specification from a URL[](#import-api-specification-from-a-url "Permalink") + +如果可以通过 URL 访问 API 规范,则可以直接将该 URL 作为目标传递. 该规范不必与要测试的 API 托管在同一主机上. + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_API_SPECIFICATION: http://my.api/api-specification.yml +``` + +#### Import API specification from a file[](#import-api-specification-from-a-file "Permalink") + +如果您的存储库中有 API 规范,则可以直接提供规范的文件名作为目标. 规范文件应位于`/zap/wrk`目录中. + +``` +dast: + script: + - mkdir -p /zap/wrk + - cp api-specification.yml /zap/wrk/api-specification.yml + - /analyze -t $DAST_WEBSITE + variables: + GIT_STRATEGY: fetch + DAST_API_SPECIFICATION: api-specification.yml +``` + +#### Full scan[](#full-scan-1 "Permalink") + +API 扫描支持完全扫描,可以使用`DAST_FULL_SCAN_ENABLED`环境变量来启用它. 完整的 API 扫描不支持域验证. + +#### Host override[](#host-override "Permalink") + +规范通常定义一个主机,其中包含一个域名和一个端口. 引用的主机可能与 API 的审阅实例的主机不同. 这可能导致导入不正确的 URL,或对不正确的主机进行扫描. 使用`DAST_API_HOST_OVERRIDE`环境变量来覆盖这些值. + +例如,对于包含以下内容的 OpenAPI V3 规范: + +``` +servers: + - url: https://api.host.com +``` + +如果 API 的测试版本在`https://api-test.host.com`上运行,则可以使用以下 DAST 配置: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_API_SPECIFICATION: http://api-test.host.com/api-specification.yml + DAST_API_HOST_OVERRIDE: api-test.host.com +``` + +请注意, `DAST_API_HOST_OVERRIDE`仅适用于 URL 导入的规范. + +#### Authentication using headers[](#authentication-using-headers "Permalink") + +请求标头中的令牌通常用作验证 API 请求的方式. 您可以通过使用`DAST_REQUEST_HEADERS`环境变量来实现. 标头适用于 DAST 提出的每个请求. + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_API_SPECIFICATION: http://api-test.api.com/api-specification.yml + DAST_REQUEST_HEADERS: "Authorization: Bearer my.token" +``` + +### Customizing the DAST settings[](#customizing-the-dast-settings "Permalink") + +**弃用:**从 GitLab 13.0 开始,不再支持[`only`和`except`](../../../ci/yaml/README.html#onlyexcept-basic)的使用. 覆盖模板时,必须使用[`rules`](../../../ci/yaml/README.html#rules) . + +可以使用`.gitlab-ci.yml`的[`variables`](../../../ci/yaml/README.html#variables)参数通过环境变量更改 DAST 设置. 这些变量记录在[可用变量中](#available-variables) . + +例如: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_WEBSITE: https://example.com + DAST_SPIDER_MINS: 120 +``` + +因为模板是[在](../../../ci/yaml/README.html#include)管道配置[之前评估](../../../ci/yaml/README.html#include)的,所以最后提到的变量将具有优先权. + +### Available variables[](#available-variables "Permalink") + +可以使用环境变量[配置](#customizing-the-dast-settings) DAST. + +| 环境变量 | Type | Description | +| --- | --- | --- | +| `SECURE_ANALYZERS_PREFIX` | URL | 设置用于下载分析器的 Docker 注册表基地址. | +| `DAST_WEBSITE` | URL | 要扫描的网站的 URL. 如果省略,则必须指定`DAST_API_SPECIFICATION` . | +| `DAST_API_SPECIFICATION` | 网址或字符串 | 要导入的 API 规范. 该规范可以托管在 URL 或`/zap/wrk`目录中存在的文件的名称中. 如果省略,则必须指定`DAST_WEBSITE` . | +| `DAST_AUTH_URL` | URL | 目标网站上包含登录 HTML 表单的页面的 URL. `DAST_USERNAME`和`DAST_PASSWORD`将与登录表单一起提交,以创建经过身份验证的扫描. API 扫描不支持. | +| `DAST_USERNAME` | string | 网站中要验证的用户名. | +| `DAST_PASSWORD` | string | 网站中要验证的密码. | +| `DAST_USERNAME_FIELD` | string | 登录 HTML 表单中的用户名字段名称. | +| `DAST_PASSWORD_FIELD` | string | 登录 HTML 表单中的密码字段名称. | +| `DAST_MASK_HTTP_HEADERS` | string | 要屏蔽的请求和响应头的逗号分隔列表(在 GitLab 13.1 中引入). 必须包含**所有**要屏蔽的标头. 请参阅[默认情况下被屏蔽的标题列表](#hide-sensitive-information) . | +| `DAST_AUTH_EXCLUDE_URLS` | URLs | 经过身份验证的扫描期间要跳过的 URL; 以逗号分隔,中间没有空格. API 扫描不支持. | +| `DAST_FULL_SCAN_ENABLED` | boolean | 设置为`true`可以运行[ZAP 全面扫描](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan)而不是[ZAP 基线扫描](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan) . 默认值: `false` | +| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | boolean | 设置为`true`以在运行 DAST 全面扫描时要求[域验证](#domain-validation) . API 扫描不支持. 默认值: `false` | +| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP 附件固定在 DAST Docker 映像中的特定版本. 设置为`true`以在扫描开始时下载最新版本. 默认值: `false` | +| `DAST_API_HOST_OVERRIDE` | string | 用于覆盖 API 规范文件中定义的域. 范例: `example.com:8080` : `example.com:8080` | +| `DAST_EXCLUDE_RULES` | string | 设置为以逗号分隔的漏洞规则 ID 列表,以将其排除在扫描过程之外. 规则 ID 是数字,可以从 DAST 日志或[ZAP 项目中找到](https://github.com/zaproxy/zaproxy/blob/develop/docs/scanners.md) . 例如, `HTTP Parameter Override`的规则 ID 为`10026` . **注意:**在早期版本的 GitLab 中,已执行排除的规则,但禁止生成它们的警报. 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) . | +| `DAST_REQUEST_HEADERS` | string | 设置为请求标题名称和值的逗号分隔列表. 标头将添加到 DAST 提出的每个请求中. 例如, `Cache-control: no-cache,User-Agent: DAST/1.0` | +| `DAST_DEBUG` | boolean | 启用调试消息输出. 默认值: `false` | +| `DAST_SPIDER_MINS` | number | 蜘蛛扫描的最大持续时间(以分钟为单位). 设置为`0`表示无限制. 默认值:一分钟,如果扫描为完全扫描,则为无限. | +| `DAST_HTML_REPORT` | string | 扫描结束时编写的 HTML 报告的文件名. | +| `DAST_MARKDOWN_REPORT` | string | 扫描结束时写入的 Markdown 报告的文件名. | +| `DAST_XML_REPORT` | string | 扫描结束时写入的 XML 报告的文件名. | +| `DAST_INCLUDE_ALPHA_VULNERABILITIES` | boolean | 设置为`true`以包括 alpha 被动和主动扫描规则. 默认值: `false` | +| `DAST_USE_AJAX_SPIDER` | boolean | 设置为`true`可以除传统蜘蛛外还使用 AJAX 蜘蛛,对爬网需要 JavaScript 的站点很有用. 默认值: `false` | +| `DAST_ZAP_CLI_OPTIONS` | string | ZAP 服务器命令行选项. 例如, `-Xmx3072m`将设置 Java 最大内存分配池大小. | +| `DAST_ZAP_LOG_CONFIGURATION` | string | 设置为 ZAP 服务器的其他 log4j 属性的分号分隔列表. 例如, `log4j.logger.org.parosproxy.paros.network.HttpSender=DEBUG;log4j.logger.com.crawljax=DEBUG` | + +### DAST command-line options[](#dast-command-line-options "Permalink") + +并非所有 DAST 配置都可以通过环境变量获得. 要找出所有可能的选项,请运行以下配置. 可用的命令行选项将被打印到作业日志中: + +``` +include: + template: DAST.gitlab-ci.yml + +dast: + script: + - /analyze --help +``` + +然后,您必须覆盖`script`命令以传递适当的参数. 例如,可以使用选项`-D`延迟被动扫描. 以下配置将被动扫描延迟了五分钟: + +``` +include: + template: DAST.gitlab-ci.yml + +dast: + script: + - export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)} + - /analyze -D 300 -t $DAST_WEBSITE +``` + +### Custom ZAProxy configuration[](#custom-zaproxy-configuration "Permalink") + +ZAProxy 服务器包含许多[有用的可配置值](https://gitlab.com/gitlab-org/gitlab/-/issues/36437#note_245801885) . `-config`许多键/值仍未记录,但是有未测试的[可能键](https://gitlab.com/gitlab-org/gitlab/-/issues/36437#note_244981023)列表. 请注意,DAST 不支持这些选项,并且在使用时可能会中断 DAST 扫描. 下面是一个如何使用`TOKEN`重写 Authorization 标头值的示例: + +``` +include: + template: DAST.gitlab-ci.yml + +variables: + DAST_ZAP_CLI_OPTIONS: "-config replacer.full_list(0).description=auth -config replacer.full_list(0).enabled=true -config replacer.full_list(0).matchtype=REQ_HEADER -config replacer.full_list(0).matchstr=Authorization -config replacer.full_list(0).regex=false -config replacer.full_list(0).replacement=TOKEN" +``` + +### Cloning the project’s repository[](#cloning-the-projects-repository "Permalink") + +DAST 作业在运行时不需要存在项目的存储库,因此默认情况下[`GIT_STRATEGY`](../../../ci/yaml/README.html#git-strategy)设置为`none` . + +### Debugging DAST jobs[](#debugging-dast-jobs "Permalink") + +A DAST job has two executing processes: + +* ZAP 服务器. +* 启动,控制和停止 ZAP 服务器的一系列脚本. + +可以使用`DAST_DEBUG`环境变量来启用脚本的调试模式. 这在对作业进行故障排除时会有所帮助,并且将输出指示扫描完成百分比的语句. 有关使用变量的详细信息,请参见[覆盖 DAST 模板](#customizing-the-dast-settings) . + +可以使用`DAST_ZAP_LOG_CONFIGURATION`环境变量启用 ZAP 服务器的调试模式. 下表概述了可以设置的值的示例,以及它们对记录的输出的影响. 可以指定多个值,以分号分隔. + +| 日志配置值 | Effect | +| --- | --- | +| `log4j.rootLogger=DEBUG` | 启用所有调试日志记录语句. | +| `log4j.logger.org.apache.commons.httpclient=DEBUG` | 记录 ZAP 服务器所做的每个 HTTP 请求和响应. | +| `log4j.logger.org.zaproxy.zap.spider.SpiderController=DEBUG` | 在目标的蜘蛛扫描期间找到的日志 URL. | +| `log4j.logger.com.crawljax=DEBUG` | 启用 Ajax Crawler 调试日志记录语句. | +| `log4j.logger.org.parosproxy.paros=DEBUG` | 启用 ZAP 服务器代理调试日志记录语句. | +| `log4j.logger.org.zaproxy.zap=DEBUG` | 启用常规 ZAP 服务器代码的调试日志记录语句. | + +## Running DAST in an offline environment[](#running-dast-in-an-offline-environment "Permalink") + +对于在通过互联网有限,受限或间歇性访问外部资源的环境中进行自我管理的 GitLab 实例,需要进行一些调整才能成功运行 DAST 作业. 有关更多信息,请参阅[脱机环境](../offline_deployments/index.html) . + +### Requirements for offline DAST support[](#requirements-for-offline-dast-support "Permalink") + +要在离线环境中使用 DAST,您需要: + +* GitLab 亚军与[`docker`或`kubernetes`执行](#requirements) . +* 带有 DAST [容器映像](https://gitlab.com/gitlab-org/security-products/dast)的本地可用副本的 Docker 容器注册表,可在[DAST 容器注册表中找到](https://gitlab.com/gitlab-org/security-products/dast/container_registry) . + +**Note:** GitLab Runner has a [default `pull policy` of `always`](https://docs.gitlab.com/runner/executors/docker.html), meaning the Runner tries to pull Docker images from the GitLab container registry even if a local copy is available. GitLab Runner’s [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html) in an offline environment if you prefer using only locally available Docker images. However, we recommend keeping the pull policy setting to `always` if not in an offline environment, as this enables the use of updated scanners in your CI/CD pipelines. + +### Make GitLab DAST analyzer images available inside your Docker registry[](#make-gitlab-dast-analyzer-images-available-inside-your-docker-registry "Permalink") + +对于 DAST,将以下默认 DAST 分析器映像从`registry.gitlab.com`导入到[本地 Docker 容器注册表](../../packages/container_registry/index.html) : + +* `registry.gitlab.com/gitlab-org/security-products/dast:latest` + +The process for importing Docker images into a local offline Docker registry depends on **您的网络安全政策**. Please consult your IT staff to find an accepted and approved process by which external resources can be imported or temporarily accessed. Note that these scanners are [updated periodically](../index.html#maintenance-and-update-of-the-vulnerabilities-database) with new definitions, so consider if you’re able to make periodic updates yourself. + +有关将 Docker 映像保存和传输为文件的详细信息,请参阅 Docker 有关[`docker save`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/save/) , [`docker load`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/load/) , [`docker export`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/export/)和[`docker import`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/import/)的文档. + +### Set DAST CI job variables to use local DAST analyzers[](#set-dast-ci-job-variables-to-use-local-dast-analyzers "Permalink") + +将以下配置添加到您的`.gitlab-ci.yml`文件. 您必须替换`image`以引用本地 Docker 容器注册表中托管的 DAST Docker 映像: + +``` +include: + - template: DAST.gitlab-ci.yml +dast: + image: registry.example.com/namespace/dast:latest +``` + +DAST 作业现在应该使用 DAST 分析器的本地副本来扫描您的代码并生成安全报告,而无需访问 Internet. + +或者,您可以使用变量`SECURE_ANALYZERS_PREFIX`覆盖`dast`映像的基本注册表地址. + +## On-Demand Scans[](#on-demand-scans "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上已禁用. +* 每个项目都可以启用或禁用它. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-on-demand-scans) . + +在 DevOps 生命周期之外,可以根据需要针对目标网站运行被动 DAST 扫描. 这些扫描将始终与项目的默认分支或`master`分支关联,并且结果可以在项目仪表板中看到. + +[![DAST On-Demand Scan](img/49588b733704d134418744f910f7809b.png)](img/dast_on_demand_v13_2.png) + +### Enable or disable On-Demand Scans[](#enable-or-disable-on-demand-scans "Permalink") + +按需扫描正在开发中,尚未准备好用于生产. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以为您的实例启用它. 可以按项目启用或禁用按需扫描 + +要启用它: + +``` +# Instance-wide +Feature.enable(:security_on_demand_scans_feature_flag) +# or by project +Feature.enable(:security_on_demand_scans_feature_flag, Project.find()) +``` + +To disable it: + +``` +# Instance-wide +Feature.disable(:security_on_demand_scans_feature_flag) +# or by project +Feature.disable(:security_on_demand_scans_feature_flag, Project.find()) +``` + +## Reports[](#reports "Permalink") + +默认情况下,DAST 工具以 JSON 格式输出报告文件. 但是,此工具还可以生成 Markdown,HTML 和 XML 的报告. 有关更多信息,请参阅[DAST 报告](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/dast-report-format.json)的[架构](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/dast-report-format.json) . + +### List of URLs scanned[](#list-of-urls-scanned "Permalink") + +当 DAST 完成扫描时,合并请求页面将说明扫描的 URL 数量. 单击**查看详细信息**以查看 Web 控制台输出,其中包括扫描的 URL 列表. + +[![DAST Widget](img/81cb03504811f2ae5f008de13366a1db.png)](img/dast_urls_scanned_v12_10.png) + +### JSON[](#json "Permalink") + +**警告:** JSON 报表工件不是 DAST 的公共 API,并且其格式预计会在将来更改. + +DAST 工具始终会发出一个名为`gl-dast-report.json`的 JSON 报告文件,并且可以在[DAST 存储库中](https://gitlab.com/gitlab-org/security-products/dast/-/tree/master/test/end-to-end/expect)找到示例报告. + +JSON 报表中有两种数据格式可以并排使用: + +* 专有的 ZAP 格式将最终弃用. +* 一种通用格式,将来会成为默认格式. + +### Other formats[](#other-formats "Permalink") + +还可以用 Markdown,HTML 和 XML 生成报告. 这些可以使用以下配置作为工件发布: + +``` +include: + template: DAST.gitlab-ci.yml + +dast: + variables: + DAST_HTML_REPORT: report.html + DAST_MARKDOWN_REPORT: report.md + DAST_XML_REPORT: report.xml + artifacts: + paths: + - $DAST_HTML_REPORT + - $DAST_MARKDOWN_REPORT + - $DAST_XML_REPORT + - gl-dast-report.json +``` + +## Security Dashboard[](#security-dashboard "Permalink") + +在"安全仪表板"中,您可以概览您的组,项目和管道中的所有安全漏洞. 阅读有关[安全仪表板的](../security_dashboard/index.html)更多[信息](../security_dashboard/index.html) . + +## Bleeding-edge vulnerability definitions[](#bleeding-edge-vulnerability-definitions "Permalink") + +ZAP 首先在`alpha`类中创建规则. 经过与社区的测试期后,他们被提升为`beta` . 默认情况下,DAST 使用`beta`定义. 要请求`alpha`定义,请使用`DAST_INCLUDE_ALPHA_VULNERABILITIES`环境变量,如以下配置所示: + +``` +include: + template: DAST.gitlab-ci.yml + +variables: + DAST_INCLUDE_ALPHA_VULNERABILITIES: true +``` + +## Interacting with the vulnerabilities[](#interacting-with-the-vulnerabilities "Permalink") + +一旦发现漏洞,便可以与其进行交互. 阅读有关如何[与漏洞](../index.html#interacting-with-the-vulnerabilities)进行[交互的](../index.html#interacting-with-the-vulnerabilities)更多信息. + +## Vulnerabilities database update[](#vulnerabilities-database-update "Permalink") + +有关漏洞数据库更新的更多信息,请查看[维护表](../index.html#maintenance-and-update-of-the-vulnerabilities-database) . + +## Optimizing DAST[](#optimizing-dast "Permalink") + +默认情况下,DAST 将下载管道中先前作业定义的所有工件. 如果您的 DAST 作业不依赖`environment_url.txt`来定义被测 URL 或以前的作业中创建的任何其他文件,我们建议您不要下载工件. 为了避免下载工件,请将以下内容添加到您的`gitlab-ci.yml`文件中: + +``` +dast: dependencies: [] +``` + +## Troubleshooting[](#troubleshooting "Permalink") + +### Running out of memory[](#running-out-of-memory "Permalink") + +默认情况下,DAST 依赖的 ZAProxy 被分配的内存总计为主机上总内存的 25%. 由于它在扫描期间将大部分信息保留在内存中,因此 DAST 在扫描大型应用程序时可能会用尽内存. 这将导致以下错误: + +``` +[zap.out] java.lang.OutOfMemoryError: Java heap space +``` + +幸运的是,通过使用`DAST_ZAP_CLI_OPTIONS`环境变量可以直接增加 DAST 可用的内存量: + +``` +include: + - template: DAST.gitlab-ci.yml + +variables: + DAST_ZAP_CLI_OPTIONS: "-Xmx3072m" +``` + +在此,DAST 被分配了 3072 MB. 将`-Xmx`之后的数字更改为所需的存储量. \ No newline at end of file diff --git a/docs/057.md b/docs/057.md new file mode 100644 index 0000000000000000000000000000000000000000..8b2a1b850199a90fe39bef322541e1d64f6c9398 --- /dev/null +++ b/docs/057.md @@ -0,0 +1,160 @@ +# GitLab Security Dashboard + +> 原文:[https://docs.gitlab.com/ee/user/application_security/security_dashboard/](https://docs.gitlab.com/ee/user/application_security/security_dashboard/) + +* [Supported reports](#supported-reports) +* [Requirements](#requirements) +* [Pipeline Security](#pipeline-security) +* [Project Security Dashboard](#project-security-dashboard) +* [Group Security Dashboard](#group-security-dashboard) +* [Instance Security Dashboard](#instance-security-dashboard) + * [Adding projects to the dashboard](#adding-projects-to-the-dashboard) +* [Export vulnerabilities](#export-vulnerabilities) +* [Keeping the dashboards up to date](#keeping-the-dashboards-up-to-date) +* [Security scans using Auto DevOps](#security-scans-using-auto-devops) +* [Vulnerability list](#vulnerability-list) + +# GitLab Security Dashboard[](#gitlab-security-dashboard-ultimate "Permalink") + +在"安全仪表板"中,您可以概览您的组,项目和管道中的所有安全漏洞. + +您还可以深入研究漏洞并获得更多信息,查看其来源,项目所在的文件以及各种元数据,以帮助您分析风险. 您也可以通过为漏洞创建问题或消除漏洞来对漏洞采取措施. + +要从"安全仪表板"中受益,您必须首先配置其中一份[安全报告](../index.html) . + +## Supported reports[](#supported-reports "Permalink") + +安全仪表板支持以下报告: + +* [Container Scanning](../container_scanning/index.html) +* [Dynamic Application Security Testing](../dast/index.html) +* [Dependency Scanning](../dependency_scanning/index.html) +* [Static Application Security Testing](../sast/index.html) + +## Requirements[](#requirements "Permalink") + +要使用实例,组,项目或管道安全性仪表板,请执行以下操作: + +1. 组中的至少一个项目必须配置有至少一个[受支持的报告](#supported-reports) . +2. 配置的作业必须使用[新的`reports`语法](../../../ci/pipelines/job_artifacts.html#artifactsreports) . +3. 必须使用[GitLab Runner](https://docs.gitlab.com/runner/) 11.5 或更高版本. 如果您在 GitLab.com 上使用共享的 Runners,那么情况已经如此. + +## Pipeline Security[](#pipeline-security "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13496) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.3. + +在管道级别,"安全性"部分显示了运行管道所针对的项目分支中存在的漏洞. + +访问页面以查看运行了任何[受支持报告的](#supported-reports)任何管道. 单击**安全性**选项卡以查看安全性发现. + +[![Pipeline Security Dashboard](img/f0d8585fb8235b36b1464ed1d142a4c0.png)](img/pipeline_security_dashboard_v13_2.png) + +**注意:**管道包含多个作业,包括 SAST 和 DAST 扫描. 如果任何作业由于任何原因无法完成,则安全信息中心将不会显示 SAST 扫描仪输出. 例如,如果 SAST 作业完成但 DAST 作业失败,则安全性仪表板将不会显示 SAST 结果. 分析器将在失败时输出[退出代码](../../../development/integrations/secure.html#exit-code) . + +## Project Security Dashboard[](#project-security-dashboard "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6165) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.1. + +在项目级别,安全性仪表板显示合并到项目的[默认分支中](../../project/repository/branches/index.html#default-branch)的漏洞. 通过导航到" **安全与合规性">"安全仪表板"**来访问它. + +安全仪表板首先按严重性显示漏洞的总数(例如,严重,高,中,低). 在此下方,有一个表显示每个漏洞的状态,严重性和描述. 单击漏洞会将您带到其" [漏洞详细信息"](../vulnerabilities)页面,以查看有关该漏洞的更多信息. + +您可以通过以下方式过滤漏洞: + +* Status +* Severity +* 报告类型 + +您还可以消除表中的漏洞: + +1. 选择要消除的每个漏洞的复选框. +2. 在出现的菜单中,选择**退出**的原因,然后点击**取消选中** . + +[![Project Security Dashboard](img/2066156f84e498acec96cdfb63d2d2a4.png)](img/project_security_dashboard_v13_2.png) + +## Group Security Dashboard[](#group-security-dashboard "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6709) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5. + +组安全仪表板概述了组及其子组中项目的默认分支中的漏洞. 通过导航至组的" **安全性">"安全性仪表板"**来访问它. + +**注意:** "安全仪表板"仅显示在组中启用了[安全报告的](#supported-reports)项目. + +[![Dashboard with action buttons and metrics](img/7b7c08f411e1307c05a834071bccb610.png)](img/group_security_dashboard_v13_2_noNav.png) + +您可以通过以下方式过滤安全仪表板显示的漏洞: + +* Status +* Severity +* 报告类型 +* Project + +表格列出了漏洞,并按严重性排序. 该表显示了每个漏洞的状态,严重性和描述. 单击漏洞会将您带到其" [漏洞详细信息"](../vulnerabilities)页面,以查看有关该漏洞的更多信息. + +列表旁边是时间线图,该图显示了您的项目在不同时间点有多少个未解决的漏洞. 您可以在 30 天,60 天和 90 天之间进行过滤,默认值为 90 天.将鼠标悬停在图表上可获得有关特定时间未解决漏洞的更多详细信息. + +时间线图表下方是项目列表,按发现的漏洞的严重程度进行分组和排序: + +* F:1 个或更多"关键" +* D:1 个或多个"高"或"未知" +* C: 1 or more “medium” +* B:1 个或多个"低" +* 答:0 个漏洞 + +未配置漏洞测试的项目不会出现在列表中. 此外,也不包含已消除的漏洞. + +阅读有关如何[与漏洞](../index.html#interacting-with-the-vulnerabilities)进行[交互的](../index.html#interacting-with-the-vulnerabilities)更多信息. + +## Instance Security Dashboard[](#instance-security-dashboard "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6953) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.8. + +在实例级别,安全仪表板显示您配置为显示在仪表板上的所有项目的默认分支中存在的漏洞. 它包括[组"安全仪表板"的](#group-security-dashboard)所有功能. + +您可以从页面顶部的菜单栏中访问 Instance Security 仪表板. 在" **更多"下** ,选择" **安全性"** . + +[![Instance Security Dashboard navigation link](img/25892ec4aa99429a91c30ac3395379e0.png)](img/instance_security_dashboard_link_v12_4.png) + +### Adding projects to the dashboard[](#adding-projects-to-the-dashboard "Permalink") + +要将项目添加到仪表板: + +1. 单击"实例安全性仪表板"页面上的**编辑仪表板**按钮. +2. 使用" **搜索您的项目"**字段搜索并添加一个或多个项目. +3. 单击**添加项目**按钮. + +添加后,安全仪表板将显示在所选项目的默认分支中发现的漏洞. + +[![Instance Security Dashboard with projects](img/5653420f4acd0e8a49be80d5d413bd10.png)](img/instance_security_dashboard_with_projects_v13_2_sm.png) + +## Export vulnerabilities[](#export-vulnerabilities "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213014) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. + +您可以通过以下方式将所有漏洞导出为 CSV 格式: 位于**安全仪表板**右上方的" **导出"**按钮. 生成报告后,CSV 报告将下载到本地计算机. 该报告包含" **安全性仪表板"中**定义的项目的所有漏洞,因为过滤器不适用于导出功能. + +**注意:**如果您的项目包含成千上万个漏洞,下载可能需要几分钟的时间才能开始. 下载完成之前,请不要关闭页面. + +## Keeping the dashboards up to date[](#keeping-the-dashboards-up-to-date "Permalink") + +安全仪表板在[默认分支](../../project/repository/branches/index.html#default-branch)上显示来自最新安全扫描结果的信息,这意味着每次更新分支时都会执行安全扫描. + +如果不经常更新默认分支,则不经常运行扫描,并且随着发现新漏洞,安全仪表板上的信息可能会过时. + +为确保安全仪表板上的信息得到定期更新,请[配置计划的管道](../../../ci/pipelines/schedules.html)以运行每日安全扫描. 不管默认分支的更新频率如何,这都会更新"安全性"仪表板上显示的信息. + +这样,即使没有代码更改也不会创建报告. + +## Security scans using Auto DevOps[](#security-scans-using-auto-devops "Permalink") + +使用[Auto DevOps 时](../../../topics/autodevops/index.html) ,请使用[特殊的环境变量](../../../topics/autodevops/customize.html#environment-variables)来配置每日安全扫描. + +## Vulnerability list[](#vulnerability-list "Permalink") + +Each dashboard’s vulnerability list contains vulnerabilities from the latest scans that were merged into the default branch. Click any vulnerability in the table to see more information on that vulnerability. To create an issue associated with the vulnerability, click the **创建问题** button. + +[![Create an issue for the vulnerability](img/a9880855e171e225a4b6c73ae1790538.png)](img/standalone_vulnerability_page_v13_1.png) + +创建问题后,漏洞列表将包含该问题的链接和一个图标,其颜色指示该问题的状态(绿色代表未解决的问题,蓝色代表未解决的问题). + +[![Display attached issues](img/f1e26381a4d60fa929a9285e04721656.png)](img/vulnerability_list_table_v13_1.png) \ No newline at end of file diff --git a/docs/058.md b/docs/058.md new file mode 100644 index 0000000000000000000000000000000000000000..faf96043e9c08bee7dd5787f3dc133eb297eff32 --- /dev/null +++ b/docs/058.md @@ -0,0 +1,64 @@ +# Offline environments + +> 原文:[https://docs.gitlab.com/ee/user/application_security/offline_deployments/](https://docs.gitlab.com/ee/user/application_security/offline_deployments/) + +* [Defining offline environments](#defining-offline-environments) +* [Overview](#overview) + * [Container registries and package repositories](#container-registries-and-package-repositories) + * [Interacting with the vulnerabilities](#interacting-with-the-vulnerabilities) + * [Suggested Solutions for vulnerabilities](#suggested-solutions-for-vulnerabilities) + * [Scanner signature and rule updates](#scanner-signature-and-rule-updates) +* [Specific scanner instructions](#specific-scanner-instructions) + +# Offline environments[](#offline-environments "Permalink") + +未连接到互联网时,可以运行大多数的 GitLab 安全扫描程序. + +本文档介绍了如何在脱机环境中操作安全类别(即扫描仪类型). 这些说明还适用于受保护,具有安全策略(例如,防火墙策略)或受其他限制而无法访问整个 Internet 的自我管理安装. GitLab 将这些环境称为*脱机环境* . 其他常用名称包括: + +* 气隙环境 +* 受限的连接环境 +* 局域网(LAN)环境 +* 内联网环境 + +这些环境具有阻止或限制 Internet 访问的物理障碍或安全策略(例如,防火墙). 这些说明是为物理上断开连接的网络而设计的,但在其他用例中也可以遵循这些说明. + +## Defining offline environments[](#defining-offline-environments "Permalink") + +在离线环境中,GitLab 实例可以是一个或多个服务器和服务,它们可以在本地网络上进行通信,但是对 Internet 的访问没有限制或受到非常严格的限制. 假设可以通过本地网络连接访问 GitLab 实例和支持基础结构(例如,私有 Maven 存储库)中的任何内容. 假定来自 Internet 的任何文件都必须通过物理媒体(USB 驱动器,硬盘驱动器,可写 DVD 等)进入. + +## Overview[](#overview "Permalink") + +GitLab 扫描仪通常会连接到互联网,以下载最新的签名,规则和补丁集. 通过使用本地网络上可用的资源,需要一些额外的步骤来配置工具以使其正常运行. + +### Container registries and package repositories[](#container-registries-and-package-repositories "Permalink") + +在较高级别,安全分析器以 Docker 映像的形式提供,并且可以利用各种软件包存储库. 当您在联网的 GitLab 安装上运行作业时,GitLab 会检查 GitLab.com 托管的容器注册表,以检查您是否具有这些 Docker 映像的最新版本,并可能连接到软件包存储库以安装必要的依赖项. + +在离线环境中,必须禁用这些检查,以便不查询 GitLab.com. 由于 GitLab.com 注册表和存储库不可用,因此您必须更新每个扫描仪以引用不同的内部托管注册表,或提供对单个扫描仪图像的访问. + +您还必须确保您的应用可以访问不在 GitLab.com 上托管的常见软件包存储库,例如 npm,yarn 或 Ruby gems. 可以通过临时连接到网络或通过镜像自己的脱机网络中的软件包来获取这些存储库中的软件包. + +### Interacting with the vulnerabilities[](#interacting-with-the-vulnerabilities "Permalink") + +一旦发现漏洞,便可以与其进行交互. 阅读有关如何[与漏洞](../index.html#interacting-with-the-vulnerabilities)进行[交互的](../index.html#interacting-with-the-vulnerabilities)更多信息. + +请注意,在某些情况下,所报告的漏洞提供的元数据可能包含 UI 中公开的外部链接. 在脱机环境中可能无法访问这些链接. + +### Suggested Solutions for vulnerabilities[](#suggested-solutions-for-vulnerabilities "Permalink") + +[建议的解决方案](../index.html#solutions-for-vulnerabilities-auto-remediation)功能(自动修复)可用于"依赖关系扫描"和"容器扫描",但可能无法运行,具体取决于实例的配置. 当我们能够访问托管该依赖项或映像的最新版本的最新注册表服务时,我们只能建议解决方案,这些解决方案通常是已修补的最新版本. + +### Scanner signature and rule updates[](#scanner-signature-and-rule-updates "Permalink") + +连接到 Internet 时,某些扫描仪会参考公共数据库以获取最新的签名集和要检查的规则. 没有连接,这是不可能的. 因此,根据扫描仪的不同,您必须禁用这些自动更新检查,并使用它们随附的数据库并手动更新这些数据库,或者提供对网络中托管的自己的副本的访问权限. + +## Specific scanner instructions[](#specific-scanner-instructions "Permalink") + +每个单独的扫描仪可能与上述步骤略有不同. 您可以在以下每个页面上找到更多信息: + +* [Container scanning offline directions](../container_scanning/index.html#running-container-scanning-in-an-offline-environment) +* [SAST offline directions](../sast/index.html#running-sast-in-an-offline-environment) +* [DAST offline directions](../dast/index.html#running-dast-in-an-offline-environment) +* [License Compliance offline directions](../../compliance/license_compliance/index.html#running-license-compliance-in-an-offline-environment) +* [Dependency Scanning offline directions](../dependency_scanning/index.html#running-dependency-scanning-in-an-offline-environment) \ No newline at end of file diff --git a/docs/059.md b/docs/059.md new file mode 100644 index 0000000000000000000000000000000000000000..1db0f5ce12927d172a21f88e5ec4a140f4b7bf0b --- /dev/null +++ b/docs/059.md @@ -0,0 +1,62 @@ +# Standalone Vulnerability pages + +> 原文:[https://docs.gitlab.com/ee/user/application_security/vulnerabilities/](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/) + +* [Changing vulnerability status](#changing-vulnerability-status) +* [Creating an issue for a vulnerability](#creating-an-issue-for-a-vulnerability) +* [Automatic remediation solutions for vulnerabilities](#automatic-remediation-solutions-for-vulnerabilities) + * [Manually applying a suggested patch](#manually-applying-a-suggested-patch) + +# Standalone Vulnerability pages[](#standalone-vulnerability-pages "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13561) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0. + +[安全仪表板](../security_dashboard/index.html#project-security-dashboard)中的每个安全漏洞都有其自己的独立页面. + +[![Standalone vulnerability page](img/62d2b5c8435d31dff0a7fc689c288e8c.png)](img/standalone_vulnerability_page_v13_1.png) + +在独立漏洞页面上,您可以通过几种不同方式与漏洞进行交互: + +* [变化的脆弱性状态](#changing-vulnerability-status) -您可以将漏洞的状态更改为**检测** , **确认** , **驳回**或**解决** . +* [创建问题](#creating-an-issue-for-a-vulnerability) -创建一个新问题,其标题和说明已预先填充了漏洞报告中的信息. 默认情况下,此类问题是[机密的](../../project/issues/confidential_issues.html) . +* [解决方案](#automatic-remediation-solutions-for-vulnerabilities) -对于某些漏洞,提供了有关如何修复该漏洞的解决方案. + +## Changing vulnerability status[](#changing-vulnerability-status "Permalink") + +您可以使用" **状态"**下拉列表将漏洞的**状态**切换为以下值之一: + +| Status | Description | +| --- | --- | +| Detected | 新发现漏洞的默认状态 | +| Confirmed | 用户已经看到此漏洞并确认它是真实的 | +| Dismissed | 用户已经看到此漏洞并将其消除 | +| Resolved | 该漏洞已修复,不再存在于代码库中 | + +## Creating an issue for a vulnerability[](#creating-an-issue-for-a-vulnerability "Permalink") + +您可以通过选择**创建问题**按钮来**创建**漏洞**问题** . + +这会在漏洞来自的项目中创建一个[机密问题](../../project/issues/confidential_issues.html) ,并使用漏洞报告中的有用信息对其进行预填充. 创建问题后,GitLab 会将您重定向到问题页面,以便您可以编辑,分配或评论问题. + +## Automatic remediation solutions for vulnerabilities[](#automatic-remediation-solutions-for-vulnerabilities "Permalink") + +您可以通过应用 GitLab 为您自动生成的解决方案来修复某些漏洞. GitLab 支持以下扫描仪: + +* [依赖项扫描](../dependency_scanning/index.html) :自动补丁创建仅适用于使用`yarn`管理的 Node.js 项目. +* [Container Scanning](../container_scanning/index.html). + +When an automatic solution is available, the button in the header will show “Resolve with merge request”: + +[![Resolve with Merge Request button](img/e661a6c6931c39f12f5b6833566b8947.png)](img/standalone_vulnerability_page_merge_request_button_v13_1.png) + +选择该按钮将创建带有自动解决方案的合并请求. + +### Manually applying a suggested patch[](#manually-applying-a-suggested-patch "Permalink") + +要手动应用由 GitLab 生成的漏洞补丁,请选择"使用合并请求解决"按钮上的下拉箭头,然后选择"下载要解决的补丁"选项: + +[![Resolve with Merge Request button dropdown](img/2310ec0a03905adc0774d21079604b57.png)](img/standalone_vulnerability_page_merge_request_button_dropdown_v13_1.png) + +这会将按钮文本更改为"下载修补程序以解决". 单击它下载补丁: + +[![Download patch button](img/4e980984ef171e4c624f56ebeb3277c7.png)](img/standalone_vulnerability_page_download_patch_button_v13_1.png) \ No newline at end of file diff --git a/docs/060.md b/docs/060.md new file mode 100644 index 0000000000000000000000000000000000000000..82a0adcc96879fefb2a014f0f771f34ff2cf9ed8 --- /dev/null +++ b/docs/060.md @@ -0,0 +1,388 @@ +# Security scanner integration + +> 原文:[https://docs.gitlab.com/ee/development/integrations/secure.html](https://docs.gitlab.com/ee/development/integrations/secure.html) + +* [Job definition](#job-definition) + * [Name](#name) + * [Image](#image) + * [Script](#script) + * [Stage](#stage) + * [Fail-safe](#fail-safe) + * [Artifacts](#artifacts) + * [Policies](#policies) + * [Policy checking example](#policy-checking-example) +* [Docker image](#docker-image) + * [Image size](#image-size) + * [Image tag](#image-tag) +* [Command line](#command-line) + * [Variables](#variables) + * [SAST and Dependency Scanning](#sast-and-dependency-scanning) + * [Container Scanning](#container-scanning) + * [Configuration files](#configuration-files) + * [Output file](#output-file) + * [Exit code](#exit-code) + * [Logging](#logging) + * [Logging level](#logging-level) + * [common logutil package](#common-logutil-package) +* [Report](#report) + * [Version](#version) + * [Vulnerabilities](#vulnerabilities) + * [ID](#id) + * [Category](#category) + * [Scanner](#scanner) + * [Name, message, and description](#name-message-and-description) + * [Solution](#solution) + * [Identifiers](#identifiers) + * [Location](#location) + * [Dependency Scanning](#dependency-scanning) + * [Container Scanning](#container-scanning-1) + * [SAST](#sast) + * [Tracking and merging vulnerabilities](#tracking-and-merging-vulnerabilities) + * [Severity and confidence](#severity-and-confidence) + * [Remediations](#remediations) + * [Summary](#summary) + * [Fixed vulnerabilities](#fixed-vulnerabilities) + * [Diff](#diff) +* [Limitations](#limitations) + * [Container Scanning](#container-scanning-2) + +# Security scanner integration[](#security-scanner-integration "Permalink") + +将安全扫描程序集成到 GitLab 包括为最终用户提供[CI 作业定义,](../../ci/yaml/README.html#introduction)他们可以将其添加到 CI 配置文件中以扫描其 GitLab 项目. 然后,此 CI 作业应以 GitLab 指定的格式输出其结果. 然后,这些结果将自动显示在 GitLab 中的各个位置,例如管道视图,合并请求小部件和安全仪表板. + +扫描作业通常基于[Docker 映像](https://s0docs0docker0com.icopy.site/) ,该[映像](https://s0docs0docker0com.icopy.site/)包含扫描程序及其在独立环境中的所有依赖性. + +该页面记录了编写实现安全扫描程序的 CI 作业的要求和准则,以及 Docker 映像的要求和准则. + +## Job definition[](#job-definition "Permalink") + +本节描述了要添加到安全扫描器的作业定义文件中的几个重要字段. 有关这些以及其他可用字段的完整文档,请参阅[CI 文档](../../ci/yaml/README.html#image) . + +### Name[](#name "Permalink") + +为了保持一致性,扫描作业应以扫描仪的名字命名(小写). 作业名称是扫描的类型之后后缀: `_dependency_scanning` , `_container_scanning` , `_dast`和`_sast` . 例如,基于" MySec"扫描程序的依赖项扫描作业将被命名为`mysec_dependency_scanning` . + +### Image[](#image "Permalink") + +[`image`](../../ci/yaml/README.html#image)关键字用于指定包含安全扫描器的[Docker 映像](../../ci/docker/using_docker_images.html#what-is-an-image) . + +### Script[](#script "Permalink") + +[`script`](../../ci/yaml/README.html#script)关键字用于指定运行扫描仪的命令. 由于`script`条目不能为空,因此必须将其设置为执行扫描的命令. 无法依靠 Docker 映像的预定义`ENTRYPOINT`和`CMD`来自动执行扫描,而无需传递任何命令. + +在作业定义中不应使用[`before_script`](../../ci/yaml/README.html#before_script-and-after_script) ,因为用户可以在执行扫描之前依靠它来准备其项目. 例如,通常的做法是在执行 SAST 或依赖项扫描之前,使用`before_script`安装特定项目所需的系统库. + +同样,在作业定义中不应使用[`after_script`](../../ci/yaml/README.html#before_script-and-after_script) ,因为它可能会被用户覆盖. + +### Stage[](#stage "Permalink") + +为了保持一致性,扫描作业应尽可能属于`test`阶段. 可以省略[`stage`](../../ci/yaml/README.html#stage)关键字,因为`test`是默认值. + +### Fail-safe[](#fail-safe "Permalink") + +为了与[GitLab Security 范例](https://about.gitlab.com/direction/secure/#security-paradigm)保持一致,扫描作业在失败时不应阻塞管道,因此[`allow_failure`](../../ci/yaml/README.html#allow_failure)参数设置为`true` . + +### Artifacts[](#artifacts "Permalink") + +扫描作业必须使用[`artifacts:reports`](../../ci/pipelines/job_artifacts.html#artifactsreports)关键字声明与其执行的扫描类型相对应的[`artifacts:reports`](../../ci/pipelines/job_artifacts.html#artifactsreports) . 有效报告为: `dependency_scanning` , `container_scanning` , `dast`和`sast` . + +例如,以下是 SAST 作业的定义,该作业生成一个名为`gl-sast-report.json`的文件,并将其作为 SAST 报告上载: + +``` +mysec_sast: + image: registry.gitlab.com/secure/mysec + artifacts: + reports: + sast: gl-sast-report.json +``` + +请注意, `gl-sast-report.json`是示例文件路径,但可以使用任何其他文件名. 有关更多详细信息,请参见["输出文件"部分](#output-file) . 之所以将其作为 SAST 报告处理是因为它是在作业定义中的`reports:sast`键下声明的,而不是因为文件名. + +### Policies[](#policies "Permalink") + +某些 GitLab 工作流程(例如[AutoDevOps](../../topics/autodevops/customize.html#disable-jobs) )定义了变量,以指示应禁用给定的扫描. 您可以通过查找诸如`DEPENDENCY_SCANNING_DISABLED` , `CONTAINER_SCANNING_DISABLED` , `SAST_DISABLED`和`DAST_DISABLED`变量来进行检查. 根据扫描仪类型,如果合适,则应禁用运行自定义扫描仪. + +GitLab 还定义了一个`CI_PROJECT_REPOSITORY_LANGUAGES`变量,该变量提供了存储库中的语言列表. 根据此值,扫描仪可能会做或可能不会做不同的事情. 目前,语言检测依赖于[`linguist`](https://github.com/github/linguist) Ruby gem. 请参阅[GitLab CI / CD 预定义变量](../../ci/variables/predefined_variables.html) . + +#### Policy checking example[](#policy-checking-example "Permalink") + +此示例显示如何跳过自定义的依赖项扫描作业`mysec_dependency_scanning` ,除非项目存储库包含 Java 源代码并且启用了`dependency_scanning`功能: + +``` +mysec_dependency_scanning: + rules: + - if: $DEPENDENCY_SCANNING_DISABLED + when: never + - if: $GITLAB_FEATURES =~ /\bdependency_scanning\b/ + exists: + - '**/*.java' +``` + +任何其他作业策略仅应由用户根据其需求进行配置. 例如,预定义策略不应触发特定分支或特定文件集更改时的扫描作业. + +## Docker image[](#docker-image "Permalink") + +Docker 映像是一个自包含的环境,将扫描仪与其依赖的所有库和工具结合在一起. 将扫描程序打包到 Docker 映像中,无论扫描程序在哪台计算机上运行,​​其依赖关系和配置始终存在. + +### Image size[](#image-size "Permalink") + +根据 CI 基础架构,CI 可能必须在每次作业运行时都获取 Docker 映像. 为了使扫描作业快速运行并避免浪费带宽,Docker 映像应尽可能小. 您的目标应该是 50MB 或更小. 如果无法做到这一点,请尝试使其保持在 1.46 GB 以下,即 CD-ROM 的大小. + +If the scanner requires a fully functional Linux environment, it is recommended to use a [Debian](https://www.debian.org/intro/about) “slim” distribution or [Alpine Linux](https://www.alpinelinux.org/). If possible, it is recommended to build the image from scratch, using the `FROM scratch` instruction, and to compile the scanner with all the libraries it needs. [Multi-stage builds](https://s0docs0docker0com.icopy.site/develop/develop-images/multistage-build/) might also help with keeping the image small. + +为了保持较小的图像大小,请考虑使用[Dive](https://github.com/wagoodman/dive#dive)分析 Docker 图像中的图层,以识别可能来自其他地方的膨胀. + +In some cases, it might be difficult to remove files from an image. When this occurs, consider using [Zstandard](https://github.com/facebook/zstd) to compress files or large directories. Zstandard offers many different compression levels that can decrease the size of your image with very little impact to decompression speed. It may be helpful to automatically decompress any compressed directories as soon as an image launches. You can accomplish this by adding a step to the Docker image’s `/etc/bashrc` or to a specific user’s `$HOME/.bashrc`. Remember to change the entry point to launch a bash login shell if you chose the latter option. + +以下是一些入门的示例: + +* [https://gitlab.com/gitlab-org/security-products/license-management/-/blob/0b976fcffe0a9b8e80587adb076bcdf279c9331c/config/install.sh#L168-170](https://gitlab.com/gitlab-org/security-products/license-management/-/blob/0b976fcffe0a9b8e80587adb076bcdf279c9331c/config/install.sh#L168-170) +* [https://gitlab.com/gitlab-org/security-products/license-management/-/blob/0b976fcffe0a9b8e80587adb076bcdf279c9331c/config/.bashrc#L49](https://gitlab.com/gitlab-org/security-products/license-management/-/blob/0b976fcffe0a9b8e80587adb076bcdf279c9331c/config/.bashrc#L49) + +### Image tag[](#image-tag "Permalink") + +如[Docker Official Images](https://github.com/docker-library/official-images#tags-and-aliases)项目中所述,强烈建议给版本号标签起别名,这使用户可以轻松地引用特定系列的"最新"版本. 另请参阅[Docker 标记:标记和版本化 Docker 映像的最佳实践](https://docs.microsoft.com/en-us/archive/blogs/stevelasker/docker-tagging-best-practices-for-tagging-and-versioning-docker-images) . + +## Command line[](#command-line "Permalink") + +扫描程序是一种命令行工具,它将环境变量作为输入,并生成一个文件,该文件作为报告上载(基于作业定义). 它还会在标准输出和标准错误流上生成文本输出,并以状态码退出. + +### Variables[](#variables "Permalink") + +所有 CI 变量都作为环境变量传递到扫描仪. 扫描的项目由[预定义的 CI 变量](../../ci/variables/README.html)描述. + +#### SAST and Dependency Scanning[](#sast-and-dependency-scanning "Permalink") + +SAST 和依赖项扫描扫描程序必须扫描项目目录中由`CI_PROJECT_DIR`变量指定的文件. + +#### Container Scanning[](#container-scanning "Permalink") + +为了与 GitLab 的官方 Container Scanning 一致,扫描程序必须扫描 Docker 映像,其名称和标记分别由`CI_APPLICATION_REPOSITORY`和`CI_APPLICATION_TAG`给出. + +如果未提供, `CI_APPLICATION_REPOSITORY`应该默认为`$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` ,这是预定义的 CI 变量的组合. `CI_APPLICATION_TAG`应该默认为`CI_COMMIT_SHA` . + +扫描程序应使用变量`DOCKER_USER`和`DOCKER_PASSWORD`登录 Docker 注册表. 如果未定义它们,则扫描程序应使用`CI_REGISTRY_USER`和`CI_REGISTRY_PASSWORD`作为默认值. + +#### Configuration files[](#configuration-files "Permalink") + +尽管扫描程序可以使用`CI_PROJECT_DIR`加载特定的配置文件,但建议将配置公开为环境变量,而不是文件. + +### Output file[](#output-file "Permalink") + +与上载到 GitLab CI / CD 的任何工件一样,由扫描仪生成的安全报告必须写入项目目录中,该目录由`CI_PROJECT_DIR`环境变量指定. + +建议以扫描类型命名输出文件,并使用`gl-`作为前缀. 由于所有安全报告都是 JSON 文件,因此建议使用`.json`作为文件扩展名. 例如,"依赖关系扫描"报告的建议文件名是`gl-dependency-scanning.json` . + +作业定义的[`artifacts:reports`](../../ci/pipelines/job_artifacts.html#artifactsreports)关键字必须与编写"安全性"报告的文件路径一致. 例如,如果 Dependency Scanning 分析器将其报告写入 CI 项目目录,并且此报告文件名为`depscan.json` ,则必须将`artifacts:reports:dependency_scanning`设置为`depscan.json` . + +### Exit code[](#exit-code "Permalink") + +遵循 POSIX 退出代码标准,扫描仪将以 0 表示成功退出,以 1 到 255 之间的任何数字表示退出. 成功还包括发现漏洞的情况. + +使用[Docker-in-Docker 特权模式](../../user/application_security/sast/index.html#requirements)执行扫描作业时,我们保留以下标准退出代码. + +| 协调器退出代码 | Description | +| --- | --- | +| 3 | 没有匹配项,没有兼容的分析仪 | +| 4 | 项目目录为空 | +| 5 | 没有兼容的 Docker 映像 | + +### Logging[](#logging "Permalink") + +扫描程序应记录错误消息和警告,以便用户可以通过查看 CI 扫描作业的日志轻松调查配置错误和集成问题. + +扫描程序可以使用[ANSI 转义码](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors)来着色它们写入 Unix 标准输出和标准错误流的消息的颜色. 我们建议您使用红色报告错误,黄色使用警告,绿色使用通知. 此外,我们建议在错误消息前添加`[ERRO]` ,在警告前添加`[WARN]` ,在通知中添加`[INFO]` . + +#### Logging level[](#logging-level "Permalink") + +如果扫描程序的日志级别低于`SECURE_LOG_LEVEL`变量中设置的级别,则扫描器应筛选出一条日志消息. 例如,当`SECURE_LOG_LEVEL`设置为`error`时,应跳过`info`和`warn`消息. 可接受的值如下,从最高到最低列出: + +* `fatal` +* `error` +* `warn` +* `info` +* `debug` + +建议将`debug`级别用于详细日志记录,这在调试时可能会很有用. `SECURE_LOG_LEVEL`的默认值应设置为`info` . + +#### common logutil package[](#common-logutil-package "Permalink") + +如果您使用[go](https://s0golang0org.icopy.site/)和[common](https://gitlab.com/gitlab-org/security-products/analyzers/common) ,那么建议您使用[logrus](https://github.com/Sirupsen/logrus)和[common 的 logutil 软件包](https://gitlab.com/gitlab-org/security-products/analyzers/common/-/tree/master/logutil)为[logrus](https://github.com/Sirupsen/logrus)配置格式化[程序](https://github.com/Sirupsen/logrus) . 请参阅[logutil README.md](https://gitlab.com/gitlab-org/security-products/analyzers/common/-/tree/master/logutil/README.md) + +## Report[](#report "Permalink") + +该报告是 JSON 文档,其中结合了漏洞和可能的补救措施. + +本文档概述了报告 JSON 格式,以及帮助集成商设置其字段的建议和示例. 该格式在[SAST](../../user/application_security/sast/index.html#reports-json-format) , [依赖项扫描](../../user/application_security/dependency_scanning/index.html#reports-json-format)和[容器扫描](../../user/application_security/container_scanning/index.html#reports-json-format)的文档中进行了广泛描述. + +目前未记录报告 JSON 格式的 DAST 变体. + +### Version[](#version "Permalink") + +This field specifies the version of the report schema you are using. Please reference individual scanner pages for the specific versions to use. + +### Vulnerabilities[](#vulnerabilities "Permalink") + +报告的`vulnerabilities`字段是漏洞对象的数组. + +#### ID[](#id "Permalink") + +`id`字段是漏洞的唯一标识符. 它用于从[修复对象中](#remediations)引用固定的漏洞. 我们建议您生成一个 UUID 并将其用作`id`字段的值. + +#### Category[](#category "Permalink") + +`category`字段的值与报告类型匹配: `dependency_scanning` , `container_scanning` , `sast`和`dast` . + +#### Scanner[](#scanner "Permalink") + +`scanner`字段是一个嵌入人类可读`name`和技术`id` . 该`id`不应与其他集成商提供的其他扫描仪冲突. + +#### Name, message, and description[](#name-message-and-description "Permalink") + +`name`和`message`字段包含该漏洞的简短描述. `description`字段提供更多详细信息. + +`name`字段不受上下文限制,并且不包含有关在何处发现漏洞的`message` ,而`message`可能会重复该位置. + +作为一个直观的示例,此屏幕快照突出显示了在将漏洞作为管道视图的一部分查看时使用这些字段的位置. + +[![Example Vulnerability](img/c7126ad3e897b95ff53bc9300bce4d43.png)](example_vuln.png) + +For instance, a `message` for a vulnerability reported by Dependency Scanning gives information on the vulnerable dependency, which is redundant with the `location` field of the vulnerability. The `name` field is preferred but the `message` field is used when the context/location cannot be removed from the title of the vulnerability. + +为了说明这一点,这是一个由"依赖关系扫描"扫描器报告的示例漏洞对象,并且该`message`重复了`location`字段: + +``` +{ "location": { "dependency": { "package": { "name": "debug" } } }, "name": "Regular Expression Denial of Service", "message": "Regular Expression Denial of Service in debug", "description": "The debug module is vulnerable to regular expression denial of service + when untrusted user input is passed into the `o` formatter. + It takes around 50k characters to block for 2 seconds making this a low severity issue." } +``` + +该`description`可能会解释漏洞的工作方式或提供有关漏洞利用的上下文. 它不应重复漏洞对象的其他字段. 特别是,该`description`不应重复`location` (受影响的对象)或`solution` (如何减轻风险). + +#### Solution[](#solution "Permalink") + +您可以使用`solution`字段来指导用户如何解决已识别的漏洞或减轻风险. 最终用户与此字段进行交互,而 GitLab 会自动处理`remediations`对象. + +#### Identifiers[](#identifiers "Permalink") + +`identifiers`数组描述了检测到的漏洞. 标识符对象的`type`和`value`字段用于判断两个标识符是否相同. 用户界面使用对象的`name`和`url`字段显示标识符. + +建议重新使用 GitLab 扫描仪已经定义的标识符: + +| Identifier | Type | 示例值 | +| --- | --- | --- | +| [CVE](https://cve.mitre.org/cve/) | `cve` | CVE-2019-10086 | +| [CWE](https://cwe.mitre.org/data/index.html) | `cwe` | CWE-1026 | +| [OSVD](https://cve.mitre.org/data/refs/refmap/source-OSVDB.html) | `osvdb` | OSVDB-113928 | +| [USN](https://usn.ubuntu.com/) | `usn` | USN-4234-1 | +| [WASC](http://projects.webappsec.org/Threat-Classification-Reference-Grid) | `wasc` | WASC-19 | +| [RHSA](https://access.redhat.com/errata/#/) | `rhsa` | RHSA-2020:0111 | +| [ELSA](https://linux.oracle.com/security/) | `elsa` | ELSA-2020-0085 | + +上面列出的通用标识符在[公共库](https://gitlab.com/gitlab-org/security-products/analyzers/common)中定义,由 GitLab 维护的分析器共享. 如果需要,您可以[贡献](https://gitlab.com/gitlab-org/security-products/analyzers/common/blob/master/issue/identifier.go)新的通用标识符. 分析人员还可以生成特定于供应商或产品的标识符,这些标识符不属于[公共库](https://gitlab.com/gitlab-org/security-products/analyzers/common) . + +`identifiers`数组的第一项称为主要标识符. 主标识符特别重要,因为当新提交被推送到存储库时,它用于[跟踪漏洞](#tracking-and-merging-vulnerabilities) . 标识符还用于[合并](#tracking-and-merging-vulnerabilities)针对同一提交报告的[重复漏洞](#tracking-and-merging-vulnerabilities) ,但`CWE`和`WASC`除外. + +### Location[](#location "Permalink") + +该`location`指示检测到漏洞的`location` . 位置的格式取决于扫描的类型. + +在内部,GitLab 提取`location`一些属性以生成**位置指纹** ,该**指纹**用于在将新的提交推送到存储库时跟踪漏洞. 用于生成位置指纹的属性还取决于扫描的类型. + +#### Dependency Scanning[](#dependency-scanning "Permalink") + +该`location`依赖关系扫描漏洞是由的`dependency`和`file` . `dependency`对象描述了受影响的`package`和依赖项`version` . `package`嵌入受影响的库/模块的`name` . `file`是声明受影响的依赖项的依赖项文件的路径. + +例如,这是一个影响 npm 软件包[`handlebars`](https://s0www0npmjs0com.icopy.site/package/handlebars)版本`4.0.11`的漏洞的`location`对象: + +``` +{ "file": "client/package.json", "dependency": { "package": { "name": "handlebars" }, "version": "4.0.11" } } +``` + +受影响的依赖项列在`client/package.json` ,该文件由 npm 或 yarn 处理. + +The location fingerprint of a Dependency Scanning vulnerability combines the `file` and the package `name`, so these attributes are mandatory. All other attributes are optional. + +#### Container Scanning[](#container-scanning-1 "Permalink") + +与依赖性扫描相似,容器扫描漏洞的`location`具有`dependency`和`file` . 它还具有一个`operating_system`字段. + +例如,这是一个漏洞对象的`location`对象,该漏洞影响 Debian 软件包`glib2.0`版本`2.50.3-2+deb9u1` `glib2.0` : + +``` +{ "dependency": { "package": { "name": "glib2.0" }, }, "version": "2.50.3-2+deb9u1", "operating_system": "debian:9", "image": "registry.gitlab.com/example/app:latest" } +``` + +在扫描 Docker 镜像`registry.gitlab.com/example/app:latest`时找到受影响的软件包. Docker 映像基于`debian:9` (Debian Stretch). + +容器扫描漏洞的位置指纹结合了`operating_system`和程序包`name` ,因此这些属性是必需的. 该`image`也是必需的. 所有其他属性都是可选的. + +#### SAST[](#sast "Permalink") + +SAST 漏洞的`location`必须具有一个`file`和一个`start_line`字段,分别提供受影响文件的路径和受影响的行号. 它还可能有一个`end_line` ,一个`class`和一个`method` . + +例如,此处是`location`为一个安全漏洞对象发现在线路`41`的`src/main/java/com/gitlab/example/App.java` ,在`generateSecretToken`所述的方法`com.gitlab.security_products.tests.App` Java 类: + +``` +{ "file": "src/main/java/com/gitlab/example/App.java", "start_line": 41, "end_line": 41, "class": "com.gitlab.security_products.tests.App", "method": "generateSecretToken1" } +``` + +SAST 漏洞的位置指纹结合了`file` , `start_line`和`end_line` ,因此这些属性是必需的. 所有其他属性都是可选的. + +### Tracking and merging vulnerabilities[](#tracking-and-merging-vulnerabilities "Permalink") + +用户可以提供有关漏洞的反馈: + +* 如果该漏洞不适用于他们的项目,他们可能会忽略该漏洞 +* 如果存在潜在威胁,他们可能会导致漏洞问题 + +GitLab 跟踪漏洞,以便在将新的 Git 提交推送到存储库时不会丢失用户反馈. 使用以下三个属性的组合来跟踪漏洞: + +* [Report type](#category) +* [Location fingerprint](#location) +* [Primary identifier](#identifiers) + +目前,如果推送新 Git 提交时其位置发生变化,则 GitLab 无法跟踪漏洞,这会导致用户反馈丢失. 例如,如果重命名受影响的文件或受影响的行向下移动,则会丢失用户对 SAST 漏洞的反馈. [问题#7586 中](https://gitlab.com/gitlab-org/gitlab/-/issues/7586)已解决. + +在某些情况下,在同一 CI 管道中执行的多次扫描会导致重复生成,这些重复使用漏洞位置和标识符自动合并. 如果两个漏洞共享相同的[位置指纹](#location)和至少一个[标识符,](#identifiers)则认为这两个漏洞是相同的. 如果两个标识符共享相同的`type`和`id`则它们是相同的. 不考虑使用 CWE 和 WASC 标识符,因为它们描述了漏洞缺陷的类别,但没有描述特定的安全缺陷. + +#### Severity and confidence[](#severity-and-confidence "Permalink") + +`severity`字段描述了漏洞对软件的影响`severity` ,而`confidence`字段描述了漏洞评估的可靠性. 严重性用于对安全性仪表板中的漏洞进行排序. + +严重性的范围从" `Info`到" `Critical` ,但也可以是" `Unknown` . 有效值为: `Unknown` , `Info` , `Low` , `Medium` , `High`或`Critical` + +置信度范围从`Low`到`Confirmed` ,但是如果要忽略此漏洞,也可以是`Unknown` , `Experimental`甚至`Ignore` . 有效值为: `Ignore` , `Unknown` , `Experimental` , `Low` , `Medium` , `High`或`Confirmed` + +`Unknown`值意味着无法获得数据来确定其实际值. 因此,它可能是`high` , `medium`或`low` ,需要进行调查. 我们[提供了](../../user/application_security/sast/analyzers.html#analyzers-data)可用的 SAST 分析仪以及当前可用的数据[的图表](../../user/application_security/sast/analyzers.html#analyzers-data) . + +### Remediations[](#remediations "Permalink") + +报告的" `remediations`字段是补救对象的数组. 每个补救措施都描述了一个补丁,可将其应用来[自动修复](../../user/application_security/#solutions-for-vulnerabilities-auto-remediation)一组漏洞. + +这是包含补救措施的报告示例. + +``` +{ "vulnerabilities": [ { "category": "dependency_scanning", "name": "Regular Expression Denial of Service", "id": "123e4567-e89b-12d3-a456-426655440000", "solution": "Upgrade to new versions.", "scanner": { "id": "gemnasium", "name": "Gemnasium" }, "identifiers": [ { "type": "gemnasium", "name": "Gemnasium-642735a5-1425-428d-8d4e-3c854885a3c9", "value": "642735a5-1425-428d-8d4e-3c854885a3c9" } ] } ], "remediations": [ { "fixes": [ { "id": "123e4567-e89b-12d3-a456-426655440000" } ], "summary": "Upgrade to new version", "diff": "ZGlmZiAtLWdpdCBhL3lhcm4ubG9jayBiL3lhcm4ubG9jawppbmRleCAwZWNjOTJmLi43ZmE0NTU0IDEwMDY0NAotLS0gYS95Y==" } ] } +``` + +#### Summary[](#summary "Permalink") + +`summary`字段概述了如何修复漏洞. 这是必填栏. + +#### Fixed vulnerabilities[](#fixed-vulnerabilities "Permalink") + +`fixes`字段是一组对象,这些对象引用了补救措施所修复的漏洞. `fixes[].id`包含一个固定漏洞的[唯一标识符](#id) . 这是必填栏. + +#### Diff[](#diff "Permalink") + +`diff`字段是 base64 编码的补救代码 diff,与[`git apply`](https://git-scm.com/docs/git-format-patch#_discussion)兼容. 这是必填栏. + +## Limitations[](#limitations "Permalink") + +### Container Scanning[](#container-scanning-2 "Permalink") + +容器扫描当前具有以下限制: + +* 尽管"安全仪表板"可以显示来自多个图像的扫描结果,但是,如果多个漏洞具有相同的指纹,则仅显示该漏洞的第一个实例. 我们正在努力消除这一限制. 您可以关注我们的问题[更改容器扫描的位置指纹](https://gitlab.com/gitlab-org/gitlab/-/issues/215466)问题的进展. +* 不同的扫描程序可能各自报告相同的漏洞,从而导致重复的发现. \ No newline at end of file diff --git a/docs/061.md b/docs/061.md new file mode 100644 index 0000000000000000000000000000000000000000..b22dd5c5f6a7a9c6231cff698010980351dfca8e --- /dev/null +++ b/docs/061.md @@ -0,0 +1,59 @@ +# Badges + +> 原文:[https://docs.gitlab.com/ee/user/project/badges.html](https://docs.gitlab.com/ee/user/project/badges.html) + +* [Project badges](#project-badges) +* [Group badges](#group-badges) +* [Placeholders](#placeholders) +* [API](#api) + +# Badges[](#badges "Permalink") + +在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41174) . + +徽章是呈现有关您的项目的简要信息的统一方法. 它们由一个小图像以及该图像指向的 URL 组成. 徽章的示例可以是[管道状态](../../ci/pipelines/settings.html#pipeline-status-badge) , [测试范围](../../ci/pipelines/settings.html#test-coverage-report-badge)或与项目维护者联系的方式. + +[![Badges on Project overview page](img/0e0e78d03e98ec2ac04952defaba83ff.png)](img/project_overview_badges.png) + +## Project badges[](#project-badges "Permalink") + +维护者或所有者可以将徽章添加到项目中,然后在项目的概述页面上可见. 如果发现必须将相同的徽标添加到多个项目,则可能需要在[组级别](#group-badges)添加它们. + +要将新徽章添加到项目: + +1. 导航到项目的**设置>常规>徽章** . +2. 在"链接"下,输入徽章应指向的 URL,在"徽章图像 URL"下输入应显示的图像的 URL. +3. 通过单击**添加徽章**按钮来提交**徽章** . + +将徽章添加到项目后,您可以在表单下方的列表中看到它. 您可以通过单击旁边的笔图标进行编辑,也可以通过单击垃圾箱图标将其删除. + +与组关联的徽章只能在[组级别](#group-badges)上进行编辑或删除. + +## Group badges[](#group-badges "Permalink") + +可以将徽章添加到组中,然后将在该组下的每个项目的概述页面上看到它们. 在这种情况下,无法在项目级别上对其进行编辑或删除. 如果每个项目需要单独的徽章,请考虑将其添加到[项目级别](#project-badges)或使用[占位符](#placeholders) . + +要将新徽章添加到组: + +1. 导航到组的**"设置">"常规">"徽章"** . +2. 在"链接"下,输入徽章应指向的 URL,在"徽章图像 URL"下输入应显示的图像的 URL. +3. 通过单击**添加徽章**按钮来提交**徽章** . + +将徽章添加到组后,您可以在表格下方的列表中看到它. 您可以通过单击徽章旁边的笔图标来编辑徽章,也可以通过单击垃圾箱图标来删除徽章. + +与项目直接关联的徽章可以在[项目级别](#project-badges)上配置. + +## Placeholders[](#placeholders "Permalink") + +徽章指向的 URL 以及图像 URL 可以包含占位符,在显示徽章时将对其进行评估. 可以使用以下占位符: + +* `%{project_path}` :包含父组的项目的路径 +* `%{project_id}` :与项目关联的数据库 ID +* `%{default_branch}` :为项目存储库配置的默认分支名称 +* `%{commit_sha}` :对项目存储库的默认分支的最新提交的 ID + +**Note:** Placeholders allow badges to expose otherwise-private information, such as the default branch or commit SHA when the project is configured to have a private repository. This is by design, as badges are intended to be used publicly. Avoid using these placeholders if the information is sensitive. + +## API[](#api "Permalink") + +您还可以通过 GitLab API 配置徽章. 与设置一样,在[项目级别](../../api/project_badges.html)和[组级别的](../../api/group_badges.html)徽章端点之间也有所区别. \ No newline at end of file diff --git a/docs/062.md b/docs/062.md new file mode 100644 index 0000000000000000000000000000000000000000..26d06c4d2c86bce8aab8ad72d0d005a8082717fe --- /dev/null +++ b/docs/062.md @@ -0,0 +1,56 @@ +# Bulk editing issues and merge requests at the project level + +> 原文:[https://docs.gitlab.com/ee/user/project/bulk_editing.html](https://docs.gitlab.com/ee/user/project/bulk_editing.html) + +* [Bulk edit issues at the project level](#bulk-edit-issues-at-the-project-level) +* [Bulk edit merge requests at the project level](#bulk-edit-merge-requests-at-the-project-level) + +# Bulk editing issues and merge requests at the project level[](#bulk-editing-issues-and-merge-requests-at-the-project-level "Permalink") + +**注意:**批量编辑问题,史诗和合并请求在**组级别**也可用. 有关更多详细信息,请参阅[在组级别批量编辑问题,史诗和合并请求](../group/bulk_editing/index.html) . + +如果要跨多个问题更新属性或合并请求,则可以通过批量编辑它们,即一起编辑它们来完成. + +[![Bulk editing](img/5b2694c5d35f9fdb42b43bb1f38ec29c.png)](img/bulk-editing_v13_2.png) + +## Bulk edit issues at the project level[](#bulk-edit-issues-at-the-project-level "Permalink") + +**注意:**您需要具有[Reporter 或更高](../permissions.html)级别的权限才能管理问题. + +When bulk editing issues in a project, you can edit the following attributes: + +* 状态(打开/关闭) +* Assignee +* Epic(在[GitLab Premium](https://about.gitlab.com/pricing/) 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/210470) ) +* Milestone +* Labels +* 健康状况(在[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/218395) ) +* Subscriptions + +要同时更新多个项目问题: + +1. 在一个项目中,转到 **问题>列表** . +2. 点击**编辑问题** . 屏幕右侧的侧边栏显示,其中包含可编辑的字段. +3. 选中要编辑的每个问题旁边的复选框. +4. 从边栏中选择适当的字段及其值. +5. Click **全部更新**. + +## Bulk edit merge requests at the project level[](#bulk-edit-merge-requests-at-the-project-level "Permalink") + +**注意:**您需要[开发人员或更高](../permissions.html)级别的权限才能管理合并请求. + +在项目中批量编辑合并请求时,可以编辑以下属性: + +* 状态(打开/关闭) +* Assignee +* Milestone +* Labels +* Subscriptions + +要同时更新多个项目合并请求: + +1. 在一个项目中,转到 **合并请求** . +2. 单击**编辑合并请求** . 屏幕右侧的侧边栏显示,其中包含可编辑的字段. +3. 选中要编辑的每个合并请求旁边的复选框. +4. 从边栏中选择适当的字段及其值. +5. Click **全部更新**. \ No newline at end of file diff --git a/docs/063.md b/docs/063.md new file mode 100644 index 0000000000000000000000000000000000000000..5ddfd6a64ae9534904341b0597a3e3a27b45f3b9 --- /dev/null +++ b/docs/063.md @@ -0,0 +1,151 @@ +# Code Owners + +> 原文:[https://docs.gitlab.com/ee/user/project/code_owners.html](https://docs.gitlab.com/ee/user/project/code_owners.html) + +* [Introduction](#introduction) +* [Why is this useful?](#why-is-this-useful) +* [How to set up Code Owners](#how-to-set-up-code-owners) +* [Approvals by Code Owners](#approvals-by-code-owners) +* [The syntax of Code Owners files](#the-syntax-of-code-owners-files) + +# Code Owners[](#code-owners-starter "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6916) . +* [支持](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53182)在 GitLab Starter 12.1 中添加的[组名称空间](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53182) . +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4418)了用于合并请求批准的代码所有者. + +## Introduction[](#introduction "Permalink") + +在为项目做贡献时,通常很难找出谁应该审查或批准合并请求. 此外,如果您对特定文件或代码块有疑问,可能很难知道从谁那里找到答案. + +GitLab 代码所有者是一项功能,用于定义谁拥有存储库中的特定文件或路径,从而允许其他用户了解谁对每个文件或路径负责. + +## Why is this useful?[](#why-is-this-useful "Permalink") + +代码所有者允许使用版本控制的单个真实文件源,该文件概述了拥有存储库中某些文件或路径的确切 GitLab 用户或组. 可以在合并请求批准过程中利用代码所有者,该过程可以简化为给定合并请求找到合适的审阅者和批准者的过程. + +在大型组织或流行的开源项目中,如果您遇到的问题可能与代码审查或合并请求批准无关,则代码所有者还可以帮助您了解与谁联系. + +## How to set up Code Owners[](#how-to-set-up-code-owners "Permalink") + +您可以使用`CODEOWNERS`文件来指定负责存储库中某些文件的用户或[共享组](members/share_project_with_groups.html) . + +您可以在三个位置选择并添加`CODEOWNERS`文件: + +* 到存储库的根目录 +* 在`.gitlab/`目录中 +* 在`docs/`目录中 + +The `CODEOWNERS` file is scoped to a branch, which means that with the introduction of new files, the person adding the new content can specify themselves as a code owner, all before the new changes get merged to the default branch. + +当一个文件与`CODEOWNERS`文件中的多个条目匹配时,与该文件匹配的上一个模式的用户将显示在给定文件的 Blob 页面上. 例如,您具有以下`CODEOWNERS`文件: + +``` +README.md @user1 + +# This line would also match the file README.md +*.md @user2 +``` + +将显示`README.md`的用户为`@user2` . + +## Approvals by Code Owners[](#approvals-by-code-owners "Permalink") + +将"代码所有者"设置为项目后,可以将其配置为用于合并请求批准: + +* As [merge request eligible approvers](merge_requests/merge_request_approvals.html#code-owners-as-eligible-approvers). +* 根据需要批准[分支机构](protected_branches.html#protected-branches-approval-by-code-owners-premium) . + +**注意** :为了批准合并请求,需要开发人员或更高[权限](../permissions.html) . + +设置后,"代码所有者"将显示在合并请求小部件中: + +[![MR widget - Code Owners](img/6deba2d9890a294d17564cce39fcbaef.png)](img/code_owners_mr_widget_v12_4.png) + +尽管`CODEOWNERS`文件除了可以用于合并请求[批准规则之外](merge_requests/merge_request_approvals.html#approval-rules) ,还可以用作合并请求批准的唯一驱动程序(不使用[批准规则](merge_requests/merge_request_approvals.html#approval-rules) ). 为此,请在上面指定的三个位置之一中创建文件,并将代码所有者设置为[受保护分支的](protected_branches.html#protected-branches-approval-by-code-owners-premium)必需批准者. 使用[代码所有者文件的语法](code_owners.html#the-syntax-of-code-owners-files)来指定实际所有者和精细权限. + +结合使用"代码所有者"和" [受保护的分支机构批准",](protected_branches.html#protected-branches-approval-by-code-owners-premium)将防止在`CODEOWNERS`文件中未指定的任何用户推送对指定文件/路径的更改,即使其角色包含在" **允许推送"**列中. 这允许采用更具包容性的推送策略,因为管理员不必限制开发人员直接将其推送到受保护的分支,而可以将推送限制到某些需要代码所有者审查的文件. + +## The syntax of Code Owners files[](#the-syntax-of-code-owners-files "Permalink") + +可以使用与`.gitignore`文件中使用的相同类型的模式来指定文件,然后使用一个或多个用户的`@username`或电子邮件或应作为文件所有者的一个或多个组的`@name`进行指定. 必须将组添加为[项目的成员](members/index.html) ,否则它们将被忽略. + +从[GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/32432)开始,您现在可以将项目组层次结构中的组或子组指定为潜在的代码所有者. + +例如,考虑给定项目的以下层次结构: + +``` +group >> sub-group >> sub-subgroup >> myproject >> file.md +``` + +以下任何组都可以被指定为代码所有者: + +* `@group` +* `@group/sub-group` +* `@group/sub-group/sub-subgroup` + +此外,使用" **成员"**工具邀请到项目的任何组也将被视为合格的代码所有者. + +定义路径的顺序很重要:与给定路径匹配的最后一个模式将用于查找代码所有者. + +以`#`开头的行表示注释. 需要使用`\#`对其进行转义,以寻址其名称以`#`开头的文件. + +Example `CODEOWNERS` file: + +``` +# This is an example of a code owners file +# lines starting with a `#` will be ignored. + +# app/ @commented-rule + +# We can specify a default match using wildcards: +* @default-codeowner + +# We can also specify "multiple tab or space" separated codeowners: +* @multiple @code @owners + +# Rules defined later in the file take precedence over the rules +# defined before. +# This will match all files for which the file name ends in `.rb` +*.rb @ruby-owner + +# Files with a `#` can still be accessed by escaping the pound sign +\#file_with_pound.rb @owner-file-with-pound + +# Multiple codeowners can be specified, separated by spaces or tabs +# In the following case the CODEOWNERS file from the root of the repo +# has 3 code owners (@multiple @code @owners) +CODEOWNERS @multiple @code @owners + +# Both usernames or email addresses can be used to match +# users. Everything else will be ignored. For example this will +# specify `@legal` and a user with email `janedoe@gitlab.com` as the +# owner for the LICENSE file +LICENSE @legal this_does_not_match janedoe@gitlab.com + +# Group names can be used to match groups and nested groups to specify +# them as owners for a file +README @group @group/with-nested/subgroup + +# Ending a path in a `/` will specify the code owners for every file +# nested in that directory, on any level +/docs/ @all-docs + +# Ending a path in `/*` will specify code owners for every file in +# that directory, but not nested deeper. This will match +# `docs/index.md` but not `docs/projects/index.md` +/docs/* @root-docs + +# This will make a `lib` directory nested anywhere in the repository +# match +lib/ @lib-owner + +# This will only match a `config` directory in the root of the +# repository +/config/ @config-owner + +# If the path contains spaces, these need to be escaped like this: +path\ with\ spaces/ @space-owner +``` \ No newline at end of file diff --git a/docs/064.md b/docs/064.md new file mode 100644 index 0000000000000000000000000000000000000000..737b1641fca87e2c818edd9817b1195b844bc7ea --- /dev/null +++ b/docs/064.md @@ -0,0 +1,10 @@ +# Compliance + +> 原文:[https://docs.gitlab.com/ee/user/compliance/](https://docs.gitlab.com/ee/user/compliance/) + +# Compliance[](#compliance-ultimate "Permalink") + +GitLab 提供的合规性工具可让您随时关注项目的各个方面. 可以使用以下合规工具: + +* [Compliance Dashboard](compliance_dashboard/index.html) :查看组中所有项目的最近合并请求活动. 这使您可以查看合并请求是否被批准以及由谁批准. +* [许可证合规性](license_compliance/index.html) :在项目的依存关系中搜索其许可证. 这样,您可以确定项目依赖项的许可证是否与项目的许可证兼容. \ No newline at end of file diff --git a/docs/065.md b/docs/065.md new file mode 100644 index 0000000000000000000000000000000000000000..2de665c3fec4d8fea1c0d9e65896fe772a34d3d7 --- /dev/null +++ b/docs/065.md @@ -0,0 +1,639 @@ +# License Compliance + +> 原文:[https://docs.gitlab.com/ee/user/compliance/license_compliance/](https://docs.gitlab.com/ee/user/compliance/license_compliance/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Supported languages and package managers](#supported-languages-and-package-managers) + * [Experimental support](#experimental-support) +* [Requirements](#requirements) +* [Configuration](#configuration) + * [Available variables](#available-variables) + * [Installing custom dependencies](#installing-custom-dependencies) + * [Overriding the template](#overriding-the-template) + * [Configuring Maven projects](#configuring-maven-projects) + * [Using private Maven repos](#using-private-maven-repos) + * [Selecting the version of Python](#selecting-the-version-of-python) + * [Custom root certificates for Python](#custom-root-certificates-for-python) + * [Using private Python repos](#using-private-python-repos) + * [Configuring NPM projects](#configuring-npm-projects) + * [Using private NPM registries](#using-private-npm-registries) + * [Custom root certificates for NPM](#custom-root-certificates-for-npm) + * [Configuring Yarn projects](#configuring-yarn-projects) + * [Using private Yarn registries](#using-private-yarn-registries) + * [Custom root certificates for Yarn](#custom-root-certificates-for-yarn) + * [Configuring Bower projects](#configuring-bower-projects) + * [Using private Bower registries](#using-private-bower-registries) + * [Custom root certificates for Bower](#custom-root-certificates-for-bower) + * [Using private Bundler registries](#using-private-bundler-registries) + * [Custom root certificates for Bundler](#custom-root-certificates-for-bundler) + * [Configuring Conan projects](#configuring-conan-projects) + * [Using private Conan registries](#using-private-conan-registries) + * [Custom root certificates for Conan](#custom-root-certificates-for-conan) + * [Configuring Go projects](#configuring-go-projects) + * [Using private Go registries](#using-private-go-registries) + * [Custom root certificates for Go](#custom-root-certificates-for-go) + * [Using private NuGet registries](#using-private-nuget-registries) + * [Custom root certificates for NuGet](#custom-root-certificates-for-nuget) + * [Migration from `license_management` to `license_scanning`](#migration-from-license_management-to-license_scanning) +* [Running License Compliance in an offline environment](#running-license-compliance-in-an-offline-environment) + * [Requirements for offline License Compliance](#requirements-for-offline-license-compliance) + * [Make GitLab License Compliance analyzer images available inside your Docker registry](#make-gitlab-license-compliance-analyzer-images-available-inside-your-docker-registry) + * [Set License Compliance CI job variables to use local License Compliance analyzers](#set-license-compliance-ci-job-variables-to-use-local-license-compliance-analyzers) +* [License list](#license-list) +* [Policies](#policies) + * [Enabling License Approvals within a project](#enabling-license-approvals-within-a-project) +* [Troubleshooting](#troubleshooting) + * [`ERROR -- : asdf: No preset version installed for command`](#error-----asdf-no-preset-version-installed-for-command) + +# License Compliance[](#license-compliance-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5483) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0. + +## Overview[](#overview "Permalink") + +如果您使用的是[GitLab CI / CD](../../../ci/README.html) ,则可以使用许可证合规性在项目依赖项中搜索其许可证. + +您可以通过[将作业包括](#configuration)在现有的`.gitlab-ci.yml`文件中,或者隐式使用[Auto DevOps](../../../topics/autodevops/index.html)提供的[自动](../../../topics/autodevops/index.html) [许可证合规性](../../../topics/autodevops/stages.html#auto-license-compliance-ultimate)来利用[许可证合规性](../../../topics/autodevops/stages.html#auto-license-compliance-ultimate) . + +GitLab 检查"许可证合规性"报告,比较源分支机构和目标分支机构之间的许可证,并在合并请求中显示信息. 拒绝许可证将有清晰可见的`x`红色图标旁边还有哪些需要从你决定新的许可证. 此外,您可以在项目的许可证合规性政策部分中[手动允许或拒绝](#policies)许可证. + +**注意:**如果许可证合规性报告没有可比较的内容,则合并请求区域中将不会显示任何信息. 第一次在`.gitlab-ci.yml`添加`license_scanning`作业时就是这种情况. 连续的合并请求将具有可比性,并且许可证合规性报告将正确显示. + +[![License Compliance Widget](img/89c2a0a388333182ff39563629933a87.png)](img/license_compliance_v13_0.png) + +如果您是项目或组维护者,则可以单击许可证以选择允许或拒绝. + +[![License approval decision](img/28ec7a2f016b77873dfadd5ab59c447b.png)](img/license_compliance_decision_v13_0.png) + +当 GitLab 检测到**拒绝的**许可证时,您可以在[许可证列表中](#license-list)查看它. + +[![License List](img/dc75662feab34ea9fa5cb187a2d77739.png)](img/license_list_v13_0.png) + +您可以从" [策略"](#policies)选项卡查看和修改现有策略. + +[![Edit Policy](img/e545dd77cf453f5a97873da4f0083ebb.png)](img/policies_maintainer_edit_v13_2.png) + +## Use cases[](#use-cases "Permalink") + +It helps you find what licenses your project uses in its dependencies, and decide for each of then whether to allow it or forbid it. For example, your application is using an external (open source) library whose license is incompatible with yours. + +## Supported languages and package managers[](#supported-languages-and-package-managers "Permalink") + +支持以下语言和程序包管理器. + +| Language | 包装经理 | 扫描工具 | +| --- | --- | --- | +| JavaScript | [Bower](https://bower.io/), [npm](https://s0www0npmjs0com.icopy.site/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Go | [Godep](https://github.com/tools/godep), [go mod](https://github.com/golang/go/wiki/Modules) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Java | [Gradle](https://s0gradle0org.icopy.site/), [Maven](https://maven.apache.org/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| .NET | [Nuget](https://www.nuget.org/) (.NET Framework 通过[mono 项目](https://www.mono-project.com/)支持.目前不支持 Windows 特定的依赖项.) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Python | [pip](https://pip.pypa.io/en/stable/) (通过[requirements.txt](https://pip.pypa.io/en/stable/user_guide/#requirements-files)和[Pipfile.lock](https://github.com/pypa/pipfile#pipfilelock)支持 Python.) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Ruby | [gem](https://rubygems.org/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| 的 Objective-C,斯威夫特 | [Carthage](https://github.com/Carthage/Carthage) | [License Finder](https://github.com/pivotal/LicenseFinder) | + +**Note:** + +不支持 Java 8 和 Gradle 1.x 项目. + +### Experimental support[](#experimental-support "Permalink") + +[实验性支持](https://github.com/pivotal/LicenseFinder#experimental-project-types)以下语言和程序包管理器,这意味着报告的许可证可能不完整或不准确. + +| Language | 包装经理 | 扫描工具 | +| --- | --- | --- | +| JavaScript | [yarn](https://yarnpkg.com/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Go | 去获取,gvt,滑行,部门,垃圾,govendor | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Erlang | [rebar](https://www.rebar3.org/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| 的 Objective-C,斯威夫特 | [CocoaPods](https://cocoapods.org/) v0.39 及以下 | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Elixir | [mix](https://s0elixir-lang0org.icopy.site/getting-started/mix-otp/introduction-to-mix.html) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| C++/C | [conan](https://conan.io/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Scala | [sbt](https://www.scala-sbt.org/) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| Rust | [cargo](https://crates.io) | [License Finder](https://github.com/pivotal/LicenseFinder) | +| PHP | [composer](https://s0getcomposer0org.icopy.site/) | [License Finder](https://github.com/pivotal/LicenseFinder) | + +## Requirements[](#requirements "Permalink") + +要运行许可证合规性扫描作业,您需要具有[`docker` executor 的](https://docs.gitlab.com/runner/executors/docker.html) GitLab Runner. + +## Configuration[](#configuration "Permalink") + +对于 GitLab 12.8 及更高版本,要启用许可证合规性,您必须[包括](../../../ci/yaml/README.html#includetemplate)在 GitLab 安装过程中提供的[`License-Scanning.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml) . 对于从 11.9 到 12.7 的较旧版本的 GitLab,您必须[包括](../../../ci/yaml/README.html#includetemplate) [`License-Management.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml) . 对于 11.9 之前的 GitLab 版本,您可以复制和使用该模板中定义的作业. + +**注意:** GitLab 13.0 删除了`License-Management.gitlab-ci.yml`模板. 请改用`License-Scanning.gitlab-ci.yml` . + +将以下内容添加到您的`.gitlab-ci.yml`文件中: + +``` +include: + - template: License-Scanning.gitlab-ci.yml +``` + +The included template will create a `license_scanning` job in your CI/CD pipeline and scan your dependencies to find their licenses. + +**注意:**在 GitLab 12.8 之前, `license_scanning`作业名为`license_management` . GitLab 13.0 删除了`license_management`作业,因此建议您迁移到`license_scanning`作业,并使用新的`License-Scanning.gitlab-ci.yml`模板. + +结果将保存为" [许可证合规性"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportslicense_scanning-ultimate) ,您以后可以下载和分析该[工件](../../../ci/pipelines/job_artifacts.html#artifactsreportslicense_scanning-ultimate) . 由于实施限制,我们始终采用最新的许可证合规性工件. 在后台, [GitLab 许可证合规性 Docker 映像](https://gitlab.com/gitlab-org/security-products/license-management)用于检测语言/框架,进而分析许可证. + +可以使用`.gitlab-ci.yml`的[`variables`](../../../ci/yaml/README.html#variables)参数通过[环境变量](#available-variables)来更改许可合规性设置. + +### Available variables[](#available-variables "Permalink") + +可以使用环境变量来配置许可证合规性. + +| 环境变量 | Required | Description | +| --- | --- | --- | +| `ADDITIONAL_CA_CERT_BUNDLE` | no | 捆绑的可信 CA 证书(当前在 Pip,Pipenv,Maven,Gradle,Yarn 和 NPM 项目中受支持). | +| `ASDF_JAVA_VERSION` | no | 用于扫描的 Java 版本. | +| `ASDF_NODEJS_VERSION` | no | 用于扫描的 Node.js 版本. | +| `ASDF_PYTHON_VERSION` | no | 用于扫描的 Python 版本. | +| `ASDF_RUBY_VERSION` | no | 用于扫描的 Ruby 版本. | +| `GRADLE_CLI_OPTS` | no | gradle 可执行文件的其他参数. 如果未提供,则默认为`--exclude-task=test` . | +| `LICENSE_FINDER_CLI_OPTS` | no | `license_finder`可执行文件的其他参数. 例如,如果您的项目同时在不同的目录中存储了 Golang 和 Ruby 代码,并且您只想扫描 Ruby 代码,则可以更新`.gitlab-ci-yml`模板以指定要扫描的项目目录,例如`LICENSE_FINDER_CLI_OPTS: '--debug --aggregate-paths=. ruby'` `LICENSE_FINDER_CLI_OPTS: '--debug --aggregate-paths=. ruby'` . | +| `LM_JAVA_VERSION` | no | Java 版本. 如果设置为`11` ,则 Maven 和 Gradle 使用 Java 11 而不是 Java 8. | +| `LM_PYTHON_VERSION` | no | Python 版本. 如果设置为`3` ,则将使用 Python 3 而非 Python 2.7 安装依赖项. | +| `MAVEN_CLI_OPTS` | no | mvn 可执行文件的附加参数. 如果未提供,则默认为`-DskipTests` . | +| `PIP_INDEX_URL` | no | Python 软件包索引的基本 URL(默认值: `https://pypi.org/simple/` : `https://pypi.org/simple/` ). | +| `SECURE_ANALYZERS_PREFIX` | no | 设置 Docker 注册表基地址以从中下载分析器. | +| `SETUP_CMD` | no | 依赖项安装的自定义设置(实验性). | + +### Installing custom dependencies[](#installing-custom-dependencies "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.4 中引入. + +`license_management`映像已经嵌入了许多自动检测脚本,语言和软件包. 但是,几乎不可能涵盖所有项目的所有案例. 这就是为什么有时需要安装额外的程序包,或在项目自动设置中进行额外步骤的原因,例如证书的下载和安装. 为此,可以将`LICENSE_MANAGEMENT_SETUP_CMD`环境变量与所需的命令一起传递到容器,以在许可证检测之前运行. + +如果存在,则此变量将覆盖安装应用程序所有软件包所必需的设置步骤(例如:对于具有`Gemfile`的项目,设置步骤可以为`bundle install` ). + +例如: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +variables: + LICENSE_MANAGEMENT_SETUP_CMD: sh my-custom-install-script.sh +``` + +在此示例中, `my-custom-install-script.sh`是项目根目录下的 shell 脚本. + +### Overriding the template[](#overriding-the-template "Permalink") + +**弃用:**从 GitLab 13.0 开始,不再支持[`only`和`except`](../../../ci/yaml/README.html#onlyexcept-basic)的使用. 覆盖模板时,必须使用[`rules`](../../../ci/yaml/README.html#rules) . + +如果要覆盖作业定义(例如,更改诸如`variables`或`dependencies`类的属性),则需要在包含模板之后声明一个`license_scanning`作业,并在其下指定任何其他键. 例如: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + CI_DEBUG_TRACE: "true" +``` + +### Configuring Maven projects[](#configuring-maven-projects "Permalink") + +许可证合规性工具提供了一个`MAVEN_CLI_OPTS`环境变量,该变量可以保存命令行参数,以传递给在`MAVEN_CLI_OPTS`执行的`mvn install`命令. 随意使用它来定制 Maven 执行. 例如: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + MAVEN_CLI_OPTS: --debug +``` + +`mvn install`过所有的运行[构建生命周期](http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html)前阶段的`install` ,包括`test` . 出于许可证扫描的目的,运行单元测试不是直接必要的,并且会浪费时间,因此可以通过将`MAVEN_CLI_OPTS`的默认值`MAVEN_CLI_OPTS`为`-DskipTests`跳过它. 如果要提供自定义的`MAVEN_CLI_OPTS`并同时跳过测试,请不要忘记将`-DskipTests`显式添加到您的选项中. 如果在`mvn install`期间仍然需要运行测试,则将`-DskipTests=false`添加到`MAVEN_CLI_OPTS` . + +#### Using private Maven repos[](#using-private-maven-repos "Permalink") + +如果您有需要登录凭据的私有 Maven 存储库,则可以使用`MAVEN_CLI_OPTS`环境变量. + +阅读更多有关[如何使用私有 Maven 仓库的信息](../../application_security/index.html#using-private-maven-repos) . + +您还可以使用`MAVEN_CLI_OPTS`连接到使用自签名或内部受信任证书的受信任 Maven 存储库. 例如: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + MAVEN_CLI_OPTS: -Dmaven.wagon.http.ssl.allowall=true -Dmaven.wagon.http.ssl.ignore.validity.dates=true -Dmaven.wagon.http.ssl.insecure=true +``` + +或者,您可以使用 Java 密钥存储来验证 TLS 连接. 有关如何生成密钥存储文件的说明,请参阅《 [Maven 通过身份验证的 HTTPS 进行远程存储库访问指南》](http://maven.apache.org/guides/mini/guide-repository-ssl.html) . + +### Selecting the version of Python[](#selecting-the-version-of-python "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0 中[引入](https://gitlab.com/gitlab-org/security-products/license-management/-/merge_requests/36) . +* 在[GitLab 12.2 中](https://gitlab.com/gitlab-org/gitlab/-/issues/12032) ,Python 3.5 成为默认设置. +* 在[GitLab 12.7 中](https://gitlab.com/gitlab-org/security-products/license-management/-/merge_requests/101) ,Python 3.8 成为默认设置. + +默认情况下,许可证合规性使用 Python 3.8 和 pip 19.1\. 如果您的项目需要 Python 2,则可以通过将`LM_PYTHON_VERSION`环境变量设置为`2`来切换到 Python 2.7 和 pip 10.0. + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + LM_PYTHON_VERSION: 2 +``` + +### Custom root certificates for Python[](#custom-root-certificates-for-python "Permalink") + +您可以使用`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables)提供自定义根证书来完成 TLS 验证. + +要绕过 TLS 验证,可以使用自定义[`pip.conf`](https://pip.pypa.io/en/stable/user_guide/#config-file)文件来配置受信任的主机. + +以下`gitlab-ci.yml`文件使用[`before_script`](../../../ci/yaml/README.html#before_script-and-after_script)注入自定义[`pip.conf`](https://pip.pypa.io/en/stable/user_guide/#config-file) : + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + PIP_INDEX_URL: 'https://pypi.example.com/simple/' + before_script: + - mkdir -p ~/.config/pip/ + - cp pip.conf ~/.config/pip/pip.conf +``` + +[`pip.conf`](https://pip.pypa.io/en/stable/reference/pip/)允许您指定[受信任主机](https://pip.pypa.io/en/stable/reference/pip/#cmdoption-trusted-host)的列表: + +``` +[global] +trusted-host = pypi.example.com +``` + +#### Using private Python repos[](#using-private-python-repos "Permalink") + +如果您拥有专用的 Python 存储库,则可以使用`PIP_INDEX_URL` [环境变量](#available-variables)来指定其位置. 也可以提供自定义的`pip.conf`进行[其他配置](#custom-root-certificates-for-python) . + +### Configuring NPM projects[](#configuring-npm-projects "Permalink") + +您可以使用[`.npmrc`](https://s0docs0npmjs0com.icopy.site/configuring-npm/npmrc.html)文件配置 NPM 项目. + +#### Using private NPM registries[](#using-private-npm-registries "Permalink") + +如果您有私有 NPM 注册表,则可以使用[`registry`](https://s0docs0npmjs0com.icopy.site/using-npm/config)设置来指定其位置. + +例如: + +``` +registry = https://npm.example.com +``` + +#### Custom root certificates for NPM[](#custom-root-certificates-for-npm "Permalink") + +您可以使用`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables)提供自定义根证书来完成 TLS 验证. + +要禁用 TLS 验证,您可以提供[`strict-ssl`](https://s0docs0npmjs0com.icopy.site/using-npm/config)设置. + +例如: + +``` +strict-ssl = false +``` + +### Configuring Yarn projects[](#configuring-yarn-projects "Permalink") + +您可以使用[`.yarnrc.yml`](https://yarnpkg.com/configuration/yarnrc)文件配置 Yarn 项目. + +#### Using private Yarn registries[](#using-private-yarn-registries "Permalink") + +如果您有专用的 Yarn 注册表,则可以使用[`npmRegistryServer`](https://yarnpkg.com/configuration/yarnrc#npmRegistryServer)设置来指定其位置. + +例如: + +``` +npmRegistryServer: "https://npm.example.com" +``` + +#### Custom root certificates for Yarn[](#custom-root-certificates-for-yarn "Permalink") + +您可以使用`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables)提供自定义根证书来完成 TLS 验证. + +### Configuring Bower projects[](#configuring-bower-projects "Permalink") + +您可以使用[`.bowerrc`](https://bower.io/docs/config/#bowerrc-specification)文件配置 Bower 项目. + +#### Using private Bower registries[](#using-private-bower-registries "Permalink") + +如果您有专用的 Bower 注册表,则可以使用[`registry`](https://bower.io/docs/config/#bowerrc-specification)设置来指定其位置. + +例如: + +``` +{ + "registry": "https://registry.bower.io" +} +``` + +#### Custom root certificates for Bower[](#custom-root-certificates-for-bower "Permalink") + +您可以使用`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables)或在[`.bowerrc`](https://bower.io/docs/config/#bowerrc-specification)文件中指定`ca`设置来提供自定义根证书来完成 TLS 验证. + +#### Using private Bundler registries[](#using-private-bundler-registries "Permalink") + +如果您有私人的 Bundler 注册表,则可以使用[`source`](https://bundler.io/man/gemfile.5.html#GLOBAL-SOURCES)设置来指定其位置. + +例如: + +``` +source "https://gems.example.com" +``` + +#### Custom root certificates for Bundler[](#custom-root-certificates-for-bundler "Permalink") + +您可以使用`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables)或在作业定义中指定[`BUNDLE_SSL_CA_CERT`](https://bundler.io/v2.0/man/bundle-config.1.html) [环境变量](../../../ci/variables/README.html#custom-environment-variables)来提供自定义根证书来完成 TLS 验证. + +### Configuring Conan projects[](#configuring-conan-projects "Permalink") + +您可以通过将`.conan`目录添加到项目根目录来配置[Conan](https://conan.io/)项目. 项目根用作[`CONAN_USER_HOME`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-user-home) . + +Consult the [Conan](https://docs.conan.io/en/latest/reference/config_files/conan.conf.html#conan-conf) documentation for a list of settings that you can apply. + +`license_scanning`作业在[Debian 10](https://www.debian.org/releases/buster/) Docker 映像中运行. 提供的映像附带了一些构建工具,例如[CMake](https://cmake.org/)和[GCC](https://gcc.gnu.org/) . 但是,默认情况下不支持所有项目类型. 要安装编译依赖关系所需的其他工具,请使用[`before_script`](../../../ci/yaml/README.html#before_script-and-after_script)使用[`apt`](https://wiki.debian.org/PackageManagementTools)软件包管理器安装必要的构建工具. 有关完整列表,请参阅[柯南文档](https://docs.conan.io/en/latest/introduction.html#all-platforms-all-build-systems-and-compilers) . + +默认的[柯南](https://conan.io/)配置将[`CONAN_LOGIN_USERNAME`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-login-username-conan-login-username-remote-name)设置为`ci_user` ,并将[`CONAN_PASSWORD`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-password-conan-password-remote-name)绑定到[`CI_JOB_TOKEN`](../../../ci/variables/predefined_variables.html)以用于正在运行的作业. 如果在`.conan/remotes.json`文件中指定了 GitLab 遥控器,则这允许 Conan 项目从[GitLab 科南存储库中](../../packages/conan_repository/#fetching-conan-package-information-from-the-gitlab-package-registry)获取软件包. + +要覆盖默认凭据,请指定一个[`CONAN_LOGIN_USERNAME_{REMOTE_NAME}`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-login-username-conan-login-username-remote-name)与`.conan/remotes.json`文件中指定的远程名称匹配. + +**注意:**不支持[MSBuild](https://github.com/mono/msbuild#microsoftbuild-msbuild)项目. `license_scanning`映像随[Mono](https://www.mono-project.com/)和[MSBuild 一起提供](https://github.com/mono/msbuild#microsoftbuild-msbuild) . 可能需要其他设置才能生成此项目配置的软件包. + +#### Using private Conan registries[](#using-private-conan-registries "Permalink") + +默认情况下, [柯南](https://conan.io/)使用[柯南](https://conan.io/) `conan-center`遥控器. 例如: + +``` +{ "remotes": [ { "name": "conan-center", "url": "https://conan.bintray.com", "verify_ssl": true } ] } +``` + +要从备用远程获取依赖项,请在`.conan/remotes.json`指定该远程. 例如: + +``` +{ "remotes": [ { "name": "gitlab", "url": "https://gitlab.com/api/v4/packages/conan", "verify_ssl": true } ] } +``` + +如果需要使用凭据进行身份验证,则可以按照[`CONAN_LOGIN_USERNAME`文档中](https://docs.conan.io/en/latest/reference/env_vars.html#conan-login-username-conan-login-username-remote-name)描述的命名约定配置[受保护的变量](../../../ci/variables/README.html#protect-a-custom-variable) . + +#### Custom root certificates for Conan[](#custom-root-certificates-for-conan "Permalink") + +您可以通过将`.conan/cacert.pem`文件添加到项目根目录并将[`CA_CERT_PATH`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-cacert-path)设置为`.conan/cacert.pem`来提供自定义证书. + +如果您指定`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables) ,则此变量的 X.509 证书将安装在 Docker 映像的默认信任库中,并且 Conan 配置为将其用作默认`CA_CERT_PATH` . + +### Configuring Go projects[](#configuring-go-projects "Permalink") + +要配置基于[Go 模块](https://github.com/golang/go/wiki/Modules)的项目,请在`.gitlab-ci.yml`的`license_scanning`作业的[变量](#available-variables)部分中指定[环境变量](https://s0golang0org.icopy.site/pkg/cmd/go/) . + +如果项目已[供应了](https://s0golang0org.icopy.site/pkg/cmd/go/)其模块,则使用`vendor`目录和`mod.sum`文件的组合来检测与 Go 模块依赖关系相关的软件许可证. + +#### Using private Go registries[](#using-private-go-registries "Permalink") + +您可以使用[`GOPRIVATE`](https://s0golang0org.icopy.site/pkg/cmd/go/)和[`GOPROXY`](https://s0golang0org.icopy.site/pkg/cmd/go/)环境变量来控制模块的来源. 另外,您可以使用[`go mod vendor`](https://s0golang0org.icopy.site/ref/mod)来供应项目的模块. + +#### Custom root certificates for Go[](#custom-root-certificates-for-go "Permalink") + +您可以通过导出[`GOFLAGS`](https://s0golang0org.icopy.site/cmd/go/)环境变量来指定[`-insecure`](https://s0golang0org.icopy.site/pkg/cmd/go/internal/get/)标志. 例如: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + GOFLAGS: '-insecure' +``` + +#### Using private NuGet registries[](#using-private-nuget-registries "Permalink") + +如果您拥有私有的 NuGet 注册表,则可以通过将其添加到[`nuget.config`](https://docs.microsoft.com/en-us/nuget/reference/nuget-config-file)文件的[`packageSources`](https://docs.microsoft.com/en-us/nuget/reference/nuget-config-file#package-source-sections)部分中来将其添加为源. + +例如: + +``` + + + + + + + +``` + +#### Custom root certificates for NuGet[](#custom-root-certificates-for-nuget "Permalink") + +您可以使用`ADDITIONAL_CA_CERT_BUNDLE` [环境变量](#available-variables)提供自定义根证书来完成 TLS 验证. + +### Migration from `license_management` to `license_scanning`[](#migration-from-license_management-to-license_scanning "Permalink") + +在 GitLab 12.8 中,引入了`license_management`作业的新名称. 进行此更改是为了提高扫描目的的清晰度,即扫描并收集项目依赖项中存在的许可证类型. GitLab 13.0 放弃了对`license_management`支持. 如果您使用自定义设置来实现"许可证合规性",则需要相应地更新 CI 配置: + +1. 将 CI 模板更改为`License-Scanning.gitlab-ci.yml` . +2. 将作业名称更改为`license_scanning` (如果在`.gitlab-ci.yml`提到了该`.gitlab-ci.yml` ). +3. 将工件名称更改为`license_scanning` ,并将文件名称更改为`gl-license-scanning-report.json` (如果在`.gitlab-ci.yml`中`.gitlab-ci.yml` ). + +例如,以下`.gitlab-ci.yml` : + +``` +include: + - template: License-Management.gitlab-ci.yml + +license_management: + artifacts: + reports: + license_management: gl-license-management-report.json +``` + +应更改为: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + artifacts: + reports: + license_scanning: gl-license-scanning-report.json +``` + +如果您在 GitLab 13.0 或更高版本中使用`license_management`工件,则"许可证合规性"作业将产生以下错误: + +``` +WARNING: Uploading artifacts to coordinator... failed id=:id responseStatus=400 Bad Request status=400 Bad Request token=:sha + +FATAL: invalid_argument +``` + +如果遇到此错误,请按照本节中的说明进行操作. + +## Running License Compliance in an offline environment[](#running-license-compliance-in-an-offline-environment "Permalink") + +对于在通过互联网有限,受限或间歇性访问外部资源的环境中进行自我管理的 GitLab 实例,需要进行一些调整才能成功运行许可合规性工作. 有关更多信息,请参阅[脱机环境](../../application_security/offline_deployments/index.html) . + +### Requirements for offline License Compliance[](#requirements-for-offline-license-compliance "Permalink") + +要在离线环境中使用许可证合规性,您需要: + +* GitLab 亚军与[`docker`或`kubernetes`执行](#requirements) . +* Docker 容器注册表,其中包含许可证合规性[分析器](https://gitlab.com/gitlab-org/security-products/analyzers)映像的本地可用副本. + +**注意:** GitLab Runner 的[默认`pull policy`为`always`](https://docs.gitlab.com/runner/executors/docker.html) ,这意味着即使本地副本可用,Runner 也会尝试从 GitLab 容器注册表中拉取 Docker 映像. 如果您只喜欢使用本地可用的 Docker 映像,则可以在离线环境[`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html) GitLab Runner 的[`pull_policy`设置为`if-not-present`](https://docs.gitlab.com/runner/executors/docker.html) . 但是,如果不在离线环境中,我们建议将拉取策略设置保持为`always` ,因为这样可以在 CI / CD 管道中使用更新的扫描仪. + +### Make GitLab License Compliance analyzer images available inside your Docker registry[](#make-gitlab-license-compliance-analyzer-images-available-inside-your-docker-registry "Permalink") + +要使用所有[支持的语言和程序包管理器进行](#supported-languages-and-package-managers)许可证合规性检查,请将以下默认许可证合规性分析器映像从`registry.gitlab.com`导入到您的离线[本地 Docker 容器注册表中](../../packages/container_registry/index.html) : + +``` +registry.gitlab.com/gitlab-org/security-products/license-management:latest +``` + +将 Docker 映像导入本地脱机 Docker 注册表的过程取决于**您的网络安全策略** . 请咨询您的 IT 员工,以找到可以导入或临时访问外部资源的已接受和批准的流程. 请注意,这些扫描程序会[定期](../../application_security/index.html#maintenance-and-update-of-the-vulnerabilities-database)使用新定义进行[更新](../../application_security/index.html#maintenance-and-update-of-the-vulnerabilities-database) ,因此请考虑您是否能够自己进行定期更新. + +有关将 Docker 映像保存和传输为文件的详细信息,请参阅 Docker 有关[`docker save`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/save/) , [`docker load`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/load/) , [`docker export`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/export/)和[`docker import`](https://s0docs0docker0com.icopy.site/engine/reference/commandline/import/)的文档. + +### Set License Compliance CI job variables to use local License Compliance analyzers[](#set-license-compliance-ci-job-variables-to-use-local-license-compliance-analyzers "Permalink") + +将以下配置添加到您的`.gitlab-ci.yml`文件. 您必须替换`image`以引用本地 Docker 容器注册表中托管的 License Compliance Docker 映像: + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + image: + name: localhost:5000/analyzers/license-management:latest +``` + +现在,"许可证合规性"作业应使用"许可证合规性"分析器的本地副本来扫描您的代码并生成安全报告,而无需访问 Internet. + +连接到[私有 Bower 注册表](#using-private-bower-registries) , [私有 Bundler 注册表](#using-private-bundler-registries) , [私有 Conan 注册表](#using-private-bower-registries) , [私有 Go 注册表](#using-private-go-registries) , [私有 Maven 仓库](#using-private-maven-repos) , [私有 NPM 注册表](#using-private-npm-registries) , [私有 Python 仓库](#using-private-python-repos)和[私有 Yarn 注册表时](#using-private-yarn-registries) ,可能需要附加配置. + +在脱机环境中运行时, [项目策略](#policies)必须与名称完全匹配( [请参阅相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/212388) ). + +## License list[](#license-list "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13582) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.7. + +许可证列表允许您查看项目的许可证以及有关许可证的关键详细信息. + +为了使许可证出现在许可证列表下,必须满足以下要求: + +1. 必须为您的项目[配置](#configuration)许可证合规性 CI 作业. +2. 您的项目必须至少使用一种[受支持的语言和程序包管理器](#supported-languages-and-package-managers) . + +设置完所有内容后,请在项目的侧边栏中导航至" **安全性和合规性">"许可证合规性"** ,您将看到显示的许可证,其中: + +* **名称:**许可证名称. +* **Component:** The components which have this license. +* **违反政策:**许可证的[许可证政策](#policies)标记为**拒绝** . + +[![License List](img/dc75662feab34ea9fa5cb187a2d77739.png)](img/license_list_v13_0.png) + +## Policies[](#policies "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22465) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9. + +通过" **策略"**选项卡,您可以查看项目的软件许可证策略以及每个策略的关联分类. + +可以由项目的维护者配置策略. + +[![Edit Policy](img/e545dd77cf453f5a97873da4f0083ebb.png)](img/policies_maintainer_edit_v13_2.png) [![Add Policy](img/45974f94466502ace734ecc3473a0d58.png)](img/policies_maintainer_add_v13_2.png) + +项目的开发人员可以查看项目中配置的策略. + +[![View Policies](img/793399d61e9710ebd809bd4c52901d68.png)](img/policies_v13_0.png) + +### Enabling License Approvals within a project[](#enabling-license-approvals-within-a-project "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13067) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.3. + +`License-Check`是一个批准规则,您可以启用它来允许批准人,个人或组批准包含`denied`许可证的合并请求. + +您可以启用`License-Check`的两种方式之一: + +* 使用区分大小写的名称`License-Check`创建[项目批准规则](../../project/merge_requests/merge_request_approvals.html#multiple-approval-rules-premium) . +* 在[项目策略部分中为许可合规](#policies)创建批准组. 您必须将此批准组的所需批准数量设置为大于零. 在项目中启用该组后,将为所有合并请求启用批准规则. + +任何代码更改都会导致重置所需的批准. + +许可证报告如下时,需要批准: + +* 包含包含被`denied`的软件许可证的依赖项. +* 在管道执行期间未生成. + +许可证报告如下时,批准是可选的: + +* 不包含任何违反软件许可证的行为. +* Contains only new licenses that are `allowed` or unknown. + +## Troubleshooting[](#troubleshooting "Permalink") + +### `ERROR -- : asdf: No preset version installed for command`[](#error-----asdf-no-preset-version-installed-for-command "Permalink") + +当项目使用的工具的版本与`license_scanning` Docker 映像中可用的预安装工具的版本不匹配时,会发生此错误. `license_scanning`作业使用[asdf-vm](https://asdf-vm.com/)来激活项目所依赖的工具的适当版本. 例如,如果您的项目依赖于特定版本的[Node.js](https://s0nodejs0org.icopy.site/)或任何其他受支持的工具,则可以通过向项目中添加[`.tool-versions`](https://asdf-vm.com/#/core-configuration?id=tool-versions)文件或使用适当的[`ASDF__VERSION`](https://asdf-vm.com/#/core-configuration?id=environment-variables)环境变量来激活所需的版本,从而指定所需的版本.适当的版本. + +例如,以下`.tool-versions`文件将激活[Node.js 的](https://s0nodejs0org.icopy.site/) `12.16.3`版和[Ruby 的](https://www.ruby-lang.org/) `2.6.6`版. + +``` +nodejs 12.16.3 +ruby 2.6.6 +``` + +下一个示例显示如何通过使用项目的`.gitlab-ci.yml`文件中定义的环境变量来激活上述工具的相同版本. + +``` +include: + - template: License-Scanning.gitlab-ci.yml + +license_scanning: + variables: + ASDF_NODEJS_VERSION: '12.16.3' + ASDF_RUBY_VERSION: '2.6.6' +``` + +完整的变量列表可以在[环境变量中](#available-variables)找到. + +要了解在`license_scanning` Docker 映像中预安装了哪些工具,请使用以下命令: + +``` +$ docker run --entrypoint='' registry.gitlab.com/gitlab-org/security-products/analyzers/license-finder:3 /bin/bash -lc 'asdf list' +golang + 1.14 +gradle + 6.3 +java + adopt-openjdk-11.0.7+10 + adopt-openjdk-8u242-b08 +maven + 3.6.3 +nodejs + 10.20.1 + 12.16.3 +php + 7.4.5 +python + 2.7.18 + 3.8.2 +ruby + 2.6.6 +sbt + 1.3.8 +``` + +要与`license_scanning`运行时环境进行交互,请使用以下命令: + +``` +$ docker run -it --entrypoint='' registry.gitlab.com/gitlab-org/security-products/analyzers/license-finder:3 /bin/bash -l +root@6abb70e9f193:~# +``` + +**注意:**当前不支持选择[Mono](https://www.mono-project.com/)或[.NET Core](https://dotnet.microsoft.com/download/dotnet-core)的自定义版本. \ No newline at end of file diff --git a/docs/066.md b/docs/066.md new file mode 100644 index 0000000000000000000000000000000000000000..ba96dbeed9900570b2bc8ea15d8d0eecddd58b9d --- /dev/null +++ b/docs/066.md @@ -0,0 +1,35 @@ +# Compliance Dashboard + +> 原文:[https://docs.gitlab.com/ee/user/compliance/compliance_dashboard/](https://docs.gitlab.com/ee/user/compliance/compliance_dashboard/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Permissions](#permissions) + +# Compliance Dashboard[](#compliance-dashboard-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36524) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.8. + +Compliance Dashboard 通过为组中的所有项目提供高级视图,使您能够查看组的"合并请求"活动. 例如,批准用于合并的代码. + +## Overview[](#overview "Permalink") + +要访问组的合规性仪表板,请导航至 组菜单上的" **安全性和合规性">"合规性** ". + +[![Compliance Dashboard](img/da827bb1926cf748cff537fec6ecc954.png)](img/compliance_dashboard_v13_2.png) + +## Use cases[](#use-cases "Permalink") + +此功能适用于关心团队中项目的合规性状态的人员. + +您可以使用仪表板执行以下操作: + +* 概述每个项目的最新合并请求. +* 查看合并请求是否被批准以及由谁批准. +* 请参阅合并请求作者. +* 查看每个合并请求的最新[CI 管道](../../../ci/pipelines/index.html)结果. + +## Permissions[](#permissions "Permalink") + +* On [GitLab Ultimate](https://about.gitlab.com/pricing/) tier. +* By **Administrators** and **集团所有者**. \ No newline at end of file diff --git a/docs/067.md b/docs/067.md new file mode 100644 index 0000000000000000000000000000000000000000..93ac84760bd5107536c6aea7d0486b275430683b --- /dev/null +++ b/docs/067.md @@ -0,0 +1,130 @@ +# Create a project + +> 原文:[https://docs.gitlab.com/ee/gitlab-basics/create-project.html](https://docs.gitlab.com/ee/gitlab-basics/create-project.html) + +* [Create a project in GitLab](#create-a-project-in-gitlab) + * [Blank projects](#blank-projects) + * [Project templates](#project-templates) + * [Built-in templates](#built-in-templates) + * [Enterprise templates](#enterprise-templates-ultimate) + * [Custom project templates](#custom-project-templates-premium) +* [Push to create a new project](#push-to-create-a-new-project) + +# Create a project[](#create-a-project "Permalink") + +GitLab 中的大多数工作都在一个[Project 中](../user/project/index.html)完成. 文件和代码保存在项目中,并且大多数功能都在项目范围内使用. + +## Create a project in GitLab[](#create-a-project-in-gitlab "Permalink") + +要在 GitLab 中创建项目: + +1. 在信息中心中,点击绿色的**新建项目**按钮或使用导航栏中的加号图标. 这将打开" **新项目"**页面. +2. 在" **新建项目"**页面上,选择是否要: + * 创建一个[空白项目](#blank-projects) . + * 使用可用的[项目模板](#project-templates)之一创建一个项目. + * 如果已在您的 GitLab 实例上启用,则从其他存储库[导入项目](../user/project/import/index.html) . 如果不可用,请与您的 GitLab 管理员联系. + * 运行[用于外部存储库的 CI / CD 管道](../ci/ci_cd_for_external_repos/index.html) . + +**注意:**有关不能用作项目名称的单词列表,请参见[保留的项目和组名称](../user/reserved_names.html) . + +### Blank projects[](#blank-projects "Permalink") + +要在" **新建项目"**页面上创建一个新的空白项目,请执行以下操作: + +1. 在" **空白项目"**选项卡上,提供以下信息: + * **项目名称**在**项目名称**字段中. 您不能使用特殊字符,但可以使用空格,连字符,下划线甚至表情符号. 添加名称时, **Project slug**将自动填充. slug 是 GitLab 实例将用作项目的 URL 路径的东西. 如果您要使用其他子弹,请先输入项目名称,然后再更改子弹. + * **Project slug**字段中项目的路径. 这是 GitLab 实例将使用的项目的 URL 路径. 如果**项目名称**为空白,则当您填写**项目 slug**时,它将自动填充. + * 使用" **项目描述"(可选)**字段,您可以为项目的仪表板输入描述,这将帮助其他人了解您的项目的含义. 尽管不是必需的,但这是个好主意. + * 更改" **可见性级别"**会修改用户的项目[查看和访问权限](../public_access/public_access.html) . + * 选择**使用 README 初始化存储库**选项将创建一个 README 文件,以便 Git 存储库被初始化,具有默认分支并可以被克隆. +2. Click **建立专案**. + +### Project templates[](#project-templates "Permalink") + +项目模板可以使用必要的文件预填充新项目,以使您快速入门. + +有两种类型的项目模板: + +* [内置模板](#built-in-templates) ,来自以下组: + * [`project-templates`](https://gitlab.com/gitlab-org/project-templates) + * [`pages`](https://gitlab.com/pages) +* [自定义项目模板](#custom-project-templates-premium) ,用于由 GitLab 管理员和用户配置的自定义模板. + +#### Built-in templates[](#built-in-templates "Permalink") + +内置模板是项目模板,它们是: + +* 在[`project-templates`](https://gitlab.com/gitlab-org/project-templates)和[`pages`](https://gitlab.com/pages)组中开发和维护. +* 与 GitLab 一起发布. + +要在" **新建项目"**页面上使用内置模板,请执行以下操作: + +1. 在" **从模板创建"**选项卡上,选择" **内置"**选项卡. +2. 从可用的内置模板列表中,单击: + * **预览**按钮以查看模板源本身. + * **使用模板**按钮开始创建项目. +3. 通过填写项目的详细信息来完成创建项目. 该过程与创建[空白项目](#blank-projects)相同. + +##### Enterprise templates[](#enterprise-templates-ultimate "Permalink") + +GitLab 正在开发企业模板,以帮助您根据选定的法规标准简化审核管理. 这些模板会自动导入与每个法规要求相对应的问题. + +要使用企业模板创建新项目,请在" **新建项目"**页面上: + +1. 在" **从模板创建"**选项卡上,选择" **内置"**选项卡. +2. 从可用的内置企业模板列表中,单击: + * **预览**按钮以查看模板源本身. + * **使用模板**按钮开始创建项目. +3. 通过填写项目的详细信息来完成创建项目. 该过程与创建[空白项目](#blank-projects)相同. + +可用的企业模板包括: + +* HIPAA 审核协议模板(在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13756) ) + +**提示:**您可以按照[以下步骤](https://gitlab.com/gitlab-org/project-templates/contributing)改进现有的内置模板或在[`project-templates`](https://gitlab.com/gitlab-org/project-templates)和[`pages`](https://gitlab.com/pages)组中添加新的[`project-templates`](https://gitlab.com/gitlab-org/project-templates) . + +#### Custom project templates[](#custom-project-templates-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6860) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2. + +Creating new projects based on custom project templates is a convenient option for quickly starting projects. + +自定义项目可以在[实例级别](../user/admin_area/custom_project_templates.html)从**实例**选项卡,或在[组级别](../user/group/custom_project_templates.html)从**组**选项卡,在**从模板**标签上的**创建** . + +要在" **新建项目"**页面上使用自定义项目模板: + +1. 在" **从模板创建"**选项卡上,选择" **实例"**选项卡或" **组"**选项卡. +2. 从可用的自定义模板列表中,单击: + * **预览**按钮以查看模板源本身. + * **使用模板**按钮开始创建项目. +3. 通过填写项目的详细信息来完成创建项目. 该过程与创建[空白项目](#blank-projects)相同. + +## Push to create a new project[](#push-to-create-a-new-project "Permalink") + +在 GitLab 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26388) . + +当您在本地创建新的存储库时,无需直接在 GitLab 上手动创建一个新项目然后[在](start-using-git.html#clone-a-repository)本地[克隆该](start-using-git.html#clone-a-repository)存储库,而无需将其直接发送到 GitLab 即可创建新项目. 如果您具有关联的名称空间的访问权,则 GitLab 将在该 GitLab 名称空间下自动创建一个新项目,其可见性默认设置为 Private(您以后可以在[项目的设置中](../public_access/public_access.html#how-to-change-project-visibility)对其进行更改). + +这可以通过使用 SSH 或 HTTPS 来完成: + +``` +## Git push using SSH +git push --set-upstream git@gitlab.example.com:namespace/nonexistent-project.git master + +## Git push using HTTPS +git push --set-upstream https://gitlab.example.com/namespace/nonexistent-project.git master +``` + +推送成功完成后,将显示一条远程消息,指示将遥控器和 URL 设置为新项目的命令: + +``` +remote: +remote: The private project namespace/nonexistent-project was created. +remote: +remote: To configure the remote, run: +remote: git remote add origin https://gitlab.example.com/namespace/nonexistent-project.git +remote: +remote: To view the project, visit: +remote: https://gitlab.example.com/namespace/nonexistent-project +remote: +``` \ No newline at end of file diff --git a/docs/068.md b/docs/068.md new file mode 100644 index 0000000000000000000000000000000000000000..ce5174968e003160fe0c9a64553ed873e0b67cc2 --- /dev/null +++ b/docs/068.md @@ -0,0 +1,131 @@ +# Description templates + +> 原文:[https://docs.gitlab.com/ee/user/project/description_templates.html](https://docs.gitlab.com/ee/user/project/description_templates.html) + +* [Overview](#overview) +* [Use-cases](#use-cases) +* [Creating issue templates](#creating-issue-templates) +* [Creating merge request templates](#creating-merge-request-templates) +* [Using the templates](#using-the-templates) +* [Setting a default template for merge requests and issues](#setting-a-default-template-for-merge-requests-and-issues-starter) +* [Description template example](#description-template-example) + +# Description templates[](#description-templates "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4981) . + +我们都知道,项目开发人员更有可能及时解决提交的问题. + +使用描述模板,您可以为问题定义特定于上下文的模板,并为项目合并请求描述字段,并帮助从问题中过滤掉许多不必要的噪音. + +## Overview[](#overview "Permalink") + +通过使用描述模板,创建新发行或合并请求的用户可以选择描述模板,以帮助他们与其他贡献者进行有效沟通. + +每个 GitLab 项目都可以定义自己的一组描述模板,这些模板将被添加到 GitLab 项目存储库的根目录中. + +描述模板必须用[Markdown](../markdown.html)编写,并存储在项目的存储库中的`.gitlab`目录下. 仅考虑默认分支的模板. + +## Use-cases[](#use-cases "Permalink") + +* 添加一个模板,该模板将用于特定项目的每个问题,并提供说明和指南,要求提供特定于该主题的信息. 例如,如果您有一个用于跟踪新博客文章的项目,则可以要求标题,大纲,作者姓名,作者社交媒体信息等等. +* 在前面的示例之后,您可以为随新博客帖子提交的每个 MR 创建模板,要求提供有关帖子日期,前事数据,图像准则,相关问题的链接,审阅者姓名等信息. +* 您还可以为工作流的不同阶段创建问题并合并请求模板,例如功能建议,功能改进或错误报告. + +## Creating issue templates[](#creating-issue-templates "Permalink") + +在存储库的`.gitlab/issue_templates/`目录内创建一个新的 Markdown( `.md` )文件. 提交并推送到您的默认分支. + +To create a Markdown file: + +1. 单击`master`旁边的`+`按钮,然后单击**New file** . +2. 将问题模板的名称添加到`master`旁边的**File name**文本字段中. 确保单词之间用下划线分隔,并且文件的扩展名为`.md` ,例如`feature_request.md` . +3. 提交并推送到您的默认分支. + +如果您的存储库中没有`.gitlab/issue_templates`目录,则需要创建它. + +要创建`.gitlab/issue_templates`目录: + +1. 单击`master`旁边的`+`按钮,然后选择**New directory** . +2. 将此新目录`.gitlab`并提交到默认分支. +3. 再次单击`master`旁边的`+`按钮,然后选择**New directory** .这次,n +4. 将目录`issue_templates`并提交到默认分支. + +要检查它是否正常工作,请[创建一个新问题,](./issues/managing_issues.html#create-a-new-issue)然后查看是否可以选择描述模板. + +## Creating merge request templates[](#creating-merge-request-templates "Permalink") + +与发布模板类似,在存储库的`.gitlab/merge_request_templates/`目录内创建一个新的 Markdown( `.md` )文件. 提交并推送到您的默认分支. + +## Using the templates[](#using-the-templates "Permalink") + +让我们以创建了`.gitlab/issue_templates/Bug.md`文件`.gitlab/issue_templates/Bug.md` . 在创建或编辑问题时,这将启用`Bug`下拉选项. 选择`Bug` , `Bug.md`模板文件中的内容将被复制到问题描述字段. "重置模板"按钮将放弃您在选择模板后所做的任何更改,并将其恢复为初始状态. + +[![Description templates](img/6224c1a367d53cc7bb5c5536af96ec6e.png)](img/description_templates.png) + +## Setting a default template for merge requests and issues[](#setting-a-default-template-for-merge-requests-and-issues-starter "Permalink") + +版本历史 + +* 此功能是在[描述模板](#overview)之前引入的,可在[GitLab Starter 中使用](https://about.gitlab.com/pricing/) . 可以在项目设置中启用它. +* 问题模板在 GitLab EE 8.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28) . +* 在 GitLab EE 6.9 中[引入](https://gitlab.com/gitlab-org/gitlab/commit/7478ece8b48e80782b5465b96c79f85cc91d391b)了合并请求的模板. + +在项目的**"设置" /"可见性","项目功能","权限"**部分中,应将问题和/或合并请求的可见性设置为"每个人都可以访问"或"只有项目成员",否则模板文本区域将不会显示. 这是默认行为,因此在大多数情况下都可以. + +1. 转到项目的**"设置"** . +2. 单击**合并请求**标题下的**展开** . +3. 填写" **合并请求**的**默认描述模板"**文本区域. +4. Click **Expand** under **默认问题模板**. +5. 填写问题的**默认描述模板**文本区域. 由于 GitLab 合并请求和问题支持[Markdown](../markdown.html) ,因此您可以使用它来格式化标题,列表等. + +[![Default merge request description templates](img/c7ee3e55c50a5f7d0e3faceda16e2dc2.png)](img/description_templates_merge_request_settings.png) + +[![Default issue description templates](img/c9d2a45b5906d81d1118b63a832bbcd4.png)](img/description_templates_issue_settings.png) + +添加描述后,点击**保存更改**以使设置生效. 现在,每次创建新的合并请求或问题时,都将使用您在模板中输入的文本预先填充. + +## Description template example[](#description-template-example "Permalink") + +我们在 GitLab 社区版项目中使用问题和合并请求的描述模板. 请参考[`.gitlab`文件夹](https://gitlab.com/gitlab-org/gitlab/tree/master/.gitlab)中的一些示例. + +**提示:**可以在描述模板中使用[快速操作](quick_actions.html)来快速添加标签,受让人和里程碑. 仅当提交问题或合并请求的用户有权执行相关操作时,才执行快速操作. + +这是错误报告模板的示例: + +``` +Summary + +(Summarize the bug encountered concisely) + +Steps to reproduce + +(How one can reproduce the issue - this is very important) + +Example Project + +(If possible, please create an example project here on GitLab.com that exhibits the problematic behaviour, and link to it here in the bug report) + +(If you are using an older version of GitLab, this will also determine whether the bug has been fixed in a more recent version) + +What is the current bug behavior? + +(What actually happens) + +What is the expected correct behavior? + +(What you should see instead) + +Relevant logs and/or screenshots + +(Paste any relevant logs - please use code blocks (```) to format console output, +logs, and code as it's very hard to read otherwise.) + +Possible fixes + +(If you can, link to the line of code that might be responsible for the problem) + +/label ~bug ~reproduced ~needs-investigation +/cc @project-manager +/assign @qa-tester +``` \ No newline at end of file diff --git a/docs/069.md b/docs/069.md new file mode 100644 index 0000000000000000000000000000000000000000..1f83928d6e543dd9b867c6d3caced9884876d4ce --- /dev/null +++ b/docs/069.md @@ -0,0 +1,119 @@ +# Deploy Keys + +> 原文:[https://docs.gitlab.com/ee/user/project/deploy_keys/](https://docs.gitlab.com/ee/user/project/deploy_keys/) + +* [Key details on deploy keys](#key-details-on-deploy-keys) +* [Deploy Keys Permissions](#deploy-keys-permissions) +* [Differences between deploy keys and deploy tokens](#differences-between-deploy-keys-and-deploy-tokens) +* [How to enable Deploy Keys](#how-to-enable-deploy-keys) + * [Project deploy keys](#project-deploy-keys) + * [Public deploy keys](#public-deploy-keys) +* [Troubleshooting](#troubleshooting) + * [Deploy Key cannot push to a protected branch](#deploy-key-cannot-push-to-a-protected-branch) + +# Deploy Keys[](#deploy-keys "Permalink") + +通过将 SSH 公钥导入到 GitLab 实例,部署密钥允许对一个或多个存储库的只读或读写(如果启用)访问. + +这对于将存储库克隆到持续集成(CI)服务器非常有用. 通过使用部署密钥,您不必设置虚拟用户帐户. + +There are two types of deploy keys: + +* [Project deploy keys](#project-deploy-keys) +* [Public deploy keys](#public-deploy-keys) + +## Key details on deploy keys[](#key-details-on-deploy-keys "Permalink") + +部署密钥使远程机器(VM,物理机等)只需几个步骤即可访问 GitLab 存储库. 如果您希望远程计算机以自动化方式与 GitLab 存储库进行交互,这是一个简单的解决方案. + +缺点是,如果远程计算机被黑客入侵,则您的存储库可能会变得脆弱. 在存储库中启用部署密钥之前,应限制对远程计算机的访问. 遵循的好规则是仅访问受信任的用户,并确保允许的用户在 GitLab 项目中具有[维护者权限或更高权限](../../permissions.html) . + +如果您的组织担心这种安全隐患,则可以使用" [部署令牌"](../deploy_tokens/index.html)作为替代方案,但具有更多的安全控制. + +## Deploy Keys Permissions[](#deploy-keys-permissions "Permalink") + +在项目上启用部署密钥时,可以选择其访问级别: + +* `read-only` :部署密钥可以读取存储库. +* `read-write` :部署密钥可以读取存储库并对其进行写入. + +项目维护者和所有者可以激活和停用部署密钥. 他们还可以添加自己的部署密钥并为该项目启用它们. + +当使用`write-access`部署密钥来推送提交时,GitLab 会检查部署密钥的**创建者**是否有权访问资源. 例如: + +* 当使用部署密钥将提交推送到[受保护的分支时](../protected_branches.html) ,部署密钥的**创建者**必须有权访问该分支. +* 当使用部署密钥来推送触发 CI / CD 管道的提交时,部署密钥的**创建者**必须有权访问 CI / CD 资源(例如受保护的环境,机密变量等). +* 如果部署密钥的**创建者**没有读取项目存储库的权限,则部署密钥*可能*在此过程中遇到错误. + +## Differences between deploy keys and deploy tokens[](#differences-between-deploy-keys-and-deploy-tokens "Permalink") + +部署密钥和[部署令牌](../deploy_tokens/index.html#deploy-tokens)都可以帮助您访问存储库,但是它们之间存在一些显着差异: + +* 部署密钥可以在不相关甚至不属于同一组的项目之间共享. 部署令牌属于项目或[组](../deploy_tokens/index.html#group-deploy-token) . +* 部署密钥是您需要在计算机上生成自己的 SSH 密钥. 部署令牌是由您的 GitLab 实例生成的,仅在创建时提供给用户一次. +* 只要已注册并启用部署密钥,该密钥便有效. 部署令牌可能是时间敏感的,因为您可以通过设置令牌的到期日期来控制令牌的有效性. +* 您不能使用部署密钥登录注册表,也不能对其执行读/写操作,但是[使用部署令牌是可以的](../deploy_tokens/index.html#gitlab-deploy-token) . +* 您需要 SSH 密钥对才能使用部署密钥,但不需要部署令牌. + +## How to enable Deploy Keys[](#how-to-enable-deploy-keys "Permalink") + +### Project deploy keys[](#project-deploy-keys "Permalink") + +[项目维护者和所有者](../../permissions.html#project-members-permissions)可以为项目存储库添加或启用部署密钥: + +1. 导航到项目的**"设置">"存储库"**页面. +2. 展开" **部署密钥"**部分. +3. 为新的部署密钥指定标题,然后粘贴您的公共 SSH 密钥. +4. (可选)检查**写访问允许**允许`read-write`访问. 保留它的`read-only`访问权限. + +有三个项目部署密钥列表: + +* 启用的部署密钥 +* Privately accessible deploy keys +* 公共可访问的部署密钥 + +[![Deploy Keys section](img/86738432aa05c0c68fffb68c00788fa4.png)](img/deploy_keys_v13_0.png) + +添加密钥后,默认情况下将为此项目启用该密钥,它将显示在"已**启用的部署密钥"**选项卡中. + +在"私有**可访问的部署密钥"**选项卡中,您可以启用已导入到其他项目中的私有密钥. 如果您有权访问这些密钥,那是因为您具有以下任一能力: + +* 以前,您自己将密钥上传到了另一个项目中. +* 您是导入密钥的另一个项目的维护者或所有者. + +在可**公开访问的部署密钥**选项卡中,您可以启用[对整个 GitLab 实例可用的](#public-deploy-keys)密钥. + +添加密钥后,您可以对其进行编辑以更新其标题,或者在`read-only`和`read-write`访问之间切换. + +**注意:**如果您为项目启用了私有或公共访问或部署密钥,并且随后将该密钥的访问级别从`read-only`更新为`read-write` ,则更改将仅适用于**当前项目** . + +### Public deploy keys[](#public-deploy-keys "Permalink") + +公共部署密钥允许对 GitLab 实例中的任何存储库进行`read-only`或`read-write`访问. 这对于将存储库集成到安全的共享服务(例如 CI / CD)很有用. + +实例管理员可以添加公共部署密钥: + +1. 转到**管理区域** ( ) **>部署密钥** . +2. 单击**新部署密钥** . + + 确保新密钥具有有意义的标题,因为这是项目维护者和所有者识别要添加的正确公共部署密钥的主要方法. 例如,如果密钥允许访问 SaaS CI / CD 实例,请在密钥名称中使用该服务的名称(如果已使用了所有密钥). + +[![Public Deploy Keys section](img/2d13f3059b88ccaf448646ed61f70d47.png)](img/public_deploy_key_v13_0.png) + +添加密钥后,它将对所有共享系统可用. 项目维护者或更高级别的人员可以[授权公共部署密钥](#project-deploy-keys)开始在项目中使用它. + +**注意:**仅在配置了至少一个公共部署密钥的情况下,Project CI / CD 设置中的" **公共可访问部署密钥"**选项卡才会显示. + +与项目部署密钥相比,公共部署密钥可以提供更高的安全性,因为目标集成系统的管理员是唯一需要知道或配置密钥值的管理员. + +创建公共部署密钥时,请确定是否可以针对非常狭窄的用途(例如仅特定服务)定义它,或者是否需要针对更广泛的用途(例如对所有服务进行完全`read-write`访问)进行定义. + +**警告:**添加公共部署密钥不会立即向其公开任何存储库. 公共部署密钥允许从其他系统进行访问,但是只有项目维护者选择使用它之后,才能访问任何项目. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Deploy Key cannot push to a protected branch[](#deploy-key-cannot-push-to-a-protected-branch "Permalink") + +如果此部署密钥的所有者无权访问[受保护的分支](../protected_branches.html) ,则此部署密钥也将无权访问该分支. 除此之外,在["允许推送"部分中](../protected_branches.html#configuring-protected-branches)选择" **否"**值意味着没有用户**和**使用部署密钥的服务都无法推送到该选定分支. + +有关更多信息,请参考[此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/30769) . \ No newline at end of file diff --git a/docs/070.md b/docs/070.md new file mode 100644 index 0000000000000000000000000000000000000000..60ad7ba10cd31ca8c15c2f50c1722061c1b96cef --- /dev/null +++ b/docs/070.md @@ -0,0 +1,169 @@ +# Deploy Tokens + +> 原文:[https://docs.gitlab.com/ee/user/project/deploy_tokens/](https://docs.gitlab.com/ee/user/project/deploy_tokens/) + +* [Creating a Deploy Token](#creating-a-deploy-token) +* [Deploy token expiration](#deploy-token-expiration) +* [Revoking a deploy token](#revoking-a-deploy-token) +* [Limiting scopes of a deploy token](#limiting-scopes-of-a-deploy-token) +* [Deploy token custom username](#deploy-token-custom-username) +* [Usage](#usage) + * [Git clone a repository](#git-clone-a-repository) + * [Read Container Registry images](#read-container-registry-images) + * [Push Container Registry images](#push-container-registry-images) + * [Read or pull packages](#read-or-pull-packages) + * [Push or upload packages](#push-or-upload-packages) + * [Group Deploy Token](#group-deploy-token) + * [GitLab Deploy Token](#gitlab-deploy-token) + +# Deploy Tokens[](#deploy-tokens "Permalink") + +版本历史 + +* 在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17894) . +* 从 GitLab 12.9 中的**设置>存储库** [移动](https://gitlab.com/gitlab-org/gitlab/-/issues/199370) . +* 在 GitLab 12.10 中[添加了`write_registry`范围](https://gitlab.com/gitlab-org/gitlab/-/issues/22743) . +* 从 GitLab 12.10.1.中的**"设置">" CI / CD"** [移动](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29280) . +* 在 GitLab 13.0 中[添加了软件包注册表范围](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) . + +部署令牌使您无需用户和密码即可下载( `git clone` )或推和拉项目的程序包和容器注册表映像. + +部署令牌只能由[维护者](../../permissions.html)管理. + +如果有密钥对,则可能要改用[部署密钥](../../../ssh/README.html#deploy-keys) . + +## Creating a Deploy Token[](#creating-a-deploy-token "Permalink") + +您可以从项目的设置中创建任意数量的部署令牌. 或者,您也可以创建[组范围的部署令牌](#group-deploy-token) . + +1. 登录到您的 GitLab 帐户. +2. 转到要为其创建"部署令牌"的项目(或组). +3. 去 **设置** > **存储库** . +4. 单击" **部署令牌"**部分上的"扩展". +5. 选择令牌的名称,有效期(可选)和用户名(可选). +6. 选择[所需的范围](#limiting-scopes-of-a-deploy-token) . +7. 单击**创建部署令牌** . +8. 将部署令牌保存在安全的地方. 离开或刷新页面后, **您将无法再次访问它** . + +[![Personal access tokens page](img/90bcd1f29936328bfb5d344868b8bb81.png)](img/deploy_tokens.png) + +## Deploy token expiration[](#deploy-token-expiration "Permalink") + +部署令牌在您定义的日期 UTC 午夜到期. + +## Revoking a deploy token[](#revoking-a-deploy-token "Permalink") + +您可以随时单击"活动的部署令牌"区域下的相应" **撤消"**按钮来撤消任何部署令牌. + +## Limiting scopes of a deploy token[](#limiting-scopes-of-a-deploy-token "Permalink") + +可以使用不同的作用域创建部署令牌,这些作用域允许给定令牌可以执行各种操作. 下表介绍了可用的范围以及引入的 GitLab 版本. + +| Scope | Description | 在 GitLab 版本中引入 | +| --- | --- | --- | +| `read_repository` | 允许通过`git clone`对存储库进行读取访问 | 10.7 | +| `read_registry` | 如果项目是私有的并且需要授权,则允许对[容器注册表](../../packages/container_registry/index.html)图像的读取访问. | 10.7 | +| `write_registry` | Allows write-access (push) to [container registry](../../packages/container_registry/index.html). | 12.10 | +| `read_package_registry` | 允许对包注册表进行读取访问. | 13.0 | +| `write_package_registry` | 允许对程序包注册表的写访问. | 13.0 | + +## Deploy token custom username[](#deploy-token-custom-username "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29639) . + +默认的用户名格式为`gitlab+deploy-token-#{n}` . 某些工具或平台可能不支持此格式,在这种情况下,您可以指定在创建部署令牌时要使用的自定义用户名. + +## Usage[](#usage "Permalink") + +### Git clone a repository[](#git-clone-a-repository "Permalink") + +要使用部署令牌下载存储库,您只需要: + +1. 创建一个以`read_repository`为范围的部署令牌. +2. 记下您的`username`和`token` . +3. `git clone`使用 Deploy Token `git clone`项目: + + ``` + git clone https://:@gitlab.example.com/tanuki/awesome_project.git + ``` + +将``和``替换为正确的值. + +### Read Container Registry images[](#read-container-registry-images "Permalink") + +要读取容器注册表图像,您需要: + +1. 使用`read_registry`作为范围创建部署令牌. +2. 记下您的`username`和`token` . +3. 使用部署令牌登录到 GitLab 的 Container Registry: + +``` +docker login -u -p registry.example.com +``` + +只需将``和``替换为适当的值即可. 然后,您可以简单地从 Container Registry 中提取图像. + +### Push Container Registry images[](#push-container-registry-images "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22743) . + +要推送容器注册表映像,您需要: + +1. 创建一个具有`write_registry`作为范围的部署令牌. +2. 记下您的`username`和`token` . +3. 使用部署令牌登录到 GitLab 的 Container Registry: + + ``` + docker login -u -p registry.example.com + ``` + +只需将``和``替换为适当的值即可. 然后,您可以简单地将图像推送到 Container Registry. + +### Read or pull packages[](#read-or-pull-packages "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) . + +要在 GitLab 软件包注册表中提取软件包,您需要: + +1. 使用`read_package_registry`作为范围创建一个部署令牌. +2. 记下您的`username`和`token` . +3. 对于[您选择](./../../packages/index.html)的[软件包类型,请](./../../packages/index.html)遵循有关部署令牌的身份验证说明. + +### Push or upload packages[](#push-or-upload-packages "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) . + +要在 GitLab 软件包注册表中上传软件包,您需要: + +1. 使用`write_package_registry`作为范围创建部署令牌. +2. 记下您的`username`和`token` . +3. 对于[您选择](./../../packages/index.html)的[软件包类型,请](./../../packages/index.html)遵循有关部署令牌的身份验证说明. + +### Group Deploy Token[](#group-deploy-token "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/21765) . + +在组级别创建的部署令牌可在属于特定组或其子组之一的所有项目中使用. + +有关概述,请参阅" [组部署令牌"](https://youtu.be/8kxTJvaD9ks) . + +要使用组部署令牌: + +1. 为组[创建](#creating-a-deploy-token)一个部署令牌. +2. 与[克隆存储库](#git-clone-a-repository)时使用项目部署令牌的方式相同. + +克隆相关项目的存储库时,应用于组部署令牌的范围(例如`read_repository` )将一致地应用. + +### GitLab Deploy Token[](#gitlab-deploy-token "Permalink") + +在 GitLab 10.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18414) . + +部署令牌是一种特殊情况. 如果用户创建了一个名为`gitlab-deploy-token`的名称,则 Deploy Token 的用户名和令牌将自动作为环境变量暴露给 CI / CD 作业: `CI_DEPLOY_USER`和`CI_DEPLOY_PASSWORD` . + +创建令牌后,可以使用以下变量登录到 Container Registry: + +``` +docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY +``` + +**注意:**目前尚未为组部署令牌实现`gitlab-deploy-token`部署令牌的特殊处理. 为了使部署令牌可用于 CI / CD 作业,必须在项目级别创建它. 有关详细信息,请参[见此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/214014) . \ No newline at end of file diff --git a/docs/071.md b/docs/071.md new file mode 100644 index 0000000000000000000000000000000000000000..31641697c1d4b4e0e5e7a2b8113e2bd7805ebd24 --- /dev/null +++ b/docs/071.md @@ -0,0 +1,35 @@ +# File finder + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/file_finder.html](https://docs.gitlab.com/ee/user/project/repository/file_finder.html) + +* [How it works](#how-it-works) + +# File finder[](#file-finder "Permalink") + +在 GitLab 8.4 中[引入](https://github.com/gitlabhq/gitlabhq/pull/9889) . + +文件查找器功能使您可以使用 GitLab UI 在存储库中搜索文件. + +您可以在项目的" **文件"**部分中找到" **查找文件"**按钮. + +[![Find file button](img/264ee345c8d001f9b7cabf52e10f47bf.png)](img/file_finder_find_button_v12_10.png) + +对于那些喜欢用手指触摸键盘的人,还有一个[快捷按钮](../../shortcuts.html) ,您可以从项目中的*任何地方*调用它. + +在**问题** , **合并请求** , **里程碑**甚至项目设置中,按`t`键启动文件搜索功能. + +开始输入您要搜索的内容,然后观察魔术的发生. 使用向上/向下箭头,您可以向上和向下搜索结果,使用`Esc`可以关闭搜索并返回" **文件"** + +## How it works[](#how-it-works "Permalink") + +文件查找器功能由[模糊过滤器](https://github.com/jeancroy/fuzz-aldrin-plus)库提供支持. + +它通过突出显示来实现模糊搜索,并试图通过识别人们在搜索时使用的模式来提供直观的结果. + +例如,考虑[GitLab FOSS 存储库](https://gitlab.com/gitlab-org/gitlab-foss/tree/master) ,并且我们要打开`app/controllers/admin/deploy_keys_controller.rb`文件. + +使用模糊搜索,我们首先输入使我们更接近文件的字母. + +**提示:**要缩小搜索范围,请在搜索词中包含`/` . + +[![Find file button](img/ead8d62e426d9309f25a82da77770f59.png)](img/file_finder_find_file_v12_10.png) \ No newline at end of file diff --git a/docs/072.md b/docs/072.md new file mode 100644 index 0000000000000000000000000000000000000000..b4506a38023b4150ff3e9bb868c683d5a233602a --- /dev/null +++ b/docs/072.md @@ -0,0 +1,22 @@ +# Project integrations + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/](https://docs.gitlab.com/ee/user/project/integrations/) + +* [Integrations](#integrations) +* [Project webhooks](#project-webhooks) + +# Project integrations[](#project-integrations "Permalink") + +您可以在项目的**设置➔集成**页面下找到可用的集成. 您至少需要对该项目具有[维护者权限](../../permissions.html) . + +## Integrations[](#integrations "Permalink") + +集成使您可以将 GitLab 与其他应用程序集成. 它们有点像插件,因为它们为 GitLab 添加功能提供了很大的自由度. + +[Learn more about integrations.](overview.html) + +## Project webhooks[](#project-webhooks "Permalink") + +通过项目 webhooks,您可以在例如推送新代码或创建新问题时触发 URL. 您可以将 webhook 配置为侦听特定事件,例如推送,问题或合并请求. GitLab 会将带有数据的 POST 请求发送到 webhook URL. + +[Learn more about webhooks.](webhooks.html) \ No newline at end of file diff --git a/docs/073.md b/docs/073.md new file mode 100644 index 0000000000000000000000000000000000000000..0f3891169dc625e1ae0ca8354fcec3195bce9c72 --- /dev/null +++ b/docs/073.md @@ -0,0 +1,112 @@ +# Integrations + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/overview.html](https://docs.gitlab.com/ee/user/project/integrations/overview.html) + +* [Accessing integrations](#accessing-integrations) +* [Integrations listing](#integrations-listing) +* [Push hooks limit](#push-hooks-limit) +* [Service templates](#service-templates) +* [Troubleshooting integrations](#troubleshooting-integrations) + * [Uninitialized repositories](#uninitialized-repositories) +* [Contributing to integrations](#contributing-to-integrations) + +# Integrations[](#integrations "Permalink") + +集成使您可以将 GitLab 与其他应用程序集成. 它们有点像插件,因为它们为 GitLab 添加功能提供了很大的自由度. + +## Accessing integrations[](#accessing-integrations "Permalink") + +您可以在项目的**设置➔集成**页面下找到可用的集成. + +有 20 多个要集成的集成. 单击您要配置的一个. + +[![Integrations list](img/da1fdf492cc3f883353bb1997795a4a5.png)](img/project_services.png) + +## Integrations listing[](#integrations-listing "Permalink") + +单击服务链接以查看更多的配置说明和详细信息. + +| Service | Description | 服务挂钩 | +| --- | --- | --- | +| Asana | Asana-无需电子邮件的团队合作 | No | +| Assembla | 项目管理软件(源提交端点) | No | +| [Atlassian Bamboo CI](bamboo.html) | 持续集成和构建服务器 | Yes | +| Buildkite | 持续集成和部署 | Yes | +| [Bugzilla](bugzilla.html) | Bugzilla 问题追踪器 | No | +| Campfire | 基于网络的简单实时群聊 | No | +| [Confluence](../../../api/services.html#confluence-service) | 将指向内部 Wiki 的链接替换为指向 Confluence Cloud Workspace 的链接 | No | +| 自定义问题跟踪器 | 自定义问题跟踪器 | No | +| [Discord Notifications](discord_notifications.html) | 在 Discord 中接收事件通知 | No | +| CI 无人机 | Go 编写的基于 Docker 的持续集成平台 | Yes | +| [Emails on push](emails_on_push.html) | 通过电子邮件将每次推送的提交和差异发送到收件人列表 | No | +| 外部维基 | 将指向内部 Wiki 的链接替换为指向外部 Wiki 的链接 | No | +| Flowdock | Flowdock 是面向技术团队的协作网络应用程序 | No | +| [Generic alerts](generic_alerts.html) | 从任何来源接收有关 GitLab 的警报 | No | +| [GitHub](github.html) | 发送管道通知到 GitHub | No | +| [Hangouts Chat](hangouts_chat.html) | 在 Google 环聊中接收事件通知 | No | +| [HipChat](hipchat.html) | 私人群聊和即时消息 | No | +| [Irker (IRC gateway)](irker.html) | 通过 Irker 网关在更新时将 IRC 消息发送到收件人列表 | No | +| [Jira](jira.html) | 吉拉问题追踪器 | No | +| [Jenkins](../../../integration/jenkins.html) | 可扩展的开源持续集成服务器 | Yes | +| JetBrains TeamCity CI | 持续集成和构建服务器 | Yes | +| [Mattermost slash commands](mattermost_slash_commands.html) | 最重要的聊天和 ChatOps 斜杠命令 | No | +| [Mattermost Notifications](mattermost.html) | 在 Mattermost 接收事件通知 | No | +| [Microsoft teams](microsoft_teams.html) | 使用 Office 365 连接器接收有关在 GitLab 上进入 Microsoft Teams 房间的操作的通知 | No | +| Packagist | 在主要 Composer 存储库 Packagist 上更新项目 | Yes | +| 管道电子邮件 | 通过电子邮件将管道状态发送给收件人列表 | No | +| [Slack Notifications](slack.html) | 将 GitLab 事件(例如,已创建问题)作为通知发送到 Slack | No | +| [Slack slash commands](slack_slash_commands.html) | 在 Slack 中使用斜杠命令控制 GitLab | No | +| [GitLab Slack application](gitlab_slack_application.html) | 使用 Slack 的官方应用程序 | No | +| PivotalTracker | 项目管理软件(源提交端点) | No | +| [Prometheus](prometheus.html) | 监控已部署应用程序的性能 | No | +| Pushover | 通过 Pushover,可以轻松在 Android 设备,iPhone,iPad 和台式机上获取实时通知 | No | +| [Redmine](redmine.html) | Redmine 问题追踪器 | No | +| [Unify Circuit](unify_circuit.html) | 在统一电路中接收事件通知 | No | +| [Webex Teams](webex_teams.html) | 在 Webex Teams 中接收事件通知 | No | +| [YouTrack](youtrack.html) | YouTrack 问题追踪器 | No | + +## Push hooks limit[](#push-hooks-limit "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17874) . + +如果单个推送包含对三个以上分支或标签的更改,则`push_hooks`和`tag_push_hooks`事件支持的服务将不会执行. + +可以通过[`push_event_hooks_limit`应用程序设置](../../../api/settings.html#list-of-settings-that-can-be-accessed-via-api-calls)来更改支持的分支或标记的数量. + +## Service templates[](#service-templates "Permalink") + +服务模板是为实例上所有新项目之间的集成设置预定义值的方法. + +[在本文档中](services_templates.html)阅读有关[服务模板的](services_templates.html)更多信息. + +## Troubleshooting integrations[](#troubleshooting-integrations "Permalink") + +某些集成使用服务挂钩来与外部应用程序集成. 要确认哪些使用服务挂钩,请参见上面[列出](#integrations-listing)的[集成](#integrations-listing) . GitLab 存储最近 2 天内发出的服务挂钩请求的详细信息. 要查看请求的详细信息,请转到该集成的配置页面. + +**最近发送**部分列出了最近 2 天内提出的每个请求的详细信息: + +* HTTP 状态代码(绿色表示 200-299 代码,红色表示其他代码, `internal error`表示传送失败) +* 触发事件 +* 请求发送到的 URL +* 请求经过的时间 +* 提出请求的相对时间 + +要查看有关请求执行的更多信息,请单击相应的**查看详细信息**链接. 在详细信息页面上,您可以看到 GitLab 发送和接收的请求标头和正文. + +要使用相同的数据重复发送,请点击**重新发送请求** . + +[![Recent deliveries](img/78dac22706dcca5ce3855d23987289ea.png)](img/webhook_logs.png) + +### Uninitialized repositories[](#uninitialized-repositories "Permalink") + +某些集成失败,并显示错误" `Test Failed. Save Anyway` 尝试在未初始化的存储库上设置它们时,仍然要`Test Failed. Save Anyway` . 某些集成使用推送数据来构建测试有效负载,并且当项目中尚无推送事件时,就会发生此错误. + +要解决此错误,请通过将测试文件推送到项目来初始化存储库,然后再次设置集成. + +## Contributing to integrations[](#contributing-to-integrations "Permalink") + +因为 GitLab 是开源的,所以我们可以附带所有插件的代码和测试. 这使社区可以使插件保持最新状态,以便它们始终在较新的 GitLab 版本中运行. + +有关可用集成的概述,请参见[project_services 源目录](https://gitlab.com/gitlab-org/gitlab/tree/master/app/models/project_services) . + +欢迎捐款! \ No newline at end of file diff --git a/docs/074.md b/docs/074.md new file mode 100644 index 0000000000000000000000000000000000000000..0d206a7579bb21fd94bdca4c71ed23c46b3d1129 --- /dev/null +++ b/docs/074.md @@ -0,0 +1,50 @@ +# Atlassian Bamboo CI Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/bamboo.html](https://docs.gitlab.com/ee/user/project/integrations/bamboo.html) + +* [Setup](#setup) + * [Complete these steps in Bamboo](#complete-these-steps-in-bamboo) + * [Complete these steps in GitLab](#complete-these-steps-in-gitlab) +* [Troubleshooting](#troubleshooting) + +# Atlassian Bamboo CI Service[](#atlassian-bamboo-ci-service "Permalink") + +GitLab 提供与 Atlassian Bamboo 的集成,以实现持续集成. 配置后,推送到项目将自动触发 Bamboo 的构建. 合并请求还将显示 CI 状态,显示构建是挂起,失败还是成功完成. 它还提供了指向 Bamboo 构建页面的链接,以获取更多信息. + +在接受 Webhook 和提交数据方面,Bamboo 并没有提供与传统构建系统相同的功能. 在 GitLab 集成之前,需要在 Bamboo 构建计划中进行一些配置. + +## Setup[](#setup "Permalink") + +### Complete these steps in Bamboo[](#complete-these-steps-in-bamboo "Permalink") + +1. 导航到 Bamboo 建设计划,然后从"操作"下拉列表中选择"配置计划". +2. 选择"触发器"标签. +3. 点击"添加触发器". +4. 输入描述,例如" GitLab 触发器" +5. 选择"提交更改后,存储库将触发构建" +6. 选中一个或多个存储库复选框 +7. 在"触发 IP 地址"框中输入 GitLab IP 地址. 这是允许触发 Bamboo 生成的 IP 地址的列表. +8. 保存触发器. +9. 在左窗格中,选择一个构建阶段. 如果您有多个构建阶段,则要选择包含 Git 签出任务的最后一个阶段. +10. Select the ‘Miscellaneous’ tab. +11. 在"模式匹配标签"下,将`${bamboo.repository.revision.number}`放在"标签"框中. +12. Save + +Bamboo 现在准备接受来自 GitLab 的触发器. 接下来,在 GitLab 中设置 Bamboo 服务. + +### Complete these steps in GitLab[](#complete-these-steps-in-gitlab "Permalink") + +1. 导航到要配置为触发构建的项目. +2. 导航到" [集成"页面](overview.html#accessing-integrations) +3. 点击" Atlassian Bamboo CI" +4. 确保启用了**活动**切换. +5. 输入 Bamboo 服务器的基本 URL. `https://bamboo.example.com` +6. Enter the build key from your Bamboo build plan. 输入 Bamboo 建造计划中的建造钥匙. Build keys are typically made up from the Project Key and Plan Key that are set on project/plan creation and separated with a dash ( `-` ), for example **PROJ-PLAN** . 构建密钥通常由在项目/计划创建时设置的项目密钥和计划密钥组成,并用破折号( `-` )分隔,例如**PROJ-PLAN** . This is a short, all uppercase identifier that is unique. 这是一个简短的全大写标识符,是唯一的. When viewing a plan within Bamboo, the build key is also shown in the browser URL, for example `https://bamboo.example.com/browse/PROJ-PLAN` . 在 Bamboo 内查看计划时,构建密钥也会显示在浏览器 URL 中,例如`https://bamboo.example.com/browse/PROJ-PLAN` . +7. 如有必要,请输入有权触发构建计划的 Bamboo 用户的用户名和密码. 如果不需要身份验证,请将这些字段留空. +8. 保存或选择单击"测试设置". 请注意,"测试设置"实际上会触发 Bamboo 的构建. + +## Troubleshooting[](#troubleshooting "Permalink") + +如果未触发构建,请确保在 Bamboo 的"触发 IP 地址"下输入了正确的 GitLab IP 地址. 还检查[服务挂钩日志中](overview.html#troubleshooting-integrations)是否存在请求失败. + +**注意:**从 GitLab 8.14.0 开始,构建会在推送事件中触发. \ No newline at end of file diff --git a/docs/075.md b/docs/075.md new file mode 100644 index 0000000000000000000000000000000000000000..eeff9e052870787d8217cd2ba62503b9f048608e --- /dev/null +++ b/docs/075.md @@ -0,0 +1,33 @@ +# Bugzilla Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/bugzilla.html](https://docs.gitlab.com/ee/user/project/integrations/bugzilla.html) + +* [Referencing issues in Bugzilla](#referencing-issues-in-bugzilla) +* [Troubleshooting](#troubleshooting) + +# Bugzilla Service[](#bugzilla-service "Permalink") + +导航到[Integrations 页面](overview.html#accessing-integrations) ,选择**Bugzilla**服务,然后按照下表中的说明填写所需的详细信息. + +| Field | Description | +| --- | --- | +| `project_url` | The URL to the project in Bugzilla which is being linked to this GitLab project. Note that the `project_url` requires PRODUCT_NAME to be updated with the product/project name in Bugzilla. | +| `issues_url` | 链接到此 GitLab 项目的 Bugzilla 项目中问题的 URL. 请注意, `issues_url`在 URL 中需要`:id` . GitLab 使用此 ID 作为占位符来替换问题编号. | +| `new_issue_url` | 这是在 Bugzilla 中为与此 GitLab 项目链接的项目创建新问题的 URL. 请注意,在`new_issue_url`中, `new_issue_url`要求使用产品/项目名称更新 PRODUCT_NAME. | + +配置并启用 Bugzilla 后,您将在 GitLab 项目页面上看到 Bugzilla 链接,该链接将您带到相应的 Bugzilla 项目. + +## Referencing issues in Bugzilla[](#referencing-issues-in-bugzilla "Permalink") + +Bugzilla 中的问题可以通过两种替代方式进行引用: + +* `#` ,其中``是数字(示例`#143` ). +* `-` ,其中``以大写字母开头,然后是大写字母,数字或下划线,并且``是数字(示例`API_32-143` ). + +如果您同时启用了内部和外部问题跟踪器,我们建议使用更长的格式. 如果您使用较短的格式,并且内部问题跟踪器中存在具有相同 ID 的问题,则内部问题将被链接. + +请注意, ``部分将被忽略,链接始终指向`issues_url`指定的地址. + +## Troubleshooting[](#troubleshooting "Permalink") + +要查看最近的服务挂钩交付,请检查[服务挂钩日志](overview.html#troubleshooting-integrations) . \ No newline at end of file diff --git a/docs/076.md b/docs/076.md new file mode 100644 index 0000000000000000000000000000000000000000..484102c4a66a9848401ada02419d0a6609b66191 --- /dev/null +++ b/docs/076.md @@ -0,0 +1,33 @@ +# Custom Issue Tracker service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/custom_issue_tracker.html](https://docs.gitlab.com/ee/user/project/integrations/custom_issue_tracker.html) + +* [Referencing issues](#referencing-issues) + +# Custom Issue Tracker service[](#custom-issue-tracker-service "Permalink") + +To enable the Custom Issue Tracker integration in a project: + +1. 去 **设置>集成** . +2. Click **自定义问题跟踪器** +3. 填写跟踪器的详细信息,例如标题,描述和 URL. 您以后也可以编辑这些字段. + + 这些是一些必填字段: + + | Field | Description | + | --- | --- | + | **项目网址** | 自定义问题跟踪器中项目的 URL. | + | **问题网址** | 问题跟踪器项目中与该 GitLab 项目链接的问题的 URL. 请注意, `issues_url`在 URL 中需要`:id` . GitLab 使用此 ID 作为占位符来替换问题编号. 例如, `https://customissuetracker.com/project-name/:id` . | + | **新发行网址** | 目前未使用. 将在以后的版本中进行更改. | + +4. Click **测试设置并保存更改**. + +配置并启用"自定义问题跟踪器"服务后,您将在 GitLab 项目页面上看到一个链接,该链接将您带至该自定义问题跟踪器. + +## Referencing issues[](#referencing-issues "Permalink") + +用`-` (例如`PROJECT-143` )引用问题,其中``可以是 CAPS 中的任何字符串,而``是自定义集成的目标项目中使用的数字. + +``是一个占位符,用于区分使用`#`引用的 GitLab 问题. 例如,您可以使用项目名称或项目密钥来替换它. + +构建超链接时, ``部分将被忽略,并且链接始终指向`issues_url`指定的地址,因此在上面的示例中, `PROJECT-143`将引用`https://customissuetracker.com/project-name/143` . \ No newline at end of file diff --git a/docs/077.md b/docs/077.md new file mode 100644 index 0000000000000000000000000000000000000000..3537af1bfd6b22996d37c1d2e76c0136809c1121 --- /dev/null +++ b/docs/077.md @@ -0,0 +1,36 @@ +# Discord Notifications service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/discord_notifications.html](https://docs.gitlab.com/ee/user/project/integrations/discord_notifications.html) + +* [Create webhook](#create-webhook) +* [Configure created webhook in GitLab](#configure-created-webhook-in-gitlab) + +# Discord Notifications service[](#discord-notifications-service "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22684) . + +Discord Notifications 服务将事件通知从 GitLab 发送到创建 Webhook 的通道. + +要将 GitLab 事件通知发送到 Discord 频道,请在 Discord 中创建一个 Webhook,然后在 GitLab 中对其进行配置. + +## Create webhook[](#create-webhook "Permalink") + +1. 打开您要接收 GitLab 事件通知的 Discord 频道. +2. 在频道菜单中,选择**编辑频道** . +3. 单击**Webhooks**菜单项. +4. 单击**创建 Webhook**按钮,然后填写将发布消息的机器人的名称. (可选)编辑头像. +5. 记下" **WEBHOOK URL"**字段中的**URL** . +6. 单击**保存**按钮. + +## Configure created webhook in GitLab[](#configure-created-webhook-in-gitlab "Permalink") + +使用在 Discord 频道中创建的 webhook URL,可以在 GitLab 中设置 Discord Notifications 服务. + +1. 导航到项目设置中的" [集成"页面](overview.html#accessing-integrations) . 也就是说, **项目>设置>集成** . +2. 选择" **Discord Notifications"**集成进行配置. +3. 确保启用了**活动**切换. +4. 选中与您要向 Discord 发送通知的 GitLab 事件相对应的复选框. +5. 粘贴您从创建 Discord Webhook 步骤复制的 Webhook URL. +6. 配置其余选项,然后单击" **保存更改"**按钮. + +您创建了 Webhook 的 Discord 频道现在将收到有关已配置的 GitLab 事件的通知. \ No newline at end of file diff --git a/docs/078.md b/docs/078.md new file mode 100644 index 0000000000000000000000000000000000000000..ac0f83415411b8dab1b32f9999d02515a30dedaf --- /dev/null +++ b/docs/078.md @@ -0,0 +1,22 @@ +# Enabling emails on push + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/emails_on_push.html](https://docs.gitlab.com/ee/user/project/integrations/emails_on_push.html) + +# Enabling emails on push[](#enabling-emails-on-push "Permalink") + +通过启用此服务,您将收到有关推送至项目的每个更改的电子邮件通知. + +在" [集成"页面中,](overview.html#accessing-integrations)选择**"推送**服务中的**电子邮件"**以激活和配置它. + +在" *收件人"*区域中,提供用空格或换行符分隔的电子邮件列表. + +提供以下选项: + +* **推送事件** -收到推送事件时将触发电子邮件. +* **标记推送事件** -创建和推送标记时将触发电子邮件. +* **从提交者**发送-如果该域是运行 GitLab 的域的一部分,则从提交者的电子邮件地址发送通知(例如`user@gitlab.com` ). +* **禁用代码差异** -通知正文中不要包含敏感的代码差异. + +| Settings | Notification | +| --- | --- | +| [![Email on push service settings](img/b4a1ffd094e753d655825c1385561991.png)](img/emails_on_push_service.png) | [![Email on push notification](img/906ca69aaf7c7a7f53479eb595f83ec0.png)](img/emails_on_push_email.png) | \ No newline at end of file diff --git a/docs/079.md b/docs/079.md new file mode 100644 index 0000000000000000000000000000000000000000..92999577b276f3f042dc55097214f8b332393e0a --- /dev/null +++ b/docs/079.md @@ -0,0 +1,53 @@ +# GitHub project integration + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/github.html](https://docs.gitlab.com/ee/user/project/integrations/github.html) + +* [Configuration](#configuration) + * [Complete these steps on GitHub](#complete-these-steps-on-github) + * [Complete these steps on GitLab](#complete-these-steps-on-gitlab) + * [Static / dynamic status check names](#static--dynamic-status-check-names) + +# GitHub project integration[](#github-project-integration-premium "Permalink") + +在 GitLab Premium 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/3836) . + +GitLab 提供了一个集成,用于更新 GitHub 上的管道状态. 如果仅将 GitLab 用于 CI / CD,这将特别有用. + +此项目集成与[实例范围的 GitHub 集成](../import/github.html#mirroring-and-pipeline-status-sharing)分开,并且在[GitHub import](../../../integration/github.html)上自动配置. + +[![Pipeline status update on GitHub](img/e3e09b090e6c8612f71f6dbd7244cbb2.png)](img/github_status_check_pipeline_update.png) + +## Configuration[](#configuration "Permalink") + +### Complete these steps on GitHub[](#complete-these-steps-on-github "Permalink") + +此集成需要[GitHub API 令牌,](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token)并授予`repo:status`访问权限: + +1. 转到[https://github.com/settings/tokens 上的](https://github.com/settings/tokens) "个人访问令牌"页面. +2. 点击"生成新令牌" +3. 确保选中`repo:status`并单击" Generate token" +4. 复制生成的令牌以在 GitLab 上使用 + +### Complete these steps on GitLab[](#complete-these-steps-on-gitlab "Permalink") + +1. Navigate to the project you want to configure. +2. 导航到" [集成"页面](overview.html#accessing-integrations) +3. 点击" GitHub". +4. 确保启用了**活动**切换. +5. 粘贴您在 GitHub 上生成的令牌 +6. 输入您在 GitHub 上的项目的路径,例如`https://github.com/username/repository` +7. (可选)取消选中" **静态状态检查名称"**复选框以禁用静态状态检查名称. +8. 保存或选择单击"测试设置". + +配置完集成后,请参阅[外部请求请求的](../../../ci/ci_cd_for_external_repos/#pipelines-for-external-pull-requests)管道,以配置要为打开请求请求运行的管道. + +#### Static / dynamic status check names[](#static--dynamic-status-check-names "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入:使用静态检查名称作为选择加入选项. +* [在 GitLab 12.4 中](https://gitlab.com/gitlab-org/gitlab/-/issues/9931) ,静态状态检查名称是新项目的默认行为. + +This makes it possible to mark these status checks as *Required* on GitHub. 这样就可以在 GitHub 上将这些状态检查标记为" *必需* ". With **Static status check names** enabled on the integration page, your GitLab instance host name is going to be appended to a status check name, whereas in case of dynamic status check names, a branch name is going to be appended. 在集成页面上启用了**静态状态检查名称后** ,您的 GitLab 实例主机名将被附加到状态检查名称中,而在动态状态检查名的情况下将被添加分支名称. + +[![Configure GitHub Project Integration](img/9101937463fa0be989f93d09d9f54d7a.png)](img/github_configuration.png) \ No newline at end of file diff --git a/docs/080.md b/docs/080.md new file mode 100644 index 0000000000000000000000000000000000000000..173779b0aa46c881710c03b55150d8fcaa68ed89 --- /dev/null +++ b/docs/080.md @@ -0,0 +1,36 @@ +# Hangouts Chat service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/hangouts_chat.html](https://docs.gitlab.com/ee/user/project/integrations/hangouts_chat.html) + +* [On Hangouts Chat](#on-hangouts-chat) +* [On GitLab](#on-gitlab) + +# Hangouts Chat service[](#hangouts-chat-service "Permalink") + +在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/43756) . + +环聊聊天服务将通知从 GitLab 发送到创建 Webhook 的房间. + +## On Hangouts Chat[](#on-hangouts-chat "Permalink") + +1. 打开要在其中查看通知的聊天室. +2. 从聊天室菜单中,选择**配置 Webhooks** . +3. 单击**添加网站,**然后填写将发布消息的机器人的名称. (可选)定义头像. +4. 单击" **保存",**然后复制您的**Webhook 的 Webhook URL** . + +另请参阅[环聊聊天文档,以配置传入的 Webhooks](https://developers.google.com/hangouts/chat/how-tos/webhooks) + +## On GitLab[](#on-gitlab "Permalink") + +当您拥有环**聊聊天**室**Webhook 的 Webhook URL 时** ,您可以设置 GitLab 服务. + +1. 导航到项目设置中的" [集成"页面](overview.html#accessing-integrations) ,即" **项目">"设置">"集成"** . +2. 选择**环聊聊天**集成进行配置. +3. 确保启用了**活动**切换. +4. 选中与您要接收的 GitLab 事件相对应的复选框. +5. 粘贴您从环**聊聊天**配置步骤中复制的**Webhook URL** . +6. 配置其余选项,然后单击" `Save changes` . + +您的环聊聊天室现在将开始接收配置的 GitLab 事件通知. + +[![Hangouts Chat configuration](img/5f87ce250e2ea1a803a3aeda446eca15.png)](img/hangouts_chat_configuration.png) \ No newline at end of file diff --git a/docs/081.md b/docs/081.md new file mode 100644 index 0000000000000000000000000000000000000000..05c94c705ab873fb774d4aecb2878e2d85c3a08f --- /dev/null +++ b/docs/081.md @@ -0,0 +1,50 @@ +# Atlassian HipChat + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/hipchat.html](https://docs.gitlab.com/ee/user/project/integrations/hipchat.html) + +* [Setup](#setup) + * [Complete these steps in HipChat](#complete-these-steps-in-hipchat) + * [Complete these steps in GitLab](#complete-these-steps-in-gitlab) +* [Troubleshooting](#troubleshooting) + +# Atlassian HipChat[](#atlassian-hipchat "Permalink") + +GitLab 提供了一种在许多事件(例如,当用户按下代码,创建分支或标签,添加注释以及创建合并请求)时发送 HipChat 通知的方法. + +## Setup[](#setup "Permalink") + +GitLab 要求使用 HipChat v2 API 令牌才能工作. 目前不支持 v1 令牌. 注意 v1 和 v2 令牌之间的区别: + +HipChat v1 API(旧版)在" Group API"菜单中支持" API Auth Tokens". 允许使用 v1 令牌将消息发送到*任何*房间. + +HipChat v2 API 具有可以使用"组"或"房间"管理页面中的"集成"选项卡创建的令牌. 根据设计,这些是轻量级令牌,允许 GitLab 仅将消息发送到*一个*房间. + +### Complete these steps in HipChat[](#complete-these-steps-in-hipchat "Permalink") + +1. 转到: `https://admin.hipchat.com/admin` : `https://admin.hipchat.com/admin` +2. 单击"组管理员"->"集成". +3. 找到"自己动手!" 然后点击"创建". +4. 选择所需的房间,将集成命名为" GitLab",然后单击"创建". +5. 在"通过发布此 URL 将消息发送到此房间"列中,您应该看到以下格式的 URL: + +``` +https://api.hipchat.com/v2/room//notification?auth_token= +``` + +HipChat 现在准备接受来自 GitLab 的消息. 接下来,在 GitLab 中设置 HipChat 服务. + +### Complete these steps in GitLab[](#complete-these-steps-in-gitlab "Permalink") + +1. 导航到您要为通知配置的项目. +2. 导航到" [集成"页面](overview.html#accessing-integrations) +3. 点击" HipChat". +4. 确保启用了**活动**切换. +5. 插入`token`从 URL 字段进入`Token`在 Web 页面上的字段. +6. 插入`room`从 URL 字段进入`Room`在 Web 页面上字段. +7. 保存或选择单击"测试设置". + +## Troubleshooting[](#troubleshooting "Permalink") + +如果没有看到通知,请确保您使用的是 HipChat v2 API 令牌,而不是 v1 令牌. + +请注意,v2 令牌绑定到特定房间. 如果希望能够指定任意房间,则可以在 HipChat 中"帐户设置"和" API 访问"下为特定用户创建 API 令牌. 使用`auth_token=XXX`下的`XXX`值. \ No newline at end of file diff --git a/docs/082.md b/docs/082.md new file mode 100644 index 0000000000000000000000000000000000000000..0c9029f818764e75ca9afb978af4329194e187e2 --- /dev/null +++ b/docs/082.md @@ -0,0 +1,43 @@ +# Irker IRC Gateway + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/irker.html](https://docs.gitlab.com/ee/user/project/integrations/irker.html) + +* [Needed setup](#needed-setup) +* [Complete these steps in GitLab](#complete-these-steps-in-gitlab) +* [Note on Irker recipients](#note-on-irker-recipients) + +# Irker IRC Gateway[](#irker-irc-gateway "Permalink") + +GitLab 提供了一种将更新消息推送到 Irker 服务器的方法. 配置后,推送到项目将触发服务将数据直接发送到 Irker 服务器. + +有关更多信息,请参见项目主页: [https](https://gitlab.com/esr/irker) : [//gitlab.com/esr/irker](https://gitlab.com/esr/irker) + +## Needed setup[](#needed-setup "Permalink") + +您首先需要一个 Irker 守护程序. 您可以从[https://gitlab.com/esr/irker 的](https://gitlab.com/esr/irker)存储库中下载 Irker 代码: + +``` +git clone https://gitlab.com/esr/irker.git +``` + +下载代码后,您可以运行名为`irkerd`的 Python 脚本. 该脚本是网关脚本,它既充当 IRC 客户端(用于显然将消息发送到 IRC 服务器),又充当 TCP 服务器(用于从 GitLab 服务接收消息). + +如果 Irker 服务器在同一台计算机上运行,​​则操作完成. 如果没有,您将需要遵循下一部分的第一步. + +## Complete these steps in GitLab[](#complete-these-steps-in-gitlab "Permalink") + +1. 导航到您要为通知配置的项目. +2. 导航到" [集成"页面](overview.html#accessing-integrations) +3. Click “Irker”. +4. 确保启用了**活动**切换. +5. 在网页的" `Server host`字段中输入`irkerd`运行的服务器主机地址(默认为`localhost` ). +6. 在网页的" `Server port`字段中输入`irkerd`的服务器端口(例如,默认为 6659). +7. 可选:如果设置了`Default IRC URI` ,则其格式必须为`irc[s]://domain.name`并且将`irc[s]://domain.name`在用户提供的每个通道(不是完整 URI)之前. +8. 指定收件人(例如,#channel1,user1 等) +9. 保存或选择单击"测试设置". + +## Note on Irker recipients[](#note-on-irker-recipients "Permalink") + +Irker 接受形式的信道名称`chan`和`#chan`为,既`#chan`通道. 如果要在查询中发送消息,则需要在频道名称后添加`,isnick` ,格式为: `Aorimn,isnick` . 在后一种情况下, `Aorimn`被视为昵称,而不再被视为频道名称. + +Irker 也可以加入受密码保护的频道. 用户需要在 chan 名称后附加`?key=thesecretpassword` . 使用此功能时,请记住**不要**在频道名称前加上`#`号; 否则,irker 会加入一个字面名为`#chan?key=password`的通道,此后将通过`/whois` IRC 命令(取决于 IRC 服务器配置)泄漏该通道密钥. 这是由于长期存在的虫虫. \ No newline at end of file diff --git a/docs/083.md b/docs/083.md new file mode 100644 index 0000000000000000000000000000000000000000..9be472f031b38d690e7bb73d34806e941b2dce2e --- /dev/null +++ b/docs/083.md @@ -0,0 +1,178 @@ +# GitLab Jira integration + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/jira.html](https://docs.gitlab.com/ee/user/project/integrations/jira.html) + +* [Configuration](#configuration) + * [Configuring Jira](#configuring-jira) + * [Jira Server](#jira-server) + * [Jira Cloud](#jira-cloud) + * [Configuring GitLab](#configuring-gitlab) + * [Obtaining a transition ID](#obtaining-a-transition-id) + * [Disabling comments on Jira issues](#disabling-comments-on-jira-issues) +* [Jira issues](#jira-issues) + * [Referencing Jira Issues](#referencing-jira-issues) + * [Closing Jira Issues](#closing-jira-issues) + * [Jira issue closing example](#jira-issue-closing-example) +* [Troubleshooting](#troubleshooting) + * [GitLab is unable to comment on a Jira issue](#gitlab-is-unable-to-comment-on-a-jira-issue) + * [GitLab is unable to close a Jira issue](#gitlab-is-unable-to-close-a-jira-issue) + * [CAPTCHA](#captcha) + +# GitLab Jira integration[](#gitlab-jira-integration "Permalink") + +GitLab 问题是讨论想法,计划和跟踪工作的强大工具. 但是,许多组织已经将 Jira 用于这些目的,并且内置了广泛的数据和业务流程. + +尽管您始终可以将内容和流程从 Jira 迁移到 GitLab Issue,但是您也可以选择继续使用 Jira,并通过我们的集成将其与 GitLab 一起使用. + +有关与 Jira 集成的视频演示,请观看有关[GitLab 工作流程的 Jira 问题和 Jenkins 管道](https://youtu.be/Jn-_fyra7xQ) . + +将 GitLab 项目与 Jira 实例集成后,即可自动检测 GitLab 项目与 Jira 中的任何项目之间的活动并进行交叉引用. 这包括在 GitLab 中完成工作后关闭或转换 Jira 问题的功能. + +在 GitLab 中执行以下操作时,集成的响应方式如下: + +* 在提交消息或 MR(合并请求)中**提及 Jira 问题 ID** . + * GitLab 超链接至 Jira 问题. + * Jira 问题将问题链接添加到 GitLab 中的提交/ MR. + * Jira 问题会添加评论,以反映在 GitLab 中发表的评论,评论作者以及在 GitLab 中指向 commit / MR 的链接,除非[禁用了](#disabling-comments-on-jira-issues)对 Jira 的评论. +* **提及提交或 MR"关闭","解决"或"修复" Jira 问题 ID** . 在项目的默认分支(通常是主分支)上进行提交或将更改合并到默认分支时: + * GitLab 的合并请求页面显示一条注释,指出"已关闭" Jira 问题,并带有指向该问题的链接. (注意:在合并之前,MR 将显示它"关闭"了 Jira 问题.) + * Jira 问题显示活动,并且 Jira 问题已关闭或已转换. + +您还可以直接从 GitLab 使用[Jira 的 Smart](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html) Commit,如文章[如何以及为什么将 GitLab 与 Jira 集成中所述](https://www.programmableweb.com/news/how-and-why-to-integrate-gitlab-jira/how-to/2017/04/25) . + +## Configuration[](#configuration "Permalink") + +每个 GitLab 项目都可以配置为连接到整个 Jira 实例. 这意味着一个 GitLab 项目一旦配置,便可以与该实例中的*所有* Jira 项目进行交互. 因此,您不必将 GitLab 项目与任何单个 Jira 项目显式关联. + +如果您有一个 Jira 实例,则可以使用默认模板预先填充设置页面. 请参阅[服务模板](services_templates.html)文档. + +为了在 GitLab 中启用 Jira 服务,您需要首先在 Jira 中配置项目,然后在 GitLab 中输入正确的值. + +### Configuring Jira[](#configuring-jira "Permalink") + +#### Jira Server[](#jira-server "Permalink") + +**Jira Server**支持基本身份验证. 连接时,需要**用户名和密码** . 请注意,无法通过 CAS 连接到 Jira Server. 首先[在 Jira Server 中设置用户,](jira_server_configuration.html)然后继续[配置 GitLab](#configuring-gitlab) . + +#### Jira Cloud[](#jira-cloud "Permalink") + +**Jira Cloud**支持通过 API 令牌进行身份验证. 连接到**Jira Cloud 时** ,需要**电子邮件和 API 令牌** . 首先[在 Jira Cloud 中设置用户,](jira_cloud_configuration.html)然后继续[配置 GitLab](#configuring-gitlab) . + +### Configuring GitLab[](#configuring-gitlab "Permalink") + +> **Notes:** +> +> * 当前支持的 Jira 版本是`v6.x, v7.x, v8.x` . 需要 GitLab 7.8 或更高版本. +> * GitLab 8.14 引入了一种与 Jira 集成的新方法,该方法大大简化了您必须输入的配置选项. 如果您使用的是旧版本,请[遵循此文档](https://gitlab.com/gitlab-org/gitlab/blob/8-13-stable-ee/doc/project_services/jira.md) . +> * 为了支持 Oracle 的 Access Manager,GitLab 将发送其他 cookie 以启用基本身份验证. 添加到每个请求的 cookie 是`OBBasicAuth` ,其值为`fromDialog` . + +要在项目中启用 Jira 集成,请导航到[Integrations 页面](overview.html#accessing-integrations) ,单击**Jira**服务,然后按照下表中的说明在页面上填写所需的详细信息. + +| Field | Description | +| --- | --- | +| `Web URL` | 链接到此 GitLab 项目的 Jira 实例 Web 界面的基本 URL. 例如, `https://jira.example.com` . | +| `Jira API URL` | The base URL to the Jira instance API. Web URL value will be used if not set. E.g., `https://jira-api.example.com`. Leave this field blank (or use the same value of `Web URL`) if using **吉拉云**. | +| `Username/Email` | 在[配置 Jira step](#configuring-jira)时创建. 将`username`用于**Jira Server**或将`email`用于**Jira Cloud** . | +| `Password/API token` | 在[配置 Jira 步骤中](#configuring-jira)创建. 为**Jira Server**使用`password`或为**Jira Cloud**使用`API token` . | +| `Transition ID` | 这是将问题移至所需状态的过渡的 ID. 它可以插入过渡 IDS 分离通过`,`或`;` 这意味着将按照给定的顺序将问题逐个移至每个州. **如果您未正确设置 ID,则无法通过提交或合并请求来关闭 Jira 问题.** | + +### Obtaining a transition ID[](#obtaining-a-transition-id "Permalink") + +在最新的 Jira 用户界面中,您不再可以在工作流管理 UI 中看到过渡 ID. 您可以通过以下两种方式之一获取所需的 ID: + +1. 通过使用 API​​,并使用诸如处于适当"打开"状态的问题的请求(例如`https://yourcompany.atlassian.net/rest/api/2/issue/ISSUE-123/transitions` +2. 通过将鼠标悬停在所需转换的链接上并在 URL 中查找" action"参数 + +请注意,即使您要更改的状态相同,过渡 ID 在工作流之间也可能有所不同(例如,错误与故事). + +保存配置后,您的 GitLab 项目将能够与 Jira 实例中的所有 Jira 项目进行交互,并且您将在 GitLab 项目页面上看到 Jira 链接,该链接将您带到适当的 Jira 项目. + +[![Jira service page](img/ebaf329b1a5a45f2d451e4574f3d7857.png)](img/jira_service_page_v12_2.png) + +### Disabling comments on Jira issues[](#disabling-comments-on-jira-issues "Permalink") + +当您引用 Jira 问题时,它将始终链接回 GitLab 中的源提交/ MR,但是,您可以控制 GitLab 是否还将交叉发布对 Jira 问题的评论. 默认情况下启用该功能. + +要禁用对 Jira 问题的自动评论: + +1. 打开" [集成"页面,](overview.html#accessing-integrations)然后选择**Jira** . +2. 在" **事件操作"**部分中,取消选中" **注释"** . + +## Jira issues[](#jira-issues "Permalink") + +现在,您应该已经[配置了 Jira](#configuring-jira)并[在 GitLab 中](#configuring-gitlab)启用了[Jira 服务](#configuring-gitlab) . 如果一切设置正确,您应该能够通过在 GitLab 提交和合并请求中提及 ID 来引用和关闭 Jira 问题. + +### Referencing Jira Issues[](#referencing-jira-issues "Permalink") + +当 GitLab 项目配置并启用了 Jira 问题跟踪器时,在 GitLab 中提及 Jira 问题将自动在 Jira 问题中添加评论,并带有返回到 GitLab 的链接. 这意味着在合并请求和提交中引用问题的注释中,例如`PROJECT-7` ,将在 Jira issue 中添加以下格式的注释: + +``` +USER mentioned this issue in RESOURCE_NAME of [PROJECT_NAME|LINK_TO_COMMENT]: +ENTITY_TITLE +``` + +* `USER`提到问题的用户. 这是指向 GitLab 中的用户配置文件的链接. +* `LINK_TO_THE_COMMENT`链接到提及的来源,带有提及吉拉问题的实体的名称. +* `RESOURCE_NAME`引用该问题的`RESOURCE_NAME`种类. 可以是提交或合并请求. +* `PROJECT_NAME` GitLab 项目名称. +* `ENTITY_TITLE`合并请求标题或提交消息的第一行. + +[![example of mentioning or closing the Jira issue](img/bf46825f18b4b1998d719dffeab0c45c.png)](img/jira_issue_reference.png) + +例如,以下提交将引用以`PROJECT-1`作为 ID 的 Jira 问题: + +``` +git commit -m "PROJECT-1 Fix spelling and grammar" +``` + +### Closing Jira Issues[](#closing-jira-issues "Permalink") + +通过在提交和合并请求中使用触发词,可以直接从 GitLab 关闭 Jira 问题. 当推送包含触发词并在提交消息中包含 Jira 问题 ID 的提交时,GitLab 将在提到的 Jira 问题中添加注释,并立即将其关闭(前提是正确设置了转换 ID). + +当前有三个触发词,您可以使用其中一个来实现相同的目标: + +* `Resolves PROJECT-1` +* `Closes PROJECT-1` +* `Fixes PROJECT-1` + +其中`PROJECT-1`是 Jira 问题的 ID. + +> **Notes:** +> +> * 只有提交并合并到项目的默认分支(通常是**master** )才能关闭 Jira 中的问题. 您可以在[项目设置](img/jira_project_settings.png)下更改项目默认分支. +> * 如果有解决方案,那么 Jira 问题将不会过渡. + +### Jira issue closing example[](#jira-issue-closing-example "Permalink") + +让我们考虑以下示例: + +1. 对于 Jira 中名为`PROJECT` ,我们实现了一项新功能,并在 GitLab 中创建了合并请求. +2. This feature was requested in Jira issue `PROJECT-7` and the merge request in GitLab contains the improvement +3. 在合并请求描述中,我们使用问题关闭触发器`Closes PROJECT-7` . +4. 合并请求合并后,Jira 问题将自动关闭,并带有注释和指向解决该问题的提交的关联链接. + +在以下屏幕截图中,您可以看到指向 Jira 问题的链接的外观. + +[![A Git commit that causes the Jira issue to be closed](img/381000c5f5c6ad01300dfcc889f7fb0f.png)](img/jira_merge_request_close.png) + +合并此合并请求后,将通过指向解决该问题的提交的链接自动关闭 Jira 问题. + +[![The GitLab integration closes Jira issue](img/ae54430a80c08d51c51659ac1a4dd8b9.png)](img/jira_service_close_issue.png) + +## Troubleshooting[](#troubleshooting "Permalink") + +如果这些功能不能按预期方式工作,则可能是由于集成设置的配置存在问题. + +### GitLab is unable to comment on a Jira issue[](#gitlab-is-unable-to-comment-on-a-jira-issue "Permalink") + +如果您希望 GitLab 也可以这样做,请确保您为集成设置的 Jira 用户具有正确的访问权限,可以发表有关 Jira 问题的评论并转换问题. 如果禁用了 GitLab 问题跟踪器,则 Jira 问题参考和更新注释将不起作用. + +### GitLab is unable to close a Jira issue[](#gitlab-is-unable-to-close-a-jira-issue "Permalink") + +确保在" Jira"设置中设置的" `Transition ID`与您的项目解决问题所需的`Transition ID`匹配. + +确保尚未将 Jira 问题标记为已解决; 也就是说,未设置" Jira 问题解决"字段. (不应在 Jira 列表中删除它.) + +### CAPTCHA[](#captcha "Permalink") + +在连续几次失败的登录尝试后,可能会触发 CAPTCHA,这可能会在测试 Jira 集成时导致`401 unauthorized`错误. 如果已触发验证码,则您将无法使用 Jira 的 REST API 对 Jira 站点进行身份验证. 您将需要登录到您的 Jira 实例并完成 CAPTCHA. \ No newline at end of file diff --git a/docs/084.md b/docs/084.md new file mode 100644 index 0000000000000000000000000000000000000000..cbe7b6a254b73e7373a167d9661bdd1d8c81e1f1 --- /dev/null +++ b/docs/084.md @@ -0,0 +1,57 @@ +# Mattermost Notifications Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/mattermost.html](https://docs.gitlab.com/ee/user/project/integrations/mattermost.html) + +* [On Mattermost](#on-mattermost) +* [On GitLab](#on-gitlab) + +# Mattermost Notifications Service[](#mattermost-notifications-service "Permalink") + +Mattermost Notifications Service 允许您的 GitLab 项目将事件(例如, `issue created` )作为通知发送到您现有的 Mattermost 团队. 这需要在 Mattermost 和 GitLab 中进行配置. + +您还可以使用 Mattermost 斜杠命令来控制 Mattermost 中的 GitLab. 这是单独配置的[Mattermost 斜杠命令](mattermost_slash_commands.html) . + +## On Mattermost[](#on-mattermost "Permalink") + +要启用 Mattermost 集成,您必须创建传入的 Webhook 集成: + +1. 登录到您的 Mattermost 实例. +2. 访问传入的 Webhooks,类似于: `https://mattermost.example.com/your_team_name/integrations/incoming_webhooks/add` ://mattermost.example.com/your_team_name/integrations/incoming_webhooks/add. +3. 选择显示名称,描述和通道,可以在 GitLab 上覆盖它们. +4. 保存它,复制**Webhook URL** ,稍后我们将在 GitLab 中使用它. + +传入的 Webhooks 可能在您的 Mattermost 实例上被阻止. 要求您的 Mattermost 管理员启用它: + +* **Mattermost** 5.12 及更高版本中的**Mattermost 系统控制台>集成>集成管理** . +* **Mattermost** 5.11 及更低版本中的**Mattermost 系统控制台>集成>自定义集成** . + +默认情况下,不启用显示名称覆盖,您需要让您的管理员在同一部分启用它. + +## On GitLab[](#on-gitlab "Permalink") + +设置 Mattermost 之后,就该设置 GitLab 了. + +导航到" [集成"页面,](overview.html#accessing-integrations)然后选择"最**重要的通知"**服务以对其进行配置. 在那里,您将看到一个带有以下可触发事件的复选框: + +* Push +* Issue +* 机密问题 +* 合并要求 +* Note +* 机密说明 +* 标签推送 +* Pipeline +* 维基页面 +* Deployment + +在每个事件复选框的下方,都有一个输入字段,用于输入您要发送该事件消息的 Mattermost 频道. 输入您首选的频道句柄(井号`#`是可选的). + +最后,填写您最重要的详细信息: + +| Field | Description | +| --- | --- | +| **Webhook** | 您必须在 Mattermost 上设置的传入 Webhook URL,它类似于: `http://mattermost.example/hooks/5xo…` | +| **Username** | 可选的用户名,可以在发送给 Mattermost 的邮件中使用. 如果要更改机器人的用户名,请填写. | +| **仅通知断开的管道** | 如果您选择启用**管道**事件,并且只希望收到有关失败管道的通知. | + +[![Mattermost configuration](img/95c0b87af108caee2a239482aec61675.png)](img/mattermost_configuration.png) \ No newline at end of file diff --git a/docs/085.md b/docs/085.md new file mode 100644 index 0000000000000000000000000000000000000000..005323550152081512b764cb7124cbfc89431dae --- /dev/null +++ b/docs/085.md @@ -0,0 +1,137 @@ +# Mattermost slash commands + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/mattermost_slash_commands.html](https://docs.gitlab.com/ee/user/project/integrations/mattermost_slash_commands.html) + +* [Prerequisites](#prerequisites) +* [Automated configuration](#automated-configuration) +* [Manual configuration](#manual-configuration) + * [Step 1\. Enable custom slash commands in Mattermost](#step-1-enable-custom-slash-commands-in-mattermost) + * [Step 2\. Open the Mattermost slash commands service in GitLab](#step-2-open-the-mattermost-slash-commands-service-in-gitlab) + * [Step 3\. Create a new custom slash command in Mattermost](#step-3-create-a-new-custom-slash-command-in-mattermost) + * [Step 4\. Copy the Mattermost token into the Mattermost slash command service](#step-4-copy-the-mattermost-token-into-the-mattermost-slash-command-service) +* [Authorizing Mattermost to interact with GitLab](#authorizing-mattermost-to-interact-with-gitlab) +* [Available slash commands](#available-slash-commands) +* [Permissions](#permissions) +* [Troubleshooting](#troubleshooting) +* [Further reading](#further-reading) + +# Mattermost slash commands[](#mattermost-slash-commands "Permalink") + +在 GitLab 8.14 中引入 + +Mattermost 命令为用户提供了一个额外的界面,可以在聊天环境中执行常见操作. 例如,这使得一个问题一经在 Mattermost 中讨论后就可以创建. + +GitLab 还可以将事件(例如, `issue created` )作为通知发送到 Mattermost. 这是单独配置的[Mattermost Notifications Service](mattermost.html) . + +## Prerequisites[](#prerequisites "Permalink") + +需要 Mattermost 3.4 及更高版本. + +如果您安装了 Omnibus GitLab 软件包,则其中已包含 Mattermost. 您所要做的就是配置它. 在[Omnibus GitLab Mattermost 文档中](https://docs.gitlab.com/omnibus/gitlab-mattermost/)阅读更多[内容](https://docs.gitlab.com/omnibus/gitlab-mattermost/) . + +## Automated configuration[](#automated-configuration "Permalink") + +如果 Mattermost 与 GitLab 安装在同一服务器上,则 GitLab 可以为您完成配置过程. + +转到项目上的 Mattermost Slash Command 服务,然后单击"添加到 Mattermost"按钮. + +## Manual configuration[](#manual-configuration "Permalink") + +配置由两部分组成. 首先,您需要在 Mattermost 中启用斜杠命令,然后在 GitLab 中启用该服务. + +### Step 1\. Enable custom slash commands in Mattermost[](#step-1-enable-custom-slash-commands-in-mattermost "Permalink") + +仅在使用源代码安装时才需要执行此步骤,Omnibus 安装将使用正确的设置进行预配置. + +在 Mattermost 中要做的第一件事是从管理员控制台启用自定义斜杠命令. + +1. 使用具有管理员权限的帐户登录并导航至系统控制台. + + [![Mattermost go to console](img/e9fe43924bd4226e7b819104bcc8b8c1.png)](img/mattermost_goto_console.png) + +2. 单击" **自定义集成"**并将" **启用自定义斜杠命令"** ," **启用自定义集成以覆盖用户名** "和" **覆盖自定义集成以覆盖个人资料图片图标"设置**为 true. + + [![Mattermost console](img/75ffde23ab0100e58532632d19b84db0.png)](img/mattermost_console_integrations.png) + +3. 点击底部的**保存** ,保存更改. + +### Step 2\. Open the Mattermost slash commands service in GitLab[](#step-2-open-the-mattermost-slash-commands-service-in-gitlab "Permalink") + +1. 打开 GitLab 的新标签,转到项目的" [集成"页面,](overview.html#accessing-integrations)然后选择**Mattermost 命令**服务进行配置. 将出现一个屏幕,其中包含您需要在 Mattermost 中复制的所有值,如下一步所述. 使窗口保持打开状态. + + **注意:** GitLab 将为"最重要的设置"建议一些值. 原样复制粘贴的唯一要求是**请求 URL** ,所有其他都只是建议. + + [![Mattermost setup instructions](img/801adc20d157f18e08adbd379180f3c7.png)](img/mattermost_config_help.png) + +2. 继续下一步,并在 Mattermost 中使用上述值创建斜线命令. + +### Step 3\. Create a new custom slash command in Mattermost[](#step-3-create-a-new-custom-slash-command-in-mattermost "Permalink") + +现在,您已在 Mattermost 中启用了自定义斜杠命令并在 GitLab 中打开了 Mattermost 斜杠命令服务,是时候将这些值复制到新的斜杠命令中了. + +1. 回到 Mattermost,在团队页面设置下,您应该看到**Integrations**选项. + + [![Mattermost team integrations](img/d7b5490ec5cb26ce71f19d5c56f003f3.png)](img/mattermost_team_integrations.png) + +2. 转到**Slash Commands**集成,然后单击**Add Slash Command**按钮添加一个新的. + + [![Mattermost add command](img/3694fc45636610ba5fb4e24d7a9eb3b9.png)](img/mattermost_add_slash_command.png) + +3. 按照[步骤 2 中的说明](#step-2-open-the-mattermost-slash-commands-service-in-gitlab)填写自定义命令的选项. + + **注意:**如果计划连接多个项目,请选择一个与项目相关的斜杠命令触发词,例如`/gitlab-project-name`或什至`/project-name` . 仅在将单个项目连接到 Mattermost 团队时才使用`/gitlab` . + + [![Mattermost add command configuration](img/1fdfdef058a3092e25352089de97fee6.png)](img/mattermost_slash_command_configuration.png) + +4. 设置所有值之后,复制令牌(我们将在下面使用它)并单击**完成** . + + [![Mattermost slash command token](img/41571e3a155c671e6ff9f259f20fdeed.png)](img/mattermost_slash_command_token.png) + +### Step 4\. Copy the Mattermost token into the Mattermost slash command service[](#step-4-copy-the-mattermost-token-into-the-mattermost-slash-command-service "Permalink") + +1. 在 GitLab 中,粘贴您在上一步中复制的最重要的令牌,并确保启用了**活动**切换. + + [![Mattermost copy token to GitLab](img/07c2c84efb64460dfa2373f1f75645ab.png)](img/mattermost_gitlab_token.png) + +2. 单击**保存更改**以使更改生效. + +现在,您已设置为在 Mattermost 中开始使用与您配置的 GitLab 项目对话的斜杠命令. + +## Authorizing Mattermost to interact with GitLab[](#authorizing-mattermost-to-interact-with-gitlab "Permalink") + +用户首次与新创建的斜杠命令进行交互时,Mattermost 将触发授权过程. + +[![Mattermost bot authorize](img/6e17896087b8446f53400a1c8d39c0d6.png)](img/mattermost_bot_auth.png) + +这会将您的 Mattermost 用户与 GitLab 用户连接起来. 您可以在个人资料页面的" **聊天"**下看到所有授权的聊天帐户. + +授权过程完成后,您可以使用 Mattermost 命令开始与 GitLab 进行交互. + +## Available slash commands[](#available-slash-commands "Permalink") + +可用的斜杠命令是: + +| Command | Description | Example | +| --- | --- | --- | +| `/ 发出新的 `⇧Shift` + `↵输入` <description>` | 在与`<trigger>`绑定的项目中创建一个新问题. `<description>`是可选的. | `/gitlab issue new We need to change the homepage` | +| `/<trigger> issue show <issue-number>` | 显示与`<trigger>`绑定的项目中 ID 为`<issue-number>` . | `/gitlab issue show 42` | +| `/ <触发>将<环境>部署到<环境>` | 开始从一个环境部署到另一环境的 CI 作业,例如`staging`到`production` . CI / CD 必须[正确配置](../../../ci/yaml/README.html) . | `/gitlab deploy staging to production` | + +要查看与 GitLab 交互的可用命令列表,请输入触发词,然后输入`help` . 示例: `/gitlab help` + +[![Mattermost bot available commands](img/0c549416181d6e18eb1dd34825b00425.png)](img/mattermost_bot_available_commands.png) + +## Permissions[](#permissions "Permalink") + +运行[可用命令](#available-slash-commands)的[权限](../../permissions.html#project-members-permissions)源自[您对项目](../../permissions.html#project-members-permissions)的[权限](../../permissions.html#project-members-permissions) . + +## Troubleshooting[](#troubleshooting "Permalink") + +如果未触发某个事件,请确认您使用的频道是公开频道,因为 Mattermost Webhooks 无法访问私有频道. + +如果需要专用频道,则可以在 Mattermost 中编辑 Webhook 的频道并选择一个专用频道. 无法将不同的通道用于不同类型的通知-所有事件都将发送到指定的通道. + +## Further reading[](#further-reading "Permalink") + +* [Mattermost slash commands documentation](https://docs.mattermost.com/developer/slash-commands.html) +* [Omnibus GitLab Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/) \ No newline at end of file diff --git a/docs/086.md b/docs/086.md new file mode 100644 index 0000000000000000000000000000000000000000..ebb6d65f6cae4a7377bdf1f89c6ae3aef951ca41 --- /dev/null +++ b/docs/086.md @@ -0,0 +1,38 @@ +# Microsoft Teams service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/microsoft_teams.html](https://docs.gitlab.com/ee/user/project/integrations/microsoft_teams.html) + +* [On Microsoft Teams](#on-microsoft-teams) +* [On GitLab](#on-gitlab) + +# Microsoft Teams service[](#microsoft-teams-service "Permalink") + +## On Microsoft Teams[](#on-microsoft-teams "Permalink") + +要启用 Microsoft Teams 集成,必须按照" [向连接器和 Webhooks 发送消息"中](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using)所述的步骤,在 Microsoft Teams 上创建传入的 Webhook 集成. + +## On GitLab[](#on-gitlab "Permalink") + +设置 Microsoft Teams 之后,就该设置 GitLab 了. + +导航到" [集成"页面,](overview.html#accessing-integrations)然后选择" **Microsoft Teams Notification"**服务进行配置. 在那里,您将看到一个带有以下可触发事件的复选框: + +* Push +* Issue +* 机密问题 +* 合并要求 +* Note +* 标签推送 +* Pipeline +* 维基页面 + +最后,填写您的 Microsoft Teams 详细信息: + +| Field | Description | +| --- | --- | +| **Webhook** | 您必须在 Microsoft Teams 上设置的传入 Webhook URL. | +| **仅通知断开的管道** | 如果您选择启用**管道**事件,并且只希望收到有关失败管道的通知. | + +完成所有操作后,单击" **保存更改"**以使更改生效. + +[![Microsoft Teams configuration](img/114dc1abb6412aca14f3c3b6ad3048dc.png)](img/microsoft_teams_configuration.png) \ No newline at end of file diff --git a/docs/087.md b/docs/087.md new file mode 100644 index 0000000000000000000000000000000000000000..927e6eb42627a0fcec3a01714bc3e81b906f92f3 --- /dev/null +++ b/docs/087.md @@ -0,0 +1,17 @@ +# Mock CI Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/mock_ci.html](https://docs.gitlab.com/ee/user/project/integrations/mock_ci.html) + +# Mock CI Service[](#mock-ci-service "Permalink") + +**注意:仅当您处于开发环境中时,此服务才会列出!** + +要设置模拟 CI 服务服务器,请响应以下端点 + +* `commit_status`: `#{project.namespace.path}/#{project.path}/status/#{sha}.json` + * 让您的服务返回`200 { status: ['failed'|'canceled'|'running'|'pending'|'success'|'success-with-warnings'|'skipped'|'not_found'] }` + * 如果服务返回 404,则将其解释为`pending` +* `build_page`: `#{project.namespace.path}/#{project.path}/status/#{sha}` + * 构建链接到的位置,是否实施无关紧要 + +有关模拟 CI 服务器的示例,请参见[`gitlab-org/gitlab-mock-ci-service`](https://gitlab.com/gitlab-org/gitlab-mock-ci-service) \ No newline at end of file diff --git a/docs/088.md b/docs/088.md new file mode 100644 index 0000000000000000000000000000000000000000..01c2052085572359738fde6af4bb7d1d5bb5f018 --- /dev/null +++ b/docs/088.md @@ -0,0 +1,135 @@ +# Prometheus integration + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html) + +* [Enabling Prometheus Integration](#enabling-prometheus-integration) + * [Managed Prometheus on Kubernetes](#managed-prometheus-on-kubernetes) + * [Requirements](#requirements) + * [Getting started](#getting-started) + * [About managed Prometheus deployments](#about-managed-prometheus-deployments) + * [Manual configuration of Prometheus](#manual-configuration-of-prometheus) + * [Requirements](#requirements-1) + * [Getting started](#getting-started-1) + * [Configuration in GitLab](#configuration-in-gitlab) + * [Thanos configuration in GitLab](#thanos-configuration-in-gitlab) + * [Precedence with multiple Prometheus configurations](#precedence-with-multiple-prometheus-configurations) +* [Determining the performance impact of a merge](#determining-the-performance-impact-of-a-merge) + +# Prometheus integration[](#prometheus-integration "Permalink") + +在 GitLab 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8935) . + +GitLab 提供与[Prometheus 的](https://s0prometheus0io.icopy.site)强大集成,可直接在 GitLab 中监视您的应用程序的关键指标. 从 Prometheus 检索每个环境的度量,然后在 GitLab 界面中显示. + +[![Environment Dashboard](img/45cb073d466ec4a6fcb5a09d7f5f204c.png)](img/prometheus_dashboard.png) + +有两种方法可以设置 Prometheus 集成,具体取决于应用程序的运行位置: + +* 对于在 Kubernetes 上的部署,GitLab 可以自动[部署和管理 Prometheus](#managed-prometheus-on-kubernetes) . +* 对于其他部署目标,只需[指定 Prometheus 服务器](#manual-configuration-of-prometheus) . + +启用后,GitLab 将自动从[度量标准库](prometheus_library/index.html)中的已知服务中检测度量[标准](prometheus_library/index.html) . 您还可以[添加自己的指标](../../../operations/metrics/index.html#adding-custom-metrics)并创建[自定义仪表板](../../../operations/metrics/dashboards/index.html) . + +## Enabling Prometheus Integration[](#enabling-prometheus-integration "Permalink") + +### Managed Prometheus on Kubernetes[](#managed-prometheus-on-kubernetes "Permalink") + +在 GitLab 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28916) . + +GitLab 可以在[连接的 Kubernetes 集群](../clusters/index.html)上无缝部署和管理 Prometheus,从而使对应用程序的监视变得容易. + +#### Requirements[](#requirements "Permalink") + +* A [connected Kubernetes cluster](../clusters/index.html) + +#### Getting started[](#getting-started "Permalink") + +拥有连接的 Kubernetes 集群后,只需单击即可轻松部署托管的 Prometheus. + +1. 转到**操作> Kubernetes**页面以查看已连接的集群 +2. 选择您要部署 Prometheus 的集群 +3. 单击**安装**按钮以将 Prometheus 部署到群集 + +[![Managed Prometheus Deploy](img/a198157b454aaa7b52001592ed46dc03.png)](img/prometheus_deploy.png) + +#### About managed Prometheus deployments[](#about-managed-prometheus-deployments "Permalink") + +使用[官方 Helm 图表](https://github.com/helm/charts/tree/master/stable/prometheus)将 Prometheus 部署到`gitlab-managed-apps`命名空间中. Prometheus 仅可在集群中访问,并且 GitLab 通过[Kubernetes API 进行](https://kubernetes.io/docs/concepts/overview/kubernetes-api/)通信. + +Prometheus 服务器将[自动检测和监视](https://s0prometheus0io.icopy.site/docs/prometheus/latest/configuration/configuration/)节点,吊舱和端点. 要配置 Prometheus 监视的资源,只需设置以下[Kubernetes 批注](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) : + +* `prometheus.io/scrape`为`true`以启用对资源的监视. +* `prometheus.io/port`定义度量标准端点的端口. +* `prometheus.io/path`来定义度量标准端点的路径. 默认为`/metrics` . + +CPU 和内存使用情况受到监视,但是需要使用[命名约定](prometheus_library/kubernetes.html#specifying-the-environment)来确定环境. 如果您使用的是[Auto DevOps](../../../topics/autodevops/index.html) ,则会自动处理. + +由 GitLab 部署到群集的[NGINX Ingress](../clusters/index.html#installing-applications)会自动添加注释,以进行监视,以提供关键的响应指标:延迟,吞吐量和错误率. + +### Manual configuration of Prometheus[](#manual-configuration-of-prometheus "Permalink") + +#### Requirements[](#requirements-1 "Permalink") + +与 Prometheus 集成需要满足以下条件: + +1. GitLab 9.0 或更高版本 +2. 必须将 Prometheus 配置为收集[支持的指标之一](prometheus_library/index.html) +3. Each metric must be have a label to indicate the environment +4. GitLab 必须与 Prometheus 服务器具有网络连接 + +#### Getting started[](#getting-started-1 "Permalink") + +安装和配置 Prometheus 来监视应用程序非常简单. + +1. [Install Prometheus](https://s0prometheus0io.icopy.site/docs/prometheus/latest/installation/) +2. 设置[受支持的监视目标之一](prometheus_library/index.html) +3. 配置 Prometheus 服务器以[收集其指标](https://s0prometheus0io.icopy.site/docs/prometheus/latest/configuration/configuration/) + +#### Configuration in GitLab[](#configuration-in-gitlab "Permalink") + +GitLab 中 Prometheus 集成的实际配置非常简单. 您只需要与您要集成的 Prometheus 服务器的域名或 IP 地址. 如果 Prometheus 资源由 Google 的身份识别代理(IAP)保护,则可以传递其他信息,例如客户端 ID 和服务帐户凭据,GitLab 可以使用这些信息来访问资源. 有关从服务帐户进行身份验证的更多信息,请参见 Google 的" [从服务帐户](https://cloud.google.com/iap/docs/authentication-howto#authenticating_from_a_service_account)进行[身份验证"](https://cloud.google.com/iap/docs/authentication-howto#authenticating_from_a_service_account)文档. + +1. 导航至位于的" [集成"页面](overview.html#accessing-integrations) **设置>集成** . +2. 单击**Prometheus**服务. +3. 对于**API URL** ,请提供服务器的域名或 IP 地址,例如`http://prometheus.example.com/`或`http://192.0.2.1/` . +4. (可选)在**Google IAP Audience Client ID 中** ,提供受 Google IAP 保护的 Prometheus OAuth Client 的 Client ID. +5. (可选)在**Google IAP 服务帐户 JSON 中** ,提供被授权访问 Prometheus 资源的服务帐户凭据文件的内容. +6. Click **保存更改**. + +[![Configure Prometheus Service](img/c154238c63e38411889c5647b2cdf20e.png)](img/prometheus_manual_configuration_v13_2.png) + +#### Thanos configuration in GitLab[](#thanos-configuration-in-gitlab "Permalink") + +您可以使用 GitLab 将[Thanos](https://thanos.io/)配置为 Prometheus 的替代品. 您将需要与之集成的 Thanos 服务器的域名或 IP 地址. + +1. 导航到" [集成"页面](overview.html#accessing-integrations) . +2. 单击**Prometheus**服务. +3. 提供服务器的域名或 IP 地址,例如`http://thanos.example.com/`或`http://192.0.2.1/` . +4. Click **保存更改**. + +### Precedence with multiple Prometheus configurations[](#precedence-with-multiple-prometheus-configurations "Permalink") + +尽管可以同时启用 Prometheus 的[手动配置](#manual-configuration-of-prometheus)和[自动配置](#managed-prometheus-on-kubernetes) ,但仅使用其中之一: + +* 如果您已[在 Kubernetes 上](#managed-prometheus-on-kubernetes)启用了[Prometheus 手动配置](#manual-configuration-of-prometheus)和[托管的 Prometheus](#managed-prometheus-on-kubernetes) ,则手动配置优先,并用于从[仪表板](../../../operations/metrics/dashboards/index.html#defining-custom-dashboards-per-project)和[自定义指标](../../../operations/metrics/index.html#adding-custom-metrics)运行查询. +* 如果您已在**不同**级别(项目,组,实例)的 Kubernetes 集群上安装了托管的 Prometheus 应用程序,则集群的优先级中将描述[优先级的顺序](../../instance/clusters/index.html#cluster-precedence) . +* If you have managed Prometheus applications installed on multiple Kubernetes clusters at the **same** level, the Prometheus application of a cluster with a matching [environment scope](../../../ci/environments/index.html#scoping-environments-with-specs) is used. + +## Determining the performance impact of a merge[](#determining-the-performance-impact-of-a-merge "Permalink") + +版本历史 + +* 在 GitLab 9.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10408) . +* GitLab 9.3 添加了 30 分钟平均值的[数字比较](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/27439) . + +开发人员可以在合并请求工作流程中查看其更改对性能的影响. + +**Note:** Requires [Kubernetes](prometheus_library/kubernetes.html) metrics. + +将源分支部署到环境后,将出现迷你图和平均内存消耗的数值比较. 在迷你图上,圆点指示部署当前更改的时间,前后最多显示 30 分钟的性能数据. 比较结果显示了部署前后 30 分钟平均值之间的差异. 部署每个提交后,将更新此信息. + +合并并重新部署目标分支后,指标将切换为显示此修订版已部署到的新环境. + +性能数据将在 Prometheus 服务器上持久保存的时间内可用. + +[![Merge Request with Performance Impact](img/33cc6d96a283a4f1b3cc5b27da9fd1c4.png)](img/merge_request_performance.png) \ No newline at end of file diff --git a/docs/089.md b/docs/089.md new file mode 100644 index 0000000000000000000000000000000000000000..eed44e89c3c5f96f063a734fc8ccfcb8bcba2b00 --- /dev/null +++ b/docs/089.md @@ -0,0 +1,34 @@ +# Redmine Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/redmine.html](https://docs.gitlab.com/ee/user/project/integrations/redmine.html) + +* [Referencing issues in Redmine](#referencing-issues-in-redmine) + +# Redmine Service[](#redmine-service "Permalink") + +1. 要在项目中启用 Redmine 集成,请导航到[Integrations 页面](overview.html#accessing-integrations) ,单击**Redmine**服务,然后按照下表中的说明在页面上填写所需的详细信息. + + | Field | Description | + | --- | --- | + | `project_url` | Redmine 中与该 GitLab 项目链接的项目的 URL | + | `issues_url` | 链接到该 GitLab 项目的 Redmine 项目中问题的 URL. 请注意, `issues_url`在 URL 中需要`:id` . GitLab 使用此 ID 作为占位符来替换问题编号. | + | `new_issue_url` | 这是在 Redmine 中为与此 GitLab 项目链接的项目创建新发行版的 URL. **当前未使用此功能,并将在以后的版本中将其删除.** | + + 配置并启用 Redmine 后,您将在 GitLab 项目页面上看到 Redmine 链接,该链接将您带到适当的 Redmine 项目. + + 例如,下面是一个名为`gitlab-ci`的项目的配置. + + [![Redmine configuration](img/31f8f986b27020e646540b9595d026cd.png)](img/redmine_configuration.png) + +2. 要禁用项目中的内部问题跟踪系统,请导航至"常规"页面,展开[权限](../settings/index.html#sharing-and-permissions)部分,然后将" **问题"**切换切换为"禁用". + +## Referencing issues in Redmine[](#referencing-issues-in-redmine "Permalink") + +Redmine 中的问题可以通过两种替代方式进行引用: + +* `#<ID>` ,其中`<ID>`是数字(示例`#143` ). +* `<PROJECT>-<ID>` where `<PROJECT>` starts with a capital letter which is then followed by capital letters, numbers or underscores, and `<ID>` is a number (example `API_32-143`). + +如果您同时启用了内部和外部问题跟踪器,我们建议使用更长的格式. 如果您使用较短的格式,并且内部问题跟踪器中存在具有相同 ID 的问题,则内部问题将被链接. + +请注意, `<PROJECT>`部分将被忽略,链接始终指向`issues_url`指定的地址. \ No newline at end of file diff --git a/docs/090.md b/docs/090.md new file mode 100644 index 0000000000000000000000000000000000000000..b28f61eb886877688c4cf637676e7b83d5555107 --- /dev/null +++ b/docs/090.md @@ -0,0 +1,94 @@ +# Slack Notifications Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/slack.html](https://docs.gitlab.com/ee/user/project/integrations/slack.html) + +* [Slack configuration](#slack-configuration) +* [GitLab configuration](#gitlab-configuration) + * [Triggers available for Slack notifications](#triggers-available-for-slack-notifications) +* [Troubleshooting](#troubleshooting) + * [Something went wrong on our end](#something-went-wrong-on-our-end) + * [`certificate verify failed`](#certificate-verify-failed) + +# Slack Notifications Service[](#slack-notifications-service "Permalink") + +Slack Notifications Service 允许您的 GitLab 项目将事件(例如问题创建)作为通知发送到您现有的 Slack 团队. 设置 Slack 通知需要同时更改 Slack 和 GitLab 的配置. + +**注意:**您还可以使用 Slack 斜杠命令在 Slack 中控制 GitLab. 这是单独配置的[Slack 斜杠命令](slack_slash_commands.html) . + +## Slack configuration[](#slack-configuration "Permalink") + +1. 登录到 Slack 团队并[开始新的 Incoming WebHooks 配置](https://my.slack.com/services/new/incoming-webhook) . +2. 选择默认情况下将通知发送到的松弛通道. 单击**添加传入的 WebHooks 集成**按钮以添加配置. +3. 复制**Webhook URL** ,我们将在以后的 GitLab 配置中使用它. + +## GitLab configuration[](#gitlab-configuration "Permalink") + +1. Open your project’s page, and navigate to your project’s [Integrations page](overview.html#accessing-integrations) at **设置>集成**. +2. 选择**Slack Notifications**集成进行配置. +3. Click **启用整合**. +4. 在**Trigger 中** ,选中每种类型的 GitLab 事件的复选框,以将其发送给 Slack 作为通知. 有关完整列表,请参阅[可用于 Slack 通知的触发器](#triggers-available-for-slack-notifications) . 默认情况下,消息将发送到您在[Slack 集成](#slack-configuration)期间配置的通道. +5. (可选)要将消息发送到其他渠道,多个渠道或作为直接消息: + * 要将消息发送到频道,请输入 Slack 频道名称,以逗号分隔. + * 要发送直接消息,请使用在用户的 Slack 个人资料中找到的会员 ID.**注意:**不支持用户名和私人频道. +6. 在**Webhook 中** ,提供您从[Slack 集成](#slack-configuration)步骤复制的**Webhook** URL. +7. (可选)在**Username 中** ,提供发送通知的 Slack 机器人的用户名. +8. 选择**仅通知断开的管道**复选框以仅通知失败. +9. 在**要通知**的**分支中**选择框,选择要为其发送通知的分支类型. +10. Click **测试设置并保存更改**. + +您的 Slack 团队现在将开始按照配置接收 GitLab 事件通知. + +### Triggers available for Slack notifications[](#triggers-available-for-slack-notifications "Permalink") + +以下触发器可用于 Slack 通知: + +* **推送** :由推送到存储库触发. +* **问题** :在创建,更新或关闭问题时触发. +* **机密问题** :创建,更新或关闭机密问题时触发. +* **合并请求** :在创建,更新或合并合并请求时触发. +* **注意** :有人添加评论时触发. +* **机密注释** :当有人添加机密注释时触发. +* **标签推送** :将新标签推送到存储库时触发. +* **管道** :管道状态更改时触发. +* **Wiki 页面** :在创建或更新 Wiki 页面时触发. +* **部署** :在部署完成时触发. +* **警报** :记录新的唯一警报时触发. + +## Troubleshooting[](#troubleshooting "Permalink") + +如果您的 Slack 集成无法正常工作,请通过在[Sidekiq 日志中](../../../administration/logs.html#sidekiqlog)搜索与 Slack 服务相关的错误来开始故障排除. + +### Something went wrong on our end[](#something-went-wrong-on-our-end "Permalink") + +这是 GitLab UI 中显示的一般错误,其本身并没有多大意义. 查看[日志](../../../administration/logs.html#productionlog)以查找错误消息,并从那里继续进行故障排除. + +### `certificate verify failed`[](#certificate-verify-failed "Permalink") + +您可能会在 Sidekiq 日志中看到类似于以下内容的条目: + +``` +2019-01-10_13:22:08.42572 2019-01-10T13:22:08.425Z 6877 TID-abcdefg ProjectServiceWorker JID-3bade5fb3dd47a85db6d78c5 ERROR: {:class=>"ProjectServiceWorker", :service_class=>"SlackService", :message=>"SSL_connect returned=1 errno=0 state=error: certificate verify failed"} +``` + +GitLab 与 Slack 通信或 GitLab 与自身通信可能是一个问题. 前者的可能性较小,因为 Slack 的安全证书*希望*始终受到信任. 我们可以使用下面的 rails 控制台脚本来确定要处理的内容. + +``` +# start a rails console: +sudo gitlab-rails console -e production + +# or for source installs: +bundle exec rails console -e production +``` + +``` +# run this in the Rails console +# replace <SLACK URL> with your actual Slack URL +result = Net::HTTP.get(URI('https://<SLACK URL>'));0 + +# replace <GITLAB URL> with your actual GitLab URL +result = Net::HTTP.get(URI('https://<GITLAB URL>'));0 +``` + +如果 GitLab 不信任自身的 HTTPS 连接,则可能需要[将证书添加到 GitLab 的受信任证书中](https://docs.gitlab.com/omnibus/settings/ssl.html) . + +如果 GitLab 不信任与 Slack 的连接,则 GitLab OpenSSL 信任存储不正确. 一些典型的原因:使用`gitlab_rails['env'] = {"SSL_CERT_FILE" => "/path/to/file.pem"}`覆盖信任库,或不小心修改了默认的 CA 捆绑包`/opt/gitlab/embedded/ssl/certs/cacert.pem` . \ No newline at end of file diff --git a/docs/091.md b/docs/091.md new file mode 100644 index 0000000000000000000000000000000000000000..0ef904b13397d299b71b742336a046d3e995cae3 --- /dev/null +++ b/docs/091.md @@ -0,0 +1,32 @@ +# Slack slash commands + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/slack_slash_commands.html](https://docs.gitlab.com/ee/user/project/integrations/slack_slash_commands.html) + +* [Configuration](#configuration) +* [Usage](#usage) + +# Slack slash commands[](#slack-slash-commands-core-only "Permalink") + +在 GitLab 8.15 中引入. + +使用 Slack 斜杠命令,您可以控制 GitLab 并直接在 Slack 内部查看内容,而不必离开它. 这需要在 Slack 和 GitLab 中进行配置. + +GitLab 还可以将事件(例如, `issue created` )作为通知发送到 Slack. 这是单独配置的[Slack Notifications Service](slack.html) . + +**注意:**对于 GitLab.com,请改用[Slack 应用程序](gitlab_slack_application.html) . + +## Configuration[](#configuration "Permalink") + +1. Slack 斜杠命令的作用域是项目. 导航到项目设置中的" [集成"页面](overview.html#accessing-integrations) ,即" **项目">"设置">"集成"** . +2. 选择**Slack 斜杠命令**集成进行配置. 该页面包含完成 Slack 中配置所需的信息. 将此浏览器选项卡保持打开状态. +3. 打开一个新的浏览器选项卡,然后登录到您的 Slack 团队. [开始新的 Slash Commands 集成](https://my.slack.com/services/new/slash-commands) . +4. 输入触发条件. 我们建议您使用项目名称. 单击**添加斜线命令集成** . +5. 使用来自 GitLab 浏览器选项卡的信息来完成 Slack 配置页面中的其余字段. 特别是,URL 需要复制和粘贴. 单击" **保存集成"**以完成 Slack 中的配置. +6. 仍在 Slack 配置页面上,复制**令牌** . 返回到 GitLab 浏览器选项卡并粘贴**令牌** . +7. 确保启用了**活动**切换,然后单击**保存更改**以完成 GitLab 中的配置. + +[![Slack setup instructions](img/1e1a93a55568355165c7529b5326427b.png)](img/slack_setup.png) + +## Usage[](#usage "Permalink") + +现在,您可以使用[Slack 斜杠命令](../../../integration/slash_commands.html) . \ No newline at end of file diff --git a/docs/092.md b/docs/092.md new file mode 100644 index 0000000000000000000000000000000000000000..a5605351f301bf9db99f9fb8946388c5286094fc --- /dev/null +++ b/docs/092.md @@ -0,0 +1,70 @@ +# GitLab Slack application + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html) + +* [Slack App Directory](#slack-app-directory) +* [Configuration](#configuration) +* [Create a project alias for Slack](#create-a-project-alias-for-slack) +* [Usage](#usage) + +# GitLab Slack application[](#gitlab-slack-application-free-only "Permalink") + +版本历史 + +* 在 GitLab 9.4 中引入. +* 分发到 GitLab 10.2 中的 Slack App Directory. + +**注意:** GitLab Slack 应用程序仅可为 GitLab.com 配置. 它**不适**用于您可以配置[Slack 斜杠命令](slack_slash_commands.html)服务的本地安装. 我们正计划使该配置可用于所有的 GitLab 安装,但是没有 ETA-参见[#28164](https://gitlab.com/gitlab-org/gitlab/-/issues/28164) . + +Slack 提供了一个本机应用程序,您可以通过 GitLab.com 上项目的集成来启用它. + +## Slack App Directory[](#slack-app-directory "Permalink") + +为您的工作区启用 GitLab Slack 应用程序的最简单方法是从[Slack App Directory](https://slack.com/apps)安装[GitLab 应用](https://slack-platform.slack.com/apps/A676ADMV5-gitlab) [程序](https://slack.com/apps) . + +单击安装会将您带到[GitLab Slack 应用程序登录页面](https://gitlab.com/profile/slack/edit) ,您可以在其中选择一个项目来为其启用 GitLab Slack 应用程序. + +[![GitLab Slack application landing page](img/618f6f4ba2a434609a1a9de7a9725e49.png)](img/gitlab_slack_app_landing_page.png) + +## Configuration[](#configuration "Permalink") + +或者,您可以使用项目的集成设置来配置 Slack 应用程序. + +请记住,您需要拥有 Slack 团队的适当权限才能安装新应用程序,请阅读 Slack 文档中有关[将应用程序添加到工作区的更多信息](https://slack.com/help/articles/202035138-Add-an-app-to-your-workspace) . + +为您的 Slack 团队启用 GitLab 的服务: + +1. 转到项目的 **设置>集成> Slack 应用程序** (仅在 GitLab.com 上可见). +2. Click **添加到松弛**. + +就这样! 现在,您可以开始使用 Slack 斜杠命令. + +## Create a project alias for Slack[](#create-a-project-alias-for-slack "Permalink") + +要在 GitLab.com 上为 Slack 集成创建项目别名: + +1. 转到项目的主页. +2. 导航 **设置>集成** (仅在 GitLab.com 上可见) +3. 在" **集成"**页面上,单击**Slack application** . +4. 显示当前的**项目别名** (如果有). 要编辑此值,请点击**编辑** . +5. 输入所需的别名,然后点击**保存更改** . + +一些 Slack 命令需要项目别名,如果项目别名不正确或命令中缺少该别名,则会失败并显示以下错误: + +``` +GitLab error: project or alias not found +``` + +## Usage[](#usage "Permalink") + +确认安装后,您和您的 Slack 团队中的其他所有人都可以使用所有[slash 命令](../../../integration/slash_commands.html) . + +当您执行第一个斜杠命令时,将要求您在 GitLab.com 上授权您的 Slack 用户. + +与[手动配置的 Slack 斜杠命令](slack_slash_commands.html)的唯一区别在于,所有命令均应以`/gitlab`关键字为前缀. 我们正在努力使此配置在将来成为可能. + +例如,要显示`gitlab-org/gitlab`项目下的问题编号`1001` ,您可以执行以下操作: + +``` +/gitlab gitlab-org/gitlab issue show 1001 +``` \ No newline at end of file diff --git a/docs/093.md b/docs/093.md new file mode 100644 index 0000000000000000000000000000000000000000..f1b1c2e60e22e51f7308f294a40be1f4e82bba77 --- /dev/null +++ b/docs/093.md @@ -0,0 +1,366 @@ +# Webhooks + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/webhooks.html](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html) + +* [Overview](#overview) +* [Use-cases](#use-cases) +* [Webhook endpoint tips](#webhook-endpoint-tips) +* [Secret token](#secret-token) +* [SSL verification](#ssl-verification) +* [Branch filtering](#branch-filtering) +* [Events](#events) + * [Push events](#push-events) + * [Tag events](#tag-events) + * [Issue events](#issue-events) + * [Comment events](#comment-events) + * [Comment on commit](#comment-on-commit) + * [Comment on merge request](#comment-on-merge-request) + * [Comment on issue](#comment-on-issue) + * [Comment on code snippet](#comment-on-code-snippet) + * [Merge request events](#merge-request-events) + * [Wiki Page events](#wiki-page-events) + * [Pipeline events](#pipeline-events) + * [Job events](#job-events) +* [Image URL rewriting](#image-url-rewriting) +* [Testing webhooks](#testing-webhooks) +* [Troubleshoot webhooks](#troubleshoot-webhooks) + * [Receiving duplicate or multiple webhook requests triggered by one event](#receiving-duplicate-or-multiple-webhook-requests-triggered-by-one-event) + * [Troubleshooting: “Unable to get local issuer certificate”](#troubleshooting-unable-to-get-local-issuer-certificate) +* [Example webhook receiver](#example-webhook-receiver) + +# Webhooks[](#webhooks "Permalink") + +> **注意:**从 GitLab 8.5 开始: +> +> * 不推荐使用`repository`密钥,而推荐使用`project`密钥 +> * 不推荐使用`project.ssh_url`密钥,而推荐使用`project.git_ssh_url`密钥 +> * 不推荐使用`project.http_url`键,而推荐使用`project.git_http_url`键 +> +> **注意:**从 GitLab 11.1 开始,一个月后会自动删除 Webhooks 的日志. +> +> **注意:**从 GitLab 11.2 开始: +> +> * 重写问题,合并请求,评论和 Wiki 页面的`description`字段,以便简单的 Markdown 图像引用(如`![](/uploads/...)` )将其目标 URL 更改为绝对 URL. 有关更多详细信息,请参见[图像 URL 重写](#image-url-rewriting) . + +通过项目 webhooks,您可以在例如推送新代码或创建新问题时触发 URL. 您可以将 webhook 配置为侦听特定事件,例如推送,问题或合并请求. GitLab 会将带有数据的 POST 请求发送到 webhook URL. + +在大多数情况下,您需要设置自己的[Webhook 接收器](#example-webhook-receiver)以从 GitLab 接收信息,然后根据需要将其发送到另一个应用程序. 我们已经有一个[内置接收器,](slack.html)用于*每个项目*发送[Slack](https://api.slack.com/incoming-webhooks)通知. + +## Overview[](#overview "Permalink") + +[Webhooks](https://en.wikipedia.org/wiki/Webhook)是" *用户定义的 HTTP 回调* ". 它们通常是由某些事件触发的,例如将代码推送到存储库或将评论发布到博客. 发生该事件时,源应用程序向为 Webhook 配置的 URI 发出 HTTP 请求. 采取的措施可能是任何事情. 常见用途是触发具有持续集成系统的构建或通知错误跟踪系统. + +Webhooks 可用于更新外部问题跟踪器,触发 CI 作业,更新备份镜像,甚至部署到您的生产服务器. 他们**每个项目**可以 GitLab 社区版,以及**每个项目和每个组** **GitLab 企业版** . + +通过转到项目的**设置➔Webhooks**导航到 webhooks 页面. + +**注意:**在 GitLab.com 上,每个项目和每个组的[最大 Webhooks 数量](../../../user/gitlab_com/index.html#maximum-number-of-webhooks)是有限的. + +## Use-cases[](#use-cases "Permalink") + +* 您可以在 GitLab 中设置一个 Webhook,以在每次作业失败时向[Slack](https://api.slack.com/incoming-webhooks)发送通知. +* 每当在 GitLab 中为特定项目或组创建问题时,您都可以[与 Twilio 集成以通过 SMS 收到通知](https://www.datadoghq.com/blog/send-alerts-sms-customizable-webhooks-twilio/) +* You can use them to [automatically assign labels to merge requests](https://about.gitlab.com/blog/2016/08/19/applying-gitlab-labels-automatically/). + +## Webhook endpoint tips[](#webhook-endpoint-tips "Permalink") + +如果您正在编写自己的将接收 GitLab webhooks 的端点(Web 服务器),请记住以下几点: + +* 您的端点应尽快发送其 HTTP 响应. 如果等待时间太长,GitLab 可能会确定挂钩失败并重试. +* 您的端点应始终返回有效的 HTTP 响应. 如果您不这样做,则 GitLab 会认为挂钩失败并重试. 大多数 HTTP 库会自动为您处理此问题,但是如果您正在编写低级钩子,记住这一点很重要. +* GitLab 会忽略端点返回的 HTTP 状态代码. + +## Secret token[](#secret-token "Permalink") + +如果您指定一个秘密令牌,它将与挂钩请求一起在`X-Gitlab-Token` HTTP 标头中发送. 您的 webhook 端点可以检查以验证请求是否合法. + +## SSL verification[](#ssl-verification "Permalink") + +默认情况下,将基于证书颁发机构的内部列表来验证 webhook 端点的 SSL 证书,这意味着该证书无法进行自签名. + +您可以在 GitLab 项目的 webhook 设置中将其关闭. + +[![SSL Verification](img/e7d35854d0a726fbc4756cca4de4bf77.png)](img/webhooks_ssl.png) + +## Branch filtering[](#branch-filtering "Permalink") + +在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20338) . + +可以使用分支名称或通配符模式按分支过滤推送事件,以限制将哪些推送事件发送到您的 Webhook 端点. 默认情况下,该字段为空白,导致所有推送事件都发送到您的 Webhook 端点. + +## Events[](#events "Permalink") + +下面介绍了受支持的事件. + +### Push events[](#push-events "Permalink") + +当您推送到存储库时(推送标签时除外)触发. + +**注意:**一次推送超过 20 个提交时,出于性能原因, `commits` webhook 属性将仅包含前 20 个. 加载详细的提交数据非常昂贵. 请注意,尽管`commits`属性中仅存在 20 个提交,但`total_commits_count`属性将包含实际总数. + +另外,如果单个推送包含三个以上分支的更改(默认情况下,取决于[`push_event_hooks_limit`设置](../../../api/settings.html#list-of-settings-that-can-be-accessed-via-api-calls) ),则不会执行此挂钩. + +**请求标头**: + +``` +X-Gitlab-Event: Push Hook +``` + +**要求正文:** + +``` +{ "object_kind": "push", "before": "95790bf891e76fee5e1747ab589903a6a1f80f22", "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "ref": "refs/heads/master", "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "user_id": 4, "user_name": "John Smith", "user_username": "jsmith", "user_email": "john@example.com", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 15, "project":{ "id": 15, "name":"Diaspora", "description":"", "web_url":"http://example.com/mike/diaspora", "avatar_url":null, "git_ssh_url":"git@example.com:mike/diaspora.git", "git_http_url":"http://example.com/mike/diaspora.git", "namespace":"Mike", "visibility_level":0, "path_with_namespace":"mike/diaspora", "default_branch":"master", "homepage":"http://example.com/mike/diaspora", "url":"git@example.com:mike/diaspora.git", "ssh_url":"git@example.com:mike/diaspora.git", "http_url":"http://example.com/mike/diaspora.git" }, "repository":{ "name": "Diaspora", "url": "git@example.com:mike/diaspora.git", "description": "", "homepage": "http://example.com/mike/diaspora", "git_http_url":"http://example.com/mike/diaspora.git", "git_ssh_url":"git@example.com:mike/diaspora.git", "visibility_level":0 }, "commits": [ { "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", "message": "Update Catalan translation to e38cb41.\n\nSee https://gitlab.com/gitlab-org/gitlab for more information", "title": "Update Catalan translation to e38cb41.", "timestamp": "2011-12-12T14:27:31+02:00", "url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", "author": { "name": "Jordi Mallach", "email": "jordi@softcatala.org" }, "added": ["CHANGELOG"], "modified": ["app/controller/application.rb"], "removed": [] }, { "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "message": "fixed readme", "title": "fixed readme", "timestamp": "2012-01-03T23:36:29+02:00", "url": "http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "author": { "name": "GitLab dev user", "email": "gitlabdev@dv6700.(none)" }, "added": ["CHANGELOG"], "modified": ["app/controller/application.rb"], "removed": [] } ], "total_commits_count": 4 } +``` + +### Tag events[](#tag-events "Permalink") + +在创建(或删除)存储库标签时触发. + +**注意:**如果单个推送包含三个以上的更改(默认情况下,取决于[`push_event_hooks_limit`设置](../../../api/settings.html#list-of-settings-that-can-be-accessed-via-api-calls) ),则不会执行此挂钩. + +**请求标头**: + +``` +X-Gitlab-Event: Tag Push Hook +``` + +**要求正文:** + +``` +{ "object_kind": "tag_push", "before": "0000000000000000000000000000000000000000", "after": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7", "ref": "refs/tags/v1.0.0", "checkout_sha": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7", "user_id": 1, "user_name": "John Smith", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 1, "project":{ "id": 1, "name":"Example", "description":"", "web_url":"http://example.com/jsmith/example", "avatar_url":null, "git_ssh_url":"git@example.com:jsmith/example.git", "git_http_url":"http://example.com/jsmith/example.git", "namespace":"Jsmith", "visibility_level":0, "path_with_namespace":"jsmith/example", "default_branch":"master", "homepage":"http://example.com/jsmith/example", "url":"git@example.com:jsmith/example.git", "ssh_url":"git@example.com:jsmith/example.git", "http_url":"http://example.com/jsmith/example.git" }, "repository":{ "name": "Example", "url": "ssh://git@example.com/jsmith/example.git", "description": "", "homepage": "http://example.com/jsmith/example", "git_http_url":"http://example.com/jsmith/example.git", "git_ssh_url":"git@example.com:jsmith/example.git", "visibility_level":0 }, "commits": [], "total_commits_count": 0 } +``` + +### Issue events[](#issue-events "Permalink") + +在创建新问题或更新/关闭/重新打开现有问题时触发. + +**请求标头**: + +``` +X-Gitlab-Event: Issue Hook +``` + +**要求正文:** + +``` +{ "object_kind": "issue", "event_type": "issue", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", "email": "admin@example.com" }, "project": { "id": 1, "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlabhq/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", "git_http_url":"http://example.com/gitlabhq/gitlab-test.git", "namespace":"GitlabHQ", "visibility_level":20, "path_with_namespace":"gitlabhq/gitlab-test", "default_branch":"master", "ci_config_path": null, "homepage":"http://example.com/gitlabhq/gitlab-test", "url":"http://example.com/gitlabhq/gitlab-test.git", "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", "http_url":"http://example.com/gitlabhq/gitlab-test.git" }, "object_attributes": { "id": 301, "title": "New API: create/update/delete file", "assignee_ids": [51], "assignee_id": 51, "author_id": 51, "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "updated_by_id": 1, "last_edited_at": null, "last_edited_by_id": null, "relative_position": 0, "description": "Create new API for manipulations with repository", "milestone_id": null, "state_id": 1, "confidential": false, "discussion_locked": true, "due_date": null, "moved_to_id": null, "duplicated_to_id": null, "time_estimate": 0, "total_time_spent": 0, "human_total_time_spent": null, "human_time_estimate": null, "weight": null, "iid": 23, "url": "http://example.com/diaspora/issues/23", "state": "opened", "action": "open", "labels": [{ "id": 206, "title": "API", "color": "#ffffff", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "API related issues", "type": "ProjectLabel", "group_id": 41 }] }, "repository": { "name": "Gitlab Test", "url": "http://example.com/gitlabhq/gitlab-test.git", "description": "Aut reprehenderit ut est.", "homepage": "http://example.com/gitlabhq/gitlab-test" }, "assignees": [{ "name": "User1", "username": "user1", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }], "assignee": { "name": "User1", "username": "user1", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "labels": [{ "id": 206, "title": "API", "color": "#ffffff", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "API related issues", "type": "ProjectLabel", "group_id": 41 }], "changes": { "updated_by_id": { "previous": null, "current": 1 }, "updated_at": { "previous": "2017-09-15 16:50:55 UTC", "current": "2017-09-15 16:52:00 UTC" }, "labels": { "previous": [{ "id": 206, "title": "API", "color": "#ffffff", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "API related issues", "type": "ProjectLabel", "group_id": 41 }], "current": [{ "id": 205, "title": "Platform", "color": "#123123", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "Platform related issues", "type": "ProjectLabel", "group_id": 41 }] } } } +``` + +> **注意** :不赞成使用`assignee`和`assignee_id`键,现在仅显示第一个受让人. + +### Comment events[](#comment-events "Permalink") + +在对提交,合并请求,问题和代码段进行新注释时触发. 音符数据将被存储在`object_attributes` (如`note` , `noteable_type` ). 有效负载还将包括有关注释目标的信息. 例如,对问题的评论将在`issue`密钥下包括特定的问题信息. 有效的目标类型: + +* `commit` +* `merge_request` +* `issue` +* `snippet` + +#### Comment on commit[](#comment-on-commit "Permalink") + +**Request header**: + +``` +X-Gitlab-Event: Note Hook +``` + +**要求正文:** + +``` +{ "object_kind": "note", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "project_id": 5, "project":{ "id": 5, "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlabhq/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", "git_http_url":"http://example.com/gitlabhq/gitlab-test.git", "namespace":"GitlabHQ", "visibility_level":20, "path_with_namespace":"gitlabhq/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlabhq/gitlab-test", "url":"http://example.com/gitlabhq/gitlab-test.git", "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", "http_url":"http://example.com/gitlabhq/gitlab-test.git" }, "repository":{ "name": "Gitlab Test", "url": "http://example.com/gitlab-org/gitlab-test.git", "description": "Aut reprehenderit ut est.", "homepage": "http://example.com/gitlab-org/gitlab-test" }, "object_attributes": { "id": 1243, "note": "This is a commit comment. How does this work?", "noteable_type": "Commit", "author_id": 1, "created_at": "2015-05-17 18:08:09 UTC", "updated_at": "2015-05-17 18:08:09 UTC", "project_id": 5, "attachment":null, "line_code": "bec9703f7a456cd2b4ab5fb3220ae016e3e394e3_0_1", "commit_id": "cfe32cf61b73a0d5e9f13e774abde7ff789b1660", "noteable_id": null, "system": false, "st_diff": { "diff": "--- /dev/null\n+++ b/six\n@@ -0,0 +1 @@\n+Subproject commit 409f37c4f05865e4fb208c771485f211a22c4c2d\n", "new_path": "six", "old_path": "six", "a_mode": "0", "b_mode": "160000", "new_file": true, "renamed_file": false, "deleted_file": false }, "url": "http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660#note_1243" }, "commit": { "id": "cfe32cf61b73a0d5e9f13e774abde7ff789b1660", "message": "Add submodule\n\nSigned-off-by: Example User \u003cuser@example.com.com\u003e\n", "timestamp": "2014-02-27T10:06:20+02:00", "url": "http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660", "author": { "name": "Example User", "email": "user@example.com" } } } +``` + +#### Comment on merge request[](#comment-on-merge-request "Permalink") + +**请求标头**: + +``` +X-Gitlab-Event: Note Hook +``` + +**要求正文:** + +``` +{ "object_kind": "note", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "project_id": 5, "project":{ "id": 5, "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlab-org/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", "namespace":"Gitlab Org", "visibility_level":10, "path_with_namespace":"gitlab-org/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlab-org/gitlab-test", "url":"http://example.com/gitlab-org/gitlab-test.git", "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "http_url":"http://example.com/gitlab-org/gitlab-test.git" }, "repository":{ "name": "Gitlab Test", "url": "http://localhost/gitlab-org/gitlab-test.git", "description": "Aut reprehenderit ut est.", "homepage": "http://example.com/gitlab-org/gitlab-test" }, "object_attributes": { "id": 1244, "note": "This MR needs work.", "noteable_type": "MergeRequest", "author_id": 1, "created_at": "2015-05-17 18:21:36 UTC", "updated_at": "2015-05-17 18:21:36 UTC", "project_id": 5, "attachment": null, "line_code": null, "commit_id": "", "noteable_id": 7, "system": false, "st_diff": null, "url": "http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244" }, "merge_request": { "id": 7, "target_branch": "markdown", "source_branch": "master", "source_project_id": 5, "author_id": 8, "assignee_id": 28, "title": "Tempora et eos debitis quae laborum et.", "created_at": "2015-03-01 20:12:53 UTC", "updated_at": "2015-03-21 18:27:27 UTC", "milestone_id": 11, "state": "opened", "merge_status": "cannot_be_merged", "target_project_id": 5, "iid": 1, "description": "Et voluptas corrupti assumenda temporibus. Architecto cum animi eveniet amet asperiores. Vitae numquam voluptate est natus sit et ad id.", "position": 0, "source":{ "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlab-org/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", "namespace":"Gitlab Org", "visibility_level":10, "path_with_namespace":"gitlab-org/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlab-org/gitlab-test", "url":"http://example.com/gitlab-org/gitlab-test.git", "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "http_url":"http://example.com/gitlab-org/gitlab-test.git" }, "target": { "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlab-org/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", "namespace":"Gitlab Org", "visibility_level":10, "path_with_namespace":"gitlab-org/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlab-org/gitlab-test", "url":"http://example.com/gitlab-org/gitlab-test.git", "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "http_url":"http://example.com/gitlab-org/gitlab-test.git" }, "last_commit": { "id": "562e173be03b8ff2efb05345d12df18815438a4b", "message": "Merge branch 'another-branch' into 'master'\n\nCheck in this test\n", "timestamp": "2015-04-08T21: 00:25-07:00", "url": "http://example.com/gitlab-org/gitlab-test/commit/562e173be03b8ff2efb05345d12df18815438a4b", "author": { "name": "John Smith", "email": "john@example.com" } }, "work_in_progress": false, "assignee": { "name": "User1", "username": "user1", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" } } } +``` + +#### Comment on issue[](#comment-on-issue "Permalink") + +**请求标头**: + +``` +X-Gitlab-Event: Note Hook +``` + +**要求正文:** + +``` +{ "object_kind": "note", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "project_id": 5, "project":{ "id": 5, "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlab-org/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", "namespace":"Gitlab Org", "visibility_level":10, "path_with_namespace":"gitlab-org/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlab-org/gitlab-test", "url":"http://example.com/gitlab-org/gitlab-test.git", "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "http_url":"http://example.com/gitlab-org/gitlab-test.git" }, "repository":{ "name":"diaspora", "url":"git@example.com:mike/diaspora.git", "description":"", "homepage":"http://example.com/mike/diaspora" }, "object_attributes": { "id": 1241, "note": "Hello world", "noteable_type": "Issue", "author_id": 1, "created_at": "2015-05-17 17:06:40 UTC", "updated_at": "2015-05-17 17:06:40 UTC", "project_id": 5, "attachment": null, "line_code": null, "commit_id": "", "noteable_id": 92, "system": false, "st_diff": null, "url": "http://example.com/gitlab-org/gitlab-test/issues/17#note_1241" }, "issue": { "id": 92, "title": "test", "assignee_ids": [], "assignee_id": null, "author_id": 1, "project_id": 5, "created_at": "2015-04-12 14:53:17 UTC", "updated_at": "2015-04-26 08:28:42 UTC", "position": 0, "branch_name": null, "description": "test", "milestone_id": null, "state": "closed", "iid": 17, "labels": [ { "id": 25, "title": "Afterpod", "color": "#3e8068", "project_id": null, "created_at": "2019-06-05T14:32:20.211Z", "updated_at": "2019-06-05T14:32:20.211Z", "template": false, "description": null, "type": "GroupLabel", "group_id": 4 }, { "id": 86, "title": "Element", "color": "#231afe", "project_id": 4, "created_at": "2019-06-05T14:32:20.637Z", "updated_at": "2019-06-05T14:32:20.637Z", "template": false, "description": null, "type": "ProjectLabel", "group_id": null } ], } } +``` + +> **注意** :不建议使用`assignee_id`字段,现在仅显示第一个受让人. + +#### Comment on code snippet[](#comment-on-code-snippet "Permalink") + +**请求标头**: + +``` +X-Gitlab-Event: Note Hook +``` + +**要求正文:** + +``` +{ "object_kind": "note", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "project_id": 5, "project":{ "id": 5, "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlab-org/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", "namespace":"Gitlab Org", "visibility_level":10, "path_with_namespace":"gitlab-org/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlab-org/gitlab-test", "url":"http://example.com/gitlab-org/gitlab-test.git", "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", "http_url":"http://example.com/gitlab-org/gitlab-test.git" }, "repository":{ "name":"Gitlab Test", "url":"http://example.com/gitlab-org/gitlab-test.git", "description":"Aut reprehenderit ut est.", "homepage":"http://example.com/gitlab-org/gitlab-test" }, "object_attributes": { "id": 1245, "note": "Is this snippet doing what it's supposed to be doing?", "noteable_type": "Snippet", "author_id": 1, "created_at": "2015-05-17 18:35:50 UTC", "updated_at": "2015-05-17 18:35:50 UTC", "project_id": 5, "attachment": null, "line_code": null, "commit_id": "", "noteable_id": 53, "system": false, "st_diff": null, "url": "http://example.com/gitlab-org/gitlab-test/snippets/53#note_1245" }, "snippet": { "id": 53, "title": "test", "content": "puts 'Hello world'", "author_id": 1, "project_id": 5, "created_at": "2015-04-09 02:40:38 UTC", "updated_at": "2015-04-09 02:40:38 UTC", "file_name": "test.rb", "expires_at": null, "type": "ProjectSnippet", "visibility_level": 0 } } +``` + +### Merge request events[](#merge-request-events "Permalink") + +在创建新的合并请求,更新/合并/关闭现有合并请求或在源分支中添加提交时触发. + +**请求标头**: + +``` +X-Gitlab-Event: Merge Request Hook +``` + +**要求正文:** + +``` +{ "object_kind": "merge_request", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "project": { "id": 1, "name":"Gitlab Test", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/gitlabhq/gitlab-test", "avatar_url":null, "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", "git_http_url":"http://example.com/gitlabhq/gitlab-test.git", "namespace":"GitlabHQ", "visibility_level":20, "path_with_namespace":"gitlabhq/gitlab-test", "default_branch":"master", "homepage":"http://example.com/gitlabhq/gitlab-test", "url":"http://example.com/gitlabhq/gitlab-test.git", "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", "http_url":"http://example.com/gitlabhq/gitlab-test.git" }, "repository": { "name": "Gitlab Test", "url": "http://example.com/gitlabhq/gitlab-test.git", "description": "Aut reprehenderit ut est.", "homepage": "http://example.com/gitlabhq/gitlab-test" }, "object_attributes": { "id": 99, "target_branch": "master", "source_branch": "ms-viewport", "source_project_id": 14, "author_id": 51, "assignee_id": 6, "title": "MS-Viewport", "created_at": "2013-12-03T17:23:34Z", "updated_at": "2013-12-03T17:23:34Z", "milestone_id": null, "state": "opened", "merge_status": "unchecked", "target_project_id": 14, "iid": 1, "description": "", "source": { "name":"Awesome Project", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/awesome_space/awesome_project", "avatar_url":null, "git_ssh_url":"git@example.com:awesome_space/awesome_project.git", "git_http_url":"http://example.com/awesome_space/awesome_project.git", "namespace":"Awesome Space", "visibility_level":20, "path_with_namespace":"awesome_space/awesome_project", "default_branch":"master", "homepage":"http://example.com/awesome_space/awesome_project", "url":"http://example.com/awesome_space/awesome_project.git", "ssh_url":"git@example.com:awesome_space/awesome_project.git", "http_url":"http://example.com/awesome_space/awesome_project.git" }, "target": { "name":"Awesome Project", "description":"Aut reprehenderit ut est.", "web_url":"http://example.com/awesome_space/awesome_project", "avatar_url":null, "git_ssh_url":"git@example.com:awesome_space/awesome_project.git", "git_http_url":"http://example.com/awesome_space/awesome_project.git", "namespace":"Awesome Space", "visibility_level":20, "path_with_namespace":"awesome_space/awesome_project", "default_branch":"master", "homepage":"http://example.com/awesome_space/awesome_project", "url":"http://example.com/awesome_space/awesome_project.git", "ssh_url":"git@example.com:awesome_space/awesome_project.git", "http_url":"http://example.com/awesome_space/awesome_project.git" }, "last_commit": { "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "message": "fixed readme", "timestamp": "2012-01-03T23:36:29+02:00", "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "author": { "name": "GitLab dev user", "email": "gitlabdev@dv6700.(none)" } }, "work_in_progress": false, "url": "http://example.com/diaspora/merge_requests/1", "action": "open", "assignee": { "name": "User1", "username": "user1", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" } }, "labels": [{ "id": 206, "title": "API", "color": "#ffffff", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "API related issues", "type": "ProjectLabel", "group_id": 41 }], "changes": { "updated_by_id": { "previous": null, "current": 1 }, "updated_at": { "previous": "2017-09-15 16:50:55 UTC", "current":"2017-09-15 16:52:00 UTC" }, "labels": { "previous": [{ "id": 206, "title": "API", "color": "#ffffff", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "API related issues", "type": "ProjectLabel", "group_id": 41 }], "current": [{ "id": 205, "title": "Platform", "color": "#123123", "project_id": 14, "created_at": "2013-12-03T17:15:43Z", "updated_at": "2013-12-03T17:15:43Z", "template": false, "description": "Platform related issues", "type": "ProjectLabel", "group_id": 41 }] } } } +``` + +### Wiki Page events[](#wiki-page-events "Permalink") + +在创建,更新或删除 Wiki 页面时触发. + +**请求标题**: + +``` +X-Gitlab-Event: Wiki Page Hook +``` + +**请求正文**: + +``` +{ "object_kind": "wiki_page", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon" }, "project": { "id": 1, "name": "awesome-project", "description": "This is awesome", "web_url": "http://example.com/root/awesome-project", "avatar_url": null, "git_ssh_url": "git@example.com:root/awesome-project.git", "git_http_url": "http://example.com/root/awesome-project.git", "namespace": "root", "visibility_level": 0, "path_with_namespace": "root/awesome-project", "default_branch": "master", "homepage": "http://example.com/root/awesome-project", "url": "git@example.com:root/awesome-project.git", "ssh_url": "git@example.com:root/awesome-project.git", "http_url": "http://example.com/root/awesome-project.git" }, "wiki": { "web_url": "http://example.com/root/awesome-project/-/wikis/home", "git_ssh_url": "git@example.com:root/awesome-project.wiki.git", "git_http_url": "http://example.com/root/awesome-project.wiki.git", "path_with_namespace": "root/awesome-project.wiki", "default_branch": "master" }, "object_attributes": { "title": "Awesome", "content": "awesome content goes here", "format": "markdown", "message": "adding an awesome page to the wiki", "slug": "awesome", "url": "http://example.com/root/awesome-project/-/wikis/awesome", "action": "create" } } +``` + +### Pipeline events[](#pipeline-events "Permalink") + +在管道状态更改时触发. + +**请求标题**: + +``` +X-Gitlab-Event: Pipeline Hook +``` + +**请求正文**: + +``` +{ "object_kind": "pipeline", "object_attributes":{ "id": 31, "ref": "master", "tag": false, "sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2", "before_sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2", "source": "merge_request_event", "status": "success", "stages":[ "build", "test", "deploy" ], "created_at": "2016-08-12 15:23:28 UTC", "finished_at": "2016-08-12 15:26:29 UTC", "duration": 63, "variables": [ { "key": "NESTOR_PROD_ENVIRONMENT", "value": "us-west-1" } ] }, "merge_request": { "id": 1, "iid": 1, "title": "Test", "source_branch": "test", "source_project_id": 1, "target_branch": "master", "target_project_id": 1, "state": "opened", "merge_status": "can_be_merged", "url": "http://192.168.64.1:3005/gitlab-org/gitlab-test/merge_requests/1" }, "user":{ "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", "email": "user_email@gitlab.com" }, "project":{ "id": 1, "name": "Gitlab Test", "description": "Atque in sunt eos similique dolores voluptatem.", "web_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test", "avatar_url": null, "git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git", "git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git", "namespace": "Gitlab Org", "visibility_level": 20, "path_with_namespace": "gitlab-org/gitlab-test", "default_branch": "master" }, "commit":{ "id": "bcbb5ec396a2c0f828686f14fac9b80b780504f2", "message": "test\n", "timestamp": "2016-08-12T17:23:21+02:00", "url": "http://example.com/gitlab-org/gitlab-test/commit/bcbb5ec396a2c0f828686f14fac9b80b780504f2", "author":{ "name": "User", "email": "user@gitlab.com" } }, "builds":[ { "id": 380, "stage": "deploy", "name": "production", "status": "skipped", "created_at": "2016-08-12 15:23:28 UTC", "started_at": null, "finished_at": null, "when": "manual", "manual": true, "allow_failure": false, "user":{ "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" }, "runner": null, "artifacts_file":{ "filename": null, "size": null } }, { "id": 377, "stage": "test", "name": "test-image", "status": "success", "created_at": "2016-08-12 15:23:28 UTC", "started_at": "2016-08-12 15:26:12 UTC", "finished_at": null, "when": "on_success", "manual": false, "allow_failure": false, "user":{ "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" }, "runner": { "id":380987, "description":"shared-runners-manager-6.gitlab.com", "active":true, "is_shared":true }, "artifacts_file":{ "filename": null, "size": null } }, { "id": 378, "stage": "test", "name": "test-build", "status": "success", "created_at": "2016-08-12 15:23:28 UTC", "started_at": "2016-08-12 15:26:12 UTC", "finished_at": "2016-08-12 15:26:29 UTC", "when": "on_success", "manual": false, "allow_failure": false, "user":{ "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" }, "runner": { "id":380987, "description":"shared-runners-manager-6.gitlab.com", "active":true, "is_shared":true }, "artifacts_file":{ "filename": null, "size": null } }, { "id": 376, "stage": "build", "name": "build-image", "status": "success", "created_at": "2016-08-12 15:23:28 UTC", "started_at": "2016-08-12 15:24:56 UTC", "finished_at": "2016-08-12 15:25:26 UTC", "when": "on_success", "manual": false, "allow_failure": false, "user":{ "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" }, "runner": { "id":380987, "description":"shared-runners-manager-6.gitlab.com", "active":true, "is_shared":true }, "artifacts_file":{ "filename": null, "size": null } }, { "id": 379, "stage": "deploy", "name": "staging", "status": "created", "created_at": "2016-08-12 15:23:28 UTC", "started_at": null, "finished_at": null, "when": "on_success", "manual": false, "allow_failure": false, "user":{ "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" }, "runner": null, "artifacts_file":{ "filename": null, "size": null } } ] } +``` + +### Job events[](#job-events "Permalink") + +在工作状态更改时触发. + +**请求标题**: + +``` +X-Gitlab-Event: Job Hook +``` + +**请求正文**: + +``` +{ "object_kind": "build", "ref": "gitlab-script-trigger", "tag": false, "before_sha": "2293ada6b400935a1378653304eaf6221e0fdb8f", "sha": "2293ada6b400935a1378653304eaf6221e0fdb8f", "build_id": 1977, "build_name": "test", "build_stage": "test", "build_status": "created", "build_started_at": null, "build_finished_at": null, "build_duration": null, "build_allow_failure": false, "build_failure_reason": "script_failure", "pipeline_id": 2366, "project_id": 380, "project_name": "gitlab-org/gitlab-test", "user": { "id": 3, "name": "User", "email": "user@gitlab.com", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" }, "commit": { "id": 2366, "sha": "2293ada6b400935a1378653304eaf6221e0fdb8f", "message": "test\n", "author_name": "User", "author_email": "user@gitlab.com", "status": "created", "duration": null, "started_at": null, "finished_at": null }, "repository": { "name": "gitlab_test", "description": "Atque in sunt eos similique dolores voluptatem.", "homepage": "http://192.168.64.1:3005/gitlab-org/gitlab-test", "git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git", "git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git", "visibility_level": 20 }, "runner": { "active": true, "is_shared": false, "id": 380987, "description": "shared-runners-manager-6.gitlab.com" } } +``` + +请注意, `commit.id`是管道的 ID,而不是提交的 ID. + +## Image URL rewriting[](#image-url-rewriting "Permalink") + +从 GitLab 11.2 开始,简单的图像引用被重写为在 webhooks 中使用绝对 URL. 因此,如果图像,合并请求,评论或维基页面的描述中包含以下内容: + +``` +![image](/uploads/$sha/image.png) +``` + +它将显示在 webhook 主体中,如下所示(假设 GitLab 安装在`gitlab.example.com` ,并且该项目位于`example-group/example-project` ): + +``` +![image](https://gitlab.example.com/example-group/example-project/uploads/$sha/image.png) +``` + +这不会重写已经指向 HTTP,HTTPS 或协议相对 URL 的 URL. 它还不会使用链接标记之类的高级 Markdown 功能重写图像 URL. + +## Testing webhooks[](#testing-webhooks "Permalink") + +您可以手动触发 Webhook. 将使用项目中的样本数据. >例如:要触发" `Push Events`您的项目应至少提交一次. + +[![Webhook testing](img/cee9b8bcba36170c0ae5df4747bb8c44.png)](img/webhook_testing.png) + +## Troubleshoot webhooks[](#troubleshoot-webhooks "Permalink") + +manbetx 客户端打不开存储 webhook 的每个执行. 您可以在每个 Webhook 的编辑页面上的"最近发送"部分中找到最近 2 天的记录. + +[![Recent deliveries](img/78dac22706dcca5ce3855d23987289ea.png)](img/webhook_logs.png) + +在本部分中,您可以看到 HTTP 状态代码(绿色表示 200-299 代码,红色表示其他代码,传递失败的`internal error` ),触发的事件,事件被调用的时间,请求的经过时间. + +如果需要有关执行的更多信息,可以单击`View details`链接. 在此页面上,您可以查看 GitLab 发送的数据(请求标头和正文)和收到的数据(响应标头和正文). + +在此页面上,您可以通过单击" `Resend Request`按钮以相同的数据重复`Resend Request` . + +> **注意:**如果已更新 Webhook 的 URL 或秘密令牌,则数据将被传递到新地址. + +### Receiving duplicate or multiple webhook requests triggered by one event[](#receiving-duplicate-or-multiple-webhook-requests-triggered-by-one-event "Permalink") + +当 GitLab 发送一个 Webhook 时,它期望在 10 秒内响应(设置默认值). 如果没有收到,它将重试网络挂钩. 如果端点在这 10 秒钟内未发送 HTTP 响应,则 GitLab 可能会确定挂钩失败并重试. + +如果接收到多个请求,可以通过取消注释或将以下设置添加到`/etc/gitlab/gitlab.rb`来尝试增加发送`/etc/gitlab/gitlab.rb`之后的默认值,以等待 HTTP 响应: + +``` +gitlab_rails['webhook_timeout'] = 10 +``` + +### Troubleshooting: “Unable to get local issuer certificate”[](#troubleshooting-unable-to-get-local-issuer-certificate "Permalink") + +启用 S​​SL 验证后,此错误表明 GitLab 无法验证 Webhook 端点的 SSL 证书. 通常,这是因为根证书不是由[CAcert.org](http://www.cacert.org/)确定的受信任的证书颁发机构[颁发的](http://www.cacert.org/) . + +如果不是这种情况,请考虑使用[SSL Checker](https://www.sslshopper.com/ssl-checker.html)来识别故障. 缺少中间证书是验证失败的常见原因. + +## Example webhook receiver[](#example-webhook-receiver "Permalink") + +如果您希望通过测试了解 GitLab 的 webhooks,可以使用在控制台会话中运行的简单回显脚本. 为了使以下脚本正常工作,您需要安装 Ruby. + +将以下文件另存为`print_http_body.rb` : + +``` +require 'webrick' + +server = WEBrick::HTTPServer.new(:Port => ARGV.first) +server.mount_proc '/' do |req, res| + puts req.body +end + +trap 'INT' do + server.shutdown +end +server.start +``` + +选择一个未使用的端口(例如 8000)并启动脚本: `ruby print_http_body.rb 8000` . 然后,将您的服务器作为 Webhook 接收器添加到 GitLab 中,作为`http://my.host:8000/` . + +在 GitLab 中按"测试"时,您应该在控制台中看到以下内容: + +``` +{"before":"077a85dd266e6f3573ef7e9ef8ce3343ad659c4e","after":"95cd4a99e93bc4bbabacfa2cd10e6725b1403c60",<SNIP>} +example.com - - [14/May/2014:07:45:26 EDT] "POST / HTTP/1.1" 200 0 +- -> / +``` + +**注意:**您可能需要[允许向本地网络](../../../security/webhooks.html)发送[请求,](../../../security/webhooks.html)以便添加此接收器. \ No newline at end of file diff --git a/docs/094.md b/docs/094.md new file mode 100644 index 0000000000000000000000000000000000000000..2497f9a1a3f3094c1a9104708e705136317b28da --- /dev/null +++ b/docs/094.md @@ -0,0 +1,42 @@ +# YouTrack Service + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/youtrack.html](https://docs.gitlab.com/ee/user/project/integrations/youtrack.html) + +* [Enable the YouTrack integration](#enable-the-youtrack-integration) +* [Disable the internal issue tracker](#disable-the-internal-issue-tracker) +* [Referencing YouTrack issues in GitLab](#referencing-youtrack-issues-in-gitlab) + +# YouTrack Service[](#youtrack-service "Permalink") + +JetBrains [YouTrack](https://www.jetbrains.com/help/youtrack/standalone/YouTrack-Documentation.html)是一个基于 Web 的问题跟踪和项目管理平台. + +您可以在 GitLab 中将 YouTrack 配置为[外部问题跟踪器](../../../integration/external-issue-tracker.html) . + +## Enable the YouTrack integration[](#enable-the-youtrack-integration "Permalink") + +要在项目中启用 YouTrack 集成,请执行以下操作: + +1. 导航到项目的**"设置">" [集成"](overview.html#accessing-integrations)**页面. +2. 单击**YouTrack**服务,确保其处于活动状态,然后按照下表中的说明在页面上输入所需的详细信息. + + | Field | Description | + | --- | --- | + | **Project URL** | 链接到该 GitLab 项目的 YouTrack 中项目的 URL. | + | **问题网址** | 链接到该 GitLab 项目的 YouTrack 项目中问题的 URL. 请注意, **问题 URL**需要**URL 中的** `:id` . GitLab 使用此 ID 作为占位符来替换问题编号. | + +3. 点击**保存更改**按钮. + +一旦配置并启用了 YouTrack,您将在 GitLab 项目页面上看到 YouTrack 链接,该链接将您带到适当的 YouTrack 项目. + +## Disable the internal issue tracker[](#disable-the-internal-issue-tracker "Permalink") + +要在项目中禁用内部问题跟踪器: + +1. 导航到项目的**"设置">"常规"**页面. +2. 展开[权限部分](../settings/index.html#sharing-and-permissions) ,然后将**问题**切换为禁用. + +## Referencing YouTrack issues in GitLab[](#referencing-youtrack-issues-in-gitlab "Permalink") + +YouTrack 中的问题可以称为`<PROJECT>-<ID>` . `<PROJECT>`必须以字母开头,后跟字母,数字或下划线. `<ID>`是一个数字. 参考示例是`YT-101` , `Api_32-143`或`gl-030` . + +合并请求,提交或注释中对`<PROJECT>-<ID>`引用将自动链接到 YouTrack 问题 URL. 有关更多信息,请参阅[外部问题跟踪器](../../../integration/external-issue-tracker.html)文档. \ No newline at end of file diff --git a/docs/095.md b/docs/095.md new file mode 100644 index 0000000000000000000000000000000000000000..930e3be10f6008d4874d390d6268fcc30d2f281a --- /dev/null +++ b/docs/095.md @@ -0,0 +1,384 @@ +# Insights + +> 原文:[https://docs.gitlab.com/ee/user/project/insights/](https://docs.gitlab.com/ee/user/project/insights/) + +* [View your project’s Insights](#view-your-projects-insights) +* [Configure your Insights](#configure-your-insights) +* [Permissions](#permissions) +* [Writing your `.gitlab/insights.yml`](#writing-your-gitlabinsightsyml) +* [Configuration parameters](#configuration-parameters) +* [Parameter details](#parameter-details) + * [`title`](#title) + * [`description`](#description) + * [`type`](#type) + * [`query`](#query) + * [`query.issuable_type`](#queryissuable_type) + * [`query.issuable_state`](#queryissuable_state) + * [`query.filter_labels`](#queryfilter_labels) + * [`query.collection_labels`](#querycollection_labels) + * [`query.group_by`](#querygroup_by) + * [`query.period_limit`](#queryperiod_limit) + * [`query.period_field`](#queryperiod_field) + * [`projects`](#projects) + * [`projects.only`](#projectsonly) +* [Complete example](#complete-example) + +# Insights[](#insights-ultimate "Permalink") + +[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. + +配置对您的项目至关重要的见解,以探索数据,例如分类诊断,在给定期间内创建/关闭的问题,合并请求的平均合并时间等等. + +[![Insights example bar chart](img/911c6aa51b9202fc3dc3bdc143b30f82.png)](img/project_insights.png) + +**注意:**此功能[在组级别也可用](../../group/insights/index.html) . + +## View your project’s Insights[](#view-your-projects-insights "Permalink") + +您可以通过点击左侧栏中的**Analytics(分析)> Insights**链接来访问项目的 Insights: + +[![Insights sidebar link](img/24ea9a3635dc27668b899d6785917b1b.png)](img/insights_sidebar_link_v12_8.png) + +## Configure your Insights[](#configure-your-insights "Permalink") + +使用项目中名为`.gitlab/insights.yml`的 YAML 文件配置`.gitlab/insights.yml` . 该文件将在项目的"见解"页面中使用. + +有关此文件内容的详细信息,请参见下面的[编写`.gitlab/insights.yml`](#writing-your-gitlabinsightsyml) . + +**注意:**一旦创建了配置文件,您也可以[将其用于项目的 group](../../group/insights/index.html#configure-your-insights) .**注意:**如果项目没有任何配置文件,则将尽可能尝试使用组配置. 如果该组没有任何配置,将使用默认配置. + +## Permissions[](#permissions "Permalink") + +如果您有权查看项目,则可以查看其见解. + +**注意:**您无法访问的问题或合并请求(因为您无法访问它们所属的项目,或者因为它们是机密的)会从 Insights 图表中过滤掉. + +您也可以查阅[组权限表](../../permissions.html#group-members-permissions) . + +## Writing your `.gitlab/insights.yml`[](#writing-your-gitlabinsightsyml "Permalink") + +`.gitlab/insights.yml`文件定义了将在项目或组的每个 Insights 页面中显示的 Insights 图表的结构和顺序. + +每个页面都有一个唯一的键以及一组要获取和显示的图表. + +例如,这是 Insights 的单个定义,它将显示一个带有一个图表的页面: + +``` +bugsCharts: + title: "Charts for bugs" + charts: + - title: "Monthly bugs created" + description: "Open bugs created per month" + type: bar + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + group_by: month + period_limit: 24 +``` + +每个图表定义均由键值对组成的哈希组成. + +例如,这是单个图表定义: + +``` +- title: "Monthly bugs created" + description: "Open bugs created per month" + type: bar + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + group_by: month + period_limit: 24 +``` + +## Configuration parameters[](#configuration-parameters "Permalink") + +图表被定义为定义图表行为的参数列表. + +下表列出了图表的可用参数: + +| Keyword | Description | +| --- | --- | +| [`title`](#title) | 图表标题. 这将显示在"见解"页面上. | +| [`description`](#description) | 单个图表的描述. 这将显示在相关图表上方. | +| [`type`](#type) | 图表类型: `bar` , `line`或`stacked-bar` . | +| [`query`](#query) | 散列,用于定义要成为图表一部分的问题/合并请求的条件. | + +## Parameter details[](#parameter-details "Permalink") + +以下是用于配置 Insights 图表的参数的详细说明. + +### `title`[](#title "Permalink") + +`title`是图表的标题,它将显示在 Insights 页面上. 例如: + +``` +monthlyBugsCreated: + title: "Monthly bugs created" +``` + +### `description`[](#description "Permalink") + +`description`文字显示在图表上方,但标题下方. 它用于提供有关图表的更多详细信息,例如: + +``` +monthlyBugsCreated: + title: "Monthly bugs created" + description: "Open bugs created per month" +``` + +### `type`[](#type "Permalink") + +`type`是图表类型. + +例如: + +``` +monthlyBugsCreated: + title: "Monthly bugs created" + type: bar +``` + +Supported values are: + +| Name | Example | +| --- | --- | +| `bar` | [![Insights example bar chart](img/441419241245b159818b469c6508f227.png)](img/insights_example_bar_chart.png) | +| `bar` (time series, i.e. when `group_by` is used) | [![Insights example bar time series chart](img/6cad1c326921f33ce6d53e7f2ebd1158.png)](img/insights_example_bar_time_series_chart.png) | +| `line` | [![Insights example stacked bar chart](img/e75b1239d806589f91c4a40aba7fdc05.png)](img/insights_example_line_chart.png) | +| `stacked-bar` | [![Insights example stacked bar chart](img/da13575f699b92fa864c2d3fae1fae9e.png)](img/insights_example_stacked_bar_chart.png) | + +### `query`[](#query "Permalink") + +`query`允许定义条件/合并请求成为图表的一部分. + +Example: + +``` +monthlyBugsCreated: + title: "Monthly bugs created" + description: "Open bugs created per month" + type: bar + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + collection_labels: + - S1 + - S2 + - S3 + - S4 + group_by: week + period_limit: 104 +``` + +#### `query.issuable_type`[](#queryissuable_type "Permalink") + +定义要为其创建图表的"可发行"的类型. + +支持的值为: + +* `issue` :图表将显示问题的数据. +* `merge_request` :图表将显示合并请求的数据. + +#### `query.issuable_state`[](#queryissuable_state "Permalink") + +按查询的"可发行"状态过滤. + +默认情况下,将使用`opened`状态过滤器. + +支持的值为: + +* `opened` :未解决问题/合并请求. +* `closed` :已关闭未解决的问题/合并请求. +* `locked` :已锁定讨论的问题/合并请求. +* `merged` :合并的合并请求. +* `all` :在所有状态下发出/合并请求 + +#### `query.filter_labels`[](#queryfilter_labels "Permalink") + +按应用于查询的"可发行"的标签过滤. + +默认情况下,不应用标签过滤器. 必须将所有定义的标签应用于"可发行",才能对其进行选择. + +Example: + +``` +monthlyBugsCreated: + title: "Monthly regressions created" + type: bar + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + - regression +``` + +#### `query.collection_labels`[](#querycollection_labels "Permalink") + +通过配置的标签将"可发行"分组. + +默认情况下,不会进行分组. 使用此关键字时,需要将`type`设置为`line`或`stacked-bar` . + +Example: + +``` +weeklyBugsBySeverity: + title: "Weekly bugs by severity" + type: stacked-bar + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + collection_labels: + - S1 + - S2 + - S3 + - S4 +``` + +#### `query.group_by`[](#querygroup_by "Permalink") + +定义图表的 X 轴. + +支持的值为: + +* `day` : `day`组数据. +* `week` : `week`组数据. +* `month` : `month`组数据. + +#### `query.period_limit`[](#queryperiod_limit "Permalink") + +定义过去查询"可耗材"的距离. + +该单位与您定义的`query.group_by`有关. 例如,如果您定义了`query.group_by: 'day'`则`query.period_limit: 365`意思是"收集并显示最近 365 天的数据". + +默认情况下,将根据您定义的`query.group_by`应用默认值. + +| `query.group_by` | 默认值 | +| --- | --- | +| `day` | 30 | +| `week` | 4 | +| `month` | 12 | + +#### `query.period_field`[](#queryperiod_field "Permalink") + +定义用于将"可耗材"分组的时间戳字段. + +支持的值为: + +* `created_at` (默认):使用`created_at`字段对数据进行分组. +* `closed_at` :使用`closed_at`字段对数据进行`closed_at` (仅针对问题). +* `merged_at` :使用`merged_at`字段对数据进行`merged_at` (仅适用于合并请求). + +`period_field`自动设置为: + +* `closed_at` if `query.issuable_state` is `closed` +* `merged_at` if `query.issuable_state` is `merged` +* `created_at` otherwise + +**注意:**在解决[此错误](https://gitlab.com/gitlab-org/gitlab/-/issues/26911)之前,您可能会看到`created_at`代替`merged_at` . 将使用`created_at`代替. + +### `projects`[](#projects "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10904) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.4. + +您可以限制从以下位置查询"可耗材"的位置: + +* 如果`.gitlab/insights.yml`用于一[组的见解](../../group/insights/index.html#configure-your-insights) ,有`projects` ,你可以限制要查询的项目. 默认情况下,将使用该组下的所有项目. +* 如果将`.gitlab/insights.yml`用于项目的见解,则指定任何其他项目均不会产生任何结果. 默认情况下,将使用项目本身. + +#### `projects.only`[](#projectsonly "Permalink") + +`projects.only`选项指定应从中查询"可发行物品"的项目. + +在以下情况下,此处列出的项目将被忽略: + +* 它们不存在. +* 当前用户没有足够的权限来读取它们. +* 他们不在小组中. + +在以下`insights.yml`示例中,我们指定将在其中使用查询的项目. 设置小组的见解时,此示例非常有用: + +``` +monthlyBugsCreated: + title: "Monthly bugs created" + description: "Open bugs created per month" + type: bar + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + projects: + only: + - 3 # You can use the project ID + - groupA/projectA # Or full project path + - groupA/subgroupB/projectC # Projects in subgroups can be included + - groupB/project # Projects outside the group will be ignored +``` + +## Complete example[](#complete-example "Permalink") + +``` +.projectsOnly: &projectsOnly + projects: + only: + - 3 + - groupA/projectA + - groupA/subgroupB/projectC + +bugsCharts: + title: "Charts for bugs" + charts: + - title: "Monthly bugs created" + description: "Open bugs created per month" + type: bar + <<: *projectsOnly + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + group_by: month + period_limit: 24 + + - title: "Weekly bugs by severity" + type: stacked-bar + <<: *projectsOnly + query: + issuable_type: issue + issuable_state: opened + filter_labels: + - bug + collection_labels: + - S1 + - S2 + - S3 + - S4 + group_by: week + period_limit: 104 + + - title: "Monthly bugs by team" + type: line + <<: *projectsOnly + query: + issuable_type: merge_request + issuable_state: opened + filter_labels: + - bug + collection_labels: + - Manage + - Plan + - Create + group_by: month + period_limit: 24 +``` \ No newline at end of file diff --git a/docs/096.md b/docs/096.md new file mode 100644 index 0000000000000000000000000000000000000000..5ea5c06ea60f6e17b4b7da8f517eb71a6df480e7 --- /dev/null +++ b/docs/096.md @@ -0,0 +1,174 @@ +# Issues + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/](https://docs.gitlab.com/ee/user/project/issues/) + +* [Overview](#overview) +* [Parts of an issue](#parts-of-an-issue) +* [Viewing and managing issues](#viewing-and-managing-issues) + * [Issue page](#issue-page) + * [Issues list](#issues-list) + * [Issue boards](#issue-boards) + * [Design Management](#design-management) + * [Epics](#epics-premium) + * [Related issues](#related-issues-starter) + * [Crosslinking issues](#crosslinking-issues) + * [Similar issues](#similar-issues) + * [Health status](#health-status-ultimate) + * [Disable issue health status](#disable-issue-health-status) +* [Other Issue actions](#other-issue-actions) + +# Issues[](#issues "Permalink") + +问题是在 GitLab 中就想法和计划工作进行协作的基本介质. + +## Overview[](#overview "Permalink") + +GitLab 问题跟踪器是用于协作开发想法,解决问题和计划工作的高级工具. + +通过问题,可以在以下各项之间,在实施之前和期间共享和讨论提案: + +* 您和您的团队. +* 外部合作者. + +它们还可以用于各种其他目的,根据您的需求和工作流程进行定制. + +问题始终与特定项目相关联,但是如果您在一个小组中有多个项目,则还可以在小组级别集体查看所有问题. + +**常见的用例包括:** + +* 讨论新想法的实施 +* 跟踪任务和工作状态 +* 接受功能建议,问题,支持请求或错误报告 +* 详细说明新的代码实现 + +另请参见[始终从问题开始讨论](https://about.gitlab.com/blog/2016/03/03/start-with-an-issue/) . + +要了解 GitLab 战略营销部门如何将 GitLab 问题与[标签](../labels.html)和[问题板一起使用](../issue_board.html) ,请参阅有关[管理问题的承诺](https://www.youtube.com/watch?v=cuIHNintg1o&t=3)的视频. + +## Parts of an issue[](#parts-of-an-issue "Permalink") + +问题包含各种内容和元数据,从而在使用方式上具有很大的灵活性. 每个问题可以包含以下属性,尽管并非必须设置所有项目. + +| + +* Content + * Title + * 描述和任务 + * 评论和其他活动 +* People + * Author + * Assignee(s) +* State + * 状态(打开或关闭) + * 健康状况(正常,需要注意或有危险) + * Confidentiality + * 任务(完成与未完成) + + | + +* 规划和跟踪 + * 里程碑 + * 截止日期 + * 重量 + * 时间跟踪 + * 标签 + * 投票数 + * 反应表情 + * 关联问题 + * 分配史诗 + * 唯一的发行号和 URL + + | + +## Viewing and managing issues[](#viewing-and-managing-issues "Permalink") + +虽然您可以在[问题页面](#issue-page)上查看和管理问题的全部详细信息,但也可以一次使用" [问题列表"](#issues-list) ," [问题板"](#issue-boards) ,"问题参考"和" [Epic"](#epics-premium)处理多个问题 . + +针对问题的关键操作包括: + +* [Creating issues](managing_issues.html#create-a-new-issue) +* [Moving issues](managing_issues.html#moving-issues) +* [Closing issues](managing_issues.html#closing-issues) +* [Deleting issues](managing_issues.html#deleting-issues) + +### Issue page[](#issue-page "Permalink") + +[![Issue view](img/a15f0b2964d7094b019c5c33425ba75b.png)](img/issues_main_view.png) + +在问题的页面上,您可以查看问题的[所有方面,](issue_data_and_actions.html)如果有必要的[权限](../../permissions.html) ,可以对其进行修改. + +### Issues list[](#issues-list "Permalink") + +[![Project issues list view](img/854d722d9976d5b36956ddbe41ceae48.png)](img/project_issues_list_view.png) + +在"问题列表"上,可以从更高级别的组上下文中打开"问题列表",从而可以查看当前项目中的所有问题,也可以查看多个项目中的所有问题. 使用[搜索查询](../../search/index.html#filtering-issue-and-merge-request-lists)过滤问题列表,包括特定的元数据,例如标签,受让人,状态等. 从此视图,您还可以对显示的问题[进行批量](../bulk_editing.html)更改. + +有关更多信息,请参见[问题数据和操作](issue_data_and_actions.html)页面,以了解问题中所有字段和信息的摘要. + +您可以通过多种方式对问题列表进行排序,例如,通过问题创建日期,里程碑到期日期. 有关更多信息,请参见" [排序和排序问题列表"](sorting_issue_lists.html)页面. + +### Issue boards[](#issue-boards "Permalink") + +[![Issue board](img/fd79e7dae86040d6e1249793ae0b1502.png)](img/issue_board.png) + +[发行板](../issue_board.html)是看板,其栏目根据其标签或他们的受让人显示问题 . 它们提供了使用高度可定制的工作流来管理问题的灵活性. + +您可以在栏中重新排序问题. 如果将发行卡拖到另一列,则其关联的标签或受让人将更改以匹配新列的标签或受让人. 整个董事会也可以被筛选为仅包括某个里程碑或总体标签中的问题. + +### Design Management[](#design-management "Permalink") + +使用[Design Management](design_management.html) ,您可以将设计资产上载到问题并一起查看它们,以轻松地与团队共享和协作. + +### Epics[](#epics-premium "Permalink") + +[Epics](../../group/epics/index.html)通过跟踪跨项目和里程碑共享主题的问题组,使您可以更有效,更[轻松地](../../group/epics/index.html)管理项目组合. + +### Related issues[](#related-issues-starter "Permalink") + +您可以将两个问题标记为"相关",以便在查看一个问题时,另一个[问题](related_issues.html)始终列在" [相关问题"](related_issues.html)部分中. 这可以帮助显示重要的上下文,例如过去的工作,依赖项或重复项. + +### Crosslinking issues[](#crosslinking-issues "Permalink") + +您可以通过引用另一个问题中的问题来[交叉链接问题](crosslinking_issues.html) ,也可以通过包括其 URL 或 ID 来合并请求. 参考的问题在活动流中显示有关参考的消息,并带有指向其他问题或 MR 的链接. + +### Similar issues[](#similar-issues "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22866) . + +为了防止同一主题重复出现问题,GitLab 在创建新问题时会搜索相似的问题. + +在" **新问题"**页面中键入标题时,GitLab 会搜索用户在当前项目中有权访问的所有问题的标题和描述. 标题框下方最多显示五个类似问题(按最新更新排序). 请注意,此功能需要启用[GraphQL](../../../api/graphql/index.html) . + +[![Similar issues](img/95882a4976be6b95971ad0011fcd7617.png)](img/similar_issues.png) + +### Health status[](#health-status-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36427) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. + +为了帮助您跟踪问题的状态,您可以为每个问题分配一个状态,以标记按计划进行或需要注意以按时进行的工作: + +* **步入正轨** (green) +* **需要注意** (amber) +* **有一定风险** (red) + +[!["On track" health status on an issue](img/8308fbab7a41e24cad0bf6c358863ae3.png)](img/issue_health_status_dropdown_v12_10.png) + +然后,您可以在[Epic 树上](../../group/epics/index.html#issue-health-status-in-epic-tree-ultimate)查看问题状态. + +#### Disable issue health status[](#disable-issue-health-status "Permalink") + +此功能默认启用`:save_issuable_health_status`功能标志. 但是,在某些情况下,此功能与旧配置不兼容. 要在迁移配置时关闭该功能,请要求具有 Rails 控制台访问权限的 GitLab 管理员运行以下命令: + +``` +Feature.disable(:save_issuable_health_status) +``` + +## Other Issue actions[](#other-issue-actions "Permalink") + +* [Create an issue from a template](../../project/description_templates.html#using-the-templates) +* [Set a due date](due_dates.html) +* [批量编辑问题](../bulk_editing.html) -从问题列表中选择多个问题,以批量更改其状态,受让人,里程碑或标签. +* [Import issues](csv_import.html) +* [Export issues](csv_export.html) +* [Issues API](../../../api/issues.html) +* 配置[外部问题跟踪器,](../../../integration/external-issue-tracker.html)例如 Jira,Redmine 或 Bugzilla. \ No newline at end of file diff --git a/docs/097.md b/docs/097.md new file mode 100644 index 0000000000000000000000000000000000000000..e11a4f4b443c24c87cc66eaa2fdc8a87809f60c2 --- /dev/null +++ b/docs/097.md @@ -0,0 +1,49 @@ +# Crosslinking Issues + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/crosslinking_issues.html](https://docs.gitlab.com/ee/user/project/issues/crosslinking_issues.html) + +* [From Commit Messages](#from-commit-messages) +* [From Related Issues](#from-related-issues) +* [From Merge Requests](#from-merge-requests) + +# Crosslinking Issues[](#crosslinking-issues "Permalink") + +请通读[GitLab 问题文档](index.html)以获取有关 GitLab 问题的概述. + +## From Commit Messages[](#from-commit-messages "Permalink") + +每次在提交消息中提及问题时,您都在开发工作流的两个阶段之间建立一种关系:问题本身以及与该问题相关的第一次提交. + +如果问题和您要提交的代码都在同一项目中,则只需在提交消息中添加`#xxx` ,其中`xxx`是问题编号. 如果它们不在同一项目中,则可以将完整的 URL 添加到问题中( `https://gitlab.com/<username>/<projectname>/issues/<xxx>` ). + +``` +git commit -m "this is my commit message. Ref #xxx" +``` + +or + +``` +git commit -m "this is my commit message. Related to https://gitlab.com/<username>/<projectname>/issues/<xxx>" +``` + +当然,您可以使用自己的 GitLab 实例的 URL 替换`gitlab.com` . + +**注意:**将您的第一次提交与您的问题相关联,对于通过[GitLab Cycle Analytics](https://about.gitlab.com/stages-devops-lifecycle/value-stream-analytics/)跟踪您的过程将非常重要. 它将测量计划该问题的实施所花费的时间,即从创建问题到进行第一次提交之间的时间. + +## From Related Issues[](#from-related-issues "Permalink") + +在合并请求中提及相关问题以及其他问题对于您的团队成员和协作者了解有关同一主题的未解决问题很有用. + +如上所述,当您[从提交消息中提到问题](#from-commit-messages)时,您可以执行此操作. + +当在问题`#222`提到问题`#111`时,问题`#111`还将在其跟踪器中显示一条通知. 也就是说,您只需提及一次关系即可在两个问题中均显示该关系. 在[合并请求中](#from-merge-requests)提及问题时,也是如此. + +[![issue mentioned in issue](img/b962444c71ad27ba05dfc6bfc69269f4.png)](img/mention_in_issue.png) + +## From Merge Requests[](#from-merge-requests "Permalink") + +Mentioning issues in merge request comments works exactly the same way as they do for [related issues](#from-related-issues). + +当您在合并请求说明中提到问题时,它将仅[将问题和合并请求链接在一起](#from-related-issues) . 此外,您还可以[将问题设置](managing_issues.html#closing-issues-automatically)为在合并请求合并后立即[自动关闭](managing_issues.html#closing-issues-automatically) . + +[![issue mentioned in MR](img/f36631c8d1fd9cb42fb7c58a495c24be.png)](img/mention_in_merge_request.png) \ No newline at end of file diff --git a/docs/098.md b/docs/098.md new file mode 100644 index 0000000000000000000000000000000000000000..0fb51b91772938fcc7a4fcd654ac29686f1082ce --- /dev/null +++ b/docs/098.md @@ -0,0 +1,251 @@ +# Design Management + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/design_management.html](https://docs.gitlab.com/ee/user/project/issues/design_management.html) + +* [Overview](#overview) +* [Requirements](#requirements) +* [Supported files](#supported-files) +* [Limitations](#limitations) +* [GitLab-Figma plugin](#gitlab-figma-plugin) +* [The Design Management section](#the-design-management-section) + * [Enable or disable displaying Designs on the issue description](#enable-or-disable-displaying-designs-on-the-issue-description-core-only) +* [Adding designs](#adding-designs) + * [Skipped designs](#skipped-designs) +* [Viewing designs](#viewing-designs) + * [Exploring designs by zooming](#exploring-designs-by-zooming) +* [Deleting designs](#deleting-designs) +* [Starting discussions on designs](#starting-discussions-on-designs) +* [Resolve Design threads](#resolve-design-threads) +* [Referring to designs in Markdown](#referring-to-designs-in-markdown) + * [Enable or disable design references](#enable-or-disable-design-references-core-only) +* [Design activity records](#design-activity-records) + +# Design Management[](#design-management "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.2 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/660) . +* 在 13.0 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) GitLab Core. + +## Overview[](#overview "Permalink") + +Design Management 允许您将设计资产(线框,模型等)上载到 GitLab 问题,并将它们存储在一个位置,由问题中的 Design Management 页面访问,从而为产品设计师,产品经理和工程师提供了一种方法在单一事实来源上进行设计合作. + +您可以轻松地与团队共享设计的模型,也可以轻松查看和解决视觉回归问题. + +有关概述,请参见视频[设计管理(GitLab 12.2)](https://www.youtube.com/watch?v=CCMtCqdK_aM) . + +## Requirements[](#requirements "Permalink") + +设计管理需要启用[大文件存储(LFS)](../../../topics/git/lfs/index.html) : + +* 对于 GitLab.com,已启用 LFS. +* 对于自我管理的实例,GitLab 管理员必须[全局启用 LFS](../../../administration/lfs/index.html) . +* 对于 GitLab.com 和自我管理实例:必须为项目本身启用 LFS. 如果全局启用,则默认情况下将对所有项目启用 LFS. 要在项目级别启用 LFS,请导航至项目的**"设置">"常规"** ,展开" **可见性",项目功能,权限**并启用" **Git Large File Storage"** . + +设计管理还要求项目使用[哈希存储](../../../administration/raketasks/storage.html#migrate-to-hashed-storage) . 从 GitLab 10.0 开始,默认情况下,新创建的项目使用哈希存储. GitLab 管理员可以通过导航到" **管理区域">"项目"** ,然后选择有问题的项目来验证项目的存储类型. 如果项目的*Gitaly 相对路径*包含`@hashed`则可以将其标识为散列存储. + +如果不满足要求,则" **设计"**选项卡会向用户显示一条消息. + +## Supported files[](#supported-files "Permalink") + +上传的文件的文件扩展名必须为`png` , `jpg` , `jpeg` , `gif` , `bmp` , `tiff`或`ico` . + +计划在将来的版本中支持[SVG 文件](https://gitlab.com/gitlab-org/gitlab/-/issues/12771)和[PDF](https://gitlab.com/gitlab-org/gitlab/-/issues/32811) . + +## Limitations[](#limitations "Permalink") + +* 设计上载一次限制为 10 个文件. +* 从 GitLab 13.1 起,设计文件名限制为 255 个字符. +* [销毁项目时,不会删除](https://gitlab.com/gitlab-org/gitlab/-/issues/13429)设计管理数据. +* [移动](https://gitlab.com/gitlab-org/gitlab/-/issues/13426)问题时, [不会移动](https://gitlab.com/gitlab-org/gitlab/-/issues/13426) Design Management 数据; [删除](https://gitlab.com/gitlab-org/gitlab/-/issues/13427)问题时,也不会[删除](https://gitlab.com/gitlab-org/gitlab/-/issues/13427)它. +* 从 GitLab 12.7 起,设计管理数据[可以](../../../administration/geo/replication/datatypes.html#limitations-on-replicationverification)由 Geo [复制](../../../administration/geo/replication/datatypes.html#limitations-on-replicationverification) ,但[不能验证](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) . +* 只能删除设计的最新版本. +* 删除的设计无法恢复,但是您可以在以前的设计版本中看到它们. + +## GitLab-Figma plugin[](#gitlab-figma-plugin "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab-figma-plugin/-/issues/2) . + +通过无缝的工作流程将设计环境与源代码管理连接起来. GitLab-Figma 插件通过将产品设计师的工作从 Figma 直接带到 GitLab Issues 作为上载的 Designs,使在 GitLab 中进行协作变得快捷,容易. + +要使用该插件,请从[Figma 目录中](https://www.figma.com/community/plugin/860845891704482356)安装它,并通过个人访问令牌连接到 GitLab. 有关详细信息,请参见[插件文档](https://gitlab.com/gitlab-org/gitlab-figma-plugin/-/wikis/home) . + +## The Design Management section[](#the-design-management-section "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/223193)设计直接显示在问题描述中,而不是单独的选项卡上. +* 新显示将部署在功能标记后面,默认情况下启用. +* 在 GitLab.com 上启用了它. +* 不能根据项目启用或禁用它. +* 建议用于生产. +* 对于 GitLab 自我管理的实例,GitLab 管理员可以选择[禁用它](#enable-or-disable-displaying-designs-on-the-issue-description-core-only) . 如果禁用,它将"设计"移回" **设计"**选项卡. + +您可以在问题描述的" **设计管理"**部分中找到: + +[![Designs section](img/a9325984eddfbb907563c5bf5003f704.png)](img/design_management_v13_2.png) + +### Enable or disable displaying Designs on the issue description[](#enable-or-disable-displaying-designs-on-the-issue-description-core-only "Permalink") + +正在开发关于问题描述的设计,但已准备好用于生产. 它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以选择为您的实例禁用它. + +禁用它: + +``` +Feature.disable(:design_management_moved) +``` + +要启用它: + +``` +Feature.enable(:design_management_moved) +``` + +通过禁用此功能,设计将显示在" **设计"**选项卡上,而不是直接显示在问题描述上. + +## Adding designs[](#adding-designs "Permalink") + +要上传设计图像,请将文件从计算机上拖放到"设计管理"部分,或单击" **上传"**以从文件浏览器中选择图像: + +[![Designs empty state](img/cbd0470f26aadc25ca385447ade97392.png)](img/design_management_upload_v13.2.png) + +在[GitLab Premium](https://about.gitlab.com/pricing/) 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) ,您可以将设计拖放到专用放置区域以上载它们. + +[![Drag and drop design uploads](img/28e0f270ca5b3b728207d80c19a82d71.png)](img/design_drag_and_drop_uploads_v13_2.png) + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/202634)后,您还可以从文件系统复制图像并将其作为新设计直接粘贴到 GitLab 的"设计"页面上. + +在 macOS 上,您还可以截取屏幕截图,并同时单击`Control` + `Command` + `Shift` + `3` ,将其立即复制到剪贴板,然后将其粘贴为设计. + +复制和粘贴有一些限制: + +* 一次只能粘贴一张图像. 复制/粘贴多个文件时,只会上传第一个文件. +* 所有图像将在引擎盖下转换为`png`格式,因此当您要复制/粘贴`gif`文件时,会导致动画损坏. +* 如果要从剪贴板粘贴屏幕截图,它将被重命名为`design_<timestamp>.png` +* Copy/pasting designs is not supported on Internet Explorer. + +与现有的上载设计具有相同文件名的设计将创建该设计的新版本,并将替换以前的版本. 如果文件名相同,则在[GitLab Premium](https://about.gitlab.com/pricing/) 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34353)后,将设计放到现有的上载设计上也会创建一个新版本. + +如果问题已移动或[讨论被锁定](../../discussions/#lock-discussions) ,则无法添加设计. + +### Skipped designs[](#skipped-designs "Permalink") + +与现有上传的设计具有相同文件名*且*其内容未更改的设计将被跳过. 这意味着将不会创建该设计的新版本. 跳过设计时,将通过关于"问题"的警告消息通知您. + +## Viewing designs[](#viewing-designs "Permalink") + +单击"设计管理"页面上的图像可以将其放大. 您可以通过单击右上角的导航按钮或使用`左` / `右`键盘按钮来浏览设计. + +设计文件名右侧列出了有关设计的讨论数(如果有). 单击此数字可以放大设计,就像单击设计上的其他任何位置一样. 添加或修改设计时,项目上会显示一个图标,以帮助总结版本之间的更改. + +| Indicator | Example | +| --- | --- | +| Discussions | [![Discussions Icon](img/1162f64da937aa1ef37877c6b8930e1e.png)](img/design_comments_v12_3.png) | +| 已修改(在所选版本中) | [![Design Modified](img/3887423740965d20eecf9471bc1b3061.png)](img/design_modified_v12_3.png) | +| 已添加(在所选版本中) | [![Design Added](img/3601605e24186a1976e7aff09112bb7e.png)](img/design_added_v12_3.png) | + +### Exploring designs by zooming[](#exploring-designs-by-zooming "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13217) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7. + +通过放大和缩小图像,可以更详细地探索设计. 使用图像底部的`+`和`-`按钮控制缩放量. 缩放后,您仍然可以在图像上[开始新的讨论](#starting-discussions-on-designs) ,并查看任何现有的讨论. 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/197324) ,放大后,您可以在图像上单击并拖动以在图像中移动. + +[![Design zooming](img/9bf0c7423d5735ccdfbdfe250f9a5452.png)](img/design_zooming_v12_7.png) + +## Deleting designs[](#deleting-designs "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11089) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4. + +有两种删除设计的方法:分别手动删除它们,或选择其中几个立即删除,如下所示. + +要删除单个设计,请单击它以将其放大查看,然后单击右上角的垃圾桶图标,并通过单击模式窗口上的" **删除"**按钮来确认删除: + +[![Confirm design deletion](img/b15b2918f982a43ce2379b4f2ec765a9.png)](img/confirm_design_deletion_v12_4.png) + +要一次删除多个设计,请在设计的列表视图上,首先选择要删除的设计: + +[![Select designs](img/9f6da2599274d0db274d6aa19a27fcfc.png)](img/select_designs_v12_4.png) + +选择后,单击" **删除所选的"**按钮以确认删除: + +[![Delete multiple designs](img/eac2240244a4d3fb9f3d16c19760ea53.png)](img/delete_multiple_designs_v12_4.png) + +**注意:**只能删除设计的最新版本. 删除的设计不会永久丢失; 可以通过浏览以前的版本来查看它们. + +## Starting discussions on designs[](#starting-discussions-on-designs "Permalink") + +上传设计后,您可以通过单击您要关注讨论的确切位置上的图像来开始讨论. 将图钉添加到图像,以标识讨论的位置. + +[![Starting a new discussion on design](img/a272933779dc7642aed4eb4acde12df9.png)](img/adding_note_to_design_1.png) + +在[GitLab Premium](https://about.gitlab.com/pricing/) 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) ,您可以通过在图像周围拖动来调整销的位置. 当您的设计布局在各修订版之间进行了更改时,或者需要移动现有的引脚以在其位置添加新的引脚时,这很有用. + +不同的讨论有不同的引脚号: + +[![Discussions on designs](img/16db6a809ddf03cf101fdbec905d41a2.png)](img/adding_note_to_design_2.png) + +从 GitLab 12.5 起,新的讨论将输出到问题活动中,以便所有相关人员都可以参与讨论. + +## Resolve Design threads[](#resolve-design-threads "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13049) . + +Discussion threads can be resolved on Designs. + +有两种解决/取消解决设计线程的方法: + +1. 您可以通过单击讨论的第一个评论的右上角的" **解决线程"**的复选标记图标,将一个线程标记为已解决或未解决: + +[![Resolve thread icon](img/729f4c6815c7118c098b6925f2375918.png)](img/resolve_design-discussion_icon_v13_1.png) + +1. 还可以通过使用复选框在其线程中解析或不解析设计线程. 回复评论时,您会看到一个复选框,您可以单击该复选框以在发布后解决或取消解决线程: + +[![Resolve checkbox](img/a14ce4f4a816ce9ceea3133c64b5f328.png)](img/resolve_design-discussion_checkbox_v13_1.png) + +请注意,您已解决的注释图钉将从设计中消失,以腾出空间进行新的讨论. 但是,如果您需要重新访问或找到已解决的讨论,则所有已解决的主题将在右侧栏底部的" **已解决的注释"**区域中可用. + +## Referring to designs in Markdown[](#referring-to-designs-in-markdown "Permalink") + +> * [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217160) in **亚搏体育 app 13.1**. +> * 它部署在功能标志后面,默认情况下处于禁用状态. +> * 它在 GitLab.com 上被禁用. +> * 不建议将其用于生产. +> * 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-design-references-core-only) . + +我们支持在[Markdown 中](../../markdown.html)引用设计,在整个应用程序中都可用,包括合并请求和问题描述,讨论和评论以及 Wiki 页面. + +目前,支持完整的 URL 引用. 例如,如果我们使用以下内容引用设计: + +``` +See https://gitlab.com/your-group/your-project/-/issues/123/designs/homescreen.png +``` + +这将呈现为: + +> See [#123[homescreen.png]](https://gitlab.com/your-group/your-project/-/issues/123/designs/homescreen.png) + +### Enable or disable design references[](#enable-or-disable-design-references-core-only "Permalink") + +设计参考解析正在开发中,尚未准备好用于生产. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以为您的实例启用它. + +要启用它: + +``` +Feature.enable(:design_management_reference_filter_gfm_pipeline) +``` + +禁用它: + +``` +Feature.disable(:design_management_reference_filter_gfm_pipeline) +``` + +## Design activity records[](#design-activity-records "Permalink") + +版本历史 + +* 在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33051) . +* 在 GitLab 13.2 中[删除](https://gitlab.com/gitlab-org/gitlab/-/issues/225205)了[功能标志](https://gitlab.com/gitlab-org/gitlab/-/issues/225205) . + +GitLab 跟踪设计上的用户活动事件(创建,删除和更新),并显示在[用户配置文件](../../profile/index.html#user-profile) , [组](../../group/index.html#view-group-activity)和[项目](../index.html#project-activity)活动页面上. \ No newline at end of file diff --git a/docs/099.md b/docs/099.md new file mode 100644 index 0000000000000000000000000000000000000000..00343c63c777baf912d10b2cbdb9ba3e0e3b04a3 --- /dev/null +++ b/docs/099.md @@ -0,0 +1,96 @@ +# Confidential issues + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/confidential_issues.html](https://docs.gitlab.com/ee/user/project/issues/confidential_issues.html) + +* [Making an issue confidential](#making-an-issue-confidential) +* [Modifying issue confidentiality](#modifying-issue-confidentiality) +* [Indications of a confidential issue](#indications-of-a-confidential-issue) +* [Permissions and access to confidential issues](#permissions-and-access-to-confidential-issues) +* [Merge Requests for Confidential Issues](#merge-requests-for-confidential-issues) + * [How it works](#how-it-works) + +# Confidential issues[](#confidential-issues "Permalink") + +在 GitLab 8.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3282) . + +机密性问题是仅对具有[足够权限](#permissions-and-access-to-confidential-issues)的项目成员可见的问题. 开源项目和公司都可以使用机密问题来使安全漏洞不公开或防止意外泄漏. + +## Making an issue confidential[](#making-an-issue-confidential "Permalink") + +您可以在创建问题或编辑现有问题的过程中将其保密. + +创建新问题时,可以在文本区域下方的复选框中将问题标记为机密. 选中该框,然后点击" **提交问题"**按钮以创建问题. 对于现有问题,请对其进行编辑,选中机密复选框,然后点击**保存更改** . + +[![Creating a new confidential issue](img/43a1d5a081bb166e1d43d6e671f250e1.png)](img/confidential_issues_create.png) + +## Modifying issue confidentiality[](#modifying-issue-confidentiality "Permalink") + +有两种方法可以更改问题的机密性. + +第一种方法是编辑问题并标记/取消标记机密复选框. 保存问题后,它将更改问题的机密性. + +第二种方法是在边栏中找到"保密性"部分,然后单击" **编辑"** . 应该会出现一个弹出窗口,并为您提供打开或关闭机密性的选项. + +| 关闭机密性 | Turn on confidentiality | +| --- | --- | +| [![Turn off confidentiality](img/429e9751a8b0336bb8b7e3faab15a373.png)](img/turn_off_confidentiality.png) | [![Turn on confidentiality](img/3252759837ced64a222db48c62becdd3.png)](img/turn_on_confidentiality.png) | + +系统注释在问题注释中指出了从常规到机密(反之亦然)的每项更改. + +[![Confidential issues system notes](img/b66dc4137ac73e81c66e408cf9fcf391.png)](img/confidential_issues_system_notes.png) + +## Indications of a confidential issue[](#indications-of-a-confidential-issue "Permalink") + +> **注意:**如果您没有[足够的权限](#permissions-and-access-to-confidential-issues) ,您将根本看不到机密问题. + +有几件事在视觉上将机密问题与常规问题分开. 在问题索引页面视图中,您可以在标记为机密的问题旁边看到斜线图标. + +[![Confidential issues index page](img/8cebf5d928a8666adcfc25eccfeec89e.png)](img/confidential_issues_index_page.png) + +* * * + +同样,在问题内部,您可以在问题编号旁边看到斜线图标,但在注释区域中也有一个指示符,表明您正在评论的问题是机密的. + +[![Confidential issue page](img/ea665ae1d507d66f5a44d05ff9e32613.png)](img/confidential_issues_issue_page.png) + +侧边栏上还有一个指示保密性的指示器. + +| 机密问题 | 非机密问题 | +| --- | --- | +| [![Sidebar confidential issue](img/813e077e7aa22bb747b5f237984f1b22.png)](img/sidebar_confidential_issue.png) | [![Sidebar not confidential issue](img/6a33d33154553990ed15338a6f9c7b35.png)](img/sidebar_not_confidential_issue.png) | + +## Permissions and access to confidential issues[](#permissions-and-access-to-confidential-issues "Permalink") + +对于机密问题,有两种级别的访问权限. 一般规则是,机密问题仅对具有[Reporter 访问权限](../../permissions.html#project-members-permissions)的项目成员可见. 但是,来宾用户也可以创建机密问题,但只能查看他们自己创建的问题. + +对于非特权用户,机密问题也隐藏在搜索结果中. 例如,这是具有"维护者"和"访客"访问权限的用户分别在项目的搜索结果中看到的内容. + +| 维护者访问 | 来宾访问 | +| --- | --- | +| [![Confidential issues search master](img/30460bec4b16c49e4f5d5ccc7ac92601.png)](img/confidential_issues_search_master.png) | [![Confidential issues search guest](img/2bb7640bbe66bec0d43070f6f4053758.png)](img/confidential_issues_search_guest.png) | + +## Merge Requests for Confidential Issues[](#merge-requests-for-confidential-issues "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/58583) . + +为了帮助防止机密信息在解决机密问题的过程中从公共项目中泄露,可以通过创建私有派生的合并请求来解决机密问题. + +创建的合并请求将针对私有派生的默认分支,而不是公共上游项目的默认分支. 这样可以防止合并请求,分支和提交进入公共存储库,以及过早地泄露机密信息. 当准备好将机密提交公开时,可以通过打开从私有派生到公共上游项目的合并请求来完成. + +**最佳实践:**如果您在原始上游的同一组或子组中创建了一个长期的私有派生,则具有开发者成员身份的公共项目的所有用户在私有项目中也将具有相同的权限. 这样,所有有权查看机密问题的开发人员都将拥有简化的工作流程来解决这些问题. + +### How it works[](#how-it-works "Permalink") + +关于机密问题," **创建机密合并请求"**按钮可用. 单击它会打开一个下拉列表,您可以在其中选择**创建机密合并请求和分支**或**创建分支** : + +| 创建机密合并请求 | 创建分支 | +| --- | --- | +| [![Create Confidential Merge Request Dropdown](img/17d0ef7b105be8069a4258a758bd25bb.png)](img/confidential_mr_dropdown_v12_1.png) | [![Create Confidential Branch Dropdown](img/4f9a7d54cb4f539c606eaef8fd65b8ed.png)](img/confidential_mr_branch_dropdown_v12_1.png) | + +**项目**下拉列表包括用户所属的私有派生列表,至少是开发人员,并且合并请求已启用. + +每当" **分支名称"**和" **源(分支或标记)"**字段更改时,将检查目标或源分支的可用性. 两个分支都应在所选的私有派生中可用. + +通过单击**创建机密合并请求**按钮,GitLab 将在私有分支中创建分支和合并请求. 当选择**Create branch 时** ,GitLab 将仅创建分支. + +在私有分支中创建分支后,开发人员现在可以将代码推送到该分支以解决机密问题. \ No newline at end of file diff --git a/docs/100.md b/docs/100.md new file mode 100644 index 0000000000000000000000000000000000000000..8f5beb3bb0bcffc6d9767e4c59bc3b1902b4fd0b --- /dev/null +++ b/docs/100.md @@ -0,0 +1,47 @@ +# Due dates + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/due_dates.html](https://docs.gitlab.com/ee/user/project/issues/due_dates.html) + +* [Setting a due date](#setting-a-due-date) +* [Making use of due dates](#making-use-of-due-dates) + +# Due dates[](#due-dates "Permalink") + +在 GitLab 8.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3614) . + +请通读[GitLab 问题文档](index.html)以获取有关 GitLab 问题的概述. + +Due dates can be used in issues to keep track of deadlines and make sure features are shipped on time. Users must have at least [Reporter permissions](../../permissions.html) to be able to edit them, but they can be seen by everybody with permission to view the issue. + +## Setting a due date[](#setting-a-due-date "Permalink") + +创建或编辑问题时,您可以单击**截止日期**字段,然后出现一个日历来帮助您选择所需的日期. 要删除日期,请选择日期文本并将其删除. 该日期与服务器的时区有关,而不与设置到期日期的用户的时区有关. + +[![Create a due date](img/36abd47af07b3b82f814e74be4619b4d.png)](img/due_dates_create.png) + +您还可以通过问题侧边栏设置截止日期. 展开边栏,然后单击" **编辑"**以选择截止日期或删除现有的日期. 更改将立即保存. + +[![Edit a due date via the sidebar](img/2dde5152cc249727c2d1016051d52131.png)](img/due_dates_edit_sidebar.png) + +设置截止日期的最后一种方法是直接在问题的描述或注释中使用[快速操作](../quick_actions.html) : + +* `/due <date>` :设置到期日. 有效的`<date>`示例包括`in 2 days` ( `this Friday`和`December 31st` . +* `/remove_due_date` :删除到期日. + +## Making use of due dates[](#making-use-of-due-dates "Permalink") + +具有到期日期的问题可以在问题跟踪器中轻松查看,并在它们旁边显示一个日期. 日期过期的问题将图标和日期标记为红色. 您可以从右侧的下拉菜单中按`Due soon` `Due later`或`Due later` `Due soon`问题对问题进行排序. + +[![Issues with due dates in the issues index page](img/371d1ca1640afbd824acc19b18bc40c9.png)](img/due_dates_issues_index_page.png) + +截止日期也会出现在您的[待办事项清单中](../../todos.html) . + +[![Issues with due dates in the todos](img/9d0b2e21b9be06d263674db132420176.png)](img/due_dates_todos.png) + +未解决问题的前一天,将向该问题的所有参与者发送电子邮件. 与截止日期一样,"截止日期之前的一天"由服务器的时区确定. + +截止日期的问题也可以导出为 iCalendar 供稿. 提要的 URL 可以添加到日历应用程序中. 通过单击以下页面上的**订阅日历**按钮可以访问该提要: + +* 在**分配的问题**页面上,该页面链接在 GitLab 标头的右侧 +* 在" **项目问题"**页面上 +* 在**组问题**页面上 \ No newline at end of file diff --git a/docs/101.md b/docs/101.md new file mode 100644 index 0000000000000000000000000000000000000000..c5a4dc890570892db49f3fb0e5aa59531d8c4a49 --- /dev/null +++ b/docs/101.md @@ -0,0 +1,446 @@ +# Issue Boards + +> 原文:[https://docs.gitlab.com/ee/user/project/issue_board.html](https://docs.gitlab.com/ee/user/project/issue_board.html) + +* [Overview](#overview) + * [Advanced features of issue boards](#advanced-features-of-issue-boards) +* [How it works](#how-it-works) +* [Use cases](#use-cases) + * [Use cases for a single issue board](#use-cases-for-a-single-issue-board) + * [Use cases for multiple issue boards](#use-cases-for-multiple-issue-boards) + * [Scrum team](#scrum-team) + * [Organization of topics](#organization-of-topics) + * [Advanced team handover](#advanced-team-handover) + * [Quick assignments](#quick-assignments) +* [Issue board terminology](#issue-board-terminology) +* [Permissions](#permissions) +* [GitLab Enterprise features for issue boards](#gitlab-enterprise-features-for-issue-boards) + * [Summary of features per tier](#summary-of-features-per-tier) + * [Multiple issue boards](#multiple-issue-boards) + * [Create an issue board](#create-an-issue-board) + * [Delete an issue board](#delete-an-issue-board) + * [Configurable issue boards](#configurable-issue-boards-starter) + * [Focus mode](#focus-mode) + * [Sum of issue weights](#sum-of-issue-weights-starter) + * [Group issue boards](#group-issue-boards-premium) + * [Assignee lists](#assignee-lists-premium) + * [Milestone lists](#milestone-lists-premium) +* [Work In Progress limits](#work-in-progress-limits-starter) +* [Blocked issues](#blocked-issues) +* [Actions you can take on an issue board](#actions-you-can-take-on-an-issue-board) + * [First time using an issue board](#first-time-using-an-issue-board) + * [Create a new list](#create-a-new-list) + * [Delete a list](#delete-a-list) + * [Add issues to a list](#add-issues-to-a-list) + * [Remove an issue from a list](#remove-an-issue-from-a-list) + * [Filter issues](#filter-issues) + * [Create workflows](#create-workflows) + * [Drag issues between lists](#drag-issues-between-lists) + * [Multi-select issue cards](#multi-select-issue-cards) + * [Issue ordering in a list](#issue-ordering-in-a-list) +* [Tips](#tips) + +# Issue Boards[](#issue-boards "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5554) in [GitLab 8.11](https://about.gitlab.com/releases/2016/08/22/gitlab-8-11-released/#issue-board). + +## Overview[](#overview "Permalink") + +GitLab 发行板是一个软件项目管理工具,用于计划,组织和可视化功能或产品发布的工作流程. 它可以用作[看板](https://en.wikipedia.org/wiki/Kanban_(development))或[Scrum](https://en.wikipedia.org/wiki/Scrum_(software_development))板. + +它结合了问题跟踪和项目管理功能,将所有内容保持在同一位置,因此您无需在不同平台之间切换即可组织工作流程. + +使用问题板,您可以将问题组织在与其分配的标签相对应的列表中,从而在这些列表中可视化设计为卡片的问题. + +您定义流程,GitLab 会为您进行组织. 您添加标签,然后创建相应的列表以提取现有问题. 准备就绪后,可以将发行卡从一个步骤拖放到下一个步骤. + +[![GitLab issue board - Core](img/2a62cf1a17a5306e4d6cd91c30149941.png)](img/issue_boards_core.png) + +观看发布板功能的[视频演示](https://youtu.be/UWsJ8tkHAa8) (在 GitLab 8.11 中引入-2016 年 8 月). + +### Advanced features of issue boards[](#advanced-features-of-issue-boards "Permalink") + +* 每个项目创建多个发行板. +* 每个组创建多个发行板. +* 添加[受让人](#assignee-lists-premium)和[里程碑的](#milestone-lists-premium)列表. + +检查[GitLab Enterprise 的](#gitlab-enterprise-features-for-issue-boards)所有[功能是否有发行板](#gitlab-enterprise-features-for-issue-boards) . + +[![GitLab issue boards - Premium](img/e6522f2cefe000bb17275b2a0451bf82.png)](img/issue_boards_premium.png) + +## How it works[](#how-it-works "Permalink") + +发行板功能通过将 GitLab 现有的[发行跟踪功能](issues/index.html#issues-list)和[标签](labels.html)用作 Scrum 板的列表而建立. + +使用问题板,您可以对问题有不同的看法,同时保持在问题跟踪器中看到的相同过滤和排序功能. 发行板基于其项目的标签结构,因此它使用相同的描述性标签来指示在板上的位置,从而在整个开发生命周期中保持一致性. + +问题板向您显示团队正在处理的问题,分配给每个人的问题以及这些问题在工作流中的位置. + +您可以从一个平台创建问题,托管代码,执行审阅,构建,测试和部署. 问题板可帮助您在 GitLab 中可视化和管理整个过程. + +有了[多个发行板](#use-cases-for-multiple-issue-boards) ,您可以走得更远,因为您不仅可以从更广阔的角度组织自己和您的项目,每个项目使用一个发行板,还可以让您的团队成员通过在多个发行板中创建多个发行板来组织自己的工作流程.同一项目. + +## Use cases[](#use-cases "Permalink") + +有多种方法可以使用针对自己喜欢的工作流程量身定制的 GitLab 发行板. 这是发行板的一些常见用例. + +### Use cases for a single issue board[](#use-cases-for-a-single-issue-board "Permalink") + +借助 GitLab 工作流程,您可以讨论问题中的提案,使用标签对其进行分类,然后在其中使用问题委员会进行组织并确定优先级. + +例如,让我们考虑以下简化的开发工作流程: + +1. 您有一个托管应用程序代码库的存储库,而您的团队则在积极贡献代码. +2. 您的**后端**团队将开始新的实施工作,收集反馈和批准,并将其传递给**前端**团队. +3. 前端完成后,新功能将部署到要测试的**登台**环境中. +4. 成功后,它将部署到**生产中** . + +如果您具有标签" **后端** "," **前端** "," **暂存** "和" **生产** ",以及带有每个列表的发行板,则可以: + +* 可视化从开发生命周期开始到部署到生产的整个实现流程. +* 通过垂直移动优先顺序排列列表中的问题. +* 在列表之间移动问题,以根据您设置的标签进行整理. +* 通过选择一个或多个现有问题,将多个问题添加到板中的列表中. + +[![issue card moving](img/a1f2874d536bbec36fba8132d424e066.png)](img/issue_board_move_issue_card_list.png) + +### Use cases for multiple issue boards[](#use-cases-for-multiple-issue-boards "Permalink") + +借助[多个发行委员会](#multiple-issue-boards) ,每个团队可以拥有自己的董事会来单独组织其工作流程. + +#### Scrum team[](#scrum-team "Permalink") + +具有多个发行董事会,每个团队只有一个董事会. 现在,您可以在流程的每个部分中解决问题. 例如: **To Do** , **Doing**和**Done** . + +#### Organization of topics[](#organization-of-topics "Permalink") + +创建列表以按主题对问题进行排序,并快速在主题或组之间(例如**UX** , **Frontend**和**Backend**之间)进行更改. 更改反映在各个方面,因为更改列表会相应更新每个问题的标签. + +#### Advanced team handover[](#advanced-team-handover "Permalink") + +例如,假设我们有一个 UX 小组,其问题板包含: + +* **去做** +* **Doing** +* **Frontend** + +完成操作后,他们将卡移至**Frontend** . 前端团队的董事会看起来像: + +* **Frontend** +* **Doing** +* **Done** + +由 UX 团队**整理的**卡片准备就绪后,会自动显示在" **前端"**列中. + +**注意:**有关更广泛的用例,请参阅博客文章[GitLab 工作流程,概述](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/#gitlab-workflow-use-case-scenario) . 对于一个真实的用例示例,您可以了解为什么[Codepen 决定采用发行版](https://about.gitlab.com/blog/2017/01/27/codepen-welcome-to-gitlab/#project-management-everything-in-one-place)来改善多个[发行版](https://about.gitlab.com/blog/2017/01/27/codepen-welcome-to-gitlab/#project-management-everything-in-one-place)的工作流程. + +#### Quick assignments[](#quick-assignments "Permalink") + +为每个团队成员创建列表,然后将问题快速拖放到每个团队成员的列表中. + +## Issue board terminology[](#issue-board-terminology "Permalink") + +**发行板**代表您的**发行**的独特视图. 它可以有多个列表,每个列表由卡代表的问题组成. + +**列表**是问题板上的一列,显示与某些属性匹配的问题. 除了默认的"打开"和"关闭"列表外,每个其他列表还显示与您选择的标签,受让人或里程碑匹配的问题. 在每个列表的顶部,您可以看到属于该问题的数量. 列表类型包括: + +* **开** (默认):不属于其他列表中的一个所有打开的问题. 始终显示为最左边的列表. +* **已关闭** (默认):所有已关闭的问题. 始终显示为最右边的列表. +* **标签列表** : **标签的**所有未解决问题. +* [**受让人列表**](#assignee-lists-premium) :分配给用户的所有未解决的问题. +* [**里程碑列表**](#milestone-lists-premium) : [**里程碑的**](#milestone-lists-premium)所有未解决的问题. + +**卡**是列表中的一个框,它代表一个问题. 您可以将卡片从一个列表拖动到另一个列表,以更改其标签,受让人或里程碑. 卡上显示的信息包括: + +* 发行标题 +* 相关标签 +* 发行数量 +* Assignee + +## Permissions[](#permissions "Permalink") + +具有[报告者和更高角色的](../permissions.html)用户可以使用发布板功能的所有功能来创建或删除列表,并将问题从一个列表拖动到另一个列表. + +## GitLab Enterprise features for issue boards[](#gitlab-enterprise-features-for-issue-boards "Permalink") + +GitLab 核心和 GitLab.com 免费层上均提供 GitLab 发行板,但某些高级功能仅在[更高层中提供](https://about.gitlab.com/pricing/) . + +### Summary of features per tier[](#summary-of-features-per-tier "Permalink") + +下表列出了在不同的[GitLab 层](https://about.gitlab.com/pricing/)中可用的不同发行板功能: + +| Tier | 项目发行委员会的数量 | Number of Group issue boards | 可配置的发行板 | 受让人名单 | +| --- | --- | --- | --- | --- | +| 核心/免费 | Multiple | 1 | No | No | +| 入门/青铜 | Multiple | 1 | Yes | No | +| 高级/白银 | Multiple | Multiple | Yes | Yes | +| 终极/金 | Multiple | Multiple | Yes | Yes | + +### Multiple issue boards[](#multiple-issue-boards "Permalink") + +版本历史 + +* 在 GitLab 8.13 中[引入](https://about.gitlab.com/releases/2016/10/22/gitlab-8-13-released/) . +* 每个项目有多个发行板[移至](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53811) GitLab 12.1 中的[GitLab Core](https://about.gitlab.com/pricing/) . +* 每套[GitLab Premium 中](https://about.gitlab.com/pricing/)都有多个发行板. + +多个发行板允许给定项目或组使用多个发行板. 对于具有多个团队的大型项目,或者在使用存储库托管多个产品代码的情况下,这非常有用. + +使用菜单顶部的搜索框,您可以过滤列出的板. + +当您有十个或更多的板可用时,菜单中还会显示" **最近"**部分,其中包含最后四个被访问板的快捷方式. + +[![Multiple issue boards](img/dbb80511727781129d638c6d3413a45f.png)](img/issue_boards_multiple.png) + +当您在具有多个板的项目或组中重新访问问题板时,GitLab 会自动加载您上次访问的板. + +#### Create an issue board[](#create-an-issue-board "Permalink") + +要创建新的发行板: + +1. 单击"发行板"页面左上角的具有当前板名称的下拉菜单. +2. Click **创建新板**. +3. 输入新板的名称并选择其范围:里程碑,标签,受让人或权重. + +#### Delete an issue board[](#delete-an-issue-board "Permalink") + +要删除当前活动的发行板: + +1. 单击"发行板"页面左上角的具有当前板名称的下拉菜单. +2. Click **删除板**. +3. 单击**删除**进行确认. + +### Configurable issue boards[](#configurable-issue-boards-starter "Permalink") + +[Introduced](https://about.gitlab.com/releases/2017/11/22/gitlab-10-2-released/#issue-boards-configuration) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2. + +发行板可以与 GitLab [里程碑](milestones/index.html#milestones) , [标签](labels.html) ,受让人和权重关联,它们会根据这些字段自动过滤发行板问题. 这使您可以根据团队的需要创建独特的董事会. + +[![Create scoped board](img/bba7007707d548d73c9b6f0efad3c50b.png)](img/issue_board_creation.png) + +您可以在创建木板时或单击"编辑木板"按钮来定义木板的范围. 将里程碑,受让人或权重分配给发行板后,您将不再能够在搜索栏中进行筛选. 为此,您需要从发行板上删除所需的范围(例如,里程碑,受让人或权重). + +[![Edit board configuration](img/0d59f9135c1fed79a51921909516ef69.png)](img/issue_board_edit_button.png) + +如果您在木板中没有编辑权限,则仍然可以通过点击**查看范围**来**查看**配置. + +[![Viewing board configuration](img/c01efbb34a741e385a7089a6799e9b59.png)](img/issue_board_view_scope.png) + +### Focus mode[](#focus-mode "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 9.1 中[引入]((https://about.gitlab.com/releases/2017/04/22/gitlab-9-1-released/#issue-boards-focus-mode-ees-eep)) . +* [移动](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28597)到 GitLab.com 的自由层在 12.10\. +* 在 13.0 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/212331) GitLab Core. + +单击右上角的按钮可打开和关闭聚焦模式. 在焦点模式下,导航 UI 处于隐藏状态,使您可以集中精力处理板上的问题. + +[![Board focus mode](img/0fdd144a1493e4d21226f1b04a5d336a.png)](img/issue_board_focus_mode.gif) + +* * * + +### Sum of issue weights[](#sum-of-issue-weights-starter "Permalink") + +每个列表的顶部指示属于该列表的问题的问题权重之和. 当使用板进行容量分配时,尤其是与[受让人列表](#assignee-lists-premium)结合使用时,这很有用. + +[![issue board summed weights](img/38c073cc1c78dc88bf317e878e9995cc.png)](img/issue_board_summed_weights.png) + +### Group issue boards[](#group-issue-boards-premium "Permalink") + +[Introduced](https://about.gitlab.com/releases/2017/09/22/gitlab-10-0-released/#group-issue-boards) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.0. + +可以在组导航级别上访问,组问题委员会提供与项目级委员会相同的功能,但是它可以显示该组及其子孙组中所有项目的问题. 同样,您只能按组标签过滤这些板. 通过边栏更新机制更新问题的里程碑和标签时,再次只有组级对象可用. + +**注意:** [GitLab Premium](https://about.gitlab.com/pricing/) 10.0 最初[引入](https://about.gitlab.com/releases/2017/09/22/gitlab-10-0-released/#group-issue-boards)了多个组发行板,而 GitLab Core 10.6 提供了每个组一个组发行板. + +[![Group issue board](img/ce119917ec56b195b909d4371bb994aa.png)](img/group_issue_board.png) + +### Assignee lists[](#assignee-lists-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5784) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.0. + +就像在常规列表中显示带有选定标签的所有问题一样,您可以添加一个受让人列表,该列表显示分配给用户的所有问题. 您可以拥有一个包含标签列表和受让人列表的木板. 添加受让人列表: + +1. Click **新增清单**. +2. 选择" **受理人列表"**选项卡. +3. 搜索并单击要添加为受让人的用户. + +现在已添加了受让人列表,您可以通过[将问题拖到](#drag-issues-between-lists)受让人列表中或从受让人列表中[拖动问题](#drag-issues-between-lists)来向该用户分配或取消分配问题. 要删除受让人列表(与标签列表一样),请单击垃圾桶图标. + +[![Assignee lists](img/baa29e50412ef4acd25e287681ad9e9e.png)](img/issue_board_assignee_lists.png) + +### Milestone lists[](#milestone-lists-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6469) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2. + +You’re also able to create lists of a milestone. These are lists that filter issues by the assigned milestone, giving you more freedom and visibility on the issue board. To add a milestone list: + +1. Click **新增清单**. +2. 选择" **里程碑"**选项卡. +3. 搜索并单击里程碑. + +与受让人列表类似,您现在可以[将问题拖到](#drag-issues-between-lists)里程碑列表中或从里程碑列表中[拖动](#drag-issues-between-lists)出来,以操纵所拖动问题的里程碑. 与其他列表类型一样,单击垃圾桶图标以删除列表. + +[![Milestone lists](img/6261dd255633edf09ab3d7245ccaf2c1.png)](img/issue_board_milestone_lists.png) + +## Work In Progress limits[](#work-in-progress-limits-starter "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/11403) + +您可以为每个问题列表设置进行中(WIP)限制. 设置限制后,列表的标题将显示列表中的问题数和问题的软限制. + +Examples: + +* 您有一个包含四个问题的列表,限制为五个,标题将显示**4/5** . 如果超出限制,则当前的问题数将显示为红色. +* 您有一个包含五个问题的列表,限制为五个. 当您将另一个问题移到该列表时,列表的标题显示**6/5** ,其中六个显示为红色. + +设置列表的在制品限制: + +1. 导航到您所属的项目或小组委员会. +2. 点击设置图标( )放在列表​​标题中. +3. 在"进行中的**工作限制"**旁边,单击" **编辑"** . +4. 输入最大问题数. +5. 按`Enter`保存. + +## Blocked issues[](#blocked-issues "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34723) . + +如果一个问题被另一个问题阻止,则其标题旁边会出现一个图标,指示其阻止状态. + +[![Blocked issues](img/b1edf28a1aa5c59ffa779a574c4fc548.png)](img/issue_boards_blocked_icon_v12_8.png) + +## Actions you can take on an issue board[](#actions-you-can-take-on-an-issue-board "Permalink") + +* [Create a new list](#create-a-new-list). +* [Delete an existing list](#delete-a-list). +* [Add issues to a list](#add-issues-to-a-list). +* [Remove an issue from a list](#remove-an-issue-from-a-list). +* [筛选](#filter-issues)出现在问题板上的问题. +* [Create workflows](#create-workflows). +* [Drag issues between lists](#drag-issues-between-lists). +* [Multi-select issue cards](#multi-select-issue-cards). +* [Re-order issues in lists](#issue-ordering-in-a-list). +* 拖动列表并重新排序. +* 更改问题标签(通过在列表之间拖动问题). +* 解决问题(将其拖动到" **完成"**列表中). + +如果您无法执行上述某些操作,请确保您具有正确的[权限](#permissions) . + +### First time using an issue board[](#first-time-using-an-issue-board "Permalink") + +第一次打开问题面板时,会显示默认列表(" **打开"**和" **关闭"** )以及欢迎消息,其中提供了两个选项. 您可以: + +* 创建一组预定义的标签(默认情况下: **To Do**和**Doing** ),并在发行板上创建其对应的列表. +* 退出并使用自己的列表. + +[![issue board welcome message](img/768ab05f8c35931c200b6da1f8d92352.png)](img/issue_board_welcome_message.png) + +如果选择使用并创建预定义列表,则它们将显示为空,因为与它们关联的标签要到那时才存在,这意味着系统无法自动填充它们. 当然,如果预定义标签还不存在. 如果确实存在,则会创建该列表,并填充具有该标签的问题. + +### Create a new list[](#create-a-new-list "Permalink") + +通过单击发行板右上角的" **添加列表"**按钮来创建新列表. + +[![issue board welcome message](img/604dc2f6326d049dca30995958a84ad2.png)](img/issue_board_add_list.png) + +然后,选择标签或用户以从中创建列表. 新列表将被插入列表的末尾,在**完成**之前. 移动和重新排序列表就像拖动列表一样简单. + +要为尚不存在的标签创建列表,请选择**创建新标签**来**创建标签** . 这将立即创建标签并将其添加到下拉列表中. 现在,您可以选择它来创建列表. + +### Delete a list[](#delete-a-list "Permalink") + +要从发布板上删除列表,请使用列表标题中的小垃圾桶图标. 将出现一个确认对话框供您确认. + +删除列表对问题和标签没有任何影响,只是删除了列表视图. 如果需要,您随时可以将其添加回去. + +### Add issues to a list[](#add-issues-to-a-list "Permalink") + +您可以通过单击**问题**面板右上角的" **添加问题"**按钮将问题添加到列表中. 这将打开一个模式窗口,您可以在其中查看不属于任何列表的所有问题. + +通过单击卡片选择一个或多个问题,然后单击" **添加问题"**以将其添加到所选列表中. 您可以通过按作者,受让人,里程碑和标签筛选来限制要添加到列表中的问题. + +[![Bulk adding issues to lists](img/1d54aa31264e3f3b98ebf2049669f910.png)](img/issue_boards_add_issues_modal.png) + +### Remove an issue from a list[](#remove-an-issue-from-a-list "Permalink") + +从列表中删除问题可以通过单击问题卡,然后单击侧边栏中的**从**面板中**删除**按钮来完成. 相应的标签被删除. + +[![Remove issue from list](img/529405d6cc5cbeb813be69b57b0e45b1.png)](img/issue_boards_remove_issue.png) + +### Filter issues[](#filter-issues "Permalink") + +You should be able to use the filters on top of your issue board to show only the results you want. This is similar to the filtering used in the issue tracker since the metadata from the issues and labels are re-used in the issue board. + +您可以按作者,受让人,里程碑和标签过滤. + +### Create workflows[](#create-workflows "Permalink") + +通过对列表重新排序,可以创建工作流程. 由于发行版中的列表基于标签,因此可以与您现有的发行版一起使用. 因此,如果您已经用"后端"和"前端"标记了事物,则问题在创建它们时会出现在列表中. 此外,这意味着您可以通过更改标签轻松地在列表之间移动某些内容. + +使用发行板的典型工作流程为: + +1. 您已经[创建了](labels.html#label-management)标签并对其进行了[优先排序,](labels.html#label-priority)以便可以轻松地对问题进行分类. +2. 您遇到很多问题(理想情况下是带有标签的). +3. 您访问发行板并开始[创建列表](#create-a-new-list)以创建工作流程. +4. 您可以在列表中四处移动问题,以便您的团队知道谁应该处理什么问题. +5. 当一个团队的工作完成时,可以将问题拖到下一个列表中,以便其他人来接听. +6. 最终解决问题后,该问题将移至" **完成"**列表并自动关闭. + +例如,您可以基于"前端"标签和"后端"标签创建一个列表. 设计师可以通过将问题添加到"前端"列表来开始处理问题. 这样,每个人都知道设计师现在正在研究此问题. 然后,一旦完成,所有要做的就是将其拖到下一个列表"后端",后端开发人员最终可以在该列表中进行选择. 完成后,将其移至**完成** ,以解决问题. + +访问问题时可以清楚地看到此过程,因为每次移动到另一个列表时,标签都会更改,并且不会记录系统. + +[![issue board system notes](img/1be5fea51b824b103e9b5bac12136a90.png)](img/issue_board_system_notes.png) + +### Drag issues between lists[](#drag-issues-between-lists "Permalink") + +在列表之间拖动问题时,根据源列表和目标列表,会发生不同的行为. + +|   | 打开 | 要关闭 | 标记`B`列表 | 分配受让人`Bob`清单 | +| --- | --- | --- | --- | --- | +| 从开放 | - | 问题已结案 | `B` added | `Bob` assigned | +| 从关闭 | 问题重新开放 | - | 问题重新开放 +`B`添加 | 问题重新开放 +`Bob`分配 | +| 从标签`A`列表 | `A` removed | 问题已结案 | `A` removed +`B` added | `Bob` assigned | +| 从受让人`Alice`名单 | `Alice` unassigned | 问题已结案 | `B` added | `Alice` unassigned +`Bob` assigned | + +### Multi-select issue cards[](#multi-select-issue-cards "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/18954) . + +您可以选择多个发行卡,然后将组拖动到列表中的另一个位置或另一个列表中. 这样可以更快地一次重新排序许多问题. + +要选择并移动多张卡片: + +1. 使用`Ctrl`选择每个卡+ `Click`在 Windows 或 Linux,或者`Cmd 的` + `Click`在 MacOS. +2. 将所选卡中的一张拖到另一个位置或列表,所有所选卡都将移动. + +[![Multi-select Issue Cards](img/09b8263a3534de004ff180005a876b4a.png)](img/issue_boards_multi_select_v12_4.png) + +### Issue ordering in a list[](#issue-ordering-in-a-list "Permalink") + +访问董事会时,问题在任何列表中都显示为有序. 您可以通过拖放问题来更改顺序. 更改后的订单将保存到系统中,以便以后访问同一板的任何人都可以看到重新排序,但有一些例外. + +给定问题首次出现在任何面板中(即,用户首次加载包含该问题的面板)时,将根据[优先级顺序](labels.html#label-priority)对该列表中的其他问题进行[排序](labels.html#label-priority) . + +此时,系统会为该问题分配一个相对顺序值,该值代表其相对于列表中其他问题的相对顺序. 每当您拖放该问题的重新排序时,其相对订单值都会相应更改. + +同样,当问题由用户加载时,在任何板上出现的任何时间,都会使用更新的相对订单值进行订购. (这是第一次出现从上述优先顺序中提取问题的问题.)这意味着,如果您的 GitLab 实例内给定板上的任何用户将问题`A`拖放到问题`B`上方的顺序进行了重新排序,每当随后将这两个问题加载到同一实例中的任何板(例如,可以是不同的项目板或不同的组板)中时,都将维持订购. + +此顺序还会影响[问题列表](issues/sorting_issue_lists.html) . 在发行板上更改订单会更改发行列表中的顺序,反之亦然. + +## Tips[](#tips "Permalink") + +需要记住的几件事: + +* 在列表之间移动问题会从其来源列表中删除标签,并从其去往列表中添加标签. +* 如果一个问题有多个标签,则它可以存在于多个列表中. +* 如果标记了问题,则会自动用问题填充列表. +* 单击卡片内的问题标题,将您转到该问题. +* 单击卡内的标签可快速筛选整个问题板,并仅显示所有带有该标签的列表中的问题. +* 出于性能和可见性的原因,每个列表默认显示前 20 个问题. 如果问题超过 20 个,请开始向下滚动,然后出现下 20 个问题. \ No newline at end of file diff --git a/docs/102.md b/docs/102.md new file mode 100644 index 0000000000000000000000000000000000000000..97ae102bcb7effb09ce0adb8cb3ea1b6ca0bf952 --- /dev/null +++ b/docs/102.md @@ -0,0 +1,266 @@ +# Issue Data and Actions + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/issue_data_and_actions.html](https://docs.gitlab.com/ee/user/project/issues/issue_data_and_actions.html) + +* [Parts of an Issue](#parts-of-an-issue) + * [New Issue, close issue (reopen issue, report issue)](#new-issue-close-issue-reopen-issue-report-issue) + * [To Do](#to-do) + * [Assignee](#assignee) + * [Multiple Assignees](#multiple-assignees-starter) + * [Epic](#epic-premium) + * [Milestone](#milestone) + * [Time tracking](#time-tracking) + * [Due date](#due-date) + * [Labels](#labels) + * [Weight](#weight-starter) + * [Confidentiality](#confidentiality) + * [Lock issue](#lock-issue) + * [Participants](#participants) + * [Notifications](#notifications) + * [Reference](#reference) + * [Edit](#edit) + * [Description](#description) + * [Mentions](#mentions) + * [Related Issues](#related-issues-starter) + * [Related Merge Requests](#related-merge-requests) + * [Award emoji](#award-emoji) + * [Show all activity](#show-all-activity) + * [Create Merge Request](#create-merge-request) + * [Issue history](#issue-history) + * [Activity sort order](#activity-sort-order) + * [Comments](#comments) + * [Submit comment, start a thread, or comment and close](#submit-comment-start-a-thread-or-comment-and-close) + * [Zoom meetings](#zoom-meetings) + * [Publish an issue](#publish-an-issue-ultimate) + +# Issue Data and Actions[](#issue-data-and-actions "Permalink") + +请通读[GitLab 问题文档](index.html)以获取有关 GitLab 问题的概述. + +## Parts of an Issue[](#parts-of-an-issue "Permalink") + +下图说明了问题的外观. 请注意,根据使用的 GitLab 版本和查看问题的用户权限,某些部分看起来可能会略有不同或不存在. + +您可以在一个屏幕上找到该问题的所有信息. + +[![Issue view](img/b6662e0dd306cb7949bbfd70db9b384c.png)](img/issues_main_view_numbered.png) + +* **1.** [New Issue, close issue (reopen issue, report issue)](#new-issue-close-issue-reopen-issue-report-issue) +* **2.** [To Do](#to-do) +* **3.** [Assignee](#assignee) + * **3.1.** [Multiple Assignees](#multiple-assignees-starter) +* **4.** [Epic](#epic-premium) +* **5.** [Milestone](#milestone) +* **6.** [Time tracking](#time-tracking) +* **7.** [Due date](#due-date) +* **8.** [Labels](#labels) +* **9.** [Weight](#weight-starter) +* **10.** [Confidentiality](#confidentiality) +* **11.** [Lock issue](#lock-issue) +* **12.** [Participants](#participants) +* **13.** [Notifications](#notifications) +* **14.** [Reference](#reference) +* **15.** [Edit](#edit) +* **16.** [Description](#description) +* **17.** [Mentions](#mentions) +* **18.** [Related Issues](#related-issues-starter) +* **19.** [Related Merge Requests](#related-merge-requests) +* **20.** [Award emoji](#award-emoji) +* **21.** [Show all activity](#show-all-activity) +* **22.** [Create Merge Request](#create-merge-request) +* **23.** [Issue history](#issue-history) + * [Activity sort order](#activity-sort-order) +* **24.** [Comments](#comments) +* **25.** [Submit comment, start a thread, or comment and close](#submit-comment-start-a-thread-or-comment-and-close) +* **26.** [Zoom meetings](#zoom-meetings) + +问题从状态(打开或关闭)开始,然后是作者,并包括许多其他功能,在上图中编号,以逐一解释其含义. + +当问题由其他用户更改时,问题屏幕的许多元素都会自动刷新,例如标题和说明. 注释和系统注释也会根据各种操作和内容更新自动更新. + +### New Issue, close issue (reopen issue, report issue)[](#new-issue-close-issue-reopen-issue-report-issue "Permalink") + +单击" **新问题"**将打开一个新窗口,以在同一项目中创建一个新问题. 单击**关闭问题**将关闭此问题,但不会被删除. 如果问题已经关闭,您仍然可以访问它,并且按钮将显示**Reopen issue** ,如下所示,您可以单击以重新打开问题. 重新开放的问题与其他任何问题都没有不同. + +[![Reopen Issue](img/136df5416c67f2d80606b4849658e289.png)](img/reopen-issue.png) + +如果您无权修改问题,则" **关闭问题"**按钮将替换为" **报告问题"** ,您可以单击该按钮以[提交](../../abuse_reports.html)有关该问题[的滥用情况报告](../../abuse_reports.html) . 如果您有权修改问题,但仅在关闭问题后,它也会显示. + +[![Report Abuse](img/16f0d7c3d19700b0e30aa6c1528acb91.png)](img/report-abuse.png) + +### To Do[](#to-do "Permalink") + +您可以在[GitLab 任务列表中](../../todos.html)添加问题或从中删除问题. + +执行此操作的按钮具有不同的标签,具体取决于问题是否已在"任务列表"中. 如果问题是: + +* 已在您的待办事项清单上:该按钮标有" **标记为已完成"** . 单击按钮以从您的任务列表中删除该问题. +* 不在您的待办事项清单上:该按钮标有**添加待办事项** . 单击按钮将问题添加到您的"任务列表"中. + +### Assignee[](#assignee "Permalink") + +可以将问题分配给: + +* Yourself. +* 另一个人. +* [Many people](#multiple-assignees-starter). + +可以根据需要频繁更改受让人. 想法是,受让人应对该问题负责,直到将其重新分配给其他人以解决该问题为止. 分配给某人后,它将显示在其分配的问题列表中. + +**提示:**如果用户不是该项目的成员,则只有他们自己创建问题后才能将其分配给他们. + +#### Multiple Assignees[](#multiple-assignees-starter "Permalink") + +通常,多个人会共同处理同一问题,而在拥有问题共享所有权的大型团队中,跟踪这些问题尤其困难. + +在[GitLab Starter 中](https://about.gitlab.com/pricing/) ,您可以[将多个人分配](multiple_assignees_for_issues.html)给一个问题. + +### Epic[](#epic-premium "Permalink") + +您可以将问题分配给[Epic](../../group/epics/index.html) ,从而可以更好地管理相关问题组. + +### Milestone[](#milestone "Permalink") + +选择一个[里程碑](../milestones/index.html) ,将问题归因于此. + +### Time tracking[](#time-tracking "Permalink") + +使用[GitLab 快速行动](../quick_actions.html)来[跟踪估计和花费在问题上的时间](../time_tracking.html) . 您可以添加解决问题[所需时间](../time_tracking.html#estimates)的[估计,](../time_tracking.html#estimates)还可以添加解决问题[所花费的时间](../time_tracking.html#time-spent) . + +### Due date[](#due-date "Permalink") + +当您的工作时间很紧时,重要的是要有一种方法来为实现和解决问题设置截止日期. 这可以在[截止日期](due_dates.html)元素中完成. 截止日期可以根据需要进行多次更改. + +### Labels[](#labels "Permalink") + +通过给它们加上[标签](../labels.html)来对问题进行分类. 它们有助于组织工作流程,并使您能够与[GitLab 发行委员会合作](index.html#issue-boards) . + +还可以为组标签分配问题,该组标签允许您对同一组内的所有项目使用相同的标签. 它们的工作原理完全相同,但可立即用于该组中的所有项目. + +**提示:**如果标签尚不存在,可以单击**编辑** ,它会打开一个下拉菜单,从中可以选择**创建新标签** . + +### Weight[](#weight-starter "Permalink") + +为问题[分配权重](issue_weight.html) . 使用较大的值表示完成此问题需要付出更多的努力. 仅允许正值或零. + +### Confidentiality[](#confidentiality "Permalink") + +您可以[将问题设置为机密](confidential_issues.html) . 设置后,未经授权的用户将无法访问该问题,也不会在项目问题委员会或问题列表中看到该问题. + +### Lock issue[](#lock-issue "Permalink") + +您可以[锁定问题中的线程](../../discussions/index.html#lock-discussions) ,以防止添加更多评论. + +### Participants[](#participants "Permalink") + +涉及该问题的所有用户. 他们要么参与了该[线程](../../discussions/index.html) ,要么在描述或线程中被提及. + +### Notifications[](#notifications "Permalink") + +单击该图标以启用/禁用该问题的[通知](../../profile/notifications.html#issue--epics--merge-request-events) . 如果您以任何方式参与该问题,它将自动启用. + +* **Enable**: If you are not a participant in the discussion on that issue, but want to receive notifications on each update, subscribe to it. +* **禁用** :如果您正在接收有关该问题的更新通知,但不再希望接收它们,请取消订阅. + +### Reference[](#reference "Permalink") + +* 快速"复制"按钮,这个问题的参考,它看起来像`foo/bar#xxx` ,其中`foo`是`username`或`groupname` , `bar`是`project-name` ,并且`xxx`是发行数量. + +### Edit[](#edit "Permalink") + +单击此图标可打开要编辑的问题,您将有权访问与创建问题时相同的所有字段. 如果用户没有编辑问题的权限,则不会显示此图标. + +### Description[](#description "Permalink") + +纯文本标题和问题描述位于问题页面的顶部中心. 该描述完全支持[GitLab 风味 Markdown](../../markdown.html#gitlab-flavored-markdown-gfm) ,允许许多格式选项. + +> [自 GitLab 12.6 起](https://gitlab.com/gitlab-org/gitlab/-/issues/10103) , [问题历史记录](#issue-history)中列出了对[问题](#issue-history)描述的更改. + +### Mentions[](#mentions "Permalink") + +您可以使用`@username`或`@groupname`提及您的 GitLab 实例中存在的用户或组,除非他们在配置文件设置中禁用了所有通知,否则它们将通过待办事项和电子邮件得到通知. 这是在[通知设置中](../../profile/notifications.html)控制的. + +自己的提及(当前登录的用户)将以不同的颜色突出显示,使您可以轻松查看涉及到的评论,帮助您快速关注它们. + +**提示:**避免在问题中提及`@all`并合并请求,因为它会向该项目组的所有成员发送电子邮件通知,这可以解释为垃圾邮件. + +### Related Issues[](#related-issues-starter "Permalink") + +这里列出了被称为[相关问题的问题](related_issues.html) . 您也可以单击`+`添加更多相关问题. + +### Related Merge Requests[](#related-merge-requests "Permalink") + +该问题的描述或问题线程中提到的[合并请求](crosslinking_issues.html#from-merge-requests)在此处列为[相关合并请求](crosslinking_issues.html#from-merge-requests) . 另外,如果当前问题在另一个合并请求中被提及是相关的,则该合并请求将在此处列出. + +### Award emoji[](#award-emoji "Permalink") + +您可以为该问题授予表情符号. 有" thumbs_up"和" thumbs_down"的快捷方式,或者您可以单击浅灰色的" face"从可用的[GitLab 风味 Markdown Emoji](../../markdown.html#emoji)下拉列表中选择其他反应. + +**提示:在主题中**张贴" +1"作为评论会对该问题的所有订阅参与者造成垃圾邮件,会使主题混乱,因此不建议这样做. 授予表情符号是一种让他们知道您的反应而不会向其发送垃圾邮件的方法. + +### Show all activity[](#show-all-activity "Permalink") + +您可以通过单击**显示所有活动**并选择以下任一内容来过滤问题历史记录中**显示的内容** : + +* **仅显示评论** ,仅显示主题并隐藏问题的更新. +* **仅显示历史记录** ,它隐藏线程并且仅显示更新. + +Also: + +* 您可以使用`@username`或`@groupname`提及您的 GitLab 实例中存在的用户或组,除非他们已[禁用](#notifications)其配置文件设置中的[所有通知](#notifications) ,否则它们将通过待办事项和电子邮件得到[通知](#notifications) . +* 自己的提及(当前登录的用户)将以不同的颜色突出显示,使您可以轻松查看涉及到的评论,帮助您快速关注它们. + +[![Show all activity](img/6a23362ee367dd144c2c8ea315b8dde0.png)](img/show-all-activity.png) + +### Create Merge Request[](#create-merge-request "Permalink") + +在一个动作中创建一个新的分支和[**草稿**合并请求](../merge_requests/work_in_progress_merge_requests.html) . 默认情况下,该分支将被命名为`issuenumber-title` ,但是您可以选择任何名称,并且 GitLab 会验证该分支尚未被使用. 合并请求将自动继承问题的里程碑和标签,并设置为在合并时关闭问题. + +[![Create MR from issue](img/2a301148b56e04c50113445dc7280c15.png)](img/create_mr_from_issue.png) + +(可选)您可以选择仅创建一个[新分支](../repository/web_editor.html#create-a-new-branch-from-an-issue) ,以该问题命名. + +### Issue history[](#issue-history "Permalink") + +All comments and updates to the issue are tracked and listed here, but this can be filtered, as shown above. + +#### Activity sort order[](#activity-sort-order "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/14588) . + +您可以颠倒默认顺序,并与按顶部的最新项目排序的活动供稿进行交互. 您的首选项通过本地存储保存,并自动应用于您查看的每个问题. + +要更改活动排序顺序,请单击**最旧的第一个**下拉菜单,然后选择最旧或最新的项目以首先显示. + +[![Issue activity sort order dropdown button](img/db92110fba2588fed57b9af6bb2a381c.png)](img/issue_activity_sort_order_v12_10.png) + +### Comments[](#comments "Permalink") + +通过在其主题中发布评论来协作解决问题. 该文本字段还完全支持[GitLab 风味 Markdown](../../markdown.html#gitlab-flavored-markdown-gfm) . + +### Submit comment, start a thread, or comment and close[](#submit-comment-start-a-thread-or-comment-and-close "Permalink") + +撰写评论后,您可以: + +* 单击**评论** ,您的评论将被发布. +* 选择从下拉列表中**启动线程** ,并启动一个新[的线程](../../discussions/index.html#threaded-discussions)这个问题的主线程中讨论具体的点. 这邀请其他参与者直接回复您的主题,并将相关评论分组在一起. + +[![Comment or thread](img/9cb5bb737c82aad68bc28e2a7357e05c.png)](img/comment-or-discussion.png) + +您也可以从此处关闭问题,因此无需滚动到问题页面的顶部. + +### Zoom meetings[](#zoom-meetings "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31103) . + +您可以使用`/zoom`和`/remove_zoom` [快速动作](../quick_actions.html)将[GitLab](../../markdown.html#gitlab-flavored-markdown-gfm) `/remove_zoom` [Markdown](../../markdown.html#gitlab-flavored-markdown-gfm)作为附件添加和删除 Zoom 会议. + +附加问题的[Zoom](https://zoom.us)呼叫会导致问题顶部顶部标题下方的" **加入 Zoom"会议**按钮. + +详细了解如何[添加或删除缩放会议](associate_zoom_meeting.html) . + +### Publish an issue[](#publish-an-issue-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30906) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1. + +If a status page application is associated with the project, you can use the `/publish` [quick action](../quick_actions.html) to publish the issue. Refer to [GitLab Status Page](../status_page/index.html) for more information. \ No newline at end of file diff --git a/docs/103.md b/docs/103.md new file mode 100644 index 0000000000000000000000000000000000000000..dfe90d9a1a796ed97dfce63f0e05f6cc2cc75f60 --- /dev/null +++ b/docs/103.md @@ -0,0 +1,209 @@ +# Labels + +> 原文:[https://docs.gitlab.com/ee/user/project/labels.html](https://docs.gitlab.com/ee/user/project/labels.html) + +* [Overview](#overview) +* [Project labels and group labels](#project-labels-and-group-labels) +* [Assign and unassign labels](#assign-and-unassign-labels) +* [Label management](#label-management) + * [Project labels](#project-labels) + * [Promote a project label to a group label](#promote-a-project-label-to-a-group-label) + * [Group labels](#group-labels) + * [Create group labels from epics](#create-group-labels-from-epics-ultimate) + * [Generate default labels](#generate-default-labels) +* [Scoped labels](#scoped-labels-premium) + * [Workflows with scoped labels](#workflows-with-scoped-labels) + * [Scoped labels with nested scopes](#scoped-labels-with-nested-scopes) +* [Subscribing to labels](#subscribing-to-labels) +* [Label priority](#label-priority) +* [Troubleshooting](#troubleshooting) + * [Some label titles end with `_duplicate<number>`](#some-label-titles-end-with-_duplicatenumber) + +# Labels[](#labels "Permalink") + +## Overview[](#overview "Permalink") + +随着您在 GitLab 中问题,合并请求和史诗数量的增长,跟踪这些项目变得越来越困难. 尤其是随着您的组织从只有几个人发展到成百上千. 标签就是在这里出现的.它们可以帮助您组织和标记工作,以便您可以跟踪和找到您感兴趣的工作项. + +标签是[发行板](issue_board.html)的关键部分. 使用标签,您可以: + +* 使用颜色和描述性标题(例如`bug` , `feature request`或`docs`对史诗,问题和合并请求进行分类. +* 动态过滤和管理史诗,问题和合并请求. +* [搜索问题列表,合并请求和史诗](../search/index.html#issues-and-merge-requests)以及[问题面板](../search/index.html#issue-boards) . + +## Project labels and group labels[](#project-labels-and-group-labels "Permalink") + +GitLab 中有两种类型的标签: + +* **项目标签**只能分配给该项目,并且只能合并该项目中的请求. +* 可以将**组标签**分配给选定组或其子组中的任何项目中的问题并合并请求. + * 也可以将它们分配给所选组或其子组中的史诗. + +## Assign and unassign labels[](#assign-and-unassign-labels "Permalink") + +每个问题,合并请求和史诗都可以分配任意数量的标签. 标签在右侧栏中管理,您可以在其中根据需要分配或取消分配标签. + +要将标签分配给问题,请合并请求或史诗: + +1. 在侧边栏的标签部分,点击**编辑** ,然后: + * 在列表中,单击所需的标签. 每个标签都带有复选标记. + * 通过输入搜索查询并单击搜索来查找标签( ),然后点击它们. 您可以反复搜索并添加更多标签. +2. 单击**X**或标签部分之外的任何位置,然后将应用标签. + +您也可以使用[`/assign @username`快速操作](quick_actions.html)来分配标签. + +## Label management[](#label-management "Permalink") + +具有 Reporter 或更高[权限级别](../permissions.html)的用户可以创建和编辑标签. + +### Project labels[](#project-labels "Permalink") + +通过转到项目并单击**问题>标签**来查看项目标签列表. 该列表包括在项目级别定义的所有标签,以及从直接父组继承的所有标签. 您可以通过在顶部输入搜索查询并点击搜索( ). + +要创建一个新的项目标签: + +1. 导航到项目中的" **问题">"标签** ". +2. 单击**新建标签**按钮. + * 输入标题. + * (可选)输入描述. + * (可选)通过单击可用颜色来选择背景颜色,或输入特定颜色的十六进制颜色值. +3. 单击**创建标签**以创建标签. + +您也可以从发布或合并请求中创建新的项目标签. 在问题或合并请求的右侧栏中的标签部分: + +1. Click **Edit**. +2. Click **创建项目标签**. + * 填写名称字段. 请注意,如果以此方式创建标签,则无法指定描述. 您可以稍后通过编辑标签来添加描述(请参见下文). + * (可选)通过单击可用颜色来选择颜色,或输入特定颜色的十六进制颜色值. +3. Click **Create**. + +创建标签后,您可以通过点击铅笔( ),或通过单击三个点( )旁边的" **订阅"**按钮,然后选择" **删除"** . + +#### Promote a project label to a group label[](#promote-a-project-label-to-a-group-label "Permalink") + +如果您以前创建了项目标签,现在想使其可用于同一组中的其他项目,则可以将其升级为组标签. + +如果同一组中的其他项目具有相同标题的标签,则它们将全部与新的组标签合并. 如果存在具有相同标题的组标签,则它也会被合并. + +所有发行,合并请求,发行板列表,发行板过滤器以及带有旧标签的标签订阅都将分配给新的组标签. + +警告: **警告:**提升标签是永久性的操作,不能撤消. + +要将项目标签提升为组标签: + +1. 导航到项目中的" **问题">"标签** ". +2. 单击三个点( )旁边的**订阅**按钮,然后选择**升级为组标签** . + +### Group labels[](#group-labels "Permalink") + +通过转到组并单击**问题>标签**来查看组标签列表. 该列表包括仅在组级别定义的所有标签. 它没有列出项目中定义的任何标签. 您可以通过在顶部输入搜索查询并点击搜索( ). + +要创建**组标签** ,请导航到**组中的"** **问题">"标签"** ,并按照与[创建项目标签](#project-labels)相同的过程进行操作. + +#### Create group labels from epics[](#create-group-labels-from-epics-ultimate "Permalink") + +您可以从 Epic 侧边栏创建组标签. 您创建的标签将属于该史诗所属的直接组. 该过程与根据[发布或合并请求](#project-labels)创建[项目标签](#project-labels)的过程相同. + +### Generate default labels[](#generate-default-labels "Permalink") + +如果项目或组没有标签,则可以从标签列表页面生成一组默认的项目或组标签. 如果列表为空,该页面将显示一个" **生成默认标签集"**按钮,单击该按钮会将以下默认标签添加到项目中: + +* `bug` +* `confirmed` +* `critical` +* `discussion` +* `documentation` +* `enhancement` +* `suggestion` +* `support` + +## Scoped labels[](#scoped-labels-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9175) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.10. + +范围标签允许团队使用标签功能来注释问题,合并请求和具有互斥标签的史诗. 通过防止某些标签一起使用,可以启用更复杂的工作流程. + +当标签标题中使用特殊的双冒号( `::` :)语法时,该标签将成为作用域,例如: + +[![Sample scoped labels](img/eeadc0bb054ceec8f09d2c44982f4103.png)](img/labels_key_value_v12_1.png) + +issue,merge request 或 epic 不能具有形式为`key::value`且具有相同`key`两个范围标签. 使用相同的`key`添加一个新标签,但是使用不同的`value`将导致以前的`key`标签被新标签替换. + +用例示例: + +1. 一个问题被标识为低优先级,并向其添加了`priority::low`项目标签. +2. 经过更多审查后,问题优先级增加了,并添加了`priority::high`标签. +3. manbetx 客户端打不开会自动删除`priority::low`标签,因为一个问题不应同时具有两个优先级标签. + +### Workflows with scoped labels[](#workflows-with-scoped-labels "Permalink") + +假设您要在问题中创建一个自定义字段,以跟踪功能所针对的操作系统平台,而每个问题只应针对一个平台. 然后,您将创建三个标签`platform::iOS` , `platform::Android` , `platform::Linux` . 在给定的问题上应用这些标签中的任何一个都会自动删除以`platform::`开头的任何其他现有标签. + +可以将相同的模式应用于代表团队的工作流状态. 假设您具有标签以下标签`workflow::development` , `workflow::review`和`workflow::deployed` . 如果一个问题已经应用了标签`workflow::development` ,并且开发人员想要将该问题推进到`workflow::review` ,他们将简单地应用该标签,然后`workflow::development`标签将被自动删除. 当您在整个标签列表中移动的问题这种行为已经存在[问题板](issue_board.html#create-workflows) ,但现在,谁可能无法在一个问题板上工作的团队成员直接将仍然能够推进工作流程中的问题始终国家本身. + +在有关[将范围标签用于自定义字段和工作流](https://www.youtube.com/watch?v=4BCBby6du3c)的视频中演示了此功能. + +### Scoped labels with nested scopes[](#scoped-labels-with-nested-scopes "Permalink") + +创建标签时,可以使用多个双冒号`::`来创建具有嵌套作用域的标签. 在这种情况下,最后一个`::`之前的所有内容都将成为作用域. + +例如, `workflow::backend::review`和`workflow::backend::development`是有效的作用域标签,但是它们**不能同时**存在于同一问题上,因为它们都共享相同的作用域, `workflow::backend` . + +此外, `workflow::backend::review`和`workflow::frontend::review`是有效的范围标签,并且它们**可以同时**存在于同一问题上,因为它们都具有不同的范围, `workflow::frontend`和`workflow::backend` . + +## Subscribing to labels[](#subscribing-to-labels "Permalink") + +在项目标签列表页面和组标签列表页面中,您可以单击任何标签右侧的**订阅**以启用该标签的[通知](../profile/notifications.html) . 只要将标签分配给史诗,发行或合并请求,您就会收到通知. + +如果要从项目内订阅组标签,则可以选择仅订阅项目或整个组的标签通知. + +[![Labels subscriptions](img/074834195e0c24213cffeef5ef08a9e1.png)](img/labels_subscriptions_v12_1.png) + +## Label priority[](#label-priority "Permalink") + +版本历史 + +* 在 GitLab 8.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14189) . +* 优先级排序仅基于最高优先级标签. [讨论中](https://gitlab.com/gitlab-org/gitlab/-/issues/14523)考虑改变这一点. + +标签可以具有相对优先级,在史诗,发布和合并请求列表页面的" **标签优先级"**和" **优先级"**排序顺序中使用. 组标签和项目标签的优先级都在项目级别进行,不能从组标签列表中进行. + +在项目标签列表页面上,在标签上加上星号以表明它具有优先级. + +[![Labels prioritized](img/2fe480e26b1b89b82607729986e5b13a.png)](img/labels_prioritized_v12_1.png) + +在列表中上下拖动已加星标的标签以更改其优先级,列表中的较高表示优先级较高. + +[![Drag to change label priority](img/9e837ca8522bced4f7b219416c893fe4.png)](img/labels_drag_priority_v12_1.gif) + +在史诗般的,合并请求和问题列表页面上(针对组和项目),您可以按`Label priority`或`Priority`进行排序. + +如果您按`Label priority`排序,则 GitLab 将使用以下排序比较顺序: + +1. 具有较高优先级标签的项目. +2. 没有优先标签的项目. + +领带被任意打破. 请注意,只会检查优先级最高的标签,而忽略优先级较低的标签. 有关更多信息,请参见此[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/14523) . + +[![Labels sort label priority](img/3636c78ef6cb3ccc1462dd451c7f3efc.png)](img/labels_sort_label_priority.png) + +如果您按`Priority`排序,则 GitLab 将使用以下排序比较顺序: + +1. 具有里程碑的截止日期的项目,最早分配的[里程碑](milestones/index.html)在此列出. +2. 具有里程碑的项目,没有截止日期. +3. 具有较高优先级标签的项目. +4. 没有优先标签的项目. + +领带被任意打破. + +[![Labels sort priority](img/640bc8c28d8cd3035fbe0c4c1018d2d1.png)](img/labels_sort_priority.png) + +## Troubleshooting[](#troubleshooting "Permalink") + +### Some label titles end with `_duplicate<number>`[](#some-label-titles-end-with-_duplicatenumber "Permalink") + +在特定情况下,可以在同一名称空间中创建具有重复标题的标签. + +为了解决重复问题, [在 GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21384)和更高版本中,某些重复标签的标题后面`_duplicate<number>` . + +如果愿意,可以安全地更改这些标签的标题. 有关原始问题的详细信息,请参见[问题 30390](https://gitlab.com/gitlab-org/gitlab/issues/30390) . \ No newline at end of file diff --git a/docs/104.md b/docs/104.md new file mode 100644 index 0000000000000000000000000000000000000000..ecf246fda9cacbd57737130371e7352c67519dda --- /dev/null +++ b/docs/104.md @@ -0,0 +1,230 @@ +# Managing issues + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/managing_issues.html](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html) + +* [Create a new issue](#create-a-new-issue) + * [Accessing the New Issue form](#accessing-the-new-issue-form) + * [Elements of the New Issue form](#elements-of-the-new-issue-form) + * [New issue from the group-level Issue Tracker](#new-issue-from-the-group-level-issue-tracker) + * [New issue via Service Desk](#new-issue-via-service-desk-starter) + * [New issue via email](#new-issue-via-email) + * [New issue via URL with prefilled fields](#new-issue-via-url-with-prefilled-fields) +* [Moving Issues](#moving-issues) + * [Moving Issues in Bulk](#moving-issues-in-bulk) +* [Closing issues](#closing-issues) + * [Closing issues automatically](#closing-issues-automatically) + * [Default closing pattern](#default-closing-pattern) + * [Disabling automatic issue closing](#disabling-automatic-issue-closing) + * [Customizing the issue closing pattern](#customizing-the-issue-closing-pattern-core-only) +* [Deleting issues](#deleting-issues) + +# Managing issues[](#managing-issues "Permalink") + +[GitLab 问题](index.html)是在[GitLab](index.html)中就想法和计划工作进行协作的基本介质. [创建](#create-a-new-issue) , [移动](#moving-issues) , [关闭](#closing-issues)和[删除](#deleting-issues)是可以解决问题的关键操作. + +## Create a new issue[](#create-a-new-issue "Permalink") + +创建新问题时,系统将提示您填写问题的[数据和字段,](issue_data_and_actions.html)如下所示. 如果知道要分配给问题的值,则可以使用" [快速操作"](../quick_actions.html)功能输入值,而不用从列表中选择它们. + +创建问题时,您可以使用**Epic**下拉列表将其与当前组中的现有史诗相关联. + +### Accessing the New Issue form[](#accessing-the-new-issue-form "Permalink") + +有多种方法可以从项目中获取"新问题"表单: + +* 导航到**项目的仪表板** > **问题** > **新问题** : + + [![New issue from the issue list view](img/ee0396a1cb32367d7ba7c6f4a7262c7f.png)](img/new_issue_from_tracker_list.png) + +* 从项目中未**解决的问题**中,单击**"**新问题"以在同一项目中创建一个新问题: + + [![New issue from an open issue](img/eb851fa4a367081c86d0a2eac3bdca65.png)](img/new_issue_from_open_issue.png) + +* 在**项目的仪表板中** ,单击加号( **+** )以打开带有一些选项的下拉菜单. 选择" **新问题"**以在该项目中创建一个问题: + + [![New issue from a project's dashboard](img/04b61606f38fddf21d194ee3e13abaa3.png)](img/new_issue_from_projects_dashboard.png) + +* 在**发行板中** ,通过单击列表顶部的加号( **+** )创建新发行. 它为该项目打开了一个新问题,并预先标记了各自的列表. + + [![From the issue board](img/7f1a1847005ab07ba8259a9e67005213.png)](img/new_issue_from_issue_board.png) + +### Elements of the New Issue form[](#elements-of-the-new-issue-form "Permalink") + +> 在[GitLab Premium](https://about.gitlab.com/pricing/) 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13847)了将新版本添加到史诗的功能. + +[![New issue from the issues list](img/94be136c7407855701b88eaded7db929.png)](img/new_issue_v13_1.png) + +创建新期刊时,可以填写以下字段: + +* Title +* Description +* 复选框以使问题保密 +* Assignee +* Weight +* Epic +* 截止日期 +* Milestone +* Labels + +### New issue from the group-level Issue Tracker[](#new-issue-from-the-group-level-issue-tracker "Permalink") + +转到"小组"仪表板,然后单击侧边栏中的" **问题** "以访问"小组"中所有项目的问题跟踪器. 使用页面右上方的下拉按钮,选择要添加问题的项目. + +[![Select project to create issue](img/31f0a42465a379e152ef6c0c7a6395e9.png)](img/select_project_from_group_level_issue_tracker.png) + +我们将跟踪您最近选择的项目,并将其用作下次访问的默认项目. 如果您主要是为同一项目创建问题,这应该可以节省大量时间和点击次数. + +[![Create issue from group-level issue tracker](img/75ca9285f50e058d4d85796b4d0b8e69.png)](img/create_issue_from_group_level_issue_tracker.png) + +### New issue via Service Desk[](#new-issue-via-service-desk-starter "Permalink") + +为您的项目启用[Service Desk](../service_desk.html)并提供电子邮件支持. 这样,当您的客户发送新电子邮件时,可以在适当的项目中创建一个新的问题,然后从那里进行后续操作. + +### New issue via email[](#new-issue-via-email "Permalink") + +如果您的 GitLab 实例配置了[传入电子邮件](../../../administration/incoming_email.html) ,则在项目的" **问题列表"**页面的底部会显示**一个"将新问题发送到该项目的电子邮件** "链接. + +[![Bottom of a project issues page](img/fd1e35952a7538923376d54325798b24.png)](img/new_issue_from_email.png) + +当您单击此链接时,将生成并显示一个电子邮件地址,该电子邮件地址**仅供您自己使用** ,以在此项目中创建问题. 您可以将此地址另存为联系人,以方便访问. + +**注意:**这是一个私人电子邮件地址,仅为您生成. **保密** ,因为任何知道它的人都可以创建问题或合并请求,就好像它们是您一样. 如果地址被盗用,或者您出于任何原因希望重新生成该地址,请再次单击"通过**电子邮件将新问题发送到此项目"** ,然后单击"重置"链接. + +向该地址发送电子邮件将以您的名字在此项目中创建一个新问题,其中: + +* The email subject becomes the issue title. +* 电子邮件正文成为问题描述. +* 支持[降价](../../markdown.html)和[快速行动](../quick_actions.html) . + +**注意:**在 GitLab 11.7 中,我们更新了生成的电子邮件地址的格式. 但是,仍支持较旧的格式,从而允许现有别名或联系人继续工作. + +### New issue via URL with prefilled fields[](#new-issue-via-url-with-prefilled-fields "Permalink") + +您可以使用 URL 中的查询字符串参数,使用预填充的字段值直接链接到给定项目的新问题页面. 这对于在外部 HTML 页面中嵌入 URL 以及在某些情况下(希望用户创建带有预填某些字段的问题)很有用. + +标题,描述,描述模板和机密字段可以使用此方法进行预填充. 您不能在同一 URL 中预先填写描述和描述模板字段(因为描述模板也会填充描述字段). + +| Field | URL 参数名称 | Notes | +| --- | --- | --- | +| title | `issue[title]` |   | +| description | `issue[description]` |   | +| 描述模板 | `issuable_template` |   | +| confidential | `issue[confidential]` | 参数值必须为`true`才能设置为机密 | + +请按照以下示例使用预填字段来形成新的问题 URL. + +* 对于 GitLab 社区版项目中的新问题,带有预填充的标题和预填充的描述,URL 为`https://gitlab.com/gitlab-org/gitlab-foss/-/issues/new?issue[title]=Validate new concept&issue[description]=Research idea` +* 对于 GitLab 社区版项目中的新问题,带有预填充的标题和预填充的描述模板,URL 为`https://gitlab.com/gitlab-org/gitlab-foss/-/issues/new?issue[title]=Validate new concept&issuable_template=Research proposal` +* 对于 GitLab 社区版项目中的新问题,其中包含预填充的标题,预填充的描述以及机密标志集,其 URL 为`https://gitlab.com/gitlab-org/gitlab-foss/-/issues/new?issue[title]=Validate new concept&issue[description]=Research idea&issue[confidential]=true` + +## Moving Issues[](#moving-issues "Permalink") + +移动问题会将其复制到新位置(项目),并在旧项目中将其关闭,但不会被删除. 这两个问题上还将添加一个系统注释,以指示它来自何处. + +The “Move issue” button is at the bottom of the right-sidebar when viewing the issue. + +[![move issue - button](img/1bc92f79d9645e6ae51aff10100e5c0d.png)](img/sidebar_move_issue.png) + +### Moving Issues in Bulk[](#moving-issues-in-bulk "Permalink") + +如果您具有高级技术技能,也可以在 Rails 控制台中将所有问题从一个项目批量转移到另一个项目. 下面的脚本会将所有问题从一个项目移至另一个状态尚未**关闭的项目** . + +要访问 rails 控制台,请在 GitLab 服务器上运行`sudo gitlab-rails console`并运行以下脚本. 请确保将**project** , **admin_user**和**target_project**更改为您的值. 我们也建议您在尝试对控制台进行任何更改之前先[创建备份](../../../raketasks/backup_restore.html#back-up-gitlab) . + +``` +project = Project.find_by_full_path('full path of the project where issues are moved from') +issues = project.issues +admin_user = User.find_by_username('username of admin user') # make sure user has permissions to move the issues +target_project = Project.find_by_full_path('full path of target project where issues moved to') + +issues.each do |issue| + if issue.state != "closed" && issue.moved_to.nil? + Issues::MoveService.new(project, admin_user).execute(issue, target_project) + else + puts "issue with id: #{issue.id} and title: #{issue.title} was not moved" + end +end; nil +``` + +## Closing issues[](#closing-issues "Permalink") + +当您确定问题已解决或不再需要时,可以使用"关闭"按钮关闭该问题: + +[![close issue - button](img/4635aba96009dfb3ab93ab6f4b92ee4c.png)](img/button_close_issue.png) + +您还可以通过将发行卡从其发行版列表中拖放到" **已关闭"**列表中来**关闭** [发行板中](../issue_board.html)的发行. + +[![close issue from the Issue Board](img/0f7aab3f307e6b54ebe4d00d94f1da0a.png)](img/close_issue_from_board.gif) + +### Closing issues automatically[](#closing-issues-automatically "Permalink") + +**注意:**由于性能原因,从现有存储库的第一次推送将禁用自动问题关闭. + +当提交或合并请求解决了一个或多个问题时,当提交或合并请求到达项目的默认分支时,可能会自动关闭这些问题. + +如果提交消息或合并请求描述包含与[定义的模式](#default-closing-pattern)匹配的文本,则匹配文本中引用的所有问题均将关闭. 将提交推送到项目的[**默认**分支时](../repository/branches/index.html#default-branch) ,或者将提交或合并请求合并到其中时,就会发生这种情况. + +例如,如果合并请求描述中包含`Closes #4, #6, Related to #5`则合并 MR 时问题`#4`和`#6`将自动关闭,但不会合并`#5` . 将" `Related to` `#5`标记[相关"](related_issues.html)用作[相关问题](related_issues.html) ,但不会自动关闭. + +[![merge request closing issue when merged](img/fee3cc5116f884089066af3908605cbe.png)](img/merge_request_closes_issue.png) + +如果问题与 MR 位于不同的存储库中,请添加问题的完整 URL: + +``` +Closes #4, #6, and https://gitlab.com/<username>/<projectname>/issues/<xxx> +``` + +#### Default closing pattern[](#default-closing-pattern "Permalink") + +如果未指定,将使用如下所示的默认问题关闭模式: + +``` +\b((?:[Cc]los(?:e[sd]?|ing)|\b[Ff]ix(?:e[sd]|ing)?|\b[Rr]esolv(?:e[sd]?|ing)|\b[Ii]mplement(?:s|ed|ing)?)(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?: *,? +and +| *,? *)?)|([A-Z][A-Z0-9_]+-\d+))+) +``` + +这将转换为以下关键字: + +* 关闭,关闭,关闭,关闭,关闭,关闭,关闭,关闭 +* 修正,修正,修正,修正,修正,修正,修正,修正 +* 解决,解决,解决,解决,解决,解决,解决,解决 +* 实施,实施,实施,实施,实施,实施,实施,实施 + +请注意, `%{issue_ref}`是在 GitLab 的源代码中定义的复杂正则表达式,可以匹配对以下内容的引用: + +* 本地问题( `#123` ). +* 跨项目问题( `group/project#123` ). +* 指向问题的链接( `https://gitlab.example.com/group/project/issues/123` ). + +例如以下提交消息: + +``` +Awesome commit message + +Fix #20, Fixes #21 and Closes group/otherproject#22. +This commit is also related to #17 and fixes #18, #19 +and https://gitlab.example.com/group/otherproject/issues/23. +``` + +将在提交被推送到的项目中关闭`#18` , `#19` , `#20`和`#21` ,以及`group/otherproject` `#22`和`#23` . `#17`将不会关闭,因为它与模式不匹配. 当从命令行与`git commit -m`一起使用时,它可以处理多行提交消息以及单行代码. + +#### Disabling automatic issue closing[](#disabling-automatic-issue-closing "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/19754) . + +可以在[项目的存储库设置中](../settings/index.html)针对每个项目禁用自动关闭问题功能. 引用的问题仍将按原样显示,但不会自动关闭. + +[![disable issue auto close - settings](img/a3802569c81d8f8dd179fd218322a4ca.png)](img/disable_issue_auto_close.png) + +这仅适用于受新合并请求或提交影响的问题. 已经解决的问题仍然保持原样. 禁用自动关闭的问题仅影响到项目*中*的合并请求,并不会阻止其他项目从通过跨项目的问题,将其关闭. + +#### Customizing the issue closing pattern[](#customizing-the-issue-closing-pattern-core-only "Permalink") + +为了更改默认的问题关闭模式,GitLab 管理员必须编辑安装的[`gitlab.rb`或`gitlab.yml`文件](../../../administration/issue_closing_pattern.html) . + +## Deleting issues[](#deleting-issues "Permalink") + +在 GitLab 8.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2982) + +具有[项目所有者权限的](../../permissions.html)用户可以通过编辑问题并单击删除按钮来删除问题. + +[![delete issue - button](img/51e7561422b1e74237ea14e916cffc78.png)](img/delete_issue.png) \ No newline at end of file diff --git a/docs/105.md b/docs/105.md new file mode 100644 index 0000000000000000000000000000000000000000..48ed5118637082fc721311d014f11745d4892d11 --- /dev/null +++ b/docs/105.md @@ -0,0 +1,176 @@ +# Milestones + +> 原文:[https://docs.gitlab.com/ee/user/project/milestones/](https://docs.gitlab.com/ee/user/project/milestones/) + +* [Overview](#overview) +* [Milestones as Agile sprints](#milestones-as-agile-sprints) +* [Milestones as releases](#milestones-as-releases) +* [Project milestones and group milestones](#project-milestones-and-group-milestones) +* [Creating milestones](#creating-milestones) + * [New project milestone](#new-project-milestone) + * [New group milestone](#new-group-milestone) +* [Editing milestones](#editing-milestones) + * [Promoting project milestones to group milestones](#promoting-project-milestones-to-group-milestones) +* [Assigning milestones from the sidebar](#assigning-milestones-from-the-sidebar) +* [Filtering issues and merge requests by milestone](#filtering-issues-and-merge-requests-by-milestone) + * [Filtering in list pages](#filtering-in-list-pages) + * [Filtering in issue boards](#filtering-in-issue-boards) + * [Special milestone filters](#special-milestone-filters) +* [Milestone view](#milestone-view) + * [Project Burndown Charts](#project-burndown-charts-starter) + * [Group Burndown Charts](#group-burndown-charts-premium) + * [Milestone sidebar](#milestone-sidebar) + +# Milestones[](#milestones "Permalink") + +## Overview[](#overview "Permalink") + +GitLab 中的里程碑是一种跟踪问题并合并为在一定时期内实现更广泛目标而创建的请求的方法. + +里程碑使您可以组织问题并将请求合并到一个紧密联系的组中,并带有一个可选的开始日期和一个可选的截止日期. + +## Milestones as Agile sprints[](#milestones-as-agile-sprints "Permalink") + +里程碑可用作敏捷冲刺,因此您可以跟踪所有问题并合并与特定冲刺有关的请求. 为此: + +1. 设置里程碑的开始日期和截止日期,以代表敏捷冲刺的开始和结束. +2. 将里程碑标题设置为敏捷 sprint 的名称,例如`November 2018 sprint` . +3. 通过将问题的右侧边栏关联到所需的里程碑,将问题添加到敏捷冲刺中. + +## Milestones as releases[](#milestones-as-releases "Permalink") + +同样,里程碑可以用作发布. 为此: + +1. 设置里程碑到期日期以表示发布的发布日期,并将里程碑开始日期保留为空白. +2. 将里程碑标题设置为您的发行版,例如`Version 9.4` . +3. 通过关联问题右侧的期望里程碑,将问题添加到您的发行中. + +此外,您可以将里程碑与 GitLab 的[Releases 功能](../releases/index.html#associate-milestones-with-a-release)集成. + +## Project milestones and group milestones[](#project-milestones-and-group-milestones "Permalink") + +您可以将**项目里程碑**分配给问题或仅合并该项目中的请求. 要查看项目里程碑列表,请在项目中转到 **问题>里程碑** . + +您可以将**组里程碑**分配给该**组**中任何项目的任何发行或合并请求. 要查看组里程碑列表,请在组中转到 **问题>里程碑** . + +您还可以在仪表板里程碑列表中查看您有权访问的所有里程碑. 要查看您可以访问的项目里程碑和组里程碑,请单击顶部导航栏上的**更多>里程碑** . + +有关项目和组里程碑 API 的信息,请参阅: + +* [Project Milestones API](../../../api/milestones.html) +* [Group Milestones API](../../../api/group_milestones.html) + +**注意:**如果您在一个小组中,然后单击**问题>里程碑** ,您将看到小组里程碑和该小组中的项目里程碑. 如果您在项目中,然后单击" **问题">"里程碑"** ,则只会看到该项目的里程碑. + +## Creating milestones[](#creating-milestones "Permalink") + +**注意:**创建里程碑需要[开发者或更高](../../permissions.html)级别的权限. + +### New project milestone[](#new-project-milestone "Permalink") + +创建**项目里程碑** : + +1. 在一个项目中,转到 **问题>里程碑** . +2. Click **新的里程碑**. +3. 输入标题,可选描述,可选开始日期和可选截止日期. +4. Click **新的里程碑**. + +[![New project milestone](img/9807a6b10b783af2ed7c8703958f017a.png)](img/milestones_new_project_milestone.png) + +### New group milestone[](#new-group-milestone "Permalink") + +创建**组里程碑** : + +1. 在一个小组中,转到 **问题>里程碑** . +2. Click **新的里程碑**. +3. 输入标题,可选描述,可选开始日期和可选截止日期. +4. Click **新的里程碑**. + +[![New group milestone](img/4d2f841f1dee2bdbbdcd14bd5518c000.png)](img/milestones_new_group_milestone.png) + +## Editing milestones[](#editing-milestones "Permalink") + +**注意:**编辑里程碑需要[开发者或更高的](../../permissions.html)权限级别. + +要编辑里程碑: + +1. 在项目或小组中,转到 **问题>里程碑** . +2. 单击里程碑标题. +3. Click **Edit**. + +您可以通过单击" **删除"**按钮来删除里程碑. + +### Promoting project milestones to group milestones[](#promoting-project-milestones-to-group-milestones "Permalink") + +If you are expanding from a few projects to a larger number of projects within the same group, you may want to share the same milestone among multiple projects in the same group. If you previously created a project milestone and now want to make it available for other projects within the same group, you can promote it to a group milestone. + +从项目里程碑列表页面,您可以将项目里程碑升级为组里程碑. 这会将具有相同名称的该组中所有项目中的所有项目里程碑合并为一个组里程碑. 以前已分配给这些项目里程碑之一的所有问题和合并请求现在都将分配给新的组里程碑. 此操作不能撤消,更改是永久的. + +**警告:**从 GitLab 12.4 和更早版本开始,将项目里程碑提升为组里程碑时,某些信息会丢失. 组里程碑视图上并非项目里程碑视图上的所有功能都可用. 如果将项目里程碑升级为组里程碑,则将失去这些功能. 请参阅" [里程碑"视图,](#milestone-view)以查看组里程碑视图中缺少哪些功能. + +[![Promote milestone](img/e14dc9ee9528f343daf09a4dd5340b99.png)](img/milestones_promote_milestone.png) + +## Assigning milestones from the sidebar[](#assigning-milestones-from-the-sidebar "Permalink") + +可以为每个问题和合并请求分配一个里程碑. 里程碑在边栏中的每个问题和合并请求页面上可见. 它们在发行板上也可见. 您可以从边栏中为对象分配或取消分配里程碑. 您也可以在评论中[快速](../quick_actions.html)执行此[操作](../quick_actions.html) . [如前所述](#project-milestones-and-group-milestones) ,对于给定的发布或合并请求,可以选择项目里程碑和组里程碑并将其分配给对象. + +## Filtering issues and merge requests by milestone[](#filtering-issues-and-merge-requests-by-milestone "Permalink") + +### Filtering in list pages[](#filtering-in-list-pages "Permalink") + +在项目发布/合并请求列表页面和组发布/合并请求列表页面中,可以按组里程碑和项目里程碑进行[筛选](../../search/index.html#issues-and-merge-requests) . + +### Filtering in issue boards[](#filtering-in-issue-boards "Permalink") + +* 在[项目发布板上](../issue_board.html) ,您可以在[搜索和过滤器栏中](../../search/index.html#issue-boards)按组里程碑和项目里程碑进行[筛选](../../search/index.html#issue-boards) . +* 在[组发布板上](../issue_board.html#group-issue-boards-premium) ,您只能在[搜索和过滤器栏中](../../search/index.html#issue-boards)按组里程碑进行[过滤](../../search/index.html#issue-boards) . +* 在[项目发行板中](../issue_board.html) ,可以在[发行板配置中](../issue_board.html#configurable-issue-boards-starter)按组里程碑和项目里程碑进行筛选. +* 在[组发行板上,](../issue_board.html#group-issue-boards-premium)您只能按[发行板配置](../issue_board.html#configurable-issue-boards-starter)中的组里程碑进行筛选. + +### Special milestone filters[](#special-milestone-filters "Permalink") + +在按里程碑进行筛选时,除了选择特定的项目里程碑或组里程碑之外,还可以选择特殊的里程碑筛选器. + +* **无** :显示问题或没有分配里程碑的合并请求. +* **任何** :显示问题或合并具有指定里程碑的请求. +* **即将到来的** :显示已分配的公开里程碑的问题或合并请求,该里程碑具有下一个即将到来的到期日(即将来的最近到期日). +* **已开始** :显示具有打开的指定里程碑且开始日期在今天之前的问题或合并请求. + +## Milestone view[](#milestone-view "Permalink") + +里程碑视图显示标题和描述. + +这些标签下面还包含显示以下内容的标签: + +* **问题** :显示分配给里程碑的所有问题. 这些内容显示在名为: + * 未开始的问题(未解决和未分配) + * 进行中的问题(未解决和已分配) + * 已完成的问题(已关闭) +* **合并请求** :显示分配给里程碑的所有合并请求. 这些将显示在名为: + * 进行中的工作(开放且未分配) + * 等待合并(打开和未分配) + * 拒绝(关闭) + * 合并后 +* **参与者** :显示分配给该里程碑的所有问题的受让人. +* **Labels**: Shows all labels that are used in issues assigned to the milestone. + +### Project Burndown Charts[](#project-burndown-charts-starter "Permalink") + +对于[GitLab Starter 中的](https://about.gitlab.com/pricing/)项目里程碑,里程碑视图中有一个[燃尽图](burndown_charts.html) ,显示完成里程碑的进度. + +[![burndown chart](img/eb36e4acf26c49641689d1a05dd8fa8a.png)](img/burndown_chart.png) + +### Group Burndown Charts[](#group-burndown-charts-premium "Permalink") + +对于[GitLab Premium 中的](https://about.gitlab.com/pricing/)组里程碑,里程碑视图中有一个[燃尽图](burndown_charts.html) ,显示完成里程碑的进度. + +### Milestone sidebar[](#milestone-sidebar "Permalink") + +里程碑视图上的里程碑侧栏显示以下内容: + +* 完成百分比,计算方式为已完成的问题数除以问题总数. +* 开始日期和截止日期. +* 在分配给里程碑的所有问题和合并请求上花费的总时间. +* 分配给里程碑的所有问题的总问题权重. + +[![Project milestone page](img/11f64bd49fd604a4644dd54ed7e423e8.png)](img/milestones_project_milestone_page.png) \ No newline at end of file diff --git a/docs/106.md b/docs/106.md new file mode 100644 index 0000000000000000000000000000000000000000..a10dd67a8f28e93895a7e334764f9316b6078c5b --- /dev/null +++ b/docs/106.md @@ -0,0 +1,35 @@ +# Multiple Assignees for Issues + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html](https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [How it works](#how-it-works) + +# Multiple Assignees for Issues[](#multiple-assignees-for-issues-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1904) in [GitLab Starter 9.2](https://about.gitlab.com/releases/2017/05/22/gitlab-9-2-released/#multiple-assignees-for-issues). + +## Overview[](#overview "Permalink") + +在拥有问题共享所有权的大型团队中,可能很难跟踪谁正在处理问题,谁已经完成了贡献,谁还没有开始. + +在[GitLab 企业版中](https://about.gitlab.com/pricing/) ,您还可以选择一个问题的多个受让人,使其更容易跟踪,并更清楚地由谁负责. + +[![multiple assignees for issues](img/d0707d7a1f822105efb120e442c32246.png)](img/multiple_assignees_for_issues.png) + +## Use cases[](#use-cases "Permalink") + +考虑一个由前端开发人员,后端开发人员,UX 设计人员,QA 测试人员和产品经理组成的团队,他们共同努力将创意推向市场. + +多个问题分配者可以使协作更加顺畅,并可以清晰显示共享的职责. 在团队的工作流程中将显示所有受让人,并接收通知(就像作为单个受让人一样),从而简化了沟通和所有权. + +受让人完成工作后,他们将离开自己,成为受让人,这清楚表明他们的角色已经完成. + +## How it works[](#how-it-works "Permalink") + +在未解决的问题中,展开右侧栏,找到受让人条目,然后单击" **编辑"** . 从下拉菜单中,选择要分配问题的用户数. + +[![adding multiple assignees](img/9149638f26311ced385bcc879401a8fd.png)](img/multiple_assignees.gif) + +通过从同一下拉菜单中取消选择受让人可以轻松将其删除. \ No newline at end of file diff --git a/docs/107.md b/docs/107.md new file mode 100644 index 0000000000000000000000000000000000000000..0cba33acb474e76f8419c0fa47c17ba1cde850c5 --- /dev/null +++ b/docs/107.md @@ -0,0 +1,49 @@ +# Related issues + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/related_issues.html](https://docs.gitlab.com/ee/user/project/issues/related_issues.html) + +* [Adding a related issue](#adding-a-related-issue) +* [Removing a related issue](#removing-a-related-issue) + +# Related issues[](#related-issues-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1797) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.4. + +相关问题是任何两个问题之间的双向关系,并出现在问题描述下方的方框中. 问题可能会跨越小组和项目. + +如果用户可以看到两个问题,则该关系仅显示在 UI 中. + +## Adding a related issue[](#adding-a-related-issue "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/2035) . +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 13.0 中进行了[改进](https://gitlab.com/gitlab-org/gitlab/-/issues/34239) . 当您尝试使用打开的阻止程序来解决问题时,您会看到一条警告,您可以将其关闭. + +You can relate one issue to another by clicking the related issues “+” button in the header of the related issue block. Then, input the issue reference number or paste in the full URL of the issue. + +此外,您可以选择当前问题是与输入的问题相关,被阻止还是被阻止. + +[![Adding a related issue](img/8d249dc6a1ff208c520bfc8cad423a4a.png)](img/related_issues_add_v12_8.png) + +同一项目的问题只能通过参考编号指定. 来自其他项目的问题需要其他信息,例如组和项目名称. 例如: + +* 同一项目: `#44` +* 同一组: `project#44` +* 不同的组: `group/project#44` + +有效参考将添加到您可以查看的临时列表中. 添加完所有相关问题后,请单击**添加**以提交. + +完成所有相关问题的添加后,您将能够看到它们的分类,以便可以从视觉上更好地理解它们之间的关系. + +[![Related issue block](img/e3439aafb873fb6b7cdb3a5c6d51c3b9.png)](img/related_issue_block_v12_8.png) + +## Removing a related issue[](#removing-a-related-issue "Permalink") + +在相关问题区域中,单击要删除的每个问题令牌右侧的" x"图标. 由于双向关系,它将不再出现在任何一个问题中. + +[![Removing a related issue](img/9e8d2b5134e62de656bff96c60c04e10.png)](img/related_issues_remove_v12_8.png) + +请访问我们的[权限](../../permissions.html)页面以获取更多信息. + +此外,您还可以通过[我们的 API](../../../api/issue_links.html)管理相关问题. \ No newline at end of file diff --git a/docs/108.md b/docs/108.md new file mode 100644 index 0000000000000000000000000000000000000000..1b6a304839222b8c58b5e8ef7170685d63848d84 --- /dev/null +++ b/docs/108.md @@ -0,0 +1,207 @@ +# Service Desk + +> 原文:[https://docs.gitlab.com/ee/user/project/service_desk.html](https://docs.gitlab.com/ee/user/project/service_desk.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [How it works](#how-it-works) +* [Configuring Service Desk](#configuring-service-desk) + * [Using customized email templates](#using-customized-email-templates) + * [Thank you email](#thank-you-email) + * [New note email](#new-note-email) + * [Using custom email display name](#using-custom-email-display-name) + * [Using custom email address](#using-custom-email-address) + * [Enable custom email address](#enable-custom-email-address) +* [Using Service Desk](#using-service-desk) + * [As an end user (issue creator)](#as-an-end-user-issue-creator) + * [As a responder to the issue](#as-a-responder-to-the-issue) + * [Support Bot user](#support-bot-user) + +# Service Desk[](#service-desk "Permalink") + +Version history + +* [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/149) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.1. +* 在 13.0 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/214839) [GitLab Starter](https://about.gitlab.com/pricing/) . +* 在 13.2 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/215364) [GitLab Core](https://about.gitlab.com/pricing/) . + +## Overview[](#overview "Permalink") + +Service Desk 是一个模块,可让您的团队直接在 GitLab 内部通过电子邮件与任何外部方联系. 无需外部工具. 在构建软件的过程中进行的持续对话可确保用户反馈直接在需要的地方结束,从而帮助您构建正确的功能来解决用户的实际问题. + +借助 Service Desk,您可以为客户提供有效的电子邮件支持,他们现在可以通过电子邮件向您发送错误报告,功能请求或常规反馈,这些问题将作为新问题最终出现在您的 GitLab 项目中. 反过来,您的团队可以直接从项目中做出回应. + +由于 Service Desk 直接内置在 GitLab 中,因此消除了多种工具和外部集成的复杂性和低效率,从而大大缩短了从反馈到软件更新的周期时间. + +有关概述,请查看[GitLab 服务](https://about.gitlab.com/blog/2017/05/09/demo-service-desk/)台上的视频演示. + +## Use cases[](#use-cases "Permalink") + +例如,假设您为 iOS 或 Android 开发游戏. 该代码库托管在您的 GitLab 实例中,并通过 GitLab CI / CD 构建和部署. + +这是 Service Desk 为您工作的方式: + +1. 您向付费客户提供特定于项目的电子邮件地址,他们可以直接从应用程序内向您发送电子邮件. +2. 他们发送的每封电子邮件都会在相应的项目中产生一个问题. +3. 您的团队成员导航到 Service Desk 问题跟踪器,在这里他们可以查看新的支持请求并在内部相关问题中做出响应. +4. 您的团队与客户进行来回沟通以了解请求. +5. 您的团队开始着手实施代码以解决客户的问题. +6. 当您的团队完成实施后,合并请求将合并,问题将自动关闭. +7. 该客户将通过电子邮件成功出席,而无需真正访问您的 GitLab 实例. +8. 您的团队无需离开 GitLab(或设置任何集成)即可跟进客户,从而节省了时间. + +## How it works[](#how-it-works "Permalink") + +GitLab 服务台是一种简单的方法,使人们无需自己的用户帐户即可在您的 GitLab 实例中创建问题. + +它为最终用户提供了一个在项目中创建问题的唯一电子邮件地址,并且可以通过 GitLab 界面或通过电子邮件发送答复. 最终用户将仅通过电子邮件看到该主题. + +## Configuring Service Desk[](#configuring-service-desk "Permalink") + +**注意:**在 GitLab.com 上启用了 Service Desk. 您可以跳过下面的步骤 1; 您只需要为每个项目启用它. + +如果您具有项目维护者访问权限,则可以选择设置服务台. 请按照以下步骤操作: + +1. 为 GitLab 实例[设置传入电子邮件](../../administration/incoming_email.html#set-it-up) . + * 我们建议使用[电子邮件子地址](../../administration/incoming_email.html#email-sub-addressing) ,但在 GitLab 11.7 及更高版本中,您也可以使用[全部接收邮箱](../../administration/incoming_email.html#catch-all-mailbox) . +2. 导航到项目的**"设置">"常规",**然后找到" **服务台"**部分. +3. 启用**激活服务台**切换. 这显示了一个唯一的电子邮件地址,可将问题发送给项目. 这些问题将是[机密的](issues/confidential_issues.html) ,因此它们仅对项目成员可见. 请注意,在 GitLab 11.7 中,我们更新了生成的电子邮件地址的格式. 仍然支持较旧的格式,但是允许现有的别名或联系人继续工作. + + **危险:**任何人都可以使用此电子邮件地址在此项目上创建问题,无论他们是否有权访问您的 GitLab 实例. 我们建议**将其放在别名后面,**以便可以根据需要进行更改,并在您的 GitLab 实例上**[启用 Akismet](../../integration/akismet.html)**来向该服务添加垃圾邮件检查. 畅通无阻的电子邮件垃圾邮件将导致创建许多垃圾邮件问题. + + 如果存储库中有[模板](description_templates.html) ,则可以选择从选择器菜单中选择一个[模板](description_templates.html) ,以将其附加到所有 Service Desk 问题上. + + [![Service Desk enabled](img/d32d8400522e9b5c9dd295fba00e1255.png)](img/service_desk_enabled.png) + +现在已为此项目启用 Service Desk! 您应该能够从项目导航的" **问题"**菜单中访问它. + +[![Service Desk Navigation Item](img/c42e6852cdd2c45b0a814f7a659ee5d2.png)](img/service_desk_nav_item.png) + +### Using customized email templates[](#using-customized-email-templates "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2460) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7. + +当用户使用 Service Desk 提交新问题时,或在 Service Desk 问题上创建新便笺时,将向作者发送电子邮件. + +这些电子邮件的正文可以使用模板进行自定义. 要创建新的自定义模板,请在存储库的`.gitlab/service_desk_templates/`目录内创建一个新的 Markdown( `.md` )文件. 提交并推送到您的默认分支. + +#### Thank you email[](#thank-you-email "Permalink") + +**谢谢电子邮件**是用户提交问题后发送给用户的电子邮件. 模板的文件名必须为`thank_you.md` . 您可以使用`%{ISSUE_ID}`占位符,它将由电子邮件中的问题 IID 替换;而`%{ISSUE_PATH}`占位符,将由项目路径和问题 IID 替换. 由于服务台问题被创建为机密(只有项目成员才能看到),因此回复电子邮件中没有提供问题链接. + +#### New note email[](#new-note-email "Permalink") + +**新笔记电子邮件**是当用户提交的问题有新评论时发送给用户的电子邮件. 模板的文件名必须为`new_note.md` . 您可以使用`%{ISSUE_ID}`占位符(将在电子邮件中替换为问题 IID), `%{ISSUE_PATH}`占位符(将替换为项目路径)以及问题 IID 和`%{NOTE_TEXT}`占位符(将替换为注释文本) . + +### Using custom email display name[](#using-custom-email-display-name "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7529) . + +您可以自定义电子邮件显示名称. 从服务台发送的电子邮件在" `From`标题中将具有此名称. 默认显示名称是`GitLab Support Bot` . + +### Using custom email address[](#using-custom-email-address "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2201) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0. + +**注意:**默认情况下禁用此功能. 有关启用它的步骤,请参阅[启用自定义电子邮件地址](#enable-custom-email-address) . + +如果在配置中启用了`service_desk_email`功能标记,则可以通过将电子邮件发送到自定义 Service Desk 电子邮件地址来创建 Service Desk 问题,该电子邮件地址应采用以下格式: `project_contact+%{key}@example.com` . + +`%{key}`部分用于查找应在其中创建问题的项目. `%{key}`部分组合了项目的路径和可配置的项目名称后缀: `<project_full_path>-<project_name_suffix>` . + +您可以在项目的服务台设置中设置项目名称后缀. 它只能包含小写字母( `az` ),数字( `0-9` )或下划线( `_` ). + +[![Setting custom Service Desk email address](img/210e34a4dbdbe21aba5083c6f7dac9cb.png)](img/service_desk_custom_email_address_v13_0.png) + +您可以将以下代码片段添加到您的配置中. + +从源安装的示例: + +``` +service_desk_email: + enabled: true + address: "project_contact+%{key}@example.com" + user: "project_support@example.com" + password: "[REDACTED]" + host: "imap.gmail.com" + port: 993 + ssl: true + start_tls: false + log_path: "log/mailroom.log" + mailbox: "inbox" + idle_timeout: 60 + expunge_deleted: true +``` + +Omnibus GitLab 安装示例: + +``` +gitlab_rails['service_desk_email_enabled'] = true + +gitlab_rails['service_desk_email_address'] = "project_contact+%{key}@gmail.com" + +gitlab_rails['service_desk_email_email'] = "project_support@gmail.com" + +gitlab_rails['service_desk_email_password'] = "[REDACTED]" + +gitlab_rails['service_desk_email_mailbox_name'] = "inbox" + +gitlab_rails['service_desk_email_idle_timeout'] = 60 + +gitlab_rails['service_desk_email_log_file'] = "/var/log/gitlab/mailroom/mail_room_json.log" + +gitlab_rails['service_desk_email_host'] = "imap.gmail.com" + +gitlab_rails['service_desk_email_port'] = 993 + +gitlab_rails['service_desk_email_ssl'] = true + +gitlab_rails['service_desk_email_start_tls'] = false +``` + +在这种情况下,假设`mygroup/myproject`项目 Service Desk 设置的项目名称后缀设置为`support` ,并且用户将电子邮件发送到`project_contact+mygroup-myproject-support@example.com` . 结果,将在`mygroup/myproject`项目中从此电子邮件中创建一个新的 Service Desk 问题. + +#### Enable custom email address[](#enable-custom-email-address "Permalink") + +默认情况下,此功能附带`service_desk_custom_address`功能标志. 要打开此功能,请要求具有 Rails 控制台访问权限的 GitLab 管理员运行以下命令: + +``` +Feature.enable(:service_desk_custom_address) +``` + +配置选项与配置[传入电子邮件](../../administration/incoming_email.html#set-it-up)相同. + +## Using Service Desk[](#using-service-desk "Permalink") + +### As an end user (issue creator)[](#as-an-end-user-issue-creator "Permalink") + +要创建服务台问题,最终用户无需了解有关 GitLab 实例的任何信息. 他们只是将电子邮件发送到给定的地址,然后收到一封确认回执的电子邮件: + +[![Service Desk enabled](img/3b8b0bcac599d7207d90ed8194bed83e.png)](img/service_desk_confirmation_email.png) + +这也使最终用户可以选择退订. + +如果他们不选择退订,那么添加到该问题的任何新评论都将作为电子邮件发送: + +[![Service Desk reply email](img/85055487485aff8bd5dc0cf97f711d52.png)](img/service_desk_reply.png) + +他们发送的所有回复都将显示在问题本身中. + +### As a responder to the issue[](#as-a-responder-to-the-issue "Permalink") + +For responders to the issue, everything works as usual. They will see a familiar looking issue tracker, where they can see issues created via customer support requests and filter and interact with them just like other GitLab issues. + +[![Service Desk Issue tracker](img/daa9468beb587bb748cbb9ec37bbb43f.png)](img/service_desk_issue_tracker.png) + +来自最终用户的消息将显示为来自特殊的支持机器人用户,但是除此之外,您可以像平常一样阅读和编写评论: + +[![Service Desk issue thread](img/1b69e9fcb692fa835e9b7e06fa856aee.png)](img/service_desk_thread.png) + +注意: + +* 项目的可见性(私有,内部,公共)不会影响 Service Desk. +* 项目的路径,包括其组或名称空间,将显示在电子邮件中. + +### Support Bot user[](#support-bot-user "Permalink") + +在后台,服务台由支持机器人的特殊用户创建问题. 该用户不计入许可证限制数. \ No newline at end of file diff --git a/docs/109.md b/docs/109.md new file mode 100644 index 0000000000000000000000000000000000000000..40ab81a99689f651f1be335babb75caf0f5a1689 --- /dev/null +++ b/docs/109.md @@ -0,0 +1,23 @@ +# Sorting and ordering issue lists + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/sorting_issue_lists.html](https://docs.gitlab.com/ee/user/project/issues/sorting_issue_lists.html) + +* [Manual sorting](#manual-sorting) + +# Sorting and ordering issue lists[](#sorting-and-ordering-issue-lists "Permalink") + +您可以通过多种方式对问题列表进行排序,包括按问题创建日期,里程碑到期日期等进行排序.可用的排序选项可以根据列表的上下文进行更改. 有关按发布优先级排序的信息,请参见[标签优先级](../labels.html#label-priority) . + +在组和项目问题清单中,也可以手动订购问题,类似于[问题委员会](../issue_board.html#issue-ordering-in-a-list) . + +## Manual sorting[](#manual-sorting "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62178) . + +选择" **手动**排序"时,可以通过拖放问题来更改顺序. 更改后的订单将保留. 除了某些例外,访问同一列表的每个人都将看到重新排序的列表. + +每个问题都分配有一个相对顺序值,代表其相对于列表中其他问题的相对顺序. 当您拖放问题的重新排序时,其相对顺序值也会相应更改. + +此外,任何问题出现在手动排序的列表中时,更新的相对订单值将用于订购. 这意味着,如果您的 GitLab 实例内给定列表中的任何用户将问题`A`拖放到问题`B`上方,则随后将这两个问题随后加载到同一实例的任何列表中(可能是不同的)例如项目专案清单或其他群组专案清单),即可维持订购顺序. + +此顺序还会影响[发行板](../issue_board.html#issue-ordering-in-a-list) . 更改问题列表中的顺序会更改问题面板中的顺序,反之亦然. \ No newline at end of file diff --git a/docs/110.md b/docs/110.md new file mode 100644 index 0000000000000000000000000000000000000000..e9eff2c7893784091b9e63d0ed1105f5318cd709 --- /dev/null +++ b/docs/110.md @@ -0,0 +1,17 @@ +# Issue weight + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/issue_weight.html](https://docs.gitlab.com/ee/user/project/issues/issue_weight.html) + +# Issue weight[](#issue-weight-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.3. + +当您遇到很多问题时,可能很难获得概述. 通过为每个问题增加权重,您可以更好地了解给定问题要花费或花费多少时间,价值或复杂性. + +您可以通过简单地更改下拉菜单中的值来设置问题的权重. 您可以将其设置为 0、1、2 等的非负整数值. (数据库存储一个 4 字节的值,因此上限基本上是无限的). 您也可以减轻问题的负担. + +该值将显示在单个问题的右侧栏上,以及在独特的余额比例图标旁边的问题页面中. + +另外,您可以在里程碑页面上查看所有问题的总和. + +[![issue page](img/ff2558c68f4e646052a0c39a7d3f8710.png)](img/issue_weight.png) \ No newline at end of file diff --git a/docs/111.md b/docs/111.md new file mode 100644 index 0000000000000000000000000000000000000000..423ea1162ca56cd2d5ad622d6daab340b7c0369f --- /dev/null +++ b/docs/111.md @@ -0,0 +1,38 @@ +# Associate a Zoom meeting with an issue + +> 原文:[https://docs.gitlab.com/ee/user/project/issues/associate_zoom_meeting.html](https://docs.gitlab.com/ee/user/project/issues/associate_zoom_meeting.html) + +* [Adding a zoom meeting to an issue](#adding-a-zoom-meeting-to-an-issue) +* [Removing an existing Zoom meeting from an issue](#removing-an-existing-zoom-meeting-from-an-issue) + +# Associate a Zoom meeting with an issue[](#associate-a-zoom-meeting-with-an-issue "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16609) . + +为了同步进行事件管理通信,GitLab 允许将 Zoom 会议与问题相关联. 一旦开始进行消防战斗的变焦呼叫,就需要一种将电话会议与问题相关联的方法,以便您的团队成员可以快速加入而无需请求链接. + +## Adding a zoom meeting to an issue[](#adding-a-zoom-meeting-to-an-issue "Permalink") + +要将缩放会议与问题相关联,可以使用 GitLab 的[快速操作](../quick_actions.html#quick-actions-for-issues-merge-requests-and-epics) . + +在一个问题中,使用`/zoom`快速操作和有效的 Zoom 链接发表评论: + +``` +/zoom https://zoom.us/j/123456789 +``` + +如果"缩放会议 URL"有效且您至少具有" [报告者"权限](../../permissions.html) ,则系统警报将通知您会议 URL 添加成功. 该问题的描述将被自动编辑以包含"缩放"链接,并且在该问题的标题下方将出现一个按钮. + +[![Link Zoom Call in Issue](img/2b66844a710706131349b467b399b449.png)](img/zoom-quickaction-button.png) + +您只能将单个 Zoom 会议附加到一个问题. 如果您尝试使用`/zoom`快速操作添加第二个 Zoom 会议,它将无法正常工作,您需要先将其[删除](#removing-an-existing-zoom-meeting-from-an-issue) . + +## Removing an existing Zoom meeting from an issue[](#removing-an-existing-zoom-meeting-from-an-issue "Permalink") + +与添加缩放会议类似,您可以通过快速操作将其删除: + +``` +/remove_zoom +``` + +如果您至少具有[Reporter 权限](../../permissions.html) ,系统警报将通知您会议 URL 已成功删除. \ No newline at end of file diff --git a/docs/112.md b/docs/112.md new file mode 100644 index 0000000000000000000000000000000000000000..51e66d42e4fc1a9ddd75c96c4d449d5b47ffdd94 --- /dev/null +++ b/docs/112.md @@ -0,0 +1,91 @@ +# Merge requests + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/](https://docs.gitlab.com/ee/user/project/merge_requests/) + +* [Use cases](#use-cases) +* [Overview](#overview) +* [Merge request navigation tabs at the top](#merge-request-navigation-tabs-at-the-top) +* [Creating merge requests](#creating-merge-requests) +* [Reviewing and managing merge requests](#reviewing-and-managing-merge-requests) +* [Testing and reports in merge requests](#testing-and-reports-in-merge-requests) +* [Authorization for merge requests](#authorization-for-merge-requests) + +# Merge requests[](#merge-requests "Permalink") + +合并请求使您可以可视化并协作对作为对指定 Git 分支的提交而存在的源代码的建议更改. + +[![Merge request view](img/44dfa1e85103f88c82598a4ef9f8d0ae.png)](img/merge_request.png) + +合并请求( **MR** )是 GitLab 作为代码协作和版本控制平台的基础. 顾名思义,它就是一个*将*一个分支*合并*到另一个分支的*请求* . + +## Use cases[](#use-cases "Permalink") + +答:考虑您是一个团队中的软件开发人员: + +1. 您签出新分支,并通过合并请求提交更改 +2. 您从团队中收集反馈 +3. 您可以使用["代码质量"报告来进行](code_quality.html)优化代码的实现 +4. 您可以在 GitLab CI / CD 中使用[JUnit 测试报告](../../../ci/junit_test_reports.html)来验证您的更改 +5. 通过" [许可证合规性"报告,](../../compliance/license_compliance/index.html)可以避免使用许可证与您的项目不兼容的依赖项 +6. 您要求您的经理[批准](merge_request_approvals.html) +7. 您的经理: + 1. 推动提交并进行最终审查 + 2. [批准合并请求](merge_request_approvals.html) + 3. 将其设置为[在管道成功时合并](merge_when_pipeline_succeeds.html) +8. 您的更改将通过[手动操作](../../../ci/yaml/README.html#whenmanual) GitLab CI / CD 部署到生产中 +9. 您的实施已成功交付给客户 + +B.考虑您是为您公司网站编写网页的 Web 开发人员: + +1. 您签出新分支,并通过合并请求提交新页面 +2. 您从审稿人那里收集反馈 +3. 您的更改将通过[Review Apps](../../../ci/review_apps/index.html)进行预览 +4. 您要求您的网页设计师实施 +5. 您要求您的经理[批准](merge_request_approvals.html) +6. 一旦批准,您的合并请求将被[压缩和合并](squash_and_merge.html) ,并[部署到带有 GitLab 页面的暂存中](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/) +7. 您的生产团队[选择](cherry_pick_changes.html)合并提交到生产中 + +## Overview[](#overview "Permalink") + +合并请求(也称为" MR")显示有关建议的更改的大量信息. MR 的主体包含其描述以及其小部件(显示有关 CI / CD 管道的信息,如果存在的话),然后是与该 MR 合作的人员的讨论线程. + +MR 还包含导航选项卡,从中可以查看线程上正在进行的讨论,提交列表,管道和作业列表,代码更改以及内联代码审阅. + +首先,请阅读[合并请求简介](getting_started.html) . + +## Merge request navigation tabs at the top[](#merge-request-navigation-tabs-at-the-top "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33813) . 此定位是实验性的. + +到目前为止,在合并请求窗口小部件之后,位于合并请求中以显示" **讨论区"** ," **提交"** ," **管道** "和" **更改"**的导航选项卡. + +To facilitate this navigation without having to scroll up and down through the page to find these tabs, based on user feedback, we’re experimenting with a new positioning of these tabs. They are now located at the top of the merge request, with a new **Overview** tab, containing the description of the merge request followed by the widget. Next to **Overview**, you can find **Pipelines**, **Commits**, and **Changes**. + +[![Merge request tab positions](img/9e7b70cdf92b88509713225035e8e964.png)](img/merge_request_tab_position_v12_6.png) + +请注意,此更改当前位于默认情况下启用的功能标志之后. 对于自我管理的实例,GitLab 管理员可以通过 Rails 控制台使用以下命令将其禁用: + +``` +Feature.disable(:mr_tabs_position) +``` + +## Creating merge requests[](#creating-merge-requests "Permalink") + +Learn [how to create a merge request](creating_merge_requests.html). + +## Reviewing and managing merge requests[](#reviewing-and-managing-merge-requests "Permalink") + +查看可使用的功能来[查看和管理合并请求](reviewing_and_managing_merge_requests.html) . + +## Testing and reports in merge requests[](#testing-and-reports-in-merge-requests "Permalink") + +了解有关合并请求中的[测试](testing_and_reports_in_merge_requests.html)选项[和报告](testing_and_reports_in_merge_requests.html)更改的信息. + +## Authorization for merge requests[](#authorization-for-merge-requests "Permalink") + +使用 GitLab 进行合并请求的主要方法有两种: + +1. 在单个存储库中使用[受保护的分支](../protected_branches.html) +2. 使用权威项目的分支 + +[Learn more about the authorization for merge requests.](authorization_for_merge_requests.html) \ No newline at end of file diff --git a/docs/113.md b/docs/113.md new file mode 100644 index 0000000000000000000000000000000000000000..7b1fff144ab4ea316b87b28e7f1a46047c9a4b3e --- /dev/null +++ b/docs/113.md @@ -0,0 +1,61 @@ +# Allow collaboration on merge requests across forks + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/allow_collaboration.html](https://docs.gitlab.com/ee/user/project/merge_requests/allow_collaboration.html) + +* [Enabling commit edits from upstream members](#enabling-commit-edits-from-upstream-members) +* [Pushing to the fork as the upstream member](#pushing-to-the-fork-as-the-upstream-member) + +# Allow collaboration on merge requests across forks[](#allow-collaboration-on-merge-requests-across-forks "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17395) . + +当用户从派生打开合并请求时,将为他们提供允许上游成员在源分支上与其进行协作的选项. 这使上游项目的成员可以在合并之前进行小规模修复或重新分支,从而减少了接受外部贡献的来回过程. + +此功能可用于可公开访问的分支项目之间的合并请求. + +为合并请求启用后,对项目目标分支具有合并访问权限的成员将被授予对合并请求的源分支的写权限. + +## Enabling commit edits from upstream members[](#enabling-commit-edits-from-upstream-members "Permalink") + +只有具有对源项目的推送访问权限的用户才能启用该功能,并且只有在合并请求打开时才能持续使用. 启用后,上游成员也将能够重试合并请求的管道和作业: + +1. 在创建或编辑合并请求时启用贡献. + + [![Enable contribution](img/3794ce06aeeb9528fa1a66915cc69072.png)](img/allow_collaboration.png) + +2. 创建合并请求后,您将看到允许可以合并到目标分支的成员的提交. + + [![Check that contribution is enabled](img/381cb6fd4ceed7b2a8b3642926cb8cf2.png)](img/allow_collaboration_after_save.png) + +## Pushing to the fork as the upstream member[](#pushing-to-the-fork-as-the-upstream-member "Permalink") + +如果合并请求的创建者启用了上游成员的贡献,则可以直接推送到派生存储库的分支. + +假如说: + +* 分叉的项目 URL 为`git@gitlab.com:thedude/awesome-project.git` . +* 合并请求的分支是`update-docs` . + +流程如下所示: + +1. 首先,您需要获取合并请求已引入的更改. 单击" **签出"分支**按钮,其中包含可以运行的一些预填充命令. + + [![Check out branch button](img/e9dbc908a405f57008dbb80d1b8a9a70.png)](img/checkout_button.png) + +2. 使用复制按钮复制第一个命令并将其粘贴到您的终端中: + + ``` + git fetch git@gitlab.com:thedude/awesome-project.git update-docs + git checkout -b thedude-awesome-project-update-docs FETCH_HEAD + ``` + + 这将获取派生项目的分支,然后基于所获取的分支创建本地分支. + +3. Make any changes you want and commit. +4. 推送到分叉的项目: + + ``` + git push git@gitlab.com:thedude/awesome-project.git thedude-awesome-project-update-docs:update-docs + ``` + + 注意冒号( `:`两个分支之间). 上面的命令会将本地分支`thedude-awesome-project-update-docs` `git@gitlab.com:thedude/awesome-project.git`存储库的`update-docs`分支. \ No newline at end of file diff --git a/docs/114.md b/docs/114.md new file mode 100644 index 0000000000000000000000000000000000000000..ac13a596d8ffc0c835e810a721bb5801d3e72219 --- /dev/null +++ b/docs/114.md @@ -0,0 +1,246 @@ +# Merge Request Approvals + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) + +* [Optional Approvals](#optional-approvals-core-only) +* [Required Approvals](#required-approvals-starter) + * [Approval Rules](#approval-rules) + * [Eligible Approvers](#eligible-approvers) + * [Implicit Approvers](#implicit-approvers) + * [Code Owners as eligible approvers](#code-owners-as-eligible-approvers) + * [Adding / editing a default approval rule](#adding--editing-a-default-approval-rule) + * [Editing / overriding approval rules per merge request](#editing--overriding-approval-rules-per-merge-request) + * [Multiple approval rules](#multiple-approval-rules-premium) + * [Scoped to Protected Branch](#scoped-to-protected-branch-premium) + * [Adding or removing an approval](#adding-or-removing-an-approval) + * [Merge request approvals project settings](#merge-request-approvals-project-settings) + * [Prevent overriding default approvals](#prevent-overriding-default-approvals) + * [Resetting approvals on push](#resetting-approvals-on-push) + * [Allowing merge request authors to approve their own merge requests](#allowing-merge-request-authors-to-approve-their-own-merge-requests) + * [Prevent approval of merge requests by their committers](#prevent-approval-of-merge-requests-by-their-committers) + * [Require authentication when approving a merge request](#require-authentication-when-approving-a-merge-request) + * [Security approvals in merge requests](#security-approvals-in-merge-requests-ultimate) + * [Enabling the new approvals interface](#enabling-the-new-approvals-interface) + +# Merge Request Approvals[](#merge-request-approvals "Permalink") + +代码审查是每个成功项目的基本实践,一旦合并请求状态良好,就需要您的批准,这是审查过程的重要组成部分,因为它清楚地传达了合并变更的能力. + +## Optional Approvals[](#optional-approvals-core-only "Permalink") + +在[GitLab Core 13.2 中](https://gitlab.com/gitlab-org/gitlab/-/issues/27426)引入. + +具有开发者[权限](../../permissions.html)或更高[权限的](../../permissions.html)任何用户都可以在 GitLab Core 中批准合并请求. 这为审阅者提供了一种一致的机制来提供批准,并使维护者更容易知道何时可以合并更改. Core 中的批准是可选的,并且在没有批准的情况下不会阻止合并请求的合并. + +## Required Approvals[](#required-approvals-starter "Permalink") + +在[GitLab 企业版 7.12 中](https://about.gitlab.com/releases/2015/06/22/gitlab-7-12-released/#merge-request-approvers-ee-only)引入. + +必需的批准通过要求指定的人在可以合并的合并请求之前批准,可以强制执行代码审查. + +所需的批准可启用多个用例: + +* 强制审查所有合并到存储库中的代码. +* 通过[批准规则](#approval-rules)指定给定提议的代码更改的审核者,以及最少数量的审核者. +* 为所有建议的代码更改指定审阅者的类别,例如后端,前端,质量保证,数据库等. +* 由合并请求中更改的文件确定,自动将[代码所有者](#code-owners-as-eligible-approvers)指定[为合格的批准者](#code-owners-as-eligible-approvers) . +* 在合并可能引入漏洞的代码之前, [需要获得安全团队的批准](#security-approvals-in-merge-requests-ultimate) . + +### Approval Rules[](#approval-rules "Permalink") + +批准规则定义了合并请求在可以合并之前必须获得多少个批准,以及可选地应该由哪些用户进行批准. 可以定义批准: + +* [As project defaults](#adding--editing-a-default-approval-rule). +* [Per merge request](#editing--overriding-approval-rules-per-merge-request). + +如果未定义批准规则,则任何用户都可以批准合并请求,尽管仍可以在[项目设置中为合并请求批准设置](#merge-request-approvals-project-settings)所需批准者的默认最小数量. + +批准规则定义了合并请求在可以合并之前必须获得多少个批准,以及可选地应该由哪些用户进行批准. 可以定义批准: + +* [As project defaults](#adding--editing-a-default-approval-rule). +* [Per merge request](#editing--overriding-approval-rules-per-merge-request). + +如果未定义批准规则,则任何用户都可以批准合并请求,尽管仍可以在[项目设置中为合并请求批准设置](#merge-request-approvals-project-settings)所需批准者的默认最小数量. + +#### Eligible Approvers[](#eligible-approvers "Permalink") + +以下用户可以批准合并请求: + +* 在项目中被添加为批准者的用户,或将请求级别与开发者或更高[权限](../../permissions.html)合并的[用户](../../permissions.html) . +* 由合并请求更改的具有开发人员或更高[权限](../../permissions.html)的文件的[代码所有者](#code-owners-as-eligible-approvers) . + +如果单个用户是以下成员的成员,则可以将其添加为项目的批准者: + +* 该项目. +* 该项目的直接上级组. +* 可以通过[共享](../members/share_project_with_groups.html)访问项目的组. + +也可以将一组用户添加为批准者. 将来,小组批准者可能只[限于对项目具有共享访问权限的小组](https://gitlab.com/gitlab-org/gitlab/-/issues/2048) . + +如果将用户添加为个人批准者,并且也是组批准者的一部分,则该用户仅被计数一次. 如果在项目设置上启用了" [**阻止作者批准"**](#allowing-merge-request-authors-to-approve-their-own-merge-requests) (默认情况下启用)和" [**阻止提交者批准"**](#prevent-approval-of-merge-requests-by-their-committers) (默认情况下禁用),则合并请求作者以及已提交合并请求的用户均不算作合格批准者. + +##### Implicit Approvers[](#implicit-approvers "Permalink") + +如果所需批准的数量大于分配的批准者的数量,则来自其他用户的批准将计入满足要求. 这些将是在项目中具有开发人员[权限](../../permissions.html)或更高[权限的](../../permissions.html)用户,但未在批准规则中明确列出. + +##### Code Owners as eligible approvers[](#code-owners-as-eligible-approvers "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7933) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.5. + +如果将[代码所有者](../code_owners.html)添加到存储库中,则相应文件的所有者将与具有 Developer 或更高[权限的](../../permissions.html)成员一起成为合格的批准者. + +要启用此合并请求批准规则: + +1. 导航到项目的**"设置">"常规",**然后展开" **合并请求批准"** . +2. 找到**任何合格的用户,**然后选择所需的批准数量. + +[![MR approvals by Code Owners](img/6a2d24148988c584ff47ac7c526b48ff.png)](img/mr_approvals_by_code_owners_v12_7.png) + +设置后,合并请求只能在您设置的批准数量批准后才能合并. manbetx 客户端打不开将毫无区别地接受来自具有开发者或更高权限的用户以及代码所有者的批准. + +或者,您可以**要求** [保护所有者的代码所有者批准](../protected_branches.html#protected-branches-approval-by-code-owners-premium) . + +#### Adding / editing a default approval rule[](#adding--editing-a-default-approval-rule "Permalink") + +要添加或编辑默认的合并请求批准规则: + +1. 导航到您项目的 **设置>常规,**然后展开**合并请求批准** . + +2. 单击**添加批准规则** ,或单击**编辑** . + * 添加或更改**规则名称** . + * 设置**所需的批准号**所需的批准数量. 最小值是`0` . + * (可选)搜索有[资格批准](#eligible-approvers)合并请求的用户或组,然后单击" **添加"**按钮将其添加为批准者. 在搜索字段中键入之前,将根据合并请求更改的文件的先前作者来建议批准者. + * (可选)点击 组或用户旁边的" **删除"**按钮可将其从规则中删除. +3. Click **添加批准规则** or **更新批准规则**. + +在更改规则之前创建的任何合并请求都不会更改. 他们将保留原始批准规则,除非手动[覆盖](#editing--overriding-approval-rules-per-merge-request) . + +**注意:**如果合并请求的目标是其他项目,例如从分支到上游项目,则默认批准规则将从目标(上游)项目而不是源(叉子)获取. + +##### Editing / overriding approval rules per merge request[](#editing--overriding-approval-rules-per-merge-request "Permalink") + +在 GitLab 企业版 9.4 中引入. + +默认情况下,MR 作者或具有足够[权限](../../permissions.html)的用户可以编辑每个合并请求(MR)中列出的合并请求批准规则. 可以在[合并请求批准设置中](#prevent-overriding-default-approvals)禁用此功能. + +一种可能的情况是添加比默认设置中定义更多的批准者. + +创建或编辑合并请求时,请找到" **批准规则"**部分,然后按照与[添加/编辑默认批准规则](#adding--editing-a-default-approval-rule)相同的步骤进行操作. + +#### Multiple approval rules[](#multiple-approval-rules-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1979) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.10. + +在 GitLab Premium 中,每个合并请求可以有多个批准规则,每个项目可以有多个默认批准规则. + +添加或编辑多个默认规则与[添加或编辑单个默认批准规则相同](#adding--editing-a-default-approval-rule) ,不同之处在于,即使已经定义了规则," **添加批准规则"**按钮仍可用于添加更多规则. + +同样,每个合并请求中编辑或覆盖多个批准规则与每个合并请求中[编辑或覆盖批准规则](#editing--overriding-approval-rules-per-merge-request)相同,只是即使已定义一个规则," **添加批准规则"**按钮仍可用于添加更多规则. + +当[合格的批准人](#eligible-approvers)批准合并请求时,它将减少批准人所属的所有规则的剩余批准数. + +[![Approvals premium merge request widget](img/b1b6eda7a121cb284375e6c83317263d.png)](img/approvals_premium_mr_widget_v12_7.png) + +#### Scoped to Protected Branch[](#scoped-to-protected-branch-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.8. + +批准规则通常仅与特定分支(例如`master` . 在配置[**默认批准规则时,**](#adding--editing-a-default-approval-rule)可以通过导航到项目的**"设置"** ,展开" **合并请求批准"** ,然后从" **目标"分支**下拉列表中选择" **任何"分支** ,将这些作用域一下子作用于所有受保护的分支. + +或者,您可以从" **目标"分支**下拉列表中选择一个非常特定的受保护分支: + +[![Scoped to Protected Branch](img/439a9c21f68de25b8a16d0d0a28d19be.png)](img/scoped_to_protected_branch_v12_8.png) + +要启用此配置,请参阅[代码所有者对受保护分支的批准](../protected_branches.html#protected-branches-approval-by-code-owners-premium) . + +### Adding or removing an approval[](#adding-or-removing-an-approval "Permalink") + +当[合格的批准者](#eligible-approvers)访问一个开放合并请求时,可能是以下之一: + +* 如果所需的批准数目*尚未*满足,他们可以通过点击批准它显示的**批准**按钮. + + [![Approve](img/45cc34490ebcb0a656d7c57d3dcbbb00.png)](img/approve.png) + +* 如果已经满足所需的批准数量,则他们仍然可以通过单击显示的**"额外批准"**按钮来**批准** . + + [![Add approval](img/a3b1935e9fe6f6222ef3200715c2f595.png)](img/approve_additionally.png) + +* **他们已经批准了此合并请求** :他们可以删除他们的批准. + + [![Remove approval](img/aabf40f234d995e031a5a1a0f66b5905.png)](img/remove_approval.png) + +**注意:**如果在项目设置中启用了" [**阻止作者批准",**](#allowing-merge-request-authors-to-approve-their-own-merge-requests)则不允许合并请求作者批准自己的合并请求. + +满足批准规则后,如果没有其他阻止请求,则可以合并合并请求. 请注意,合并请求仍可能被其他条件阻止,例如合并冲突, [挂起的讨论](../../discussions/index.html#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved)或[失败的 CI / CD 管道](merge_when_pipeline_succeeds.html) . + +### Merge request approvals project settings[](#merge-request-approvals-project-settings "Permalink") + +可以通过以下步骤找到合并请求批准的项目设置: **设置>常规**和扩展**合并请求批准** . + +#### Prevent overriding default approvals[](#prevent-overriding-default-approvals "Permalink") + +默认情况下,用户可以在合并请求中编辑批准规则. 如果禁用,则所有新合并请求的[批准规则](#adding--editing-a-default-approval-rule)将由[默认批准规则](#adding--editing-a-default-approval-rule)确定. 要禁用此功能: + +1. 取消选中**可以覆盖每个合并请求所需的批准人和批准**复选框. +2. Click **保存更改**. + +#### Resetting approvals on push[](#resetting-approvals-on-push "Permalink") + +当新的提交被推送到合并请求的源分支时,您可以强制删除对合并请求的所有批准. 如果禁用,则即使合并请求中添加了更改,批准也将持续. 要启用此功能: + +1. Check the **将新提交推送到其源分支时,删除合并请求中的所有批准** checkbox. +2. Click **保存更改**. + +**注意:**重新定义来自 UI [的合并请求](fast_forward_merge.html)时,批准不会重置. 但是,如果更改了目标分支,则批准将被重置. + +#### Allowing merge request authors to approve their own merge requests[](#allowing-merge-request-authors-to-approve-their-own-merge-requests "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3349) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.3. + +您可以允许合并请求作者自行批准合并请求. 作者也必须包含在批准者列表中,以便能够批准其合并请求. 要启用此功能: + +1. 取消选中" **阻止合并请求作者批准合并请求"**复选框,默认情况下启用此复选框. +2. Click **保存更改**. + +#### Prevent approval of merge requests by their committers[](#prevent-approval-of-merge-requests-by-their-committers "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10441) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.10. + +您可以阻止已提交合并请求的用户批准它. 要启用此功能: + +1. 选中**阻止提交者批准合并请求**复选框. +2. Click **保存更改**. + +#### Require authentication when approving a merge request[](#require-authentication-when-approving-a-merge-request "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5981) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.0. + +**注意:**要在批准合并请求时要求身份验证,必须在[登录限制](../../admin_area/settings/sign_in_restrictions.html#password-authentication-enabled)下**启用为 Web 界面**启用的**密码身份验证** . 在管理区域中. + +您可以强制批准者输入密码以进行身份​​验证,然后再添加批准. 这使电子签名能够获得批准,例如[CFR Part 11](https://www.accessdata.fda.gov/scripts/cdrh/cfdocs/cfcfr/CFRSearch.cfm?CFRPart=11&showFR=1&subpartNode=21:1.0.1.1.8.3)所定义的签名. 要启用此功能: + +1. 选中**需要用户密码批准**复选框. +2. Click **保存更改**. + +### Security approvals in merge requests[](#security-approvals-in-merge-requests-ultimate "Permalink") + +可以将合并请求批准配置为在合并请求引入漏洞时需要安全团队成员的批准. + +有关更多信息,请参见[合并请求中的安全性批准](../../application_security/index.html#security-approvals-in-merge-requests) . + +### Enabling the new approvals interface[](#enabling-the-new-approvals-interface "Permalink") + +从[GitLab v12.0 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/10685) ,默认情况下会提供更新的批准界面. 在 12.0 之前的版本中,除非启用了`approval_rules`功能标志,否则更新的界面不可用,这可由实例管理员从 Rails 控制台中完成. + +使用以下命令来启动 Rails 控制台: + +``` +# Omnibus GitLab +gitlab-rails console + +# Installation from source +cd /home/git/gitlab +sudo -u git -H bin/rails console -e production +``` + +然后运行`Feature.enable(:approval_rules)`以启用更新的界面. \ No newline at end of file diff --git a/docs/115.md b/docs/115.md new file mode 100644 index 0000000000000000000000000000000000000000..f77f4cd3fc99e1506cc2e394e97f03dc2a4eb22b --- /dev/null +++ b/docs/115.md @@ -0,0 +1,203 @@ +# Browser Performance Testing + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html](https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [How browser performance testing works](#how-browser-performance-testing-works) +* [Configuring Browser Performance Testing](#configuring-browser-performance-testing) + * [Configuring degradation threshold](#configuring-degradation-threshold) + * [Performance testing on Review Apps](#performance-testing-on-review-apps) + * [GitLab versions 12.3 and older](#gitlab-versions-123-and-older) + +# Browser Performance Testing[](#browser-performance-testing-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3507) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.3. + +如果您的应用程序提供 Web 界面,并且您正在使用[GitLab CI / CD](../../../ci/README.html) ,则可以快速确定浏览器中待处理代码更改对渲染性能的影响. + +## Overview[](#overview "Permalink") + +GitLab 使用[Sitespeed.io](https://www.sitespeed.io) (一种免费的开源工具)来测量网站的渲染性能. GitLab 构建的[Sitespeed 插件](https://gitlab.com/gitlab-org/gl-performance)在名为`browser-performance.json`的文件中输出所分析的每个页面的性能得分,该数据可以显示在合并请求中. + +## Use cases[](#use-cases "Permalink") + +考虑以下工作流程: + +1. 营销团队的成员正在尝试通过添加新工具来跟踪参与度. +2. 通过浏览器性能指标,他们可以看到他们的更改如何影响最终用户页面的可用性. +3. 指标显示,更改后,页面的性能得分有所下降. +4. 查看详细报告时,他们看到`<head>`包含了新的 JavaScript 库,这会影响加载页面的速度. +5. 他们向前端开发人员寻求帮助,他们将库设置为异步加载. +6. 前端开发人员批准合并请求,并授权将其部署到生产中. + +## How browser performance testing works[](#how-browser-performance-testing-works "Permalink") + +首先,在`.gitlab-ci.yml`文件中定义一个生成[浏览器性能报告工件的作业](../../../ci/pipelines/job_artifacts.html#artifactsreportsperformance-premium) . 然后,GitLab 会检查此报告,比较源分支和目标分支之间每一页的关键性能指标,并在合并请求中显示信息. + +有关性能作业的示例,请参阅" [配置浏览器性能测试"](#configuring-browser-performance-testing) . + +**注意:**如果"浏览器性能"报告没有可比较的数据,例如,当您第一次在`.gitlab-ci.yml`添加"浏览器性能"作业时,"浏览器性能"报告小部件将不会显示. 它必须在目标分支(例如`master` )上至少运行一次,然后才能在针对该分支的合并请求中显示. + +[![Browser Performance Widget](img/c7a5bc700a43a5880572c7f8cc0acdc7.png)](img/browser_performance_testing.png) + +## Configuring Browser Performance Testing[](#configuring-browser-performance-testing "Permalink") + +这个例子显示如何运行[sitespeed.io 容器](https://hub.docker.com/r/sitespeedio/sitespeed.io/)使用 GitLab CI / CD 上的代码和[sitespeed.io](https://www.sitespeed.io)使用泊坞窗功能于泊坞窗. + +1. 首先,使用[Docker-in-Docker 构建](../../../ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor)设置 GitLab Runner. +2. 在`.gitlab-ci.yml`文件中,按如下所示配置默认的浏览器性能测试 CI 作业: + + ``` + include: + template: Verify/Browser-Performance.gitlab-ci.yml + + performance: + variables: + URL: https://example.com + ``` + +**注意:**对于 12.4 之前的版本,请参阅[旧版 GitLab](#gitlab-versions-123-and-older)的信息. 如果您正在使用 Kubernetes 集群,请使用[`template: Jobs/Browser-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml) . + +上面的示例在 CI / CD 管道中创建了一个`performance`作业,并针对您在`URL`定义的网页运行 sitespeed.io 以收集关键指标. + +该示例使用的 CI / CD 模板自 12.4 起已包含在所有 GitLab 安装中,但不适用于 Kubernetes 集群. 如果您使用的是 GitLab 12.3 或更早版本,则必须[手动添加配置](#gitlab-versions-123-and-older) + +该模板将[GitLab 插件用于 sitespeed.io](https://gitlab.com/gitlab-org/gl-performance) ,并将完整的 HTML sitespeed.io 报告保存为" [浏览器性能"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsperformance-premium) ,您可以稍后下载和分析该[工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsperformance-premium) . 此实现始终采用最新的浏览器性能工件. 如果启用了[GitLab Pages,](../pages/index.html)则可以直接在浏览器中查看报告. + +您还可以使用环境变量自定义作业: + +* `SITESPEED_IMAGE` :配置要用于作业的 Docker 映像(默认为`sitespeedio/sitespeed.io` ),而不是映像版本. +* `SITESPEED_VERSION` :配置要用于作业的 Docker 映像的版本(默认`13.3.0` ). +* `SITESPEED_OPTIONS` :根据需要配置任何其他 sitespeed.io 选项(默认为`nil` ). 有关更多详细信息,请参阅[sitespeed.io 文档](https://www.sitespeed.io/documentation/sitespeed.io/configuration/) . + +For example, you can override the number of runs sitespeed.io makes on the given URL, and change the version: + +``` +include: + template: Verify/Browser-Performance.gitlab-ci.yml + +performance: + variables: + URL: https://www.sitespeed.io/ + SITESPEED_VERSION: 13.2.0 + SITESPEED_OPTIONS: -n 5 +``` + +### Configuring degradation threshold[](#configuring-degradation-threshold "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27599) . + +您可以配置降级警报的敏感度,以避免针对度量指标的小幅下降获得警报. 这是通过设置`DEGRADATION_THRESHOLD`变量来完成的. 在以下示例中,仅当" `Total Score`指标下降 5 分或更多时,才会显示警报: + +``` +include: + template: Verify/Browser-Performance.gitlab-ci.yml + +performance: + variables: + URL: https://example.com + DEGRADATION_THRESHOLD: 5 +``` + +`Total Score`指标基于 sitespeed.io 的[教练表现得分](https://www.sitespeed.io/documentation/sitespeed.io/metrics/#performance-score) . 在[教练文档中](https://www.sitespeed.io/documentation/coach/how-to/#what-do-the-coach-do)有更多信息. + +### Performance testing on Review Apps[](#performance-testing-on-review-apps "Permalink") + +上面的 CI YAML 配置非常适合在静态环境下进行测试,并且可以扩展为动态环境,但是还需要一些额外的步骤: + +1. `performance`作业应在动态环境启动后运行. +2. 在`review`工作中: + 1. 生成带有动态 URL 的 URL 列表文件. + 2. 将文件另存为工件,例如,在作业`script`使用`echo $CI_ENVIRONMENT_URL > environment_url.txt` . + 3. 将列表作为 URL 环境变量(可以是 URL 或包含 URL 的文件)传递给`performance`作业. +3. 现在,您可以针对所需的主机名和路径运行 sitespeed.io 容器. + +您的`.gitlab-ci.yml`文件如下所示: + +``` +stages: + - deploy + - performance + +include: + template: Verify/Browser-Performance.gitlab-ci.yml + +review: + stage: deploy + environment: + name: review/$CI_COMMIT_REF_SLUG + url: http://$CI_COMMIT_REF_SLUG.$APPS_DOMAIN + script: + - run_deploy_script + - echo $CI_ENVIRONMENT_URL > environment_url.txt + artifacts: + paths: + - environment_url.txt + only: + - branches + except: + - master + +performance: + dependencies: + - review + variables: + URL: environment_url.txt +``` + +### GitLab versions 12.3 and older[](#gitlab-versions-123-and-older "Permalink") + +自推出以来,浏览器性能测试经历了几处更改. 在本节中,我们将详细介绍这些更改以及如何基于 GitLab 版本运行测试: + +* 在 GitLab 12.4 中提供[了一个工作模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml) . +* 在 13.2 中,使用其他模板变量将该功能从`Performance`重命名为`Browser Performance` . 出于兼容性原因,模板中的作业名称仍然是`performance` ,但可以在以后的迭代中重命名以匹配. +* 对于 11.5 至 12.3,没有可用的模板,必须按以下方式手动定义作业: + +``` +performance: + stage: performance + image: docker:git + variables: + URL: https://example.com + SITESPEED_VERSION: 13.3.0 + SITESPEED_OPTIONS: '' + services: + - docker:stable-dind + script: + - mkdir gitlab-exporter + - wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/master/index.js + - mkdir sitespeed-results + - docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --outputFolder sitespeed-results $URL $SITESPEED_OPTIONS + - mv sitespeed-results/data/performance.json performance.json + artifacts: + paths: + - performance.json + - sitespeed-results/ + reports: + performance: performance.json +``` + +* 对于 11.4 和更早版本,应按以下方式定义作业: + +``` +performance: + stage: performance + image: docker:git + variables: + URL: https://example.com + services: + - docker:stable-dind + script: + - mkdir gitlab-exporter + - wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/master/index.js + - mkdir sitespeed-results + - docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results $URL + - mv sitespeed-results/data/performance.json performance.json + artifacts: + paths: + - performance.json + - sitespeed-results/ +``` + +建议升级到最新版本并使用模板,以确保您收到最新更新,包括对 sitespeed.io 版本的更新. \ No newline at end of file diff --git a/docs/116.md b/docs/116.md new file mode 100644 index 0000000000000000000000000000000000000000..0a97cf1bf023d132266847ae70baecc276a17b9f --- /dev/null +++ b/docs/116.md @@ -0,0 +1,160 @@ +# How to create a merge request + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) + +* [New Merge Request page](#new-merge-request-page) +* [Create Merge Request button](#create-merge-request-button) +* [New merge request by adding, editing, and uploading a file](#new-merge-request-by-adding-editing-and-uploading-a-file) +* [New merge request from a new branch created through the UI](#new-merge-request-from-a-new-branch-created-through-the-ui) +* [New merge request from your local environment](#new-merge-request-from-your-local-environment) +* [New merge request from an issue](#new-merge-request-from-an-issue) +* [New merge request from the Merge Requests page](#new-merge-request-from-the-merge-requests-page) +* [New merge request from a fork](#new-merge-request-from-a-fork) +* [New merge request by email](#new-merge-request-by-email-core-only) + * [Adding patches when creating a merge request via e-mail](#adding-patches-when-creating-a-merge-request-via-e-mail) +* [Reviewing and managing Merge Requests](#reviewing-and-managing-merge-requests) + +# How to create a merge request[](#how-to-create-a-merge-request "Permalink") + +在创建合并请求之前,请通读"合并请求"的[简介,](getting_started.html)以熟悉概念,术语并了解如何使用它们. + +每个合并请求都从创建一个分支开始. 您可以通过[命令行](#new-merge-request-from-your-local-environment) ,Git CLI 应用程序或[GitLab UI](#new-merge-request-from-a-new-branch-created-through-the-ui)在本地进行操作. + +本文档介绍了创建合并请求的几种方法. + +启动新的合并请求时,无论使用哪种方法,都将转到" [**新合并请求"**页面,](#new-merge-request-page)以在其中添加有关合并请求的信息. + +如果将新分支推送到 GitLab,也不管使用哪种方法,都可以单击[**Create Merge Request**](#create-merge-request-button)按钮并从此处启动合并请求. + +## New Merge Request page[](#new-merge-request-page "Permalink") + +在" **新合并请求"**页面上,首先填写**合并请求**的标题和描述. 如果分支上已经有提交,则标题将用第一条提交消息的第一行预填充,描述将用提交消息中的任何其他行预填充. 在所有情况下,标题都是唯一的必填字段. + +在此处,您可以在其中填充信息(标题,描述,受让人,里程碑,标签,批准人),然后点击**创建合并请求** . + +在初始屏幕上,您还可以查看提交合并请求之前推送到分支的所有提交,管道和文件更改. + +[![New Merge Request page](img/9255a795b62eb0bbe1c91eab2f85c149.png)](img/new_merge_request_page_v12_6.png) + +**提示:**您可以在创建合并请求之前将一次或多次推送到 GitLab 中的分支. + +## Create Merge Request button[](#create-merge-request-button "Permalink") + +将新分支推送到 GitLab 后,请访问 GitLab 中的存储库,并在屏幕顶​​部看到一个号召性用语,您可以从中单击**创建合并请求**按钮. + +[![Create Merge Request button](img/2257f7989872604ba6ce6506ba811b15.png)](img/create_merge_request_button_v12_6.png) + +您还可以在以下页面的右上方看到" **创建合并请求"**按钮: + +* **Project** page. +* **资料库>文件** page. +* **合并请求** page. + +In this case, GitLab will use the most recent branch you pushed changes to as the source branch, and the default branch in the current project as the target. + +## New merge request by adding, editing, and uploading a file[](#new-merge-request-by-adding-editing-and-uploading-a-file "Permalink") + +当您选择通过 GitLab UI 编辑,添加或上传文件时,在文件末尾,您会看到以下选项:添加**Commit 消息** ,选择该**提交**的**Target 分支** ,然后选中**Start new**复选框. **具有这些更改的合并请求** . + +同样,如果通过 Web IDE 更改文件,则在左侧边栏中导航到" **提交"**时,将看到这些相同的选项. + +添加,编辑或上传文件后,请执行以下操作: + +1. 在提交消息中描述您的更改. +2. 选择一个现有分支以将您的提交添加到其中,或者,如果您想创建一个新分支,请键入新的分支名称(不带空格,大写字母或特殊字符). +3. 保持选中复选框以立即开始新的合并请求,或者取消选中该复选框以在开始合并请求之前向该分支添加更多更改. +4. Click **提交变更**. + +如果您选择开始合并请求,则将转到" [**新合并请求"**页面](#new-merge-request-page) ,您可以在其中填写信息并提交合并请求. + +合并请求将针对存储库的默认分支. 如果要更改它,可以稍后通过编辑合并请求来进行更改. + +## New merge request from a new branch created through the UI[](#new-merge-request-from-a-new-branch-created-through-the-ui "Permalink") + +要通过 GitLab UI 快速开始处理文件,请导航至项目的" **存储库">"分支"** ,然后单击" **新建分支"** . 将创建一个新分支,您可以开始编辑文件. + +提交并推送后,您可以单击" [**创建合并请求"**](#create-merge-request-button)按钮以打开" [**新合并请求"**页面](#new-merge-request-page) . 将使用当前分支作为源,并使用当前项目中的默认分支作为目标来启动新的合并请求. + +## New merge request from your local environment[](#new-merge-request-from-your-local-environment "Permalink") + +假设您已将存储库克隆到计算机中,并且想要开始处理文件更改,请先创建并签出一个新分支: + +``` +git checkout -b my-new-branch +``` + +处理文件更改,暂存并提交它们: + +``` +git add . +git commit -m "My commit message" +``` + +完成后, [将分支推送到 GitLab](../../../gitlab-basics/start-using-git.html#send-changes-to-gitlabcom) : + +``` +git push origin my-new-branch +``` + +在输出中,GitLab 将提示您一个直接链接来创建合并请求: + +``` +... +remote: To create a merge request for docs-new-merge-request, visit: +remote: https://gitlab-instance.com/my-group/my-project/merge_requests/new?merge_request%5Bsource_branch%5D=my-new-branch +``` + +复制该链接并将其粘贴到浏览器中,将显示" [**新合并请求"页面**](#new-merge-request-page) . + +在[通过命令行推送时](../push_options.html) , [还可以向命令添加](../push_options.html)一些[标志,](../push_options.html)以减少通过 UI 手动编辑合并请求的需要. + +如果您没有通过命令行将分支推送到 GitLab(例如,您使用 Git CLI 应用程序来推送更改),则可以通过单击" [**创建合并请求"**](#create-merge-request-button)按钮通过 GitLab UI [**创建合并请求**](#create-merge-request-button) . + +## New merge request from an issue[](#new-merge-request-from-an-issue "Permalink") + +您也可以[直接从 issue 创建一个新的合并请求](../repository/web_editor.html#create-a-new-branch-from-an-issue) . + +## New merge request from the Merge Requests page[](#new-merge-request-from-the-merge-requests-page "Permalink") + +您可以通过在项目中的" **合并请求"**页面上单击" **新建合并请求"**按钮来开始创建新的合并请求. 然后选择包含更改的源项目和分支,以及要将更改合并到的目标项目和分支. 单击**比较分支,然后继续**转到" [**新合并请求"**页面](#new-merge-request-page)并填写详细信息. + +## New merge request from a fork[](#new-merge-request-from-a-fork "Permalink") + +分叉项目并应用本地更改后,请完成以下步骤,从您的 fork 创建一个合并请求以贡献回主项目: + +1. 转到**项目>您的项目,**然后选择存储库的分支. +2. 在左侧菜单中,转到**合并请求** ,然后点击**新建合并请求** . +3. 在" **源分支"**下拉列表框中,在分支的存储库中选择您的分支作为源分支. +4. 在" **目标分支"**下拉列表框中,从上游存储库中选择分支作为目标分支. +5. 输入凭据后,单击" **比较分支",然后继续**将本地更改与上游存储库进行比较. +6. 分配用户以查看您的更改,然后点击**提交合并请求** . + +合并更改后,您的更改将按照规范添加到上游存储库和分支中. 合并工作后,如果您不想对上游项目做出任何其他贡献,则可以通过[删除分支关系](../settings/index.html#removing-a-fork-relationship) ,在**Settings> Advanced Settings**部分[中将 fork 与](../settings/index.html#removing-a-fork-relationship)上游项目断开链接. + +有关更多详细信息, [请参阅分叉工作流文档](../repository/forking_workflow.html) . + +## New merge request by email[](#new-merge-request-by-email-core-only "Permalink") + +*要使用此功能,需要由 GitLab 管理员配置[传入电子邮件](../../../administration/incoming_email.html)才能使用.* 它在 GitLab.com 中不可用. + +您可以通过将电子邮件发送到特定于用户的电子邮件地址来创建新的合并请求. 通过单击**将新的合并请求**通过**电子邮件发送到该项目**按钮,可以在合并请求页面上获取地址. 该主题将用作新合并请求的源分支名称,而目标分支将是项目的默认分支. 消息正文(如果不为空)将用作合并请求描述. 您需要启用["通过电子邮件回复"](../../../administration/reply_by_email.html)才能使用此功能. 如果您的实例未启用它,则可以要求您的 GitLab 管理员这样做. + +这是一个私人电子邮件地址,仅为您生成. **将其保存在自己**手中,因为拥有它的任何人都可以像您一样创建问题或合并请求. 您可以将此地址添加到您的联系人列表中以便于访问. + +[![Create new merge requests by email](img/4f0a47acf91c1135738d76e1c06eec3a.png)](img/create_from_email.png) + +*在 GitLab 11.7 中,我们更新了生成的电子邮件地址的格式. 但是,仍支持较旧的格式,从而允许现有别名或联系人继续工作.* + +### Adding patches when creating a merge request via e-mail[](#adding-patches-when-creating-a-merge-request-via-e-mail "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22723) . + +您可以通过将补丁添加为电子邮件的附件,将提交添加到正在创建的合并请求中. 文件名以`.patch`结尾的所有附件都将被视为补丁程序,并将按名称顺序对其进行处理. + +补丁的总大小可以是 2MB. + +如果主题的源分支不存在,那么将从存储库的 HEAD 或指定的目标分支创建源分支以应用补丁. 可以使用[`/target_branch`快速操作](../quick_actions.html)指定目标分支. 如果源分支已经存在,则将在其顶部应用补丁. + +## Reviewing and managing Merge Requests[](#reviewing-and-managing-merge-requests "Permalink") + +提交合并请求后,可以通过 GitLab 进行[审查和管理](reviewing_and_managing_merge_requests.html) . \ No newline at end of file diff --git a/docs/117.md b/docs/117.md new file mode 100644 index 0000000000000000000000000000000000000000..685f2f2319df803cbbeae8d1165d335a2925c3aa --- /dev/null +++ b/docs/117.md @@ -0,0 +1,50 @@ +# Cherry-pick changes + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/cherry_pick_changes.html](https://docs.gitlab.com/ee/user/project/merge_requests/cherry_pick_changes.html) + +* [Cherry-picking a merge request](#cherry-picking-a-merge-request) + * [Cherry-pick tracking](#cherry-pick-tracking) +* [Cherry-picking a commit](#cherry-picking-a-commit) + +# Cherry-pick changes[](#cherry-pick-changes "Permalink") + +GitLab 实现了 Git 的强大功能,通过在合并请求和提交详细信息中引入**Cherry-pick**按钮来[挑选任何提交](https://git-scm.com/docs/git-cherry-pick "Git Cherry-Pick 文档") . + +## Cherry-picking a merge request[](#cherry-picking-a-merge-request "Permalink") + +合并请求合并后,将可以使用**Cherry-pick**按钮来选择该合并请求引入的更改. + +[![Cherry-pick Merge Request](img/fe7d77556848be98a93c7b6516b0e6f8.png)](img/cherry_pick_changes_mr.png) + +单击该按钮后,将出现一个模态,显示一个[分支过滤器搜索框](../repository/branches/index.html#branch-filter-search-box) ,您可以在其中选择: + +* 将更改直接选择到所选分支中. +* 使用经过精心挑选的更改创建一个新的合并请求. + +### Cherry-pick tracking[](#cherry-pick-tracking "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2675) . + +当您选择一个合并提交时,GitLab 将向相关的合并请求线程输出系统注释,使新提交与现有合并请求交联. + +[![Cherry-pick tracking in Merge Request timeline](img/e20aec7ab33bbd61bae4825e6c9e35f1.png)](img/cherry_pick_mr_timeline_v12_9.png) + +每个部署的[关联合并请求列表](../../../api/deployments.html#list-of-merge-requests-associated-with-a-deployment)将包括精心挑选的合并提交. + +**注意:**我们仅跟踪从 GitLab(UI 和 API)执行的 cherry-pick. 计划在将来的发行版中支持[通过命令行跟踪精心挑选的提交](https://gitlab.com/gitlab-org/gitlab/-/issues/202215) . + +## Cherry-picking a commit[](#cherry-picking-a-commit "Permalink") + +您可以从提交详细信息页面中挑选一个提交: + +[![Cherry-pick commit](img/b4e821b8b83e29e837f01f4620e557b7.png)](img/cherry_pick_changes_commit.png) + +与选择合并请求类似,您可以选择将更改直接选择到目标分支中,也可以选择创建新的合并请求以选择更改. + +请注意,在进行樱桃挑选合并提交时,主线将始终是第一父级. 如果要使用其他主线,则需要从命令行执行. + +这是一个使用第二个父级作为主线来挑选合并提交的快速示例: + +``` +git cherry-pick -m 2 7a39eb0 +``` \ No newline at end of file diff --git a/docs/118.md b/docs/118.md new file mode 100644 index 0000000000000000000000000000000000000000..70625d490900a60e01c117d82b0140c67e67ddf9 --- /dev/null +++ b/docs/118.md @@ -0,0 +1,275 @@ +# Code Quality + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html) + +* [Use cases](#use-cases) +* [Example configuration](#example-configuration) + * [Previous job definitions](#previous-job-definitions) +* [Configuring jobs using variables](#configuring-jobs-using-variables) +* [Implementing a custom tool](#implementing-a-custom-tool) +* [Code Quality reports](#code-quality-reports) +* [Extending functionality](#extending-functionality) + * [Using Analysis Plugins](#using-analysis-plugins) +* [Troubleshooting](#troubleshooting) + * [Changing the default configuration has no effect](#changing-the-default-configuration-has-no-effect) + * [No Code Quality report is displayed in a Merge Request](#no-code-quality-report-is-displayed-in-a-merge-request) + * [Only a single Code Quality report is displayed, but more are defined](#only-a-single-code-quality-report-is-displayed-but-more-are-defined) + +# Code Quality[](#code-quality-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1984) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.3. + +确保项目的代码保持简单,易读和易于贡献可能会引起问题. 借助[GitLab CI / CD](../../../ci/README.html) ,您可以使用 GitLab 代码质量分析源代码质量. + +代码质量: + +* 使用[Code Climate Engines](https://codeclimate.com) ,它们是免费的开放源代码. 代码质量不需要"代码气候"订阅. +* 使用[默认的 Code Climate 配置](https://gitlab.com/gitlab-org/ci-cd/codequality/-/tree/master/codeclimate_defaults)在[GitLab Code Quality](https://gitlab.com/gitlab-org/ci-cd/codequality)项目中构建的 Docker 映像在[管道中](../../../ci/pipelines/index.html)运行. +* 可以利用[模板](#example-configuration) . +* 可与[Auto DevOps 一起使用](../../../topics/autodevops/stages.html#auto-code-quality-starter) . +* 可以通过[分析插件](https://docs.codeclimate.com/docs/list-of-engines)或[自定义工具](#implementing-a-custom-tool)进行扩展. + +更进一步,GitLab 可以在合并请求小部件区域中显示"代码质量"报告: + +[![Code Quality Widget](img/486761bb835c9408dac03956a04b3a53.png)](img/code_quality.png) + +观看实践中的代码质量快速演练: + +观看视频: [代码质量:快速运行](https://www.youtube.com/watch?v=B32LxtJKo9M) . + +<figure class="video-container"><iframe src="https://www.youtube.com/embed/B32LxtJKo9M" frameborder="0" allowfullscreen=""></iframe></figure> + +**注意:**对于一位客户,审核员发现,在 GitLab CI / CD 中使代码质量,SAST 和容器扫描全部自动化几乎比手动审核要好! [阅读更多](https://about.gitlab.com/customers/bi_worldwide/) . + +另请参阅" [可维护性支持的语言](https://docs.codeclimate.com/docs/supported-languages-for-maintainability)的代码气候列表". + +## Use cases[](#use-cases "Permalink") + +例如,考虑以下工作流程: + +1. 您的后端团队成员将开始新的实施,以更快地使您的应用中的某些功能. +2. 通过代码质量报告,他们可以分析其实施如何影响代码质量. +3. The metrics show that their code degrades the quality by 10 points. +4. 您要求同事来帮助他们进行此修改. +5. 他们都将对更改进行处理,直到"代码质量"报告显示不降级,仅显示改进. +6. 您批准合并请求并授权其部署到暂存. +7. 验证后,其更改将部署到生产中. + +## Example configuration[](#example-configuration "Permalink") + +**注意:** GitLab 11.11 和更高版本支持以下所示的作业定义. 它还需要 GitLab Runner 11.5 或更高版本. 对于早期版本,请使用[先前的作业定义](#previous-job-definitions) . + +本示例说明如何使用 GitLab CI / CD 和 Docker 在代码上运行代码质量. + +首先,您需要配置 GitLab Runner: + +* 对于[Docker-in-Docker 工作流程](../../../ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor) . +* 有足够的磁盘空间来处理生成的代码质量文件. 例如,在[GitLab 项目上](https://gitlab.com/gitlab-org/gitlab) ,文件约为 7 GB. + +设置运行器后,在您的 CI 配置中包括代码质量模板: + +``` +include: + - template: Code-Quality.gitlab-ci.yml +``` + +上面的示例将在 CI / CD 管道中创建一个`code_quality`作业,该作业将扫描源代码以查看代码质量问题. 该报告将另存为["代码质量"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportscodequality-starter) ,您以后可以下载和分析该[工件](../../../ci/pipelines/job_artifacts.html#artifactsreportscodequality-starter) . + +通过设置`CODE_QUALITY_IMAGE`变量,也可以覆盖 URL 到"代码质量"图像. 如果您想锁定特定版本的 Code Quality 或使用其中的一个分支,这将特别有用: + +``` +include: + - template: Code-Quality.gitlab-ci.yml + +code_quality: + variables: + CODE_QUALITY_IMAGE: "registry.example.com/codequality-fork:latest" +``` + +默认情况下,报告工件不可下载. 如果需要在工作详细信息页面上下载它们,则可以将`gl-code-quality-report.json`到工件路径,如下所示: + +``` +include: + - template: Code-Quality.gitlab-ci.yml + +code_quality: + artifacts: + paths: [gl-code-quality-report.json] +``` + +包含的`code_quality`作业正在`test`阶段运行,因此需要将其包含在 CI 配置中,如下所示: + +``` +stages: + - test +``` + +**提示:**该信息将被自动提取并显示在合并请求小部件中.**注意:**在自我管理的实例上,如果恶意行为者破坏了 Code Quality 作业定义,则他们将能够在 Runner 主机上执行特权的 Docker 命令. 拥有适当的访问控制策略,可以通过仅允许访问受信任的参与者来减轻这种攻击. + +### Previous job definitions[](#previous-job-definitions "Permalink") + +**警告:**在 GitLab 11.5 之前,必须专门命名代码质量作业和工件以自动提取报告数据并将其显示在合并请求小部件中. 尽管这些旧的作业定义仍然保留,但它们已被弃用,并且在 GitLab 12.0 或更高版本中不再受支持. 建议您更新`.gitlab-ci.yml`配置以反映该更改. + +对于 GitLab 11.5 及更高版本,该工作应如下所示: + +``` +code_quality: + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + allow_failure: true + services: + - docker:stable-dind + script: + - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') + - docker run + --env SOURCE_CODE="$PWD" + --volume "$PWD":/code + --volume /var/run/docker.sock:/var/run/docker.sock + "registry.gitlab.com/gitlab-org/ci-cd/codequality:$SP_VERSION" /code + artifacts: + reports: + codequality: gl-code-quality-report.json +``` + +在 GitLab 12.6 中,"代码质量"切换到了[新的版本控制方案](https://gitlab.com/gitlab-org/ci-cd/codequality#versioning-and-release-cycle) . 强烈建议包括代码质量模板,如[示例配置](#example-configuration)所示,该模板使用新的版本控制方案. 如果不使用模板,则可以将`SP_VERSION`变量硬编码为使用新的映像版本: + +``` +code_quality: + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + SP_VERSION: 0.85.6 + allow_failure: true + services: + - docker:stable-dind + script: + - docker run + --env SOURCE_CODE="$PWD" + --volume "$PWD":/code + --volume /var/run/docker.sock:/var/run/docker.sock + "registry.gitlab.com/gitlab-org/ci-cd/codequality:$SP_VERSION" /code + artifacts: + reports: + codequality: gl-code-quality-report.json +``` + +对于 GitLab 11.4 和更早版本,该工作应如下所示: + +``` +code_quality: + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + allow_failure: true + services: + - docker:stable-dind + script: + - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') + - docker run + --env SOURCE_CODE="$PWD" + --volume "$PWD":/code + --volume /var/run/docker.sock:/var/run/docker.sock + "registry.gitlab.com/gitlab-org/ci-cd/codequality:$SP_VERSION" /code + artifacts: + paths: [gl-code-quality-report.json] +``` + +或者,作业名称可以是`codeclimate`或`codequality` ,工件名称可以是`codeclimate.json` . 这些名称已在 GitLab 11.0 中弃用,并可能在下一个主要版本 GitLab 12.0 中删除. + +对于 GitLab 10.3 及更早版本,该工作应如下所示: + +``` +codequality: + image: docker:latest + variables: + DOCKER_DRIVER: overlay + services: + - docker:dind + script: + - docker pull codeclimate/codeclimate:0.69.0 + - docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate:0.69.0 init + - docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate:0.69.0 analyze -f json > codeclimate.json || true + artifacts: + paths: [codeclimate.json] +``` + +## Configuring jobs using variables[](#configuring-jobs-using-variables "Permalink") + +代码质量作业支持环境变量,用户可以将其设置为在运行时配置作业执行. + +For a list of available environment variables, see [Environment variables](https://gitlab.com/gitlab-org/ci-cd/codequality#environment-variables). + +## Implementing a custom tool[](#implementing-a-custom-tool "Permalink") + +可以使用自定义工具在 GitLab 中提供代码质量报告. 去做这个: + +1. 在`.gitlab-ci.yml`文件中定义一个生成[代码质量报告工件的作业](../../../ci/pipelines/job_artifacts.html#artifactsreportscodequality-starter) . +2. 配置您的工具以将代码质量报告工件作为 JSON 文件生成,该文件实现了[Code Climate 规范](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#data-types)的子集. + +代码质量报告工件 JSON 文件必须包含具有以下属性的对象数组: + +| Name | Description | +| --- | --- | +| `description` | A description of the code quality violation. | +| `fingerprint` | 用于识别代码质量违规的唯一指纹. 例如,MD5 哈希. | +| `location.path` | 包含代码质量违规的文件的相对路径. | +| `location.lines.begin` | 发生代码质量违规的行. | + +Example: + +``` +[ { "description": "'unused' is assigned a value but never used.", "fingerprint": "7815696ecbf1c96e6894b779456d330e", "location": { "path": "lib/index.js", "lines": { "begin": 42 } } } ] +``` + +**注意:**尽管 Code Climate 规范支持更多属性,但 GitLab 会忽略这些属性. + +## Code Quality reports[](#code-quality-reports "Permalink") + +代码质量工作完成后: + +* 管道生成的违反代码质量的完整列表可在"管道详细信息"页面的"代码质量"选项卡中找到. +* 代码质量的潜在更改直接在合并请求中显示. 合并请求中的"代码质量"窗口小部件比较分支基础和头部的报告,然后列出合并分支时将解决或创建的所有违例. +* 完整的 JSON 报告可作为`code_quality`作业的可[下载工件](../../../ci/pipelines/job_artifacts.html#downloading-artifacts)获得. + +## Extending functionality[](#extending-functionality "Permalink") + +### Using Analysis Plugins[](#using-analysis-plugins "Permalink") + +如果有需要延长的代码质量所提供的默认功能,如在规定[的代码质量](#code-quality-starter) , [分析插件](https://docs.codeclimate.com/docs/list-of-engines)可供选择. + +例如,要使用[SonarJava 分析器](https://docs.codeclimate.com/docs/sonar-java) ,请在存储库的根目录中添加一个名为`.codeclimate.yml`的文件, `.codeclimate.yml`包含插件的[启用代码](https://docs.codeclimate.com/docs/sonar-java#enable-the-plugin) : + +``` +version: "2" +plugins: + sonar-java: + enabled: true +``` + +这会将 SonarJava 添加到项目中[默认`.codeclimate.yml`](https://gitlab.com/gitlab-org/ci-cd/codequality/-/blob/master/codeclimate_defaults/.codeclimate.yml)的`plugins:`部分. + +对`plugins:`部分的更改不会影响 defeault `.codeclimate.yml`的`exclude_patterns`部分. 有关更多详细信息,请参见代码气候文档以[排除文件和文件夹](https://docs.codeclimate.com/docs/excluding-files-and-folders) . + +这是[一个示例项目](https://gitlab.com/jheimbuck_gl/jh_java_example_project) , [该示例项目](https://gitlab.com/jheimbuck_gl/jh_java_example_project)将 Code Quality 与`.codeclimate.yml`文件一起使用. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Changing the default configuration has no effect[](#changing-the-default-configuration-has-no-effect "Permalink") + +一个普遍的问题是`Code Quality` (特定于 GitLab)和`Code Climate` (GitLab 使用的引擎)这两个术语非常相似. 您必须添加**`.codeclimate.yml`**文件来更改默认配置, **而不是** `.codequality.yml`文件. 如果使用错误的文件名,仍将使用[默认的`.codeclimate.yml`](https://gitlab.com/gitlab-org/ci-cd/codequality/-/blob/master/codeclimate_defaults/.codeclimate.yml) . + +### No Code Quality report is displayed in a Merge Request[](#no-code-quality-report-is-displayed-in-a-merge-request "Permalink") + +这可能是由于多种原因: + +* 您刚刚在`.gitlab-ci.yml`添加了代码质量工作. 该报告尚无可比较的内容,因此无法显示任何信息. 将来的合并请求将具有可比性. +* 如果未[检测到降级或错误](https://docs.codeclimate.com/docs/maintainability#section-checks) ,则不会显示任何内容. +* [`artifacts:expire_in`](../../../ci/yaml/README.html#artifactsexpire_in) CI / CD 设置可能导致代码质量构件过期快于所需. +* `codeclimate.json`较大的`codeclimate.json`文件(尤其是> 10 MB)会[阻止报告的显示](https://gitlab.com/gitlab-org/gitlab/-/issues/2737) . 解决方法是,尝试删除[GitLab 忽略的](#implementing-a-custom-tool) [属性](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#data-types) . 您可以: + * 配置代码质量工具以不输出那些类型. + * 在作业完成之前,请在`.gitlab-ci.yml`脚本中使用`sed` , `awk`或类似命令来编辑`codeclimate.json` . + +### Only a single Code Quality report is displayed, but more are defined[](#only-a-single-code-quality-report-is-displayed-but-more-are-defined "Permalink") + +GitLab 仅使用最新创建的作业(具有最大的作业 ID)的代码质量工件. 如果管道中的多个作业生成代码质量工件,则较早作业的那些将被忽略. 为避免混淆,仅配置一个作业即可生成`codeclimate.json` . \ No newline at end of file diff --git a/docs/119.md b/docs/119.md new file mode 100644 index 0000000000000000000000000000000000000000..48ad50b9137038cbda0299b7561d3b8e6cb21244 --- /dev/null +++ b/docs/119.md @@ -0,0 +1,156 @@ +# Load Performance Testing + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/load_performance_testing.html](https://docs.gitlab.com/ee/user/project/merge_requests/load_performance_testing.html) + +* [How Load Performance Testing works](#how-load-performance-testing-works) +* [Configure the Load Performance Testing job](#configure-the-load-performance-testing-job) + * [Determine the test parameters](#determine-the-test-parameters) + * [Test Environment setup](#test-environment-setup) + * [Write the load performance test](#write-the-load-performance-test) + * [Configure the test in GitLab CI/CD](#configure-the-test-in-gitlab-cicd) + * [Load Performance testing in Review Apps](#load-performance-testing-in-review-apps) + +# Load Performance Testing[](#load-performance-testing-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10683) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + +使用负载性能测试,您可以在[GitLab CI / CD 中](../../../ci/README.html)测试任何待处理代码更改对应用程序后端的影响. + +GitLab 使用免费的开源工具[k6](https://k6.io/)来测量负载下应用程序的系统性能. + +Unlike [Browser Performance Testing](browser_performance_testing.html), which is used to measure how web sites perform in client browsers, Load Performance Testing can be used to perform various types of [load tests](https://k6.io/docs/#use-cases) against application endpoints such as APIs, Web Controllers, and so on. This can be used to test how the backend or the server performs at scale. + +例如,您可以使用负载性能测试对应用程序中流行的 API 端点执行许多并发 GET 调用,以查看其性能. + +## How Load Performance Testing works[](#how-load-performance-testing-works "Permalink") + +首先,在您的`.gitlab-ci.yml`文件中定义一个作业,以生成" [负载性能"报告工件](../../../ci/pipelines/job_artifacts.html#artifactsreportsload_performance-premium) . GitLab 会检查此报告,比较源分支和目标分支之间的关键负载性能指标,然后在合并请求小部件中显示信息: + +[![Load Performance Widget](img/1d9bd6ef20c22f103a6d120b8c673b06.png)](img/load_performance_testing.png) + +接下来,您需要配置测试环境并编写 k6 测试. + +测试完成后,合并请求窗口小部件显示的关键性能指标是: + +* 支票:在 k6 测试中配置的[支票的](https://k6.io/docs/using-k6/checks)通过率. +* TTFB P90: The 90th percentile of how long it took to start receiving responses, aka the [Time to First Byte](https://en.wikipedia.org/wiki/Time_to_first_byte) (TTFB). +* TTFB P95:TTFB 的第 95 个百分点. +* RPS:测试能够达到的平均每秒请求数(RPS). + +**注意:**如果"负载性能"报告没有可比较的数据,例如,当您第一次在`.gitlab-ci.yml`添加"负载性能"作业时,"负载性能"报告小部件将不会显示. 它必须在目标分支(例如`master` )上至少运行一次,然后才能在针对该分支的合并请求中显示. + +## Configure the Load Performance Testing job[](#configure-the-load-performance-testing-job "Permalink") + +配置负载性能测试作业可以分为几个不同的部分: + +* 确定测试参数,例如吞吐量,等等. +* 设置目标测试环境以进行负载性能测试. +* 设计并编写 k6 测试. + +### Determine the test parameters[](#determine-the-test-parameters "Permalink") + +您需要做的第一件事是确定要运行[的负载测试](https://k6.io/docs/test-types/introduction)的[类型](https://k6.io/docs/test-types/introduction)以及运行方式(例如,用户数量,吞吐量等). + +请参阅[k6 文档](https://k6.io/docs/) ,尤其是[k6 测试指南](https://k6.io/docs/testing-guides) ,以获取有关上述内容及更多内容的指南. + +### Test Environment setup[](#test-environment-setup "Permalink") + +负载性能测试的大部分工作是为高负载准备目标测试环境. 您应该确保它能够处理将要测试的[吞吐量](https://k6.io/blog/monthly-visits-concurrent-users) . + +通常还需要在目标环境中具有代表性的测试数据,以供负载性能测试使用. + +强烈建议[不要在生产环境中运行这些测试](https://k6.io/our-beliefs#load-test-in-a-pre-production-environment) . + +### Write the load performance test[](#write-the-load-performance-test "Permalink") + +准备好环境后,您可以编写 k6 测试本身. k6 是一种灵活的工具,可用于运行[多种性能测试](https://k6.io/docs/test-types/introduction) . 有关如何编写测试的详细信息,请参阅[k6 文档](https://k6.io/docs/) . + +### Configure the test in GitLab CI/CD[](#configure-the-test-in-gitlab-cicd "Permalink") + +准备好 k6 测试后,下一步就是在 GitLab CI / CD 中配置负载性能测试作业. 最简单的方法是使用 GitLab 随附的[`Verify/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml)模板. + +**注意:**对于大型 k6 测试,您需要确保执行实际测试的 GitLab Runner 实例能够处理运行测试. 有关规格的详细信息,请参阅[k6 的指南](https://k6.io/docs/testing-guides/running-large-tests#hardware-considerations) . [默认的共享 GitLab.com 运行程序](../../gitlab_com/#linux-shared-runners)可能没有足够的规格来处理大多数大型 k6 测试. + +该模板在作业中运行[k6 Docker 容器](https://hub.docker.com/r/loadimpact/k6/) ,并提供了几种自定义作业的方法. + +配置工作流程示例: + +1. 设置一个可以运行 Docker 容器的 GitLab Runner,例如使用[Docker-in-Docker 工作流](../../../ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor)的 Runner. +2. 在`.gitlab-ci.yml`文件中配置默认​​的 Load Performance Testing CI 作业. 您需要包括模板并使用变量进行配置: + + ``` + include: + template: Verify/Load-Performance-Testing.gitlab-ci.yml + + load_performance: + variables: + K6_TEST_FILE: <PATH TO K6 TEST FILE IN PROJECT> + ``` + +上面的示例在运行 k6 测试的 CI / CD 管道中创建了一个`load_performance`作业. + +**注意:**对于 Kubernetes 设置,应使用其他模板: [`Jobs/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml) . + +k6 具有[各种选项](https://k6.io/docs/using-k6/options)来配置它将如何运行测试,例如运行什么吞吐量(RPS),测试应该运行多长时间等等. 几乎所有选项都可以在测试本身中进行配置,但是您也可以通过`K6_OPTIONS`变量传递命令行选项. + +例如,您可以使用 CLI 选项覆盖测试的持续时间: + +``` + include: + template: Verify/Load-Performance-Testing.gitlab-ci.yml + + load_performance: + variables: + K6_TEST_FILE: <PATH TO K6 TEST FILE IN PROJECT> + K6_OPTIONS: '--duration 30s' +``` + +如果 k6 的结果通过[摘要导出](https://k6.io/docs/results-visualization/json#summary-export)保存为" [负载性能"报告工件,则](../../../ci/pipelines/job_artifacts.html#artifactsreportsload_performance-premium) GitLab 仅在 MR 小部件中显示关键性能指标. 始终使用最新的可用负载性能工件. + +如果启用了[GitLab Pages,](../pages/index.html)则可以直接在浏览器中查看报告. + +### Load Performance testing in Review Apps[](#load-performance-testing-in-review-apps "Permalink") + +上面的 CI / CD YAML 配置示例适用于针对静态环境进行测试,但是可以通过一些额外的步骤将其扩展为与[审阅应用程序](../../../ci/review_apps)或[动态环境](../../../ci/environments)一起使用. + +最好的方法是将动态 URL 捕获到一个自定义环境变量中,然后由`load_performance`作业[继承](../../../ci/variables/README.html#inherit-environment-variables)该`load_performance` . 然后应将要运行的 k6 测试脚本配置为使用该环境 URL,例如: `http.get(`${__ENV.ENVIRONMENT_URL`})` . + +例如: + +1. 在`review`工作中: + 1. 捕获动态 URL 并将其保存到`.env`文件,例如`echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env` . + 2. 将`.env`文件设置为[`artifacts:reports:dotenv` report](../../../ci/variables/README.html#inherit-environment-variables) . +2. 将`load_performance`作业设置为依赖于审阅作业,以便它继承环境变量. +3. 配置 k6 测试脚本以在其步骤中使用环境变量. + +您的`.gitlab-ci.yml`文件可能类似于: + +``` +stages: + - deploy + - performance + +include: + template: Verify/Load-Performance-Testing.gitlab-ci.yml + +review: + stage: deploy + environment: + name: review/$CI_COMMIT_REF_NAME + url: http://$CI_ENVIRONMENT_SLUG.example.com + script: + - run_deploy_script + - echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env + artifacts: + reports: + dotenv: + review.env + rules: + - if: '$CI_COMMIT_BRANCH' # Modify to match your pipeline rules, or use `only/except` if needed. + +load_performance: + dependencies: + - review + rules: + - if: '$CI_COMMIT_BRANCH' # Modify to match your pipeline rules, or use `only/except` if needed. +``` \ No newline at end of file diff --git a/docs/120.md b/docs/120.md new file mode 100644 index 0000000000000000000000000000000000000000..0ef4acaba3a6a21fd7f86f75acae9c89b8d60255 --- /dev/null +++ b/docs/120.md @@ -0,0 +1,83 @@ +# Merge Request dependencies + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_dependencies.html](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_dependencies.html) + +* [Use cases](#use-cases) +* [Configuration](#configuration) +* [Limitations](#limitations) + +# Merge Request dependencies[](#merge-request-dependencies-premium "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9688) . +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.4 中从"跨项目依赖项" [重命名](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17291)为"合并请求依赖项". +* [GitLab Premium](https://about.gitlab.com/pricing/) 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16799)了项目内 MR 依赖关系. + +合并请求相关性允许表达合并请求之间的合并所需顺序. 如果合并请求"依赖"另一个请求,则在合并其依赖项之前,不能将其合并. + +**注意:**合并请求依赖项是**PREMIUM**功能,但是此限制仅对依赖合并请求强制执行. **CORE**或**STARTER**项目中的合并请求可以是**PREMIUM**合并请求的依赖项,反之亦然. + +## Use cases[](#use-cases "Permalink") + +* 在更改导入库的项目之前,请确保对库的更改已合并. +* 在实现要记录功能的合并请求之前,防止仅文档合并请求被合并. +* 在合并来自尚未被授予权限的人的合并请求之前,要求合并请求更新要合并的权限矩阵. + +单个逻辑更改通常会跨越多个合并请求,并分散到多个项目中,并且合并的顺序可能很重要. + +例如,给定项目`mycorp/awesome-project`在`myfriend/awesome-lib`处导入了库,在`awesome-project`添加功能可能**还**需要更改`awesome-lib` ,因此需要两个合并请求. 在`awesome-lib`之前合并`awesome-project`合并请求会破坏`master`分支. + +`awesome-project`合并请求可以[标记为**Draft**](work_in_progress_merge_requests.html) ,注释中包含所述草案的原因. 但是,这要求手动跟踪`awesome-lib`合并请求的状态,并且如果`awesome-project`合并请求依赖于对其他**几个**项目的更改,则伸缩性不好. + +通过使`awesome-project`合并请求依赖于`awesome-lib`合并请求,此关系将由 GitLab 自动跟踪,草稿状态可用于在每个单独的合并请求中传达代码的就绪状态. + +## Configuration[](#configuration "Permalink") + +要继续上面的示例,您可以在`awesome-project`创建新的合并请求时配置依赖项(或通过编辑(如果已经存在)). 需要在**依赖**合并请求上配置**依赖** . 表单中有一个" **合并请求依赖项"**部分: + +[![Merge request dependencies form control](img/86c94810add9e77037bd8a135ef2b972.png)](img/dependencies_edit_v12_4.png) + +任何可以编辑合并请求的人都可以更改依赖关系列表. + +可以通过引用或 URL 添加新的依赖项. 要删除依赖项,请按其引用旁边的**X.** + +由于可以在项目之间指定依赖关系,因此其他人可能为您无权访问的项目中的合并请求添加了依赖关系. 这些显示为简单计数: + +[![Merge request dependencies form control with inaccessible merge requests](img/9d8d2ee20801484a30509d79022ce53c.png)](img/dependencies_edit_inaccessible_v12_4.png) + +如有必要,您可以按**X**来删除所有类似的依赖项,就像对单个可见的依赖项一样. + +完成后,请按" **保存更改"**按钮以提交请求,或按" **取消"**以不做任何更改地返回. + +合并请求窗口小部件中显示了已配置依赖项的列表以及每个依赖项的状态: + +[![Dependencies in merge request widget](img/e4b88f4d9d317b9a38522ce9c63f84bc.png)](img/dependencies_view_v12_2.png) + +在所有依赖项本身都被合并之前,对于依赖项合并请求将禁用" **合并"**按钮. 特别要注意的是, **封闭的合并请求**仍会阻止其依赖项被合并-无法自动确定是否已以其他某种方式满足了由封闭的合并请求表示的依赖关系. + +如果已关闭合并请求**,**并且依赖项不再相关,则必须在合并之前按照上述说明将其作为依赖项除去. + +## Limitations[](#limitations "Permalink") + +* API 支持: [问题#12551](https://gitlab.com/gitlab-org/gitlab/-/issues/12551) +* 在项目导出/导入之间未保留依赖项: [问题#12549](https://gitlab.com/gitlab-org/gitlab/-/issues/12549) +* 不支持复杂的合并顺序相关性: [问题#11393](https://gitlab.com/gitlab-org/gitlab/-/issues/11393) + +最后一项值得更多解释. 合并请求之间的依赖关系可以描述为关系图. 最简单的图可能有一个合并请求,该合并请求取决于另一个: + +图 LR; myfriend / awesome-lib!10-> mycorp / awesome-project!100; + +更为复杂(且仍受支持)的图可能具有一个合并请求,该合并请求直接取决于其他几个: + +图 LR; myfriend / awesome-lib!10-> mycorp / awesome-project!100; herfriend / another-lib!1-> mycorp / awesome-project!100; + +几个不同的合并请求也可以直接依赖于同一合并请求: + +图 LR; herfriend / another-lib!1-> myfriend / awesome-lib!10; herfriend / another-lib!1-> mycorp / awesome-project!100; + +**不**支持的是依赖项的"深度"或"嵌套"图. 例如: + +图 LR; herfriend / another-lib!1-> myfriend / awesome-lib!10; myfriend / awesome-lib!10-> mycorp / awesome-project!100; + +在此示例中, `myfriend/awesome-lib!10`取决于`herfriend/another-lib!1` ,它本身是`mycorp/awesome-project!100`的依赖项. 这意味着`myfriend/awesome-lib!10`成为`mycorp/awesome-project!100`的**间接**依赖项,尚不受支持. \ No newline at end of file diff --git a/docs/121.md b/docs/121.md new file mode 100644 index 0000000000000000000000000000000000000000..504bcd33be5f0f166ac75cc9e7d8905429f27e85 --- /dev/null +++ b/docs/121.md @@ -0,0 +1,36 @@ +# Fast-forward merge requests + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/fast_forward_merge.html](https://docs.gitlab.com/ee/user/project/merge_requests/fast_forward_merge.html) + +* [Overview](#overview) +* [Enabling fast-forward merges](#enabling-fast-forward-merges) + +# Fast-forward merge requests[](#fast-forward-merge-requests "Permalink") + +有时,工作流策略可能会强制要求没有合并提交的干净提交历史记录. 在这种情况下,快速合并是理想的选择. + +使用快速转发合并请求,您可以保留线性 Git 历史记录以及一种无需创建合并提交即可接受合并请求的方法. + +## Overview[](#overview "Permalink") + +启用快进合并( [`--ff-only`](https://git-scm.com/docs/git-merge#git-merge---ff-only) )设置时,将不会创建任何合并提交,并且所有合并都将被快速转发,这意味着仅当分支可以被快速转发时才允许合并. + +当无法进行快速合并时,将为用户提供重新设置基准的选项. + +## Enabling fast-forward merges[](#enabling-fast-forward-merges "Permalink") + +1. 导航到项目的**设置,**然后搜索"合并方法" +2. 选择**快速合并**选项 +3. 点击**保存更改**以使更改生效 + +现在,当您访问合并请求页面时, **只有在可能进行快速**合并的情况下,您才能接受它. + +[![Fast forward merge request](img/50ab118d473b61d3d08773d6ea65a8ac.png)](img/ff_merge_mr.png) + +如果无法进行快速合并,但可以进行无冲突的变基,则将提供一个变基按钮. + +[![Fast forward merge request](img/51192310b3785dec5f60b6d59717a7a6.png)](img/ff_merge_rebase.png) + +如果目标分支位于源分支的前面,并且无法进行无冲突的变基,则需要先在本地对源分支进行变基,然后才能进行快速合并. + +[![Fast forward merge rebase locally](img/d241e2868510cfa5755170c1f02c78f3.png)](img/ff_merge_rebase_locally.png) \ No newline at end of file diff --git a/docs/122.md b/docs/122.md new file mode 100644 index 0000000000000000000000000000000000000000..c1d407d8ac952d10c43ede28fbb51365fd7cf905 --- /dev/null +++ b/docs/122.md @@ -0,0 +1,84 @@ +# Merge when pipeline succeeds + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) + +* [How it works](#how-it-works) +* [Only allow merge requests to be merged if the pipeline succeeds](#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds) + * [Limitations](#limitations) + * [Skipped pipelines](#skipped-pipelines) +* [From the command line](#from-the-command-line) + +# Merge when pipeline succeeds[](#merge-when-pipeline-succeeds "Permalink") + +在查看看起来准备合并但仍在运行管道的合并请求时,可以将其设置为在管道成功时自动合并. 这样,您不必等待管道完成,而不必记住手动合并请求. + +[![Enable](img/ac3623994213ad815a95e7826a3cfc3e.png)](img/merge_when_pipeline_succeeds_enable.png) + +## How it works[](#how-it-works "Permalink") + +当您单击"管道成功时合并"时,合并请求的状态将更新以显示即将进行的合并. 如果您不能等待管道成功,则可以**立即**在主按钮右侧的下拉菜单中选择" **合并"** . + +合并请求的作者和具有开发人员权限的项目成员可以在管道完成之前的任何时间取消自动合并. + +[![Status](img/46322215ec68c4896b6b622f9f1ad11e.png)](img/merge_when_pipeline_succeeds_status.png) + +管道成功后,合并请求将自动合并. 当管道失败时,作者有机会重试任何失败的作业,或推送新的提交以修复失败. + +重试作业并第二次尝试成功后,合并请求将自动合并. 当使用新提交更新合并请求时,自动合并将被取消以允许查看新更改. + +## Only allow merge requests to be merged if the pipeline succeeds[](#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds "Permalink") + +如果合并请求的管道未成功或存在要解析的线程,则可以阻止合并请求. 这对两个都适用: + +* GitLab CI / CD 管道 +* 管道从[外部 CI 集成](../integrations/overview.html#integrations-listing)运行 + +因此, [禁用 GitLab CI / CD 管道](../../../ci/enable_or_disable_ci.html)不会禁用此功能,因为可以将外部 CI 提供程序的管道与该功能一起使用. 要启用它,您必须: + +1. 导航到项目的**"设置">"常规"**页面. +2. 展开**合并请求**部分. +3. 在" **合并检查"**小节中,选中" **管道必须成功"**复选框. +4. 按**保存**使更改生效. + +This setting also prevents merge requests from being merged if there is no pipeline. + +### Limitations[](#limitations "Permalink") + +启用此设置后,如果没有管道,将阻止合并请求. 这可能与[`only/except`](../../../ci/yaml/README.html#onlyexcept-advanced)使用[`only/except`](../../../ci/yaml/README.html#onlyexcept-advanced)或[`rules`](../../../ci/yaml/README.html#rules)且不生成任何管道的某些用例相冲突. + +您应该确保[始终有一个管道](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54226)并且该[管道](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54226)是成功的. + +如果为单个合并请求触发了分支管道和合并请求管道,则仅检查*合并请求管道*的成功或失败. 如果合并请求管道配置的工作少于分支管道,则它可能允许失败测试的代码被合并: + +``` +branch-pipeline-job: + rules: + - if: '$CI_PIPELINE_SOURCE == "push"' + script: + - echo "Code testing scripts here, for example." + +merge-request-pipeline-job: + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + script: + - echo "No tests run, but this pipeline always succeeds and enables merge." + - echo true +``` + +您应该避免这样的配置,并尽可能使用分支( `push` )管道或合并请求管道. 有关在单个合并请求中避免使用两个管道的详细信息,请参见[`rules`文档](../../../ci/yaml/README.html#differences-between-rules-and-onlyexcept) . + +### Skipped pipelines[](#skipped-pipelines "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/211482) . + +选中" **管道必须成功"**复选框时, [跳过的管道会](../../../ci/yaml/README.html#skip-pipeline)阻止合并请求被合并. 更改此行为: + +1. 导航到项目的**"设置">"常规"**页面. +2. 展开**合并请求**部分. +3. 在" **合并检查"**小节中,确保已选中" **管道必须成功"** . +4. 在" **合并检查"**小节中,选中" **跳过的管道被视为成功"**复选框. +5. 按**保存**使更改生效. + +## From the command line[](#from-the-command-line "Permalink") + +当从命令行进行[推送](../push_options.html)时,当管道成功请求合并请求时,可以使用" [推送选项"](../push_options.html)启用合并. \ No newline at end of file diff --git a/docs/123.md b/docs/123.md new file mode 100644 index 0000000000000000000000000000000000000000..dc30395d2d3eebc00482b3597bc40177351094f3 --- /dev/null +++ b/docs/123.md @@ -0,0 +1,51 @@ +# Merge request conflict resolution + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/resolve_conflicts.html](https://docs.gitlab.com/ee/user/project/merge_requests/resolve_conflicts.html) + +* [Resolve conflicts: interactive mode](#resolve-conflicts-interactive-mode) +* [Resolve conflicts: inline editor](#resolve-conflicts-inline-editor) +* [Conflicts available for resolution](#conflicts-available-for-resolution) + +# Merge request conflict resolution[](#merge-request-conflict-resolution "Permalink") + +当两个分支具有无法自动合并的不同更改时,将发生合并冲突. + +在大多数情况下,Git 能够自动合并分支之间的更改,但是在某些情况下,Git 需要您的帮助来手动解决冲突. 通常,当人们更改同一文件的相同部分时,这是必需的. + +在解决所有冲突之前,GitLab 将阻止合并请求. 冲突可以在本地解决,也可以在许多情况下在 GitLab 中解决(有关何时可用的信息,请参见可解决的[冲突](#conflicts-available-for-resolution) ). + +[![Merge request widget](img/c3174e54aed82ba15686b58fc97068f1.png)](img/merge_request_widget.png) + +**注意:** GitLab 通过在未自动合并到目标分支的源分支中创建合并提交来解决冲突. 这允许在合并更改之前对合并提交进行检查和测试,从而防止意外更改进入目标分支而无需检查或破坏构建. + +## Resolve conflicts: interactive mode[](#resolve-conflicts-interactive-mode "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5479) . + +单击此按钮将显示有冲突的文件列表,突出显示冲突部分: + +[![Conflict section](img/7a9e6a406ba2eb40638f2b43024b368b.png)](img/conflict_section.png) + +一旦所有冲突都标记为使用"我们的"或"他们的",则可以解决冲突. 这将执行合并请求的目标分支到源分支的合并,使用选择的选项解决冲突. 如果源分支是`feature` ,目标分支是`master` ,则类似于执行`git checkout feature; git merge master` `git checkout feature; git merge master`本地`git checkout feature; git merge master` . + +## Resolve conflicts: inline editor[](#resolve-conflicts-inline-editor "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6374) in GitLab 8.13. + +合并冲突解决编辑器允许更复杂的合并冲突,需要用户手动修改文件以解决冲突,才能从 GitLab 界面中解决. 使用**内联编辑**按钮打开编辑器. 确定更改后,请单击" **提交到源"分支**按钮. + +[![Merge conflict editor](img/7a5996be0f8e75beb29e443470d79ee6.png)](img/merge_conflict_editor.png) + +## Conflicts available for resolution[](#conflicts-available-for-resolution "Permalink") + +GitLab 允许解决以下所有条件均成立的文件中的冲突: + +* 该文件是文本,不是二进制 +* 该文件采用 UTF-8 兼容编码 +* 该文件尚未包含冲突标记 +* 添加了冲突标记的文件大小不超过 200 KB +* 该文件在两个分支中位于相同路径下 + +如果该合并请求中有冲突的任何文件均不满足所有这些条件,则无法在 UI 中解决该合并请求的冲突. + +此外,GitLab 不会在路径之外的重命名中检测到冲突. 例如,这不会造成冲突:在分支`a`执行`git mv file1 file2` ; 在分支`b` ,执行`git mv file1 file3` . 而是,合并请求合并后,两个文件都将出现在分支中. \ No newline at end of file diff --git a/docs/124.md b/docs/124.md new file mode 100644 index 0000000000000000000000000000000000000000..a970a0c4c15102375ae5f41fa6bbbc98b7c48693 --- /dev/null +++ b/docs/124.md @@ -0,0 +1,40 @@ +# Reverting changes + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/revert_changes.html](https://docs.gitlab.com/ee/user/project/merge_requests/revert_changes.html) + +* [Reverting a merge request](#reverting-a-merge-request) +* [Reverting a commit](#reverting-a-commit) + +# Reverting changes[](#reverting-changes "Permalink") + +您可以使用 Git 的强大功能,通过在合并请求和提交详细信息中单击" **还原"**按钮来[还原任何提交](https://git-scm.com/docs/git-revert "Git 恢复文档") . + +## Reverting a merge request[](#reverting-a-merge-request "Permalink") + +**注意:** " **还原"**按钮仅可用于自 GitLab 8.5 起创建的合并请求. 但是,您仍然可以通过从"提交"页面列表中还原合并提交来还原合并请求.**注意:**仅对使用合并方法"合并提交"的项目显示" **还原"**按钮,该方法可以在项目的**"设置">"常规">"合并请求"**下**设置** . 无法通过 MR 视图还原[快进提交](fast_forward_merge.html) . + +合并请求合并后,将有一个**还原**按钮可用于还原该合并请求引入的更改. + +[![Revert Merge Request](img/fe7d77556848be98a93c7b6516b0e6f8.png)](img/cherry_pick_changes_mr.png) + +单击该按钮后,将出现一个模式,您可以在其中选择将更改直接还原到所选分支中,也可以选择使用还原更改创建新的合并请求. + +合并请求恢复后," **恢复"**按钮将不再可用. + +## Reverting a commit[](#reverting-a-commit "Permalink") + +您可以从提交详细信息页面还原提交: + +[![Revert commit](img/b4e821b8b83e29e837f01f4620e557b7.png)](img/cherry_pick_changes_commit.png) + +与还原合并请求类似,您可以选择将更改直接还原到目标分支中,也可以选择创建新的合并请求以还原更改. + +恢复提交后," **恢复"**按钮将不再可用. + +请注意,还原合并提交时,主线将始终是第一父级. 如果要使用其他主线,则需要从命令行执行. + +这是一个使用第二个父级作为主线还原合并提交的快速示例: + +``` +git revert -m 2 7a39eb0 +``` \ No newline at end of file diff --git a/docs/125.md b/docs/125.md new file mode 100644 index 0000000000000000000000000000000000000000..7961872890874955841bb21b7cbee07b6ec8706d --- /dev/null +++ b/docs/125.md @@ -0,0 +1,290 @@ +# Reviewing and managing merge requests + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/reviewing_and_managing_merge_requests.html](https://docs.gitlab.com/ee/user/project/merge_requests/reviewing_and_managing_merge_requests.html) + +* [View project merge requests](#view-project-merge-requests) +* [View merge requests for all projects in a group](#view-merge-requests-for-all-projects-in-a-group) +* [Semi-linear history merge requests](#semi-linear-history-merge-requests) +* [View changes between file versions](#view-changes-between-file-versions) + * [Merge request diff file navigation](#merge-request-diff-file-navigation) + * [File-by-file diff navigation](#file-by-file-diff-navigation) + * [Enable or disable file-by-file diff navigation](#enable-or-disable-file-by-file-diff-navigation-core-only) + * [Merge requests commit navigation](#merge-requests-commit-navigation) + * [Incrementally expand merge request diffs](#incrementally-expand-merge-request-diffs) + * [Ignore whitespace changes in Merge Request diff view](#ignore-whitespace-changes-in-merge-request-diff-view) +* [Perform inline code reviews](#perform-inline-code-reviews) +* [Pipeline status in merge requests widgets](#pipeline-status-in-merge-requests-widgets) + * [Post-merge pipeline status](#post-merge-pipeline-status) + * [Merge when pipeline succeeds (MWPS)](#merge-when-pipeline-succeeds-mwps) + * [Live preview with Review Apps](#live-preview-with-review-apps) +* [Associated features](#associated-features) +* [Troubleshooting](#troubleshooting) + * [Merge request cannot retrieve the pipeline status](#merge-request-cannot-retrieve-the-pipeline-status) + * [Sidekiq](#sidekiq) + * [Bug](#bug) +* [Tips](#tips) + * [Checkout merge requests locally](#checkout-merge-requests-locally) + * [Checkout locally by adding a Git alias](#checkout-locally-by-adding-a-git-alias) + * [Checkout locally by modifying `.git/config` for a given repository](#checkout-locally-by-modifying-gitconfig-for-a-given-repository) + +# Reviewing and managing merge requests[](#reviewing-and-managing-merge-requests "Permalink") + +合并请求是在 GitLab 项目中更改文件的主要方法. 通过[创建并提交合并请求](creating_merge_requests.html)来提出更改,然后将其审核并接受(或拒绝). + +## View project merge requests[](#view-project-merge-requests "Permalink") + +导航到" **项目">"合并请求",**以查看项目中的所有**合并请求** . + +当您访问项目的合并请求时,GitLab 会将它们显示在列表中,并且您可以使用可用的选项卡来快速按打开和关闭进行过滤. 您还可以[搜索和过滤结果](../../search/index.html#filtering-issue-and-merge-request-lists) . + +[![Project merge requests list view](img/252e40c4dc029a21eb939cb40f715d34.png)](img/project_merge_requests_list_view.png) + +## View merge requests for all projects in a group[](#view-merge-requests-for-all-projects-in-a-group "Permalink") + +查看组中所有项目中的合并请求,包括组中所有后代子组的所有项目. 导航到**组>合并请求**以查看这些合并请求. 该视图还具有打开和关闭的合并请求选项卡. + +您可以从此处[搜索和过滤结果](../../search/index.html#filtering-issue-and-merge-request-lists) . + +[![Group Issues list view](img/1c96e8d94988240b7dc68ae02dbea405.png)](img/group_merge_requests_list_view.png) + +## Semi-linear history merge requests[](#semi-linear-history-merge-requests "Permalink") + +将为每个合并创建一个合并提交,但是只有在可能进行快速合并的情况下才合并分支. 这样可以确保如果合并请求构建成功,则合并后目标分支构建也将成功. + +导航到项目的设置,在" **合并请求:合并"方法**下选择" **使用半线性历史** **合并合并"**选项,然后保存更改. + +## View changes between file versions[](#view-changes-between-file-versions "Permalink") + +**更改**选项卡位于主要合并请求详细信息下方,并且在讨论选项卡旁边,显示了分支或提交之间文件的更改. 这种对文件更改的视图也称为**diff** . 默认情况下,差异视图将合并请求分支中的文件与目标分支中的文件进行比较. + +The diff view includes the following: + +* 文件的名称和路径. +* 添加和删​​除的行数. +* 用于以下选项的按钮: + * 切换此文件的注释; 用于内联评论. + * 在合并请求的分支中编辑文件. + * 显示完整文件,以防您要查看上下文中文件其余部分的更改. + * 在当前提交时查看文件. + * 使用[Review Apps](../../../ci/review_apps/index.html)预览更改. +* 已更改的行,突出显示了特定的更改. + +[![Example screenshot of a source code diff](img/1a3f578f317c266ca4b5d61eb91d025b.png)](img/merge_request_diff_v12_2.png) + +### Merge request diff file navigation[](#merge-request-diff-file-navigation "Permalink") + +在" **更改"**选项卡中查看更改时,可以使用文件树或文件列表来浏览差异. 在具有许多更改的大型差异中滚动时,可以使用文件树或文件列表快速跳转到任何更改的文件. + +[![Merge request diff file navigation](img/65770b50cd2119e84c6a852b44cf403d.png)](img/merge_request_diff_file_navigation.png) + +### File-by-file diff navigation[](#file-by-file-diff-navigation "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/222790) . +* 它部署在默认情况下启用的功能标志后面. +* 建议用于生产. +* 在 GitLab.com 上启用了它. +* 对于 GitLab 自我管理的实例,GitLab 管理员可以选择[禁用它](#enable-or-disable-file-by-file-diff-navigation-core-only) . + +对于较大的合并请求,有时一次查看单个文件可能会很有用. 要启用,请从右上角导航栏上的头像,单击**"设置"** ,然后转到左侧边栏上的**"首选项"** . 向下滚动到" **行为"**部分,然后**在合并请求的"更改"标签上**选择**"一次显示一个文件"** . 点击**保存更改**以应用. + +从那里,在查看合并请求的" **更改"**选项卡时,一次只能看到一个文件. 然后,您可以单击按钮上**一个**和**下一个**以查看其他已更改的文件. + +[![File-by-file diff navigation](img/7887f58c141f9c2e749a75158e430ac6.png)](img/file_by_file_v13_2.png) + +#### Enable or disable file-by-file diff navigation[](#enable-or-disable-file-by-file-diff-navigation-core-only "Permalink") + +逐文件差异导航正在开发中,但已准备好用于生产. 它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以选择为您的实例禁用它. + +要启用它: + +``` +# Instance-wide +Feature.enable(:view_diffs_file_by_file) +``` + +禁用它: + +``` +# Instance-wide +Feature.disable(:view_diffs_file_by_file>) +``` + +### Merge requests commit navigation[](#merge-requests-commit-navigation "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18140) in GitLab 13.0. + +要在合并请求中的**提交**之间无缝导航,请从" **提交"**选项卡中,单击其中一个提交以打开单提交视图. 从那里,您可以通过单击页面右上角的**Prev**和**Next**按钮或使用`X`和`C`键盘快捷键在提交之间进行导航. + +### Incrementally expand merge request diffs[](#incrementally-expand-merge-request-diffs "Permalink") + +默认情况下,差异仅显示文件中已更改的部分. 要查看更改上方或下方的更多未更改行,请单击" **向上** **扩展"**或" **向下扩展"**图标. 您也可以单击**显示未更改的行**以展开整个文件. + +[![Incrementally expand merge request diffs](img/da60a36cf66e162640faa1f6cddaacdc.png)](img/incrementally_expand_merge_request_diffs_v12_2.png) + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/205401) ,当查看合并请求的**更改**选项卡时,如果仅重命名了某个文件,则可以通过单击**显示文件内容**展开它以查看全部**内容** . + +### Ignore whitespace changes in Merge Request diff view[](#ignore-whitespace-changes-in-merge-request-diff-view "Permalink") + +如果单击" **隐藏空白更改"**按钮,则可以看到没有空白更改的差异(如果有的话). 在特定的提交页面上,这也可以工作. + +[![MR diff](img/1a097c142decf7d516165322a0f7b880.png)](img/merge_request_diff.png) + +> **提示:**您可以在合并请求的差异页面上附加`?w=1` ,以忽略任何空格更改. + +## Perform inline code reviews[](#perform-inline-code-reviews "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/13950) . + +GitLab 提供了一种在合并请求中更改文件的任何部分中保留注释的方法. 为此,请在"合并请求"差异 UI 的装订线中单击**…**按钮以展开差异行并留下评论,就像更改行一样. + +[![Comment on any diff file line](img/9aa51957855aec8590e352694fe75d5d.png)](img/comment-on-any-diff-line.png) + +## Pipeline status in merge requests widgets[](#pipeline-status-in-merge-requests-widgets "Permalink") + +如果您在项目中设置了[GitLab CI / CD](../../../ci/README.html) ,您将能够看到: + +* 合并前和合并后管道以及环境信息(如果有). +* 正在进行哪些部署. + +如果存在[环境](../../../ci/environments/index.html)并且已将应用程序成功部署到该环境,则还将显示已部署的环境以及指向 Review App 的链接. + +### Post-merge pipeline status[](#post-merge-pipeline-status "Permalink") + +合并请求合并后,可以看到合并请求合并到的分支的合并后管道状态. 例如,当合并请求合并到 master 分支中,然后触发到暂存环境的部署时. + +将显示正在进行的部署,以及环境的部署/部署状态. 如果是第一次部署分支,则该链接将返回`404`错误,直到完成. 在部署期间,停止按钮将被禁用. 如果管道无法部署,则部署信息将被隐藏. + +[![Merge request pipeline](img/1c4eef7cdb82fd840a9facad4ee93d6b.png)](img/merge_request_pipeline.png) + +有关更多信息,请[阅读有关管道](../../../ci/pipelines/index.html) . + +### Merge when pipeline succeeds (MWPS)[](#merge-when-pipeline-succeeds-mwps "Permalink") + +设置一个看起来准备合并的合并请求,以[在 CI 管道成功时自动合并](merge_when_pipeline_succeeds.html) . + +### Live preview with Review Apps[](#live-preview-with-review-apps "Permalink") + +如果为项目配置了[Review Apps](https://about.gitlab.com/stages-devops-lifecycle/review-apps/) ,则可以逐分支预览通过合并请求提交给功能分支的更改. 无需检出分支机构,在本地安装和预览; 带有"评论应用"链接的任何人都可以预览所有更改. + +设置了 GitLab 的" [路线图"后](../../../ci/review_apps/index.html#route-maps) ,合并请求小部件会将您直接带到已更改的页面,从而使预览建议的修改变得更加轻松快捷. + +[Read more about Review Apps](../../../ci/review_apps/index.html). + +## Associated features[](#associated-features "Permalink") + +还有大量与合并请求关联的功能: + +| Feature | Description | +| --- | --- | +| [Bulk editing merge requests](../../project/bulk_editing.html) | 同时更新多个合并请求的属性. | +| [Cherry-pick changes](cherry_pick_changes.html) | 只需在合并的合并请求或提交中单击**Cherry-pick**按钮,即可在 UI 中 Cherry-pick 任何**选择** . | +| [Fast-forward merge requests](fast_forward_merge.html) | 有关线性 Git 历史记录以及接受合并请求而不创建合并提交的方法 | +| [Find the merge request that introduced a change](versions.html) | 当查看提交详细信息页面时,GitLab 将链接到包含该提交的合并请求. | +| [Merge requests versions](versions.html) | 选择并比较合并请求差异的不同版本 | +| [Resolve conflicts](resolve_conflicts.html) | GitLab 可以提供选项来解决 GitLab UI 中的某些合并请求冲突. | +| [Revert changes](revert_changes.html) | 从合并请求中的任何提交还原更改. | + +## Troubleshooting[](#troubleshooting "Permalink") + +有时,合并请求中的操作并没有按预期进行,这是一些故障排除步骤. + +### Merge request cannot retrieve the pipeline status[](#merge-request-cannot-retrieve-the-pipeline-status "Permalink") + +如果 Sidekiq 没有足够快地进行更改,则会发生这种情况. + +#### Sidekiq[](#sidekiq "Permalink") + +Sidekiq 没有足够快地处理 CI 状态更改. 请等待几秒钟,状态将自动更新. + +#### Bug[](#bug "Permalink") + +发生以下情况时,无法检索合并请求管道的状态: + +1. 创建合并请求 +2. 合并请求已关闭 +3. 在项目中进行了更改 +4. 合并请求被重新打开 + +要正确检索管道状态,请再次关闭并重新打开"合并请求". + +## Tips[](#tips "Permalink") + +以下是一些技巧,可帮助您在命令行中更有效地处理合并请求. + +> **注意:**此部分将来可能会在其自己的文档中移动. + +### Checkout merge requests locally[](#checkout-merge-requests-locally "Permalink") + +合并请求包含来自存储库的所有历史记录,以及添加到与合并请求关联的分支的其他提交. 这是一些在本地检出合并请求的技巧. + +请注意,即使源项目是目标项目的分支(甚至是私有分支),也可以在本地签出合并请求. + +#### Checkout locally by adding a Git alias[](#checkout-locally-by-adding-a-git-alias "Permalink") + +将以下别名添加到`~/.gitconfig` : + +``` +[alias] + mr = !sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' - +``` + +现在,您可以从任何存储库和任何远程签出特定的合并请求. 例如,要从`origin`远程服务器签出 ID 为 5 的合并请求(如 GitLab 所示),请执行以下操作: + +``` +git mr origin 5 +``` + +这会将合并请求提取到本地`mr-origin-5`分支中,并检出它. + +#### Checkout locally by modifying `.git/config` for a given repository[](#checkout-locally-by-modifying-gitconfig-for-a-given-repository "Permalink") + +在`.git/config`文件中找到适用于 GitLab 遥控器的部分. 看起来像这样: + +``` +[remote "origin"] + url = https://gitlab.com/gitlab-org/gitlab-foss.git + fetch = +refs/heads/*:refs/remotes/origin/* +``` + +您可以使用以下方式打开文件: + +``` +git config -e +``` + +现在,将以下行添加到上面的部分: + +``` +fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/* +``` + +最后,它应如下所示: + +``` +[remote "origin"] + url = https://gitlab.com/gitlab-org/gitlab-foss.git + fetch = +refs/heads/*:refs/remotes/origin/* + fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/* +``` + +现在,您可以获取所有合并请求: + +``` +git fetch origin + +... +From https://gitlab.com/gitlab-org/gitlab-foss.git + * [new ref] refs/merge-requests/1/head -> origin/merge-requests/1 + * [new ref] refs/merge-requests/2/head -> origin/merge-requests/2 +... +``` + +并检查特定的合并请求: + +``` +git checkout origin/merge-requests/1 +``` + +以上所有操作均可通过[`git-mr`](https://gitlab.com/glensc/git-mr)脚本完成. \ No newline at end of file diff --git a/docs/126.md b/docs/126.md new file mode 100644 index 0000000000000000000000000000000000000000..2caaf125ceb444d3c7f0d457016ec9ac7e92fd56 --- /dev/null +++ b/docs/126.md @@ -0,0 +1,123 @@ +# Squash and merge + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html](https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Enabling squash for a merge request](#enabling-squash-for-a-merge-request) +* [Commit metadata for squashed commits](#commit-metadata-for-squashed-commits) +* [Squash and fast-forward merge](#squash-and-fast-forward-merge) +* [Squash Commits Options](#squash-commits-options) + * [Enable or disable Squash Commit Options](#enable-or-disable-squash-commit-options-core-only) + +# Squash and merge[](#squash-and-merge "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 8.17 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1024) . +* [移植](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18956)到 GitLab Core 11.0\. + +使用 squash 和 merge,您可以将所有合并请求的提交合并为一个并保留干净的历史记录. + +## Overview[](#overview "Permalink") + +通过压接,您可以在接受合并请求时整理分支的提交历史记录. 它将合并请求中的所有更改作为单个提交应用,然后使用为项目设置的合并方法合并该提交. + +换句话说,挤压合并请求会变成一长串提交: + +[![List of commits from a merge request](img/f2d420adddd87cc8087fea62246e7b67.png)](img/squash_mr_commits.png) + +合并为单个提交: + +[![A squashed commit followed by a merge commit](img/e81fe926a5b379f37dfc5af80b8f83f3.png)](img/squash_squashed_commit.png) + +压缩的提交的提交消息将是: + +* 取自合并中的第一条多行提交消息. +* 如果找不到多行提交消息,则合并请求的标题. + +**注意:**仅在至少 2 次提交时,此选项才生效. 由于没有什么可压缩的,因此如果只有 1 次提交,则提交消息不会更改. + +可以在合并合并请求之前对其进行自定义. + +[![A squash commit message editor](img/618ce3d47266d9b45262489065b68cf7.png)](img/squash_mr_message.png) + +**注意:**在此示例中,压缩的提交之后是合并提交,因为此示例存储库的合并方法使用了合并提交. + +压缩也适用于快进合并策略,有关更多详细信息,请参见[压缩和快进合并](#squash-and-fast-forward-merge) . + +## Use cases[](#use-cases "Permalink") + +在功能分支上工作时,有时您想提交当前进度,但实际上并不关心提交消息. 这些"进行中的提交"不一定包含重要的信息,因此,您宁愿不将其包含在目标分支中. + +使用 squash 和 merge,当准备好要合并的合并请求时,您要做的就是在按下 merge 之前将挤压启用,以将合并请求中的提交加入到单个提交中. + +这样,您的基本分支的历史记录将保留有意义的提交消息,并且: + +* 如有必要, [还原](revert_changes.html)更为简单. +* 合并的分支将保留完整的提交历史记录. + +## Enabling squash for a merge request[](#enabling-squash-for-a-merge-request "Permalink") + +可以创建或编辑合并请求的任何人都可以选择将其压缩在合并请求表单上: + +[![Squash commits checkbox on edit form](img/fd54213f0e98a4b2f6482ab98d497410.png)](img/squash_edit_form.png) + +然后可以在接受合并请求时覆盖它: + +[![Squash commits checkbox on accept merge request form](img/3667bc1901823963df25df8a2458047a.png)](img/squash_mr_widget.png) + +## Commit metadata for squashed commits[](#commit-metadata-for-squashed-commits "Permalink") + +压缩的提交具有以下元数据: + +* 消息:壁球提交消息或自定义消息. +* 作者:合并请求的作者. +* 提交者:发起壁球的用户. + +## Squash and fast-forward merge[](#squash-and-fast-forward-merge "Permalink") + +当项目[启用](fast_forward_merge.html#enabling-fast-forward-merges)了[快进合并设置时](fast_forward_merge.html#enabling-fast-forward-merges) ,合并请求必须能够不压缩而进行快速转发以进行压缩. 这是因为压缩仅在接受合并请求时可用,因此即使挤压本身可以被认为等同于重新基准化,也可能需要在压缩之前对合并请求进行重新基准化. + +## Squash Commits Options[](#squash-commits-options "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/17613) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上已禁用. +* 不建议将其用于生产. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-squash-commit-options-core-only) . + +使用 Squash Commits Options,您可以为项目配置 Squash 和 Merge 的行为. 要进行设置,请导航至项目的**设置>常规,**然后展开**合并请求** . 您将找到以下选项可供选择,这将影响提交给您的项目的现有和新合并请求: + +* **不允许** :用户不能在合并之前立即使用 Squash 和 Merge 来压缩所有提交. 启用或禁用它的复选框将被取消选中,并且对用户隐藏. +* **Allow**: users will have the option to enable Squash and Merge on a merge request basis. The checkbox will be unchecked (disabled) by default, but and the user is allowed to enable it. +* **鼓励** :用户可以选择在合并请求的基础上启用 Squash 和 Merge. 默认情况下会选中(启用)该复选框以鼓励使用,但允许用户禁用它. +* **要求** :对所有合并请求都启用了"挤压和合并",因此将始终执行. 启用或禁用它的复选框将被选中并向用户隐藏. + +创建合并请求以及编辑现有请求的描述时,将显示" Squash and Merge"复选框,但" Squash Commit Options"设置为**"不允许"**或" **Require"**时除外. + +**注意:**如果您的项目设置为**"不允许**挤压和合并",则用户仍然可以选择通过命令行在本地挤压提交,并在合并之前强制将其推送到其远程分支. + +### Enable or disable Squash Commit Options[](#enable-or-disable-squash-commit-options-core-only "Permalink") + +壁球提交选项正在开发中,尚未准备好用于生产. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以为您的实例启用它. 可以根据项目启用或禁用壁球提交选项. + +要启用它: + +``` +# Instance-wide +Feature.enable(:squash_options) +# or by project +Feature.enable(:squash_options, Project.find(<project id>)) +``` + +禁用它: + +``` +# Instance-wide +Feature.disable(:squash_options) +# or by project +Feature.disable(:squash_options, Project.find(<project id>)) +``` \ No newline at end of file diff --git a/docs/127.md b/docs/127.md new file mode 100644 index 0000000000000000000000000000000000000000..556beb01657384d332ae1f2cf79b60de108154e1 --- /dev/null +++ b/docs/127.md @@ -0,0 +1,49 @@ +# Merge requests versions + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/versions.html](https://docs.gitlab.com/ee/user/project/merge_requests/versions.html) + +* [Selecting a version](#selecting-a-version) +* [Find the merge request that introduced a change](#find-the-merge-request-that-introduced-a-change) +* [`HEAD` comparison mode for Merge Requests](#head-comparison-mode-for-merge-requests) + +# Merge requests versions[](#merge-requests-versions "Permalink") + +每次您推送到与合并请求绑定的分支时,都会创建新版本的合并请求 diff. 当您访问包含多个推送的合并请求时,可以选择并比较那些合并请求差异的版本. + +[![Merge request versions](img/0d2f752f5d8c7352da5333f4f0d27835.png)](img/versions.png) + +## Selecting a version[](#selecting-a-version "Permalink") + +默认情况下,显示更改的最新版本. 但是,您可以从版本下拉列表中选择一个较旧的版本. + +[![Merge request versions dropdown](img/1864a1996bbb1636d65648dd8b0857df.png)](img/versions_dropdown.png) + +合并请求版本基于推送而不是提交. 因此,如果您单次推送了 5 次提交,那么下拉菜单中的选项就是一个. 如果您按了 5 次,则算上 5 个选项. + +您还可以将合并请求版本与旧版本进行比较,以查看此后发生了什么变化. + +[![Merge request versions compare](img/f0a8b71ac0a74f03724937e45e8782b9.png)](img/versions_compare.png) + +在查看过时的合并版本或与基本版本以外的版本进行比较时,将禁用注释. + +每次将新更改推送到分支时,系统都会显示一个用于比较最后更改的链接. + +[![Merge request versions system note](img/8201105b83669750c4d60036b41f6c6d.png)](img/versions_system_note.png) + +## Find the merge request that introduced a change[](#find-the-merge-request-that-introduced-a-change "Permalink") + +在 GitLab 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/2383) . + +在查看提交详细信息页面时,GitLab 将链接到包含该提交的合并请求(或合并请求,如果存在多个). + +这仅适用于最新版本的合并请求中的提交-如果某个提交位于合并请求中,然后根据该合并请求重新建立基础,则不会链接它们. + +## `HEAD` comparison mode for Merge Requests[](#head-comparison-mode-for-merge-requests "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27008) . + +合并请求(尤其是" **更改"**选项卡)是查看和讨论源代码的地方. 在目标分支被合并到合并请求的源分支的情况下,源分支和目标分支中的更改可以显示为混合在一起,这使得很难理解目标分支中正在添加哪些更改以及已经存在哪些更改. + +在 GitLab 12.10 中,我们添加了一个比较模式,该模式显示了通过模拟合并后的差异计算出的差异-更准确地表示更改,而不是使用两个分支的基础. 通过选择**master(HEAD),**可以从比较目标下拉列表中使用新模式. 将来它将[替换](https://gitlab.com/gitlab-org/gitlab/-/issues/198458)当前的默认比较. + +[![Merge request versions compare HEAD](img/3478cae6da4e529f7c9cf2f4e71dd462.png)](img/versions_compare_head_v12_10.png) \ No newline at end of file diff --git a/docs/128.md b/docs/128.md new file mode 100644 index 0000000000000000000000000000000000000000..f4946df513d05e24390f5c927643b7d39b806b90 --- /dev/null +++ b/docs/128.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/authorization_for_merge_requests.html](https://docs.gitlab.com/ee/user/project/merge_requests/authorization_for_merge_requests.html) \ No newline at end of file diff --git a/docs/129.md b/docs/129.md new file mode 100644 index 0000000000000000000000000000000000000000..414fe2486951773e6a5a0d736b745991bf13dc39 --- /dev/null +++ b/docs/129.md @@ -0,0 +1,38 @@ +# Draft merge requests + +> 原文:[https://docs.gitlab.com/ee/user/project/merge_requests/work_in_progress_merge_requests.html](https://docs.gitlab.com/ee/user/project/merge_requests/work_in_progress_merge_requests.html) + +* [Adding the “Draft” flag to a merge request](#adding-the-draft-flag-to-a-merge-request) +* [Removing the “Draft” flag from a merge request](#removing-the-draft-flag-from-a-merge-request) +* [Including/excluding WIP merge requests when searching](#includingexcluding-wip-merge-requests-when-searching) + +# Draft merge requests[](#draft-merge-requests "Permalink") + +如果合并请求尚未准备好进行合并(可能是由于持续的开发或开放的线程),则可以通过将其标记为**Draft**来阻止在合并之前接受该合并请求. 这将禁用"合并"按钮,从而防止其被合并,并且在删除"草稿"标志之前它将保持禁用状态. + +[![Blocked Merge Button](img/284b72b1bfc8d5679fdaa384932b3b8c.png)](img/draft_blocked_merge_button_v13_2.png) + +## Adding the “Draft” flag to a merge request[](#adding-the-draft-flag-to-a-merge-request "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32692)的在进行中(WIP)合并请求已重命名为**Draft** . 在 GitLab 14.0 中将删除对使用**WIP 的**支持. + +There are several ways to flag a merge request as a Draft: + +* 将`[Draft]` , `Draft:`或`(Draft)`到合并请求标题的开头. 单击标题框下的" **以草稿开始标题:** ",在编辑合并请求的描述时将具有相同的效果. +* **不推荐使用**将`[WIP]`或`WIP:`添加到合并请求标题的开头. **WIP**仍然有效,但不赞成使用**Draft** . 它将在下一个主要版本(GitLab 14.0)中删除. +* 在合并请求的注释中添加`/wip` [快速操作](../quick_actions.html#quick-actions-for-issues-merge-requests-and-epics) . 这是一个切换,可以重复进行以将状态改回. 请注意,注释中的任何其他文本将被丢弃. +* 将`draft:`或`Draft:`添加到针对合并请求的源分支的提交消息的开头. 这不是切换,并且在另一次提交中再次执行将无效. + +## Removing the “Draft” flag from a merge request[](#removing-the-draft-flag-from-a-merge-request "Permalink") + +与上述类似,当准备合并请求时,可以通过以下几种方式删除" `Draft`标志: + +* 从合并请求标题的开头删除`[Draft]` , `Draft:`或`(Draft)` . 在编辑合并请求的描述时,在标题框下单击" **从标题中删除草稿:"前缀** ,将具有相同的效果. +* 在合并请求的注释中添加`/wip` [快速操作](../quick_actions.html#quick-actions-for-issues-merge-requests-and-epics) . 这是一个切换,可以重复进行以将状态改回. 请注意,注释中的任何其他文本将被丢弃. +* 点击靠近合并请求描述底部的**解决草案状态**按钮,旁边的**合并**按钮(见[上面的图片](#draft-merge-requests) ). 必须对该项目至少具有开发人员级别的权限,该按钮才可见. + +## Including/excluding WIP merge requests when searching[](#includingexcluding-wip-merge-requests-when-searching "Permalink") + +查看/搜索合并请求列表时,可以通过在搜索框中添加" WIP"过滤器,然后选择"是"(包括)或"否"(排除)来选择包括或排除 WIP 合并请求. + +[![Filter WIP MRs](img/fa591f90dc1e8840fe7fd692f24dcffe.png)](img/filter_wip_merge_requests.png) \ No newline at end of file diff --git a/docs/130.md b/docs/130.md new file mode 100644 index 0000000000000000000000000000000000000000..da43cee1c9e28178ca2bd77865ebec581bcabb58 --- /dev/null +++ b/docs/130.md @@ -0,0 +1,131 @@ +# Members of a project + +> 原文:[https://docs.gitlab.com/ee/user/project/members/](https://docs.gitlab.com/ee/user/project/members/) + +* [Inherited membership](#inherited-membership) +* [Add a user](#add-a-user) +* [Import users from another project](#import-users-from-another-project) +* [Invite people using their e-mail address](#invite-people-using-their-e-mail-address) +* [Project membership and requesting access](#project-membership-and-requesting-access) +* [Share project with group](#share-project-with-group) +* [Remove a member from the project](#remove-a-member-from-the-project) + +# Members of a project[](#members-of-a-project "Permalink") + +您可以在所有项目中管理组和用户及其访问级别. 您还可以个性化为每个项目赋予每个用户的访问级别. + +您应该具有维护者或所有者[权限,](../../permissions.html)才能将新用户添加或导入到项目中. + +要查看,编辑,添加和删除项目的成员,请转到项目的**成员** . + +## Inherited membership[](#inherited-membership "Permalink") + +当您的项目属于该组时,组成员将从该组继承该项目的成员资格和权限级别. + +[![Project members page](img/3f64ac42c5324a759f292fa0f7e4d991.png)](img/project_members.png) + +从上图可以得出以下几点: + +* 有 3 个成员可以访问该项目. +* User0 是记者,并且已从包含当前项目的组`demo`继承了他们的权限. +* 对于 User1,没有组的指示,因此它们直接属于我们正在检查的项目. +* 管理员是**所有**组的所有者和所有者,因此,有迹象表明祖先组和继承的所有者权限. + +[在 GitLab 12.6 中](https://gitlab.com/gitlab-org/gitlab/-/issues/21727) ,您可以使用右侧的下拉列表过滤此列表: + +[![Project members filter](img/4d5fab6dd3f65351ba798d87517db0bd.png)](img/project_members_filter_v12_6.png) + +* **仅显示直接成员**仅显示 User1. +* **仅显示继承的成员将**显示 User0 和 Administrator. + +## Add a user[](#add-a-user "Permalink") + +旁边的**人** ,开始输入要添加的用户的姓名或用户名. + +[![Search for people](img/5d98850d2ad30c43029645c8c0486059.png)](img/add_user_search_people.png) + +选择用户以及您要赋予该用户的[权限级别](../../permissions.html) . 请注意,您可以选择多个用户. + +[![Give user permissions](img/c736ba09ab7186102250ad9e624d79c1.png)](img/add_user_give_permissions.png) + +完成后,点击**将用户添加到项目中** ,这些**用户**将立即使用您在上面授予他们的权限添加到您的项目中. + +[![List members](img/a94b1f6b20cc665168a8d8359d195f78.png)](img/add_user_list_members.png) + +从那里开始,您可以删除现有用户或更改其对项目的访问级别. + +## Import users from another project[](#import-users-from-another-project "Permalink") + +您可以通过单击" **成员"**菜单右上角的" **导入成员"**按钮,将另一个项目的用户导入您自己的项目中. + +在下拉菜单中,您只能看到维护者所在的项目. + +[![Import members from another project](img/4c34240e5c09caa62a018e3d109c1ba3.png)](img/add_user_import_members_from_another_project.png) + +选择所需的一个,然后单击" **导入项目成员"** . 将会出现一条简短的消息,通知您导入已成功,并且新成员现在位于项目的成员列表中. 请注意,保留了他们对您从中导入的项目的权限. + +[![Members list of new members](img/f9a1ce8fe1042543bc2355950f642a05.png)](img/add_user_imported_members.png) + +## Invite people using their e-mail address[](#invite-people-using-their-e-mail-address "Permalink") + +如果要授予访问权限的用户在您的 GitLab 实例上没有帐户,则可以通过在用户搜索字段中键入其电子邮件地址来邀请他们. + +[![Invite user by mail](img/27d6bf9eb64fd8e4298e7a2a8ae64983.png)](img/add_user_email_search.png) + +可以想象,您可以混合邀请多个人并将现有的 GitLab 用户添加到项目中. + +[![Invite user by mail ready to submit](img/1fa927abbc0d78f64822dcc6c7295cd4.png)](img/add_user_email_ready.png) + +完成后,点击" **将用户添加到项目中",**然后观察到有一个新成员具有我们上面使用的电子邮件地址. 在此之后,您可以重新发送邀请,更改其访问级别,甚至删除它们. + +[![Invite user members list](img/878c3488cf7403499b80fcd402198e32.png)](img/add_user_email_accept.png) + +用户接受邀请后,将提示他们使用邀请发送到的相同电子邮件地址创建一个新的 GitLab 帐户. + +## Project membership and requesting access[](#project-membership-and-requesting-access "Permalink") + +项目所有者可以: + +* 允许非成员请求访问该项目. +* 防止非会员请求访问. + +要进行配置,请转到项目设置,然后单击**允许用户请求访问权限** . + +GitLab 用户可以请求成为项目成员. 转到您要加入的项目,然后单击屏幕右侧的" **请求访问**权"按钮. + +[![Request access button](img/1ff79a3af1496b3e864efbcf5f93307f.png)](img/request_access_button.png) + +请求访问后: + +* 通过电子邮件将最多十个项目维护者通知该请求. 电子邮件被发送给最近活跃的项目维护者. +* 任何项目维护者都可以在成员页面上批准或拒绝该请求. + +**注意:**如果项目没有任何维护者,则将通知发送给该项目组的最近活动的所有者. + +[![Manage access requests](img/083580c1827d40263d500a21f072249f.png)](img/access_requests_management.png) + +如果您在批准请求之前改变主意,只需单击" **撤回访问请求"**按钮. + +[![Withdraw access request button](img/dbb89cfb3c7539310a17d809c65c34a5.png)](img/withdraw_access_request_button.png) + +## Share project with group[](#share-project-with-group "Permalink") + +或者,您可以[与整个组共享一个项目,](share_project_with_groups.html)而不是一个一个地添加用户. + +## Remove a member from the project[](#remove-a-member-from-the-project "Permalink") + +只有[拥有所有者](../../permissions.html#group-members-permissions)权限的[用户](../../permissions.html#group-members-permissions)才能管理项目成员. + +如果给定成员在项目中具有直接成员资格,则可以从项目中删除用户. 如果成员资格是从父组继承的,则该成员只能从父组本身中删除. + +删除成员时,您可以决定是从所有问题中取消分配用户,还是合并当前已分配的请求,还是保留分配. + +* 当用户离开私有项目并且您希望撤消他们对所有问题和已分配的合并请求的访问时,从所有问题和合并请求中**取消分配已删除的成员**可能会有所帮助. +* **保留问题和合并请求的分配**可能对于接受公共贡献的项目很有帮助,在这些项目中,用户不必成为成员就可以为问题和合并请求做出贡献. + +To remove a member from a project: + +1. 在一个项目中,转到 **成员们** . +2. 点击**删除** 要删除的项目成员旁边的按钮. 出现" **删除成员"**模态. +3. (可选)选中" **也从相关问题中取消分配此用户并合并请求"**复选框. +4. Click **删除会员**. \ No newline at end of file diff --git a/docs/131.md b/docs/131.md new file mode 100644 index 0000000000000000000000000000000000000000..2bc50f1276e64767b6c10a4f926ff1730a044786 --- /dev/null +++ b/docs/131.md @@ -0,0 +1,62 @@ +# Migrating projects to a GitLab instance + +> 原文:[https://docs.gitlab.com/ee/user/project/import/](https://docs.gitlab.com/ee/user/project/import/) + +* [Migrating from self-managed GitLab to GitLab.com](#migrating-from-self-managed-gitlab-to-gitlabcom) +* [Migrating from GitLab.com to self-managed GitLab](#migrating-from-gitlabcom-to-self-managed-gitlab) +* [Migrating between two self-managed GitLab instances](#migrating-between-two-self-managed-gitlab-instances) + +# Migrating projects to a GitLab instance[](#migrating-projects-to-a-gitlab-instance "Permalink") + +1. [From Bitbucket Cloud](bitbucket.html) +2. [From Bitbucket Server (also known as Stash)](bitbucket_server.html) +3. [From ClearCase](clearcase.html) +4. [From CVS](cvs.html) +5. [From FogBugz](fogbugz.html) +6. [From GitHub.com or GitHub Enterprise](github.html) +7. [From GitLab.com](gitlab_com.html) +8. [From Gitea](gitea.html) +9. [From Perforce](perforce.html) +10. [From SVN](svn.html) +11. [From TFVC](tfvc.html) +12. [From repo by URL](repo_by_url.html) +13. [By uploading a manifest file (AOSP)](manifest.html) +14. [From Gemnasium](gemnasium.html) +15. [From Phabricator](phabricator.html) +16. [From Jira (issues only)](jira.html) + +除了上述特定的迁移文档之外,您还可以从 New Project 页面通过 HTTP 导入任何 Git 存储库. 请注意,如果存储库太大,则导入可能会超时. + +还可以选择[连接您的外部存储库以获得 CI / CD 好处](../../../ci/ci_cd_for_external_repos/index.html) . + +## Migrating from self-managed GitLab to GitLab.com[](#migrating-from-self-managed-gitlab-to-gitlabcom "Permalink") + +如果只需要迁移 Git 仓库,则可以[通过 URL 导入每个项目](repo_by_url.html) . 问题和合并请求无法导入. + +如果要保留所有元数据(例如问题和合并请求),则可以使用[导入/导出功能](../settings/import_export.html)从自我管理的 GitLab 导出项目,并将这些项目导入 GitLab.com. + +所有的 GitLab 用户关联(例如评论作者)都将更改为导入项目的用户. 有关更多信息,请参阅[导入说明](../settings/import_export.html#important-notes) . + +如果您需要迁移所有数据,则可以利用我们的[API](../../../api/README.html)从自我管理迁移到 GitLab.com. 从自我管理实例迁移到 GitLab.com 的资产顺序如下: + +**注意:**迁移到 GitLab.com 时,除非要使用[SCIM,](../../../user/group/saml_sso/scim_setup.html)否则需要手动创建用户. 使用 API​​创建用户仅限于自我管理的实例,因为它需要管理员访问权限. + +1. [Groups](../../../api/groups.html) +2. [Projects](../../../api/projects.html) +3. [Project variables](../../../api/project_level_variables.html) + +请记住[导入/导出功能](../settings/import_export.html#exported-contents)的局限性. + +您仍然需要通过一系列 Docker 推和推来迁移 Container Registry,并重新运行任何 CI 管道以检索任何构建工件. + +## Migrating from GitLab.com to self-managed GitLab[](#migrating-from-gitlabcom-to-self-managed-gitlab "Permalink") + +该过程与[从自我管理的 GitLab 迁移到 GitLab.com](#migrating-from-self-managed-gitlab-to-gitlabcom)的过程基本相同. 主要区别在于,管理员可以通过 UI 或[用户 API](../../../api/users.html#user-creation)在自助 GitLab 实例上创建[用户](../../../api/users.html#user-creation) . + +## Migrating between two self-managed GitLab instances[](#migrating-between-two-self-managed-gitlab-instances "Permalink") + +The best method for migrating from one GitLab instance to another, perhaps from an old server to a new server for example, is to [back up the instance](../../../raketasks/backup_restore.html), then restore it on the new server. + +如果将两个 GitLab 实例合并在一起(例如,两个实例上都有现有数据,并且不能擦除),请参阅[从自我管理的 GitLab 迁移到 GitLab.com 中的说明](#migrating-from-self-managed-gitlab-to-gitlabcom) . + +此外,您可以将用户[API](../../../api/users.html)与管理员用户一起使用来迁移用户. \ No newline at end of file diff --git a/docs/132.md b/docs/132.md new file mode 100644 index 0000000000000000000000000000000000000000..ca6a25b7e4fa7ba179b1d76e2e82693bb73f9dc3 --- /dev/null +++ b/docs/132.md @@ -0,0 +1,64 @@ +# Import your project from Bitbucket Cloud to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/bitbucket.html](https://docs.gitlab.com/ee/user/project/import/bitbucket.html) + +* [Overview](#overview) +* [Requirements](#requirements) +* [How it works](#how-it-works) +* [Import your Bitbucket repositories](#import-your-bitbucket-repositories) +* [Troubleshooting](#troubleshooting) + +# Import your project from Bitbucket Cloud to GitLab[](#import-your-project-from-bitbucket-cloud-to-gitlab "Permalink") + +**注意:** Bitbucket Cloud 导入程序仅适用于 Bitbucket.org,不适用于 Bitbucket Server(又名 Stash). 如果您尝试从 Bitbucket Server 导入项目,请使用[Bitbucket Server importer](bitbucket_server.html) . + +轻松地将项目从 Bitbucket Cloud 导入到 GitLab. + +## Overview[](#overview "Permalink") + +* 在当前状态下,Bitbucket 导入器可以导入: + * 仓库描述(GitLab 7.7+) + * Git 存储库数据(GitLab 7.7+) + * 问题(GitLab 7.7+) + * 问题评论(GitLab 8.15+) + * 拉取请求(GitLab 8.4+) + * 拉取请求注释(GitLab 8.15+) + * 里程碑(GitLab 8.15+) + * Wiki(GitLab 8.15+) +* 保留对拉取请求和问题的引用(GitLab 8.7+) +* 知识库公共访问权限保留. 如果存储库在 Bitbucket 中是私有的,则它也会在 GitLab 中也创建为私有的. + +## Requirements[](#requirements "Permalink") + +必须首先启用[Bitbucket Cloud 集成](../../../integration/bitbucket.html) ,以便能够从 Bitbucket Cloud 导入项目. 请您的 GitLab 管理员启用该功能(如果尚未启用). + +## How it works[](#how-it-works "Permalink") + +当导入问题/拉取请求时,Bitbucket 导入程序将尝试使用 Bitbucket `nickname`在 GitLab 的数据库中查找 Bitbucket 作者/受让人. 为此,Bitbucket 作者/受让人应事先在 GitLab 中登录并**关联其 Bitbucket 帐户** . 他们的`nickname`也必须与他们的 Bitbucket `username.`匹配`username.` . 如果在 GitLab 的数据库中找不到该用户,则将项目创建者(大多数情况下,当前用户已开始导入过程)设置为作者,但保留有关原始 Bitbucket 作者的问题的参考. + +如果不存在任何新的名称空间(组),或者如果采用了该名称空间,则导入器将创建任何新的名称空间(组),存储库将在启动导入过程的用户名称空间下导入. + +## Import your Bitbucket repositories[](#import-your-bitbucket-repositories "Permalink") + +1. Sign in to GitLab and go to your dashboard. +2. 单击**新建项目** . + +3. 点击" Bitbucket Cloud"按钮. + + [![Bitbucket](img/33da6433c882c8bcc4c699a4e0008b7c.png)](img/import_projects_from_new_project_page.png) + +4. 授予 GitLab 访问您的 Bitbucket 帐户的权限 + + [![Grant access](img/ea804dce7429c547bcf0703446150f59.png)](img/bitbucket_import_grant_access.png) + +5. 点击您要**导入的项目**或**导入所有项目** . 您还可以按名称过滤项目,并选择将在其下导入每个项目的名称空间. + + [![Import projects](img/01df5698e4465e052dcb7bf0ed6a55ae.png)](img/bitbucket_import_select_project_v12_3.png) + +## Troubleshooting[](#troubleshooting "Permalink") + +如果您拥有多个 Bitbucket 帐户,请确保登录正确的帐户. 如果您不小心以错误的帐户启动了导入过程,请按照以下步骤操作: + +1. 撤消对您的 Bitbucket 帐户的 GitLab 访问,实质上是通过以下过程来逆转该过程: [导入 Bitbucket 存储库](#import-your-bitbucket-repositories) . + +2. 退出 Bitbucket 帐户. 请遵循上一步中链接的过程. \ No newline at end of file diff --git a/docs/133.md b/docs/133.md new file mode 100644 index 0000000000000000000000000000000000000000..bb2ceec31706287740f3720587dd5a3410cf6ae4 --- /dev/null +++ b/docs/133.md @@ -0,0 +1,71 @@ +# Import your project from Bitbucket Server to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/bitbucket_server.html](https://docs.gitlab.com/ee/user/project/import/bitbucket_server.html) + +* [Overview](#overview) +* [Limitations](#limitations) +* [How it works](#how-it-works) + * [User assignment](#user-assignment) +* [Importing your Bitbucket repositories](#importing-your-bitbucket-repositories) +* [Troubleshooting](#troubleshooting) + +# Import your project from Bitbucket Server to GitLab[](#import-your-project-from-bitbucket-server-to-gitlab "Permalink") + +在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20164) . + +**注意:** Bitbucket Server 导入程序不适用于[Bitbucket Cloud](https://bitbucket.org) . 为此,请使用[Bitbucket Cloud 导入](bitbucket.html)程序. + +轻松地将项目从 Bitbucket Server 导入到 GitLab. + +## Overview[](#overview "Permalink") + +* 在当前状态下,Bitbucket 导入器可以导入: + * 仓库描述(GitLab 11.2+) + * Git 存储库数据(GitLab 11.2+) + * 拉取请求(GitLab 11.2+) + * 拉取请求注释(GitLab 11.2+) +* 知识库公共访问权限保留. 如果存储库在 Bitbucket 中是私有的,则它也会在 GitLab 中也创建为私有的. + +## Limitations[](#limitations "Permalink") + +1. 目前,GitLab 不允许在任意代码行上添加注释,因此任何超出范围的 Bitbucket 注释都将作为注释插入到合并请求中. +2. Bitbucket Server 允许多个级别的线程. GitLab 导入会将其折叠到一个线程中,并引用原始注释的一部分. +3. 拒绝的拉取请求具有无法到达的提交,这会阻止 GitLab 导入器生成适当的差异. 这些拉取请求将显示为空更改. +4. Markdown 中的附件当前未导入. +5. 任务列表未导入. +6. 表情符号反应未导入 +7. 项目过滤不支持模糊搜索(当前仅支持`starts with`或`full match strings` ) + +## How it works[](#how-it-works "Permalink") + +Bitbucket 服务器导入程序的工作方式如下: + +1. 系统将提示用户输入 URL,用户名和密码(或个人访问令牌)以登录到 Bitbucket. 这些凭据仅在导入程序运行时才保留. +2. 导入程序将尝试列出 Bitbucket 服务器上的所有当前存储库. +3. 选择后,导入程序将克隆存储库并导入拉取请求和注释. + +### User assignment[](#user-assignment "Permalink") + +当导入问题/拉取请求时,Bitbucket 导入器将尝试在 GitLab 用户数据库中查找作者的电子邮件地址以及已确认的电子邮件地址. 如果没有这样的用户可用,则将项目创建者设置为作者. 进口商将在注释中添加注释以标记原始创建者. + +如果不存在任何新的名称空间(组),或者如果采用了该名称空间,则导入器将创建任何新的名称空间(组),存储库将在启动导入过程的用户名称空间下导入. + +## Importing your Bitbucket repositories[](#importing-your-bitbucket-repositories "Permalink") + +1. 登录到 GitLab 并转到您的仪表板. +2. 单击**新建项目** . +3. 点击" Bitbucket 服务器"按钮. 如果该按钮不存在,请在**管理>应用程序设置>可见性和访问控制>导入源中**启用**导入器** . + + [![Bitbucket](img/33da6433c882c8bcc4c699a4e0008b7c.png)](img/import_projects_from_new_project_page.png) + +4. 输入您的 Bitbucket 服务器凭据. + + [![Grant access](img/cca5497f42d0f0512126392deb81fa3e.png)](img/bitbucket_server_import_credentials.png) + +5. 点击您要**导入的项目**或**导入所有项目** . 您还可以按名称过滤项目,并选择将在其下导入每个项目的名称空间. + + [![Import projects](img/c43432893b48081561609f3667b7d497.png)](img/bitbucket_server_import_select_project_v12_3.png) + +## Troubleshooting[](#troubleshooting "Permalink") + +请参阅[Bitbucket](bitbucket.html)的[故障排除](bitbucket.html#troubleshooting)部分. \ No newline at end of file diff --git a/docs/134.md b/docs/134.md new file mode 100644 index 0000000000000000000000000000000000000000..5dfc6f0eab9a1bce8402f5a5c1b8eccdff1b4dd4 --- /dev/null +++ b/docs/134.md @@ -0,0 +1,46 @@ +# Migrating from ClearCase + +> 原文:[https://docs.gitlab.com/ee/user/project/import/clearcase.html](https://docs.gitlab.com/ee/user/project/import/clearcase.html) + +* [Why migrate](#why-migrate) +* [How to migrate](#how-to-migrate) + +# Migrating from ClearCase[](#migrating-from-clearcase "Permalink") + +[ClearCase](https://www.ibm.com/us-en/marketplace/rational-clearcase)是 IBM 开发的一组工具,还包括类似于 Git 的集中式版本控制系统. + +可以在此[StackOverflow 帖子中](https://stackoverflow.com/a/645771/974710)找到有关 ClearCase 基本概念的良好阅读. + +下表说明了 ClearCase 和 Git 之间的主要区别: + +| Aspect | ClearCase | Git | +| --- | --- | --- | +| 仓库模型 | Client-server | Distributed | +| 修订版 ID | 分行号 | 全局字母数字 ID | +| 变更范围 | File | 目录树快照 | +| 并发模型 | Merge | Merge | +| 储存方式 | Deltas | 全部内容 | +| Client | CLI,Eclipse,CC 客户端 | CLI,Eclipse,Git 客户端/ GUI | +| Server | UNIX,Windows 旧式系统 | UNIX,macOS | +| License | Proprietary | GPL | + +*选自 ClearClase 幻灯片[和](https://www.open.collab.net/media/pdfs/ClearCase-and-the-journey-to-Git.pdf) collab.net 提供的[Git 之旅](https://www.open.collab.net/media/pdfs/ClearCase-and-the-journey-to-Git.pdf)* + +## Why migrate[](#why-migrate "Permalink") + +从用户和管理员的角度来看,ClearCase 都可能难以管理. 迁移到 Git / GitLab 有: + +* **没有许可费用** ,Git 是 GPL,而 ClearCase 是专有的. +* **学习曲线更短** ,Git 有一个庞大的社区和大量的入门指南. +* **与现代工具集成** ,迁移到 Git 和 GitLab,您可以拥有一个开源的端到端软件开发平台,该平台具有内置的版本控制,问题跟踪,代码审查,CI / CD 等. + +## How to migrate[](#how-to-migrate "Permalink") + +虽然不存在从 ClearCase 完全迁移到 Git 的工具,但是这里有一些有用的链接可以帮助您入门: + +* [Bridge for Git and ClearCase](https://github.com/charleso/git-cc) +* [Slides “ClearCase and the journey to Git”](https://www.open.collab.net/media/pdfs/ClearCase-and-the-journey-to-Git.pdf) +* [ClearCase to Git](https://therub.org/2013/07/19/clearcase-to-git/) +* [Dual syncing ClearCase to Git](https://therub.org/2013/10/22/dual-syncing-clearcase-and-git/) +* [Moving to Git from ClearCase](https://sateeshkumarb.wordpress.com/2011/01/15/moving-to-git-from-clearcase/) +* [ClearCase to Git webinar](https://www.brighttalk.com/webcast/11817/162473/clearcase-to-git) \ No newline at end of file diff --git a/docs/135.md b/docs/135.md new file mode 100644 index 0000000000000000000000000000000000000000..bed5388f0015a2d74d0616b4ce6b95bd0b6cbf54 --- /dev/null +++ b/docs/135.md @@ -0,0 +1,41 @@ +# Migrating from CVS + +> 原文:[https://docs.gitlab.com/ee/user/project/import/cvs.html](https://docs.gitlab.com/ee/user/project/import/cvs.html) + +* [CVS vs Git](#cvs-vs-git) +* [Why migrate](#why-migrate) +* [How to migrate](#how-to-migrate) + +# Migrating from CVS[](#migrating-from-cvs "Permalink") + +[CVS](https://savannah.nongnu.org/projects/cvs)是类似于[SVN](svn.html)的旧式集中版本控制系统. + +## CVS vs Git[](#cvs-vs-git "Permalink") + +以下列表说明了 CVS 和 Git 之间的主要区别: + +* **Git 已分发.** 另一方面,CVS 使用客户端-服务器体系结构进行集中管理. 这意味着 Git 具有更灵活的工作流程,因为您的工作区是整个存储库的副本. 例如,由于不必与远程服务器进行通信,因此这减少了切换分支或合并时的开销. +* **原子操作.** 在 Git 中,所有操作都是[原子](https://en.wikipedia.org/wiki/Atomic_commit)操作,它们要么全部成功,要么失败而没有任何更改. 在 CVS 中,提交(和其他操作)不是原子的. 如果对存储库的操作在中间中断,则存储库可能处于不一致状态. +* **存放方法.** CVS 中的更改是按文件(更改集)进行的,而在 Git 中,已提交的文件将全部存储(快照). 这意味着在 Git 中还原或撤消整个更改非常容易. +* **修订版 ID.** 在 CVS 中,更改是针对每个文件的,修订 ID 由版本号表示,例如`1.4`反映了给定文件已更改了多少次. 在 Git 中,整个项目的每个版本(每次提交)的唯一名称都由 SHA-1 给出. +* **合并跟踪.** Git 使用一种先合并后提交的方法,而不是像 CVS 那样先合并后提交(或先更新再提交). 如果在准备创建新提交(新修订版)时有人在同一个分支上创建了一个新提交并推送到中央存储库,则 CVS 将强制您首先更新工作目录并解决冲突,然后再允许您提交. Git 并非如此. 您首先提交,将状态保存在版本控制中,然后合并其他开发人员的更改. 您还可以要求其他开发人员进行合并并自己解决任何冲突. +* **签名提交.** Git 支持使用 GPG 对提交进行签名,以提高安全性并验证提交确实来自其原始作者. GitLab 可以[与 GPG 集成,](../repository/gpg_signed_commits/index.html)并显示签名提交是否得到正确验证. + +*上面的一些内容摘自这个很棒的[Stack Overflow 帖子](https://stackoverflow.com/a/824241/974710) . 有关差异的更完整列表,请查阅 Wikipedia 上有关[比较不同版本控制软件的文章](https://en.wikipedia.org/wiki/Comparison_of_version_control_software) .* + +## Why migrate[](#why-migrate "Permalink") + +CVS 较旧,自 2008 年以来没有新版本发布.Git 提供了更多可使用的工具( `git bisect`之一),这使工作流程更加高效. 迁移到 Git / GitLab 有: + +* **学习曲线更短** ,Git 具有庞大的社区和大量的入门指南(请参阅我们的[Git 主题](../../../topics/git/index.html) ). +* **与现代工具集成** ,迁移到 Git 和 GitLab,您可以拥有一个开源的端到端软件开发平台,该平台具有内置的版本控制,问题跟踪,代码审查,CI / CD 等. +* **支持许多网络协议** . Git 支持 SSH,HTTP / HTTPS 和 rsync 等,而 CVS 仅支持 SSH 及其自身的不安全的 pserver 协议,无需用户身份验证. + +## How to migrate[](#how-to-migrate "Permalink") + +以下是一些链接,可帮助您开始进行迁移: + +* [Migrate using the `cvs-fast-export` tool](http://www.catb.org/~esr/reposurgeon/dvcs-migration-guide.html) ([*source code*](https://gitlab.com/esr/cvs-fast-export)) +* [Stack Overflow post on importing the CVS repo](https://stackoverflow.com/a/11490134/974710) +* [Convert a CVS repository to Git](https://www.techrepublic.com/blog/linux-and-open-source/convert-cvs-repositories-to-git/) +* [Man page of the `git-cvsimport` tool](https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-cvsimport.html) \ No newline at end of file diff --git a/docs/136.md b/docs/136.md new file mode 100644 index 0000000000000000000000000000000000000000..c4eb1168aa178c67521d3fbb4acac09fee11a0a7 --- /dev/null +++ b/docs/136.md @@ -0,0 +1,28 @@ +# Import your project from FogBugz to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/fogbugz.html](https://docs.gitlab.com/ee/user/project/import/fogbugz.html) + +# Import your project from FogBugz to GitLab[](#import-your-project-from-fogbugz-to-gitlab "Permalink") + +从 FogBugz 导入项目只需几个简单的步骤. 导入程序将导入您的所有案例和注释以及原始案例编号和时间戳. 您还将有机会将 FogBugz 用户映射到 GitLab 用户. + +1. 在您的 GitLab 仪表板中,单击"新建项目" +2. 点击" FogBugz"按钮 + +[![FogBugz](img/191e4984d9e1aa615a86fec2b6d42dcd.png)](img/fogbugz_import_select_fogbogz.png) + +1. 输入您的 FogBugz URL,电子邮件地址和密码. + +[![Login](img/2b49f82a2ff96781b55685367813e6c9.png)](img/fogbugz_import_login.png) + +1. 创建从 FogBugz 用户到 GitLab 用户的映射. + +[![User Map](img/e71e8b254fc758ab1a18ac4373e14344.png)](img/fogbugz_import_user_map.png) + +1. 通过单击导入按钮选择要导入的项目 + +[![Import Project](img/d677bbf1d2f77fd7394cddab976e6f67.png)](img/fogbugz_import_select_project.png) + +1. 导入完成后,单击链接将您带到项目仪表板. 按照说明推送现有存储库. + +[![Finished](img/1b984d904256e7a325a4cc30bcf71ee1.png)](img/fogbugz_import_finished.png) \ No newline at end of file diff --git a/docs/137.md b/docs/137.md new file mode 100644 index 0000000000000000000000000000000000000000..4672b9c3c4c8e0a664e58c22c747a368c51233f3 --- /dev/null +++ b/docs/137.md @@ -0,0 +1,84 @@ +# Gemnasium + +> 原文:[https://docs.gitlab.com/ee/user/project/import/gemnasium.html](https://docs.gitlab.com/ee/user/project/import/gemnasium.html) + +* [Why is Gemnasium.com closed?](#why-is-gemnasiumcom-closed) +* [What happened to my account?](#what-happened-to-my-account) +* [Will my account/data be transferred to GitLab Inc.?](#will-my-accountdata-be-transferred-to-gitlab-inc) +* [What happened to my badge?](#what-happened-to-my-badge) +* [Migrating to GitLab](#migrating-to-gitlab) + * [If your project is hosted on GitLab (`https://gitlab.com` / self-managed)](#if-your-project-is-hosted-on-gitlab-httpsgitlabcom--self-managed) + * [If your project is hosted on GitHub (`https://github.com` / GitHub Enterprise)](#if-your-project-is-hosted-on-github-httpsgithubcom--github-enterprise) + +# Gemnasium[](#gemnasium-ultimate "Permalink") + +本指南介绍了如何从 Gemnasium.com 迁移到您自己的 GitLab 实例或 GitLab.com. + +## Why is Gemnasium.com closed?[](#why-is-gemnasiumcom-closed "Permalink") + +Gemnasium 在 2018 年 1 月[被 GitLab 收购](https://about.gitlab.com/press/releases/2018-01-30-gemnasium-acquisition.html) .自 2018 年 5 月 15 日起,Gemnasium 提供的服务不再可用. Gemnasium 背后的团队已加入 GitLab,成为新的安全产品团队,并且正在开发[各种工具](../../application_security/index.html) ,包括: + +* [Dependency Scanning](../../application_security/dependency_scanning/index.html) +* [SAST](../../application_security/sast/index.html) +* [DAST](../../application_security/dast/index.html) +* [Container Scanning](../../application_security/container_scanning/index.html) + +如果要继续监视依赖项,请参见下面的" [迁移到 GitLab"](#migrating-to-gitlab)部分. + +## What happened to my account?[](#what-happened-to-my-account "Permalink") + +您的帐户已于 2018 年 5 月 15 日自动关闭.如果您当时有付费订阅,则您的卡将按比例退还. 您可以联系`gemnasium@gitlab.com`了解您的已关闭帐户. + +## Will my account/data be transferred to GitLab Inc.?[](#will-my-accountdata-be-transferred-to-gitlab-inc "Permalink") + +所有帐户和数据已于 2018 年 5 月 15 日被删除.GitLab Inc.对您的私人数据或项目一无所知,因此不知道它们是否容易受到攻击. GitLab Inc.非常重视个人信息. + +## What happened to my badge?[](#what-happened-to-my-badge "Permalink") + +为避免损坏的 404 图像,所有指向 Gemnasium.com 的徽章都将用作占位符,邀请您迁移到 GitLab(并指向此页面). + +## Migrating to GitLab[](#migrating-to-gitlab "Permalink") + +Gemnasium 已被移植并直接集成到 GitLab CI / CD 中. 您仍然可以从我们的依赖项监视功能中受益,并且需要一些步骤来迁移项目. 由于 GitLab 对 Gemnasium.com 上存在的任何项目一无所知,因此没有自动导入. GitLab.com 上托管的公共(开源)项目免费提供安全功能. + +### If your project is hosted on GitLab (`https://gitlab.com` / self-managed)[](#if-your-project-is-hosted-on-gitlab-httpsgitlabcom--self-managed "Permalink") + +您快要准备好了! 如果您已经在使用[Auto DevOps](../../../topics/autodevops/) ,那么您已经了解了. 否则,您必须根据[依赖项扫描页面](../../application_security/dependency_scanning/index.html)配置`.gitlab-ci.yml` . + +### If your project is hosted on GitHub (`https://github.com` / GitHub Enterprise)[](#if-your-project-is-hosted-on-github-httpsgithubcom--github-enterprise "Permalink") + +由于[GitLab 10.6 带有 GitHub 集成](https://about.gitlab.com/solutions/github/) ,因此 GitLab 用户现在可以在 GitLab 中创建一个 CI / CD 项目,该项目连接到外部 GitHub.com 或 GitHub Enterprise 仓库. 每当将代码推送到 GitHub 时,这都会自动提示 GitLab CI / CD 运行,并在完成后将 CI / CD 结果发布回 GitLab 和 GitHub. + +1. 创建一个新项目,然后选择"用于外部仓库的 CI / CD"选项卡: + + [![Create new Project](img/e3489f723615b369a1abec41ebe9dea2.png)](img/gemnasium/create_project.png) + +2. 使用" GitHub"按钮连接存储库. + + [![Connect from GitHub](img/7ebc386f852ada24782fd3b7e5dd226e.png)](img/gemnasium/connect_github.png) + +3. 选择要使用 GitLab CI / CD 设置的项目,然后选择"连接". + + [![Select projects](img/611650a65dd2baf63b32d99fbe8e4a8a.png)](img/gemnasium/select_project.png) + + 配置完成后,您可以在 GitLab 上单击新项目. + + [![click on connected project](img/35b66299a79c8b3212bf8fbb00e9c903.png)](img/gemnasium/project_connected.png) + + 现在,您的项目已镜像到 GitLab,Runners 可以在其中访问您的源代码并运行您的测试. + + 可选步骤:如果您在 GitHub 项目是公共的,则在 GitLab.com 上进行设置,请确保该项目是公共的(在项目设置中),因为该安全功能仅适用于[GitLab Ultimate](https://about.gitlab.com/pricing/) . + +4. 要设置与 Gemnasium 所做的工作相对应的依赖项扫描作业,您必须创建`.gitlab-ci.yml`文件,或根据[依赖项扫描文档](../../application_security/dependency_scanning/index.html)对其进行更新. 默认情况下,镜像是仅拉式的,因此您可以在 GitHub 上创建或更新文件: + + [![Edit gitlab-ci.yml file](img/6427e1b107996a8eb9c401e1aa76bf87.png)](img/gemnasium/edit_gitlab-ci.png) + +5. 提交文件后,如果文件有效,将自动触发新的管道: + + [![pipeline](img/97acbf99c97921ca9e5837c4c70cfa4c.png)](img/gemnasium/pipeline.png) + +6. 作业的结果将直接在管道视图中可见: + + [![Security Dashboard](img/f0d8585fb8235b36b1464ed1d142a4c0.png)](../../application_security/security_dashboard/img/pipeline_security_dashboard_v13_2.png) + +**注意:**如果您不经常提交项目,则可能要使用[计划的管道](../../../ci/pipelines/schedules.html)定期运行作业. \ No newline at end of file diff --git a/docs/138.md b/docs/138.md new file mode 100644 index 0000000000000000000000000000000000000000..7e9b8c9ff825808e950a32335b78a56c64ef731c --- /dev/null +++ b/docs/138.md @@ -0,0 +1,119 @@ +# Import your project from GitHub to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/github.html](https://docs.gitlab.com/ee/user/project/import/github.html) + +* [Overview](#overview) +* [How it works](#how-it-works) +* [Import your GitHub repository into GitLab](#import-your-github-repository-into-gitlab) + * [Using the GitHub integration](#using-the-github-integration) + * [Using a GitHub token](#using-a-github-token) + * [Selecting which repositories to import](#selecting-which-repositories-to-import) +* [Mirroring and pipeline status sharing](#mirroring-and-pipeline-status-sharing) +* [Improving the speed of imports on self-managed instances](#improving-the-speed-of-imports-on-self-managed-instances) + +# Import your project from GitHub to GitLab[](#import-your-project-from-github-to-gitlab "Permalink") + +使用导入器,您可以将 GitHub 存储库导入 GitLab.com 或自管理的 GitLab 实例. + +## Overview[](#overview "Permalink") + +**注意:**这些说明适用于 GitLab.com 上的用户,但是如果您是自助 GitLab 实例的管理员,或者要从 GitHub Enterprise 导入,则必须启用[GitHub 集成](../../../integration/github.html) . GitHub 集成是从 GitHub Enterprise 导入的唯一方法. 如果您使用的是 GitLab.com,则可以使用[个人访问令牌](#using-a-github-token)导入 GitHub 存储库,但不建议使用此方法,因为该方法无法将所有用户活动(例如问题和请求请求)与匹配的 GitLab 用户相关联. 如果您是自我管理的 GitLab 实例的管理员,则还可以使用[GitHub Rake 任务](../../../administration/raketasks/github_import.html)从 GitHub 导入项目,而不受 Sidekiq worker 的限制. + +导入了项目的以下方面: + +* 仓库描述(GitLab.com&7.7+) +* Git 存储库数据(GitLab.com&7.7+) +* 问题(GitLab.com 和 7.7+) +* 拉取请求(GitLab.com&8.4+) +* Wiki 页面(GitLab.com&8.4+) +* 里程碑(GitLab.com&8.7+) +* 标签(GitLab.com 和 8.7+) +* 发行说明说明(GitLab.com 和 8.12+) +* 拉取请求评论评论(GitLab.com&10.2+) +* 定期发布和请求请求注释 + +保留对拉取请求和问题的引用(GitLab.com&8.7+),并且每个导入的存储库都保持可见性级别,除非该[可见性级别受到限制](../../../public_access/public_access.html#restricting-the-use-of-public-or-internal-projects) ,在这种情况下,它默认为默认项目可见性. + +## How it works[](#how-it-works "Permalink") + +导入问题和请求请求时,导入程序会尝试在 GitLab 实例的数据库中查找其 GitHub 作者和受让人(请注意,请求请求在 GitLab 中称为"合并请求"). + +For this association to succeed, each GitHub author and assignee in the repository must meet one of the following conditions prior to the import: + +* 以前使用 GitHub 图标登录到 GitLab 帐户. +* 有一个 GitHub 帐户,其[主要电子邮件地址](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/setting-your-commit-email-address)与其 GitLab 帐户的电子邮件地址匹配. + +如果在 GitLab 的数据库中未找到项目中引用的用户,则将项目创建者(通常是启动导入过程的用户)设置为作者/受让人,但是会添加关于该问题的注释,其中提及原始 GitHub 作者. + +如果不存在任何新的名称空间(组),或者如果采用了名称空间,则导入器会创建存储库,该存储库将在启动导入过程的用户的名称空间下导入. 命名空间/存储库名称也可以使用适当的权限进行编辑. + +进口商还将在与未完成拉取请求相关的项目的分支上导入分支. 这些分支将以类似于`GH-SHA-username/pull-request-number/fork-name/branch`的命名方案导入. 与 GitHub 存储库相比,这可能导致分支中的差异. + +有关更多技术细节,您可以参考[GitHub Importer](../../../development/github_importer.html "使用 GitHub 导入器")开发人员文档. + +有关导入过程的概述,请参阅[从 GitHub 迁移到 GitLab](https://youtu.be/VYOXuOg9tQI)的视频. + +## Import your GitHub repository into GitLab[](#import-your-github-repository-into-gitlab "Permalink") + +### Using the GitHub integration[](#using-the-github-integration "Permalink") + +在开始之前,请确保要映射到 GitLab 用户的所有 GitHub 用户都具有以下任一条件: + +* 使用 GitHub 图标登录的 GitLab 帐户-或- +* 一个 GitLab 帐户,其电子邮件地址与 GitHub 用户的[公共电子邮件地址](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/setting-your-commit-email-address)匹配 + +用户匹配尝试将按该顺序进行,并且如果两种方法均未识别到用户,则该活动将与执行导入的用户帐户相关联. + +**注意:**如果您使用的是自助式 GitLab 实例,或者要从 GitHub Enterprise 导入,则此过程要求您已配置[GitHub 集成](../../../integration/github.html) . + +1. 在顶部导航栏中,单击**+** ,然后选择**新建项目** . +2. 选择**导入项目**选项卡,然后选择**GitHub** . +3. 选择第一个按钮以**列出您的 GitHub 存储库** . 您将被重定向到[GitHub 上](https://github.com)的页面以授权 GitLab 应用程序. +4. 点击**授权 gitlabhq** . 您将被重定向回 GitLab 的 Import 页面,并列出所有 GitHub 存储库. +5. 继续[选择要导入的存储库](#selecting-which-repositories-to-import) . + +### Using a GitHub token[](#using-a-github-token "Permalink") + +**注意:**不建议使用个人访问令牌导入项目. 如果您是 GitLab.com 用户,则可以使用个人访问令牌从 GitHub 导入项目,但是该方法无法将所有用户活动(例如问题和请求请求)与匹配的 GitLab 用户关联. 如果您是自我管理的 GitLab 实例的管理员,或者要从 GitHub Enterprise 导入,则不能使用个人访问令牌. 建议所有用户使用[GitHub 集成方法(上述)](#using-the-github-integration) . 在" [如何工作"](#how-it-works)部分中了解更多信息. + +如果您不使用 GitHub 集成,则仍可以通过 GitHub 执行授权以授予 GitLab 访问您的存储库的权限: + +1. 转到[https://github.com/settings/tokens/new](https://github.com/settings/tokens/new) +2. 输入令牌描述. +3. 选择回购范围​​. +4. Click **生成令牌**. +5. 复制令牌哈希. +6. 返回到 GitLab 并将令牌提供给 GitHub 导入器. +7. 点击**列出您的 GitHub 存储库**按钮,并等待 GitLab 读取您的存储库信息. 完成后,将带您到导入器页面以选择要导入的存储库. + +### Selecting which repositories to import[](#selecting-which-repositories-to-import "Permalink") + +在授权访问 GitHub 存储库后,您将重定向到 GitHub 导入程序页面,并列出 GitHub 存储库. + +1. 默认情况下,建议的存储库名称空间与 GitHub 中存在的名称匹配,但是根据您的权限,您可以选择在继续导入任何名称之前编辑这些名称. +2. 选择任意数量的存储库旁边的**导入**按钮,或选择**导入所有存储库** . 此外,您可以按名称过滤项目. 如果应用了过滤器,则" **导入所有存储库"**仅导入匹配的存储库. +3. " **状态"**列显示每个存储库的导入状态. 您可以选择让页面保持打开状态,它将实时更新,也可以稍后返回. +4. 导入存储库后,单击其 GitLab 路径以打开其 GitLab URL. + +[![Github importer page](img/67f7d8117f3d6bf60fe4d5e03bca7b6e.png)](img/import_projects_from_github_importer_v12_3.png) + +## Mirroring and pipeline status sharing[](#mirroring-and-pipeline-status-sharing "Permalink") + +根据您的 GitLab 层,可以设置[项目镜像](../repository/repository_mirroring.html) ,以使导入的项目与其 GitHub 副本保持同步. + +此外,您可以配置 GitLab 以通过[GitHub Project Integration](../integrations/github.html)将管道状态更新发送回 GitHub. + +如果使用[CI / CD 作为外部存储库](../../../ci/ci_cd_for_external_repos/index.html)导入项目,则会自动配置以上两项. + +## Improving the speed of imports on self-managed instances[](#improving-the-speed-of-imports-on-self-managed-instances "Permalink") + +**注意:**必须具有对 GitLab 服务器的管理员访问权限. + +对于大型项目,可能需要一段时间才能导入所有数据. 为了减少必要的时间,您可以增加处理以下队列的 Sidekiq 工作程序的数量: + +* `github_importer` +* `github_importer_advance_stage` + +For an optimal experience, it’s recommended having at least 4 Sidekiq processes (each running a number of threads equal to the number of CPU cores) that *only* process these queues. It’s also recommended that these processes run on separate servers. For 4 servers with 8 cores this means you can import up to 32 objects (e.g., issues) in parallel. + +减少克隆存储库所花费的时间可以通过增加存储 Git 存储库(适用于您的 GitLab 实例)的磁盘的网络吞吐量,CPU 容量和磁盘性能(例如,使用高性能 SSD)来完成. 增加 Sidekiq 工作人员的数量*不会*减少克隆存储库所花费的时间. \ No newline at end of file diff --git a/docs/139.md b/docs/139.md new file mode 100644 index 0000000000000000000000000000000000000000..0d1bdbae5d497f853f5aec8b491459f05ac3042a --- /dev/null +++ b/docs/139.md @@ -0,0 +1,19 @@ +# Project importing from GitLab.com to your private GitLab instance + +> 原文:[https://docs.gitlab.com/ee/user/project/import/gitlab_com.html](https://docs.gitlab.com/ee/user/project/import/gitlab_com.html) + +# Project importing from GitLab.com to your private GitLab instance[](#project-importing-from-gitlabcom-to-your-private-gitlab-instance "Permalink") + +您可以将现有的 GitLab.com 项目导入到 GitLab 实例中,但请记住,只有在 GitLab 实例上启用了 GitLab.com 集成后,才有可能. [阅读有关 GitLab.com 集成的更多信息,以实现自我管理的 GitLab 实例](../../../integration/gitlab.html) . + +要进入进口商页面,您需要进入"新项目"页面. + +> **注意:**如果您有兴趣将 Wiki 和合并请求数据导入到新实例,则需要按照说明[导出项目](../settings/import_export.html#exporting-a-project-and-its-data) + +[![New project page](img/0d0a16295f0edf554f921ffda49ff421.png)](img/gitlab_new_project_page_v12_2.png) + +转到" **导入项目"**选项卡,然后单击**GitLab.com** ,您将被重定向到 GitLab.com 以获取访问项目的权限. 接受后,您将自动重定向到导入程序. + +[![Importer page](img/e0fb1b28f653637edd64e072798f2385.png)](img/gitlab_importer.png) + +要导入项目,请单击"导入". 导入程序将导入您的存储库和问题. 导入器完成后,将使用导入的数据创建一个新的 GitLab 项目. \ No newline at end of file diff --git a/docs/140.md b/docs/140.md new file mode 100644 index 0000000000000000000000000000000000000000..d5f9fda63ad4d36d57cdaf8d9d6cb08e58c1ba7d --- /dev/null +++ b/docs/140.md @@ -0,0 +1,73 @@ +# Import your project from Gitea to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/gitea.html](https://docs.gitlab.com/ee/user/project/import/gitea.html) + +* [Overview](#overview) +* [How it works](#how-it-works) +* [Importing your Gitea repositories](#importing-your-gitea-repositories) + * [Authorize access to your repositories using a personal access token](#authorize-access-to-your-repositories-using-a-personal-access-token) + * [Select which repositories to import](#select-which-repositories-to-import) + +# Import your project from Gitea to GitLab[](#import-your-project-from-gitea-to-gitlab "Permalink") + +Import your projects from Gitea to GitLab with minimal effort. + +## Overview[](#overview "Permalink") + +> **注意:**这需要 Gitea `v1.0.0`或更高版本. + +* 在当前状态下,Gitea 进口商可以进口: + * 仓库描述(GitLab 8.15+) + * Git 存储库数据(GitLab 8.15+) + * 问题(GitLab 8.15+) + * 拉取请求(GitLab 8.15+) + * 里程碑(GitLab 8.15+) + * 标签(GitLab 8.15+) +* 知识库公共访问权限保留. 如果存储库在 Gitea 中是私有的,则它也将在 GitLab 中创建为私有的. + +## How it works[](#how-it-works "Permalink") + +由于 Gitea 当前不是 OAuth 提供者,因此无法将作者/受让人映射到您的 GitLab 实例中的用户. 这意味着将项目创建者(大多数情况下是当前开始导入过程的当前用户)设置为作者,但是保留了有关原始 Gitea 作者的问题的参考. + +如果不存在任何新的名称空间(组),或者如果采用了该名称空间,则导入器将创建任何新的名称空间(组),存储库将在启动导入过程的用户名称空间下导入. + +## Importing your Gitea repositories[](#importing-your-gitea-repositories "Permalink") + +创建新项目时,将显示导入器页面. + +[![New project page on GitLab](img/33da6433c882c8bcc4c699a4e0008b7c.png)](img/import_projects_from_new_project_page.png) + +单击**Gitea**链接,导入授权过程将开始. + +[![New Gitea project import](img/23b032de89e1f1056b75bd7ad55823ea.png)](img/import_projects_from_gitea_new_import.png) + +### Authorize access to your repositories using a personal access token[](#authorize-access-to-your-repositories-using-a-personal-access-token "Permalink") + +使用这种方法,您将对 Gitea 执行一次性授权,以授权 GitLab 访问您的存储库: + +1. 转到`https://your-gitea-instance/user/settings/applications` (将`your-gitea-instance`替换`your-gitea-instance`的主机). +2. Click **生成新令牌**. +3. 输入令牌描述. +4. Click **生成令牌**. +5. 复制令牌哈希. +6. 返回到 GitLab 并将令牌提供给 Gitea 进口商. +7. 点击**列出您的 Gitea 存储库**按钮,然后等待 GitLab 读取您的存储库信息. 完成后,将带您到导入器页面以选择要导入的存储库. + +### Select which repositories to import[](#select-which-repositories-to-import "Permalink") + +在授权访问 Gitea 存储库后,您将被重定向到 Gitea 导入程序页面. + +从那里,您可以查看 Gitea 存储库的导入状态. + +* 那些正在导入的将显示*开始*状态, +* 那些已经成功导入的将变成绿色,状态为" *完成"* , +* 而尚未导入的表格将在表格的右侧具有" **导入"**按钮. + +您还可以: + +* 点击左上角的" **导入所有项目"** ,一次性导入所有 Gitea 项目. +* 按名称过滤项目. 如果应用了过滤器,则点击**导入所有项目**将仅导入匹配的项目 + +[![Gitea importer page](img/2c8994d4c86769ec5151192ff555b261.png)](img/import_projects_from_gitea_importer_v12_3.png) + +如果您有特权,也可以为项目选择其他名称和名称空间. \ No newline at end of file diff --git a/docs/141.md b/docs/141.md new file mode 100644 index 0000000000000000000000000000000000000000..8509befa96a43bc2cbcb606e6d0ad13413144016 --- /dev/null +++ b/docs/141.md @@ -0,0 +1,67 @@ +# Import your Jira project issues to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/jira.html](https://docs.gitlab.com/ee/user/project/import/jira.html) + +* [Future iterations](#future-iterations) +* [Prerequisites](#prerequisites) + * [Permissions](#permissions) + * [Jira integration](#jira-integration) +* [Import Jira issues to GitLab](#import-jira-issues-to-gitlab) + +# Import your Jira project issues to GitLab[](#import-your-jira-project-issues-to-gitlab "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2766) . + +使用 GitLab Jira 导入器,您可以将 Jira 问题导入到 GitLab.com 或您自己管理的 GitLab 实例. + +Jira 问题导入是 MVC 项目级别的功能,这意味着可以将来自多个 Jira 项目的问题导入到 GitLab 项目中. MVC 版本将问题标题和描述以及一些其他问题元数据作为问题描述的一部分导入. + +## Future iterations[](#future-iterations "Permalink") + +从 GitLab 12.10 开始,Jira 问题导入程序仅提供问题的标题和描述. + +有[史诗般的](https://gitlab.com/groups/gitlab-org/-/epics/2738)跟踪项目的添加,例如问题受让人,标签,评论,用户映射等等. 这些将包含在 GitLab Jira 进口商的未来版本中. + +## Prerequisites[](#prerequisites "Permalink") + +### Permissions[](#permissions "Permalink") + +In order to be able to import issues from a Jira project you need to have read access on Jira issues and a [Maintainer or higher](../../permissions.html#project-members-permissions) role in the GitLab project that you wish to import into. + +### Jira integration[](#jira-integration "Permalink") + +此功能使用现有的 GitLab [Jira 集成](../integrations/jira.html) . + +在尝试导入 Jira 问题之前,请确保已设置集成. + +## Import Jira issues to GitLab[](#import-jira-issues-to-gitlab "Permalink") + +GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/216145)了新的导入表单. + +要将 Jira 问题导入到 GitLab 项目,请执行以下步骤. + +**注意:**导入 Jira 问题是作为异步后台作业完成的,这可能会由于导入队列负载,系统负载或其他因素而导致延迟. 导入大型项目可能需要几分钟,具体取决于导入的大小. + +1. 在 **在问题**页面上,点击**导入问题** ( ) **>从 Jira 导入** . + + [![Import issues from Jira button](img/6b48060a3ef4c055e75a74e6a396ebb9.png)](img/jira/import_issues_from_jira_button_v12_10.png) + + 仅当您具有[正确的权限时,"](#permissions) **从 Jira 导入"**选项才可见. + + 出现以下形式. 如果您先前已经设置了[Jira 集成](../integrations/jira.html) ,现在可以在下拉列表中看到您有权访问的 Jira 项目. + + [![Import issues from Jira form](img/c10c0f19a1d0076044db1057cfb19875.png)](img/jira/import_issues_from_jira_form_v13_2.png) + +2. 单击**导入自**下拉列表,然后选择要从中导入问题的 Jira 项目. + + 在" **Jira-GitLab 用户映射模板"**部分中,该表显示了您的 Jira 用户将映射到哪些 GitLab 用户. 如果无法将 Jira 用户与 GitLab 用户匹配,则该下拉列表默认为执行导入的用户. + +3. 要更改任何建议的映射,请单击**GitLab 用户名列中**的下拉列表,然后选择要映射到每个 Jira 用户的用户. + + 该下拉列表可能不会显示所有用户,因此请使用搜索栏在此 GitLab 项目中查找特定用户. + +4. 点击**继续** . 系统会提示您已开始导入. + + 当导入在后台运行时,您可以从导入状态页面导航到问题页面,并且您会看到新问题出现在问题列表中. + +5. 要检查导入状态,请再次转到" Jira 导入"页面. \ No newline at end of file diff --git a/docs/142.md b/docs/142.md new file mode 100644 index 0000000000000000000000000000000000000000..970fe9a52bdd57087ad8b6f73bf2b0900e352a0e --- /dev/null +++ b/docs/142.md @@ -0,0 +1,40 @@ +# Migrating from Perforce Helix + +> 原文:[https://docs.gitlab.com/ee/user/project/import/perforce.html](https://docs.gitlab.com/ee/user/project/import/perforce.html) + +* [Perforce vs Git](#perforce-vs-git) +* [Why migrate](#why-migrate) +* [How to migrate](#how-to-migrate) + +# Migrating from Perforce Helix[](#migrating-from-perforce-helix "Permalink") + +[Perforce Helix](https://www.perforce.com/)提供了一套工具,其中还包括类似于 Git 的集中式专有版本控制系统. + +## Perforce vs Git[](#perforce-vs-git "Permalink") + +以下列表说明了 Perforce Helix 和 Git 之间的主要区别: + +1. 通常,最大的区别是与 Git 的轻量级分支相比,Perforce 分支是重量级的. 当您在 Perforce 中创建分支时,它会在其专有数据库中为分支中的每个文件创建一个集成记录,无论实际更改了多少. 而 Git 是采用不同的体系结构实现的,因此,单个 SHA 可以充当更改后整个存储库状态的指针,这使得分支非常容易. 这就是功能分支工作流如此容易被 Git 采纳的原因. +2. 而且,在 Git 中,分支之间的上下文切换要容易得多. 如果您的经理说"您需要停止使用该新功能并修复此安全漏洞",那么您可以在 Git 中轻松地做到这一点. +3. 在本地计算机上拥有项目及其历史的完整副本意味着每笔交易都非常快,而 Git 则提供了该副本. 您可以单独进行分支/合并和试验,然后在与所有人共享新的有趣内容之前清理混乱. +4. Git 还使代码审核变得简单,因为您可以共享更改而无需将更改合并到主版本中,而 Perforce 必须在服务器上实现 Shelving 功能,以便其他人可以在合并之前查看更改. + +## Why migrate[](#why-migrate "Permalink") + +从用户和管理员的角度来看,Perforce Helix 可能难以管理. 迁移到 Git / GitLab 有: + +* **没有许可费用** ,Git 是 GPL,而 Perforce Helix 是专有的. +* **学习曲线更短** ,Git 有一个庞大的社区和大量的入门指南. +* **与现代工具集成** ,迁移到 Git 和 GitLab,您可以拥有一个开源的端到端软件开发平台,该平台具有内置的版本控制,问题跟踪,代码审查,CI / CD 等. + +## How to migrate[](#how-to-migrate "Permalink") + +Git 包含一个内置机制( `git p4` ),用于从 Perforce 中提取代码并将其从 Git 提交回 Perforce. + +以下是一些入门指南: + +* [`git-p4` manual page](https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-p4.html) +* [`git-p4` example usage](https://git.wiki.kernel.org/index.php/Git-p4_Usage) +* [Git book migration guide](https://git-scm.com/book/en/v2/Git-and-Other-Systems-Migrating-to-Git#_perforce_import) + +请注意, `git p4`和`git filter-branch`在创建小型高效 Git 包文件方面不是很好. 因此,在第一次将存储库发送到 GitLab 服务器之前,花一些时间和 CPU 适当地重新打包存储库可能是个好主意. 请参阅[此 StackOverflow 问题](https://stackoverflow.com/questions/28720151/git-gc-aggressive-vs-git-repack/) . \ No newline at end of file diff --git a/docs/143.md b/docs/143.md new file mode 100644 index 0000000000000000000000000000000000000000..ee84f539c1f80f32557dbb88e9669a2e1d8bbf56 --- /dev/null +++ b/docs/143.md @@ -0,0 +1,36 @@ +# Import Phabricator tasks into a GitLab project + +> 原文:[https://docs.gitlab.com/ee/user/project/import/phabricator.html](https://docs.gitlab.com/ee/user/project/import/phabricator.html) + +* [Users](#users) +* [Enabling this feature](#enabling-this-feature) + +# Import Phabricator tasks into a GitLab project[](#import-phabricator-tasks-into-a-gitlab-project "Permalink") + +在 GitLab 12.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/60562) . + +GitLab 允许您将所有任务从 Phabricator 实例导入到 GitLab 问题中. 导入将创建一个项目,并禁用存储库. + +当前,仅导入以下基本字段: + +* Title +* Description +* 状态(打开或关闭) +* 创建于 +* 在关闭 + +## Users[](#users "Permalink") + +用户的受让人和作者将从 Task 的所有者和作者中扣除:如果具有相同用户名的用户有权访问要导入到的项目的名称空间,则将链接该用户. + +## Enabling this feature[](#enabling-this-feature "Permalink") + +当此功能不完整时,需要一个功能标志来启用它,以便我们在向所有人发布该功能之前获得早期反馈. 要启用它: + +1. 在 Rails 控制台中运行以下命令: + + ``` + Feature.enable(:phabricator_import) + ``` + +2. 在管理区域中将 Phabricator 用作[导入源](../../admin_area/settings/visibility_and_access_controls.html#import-sources) . \ No newline at end of file diff --git a/docs/144.md b/docs/144.md new file mode 100644 index 0000000000000000000000000000000000000000..6e5f5c5e2891393b4aa59ab915f2434613d3f608 --- /dev/null +++ b/docs/144.md @@ -0,0 +1,55 @@ +# Import multiple repositories by uploading a manifest file + +> 原文:[https://docs.gitlab.com/ee/user/project/import/manifest.html](https://docs.gitlab.com/ee/user/project/import/manifest.html) + +* [Requirements](#requirements) +* [Manifest format](#manifest-format) +* [Importing the repositories](#importing-the-repositories) + +# Import multiple repositories by uploading a manifest file[](#import-multiple-repositories-by-uploading-a-manifest-file "Permalink") + +在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28811) . + +GitLab 允许您基于清单文件(如[Android 存储库](https://android.googlesource.com/platform/manifest/+/2d6f081a3b05d8ef7a2b1b52b0d536b2b74feab4/default.xml)使用的清单文件)导入所有必需的 Git 存储[库](https://android.googlesource.com/platform/manifest/+/2d6f081a3b05d8ef7a2b1b52b0d536b2b74feab4/default.xml) . 当您需要导入具有许多存储库(例如 Android 开放源项目(AOSP))的项目时,此功能非常方便. + +## Requirements[](#requirements "Permalink") + +GitLab 必须为其数据库使用 PostgreSQL,因为清单导入工作需要[子组](../../group/subgroups/index.html) . + +阅读有关[数据库要求的](../../../install/requirements.html#database)更多信息. + +## Manifest format[](#manifest-format "Permalink") + +清单必须是 XML 文件. 必须有一个带有`review`属性的`remote`标签,该`review`属性包含指向 Git 服务器的 URL,并且每个`project`标签都必须具有`name`和`path`属性. 然后,GitLab 将通过将`remote`标记中的 URL 与项目名称组合来构建到存储库的 URL. 路径属性将用于表示 GitLab 中的项目路径. + +以下是清单文件的有效示例: + +``` +<manifest> + <remote review="https://android.googlesource.com/" /> + + <project path="build/make" name="platform/build" /> + <project path="build/blueprint" name="platform/build/blueprint" /> +</manifest> +``` + +结果,将创建以下项目: + +| GitLab | 导入网址 | +| --- | --- | +| `https://gitlab.com/YOUR_GROUP/build/make` | [https://android.googlesource.com/platform/build](https://android.googlesource.com/platform/build) | +| `https://gitlab.com/YOUR_GROUP/build/blueprint` | [https://android.googlesource.com/platform/build/blueprint](https://android.googlesource.com/platform/build/blueprint) | + +## Importing the repositories[](#importing-the-repositories "Permalink") + +You can start the import with: + +1. 在您的 GitLab 仪表板中,单击" **新建项目".** +2. 切换到**导入项目**选项卡 +3. 单击**清单文件**按钮 +4. 为 GitLab 提供清单 xml 文件 +5. 选择要导入的组(如果没有,则需要先创建一个组) +6. 单击**列出可用的存储库** . 此时,您将根据清单文件重定向到带有项目列表的导入状态页面. +7. 检查列表,然后单击" **导入所有存储库"**以开始导入. + + [![Manifest status](img/e5f179b25c2db023892b0a5f559b67d5.png)](img/manifest_status.png) \ No newline at end of file diff --git a/docs/145.md b/docs/145.md new file mode 100644 index 0000000000000000000000000000000000000000..6df03b6d402a1253d067802025a3f6982c0e9879 --- /dev/null +++ b/docs/145.md @@ -0,0 +1,16 @@ +# Import project from repo by URL + +> 原文:[https://docs.gitlab.com/ee/user/project/import/repo_by_url.html](https://docs.gitlab.com/ee/user/project/import/repo_by_url.html) + +# Import project from repo by URL[](#import-project-from-repo-by-url "Permalink") + +您可以通过提供 Git URL 来导入现有存储库: + +1. 在您的 GitLab 仪表板中,单击" **新建项目".** +2. 切换到**导入项目**选项卡 +3. 点击**按 URL 回购**按钮 +4. 填写" Git 存储库 URL"和其余项目字段 +5. 单击**创建项目**开始导入过程 +6. 完成后,您将被重定向到新创建的项目 + +[![Import project by repo URL](img/731943edb4428a3eb27c86d8d454d0e0.png)](img/import_projects_from_repo_url.png) \ No newline at end of file diff --git a/docs/146.md b/docs/146.md new file mode 100644 index 0000000000000000000000000000000000000000..3ebeb7ec335e06ee587887279dd60028422c6dbe --- /dev/null +++ b/docs/146.md @@ -0,0 +1,141 @@ +# Migrating from SVN to GitLab + +> 原文:[https://docs.gitlab.com/ee/user/project/import/svn.html](https://docs.gitlab.com/ee/user/project/import/svn.html) + +* [Overview](#overview) +* [Smooth migration with a Git/SVN mirror using SubGit](#smooth-migration-with-a-gitsvn-mirror-using-subgit) + * [SubGit prerequisites](#subgit-prerequisites) + * [SubGit configuration](#subgit-configuration) + * [Initial translation](#initial-translation) + * [SubGit licensing](#subgit-licensing) + * [SubGit support](#subgit-support) +* [Cut over migration with svn2git](#cut-over-migration-with-svn2git) +* [Contribute to this guide](#contribute-to-this-guide) + +# Migrating from SVN to GitLab[](#migrating-from-svn-to-gitlab "Permalink") + +Subversion(SVN)是中央版本控制系统(VCS),而 Git 是分布式版本控制系统. 两者之间有一些主要区别,有关更多信息,请咨询您喜欢的搜索引擎. + +## Overview[](#overview "Permalink") + +SVN 到 Git 迁移的方法有两种: + +1. [Git/SVN Mirror](#smooth-migration-with-a-gitsvn-mirror-using-subgit) which: + * 使 GitLab 存储库镜像 SVN 项目. + * Git 和 SVN 存储库保持同步; 您可以使用任何一个. + * 简化迁移过程并允许管理迁移风险. +2. [Cut over migration](#cut-over-migration-with-svn2git) which: + * 将现有数据和历史记录从 SVN 转换并导入到 Git. + * 是一劳永逸的方法,对较小的团队有用. + +## Smooth migration with a Git/SVN mirror using SubGit[](#smooth-migration-with-a-gitsvn-mirror-using-subgit "Permalink") + +[SubGit](https://subgit.com)是用于平稳,无压力的 SVN 到 Git 迁移的工具. 它创建本地或远程 Subversion 存储库的可写 Git 镜像,并且您可以根据需要同时使用 Subversion 和 Git. 它需要直接在文件系统级别与 Git 存储库通信时访问您的 GitLab 服务器. + +### SubGit prerequisites[](#subgit-prerequisites "Permalink") + +1. 安装 Oracle JRE 1.8 或更高版本. 在基于 Debian 的 Linux 发行版上,您可以阅读[本文](http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html) . +2. 从[https://subgit.com/download](https://subgit.com/download)下载 SubGit. +3. 将下载的 SubGit zip 存档解压缩到`/opt`目录. `subgit`命令将在`/opt/subgit-VERSION/bin/subgit` . + +### SubGit configuration[](#subgit-configuration "Permalink") + +在 GitLab 中镜像 SVN 存储库的第一步是创建一个新的空项目,该项目将用作镜像. 对于 Omnibus 安装,默认情况下,存储库的路径将位于`/var/opt/gitlab/git-data/repositories/USER/REPO.git` . 对于从源安装,默认的存储库目录将是`/home/git/repositories/USER/REPO.git` . 为方便起见,将此路径分配给变量: + +``` +GIT_REPO_PATH=/var/opt/gitlab/git-data/repositories/USER/REPOS.git +``` + +SubGit 将使该存储库与远程 SVN 项目保持同步. 为了方便起见,请将您的远程 SVN 项目 URL 分配给一个变量: + +``` +SVN_PROJECT_URL=http://svn.company.com/repos/project +``` + +接下来,您需要运行 SubGit 来设置 Git / SVN 镜像. 确保代表拥有 GitLab Git 存储库所有权的同一用户运行以下`subgit`命令(默认情况下为`git` ): + +``` +subgit configure --layout auto $SVN_PROJECT_URL $GIT_REPO_PATH +``` + +如有必要,请调整作者和分支机构的映射. 用您喜欢的文本编辑器打开: + +``` +edit $GIT_REPO_PATH/subgit/authors.txt +edit $GIT_REPO_PATH/subgit/config +``` + +有关 SubGit 配置选项的更多信息,请参阅[SubGit 文档](https://subgit.com/documentation/)网站. + +### Initial translation[](#initial-translation "Permalink") + +现在,SubGit 已经配置了 Git / SVN 存储库,运行`subgit`来执行将现有 SVN 修订版初始转换为 Git 存储库的操作: + +``` +subgit install $GIT_REPO_PATH +``` + +初始翻译完成后,Git 存储库和 SVN 项目将通过`subgit`保持同步-新的 Git 提交将转换为 SVN 修订版,而新的 SVN 修订版将转换为 Git 提交. Mirror 透明地工作,不需要任何特殊命令. + +如果您希望使用`subgit`执行一次性迁移,请使用`import`命令而不是`install` : + +``` +subgit import $GIT_REPO_PATH +``` + +### SubGit licensing[](#subgit-licensing "Permalink") + +以镜像模式运行 SubGit 需要[注册](https://subgit.com/pricing) . 开源,学术和启动项目免费注册. + +### SubGit support[](#subgit-support "Permalink") + +对于与 SubGit 的 SVN 到 GitLab 迁移有关的任何问题,您可以直接通过[support@subgit.com](mailto:support@subgit.com)与 SubGit 团队[联系](mailto:support@subgit.com) . + +## Cut over migration with svn2git[](#cut-over-migration-with-svn2git "Permalink") + +如果当前正在使用 SVN 存储库,则可以将该存储库迁移到 Git 和 GitLab. 我们建议您进行一次硬性转换-运行一次迁移命令,然后让所有开发人员立即开始使用新的 GitLab 存储库. 否则,很难保持双向同步更改. 转换过程应在本地工作站上运行. + +安装`svn2git` . 在所有系统上,如果已经安装了 Ruby 和 Git,则可以作为 Ruby gem 安装. + +``` +sudo gem install svn2git +``` + +在基于 Debian 的 Linux 发行版上,您可以安装本机软件包: + +``` +sudo apt-get install git-core git-svn ruby +``` + +(可选)准备一个 authors 文件,以便`svn2git`可以将 SVN 作者映射到 Git 作者. 如果您选择不创建作者文件,则提交将不会归因于正确的 GitLab 用户. 有些用户可能不会认为这是一个大问题,而另一些用户则希望确保他们完成此步骤. 如果选择映射作者,则将需要映射 SVN 信息库中的更改中存在的每个作者. 否则,转换将失败,您将必须相应地更新作者文件. 以下命令将搜索存储库并输出作者列表. + +``` +svn log --quiet | grep -E "r[0-9]+ \| .+ \|" | cut -d'|' -f2 | sed 's/ //g' | sort | uniq +``` + +使用最后一条命令的输出来构造作者文件. 创建一个名为`authors.txt`的文件,并在每行添加一个映射. + +``` +janedoe = Jane Doe <janedoe@example.com> +johndoe = John Doe <johndoe@example.com> +``` + +如果您的 SVN 储存库为标准格式(主干,分支,标签,而非嵌套),则转换很简单. 对于非标准存储库,请参见[svn2git 文档](https://github.com/nirvdrum/svn2git) . 以下命令将检出存储库并在当前工作目录中进行转换. 在运行`svn2git`命令之前,请确保为每个存储库创建一个新目录. 转换过程将需要一些时间. + +``` +svn2git https://svn.example.com/path/to/repo --authors /path/to/authors.txt +``` + +如果您的 SVN 信息库需要用户名和密码,请在上述命令中添加`--username <username>`和`--password <password>`标志. `svn2git`还支持排除某些文件路径,分支,标签等.请参阅[svn2git 文档](https://github.com/nirvdrum/svn2git)或运行`svn2git --help`以获取有关所有可用选项的完整文档. + +创建一个新的 GitLab 项目,您最终将在其中推送转换后的代码. 从项目页面复制 SSH 或 HTTP(S)存储库 URL. 将 GitLab 存储库添加为 Git 远程,并推送所有更改. 这将推送所有提交,分支和标签. + +``` +git remote add origin git@gitlab.com:<group>/<project>.git +git push --all origin +git push --tags origin +``` + +## Contribute to this guide[](#contribute-to-this-guide "Permalink") + +我们欢迎所有将扩展本指南的贡献,其中包括有关如何从 SVN 和其他版本控制系统进行迁移的说明. \ No newline at end of file diff --git a/docs/147.md b/docs/147.md new file mode 100644 index 0000000000000000000000000000000000000000..d0725824ce0de369ed508f874854b212db5b30a1 --- /dev/null +++ b/docs/147.md @@ -0,0 +1,37 @@ +# Migrating from TFVC to Git + +> 原文:[https://docs.gitlab.com/ee/user/project/import/tfvc.html](https://docs.gitlab.com/ee/user/project/import/tfvc.html) + +* [TFVC vs Git](#tfvc-vs-git) +* [Why migrate](#why-migrate) +* [How to migrate](#how-to-migrate) + +# Migrating from TFVC to Git[](#migrating-from-tfvc-to-git "Permalink") + +Team Foundation Server(TFS)在 2019 年重命名为[Azure DevOps Server](https://azure.microsoft.com/en-us/services/devops/server/) ,是 Microsoft 开发的一组工具,还包括[Team Foundation Version Control](https://docs.microsoft.com/en-us/azure/devops/repos/tfvc/what-is-tfvc?view=azure-devops) (TFVC),这是一个类似于 Git 的集中式版本控制系统. + +在本文档中,我们重点介绍从 TFVC 到 Git 的迁移. + +## TFVC vs Git[](#tfvc-vs-git "Permalink") + +TFVC 和 Git 之间的主要区别是: + +* **Git 是分布式的:**虽然 TFVC 使用客户端-服务器体系结构进行集中管理,但 Git 是分布式的. 由于您使用了整个存储库的副本,因此 Git 的工作流程更加灵活. 例如,这使您可以快速切换分支或合并,而无需与远程服务器进行通信. +* **存储:**集中式版本控制系统中的更改是按文件(更改集)进行的,而在 Git 中,已提交的文件将全部存储(快照). 这意味着还原或撤消 Git 的整个更改非常容易. + +有关更多信息,请参见: + +* Microsoft’s [comparison of Git and TFVC](https://docs.microsoft.com/en-us/azure/devops/repos/tfvc/comparison-git-tfvc?view=azure-devops). +* The Wikipedia [comparison of version control software](https://en.wikipedia.org/wiki/Comparison_of_version_control_software). + +## Why migrate[](#why-migrate "Permalink") + +迁移到 Git / GitLab 的优势: + +* **无需许可费用:** Git 是开源的,而 TFVC 是专有的. +* **较短的学习曲线:** Git 拥有一个庞大的社区和大量的入门指南(请参阅我们的[Git 主题](../../../topics/git/index.html) ). +* **与现代工具的集成:**迁移到 Git 和 GitLab 之后,您将拥有一个带有内置版本控制,问题跟踪,代码审查,CI / CD 等的开源,端到端软件开发平台. + +## How to migrate[](#how-to-migrate "Permalink") + +从 TFVC 迁移到 Git 的最佳选择是使用[`git-tfs`](https://github.com/git-tfs/git-tfs)工具. 阅读" [将 TFS 迁移到 Git"](https://github.com/git-tfs/git-tfs/blob/master/doc/usecases/migrate_tfs_to_git.md)指南以获取更多详细信息. \ No newline at end of file diff --git a/docs/148.md b/docs/148.md new file mode 100644 index 0000000000000000000000000000000000000000..eb318a127571726610ba6d2fb6b1e9aabf48c717 --- /dev/null +++ b/docs/148.md @@ -0,0 +1,106 @@ +# Push Options + +> 原文:[https://docs.gitlab.com/ee/user/project/push_options.html](https://docs.gitlab.com/ee/user/project/push_options.html) + +* [Push options for GitLab CI/CD](#push-options-for-gitlab-cicd) +* [Push options for merge requests](#push-options-for-merge-requests) +* [Useful Git aliases](#useful-git-aliases) + * [Merge when pipeline succeeds alias](#merge-when-pipeline-succeeds-alias) + +# Push Options[](#push-options "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15643) . + +GitLab 支持使用客户端[Git 推送选项](https://git-scm.com/docs/git-push#Documentation/git-push.txt--oltoptiongt)在推送更改的同时执行各种操作. 此外, [推送规则](../../push_rules/push_rules.html)提供服务器端控制和实施选项. + +当前,有推送选项可用于: + +* [Skipping CI jobs](#push-options-for-gitlab-cicd) +* [Merge requests](#push-options-for-merge-requests) + +**注意:** Git 推送选项仅在 Git 2.10 或更高版本中可用. + +对于 2.10 至 2.17 版本的 Git,请使用`--push-option` : + +``` +git push --push-option=<push_option> +``` + +对于 2.18 及更高版本,可以使用以上格式,或更短的`-o` : + +``` +git push -o <push_option> +``` + +## Push options for GitLab CI/CD[](#push-options-for-gitlab-cicd "Permalink") + +您可以使用推入选项跳过 CI / CD 管道或传递环境变量. + +| 推送选项 | Description | 版本介绍 | +| --- | --- | --- | +| `ci.skip` | 不要为最新推送创建 CI 管道. | [11.7](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15643) | +| `ci.variable="<name>=<value>"` | 如果由于推送而创建了[环境变量](../../ci/variables/README.html) ,请提供要在 CI 管道中使用的[环境变量](../../ci/variables/README.html) . | [12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/27983) | + +使用`ci.skip`的示例: + +``` +git push -o ci.skip +``` + +An example of passing some environment variables for a pipeline: + +``` +git push -o ci.variable="MAX_RETRIES=10" -o ci.variable="MAX_TIME=600" +``` + +## Push options for merge requests[](#push-options-for-merge-requests "Permalink") + +您可以在推送更改的同时使用 Git 推送选项对合并请求执行某些操作: + +| 推送选项 | Description | 版本介绍 | +| --- | --- | --- | +| `merge_request.create` | 为推送的分支创建一个新的合并请求. | [11.10](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26752) | +| `merge_request.target=<branch_name>` | 将合并请求的目标设置为特定分支. | [11.10](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26752) | +| `merge_request.merge_when_pipeline_succeeds` | 设置合并请求以[在其管道成功时](merge_requests/merge_when_pipeline_succeeds.html)进行[合并](merge_requests/merge_when_pipeline_succeeds.html) . | [11.10](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26752) | +| `merge_request.remove_source_branch` | 设置合并请求以在合并时删除源分支. | [12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64320) | +| `merge_request.title="<title>"` | 设置合并请求的标题. 例如: `git push -o merge_request.title="The title I want"` . | [12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64320) | +| `merge_request.description="<description>"` | 设置合并请求的描述. 例如: `git push -o merge_request.description="The description I want"` . | [12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64320) | +| `merge_request.label="<label>"` | 将标签添加到合并请求. 如果标签不存在,它将被创建. 例如,对于两个标签: `git push -o merge_request.label="label1" -o merge_request.label="label2"` . | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) | +| `merge_request.unlabel="<label>"` | 从合并请求中删除标签. 例如,对于两个标签: `git push -o merge_request.unlabel="label1" -o merge_request.unlabel="label2"` . | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) | + +如果您使用要求文本带有空格的 push 选项,则需要用引号( `"` )括起来.如果没有空格,则可以省略引号.例如: + +``` +git push -o merge_request.label="Label with spaces" +git push -o merge_request.label=Label-with-no-spaces +``` + +您可以通过使用多个`-o` (或`--push-option` )标志来组合推送选项以一次完成多个任务. 例如,如果您要创建一个新的合并请求,并定位一个名为`my-target-branch` : + +``` +git push -o merge_request.create -o merge_request.target=my-target-branch +``` + +此外,如果希望合并请求在管道成功后立即合并,则可以执行以下操作: + +``` +git push -o merge_request.create -o merge_request.target=my-target-branch -o merge_request.merge_when_pipeline_succeeds +``` + +## Useful Git aliases[](#useful-git-aliases "Permalink") + +如上所示,Git 推送选项可能导致 Git 命令增长很长. 如果您经常使用相同的 push 选项,则创建[Git 别名会](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases)很有用. Git 别名是 Git 的命令行快捷方式,可以大大简化长 Git 命令的使用. + +### Merge when pipeline succeeds alias[](#merge-when-pipeline-succeeds-alias "Permalink") + +要[在管道成功执行 Git push 选项时](#push-options-for-merge-requests)为[合并](#push-options-for-merge-requests)设置 Git 别名: + +``` +git config --global alias.mwps "push -o merge_request.create -o merge_request.target=master -o merge_request.merge_when_pipeline_succeeds" +``` + +然后,为了在管道成功时快速推送将针对 master 并合并的本地分支: + +``` +git mwps origin <local-branch-name> +``` \ No newline at end of file diff --git a/docs/149.md b/docs/149.md new file mode 100644 index 0000000000000000000000000000000000000000..cb1f81da37a4a7cf6c26d7528b6dba7acce7ec04 --- /dev/null +++ b/docs/149.md @@ -0,0 +1,341 @@ +# Releases + +> 原文:[https://docs.gitlab.com/ee/user/project/releases/](https://docs.gitlab.com/ee/user/project/releases/) + +* [View releases](#view-releases) +* [Create a release](#create-a-release) + * [Schedule a future release](#schedule-a-future-release) +* [Edit a release](#edit-a-release) +* [Add release notes to Git tags](#add-release-notes-to-git-tags) +* [Associate milestones with a release](#associate-milestones-with-a-release) +* [Get notified when a release is created](#get-notified-when-a-release-is-created) +* [Prevent unintentional releases by setting a deploy freeze](#prevent-unintentional-releases-by-setting-a-deploy-freeze) +* [Release fields](#release-fields) + * [Tag name](#tag-name) + * [Release notes description](#release-notes-description) + * [Release assets](#release-assets) + * [Permanent links to release assets](#permanent-links-to-release-assets) + * [Source code](#source-code) + * [Links](#links) +* [Release evidence](#release-evidence) + * [Collect release evidence](#collect-release-evidence-premium-only) + * [Include report artifacts as release evidence](#include-report-artifacts-as-release-evidence-ultimate-only) + * [Schedule release evidence collection](#schedule-release-evidence-collection) + * [Disable release evidence display](#disable-release-evidence-display-core-only) +* [GitLab Releaser](#gitlab-releaser) + +# Releases[](#releases "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766) . + +要在源代码历史记录中引入检查点,可以在发布时分配[Git 标签](https://git-scm.com/book/en/v2/Git-Basics-Tagging) . 但是,在大多数情况下,您的用户不仅需要原始源代码. 他们需要 CI / CD 系统输出的已编译对象或其他资产. + +GitLab *发行版*是与代码的发行版本相关联的源,构建输出,工件和其他元数据的快照. + +您可以在任何分支上创建一个 GitLab 版本. 创建发行版时: + +* manbetx 客户端打不开自动归档源代码,并将其与版本关联. +* GitLab 会自动创建一个 JSON 文件,其中列出了发行版中的所有内容,因此您可以比较和审核发行版. 该文件称为[发布证据](#release-evidence) . +* 您可以添加发行说明以及与发行版关联的标签的消息. + +创建发行版后,您可以将[里程碑与其关联](#associate-milestones-with-a-release) ,并附加[发行资产](#release-assets) ,例如运行手册或软件包. + +## View releases[](#view-releases "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36667) . + +要查看版本列表: + +* 转到**项目概述>版本** ,或 + +* 在项目的概述页面上,如果存在至少一个版本,请单击版本数. + + [![Number of Releases](img/4b690260474eb340f7b3f6d25b0568d2.png "Incremental counter of Releases")](img/releases_count_v13_2.png) + + * 在公共项目上,此数字对所有用户可见. + * 在私有项目上,具有 Reporter [权限](../../permissions.html#project-members-permissions)或更高[权限的](../../permissions.html#project-members-permissions)用户可以看到此数字. + +## Create a release[](#create-a-release "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32812) . 可以在 GitLab UI 中直接创建发布. + +**注意:**只有具有开发者权限或更高权限的用户才能创建发行版. 阅读有关[释放权限的](../../../user/permissions.html#project-members-permissions)更多信息. + +您可以在用户界面中或使用[Releases API](../../../api/releases/index.html#create-a-release)创建发布. 我们建议使用 API​​添加发行说明,作为 CI / CD 发行流程中的最后步骤之一. + +要通过 GitLab UI 创建新版本: + +1. 导航到**项目概述>发布** ,然后单击**新发布**按钮. +2. 在[**标签名称**](#tag-name)框中,输入一个名称. +3. In the **从创建** list, select the branch or enter a tag or commit SHA. +4. 在" **消息"**框中,输入与标签关联的消息. +5. (可选)在" [**发行说明"**](#release-notes-description)字段中,输入发行说明. 您可以使用 Markdown 并将文件拖放到此字段. + * 如果将此字段留空,则只会创建一个标签. + * 如果您填充它,将同时创建标签和发行版. +6. Click **创建标签**. + +如果创建了发行​​版,则可以在**项目概述>发行版中**对其进行查看. 如果创建了标签,则可以在**存储库>标签中**查看它. + +现在,您可以编辑发布以[添加里程碑](#associate-milestones-with-a-release)和[发布资产](#release-assets) . + +### Schedule a future release[](#schedule-a-future-release "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/38105) . + +您可以使用[Releases API](../../../api/releases/index.html#upcoming-releases)提前创建发行[版](../../../api/releases/index.html#upcoming-releases) . 当您设置将来的`released_at`日期时,将在发布标签旁边显示**即将发布**的发布标志. 经过`released_at`日期和时间后,会自动删除徽章. + +[![An upcoming release](img/7727ed12caef6b761b73e4bd379c7839.png)](img/upcoming_release_v12_7.png) + +## Edit a release[](#edit-a-release "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/26016) . 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9427)了资产链接编辑. + +**注意:**只有具有开发者权限或更高权限的用户才能编辑发行版. 阅读有关[释放权限的](../../../user/permissions.html#project-members-permissions)更多信息. + +要编辑发布的详细信息: + +1. 导航到**项目概述>发布** . +2. 在您要修改的发行版的右上角,单击" **编辑此发行版"** (铅笔图标). +3. 在" **编辑版本"**页面上,更改版本的详细信息. +4. Click **保存更改**. + +您可以编辑发行标题,注释,关联的里程碑和资产链接. 要更改其他发行信息,例如标签或发行日期,请使用[Releases API](../../../api/releases/index.html#update-a-release) . + +## Add release notes to Git tags[](#add-release-notes-to-git-tags "Permalink") + +If you have an existing Git tag, you can add release notes to it. + +您可以在用户界面中或使用[Releases API](../../../api/releases/index.html)来执行此操作. 我们建议使用 API​​添加发行说明,作为 CI / CD 发行流程中的最后步骤之一. + +在界面中,要向新的 Git 标签添加发行说明: + +1. 导航到您项目的**Repository> Tags** . +2. Click **新的一天**. +3. 在**发行说明**字段中,输入发行说明. 您可以使用 Markdown 并将文件拖放到此字段. +4. Click **创建标签**. + +在界面中,要将发行说明添加到现有的 Git 标签: + +1. 导航到您项目的**Repository> Tags** . +2. 单击**编辑发行说明** (铅笔图标). +3. 在**发行说明**字段中,输入发行说明. 您可以在此字段中使用 Markdown,并将文件拖放到该字段中. +4. Click **保存更改**. + +## Associate milestones with a release[](#associate-milestones-with-a-release "Permalink") + +版本历史 + +* 在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/29020) . +* [已更新](https://gitlab.com/gitlab-org/gitlab/-/issues/39467) ,可在 GitLab 13.0 中的 UI 中编辑里程碑. + +您可以将一个版本与一个或多个[项目里程碑](../milestones/index.html#project-milestones-and-group-milestones)相关联. + +您可以在用户界面中执行此操作,也可以在对[Releases API 的](../../../api/releases/index.html#create-a-release)请求中包含一个`milestones`数组. + +在用户界面中,要将里程碑与版本关联: + +1. 导航到**项目概述>发布** . +2. 在您要修改的发行版的右上角,单击" **编辑此发行版"** (铅笔图标). +3. 从" **里程碑"**列表中,选择要关联的每个里程碑. 您可以选择多个里程碑. +4. Click **保存更改**. + +在" **项目概述">"发布"**页面上, **里程碑**列在顶部,以及有关里程碑问题的统计信息. + +[![A Release with one associated milestone](img/21967843cf3a12bcfa5e39a39b1b3f69.png)](img/release_with_milestone_v12_9.png) + +在" **问题">"里程碑"**页面上,以及当您单击此页面上的里程碑时,也可以看到发行版本. + +这是一个里程碑示例,分别没有发布,一个发布和两个发布. + +[![Milestones with and without Release associations](img/e6ef8c883764c13967c9c9fcc5617980.png)](img/milestone_list_with_releases_v12_5.png) + +## Get notified when a release is created[](#get-notified-when-a-release-is-created "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/26001) . + +为您的项目创建新版本时,将通过电子邮件通知您. + +订阅发布通知: + +1. 导航到" **项目概述"** . +2. 单击**通知设置** (响铃图标). +3. 在列表中,点击**自定义** . +4. Select the **新品发布** check box. +5. 关闭对话框进行保存. + +## Prevent unintentional releases by setting a deploy freeze[](#prevent-unintentional-releases-by-setting-a-deploy-freeze "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29382) . + +通过设置[*部署冻结*期,](../../../ci/environments/deployment_safety.html)可以在指定的时间内防止意外的生产发布. 冻结部署有助于减少自动化部署时的不确定性和风险. + +使用" [冻结时间" API](../../../api/freeze_periods.html)设置被定义为[crontab](https://crontab.guru/)条目的`freeze_start`和`freeze_end` . + +如果正在执行的作业处于冻结期,则 GitLab CI / CD 会创建一个名为`$CI_DEPLOY_FREEZE`的环境变量. + +为了防止执行部署作业,请在`gitlab-ci.yaml`创建一个`rules`条目,例如: + +``` +deploy_to_production: + stage: deploy + script: deploy_to_prod.sh + rules: + - if: $CI_DEPLOY_FREEZE == null +``` + +如果项目包含多个冻结期,则所有时期都适用. 如果它们重叠,则冻结将覆盖整个重叠期间. + +有关更多信息,请参阅[部署安全](../../../ci/environments/deployment_safety.html) . + +## Release fields[](#release-fields "Permalink") + +创建或编辑发行版时,以下字段可用. + +### Tag name[](#tag-name "Permalink") + +发行标签名称应包括发行版本. GitLab 在我们的发行版中使用[语义版本控制](https://semver.org/) ,我们建议您也这样做. 使用`(Major).(Minor).(Patch)` ,如[GitLab 版本控制政策](../../../policy/maintenance.html#versioning)中所述. + +例如,对于 GitLab 版本`10.5.7` : + +* `10`代表主要版本. 主要版本是`10.0.0` ,但通常称为`10.0` . +* `5`代表次要版本. 次要版本为`10.5.0` ,但通常称为`10.5` . +* `7`代表补丁号码. + +版本号的任何部分都可以是多个数字,例如`13.10.11` . + +### Release notes description[](#release-notes-description "Permalink") + +每个版本都有说明. 您可以添加任何您喜欢的文本,但是我们建议您添加一个变更日志来描述发行版本的内容. 这可以帮助用户快速扫描您发布的每个版本之间的差异. + +**注意:** [Git 的标记消息](https://git-scm.com/book/en/v2/Git-Basics-Tagging)和发行说明描述无关. 说明支持[Markdown](../../markdown.html) . + +### Release assets[](#release-assets "Permalink") + +当前,您可以将以下类型的资产添加到每个版本: + +* [Source code](#source-code) +* [Links](#links) + +manbetx 客户端打不开将在未来支持更多的资产类型,包括诸如预装包,合规性/安全证据或容器图像之类的对象. + +#### Permanent links to release assets[](#permanent-links-to-release-assets "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27300) . + +与发布相关联的资产可通过永久 URL 访问. GitLab 将始终将此 URL 重定向到实际资产位置,因此,即使资产移动到其他位置,您也可以继续使用相同的 URL. 这是在[链接创建](../../../api/releases/links.html#create-a-link)或[更新](../../../api/releases/links.html#update-a-link)期间定义的. + +每个资产都有一个名称, *实际*资产位置的 URL,以及一个可选的`filepath`参数,如果您指定它,它将创建指向发布的资产的 URL. URL 的格式为: + +``` +https://host/namespace/project/releases/:release/downloads/:filepath +``` + +如果您对资产`v11.9.0-rc2`的发布`gitlab-org`命名空间和`gitlab-runner`项目上`gitlab.com` ,例如: + +``` +{ "name": "linux amd64", "filepath": "/binaries/gitlab-runner-linux-amd64", "url": "https://gitlab-runner-downloads.s3.amazonaws.com/v11.9.0-rc2/binaries/gitlab-runner-linux-amd64" } +``` + +该资产具有以下直接链接: + +``` +https://gitlab.com/gitlab-org/gitlab-runner/releases/v11.9.0-rc2/downloads/binaries/gitlab-runner-linux-amd64 +``` + +资产的物理位置可以随时更改,并且直接链接将保持不变. + +### Source code[](#source-code "Permalink") + +GitLab 会根据给定的 Git 标签自动生成`zip` , `tar.gz` , `tar.bz2`和`tar`归档的源代码. 这些是只读资产. + +### Links[](#links "Permalink") + +A link is any URL which can point to whatever you like: documentation, built binaries, or other related materials. These can be both internal or external links from your GitLab instance. + +链接的四种类型是" Runbook"," Package"," Image"和" Other". + +## Release evidence[](#release-evidence "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/26019) . + +每次创建发行版时,GitLab 都会拍摄与之相关的数据快照. 此数据保存在 JSON 文件中,称为*发布证据* . 它包括链接的里程碑和问题,并且可以促进内部流程,例如外部审核. + +要访问发布证据,请在"发布"页面上,单击" **证据集合"**标题下列出的 JSON 文件的链接. + +您还可以[使用 API](../../../api/releases/index.html#collect-release-evidence-premium-only)生成现有版本的版本证据. 因此,每个版本可以具有多个版本证据快照. 您可以在"发布"页面上查看发布证据及其详细信息. + +**注意:**禁用问题跟踪器后, [将无法下载](https://gitlab.com/gitlab-org/gitlab/-/issues/208397)发布证据. + +这是释放证据对象的示例: + +``` +{ "release": { "id": 5, "tag_name": "v4.0", "name": "New release", "project": { "id": 20, "name": "Project name", "created_at": "2019-04-14T11:12:13.940Z", "description": "Project description" }, "created_at": "2019-06-28 13:23:40 UTC", "description": "Release description", "milestones": [ { "id": 11, "title": "v4.0-rc1", "state": "closed", "due_date": "2019-05-12 12:00:00 UTC", "created_at": "2019-04-17 15:45:12 UTC", "issues": [ { "id": 82, "title": "The top-right popup is broken", "author_name": "John Doe", "author_email": "john@doe.com", "state": "closed", "due_date": "2019-05-10 12:00:00 UTC" }, { "id": 89, "title": "The title of this page is misleading", "author_name": "Jane Smith", "author_email": "jane@smith.com", "state": "closed", "due_date": "nil" } ] }, { "id": 12, "title": "v4.0-rc2", "state": "closed", "due_date": "2019-05-30 18:30:00 UTC", "created_at": "2019-04-17 15:45:12 UTC", "issues": [] } ], "report_artifacts": [ { "url":"https://gitlab.example.com/root/project-name/-/jobs/111/artifacts/download" } ] } } +``` + +### Collect release evidence[](#collect-release-evidence-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199065) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10. + +创建发布后,将自动收集发布证据. 要在其他任何时间启动证据收集,请使用[API 调用](../../../api/releases/index.html#collect-release-evidence-premium-only) . 您可以为一个发布多次收集发布证据. + +在"发布"页面上可以看到证据收集快照,以及收集证据的时间戳. + +### Include report artifacts as release evidence[](#include-report-artifacts-as-release-evidence-ultimate-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32773) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2. + +创建发布时,如果[作业工件](../../../ci/pipelines/job_artifacts.html#artifactsreports)包含在最后运行的管道中,则它们会自动作为发布证据包含在发布中. + +尽管工作工件通常会过期,但发布证据中包含的工件不会过期. + +要启用作业工件收集,您需要同时指定两个: + +1. [`artifacts:paths`](../../../ci/yaml/README.html#artifactspaths) +2. [`artifacts:reports`](../../../ci/pipelines/job_artifacts.html#artifactsreports) + +``` +ruby: + script: + - gem install bundler + - bundle install + - bundle exec rspec --format progress --format RspecJunitFormatter --out rspec.xml + artifacts: + paths: + - rspec.xml + reports: + junit: rspec.xml +``` + +如果管道成功运行,则在创建发布时, `rspec.xml`文件将保存为发布证据. + +**注:**如果您[计划发布证据收集](#schedule-release-evidence-collection) ,则某些[证据](#schedule-release-evidence-collection)可能在证据收集时已经过期. 为了避免这种情况,可以使用[`artifacts:expire_in`](../../../ci/yaml/README.html#artifactsexpire_in)关键字. 了解更多在[这个问题上](https://gitlab.com/gitlab-org/gitlab/-/issues/222351) . + +### Schedule release evidence collection[](#schedule-release-evidence-collection "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23697) . + +在 API 中: + +* 如果您指定未来的`released_at`日期,则该发布将成为**即将发布的发布,**并且将在发布日期收集证据. 在此之前,您无法收集释放证据. +* 如果您使用过去的`released_at`日期,则不会收集任何证据. +* 如果您未指定`released_at`日期,则在创建发布的日期收集发布证据. + +### Disable release evidence display[](#disable-release-evidence-display-core-only "Permalink") + +`:release_evidence_collection`功能标志在 GitLab 自管理实例中默认启用. 要关闭它,请要求具有 Rails 控制台访问权限的 GitLab 管理员运行以下命令: + +``` +Feature.disable(:release_evidence_collection) +``` + +**注意:**无论使用此功能标志如何,都将收集发布证据,该标志仅启用或禁用"发布"页面上的数据显示. + +## GitLab Releaser[](#gitlab-releaser "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab-releaser/-/merge_requests/6) . + +GitLab Releaser 是一个 CLI 工具,用于从命令行或 GitLab 的 CI / CD 配置文件`.gitlab-ci.yml`管理 GitLab 版本. + +有了它,您可以直接通过终端创建,更新,修改和删除发行版. + +有关详细信息,请阅读[GitLab Releaser 文档](https://gitlab.com/gitlab-org/gitlab-releaser/-/tree/master/docs/index.md) . \ No newline at end of file diff --git a/docs/150.md b/docs/150.md new file mode 100644 index 0000000000000000000000000000000000000000..bb9052cbba9b98c5adf1492e58bfeb63c2a662ff --- /dev/null +++ b/docs/150.md @@ -0,0 +1,204 @@ +# Repository + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/](https://docs.gitlab.com/ee/user/project/repository/) + +* [Create a repository](#create-a-repository) +* [Files](#files) + * [Create and edit files](#create-and-edit-files) + * [Find files](#find-files) + * [Supported markup languages and extensions](#supported-markup-languages-and-extensions) + * [Repository README and index files](#repository-readme-and-index-files) + * [Jupyter Notebook files](#jupyter-notebook-files) + * [OpenAPI viewer](#openapi-viewer) +* [Branches](#branches) +* [Commits](#commits) +* [Project and repository size](#project-and-repository-size) +* [Contributors](#contributors) +* [Repository graph](#repository-graph) +* [Repository Languages](#repository-languages) +* [Locked files](#locked-files-premium) +* [Repository’s API](#repositorys-api) +* [Clone in Apple Xcode](#clone-in-apple-xcode) +* [Download Source Code](#download-source-code) + +# Repository[](#repository "Permalink") + +[存储库](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository)是用于将代码库存储在 GitLab 中并通过版本控制对其进行更改的存储库. 存储库是[项目的](../index.html)一部分,它具有许多其他功能. + +## Create a repository[](#create-a-repository "Permalink") + +要创建一个新的存储库,您需要做的就是[创建一个新项目](../../../gitlab-basics/create-project.html)或[创建](../../../gitlab-basics/create-project.html) [一个现有项目](forking_workflow.html) . + +创建新项目后,您可以通过 UI(请参阅以下部分)或通过命令行添加新文件. 要从命令行添加文件,请遵循创建新项目时在屏幕上显示的说明,或在[命令行基础](../../../gitlab-basics/start-using-git.html)文档中通读它们. + +> **重要提示:**出于安全原因,强烈建议您在使用命令行时[通过 SSH 与 GitLab 连接](../../../ssh/README.html) . + +## Files[](#files "Permalink") + +使用存储库将文件存储在 GitLab 中. 在[GitLab 12.10 及更高版本中](https://gitlab.com/gitlab-org/gitlab/-/issues/33806) ,您将在存储库的文件树中根据其扩展名在文件名旁边看到一个图标: + +[![Repository file icons](img/8489a6c45ad75964ea7b4b54b9d9fcaa.png)](img/file_ext_icons_repo_v12_10.png) + +### Create and edit files[](#create-and-edit-files "Permalink") + +通过将文件推送到 GitLab,将代码库托管在 GitLab 存储库中. 您可以使用用户界面(UI),也可以[通过命令行将](../../../gitlab-basics/command-line-commands.html#start-working-on-your-project)本地计算机与 GitLab 连接. + +要配置[GitLab CI / CD](../../../ci/README.html)来构建,测试和部署代码,请在存储库的根目录中添加一个名为[`.gitlab-ci.yml`](../../../ci/quick_start/README.html)的文件. + +**从用户界面:** + +GitLab 的用户界面允许您执行许多 Git 命令,而无需触摸命令行. 即使您定期使用命令行,有时[通过 GitLab UI](web_editor.html)也更容易做到: + +* [Create a file](web_editor.html#create-a-file) +* [Upload a file](web_editor.html#upload-a-file) +* [File templates](web_editor.html#template-dropdowns) +* [Create a directory](web_editor.html#create-a-directory) +* [Start a merge request](web_editor.html#tips) +* [Find file history](git_history.html) +* [Identify changes by line (Git blame)](git_blame.html) + +**在命令行中:** + +要开始使用命令行,请通读[命令行基础文档](../../../gitlab-basics/command-line-commands.html) . + +### Find files[](#find-files "Permalink") + +使用 GitLab 的[文件查找器](file_finder.html)在存储库中搜索文件. + +### Supported markup languages and extensions[](#supported-markup-languages-and-extensions "Permalink") + +GitLab 支持多种标记语言(有时称为[轻量标记语言](https://en.wikipedia.org/wiki/Lightweight_markup_language) ),您可以将其用于存储库中文件的内容. 它们主要用于文档目的. + +只需为文件选择正确的扩展名,GitLab 就会根据标记语言来渲染它们. + +| 标记语言 | Extensions | +| --- | --- | +| 纯文本 | `txt` | +| [Markdown](../../markdown.html) | `mdown`, `mkd`, `mkdn`, `md`, `markdown` | +| [reStructuredText](https://docutils.sourceforge.io/rst.html) | `rst` | +| [AsciiDoc](../../asciidoc.html) | `adoc`, `ad`, `asciidoc` | +| [Textile](https://textile-lang.com/) | `textile` | +| [rdoc](http://rdoc.sourceforge.net/doc/index.html) | `rdoc` | +| [Org mode](https://orgmode.org/) | `org` | +| [creole](http://www.wikicreole.org/) | `creole` | +| [MediaWiki](https://www.mediawiki.org/wiki/MediaWiki) | `wiki`, `mediawiki` | + +### Repository README and index files[](#repository-readme-and-index-files "Permalink") + +当存储库中存在`README`或`index`文件时,它的内容将由 GitLab 自动预渲染,而无需打开它. + +它们可以是纯文本,也可以具有[受支持的标记语言](#supported-markup-languages-and-extensions)的扩展名: + +有关优先级的一些注意事项: + +1. 当`README`文件和`index`文件同时存在时, `README`文件将始终优先. +2. 如果存在多个具有不同扩展名的文件,则按字母顺序排列,但不带扩展名的文件例外,该扩展名始终优先. 例如, `README.adoc`将优先于`README.md` ,而`README.rst`将优先于`README` . + +### Jupyter Notebook files[](#jupyter-notebook-files "Permalink") + +[Jupyter](https://jupyter.org/) Notebook(以前的 IPython Notebook)文件用于许多领域的交互式计算,并且包含用户会话的完整记录,并包括代码,叙述性文本,方程式和丰富的输出. + +[Read how to use Jupyter notebooks with GitLab.](jupyter_notebooks/index.html) + +### OpenAPI viewer[](#openapi-viewer "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/19515) . + +如果文件名包含`openapi`或`swagger`且扩展名为`yaml` , `yml`或`json` ,则 GitLab 可以使用其文件查看器呈现 OpenAPI 规范文件. 以下示例都是正确的: + +* `openapi.yml` +* `openapi.yaml` +* `openapi.json` +* `swagger.yml` +* `swagger.yaml` +* `swagger.json` +* `gitlab_swagger.yml` +* `openapi_gitlab.yml` +* `OpenAPI.YML` +* `openapi.Yaml` +* `openapi.JSON` +* `openapi.gitlab.yml` +* `gitlab.openapi.yml` + +然后,渲染它们: + +1. 在 GitLab 的用户界面中导航至存储库中的 OpenAPI 文件. +2. 单击位于"显示源"和"编辑"按钮之间的"显示 OpenAPI"按钮(找到 OpenAPI 文件后,它将替换"显示渲染的文件"按钮). + +## Branches[](#branches "Permalink") + +有关详细信息,请参见[分支](branches/index.html) . + +## Commits[](#commits "Permalink") + +[提交更改时](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository) ,您会将这些更改引入分支机构. 通过命令行,您可以在提交之前多次提交. + +* **提交消息:**提交消息对于标识正在更改的内容以及更重要的原因至关重要. 在 GitLab 中,您可以将关键字添加到提交消息中,以执行以下操作之一: + * **触发 GitLab CI / CD 管道:**如果您的项目配置有[GitLab CI / CD](../../../ci/README.html) ,则将在每次推送而不是每次提交时触发一个管道. + * **跳过管道:**您可以在提交消息中添加关键字[`[ci skip]`](../../../ci/yaml/README.html#skip-pipeline) ,GitLab CI / CD 将跳过该管道. + * **交叉链接问题和合并请求:** [交叉链接](../issues/crosslinking_issues.html#from-commit-messages)非常适合跟踪工作流程中与之相关的内容. 如果您在提交消息中提到问题或合并请求,它们将显示在各自的线程上. +* **樱桃选择提交:**在 GitLab 中,您可以直接从 UI [樱桃选择提交](../merge_requests/cherry_pick_changes.html#cherry-picking-a-commit) . +* **还原提交:**轻松[将提交](../merge_requests/revert_changes.html#reverting-a-commit)从 UI [还原](../merge_requests/revert_changes.html#reverting-a-commit)到所选分支. +* **签署提交:**使用 GPG [签署您的提交](gpg_signed_commits/index.html) . + +## Project and repository size[](#project-and-repository-size "Permalink") + +在项目的" **详细信息"**页面上报告项目的大小. 报告的大小最多每 15 分钟更新一次,因此可能无法反映最近的活动. 显示的文件大小包括存储库文件,工件和 LFS. + +由于压缩,内务处理和其他因素,每个项目的项目规模可能会略有不同. + +[储存库大小限制](../../admin_area/settings/account_and_limit_settings.html)可以由管理员设置. GitLab.com 的存储库大小限制[由 GitLab 设置](../../gitlab_com/index.html#repository-size-limit) . + +## Contributors[](#contributors "Permalink") + +代码库的所有贡献者都显示在项目的**设置>贡献者下** . + +它们是从协作者中以最少的提交次数排序的,并显示在一个漂亮的图形上: + +[![contributors to code](img/d69ab181c07176aa054b0ceac08b702c.png)](img/contributors_graph.png) + +## Repository graph[](#repository-graph "Permalink") + +存储库图形以可视方式显示存储网络的历史记录,包括分支和合并. 这可以帮助您可视化存储库中使用的 Git 流策略: + +[![repository Git flow](img/a1efb7c23a97e2901852465c9168914f.png)](img/repo_graph.png) + +在您项目的**Repository> Graph**下找到它. + +## Repository Languages[](#repository-languages "Permalink") + +对于每个存储库的默认分支,GitLab 将确定使用了哪种编程语言,并将其显示在项目页面上. 如果缺少此信息,将在更新项目上的默认分支后添加. 此过程最多可能需要 5 分钟. + +[![Repository Languages bar](img/e2e835cd5cd1be1afaa876fde2475fe5.png)](img/repository_languages_v12_2.gif) + +Not all files are detected, among others; documentation, vendored code, and most markup languages are excluded. This behavior can be adjusted by overriding the default. For example, to enable `.proto` files to be detected, add the following to `.gitattributes` in the root of your repository. + +``` +*.proto linguist-detectable=true +``` + +## Locked files[](#locked-files-premium "Permalink") + +使用[文件锁定](../file_lock.html)来锁定文件,以防止发生任何冲突的更改. + +## Repository’s API[](#repositorys-api "Permalink") + +您可以通过[存储库 API](../../../api/repositories.html)访问您的[存储库](../../../api/repositories.html) . + +## Clone in Apple Xcode[](#clone-in-apple-xcode "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45820) in GitLab 11.0 + +现在,可以使用位于用于克隆项目的 Git URL 旁边的新的" **在 Xcode 中打开"**按钮**在 Xcode 中**克隆包含`.xcodeproj`或`.xcworkspace`目录的项目. 该按钮仅在 macOS 上显示. + +## Download Source Code[](#download-source-code "Permalink") + +在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/24704)了对目录下载的支持. + +可以从 UI 下载存储在存储库中的源代码. 单击下载图标,将打开一个下拉列表,其中包含下载以下内容的链接: + +[![Download source code](img/0f88b0e1a49600472f2922218cec1ed7.png)](img/download_source_code.png) + +* **源代码:**允许用户在他们当前正在查看的分支上下载源代码. 可用扩展名: `zip` , `tar` , `tar.gz`和`tar.bz2` . +* **目录:**仅在查看子目录时显示. 这使用户可以下载他们当前正在查看的特定目录. 也可以在`zip` , `tar` , `tar.gz`和`tar.bz2` . +* **工件:**允许用户下载最新 CI 构建的工件. \ No newline at end of file diff --git a/docs/151.md b/docs/151.md new file mode 100644 index 0000000000000000000000000000000000000000..0c2f188d155035132b0d9ceafbb74f591076c762 --- /dev/null +++ b/docs/151.md @@ -0,0 +1,119 @@ +# Branches + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/branches/](https://docs.gitlab.com/ee/user/project/repository/branches/) + +* [Default branch](#default-branch) + * [Custom initial branch name](#custom-initial-branch-name-core-only) + * [Enable or disable custom initial branch name](#enable-or-disable-custom-initial-branch-name-core-only) +* [Compare](#compare) +* [Delete merged branches](#delete-merged-branches) +* [Branch filter search box](#branch-filter-search-box) + +# Branches[](#branches "Permalink") + +分支是项目工作树的版本. 您为所做的每组相关更改创建一个分支. 这样可以使每组更改彼此独立,从而可以并行进行更改,而不会互相影响. + +将更改推送到新分支后,您可以: + +* 创建[合并请求](../../merge_requests/index.html) +* 执行内联代码审查 +* 与团队[讨论](../../../discussions/index.html)实施情况 +* 使用[Review Apps](../../../../ci/review_apps/index.html)预览提交到新分支的更改. + +使用[GitLab Starter](https://about.gitlab.com/pricing/) ,您还可以请求经理的[批准](../../merge_requests/merge_request_approvals.html) . + +有关使用 GitLab UI 管理分支的更多信息,请参见: + +* [Default branches](#default-branch) +* [Create a branch](../web_editor.html#create-a-new-branch) +* [Protected branches](../../protected_branches.html#protected-branches) +* [Delete merged branches](#delete-merged-branches) +* [Branch filter search box](#branch-filter-search-box) + +您也可以使用[命令行](../../../../gitlab-basics/start-using-git.html#create-a-branch)管理分支. + +观看视频[GitLab Flow](https://www.youtube.com/watch?v=InKNIvky2KE) . + +也可以看看: + +* [Branches API](../../../../api/branches.html) ,有关使用 GitLab API 在存储库分支上进行操作的信息. +* [GitLab Flow](../../../../university/training/gitlab_flow.html) documentation. +* [Git](../../../../topics/git/index.html)和 GitLab [入门](../../../../topics/git/index.html) . + +## Default branch[](#default-branch "Permalink") + +创建新[项目时](../../index.html) ,GitLab 会将`master`设置为存储库的默认分支. 您可以在项目的**设置>存储库**下选择另一个分支作为项目的默认分支. + +通过[问题关闭模式](../../issues/managing_issues.html#closing-issues-automatically)直接从合并请求中[关闭问题时](../../issues/managing_issues.html#closing-issues-automatically) ,目标是项目的**默认分支** . + +初始还对默认分支进行了[保护,以](../../protected_branches.html#protected-branches)防止意外删除和强制推送. + +### Custom initial branch name[](#custom-initial-branch-name-core-only "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/221013) . +* 它部署在默认情况下启用的功能标志后面. +* 在 GitLab.com 上启用了它. +* 不能根据项目启用或禁用它. +* 建议用于生产. +* 对于 GitLab 自我管理的实例,GitLab 管理员可以选择[禁用它](#enable-or-disable-custom-initial-branch-name-core-only) . + +默认情况下,当您在 GitLab 中创建新项目时,初始分支称为`master` . 对于自我管理的实例,GitLab 管理员可以将初始分支名称自定义为其他名称. 这样,此后创建的每个新项目都将从自定义分支名称开始,而不是`master` . 为此: + +1. 转到 **在管理区域>设置>存储库中** ,展开**默认初始分支名称** . +2. 将默认的初始分支更改为您选择的自定义名称. +3. **保存更改**. + +#### Enable or disable custom initial branch name[](#enable-or-disable-custom-initial-branch-name-core-only "Permalink") + +正在设置默认的初始分支名称,但已准备好用于生产. 它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../../administration/feature_flags.html)可以选择为您的实例禁用它. + +禁用它: + +``` +Feature.disable(:global_default_branch_name) +``` + +要启用它: + +``` +Feature.enable(:global_default_branch_name) +``` + +## Compare[](#compare "Permalink") + +要比较存储库中的分支: + +1. 导航到项目的存储库. +2. 在边栏中选择**存储库>比较** . +3. 使用[分支过滤器搜索框](#branch-filter-search-box)选择要比较的[分支](#branch-filter-search-box) +4. 单击" **比较** "以内联查看更改: + +[![compare branches](img/b4e4d114d9b2244a7848961617e05a95.png)](img/compare_branches.png) + +## Delete merged branches[](#delete-merged-branches "Permalink") + +在 GitLab 8.14 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6449) . + +[![Delete merged branches](img/6de450be845a1f48a3feae9ce8e7be6e.png)](img/delete_merged_branches.png) + +此功能允许合并的分支被批量删除. 作为此操作的一部分,只有已合并[但未受保护的](../../protected_branches.html)分支才会被删除. + +清理合并请求时未自动删除的旧分支尤其有用. + +## Branch filter search box[](#branch-filter-search-box "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22166) . + +[![Branch filter search box](img/f380fbb3646558d8becf561df5894c38.png)](img/branch_filter_search_box.png) + +此功能使您可以快速搜索和选择分支. 搜索结果按以下顺序显示: + +* 名称与搜索字词完全匹配的分支. +* 名称包含搜索词的其他分支,按字母顺序排序. + +有时,当您有数百个分支时,可能需要更灵活的匹配模式. 在这种情况下,您可以使用以下方法: + +* `^feature`将仅匹配以'feature'开头的分支名称. +* `feature$` will only match branch names that end with ‘feature’. \ No newline at end of file diff --git a/docs/152.md b/docs/152.md new file mode 100644 index 0000000000000000000000000000000000000000..d46ae9f9abea42d8b8c05327e7e7cfe5dd60aa06 --- /dev/null +++ b/docs/152.md @@ -0,0 +1,20 @@ +# Git Attributes + +> 原文:[https://docs.gitlab.com/ee/user/project/git_attributes.html](https://docs.gitlab.com/ee/user/project/git_attributes.html) + +* [Encoding Requirements](#encoding-requirements) +* [Syntax Highlighting](#syntax-highlighting) + +# Git Attributes[](#git-attributes "Permalink") + +GitLab 支持定义自定义[Git 属性,](https://git-scm.com/docs/gitattributes)例如将哪些文件视为二进制文件,以及将哪种语言用于语法突出显示差异. + +要定义这些属性, `.gitattributes`在存储库的根目录中创建一个名为`.gitattributes`的文件,并将其推送到项目的默认分支. + +## Encoding Requirements[](#encoding-requirements "Permalink") + +`.gitattributes`文件*必须*使用 UTF-8 编码,并且*不能*包含字节顺序标记. 如果使用其他编码,则文件的内容将被忽略. + +## Syntax Highlighting[](#syntax-highlighting "Permalink") + +`.gitattributes`文件可用于定义语法高亮显示文件和差异时使用的语言. 有关更多信息,请参见["语法突出显示"](highlighting.html) . \ No newline at end of file diff --git a/docs/153.md b/docs/153.md new file mode 100644 index 0000000000000000000000000000000000000000..6df9d56230e589714f739dfeb61598e2e784f2b7 --- /dev/null +++ b/docs/153.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/administration/lfs/manage_large_binaries_with_git_lfs.html](https://docs.gitlab.com/ee/administration/lfs/manage_large_binaries_with_git_lfs.html) \ No newline at end of file diff --git a/docs/154.md b/docs/154.md new file mode 100644 index 0000000000000000000000000000000000000000..057c070dcfc16d2838975d636faae1f9b5146f89 --- /dev/null +++ b/docs/154.md @@ -0,0 +1,86 @@ +# File Locking + +> 原文:[https://docs.gitlab.com/ee/user/project/file_lock.html](https://docs.gitlab.com/ee/user/project/file_lock.html) + +* [Overview](#overview) +* [Use-cases](#use-cases) +* [Locking a file or a directory](#locking-a-file-or-a-directory) +* [Unlocking a file or a directory](#unlocking-a-file-or-a-directory) +* [Viewing and managing existing locks](#viewing-and-managing-existing-locks) +* [Permissions on file locking](#permissions-on-file-locking) + +# File Locking[](#file-locking-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/440) in [GitLab Premium](https://about.gitlab.com/pricing/) 8.9. + +与多个人一起使用同一文件可能会带来风险. 合并非文本文件时的冲突很难克服,将需要大量的手动工作来解决. 文件锁定可帮助您避免这些合并冲突并更好地管理二进制文件. + +使用文件锁定,您可以锁定任何文件或目录,进行更改,然后将其解锁,以便团队的其他成员可以对其进行编辑. + +## Overview[](#overview "Permalink") + +与多个人一起使用同一文件可能会带来风险. 合并非文本文件时的冲突很难克服,将需要大量的手动工作来解决. 借助 GitLab Premium,文件锁定可防止他人(您除外)修改特定文件或整个目录,从而帮助您避免合并冲突并更好地管理二进制文件. + +## Use-cases[](#use-cases "Permalink") + +在以下情况下,文件锁定功能很有用: + +* 多个人正在同一个文件上,您要避免合并冲突. +* 您的存储库包含二进制文件,在这种情况下,没有简单的方法来告诉您与同事的更改之间的区别. +* 防止设计资产被覆盖. + +Locked directories are locked recursively, which means that everything that lies under them is also locked. + +## Locking a file or a directory[](#locking-a-file-or-a-directory "Permalink") + +**注意:**锁定仅适用于您在项目设置中设置的默认分支(通常是`master` ). + +锁定文件: + +1. 导航到项目的" **存储库">"文件"** . +2. 选择您要锁定的文件. +3. 点击"锁定"按钮. + + [![Locking file](img/2f8e418a69825e31935272d55cceae7f.png)](img/file_lock.png) + +要锁定整个目录,请在"历史记录"旁边查找"锁定"链接. + +锁定文件或目录后,它在存储库视图中将显示为已锁定. + +[![Repository view](img/0574a3e535157d8b9c5744214f19f7c7.png)](img/file_lock_repository_view.png) + +一旦锁定,对默认分支的任何合并请求将无法合并,直到文件被解锁. + +## Unlocking a file or a directory[](#unlocking-a-file-or-a-directory "Permalink") + +要解锁文件或目录,请遵循与锁定文件或目录相同的步骤. 有关每个现有锁的详细视图,请参阅下一节"查看和管理现有锁". + +您可以解锁自己或其他人先前锁定的文件,只要您对该项目具有"维护者"或更高[权限](../permissions.html) . + +## Viewing and managing existing locks[](#viewing-and-managing-existing-locks "Permalink") + +要查看或管理每个现有锁,请导航至" **项目">"存储库">"锁定文件"**区域. 在这里,您可以查看所有现有的锁,并[删除您拥有权限的](#permissions-on-file-locking)锁. + +## Permissions on file locking[](#permissions-on-file-locking "Permalink") + +锁定文件或目录的用户**是唯一**可以编辑并将其更改推回锁定对象所在存储库的用户. + +可以对存储库进行[推送访问](../permissions.html)的任何人都可以创建锁. 即开发人员和更高级别的人员,并且只能由其作者和具有维护者权限及更高权限的任何用户删除. + +如果文件被锁定并且您不是其锁定状态的作者,则在尝试推送时,预接收挂钩将拒绝您的更改. 在以下示例中,对锁定的`.gitignore`文件没有权限的用户将看到以下消息: + +``` +Counting objects: 3, done. +Delta compression using up to 4 threads. +Compressing objects: 100% (3/3), done. +Writing objects: 100% (3/3), 320 bytes | 0 bytes/s, done. +Total 3 (delta 1), reused 0 (delta 0) +remote: GitLab: The path '.gitignore' is locked by Administrator +To https://example.com/gitlab-org/gitlab-foss.git + ! [remote rejected] master -> master (pre-receive hook declined) + error: failed to push some refs to 'https://example.com/gitlab-org/gitlab-foss.git' +``` + +同样,当不是文件锁定状态作者的用户接受合并请求时,将出现一条错误消息,指出文件已锁定. + +[![Merge request error message](img/7a5c28bfcfa2942d75aaace7ccb281ce.png)](img/file_lock_merge_request_error_message.png) \ No newline at end of file diff --git a/docs/155.md b/docs/155.md new file mode 100644 index 0000000000000000000000000000000000000000..e5b6ce4357404ddf2b6ad65d29fe0b0ae810904d --- /dev/null +++ b/docs/155.md @@ -0,0 +1,54 @@ +# Git file blame + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/git_blame.html](https://docs.gitlab.com/ee/user/project/repository/git_blame.html) + +* [Blame previous commit](#blame-previous-commit) +* [Associated `git` command](#associated-git-command) +* [File blame through the API](#file-blame-through-the-api) + +# Git file blame[](#git-file-blame "Permalink") + +在 GitLab 2.5 中[引入](https://git.sphere.ly/staff/publicgitlab/commit/39c657930625ddc3ac8a921f01ffc83acadce68f) + +[Git blame](https://git-scm.com/docs/git-blame)提供有关文件中每一行的更多信息,包括最后修改时间,作者和提交哈希. + +您可以在项目中的每个文件中找到" **责备"**按钮. + +[![File blame button](img/1427a32ce32914c8100f7563817e3d64.png "Blame button")](img/file_blame_button_v12_6.png) + +选择" **责备"**按钮时,您会看到一个带有说明信息的屏幕: + +[![Git blame output](img/4a7c845c8d7b28d90af5923b08fb1e1d.png "Blame button output")](img/file_blame_output_v12_6.png) + +如果将鼠标悬停在 UI 中的提交上,您将看到该提交的确切日期和时间. + +## Blame previous commit[](#blame-previous-commit "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/19299) . + +要查看特定行的早期修订,请**在此更改**之前单击" **查看责备",**直到找到您有兴趣查看的**更改**为止: + +[![Blame previous commit](img/dc12d72310a7e06d2981fd6774b0903d.png "Blame previous commit")](img/file_blame_previous_commit_v12_7.png) + +## Associated `git` command[](#associated-git-command "Permalink") + +如果从命令行运行`git` ,则等效命令为`git blame <filename>` . 例如,如果你想找到`blame`有关信息`README.md`在本地目录中的文件,运行以下命令: + +``` +git blame README.md +``` + +您将看到类似于以下内容的输出,其中包括 UTC 格式的提交时间: + +``` +62e2353a (Achilleas Pipinellis 2019-07-11 14:52:18 +0300 1) [![build status](https://gitlab.com/gitlab-org/gitlab-docs/badges/master/build.svg)](https://gitlab.com/gitlab-com/gitlab-docs/commits/master) +fb0fc7d6 (Achilleas Pipinellis 2016-11-07 22:21:22 +0100 2) +^764ca75 (Connor Shea 2016-10-05 23:40:24 -0600 3) # GitLab Documentation +^764ca75 (Connor Shea 2016-10-05 23:40:24 -0600 4) +0e62ed6d (Mike Jang 2019-11-26 21:44:53 +0000 5) This project hosts the repository used to generate the GitLab +0e62ed6d (Mike Jang 2019-11-26 21:44:53 +0000 6) documentation website and deployed to https://docs.gitlab.com. It uses the +``` + +## File blame through the API[](#file-blame-through-the-api "Permalink") + +您也可以通过[Git 文件指责 REST API](../../../api/repository_files.html#get-file-blame-from-repository)来获取此信息. \ No newline at end of file diff --git a/docs/156.md b/docs/156.md new file mode 100644 index 0000000000000000000000000000000000000000..cd1ef819a7ae4d9b3301da08a4af85cc11c4f22c --- /dev/null +++ b/docs/156.md @@ -0,0 +1,61 @@ +# Git file history + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/git_history.html](https://docs.gitlab.com/ee/user/project/repository/git_history.html) + +* [Associated `git` command](#associated-git-command) + +# Git file history[](#git-file-history "Permalink") + +在 GitLab 0.8.0 中[引入](https://gitlab.com/gitlab-org/gitlab/blob/9ba1224867665844b117fa037e1465bb706b3685/app/controllers/commits_controller.rb) + +Git 文件历史记录提供有关与文件关联的提交历史记录的信息. + +您可以在项目中的每个文件中找到" **历史记录"**按钮. + +[![File history button](img/4b803fd891a7ec7f422522d2ff185864.png "History button")](img/file_history_button_v12_6.png) + +当选择" **历史记录"**按钮时,您将看到一个带有说明信息的屏幕: + +[![Git log output](img/0dad61d266449688c931d1703509bca3.png "History button output")](img/file_history_output_v12_6.png) + +如果将鼠标悬停在 UI 中的提交上,您将看到上次修改提交的确切日期和时间. + +## Associated `git` command[](#associated-git-command "Permalink") + +如果从命令行运行`git` ,则等效命令为`git log <filename>` . 例如,如果要在本地目录中找到有关`README.md`文件的`history`信息,请运行以下命令: + +``` +git log README.md +``` + +您将看到类似于以下内容的输出,其中包括 UTC 格式的提交时间: + +``` +commit 0e62ed6d9f39fa9bedf7efc6edd628b137fa781a +Author: Mike Jang <mjang@gitlab.com> +Date: Tue Nov 26 21:44:53 2019 +0000 + + Deemphasize GDK as a doc build tool + +commit 418879420b1e3a4662067bd07b64bb6988654697 +Author: Marcin Sedlak-Jakubowski <msedlakjakubowski@gitlab.com> +Date: Mon Nov 4 19:58:27 2019 +0100 + + Fix typo + +commit 21cc1fef11349417ed515557748369cfb235fc81 +Author: Jacques Erasmus <jerasmus@gitlab.com> +Date: Mon Oct 14 22:13:40 2019 +0000 + + Add support for modern JS + + Added rollup to the project + +commit 2f5e895aebfa5678e51db303b97de56c51e3cebe +Author: Achilleas Pipinellis <axil@gitlab.com> +Date: Fri Sep 13 14:03:01 2019 +0000 + + Remove gitlab-foss Git URLs as we don't need them anymore + + [ci skip] +``` \ No newline at end of file diff --git a/docs/157.md b/docs/157.md new file mode 100644 index 0000000000000000000000000000000000000000..cd825fadbcb512c640eef9a8781fd8f97848a748 --- /dev/null +++ b/docs/157.md @@ -0,0 +1,429 @@ +# Repository mirroring + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/repository_mirroring.html](https://docs.gitlab.com/ee/user/project/repository/repository_mirroring.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Pushing to a remote repository](#pushing-to-a-remote-repository-core) + * [Configuring push mirrors through the API](#configuring-push-mirrors-through-the-api) + * [Push only protected branches](#push-only-protected-branches-core) + * [Keep divergent refs](#keep-divergent-refs-core) +* [Setting up a push mirror from GitLab to GitHub](#setting-up-a-push-mirror-from-gitlab-to-github-core) +* [Setting up a push mirror to another GitLab instance with 2FA activated](#setting-up-a-push-mirror-to-another-gitlab-instance-with-2fa-activated) +* [Pulling from a remote repository](#pulling-from-a-remote-repository-starter) + * [How it works](#how-it-works) + * [SSH authentication](#ssh-authentication) + * [SSH public key authentication](#ssh-public-key-authentication) + * [Overwrite diverged branches](#overwrite-diverged-branches-starter) + * [Only mirror protected branches](#only-mirror-protected-branches-starter) + * [Hard failure](#hard-failure-starter) + * [Trigger update using API](#trigger-update-using-api-starter) +* [Forcing an update](#forcing-an-update-core) +* [Bidirectional mirroring](#bidirectional-mirroring-starter) + * [Configure a webhook to trigger an immediate pull to GitLab](#configure-a-webhook-to-trigger-an-immediate-pull-to-gitlab) + * [Preventing conflicts using a `pre-receive` hook](#preventing-conflicts-using-a-pre-receive-hook) + * [Mirroring with Perforce Helix via Git Fusion](#mirroring-with-perforce-helix-via-git-fusion-starter) +* [Troubleshooting](#troubleshooting) + * [13:Received RST_STREAM with error code 2 with GitHub](#13received-rst_stream-with-error-code-2-with-github) + +# Repository mirroring[](#repository-mirroring "Permalink") + +存储库镜像允许将存储库镜像到外部源或从外部源镜像. 它可用于镜像存储库之间的分支,标签和提交. + +GitLab 上的存储库镜像将自动更新. 您也可以最多每 5 分钟手动触发一次更新. + +## Overview[](#overview "Permalink") + +当您想在 GitLab 之外使用存储库时,存储库镜像很有用. + +GitLab 支持两种存储库镜像: + +* 推送:用于将 GitLab 存储库镜像到另一个位置. +* Pull: for mirroring a repository from another location to GitLab. + +镜像存储库更新后,所有新的分支,标记和提交将在项目的活动提要中可见. + +至少具有[开发人员访问](../../permissions.html)项目[权限](../../permissions.html)的用户也可以强制立即更新,除非: + +* 镜像已被更新. +* 自上次更新以来,还没有过去 5 分钟. + +出于安全原因,在[GitLab 12.10 和更高版本中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27166) ,原始存储库的 URL 仅显示给对镜像项目具有维护者或所有者权限的用户. + +## Use cases[](#use-cases "Permalink") + +以下是存储库镜像的一些可能的用例: + +* 您迁移到了 GitLab,但仍需要将项目保留在另一个源中. 在这种情况下,您只需将其设置为镜像到 GitLab(拉),所有提交,标签和分支的基本历史记录都将在您的 GitLab 实例中提供. +* 您在另一个源中有旧项目,这些旧项目不再使用,但又不想出于归档目的而删除它们. 在这种情况下,您可以创建一个推送镜像,以便您的活动 GitLab 存储库可以将其更改推送到旧位置. + +## Pushing to a remote repository[](#pushing-to-a-remote-repository-core "Permalink") + +版本历史 + +* 在 GitLab 企业版 8.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/249) . +* 在 10.8 版中[移至 GitLab Core](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18715) . + +对于现有项目,可以按如下所示设置推送镜像: + +1. 导航到项目的**"设置">"存储库",**然后展开" **镜像存储库"**部分. +2. 输入存储库 URL. +3. 从**镜像方向**下拉菜单中选择**推送** . +4. 如有必要,请从" **身份验证方法"**下拉列表中选择一种身份**验证方法** . +5. 如有必要,请选中**仅镜像保护的分支**框. +6. 如果需要, **请**选中" **保持差异引用"**框. +7. 单击**镜像存储库**按钮以保存配置. + +[![Repository mirroring push settings screen](img/d67d5681f30c4769c6d92232eada26e4.png)](img/repository_mirroring_push_settings.png) + +启用推送镜像后,只有推送会直接提交到镜像存储库,以防止镜像发散. 任何时候,所有更改都将最终存储在镜像存储库中: + +* 提交被推送到 GitLab. +* [强制更新](#forcing-an-update-core)已启动. + +推送到存储库中文件的更改至少会自动推送到远程镜像: + +* 收到后五分钟内. +* 如果启用了**仅受镜像保护的分支,**则在一分钟之内. + +如果分支分支不同,您将在" **镜像存储库"**部分看到指示的错误. + +### Configuring push mirrors through the API[](#configuring-push-mirrors-through-the-api "Permalink") + +您还可以通过[远程镜像 API](../../../api/remote_mirrors.html)创建和修改项目推送镜像. + +### Push only protected branches[](#push-only-protected-branches-core "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 10.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3350) . +* 在 10.8 版中[移至 GitLab Core](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18715) . + +您可以选择仅将受保护的分支从 GitLab 推送到远程存储库. + +要使用此选项,请在创建存储库镜像时选中" **仅镜像保护的分支"**框. + +### Keep divergent refs[](#keep-divergent-refs-core "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/208828) . + +默认情况下,如果远程镜像上的任何引用都与本地存储库不同,则*整个推送*将失败,并且不会更新任何内容. + +例如,如果存储库具有已镜像到远程的`master` , `develop`和`stable`分支,然后添加新提交以在镜像上进行`develop` ,则下一次推送尝试将失败,从而使`master`和`stable`不在可用范围内约会尽管没有分歧. 在解决分歧之前,无法反映任何分支上的更改. + +启用" **保持差异引用"**选项后,将跳过`develop`分支,从而可以更新`master`和`stable` . 镜像状态将反映`develop`已偏离并被跳过,并标记为更新失败. + +**注意:**创建镜像后,当前只能通过[API](../../../api/remote_mirrors.html)修改此选项. + +## Setting up a push mirror from GitLab to GitHub[](#setting-up-a-push-mirror-from-gitlab-to-github-core "Permalink") + +要设置从 GitLab 到 GitHub 的镜像,您需要执行以下步骤: + +1. 创建一个[GitHub 个人访问令牌](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) ,并选中`public_repo`框. +2. 使用以下格式填写**Git 存储库 URL**字段: `https://<your_github_username>@github.com/<your_github_group>/<your_github_project>.git` . +3. 使用您的 GitHub 个人访问令牌填写**密码**字段. +4. 单击**镜像存储库**按钮. + +镜像的存储库将被列出. 例如, `https://*****:*****@github.com/<your_github_group>/<your_github_project>.git` . + +该存储库将很快推送. 要强制按下,请单击适当的按钮. + +## Setting up a push mirror to another GitLab instance with 2FA activated[](#setting-up-a-push-mirror-to-another-gitlab-instance-with-2fa-activated "Permalink") + +1. 在目标 GitLab 实例上,创建一个具有`write_repository`范围的[个人访问令牌](../../profile/personal_access_tokens.html) . +2. 在源 GitLab 实例上: + 1. 使用以下格式填写**Git 存储库 URL**字段: `https://oauth2@<destination host>/<your_gitlab_group_or_name>/<your_gitlab_project>.git` . + 2. 在目标 GitLab 实例上创建的 GitLab 个人访问令牌中填写**密码**字段. + 3. 单击**镜像存储库**按钮. + +## Pulling from a remote repository[](#pulling-from-a-remote-repository-starter "Permalink") + +版本历史 + +* 在 GitLab 企业版 8.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51) . +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 11.11 中[添加了 Git LFS 支持](https://gitlab.com/gitlab-org/gitlab/-/issues/10871) . + +您可以将存储库设置为自动从上游存储库更新其分支,标记和提交. + +当您感兴趣的存储库位于其他服务器上并且您希望能够使用熟悉的 GitLab 界面浏览其内容和活动时,此功能很有用. + +要为现有项目配置镜像拉出: + +1. Navigate to your project’s **设置>存储库** and expand the **镜像存储库** section. +2. 输入存储库 URL. +3. 从**镜像方向**下拉菜单中选择**拉** . +4. 如有必要,请从" **身份验证方法"**下拉列表中选择一种身份**验证方法** . +5. 如有必要,请选中以下框: + * **覆盖分散的分支** . + * **触发管道以更新镜像** . + * **仅镜像保护的分支** . +6. 单击**镜像存储库**按钮以保存配置. + +[![Repository mirroring pull settings screen - upper part](img/5881da97228cb042e5934f836edfd06c.png)](img/repository_mirroring_pull_settings_upper.png) + +* * * + +[![Repository mirroring pull settings screen - lower part](img/d5df9e77d389b58908ef235600ccc61c.png)](img/repository_mirroring_pull_settings_lower.png) + +Because GitLab is now set to pull changes from the upstream repository, you should not push commits directly to the repository on GitLab. Instead, any commits should be pushed to the upstream repository. Changes pushed to the upstream repository will be pulled into the GitLab repository, either: + +* 在一定时间内自动. +* 启动[强制更新时](#forcing-an-update-core) . + +**警告:**如果您确实在 GitLab 存储库中更新了分支,则该分支将与上游分叉,并且 GitLab 将不再自动更新该分支以防止丢失任何更改. 另请注意,上游存储库中已删除的分支和标签将不会反映在 GitLab 存储库中. + +### How it works[](#how-it-works "Permalink") + +为存储库启用拉镜像功能后,会将存储库添加到队列中. + +每分钟一次,Sidekiq cron 作业基于以下内容计划存储库镜像的更新: + +* 可用容量. 这由 Sidekiq 设置确定. 对于 GitLab.com,请参阅[GitLab.com Sidekiq 设置](../../gitlab_com/index.html#sidekiq) . +* 队列中已经要更新的存储库镜像数. 到期时间取决于存储库镜像的最后更新时间以及重试次数. + +随着 Sidekiq 可以处理存储库镜像,它们也会更新. 如果更新存储库镜像的过程为: + +* 成功后,至少需要等待 30 分钟,更新才会重新加入队列. +* 失败(例如,分支从上游分支),稍后将再次尝试. 镜像最多可以发生 14 次故障,然后才不会再次进入队列进行更新. + +### SSH authentication[](#ssh-authentication "Permalink") + +> * 在[GitLab Starter](https://about.gitlab.com/pricing/) 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2551)了拉镜像. +> * 在[GitLab Core](https://about.gitlab.com/pricing/) 11.6 中为推送镜像[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22982) + +SSH 身份验证是相互的: + +* 您必须向服务器证明您有权访问存储库. +* 服务器还必须向*您*证明它是谁. + +您提供凭据作为密码或公共密钥. 另一个存储库所在的服务器提供其凭据作为"主机密钥",其指纹需要手动验证. + +如果您通过 SSH 镜像(即使用`ssh://` URL),则可以使用以下方法进行身份验证: + +* 基于密码的身份验证,就像通过 HTTPS 一样. +* 公钥认证. 这通常比密码身份验证更安全,尤其是当其他存储库支持[Deploy Keys 时](../../../ssh/README.html#deploy-keys) . + +开始: + +1. 导航到项目的**"设置">"存储库",**然后展开" **镜像存储库"**部分. +2. 输入`ssh://` URL 进行镜像. + +**注意:**目前不支持 SCP 样式的 URL(即`git@example.com:group/project.git` ). + +输入 URL 在页面上添加两个按钮: + +* **检测主机密钥**. +* **手动输入主机密钥**. + +如果单击: + +* **检测主机密钥**按钮,GitLab 将从服务器获取主机密钥并显示指纹. +* **手动输入主机密钥**按钮,将显示一个字段,您可以在其中粘贴主机密钥. + +假设您使用了前者,那么现在需要验证指纹是否符合您的期望. GitLab.com 和其他代码托管站点公开公开其指纹,供您检查: + +* [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/regions.html#regions-fingerprints) +* [Bitbucket](https://support.atlassian.com/bitbucket-cloud/docs/configure-ssh-and-two-step-verification/) +* [GitHub](https://help.github.com/en/github/authenticating-to-github/githubs-ssh-key-fingerprints) +* [GitLab.com](../../gitlab_com/index.html#ssh-host-keys-fingerprints) +* [Launchpad](https://help.launchpad.net/SSHFingerprints) +* [Savannah](http://savannah.gnu.org/maintenance/SshAccess/) +* [SourceForge](https://sourceforge.net/p/forge/documentation/SSH%20Key%20Fingerprints/) + +其他提供者将有所不同. 如果您正在运行自我管理的 GitLab,或者可以访问其他存储库的服务器,则可以安全地收集密钥指纹: + +``` +$ cat /etc/ssh/ssh_host*pub | ssh-keygen -E md5 -l -f - +256 MD5:f4:28:9f:23:99:15:21:1b:bf:ed:1f:8e:a0:76:b2:9d root@example.com (ECDSA) +256 MD5:e6:eb:45:8a:3c:59:35:5f:e9:5b:80:12:be:7e:22:73 root@example.com (ED25519) +2048 MD5:3f:72:be:3d:62:03:5c:62:83:e8:6e:14:34:3a:85:1d root@example.com (RSA) +``` + +**注意:**对于某些旧版本的 SSH,可能需要排除`-E md5` . + +在镜像存储库时,GitLab 现在将在连接之前检查至少一个存储的主机密钥是否匹配. 这样可以防止将恶意代码注入到您的镜像中,或者防止您的密码被盗. + +### SSH public key authentication[](#ssh-public-key-authentication "Permalink") + +要使用 SSH 公钥身份验证,您还需要从**Authentication method**下拉菜单中选择该选项. 创建镜像后,GitLab 会生成一个 4096 位 RSA 密钥,可以通过单击" **复制 SSH"公共密钥**按钮进行复制. + +[![Repository mirroring copy SSH public key to clipboard button](img/c1e086b58ff99dd5c5684a4571e568e3.png)](img/repository_mirroring_copy_ssh_public_key_button.png) + +然后,您需要将公共 SSH 密钥添加到另一个存储库的配置中: + +* 如果其他存储库托管在 GitLab 上,则应将公共 SSH 密钥添加为[Deploy Key](../../../ssh/README.html#deploy-keys) . +* 如果其他存储库位于其他位置,则可能需要将密钥添加到用户的`authorized_keys`文件中. 将整个公共 SSH 密钥单独粘贴到文件中并保存. + +如果您需要随时更改密钥,则可以删除并重新添加镜像以生成新密钥. 您必须使用新密钥更新另一个存储库,以保持镜像运行. + +**注意:**生成的密钥存储在 GitLab 数据库中,而不存储在文件系统中. 因此,无法在预接收挂钩中使用针对镜像的 SSH 公钥身份验证. + +### Overwrite diverged branches[](#overwrite-diverged-branches-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4559) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. + +您可以选择始终使用远程版本更新本地分支,即使它们与远程分支不同. + +**警告:**对于镜像分支,启用此选项会导致丢失本地更改. + +要使用此选项,请在创建存储库镜像时选中" **覆盖分支分支"**框. + +### Only mirror protected branches[](#only-mirror-protected-branches-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3326) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3. + +您可以选择仅将受保护的分支从远程存储库拉到 GitLab. 未受保护的分支不会被镜像,并且可能会分开. + +要使用此选项,请在创建存储库镜像时选中" **仅镜像保护的分支"**框. + +### Hard failure[](#hard-failure-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3117) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2. + +如果镜像过程连续 14 次失败重试,它将被标记为硬盘失败. 这将在以下任一位置中可见: + +* 项目的主要仪表板. +* 拉镜设置页面. + +当一个项目很难失败时,它将不再需要进行镜像. 用户可以通过[强制更新来](#forcing-an-update-core)再次恢复项目镜像. + +### Trigger update using API[](#trigger-update-using-api-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3453) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3. + +拉镜像使用轮询来检测新添加的分支和提交,通常是在几分钟后. 如果您通过[API](../../../api/projects.html#start-the-pull-mirroring-process-for-a-project-starter)通知 GitLab,更新将立即被拉出. + +有关更多信息,请参阅[启动项目的拉镜像过程](../../../api/projects.html#start-the-pull-mirroring-process-for-a-project-starter) . + +## Forcing an update[](#forcing-an-update-core "Permalink") + +当计划将镜像自动更新时,您始终可以使用" **存储** **库设置"**页面的" **镜像存储库"**部分上的"更新"按钮强制进行更新. + +[![Repository mirroring force update user interface](img/a6e9b62f94c53cd2f37f7300362137a9.png)](img/repository_mirroring_force_update.png) + +## Bidirectional mirroring[](#bidirectional-mirroring-starter "Permalink") + +**注意:**双向镜像可能会导致冲突. + +如果您将 GitLab 存储库配置为从同一远程源中拉出和推送到同一远程源,则不能保证这两个存储库都将正确更新. 如果为双向镜像设置存储库,则应通过确定谁将解决它们以及如何解决它们来为可能的冲突做准备. + +重写任一远程上的任何镜像提交将导致冲突,并且镜像失败. 可以通过以下方法防止此情况: + +* [Pulling only protected branches](#only-mirror-protected-branches-starter). +* [Pushing only protected branches](#push-only-protected-branches-core). + +您应该[保护](../protected_branches.html)希望在两个远程控制器上镜像[的分支](../protected_branches.html) ,以防止由于重写历史记录而引起的冲突. + +双向镜像还会创建竞态条件,在这种竞态条件中,靠近同一分支的提交会引起冲突. 通过使用[Push 事件 Webhook](../integrations/webhooks.html#push-events)触发立即拉到 GitLab,可以通过减少镜像延迟来缓解竞争状况. 当仅推送镜像受保护的分支时,来自 GitLab 的推送镜像的速率限制为每分钟一次. + +### Configure a webhook to trigger an immediate pull to GitLab[](#configure-a-webhook-to-trigger-an-immediate-pull-to-gitlab "Permalink") + +假设您已经在上游 GitLab 实例中配置了[推](#setting-up-a-push-mirror-to-another-gitlab-instance-with-2fa-activated)和[拉](#pulling-from-a-remote-repository-starter)镜像,以触发如上所述的立即提拉,则需要在下游实例中配置一个[推事件 Web 挂钩](../integrations/webhooks.html#push-events) . + +去做这个: + +* 创建具有`API`范围的[个人访问令牌](../../profile/personal_access_tokens.html) . +* 导航到**设置> Webhooks** +* 添加 webhook URL,在这种情况下,它将在存储库更新后使用[Pull Mirror API](../../../api/projects.html#start-the-pull-mirroring-process-for-a-project-starter)请求触发即时提取. + + ``` + https://gitlab.example.com/api/v4/projects/:id/mirror/pull?private_token=<your_access_token> + ``` + +* 确保已选中" **推送事件"**复选框. +* 单击**添加 Webhook**按钮以保存**Webhook** . +* 要测试集成,请单击" **测试"**按钮,并确认 GitLab 不返回任何错误. + +### Preventing conflicts using a `pre-receive` hook[](#preventing-conflicts-using-a-pre-receive-hook "Permalink") + +**警告:**提议的解决方案将对 Git 推送操作的性能产生负面影响,因为它们将被代理到上游 Git 存储库. + +服务器端`pre-receive`挂钩可通过仅在将提交首先推送到上游 Git 存储库之后才接受推送来防止上述竞争情况. 在此配置中,一个 Git 存储库充当权威的上游,另一个充当下游. `pre-receive`挂钩将安装在下游存储库中. + +阅读有关在 GitLab 服务器上[配置服务器挂钩](../../../administration/server_hooks.html)的信息. + +下面提供了一个样品`pre-receive`挂钩. + +``` +#!/usr/bin/env bash + +# --- Assume only one push mirror target +# Push mirroring remotes are named `remote_mirror_<id>`, this finds the first remote and uses that. +TARGET_REPO=$(git remote | grep -m 1 remote_mirror) + +proxy_push() +{ + # --- Arguments + OLDREV=$(git rev-parse $1) + NEWREV=$(git rev-parse $2) + REFNAME="$3" + + # --- Pattern of branches to proxy pushes + allowlist=$(expr "$branch" : "\(master\)") + + case "$refname" in refs/heads/*) + branch=$(expr "$refname" : "refs/heads/\(.*\)") + + if [ "$allowlist" = "$branch" ]; then unset GIT_QUARANTINE_PATH # handle https://git-scm.com/docs/git-receive-pack#_quarantine_environment + error="$(git push --quiet $TARGET_REPO $NEWREV:$REFNAME 2>&1)" + fail=$? + + if [ "$fail" != "0" ]; then echo >&2 "" + echo >&2 " Error: updates were rejected by upstream server" + echo >&2 " This is usually caused by another repository pushing changes" + echo >&2 " to the same ref. You may want to first integrate remote changes" + echo >&2 "" + return + fi + fi + ;; + esac +} + +# Allow dual mode: run from the command line just like the update hook, or +# if no arguments are given then run as a hook script +if [ -n "$1" -a -n "$2" -a -n "$3" ]; then + # Output to the terminal in command line mode - if someone wanted to + # resend an email; they could redirect the output to sendmail + # themselves + PAGER= proxy_push $2 $3 $1 +else + # Push is proxied upstream one ref at a time. Because of this it is possible + # for some refs to succeed, and others to fail. This will result in a failed + # push. + while read oldrev newrev refname + do proxy_push $oldrev $newrev $refname + done +fi +``` + +请注意,此示例有一些限制: + +* 此示例可能无法完全满足您的用例,并且可能需要进行修改. + * 它不考虑镜像的不同类型的身份验证机制. + * 它不适用于强制更新(重写历史记录). + * 仅匹配`allowlist`模式的分支将被代理推送. +* 该脚本规避了 Git 钩子隔离环境,因为`$TARGET_REPO`的更新被视为参考更新,Git 会对此进行抱怨. + +### Mirroring with Perforce Helix via Git Fusion[](#mirroring-with-perforce-helix-via-git-fusion-starter "Permalink") + +**警告:**双向镜像不应用作永久配置. 有关替代的迁移方法,请参阅[从 Perforce Helix](../import/perforce.html)迁移. + +[Git Fusion](https://www.perforce.com/manuals/git-fusion/#Git-Fusion/section_avy_hyc_gl.html)为[Perforce Helix](https://www.perforce.com/products)提供了一个 Git 接口,GitLab 可以使用它来双向镜像 GitLab 项目. 从 Perforce Helix 迁移到 GitLab 的某些情况下,这可能是有用的,因为重叠的 Perforce Helix 工作区无法同时迁移到 GitLab. + +如果将镜像与 Perforce Helix 一起使用,则应仅镜像受保护的分支. Perforce Helix 将拒绝任何重写历史记录的推送. 由于 Git Fusion 的性能限制,只应镜像最少数量的分支. + +通过 Git Fusion 使用 Perforce Helix 配置镜像时,建议使用以下 Git Fusion 设置: + +* `change-pusher`应禁用. 否则,每个提交都将被重写为由镜像帐户提交,而不是映射到现有的 Perforce Helix 用户或`unknown_git`用户. +* 如果 Perforce Helix 中不存在 GitLab 用户,则`unknown_git`用户将用作提交作者. + +[在 Perforce.com 上](https://www.perforce.com/manuals/git-fusion/Content/Git-Fusion/section_vss_bdw_w3.html#section_zdp_zz1_3l)了解有关[Git Fusion 设置的信息](https://www.perforce.com/manuals/git-fusion/Content/Git-Fusion/section_vss_bdw_w3.html#section_zdp_zz1_3l) . + +## Troubleshooting[](#troubleshooting "Permalink") + +如果在推送过程中发生错误,则 GitLab 将在该存储库中显示"错误"突出显示. 然后,将鼠标悬停在突出显示的文本上,即可查看有关错误的详细信息. + +### 13:Received RST_STREAM with error code 2 with GitHub[](#13received-rst_stream-with-error-code-2-with-github "Permalink") + +如果在镜像到 GitHub 存储库时收到"错误代码为 2 的 13:Received RST_STREAM",则您的 GitHub 设置可能被设置为阻止推送,以暴露用于提交的电子邮件地址. 可以将您在 GitHub 上的电子邮件地址设置为公开,或者禁用[公开我的电子邮件](https://github.com/settings/emails)设置的" [阻止"命令行推送](https://github.com/settings/emails) . \ No newline at end of file diff --git a/docs/158.md b/docs/158.md new file mode 100644 index 0000000000000000000000000000000000000000..fe9f35a011c1d8b4d616c961b945564242e9402c --- /dev/null +++ b/docs/158.md @@ -0,0 +1,171 @@ +# Protected branches + +> 原文:[https://docs.gitlab.com/ee/user/project/protected_branches.html](https://docs.gitlab.com/ee/user/project/protected_branches.html) + +* [Overview](#overview) +* [Configuring protected branches](#configuring-protected-branches) +* [Using the Allowed to merge and Allowed to push settings](#using-the-allowed-to-merge-and-allowed-to-push-settings) +* [Restricting push and merge access to certain users](#restricting-push-and-merge-access-to-certain-users-starter) +* [Wildcard protected branches](#wildcard-protected-branches) +* [Creating a protected branch](#creating-a-protected-branch) +* [Deleting a protected branch](#deleting-a-protected-branch) +* [Protected Branches approval by Code Owners](#protected-branches-approval-by-code-owners-premium) +* [Running pipelines on protected branches](#running-pipelines-on-protected-branches) +* [Changelog](#changelog) + +# Protected branches[](#protected-branches "Permalink") + +GitLab 中的[权限](../permissions.html)基本上是围绕对存储库和分支具有读或写权限的想法定义的. 为了对某些分支机构施加进一步的限制,可以对其进行保护. + +## Overview[](#overview "Permalink") + +默认情况下,受保护的分支执行以下四个简单的操作: + +* 它会阻止除具有维护者权限的用户之外的所有用户创建它(如果尚未创建). +* 它可以防止除具有**允许的**权限的用户以外的其他任何人推送. +* 它可以防止**任何人**用力推动分支机构. +* 它可以防止**任何人**删除分支. + +**注意:**允许 GitLab 管理员推送到受保护的分支. + +有关随时间的变化,请参见" [更改日志"](#changelog)部分. + +默认的分支保护级别在[管理区域中](../admin_area/settings/visibility_and_access_controls.html#default-branch-protection)设置. + +## Configuring protected branches[](#configuring-protected-branches "Permalink") + +要保护分支,您需要至少具有维护者权限级别. 请注意,默认情况下`master`分支是受保护的. + +1. 导航到项目的**"设置"➔"存储库"** +2. 滚动查找" **受保护的分支"**部分. +3. 从" **分支"**下拉菜单中,选择要保护的分支,然后单击" **保护"** . 在下面的屏幕截图中,我们选择了`develop`分支. + + [![Protected branches page](img/c29b503c10922622f8ec612bd5168b10.png)](img/protected_branches_page_v12_3.png) + +4. 完成后,受保护的分支将出现在"受保护的分支"列表中. + + [![Protected branches list](img/265f035427185c0998b05886114d104b.png)](img/protected_branches_list_v12_3.png) + +## Using the Allowed to merge and Allowed to push settings[](#using-the-allowed-to-merge-and-allowed-to-push-settings "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5081) . + +从 GitLab 8.11 开始,我们增加了分支保护的另一层,它提供了对受保护分支的更精细的管理. "开发人员可以推送"选项由"允许推送"设置代替,该设置可以设置为允许/禁止维护者和/或开发人员推送到受保护的分支. + +使用"允许推送"和"允许合并"设置,您可以控制不同角色可以在受保护分支中执行的操作. 例如,您可以将"允许推送"设置为"无人",将"允许合并"设置为"开发人员+维护人员",以要求*每个人都*提交合并请求,以请求更改进入受保护分支. 这与[GitLab 工作](../../topics/gitlab_flow.html)流程等[工作流程](../../topics/gitlab_flow.html)兼容. + +但是,有些工作流程不需要这样做,只有防止强行推动和移除分支才有用. 对于这些工作流程,您可以通过将"允许推送"设置为"开发人员+维护人员"来允许具有写访问权的每个人推送到受保护的分支. + +您可以在创建受保护的分支时设置"允许推送"和"允许合并"选项,也可以在之后通过从"已保护"区域的下拉列表中选择所需的选项来设置. + +[![Developers can push](img/eca0c9ec85c6dfc8dbde06c368a9d94d.png)](img/protected_branches_devs_can_push_v12_3.png) + +如果在创建受保护的分支时未选择任何这些选项,则默认情况下会将它们设置为"维护者". + +## Restricting push and merge access to certain users[](#restricting-push-and-merge-access-to-certain-users-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5081) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.11. + +使用 GitLab 企业版,您可以通过选择角色(维护者,开发者)以及某些用户来限制对受保护分支的访问. 从下拉菜单中选择您要合并或推送访问的角色和/或用户. + +[![Select roles and users](img/8fc9989164e038f62ee1015c2f477d84.png)](img/protected_branches_select_roles_and_users.png) + +单击" **保护"** ,该分支将出现在"受保护的分支"列表中. + +[![Roles and users list](img/0387751ed4b8717777ebac2706c2d637.png)](img/protected_branches_select_roles_and_users_list.png) + +## Wildcard protected branches[](#wildcard-protected-branches "Permalink") + +在 GitLab 8.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4665) . + +您可以指定一个通配符保护的分支,该分支将保护所有与通配符匹配的分支. 例如: + +| 通配符保护的分支 | 匹配分支 | +| --- | --- | +| `*-stable` | `production-stable`, `staging-stable` | +| `production/*` | `production/app-server`, `production/load-balancer` | +| `*gitlab*` | `gitlab`, `gitlab/staging`, `master/gitlab/production` | + +受保护的分支设置(如"开发人员可以推送")适用于所有匹配的分支. + +两个不同的通配符可能会匹配同一分支. 例如, `*-stable` `production-stable`和`production-*`都将与`production-stable`分支匹配. 在这种情况下,如果*这些*受保护的分支有这样一个设定"允许推送",然后`production-stable`也将继承这一设置. + +如果单击受保护分支的名称,将显示所有匹配分支的列表: + +[![Protected branch matches](img/09870a42c6e3e94e7553f338a65c0b6d.png)](img/protected_branches_matches.png) + +## Creating a protected branch[](#creating-a-protected-branch "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53361) . + +当受保护的分支或通配符受保护的分支设置为" [**不允许任何人** **推送"时**](#using-the-allowed-to-merge-and-allowed-to-push-settings) ,只要允许开发人员(和具有较高[权限级别的](../permissions.html)用户) [**合并**](#using-the-allowed-to-merge-and-allowed-to-push-settings) ,就可以创建新的受保护分支. 这只能通过 UI 或 API 来完成(为避免意外地从命令行或 Git 客户端应用程序创建受保护的分支). + +通过用户界面创建新分支: + +1. Visit **资料库>分支机构**. +2. Click on **新分支**. +3. 填写分支名称,然后选择一个现有的分支,标记或确认新分支将基于该分支. 仅接受现有的受保护分支和已经在受保护分支中的提交. + +## Deleting a protected branch[](#deleting-a-protected-branch "Permalink") + +在 GitLab 9.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21393) . + +有时可能需要删除或清理受保护的分支. + +具有[维护者权限](../permissions.html)并具有[维护者权限的](../permissions.html)用户可以通过 GitLab 的 Web 界面手动删除受保护的分支: + +1. Visit **资料库>分支机构** +2. 单击您要删除的分支旁边的删除图标 +3. 为了防止意外删除,需要额外的确认 + + [![Delete protected branches](img/4e86bb665dcf8b8997d807441dbd60cd.png)](img/protected_branches_delete.png) + +只能通过 Web 界面而不是 Git 删除受保护的分支. 这意味着您不能从命令行或 Git 客户端应用程序中意外删除受保护的分支. + +## Protected Branches approval by Code Owners[](#protected-branches-approval-by-code-owners-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13251) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4. + +对于合并请求更改的文件,可能需要[代码所有者的](code_owners.html)至少一项批准. 可以在保护新分支时设置"代码所有者"批准,也可以将其设置为已经受保护的分支,如下所述. + +要保护新分支并获得代码所有者的批准: + +1. 导航到项目的**"设置">"存储库",**然后展开" **受保护的分支"** . +2. 向下滚动到**保护一个分支** ,选择**分支**或通配符你想保护,选择谁的**允许合并** **,**并**允许推** ,以及切换**需要从代码的业主**滑块**批准** . +3. Click **Protect**. + +[![Code Owners approval - new protected branch](img/9a996b513114d1fe39fa67c75e54df46.png)](img/code_owners_approval_new_protected_branch_v12_4.png) + +要使代码所有者批准已受保护的分支机构,请执行以下操作: + +1. 导航到项目的**"设置">"存储库",**然后展开" **受保护的分支"** . +2. 向下滚动到" **受保护"分支,**然后切换所选分支的**"代码所有者"批准**滑块. + +[![Code Owners approval - branch already protected](img/7a4195dce33a791e39b721499e4137ad.png)](img/code_owners_approval_protected_branch_v12_4.png) + +启用后,所有针对这些分支的合并请求都将需要代码所有者根据匹配的规则进行批准,然后才能合并. 此外,如果匹配规则,则拒绝直接推送到受保护的分支. + +## Running pipelines on protected branches[](#running-pipelines-on-protected-branches "Permalink") + +合并或推送到受保护分支的权限用于定义用户是否可以运行 CI / CD 管道并在与那些分支相关的作业上执行操作. + +有关管道安全模型的详细信息,请参阅[受保护分支上](../../ci/pipelines/index.html#pipeline-security-on-protected-branches)的安全性. + +## Changelog[](#changelog "Permalink") + +**11.9** + +* [允许](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53361)开发人员(和具有更高权限级别的用户)通过 API 和用户界面[创建受保护的分支](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53361) . + +**9.2** + +* 允许通过 Web 界面删除受保护的分支( [问题#21393](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21393) ). + +**8.11** + +* 允许创建无法推送到的受保护分支( [合并请求!5081](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5081) ). + +**8.10** + +* 允许没有推送访问权限的开发人员合并到受保护的分支中( [合并请求!4892](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4892) ). +* 允许使用通配符指定受保护的分支( [合并请求!4665](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4665) ). \ No newline at end of file diff --git a/docs/159.md b/docs/159.md new file mode 100644 index 0000000000000000000000000000000000000000..3f697d78040addc531af631bbd7e033bdd193bf8 --- /dev/null +++ b/docs/159.md @@ -0,0 +1,56 @@ +# Protected tags + +> 原文:[https://docs.gitlab.com/ee/user/project/protected_tags.html](https://docs.gitlab.com/ee/user/project/protected_tags.html) + +* [Overview](#overview) +* [Configuring protected tags](#configuring-protected-tags) +* [Wildcard protected tags](#wildcard-protected-tags) + +# Protected tags[](#protected-tags "Permalink") + +在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10356) . + +受保护的标签可控制谁有权创建标签,并防止创建后意外更新或删除. 每个规则都允许您匹配单个标签名称,或使用通配符一次控制多个标签. + +此功能从[受保护的分支](protected_branches.html)演变而来 + +## Overview[](#overview "Permalink") + +受保护的标签将阻止任何人更新或删除标签,并且将根据您选择的权限阻止创建匹配的标签. 默认情况下,任何未经维护者许可的人都将无法创建标签. + +## Configuring protected tags[](#configuring-protected-tags "Permalink") + +为了保护标签,您需要至少具有维护者权限级别. + +1. 导航到项目的**"设置">"存储库"** : + + [![Repository Settings](img/bec396562e8fe025cb7009de091ff2aa.png)](img/project_repository_settings.png) + +2. 从**标签**下拉菜单中,选择要保护或输入的标签,然后点击**创建通配符** . 在下面的屏幕截图中,我们选择保护所有与`v*`匹配的标签: + + [![Protected tags page](img/8ab62c2dee9f26abae9b7f794b4f5fae.png)](img/protected_tags_page_v12_3.png) + +3. 从" **允许创建"**下拉列表中,选择谁有权创建匹配的标签,然后单击" **保护"** : + + [![Allowed to create tags dropdown](img/52fecb33c2f168630e9a8f7c95aaf517.png)](img/protected_tags_permissions_dropdown_v12_3.png) + +4. 完成后,受保护的标签将显示在" **受保护的标签"**列表中: + + [![Protected tags list](img/572645049ee5ab43733f62fc45312843.png)](img/protected_tags_list_v12_3.png) + +## Wildcard protected tags[](#wildcard-protected-tags "Permalink") + +您可以指定一个通配符保护的标记,它将保护所有与通配符匹配的标记. 例如: + +| 通配符保护标签 | 匹配标签 | +| --- | --- | +| `v*` | `v1.0.0`, `version-9.1` | +| `*-deploy` | `march-deploy`, `1.0-deploy` | +| `*gitlab*` | `gitlab`, `gitlab/v1` | +| `*` | `v1.0.1rc2`, `accidental-tag` | + +两个不同的通配符可以潜在地匹配同一标签. 例如, `*-stable` `production-stable`和`production-*`都将与`production-stable`标签匹配. 在这种情况下,如果*这些*受保护的标签都像**允许创建**一个设定,然后`production-stable`也将沿用此设置. + +如果单击受保护标签的名称,将显示所有匹配标签的列表: + +[![Protected tag matches](img/cc52a99e48b72695add0c3e8efab158f.png)](img/protected_tag_matches.png) \ No newline at end of file diff --git a/docs/160.md b/docs/160.md new file mode 100644 index 0000000000000000000000000000000000000000..e8c1e32df32c23ca6e3568712e6555611916e058 --- /dev/null +++ b/docs/160.md @@ -0,0 +1,147 @@ +# Push Rules + +> 原文:[https://docs.gitlab.com/ee/push_rules/push_rules.html](https://docs.gitlab.com/ee/push_rules/push_rules.html) + +* [Overview](#overview) +* [Use cases](#use-cases) + * [Commit messages with a specific reference](#commit-messages-with-a-specific-reference) + * [Restrict branch names](#restrict-branch-names) + * [Custom Push Rules](#custom-push-rules-core-only) +* [Enabling push rules](#enabling-push-rules) +* [Prevent pushing secrets to the repository](#prevent-pushing-secrets-to-the-repository) + +# Push Rules[](#push-rules-starter "Permalink") + +通过使用正则表达式拒绝基于提交内容,分支名称或文件详细信息的推送,来获得对哪些内容可以推送或不能推送到存储库的额外控制. + +## Overview[](#overview "Permalink") + +GitLab 已经提供了[受保护的分支](../user/project/protected_branches.html) ,但是在某些情况下,您需要一些特定的规则,例如,防止删除 Git 标签或对提交消息强制采用特殊格式. + +推送规则本质上是[预先接收的 Git 挂钩](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) ,可在用户友好的界面中轻松启用. 如果您是管理员或每个项目,它们是全局定义的,因此您可以根据需要将不同的规则应用于不同的项目. + +## Use cases[](#use-cases "Permalink") + +每个推送规则都可以有自己的用例,但让我们考虑一些示例. + +### Commit messages with a specific reference[](#commit-messages-with-a-specific-reference "Permalink") + +假设您对工作流程有以下要求: + +* 每个提交都应引用 Jira 问题,例如: `Refactored css. Fixes JIRA-123.` `Refactored css. Fixes JIRA-123.` +* 用户应该无法使用`git push`删除 Git 标签 + +您需要做的就是编写一个简单的正则表达式,要求在提交消息中提及一个 Jira 问题,例如`JIRA\-\d+` . + +现在,当用户尝试通过消息`Bugfix`推送提交时,他们的推送将被拒绝. 仅接受`Bugfix according to JIRA-123`推送带有`Bugfix according to JIRA-123`消息的提交. + +### Restrict branch names[](#restrict-branch-names "Permalink") + +假设您公司中有严格的分支机构名称政策,并且您希望分支机构以特定名称开头,因为您有不同的 GitLab CI / CD 作业( `feature` , `hotfix` , `docker` , `android`等)依赖于分支机构名称. + +但是,您的开发人员并不总是记住该策略,因此他们可能会推送到各个分支,并且 CI 管道可能无法按预期工作. 通过在推送规则中全局限制分支名称,可以防止此类错误. 与您的推送规则不匹配的任何分支名称都将被拒绝. + +请注意,不管指定的分支命名正则表达式(regex)如何,始终允许使用默认分支的名称. 通过这种方式配置 GitLab,因为合并通常将默认分支作为目标. 如果您还有其他目标分支,请将其包含在正则表达式中. (请参阅[启用推送规则](#enabling-push-rules) ). + +默认分支还默认为[受保护分支](../user/project/protected_branches.html) ,这已经限制了用户直接推送. + +### Custom Push Rules[](#custom-push-rules-core-only "Permalink") + +通过使用更高级的服务器挂钩,可以创建自定义推送规则,而不是" **管理区域">"推送规则"中**可用的**推送规则** . + +有关更多信息,请参见[服务器挂钩](../administration/server_hooks.html) . + +## Enabling push rules[](#enabling-push-rules "Permalink") + +**注意:** GitLab 管理员可以在" **管理区域">"**所有新项目都将继承的**推送规则"**下全局设置推送规则. 您以后可以在项目的设置中覆盖它们. 也可以在[组级别](../user/group/index.html#group-push-rules-starter)上设置它们. + +1. 导航到项目的**"设置">"存储库",**然后展开" **推送规则"** +2. 设置所需的规则 +3. 单击" **保存推送规则"**以使更改生效 + +以下选项可用. + +| 推送规则 | GitLab 版本 | Description | +| --- | --- | --- | +| 用`git push`删除标签 | **Starter** 7.10 | 禁止用户使用`git push`删除 Git 标签. 仍然可以通过 Web UI 删除标签. | +| 检查作者是否是 GitLab 用户 | **Starter** 7.10 | 限制作者(电子邮件)对现有 GitLab 用户的提交. | +| 提交者限制 | **Premium** 10.2 | GitLab will reject any commit that was not committed by the current authenticated user | +| 检查提交是否通过 GPG 签名 | **Premium** 10.1 | 如果未通过 GPG 签名,则拒绝提交. [使用 GPG](../user/project/repository/gpg_signed_commits/index.html)阅读[签名提交](../user/project/repository/gpg_signed_commits/index.html) . | +| 防止向 Git 提交机密 | **Starter** 8.12 | GitLab 将拒绝任何可能包含机密的文件. 阅读[禁止使用的文件](#prevent-pushing-secrets-to-the-repository) . | +| 通过提交消息限制 | **Starter** 7.10 | 只允许推送与此正则表达式匹配的提交消息. 保留为空以允许任何提交消息. 使用多行模式,可以使用`(?-m)`禁用该模式. | +| 受提交消息限制(负匹配) | **Starter** 11.1 | 只允许提交与此正则表达式不匹配的提交消息. 保留为空以允许任何提交消息. 使用多行模式,可以使用`(?-m)`禁用该模式. | +| 受分支名称限制 | **Starter** 9.3 | 只允许推送与此正则表达式匹配的分支名称. 保留为空以允许使用任何分支名称. | +| 通过提交作者的电子邮件进行限制 | **Starter** 7.10 | 只允许推送与此正则表达式匹配的提交者的电子邮件. 留空以允许任何电子邮件. | +| 禁止的文件名 | **Starter** 7.10 | 与该正则表达式匹配的所有提交的文件名均不允许推送. 保留为空以允许任何文件名. | +| 最大档案大小 | **Starter** 7.12 | 包含超过此文件大小(以 MB 为单位)的添加或更新文件的推送将被拒绝. 设置为 0 允许任何大小的文件. 由 Git LFS 跟踪的文件被豁免. | + +**提示:** GitLab 对推送规则中的正则表达式使用[RE2 语法](https://github.com/google/re2/wiki/Syntax) ,您可以在[GoLang regex tester 上](https://regex-golang.appspot.com/assets/html/index.html)对其进行[测试](https://regex-golang.appspot.com/assets/html/index.html) . + +## Prevent pushing secrets to the repository[](#prevent-pushing-secrets-to-the-repository "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.12. + +诸如凭证文件,SSH 私钥之类的机密以及其他包含机密的文件绝不应提交给源代码控制. GitLab 允许您打开文件的预定义拒绝列表,该列表将不允许被推送到存储库,从而阻止这些提交到达远程存储库. + +通过选中*防止向 Git 提交机密*复选框,当文件与从[`files_denylist.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/gitlab/checks/files_denylist.yml)读取的正则表达式匹配时,GitLab 会阻止将其推送到存储库(在查看此文件时,请确保您处于与 GitLab 版本相同的正确分支). + +**注意:**已经提交的文件将不受此推送规则的限制. + +下面是这些正则表达式将拒绝的内容的示例列表: + +``` +##################### +# AWS CLI credential blobs +##################### +.aws/credentials +aws/credentials +homefolder/aws/credentials + +##################### +# Private RSA SSH keys +##################### +/ssh/id_rsa +/.ssh/personal_rsa +/config/server_rsa +id_rsa +.id_rsa + +##################### +# Private DSA SSH keys +##################### +/ssh/id_dsa +/.ssh/personal_dsa +/config/server_dsa +id_dsa +.id_dsa + +##################### +# Private ed25519 SSH keys +##################### +/ssh/id_ed25519 +/.ssh/personal_ed25519 +/config/server_ed25519 +id_ed25519 +.id_ed25519 + +##################### +# Private ECDSA SSH keys +##################### +/ssh/id_ecdsa +/.ssh/personal_ecdsa +/config/server_ecdsa +id_ecdsa +.id_ecdsa + +##################### +# Any file with .pem or .key extensions +##################### +*.pem +*.key + +##################### +# Any file ending with _history or .history extension +##################### +pry.history +bash_history +``` \ No newline at end of file diff --git a/docs/161.md b/docs/161.md new file mode 100644 index 0000000000000000000000000000000000000000..8d07161c22c78189c5523934fd545fcb56581996 --- /dev/null +++ b/docs/161.md @@ -0,0 +1,211 @@ +# Reduce repository size + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/reducing_the_repo_size_using_git.html](https://docs.gitlab.com/ee/user/project/repository/reducing_the_repo_size_using_git.html) + +* [Purge files from repository history](#purge-files-from-repository-history) +* [Purge files from GitLab storage](#purge-files-from-gitlab-storage) +* [Repository cleanup](#repository-cleanup) +* [Storage limits](#storage-limits) + +# Reduce repository size[](#reduce-repository-size "Permalink") + +随着时间的流逝,Git 存储库变得越来越大. 将大文件添加到 Git 存储库后: + +* 由于每个人都必须下载文件,因此获取存储库的速度变慢. +* 它们占用服务器上的大量存储空间. +* [可以达到](#storage-limits) Git 仓库的存储限制. + +重写存储库可能会删除不需要的历史记录,从而使存储库更小. [`git filter-repo`](https://github.com/newren/git-filter-repo)是用于快速重写 Git 存储库历史记录的工具,建议同时使用以下两种工具: + +* [`git filter-branch`](https://git-scm.com/docs/git-filter-branch). +* [BFG](https://rtyley.github.io/bfg-repo-cleaner/). + +**危险:**重写存储库历史记录是一种破坏性操作. 在开始之前,请确保备份您的存储库. 备份存储库的最佳方法是[导出项目](../settings/import_export.html#exporting-a-project-and-its-data) .**注意:** Git LFS 文件只能由管理员使用[Rake 任务](../../../raketasks/cleanup.html)删除. [计划](https://gitlab.com/gitlab-org/gitlab/-/issues/223621)消除此限制. + +## Purge files from repository history[](#purge-files-from-repository-history "Permalink") + +为了使克隆项目更快,请重写分支和标签以删除不需要的文件. + +1. 使用受支持的程序包管理器或从源代码[安装`git filter-repo`](https://github.com/newren/git-filter-repo/blob/main/INSTALL.md) . + +2. 使用`--bare`克隆存储库的新副本: + + ``` + git clone --bare https://example.gitlab.com/my/project.git + ``` + +3. 使用`git filter-repo` ,从存储库的历史记录中清除所有文件. + + 要清除大文件,可以使用`--strip-blobs-bigger-than`选项: + + ``` + git filter-repo --strip-blobs-bigger-than 10M + ``` + + 要清除使用 Git LFS 存储的大文件,可以使用`--blob--callback`选项. 下面的示例使用回调从 Git LFS 指针读取文件大小,并删除大于 10MB 的文件. + + ``` + git filter-repo --blob-callback ' + if blob.data.startswith(b"version https://git-lfs.github.com/spec/v1"): + size_in_bytes = int.from_bytes(blob.data[124:], byteorder="big") + if size_in_bytes > 10*1000: + blob.skip() + ' + ``` + + 要按路径清除特定的大文件,可以组合使用`--path`和`--invert-paths`选项: + + ``` + git filter-repo --path path/to/big/file.m4v --invert-paths + ``` + + 有关更多示例和完整文档,请参见[`git filter-repo`](https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html#EXAMPLES)文档. + +4. 运行`git filter-repo`会删除所有遥控器. 要为您的项目还原遥控器,请运行: + + ``` + git remote add origin https://example.gitlab.com/<namespace>/<project_name>.git + ``` + +5. 强制推送更改以覆盖 GitLab 上的所有分支: + + ``` + git push origin --force --all + ``` + + [受保护的分支](../protected_branches.html)将导致此操作失败. 要继续,您必须删除分支保护,推送,然后重新启用受保护的分支. + +6. 要从标记的发行版中删除大文件,请强制将更改推送到 GitLab 上的所有标记: + + ``` + git push origin --force --tags + ``` + + [受保护的标签](../protected_tags.html)将导致此操作失败. 要继续,您必须删除标签保护,推送,然后重新启用受保护的标签. + +7. 手动执行[项目整理](../../../administration/housekeeping.html#manual-housekeeping) + +**注意:**为提高性能而缓存了项目统计信息. 您可能需要等待 5 到 10 分钟才能看到存储利用率下降. + +## Purge files from GitLab storage[](#purge-files-from-gitlab-storage "Permalink") + +要减少 GitLab 中存储库的大小,必须删除 GitLab 内部引用以包含大文件的提交. 在完成这些步骤之前,请[从存储库历史记录中清除文件](#purge-files-from-repository-history) . + +除了[分支](branches/index.html)和标签(这是一种 Git 引用)之外,GitLab 还会自动创建其他引用. 这些引用可防止在查看合并请求时死链接到提交或丢失差异. [存储库清理](#repository-cleanup)可用于从 GitLab 中删除它们. + +以下内部参考文献不做广告: + +* `refs/merge-requests/*`用于合并请求. +* `refs/pipelines/*` for [pipelines](../../../ci/pipelines/index.html#troubleshooting-fatal-reference-is-not-a-tree). +* `refs/environments/*`用于环境. + +这意味着在获取时通常不包含它们,这使得获取速度更快. 另外, `refs/keep-around/*`是隐藏的 refs,以防止与讨论相关的提交被删除并且根本无法被获取. + +但是,可以从项目导出内的 Git 捆绑包访问这些引用. + +1. 使用受支持的程序包管理器或从源代码[安装`git filter-repo`](https://github.com/newren/git-filter-repo/blob/main/INSTALL.md) . + +2. [从项目中](../settings/import_export.html#exporting-a-project-and-its-data)生成一个新的[导出](../settings/import_export.html#exporting-a-project-and-its-data)并下载. + +3. 使用`tar`解压缩备份: + + ``` + tar xzf project-backup.tar.gz + ``` + + 这将包含一个由[`git bundle`](https://git-scm.com/docs/git-bundle)创建的`project.bundle`文件. + +4. 从包中克隆存储库的新副本: + + ``` + git clone --bare --mirror /path/to/project.bundle + ``` + +5. 使用`git filter-repo` ,从存储库的历史记录中清除所有文件. 因为我们正在尝试删除内部引用,所以我们将依靠每次运行生成的`commit-map`来告诉我们要删除哪些内部引用. + + **注意:** `git filter-repo`每次运行都会创建一个新的`commit-map`文件,并覆盖前一次运行的`commit-map` . **每次**运行都将需要此文件. 每次运行`git filter-repo`都要执行下一步. + + 要清除所有大文件,可以使用`--strip-blobs-bigger-than`选项: + + ``` + git filter-repo --strip-blobs-bigger-than 10M + ``` + + 要按路径清除特定的大文件,可以组合使用`--path`和`--invert-paths`选项. + + ``` + git filter-repo --path path/to/big/file.m4v --invert-paths + ``` + + 有关更多示例和完整文档,请参见[`git filter-repo`](https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html#EXAMPLES)文档. + +6. 运行[存储库清理](#repository-cleanup) . + +## Repository cleanup[](#repository-cleanup "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/19376) . + +仓库清理允许您上传对象的文本文件,并且 GitLab 将删除对这些对象的内部 Git 引用. 您可以使用[`git filter-repo`](https://github.com/newren/git-filter-repo)生成对象列表(在`commit-map`文件中),该对象列表可与存储库清理一起使用. + +要清理存储库: + +1. 转到存储库的项目. +2. 导航 **设置>存储库** . +3. 上载对象列表. 例如,一个`commit-map`文件. +4. Click **开始清理**. + +这将: + +* 删除所有对旧提交的内部 Git 引用. +* 针对存储库运行`git gc` . + +完成后,您将收到一封电子邮件. + +When using repository cleanup, note: + +* 项目统计信息已缓存. 您可能需要等待 5 到 10 分钟才能看到存储利用率下降. +* 客房部修剪 2 周以上的松散物品. 这意味着在最近 2 周内添加的对象将不会立即删除. 如果您有权访问[Gitaly](../../../administration/gitaly/index.html)服务器,则可以运行`git gc --prune=now`立即修剪所有松散的对象. +* 此过程将从 GitLab 的缓存和数据库中删除一些重写提交的副本,但是覆盖范围仍然存在许多空白,并且某些副本可能会无限期地存在. [清除实例缓存](../../../administration/raketasks/maintenance.html#clear-redis-cache)可能有助于删除其中的一些[实例](../../../administration/raketasks/maintenance.html#clear-redis-cache) ,但出于安全考虑,不应依赖它! + +## Storage limits[](#storage-limits "Permalink") + +储存库大小限制: + +* 可以[由管理员](../../admin_area/settings/account_and_limit_settings.html#repository-size-limit-starter-only)在自我管理实例上设置. +* Are [set for GitLab.com](../../gitlab_com/index.html#repository-size-limit). + +当项目达到其大小限制时,您不能: + +* 推送到项目. +* 创建一个新的合并请求. +* 合并现有的合并请求. +* 上载 LFS 对象. + +您仍然可以: + +* 创造新问题. +* 克隆项目. + +如果超出存储库大小限制,则可以尝试: + +1. 删除一些数据. +2. 进行新的提交. +3. 推回存储库. + +也许您还可以: + +* 将一些斑点移到 LFS. +* 从历史记录中删除一些旧的依赖项更新. + +不幸的是,该工作流程无法正常工作. 实际上,在提交中删除文件并不会减小存储库的大小,因为早期的提交和 Blob 仍然存在. + +您需要做的是重写历史记录. 我们建议使用开源社区维护的工具[`git filter-repo`](https://github.com/newren/git-filter-repo) . + +**注意:**在 GitLab 端运行`git gc`之前,"已删除"的提交和 blob 仍将存在. 您还必须能够将重写的历史记录推送到 GitLab,如果您已经超过最大大小限制,则可能无法实现. + +为了解除这些限制,自我管理的 GitLab 实例的管理员必须增加对超出它的特定项目的限制. 因此,最好始终主动保持在限制之下. 如果您达到了极限,并且无法暂时提高极限,则唯一的选择是: + +1. 在本地修剪所有不需要的东西. +2. 在 GitLab 上创建一个新项目,然后开始使用它. + +**Caution:** This process is not suitable for removing sensitive data like password or keys from your repository. Information about commits, including file content, is cached in the database, and will remain visible even after they have been removed from the repository. \ No newline at end of file diff --git a/docs/162.md b/docs/162.md new file mode 100644 index 0000000000000000000000000000000000000000..c905109ea97aacdcf833cbc88d255c1bff4a63bb --- /dev/null +++ b/docs/162.md @@ -0,0 +1,252 @@ +# Signing commits with GPG + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/gpg_signed_commits/](https://docs.gitlab.com/ee/user/project/repository/gpg_signed_commits/) + +* [How GitLab handles GPG](#how-gitlab-handles-gpg) +* [Generating a GPG key](#generating-a-gpg-key) +* [Adding a GPG key to your account](#adding-a-gpg-key-to-your-account) +* [Associating your GPG key with Git](#associating-your-gpg-key-with-git) +* [Signing commits](#signing-commits) +* [Verifying commits](#verifying-commits) +* [Revoking a GPG key](#revoking-a-gpg-key) +* [Removing a GPG key](#removing-a-gpg-key) +* [Rejecting commits that are not signed](#rejecting-commits-that-are-not-signed-premium) +* [GPG signing API](#gpg-signing-api) +* [Further reading](#further-reading) + +# Signing commits with GPG[](#signing-commits-with-gpg "Permalink") + +版本历史 + +* 在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9546) . +* 在 GitLab 10.1 中添加了子项支持. + +您可以使用 GPG 密钥对在 GitLab 存储库中进行的 Git 提交进行签名. 如果可以验证提交者的身份,则已签名的提交将标记为" **已**验证". 为了验证提交者的身份,GitLab 需要他们的公共 GPG 密钥. + +**注意:**术语 GPG 用于所有与 OpenPGP / PGP / GPG 相关的材料和实现. + +目前尚不支持通过 GPG 验证的标签. + +有关 GPG 的更多详细信息,请参见[进一步阅读](#further-reading)部分. + +## How GitLab handles GPG[](#how-gitlab-handles-gpg "Permalink") + +GitLab 使用其自己的密钥环来验证 GPG 签名. 它不访问任何公钥服务器. + +对于要由 GitLab 验证的提交: + +* 提交者必须具有 GPG 公钥/私钥对. +* 提交者的公钥必须已上传到其 GitLab 帐户. +* GPG 密钥中的一封电子邮件必须与提交者在 GitLab 中使用的**经过验证的**电子邮件地址匹配. +* 提交者的电子邮件地址必须与 GPG 密钥中验证的电子邮件地址匹配. + +## Generating a GPG key[](#generating-a-gpg-key "Permalink") + +如果您还没有 GPG 密钥,则以下步骤将帮助您入门: + +1. 为您的操作系统[安装 GPG](https://www.gnupg.org/download/index.html) . 如果您的操作系统具有`gpg2`安装,更换`gpg`与`gpg2`在下面的命令. +2. 使用以下命令生成私钥/公钥对,这将产生一系列问题: + + ``` + gpg --full-gen-key + ``` + + **注意:**在某些情况下,例如 Windows 和其他 macOS 版本上的 Gpg4win,此处的命令可能是`gpg --gen-key` . +3. 第一个问题是可以使用哪种算法. 选择所需的类型或按`Enter 键`选择默认类型(RSA 和 RSA): + + ``` + Please select what kind of key you want: + (1) RSA and RSA (default) + (2) DSA and Elgamal + (3) DSA (sign only) + (4) RSA (sign only) + Your selection? 1 + ``` + +4. 下一个问题是密钥长度. 我们建议您选择`4096` : + + ``` + RSA keys may be between 1024 and 4096 bits long. + What keysize do you want? (2048) 4096 + Requested keysize is 4096 bits + ``` + +5. 指定密钥的有效期. 这是主观的,您可以使用默认值,该值永远不会过期: + + ``` + Please specify how long the key should be valid. + 0 = key does not expire + <n> = key expires in n days + <n>w = key expires in n weeks + <n>m = key expires in n months + <n>y = key expires in n years + Key is valid for? (0) 0 + Key does not expire at all + ``` + +6. 通过输入`y`确认您给出的答案是正确的: + + ``` + Is this correct? (y/N) y + ``` + +7. 输入您的真实姓名,与此键关联的电子邮件地址(应与您在 GitLab 中使用的经过验证的电子邮件地址匹配)和可选注释(按`Enter`跳过): + + ``` + GnuPG needs to construct a user ID to identify your key. + + Real name: Mr. Robot + Email address: <your_email> + Comment: + You selected this USER-ID: + "Mr. Robot <your_email>" + + Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O + ``` + +8. 在询问时选择一个强密码,然后输入两次以确认. +9. 使用以下命令列出您刚刚创建的私密 GPG 密钥: + + ``` + gpg --list-secret-keys --keyid-format LONG <your_email> + ``` + + 将`<your_email>`替换为您在上面输入的电子邮件地址. + +10. 复制以`sec`开头的 GPG 密钥 ID. 在以下示例中,即`30F2B65B9246B6CA` : + + ``` + sec rsa4096/30F2B65B9246B6CA 2017-08-18 [SC] + D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA + uid [ultimate] Mr. Robot <your_email> + ssb rsa4096/B7ABC0813E4028C0 2017-08-18 [E] + ``` + +11. 导出该 ID 的公共密钥(替换上一步中的密钥 ID): + + ``` + gpg --armor --export 30F2B65B9246B6CA + ``` + +12. 最后,复制公钥并将其[添加到您的个人资料设置中](#adding-a-gpg-key-to-your-account) + +## Adding a GPG key to your account[](#adding-a-gpg-key-to-your-account "Permalink") + +**注意:**添加密钥后,就无法对其进行编辑,只能将其删除. 如果粘贴无效,则必须删除有问题的密钥并重新添加. + +您可以在个人资料的设置中添加 GPG 密钥: + +1. 点击右上角的头像,然后转到**"设置"** . + + [![Settings dropdown](img/5e2e81b44d67af322056491cf32bb8da.png)](../../../profile/img/profile_settings_dropdown.png) + +2. 导航至**GPG 密钥**标签,然后将您的*公共*密钥粘贴到"密钥"框中. + + [![Paste GPG public key](img/d04d999de9102632af46c867821c47c3.png)](img/profile_settings_gpg_keys_paste_pub.png) + +3. 最后,单击**添加键**将其添加到 GitLab. 您将能够看到其指纹,相应的电子邮件地址和创建日期. + + [![GPG key single page](img/8a56e678752a9bd9def98422dee92f3e.png)](img/profile_settings_gpg_keys_single_key.png) + +## Associating your GPG key with Git[](#associating-your-gpg-key-with-git "Permalink") + +[创建 GPG 密钥](#generating-a-gpg-key)并将其[添加到您的帐户之后](#adding-a-gpg-key-to-your-account) ,是时候告诉 Git 使用哪个密钥了. + +1. 使用以下命令列出您刚刚创建的私密 GPG 密钥: + + ``` + gpg --list-secret-keys --keyid-format LONG <your_email> + ``` + + 将`<your_email>`替换为您在上面输入的电子邮件地址. + +2. 复制以`sec`开头的 GPG 密钥 ID. 在以下示例中,即`30F2B65B9246B6CA` : + + ``` + sec rsa4096/30F2B65B9246B6CA 2017-08-18 [SC] + D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA + uid [ultimate] Mr. Robot <your_email> + ssb rsa4096/B7ABC0813E4028C0 2017-08-18 [E] + ``` + +3. 告诉 Git 使用该密钥对提交进行签名: + + ``` + git config --global user.signingkey 30F2B65B9246B6CA + ``` + + 用您的 GPG 密钥 ID 替换`30F2B65B9246B6CA` . + +4. (可选)如果 Git 使用`gpg`并且出现诸如`secret key not available`或`gpg: signing failed: secret key not available` ,请运行以下命令更改为`gpg2` : + + ``` + git config --global gpg.program gpg2 + ``` + +## Signing commits[](#signing-commits "Permalink") + +[创建 GPG 密钥](#generating-a-gpg-key)并将其[添加到您的帐户之后](#adding-a-gpg-key-to-your-account) ,您可以开始对提交进行签名: + +1. 像以前一样提交,唯一的区别是添加了`-S`标志: + + ``` + git commit -S -m "My commit msg" + ``` + +2. 询问时输入 GPG 密钥的密码. +3. 推送至 GitLab 并检查您的提交[是否已通过验证](#verifying-commits) . + +如果您不想在每次提交时都键入`-S`标志,则可以告诉 Git 自动签名您的提交: + +``` +git config --global commit.gpgsign true +``` + +## Verifying commits[](#verifying-commits "Permalink") + +1. 在项目或[合并请求中](../../merge_requests/index.html) ,导航到" **提交"**选项卡. 签名的提交将显示包含" Verified"或" Unverified"的徽章,具体取决于 GPG 签名的验证状态. + + [![Signed and unsigned commits](img/7d08a10bdee492162fdb554fb3033f0d.png)](img/project_signed_and_unsigned_commits.png) + +2. 通过单击 GPG 徽章,将显示签名的详细信息. + + [![Signed commit with verified signature](img/544adf1331ba8dc0c6391bf07ba6df8c.png)](img/project_signed_commit_verified_signature.png) + + [![Signed commit with verified signature](img/cc6935399d2235840119ad00eb778fc9.png)](img/project_signed_commit_unverified_signature.png) + +## Revoking a GPG key[](#revoking-a-gpg-key "Permalink") + +撤消密钥将**取消验证**已签名的提交. 使用此密钥验证的提交将变为未验证状态. 撤销此密钥后,将来的提交也将保持不变. 如果您的密钥已被盗用,则应使用此操作. + +撤销 GPG 密钥: + +1. 点击右上角的头像,然后转到**"设置"** . +2. 导航到**GPG 键**标签. +3. 单击您要删除的 GPG 键**旁边的撤消** . + +## Removing a GPG key[](#removing-a-gpg-key "Permalink") + +删除密钥**不会**取消**验证**已签名的提交. 使用此密钥验证的提交将保持验证状态. 删除此密钥后,只有未按下的提交才会保持未验证状态. 要取消验证已签名的提交,您需要从您的帐户中[撤销关联的 GPG 密钥](#revoking-a-gpg-key) . + +要从您的帐户中删除 GPG 密钥,请执行以下操作: + +1. 点击右上角的头像,然后转到**"设置"** . +2. 导航到**GPG 键**标签. +3. 单击您要删除的 GPG 密钥旁边的垃圾桶图标. + +## Rejecting commits that are not signed[](#rejecting-commits-that-are-not-signed-premium "Permalink") + +您可以将您的项目配置为拒绝不是通过[推送规则进行](../../../../push_rules/push_rules.html) GPG 签名的提交. + +## GPG signing API[](#gpg-signing-api "Permalink") + +了解如何[通过 API 通过提交获取 GPG 签名](../../../../api/commits.html#get-gpg-signature-of-a-commit) . + +## Further reading[](#further-reading "Permalink") + +有关 GPG 的更多详细信息,请参见: + +* [Git Tools - Signing Your Work](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work) +* [Managing OpenPGP Keys](https://riseup.net/en/security/message-security/openpgp/gpg-keys) +* [OpenPGP Best Practices](https://riseup.net/en/security/message-security/openpgp/best-practices) +* [Creating a new GPG key with subkeys](https://www.void.gr/kargig/blog/2013/12/02/creating-a-new-gpg-key-with-subkeys/) (advanced) \ No newline at end of file diff --git a/docs/163.md b/docs/163.md new file mode 100644 index 0000000000000000000000000000000000000000..507059f8a9963d89700c33db31cc1f391375bd15 --- /dev/null +++ b/docs/163.md @@ -0,0 +1,35 @@ +# Syntax Highlighting + +> 原文:[https://docs.gitlab.com/ee/user/project/highlighting.html](https://docs.gitlab.com/ee/user/project/highlighting.html) + +# Syntax Highlighting[](#syntax-highlighting "Permalink") + +GitLab 通过[Rouge](https://rubygems.org/gems/rouge) Ruby gem 在所有文件上提供语法高亮显示. 它将尝试根据文件扩展名猜测要使用哪种语言,大多数时间是足够的. + +**注意:** [Web IDE](web_ide/index.html)和[代码片段](../snippets.html)使用[Monaco Editor](https://microsoft.github.io/monaco-editor/)进行文本编辑,而在内部使用[Monarch](https://microsoft.github.io/monaco-editor/monarch.html)库进行语法突出显示. + +如果 GitLab 在猜测错了,你可以覆盖其选择使用语言的`gitlab-language`的属性`.gitattributes` . 例如,如果您在 Prolog 项目中工作并使用`.pl`文件扩展名(通常以 Perl 突出显示),则可以将以下内容添加到`.gitattributes`文件中: + +``` +*.pl gitlab-language=prolog +``` + +当您签入并进行更改时,项目中的所有`*.pl`文件都将突出显示为 Prolog. + +这里的路径只是 Git 内置的[`.gitattributes`接口](https://git-scm.com/docs/gitattributes) . 因此,如果您要在使用 Ruby 语法的项目根目录下发明一种名为`Nicefile`的文件格式,那么您需要做的就是: + +``` +/Nicefile gitlab-language=ruby +``` + +要完全禁用突出显示,请使用`gitlab-language=text` . 可通过 CGI 选项获得更多有趣的恶作剧,例如: + +``` +# json with erb in it /my-cool-file gitlab-language=erb?parent=json + +# an entire file of highlighting errors! /other-file gitlab-language=text?token=Error +``` + +请注意,这些配置仅在`.gitattributes`文件位于默认分支(通常为`master` )中时才生效. + +**注意:** Web IDE 不支持`.gitattribute`文件,但已[计划在将来的发行版中使用](https://gitlab.com/gitlab-org/gitlab/-/issues/22014) . \ No newline at end of file diff --git a/docs/164.md b/docs/164.md new file mode 100644 index 0000000000000000000000000000000000000000..c2df661079aa443146ba76cf8060267dd4bc1fd2 --- /dev/null +++ b/docs/164.md @@ -0,0 +1,127 @@ +# GitLab Web Editor + +> 原文:[https://docs.gitlab.com/ee/user/project/repository/web_editor.html](https://docs.gitlab.com/ee/user/project/repository/web_editor.html) + +* [Create a file](#create-a-file) + * [Template dropdowns](#template-dropdowns) +* [Upload a file](#upload-a-file) +* [Create a directory](#create-a-directory) +* [Create a new branch](#create-a-new-branch) + * [Create a new branch from an issue](#create-a-new-branch-from-an-issue) + * [Create a new branch from a project’s dashboard](#create-a-new-branch-from-a-projects-dashboard) +* [Create a new tag](#create-a-new-tag) +* [Tips](#tips) + +# GitLab Web Editor[](#gitlab-web-editor "Permalink") + +有时,直接从 GitLab 界面进行快速更改要比克隆项目并使用 Gi​​t 命令行工具容易. 在此功能中,我们重点介绍如何从文件浏览器创建新文件,目录,分支或标记. 所有这些操作都可以通过一个下拉菜单获得. + +## Create a file[](#create-a-file "Permalink") + +在项目的文件页面中,单击分支选择器右侧的" +"按钮. 从下拉列表中选择**新文件** . + +[![New file dropdown menu](img/149fa515778bea7ce86903f0c8d9b31f.png)](img/web_editor_new_file_dropdown.png) + +在" **文件名"**框中输入文件名. 然后,在编辑器区域中添加文件内容. 添加描述性提交消息并选择一个分支. 分支字段将默认为您在文件浏览器中查看的分支. 如果输入新的分支名称,将出现一个复选框,允许您在提交更改后启动新的合并请求. + +当您对新文件感到满意时,请单击底部的" **提交更改** ". + +[![Create file editor](img/07e4663db45be7313a205a17ec342edb.png)](img/web_editor_new_file_editor.png) + +### Template dropdowns[](#template-dropdowns "Permalink") + +启动新项目时,新项目可能也需要一些通用文件. 因此,GitLab 将显示一条消息,以简化您的操作. + +[![First file for your project](img/1e0213e85ced3ac9dcc079f0e1831068.png)](img/web_editor_template_dropdown_first_file.png) + +当单击`LICENSE`或`.gitignore`等时,将显示一个下拉列表,为您提供适合您的项目的模板. + +[![MIT license selected](img/097706015c4d2abaaf34d0782cfac635.png)](img/web_editor_template_dropdown_mit_license.png) + +许可证, `.gitlab-ci.yml`日志,贡献指南或`.gitlab-ci.yml`文件也可以通过项目页面上的按钮添加. 在下面的示例中,许可证已经创建,这将创建指向许可证本身的链接. + +[![New file button](img/adc0d64a6c4c1979d43d8bf1d8d485e8.png)](img/web_editor_template_dropdown_buttons.png) + +> **Note:** The **设置 CI / CD** button will not appear on an empty repository. You have to at least add a file in order for the button to show up. + +## Upload a file[](#upload-a-file "Permalink") + +当内容为文本时,创建文件的能力非常出色. 但是,这不适用于二进制数据,例如图像,PDF 或其他文件类型. 在这种情况下,您需要上传文件. + +在项目的文件页面中,单击分支选择器右侧的" +"按钮. 从下拉菜单中选择上**载文件** . + +[![Upload file dropdown menu](img/671787cdf6cd1dde3e748fae72d46779.png)](img/web_editor_upload_file_dropdown.png) + +弹出上传对话框后,有两种方法可以上传文件. 可以在弹出窗口中拖放文件,也可以使用**点击上传**链接. 选择要上传的文件后,将显示文件预览. + +输入提交消息,选择一个分支,并在准备好后单击"上**载文件"** . + +[![Upload file dialog](img/2ed1719eefb651778ccd248f0bbe577c.png)](img/web_editor_upload_file_dialog.png) + +## Create a directory[](#create-a-directory "Permalink") + +为了使档案库中的文件井井有条,创建一个新目录通常会很有帮助. + +在项目的文件页面中,单击分支选择器右侧的加号按钮( `+` ). 从下拉菜单中选择" **新建目录** ". + +[![New directory dropdown](img/c65afb6da67de7dea9950e2b151cca40.png)](img/web_editor_new_directory_dropdown.png) + +在新目录对话框中,输入目录名称,提交消息并选择目标分支. 单击**创建目录**以完成. + +[![New directory dialog](img/0b804819bf30ce8e657ad538d376ecc5.png)](img/web_editor_new_directory_dialog.png) + +## Create a new branch[](#create-a-new-branch "Permalink") + +有多种方法可从 GitLab 的 Web 界面创建分支. + +### Create a new branch from an issue[](#create-a-new-branch-from-an-issue "Permalink") + +在 GitLab 8.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2808) . + +如果您的开发工作流程要求每个合并请求都存在问题,则可以直接从该问题快速创建分支,以加快流程. 新分支及其以后的合并请求将被标记为与此问题相关. 合并后,MR 将自动关闭问题. 您可以在问题说明下方看到" **创建合并请求"**下拉列表. + +**注意:**如果已经有一个具有相同名称的分支或一个引用的合并请求,或者您的项目具有活动的派生关系,则不会看到" **创建合并请求"**按钮. 如果您想显示此按钮,则可能的解决方法是[删除项目的 fork 关系](../settings/index.html#removing-a-fork-relationship) . 删除后,派生关系将无法恢复,您将不再能够将合并请求发送到源. + +[![Create Button](img/ab48b86f7a0dfe92d4358f705bf938a8.png)](img/web_editor_new_branch_from_issue_create_button_v12_6.png) + +该下拉列表包含选项**创建合并请求和分支**以及**创建分支** . + +[![New Branch Button](img/2f78c411d32ee05e95a1984ef90b2356.png)](img/web_editor_new_branch_from_issue_v_12_6.png) + +选择这些选项之一后,将基于项目的默认分支(默认为`master`创建新的分支或分支与合并请求. 分支名称将基于问题的标题,并作为前缀具有其内部 ID. 因此,上面的示例屏幕快照将创建一个名为`2-make-static-site-auto-deploy-and-serve`的分支. + +当您在一个空的存储库项目中单击**创建分支**按钮时,GitLab 会自动创建一个`master`分支, `README.md`提交一个空白的`README.md`文件,并根据问题标题创建并将您重定向到新分支. 如果您的[项目已经配置了](../integrations/overview.html) Kubernetes 等[部署服务](../integrations/overview.html) ,则 GitLab 会更进一步,并通过帮助您创建`.gitlab-ci.yml`文件来提示您设置[自动部署](../../../topics/autodevops/stages.html#auto-deploy) . + +创建分支后,您可以编辑存储库中的文件以解决此问题. 当基于新创建的分支创建合并请求时,描述字段将自动显示[问题关闭模式](../issues/managing_issues.html#closing-issues-automatically) `Closes #ID` ,其中`ID`为问题的 ID. 一旦合并请求被合并,这将解决问题. + +### Create a new branch from a project’s dashboard[](#create-a-new-branch-from-a-projects-dashboard "Permalink") + +如果要在创建新的合并请求之前对多个文件进行更改,则可以预先创建一个新的分支. 在项目的文件页面上,从下拉列表中选择" **新建分支** ". + +[![New branch dropdown](img/83a4859fc1c1d9fc2ea68819a53eaea8.png)](img/web_editor_new_branch_dropdown.png) + +输入新的**分支名称** . (可选)更改" **创建自"**字段以选择该新分支将来自哪个分支,标记或提交 SHA. 如果您开始键入现有的分支或标签,则此字段将自动完成. 单击**创建分支** ,您将返回到该新分支上的文件浏览器. + +[![New branch page](img/dc5fe88e82dc925a618598e1ac284f39.png)](img/web_editor_new_branch_page.png) + +现在,您可以根据需要更改任何文件. 当您准备好将更改合并回母版时,可以使用屏幕顶部的小部件. 在创建分支或修改文件后,此窗口小部件仅显示一段时间. + +[![New push widget](img/2279c6b38c41208a2726d04b0df15c37.png)](img/web_editor_new_push_widget.png) + +## Create a new tag[](#create-a-new-tag "Permalink") + +标签可用于标记主要的里程碑,例如生产版本,候选版本等等. 您可以从分支或提交 SHA 创建标签. 在项目的文件页面上,从下拉列表中选择" **新建标签** ". + +[![New tag dropdown](img/a8ac57717b491533848b3ebca40aae86.png)](img/web_editor_new_tag_dropdown.png) + +给标签起一个名字,例如`v1.0.0` . 选择您要从中创建此新标签的分支或 SHA. 您可以选择添加一条消息和发行说明. 发行说明部分支持 Markdown 格式,您也可以上传附件. 单击**创建标签** ,您将被带到标签列表页面. + +[![New tag page](img/36d97eaa1e64c3f6d5b78d205d1ce881.png)](img/web_editor_new_tag_page.png) + +## Tips[](#tips "Permalink") + +创建或上载新文件或创建新目录时,可以触发新的合并请求,而不是直接提交给 master. 在**目标分支**字段中输入新的分支名称. 您会注意到出现一个复选框,标**有"通过这些更改启动新的合并请求"** . 提交更改后,您将进入新的合并请求表单. + +[![Start a new merge request with these changes](img/f293e9e73b2cf8c4ef278104fbd068d5.png)](img/web_editor_start_new_merge_request.png) + +如果你*不*希望使用您的主电子邮件地址通过 Web 编辑器创建的提交,您可以选择使用其他的链接的电子邮件地址的从**用户设置>编辑个人资料**页面. \ No newline at end of file diff --git a/docs/165.md b/docs/165.md new file mode 100644 index 0000000000000000000000000000000000000000..1e1dd4b3d89aa6d2a431b6a3a564b5bdc9c079c1 --- /dev/null +++ b/docs/165.md @@ -0,0 +1,285 @@ +# Web IDE + +> 原文:[https://docs.gitlab.com/ee/user/project/web_ide/](https://docs.gitlab.com/ee/user/project/web_ide/) + +* [Open the Web IDE](#open-the-web-ide) +* [File finder](#file-finder) +* [Syntax highlighting](#syntax-highlighting) + * [Themes](#themes) +* [Configure the Web IDE](#configure-the-web-ide) +* [Commit changes](#commit-changes) +* [Reviewing changes](#reviewing-changes) +* [View CI job logs](#view-ci-job-logs) +* [Switching merge requests](#switching-merge-requests) +* [Switching branches](#switching-branches) +* [Markdown editing](#markdown-editing) +* [Live Preview](#live-preview) + * [Enabling Live Preview](#enabling-live-preview) +* [Interactive Web Terminals for the Web IDE](#interactive-web-terminals-for-the-web-ide) + * [Runner configuration](#runner-configuration) + * [Web IDE configuration file](#web-ide-configuration-file) + * [Running interactive terminals in the Web IDE](#running-interactive-terminals-in-the-web-ide) + * [File syncing to web terminal](#file-syncing-to-web-terminal) + * [Limitations](#limitations) + * [Troubleshooting](#troubleshooting) + +# Web IDE[](#web-ide "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4539) . +* 在 10.7 版中[移至](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44157) GitLab Core. + +Web IDE 编辑器通过提供具有提交阶段的高级编辑器,可以更快,更轻松地为项目贡献更改. + +## Open the Web IDE[](#open-the-web-ide "Permalink") + +您可以从存储库文件列表和合并请求中查看文件时打开 Web IDE. + +[![Open Web IDE](img/7a0b5b2ee322d8676753d89561c1d3cb.png)](img/open_web_ide.png) + +## File finder[](#file-finder "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18323) in [GitLab Core](https://about.gitlab.com/pricing/) 10.8. + +通过文件查找器,您可以通过搜索快速打开当前分支中的文件. 使用键盘快捷键`Command-p` , `Control-p`或`t` (当编辑器不在焦点时)启动文件查找器. 输入文件名或文件路径片段以开始查看结果. + +## Syntax highlighting[](#syntax-highlighting "Permalink") + +正如 IDE 所期望的那样,Web IDE 中多种语言的语法突出显示将使您的直接编辑更加容易. + +Web IDE 当前提供: + +* 基本语法着色,适用于各种编程,脚本和标记语言,例如 XML,PHP,C#,C ++,Markdown,Java,VB,Batch,Python,Ruby 和 Objective-C. +* 某些语言的 IntelliSense 和验证支持(显示错误和警告,提供智能补全,格式设置和概述). 例如:TypeScript,JavaScript,CSS,LESS,SCSS,JSON 和 HTML. + +因为 Web IDE 基于[Monaco Editor](https://microsoft.github.io/monaco-editor/) ,所以您可以在[Monaco 语言](https://github.com/Microsoft/monaco-languages)存储库中找到更完整的受支持语言列表. 在幕后,摩纳哥使用[Monarch](https://microsoft.github.io/monaco-editor/monarch.html)库来突出显示语法. + +如果您缺少对任何语言的语法突出显示支持,我们准备了一份简短指南,介绍如何[为缺少的语言语法突出显示添加支持.](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/ide/lib/languages/README.md) + +**注意:**单个文件编辑基于[Ace 编辑器](https://ace.c9.io) . + +### Themes[](#themes "Permalink") + +版本历史 + +* 在 13.0 版的 GitLab 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2389) . +* GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/219228)了完全日光化黑暗主题. + +GitLab 支持的语法突出显示的所有主题都添加到了 Web IDE 的代码编辑器中. 您可以从个人[资料首选项中](../../profile/preferences.html)选择一个主题. + +主题仅在 Web IDE 文件编辑器中可用, [深色主题](https://gitlab.com/gitlab-org/gitlab/-/issues/209808)和[日光化深色主题](https://gitlab.com/gitlab-org/gitlab/-/issues/219228)除外,它们适用于整个 Web IDE 屏幕. + +| 日光灯主题 | 日晒黑暗主题 | 黑暗主题 | +| --- | --- | --- | +| [![Solarized Light Theme](img/d79207e6e4f140448c9dd5e6ebe5e380.png)](img/solarized_light_theme_v13_0.png) | [![Solarized Dark Theme](img/c187176d6b8d40e19db360c4c68ffb46.png)](img/solarized_dark_theme_v13_1.png) | [![Dark Theme](img/30152366655be1543f687603c8d34d96.png)](img/dark_theme_v13_0.png) | + +## Configure the Web IDE[](#configure-the-web-ide "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23352) in [GitLab Core](https://about.gitlab.com/pricing/) 13.1. + +Web IDE 支持使用[`.editorconfig`文件](https://editorconfig.org/)配置某些编辑器设置. 打开文件时,Web IDE 将在当前目录和所有父目录中查找名为`.editorconfig`的文件. 如果找到配置文件并且其设置与文件的路径匹配,则将在打开的文件上强制执行这些设置. + +Web IDE 当前支持以下`.editorconfig`设置: + +* `indent_style` +* `indent_size` +* `end_of_line` +* `trim_trailing_whitespace` +* `tab_width` +* `insert_final_newline` + +## Commit changes[](#commit-changes "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4539) . +* 在 10.7 版中[移至](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44157) GitLab Core. +* 从[GitLab 12.7 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/33441) ,将自动暂存文件. +* 从[GitLab 12.9 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/196609) ,删除了对暂存文件的支持,以防止丢失未暂存的数据. 您当前的所有更改都必须提交或放弃. + +进行更改后,单击左下角的" **提交"**按钮以查看已更改文件的列表. + +完成更改后,可以添加提交消息,提交更改并直接创建合并请求. 如果您没有对所选分支的写访问权,则会看到警告,但仍然可以创建新分支并启动合并请求. + +要放弃特定文件中的更改,请在"更改"选项卡中单击该文件上的" **放弃更改"**按钮. 要放弃所有更改,请单击更改侧栏右上角的垃圾桶图标. + +[![Commit changes](img/bad584bc95c83e26be6c67a2b54b26ae.png)](img/commit_changes_v12_9.png) + +## Reviewing changes[](#reviewing-changes "Permalink") + +提交更改之前,可以通过切换到查看模式或从更改列表中选择文件来将它们与上一次提交进行比较. + +当您打开合并请求时,还可以使用其他查看模式,如果您提交更改,该模式将向您显示合并请求 diff 的预览. + +## View CI job logs[](#view-ci-job-logs "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19279) in [GitLab Core](https://about.gitlab.com/pricing/) 11.0. + +您可以使用 Web IDE 通过在 Web IDE 中打开分支或合并请求并打开失败作业的日志来快速修复失败的测试. 通过单击右上角的" **管道"**按钮,可以访问最新管道的所有作业的状态以及当前提交的作业跟踪. + +管道状态也始终显示在左下方的状态栏中. + +## Switching merge requests[](#switching-merge-requests "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19318) in [GitLab Core](https://about.gitlab.com/pricing/) 11.0. + +要在创作的和分配的合并请求之间切换,请单击侧栏顶部的下拉列表以打开合并请求列表. 在切换到其他合并请求之前,您将需要提交或放弃所有更改. + +## Switching branches[](#switching-branches "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20850) in [GitLab Core](https://about.gitlab.com/pricing/) 11.2. + +To switch between branches of the current project repository, click the dropdown in the top of the sidebar to open a list of branches. You will need to commit or discard all your changes before switching to a different branch. + +## Markdown editing[](#markdown-editing "Permalink") + +版本历史 + +* [GitLab Core](https://about.gitlab.com/pricing/) 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18059)了 Markdown 预览. +* 支持在[GitLab Core](https://about.gitlab.com/pricing/) 13.1 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/22822)粘贴图像. + +在 Web IDE 中编辑 Markdown 文件时,可以通过单击文件编辑器上方的" **预览 Markdown"**选项卡来预览更改. Markdown 预览支持[GitLab 风味 Markdown](../../markdown.html#gitlab-flavored-markdown-gfm) . + +您还可以通过将任何本地图像直接粘贴到 Markdown 文件中来上传它们. 该图像将上传到同一目录,默认情况下命名为`image.png` . 如果已经存在相同名称的另一个文件,则将数字后缀自动添加到文件名. + +## Live Preview[](#live-preview "Permalink") + +版本历史 + +* 在[GitLab Core](https://about.gitlab.com/pricing/) 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19764) . +* 在 GitLab 13.0 中从*客户端评估* [重命名](https://gitlab.com/gitlab-org/gitlab/-/issues/213853)为*实时预览* . + +您可以使用 Web IDE 在浏览器中预览 JavaScript 项目. 此功能使用 CodeSandbox 编译和捆绑用于预览 Web 应用程序的 JavaScript. + +[![Web IDE Live Preview](img/7efae901a0febb2a8e969415dced271a.png)](img/live_preview_v13_0.png) + +Additionally, for public projects an **在 CodeSandbox 中打开** button is available to transfer the contents of the project into a public CodeSandbox project to quickly share your project with others. + +### Enabling Live Preview[](#enabling-live-preview "Permalink") + +需要在 GitLab 实例管理员设置中启用实时预览功能. 在 GitLab.com 上为所有项目启用了实时预览 + +[![Admin Live Preview setting](img/fb0d67715160a5a049ca0b8e7d7af698.png)](img/admin_live_preview_v13_0.png) + +完成此操作后,您可以使用`package.json`文件和 Web IDE 内的`main`入口点预览项目. 下面显示了一个示例`package.json` . + +``` +{ "main": "index.js", "dependencies": { "vue": "latest" } } +``` + +## Interactive Web Terminals for the Web IDE[](#interactive-web-terminals-for-the-web-ide "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/5426) . +* 在 13.1 版中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/211685) GitLab Core. + +**警告:** Web IDE 的交互式 Web 终端当前处于**Beta 中** . 共享运行程序[尚不支持交互式 Web 终端](https://gitlab.com/gitlab-org/gitlab/-/issues/24674) ,因此您需要使用自己的私有运行程序来使用此功能. + +[交互式 Web 终端](../../../ci/interactive_web_terminal/index.html)使项目[维护者](../../permissions.html#project-members-permissions)用户可以直接从 GitLab(包括通过 Web IDE)访问终端以与 Runner 进行交互. + +### Runner configuration[](#runner-configuration "Permalink") + +为了使交互式 Web 终端正常工作,需要在运行程序中配置一些内容: + +* 跑步者需要[正确配置`[session_server]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) . 本部分至少需要一个`session_timeout`值(默认为 1800 秒)和一个`listen_address`值. 如果未定义`advertise_address` ,则使用`listen_address` . +* 如果您对 GitLab 实例使用反向代理,则需要[启用](../../../administration/integration/terminal.html#enabling-and-disabling-terminal-support) Web 终端. + +如果您打开终端并且作业已完成其任务,则终端将在[`[session_server].session_timeout`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)配置的持续时间内阻止作业完成,直到关闭终端窗口. + +**注意:**并非所有执行程序都[受支持](https://docs.gitlab.com/runner/executors/) . [文件同步](#file-syncing-to-web-terminal)功能仅在 Kubernetes 运行程序上受支持. + +### Web IDE configuration file[](#web-ide-configuration-file "Permalink") + +为了启用 Web IDE 终端,您需要在存储库根目录内创建文件`.gitlab/.gitlab-webide.yml` . 该文件与[CI 配置文件的](../../../ci/yaml/README.html)语法非常相似,但有一些限制: + +* 无法定义全局块(即: `before_script`或`after_script` ) +* 只能将一个名为`terminal`作业添加到该文件中. +* 仅允许使用关键字`image` , `services` , `tags` , `before_script` , `script`和`variables`来配置作业. +* 要连接到交互式终端, `terminal`作业必须仍然处于活动状态并且正在运行,否则终端将无法连接到作业的会话. 默认情况下, `script`关键字的值是`sleep 60`以防止作业结束并为 Web IDE 提供足够的连接时间. 这意味着,如果您覆盖默认`script`值,则必须添加一个使作业保持运行`sleep`的命令,例如`sleep` . + +在下面的代码中,有此配置文件的示例: + +``` +terminal: + # This can be any image that has the necessary runtime environment for your project. + image: node:10-alpine + before_script: + - apt-get update + script: sleep 60 + variables: + RAILS_ENV: "test" + NODE_ENV: "test" +``` + +终端启动后,将显示控制台,我们可以访问项目存储库文件. + +**重要的** . 终端作业取决于分支. 这意味着用于触发和配置终端的配置文件将是 Web IDE 所选分支中的配置文件. + +如果分支中没有配置文件,将显示错误消息. + +### Running interactive terminals in the Web IDE[](#running-interactive-terminals-in-the-web-ide "Permalink") + +如果交互式终端可供当前用户使用,则" **终端"**按钮将显示在 Web IDE 的右侧栏中. 单击此按钮可以打开或关闭终端选项卡. + +打开后,该选项卡将显示" **启动 Web 终端"**按钮. 如果环境配置不正确,则可能禁用此按钮. 如果是这样,状态消息将描述问题. 以下是可能会禁用" **启动 Web 终端"的**一些原因: + +* `.gitlab/.gitlab-webide.yml`不存在或设置错误. +* 该项目没有活跃的私人跑步者. + +如果处于活动状态,则单击" **启动 Web 终端"**按钮将加载终端视图并开始连接到跑步者的终端. 任何时候都可以关闭并重新打开**终端**选项卡,并且不会影响终端的状态. + +当终端启动并成功连接到跑步者时,跑步者的外壳提示将出现在终端中. 在这里,您可以输入将在跑步者的环境中执行的命令. 这类似于在本地终端或通过 SSH 运行命令. + +在终端运行时,可以通过单击**Stop Terminal**停止它. 这将断开终端并停止跑步者的终端工作. 在此处,单击" **重新启动终端"**以启动新的终端会话. + +### File syncing to web terminal[](#file-syncing-to-web-terminal "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/5276) . +* 在 13.1 版中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/211686) GitLab Core. + +Web IDE 中的文件更改可以同步到正在运行的 Web 终端. 这使用户能够在预配置的终端环境中测试其代码更改. + +**注意:**仅将 Web IDE 中的文件更改同步到终端. 在终端中所做的更改**不会**同步到 Web IDE. 此功能仅适用于 Kubernetes Runners. + +要使文件同步到 Web 终端, `.gitlab/.gitlab-webide.yml`文件需要配置`webide-file-sync`服务. 这是使用此服务的 Node JS 项目的示例配置: + +``` +terminal: + # This can be any image that has the necessary runtime environment for your project. + image: + name: node:10-alpine + services: + - name: registry.gitlab.com/gitlab-org/webide-file-sync:latest + alias: webide-file-sync + entrypoint: ["/bin/sh"] + command: ["-c", "sleep 5 && ./webide-file-sync -project-dir $CI_PROJECT_DIR"] + ports: + # The `webide-file-sync` executable defaults to port 3000. + - number: 3000 +``` + +* 项目目录可用**后** ,必须启动`webide-file-sync`可执行文件. 这就是为什么我们需要在`command`添加`sleep 5`的原因. 有关更多信息,请参[见此问题](https://gitlab.com/gitlab-org/webide-file-sync/-/issues/7) . +* `$CI_PROJECT_DIR`是 GitLab Runners 的[预定义环境变量](../../../ci/variables/predefined_variables.html) . 这是您项目的存储库所在的位置. + +一旦将 Web 终端配置为用于文件同步,则在启动 Web 终端后,状态栏中将显示**终端**状态. + +[![Web IDE Client Side Evaluation](img/37238acd557de0d61f0c3be198c56e00.png)](img/terminal_status.png) + +在以下情况下,通过 Web IDE 对文件所做的更改将同步到正在运行的终端: + +* 编辑文件时,按`Ctrl` + `S` (在 Mac 上为`Cmd` + `S` ). +* 编辑文件后,将单击文件编辑器之外的所有内容. +* 创建,删除或重命名文件或文件夹. + +### Limitations[](#limitations "Permalink") + +交互式终端处于 beta 阶段,并将在以后的发行版中继续进行改进. 同时,请注意,用户一次只能拥有一个活动终端. + +### Troubleshooting[](#troubleshooting "Permalink") + +* 如果终端的文本为灰色且无响应,则表明终端已停止,无法再使用. 停止的终端可以通过单击**Restart Terminal 重新启动** . +* 如果终端显示**Connection Failure** ,则终端无法连接到流道. 请尝试停止并重新启动终端. 如果问题仍然存在,请仔细检查流道配置. \ No newline at end of file diff --git a/docs/166.md b/docs/166.md new file mode 100644 index 0000000000000000000000000000000000000000..ec97ba4bebc1a48cd7ed042d487875a9dfdb18e4 --- /dev/null +++ b/docs/166.md @@ -0,0 +1,160 @@ +# Requirements Management + +> 原文:[https://docs.gitlab.com/ee/user/project/requirements/](https://docs.gitlab.com/ee/user/project/requirements/) + +* [Create a requirement](#create-a-requirement) +* [Edit a requirement](#edit-a-requirement) +* [Archive a requirement](#archive-a-requirement) +* [Reopen a requirement](#reopen-a-requirement) +* [Search for a requirement](#search-for-a-requirement) +* [Allow requirements to be satisfied from a CI job](#allow-requirements-to-be-satisfied-from-a-ci-job) + * [Add the manual job to CI](#add-the-manual-job-to-ci) + * [Specifying individual requirements](#specifying-individual-requirements) + * [Add the manual job to CI conditionally](#add-the-manual-job-to-ci-conditionally) + +# Requirements Management[](#requirements-management-ultimate "Permalink") + +[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2703) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. + +根据要求,您可以设置标准来检查产品. 它们可以基于用户,涉众,系统,软件或您认为重要的其他任何内容. + +需求是 GitLab 中的工件,用于描述产品的特定行为. 需求是长期存在的,除非手动清除,否则它们不会消失. + +如果行业标准*要求*您的应用程序具有某些功能或行为,则可以[创建一个要求](#create-a-requirement)来反映这一点. 如果不再需要某个功能,则可以[归档相关需求](#archive-a-requirement) . + +有关概述,请参见[GitLab 12.10 引入需求管理](https://www.youtube.com/watch?v=uSS7oUNSEoU) . + +[![requirements list view](img/56d89ff1e02ecf30404a57092adae96d.png)](img/requirements_list_v13_1.png) + +## Create a requirement[](#create-a-requirement "Permalink") + +每个项目都有一个分页的需求清单,您可以在其中创建一个新需求. + +创建需求: + +1. 在您的项目页面上,转到 **要求** . +2. Click **新要求**. +3. 输入描述性标题,然后单击**创建需求** . + +您将在列表顶部看到新创建的需求,因为需求列表按创建日期降序排列. + +## Edit a requirement[](#edit-a-requirement "Permalink") + +您可以从需求列表页面编辑需求(如果您具有必要的特权). + +要编辑需求: + +1. 在需求清单中,按一下[ **编辑** ( ). +2. 在文本输入字段中更新标题. +3. Click **保存更改**. + +## Archive a requirement[](#archive-a-requirement "Permalink") + +在" **打开"**选项卡中时,可以存档一个未完成的需求(如果有必要的特权). + +要存档需求,请点击**存档** ( ). + +需求存档后,它不再出现在" **打开"**选项卡中. + +## Reopen a requirement[](#reopen-a-requirement "Permalink") + +您可以在"已**归档"**选项卡中查看已归档需求的列表. + +[![archived requirements list](img/596a395127f6b3d5c9d1deac3f676680.png)](img/requirements_archived_list_view_v13_1.png) + +要重新打开已归档的需求,请点击**重新打开** . + +重新打开需求后,它不再出现在" **归档"**选项卡中. + +## Search for a requirement[](#search-for-a-requirement "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212543) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1. + +您可以根据以下条件从需求列表页面中搜索需求: + +* 要求标题 +* 作者的用户名 + +要搜索需求: + +1. 在一个项目中,转到 **需求>清单** . +2. 单击**搜索或过滤结果**字段. 出现一个下拉菜单. +3. 从下拉列表中选择需求作者或输入纯文本以按需求标题进行搜索. +4. 在键盘上按`Enter`键以过滤列表. + +您还可以通过以下方式对需求列表进行排序: + +* 创建日期 +* 最近更新时间 + +## Allow requirements to be satisfied from a CI job[](#allow-requirements-to-be-satisfied-from-a-ci-job "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2859) . +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2 中[增加](https://gitlab.com/gitlab-org/gitlab/-/issues/215514)了指定个别要求及其状态的功能. + +GitLab 现在支持[需求测试报告](../../../ci/pipelines/job_artifacts.html#artifactsreportsrequirements-ultimate) . 您可以将作业添加到 CI 管道,该作业在触发时会将所有现有需求标记为"满足". + +### Add the manual job to CI[](#add-the-manual-job-to-ci "Permalink") + +要配置您的 CI 以在触发手动作业时将要求标记为"满足",请将以下代码添加到`.gitlab-ci.yml`文件中. + +``` +requirements_confirmation: + when: manual + allow_failure: false + script: + - mkdir tmp + - echo "{\"*\":\"passed\"}" > tmp/requirements.json + artifacts: + reports: + requirements: tmp/requirements.json +``` + +此定义将手动触发的( `when: manual` )作业添加到 CI 管道. 它阻止了( `allow_failure: false` ),但是由您决定触发 CI 作业的条件是什么. 另外,您可以使用任何现有的 CI 作业将所有需求标记为已满足,前提是 CI 作业生成并上传了`requirements.json`工件. + +当您手动触发此作业时,包含`{"*":"passed"}`的`requirements.json`文件将作为工件上传到服务器. 在服务器端,将检查需求报告中的"所有通过"记录( `{"*":"passed"}` ),并在成功后将所有现有的打开需求标记为"满意". + +#### Specifying individual requirements[](#specifying-individual-requirements "Permalink") + +可以指定个别要求及其状态. + +如果存在以下要求: + +* `REQ-1` (具有 IID `1` ) +* `REQ-2` (具有 IID `2` ) +* `REQ-3` (具有 IID `3` ) + +可以指定第一个要求通过,第二个失败. 有效值为"通过"和"失败". 通过省略需求 IID(在这种情况下为`REQ-3`的 IID `3` ),没有发现结果. + +``` +requirements_confirmation: + when: manual + allow_failure: false + script: + - mkdir tmp + - echo "{\"1\":\"passed\", \"2\":\"failed\"}" > tmp/requirements.json + artifacts: + reports: + requirements: tmp/requirements.json +``` + +### Add the manual job to CI conditionally[](#add-the-manual-job-to-ci-conditionally "Permalink") + +要将 CI 配置为仅在有某些开放要求时才包括手动作业,请添加一条规则以检查`CI_HAS_OPEN_REQUIREMENTS` CI 变量. + +``` +requirements_confirmation: + rules: + - if: "$CI_HAS_OPEN_REQUIREMENTS" == "true" + when: manual + - when: never + allow_failure: false + script: + - mkdir tmp + - echo "{\"*\":\"passed\"}" > tmp/requirements.json + artifacts: + reports: + requirements: tmp/requirements.json +``` \ No newline at end of file diff --git a/docs/167.md b/docs/167.md new file mode 100644 index 0000000000000000000000000000000000000000..da809430dfcae16b64b3db73b630a929108ce1b7 --- /dev/null +++ b/docs/167.md @@ -0,0 +1,244 @@ +# Project settings + +> 原文:[https://docs.gitlab.com/ee/user/project/settings/](https://docs.gitlab.com/ee/user/project/settings/) + +* [General settings](#general-settings) + * [General project settings](#general-project-settings) + * [Compliance framework](#compliance-framework-premium) + * [Sharing and permissions](#sharing-and-permissions) + * [Disabling email notifications](#disabling-email-notifications) + * [Merge request settings](#merge-request-settings) + * [Service Desk](#service-desk-starter) + * [Export project](#export-project) + * [Advanced settings](#advanced-settings) + * [Archiving a project](#archiving-a-project) + * [Unarchiving a project](#unarchiving-a-project) + * [Renaming a repository](#renaming-a-repository) + * [Transferring an existing project into another namespace](#transferring-an-existing-project-into-another-namespace) + * [Remove a project](#remove-a-project) + * [Restore a project](#restore-a-project-premium) + * [Removing a fork relationship](#removing-a-fork-relationship) +* [Operations settings](#operations-settings) + * [Error Tracking](#error-tracking) + * [Jaeger tracing](#jaeger-tracing-ultimate) + * [Status Page](#status-page) + +# Project settings[](#project-settings "Permalink") + +**注意:**只有项目维护者和管理员用户[有权](../../permissions.html#project-members-permissions)访问项目设置. + +您可以通过导航到项目的主页并点击**设置**来调整[项目](../index.html)设置. + +## General settings[](#general-settings "Permalink") + +在项目的常规设置下,您可以找到与项目功能有关的所有内容. + +### General project settings[](#general-project-settings "Permalink") + +调整项目的名称,描述,头像, [默认分支](../repository/branches/index.html#default-branch)和主题: + +[![general project settings](img/743ce9a40d40e900e957589a9024f116.png)](img/general_settings.png) + +项目描述还部分支持[标准 Markdown](../../markdown.html#standard-markdown-and-extensions-in-gitlab) . 您可以使用[强调](../../markdown.html#emphasis) , [链接](../../markdown.html#links)和[换行符](../../markdown.html#line-breaks)为项目描述添加更多上下文. + +#### Compliance framework[](#compliance-framework-premium "Permalink") + +您可以选择一个框架标签来标识您的项目具有某些合规性要求或需要其他监督. 可用的标签包括: + +* GDPR-通用数据保护法规 +* HIPAA-健康保险可移植性和责任法案 +* PCI-DSS-支付卡行业数据安全标准 +* SOC 2-服务组织控制 2 +* SOX-萨班斯-奥克斯利 + +### Sharing and permissions[](#sharing-and-permissions "Permalink") + +对于您的存储库,您可以设置功能,例如公共访问,存储库功能,文档,访问权限等等. 要从您的项目中执行此操作,请转到**"设置"** >" **常规"** ,然后展开" **可见性","项目功能","权限"**部分. + +现在,您可以更改[项目可见性](../../../public_access/public_access.html) . 如果将" **项目可见性"**设置为公开,则可以将某些功能的访问权限限制为" **仅项目成员"** . 此外,您可以选择[允许用户请求访问权限](../members/index.html#project-membership-and-requesting-access)的选项. + +**警告:**如果[降低项目的可见性级别](../../../public_access/public_access.html#reducing-visibility) ,则该操作将取消该项目的所有分支的链接. + +使用开关启用或禁用以下功能: + +| Option | 更多访问限制选项 | Description | +| --- | --- | --- | +| **Issues** | ✓ | 激活 GitLab 问题跟踪器 | +| **Repository** | ✓ | Enables [repository](../repository/) functionality | +| **合并请求** | ✓ | 启用[合并请求](../merge_requests/)功能; 另请参阅[合并请求设置](#merge-request-settings) | +| **Forks** | ✓ | Enables [forking](../index.html#fork-a-project) functionality | +| **Pipelines** | ✓ | Enables [CI/CD](../../../ci/README.html) functionality | +| **集装箱登记处** |   | 为您的 Docker 映像激活[注册表](../../packages/container_registry/) | +| **Git 大文件存储** |   | 允许使用[大文件](../../../topics/git/lfs/index.html#git-large-file-storage-lfs) | +| **Packages** |   | Supports configuration of a [package registry](../../../administration/packages/index.html#gitlab-package-registry-administration-premium-only) functionality | +| **Wiki** | ✓ | 启用单独的[文档](../wiki/)系统 | +| **Snippets** | ✓ | Enables [sharing of code and text](../../snippets.html) | +| **Pages** | ✓ | 允许您[发布静态网站](../pages/) | +| **指标仪表板** | ✓ | 控制对[指标仪表板的](../integrations/prometheus.html)访问 | + +一些功能取决于其他功能: + +* 如果禁用" **问题"**选项,则 GitLab 还将删除以下功能: + * **发行板** + * [**服务台**](#service-desk-starter)**注意:**禁用" **问题"**选项后,您仍然可以从合并请求访问**里程碑** . +* 此外,如果您同时禁用**Issues**和**Merge Requests** ,则将无法再访问: + * **标签** + * **大事记** +* 如果禁用**存储库**功能,GitLab 还将为您的项目禁用以下功能: + * **合并请求** + * **流水线** + * **集装箱登记处** + * **Git 大文件存储** + * **配套** +* 指标仪表板访问要求同时阅读项目环境和部署. 有权访问指标仪表板的用户还可以访问环境和部署. + +#### Disabling email notifications[](#disabling-email-notifications "Permalink") + +项目所有者可以通过选中" **禁用电子邮件通知"**复选框来**禁用**与项目相关的所有[电子邮件通知](../../profile/notifications.html#gitlab-notification-emails) . + +### Merge request settings[](#merge-request-settings "Permalink") + +设置项目的合并请求设置: + +* 设置合并请求方法(合并提交, [快速合并](../merge_requests/fast_forward_merge.html) ). +* 添加合并请求[描述模板](../description_templates.html#description-templates) . +* Enable [merge request approvals](../merge_requests/merge_request_approvals.html). +* Enable [merge only if pipeline succeeds](../merge_requests/merge_when_pipeline_succeeds.html). +* Enable [merge only when all threads are resolved](../../discussions/index.html#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved). +* Enable [`delete source branch after merge` option by default](../merge_requests/getting_started.html#deleting-the-source-branch) +* Configure [suggested changes commit messages](../../discussions/index.html#configure-the-commit-message-for-applied-suggestions) + +[![project's merge request settings](img/813cda0881e353d15eed9ca9417104f1.png)](img/merge_requests_settings.png) + +### Service Desk[](#service-desk-starter "Permalink") + +为您的项目启用[Service Desk](../service_desk.html)以提供客户支持. + +### Export project[](#export-project "Permalink") + +了解如何在 GitLab 中[导出项目](import_export.html#importing-the-project) . + +### Advanced settings[](#advanced-settings "Permalink") + +在这里,您可以运行内部管理,存档,重命名,传输, [删除派生关系](#removing-a-fork-relationship)或删除项目. + +#### Archiving a project[](#archiving-a-project "Permalink") + +归档项目后,所有用户都将其设为只读,并表明该项目已不再处于主动维护状态. 也可以取消归档已归档的项目. 只有项目所有者和管理员用户才[有权](../../permissions.html#project-members-permissions)归档项目. + +归档项目后,存储库,问题,合并请求和所有其他功能均为只读. 归档的项目也隐藏在项目列表中. + +归档项目: + +1. 导航到您项目的 **设置>常规** . +2. 在" **高级"下** ,单击" **展开"** . +3. 在" **存档项目"**部分中,单击" **存档项目"**按钮. +4. 根据要求确认操作. + +#### Unarchiving a project[](#unarchiving-a-project "Permalink") + +取消归档项目会删除对项目的只读限制,并使其在项目列表中可用. 只有项目所有者和管理员用户才[有权](../../permissions.html#project-members-permissions)取消归档项目. + +要查找已归档的项目: + +1. 以具有项目所有者或管理员权限的用户身份登录到 GitLab. +2. 如果你: + * 拥有项目的 URL,在浏览器中打开项目的页面. + * 没有项目的 URL:1.单击**项目>浏览项目** . 1.在" **排序项目"**下拉框中,选择" **显示存档的项目"** . 1.在**按名称过滤**字段中,提供项目的名称. 1.单击指向项目的链接以打开其" **详细信息"**页面. + +接下来,要取消归档项目: + +1. 导航到您项目的 **设置>常规** . +2. Under **Advanced**, click **Expand**. +3. 在" **取消存档项目"**部分中,单击" **取消存档项目"**按钮. +4. 根据要求确认操作. + +#### Renaming a repository[](#renaming-a-repository "Permalink") + +**注意:**只有项目维护者和管理员用户才[有权](../../permissions.html#project-members-permissions)重命名存储库. 不要与项目名称混淆,也可以从[常规项目设置中](#general-project-settings)进行更改. + +项目的存储库名称定义其 URL(您用于通过浏览器访问该项目的 URL)及其在安装 GitLab 的文件磁盘上的位置. + +要重命名存储库: + +1. 导航到您项目的 **设置>常规** . +2. 在" **高级"下** ,单击" **展开"** . +3. 在"重命名存储库"下,根据您的喜好更改"路径". +4. Hit **重命名项目**. + +请记住,这可能会带来意想不到的副作用,因为使用旧网址的每个人都无法推送或拉动. 阅读有关[重命名存储库时重定向](../index.html#redirects-when-changing-repository-paths)发生的更多[信息](../index.html#redirects-when-changing-repository-paths) . + +#### Transferring an existing project into another namespace[](#transferring-an-existing-project-into-another-namespace "Permalink") + +**注意:**只有项目所有者和管理员用户才[有权](../../permissions.html#project-members-permissions)传输项目. + +在以下情况下,您可以将现有项目转移到[组中](../../group/index.html) : + +* 您至少对该组具有**维护者** [权限](../../permissions.html#project-members-permissions) . +* 您至少是要转让的项目的**所有者** . +* 将项目转移到的组必须允许创建新项目. + +转移项目: + +1. 导航到您项目的 **设置>常规** . +2. 在" **高级"下** ,单击" **展开"** . +3. 在"传输项目"下,选择要将项目传输到的名称空间. +4. 按照说明键入项目路径,以确认传输. + +完成后,您将被带到新项目的名称空间. 此时,请阅读[从旧项目到新项目](../index.html#redirects-when-changing-repository-paths)的[重定向](../index.html#redirects-when-changing-repository-paths)发生了什么. + +**注意:**如果需要,GitLab 管理员可以使用管理界面将任何项目移动到任何名称空间. + +#### Remove a project[](#remove-a-project "Permalink") + +**注意:**只有项目所有者和管理员才[有权](../../permissions.html#project-members-permissions)删除项目. + +删除项目: + +1. 导航到您的项目,然后选择 **设置>常规>高级** . +2. 在"删除项目"部分中,单击" **删除项目"**按钮. +3. 根据要求确认操作. + +这个动作: + +* 删除包含所有相关资源(问题,合并请求等)的项目. +* 从[Premium 或 Silver](https://about.gitlab.com/pricing/)或更高级别的[GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) ,组管理员可以[将](../../group/index.html#enabling-delayed-project-removal-premium)组内的项目[配置](../../group/index.html#enabling-delayed-project-removal-premium)为在延迟一段时间后删除. 启用后,实际删除将在[实例设置中](../../admin_area/settings/visibility_and_access_controls.html#default-deletion-adjourned-period-premium-only)指定的天数后发生. + +**Warning:** The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6 was changed to [Immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2. + +#### Restore a project[](#restore-a-project-premium "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) . + +要还原标记为删除的项目: + +1. 导航到您的项目,然后选择 **设置>常规>高级** . +2. 在"还原项目"部分中,单击" **还原项目"**按钮. + +#### Removing a fork relationship[](#removing-a-fork-relationship "Permalink") + +分叉是为您不是会员[的项目](../repository/forking_workflow.html)做[贡献](../repository/forking_workflow.html)的好方法. 如果您想自己使用 fork,而无需将[合并请求](../merge_requests.html)发送到上游项目,则可以安全地删除 fork 关系. + +**注意:**删除后,将无法恢复派生关系. 您将不再能够将合并请求发送到源,并且如果有人分叉了您的项目,他们的分支也将失去关系. + +为此: + +1. 导航到项目的**设置>常规>高级** . +2. 在" **删除分叉关系"下** ,单击同样标记的按钮. +3. 按照说明键入项目的路径,以确认操作. + +**注意:**只有项目所有者[有权](../../permissions.html#project-members-permissions)删除派生关系. + +## Operations settings[](#operations-settings "Permalink") + +### Error Tracking[](#error-tracking "Permalink") + +配置错误跟踪以[在 GitLab 中](../operations/error_tracking.html)发现和查看[Sentry 错误](../operations/error_tracking.html) . + +### Jaeger tracing[](#jaeger-tracing-ultimate "Permalink") + +添加 Jaeger 服务器的 URL,以使您的用户可以[从 GitLab 轻松访问 Jaeger UI](../../../operations/tracing.html) . + +### Status Page[](#status-page "Permalink") + +[添加存储凭据](../status_page/#syncing-incidents-to-the-status-page)以启用将公共问题同步到已[部署状态页面的功能](../status_page/#status-page-project) . \ No newline at end of file diff --git a/docs/168.md b/docs/168.md new file mode 100644 index 0000000000000000000000000000000000000000..78ed81069ad163e008d15142e6cccb4eecb58562 --- /dev/null +++ b/docs/168.md @@ -0,0 +1,172 @@ +# Project import/export + +> 原文:[https://docs.gitlab.com/ee/user/project/settings/import_export.html](https://docs.gitlab.com/ee/user/project/settings/import_export.html) + +* [Important notes](#important-notes) +* [Version history](#version-history) + * [13.0+](#130) + * [12.x](#12x) +* [Between CE and EE](#between-ce-and-ee) +* [Exported contents](#exported-contents) +* [Exporting a project and its data](#exporting-a-project-and-its-data) +* [Importing the project](#importing-the-project) + * [Project import status](#project-import-status) + * [Import large projects](#import-large-projects-core-only) +* [Rate limits](#rate-limits) + +# Project import/export[](#project-importexport "Permalink") + +版本历史 + +* 在 GitLab 8.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3050) . +* 从 GitLab 10.0,管理员可以在 GitLab 实例上禁用项目导出选项. + +可以将在任何 GitLab 实例或 GitLab.com 上运行的现有项目及其所有相关数据导出,并移入新的 GitLab 实例. + +如果启用了项目导入选项,则会显示**GitLab 导入/导出**按钮. + +也可以看看: + +* [Project import/export API](../../../api/project_import_export.html) +* [Project import/export administration Rake tasks](../../../administration/raketasks/project_import_export.html) +* [Group import/export](../../group/settings/import_export.html) +* [Group import/export API](../../../api/group_import_export.html) + +设置项目导入/导出: + +1. 导航 **管理区>** **设置>可见性和访问控制** . +2. 滚动到**导入源** +3. 启用所需的**导入源** + +## Important notes[](#important-notes "Permalink") + +请注意以下几点: + +* 不支持从较新版本的 GitLab 导入. 导入的 GitLab 版本必须大于或等于导出的 GitLab 版本. +* 除非导入和导出 GitLab 实例与[版本历史记录中](#version-history)描述的兼容,否则导入将失败. +* 导出存储在一个临时[共享目录中](../../../development/shared_files.html) ,并由特定工作人员每 24 小时删除一次. +* 只要用户对所导出项目所在的组具有维护者或管理员访问权限,组成员就会作为项目成员导出. +* 具有所有者访问权限的项目成员将被导入为维护者. +* 使用管理员帐户导入将通过电子邮件地址映射用户(仅限自我管理). 否则,将留下补充评论,以提及原始作者和 MR,注释或问题将归进口商所有. +* 如果导入的项目包含源自派生的合并请求,则将在导入/导出期间在项目内创建与此类合并请求关联的新分支. 因此,导出项目中的分支数量可能会大于原始项目中的分支数量. + +## Version history[](#version-history "Permalink") + +### 13.0+[](#130 "Permalink") + +从 GitLab 13.0 开始,GitLab 可以导入从其他 GitLab 部署导出的捆绑软件. 此功能仅限于之前的两个 GitLab [次要](../../../policy/maintenance.html#versioning)发行版,这与我们的[安全发布](../../../policy/maintenance.html#security-releases)流程类似. + +例如: + +| 当前版本 | 可以导入从 | +| --- | --- | +| 13.0 | 13.0, 12.10, 12.9 | +| 13.1 | 13.1, 13.0, 12.10 | + +### 12.x[](#12x "Permalink") + +在 13.0 之前,这是一个已定义的兼容性表: + +| 导出 GitLab 版本 | 导入 GitLab 版本 | +| --- | --- | +| 11.7 至 12.10 | 11.7 至 12.10 | +| 11.1 至 11.6 | 11.1 至 11.6 | +| 10.8 至 11.0 | 10.8 至 11.0 | +| 10.4 至 10.7 | 10.4 至 10.7 | +| 10.3 | 10.3 | +| 10.0 至 10.2 | 10.0 至 10.2 | +| 9.4 至 9.6 | 9.4 至 9.6 | +| 9.2 至 9.3 | 9.2 至 9.3 | +| 8.17 至 9.1 | 8.17 至 9.1 | +| 8.13 至 8.16 | 8.13 至 8.16 | +| 8.12 | 8.12 | +| 8.10.3 至 8.11 | 8.10.3 至 8.11 | +| 8.10.0 至 8.10.2 | 8.10.0 至 8.10.2 | +| 8.9.5 至 8.9.11 | 8.9.5 至 8.9.11 | +| 8.9.0 至 8.9.4 | 8.9.0 至 8.9.4 | + +只能在具有匹配导入/导出版本的 GitLab 版本之间导出和导入项目. + +例如,8.10.3 和 8.11 具有相同的导入/导出版本(0.1.3),它们之间的导出将兼容. + +## Between CE and EE[](#between-ce-and-ee "Permalink") + +您可以将项目从[Community Edition](https://about.gitlab.com/install/ce-or-ee/)导出[到 Enterprise Edition](https://about.gitlab.com/install/ce-or-ee/) ,反之亦然. 假定满足[版本历史记录](#version-history)要求. + +如果要将项目从企业版导出到社区版,则可能会丢失仅保留在企业版中的数据. 有关更多信息,请参阅[从 EE 降级为 CE](../../../README.html) . + +## Exported contents[](#exported-contents "Permalink") + +将导出以下项目: + +* 项目和 Wiki 存储库 +* 项目上传 +* 项目配置,不包括集成 +* 注释问题,带有差异和注释的合并请求,标签,里程碑,摘要,时间跟踪和其他项目实体 +* 设计管理文件和数据 +* LFS 对象 +* 发行板 +* 管道历史 + +以下项目将不会导出: + +* 建立痕迹和工件 +* 容器注册表映像 +* 可变配置项 +* Webhooks +* 任何加密令牌 +* 合并请求批准者 +* 推送规则 +* Awards + +**注意:**有关项目导出中[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/import_export/project/import_export.yml)的特定数据的更多详细信息,请参阅[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/import_export/project/import_export.yml)文件. + +## Exporting a project and its data[](#exporting-a-project-and-its-data "Permalink") + +1. 转到项目的主页. + +2. 请点击 侧栏中的**设置** . + +3. 向下滚动以找到" **导出项目"**按钮: + + [![Export button](img/5f6c85f0240f3ec56519dde74a715dba.png)](img/import_export_export_button.png) + +4. 生成导出后,您应该会收到一封电子邮件,其中包含用于下载文件的链接: + + [![Email download link](img/3e903eab58c2b1ac777ef30adf3bd44e.png)](img/import_export_mail_link.png) + +5. 或者,您可以返回项目设置并从那里下载文件,或生成新的导出. 文件可用后,页面应显示" **下载导出"**按钮: + + [![Download export](img/0b5158f524983df0ee4e4aa152abcc86.png)](img/import_export_download_export.png) + +## Importing the project[](#importing-the-project "Permalink") + +1. 在创建新项目时,GitLab 项目导入功能是第一个导入选项. 点击**GitLab 导出** : + + [![New project](img/abdf7941c6dc575d115b24d74a80a68b.png)](img/import_export_new_project.png) + +2. 输入您的项目名称和 URL. 然后选择您之前导出的文件: + + [![Select file](img/7356a350b6fac674fc341d110380f723.png)](img/import_export_select_file.png) + +3. 单击**导入项目**开始导入. 您新导入的项目页面将很快出现. + +**注意:**如果" `Internal`可见性级别[的使用受到限制](../../../public_access/public_access.html#restricting-the-use-of-public-or-internal-projects) ,则所有导入的项目都将获得" `Private`的可见性.**注意:**可以由管理员设置最大导入文件大小,默认为 50MB. 作为管理员,您可以修改最大导入文件大小. 为此,请在" [应用程序设置" API](../../../api/settings.html#change-application-settings)或" [管理界面"中](../../admin_area/settings/account_and_limit_settings.html)使用`max_import_size`选项. + +### Project import status[](#project-import-status "Permalink") + +您可以通过[Project import / export API](../../../api/project_import_export.html#import-status)查询导入. 如 API 文档中所述,查询可能返回导入错误或异常. + +### Import large projects[](#import-large-projects-core-only "Permalink") + +如果您的项目较大,请考虑使用 Rake 任务,如[开发人员文档中所述](../../../development/import_project.html#importing-via-a-rake-task) . + +## Rate limits[](#rate-limits "Permalink") + +为了避免滥用,用户的速率仅限于: + +| 请求类型 | Limit | +| --- | --- | +| Export | 每 5 分钟 30 个项目 | +| 下载导出 | 每 10 分钟有 10 个下载项目 | +| Import | 每 5 分钟 30 个项目 | \ No newline at end of file diff --git a/docs/169.md b/docs/169.md new file mode 100644 index 0000000000000000000000000000000000000000..b6eaea447512686c4c2b0f4791ee5cb7f073fa15 --- /dev/null +++ b/docs/169.md @@ -0,0 +1,77 @@ +# Project access tokens (Alpha) + +> 原文:[https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html) + +* [Creating a project access token](#creating-a-project-access-token) +* [Project bot users](#project-bot-users) +* [Revoking a project access token](#revoking-a-project-access-token) +* [Limiting scopes of a project access token](#limiting-scopes-of-a-project-access-token) + * [Enable or disable project access tokens](#enable-or-disable-project-access-tokens) + +# Project access tokens (Alpha)[](#project-access-tokens-alpha-core-only "Permalink") + +**警告:**这是[Alpha](https://about.gitlab.com/handbook/product/#alpha)功能,随时可能更改,恕不另行通知.版本历史 + +* 在 GitLab 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2587) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上已禁用. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-project-access-tokens) . + +项目访问令牌的范围仅限于项目,可用于通过[GitLab API](../../../api/README.html#personalproject-access-tokens)进行身份验证. + +您还可以将项目访问令牌与 Git 一起使用,以通过 HTTP 或 SSH 进行身份验证. + +项目访问令牌在您定义的日期 UTC 午夜到期. + +有关如何使用项目访问令牌对 API 进行身份验证的示例,请参见[API 文档中](../../../api/README.html#personalproject-access-tokens)的以下部分. + +## Creating a project access token[](#creating-a-project-access-token "Permalink") + +1. 登录到 GitLab. +2. 导航至您要为其创建访问令牌的项目. +3. 在里面 **在设置**菜单中,选择**访问令牌** . +4. 选择令牌的名称和可选的到期日期. +5. 选择[所需的范围](#limiting-scopes-of-a-project-access-token) . +6. 单击**创建项目访问令牌**按钮. +7. 将项目访问令牌保存在安全的地方. 离开或刷新页面后,将无法再次访问它. + +## Project bot users[](#project-bot-users "Permalink") + +对于创建的每个项目访问令牌,还将创建一个机器人用户,并将其添加到具有["维护者"级别权限](../../permissions.html#project-members-permissions)的项目中. 使用项目访问令牌进行的 API 调用将与相应的 bot 用户相关联. + +这些用户将出现在" **成员"中,**但不能被修改. 此外,该漫游器用户无法添加到任何其他项目. + +[吊销](#revoking-a-project-access-token)项目访问令牌后,该漫游器用户将被删除,所有记录都将被移动到用户名" Ghost User"的系统范围内的用户. 有关更多信息,请参见[关联记录](../../profile/account/delete_account.html#associated-records) . + +## Revoking a project access token[](#revoking-a-project-access-token "Permalink") + +您可以随时通过单击相应的" **撤消"**按钮来撤消任何项目访问令牌. **设置>访问令牌** . + +## Limiting scopes of a project access token[](#limiting-scopes-of-a-project-access-token "Permalink") + +可以使用一个或多个范围创建项目访问令牌,这些范围允许给定令牌可以执行各种操作. 下表描述了可用范围. + +| Scope | Description | +| --- | --- | +| `api` | 授予对范围内的项目 API 的完全读取/写入访问权限. | +| `read_api` | 授予对范围内的项目 API 的读取权限. | +| `read_registry` | 如果项目是私有的并且需要授权,则允许对[容器注册表](../../packages/container_registry/index.html)图像的读取(拉). | +| `write_registry` | 允许对[容器注册表](../../packages/container_registry/index.html)进行写访问(推送). | +| `read_repository` | 允许对存储库进行只读访问(拉). | +| `write_repository` | 允许对存储库进行读写访问(拉,推). | + +### Enable or disable project access tokens[](#enable-or-disable-project-access-tokens "Permalink") + +项目访问令牌是[Alpha](https://about.gitlab.com/handbook/product/#alpha)功能,不建议用于生产环境. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以为您的实例启用它. + +To enable it: + +``` +Feature.enable(:resource_access_token) +``` + +禁用它: + +``` +Feature.disable(:resource_access_token) +``` \ No newline at end of file diff --git a/docs/170.md b/docs/170.md new file mode 100644 index 0000000000000000000000000000000000000000..1c26d2eeced0a4062a2d625612a63702b936ec39 --- /dev/null +++ b/docs/170.md @@ -0,0 +1,58 @@ +# Share Projects with other Groups + +> 原文:[https://docs.gitlab.com/ee/user/project/members/share_project_with_groups.html](https://docs.gitlab.com/ee/user/project/members/share_project_with_groups.html) + +* [Groups as collections of users](#groups-as-collections-of-users) +* [Sharing a project with a group of users](#sharing-a-project-with-a-group-of-users) +* [Maximum access level](#maximum-access-level) +* [Sharing public project with private group](#sharing-public-project-with-private-group) +* [Share project with group lock](#share-project-with-group-lock) + +# Share Projects with other Groups[](#share-projects-with-other-groups "Permalink") + +您可以与其他[小组](../../group/index.html)共享项目. 这样就可以通过一个操作将一组用户添加到项目中. + +## Groups as collections of users[](#groups-as-collections-of-users "Permalink") + +组主要用于[创建项目集合](../../group/index.html) ,但是您还可以利用以下事实:组定义了*用户*集合,即组成员. + +## Sharing a project with a group of users[](#sharing-a-project-with-a-group-of-users "Permalink") + +在 GitLab 中授予一组用户(例如"工程")访问项目(例如" Acme 项目")的主要机制是使"工程"组成为" Project Acme"的所有者. 但是,如果" Acme 项目"已经属于另一个小组,比如"开源",该怎么办? 这是可以使用组共享功能的地方. + +与"工程"组共享" Acme 项目": + +1. 对于" Acme 项目",请使用左侧导航菜单转到" **会员"** + + [![share project with groups](img/0d1c10a8d14f11dd831b96878fc521e5.png)](img/share_project_with_groups.png) + +2. 选择"与组共享"标签 +3. 添加具有您选择的最大访问权限级别的"工程"组 +4. 点击**共享**分享 + + [![share project with groups tab](img/0e2287fb4b32bf9dff45f3255ddd45fe.png)](img/share_project_with_groups_tab.png) + +5. 与"工程"共享"项目 Acme"后,该项目将列在组仪表板上 + + [!['Project Acme' is listed as a shared project for 'Engineering'](img/000b14e609fee563642c55e238caca88.png)](img/other_group_sees_shared_project.png) + +请注意,您只能与以下项目共享一个项目: + +* 您具有明确定义的成员资格的组 +* 包含嵌套子组或项目的组,您对其具有明确定义的角色 + +管理员可以与系统中的任何组共享项目. + +## Maximum access level[](#maximum-access-level "Permalink") + +在上面的示例中,"工程"成员的最大"开发人员"访问级别意味着"工程"中具有较高访问级别的用户("维护者"或"所有者")将仅对" Acme 项目"具有"开发者"访问权限'. + +## Sharing public project with private group[](#sharing-public-project-with-private-group "Permalink") + +与私有组共享公共项目时,项目的所有者和维护者将在`members`页面上看到该组的名称. 所有者还可以在问题或合并请求中提及他们时,可以看到他们无权访问的私人群组的成员. + +## Share project with group lock[](#share-project-with-group-lock "Permalink") + +可以防止一个组中[的项目与另一个组共享一个项目](../members/share_project_with_groups.html) . 这样可以更严格地控​​制项目访问. + +了解更多有关[使用组锁共享的信息](../../group/index.html#share-with-group-lock) . \ No newline at end of file diff --git a/docs/171.md b/docs/171.md new file mode 100644 index 0000000000000000000000000000000000000000..5007724d99dac20bc2750279eb4190cba2628abd --- /dev/null +++ b/docs/171.md @@ -0,0 +1,133 @@ +# Snippets + +> 原文:[https://docs.gitlab.com/ee/user/snippets.html](https://docs.gitlab.com/ee/user/snippets.html) + +* [Personal snippets](#personal-snippets) +* [Project snippets](#project-snippets) +* [Create a snippet](#create-a-snippet) +* [Versioned Snippets](#versioned-snippets) + * [File names](#file-names) + * [Cloning snippets](#cloning-snippets) + * [Limitations](#limitations) +* [Discover snippets](#discover-snippets) +* [Snippet comments](#snippet-comments) +* [Downloading snippets](#downloading-snippets) +* [Embedded snippets](#embedded-snippets) + +# Snippets[](#snippets "Permalink") + +借助 GitLab 代码片段,您可以存储和与其他用户共享代码和文本. + +[![GitLab Snippet](img/677d8f883392679f3fba97024a259665.png)](img/gitlab_snippet_v13_0.png) + +可以使用[摘要 API](../api/snippets.html)来维护[摘要](../api/snippets.html) . + +片段类型有两种: + +* 个人摘要. +* 项目摘要. + +## Personal snippets[](#personal-snippets "Permalink") + +个人代码段与任何项目均无关,可以完全独立地创建. 可以设置 3 种可见性级别,公共,内部和私有. 有关更多信息,请参见[公共访问](../public_access/public_access.html) . + +## Project snippets[](#project-snippets "Permalink") + +项目摘要始终与特定项目相关. 有关更多信息,请参见[项目功能](project/index.html#project-features) . + +## Create a snippet[](#create-a-snippet "Permalink") + +要创建个人代码段,请点击加号图标( ),然后从下拉菜单中选择" **新建代码段** ": + +[![New personal snippet from non-project pages](img/169af1eb67d287048e2bd4de1d3a178a.png)](img/new_personal_snippet_v12_10.png) + +如果您在项目页面上,但要创建一个新的个人代码段,请点击加号图标( ),然后从下拉菜单的下部选择**新代码段** (在 GitLab.com 上为**GitLab** ;在自托管实例上为**您的**实例): + +[![New personal snippet from project pages](img/ee04e8247fff074d8b122d6b5ec848f4.png)](img/new_personal_snippet_from_project_v12_10.png) + +要创建项目摘要,请导航到您的项目页面,然后点击加号图标( ),然后从下拉菜单的上方选择**新建代码段** ( **此项目** ). + +[![New personal snippet from project pages](img/ea0e34b1e4e7a7a6379bc52995143bf9.png)](img/new_project_snippet_from_project_v12_10.png) + +从那里添加**Title** , **Description**和带有适当扩展名的**文件**名(例如`example.rb` , `index.html` ). + +**警告:**确保添加文件名以突出显示代码并避免此[粘贴错误](https://gitlab.com/gitlab-org/gitlab/-/issues/22870) . + +## Versioned Snippets[](#versioned-snippets "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/239) . + +从 13.0 开始,片段(个人片段和项目片段)默认都启用了版本控制. + +这意味着在创建代码段时,所有代码段都将获得自己的基础存储库,并使用`master`分支进行初始化. 每当保存对代码段的更改时,都会记录对 master 分支的新提交. 提交消息是自动生成的. 该代码段的存储库默认情况下只有一个分支(母版),不支持将其删除或创建其他分支. + +现有代码段将在 13.0 中自动迁移. 它们的当前内容将被保存为对代码段存储库的初始提交. + +### File names[](#file-names "Permalink") + +代码段支持基于为其提供的文件名和扩展名突出显示语法. 尽管可以在不指定文件名和扩展名的情况下提交代码段,但它需要一个有效的名称,以便可以将内容作为文件创建在代码段的存储库中. + +如果用户未将文件名和扩展名归于代码段,则 GitLab 会自动以`snippetfile<x>.txt`格式添加文件名,其中`<x>`代表添加到文件的数字,从 1 开始.添加了更多没有属性文件名的代码段. + +从早期版本的 GitLab 升级到 13.0 时,不支持文件名的现有代码片段将重命名为兼容格式. 例如,如果代码段的文件名是`http://a-weird-filename.me` ,它将被更改为`http-a-weird-filename-me` ,以包含在代码段的存储库中. 由于代码段是通过 ID 存储的,因此更改其文件名不会破坏该代码段的直接链接或嵌入式链接. + +### Cloning snippets[](#cloning-snippets "Permalink") + +可以使用 SSH 或 HTTPS 将片段克隆为常规的 Git 存储库. 单击摘要内容上方的" **复制"**按钮以复制您选择的 URL. + +[![Clone Snippet](img/ed5a96971ab453e6d33b3ad9079bd47c.png)](img/snippet_clone_button_v13_0.png) + +这使您可以获取代码段存储库的本地副本,并根据需要进行更改. 您可以提交这些更改并将其推送到远程 master 分支. + +### Limitations[](#limitations "Permalink") + +* 不支持二进制文件. +* 不支持创建或删除分支. 只有默认的*主人* . 使用分支. +* 代码段存储库中不支持 Git 标签. +* 片段的存储库仅限于一个文件. 尝试推送多个文件将导致错误. +* 修订在 GitLab UI 上对用户*尚不*可见,但计划在以后的迭代中添加. 有关更新,请参见[修订标签问题](https://gitlab.com/gitlab-org/gitlab/-/issues/39271) . +* 默认情况下, [摘要](../administration/snippets/index.html#snippets-content-size-limit)的[最大大小为](../administration/snippets/index.html#snippets-content-size-limit) 50 MB. + +## Discover snippets[](#discover-snippets "Permalink") + +在 GitLab 中发现片段的主要方法有两种. + +要浏览对您可见的所有代码片段,您可以通过顶部导航转到 GitLab 实例的代码片段仪表板. 对于 GitLab.com,您可以在[这里](https://gitlab.com/dashboard/snippets)找到它. 这会将您导航到一个概述,该概述显示您创建的摘要,并允许您浏览所有摘要. + +如果要发现属于特定项目的摘录,则可以通过项目页面上的左侧导航导航到摘录页面. 项目片段被启用,默认情况下可用,但他们可以通过导航到项目的**设置** ,扩大**知名度,项目功能,权限**和向下滚动到**片段**被禁用. 从那里,您可以切换以禁用它们,或从下拉菜单中选择其他可见性级别. + +## Snippet comments[](#snippet-comments "Permalink") + +在 GitLab 9.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/12910) . + +使用 GitLab 代码片段,您可以参与有关该代码段的对话,从而促进用户之间的协作. + +## Downloading snippets[](#downloading-snippets "Permalink") + +您可以下载代码段的原始内容. + +默认情况下,将下载带有 Linux 样式的行尾( `LF` )的代码段. 如果要保留原始的行尾,则需要添加参数`line_ending=raw` (例如, `https://gitlab.com/snippets/SNIPPET_ID/raw?line_ending=raw` : `line_ending=raw` ). 如果使用 GitLab Web 界面创建了代码段,则原始行结尾类似于 Windows( `CRLF` ). + +## Embedded snippets[](#embedded-snippets "Permalink") + +在 GitLab 10.8 中引入. + +公开片段不仅可以共享,还可以嵌入任何网站中. 这样,您可以在多个地方重用 GitLab 代码段,并且对源代码的任何更改都会自动反映在嵌入式代码段中. + +To embed a snippet, first make sure that: + +* 该项目是公开的(如果是项目摘要) +* 摘要是公开的 +* 在" **项目">"设置">"权限"中** ,将片段权限设置为" **具有访问**权限的**所有人"** + +满足以上条件后,"嵌入"部分将出现在您的代码片段中,您只需单击"复制"按钮即可. 这将复制一个单行脚本,您可以将其添加到任何网站或博客文章中. + +示例代码如下所示: + +``` +<script src="https://gitlab.com/namespace/project/snippets/SNIPPET_ID.js"></script> +``` + +嵌入式代码段的外观如下: + +嵌入的代码片段带有一个标题,该标题显示文件名(如果已定义),代码片段大小,到 GitLab 的链接以及实际的代码片段内容. 标头中的操作使用户可以查看原始格式的代码段并下载. \ No newline at end of file diff --git a/docs/172.md b/docs/172.md new file mode 100644 index 0000000000000000000000000000000000000000..d32e3f0480fe33df72cf499b06630c224def1656 --- /dev/null +++ b/docs/172.md @@ -0,0 +1,83 @@ +# Static Site Editor + +> 原文:[https://docs.gitlab.com/ee/user/project/static_site_editor/](https://docs.gitlab.com/ee/user/project/static_site_editor/) + +* [Use cases](#use-cases) +* [Requirements](#requirements) +* [How it works](#how-it-works) +* [Getting started](#getting-started) + * [Set up your project](#set-up-your-project) + * [Use the Static Site Editor to edit your content](#use-the-static-site-editor-to-edit-your-content) +* [Limitations](#limitations) + +# Static Site Editor[](#static-site-editor "Permalink") + +版本历史 + +* 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28758) . +* 在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214559)了所见即所得的编辑器. +* 支持通过 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/216640)的 WYSIWYG 编辑器添加图像. +* Markdown 前端问题隐藏在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/216834)的 WYSIWYG 编辑器中. +* 支持 GitLab 13.2 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/223171) `*.md.erb`文件. + +**危险:**在 GitLab 13.0 中,我们对静态站点编辑器的 URL 结构进行了[重大更改](https://gitlab.com/gitlab-org/gitlab/-/issues/213282) . 请按照此[代码段中](https://gitlab.com/gitlab-org/project-templates/static-site-editor-middleman/snippets/1976539)的说明使用最新更改来更新您的项目. + +静态站点编辑器使用户可以在静态网站上编辑内容,而无需事先了解基础模板语言,站点体系结构或 Git 命令. 您的项目的贡献者可以快速编辑 Markdown 页面,并将更改提交审核. + +## Use cases[](#use-cases "Permalink") + +静态站点编辑器允许协作者无缝地将更改提交到静态站点文件. 例如: + +* 非技术合作者可以直接从浏览器中轻松编辑页面; 他们不需要知道 Git 和您的项目的详细信息就能做出贡献. +* 最近雇用的团队成员可以快速编辑内容. +* 临时协作者可以从一个项目跳到另一个项目并快速编辑页面,而不必克隆或派生需要提交更改的每个项目. + +## Requirements[](#requirements "Permalink") + +* 为了使用静态站点编辑器功能,您的项目需要使用[静态站点编辑器 Middleman 模板](https://gitlab.com/gitlab-org/project-templates/static-site-editor-middleman)进行预配置. +* 该编辑器需要登录到 GitLab,并且必须是该项目的成员(具有 Developer 或更高权限级别). + +## How it works[](#how-it-works "Permalink") + +静态网站编辑器尚处于开发的早期阶段,目前仅适用于 Middleman 网站. 您必须使用特定的站点模板才能开始使用它. 项目模板配置为使用[GitLab Pages](../pages/index.html)部署[Middleman](https://middlemanapp.com/)静态网站. + +网站启动并运行后,您将在其页面的左下角看到一个" **编辑此页面"**按钮: + +[![Edit this page button](img/865915f0e39a0035ffc91de736f5a047.png)](img/edit_this_page_button_v12_10.png) + +单击它后,GitLab 将打开一个编辑器窗口,从中可以直接编辑内容. 准备就绪后,只需单击一下按钮即可提交更改: + +[![Static Site Editor](img/a7a0c433c6f01281a584ba08db57d159.png)](img/wysiwyg_editor_v13_0.png) + +当编辑者在后台提交更改时,GitLab 会自动创建一个新分支,提交更改并打开合并请求. 编辑者将直接进入合并请求,然后可以将其分配给同事进行审查. + +## Getting started[](#getting-started "Permalink") + +首先,设置项目. 完成后,您可以使用静态站点编辑器轻松地编辑您的内容. + +### Set up your project[](#set-up-your-project "Permalink") + +1. 首先,从" [静态站点编辑器-中间人"](https://gitlab.com/gitlab-org/project-templates/static-site-editor-middleman)模板创建一个新项目. 您可以将其[派生](../repository/forking_workflow.html#creating-a-fork)或[从模板创建一个新项目](../../../gitlab-basics/create-project.html#built-in-templates) . +2. 编辑`data/config.yml`文件,添加项目的路径. +3. 编辑文件将触发 CI / CD 管道,以使用 GitLab Pages 部署项目. +4. 管道完成后,从项目的左侧菜单转到**"设置">"页面"**以找到新网站的 URL. +5. 访问您的网站并查看屏幕的左下角,以查看新的" **编辑此页面"**按钮. + +满足[要求的](#requirements)任何人都可以编辑页面内容,而无需事先了解 Git 或您网站的代码库. + +**注意:**从 GitLab 13.1 开始,Markdown 文件的 YAML 前端问题被隐藏在 WYSIWYG 编辑器中,以避免意外更改. 要对其进行编辑,请使用 Markdown 编辑模式,常规的 GitLab 文件编辑器或 Web IDE. + +### Use the Static Site Editor to edit your content[](#use-the-static-site-editor-to-edit-your-content "Permalink") + +例如,假设您是一家大型公司的新近聘用的技术作家,并且该公司的产品已添加了新功能. + +1. 您被分配了更新文档的任务. +2. 您访问页面并看到需要编辑的内容. +3. 单击生产站点上的" **编辑此页面"**按钮. +4. 该文件在"静态站点编辑器"中以" **所见即所得"**模式打开. 如果您想编辑原始 Markdown,则可以在右下角切换**Markdown**模式. +5. 您在此处编辑文件,然后单击" **提交更改"** . +6. 将自动创建一个新的合并请求,然后将其分配给您的同事进行审核. + +## Limitations[](#limitations "Permalink") + +* 静态站点编辑器仍然不能快速添加到现有的 Middleman 站点. 跟随此[史诗](https://gitlab.com/groups/gitlab-org/-/epics/2784)进行更新. \ No newline at end of file diff --git a/docs/173.md b/docs/173.md new file mode 100644 index 0000000000000000000000000000000000000000..fce31d527ba632fee3263058a5e2c57f0fe9c5e0 --- /dev/null +++ b/docs/173.md @@ -0,0 +1,202 @@ +# Wiki + +> 原文:[https://docs.gitlab.com/ee/user/project/wiki/](https://docs.gitlab.com/ee/user/project/wiki/) + +* [First time creating the Home page](#first-time-creating-the-home-page) +* [Creating a new wiki page](#creating-a-new-wiki-page) + * [Attachment storage](#attachment-storage) + * [Special characters in page titles](#special-characters-in-page-titles) + * [Length restrictions for file and directory names](#length-restrictions-for-file-and-directory-names) +* [Editing a wiki page](#editing-a-wiki-page) + * [Adding a table of contents](#adding-a-table-of-contents) +* [Deleting a wiki page](#deleting-a-wiki-page) +* [Moving a wiki page](#moving-a-wiki-page) +* [Viewing a list of all created wiki pages](#viewing-a-list-of-all-created-wiki-pages) +* [Viewing the history of a wiki page](#viewing-the-history-of-a-wiki-page) + * [Viewing the changes between page versions](#viewing-the-changes-between-page-versions) +* [Wiki activity records](#wiki-activity-records) + * [Limitations](#limitations) + * [Enable or disable Wiki Events](#enable-or-disable-wiki-events-core-only) +* [Adding and editing wiki pages locally](#adding-and-editing-wiki-pages-locally) +* [Customizing sidebar](#customizing-sidebar) + +# Wiki[](#wiki "Permalink") + +每个 GitLab 项目都内置了一个称为 Wiki 的独立文档系统. 默认情况下,所有新项目都启用此功能,您可以在项目的**Wiki**下找到它. + +如果您不想将文档保留在存储库中,但确实希望将其保留在代码所在的项目中,则 Wiki 非常方便. + +您可以在 Web 界面中或[使用 Git 在本地](#adding-and-editing-wiki-pages-locally)创建 Wiki 页面,因为每个 Wiki 都是单独的 Git 存储库. + +## First time creating the Home page[](#first-time-creating-the-home-page "Permalink") + +首次访问 Wiki 时,系统将指示您创建主页. 必须创建主页,因为它是查看 Wiki 时的登录页面. 您只需要填写**内容**部分,然后单击**创建页面** . 您以后可以随时对其进行编辑,因此继续写欢迎信息. + +[![New home page](img/909d20c0dd57155c8ac404a81c2a30cb.png)](img/wiki_create_home_page.png) + +## Creating a new wiki page[](#creating-a-new-wiki-page "Permalink") + +**注意:**需要开发者[权限](../../permissions.html) . + +通过单击可在所有 Wiki 页面中找到的" **新页面"**按钮来创建新页面. + +系统将要求您为新的 Wiki 页面填写标题. + +您可以通过在标题中使用" /"指示子目录来为 Wiki 页面指定完整路径. 任何丢失的目录将自动创建. 例如, `docs/my-page`的标题将创建一个 Wiki 页面,其路径为`/wikis/docs/my-page` . + +输入页面名称后,就该填写其内容了. GitLab Wiki 支持 Markdown,RDoc,AsciiDoc 和 Org. 对于基于 Markdown 的页面,所有[Markdown 功能](../../markdown.html)均受支持,对于链接,则存在一些[特定](../../markdown.html#wiki-specific-markdown)于[Wiki 的](../../markdown.html#wiki-specific-markdown)行为. + +在 Web 界面中,提交消息是可选的,但是 GitLab Wiki 是基于 Git 的,并且需要提交消息,因此如果您不输入消息,则会为您创建一条. + +When you’re ready, click the **建立页面** and the new page will be created. + +[![New page](img/0a61445809db70ca6bf85d986bf52223.png)](img/wiki_create_new_page.png) + +### Attachment storage[](#attachment-storage "Permalink") + +在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33475) . + +从 GitLab 11.3 开始,通过 GitLab 界面上载到 Wiki 的任何文件都将存储在 Wiki Git 存储库中,如果您在本地克隆 Wiki 存储库,该文件将可用. GitLab 11.3 之前的所有上传文件都存储在 GitLab 本身中. 如果希望它们成为 Wiki 的 Git 存储库的一部分,则必须再次上传它们. + +### Special characters in page titles[](#special-characters-in-page-titles "Permalink") + +Wiki 页面作为文件存储在 Git 存储库中,因此某些字符具有特殊含义: + +* 存储页面时,空格会转换为连字符. +* 显示页面时,连字符( `-` )转换回空格. +* 不能使用斜杠( `/` ),因为它们用作路径分隔符. + +### Length restrictions for file and directory names[](#length-restrictions-for-file-and-directory-names "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24364) . + +许多常见的文件系统[的文件名和目录名限制为 255 个字节](https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits) ,尽管 Git 和 GitLab 都支持超出这些限制的路径,但是它们的存在使这些文件系统上的用户无法在本地检出 Wiki 存储库. + +为了避免这种情况,通过 GitLab Web 界面和 API 编辑页面时会强制执行以下限制: + +* 页面标题为 245 个字节(文件扩展名保留 10 个字节). +* 255 个字节的目录名称. + +请注意: + +* 非 ASCII 字符占用多个字节. +* 仍然可以通过 Git 在本地创建超出限制的文件和目录,但这可能会在其他人的计算机上中断. + +## Editing a wiki page[](#editing-a-wiki-page "Permalink") + +**注意:**需要开发者[权限](../../permissions.html) . + +要编辑页面,只需单击" **编辑"**按钮. 从那里开始,您可以更改其内容. 完成后,单击" **保存更改"**以使更改生效. + +### Adding a table of contents[](#adding-a-table-of-contents "Permalink") + +要从 Wiki 页面中的标题生成目录,请使用`[[_TOC_]]`标签. 有关示例,请参阅[目录](../../markdown.html#table-of-contents) . + +## Deleting a wiki page[](#deleting-a-wiki-page "Permalink") + +**注意:**需要维护者[权限](../../permissions.html) . + +仅在编辑页面时才能找到" **删除"**按钮. 单击它并确认您要删除页面. + +## Moving a wiki page[](#moving-a-wiki-page "Permalink") + +通过在[编辑](#editing-a-wiki-page)表单的 Wiki 页面标题中指定完整路径,可以将 Wiki 页面从一个目录移动到另一个目录. + +[![Moving a page](img/7a0180479e056fe1c4aa11c3e8684906.png)](img/wiki_move_page_1.png) + +[![After moving a page](img/70117ebf119dd375e0def463921cc363.png)](img/wiki_move_page_2.png) + +为了将 Wiki 页面移动到根目录,必须在 Wiki 页面标题前加上斜杠( `/` )字符. + +## Viewing a list of all created wiki pages[](#viewing-a-list-of-all-created-wiki-pages "Permalink") + +每个 Wiki 都有一个侧边栏,从中可以找到所创建页面的简短列表. 该列表按字母顺序排列. + +[![Wiki sidebar](img/03d3f984ea7608322b1fd6a7feba47c0.png)](img/wiki_sidebar.png) + +如果页面很多,则不会在侧边栏中列出所有页面. 单击**查看所有页面**以**查看所有页面** . + +## Viewing the history of a wiki page[](#viewing-the-history-of-a-wiki-page "Permalink") + +Wiki 页面随时间的变化记录在 Wiki 的 Git 存储库中,您可以通过单击**Page history**按钮来查看它们. + +从历史记录页面中,您可以看到页面的修订版(Git commit SHA),其作者,提交消息以及上次更新时间. 要查看页面的先前版本的外观,请在" **页面版本"**列中单击修订号. + +[![Wiki page history](img/2fdc2024eee83764328fb015ffd4e392.png)](img/wiki_page_history.png) + +### Viewing the changes between page versions[](#viewing-the-changes-between-page-versions "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/15242) . + +类似于版本化的差异文件视图,您可以看到在给定的 Wiki 页面版本中所做的更改: + +1. 导航到您感兴趣的 Wiki 页面. +2. 单击**页面历史记录**以查看所有页面版本. +3. 单击" **更改"**列中的提交消息以获取您感兴趣的版本: + + [![Wiki page changes](img/9cc2ca9eb5afc113cacfbc529374fe3b.png)](img/wiki_page_diffs_v13_2.png) + +## Wiki activity records[](#wiki-activity-records "Permalink") + +版本历史 + +* 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/14902) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上启用了它. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-wiki-events-core-only) . + +Wiki 事件(创建,删除和更新)由 GitLab 跟踪,并显示在[用户个人资料](../../profile/index.html#user-profile) , [组](../../group/index.html#view-group-activity)和[项目](../index.html#project-activity)活动页面上. + +### Limitations[](#limitations "Permalink") + +只有在浏览器中或通过 API 进行的编辑才会记录其活动. 当前在活动列表中未列出通过 Git 进行和推送的编辑. + +### Enable or disable Wiki Events[](#enable-or-disable-wiki-events-core-only "Permalink") + +Wiki 事件活动正在开发中,尚未准备好用于生产. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/troubleshooting/navigating_gitlab_via_rails_console.html#starting-a-rails-console-session)可以为您的实例启用它. 欢迎您对其进行测试,但使用风险自负. + +要启用它: + +``` +Feature.enable(:wiki_events) +``` + +禁用它: + +``` +Feature.disable(:wiki_events) +``` + +## Adding and editing wiki pages locally[](#adding-and-editing-wiki-pages-locally "Permalink") + +由于 Wiki 基于 Git 存储库,因此您可以像在其他所有 Git 存储库中一样在本地克隆它们并进行编辑. + +在右侧栏上,单击" **克隆存储库",**然后按照屏幕上的说明进行操作. + +根据您要使用的标记语言,您在本地添加到 Wiki 的文件必须具有以下受支持的扩展名之一,否则当推送到 GitLab 时将不会显示这些文件: + +* Markdown 扩展名: `.mdown` , `.mkd` , `.mkdn` , `.md` , `.markdown` . +* AsciiDoc 扩展名: `.adoc` , `.ad` , `.asciidoc` . +* 其他标记扩展名: `.textile` , `.rdoc` , `.org` , `.creole` , `.wiki` , `.mediawiki` , `.rst` . + +## Customizing sidebar[](#customizing-sidebar "Permalink") + +在项目的 Wiki 页面上,有一个右侧导航,默认情况下呈现带有层次结构的完整 Wiki 页面列表. + +要自定义边栏,您可以创建一个名为`_sidebar`的文件以完全替换默认导航. + +**警告:**除非您从自定义导航链接`_sidebar`文件,否则要进行编辑,必须输入以下内容直接从浏览器的地址栏中访问: `https://gitlab.com/<namespace>/<project_name>/-/wikis/_sidebar` : `_sidebar` /- `https://gitlab.com/<namespace>/<project_name>/-/wikis/_sidebar` (对于自我管理的 GitLab 实例,将`gitlab.com`替换为实例的 URL). + +`_sidebar`示例(使用 Markdown 格式): + +``` +### [Home](home) + - [Hello World](hello) +- [Foo](foo) +- [Bar](bar) + --- + +- [Sidebar](_sidebar) +``` + +计划支持使用自定义侧面导航显示生成的目录. \ No newline at end of file diff --git a/docs/174.md b/docs/174.md new file mode 100644 index 0000000000000000000000000000000000000000..f1cc06713fde6a2feee1b61a35e0af4e514e00ba --- /dev/null +++ b/docs/174.md @@ -0,0 +1,17 @@ +# Project operations + +> 原文:[https://docs.gitlab.com/ee/operations/](https://docs.gitlab.com/ee/operations/) + +# Project operations[](#project-operations "Permalink") + +manbetx 客户端打不开提供各种工具来帮助操作和维护您的应用程序: + +* Collect [Prometheus metrics](../user/project/integrations/prometheus_library/index.html). +* 部署到不同的[环境](../ci/environments/index.html) . +* 管理您的[警报](../user/project/operations/alert_management.html)和[事件](../user/incident_management/index.html) . +* 将您的项目连接到[Kubernetes 集群](../user/project/clusters/index.html) . +* 通过" [按代码实施](../user/infrastructure/index.html)基础[结构"](../user/infrastructure/index.html)管理基础[结构](../user/infrastructure/index.html) . +* 通过[错误跟踪](../user/project/operations/error_tracking.html)发现并查看由应用程序生成的[错误](../user/project/operations/error_tracking.html) . +* 创建,切换和删除[功能标记](feature_flags.html) . +* [跟踪](tracing.html)已部署应用程序的性能和运行状况. +* 更改" [监视仪表板](../user/project/operations/dashboard_settings.html) "的[设置](../user/project/operations/dashboard_settings.html) . \ No newline at end of file diff --git a/docs/175.md b/docs/175.md new file mode 100644 index 0000000000000000000000000000000000000000..c4fc4164df80bcf32aa16baf46b373545abad055 --- /dev/null +++ b/docs/175.md @@ -0,0 +1,108 @@ +# Monitor metrics for your CI/CD environment + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/](https://docs.gitlab.com/ee/operations/metrics/) + +* [Populate your metrics dashboard](#populate-your-metrics-dashboard) +* [Customize your metrics dashboard](#customize-your-metrics-dashboard) +* [Metrics dashboard visibility](#metrics-dashboard-visibility) +* [Adding custom metrics](#adding-custom-metrics) +* [Editing additional metrics from the dashboard](#editing-additional-metrics-from-the-dashboard) +* [Keyboard shortcuts for charts](#keyboard-shortcuts-for-charts) + +# Monitor metrics for your CI/CD environment[](#monitor-metrics-for-your-cicd-environment "Permalink") + +在[为群集配置 Prometheus](../../user/project/integrations/prometheus.html)之后,GitLab 会尝试在成功部署的任何[环境中](../../ci/environments/index.html)检索性能指标. + +GitLab 在 Prometheus 服务器上扫描来自 Kubernetes 和 NGINX 等已知服务器的指标,并尝试识别各个环境. 要了解有关支持的指标和扫描过程的更多信息,请参阅[Prometheus Metrics Library 文档](../../user/project/integrations/prometheus_library/index.html) . + +要查看已[完成至少一个部署](#populate-your-metrics-dashboard)的环境的指标仪表板,请执行[以下操作](#populate-your-metrics-dashboard) : + +1. *如果指标仪表盘仅对项目成员可见,请以项目成员*身份登录到 GitLab. 了解有关[指标仪表板可见性的](#metrics-dashboard-visibility)更多[信息](#metrics-dashboard-visibility) . +2. 在您的项目中,导航到 **操作>指标** . + +GitLab 显示环境的默认指标仪表板,如以下示例所示: + +[![Example of metrics dashboard](img/b12f4326b7cccf6e82c375163842f58e.png)](img/example-dashboard_v13_1.png) + +仪表板的顶部包含一个导航栏. 从左到右,导航栏包含: + +* **仪表板** -项目可用的所有仪表板的下拉列表,其中加星标的仪表板排在最前面. +* **环境** -所有[环境的](../index.html)下拉列表,可在您键入时搜索所有环境. +* **范围** -要显示的数据的时间段. +* **刷新仪表板** -用当前数据重新加载仪表板. +* **设置刷新率** - Set a time frame for refreshing the data displayed. +* **明星仪表板** -单击以将仪表板标记为收藏夹. 已加星标的信息中心显示实心星 按钮,然后在" **仪表板"**下拉列表中首先显示. (在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214582) .) +* **创建仪表板** - [为您的项目](dashboards/index.html#adding-a-new-dashboard-to-your-project)创建一个[新的自定义仪表板](dashboards/index.html#adding-a-new-dashboard-to-your-project) . +* **指标设置** -配置[此仪表板](dashboards/index.html#manage-the-metrics-dashboard-settings)的[设置](dashboards/index.html#manage-the-metrics-dashboard-settings) . + +## Populate your metrics dashboard[](#populate-your-metrics-dashboard "Permalink") + +在[为群集配置 Prometheus](../../user/project/integrations/prometheus.html)之后,您还必须为 **操作>指标**页面以包含数据. 设置[Auto DevOps](../../topics/autodevops/index.html)有助于快速创建部署: + +1. 导航到您项目的 **操作> Kubernetes**页面. +2. 确保除了 Prometheus 外,还安装了 Runner 和 Ingress. +3. 安装 Ingress 后,复制其端点. +4. Navigate to your project’s **设置> CI / CD** page. In the **自动 DevOps** section, select a deployment strategy and save your changes. +5. 在同一页上的" **变量"**部分中,添加一个名为`KUBE_INGRESS_BASE_DOMAIN`的变量, `KUBE_INGRESS_BASE_DOMAIN`包含您先前复制的 Ingress 端点的值. 将类型保留为**Variable** . +6. 导航到您项目的 **CI / CD>管道**页面,然后在任何分支上运行管道. +7. 管道成功运行后,图表将在 **操作>指标**页面. + +[![Monitoring Dashboard](img/1bce7244cd585ee6d059a7aa1903f194.png)](../../user/project/integrations/img/prometheus_monitoring_dashboard_v13_1.png) + +## Customize your metrics dashboard[](#customize-your-metrics-dashboard "Permalink") + +创建仪表板后,您可以对其进行自定义以满足您的需求: + +* **添加自定义指标** :除了 GitLab 默认指标之外,您还可以[创建自定义指标](#adding-custom-metrics)并将其显示在指标仪表板上. +* **配置指标警报** :当环境性能超出您设置的范围时,为团队[配置自定义警报](alerts.html) . +* **通过警报触发操作** : [为您的团队打开新问题](alerts.html#trigger-actions-from-alerts-ultimate) 当环境性能超出您设置的范围时. + +## Metrics dashboard visibility[](#metrics-dashboard-visibility "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/201924) . + +您可以将指标仪表板的可见性设置为" **仅项目成员"**或" **具有访问权限的所有人"** . 当设置为" **具有访问权的所有人"时** ,指标仪表板对于已认证和未认证的用户都是可见的. + +## Adding custom metrics[](#adding-custom-metrics "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3799) . +* [移至](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28527) [GitLab Core](https://about.gitlab.com/pricing/) 12.10\. + +可以通过在监控仪表板页面上添加自定义指标来对其进行监控. 保存它们后,它们将显示在环境指标仪表板上,前提是: + +* 使用具有匹配[环境范围的](../../ci/environments/index.html#scoping-environments-with-specs) [连接的 Kubernetes 群集](../../user/project/clusters/add_remove_clusters.html) ,并将[Prometheus 安装在群集上](../../user/project/integrations/prometheus.html#enabling-prometheus-integration) . +* Prometheus 是[手动配置的](../../user/project/integrations/prometheus.html#manual-configuration-of-prometheus) . + +[![Add New Metric](img/ecb68ae545435c5eb9229937635a5aee.png)](../../user/project/integrations/img/prometheus_add_metric.png) + +必须填写几个字段: + +* **名称** :图表标题 +* **类型** :指标的类型. 相同类型的指标将一起显示. +* **查询** :有效的[PromQL 查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/basics/) . +* **Y 轴标签** :Y 轴标题显示在仪表板上. +* **单位标签** :查询单位,例如`req / sec` . 值旁边显示. + +如果指标之间的**名称** , **类型**和**Y 轴标签**字段匹配,则可以在同一图表上显示多个指标. 例如,具有" **名称** `Requests Rate` ," `Business` **类型"**和**Y 轴标签** `rec / sec`度量标准将与另一个具有相同值的度量标准显示在同一图表上. 如果使用此功能,则建议使用**图例标签** . + +## Editing additional metrics from the dashboard[](#editing-additional-metrics-from-the-dashboard "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/208976) . + +您可以通过以下方式为信息中心编辑现有的其他自定义指标: **更多操作**下拉菜单,然后选择**编辑指标** . + +[![Edit metric](img/f0d4bcbd75dfae1dbbc867343090a4ca.png)](../../user/project/integrations/img/prometheus_dashboard_edit_metric_link_v_12_9.png) + +## Keyboard shortcuts for charts[](#keyboard-shortcuts-for-charts "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/202146) . + +您可以使用键盘快捷键与当前关注的图表面板更快地进行交互. 要激活键盘快捷键,请使用键盘标签突出显示 **"更多操作"**下拉菜单,或用鼠标悬停在下拉菜单上,然后按与所需操作对应的键: + +* **展开面板** - `e` +* **查看日志** `-l` (小写" L") +* **下载 CSV** - `d` +* **复制链接到图表** - `c` +* **Alerts** - `a` \ No newline at end of file diff --git a/docs/176.md b/docs/176.md new file mode 100644 index 0000000000000000000000000000000000000000..a8d188de1a4f13421582bafc95d5f36f12b4c2ad --- /dev/null +++ b/docs/176.md @@ -0,0 +1,88 @@ +# Set up alerts for Prometheus metrics + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/alerts.html](https://docs.gitlab.com/ee/operations/metrics/alerts.html) + +* [Managed Prometheus instances](#managed-prometheus-instances) +* [External Prometheus instances](#external-prometheus-instances) +* [Trigger actions from alerts](#trigger-actions-from-alerts-ultimate) + +# Set up alerts for Prometheus metrics[](#set-up-alerts-for-prometheus-metrics "Permalink") + +在[为 CI / CD 环境配置指标](index.html)后,您可以根据实例的位置为 Prometheus 指标设置警报,并在环境性能超出您设置的范围时[触发警报操作](#trigger-actions-from-alerts-ultimate)以通知您的团队. + +## Managed Prometheus instances[](#managed-prometheus-instances "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6590)了[自定义指标](index.html#adding-custom-metrics) ,在 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6590)了[图书馆指标](../../user/project/integrations/prometheus_library/metrics.html) . + +对于使用自动配置的托管 Prometheus 实例,您可以直接在[指标仪表板中](index.html) [配置指标警报](index.html#adding-custom-metrics) . 设置警报: + +1. 在您的项目中,导航到 **操作>指标** , +2. 确定要为其创建警报的指标,然后单击**省略号** 指标右上角的图标. +3. Choose **Alerts**. +4. 设置阈值和运算符. +5. 单击**添加**以保存并激活警报. + +[![Adding an alert](img/659964d0e0d080d80881d6eb74aaaf7e.png)](../../user/project/integrations/img/prometheus_alert.png) + +要删除警报,请在警报图标上返回所需的指标,然后单击" **删除"** . + +## External Prometheus instances[](#external-prometheus-instances "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9258) . +* 在 12.10 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) [GitLab Core](https://about.gitlab.com/pricing/) . + +对于手动配置的 Prometheus 服务器,GitLab 提供了一个通知端点,用于 Prometheus Webhooks. 如果启用了手动配置,则会将" **警报"**部分添加到 **设置>集成> Prometheus** . 本部分包含您需要的**URL**和**授权密钥** . **重置密钥**按钮将使密钥无效并生成一个新密钥. + +[![Prometheus service configuration of Alerts](img/510cd4b11aa5f23be76d594a9ad782d6.png)](../../user/project/integrations/img/prometheus_service_alerts.png) + +要发送 GitLab 警报通知,请将**URL**和**授权密钥**复制到 Prometheus Alertmanager 配置的[`webhook_configs`](https://s0prometheus0io.icopy.site/docs/alerting/latest/configuration/)部分: + +``` +receivers: + name: gitlab + webhook_configs: + - http_config: + bearer_token: 9e1cbfcd546896a9ea8be557caf13a76 + send_resolved: true + url: http://192.168.178.31:3001/root/manual_prometheus/prometheus/alerts/notify.json + ... +``` + +为了使 GitLab 将警报与[环境](../../ci/environments/index.html)相关联,您必须在 Prometheus 中设置的警报上配置`gitlab_environment_name`标签. 此值应与您在 GitLab 中的环境名称匹配. + +**Note:** In GitLab versions 13.1 and greater, you can configure your manually configured Prometheus server to use the [Generic alerts integration](../../user/project/integrations/generic_alerts.html). + +## Trigger actions from alerts[](#trigger-actions-from-alerts-ultimate "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4925) . +* [从 GitLab Ultimate 12.5 起](https://gitlab.com/gitlab-org/gitlab/-/issues/13401) ,当 GitLab 收到恢复警报时,它将自动关闭相关问题. + +警报可用于触发操作,例如自动打开问题(自`13.1`默认禁用). 要配置操作: + +1. 导航到您项目的 **设置>操作>事件** . +2. 启用该选项以创建问题. +3. 选择要从中创建问题的[问题模板](../../user/project/description_templates.html) . +4. (可选)选择是否将电子邮件通知发送给项目的开发人员. +5. Click **保存更改**. + +启用后,当触发包含包含从[警报有效负载中](https://s0prometheus0io.icopy.site/docs/alerting/latest/configuration/)提取的值的警报时,GitLab 会自动打开一个问题: + +* 问题作者: `GitLab Alert Bot` +* 问题标题:从`annotations/title` , `annotations/summary`或`labels/alertname` +* 警报`Summary` :属性列表 + * `starts_at` :通过`startsAt`警报的开始时间 + * `full_query` :从`generatorURL`提取的警报查询 + * 从`annotations/*`提取的附加注释的可选列表 +* Alert [GFM](../../user/markdown.html) :来自`annotations/gitlab_incident_markdown` GitLab 风味`annotations/gitlab_incident_markdown` + +当 GitLab 收到**Recovery Alert 时** ,它将关闭相关问题. 该操作记录为关于该问题的系统消息,表明该操作已由 GitLab Alert 机器人自动关闭. + +要进一步自定义问题,您可以在所选问题模板中添加标签,提及或任何其他受支持的[快速操作](../../user/project/quick_actions.html) ,该操作适用于所有事件. 要将快速操作或其他信息限制为仅特定类型的警报,请使用`annotations/gitlab_incident_markdown`字段. + +从[版本 12.2 开始](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/63373) ,GitLab 会使用`incident`标签自动标记每个事件问题. 如果标签尚不存在,则会自动创建. + +如果度量标准超过警报阈值超过 5 分钟,则 GitLab 会向该项目的所有[维护者和所有者](../../user/permissions.html#project-members-permissions)发送电子邮件. \ No newline at end of file diff --git a/docs/177.md b/docs/177.md new file mode 100644 index 0000000000000000000000000000000000000000..203fcaa1471602189f160c27a142c8b831f96862 --- /dev/null +++ b/docs/177.md @@ -0,0 +1,92 @@ +# Embedding metric charts within GitLab-flavored Markdown + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/embed.html](https://docs.gitlab.com/ee/operations/metrics/embed.html) + +* [Embedding GitLab-managed Kubernetes metrics](#embedding-gitlab-managed-kubernetes-metrics) +* [Embedding metrics in issue templates](#embedding-metrics-in-issue-templates) +* [Embedding metrics based on alerts in incident issues](#embedding-metrics-based-on-alerts-in-incident-issues) +* [Embedding cluster health charts](#embedding-cluster-health-charts) + +# Embedding metric charts within GitLab-flavored Markdown[](#embedding-metric-charts-within-gitlab-flavored-markdown "Permalink") + +您可以在[GitLab 风味降价](../../user/markdown.html#gitlab-flavored-markdown-gfm)字段中显示指标图表,例如发布或合并请求说明. GitLab 风味的 Markdown 字段中允许的最大嵌入图表数为 100.当与其他人共享应用程序事件或性能指标并且您想直接获得相关信息时,嵌入图表很有用. + +## Embedding GitLab-managed Kubernetes metrics[](#embedding-gitlab-managed-kubernetes-metrics "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29691) . + +**Note:** Requires [Kubernetes](../../user/project/integrations/prometheus_library/kubernetes.html) metrics. + +要显示度量图表,请在支持 GitLab 风格的 Markdown 的字段中包含`https://<root_url>/<project>/-/environments/<environment_id>/metrics`形式的链接: + +[![Embedded Metrics Markdown](img/8f07bae8fce74cd6b8276b7dd9e59c2e.png)](../../user/project/integrations/img/embedded_metrics_markdown_v12_8.png) + +GitLab 将链接展开为嵌入式指标面板: + +[![Embedded Metrics Rendered](img/276614fbc4ef7b7b9f7a445dffbc5691.png)](../../user/project/integrations/img/embedded_metrics_rendered_v12_8.png) + +您还可以嵌入一个图表. 要获取图表链接,请点击 图表右上角的" **更多操作"**菜单,然后选择" **将链接复制到图表"** ,如本示例所示: + +[![Copy Link To Chart](img/6f52527c138db466f7fba27994ad67f8.png)](../../user/project/integrations/img/copy_link_to_chart_v12_10.png) + +指标必须满足以下要求: + +* `<environment_id>`必须与真实环境相对应. +* 普罗米修斯必须在监视环境. +* 必须将 GitLab 实例配置为从环境接收数据. +* 必须允许用户访问环境( [Reporter 或更高版本](../../user/permissions.html) )的监视仪表板. +* 仪表板必须在最近 8 小时内具有数据. + +如果以上所有条件均成立,则该指标将展开,如下所示: + +[![Embedded Metrics](img/0ff1ac0799b3b8867f4ebefa4e22d786.png)](../../user/project/integrations/img/view_embedded_metrics_v12_10.png) + +公制图表也可能被隐藏: + +[![Show Hide](img/cb4ff59b46134d4c61caedcf5a66a74f.png)](../../user/project/integrations/img/hide_embedded_metrics_v12_10.png) + +您可以直接在浏览器中打开链接[以获取数据](dashboards/index.html#expand-panel)的[详细视图](dashboards/index.html#expand-panel) . + +## Embedding metrics in issue templates[](#embedding-metrics-in-issue-templates "Permalink") + +您也可以在问题模板中嵌入默认仪表板指标或单个指标. 要使图表并排显示,请使用逗号或空格将指向整个指标仪表板或单个指标的单独链接分开. + +[![Embedded Metrics in issue templates](img/b51efc1bf28d2363ac0b4e95c4318fbe.png)](../../user/project/integrations/img/embed_metrics_issue_template.png) + +## Embedding metrics based on alerts in incident issues[](#embedding-metrics-based-on-alerts-in-incident-issues "Permalink") + +对于由[GitLab 管理的警报规则](alerts.html) ,问题包括与警报相对应的查询的嵌入式图表. 该图表显示了事件开始点前后一个小时(前后 30 分钟)的一小时数据. + +对于[手动配置的 Prometheus 实例](../../user/project/integrations/prometheus.html#manual-configuration-of-prometheus) ,如果满足以下要求,则可以包括与查询相对应的图表: + +* 该警报对应于通过 GitLab 管理的环境. +* 警报对应于[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) . +* 警报包含下表中列出的必需属性. + +| Attributes | Required | Description | +| --- | --- | --- | +| `annotations/gitlab_environment_name` | Yes | 与警报对应的由 GitLab 管理的环境的名称 | +| `annotations/title` , `annotations/summary` , `labels/alertname` | Yes | 用作图表标题 | +| `annotations/gitlab_y_label` | No | 用作图表的 y 轴标签 | + +## Embedding cluster health charts[](#embedding-cluster-health-charts "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/40997) . +* 在 13.2 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/208224) GitLab 核心. + +[Cluster Health Metrics](../../user/project/clusters/index.html#visualizing-cluster-health)也可以嵌入到[GitLab 风格的 Markdown 中](../../user/markdown.html) . + +要嵌入度量标准图表,请在支持 GitLab 风格的 Markdown 的任何位置以`https://<root_url>/<project>/-/cluster/<cluster_id>?<query_params>`的形式包含指向该图表的链接. 要生成并复制到图表的链接,请遵循[Cluster Health Metric 文档中的说明](../../user/project/clusters/index.html#visualizing-cluster-health) . + +指标必须满足以下要求: + +* `<cluster_id>`必须与实际群集相对应. +* Prometheus 必须监视群集. +* 必须允许用户访问项目集群指标. +* 仪表板必须在" [集群运行状况"页面](../../user/project/clusters/index.html#visualizing-cluster-health)上报告数据 + +如果满足上述要求,则度量标准将展开,如下所示. + +[![Embedded Cluster Metric in issue descriptions](img/f8c421bf7dd271d1aeee39c15aab183d.png)](../../user/project/integrations/img/prometheus_cluster_health_embed_v12_9.png) \ No newline at end of file diff --git a/docs/178.md b/docs/178.md new file mode 100644 index 0000000000000000000000000000000000000000..0e6fd4726745c7fc7d5300bf4eee899d51ea3ad1 --- /dev/null +++ b/docs/178.md @@ -0,0 +1,63 @@ +# Embedding Grafana charts + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/embed_grafana.html](https://docs.gitlab.com/ee/operations/metrics/embed_grafana.html) + +* [Embedding charts via Grafana Rendered Images](#embedding-charts-via-grafana-rendered-images) +* [Embedding charts via integration with Grafana HTTP API](#embedding-charts-via-integration-with-grafana-http-api) +* [Setting up the Grafana integration](#setting-up-the-grafana-integration) +* [Generating a link to a chart](#generating-a-link-to-a-chart) + +# Embedding Grafana charts[](#embedding-grafana-charts "Permalink") + +Grafana 指标可以嵌入到[GitLab 风味 Markdown 中](../../user/markdown.html) . + +## Embedding charts via Grafana Rendered Images[](#embedding-charts-via-grafana-rendered-images "Permalink") + +可以在问题中嵌入实时[Grafana](https://docs.gitlab.com/omnibus/settings/grafana.html)图表,作为[直接链接的渲染图像](https://grafana.com/docs/grafana/latest/reference/share_panel/#direct-link-rendered-image) . + +Grafana 中的共享对话框提供了链接,如下所示. + +[![Grafana Direct Linked Rendered Image](img/f406b88682259abab36d343539b1664c.png)](../../user/project/integrations/img/grafana_live_embed.png) + +**注意:**为了使此嵌入正确显示,Grafana 实例必须可作为公共仪表板或在同一网络上供目标用户使用. + +复制链接并在 Markdown 中将图像标签添加为[内联 HTML](../../user/markdown.html#inline-html) . 您可以根据需要调整查询参数. 例如,删除`&from=`和`&to=`参数将为您提供实时图表. 这是来自 GitLab 公共仪表板的实时图表的示例标记: + +``` +<img src="https://dashboards.gitlab.com/d/RZmbBr7mk/gitlab-triage?orgId=1&refresh=30s&var-env=gprd&var-environment=gprd&var-prometheus=prometheus-01-inf-gprd&var-prometheus_app=prometheus-app-01-inf-gprd&var-backend=All&var-type=All&var-stage=main&from=1580444107655&to=1580465707655"/> +``` + +这将呈现为: + +[![Grafana dashboard embedded preview](img/b820c73810583190a0b1697c813fdda8.png)](../../user/project/integrations/img/grafana_embedded.png) + +## Embedding charts via integration with Grafana HTTP API[](#embedding-charts-via-integration-with-grafana-http-api "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31376) . + +每个项目可以支持与一个 Grafana 实例的集成. 此配置允许用户将链接复制到 Grafana 中的面板,然后将其粘贴到 GitLab Markdown 字段中. 该图表将以 GitLab 图表格式呈现. + +从 Grafana 实例嵌入的先决条件: + +1. 数据源必须是 Prometheus 实例. +2. 数据源必须是可代理的,因此 HTTP 访问设置应设置为`Server` . + +[![HTTP Proxy Access](img/7896b9b275d92d4b9cb2001cc464e509.png)](../../user/project/integrations/img/http_proxy_access_v12_5.png) + +## Setting up the Grafana integration[](#setting-up-the-grafana-integration "Permalink") + +1. [Generate an Admin-level API Token in Grafana.](https://grafana.com/docs/grafana/latest/http_api/auth/#create-api-token) +2. 在您的 GitLab 项目中,导航至**设置>操作> Grafana 身份验证** . +3. 要启用集成,请选中"活动"复选框. +4. 对于" Grafana URL",输入 Grafana 实例的基本 URL. +5. 对于" API 令牌",输入您刚生成的 Admin API 令牌. +6. Click **保存更改**. + +## Generating a link to a chart[](#generating-a-link-to-a-chart "Permalink") + +1. 在 Grafana 中,导航到要嵌入面板的仪表板. [![Grafana 公制面板](img/eb191fa059117d5fb30958d7f6241704.png)](../../user/project/integrations/img/grafana_panel_v12_5.png) +2. 在页面的左上角,为图表中查询所需的每个变量选择一个特定值. [![选择查询变量](img/40834a63780a362f429e1902450a4a7a.png)](../../user/project/integrations/img/select_query_variables_v12_5.png) +3. 在 Grafana 中,单击面板的标题,然后单击" **共享"**以将面板的共享对话框打开到" **链接"**选项卡. 如果您单击*仪表板的*共享面板,则 GitLab 将尝试在仪表板上嵌入第一个受支持的面板(如果有). +4. 如果您的普罗米修斯查询使用 Grafana 的自定义模板变量,确保"模板变量"选项切换为**开** . 在 Grafana 全局模板变量中,目前仅支持`$__interval` , `$__from`和`$__to` . 切换**"**当前时间范围"选项来指定图表的时间范围. 否则,默认范围将是最近 8 小时. [![Grafana 共享对话框](img/ce9e5e0a216a3a51d412bcb3cb11f420.png)](../../user/project/integrations/img/grafana_sharing_dialog_v12_5.png) +5. 单击**复制**将 URL **复制**到剪贴板. +6. 在 GitLab 中,将该 URL 粘贴到 Markdown 字段中并保存. 该图表将需要一些时间来呈现. [![GitLab 渲染的 Grafana 面板](img/c67bf60334fcbd1f63dc0a6515d02eca.png)](../../user/project/integrations/img/rendered_grafana_embed_v12_5.png) \ No newline at end of file diff --git a/docs/179.md b/docs/179.md new file mode 100644 index 0000000000000000000000000000000000000000..125d3db03ed668014a756625c930b03baf04bb72 --- /dev/null +++ b/docs/179.md @@ -0,0 +1,216 @@ +# Using the Metrics Dashboard + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/dashboards/](https://docs.gitlab.com/ee/operations/metrics/dashboards/) + +* [Manage the metrics dashboard settings](#manage-the-metrics-dashboard-settings) +* [Chart Context Menu](#chart-context-menu) + * [View and edit the source file of a custom dashboard](#view-and-edit-the-source-file-of-a-custom-dashboard) + * [Expand panel](#expand-panel) + * [View Logs](#view-logs-ultimate) + * [Timeline zoom and URL sharing](#timeline-zoom-and-url-sharing) + * [Downloading data as CSV](#downloading-data-as-csv) +* [Dashboard Annotations](#dashboard-annotations) + * [Retention policy](#retention-policy) +* [Add related links to custom dashboards](#add-related-links-to-custom-dashboards) + * [Links Syntax](#links-syntax) +* [Defining custom dashboards per project](#defining-custom-dashboards-per-project) + * [Adding a new dashboard to your project](#adding-a-new-dashboard-to-your-project) + * [Navigating to a custom dashboard](#navigating-to-a-custom-dashboard) + * [Duplicating a GitLab-defined dashboard](#duplicating-a-gitlab-defined-dashboard) +* [Troubleshooting](#troubleshooting) + * [“No data found” error on Metrics dashboard page](#no-data-found-error-on-metrics-dashboard-page) + +# Using the Metrics Dashboard[](#using-the-metrics-dashboard "Permalink") + +## Manage the metrics dashboard settings[](#manage-the-metrics-dashboard-settings "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/223204) . + +要管理指标信息中心的设置,请执行以下操作: + +1. 以具有项目维护者或管理员[权限](../../../user/permissions.html#project-members-permissions)的用户身份登录. +2. 导航至以下位置的信息中心 **操作>指标** . +3. 在资讯主页的右上角,按一下 **指标设置** : + + [![Monitoring Dashboard actions menu with create new item](img/0df7602f630bb279bdd6d7dc6a5dcf2f.png)](../../../user/project/integrations/img/metrics_settings_button_v13_2.png) + +## Chart Context Menu[](#chart-context-menu "Permalink") + +在信息中心的每个面板上,您都可以通过以下方式访问上下文菜单: 面板右上角上方的" **更多操作"**下拉框可采取与图表数据相关的操作. + +[![Context Menu](img/1a3371a11e14e221f5c8e0e75e327d08.png)](../../../user/project/integrations/img/panel_context_menu_v13_0.png) + +选项包括: + +* [Expand panel](#expand-panel) +* [View logs](#view-logs-ultimate) +* [Download CSV](#downloading-data-as-csv) +* [Copy link to chart](../embed.html#embedding-gitlab-managed-kubernetes-metrics) +* [Alerts](../alerts.html) + +### View and edit the source file of a custom dashboard[](#view-and-edit-the-source-file-of-a-custom-dashboard "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34779) . + +查看项目的自定义仪表板时,可以通过单击" **编辑仪表板"**按钮来查看原始的`.yml`文件. + +### Expand panel[](#expand-panel "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/3100) . + +要查看较大的可视化版本,请点击 **更多操作**图标,然后选择**展开面板** . + +要返回指标仪表板,请单击浏览器中的" **后退"**按钮,或按`Esc`键. + +### View Logs[](#view-logs-ultimate "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/122013) . + +如果启用了[日志](../../../user/project/clusters/kubernetes_pod_logs.html) ,则可以通过单击右上角的上下文菜单从仪表板中的图表导航以查看日志. + +如果使用图表底部的**时间轴缩放**功能,日志将缩小到您选择的时间范围. + +### Timeline zoom and URL sharing[](#timeline-zoom-and-url-sharing "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/198910) . + +您可以使用图表底部的**时间轴缩放**功能来放大所选的日期和时间. 单击并拖动滑块以选择要显示的数据的其他开始或结束日期时,GitLab 会将所选的开始和结束时间添加到 URL,从而使您可以更轻松地共享特定的时间范围. + +### Downloading data as CSV[](#downloading-data-as-csv "Permalink") + +指标仪表板上 Prometheus 图表中的数据可以 CSV 格式下载. + +## Dashboard Annotations[](#dashboard-annotations "Permalink") + +版本历史 + +* 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/211330) (由功能标志`metrics_dashboard_annotations`启用). +* 在 GitLab 13.0 中[删除](https://gitlab.com/gitlab-org/gitlab/-/issues/215224)了[功能标志](https://gitlab.com/gitlab-org/gitlab/-/issues/215224) . + +您可以使用" **指标仪表板注释"**通过在每个指标仪表板上添加注释来标记任何重要事件. 在查看仪表板时,分配给所选时间范围的注释条目将自动获取并显示在该仪表板内的每个图表上. 鼠标悬停时,每个注释都会显示其他详细信息,包括事件的确切时间及其描述. + +您可以通过向[Metrics 仪表板注释 API](../../../api/metrics_dashboard_annotations.html)发出请求来创建注释 + +[![Annotations UI](img/afe1906c0ba8e9c44277342a20a48db6.png)](../../../user/project/integrations/img/metrics_dashboard_annotations_ui_v13.0.png) + +### Retention policy[](#retention-policy "Permalink") + +在 GitLab 13.01 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/211433) . + +为了避免过时的注释浪费过多的存储空间,每天都会删除附加到超过两周时间段的记录. 此重复后台作业在本地服务器时间上午 1:00 运行. + +## Add related links to custom dashboards[](#add-related-links-to-custom-dashboards "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/216385) . + +You can embed links to other dashboards or external services in your custom dashboard by adding **相关链接** to your dashboard’s YAML file. Related links open in the same tab as the dashboard. Related links can be displayed in the following locations on your dashboard: + +* 在仪表板顶部,作为顶层[`links`仪表板属性](../../../operations/metrics/dashboards/yaml.html#dashboard-top-level-properties) . +* 在图表中,上下文菜单作为[面板](../../../operations/metrics/dashboards/yaml.html#panel-panels-properties)的[`links`属性](../../../operations/metrics/dashboards/yaml.html#panel-panels-properties) . + +相关链接可以包含以下属性: + +* `url` :链接的完整 URL. 需要. +* `title` :描述链接的短语. 可选的. 如果未设置此属性,则将完整的 URL 用于链接标题. +* `type` :一个声明链接类型的字符串. 可选的. 如果设置为`grafana` ,则仪表板的时间范围值将转换为 Grafana 的时间范围格式并附加到`url` . + +仪表板的时间范围作为 URL 参数附加到`url` . + +以下示例显示了添加到仪表板的两个相关链接( `GitLab.com`和`GitLab Documentation` ): + +[![Links UI](img/fe601ff47f99f0fd5220742f61007450.png)](../../../user/project/integrations/img/related_links_v13_1.png) + +### Links Syntax[](#links-syntax "Permalink") + +``` +links: + - title: GitLab.com + url: https://gitlab.com + - title: GitLab Documentation + url: https://docs.gitlab.com + - title: Public Grafana playground dashboard + url: https://play.grafana.org/d/000000012/grafana-play-home?orgId=1 + type: grafana +``` + +## Defining custom dashboards per project[](#defining-custom-dashboards-per-project "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/59974) . + +默认情况下,所有项目都包含一个由 GitLab 定义的 Prometheus 仪表板,其中包括一些关键指标,但是您也可以定义自己的自定义仪表板. + +您可以从头开始创建新文件,也可以复制 GitLab 定义的 Prometheus 仪表板. + +**注意:**与[自定义指标](../index.html#adding-custom-metrics)不同,以下[定义的指标](../index.html#adding-custom-metrics)不支持警报. + +### Adding a new dashboard to your project[](#adding-a-new-dashboard-to-your-project "Permalink") + +GitLab 13.2 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/223204) UI 选项. + +您可以通过将新的 YAML 文件添加到项目的`.gitlab/dashboards/`目录中来配置自定义仪表`.gitlab/dashboards/` . 为了将仪表板显示在项目的 **在"操作">"度量标准"**页面上,文件必须具有`.yml`扩展名,并且应存在于项目的**默认**分支中. + +要从 GitLab 用户界面创建新的仪表板,请执行以下操作: + +1. 以具有"维护者"或"所有者" [权限](../../../user/permissions.html#project-members-permissions)的用户身份登录到 GitLab. +2. 导航至以下位置的信息中心 **操作>指标** . +3. 在信息中心的右上角,点击 **在"操作"**菜单上,然后选择" **新建"** : [![使用创建新项目的](img/b24c623173b50fdf9cd2676f1f311580.png)](../../../user/project/integrations/img/actions_menu_create_new_dashboard_v13_2.png) +4. 在模式窗口中,单击**打开存储库** ,然后按照说明从命令行创建新的仪表板. + +要从命令行创建新的仪表板: + +1. 在存储库的根目录下创建`.gitlab/dashboards/prom_alerts.yml` . 每个 YAML 文件都应定义仪表板的布局以及用于填充数据的 Prometheus 查询. 此示例仪表板显示一个面积图: + + ``` + dashboard: 'Dashboard Title' + panel_groups: + - group: 'Group Title' + panels: + - type: area-chart + title: "Chart Title" + y_label: "Y-Axis" + y_axis: + format: number + precision: 0 + metrics: + - id: my_metric_id + query_range: 'http_requests_total' + label: "Instance: {{instance}}, method: {{method}}" + unit: "count" + ``` + +2. 保存文件,提交并推送到您的存储库. 该文件必须存在于您的**默认**分支中. +3. 导航到项目的" **操作">"指标",**然后从下拉列表中选择自定义仪表板. + +**注意:**不支持嵌套在`.gitlab/dashboards`子目录下的配置文件,并且在 UI 中将不可用. + +### Navigating to a custom dashboard[](#navigating-to-a-custom-dashboard "Permalink") + +自定义仪表板通过其文件名唯一标识. 为了快速查看自定义仪表板,只需通过以下方式在 URL 中使用仪表板文件名: `https://gitlab-instance.example.com/project/-/metrics/custom_dashboard_name.yml` : `https://gitlab-instance.example.com/project/-/metrics/custom_dashboard_name.yml` . + +### Duplicating a GitLab-defined dashboard[](#duplicating-a-gitlab-defined-dashboard "Permalink") + +版本历史 + +* 在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/37238) . +* 从[GitLab 12.8 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/39505) ,自定义指标也将在您复制仪表板时被复制. + +您可以保存 GitLab 定义的仪表板的完整副本以及添加到其中的所有自定义指标. 可以对生成的`.yml`文件进行自定义并使其适合您的项目. 您可以决定将仪表板`.yml`文件保存在项目的**默认**分支或新分支中. + +1. 在仪表板下拉菜单或操作菜单中,单击**重复仪表**板. + + **注意:**您只能复制 GitLab 定义的仪表板. +2. 输入文件名和其他信息,例如新提交的消息,然后单击**Duplicate** . + +如果选择**默认**分支,新的仪表板将立即可用. 如果选择另一个分支,则应首先将此分支合并到**默认**分支. + +## Troubleshooting[](#troubleshooting "Permalink") + +对托管的 Prometheus 应用程序的问题进行故障排除时, [查看 Prometheus UI](../../../development/prometheus.html#access-the-ui-of-a-prometheus-managed-application-in-kubernetes)通常很有用. + +### “No data found” error on Metrics dashboard page[](#no-data-found-error-on-metrics-dashboard-page "Permalink") + +如果继续出现"找不到数据"屏幕,则可能是由于: + +* 此环境尚未成功部署. +* Prometheus 没有此环境的性能数据,或者指标未正确标记. 要对此进行测试,请连接到 Prometheus 服务器并[运行查询](../../../user/project/integrations/prometheus_library/kubernetes.html#metrics-supported) ,将`$CI_ENVIRONMENT_SLUG`替换`$CI_ENVIRONMENT_SLUG`您的环境名称. +* 您可能需要重新添加 GitLab 预定义的通用指标. 这可以通过运行[导入公用度量 Rake 任务来完成](../../../administration/raketasks/maintenance.html#import-common-metrics) . \ No newline at end of file diff --git a/docs/180.md b/docs/180.md new file mode 100644 index 0000000000000000000000000000000000000000..1f9d9484c06a84400c9edfaa57fe9cb48d809380 --- /dev/null +++ b/docs/180.md @@ -0,0 +1,173 @@ +# Dashboard YAML properties + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/dashboards/yaml.html](https://docs.gitlab.com/ee/operations/metrics/dashboards/yaml.html) + +* [**Dashboard (top-level) properties**](#dashboard-top-level-properties) +* [**Templating (`templating`) properties**](#templating-templating-properties) +* [**Links (`links`) properties**](#links-links-properties) +* [**Panel group (`panel_groups`) properties**](#panel-group-panel_groups-properties) +* [**Panel (`panels`) properties**](#panel-panels-properties) +* [**Axis (`panels[].y_axis`) properties**](#axis-panelsy_axis-properties) +* [**Metrics (`metrics`) properties**](#metrics-metrics-properties) +* [Dynamic labels](#dynamic-labels) +* [Dashboard YAML syntax validation](#dashboard-yaml-syntax-validation) + +# Dashboard YAML properties[](#dashboard-yaml-properties "Permalink") + +仪表板包含几个组件: + +* 模板变量. +* 面板组,由面板组成. +* 支持一个或多个指标的面板. + +下表概述了预期属性的详细信息. + +## **Dashboard (top-level) properties**[](#dashboard-top-level-properties "Permalink") + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `dashboard` | string | yes | 前往仪表板. 每个文件只能定义一个仪表板. | +| `panel_groups` | array | yes | 应在仪表板上的面板组. | +| `templating` | hash | no | 可以在其下添加模板相关选项的顶级键. | +| `links` | array | no | 添加链接以显示在仪表板上. | + +## **Templating (`templating`) properties**[](#templating-templating-properties "Permalink") + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `variables` | hash | yes | 可以在这里定义变量. | + +阅读有关[模板](templating_variables.html)的文档. + +## **Links (`links`) properties**[](#links-links-properties "Permalink") + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `url` | string | yes | 链接的地址. | +| `title` | string | no | 显示链接的标题. | +| `type` | string | no | 链接的类型. 指定链接类型,可以是: `grafana` | + +阅读有关[链接](index.html#add-related-links-to-custom-dashboards)的文档. + +## **Panel group (`panel_groups`) properties**[](#panel-group-panel_groups-properties "Permalink") + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `group` | string | required | 前往面板组. | +| `priority` | number | 可选,默认为按文件顺序 | 命令显示在仪表板上. 数字越高意味着优先级越高,该页面上的优先级越高. 数字不必是连续的. | +| `panels` | array | required | 应在面板组中的面板. | + +面板组中的面板排成一排,每行包含两个面板. 该规则的一个例外是一行上的单个面板:这些面板将采用其所在行的整个宽度. + +## **Panel (`panels`) properties**[](#panel-panels-properties "Permalink") + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | enum | 不,默认为`area-chart` | 指定要使用的面板类型,例如`area-chart` , `line-chart`或`anomaly-chart` . [查看所有面板类型的文档.](panel_types.html) | +| `title` | string | yes | 前往面板. | +| `y_label` | string | 不,但强烈鼓励 | 面板的 Y 轴标签. | +| `y_axis` | string | no | 面板的 Y 轴配置. | +| `max_value` | number | no | 分母值用于计算[基于百分位数的结果](panel_types.html#percentile-based-results) | +| `weight` | number | 否,默认为按文件顺序 | 顺序出现在分组中. 较低的数字表示较高的优先级,在页面上较高. 数字不必是连续的. | +| `metrics` | array | yes | 应在面板中显示的指标. 当`type`是`area-chart`或`line-chart` ,可以显示任意数量的度量标准,而当`type`是`anomaly-chart`时,只能显示 3 个度量标准. | +| `links` | array | no | 添加链接以显示在图表的[上下文菜单上](index.html#chart-context-menu) . | + +## **Axis (`panels[].y_axis`) properties**[](#axis-panelsy_axis-properties "Permalink") + +| Property | Type | Required | Description |   | +| --- | --- | --- | --- | --- | +| `name` | string | 不,但强烈鼓励 | 面板的 Y 轴标签. 如果设置,则替换`y_label` . |   | +| `format` | string | 否,默认为`engineering` | 使用的单位格式. 请参阅[单位](yaml_number_format.html)的[完整列表](yaml_number_format.html) . |   | +| `precision` | number | 否,默认为`2` | 要显示在数字中的小数位数. |   | + +## **Metrics (`metrics`) properties**[](#metrics-metrics-properties "Permalink") + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | string | no | 用于将仪表板指标与数据库记录相关联. 在仪表板配置文件中必须唯一. [警报所](../alerts.html)必需(尚未启用支持,请参阅[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/27980) ). | +| `unit` | string | yes | 定义查询的返回数据的单位. | +| `label` | string | 不,但强烈鼓励 | 定义查询的图例标签. 在面板指标内应唯一. 可以包含时间序列标签作为内插变量. | +| `query` | string | 是,如果没有定义`query_range` | 定义用于填充图表/面板的 Prometheus 查询. 如果定义,将使用[Prometheus API](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/)的`query`端点. | +| `query_range` | string | 是,如果未定义`query` | 定义用于填充图表/面板的 Prometheus 查询. 如果定义,将使用[Prometheus API](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/)的`query_range`端点. | +| `step` | number | 不,如果未定义,则计算值 | 定义查询解析步长(以秒为单位). 同一面板上的指标应使用相同的`step`值. | + +## Dynamic labels[](#dynamic-labels "Permalink") + +从 Prometheus 查询返回多个时间序列时,动态标签很有用. + +当使用静态标签并且查询返回多个时间序列时,所有图例项将被标记为相同,这使得识别每个时间序列变得困难: + +``` +metrics: + - id: my_metric_id + query_range: 'http_requests_total' + label: "Time Series" + unit: "count" +``` + +这可能会生成如下图例: + +[![repeated legend label chart](img/366832d79f753b4e66470fa923fa7acf.png)](../../../user/project/integrations/img/prometheus_dashboard_repeated_label.png) + +为了使标签更明确,使用反映时间序列标签的变量是一个好习惯. 渲染图例时,变量将被时间序列标签的值替换: + +``` +metrics: + - id: my_metric_id + query_range: 'http_requests_total' + label: "Instance: {{instance}}, method: {{method}}" + unit: "count" +``` + +生成的渲染图例将如下所示: + +[![legend with label variables](img/ef26fe9cbbfc0c1f060c6e7c578bd450.png)](../../../user/project/integrations/img/prometheus_dashboard_label_variables.png) + +动态仪表板标签还有一个简写值,该标签仅使用一个时间序列标签: + +``` +metrics: + - id: my_metric_id + query_range: 'http_requests_total' + label: "Method" + unit: "count" +``` + +这可以通过降低`label`的值来实现,如果还有更多的单词用空格分隔,请用下划线( `_` )替换这些空格. 然后根据 Prometheus 查询返回的时间序列的标签检查转换后的值. 如果找到与转换后的值相等的时间序列标签,则将使用标签值并将其呈现在图例中,如下所示: + +[![legend with label shorthand variable](img/def845e9e4d65228469b73dbc625c6cd.png)](../../../user/project/integrations/img/prometheus_dashboard_label_variable_shorthand.png) + +## Dashboard YAML syntax validation[](#dashboard-yaml-syntax-validation "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33202) . + +要确认您的仪表板定义包含有效的 YAML 语法,请执行以下操作: + +1. 导航 **存储库>文件** . +2. 导航到存储库中的仪表板文件. +3. 查看文件内容上方显示的有关文件的信息窗格. + +具有有效语法的文件显示**Metrics 仪表板 YAML 定义有效** ,而具有无效语法的文件显示**Metrics Dashboard YAML 定义无效** . + +[![Metrics Dashboard_YAML_syntax_validation](img/5f3552f35a06cac8dfa02c21fd48c852.png)](../../../user/project/integrations/img/prometheus_dashboard_yaml_validation_v13_1.png) + +当" **指标仪表板" YAML 定义无效时** ,将至少显示以下消息之一: + +1. `dashboard: can't be blank` [learn more](../../../operations/metrics/dashboards/yaml.html#dashboard-top-level-properties) +2. `panel_groups: should be an array of panel_groups objects` [learn more](../../../operations/metrics/dashboards/yaml.html#dashboard-top-level-properties) +3. `group: can't be blank` [learn more](../../../operations/metrics/dashboards/yaml.html#panel-group-panel_groups-properties) +4. `panels: should be an array of panels objects` [learn more](../../../operations/metrics/dashboards/yaml.html#panel-group-panel_groups-properties) +5. `title: can't be blank` [learn more](../../../operations/metrics/dashboards/yaml.html#panel-panels-properties) +6. `metrics: should be an array of metrics objects` [learn more](../../../operations/metrics/dashboards/yaml.html#panel-panels-properties) +7. `query: can't be blank` [learn more](../../../operations/metrics/dashboards/yaml.html#metrics-metrics-properties) +8. `query_range: can't be blank` [learn more](../../../operations/metrics/dashboards/yaml.html#metrics-metrics-properties) +9. `unit: can't be blank` [learn more](../../../operations/metrics/dashboards/yaml.html#metrics-metrics-properties) +10. `YAML syntax: The parsed YAML is too big` + + 当 YAML 文件大于 1 MB 时显示. + +11. `YAML syntax: Invalid configuration format` + + 当 YAML 文件为空或不包含有效的 YAML 时显示. + +指标仪表板 YAML 定义验证信息也可以作为[GraphQL API 字段获得](../../../api/graphql/reference/index.html#metricsdashboard) \ No newline at end of file diff --git a/docs/181.md b/docs/181.md new file mode 100644 index 0000000000000000000000000000000000000000..d9075099a55a5d9b195a1b926874a44af194ce45 --- /dev/null +++ b/docs/181.md @@ -0,0 +1,44 @@ +# Metrics dashboard settings + +> 原文:[https://docs.gitlab.com/ee/user/project/operations/dashboard_settings.html](https://docs.gitlab.com/ee/user/project/operations/dashboard_settings.html) + +* [Change the dashboard time zone](#change-the-dashboard-time-zone) +* [Link to an external dashboard](#link-to-an-external-dashboard) + +# Metrics dashboard settings[](#metrics-dashboard-settings "Permalink") + +您可以配置[监控仪表板](../integrations/prometheus.html)以显示您选择的时区以及您选择的链接. + +要配置这些设置,您必须具有"管理项目操作" [权限](../../permissions.html) . + +## Change the dashboard time zone[](#change-the-dashboard-time-zone "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214370) . + +默认情况下,监视仪表板在本地时区中显示日期和时间,但是您可以 UTC 格式显示日期和时间. 更改时区: + +1. 以具有"管理项目操作" [权限](../../permissions.html)的用户身份登录. +2. 导航 **设置>操作** ,然后滚动到" **指标仪表板"** . +3. 在" **仪表板时区"**选择框中,选择" *用户的本地时区"*或" *UTC"* : + + [![Dashboard timezone setting](img/9079254cc7f9fbc13ee5005765608b59.png)](img/dashboard_local_timezone_v13_1.png) + +4. Click **保存更改**. + +## Link to an external dashboard[](#link-to-an-external-dashboard "Permalink") + +在 GitLab 12.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/57171) . + +您可以在监视仪表板上添加一个按钮,该按钮直接链接到现有的外部仪表板: + +1. 以具有"管理项目操作" [权限](../../permissions.html)的用户身份登录. +2. 导航 **设置>操作** ,然后滚动到" **指标仪表板"** . +3. 在**外部仪表板 URL 中** ,提供您的外部仪表板的 URL: + + [![External Dashboard Setting](img/3da5d65194b00f9dc3ffde2ac5f8473b.png)](img/dashboard_external_link_v13_1.png) + +4. Click **保存更改**. + +GitLab 在[监视仪表板的](../../../ci/environments/index.html#monitoring-environments)右上角显示一个" **查看完整的仪表板"**按钮,该按钮可打开您提供的 URL: + +[![External Dashboard Link](img/ddc1b7f5f622e5c8f6581738b42964cb.png)](img/external_dashboard_link.png) \ No newline at end of file diff --git a/docs/182.md b/docs/182.md new file mode 100644 index 0000000000000000000000000000000000000000..3219ca57d990e9b1774d34c5f122f52c233712e0 --- /dev/null +++ b/docs/182.md @@ -0,0 +1,268 @@ +# Panel types for dashboards + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/dashboards/panel_types.html](https://docs.gitlab.com/ee/operations/metrics/dashboards/panel_types.html) + +* [Area or Line Chart](#area-or-line-chart) +* [Anomaly chart](#anomaly-chart) +* [Bar chart](#bar-chart) +* [Column chart](#column-chart) +* [Stacked column](#stacked-column) +* [Single Stat](#single-stat) +* [Percentile based results](#percentile-based-results) +* [Heatmaps](#heatmaps) + +# Panel types for dashboards[](#panel-types-for-dashboards "Permalink") + +监视仪表板中支持以下面板类型. + +## Area or Line Chart[](#area-or-line-chart "Permalink") + +要将面积图面板类型添加到仪表盘,请查看以下样本仪表盘文件: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group Title' + panels: + - type: area-chart # or line-chart + title: 'Area Chart Title' + y_label: "Y-Axis" + y_axis: + format: number + precision: 0 + metrics: + - id: area_http_requests_total + query_range: 'http_requests_total' + label: "Instance: {{instance}}, Method: {{method}}" + unit: "count" +``` + +请注意以下属性: + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| type | string | no | 要渲染的面板类型. 区域面板类型的可选 | +| query_range | string | required | 对于区域面板类型,必须使用[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) | + +[![area panel chart](img/adf6de6d0c4125be4e7a25119c0193e1.png)](../../../user/project/integrations/img/prometheus_dashboard_area_panel_type_v12_8.png) + +从[版本 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/202696)开始,y 轴值将根据数据自动缩放. 以前,它总是从 0 开始. + +## Anomaly chart[](#anomaly-chart "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16530) . + +要将异常图表面板类型添加到仪表盘,请添加*恰好具有* 3 个指标的面板. + +第一个指标代表当前状态,第二个和第三个指标分别代表上限和下限: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group Title' + panels: + - type: anomaly-chart + title: "Chart Title" + y_label: "Y-Axis" + metrics: + - id: anomaly_requests_normal + query_range: 'http_requests_total' + label: "# of Requests" + unit: "count" + metrics: + - id: anomaly_requests_upper_limit + query_range: 10000 + label: "Max # of requests" + unit: "count" + metrics: + - id: anomaly_requests_lower_limit + query_range: 2000 + label: "Min # of requests" + unit: "count" +``` + +请注意以下属性: + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| type | string | required | 异常面板类型必须为`anomaly-chart` | +| query_range | yes | required | 对于异常面板类型,必须在每个指标中使用[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) . | + +[![anomaly panel type](img/8a4af39c416005af074623092e32d782.png)](../../../user/project/integrations/img/prometheus_dashboard_anomaly_panel_type.png) + +## Bar chart[](#bar-chart "Permalink") + +要将条形图添加到仪表板,请查看以下样本仪表板文件: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group title' + panels: + - type: bar + title: "Http Handlers" + x_label: 'Response Size' + y_axis: + name: "Handlers" + metrics: + - id: prometheus_http_response_size_bytes_bucket + query_range: "sum(increase(prometheus_http_response_size_bytes_bucket[1d])) by (handler)" + unit: 'Bytes' +``` + +请注意以下属性: + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | string | yes | 要渲染的面板类型. 对于条形图类型,设置为`bar` | +| `query_range` | yes | yes | 对于条形图,必须使用[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) | + +[![bar chart panel type](img/c61ac95a0fe55d92ab3c711ea814a8c8.png)](../../../user/project/integrations/img/prometheus_dashboard_bar_chart_panel_type_v12.10.png) + +## Column chart[](#column-chart "Permalink") + +要将列面板类型添加到仪表板,请查看以下样本仪表板文件: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group title' + panels: + - title: "Column" + type: "column" + metrics: + - id: 1024_memory + query: 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024' + unit: MB + label: "Memory Usage" +``` + +请注意以下属性: + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| type | string | yes | 要渲染的面板类型. 对于列面板类型,设置为`column` | +| query_range | yes | yes | 对于列面板类型,必须使用[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) | + +[![anomaly panel type](img/468eb44e935f615292705e2fc013ddb7.png)](../../../user/project/integrations/img/prometheus_dashboard_column_panel_type.png) + +## Stacked column[](#stacked-column "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30583) . + +要将堆叠的列面板类型添加到仪表板,请查看以下样本仪表板文件: + +``` +dashboard: 'Dashboard title' +priority: 1 +panel_groups: + - group: 'Group Title' + priority: 5 + panels: + - type: 'stacked-column' + title: "Stacked column" + y_label: "y label" + x_label: 'x label' + metrics: + - id: memory_1 + query_range: 'memory_query' + label: "memory query 1" + unit: "count" + series_name: 'group 1' + - id: memory_2 + query_range: 'memory_query_2' + label: "memory query 2" + unit: "count" + series_name: 'group 2' +``` + +[![stacked column panel type](img/62313a9f27e05c60c700ec9625e27d02.png)](../../../user/project/integrations/img/prometheus_dashboard_stacked_column_panel_type_v12_8.png) + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | string | yes | 要渲染的面板类型. 对于堆叠式柱面板类型,设置为" `stacked-column` | +| `query_range` | yes | yes | 对于堆叠式列面板类型,必须使用[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) | + +## Single Stat[](#single-stat "Permalink") + +要将单个状态面板类型添加到仪表板,请查看以下样本仪表板文件: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group Title' + panels: + - title: "Single Stat" + type: "single-stat" + metrics: + - id: 10 + query: 'max(go_memstats_alloc_bytes{job="prometheus"})' + unit: MB + label: "Total" +``` + +请注意以下属性: + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| type | string | yes | 要渲染的面板类型. 对于单一统计信息面板类型,设置为`single-stat` | +| field | string | no | 面板显示指标的值. 要使面板显示标签的值,请在该键中放置标签的名称. | +| query | string | yes | For single stat panel types, you must use an [instant query](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) | + +[![single stat panel type](img/51902d01ed097ad499a4e6eb984d3e86.png)](../../../user/project/integrations/img/prometheus_dashboard_single_stat_panel_type.png) + +## Percentile based results[](#percentile-based-results "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/201946) . + +有时需要将查询结果表示为 100 中的百分比值.您可以在面板定义的根部使用`max_value`属性: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group Title' + panels: + - title: "Single Stat" + type: "single-stat" + max_value: 100 + metrics: + - id: 10 + query: 'max(go_memstats_alloc_bytes{job="prometheus"})' + unit: '%' + label: "Total" +``` + +例如,如果查询值为`53.6` ,则将`%`添加为单位将得出`53.6%`的单个统计值,但是如果查询的最大期望值为`120` ,则该值为`44.6%` . 添加`max_value`会导致显示正确的百分比值. + +## Heatmaps[](#heatmaps "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30581) . + +要将热图面板类型添加到仪表板,请查看以下样本仪表板文件: + +``` +dashboard: 'Dashboard Title' +panel_groups: + - group: 'Group Title' + panels: + - title: "Heatmap" + type: "heatmap" + metrics: + - id: 10 + query: 'sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[60m])) by (status_code)' + unit: req/sec + label: "Status code" +``` + +请注意以下属性: + +| Property | Type | Required | Description | +| --- | --- | --- | --- | +| type | string | yes | 要渲染的面板类型. 对于热图面板类型,设置为`heatmap` | +| query_range | yes | yes | 对于区域面板类型,必须使用[范围查询](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/api/) | + +[![heatmap panel type](img/10fd27d874d8e6ace6b74801909782ae.png)](../../../user/project/integrations/img/heatmap_panel_type.png) + +**警告:**当查询返回太多数据点时,热图数据桶的尺寸趋于向下至 0,从而使图表的数据不可见,如下图所示. 要解决此问题,请通过更改指标仪表板 UI 上的时间范围过滤器,或将**step**属性添加到仪表板的 YAML 文件中,来限制返回的数据量. + +[![heatmap chart_too_much_data](img/c89e56a24555efe89bb446cf31b5f764.png)](../../../user/project/integrations/img/heatmap_chart_too_much_data_v_13_2.png) \ No newline at end of file diff --git a/docs/183.md b/docs/183.md new file mode 100644 index 0000000000000000000000000000000000000000..b420a17043d07b6866fd392de6bd78395c1bcc05 --- /dev/null +++ b/docs/183.md @@ -0,0 +1,55 @@ +# Using Variables + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/dashboards/variables.html](https://docs.gitlab.com/ee/operations/metrics/dashboards/variables.html) + +* [Query Variables](#query-variables) +* [Predefined variables](#predefined-variables) + * [__range](#__range) +* [User-defined variables](#user-defined-variables) +* [Query Variables from URL](#query-variables-from-url) + +# Using Variables[](#using-variables "Permalink") + +## Query Variables[](#query-variables "Permalink") + +可以使用双花括号来指定变量,例如`"{{ci_environment_slug}}"` (在 GitLab 12.7 中已[添加](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20793) ). + +在 GitLab 13.0 中[删除](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31581)了对`"%{ci_environment_slug}"`格式的支持. 继续使用旧格式的查询将不会显示任何数据. + +## Predefined variables[](#predefined-variables "Permalink") + +GitLab 在 Prometheus 查询中支持一组有限的[CI 变量](../../../ci/variables/README.html) . 这对于标识特定环境(例如`ci_environment_slug` )特别有用. 支持的变量是: + +* `ci_environment_slug` +* `kube_namespace` +* `ci_project_name` +* `ci_project_namespace` +* `ci_project_path` +* `ci_environment_name` +* `__range` + +**注意:** Prometheus 查询的变量必须小写. + +### __range[](#__range "Permalink") + +`__range`变量在 Prometheus [范围向量选择器中](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/basics/)很有用. 它的值是仪表板时间范围内的总秒数. 例如,如果仪表板时间范围设置为 8 小时,则`__range`值为`28800s` . + +## User-defined variables[](#user-defined-variables "Permalink") + +[可以](../../../operations/metrics/dashboards/yaml.html#templating-templating-properties)在自定义仪表板 YAML 文件中[定义变量](../../../operations/metrics/dashboards/yaml.html#templating-templating-properties) . + +## Query Variables from URL[](#query-variables-from-url "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214500) . + +GitLab 支持通过 URL 参数设置自定义变量. 用双花括号( `{{example}}` )包围变量名称,以在查询中插入变量: + +``` +avg(sum(container_memory_usage_bytes{container_name!="{{pod}}"}) by (job)) without (job) /1024/1024/1024' +``` + +该查询的 URL 为: + +``` +http://gitlab.com/<user>/<project>/-/environments/<environment_id>/metrics?dashboard=.gitlab%2Fdashboards%2Fcustom.yml&pod=POD +``` \ No newline at end of file diff --git a/docs/184.md b/docs/184.md new file mode 100644 index 0000000000000000000000000000000000000000..1f86ab43d4259275ac428e1694f3c2d9096ecc19 --- /dev/null +++ b/docs/184.md @@ -0,0 +1,112 @@ +# Templating variables for metrics dashboards + +> 原文:[https://docs.gitlab.com/ee/operations/metrics/dashboards/templating_variables.html](https://docs.gitlab.com/ee/operations/metrics/dashboards/templating_variables.html) + +* [`text` variable type](#text-variable-type) + * [Simple syntax](#simple-syntax) + * [Full syntax](#full-syntax) +* [`custom` variable type](#custom-variable-type) + * [Simple syntax](#simple-syntax-1) + * [Full syntax](#full-syntax-1) +* [`metric_label_values` variable type](#metric_label_values-variable-type) + * [Full syntax](#full-syntax-2) + +# Templating variables for metrics dashboards[](#templating-variables-for-metrics-dashboards "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214539) . + +模板变量可用于使指标仪表板更加通用. + +`templating`是[仪表板 YAML 中](yaml.html#dashboard-top-level-properties)的顶级键. 在`templating`下的`variables`键中定义变量. `variables`键的值应为哈希, `variables`下的每个键在仪表板上定义一个模板变量,并且可以包含字母数字和下划线字符. + +可以使用[使用变量中](variables.html)所述的语法在同一仪表板的 Prometheus 查询[中使用变量](variables.html) . + +## `text` variable type[](#text-variable-type "Permalink") + +**警告:**此变量类型是*alpha*功能,如有更改,恕不另行通知! + +对于仪表板 YAML 中定义的每个`text`变量,仪表板 UI 上都会有一个自由文本框,您可以为每个变量输入一个值. + +`text`变量类型支持简单和完整的语法. + +### Simple syntax[](#simple-syntax "Permalink") + +本示例创建一个名为`variable1` ,其默认值为`default value` : + +``` +templating: + variables: + variable1: 'default value' # `text` type variable with `default value` as its default. +``` + +### Full syntax[](#full-syntax "Permalink") + +本示例创建一个名为`variable1` ,其默认值为`default` . UI 上文本框的标签将为`label`键的值: + +``` +templating: + variables: + variable1: # The variable name that can be used in queries. + label: 'Variable 1' # (Optional) label that will appear in the UI for this text box. + type: text + options: + default_value: 'default' # (Optional) default value. +``` + +## `custom` variable type[](#custom-variable-type "Permalink") + +**警告:**此变量类型是*alpha*功能,如有更改,恕不另行通知! + +仪表板 YAML 中定义的每个`custom`变量都会在仪表板 UI 上创建一个下拉选择器,允许您为每个变量选择一个值. + +`custom`变量类型支持简单和完整的语法. + +### Simple syntax[](#simple-syntax-1 "Permalink") + +本示例创建一个名为`variable1` ,其默认值为`value1` . 仪表板界面将显示一个下拉列表,其中包含`value1` , `value2`和`value3`作为选择. + +``` +templating: + variables: + variable1: ['value1', 'value2', 'value3'] +``` + +### Full syntax[](#full-syntax-1 "Permalink") + +本示例创建一个名为`variable1` ,其默认值为`value_option_2` . UI 上文本框的标签将为`label`键的值. 仪表板界面将显示一个下拉列表,其中包含`Option 1`和`Option 2` . + +如果从下拉列表中选择`Option 1` ,则变量将被替换为`value option 1` . 同样,如果选择`Option 2` ,则变量将替换为`value_option_2` : + +``` +templating: + variables: + variable1: # The variable name that can be used in queries. + label: 'Variable 1' # (Optional) label that will appear in the UI for this dropdown. + type: custom + options: + values: + - value: 'value option 1' # The value that will replace the variable in queries. + text: 'Option 1' # (Optional) Text that will appear in the UI dropdown. + - value: 'value_option_2' + text: 'Option 2' + default: true # (Optional) This option should be the default value of this variable. +``` + +## `metric_label_values` variable type[](#metric_label_values-variable-type "Permalink") + +**警告:**此变量类型是*alpha*功能,如有更改,恕不另行通知! + +### Full syntax[](#full-syntax-2 "Permalink") + +本示例创建一个名为`variable2` . 下拉列表的值将是`up{env="production"}`描述的 Prometheus 系列中`backend`标签的所有不同值. + +``` +templating: + variables: + variable2: # The variable name that can be interpolated in queries. + label: 'Variable 2' # (Optional) label that will appear in the UI for this dropdown. + type: metric_label_values + options: + series_selector: 'up{env="production"}' + label: 'backend' +``` \ No newline at end of file diff --git a/docs/185.md b/docs/185.md new file mode 100644 index 0000000000000000000000000000000000000000..794c0445f98fbe1d89008d1410849bde93fb60f8 --- /dev/null +++ b/docs/185.md @@ -0,0 +1,31 @@ +# Prometheus Metrics library + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/) + +* [Exporters](#exporters) +* [Identifying Environments](#identifying-environments) + +# Prometheus Metrics library[](#prometheus-metrics-library "Permalink") + +在 GitLab 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8935) . + +GitLab 可自动检测某些[Prometheus 出口商](https://s0prometheus0io.icopy.site/docs/instrumenting/exporters/) . + +## Exporters[](#exporters "Permalink") + +当前支持的出口商是: + +* [Kubernetes](kubernetes.html) +* [NGINX](nginx.html) +* [NGINX Ingress Controller 0.9.0-0.15.x](nginx_ingress_vts.html) +* [NGINX Ingress Controller 0.16.0+](nginx_ingress.html) +* [HAProxy](haproxy.html) +* [Amazon Cloud Watch](cloudwatch.html) + +我们已尝试为每个出口商展示最重要的指标,并将在以后的版本中继续增加对其他出口商的支持. 如果您想增加对其他官方出口商的支持,欢迎捐款. + +## Identifying Environments[](#identifying-environments "Permalink") + +GitLab 从已配置的 Prometheus 服务器检索性能数据,并尝试识别已知指标的存在. 一旦确定,GitLab 然后需要能够将数据映射到特定环境. + +为了隔离并仅显示给定环境的相关指标,GitLab 需要一种方法来检测关联了哪些标签. 为此,GitLab 使用已定义的查询并填写特定于环境的变量. 通常,这涉及寻找[`$CI_ENVIRONMENT_SLUG`](../../../../ci/variables/README.html#predefined-environment-variables) ,但也可能包括其他信息,例如项目的 Kubernetes 命名空间. 每个搜索查询都在[导出器特定的文档中](#exporters)定义. \ No newline at end of file diff --git a/docs/186.md b/docs/186.md new file mode 100644 index 0000000000000000000000000000000000000000..b4e4bf99e20d85eb2d1a9efe4d86b786c786d30e --- /dev/null +++ b/docs/186.md @@ -0,0 +1,38 @@ +# Monitoring AWS Resources + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/cloudwatch.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/cloudwatch.html) + +* [Requirements](#requirements) +* [Metrics supported](#metrics-supported) +* [Configuring Prometheus to monitor for Cloudwatch metrics](#configuring-prometheus-to-monitor-for-cloudwatch-metrics) +* [Specifying the Environment label](#specifying-the-environment-label) + +# Monitoring AWS Resources[](#monitoring-aws-resources "Permalink") + +在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12621) + +GitLab 支持从[Elastic Load Balancer](https://aws.amazon.com/elasticloadbalancing/)开始自动检测和监视 AWS 资源. 这是通过利用官方[Cloudwatch 导出程序提供的](https://github.com/prometheus/cloudwatch_exporter) ,该程序将[Cloudwatch 指标](https://aws.amazon.com/cloudwatch/)转换为 Prometheus 可读形式. + +## Requirements[](#requirements "Permalink") + +必须启用[Prometheus 服务](../prometheus.html) . + +## Metrics supported[](#metrics-supported "Permalink") + +| Name | Query | +| --- | --- | +| 吞吐量(要求/秒) | `sum(aws_elb_request_count_sum{%{environment_filter}}) / 60` | +| 延迟(毫秒) | `avg(aws_elb_latency_average{%{environment_filter}}) * 1000` | +| HTTP 错误率(%) | `sum(aws_elb_httpcode_backend_5_xx_sum{%{environment_filter}}) / sum(aws_elb_request_count_sum{%{environment_filter}})` | + +## Configuring Prometheus to monitor for Cloudwatch metrics[](#configuring-prometheus-to-monitor-for-cloudwatch-metrics "Permalink") + +要开始使用 Cloudwatch 监控,您应该安装和配置[Cloudwatch 导出程序](https://github.com/prometheus/cloudwatch_exporter) ,该程序可检索和解析指定的 Cloudwatch 指标并将其转换为 Prometheus 监控端点. + +目前,唯一受支持的 AWS 资源是 Elastic Load Balancer,其 Cloudwatch 指标在[此处记录](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-cloudwatch-metrics.html) . + +样品的 CloudWatch 导出配置文件,配置用于基本 AWS ELB 监测,是[可供下载](../samples/cloudwatch.yml) . + +## Specifying the Environment label[](#specifying-the-environment-label "Permalink") + +为了隔离并仅显示给定环境的相关指标,GitLab 需要一种方法来检测关联了哪些标签. 为此,GitLab 将[查找`environment`标签](index.html#identifying-environments) . \ No newline at end of file diff --git a/docs/187.md b/docs/187.md new file mode 100644 index 0000000000000000000000000000000000000000..9427da48d5e8744eddaeb1091b46399b4e7a6b89 --- /dev/null +++ b/docs/187.md @@ -0,0 +1,33 @@ +# Monitoring HAProxy + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/haproxy.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/haproxy.html) + +* [Requirements](#requirements) +* [Metrics supported](#metrics-supported) +* [Configuring Prometheus to monitor for HAProxy metrics](#configuring-prometheus-to-monitor-for-haproxy-metrics) +* [Specifying the Environment label](#specifying-the-environment-label) + +# Monitoring HAProxy[](#monitoring-haproxy "Permalink") + +在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12621) + +GitLab 支持自动检测和监视 HAProxy. 这是通过利用[HAProxy Exporter](https://github.com/prometheus/haproxy_exporter)来提供的,后者将 HAProxy 统计信息转换为 Prometheus 可读形式. + +## Requirements[](#requirements "Permalink") + +必须启用[Prometheus 服务](../prometheus.html) . + +## Metrics supported[](#metrics-supported "Permalink") + +| Name | Query | +| --- | --- | +| 吞吐量(要求/秒) | `sum(rate(haproxy_frontend_http_requests_total{%{environment_filter}}[2m])) by (code)` | +| HTTP 错误率(%) | `sum(rate(haproxy_frontend_http_requests_total{code="5xx",%{environment_filter}}[2m])) / sum(rate(haproxy_frontend_http_requests_total{%{environment_filter}}[2m]))` | + +## Configuring Prometheus to monitor for HAProxy metrics[](#configuring-prometheus-to-monitor-for-haproxy-metrics "Permalink") + +要开始使用 NGINX 监视,您应该安装并配置[HAProxy 导出程序](https://github.com/prometheus/haproxy_exporter) ,该程序可以解析这些统计信息并将其转换为 Prometheus 监视端点. + +## Specifying the Environment label[](#specifying-the-environment-label "Permalink") + +为了隔离并仅显示给定环境的相关指标,GitLab 需要一种方法来检测关联了哪些标签. 为此,GitLab 将[查找`environment`标签](index.html#identifying-environments) . \ No newline at end of file diff --git a/docs/188.md b/docs/188.md new file mode 100644 index 0000000000000000000000000000000000000000..5cfdd39487d7e51c41be7e1c2b13db3c1fafeb99 --- /dev/null +++ b/docs/188.md @@ -0,0 +1,69 @@ +# Monitoring Kubernetes + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/kubernetes.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/kubernetes.html) + +* [Requirements](#requirements) +* [Metrics supported](#metrics-supported) +* [Configuring Prometheus to monitor for Kubernetes metrics](#configuring-prometheus-to-monitor-for-kubernetes-metrics) +* [Specifying the Environment](#specifying-the-environment) +* [Displaying Canary metrics](#displaying-canary-metrics-premium) + * [Canary metrics supported](#canary-metrics-supported) + +# Monitoring Kubernetes[](#monitoring-kubernetes "Permalink") + +在 GitLab 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8935) . + +GitLab 支持自动检测和监视 Kubernetes 指标. + +## Requirements[](#requirements "Permalink") + +必须启用[Prometheus](../prometheus.html)和[Kubernetes](../kubernetes.html)集成服务. + +## Metrics supported[](#metrics-supported "Permalink") + +* 平均内存使用量(MB): + + ``` + avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024 + ``` + +* 平均 CPU 使用率(%): + + ``` + avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job) / count(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}[15m])) by (pod_name)) + ``` + +## Configuring Prometheus to monitor for Kubernetes metrics[](#configuring-prometheus-to-monitor-for-kubernetes-metrics "Permalink") + +为了收集 Kubernetes 指标,需要将 Prometheus 部署到集群中并进行正确配置. GitLab 支持两种方法: + +* GitLab [与 Kubernetes 集成](../../clusters/index.html) ,并且可以[将 Prometheus 部署到连接的集群中](../prometheus.html#managed-prometheus-on-kubernetes) . 它被自动配置为收集 Kubernetes 指标. +* 要配置自己的 Prometheus 服务器,可以遵循[Prometheus 文档](https://s0prometheus0io.icopy.site/docs/introduction/overview/) . + +## Specifying the Environment[](#specifying-the-environment "Permalink") + +为了隔离并仅显示给定环境的相关 CPU 和内存指标,GitLab 需要一种方法来检测其正在运行的容器. 由于这些指标是在容器级别跟踪的,因此传统的 Kubernetes 标签不可用. + +相反, [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)或[DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/)名称应以[CI_ENVIRONMENT_SLUG 开头](../../../../ci/variables/README.html#predefined-environment-variables) . 如果需要,可以在其后跟一个`-`和其他内容. 例如, `review-homepage-5620p5`的部署名称将与`review/homepage`环境匹配. + +## Displaying Canary metrics[](#displaying-canary-metrics-premium "Permalink") + +在[GitLab 10.2 中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15201)引入. + +GitLab 还收集了针对[Canary 部署的](../../canary_deployments.html) Kubernetes 指标,从而可以轻松比较当前部署的版本和 Canary. + +这些度量标准期望[Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)或[DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/)名称以`$CI_ENVIRONMENT_SLUG-canary`开头,以隔离 canary 度量标准. + +### Canary metrics supported[](#canary-metrics-supported "Permalink") + +* 平均内存使用量(MB) + + ``` + avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024 + ``` + +* 平均 CPU 使用率(%) + + ``` + avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job) / count(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}[15m])) by (pod_name)) + ``` \ No newline at end of file diff --git a/docs/189.md b/docs/189.md new file mode 100644 index 0000000000000000000000000000000000000000..b79baafb0a4df2c97bb2a2fcb2e3d86a386b2121 --- /dev/null +++ b/docs/189.md @@ -0,0 +1,39 @@ +# Monitoring NGINX + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx.html) + +* [Requirements](#requirements) +* [Metrics supported](#metrics-supported) +* [Configuring Prometheus to monitor for NGINX metrics](#configuring-prometheus-to-monitor-for-nginx-metrics) +* [Specifying the Environment label](#specifying-the-environment-label) + +# Monitoring NGINX[](#monitoring-nginx "Permalink") + +在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12621) + +GitLab 支持自动检测和监视 NGINX. 这是通过利用[NGINX VTS 导出器提供的](https://github.com/hnlq715/nginx-vts-exporter) ,该[导出](https://github.com/hnlq715/nginx-vts-exporter)器将[VTS 统计信息](https://github.com/vozlt/nginx-module-vts)转换为 Prometheus 可读形式. + +## Requirements[](#requirements "Permalink") + +必须启用[Prometheus 服务](../prometheus.html) . + +## Metrics supported[](#metrics-supported "Permalink") + +检测到 NGINX 服务器指标,该指标跟踪 NGINX 直接提供的页面和内容. + +| Name | Query | +| --- | --- | +| 吞吐量(要求/秒) | `sum(rate(nginx_server_requests{server_zone!="*", server_zone!="_", %{environment_filter}}[2m])) by (code)` | +| 延迟(毫秒) | `avg(nginx_server_requestMsec{%{environment_filter}})` | +| HTTP 错误率(HTTP 错误/秒) | `sum(rate(nginx_server_requests{code="5xx", %{environment_filter}}[2m]))` | +| HTTP 错误(%) | `sum(rate(nginx_server_requests{code=~"5.*", host="*", %{environment_filter}}[2m])) / sum(rate(nginx_server_requests{code="total", host="*", %{environment_filter}}[2m])) * 100` | + +## Configuring Prometheus to monitor for NGINX metrics[](#configuring-prometheus-to-monitor-for-nginx-metrics "Permalink") + +要开始使用 NGINX 监视,您应该首先为 NGINX 服务器启用[VTS 统计](https://github.com/vozlt/nginx-module-vts)模块. 这将捕获并以 HTML 可读形式显示统计信息. 接下来,您应该安装并配置[NGINX VTS 导出器](https://github.com/hnlq715/nginx-vts-exporter) ,该[导出器](https://github.com/hnlq715/nginx-vts-exporter)将解析这些统计信息并将其转换为 Prometheus 监视端点. + +如果您将 NGINX 用作 Kubernetes 入口,GitLab 将在 0.9.0 及更高版本中启用后[自动检测](nginx_ingress.html)指标. + +## Specifying the Environment label[](#specifying-the-environment-label "Permalink") + +为了隔离并仅显示给定环境的相关指标,GitLab 需要一种方法来检测关联了哪些标签. 为此,GitLab 将[查找`environment`标签](index.html#identifying-environments) . \ No newline at end of file diff --git a/docs/190.md b/docs/190.md new file mode 100644 index 0000000000000000000000000000000000000000..9a8391d0e5fe4608652337ab41412ee1a93d3b15 --- /dev/null +++ b/docs/190.md @@ -0,0 +1,69 @@ +# Monitoring NGINX Ingress Controller + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx_ingress.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx_ingress.html) + +* [Requirements](#requirements) +* [Metrics supported](#metrics-supported) +* [Configuring NGINX Ingress monitoring](#configuring-nginx-ingress-monitoring) + * [About managed NGINX Ingress deployments](#about-managed-nginx-ingress-deployments) + * [Manually setting up NGINX Ingress for Prometheus monitoring](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) +* [Specifying the Environment label](#specifying-the-environment-label) + +# Monitoring NGINX Ingress Controller[](#monitoring-nginx-ingress-controller "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22133) . + +**注意:** 0.16.0 之前的 NGINX Ingress 版本提供了一个随附的[VTS Prometheus 指标导出器](nginx_ingress_vts.html) ,该导出器导出的指标与内置指标不同. + +GitLab 支持自动检测和监视 Kubernetes NGINX Ingress 控制器. 这是通过利用 Kubernetes NGINX Ingress 控制器[版本 0.16.0](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#0160)及更高[版本随附](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#0160)的内置 Prometheus 指标来提供的. + +## Requirements[](#requirements "Permalink") + +[Prometheus integration](../prometheus.html) must be active. + +## Metrics supported[](#metrics-supported "Permalink") + +| Name | Query | +| --- | --- | +| 吞吐量(要求/秒) | `sum(label_replace(rate(nginx_ingress_controller_requests{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m]), "status_code", "${1}xx", "status", "(.)..")) by (status_code)` | +| 延迟(毫秒) | `sum(rate(nginx_ingress_controller_ingress_upstream_latency_seconds_sum{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) / sum(rate(nginx_ingress_controller_ingress_upstream_latency_seconds_count{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) * 1000` | +| HTTP 错误率(%) | `sum(rate(nginx_ingress_controller_requests{status=~"5.*",namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) / sum(rate(nginx_ingress_controller_requests{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) * 100` | + +## Configuring NGINX Ingress monitoring[](#configuring-nginx-ingress-monitoring "Permalink") + +如果您已经使用 GitLab 的[Kubernetes 集群集成](../../clusters/index.html#installing-applications)部署了 NGINX Ingress,则 Prometheus 将[自动对其进行监视](#about-managed-nginx-ingress-deployments) . + +对于其他部署,需要根据您的安装进行[一些配置](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) : + +* NGINX Ingress 的版本应为 0.16.0 或更高,并启用指标. +* NGINX Ingress 应该标注为 Prometheus 监视. +* Prometheus 应该配置为监视带注释的容器. + +### About managed NGINX Ingress deployments[](#about-managed-nginx-ingress-deployments "Permalink") + +使用[官方 Helm 图表将](https://github.com/helm/charts/tree/master/stable/nginx-ingress) NGINX Ingress 部署到`gitlab-managed-apps`命名空间中. NGINX Ingress 将[通过 Load Balancer 的 Endpoint](../../../clusters/applications.html#ingress)在[外部访问](../../../clusters/applications.html#ingress) . + +通过设置以下内容,将 NGINX 配置为进行 Prometheus 监视: + +* `enable-vts-status: "true"` ,以导出 Prometheus 指标. +* `prometheus.io/scrape: "true"` ,以启用自动发现. +* `prometheus.io/port: "10254"` ,以指定度量标准端口. + +与 GitLab 部署的 Prometheus 服务结合使用时,将自动收集响应指标. + +### Manually setting up NGINX Ingress for Prometheus monitoring[](#manually-setting-up-nginx-ingress-for-prometheus-monitoring "Permalink") + +[NGINX Ingress 的](https://github.com/kubernetes/ingress-nginx) 0.9.0 及更高版本具有对导出 Prometheus 指标的内置支持. 要启用,必须传递 ConfigMap 设置: `enable-vts-status: "true"` . 启用后,Prometheus 指标端点将开始在端口 10254 上运行. + +接下来,需要对 Ingress 进行注释,以进行 Prometheus 监视. 需要添加两个新的注释: + +* `prometheus.io/scrape: "true"` +* `prometheus.io/port: "10254"` + +管理这些设置取决于如何部署 NGINX Ingress. 如果您通过[官方 Helm 图表](https://github.com/helm/charts/tree/master/stable/nginx-ingress)进行了部署,则可以使用`controller.stats.enabled`以及所需的注释来启用指标. 另外,也可以直接在[Kubernetes 仪表板中](https://github.com/kubernetes/dashboard)编辑 NGINX Ingress YML. + +## Specifying the Environment label[](#specifying-the-environment-label "Permalink") + +为了隔离并仅显示给定环境的相关指标,GitLab 需要一种方法来检测关联了哪些标签. 为此,GitLab 将搜索带有适当标签的指标. 在这种情况下, `ingress`标签必须为`<CI_ENVIRONMENT_SLUG>` . + +如果您使用[自动部署](../../../../topics/autodevops/stages.html#auto-deploy)来部署您的应用程序,则将自动使用此格式,并且无需您执行任何操作即可检测到指标. \ No newline at end of file diff --git a/docs/191.md b/docs/191.md new file mode 100644 index 0000000000000000000000000000000000000000..8b58916146bcc045dc767c60aca28edb448642b7 --- /dev/null +++ b/docs/191.md @@ -0,0 +1,69 @@ +# Monitoring NGINX Ingress Controller with VTS metrics + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx_ingress_vts.html](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx_ingress_vts.html) + +* [Requirements](#requirements) +* [Metrics supported](#metrics-supported) +* [Configuring NGINX Ingress monitoring](#configuring-nginx-ingress-monitoring) + * [About managed NGINX Ingress deployments](#about-managed-nginx-ingress-deployments) + * [Manually setting up NGINX Ingress for Prometheus monitoring](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) +* [Specifying the Environment label](#specifying-the-environment-label) + +# Monitoring NGINX Ingress Controller with VTS metrics[](#monitoring-nginx-ingress-controller-with-vts-metrics "Permalink") + +在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13438) . + +**注意:** [NGINX Ingress 版本 0.16](nginx_ingress.html)及更高[版本](nginx_ingress.html)具有内置的 Prometheus 度量标准,该度量标准与基于 VTS 的度量标准不同. + +GitLab 支持自动检测和监视 Kubernetes NGINX Ingress 控制器. 这是通过利用[版本 0.9.0](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#09-beta1)至[0.15.x 中](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#0150)随附的 VTS Prometheus 度量标准导出程序来[提供的](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#0150) . + +## Requirements[](#requirements "Permalink") + +[Prometheus 集成](../prometheus.html)必须处于活动状态. + +## Metrics supported[](#metrics-supported "Permalink") + +| Name | Query | +| --- | --- | +| 吞吐量(要求/秒) | `sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) by (status_code)` | +| 延迟(毫秒) | `avg(nginx_upstream_response_msecs_avg{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"})` | +| HTTP 错误率(%) | `sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) / sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) * 100` | + +## Configuring NGINX Ingress monitoring[](#configuring-nginx-ingress-monitoring "Permalink") + +如果您已经使用 GitLab 的[Kubernetes 集群集成](../../clusters/index.html#installing-applications)部署了 NGINX Ingress,则 Prometheus 将[自动对其进行监视](#about-managed-nginx-ingress-deployments) . + +对于其他部署,需要根据您的安装进行[一些配置](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) : + +* NGINX Ingress 的版本应为 0.9.0 或更高版本,并启用指标. +* NGINX Ingress 应该标注为 Prometheus 监视. +* Prometheus 应该配置为监视带注释的容器. + +### About managed NGINX Ingress deployments[](#about-managed-nginx-ingress-deployments "Permalink") + +NGINX Ingress is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress). NGINX Ingress will be [externally reachable via the Load Balancer’s Endpoint](../../../clusters/applications.html#ingress). + +通过设置以下内容,将 NGINX 配置为进行 Prometheus 监视: + +* `enable-vts-status: "true"` ,以导出 Prometheus 指标. +* `prometheus.io/scrape: "true"` ,以启用自动发现. +* `prometheus.io/port: "10254"` ,以指定度量标准端口. + +与 GitLab 部署的 Prometheus 服务结合使用时,将自动收集响应指标. + +### Manually setting up NGINX Ingress for Prometheus monitoring[](#manually-setting-up-nginx-ingress-for-prometheus-monitoring "Permalink") + +[NGINX Ingress 的](https://github.com/kubernetes/ingress-nginx) 0.9.0 及更高版本具有对导出 Prometheus 指标的内置支持. 要启用,必须传递 ConfigMap 设置: `enable-vts-status: "true"` . 启用后,Prometheus 指标端点将开始在端口 10254 上运行. + +接下来,需要对 Ingress 进行注释,以进行 Prometheus 监视. 需要添加两个新的注释: + +* `prometheus.io/scrape: "true"` +* `prometheus.io/port: "10254"` + +管理这些设置取决于如何部署 NGINX Ingress. 如果您通过[官方 Helm 图表](https://github.com/helm/charts/tree/master/stable/nginx-ingress)进行了部署,则可以使用`controller.stats.enabled`以及所需的注释来启用指标. 或者,也可以直接在[Kubernetes 仪表板中](https://github.com/kubernetes/dashboard)编辑 NGINX Ingress YAML. + +## Specifying the Environment label[](#specifying-the-environment-label "Permalink") + +为了隔离并仅显示给定环境的相关指标,GitLab 需要一种方法来检测关联了哪些标签. 为此,GitLab 将搜索带有适当标签的指标. 在这种情况下, `upstream`标签的格式必须为`<KUBE_NAMESPACE>-<CI_ENVIRONMENT_SLUG>-*` . + +如果您使用[自动部署](../../../../topics/autodevops/stages.html#auto-deploy)来部署您的应用程序,则将自动使用此格式,并且无需您执行任何操作即可检测到指标. \ No newline at end of file diff --git a/docs/192.md b/docs/192.md new file mode 100644 index 0000000000000000000000000000000000000000..57d5d45c9f055a3a52fd4402abef4f38dd48ee25 --- /dev/null +++ b/docs/192.md @@ -0,0 +1,210 @@ +# Alert Management + +> 原文:[https://docs.gitlab.com/ee/user/project/operations/alert_management.html](https://docs.gitlab.com/ee/user/project/operations/alert_management.html) + +* [Enable Alert Management](#enable-alert-management) + * [Enable a Generic Alerts endpoint](#enable-a-generic-alerts-endpoint) + * [Enable GitLab-managed Prometheus alerts](#enable-gitlab-managed-prometheus-alerts) + * [Enable external Prometheus alerts](#enable-external-prometheus-alerts) +* [Alert Management severity](#alert-management-severity) +* [Alert Management list](#alert-management-list) + * [Alert Management list sorting](#alert-management-list-sorting) + * [Searching alerts](#searching-alerts) + * [Alert Management statuses](#alert-management-statuses) +* [Alert Management details](#alert-management-details) + * [Update an Alert’s status](#update-an-alerts-status) + * [Create an Issue from an Alert](#create-an-issue-from-an-alert) + * [Update an Alert’s assignee](#update-an-alerts-assignee) + * [Alert system notes](#alert-system-notes) + * [View an Alert’s metrics data](#view-an-alerts-metrics-data) +* [Use cases for assigning alerts](#use-cases-for-assigning-alerts) + * [Slack Notifications](#slack-notifications) + +# Alert Management[](#alert-management "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2877) . + +警报管理使开发人员可以轻松发现和查看其应用程序生成的警报. 通过在开发代码的地方显示警报信息,可以提高效率和知名度. + +## Enable Alert Management[](#enable-alert-management "Permalink") + +**注意:**您至少需要维护者[权限](../../permissions.html)才能启用警报管理功能. + +如下所述,有几种方法可以将警报接受到您的 GitLab 项目中. 启用任何这些方法将允许显示警报列表. 配置警报后,访问 您可以在项目的边栏中[查看](#alert-management-list) **操作>警报** ,以[查看](#alert-management-list)警报[列表](#alert-management-list) . + +### Enable a Generic Alerts endpoint[](#enable-a-generic-alerts-endpoint "Permalink") + +GitLab 提供了通用警报端点,因此您可以接受来自第三方警报服务的警报. 请参阅有关[切换常规警报](../integrations/generic_alerts.html#setting-up-generic-alerts)的[说明](../integrations/generic_alerts.html#setting-up-generic-alerts)以添加此选项. 配置端点后,将启用" [警报"列表](#alert-management-list) . + +要用数据填充警报,请参阅为警报端点的请求[自定义有效负载](../integrations/generic_alerts.html#customizing-the-payload) . + +### Enable GitLab-managed Prometheus alerts[](#enable-gitlab-managed-prometheus-alerts "Permalink") + +您可以在 Kubernetes 集群上安装 GitLab 管理的 Prometheus 应用程序. 有关更多信息,请参见[Kubernetes 上的 Managed Prometheus](../integrations/prometheus.html#managed-prometheus-on-kubernetes) . 安装了由 GitLab 管理的 Prometheus 时,也会启用[警报列表](#alert-management-list) . + +要用数据填充警报,请参阅[GitLab 管理的 Prometheus 实例](../../../operations/metrics/index.html#managed-prometheus-instances) . + +### Enable external Prometheus alerts[](#enable-external-prometheus-alerts "Permalink") + +您可以配置外部管理的 Prometheus 实例,以将警报发送到 GitLab. 要设置此配置,请参阅[配置 Prometheus](../../../operations/metrics/index.html#external-prometheus-instances)文档. 激活外部 Prometheus 配置也会启用" [警报"列表](#alert-management-list) . + +要用数据填充警报,请参阅[外部 Prometheus 实例](../../../operations/metrics/index.html#external-prometheus-instances) . + +## Alert Management severity[](#alert-management-severity "Permalink") + +警报的每个级别均包含一个形状和颜色编码独特的图标,以帮助您确定特定警报的严重性. 这些严重性图标可帮助您立即确定应优先调查的警报: + +[![Alert Management Severity System](img/56eeecad0f9627fae21bc6b196391ba7.png)](img/alert_management_severity_v13_0.png) + +警报包含以下图标之一: + +| Severity | Icon | 颜色(十六进制) | +| --- | --- | --- | +| Critical | | `#8b2615` | +| High | | `#c0341d` | +| Medium | | `#fca429` | +| Low | | `#fdbc60` | +| Info | | `#418cd8` | +| Unknown | | `#bababa` | + +## Alert Management list[](#alert-management-list "Permalink") + +**注意:**您将至少需要具有开发人员[权限](../../permissions.html)才能查看警报管理列表. + +您可以在以下位置找到警报管理列表 项目侧边栏中的**操作>警报** . 每个警报包含以下指标: + +[![Alert Management List](img/c932281f198053757ebfaf5a9b99b335.png)](img/alert_list_v13_1.png) + +* **严重性** -警报的当前重要性及其应受到的关注. +* **开始时间** -警报触发前多久. 此字段使用`X time ago`的标准 GitLab 模式,但细化的日期/时间工具提示支持此字段,具体取决于用户的语言环境. +* **警报说明** - The description of the alert, which attempts to capture the most meaningful data. +* **事件计数** -警报触发的次数. +* **问题** -指向为警报创建的事件问题的链接. +* **状态** -警报的[当前状态](#alert-management-statuses) . + +### Alert Management list sorting[](#alert-management-list-sorting "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/217745) . + +警报管理列表显示按开始时间排序的警报,但是您可以通过单击警报管理列表中的标题来更改排序顺序. + +要查看列是否可排序,请将鼠标指向标题. 可排序的列在列名旁边显示一个箭头,如以下示例所示: + +[![Alert Management List Sorting](img/b46359f55df1f2affc4fe493965ebd0a.png)](img/alert_list_sort_v13_1.png) + +### Searching alerts[](#searching-alerts "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/213884) . + +警报列表支持简单的自由文本搜索. + +[![Alert List Search](img/cf0c5e15a3b44eb89d7513b961d6a274.png)](img/alert_list_search_v13_1.png) + +此搜索过滤以下字段: + +* Title +* Description +* 监控工具 +* Service + +### Alert Management statuses[](#alert-management-statuses "Permalink") + +每个警报都包含一个状态下拉列表,以指示需要调查的警报. 标准警报状态包括已`triggered` ,已`acknowledged`和已`resolved` : + +* **触发** :没有人开始调查. +* **致谢** :有人正在积极调查问题. +* **解决** :不需要进一步的工作. + +## Alert Management details[](#alert-management-details "Permalink") + +**注意:**您至少需要具有开发人员[权限](../../permissions.html)才能查看警报管理详细信息. + +通过访问[警报管理列表](#alert-management-list)并从列表中选择一个警报,导航到警报管理详细信息视图. + +[![Alert Management Detail Overview](img/fd15df8f9a5a46582845610e8b5881bb.png)](img/alert_detail_overview_v13_1.png) + +[![Alert Management Full Details](img/393dab24a6c8be1031a4cf469f3039e9.png)](img/alert_detail_full_v13_1.png) + +### Update an Alert’s status[](#update-an-alerts-status "Permalink") + +警报管理详细信息视图使您可以更新警报状态. 有关更多详细信息,请参见[警报管理状态](#alert-management-statuses) . + +### Create an Issue from an Alert[](#create-an-issue-from-an-alert "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/217745) . + +警报管理详细信息视图使您可以创建问题,并使用从警报自动填充的描述来创建问题. 要创建问题,请单击**创建问题**按钮. 然后,您可以通过单击**查看问题**按钮从警报中**查看问题** . + +关闭与警报相关的 GitLab 问题会将警报的状态更改为"已解决". 有关[状态](#alert-management-statuses)的更多详细信息,请参阅[警报管理](#alert-management-statuses)状态. + +### Update an Alert’s assignee[](#update-an-alerts-assignee "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/3066) . + +警报管理详细信息视图允许用户更新警报受让人. + +在大型团队中,共享警报的所有权,可能很难跟踪谁在调查和处理警报. 警报管理详细信息视图使您可以更新警报受让人: + +**注意:** manbetx 客户端打不开目前仅支持每个警报一个受让人. + +1. 要显示当前警报列表,请单击 **操作>警报** : + + [![Alert Management List View Assignee(s)](img/2ae8145aa44498bcadafa3451ee343b1.png)](img/alert_list_assignees_v13_1.png) + +2. 选择所需的警报以显示其**警报管理详细信息视图** : + + [![Alert Management Details View Assignee(s)](img/e80fdda43c295fbc39611b3d918d4b75.png)](img/alert_details_assignees_v13_1.png) + +3. 如果右侧栏没有展开,请单击 **展开侧边栏**以展开它. +4. 在右侧栏中,找到**受让人** ,然后点击**编辑** . 从下拉菜单中,选择要分配给警报的每个用户. GitLab 为每个用户创建一个[待办事项列表项](../../todos.html) . + + [![Alert Management Details View Assignee(s)](img/f7ae6b6be5d2dd02010825234555fee6.png)](img/alert_todo_assignees_v13_1.png) + +要删除受让人,请单击" **受让人"**下拉菜单旁边的" **编辑"** ,然后从**受让人**列表中取消选择该用户,或单击" **未分配"** . + +### Alert system notes[](#alert-system-notes "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/3066) . + +当您对警报采取措施时,它会记录为系统注释,在"警报详细信息"视图中可见. 这为您提供了警报调查和分配历史的线性时间表. + +以下操作将产生系统注释: + +* [Updating the status of an alert](#update-an-alerts-status) +* [Creating an issue based on an alert](#create-an-issue-from-an-alert) +* [Assignment of an alert to a user](#update-an-alerts-assignee) + +[![Alert Management Details View System Notes](img/b6f3d1302a444a29689905582d97eb84.png)](img/alert_detail_system_notes_v13_1.png) + +### View an Alert’s metrics data[](#view-an-alerts-metrics-data "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/217768) . + +要查看警报的指标,请执行以下操作: + +1. 以具有 Developer 或更高[权限](../../permissions.html)的用户身份登录. +2. 导航 **操作>警报** . +3. 单击您要查看的警报. +4. 在警报标题下,单击" **指标"**选项卡. + +[![Alert Management Metrics View](img/ca33b4a75b3a1bc207dd2eddae8c3949.png)](img/alert_detail_metrics_v13_2.png) + +For GitLab-managed Prometheus instances, metrics data is automatically available for the alert, making it easy to see surrounding behavior. See [Managed Prometheus instances](../../../operations/metrics/index.html#managed-prometheus-instances) for information on setting up alerts. + +对于外部管理的 Prometheus 实例,您可以配置警报规则以在警报中显示图表. 有关如何正确配置警报规则的信息,请参阅[基于警报在事件问题中嵌入指标](../../../operations/metrics/embed.html#embedding-metrics-based-on-alerts-in-incident-issues) . 有关为自己管理的 Prometheus 实例设置警报的信息,请参阅[外部](../../../operations/metrics/index.html#external-prometheus-instances) Prometheus 实例. + +## Use cases for assigning alerts[](#use-cases-for-assigning-alerts "Permalink") + +考虑一个由监视的不同部分组成的团队,在单个应用程序上进行协作. 警报浮出水面之后,将警报发送给可以处理和解决警报的团队成员非常重要. + +将警报分配给多个受让人可以简化协作和委派. 所有分配者都显示在团队的工作流程中,并且所有分配者都会收到通知,从而简化了警报的通信和所有权. + +完成调查或修复警报的部分后,用户可以在角色完成后从警报中取消分配帐户. 可以更新[警报状态](#alert-management-statuses)以反映警报是否已解决. + +### Slack Notifications[](#slack-notifications "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/216326) . + +当收到新的警报时,可以通过 Slack 消息向您发出警报. + +有关如何进行设置的信息,请参阅[Slack Notifications Service 文档](../integrations/slack.html) . \ No newline at end of file diff --git a/docs/193.md b/docs/193.md new file mode 100644 index 0000000000000000000000000000000000000000..6e8e1564fb4a831782c24e608d57d9e6b542c992 --- /dev/null +++ b/docs/193.md @@ -0,0 +1,98 @@ +# Error Tracking + +> 原文:[https://docs.gitlab.com/ee/user/project/operations/error_tracking.html](https://docs.gitlab.com/ee/user/project/operations/error_tracking.html) + +* [Sentry error tracking](#sentry-error-tracking) + * [Deploying Sentry](#deploying-sentry) + * [Enabling Sentry](#enabling-sentry) + * [Enabling GitLab issues links](#enabling-gitlab-issues-links) +* [Error Tracking List](#error-tracking-list) +* [Error Details](#error-details) +* [Taking Action on errors](#taking-action-on-errors) + * [Ignoring errors](#ignoring-errors) + * [Resolving errors](#resolving-errors) + +# Error Tracking[](#error-tracking "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/169) . + +错误跟踪使开发人员可以轻松发现和查看其应用程序可能产生的错误. 通过在开发代码的地方显示错误信息,可以提高效率和知名度. + +## Sentry error tracking[](#sentry-error-tracking "Permalink") + +[Sentry](https://sentry.io/)是一个开源错误跟踪系统. GitLab 允许管理员将 Sentry 连接到 GitLab,以允许用户查看 GitLab 中的 Sentry 错误列表. + +### Deploying Sentry[](#deploying-sentry "Permalink") + +您可以注册到托管在[https://sentry.io](https://sentry.io)上的云,部署自己[的本地实例](https://docs.sentry.io/server/installation/)或使用 GitLab [将 Sentry 安装到 Kubernetes 集群](../../clusters/applications.html#install-sentry-using-gitlab-cicd) . + +### Enabling Sentry[](#enabling-sentry "Permalink") + +**注意:**您至少需要维护者[权限](../../permissions.html)才能启用 Sentry 集成. + +GitLab 提供了一种将 Sentry 连接到您的项目的简便方法: + +1. 注册到 Sentry.io 或[部署您自己的](#deploying-sentry) Sentry 实例. +2. [创建](https://docs.sentry.io/guides/integrate-frontend/create-new-project/)一个新的 Sentry 项目. 对于您要集成的每个 GitLab 项目,我们建议您创建一个新的 Sentry 项目. +3. [查找或生成](https://docs.sentry.io/api/auth/)您的 Sentry 项目的 Sentry 身份验证令牌. 确保至少给令牌以下范围: `event:read`和`project:read` . +4. 导航到项目的**"设置">"操作"** . +5. 确保设置了**活动**复选框. +6. 在**Sentry API URL**字段中,输入您的 Sentry 主机名. 例如,如果这是您的 Sentry 实例可用的地址,请输入`https://sentry.example.com` . 对于 Sena 的 SaaS 版本,主机名将为`https://sentry.io` . +7. 在" **验证令牌"**字段中,输入您先前生成的令牌. +8. 单击" **连接"**按钮以测试与 Sentry 的连接并填充" **项目"**下拉列表. +9. 从**项目**下拉菜单中,选择一个 Sentry 项目以链接到您的 GitLab 项目. +10. 单击**保存更改**以使更改生效. +11. 现在,您可以在项目的侧栏中访问" **操作">"错误跟踪"** ,以[查看](#error-tracking-list) Sentry 错误[的列表](#error-tracking-list) . + +### Enabling GitLab issues links[](#enabling-gitlab-issues-links "Permalink") + +您可能还需要按照[Sentry 文档中](https://docs.sentry.io/workflow/integrations/global-integrations/#gitlab)的步骤来启用 Sentry 的 GitLab 集成. + +## Error Tracking List[](#error-tracking-list "Permalink") + +**注意:**您将至少需要 Reporter [权限](../../permissions.html)才能查看"错误跟踪"列表. + +您可以在项目的边栏中的" **操作">"错误跟踪"**中找到"错误跟踪"列表. 在这里,您可以按标题或状态("已忽略","已解决"或"未解决"之一)过滤错误,并按"频率","首次看到"或"最后看到"的降序排列. 默认情况下,错误列表按"上次发现"排序,并过滤为"未解决的错误". + +[![Error Tracking list](img/8375b8805ee35febb22389954e463cb3.png)](img/error_tracking_list_v12_6.png) + +## Error Details[](#error-details "Permalink") + +从错误列表中,用户可以通过单击任何错误的标题导航到错误详细信息页面. + +该页面具有: + +* 哨兵问题的链接. +* 如果 Sentry Issue 的第一个发行[版](https://docs.sentry.io/workflow/releases/?platform=javascript#configure-sdk)的 Sentry [版本 ID /版本](https://docs.sentry.io/workflow/releases/?platform=javascript#configure-sdk)与您的 GitLab 托管项目中的提交 SHA 匹配,则指向 GitLab 提交的链接. +* 有关该问题的其他详细信息,包括完整的堆栈跟踪. +* 在[GitLab 12.7 及更高版本中](https://gitlab.com/gitlab-org/gitlab/-/issues/36246) ,显示语言和紧急度. + +默认情况下,显示**创建问题**按钮: + +[![Error Details without Issue Link](img/8d66587fae4dab1dca05f85389caa499.png)](img/error_details_v12_7.png) + +如果您从错误中创建了一个 GitLab 问题,则" **创建问题"**按钮将变为" **查看问题"**按钮,并且指向 GitLab 问题的链接将出现在"错误详细信息"部分中: + +[![Error Details with Issue Link](img/2fed535a429569e1ae792fb3960bcdd5.png)](img/error_details_with_issue_v12_8.png) + +## Taking Action on errors[](#taking-action-on-errors "Permalink") + +您可以从 GitLab UI 中对哨兵错误采取措施. + +### Ignoring errors[](#ignoring-errors "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/39665) . + +在" [错误详细信息"](#error-details)页面中,只需单击页面顶部附近的" **忽略"**按钮,就可以忽略 Sentry 错误. + +忽略错误将阻止它出现在" [错误跟踪列表"中](#error-tracking-list) ,并将使 Sentry 中设置的通知静音. + +### Resolving errors[](#resolving-errors "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/39825) . + +在" [错误详细信息"](#error-details)页面中,您可以通过单击页面顶部附近的" **解决"**按钮来解决 Sentry 错误. + +将错误标记为已解决表示错误已停止触发事件. 如果 GitLab 问题与错误相关联,则该问题将被关闭. + +如果发生另一个事件,该错误将恢复为未解决. \ No newline at end of file diff --git a/docs/194.md b/docs/194.md new file mode 100644 index 0000000000000000000000000000000000000000..7f6bbcc571cb43117b7468ab42fc21bd1141d472 --- /dev/null +++ b/docs/194.md @@ -0,0 +1,32 @@ +# Tracing + +> 原文:[https://docs.gitlab.com/ee/operations/tracing.html](https://docs.gitlab.com/ee/operations/tracing.html) + +* [Jaeger tracing](#jaeger-tracing) + * [Deploying Jaeger](#deploying-jaeger) + * [Enabling Jaeger](#enabling-jaeger) + +# Tracing[](#tracing-ultimate "Permalink") + +在 GitLab Ultimate 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7903) . + +跟踪提供对已部署应用程序的性能和运行状况的洞察力,跟踪处理给定请求的每个功能或微服务. + +不管您使用的是整体系统还是分布式系统,这都可以轻松理解请求的端到端流程. + +## Jaeger tracing[](#jaeger-tracing "Permalink") + +[Jaeger](https://www.jaegertracing.io/)是一个开源的,端到端的分布式跟踪系统,用于监视和调试基于微服务的分布式系统. + +### Deploying Jaeger[](#deploying-jaeger "Permalink") + +要了解有关部署 Jaeger 的更多信息,请阅读官方的《 [入门指南》文档](https://www.jaegertracing.io/docs/latest/getting-started/) . 有一个易于使用[的多合一 Docker 映像](https://www.jaegertracing.io/docs/latest/getting-started/#AllinoneDockerimage) ,以及[Kubernetes](https://github.com/jaegertracing/jaeger-kubernetes)和[OpenShift 的](https://github.com/jaegertracing/jaeger-openshift)部署选项. + +### Enabling Jaeger[](#enabling-jaeger "Permalink") + +GitLab 提供了一种从项目内部打开 Jaeger UI 的简便方法: + +1. 使用[客户端库](https://www.jaegertracing.io/docs/latest/client-libraries/)之一[设置 Jaeger](https://www.jaegertracing.io)并配置您的应用[程序](https://www.jaegertracing.io/docs/latest/client-libraries/) . +2. 导航到项目的**"设置">"操作",**然后提供 Jaeger URL. +3. 单击**保存更改**以使更改生效. +4. 现在,您可以在项目的侧边栏中访问" **操作">"跟踪"** ,GitLab 会将您重定向到已配置的 Jaeger URL. \ No newline at end of file diff --git a/docs/195.md b/docs/195.md new file mode 100644 index 0000000000000000000000000000000000000000..95186af8e98112f3dd34615150780c235c8974ab --- /dev/null +++ b/docs/195.md @@ -0,0 +1,104 @@ +# Incident Management + +> 原文:[https://docs.gitlab.com/ee/user/incident_management/](https://docs.gitlab.com/ee/user/incident_management/) + +* [Configure incidents](#configure-incidents-ultimate) + * [Notify developers of alerts](#notify-developers-of-alerts) +* [Configure PagerDuty integration](#configure-pagerduty-integration) +* [Configure Prometheus alerts](#configure-prometheus-alerts) +* [Configure external generic alerts](#configure-external-generic-alerts) +* [Embed metrics in incidents and issues](#embed-metrics-in-incidents-and-issues) + * [Context menu](#context-menu) + * [View logs from metrics panel](#view-logs-from-metrics-panel) +* [Integrate incidents with Slack](#integrate-incidents-with-slack) +* [Integrate issues with Zoom](#integrate-issues-with-zoom) + +# Incident Management[](#incident-management "Permalink") + +GitLab 提供了用于处理应用程序和服务中的事件的解决方案,例如设置 Prometheus 警报,显示指标和发送通知. + +## Configure incidents[](#configure-incidents-ultimate "Permalink") + +在 GitLab Ultimate 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4925) . + +您可以在 GitLab 用户界面中启用或禁用事件管理功能,以在触发警报时创建问题: + +1. 导航 **设置>操作>事件,**然后展开**事件** : + + [![Incident Management Settings](img/f652f5dac5bec0bb81edc08cbfd7a01b.png)](img/incident_management_settings.png) + +2. 对于 GitLab 11.11 及更高版本,您可以选中**创建问题**复选框以根据自己的[问题模板](../project/description_templates.html#creating-issue-templates)创建[问题](../project/description_templates.html#creating-issue-templates) . 有关更多信息,请参阅[从警报触发操作](../../operations/metrics/alerts.html#trigger-actions-from-alerts-ultimate) . +3. 要从警报中创建问题,请在" **问题模板"**选择框中选择**模板** . +4. 要向具有[开发者权限的](../permissions.html)用户发送[单独的电子邮件通知](#notify-developers-of-alerts) ,请选择" **向开发者发送单独的电子邮件通知"** . +5. Click **保存更改**. + +适当配置的警报包括与警报相对应的查询的[嵌入式图表](../../operations/metrics/embed.html#embedding-metrics-based-on-alerts-in-incident-issues) . 您还可以将 GitLab 配置为在收到警报已解决的通知时[关闭问题](../../operations/metrics/alerts.html#trigger-actions-from-alerts-ultimate) . + +### Notify developers of alerts[](#notify-developers-of-alerts "Permalink") + +GitLab 可以通过创建问题并通过电子邮件提醒开发人员来应对您的应用程序和服务触发的警报. 默认情况下,GitLab 将这些电子邮件发送给项目的[所有者和维护者](../permissions.html) . 这些电子邮件包含警报的详细信息以及更多信息的链接. + +要将单独的电子邮件通知发送给具有[开发者权限的](../permissions.html)用户,请参阅[配置事件](#configure-incidents-ultimate) . + +## Configure PagerDuty integration[](#configure-pagerduty-integration "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/119018) . + +您可以使用 PagerDuty 设置一个 Webhook,以便为每个 PagerDuty 事件自动创建一个 GitLab 问题. 此配置要求您同时更改 PagerDuty 和 GitLab: + +1. 以具有维护者[权限](../permissions.html)的用户身份登录. +2. 导航 **设置>操作>事件,**然后展开**事件** . +3. 选择**PagerDuty 集成**选项卡: + + [![PagerDuty incidents integration](img/370ac43323901b08b905644b04f6a802.png)](img/pagerduty_incidents_integration_13_2.png) + +4. 激活集成,并将更改保存在 GitLab 中. +5. 复制**Webhook URL**的值, **以**供以后使用. +6. 按照[PagerDuty 文档中](https://support.pagerduty.com/docs/webhooks)描述的步骤,将[Webhook](https://support.pagerduty.com/docs/webhooks) URL 添加到 PagerDuty Webhook 集成中. + +为了确认集成成功,从 PagerDuty 触发一个测试事件以确认是否从该事件中创建了一个 GitLab 问题. + +## Configure Prometheus alerts[](#configure-prometheus-alerts "Permalink") + +您可以在以下位置设置 Prometheus 警报: + +* [GitLab-managed Prometheus](../../operations/metrics/alerts.html) installations. +* [Self-managed Prometheus](../../operations/metrics/alerts.html#external-prometheus-instances) installations. + +Prometheus 警报由特殊的警报机器人用户创建. 您无法删除此用户,但不计入您的许可限制. + +## Configure external generic alerts[](#configure-external-generic-alerts "Permalink") + +GitLab 可以通过通用的 Webhook 接收器接受来自任何来源的警报. 在[配置通用警报集成时](../project/integrations/generic_alerts.html) ,GitLab 会创建一个唯一的端点,该端点接收 JSON 格式的可自定义负载. + +## Embed metrics in incidents and issues[](#embed-metrics-in-incidents-and-issues "Permalink") + +您可以在使用[GitLab Markdown 的](../markdown.html)任何地方嵌入指标,例如描述,问题评论和合并请求. 嵌入指标可帮助您在讨论事件或性能问题时共享它们. 通过[将链接复制并粘贴到指标仪表盘](../../operations/metrics/embed.html#embedding-gitlab-managed-kubernetes-metrics) ,您可以将仪表盘直接输出到 GitLab 中的任何问题,合并请求,史诗或其他 Markdown 文本字段中. + +您可以将[GitLab 托管的指标](../../operations/metrics/embed.html)和[Grafana 指标](../../operations/metrics/embed_grafana.html)都嵌入事件和问题模板中. + +### Context menu[](#context-menu "Permalink") + +您可以从上下文菜单中查看有关嵌入式指标面板的更多详细信息. 要访问上下文菜单,请单击 面板右上角上方的**更多操作**下拉框. 选项包括: + +* [View logs](#view-logs-from-metrics-panel). +* **下载 CSV-**嵌入式图表中的数据可以[CSV 格式下载](../../operations/metrics/dashboards/index.html#downloading-data-as-csv) . + +#### View logs from metrics panel[](#view-logs-from-metrics-panel "Permalink") + +版本历史 + +* 在 GitLab Ultimate 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/201846) . +* [移至](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25455) [GitLab Core](https://about.gitlab.com/pricing/) 12.9\. + +如果您要对应用程序事件进行分类并需要[浏览](../../operations/metrics/dashboards/index.html#view-logs-ultimate)整个应用程序中的日志,则从指标面板查看日志可能会很有用. 这些日志可帮助您了解影响应用程序性能的因素并解决所有问题. + +## Integrate incidents with Slack[](#integrate-incidents-with-slack "Permalink") + +使用 Slack 斜杠命令,您可以控制 GitLab 并查看 GitLab 内容,而无需离开 Slack. + +了解如何[设置 Slack 斜杠命令](../project/integrations/slack_slash_commands.html)以及如何[使用可用的斜杠命令](../../integration/slash_commands.html) . + +## Integrate issues with Zoom[](#integrate-issues-with-zoom "Permalink") + +通过 GitLab,您可以[将 Zoom 会议与](../project/issues/associate_zoom_meeting.html)事件[相关联,](../project/issues/associate_zoom_meeting.html)以便在事件管理期间进行同步通信. 在启动事件的 Zoom 呼叫后,您可以将电话会议与问题关联. 您的团队成员无需请求链接即可加入 Zoom 通话. \ No newline at end of file diff --git a/docs/196.md b/docs/196.md new file mode 100644 index 0000000000000000000000000000000000000000..2514473ab26b69da613234f6947ab927d00a91b1 --- /dev/null +++ b/docs/196.md @@ -0,0 +1,125 @@ +# GitLab Status Page + +> 原文:[https://docs.gitlab.com/ee/user/project/status_page/](https://docs.gitlab.com/ee/user/project/status_page/) + +* [How to set up](#how-to-set-up) + * [Cloud account set up](#cloud-account-set-up) + * [AWS Setup](#aws-setup) + * [Status Page project](#status-page-project) + * [Syncing incidents to the Status Page](#syncing-incidents-to-the-status-page) +* [Status Page UI](#status-page-ui) + * [Incident detail page](#incident-detail-page) +* [How it works](#how-it-works) + * [Publishing Incidents](#publishing-incidents) + * [Publishing updates](#publishing-updates) + * [Adding comments](#adding-comments) + * [Changing the Incident status](#changing-the-incident-status) +* [Attachment storage](#attachment-storage) + * [Limit](#limit) + +# GitLab Status Page[](#gitlab-status-page-ultimate "Permalink") + +[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2479) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. + +通过 GitLab 状态页面,您可以创建和部署静态网站,以便在事件发生时与用户进行有效沟通. + +## How to set up[](#how-to-set-up "Permalink") + +**注意:**仅支持将 AWS S3 作为部署目标.图 TB 子图 GitLab 实例问题(问题更新)-触发器->中间件(背景工作:JSON 生成)结束子图 Cloud Provider 中间件-保存数据-> c1(云桶存储 JSON 文件)结束子图状态页 d( CDN 上的静态站点)-获取数据-> C1 端 + +设置状态页面非常简单,但是您需要做一些事情. + +### Cloud account set up[](#cloud-account-set-up "Permalink") + +要使用 GitLab 状态页,您首先需要在操作设置页中为您的云提供商设置帐户详细信息. 今天,仅支持 AWS. + +#### AWS Setup[](#aws-setup "Permalink") + +1. 在您的 AWS acccout 中,创建两个新的 IAM 策略. + * [创建存储桶](https://gitlab.com/gitlab-org/status-page/-/blob/master/deploy/etc/s3_create_policy.json) . + * [更新存储桶内容](https://gitlab.com/gitlab-org/status-page/-/blob/master/deploy/etc/s3_update_bucket_policy.json) (请记住用您的存储桶名称替换`S3_BUCKET_NAME` ). +2. 使用第一步中创建的权限策略创建一个新的 AWS 访问密钥. + +### Status Page project[](#status-page-project "Permalink") + +要将状态页面部署到 AWS S3,您需要添加状态页面项目并配置必要的 CI 变量. + +1. 分叉[状态页](https://gitlab.com/gitlab-org/status-page)项目. 这也可以通过" [存储库镜像"](https://gitlab.com/gitlab-org/status-page#repository-mirroring)来完成,这将确保您获得最新的"状态页"功能. +2. 在**设置> CI / CD>变量中**添加以下**变量** . (要从 Amazon 获取这些变量,请使用您的 Amazon Console): + * `S3_BUCKET_NAME` -Amazon S3 存储桶的名称(如果不存在具有提供名称的存储桶,则第一个管道运行将创建一个并为[静态网站托管](https://docs.aws.amazon.com/AmazonS3/latest/dev/HostingWebsiteOnS3Setup.html)配置它) + * `AWS_DEFAULT_REGION` -AWS 区域 + * `AWS_ACCESS_KEY_ID` -AWS 访问密钥 ID + * `AWS_SECRET_ACCESS_KEY` -AWS 秘密 +3. 运行管道以将状态页部署到 S3. + +### Syncing incidents to the Status Page[](#syncing-incidents-to-the-status-page "Permalink") + +设置 CI / CD 变量后,您需要设置要用于事件问题的项目: + +1. 要查看" [操作设置"](../settings/#operations-settings)页面,请导航至 **设置>操作>状态页面** . +2. 填写您的云提供商的凭据,并确保已选中" **活动"**复选框. +3. Click **保存更改**. + +## Status Page UI[](#status-page-ui "Permalink") + +"状态页面"登录页面显示了最近事件的概述. 单击事件将带您到事件的详细信息页面. + +[![Status Page landing page](img/d4a6279fcd73fa0a1dc68761261f4854.png)](../img/status_page_incidents_v12_10.png) + +### Incident detail page[](#incident-detail-page "Permalink") + +事件详细信息页面显示有关特定事件的详细信息. 例如: + +* 事件的状态,包括事件的最新更新时间. +* 事件标题,包括所有表情符号. +* 事件描述,包括表情符号. +* 事件描述或注释中提供的带有有效图像扩展名的任何文件附件. 在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/205166) . +* 按时间顺序排列的事件更新列表. + +[![Status Page detail](img/8f8d204a16e9c896b01a62220529b921.png)](../img/status_page_detail_v12_10.png) + +## How it works[](#how-it-works "Permalink") + +### Publishing Incidents[](#publishing-incidents "Permalink") + +要发布事件,您首先需要在启用状态页设置的项目中创建一个问题. + +默认情况下,问题不会发布到状态页面. 在问题中使用`/publish` [快速操作](../quick_actions.html)来发布问题. 仅[项目或小组所有者](../../permissions.html)可以发布问题. + +使用快速操作后,后台工作人员将使用在安装过程中提供的凭据将问题发布到"状态页"上. + +由于所有事件都是公开发布的,因此用户和组提及将由`Incident Responder`匿名,并且非公共[GitLab 参考的](../../markdown.html#special-gitlab-references)标题也将被删除. + +When an Incident is published in the GitLab project, you can access the details page of the Incident by clicking the **在状态页上发布** button displayed under the Incident’s title. + +[![Status Page detail link](img/3c9cb466046f19c70255f0de753a307c.png)](../img/status_page_detail_link_v13_1.png) + +**注意:**机密性问题无法发布. 如果您将已发布的问题设为机密,则它将不会发布. + +### Publishing updates[](#publishing-updates "Permalink") + +要发布事件更新,请更新事件问题的描述. + +**小心:**更改引用的问题(例如标题,机密性)时,引用的事件不会自动更新. + +### Adding comments[](#adding-comments "Permalink") + +要将评论添加到状态页事件中,请对事件问题创建评论. + +准备发布评论时,请在评论中添加麦克风[奖表情符号](../../../user/award_emojis.html)反应( `:microphone` ). 这会将注释标记为应部署到状态页的注释. + +**警告:**有权查看问题的任何人都可以在评论中添加表情符号奖,因此您可能希望将问题仅限于团队成员. + +### Changing the Incident status[](#changing-the-incident-status "Permalink") + +要将事件状态从`open`更改为`closed` ,请在 GitLab 中关闭事件问题. 然后将在状态页面网站上对此进行更新. + +## Attachment storage[](#attachment-storage "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/205166) . + +从 GitLab 13.1 开始,作为[发布流程的](#how-it-works)一部分,附加到事件问题描述或注释的文件将被发布和未发布到状态页存储中. + +### Limit[](#limit "Permalink") + +每个问题仅 5000 个附件将被转移到状态页面. \ No newline at end of file diff --git a/docs/197.md b/docs/197.md new file mode 100644 index 0000000000000000000000000000000000000000..9b247baecb1fc29e11e6190d8389698d9ba6b40e --- /dev/null +++ b/docs/197.md @@ -0,0 +1,290 @@ +# Feature Flags + +> 原文:[https://docs.gitlab.com/ee/operations/feature_flags.html](https://docs.gitlab.com/ee/operations/feature_flags.html) + +* [How it works](#how-it-works) +* [Create a feature flag](#create-a-feature-flag) +* [Rollout strategy (legacy)](#rollout-strategy-legacy) +* [Feature flag strategies](#feature-flag-strategies) + * [All users](#all-users) + * [Percent of Users](#percent-of-users) + * [User IDs](#user-ids) + * [User List](#user-list) + * [Enable or disable feature flag strategies](#enable-or-disable-feature-flag-strategies) +* [Disable a feature flag for a specific environment](#disable-a-feature-flag-for-a-specific-environment) +* [Disable a feature flag for all environments](#disable-a-feature-flag-for-all-environments) +* [Integrate feature flags with your application](#integrate-feature-flags-with-your-application) + * [Get access credentials](#get-access-credentials) + * [Choose a client library](#choose-a-client-library) + * [Feature flags API information](#feature-flags-api-information) + * [Golang application example](#golang-application-example) + * [Ruby application example](#ruby-application-example) +* [Feature Flag Related Issues](#feature-flag-related-issues) + * [Enable or disable Feature Flag Related Issues](#enable-or-disable-feature-flag-related-issues-core-only) + +# Feature Flags[](#feature-flags-premium "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7433) . + +借助功能标志,您可以将应用程序的新功能部署到较小的批量生产中. 您可以将功能打开或关闭到部分用户,以帮助您实现持续交付. 功能标记有助于降低风险,使您能够进行受控测试,并将功能交付与客户发布分开. + +有关实际使用的功能标志的示例,请参阅[用于部署的 GitLab,功能标志和错误跟踪](https://www.youtube.com/embed/5tw2p6lwXxo) . + +## How it works[](#how-it-works "Permalink") + +GitLab 使用功能切换服务[Unleash](https://github.com/Unleash/unleash) . + +通过在 GitLab 中启用或禁用标记,您的应用程序可以确定要启用或禁用的功能. + +您可以在 GitLab 中创建功能标记,并使用应用程序中的 API 来获取功能标记及其状态的列表. 必须将应用程序配置为与 GitLab 进行通信,因此,开发人员可以使用兼容的客户端库并将[功能标记集成到您的应用程序中](#integrate-feature-flags-with-your-application) . + +## Create a feature flag[](#create-a-feature-flag "Permalink") + +要创建并启用功能标志: + +1. 导航到项目的" **操作">"功能标志"** . +2. 单击**新功能标志**按钮. +3. 输入一个以字母开头的名称,该名称仅包含小写字母,数字,下划线( `_` )或破折号( `-` ),并且不以破折号( `-` )或下划线( `_` )结尾. +4. 输入描述(可选,最多 255 个字符). +5. Enter details about how the flag should be applied: + * 在 GitLab 13.0 和更早版本中,添加**Environment specs** . 对于每个环境,包括" **状态"** (默认启用)和" [**部署"策略**](#rollout-strategy-legacy) (默认为" **所有用户"** ). + * 在 GitLab 13.1 和更高版本中,添加 Feature Flag [**Strategies**](#feature-flag-strategies) . 对于每种策略,请包括" **类型"** (默认为" [**所有用户"**](#all-users) )和" **环境"** (默认为所有环境). +6. Click **创建功能标志**. + +您可以通过单击 列表中任何功能标志旁边的(编辑)按钮. + +## Rollout strategy (legacy)[](#rollout-strategy-legacy "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/8240) . + +在 GitLab 13.0 和更早版本中," **推出"策略**设置会影响哪些用户将启用该功能. 选择要启用该功能的用户百分比. 如果禁用环境规范,则推出策略将无效. + +可以设置为: + +* 全部用户 +* [Percent of users](#percent-of-users) + * (可选)您可以单击" **包括其他用户 ID"**复选框,并添加特定用户 ID 列表以启用该功能. +* [User IDs](#user-ids) + +## Feature flag strategies[](#feature-flag-strategies "Permalink") + +版本历史 + +* 在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/35555) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上启用了它. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-feature-flag-strategies) . + +您可以在多个环境中应用功能标记策略,而无需多次定义策略. + +GitLab 功能标志使用[Unleash](https://unleash.github.io)作为功​​能标志引擎. 在"释放"中,有用于粒度特征标志控件的[策略](https://unleash.github.io/docs/activation_strategy) . GitLab 功能标志可以有多种策略,支持的策略有: + +* [All users](#all-users) +* [Percent of Users](#percent-of-users) +* [User IDs](#user-ids) +* [User List](#user-list) + +可以在[创建](#create-a-feature-flag)功能部件标记时将策略添加到功能部件标记,也可以在[创建](#create-a-feature-flag)后通过导航到" **操作">"功能部件标记"**并单击以编辑现有功能部件标记 (编辑). + +### All users[](#all-users "Permalink") + +为所有用户启用该功能. 它使用[`default`](https://unleash.github.io/docs/activation_strategy#default)释放激活策略. + +### Percent of Users[](#percent-of-users "Permalink") + +为一定百分比的已认证用户启用该功能. 它使用[`gradualRolloutUserId`](https://unleash.github.io/docs/activation_strategy#gradualrolloutuserid)释放激活策略. + +例如,将值设置为 15%即可为 15%的经过身份验证的用户启用该功能. + +推出百分比可以从 0%到 100%. + +**注意:**对于已登录的用户,但对于匿名用户,保证了粘性(同一用户的一致应用程序行为).**警告:**如果选择此策略,则**必须**为 Unleash 客户端提供一个用户 ID,以启用该功能. 请参见下面的[Ruby 示例](#ruby-application-example) . + +### User IDs[](#user-ids "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/8240) . [更新](https://gitlab.com/gitlab-org/gitlab/-/issues/34363)为在 GitLab 12.6 中按环境定义. + +为目标用户列表启用该功能. 它是使用 Unleash [`userWithId`](https://unleash.github.io/docs/activation_strategy#userwithid)激活策略实现的. + +输入用户 ID 作为逗号分隔的值列表. 例如, `user@example.com, user2@example.com`或`username1,username2,username3`等. + +**注意:**用户 ID 是您的应用程序用户的标识符. 他们不必是 GitLab 用户.**注意:** **必须**为 Unleash 客户端提供用户 ID,才能为目标用户启用该功能. 请参见下面的[Ruby 示例](#ruby-application-example) . + +### User List[](#user-list "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/35930) . + +为使用[Feature Flag User List API](../api/feature_flag_user_lists.html)创建的[用户列表](../api/feature_flag_user_lists.html)启用功能. 与[用户 ID](#user-ids)相似,它使用 Unleash [`userWithId`](https://unleash.github.io/docs/activation_strategy#userwithid)激活策略. + +### Enable or disable feature flag strategies[](#enable-or-disable-feature-flag-strategies "Permalink") + +此功能正在开发中,但已准备好进行测试. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../administration/feature_flags.html)可以为您的实例启用它. + +要启用它: + +``` +Feature.enable(:feature_flags_new_version) +``` + +禁用它: + +``` +Feature.disable(:feature_flags_new_version) +``` + +## Disable a feature flag for a specific environment[](#disable-a-feature-flag-for-a-specific-environment "Permalink") + +在[GitLab 13.0 和更早版本中](https://gitlab.com/gitlab-org/gitlab/-/issues/8621) ,要为特定环境禁用功能标志: + +1. 导航到项目的" **操作">"功能标志"** . +2. 对于要禁用的功能标志,请单击"铅笔"图标. +3. 禁用标志: + + * 在 GitLab 13.0 和更低版本中:滑动环境的"状态"切换. 或者,要删除环境规范,请单击右侧的" **删除(X)"**图标. + * 在 GitLab 13.1 及更高版本:对于每一个战略,它适用于在**环境** ,删除环境. +4. Click **保存更改**. + +## Disable a feature flag for all environments[](#disable-a-feature-flag-for-all-environments "Permalink") + +禁用所有环境的功能标志: + +1. 导航到项目的" **操作">"功能标志"** . +2. 对于要禁用的功能标志,请将状态切换滑动到**禁用** . + +功能标志显示在" **禁用"**选项卡上. + +## Integrate feature flags with your application[](#integrate-feature-flags-with-your-application "Permalink") + +要在应用程序中使用功能标志,请从 GitLab 获取访问凭据. 然后使用客户端库准备您的应用程序. + +### Get access credentials[](#get-access-credentials "Permalink") + +要获取您的应用程序需要与 GitLab 通信的访问凭据: + +1. 导航到项目的" **操作">"功能标志"** . +2. 单击**配置**按钮以查看以下内容: + * **API URL** :客户端(应用程序)连接以获取功能标志列表的 URL. + * **实例 ID** :授权检索功能标志的唯一令牌. + * **应用程序名称** :运行环境的名称. 例如,如果应用程序为生产服务器运行,则应用程序名称将为`production`或类似名称. 该值用于环境规格评估. + +**注意:**这些字段的含义可能会随着时间而改变. 例如,我们不确定**实例 ID**是分配给**Environment 的**是单个令牌还是多个令牌. 另外, **应用程序名称**可以描述应用程序的版本,而不是运行环境. + +### Choose a client library[](#choose-a-client-library "Permalink") + +GitLab 实现与 Unleash 客户端兼容的单个后端. + +使用 Unleash 客户端,开发人员可以在应用程序代码中定义标志的默认值. 如果提供的配置文件中不存在该标志,则每个功能标志评估都可以表达所需的结果. + +目前,Unleash [提供了许多用于各种语言和框架的 SDK](https://github.com/Unleash/unleash#client-implementations) . + +### Feature flags API information[](#feature-flags-api-information "Permalink") + +有关 API 的内容,请参见: + +* [Feature Flags API](../api/feature_flags.html) +* [功能标志规范 API](../api/feature_flag_specs.html) (已[在 GitLab 14.0 中](https://gitlab.com/gitlab-org/gitlab/-/issues/213369)弃用并[计划将其删除](https://gitlab.com/gitlab-org/gitlab/-/issues/213369) .) +* [Feature Flag User Lists API](../api/feature_flag_user_lists.html) +* [Legacy Feature Flags API](../api/feature_flags_legacy.html) + +### Golang application example[](#golang-application-example "Permalink") + +这是一个如何在 Golang 应用程序中集成特征标记的示例: + +``` +package main + +import ( + "io" + "log" + "net/http" + + "github.com/Unleash/unleash-client-go" +) + +type metricsInterface struct { +} + +func init() { + unleash.Initialize( + unleash.WithUrl("https://gitlab.com/api/v4/feature_flags/unleash/42"), + unleash.WithInstanceId("29QmjsW6KngPR5JNPMWx"), + unleash.WithAppName("production"), + unleash.WithListener(&metricsInterface{}), + ) +} + +func helloServer(w http.ResponseWriter, req *http.Request) { + if unleash.IsEnabled("my_feature_name") { + io.WriteString(w, "Feature enabled\n") + } else { + io.WriteString(w, "hello, world!\n") + } +} + +func main() { + http.HandleFunc("/", helloServer) + log.Fatal(http.ListenAndServe(":8080", nil)) +} +``` + +### Ruby application example[](#ruby-application-example "Permalink") + +这是一个如何在 Ruby 应用程序中集成功能标记的示例. + +为 Unleash 客户端提供了一个用户 ID,以与" **百分比"卷展栏(已登录用户)卷**展策略或" **目标用户"**列表一起使用. + +``` +#!/usr/bin/env ruby + +require 'unleash' +require 'unleash/context' + +unleash = Unleash::Client.new({ + url: 'http://gitlab.com/api/v4/feature_flags/unleash/42', + app_name: 'production', + instance_id: '29QmjsW6KngPR5JNPMWx' +}) + +unleash_context = Unleash::Context.new +# Replace "123" with the id of an authenticated user. +# Note that the context's user id must be a string: +# https://unleash.github.io/docs/unleash_context +unleash_context.user_id = "123" + +if unleash.is_enabled?("my_feature_name", unleash_context) + puts "Feature enabled" +else + puts "hello, world!" +end +``` + +## Feature Flag Related Issues[](#feature-flag-related-issues "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36617) . +* 它部署在默认情况下启用的功能标志后面. +* 在 GitLab.com 上启用了它. +* 不能根据项目启用或禁用它 +* 建议用于生产. +* 对于 GitLab 自我管理的实例,GitLab 管理员可以选择禁用它. + +您可以将相关问题链接到功能标志. 在" **链接的问题"**部分中,单击`+`按钮,然后输入问题参考编号或问题的完整 URL. + +此功能类似于[相关问题](../user/project/issues/related_issues.html)功能. + +### Enable or disable Feature Flag Related Issues[](#enable-or-disable-feature-flag-related-issues-core-only "Permalink") + +与功能标记相关​​的问题正在开发中,但已准备好用于生产. 它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../administration/feature_flags.html)可以选择为您的实例禁用它. + +禁用它: + +``` +Feature.disable(:feature_flags_issue_links) +``` + +To enable it: + +``` +Feature.enable(:feature_flags_issue_links) +``` \ No newline at end of file diff --git a/docs/198.md b/docs/198.md new file mode 100644 index 0000000000000000000000000000000000000000..7c587b7b6f8716c69c37c732b0009aafe91a6464 --- /dev/null +++ b/docs/198.md @@ -0,0 +1,203 @@ +# GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/README.html](https://docs.gitlab.com/ee/ci/README.html) + +* [Overview](#overview) +* [Getting started](#getting-started) +* [Concepts](#concepts) +* [Configuration](#configuration) +* [Feature set](#feature-set) +* [Examples](#examples) +* [Administration](#administration-core-only) +* [References](#references) + * [Why GitLab CI/CD?](#why-gitlab-cicd) + * [Breaking changes](#breaking-changes) + * [13.0](#130) + * [12.0](#120) + * [11.0](#110) + * [10.0](#100) + * [9.0](#90) + +# GitLab CI/CD[](#gitlab-cicd "Permalink") + +GitLab CI / CD 是 GitLab 内置的工具,用于通过[连续方法](introduction/index.html#introduction-to-cicd-methodologies)进行软件开发: + +* 持续集成(CI) +* 连续交付(CD) +* 持续部署(CD) + +**注意:**开箱即用的管理系统可以将维护工具链所花费的时间减少 10%或更多. 观看我们的["精通持续软件开发"](https://about.gitlab.com/webcast/mastering-ci-cd/)网络广播,以了解连续方法以及 GitLab 的内置 CI 如何帮助您简化和扩展软件开发. + +## Overview[](#overview "Permalink") + +持续集成的工作原理是将小的代码块推送到 Git 存储库中托管的应用程序代码库中,并且每次推送时,都要运行脚本管道来构建,测试和验证代码更改,然后再将其合并到主分支中. + +持续交付和部署包括进一步的 CI,可在每次推送到存储库默认分支时将应用程序部署到生产环境. + +这些方法使您可以在开发周期的早期发现错误和错误,从而确保部署到生产环境的所有代码均符合为应用程序建立的代码标准. + +有关这些方法和 GitLab CI / CD 的完整概述,请阅读 GitLab 的 CI / CD [简介](introduction/index.html) . + +GitLab CI / CD 的视频演示: [演示:](https://www.youtube.com/watch?v=1iXFbchozdY) GitLab 的 CI / CD. + +<figure class="video-container"><iframe src="https://www.youtube.com/embed/1iXFbchozdY" frameborder="0" allowfullscreen=""></iframe></figure> + +## Getting started[](#getting-started "Permalink") + +GitLab CI / CD 由位于存储库根目录的名为`.gitlab-ci.yml`的文件配置. 该文件创建[管道](pipelines/index.html) ,该[管道](pipelines/index.html)运行以更改存储库中的代码. 管道包含一个或多个顺序运行的阶段,每个阶段可以包含一个或多个并行运行的作业. 这些作业(或脚本)由[GitLab Runner](https://docs.gitlab.com/runner/)代理执行. + +要开始使用 GitLab CI / CD,我们建议您通读以下文档: + +* [How GitLab CI/CD works](introduction/index.html#how-gitlab-cicd-works). +* [Fundamental pipeline architectures](pipelines/pipeline_architectures.html). +* [GitLab CI/CD basic workflow](introduction/index.html#basic-cicd-workflow). +* [Step-by-step guide for writing `.gitlab-ci.yml` for the first time](../user/project/pages/getting_started/pages_from_scratch.html). + +如果您要从其他 CI / CD 工具迁移,请查看我们方便的参考资料: + +* [Migrating from CircleCI](migration/circleci.html) +* [Migrating from Jenkins](jenkins/index.html) + +您也可以使用 UI 中提供的[`.gitlab-ci.yml`模板](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/lib/gitlab/ci/templates)之一来开始使用. 您可以通过创建新文件,选择适合您的应用程序的模板并根据需要进行调整来使用它们: + +[![Use a `.gitlab-ci.yml` template](img/e006fccde54b694d8c0f506a675942e0.png)](img/add_file_template_11_10.png) + +有关更广泛的概述,请参阅《 [CI / CD 入门](quick_start/README.html)指南》. + +熟悉 GitLab CI / CD 的工作原理后,请参阅[`.gitlab-ci.yml`完整参考,](yaml/README.html)以获取可以设置和使用的所有属性. + +**注意:** GitLab CI / CD 和[共享运行](runners/README.html#shared-runners)器在 GitLab.com 中启用,并且对所有用户可用,仅限于[用户的管道配额](../user/gitlab_com/index.html#shared-runners) . + +## Concepts[](#concepts "Permalink") + +GitLab CI / CD 使用许多概念来描述和运行您的构建和部署. + +| Concept | Description | +| --- | --- | +| [Pipelines](pipelines/index.html) | Structure your CI/CD process through pipelines. | +| [Environment variables](variables/README.html) | 根据变量/值键对重用值. | +| [Environments](environments/index.html) | 将您的应用程序部署到不同的环境(例如,登台,生产). | +| [Job artifacts](pipelines/job_artifacts.html) | 输出,使用和重用作业工件. | +| [Cache dependencies](caching/index.html) | 缓存您的依赖项以加快执行速度. | +| [GitLab Runner](https://docs.gitlab.com/runner/) | 配置自己的 GitLab 运行程序以执行脚本. | + +## Configuration[](#configuration "Permalink") + +GitLab CI / CD 支持多种配置选项: + +| Configuration | Description | +| --- | --- | +| [Schedule pipelines](pipelines/schedules.html) | 计划管道以根据需要运行. | +| [Custom path for `.gitlab-ci.yml`](pipelines/settings.html#custom-ci-configuration-path) | 为 CI / CD 配置文件定义自定义路径. | +| [Git submodules for CI/CD](git_submodules.html) | 配置作业以使用 Git 子模块. | +| [SSH keys for CI/CD](ssh_keys/README.html) | 在 CI 管道中使用 SSH 密钥. | +| [Pipeline triggers](triggers/README.html) | 通过 API 触发管道. | +| [Pipelines for Merge Requests](merge_request_pipelines/index.html) | 设计用于在合并请求中运行管道的管道结构. | +| [Integrate with Kubernetes clusters](../user/project/clusters/index.html) | 将您的项目连接到 Google Kubernetes Engine(GKE)或现有的 Kubernetes 集群. | +| [Optimize GitLab and Runner for large repositories](large_repositories/index.html) | 处理大型存储库的推荐策略. | +| [`.gitlab-ci.yml` full reference](yaml/README.html) | 您可以在 GitLab CI / CD 中使用的所有属性. | + +请注意,某些操作只能根据[用户](../user/permissions.html#gitlab-cicd-permissions)和[作业](../user/permissions.html#job-permissions)权限执行. + +## Feature set[](#feature-set "Permalink") + +使用庞大的 GitLab CI / CD 可以轻松地针对特定目的进行配置. 根据 DevOps 阶段,其功能集在下表中列出. + +| Feature | Description | +| --- | --- | +| **Configure** |   | +| [Auto DevOps](../topics/autodevops/index.html) | 设置应用的整个生命周期. | +| [ChatOps](chatops/README.html) | 从聊天中触发 CI 作业,并将结果发送回通道. | +| **Verify** |   | +| [Browser Performance Testing](../user/project/merge_requests/browser_performance_testing.html) | 快速确定即将发生的代码更改对浏览器性能的影响. | +| [Load Performance Testing](../user/project/merge_requests/load_performance_testing.html) | 快速确定未决代码更改对服务器性能的影响. | +| [CI services](services/README.html) | 将 Docker 容器与您的基本映像链接起来. | +| [Code Quality](../user/project/merge_requests/code_quality.html) | 分析您的源代码质量. | +| [GitLab CI/CD for external repositories](ci_cd_for_external_repos/index.html) | 结合使用 GitHub 和 Bitbucket Cloud 中的存储库,获得 GitLab CI / CD 的优势. | +| [Interactive Web Terminals](interactive_web_terminal/index.html) | 打开一个交互式 Web 终端以调试正在运行的作业. | +| [JUnit tests](junit_test_reports.html) | 直接在合并请求中识别脚本失败. | +| [Using Docker images](docker/using_docker_images.html) | 将 GitLab 和 GitLab Runner 与 Docker 结合使用来构建和测试应用程序. | +| **Release** |   | +| [Auto Deploy](../topics/autodevops/stages.html#auto-deploy) | 将您的应用程序部署到 Kubernetes 集群中的生产环境. | +| [Building Docker images](docker/using_docker_build.html) | 使用 GitLab CI / CD 维护基于 Docker 的项目. | +| [Canary Deployments](../user/project/canary_deployments.html) | 仅将功能部件运送到一部分吊舱中,并让一定比例的用户群访问临时部署的功能部件. | +| [Deploy Boards](../user/project/deploy_boards.html) | 检查 Kubernetes 上运行的每个 CI / CD 环境的当前运行状况和状态. | +| [Feature Flags](../operations/feature_flags.html) | 在功能标记后部署功能. | +| [GitLab Pages](../user/project/pages/index.html) | 部署静态网站. | +| [GitLab Releases](../user/project/releases/index.html) | 将发行说明添加到 Git 标签. | +| [Review Apps](review_apps/index.html) | 配置 GitLab CI / CD 预览代码更改. | +| [Cloud deployment](cloud_deployment/index.html) | 将您的应用程序部署到主要的云提供商. | +| **Secure** |   | +| [Container Scanning](../user/application_security/container_scanning/index.html) | 检查您的 Docker 容器是否存在已知漏洞. | +| [Dependency Scanning](../user/application_security/dependency_scanning/index.html) | 分析您的依赖项是否存在已知漏洞. | +| [License Compliance](../user/compliance/license_compliance/index.html) | 在项目依赖项中搜索其许可证. | +| [Security Test reports](../user/application_security/index.html) | 检查应用程序漏洞. | + +## Examples[](#examples "Permalink") + +在" [CI 实例"](examples/README.html)页面上查找示例项目代码和教程,以将 GitLab CI / CD 与各种应用程序框架,语言和平台结合使用. + +GitLab 还提供了[示例项目,这些项目已](https://gitlab.com/gitlab-examples)预先配置为使用 GitLab CI / CD. + +## Administration[](#administration-core-only "Permalink") + +作为 GitLab 管理员,您可以将 GitLab CI / CD 的默认行为更改为: + +* An [entire GitLab instance](../user/admin_area/settings/continuous_integration.html). +* 具体项目,使用[管道设置](pipelines/settings.html) . + +也可以看看: + +* [How to enable or disable GitLab CI/CD](enable_or_disable_ci.html). +* Other [CI administration settings](../administration/index.html#continuous-integration-settings). + +## References[](#references "Permalink") + +### Why GitLab CI/CD?[](#why-gitlab-cicd "Permalink") + +学习更多关于: + +* [Why you might chose GitLab CI/CD](https://about.gitlab.com/blog/2016/10/17/gitlab-ci-oohlala/). +* [Reasons you might migrate from another platform](https://about.gitlab.com/blog/2016/07/22/building-our-web-app-on-gitlab-ci/). +* [5 Teams that made the switch to GitLab CI/CD](https://about.gitlab.com/blog/2019/04/25/5-teams-that-made-the-switch-to-gitlab-ci-cd/) + +另请参阅[为什么选择 CI / CD?](https://docs.google.com/presentation/d/1OGgk2Tcxbpl7DJaIOzCX4Vqg3dlwfELC3u2jEeCBbDk) 介绍. + +### Breaking changes[](#breaking-changes "Permalink") + +随着 GitLab CI / CD 的发展,必须进行一些重大更改. 这些是: + +#### 13.0[](#130 "Permalink") + +* [Remove Backported `os.Expand`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4915) +* [Remove Fedora 29 package support](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/16158) +* [Remove macOS 32-bit support](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25466) +* [Removed `debug/jobs/list?v=1` endpoint](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6361) +* [Remove support for array of strings when defining services for Docker executor](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4922) +* [Remove `--docker-services` flag on register command](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6404) +* [Remove legacy build directory caching](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4180) +* [Remove `FF_USE_LEGACY_VOLUMES_MOUNTING_ORDER` feature flag](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6581) +* [Remove support for Windows Server 1803](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6553) + +#### 12.0[](#120 "Permalink") + +* [Use refspec to clone/fetch Git repository](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4069). +* [Old cache configuration](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4070). +* [Old metrics server configuration](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4072). +* [Remove `FF_K8S_USE_ENTRYPOINT_OVER_COMMAND`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4073). +* [Remove Linux distributions that reach EOL](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/1130). +* [Update command line API for helper images](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4013). +* [Remove old `git clean` flow](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4175). + +#### 11.0[](#110 "Permalink") + +* 没有重大变化. + +#### 10.0[](#100 "Permalink") + +* 没有重大变化. + +#### 9.0[](#90 "Permalink") + +* [为 GitLab 9.0 重命名 CI 变量](variables/deprecated_variables.html#gitlab-90-renamed-variables) . 了解不建议使用的 CI 变量以及在 GitLab 9.0+中应使用的内容. +* [新的 CI 作业权限模型](../user/project/new_ci_build_permissions_model.html) . 查看 GitLab 8.12 中的更改及其对工作的影响. 有一种新方法可以访问作业中的 Git 子模块和 LFS 对象. \ No newline at end of file diff --git a/docs/199.md b/docs/199.md new file mode 100644 index 0000000000000000000000000000000000000000..aa74f9e975ad8849b048c38868f637dd779271f4 --- /dev/null +++ b/docs/199.md @@ -0,0 +1,3929 @@ +# GitLab CI/CD pipeline configuration reference + +> 原文:[https://docs.gitlab.com/ee/ci/yaml/README.html](https://docs.gitlab.com/ee/ci/yaml/README.html) + +* [Introduction](#introduction) + * [Validate the `.gitlab-ci.yml`](#validate-the-gitlab-ciyml) + * [Unavailable names for jobs](#unavailable-names-for-jobs) + * [Using reserved keywords](#using-reserved-keywords) +* [Configuration parameters](#configuration-parameters) +* [Global parameters](#global-parameters) + * [Global defaults](#global-defaults) + * [`inherit`](#inherit) + * [`stages`](#stages) + * [`workflow:rules`](#workflowrules) + * [`workflow:rules` templates](#workflowrules-templates) + * [`include`](#include) + * [`include:local`](#includelocal) + * [`include:file`](#includefile) + * [`include:remote`](#includeremote) + * [`include:template`](#includetemplate) + * [Nested includes](#nested-includes) + * [Additional `includes` examples](#additional-includes-examples) +* [Parameter details](#parameter-details) + * [`image`](#image) + * [`image:name`](#imagename) + * [`image:entrypoint`](#imageentrypoint) + * [`services`](#services) + * [`services:name`](#servicesname) + * [`services:alias`](#servicesalias) + * [`services:entrypoint`](#servicesentrypoint) + * [`services:command`](#servicescommand) + * [`script`](#script) + * [`before_script` and `after_script`](#before_script-and-after_script) + * [Coloring script output](#coloring-script-output) + * [Multiline commands](#multiline-commands) + * [`stage`](#stage) + * [Using your own Runners](#using-your-own-runners) + * [`.pre` and `.post`](#pre-and-post) + * [`extends`](#extends) + * [Merge details](#merge-details) + * [Using `extends` and `include` together](#using-extends-and-include-together) + * [`rules`](#rules) + * [Rules attributes](#rules-attributes) + * [Rules clauses](#rules-clauses) + * [Differences between `rules` and `only`/`except`](#differences-between-rules-and-onlyexcept) + * [`rules:if`](#rulesif) + * [`rules:changes`](#ruleschanges) + * [`rules:exists`](#rulesexists) + * [`rules:allow_failure`](#rulesallow_failure) + * [Complex rule clauses](#complex-rule-clauses) + * [`only`/`except` (basic)](#onlyexcept-basic) + * [Regular expressions](#regular-expressions) + * [Supported `only`/`except` regexp syntax](#supported-onlyexcept-regexp-syntax) + * [`only`/`except` (advanced)](#onlyexcept-advanced) + * [`only:refs`/`except:refs`](#onlyrefsexceptrefs) + * [`only:kubernetes`/`except:kubernetes`](#onlykubernetesexceptkubernetes) + * [`only:variables`/`except:variables`](#onlyvariablesexceptvariables) + * [`only:changes`/`except:changes`](#onlychangesexceptchanges) + * [Using `only:changes` with pipelines for merge requests](#using-onlychanges-with-pipelines-for-merge-requests) + * [Using `only:changes` without pipelines for merge requests](#using-onlychanges-without-pipelines-for-merge-requests) + * [Using `only:changes` with scheduled pipelines](#using-onlychanges-with-scheduled-pipelines) + * [`needs`](#needs) + * [Requirements and limitations](#requirements-and-limitations) + * [Changing the `needs:` job limit](#changing-the-needs-job-limit) + * [Artifact downloads with `needs`](#artifact-downloads-with-needs) + * [Cross project artifact downloads with `needs`](#cross-project-artifact-downloads-with-needs-premium) + * [Artifact downloads between pipelines in the same project](#artifact-downloads-between-pipelines-in-the-same-project) + * [`tags`](#tags) + * [`allow_failure`](#allow_failure) + * [`when`](#when) + * [`when:manual`](#whenmanual) + * [Protecting manual jobs](#protecting-manual-jobs-premium) + * [`when:delayed`](#whendelayed) + * [`environment`](#environment) + * [`environment:name`](#environmentname) + * [`environment:url`](#environmenturl) + * [`environment:on_stop`](#environmenton_stop) + * [`environment:action`](#environmentaction) + * [`environment:auto_stop_in`](#environmentauto_stop_in) + * [`environment:kubernetes`](#environmentkubernetes) + * [Dynamic environments](#dynamic-environments) + * [`cache`](#cache) + * [`cache:paths`](#cachepaths) + * [`cache:key`](#cachekey) + * [`cache:key:files`](#cachekeyfiles) + * [`cache:key:prefix`](#cachekeyprefix) + * [`cache:untracked`](#cacheuntracked) + * [`cache:policy`](#cachepolicy) + * [`artifacts`](#artifacts) + * [`artifacts:paths`](#artifactspaths) + * [`artifacts:exclude`](#artifactsexclude) + * [`artifacts:expose_as`](#artifactsexpose_as) + * [`artifacts:name`](#artifactsname) + * [`artifacts:untracked`](#artifactsuntracked) + * [`artifacts:when`](#artifactswhen) + * [`artifacts:expire_in`](#artifactsexpire_in) + * [`artifacts:reports`](#artifactsreports) + * [`dependencies`](#dependencies) + * [When a dependent job will fail](#when-a-dependent-job-will-fail) + * [`coverage`](#coverage) + * [`retry`](#retry) + * [`timeout`](#timeout) + * [`parallel`](#parallel) + * [`trigger`](#trigger) + * [Simple `trigger` syntax for multi-project pipelines](#simple-trigger-syntax-for-multi-project-pipelines) + * [Complex `trigger` syntax for multi-project pipelines](#complex-trigger-syntax-for-multi-project-pipelines) + * [`trigger` syntax for child pipeline](#trigger-syntax-for-child-pipeline) + * [Trigger child pipeline with generated configuration file](#trigger-child-pipeline-with-generated-configuration-file) + * [Linking pipelines with `trigger:strategy`](#linking-pipelines-with-triggerstrategy) + * [Trigger a pipeline by API call](#trigger-a-pipeline-by-api-call) + * [`interruptible`](#interruptible) + * [`resource_group`](#resource_group) + * [`release`](#release) + * [`release-cli` Docker image](#release-cli-docker-image) + * [Script](#script-1) + * [`release:tag_name`](#releasetag_name) + * [`release:name`](#releasename) + * [`release:description`](#releasedescription) + * [`release:ref`](#releaseref) + * [`release:milestones`](#releasemilestones) + * [`release:released_at`](#releasereleased_at) + * [Complete example for `release`](#complete-example-for-release) + * [`releaser-cli` command line](#releaser-cli-command-line) + * [`pages`](#pages) +* [`variables`](#variables) + * [Git strategy](#git-strategy) + * [Git submodule strategy](#git-submodule-strategy) + * [Git checkout](#git-checkout) + * [Git clean flags](#git-clean-flags) + * [Git fetch extra flags](#git-fetch-extra-flags) + * [Job stages attempts](#job-stages-attempts) + * [Shallow cloning](#shallow-cloning) + * [Custom build directories](#custom-build-directories) + * [Handling concurrency](#handling-concurrency) + * [Nested paths](#nested-paths) +* [Special YAML features](#special-yaml-features) + * [Anchors](#anchors) + * [YAML anchors for `before_script` and `after_script`](#yaml-anchors-for-before_script-and-after_script) + * [YAML anchors for `script`](#yaml-anchors-for-script) + * [YAML anchors for variables](#yaml-anchors-for-variables) + * [Hide jobs](#hide-jobs) +* [Skip Pipeline](#skip-pipeline) +* [Processing Git pushes](#processing-git-pushes) +* [Deprecated parameters](#deprecated-parameters) + * [Globally-defined `types`](#globally-defined-types) + * [Job-defined `type`](#job-defined-type) + * [Globally-defined `image`, `services`, `cache`, `before_script`, `after_script`](#globally-defined-image-services-cache-before_script-after_script) + +# GitLab CI/CD pipeline configuration reference[](#gitlab-cicd-pipeline-configuration-reference "Permalink") + +在每个项目中,使用名为`.gitlab-ci.yml`的 YAML 文件配置 GitLab CI / CD [管道](../pipelines/index.html) . + +`.gitlab-ci.yml`文件定义管道的结构和顺序,并确定: + +* 使用[GitLab Runner](https://docs.gitlab.com/runner/)执行什么. +* 遇到特定条件时要做出什么决定. 例如,当一个过程成功或失败时. + +本主题涵盖 CI / CD 管道配置. 有关其他 CI / CD 配置信息,请参阅: + +* [GitLab CI / CD 变量](../variables/README.html) ,用于配置运行管道的环境. +* [GitLab Runner 高级配置](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) ,用于配置 GitLab Runner. + +我们有配置管道的完整示例: + +* 有关 GitLab CI / CD 的快速介绍,请遵循我们的[快速入门指南](../quick_start/README.html) . +* 有关示例集合,请参见[GitLab CI / CD 示例](../examples/README.html) . +* 要看到一个大`.gitlab-ci.yml`在企业使用的文件,看到[`.gitlab-ci.yml`文件`gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml) . + +> 有关 GitLab CI / CD 的其他信息: +> +> * 观看[CI / CD 轻松配置](https://www.youtube.com/embed/opdLqwz6tcE)视频. +> * [在组织的](https://about.gitlab.com/compare/github-actions-alternative/)网络广播中观看" [为 CI / CD](https://about.gitlab.com/compare/github-actions-alternative/)辩护",以了解 CI / CD 的好处以及如何衡量 CI / CD 自动化的结果. +> * 了解[Verizon](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/)如何使用 GitLab [将重建工作](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/)从 30 天[减少](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/)到 8 小时以下. + +**注意:**如果您有[从 GitLab 提取镜像的存储库](../../user/project/repository/repository_mirroring.html#pulling-from-a-remote-repository-starter) ,则可能需要在项目的**"设置">"存储库">"从远程存储库中提取">"触发管道更新镜像"中**启用管道触发. + +## Introduction[](#introduction "Permalink") + +管道配置从作业开始. 作业是`.gitlab-ci.yml`文件的最基本元素. + +工作是: + +* 定义了约束,指出应在什么条件下执行它们. +* 具有任意名称的顶级元素,并且必须至少包含[`script`](#script)子句. +* 不限制可以定义多少个. + +例如: + +``` +job1: + script: "execute-script-for-job1" + +job2: + script: "execute-script-for-job2" +``` + +上面的示例是具有两个单独作业的最简单的 CI / CD 配置,其中每个作业执行一个不同的命令. 当然,命令可以直接执行代码( `./configure;make;make install` )或在存储库中运行脚本( `test.sh` ). + +乔布斯被拾起[运动员](../runners/README.html)和跑步者的环境中执行. 重要的是,每个作业彼此独立运行. + +### Validate the `.gitlab-ci.yml`[](#validate-the-gitlab-ciyml "Permalink") + +GitLab CI / CD 的每个实例都有一个称为 Lint 的嵌入式调试工具,该工具可以验证`.gitlab-ci.yml`文件的内容. 您可以在项目名称空间的`ci/lint`页下找到 Lint. 例如, `https://gitlab.example.com/gitlab-org/project-123/-/ci/lint` . + +### Unavailable names for jobs[](#unavailable-names-for-jobs "Permalink") + +每个作业必须具有唯一的名称,但是有一些**保留的`keywords`不能用作作业名称** : + +* `image` +* `services` +* `stages` +* `types` +* `before_script` +* `after_script` +* `variables` +* `cache` +* `include` + +### Using reserved keywords[](#using-reserved-keywords "Permalink") + +如果在使用特定值(例如`true`或`false` )时收到验证错误,请尝试执行以下操作: + +* 引用他们. +* 将它们更改为其他形式. 例如, `/bin/true` . + +## Configuration parameters[](#configuration-parameters "Permalink") + +作业定义为定义作业行为的参数列表. + +下表列出了作业的可用参数: + +| Keyword | Description | +| --- | --- | +| [`script`](#script) | 由 Runner 执行的 Shell 脚本. | +| [`image`](#image) | 使用 Docker 映像 也可用: `image:name`和`image:entrypoint` . | +| [`services`](#services) | Use Docker services images. Also available: `services:name`, `services:alias`, `services:entrypoint`, and `services:command`. | +| [`before_script`](#before_script-and-after_script) | 覆盖作业之前执行的一组命令. | +| [`after_script`](#before_script-and-after_script) | 覆盖作业后执行的一组命令. | +| [`stage`](#stage) | 定义一个工作阶段(默认: `test` ). | +| [`only`](#onlyexcept-basic) | 限制创建作业的时间. 也可用: [`only:refs` , `only:kubernetes` , `only:variables`和`only:changes`](#onlyexcept-advanced) . | +| [`except`](#onlyexcept-basic) | 限制未创建作业的时间. 也可用: [`except:refs` , `except:kubernetes` , `except:variables`和`except:changes`](#onlyexcept-advanced) . | +| [`rules`](#rules) | 评估和确定作业的选定属性以及是否创建作业的条件列表. 不能`only`与/ `except`一起使用. | +| [`tags`](#tags) | 用于选择 Runner 的标签列表. | +| [`allow_failure`](#allow_failure) | 允许作业失败. 失败的作业不会影响提交状态. | +| [`when`](#when) | 什么时候开始工作. 也可用: `when:manual`和`when:delayed` . | +| [`environment`](#environment) | 作业部署到的环境的名称. 也可用: `environment:name` , `environment:url` , `environment:on_stop` , `environment:auto_stop_in`和`environment:action` . | +| [`cache`](#cache) | 在后续运行之间应缓存的文件列表. 也可用: `cache:paths` , `cache:key` , `cache:untracked`和`cache:policy` . | +| [`artifacts`](#artifacts) | 成功时附加到作业的文件和目录列表. 也可以使用: `artifacts:paths` , `artifacts:exclude` , `artifacts:expose_as` , `artifacts:name` , `artifacts:untracked` , `artifacts:when` , `artifacts:expire_in` , `artifacts:reports` , `artifacts:reports:junit` , `artifacts:reports:cobertura`和`artifacts:reports:terraform` . + +在 GitLab [企业版](https://about.gitlab.com/pricing/) ,这些都是可供选择: `artifacts:reports:codequality` , `artifacts:reports:sast` , `artifacts:reports:dependency_scanning` , `artifacts:reports:container_scanning` , `artifacts:reports:dast` , `artifacts:reports:license_scanning` , `artifacts:reports:license_management` (已在 GitLab 13.0 中删除), `artifacts:reports:performance`和`artifacts:reports:metrics` . | +| [`dependencies`](#dependencies) | 通过提供要从中获取工件的作业列表,限制将哪些工件传递给特定作业. | +| [`coverage`](#coverage) | 给定作业的代码覆盖率设置. | +| [`retry`](#retry) | 发生故障时可以自动重试作业的时间和次数. | +| [`timeout`](#timeout) | 定义优先于项目范围设置的自定义作业级别超时. | +| [`parallel`](#parallel) | 多少个作业实例应并行运行. | +| [`trigger`](#trigger) | 定义下游管道触发器. | +| [`include`](#include) | 允许此作业包括外部 YAML 文件. 也可用: `include:local` , `include:file` , `include:template`和`include:remote` . | +| [`extends`](#extends) | 该作业将要继承的配置条目. | +| [`pages`](#pages) | 上载作业结果以用于 GitLab 页面. | +| [`variables`](#variables) | 在作业级别上定义作业变量. | +| [`interruptible`](#interruptible) | 定义在通过新的运行使其冗余时是否可以取消作业. | +| [`resource_group`](#resource_group) | 限制作业并发. | +| [`release`](#release) | 指示 Runner 生成[Release](../../user/project/releases/index.html)对象. | + +**Note:** Parameters `types` and `type` are [deprecated](#deprecated-parameters). + +## Global parameters[](#global-parameters "Permalink") + +必须在全局级别定义一些参数,这会影响管道中的所有作业. + +### Global defaults[](#global-defaults "Permalink") + +可以使用`default:`关键字将某些参数全局设置为所有作业的`default:` . 然后可以通过特定于作业的配置覆盖默认参数. + +可以在`default:`块内定义以下作业参数: + +* [`image`](#image) +* [`services`](#services) +* [`before_script`](#before_script-and-after_script) +* [`after_script`](#before_script-and-after_script) +* [`tags`](#tags) +* [`cache`](#cache) +* [`artifacts`](#artifacts) +* [`retry`](#retry) +* [`timeout`](#timeout) +* [`interruptible`](#interruptible) + +在以下示例中,除了`rspec 2.6`作业(使用`ruby:2.6`图像)以外,所有作业的默认设置都是`ruby:2.5`图像: + +``` +default: + image: ruby:2.5 + +rspec: + script: bundle exec rspec + +rspec 2.6: + image: ruby:2.6 + script: bundle exec rspec +``` + +#### `inherit`[](#inherit "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/207484) . + +您可以使用`inherit:`参数禁用对全局定义的默认值和变量的`inherit:` . + +要启用或禁用所有`variables:`或`default:`参数的继承,请使用以下格式: + +* `default: true` or `default: false` +* `variables: true` or `variables: false` + +要仅继承`default:`参数或`variables:`的子集,请指定要继承的内容,未列出的任何内容均**不会**被继承. 使用以下格式之一: + +``` +inherit: + default: [parameter1, parameter2] + variables: [VARIABLE1, VARIABLE2] +``` + +Or: + +``` +inherit: + default: + - parameter1 + - parameter2 + variables: + - VARIABLE1 + - VARIABLE2 +``` + +在以下示例中: + +* `rubocop`: + * **会**继承:没有. +* `rspec`: + * **将**继承:默认`image`和`WEBHOOK_URL`变量. + * **不会**继承:默认的`before_script`和`DOMAIN`变量. +* `capybara`: + * **将**继承:默认的`before_script`和`image` . + * 将**不会**继承: `DOMAIN`和`WEBHOOK_URL`变量. +* `karma`: + * **将**继承:默认`image` , `before_script`和`DOMAIN`变量. + * will **not** inherit: `WEBHOOK_URL` variable. + +``` +default: + image: 'ruby:2.4' + before_script: + - echo Hello World + +variables: + DOMAIN: example.com + WEBHOOK_URL: https://my-webhook.example.com + +rubocop: + inherit: + default: false + variables: false + script: bundle exec rubocop + +rspec: + inherit: + default: [image] + variables: [WEBHOOK_URL] + script: bundle exec rspec + +capybara: + inherit: + variables: false + script: bundle exec capybara + +karma: + inherit: + default: true + variables: [DOMAIN] + script: karma +``` + +### `stages`[](#stages "Permalink") + +`stages`用于定义包含作业的阶段,并且为管道全局定义. + +的规范`stages`允许具有灵活的多阶段流水线. `stages`中元素的顺序定义了作业执行的顺序: + +1. 同一阶段的作业并行运行. +2. 前一阶段的作业成功完成后,将运行下一阶段的作业. + +让我们考虑以下示例,该示例定义了 3 个阶段: + +``` +stages: + - build + - test + - deploy +``` + +1. 首先,所有`build`作业均并行执行. +2. 如果所有`build`作业均成功,则`test`作业将并行执行. +3. 如果所有`test`作业均成功,则将并行执行`deploy`作业. +4. 如果所有`deploy`作业均成功,则将提交标记为`passed` . +5. 如果先前的任何作业失败,则将提交标记为`failed`并且不执行后续阶段的作业. + +还有两个边缘情况值得一提: + +1. 如果`.gitlab-ci.yml`中未定义任何`stages` ,则默认允许将`build` , `test`和`deploy`用作作业的阶段. +2. 如果作业未指定`stage` ,则为该作业分配`test`阶段. + +### `workflow:rules`[](#workflowrules "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/29654) + +顶级`workflow:`关键字适用于整个管道,并将确定是否创建管道. 当前,它接受一个`rules:`与[`rules:`](#rules)类似的键:在 job 中[定义](#rules) ,可动态配置管道. + +如果您不熟悉 GitLab CI / CD 和`workflow: rules` ,则可能会发现[`workflow:rules`模板](#workflowrules-templates)很有用. + +要定义自己的`workflow: rules` ,当前可用的配置选项为: + +* [`if`](#rulesif) :定义规则. +* [`when`](#when) :可以设置为`always`或`never` . 如果未提供,则默认值`always` . + +评估`if`规则的列表,直到匹配单个规则. 如果没有比赛,最后`when`会被使用: + +``` +workflow: + rules: + - if: $CI_COMMIT_REF_NAME =~ /-wip$/ + when: never + - if: $CI_COMMIT_TAG + when: never + - when: always +``` + +#### `workflow:rules` templates[](#workflowrules-templates "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/217732) . + +我们提供预制模板,供您用于设置`workflow: rules`管道使用`workflow: rules`常见方案的`workflow: rules` . 使用这些将使事情变得容易,并防止重复的管道运行. + +[`Branch-Pipelines`模板](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Workflows/Branch-Pipelines.gitlab-ci.yml)使您的管道针对分支和标签运行. + +分支管道状态将显示在使用该分支作为源的合并请求中,但是此管道类型不支持" [合并请求管道"](../merge_request_pipelines/)提供的任何功能,例如["合并结果管道"](../merge_request_pipelines/#pipelines-for-merged-results-premium)或" [合并训练"](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/) . 如果您有意避免使用这些功能,请使用此模板. + +它[包括](#include)以下内容: + +``` +include: + - template: 'Workflows/Branch-Pipelines.gitlab-ci.yml' +``` + +The [`MergeRequest-Pipelines` template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Workflows/MergeRequest-Pipelines.gitlab-ci.yml) makes your pipelines run for the default branch (usually `master`), tags, and all types of merge request pipelines. Use this template if you use any of the the [Pipelines for Merge Requests features](../merge_request_pipelines/), as mentioned above. + +它[包括](#include)以下内容: + +``` +include: + - template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml' +``` + +### `include`[](#include "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 10.5 中引入. +* 自 10.6 开始适用于 Starter,Premium 和 Ultimate. +* 在 11.4 中[移至](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/42861) GitLab Core. + +使用`include`关键字允许包含外部 YAML 文件. 这有助于将 CI / CD 配置分解为多个文件,并提高了长配置文件的可读性. 也可以将模板文件存储在中央存储库中,并且项目包括其配置文件. 这有助于避免重复配置,例如,所有项目的全局默认变量. + +`include`要求外部 YAML 文件具有扩展名`.yml`或`.yaml` ,否则将不包含外部文件. + +`include`支持以下包含方法: + +| Method | Description | +| --- | --- | +| [`local`](#includelocal) | 包括来自本地项目存储库的文件. | +| [`file`](#includefile) | 包括来自其他项目存储库的文件. | +| [`remote`](#includeremote) | 包括来自远程 URL 的文件. 必须公开可用. | +| [`template`](#includetemplate) | 包括由 GitLab 提供的模板. | + +`include`方法不支持[变量扩展](../variables/where_variables_can_be_used.html#variables-usage) . + +**注意:**所有方法包含的`.gitlab-ci.yml`配置在创建管道时进行评估. 该配置是及时的快照,并保留在数据库中. 在创建下一个管道之前,对引用的`.gitlab-ci.yml`配置的任何更改都不会反映在 GitLab 中. + +`include`定义的文件是: + +* 与`.gitlab-ci.yml`那些合并. +* 无论`include`关键字的位置如何,始终首先评估并与`.gitlab-ci.yml`的内容合并. + +**提示:**使用合并功能可以自定义和覆盖包含本地定义的 CI / CD 配置. `.gitlab-ci.yml`本地定义将覆盖包含的定义.**注意:**不支持在`include`来源的不同 YAML 文件中使用[YAML 锚](#anchors) . 您只能引用同一文件中的锚. 除了使用 YAML 定位符,您还可以使用[`extends`关键字](#extends) . + +#### `include:local`[](#includelocal "Permalink") + +`include:local`包含与`.gitlab-ci.yml`位于同一存储库中的文件. 使用相对于根目录( `/` )的完整路径进行引用. + +您只能在配置文件所在的同一分支上使用 Git 当前跟踪的文件. 换句话说,使用`include:local` ,请确保`.gitlab-ci.yml`和本地文件都在同一分支上. + +所有[嵌套的包含](#nested-includes)将在同一项目的范围内执行,因此可以使用本地,项目,远程或模板包含. + +**注意:**不支持通过 Git 子模块路径包含本地文件. + +Example: + +``` +include: + - local: '/templates/.gitlab-ci-template.yml' +``` + +**Tip:** Local includes can be used as a replacement for symbolic links which are not followed. + +可以将其定义为简短的本地包含: + +``` +include: '.gitlab-ci-production.yml' +``` + +#### `include:file`[](#includefile "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53903) . + +要在同一 GitLab 实例下包含来自另一个私有项目的`include:file` ,请使用`include:file` . 使用相对于根目录( `/` )的完整路径引用该文件. 例如: + +``` +include: + - project: 'my-group/my-project' + file: '/templates/.gitlab-ci-template.yml' +``` + +您还可以指定`ref` ,默认值为项目的`HEAD` : + +``` +include: + - project: 'my-group/my-project' + ref: master + file: '/templates/.gitlab-ci-template.yml' + + - project: 'my-group/my-project' + ref: v1.0.0 + file: '/templates/.gitlab-ci-template.yml' + + - project: 'my-group/my-project' + ref: 787123b47f14b552955ca2786bc9542ae66fee5b # Git SHA + file: '/templates/.gitlab-ci-template.yml' +``` + +所有[嵌套的包含](#nested-includes)将在目标项目的范围内执行,因此可以使用本地(相对于目标项目),项目,远程或模板包含. + +#### `include:remote`[](#includeremote "Permalink") + +`include:remote`可用于通过 HTTP / HTTPS 包含来自其他位置的文件,并使用完整 URL 进行引用. 远程文件必须可以通过简单的 GET 请求公开访问,因为不支持远程 URL 中的身份验证模式. 例如: + +``` +include: + - remote: 'https://gitlab.com/awesome-project/raw/master/.gitlab-ci-template.yml' +``` + +所有[嵌套的 include](#nested-includes)将在没有上下文的情况下作为公共用户执行,因此仅允许另一个远程或公共项目或模板. + +#### `include:template`[](#includetemplate "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53445) . + +`include:template`可用于包含[GitLab 随附的](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates) `.gitlab-ci.yml`模板. + +例如: + +``` +# File sourced from GitLab's template collection +include: + - template: Auto-DevOps.gitlab-ci.yml +``` + +Multiple `include:template` files: + +``` +include: + - template: Android-Fastlane.gitlab-ci.yml + - template: Auto-DevOps.gitlab-ci.yml +``` + +所有[嵌套的包含](#nested-includes)将仅在用户许可下执行,因此可以使用项目,远程或模板包含. + +#### Nested includes[](#nested-includes "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/56836) . + +嵌套包含可让您组成一组包含. + +总共允许 100 个 include,但是重复的 include 被视为配置错误. + +从[GitLab 12.4 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/28212) ,解析所有文件的时间限制为 30 秒. + +#### Additional `includes` examples[](#additional-includes-examples "Permalink") + +有可用的[其他`includes`示例](includes.html)列表. + +## Parameter details[](#parameter-details "Permalink") + +以下是用于配置 CI / CD 管道的参数的详细说明. + +### `image`[](#image "Permalink") + +用于指定要用于作业[的 Docker 映像](../docker/using_docker_images.html#what-is-an-image) . + +For: + +* Simple definition examples, see [Define `image` and `services` from `.gitlab-ci.yml`](../docker/using_docker_images.html#define-image-and-services-from-gitlab-ciyml). +* 详细的使用信息,请参阅[Docker 集成](../docker/README.html)文档. + +#### `image:name`[](#imagename "Permalink") + +An [extended Docker configuration option](../docker/using_docker_images.html#extended-docker-configuration-options). + +有关更多信息,请参阅[`image`可用设置](../docker/using_docker_images.html#available-settings-for-image) . + +#### `image:entrypoint`[](#imageentrypoint "Permalink") + +An [extended Docker configuration option](../docker/using_docker_images.html#extended-docker-configuration-options). + +有关更多信息,请参阅[`image`可用设置](../docker/using_docker_images.html#available-settings-for-image) . + +#### `services`[](#services "Permalink") + +用于指定[服务 Docker 映像](../docker/using_docker_images.html#what-is-a-service) ,该映像链接到 image 中指定的基本[`image`](#image) . + +For: + +* 简单的定义示例,请参阅[从`.gitlab-ci.yml`定义`image`和`services`](../docker/using_docker_images.html#define-image-and-services-from-gitlab-ciyml) . +* 详细的使用信息,请参阅[Docker 集成](../docker/README.html)文档. +* 有关示例服务,请参见[GitLab CI / CD 服务](../services/README.html) . + +##### `services:name`[](#servicesname "Permalink") + +An [extended Docker configuration option](../docker/using_docker_images.html#extended-docker-configuration-options). + +For more information, see [Available settings for `services`](../docker/using_docker_images.html#available-settings-for-services). + +##### `services:alias`[](#servicesalias "Permalink") + +An [extended Docker configuration option](../docker/using_docker_images.html#extended-docker-configuration-options). + +有关更多信息,请参阅[`services`可用设置](../docker/using_docker_images.html#available-settings-for-services) . + +##### `services:entrypoint`[](#servicesentrypoint "Permalink") + +An [extended Docker configuration option](../docker/using_docker_images.html#extended-docker-configuration-options). + +有关更多信息,请参阅[`services`可用设置](../docker/using_docker_images.html#available-settings-for-services) . + +##### `services:command`[](#servicescommand "Permalink") + +An [extended Docker configuration option](../docker/using_docker_images.html#extended-docker-configuration-options). + +有关更多信息,请参阅[`services`可用设置](../docker/using_docker_images.html#available-settings-for-services) . + +### `script`[](#script "Permalink") + +`script`是作业所需的唯一必需关键字. 这是一个由 Runner 执行的 shell 脚本. 例如: + +``` +job: + script: "bundle exec rspec" +``` + +[脚本的 YAML 锚](#yaml-anchors-for-script)可用. + +此参数还可以包含使用数组的多个命令: + +``` +job: + script: + - uname -a + - bundle exec rspec +``` + +**注意:**有时, `script`命令将需要用单引号或双引号引起来. 例如,包含冒号命令( `:` )需要加引号,以便被包裹的 YAML 解析器知道来解释整个事情作为一个字符串,而不是一个"键:值"对. 使用特殊字符时要小心: `:` , `{` , `}` , `[` , `]` , `,` , `&` , `*` , `#` , `?` , `|` , `-` , `<` , `>` , `=` `!` , `%` , `@` , ``` . + +如果任何脚本命令返回的退出代码都不为零,则该作业将失败,并且其他命令将不再执行. 通过将退出代码存储在变量中,可以避免此行为: + +``` +job: + script: + - false || exit_code=$? + - if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi; +``` + +#### `before_script` and `after_script`[](#before_script-and-after_script "Permalink") + +在 GitLab 8.7 中引入,需要 GitLab Runner v1.2. + +`before_script`用于定义一个命令,该命令应在每个作业(包括部署作业)之前,但在还原任何[工件之后运行](#artifacts) . 这必须是一个数组. + +`before_script`中指定的[`script`](#script)与主脚本中指定的任何脚本串联在一起,并在单个 shell 中一起执行. + +`after_script`用于定义将在每个作业(包括失败的作业)之后运行的命令. 这必须是一个数组. + +`after_script`中指定的脚本在新的 shell 中执行,与任何`before_script`或`script`脚本分开. 结果,他们: + +* 将当前工作目录设置回默认目录. +* 无法访问由`before_script`或`script`定义的脚本完成的更改,包括: + * `script`脚本中导出的命令别名和变量. + * 在工作树之外进行更改(取决于 Runner 执行程序),例如`before_script`或`script`脚本安装的软件. +* 有一个单独的超时,硬编码为 5 分钟. 有关详细信息,请参见[相关问题](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2716) . +* 不要影响作业的退出代码. 如果`script`部分成功并且`after_script`超时或失败,则该作业将以代码`0` ( `Job Succeeded` )退出. + +如果按工作设置全局定义的`before_script`或`after_script`则有可能覆盖它: + +``` +default: + before_script: + - global before script + +job: + before_script: + - execute this instead of global before script + script: + - my command + after_script: + - execute this after my script +``` + +[YAML anchors for `before_script` and `after_script`](#yaml-anchors-for-before_script-and-after_script) are available. + +#### Coloring script output[](#coloring-script-output "Permalink") + +脚本输出可以使用[ANSI 转义码](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors)或运行输出 ANSI 转义码的命令或程序来着色. + +例如,使用[带有颜色代码的 Bash](https://misc.flogisoft.com/bash/tip_colors_and_formatting) : + +``` +job: + script: + - echo -e "\e[31mThis text is red,\e[0m but this text isn't\e[31m however this text is red again." +``` + +您可以在 Shell 变量甚至[自定义环境变量中](../variables/README.html#custom-environment-variables)定义颜色代码,这使命令更易于阅读和重用. + +例如,使用与上述相同的示例以及在`before_script`定义的变量: + +``` +job: + before_script: + - TXT_RED="\e[31m" && TXT_CLEAR="\e[0m" + script: + - echo -e "${TXT_RED}This text is red,${TXT_CLEAR} but this part isn't${TXT_RED} however this part is again." + - echo "This text is not colored" +``` + +或使用[PowerShell 颜色代码](https://superuser.com/a/1259916) : + +``` +job: + before_script: + - $esc="$([char]27)"; $TXT_RED="$esc[31m"; $TXT_CLEAR="$esc[0m" + script: + - Write-Host $TXT_RED"This text is red,"$TXT_CLEAR" but this text isn't"$TXT_RED" however this text is red again." + - Write-Host "This text is not colored" +``` + +#### Multiline commands[](#multiline-commands "Permalink") + +您可以使用[`|`](https://yaml-multiline.info/)将长命令分成多行命令以提高可读性[`|`](https://yaml-multiline.info/) [(文字)和`>` (折叠)YAML 多行块标量指标](https://yaml-multiline.info/) . + +**警告:**如果将多个命令组合到一个命令字符串中,则只会报告最后一个命令的失败或成功, [错误地忽略了由于 bug 导致的先前命令的失败](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394) . 如果作业的成功取决于这些命令的成功或失败,则可以将命令作为单独的`script:`项目运行,或在需要时将`exit 1`命令添加到适当的命令字符串中. + +您可以使用`|` (文字)YAML 多行块标量指示器,用于在作业描述的`script`部分中的多行上编写命令. 每行都被视为一个单独的命令. 在作业日志中仅重复第一个命令,但仍执行其他命令: + +``` +job: + script: + - | + echo "First command line." + echo "Second command line." + echo "Third command line." +``` + +上面的示例在作业日志中呈现为: + +``` +$ echo First command line # collapsed multi-line command +First command line +Second command line. +Third command line. +``` + +`>` (折叠的)YAML 多行块标量指示符将节之间的空行视为新命令的开始: + +``` +job: + script: + - > + echo "First command line + is split over two lines." + + echo "Second command line." +``` + +这与编写不带`>`或`|`多行命令的行为类似 块标量指标: + +``` +job: + script: + - echo "First command line + is split over two lines." + + echo "Second command line." +``` + +上面的两个示例在作业日志中均显示为: + +``` +$ echo First command line is split over two lines. # collapsed multi-line command +First command line is split over two lines. +Second command line. +``` + +当`>`或`|` 块标量指示符被省略,GitLab 将通过连接非空行来形成命令,因此请确保在连接时行可以运行. + +[此处的](https://en.wikipedia.org/wiki/Here_document) Shell [文件可](https://en.wikipedia.org/wiki/Here_document)与`|` 和`>`运算符. 下面的示例将小写字母音译为大写字母: + +``` +job: + script: + - | + tr a-z A-Z << END_TEXT + one two three + four five six + END_TEXT +``` + +结果是: + +``` +$ tr a-z A-Z << END_TEXT # collapsed multi-line command + ONE TWO THREE + FOUR FIVE SIX +``` + +### `stage`[](#stage "Permalink") + +`stage`是按职位定义的,并且依赖于全局定义的[`stages`](#stages) . 它允许将作业分为不同的阶段,并且同一`stage`作业可以并行执行(取决于[特定条件](#using-your-own-runners) ). 例如: + +``` +stages: + - build + - test + - deploy + +job 0: + stage: .pre + script: make something useful before build stage + +job 1: + stage: build + script: make build dependencies + +job 2: + stage: build + script: make build artifacts + +job 3: + stage: test + script: make test + +job 4: + stage: deploy + script: make deploy + +job 5: + stage: .post + script: make something useful at the end of pipeline +``` + +#### Using your own Runners[](#using-your-own-runners "Permalink") + +使用自己的 Runners 时,默认情况下,GitLab Runner 一次仅运行一个作业(有关更多信息,请参见[Runner 全局设置中](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)的`concurrent`标志). + +仅在以下情况下,作业将在您自己的跑步者上并行运行: + +* Run on different Runners. +* 跑步者的`concurrent`设置已更改. + +#### `.pre` and `.post`[](#pre-and-post "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31441) . + +每个管道均可使用以下阶段: + +* `.pre` ,它始终是管道中的第一阶段. +* `.post` ,它始终是管道中的最后一个阶段. + +用户定义的阶段在`.pre`之后和`.post`之前执行. + +即使`.gitlab-ci.yml`定义不正确, `.pre`和`.post`的顺序也无法更改. 例如,以下是等效配置: + +* 按顺序配置: + + ``` + stages: + - .pre + - a + - b + - .post + ``` + +* 配置乱序: + + ``` + stages: + - a + - .pre + - b + - .post + ``` + +* 未明确配置: + + ``` + stages: + - a + - b + ``` + +**Note:** A pipeline won’t be created if it only contains jobs in `.pre` or `.post` stages. + +### `extends`[](#extends "Permalink") + +在 GitLab 11.3 中引入. + +`extends`定义使用`extends`的作业将要继承的条目名称. + +它是使用[YAML 锚点](#anchors)的替代方法,并且更具灵活性和可读性: + +``` +.tests: + script: rake test + stage: test + only: + refs: + - branches + +rspec: + extends: .tests + script: rake rspec + only: + variables: + - $RSPEC +``` + +在上面的示例中, `rspec`作业继承自`.tests`模板作业. GitLab 将基于密钥执行反向深度合并. GitLab 将: + +* Merge the `rspec` contents into `.tests` recursively. +* 不合并键的值. + +这将导致以下`rspec`作业: + +``` +rspec: + script: rake rspec + stage: test + only: + refs: + - branches + variables: + - $RSPEC +``` + +**注意:**请注意, `script: rake test`已被`script: rake rspec`覆盖. + +如果您确实希望包含`rake test` ,请参见[`before_script`和`after_script`](#before_script-and-after_script) . + +在此示例中, `.tests`是[隐藏作业](#hide-jobs) ,但是也可以从常规作业继承. + +`extends`支持多级继承,但是不建议使用三个以上级别. 支持的最大嵌套级别为 10.以下示例具有两个继承级别: + +``` +.tests: + only: + - pushes + +.rspec: + extends: .tests + script: rake rspec + +rspec 1: + variables: + RSPEC_SUITE: '1' + extends: .rspec + +rspec 2: + variables: + RSPEC_SUITE: '2' + extends: .rspec + +spinach: + extends: .tests + script: rake spinach +``` + +在 GitLab 12.0 和更高版本中,还可以使用多个父对象进行`extends` . + +#### Merge details[](#merge-details "Permalink") + +`extends`可以合并哈希,但不能合并数组. 用于合并的算法是"最近的范围获胜",因此来自最后一个成员的键将始终覆盖在其他级别定义的任何内容. 例如: + +``` +.only-important: + variables: + URL: "http://my-url.internal" + IMPORTANT_VAR: "the details" + only: + - master + - stable + tags: + - production + script: + - echo "Hello world!" + +.in-docker: + variables: + URL: "http://docker-url.internal" + tags: + - docker + image: alpine + +rspec: + variables: + GITLAB: "is-awesome" + extends: + - .only-important + - .in-docker + script: + - rake rspec +``` + +这将导致以下`rspec`作业: + +``` +rspec: + variables: + URL: "http://docker-url.internal" + IMPORTANT_VAR: "the details" + GITLAB: "is-awesome" + only: + - master + - stable + tags: + - docker + image: alpine + script: + - rake rspec +``` + +请注意,在上面的示例中: + +* `variables`部分已合并,但`URL: "http://my-url.internal"`已被`URL: "http://docker-url.internal"`覆盖. +* `tags: ['production']`已被`tags: ['docker']`覆盖. +* `script`尚未合并,而是`script: ['echo "Hello world!"']`被`script: ['rake rspec']`覆盖. 可以使用[YAML 锚点](#anchors)合并数组. + +#### Using `extends` and `include` together[](#using-extends-and-include-together "Permalink") + +`extends`配置文件`extends`到`include`配置文件. + +例如,如果您有本地`included.yml`文件: + +``` +.template: + script: + - echo Hello! +``` + +然后,在`.gitlab-ci.yml`您可以像这样使用它: + +``` +include: included.yml + +useTemplate: + image: alpine + extends: .template +``` + +这将运行一个名为`useTemplate`的作业,该作业运行`echo Hello!` 如`.template`作业中所定义,并使用本地作业中所定义的`alpine` Docker 映像. + +### `rules`[](#rules "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27863) . + +`rules`关键字是一种设置作业策略的方法,该策略确定是否将作业添加到管道. + +将按*顺序*评估单个规则子句的列表,直到一个匹配. 匹配后,根据配置将作业包括在管道中或从管道中排除. 如果包含,则作业还会添加[某些属性](#rules-attributes) . + +**注意:** `rules`不能[`only/except`](#onlyexcept-basic)与[`only/except`](#onlyexcept-basic)不能结合使用,因为它是该功能的替代品. 如果尝试执行此操作,则 linter 返回的`key may not be used with rules`错误`key may not be used with rules` . + +#### Rules attributes[](#rules-attributes "Permalink") + +`rules`允许的作业属性是: + +* [`when`](#when) :如果未定义,则默认为`when: on_success` . + * 如果用作`when: delayed` ,则还需要`start_in` . +* [`allow_failure`](#allow_failure) :如果未定义,则默认为`allow_failure: false` . + +如果一个规则的计算结果为 true,并且`when`具有除`never`以外的任何值`when` ,该作业将包括在管道中. + +例如: + +``` +docker build: + script: docker build -t my-image:$CI_COMMIT_REF_SLUG . + rules: + - if: '$CI_COMMIT_BRANCH == "master"' + when: delayed + start_in: '3 hours' + allow_failure: true +``` + +将来可能会将其他作业配置添加到规则中. 如果没有有用的东西,请[打开一个问题](https://gitlab.com/gitlab-org/gitlab/-/issues) . + +#### Rules clauses[](#rules-clauses "Permalink") + +可用的规则子句为: + +| Clause | Description | +| --- | --- | +| [`if`](#rulesif) | 通过评估`if`语句在管道中添加或排除作业. 与[`only:variables`](#onlyvariablesexceptvariables)类似. | +| [`changes`](#ruleschanges) | 根据更改的文件在管道中添加或排除作业. 与[`only:changes`](#onlychangesexceptchanges)相同. | +| [`exists`](#rulesexists) | 根据特定文件的存在在管道中添加或排除作业. | + +Rules are evaluated in order until a match is found. If a match is found, the attributes are checked to see if the job should be added to the pipeline. If no attributes are defined, the defaults are: + +* `when: on_success` +* `allow_failure: false` + +作业已添加到管道中: + +* 如果规则匹配并且具有以下条件`when: on_success` , `when: delayed` `when: on_success`或`when: always` . +* 如果没有规则匹配,但最后一个子句为`when: on_success` , `when: delayed` `when: on_success`或`when: always` (无规则). + +作业未添加到管道: + +* 如果没有规则匹配,并且在以下情况下没有独立的条件`when: on_success` , `when: delayed` `when: on_success`或`when: always` . +* 如果规则匹配,并且具有以下条件`when: never`作为属性. + +例如,使用`if`子句严格限制作业运行的时间: + +``` +job: + script: "echo Hello, Rules!" + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + when: manual + allow_failure: true + - if: '$CI_PIPELINE_SOURCE == "schedule"' +``` + +在此示例中: + +* 如果管道用于合并请求,则第一个规则匹配,并且作业将添加到[合并请求管道](../merge_request_pipelines/index.html) ,其属性为: + * `when: manual` (手动工作) + * `allow_failure: true` (即使未运行手动作业,也允许管道继续运行) +* 如果管道**不是**用于合并请求的,则第一条规则不匹配,并且第二条规则被评估. +* 如果管道是计划的管道,则第二条规则匹配,并将作业添加到计划的管道. 由于未定义任何属性,因此添加了: + * `when: on_success` (默认) + * `allow_failure: false` (默认) +* 在**所有其他情况下** ,没有规则匹配,因此该作业**不会**添加到任何其他管道. + +另外,您可以定义一组规则以在某些情况下排除作业,但在所有其他情况下运行它们: + +``` +job: + script: "echo Hello, Rules!" + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + when: never + - if: '$CI_PIPELINE_SOURCE == "schedule"' + when: never + - when: on_success +``` + +* 如果管道用于合并请求, **则不**会将作业添加到管道. +* 如果管道是计划的管道, **则不**会将作业添加到管道. +* 在**所有其他情况下** ,将使用以下时间将作业添加到管道中`when: on_success` . + +**注意**如果你使用`when: on_success` , `always` ,或`delayed`作为最终的规则,两个同时进行的管道可能会启动. 推送管道和合并请求管道都可以由同一事件触发(对于打开的合并请求,将其推送到源分支). 请参阅[`rules`之间](#differences-between-rules-and-onlyexcept)的[重要区别, `only` / `except`](#differences-between-rules-and-onlyexcept)以获取更多详细信息. + +#### Differences between `rules` and `only`/`except`[](#differences-between-rules-and-onlyexcept "Permalink") + +默认情况下, `only/except`定义的作业不会触发合并请求管道. 您必须`only: merge_requests`明确添加`only: merge_requests` . + +用`rules`定义的作业可以触发所有类型的管道. 您不必显式配置每种类型. + +例如: + +``` +job: + script: "echo This creates double pipelines!" + rules: + - if: '$CUSTOM_VARIABLE == "false"' + when: never + - when: always +``` + +This job does not run when `$CUSTOM_VARIABLE` is false, but it *does* run in **all** other pipelines, including **both** push (branch) and merge request pipelines. With this configuration, every push to an open merge request’s source branch causes duplicated pipelines. Explicitly allowing both push and merge request pipelines in the same job could have the same effect. + +我们建议使用[`workflow: rules`](#workflowrules)来限制允许的管道类型. 仅允许合并请求管道,或仅允许分支管道,可以消除重复的管道. 另外,您也可以使用最终避免重写规则更严格,或`when` ( `always` , `on_success`或`delayed` ). + +另外,我们不建议在同一管道中将`only/except`作业与`rules`作业混合使用. 它可能不会导致 YAML 错误,但是由于`only/except`和`rules`默认行为不同,因此调试确切的执行行为可能会很复杂. + +##### `rules:if`[](#rulesif "Permalink") + +`rules:if`子句通过评估简单的`if`语句来确定是否将作业添加到管道. 如果`if`语句为 true,则将作业包括在管道中或从管道中排除. 用简单的英语, `if`规则可以解释为之一: + +* "如果此规则评估为 true,则添加作业"(默认值). +* "如果该规则评估为 true,则不要添加作业"(通过添加`when: never` ). + +`rules:if`与`only:variables`略有不同,每个规则仅接受一个表达式字符串,而不是它们的数组. 可以使用`&&`或`||`将要求值的任何表达式集组合为一个表达式. ,并使用[变量匹配语法](../variables/README.html#syntax-of-environment-variable-expressions) . + +`if:` clauses are evaluated based on the values of [predefined environment variables](../variables/predefined_variables.html) or [custom environment variables](../variables/README.html#custom-environment-variables). + +例如: + +``` +job: + script: "echo Hello, Rules!" + rules: + - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"' + when: always + - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/' + when: manual + allow_failure: true + - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME' # Checking for the presence of a variable is possible +``` + +有关确定`when`上班的逻辑的一些详细信息: + +* 如果提供的规则都不匹配,则将作业设置为以下`when: never` ,并且不包含在管道中. +* 不带任何条件子句的规则,例如不带`if`或`changes`的`when`或`allow_failure`规则,始终匹配,并且在达到条件时始终使用. +* If a rule matches and has no `when` defined, the rule uses the `when` defined for the job, which defaults to `on_success` if not defined. +* 您可以定义`when`一次按规则,或在一次作业级别,它适用于所有规则. 你不能混用`when`在作业水平`when`的规则. + +对于类似于[`only` / `except`关键字的](#onlyexcept-basic)行为,可以检查`$CI_PIPELINE_SOURCE`变量的值. + +| Value | Description | +| --- | --- | +| `push` | 对于由`git push`事件触发的管道,包括分支和标签. | +| `web` | 对于使用 GitLab UI 中的**"运行管道"**按钮创建的**管道** ,请从项目的**CI / CD>"管道"**部分. | +| `trigger` | For pipelines created by using a trigger token. | +| `schedule` | For [scheduled pipelines](../pipelines/schedules.html). | +| `api` | 对于由[管道 API](../../api/pipelines.html#create-a-new-pipeline)触发的[管道](../../api/pipelines.html#create-a-new-pipeline) . | +| `external` | 使用除 GitLab 以外的 CI 服务时. | +| `pipelines` | 对于通过[将 API 与`CI_JOB_TOKEN`一起使用](../triggers/README.html#when-used-with-multi-project-pipelines)创建的多项目管道. | +| `chat` | 对于使用[GitLab ChatOps](../chatops/README.html)命令创建的管道. | +| `webide` | 对于使用[WebIDE](../../user/project/web_ide/index.html)创建的管道. | +| `merge_request_event` | 对于在创建或更新合并请求时创建的管道. 启用[合并请求管道](../merge_request_pipelines/index.html) , [合并结果管道](../merge_request_pipelines/pipelines_for_merged_results/index.html)和[合并序列所](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)必需. | +| `external_pull_request_event` | 在 GitHub 上创建或更新外部拉取请求时. 有关[外部拉取请求,](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)请参见[管道](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests) . | +| `parent_pipeline` | 对于由具有`rules`的[父/子](../parent_child_pipelines.html)管道触发的[管道](../parent_child_pipelines.html) ,请在子管道配置中使用它,以便可以由父管道触发. | + +例如: + +``` +job: + script: "echo Hello, Rules!" + rules: + - if: '$CI_PIPELINE_SOURCE == "schedule"' + when: manual + allow_failure: true + - if: '$CI_PIPELINE_SOURCE == "push"' +``` + +此示例在以下情况下在计划的管道或推送管道(到分支或标签)中将其作为手动作业运行`when: on_success` (默认). 不会将作业添加到任何其他管道类型. + +另一个例子: + +``` +job: + script: "echo Hello, Rules!" + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + - if: '$CI_PIPELINE_SOURCE == "schedule"' +``` + +本示例将作业作为以下`when: on_success`运行`when: on_success`在[合并请求管道](../merge_request_pipelines/index.html)和计划管道中的`when: on_success`作业. 它不能在任何其他管道类型中运行. + +`if`子句的其他常用变量: + +* `if: $CI_COMMIT_TAG` :是否为标签推送更改. +* `if: $CI_COMMIT_BRANCH` :是否将更改推送到任何分支. +* `if: '$CI_COMMIT_BRANCH == "master"'` :如果将更改推送到`master` . +* `if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'` :如果将更改推送到默认分支(通常是`master` ). 如果在可能具有不同默认分支的多个项目中重用同一配置,则很有用. +* `if: '$CI_COMMIT_BRANCH =~ /regex-expression/'` :如果 commit 分支与正则表达式匹配. +* `if: '$CUSTOM_VARIABLE !~ /regex-expression/'` :如果[自定义变量](../variables/README.html#custom-environment-variables) `CUSTOM_VARIABLE`与正则表达式**不**匹配. +* `if: '$CUSTOM_VARIABLE == "value1"'` :如果自定义变量`CUSTOM_VARIABLE`恰好是`value1` . + +##### `rules:changes`[](#ruleschanges "Permalink") + +要确定是否应将作业添加到管道,请使用`rules: changes`子句检查由 Git push 事件更改的文件. + +`rules: changes`工作方式与[`only: changes`和`except: changes`](#onlychangesexceptchanges) ,接受路径数组. 同样,如果没有 Git 推送事件,则始终返回 true. 它仅应用于分支管道或合并请求管道. + +例如: + +``` +workflow: + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + +docker build: + script: docker build -t my-image:$CI_COMMIT_REF_SLUG . + rules: + - changes: + - Dockerfile + when: manual + allow_failure: true +``` + +在此示例中: + +* [`workflow: rules`](#workflowrules)仅允许用于所有作业的合并请求的管道. +* 如果`Dockerfile`已更改,则将作业作为手动作业添加到管道中,并允许管道继续运行,即使未触发该作业( `allow_failure: true` ). +* 如果`Dockerfile`尚未更改,请不要将作业添加到任何管道(与`when: never`相同). + +##### `rules:exists`[](#rulesexists "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/24021) . + +`exists` accepts an array of paths and will match if any of these paths exist as files in the repository. + +例如: + +``` +job: + script: docker build -t my-image:$CI_COMMIT_REF_SLUG . + rules: + - exists: + - Dockerfile +``` + +您还可以使用全局模式来匹配存储库中任何目录中的多个文件. + +例如: + +``` +job: + script: bundle exec rspec + rules: + - exists: + - spec/**.rb +``` + +**注意:**出于性能原因,使用`exists`与模式限制为 10000 个检查. 第 10000 次检查后,带有图案化球形的规则将始终匹配. + +##### `rules:allow_failure`[](#rulesallow_failure "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30235) . + +您可以在`rules:`使用[`allow_failure: true`](#allow_failure) `rules:`在不停止管道本身的情况下允许作业失败或手动作业等待操作. 所有使用`rules:`作业`rules:`默认为`allow_failure: false`如果`allow_failure:` , `allow_failure: false` . + +规则级`rules:allow_failure`选项将覆盖作业级[`allow_failure`](#allow_failure)选项,并且仅在特定规则触发作业时才应用. + +``` +job: + script: "echo Hello, Rules!" + rules: + - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"' + when: manual + allow_failure: true +``` + +在此示例中,如果第一个规则匹配,则作业将具有以下`when: manual`和`allow_failure: true` . + +#### Complex rule clauses[](#complex-rule-clauses "Permalink") + +要使`if` , `changes`和`exists`子句与 AND 结合在一起,请在同一规则中使用它们. + +在以下示例中: + +* 如果`Dockerfile`或`Dockerfile` `docker/scripts/`任何文件已更改并且`$VAR == "string value"`我们将手动运行作业. +* 否则,该作业将不会包含在管道中. + +``` +docker build: + script: docker build -t my-image:$CI_COMMIT_REF_SLUG . + rules: + - if: '$VAR == "string value"' + changes: # Will include the job and set to when:manual if any of the follow paths match a modified file. + - Dockerfile + - docker/scripts/* + when: manual + # - when: never would be redundant here, this is implied any time rules are listed. +``` + +当前`only`可用于/ `except`关键字(例如`branches`或`refs`在`rules`尚不可用,因为在这种情况下,它们的用法和行为被单独考虑. 我们将在[史诗](https://gitlab.com/groups/gitlab-org/-/epics/2783)中讨论未来的关键字改进, [以改进`rules`](https://gitlab.com/groups/gitlab-org/-/epics/2783) ,任何人都可以添加建议或请求. + +### `only`/`except` (basic)[](#onlyexcept-basic "Permalink") + +**注意:** [`rules`](#rules)语法是一种改进的功能更强大的解决方案,用于定义作业何时运行或不运行. 考虑使用`rules`而不是`only/except`来最大程度地利用管道. + +`only`和`except`是用于设置作业策略以限制创建作业时间的两个参数: + +1. `only` defines the names of branches and tags for which the job will run. +2. `except`定义将**不**运行作业的分支和标签的名称. + +有一些适用于作业策略的规则: + +* `only`且`except` . 如果作业规范中同时定义了`only`和`except` ,则 ref 将被`only`和`except`过滤. +* `only`且`except`允许使用正则表达式( [受支持的 regexp 语法](#supported-onlyexcept-regexp-syntax) ). +* `only`且`except`允许指定存储库路径以过滤派生作业. + +此外, `only`和`except`允许使用特殊关键字: + +| **Value** | **Description** | +| --- | --- | +| `branches` | 当管道的 Git 参考是分支时. | +| `tags` | 当管道的 Git 参考是标签时. | +| `api` | 对于由[管道 API](../../api/pipelines.html#create-a-new-pipeline)触发的[管道](../../api/pipelines.html#create-a-new-pipeline) . | +| `external` | 使用除 GitLab 以外的 CI 服务时. | +| `pipelines` | 对于通过将 API 与`CI_JOB_TOKEN`一起使用创建的多项目管道. | +| `pushes` | 对于由`git push`事件触发的管道,包括分支和标签. | +| `schedules` | For [scheduled pipelines](../pipelines/schedules.html). | +| `triggers` | 对于使用触发令牌创建的管道. | +| `web` | 对于使用 GitLab UI 中的**"运行管道"**按钮创建的**管道** ,请从项目的**CI / CD>"管道"**部分. | +| `merge_requests` | 对于在创建或更新合并请求时创建的管道. 启用[合并请求管道](../merge_request_pipelines/index.html) , [合并结果管道](../merge_request_pipelines/pipelines_for_merged_results/index.html)和[合并序列](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html) . | +| `external_pull_requests` | 在 GitHub 上创建或更新[外部拉取请求时](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests) (有关[外部拉取请求,](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)请参见[管道](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests) ). | +| `chat` | 对于使用[GitLab ChatOps](../chatops/README.html)命令创建的管道. | + +在下面的例子中, `job`将只运行了与裁判开始`issue-` ,而所有分支机构将被忽略: + +``` +job: + # use regexp + only: + - /^issue-.*$/ + # use special keyword + except: + - branches +``` + +模式匹配默认情况下区分大小写. 使用`i`标志修饰符,例如`/pattern/i` ,使模式不区分大小写: + +``` +job: + # use regexp + only: + - /^issue-.*$/i + # use special keyword + except: + - branches +``` + +在此示例中, `job`仅对标记了标签的引用运行,或者如果通过 API 触发器或[管道时间表](../pipelines/schedules.html)明确请求构建,则`job`将运行: + +``` +job: + # use special keywords + only: + - tags + - triggers + - schedules +``` + +存储库路径可用于仅对父存储库执行作业,而不能用于派生: + +``` +job: + only: + - branches@gitlab-org/gitlab + except: + - master@gitlab-org/gitlab + - /^release/.*$/@gitlab-org/gitlab +``` + +上面的示例将为`gitlab-org/gitlab`上的所有分支运行`job` ,但`master`和名称以`release/` `gitlab-org/gitlab`分支除外. + +如果作业没有`only`规则,则默认情况下`only: ['branches', 'tags']` . 如果没有`except`规则,则为空. + +例如, + +``` +job: + script: echo 'test' +``` + +转换为: + +``` +job: + script: echo 'test' + only: ['branches', 'tags'] +``` + +#### Regular expressions[](#regular-expressions "Permalink") + +因为`@`用于表示 ref 的存储库路径的开头,所以匹配正则表达式中包含`@`字符的 ref 名称需要使用十六进制字符代码匹配`\x40` . + +正则表达式只能匹配标签或分支名称. 如果给定存储库路径,则始终在字面上匹配. + +如果必须使用正则表达式来匹配标记或分支名称,则模式的整个 ref 名称部分必须是正则表达式,并且必须用`/`括起来. (在结束符`/`之后附加正则表达式标志.)因此`issue-/.*/`不能匹配所有以`issue-`开头的标记名或分支名. + +**提示**使用定位符`^`和`$`避免正则表达式仅匹配标记名称或分支名称的子字符串. 例如, `/^issue-/` `/^issue-.*$/` `/^issue-/`等效于`/^issue-/` `/^issue-.*$/` `/^issue-/` ,而只是`/issue/`也会匹配一个名为`/^issue-.*$/` `severe-issues`的分支. + +#### Supported `only`/`except` regexp syntax[](#supported-onlyexcept-regexp-syntax "Permalink") + +**警告:**这是 GitLab 11.9.4 引入的重大更改. + +在 GitLab 11.9.4 中,GitLab 开始内部将`only`用于参数(参数`except` regexp 转换为[RE2](https://github.com/google/re2/wiki/Syntax) . + +这意味着仅支持[Ruby Regexp](https://ruby-doc.org/core/Regexp.html)提供的功能子集. 由于计算复杂性, [RE2](https://github.com/google/re2/wiki/Syntax)限制了所提供的功能集,这意味着某些功能在 GitLab 11.9.4 中变得不可用. 例如,负面的前瞻. + +For GitLab versions from 11.9.7 and up to GitLab 12.0, GitLab provides a feature flag that can be enabled by administrators that allows users to use unsafe regexp syntax. This brings compatibility with previously allowed syntax version and allows users to gracefully migrate to the new syntax. + +``` +Feature.enable(:allow_unsafe_ruby_regexp) +``` + +### `only`/`except` (advanced)[](#onlyexcept-advanced "Permalink") + +**警告:**这是*Alpha 版*功能,如有更改,恕不另行通知! + +GitLab 支持简单策略和复杂策略,因此可以使用数组和哈希配置方案. + +有四个键可用: + +* `refs` +* `variables` +* `changes` +* `kubernetes` + +如果`only`或`except`下使用多个键,则这些键将被视为单个联合表达式. 那是: + +* `only:`表示"如果所有条件都匹配,则包括此作业". +* `except:`表示"如果任何条件匹配,则排除此工作". + +使用`only` ,各个键在逻辑上由 AND 联接: + +> (任何参考)AND(任何变量)AND(任何变化)AND(如果 Kubernetes 是活动的) + +在下面的示例中, `only`在满足以下**所有条件** `only`创建`test`作业: + +* 该管道已被[调度](../../user/project/pipelines/schedules.html) **或**正在`master`管道运行. +* `variables`关键字匹配. +* `kubernetes`服务在项目上处于活动状态. + +``` +test: + script: npm run test + only: + refs: + - master + - schedules + variables: + - $CI_COMMIT_MESSAGE =~ /run-end-to-end-tests/ + kubernetes: active +``` + +`except`被实现为对此完整表达式的否定: + +> NOT((任何参考)AND(任何变量)AND(任何变化)AND(如果 Kubernetes 处于活动状态)) + +This means the keys are treated as if joined by an OR. This relationship could be described as: + +> (任何参考)或(任何变量)或(任何变化)或(如果 Kubernetes 处于活动状态) + +在以下示例中,如果满足以下**任一条件** ,则**不会**创建`test`作业: + +* 该管道的运行`master` . +* 存储库的根目录中的`README.md`文件进行了更改. + +``` +test: + script: npm run test + except: + refs: + - master + changes: + - "README.md" +``` + +#### `only:refs`/`except:refs`[](#onlyrefsexceptrefs "Permalink") + +GitLab 10.0 中引入的`refs`策略. + +`refs`策略可以采用与[简化的 only / except 配置](#onlyexcept-basic)相同的值. + +在下面的示例中,仅在`master`分支[计划](../pipelines/schedules.html)或运行管道时才创建`deploy`作业: + +``` +deploy: + only: + refs: + - master + - schedules +``` + +#### `only:kubernetes`/`except:kubernetes`[](#onlykubernetesexceptkubernetes "Permalink") + +GitLab 10.0 中引入的`kubernetes`策略. + +The `kubernetes` strategy accepts only the `active` keyword. + +在下面的示例中,仅当项目中的 Kubernetes 服务处于活动状态时,才将创建`deploy`作业: + +``` +deploy: + only: + kubernetes: active +``` + +#### `only:variables`/`except:variables`[](#onlyvariablesexceptvariables "Permalink") + +GitLab 10.7 中引入了`variables`策略. + +`variables`关键字用于定义变量表达式. 换句话说,您可以使用预定义变量/项目/组或环境范围的变量来定义 GitLab 将要评估的表达式,以决定是否应创建作业. + +使用变量表达式的示例: + +``` +deploy: + script: cap staging deploy + only: + refs: + - branches + variables: + - $RELEASE == "staging" + - $STAGING +``` + +另一个用例是根据提交消息排除作业: + +``` +end-to-end: + script: rake test:end-to-end + except: + variables: + - $CI_COMMIT_MESSAGE =~ /skip-end-to-end-tests/ +``` + +了解有关[变量表达式的](../variables/README.html#environment-variables-expressions)更多信息. + +#### `only:changes`/`except:changes`[](#onlychangesexceptchanges "Permalink") + +`changes` GitLab 11.4 中[引入的](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/19232)策略. + +利用`changes`与关键字`only`或`except`能够基于通过推送操作事件被修改的文件定义,如果一个工作应该被创建. + +这意味着`only:changes`策略对以下情况的管道很有用: + +* `$CI_PIPELINE_SOURCE == 'push'` +* `$CI_PIPELINE_SOURCE == 'merge_request_event'` +* `$CI_PIPELINE_SOURCE == 'external_pull_request_event'` + +如果没有 Git 推送事件(例如,对于具有[上述三个之外的源的](../variables/predefined_variables.html)管道),则`changes`无法确定给定文件是新文件还是旧文件,并且始终返回 true. + +`only: changes`使用的一个基本示例`only: changes` : + +``` +docker build: + script: docker build -t my-image:$CI_COMMIT_REF_SLUG . + only: + changes: + - Dockerfile + - docker/scripts/* + - dockerfiles/**/* + - more_scripts/*.{rb,py,sh} +``` + +在上述场景中,当将提交推送到 GitLab 中的现有分支时,它会创建并触发`docker build`作业,只要其中一个提交包含对以下任何一项的更改: + +* The `Dockerfile` file. +* `docker/scripts/`目录中的任何文件. +* `dockerfiles`目录中的任何文件和子目录. +* `more_scripts`目录中具有`rb` , `py` , `sh`扩展名的`more_scripts`文件. + +**警告:**如果`only:changes`使用`only:changes` [仅允许在管道成功的情况下合并合并请求,则](../../user/project/merge_requests/merge_when_pipeline_succeeds.html#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds)如果不[同时使用`only:merge_requests`](#using-onlychanges-with-pipelines-for-merge-requests)则可能导致不良行为. + +您还可以使用 glob 模式来匹配存储库的根目录或存储库内*任何*目录中的多个文件,但是它们必须用双引号引起来,否则 GitLab 将无法解析`.gitlab-ci.yml` . 例如: + +``` +test: + script: npm run test + only: + changes: + - "*.json" + - "**/*.sql" +``` + +如果在存储库根目录中任何扩展名为`.md`文件中检测到更改,以下示例将跳过`build`作业: + +``` +build: + script: npm run build + except: + changes: + - "*.md" +``` + +**警告:**当[将此功能与*没有*合并请求管道的新分支或标记一起使用](#using-onlychanges-without-pipelines-for-merge-requests)时,需要注意一些要点.**警告:**在[计划的管道上使用此功能](#using-onlychanges-with-scheduled-pipelines)时,需要注意一些要点. + +##### Using `only:changes` with pipelines for merge requests[](#using-onlychanges-with-pipelines-for-merge-requests "Permalink") + +使用[用于合并请求的管道,](../merge_request_pipelines/index.html)可以根据在合并请求中修改的文件来定义要创建的作业. + +为了推断源分支的正确基础 SHA,建议`only: [merge_requests]`将此关键字与`only: [merge_requests]` . 这样,可以从任何进一步的提交中正确计算出文件差异,因此可以在管道中正确测试合并请求中的所有更改. + +例如: + +``` +docker build service one: + script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG . + only: + refs: + - merge_requests + changes: + - Dockerfile + - service-one/**/* +``` + +在上述情况下,如果创建或更新了合并请求,从而更改了`service-one`目录中的文件或`Dockerfile` ,则 GitLab 将创建并触发`Dockerfile` `docker build service one`作业. + +Note that if [pipelines for merge requests](../merge_request_pipelines/index.html) is combined with `only: [change]`, but `only: [merge_requests]` is omitted, there could be unwanted behavior. + +例如: + +``` +docker build service one: + script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG . + only: + changes: + - Dockerfile + - service-one/**/* +``` + +在上面的示例中,管道可能由于对`service-one/**/*`的文件的更改而失败. 然后可以推送更高版本的提交,该提交不包括对该文件的任何更改,但包括对`Dockerfile`更改,并且该管道可以通过,因为它仅测试对`Dockerfile`的更改. GitLab 会检查**最近** **通过的** **管道** ,并且将合并请求显示为可合并,尽管较早的管道失败是由于尚未更正的更改引起的. + +使用此配置时,必须注意检查最新的管道是否正确地纠正了先前管道的任何故障. + +##### Using `only:changes` without pipelines for merge requests[](#using-onlychanges-without-pipelines-for-merge-requests "Permalink") + +如果没有[用于合并请求的](../merge_request_pipelines/index.html)管道,则管道将在与合并请求没有明确关联的分支或标签上运行. 在这种情况下,将使用先前的 SHA 来计算 diff,这等效于`git diff HEAD~` . 这可能会导致某些意外行为,包括: + +* When pushing a new branch or a new tag to GitLab, the policy always evaluates to true. +* 推送新提交时,更改的文件将使用先前的提交作为基础 SHA 进行计算. + +##### Using `only:changes` with scheduled pipelines[](#using-onlychanges-with-scheduled-pipelines "Permalink") + +`only:changes`在[Scheduled 管道中](../pipelines/schedules.html)始终评估为" true". 当计划的管道运行时,所有文件都被视为"已更改". + +### `needs`[](#needs "Permalink") + +版本历史 + +* 在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47063) . +* 在 GitLab 12.3 中, `needs`阵列中的最大作业数从 5 个增加到 50 个. +* 在 GitLab 12.8 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/30631) `needs: []`使作业立即开始. + +`needs:`关键字可无序执行作业,使您可以在`.gitlab-ci.yml`实现有[向无环图](../directed_acyclic_graph/index.html) . + +这样,您无需等待阶段顺序即可运行某些作业,而无需等待其他任务,因此您可以让多个阶段同时运行. + +让我们考虑以下示例: + +``` +linux:build: + stage: build + +mac:build: + stage: build + +lint: + stage: test + needs: [] + +linux:rspec: + stage: test + needs: ["linux:build"] + +linux:rubocop: + stage: test + needs: ["linux:build"] + +mac:rspec: + stage: test + needs: ["mac:build"] + +mac:rubocop: + stage: test + needs: ["mac:build"] + +production: + stage: deploy +``` + +本示例创建四个执行路径: + +* 棉短绒:在`lint`作业将立即运行,而无需等待`build`阶段完成,因为它没有需求( `needs: []` + +* Linux 路径: `linux:build`作业完成后,将立即运行`linux:rspec`和`linux:rubocop`作业,而无需等待`mac:build`完成. + +* macOS 路径: `mac:build`作业完成后,将立即运行`mac:rspec`和`mac:rubocop`作业,而无需等待`linux:build`完成. + +* `production`作业将在所有先前的作业完成后立即执行; 在这种情况下: `linux:build` , `linux:rspec` , `linux:rubocop` , `mac:build` , `mac:rspec` , `mac:rubocop` . + +#### Requirements and limitations[](#requirements-and-limitations "Permalink") + +* 如果`needs:`设置为指向`only/except`因`only/except`规则而未实例化的作业,或者不存在,则创建管道时会出现 YAML 错误. +* `needs:`数组中单个作业可能需要的最大作业数是有限的: + * 对于 GitLab.com,限制为十个. 有关更多信息,请参见[基础结构问题](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7541) . + * 对于自我管理的实例,限制为: + * 10,如果`ci_dag_limit_needs`功能标志已启用(默认). + * 50,如果`ci_dag_limit_needs`功能标记被禁用. +* 如果`needs:`是指标记为" `parallel:`的作业. 当前作业将取决于创建的所有并行作业. +* `needs:`类似于`dependencies:`它需要使用之前阶段的作业,这意味着不可能创建循环依赖关系. 在当前阶段也不可能依赖于工作,但是[已计划了](https://gitlab.com/gitlab-org/gitlab/-/issues/30632)支持. +* 与上述相关,必须为所有具有关键字`needs:`或由一个人引用的作业明确定义阶段. + +##### Changing the `needs:` job limit[](#changing-the-needs-job-limit "Permalink") + +可以在`needs:`定义的最大作业数`needs:`默认为 10,但可以通过功能标志更改为 50\. 要将限制更改为 50,请[启动 Rails 控制台会话](../../administration/troubleshooting/debug.html#starting-a-rails-console-session)并运行: + +``` +Feature::disable(:ci_dag_limit_needs) +``` + +要将其设置回 10,请运行相反的命令: + +``` +Feature::enable(:ci_dag_limit_needs) +``` + +#### Artifact downloads with `needs`[](#artifact-downloads-with-needs "Permalink") + +[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/14311)在 GitLab v12.6. + +在使用`needs` ,可通过`artifacts: true` (默认)或`artifacts: false`来控制工件下载. + +从 GitLab 12.6 开始,您不能将[`dependencies`](#dependencies)关键字与控制作业中工件下载的`needs`结合使用. `dependencies`在不使用`needs`作业中仍然有效. + +在以下示例中, `rspec`作业将下载`build_job`工件,而`rubocop`作业则不会: + +``` +build_job: + stage: build + artifacts: + paths: + - binaries/ + +rspec: + stage: test + needs: + - job: build_job + artifacts: true + +rubocop: + stage: test + needs: + - job: build_job + artifacts: false +``` + +另外,在下面的三个语法示例中, `rspec`作业将从所有三个`build_jobs`下载工件,因为`artifacts`对于`build_job_1`是 true,并且对于`build_job_2`和`build_job_3`都**默认**为 true. + +``` +rspec: + needs: + - job: build_job_1 + artifacts: true + - job: build_job_2 + - build_job_3 +``` + +#### Cross project artifact downloads with `needs`[](#cross-project-artifact-downloads-with-needs-premium "Permalink") + +[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/14311)在 GitLab v12.7. + +`needs`可用于从[同一项目中其他 ref](#artifact-downloads-between-pipelines-in-the-same-project)或不同项目中的管道上的多达五个作业的工件中下载工件: + +``` +build_job: + stage: build + script: + - ls -lhR + needs: + - project: group/project-name + job: build-1 + ref: master + artifacts: true +``` + +`build_job`将从`group/project-name`项目的`master`分支上的最新成功`build-1`作业中下载工件. + +##### Artifact downloads between pipelines in the same project[](#artifact-downloads-between-pipelines-in-the-same-project "Permalink") + +通过将`project`关键字设置为当前项目的名称,并指定引用,可以使用`needs`从当前项目的不同管道中下载工件. 在下面的示例中, `build_job`将使用`other-ref` ref 下载最新成功的`build-1`作业的工件: + +``` +build_job: + stage: build + script: + - ls -lhR + needs: + - project: group/same-project-name + job: build-1 + ref: other-ref + artifacts: true +``` + +**注意:**不支持从[`parallel:`](#parallel)运行的作业中下载工件[`parallel:`](#parallel) + +### `tags`[](#tags "Permalink") + +`tags`用于从允许运行该项目的所有 Runner 列表中选择特定的 Runner. + +在 Runner 的注册过程中,您可以指定 Runner 的标签,例如`ruby` , `postgres` , `development` . + +`tags`可让您为具有指定标签的跑步者运行作业: + +``` +job: + tags: + - ruby + - postgres +``` + +上面的规范将确保`job`由同时定义了`ruby`和`postgres`标签的 Runner 构建. + +标签也是在不同平台上运行不同作业的好方法,例如,给定带有`osx`标签的 OS X Runner 和带有`windows`标签的 Windows Runner,以下作业将在各自的平台上运行: + +``` +windows job: + stage: + - build + tags: + - windows + script: + - echo Hello, %USERNAME%! + +osx job: + stage: + - build + tags: + - osx + script: + - echo "Hello, $USER!" +``` + +### `allow_failure`[](#allow_failure "Permalink") + +`allow_failure`允许作业失败,而不会影响其余 CI 套件. 默认值是`false` ,除了使用`when: manual`语法的[手动](#whenmanual)作业之外,除非使用[`rules:`](#rules)语法,否则所有作业默认为 false, *包括* `when: manual`作业. + +启用后,如果作业失败,该作业将在用户界面中显示橙色警告. 但是,管道的逻辑流程将认为作业成功/通过,并且不会被阻塞. + +假设所有其他作业均成功,则该作业的阶段及其管道将显示相同的橙色警告. 但是,关联的提交将被标记为"通过",而不会发出警告. + +在下面的示例中, `job1`和`job2`将并行运行,但是如果`job1`失败,它不会停止下一阶段的运行,因为它标记有`allow_failure: true` : + +``` +job1: + stage: test + script: + - execute_script_that_will_fail + allow_failure: true + +job2: + stage: test + script: + - execute_script_that_will_succeed + +job3: + stage: deploy + script: + - deploy_to_staging +``` + +### `when`[](#when "Permalink") + +`when`用于实现在发生故障或发生故障时运行的作业. + +`when`可以被设置为以下值中的一个: + +1. `on_success`仅在先前阶段中的所有作业都成功(或因为标记为`allow_failure`而被视为成功)时才执行作业. 这是默认值. +2. `on_failure`仅在`on_failure`中的至少一项作业失败时才执行作业. +3. `always` -执行作业,而不管先前阶段的作业状态如何. +4. `manual` -手动执行作业(在 GitLab 8.10 中已添加). 在下面阅读有关[手动操作的信息](#whenmanual) . +5. `delayed` -一定时间后执行作业(在 GitLab 11.14 中已添加). 在下面阅读有关[延迟动作的信息](#whendelayed) . + +For example: + +``` +stages: + - build + - cleanup_build + - test + - deploy + - cleanup + +build_job: + stage: build + script: + - make build + +cleanup_build_job: + stage: cleanup_build + script: + - cleanup build when failed + when: on_failure + +test_job: + stage: test + script: + - make test + +deploy_job: + stage: deploy + script: + - make deploy + when: manual + +cleanup_job: + stage: cleanup + script: + - cleanup after jobs + when: always +``` + +上面的脚本将: + +1. 仅当`build_job`失败时才执行`cleanup_build_job` . +2. 无论成功与失败,始终执行`cleanup_job`作为管道的最后一步. +3. 允许您从 GitLab 的 UI 手动执行`deploy_job` . + +#### `when:manual`[](#whenmanual "Permalink") + +版本历史 + +* 在 GitLab 8.10 中引入. +* 在 GitLab 9.0 中引入了阻止手动操作. +* GitLab 9.2 中引入了受保护的操作. + +手动操作是一种特殊类型的作业,不会自动执行,需要用户明确启动. 手动操作的示例用法是部署到生产环境. 可以从管道,作业,环境和部署视图开始手动操作. 在[环境文档中](../environments/index.html#configuring-manual-deployments)阅读更多[内容](../environments/index.html#configuring-manual-deployments) . + +手动操作可以是可选的或阻止的. 阻止手动操作将在定义此操作的阶段阻止管道的执行.当有人通过单击*播放*按钮执行阻止手动操作时,可以恢复管道的执行. + +当管道被阻塞时,如果设置了"管道成功时合并",则不会被合并. 阻塞的管道也确实有一种特殊的状态,称为*手动* . 使用`when:manual`语法`when:manual` ,默认情况下手动操作是非阻塞的. 如果要进行手动操作阻止,则必须在`.gitlab-ci.yml`的作业定义中添加`allow_failure: false` . + +可选的手动操作具有`allow_failure: true`默认情况下设置为`allow_failure: true` ,并且它们的状态不影响总体管道状态. 因此,如果手动操作失败,则管道最终将成功. + +**注意:**使用[`rules:`](#rules) , `allow_failure`默认为`false` ,包括手动作业. + +手动操作被视为写操作,因此当用户想要触发操作时,将使用[受保护分支的](../../user/project/protected_branches.html)权限. 换句话说,为了触发分配给正在为其运行管道的分支的手动操作,用户需要具有合并到该分支的能力. 可以使用受保护的环境来更严格地[保护手动部署](#protecting-manual-jobs-premium) ,以防止未经授权的用户运行. + +**注意:同时**使用`when:manual`和`trigger`导致错误`jobs:#{job-name} when should be on_success, on_failure or always` ,因为`when:manual`阻止使用触发器. + +##### Protecting manual jobs[](#protecting-manual-jobs-premium "Permalink") + +可以使用[受保护的环境](../environments/protected_environments.html)来定义授权运行手动作业的用户的精确列表. 通过仅允许与受保护环境关联的用户触发手动作业,可以实现一些特殊用例,例如: + +* 更精确地限制可以部署到环境的人员. +* 使管道能够被阻塞,直到获得批准的用户"批准"为止. + +为此,您必须: + +1. 为作业添加`environment` . 例如: + + ``` + deploy_prod: + stage: deploy + script: + - echo "Deploy to production server" + environment: + name: production + url: https://example.com + when: manual + only: + - master + ``` + +2. 在" [受保护的环境"设置中](../environments/protected_environments.html#protecting-environments) ,选择环境(上面的示例中为`production` ),然后将被授权触发手动作业的用户,角色或组添加到" **允许部署"**列表中. 只有该列表中的人员以及始终能够使用受保护环境的 GitLab 管理员才能触发此手动作业. + +此外,如果通过添加`allow_failure: false`将手动作业定义为阻塞,则直到触发手动作业后,管道的下`allow_failure: false`才会运行. 这可以用作一种方法,使定义的用户列表可以通过触发阻止的手动作业来"批准"后续的管道阶段. + +#### `when:delayed`[](#whendelayed "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51352) . + +延迟的作业用于在一定时间后执行脚本. 如果要避免作业立即进入`pending`状态,此功能很有用. + +您可以使用`start_in`键设置时间段. 除非提供了单位,否则`start_in`键的值是以秒为单位的经过时间. `start_in`键必须小于或等于一周. 有效值的示例包括: + +* `'5'` +* `10 seconds` +* `30 minutes` +* `1 day` +* `1 week` + +当阶段中有延迟的工作时,直到延迟的工作完成,管道才能继续进行. 这意味着该关键字也可以用于在不同阶段之间插入延迟. + +上一阶段完成后,延迟作业的计时器立即启动. 与其他类型的作业类似,延迟的作业计时器不会启动,除非前一个阶段通过. + +以下示例创建一个名为`timed rollout 10%`的作业,该作业在上一阶段完成后 30 分钟执行: + +``` +timed rollout 10%: + stage: deploy + script: echo 'Rolling out 10% ...' + when: delayed + start_in: 30 minutes +``` + +您可以通过单击"停止"来停止延迟作业的活动计时器. ( **计划外** )按钮. 除非您手动执行该作业,否则以后将永远不会执行该作业. + +您可以通过单击" **播放"**按钮立即开始延迟的作业. GitLab Runner 将很快开始您的工作并开始工作. + +### `environment`[](#environment "Permalink") + +版本历史 + +* 在 GitLab 8.9 中引入. +* 您可以阅读有关环境的更多信息,并在[有关环境](../environments/index.html)的[文档中](../environments/index.html)找到更多示例. + +`environment`用于定义作业部署到特定环境. 如果指定了`environment` ,但不存在该名称下的环境,则将自动创建一个新环境. + +以最简单的形式,可以将`environment`关键字定义为: + +``` +deploy to production: + stage: deploy + script: git push production HEAD:master + environment: production +``` + +在上面的示例中,将`deploy to production`作业标记为正在部署到`production`环境. + +#### `environment:name`[](#environmentname "Permalink") + +版本历史 + +* 在 GitLab 8.11 中引入. +* 在 GitLab 8.11 之前,环境的名称可以定义为类似于`environment: production`的字符串`environment: production` . 现在推荐的方法是在`name`关键字下定义它. +* `name`参数可以使用任何已定义的 CI 变量,包括预定义的安全变量和`.gitlab-ci.yml` [`variables`](#variables) . 但是,您不能使用`script`下定义的变量. + +`environment`名称可以包含: + +* letters +* digits +* spaces +* `-` +* `_` +* `/` +* `$` +* `{` +* `}` + +通用名称是`qa` , `staging`和`production` ,但是您可以使用与您的工作流程兼容的任何名称. + +除了在`environment`关键字之后直接定义环境名称之外,还可以将其定义为单独的值. 为此,请在`environment`下使用`name`关键字: + +``` +deploy to production: + stage: deploy + script: git push production HEAD:master + environment: + name: production +``` + +#### `environment:url`[](#environmenturl "Permalink") + +版本历史 + +* 在 GitLab 8.11 中引入. +* 在 GitLab 8.11 之前,只能在 GitLab 的 UI 中添加 URL. 现在推荐的方法是在`.gitlab-ci.yml`定义它. +* `url`参数可以使用任何已定义的 CI 变量,包括预定义的安全变量和`.gitlab-ci.yml` [`variables`](#variables) . 但是,您不能使用`script`下定义的变量. + +这是一个可选值,设置该值时,它将在 GitLab 中的不同位置显示按钮,单击这些按钮会将您带到定义的 URL. + +在下面的示例中,如果作业成功完成,它将在合并请求和环境/部署页面中创建按钮,这些页面将指向`https://prod.example.com` . + +``` +deploy to production: + stage: deploy + script: git push production HEAD:master + environment: + name: production + url: https://prod.example.com +``` + +#### `environment:on_stop`[](#environmenton_stop "Permalink") + +版本历史 + +* 在 GitLab 8.13 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22191) . +* 从 GitLab 8.14 开始,当您具有定义了停止动作的环境时,当删除关联的分支时,GitLab 将自动触发停止动作. + +可以通过在`on_stop`下定义的`on_stop`关键字来实现关闭(停止) `environment` . 它声明运行另一个作业以关闭环境. + +请阅读`environment:action`部分以获取示例. + +#### `environment:action`[](#environmentaction "Permalink") + +在 GitLab 8.13 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22191) . + +`action`关键字将与`on_stop`结合使用,并在调用关闭环境的作业中定义. + +举个例子: + +``` +review_app: + stage: deploy + script: make deploy-app + environment: + name: review/$CI_COMMIT_REF_NAME + url: https://$CI_ENVIRONMENT_SLUG.example.com + on_stop: stop_review_app + +stop_review_app: + stage: deploy + variables: + GIT_STRATEGY: none + script: make delete-app + when: manual + environment: + name: review/$CI_COMMIT_REF_NAME + action: stop +``` + +在上面的例子中,我们建立了`review_app`工作部署到`review`环境,我们还定义了一个新`stop_review_app`下工作`on_stop` . 一旦`review_app`作业成功完成,就会触发`stop_review_app`根据什么下定义的作业`when` . 在这种情况下,我们将其设置为`manual`因此需要通过 GitLab 的 Web 界面进行[手动操作](#whenmanual)才能运行. + +同样在该示例中, `GIT_STRATEGY`设置为`none`以便当[自动触发](../environments/index.html#automatically-stopping-an-environment) `stop_review_app`作业时,删除分支后,GitLab Runner 将不会尝试检出代码. + +**注意:**上面的示例覆盖了全局变量. 如果停止环境作业依赖于全局变量,则可以在设置`GIT_STRATEGY`时使用[锚变量](#yaml-anchors-for-variables)来更改它,而不覆盖全局变量. + +**需要** `stop_review_app`作业定义以下关键字: + +* `when` - [reference](#when) +* `environment:name` +* `environment:action` + +此外,两个作业都应具有匹配的[`rules`](../yaml/README.html#onlyexcept-basic)或[`only/except`](../yaml/README.html#onlyexcept-basic)配置[`only/except`](../yaml/README.html#onlyexcept-basic) . 在上面的示例中,如果配置不同,则`stop_review_app`作业可能未包含在所有包含`review_app`作业的管道中,并且将无法触发该`action: stop`以自动停止环境. + +#### `environment:auto_stop_in`[](#environmentauto_stop_in "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/20956) . + +`auto_stop_in`关键字用于指定环境的生命周期,当 GitLab 过期时,它将自动停止它们. + +例如, + +``` +review_app: + script: deploy-review-app + environment: + name: review/$CI_COMMIT_REF_NAME + auto_stop_in: 1 day +``` + +当执行`review_app`作业并创建评论应用程序时,环境的生命周期设置为`1 day` . + +有关更多信息,请参见[环境自动停止文档.](../environments/index.html#environments-auto-stop) + +#### `environment:kubernetes`[](#environmentkubernetes "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) . + +`kubernetes`块用于将部署配置为与您的项目关联的[Kubernetes 集群](../../user/project/clusters/index.html) . + +例如: + +``` +deploy: + stage: deploy + script: make deploy-app + environment: + name: production + kubernetes: + namespace: production +``` + +这将使用`production` [Kubernetes 名称空间](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)设置`deploy`作业以部署到`production`环境. + +有关更多信息,请参阅[`kubernetes`可用设置](../environments/index.html#configuring-kubernetes-deployments) . + +**注意:** [由 GitLab 管理的](../../user/project/clusters/index.html#gitlab-managed-clusters) Kubernetes 集群不支持 Kubernetes 配置. 要跟踪对 GitLab 管理的集群的支持进度,请参阅[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/38054) . + +#### Dynamic environments[](#dynamic-environments "Permalink") + +版本历史 + +* 在 GitLab 8.12 和 GitLab Runner 1.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21971) . +* `$CI_ENVIRONMENT_SLUG`是在 GitLab 8.15 中[引入的](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22864) . +* `name`和`url`参数可以使用任何已定义的 CI 变量,包括预定义的安全变量和`.gitlab-ci.yml` [`variables`](#variables) . 但是,您不能使用`script`下定义的变量. + +例如: + +``` +deploy as review app: + stage: deploy + script: make deploy + environment: + name: review/$CI_COMMIT_REF_NAME + url: https://$CI_ENVIRONMENT_SLUG.example.com/ +``` + +`deploy as review app`作业将被标记为部署,以动态创建`review/$CI_COMMIT_REF_NAME`环境,其中`$CI_COMMIT_REF_NAME`是 Runner 设置的[环境变量](../variables/README.html) . `$CI_ENVIRONMENT_SLUG`变量基于环境名称,但适合包含在 URL 中. 在这种情况下,如果" `deploy as review app`作业在名为`pow`的分支中运行,则可以使用`https://review-pow.example.com/`类的 URL 访问此环境. + +当然,这意味着托管应用程序的基础服务器已正确配置. + +常见的用例是为分支创建动态环境并将其用作 Review Apps. 您可以在[https://gitlab.com/gitlab-examples/review-apps-nginx/上](https://gitlab.com/gitlab-examples/review-apps-nginx/)查看使用 Review Apps 的简单示例. + +### `cache`[](#cache "Permalink") + +版本历史 + +* 在 GitLab Runner v0.7.0 中引入. +* `cache`可以全局设置,也可以按作业设置. +* 从 GitLab 9.0 起,默认情况下启用缓存并在管道和作业之间共享缓存. +* 从 GitLab 9.2 起,缓存将在[工件](#artifacts)之前恢复. + +**了解更多信息:**阅读缓存工作原理,并在[缓存依赖文档中](../caching/index.html)找到一些好的做法. + +`cache`用于指定应在作业之间缓存的文件和目录的列表. 您只能使用本地工作副本中的路径. + +如果在作业范围之外定义了`cache` ,则意味着已全局设置`cache` ,并且所有作业都将使用该定义. + +#### `cache:paths`[](#cachepaths "Permalink") + +使用`paths`指令选择要缓存的文件或目录. 路径是相对于项目目录( `$CI_PROJECT_DIR` )的,不能直接链接到其外部. 可以使用遵循[通配符](https://en.wikipedia.org/wiki/Glob_(programming))模式的[通配符,](https://en.wikipedia.org/wiki/Glob_(programming))并且: + +* 在[GitLab Runner 13.0](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620)和更高版本中,请选择[`doublestar.Glob`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#Match) . +* 在 GitLab Runner 12.10 及更早版本中, [`filepath.Match`](https://pkg.go.dev/path/filepath/#Match) . + +将所有文件缓存在以`.apk`和`.config`文件结尾的`binaries`文件中: + +``` +rspec: + script: test + cache: + paths: + - binaries/*.apk + - .config +``` + +本地定义的缓存将覆盖全局定义的选项. 以下`rspec`作业将仅缓存`binaries/` : + +``` +cache: + paths: + - my/files + +rspec: + script: test + cache: + key: rspec + paths: + - binaries/ +``` + +请注意,由于缓存是在作业之间共享的,因此如果您为不同的作业使用不同的路径,则还应该设置不同的**cache:key,**否则缓存内容可能会被覆盖. + +#### `cache:key`[](#cachekey "Permalink") + +在 GitLab Runner v1.0.0 中引入. + +由于缓存是在作业之间共享的,因此如果您为不同的作业使用不同的路径,则还应该设置不同的`cache:key`否则缓存内容可能会被覆盖. + +`key`指令允许您定义作业之间的缓存相似性,从而允许为所有作业使用单个缓存,按作业缓存,按分支缓存或适合您工作流程的任何其他方式. 这样,您可以微调缓存,从而允许您在不同作业甚至不同分支之间缓存数据. + +`cache:key`变量可以使用任何[预定义的变量](../variables/README.html) ,并且默认键(如果未设置)只是文字`default` ,这意味着从 GitLab 9.0 开始,默认情况下所有内容都在管道和作业之间共享. + +**注意:** `cache:key`变量不能包含`/`字符或等效的 URI 编码的`/` ; 也禁止仅由点( `.` , `.` )组成的值. + +例如,要启用每分支缓存: + +``` +cache: + key: "$CI_COMMIT_REF_SLUG" + paths: + - binaries/ +``` + +如果使用**Windows Batch**运行 Shell 脚本,则需要将`$`替换`$` `%` : + +``` +cache: + key: "%CI_COMMIT_REF_SLUG%" + paths: + - binaries/ +``` + +##### `cache:key:files`[](#cachekeyfiles "Permalink") + +[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/18986)在 GitLab v12.5. + +The `cache:key:files` keyword extends the `cache:key` functionality by making it easier to reuse some caches, and rebuild them less often, which will speed up subsequent pipeline runs. + +当包含`cache:key:files` ,还必须列出将用于生成密钥的项目文件,最多两个文件. 缓存`key`将是根据更改给定文件的最新提交(最多两个,如果列出了两个文件)计算出的 SHA 校验和. 如果在任何提交中都没有更改文件,则后备密钥将为`default` . + +``` +cache: + key: + files: + - Gemfile.lock + - package.json + paths: + - vendor/ruby + - node_modules +``` + +在此示例中,我们将为 Ruby 和 Node.js 依赖关系创建一个缓存,该缓存与`Gemfile.lock`和`package.json`文件的当前版本相关`Gemfile.lock` . 只要这些文件之一发生更改,就会计算新的缓存键并创建新的缓存. 任何将来的作业都使用相同的`Gemfile.lock`和`package.json`和`cache:key:files`将使用新的缓存,而不是重建依赖关系. + +##### `cache:key:prefix`[](#cachekeyprefix "Permalink") + +[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/18986)在 GitLab v12.5. + +`prefix`参数通过允许密钥由给定的`prefix`与为`cache:key:files`计算的 SHA 组合而成,从而为`key:files`添加了额外的功能. 例如,添加`test`的`prefix`将导致键看起来像: `test-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5` . 如果在任何提交中都未更改两个文件,则将前缀添加到`default` ,因此示例中的键将为`test-default` . + +像`cache:key`一样, `prefix`可以使用任何[预定义的变量](../variables/README.html) ,但是不允许以下操作: + +* `/`字符(或等效的 URI 编码的`/` ) +* 仅由组成的值`.` (或等效的 URI 编码的`.` ) + +``` +cache: + key: + files: + - Gemfile.lock + prefix: ${CI_JOB_NAME} + paths: + - vendor/ruby + +rspec: + script: + - bundle exec rspec +``` + +例如,添加`$CI_JOB_NAME` `prefix`将使密钥看起来像: `rspec-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5` ,并且作业缓存在不同分支之间共享. 如果分支更改`Gemfile.lock` ,则该分支将为`cache:key:files`具有新的 SHA 校验和. 将生成一个新的缓存密钥,并为该密钥创建一个新的缓存. 如果未找到`Gemfile.lock` ,则将前缀添加到`default` ,因此示例中的键将为`rspec-default` . + +#### `cache:untracked`[](#cacheuntracked "Permalink") + +设置`untracked: true`以缓存 Git 存储库中所有未跟踪的文件: + +``` +rspec: + script: test + cache: + untracked: true +``` + +缓存所有 Git 未跟踪的文件和`binaries` : + +``` +rspec: + script: test + cache: + untracked: true + paths: + - binaries/ +``` + +#### `cache:policy`[](#cachepolicy "Permalink") + +在 GitLab 9.4 中引入. + +缓存作业的默认行为是在执行开始时下载文件,然后在结束时重新上传文件. 这样可以将作业所做的任何更改保留下来,以备将来运行,这被称为" `pull-push`缓存策略. + +如果您知道该作业不会更改缓存的文件,则可以通过设置`policy: pull`来跳过上载步骤`policy: pull`插入作业规范. 通常,这会在较早的阶段与普通的缓存作业结合在一起,以确保不时更新缓存: + +``` +stages: + - setup + - test + +prepare: + stage: setup + cache: + key: gems + paths: + - vendor/bundle + script: + - bundle install --deployment + +rspec: + stage: test + cache: + key: gems + paths: + - vendor/bundle + policy: pull + script: + - bundle exec rspec ... +``` + +这有助于加快作业执行速度并减少缓存服务器上的负载,尤其是当您有大量并行使用缓存的作业时. + +此外,如果您有一项作业无条件地重新创建了高速缓存而不参考其先前的内容,则可以使用`policy: push`该作业以跳过下载步骤. + +### `artifacts`[](#artifacts "Permalink") + +版本历史 + +* 在非 Windows 平台的 GitLab Runner v0.7.0 中引入. +* Windows 支持已在 GitLab Runner v.1.0.0 中添加. +* 从 GitLab 9.2 起,缓存将在工件之前恢复. +* 并非所有执行程序都[受支持](https://docs.gitlab.com/runner/executors/) . +* 默认情况下,仅为成功的作业收集作业工件. + +`artifacts`用于指定在[成功,失败或始终成功](#artifactswhen)时应附加到作业的文件和目录的列表. + +作业完成后,工件将被发送到 GitLab,并可在 GitLab UI 中下载. + +[Read more about artifacts](../pipelines/job_artifacts.html). + +#### `artifacts:paths`[](#artifactspaths "Permalink") + +路径是相对于项目目录( `$CI_PROJECT_DIR` )的,不能直接链接到其外部. 可以使用遵循[通配符](https://en.wikipedia.org/wiki/Glob_(programming))模式和[`filepath.Match`](https://s0golang0org.icopy.site/pkg/path/filepath/)的[通配符](https://en.wikipedia.org/wiki/Glob_(programming)) . + +要限制特定作业将从中获取工件的作业,请参阅[dependencies](#dependencies) . + +发送所有`binaries`和`.config`文件: + +``` +artifacts: + paths: + - binaries/ + - .config +``` + +要禁用工件传递,请使用空的[依赖项](#dependencies)定义作业: + +``` +job: + stage: build + script: make build + dependencies: [] +``` + +您可能只想为标记的发行版创建构件,以避免用临时构建构件填充构建服务器存储. + +仅为标签创建工件( `default-job`不会创建工件): + +``` +default-job: + script: + - mvn test -U + except: + - tags + +release-job: + script: + - mvn package -U + artifacts: + paths: + - target/*.war + only: + - tags +``` + +您也可以为目录使用通配符. 例如,如果要获取以`xyz`结尾的目录中的所有文件: + +``` +job: + artifacts: + paths: + - path/*xyz/* +``` + +#### `artifacts:exclude`[](#artifactsexclude "Permalink") + +版本历史 + +* 在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/15122) +* 需要 GitLab Runner 13.1 + +`exclude`可以防止将文件添加到工件存档中. + +类似于[`artifacts:paths`](#artifactspaths) , `exclude`路径相对于项目目录. 可以使用遵循[通配符](https://en.wikipedia.org/wiki/Glob_(programming))模式和[`filepath.Match`](https://s0golang0org.icopy.site/pkg/path/filepath/)的[通配符](https://en.wikipedia.org/wiki/Glob_(programming)) . + +例如,所有的文件存储在`binaries/` ,而不是`*.o`位于的子目录中的文件`binaries/` : + +``` +artifacts: + paths: + - binaries/ + exclude: + - binaries/**/*.o +``` + +与[`artifacts:untracked`](#artifactsuntracked)匹配的文件也可以使用`artifacts:exclude` . + +#### `artifacts:expose_as`[](#artifactsexpose_as "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/15018) . + +关键字`expose_as`可用于在[合并请求](../../user/project/merge_requests/index.html) UI 中公开[作业工件](../pipelines/job_artifacts.html) . + +例如,要匹配单个文件: + +``` +test: + script: [ "echo 'test' > file.txt" ] + artifacts: + expose_as: 'artifact 1' + paths: ['file.txt'] +``` + +使用此配置,GitLab 会将链接**工件 1**添加到指向`file1.txt`的相关合并请求中. + +匹配整个目录的示例: + +``` +test: + script: [ "mkdir test && echo 'test' > test/file.txt" ] + artifacts: + expose_as: 'artifact 1' + paths: ['test/'] +``` + +请注意以下几点: + +* 使用变量定义`artifacts:paths`时,工件不会显示在合并请求 UI 中. +* 每个合并请求最多可以公开 10 个作业工件. +* 不支持 glob 模式. +* 如果指定了目录,那么如果目录中有多个文件,则该链接将指向作业[工件浏览器](../pipelines/job_artifacts.html#browsing-artifacts) . +* 对于带有`.html` , `.htm` , `.txt` , `.json` , `.xml`和`.log`扩展名的暴露的单个文件工件,如果[GitLab Pages](../../administration/pages/index.html)为: + * 启用后,GitLab 将自动渲染工件. + * 未启用,您将在工件浏览器中看到该文件. + +#### `artifacts:name`[](#artifactsname "Permalink") + +在 GitLab 8.6 和 GitLab Runner v1.1.0 中引入. + +通过`name`指令,您可以定义所创建的工件存档的名称. 这样,您可以为每个档案使用一个唯一的名称,这在您要从 GitLab 下载档案时很有用. `artifacts:name`变量可以使用任何[预定义变量](../variables/README.html) . 默认名称是`artifacts` ,下载`artifacts`变为`artifacts.zip` . + +**注意:**如果您的分支名称包含正斜杠(例如`feature/my-feature` ),建议使用`$CI_COMMIT_REF_SLUG`而不是`$CI_COMMIT_REF_NAME`来正确命名工件. + +要使用当前作业的名称创建档案: + +``` +job: + artifacts: + name: "$CI_JOB_NAME" + paths: + - binaries/ +``` + +要使用当前分支或标记的名称(仅包括二进制文件目录)创建档案,请执行以下操作: + +``` +job: + artifacts: + name: "$CI_COMMIT_REF_NAME" + paths: + - binaries/ +``` + +要使用当前作业的名称和当前分支或标记(仅包括二进制文件目录)创建档案,请执行以下操作: + +``` +job: + artifacts: + name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME" + paths: + - binaries/ +``` + +要创建一个具有当前[阶段](#stages)名称和分支名称的档案: + +``` +job: + artifacts: + name: "$CI_JOB_STAGE-$CI_COMMIT_REF_NAME" + paths: + - binaries/ +``` + +* * * + +如果使用**Windows Batch**运行 Shell 脚本,则需要将`$`替换`$` `%` : + +``` +job: + artifacts: + name: "%CI_JOB_STAGE%-%CI_COMMIT_REF_NAME%" + paths: + - binaries/ +``` + +如果使用**Windows PowerShell**运行 Shell 脚本,则需要将`$`替换`$` `$env:` :: + +``` +job: + artifacts: + name: "$env:CI_JOB_STAGE-$env:CI_COMMIT_REF_NAME" + paths: + - binaries/ +``` + +#### `artifacts:untracked`[](#artifactsuntracked "Permalink") + +`artifacts:untracked`用于将所有 Git 未跟踪的文件添加为工件(以及`artifacts:paths`定义的`artifacts:paths` ). + +**Note:** `artifacts:untracked` ignores configuration in the repository’s `.gitignore` file. + +发送所有未跟踪的 Git 文件: + +``` +artifacts: + untracked: true +``` + +发送所有 Git 未跟踪的文件和`binaries` : + +``` +artifacts: + untracked: true + paths: + - binaries/ +``` + +发送所有未跟踪的文件,但[不包括](#artifactsexclude) `*.txt` : + +``` +artifacts: + untracked: true + exclude: + - *.txt +``` + +#### `artifacts:when`[](#artifactswhen "Permalink") + +在 GitLab 8.9 和 GitLab Runner v1.3.0 中引入. + +`artifacts:when`用于在作业失败时或尽管失败而上传工件. + +可以设置为以下值之一的`artifacts:when` : + +1. `on_success`仅在作业成功时才上传工件. 这是默认值. +2. `on_failure`仅在作业失败时上载工件. +3. `always` -上载工件,无论作业状态如何. + +要仅在作业失败时上传工件: + +``` +job: + artifacts: + when: on_failure +``` + +#### `artifacts:expire_in`[](#artifactsexpire_in "Permalink") + +在 GitLab 8.9 和 GitLab Runner v1.3.0 中引入. + +`expire_in` allows you to specify how long artifacts should live before they expire and are therefore deleted, counting from the time they are uploaded and stored on GitLab. If the expiry time is not defined, it defaults to the [instance wide setting](../../user/admin_area/settings/continuous_integration.html#default-artifacts-expiration-core-only) (30 days by default). + +您可以使用作业页面上的" **保留"**按钮来覆盖过期并永久保留工件. + +过期后,默认情况下每小时(通过 cron 作业)删除工件,并且不再可用. + +The value of `expire_in` is an elapsed time in seconds, unless a unit is provided. Examples of valid values: + +* `42` +* `3 mins 4 sec` +* `2 hrs 20 min` +* `2h20min` +* `6 mos 1 day` +* `47 yrs 6 mos and 4d` +* `3 weeks and 2 days` + +要在上传后 1 周内使工件过期: + +``` +job: + artifacts: + expire_in: 1 week +``` + +**注意:**对于在[GitLab 13.1](https://gitlab.com/gitlab-org/gitlab/-/issues/16267)和更高版本中创建的工件,无论有效时间如何,始终会保留引用的最新工件. + +#### `artifacts:reports`[](#artifactsreports "Permalink") + +[`artifacts:reports`关键字](../pipelines/job_artifacts.html#artifactsreports)用于从作业中收集测试报告,代码质量报告和安全性报告. 它还在 GitLab 的 UI 中显示这些报告(合并请求,管道视图和安全性仪表板). + +这些是可用的报告类型: + +| Parameter | Description | +| --- | --- | +| [`artifacts:reports:junit`](../pipelines/job_artifacts.html#artifactsreportsjunit) | `junit`报告收集 JUnit XML 文件. | +| [`artifacts:reports:dotenv`](../pipelines/job_artifacts.html#artifactsreportsdotenv) | `dotenv`报告收集一组环境变量. | +| [`artifacts:reports:cobertura`](../pipelines/job_artifacts.html#artifactsreportscobertura) | `cobertura`报告收集 Co​​bertura coverage XML 文件. | +| [`artifacts:reports:terraform`](../pipelines/job_artifacts.html#artifactsreportsterraform) | `terraform`报告收集 Terraform `tfplan.json`文件. | +| [`artifacts:reports:codequality`](../pipelines/job_artifacts.html#artifactsreportscodequality-starter) | `codequality`报告收集 Co​​deQuality 问题. | +| [`artifacts:reports:sast`](../pipelines/job_artifacts.html#artifactsreportssast-ultimate) | `sast`报告收集"静态应用程序安全性测试"漏洞. | +| [`artifacts:reports:dependency_scanning`](../pipelines/job_artifacts.html#artifactsreportsdependency_scanning-ultimate) | `dependency_scanning`报告收集"依赖关系扫描"漏洞. | +| [`artifacts:reports:container_scanning`](../pipelines/job_artifacts.html#artifactsreportscontainer_scanning-ultimate) | `container_scanning`报告收集容器扫描漏洞. | +| [`artifacts:reports:dast`](../pipelines/job_artifacts.html#artifactsreportsdast-ultimate) | `dast`报告收集动态应用程序安全测试漏洞. | +| [`artifacts:reports:license_management`](../pipelines/job_artifacts.html#artifactsreportslicense_management-ultimate) | `license_management`报告收集许可证( *已从 GitLab 13.0 中删除* ). | +| [`artifacts:reports:license_scanning`](../pipelines/job_artifacts.html#artifactsreportslicense_scanning-ultimate) | `license_scanning`报告收集许可证. | +| [`artifacts:reports:performance`](../pipelines/job_artifacts.html#artifactsreportsperformance-premium) | `performance`报告收集绩效指标. | +| [`artifacts:reports:metrics`](../pipelines/job_artifacts.html#artifactsreportsmetrics-premium) | `metrics`报告收集指标. | + +#### `dependencies`[](#dependencies "Permalink") + +在 GitLab 8.6 和 GitLab Runner v1.1.1 中引入. + +默认情况下,所有先前[阶段的](#stages)所有[`artifacts`](#artifacts)都被传递,但是您可以使用`dependencies`参数来定义要从中获取工件的有限的作业列表(或没有作业). + +要使用此功能,请在作业的上下文中定义`dependencies` ,并传递所有以前的工件应从中下载工件的列表. 您只能从当前阶段之前执行的阶段定义作业. 如果您从当前阶段或下一个阶段定义作业,将显示错误. 定义一个空数组将跳过下载该作业的任何工件. 在使用`dependencies` ,不会考虑先前作业的状态,因此,如果它失败或它是未运行的手动作业,则不会发生错误. + +在以下示例中,我们使用工件定义了两个作业`build:osx`和`build:linux` . 当执行`test:osx` ,将在`build:osx`上下文中下载并提取来自`build:osx`的工件. `test:linux`和`build:linux`工件也发生了同样的情况. + +由于[阶段](#stages)优先,作业`deploy`将下载所有先前作业的工件: + +``` +build:osx: + stage: build + script: make build:osx + artifacts: + paths: + - binaries/ + +build:linux: + stage: build + script: make build:linux + artifacts: + paths: + - binaries/ + +test:osx: + stage: test + script: make test:osx + dependencies: + - build:osx + +test:linux: + stage: test + script: make test:linux + dependencies: + - build:linux + +deploy: + stage: deploy + script: make deploy +``` + +##### When a dependent job will fail[](#when-a-dependent-job-will-fail "Permalink") + +在 GitLab 10.3 中引入. + +如果设置为依赖项的作业的工件已[过期](#artifactsexpire_in)或已[擦除](../pipelines/job_artifacts.html#erasing-artifacts) ,则依赖项作业将失败. + +**注意:**您可以要求管理员[翻转此开关](../../administration/job_artifacts.html#validation-for-dependencies)并恢复原来的行为. + +### `coverage`[](#coverage "Permalink") + +在 GitLab 8.17 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20428) . + +`coverage`允许您配置如何从作业输出中提取代码 coverage. + +正则表达式是此处期望的唯一有效值. 因此,必须使用周围的`/` ,以便一致且显式表示正则表达式字符串. 如果要按字面意义匹配特殊字符,则必须转义它们. + +一个简单的例子: + +``` +job1: + script: rspec + coverage: '/Code coverage: \d+\.\d+/' +``` + +### `retry`[](#retry "Permalink") + +版本历史 + +* 在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3442) . +* [行为](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3515)在 GitLab 11.5 中进行了[扩展](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3515) ,以控制重试哪些失败. + +`retry`允许您配置在失败的情况下重试作业的次数. + +当作业失败并配置了`retry` ,它将再次处理,直到`retry`关键字指定的时间. + +如果`retry`设置为 2,并且作业在第二次运行中成功(第一次重试),则不会再次重试. `retry`值必须是一个正整数,等于或大于 0,但小于或等于 2(最多两次重试,总共运行 3 次). + +在所有失败情况下重试的简单示例: + +``` +test: + script: rspec + retry: 2 +``` + +默认情况下,将在所有失败情况下重试作业. 为了更好地控制重`retry`哪些失败,重`retry`可以是具有以下键的哈希值: + +* `max` :最大重试次数. +* `when` :失败案例重试. + +要最多仅重试运行程序系统故障两次: + +``` +test: + script: rspec + retry: + max: 2 + when: runner_system_failure +``` + +如果有其他故障,而不是运行器系统故障,则不会重试该作业. + +重试对多个故障的情况下, `when`也可以是故障的数组: + +``` +test: + script: rspec + retry: + max: 2 + when: + - runner_system_failure + - stuck_or_timeout_failure +``` + +`when`可能值为: + +* `always` :发生任何故障时重试(默认). +* `unknown_failure` :当失败原因未知时重试. +* `script_failure` :脚本失败时重试. +* `api_failure` :API 失败重试. +* `stuck_or_timeout_failure` :作业卡住或超时时重试. +* `runner_system_failure` :如果运行系统发生故障(例如,作业设置失败),请重试. +* `missing_dependency_failure` :如果缺少依赖项,请重试. +* `runner_unsupported` :如果跑步者不受支持,请重试. +* `stale_schedule` :如果无法执行延迟的作业,请重试. +* `job_execution_timeout` :如果脚本超出了为作业设置的最大执行时间,则重试. +* `archived_failure` :如果作业已存档且无法运行,请重试. +* `unmet_prerequisites` :如果作业未能完成先决条件任务,请重试. +* `scheduler_failure` :如果调度程序未能将作业分配给运行`scheduler_failure`重试. +* `data_integrity_failure` :如果检测到结构完整性问题,请重试. + +您可以使用变量指定[作业执行某些阶段的重试次数](#job-stages-attempts) . + +### `timeout`[](#timeout "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/14887) . + +`timeout`允许您为特定作业配置超时. 例如: + +``` +build: + script: build.sh + timeout: 3 hours 30 minutes + +test: + script: rspec + timeout: 3h 30m +``` + +作业级超时可以超过[项目级超时,](../pipelines/settings.html#timeout)但不能超过 Runner 特定的超时. + +### `parallel`[](#parallel "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21480) . + +`parallel`允许您配置要并行运行的作业实例数. 此值必须大于或等于两(2)并且小于或等于 50. + +这将创建 N 个并行运行的同一作业实例. 它们从`job_name 1/N`到`job_name N/N`依次命名. + +对于每个作业, `CI_NODE_INDEX`设置`CI_NODE_INDEX`和`CI_NODE_TOTAL` [环境变量](../variables/README.html#predefined-environment-variables) . + +标记要并行运行的作业需要将`parallel`添加到配置文件中. 例如: + +``` +test: + script: rspec + parallel: 5 +``` + +**提示:**跨并行作业并行测试套件. 不同的语言具有不同的工具来促进这一点. + +一个使用[信号量测试助推器](https://github.com/renderedtext/test-boosters)和 RSpec 来运行一些 Ruby 测试的简单示例: + +``` +# Gemfile +source 'https://rubygems.org' + +gem 'rspec' +gem 'semaphore_test_boosters' +``` + +``` +test: + parallel: 3 + script: + - bundle + - bundle exec rspec_booster --job $CI_NODE_INDEX/$CI_NODE_TOTAL +``` + +**警告:**请注意 semaphore_test_boosters 向作者报告使用情况统计信息. + +然后,您可以导航到新管道构建的" **作业"**选项卡,并查看 RSpec 作业分为三个单独的作业. + +### `trigger`[](#trigger "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) . +* 在 12.8 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) GitLab Core. + +`trigger`允许您定义下游管道触发器. 当 GitLab 从`trigger`定义创建的作业启动时,将创建一个下游管道. + +此关键字允许创建两种不同类型的下游管道: + +* [Multi-project pipelines](../multi_project_pipelines.html#creating-multi-project-pipelines-from-gitlab-ciyml) +* [Child pipelines](../parent_child_pipelines.html) + +**注意:**将`trigger`与`when:manual`一起使用会导致错误`jobs:#{job-name} when should be on_success, on_failure or always` ,因为`when:manual`阻止使用触发器. + +#### Simple `trigger` syntax for multi-project pipelines[](#simple-trigger-syntax-for-multi-project-pipelines "Permalink") + +配置下游触发器的最简单方法是使用带有指向下游项目的完整路径的`trigger`关键字: + +``` +rspec: + stage: test + script: bundle exec rspec + +staging: + stage: deploy + trigger: my/deployment +``` + +#### Complex `trigger` syntax for multi-project pipelines[](#complex-trigger-syntax-for-multi-project-pipelines "Permalink") + +可以配置分支名称,GitLab 将使用该分支名称来创建下游管道: + +``` +rspec: + stage: test + script: bundle exec rspec + +staging: + stage: deploy + trigger: + project: my/deployment + branch: stable +``` + +可以从触发的管道中镜像状态: + +``` +trigger_job: + trigger: + project: my/project + strategy: depend +``` + +可以从上游管道镜像状态: + +``` +upstream_bridge: + stage: test + needs: + pipeline: other/project +``` + +#### `trigger` syntax for child pipeline[](#trigger-syntax-for-child-pipeline "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/16094) . + +要创建[子管道](../parent_child_pipelines.html) ,请指定包含子管道的 CI 配置的 YAML 文件的路径: + +``` +trigger_job: + trigger: + include: path/to/child-pipeline.yml +``` + +类似于[多项目管道](../multi_project_pipelines.html#mirroring-status-from-triggered-pipeline) ,可以从触发的管道中镜像状态: + +``` +trigger_job: + trigger: + include: + - local: path/to/child-pipeline.yml + strategy: depend +``` + +##### Trigger child pipeline with generated configuration file[](#trigger-child-pipeline-with-generated-configuration-file "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/35632) . + +您还可以从[动态生成的配置文件](../parent_child_pipelines.html#dynamic-child-pipelines)触发子管道: + +``` +generate-config: + stage: build + script: generate-ci-config > generated-config.yml + artifacts: + paths: + - generated-config.yml + +child-pipeline: + stage: test + trigger: + include: + - artifact: generated-config.yml + job: generate-config +``` + +从工件中提取了`generated-config.yml` ,并用作触发子管道的配置. + +#### Linking pipelines with `trigger:strategy`[](#linking-pipelines-with-triggerstrategy "Permalink") + +默认情况下,一旦创建下游管道, `trigger`作业就会以`success`状态完成. + +要强制`trigger`作业等待下游(多项目或子项目)管道完成,请使用`strategy: depend` . 这将使触发作业以"运行"状态等待,直到触发的管道完成. 此时, `trigger`作业将完成并显示与下游作业相同的状态. + +``` +trigger_job: + trigger: + include: path/to/child-pipeline.yml + strategy: depend +``` + +这可以使您的管道执行保持线性. 在上面的示例中,后续阶段的作业将在启动之前等待触发的管道成功完成,但代价是并行化程度降低. + +#### Trigger a pipeline by API call[](#trigger-a-pipeline-by-api-call "Permalink") + +当使用触发器令牌创建管道时,触发器可以用于通过 API 调用强制重建特定的分支,标记或提交. + +不要与[`trigger`](#trigger)参数混淆. + +[Read more in the triggers documentation.](../triggers/README.html) + +### `interruptible`[](#interruptible "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32022) . + +`interruptible`可用于指示如果作业因新的管道运行而变得多余,则应取消该作业. 默认为`false` . 仅当启用了[自动取消冗余管道功能](../pipelines/settings.html#auto-cancel-pending-pipelines)时,才使用此值. + +启用后,在以下情况下,将取消同一分支上的管道: + +* 它通过新的管道运行而变得多余. +* 将所有作业都设置为可中断,或者尚未开始任何不间断的作业. + +待处理的作业始终被视为可中断的. + +**Tip:** Set jobs as interruptible that can be safely canceled once started (for instance, a build job). + +这是一个简单的示例: + +``` +stages: + - stage1 + - stage2 + - stage3 + +step-1: + stage: stage1 + script: + - echo "Can be canceled." + interruptible: true + +step-2: + stage: stage2 + script: + - echo "Can not be canceled." + +step-3: + stage: stage3 + script: + - echo "Because step-2 can not be canceled, this step will never be canceled, even though set as interruptible." + interruptible: true +``` + +在上面的示例中,新的管道运行将导致现有的正在运行的管道为: + +* 如果仅`step-1`正在运行或挂起,则取消. +* 一旦`step-2`开始运行,则不会取消. + +**注意:**一旦运行了不间断的作业,无论最终作业的状态如何,管道将永远不会被取消. + +### `resource_group`[](#resource_group "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/15536) . + +有时在环境中同时运行多个作业或管道可能会导致在部署过程中出错. + +为了避免这些错误,可以使用`resource_group`属性来确保 Runner 不会同时运行某些作业. + +当在`.gitlab-ci.yml`为作业定义了`resource_group`键时,作业执行在同一项目的不同管道之间是互斥的. 如果属于同一资源组的多个作业同时进入队列,则 Runner 将仅选择一个作业,其他作业将等待,直到`resource_group`空闲为止. + +这是一个简单的示例: + +``` +deploy-to-production: + script: deploy + resource_group: production +``` + +在这种情况下,如果`deploy-to-production`作业在管道运行,并且新的`deploy-to-production`中不同的管道创建工作,它不会运行,直到当前运行的/未决`deploy-to-production`工作完成. 结果,您可以确保并发部署永远不会在生产环境中发生. + +每个环境可以定义多个`resource_group` . 一个很好的用例是在部署到物理设备时. 您可能具有多个物理设备,并且每个物理设备都可以部署到其中,但是在任何给定时间,每个设备只能有一个部署. + +**注:**此键只能包含字母,数字, `-` `_` , `/` , `$` , `{` , `}` , `.` 和空格. 它不能以`/`开头或结尾. + +有关更多信息,请参见[部署安全](../environments/deployment_safety.html) . + +### `release`[](#release "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/merge_requests/19298) . + +`release`表示作业创建一个[Release](../../user/project/releases/index.html) ,并且可以选择包含 Release 资产的 URL. + +支持以下方法: + +* [`tag_name`](#releasetag_name) +* [`name`](#releasename) (optional) +* [`description`](#releasedescription) (optional) +* [`ref`](#releaseref) (optional) +* [`milestones`](#releasemilestones) (optional) +* [`released_at`](#releasereleased_at) (optional) + +仅当作业处理没有错误时才创建发布. 如果 Rails API 在发布创建期间返回错误,则`release`作业将失败. + +#### `release-cli` Docker image[](#release-cli-docker-image "Permalink") + +必须使用以下指令指定用于`release-cli`的 Docker 映像: + +``` +image: registry.gitlab.com/gitlab-org/release-cli:latest +``` + +#### Script[](#script-1 "Permalink") + +所有作业至少需要一个`script`标签. `:release`作业可以使用`:script`标记的输出,但是如果没有必要,则可以使用占位符脚本,例如: + +``` +script: + - echo 'release job' +``` + +在即将发布的 GitLab 版本中存在删除此要求的[问题](https://gitlab.com/gitlab-org/gitlab/-/issues/223856) . + +管道可以具有多个`release`作业,例如: + +``` +ios-release: + script: + - echo 'iOS release job' + release: + tag_name: v1.0.0-ios + description: 'iOS release v1.0.0' + +android-release: + script: + - echo 'Android release job' + release: + tag_name: v1.0.0-android + description: 'Android release v1.0.0' +``` + +#### `release:tag_name`[](#releasetag_name "Permalink") + +必须指定`tag_name` . 它可以引用现有的 Git 标记,也可以由用户指定. + +当存储库中不存在指定的标签时,将从管道的关联 SHA 创建一个新标签. + +例如,从 Git 标签创建 Release 时: + +``` +job: + release: + tag_name: $CI_COMMIT_TAG + description: changelog.txt +``` + +也可以创建任何唯一标签, `only: tags`在这种情况下`only: tags`不是必需的. 语义版本控制示例: + +``` +job: + release: + tag_name: ${MAJOR}_${MINOR}_${REVISION} + description: changelog.txt +``` + +* 仅当作业的主脚本成功时才创建发布. +* 如果版本已经存在,则不会更新,并且带有`release`关键字的作业将失败. +* `release`部分在`script`标记之后和`after_script`之前`after_script` . + +#### `release:name`[](#releasename "Permalink") + +发布名称. 如果省略,则使用`release: tag_name`的值填充`release: tag_name` . + +#### `release:description`[](#releasedescription "Permalink") + +指定发布的详细描述. + +#### `release:ref`[](#releaseref "Permalink") + +如果`release: tag_name`尚不存在,则从`ref`创建版本. `ref`可以是提交 SHA,其他标记名称或分支名称. + +#### `release:milestones`[](#releasemilestones "Permalink") + +与发行版关联的每个里程碑的标题. + +#### `release:released_at`[](#releasereleased_at "Permalink") + +发布准备就绪的日期和时间. 如果未定义,则默认为当前日期和时间. 预期为 ISO 8601 格式(2019-03-15T08:00:00Z). + +#### Complete example for `release`[](#complete-example-for-release "Permalink") + +结合上面给出的`release`示例,将产生以下代码段. 有两种选择,具体取决于生成标记的方式. 这些选项不能一起使用,因此请选择以下一种: + +* 要在按下 Git 标签或在 UI 中通过添加**存储库>标签**来添加 Git 标签时创建发行版: + + ``` + release_job: + stage: release + image: registry.gitlab.com/gitlab-org/release-cli:latest + rules: + - if: $CI_COMMIT_TAG # Run this job when a tag is created manually + script: + - echo 'running release_job' + release: + name: 'Release $CI_COMMIT_TAG' + description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION must be defined + tag_name: '$CI_COMMIT_TAG' # elsewhere in the pipeline. + ref: '$CI_COMMIT_TAG' + milestones: + - 'm1' + - 'm2' + - 'm3' + released_at: '2020-07-15T08:00:00Z' # Optional, will auto generate if not defined, + # or can use a variable. + ``` + +* 要使用更改定义的新 Git 标签,将更改推送到默认分支时自动创建发行版: + + ``` + release_job: + stage: release + image: registry.gitlab.com/gitlab-org/release-cli:latest + rules: + - if: $CI_COMMIT_TAG + when: never # Do not run this job when a tag is created manually + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when the default branch changes + script: + - echo 'running release_job' + release: + name: 'Release $CI_COMMIT_SHA' + description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION and the tag_name + tag_name: 'v${MAJOR}.${MINOR}.${REVISION}' # variables must be defined elsewhere + ref: '$CI_COMMIT_SHA' # in the pipeline. + milestones: + - 'm1' + - 'm2' + - 'm3' + released_at: '2020-07-15T08:00:00Z' # Optional, will auto generate if not defined, + # or can use a variable. + ``` + +#### `releaser-cli` command line[](#releaser-cli-command-line "Permalink") + +`:release`节点下的条目被转换为`bash`命令行,并发送到包含[release-cli](https://gitlab.com/gitlab-org/release-cli)的 Docker 容器. 您也可以直接从`script`条目调用`release-cli` . + +上面描述的 YAML 将被翻译成如下的 CLI 命令: + +``` +release-cli create --name "Release $CI_COMMIT_SHA" --description "Created using the release-cli $EXTRA_DESCRIPTION" --tag-name "v${MAJOR}.${MINOR}.${REVISION}" --ref "$CI_COMMIT_SHA" --released-at "2020-07-15T08:00:00Z" --milestone "m1" --milestone "m2" --milestone "m3" +``` + +### `pages`[](#pages "Permalink") + +`pages`是一项特殊的工作,用于将静态内容上传到 GitLab,可用于为您的网站提供服务. 它具有特殊的语法,因此必须满足以下两个要求: + +* 任何静态内容都必须放在`public/`目录下. +* 必须定义带有`public/`目录路径的`artifacts` . + +下面的示例只是将所有文件从项目的根目录移到`public/`目录. `.public`解决方法是,因此`cp`也不会在无限循环中将`public/`复制到自身: + +``` +pages: + stage: deploy + script: + - mkdir .public + - cp -r * .public + - mv .public public + artifacts: + paths: + - public + only: + - master +``` + +阅读有关[GitLab Pages 用户文档的](../../user/project/pages/index.html)更多[信息](../../user/project/pages/index.html) . + +## `variables`[](#variables "Permalink") + +在 GitLab Runner v0.5.0 中引入. + +**注意:**对于变量的名称和值,整数(以及字符串)都是合法的. 浮动广告不合法,不能使用. + +GitLab CI / CD 允许您在`.gitlab-ci.yml`中定义变量,然后在作业环境中传递这些变量. 它们可以全局设置,也可以按工作设置. 在作业级别上使用`variables`关键字时,它将覆盖全局 YAML 变量和相同名称的预定义变量. + +它们存储在 Git 存储库中,用于存储非敏感项目配置,例如: + +``` +variables: + DATABASE_URL: "postgres://postgres@postgres/my_database" +``` + +这些变量以后可以在所有执行的命令和脚本中使用. YAML 定义的变量也设置为所有创建的服务容器,从而允许对其进行微调. + +除了用户定义的变量外,还有[由 Runner 本身设置的](../variables/README.html#predefined-environment-variables)变量. 一个示例是`CI_COMMIT_REF_NAME` ,它具有为其构建项目的分支或标记名称的值. 除了可以在`.gitlab-ci.yml`设置的变量`.gitlab-ci.yml` ,还有可以在 GitLab 的 UI 中设置的所谓[变量](../variables/README.html#gitlab-cicd-environment-variables) . + +提供了[用于变量的 YAML 锚](#yaml-anchors-for-variables) . + +了解有关[变量及其优先级的](../variables/README.html)更多信息. + +### Git strategy[](#git-strategy "Permalink") + +版本历史 + +* 在 GitLab 8.9 中作为实验功能引入. +* `GIT_STRATEGY=none`要求 GitLab Runner `GIT_STRATEGY=none` +. + +**注意:**在将来的版本中可能会更改或完全删除. + +您可以在[`variables`](#variables)部分中全局或按作业设置用于获取最新应用程序代码的`GIT_STRATEGY` . 如果未指定,将使用项目设置中的默认设置. + +有三个可能的值: `clone` , `fetch`和`none` . + +`clone`是最慢的选择. 它为每个作业从头克隆存储库,以确保本地工作副本始终是原始的. + +``` +variables: + GIT_STRATEGY: clone +``` + +`fetch`速度更快,因为它可以重新使用本地工作副本(如果不存在则回退到`clone` ). `git clean`用于撤消上一个作业所做的任何更改,而`git fetch`用于检索自上一个作业运行以来进行的提交. + +``` +variables: + GIT_STRATEGY: fetch +``` + +`none`再使用本地工作副本,但是会跳过所有 Git 操作(包括 GitLab Runner 的预克隆脚本(如果存在)). 对于仅在工件上运行的作业(例如`deploy` ),它最有用. Git 存储库数据可能存在,但是肯定会过时,因此您应该仅依靠从缓存或工件导入本地工作副本的文件. + +``` +variables: + GIT_STRATEGY: none +``` + +**注意:** `GIT_STRATEGY`器不支持[GIT_STRATEGY](https://docs.gitlab.com/runner/executors/kubernetes.html) ,但将来可能会支持. 有关更新,请参阅[带有 Kubernetes 执行器功能建议](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3847)的[支持 Git 策略](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3847) . + +### Git submodule strategy[](#git-submodule-strategy "Permalink") + +> 需要 GitLab Runner v1.10 +. + +`GIT_SUBMODULE_STRATEGY`变量用于控制在构建之前获取代码时是否包含/如何包含 Git 子模块. 您可以在[`variables`](#variables)部分中全局或按作业设置它们. + +共有三个可能的值: `none` , `normal`和`recursive` : + +* `none`表示在获取项目代码时将不包含子模块. 这是默认设置,与 v1.10 之前的行为匹配. + +* `normal`意味着仅包括顶级子模块. 等效于: + + ``` + git submodule sync git submodule update --init + ``` + +* `recursive`意味着将包括所有子模块(包括子模块的子模块). 此功能需要 Git v1.8.1 及更高版本. 当将 GitLab Runner 与不基于 Docker 的执行器一起使用时,请确保 Git 版本符合该要求. 等效于: + + ``` + git submodule sync --recursive + git submodule update --init --recursive + ``` + +请注意,为使此功能正常工作,必须使用以下任一方式(在`.gitmodules` )配置子模块: + +* 可公开访问的存储库的 HTTP(S)URL,或者 +* 到同一 GitLab 服务器上另一个存储库的相对路径. 请参阅[Git 子模块](../git_submodules.html)文档. + +### Git checkout[](#git-checkout "Permalink") + +在 GitLab Runner 9.3 中引入. + +当`GIT_STRATEGY`设置为`clone`或`fetch`以指定是否应运行`git checkout`时,可以使用`GIT_CHECKOUT`变量. 如果未指定,则默认为 true. 您可以在[`variables`](#variables)部分中全局或按作业设置它们. + +如果设置为`false` ,则跑步者将: + +* 进行`fetch` -更新存​​储库,并将工作副本保留在当前版本中, +* 执行`clone` -克隆存储库,并将工作副本保留在默认分支上. + +将此设置设置为`true`意味着对于`clone`和`fetch`策略,Runner 将签出工作副本到与 CI 管道相关的修订版本: + +``` +variables: + GIT_STRATEGY: clone + GIT_CHECKOUT: "false" +script: + - git checkout -B master origin/master + - git merge $CI_COMMIT_SHA +``` + +### Git clean flags[](#git-clean-flags "Permalink") + +在 GitLab Runner 11.10 中引入 + +`GIT_CLEAN_FLAGS`变量用于在签出源代码后控制`git clean`的默认行为. 您可以在[`variables`](#variables)部分中全局设置或按作业设置. + +`GIT_CLEAN_FLAGS`接受[`git clean`](https://git-scm.com/docs/git-clean)命令的所有可能选项. + +如果指定了`GIT_CHECKOUT: "false"`则禁用`git clean` . + +If `GIT_CLEAN_FLAGS` is: + +* 未指定, `git clean`标志默认为`-ffdx` . +* 给定值`none` ,将不执行`git clean` . + +例如: + +``` +variables: + GIT_CLEAN_FLAGS: -ffdx -e cache/ +script: + - ls -al cache/ +``` + +### Git fetch extra flags[](#git-fetch-extra-flags "Permalink") + +在 GitLab Runner 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4142) . + +`GIT_FETCH_EXTRA_FLAGS`变量用于控制`git fetch`的行为. 您可以在[`variables`](#variables)部分中全局设置或按作业设置. + +`GIT_FETCH_EXTRA_FLAGS`接受[`git fetch`](https://git-scm.com/docs/git-fetch)命令的所有可能选项,但请注意, `GIT_FETCH_EXTRA_FLAGS`标志将附加在无法修改的默认标志之后. + +默认标志是: + +* [GIT_DEPTH](#shallow-cloning). +* [refspec](https://git-scm.com/book/en/v2/Git-Internals-The-Refspec)列表. +* 遥远的`origin` . + +If `GIT_FETCH_EXTRA_FLAGS` is: + +* 未指定, `git fetch`标志与默认标志一起默认为`--prune --quiet` . +* 给定值`none` ,仅使用默认标志执行`git fetch` . + +例如,默认标志是`--prune --quiet` ,因此您可以通过仅用`--prune`覆盖它来使`git fetch`更加详细: + +``` +variables: + GIT_FETCH_EXTRA_FLAGS: --prune +script: + - ls -al cache/ +``` + +上面的配置将导致以这种方式调用`git fetch` : + +``` +git fetch origin $REFSPECS --depth 50 --prune +``` + +其中`$REFSPECS`是 GitLab 内部提供给 Runner 的值. + +### Job stages attempts[](#job-stages-attempts "Permalink") + +在 GitLab 中引入,它需要 GitLab Runner v1.9 +. + +您可以设置正在运行的作业尝试执行以下每个阶段的尝试次数: + +| Variable | Description | +| --- | --- | +| **GET_SOURCES_ATTEMPTS** | 尝试获取运行作业的源的次数 | +| **ARTIFACT_DOWNLOAD_ATTEMPTS** | 尝试下载运行作业的工件的次数 | +| **RESTORE_CACHE_ATTEMPTS** | 还原运行作业的缓存的尝试次数 | +| **EXECUTOR_JOB_SECTION_ATTEMPTS** | [从 GitLab 12.10 开始](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450) ,出现[`No Such Container`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450)错误(仅限[Docker 执行器](https://docs.gitlab.com/runner/executors/docker.html) )后,尝试在作业中运行部分的次数. | + +默认为一次尝试. + +Example: + +``` +variables: + GET_SOURCES_ATTEMPTS: 3 +``` + +您可以在[`variables`](#variables)部分中全局或按作业设置它们. + +### Shallow cloning[](#shallow-cloning "Permalink") + +在 GitLab 8.9 中作为实验功能引入. + +**注意** :从 GitLab 12.0 开始,新创建的项目将自动具有[默认的`git depth`值`50`](../pipelines/settings.html#git-shallow-clone) . + +您可以使用`GIT_DEPTH`指定获取和克隆的深度. 这允许对存储库进行浅层克隆,从而可以显着加快克隆具有大量提交或旧的大型二进制文件的存储库. 该值传递给`git fetch`和`git clone` . + +**注意:**如果使用 1 的深度,并且有作业队列或重试作业,则作业可能会失败. + +由于 Git 的获取和克隆基于引用(例如分支名称),因此 Runners 无法克隆特定的提交 SHA. 如果队列中有多个作业,或者您要重试旧的作业,则要测试的提交必须在克隆的 Git 历史记录内. 如果为`GIT_DEPTH`设置的值`GIT_DEPTH`则无法运行这些旧的提交. 您将在作业日志中看到`unresolved reference` . 然后,您应该重新考虑将`GIT_DEPTH`更改为更高的值. + +设置`GIT_DEPTH`时,依赖`git describe`作业可能无法正常工作,因为仅存在一部分 Git 历史记录. + +要仅获取或克隆最后 3 个提交,请执行以下操作: + +``` +variables: + GIT_DEPTH: "3" +``` + +您可以在[`variables`](#variables)部分中全局设置或按作业设置. + +### Custom build directories[](#custom-build-directories "Permalink") + +在 GitLab Runner 11.10 中[引入](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2211) + +**注意:**仅当在[Runner 的配置中](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)启用`custom_build_dir`时,才可以使用此`custom_build_dir` . 这是默认配置`docker`和`kubernetes`执行. + +默认情况下,GitLab Runner 将存储`$CI_BUILDS_DIR`到`$CI_BUILDS_DIR`目录的唯一子路径中. 但是,您的项目可能需要特定目录中的代码(例如,Go 项目). 在这种情况下,您可以指定`GIT_CLONE_PATH`变量,以告知 Runner 在哪个目录中克隆存储库: + +``` +variables: + GIT_CLONE_PATH: $CI_BUILDS_DIR/project-name + +test: + script: + - pwd +``` + +`GIT_CLONE_PATH`必须始终在`$CI_BUILDS_DIR` . `$CI_BUILDS_DIR`设置的目录取决于执行程序和[runners.builds_dir](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)设置的配置. + +#### Handling concurrency[](#handling-concurrency "Permalink") + +使用并发性大于`1`的执行程序可能会导致失败,因为如果在作业之间共享`builds_dir`则多个作业可能在同一目录上工作. GitLab Runner 不会尝试防止这种情况. 管理员和开发人员必须遵守 Runner 配置的要求. + +为了避免这种情况,您可以在`$CI_BUILDS_DIR`内使用唯一路径,因为 Runner 公开了两个提供唯一并发`ID`的变量: + +* `$CI_CONCURRENT_ID` :给定执行程序中运行的所有作业的唯一 ID. +* `$CI_CONCURRENT_PROJECT_ID` :给定执行程序和项目中运行的所有作业的唯一 ID. + +在任何情况下以及在任何执行程序上都应能正常工作的最稳定的配置是在`$CI_CONCURRENT_ID`中使用`$CI_CONCURRENT_ID` `GIT_CLONE_PATH` . 例如: + +``` +variables: + GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/project-name + +test: + script: + - pwd +``` + +在`$CI_CONCURRENT_PROJECT_ID`应结合使用`$CI_PROJECT_PATH`为`$CI_PROJECT_PATH`提供了一个存储库的路径. 即`group/subgroup/project` . 例如: + +``` +variables: + GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH + +test: + script: + - pwd +``` + +#### Nested paths[](#nested-paths "Permalink") + +`GIT_CLONE_PATH`的值被扩展一次,并且不支持其中的嵌套变量. + +例如,您在`.gitlab-ci.yml`文件中定义以下两个变量: + +``` +variables: + GOPATH: $CI_BUILDS_DIR/go + GIT_CLONE_PATH: $GOPATH/src/namespace/project +``` + +`GIT_CLONE_PATH`的值一次扩展到`$CI_BUILDS_DIR/go/src/namespace/project` ,并且由于`$CI_BUILDS_DIR`没有扩展而导致失败. + +## Special YAML features[](#special-yaml-features "Permalink") + +可以使用特殊的 YAML 功能,例如锚点( `&` ),别名( `*` )和地图合并( `<<` ),这将使您大大降低`.gitlab-ci.yml`的复杂性. + +阅读有关各种[YAML 功能的](https://learnxinyminutes.com/docs/yaml/)更多信息. + +在大多数情况下, [`extends`关键字](#extends)更加用户友好,应该在这些特殊的 YAML 功能上使用. 可能仍需要使用 YAML 锚来合并数组. + +### Anchors[](#anchors "Permalink") + +在 GitLab 8.6 和 GitLab Runner v1.1.1 中引入. + +YAML 具有称为"锚"的便捷功能,使您可以轻松地在整个文档中复制内容. 锚可用于复制/继承属性,并且是与[隐藏作业](#hide-jobs)一起使用以为您的作业提供模板的完美示例. 当有重复的密钥时,GitLab 将基于密钥执行反向深度合并. + +以下示例使用锚点和地图合并. 它将创建两个作业`test1`和`test2` ,它们将继承`.job_template`的参数,每个参数都定义了自己的自定义`script` : + +``` +.job_template: &job_definition # Hidden key that defines an anchor named 'job_definition' + image: ruby:2.6 + services: + - postgres + - redis + +test1: + <<: *job_definition # Merge the contents of the 'job_definition' alias + script: + - test1 project + +test2: + <<: *job_definition # Merge the contents of the 'job_definition' alias + script: + - test2 project +``` + +`&`设置锚点的名称( `job_definition` ), `<<`表示"将给定的哈希值合并到当前哈希中",并且`*`包括命名的锚点(再次为`job_definition` ). 扩展版本如下所示: + +``` +.job_template: + image: ruby:2.6 + services: + - postgres + - redis + +test1: + image: ruby:2.6 + services: + - postgres + - redis + script: + - test1 project + +test2: + image: ruby:2.6 + services: + - postgres + - redis + script: + - test2 project +``` + +让我们来看另一个例子. 这次,我们将使用锚来定义两组服务. 这将创建两个作业: `test:postgres`和`test:mysql` ,它们将共享`.job_template`定义的`script`指令以及`.postgres_services`和`.mysql_services`定义的`services`指令: + +``` +.job_template: &job_definition + script: + - test project + tags: + - dev + +.postgres_services: + services: &postgres_definition + - postgres + - ruby + +.mysql_services: + services: &mysql_definition + - mysql + - ruby + +test:postgres: + <<: *job_definition + services: *postgres_definition + tags: + - postgres + +test:mysql: + <<: *job_definition + services: *mysql_definition +``` + +扩展版本如下所示: + +``` +.job_template: + script: + - test project + tags: + - dev + +.postgres_services: + services: + - postgres + - ruby + +.mysql_services: + services: + - mysql + - ruby + +test:postgres: + script: + - test project + services: + - postgres + - ruby + tags: + - postgres + +test:mysql: + script: + - test project + services: + - mysql + - ruby + tags: + - dev +``` + +您可以看到隐藏的作业可以方便地用作模板. + +**Note:** Note that `tags: [dev]` has been overwritten by `tags: [postgres]`.**注意:**利用[`include`](#include)功能时,不能在多个文件中使用 YAML 锚. 锚仅在定义它们的文件内有效.您可以使用[`extends`关键字](#extends)来代替使用 YAML 锚. + +#### YAML anchors for `before_script` and `after_script`[](#yaml-anchors-for-before_script-and-after_script "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/23005) . + +您可以将[YAML 定位](#anchors) `after_script`与`before_script`和`after_script` ,从而可以在多个作业中包括预定义的命令列表. + +Example: + +``` +.something_before: &something_before + - echo 'something before' + +.something_after: &something_after + - echo 'something after' + - echo 'another thing after' + +job_name: + before_script: + - *something_before + script: + - echo 'this is the script' + after_script: + - *something_after +``` + +#### YAML anchors for `script`[](#yaml-anchors-for-script "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/23005) . + +您可以将[YAML 锚点](#anchors)与脚本一起使用,从而可以在多个作业中包括预定义的命令列表. + +例如: + +``` +.something: &something + - echo 'something' + +job_name: + script: + - *something + - echo 'this is the script' +``` + +#### YAML anchors for variables[](#yaml-anchors-for-variables "Permalink") + +[YAML 锚](#anchors)可以与`variables`一起使用,以轻松地在多个作业之间重复分配变量. 当作业需要特定的`variables`块(否则将覆盖全局变量)时,它还可以提供更大的灵活性. + +在下面的示例中,我们将覆盖`GIT_STRATEGY`变量,而不会影响`SAMPLE_VARIABLE`变量的使用: + +``` +# global variables +variables: &global-variables + SAMPLE_VARIABLE: sample_variable_value + ANOTHER_SAMPLE_VARIABLE: another_sample_variable_value + +# a job that needs to set the GIT_STRATEGY variable, yet depend on global variables +job_no_git_strategy: + stage: cleanup + variables: + <<: *global-variables + GIT_STRATEGY: none + script: echo $SAMPLE_VARIABLE +``` + +### Hide jobs[](#hide-jobs "Permalink") + +在 GitLab 8.6 和 GitLab Runner v1.1.1 中引入. + +如果要临时"禁用"作业,而不是注释掉定义作业的所有行: + +``` +#hidden_job: +# script: +# - run test +``` + +您可以改为以点号( `.` )开头,GitLab CI / CD 不会对其进行处理. 在以下示例中, `.hidden_job`将被忽略: + +``` +.hidden_job: + script: + - run test +``` + +使用此功能可忽略作业,或使用[特殊的 YAML 功能](#special-yaml-features)并将隐藏的作业转换为模板. + +## Skip Pipeline[](#skip-pipeline "Permalink") + +如果您的提交消息包含`[ci skip]`或`[skip ci]` ,则使用大写字母将创建提交,但是将跳过管道. + +或者,如果使用 Git 2.10 或更高版本,则可以传递`ci.skip` [Git 推送选项](../../user/project/push_options.html#push-options-for-gitlab-cicd) . + +## Processing Git pushes[](#processing-git-pushes "Permalink") + +当在单个`git push`调用中推送多个更改时,GitLab 将最多创建 4 条分支和标签管道. + +此限制不影响任何更新的合并请求管道. 使用[合并请求](../merge_request_pipelines/index.html)管道时,所有更新的合并请求都将创建一个管道. + +## Deprecated parameters[](#deprecated-parameters "Permalink") + +不推荐使用以下参数. + +### Globally-defined `types`[](#globally-defined-types "Permalink") + +**不**推荐**使用:** `types`不推荐使用,可以在以后的版本中删除. 使用[`stages`](#stages)代替. + +### Job-defined `type`[](#job-defined-type "Permalink") + +**不**推荐**使用:** `type`不推荐使用,可以在将来的发行版之一中将其删除. 使用[`stage`](#stage)代替. + +### Globally-defined `image`, `services`, `cache`, `before_script`, `after_script`[](#globally-defined-image-services-cache-before_script-after_script "Permalink") + +不`after_script`全局定义`image` , `services` , `cache` , `before_script`和`after_script` . 支持可以从将来的版本中删除. + +使用[`default:`](#global-defaults)代替. 例如: + +``` +default: + image: ruby:2.5 + services: + - docker:dind + cache: + paths: [vendor/] + before_script: + - bundle install --path vendor/ + after_script: + - rm -rf tmp/ +``` \ No newline at end of file diff --git a/docs/200.md b/docs/200.md new file mode 100644 index 0000000000000000000000000000000000000000..e7b98b4bb89a8f79fcb190f46cc0d1c8f237ab00 --- /dev/null +++ b/docs/200.md @@ -0,0 +1,206 @@ +# GitLab CI/CD include examples + +> 原文:[https://docs.gitlab.com/ee/ci/yaml/includes.html](https://docs.gitlab.com/ee/ci/yaml/includes.html) + +* [Single string or array of multiple values](#single-string-or-array-of-multiple-values) +* [Re-using a `before_script` template](#re-using-a-before_script-template) +* [Overriding external template values](#overriding-external-template-values) +* [Using nested includes](#using-nested-includes) + +# GitLab CI/CD include examples[](#gitlab-cicd-include-examples "Permalink") + +除了[GitLab CI YAML 参考中](README.html)列出的[`includes`示例](README.html#include)之外,此页面还列出了`include`用法的更多变化. + +## Single string or array of multiple values[](#single-string-or-array-of-multiple-values "Permalink") + +您可以将额外的 YAML 文件作为单个字符串或多个值的数组包含在内. 以下示例均有效. + +`include:local`方法的单个字符串暗含: + +``` +include: '/templates/.after-script-template.yml' +``` + +Array with `include` method implied: + +``` +include: + - 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml' + - '/templates/.after-script-template.yml' +``` + +具有明确指定的`include`方法的单个字符串: + +``` +include: + remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml' +``` + +`include:remote`为单个项目的数组: + +``` +include: + - remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml' +``` + +具有多个显式指定的`include`方法的数组: + +``` +include: + - remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml' + - local: '/templates/.after-script-template.yml' + - template: Auto-DevOps.gitlab-ci.yml +``` + +数组混合语法: + +``` +include: + - 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml' + - '/templates/.after-script-template.yml' + - template: Auto-DevOps.gitlab-ci.yml + - project: 'my-group/my-project' + ref: master + file: '/templates/.gitlab-ci-template.yml' +``` + +## Re-using a `before_script` template[](#re-using-a-before_script-template "Permalink") + +在以下示例中, `.before-script-template.yml`的内容将与`.gitlab-ci.yml`的内容一起自动获取和评估. + +`https://gitlab.com/awesome-project/raw/master/.before-script-template.yml`内容: + +``` +before_script: + - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs + - gem install bundler --no-document + - bundle install --jobs $(nproc) "${FLAGS[@]}" +``` + +`.gitlab-ci.yml`内容: + +``` +include: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml' + +rspec: + script: + - bundle exec rspec +``` + +## Overriding external template values[](#overriding-external-template-values "Permalink") + +以下示例显示了特定的 YAML 定义的变量以及`.gitlab-ci.yml`自定义的包含文件中`production`作业的详细信息. + +`https://company.com/autodevops-template.yml`内容: + +``` +variables: + POSTGRES_USER: user + POSTGRES_PASSWORD: testing_password + POSTGRES_DB: $CI_ENVIRONMENT_SLUG + +production: + stage: production + script: + - install_dependencies + - deploy + environment: + name: production + url: https://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN + only: + - master +``` + +`.gitlab-ci.yml`内容: + +``` +include: 'https://company.com/autodevops-template.yml' + +image: alpine:latest + +variables: + POSTGRES_USER: root + POSTGRES_PASSWORD: secure_password + +stages: + - build + - test + - production + +production: + environment: + url: https://domain.com +``` + +在这种情况下,变量`POSTGRES_USER`和`POSTGRES_PASSWORD`以及`autodevops-template.yml`定义的`production`作业的环境 URL 已被`.gitlab-ci.yml`定义的新值覆盖. + +合并使您可以扩展和覆盖字典映射,但是不能向包含的数组添加或修改项目. 例如,要将其他项目添加到生产作业脚本中,必须重复现有的脚本项目: + +`https://company.com/autodevops-template.yml`内容: + +``` +production: + stage: production + script: + - install_dependencies + - deploy +``` + +`.gitlab-ci.yml`内容: + +``` +include: 'https://company.com/autodevops-template.yml' + +stages: + - production + +production: + script: + - install_dependencies + - deploy + - notify_owner +``` + +在这种情况下,如果未在`.gitlab-ci.yml`重复`install_dependencies`和`deploy` ,则它们将不会成为组合 CI 配置中`production`作业脚本的一部分. + +## Using nested includes[](#using-nested-includes "Permalink") + +以下示例显示了如何使用不同方法的组合从不同来源嵌套包含对象. + +在此示例中, `.gitlab-ci.yml`本地包含文件`/.gitlab-ci/another-config.yml` : + +``` +include: + - local: /.gitlab-ci/another-config.yml +``` + +`/.gitlab-ci/another-config.yml`包含一个模板和另一个项目中的`/templates/docker-workflow.yml`文件: + +``` +include: + - template: Bash.gitlab-ci.yml + - project: group/my-project + file: /templates/docker-workflow.yml +``` + +该`/templates/docker-workflow.yml`出现在`group/my-project`包括的两个本地文件`group/my-project` : + +``` +include: + - local: /templates/docker-build.yml + - local: /templates/docker-testing.yml +``` + +我们在`group/my-project` `/templates/docker-build.yml`添加了一个`docker-build`作业: + +``` +docker-build: + script: docker build -t my-image . +``` + +我们在`group/my-project`出现的第二个`/templates/docker-test.yml`添加了一个`docker-test`作业: + +``` +docker-test: + script: docker run my-image /run/tests.sh +``` \ No newline at end of file diff --git a/docs/201.md b/docs/201.md new file mode 100644 index 0000000000000000000000000000000000000000..5fca31e1ec00b9b213a10050246be1b3695166a3 --- /dev/null +++ b/docs/201.md @@ -0,0 +1,156 @@ +# Introduction to CI/CD with GitLab + +> 原文:[https://docs.gitlab.com/ee/ci/introduction/](https://docs.gitlab.com/ee/ci/introduction/) + +* [Introduction to CI/CD methodologies](#introduction-to-cicd-methodologies) + * [Continuous Integration](#continuous-integration) + * [Continuous Delivery](#continuous-delivery) + * [Continuous Deployment](#continuous-deployment) +* [Introduction to GitLab CI/CD](#introduction-to-gitlab-cicd) + * [How GitLab CI/CD works](#how-gitlab-cicd-works) + * [Basic CI/CD workflow](#basic-cicd-workflow) + * [A deeper look into the CI/CD basic workflow](#a-deeper-look-into-the-cicd-basic-workflow) + * [Setting up GitLab CI/CD for the first time](#setting-up-gitlab-cicd-for-the-first-time) + +# Introduction to CI/CD with GitLab[](#introduction-to-cicd-with-gitlab "Permalink") + +在本文档中,我们将概述持续集成,持续交付和持续部署的概念,并介绍 GitLab CI / CD. + +**开箱即用的管理系统可以将维护工具链所花费的时间减少 10%或更多.** 观看我们的["精通持续软件开发"](https://about.gitlab.com/webcast/mastering-ci-cd/)网络广播,以了解连续方法以及 GitLab 的内置 CI 如何帮助您简化和扩展软件开发. + +## Introduction to CI/CD methodologies[](#introduction-to-cicd-methodologies "Permalink") + +软件开发的连续方法基于自动执行脚本,以最大程度地减少在开发应用程序时引入错误的机会. 从开发新代码到部署新代码,他们几乎不需要人工干预,甚至根本不需要干预. + +它涉及到在每次小的迭代中就不断地构建,测试和部署代码更改,从而减少了基于错误或失败的先前版本开发新代码的机会. + +此方法有三种主要方法,每种方法都将根据最适合您的策略的方式进行应用. + +### Continuous Integration[](#continuous-integration "Permalink") + +考虑一个应用程序,其代码存储在 GitLab 的 Git 存储库中. 开发人员每天要多次推送代码更改. 对于每次向存储库的推送,您都可以创建一组脚本来自动构建和测试您的应用程序,从而减少了向应用程序引入错误的机会. + +这种做法被称为[持续整合](https://en.wikipedia.org/wiki/Continuous_integration) ; 对于提交给应用程序(甚至是开发分支)的每个更改,它都会自动连续地构建和测试,以确保所引入的更改通过您为应用程序建立的所有测试,准则和代码合规性标准. + +[GitLab 本身](https://gitlab.com/gitlab-org/gitlab-foss)就是使用持续集成作为软件开发方法的一个示例. 对于项目的每一次推送,都有一组检查脚本的脚本. + +### Continuous Delivery[](#continuous-delivery "Permalink") + +[持续交付](https://continuousdelivery.com/)是超越持续集成的一步. 您的应用程序不仅会在推送到代码库的每次代码更改时都进行构建和测试,而且作为附加步骤,尽管部署是手动触发的,但它仍会持续部署. + +此方法可确保自动检查代码,但需要人工干预才能从策略上手动触发更改的部署. + +### Continuous Deployment[](#continuous-deployment "Permalink") + +类似于持续交付, [持续部署](https://www.airpair.com/continuous-deployment/posts/continuous-deployment-for-practical-people)也是超越持续集成的又一步. 区别在于,您无需将其手动部署,而是将其设置为自动部署. 部署您的应用程序完全不需要人工干预. + +## Introduction to GitLab CI/CD[](#introduction-to-gitlab-cicd "Permalink") + +GitLab CI / CD 是内置在 GitLab 中的功能强大的工具,它使您可以将所有连续方法(连续集成,交付和部署)应用于软件,而无需第三方应用程序或集成. + +有关概述,请参阅最近的 GitLab 聚会中的[GitLab CI 简介](https://www.youtube.com/watch?v=l5705U8s_nQ&t=397) . + +### How GitLab CI/CD works[](#how-gitlab-cicd-works "Permalink") + +要使用 GitLab CI / CD,您需要做的是托管在 Git 存储库中的应用程序代码库,并在[`.gitlab-ci.yml`](../yaml/README.html)文件中指定生成,测试和部署脚本,该文件位于以下目录的根路径中:您的存储库. + +在此文件中,您可以定义要运行的脚本,定义包含和缓存依赖项,选择要按顺序运行的命令和要并行运行的命令,定义要在哪里部署应用程序,以及指定是否将要自动运行脚本或手动触发任何脚本. 熟悉 GitLab CI / CD 后,您可以在配置文件中添加更多高级步骤. + +要将脚本添加到该文件,您需要按照适合您的应用程序并符合您要执行的测试的顺序来组织它们. 为了可视化该过程,假设添加到配置文件中的所有脚本与在计算机的终端上运行的命令相同. + +将`.gitlab-ci.yml`配置文件添加到存储库后,GitLab 将检测到该文件并使用名为[GitLab Runner](https://docs.gitlab.com/runner/)的工具运行脚本,该工具的操作与终端类似. + +这些脚本被分组为**作业** ,它们共同组成了一个**管道** . `.gitlab-ci.yml`文件的一个简约示例可以包含: + +``` +before_script: + - apt-get install rubygems ruby-dev -y + +run-test: + script: + - ruby --version +``` + +`before_script`属性将在运行任何内容之前为您的应用程序安装依赖项,并且名为`run-test`的**作业**将打印当前系统的 Ruby 版本. 它们两者都构成了在每次推送到存储库的任何分支时触发的**管道** . + +GitLab CI / CD 不仅执行您已设置的作业,而且还向您显示执行期间发生的事情,就像您在终端中看到的那样: + +[![job running](img/b452a194fd7fbbdd22f73a1dda9b236a.png)](img/job_running.png) + +您为您的应用程序创建了策略,GitLab 根据您定义的内容为您运行管道. 您的管道状态也会由 GitLab 显示: + +[![pipeline status](img/be1eaf723e0603b081c01aa4310c304c.png)](img/pipeline_status.png) + +最后,如果出现任何问题,您可以轻松[回滚](../environments/index.html#retrying-and-rolling-back)所有更改: + +[![rollback button](img/ce2f28e687df2b322895dbfb6c48d389.png)](img/rollback.png) + +### Basic CI/CD workflow[](#basic-cicd-workflow "Permalink") + +考虑以下示例,以了解 GitLab CI / CD 如何适合通用开发工作流程. + +假设您已在一个问题中讨论了代码实现,并在本地进行了建议的更改. 将提交推送到 GitLab 中的远程存储库中的功能分支后,将触发项目的 CI / CD 管道集. 这样,GitLab CI / CD: + +* 运行自动化脚本(顺序或并行)以: + * 构建并测试您的应用. + * 就像在`localhost`看到的那样,使用 Review Apps 预览每个合并请求的更改. + +对实施感到满意后: + +* 让您的代码得到审查和批准. +* 将功能分支合并到默认分支. + * GitLab CI / CD 将您的更改自动部署到生产环境. +* 最后,如果出现问题,您和您的团队可以轻松地将其回滚. + +[![GitLab workflow example](img/4ab2d185d65e76a0d58ad6564dff777a.png)](img/gitlab_workflow_example_11_9.png) + +GitLab CI / CD 可以做更多的事情,但是此工作流程体现了 GitLab 跟踪整个过程的能力,而无需使用外部工具来交付软件. 而且,最有用的是,您可以通过 GitLab UI 可视化所有步骤. + +#### A deeper look into the CI/CD basic workflow[](#a-deeper-look-into-the-cicd-basic-workflow "Permalink") + +如果我们深入研究基本工作流程,则可以在 DevOps 生命周期的每个阶段看到 GitLab 中可用的功能,如下图所示. + +[![Deeper look into the basic CI/CD workflow](img/33c514aefa1ff87fe18907b27d473e03.png)](img/gitlab_workflow_example_extended_v12_3.png) + +如果您从左至右查看图像,则会根据每个阶段(验证,打包,发布)看到 GitLab 中的一些可用功能. + +1. **Verify**: + * 通过持续集成自动构建和测试您的应用程序. + * 使用[GitLab 代码质量](../../user/project/merge_requests/code_quality.html)分析您的源代码[质量](../../user/project/merge_requests/code_quality.html) . + * 使用[浏览器性能测试](../../user/project/merge_requests/browser_performance_testing.html)确定代码更改对性能的影响. + * 执行一系列测试,例如[容器扫描](../../user/application_security/container_scanning/index.html) , [依赖扫描](../../user/application_security/dependency_scanning/index.html) 和[JUnit 测试](../junit_test_reports.html) . + * 使用[Review Apps](../review_apps/index.html)部署更改,以预览每个分支上的应用程序更改. +2. **Package**: + * 使用[Container Registry](../../user/packages/container_registry/index.html)存储 Docker 映像. + * 使用[NPM Registry](../../user/packages/npm_registry/index.html)存储 NPM 软件包. + * 用[Maven 存储库](../../user/packages/maven_repository/index.html)存储 Maven 工件. + * 将 Conan 软件包存储在[Conan 仓库中](../../user/packages/conan_repository/index.html) . +3. **Release**: + * 持续部署,自动将您的应用程序部署到生产环境. + * 连续交付,手动单击以将您的应用程序部署到生产环境. + * 使用[GitLab Pages](../../user/project/pages/index.html)部署静态网站. + * 仅将功能部件运送到您的一部分吊舱中,并让一定比例的用户群通过[Canary Deployments](../../user/project/canary_deployments.html)访问临时部署的功能部件. + * 在[功能标记](../../operations/feature_flags.html)后面部署[功能](../../operations/feature_flags.html) . + * 使用[GitLab Releases](../../user/project/releases/index.html)向任何 Git 标签添加发行说明. + * View of the current health and status of each CI environment running on Kubernetes with [Deploy Boards](../../user/project/deploy_boards.html). + * 使用[Auto Deploy](../../topics/autodevops/stages.html#auto-deploy)将应用程序部署到 Kubernetes 集群中的生产环境. + +使用 GitLab CI / CD,您还可以: + +* 通过[Auto DevOps](../../topics/autodevops/index.html)轻松设置应用程序的整个生命周期. +* 将您的应用程序部署到不同的[环境](../environments/index.html) . +* 安装自己的[GitLab Runner](https://docs.gitlab.com/runner/) . +* [Schedule pipelines](../pipelines/schedules.html). +* 使用[安全测试报告](../../user/application_security/index.html)检查应用程序漏洞. + +要查看所有 CI / CD 功能,请导航回[CI / CD 索引](../README.html) . + +观看视频[GitLab CI Live 演示](https://youtu.be/l5705U8s_nQ?t=369) ,深入了解 GitLab CI / CD. + +### Setting up GitLab CI/CD for the first time[](#setting-up-gitlab-cicd-for-the-first-time "Permalink") + +要开始使用 GitLab CI / CD,您需要熟悉[`.gitlab-ci.yml`](../yaml/README.html)配置文件的语法及其属性. + +本文档[在 GitLab Pages 的范围内介绍了 GitLab CI / CD 的概念](../../user/project/pages/getting_started/pages_from_scratch.html) ,用于部署静态网站. 尽管它是为想要从头开始编写自己的 Pages 脚本的用户而设计的,但它也可以作为 GitLab CI / CD 设置过程的简介. 它涵盖了编写 CI / CD 配置文件的最初一般步骤,因此我们建议您通读它以了解 GitLab 的 CI / CD 逻辑,并学习如何为任何应用程序编写自己的脚本(或调整现有脚本). + +要深入了解 GitLab 的 CI / CD 配置选项,请查看[`.gitlab-ci.yml`完整参考](../yaml/README.html) . \ No newline at end of file diff --git a/docs/202.md b/docs/202.md new file mode 100644 index 0000000000000000000000000000000000000000..42613889e09d76dc10128827815209ac0d416d09 --- /dev/null +++ b/docs/202.md @@ -0,0 +1,172 @@ +# Getting started with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/quick_start/README.html](https://docs.gitlab.com/ee/ci/quick_start/README.html) + +* [Creating a `.gitlab-ci.yml` file](#creating-a-gitlab-ciyml-file) + * [What is `.gitlab-ci.yml`](#what-is-gitlab-ciyml) + * [Creating a simple `.gitlab-ci.yml` file](#creating-a-simple-gitlab-ciyml-file) + * [Push `.gitlab-ci.yml` to GitLab](#push-gitlab-ciyml-to-gitlab) +* [Configuring a Runner](#configuring-a-runner) + * [Shared Runners](#shared-runners) +* [Seeing the status of your pipeline and jobs](#seeing-the-status-of-your-pipeline-and-jobs) +* [Examples](#examples) + +# Getting started with GitLab CI/CD[](#getting-started-with-gitlab-cicd "Permalink") + +**注意:**从 8.0 版开始,GitLab [持续集成](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/) (CI)已完全集成到 GitLab 本身,并且默认情况下在所有项目上都[启用](../enable_or_disable_ci.html) .**注意:**请记住,只有项目维护者和管理员用户有权访问项目的设置.**注意:**要从 Jenkins 转到 GitLab 吗? 查阅我们的[参考](../jenkins/index.html) ,将您先前存在的管道转换为我们的格式.**注意:**您可以考虑在项目中使用几种不同的[基本管道体系结构](../pipelines/pipeline_architectures.html) . 您可能需要在开始之前熟悉这些内容. + +GitLab 提供[持续集成](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)服务. 对于每次提交或推送以触发您的 CI [管道](../pipelines/index.html) ,您必须: + +* Add a [`.gitlab-ci.yml` file](#creating-a-gitlab-ciyml-file) to your repository’s root directory. +* 确保将项目配置为使用[Runner](#configuring-a-runner) . + +`.gitlab-ci.yml`文件告诉 GitLab Runner 做什么. 一个简单的管道通常包括三个[阶段](../yaml/README.html#stages) : + +* `build` +* `test` +* `deploy` + +您不需要使用所有三个阶段; 没有工作的阶段将被忽略. + +管道显示在项目的**CI / CD>管道**页面下. 如果一切运行正常(没有非零返回值),您将获得与提交关联的绿色复选标记. 这样就可以轻松查看提交是否导致任何测试失败,甚至无需查看作业(测试)日志. 许多项目使用 GitLab 的 CI 服务来运行测试套件,因此如果开发人员遇到问题,他们会立即获得反馈. + +通常,使用管道将经过测试的代码自动部署到登台和生产环境中. + +* * * + +本指南假定您具有: + +* 8.0+或正在使用[GitLab.com 的](https://gitlab.com)有效 GitLab 实例. +* 您要在其中使用 CI 的 GitLab 中的项目. +* 维护者或所有者对项目的访问 + +让我们将其分解为 GitLab CI / CD 难题. + +## Creating a `.gitlab-ci.yml` file[](#creating-a-gitlab-ciyml-file "Permalink") + +在创建`.gitlab-ci.yml`之前,让我们首先简要地解释这是怎么回事. + +### What is `.gitlab-ci.yml`[](#what-is-gitlab-ciyml "Permalink") + +您可以在`.gitlab-ci.yml`文件中配置 CI 对项目的作用. 它位于存储库的根目录中. + +在对存储库进行任何推送时,GitLab 都会查找`.gitlab-ci.yml`文件,并根据该文件的内容在*Runners*上启动作业,以进行提交. + +由于`.gitlab-ci.yml`在存储库中并且受版本控制,因此旧版本仍然可以成功构建,fork 可以轻松使用 CI,分支可以具有不同的管道和作业,并且您拥有 CI 的唯一真实来源. 您可以[在我们的博客中](https://about.gitlab.com/blog/2015/05/06/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml/)阅读更多有关为什么使用`.gitlab-ci.yml`的原因. + +### Creating a simple `.gitlab-ci.yml` file[](#creating-a-simple-gitlab-ciyml-file "Permalink") + +> **注意:** `.gitlab-ci.yml`是一个[YAML](https://en.wikipedia.org/wiki/YAML)文件,因此您必须特别注意缩进. 始终使用空格,不要使用制表符. + +您需要在存储库的根目录中创建一个名为`.gitlab-ci.yml`的文件. 以下是 Ruby on Rails 项目的示例. + +``` +image: "ruby:2.5" + +before_script: + - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs + - ruby -v + - which ruby + - gem install bundler --no-document + - bundle install --jobs $(nproc) "${FLAGS[@]}" + +rspec: + script: + - bundle exec rspec + +rubocop: + script: + - bundle exec rubocop +``` + +This is the simplest possible configuration that will work for most Ruby applications: + +1. 用要执行的不同命令定义两个作业`rspec`和`rubocop` (名称是任意的). +2. 在执行每个作业之前,将执行`before_script`定义的命令. + +`.gitlab-ci.yml`文件定义了作业集,并限制了作业的运行方式和时间. 作业被定义为具有名称的顶级元素(在我们的示例中为`rspec`和`rubocop` ),并且始终必须包含`script`关键字. 乔布斯被用于创造就业机会,然后由挑选[运动员](../runners/README.html)和跑步者的环境中执行. + +重要的是每个作业都彼此独立运行. + +如果要检查项目的`.gitlab-ci.yml`是否有效,则项目名称空间的`/-/ci/lint`页下有一个 Lint 工具. 您也可以在项目的**CI / CD➔管道**和**管道➔作业**下找到" CI Lint"按钮以转到此页面. + +有关更多信息和完整的`.gitlab-ci.yml`语法,请阅读[`.gitlab-ci.yml`上的参考文档](../yaml/README.html) . + +### Push `.gitlab-ci.yml` to GitLab[](#push-gitlab-ciyml-to-gitlab "Permalink") + +创建`.gitlab-ci.yml` ,应将其添加到 Git 存储库中并将其推送到 GitLab. + +``` +git add .gitlab-ci.yml +git commit -m "Add .gitlab-ci.yml" +git push origin master +``` + +现在,如果您转到" **管道"**页面,您将看到管道处于挂起状态. + +**注意:**如果您有一个[从 GitLab 提取镜像的存储库](../../user/project/repository/repository_mirroring.html#pulling-from-a-remote-repository-starter) ,则可能需要在项目的**"设置">"存储库">"从远程存储库中提取">"触发管道以进行镜像更新"中**启用管道触发. + +您也可以转到" **提交"**页面,注意提交 SHA 旁边的小暂停图标. + +[![New commit pending](img/3b3e644f832753a09f245236299e74b2.png)](img/new_commit.png) + +单击它,您将被定向到该特定提交的作业页面. + +[![Single commit jobs page](img/f8cfebdbd362ba809375c8d9c38416ba.png)](img/single_commit_status_pending.png) + +注意,有一个待处理的作业以我们在`.gitlab-ci.yml`编写的`.gitlab-ci.yml` . "卡住"表示尚未为此作业配置任何运行器. + +下一步是配置运行器,以便它选择挂起的作业. + +## Configuring a Runner[](#configuring-a-runner "Permalink") + +在 GitLab 中,Runners 运行您在`.gitlab-ci.yml`定义的作业. Runner 可以是虚拟机,VPS,裸机,Docker 容器甚至是容器集群. GitLab 和 Runners 通过 API 进行通信,因此唯一的要求是 Runner 的计算机具有对 GitLab 服务器的网络访问权限. + +Runner 可以特定于某个项目,也可以在 GitLab 中服务多个项目. 如果它服务于所有项目,则称为*Shared Runner* . + +在" [跑步者"](../runners/README.html)文档中查找有关不同跑步者的更多信息. + +您可以通过转到**设置➔CI / CD**来查找是否将任何跑步者分配给您的项目. 设置 Runner 既简单又直接. GitLab 支持的官方 Runner 是用 Go 编写的,其文档可以在[https://docs.gitlab.com/runner/中](https://docs.gitlab.com/runner/)找到. + +为了拥有功能正常的 Runner,您需要执行以下两个步骤: + +1. [Install it](https://docs.gitlab.com/runner/install/) +2. [Configure it](https://docs.gitlab.com/runner/configuration/) + +请按照上面的链接设置您自己的 Runner 或使用下一节所述的 Shared Runner. + +设置 Runner 之后,您应该在**设置➔CI / CD**后面的项目的 Runners 页面上看到它. + +[![Activated runners](img/423e566cce1da11ef163c69219f870aa.png)](img/runners_activated.png) + +### Shared Runners[](#shared-runners "Permalink") + +如果使用[GitLab.com](https://gitlab.com/) ,则可以使用 GitLab Inc.提供的**共享运行程序** . + +这些是在 GitLab 基础架构上运行的特殊虚拟机,可以构建任何项目. + +要启用**共享运行程序,**您必须转到项目的**设置➔CI / CD** ,然后单击**启用共享运行程序** . + +[Read more on Shared Runners](../runners/README.html). + +## Seeing the status of your pipeline and jobs[](#seeing-the-status-of-your-pipeline-and-jobs "Permalink") + +成功配置 Runner 之后,您应该看到上一次提交的状态从" *未决"*更改为" *正在* *运行"* ," *成功"*或" *失败"* . + +您可以转到项目中的" **管道"**页面来查看所有管道. + +[![Commit status](img/0748208b938145b0cf688cc0a3cb7b09.png)](img/pipelines_status.png) + +或者,您可以转到" **管道➔作业"**页面查看所有作业. + +[![Commit status](img/c0fd76908cea66a75fbd88aeb1ccec31.png)](img/builds_status.png) + +通过单击作业的状态,您将能够看到该作业的日志. 这对于诊断工作为什么失败或行为与您预期的不同很重要. + +[![Build log](img/f5f57e5e3d074f574a5b26d23eb0b721.png)](img/build_log.png) + +您还可以在 GitLab 的各个页面中查看任何提交的状态,例如**提交**和**合并请求** . + +## Examples[](#examples "Permalink") + +请访问[示例自述文件](../examples/README.html)以查看使用各种语言的 GitLab CI 的示例列表. \ No newline at end of file diff --git a/docs/203.md b/docs/203.md new file mode 100644 index 0000000000000000000000000000000000000000..ea42af4eb2b08c797a960758512c5396b4caebf6 --- /dev/null +++ b/docs/203.md @@ -0,0 +1,80 @@ +# How to enable or disable GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/enable_or_disable_ci.html](https://docs.gitlab.com/ee/ci/enable_or_disable_ci.html) + +* [Per-project user setting](#per-project-user-setting) +* [Site-wide admin setting](#site-wide-admin-setting) + +# How to enable or disable GitLab CI/CD[](#how-to-enable-or-disable-gitlab-cicd "Permalink") + +为了有效使用 GitLab CI / CD,您需要: + +* 项目根目录中存在一个有效的[`.gitlab-ci.yml`](yaml/README.html)文件. +* [跑步者](runners/README.html)正确设置. + +您可以阅读我们的[快速入门指南](quick_start/README.html)以开始使用. + +如果您使用的是 Jenkins 或 Drone CI 之类的外部 CI / CD 服务器,建议禁用 GitLab CI / CD,以免与提交状态 API 发生冲突. + +GitLab CI/CD is exposed via the `/pipelines` and `/jobs` pages of a project. Disabling GitLab CI/CD in a project does not delete any previous jobs. In fact, the `/pipelines` and `/jobs` pages can still be accessed, although it’s hidden from the left sidebar menu. + +GitLab CI / CD 在新安装中默认情况下处于启用状态,并且可以被禁用: + +* 在每个项目的设置下单独进行. +* 通过修改分别用于源代码安装和 Omnibus 安装的`gitlab.yml`和`gitlab.rb`的设置在`gitlab.yml`站点范围内. + +**注意:**这仅适用于作为 GitLab CI / CD 的一部分运行的管道. 这将不会启用或禁用通过[外部集成](../user/project/integrations/overview.html#integrations-listing)运行的管道. + +## Per-project user setting[](#per-project-user-setting "Permalink") + +要在项目中启用或禁用 GitLab CI / CD 管道: + +1. 导航至**设置>常规>可见性,项目功能,权限** . +2. 展开**存储库**部分 +3. 根据需要启用或禁用" **管道"**切换. + +**项目可见性**还将影响管道可见性. 如果设置为: + +* **私有** :只有项目成员才能访问管道. +* **内部**或**公共** :可以通过下拉框将管道设置为" **仅项目成员"**或" **具有访问权限的所有人** ". + +按**保存更改**以使设置生效. + +## Site-wide admin setting[](#site-wide-admin-setting "Permalink") + +您可以在`gitlab.yml`站点上禁用 GitLab CI / CD,方法是修改`gitlab.yml`用于源代码安装的设置,以及`gitlab.rb`用于 Omnibus 安装的设置. + +有两件事要注意: + +* 禁用 GitLab CI / CD,将仅影响新创建的项目. 在此修改之前启用了此功能的项目将照常工作. +* 即使您禁用了 GitLab CI / CD,用户仍然可以在项目的设置中启用它. + +对于源安装, `gitlab.yml`使用编辑器打开`gitlab.yml`并将`builds`设置为`false` : + +``` +## Default project features settings +default_projects_features: + issues: true + merge_requests: true + wiki: true + snippets: false + builds: false +``` + +保存文件并重新启动 GitLab: + +``` +sudo service gitlab restart +``` + +对于 Omnibus 安装,请编辑`/etc/gitlab/gitlab.rb`并添加以下行: + +``` +gitlab_rails['gitlab_default_projects_features_builds'] = false +``` + +保存文件并重新配置 GitLab: + +``` +sudo gitlab-ctl reconfigure +``` \ No newline at end of file diff --git a/docs/204.md b/docs/204.md new file mode 100644 index 0000000000000000000000000000000000000000..ffe0a500e8e38d706b69bac121f09ac59af2b19c --- /dev/null +++ b/docs/204.md @@ -0,0 +1,164 @@ +# Using SSH keys with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/ssh_keys/README.html](https://docs.gitlab.com/ee/ci/ssh_keys/README.html) + +* [How it works](#how-it-works) +* [SSH keys when using the Docker executor](#ssh-keys-when-using-the-docker-executor) +* [SSH keys when using the Shell executor](#ssh-keys-when-using-the-shell-executor) +* [Verifying the SSH host keys](#verifying-the-ssh-host-keys) +* [Example project](#example-project) + +# Using SSH keys with GitLab CI/CD[](#using-ssh-keys-with-gitlab-cicd "Permalink") + +GitLab 当前不支持在构建环境(运行 GitLab Runner 的环境)中管理 SSH 密钥的内置支持. + +SSH 密钥在以下情况下很有用: + +1. 您想签出内部子模块 +2. 您想使用包管理器(例如 Bundler)下载私有包 +3. 您想要将应用程序部署到自己的服务器上,例如 Heroku +4. 您要执行从构建环境到远程服务器的 SSH 命令 +5. 您想将文件从构建环境同步到远程服务器 + +如果上述任何事情都响了,那么您很可能需要 SSH 密钥. + +支持最广泛的方法是通过扩展`.gitlab-ci.yml`来将 SSH 密钥注入构建环境,该解决方案可与任何类型的[执行器](https://docs.gitlab.com/runner/executors/) (Docker,shell 等)一起使用. + +## How it works[](#how-it-works "Permalink") + +1. 使用[`ssh-keygen`](https://linux.die.net/man/1/ssh-keygen)在本地创建新的 SSH 密钥对 +2. 将私钥作为[变量](../variables/README.html)添加到您的项目中 +3. 在作业期间运行[`ssh-agent`](https://linux.die.net/man/1/ssh-agent)以加载私钥. +4. 将公用密钥复制到您要访问的服务器上(通常在`~/.ssh/authorized_keys` ),如果要访问私有的 GitLab 存储库,则将其添加为[部署密钥](../../ssh/README.html#deploy-keys) . + +**注意:**除非您启用[调试日志](../variables/README.html#debug-logging)记录,否则私钥将不会显示在作业日志中. 您可能还需要检查[管道](../pipelines/settings.html#visibility-of-pipelines)的[可见性](../pipelines/settings.html#visibility-of-pipelines) . + +## SSH keys when using the Docker executor[](#ssh-keys-when-using-the-docker-executor "Permalink") + +当您的 CI / CD 作业在 Docker 容器中运行(意味着包含环境)并且您想要在私有服务器中部署代码时,您需要一种访问它的方法. 这是 SSH 密钥对派上用场的地方. + +1. 您首先需要创建一个 SSH 密钥对. 有关更多信息,请按照说明[生成 SSH 密钥](../../ssh/README.html#generating-a-new-ssh-key-pair) . **不要**在 SSH 密钥中添加密码,否则`before_script`会提示您输入密码. + +2. 创建一个新[变量](../variables/README.html#gitlab-cicd-environment-variables) . 在" **密钥"中**输入名称`SSH_PRIVATE_KEY`然后在" **值"**字段中粘贴先前创建的*私钥*的内容. + +3. 使用`before_script`操作修改`.gitlab-ci.yml` . 在以下示例中,假定使用基于 Debian 的图像. 根据需要进行编辑: + + ``` + before_script: + ## + ## Install ssh-agent if not already installed, it is required by Docker. + ## (change apt-get to yum if you use an RPM-based image) + ## + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + + ## + ## Run ssh-agent (inside the build environment) + ## + - eval $(ssh-agent -s) + + ## + ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store + ## We're using tr to fix line endings which makes ed25519 keys work + ## without extra base64 encoding. + ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556 + ## + - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - + + ## + ## Create the SSH directory and give it the right permissions + ## + - mkdir -p ~/.ssh + - chmod 700 ~/.ssh + + ## + ## Optionally, if you will be using any Git commands, set the user name and + ## and email. + ## + #- git config --global user.email "user@example.com" + #- git config --global user.name "User name" + ``` + + **注意:** [`before_script`](../yaml/README.html#before_script-and-after_script)可以全局设置或按作业设置. +4. 确保专用服务器的[SSH 主机密钥已验证](#verifying-the-ssh-host-keys) . + +5. 作为最后一步,从添加您在第一步,你想拥有从构建环境中的接入服务创建一个*公共*密钥. 如果要访问私有的 GitLab 存储库,则需要将其添加为[部署密钥](../../ssh/README.html#deploy-keys) . + +而已! 现在,您可以在构建环境中访问私有服务器或存储库. + +## SSH keys when using the Shell executor[](#ssh-keys-when-using-the-shell-executor "Permalink") + +如果您使用的是 Shell 执行程序而不是 Docker,则设置 SSH 密钥会更加容易. + +您可以从安装了 GitLab Runner 的计算机生成 SSH 密钥,并将该密钥用于在该计算机上运行的所有项目. + +1. 首先,登录到运行您的作业的服务器. + +2. 然后,从终端以`gitlab-runner`用户身份登录: + + ``` + sudo su - gitlab-runner + ``` + +3. 按照说明生成 SSH 密钥对,以[生成 SSH 密钥](../../ssh/README.html#generating-a-new-ssh-key-pair) . **不要**在 SSH 密钥中添加密码,否则`before_script`会提示您输入密码. + +4. 作为最后一步,加前面创建要具有从构建环境中的接入服务的一个*公共*密钥. 如果要访问私有的 GitLab 存储库,则需要将其添加为[部署密钥](../../ssh/README.html#deploy-keys) . + +完成后,尝试登录到远程服务器以接受指纹: + +``` +ssh example.com +``` + +要访问 GitLab.com 上的存储库,可以使用`git@gitlab.com` . + +## Verifying the SSH host keys[](#verifying-the-ssh-host-keys "Permalink") + +最好检查私有服务器自己的公用密钥,以确保您不会受到中间人攻击的攻击. 万一发生任何可疑事件,您将注意到它,因为作业将失败(如果公钥不匹配,则 SSH 连接将失败). + +要查找服务器的主机密钥,请从受信任的网络(最好是从私有服务器本身)运行`ssh-keyscan`命令: + +``` +## Use the domain name +ssh-keyscan example.com + +## Or use an IP +ssh-keyscan 1.2.3.4 +``` + +使用`SSH_KNOWN_HOSTS`作为"密钥"创建一个新[变量](../variables/README.html#gitlab-cicd-environment-variables) ,并作为"值"添加`ssh-keyscan`的输出. + +**注意:**如果需要连接到多个服务器,则所有服务器主机密钥都需要收集在变量的**Value**中,每行一个密钥.**提示:**通过在`.gitlab-ci.yml`直接使用变量而不是`ssh-keyscan` ,这样做的好处是,如果主机域名由于某种原因而更改,则不必更改`.gitlab-ci.yml` . 而且,这些值是由您预定义的,这意味着如果主机密钥突然更改,CI / CD 作业将失败,并且您将知道服务器或网络出了点问题. + +现在已经创建了`SSH_KNOWN_HOSTS`变量,除了上面[`.gitlab-ci.yml`](#ssh-keys-when-using-the-docker-executor)的[内容](#ssh-keys-when-using-the-docker-executor)之外,还需要添加以下内容: + +``` +before_script: + ## + ## Assuming you created the SSH_KNOWN_HOSTS variable, uncomment the + ## following two lines. + ## + - echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts + - chmod 644 ~/.ssh/known_hosts + + ## + ## Alternatively, use ssh-keyscan to scan the keys of your private server. + ## Replace example.com with your private server's domain name. Repeat that + ## command if you have more than one server to connect to. + ## + #- ssh-keyscan example.com >> ~/.ssh/known_hosts + #- chmod 644 ~/.ssh/known_hosts + + ## + ## You can optionally disable host key checking. Be aware that by adding that + ## you are susceptible to man-in-the-middle attacks. + ## WARNING: Use this only with the Docker executor, if you use it with shell + ## you will overwrite your user's SSH config. + ## + #- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config' +``` + +## Example project[](#example-project "Permalink") + +为了方便起见,我们建立了一个[示例 SSH 项目](https://gitlab.com/gitlab-examples/ssh-private-key/) ,使用我们的公共[共享](../runners/README.html)运行程序在[GitLab.com](https://gitlab.com)上运行. + +想要破解吗? 只需对其进行分叉,提交并推送您的更改. 稍后,公共跑步者将选择更改并开始工作. \ No newline at end of file diff --git a/docs/205.md b/docs/205.md new file mode 100644 index 0000000000000000000000000000000000000000..f3530272e1b1a92eb24d051f72cc5c677e128450 --- /dev/null +++ b/docs/205.md @@ -0,0 +1,342 @@ +# Migrating from CircleCI + +> 原文:[https://docs.gitlab.com/ee/ci/migration/circleci.html](https://docs.gitlab.com/ee/ci/migration/circleci.html) + +* [`config.yml` vs `gitlab-ci.yml`](#configyml-vs-gitlab-ciyml) + * [Jobs](#jobs) + * [Docker image definition](#docker-image-definition) + * [Workflows](#workflows) + * [Parallel and sequential job execution](#parallel-and-sequential-job-execution) + * [Scheduled run](#scheduled-run) + * [Manual run](#manual-run) + * [Filter job by branch](#filter-job-by-branch) + * [Caching](#caching) +* [Contexts and variables](#contexts-and-variables) +* [Orbs](#orbs) +* [Build environments](#build-environments) + * [Machine and specific build environments](#machine-and-specific-build-environments) + +# Migrating from CircleCI[](#migrating-from-circleci "Permalink") + +如果您当前正在使用 CircleCI,则可以将 CI / CD 管道迁移到[GitLab CI / CD](../introduction/index.html) ,并开始使用其所有强大功能. 查看我们的[CircleCI 与 GitLab](https://about.gitlab.com/devops-tools/circle-ci-vs-gitlab.html)比较,以了解有什么不同. + +在开始迁移之前,我们已经收集了一些您可能会觉得有用的资源. + +[快速入门指南](../quick_start/README.html)很好地概述了 GitLab CI / CD 的工作方式. 您可能还对[Auto DevOps](../../topics/autodevops/index.html)感兴趣,可以将其用于构建,测试和部署应用程序,而几乎不需要或根本不需要进行任何配置. + +对于高级 CI / CD 团队, [自定义项目模板](../../user/admin_area/custom_project_templates.html)可以启用管道配置的重用. + +如果您有未在此处回答的问题, [GitLab 社区论坛](https://forum.gitlab.com/)将是一个很好的资源. + +## `config.yml` vs `gitlab-ci.yml`[](#configyml-vs-gitlab-ciyml "Permalink") + +CircleCI 的`config.yml`配置文件定义了脚本,作业和工作流程(在 GitLab 中称为"阶段"). 在 GitLab 中,对存储库根目录中的`.gitlab-ci.yml`文件使用类似的方法. + +### Jobs[](#jobs "Permalink") + +在 CircleCI 中,作业是执行特定任务的步骤的集合. 在 GitLab 中, [作业](../yaml/README.html#introduction)也是配置文件中的基本元素. 在 GitLab CI / CD 中,不需要`checkout`参数,因为系统会自动获取存储库. + +CircleCI 示例作业定义: + +``` +jobs: + job1: + steps: + - checkout + - run: "execute-script-for-job1" +``` + +GitLab CI / CD 中相同作业定义的示例: + +``` +job1: + script: "execute-script-for-job1" +``` + +### Docker image definition[](#docker-image-definition "Permalink") + +CircleCI 在作业级别定义图像,GitLab CI / CD 也支持该图像. 此外,GitLab CI / CD 支持全局设置此设置,以供所有未定义`image`作业使用. + +CircleCI 示例图像定义: + +``` +jobs: + job1: + docker: + - image: ruby:2.6 +``` + +Example of the same image definition in GitLab CI/CD: + +``` +job1: + image: ruby:2.6 +``` + +### Workflows[](#workflows "Permalink") + +CircleCI 确定具有`workflows`作业的运行顺序. 这也可用于确定并发,顺序,计划或手动运行. GitLab CI / CD 中的等效功能称为[stage](../yaml/README.html#stages) . 同一阶段的作业并行运行,并且仅在先前阶段完成后才运行. 默认情况下,当作业失败时,将跳过下一阶段的执行,但是即使[在](../yaml/README.html#allow_failure)作业失败之后,也可以继续执行下一阶段. + +有关可使用的不同类型的管道的指南,请参见["管道体系结构概述](../pipelines/pipeline_architectures.html) ". 可以定制管道来满足您的需求,例如大型复杂项目或具有独立定义组件的 monorepo. + +#### Parallel and sequential job execution[](#parallel-and-sequential-job-execution "Permalink") + +以下示例显示了作业如何并行或顺序运行: + +1. `job1`和`job2`并行运行(在 GitLab CI / CD 的`build`阶段). +2. 仅在`job1`和`job2`成功完成之后(在`test`阶段), `job1` `job3`运行. +3. 仅在`job3`成功完成之后(在`deploy`阶段), `job3` `job4`运行. + +CircleCI `workflows`示例: + +``` +version: 2 +jobs: + job1: + steps: + - checkout + - run: make build dependencies + job2: + steps: + - run: make build artifacts + job3: + steps: + - run: make test + job4: + steps: + - run: make deploy + +workflows: + version: 2 + jobs: + - job1 + - job2 + - job3: + requires: + - job1 + - job2 + - job4: + requires: + - job3 +``` + +与 GitLab CI / CD 中的`stages`相同的工作流程示例: + +``` +stages: + - build + - test + - deploy + +job 1: + stage: build + script: make build dependencies + +job 2: + stage: build + script: make build artifacts + +job3: + stage: test + script: make test + +job4: + stage: deploy + script: make deploy +``` + +#### Scheduled run[](#scheduled-run "Permalink") + +GitLab CI / CD 具有易于使用的 UI 来[调度管道](../pipelines/schedules.html) . 同样,可以使用[规则](../yaml/README.html#rules)来确定是否应将作业包括在计划的管道中或从计划的管道中排除. + +计划的工作流程的 CircleCI 示例: + +``` +commit-workflow: + jobs: + - build +scheduled-workflow: + triggers: + - schedule: + cron: "0 1 * * *" + filters: + branches: + only: try-schedule-workflow + jobs: + - build +``` + +使用 GitLab CI / CD 中的[`rules`](../yaml/README.html#rules)使用同一调度管道的示例: + +``` +job1: + script: + - make build + rules: + - if: '$CI_PIPELINE_SOURCE == "schedule" && $CI_COMMIT_REF_NAME == "try-schedule-workflow"' +``` + +保存管道配置后,您可以在[GitLab UI 中](../pipelines/schedules.html#configuring-pipeline-schedules)配置 cron 计划,并且还可以在 UI 中启用或禁用计划. + +#### Manual run[](#manual-run "Permalink") + +手动工作流程的 CircleCI 示例: + +``` +release-branch-workflow: + jobs: + - build + - testing: + requires: + - build + - deploy: + type: approval + requires: + - testing +``` + +使用[`when: manual`](../yaml/README.html#whenmanual) GitLab CI / CD 中的[`when: manual`](../yaml/README.html#whenmanual)的相同工作流程示例: + +``` +deploy_prod: + stage: deploy + script: + - echo "Deploy to production server" + when: manual +``` + +### Filter job by branch[](#filter-job-by-branch "Permalink") + +[规则](../yaml/README.html#rules)是一种机制,用于确定作业是否将针对特定分支运行. + +按分支过滤的作业的 CircleCI 示例: + +``` +jobs: + deploy: + branches: + only: + - master + - /rc-.*/ +``` + +在 GitLab CI / CD 中使用`rules`的相同工作流程示例: + +``` +deploy_prod: + stage: deploy + script: + - echo "Deploy to production server" + rules: + - if: '$CI_COMMIT_BRANCH == "master"' +``` + +### Caching[](#caching "Permalink") + +GitLab 提供了一种缓存机制,可通过重用以前下载的依赖项来加快作业的构建时间. 重要的是要了解[缓存和工件](../caching/index.html#cache-vs-artifacts)之间的区别,以充分利用这些功能. + +使用缓存的作业的 CircleCI 示例: + +``` +jobs: + job1: + steps: + - restore_cache: + key: source-v1-< .Revision > + - checkout + - run: npm install + - save_cache: + key: source-v1-< .Revision > + paths: + - "node_modules" +``` + +在 GitLab CI / CD 中使用`cache`的同一管道的示例: + +``` +image: node:latest + +# Cache modules in between jobs +cache: + key: $CI_COMMIT_REF_SLUG + paths: + - .npm/ + +before_script: + - npm ci --cache .npm --prefer-offline + +test_async: + script: + - node ./specs/start.js ./specs/async.spec.js +``` + +## Contexts and variables[](#contexts-and-variables "Permalink") + +CircleCI 提供了[上下文,](https://s0circleci0com.icopy.site/docs/2.0/contexts/)以跨项目管道安全地传递环境变量. 在 GitLab 中,可以创建一个[组](../../user/group/index.html)来将相关项目组装在一起. 在组级别, [变量](../variables/README.html#group-level-environment-variables)可以存储在各个项目之外,并安全地传递到跨多个项目的管道中. + +## Orbs[](#orbs "Permalink") + +有两个 GitLab 问题需要解决 CircleCI Orb,以及 GitLab 如何实现类似功能. + +* [https://gitlab.com/gitlab-com/Product/-/issues/1151](https://gitlab.com/gitlab-com/Product/-/issues/1151) +* [https://gitlab.com/gitlab-org/gitlab/-/issues/195173](https://gitlab.com/gitlab-org/gitlab/-/issues/195173) + +## Build environments[](#build-environments "Permalink") + +CircleCI 为`executors`提供`executors`特定工作的基础技术. 在 GitLab 中,这是由[Runners](https://docs.gitlab.com/runner/)完成的. + +支持以下环境: + +自我管理的跑步者: + +* Linux +* Windows +* macOS + +GitLab.com 共享跑步者: + +* Linux +* Windows +* [Planned: macOS](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/5720) + +### Machine and specific build environments[](#machine-and-specific-build-environments "Permalink") + +通过告诉 GitLab 哪些 Runners 应该运行作业, [标签](../yaml/README.html#tags)可以用于在不同平台上运行作业. + +在特定环境中运行的作业的 CircleCI 示例: + +``` +jobs: + ubuntuJob: + machine: + image: ubuntu-1604:201903-01 + steps: + - checkout + - run: echo "Hello, $USER!" + osxJob: + macos: + xcode: 11.3.0 + steps: + - checkout + - run: echo "Hello, $USER!" +``` + +在 GitLab CI / CD 中使用`tags`进行同一作业的示例: + +``` +windows job: + stage: + - build + tags: + - windows + script: + - echo Hello, %USERNAME%! + +osx job: + stage: + - build + tags: + - osx + script: + - echo "Hello, $USER!" +``` \ No newline at end of file diff --git a/docs/206.md b/docs/206.md new file mode 100644 index 0000000000000000000000000000000000000000..0957eba2ed2600c12cfd52198be7e90ac31dd6a2 --- /dev/null +++ b/docs/206.md @@ -0,0 +1,266 @@ +# Migrating from Jenkins + +> 原文:[https://docs.gitlab.com/ee/ci/jenkins/](https://docs.gitlab.com/ee/ci/jenkins/) + +* [Managing the organizational transition](#managing-the-organizational-transition) +* [JenkinsFile Wrapper](#jenkinsfile-wrapper) +* [Important product differences](#important-product-differences) +* [Agents vs. Runners](#agents-vs-runners) +* [Groovy vs. YAML](#groovy-vs-yaml) +* [Artifact publishing](#artifact-publishing) +* [Integrated features](#integrated-features) + * [Templates](#templates) +* [Converting a declarative Jenkinsfile](#converting-a-declarative-jenkinsfile) + * [Sections](#sections) + * [`agent`](#agent) + * [`post`](#post) + * [`stages`](#stages) + * [`steps`](#steps) + * [Directives](#directives) + * [`environment`](#environment) + * [`options`](#options) + * [`parameters`](#parameters) + * [`triggers` / `cron`](#triggers--cron) + * [`tools`](#tools) + * [`input`](#input) + * [`when`](#when) + +# Migrating from Jenkins[](#migrating-from-jenkins "Permalink") + +许多 GitLab 用户已经从 Jenkins 成功迁移到 GitLab CI / CD. 为了使您入门时更容易,我们在这里收集了一些您可能会在使用之前可能会发现有用的资源.请将此页面视为" Jenkins 用户的 GitLab CI / CD"指南. + +建议的步骤的以下列表是在观察能够快速完成此迁移的组织之后创建的: + +1. 首先阅读《 GitLab CI / CD [快速入门指南》](../quick_start/README.html)和[重要的产品差异](#important-product-differences) . +2. 了解[管理组织过渡](#managing-the-organizational-transition)的重要性. +3. [将 Runners 添加](../runners/README.html)到您的 GitLab 实例. +4. 教育开发人员并使他们能够在他们的项目中独立执行以下步骤: + 1. 查看《 [快速入门指南](../quick_start/README.html)和[管道配置参考》](../yaml/README.html) . + 2. 使用[Jenkins 包装器](#jenkinsfile-wrapper)暂时维护脆弱的 Jenkins 作业. + 3. 迁移构建和 CI 作业并将其配置为直接在合并请求中显示结果. 他们可以使用[Auto DevOps](../../topics/autodevops/index.html)作为起点,并[根据](../../topics/autodevops/customize.html)需要[自定义](../../topics/autodevops/customize.html)或[分解](../../topics/autodevops/customize.html#using-components-of-auto-devops)配置. + 4. 添加[评论应用](../review_apps/index.html) . + 5. 使用[云部署模板](../cloud_deployment/index.html) ,添加[环境](../environments/index.html)和[部署板](../..//user/project/deploy_boards.html)来迁移部署作业. + 6. 使用 Jenkins 包装器解开仍在运行的所有作业的包装. +5. 盘点所有常见的 CI / CD 作业定义,然后为其创建和共享[模板](#templates) . + +有关如何将 Jenkins 管道转换为 GitLab CI / CD 管道的示例,或如何使用 Auto DevOps 自动测试代码的示例,请观看[从 Jenkins 迁移到 GitLab 的](https://www.youtube.com/watch?v=RlEVGOpYF5Y)视频. + +否则,请继续阅读以获取重要信息,这些信息将帮助您取得成功. 欢迎来到 GitLab! + +如果您有未在此处回答的问题, [GitLab 社区论坛](https://forum.gitlab.com/)将是一个很好的资源. + +## Managing the organizational transition[](#managing-the-organizational-transition "Permalink") + +从詹金斯过渡到 GitLab 的一个重要部分是随之而来的文化和组织变革,并成功地对其进行了管理. 我们发现了一些有助于解决问题的方法: + +* 为您的迁移目标设定并传达清晰的愿景有助于您的用户理解为什么值得付出努力. 当工作完成时,该值将很明显,但是在进行过程中,人们也需要意识到. +* 有关领导团队的赞助和配合有助于上述观点. +* 花时间对用户进行不同的教育,与他们共享此文档等等,将有助于确保您成功. +* 寻找顺序或延迟部分迁移的方法可能会很有帮助,但是您不想让事物长时间处于未迁移(或部分迁移)状态. 要获得 GitLab 的所有好处,仅将现有的 Jenkins 设置转移到原样上(包括任何当前问题)是不够的. 您需要利用 GitLab 提供的改进,这最终需要(最终)更新您的实现. + +## JenkinsFile Wrapper[](#jenkinsfile-wrapper "Permalink") + +我们正在构建一个[JenkinsFile 包装器](https://gitlab.com/gitlab-org/jfr-container-builder/) ,它将允许您在 GitLab 作业(包括插件)中运行完整的 Jenkins 实例. 通过让您将不太紧急的管道的迁移延迟一段时间,可以帮助简化过渡过程. + +如果您有兴趣帮助 GitLab 测试包装器,请加入我们的[公共测试问题](https://gitlab.com/gitlab-org/gitlab/-/issues/215675)以获取说明并提供您的反馈. + +## Important product differences[](#important-product-differences "Permalink") + +值得一提的产品之间存在一些高级差异: + +* 使用 GitLab,您不需要根`pipeline`关键字即可包装所有内容. +* 管道触发和[触发其他管道的](../yaml/README.html#trigger)方式与詹金斯不同. 可以触发 GitLab 管道: + + * 在推 + * on [schedule](../pipelines/schedules.html) + * 从[GitLab UI](../pipelines/index.html#run-a-pipeline-manually) + * by [API call](../triggers/README.html) + * by [webhook](../triggers/README.html#triggering-a-pipeline-from-a-webhook) + * by [ChatOps](../chatops/README.html) +* 您可以使用[`rules`语法](../yaml/README.html#rules)来控制在哪种情况下运行哪些作业,具体取决于触发方式. +* GitLab [管道调度概念](../pipelines/schedules.html)也与 Jenkins 不同. +* 您可以使用[`include`关键字](../yaml/README.html#include)和[模板](#templates)重复使用管道配置. 您的模板可以保存在中央存储库中(具有不同的权限),然后任何项目都可以使用它们. 这个中央项目也可以包含脚本或其他可重用的代码. +* You can also use the [`extends` keyword](../yaml/README.html#extends) to reuse configuration within a single pipeline configuration. +* 单个阶段中的所有作业始终并行运行,并且所有阶段均按顺序运行. 我们计划通过我们的有[向无环图](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47063)功能允许某些作业根据需要中断此排序. +* [`parallel`](../yaml/README.html#parallel)关键字可以自动并行化任务,例如支持并行化的测试. +* 通常,单个阶段中的所有作业并行运行,并且所有阶段按顺序运行. 有不同的[管道体系结构](../pipelines/pipeline_architectures.html)允许您更改此行为. +* 建议使用新[`rules`语法](../yaml/README.html#rules)控制何时运行不同作业. 它比`only/except`语法更强大. +* 一个重要的区别是,作业彼此独立运行,并且每个作业都具有全新的环境. 使用[`artifacts`](../yaml/README.html#artifacts)和[`dependencies`](../yaml/README.html#dependencies)关键字控制作业之间传递工件. 完成后,计划的[工作区](https://gitlab.com/gitlab-org/gitlab/-/issues/29265)功能将使您能够更轻松地在串行作业之间持久保留公共工作区. +* `.gitlab-ci.yml`文件已签入到存储库的根目录,非常类似于 Jenkinsfile,但采用 YAML 格式(请参阅[完整参考](../yaml/README.html) )而不是 Groovy DSL. 它与声明性 Jenkinsfile 格式最相似. +* 手动批准或登机口可以设置为以下[`when:manual`作业](../yaml/README.html#whenmanual) . 这些还可以利用[`protected environments`](../yaml/README.html#protecting-manual-jobs-premium)来控制谁可以批准它们. +* GitLab 带有[容器注册表](../../user/packages/container_registry/index.html) ,我们建议使用容器映像来设置您的构建环境. 例如,设置一个管道来构建您自己的构建环境,并将其发布到容器注册表. 然后,让您的管道使用此方法,而不是每个管道都使用它们自己的环境,这将变得更慢,并且一致性可能会降低. 我们有大量有关[如何使用 Container Registry 的](../../user/packages/container_registry/index.html)文档. +* 中央实用程序存储库是放置各种计划作业或其他功能类似于实用程序的手动作业的好地方. 詹金斯的装置中往往有一些. + +## Agents vs. Runners[](#agents-vs-runners "Permalink") + +Jenkins 代理和 GitLab Runners 都是运行作业的主机. 要转换 Jenkins 代理,只需将其卸载,然后[安装并注册 Runner](../runners/README.html) . 运行程序不需要太多的开销,因此您可以像使用的 Jenkins 代理一样调整它们的大小. + +与代理相比,Runners 的工作方式存在一些重要差异: + +* 跑步者可以设置为[在实例之间共享,也可以在组级别添加,也可以在项目级别设置](../runners/README.html#types-of-runners) . 他们将从您自动定义的范围中自动选择作业. +* 您还可以[使用标签](../runners/README.html#use-tags-to-limit-the-number-of-jobs-using-the-runner)进行更精细的控制,并将跑步者与特定工作相关联. 例如,您可以将标签用于需要专用,功能更强大或特定硬件的作业. +* GitLab 具有[针对](https://docs.gitlab.com/runner/configuration/autoscale.html) Runner 的[自动缩放功能](https://docs.gitlab.com/runner/configuration/autoscale.html) ,可让您将其配置为根据需要进行设置,并在不进行缩放时进行缩放. 这类似于詹金斯中的临时代理. + +如果您使用的是`gitlab.com` ,则可以利用我们[共享的 Runner](../../user/gitlab_com/index.html#shared-runners) `gitlab.com`来运行作业,而无需置备自己的 Runners. 我们正在研究使它们也[可用于自我管理实例](https://gitlab.com/groups/gitlab-org/-/epics/835) . + +## Groovy vs. YAML[](#groovy-vs-yaml "Permalink") + +Jenkins 管道基于[Groovy](https://s0groovy-lang0org.icopy.site/) ,因此管道规范以代码形式编写. GitLab 的工作方式略有不同,我们使用结构更高级的[YAML](https://yaml.org/)格式,该格式将脚本元素放置在`script:`内部`script:`块与管道规范本身分开. + +这是 GitLab 的优势,因为它有助于使学习曲线更简单地启动和运行,并且避免了一些不受限制的复杂性问题,这些问题会使您的 Jenkinsfile 难以理解和管理. + +就是说,我们当然仍然重视 DRY(不要重复自己)的原则,并希望确保您的工作行为可以被一次编码并根据需要进行应用. 您可以使用`extends:`语法[在您的作业中重用配置](../yaml/README.html#extends) , `include:`可用于在不同项目的管道中[重用管道配置](../yaml/README.html#include) : + +``` +.in-docker: + tags: + - docker + image: alpine + +rspec: + extends: + - .in-docker + script: + - rake rspec +``` + +## Artifact publishing[](#artifact-publishing "Permalink") + +工件的工作方式可能与您与詹金斯一起使用时有所不同. 在 GitLab 中,任何作业都可以使用`artifacts:`关键字定义一组要保存的`artifacts:` . 可以将其配置为指向一个文件或一组文件,然后可以在每个作业之间将其持久化. 阅读更多关于我们详细的[工件文档的信息](../pipelines/job_artifacts.html) : + +``` +pdf: + script: xelatex mycv.tex + artifacts: + paths: + - ./mycv.pdf + - ./output/ + expire_in: 1 week +``` + +此外,我们还具有包管理功能,例如可以利用的内置容器,NPM 和 Maven 注册表. 您可以在[我们的文档](../../README.html#package)的[包装部分中](../../README.html#package)查看打包功能的完整列表(包括指向文档的链接). + +## Integrated features[](#integrated-features "Permalink") + +在 Jenkins 中,您可能曾经使用插件来获得代码质量,单元测试,安全扫描等功能,但 GitLab 充分利用了我们连接的生态系统,将这些结果自动提取到您的合并请求,管道详细信息页面和其他位置. 您可能会发现实际上不需要配置任何内容即可显示这些内容. + +如果它们无法正常工作,或者您想查看可用的[功能](../README.html#feature-set) ,则我们的[CI 功能索引](../README.html#feature-set)将提供捆绑功能的完整列表,并提供每个功能的文档链接. + +### Templates[](#templates "Permalink") + +对于高级 CI / CD 团队,项目模板可以启用管道配置的重用,并鼓励内部采购. + +In self-managed GitLab instances, you can build an [Instance Template Repository](../../user/admin_area/settings/instance_template_repository.html). Development teams across the whole organization can select templates from a dropdown menu. A group administrator is able to set a group to use as the source for the [custom project templates](../../user/admin_area/custom_project_templates.html), which can be used by all projects in the group. An instance administrator can set a group as the source for [instance project templates](../../user/group/custom_project_templates.html), which can be used by projects in that instance. + +## Converting a declarative Jenkinsfile[](#converting-a-declarative-jenkinsfile "Permalink") + +声明性 Jenkinsfile 包含用于控制管道行为的" Sections"和" Directives". GitLab 中有所有这些的等效项,我们在下面对此进行了介绍. + +本节基于[Jenkinsfile 语法文档](https://www.jenkins.io/doc/book/pipeline/syntax/) ,旨在将其中的概念映射到 GitLab 中的概念. + +### Sections[](#sections "Permalink") + +#### `agent`[](#agent "Permalink") + +代理部分用于定义如何执行管道. 对于 GitLab,我们使用[GitLab Runner](../runners/README.html)来提供此功能. 您可以在 Kubernetes 或任何主机上配置自己的运行程序,也可以利用我们的共享运行程序队列(请注意,共享运行程序队列仅适用于 GitLab.com 用户.)以上链接将带您进入说明文档的文档如何快速起步和运行. 我们还支持使用[标签](../runners/README.html#use-tags-to-limit-the-number-of-jobs-using-the-runner)将不同的作业定向到不同的 Runner(执行代理). + +`agent`部分还允许您定义应使用哪些 Docker 映像执行,而我们使用[`image`](../yaml/README.html#image)关键字. 该`image`可以设置在单个作业或顶层,在这种情况下,它将应用于管道中的所有作业: + +``` +my_job: + image: alpine + ... +``` + +#### `post`[](#post "Permalink") + +`post`部分定义了应在管道末尾执行的操作. GitLab 也通过阶段的使用来支持这一点. 您可以按以下方式定义阶段,分配给`before_pipeline`或`after_pipeline`阶段的所有作业都将按预期运行. 您可以根据需要将这些阶段称为: + +``` +stages: + - before_pipeline + - build + - test + - deploy + - after_pipeline +``` + +可以通过[`before_script`和`after_script`关键字](../yaml/README.html#before_script-and-after_script)设置要在任何作业之前和之后执行的步骤: + +``` +default: + before_script: + - echo "I run before any jobs starts in the entire pipeline, and can be responsible for setting up the environment." +``` + +#### `stages`[](#stages "Permalink") + +GitLab CI / CD 也可以让您定义阶段,但是可以自由配置一些. GitLab [`stages`关键字](../yaml/README.html#stages)是一个顶级设置,它枚举了阶段列表,但是您不需要在" `stages`部分下嵌套单个作业. 通过使用[`stage:`关键字,](../yaml/README.html#stage)可以使`.gitlab-ci.yml`定义的任何作业成为任何阶段的一部分. + +请注意,除非另有说明,否则每个管道都以`build` , `test`和`deploy`阶段实例化,并按该顺序运行. 未定义`stage`作业默认情况下放置在`test`阶段. 当然,引用阶段的每个作业都必须引用管道配置中存在的阶段. + +``` +stages: + - build + - test + - deploy + +my_job: + stage: build + ... +``` + +#### `steps`[](#steps "Permalink") + +The `steps` section is equivalent to the [`script` section](../yaml/README.html#script) of an individual job. This is a simple YAML array with each line representing an individual command to be run: + +``` +my_job: + script: + - echo "hello! the current time is:" + - time + ... +``` + +### Directives[](#directives "Permalink") + +#### `environment`[](#environment "Permalink") + +在 GitLab 中,我们使用[`variables`关键字](../yaml/README.html#variables)在运行时定义不同的变量. 这些也可以通过 CI / CD 设置下的 GitLab UI 进行设置. 另请参阅我们[有关变量](../variables/README.html)的[一般文档](../variables/README.html) ,包括有关[受保护变量](../variables/README.html#protect-a-custom-variable)的部分,该部分可用于将对某些变量的访问限制为某些环境或运行程序: + +``` +variables: + POSTGRES_USER: user + POSTGRES_PASSWORD: testing_password +``` + +#### `options`[](#options "Permalink") + +这里,存在与所讨论的对象本身相关联的用于不同事物的选项. 例如,与作业相关的选项是相对于作业本身定义的. 如果您正在寻找某个选项,则应该可以通过搜索[完整的配置参考](../yaml/README.html)页面来找到它的位置. + +#### `parameters`[](#parameters "Permalink") + +GitLab 不需要您定义在开始手动作业时希望可用的变量. 用户可以提供他们喜欢的任何变量. + +#### `triggers` / `cron`[](#triggers--cron "Permalink") + +Because GitLab is integrated tightly with Git, SCM polling options for triggers are not needed. We support an easy to use [syntax for scheduling pipelines](../pipelines/schedules.html). + +#### `tools`[](#tools "Permalink") + +GitLab 不支持单独的`tools`指令. 我们的最佳实践建议是使用预构建的容器映像,该映像可以缓存,并且可以构建为包含管道所需的工具. 可以设置管道以根据需要自动构建这些映像,并将它们部署到[容器注册表中](../../user/packages/container_registry/index.html) . + +如果您没有在 Docker / Kubernetes 上使用容器映像,例如在 Mac 或 FreeBSD 上,则`shell`执行程序确实需要您预先设置环境或作为作业的一部分. 您可以创建一个`before_script`动作来为您处理. + +#### `input`[](#input "Permalink") + +与`parameters`关键字类似,这是不需要的,因为始终可以为运行时变量条目提供手动作业. + +#### `when`[](#when "Permalink") + +GitLab 确实支持[`when`关键字](../yaml/README.html#when) ,用于指示在(或尽管发生)故障的情况下应在何时运行作业,但是大多数用于控制管道的逻辑都可以在我们功能非常强大的[`only/except`规则系统中找到](../yaml/README.html#onlyexcept-basic) (另请参见[高级语法](../yaml/README.html#onlyexcept-basic) ): + +``` +my_job: + only: [branches] +``` \ No newline at end of file diff --git a/docs/207.md b/docs/207.md new file mode 100644 index 0000000000000000000000000000000000000000..c5403aeb4b4c621ef2265ead1b3d413db4471a6c --- /dev/null +++ b/docs/207.md @@ -0,0 +1,302 @@ +# Auto DevOps + +> 原文:[https://docs.gitlab.com/ee/topics/autodevops/](https://docs.gitlab.com/ee/topics/autodevops/) + +* [Overview](#overview) +* [Enabled by default](#enabled-by-default) +* [Quick start](#quick-start) +* [Comparison to application platforms and PaaS](#comparison-to-application-platforms-and-paas) +* [Features](#features) +* [Auto DevOps base domain](#auto-devops-base-domain) +* [Enabling/Disabling Auto DevOps](#enablingdisabling-auto-devops) + * [At the project level](#at-the-project-level) + * [At the group level](#at-the-group-level) + * [At the instance level (Administrators only)](#at-the-instance-level-administrators-only) + * [Deployment strategy](#deployment-strategy) +* [Using multiple Kubernetes clusters](#using-multiple-kubernetes-clusters-premium) +* [Limitations](#limitations) + * [Private registry support](#private-registry-support) + * [Installing Helm behind a proxy](#installing-helm-behind-a-proxy) +* [Troubleshooting](#troubleshooting) + * [Unable to select a buildpack](#unable-to-select-a-buildpack) + * [Pipeline that extends Auto DevOps with only / except fails](#pipeline-that-extends-auto-devops-with-only--except-fails) + * [Failure to create a Kubernetes namespace](#failure-to-create-a-kubernetes-namespace) + * [Detected an existing PostgreSQL database](#detected-an-existing-postgresql-database) +* [Development guides](#development-guides) + +# Auto DevOps[](#auto-devops "Permalink") + +版本历史 + +* 在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/37115) . +* 通常在 GitLab 11.0 上可用. + +Auto DevOps provides pre-defined CI/CD configuration allowing you to automatically detect, build, test, deploy, and monitor your applications. Leveraging CI/CD best practices and tools, Auto DevOps aims to simplify the setup and execution of a mature and modern software development lifecycle. + +## Overview[](#overview "Permalink") + +您可以花费大量精力来设置构建,部署和监视项目所需的工作流和流程. 当您的公司要维护数百个(甚至数千个)项目时,情况会变得更糟. 随着新项目的不断启动,整个软件开发过程变得难以管理. + +Auto DevOps 通过自动检测以最小的配置测试,构建,打包,部署和监视每个项目所需的所有依赖关系和语言技术,为您提供了无缝的软件开发过程. 自动化可确保项目之间的一致性,流程的无缝管理以及更快地创建新项目:推送代码,而 GitLab 则完成其余工作,从而提高了生产率和效率. + +有关 Auto DevOps 的介绍, [请在 GitLab 11.0 中](https://youtu.be/0Tc0YYBxqi4)观看[AutoDevOps](https://youtu.be/0Tc0YYBxqi4) . + +有关要求,请参阅[Auto DevOps 要求以](requirements.html)获取更多信息. + +## Enabled by default[](#enabled-by-default "Permalink") + +在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41729) . + +默认情况下,所有项目都会启用 Auto DevOps,并尝试在每个项目的所有管道中运行. 实例管理员可以在[Auto DevOps 设置中](../../user/admin_area/settings/continuous_integration.html#auto-devops-core-only)启用或禁用此默认[设置](../../user/admin_area/settings/continuous_integration.html#auto-devops-core-only) . 如果尚未为项目显式启用,Auto DevOps 会在各个项目的第一个管道故障时自动将其禁用. + +从[GitLab 12.7 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/26655) ,仅当存在[`Dockerfile`或匹配的 buildpack](stages.html#auto-build)时,Auto DevOps 才会在管道上自动运行. + +如果项目中存在[CI / CD 配置文件](../../ci/yaml/README.html) ,则无论是否启用了 Auto DevOps,它都将继续使用. + +## Quick start[](#quick-start "Permalink") + +如果您使用的是 GitLab.com,请参阅[快速入门指南](quick_start_guide.html) ,以使用 GitLab.com 和 Google Kubernetes Engine(GKE)上的 Kubernetes 集群设置 Auto DevOps. + +如果使用 GitLab 的自我管理实例,则必须先配置[Google OAuth2 OmniAuth Provider,](../../integration/google.html)然后才能在 GKE 上配置集群. 配置提供程序后,您可以按照[快速入门指南中](quick_start_guide.html)的步骤进行入门. + +In [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/208132) and later, it is possible to leverage Auto DevOps to deploy to [AWS ECS](requirements.html#auto-devops-requirements-for-amazon-ecs). + +## Comparison to application platforms and PaaS[](#comparison-to-application-platforms-and-paas "Permalink") + +Auto DevOps provides features often included in an application platform or a Platform as a Service (PaaS). It takes inspiration from the innovative work done by [Heroku](https://www.heroku.com/) and goes beyond it in multiple ways: + +* Auto DevOps 可与任何 Kubernetes 集群一起使用; 您不仅限于在 GitLab 的基础架构上运行. (请注意,许多功能在没有 Kubernetes 的情况下也可以使用). +* 没有额外的费用(基础设施费用没有加价),您可以在任何公共云(例如[Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/) )上使用托管的 Kubernetes 群集或容器即服务. +* Auto DevOps 具有更多功能,包括安全测试,性能测试和代码质量测试. +* Auto DevOps 提供增量的毕业路径. 如果需要高级自定义,则可以开始修改模板,而无需在完全不同的平台上重新开始. 查看[定制](customize.html)文档以获取更多信息. + +## Features[](#features "Permalink") + +Auto DevOps 由一组[阶段组成](stages.html) ,以简单,自动的方式为您的项目带来了这些最佳实践: + +1. [Auto Build](stages.html#auto-build) +2. [Auto Test](stages.html#auto-test) +3. [Auto Code Quality](stages.html#auto-code-quality-starter) +4. [Auto SAST (Static Application Security Testing)](stages.html#auto-sast-ultimate) +5. [Auto Secret Detection](stages.html#auto-secret-detection-ultimate) +6. [Auto Dependency Scanning](stages.html#auto-dependency-scanning-ultimate) +7. [Auto License Compliance](stages.html#auto-license-compliance-ultimate) +8. [Auto Container Scanning](stages.html#auto-container-scanning-ultimate) +9. [Auto Review Apps](stages.html#auto-review-apps) +10. [Auto DAST (Dynamic Application Security Testing)](stages.html#auto-dast-ultimate) +11. [Auto Deploy](stages.html#auto-deploy) +12. [Auto Browser Performance Testing](stages.html#auto-browser-performance-testing-premium) +13. [Auto Monitoring](stages.html#auto-monitoring) + +由于 Auto DevOps 依赖于许多不同的组件,因此您应该具有以下基本知识: + +* [Kubernetes](https://kubernetes.io/docs/home/) +* [Helm](https://helm.sh/docs/) +* [Docker](https://s0docs0docker0com.icopy.site) +* [GitLab Runner](https://docs.gitlab.com/runner/) +* [Prometheus](https://s0prometheus0io.icopy.site/docs/introduction/overview/) + +Auto DevOps 为所有阶段提供了出色的默认设置. 但是,您可以[根据](customize.html)需要[自定义](customize.html)几乎所有内容. + +有关创建 Auto DevOps 的概述,请阅读[本博客文章中的](https://about.gitlab.com/blog/2017/06/29/whats-next-for-gitlab-ci/)更多[信息](https://about.gitlab.com/blog/2017/06/29/whats-next-for-gitlab-ci/) . + +**注意** Kubernetes 集群可以[在没有](../../user/project/clusters/index.html) Auto DevOps 的[情况下使用](../../user/project/clusters/index.html) . + +## Auto DevOps base domain[](#auto-devops-base-domain "Permalink") + +必须使用 Auto DevOps 基本域才能使用[Auto Review Apps](stages.html#auto-review-apps) , [Auto Deploy](stages.html#auto-deploy)和[Auto Monitoring](stages.html#auto-monitoring) . 您可以在以下任意位置定义基本域: + +* 在集群的设置下(对于实例, [项目](../../user/project/clusters/index.html#base-domain)还是[组)](../../user/group/clusters/index.html#base-domain) +* 或在项目级别作为变量: `KUBE_INGRESS_BASE_DOMAIN` +* 或在组级别作为变量: `KUBE_INGRESS_BASE_DOMAIN` +* 或作为实例范围的后备 **持续集成和交付**部分下的**管理区域>设置** + +基本域变量`KUBE_INGRESS_BASE_DOMAIN`与其他环境[变量](../../ci/variables/README.html#priority-of-environment-variables)遵循相同的优先级顺序. 如果未设置 CI / CD 变量,并且群集设置为空,则在设置实例范围的**Auto DevOps 域**设置时将使用该设置. + +**提示:**如果您将[GitLab 托管应用程序用于 Ingress](../../user/clusters/applications.html#ingress) ,则应自动为您配置 URL 端点. 您所要做的就是将其值用于`KUBE_INGRESS_BASE_DOMAIN`变量.**注:** `AUTO_DEVOPS_DOMAIN`被[弃用 GitLab 11.8](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52363) ,取而代之的`KUBE_INGRESS_BASE_DOMAIN` ,并在除去[GitLab 12.0](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/56959) . + +Auto DevOps 需要与基础域匹配的通配符 DNS A 记录. 对于`example.com`的基本域,您需要一个 DNS 条目,例如: + +``` +*.example.com 3600 A 1.2.3.4 +``` + +在这种情况下,已部署的应用程序是从`example.com` ,而`1.2.3.4`是负载均衡器的 IP 地址. 通常为 NGINX( [请参阅要求](#requirements) ). 设置 DNS 记录不在本文档的讨论范围内. 请与您的 DNS 提供商联系以获取信息. + +另外,您可以使用免费的公共服务,例如[nip.io](https://nip.io) ,无需任何配置即可提供自动通配符 DNS. 对于[nip.io](https://nip.io) ,将 Auto DevOps 基本域设置为`1.2.3.4.nip.io` + +完成设置后,所有请求都将到达负载均衡器,该负载均衡器会将请求路由到运行您的应用程序的 Kubernetes Pod. + +## Enabling/Disabling Auto DevOps[](#enablingdisabling-auto-devops "Permalink") + +首次使用 Auto DevOps 时,请查看[要求,](#requirements)以确保可以充分利用 Auto DevOps 的所有必需组件. 初学者应遵循[快速入门指南](quick_start_guide.html) . + +GitLab.com 用户只能在项目级别启用或禁用 Auto DevOps. 自我管理的用户可以在项目,组或实例级别启用或禁用 Auto DevOps. + +### At the project level[](#at-the-project-level "Permalink") + +如果启用,请检查您的项目是否没有`.gitlab-ci.yml` ,或者如果存在,请将其删除. + +1. 转到项目的 **设置> CI / CD>自动 DevOps** . +2. 选中**默认为 Auto DevOps 管道**复选框以启用它. +3. (可选,但建议使用)启用后,您可以在 Auto DevOps 用于[部署应用程序](stages.html#auto-deploy)的[基本域中](#auto-devops-base-domain)添加,并选择[部署策略](#deployment-strategy) . +4. 单击**保存更改**以使更改生效. + +启用该功能后,将在默认分支上触发 Auto DevOps 管道. + +### At the group level[](#at-the-group-level "Permalink") + +在 GitLab 11.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52447) . + +仅管理员和组所有者可以在组级别启用或禁用自动 DevOps. + +在组级别启用或禁用 Auto DevOps 时,除非在子组或项目上专门启用或禁用了 Auto DevOps,否则组配置将隐式用于该组内的子组和项目. + +要在组级别启用或禁用自动 DevOps: + +1. 前往您小组的 **设置> CI / CD>自动 DevOps**页面. +2. 选中**默认为 Auto DevOps 管道**复选框以启用它. +3. 单击**保存更改**以使更改生效. + +### At the instance level (Administrators only)[](#at-the-instance-level-administrators-only "Permalink") + +即使在实例级别被禁用,组所有者和项目维护者仍可以分别在组和项目级别启用 Auto DevOps. + +1. 去 **管理区域>设置>持续集成和部署** . +2. **为所有项目**选择" **默认为自动 DevOps 管道"**以启用它. +3. (可选)您可以设置 Auto DevOps [基本域](#auto-devops-base-domain) ,以供 Auto Deploy 和 Auto Review Apps 使用. +4. 单击**保存更改**以使更改生效. + +### Deployment strategy[](#deployment-strategy "Permalink") + +在 GitLab 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/38542) . + +您可以转到项目的目录,更改 Auto DevOps 使用的部署策略. **设置> CI / CD>自动 DevOps** . 提供以下选项: + +* **持续部署到生产中** :启用将`master`分支直接部署到生产中的[自动部署](stages.html#auto-deploy) . +* **使用定时增量部署连续部署到生产中** :将[`INCREMENTAL_ROLLOUT_MODE`](customize.html#timed-incremental-rollout-to-production-premium)变量设置为`timed` . 生产部署在每次部署增量之间有 5 分钟的延迟执行. +* **自动部署到登台,手动部署到生产** :将[`STAGING_ENABLED`](customize.html#deploy-policy-for-staging-and-production-environments)和[`INCREMENTAL_ROLLOUT_MODE`](customize.html#incremental-rollout-to-production-premium)变量设置为`1`并`manual` . 这表示: + + * `master`分支直接部署到登台. + * 提供了手动操作以逐步推广到生产中. + +**提示:**使用[蓝绿色部署](../../ci/environments/incremental_rollouts.html#blue-green-deployment)技术可最大程度地减少停机时间和风险. + +## Using multiple Kubernetes clusters[](#using-multiple-kubernetes-clusters-premium "Permalink") + +使用 Auto DevOps 时,由于[它们之间存在](../../user/project/clusters/index.html#multiple-kubernetes-clusters-premium) 1:1 连接,因此可以将不同的环境部署到不同的 Kubernetes 集群. + +Auto DevOps 使用的" [部署作业"模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml)当前定义了 3 个环境名称: + +* `review/` (从`review/`开始的所有环境`review/` ) +* `staging` +* `production` + +这些环境使用[Auto Deploy](stages.html#auto-deploy)与作业绑定,因此,除了环境范围外,它们必须具有不同的部署域. 您必须[根据环境](../../ci/variables/README.html#limit-the-environment-scopes-of-environment-variables)为上述每个项定义一个单独的`KUBE_INGRESS_BASE_DOMAIN`变量. + +下表是如何配置三个不同群集的示例: + +| 集群名称 | 集群环境范围 | `KUBE_INGRESS_BASE_DOMAIN`变量值 | 可变环境范围 | Notes | +| --- | --- | --- | --- | --- | +| review | `review/*` | `review.example.com` | `review/*` | 运行所有[Review Apps](../../ci/review_apps/index.html)的评论集群. `*`是一个通配符,每个环境名称都以`review/`开头使用. | +| staging | `staging` | `staging.example.com` | `staging` | (可选)运行临时环境的部署的临时集群. 您必须先[启用它](customize.html#deploy-policy-for-staging-and-production-environments) . | +| production | `production` | `example.com` | `production` | 运行生产环境部署的生产集群. 您可以使用[增量卷展栏](customize.html#incremental-rollout-to-production-premium) . | + +为每个环境添加不同的集群: + +1. 导航到您项目的 **运营> Kubernetes** . +2. 如上表所述,使用各自的环境范围创建 Kubernetes 集群. +3. 创建集群后,导航至每个集群并安装 Helm Tiller 和 Ingress. 等待分配入口 IP 地址. +4. 确保已使用指定的 Auto DevOps 域[配置 DNS](#auto-devops-base-domain) . +5. 导航到每个集群的页面,方法是 **操作> Kubernetes** ,然后根据其入口 IP 地址添加域. + +完成配置后,您可以通过创建合并请求并验证您的应用程序是否已作为具有 Review `review/*`环境范围的 Kubernetes 集群中的 Review App 部署来测试设置. 同样,您可以检查其他环境. + +## Limitations[](#limitations "Permalink") + +以下限制适用. + +### Private registry support[](#private-registry-support "Permalink") + +没有记录的将私有容器注册表与 Auto DevOps 结合使用的方式. 我们强烈建议将 GitLab 容器注册表与 Auto DevOps 结合使用,以简化配置并防止任何不可预见的问题. + +### Installing Helm behind a proxy[](#installing-helm-behind-a-proxy "Permalink") + +当在代理后面时,GitLab 不支持将[Helm 作为 GitLab 管理的应用程序](../../user/clusters/applications.html#helm)安装. 想要这样做的用户必须在运行时将其代理设置注入到安装 Pod 中,例如使用[`PodPreset`](https://kubernetes.io/docs/concepts/workloads/pods/podpreset/) : + +``` +apiVersion: settings.k8s.io/v1alpha1 +kind: PodPreset +metadata: + name: gitlab-managed-apps-default-proxy + namespace: gitlab-managed-apps +spec: + env: + - name: http_proxy + value: "PUT_YOUR_HTTP_PROXY_HERE" + - name: https_proxy + value: "PUT_YOUR_HTTPS_PROXY_HERE" +``` + +## Troubleshooting[](#troubleshooting "Permalink") + +### Unable to select a buildpack[](#unable-to-select-a-buildpack "Permalink") + +自动构建和自动测试可能无法检测到您的语言或框架,并出现以下错误: + +``` +Step 5/11 : RUN /bin/herokuish buildpack build + ---> Running in eb468cd46085 + -----> Unable to select a buildpack +The command '/bin/sh -c /bin/herokuish buildpack build' returned a non-zero code: 1 +``` + +以下是可能的原因: + +* 您的应用程序可能缺少 buildpack 寻找的关键文件. Ruby 应用程序需要正确检测`Gemfile` ,即使编写不带`Gemfile`的 Ruby 应用程序也是`Gemfile` . +* 您的应用程序可能不存在 buildpack. 尝试指定[自定义 buildpack](customize.html#custom-buildpacks) . + +### Pipeline that extends Auto DevOps with only / except fails[](#pipeline-that-extends-auto-devops-with-only--except-fails "Permalink") + +如果您的管道失败并显示以下消息: + +``` +Found errors in your .gitlab-ci.yml: + + jobs:test config key may not be used with `rules`: only +``` + +当包含作业的规则配置已被`only`或`except`语法覆盖时,将出现此错误. 要解决此问题,您必须: + +* 将您的`only/except`语法转换为规则. +* (临时)将模板固定到[基于 GitLab 12.10 的模板](https://gitlab.com/gitlab-org/auto-devops-v12-10) . + +### Failure to create a Kubernetes namespace[](#failure-to-create-a-kubernetes-namespace "Permalink") + +如果 GitLab 无法为您的项目创建 Kubernetes 命名空间和服务帐户,则 Auto Deploy 将失败. 有关调试此问题的帮助,请参阅[对失败的部署作业进行故障排除](../../user/project/clusters/index.html#troubleshooting) . + +### Detected an existing PostgreSQL database[](#detected-an-existing-postgresql-database "Permalink") + +升级到 GitLab 13.0 后,使用 Auto DevOps 部署时可能会遇到以下消息: + +> 检测到已安装在不赞成使用的通道 1 上的现有 PostgreSQL 数据库,但当前通道设置为 2.在 GitLab 13.0 中,默认通道更改为 2\. […] + +默认情况下,Auto DevOps 会在应用程序旁边安装集群内 PostgreSQL 数据库. 在 GitLab 13.0 中更改了默认安装方法,并且升级现有数据库需要用户参与. 两种安装方法是: + +* **通道 1(不建议使用):**作为关联的 Helm 图表的依赖项拉入数据库. 只支持 Kubernetes 版本 1.15 之前的版本. +* **通道 2(当前):**将数据库安装为独立的 Helm 图表. 将集群内数据库功能与 Kubernetes 1.16 及更高版本一起使用时是必需的. + +如果收到此错误,则可以执行以下操作之一: + +* 通过将`AUTO_DEVOPS_POSTGRES_CHANNEL`设置为`1`并重新部署,可以*放心地*忽略该警告并继续使用通道 1 PostgreSQL 数据库. + +* 通过将`AUTO_DEVOPS_POSTGRES_DELETE_V1`设置为非空值并重新部署,可以删除通道 1 PostgreSQL 数据库并安装新的通道 2 数据库. + + **危险:**删除通道 1 PostgreSQL 数据库将永久删除现有的通道 1 数据库及其所有数据. 有关备份和升级数据库的更多信息,请参见[升级 PostgreSQL](upgrading_postgresql.html) . +* 如果不使用集群内数据库,则可以将`POSTGRES_ENABLED`设置为`false`并重新部署. 此选项与*没有图表内 PostgreSQL 依赖项*的*自定义图表的*用户特别相关. 数据库自动检测基于您的发行版的`postgresql.enabled` Helm 值. 该值是基于`POSTGRES_ENABLED` CI 变量设置的,并且由 Helm 保留,无论您的图表是否使用该变量. + +**危险:**将`POSTGRES_ENABLED`设置为`false`永久删除您环境中的任何现有通道 1 数据库. + +## Development guides[](#development-guides "Permalink") + +[Development guide for Auto DevOps](../../development/auto_devops.html) \ No newline at end of file diff --git a/docs/208.md b/docs/208.md new file mode 100644 index 0000000000000000000000000000000000000000..a9e705c9a0a9d42d71b0ebc103400754053832ae --- /dev/null +++ b/docs/208.md @@ -0,0 +1,214 @@ +# Getting started with Auto DevOps + +> 原文:[https://docs.gitlab.com/ee/topics/autodevops/quick_start_guide.html](https://docs.gitlab.com/ee/topics/autodevops/quick_start_guide.html) + +* [Configure your Google account](#configure-your-google-account) +* [Create a new project from a template](#create-a-new-project-from-a-template) +* [Create a Kubernetes cluster from within GitLab](#create-a-kubernetes-cluster-from-within-gitlab) +* [Install Ingress and Prometheus](#install-ingress-and-prometheus) +* [Enable Auto DevOps (optional)](#enable-auto-devops-optional) +* [Deploy the application](#deploy-the-application) + * [Monitor your project](#monitor-your-project) + * [Work with branches](#work-with-branches) +* [Conclusion](#conclusion) + +# Getting started with Auto DevOps[](#getting-started-with-auto-devops "Permalink") + +本分步指南将帮助您使用[Auto DevOps](index.html)将 GitLab.com 上托管的项目部署到 Google Kubernetes Engine. + +您将使用 GitLab 的本地 Kubernetes 集成,因此您无需使用 Google Cloud Platform 控制台手动创建 Kubernetes 集群. 您将创建并部署一个从 GitLab 模板创建的简单应用程序. + +这些说明也适用于自我管理的 GitLab 实例; 您只需要确保[配置了](../../ci/runners/README.html)自己的[Runners](../../ci/runners/README.html)并[启用了 Google OAuth](../../integration/google.html) . + +## Configure your Google account[](#configure-your-google-account "Permalink") + +在创建 Kubernetes 集群并将其连接到 GitLab 项目之前,您需要一个[Google Cloud Platform 帐户](https://console.cloud.google.com) . 使用现有的 Google 帐户登录,例如用于访问 Gmail 或 Google 云端硬盘的帐户,或创建一个新帐户. + +1. 请按照 Kubernetes Engine 文档的["开始之前"一节](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin)中描述的步骤来启用所需的 API 和相关服务. +2. 确保您已使用 Google Cloud Platform 创建了一个[结算帐户](https://cloud.google.com/billing/docs/how-to/manage-billing-account) . + +**提示:**每个新的 Google Cloud Platform(GCP)帐户都会获得[$ 300 的信用额](https://console.cloud.google.com/freetrial) ,并且与 Google 合作,GitLab 能够为新的 GCP 帐户提供额外的$ 200,以开始使用 GitLab 的 Google Kubernetes Engine Integration. [点击此链接](https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form)并申请信用. + +## Create a new project from a template[](#create-a-new-project-from-a-template "Permalink") + +我们将使用 GitLab 的项目模板之一来开始. 顾名思义,这些项目提供了基于某些知名框架的准系统应用程序. + +1. 在 GitLab 中,单击加号( ),然后选择**新建项目** . +2. 转到**从模板创建**选项卡,您可以在其中选择 Ruby on Rails,Spring 或 NodeJS Express 项目. 对于本教程,请使用 Ruby on Rails 模板. + + [![Select project template](img/db0b9c2164464a7b2e1772c54232681a.png)](img/guide_project_template_v12_3.png) + +3. 给您的项目起一个名字,或者选择一个描述,并将其公开,以便您可以利用[GitLab Gold 计划](https://about.gitlab.com/pricing/#gitlab-com)中的可用功能. + + [![Create project](img/0991c603daeaefcd2df14e098fa66ea4.png)](img/guide_create_project_v12_3.png) + +4. Click **建立专案**. + +现在,您已经创建了一个项目,接下来将创建 Kubernetes 集群以将该项目部署到该集群. + +## Create a Kubernetes cluster from within GitLab[](#create-a-kubernetes-cluster-from-within-gitlab "Permalink") + +1. 在项目的登录页面上,单击**添加 Kubernetes 集群** (请注意,当您导航到 **操作> Kubernetes** ). + + [![Project landing page](img/0bef311ef1713ebb246577aeaaa012c3.png)](img/guide_project_landing_page_v12_10.png) + +2. 在" **添加 Kubernetes 集群集成"**页面上,单击" **创建新集群"**选项卡,然后单击" **Google GKE"** . + +3. 与您的 Google 帐户关联,然后单击" **允许"**以允许访问您的 Google 帐户. (此授权请求仅在您第一次将 GitLab 与您的 Google 帐户连接时显示.) + + 授权访问后,将显示" **添加 Kubernetes 集群集成"**页面. + +4. 在**输入 Kubernetes 集群的详细信息**部分中,提供有关集群的详细信息: + + * **Kubernetes cluster name** + * **环境范围** -保留此字段不变. + * **Google Cloud Platform 项目** -选择一个项目. 在[配置 Google 帐户后](#configure-your-google-account) ,应该已经为您创建了一个项目. + * **区域** -要在其中创建群集的[区域/区域](https://cloud.google.com/compute/docs/regions-zones/) . + * **节点数** + * **机器类型** -有关[机器类型的](https://cloud.google.com/compute/docs/machine-types)更多信息,请参阅 Google 文档. + * **为 Anthos 启用 Cloud Run-**选中此复选框以对该集群使用[Cloud Run](../../user/project/clusters/add_gke_clusters.html#cloud-run-for-anthos) ,Istio 和 HTTP Load Balancing 加载项. + * **由 GitLab 管理的群集** -选中此复选框以[允许 GitLab 管理](../../user/project/clusters/index.html#gitlab-managed-clusters)该群集的[名称空间和服务帐户](../../user/project/clusters/index.html#gitlab-managed-clusters) . +5. Click **创建一个 Kubernetes 集群**. + +几分钟后,将创建集群. 您还可以在[GCP 仪表板上](https://console.cloud.google.com/kubernetes)查看其状态. + +接下来,您将在群集上安装一些需要充分利用 Auto DevOps 的应用程序. + +## Install Ingress and Prometheus[](#install-ingress-and-prometheus "Permalink") + +集群运行后,您可以安装第一个应用程序. 在本指南中,我们将安装 Ingress 和 Prometheus: + +* 入口-在后台使用 NGINX 提供负载平衡,SSL 终止和基于名称的虚拟主机. +* Prometheus-一种用于监视已部署应用程序的开源监视和警报系统. + +**注意:**我们不会在此快速入门指南中安装 GitLab Runner,因为该指南使用了 GitLab.com 提供的共享 Runners. + +要安装应用程序: + +* 单击**Ingress**的**安装**按钮. +* 显示**入口端点时** ,复制 IP 地址. +* 添加您的**基本域** . 对于本指南,我们将使用 GitLab 建议的域. +* Click **保存更改**. + +[![Cluster Base Domain](img/3b33bfa40900241891ce4c916e441a22.png)](img/guide_base_domain_v12_3.png) + +## Enable Auto DevOps (optional)[](#enable-auto-devops-optional "Permalink") + +默认情况下启用 Auto DevOps 时,可以在实例级别(对于自我管理的实例)和组级别禁用 Auto DevOps. 完成以下步骤以启用 Auto DevOps(如果已禁用): + +1. 导航 **设置> CI / CD>自动 DevOps** ,然后点击**扩展** . +2. 选择**默认为自动 DevOps 管道**以显示更多选项. +3. 在" **部署策略"中** ,选择所需的[连续部署策略](index.html#deployment-strategy) ,以在管道成功在`master`分支上运行之后将应用程序部署到生产中. +4. Click **保存更改**. + + [![Auto DevOps settings](img/80a62bce7846a67c7743ef7324a58757.png)](img/guide_enable_autodevops_v12_3.png) + +保存更改后,GitLab 将创建一个新管道. 要查看它,请转到 **CI / CD>管道** . + +在下一节中,我们将解释管道中每个作业的作用. + +## Deploy the application[](#deploy-the-application "Permalink") + +当管道运行时,它在做什么? + +要查看管道中的作业,请单击管道的状态标记. 的 图标在管道作业运行时显示,并在不刷新页面的情况下进行更新 (成功)或 (失败)作业完成时. + +作业分为以下几个阶段: + +[![Pipeline stages](img/bc03121106ba9696b67a617d6aeb3878.png)](img/guide_pipeline_stages_v13_0.png) + +* **构建** -应用程序将构建 Docker 映像并将其上传到项目的[Container Registry](../../user/packages/container_registry/index.html) ( [Auto Build](stages.html#auto-build) ). +* **测试** -GitLab 在应用程序上运行各种检查: + + * `test`作业通过检测语言和框架来运行单元测试和集成测试( [自动测试](stages.html#auto-test) ) + * `code_quality`作业检查代码质量,并允许失败( [自动代码质量](stages.html#auto-code-quality-starter) ) + * `container_scanning`作业检查 Docker 容器是否存在任何漏洞并被允许失败( [自动容器扫描](stages.html#auto-container-scanning-ultimate) ) + * `dependency_scanning`作业检查应用程序是否具有易受漏洞影响的任何依赖关系,并允许其失败( [自动依赖关系扫描](stages.html#auto-dependency-scanning-ultimate) ) + * 后缀为`-sast`作业在当前代码上运行静态分析,以检查潜在的安全问题,并允许其失败( [Auto SAST](stages.html#auto-sast-ultimate) ) + * `secret-detection`作业会检查泄漏的机密并允许其失败( [自动机密检测](stages.html#auto-secret-detection-ultimate) ) + * `license_management`作业搜索应用程序的依存关系,以确定其每个许可证并被允许失败( [自动许可证合规](stages.html#auto-license-compliance-ultimate) )**注意:**除`test`外,所有作业均允许在测试阶段失败. +* **回顾** -对输水管道`master`包括这个阶段有`dast_environment_deploy`工作. 要了解更多信息,请参阅[动态应用程序安全性测试(DAST)](../../user/application_security/dast/index.html) . + +* **生产** -测试和检查完成后,该应用程序将在 Kubernetes 中进行部署( [Auto Deploy](stages.html#auto-deploy) ). + +* **性能** -性能测试在已部署的应用程序上运行( [自动浏览器性能测试](stages.html#auto-browser-performance-testing-premium) ). + +* **清理** -对输水管道`master`包括这个阶段有`stop_dast_environment`工作. + +在运行管道之后,您应该查看已部署的网站并学习如何对其进行监视. + +### Monitor your project[](#monitor-your-project "Permalink") + +成功部署您的应用程序后,您可以通过导航到" **环境"**页面来查看其网站并检查其运行状况. **运营>环境** . 该页面显示有关已部署应用程序的详细信息,右侧列显示将您链接到常见环境任务的图标: + +[![Environments](img/c2b9039967ef1a229c8db9d7542591fb.png)](img/guide_environments_v12_3.png) + +* **开放的现场环境** ( )-打开生产环境中部署的应用程序的 URL +* **Monitoring** () - Opens the metrics page where Prometheus collects data about the Kubernetes cluster and how the application affects it in terms of memory usage, CPU usage, and latency +* **部署到** ( )-显示可以部署到的环境的列表 +* **终端** ( )-在运行应用程序的容器内打开[Web 终端](../../ci/environments/index.html#web-terminals)会话 +* **重新部署到环境** ( )-有关更多信息,请参阅[重试和回滚](../../ci/environments/index.html#retrying-and-rolling-back) +* **停止环境** ( )-有关更多信息,请参阅[停止环境](../../ci/environments/index.html#stopping-an-environment) + +GitLab 在环境信息下方显示[部署板](../../user/project/deploy_boards.html) ,并用正方形表示 Kubernetes 集群中的 Pod,并用颜色编码以显示其状态. 将鼠标悬停在部署板上的正方形上会显示部署的状态,单击该正方形会将您带到窗格的日志页面. + +**提示:**该示例目前仅显示一个托管应用程序的 Pod,但是您可以通过在以下[`REPLICAS`](customize.html#environment-variables)定义[`REPLICAS`变量](customize.html#environment-variables)来添加更多 Pod **设置> CI / CD>环境变量** . + +### Work with branches[](#work-with-branches "Permalink") + +按照[GitLab 流程](../gitlab_flow.html#working-with-feature-branches) ,您接下来应该创建一个功能分支以向您的应用程序添加内容: + +1. 在项目的存储库中,导航到以下文件: `app/views/welcome/index.html.erb` . 该文件应仅包含一个段落: `<p>You're on Rails!</p>` . +2. 打开 GitLab [Web IDE](../../user/project/web_ide/index.html)进行更改. +3. 编辑文件,使其包含: + + ``` + <p>You're on Rails! Powered by GitLab Auto DevOps.</p> + ``` + +4. 暂存文件. 添加提交消息,然后通过单击**Commit**创建一个新分支和一个合并请求. + + [![Web IDE commit](img/d8baae909b3683bffff327402580132f.png)](img/guide_ide_commit_v12_3.png) + +提交合并请求后,GitLab 运行你的管道,而在这一切的工作,如[前文所述](#deploy-the-application) ,除了仅在比其他分支多跑几个`master` . + +[![Merge request](img/161780e2fab1ff78247b22985553ba96.png)](img/guide_merge_request_v12_3.png) + +几分钟后,您会注意到测试失败,这意味着您的更改"破坏了"测试. 单击失败的`test`作业以查看有关它的更多信息: + +``` +Failure: +WelcomeControllerTest#test_should_get_index [/app/test/controllers/welcome_controller_test.rb:7]: +<You're on Rails!> expected but was +<You're on Rails! Powered by GitLab Auto DevOps.>.. +Expected 0 to be >= 1. + +bin/rails test test/controllers/welcome_controller_test.rb:4 +``` + +要修复损坏的测试: + +1. 返回到合并请求的" **概述"**页面,然后单击" **在 Web IDE 中打开"** . +2. 在文件的左侧目录中,找到`test/controllers/welcome_controller_test.rb`文件,然后单击将其打开. +3. 更改第 7 行,说" `You're on Rails! Powered by GitLab Auto DevOps.` `You're on Rails! Powered by GitLab Auto DevOps.` +4. Click **Commit**. +5. 在左侧列的"未**分段的更改"下** ,单击选中标记图标( )进行更改. +6. 编写提交消息,然后单击**提交** . + +返回到合并请求的" **概述"**页面,您不仅应该看到测试通过,而且应该看到部署为[审阅应用程序的应用程序](stages.html#auto-review-apps) . 您可以通过单击**查看应用程序**来访问它 按钮以查看已部署的更改. + +[![Review app](img/afdb4890858bdb916f8a393b22b8ef96.png)](img/guide_merge_request_review_app_v12_3.png) + +合并合并请求后,GitLab 在`master`分支上运行管道,然后将应用程序部署到生产环境. + +## Conclusion[](#conclusion "Permalink") + +实施该项目之后,您应该对 Auto DevOps 的基础有深入的了解. 您从构建和测试开始,到在 GitLab 中全部部署和监视应用程序. 尽管具有自动特性,但也可以配置和自定义 Auto DevOps 以适合您的工作流程. 以下是一些有用的资源,供您进一步阅读: + +1. [Auto DevOps](index.html) +2. [Multiple Kubernetes clusters](index.html#using-multiple-kubernetes-clusters) +3. [Incremental rollout to production](customize.html#incremental-rollout-to-production-premium) +4. [Disable jobs you don’t need with environment variables](customize.html#environment-variables) +5. [Use a static IP for your cluster](../../user/clusters/applications.html#using-a-static-ip) +6. [Use your own buildpacks to build your application](customize.html#custom-buildpacks) +7. [Prometheus monitoring](../../user/project/integrations/prometheus.html) \ No newline at end of file diff --git a/docs/209.md b/docs/209.md new file mode 100644 index 0000000000000000000000000000000000000000..9897a69e0d73d0715ddcb6678d536188f6be3c44 --- /dev/null +++ b/docs/209.md @@ -0,0 +1,73 @@ +# Requirements for Auto DevOps + +> 原文:[https://docs.gitlab.com/ee/topics/autodevops/requirements.html](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) + +* [Auto DevOps requirements for Kubernetes](#auto-devops-requirements-for-kubernetes) +* [Auto DevOps requirements for Amazon ECS](#auto-devops-requirements-for-amazon-ecs) + +# Requirements for Auto DevOps[](#requirements-for-auto-devops "Permalink") + +您可以为[Kubernetes](#auto-devops-requirements-for-kubernetes)或[Amazon Elastic Container Service(ECS)](#auto-devops-requirements-for-amazon-ecs)设置 Auto DevOps. 有关 Auto DevOps 的更多信息,请参见[Auto DevOps 主页](index.html)或[快速入门指南](quick_start_guide.html) . + +## Auto DevOps requirements for Kubernetes[](#auto-devops-requirements-for-kubernetes "Permalink") + +要充分利用 Auto DevOps 和 Kubernetes,您需要: + +* **Kubernetes** (用于[自动审阅应用程序](stages.html#auto-review-apps) , [自动部署](stages.html#auto-deploy)和[自动监视](stages.html#auto-monitoring) ) + + 要启用部署,您需要: + + 1. 您的项目的[Kubernetes 1.12+集群](../../user/project/clusters/index.html) . 最简单的方法是[使用 GitLab UI](../../user/project/clusters/add_remove_clusters.html#create-new-cluster)创建[新集群](../../user/project/clusters/add_remove_clusters.html#create-new-cluster) . 对于 Kubernetes 1.16+群集,您必须为[Auto Deploy for Kubernetes 1.16+](stages.html#kubernetes-116)执行附加配置. + 2. NGINX 入口. 在上一步中配置了 GitLab 的 Kubernetes 集成之后,可以通过安装[用于 Ingress](../../user/clusters/applications.html#ingress)的[GitLab 托管的应用程序,](../../user/clusters/applications.html#ingress)将其部署到 Kubernetes 集群中. + + 另外,您可以使用[`nginx-ingress`](https://github.com/helm/charts/tree/master/stable/nginx-ingress) Helm 图表手动安装 Ingress. + + **注意:**如果您使用自己的 Ingress 而不是 GitLab 托管应用程序提供的 Ingress,请确保您至少运行的是 NGINX Ingress 0.9.0 版,并[启用 Prometheus](https://github.com/helm/charts/tree/master/stable/nginx-ingress#prometheus-metrics)指标以显示响应指标. 您还必须使用`prometheus.io/scrape: "true"`和`prometheus.io/port: "10254"` [注释](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)由 Prometheus 抓取的 NGINX Ingress 部署. +* **基本域** (用于[自动审阅应用程序](stages.html#auto-review-apps) , [自动部署](stages.html#auto-deploy)和[自动监视](stages.html#auto-monitoring) ) + + 您需要一个配置了通配符 DNS 的域,所有您的 Auto DevOps 应用程序都将使用该域. 如果您使用的是[GitLab 托管的 Ingress 应用程序](../../user/clusters/applications.html#ingress) ,则会自动为您配置 URL 端点. + + 您还必须[指定 Auto DevOps 基本域](index.html#auto-devops-base-domain) . + +* **GitLab Runner** (所有阶段) + + 必须将 Runner 配置为运行 Docker,通常使用[Docker](https://docs.gitlab.com/runner/executors/docker.html)或[Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html)执行程序,并[启用特权模式](https://docs.gitlab.com/runner/executors/docker.html) . Runner 不需要安装在 Kubernetes 集群中,但是 Kubernetes 执行器易于使用,并且可以自动缩放. 您还可以使用[Docker Machine 将](https://docs.gitlab.com/runner/install/autoscaling.html)基于 Docker 的 Runner 配置为自动缩放. + + 如果您在第一步中配置了 GitLab 的 Kubernetes 集成,则可以通过[为 GitLab Runner](../../user/clusters/applications.html#gitlab-runner)安装由[GitLab 管理的应用程序](../../user/clusters/applications.html#gitlab-runner)将其部署到集群中. + + 运动员应注册为[共享亚军](../../ci/runners/README.html#shared-runners)整个 GitLab 实例或[特定的运动员](../../ci/runners/README.html#specific-runners)被分配到具体项目(默认值,如果你已经安装了 GitLab 亚军管理应用程序). + +* **Prometheus** (for [Auto Monitoring](stages.html#auto-monitoring)) + + 要启用自动监控,您需要在集群内部或外部安装 Prometheus,并配置为刮取 Kubernetes 集群. 如果已经配置了 GitLab 的 Kubernetes 集成,则可以通过安装[Prometheus](../../user/clusters/applications.html#prometheus)的[GitLab 托管的应用程序](../../user/clusters/applications.html#prometheus)将其部署到集群中. + + 必须为项目启用[Prometheus 服务](../../user/project/integrations/prometheus.html)集成,或者将其作为整个 GitLab 安装的[默认服务模板](../../user/project/integrations/services_templates.html)启用. + + 要获取响应指标(除了系统指标之外),您必须[配置 Prometheus 来监视 NGINX](../../user/project/integrations/prometheus_library/nginx_ingress.html#configuring-nginx-ingress-monitoring) . + +* **cert-manager** (可选,用于 TLS / HTTPS) + + 要为您的应用程序启用 HTTPS 端点,必须安装 cert-manager,这是一个本地 Kubernetes 证书管理控制器,可帮助颁发证书. 在您的群集上安装 cert-manager 会发出[Let's Encrypt](https://letsencrypt.org/)证书,并确保证书有效和最新. 如果已经配置了 GitLab 的 Kubernetes 集成,则可以通过安装[GitLab 托管的 cert-manager 应用程序](../../user/clusters/applications.html#cert-manager)将其部署到集群中. + +如果您没有安装 Kubernetes 或 Prometheus,则将跳过[Auto Review Apps](stages.html#auto-review-apps) , [Auto Deploy](stages.html#auto-deploy)和[Auto Monitoring](stages.html#auto-monitoring) . + +满足所有要求后,您可以[启用 Auto DevOps](index.html#enablingdisabling-auto-devops) . + +## Auto DevOps requirements for Amazon ECS[](#auto-devops-requirements-for-amazon-ecs "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208132) in GitLab 13.0. + +您可以选择将[AWS ECS](../../ci/cloud_deployment/index.html)定位为部署平台,而不是使用 Kubernetes. + +要开始使用针对 AWS ECS 的 Auto DevOps,您必须添加特定的环境变量. 这样做,请按照下列步骤操作: + +1. 在您的项目中,转到**"设置">" CI / CD",**然后展开" **变量"**部分. + +2. 通过添加具有以下值之一的`AUTO_DEVOPS_PLATFORM_TARGET`变量,指定在 Auto DevOps 部署期间要定位的 AWS 平台: + + * `FARGATE`如果您的目标服务必须启动类型 FARGATE 的. + * `ECS`如果部署到 ECS,当你不执行任何启动类型检查. + +触发管道时,如果启用了 Auto DevOps 且已正确[输入 AWS 凭证作为环境变量](../../ci/cloud_deployment/index.html#deploy-your-application-to-the-aws-elastic-container-service-ecs) ,则您的应用程序将部署到 AWS ECS. + +**注意:**部署到 AWS ECS 时, [GitLab 托管应用程序](../../user/clusters/applications.html)不可用. 您必须在 AWS ECS 上手动配置应用程序(例如 Ingress 或 Help).**注意:**如果您同时具有有效的`AUTO_DEVOPS_PLATFORM_TARGET`变量和与项目绑定的 Kubernetes 集群,则仅运行 Kubernetes 的部署.**警告:**将`AUTO_DEVOPS_PLATFORM_TARGET`变量设置为`ECS`将触发[`Jobs/Deploy/ECS.gitlab-ci.yml`模板中](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml)定义的[`Jobs/Deploy/ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml) . 但是,不建议单独[包含](../../ci/yaml/README.html#includetemplate)它. 该模板仅设计用于 Auto DevOps. 如果单独包含它,它可能会发生意外更改,从而导致您的管道失败. 同样,此模板中的作业名称也可能会更改. 不要在自己的管道中覆盖这些作业的名称,因为当名称更改时,覆盖将停止工作. \ No newline at end of file diff --git a/docs/210.md b/docs/210.md new file mode 100644 index 0000000000000000000000000000000000000000..907af70b387223245f60e4766cd922a110266c59 --- /dev/null +++ b/docs/210.md @@ -0,0 +1,471 @@ +# Customizing Auto DevOps + +> 原文:[https://docs.gitlab.com/ee/topics/autodevops/customize.html](https://docs.gitlab.com/ee/topics/autodevops/customize.html) + +* [Custom buildpacks](#custom-buildpacks) + * [Multiple buildpacks](#multiple-buildpacks) +* [Custom `Dockerfile`](#custom-dockerfile) +* [Passing arguments to `docker build`](#passing-arguments-to-docker-build) +* [Forward CI variables to the build environment](#forward-ci-variables-to-the-build-environment) +* [Custom Helm Chart](#custom-helm-chart) +* [Customize values for Helm Chart](#customize-values-for-helm-chart) +* [Custom Helm chart per environment](#custom-helm-chart-per-environment) +* [Customizing `.gitlab-ci.yml`](#customizing-gitlab-ciyml) +* [Customizing the Kubernetes namespace](#customizing-the-kubernetes-namespace) +* [Using components of Auto DevOps](#using-components-of-auto-devops) +* [PostgreSQL database support](#postgresql-database-support) + * [Upgrading PostgresSQL](#upgrading-postgressql) + * [Using external PostgreSQL database providers](#using-external-postgresql-database-providers) +* [Environment variables](#environment-variables) + * [Build and deployment](#build-and-deployment) + * [Database](#database) + * [Disable jobs](#disable-jobs) + * [Application secret variables](#application-secret-variables) + * [Advanced replica variables setup](#advanced-replica-variables-setup) + * [Deploy policy for staging and production environments](#deploy-policy-for-staging-and-production-environments) + * [Deploy policy for canary environments](#deploy-policy-for-canary-environments-premium) + * [Incremental rollout to production](#incremental-rollout-to-production-premium) + * [Timed incremental rollout to production](#timed-incremental-rollout-to-production-premium) +* [Auto DevOps banner](#auto-devops-banner) + +# Customizing Auto DevOps[](#customizing-auto-devops "Permalink") + +尽管[Auto DevOps](index.html)提供了很好的默认设置来帮助您入门,但是您可以自定义几乎所有内容以满足您的需求. Auto DevOps 提供了从自定义[buildpacks](#custom-buildpacks)到[Dockerfiles](#custom-dockerfile)和[Helm 图表的所有内容](#custom-helm-chart) . 您甚至可以将完整的[CI / CD 配置](#customizing-gitlab-ciyml)复制到您的项目中,以启用暂存和 Canary 部署等. + +## Custom buildpacks[](#custom-buildpacks "Permalink") + +如果您的项目无法自动检测到构建包,或者要使用自定义构建包,则可以在项目中使用项目变量或`.buildpacks`文件覆盖`.buildpacks` : + +* **项目变量** -使用要使用的 buildpack 的 URL 创建项目变量`BUILDPACK_URL` . +* **`.buildpacks`文件** -在项目的存储库中添加一个名为`.buildpacks`的文件,并添加要在文件中一行使用的 buildpack 的 URL. 如果要使用多个 buildpack,请每行输入一个 buildpack. + +buildpack URL 可以指向 Git 存储库 URL 或 tarball URL. 对于 Git 存储库,您可以通过将`#<ref>`附加到 Git 存储库 URL 来指向特定的 Git 引用(例如,提交 SHA,标记名称或分支名称). 例如: + +* 标签`v142` : `https://github.com/heroku/heroku-buildpack-ruby.git#v142` : `https://github.com/heroku/heroku-buildpack-ruby.git#v142` . +* 分支`mybranch` : `https://github.com/heroku/heroku-buildpack-ruby.git#mybranch` : `https://github.com/heroku/heroku-buildpack-ruby.git#mybranch` . +* 提交 SHA `f97d8a8ab49` : `https://github.com/heroku/heroku-buildpack-ruby.git#f97d8a8ab49` : `https://github.com/heroku/heroku-buildpack-ruby.git#f97d8a8ab49` . + +### Multiple buildpacks[](#multiple-buildpacks "Permalink") + +Auto DevOps 不完全支持使用多个 buildpack,因为在使用`.buildpacks`文件时,自动测试将不起作用. 在后端用于解析`.buildpacks`文件的 buildpack [heroku-buildpack-multi](https://github.com/heroku/heroku-buildpack-multi/)没有提供必要的命令`bin/test-compile`和`bin/test` . + +If your goal is to use only a single custom buildpack, you should provide the project variable `BUILDPACK_URL` instead. + +## Custom `Dockerfile`[](#custom-dockerfile "Permalink") + +> [在 GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35662)中[添加了](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35662)对`DOCKERFILE_PATH`支持 + +如果您的项目在项目存储库的根目录中有一个`Dockerfile` ,则 Auto DevOps 会基于 Dockerfile 而不是使用 buildpacks 构建 Docker 映像. 这样可以更快,并产生较小的映像,尤其是在您的 Dockerfile 基于[Alpine 的情况下](https://hub.docker.com/_/alpine/) . + +如果设置`DOCKERFILE_PATH` CI 变量,则"自动构建"将在其中查找 Dockerfile. + +## Passing arguments to `docker build`[](#passing-arguments-to-docker-build "Permalink") + +可以使用`AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS`项目变量将参数传递给`AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` `docker build`命令. 例如,要基于`ruby:alpine`而不是默认的`ruby:latest`构建 Docker 映像: + +1. Set `AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` to `--build-arg=RUBY_VERSION=alpine`. +2. 将以下内容添加到自定义`Dockerfile` : + + ``` + ARG RUBY_VERSION=latest + FROM ruby:$RUBY_VERSION + + # ... put your stuff here + ``` + +**注意:**如果需要传递复杂的值(例如换行符和空格), **请**使用 Base64 编码. 由于 Auto DevOps 如何使用自变量,此类未经编码的复杂值可能导致转义问题.**警告:**尽可能避免将秘密作为 Docker 构建参数传递,因为它们可能会保留在映像中. 有关详细信息,请参见[有关最佳实践的讨论](https://github.com/moby/moby/issues/13490) . + +## Forward CI variables to the build environment[](#forward-ci-variables-to-the-build-environment "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/25514) ,但在 11.9 及更高版本中可用. + +可以使用`AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` CI 变量将 CI 变量转发到构建环境中. 转发的变量应在逗号分隔的列表中按名称指定. 例如,要转发变量`CI_COMMIT_SHA`和`CI_ENVIRONMENT_NAME` ,请将`AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES`设置为`CI_COMMIT_SHA,CI_ENVIRONMENT_NAME` . + +* 使用 Buildpacks 时,转发的变量将自动用作环境变量. +* 使用`Dockerfile` ,需要执行以下附加步骤: + + 1. 通过将以下代码添加到文件顶部来激活实验性`Dockerfile`语法: + + ``` + # syntax = docker/dockerfile:experimental + ``` + + 2. 要在任何可用的秘密`RUN $COMMAND`在`Dockerfile` ,秘密文件和源安装运行之前,它`$COMMAND` : + + ``` + RUN --mount=type=secret,id=auto-devops-build-secrets . /run/secrets/auto-devops-build-secrets && $COMMAND + ``` + +**注意:**设置`AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` ,Auto DevOps 会启用实验性[Docker BuildKit](https://s0docs0docker0com.icopy.site/develop/develop-images/build_enhancements/)功能以使用`--secret`标志. + +## Custom Helm Chart[](#custom-helm-chart "Permalink") + +Auto DevOps 使用[Helm](https://helm.sh/)将您的应用程序部署到 Kubernetes. 您可以通过将图表捆绑到项目存储库中或通过指定项目变量来覆盖使用的 Helm 图表: + +* **捆绑图** -如果您的项目中有一个带有`Chart.yaml`文件的`./chart`目录,则 Auto DevOps 将检测到该图并使用它代替[默认图](https://gitlab.com/gitlab-org/charts/auto-deploy-app) ,从而使您能够精确地控制应用程序的部署方式. +* **项目变量** -创建一个[项目变量](../../ci/variables/README.html#gitlab-cicd-environment-variables) `AUTO_DEVOPS_CHART`有一个自定义图表的 URL 来使用,或创建两个项目变量: `AUTO_DEVOPS_CHART_REPOSITORY`有一个自定义图表库的 URL,并`AUTO_DEVOPS_CHART`与路径图. + +## Customize values for Helm Chart[](#customize-values-for-helm-chart "Permalink") + +[介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/30628)在 GitLab 12.6, `.gitlab/auto-deploy-values.yaml`将默认为头盔升级使用. + +您可以通过以下任一方式覆盖[默认 Helm 图表中](https://gitlab.com/gitlab-org/charts/auto-deploy-app) `values.yaml`文件中的[默认值](https://gitlab.com/gitlab-org/charts/auto-deploy-app) : + +* 将名为`.gitlab/auto-deploy-values.yaml`的文件添加到您的存储库,如果找到,该文件将自动使用. +* 将具有不同名称或路径的文件添加到存储库,并使用路径和名称设置`HELM_UPGRADE_VALUES_FILE` [环境变量](#environment-variables) . + +**注:**对于 GitLab 12.5 和更早的版本,使用`HELM_UPGRADE_EXTRA_ARGS`环境变量设置以覆盖默认图表值`HELM_UPGRADE_EXTRA_ARGS`到`--values <my-values.yaml>` + +## Custom Helm chart per environment[](#custom-helm-chart-per-environment "Permalink") + +您可以通过将环境变量定义为所需环境来指定每个环境使用自定义 Helm 图表. 请参阅[限制变量的环境范围](../../ci/variables/README.html#limit-the-environment-scopes-of-environment-variables) . + +## Customizing `.gitlab-ci.yml`[](#customizing-gitlab-ciyml "Permalink") + +Auto DevOps 是完全可自定义的,因为[Auto DevOps 模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)只是[`.gitlab-ci.yml`](../../ci/yaml/README.html)文件的实现,并且仅使用任何`.gitlab-ci.yml`实现的`.gitlab-ci.yml` . + +要修改 Auto DevOps 使用的 CI / CD 管道,请[`include`模板](../../ci/yaml/README.html#includetemplate) ,并根据需要通过向包含以下内容的存储库的根目录中添加`.gitlab-ci.yml`文件来自定义它: + +``` +include: + - template: Auto-DevOps.gitlab-ci.yml +``` + +添加您的更改,您的添加将使用[`include`](../../ci/yaml/README.html#include)所描述的行为与[Auto DevOps 模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)合并. + +如果您需要专门删除文件的一部分,还可以将[Auto DevOps 模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)的内容复制并粘贴到您的项目中,并根据需要进行编辑. + +## Customizing the Kubernetes namespace[](#customizing-the-kubernetes-namespace "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) . + +对于不受 GitLab 管理的集群,可以通过指定[`environment:kubernetes:namespace`](../../ci/environments/index.html#configuring-kubernetes-deployments)来自定义`.gitlab-ci.yml`的[`environment:kubernetes:namespace`](../../ci/environments/index.html#configuring-kubernetes-deployments) . 例如,以下配置将覆盖用于`production`部署的名称空间: + +``` +include: + - template: Auto-DevOps.gitlab-ci.yml + +production: + environment: + kubernetes: + namespace: production +``` + +使用 Auto DevOps 部署到自定义名称空间时,群集随附的服务帐户至少需要名称空间内的`edit`角色. + +* 如果服务帐户可以创建名称空间,则可以按需创建名称空间. +* 否则,名称空间必须在部署之前存在. + +## Using components of Auto DevOps[](#using-components-of-auto-devops "Permalink") + +如果仅需要 Auto DevOps 提供的功能的子集,则可以将各个 Auto DevOps 作业包括在自己的`.gitlab-ci.yml` . 每个组件作业都依赖于一个阶段,该阶段应该在包含模板的`.gitlab-ci.yml`中定义. + +例如,要使用[自动构建](stages.html#auto-build) ,可以将以下内容添加到`.gitlab-ci.yml` : + +``` +stages: + - build + +include: + - template: Jobs/Build.gitlab-ci.yml +``` + +有关可用作业的信息,请参见[Auto DevOps 模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml) . + +**弃用:**从[GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213336)开始,使用[`only`](../../ci/yaml/README.html#onlyexcept-basic)或[`except`](../../ci/yaml/README.html#onlyexcept-basic)语法的 Auto DevOps 模板将切换到[`rules`](../../ci/yaml/README.html#rules)语法. 如果您`.gitlab-ci.yml`扩展了这些汽车的 DevOps 模板和覆盖`only`或`except`关键字,您必须迁移模板使用[`rules`](../../ci/yaml/README.html#rules)语法的基本模板被迁移到使用后`rules`语法. 对于尚不能迁移的用户,您可以选择将模板固定到[基于 GitLab 12.10 的模板](https://gitlab.com/gitlab-org/auto-devops-v12-10) . + +## PostgreSQL database support[](#postgresql-database-support "Permalink") + +为了支持需要数据库的应用程序,默认情况下配置[PostgreSQL](https://s0www0postgresql0org.icopy.site/) . 访问数据库的凭据已预先配置,但可以通过设置关联[变量](#environment-variables)进行自定义. 您可以使用这些凭据来定义`DATABASE_URL` : + +``` +postgres://user:password@postgres-host:postgres-port/postgres-database +``` + +### Upgrading PostgresSQL[](#upgrading-postgressql "Permalink") + +**弃用:**用于控制默认`AUTO_DEVOPS_POSTGRES_CHANNEL`配置 PostgreSQL 的变量`AUTO_DEVOPS_POSTGRES_CHANNEL`在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/issues/210499)已更改为`2` . 要继续使用旧的 PostgreSQL,请将`AUTO_DEVOPS_POSTGRES_CHANNEL`变量设置为`1` . + +用于配置 PostgreSQL 的图表的版本: + +* 在 GitLab 13.0 和更高版本中为 8.2.1,但如果需要可以将其设置回 0.7.1. +* 可以在 GitLab 12.9 和 12.10 中设置为 0.7.1 至 8.2.1. +* 在 GitLab 12.8 及更早版本中为 0.7.1. + +GitLab 鼓励用户[将其数据库迁移](upgrading_postgresql.html)到较新的 PostgreSQL. + +### Using external PostgreSQL database providers[](#using-external-postgresql-database-providers "Permalink") + +尽管 Auto DevOps 为生产环境提供了对 PostgreSQL 容器的开箱即用支持,但在某些情况下,它可能不够安全或没有弹性,您可能要使用外部托管提供程序(例如 AWS Relational Database)服务)(适用于 PostgreSQL). + +您必须在项目的 CI / CD 设置中为`POSTGRES_ENABLED`和`DATABASE_URL`定义环境范围的变量: + +1. 使用范围内的[环境变量](../../ci/environments/index.html#scoping-environments-with-specs)针对所需环境禁用内置 PostgreSQL 安装. 对于此用例,可能只需要将`production`添加到此列表中. 用于 Review Apps 和登台的内置 PostgreSQL 设置就足够了. + + [![Auto Metrics](img/f4a6d7020c73bd402fc6428d02a4e550.png)](img/disable_postgres.png) + +2. Define the `DATABASE_URL` CI variable as a scoped environment variable that will be available to your application. This should be a URL in the following format: + + ``` + postgres://user:password@postgres-host:postgres-port/postgres-database + ``` + +您必须确保您的 Kubernetes 集群可以访问托管 PostgreSQL 的任何地方的网络. + +## Environment variables[](#environment-variables "Permalink") + +以下变量可用于设置 Auto DevOps 域,提供自定义 Helm 图表或缩放应用程序. PostgreSQL 也可以自定义,您可以使用[自定义 buildpack](#custom-buildpacks) . + +### Build and deployment[](#build-and-deployment "Permalink") + +下表列出了与构建和部署应用程序有关的变量. + +| **Variable** | **Description** | +| --- | --- | +| `ADDITIONAL_HOSTS` | 指定为逗号分隔列表的标准域名,添加到 Ingress 主机中. | +| `<ENVIRONMENT>_ADDITIONAL_HOSTS` | 对于特定环境,将指定为逗号分隔列表的标准域名添加到 Ingress 主机. 这优先于`ADDITIONAL_HOSTS` . | +| `AUTO_DEVOPS_ATOMIC_RELEASE` | 从 GitLab 13.0 开始,默认情况下,Auto DevOps 使用[`--atomic`](https://v2.helm.sh/docs/helm/#options-43)进行 Helm 部署. 将此变量设置为`false`可禁用`--atomic` | +| `AUTO_DEVOPS_BUILD_IMAGE_CNB_ENABLED` | 当设置为非空值且不存在`Dockerfile` ,"自动构建"将使用 Cloud Native Buildpacks 而非 Herokuish 构建应用程序. [更多细节](stages.html#auto-build-using-cloud-native-buildpacks-beta) . | +| `AUTO_DEVOPS_BUILD_IMAGE_CNB_BUILDER` | 使用 Cloud Native Buildpacks 构建时使用的构建器. 默认的构建器是`heroku/buildpacks:18` . [更多细节](stages.html#auto-build-using-cloud-native-buildpacks-beta) . | +| `AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` | 要传递给`docker build`命令的额外参数. 请注意,使用引号不会阻止单词拆分. [更多细节](#passing-arguments-to-docker-build) . | +| `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` | A [comma-separated list of CI variable names](#forward-ci-variables-to-the-build-environment) to be forwarded to the build environment (the buildpack builder or `docker build`). | +| `AUTO_DEVOPS_CHART` | Helm Chart 用于部署您的应用程序. 默认为[GitLab 提供的](https://gitlab.com/gitlab-org/charts/auto-deploy-app) . | +| `AUTO_DEVOPS_CHART_REPOSITORY` | Helm Chart 存储库用于搜索图表. 默认为`https://charts.gitlab.io` . | +| `AUTO_DEVOPS_CHART_REPOSITORY_NAME` | 从 GitLab 11.11 开始,用于设置 Helm 存储库的名称. 默认为`gitlab` . | +| `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME` | 从 GitLab 11.11 开始,用于设置用户名以连接到 Helm 存储库. 默认为无凭据. 还要设置`AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD` . | +| `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD` | 从 GitLab 11.11 开始,用于设置密码以连接到 Helm 存储库. 默认为无凭据. 还要设置`AUTO_DEVOPS_CHART_REPOSITORY_USERNAME` . | +| `AUTO_DEVOPS_DEPLOY_DEBUG` | 从 GitLab 13.1 开始,如果存在此变量,Helm 将输出调试日志. | +| `AUTO_DEVOPS_ALLOW_TO_FORCE_DEPLOY_V<N>` | 从[auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image) v1.0.0 起,如果存在此变量,则将强制部署新的主要图表版本. [更多细节](upgrading_chart.html#ignore-warning-and-continue-deploying) | +| `AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE` | 从 GitLab 12.5 起,与[ModSecurity 功能标记](../../user/clusters/applications.html#web-application-firewall-modsecurity)结合使用可切换[ModSecurity 的`SecRuleEngine`](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#SecRuleEngine)行为. 默认为`DetectionOnly` . | +| `BUILDPACK_URL` | Buildpack’s full URL. Can point to either [a Git repository URL or a tarball URL](#custom-buildpacks). | +| `CANARY_ENABLED` | 从 GitLab 11.0 开始,用于定义[Canary 环境](#deploy-policy-for-canary-environments-premium)的[部署策略](#deploy-policy-for-canary-environments-premium) . | +| `CANARY_PRODUCTION_REPLICAS` | 要在生产环境中为[Canary 部署](../../user/project/canary_deployments.html)进行部署的 Canary 副本数. 优先于`CANARY_REPLICAS` . 默认为 1. | +| `CANARY_REPLICAS` | 用于[Canary 部署](../../user/project/canary_deployments.html)的 Canary 副本数. 默认为 1. | +| `DOCKERFILE_PATH` | 从 GitLab 13.2 开始,允许[在构建阶段](#custom-dockerfile)覆盖[默认的 Dockerfile 路径](#custom-dockerfile) | +| `HELM_RELEASE_NAME` | 从 GitLab 12.1 起,可以覆盖`helm`发布名称. 将多个项目部署到单个名称空间时,可用于分配唯一的发行版名称. | +| `HELM_UPGRADE_VALUES_FILE` | 从 GitLab 12.6 起,可以覆盖`helm upgrade`值文件. 默认为`.gitlab/auto-deploy-values.yaml` . | +| `HELM_UPGRADE_EXTRA_ARGS` | 从 GitLab 11.11 开始,在部署应用程序时允许在`helm`命令中使用其他参数. 请注意,使用引号不会阻止单词拆分. | +| `INCREMENTAL_ROLLOUT_MODE` | 从 GitLab 11.4 起,如果存在的话,可用于为生产环境启用应用程序的[增量部署](#incremental-rollout-to-production-premium) . 对于手动部署作业,设置为" `manual` ;对于自动部署部署,则设置为" `timed` ,每个延迟 5 分钟. | +| `K8S_SECRET_*` | 从 GitLab 11.7 开始,Auto DevOps 会将任何前缀为[`K8S_SECRET_`](#application-secret-variables)变量作为环境变量提供给已部署的应用程序. | +| `KUBE_INGRESS_BASE_DOMAIN` | 从 GitLab 11.8 开始,可用于为每个群集设置一个域. 有关更多信息,请参见[群集域](../../user/project/clusters/index.html#base-domain) . | +| `PRODUCTION_REPLICAS` | 要在生产环境中部署的副本数. 优先于`REPLICAS` ,默认值为 1.对于零停机升级,设置为 2 或更大. | +| `REPLICAS` | 要部署的副本数. 默认为 1. | +| `ROLLOUT_RESOURCE_TYPE` | 从 GitLab 11.9 开始,允许使用自定义 Helm 图表指定正在部署的资源类型. 默认值为`deployment` . | +| `ROLLOUT_STATUS_DISABLED` | 从 GitLab 12.0 开始,用于禁用推出状态检查,因为它不支持所有资源类型,例如`cronjob` . | +| `STAGING_ENABLED` | 从 GitLab 10.8 开始,用于定义[登台和生产环境](#deploy-policy-for-staging-and-production-environments)的[部署策略](#deploy-policy-for-staging-and-production-environments) . | + +**提示:**使用[项目变量](../../ci/variables/README.html#gitlab-cicd-environment-variables)设置副本[变量后](../../ci/variables/README.html#gitlab-cicd-environment-variables) ,可以通过重新部署来缩放应用程序.**注意:**您*不*应该直接扩展使用 Kubernetes 您的应用程序. 这可能会导致 Helm 无法检测到更改而造成混乱,随后使用 Auto DevOps 进行的部署可能会撤消您的更改. + +### Database[](#database "Permalink") + +下表列出了与数据库有关的变量. + +| **Variable** | **Description** | +| --- | --- | +| `DB_INITIALIZE` | 从 GitLab 11.4 开始,用于指定运行以初始化应用程序的 PostgreSQL 数据库的命令. 在应用程序窗格中运行. | +| `DB_MIGRATE` | 从 GitLab 11.4 开始,用于指定运行以迁移应用程序的 PostgreSQL 数据库的命令. 在应用程序窗格中运行. | +| `POSTGRES_ENABLED` | 是否启用 PostgreSQL. 默认为`true` . 设置为`false`可禁用 PostgreSQL 的自动部署. | +| `POSTGRES_USER` | PostgreSQL 用户. 默认为`user` . 将其设置为使用自定义用户名. | +| `POSTGRES_PASSWORD` | PostgreSQL 密码. 默认为`testing-password` . 将其设置为使用自定义密码. | +| `POSTGRES_DB` | PostgreSQL 数据库名称. 默认为[`$CI_ENVIRONMENT_SLUG`](../../ci/variables/README.html#predefined-environment-variables)的值. 将其设置为使用自定义数据库名称. | +| `POSTGRES_VERSION` | 用于[`postgres` Docker 映像的](https://hub.docker.com/_/postgres)标签. 对于`9.6.16` GitLab 13.0 `9.6.16`的测试和部署,默认值为`9.6.16` (以前为`9.6.2` ). 如果`AUTO_DEVOPS_POSTGRES_CHANNEL`设置为`1` ,则部署将使用默认版本`9.6.2` . | + +### Disable jobs[](#disable-jobs "Permalink") + +下表列出了用于禁用作业的变量. + +| **Variable** | **Description** | +| --- | --- | +| `CODE_QUALITY_DISABLED` | 从 GitLab 11.0 起,用于禁用`codequality`作业. 如果存在变量,则不会创建作业. | +| `CONTAINER_SCANNING_DISABLED` | From GitLab 11.0, used to disable the `sast:container` job. If the variable is present, the job won’t be created. | +| `DAST_DISABLED` | 从 GitLab 11.0 起,用于禁用`dast`作业. 如果存在变量,则不会创建作业. | +| `DEPENDENCY_SCANNING_DISABLED` | 从 GitLab 11.0 起,用于禁用`dependency_scanning`作业. 如果存在变量,则不会创建作业. | +| `LICENSE_MANAGEMENT_DISABLED` | 从 GitLab 11.0 开始,用于禁用`license_management`作业. 如果存在变量,则不会创建作业. | +| `PERFORMANCE_DISABLED` | 从 GitLab 11.0 起,用于禁用浏览器`performance`作业. 如果存在变量,则不会创建作业. | +| `LOAD_PERFORMANCE_DISABLED` | 从 GitLab 13.2 开始,用于禁用`load_performance`作业. 如果存在变量,则不会创建作业. | +| `REVIEW_DISABLED` | 从 GitLab 11.0 开始,用于禁用`review`和手动`review:stop`作业. 如果存在该变量,则不会创建这些作业. | +| `SAST_DISABLED` | 从 GitLab 11.0 起,用于禁用`sast`作业. 如果存在变量,则不会创建作业. | +| `TEST_DISABLED` | 从 GitLab 11.0 起,用于禁用`test`作业. 如果存在变量,则不会创建作业. | + +### Application secret variables[](#application-secret-variables "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49056) . + +某些应用程序需要定义可由部署的应用程序访问的秘密变量. Auto DevOps 会检测以`K8S_SECRET_`开头的变量,并将这些带前缀的变量作为环境变量提供给已部署的应用程序. + +要配置您的应用程序变量: + +1. Go to your project’s **设置> CI / CD**, then expand the **Variables** section. + +2. 创建一个 CI / CD 变量,确保密钥以`K8S_SECRET_`为前缀. 例如,您可以使用键`K8S_SECRET_RAILS_MASTER_KEY`创建一个变量. + +3. 通过手动创建新管道或将代码更改推送到 GitLab 来运行 Auto DevOps 管道. + +Auto DevOps 管道将使用您的应用程序秘密变量来填充 Kubernetes 秘密. 这个秘密在每个环境中都是唯一的. 部署应用程序时,机密将作为环境变量加载到运行应用程序的容器中. 在上面的示例之后,您可以在下面看到包含`RAILS_MASTER_KEY`变量的机密. + +``` +$ kubectl get secret production-secret -n minimal-ruby-app-54 -o yaml + +apiVersion: v1 +data: + RAILS_MASTER_KEY: MTIzNC10ZXN0 +kind: Secret +metadata: + creationTimestamp: 2018-12-20T01:48:26Z + name: production-secret + namespace: minimal-ruby-app-54 + resourceVersion: "429422" + selfLink: /api/v1/namespaces/minimal-ruby-app-54/secrets/production-secret + uid: 57ac2bfd-03f9-11e9-b812-42010a9400e4 +type: Opaque +``` + +通常认为环境变量在 Kubernetes 容器中是不可变的. 如果在不更改任何代码的情况下更新应用程序机密,然后手动创建新管道,则会发现任何正在运行的应用程序吊舱都不会具有更新后的机密. 要更新机密,请执行以下任一操作: + +* 将代码更新推送到 GitLab,以强制 Kubernetes 部署重新创建 Pod. +* 手动删除正在运行的 Pod,以使 Kubernetes 创建具有更新机密的新 Pod. + +**注意:**由于当前 Auto DevOps 脚本环境的限制,当前不支持具有多行值的变量. + +### Advanced replica variables setup[](#advanced-replica-variables-setup "Permalink") + +除了上面提到的两个与副本相关的生产变量之外,您还可以将其他变量用于不同的环境. + +Kubernetes 的标签名为`track` ,GitLab CI / CD 环境名称和副本环境变量被组合为`TRACK_ENV_REPLICAS`格式,使您能够定义自己的变量来扩展 Pod 的副本: + +* `TRACK` :Helm Chart 应用程序定义中`track` [Kubernetes 标签](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)的大写值. 如果未设置,则不会考虑到变量名. +* `ENV` :部署作业的大写环境名称,在`.gitlab-ci.yml`设置. + +在下面的示例中,环境的名称为`qa` ,并且部署了轨道`foo` ,这将导致一个名为`FOO_QA_REPLICAS`的环境变量: + +``` +QA testing: + stage: deploy + environment: + name: qa + script: + - deploy foo +``` + +还必须在应用程序的 Helm 图表中定义被引用的`foo`轨道,例如: + +``` +replicaCount: 1 +image: + repository: gitlab.example.com/group/project + tag: stable + pullPolicy: Always + secrets: + - name: gitlab-registry +application: + track: foo + tier: web +service: + enabled: true + name: web + type: ClusterIP + url: http://my.host.com/ + externalPort: 5000 + internalPort: 5000 +``` + +### Deploy policy for staging and production environments[](#deploy-policy-for-staging-and-production-environments "Permalink") + +在 GitLab 10.8 中[引入](https://gitlab.com/gitlab-org/gitlab-ci-yml/-/merge_requests/160) . + +**提示:**您也可以在[项目的设置中进行设置](index.html#deployment-strategy) . + +Auto DevOps 的正常行为是使用连续部署,每次在默认分支上运行新管道时,都会自动推送到`production`环境. 但是,在某些情况下,您可能需要使用暂存环境并手动部署到生产环境. 对于这种情况,引入了`STAGING_ENABLED`环境变量. + +如果您定义`STAGING_ENABLED` ,例如将`STAGING_ENABLED`设置为`1`作为 CI / CD 变量,则 GitLab 会自动将应用程序部署到`staging`环境,并在准备好手动部署到生产环境时为您创建`production_manual`作业. + +### Deploy policy for canary environments[](#deploy-policy-for-canary-environments-premium "Permalink") + +在 GitLab 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab-ci-yml/-/merge_requests/171) . + +在将任何更改部署到生产之前,可以使用[Canary 环境](../../user/project/canary_deployments.html) . + +如果您在项目中定义`CANARY_ENABLED` ,例如将`CANARY_ENABLED`设置为`1`作为 CI / CD 变量,则会创建两个手动作业: + +* `canary` -将应用程序部署到金丝雀环境. +* `production_manual`手动将应用程序部署到生产环境. + +### Incremental rollout to production[](#incremental-rollout-to-production-premium "Permalink") + +在 GitLab 10.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/5415) . + +**提示:**您也可以在[项目的设置中进行设置](index.html#deployment-strategy) . + +当您准备将新版本的应用程序部署到生产环境时,您可能希望使用增量部署将最新的代码替换为少数 Pod,以检查应用程序的行为,然后手动将部署率提高到 100% . + +如果在项目中将`INCREMENTAL_ROLLOUT_MODE`设置为`manual` ,则将创建 4 个不同的[手动](../../ci/pipelines/index.html#add-manual-interaction-to-your-pipeline)作业,而不是标准`production`作业: + +1. `rollout 10%` +2. `rollout 25%` +3. `rollout 50%` +4. `rollout 100%` + +该百分比基于`REPLICAS`变量,并定义了您要用于部署的 Pod 数量. 如果该值为`10` ,并且您运行`10%`部署作业,那么将有`1`新容器+ `9`个旧容器. + +要开始工作,请点击播放图标( )旁边的职位名称. 您不需要从`10%`增加到`100%` ,您可以跳到所需的任何工作. 您也可以在达到`100%`之前通过执行较低百分比的作业来缩小规模. 一旦达到`100%` ,您将无法缩小规模,并且必须通过使用环境页面中的" [回滚"按钮](../../ci/environments/index.html#retrying-and-rolling-back)重新部署旧版本来进行[回滚](../../ci/environments/index.html#retrying-and-rolling-back) . + +在下面,您可以看到如果定义了发布或登台变量,管道的外观. + +没有`INCREMENTAL_ROLLOUT_MODE`和`STAGING_ENABLED` : + +[![Staging and rollout disabled](img/4a3c28657f884da12667bc861ea60e0c.png)](img/rollout_staging_disabled.png) + +没有`INCREMENTAL_ROLLOUT_MODE`和`STAGING_ENABLED` : + +[![Staging enabled](img/c79ebe6e2611f151d42f879eaee753fe.png)](img/staging_enabled.png) + +在将`INCREMENTAL_ROLLOUT_MODE`设置为`manual`且没有`STAGING_ENABLED`情况`STAGING_ENABLED` : + +[![Rollout enabled](img/ceb135d0071e5591ba58f5d2820e8f4b.png)](img/rollout_enabled.png) + +将`INCREMENTAL_ROLLOUT_MODE`设置为`manual` ,并将`STAGING_ENABLED` + +[![Rollout and staging enabled](img/1780684b75826fc70c4f9d6a00cd9984.png)](img/rollout_staging_enabled.png) + +**注意:**在 GitLab 11.4 之前, `INCREMENTAL_ROLLOUT_ENABLED`环境变量的存在启用了此功能. 此配置已弃用,以后将被删除. + +### Timed incremental rollout to production[](#timed-incremental-rollout-to-production-premium "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7545) . + +**提示:**您也可以在[项目的设置中进行设置](index.html#deployment-strategy) . + +此配置基于[向生产的增量部署](#incremental-rollout-to-production-premium) . + +除以下内容外,其他所有行为均相同: + +* 要启用它,请将`INCREMENTAL_ROLLOUT_MODE`变量设置为`timed` . +* Instead of the standard `production` job, the following jobs are created with a 5 minute delay between each: + + 1. `timed rollout 10%` + 2. `timed rollout 25%` + 3. `timed rollout 50%` + 4. `timed rollout 100%` + +## Auto DevOps banner[](#auto-devops-banner "Permalink") + +在未启用自动 DevOps 的情况下,对新项目具有维护者或更高权限的用户将显示以下 Auto DevOps 标语: + +[![Auto DevOps banner](img/5262199c26e59a11bfa467901c29122a.png)](img/autodevops_banner_v12_6.png) + +可以为以下内容禁用横幅: + +* 用户,当他们自己关闭它时. +* 通过显式[禁用 Auto DevOps 的项目](index.html#enablingdisabling-auto-devops) . +* 整个 GitLab 实例: + * 由管理员在 Rails 控制台中运行以下命令: + + ``` + Feature . enable ( :auto_devops_banner_disabled ) + ``` + + * 通过带有管理员访问令牌的 REST API: + + ``` + curl --data "value=true" --header "PRIVATE-TOKEN: <personal_access_token>" https://gitlab.example.com/api/v4/features/auto_devops_banner_disabled + ``` \ No newline at end of file diff --git a/docs/211.md b/docs/211.md new file mode 100644 index 0000000000000000000000000000000000000000..f50e8796dbb60ee4e09dac60d1ff30d8a92aa950 --- /dev/null +++ b/docs/211.md @@ -0,0 +1,442 @@ +# Stages of Auto DevOps + +> 原文:[https://docs.gitlab.com/ee/topics/autodevops/stages.html](https://docs.gitlab.com/ee/topics/autodevops/stages.html) + +* [Auto Build](#auto-build) + * [Auto Build using a Dockerfile](#auto-build-using-a-dockerfile) + * [Auto Build using Heroku buildpacks](#auto-build-using-heroku-buildpacks) + * [Auto Build using Cloud Native Buildpacks (beta)](#auto-build-using-cloud-native-buildpacks-beta) +* [Auto Test](#auto-test) + * [Currently supported languages](#currently-supported-languages) +* [Auto Code Quality](#auto-code-quality-starter) +* [Auto SAST](#auto-sast-ultimate) +* [Auto Secret Detection](#auto-secret-detection-ultimate) +* [Auto Dependency Scanning](#auto-dependency-scanning-ultimate) +* [Auto License Compliance](#auto-license-compliance-ultimate) +* [Auto Container Scanning](#auto-container-scanning-ultimate) +* [Auto Review Apps](#auto-review-apps) +* [Auto DAST](#auto-dast-ultimate) + * [Overriding the DAST target](#overriding-the-dast-target) + * [Disabling Auto DAST](#disabling-auto-dast) +* [Auto Browser Performance Testing](#auto-browser-performance-testing-premium) +* [Auto Load Performance Testing](#auto-load-performance-testing-premium) +* [Auto Deploy](#auto-deploy) + * [GitLab deploy tokens](#gitlab-deploy-tokens) + * [Kubernetes 1.16+](#kubernetes-116) + * [Migrations](#migrations) + * [Workers](#workers) + * [Network Policy](#network-policy) + * [Web Application Firewall (ModSecurity) customization](#web-application-firewall-modsecurity-customization) + * [Running commands in the container](#running-commands-in-the-container) +* [Auto Monitoring](#auto-monitoring) + +# Stages of Auto DevOps[](#stages-of-auto-devops "Permalink") + +以下各节描述了[Auto DevOps](index.html)的阶段. 仔细阅读它们,以了解它们的工作原理. + +## Auto Build[](#auto-build "Permalink") + +自动构建使用现有的`Dockerfile`或 Heroku 构建包创建应用程序的构建. 生成的 Docker 映像被推送到[Container Registry](../../user/packages/container_registry/index.html) ,并用提交 SHA 或标记进行标记. + +### Auto Build using a Dockerfile[](#auto-build-using-a-dockerfile "Permalink") + +如果项目的存储库在其根目录中包含`Dockerfile` ,则"自动构建"将使用`Dockerfile` `docker build`来创建 Docker 映像. + +如果您还使用 Auto Review Apps 和 Auto Deploy,并且选择提供自己的`Dockerfile` ,那么您必须: + +* 将您的应用程序公开到端口`5000` ,因为[默认的 Helm 图表](https://gitlab.com/gitlab-org/charts/auto-deploy-app)假定此端口可用. +* 通过[自定义 Auto Deploy Helm 图表来](customize.html#custom-helm-chart)覆盖默认值. + +### Auto Build using Heroku buildpacks[](#auto-build-using-heroku-buildpacks "Permalink") + +自动构建使用项目的`Dockerfile`如果存在)构建应用程序. 如果不存在`Dockerfile` ,它将使用[Herokuish](https://github.com/gliderlabs/herokuish)和[Heroku buildpacks](https://devcenter.heroku.com/articles/buildpacks)检测应用程序并将其构建到 Docker 映像中. + +每个 buildpack 都需要您项目的存储库包含某些文件,以便 Auto Build 成功构建您的应用程序. 例如,您的应用程序的根目录必须包含与您的应用程序语言相对应的文件: + +* 对于 Python 项目,为`Pipfile`或`requirements.txt`文件. +* 对于 Ruby 项目,请使用`Gemfile`或`Gemfile.lock`文件. + +有关其他语言和框架的要求,请阅读[Heroku buildpacks 文档](https://devcenter.heroku.com/articles/buildpacks#officially-supported-buildpacks) . + +**提示:**如果尽管项目满足 buildpack 要求,但 Auto Build 失败,请设置项目变量`TRACE=true`启用详细日志记录,这可能有助于您进行故障排除. + +### Auto Build using Cloud Native Buildpacks (beta)[](#auto-build-using-cloud-native-buildpacks-beta "Permalink") + +在[GitLab 12.10 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28165)引入. + +自动构建支持通过[`pack`命令](https://github.com/buildpacks/pack)使用[Cloud Native Buildpacks](https://buildpacks.io)构建应用程序. 要使用 Cloud Native Buildpacks,请将 CI 变量`AUTO_DEVOPS_BUILD_IMAGE_CNB_ENABLED`设置为非空值. 默认的构建器是`heroku/buildpacks:18`但是可以使用 CI 变量`AUTO_DEVOPS_BUILD_IMAGE_CNB_BUILDER`选择其他构建器. + +Cloud Native Buildpacks(CNB)是 Heroku buildpack 的演进,最终将取代 Auto DevOps 中基于 Herokuish 的构建. 有关更多信息,请参见此[问题](https://gitlab.com/gitlab-org/gitlab/-/issues/212692) . + +使用 Cloud Native Buildpacks 的构建与使用 Heroku buildpacks 的构建支持相同的选项,但有以下警告: + +* 该构建包必须是 Cloud Native Buildpack. 可以使用 Heroku 的 cnb [`cnb-shim`](https://github.com/heroku/cnb-shim)将 Heroku 构建包转换为 Cloud Native 构建包. +* `BUILDPACK_URL`必须[采用`pack`支持](https://buildpacks.io/docs/app-developer-guide/specific-buildpacks/)的格式. +* `/bin/herokuish`命令不出现在结果图像中,并且不再需要(也不可能)使用`/bin/herokuish procfile exec`作为前缀命令. + +**Note:** Auto Test still uses Herokuish, as test suite detection is not yet part of the Cloud Native Buildpack specification. For more information, see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/212689). + +## Auto Test[](#auto-test "Permalink") + +自动测试通过分析项目以检测语言和框架,使用[Herokuish](https://github.com/gliderlabs/herokuish)和[Heroku](https://devcenter.heroku.com/articles/buildpacks)构建[包](https://github.com/gliderlabs/herokuish)为您的应用程序运行适当的测试. 系统会自动检测到多种语言和框架,但是如果未检测到您的语言,则可以创建[自定义 buildpack](customize.html#custom-buildpacks) . 检查[当前支持的语言](#currently-supported-languages) . + +自动测试使用您的应用程序中已有的测试. 如果没有测试,则由您决定添加它们. + +### Currently supported languages[](#currently-supported-languages "Permalink") + +请注意,并不是所有的 buildpack 都支持自动测试,因为它是一个相对较新的增强功能. Heroku 的所有[官方支持的语言都](https://devcenter.heroku.com/articles/heroku-ci#supported-languages)支持自动测试. Heroku 的 Herokuish buildpack 支持的语言都支持自动测试,但值得注意的是 multi-buildpack 不支持. + +支持的构建包是: + +``` +- heroku-buildpack-multi +- heroku-buildpack-ruby +- heroku-buildpack-nodejs +- heroku-buildpack-clojure +- heroku-buildpack-python +- heroku-buildpack-java +- heroku-buildpack-gradle +- heroku-buildpack-scala +- heroku-buildpack-play +- heroku-buildpack-php +- heroku-buildpack-go +- buildpack-nginx +``` + +如果您的应用程序需要的构建包不在上面的列表中,则可能要使用[自定义的 buildpack](customize.html#custom-buildpacks) . + +## Auto Code Quality[](#auto-code-quality-starter "Permalink") + +自动代码质量使用[代码质量图像](https://gitlab.com/gitlab-org/ci-cd/codequality)对当前代码运行静态分析和其他代码检查. 创建报告后,报告将作为工件上传,您可以稍后下载并签出. 合并请求小部件还显示[源分支和目标分支之间的](../../user/project/merge_requests/code_quality.html)任何[差异](../../user/project/merge_requests/code_quality.html) . + +## Auto SAST[](#auto-sast-ultimate "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.3 中引入. + +Static Application Security Testing (SAST) uses the [SAST Docker image](https://gitlab.com/gitlab-org/security-products/sast) to run static analysis on the current code, and checks for potential security issues. The Auto SAST stage will be skipped on licenses other than [Ultimate](https://about.gitlab.com/pricing/), and requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 or above. + +创建报告后,报告将作为工件上传,您可以稍后下载并签出. 合并请求小部件还显示任何安全警告. + +要了解有关[SAST 工作原理的](../../user/application_security/sast/index.html)更多信息,请参阅文档. + +## Auto Secret Detection[](#auto-secret-detection-ultimate "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1 中引入. + +秘密检测使用[秘密检测 Docker 映像](https://gitlab.com/gitlab-org/security-products/analyzers/secrets)在当前代码上运行秘密检测,并检查泄漏的秘密. 自动秘密检测阶段仅在[Ultimate](https://about.gitlab.com/pricing/)层上运行,并且需要[GitLab Runner](https://docs.gitlab.com/runner/) 11.5 或更高版本. + +创建报告后,报告将作为工件上传,您可以稍后下载和评估. 合并请求小部件还显示任何安全警告. + +要了解更多信息,请参阅[秘密检测](../../user/application_security/secret_detection/index.html) . + +## Auto Dependency Scanning[](#auto-dependency-scanning-ultimate "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.7 中引入. + +Dependency Scanning 使用[Dependency Scanning Docker 映像](https://gitlab.com/gitlab-org/security-products/dependency-scanning)对项目依赖项进行分析,并检查潜在的安全问题. 在非[Ultimate](https://about.gitlab.com/pricing/)许可证上,将跳过"自动依赖项扫描"阶段,并且需要[GitLab Runner](https://docs.gitlab.com/runner/) 11.5 或更高版本. + +创建报告后,报告将作为工件上传,您可以稍后下载并签出. 合并请求小部件显示检测到的所有安全警告, + +要了解有关" [依赖关系扫描"的](../../user/application_security/dependency_scanning/index.html)更多信息,请参阅文档. + +## Auto License Compliance[](#auto-license-compliance-ultimate "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0 中引入. + +许可证合规性使用[许可证合规性 Docker 映像](https://gitlab.com/gitlab-org/security-products/license-management)在项目依赖项中搜索其许可证. 除[Ultimate](https://about.gitlab.com/pricing/)以外的其他许可证将跳过"自动许可证合规性"阶段. + +创建报告后,报告将作为工件上传,您可以稍后下载并签出. 合并请求显示所有检测到的许可证. + +要了解有关[许可证合规性的](../../user/compliance/license_compliance/index.html)更多[信息](../../user/compliance/license_compliance/index.html) ,请参阅文档. + +## Auto Container Scanning[](#auto-container-scanning-ultimate "Permalink") + +在 GitLab 10.4 中引入. + +Vulnerability Static Analysis for containers uses [Clair](https://github.com/quay/clair) to check for potential security issues on Docker images. The Auto Container Scanning stage is skipped on licenses other than [Ultimate](https://about.gitlab.com/pricing/). + +创建报告后,报告将作为工件上传,您可以稍后下载并签出. 合并请求显示所有检测到的安全问题. + +To learn more about [Container Scanning](../../user/application_security/container_scanning/index.html), see the documentation. + +## Auto Review Apps[](#auto-review-apps "Permalink") + +这是一个可选步骤,因为许多项目没有可用的 Kubernetes 集群. 如果不满足[要求](requirements.html) ,则将跳过该作业. + +[Review App](../../ci/review_apps/index.html)是基于分支机构代码的临时应用程序环境,因此开发人员,设计人员,质量检查人员,产品经理和其他审阅者可以在审阅过程中实际查看代码更改并与之交互. 自动审核应用程序为每个分支创建一个审核应用程序. + +Auto Review Apps 仅将您的应用程序部署到 Kubernetes 集群. 如果没有可用的群集,则不会进行部署. + +Review App 具有基于项目 ID,分支或标签名称,唯一编号和 Auto DevOps 基本域(例如`13083-review-project-branch-123456.example.com`的组合的唯一 URL. 合并请求小部件显示指向 Review App 的链接,以便于发现. 当删除分支或标签时,例如在合并合并请求之后,Review App 也将被删除. + +可以使用带有 Helm 的[auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app)图表来部署评论应用,您可以对其进行[自定义](customize.html#custom-helm-chart) . 该应用程序将部署到环境的[Kubernetes 命名空间](../../user/project/clusters/index.html#deployment-variables)中. + +从 GitLab 11.4 开始,使用[本地 Tiller](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22036) . 早期版本的 GitLab 在项目名称空间中安装了一个 Tiller. + +**注意:**您的应用程序*不*应该(直接使用 Kubernetes)以外的操纵舵的. 这可能会导致 Helm 无法检测到更改而造成混乱,随后使用 Auto DevOps 进行的部署可能会撤消您的更改. 同样,如果您更改了某些内容并想通过再次部署来撤消它,Helm 可能不会在一开始就检测到任何更改,因此不会意识到它需要重新应用旧配置. + +## Auto DAST[](#auto-dast-ultimate "Permalink") + +在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4 中引入. + +动态应用程序安全测试(DAST)使用流行的开源工具[OWASP ZAProxy](https://github.com/zaproxy/zaproxy)分析当前代码并检查潜在的安全问题. 除[Ultimate](https://about.gitlab.com/pricing/)以外的其他许可证将跳过 Auto DAST 阶段. + +* 在默认分支上,除非您[覆盖目标分支](#overriding-the-dast-target) ,否则 DAST 会扫描专门为此目的部署的应用程序. DAST 运行后,该应用将被删除. +* 在功能分支上,DAST 扫描[审阅应用程序](#auto-review-apps) . + +DAST 扫描完成后,所有安全警告都会显示在" [安全仪表板"](../../user/application_security/security_dashboard/index.html)和"合并请求"小部件上. + +To learn more about [Dynamic Application Security Testing](../../user/application_security/dast/index.html), see the documentation. + +### Overriding the DAST target[](#overriding-the-dast-target "Permalink") + +要使用自定义目标而不是自动部署的审阅应用程序,请将`DAST_WEBSITE`环境变量设置为 URL 以便 DAST 进行扫描. + +**危险:**如果启用了[DAST Full Scan](../../user/application_security/dast/index.html#full-scan) ,则 GitLab 强烈建议**不要**将`DAST_WEBSITE`设置为任何暂存或生产环境. DAST 全面扫描会主动攻击目标,这可能会破坏您的应用程序并导致数据丢失或损坏. + +### Disabling Auto DAST[](#disabling-auto-dast "Permalink") + +您可以禁用 DAST: + +* 通过将`DAST_DISABLED`环境变量设置为`"true"`在所有分支上. +* 通过将`DAST_DISABLED_FOR_DEFAULT_BRANCH`环境变量设置为`"true"`仅在默认分支上. +* 通过将环境变量`REVIEW_DISABLED`设置为`"true"`仅在要素分支上. 这也会禁用 Review App. + +## Auto Browser Performance Testing[](#auto-browser-performance-testing-premium "Permalink") + +在[GitLab Premium](https://about.gitlab.com/pricing/) 10.4 中引入. + +自动[浏览器性能测试](../../user/project/merge_requests/browser_performance_testing.html)使用[Sitespeed.io 容器](https://hub.docker.com/r/sitespeedio/sitespeed.io/)测量网页的浏览器性能,创建包括每个页面的整体性能得分的 JSON 报告,并将报告作为工件上传. 默认情况下,它将测试"审阅"和"生产"环境的根页面. 如果要测试其他 URL,请将路径添加到根目录中名为`.gitlab-urls.txt`的文件中,每行一个文件. 例如: + +``` +/ +/features +/direction +``` + +[合并请求小部件](../../user/project/merge_requests/browser_performance_testing.html)中还会[显示](../../user/project/merge_requests/browser_performance_testing.html)源分支与目标分支之间的任何浏览器性能差异. + +## Auto Load Performance Testing[](#auto-load-performance-testing-premium "Permalink") + +在[GitLab Premium](https://about.gitlab.com/pricing/) 13.2 中引入. + +自动[负载性能测试](../../user/project/merge_requests/load_performance_testing.html)使用[k6 容器](https://hub.docker.com/r/loadimpact/k6/)测量应用程序的服务器性能,创建包含多个关键结果指标的 JSON 报告,并将报告作为工件上传. + +需要一些初始设置. 需要编写针对您的特定应用的[k6](https://k6.io/)测试. 还需要配置测试,以便它可以通过环境变量获取环境的动态 URL. + +[合并请求小部件](../../user/project/merge_requests/load_performance_testing.html)中还会[显示](../../user/project/merge_requests/load_performance_testing.html)源分支与目标分支之间的任何负载性能测试结果差异. + +## Auto Deploy[](#auto-deploy "Permalink") + +这是一个可选步骤,因为许多项目没有可用的 Kubernetes 集群. 如果不满足[要求](requirements.html) ,则跳过该作业. + +将分支或合并请求合并到项目的默认分支(通常是`master` )后,Auto Deploy 会将应用程序部署到 Kubernetes 集群中的`production`环境中,该环境具有基于项目名称和唯一项目 ID 的命名空间,例如`project-4321` . + +默认情况下,"自动部署"不包括到暂存或 Canary 环境的部署,但是如果要启用这些任务,则" [Auto DevOps"模板](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)包含这些任务的作业定义. + +您可以使用[环境变量](customize.html#environment-variables)来自动缩放 Pod 副本,并将自定义参数应用于 Auto DevOps `helm upgrade`命令. 这是[自定义 Auto Deploy Helm 图表](customize.html#custom-helm-chart)的简便方法. + +Helm 使用[auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app)图表将应用程序部署到环境的[Kubernetes 命名空间](../../user/project/clusters/index.html#deployment-variables)中. + +从 GitLab 11.4 开始,将使用[本地 Tiller](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22036) . 早期版本的 GitLab 在项目名称空间中安装了一个 Tiller. + +**注意:**您的应用程序*不*应该(直接使用 Kubernetes)以外的操纵舵的. 这可能会导致 Helm 无法检测到更改而造成混乱,随后使用 Auto DevOps 进行的部署可能会撤消您的更改. 同样,如果您更改了某些内容并想通过再次部署来撤消它,Helm 可能不会在一开始就检测到任何更改,因此不会意识到它需要重新应用旧配置. + +### GitLab deploy tokens[](#gitlab-deploy-tokens "Permalink") + +在 GitLab 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19507) . + +启用 Auto DevOps 时,将为内部和私有项目创建[GitLab 部署令牌](../../user/project/deploy_tokens/index.html#gitlab-deploy-token) ,并保存 Auto DevOps 设置. 您可以使用部署令牌对注册表进行永久访问. 手动吊销 GitLab 部署令牌后,将不会自动创建它. + +如果找不到 GitLab 部署令牌,则使用`CI_REGISTRY_PASSWORD` . + +**Note:** `CI_REGISTRY_PASSWORD` is only valid during deployment. Kubernetes will be able to successfully pull the container image during deployment, but if the image must be pulled again, such as after pod eviction, Kubernetes will fail to do so as it attempts to fetch the image using `CI_REGISTRY_PASSWORD`. + +### Kubernetes 1.16+[](#kubernetes-116 "Permalink") + +版本历史 + +* 在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/charts/auto-deploy-app/-/merge_requests/51) . +* 在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/merge_requests/49)了对部署支持 Kubernetes 1.16+的 PostgreSQL 版本的支持. +* 自 GitLab 13.0 起为新部署提供开箱即用的支持. + +**弃用:**在[GitLab 13.0 中](https://gitlab.com/gitlab-org/charts/auto-deploy-app/-/issues/47) , `deploymentApiVersion`设置的默认值已从`extensions/v1beta`更改为`apps/v1` . + +在 Kubernetes 1.16 和更高版本中, [删除](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/)了许多[API](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/) ,包括在`extensions/v1beta1`版本中支持`Deployment` . + +要在 Kubernetes 1.16+群集上使用 Auto Deploy: + +1. 如果您是第一次在 GitLab 13.0 或更高版本上部署应用程序,则无需进行配置. + +2. 在 GitLab 12.10 或更旧版本上,在[`.gitlab/auto-deploy-values.yaml`文件中](customize.html#customize-values-for-helm-chart)设置以下内容: + + ``` + deploymentApiVersion: apps/v1 + ``` + +3. 如果您安装了集群内 PostgreSQL 数据库,并且`AUTO_DEVOPS_POSTGRES_CHANNEL`设置为`1` ,请按照[指南升级 PostgreSQL](upgrading_postgresql.html) . + +4. 如果您是第一次部署应用程序,并且使用的是 GitLab 12.9 或 12.10,请将`AUTO_DEVOPS_POSTGRES_CHANNEL`设置为`2` . + +**危险:**在 GitLab 12.9 和 12.10 上,选择使用`AUTO_DEVOPS_POSTGRES_CHANNEL`版本`2`会删除版本`1` PostgreSQL 数据库. 在选择版本`2`之前,请遵循[升级 PostgreSQL](upgrading_postgresql.html)的[指南来](upgrading_postgresql.html)备份和还原数据库(在 GitLab 13.0 上,需要附加变量来触发数据库删除). + +### Migrations[](#migrations "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21955) + +您可以通过分别设置项目变量`DB_INITIALIZE`和`DB_MIGRATE`来配置 PostgreSQL 的数据库初始化和迁移,以使其在应用程序窗格中运行. + +如果存在, `DB_INITIALIZE`作为 Shell 命令作为 Helm 安装后挂钩在外壳中运行. 由于某些应用程序如果没有成功的数据库初始化步骤就无法运行,因此 GitLab 部署的第一个发行版没有应用程序部署,而只有数据库初始化步骤. 数据库初始化完成后,GitLab 部署第二个版本,并且应用程序部署正常. + +请注意,安装后挂钩意味着如果任何部署成功,则`DB_INITIALIZE`将不再处理`DB_INITIALIZE` . + +如果存在, `DB_MIGRATE`作为 Shell 命令作为 Helm 预升级挂钩在 Shell 中运行. + +例如,在用[Herokuish](https://github.com/gliderlabs/herokuish)构建的图像中的 Rails 应用程序中: + +* 可以将`DB_INITIALIZE`设置为`RAILS_ENV=production /bin/herokuish procfile exec bin/rails db:setup` +* 可以将`DB_MIGRATE`设置为`RAILS_ENV=production /bin/herokuish procfile exec bin/rails db:migrate` + +除非您的存储库包含`Dockerfile` ,否则映像是使用 Herokuish 构建的,并且必须在这些映像中运行的命令前加上`/bin/herokuish procfile exec`前缀,以复制将在其中运行应用程序的环境. + +### Workers[](#workers "Permalink") + +某些 Web 应用程序必须为"工作流程"运行额外的部署. 例如,Rails 应用程序通常使用单独的工作进程来运行后台任务,例如发送电子邮件. + +Auto Deploy 中使用的[默认 Helm 图表](https://gitlab.com/gitlab-org/charts/auto-deploy-app) [支持运行工作进程](https://gitlab.com/gitlab-org/charts/auto-deploy-app/-/merge_requests/9) . + +要运行工作程序,必须确保工作程序可以响应标准的运行状况检查,该检查将在端口`5000`上期望成功的 HTTP 响应. 对于[Sidekiq](https://github.com/mperham/sidekiq) ,可以使用[`sidekiq_alive` gem](https://rubygems.org/gems/sidekiq_alive) . + +要使用 Sidekiq,还必须确保您的部署可以访问 Redis 实例. Auto DevOps 不会为您部署此实例,因此您必须: + +* 维护您自己的 Redis 实例. +* 设置 CI 变量`K8S_SECRET_REDIS_URL` ,它是该实例的 URL,以确保将其传递到您的部署中. + +在将工作程序配置为对运行状况检查作出响应之后,为您的 Rails 应用程序运行 Sidekiq 工作程序. 您可以通过在[`.gitlab/auto-deploy-values.yaml`文件中](customize.html#customize-values-for-helm-chart)设置以下内容来启用工作[`.gitlab/auto-deploy-values.yaml`](customize.html#customize-values-for-helm-chart) : + +``` +workers: + sidekiq: + replicaCount: 1 + command: + - /bin/herokuish + - procfile + - exec + - sidekiq + preStopCommand: + - /bin/herokuish + - procfile + - exec + - sidekiqctl + - quiet + terminationGracePeriodSeconds: 60 +``` + +### Network Policy[](#network-policy "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/charts/auto-deploy-app/-/merge_requests/30) . + +默认情况下,所有 Kubernetes 容器都是[非隔离的](https://kubernetes.io/docs/concepts/services-networking/network-policies/#isolated-and-non-isolated-pods) ,并且接受来自任何来源的流量. 您可以使用[NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/)限制与选定 Pod,名称空间和 Internet 之间的连接. + +**注意:**您必须使用 Kubernetes 网络插件来实现对`NetworkPolicy`支持. Kubernetes( `kubenet` )的默认网络插件[未实现](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/#kubenet) `kubenet`支持. 可以将[Cilium](https://cilium.io/)网络插件安装为[群集应用程序,](../../user/clusters/applications.html#install-cilium-using-gitlab-cicd)以支持网络策略. + +您可以通过在`.gitlab/auto-deploy-values.yaml`文件中设置以下内容来启用网络策略`.gitlab/auto-deploy-values.yaml` : + +``` +networkPolicy: + enabled: true +``` + +Auto Deploy 管道部署的默认策略允许本地名称空间内以及`gitlab-managed-apps`名称空间的`gitlab-managed-apps` . 所有其他入站连接均被阻止. 出站流量(例如,到 Internet 的流量)不受默认策略的影响. + +您还可以在`.gitlab/auto-deploy-values.yaml`文件中提供自定义[策略规范](https://kubernetes.io/docs/concepts/services-networking/network-policies/) ,例如: + +``` +networkPolicy: + enabled: true + spec: + podSelector: + matchLabels: + app.gitlab.com/env: staging + ingress: + - from: + - podSelector: + matchLabels: {} + - namespaceSelector: + matchLabels: + app.gitlab.com/managed_by: gitlab +``` + +有关安装网络策略的更多信息,请参阅[使用 GitLab CI / CD 安装 Cilium](../../user/clusters/applications.html#install-cilium-using-gitlab-cicd) . + +### Web Application Firewall (ModSecurity) customization[](#web-application-firewall-modsecurity-customization "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/charts/auto-deploy-app/-/merge_requests/44) . + +[安装](../../user/clusters/applications.html#web-application-firewall-modsecurity)了[ModSecurity 的](../../user/clusters/applications.html#web-application-firewall-modsecurity)群集可以在[Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)或部署基础上进行自定义. + +要在 Auto Deploy 中启用 ModSecurity,必须在项目中使用以下属性创建`.gitlab/auto-deploy-values.yaml`文件. + +| Attribute | Description | Default | +| --- | --- | --- | +| `enabled` | 启用 ModSecurity 的自定义配置,默认为" [核心规则集"](https://coreruleset.org/) | `false` | +| `secRuleEngine` | 配置[规则引擎](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#secruleengine) | `DetectionOnly` | +| `secRules` | 创建一个或多个其他[规则](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#SecRule) | `nil` | + +在以下`auto-deploy-values.yaml`示例中,为 ModSecurity 启用了一些自定义设置. 其中包括将其引擎设置为处理规则,而不是仅记录规则,同时添加两个基于标头的特定规则: + +``` +ingress: + modSecurity: + enabled: true + secRuleEngine: "On" + secRules: + - variable: "REQUEST_HEADERS:User-Agent" + operator: "printer" + action: "log,deny,id:'2010',status:403,msg:'printer is an invalid agent'" + - variable: "REQUEST_HEADERS:Content-Type" + operator: "text/plain" + action: "log,deny,id:'2011',status:403,msg:'Text is not supported as content type'" +``` + +### Running commands in the container[](#running-commands-in-the-container "Permalink") + +除非您的存储库包含[自定义 Dockerfile](#auto-build-using-a-dockerfile) ,否则默认情况下使用 Herokuish 使用[Auto Build 构建的](#auto-build)应用程序可能要求将命令包装如下: + +``` +/bin/herokuish procfile exec $COMMAND +``` + +您可能需要包装命令的一些原因: + +* 使用`kubectl exec`附加. +* 使用 GitLab 的[Web 终端](../../ci/environments/index.html#web-terminals) . + +例如,要从应用程序根目录启动 Rails 控制台,请运行: + +``` +/bin/herokuish procfile exec bin/rails c +``` + +## Auto Monitoring[](#auto-monitoring "Permalink") + +部署应用程序后,"自动监视"可帮助您立即监视应用程序的服务器和响应指标. 自动监控使用[Prometheus](../../user/project/integrations/prometheus.html)直接从[Kubernetes](../../user/project/integrations/prometheus_library/kubernetes.html)检索系统指标,例如 CPU 和内存使用情况,以及从[NGINX 服务器](../../user/project/integrations/prometheus_library/nginx_ingress.html)检索响应指标,例如 HTTP 错误率,延迟和吞吐量. + +指标包括: + +* **响应指标:**延迟,吞吐量,错误率 +* **系统指标:** CPU 利用率,内存利用率 + +安装 Prometheus 之后,GitLab 会为您提供一些初始警报: + +* 入口状态码`500` > 0.1% +* NGINX 状态码`500` > 0.1% + +要使用自动监视: + +1. [Install and configure the Auto DevOps requirements](requirements.html). +2. 如果尚未[启用 Auto DevOps](index.html#enablingdisabling-auto-devops) ,请[启用它](index.html#enablingdisabling-auto-devops) . +3. 导航到您项目的 **CI / CD>管道** ,然后单击**运行管道** . +4. 管道成功完成后,打开已[部署环境](../../ci/environments/index.html#monitoring-environments)的[监视仪表板](../../ci/environments/index.html#monitoring-environments)以查看已部署应用程序的指标. 要查看整个 Kubernetes 集群的指标,请导航至 **操作>指标** . + +[![Auto Metrics](img/96aa3b50d60a091349e8d39c74877a5d.png)](img/auto_monitoring.png) \ No newline at end of file diff --git a/docs/212.md b/docs/212.md new file mode 100644 index 0000000000000000000000000000000000000000..ba474c1b9b9bffbda9cfc82ebf20db71516cd56f --- /dev/null +++ b/docs/212.md @@ -0,0 +1,207 @@ +# Upgrading PostgreSQL for Auto DevOps + +> 原文:[https://docs.gitlab.com/ee/topics/autodevops/upgrading_postgresql.html](https://docs.gitlab.com/ee/topics/autodevops/upgrading_postgresql.html) + +* [Prerequisites](#prerequisites) +* [Take your application offline](#take-your-application-offline) +* [Backup](#backup) +* [Retain persistent volumes](#retain-persistent-volumes) +* [Install new PostgreSQL](#install-new-postgresql) +* [Restore](#restore) +* [Reinstate your application](#reinstate-your-application) + +# Upgrading PostgreSQL for Auto DevOps[](#upgrading-postgresql-for-auto-devops "Permalink") + +Auto DevOps 为您的应用程序提供[集群内 PostgreSQL 数据库](customize.html#postgresql-database-support) . + +用于配置 PostgreSQL 的图表的版本: + +* 在 GitLab 12.8 及更早版本中为 0.7.1. +* 在 GitLab 12.9 及更高版本中可以设置为 0.7.1 至 8.2.1. + +GitLab 鼓励用户将其数据库迁移到较新的 PostgreSQL 图表. + +本指南提供有关如何迁移 PostgreSQL 数据库的说明,其中包括: + +1. 对数据进行数据库转储. +2. 使用图表的较新版本 8.2.1 安装新的 PostgreSQL 数据库,并删除旧的 PostgreSQL 安装. +3. 将数据库转储还原到新的 PostgreSQL 中. + +## Prerequisites[](#prerequisites "Permalink") + +1. Install [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/). +2. 确保您可以使用`kubectl`访问 Kubernetes 集群. 这取决于 Kubernetes 提供者. +3. 准备停机. 下面的步骤包括使应用程序脱机,以便在创建数据库转储后不修改集群内数据库. +4. 确保尚未将`POSTGRES_ENABLED`设置为`false` ,因为此设置将删除任何现有的通道 1 数据库. 有关更多信息,请参见[检测到现有的 PostgreSQL 数据库](index.html#detected-an-existing-postgresql-database) . + +**提示:**如果已将 Auto DevOps 配置为具有暂存,请考虑先尝试暂存并还原备份和还原步骤,或者在审阅应用程序中尝试此步骤. + +## Take your application offline[](#take-your-application-offline "Permalink") + +如果需要,请使应用程序脱机,以防止在创建数据库转储后修改数据库. + +1. 获取环境的 Kubernetes 命名空间. 它通常看起来像`<project-name>-<project-id>-<environment>` . 在我们的示例中,名称空间称为`minimal-ruby-app-4349298-production` . + + ``` + $ kubectl get ns + + NAME STATUS AGE + minimal-ruby-app-4349298-production Active 7d14h + ``` + +2. 为了易于使用,请导出名称空间名称: + + ``` + export APP_NAMESPACE=minimal-ruby-app-4349298-production + ``` + +3. 使用以下命令获取应用程序的部署名称. 在我们的示例中,部署名称为`production` . + + ``` + $ kubectl get deployment --namespace "$APP_NAMESPACE" + NAME READY UP-TO-DATE AVAILABLE AGE + production 2/2 2 2 7d21h + production-postgres 1/1 1 1 7d21h + ``` + +4. 为了防止数据库被修改,请使用以下命令将副本的副本数设置为 0\. 我们使用上一步中的部署名称( `deployments/<DEPLOYMENT_NAME>` ). + + ``` + $ kubectl scale --replicas=0 deployments/production --namespace "$APP_NAMESPACE" + deployment.extensions/production scaled + ``` + +5. 如果有的话,还需要将 worker 的副本设置为零. + +## Backup[](#backup "Permalink") + +1. 获取 PostgreSQL 的服务名称. 服务的名称应以`-postgres` . 在我们的示例中,服务名称为`production-postgres` . + + ``` + $ kubectl get svc --namespace "$APP_NAMESPACE" + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + production-auto-deploy ClusterIP 10.30.13.90 <none> 5000/TCP 7d14h + production-postgres ClusterIP 10.30.4.57 <none> 5432/TCP 7d14h + ``` + +2. 使用以下命令获取 PostgreSQL 的 pod 名称. 在我们的示例中,吊舱名称为`production-postgres-5db86568d7-qxlxv` . + + ``` + $ kubectl get pod --namespace "$APP_NAMESPACE" -l app=production-postgres + NAME READY STATUS RESTARTS AGE + production-postgres-5db86568d7-qxlxv 1/1 Running 0 7d14h + ``` + +3. 通过以下方式连接到吊舱: + + ``` + kubectl exec -it production-postgres-5db86568d7-qxlxv --namespace "$APP_NAMESPACE" bash + ``` + +4. 连接后,使用以下命令创建转储文件. + + * `SERVICE_NAME`是在上一步中获得的服务名称. + * `USERNAME`是您为 PostgreSQL 配置的用户名. 默认值为`user` . + * `DATABASE_NAME`通常是环境名称. + + * 系统将要求您输入数据库密码,默认`testing-password`是`testing-password` . + + ``` + ## Format is: + # pg_dump -h SERVICE_NAME -U USERNAME DATABASE_NAME > /tmp/backup.sql + + pg_dump -h production-postgres -U user production > /tmp/backup.sql + ``` + +5. 备份转储完成后,使用`Control-D` `exit` Kubernetes exec 进程或`exit` . + +6. 使用以下命令下载转储文件: + + ``` + kubectl cp --namespace "$APP_NAMESPACE" production-postgres-5db86568d7-qxlxv:/tmp/backup.sql backup.sql + ``` + +## Retain persistent volumes[](#retain-persistent-volumes "Permalink") + +默认情况下,当`Delete`使用该卷的 Pod 和 Pod 声明时,用于存储 PostgreSQL 基础数据的[持久卷](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)将标记为`Delete` . + +这很重要,因为当您选择使用较新的 8.2.1 PostgreSQL 时,会删除较旧的 0.7.1 PostgreSQL,从而导致永久卷也被删除. + +您可以使用以下命令进行验证: + +``` +$ kubectl get pv +NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE +pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 8Gi RWO Delete Bound minimal-ruby-app-4349298-staging/staging-postgres standard 7d22h +pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096 8Gi RWO Delete Bound minimal-ruby-app-4349298-production/production-postgres standard 7d22h +``` + +为了保留持久卷,即使删除了较旧的 0.7.1 PostgreSQL,我们也可以将保留策略更改为`Retain` . 在此示例中,我们通过查看声明名称来找到持久卷名称. 由于我们有兴趣保留用于`minimal-ruby-app-4349298`应用程序的阶段和生产的卷,因此此处的卷名称为`pvc-0da80c08-5239-11ea-9c8d-42010a8e0096`和`pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096` : + +``` +$ kubectl patch pv pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' +persistentvolume/pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 patched +$ kubectl patch pv pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096 -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' +persistentvolume/pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096 patched +$ kubectl get pv +NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE +pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 8Gi RWO Retain Bound minimal-ruby-app-4349298-staging/staging-postgres standard 7d22h +pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096 8Gi RWO Retain Bound minimal-ruby-app-4349298-production/production-postgres standard 7d22h +``` + +## Install new PostgreSQL[](#install-new-postgresql "Permalink") + +**注意:**使用较新版本的 PostgreSQL 将删除较旧的 0.7.1 PostgreSQL. 为了防止基础数据被删除,您可以选择保留[持久卷](#retain-persistent-volumes) .**提示:**您还可以将`AUTO_DEVOPS_POSTGRES_CHANNEL` , `AUTO_DEVOPS_POSTGRES_DELETE_V1`和`POSTGRES_VERSION`变量的[作用域](../../ci/environments/index.html#scoping-environments-with-specs)设置为特定环境,例如`staging` . + +1. 将`AUTO_DEVOPS_POSTGRES_CHANNEL`设置为`2` . 选择使用较新的基于 8.2.1 的 PostgreSQL,并删除较旧的基于 0.7.1 的 PostgreSQL. +2. 将`AUTO_DEVOPS_POSTGRES_DELETE_V1`设置为非空值. 此标志是防止意外删除数据库的保护措施. +3. 将`POSTGRES_VERSION`设置为`11.7` . 这是支持的最低 PostgreSQL 版本. +4. 将`PRODUCTION_REPLICAS`设置为`0` . 对于其他环境, `REPLICAS`在[环境范围内](../../ci/environments/index.html#scoping-environments-with-specs)使用`REPLICAS` . +5. 如果已设置`DB_INITIALIZE`或`DB_MIGRATE`变量,请删除变量,或将变量临时重命名为`XDB_INITIALIZE`或`XDB_MIGRATE`以有效地禁用它们. +6. Run a new CI pipeline for the branch. In this case, we run a new CI pipeline for `master`. +7. 一旦管道成功,您的应用程序现在将安装新的 PostgreSQL 进行升级. 复制品也将为零,这意味着将不为您的应用程序提供任何流量(以防止新数据进入). + +## Restore[](#restore "Permalink") + +1. 获取新 PostgreSQL 的容器名称,在我们的示例中,容器名称为`production-postgresql-0` : + + ``` + $ kubectl get pod --namespace "$APP_NAMESPACE" -l app=postgresql + NAME READY STATUS RESTARTS AGE + production-postgresql-0 1/1 Running 0 19m + ``` + +2. 将转储文件从备份步骤复制到 Pod: + + ``` + kubectl cp --namespace "$APP_NAMESPACE" backup.sql production-postgresql-0:/tmp/backup.sql + ``` + +3. 连接到吊舱: + + ``` + kubectl exec -it production-postgresql-0 --namespace "$APP_NAMESPACE" bash + ``` + +4. 连接到 Pod 后,运行以下命令来还原数据库. + + * 系统将要求您输入数据库密码,默认`testing-password`是`testing-password` . + * `USERNAME`是您为 PostgreSQL 配置的用户名. 默认值为`user` . + * `DATABASE_NAME`通常是环境名称. + + ``` + ## Format is: + # psql -U USERNAME -d DATABASE_NAME < /tmp/backup.sql + + psql -U user -d production < /tmp/backup.sql + ``` + +5. 现在,您可以检查还原完成后是否已正确还原数据. 您可以使用`psql`对数据进行抽查. + +## Reinstate your application[](#reinstate-your-application "Permalink") + +对数据库已还原感到满意后,请运行以下步骤来恢复您的应用程序: + +1. 如果先前已删除或禁用了`DB_INITIALIZE`和`DB_MIGRATE`变量,则将其还原. +2. 将`PRODUCTION_REPLICAS`或`REPLICAS`变量恢复为其原始值. +3. 为分支运行新的 CI 管道. 在这种情况下,我们为`master`运行新的 CI 管道. 管道成功后,您的应用程序应该像以前一样提供流量. \ No newline at end of file diff --git a/docs/213.md b/docs/213.md new file mode 100644 index 0000000000000000000000000000000000000000..e63a1b68af65fe7ac8588b3955c531c4d72eef7d --- /dev/null +++ b/docs/213.md @@ -0,0 +1,477 @@ +# Cache dependencies in GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/caching/](https://docs.gitlab.com/ee/ci/caching/) + +* [Cache vs artifacts](#cache-vs-artifacts) +* [Good caching practices](#good-caching-practices) + * [Sharing caches across the same branch](#sharing-caches-across-the-same-branch) + * [Sharing caches across different branches](#sharing-caches-across-different-branches) + * [Disabling cache on specific jobs](#disabling-cache-on-specific-jobs) + * [Inherit global config, but override specific settings per job](#inherit-global-config-but-override-specific-settings-per-job) +* [Common use cases](#common-use-cases) + * [Caching Node.js dependencies](#caching-nodejs-dependencies) + * [Caching PHP dependencies](#caching-php-dependencies) + * [Caching Python dependencies](#caching-python-dependencies) + * [Caching Ruby dependencies](#caching-ruby-dependencies) + * [Caching Go dependencies](#caching-go-dependencies) +* [Availability of the cache](#availability-of-the-cache) + * [Where the caches are stored](#where-the-caches-are-stored) + * [How archiving and extracting works](#how-archiving-and-extracting-works) + * [Cache mismatch](#cache-mismatch) + * [Examples](#examples) +* [Clearing the cache](#clearing-the-cache) + * [Clearing the cache by changing `cache:key`](#clearing-the-cache-by-changing-cachekey) + * [Clearing the cache manually](#clearing-the-cache-manually) + +# Cache dependencies in GitLab CI/CD[](#cache-dependencies-in-gitlab-cicd "Permalink") + +GitLab CI / CD 提供了一种缓存机制,可用于在作业运行时节省时间. + +缓存是指通过重用先前作业的相同内容来加快执行作业的时间. 当您开发依赖于在构建期间通过 Internet 获取的其他库的软件时,此功能特别有用. + +如果启用了缓存,则默认情况下从 GitLab 9.0 开始,它在项目级别的管道和作业之间共享. 缓存不跨项目共享. + +确保您阅读了[`cache`参考](../yaml/README.html#cache)以了解`.gitlab-ci.yml`定义. + +## Cache vs artifacts[](#cache-vs-artifacts "Permalink") + +**注意:**如果您使用缓存和工件在作业中存储相同的路径时要小心,因为在覆盖**工件**和内容**之前** ,将**还原缓存** . + +不要使用缓存在阶段之间传递工件,因为缓存旨在存储编译项目所需的运行时依赖项: + +* `cache`: **用于存储项目依赖项** + + 缓存用于通过存储下载的依赖项来加快后续作业在给定**管道中的**运行速度,这样就不必再次从 Internet 上获取它们(例如 npm 软件包,Go 供应商软件包等).配置为在阶段之间传递中间构建结果,则应该使用工件来完成. + +* `artifacts`: **用于在阶段之间传递的阶段结果.** + + 工件是由作业生成的文件,可以存储并上载,然后可以在**同一管道的**后续阶段中由作业获取和使用. 换句话说, [您不能在阶段 1 的 job-A 中创建工件,然后在阶段 1 的 job-B 中使用此工件](https://gitlab.com/gitlab-org/gitlab/-/issues/25837) . 此数据在不同的管道中将不可用,但可以从 UI 下载. + +`artifacts`的名称听起来像是仅在工作之外有用,例如用于下载最终图像,但是人工制品也可以在管道的后期阶段使用. 因此,如果通过下载所有必需的模块来构建应用程序,则可能需要将它们声明为工件,以便后续阶段可以使用它们. 有一些优化措施,例如声明[到期时间,](../yaml/README.html#artifactsexpire_in)这样您就不会将工件保留太长时间,或者使用[依赖项](../yaml/README.html#dependencies)来控制哪些作业会获取工件. + +Caches: + +* 如果未全局定义或未按作业定义(使用`cache:` :),则禁用该功能. +* 如果全局启用,则可用于`.gitlab-ci.yml`所有作业. +* 可以由创建缓存的同一作业在后续管道中使用(如果未全局定义). +* 如果[启用了分布式缓存](https://docs.gitlab.com/runner/configuration/autoscale.html) ,则将它们存储在 Runner 安装的位置**并**上传到 S3. +* 如果按作业定义,则使用: + * 通过后续管道中的相同作业. + * 如果它们具有相同的依赖关系,则由同一管道中的后续作业组成. + +Artifacts: + +* 如果未按作业定义(使用`artifacts:` :),则将其禁用. +* 只能针对每个作业启用,不能全局启用. +* 在管道中创建,并且可以被当前活动管道的后续作业使用. +* 始终上传到 GitLab(称为协调器). +* 可以具有用于控制磁盘使用量的到期值(默认为 30 天). + +**注意:**工件和缓存均定义了相对于项目目录的路径,并且无法链接到其外部的文件. + +## Good caching practices[](#good-caching-practices "Permalink") + +We have the cache from the perspective of the developers (who consume a cache within the job) and the cache from the perspective of the Runner. Depending on which type of Runner you are using, cache can act differently. + +从开发人员的角度来看,要确保高速缓存的最大可用性,在作业中声明`cache` ,请使用以下一项或多项: + +* [为跑步者](../runners/README.html#use-tags-to-limit-the-number-of-jobs-using-the-runner)添加标签,并在共享其缓存的作业上使用标签. +* [使用](../runners/README.html#prevent-a-specific-runner-from-being-enabled-for-other-projects)仅适用于特定项目的[粘性运行器](../runners/README.html#prevent-a-specific-runner-from-being-enabled-for-other-projects) . +* [使用](../yaml/README.html#cachekey)适合您的工作流[的`key`](../yaml/README.html#cachekey) (例如,每个分支上的不同缓存). 为此,您可以利用[CI / CD 预定义变量](../variables/README.html#predefined-environment-variables) . + +**提示:**在管道中使用相同的 Runner 是在一个阶段或管道中缓存文件,并以有保证的方式将该缓存传递到后续阶段或管道的最简单,最有效的方法. + +从 Runner 的角度来看,为了使缓存有效运行,必须满足以下条件之一: + +* 为您的所有工作使用一个赛跑者. +* 使用多个使用[分布式缓存的](https://docs.gitlab.com/runner/configuration/autoscale.html) Runner(无论是否处于自动缩放模式),这些[缓存](https://docs.gitlab.com/runner/configuration/autoscale.html)将缓存存储在 S3 存储桶中(例如 GitLab.com 上的共享 Runner). +* 使用具有相同体系结构的多个运行程序(不在自动伸缩模式下)共享公共网络安装目录(使用 NFS 或类似方式),以存储缓存. + +**提示:**了解[缓存](#availability-of-the-cache)的[可用性,](#availability-of-the-cache)以了解有关内部的更多信息,并更好地了解缓存的工作方式. + +### Sharing caches across the same branch[](#sharing-caches-across-the-same-branch "Permalink") + +使用`key: ${CI_COMMIT_REF_SLUG}`定义一个缓存,以便每个分支的作业始终使用相同的缓存: + +``` +cache: + key: ${CI_COMMIT_REF_SLUG} +``` + +尽管这似乎可以防止意外覆盖缓存,但是这意味着合并请求的第一个流水线很慢,这可能会给开发人员带来糟糕的体验. 下次将新提交推送到分支时,将重新使用缓存. + +To enable per-job and per-branch caching: + +``` +cache: + key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG" +``` + +要启用每个分支和每个阶段的缓存: + +``` +cache: + key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG" +``` + +### Sharing caches across different branches[](#sharing-caches-across-different-branches "Permalink") + +如果要缓存的文件需要在所有分支和所有作业之间共享,则可以对所有这些文件使用相同的密钥: + +``` +cache: + key: one-key-to-rule-them-all +``` + +要在分支之间共享相同的缓存,但按作业将它们分开: + +``` +cache: + key: ${CI_JOB_NAME} +``` + +### Disabling cache on specific jobs[](#disabling-cache-on-specific-jobs "Permalink") + +如果已全局定义了缓存,则意味着每个作业将使用相同的定义. 您可以按工作覆盖此行为,如果要完全禁用它,请使用空哈希: + +``` +job: + cache: {} +``` + +### Inherit global config, but override specific settings per job[](#inherit-global-config-but-override-specific-settings-per-job "Permalink") + +您可以使用[定位符](../yaml/README.html#anchors)覆盖缓存设置,而无需覆盖全局缓存. 例如,如果要覆盖一项作业的`policy` : + +``` +cache: &global_cache + key: ${CI_COMMIT_REF_SLUG} + paths: + - node_modules/ + - public/ + - vendor/ + policy: pull-push + +job: + cache: + # inherit all global cache settings + <<: *global_cache + # override the policy + policy: pull +``` + +要进行更精细的调整,还请阅读有关[`cache: policy`](../yaml/README.html#cachepolicy) . + +## Common use cases[](#common-use-cases "Permalink") + +缓存最常见的用例是在后续作业之间保留内容,以用于诸如依赖项和常用库(Node.js 包,PHP 包,rubygems,Python 库等)之类的东西,因此不必从公共互联网重新获取. + +**注意:**有关更多示例,请查看我们的[GitLab CI / CD 模板](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates) . + +### Caching Node.js dependencies[](#caching-nodejs-dependencies "Permalink") + +假设您的项目正在使用[npm](https://s0www0npmjs0com.icopy.site/)安装 Node.js 依赖项,下面的示例将全局定义`cache` ,以便所有作业都继承它. 默认情况下,npm 将缓存数据存储在主文件夹`~/.npm`但是由于[您无法缓存项目目录之外的内容](../yaml/README.html#cachepaths) ,因此我们告诉 npm 使用`./.npm` ,它按分支缓存: + +``` +# +# https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml +# +image: node:latest + +# Cache modules in between jobs +cache: + key: ${CI_COMMIT_REF_SLUG} + paths: + - .npm/ + +before_script: + - npm ci --cache .npm --prefer-offline + +test_async: + script: + - node ./specs/start.js ./specs/async.spec.js +``` + +### Caching PHP dependencies[](#caching-php-dependencies "Permalink") + +假设您的项目正在使用[Composer](https://s0getcomposer0org.icopy.site/)安装 PHP 依赖项,下面的示例将全局定义`cache` ,以便所有作业都继承它. PHP 库模块安装在`vendor/`并按分支缓存: + +``` +# +# https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates/PHP.gitlab-ci.yml +# +image: php:7.2 + +# Cache libraries in between jobs +cache: + key: ${CI_COMMIT_REF_SLUG} + paths: + - vendor/ + +before_script: + # Install and run Composer + - curl --show-error --silent https://getcomposer.org/installer | php + - php composer.phar install + +test: + script: + - vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never +``` + +### Caching Python dependencies[](#caching-python-dependencies "Permalink") + +假设您的项目正在使用[pip](https://pip.pypa.io/en/stable/)安装 Python 依赖项,以下示例将全局定义`cache` ,以便所有作业都继承它. Python 库安装在`venv/`下的虚拟环境中,pip 的缓存在`.cache/pip/`下定义,并且两者均按分支缓存: + +``` +# +# https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates/Python.gitlab-ci.yml +# +image: python:latest + +# Change pip's cache directory to be inside the project directory since we can +# only cache local items. +variables: + PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" + +# Pip's cache doesn't store the python packages +# https://pip.pypa.io/en/stable/reference/pip_install/#caching +# +# If you want to also cache the installed packages, you have to install +# them in a virtualenv and cache it as well. +cache: + paths: + - .cache/pip + - venv/ + +before_script: + - python -V # Print out python version for debugging + - pip install virtualenv + - virtualenv venv + - source venv/bin/activate + +test: + script: + - python setup.py test + - pip install flake8 + - flake8 . +``` + +### Caching Ruby dependencies[](#caching-ruby-dependencies "Permalink") + +假设您的项目正在使用[Bundler](https://bundler.io)安装 gem 依赖项,以下示例将全局定义`cache` ,以便所有作业都继承它. 宝石安装在`vendor/ruby/`并按分支缓存: + +``` +# +# https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml +# +image: ruby:2.6 + +# Cache gems in between builds +cache: + key: ${CI_COMMIT_REF_SLUG} + paths: + - vendor/ruby + +before_script: + - ruby -v # Print out ruby version for debugging + - bundle install -j $(nproc) --path vendor/ruby # Install dependencies into ./vendor/ruby + +rspec: + script: + - rspec spec +``` + +### Caching Go dependencies[](#caching-go-dependencies "Permalink") + +假设您的项目正在使用[Go Modules](https://github.com/golang/go/wiki/Modules)安装 Go 依赖项,以下示例在`go-cache`模板中定义了`cache` ,任何作业都可以扩展. Go 模块安装在`${GOPATH}/pkg/mod/` ,并为所有`go`项目缓存: + +``` +.go-cache: + variables: + GOPATH: $CI_PROJECT_DIR/.go + before_script: + - mkdir -p .go + cache: + paths: + - .go/pkg/mod/ + +test: + image: golang:1.13 + extends: .go-cache + script: + - go test ./... -v -short +``` + +## Availability of the cache[](#availability-of-the-cache "Permalink") + +缓存是一种优化,但不能保证始终有效,因此您需要准备好在需要它们的每个作业中重新生成所有缓存的文件. + +假设您已根据工作流程[在`.gitlab-ci.yml`](../yaml/README.html#cache)正确[定义了`cache`](../yaml/README.html#cache) ,则缓存的可用性最终取决于 Runner 的配置方式(执行程序类型以及是否使用不同的 Runner 在作业之间传递缓存). + +### Where the caches are stored[](#where-the-caches-are-stored "Permalink") + +由于亚军是一个负责存储的缓存,这是必须要知道它的存储**位置** . 在`.gitlab-ci.yml`中的作业下定义的所有缓存路径都存储在单个`cache.zip`文件中,并存储在 Runner 的配置缓存位置中. 默认情况下,它们存储在本地安装了 Runner 的计算机中,具体取决于执行程序的类型. + +| GitLab Runner 执行器 | 缓存的默认路径 | +| --- | --- | +| [Shell](https://docs.gitlab.com/runner/executors/shell.html) | 在本地,存储在`gitlab-runner`用户的主目录下: `/home/gitlab-runner/cache/<user>/<project>/<cache-key>/cache.zip` home/ `gitlab-runner` user>/< `gitlab-runner` < `gitlab-runner` `/home/gitlab-runner/cache/<user>/<project>/<cache-key>/cache.zip` . | +| [Docker](https://docs.gitlab.com/runner/executors/docker.html) | 在本地存储在[Docker 卷下](https://docs.gitlab.com/runner/executors/docker.html) :/ `/var/lib/docker/volumes/<volume-id>/_data/<user>/<project>/<cache-key>/cache.zip` [docker / volumes / <卷](https://docs.gitlab.com/runner/executors/docker.html) `/var/lib/docker/volumes/<volume-id>/_data/<user>/<project>/<cache-key>/cache.zip` _ `/var/lib/docker/volumes/<volume-id>/_data/<user>/<project>/<cache-key>/cache.zip` . | +| [Docker 机器](https://docs.gitlab.com/runner/executors/docker_machine.html) (自动缩放赛跑者) | 行为与 Docker 执行器相同. | + +### How archiving and extracting works[](#how-archiving-and-extracting-works "Permalink") + +在最简单的情况下,请考虑仅使用一台安装了 Runner 的计算机,并且项目的所有作业都在同一主机上运行. + +让我们看下面两个属于两个连续阶段的作业的示例: + +``` +stages: + - build + - test + +before_script: + - echo "Hello" + +job A: + stage: build + script: + - mkdir vendor/ + - echo "build" > vendor/hello.txt + cache: + key: build-cache + paths: + - vendor/ + after_script: + - echo "World" + +job B: + stage: test + script: + - cat vendor/hello.txt + cache: + key: build-cache +``` + +这是幕后发生的事情: + +1. 管道开始. +2. `job A` runs. +3. 执行`before_script` . +4. `script`已执行. +5. `after_script`被执行. +6. `cache`运行,并且`vendor/`目录被压缩到`cache.zip` . 然后根据[Runner 的设置](#where-the-caches-are-stored)和`cache: key`将该文件保存在目录中. +7. `job B` runs. +8. 提取缓存(如果找到). +9. 执行`before_script` . +10. `script`已执行. +11. 管道完成. + +通过在单台计算机上使用单个 Runner,就不会出现`job B`可能在不同于`job A`的 Runner 上执行的问题,从而保证了各个阶段之间的缓存. 仅当构建在同一 Runner /机器上从阶段`build`到`test` ,此方法才有效,否则,您[可能没有可用的缓存](#cache-mismatch) . + +在缓存过程中,还需要考虑以下几点: + +* 如果具有其他缓存配置的某些其他作业已将其缓存保存在同一 zip 文件中,则它将被覆盖. 如果使用了基于 S3 的共享缓存,则还会根据缓存密钥将文件另外上传到 S3 到对象. 因此,路径不同但缓存键相同的两个作业将覆盖其缓存. +* 从`cache.zip`提取缓存时,zip 文件中的所有内容都提取到作业的工作目录(通常是下拉的存储库)中,并且 Runner 不在乎`job A`的存档是否覆盖了`job B` + +之所以以这种方式工作,是因为为一个 Runner 创建的缓存通常在由可以在**不同体系结构**上运行的缓存使用时才无效(例如,当缓存包含二进制文件时). 而且由于不同的步骤可能由运行在不同计算机上的运行程序执行,因此这是安全的默认设置. + +### Cache mismatch[](#cache-mismatch "Permalink") + +在下表中,您可以看到可能导致缓存不匹配的一些原因以及一些解决方法. + +| 缓存不匹配的原因 | 如何修复 | +| --- | --- | +| 您使用多个独立运行器(不在自动缩放模式下)附加到一个项目,而没有共享缓存 | 您的项目仅使用一个 Runner 或使用启用了分布式缓存的多个 Runner | +| 您在未启用分布式缓存的自动缩放模式下使用 Runners | 配置自动缩放运行器以使用分布式缓存 | +| 安装了 Runner 的计算机磁盘空间不足,或者,如果设置了分布式缓存,则存储缓存的 S3 存储桶空间不足 | 确保清除一些空间以允许存储新的缓存. 当前,没有自动的方法可以做到这一点. | +| 对于作业中缓存不同路径的作业,请使用相同的`key` . | Use different cache keys to that the cache archive is stored to a different location and doesn’t overwrite wrong caches. | + +让我们探索一些例子. + +#### Examples[](#examples "Permalink") + +假设您只为项目分配了一个 Runner,因此默认情况下缓存将存储在 Runner 的计算机中. 如果两个作业 A 和 B 具有相同的缓存密钥,但是它们缓存不同的路径,则即使它们的`paths`不匹配,缓存 B 也会覆盖缓存 A: + +当管道第二次运行时,我们希望`job A`和`job B`重用其缓存. + +``` +stages: + - build + - test + +job A: + stage: build + script: make build + cache: + key: same-key + paths: + - public/ + +job B: + stage: test + script: make test + cache: + key: same-key + paths: + - vendor/ +``` + +1. `job A` runs. +2. `public/`作为 cache.zip 缓存. +3. `job B` runs. +4. 先前的缓存(如果有)已解压缩. +5. `vendor/`作为 cache.zip 缓存,并覆盖前一个. +6. 下次`job A`运行时,它将使用`job B`的缓存,缓存不同,因此无效. + +要解决此问题,请为每个作业使用不同的`keys` . + +在另一种情况下,假设您为项目分配了多个运行器,但是未启用分布式缓存. 第二次运行管道时,我们希望`job A`和`job B`重用其缓存(在这种情况下将有所不同): + +``` +stages: + - build + - test + +job A: + stage: build + script: build + cache: + key: keyA + paths: + - vendor/ + +job B: + stage: test + script: test + cache: + key: keyB + paths: + - vendor/ +``` + +在这种情况下,即使`key`不同(不必担心覆盖),如果作业在后续管道中的不同运行器上运行,您也可能会在每个阶段之前"清理"缓存的文件. + +## Clearing the cache[](#clearing-the-cache "Permalink") + +GitLab Runners 使用[缓存](../yaml/README.html#cache)通过重用现有数据来加快作业的执行速度. 但是,这有时可能导致行为不一致. + +要从缓存的新副本开始,有两种方法可以做到这一点. + +### Clearing the cache by changing `cache:key`[](#clearing-the-cache-by-changing-cachekey "Permalink") + +您所需要做的就是设置一个新的`cache: key` `.gitlab-ci.yml` . 在下一个管道运行中,缓存将存储在其他位置. + +### Clearing the cache manually[](#clearing-the-cache-manually "Permalink") + +在 GitLab 10.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41249) . + +如果要避免编辑`.gitlab-ci.yml` ,则可以通过 GitLab 的 UI 轻松清除缓存: + +1. 导航到项目的**CI / CD>管道**页面. +2. 单击" **清除流道缓存"**按钮以清理缓存. + + [![Clear Runners cache](img/97c7baeb5e993264f4619e443bdacebc.png)](img/clear_runners_cache.png) + +3. 在下一次推送时,您的 CI / CD 作业将使用新的缓存. + +在后台,这可以通过在数据库中增加一个计数器来实现,该计数器的值用于通过将整数附加到`-1` , `-2`等来为高速缓存创建密钥.密钥已生成,旧的缓存不再有效. \ No newline at end of file diff --git a/docs/214.md b/docs/214.md new file mode 100644 index 0000000000000000000000000000000000000000..d08c22d196819a0e3ac71e583487528b881d8f85 --- /dev/null +++ b/docs/214.md @@ -0,0 +1,80 @@ +# GitLab ChatOps + +> 原文:[https://docs.gitlab.com/ee/ci/chatops/README.html](https://docs.gitlab.com/ee/ci/chatops/README.html) + +* [How GitLab ChatOps works](#how-gitlab-chatops-works) +* [Best practices for ChatOps CI jobs](#best-practices-for-chatops-ci-jobs) + * [Controlling the ChatOps reply](#controlling-the-chatops-reply) +* [GitLab ChatOps examples](#gitlab-chatops-examples) +* [GitLab ChatOps icon](#gitlab-chatops-icon) + +# GitLab ChatOps[](#gitlab-chatops "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) . +* 在 11.9 中[移至](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) [GitLab Core](https://about.gitlab.com/pricing/) . + +GitLab ChatOps 提供了一种通过 Slack 等聊天服务与 CI / CD 作业进行交互的方法. 许多组织的讨论,协作和故障排除都是在聊天服务中进行的. 拥有一种方法来运行 CI / CD 作业并将输出回传到渠道,可以极大地增强团队的工作流程. + +## How GitLab ChatOps works[](#how-gitlab-chatops-works "Permalink") + +GitLab ChatOps 是基于[GitLab CI / CD](../README.html)和[Slack Slash Commands](../../user/project/integrations/slack_slash_commands.html)构建的. ChatOps 使用以下参数为[斜杠命令](../../integration/slash_commands.html)提供`run`操作: + +* 要执行的`<job name>` . +* The `<job arguments>`. + +ChatOps 将以下[CI / CD 变量](../variables/README.html#predefined-environment-variables)传递给作业: + +* `CHAT_INPUT`包含任何其他参数. +* `CHAT_CHANNEL`设置为触发该动作的通道的名称. + +当执行时,ChatOps 查找指定的作业名称,并尝试将其与[`.gitlab-ci.yml`](../yaml/README.html)的相应作业匹配. 如果在`master`上找到匹配的作业,则计划仅包含该作业的管道. 作业完成后: + +* 如果作业在*不到 30 分钟内完成* ,则 ChatOps 会将作业的输出发送到 Slack. +* 如果作业在*30 分钟内完成* ,则该作业必须使用[Slack API](https://api.slack.com/)将数据发送到通道. + +要使用`run`命令,您必须具有[Developer 访问权限或更高权限](../../user/permissions.html#project-members-permissions) . 如果不能从聊天中触发某项工作,则可以将其设置为下列`except: [chat]` . + +## Best practices for ChatOps CI jobs[](#best-practices-for-chatops-ci-jobs "Permalink") + +由于 ChatOps 是基于 GitLab CI / CD 构建的,因此该作业具有可用的所有相同功能. 创建 ChatOps 作业时,请考虑以下最佳做法: + +* GitLab 强烈建议您`only: [chat]`设置`only: [chat]`以便该作业不会作为标准 CI 管道的一部分运行. +* 如果作业设置为以下`when: manual` ,则 ChatOps 将创建管道,但是作业等待启动. +* ChatOps 为访问控制提供了有限的支持. 如果触发斜杠命令的用户在项目中具有" [开发人员"访问权限或更高权限](../../user/permissions.html#project-members-permissions) ,则作业将运行. 作业本身可以使用现有的[CI / CD 变量(](../variables/README.html#predefined-environment-variables)例如`GITLAB_USER_ID`来执行其他权限验证,但是可以[覆盖](../variables/README.html#priority-of-environment-variables)这些变量. + +### Controlling the ChatOps reply[](#controlling-the-chatops-reply "Permalink") + +单个命令的作业输出将作为答复发送到通道. 例如,以下任务的聊天回复是频道中的`Hello World` : + +``` +hello-world: + stage: chatops + only: [chat] + script: + - echo "Hello World" +``` + +包含多个命令(或`before_script` )的作业将在聊天回复中返回其他内容. 在这些情况下,命令和它们的输出都包括在内,并且命令以 ANSI 颜色代码包装. + +To selectively reply with the output of one command, its output must be bounded by the `chat_reply` section. For example, the following job lists the files in the current directory: + +``` +ls: + stage: chatops + only: [chat] + script: + - echo "This command will not be shown." + - echo -e "section_start:$( date +%s ):chat_reply\r\033[0K\n$( ls -la )\nsection_end:$( date +%s ):chat_reply\r\033[0K" +``` + +## GitLab ChatOps examples[](#gitlab-chatops-examples "Permalink") + +GitLab.com 团队创建了一个[常见 ChatOps 脚本](https://gitlab.com/gitlab-com/chatops)的存储库,它们用于与我们的 GitLab 生产实例进行交互. 其他 GitLab 实例的管理员可能会发现它们很有用. 它们可以作为您可以编写以与自己的应用程序进行交互的 ChatOps 脚本的灵感. + +## GitLab ChatOps icon[](#gitlab-chatops-icon "Permalink") + +[官方的 GitLab ChatOps 图标](img/gitlab-chatops-icon.png)可以下载. 您可以在此处找到并下载官方的 GitLab ChatOps 图标. + +[![GitLab ChatOps bot icon](img/b7658a174f8b110251a289f5276dc822.png)](img/gitlab-chatops-icon-small.png) \ No newline at end of file diff --git a/docs/215.md b/docs/215.md new file mode 100644 index 0000000000000000000000000000000000000000..16926e32d734b773c166a41dde8781db9ddfcc39 --- /dev/null +++ b/docs/215.md @@ -0,0 +1,122 @@ +# Cloud deployment + +> 原文:[https://docs.gitlab.com/ee/ci/cloud_deployment/](https://docs.gitlab.com/ee/ci/cloud_deployment/) + +* [AWS](#aws) + * [Run AWS commands from GitLab CI/CD](#run-aws-commands-from-gitlab-cicd) + * [Use an AWS Elastic Container Registry (ECR) image in your CI/CD](#use-an-aws-elastic-container-registry-ecr-image-in-your-cicd) + * [Deploy your application to the AWS Elastic Container Service (ECS)](#deploy-your-application-to-the-aws-elastic-container-service-ecs) + +# Cloud deployment[](#cloud-deployment "Permalink") + +与主要的云提供商进行交互可能已成为交付过程中非常需要的任务. GitLab 通过提供预安装了所需库和工具的 Docker 映像,减轻了这一过程的麻烦. 通过在 CI / CD 管道中引用它们,您将能够更轻松地与所选的云提供商进行交互. + +## AWS[](#aws "Permalink") + +GitLab 提供了可用于[从 GitLab CI / CD 运行 AWS 命令的](#run-aws-commands-from-gitlab-cicd) Docker 映像,并提供了一个模板,以使其更易于[部署到 AWS](#deploy-your-application-to-the-aws-elastic-container-service-ecs) . + +### Run AWS commands from GitLab CI/CD[](#run-aws-commands-from-gitlab-cicd "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31167) . + +GitLab 的 AWS Docker 映像提供了[AWS Command Line Interface](https://aws.amazon.com/cli/) ,可让您运行`aws`命令. 作为部署策略的一部分,您可以通过指定[GitLab 的 AWS Docker 映像](https://gitlab.com/gitlab-org/cloud-deploy)直接从`.gitlab-ci.yml`运行`aws`命令. + +需要一些凭据才能运行`aws`命令: + +1. 如果您还没有[一个 AWS 账户](https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-set-up.html) ,请注册一个. +2. 登录到控制台并创建[一个新的 IAM 用户](https://console.aws.amazon.com/iam/home#/home) . +3. 选择您新创建的用户以访问其详细信息. 导航到**安全凭证>创建新的访问密钥** . + + **注意:**将生成新的**访问密钥 ID**和**秘密访问密钥**对. 请立即记录下来. +4. 在您的 GitLab 项目中,转到**"设置">" CI / CD"** . 将以下内容设置为[环境变量](../variables/README.html#gitlab-cicd-environment-variables) (请参见下表): + + * 访问密钥 ID. + * 秘密访问密钥. + * 地区代码. 您可以检查[AWS 区域终端节点列表](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints) . 您可能想要检查要使用的 AWS 服务[在所选区域中](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/)是否[可用](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/) . + + | 环保 变量名 | Value | + | --- | --- | + | `AWS_ACCESS_KEY_ID` | 您的访问密钥 ID | + | `AWS_SECRET_ACCESS_KEY` | 您的秘密访问密钥 | + | `AWS_DEFAULT_REGION` | 您的地区代码 | + +5. 现在,您可以在此项目的`.gitlab-ci.yml`文件中使用`aws`命令: + + ``` + deploy: + stage: deploy + image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest # see the note below + script: + - aws s3 ... + - aws create-deployment ... + ``` + + **注意:**上例中使用的映像( `registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest` )托管在[GitLab 容器注册表中](../../user/packages/container_registry/index.html) ,可以使用. 或者,将映像替换为 AWS ECR 上托管的映像. + +### Use an AWS Elastic Container Registry (ECR) image in your CI/CD[](#use-an-aws-elastic-container-registry-ecr-image-in-your-cicd "Permalink") + +除了引用托管在 GitLab 注册表上的映像外,您还可以引用托管在任何第三方注册表上的映像,例如[Amazon Elastic Container Registry(ECR)](https://aws.amazon.com/ecr/) . + +为此, [将映像推送到 ECR 存储库中](https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-push-ecr-image.html) . 然后在`.gitlab-ci.yml`文件中引用它,并替换`image`路径以指向您的 ECR 图像. + +### Deploy your application to the AWS Elastic Container Service (ECS)[](#deploy-your-application-to-the-aws-elastic-container-service-ecs "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/207962) . + +GitLab 提供了一系列[CI 模板,您可以将其包含在项目中](../yaml/README.html#include) . 要自动将应用程序部署到[Amazon Elastic Container Service](https://aws.amazon.com/ecs/) (AWS ECS)集群,您可以在`.gitlab-ci.yml`文件中`include` `Deploy-ECS.gitlab-ci.yml`模板. + +GitLab 还提供了可在您的`gitlab-ci.yml`文件中使用的[Docker 映像](https://gitlab.com/gitlab-org/cloud-deploy/-/tree/master/aws) ,以简化使用 AWS 的工作: + +* 使用`registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest`以使用 AWS CLI 命令. +* 使用`registry.gitlab.com/gitlab-org/cloud-deploy/aws-ecs:latest`将您的应用程序部署到 AWS ECS. + +在开始此过程之前,您需要 AWS ECS 上的集群以及相关组件,例如 ECS 服务,ECS 任务定义,AWS RDS 上的数据库等. [了解有关 AWS ECS 的更多信息](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html) . + +在 AWS ECS 上完成所有设置后,请执行以下步骤: + +1. 确保将您的 AWS 凭证设置为项目的环境变量. 您可以按照[上述步骤](#run-aws-commands-from-gitlab-cicd)完成此设置. +2. Add these variables to your project’s `.gitlab-ci.yml` file: + + ``` + variables: + CI_AWS_ECS_CLUSTER: my-cluster + CI_AWS_ECS_SERVICE: my-service + CI_AWS_ECS_TASK_DEFINITION: my-task-definition + ``` + + Three variables are defined in this snippet: + + * `CI_AWS_ECS_CLUSTER` :您要为部署目标的 AWS ECS 集群的名称. + * `CI_AWS_ECS_SERVICE` :绑定到您的 AWS ECS 集群的目标服务的名称. + * `CI_AWS_ECS_TASK_DEFINITION` :与上述服务绑定的任务定义的名称. + + 您可以在[AWS ECS 仪表板上](https://console.aws.amazon.com/ecs/home)选择目标集群后找到这些名称: + + [![AWS ECS dashboard](img/7dc58177067caac48605788b7932d846.png)](../img/ecs_dashboard_v12_9.png) + +3. 将此模板包括在`.gitlab-ci.yml` : + + ``` + include: + - template: AWS/Deploy-ECS.gitlab-ci.yml + ``` + + `Deploy-ECS`模板随 GitLab 一起提供[,](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml)可[在 GitLab.com 上获得](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml) . + +4. 提交更新的`.gitlab-ci.yml`并将其推送到项目的存储库中,您就完成了! + + 您的应用程序 Docker 映像将被重建并推送到 GitLab 注册表中. 然后,目标任务定义将使用新 Docker 映像的位置进行更新,结果将在 ECS 中创建新的修订版. + + 最后,您的 AWS ECS 服务将使用任务定义的新修订版进行更新,从而使群集提取应用程序的最新版本. + +**警告:** [`Deploy-ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml)模板包括[`Jobs/Build.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml)和[`Jobs/Deploy/ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml) "子模板". 不要单独包括这些"子模板",而仅包括主`Deploy-ECS.gitlab-ci.yml`模板. "子模板"旨在仅与主模板一起使用. 如果不包括主模板,它们可能会移动或发生意外更改,从而导致您的管道失败. 此外,这些模板中的作业名称可能会更改. 不要在您自己的管道中覆盖这些作业的名称,因为当名称更改时,覆盖将停止工作. + +另外,如果您不希望使用`Deploy-ECS.gitlab-ci.yml`模板部署到 AWS ECS,则始终可以使用基于`aws-base` Docker 映像[为 ECS](https://docs.aws.amazon.com/cli/latest/reference/ecs/index.html#cli-aws-ecs)运行您自己的[AWS CLI 命令](https://docs.aws.amazon.com/cli/latest/reference/ecs/index.html#cli-aws-ecs) . + +``` +deploy: + stage: deploy + image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest + script: + - aws ecs register-task-definition ... +``` \ No newline at end of file diff --git a/docs/216.md b/docs/216.md new file mode 100644 index 0000000000000000000000000000000000000000..0cf03ca0e5dc67955c96e15a164262c8ac63e314 --- /dev/null +++ b/docs/216.md @@ -0,0 +1,13 @@ +# Docker integration + +> 原文:[https://docs.gitlab.com/ee/ci/docker/README.html](https://docs.gitlab.com/ee/ci/docker/README.html) + +# Docker integration[](#docker-integration "Permalink") + +GitLab CI / CD 可以与[Docker](https://www.docker.com)结合使用,以实现两者之间的集成. + +以下文档可用于将 GitLab CI / CD 与 Docker 结合使用: + +* [Using Docker images](using_docker_images.html). +* [Building Docker images with GitLab CI/CD](using_docker_build.html). +* [Building images with kaniko and GitLab CI/CD](using_kaniko.html). \ No newline at end of file diff --git a/docs/217.md b/docs/217.md new file mode 100644 index 0000000000000000000000000000000000000000..a9456d40ff747b45f77488b574029d7a6272582c --- /dev/null +++ b/docs/217.md @@ -0,0 +1,436 @@ +# Building Docker images with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/docker/using_docker_build.html](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html) + +* [Runner Configuration](#runner-configuration) + * [Use shell executor](#use-shell-executor) + * [Use Docker-in-Docker workflow with Docker executor](#use-docker-in-docker-workflow-with-docker-executor) + * [TLS enabled](#tls-enabled) + * [TLS disabled](#tls-disabled) + * [Use Docker socket binding](#use-docker-socket-binding) +* [Making Docker-in-Docker builds faster with Docker layer caching](#making-docker-in-docker-builds-faster-with-docker-layer-caching) + * [How Docker caching works](#how-docker-caching-works) + * [Using Docker caching](#using-docker-caching) +* [Use the OverlayFS driver](#use-the-overlayfs-driver) + * [Requirements](#requirements) + * [Use the OverlayFS driver per project](#use-the-overlayfs-driver-per-project) + * [Use the OverlayFS driver for every project](#use-the-overlayfs-driver-for-every-project) +* [Using the GitLab Container Registry](#using-the-gitlab-container-registry) +* [Troubleshooting](#troubleshooting) + * [`docker: Cannot connect to the Docker daemon at tcp://docker:2375\. Is the docker daemon running?`](#docker-cannot-connect-to-the-docker-daemon-at-tcpdocker2375-is-the-docker-daemon-running) + +# Building Docker images with GitLab CI/CD[](#building-docker-images-with-gitlab-cicd "Permalink") + +GitLab CI / CD 允许您使用 Docker Engine 来构建和测试基于 Docker 的项目. + +持续集成/部署中的新趋势之一是: + +1. Create an application image. +2. 针对创建的图像运行测试. +3. 将映像推送到远程注册表. +4. 从推送的映像部署到服务器. + +当您的应用程序已经具有可用于创建和测试映像的`Dockerfile` ,它也很有用: + +``` +docker build -t my-image dockerfiles/ +docker run my-image /script/to/run/tests +docker tag my-image my-registry:5000/my-image +docker push my-registry:5000/my-image +``` + +这需要对 GitLab Runner 进行特殊配置才能在作业期间启用`docker`支持. + +## Runner Configuration[](#runner-configuration "Permalink") + +有三种方法可在作业期间启用`docker build`和`docker run`的使用: 每个都有自己的权衡. + +[使用 docker](using_kaniko.html) `docker build`的替代方法是[使用 kaniko](using_kaniko.html) . 这避免了必须在特权模式下执行 Runner. + +**提示:**要了解如何在 GitLab.com 上为共享的 Runner 配置 Docker 和 Runner,请参阅[GitLab.com 的共享的 Runners](../../user/gitlab_com/index.html#shared-runners) . + +### Use shell executor[](#use-shell-executor "Permalink") + +最简单的方法是在`shell`执行模式下安装 GitLab Runner. 然后,GitLab Runner 以`gitlab-runner`用户身份执行作业脚本. + +1. Install [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/#installation). + +2. 在 GitLab Runner 安装过程中,选择`shell`作为执行作业脚本的方法或使用命令: + + ``` + sudo gitlab-runner register -n \ + --url https://gitlab.com/ \ + --registration-token REGISTRATION_TOKEN \ + --executor shell \ + --description "My Runner" + ``` + +3. 在服务器上安装 Docker Engine. + + 有关如何在不同系统上安装 Docker Engine 的更多信息,请查看[支持的安装](https://s0docs0docker0com.icopy.site/engine/installation/) . + +4. Add `gitlab-runner` user to `docker` group: + + ``` + sudo usermod -aG docker gitlab-runner + ``` + +5. 确认`gitlab-runner`有权访问 Docker: + + ``` + sudo -u gitlab-runner -H docker info + ``` + + 现在,您可以通过将`.gitlab-ci.yml` `docker info`添加到`.gitlab-ci.yml`来验证一切正常: + + ``` + before_script: + - docker info + + build_image: + script: + - docker build -t my-docker-image . + - docker run my-docker-image /script/to/run/tests + ``` + +6. 您现在可以使用`docker`命令(并在需要时**安装** `docker-compose` ). + +**注:**通过添加`gitlab-runner`的`docker`您可以有效地授予组`gitlab-runner`完整的 root 权限. 有关更多信息,请阅读[关于 Docker 安全性: `docker` group 认为是有害的](https://www.andreas-jung.com/contents/on-docker-security-docker-group-considered-harmful) . + +### Use Docker-in-Docker workflow with Docker executor[](#use-docker-in-docker-workflow-with-docker-executor "Permalink") + +第二种方法是使用特殊泊坞窗功能于泊坞(DIND) [泊坞窗图像](https://hub.docker.com/_/docker/)安装(所有工具`docker` ),并在特权模式图像的上下文中运行作业脚本. + +**注意:** `docker-compose`不是 Docker-in-Docker(dind)的一部分. 要在 CI 构建中使用`docker-compose` ,请遵循`docker-compose` [安装说明](https://s0docs0docker0com.icopy.site/compose/install/) .**危险:**通过启用`--docker-privileged` ,可以有效地禁用容器的所有安全机制,并使主机暴露于特权升级之下,这可能导致容器突破. 有关更多信息,请查看有关[运行时特权和 Linux 功能](https://s0docs0docker0com.icopy.site/engine/reference/run/)的官方 Docker 文档. + +Docker-in-Docker 运作良好,是推荐的配置,但并非没有挑战: + +* When using Docker-in-Docker, each job is in a clean environment without the past history. Concurrent jobs work fine because every build gets its own instance of Docker engine so they won’t conflict with each other. But this also means that jobs can be slower because there’s no caching of layers. +* 默认情况下,Docker 17.09 及更高版本使用`--storage-driver overlay2` ,这是推荐的存储驱动程序. 有关详细信息,请参见[使用 overlayfs 驱动程序](#use-the-overlayfs-driver) . +* 由于`docker:19.03.12-dind`容器和 Runner 容器不共享其根文件系统,因此作业的工作目录可用作子容器的安装点. 例如,如果您有要与子容器共享的文件,则可以在`/builds/$CI_PROJECT_PATH`下创建一个子目录,并将其用作安装点(有关更详尽的解释,请[参见问题#41227](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41227) ): + + ``` + variables: + MOUNT_POINT: /builds/$CI_PROJECT_PATH/mnt + + script: + - mkdir -p "$MOUNT_POINT" + - docker run -v "$MOUNT_POINT:/mnt" my-docker-image + ``` + +可在以下位置找到使用此方法的示例项目: [https](https://gitlab.com/gitlab-examples/docker) : [//gitlab.com/gitlab-examples/docker](https://gitlab.com/gitlab-examples/docker) . + +在以下示例中,我们使用 Docker images 标签指定特定版本,例如`docker:19.03.12` . 如果使用了诸如`docker:stable`类的标签,则您将无法控制要使用的版本,这可能导致无法预测的行为,尤其是在发布新版本时. + +#### TLS enabled[](#tls-enabled "Permalink") + +**注意:**需要 GitLab Runner 11.11 或更高版本,但是如果使用[Helm chart](https://docs.gitlab.com/runner/install/kubernetes.html)安装了 GitLab Runner,则不支持. 有关详细信息,请参见[相关问题](https://gitlab.com/gitlab-org/charts/gitlab-runner/-/issues/83) . + +Docker 守护程序支持通过 TLS 的连接,默认情况下,对于 Docker 19.03.12 或更高版本,它已完成. 这是使用 Docker-in-Docker 服务的**建议**方法, [GitLab.com 共享运行程序](../../user/gitlab_com/index.html#shared-runners)支持此方法. + +1. Install [GitLab Runner](https://docs.gitlab.com/runner/install/). + +2. 从命令行注册 GitLab Runner 以使用`docker`和`privileged`模式: + + ``` + sudo gitlab-runner register -n \ + --url https://gitlab.com/ \ + --registration-token REGISTRATION_TOKEN \ + --executor docker \ + --description "My Docker Runner" \ + --docker-image "docker:19.03.12" \ + --docker-privileged \ + --docker-volumes "/certs/client" + ``` + + 上面的命令将注册一个新的 Runner 以使用由 Docker 提供的特殊`docker:19.03.12`映像. **注意,它使用`privileged`模式来启动构建和服务容器.** 如果要使用[Docker-in-Docker](https://www.docker.com/blog/docker-can-now-run-within-docker/)模式,则始终必须在 Docker 容器中使用`privileged = true` . + + 这还将为服务安装`/certs/client`并构建容器,这是 Docker 客户端使用该目录内的证书所必需的. 有关更多信息,请参阅[https://hub.docker.com/_/docker/#tls](https://hub.docker.com/_/docker/#tls) . + + 上面的命令将创建一个类似于以下内容的`config.toml`条目: + + ``` + [[runners]] + url = "https://gitlab.com/" + token = TOKEN + executor = "docker" + [runners.docker] + tls_verify = false + image = "docker:19.03.12" + privileged = true + disable_cache = false + volumes = ["/certs/client", "/cache"] + [runners.cache] + [runners.cache.s3] + [runners.cache.gcs] + ``` + +3. 您现在可以使用`docker`在构建脚本(注意列入`docker:19.03.12-dind`服务): + + ``` + image: docker:19.03.12 + + variables: + # When using dind service, we need to instruct docker, to talk with + # the daemon started inside of the service. The daemon is available + # with a network connection instead of the default + # /var/run/docker.sock socket. Docker 19.03 does this automatically + # by setting the DOCKER_HOST in + # https://github.com/docker-library/docker/blob/d45051476babc297257df490d22cbd806f1b11e4/19.03/docker-entrypoint.sh#L23-L29 + # + # The 'docker' hostname is the alias of the service container as described at + # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services. + # + # Note that if you're using GitLab Runner 12.7 or earlier with the Kubernetes executor and Kubernetes 1.6 or earlier, + # the variable must be set to tcp://localhost:2376 because of how the + # Kubernetes executor connects services to the job container + # DOCKER_HOST: tcp://localhost:2376 + # + # Specify to Docker where to create the certificates, Docker will + # create them automatically on boot, and will create + # `/certs/client` that will be shared between the service and job + # container, thanks to volume mount from config.toml + DOCKER_TLS_CERTDIR: "/certs" + + services: + - docker:19.03.12-dind + + before_script: + - docker info + + build: + stage: build + script: + - docker build -t my-docker-image . + - docker run my-docker-image /script/to/run/tests + ``` + +#### TLS disabled[](#tls-disabled "Permalink") + +有时出于某些合理原因,您可能想要禁用 TLS. 例如,您无法控制所使用的 GitLab Runner 配置. + +假设 Runner `config.toml`类似于: + +``` +[[runners]] + url = "https://gitlab.com/" + token = TOKEN + executor = "docker" + [runners.docker] + tls_verify = false + image = "docker:19.03.12" + privileged = true + disable_cache = false + volumes = ["/cache"] + [runners.cache] + [runners.cache.s3] + [runners.cache.gcs] +``` + +您现在可以使用`docker`在构建脚本(注意列入`docker:19.03.12-dind`服务): + +``` +image: docker:19.03.12 + +variables: + # When using dind service we need to instruct docker, to talk with the + # daemon started inside of the service. The daemon is available with + # a network connection instead of the default /var/run/docker.sock socket. + # + # The 'docker' hostname is the alias of the service container as described at + # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services + # + # Note that if you're using GitLab Runner 12.7 or earlier with the Kubernetes executor and Kubernetes 1.6 or earlier, + # the variable must be set to tcp://localhost:2375 because of how the + # Kubernetes executor connects services to the job container + # DOCKER_HOST: tcp://localhost:2375 + # + DOCKER_HOST: tcp://docker:2375 + # + # This will instruct Docker not to start over TLS. + DOCKER_TLS_CERTDIR: "" + +services: + - docker:19.03.12-dind + +before_script: + - docker info + +build: + stage: build + script: + - docker build -t my-docker-image . + - docker run my-docker-image /script/to/run/tests +``` + +### Use Docker socket binding[](#use-docker-socket-binding "Permalink") + +第三种方法是将`/var/run/docker.sock`绑定安装到容器中,以便 Docker 在该映像的上下文中可用. + +**注意:**如果[在使用 GitLab Runner 11.11 或更高版本时](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/1261)绑定 Docker 套接字,则不能再将`docker:19.03.12-dind`用作服务,因为对服务也进行了卷绑定,从而使它们不兼容. + +为此,请按照下列步骤操作: + +1. Install [GitLab Runner](https://docs.gitlab.com/runner/install/). + +2. 从命令行注册 GitLab Runner 以使用`docker`并共享`/var/run/docker.sock` : + + ``` + sudo gitlab-runner register -n \ + --url https://gitlab.com/ \ + --registration-token REGISTRATION_TOKEN \ + --executor docker \ + --description "My Docker Runner" \ + --docker-image "docker:19.03.12" \ + --docker-volumes /var/run/docker.sock:/var/run/docker.sock + ``` + + 上面的命令将注册一个新的 Runner 以使用由 Docker 提供的特殊`docker:19.03.12`映像. **请注意,它使用的是 Runner 本身的 Docker 守护进程,并且 Docker 命令产生的任何容器都将是 Runner 的兄弟,而不是 Runner 的子代.** 这可能会带来一些不适合您的工作流程的复杂性和局限性. + + 上面的命令将创建一个类似于以下内容的`config.toml`条目: + + ``` + [[runners]] + url = "https://gitlab.com/" + token = REGISTRATION_TOKEN + executor = "docker" + [runners.docker] + tls_verify = false + image = "docker:19.03.12" + privileged = false + disable_cache = false + volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"] + [runners.cache] + Insecure = false + ``` + +3. 您现在可以使用`docker`在构建脚本(请注意,您不需要包括`docker:19.03.12-dind`服务泊坞执行使用泊坞时): + + ``` + image: docker:19.03.12 + + before_script: + - docker info + + build: + stage: build + script: + - docker build -t my-docker-image . + - docker run my-docker-image /script/to/run/tests + ``` + +尽管上述方法避免在特权模式下使用 Docker,但您应注意以下含义: + +* 通过共享 Docker 守护程序,您可以有效地禁用容器的所有安全机制,并使主机暴露于特权升级之下,这可能导致容器突破. 例如,如果一个项目运行`docker rm -f $(docker ps -a -q)` ,它将删除 GitLab Runner 容器. +* 并发工作可能无法正常工作; 如果您的测试创建了具有特定名称的容器,则它们可能会相互冲突. +* 将源仓库中的文件和目录共享到容器中可能无法正常工作,因为卷安装是在主机而不是构建容器的上下文中完成的. 例如: + + ``` + docker run --rm -t -i -v $(pwd)/src:/home/app/src test-image:latest run_app_tests + ``` + +## Making Docker-in-Docker builds faster with Docker layer caching[](#making-docker-in-docker-builds-faster-with-docker-layer-caching "Permalink") + +在使用 Docker-in-Docker 时,每次创建构建时 Docker 都会下载映像的所有层. 最新版本的 Docker(Docker 1.13 及更高版本)可以在 Docker `docker build`步骤中使用预先存在的映像作为缓存,从而大大加快了构建过程. + +### How Docker caching works[](#how-docker-caching-works "Permalink") + +运行`Dockerfile` `docker build` , `Dockerfile`中的每个命令`Dockerfile`一个图层. 这些层保留为高速缓存,如果没有任何更改,可以重复使用. 一层中的更改将导致重新创建所有后续层. + +您可以使用`--cache-from`参数指定标记的图像用作`--cache-from` `docker build`命令的缓存源. 可以使用多个`--cache-from`参数将多个图像指定为缓存源. 请记住,与`--cache-from`参数一起使用的任何映像都必须先被拉出(使用`docker pull` ),然后才能用作缓存源. + +### Using Docker caching[](#using-docker-caching "Permalink") + +这是一个`.gitlab-ci.yml`文件,显示了如何使用 Docker 缓存: + +``` +image: docker:19.03.12 + +services: + - docker:19.03.12-dind + +variables: + # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled + DOCKER_HOST: tcp://docker:2376 + DOCKER_TLS_CERTDIR: "/certs" + +before_script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + +build: + stage: build + script: + - docker pull $CI_REGISTRY_IMAGE:latest || true + - docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest . + - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA + - docker push $CI_REGISTRY_IMAGE:latest +``` + +`build`阶段的`script`部分中的步骤可以总结为: + +1. 第一个命令尝试从注册表中提取映像,以便将其用作`docker build`命令的缓存. +2. 第二个命令使用拉取的映像作为缓存来构建 Docker 映像(请注意`--cache-from $CI_REGISTRY_IMAGE:latest`参数),并对其进行标记. +3. 最后两个命令将标记的 Docker 映像推送到容器注册表,以便它们也可用作后续构建的缓存. + +## Use the OverlayFS driver[](#use-the-overlayfs-driver "Permalink") + +**注意:**默认情况下,GitLab.com 上的共享 Runners 使用`overlay2`驱动程序. + +默认情况下,使用`docker:dind` ,Docker 使用`vfs`存储驱动程序,该驱动程序会在每次运行时复制文件系统. 这是磁盘密集型操作,如果使用其他驱动程序(例如`overlay2` ,则可以避免. + +### Requirements[](#requirements "Permalink") + +1. 确保使用最新内核,最好`>= 4.2` . +2. 检查是否已加载`overlay`模块: + + ``` + sudo lsmod | grep overlay + ``` + + 如果看不到任何结果,则说明未加载. 要加载它,请使用: + + ``` + sudo modprobe overlay + ``` + + 如果一切正常,则需要确保模块在重新启动时已加载. 在 Ubuntu 系统上,这是通过编辑`/etc/modules` . 只需将以下行添加到其中: + + ``` + overlay + ``` + +### Use the OverlayFS driver per project[](#use-the-overlayfs-driver-per-project "Permalink") + +您可以使用`.gitlab-ci.yml`的`DOCKER_DRIVER`环境[变量](../yaml/README.html#variables)分别为每个项目启用驱动程序: + +``` +variables: + DOCKER_DRIVER: overlay2 +``` + +### Use the OverlayFS driver for every project[](#use-the-overlayfs-driver-for-every-project "Permalink") + +如果使用自己的[GitLab Runners](https://docs.gitlab.com/runner/) ,则可以通过在[`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)的[`[[runners]]`部分中](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)设置`DOCKER_DRIVER`环境变量来为每个项目启用驱动程序: + +``` +environment = ["DOCKER_DRIVER=overlay2"] +``` + +如果您正在运行多个运行程序,则必须修改所有配置文件. + +**注意:**阅读有关[Runner 配置](https://docs.gitlab.com/runner/configuration/)和[使用 OverlayFS 存储驱动程序的更多信息](https://s0docs0docker0com.icopy.site/engine/userguide/storagedriver/overlayfs-driver/) . + +## Using the GitLab Container Registry[](#using-the-gitlab-container-registry "Permalink") + +构建 Docker 映像后,可以将其推送到内置的[GitLab Container Registry 中](../../user/packages/container_registry/index.html#build-and-push-images-using-gitlab-cicd) . + +## Troubleshooting[](#troubleshooting "Permalink") + +### `docker: Cannot connect to the Docker daemon at tcp://docker:2375\. Is the docker daemon running?`[](#docker-cannot-connect-to-the-docker-daemon-at-tcpdocker2375-is-the-docker-daemon-running "Permalink") + +[在 Docker](#use-docker-in-docker-workflow-with-docker-executor) v19.03 或更高版本中使用[Docker](#use-docker-in-docker-workflow-with-docker-executor)时,这是一个常见错误. + +发生这种情况是因为 Docker 自动在 TLS 上启动,因此您需要进行一些设置. 如果: + +* 这是第一次设置,请[在 Docker 工作流程中使用 Docker](#use-docker-in-docker-workflow-with-docker-executor)仔细阅读. +* 您要从 v18.09 或更早版本[升级](https://about.gitlab.com/releases/2019/07/31/docker-in-docker-with-docker-19-dot-03/) ,请阅读我们的[升级指南](https://about.gitlab.com/releases/2019/07/31/docker-in-docker-with-docker-19-dot-03/) . \ No newline at end of file diff --git a/docs/218.md b/docs/218.md new file mode 100644 index 0000000000000000000000000000000000000000..1d2e08533a91c8f5b7b1aa64728bf53fba0cb0ac --- /dev/null +++ b/docs/218.md @@ -0,0 +1,687 @@ +# Using Docker images + +> 原文:[https://docs.gitlab.com/ee/ci/docker/using_docker_images.html](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html) + +* [Register Docker Runner](#register-docker-runner) +* [What is an image](#what-is-an-image) +* [What is a service](#what-is-a-service) + * [How services are linked to the job](#how-services-are-linked-to-the-job) + * [How the health check of services works](#how-the-health-check-of-services-works) + * [What services are not for](#what-services-are-not-for) + * [Accessing the services](#accessing-the-services) +* [Define `image` and `services` from `.gitlab-ci.yml`](#define-image-and-services-from-gitlab-ciyml) +* [Passing environment variables to services](#passing-environment-variables-to-services) +* [Extended Docker configuration options](#extended-docker-configuration-options) + * [Available settings for `image`](#available-settings-for-image) + * [Available settings for `services`](#available-settings-for-services) + * [Starting multiple services from the same image](#starting-multiple-services-from-the-same-image) + * [Setting a command for the service](#setting-a-command-for-the-service) + * [Overriding the entrypoint of an image](#overriding-the-entrypoint-of-an-image) +* [Define image and services in `config.toml`](#define-image-and-services-in-configtoml) +* [Define an image from a private Container Registry](#define-an-image-from-a-private-container-registry) + * [Requirements and limitations](#requirements-and-limitations) + * [Using statically-defined credentials](#using-statically-defined-credentials) + * [Determining your `DOCKER_AUTH_CONFIG` data](#determining-your-docker_auth_config-data) + * [Configuring a job](#configuring-a-job) + * [Configuring a Runner](#configuring-a-runner) + * [Using Credentials Store](#using-credentials-store) + * [Using Credential Helpers](#using-credential-helpers) +* [Configuring services](#configuring-services) + * [PostgreSQL service example](#postgresql-service-example) + * [MySQL service example](#mysql-service-example) +* [How Docker integration works](#how-docker-integration-works) +* [How to debug a job locally](#how-to-debug-a-job-locally) + +# Using Docker images[](#using-docker-images "Permalink") + +GitLab CI / CD 与[GitLab Runner](../runners/README.html)一起可以使用[Docker Engine](https://www.docker.com/)测试和构建任何应用程序. + +Docker 是一个开源项目,它允许您使用预定义的映像在单个 Linux 实例中运行的独立"容器"中运行应用程序. [Docker Hub](https://hub.docker.com/)具有丰富的预构建映像数据库,可用于测试和构建您的应用程序. + +与 GitLab CI / CD 一起使用时,Docker 使用[`.gitlab-ci.yml`](../yaml/README.html)设置的预定义映像在单独的隔离容器中运行每个作业. + +这使得拥有可以在您的工作站上运行的简单且可复制的构建环境更加容易. 额外的好处是您可以测试稍后将在您的 Shell 中探索的所有命令,而不必在专用的 CI 服务器上对其进行测试. + +## Register Docker Runner[](#register-docker-runner "Permalink") + +要将 GitLab Runner 与 Docker 一起使用,您需要[注册一个新的 Runner](https://docs.gitlab.com/runner/register/)以使用`docker` executor. + +An example can be seen below. First we set up a temporary template to supply the services: + +``` +cat > /tmp/test-config.template.toml << EOF [[runners]] +[runners.docker] +[[runners.docker.services]] +name = "postgres:latest" +[[runners.docker.services]] +name = "mysql:latest" EOF +``` + +然后,我们使用刚刚创建的模板注册跑步者: + +``` +sudo gitlab-runner register \ + --url "https://gitlab.example.com/" \ + --registration-token "PROJECT_REGISTRATION_TOKEN" \ + --description "docker-ruby:2.6" \ + --executor "docker" \ + --template-config /tmp/test-config.template.toml \ + --docker-image ruby:2.6 +``` + +注册的运行器将使用`ruby:2.6` Docker 映像,并将运行两个服务`postgres:latest`和`mysql:latest` ,在构建过程中均可访问这两个服务. + +## What is an image[](#what-is-an-image "Permalink") + +`image`关键字是 Docker 执行程序将运行以执行 CI 任务的 Docker 映像的名称. + +默认情况下,执行程序仅从[Docker Hub](https://hub.docker.com/)提取图像,但是可以通过设置[Docker 提取策略](https://docs.gitlab.com/runner/executors/docker.html)以允许使用本地映像在`gitlab-runner/config.toml`进行配置. + +有关映像和 Docker Hub 的更多信息,请阅读[Docker Fundamentals](https://s0docs0docker0com.icopy.site/engine/understanding-docker/)文档. + +## What is a service[](#what-is-a-service "Permalink") + +`services`关键字仅定义在您的工作期间运行的另一个 Docker 映像,并链接到`image`关键字定义的 Docker 映像. 这样,您就可以在构建期间访问服务映像. + +服务映像可以运行任何应用程序,但是最常见的用例是运行数据库容器,例如`mysql` . 与每次安装项目时都安装`mysql`相比,使用现有映像并将其作为附加容器运行更容易,更快捷. + +您不仅限于仅具有数据库服务. 您可以将所需的服务添加到`.gitlab-ci.yml`或手动修改`config.toml` . 在[Docker Hub](https://hub.docker.com/)或您的私有 Container Registry 中找到的任何映像都可以用作服务. + +服务继承与 CI 容器本身相同的 DNS 服务器,搜索域和其他主机. + +您可以在[CI 服务示例](../services/README.html)的相关文档中看到一些广泛使用的[服务示例](../services/README.html) . + +### How services are linked to the job[](#how-services-are-linked-to-the-job "Permalink") + +为了更好地了解容器链接的工作方式,请阅读[将容器链接在一起](https://s0docs0docker0com.icopy.site/engine/userguide/networking/default_network/dockerlinks/) . + +总而言之,如果将`mysql`作为服务添加到应用程序,则该映像将用于创建链接到作业容器的容器. + +The service container for MySQL will be accessible under the hostname `mysql`. So, in order to access your database service you have to connect to the host named `mysql` instead of a socket or `localhost`. Read more in [accessing the services](#accessing-the-services). + +### How the health check of services works[](#how-the-health-check-of-services-works "Permalink") + +服务旨在提供可通过**网络访问的**附加功能. 它可能是一个数据库,例如 MySQL 或 Redis,甚至是`docker:stable-dind` ,它允许您在 Docker 中使用 Docker. CI / CD 作业继续进行并可以通过网络进行访问几乎是任何事情. + +为确保此方法有效,跑步者: + +1. 检查默认情况下哪些端口从容器中暴露出来. +2. 启动一个特殊的容器,等待这些端口可访问. + +当检查的第二阶段失败时(由于服务中没有打开的端口,或者由于在超时之前服务未正确启动且端口没有响应),它会显示警告: `*** WARNING: Service XYZ probably didn't start properly` . + +在大多数情况下,它将影响作业,但是在某些情况下,即使打印了该警告,作业仍将成功. 例如: + +* 发出警告后不久,该服务已启动,并且该作业从一开始就没有使用链接的服务. 在那种情况下,当作业需要访问服务时,它可能已经在那里等待连接. +* 服务容器不提供任何网络服务,但是它正在使用作业的目录(所有服务都将作业目录作为卷挂载在`/builds` ). 在这种情况下,服务将完成其工作,并且由于该工作未尝试与其连接,因此它不会失败. + +### What services are not for[](#what-services-are-not-for "Permalink") + +如前所述,此功能旨在提供**网络可访问的**服务. 数据库是此类服务的最简单示例. + +**注意:**服务功能并非旨在且不会将已定义的`services`映像中的任何软件添加到作业的容器中. + +例如,如果您在作业中定义了以下`services` ,则脚本**无法**使用`php` , `node`或`go`命令,因此该作业将失败: + +``` +job: + services: + - php:7 + - node:latest + - golang:1.10 + image: alpine:3.7 + script: + - php -v + - node -v + - go version +``` + +如果你需要有`php` , `node`和`go`供你的脚本,你应该: + +* 选择一个包含所有必需工具的现有 Docker 映像. +* 创建您自己的 Docker 映像,它将包含所有必需的工具,并在您的工作中使用它. + +### Accessing the services[](#accessing-the-services "Permalink") + +假设您需要一个 Wordpress 实例来测试与应用程序的某些 API 集成. + +然后,您可以在`.gitlab-ci.yml`使用例如[tutum / wordpress](https://hub.docker.com/r/tutum/wordpress/)图像: + +``` +services: + - tutum/wordpress:latest +``` + +如果未[指定服务别名](#available-settings-for-services) ,则在运行作业时,将启动`tutum/wordpress` ,您将可以从构建容器中使用以下两个主机名访问它: + +* `tutum-wordpress` +* `tutum__wordpress` + +**注意:**带下划线的主机名是 RFC 无效的,可能会导致第三方应用程序出现问题. + +服务主机名的默认别名是根据以下规则从其映像名称创建的: + +* 冒号后一切( `:` )被剥离. +* 将斜杠( `/` )替换为双下划线( `__` ),并创建主别名. +* 斜杠( `/` )替换为单破折号( `-` ),并创建了辅助别名(需要 GitLab Runner v1.1.0 或更高版本). + +要覆盖默认行为,可以[指定服务别名](#available-settings-for-services) . + +## Define `image` and `services` from `.gitlab-ci.yml`[](#define-image-and-services-from-gitlab-ciyml "Permalink") + +您可以简单地定义将用于所有作业的映像以及要在构建期间使用的服务列表: + +``` +default: + image: ruby:2.6 + + services: + - postgres:11.7 + + before_script: + - bundle install + +test: + script: + - bundle exec rake spec +``` + +图像名称必须采用以下格式之一: + +* `image: <image-name>` (同使用`<image-name>`与`latest`标签) +* `image: <image-name>:<tag>` +* `image: <image-name>@<digest>` + +还可以为每个作业定义不同的图像和服务: + +``` +default: + before_script: + - bundle install + +test:2.6: + image: ruby:2.6 + services: + - postgres:11.7 + script: + - bundle exec rake spec + +test:2.7: + image: ruby:2.7 + services: + - postgres:12.2 + script: + - bundle exec rake spec +``` + +或者,您可以传递一些[扩展](#extended-docker-configuration-options)的`image`和`services` [配置选项](#extended-docker-configuration-options) : + +``` +default: + image: + name: ruby:2.6 + entrypoint: ["/bin/bash"] + + services: + - name: my-postgres:11.7 + alias: db-postgres + entrypoint: ["/usr/local/bin/db-postgres"] + command: ["start"] + + before_script: + - bundle install + +test: + script: + - bundle exec rake spec +``` + +## Passing environment variables to services[](#passing-environment-variables-to-services "Permalink") + +您还可以传递自定义环境[变量,](../variables/README.html)以直接在`.gitlab-ci.yml`文件中微调 Docker `images`和`services` . 有关更多信息,请参见[自定义环境变量.](../variables/README.html#gitlab-ciyml-defined-variables) + +``` +# The following variables will automatically be passed down to the Postgres container +# as well as the Ruby container and available within each. +variables: + HTTPS_PROXY: "https://10.1.1.1:8090" + HTTP_PROXY: "https://10.1.1.1:8090" + POSTGRES_DB: "my_custom_db" + POSTGRES_USER: "postgres" + POSTGRES_PASSWORD: "example" + PGDATA: "/var/lib/postgresql/data" + POSTGRES_INITDB_ARGS: "--encoding=UTF8 --data-checksums" + +services: + - name: postgres:11.7 + alias: db + entrypoint: ["docker-entrypoint.sh"] + command: ["postgres"] + +image: + name: ruby:2.6 + entrypoint: ["/bin/bash"] + +before_script: + - bundle install + +test: + script: + - bundle exec rake spec +``` + +## Extended Docker configuration options[](#extended-docker-configuration-options "Permalink") + +在 GitLab 和 GitLab Runner 9.4 中引入. + +配置`image`或`services`条目时,可以使用字符串或地图作为选项: + +* 使用字符串作为选项时,它必须是要使用的映像的全名(如果要从 Docker Hub 以外的注册表中下载映像,则应包括注册表部分) +* 使用地图作为选项时,它必须至少包含`name`选项,该名称与用于字符串设置的图像名称相同 + +例如,以下两个定义相等: + +1. 使用字符串作为`image`和`services`的选项: + + ``` + image: "registry.example.com/my/image:latest" + + services: + - postgresql:9.4 + - redis:latest + ``` + +2. 使用地图作为`image`和`services`的选项. 必须使用`image:name` : + + ``` + image: + name: "registry.example.com/my/image:latest" + + services: + - name: postgresql:9.4 + - name: redis:latest + ``` + +### Available settings for `image`[](#available-settings-for-image "Permalink") + +在 GitLab 和 GitLab Runner 9.4 中引入. + +| Setting | Required | GitLab 版本 | Description | +| --- | --- | --- | --- | +| `name` | 是的,当与任何其他选项一起使用时 | 9.4 | 应使用的图像的全名. 如果需要,它应包含注册表部分. | +| `entrypoint` | no | 9.4 | 应该作为容器的入口点执行的命令或脚本. 创建容器时,它将转换为 Docker 的`--entrypoint`选项. 语法类似于[`Dockerfile`的`ENTRYPOINT`](https://s0docs0docker0com.icopy.site/engine/reference/builder/)指令,其中每个 shell 令牌是数组中的单独字符串. | + +### Available settings for `services`[](#available-settings-for-services "Permalink") + +在 GitLab 和 GitLab Runner 9.4 中引入. + +| Setting | Required | GitLab 版本 | Description | +| --- | --- | --- | --- | +| `name` | 是的,当与任何其他选项一起使用时 | 9.4 | Full name of the image that should be used. It should contain the Registry part if needed. | +| `entrypoint` | no | 9.4 | 应该作为容器的入口点执行的命令或脚本. 创建容器时,它将转换为 Docker 的`--entrypoint`选项. 语法类似于[`Dockerfile`的`ENTRYPOINT`](https://s0docs0docker0com.icopy.site/engine/reference/builder/)指令,其中每个 shell 令牌是数组中的单独字符串. | +| `command` | no | 9.4 | 应该用作容器命令的命令或脚本. 它将转换为映像名称后传递给 Docker 的参数. 语法类似于[`Dockerfile`的`CMD`](https://s0docs0docker0com.icopy.site/engine/reference/builder/)指令,其中每个 shell 令牌是数组中的单独字符串. | +| `alias` | no | 9.4 | 可用于从作业的容器访问服务的其他别名. 请阅读[访问服务](#accessing-the-services)以获取更多信息. | + +**注意:** GitLab Runner 12.8 [引入](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2229)了对 Kubernetes 执行器的别名支持,并且仅对 Kubernetes 1.7 或更高版本可用. + +### Starting multiple services from the same image[](#starting-multiple-services-from-the-same-image "Permalink") + +在 GitLab 和 GitLab Runner 9.4 中引入. 阅读有关[扩展配置选项的](#extended-docker-configuration-options)更多信息. + +在使用新的扩展 Docker 配置选项之前,以下配置将无法正常工作: + +``` +services: + - mysql:latest + - mysql:latest +``` + +The Runner would start two containers using the `mysql:latest` image, but both of them would be added to the job’s container with the `mysql` alias based on the [default hostname naming](#accessing-the-services). This would end with one of the services not being accessible. + +在新的扩展 Docker 配置选项之后,以上示例将如下所示: + +``` +services: + - name: mysql:latest + alias: mysql-1 + - name: mysql:latest + alias: mysql-2 +``` + +Runner 仍将使用`mysql:latest`映像启动两个容器,但是现在每个容器也可以使用`.gitlab-ci.yml`文件中配置的别名进行访问. + +### Setting a command for the service[](#setting-a-command-for-the-service "Permalink") + +在 GitLab 和 GitLab Runner 9.4 中引入. 阅读有关[扩展配置选项的](#extended-docker-configuration-options)更多信息. + +假设您有一个`super/sql:latest`映像,其中包含一些 SQL 数据库,并且想将其用作您的工作服务. 我们还假设该映像在启动容器时不会启动数据库进程,并且用户需要手动使用`/usr/bin/super-sql run`作为命令来启动数据库. + +在使用新的扩展 Docker 配置选项之前,您需要基于`super/sql:latest`映像创建自己的映像,添加默认命令,然后在作业的配置中使用它,例如: + +``` +# my-super-sql:latest image's Dockerfile + +FROM super/sql:latest +CMD ["/usr/bin/super-sql", "run"] +``` + +``` +# .gitlab-ci.yml + +services: + - my-super-sql:latest +``` + +在新的扩展 Docker 配置选项之后,您现在可以简单地在`.gitlab-ci.yml`设置`command` ,例如: + +``` +# .gitlab-ci.yml + +services: + - name: super/sql:latest + command: ["/usr/bin/super-sql", "run"] +``` + +如您所见, `command`的语法类似于[Dockerfile 的`CMD`](https://s0docs0docker0com.icopy.site/engine/reference/builder/) . + +### Overriding the entrypoint of an image[](#overriding-the-entrypoint-of-an-image "Permalink") + +在 GitLab 和 GitLab Runner 9.4 中引入. 阅读有关[扩展配置选项的](#extended-docker-configuration-options)更多信息. + +在显示可用的入口点覆盖方法之前,让我们简要介绍一下 Runner 如何启动以及如何将 Docker 映像用于 CI 作业中使用的容器: + +1. Runner 使用定义的入口点启动 Docker 容器( `Dockerfile`中的默认值,该文件可能会在`.gitlab-ci.yml`覆盖) +2. 跑步者将自己附加到正在运行的容器上. +3. 跑步者准备一个脚本( [`before_script`](../yaml/README.html#before_script-and-after_script) , [`script`](../yaml/README.html#script)和[`after_script`](../yaml/README.html#before_script-and-after_script)的组合). +4. 运行程序将脚本发送到容器的外壳 STDIN 并接收输出. + +要覆盖 Docker 映像的入口点,建议的解决方案是在`.gitlab-ci.yml`定义一个空`entrypoint` `.gitlab-ci.yml` ,以便 Runner 不会启动无用的 shell 层. 但是,这不适用于所有 Docker 版本,因此您应检查 Runner 使用的是哪个版本. 特别: + +* 如果使用 Docker 17.06 或更高版本,则`entrypoint`可以设置为空值. +* 如果使用 Docker 17.03 或更早版本,则`entrypoint`可以设置为`/bin/sh -c` , `/bin/bash -c`或映像中可用的等效 shell. + +`image:entrypoint`的语法类似于[Dockerfile 的`ENTRYPOINT`](https://s0docs0docker0com.icopy.site/engine/reference/builder/) . + +假设您有一个`super/sql:experimental`映像,其中包含一些 SQL 数据库,并且您想将其用作工作的基础映像,因为您想使用此数据库二进制文件执行一些测试. 我们还假设此映像是使用`/usr/bin/super-sql run`作为入口点配置的. 这意味着在启动没有其他选项的容器时,它将运行数据库的进程,而 Runner 希望映像没有入口点,或者入口点已准备好启动 Shell 命令. + +使用扩展的 Docker 配置选项,而不是基于`super/sql:experimental`创建自己的映像,将`ENTRYPOINT`设置为 shell,然后在 CI 作业中使用新映像,您现在只需在`.gitlab-ci.yml`定义一个`entrypoint` `.gitlab-ci.yml` . + +**对于 Docker 17.06+:** + +``` +image: + name: super/sql:experimental + entrypoint: [""] +``` + +**对于 Docker = <17.03:** + +``` +image: + name: super/sql:experimental + entrypoint: ["/bin/sh", "-c"] +``` + +## Define image and services in `config.toml`[](#define-image-and-services-in-configtoml "Permalink") + +查找`[runners.docker]`部分: + +``` +[runners.docker] + image = "ruby:latest" + services = ["mysql:latest", "postgres:latest"] +``` + +以这种方式定义的图像和服务将添加到该运行程序运行的所有作业中. + +## Define an image from a private Container Registry[](#define-an-image-from-a-private-container-registry "Permalink") + +要访问私有容器注册表,GitLab Runner 进程可以使用: + +* [静态定义的凭证](#using-statically-defined-credentials) . 也就是说,特定注册表的用户名和密码. +* [凭证存储](#using-credentials-store) . 有关更多信息,请参阅[相关的 Docker 文档](https://docs.docker.com/engine/reference/commandline/login/#credentials-store) . +* [凭证助手](#using-credential-helpers) . 有关更多信息,请参阅[相关的 Docker 文档](https://docs.docker.com/engine/reference/commandline/login/#credential-helpers) . + +为了定义应该使用哪个,GitLab Runner 进程按以下顺序读取配置: + +* `DOCKER_AUTH_CONFIG`变量提供为: + * `.gitlab-ci.yml` [变量](../variables/README.html#gitlab-cicd-environment-variables) . + * 项目的变量存储在项目的**"设置">" CI / CD"**页面上. +* Runner 的`config.toml`中提供了`DOCKER_AUTH_CONFIG`变量作为环境变量. +* `config.json`文件放置在运行 GitLab Runner 进程的用户的`$HOME/.docker`目录中. 如果提供了`--user`标志以非特权用户身份运行 GitLab Runner 子进程,则将使用 GitLab Runner 主进程用户的主目录. + +**注意:** GitLab Runner **仅从** `config.toml`读取此配置,并且如果它是作为环境变量提供的,则忽略它. 这是因为 GitLab Runner **仅**使用`config.toml`配置,并且不会在运行时内插**任何**环境变量. + +### Requirements and limitations[](#requirements-and-limitations "Permalink") + +* 此功能需要 GitLab Runner **1.8**或更高版本. +* 对于**> = 0.6,<1.8 的** GitLab Runner 版本**,**部分支持使用私有注册表,这要求在运行者的主机上手动配置凭据. 如果要使用私人注册表,建议将 Runner 至少升级到**1.8**版. +* 在 GitLab Runner 13.1 和更高版本中适用于[Kubernetes 执行器](https://docs.gitlab.com/runner/executors/kubernetes.html) . + +### Using statically-defined credentials[](#using-statically-defined-credentials "Permalink") + +您可以采用两种方法来访问私有注册表. 两者都需要使用适当的身份验证信息设置环境变量`DOCKER_AUTH_CONFIG` . + +1. 每个作业:要配置一个作业以访问专用注册表,请添加`DOCKER_AUTH_CONFIG`作为作业变量. +2. 每个运行者:要配置 Runner 以便其所有作业都可以访问私有注册表,请在 Runner 的配置中将`DOCKER_AUTH_CONFIG`添加到环境中. + +请参阅下面的示例. + +#### Determining your `DOCKER_AUTH_CONFIG` data[](#determining-your-docker_auth_config-data "Permalink") + +例如,假设您要使用`registry.example.com:5000/private/image:latest`映像,该映像是私有映像,需要您登录到私有容器注册表. + +我们还假设这些是登录凭据: + +| Key | Value | +| --- | --- | +| registry | `registry.example.com:5000` | +| username | `my_username` | +| password | `my_password` | + +有两种方法可以确定`DOCKER_AUTH_CONFIG`的值: + +* **第一种方法-**在本地计算机上进行`docker login` : + + ``` + docker login registry.example.com:5000 --username my_username --password my_password + ``` + + 然后复制`~/.docker/config.json` . + + 如果您不需要从计算机访问注册表,则可以执行`docker logout` : + + ``` + docker logout registry.example.com:5000 + ``` + +* **第二种方式-**在某些设置中,Docker 客户端可能会使用可用的系统密钥存储区来存储`docker login`的结果. 在这种情况下,无法读取`~/.docker/config.json` ,因此您将需要准备所需的`${username}:${password}` base64 编码版本,并手动创建 Docker 配置 JSON. 打开一个终端并执行以下命令: + + ``` + # Note the use of "-n" - it prevents encoding a newline in the password. + echo -n "my_username:my_password" | base64 + + # Example output to copy + bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ= + ``` + + 创建 Docker JSON 配置内容,如下所示: + + ``` + { "auths": { "registry.example.com:5000": { "auth": "(Base64 content from above)" } } } + ``` + +#### Configuring a job[](#configuring-a-job "Permalink") + +要配置具有对`registry.example.com:5000`访问权限的单个作业,请按照下列步骤操作: + +1. 创建一个[变量](../variables/README.html#gitlab-cicd-environment-variables) `DOCKER_AUTH_CONFIG` ,并将 Docker 配置文件的内容作为值: + + ``` + { "auths": { "registry.example.com:5000": { "auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=" } } } + ``` + +2. 现在,您可以使用`.gitlab-ci.yml`文件中`image`和/或`services`中定义的`registry.example.com:5000`任何私有图像: + + ``` + image: registry.example.com:5000/namespace/image:tag + ``` + + 在上面的例子,GitLab 转轮会看`registry.example.com:5000`用于图像`namespace/image:tag` . + +您可以根据需要添加任意数量的注册表配置,如上所述,将更多注册表添加到`"auths"`哈希中. + +**注意:** Runner 到处都需要完整的`hostname:port`组合,以使其与`DOCKER_AUTH_CONFIG`相匹配. 例如,如果`registry.example.com:5000/namespace/image:tag`中指定`.gitlab-ci.yml` ,则`DOCKER_AUTH_CONFIG`还必须指定`registry.example.com:5000` . 仅指定`registry.example.com`将不起作用. + +### Configuring a Runner[](#configuring-a-runner "Permalink") + +如果您有许多访问同一注册表的管道,最好在运行程序级别设置注册表访问. 这使管道作者仅通过在适当的运行程序上运行作业即可访问私有注册表. 这也使注册表更改和凭据轮换更加简单. + +当然,这意味着该运行程序上的任何作业都可以使用相同的特权访问注册表,即使在整个项目中也是如此. 如果需要控制对注册表的访问,则需要确保控制对运行器的访问. + +要将`DOCKER_AUTH_CONFIG`添加到运行器: + +1. 修改 Runner 的`config.toml`文件,如下所示: + + ``` + [[runners]] + environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"registry.example.com:5000\":{\"auth\":\"bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=\"}}}"] + ``` + +2. 重新启动 Runner 服务. + +**注意:** `DOCKER_AUTH_CONFIG`数据中包含的双引号必须使用反斜杠转义. 这样可以防止将它们解释为 TOML.**注意:** `environment`选项是一个列表. 因此,您的跑步者可能已有条目,您应该将其添加到列表中,而不是替换它. + +### Using Credentials Store[](#using-credentials-store "Permalink") + +> 在 GitLab Runner 9.5 中添加了对使用凭据存储的支持. + +要配置凭据存储,请按照下列步骤操作: + +1. 要使用凭据存储,您需要一个外部帮助程序来与特定的钥匙串或外部存储进行交互. 确保 GitLab Runner `$PATH`有可用的帮助程序. + +2. 使 GitLab Runner 使用它. 有两种方法可以完成此操作. 要么: + + * 创建一个[变量](../variables/README.html#gitlab-cicd-environment-variables) `DOCKER_AUTH_CONFIG` ,并将 Docker 配置文件的内容作为值: + + ``` + { "credsStore": "osxkeychain" } + ``` + + * 或者,如果您正在运行自我管理的`${GITLAB_RUNNER_HOME}/.docker/config.json` ,请将上面的 JSON 添加到`${GITLAB_RUNNER_HOME}/.docker/config.json` . GitLab Runner 将读取此配置文件,并将使用此特定存储库所需的帮助程序. + +**注意:** `credsStore`用于访问所有注册表. 如果要同时使用私有注册表中的映像和 DockerHub 中的公共映像,则从 DockerHub 提取将失败,因为 Docker 守护程序将尝试对**所有**注册表使用相同的凭据. + +### Using Credential Helpers[](#using-credential-helpers "Permalink") + +> 在 GitLab Runner 12.0 中添加了对使用凭据助手的支持 + +作为示例,假设您要使用`aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest`映像,该映像是私有的,需要您登录到私有容器注册表. + +要配置`aws_account_id.dkr.ecr.region.amazonaws.com`访问`aws_account_id.dkr.ecr.region.amazonaws.com` ,请按照以下步骤操作: + +1. 确保`docker-credential-ecr-login`在 GitLab Runner 的`$PATH`可用. + +2. 具有以下任何[AWS 凭证设置](https://github.com/awslabs/amazon-ecr-credential-helper#aws-credentials) . 确保 GitLab Runner 可以访问凭据. + +3. 使 GitLab Runner 使用它. 有两种方法可以完成此操作. 要么: + + * 创建一个[变量](../variables/README.html#gitlab-cicd-environment-variables) `DOCKER_AUTH_CONFIG` ,并将 Docker 配置文件的内容作为值: + + ``` + { "credHelpers": { "aws_account_id.dkr.ecr.region.amazonaws.com": "ecr-login" } } + ``` + + 这会将 Docker 配置为对特定注册表使用凭据帮助器. + + or + + ``` + { "credsStore": "ecr-login" } + ``` + + 这会将 Docker 配置为对所有 Amazon ECR 注册表使用凭证帮助器. + + * 或者,如果您正在运行自我管理的`${GITLAB_RUNNER_HOME}/.docker/config.json` ,请将上面的 JSON 添加到`${GITLAB_RUNNER_HOME}/.docker/config.json` . GitLab Runner 将读取此配置文件,并将使用此特定存储库所需的帮助程序. + +4. 现在,您可以使用`.gitlab-ci.yml`文件中`image`和/或`services`中定义的`aws_account_id.dkr.ecr.region.amazonaws.com`任何私有图像: + + ``` + image: aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest + ``` + + 在上面的示例中,GitLab Runner 将查看`aws_account_id.dkr.ecr.region.amazonaws.com`中的图像`private/image:latest` . + +您可以根据需要添加`"credHelpers"`数量的注册表配置,如上所述,将更多注册表添加到`"credHelpers"`哈希中. + +## Configuring services[](#configuring-services "Permalink") + +许多服务接受环境变量,这些变量使您可以根据环境轻松更改数据库名称或设置帐户名称. + +GitLab Runner 0.5.0 及更高版本将所有 YAML 定义的变量传递到创建的服务容器. + +For all possible configuration variables check the documentation of each image provided in their corresponding Docker hub page. + +**注意:**所有变量都将传递到所有服务容器. 它并非旨在区分哪个变量应该放在哪里. + +### PostgreSQL service example[](#postgresql-service-example "Permalink") + +请参阅有关将[PostgreSQL 用作服务](../services/postgres.html)的特定文档. + +### MySQL service example[](#mysql-service-example "Permalink") + +请参阅有关将[MySQL 用作服务](../services/mysql.html)的特定文档. + +## How Docker integration works[](#how-docker-integration-works "Permalink") + +以下是 Docker 在作业期间执行的步骤的高级概述. + +1. 创建任何服务容器: `mysql` , `postgresql` , `mongodb` , `redis` . +2. 创建缓存容器以存储`config.toml`和构建映像的`Dockerfile`中定义的所有卷(如上例中的`ruby:2.6` ). +3. 创建构建容器并将任何服务容器链接到构建容器. +4. 启动构建容器并将作业脚本发送到该容器. +5. 运行作业脚本. +6. 检出代码: `/builds/group-name/project-name/` . +7. 运行`.gitlab-ci.yml`定义的任何步骤. +8. 检查构建脚本的退出状态. +9. 删除构建容器和所有创建的服务容器. + +## How to debug a job locally[](#how-to-debug-a-job-locally "Permalink") + +**注意:**以下命令在没有 root 特权的情况下运行. 您应该能够使用常规用户帐户运行 Docker. + +首先从创建一个名为`build_script`的文件`build_script` : + +``` +cat <<EOF > build_script +git clone https://gitlab.com/gitlab-org/gitlab-runner.git /builds/gitlab-org/gitlab-runner +cd /builds/gitlab-org/gitlab-runner +make EOF +``` + +在这里,我们以包含 Makefile 的 GitLab Runner 存储库为例,因此运行`make`将执行 Makefile 中定义的命令. 您的里程可能会有所不同,所以不是`make`你可以运行它是特定于项目的命令. + +然后创建一些服务容器: + +``` +docker run -d --name service-mysql mysql:latest +docker run -d --name service-postgres postgres:latest +``` + +这将创建两个服务容器,分别名为`service-mysql`和`service-postgres` ,它们分别使用最新的 MySQL 和 PostgreSQL 映像. 它们都将在后台( `-d` )运行. + +最后,通过执行我们之前创建的`build_script`文件来创建构建容器: + +``` +docker run --name build -i --link=service-mysql:mysql --link=service-postgres:postgres ruby:2.6 /bin/bash < build_script +``` + +上面的命令将创建一个名为`build`的容器,该容器是从`ruby:2.6`镜像派生的,并且有两个链接到它的服务. 使用 STDIN 将`build_script`通过管道传输到 bash 解释器,然后 bash 解释器将在`build`容器中执行`build_script` . + +完成测试后,不再需要这些容器时,可以使用以下方法删除它们: + +``` +docker rm -f -v build service-mysql service-postgres +``` + +这将强制( `-f` )删除`build`容器,两个服务容器以及随容器创建而创建的所有卷( `-v` ). \ No newline at end of file diff --git a/docs/219.md b/docs/219.md new file mode 100644 index 0000000000000000000000000000000000000000..f556d8c15e2fee018f8927a7f3bba8ab1e947637 --- /dev/null +++ b/docs/219.md @@ -0,0 +1,88 @@ +# Building images with kaniko and GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/docker/using_kaniko.html](https://docs.gitlab.com/ee/ci/docker/using_kaniko.html) + +* [Requirements](#requirements) +* [Building a Docker image with kaniko](#building-a-docker-image-with-kaniko) +* [Using a registry with a custom certificate](#using-a-registry-with-a-custom-certificate) +* [Video walkthrough of a working example](#video-walkthrough-of-a-working-example) + +# Building images with kaniko and GitLab CI/CD[](#building-images-with-kaniko-and-gitlab-cicd "Permalink") + +在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45512) . 需要 GitLab Runner 11.2 及更高版本. + +[kaniko](https://github.com/GoogleContainerTools/kaniko)是从容器或 Kubernetes 集群内部的 Dockerfile 构建容器映像的工具. + +kaniko 使用[Docker-in-Docker 构建](using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor)方法解决了两个问题: + +* Docker-in-Docker 需要[特权模式](https://s0docs0docker0com.icopy.site/engine/reference/run/)才能运行,这是一个重大的安全问题. +* Docker-in-Docker 通常会导致性能下降,并且可能会非常慢. + +## Requirements[](#requirements "Permalink") + +为了在 GitLab 中使用 kaniko,需要使用以下执行程序之一的[GitLab Runner](https://docs.gitlab.com/runner/) : + +* [Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html). +* [Docker](https://docs.gitlab.com/runner/executors/docker.html). +* [Docker Machine](https://docs.gitlab.com/runner/executors/docker_machine.html). + +## Building a Docker image with kaniko[](#building-a-docker-image-with-kaniko "Permalink") + +使用 kaniko 和 GitLab CI / CD 构建映像时,应注意一些重要细节: + +* 推荐使用 kaniko 调试映像( `gcr.io/kaniko-project/executor:debug` ),因为它具有外壳,并且该映像与 GitLab CI / CD 一起使用时需要外壳. +* 入口点将需要被[覆盖](using_docker_images.html#overriding-the-entrypoint-of-an-image) ,否则构建脚本将无法运行. +* 需要使用所需容器注册表的身份验证信息创建一个 Docker `config.json`文件. + +In the following example, kaniko is used to: + +1. 构建一个 Docker 镜像 +2. 然后将其推送到[GitLab 容器注册表](../../user/packages/container_registry/index.html) . + +仅当按下标签时作业才会运行. 使用从 GitLab CI / CD 提供的[环境变量中](../variables/README.html#predefined-environment-variables)获取的所需 GitLab 容器注册表凭据在`/kaniko/.docker`下创建一个`config.json`文件. + +在最后一步中,kaniko 使用项目根目录下的`Dockerfile` ,构建 Docker 映像并将其推送到项目的 Container Registry,同时使用 Git 标签对其进行标记: + +``` +build: + stage: build + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] + script: + - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json + - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG + only: + - tags +``` + +## Using a registry with a custom certificate[](#using-a-registry-with-a-custom-certificate "Permalink") + +尝试推送到使用由自定义 CA 签名的证书的 Docker 注册表时,您可能会遇到以下错误: + +``` +$ /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --no-push +INFO[0000] Downloading base image registry.gitlab.example.com/group/docker-image +error building image: getting stage builder for stage 0: Get https://registry.gitlab.example.com/v2/: x509: certificate signed by unknown authority +``` + +可以通过将您的 CA 证书添加到 kaniko 证书存储区来解决: + +``` + before_script: + - mkdir -p /kaniko/.docker + - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json + - | + echo "-----BEGIN CERTIFICATE----- + ... + -----END CERTIFICATE-----" >> /kaniko/ssl/certs/additional-ca-cert-bundle.crt +``` + +## Video walkthrough of a working example[](#video-walkthrough-of-a-working-example "Permalink") + +[在 GitLab](https://www.youtube.com/watch?v=d96ybcELpFs)视频[上使用 Kaniko](https://www.youtube.com/watch?v=d96ybcELpFs)的[最低权限容器构建](https://www.youtube.com/watch?v=d96ybcELpFs)是对[Kaniko Docker Build](https://gitlab.com/guided-explorations/containers/kaniko-docker-build) Guided Exploration 项目管道的演练. 经过测试: + +* [GitLab.com Shared Runners](../../user/gitlab_com/index.html#shared-runners) +* [The Kubernetes Runner executor](https://docs.gitlab.com/runner/executors/kubernetes.html) + +可以将示例复制到您自己的组或实例中进行测试. 项目页面上提供了有关演示其他 GitLab CI 模式的更多详细信息. \ No newline at end of file diff --git a/docs/220.md b/docs/220.md new file mode 100644 index 0000000000000000000000000000000000000000..713bd405ff07c5ae5fc3fdffa9b138877586e463 --- /dev/null +++ b/docs/220.md @@ -0,0 +1,893 @@ +# GitLab CI/CD environment variables + +> 原文:[https://docs.gitlab.com/ee/ci/variables/README.html](https://docs.gitlab.com/ee/ci/variables/README.html) + +* [Predefined environment variables](#predefined-environment-variables) + * [Use predefined environment variables](#use-predefined-environment-variables) +* [Custom environment variables](#custom-environment-variables) + * [Create a custom variable in `.gitlab-ci.yml`](#create-a-custom-variable-in-gitlab-ciyml) + * [Create a custom variable in the UI](#create-a-custom-variable-in-the-ui) + * [Custom environment variables of type Variable](#custom-environment-variables-of-type-variable) + * [Custom environment variables of type File](#custom-environment-variables-of-type-file) + * [Mask a custom variable](#mask-a-custom-variable) + * [Masked variable requirements](#masked-variable-requirements) + * [Protect a custom variable](#protect-a-custom-variable) + * [Custom variables validated by GitLab](#custom-variables-validated-by-gitlab) +* [Syntax of environment variables in job scripts](#syntax-of-environment-variables-in-job-scripts) + * [Bash](#bash) + * [PowerShell](#powershell) + * [Windows Batch](#windows-batch) + * [List all environment variables](#list-all-environment-variables) +* [`.gitlab-ci.yml` defined variables](#gitlab-ciyml-defined-variables) +* [Group-level environment variables](#group-level-environment-variables) +* [Instance-level CI/CD environment variables](#instance-level-cicd-environment-variables) + * [Enable or disable UI interface for instance-level CI/CD variables](#enable-or-disable-ui-interface-for-instance-level-cicd-variables) +* [Inherit environment variables](#inherit-environment-variables) +* [Priority of environment variables](#priority-of-environment-variables) +* [Unsupported variables](#unsupported-variables) +* [Where variables can be used](#where-variables-can-be-used) +* [Advanced use](#advanced-use) + * [Limit the environment scopes of environment variables](#limit-the-environment-scopes-of-environment-variables) + * [Deployment environment variables](#deployment-environment-variables) + * [Auto DevOps environment variables](#auto-devops-environment-variables) + * [Override a variable by manually running a pipeline](#override-a-variable-by-manually-running-a-pipeline) +* [Environment variables expressions](#environment-variables-expressions) + * [Syntax of environment variable expressions](#syntax-of-environment-variable-expressions) + * [Storing regular expressions in variables](#storing-regular-expressions-in-variables) +* [Debug logging](#debug-logging) +* [Video walkthrough of a working example](#video-walkthrough-of-a-working-example) + +# GitLab CI/CD environment variables[](#gitlab-cicd-environment-variables "Permalink") + +环境变量是一个动态命名的值,它可以影响正在运行的进程在操作系统上的行为方式. + +环境变量是进程在其中运行的环境的一部分. 例如,正在运行的进程可以查询`TEMP`环境变量的值以发现合适的位置来存储临时文件,或者为可以在不同脚本中重用的数据库定义`URL` . + +变量对于在 GitLab CI / CD 中自定义作业很有用. 使用变量时,不必对值进行硬编码. + +> 有关高级使用 GitLab CI / CD 的更多信息: +> +> * 由 GitLab 工程师共享的这[7 种高级 GitLab CI 工作流程黑客,](https://about.gitlab.com/webcast/7cicd-hacks/)可以更快地提高生产力. +> * 了解 Cloud Native Computing Foundation(CNCF)如何通过 GitLab CI / CD [消除](https://about.gitlab.com/customers/cncf/)许多云提供商之间管理项目[的复杂性](https://about.gitlab.com/customers/cncf/) . + +## Predefined environment variables[](#predefined-environment-variables "Permalink") + +GitLab CI / CD 具有一组[默认的预定义变量](predefined_variables.html) ,您可以使用它们而无需任何其他说明. 您可以呼叫问题编号,用户名,分支名称,管道和提交 ID 等. + +GitLab 为 Runner 的本地环境提供了预定义的环境变量. + +GitLab 读取`.gitlab-ci.yml`文件,并将信息发送到 Runner,在此处公开变量. 然后,运行程序运行脚本命令. + +### Use predefined environment variables[](#use-predefined-environment-variables "Permalink") + +您可以选择现有的预定义变量之一,以由 Runner 输出. + +本示例说明如何使用预定义变量`CI_JOB_STAGE`输出作业的阶段. + +在您的`.gitlab-ci.yml`文件中,从脚本中调用变量. 确保使用正确的[语法](#syntax-of-environment-variables-in-job-scripts) . + +``` +test_variable: + stage: test + script: + - echo $CI_JOB_STAGE +``` + +在这种情况下,跑步者输出工作`test_variable`的`stage` ,即`test` : + +[![Output `$CI_JOB_STAGE`](img/b6a9c5aa2e348263baf61cb961ac802f.png)](img/ci_job_stage_output_example.png) + +再举一个例子,假设您使用自己的 GitLab 实例,并且想知道 GitLab 页面在哪个域下提供服务. 您可以通过在脚本中使用预定义变量`$CI_PAGES_DOMAIN`来调用它: + +``` +pages: + script: + - ... + - echo $CI_PAGES_DOMAIN +``` + +对于 GitLab.com 用户,输出将为`gitlab.io` . 对于您的私有实例,输出将是您的系统管理员定义的任何内容. + +## Custom environment variables[](#custom-environment-variables "Permalink") + +当需要特定的自定义环境变量时,可以[在 UI](#create-a-custom-variable-in-the-ui)中[,API](../../api/project_level_variables.html)中或直接[在`.gitlab-ci.yml`文件中进行设置](#create-a-custom-variable-in-gitlab-ciyml) . + +每当管道运行时,Runner 就会使用这些变量. 您还[可以手动覆盖特定管道的变量值](../pipelines/index.html#specifying-variables-when-running-manual-jobs) . + +变量有两种类型: **Variable**和**File** . 您无法在`.gitlab-ci.yml`文件中设置类型,但可以在 UI 和 API 中进行设置. + +### Create a custom variable in `.gitlab-ci.yml`[](#create-a-custom-variable-in-gitlab-ciyml "Permalink") + +要创建自定义`env_var`在可变[`.gitlab-ci.yml`](../yaml/README.html#variables)文件中,定义下的变量/值对`variables` : + +``` +variables: + TEST: "HELLO WORLD" +``` + +然后,您可以在脚本中调用其值: + +``` + script: + - echo "$TEST" +``` + +有关更多详细信息,请参见[`.gitlab-ci.yml`定义的变量](#gitlab-ciyml-defined-variables) . + +### Create a custom variable in the UI[](#create-a-custom-variable-in-the-ui "Permalink") + +在用户界面中,您可以添加或更新自定义环境变量: + +1. 转到项目的**"设置">" CI / CD",**然后展开" **变量"**部分. +2. 单击**添加变量**按钮. 在" **添加变量**模式"中,填写详细信息: + + * **密钥** :必须是一行,没有空格,只能使用字母,数字或`_` . + * **价值** :无限制. + * **Type**: `File` or `Variable`. + * **环境范围** : `All`或特定环境. + * **保护变量** (可选):如果选中,则该变量将仅在在受保护的分支或标签上运行的管道中可用. + * **屏蔽变量** (可选):如果选中,则变量的**值**将在作业日志中被屏蔽. 如果该值不满足[屏蔽要求,](#masked-variable-requirements)则变量将无法保存. + +创建变量后,您可以通过点击 **编辑**按钮. + +设置变量后,请从`.gitlab-ci.yml`文件中调用它: + +``` +test_variable: + stage: test + script: + - echo $CI_JOB_STAGE # calls a predefined variable + - echo $TEST # calls a custom variable of type `env_var` + - echo $GREETING # calls a custom variable of type `file` that contains the path to the temp file + - cat $GREETING # the temp file itself contains the variable value +``` + +输出将是: + +[![Output custom variable](img/4401376aa4e3f3764851b2dbb25f6f2e.png)](img/custom_variables_output.png) + +### Custom environment variables of type Variable[](#custom-environment-variables-of-type-variable "Permalink") + +在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46806) . + +对于类型为**Variable 的变量** ,Runner 会创建一个环境变量,该环境变量将键用作名称,并将值用作值. + +有[一些](#custom-variables-validated-by-gitlab)这种类型的[预定义变量](#custom-variables-validated-by-gitlab) ,可以进一步验证. 它们在您在 UI 中添加或更新变量时出现. + +### Custom environment variables of type File[](#custom-environment-variables-of-type-file "Permalink") + +在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46806) . + +对于**File**类型的变量,Runner 创建一个环境变量,该环境变量使用键作为名称. 对于该值,Runner 将变量值写入临时文件并使用此路径. + +您可以使用诸如[AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)和[`kubectl`](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#the-kubeconfig-environment-variable)类[的](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)工具通过使用**File** type 变量来自定义配置. + +过去,常见的模式是读取 CI 变量的值,将其保存在文件中,然后在脚本中使用新创建的文件: + +``` +# Read certificate stored in $KUBE_CA_PEM variable and save it in a new file +echo "$KUBE_CA_PEM" > "$(pwd)/kube.ca.pem" +# Pass the newly created file to kubectl +kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$(pwd)/kube.ca.pem" +``` + +代替此,您可以使用**文件**类型变量. 例如,如果您具有以下变量: + +* 类型为**Variable** : `KUBE_URL` **变量** ,其值为`https://example.com` . +* 类型为**File** : `KUBE_CA_PEM`变量,其值为证书. + +您可以从`.gitlab-ci.yml`调用它们,如下所示: + +``` +kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$KUBE_CA_PEM" +``` + +### Mask a custom variable[](#mask-a-custom-variable "Permalink") + +在 GitLab 11.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/13784) + +可以屏蔽变量,以便将变量的值隐藏在作业日志中. + +要屏蔽变量: + +1. 转到**设置> CI / CD** . +2. 展开**变量**部分. +3. 在您要保护的变量旁边,点击**编辑** . +4. 选择**掩码变量**复选框. +5. Click **更新变量**. + +#### Masked variable requirements[](#masked-variable-requirements "Permalink") + +变量的值必须: + +* 在一行中. +* 至少要包含 8 个字符. +* 不是预定义或自定义环境变量. +* 仅由 Base64 字母(RFC4648)中的字符组成. [在 GitLab 12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/63043)和更高版本中, `@`和`:`也是有效值. + +您不能屏蔽不满足这些要求的变量. + +### Protect a custom variable[](#protect-a-custom-variable "Permalink") + +在 GitLab 9.3 中引入. + +变量可以被保护. 受保护的变量将安全地传递到仅在[受保护的分支](../../user/project/protected_branches.html)或[受保护的标签](../../user/project/protected_tags.html)上运行的管道. 其他管道不获取受保护的变量. + +要保护变量: + +1. 转到**设置> CI / CD** . +2. 展开**变量**部分. +3. 在您要保护的变量旁边,点击**编辑** . +4. 选择**保护变量**复选框. +5. Click **更新变量**. + +该变量可用于所有后续管道. 受保护的变量只能由拥有[维护者权限的](../../user/permissions.html#project-members-permissions)项目成员更新或查看. + +### Custom variables validated by GitLab[](#custom-variables-validated-by-gitlab "Permalink") + +UI 中列出了一些变量,因此您可以更快地选择它们. GitLab 会验证这些变量的值,以确保它们的格式正确. + +| Variable | 允许值 | 引入 | +| --- | --- | --- | +| `AWS_ACCESS_KEY_ID` | 20 个字符:字母,数字 | 12.10 | +| `AWS_DEFAULT_REGION` | Any | 12.10 | +| `AWS_SECRET_ACCESS_KEY` | 40 个字符:字母,数字,特殊字符 | 12.10 | + +**注意:**存储凭据时,会涉及安全性. 例如,如果您使用的是 AWS 密钥,请遵循其[最佳做法](https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html) . + +## Syntax of environment variables in job scripts[](#syntax-of-environment-variables-in-job-scripts "Permalink") + +所有变量都在构建环境中设置为环境变量,并且可以使用用于访问此类变量的常规方法来访问它们. 在大多数情况下, `bash`或`sh`用于执行作业脚本. + +要访问环境变量,请为 Runner's [shell](https://docs.gitlab.com/runner/executors/)使用语法. + +| Shell | Usage | +| --- | --- | +| bash/sh | `$variable` | +| PowerShell | `$env:variable` (主`$env:variable` )或`$variable` | +| Windows 批处理 | `%variable%` | + +### Bash[](#bash "Permalink") + +要在**bash 中**访问环境变量,请在变量名前加上( `$` ): + +``` +job_name: + script: + - echo $CI_JOB_ID +``` + +### PowerShell[](#powershell "Permalink") + +要访问**Windows PowerShell**环境中的环境变量,请在变量名前加上( `$env:` . 对于由 GitLab CI 设置的环境变量,包括由[`variables`](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/ci/yaml/README.md#variables)参数设置的环境[`variables`](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/ci/yaml/README.md#variables) ,还可以通过在[GitLab Runner 1.0.0 开始](https://gitlab.com/gitlab-org/gitlab-runner/-/commit/abc44bb158008cd3a49c0d8173717c38dadb29ae#47afd7e8f12afdb8f0246262488f24e6dd071a22) ,通过在变量名称前加上( `$` )来访问它们. 但是,必须使用( `$env:`访问系统设置的环境变量. + +``` +job_name: + script: + - echo $env:CI_JOB_ID + - echo $CI_JOB_ID + - echo $env:PATH +``` + +在[某些情况下,](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4115#note_157692820)环境变量可能需要用引号引起来才能正确扩展: + +``` +job_name: + script: + - D:\\qislsf\\apache-ant-1.10.5\\bin\\ant.bat "-DsosposDailyUsr=$env:SOSPOS_DAILY_USR" portal_test +``` + +### Windows Batch[](#windows-batch "Permalink") + +要访问**Windows Batch 中的**环境变量,请用( `%` )包围变量: + +``` +job_name: + script: + - echo %CI_JOB_ID% +``` + +### List all environment variables[](#list-all-environment-variables "Permalink") + +您还可以使用 Bash 中的`export`命令或 PowerShell 中的`dir env:`命令列出所有环境变量. 请注意,这还将在作业日志中公开您设置的所有变量的值: + +``` +job_name: + script: + - export + # - 'dir env:' # use this for PowerShell +``` + +值示例: + +``` +export CI_JOB_ID="50" +export CI_COMMIT_SHA="1ecfd275763eff1d6b4844ea3168962458c9f27a" +export CI_COMMIT_SHORT_SHA="1ecfd275" +export CI_COMMIT_REF_NAME="master" +export CI_REPOSITORY_URL="https://gitlab-ci-token:abcde-1234ABCD5678ef@example.com/gitlab-org/gitlab-foss.git" +export CI_COMMIT_TAG="1.0.0" +export CI_JOB_NAME="spec:other" +export CI_JOB_STAGE="test" +export CI_JOB_MANUAL="true" +export CI_JOB_TRIGGERED="true" +export CI_JOB_TOKEN="abcde-1234ABCD5678ef" +export CI_PIPELINE_ID="1000" +export CI_PIPELINE_IID="10" +export CI_PAGES_DOMAIN="gitlab.io" +export CI_PAGES_URL="https://gitlab-org.gitlab.io/gitlab-foss" +export CI_PROJECT_ID="34" +export CI_PROJECT_DIR="/builds/gitlab-org/gitlab-foss" +export CI_PROJECT_NAME="gitlab-foss" +export CI_PROJECT_TITLE="GitLab FOSS" +export CI_PROJECT_NAMESPACE="gitlab-org" +export CI_PROJECT_ROOT_NAMESPACE="gitlab-org" +export CI_PROJECT_PATH="gitlab-org/gitlab-foss" +export CI_PROJECT_URL="https://example.com/gitlab-org/gitlab-foss" +export CI_REGISTRY="registry.example.com" +export CI_REGISTRY_IMAGE="registry.example.com/gitlab-org/gitlab-foss" +export CI_REGISTRY_USER="gitlab-ci-token" +export CI_REGISTRY_PASSWORD="longalfanumstring" +export CI_RUNNER_ID="10" +export CI_RUNNER_DESCRIPTION="my runner" +export CI_RUNNER_TAGS="docker, linux" +export CI_SERVER="yes" +export CI_SERVER_URL="https://example.com" +export CI_SERVER_HOST="example.com" +export CI_SERVER_PORT="443" +export CI_SERVER_PROTOCOL="https" +export CI_SERVER_NAME="GitLab" +export CI_SERVER_REVISION="70606bf" +export CI_SERVER_VERSION="8.9.0" +export CI_SERVER_VERSION_MAJOR="8" +export CI_SERVER_VERSION_MINOR="9" +export CI_SERVER_VERSION_PATCH="0" +export GITLAB_USER_EMAIL="user@example.com" +export GITLAB_USER_ID="42" +``` + +## `.gitlab-ci.yml` defined variables[](#gitlab-ciyml-defined-variables "Permalink") + +**注意:**此功能需要 GitLab Runner 0.5.0 或更高版本以及 GitLab 7.14 或更高版本. + +您可以将在构建环境中设置的变量添加到`.gitlab-ci.yml` . 这些变量保存在存储库中,它们旨在存储非敏感项目配置,例如`RAILS_ENV`或`DATABASE_URL` . + +例如,如果将变量全局设置为下方(而不是在作业内部),它将在所有已执行的命令和脚本中使用: + +``` +variables: + DATABASE_URL: "postgres://postgres@postgres/my_database" +``` + +还将 YAML 定义的变量设置为所有创建的[服务容器](../docker/using_docker_images.html) ,以便您可以对其进行微调. + +变量可以在全局级别定义,也可以在作业级别定义. 要在作业中关闭全局定义的变量,请定义一个空哈希: + +``` +job_name: + variables: {} +``` + +您可以在变量定义内使用其他变量(或使用`$$`对其进行转义): + +``` +variables: + LS_CMD: 'ls $FLAGS $$TMP_DIR' + FLAGS: '-al' +script: + - 'eval $LS_CMD' # will execute 'ls -al $TMP_DIR' +``` + +## Group-level environment variables[](#group-level-environment-variables "Permalink") + +Introduced in GitLab 9.4. + +您可以定义在管道环境中设置的每个项目或每个组的变量. 组级变量存储在存储库之外(不在`.gitlab-ci.yml` ),并安全地传递到 GitLab Runner,这使它们在管道运行期间可用. 对于**不**使用外部密钥存储或使用 GitLab [与 HashiCorp Vault 集成的](../examples/authenticating-with-hashicorp-vault/index.html)高级用户,我们建议使用组环境变量来存储密码,SSH 密钥和凭据之类的机密. + +组级变量可以通过以下方式添加: + +1. 导航到组的**"设置">" CI / CD"**页面. +2. 在" **变量"**部分中输入变量类型,键和值. [子组的](../../user/group/subgroups/index.html)任何变量将被递归继承. + +设置它们后,它们将可用于所有后续管道. 可以通过以下方式在项目中查看任何组级用户定义的变量: + +1. 导航到项目的**"设置">" CI / CD"**页面. +2. 展开**变量**部分. + +[![CI/CD settings - inherited variables](img/bcbedbd56c50879eb35c2fc2f534d693.png)](img/inherited_group_variables_v12_5.png) + +## Instance-level CI/CD environment variables[](#instance-level-cicd-environment-variables "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/14108) . + +实例变量非常有用,因为不再需要为所有项目重复手动输入相同的凭据. 实例级变量可用于实例上的所有项目和组. + +**注意:**实例级变量的最大数量[计划为 25](https://gitlab.com/gitlab-org/gitlab/-/issues/216097) . + +您可以通过 UI 或[API](../../api/instance_level_ci_variables.html)定义实例级变量. + +要添加实例级变量: + +1. 导航到管理区域的**"设置">" CI / CD",**然后展开" **变量"**部分. +2. 单击**添加变量**按钮,然后填写详细信息: + + * **密钥** :必须为一行,只能使用字母,数字或`_` (下划线),且不能有空格. + * **值** :允许 700 个字符. + * **Type**: `File` or `Variable`. + * **保护变量** (可选):如果选中,则该变量将仅在在受保护的分支或标签上运行的管道中可用. + * **屏蔽变量** (可选):如果选中,则变量的**值**将不会显示在作业日志中. 如果该值不满足[屏蔽要求,](#masked-variable-requirements)则不会保存该变量. + +创建变量后,您可以通过点击 **编辑**按钮. + +### Enable or disable UI interface for instance-level CI/CD variables[](#enable-or-disable-ui-interface-for-instance-level-cicd-variables "Permalink") + +实例级 CI / CD 变量的 UI 界面正在开发中,但可用于生产环境. 它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../administration/feature_flags.html)可以选择为您的实例禁用它. + +禁用它: + +``` +Feature.disable(:instance_variables_ui) +``` + +要启用它: + +``` +Feature.enable(:instance_variables_ui) +``` + +## Inherit environment variables[](#inherit-environment-variables "Permalink") + +版本历史 + +* [介绍](https://gitlab.com/gitlab-org/gitlab/-/issues/22638)在 GitLab 13.0 后面的禁用[功能标志](../../administration/feature_flags.html) : `ci_dependency_variables` . +* 在 GitLab 13.1 中[已删除功能标记](https://gitlab.com/gitlab-org/gitlab/-/issues/217834) . + +您可以从相关作业中继承环境变量. + +该功能利用了[`artifacts:reports:dotenv`](../pipelines/job_artifacts.html#artifactsreportsdotenv)报告功能. + +带有[`dependencies`](../yaml/README.html#dependencies)关键字的示例. + +``` +build: + stage: build + script: + - echo "BUILD_VERSION=hello" >> build.env + artifacts: + reports: + dotenv: build.env + +deploy: + stage: deploy + script: + - echo $BUILD_VERSION # => hello + dependencies: + - build +``` + +带[`needs`](../yaml/README.html#artifact-downloads-with-needs)关键字的示例: + +``` +build: + stage: build + script: + - echo "BUILD_VERSION=hello" >> build.env + artifacts: + reports: + dotenv: build.env + +deploy: + stage: deploy + script: + - echo $BUILD_VERSION # => hello + needs: + - job: build + artifacts: true +``` + +## Priority of environment variables[](#priority-of-environment-variables "Permalink") + +不同类型的变量可以优先于其他变量,具体取决于它们的定义位置. + +变量的优先顺序为(从最高到最低): + +1. [触发器变量](../triggers/README.html#making-use-of-trigger-variables) , [计划的管道变量](../pipelines/schedules.html#using-variables)和[手动管道运行变量](#override-a-variable-by-manually-running-a-pipeline) . +2. Project-level [variables](#custom-environment-variables) or [protected variables](#protect-a-custom-variable). +3. Group-level [variables](#group-level-environment-variables) or [protected variables](#protect-a-custom-variable). +4. [Inherited environment variables](#inherit-environment-variables). +5. YAML-defined [job-level variables](../yaml/README.html#variables). +6. YAML-defined [global variables](../yaml/README.html#variables). +7. [Deployment variables](#deployment-environment-variables). +8. [Predefined environment variables](predefined_variables.html). + +例如,如果您定义: + +* `API_TOKEN=secure`作为项目变量. +* 您的`.gitlab-ci.yml` `API_TOKEN=yaml` . + +`API_TOKEN`将采用`secure`值,因为项目变量优先于`.gitlab-ci.yml`定义`.gitlab-ci.yml` . + +## Unsupported variables[](#unsupported-variables "Permalink") + +Variable names are limited by the underlying shell used to execute scripts (see [available shells](https://docs.gitlab.com/runner/shells/index.html). Each shell has its own unique set of reserved variable names. You will also want to keep in mind the [scope of environment variables](where_variables_can_be_used.html) to ensure a variable is defined in the scope in which you wish to use it. + +## Where variables can be used[](#where-variables-can-be-used "Permalink") + +单击[此处](where_variables_can_be_used.html)以获得描述在何处以及如何使用不同类型的变量的部分. + +## Advanced use[](#advanced-use "Permalink") + +### Limit the environment scopes of environment variables[](#limit-the-environment-scopes-of-environment-variables "Permalink") + +您可以通过[定义](../environments/index.html)变量可用于的环境来限制变量的环境范围. + +要了解有关范围界定环境的更多信息,请参阅[使用规范范围界定环境](../environments/index.html#scoping-environments-with-specs) . + +### Deployment environment variables[](#deployment-environment-variables "Permalink") + +在 GitLab 8.15 中引入. + +负责部署配置的[集成](../../user/project/integrations/overview.html)可以定义在构建环境中设置的自己的变量. 这些变量仅为[部署作业](../environments/index.html)定义. 请查阅所用集成的文档,以了解它们定义了哪些变量. + +定义部署变量的示例集成是[Kubernetes 集成](../../user/project/clusters/index.html#deployment-variables) . + +### Auto DevOps environment variables[](#auto-devops-environment-variables "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49056) . + +您可以配置[Auto DevOps,](../../topics/autodevops/index.html)以将 CI 变量传递给正在运行的应用程序,方法是在变量的键之前添加`K8S_SECRET_` . + +然后,这些[前缀变量](../../topics/autodevops/customize.html#application-secret-variables)将在运行的应用程序容器上用作环境变量. + +**警告:**由于当前 Auto DevOps 脚本环境的限制,当前不支持具有多行值的变量. + +### Override a variable by manually running a pipeline[](#override-a-variable-by-manually-running-a-pipeline "Permalink") + +在 GitLab 10.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44059) . + +您可以通过[手动运行管道](../pipelines/index.html#run-a-pipeline-manually)来覆盖当前变量的值. + +例如,假设您添加了一个名为`$TEST`的自定义变量,并且想在手动管道中覆盖它. + +导航到项目的**CI / CD>管道** ,然后单击**运行管道** . 选择要为其运行管道的分支,然后在 UI 中添加变量及其值: + +[![Override variable value](img/599297cd25b4f282b1340e8e61e2e087.png)](img/override_variable_manual_pipeline.png) + +运行器将覆盖先前设置的值,并将自定义值用于此特定管道. + +[![Manually overridden variable output](img/e392f78e991a2b0865f4a2fe825fd7fc.png)](img/override_value_via_manual_pipeline_output.png) + +## Environment variables expressions[](#environment-variables-expressions "Permalink") + +版本历史 + +* 在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/37397) [了`only`和`except` CI 关键字](../yaml/README.html#onlyexcept-advanced) +* 在 GitLab 12.3 中使用[`rules`关键字](../yaml/README.html#rules) [扩展](https://gitlab.com/gitlab-org/gitlab/-/issues/27863) + +使用变量表达式来限制将更改推送到 GitLab 之后在管道中创建的作业. + +在`.gitlab-ci.yml` ,变量表达式可同时用于以下两种情况: + +* [`rules`](../yaml/README.html#rules) ,这是推荐的方法,以及 +* [`only`和`except`](../yaml/README.html#onlyexcept-basic) ,它们是不推荐使用的候选对象. + +与变量和触发的管道变量结合使用时,这特别有用. + +``` +deploy: + script: cap staging deploy + environment: staging + only: + variables: + - $RELEASE == "staging" + - $STAGING +``` + +在创建管道之前,将对提供的每个表达式进行求值. + +如果`only`使用时`variables`任何条件评估为 true,则会创建一个新作业. 如果在使用`except`任何表达式的结果为 true,则不会创建作业. + +这遵循[`only` / `except`策略](../yaml/README.html#onlyexcept-advanced)的常规规则. + +### Syntax of environment variable expressions[](#syntax-of-environment-variable-expressions "Permalink") + +您可以在下面找到受支持的语法参考: + +1. 使用字符串进行相等匹配 + + Examples: + + * `$VARIABLE == "some value"` + * `$VARIABLE != "some value"` (在 GitLab 11.11 中引入) + + 您可以使用等于运算符`==`或`!=`将变量内容与字符串进行比较. 我们支持双引号和单引号来定义字符串值,因此同时支持`$VARIABLE == "some value"`和`$VARIABLE == 'some value'` . `"some value" == $VARIABLE`也正确. + +2. 检查未定义的值 + + Examples: + + * `$VARIABLE == null` + * `$VARIABLE != null` (在 GitLab 11.11 中引入) + + 有时,您可能想检查是否定义了变量. 为此,您可以将变量与`null`关键字进行比较,例如`$VARIABLE == null` . 如果在使用`==`时未定义变量,则该表达式的值为 true;如果使用`!=`则该表达式的值为 false. + +3. 检查空变量 + + Examples: + + * `$VARIABLE == ""` + * `$VARIABLE != ""` (introduced in GitLab 11.11) + + 如果要检查变量是否已定义但为空,则可以将其与空字符串(例如`$VAR == ''`或非空字符串`$VARIABLE != ""` . + +4. 比较两个变量 + + Examples: + + * `$VARIABLE_1 == $VARIABLE_2` + * `$VARIABLE_1 != $VARIABLE_2` (在 GitLab 11.11 中引入) + + 可以比较两个变量. 这将比较这些变量的值. + +5. 可变状态检查 + + Example: `$STAGING` + + 如果只想在存在某个变量时创建作业,这意味着它是已定义且非空的,则可以简单地使用变量名作为表达式,例如`$STAGING` . 如果`$STAGING`变量已定义且不为空,则表达式将求值为真. `$STAGING`值必须是长度大于零的字符串. 仅包含空格字符的变量不是空变量. + +6. 模式匹配(在 GitLab 11.0 中引入) + + Examples: + + * `=~` :如果模式匹配则为真. 例如: `$VARIABLE =~ /^content.*/` + * `!~` :如果模式不匹配,则为 true. 例如: `$VARIABLE_1 !~ /^content.*/` (在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/61900) ) + + 与正则表达式匹配的变量模式使用[RE2 正则表达式语法](https://github.com/google/re2/wiki/Syntax) . 如果满足以下条件,则表达式的计算结果为`true` : + + * 使用`=~`时找到匹配项. + * 当使用火柴都*没有*发现`!~` + + 模式匹配默认情况下区分大小写. 使用`i`标志修饰符,例如`/pattern/i` ,使模式不区分大小写. + +7. Conjunction / Disjunction ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27925) in GitLab 12.0) + + Examples: + + * `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"` + * `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3` + * `$VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3` + + 可以使用`&&`或`||`加入多个条件 . 任何在其他情况下受支持的语法都可以在合并或不合并语句中使用. 运算符的优先级遵循[Ruby 2.5 标准](https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html) ,因此`&&`在`||`之前进行评估 . + +### Storing regular expressions in variables[](#storing-regular-expressions-in-variables "Permalink") + +可以将正则表达式存储在变量中,以用于模式匹配: + +``` +variables: + STAGINGRELS: '/staging0|staging1/' + +deploy_staging: + script: do.sh deploy staging + environment: staging + rules: + - if: '$RELEASE =~ $STAGINGRELS' +``` + +**注意:**可用的正则表达式语法受到限制. 有关更多详细信息,请参见[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/35438) . + +如果需要,您可以使用测试管道来确定正则表达式是否可以在变量中工作. 下面的示例直接从变量内部测试`^mast.*`正则表达式: + +``` +variables: + MYSTRING: 'master' + MYREGEX: '/^mast.*/' + +testdirect: + script: /bin/true + rules: + - if: '$MYSTRING =~ /^mast.*/' + +testvariable: + script: /bin/true + rules: + - if: '$MYSTRING =~ $MYREGEX' +``` + +## Debug logging[](#debug-logging "Permalink") + +在 GitLab Runner 1.7 中引入. + +**警告:**启用调试跟踪可能会严重影响安全性. 输出**将**包含所有变量和其他任何秘密的内容! 输出**将**上传到 GitLab 服务器,并在作业日志中显示! + +默认情况下,GitLab Runner 隐藏处理作业时所执行操作的大多数细节. 此行为使作业日志简短,并防止机密信息泄露到日志中,除非您的脚本将其写入屏幕. + +如果一项工作没有按预期进行,则可能使问题难以调查. 在这种情况下,您可以在`.gitlab-ci.yml`启用调试跟踪. 在 GitLab Runner v1.7 +上可用,此功能启用外壳程序的执行日志,从而产生详细的作业日志,其中列出了所有已运行的命令,已设置的变量等. + +在启用此功能之前,您应确保作业[仅对团队成员](../../user/permissions.html#project-features)可见. 您还应该[清除](../pipelines/index.html#view-jobs-in-a-pipeline)所有生成的作业日志,然后才能再次显示它们. + +要启用调试日志(跟踪),请将`CI_DEBUG_TRACE`变量设置为`true` : + +``` +job_name: + variables: + CI_DEBUG_TRACE: "true" +``` + +将`CI_DEBUG_TRACE`设置为`true`示例截断输出: + +``` +... + +export CI_SERVER_TLS_CA_FILE="/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE" +if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then echo $'\''\x1b[32;1mFetching changes...\x1b[0;m'\'' + $'\''cd'\'' "/builds/gitlab-examples/ci-debug-trace" + $'\''git'\'' "config" "fetch.recurseSubmodules" "false" + $'\''rm'\'' "-f" ".git/index.lock" + $'\''git'\'' "clean" "-ffdx" + $'\''git'\'' "reset" "--hard" + $'\''git'\'' "remote" "set-url" "origin" "https://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@example.com/gitlab-examples/ci-debug-trace.git" + $'\''git'\'' "fetch" "origin" "--prune" "+refs/heads/*:refs/remotes/origin/*" "+refs/tags/*:refs/tags/lds" +++ CI_BUILDS_DIR=/builds +++ export CI_PROJECT_DIR=/builds/gitlab-examples/ci-debug-trace +++ CI_PROJECT_DIR=/builds/gitlab-examples/ci-debug-trace +++ export CI_CONCURRENT_ID=87 +++ CI_CONCURRENT_ID=87 +++ export CI_CONCURRENT_PROJECT_ID=0 +++ CI_CONCURRENT_PROJECT_ID=0 +++ export CI_SERVER=yes +++ CI_SERVER=yes +++ mkdir -p /builds/gitlab-examples/ci-debug-trace.tmp +++ echo -n '-----BEGIN CERTIFICATE----- +-----END CERTIFICATE-----' +++ export CI_SERVER_TLS_CA_FILE=/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE +++ CI_SERVER_TLS_CA_FILE=/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE +++ export CI_PIPELINE_ID=52666 +++ CI_PIPELINE_ID=52666 +++ export CI_PIPELINE_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/pipelines/52666 +++ CI_PIPELINE_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/pipelines/52666 +++ export CI_JOB_ID=7046507 +++ CI_JOB_ID=7046507 +++ export CI_JOB_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/-/jobs/379424655 +++ CI_JOB_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/-/jobs/379424655 +++ export CI_JOB_TOKEN=[MASKED] +++ CI_JOB_TOKEN=[MASKED] +++ export CI_BUILD_ID=379424655 +++ CI_BUILD_ID=379424655 +++ export CI_BUILD_TOKEN=[MASKED] +++ CI_BUILD_TOKEN=[MASKED] +++ export CI_REGISTRY_USER=gitlab-ci-token +++ CI_REGISTRY_USER=gitlab-ci-token +++ export CI_REGISTRY_PASSWORD=[MASKED] +++ CI_REGISTRY_PASSWORD=[MASKED] +++ export CI_REPOSITORY_URL=https://gitlab-ci-token:[MASKED]@gitlab.com/gitlab-examples/ci-debug-trace.git +++ CI_REPOSITORY_URL=https://gitlab-ci-token:[MASKED]@gitlab.com/gitlab-examples/ci-debug-trace.git +++ export CI_JOB_NAME=debug_trace +++ CI_JOB_NAME=debug_trace +++ export CI_JOB_STAGE=test +++ CI_JOB_STAGE=test +++ export CI_NODE_TOTAL=1 +++ CI_NODE_TOTAL=1 +++ export CI_BUILD_NAME=debug_trace +++ CI_BUILD_NAME=debug_trace +++ export CI_BUILD_STAGE=test +++ CI_BUILD_STAGE=test +++ export CI=true +++ CI=true +++ export GITLAB_CI=true +++ GITLAB_CI=true +++ export CI_SERVER_URL=https://gitlab.com:3000 +++ CI_SERVER_URL=https://gitlab.com:3000 +++ export CI_SERVER_HOST=gitlab.com +++ CI_SERVER_HOST=gitlab.com +++ export CI_SERVER_PORT=3000 +++ CI_SERVER_PORT=3000 +++ export CI_SERVER_PROTOCOL=https +++ CI_SERVER_PROTOCOL=https +++ export CI_SERVER_NAME=GitLab +++ CI_SERVER_NAME=GitLab +++ export CI_SERVER_VERSION=12.6.0-pre +++ CI_SERVER_VERSION=12.6.0-pre +++ export CI_SERVER_VERSION_MAJOR=12 +++ CI_SERVER_VERSION_MAJOR=12 +++ export CI_SERVER_VERSION_MINOR=6 +++ CI_SERVER_VERSION_MINOR=6 +++ export CI_SERVER_VERSION_PATCH=0 +++ CI_SERVER_VERSION_PATCH=0 +++ export CI_SERVER_REVISION=f4cc00ae823 +++ CI_SERVER_REVISION=f4cc00ae823 +++ export GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_project_service_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,pseudonymizer,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal +++ GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_project_service_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,cluster_health,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,pseudonymizer,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal +++ export CI_PROJECT_ID=17893 +++ CI_PROJECT_ID=17893 +++ export CI_PROJECT_NAME=ci-debug-trace +++ CI_PROJECT_NAME=ci-debug-trace +++ export CI_PROJECT_TITLE='GitLab FOSS' +++ CI_PROJECT_TITLE='GitLab FOSS' +++ export CI_PROJECT_PATH=gitlab-examples/ci-debug-trace +++ CI_PROJECT_PATH=gitlab-examples/ci-debug-trace +++ export CI_PROJECT_PATH_SLUG=gitlab-examples-ci-debug-trace +++ CI_PROJECT_PATH_SLUG=gitlab-examples-ci-debug-trace +++ export CI_PROJECT_NAMESPACE=gitlab-examples +++ CI_PROJECT_NAMESPACE=gitlab-examples +++ export CI_PROJECT_ROOT_NAMESPACE=gitlab-examples +++ CI_PROJECT_ROOT_NAMESPACE=gitlab-examples +++ export CI_PROJECT_URL=https://gitlab.com/gitlab-examples/ci-debug-trace +++ CI_PROJECT_URL=https://gitlab.com/gitlab-examples/ci-debug-trace +++ export CI_PROJECT_VISIBILITY=public +++ CI_PROJECT_VISIBILITY=public +++ export CI_PROJECT_REPOSITORY_LANGUAGES= +++ CI_PROJECT_REPOSITORY_LANGUAGES= +++ export CI_DEFAULT_BRANCH=master +++ CI_DEFAULT_BRANCH=master +++ export CI_REGISTRY=registry.gitlab.com +++ CI_REGISTRY=registry.gitlab.com +++ export CI_API_V4_URL=https://gitlab.com/api/v4 +++ CI_API_V4_URL=https://gitlab.com/api/v4 +++ export CI_PIPELINE_IID=123 +++ CI_PIPELINE_IID=123 +++ export CI_PIPELINE_SOURCE=web +++ CI_PIPELINE_SOURCE=web +++ export CI_CONFIG_PATH=.gitlab-ci.yml +++ CI_CONFIG_PATH=.gitlab-ci.yml +++ export CI_COMMIT_SHA=dd648b2e48ce6518303b0bb580b2ee32fadaf045 +++ CI_COMMIT_SHA=dd648b2e48ce6518303b0bb580b2ee32fadaf045 +++ export CI_COMMIT_SHORT_SHA=dd648b2e +++ CI_COMMIT_SHORT_SHA=dd648b2e +++ export CI_COMMIT_BEFORE_SHA=0000000000000000000000000000000000000000 +++ CI_COMMIT_BEFORE_SHA=0000000000000000000000000000000000000000 +++ export CI_COMMIT_REF_NAME=master +++ CI_COMMIT_REF_NAME=master +++ export CI_COMMIT_REF_SLUG=master +++ CI_COMMIT_REF_SLUG=master +++ export CI_COMMIT_MESSAGE=s/CI/Runner +++ CI_COMMIT_MESSAGE=s/CI/Runner +++ export CI_COMMIT_TITLE=s/CI/Runner +++ CI_COMMIT_TITLE=s/CI/Runner +++ export CI_COMMIT_DESCRIPTION= +++ CI_COMMIT_DESCRIPTION= +++ export CI_COMMIT_REF_PROTECTED=true +++ CI_COMMIT_REF_PROTECTED=true +++ export CI_BUILD_REF=dd648b2e48ce6518303b0bb580b2ee32fadaf045 +++ CI_BUILD_REF=dd648b2e48ce6518303b0bb580b2ee32fadaf045 +++ export CI_BUILD_BEFORE_SHA=0000000000000000000000000000000000000000 +++ CI_BUILD_BEFORE_SHA=0000000000000000000000000000000000000000 +++ export CI_BUILD_REF_NAME=master +++ CI_BUILD_REF_NAME=master +++ export CI_BUILD_REF_SLUG=master +++ CI_BUILD_REF_SLUG=master +++ export CI_RUNNER_ID=1337 +++ CI_RUNNER_ID=1337 +++ export CI_RUNNER_DESCRIPTION=shared-runners-manager-4.gitlab.com +++ CI_RUNNER_DESCRIPTION=shared-runners-manager-4.gitlab.com +++ export 'CI_RUNNER_TAGS=gce, east-c, shared, docker, linux, ruby, mysql, postgres, mongo, git-annex' +++ CI_RUNNER_TAGS='gce, east-c, shared, docker, linux, ruby, mysql, postgres, mongo, git-annex' +++ export CI_DEBUG_TRACE=true +++ CI_DEBUG_TRACE=true +++ export GITLAB_USER_ID=42 +++ GITLAB_USER_ID=42 +++ export GITLAB_USER_EMAIL=user@example.com +++ GITLAB_USER_EMAIL=user@example.com +++ export GITLAB_USER_LOGIN=root +++ GITLAB_USER_LOGIN=root +++ export 'GITLAB_USER_NAME=User' +++ GITLAB_USER_NAME='User' +++ export CI_DISPOSABLE_ENVIRONMENT=true +++ CI_DISPOSABLE_ENVIRONMENT=true +++ export CI_RUNNER_VERSION=12.5.0 +++ CI_RUNNER_VERSION=12.5.0 +++ export CI_RUNNER_REVISION=577f813d +++ CI_RUNNER_REVISION=577f813d +++ export CI_RUNNER_EXECUTABLE_ARCH=linux/amd64 +++ CI_RUNNER_EXECUTABLE_ARCH=linux/amd64 +++ export VERY_SECURE_VARIABLE=imaverysecurevariable +++ VERY_SECURE_VARIABLE=imaverysecurevariable + +... +``` + +## Video walkthrough of a working example[](#video-walkthrough-of-a-working-example "Permalink") + +[使用 GitLab 管理复杂配置数据管理怪兽](https://www.youtube.com/watch?v=v4ZOJ96hAck)视频是[复杂配置数据 Monorepo](https://gitlab.com/guided-explorations/config-data-top-scope/config-data-subscope/config-data-monorepo)工作示例项目的演练. 它解释了如何将多个级别的组 CI / CD 变量与环境范围的项目变量组合在一起,以实现应用程序构建或部署的复杂配置. + +可以将示例复制到您自己的组或实例中进行测试. 项目页面上提供了有关演示其他 GitLab CI 模式的更多详细信息. \ No newline at end of file diff --git a/docs/221.md b/docs/221.md new file mode 100644 index 0000000000000000000000000000000000000000..02caa08909b904b5b9a2be4d8815f528186618f5 --- /dev/null +++ b/docs/221.md @@ -0,0 +1,128 @@ +# Predefined environment variables reference + +> 原文:[https://docs.gitlab.com/ee/ci/variables/predefined_variables.html](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) + +# Predefined environment variables reference[](#predefined-environment-variables-reference "Permalink") + +有关此主题的介绍,请通读[环境变量入门](README.html)文档. + +仅当使用最低版本的[GitLab Runner 时,](https://docs.gitlab.com/runner/)某些预定义的环境变量才可用. 请查阅下表以查找所需的 Runner 版本. + +**注意:**从 GitLab 9.0 开始,我们已弃用了一些变量. 阅读[9.0 重命名](deprecated_variables.html#gitlab-90-renamed-variables)部分以查找其替换内容. **强烈建议您使用新变量,因为我们将在以后的 GitLab 版本中删除旧变量.** + +您可以在`.gitlab-ci.yml`文件中添加命令,以[输出可用于作业的所有变量的值](README.html#list-all-environment-variables) . + +Kubernetes 特定于环境的环境变量在[Kubernetes 部署变量](../../user/project/clusters/index.html#deployment-variables)部分中进行了详细介绍. + +| Variable | GitLab | Runner | Description | +| --- | --- | --- | --- | +| `CHAT_CHANNEL` | 10.6 | all | 触发[ChatOps](../chatops/README.html)命令的源聊天通道 | +| `CHAT_INPUT` | 10.6 | all | 在[ChatOps](../chatops/README.html)命令中传递的其他参数 | +| `CI` | all | 0.4 | 标记作业在 CI 环境中执行 | +| `CI_API_V4_URL` | 11.7 | all | GitLab API v4 根 URL | +| `CI_BUILDS_DIR` | all | 11.10 | 执行构建的顶级目录. | +| `CI_COMMIT_BEFORE_SHA` | 11.2 | all | 先前的最新提交存在于分支中. 合并请求的管道中始终为`0000000000000000000000000000000000000000` | +| `CI_COMMIT_DESCRIPTION` | 10.8 | all | 提交的描述:如果标题少于 100 个字符,则不带第一行的消息; 在其他情况下为完整消息. | +| `CI_COMMIT_MESSAGE` | 10.8 | all | 完整的提交消息. | +| `CI_COMMIT_REF_NAME` | 9.0 | all | 构建项目的分支或标记名称 | +| `CI_COMMIT_REF_PROTECTED` | 11.11 | all | 如果作业在受保护的引用上运行,则为`true`否则为`false` | +| `CI_COMMIT_REF_SLUG` | 9.0 | all | `$CI_COMMIT_REF_NAME`小写,缩短为 63 个字节,并且将`0-9`和`az`以外的所有内容替换为`-` . 没有前导/尾随`-` . 在 URL,主机名和域名中使用. | +| `CI_COMMIT_SHA` | 9.0 | all | 为其构建项目的提交修订 | +| `CI_COMMIT_SHORT_SHA` | 11.7 | all | `CI_COMMIT_SHA`的前八个字符 | +| `CI_COMMIT_BRANCH` | 12.6 | 0.5 | 提交分支名称. 仅在建立分支时显示. | +| `CI_COMMIT_TAG` | 9.0 | 0.5 | 提交标记名称. 仅在构建标签时显示. | +| `CI_COMMIT_TITLE` | 10.8 | all | 提交的标题-消息的第一行 | +| `CI_CONCURRENT_ID` | all | 11.10 | 单个执行程序中生成执行的唯一 ID. | +| `CI_CONCURRENT_PROJECT_ID` | all | 11.10 | 单个执行程序和项目中生成执行的唯一 ID. | +| `CI_CONFIG_PATH` | 9.4 | 0.5 | CI 配置文件的路径. 默认为`.gitlab-ci.yml` | +| `CI_DEBUG_TRACE` | all | 1.7 | 是否启用[调试日志记录(跟踪)](README.html#debug-logging) | +| `CI_DEFAULT_BRANCH` | 12.4 | all | 项目的默认分支的名称. | +| `CI_DEPLOY_PASSWORD` | 10.8 | all | [GitLab Deploy 令牌的](../../user/project/deploy_tokens/index.html#gitlab-deploy-token)身份验证密码,仅在项目具有相关性时才提供. | +| `CI_DEPLOY_USER` | 10.8 | all | [GitLab Deploy 令牌的](../../user/project/deploy_tokens/index.html#gitlab-deploy-token)身份验证用户名,仅在项目具有相关性时才存在. | +| `CI_DISPOSABLE_ENVIRONMENT` | all | 10.1 | 标记作业是在一次性环境中执行的(仅为该作业创建并在执行后处置/销毁的东西-除`shell`和`ssh`以外的所有执行程序). 如果环境是一次性的,则将其设置为 true,否则将完全未定义. | +| `CI_ENVIRONMENT_NAME` | 8.15 | all | 该作业的环境名称. 仅在设置了[`environment:name`](../yaml/README.html#environmentname)存在. | +| `CI_ENVIRONMENT_SLUG` | 8.15 | all | 环境名称的简化版本,适合包含在 DNS,URL,Kubernetes 标签等中.仅在设置了[`environment:name`](../yaml/README.html#environmentname)存在. | +| `CI_ENVIRONMENT_URL` | 9.3 | all | 该作业的环境的 URL. 仅当设置了[`environment:url`](../yaml/README.html#environmenturl)时才存在. | +| `CI_EXTERNAL_PULL_REQUEST_IID` | 12.3 | all | 如果[管道用于外部请求,](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)则来自 GitHub 的请求请求 ID. 仅在以下情况`only: [external_pull_requests]`可用`only: [external_pull_requests]`或[`rules`](../yaml/README.html#rules)语法,并且拉取请求处于打开状态. | +| `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_NAME` | 12.3 | all | 如果[管道用于外部](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)请求,则请求请求的源分支名称. 仅在以下情况`only: [external_pull_requests]`可用`only: [external_pull_requests]`或[`rules`](../yaml/README.html#rules)语法,并且拉取请求处于打开状态. | +| `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_SHA` | 12.3 | all | 如果[管道用于外部](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)请求,则请求请求的源分支的 HEAD SHA. 仅在以下情况`only: [external_pull_requests]`可用`only: [external_pull_requests]`或[`rules`](../yaml/README.html#rules)语法,并且拉取请求处于打开状态. | +| `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_NAME` | 12.3 | all | 如果[管道用于外部](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)请求,则请求请求的目标分支名称. 仅在以下情况`only: [external_pull_requests]`可用`only: [external_pull_requests]`或[`rules`](../yaml/README.html#rules)语法,并且拉取请求处于打开状态. | +| `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_SHA` | 12.3 | all | 如果[管道用于外部](../ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests)请求,则请求请求目标分支的 HEAD SHA. 仅在以下情况`only: [external_pull_requests]`可用`only: [external_pull_requests]`或[`rules`](../yaml/README.html#rules)语法,并且拉取请求处于打开状态. | +| `CI_HAS_OPEN_REQUIREMENTS` | 13.1 | all | 仅当管道的项目有任何开放[要求时,](../../user/project/requirements/index.html)才将值包括为`true` . 如果管道项目没有开放要求,则不包括在内. | +| `CI_JOB_ID` | 9.0 | all | GitLab CI / CD 在内部使用的当前作业的唯一 ID | +| `CI_JOB_IMAGE` | 12.9 | 12.9 | 运行 CI 作业的图像的名称 | +| `CI_JOB_MANUAL` | 8.12 | all | 指示作业已手动启动的标志 | +| `CI_JOB_NAME` | 9.0 | 0.5 | `.gitlab-ci.yml`定义的作业名称 | +| `CI_JOB_STAGE` | 9.0 | 0.5 | `.gitlab-ci.yml`定义的阶段名称 | +| `CI_JOB_TOKEN` | 9.0 | 1.2 | 用于通过[GitLab 容器注册表](../../user/packages/container_registry/index.html)进行身份验证,下载[从属存储库](../../user/project/new_ci_build_permissions_model.html#dependent-repositories)以及访问[GitLab 管理的 Terraform 状态的](../../user/infrastructure/index.html#gitlab-managed-terraform-state)令牌. | +| `CI_JOB_JWT` | 12.10 | all | RS256 JSON Web 令牌,可用于与支持 JWT 身份验证的第三方系统进行身份验证,例如[HashiCorp 的 Vault](../examples/authenticating-with-hashicorp-vault) . | +| `CI_JOB_URL` | 11.1 | 0.5 | 职位详情网址 | +| `CI_KUBERNETES_ACTIVE` | 13.0 | all | Included with the value `true` only if the pipeline has a Kubernetes cluster available for deployments. Not included if no cluster is available. Can be used as an alternative to [`only:kubernetes`/`except:kubernetes`](../yaml/README.html#onlykubernetesexceptkubernetes) with [`rules:if`](../yaml/README.html#rulesif) | +| `CI_MERGE_REQUEST_ASSIGNEES` | 11.9 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则该合并请求的受让人的用户名列表用逗号分隔. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_ID` | 11.6 | all | 合并请求的项目级别 ID. 仅当[管道用于合并请求](../merge_request_pipelines/index.html)并且创建[合并请求](../merge_request_pipelines/index.html)时才可用. | +| `CI_MERGE_REQUEST_IID` | 11.6 | all | 合并请求的实例级 IID. 仅[当管道用于合并请求](../merge_request_pipelines/index.html)并且创建[合并请求](../merge_request_pipelines/index.html)时才可用. | +| `CI_MERGE_REQUEST_LABELS` | 11.9 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的逗号分隔标签名称. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_MILESTONE` | 11.9 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的里程碑标题. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_PROJECT_ID` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的项目的 ID. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_PROJECT_PATH` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的项目路径(例如, `namespace/awesome-project` ). 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_PROJECT_URL` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的项目的 URL(例如`http://192.168.10.15:3000/namespace/awesome-project` ). 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_REF_PATH` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的 ref 路径. (例如`refs/merge-requests/1/head` ). 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_SOURCE_BRANCH_NAME` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的源分支名称. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` | 11.9 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的源分支的 HEAD SHA. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法,创建合并请求,并且管道是[合并结果管道](../merge_request_pipelines/pipelines_for_merged_results/index.html) . | +| `CI_MERGE_REQUEST_SOURCE_PROJECT_ID` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的源项目的 ID. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的源项目的路径. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_SOURCE_PROJECT_URL` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的源项目的 URL. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_TARGET_BRANCH_NAME` | 11.6 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的目标分支名称. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` | 11.9 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的目标分支的 HEAD SHA. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法,创建合并请求,并且管道是[合并结果管道](../merge_request_pipelines/pipelines_for_merged_results/index.html) . | +| `CI_MERGE_REQUEST_TITLE` | 11.9 | all | 如果[管道用于合并请求](../merge_request_pipelines/index.html) ,则合并请求的标题. 仅在以下情况`only: [merge_requests]`可用:仅使用`only: [merge_requests]`或[`rules`](../yaml/README.html#rules)语法并创建合并请求. | +| `CI_MERGE_REQUEST_EVENT_TYPE` | 12.3 | all | 合并请求的事件类型(如果[管道用于合并请求)](../merge_request_pipelines/index.html) . 可以`detached` , `merged_result`或`merge_train` . | +| `CI_NODE_INDEX` | 11.5 | all | 作业在作业集中的索引. 如果作业未并行化,则不会设置此变量. | +| `CI_NODE_TOTAL` | 11.5 | all | Total number of instances of this job running in parallel. If the job is not parallelized, this variable is set to `1`. | +| `CI_PAGES_DOMAIN` | 11.8 | all | 托管 GitLab 页面的已配置域. | +| `CI_PAGES_URL` | 11.8 | all | GitLab 页面构建页面的 URL. 始终属于`CI_PAGES_DOMAIN`的子域. | +| `CI_PIPELINE_ID` | 8.10 | all | GitLab CI / CD 在内部使用的当前管道的唯一 ID | +| `CI_PIPELINE_IID` | 11.0 | all | 当前管道的唯一 ID 范围为项目 | +| `CI_PIPELINE_SOURCE` | 10.0 | all | 指示如何触发管道. 可能的选项是: `push` , `web` , `schedule` , `api` , `external` , `chat` , `webide` , `merge_request_event` , `external_pull_request_event` , `parent_pipeline` , [`trigger`或`pipeline`](../triggers/README.html#authentication-tokens) (自 13.0 起改名为`cross_project_pipeline` ). 对于在 GitLab 9.5 之前创建的管道,这将显示为`unknown` . | +| `CI_PIPELINE_TRIGGERED` | all | all | 指示已[触发](../triggers/README.html)作业的标志 | +| `CI_PIPELINE_URL` | 11.1 | 0.5 | 管道详细资料网址 | +| `CI_PROJECT_DIR` | all | all | 克隆存储库以及运行作业的完整路径. 如果设置了 GitLab Runner 的`builds_dir`参数,则相对于`builds_dir`的值设置此变量. 有关更多信息,请参见 GitLab Runner 的[高级配置](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) . | +| `CI_PROJECT_ID` | all | all | GitLab CI / CD 在内部使用的当前项目的唯一 ID | +| `CI_PROJECT_NAME` | 8.10 | 0.5 | 当前正在构建的项目的目录名称. 例如,如果项目 URL 为`gitlab.example.com/group-name/project-1` ,则`CI_PROJECT_NAME`将为`project-1` . | +| `CI_PROJECT_NAMESPACE` | 8.10 | 0.5 | 当前正在构建的项目名称空间(用户名或组名) | +| `CI_PROJECT_ROOT_NAMESPACE` | 13.2 | 0.5 | 当前正在构建的**根**项目名称空间(用户名或组名). 例如,如果`CI_PROJECT_NAME`是`root-group/child-group/grandchild-group` ,则`CI_PROJECT_ROOT_NAMESPACE`将是`root-group` . | +| `CI_PROJECT_PATH` | 8.10 | 0.5 | 具有项目名称的名称空间 | +| `CI_PROJECT_PATH_SLUG` | 9.3 | all | `$CI_PROJECT_PATH`小写,除`0-9`和`az`以外的所有内容都用`-`代替. 在 URL 和域名中使用. | +| `CI_PROJECT_REPOSITORY_LANGUAGES` | 12.3 | all | 库中使用的语言的逗号分隔,小写列表(例如`ruby,javascript,html,css` ) | +| `CI_PROJECT_TITLE` | 12.4 | all | 可读的项目名称,显示在 GitLab Web 界面中. | +| `CI_PROJECT_URL` | 8.10 | 0.5 | The HTTP(S) address to access project | +| `CI_PROJECT_VISIBILITY` | 10.3 | all | 项目可见性(内部,私人,公共) | +| `CI_REGISTRY` | 8.10 | 0.5 | 如果启用了 Container Registry,它将返回 GitLab 的 Container Registry 的地址. 如果在注册表配置中指定了一个变量,则该变量将包含`:port`值. | +| `CI_REGISTRY_IMAGE` | 8.10 | 0.5 | 如果为项目启用了容器注册表,则它将返回绑定到特定项目的注册表地址 | +| `CI_REGISTRY_PASSWORD` | 9.0 | all | The password to use to push containers to the GitLab Container Registry, for the current project. | +| `CI_REGISTRY_USER` | 9.0 | all | 用于将容器推送到当前项目的 GitLab 容器注册表的用户名. | +| `CI_REPOSITORY_URL` | 9.0 | all | 克隆 Git 存储库的 URL | +| `CI_RUNNER_DESCRIPTION` | 8.10 | 0.5 | 保存在 GitLab 中的跑步者的描述 | +| `CI_RUNNER_EXECUTABLE_ARCH` | all | 10.6 | GitLab Runner 可执行文件的操作系统/体系结构(请注意,它不一定与执行程序的环境相同) | +| `CI_RUNNER_ID` | 8.10 | 0.5 | 正在使用的跑步者的唯一 ID | +| `CI_RUNNER_REVISION` | all | 10.6 | 正在执行当前作业的 GitLab Runner 版本 | +| `CI_RUNNER_SHORT_TOKEN` | all | 12.3 | GitLab Runner 令牌的前八个字符用于验证新的作业请求. 用作跑步者的唯一 ID | +| `CI_RUNNER_TAGS` | 8.10 | 0.5 | 定义的运行器标签 | +| `CI_RUNNER_VERSION` | all | 10.6 | 正在执行当前作业的 GitLab Runner 版本 | +| `CI_SERVER` | all | all | 标记作业在 CI 环境中执行 | +| `CI_SERVER_URL` | 12.7 | all | GitLab 实例的基本 URL,包括协议和端口(例如`https://gitlab.example.com:8080` ) | +| `CI_SERVER_HOST` | 12.1 | all | GitLab 实例 URL 的主机组件,不带协议和端口(例如`gitlab.example.com` ) | +| `CI_SERVER_PORT` | 12.8 | all | GitLab 实例 URL 的端口组件,不包含主机和协议(例如`3000` ) | +| `CI_SERVER_PROTOCOL` | 12.8 | all | GitLab 实例 URL 的协议组件,不带主机和端口(例如`https` ) | +| `CI_SERVER_NAME` | all | all | 用于协调作业的 CI 服务器的名称 | +| `CI_SERVER_REVISION` | all | all | 用于计划作业的 GitLab 修订版 | +| `CI_SERVER_VERSION` | all | all | 用于计划作业的 GitLab 版本 | +| `CI_SERVER_VERSION_MAJOR` | 11.4 | all | GitLab 版本主要组件 | +| `CI_SERVER_VERSION_MINOR` | 11.4 | all | GitLab 版本次要组件 | +| `CI_SERVER_VERSION_PATCH` | 11.4 | all | GitLab 版本补丁组件 | +| `CI_SHARED_ENVIRONMENT` | all | 10.1 | 标记作业是在共享环境中执行的(在诸如`shell`或`ssh`执行程序之类的 CI 调用之间持久存在的内容). 如果共享环境,则将其设置为 true,否则将完全未定义. | +| `GITLAB_CI` | all | all | 标记作业在 GitLab CI / CD 环境中执行 | +| `GITLAB_FEATURES` | 10.6 | all | 以逗号分隔的实例和计划可用的许可功能列表 | +| `GITLAB_USER_EMAIL` | 8.12 | all | 开始工作的用户的电子邮件 | +| `GITLAB_USER_ID` | 8.12 | all | 开始工作的用户的 ID | +| `GITLAB_USER_LOGIN` | 10.0 | all | 开始工作的用户的登录用户名 | +| `GITLAB_USER_NAME` | 10.0 | all | 开始工作的用户的真实姓名 | \ No newline at end of file diff --git a/docs/222.md b/docs/222.md new file mode 100644 index 0000000000000000000000000000000000000000..ec18696bc75fa49e2c97ede4fe8073a80dd37f38 --- /dev/null +++ b/docs/222.md @@ -0,0 +1,148 @@ +# Where variables can be used + +> 原文:[https://docs.gitlab.com/ee/ci/variables/where_variables_can_be_used.html](https://docs.gitlab.com/ee/ci/variables/where_variables_can_be_used.html) + +* [Variables usage](#variables-usage) + * [`.gitlab-ci.yml` file](#gitlab-ciyml-file) + * [`config.toml` file](#configtoml-file) +* [Expansion mechanisms](#expansion-mechanisms) + * [GitLab internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) + * [GitLab Runner internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) + * [Execution shell environment](#execution-shell-environment) +* [Persisted variables](#persisted-variables) +* [Variables with an environment scope](#variables-with-an-environment-scope) + +# Where variables can be used[](#where-variables-can-be-used "Permalink") + +如[CI / CD 变量](README.html)文档中所述,您可以定义许多不同的变量. 其中一些可用于所有 GitLab CI / CD 功能,但其中某些功能或多或少受到限制. + +本文档描述了在何处以及如何使用不同类型的变量. + +## Variables usage[](#variables-usage "Permalink") + +有两个地方可以使用定义的变量. 在: + +1. GitLab 端,位于`.gitlab-ci.yml` . +2. 跑步者方面,位于`config.toml` . + +### `.gitlab-ci.yml` file[](#gitlab-ciyml-file "Permalink") + +| Definition | 可以扩大吗? | 扩展地点 | Description | +| --- | --- | --- | --- | +| `environment:url` | yes | GitLab | 变量扩展由 GitLab 的[内部变量扩展机制完成](#gitlab-internal-variable-expansion-mechanism) . + +支持为作业定义的所有变量(项目/组变量, `.gitlab-ci.yml`中的变量,触发器中的变量,管道计划中的变量). + +不支持在 Runner 的`config.toml`定义的变量和在 job 的`script`创建的变量. | +| `environment:name` | yes | GitLab | 与`environment:url`相似,但是变量扩展不支持以下内容: + +-基于环境名称的变量( `CI_ENVIRONMENT_NAME` , `CI_ENVIRONMENT_SLUG` ). +-与环境相关的任何其他变量(当前仅`CI_ENVIRONMENT_URL` ). +- [持久变量](#persisted-variables) . | +| `resource_group` | yes | GitLab | 与`environment:url`相似,但是变量扩展不支持以下内容: + +-基于环境名称的变量( `CI_ENVIRONMENT_NAME` , `CI_ENVIRONMENT_SLUG` ). +-与环境相关的任何其他变量(当前仅`CI_ENVIRONMENT_URL` ). +- [持久变量](#persisted-variables) . | +| `variables` | yes | Runner | 变量扩展由 GitLab Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `image` | yes | Runner | 变量扩展由 GitLab Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `services:[]` | yes | Runner | 变量扩展由 GitLab Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `services:[]:name` | yes | Runner | 变量扩展由 GitLab Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `cache:key` | yes | Runner | 变量扩展由 GitLab Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `artifacts:name` | yes | Runner | 变量扩展由 GitLab Runner 的外壳环境完成 | +| `script`, `before_script`, `after_script` | yes | 脚本执行外壳 | 变量扩展由[执行外壳环境进行](#execution-shell-environment) | +| `only:variables:[]`, `except:variables:[]` | no | n/a | 变量必须采用`$variable`的形式. 以下不支持: + +-基于环境名称的变量( `CI_ENVIRONMENT_NAME` , `CI_ENVIRONMENT_SLUG` ). +-与环境相关的任何其他变量(当前仅`CI_ENVIRONMENT_URL` ). +- [持久变量](#persisted-variables) . | + +### `config.toml` file[](#configtoml-file "Permalink") + +**注意:**您可以在[Runner 的 docs 中](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)阅读有关`config.toml`更多信息. + +| Definition | 可以扩大吗? | Description | +| --- | --- | --- | +| `runners.environment` | yes | 变量扩展由 Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `runners.kubernetes.pod_labels` | yes | 变量扩展由 Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | +| `runners.kubernetes.pod_annotations` | yes | 变量扩展由 Runner 的[内部变量扩展机制完成](#gitlab-runner-internal-variable-expansion-mechanism) | + +## Expansion mechanisms[](#expansion-mechanisms "Permalink") + +共有三种扩展机制: + +* GitLab +* 亚搏体育 app Runner +* 执行外壳环境 + +### GitLab internal variable expansion mechanism[](#gitlab-internal-variable-expansion-mechanism "Permalink") + +扩展部分需要采用`$variable`或`${variable}`或`%variable%` . 每种格式都以相同的方式处理,无论最终由哪个 OS / shell 处理,因为扩展是在任何 Runner 获得该工作之前在 GitLab 中完成的. + +### GitLab Runner internal variable expansion mechanism[](#gitlab-runner-internal-variable-expansion-mechanism "Permalink") + +* 支持:项目/组变量, `.gitlab-ci.yml`变量, `config.toml`变量以及触发器,管道计划和手动管道中的变量. +* 不支持:在脚本内部定义的变量(例如, `export MY_VARIABLE="test"` ). + +跑步者使用 Go 的`os.Expand()`方法进行变量扩展. 这意味着它将仅处理定义为`$variable`和`${variable}` . 同样重要的是,扩展只能执行一次,因此嵌套变量可能会或可能不会起作用,这取决于变量定义的顺序. + +### Execution shell environment[](#execution-shell-environment "Permalink") + +这是`script`执行期间发生的扩展. 它的工作方式取决于所使用的 shell( `bash` , `sh` , `cmd` ,PowerShell). 例如,如果作业的`script`包含行`echo $MY_VARIABLE-${MY_VARIABLE_2}` ,则应由 bash / sh 正确处理(保留空字符串或某些值,具体取决于是否定义了变量),但不适用于 Windows 的`cmd`或 PowerShell,因为这些外壳使用不同的变量语法. + +Supported: + +* 该`script`可以使用外壳默认的所有可用变量(例如,应在所有 bash / sh 外壳中包含的`$PATH` )以及 GitLab CI / CD 定义的所有变量(项目/组变量, `.gitlab-ci.yml`变量, `config.toml`变量以及触发器和管道计划中的变量). +* 该`script`还可以使用前面各行中定义的所有变量. 因此,例如,如果您定义变量`export MY_VARIABLE="test"` : + * 在`before_script` ,这将在以下几行工作`before_script`和相关的所有行`script` . + * 在`script` ,它将在以下`script`行中工作. + * 在`after_script` ,它将在`after_script`以下行中`after_script` . + +对于`after_script`脚本,它们可以: + +* 仅在同一`after_script`部分中使用在脚本之前定义的变量. +* 不要使用在`before_script`和`script`定义的变量. + +这些限制是因为`after_script`脚本在[单独的 shell 上下文](../yaml/README.html#before_script-and-after_script)中执行. + +## Persisted variables[](#persisted-variables "Permalink") + +**注意:**一些持久变量包含令牌,由于安全原因,某些定义不能使用它们. + +以下变量称为"持久": + +* `CI_PIPELINE_ID` +* `CI_JOB_ID` +* `CI_JOB_TOKEN` +* `CI_BUILD_ID` +* `CI_BUILD_TOKEN` +* `CI_REGISTRY_USER` +* `CI_REGISTRY_PASSWORD` +* `CI_REPOSITORY_URL` +* `CI_DEPLOY_USER` +* `CI_DEPLOY_PASSWORD` + +他们是: + +* 支持["扩展位置"](#gitlab-ciyml-file)为的定义: + * 赛跑者. + * 脚本执行外壳. +* 不支持: + * 对于["扩展位置"](#gitlab-ciyml-file)是 GitLab 的定义. + * 在`only`和`except` [变量表达式中](README.html#environment-variables-expressions) . + +## Variables with an environment scope[](#variables-with-an-environment-scope "Permalink") + +支持使用环境范围定义的变量. 鉴于在`review/staging/*`范围内定义了一个变量`$STAGING_SECRET` ,将基于匹配的变量表达式创建以下使用动态环境的作业: + +``` +my-job: + stage: staging + environment: + name: review/$CI_JOB_STAGE/deploy + script: + - 'deploy staging' + only: + variables: + - $STAGING_SECRET == 'something' +``` \ No newline at end of file diff --git a/docs/223.md b/docs/223.md new file mode 100644 index 0000000000000000000000000000000000000000..853b4c25debfe15d6d5b64dcf93b23144d5ae2a0 --- /dev/null +++ b/docs/223.md @@ -0,0 +1,30 @@ +# Deprecated GitLab CI/CD variables + +> 原文:[https://docs.gitlab.com/ee/ci/variables/deprecated_variables.html](https://docs.gitlab.com/ee/ci/variables/deprecated_variables.html) + +* [GitLab 9.0 renamed variables](#gitlab-90-renamed-variables) + +# Deprecated GitLab CI/CD variables[](#deprecated-gitlab-cicd-variables "Permalink") + +通读本文档以了解不赞成使用哪些预定义变量及其新引用. + +## GitLab 9.0 renamed variables[](#gitlab-90-renamed-variables "Permalink") + +为了在整个 GitLab 上遵循命名约定,并进一步远离`build`术语而转向`job` ,一些[CI / CD 环境变量](README.html#predefined-environment-variables)被重命名为 GitLab 9.0 版本. + +**注意:**从 GitLab 9.0 开始,我们已弃用`$CI_BUILD_*`变量. **强烈建议您使用新变量,因为我们将在以后的 GitLab 版本中删除旧变量.** + +| 8.x 名称 | 9.0+ name | +| --- | --- | +| `CI_BUILD_BEFORE_SHA` | `CI_COMMIT_BEFORE_SHA` | +| `CI_BUILD_ID` | `CI_JOB_ID` | +| `CI_BUILD_MANUAL` | `CI_JOB_MANUAL` | +| `CI_BUILD_NAME` | `CI_JOB_NAME` | +| `CI_BUILD_REF` | `CI_COMMIT_SHA` | +| `CI_BUILD_REF_NAME` | `CI_COMMIT_REF_NAME` | +| `CI_BUILD_REF_SLUG` | `CI_COMMIT_REF_SLUG` | +| `CI_BUILD_REPO` | `CI_REPOSITORY_URL` | +| `CI_BUILD_STAGE` | `CI_JOB_STAGE` | +| `CI_BUILD_TAG` | `CI_COMMIT_TAG` | +| `CI_BUILD_TOKEN` | `CI_JOB_TOKEN` | +| `CI_BUILD_TRIGGERED` | `CI_PIPELINE_TRIGGERED` | \ No newline at end of file diff --git a/docs/224.md b/docs/224.md new file mode 100644 index 0000000000000000000000000000000000000000..76ec5964158d052f10ba1b05b38190ec1aedfa81 --- /dev/null +++ b/docs/224.md @@ -0,0 +1,853 @@ +# Environments and deployments + +> 原文:[https://docs.gitlab.com/ee/ci/environments/](https://docs.gitlab.com/ee/ci/environments/) + +* [Introduction](#introduction) +* [Configuring environments](#configuring-environments) + * [Defining environments](#defining-environments) + * [Environment variables and Runner](#environment-variables-and-runner) + * [Set dynamic environment URLs after a job finishes](#set-dynamic-environment-urls-after-a-job-finishes) + * [Example of setting dynamic environment URLs](#example-of-setting-dynamic-environment-urls) + * [Configuring manual deployments](#configuring-manual-deployments) + * [Configuring dynamic environments](#configuring-dynamic-environments) + * [Allowed variables](#allowed-variables) + * [Example configuration](#example-configuration) + * [Configuring Kubernetes deployments](#configuring-kubernetes-deployments) + * [Configuring incremental rollouts](#configuring-incremental-rollouts) + * [Deployment safety](#deployment-safety) + * [Complete example](#complete-example) + * [Protected environments](#protected-environments) +* [Working with environments](#working-with-environments) + * [Viewing environments and deployments](#viewing-environments-and-deployments) + * [Viewing deployment history](#viewing-deployment-history) + * [Retrying and rolling back](#retrying-and-rolling-back) + * [What to expect with a rollback](#what-to-expect-with-a-rollback) + * [Using the environment URL](#using-the-environment-url) + * [Going from source files to public pages](#going-from-source-files-to-public-pages) + * [Stopping an environment](#stopping-an-environment) + * [Automatically stopping an environment](#automatically-stopping-an-environment) + * [Environments auto-stop](#environments-auto-stop) + * [Auto-stop example](#auto-stop-example) + * [Delete a stopped environment](#delete-a-stopped-environment) + * [Delete environments through the UI](#delete-environments-through-the-ui) + * [Delete environments through the API](#delete-environments-through-the-api) + * [Prepare an environment](#prepare-an-environment) + * [Grouping similar environments](#grouping-similar-environments) + * [Monitoring environments](#monitoring-environments) + * [Embedding metrics in GitLab Flavored Markdown](#embedding-metrics-in-gitlab-flavored-markdown) + * [Web terminals](#web-terminals) + * [Check out deployments locally](#check-out-deployments-locally) + * [Scoping environments with specs](#scoping-environments-with-specs) + * [Environments Dashboard](#environments-dashboard-premium) +* [Limitations](#limitations) +* [Further reading](#further-reading) + +# Environments and deployments[](#environments-and-deployments "Permalink") + +在 GitLab 8.9 中引入. + +环境允许您在 GitLab 中控制软件的连续部署. + +## Introduction[](#introduction "Permalink") + +在准备将软件投入大众使用之前,软件开发过程需要许多阶段. + +例如: + +1. 开发代码. +2. 测试您的代码. +3. 在将代码发布给公众之前,请将其部署到测试或暂存环境中. + +This helps find bugs in your software, and also in the deployment process as well. + +GitLab CI / CD 不仅能够测试或构建您的项目,而且还可以在基础架构中部署它们,并具有给您提供一种跟踪部署的方式的额外好处. 换句话说,您将始终知道服务器上当前正在部署或已经部署了什么. + +重要的是要知道: + +* 环境就像您的 CI 作业的标签一样,描述了代码的部署位置. +* [作业](../yaml/README.html#introduction)是在[作业](../yaml/README.html#introduction)将代码版本部署到环境时创建的,因此每个环境可以有一个或多个部署. + +GitLab: + +* 提供每种环境的完整部署历史记录. +* 跟踪您的部署,因此您始终知道服务器上当前正在部署什么. + +如果您有与项目关联的部署服务(例如[Kubernetes)](../../user/project/clusters/index.html) ,则可以使用它来协助您的部署,甚至可以从 GitLab 中访问您环境的[Web 终端](#web-terminals) ! + +## Configuring environments[](#configuring-environments "Permalink") + +配置环境涉及: + +1. 了解[管道的](../pipelines/index.html)工作方式. +2. 在项目的[`.gitlab-ci.yml`](../yaml/README.html)文件中定义环境. +3. 创建配置为部署您的应用程序的作业. 例如,配置了[`environment`](../yaml/README.html#environment)的部署作业将您的应用程序部署到[Kubernetes 集群](../../user/project/clusters/index.html) . + +本节的其余部分说明了如何使用示例方案配置环境和部署. 假设您已经: + +* 在 GitLab 中创建了一个[项目](../../gitlab-basics/create-project.html) . +* 设置[亚军](../runners/README.html) . + +在方案中: + +* 我们正在开发一个应用程序. +* 我们想运行测试并在所有分支上构建我们的应用程序. +* 我们的默认分支是`master` . +* We deploy the app only when a pipeline on `master` branch is run. + +### Defining environments[](#defining-environments "Permalink") + +让我们考虑以下`.gitlab-ci.yml`示例: + +``` +stages: + - test + - build + - deploy + +test: + stage: test + script: echo "Running tests" + +build: + stage: build + script: echo "Building the app" + +deploy_staging: + stage: deploy + script: + - echo "Deploy to staging server" + environment: + name: staging + url: https://staging.example.com + only: + - master +``` + +我们定义了三个[阶段](../yaml/README.html#stages) : + +* `test` +* `build` +* `deploy` + +分配给这些阶段的作业将按此顺序运行. 如果任何作业失败,则管道将失败,分配给下一阶段的作业将不会运行. + +在我们的情况下: + +* `test`作业将首先运行. +* 然后是`build`作业. +* 最后, `deploy_staging`作业. + +使用此配置,我们: + +* 检查测试是否通过. +* 确保我们的应用程序能够成功构建. +* 最后,我们部署到登台服务器. + +**注意:** `environment`关键字定义了应用程序的部署位置. 环境`name`和`url`在 GitLab 中的各个位置公开. 每次指定环境的作业成功执行时,都会记录部署,Git SHA 和环境名称.**注意:**环境名称中不允许使用某些字符. 仅使用字母,数字,空格和`-` , `_` , `/` , `{` , `}`或`.` . 另外,它不得以`/`开头或结尾. + +总而言之,使用上述`.gitlab-ci.yml`我们已经实现了以下目标: + +* 所有分支机构将运行`test`并`build`作业. +* `deploy_staging`作业将[仅](../yaml/README.html#onlyexcept-basic)在`master`分支上运行,这意味着从分支创建的所有合并请求都不会部署到登台服务器. +* 合并请求合并后,所有作业将运行,并且`deploy_staging`作业会将我们的代码部署到登台服务器,而部署将记录在名为`staging`的环境中. + +#### Environment variables and Runner[](#environment-variables-and-runner "Permalink") + +从 GitLab 8.15 开始,环境名称以两种形式向 Runner 显示: + +* `$CI_ENVIRONMENT_NAME` . `.gitlab-ci.yml`给出的名称(扩展了所有变量). +* `$CI_ENVIRONMENT_SLUG` . 名称的"清理"版本,适用于 URL,DNS 等. + +如果更改现有环境的名称,则: + +* `$CI_ENVIRONMENT_NAME`变量将使用新的环境名称进行更新. +* `$CI_ENVIRONMENT_SLUG`变量将保持不变,以防止意外的副作用. + +从 GitLab 9.3 开始,环境 URL 通过`$CI_ENVIRONMENT_URL`向 Runner `$CI_ENVIRONMENT_URL` . URL 可以从以下任意一个展开: + +* `.gitlab-ci.yml`. +* 如果未在`.gitlab-ci.yml`定义,则来自环境的外部 URL. + +#### Set dynamic environment URLs after a job finishes[](#set-dynamic-environment-urls-after-a-job-finishes "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/17066) . + +在作业脚本中,您可以指定静态[环境 URL](#using-the-environment-url) . 但是,有时可能需要动态 URL. 例如,如果您将 Review App 部署到一个外部托管服务,该服务会为每个部署生成一个随机 URL,例如`https://94dd65b.amazonaws.com/qa-lambda-1234567` ,则在部署脚本之前您不会知道该 URL 完成. 如果要在 GitLab 中使用环境 URL,则必须手动更新. + +为了解决此问题,您可以配置部署作业以报告一组变量,包括由外部服务动态生成的 URL. GitLab 支持[dotenv( `.env` )](https://github.com/bkeepers/dotenv)文件格式,并使用`.env`文件中定义的变量扩展`environment:url`值. + +要使用此功能,请在`.gitlab-ci.yml`指定[`artifacts:reports:dotenv`](../pipelines/job_artifacts.html#artifactsreportsdotenv)关键字. + +有关概述,请参阅[在作业完成后设置动态 URL](https://youtu.be/70jDXtOf4Ig) . + +##### Example of setting dynamic environment URLs[](#example-of-setting-dynamic-environment-urls "Permalink") + +以下示例显示了一个 Review App,该 App 为每个合并请求创建一个新环境. 每次推送都会触发`review`作业,并创建或更新一个名为`review/your-branch-name` . 环境 URL 设置为`$DYNAMIC_ENVIRONMENT_URL` : + +``` +review: + script: + - DYNAMIC_ENVIRONMENT_URL=$(deploy-script) # In script, get the environment URL. + - echo "DYNAMIC_ENVIRONMENT_URL=$DYNAMIC_ENVIRONMENT_URL" >> deploy.env # Add the value to a dotenv file. + artifacts: + reports: + dotenv: deploy.env # Report back dotenv file to rails. + environment: + name: review/$CI_COMMIT_REF_SLUG + url: $DYNAMIC_ENVIRONMENT_URL # and set the variable produced in script to `environment:url` + on_stop: stop_review + +stop_review: + script: + - ./teardown-environment + when: manual + environment: + name: review/$CI_COMMIT_REF_SLUG + action: stop +``` + +`review`作业完成后,GitLab 会立即更新`review/your-branch-name`环境的 URL. 它解析`deploy.env`报告工件,将变量列表注册为在运行时创建的变量,并将其用于扩展`environment:url: $DYNAMIC_ENVIRONMENT_URL`并将其设置为环境 URL. 您还可以在`environment:url:`处指定 URL 的静态部分,例如`https://$DYNAMIC_ENVIRONMENT_URL` . 如果`DYNAMIC_ENVIRONMENT_URL`值为`example.com` ,则最终结果将为`https://example.com` . + +[在 UI 中可以看到](#using-the-environment-url)为`review/your-branch-name`环境分配的 URL. + +> **Notes:** +> +> * `stop_review`不会生成 dotenv 报告工件,因此不会识别`DYNAMIC_ENVIRONMENT_URL`变量. 因此,您不应在`stop_review`作业中设置`environment:url:` `stop_review` +> * 如果环境 URL 无效(例如,URL 格式错误),则系统不会更新环境 URL. + +### Configuring manual deployments[](#configuring-manual-deployments "Permalink") + +添加`when: manual`添加到自动执行的作业的配置会将其转换为需要手动操作的作业. + +为了扩展[前面的示例](#defining-environments) ,以下内容包括另一个作业,该作业将我们的应用程序部署到生产服务器,并由`production`环境进行跟踪. + +`.gitlab-ci.yml`文件如下: + +``` +stages: + - test + - build + - deploy + +test: + stage: test + script: echo "Running tests" + +build: + stage: build + script: echo "Building the app" + +deploy_staging: + stage: deploy + script: + - echo "Deploy to staging server" + environment: + name: staging + url: https://staging.example.com + only: + - master + +deploy_prod: + stage: deploy + script: + - echo "Deploy to production server" + environment: + name: production + url: https://example.com + when: manual + only: + - master +``` + +The `when: manual` action: + +* 在 GitLab 的用户界面中显示该作业的"播放"按钮. +* 意味着仅在单击"播放"按钮时才会触发`deploy_prod`作业. + +您可以在管道,环境,部署和作业视图中找到"播放"按钮. + +| View | Screenshot | +| --- | --- | +| Pipelines | [![Pipelines manual action](img/379bd77b46dd7f0617bc273a203c9a29.png)](../img/environments_manual_action_pipelines.png) | +| 单管道 | [![Pipelines manual action](img/e2e1d44121ea24d32b388b9b84bd7ea5.png)](../img/environments_manual_action_single_pipeline.png) | +| Environments | [![Environments manual action](img/14b1dcd13ed2d776e5cab726504e2df9.png)](../img/environments_manual_action_environments.png) | +| Deployments | [![Deployments manual action](img/85b07bb9804f9dd3c4e3edfc1e562f31.png)](../img/environments_manual_action_deployments.png) | +| Jobs | [![Builds manual action](img/ef8ff296b4a28ddcd52a6c4fd3ded454.png)](../img/environments_manual_action_jobs.png) | + +在任何视图中单击播放按钮都将触发`deploy_prod`作业,并且部署将记录为名为`production`的新环境. + +**注意:**如果您环境的名称是`production` (全部为小写),它将记录在[Value Stream Analytics 中](../../user/project/cycle_analytics.html) . + +### Configuring dynamic environments[](#configuring-dynamic-environments "Permalink") + +当部署到"稳定"的环境(例如分阶段或生产)时,常规环境会很好. + +但是,对于`master`以外的分支环境,可以使用动态环境. 动态环境可以通过在`.gitlab-ci.yml`动态声明其名称来动态创建环境. + +动态环境是[Review 应用程序](../review_apps/index.html)的基本组成部分. + +#### Allowed variables[](#allowed-variables "Permalink") + +动态环境的`name`和`url`参数可以使用大多数可用的 CI / CD 变量,包括: + +* [Predefined environment variables](../variables/README.html#predefined-environment-variables) +* [Project and group variables](../variables/README.html#gitlab-cicd-environment-variables) +* [`.gitlab-ci.yml` variables](../yaml/README.html#variables) + +但是,不能使用定义的变量: + +* Under `script`. +* 在跑步者方面. + +在`environment:name`上下文中还不支持其他变量. 有关更多信息,请参见[在哪里可以使用变量](../variables/where_variables_can_be_used.html) . + +#### Example configuration[](#example-configuration "Permalink") + +GitLab Runner 在作业运行时会公开各种[环境变量](../variables/README.html) ,因此您可以将它们用作环境名称. + +在以下示例中,作业将部署到`master`以外的所有分支: + +``` +deploy_review: + stage: deploy + script: + - echo "Deploy a review app" + environment: + name: review/$CI_COMMIT_REF_NAME + url: https://$CI_ENVIRONMENT_SLUG.example.com + only: + - branches + except: + - master +``` + +在此示例中: + +* 作业的名称为`deploy_review` ,它在`deploy`阶段运行. +* 我们将`environment`设置为`environment` `environment:name`作为`review/$CI_COMMIT_REF_NAME` . 由于[环境名称](../yaml/README.html#environmentname)可以包含斜杠( `/` ),因此我们可以使用此模式来区分动态环境和常规环境. +* We tell the job to run [`only`](../yaml/README.html#onlyexcept-basic) on branches, [`except`](../yaml/README.html#onlyexcept-basic) `master`. + +对于以下值: + +* `environment:name` ,第一部分是`review` ,后跟一个`/` ,然后是`$CI_COMMIT_REF_NAME` ,它接收分支名称的值. +* `environment:url` ,我们希望每个分支都有一个特定且不同的 URL. `$CI_COMMIT_REF_NAME`可能包含`/`或其他在域名或 URL 中无效的字符,因此我们使用`$CI_ENVIRONMENT_SLUG`来确保获得有效的 URL. + + 例如,给定`$CI_COMMIT_REF_NAME`为`100-Do-The-Thing` ,URL 将类似于`https://100-do-the-4f99a2.example.com` . 同样,设置 Web 服务器来满足这些请求的方式取决于您的设置. + + 我们在这里使用了`$CI_ENVIRONMENT_SLUG` ,因为它保证是唯一的. 如果您使用的是[GitLab Flow 之](../../topics/gitlab_flow.html)类的工作[流程](../../topics/gitlab_flow.html) ,则冲突不太可能发生,并且您可能更希望环境名称与分支名称更紧密地[关联](../../topics/gitlab_flow.html) . 在这种情况下,您可以在上面的示例中的`environment:url`中使用`$CI_COMMIT_REF_NAME` : `https://$CI_COMMIT_REF_NAME.example.com` ,其 URL 为`https://100-do-the-thing.example.com` . + +**注意:**您不需要在动态环境的名称中使用相同的前缀或仅使用斜杠( `/` ). 但是,使用此格式将启用[类似环境分组](#grouping-similar-environments)功能. + +### Configuring Kubernetes deployments[](#configuring-kubernetes-deployments "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) . + +如果要部署到与项目关联的[Kubernetes 集群](../../user/project/clusters/index.html) ,则可以从`gitlab-ci.yml`文件配置这些部署. + +支持以下配置选项: + +* [`namespace`](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) + +在以下示例中,作业会将您的应用程序部署到`production` Kubernetes 命名空间. + +``` +deploy: + stage: deploy + script: + - echo "Deploy to production server" + environment: + name: production + url: https://example.com + kubernetes: + namespace: production + only: + - master +``` + +使用 GitLab 的 Kubernetes 集成部署到 Kubernetes 集群时,有关集群和名称空间的信息将显示在部署作业页面上的作业跟踪上方: + +[![Deployment cluster information](img/5e3cf2019e5c2c58b6dd5868fffb9e81.png)](../img/environments_deployment_cluster_v12_8.png) + +**注意:** [由 GitLab 管理的](../../user/project/clusters/index.html#gitlab-managed-clusters) Kubernetes 集群不支持 Kubernetes 配置. 要跟踪对 GitLab 管理的集群的支持进度,请参阅[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/38054) . + +#### Configuring incremental rollouts[](#configuring-incremental-rollouts "Permalink") + +了解如何通过[增量部署](../environments/incremental_rollouts.html)仅对 Kubernetes Pod 的一部分发布生产更改. + +### Deployment safety[](#deployment-safety "Permalink") + +部署作业可能比管道中的其他作业更敏感,并且可能需要格外小心. GitLab 中有多个功能可帮助维护部署安全性和稳定性. + +* [Restrict write-access to a critical environment](deployment_safety.html#restrict-write-access-to-a-critical-environment) +* [Limit the job-concurrency for deployment jobs](deployment_safety.html#ensure-only-one-deployment-job-runs-at-a-time) +* [Skip outdated deployment jobs](deployment_safety.html#skip-outdated-deployment-jobs) +* [Prevent deployments during deploy freeze windows](deployment_safety.html#prevent-deployments-during-deploy-freeze-windows) + +### Complete example[](#complete-example "Permalink") + +本节中的配置提供了完整的开发工作流程,其中您的应用程序是: + +* Tested. +* Built. +* 部署为 Review App. +* 合并请求合并后,部署到登台服务器. +* 最后,能够手动部署到生产服务器. + +以下内容结合了之前的配置示例,包括: + +* Defining [simple environments](#defining-environments) for testing, building, and deployment to staging. +* 添加[手动操作](#configuring-manual-deployments)以部署到生产中. +* 为部署创建[动态环境](#configuring-dynamic-environments)以供查看. + +``` +stages: + - test + - build + - deploy + +test: + stage: test + script: echo "Running tests" + +build: + stage: build + script: echo "Building the app" + +deploy_review: + stage: deploy + script: + - echo "Deploy a review app" + environment: + name: review/$CI_COMMIT_REF_NAME + url: https://$CI_ENVIRONMENT_SLUG.example.com + only: + - branches + except: + - master + +deploy_staging: + stage: deploy + script: + - echo "Deploy to staging server" + environment: + name: staging + url: https://staging.example.com + only: + - master + +deploy_prod: + stage: deploy + script: + - echo "Deploy to production server" + environment: + name: production + url: https://example.com + when: manual + only: + - master +``` + +一个更现实的示例还包括将文件复制到 Web 服务器(例如 NGINX)可以访问并为其提供服务的位置. + +下面的示例将`public`目录复制到`/srv/nginx/$CI_COMMIT_REF_SLUG/public` : + +``` +review_app: + stage: deploy + script: + - rsync -av --delete public /srv/nginx/$CI_COMMIT_REF_SLUG + environment: + name: review/$CI_COMMIT_REF_NAME + url: https://$CI_COMMIT_REF_SLUG.example.com +``` + +此示例要求在要运行此作业的服务器上设置 NGINX 和 GitLab Runner. + +**注意:**有关分支机构和 Review Apps 命名的一些极端情况,请参阅" [限制"](#limitations)部分. + +完整的示例为开发人员提供了以下工作流程: + +* 在本地创建分支. +* 进行更改并提交. +* 将分支推送到 GitLab. +* 创建一个合并请求. + +在后台,GitLab Runner 将: + +* 拾取更改并开始运行作业. +* 按`stages`定义顺序运行作业: + * 首先,运行测试. + * 如果测试成功,请构建应用程序. + * 如果构建成功,则将应用程序部署到具有特定于分支机构名称的环境. + +所以现在,每个分支: + +* 获取自己的环境. +* 已部署到其自己的唯一位置,具有以下优点: + * 有[部署历史](#viewing-deployment-history) . + * 如果需要,能够[回滚更改](#retrying-and-rolling-back) . + +有关更多信息,请参见[使用环境 URL](#using-the-environment-url) . + +### Protected environments[](#protected-environments "Permalink") + +可以对环境进行"保护",限制对它们的访问. + +有关更多信息,请参阅[受保护的环境](protected_environments.html) . + +## Working with environments[](#working-with-environments "Permalink") + +配置环境后,GitLab 将提供许多用于处理环境的功能,如下所述. + +### Viewing environments and deployments[](#viewing-environments-and-deployments "Permalink") + +每个项目的" **操作">"环境"**页面上都提供了环境和部署状态的列表. + +例如: + +[![Environment view](img/9121e1772146daa5a3259be82cde8902.png)](../img/environments_available.png) + +此示例显示: + +* 环境名称以及指向其部署的链接. +* 最后的部署 ID 号以及执行者. +* 上次部署的作业 ID 及其各自的作业名称. +* 上次部署的提交信息,例如谁提交了它,到哪个分支以及提交的 Git SHA. +* 上次部署的确切时间. +* 该按钮`.gitlab-ci.yml`您带到您在`.gitlab-ci.yml`的`environment`关键字下定义的 URL. +* 重新部署最新部署的按钮,这意味着它将运行由环境名称定义的特定提交的作业. + +" **环境"**页面中显示的信息仅限于最新的部署,但是一个环境可以具有多个部署. + +> **Notes:** +> +> * 虽然您可以在 Web 界面中手动创建环境,但建议您首先在`.gitlab-ci.yml`定义环境. 首次部署后,将自动为您创建它们. +> * 只有具有[Reporter 权限](../../user/permissions.html#project-members-permissions)及以上[权限](../../user/permissions.html#project-members-permissions)的用户才能查看环境页面. 有关权限的更多信息,请参阅[权限文档](../../user/permissions.html) . +> * 只有在正确配置`.gitlab-ci.yml`之后发生的部署才会显示在" **环境"**和" **最后部署"**列表中. + +### Viewing deployment history[](#viewing-deployment-history "Permalink") + +GitLab keeps track of your deployments, so you: + +* 始终知道服务器上当前正在部署什么. +* 可以具有每种环境的完整部署历史记录. + +单击环境可显示其部署的历史记录. 这是具有多个部署的**环境**示例页面: + +[![Deployments](img/e3feca46add6d42b1afc92fcf120dbfb.png)](../img/deployments_view.png) + +该视图类似于" **环境"**页面,但是显示了所有部署. 在此视图中,还有一个" **回滚"**按钮. 有关更多信息,请参阅[重试和回滚](#retrying-and-rolling-back) . + +### Retrying and rolling back[](#retrying-and-rolling-back "Permalink") + +如果部署存在问题,则可以重试或回滚. + +要重试或回滚部署: + +1. 导航到" **操作">"环境"** . +2. 单击环境. +3. 在环境的部署历史记录列表中,单击: + * 最后部署旁边的" **重试"**按钮,以重试该部署. + * 先前成功部署旁边的" **回滚"**按钮,以回滚到该部署. + +#### What to expect with a rollback[](#what-to-expect-with-a-rollback "Permalink") + +在特定提交上按**回滚**按钮将触发具有其自己的唯一作业 ID 的*新*部署. + +这意味着您将看到一个新的部署,该部署指向您要回滚的提交. + +**注意:**作业`script`定义的部署过程确定回滚是否成功. + +### Using the environment URL[](#using-the-environment-url "Permalink") + +[环境 URL](../yaml/README.html#environmenturl)在 GitLab 中的几个位置公开: + +* 在合并请求小部件中作为链接: [![合并请求中的环境 URL](img/3d8b21038a5aa14baa75dc65de55d728.png)](../img/environments_mr_review_app.png) +* 在"环境"视图中作为按钮: [![环境中的环境 URL](img/9121e1772146daa5a3259be82cde8902.png)](../img/environments_available.png) +* 在"部署"视图中作为按钮: [![部署中的环境 URL](img/e3feca46add6d42b1afc92fcf120dbfb.png)](../img/deployments_view.png) + +在以下情况下,您可以在合并请求本身中看到此信息: + +* 合并请求最终合并到默认分支(通常是`master` ). +* 该分支还部署到环境(例如, `staging`或`production` ). + +例如: + +[![Environment URLs in merge request](img/061d5d0d60fdf019ad696860942563af.png)](../img/environments_link_url_mr.png) + +#### Going from source files to public pages[](#going-from-source-files-to-public-pages "Permalink") + +使用 GitLab 的[路线图,](../review_apps/index.html#route-maps)您可以在为 Review Apps 设置的环境中直接从源文件转到公共页面. + +### Stopping an environment[](#stopping-an-environment "Permalink") + +停止环境: + +* 将其从" **可用"**环境列表移至" [**环境"**页面](#viewing-environments-and-deployments)上的"已**停止"**环境列表. +* 执行[`on_stop`操作](../yaml/README.html#environmenton_stop) (如果已定义). + +当多个开发人员同时在一个项目上工作时,通常会使用此方法,每个开发人员都将推入自己的分支,从而创建了许多动态环境. + +**注意:**从 GitLab 8.14 开始,删除动态环境的关联分支后,它们会自动停止. + +#### Automatically stopping an environment[](#automatically-stopping-an-environment "Permalink") + +可以使用特殊配置自动停止环境. + +考虑以下示例,其中`deploy_review`作业调用`stop_review`清理并停止环境: + +``` +deploy_review: + stage: deploy + script: + - echo "Deploy a review app" + environment: + name: review/$CI_COMMIT_REF_NAME + url: https://$CI_ENVIRONMENT_SLUG.example.com + on_stop: stop_review + only: + - branches + except: + - master + +stop_review: + stage: deploy + variables: + GIT_STRATEGY: none + script: + - echo "Remove review app" + when: manual + environment: + name: review/$CI_COMMIT_REF_NAME + action: stop +``` + +设置[`GIT_STRATEGY`](../yaml/README.html#git-strategy)到`none`是必要的`stop_review`使各项工作[GitLab 亚军](https://docs.gitlab.com/runner/)不会尝试分支被删除后退房的代码. + +当您的环境中定义了停止动作时(通常在该环境描述了 Review App 时),当关联的分支被删除时,GitLab 将自动触发停止动作. `stop_review`作业必须与`deploy_review`作业处于同一`stage` ,以便环境自动停止. + +此外,两个作业都应具有匹配的[`rules`](../yaml/README.html#onlyexcept-basic)或[`only/except`](../yaml/README.html#onlyexcept-basic)配置[`only/except`](../yaml/README.html#onlyexcept-basic) . 在上面的示例中,如果配置不同,则`stop_review`作业可能不会包含在所有包含`deploy_review`作业的管道中,并且将无法触发该`action: stop`会自动停止环境. + +您可以在[`.gitlab-ci.yml`参考中](../yaml/README.html#environmenton_stop)阅读更多[`.gitlab-ci.yml`](../yaml/README.html#environmenton_stop) . + +#### Environments auto-stop[](#environments-auto-stop "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/20956) . + +您可以设置环境的到期时间,并在一定时间后自动将其停止. + +例如,考虑在 Review Apps 环境中使用此功能. 设置 Review Apps 时,有时它们会长时间运行,因为某些合并请求处于打开状态. 这种情况的一个示例是,由于优先级更改或决定采用其他方法而导致合并请求的作者未积极处理合并请求,而合并请求却被遗忘了. 空闲环境会浪费资源,因此应尽快终止它们. + +要解决此问题,您可以为 Review Apps 环境指定一个可选的到期日期. 当达到到期时间时,GitLab 将自动触发作业以停止环境,而无需手动执行此操作. 万一更新了环境,则到期将得到更新,以确保只有活动的合并请求才能继续运行 Review Apps. + +要启用此功能,您需要在`.gitlab-ci.yml`指定[`environment:auto_stop_in`](../yaml/README.html#environmentauto_stop_in)关键字. 您可以指定一个对人类友好的日期作为值,例如`1 hour and 30 minutes`或`1 day` . `auto_stop_in`使用相同的[`artifacts:expire_in`](../yaml/README.html#artifactsexpire_in)格式[`artifacts:expire_in` docs](../yaml/README.html#artifactsexpire_in) . + +**注意:**由于资源限制,用于停止环境的后台工作器每小时仅运行一次. 这意味着不会按指定的确切时间在特定的时间戳记下停止环境,而是在每小时的 cron 工作者检测到过期的环境时将其停止. + +##### Auto-stop example[](#auto-stop-example "Permalink") + +在以下示例中,有一个基本的审阅应用程序设置,可为每个合并请求创建一个新环境. 每次推送都会触发`review_app`作业,并创建或更新一个名为`review/your-branch-name` . 环境一直运行,直到执行`stop_review_app` : + +``` +review_app: + script: deploy-review-app + environment: + name: review/$CI_COMMIT_REF_NAME + on_stop: stop_review_app + auto_stop_in: 1 week + +stop_review_app: + script: stop-review-app + environment: + name: review/$CI_COMMIT_REF_NAME + action: stop + when: manual +``` + +只要合并请求处于活动状态并不断获得新的提交,审阅应用程序就不会停止,因此开发人员无需担心重新启动审阅应用程序. + +另一方面,由于将`stop_review_app`设置为`auto_stop_in: 1 week` ,如果合并请求变得不活动超过一个星期,则 G​​itLab 会自动触发`stop_review_app`作业以停止环境. + +您还可以通过 GitLab UI 检查环境的到期日期. 为此,请转到**操作>环境>环境** . 您可以在左上部分看到自动停止时间,并在右上部分看到一个记号按钮. 此固定标记按钮可用于防止环境自动停止. 单击此按钮,将`auto_stop_in`设置,并且环境将处于活动状态,直到手动将其停止为止. + +[![Environment auto stop](img/c67faf1fb34407861ed68b426e46da72.png)](../img/environment_auto_stop_v12_8.png) + +#### Delete a stopped environment[](#delete-a-stopped-environment "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/20620) . + +您可以通过以下两种方式之一删除已[停止的环境](#stopping-an-environment) :通过 GitLab UI 或通过 API. + +##### Delete environments through the UI[](#delete-environments-through-the-ui "Permalink") + +要查看已**停止**环境的列表,请导航至" **操作">"环境"** ,然后单击"已**停止"**选项卡. + +在此处,您可以直接单击" **删除"**按钮,也可以单击环境名称以查看其详细信息,然后从此处**删除**它. + +您还可以通过查看已停止环境的详细信息来删除环境: + +1. 导航到" **操作">"环境"** . +2. 在"已**停止的**环境"列表中单击环境的名称. +3. 单击显示在所有已停止环境顶部的" **删除"**按钮. +4. 最后,在似乎要删除它的模式中确认您选择的环境. + +##### Delete environments through the API[](#delete-environments-through-the-api "Permalink") + +也可以使用[Environments API](../../api/environments.html#delete-an-environment)删除[环境](../../api/environments.html#delete-an-environment) . + +### Prepare an environment[](#prepare-an-environment "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/208655) . + +默认情况下,每次运行具有指定环境的构建时,GitLab 都会创建一个[部署](#viewing-deployment-history) . 较新的部署也可以[取消较旧的](deployment_safety.html#skip-outdated-deployment-jobs)部署. + +您可能需要指定一个环境关键字来[保护构建免受未经授权的访问](protected_environments.html) ,或获得对[范围变量的](#scoping-environments-with-specs)访问. 在这些情况下,可以使用以下`action: prepare`关键字以确保不会创建部署,并且不会取消任何构建: + +``` +build: + stage: build + script: + - echo "Building the app" + environment: + name: staging + action: prepare + url: https://staging.example.com +``` + +### Grouping similar environments[](#grouping-similar-environments "Permalink") + +在 GitLab 8.14 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7015) . + +如[配置动态环境中所述](#configuring-dynamic-environments) ,您可以在环境名称前添加一个单词,后跟一个`/` ,最后是分支名称,该分支名称由`CI_COMMIT_REF_NAME`变量自动定义. + +简而言之,所有名为`type/foo`的环境都在同一个名为`type`组下显示. + +在[最小的示例中](#example-configuration) ,我们将环境命名为`review/$CI_COMMIT_REF_NAME` ,其中`$CI_COMMIT_REF_NAME`是分支名称. 这是示例的片段: + +``` +deploy_review: + stage: deploy + script: + - echo "Deploy a review app" + environment: + name: review/$CI_COMMIT_REF_NAME +``` + +在这种情况下,如果您访问" **环境"**页面并且分支存在,则应该看到类似以下内容的内容: + +[![Environment groups](img/60958029f56e4c49c6a21082ea151191.png)](../img/environments_dynamic_groups.png) + +### Monitoring environments[](#monitoring-environments "Permalink") + +如果已启用[Prometheus 来监视系统和响应指标](../../user/project/integrations/prometheus.html) ,则可以监视在每个环境中运行的应用程序的行为. 为了显示监视仪表板,您需要配置 Prometheus 来收集至少一个[支持的指标](../../user/project/integrations/prometheus_library/index.html) . + +**注意:**从 GitLab 9.2 开始,到环境的所有部署都直接显示在监视仪表板上. + +配置完成后,GitLab 将尝试为成功部署的任何环境检索[支持的性能指标](../../user/project/integrations/prometheus_library/index.html) . 如果成功检索到监视数据,则将为每个环境显示一个" **监视"**按钮. + +[![Environment Detail with Metrics](img/e3feca46add6d42b1afc92fcf120dbfb.png)](../img/deployments_view.png) + +单击" **监视"**按钮将显示一个新页面,该页面最多显示最近 8 个小时的性能数据. 初始部署后,可能需要一两分钟的时间才能显示数据. + +环境的所有部署都直接显示在监视仪表板上,这使性能的任何变化与应用程序的新版本之间都可以轻松关联,而无需离开 GitLab. + +[![Monitoring dashboard](img/8c80632a58ede646cb8f2046924a504a.png)](../img/environments_monitoring.png) + +#### Embedding metrics in GitLab Flavored Markdown[](#embedding-metrics-in-gitlab-flavored-markdown "Permalink") + +公制图表可以嵌入到 GitLab Flavored Markdown 中. 有关更多详细信息,请参见[在 GitLab 风味 Markdown 中嵌入指标](../../operations/metrics/embed.html) . + +### Web terminals[](#web-terminals "Permalink") + +> Web 终端已在 GitLab 8.15 中添加,仅对项目维护者和所有者可用. + +If you deploy to your environments with the help of a deployment service (for example, the [Kubernetes integration](../../user/project/clusters/index.html)), GitLab can open a terminal session to your environment. + +这是一项功能强大的功能,可让您调试问题而不会离开 Web 浏览器. 要启用它,只需按照服务集成文档中给出的说明进行操作. + +启用后,您的环境将获得一个"终端"按钮: + +[![Terminal button on environment index](img/47c6e09feffe93d1d9f758d50837b31b.png)](../img/environments_terminal_button_on_index.png) + +您还可以从页面访问特定环境的终端按钮: + +[![Terminal button for an environment](img/b6d33f6e98bcf842659df9a637bbaeb9.png)](../img/environments_terminal_button_on_show.png) + +无论在哪里找到它,单击按钮都会带您到单独的页面来建立终端会话: + +[![Terminal page](img/92601175945fcac1aee644fd449e9adf.png)](../img/environments_terminal_page.png) + +就像其他终端一样工作. 您将处于部署创建的容器中,因此您可以: + +* 运行 shell 命令并实时获取响应. +* 检查日志. +* 试用配置或代码调整等. + +您可以在同一环境中打开多个终端,它们每个都有自己的 shell 会话,甚至可以是`screen`或`tmux`的多路复用器. + +**注意:**基于容器的部署通常缺少基本工具(例如编辑器),并且可以随时停止或重新启动. 如果发生这种情况,您将丢失所有更改. 将此视为调试工具,而不是全面的在线 IDE. + +### Check out deployments locally[](#check-out-deployments-locally "Permalink") + +从 GitLab 8.13 开始,每次部署都会在 Git 存储库中保存一个引用,因此仅需`git fetch`知道当前环境的状态. + +In your Git configuration, append the `[remote "<your-remote>"]` block with an extra fetch line: + +``` +fetch = +refs/environments/*:refs/remotes/origin/environments/* +``` + +### Scoping environments with specs[](#scoping-environments-with-specs "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2112) . +* 在 GitLab 12.2 中将[环境变量的作用域移至 Core](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30779) . + +您可以通过定义变量可用于的环境来限制变量的环境范围. + +可以使用通配符,默认环境范围是`*` ,这意味着任何作业都将具有此变量,与是否定义环境无关. + +例如,如果环境范围是`production` ,那么只有定义了环境`production`的作业才具有此特定变量. 通配符( `*` )可以与环境名称一起使用,因此,如果环境范围是`review/*`那么任何以环境名称以`review/`开头的作业都将具有该特定变量. + +对于每个环境,某些 GitLab 功能可能会有不同的行为. 例如,您可以[创建一个秘密变量,仅将其注入生产环境](../variables/README.html#limit-the-environment-scopes-of-environment-variables) . + +在大多数情况下,这些功能使用*环境规范*机制,该机制提供了一种在每个环境组内实现作用域的有效方法. + +假设有四种环境: + +* `production` +* `staging` +* `review/feature-1` +* `review/feature-2` + +Each environment can be matched with the following environment spec: + +| 环境规格 | `production` | `staging` | `review/feature-1` | `review/feature-2` | +| --- | --- | --- | --- | --- | +| * | Matched | Matched | Matched | Matched | +| production | Matched |   |   |   | +| staging |   | Matched |   |   | +| review/* |   |   | Matched | Matched | +| review/feature-1 |   |   | Matched |   | + +如您所见,您可以使用特定的匹配来选择特定的环境,也可以使用通配符匹配( `*` )来选择特定的环境组,例如[Review Apps](../review_apps/index.html) ( `review/*` ). + +**注意:**最*具体的*规范优先于其他通配符匹配. 在这种情况下, `review/feature-1`规范优先于`review/*`和`*`规范. + +### Environments Dashboard[](#environments-dashboard-premium "Permalink") + +有关每个环境的运行状况的摘要,请参见[环境仪表板](../environments/environments_dashboard.html) . + +## Limitations[](#limitations "Permalink") + +在`environment: name` ,您仅限于[预定义的环境变量](../variables/predefined_variables.html) . 重用`script`内部定义为环境名称一部分的变量将不起作用. + +## Further reading[](#further-reading "Permalink") + +以下是一些您可能会发现有趣的链接: + +* [The `.gitlab-ci.yml` definition of environments](../yaml/README.html#environment) +* [A blog post on Deployments & Environments](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/) +* [Review Apps - Use dynamic environments to deploy your code for every branch](../review_apps/index.html) +* [Deploy Boards for your applications running on Kubernetes](../../user/project/deploy_boards.html) \ No newline at end of file diff --git a/docs/225.md b/docs/225.md new file mode 100644 index 0000000000000000000000000000000000000000..9bb6b86f0f33ebbcdcacee8f754a68eaba697fa4 --- /dev/null +++ b/docs/225.md @@ -0,0 +1,52 @@ +# Protected Environments + +> 原文:[https://docs.gitlab.com/ee/ci/environments/protected_environments.html](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) + +* [Overview](#overview) +* [Protecting environments](#protecting-environments) +* [Modifying and unprotecting environments](#modifying-and-unprotecting-environments) + +# Protected Environments[](#protected-environments-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6303) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.3. + +## Overview[](#overview "Permalink") + +可以出于多种原因使用[环境](../environments/index.html) : + +* 其中一些仅用于测试. +* 其他用于生产. + +由于部署工作可以由具有不同角色的不同用户来提出,因此对"特定"环境进行"保护"以防止未经授权的人员影响他们很重要. + +默认情况下,受保护的环境会做一件事:它确保只有具有适当特权的人才能部署到该环境,从而确保其安全. + +**注意:**始终允许 GitLab 管理员使用环境,即使环境受到保护也是如此. + +要保护,更新或取消保护环境,您至少需要具有[维护者权限](../../user/permissions.html) . + +## Protecting environments[](#protecting-environments "Permalink") + +为了保护环境: + +1. 导航到项目的**"设置">" CI / CD"** . +2. 展开" **保护环境"**部分. +3. 从" **环境"**下拉菜单中,选择要保护的环境. +4. 在" **允许部署"**下拉菜单中,选择要授予其部署访问权限的角色,用户或组. 请记住: + * 有两种角色可供选择: + * **维护者** :将允许访问项目中的所有维护者. + * **开发人员** :将允许访问该项目中的所有维护人员和所有开发人员. + * 您只能选择已经与项目关联的组. + * 只有具有至少开发人员权限级别的用户才会显示在" **允许部署"**下拉菜单中. +5. 单击**保护**按钮. + +现在,受保护的环境将出现在受保护环境的列表中. + +## Modifying and unprotecting environments[](#modifying-and-unprotecting-environments "Permalink") + +维护者可以: + +* 通过在" **允许部署"**下拉菜单中更改访问权限,可以随时更新现有的受保护环境. +* 通过单击该环境的" **取消保护"**按钮来**取消保护**该环境. + +有关更多信息,请参阅[部署安全](deployment_safety.html) . \ No newline at end of file diff --git a/docs/226.md b/docs/226.md new file mode 100644 index 0000000000000000000000000000000000000000..0a508732bc371af564f93c4cedd40e2779ce55e2 --- /dev/null +++ b/docs/226.md @@ -0,0 +1,174 @@ +# GitLab CI/CD Examples + +> 原文:[https://docs.gitlab.com/ee/ci/examples/README.html](https://docs.gitlab.com/ee/ci/examples/README.html) + +* [CI/CD examples](#cicd-examples) + * [Contributing examples](#contributing-examples) +* [CI/CD templates](#cicd-templates) + * [Adding templates to your GitLab installation](#adding-templates-to-your-gitlab-installation-premium-only) +* [Other resources](#other-resources) + * [CI/CD in the cloud](#cicd-in-the-cloud) + * [Customer stories](#customer-stories) + * [Getting started](#getting-started) + * [Implementing GitLab CI/CD](#implementing-gitlab-cicd) + * [Migrating to GitLab from third-party CI tools](#migrating-to-gitlab-from-third-party-ci-tools) + * [Integrating GitLab CI/CD with other systems](#integrating-gitlab-cicd-with-other-systems) + * [Mobile development](#mobile-development) + +# GitLab CI/CD Examples[](#gitlab-cicd-examples "Permalink") + +该页面包含指向各种示例的链接,这些示例可以帮助您了解如何针对特定用例实现[GitLab CI / CD](../README.html) . + +示例有几种形式. 作为以下内容的集合: + +* 在 GitLab 中维护的`.gitlab-ci.yml` [模板文件](#cicd-templates) ,用于许多常见的框架和编程语言. +* 具有各种语言[示例项目的](https://gitlab.com/gitlab-examples)存储库. 您可以分叉并根据自己的需要进行调整. 项目包括[多项目管道的](https://gitlab.com/gitlab-examples/multi-project-pipelines)演示以及[在 NGINX 服务的静态站点上](https://gitlab.com/gitlab-examples/review-apps-nginx/)使用[Review Apps](https://gitlab.com/gitlab-examples/review-apps-nginx/) . +* 下面列出了示例和[其他资源](#other-resources) . + +## CI/CD examples[](#cicd-examples "Permalink") + +下表列出了本节中包含分步教程的示例. + +| 用例 | Resource | +| --- | --- | +| 浏览器性能测试 | [Browser Performance Testing with the Sitespeed.io container](../../user/project/merge_requests/browser_performance_testing.html). | +| 负载性能测试 | [Load Performance Testing with the k6 container](../../user/project/merge_requests/load_performance_testing.html). | +| Clojure | [Test a Clojure application with GitLab CI/CD](test-clojure-application.html). | +| 使用 Dpl 进行部署 | [Using `dpl` as deployment tool](deployment/README.html). | +| Elixir | [Testing a Phoenix application with GitLab CI/CD](test_phoenix_app_with_gitlab_ci_cd/index.html). | +| 端到端测试 | [End-to-end testing with GitLab CI/CD and WebdriverIO](end_to_end_testing_webdriverio/index.html). | +| Game development | [DevOps and Game Dev with GitLab CI/CD](devops_and_game_dev_with_gitlab_ci_cd/index.html). | +| GitLab 页面 | 有关部署静态站点的完整示例,请参见[GitLab Pages](../../user/project/pages/index.html)文档. | +| 带有 Spring Boot 的 Java | [Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD](deploy_spring_boot_to_cloud_foundry/index.html). | +| Java 与 Maven | [How to deploy Maven projects to Artifactory with GitLab CI/CD](artifactory_and_gitlab/index.html). | +| PHP 与 PHPunit,Atoum | [Testing PHP projects](php.html). | +| PHP 与 NPM,SCP | [Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD](deployment/composer-npm-deploy.html). | +| PHP 与 Laravel,Envoy | [Test and deploy Laravel applications with GitLab CI/CD and Envoy](laravel_with_gitlab_and_envoy/index.html). | +| Heroku 上的 Python | [Test and deploy a Python application with GitLab CI/CD](test-and-deploy-python-application-to-heroku.html). | +| 红宝石在 Heroku 上 | [Test and deploy a Ruby application with GitLab CI/CD](test-and-deploy-ruby-application-to-heroku.html). | +| Heroku 上的 Scala | [Test and deploy a Scala application to Heroku](test-scala-application.html). | +| 并行测试 Ruby 和 JS | [GitLab CI/CD parallel jobs testing for Ruby & JavaScript projects](https://docs.knapsackpro.com/2019/how-to-run-parallel-jobs-for-rspec-tests-on-gitlab-ci-pipeline-and-speed-up-ruby-javascript-testing). | +| Vault 的秘密管理 | [Authenticating and Reading Secrets With Hashicorp Vault](authenticating-with-hashicorp-vault/index.html). | + +### Contributing examples[](#contributing-examples "Permalink") + +欢迎捐款! 您可以通过发送合并请求和该语言的指南来帮助您最喜欢的编程语言用户和 GitLab. + +## CI/CD templates[](#cicd-templates "Permalink") + +使用`.gitlab-ci.yml` [模板](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates)开始使用 GitLab CI / CD 和您喜欢的编程语言或框架. + +在用户界面中创建`gitlab-ci.yml`文件时,可以选择以下模板之一: + +* [Android (`Android.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Android.gitlab-ci.yml) +* [Android with fastlane (`Android-Fastlane.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml) +* [Bash (`Bash.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Bash.gitlab-ci.yml) +* [C++ (`C++.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/C++.gitlab-ci.yml) +* [Chef (`Chef.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Chef.gitlab-ci.yml) +* [Clojure (`Clojure.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml) +* [Composer `Composer.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Composer.gitlab-ci.yml) +* [Crystal (`Crystal.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml) +* [Django (`Django.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Django.gitlab-ci.yml) +* [Docker (`Docker.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Docker.gitlab-ci.yml) +* [dotNET (`dotNET.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml) +* [dotNET Core (`dotNET-Core.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/dotNET-Core.yml) +* [Elixir (`Elixir.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml) +* [goLang (`Go.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Go.gitlab-ci.yml) +* [Gradle (`Gradle.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Gradle.gitlab-ci.yml) +* [Grails (`Grails.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Grails.gitlab-ci.yml) +* [iOS with fastlane (`iOS-Fastlane.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml) +* [Julia (`Julia.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Julia.gitlab-ci.yml) +* [Laravel (`Laravel.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml) +* [LaTeX (`LaTeX.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/LaTeX.gitlab-ci.yml) +* [Maven (`Maven.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Maven.gitlab-ci.yml) +* [Mono (`Mono.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Mono.gitlab-ci.yml) +* [NPM (`npm.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/npm.gitlab-ci.yml) +* [Node.js (`Nodejs.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml) +* [OpenShift (`OpenShift.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/OpenShift.gitlab-ci.yml) +* [Packer (`Packer.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Packer.gitlab-ci.yml) +* [PHP (`PHP.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/PHP.gitlab-ci.yml) +* [Python (`Python.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Python.gitlab-ci.yml) +* [Ruby (`Ruby.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml) +* [Rust (`Rust.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Rust.gitlab-ci.yml) +* [Scala (`Scala.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Scala.gitlab-ci.yml) +* [Swift (`Swift.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Swift.gitlab-ci.yml) +* [Terraform (`Terraform.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml) + +如果编程语言或框架模板不在此列表中,则可以提供一种. 要创建模板,请向[https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates)提交合并请求. + +### Adding templates to your GitLab installation[](#adding-templates-to-your-gitlab-installation-premium-only "Permalink") + +您可以将自定义示例和模板添加到自我管理的 GitLab 实例. 您的 GitLab 管理员可以[指定一个实例模板存储库](../../user/admin_area/settings/instance_template_repository.html) ,其中包含特定于您组织的示例和模板. + +## Other resources[](#other-resources "Permalink") + +本节提供更多资源,以帮助您熟悉 GitLab CI / CD 的各种用法. 请注意,较早的文章和视频可能无法反映最新的 GitLab 版本的状态. + +### CI/CD in the cloud[](#cicd-in-the-cloud "Permalink") + +有关为基于云的环境设置 GitLab CI / CD 的示例,请参见: + +* [How to set up multi-account AWS SAM deployments with GitLab CI](https://about.gitlab.com/blog/2019/02/04/multi-account-aws-sam-deployments-with-gitlab-ci/) +* [Automating Kubernetes Deployments with GitLab CI/CD](https://www.youtube.com/watch?v=wEDRfAz6_Uw) +* [How to autoscale continuous deployment with GitLab Runner on DigitalOcean](https://about.gitlab.com/blog/2018/06/19/autoscale-continuous-deployment-gitlab-runner-digital-ocean/) +* [How to create a CI/CD pipeline with Auto Deploy to Kubernetes using GitLab and Helm](https://about.gitlab.com/blog/2017/09/21/how-to-create-ci-cd-pipeline-with-autodeploy-to-kubernetes-using-gitlab-and-helm/) +* [Demo - Deploying from GitLab to OpenShift Container Cluster](https://youtu.be/EwbhA53Jpp4) + +另请参阅以下视频概述: + +* [Kubernetes, GitLab, and Cloud Native](https://www.youtube.com/watch?v=d-9awBxEbvQ). +* [Deploying to IBM Cloud with GitLab CI/CD](https://www.youtube.com/watch?v=6ZF4vgKMd-g). + +### Customer stories[](#customer-stories "Permalink") + +有关使用 GitLab CI / CD 的一些客户体验,请参阅: + +* [How Verizon Connect reduced datacenter deploys from 30 days to under 8 hours with GitLab](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/) +* [How Wag! cut their release process from 40 minutes to just 6](https://about.gitlab.com/blog/2019/01/16/wag-labs-blog-post/) +* [How Jaguar Land Rover embraced CI to speed up their software lifecycle](https://about.gitlab.com/blog/2018/07/23/chris-hill-devops-enterprise-summit-talk/) + +### Getting started[](#getting-started "Permalink") + +有关帮助您入门的一些示例,请参阅: + +* [GitLab CI/CD’s 2018 highlights](https://about.gitlab.com/blog/2019/01/21/gitlab-ci-cd-features-improvements/) +* [A beginner’s guide to continuous integration](https://about.gitlab.com/blog/2018/01/22/a-beginners-guide-to-continuous-integration/) + +### Implementing GitLab CI/CD[](#implementing-gitlab-cicd "Permalink") + +有关其他已实施 GitLab CI / CD 的示例,请参见: + +* [How to streamline interactions between multiple repositories with multi-project pipelines](https://about.gitlab.com/blog/2018/10/31/use-multiproject-pipelines-with-gitlab-cicd/) +* [How we used GitLab CI to build GitLab faster](https://about.gitlab.com/blog/2018/05/02/using-gitlab-ci-to-build-gitlab-faster/) +* [Test all the things in GitLab CI with Docker by example](https://about.gitlab.com/blog/2018/02/05/test-all-the-things-gitlab-ci-docker-examples/) +* [A Craftsman looks at continuous integration](https://about.gitlab.com/blog/2018/01/17/craftsman-looks-at-continuous-integration/) +* [Go tools and GitLab: How to do continuous integration like a boss](https://about.gitlab.com/blog/2017/11/27/go-tools-and-gitlab-how-to-do-continuous-integration-like-a-boss/) +* [GitBot – automating boring Git operations with CI](https://about.gitlab.com/blog/2017/11/02/automating-boring-git-operations-gitlab-ci/) +* [How to use GitLab CI for Vue.js](https://about.gitlab.com/blog/2017/09/12/vuejs-app-gitlab/) +* Video: [GitLab CI/CD Deep Dive](https://youtu.be/pBe4t1CD8Fc?t=195) +* [Dockerizing GitLab Review Apps](https://about.gitlab.com/blog/2017/07/11/dockerizing-review-apps/) +* [Fast and natural continuous integration with GitLab CI](https://about.gitlab.com/blog/2017/05/22/fast-and-natural-continuous-integration-with-gitlab-ci/) +* [Demo: CI/CD with GitLab in action](https://about.gitlab.com/blog/2017/03/13/ci-cd-demo/) + +### Migrating to GitLab from third-party CI tools[](#migrating-to-gitlab-from-third-party-ci-tools "Permalink") + +* [Migrating from Jenkins to GitLab](https://youtu.be/RlEVGOpYF5Y) + +### Integrating GitLab CI/CD with other systems[](#integrating-gitlab-cicd-with-other-systems "Permalink") + +要查看如何将 GitLab CI / CD 与第三方系统集成,请参阅: + +* [Streamline and shorten error remediation with Sentry’s new GitLab integration](https://about.gitlab.com/blog/2019/01/25/sentry-integration-blog-post/) +* [How to simplify your smart home configuration with GitLab CI/CD](https://about.gitlab.com/blog/2018/08/02/using-the-gitlab-ci-slash-cd-for-smart-home-configuration-management/) +* [Demo: GitLab + Jira + Jenkins](https://about.gitlab.com/blog/2018/07/30/gitlab-workflow-with-jira-jenkins/) +* [Introducing Auto Breakfast from GitLab (sort of)](https://about.gitlab.com/blog/2018/06/29/introducing-auto-breakfast-from-gitlab/) + +### Mobile development[](#mobile-development "Permalink") + +有关使用 GitLab CI / CD 进行移动应用程序开发的帮助,请参阅: + +* [How to publish Android apps to the Google Play Store with GitLab and fastlane](https://about.gitlab.com/blog/2019/01/28/android-publishing-with-gitlab-and-fastlane/) +* [Setting up GitLab CI for Android projects](https://about.gitlab.com/blog/2018/10/24/setting-up-gitlab-ci-for-android-projects/) +* [Working with YAML in GitLab CI from the Android perspective](https://about.gitlab.com/blog/2017/11/20/working-with-yaml-gitlab-ci-android/) +* [How to use GitLab CI and MacStadium to build your macOS or iOS projects](https://about.gitlab.com/blog/2017/05/15/how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects/) +* [Setting up GitLab CI for iOS projects](https://about.gitlab.com/blog/2016/03/10/setting-up-gitlab-ci-for-ios-projects/) \ No newline at end of file diff --git a/docs/227.md b/docs/227.md new file mode 100644 index 0000000000000000000000000000000000000000..be771bafe32f9488d4e2b84c00e889484adab1a1 --- /dev/null +++ b/docs/227.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/ci/examples/browser_performance.html](https://docs.gitlab.com/ee/ci/examples/browser_performance.html) \ No newline at end of file diff --git a/docs/228.md b/docs/228.md new file mode 100644 index 0000000000000000000000000000000000000000..04e39d536302e82065c76aac7aa475e606ab6618 --- /dev/null +++ b/docs/228.md @@ -0,0 +1,43 @@ +# Test a Clojure application with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/test-clojure-application.html](https://docs.gitlab.com/ee/ci/examples/test-clojure-application.html) + +* [Configure the project](#configure-the-project) + +**注意:**本文档最近未更新,可能已过期. 有关最新文档,请参见[GitLab CI / CD](../README.html)页面和《 [GitLab CI / CD 管道配置参考》](../yaml/README.html) . + +# Test a Clojure application with GitLab CI/CD[](#test-a-clojure-application-with-gitlab-cicd "Permalink") + +本示例将指导您如何在 Clojure 应用程序上运行测试. + +您可以查看或派生[示例源,](https://gitlab.com/dzaporozhets/clojure-web-application)并查看其过去的[CI 作业](https://gitlab.com/dzaporozhets/clojure-web-application/builds?scope=finished)的日志. + +## Configure the project[](#configure-the-project "Permalink") + +这是此项目的`.gitlab-ci.yml`文件的外观: + +``` +variables: + POSTGRES_DB: sample-test + DATABASE_URL: "postgresql://postgres@postgres:5432/sample-test" + +before_script: + - apt-get update -y + - apt-get install default-jre postgresql-client -y + - wget https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein + - chmod a+x lein + - export LEIN_ROOT=1 + - PATH=$PATH:. + - lein deps + - lein migratus migrate + +test: + script: + - lein test +``` + +在`before_script` ,我们安装了 JRE 和[Leiningen](https://leiningen.org/) . + +该示例项目使用[migratus](https://github.com/yogthos/migratus)库管理数据库迁移,并且在`before_script`的最后一步中添加了数据库迁移. + +您可以使用`gitlab.com`可用的公共`gitlab.com`程序来使用此配置测试您的应用程序. \ No newline at end of file diff --git a/docs/229.md b/docs/229.md new file mode 100644 index 0000000000000000000000000000000000000000..10f1daf2ab444e3ab4237981c2525a6d91016d17 --- /dev/null +++ b/docs/229.md @@ -0,0 +1,115 @@ +# Using Dpl as deployment tool + +> 原文:[https://docs.gitlab.com/ee/ci/examples/deployment/README.html](https://docs.gitlab.com/ee/ci/examples/deployment/README.html) + +* [Requirements](#requirements) +* [Basic usage](#basic-usage) +* [Using Dpl with Docker](#using-dpl-with-docker) +* [Usage in staging and production](#usage-in-staging-and-production) +* [Storing API keys](#storing-api-keys) + +# Using Dpl as deployment tool[](#using-dpl-as-deployment-tool "Permalink") + +[Dpl](https://github.com/travis-ci/dpl) (发音为 DPL)是由 Travis CI 开发和使用的,用于连续部署的部署工具,但也可以与 GitLab CI / CD 一起使用. + +Dpl 可用于部署到任何[受支持的提供程序](https://github.com/travis-ci/dpl#supported-providers) . + +## Requirements[](#requirements "Permalink") + +要使用 Dpl,您至少需要具备安装 gem 的 Ruby 1.9.3. + +## Basic usage[](#basic-usage "Permalink") + +可以将 Dpl 安装在具有以下条件的任何计算机上: + +``` +gem install dpl +``` + +这使您可以从本地终端测试所有命令,而不必在 CI 服务器上进行测试. + +如果您没有安装 Ruby,则可以在兼容 Debian 的 Linux 上执行以下操作: + +``` +apt-get update +apt-get install ruby-dev +``` + +Dpl 为大量服务提供支持,包括:Heroku,Cloud Foundry,AWS / S3 等. 要使用它,只需定义提供者和提供者所需的任何其他参数. + +例如,如果要使用它将应用程序部署到 Heroku,则需要将`heroku`指定为提供者,并指定`api-key`和`app` . 所有可能的参数都可以在这里找到: [https](https://github.com/travis-ci/dpl#heroku-api) : [//github.com/travis-ci/dpl#heroku-api](https://github.com/travis-ci/dpl#heroku-api) . + +``` +staging: + stage: deploy + script: + - gem install dpl + - dpl --provider=heroku --app=my-app-staging --api-key=$HEROKU_STAGING_API_KEY +``` + +在上面的示例中,我们使用 Dpl 通过存储在`HEROKU_STAGING_API_KEY`安全变量中的 API 密钥将`my-app-staging`部署到 Heroku 服务器. + +要使用其他提供程序,请查看一整列[受支持的提供程序](https://github.com/travis-ci/dpl#supported-providers) . + +## Using Dpl with Docker[](#using-dpl-with-docker "Permalink") + +在大多数情况下,您将配置[GitLab Runner](https://docs.gitlab.com/runner/)以使用服务器的 Shell 命令. 这意味着所有命令都在本地用户的上下文中运行(例如`gitlab_runner`或`gitlab_ci_multi_runner` ). 这也意味着最有可能在 Docker 容器中没有安装 Ruby 运行时. 您将必须安装它: + +``` +staging: + stage: deploy + script: + - apt-get update -yq + - apt-get install -y ruby-dev + - gem install dpl + - dpl --provider=heroku --app=my-app-staging --api-key=$HEROKU_STAGING_API_KEY + only: + - master +``` + +第一行`apt-get update -yq`更新可用软件包的列表,第二行`apt-get install -y ruby-dev`在系统上安装 Ruby 运行时. 上面的示例对所有与 Debian 兼容的系统均有效. + +## Usage in staging and production[](#usage-in-staging-and-production "Permalink") + +在开发工作流程中具有暂存(开发)和生产环境是很常见的 + +让我们考虑以下示例:我们希望将`master`分支部署到`staging`并将所有标签部署到`production`环境. 该设置的最终`.gitlab-ci.yml`如下所示: + +``` +staging: + stage: deploy + script: + - gem install dpl + - dpl --provider=heroku --app=my-app-staging --api-key=$HEROKU_STAGING_API_KEY + only: + - master + +production: + stage: deploy + script: + - gem install dpl + - dpl --provider=heroku --app=my-app-production --api-key=$HEROKU_PRODUCTION_API_KEY + only: + - tags +``` + +我们创建了两个在不同事件上执行的部署作业: + +1. `staging` is executed for all commits that were pushed to `master` branch, +2. 对所有推送的标签执行`production` . + +我们还使用两个安全变量: + +1. `HEROKU_STAGING_API_KEY` -Heroku API 密钥,用于部署登台应用程序, +2. `HEROKU_PRODUCTION_API_KEY` -Heroku API 密钥,用于部署生产应用程序. + +## Storing API keys[](#storing-api-keys "Permalink") + +可以通过在项目的**设置➔CI / CD➔变量中**添加安全**变量** . 项目设置中定义的变量与构建脚本一起发送到 Runner. 安全变量存储在存储库之外. 切勿将机密存储在项目的`.gitlab-ci.yml` . 将秘密的值隐藏在作业日志中也很重要. + +您可以通过使用`$` (在非 Windows 运行程序上)或`%` (对于 Windows 批处理运行程序)前缀名称来访问添加的变量: + +1. `$VARIABLE`用于非 Windows 运行器 +2. `%VARIABLE%` -用于 Windows 批处理运行器 + +阅读有关[CI 变量的](../../variables/README.html)更多信息. \ No newline at end of file diff --git a/docs/230.md b/docs/230.md new file mode 100644 index 0000000000000000000000000000000000000000..c89200a474a67cf33dc10914c14199309fde131a --- /dev/null +++ b/docs/230.md @@ -0,0 +1,326 @@ +# Testing a Phoenix application with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/test_phoenix_app_with_gitlab_ci_cd/](https://docs.gitlab.com/ee/ci/examples/test_phoenix_app_with_gitlab_ci_cd/) + +* [Introduction](#introduction) + * [What is Phoenix?](#what-is-phoenix) + * [What is Elixir?](#what-is-elixir) +* [Requirements](#requirements) + * [Create a new Phoenix project](#create-a-new-phoenix-project) + * [Initialize the PostgreSQL database](#initialize-the-postgresql-database) + * [Start Phoenix server](#start-phoenix-server) +* [Introducing GitLab CI/CD](#introducing-gitlab-cicd) +* [Adjusting Phoenix configuration](#adjusting-phoenix-configuration) +* [Testing](#testing) +* [Configuring CI/CD Pipeline](#configuring-cicd-pipeline) +* [Watching the build](#watching-the-build) +* [Conclusion](#conclusion) +* [References](#references) + +# Testing a Phoenix application with GitLab CI/CD[](#testing-a-phoenix-application-with-gitlab-cicd "Permalink") + +[Phoenix](https://www.phoenixframework.org/)是用[Elixir](https://s0elixir-lang0org.icopy.site)编写的 Web 开发框架, [Elixir](https://s0elixir-lang0org.icopy.site)是在[Erlang VM](https://www.erlang.org)上运行的旨在提高生产力和可维护性的功能性语言. Erlang VM 确实非常快,并且可以处理大量同时用户. + +这就是为什么我们今天听到太多有关 Phoenix 的原因. + +在本教程中,我们将教您如何设置[GitLab CI / CD](../../README.html)来构建和测试 Phoenix 应用程序. + +本教程假定您知道如何创建 Phoenix 应用程序,在本地运行测试以及如何使用 Git 和 GitLab UI. + +## Introduction[](#introduction "Permalink") + +### What is Phoenix?[](#what-is-phoenix "Permalink") + +[Phoenix](https://www.phoenixframework.org/) is a web development framework written in [Elixir](https://s0elixir-lang0org.icopy.site). It’s useful for building fast, reliable, and high-performance applications, as it uses [Erlang VM](https://www.erlang.org). + +许多组件和概念类似于 Ruby on Rails 或 Python 的 Django. 高开发人员生产率和高应用程序性能只是学习如何使用它的几个优点. 使用 MVC 模式,它被设计为模块化和灵活的. 易于维护不断增长的应用程序是一个加号. + +Phoenix 可以在任何支持 Erlang 的操作系统上运行: + +* Ubuntu +* CentOS +* Mac OS X +* Debian +* Windows +* Fedora +* Raspberry Pi 操作系统 + +查看[Phoenix 学习指南](https://s0hexdocs0pm.icopy.site/phoenix/overview.html)以获取更多信息. + +### What is Elixir?[](#what-is-elixir "Permalink") + +[Elixir](https://s0elixir-lang0org.icopy.site)是一种动态的,功能性的语言,旨在轻松地使用当今所有成熟的 Erlang(已有 30 年的历史!). 它与 Ruby 有相似之处,特别是在语法上,因此 Ruby 开发人员对 Elixir 的快速增长感到非常兴奋. 一个全栈的 Ruby 开发人员可以在短短几周内学会如何使用 Elixir 和 Phoenix. + +在药剂我们有一个叫做命令`mix` ,这是一个帮助创建项目,测试,运行迁移和[更多](https://s0elixir-lang0org.icopy.site/getting-started/mix-otp/introduction-to-mix) . 我们将在本教程的后面部分中使用它. + +查看[Elixir 文档](https://s0elixir-lang0org.icopy.site/getting-started/introduction)以获取更多信息. + +## Requirements[](#requirements "Permalink") + +要遵循本教程,您需要先安装: + +* Elixir [installation instructions](https://s0elixir-lang0org.icopy.site/install) +* Phoenix Framework [安装说明](https://s0hexdocs0pm.icopy.site/phoenix/installation.html) +* PostgreSQL(如果需要使用 MySQL 服务器,请查看[Phoenix 说明](https://s0hexdocs0pm.icopy.site/phoenix/ecto.html) ) + +### Create a new Phoenix project[](#create-a-new-phoenix-project "Permalink") + +打开终端,然后转到要创建项目的目录. 您无需为项目的文件创建一个空目录,因为`mix`命令将为我们完成此操作. + +当我们调用`mix`命令时,我们将传递两个参数: + +* 我们希望它运行的任务: `phoenix.new` +* 参数`phoenix.new`需要,这是新项目的名称. 在这种情况下,我们称其为`hello_gitlab_ci` ,但您可以自由设置自己的名称: + +``` +mix phoenix.new hello_gitlab_ci +``` + +当询问时,请回答`Y`以获取并安装依赖项. + +如果一切顺利,您将获得如下输出: + +[![mix phoenix.new](img/28300ad671ab6b5aec8525cb2a7af157.png)](img/mix-phoenix-new.png) + +现在,我们的项目位于目录中,该目录与传递给`mix`命令的名称相同,例如`~/GitLab/hello_gitlab_ci` . 如果查看目录,我们将看到 Phoenix 文件和运行所需的依赖项. + +### Initialize the PostgreSQL database[](#initialize-the-postgresql-database "Permalink") + +By default, Phoenix requires a PostgreSQL database to store whatever we need to store in our app. In this case, we’ll only create an empty database. + +首先,我们需要导航到我们最近创建的项目的目录,然后再次执行`mix` . 这次, `mix`将收到参数`ecto.create` ,这是创建新数据库的任务. [Ecto](https://s0hexdocs0pm.icopy.site/ecto/Ecto.html)是 Elixir 的数据库包装器. + +创建项目后第一次运行`mix`时,它将把我们的文件编译为字节码,然后由 Erlang VM 解释. 在接下来的时间里,它只会编译我们的更改. + +运行以下命令以创建我们的空数据库: + +``` +cd hello_gitlab_ci +mix ecto.create +``` + +我们希望在命令末尾看到以下输出: + +``` +Generated hello_gitlab_ci app +The database for HelloGitlabCi.Repo has been created +``` + +> **注意:** Phoenix 假设我们的 PostgreSQL 数据库将具有一个具有正确权限的`postgres`用户帐户和一个`postgres`密码. 如果不是您的情况,请查看[Ecto 的说明](https://s0hexdocs0pm.icopy.site/ecto/Ecto.html) . + +### Start Phoenix server[](#start-phoenix-server "Permalink") + +现在,该看看我们到目前为止所做的一切是否进展顺利. 我们将再次使用`phoenix.server`参数调用`mix` ,它将启动 Phoenix 的 HTTP Server. + +``` +mix phoenix.server +``` + +这将是此命令的输出: + +``` +[info] Running HelloGitlabCi.Endpoint with Cowboy using http://localhost:4000 +23 May 11:44:35 - info: compiling +23 May 11:44:37 - info: compiled 6 files into 2 files, copied 3 in 9.8 sec +``` + +现在,我们的应用程序在本地运行. 我们可以直接在浏览器中预览它. 让我们打开[`localhost:4000`](http://localhost:4000)来查看我们的 Phoenix Framework 欢迎页面. 如果链接不起作用,请改为打开[`127.0.0.1:4000`](http://127.0.0.1:4000) ,然后[`127.0.0.1:4000`](http://127.0.0.1:4000)操作系统配置为将`localhost`指向`127.0.0.1` . + +[![mix phoenix.server](img/13c910771ce7fad76e82ba7b8bdd440b.png)](img/mix-phoenix-server.png) + +太好了,现在我们有一个本地 Phoenix Server 运行我们的应用程序. + +在本地,我们的应用程序在[`iex`](https://s0elixir-lang0org.icopy.site/getting-started/introduction.html)会话中运行,该会话代表 Interactive Elixir. 在这种交互模式下,我们可以键入任何 Elixir 表达式并获取其结果. 要退出`iex` ,我们需要按两次`Ctrl+C` 因此,当我们需要停止 Phoenix 服务器时,我们必须`Ctrl+C`两次`Ctrl+C` + +## Introducing GitLab CI/CD[](#introducing-gitlab-cicd "Permalink") + +借助 GitLab,我们可以在一个平台上管理开发工作流程,提高生产力,跟踪问题,执行代码审查等. 使用 GitLab CI / CD,我们可以提高工作效率,因为每次我们或我们的同事发布任何代码时,GitLab CI / CD 都会构建并测试更改,并实时告诉我们是否有任何问题. + +当然,当我们的应用程序开始增长时,我们将需要更多的开发人员在同一个项目上工作,并且这种构建和测试过程很容易在没有适当管理的情况下变得一团糟. 这也是为什么 GitLab CI / CD 对我们的应用如此重要的原因. 每当有人将其代码推送到 GitLab 时,我们都会很快知道他们的更改是否破坏了某些内容. 我们不需要停止所做的一切工作,就可以手动进行测试,而无需在团队中进行任何更改. + +让我们在实践中看一下. + +## Adjusting Phoenix configuration[](#adjusting-phoenix-configuration "Permalink") + +现在,我们需要在配置 GitLab CI / CD 之前调整 Phoenix 配置. Phoenix 项目中有一个目录( `config` ),其中包含可以运行的每个环境的配置文件. 由于我们将在单个环境中工作,因此我们将仅编辑测试配置文件( `test.exs` ). + +但是,为什么我们需要调整配置? 好吧,GitLab CI / CD 使用 Docker 技术在一个称为[Runner 的](../../runners/README.html)隔离虚拟机中构建和测试我们的代码. 在此 Runner 中,GitLab CI / CD 可以访问 Phoenix 应用程序需要运行的所有内容,就像在`localhost` ,但是我们必须告诉 GitLab CI / CD 使用系统变量在哪里创建和找到该数据库. 这样,GitLab CI / CD 将在 Runner 内部创建测试数据库,就像在`localhost`运行 Phoenix 时一样. + +* 在您喜欢的代码编辑器上打开`hello_gitlab_ci/config/test.exs` +* 转到" **配置数据库**会话"并编辑该块以包含`System.get_env` : + + ``` + # Configure your database + config :hello_gitlab_ci, HelloGitlabCi.Repo, + adapter: Ecto.Adapters.Postgres, + username: System.get_env("POSTGRES_USER") || "postgres", + password: System.get_env("POSTGRES_PASSWORD") || "postgres", + database: System.get_env("POSTGRES_DB") || "hello_gitlab_ci_test", + hostname: System.get_env("POSTGRES_HOST") || "localhost", + pool: Ecto.Adapters.SQL.Sandbox + ``` + + 稍后我们将需要这些系统变量. + +* 在`hello_gitlab_ci/priv/repo/migrations`创建一个名为`.gitkeep`的空文件 + + 由于我们的项目仍然很新鲜,因此我们的数据库上没有任何数据,因此`migrations`目录将为空. 如果没有`.gitkeep` ,Git 将不会上传该空目录,并且在 GitLab 上运行测试时会出现错误. + + > **注意:**如果我们通过 GitLab UI 添加文件夹,则 GitLab 本身会将`.gitkeep`添加到该新目录中. + +现在,让我们运行一个本地测试,看看我们所做的一切是否都没有破坏任何东西. + +## Testing[](#testing "Permalink") + +之前,当我们创建项目时,我们运行了`mix phoenix.new` . 该任务创建了 Phoenix 应用程序所需的所有内容,包括一些进入`hello_gitlab_ci/test`目录的单元测试. + +让我们运行带有`mix`的新任务来为我们运行这些测试. 这次,预期的参数是`test` . 我们可以添加`--trace`参数以进行调试. + +在您的终端中,导航到目录`hello_gitlab_ci`并运行: + +``` +mix test +``` + +我们的预期结果是: + +``` +.... + +Finished in 0.7 seconds +4 tests, 0 failures + +Randomized with seed 610000 +``` + +我们的测试成功了. 是时候将我们的文件推送到 GitLab 了. + +## Configuring CI/CD Pipeline[](#configuring-cicd-pipeline "Permalink") + +第一步是在我们项目的`hello_gitlab_ci`目录中创建一个名为`.gitlab-ci.yml`的新文件. + +* 最简单的方法是单击项目主页上的" **设置 CI / CD** ": + + [![Set up CI](img/8a05f3552d23f56607411f613a5ceb05.png)](img/set_up_ci_v12_6.png) + +* 在下一个屏幕上,我们可以使用已包含 Elixir 测试的模板. 单击" **应用模板",**然后选择**Elixir** : + + [![Select template](img/b96e754d4dd8ba06065aac231327e160.png)](img/select_template_v12_6.png) + + 该模板文件告诉 GitLab CI / CD 每次新的提交时我们希望做什么. 但是,我们必须对其稍作调整才能运行 Phoenix 应用程序. + +* The first line tells GitLab what Docker image will be used. + + 还记得我们了解 Runners 时,GitLab CI / CD 在其中构建和测试我们的应用程序的隔离虚拟机吗? 该虚拟机必须具有所有依赖关系才能运行我们的应用程序. 这是需要 Docker 映像的地方. 正确的图像将为我们提供整个系统. + + 当我们专注于测试(而不是部署)时,可以使用[elixir:latest](https://hub.docker.com/_/elixir) Docker 映像,该映像已经具有用于运行 Phoenix 测试的依赖项,例如 Elixir 和 Erlang: + + ``` + image: elixir:latest + ``` + +* 我们将仅使用`postgres` ,因此我们可以从`services`部分删除`mysql`和`redis`行: + + ``` + services: + - postgres:latest + ``` + +* 现在,我们将在`before_script`部分之前创建一个名为`variables`的新部分: + + ``` + variables: + POSTGRES_DB: hello_gitlab_ci_test + POSTGRES_HOST: postgres + POSTGRES_USER: postgres + POSTGRES_PASSWORD: "postgres" + MIX_ENV: "test" + ``` + + 上面,我们设置了 GitLab CI / CD 的值以验证到 PostgreSQL,就像我们之前在`config/test.exs`那样. `postgres`服务使用`POSTGRES_USER`和`POSTGRES_PASSWORD`值来创建具有这些凭据的用户. + +* 在`before_script`部分中,我们将添加一些命令来为测试做准备: + + ``` + before_script: + - mix local.rebar --force + - mix local.hex --force + - mix deps.get --only test + - mix ecto.create + - mix ecto.migrate + ``` + + 这样可以确保在尝试获取运行测试所需的依赖项之前,都同时安装了[rebar3](https://www.rebar3.org)和[hex](https://s0hex0pm.icopy.site) . 接下来,使用`ecto`创建并迁移`postgres` db,以确保它是最新的. + +* 最后,我们将`mix`部分保持不变. + +让我们看一下更改后的更新文件: + +``` +image: elixir:latest + +services: + - postgres:latest + +variables: + POSTGRES_DB: hello_gitlab_ci_test + POSTGRES_HOST: postgres + POSTGRES_USER: postgres + POSTGRES_PASSWORD: "postgres" + MIX_ENV: "test" + +before_script: + - mix local.rebar --force + - mix local.hex --force + - mix deps.get --only test + - mix ecto.create + - mix ecto.migrate + +mix: + script: + - mix test +``` + +为了安全起见,在将此文件提交到 GitLab 之前,我们可以检查是否有语法错误. 复制`.gitlab-ci.yml`的内容并将其粘贴到[GitLab CI / CD Lint 工具上](https://gitlab.com/ci/lint) . 请注意,此链接仅对登录用户有效. + +## Watching the build[](#watching-the-build "Permalink") + +我不了解您,但是我喜欢看黑屏上充满了编译输出. 这样,我可以感觉到我所做的正确工作带来的快乐. 在`localhost` ,很容易观看我们的构建,但是在 GitLab 上,这可能吗? 是! + +让我们去**管道** ,看看 GitLab 做这项工作. 只需单击**管道**以查找实际正在运行的构建作业. + +[![Pipelines](img/d7b0c4003d725d7125fdfb9c24aae17e.png)](img/pipelines.png) + +单击内部版本的 ID 观看整个过程. 如果一切都按预期进行,我们可以等待**构建成功**完成! :) + +``` +$ mix test +.... + +Finished in 0.3 seconds +4 tests, 0 failures + +Randomized with seed 206909 +Build succeeded +``` + +如果我们在 GitLab UI 上查看项目的主页,我们可以看到 GitLab CI / CD 进行的最后构建的状态. + +是时候向世界展示我们的绿色建筑徽章! 导航到项目的**"设置">" CI / CD",**然后展开" **常规管道设置"** . 向下滚动到**管道状态,**并复制您的徽章的降价代码. 将其粘贴到`README.md`文件的顶部,以使项目外的人员可以看到我们的最新代码是否正在正确运行. + +完成此版本后,GitLab 将启动另一个构建并显示一个**运行**徽标. 可以预期的是,毕竟我们只是配置了 GitLab CI / CD 来完成每次推送! 但是您可能会想"为什么要针对诸如 README.md 之类的简单操作运行构建和测试?" 这是一个很好的问题. 对于不影响您的应用程序的更改,您可以添加关键字[`[ci skip]`](../../yaml/README.html#skip-pipeline)来提交消息,并且与该提交相关的内部版本将被跳过. + +最后,我们终于获得了绿色环保的成功徽章! 通过将结果输出到 README 文件中,它可以向登录项目页面的任何人显示您的代码是最新的并且可以正常工作. + +## Conclusion[](#conclusion "Permalink") + +当我们的应用程序不断增长且有许多开发人员在处理该应用程序时,或者当社区正在监视和贡献一个开源项目时,使我们的代码永久运行非常重要. GitLab CI / CD 是节省时间的强大工具,可帮助我们维护代码的组织和工作. + +正如我们在这篇文章中所看到的,GitLab CI / CD 确实很容易配置和使用. 我们还有[许多其他理由](https://about.gitlab.com/blog/2015/02/03/7-reasons-why-you-should-be-using-ci/)继续使用 GitLab CI / CD. 给我们团队带来的好处是巨大的! + +## References[](#references "Permalink") + +* [GitLab CI/CD introductory guide](https://about.gitlab.com/blog/2015/12/14/getting-started-with-gitlab-and-gitlab-ci/) +* [GitLab CI/CD full Documentation](../../README.html) +* [GitLab Runners documentation](../../runners/README.html) +* [Using Docker images documentation](../../docker/using_docker_images.html) \ No newline at end of file diff --git a/docs/231.md b/docs/231.md new file mode 100644 index 0000000000000000000000000000000000000000..6787ab5b2f762f708fed5dcbc04e148eb9062e34 --- /dev/null +++ b/docs/231.md @@ -0,0 +1,168 @@ +# End-to-end testing with GitLab CI/CD and WebdriverIO + +> 原文:[https://docs.gitlab.com/ee/ci/examples/end_to_end_testing_webdriverio/](https://docs.gitlab.com/ee/ci/examples/end_to_end_testing_webdriverio/) + +* [What to test](#what-to-test) +* [Selenium and WebdriverIO](#selenium-and-webdriverio) +* [Writing tests](#writing-tests) +* [Running locally](#running-locally) +* [Configuring GitLab CI/CD](#configuring-gitlab-cicd) +* [What’s next](#whats-next) + +# End-to-end testing with GitLab CI/CD and WebdriverIO[](#end-to-end-testing-with-gitlab-cicd-and-webdriverio "Permalink") + +[Review App](../../review_apps/index.html)很棒:对于每个合并请求(或分支),都可以将新代码复制并部署到新的类似于生产的实时环境中,从而非常省力地评估更改的影响. 因此,当我们使用像[Dependencies.io](https://www.dependencies.io/)这样的依赖项管理器时,它可以提交具有更新的依赖项的合并请求,并且很明显,仍然可以正确地构建和部署应用程序. 毕竟,您可以*看到*它正在运行! + +![dependencies.io](img/423fb353db83bd90502f2f029c398e43.png) + +但是,查看新部署的代码以检查其外观和行为是否仍符合预期是重复的手动工作,这意味着它是自动化的主要候选对象. 这就是自动[端到端测试的目的](https://martinfowler.com/bliki/BroadStackTest.html) :让计算机在几种简单的场景下运行,这些场景要求您的应用程序的所有层(从前[端到数据库)](https://martinfowler.com/bliki/BroadStackTest.html)都具有适当的功能. + +在本文中,我们将讨论如何编写这样的端到端测试,以及如何设置 GitLab CI / CD 以逐分支的基础针对新代码自动运行这些测试. 在本文的范围内,我们将引导您完成设置 GitLab CI / CD 的过程,以使用 WebdriverIO 端对端测试基于 JavaScript 的应用程序,但是一般策略应延续到其他语言. 我们假设您熟悉 GitLab, [GitLab CI / CD](../../README.html) , [Review Apps](../../review_apps/index.html) ,并在本地运行您的应用程序,例如,在`localhost:8000` . + +## What to test[](#what-to-test "Permalink") + +在广泛使用的[测试金字塔策略中](https://martinfowler.com/bliki/TestPyramid.html) ,端到端测试的行为更像是一种保护措施: [大多数代码应包含在单元测试中](https://vincenttunru.com/100-percent-coverage/) ,以使您可以轻松地确定问题的根源. 相反,您可能希望将[端到端测试的数量限制](https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html)为刚好足以使您确信部署按预期进行,基础结构已启动并正在运行以及代码单元可以很好地协同工作. + +## Selenium and WebdriverIO[](#selenium-and-webdriverio "Permalink") + +[Selenium](https://s0www0selenium0dev.icopy.site/)是一款可以控制 Web 浏览器的软件,例如,使它们能够访问特定的 URL 或与页面上的元素进行交互. 它可以通过多种编程语言进行编程控制. 在本文中,我们将使用[WebdriverIO](https://webdriver.io/) JavaScript 绑定,但是一般概念应该可以很好地延续到[Selenium 支持的其他编程语言中](https://s0www0selenium0dev.icopy.site/documentation/en/legacy_docs/selenium_rc/) . + +## Writing tests[](#writing-tests "Permalink") + +您可以使用[WebdriverIO 支持的多个测试框架](https://webdriver.io/guide/testrunner/frameworks.html)编写测试. 我们将在这里使用[茉莉花](https://jasmine.github.io/) : + +``` +describe('A visitor without account', function(){ + it('should be able to navigate to the homepage from the 404 page', function(){ + browser.url('/page-that-does-not-exist'); + + expect(browser.getUrl()).toMatch('page-that-does-not-exist'); + + browser.element('.content a[href="/"]').click(); + + expect(browser.getUrl()).not.toMatch('page-that-does-not-exist'); + }); +}); +``` + +WebdriverIO 提供了`describe` , `it`和`browser`的功能. 让我们一一分解. + +函数`describe`允许您对相关测试进行分组. 例如,如果您想对多个测试运行相同的初始化命令(使用[`beforeEach`](https://jasmine.github.io/api/2.9/global.html#beforeEach) ),例如确保您已登录,则这将很有用. + +`it`定义了单个测试的功能. + +[`browser`对象](https://webdriver.io/guide/testrunner/browserobject.html)是 WebdriverIO 的特长. 它提供了大多数[WebdriverIO API 方法](https://webdriver.io/api.html) ,这些[方法](https://webdriver.io/api.html)是引导浏览器的关键. 在这种情况下,我们可以使用[`browser.url`](https://webdriver.io/api/protocol/url.html)来访问`/page-that-does-not-exist`以访问 404 页面. 然后,我们可以使用[`browser.getUrl`](https://webdriver.io/api/property/getUrl.html)验证当前页面确实在我们指定的位置. 要与页面进行交互,我们只需将 CSS 选择器传递给[`browser.element`](https://webdriver.io/api/protocol/element.html)即可访问页面上的元素并与其进行交互-例如,单击返回首页的链接. + +上面显示的简单测试如果通过则可以给我们很大的信心:我们知道我们的部署成功了,这些元素在页面上可见,并且实际的浏览器可以与它交互,并且路由按预期工作. 所有这些仅用免费的空格就可以在 10 行中完成! 加上后续的单元测试和成功完成的管道,您可以完全确信,依赖项升级不会破坏任何内容,甚至无需查看您的网站. + +## Running locally[](#running-locally "Permalink") + +稍后我们将在 CI / CD 中运行上述测试. 但是,在编写测试时,如果您不必等待管道成功以检查它们是否按照您期望的方式工作,那么它会有所帮助. 换句话说,让它在本地运行. + +确保您的应用程序在本地运行. 如果使用 Webpack,则可以使用[Webpack Dev Server WebdriverIO 插件](https://s0www0npmjs0com.icopy.site/package/wdio-webpack-dev-server-service)在执行测试之前自动启动开发服务器. + +The WebdriverIO documentation has [an overview of all configuration options](https://webdriver.io/guide/getstarted/configuration.html), but the easiest way to get started is to start with [WebdriverIO’s default configuration](https://webdriver.io/guide/testrunner/configurationfile.html), which provides an overview of all available options. The two options that are going to be most relevant now are the `specs` option, which is an array of paths to your tests, and the `baseUrl` option, which points to where your app is running. And finally, we will need to tell WebdriverIO in which browsers we would like to run our tests. This can be configured through the `capabilities` option, which is an array of browser names (e.g. `firefox` or `chrome`). It is recommended to install [selenium-assistant](https://googlechromelabs.github.io/selenium-assistant/) to detect all installed browsers: + +``` + const seleniumAssistant = require('selenium-assistant'); + const browsers = seleniumAssistant.getLocalBrowsers(); + config.capabilities = browsers.map(browser => ({ browserName: browser.getId() })); +``` + +但是,当然,简单的配置`config.capabilities = ['firefox']`也可以. + +如果已将 WebdriverIO 安装为依赖项( `npm install --save-dev webdriverio` ),则可以在`package.json`中的`scripts`属性中添加一行,该行运行`wdio`并将配置文件的路径作为值,例如: + +``` + "confidence-check": "wdio wdio.conf.js", +``` + +然后,您可以使用`npm run confidence-check`执行测试,之后您实际上会看到一个新的浏览器窗口,与您指定的应用交互. + +## Configuring GitLab CI/CD[](#configuring-gitlab-cicd "Permalink") + +这使我们进入了令人兴奋的部分:我们如何在 GitLab CI / CD 中运行它? 为此,我们需要做两件事: + +1. 设置实际上具有浏览器的[CI / CD 作业](../../yaml/README.html#introduction) . +2. 更新我们的 WebdriverIO 配置以使用那些浏览器来访问评论应用程序. + +对于本文的范围,我们定义了一个附加的[CI / CD 阶段](../../yaml/README.html#stages) `confidence-check` ,该`confidence-check` *在*部署审阅应用程序的阶段*之后*执行. 它使用`node:latest` [Docker image](../../docker/using_docker_images.html) . 但是,WebdriverIO 会启动实际的浏览器来与您的应用程序进行交互,因此我们需要安装并运行它们. 此外,WebdriverIO 使用 Selenium 作为控制不同浏览器的通用接口,因此我们也需要安装和运行 Selenium. 幸运的是,Selenium 项目提供了分别为 Firefox 和 Chrome 提供的 Docker 映像[standalone-firefox](https://hub.docker.com/r/selenium/standalone-firefox/)和[standalone-chrome](https://hub.docker.com/r/selenium/standalone-chrome/) . (由于 Safari 和 Internet Explorer / Edge 不是开源的,并且不适用于 Linux,因此很遗憾,我们无法在 GitLab CI / CD 中使用它们.) + +GitLab CI / CD 使用`service`属性将这些图像链接到我们的`confidence-check`作业变得轻而易举,这使得 Selenium 服务器可以在基于图像名称的主机名下使用. 我们的工作配置如下所示: + +``` +e2e:firefox: + stage: confidence-check + services: + - selenium/standalone-firefox + script: + - npm run confidence-check --host=selenium__standalone-firefox +``` + +对于 Chrome 同样如此: + +``` +e2e:chrome: + stage: confidence-check + services: + - selenium/standalone-chrome + script: + - npm run confidence-check --host=selenium__standalone-chrome +``` + +现在我们有一项工作可以运行端到端测试,我们需要告诉 WebdriverIO 如何连接到与其并排运行的 Selenium 服务器. 通过将[`host`](https://webdriver.io/guide/getstarted/configuration.html#host)选项的值作为参数传递给`npm run confidence-check`命令在命令行上`npm run confidence-check` ,我们已经作弊了. 但是,我们仍然需要告诉 WebdriverIO 使用哪个浏览器. + +[GitLab CI / CD 提供了许多](../../variables/README.html#predefined-environment-variables)有关当前 CI 作业的信息[的变量](../../variables/README.html#predefined-environment-variables) . 我们可以使用此信息根据正在运行的作业动态设置 WebdriverIO 配置. 更具体地说,我们可以根据当前正在运行的作业的名称,告诉 WebdriverIO 使用哪个浏览器执行测试. 我们可以在 WebdriverIO 的配置文件中执行此操作,在上面将其命名为`wdio.conf.js` : + +``` +if(process.env.CI_JOB_NAME) { + dynamicConfig.capabilities = [ + { browserName: process.env.CI_JOB_NAME === 'e2e:chrome' ? 'chrome' : 'firefox' }, + ]; +} +``` + +同样,我们可以告诉 WebdriverIO 审阅应用程序在哪里运行-在本示例中,它位于`<branch name>.flockademic.com` : + +``` +if(process.env.CI_COMMIT_REF_SLUG) { + dynamicConfig.baseUrl = `https://${process.env.CI_COMMIT_REF_SLUG}.flockademic.com`; +} +``` + +并且我们可以确保仅当*不*使用`if (!process.env.CI)`在 CI 中运行时,才使用本地特定的配置. 基本上,这是在 GitLab CI / CD 上进行端到端测试所需的全部成分! + +回顾一下,我们的`.gitlab-ci.yml`配置文件如下所示: + +``` +image: node:8.10 +stages: + - deploy + - confidence-check +deploy_terraform: + stage: deploy + script: + # Your Review App deployment scripts - for a working example please check https://gitlab.com/Flockademic/Flockademic/blob/5a45f1c2412e93810fab50e2dab8949e2d0633c7/.gitlab-ci.yml#L315 +e2e:firefox: + stage: confidence-check + services: + - selenium/standalone-firefox + script: + - npm run confidence-check --host=selenium__standalone-firefox +e2e:chrome: + stage: confidence-check + services: + - selenium/standalone-chrome + script: + - npm run confidence-check --host=selenium__standalone-chrome +``` + +## What’s next[](#whats-next "Permalink") + +如果您要自己进行设置并希望了解生产项目的工作配置,请参阅: + +* [Flockademic’s `wdio.conf.js`](https://gitlab.com/Flockademic/Flockademic/blob/dev/wdio.conf.js) +* [Flockademic’s `.gitlab-ci.yml`](https://gitlab.com/Flockademic/Flockademic/blob/dev/.gitlab-ci.yml) +* [Flockademic’s tests](https://gitlab.com/Flockademic/Flockademic/tree/dev/__e2e__) + +WebdriverIO 还可以做更多的事情. 例如,您可以配置一个[`screenshotPath`](https://webdriver.io/guide/getstarted/configuration.html#screenshotPath)以告诉 WebdriverIO 在测试失败时进行截图. 然后告诉 GitLab CI / CD 存储这些[工件](../../yaml/README.html#artifacts) ,您将能够看到 GitLab 中出了什么问题. \ No newline at end of file diff --git a/docs/232.md b/docs/232.md new file mode 100644 index 0000000000000000000000000000000000000000..bc5bcc6cb4219aabe25f120181f86c59ba666884 --- /dev/null +++ b/docs/232.md @@ -0,0 +1,460 @@ +# DevOps and Game Dev with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/](https://docs.gitlab.com/ee/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/) + +* [The game](#the-game) +* [Requirements and setup](#requirements-and-setup) +* [Continuous Integration](#continuous-integration) + * [Build your game with GitLab CI/CD](#build-your-game-with-gitlab-cicd) + * [Test your game with GitLab CI/CD](#test-your-game-with-gitlab-cicd) + * [Run your CI/CD pipeline](#run-your-cicd-pipeline) +* [Continuous Deployment](#continuous-deployment) + * [Set up S3 Bucket](#set-up-s3-bucket) + * [Set up AWS Secrets](#set-up-aws-secrets) + * [Deploy your game with GitLab CI/CD](#deploy-your-game-with-gitlab-cicd) +* [Conclusion](#conclusion) +* [Further settings](#further-settings) + +# DevOps and Game Dev with GitLab CI/CD[](#devops-and-game-dev-with-gitlab-cicd "Permalink") + +随着 WebGL 和 WebSockets 的进步,浏览器作为游戏开发平台非常可行,而无需使用 Adobe Flash 之类的插件. 此外,通过使用 GitLab 和[AWS](https://aws.amazon.com/) ,单个游戏开发人员以及游戏开发团队可以轻松地在线托管基于浏览器的游戏. + +在本教程中,我们将专注于 DevOps,以及使用[GitLab CI / CD](../../README.html)使用持续集成/部署方法测试和托管游戏. 我们假设您熟悉 GitLab,JavaScript 和游戏开发的基础知识. + +## The game[](#the-game "Permalink") + +我们的[演示游戏](http://gitlab-game-demo.s3-website-us-east-1.amazonaws.com/)由一个简单的太空飞船组成,该太空飞船通过在给定方向上单击鼠标进行射击. + +在开发另一款游戏[Dark Nova](https://www.darknova.io)的开始时,创建强大的 CI / CD 流水线对于团队工作的快速节奏至关重要. 本教程将以我[之前的介绍性文章为基础,](https://ryanhallcs.wordpress.com/2017/03/15/devops-and-game-dev/)并执行以下步骤: + +1. 使用上一篇文章中的代码开始由 gulp 文件构建的准[相位](https://phaser.io)游戏 +2. 添加和运行单元测试 +3. 创建可以触发以给定方向生成`Bullet`的`Weapon`类 +4. 添加使用此武器并在屏幕上四处移动的`Player`类 +5. 添加我们将用于`Player`和`Weapon`的精灵 +6. 使用持续集成和持续部署方法进行测试和部署 + +到最后,我们将拥有一个[可玩游戏](http://gitlab-game-demo.s3-website-us-east-1.amazonaws.com/)的核心,该[游戏](http://gitlab-game-demo.s3-website-us-east-1.amazonaws.com/)在每次推送到[代码库](https://gitlab.com/blitzgren/gitlab-game-demo) `master`分支时都经过测试和部署. 这还将提供样板代码,用于启动具有以下组件的基于浏览器的游戏: + +* 用[TypeScript](https://s0www0typescriptlang0org.icopy.site/)和[PhaserJs 编写](https://phaser.io) +* 使用[Gulp](https://gulpjs.com)构建,运行和测试 +* [Chai](https://www.chaijs.com)和[Mocha 的](https://s0mochajs0org.icopy.site/)单元测试 +* 使用 GitLab 进行 CI / CD +* 在 GitLab.com 上托管代码库 +* 在 AWS 上托管游戏 +* 部署到 AWS + +## Requirements and setup[](#requirements-and-setup "Permalink") + +请参考我以前的文章[DevOps 和 Game Dev,](https://ryanhallcs.wordpress.com/2017/03/15/devops-and-game-dev/)以学习基础开发工具,运行类似于 Hello World 的游戏,以及从每次新推手到使用 GitLab CI / CD 来构建此游戏. 此游戏[存储库](https://gitlab.com/blitzgren/gitlab-game-demo)的`master`分支包含具有所有配置的完整版本. 如果您想继续阅读本文,可以从`devops-article`分支进行克隆并进行工作: + +``` +git clone git@gitlab.com:blitzgren/gitlab-game-demo.git +git checkout devops-article +``` + +接下来,我们将创建一小部分测试,以举例说明我希望该`Weapon`类经历的大多数状态. 首先,创建一个名为`lib/tests`的文件夹,并将以下代码添加到一个新文件`weaponTests.ts` : + +``` +import { expect } from 'chai'; +import { Weapon, BulletFactory } from '../lib/weapon'; + +describe('Weapon', () => { + var subject: Weapon; + var shotsFired: number = 0; + // Mocked bullet factory + var bulletFactory: BulletFactory = <BulletFactory>{ + generate: function(px, py, vx, vy, rot) { + shotsFired++; + } + }; + var parent: any = { x: 0, y: 0 }; + + beforeEach(() => { + shotsFired = 0; + subject = new Weapon(bulletFactory, parent, 0.25, 1); + }); + + it('should shoot if not in cooldown', () => { + subject.trigger(true); + subject.update(0.1); + expect(shotsFired).to.equal(1); + }); + + it('should not shoot during cooldown', () => { + subject.trigger(true); + subject.update(0.1); + subject.update(0.1); + expect(shotsFired).to.equal(1); + }); + + it('should shoot after cooldown ends', () => { + subject.trigger(true); + subject.update(0.1); + subject.update(0.3); // longer than timeout + expect(shotsFired).to.equal(2); + }); + + it('should not shoot if not triggered', () => { + subject.update(0.1); + subject.update(0.1); + expect(shotsFired).to.equal(0); + }); +}); +``` + +为了使用`gulpfile.js`构建和运行这些测试,我们还要将以下`gulpfile.js`函数添加到现有的`gulpfile.js`文件中: + +``` +gulp.task('build-test', function () { + return gulp.src('src/tests/**/*.ts', { read: false }) + .pipe(tap(function (file) { + // replace file contents with browserify's bundle stream + file.contents = browserify(file.path, { debug: true }) + .plugin(tsify, { project: "./tsconfig.test.json" }) + .bundle(); + })) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true}) ) + .pipe(gulp.dest('built/tests')); +}); + +gulp.task('run-test', function() { + gulp.src(['./built/tests/**/*.ts']).pipe(mocha()); +}); +``` + +我们将开始实施游戏的第一部分,并通过这些`Weapon`测试. `Weapon`类将公开一种方法,以给定的方向和速度触发子弹的生成. 稍后,我们将实现一个`Player`类,将用户输入绑定在一起以触发武器. 在`src/lib`文件夹中,创建一个`weapon.ts`文件. 我们将添加两个类: `Weapon`和`BulletFactory` ,它们将封装 Phaser 的**sprite**和**group**对象,以及游戏特定的逻辑. + +``` +export class Weapon { + private isTriggered: boolean = false; + private currentTimer: number = 0; + + constructor(private bulletFactory: BulletFactory, private parent: Phaser.Sprite, private cooldown: number, private bulletSpeed: number) { + } + + public trigger(on: boolean): void { + this.isTriggered = on; + } + + public update(delta: number): void { + this.currentTimer -= delta; + + if (this.isTriggered && this.currentTimer <= 0) { + this.shoot(); + } + } + + private shoot(): void { + // Reset timer + this.currentTimer = this.cooldown; + + // Get velocity direction from player rotation + var parentRotation = this.parent.rotation + Math.PI / 2; + var velx = Math.cos(parentRotation); + var vely = Math.sin(parentRotation); + + // Apply a small forward offset so bullet shoots from head of ship instead of the middle + var posx = this.parent.x - velx * 10 + var posy = this.parent.y - vely * 10; + + this.bulletFactory.generate(posx, posy, -velx * this.bulletSpeed, -vely * this.bulletSpeed, this.parent.rotation); + } +} + +export class BulletFactory { + + constructor(private bullets: Phaser.Group, private poolSize: number) { + // Set all the defaults for this BulletFactory's bullet object + this.bullets.enableBody = true; + this.bullets.physicsBodyType = Phaser.Physics.ARCADE; + this.bullets.createMultiple(30, 'bullet'); + this.bullets.setAll('anchor.x', 0.5); + this.bullets.setAll('anchor.y', 0.5); + this.bullets.setAll('outOfBoundsKill', true); + this.bullets.setAll('checkWorldBounds', true); + } + + public generate(posx: number, posy: number, velx: number, vely: number, rot: number): Phaser.Sprite { + // Pull a bullet from Phaser's Group pool + var bullet = this.bullets.getFirstExists(false); + + // Set the few unique properties about this bullet: rotation, position, and velocity + if (bullet) { + bullet.reset(posx, posy); + bullet.rotation = rot; + bullet.body.velocity.x = velx; + bullet.body.velocity.y = vely; + } + + return bullet; + } +} +``` + +最后,我们将重做我们的入口点`game.ts` ,将`Player`和`Weapon`对象绑定在一起,并将它们添加到更新循环中. 这是更新的`game.ts`文件的外观: + +``` +import { Player } from "./player"; +import { Weapon, BulletFactory } from "./weapon"; + +window.onload = function() { + var game = new Phaser.Game(800, 600, Phaser.AUTO, 'gameCanvas', { preload: preload, create: create, update: update }); + var player: Player; + var weapon: Weapon; + + // Import all assets prior to loading the game + function preload () { + game.load.image('player', 'assets/player.png'); + game.load.image('bullet', 'assets/bullet.png'); + } + + // Create all entities in the game, after Phaser loads + function create () { + // Create and position the player + var playerSprite = game.add.sprite(400, 550, 'player'); + playerSprite.anchor.setTo(0.5); + player = new Player(game.input, playerSprite, 150); + + var bulletFactory = new BulletFactory(game.add.group(), 30); + weapon = new Weapon(bulletFactory, player.sprite, 0.25, 1000); + + player.loadWeapon(weapon); + } + + // This function is called once every tick, default is 60fps + function update() { + var deltaSeconds = game.time.elapsedMS / 1000; // convert to seconds + player.update(deltaSeconds); + weapon.update(deltaSeconds); + } +} +``` + +运行`gulp serve` ,您可以四处奔跑射击. 精彩! 让我们更新 CI 管道,使其包括运行测试以及现有的构建作业. + +## Continuous Integration[](#continuous-integration "Permalink") + +为了确保我们的更改不会破坏构建并且所有测试仍然通过,我们利用持续集成(CI)来为每次推送自动运行这些检查. 通读本文以了解[持续集成,持续交付和持续部署](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) ,以及 GitLab 如何利用这些方法. 在上[一教程中,](https://ryanhallcs.wordpress.com/2017/03/15/devops-and-game-dev/)我们已经设置了一个`.gitlab-ci.yml`文件,用于从每次推送开始构建我们的应用程序. 我们需要设置一个新的 CI 作业进行测试,GitLab CI / CD 将使用我们从 gulp 生成的工件在构建作业后运行. + +请通读[CI / CD 配置](../../../ci/yaml/README.html)文件[上](../../../ci/yaml/README.html)的[文档,](../../../ci/yaml/README.html)以探索其内容并根据需要进行调整. + +### Build your game with GitLab CI/CD[](#build-your-game-with-gitlab-cicd "Permalink") + +我们需要更新构建作业以确保测试也能运行. 将`gulp build-test`添加到现有`build`作业的`script`数组的末尾. 一旦这些命令运行,我们就知道需要访问 GitLab CI / CD `artifacts`提供的`built`文件夹中的所有内容. 我们还将缓存`node_modules`以避免不得不完全重新拉动那些依赖项:只需将它们打包在缓存中即可. 这是完整的`build`工作: + +``` +build: + stage: build + script: + - npm i gulp -g + - npm i + - gulp + - gulp build-test + cache: + policy: push + paths: + - node_modules + artifacts: + paths: + - built +``` + +### Test your game with GitLab CI/CD[](#test-your-game-with-gitlab-cicd "Permalink") + +对于本地测试,我们只需要运行`gulp run-tests` ,这需要像`build`作业一样在全球范围内安装 gulp. 我们从缓存中拉出`node_modules` ,因此`npm i`命令不必做太多事情. 在准备部署时,我们知道我们仍然需要工件中的`built`文件夹,该文件夹将作为上一个作业的默认行为被带入. 最后,按照惯例,我们通过给 GitLab CI / CD 一个`test` [阶段](../../../ci/yaml/README.html#stages)来告知需要在`build`工作之后运行它. 按照 YAML 结构, `test`作业应如下所示: + +``` +test: + stage: test + script: + - npm i gulp -g + - npm i + - gulp run-test + cache: + policy: push + paths: + - node_modules/ + artifacts: + paths: + - built/ +``` + +我们为以指定间隔射击的`Weapon`类添加了单元测试. `Player`类实现了`Weapon`以及四处移动和射击的能力. 此外,我们还使用`.gitlab-ci.yml`在 GitLab CI / CD 管道中添加了测试工件和测试阶段,从而使我们能够在每次推送时运行测试. 现在,我们整个`.gitlab-ci.yml`文件应如下所示: + +``` +image: node:10 + +build: + stage: build + script: + - npm i gulp -g + - npm i + - gulp + - gulp build-test + cache: + policy: push + paths: + - node_modules/ + artifacts: + paths: + - built/ + +test: + stage: test + script: + - npm i gulp -g + - npm i + - gulp run-test + cache: + policy: pull + paths: + - node_modules/ + artifacts: + paths: + - built/ +``` + +### Run your CI/CD pipeline[](#run-your-cicd-pipeline "Permalink") + +而已! 添加所有新文件,提交并推送. 有关此时存储库外观的参考,请参考[示例存储库中与本文相关](https://gitlab.com/blitzgren/gitlab-game-demo/commit/8b36ef0ecebcf569aeb251be4ee13743337fcfe2)的[最终提交](https://gitlab.com/blitzgren/gitlab-game-demo/commit/8b36ef0ecebcf569aeb251be4ee13743337fcfe2) . 通过同时应用构建和测试阶段,GitLab 将在每次推送到我们的存储库时按顺序运行它们. 如果一切顺利,您将在管道的每个作业上得到一个绿色的复选标记: + +[![Passing Pipeline](img/1d8faac0ce4cf1206b5c2745df725ca6.png)](img/test_pipeline_pass.png) + +您可以通过单击`test`作业以输入完整的构建日志来确认测试通过. 滚动到底部,观察所有过去的荣耀: + +``` +$ gulp run-test +[18:37:24] Using gulpfile /builds/blitzgren/gitlab-game-demo/gulpfile.js +[18:37:24] Starting 'run-test'... +[18:37:24] Finished 'run-test' after 21 ms + + Weapon + ✓ should shoot if not in cooldown + ✓ should not shoot during cooldown + ✓ should shoot after cooldown ends + ✓ should not shoot if not triggered + + 4 passing (18ms) + +Uploading artifacts... +built/: found 17 matching files +Uploading artifacts to coordinator... ok id=17095874 responseStatus=201 Created token=aaaaaaaa Job succeeded +``` + +## Continuous Deployment[](#continuous-deployment "Permalink") + +我们在每次推送时都构建并测试了代码库. 为了完成持续部署的全部流程,让我们[使用 AWS S3](https://aws.amazon.com/free/)设置[免费的 Web 托管,](https://aws.amazon.com/free/)并通过一项工作来部署构建工件. GitLab 还提供了免费的静态站点托管服务[GitLab Pages](https://about.gitlab.com/stages-devops-lifecycle/pages/) ,但是 Dark Nova 特别使用需要使用`AWS S3`其他 AWS 工具. 通读本文,该文章描述了[如何同时部署到 S3 和 GitLab 页面,](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/)并且比本文讨论的内容更深入地研究 GitLab CI / CD 的原理. + +### Set up S3 Bucket[](#set-up-s3-bucket "Permalink") + +1. 登录您的 AWS 账户并转到[S3](https://console.aws.amazon.com/s3/home) +2. 点击顶部的**创建存储桶**链接 +3. 输入您选择的名称,然后单击下一步 +4. 保留默认**属性** ,然后单击下一步 +5. 单击" **管理组"权限** ,然后为" **所有人"**组允许" **读取** ",单击"下一步". +6. 创建存储桶,然后在您的 S3 存储桶列表中选择它 +7. 在右侧,单击" **属性"**并启用" **静态网站托管"**类别 +8. Update the radio button to the **使用此存储桶托管网站** selection. Fill in `index.html` and `error.html` respectively + +### Set up AWS Secrets[](#set-up-aws-secrets "Permalink") + +我们需要能够使用我们的 AWS 账户凭证部署到 AWS,但是我们当然不希望在源代码中添加机密信息. 幸运的是,GitLab 通过[Variables](../../../ci/variables/README.html)提供了解决方案. 由于[IAM](https://aws.amazon.com/iam/)管理,这可能会变得复杂. 作为最佳实践,您不应使用根安全凭证. 正确的 IAM 凭据管理不在本文讨论范围之内,但是 AWS 会提醒您,不建议使用 root 凭据,并且应该违反其最佳做法. 随意遵循最佳实践并使用自定义 IAM 用户的凭据,这将是两个相同的凭据(密钥 ID 和密钥). 充分了解[AWS 中的 IAM 最佳做法](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html)是一个好主意. 我们需要将以下凭据添加到 GitLab: + +1. 登录您的 AWS 账户并转到[安全凭证页面](https://console.aws.amazon.com/iam/home#/security_credential) +2. 单击**访问密钥**部分,然后**创建新的访问密钥** . 创建密钥并保留 ID 和秘密,以后需要它们 + + [![AWS Access Key Configuration](img/6b5837eb8878551d4881e94247d957e9.png)](img/aws_config_window.png) + +3. 转到您的 GitLab 项目,单击左侧栏中的**设置> CI / CD** . +4. 展开**变量**部分 + + [![GitLab Secret Config](img/7ac2e224cec000f3932b1186bc1d643f.png)](img/gitlab_config.png) + +5. 添加一个名为`AWS_KEY_ID`的密钥,并将步骤 2 中的密钥 ID 复制到" **值"**字段中 +6. 添加一个名为`AWS_KEY_SECRET`的密钥,并将步骤 2 中的密钥机密复制到" **值"**字段中 + +### Deploy your game with GitLab CI/CD[](#deploy-your-game-with-gitlab-cicd "Permalink") + +要部署构建工件,我们需要在 Shared Runner 上安装[AWS CLI](https://aws.amazon.com/cli/) . Shared Runner 还需要能够通过您的 AWS 账户进行身份验证以部署工件. 按照约定,AWS CLI 将寻找`AWS_ACCESS_KEY_ID`和`AWS_SECRET_ACCESS_KEY` . GitLab 的 CI 为我们提供了一种使用`deploy`作业的`variables`部分传递在上一节中设置的`variables`的方法. 最后,我们添加指令以确保`only`在推送到`master`时进行部署. 这样,每个分支仍然通过 CI 运行,并且只有合并(或直接提交)到 master 才会触发管道的`deploy`工作. 将它们放在一起可获得以下内容: + +``` +deploy: + stage: deploy + variables: + AWS_ACCESS_KEY_ID: "$AWS_KEY_ID" + AWS_SECRET_ACCESS_KEY: "$AWS_KEY_SECRET" + script: + - apt-get update + - apt-get install -y python3-dev python3-pip + - easy_install3 -U pip + - pip3 install --upgrade awscli + - aws s3 sync ./built s3://gitlab-game-demo --region "us-east-1" --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --cache-control "no-cache, no-store, must-revalidate" --delete + only: + - master +``` + +确保在最后一个脚本命令中更新区域和 S3 URL 以适合您的设置. 我们的最终配置文件`.gitlab-ci.yml`看起来像: + +``` +image: node:10 + +build: + stage: build + script: + - npm i gulp -g + - npm i + - gulp + - gulp build-test + cache: + policy: push + paths: + - node_modules/ + artifacts: + paths: + - built/ + +test: + stage: test + script: + - npm i gulp -g + - gulp run-test + cache: + policy: pull + paths: + - node_modules/ + artifacts: + paths: + - built/ + +deploy: + stage: deploy + variables: + AWS_ACCESS_KEY_ID: "$AWS_KEY_ID" + AWS_SECRET_ACCESS_KEY: "$AWS_KEY_SECRET" + script: + - apt-get update + - apt-get install -y python3-dev python3-pip + - easy_install3 -U pip + - pip3 install --upgrade awscli + - aws s3 sync ./built s3://gitlab-game-demo --region "us-east-1" --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --cache-control "no-cache, no-store, must-revalidate" --delete + only: + - master +``` + +## Conclusion[](#conclusion "Permalink") + +在[演示存储库中,](https://gitlab.com/blitzgren/gitlab-game-demo)您还可以找到一些样板代码来使[TypeScript](https://s0www0typescriptlang0org.icopy.site/) , [Mocha](https://s0mochajs0org.icopy.site/) , [Gulp](https://gulpjs.com/)和[Phaser](https://phaser.io)与 GitLab CI / CD 完美地结合在一起,这是在制作[Dark Nova 时](https://www.darknova.io)汲取的教训的结果. 使用免费和开源软件的组合,我们拥有完整的 CI / CD 流水线,游戏基础和单元测试,所有这些操作和部署都可以在每次熟练掌握的情况下完成-只需很少的代码. 可以通过 GitLab 的构建日志轻松调试错误,并且在成功提交后的几分钟内,您就可以在游戏中实时看到更改. + +借助 Dark Nova 从一开始就设置持续集成和持续部署可实现快速而稳定的开发. 我们可以轻松地在单独的[环境中](../../environments/index.html)测试更改,如果需要,可以在多个环境中测试更改. 平衡和更新多人游戏可能会持续且乏味,但是相信使用 GitLab CI / CD 进行稳定部署会在快速获得玩家更改方面有很大的喘息空间. + +## Further settings[](#further-settings "Permalink") + +以下是一些可以进一步研究的想法,可以加快或改善您的流程: + +* [纱线](https://yarnpkg.com)代替 npm +* 设置可以预加载依赖项和工具(如 AWS CLI)的自定义[Docker](../../../ci/docker/using_docker_images.html#define-image-and-services-from-gitlab-ciyml)映像 +* 将[自定义域](https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html)转发到游戏的 S3 静态网站 +* 如果您发现小型项目不必要,请合并工作 +* 避免排队,并设置自己的[自定义 GitLab CI / CD 运行器](https://about.gitlab.com/blog/2016/03/01/gitlab-runner-with-docker/) \ No newline at end of file diff --git a/docs/233.md b/docs/233.md new file mode 100644 index 0000000000000000000000000000000000000000..e49839b0b200df36d47ece2f15094399cfdbab85 --- /dev/null +++ b/docs/233.md @@ -0,0 +1,107 @@ +# Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/deploy_spring_boot_to_cloud_foundry/](https://docs.gitlab.com/ee/ci/examples/deploy_spring_boot_to_cloud_foundry/) + +* [Introduction](#introduction) +* [Requirements](#requirements) +* [Create your project](#create-your-project) +* [Configure the deployment to Cloud Foundry](#configure-the-deployment-to-cloud-foundry) +* [Configure GitLab CI/CD to deploy your application](#configure-gitlab-cicd-to-deploy-your-application) + +# Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD[](#deploy-a-spring-boot-application-to-cloud-foundry-with-gitlab-cicd "Permalink") + +## Introduction[](#introduction "Permalink") + +在本文中,我们将演示如何使用[连续部署](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-deployment)方法通过 GitLab CI / CD 将[Spring Boot](https://projects.spring.io/spring-boot/)应用程序部署到[Cloud Foundry(CF)](https://www.cloudfoundry.org/) . + +该项目的所有代码都可以在该[GitLab 存储库中](https://gitlab.com/gitlab-examples/spring-gitlab-cf-deploy-demo)找到. + +如果您有兴趣使用 GitLab CI / CD 将 Spring Boot 应用程序部署到 Kubernetes,请通读博客文章[GitLab CI 和 Kubernetes 持续交付 Spring Boot 应用程序](https://about.gitlab.com/blog/2016/12/14/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/) . + +## Requirements[](#requirements "Permalink") + +本教程假定您熟悉 Java,GitLab,Cloud Foundry 和 GitLab CI / CD. + +要继续进行,您将需要: + +* [Pivotal Web 服务(PWS)](https://run.pivotal.io/)或任何其他 Cloud Foundry(CF)实例上的帐户. +* 在 GitLab 上的帐户. + +**注意:**如果您没有部署到 PWS,则需要将以下所有命令中的`api.run.pivotal.io` URL 替换为 CF 实例的[API URL](https://docs.cloudfoundry.org/running/cf-api-endpoint.html) . + +## Create your project[](#create-your-project "Permalink") + +要创建您的 Spring Boot 应用程序,可以在创建新项目时在 GitLab 中使用 Spring 模板: + +[![New Project From Template](img/b64907bafa7c740c069ec7395a5c5471.png)](img/create_from_template.png) + +## Configure the deployment to Cloud Foundry[](#configure-the-deployment-to-cloud-foundry "Permalink") + +要部署到 Cloud Foundry,我们需要添加`manifest.yml`文件. 这是我们将用于部署应用程序的 CF CLI 的配置. 我们将在项目的根目录中创建以下内容: + +``` +--- +applications: + - name: gitlab-hello-world + random-route: true + memory: 1G + path: target/demo-0.0.1-SNAPSHOT.jar +``` + +## Configure GitLab CI/CD to deploy your application[](#configure-gitlab-cicd-to-deploy-your-application "Permalink") + +现在,我们需要将 GitLab CI / CD 配置文件( [`.gitlab-ci.yml`](../../yaml/README.html) )添加到项目的根目录. 这就是 GitLab 找出每当将代码推送到我们的存储库时需要运行哪些命令的方式. 我们将以下`.gitlab-ci.yml`文件添加到存储库的根目录中,GitLab 将自动检测该文件,并在推送代码后运行定义的步骤: + +``` +image: java:8 + +stages: + - build + - deploy + +before_script: + - chmod +x mvnw + +build: + stage: build + script: ./mvnw package + artifacts: + paths: + - target/demo-0.0.1-SNAPSHOT.jar + +production: + stage: deploy + script: + - curl --location "https://cli.run.pivotal.io/stable?release=linux64-binary&source=github" | tar zx + - ./cf login -u $CF_USERNAME -p $CF_PASSWORD -a api.run.pivotal.io + - ./cf push + only: + - master +``` + +我们使用了`java:8` [Docker 映像](../../docker/using_docker_images.html)来构建我们的应用程序,因为它在[Docker Hub](https://hub.docker.com/)上提供了最新的 Java 8 JDK. 我们还添加了[`only`子句,](../../yaml/README.html#onlyexcept-basic)以确保仅当我们推送到 master 分支[`only`](../../yaml/README.html#onlyexcept-basic)进行部署. + +现在,由于`.gitlab-ci.yml`定义的步骤需要凭据才能登录到 CF,因此您需要将 CF 凭据作为[环境变量添加](../../variables/README.html#predefined-environment-variables)到 GitLab CI / CD 上. 要设置环境变量,请导航至项目的**"设置">" CI / CD",**然后展开" **变量"** . 将变量命名为`CF_USERNAME`和`CF_PASSWORD`并将其设置为正确的值. + +[![Variable Settings in GitLab](img/75ff7ad133721fa954b7960ba4edc025.png)](img/cloud_foundry_variables.png) + +设置完成后,每次推送到存储库默认分支时,GitLab CI / CD 都会将您的应用程序部署到 CF. 要查看构建日志或观看构建的实时运行,请导航至**CI / CD> Pipelines** . + +**注意:**为安全性的最佳做法是为应用程序创建一个单独的部署用户,并将其凭据添加到 GitLab,而不使用开发人员的凭据. + +要在 GitLab 中开始手动部署,请转到**CI / CD>管道,**然后单击**运行管道** . 应用程序完成部署后,它将在`production`作业的日志中显示应用程序的 URL,例如: + +``` +requested state: started +instances: 1/1 +usage: 1G x 1 instances +urls: gitlab-hello-world-undissembling-hotchpot.cfapps.io +last uploaded: Mon Nov 6 10:02:25 UTC 2017 +stack: cflinuxfs2 +buildpack: client-certificate-mapper=1.2.0_RELEASE container-security-provider=1.8.0_RELEASE java-buildpack=v4.5-offline-https://github.com/cloudfoundry/java-buildpack.git#ffeefb9 java-main java-opts jvmkill-agent=1.10.0_RELEASE open-jdk-like-jre=1.8.0_1... + + state since cpu memory disk details +#0 running 2017-11-06 09:03:22 PM 120.4% 291.9M of 1G 137.6M of 1G +``` + +然后,您可以访问已部署的应用程序(对于本示例,为`https://gitlab-hello-world-undissembling-hotchpot.cfapps.io/` ),您应该看到"春天在这里!" 信息. \ No newline at end of file diff --git a/docs/234.md b/docs/234.md new file mode 100644 index 0000000000000000000000000000000000000000..dd7a45957a34536d92deee9f38dd59b8ace6682b --- /dev/null +++ b/docs/234.md @@ -0,0 +1,263 @@ +# How to deploy Maven projects to Artifactory with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/artifactory_and_gitlab/](https://docs.gitlab.com/ee/ci/examples/artifactory_and_gitlab/) + +* [Introduction](#introduction) +* [Create the simple Maven dependency](#create-the-simple-maven-dependency) + * [Prepare the dependency application](#prepare-the-dependency-application) + * [Configure the Artifactory deployment](#configure-the-artifactory-deployment) + * [Configure GitLab CI/CD for `simple-maven-dep`](#configure-gitlab-cicd-for-simple-maven-dep) +* [Create the main Maven application](#create-the-main-maven-application) + * [Prepare the main application](#prepare-the-main-application) + * [Configure the Artifactory repository location](#configure-the-artifactory-repository-location) + * [Configure GitLab CI/CD for `simple-maven-app`](#configure-gitlab-cicd-for-simple-maven-app) +* [Conclusion](#conclusion) + +# How to deploy Maven projects to Artifactory with GitLab CI/CD[](#how-to-deploy-maven-projects-to-artifactory-with-gitlab-cicd "Permalink") + +## Introduction[](#introduction "Permalink") + +在本文中,我们展示了如何利用[GitLab CI / CD 的功能](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)来构建[Maven](https://maven.apache.org/)项目,将其部署到[Artifactory](https://jfrog.com/artifactory/) ,然后从另一个 Maven 应用程序中将其用作依赖项. + +您将创建两个不同的项目: + +* `simple-maven-dep` :构建并部署到 Artifactory 的应用程序(请参阅[simple-maven-dep](https://gitlab.com/gitlab-examples/maven/simple-maven-dep)示例项目) +* `simple-maven-app` :使用前一个作为依赖[项的应用程序](https://gitlab.com/gitlab-examples/maven/simple-maven-app) (请参见[simple-maven-app](https://gitlab.com/gitlab-examples/maven/simple-maven-app)示例项目) + +我们假设您已经在[GitLab.com](https://gitlab.com/)上拥有一个 GitLab 帐户,并且您知道 Git 和[GitLab CI / CD](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)的基本用法. 我们还假定 Artifactory 实例在 Internet 上可用且可访问,并且您具有在其上部署的有效凭据. + +## Create the simple Maven dependency[](#create-the-simple-maven-dependency "Permalink") + +First of all, you need an application to work with: in this specific case we will use a simple one, but it could be any Maven application. This will be the dependency you want to package and deploy to Artifactory, in order to be available to other projects. + +### Prepare the dependency application[](#prepare-the-dependency-application "Permalink") + +对于本文,您将使用可以从示例项目中克隆的 Maven 应用程序: + +1. 登录到您的 GitLab 帐户 +2. 通过选择**URL 通过 URL 回购导入项目来**创建新项目 +3. 添加以下 URL: + + ``` + https://gitlab.com/gitlab-examples/maven/simple-maven-dep.git + ``` + +4. Click **建立专案** + +该应用程序不过是带有基于 JUnit 的测试套件的存根的基本类. 它公开了一种名为`hello`的方法,该方法接受字符串作为输入,并在屏幕上显示 hello 消息. + +该项目的结构非常简单,您应该考虑以下两个资源: + +* `pom.xml` :项目对象模型(POM)配置文件 +* `src/main/java/com/example/dep/Dep.java` :我们应用程序的源代码 + +### Configure the Artifactory deployment[](#configure-the-artifactory-deployment "Permalink") + +该应用程序已准备就绪,可以使用,但是您需要一些其他步骤才能将其部署到 Artifactory: + +1. 使用您的用户凭据登录到 Artifactory. +2. 在主屏幕上,单击" **设置我"**面板中的`libs-release-local`项目. +3. 将" **部署"**段落下的配置片段复制到剪贴板. +4. 更改`url`值,以使其可通过变量进行配置. +5. 在`dependencies`部分之后,将片段复制到项目的`pom.xml`文件中. 该代码段应如下所示: + + ``` + <distributionManagement> + <repository> + <id>central</id> + <name>83d43b5afeb5-releases</name> + <url>${env.MAVEN_REPO_URL}/libs-release-local</url> + </repository> + </distributionManagement> + ``` + +将依赖项部署到 Artifactory 之前,您需要做的另一步骤是配置身份验证数据. 这是一个简单的任务,但是 Maven 要求它保留在一个名为`settings.xml`的文件中,该文件必须位于用户 homedir 的`.m2`子目录中. + +由于要使用 GitLab Runner 自动部署应用程序,因此应在项目的主目录中创建文件,并在`.gitlab-ci.yml`设置命令行参数以使用自定义位置,而不是默认位置: + +1. 在存储库的根目录中创建一个名为`.m2`的文件夹 +2. 在`.m2`文件夹中创建一个名为`settings.xml`的文件 +3. 将以下内容复制到`settings.xml`文件中: + + ``` + <settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd" + xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <servers> + <server> + <id>central</id> + <username>${env.MAVEN_REPO_USER}</username> + <password>${env.MAVEN_REPO_PASS}</password> + </server> + </servers> + </settings> + ``` + + 用户名和密码将使用变量替换为正确的值. + +### Configure GitLab CI/CD for `simple-maven-dep`[](#configure-gitlab-cicd-for-simple-maven-dep "Permalink") + +现在是时候设置[GitLab CI / CD](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)来自动构建,测试和部署依赖项了! + +GitLab CI / CD 使用存储库根目录中的一个名为`.gitlab-ci.yml`来读取将由已配置的 GitLab Runners 执行的作业的定义. 您可以在[GitLab 文档中](../../yaml/README.html)阅读有关此文件的更多信息. + +首先,请记住为您的部署设置变量. 导航到项目的**"设置">" CI / CD">"环境变量"**页面,并添加以下内容(当然,将它们替换为当前值): + +* **MAVEN_REPO_URL** : `http://artifactory.example.com:8081/artifactory` : **//artifactory.example.com** : **8081/artifactory** (您的 Artifactory URL) +* **MAVEN_REPO_USER** : `gitlab` (您的 Artifactory 用户名) +* **MAVEN_REPO_PASS** : `AKCp2WXr3G61Xjz1PLmYa3arm3yfBozPxSta4taP3SeNu2HPXYa7FhNYosnndFNNgoEds8BCS` (您的 Artifactory 加密密码) + +现在是时候在`.gitlab-ci.yml`定义作业并将其推送到存储库了: + +``` +image: maven:latest + +variables: + MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode" + MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository" + +cache: + paths: + - .m2/repository/ + - target/ + +build: + stage: build + script: + - mvn $MAVEN_CLI_OPTS compile + +test: + stage: test + script: + - mvn $MAVEN_CLI_OPTS test + +deploy: + stage: deploy + script: + - mvn $MAVEN_CLI_OPTS deploy + only: + - master +``` + +GitLab Runner 将使用最新的[Maven Docker 映像](https://hub.docker.com/_/maven/) ,该[映像](https://hub.docker.com/_/maven/)已经包含了管理项目以运行作业所需的所有工具和依赖项. + +设置环境变量以指示 Maven 在搜索配置和依赖项时使用存储库的`homedir`而不是用户的`homedir` . + +缓存`.m2/repository folder` ( `.m2/repository folder`所有 Maven 文件的位置)和`target`文件夹(将创建我们的应用程序的位置),对于按顺序运行所有 Maven 阶段来加快过程非常有用,因此,执行`mvn test`会在必要时自动运行`mvn compile` . + +`build`作业和`test`作业均利用`mvn`命令来编译应用程序,并按照应用程序一部分的测试套件中的定义对其进行测试. + +部署到 Artifactory 的过程已由我们刚刚设置的变量定义. 仅当我们推送或合并到`master`分支时才进行部署,以便开发版本经过测试但未发布. + +做完了! 现在,您已在 GitLab 存储库中进行了所有更改,并且已经为此提交启动了管道. 在" **管道"**选项卡中,您可以查看正在发生的事情. 如果部署成功,则部署作业日志将输出: + +``` +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 1.983 s +``` + +> **注意** : `mvn`命令从 Internet 下载大量文件,因此,首次运行日志时,您会在日志中看到很多额外的活动. + +好极了! 你做到了! 检入 Artifactory 将确认`libs-release-local`存储库中有可用的新工件. + +## Create the main Maven application[](#create-the-main-maven-application "Permalink") + +现在您已经有了 Artifactory 上的依赖项,是时候使用它了! 让我们看看如何将其作为对主应用程序的依赖. + +### Prepare the main application[](#prepare-the-main-application "Permalink") + +我们将再次使用可以从示例项目中克隆的 Maven 应用程序: + +1. 通过选择**URL 通过 URL 回购导入项目来**创建新项目 +2. 添加以下 URL: + + ``` + https://gitlab.com/gitlab-examples/maven/simple-maven-app.git + ``` + +3. Click **建立专案** + +This one is a simple app as well. If you look at the `src/main/java/com/example/app/App.java` file you can see that it imports the `com.example.dep.Dep` class and calls the `hello` method passing `GitLab` as a parameter. + +由于 Maven 不知道如何解决依赖关系,因此您需要修改配置: + +1. 回到 Artifactory +2. 浏览`libs-release-local`存储库 +3. 选择`simple-maven-dep-1.0.jar`文件 +4. 从主面板的**Dependency Declaration**部分中找到配置片段 +5. 将代码段复制到`pom.xml`文件的`dependencies`部分中. 该代码段应如下所示: + + ``` + <dependency> + <groupId>com.example.dep</groupId> + <artifactId>simple-maven-dep</artifactId> + <version>1.0</version> + </dependency> + ``` + +### Configure the Artifactory repository location[](#configure-the-artifactory-repository-location "Permalink") + +至此,您已经定义了应用程序的依赖关系,但是仍然错过了可以找到所需文件的位置. 您需要像创建依赖项项目一样创建一个`.m2/settings.xml`文件,并使用环境变量让 Maven 知道位置. + +这是直接从 Artifactory 获取文件内容的方法: + +1. 在主屏幕上,单击" **设置我"**面板中的`libs-release-local`项目 +2. 单击**生成 Maven 设置** +3. 点击**生成设置** +4. 将配置文件复制到剪贴板 +5. 在存储库中将文件另存为`.m2/settings.xml` + +现在您可以使用 Artifactory 存储库来解决依赖关系,并在主应用程序中使用`simple-maven-dep` ! + +### Configure GitLab CI/CD for `simple-maven-app`[](#configure-gitlab-cicd-for-simple-maven-app "Permalink") + +您需要完成所有步骤:为该项目配置`.gitlab-ci.yml`文件,就像对`simple-maven-dep`所做的那样. + +您想利用[GitLab CI / CD](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)自动构建,测试和运行您的超赞应用程序,并查看是否可以按预期方式获得欢迎! + +您需要做的就是将以下`.gitlab-ci.yml`添加到存储库中: + +``` +image: maven:latest + +stages: + - build + - test + - run + +variables: + MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode" + MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository" + +cache: + paths: + - .m2/repository/ + - target/ + +build: + stage: build + script: + - mvn $MAVEN_CLI_OPTS compile + +test: + stage: test + script: + - mvn $MAVEN_CLI_OPTS test + +run: + stage: run + script: + - mvn $MAVEN_CLI_OPTS package + - mvn $MAVEN_CLI_OPTS exec:java -Dexec.mainClass="com.example.app.App" +``` + +它与用于`simple-maven-dep`的配置非常相似,但是有一个`run`作业代替了`deploy`作业. 可能是您不想在实际项目中使用的东西,但是在这里查看自动执行的应用程序很有用. + +就是这样! 在`run`作业输出日志中,您会找到与 GitLab 的友好问好! + +## Conclusion[](#conclusion "Permalink") + +在本文中,我们介绍了使用 Artifactory Maven 存储库自动发布和使用工件的基本步骤. + +可以使用类似的方法与任何其他 Maven 兼容的 Binary Repository Manager 进行交互. 显然,您可以改进这些示例,优化`.gitlab-ci.yml`文件以更好地满足您的需求,并适应您的工作流程. \ No newline at end of file diff --git a/docs/235.md b/docs/235.md new file mode 100644 index 0000000000000000000000000000000000000000..144596339736522ac6362914b9227fb6b665edca --- /dev/null +++ b/docs/235.md @@ -0,0 +1,255 @@ +# Testing PHP projects + +> 原文:[https://docs.gitlab.com/ee/ci/examples/php.html](https://docs.gitlab.com/ee/ci/examples/php.html) + +* [Test PHP projects using the Docker executor](#test-php-projects-using-the-docker-executor) + * [Test against different PHP versions in Docker builds](#test-against-different-php-versions-in-docker-builds) + * [Custom PHP configuration in Docker builds](#custom-php-configuration-in-docker-builds) +* [Test PHP projects using the Shell executor](#test-php-projects-using-the-shell-executor) + * [Test against different PHP versions in Shell builds](#test-against-different-php-versions-in-shell-builds) + * [Install custom extensions](#install-custom-extensions) +* [Extend your tests](#extend-your-tests) + * [Using atoum](#using-atoum) + * [Using Composer](#using-composer) +* [Access private packages or dependencies](#access-private-packages-or-dependencies) +* [Use databases or other services](#use-databases-or-other-services) +* [Testing things locally](#testing-things-locally) +* [Example project](#example-project) + +# Testing PHP projects[](#testing-php-projects "Permalink") + +本指南涵盖了 PHP 项目的基本构建说明. + +涵盖了两种测试方案:使用 Docker 执行程序和使用 Shell 执行程序. + +## Test PHP projects using the Docker executor[](#test-php-projects-using-the-docker-executor "Permalink") + +尽管可以在任何系统上测试 PHP 应用程序,但这都需要开发人员进行手动配置. 为了克服这个问题,我们将使用可在 Docker Hub 中找到的官方[PHP Docker 映像](https://hub.docker.com/_/php) . + +这将使我们能够针对不同版本的 PHP 测试 PHP 项目. 但是,并非所有事情都是即插即用的,您仍然需要手动配置一些东西. + +与每项工作一样,您需要创建一个描述构建环境的有效`.gitlab-ci.yml` . + +首先,让我们指定将用于作业过程的 PHP 映像(您可以在 Runner 的术语中阅读有关[使用 Docker 映像的](../docker/using_docker_images.html#what-is-an-image)更多信息,以了解映像的含义). + +首先将图像添加到您的`.gitlab-ci.yml` : + +``` +image: php:5.6 +``` + +官方图片很棒,但是缺少一些有用的测试工具. 我们需要首先准备构建环境. 解决此问题的一种方法是创建一个脚本,该脚本在完成实际测试之前会安装所有必备组件. + +Let’s create a `ci/docker_install.sh` file in the root directory of our repository with the following content: + +``` +#!/bin/bash + +# We need to install dependencies only for Docker +[[ ! -e /.dockerenv ]] && exit 0 + +set -xe + +# Install git (the php image doesn't have it) which is required by composer +apt-get update -yqq +apt-get install git -yqq + +# Install phpunit, the tool that we will use for testing +curl --location --output /usr/local/bin/phpunit https://phar.phpunit.de/phpunit.phar +chmod +x /usr/local/bin/phpunit + +# Install mysql driver +# Here you can install any other extension that you need +docker-php-ext-install pdo_mysql +``` + +您可能想知道`docker-php-ext-install`是什么. 简而言之,它是官方 PHP Docker 映像提供的脚本,可用于轻松安装扩展. 有关更多信息,请参阅[https://hub.docker.com/_/php 上](https://hub.docker.com/_/php)的文档. + +现在,我们创建了包含构建环境的所有先决条件的脚本,让我们将其添加到`.gitlab-ci.yml` : + +``` +... + +before_script: + - bash ci/docker_install.sh > /dev/null + +... +``` + +最后一步,使用`phpunit`运行实际测试: + +``` +... + +test:app: + script: + - phpunit --configuration phpunit_myapp.xml + +... +``` + +最后,提交文件并将其推送到 GitLab,以查看构建成功(或失败). + +最终的`.gitlab-ci.yml`应该类似于以下内容: + +``` +# Select image from https://hub.docker.com/_/php +image: php:5.6 + +before_script: +# Install dependencies + - bash ci/docker_install.sh > /dev/null + +test:app: + script: + - phpunit --configuration phpunit_myapp.xml +``` + +### Test against different PHP versions in Docker builds[](#test-against-different-php-versions-in-docker-builds "Permalink") + +针对多个版本的 PHP 进行测试非常容易. 只需添加另一个具有不同 Docker 映像版本的作业,即可由跑步者完成其余工作: + +``` +before_script: +# Install dependencies + - bash ci/docker_install.sh > /dev/null + +# We test PHP5.6 +test:5.6: + image: php:5.6 + script: + - phpunit --configuration phpunit_myapp.xml + +# We test PHP7.0 (good luck with that) +test:7.0: + image: php:7.0 + script: + - phpunit --configuration phpunit_myapp.xml +``` + +### Custom PHP configuration in Docker builds[](#custom-php-configuration-in-docker-builds "Permalink") + +有时,您需要通过将`.ini`文件放入`/usr/local/etc/php/conf.d/`来自定义 PHP 环境. 为此,添加一个`before_script`动作: + +``` +before_script: + - cp my_php.ini /usr/local/etc/php/conf.d/test.ini +``` + +当然, `my_php.ini`必须存在于存储库的根目录中. + +## Test PHP projects using the Shell executor[](#test-php-projects-using-the-shell-executor "Permalink") + +Shell 执行程序在服务器上的终端会话中运行您的作业. 因此,为了测试您的项目,您首先需要确保已安装所有依赖项. + +例如,在运行 Debian 8 的 VM 中,我们首先更新缓存,然后安装`phpunit`和`php5-mysql` : + +``` +sudo apt-get update -y +sudo apt-get install -y phpunit php5-mysql +``` + +接下来,将以下代码段添加到`.gitlab-ci.yml` : + +``` +test:app: + script: + - phpunit --configuration phpunit_myapp.xml +``` + +最后,推送到 GitLab 并开始测试! + +### Test against different PHP versions in Shell builds[](#test-against-different-php-versions-in-shell-builds "Permalink") + +[phpenv](https://github.com/phpenv/phpenv)项目使您可以轻松管理不同版本的 PHP,每个版本都有自己的配置. 当使用 Shell 执行程序测试 PHP 项目时,这特别有用. + +您必须按照[上游安装指南](https://github.com/phpenv/phpenv#installation)在`gitlab-runner`用户下将其安装在构建计算机[上](https://github.com/phpenv/phpenv#installation) . + +使用 phpenv 还可以通过以下方式轻松配置 PHP 环境: + +``` +phpenv config-add my_config.ini +``` + +***重要说明:**似乎`phpenv/phpenv` [被放弃了](https://github.com/phpenv/phpenv/issues/57) . [madumlao / phpenv](https://github.com/madumlao/phpenv)上有一个分叉,试图使该项目[复活](https://github.com/madumlao/phpenv) . [CHH / phpenv](https://github.com/CHH/phpenv)似乎也是一个不错的选择. 选择任何提到的工具将与基本 phpenv 命令一起使用. 指导您选择正确的 phpenv 不在本教程的范围内.* + +### Install custom extensions[](#install-custom-extensions "Permalink") + +由于这是 PHP 环境的裸机安装,因此您可能需要一些构建机器上当前不存在的扩展. + +要安装其他扩展,只需执行以下命令: + +``` +pecl install <extension> +``` + +不建议将其添加到`.gitlab-ci.yml` . 您应该只执行一次此命令,仅用于设置构建环境. + +## Extend your tests[](#extend-your-tests "Permalink") + +### Using atoum[](#using-atoum "Permalink") + +除了 PHPUnit,您可以使用任何其他工具来运行单元测试. 例如,您可以使用[atoum](https://github.com/atoum/atoum) : + +``` +before_script: + - wget http://downloads.atoum.org/nightly/mageekguy.atoum.phar + +test:atoum: + script: + - php mageekguy.atoum.phar +``` + +### Using Composer[](#using-composer "Permalink") + +大多数 PHP 项目使用 Composer 来管理其 PHP 软件包. 为了在运行测试之前执行 Composer,只需在`.gitlab-ci.yml`添加以下`.gitlab-ci.yml` : + +``` +... + +# Composer stores all downloaded packages in the vendor/ directory. +# Do not use the following if the vendor/ directory is committed to +# your git repository. +cache: + paths: + - vendor/ + +before_script: +# Install composer dependencies + - wget https://composer.github.io/installer.sig -O - -q | tr -d '\n' > installer.sig + - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + - php -r "if (hash_file('SHA384', 'composer-setup.php') === file_get_contents('installer.sig')) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" + - php composer-setup.php + - php -r "unlink('composer-setup.php'); unlink('installer.sig');" + - php composer.phar install + +... +``` + +## Access private packages or dependencies[](#access-private-packages-or-dependencies "Permalink") + +如果您的测试套件需要访问私有存储库,则需要配置[SSH 密钥](../ssh_keys/README.html)才能克隆它. + +## Use databases or other services[](#use-databases-or-other-services "Permalink") + +大多数时候,您将需要一个正在运行的数据库才能运行测试. 如果您使用的是 Docker 执行器,则可以利用 Docker 链接到其他容器的功能. 使用 GitLab Runner,可以通过定义`service`来实现. + +[CI 服务](../services/README.html)文档中涵盖了此功能. + +## Testing things locally[](#testing-things-locally "Permalink") + +使用 GitLab Runner 1.0,您还可以在本地测试所有更改. 从您的终端执行: + +``` +# Check using docker executor +gitlab-runner exec docker test:app + +# Check using shell executor +gitlab-runner exec shell test:app +``` + +## Example project[](#example-project "Permalink") + +为了方便起见,我们建立了一个[示例 PHP 项目](https://gitlab.com/gitlab-examples/php) ,该[项目](https://gitlab.com/gitlab-examples/php)使用我们的公共[共享](../runners/README.html)运行器在[GitLab.com](https://gitlab.com)上运行. + +想要破解吗? 只需对其进行分叉,提交并推送您的更改. 稍后,公共跑步者将选择更改并开始工作. \ No newline at end of file diff --git a/docs/236.md b/docs/236.md new file mode 100644 index 0000000000000000000000000000000000000000..eefebd37bc90e2fcabd066affce9dfe0338504af --- /dev/null +++ b/docs/236.md @@ -0,0 +1,165 @@ +# Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/deployment/composer-npm-deploy.html](https://docs.gitlab.com/ee/ci/examples/deployment/composer-npm-deploy.html) + +* [How to transfer files to a live server](#how-to-transfer-files-to-a-live-server) + * [Security tip](#security-tip) +* [How to deploy](#how-to-deploy) + * [Why we do it this way](#why-we-do-it-this-way) +* [Where to go next](#where-to-go-next) + +# Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD[](#running-composer-and-npm-scripts-with-deployment-via-scp-in-gitlab-cicd "Permalink") + +本指南涵盖了在使用[GitLab CI / CD](../../README.html)通过 NPM 脚本编译资产时,如何构建 PHP 项目的依赖项. + +虽然可以使用自定义的 PHP 和 Node.js 版本创建自己的映像,但为了简便起见,我们将使用既包含 PHP 又安装 Node.js 的现有[Docker 映像](https://hub.docker.com/r/tetraweb/php/) . + +``` +image: tetraweb/php +``` + +下一步是安装 zip / unzip 软件包并使 composer 可用. 我们将它们放在`before_script`部分中: + +``` +before_script: + - apt-get update + - apt-get install zip unzip + - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + - php composer-setup.php + - php -r "unlink('composer-setup.php');" +``` + +这将确保我们已准备好所有要求. 接下来,我们要运行`composer install`来获取所有 PHP 依赖项,然后运行`npm install`来加载 Node.js 包,然后运行`npm`脚本. 我们需要将它们附加到`before_script`部分: + +``` +before_script: + # ... + - php composer.phar install + - npm install + - npm run deploy +``` + +在此特定情况下, `npm deploy`脚本是执行以下操作的 Gulp 脚本: + +1. 编译 CSS 和 JS +2. Create sprites +3. 复制各种资产(图像,字体) +4. 替换一些字符串 + +所有这些操作会将所有文件放入一个`build`文件夹,该文件夹准备好部署到实时服务器中. + +## How to transfer files to a live server[](#how-to-transfer-files-to-a-live-server "Permalink") + +您有多种选择:rsync,SCP,SFTP 等. 现在,我们将使用 SCP. + +为此,您需要添加一个 GitLab CI / CD 变量(可在`gitlab.example/your-project-name/variables` ). 该变量将称为`STAGING_PRIVATE_KEY` ,它是服务器的**私密** SSH 密钥. + +### Security tip[](#security-tip "Permalink") + +创建一个**仅**可以访问需要更新的文件夹的用户. + +创建该变量后,需要确保在运行时将密钥添加到 Docker 容器中: + +``` +before_script: + # - .... + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + - mkdir -p ~/.ssh + - eval $(ssh-agent -s) + - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' +``` + +按顺序,这意味着: + +1. 我们检查`ssh-agent`是否可用,如果没有,则安装它. +2. 我们创建`~/.ssh`文件夹. +3. 我们确保正在运行 bash. +4. 我们禁用主机检查(当我们首次连接到服务器时,我们不要求用户接受,并且由于每个作业都将等同于首次连接,因此我们有点需要这样做). + +这基本上是您在`before_script`部分中所需要的. + +## How to deploy[](#how-to-deploy "Permalink") + +如上所述,我们需要将 Docker 镜像中的`build`文件夹部署到我们的服务器. 为此,我们创建了一个新作业: + +``` +stage_deploy: + artifacts: + paths: + - build/ + only: + - dev + script: + - ssh-add <(echo "$STAGING_PRIVATE_KEY") + - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp" + - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp + - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live" + - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old" +``` + +这是细分: + +1. `only:dev`表示仅当将某些内容推送到`dev`分支时,此构建才会运行. 您可以完全删除此块,并在每次推送时都运行所有内容(但是这可能是您不想要的) +2. `ssh-add ...`我们会将您在 Web UI 上添加的私钥添加到 Docker 容器中 +3. 我们将通过`ssh`连接并创建一个新的`_tmp`文件夹 +4. 我们将通过`scp`连接并将`build`文件夹(由`npm`脚本生成)上传到我们先前创建的`_tmp`文件夹中 +5. 我们将再次通过`ssh`连接,然后将`live`文件夹移至`_old`文件夹,然后将`_tmp`移至`live` . +6. 我们连接到 SSH 并删除`_old`文件夹 + +这些文物怎么处理? 我们只是告诉 GitLab CI / CD 保留`build`目录(以后,您可以根据需要下载该目录). + +### Why we do it this way[](#why-we-do-it-this-way "Permalink") + +如果仅将其用于舞台服务器,则可以分两个步骤进行操作: + +``` +- ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/live/*" +- scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/live +``` + +问题在于,服务器将在短时间内没有该应用程序. + +因此,对于生产环境,我们使用其他步骤来确保在任何给定时间都可以使用功能正常的应用程序. + +## Where to go next[](#where-to-go-next "Permalink") + +由于这是一个 WordPress 项目,因此我给出了真实的代码片段. 您可以追求一些进一步的想法: + +* `master`分支的脚本稍有不同,将使您可以从该分支部署到生产服务器,并从任何其他分支部署到阶段服务器. +* 除了将其实时发布之外,您还可以将其推送到 WordPress 官方存储库(创建 SVN 提交等). +* 您可以动态生成 i18n 文本域. + +* * * + +我们最终的`.gitlab-ci.yml`将如下所示: + +``` +image: tetraweb/php + +before_script: + - apt-get update + - apt-get install zip unzip + - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + - php composer-setup.php + - php -r "unlink('composer-setup.php');" + - php composer.phar install + - npm install + - npm run deploy + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + - mkdir -p ~/.ssh + - eval $(ssh-agent -s) + - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' + +stage_deploy: + artifacts: + paths: + - build/ + only: + - dev + script: + - ssh-add <(echo "$STAGING_PRIVATE_KEY") + - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp" + - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp + - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live" + - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old" +``` \ No newline at end of file diff --git a/docs/237.md b/docs/237.md new file mode 100644 index 0000000000000000000000000000000000000000..0bd7654e9b9d3d29578b11e353fcfe9d30937192 --- /dev/null +++ b/docs/237.md @@ -0,0 +1,644 @@ +# Test and deploy Laravel applications with GitLab CI/CD and Envoy + +> 原文:[https://docs.gitlab.com/ee/ci/examples/laravel_with_gitlab_and_envoy/](https://docs.gitlab.com/ee/ci/examples/laravel_with_gitlab_and_envoy/) + +* [Introduction](#introduction) +* [Initialize our Laravel app on GitLab](#initialize-our-laravel-app-on-gitlab) + * [Unit Test](#unit-test) + * [Push to GitLab](#push-to-gitlab) +* [Configure the production server](#configure-the-production-server) + * [Create a new user](#create-a-new-user) + * [Add SSH key](#add-ssh-key) + * [Configuring NGINX](#configuring-nginx) +* [Setting up Envoy](#setting-up-envoy) + * [How Envoy works](#how-envoy-works) + * [Zero downtime deployment](#zero-downtime-deployment) + * [@setup directive](#setup-directive) + * [@story directive](#story-directive) + * [Clone the repository](#clone-the-repository) + * [Installing dependencies with Composer](#installing-dependencies-with-composer) + * [Activate new release](#activate-new-release) + * [Full script](#full-script) +* [Continuous Integration with GitLab](#continuous-integration-with-gitlab) + * [Create a Container Image](#create-a-container-image) + * [Setting Up GitLab Container Registry](#setting-up-gitlab-container-registry) + * [Setting up GitLab CI/CD](#setting-up-gitlab-cicd) + * [Image and Services](#image-and-services) + * [Variables](#variables) + * [Unit Test as the first job](#unit-test-as-the-first-job) + * [Deploy to production](#deploy-to-production) + * [Turn on GitLab CI/CD](#turn-on-gitlab-cicd) +* [Conclusion](#conclusion) + +# Test and deploy Laravel applications with GitLab CI/CD and Envoy[](#test-and-deploy-laravel-applications-with-gitlab-cicd-and-envoy "Permalink") + +## Introduction[](#introduction "Permalink") + +GitLab 通过持续集成为我们的应用程序提供功能,并且可以随时将新的代码更改轻松部署到生产服务器. + +在本教程中,我们将向您展示如何初始化[Laravel](https://s0laravel0com.icopy.site)应用程序并设置[Envoy](https://s0laravel0com.icopy.site/docs/master/envoy)任务,然后我们将跳入如何使用[GitLab CI / CD](../README.html)通过[Continuous Delivery](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/)测试和部署它的方法. + +我们假设您具有 Laravel 和 Linux 服务器的基本经验,并且知道如何使用 GitLab. + +Laravel 是一个用 PHP 编写的高质量 Web 框架. 它有一个很棒的社区,提供了[很棒的文档](https://s0laravel0com.icopy.site/docs) . 除了常规的路由,控制器,请求,响应,视图和(刀片)模板外,Laravel 还提供了许多其他服务,例如缓存,事件,本地化,身份验证以及许多其他服务. + +我们将使用[Envoy](https://s0laravel0com.icopy.site/docs/master/envoy)作为基于 PHP 的 SSH 任务运行程序. 它使用简洁的[Blade 语法](https://s0laravel0com.icopy.site/docs/master/blade)来设置可以在远程服务器上运行的任务,例如,从存储库克隆项目,安装 Composer 依赖项以及运行[Artisan 命令](https://s0laravel0com.icopy.site/docs/master/artisan) . + +## Initialize our Laravel app on GitLab[](#initialize-our-laravel-app-on-gitlab "Permalink") + +我们假设[您已经安装了一个新的 Laravel 项目](https://s0laravel0com.icopy.site/docs/master/installation) ,所以让我们从单元测试开始,并为该项目初始化 Git. + +### Unit Test[](#unit-test "Permalink") + +Laravel 的每个新安装(当前为 5.4)都在测试目录中放置了两种类型的测试:"功能"和"单元". 这是来自`test/Unit/ExampleTest.php`的单元测试: + +``` +<?php + +namespace Tests\Unit; + +... + +class ExampleTest extends TestCase +{ + public function testBasicTest() + { + $this->assertTrue(true); + } +} +``` + +该测试就像断言给定值是 true 一样简单. + +Laravel 默认使用`PHPUnit`进行测试. 如果运行`vendor/bin/phpunit`我们应该看到绿色输出: + +``` +vendor/bin/phpunit +OK (1 test, 1 assertions) +``` + +该测试将在以后用于通过 GitLab CI / CD 持续测试我们的应用程序. + +### Push to GitLab[](#push-to-gitlab "Permalink") + +由于我们已经在本地启动并运行了应用程序,因此现在是将代码库推送到我们的远程存储库的时候了. 让我们在 GitLab 中创建[一个](../../../gitlab-basics/create-project.html)名为`laravel-sample` [的新项目](../../../gitlab-basics/create-project.html) . 之后,按照项目主页上显示的命令行说明在我们的计算机上启动存储库并推送第一个提交. + +``` +cd laravel-sample +git init +git remote add origin git@gitlab.example.com:<USERNAME>/laravel-sample.git +git add . +git commit -m 'Initial Commit' +git push -u origin master +``` + +## Configure the production server[](#configure-the-production-server "Permalink") + +在开始设置 Envoy 和 GitLab CI / CD 之前,让我们快速确保生产服务器已准备好进行部署. 我们已经在 Ubuntu 16.04 上安装了 LEMP 堆栈,该堆栈代表 Linux,NGINX,MySQL 和 PHP. + +### Create a new user[](#create-a-new-user "Permalink") + +现在,让我们创建一个新用户,该用户将用于部署我们的网站并使用[Linux ACL](https://serversforhackers.com/c/linux-acls)为其授予所需的权限: + +``` +# Create user deployer +sudo adduser deployer +# Give the read-write-execute permissions to deployer user for directory /var/www +sudo setfacl -R -m u:deployer:rwx /var/www +``` + +如果您的 Ubuntu 服务器上未安装 ACL,请使用以下命令进行安装: + +``` +sudo apt install acl +``` + +### Add SSH key[](#add-ssh-key "Permalink") + +假设我们要从 GitLab 上的私有存储库将应用程序部署到生产服务器. 首先,我们需要为部署者用户[生成一个**没有密码短语**的新 SSH 密钥对](../../../ssh/README.html) . + +之后,我们需要复制私钥,以使用 SSH 作为部署者用户将其用于连接到我们的服务器,以便能够自动化部署过程: + +``` +# As the deployer user on server +# +# Copy the content of public key to authorized_keys +cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys +# Copy the private key text block +cat ~/.ssh/id_rsa +``` + +现在,让我们将其作为[变量](../../variables/README.html#gitlab-cicd-environment-variables)添加到您的 GitLab 项目中. 变量是用户定义的变量,出于安全目的,它们存储在`.gitlab-ci.yml` . 可以通过导航到项目的**设置** > **CI / CD**来为每个项目添加它们. + +在**KEY**字段中,添加名称`SSH_PRIVATE_KEY` ,然后在**VALUE**字段中,粘贴您先前复制的私钥. 稍后,我们将在`.gitlab-ci.yml`使用此变量,以轻松地以部署者用户身份连接到我们的远程服务器,而无需输入其密码. + +[![variables page](img/a51fbcc597a6bc32e35c13c31799e36c.png)](img/variables_page.png) + +我们还需要将公共密钥作为[部署密钥](../../../ssh/README.html#deploy-keys)添加到" **项目"** > **"设置"** >" **存储库"** ,这使我们能够通过[SSH 协议](../../../gitlab-basics/command-line-commands.html#start-working-on-your-project)从服务器访问存储库. + +``` +# As the deployer user on the server +# +# Copy the public key +cat ~/.ssh/id_rsa.pub +``` + +在" **标题** "字段中,添加所需的任何名称,然后将公共密钥粘贴到" **密钥"**字段中. + +[![deploy keys page](img/9443fbb9f077bc7be6beb1486c392c96.png)](img/deploy_keys_page.png) + +现在,让我们在服务器上克隆存储库,以确保`deployer`用户可以访问该存储库. + +``` +# As the deployer user on server +# +git clone git@gitlab.example.com:<USERNAME>/laravel-sample.git +``` + +> **注意:**如果询问, **请**回答**是.** `Are you sure you want to continue connecting (yes/no)?` . 它将 GitLab.com 添加到已知主机. + +### Configuring NGINX[](#configuring-nginx "Permalink") + +现在,让我们确保我们的 Web 服务器配置指向`current/public`而不是`public` . + +通过键入以下内容来打开默认的 NGINX 服务器块配置文件: + +``` +sudo nano /etc/nginx/sites-available/default +``` + +配置应该是这样的. + +``` +server { + root /var/www/app/current/public; + server_name example.com; + # Rest of the configuration +} +``` + +> **注意:**您可以将`/var/www/app/current/public`的应用程序名称替换为应用程序的文件夹名称. + +## Setting up Envoy[](#setting-up-envoy "Permalink") + +因此,我们已经准备好生产 Laravel 应用. 接下来是使用 Envoy 执行部署. + +要使用 Envoy,我们应该首先[按照 Laravel 给出的说明](https://s0laravel0com.icopy.site/docs/master/envoy/)将其安装在本地计算机上. + +### How Envoy works[](#how-envoy-works "Permalink") + +Envoy 的优点是它不需要 Blade 引擎,只使用 Blade 语法定义任务. 首先,我们在应用程序的根目录中创建一个`Envoy.blade.php` ,其中包含一个简单的测试 Envoy 的任务. + +``` +@servers(['web' => 'remote_username@remote_host']) + +@task('list', ['on' => 'web']) + ls -l +@endtask +``` + +如您所料,我们在文件顶部的`@servers`指令中有一个数组,其中包含一个名为`web`的键,其值为服务器地址的值(例如, `deployer@192.168.1.1` 192.168.1.1). 然后,在我们的`@task`指令中,定义执行任务时应在服务器上运行的 bash 命令. + +在本地计算机上,使用`run`命令运行 Envoy 任务. + +``` +envoy run list +``` + +它应该执行我们之前定义的`list`任务,该任务连接到服务器并列出目录内容. + +Envoy 不是 Laravel 的依赖项,因此您可以将其用于任何 PHP 应用程序. + +### Zero downtime deployment[](#zero-downtime-deployment "Permalink") + +每次我们部署到生产服务器时,Envoy 都会从 GitLab 存储库下载我们应用程序的最新版本,并将其替换为预览版本. Envoy 做到了这一点,没有任何[停机时间](https://en.wikipedia.org/wiki/Downtime) ,因此我们在部署过程中不必担心有人在审查站点. 我们的部署计划是从 GitLab 存储库克隆最新版本,安装 Composer 依赖项,最后激活新版本. + +#### [@setup](https://gitlab.com/setup) directive[](#setup-directive "Permalink") + +我们部署过程的第一步是在内部定义一组变量 [](https://s0laravel0com.icopy.site/docs/master/envoy/)[@setup](https://gitlab.com/setup)指令. 您可以将`app`更改为您的应用名称: + +``` +... + +@setup + $repository = 'git@gitlab.example.com:<USERNAME>/laravel-sample.git'; + $releases_dir = '/var/www/app/releases'; + $app_dir = '/var/www/app'; + $release = date('YmdHis'); + $new_release_dir = $releases_dir .'/'. $release; +@endsetup + +... +``` + +* `$repository`是我们存储库的地址 +* `$releases_dir`目录是我们部署应用程序的位置 +* `$app_dir`是服务器上实时存在的应用程序的实际位置 +* `$release` contains a date, so every time that we deploy a new release of our app, we get a new folder with the current date as name +* `$new_release_dir`是新版本的完整路径,仅用于使任务更整洁 + +#### [@story](https://gitlab.com/story) directive[](#story-directive "Permalink") + +的 [](https://s0laravel0com.icopy.site/docs/master/envoy/)[@story](https://gitlab.com/story)指令允许我们定义可以作为单个任务运行的任务列表. 在这里,我们有三个任务,称为`clone_repository` , `run_composer`和`update_symlinks` . 这些变量可用于使我们的任务代码更清晰: + +``` +... + +@story('deploy') + clone_repository + run_composer + update_symlinks +@endstory + +... +``` + +让我们一一创建这三个任务. + +#### Clone the repository[](#clone-the-repository "Permalink") + +第一个任务将创建`releases`目录(如果不存在),然后将存储库的`master`分支(默认情况下)克隆到由`$new_release_dir`变量指定的新 release 目录中. `releases`目录将包含我们所有的部署: + +``` +... + +@task('clone_repository') + echo 'Cloning repository' + [ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }} + git clone --depth 1 {{ $repository }} {{ $new_release_dir }} + cd {{ $new_release_dir }} + git reset --hard {{ $commit }} +@endtask + +... +``` + +随着我们项目的发展,它的 Git 历史将随着时间的流逝而持续很长时间. 由于我们为每个版本创建一个目录,因此不必为每个版本下载项目的历史记录. `--depth 1`选项是一个很好的解决方案, `--depth 1`可以节省系统时间和磁盘空间. + +#### Installing dependencies with Composer[](#installing-dependencies-with-composer "Permalink") + +您可能知道,此任务只是导航到新的发行目录并运行 Composer 来安装应用程序依赖项: + +``` +... + +@task('run_composer') + echo "Starting deployment ({{ $release }})" + cd {{ $new_release_dir }} + composer install --prefer-dist --no-scripts -q -o +@endtask + +... +``` + +#### Activate new release[](#activate-new-release "Permalink") + +在准备好新版本的要求之后,接下来要做的就是从其中删除存储目录,并创建两个符号链接,以将应用程序的`storage`目录和`.env`文件指向新版本. 然后,我们需要创建另一个符号链接到新版本用的名称`current`放置在 app 目录. `current`符号链接始终指向我们应用程序的最新版本: + +``` +... + +@task('update_symlinks') + echo "Linking storage directory" + rm -rf {{ $new_release_dir }}/storage + ln -nfs {{ $app_dir }}/storage {{ $new_release_dir }}/storage + + echo 'Linking .env file' + ln -nfs {{ $app_dir }}/.env {{ $new_release_dir }}/.env + + echo 'Linking current release' + ln -nfs {{ $new_release_dir }} {{ $app_dir }}/current +@endtask +``` + +如您所见,我们使用`-nfs`作为`ln`命令的选项,它表示`storage` , `.env`和`current`不再指向预览的发行版, `-nfs`通过强制将它们指向新发行版( `-nfs` `f`表示强制) ,这是我们进行多个部署的情况. + +### Full script[](#full-script "Permalink") + +脚本已准备就绪,但请确保将`deployer@192.168.1.1`更改为服务器,并使用要部署应用程序的目录更改`/var/www/app` app. + +最后,我们的`Envoy.blade.php`文件将如下所示: + +``` +@servers(['web' => 'deployer@192.168.1.1']) + +@setup + $repository = 'git@gitlab.example.com:<USERNAME>/laravel-sample.git'; + $releases_dir = '/var/www/app/releases'; + $app_dir = '/var/www/app'; + $release = date('YmdHis'); + $new_release_dir = $releases_dir .'/'. $release; +@endsetup + +@story('deploy') + clone_repository + run_composer + update_symlinks +@endstory + +@task('clone_repository') + echo 'Cloning repository' + [ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }} + git clone --depth 1 {{ $repository }} {{ $new_release_dir }} + cd {{ $new_release_dir }} + git reset --hard {{ $commit }} +@endtask + +@task('run_composer') + echo "Starting deployment ({{ $release }})" + cd {{ $new_release_dir }} + composer install --prefer-dist --no-scripts -q -o +@endtask + +@task('update_symlinks') + echo "Linking storage directory" + rm -rf {{ $new_release_dir }}/storage + ln -nfs {{ $app_dir }}/storage {{ $new_release_dir }}/storage + + echo 'Linking .env file' + ln -nfs {{ $app_dir }}/.env {{ $new_release_dir }}/.env + + echo 'Linking current release' + ln -nfs {{ $new_release_dir }} {{ $app_dir }}/current +@endtask +``` + +在进行任何部署之前,我们应该做的另一件事是第一次将我们的应用程序`storage`文件夹手动复制到服务器上的`/var/www/app`目录. 您可能想要创建另一个 Envoy 任务来为您完成此任务. 我们还在同一路径中创建`.env`文件, `.env`设置生产环境变量. 这些是永久性数据,将与每个新版本共享. + +现在,我们需要通过运行`envoy run deploy`来部署我们的应用程序,但这不是必需的,因为 GitLab 可以在 CI 的[环境下](../../environments/index.html)为我们处理此事,这将在本教程的[后面部分](#setting-up-gitlab-cicd)进行介绍. + +现在是时候提交[Envoy.blade.php](https://gitlab.com/mehranrasulian/laravel-sample/blob/master/Envoy.blade.php)并将其推送到`master`分支了. 为了简化起见,我们直接致力于`master` ,而无需使用[功能分支,](../../../topics/gitlab_flow.html#github-flow-as-a-simpler-alternative)因为协作不在本教程的讨论范围之内. 在现实世界的项目中,团队可以使用[问题跟踪程序](../../../user/project/issues/index.html)和[合并请求](../../../user/project/merge_requests/index.html)在分支之间移动代码: + +``` +git add Envoy.blade.php +git commit -m 'Add Envoy' +git push origin master +``` + +## Continuous Integration with GitLab[](#continuous-integration-with-gitlab "Permalink") + +我们已经在 GitLab 上准备好了我们的应用程序,我们也可以手动部署它. 但是,让我们向前迈出一步,使用" [持续交付"](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-delivery)方法自动完成此操作. 我们需要使用一组自动化测试来检查每个提交,以尽早发现问题,然后,如果我们对测试结果感到满意,则可以将其部署到目标环境. + +[GitLab CI / CD](../../README.html)允许我们使用[Docker](https://www.docker.com)引擎来处理测试和部署应用程序的过程. 如果您不熟悉 Docker,请参阅[如何自动化 Docker 部署](http://paislee.io/how-to-automate-docker-deployments/) . + +为了能够使用 GitLab CI / CD 构建,测试和部署我们的应用程序,我们需要准备工作环境. 为此,我们将使用具有 Laravel 应用程序运行最低要求的 Docker 映像. [也有其他方法](../php.html#test-php-projects-using-the-docker-executor)可以执行此操作,但是它们可能会使我们的构建运行缓慢,而在使用更快的选项时,这不是我们想要的. + +有了 Docker 映像,我们的构建运行得异常快! + +### Create a Container Image[](#create-a-container-image "Permalink") + +让我们在应用程序的根目录中创建一个[包含](https://gitlab.com/mehranrasulian/laravel-sample/blob/master/Dockerfile)以下内容的[Dockerfile](https://gitlab.com/mehranrasulian/laravel-sample/blob/master/Dockerfile) : + +``` +# Set the base image for subsequent instructions +FROM php:7.1 + +# Update packages +RUN apt-get update + +# Install PHP and composer dependencies +RUN apt-get install -qq git curl libmcrypt-dev libjpeg-dev libpng-dev libfreetype6-dev libbz2-dev + +# Clear out the local repository of retrieved package files +RUN apt-get clean + +# Install needed extensions +# Here you can install any other extension that you need during the test and deployment process +RUN docker-php-ext-install mcrypt pdo_mysql zip + +# Install Composer +RUN curl --silent --show-error https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Install Laravel Envoy +RUN composer global require "laravel/envoy=~1.0" +``` + +我们添加了[官方的 PHP 7.1 Docker 映像](https://hub.docker.com/_/php) ,该[映像](https://hub.docker.com/_/php)由 Debian Jessie 的最低安装和预安装的 PHP 组成,并且非常适合我们的用例. + +我们使用了`docker-php-ext-install` (由官方 PHP Docker 映像提供)来安装所需的 PHP 扩展. + +#### Setting Up GitLab Container Registry[](#setting-up-gitlab-container-registry "Permalink") + +现在我们有了`Dockerfile`让我们构建并将其推送到[GitLab 容器注册表](../../../user/packages/container_registry/index.html) . + +> 注册表是存储和标记图像以供以后使用的地方. 开发人员可能希望维护自己的注册表,以用于私人,公司映像或仅用于测试的一次性映像. 使用 GitLab 容器注册表意味着您无需设置和管理另一项服务或使用公共注册表. + +在您的 GitLab 项目存储库上,导航到" **注册表"**选项卡. + +[![container registry page empty image](img/31d242e54217fe005ee1481fbb81c786.png)](img/container_registry_page_empty_image.png) + +您可能需要对项目[启用 Container Registry](../../../user/packages/container_registry/index.html#enable-the-container-registry-for-your-project)才能看到此选项卡. 您可以在项目的**设置>常规>可见性,项目功能,权限**下找到它. + +要在我们的机器上开始使用 Container Registry,我们首先需要使用我们的 GitLab 用户名和密码登录到 GitLab 注册表: + +``` +docker login registry.gitlab.com +``` + +然后,我们可以构建图像并将其推送到 GitLab: + +``` +docker build -t registry.gitlab.com/<USERNAME>/laravel-sample . + +docker push registry.gitlab.com/<USERNAME>/laravel-sample +``` + +> **注意:**要运行上述命令,我们首先需要在计算机上安装[Docker](https://s0docs0docker0com.icopy.site/engine/installation/) . + +恭喜你! 您刚刚将第一个 Docker 映像推送到了 GitLab 注册表,如果刷新页面,您应该可以看到它: + +[![container registry page with image](img/771e5d2c3cbeba5811f78938b976dfdf.png)](img/container_registry_page_with_image.jpg) + +> **注意:**您也可以[使用 GitLab CI / CD](https://about.gitlab.com/blog/2016/05/23/gitlab-container-registry/#use-with-gitlab-ci)来构建和推送 Docker 映像,而不是在计算机上执行. + +我们将在`.gitlab-ci.yml`配置文件中进一步使用此图像,以处理测试和部署我们的应用程序的过程. + +让我们提交`Dockerfile`文件. + +``` +git add Dockerfile +git commit -m 'Add Dockerfile' +git push origin master +``` + +### Setting up GitLab CI/CD[](#setting-up-gitlab-cicd "Permalink") + +为了使用 GitLab CI / CD 构建和测试我们的应用程序,我们需要在存储库的根目录中有一个名为`.gitlab-ci.yml`的文件. 它类似于 Circle CI 和 Travis CI,但内置 GitLab. + +我们的`.gitlab-ci.yml`文件将如下所示: + +``` +image: registry.gitlab.com/<USERNAME>/laravel-sample:latest + +services: + - mysql:5.7 + +variables: + MYSQL_DATABASE: homestead + MYSQL_ROOT_PASSWORD: secret + DB_HOST: mysql + DB_USERNAME: root + +stages: + - test + - deploy + +unit_test: + stage: test + script: + - cp .env.example .env + - composer install + - php artisan key:generate + - php artisan migrate + - vendor/bin/phpunit + +deploy_production: + stage: deploy + script: + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + - eval $(ssh-agent -s) + - ssh-add <(echo "$SSH_PRIVATE_KEY") + - mkdir -p ~/.ssh + - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' + + - ~/.composer/vendor/bin/envoy run deploy --commit="$CI_COMMIT_SHA" + environment: + name: production + url: http://192.168.1.1 + when: manual + only: + - master +``` + +需要很多东西,不是吗? 让我们逐步进行操作. + +#### Image and Services[](#image-and-services "Permalink") + +[GitLab Runners](../../runners/README.html)运行`.gitlab-ci.yml`定义的脚本. `image`关键字告诉跑步者要使用哪个图像. `services`关键字定义[链接到主图像的其他图像](../../docker/using_docker_images.html#what-is-a-service) . 在这里,我们将之前创建的容器映像用作主映像,还将 MySQL 5.7 用作服务. + +``` +image: registry.gitlab.com/<USERNAME>/laravel-sample:latest + +services: + - mysql:5.7 + +... +``` + +> **注意:**如果要使用不同的 PHP 版本和[数据库管理系统](../../services/README.html)测试应用程序,则可以为每个测试作业定义不同的`image`和`services`关键字. + +#### Variables[](#variables "Permalink") + +GitLab CI / CD 允许我们在工作中使用[环境变量](../../yaml/README.html#variables) . 我们将 MySQL 定义为数据库管理系统,它带有默认创建的超级用户根. + +因此,我们应该通过将`MYSQL_DATABASE`变量定义为数据库名称并将`MYSQL_ROOT_PASSWORD`变量定义为`root`的密码来调整 MySQL 实例的配置. 在[官方的 MySQL Docker Image 中](https://hub.docker.com/_/mysql)找到有关 MySQL 变量的更多信息. + +还要将变量`DB_HOST`设置为`mysql` ,将`DB_USERNAME`为`root` ,这是 Laravel 特定的变量. 我们将`DB_HOST`定义为`mysql`而不是`127.0.0.1` ,因为我们将 MySQL Docker 映像用作[与主 Docker 映像链接](../../docker/using_docker_images.html#how-services-are-linked-to-the-job)的服务. + +``` +... + +variables: + MYSQL_DATABASE: homestead + MYSQL_ROOT_PASSWORD: secret + DB_HOST: mysql + DB_USERNAME: root + +... +``` + +#### Unit Test as the first job[](#unit-test-as-the-first-job "Permalink") + +我们将所需的外壳程序脚本定义为运行`unit_test`作业时要执行的[脚本](../../yaml/README.html#script)变量的数组. + +These scripts are some Artisan commands to prepare the Laravel, and, at the end of the script, we’ll run the tests by `PHPUnit`. + +``` +... + +unit_test: + script: + # Install app dependencies + - composer install + # Set up .env + - cp .env.example .env + # Generate an environment key + - php artisan key:generate + # Run migrations + - php artisan migrate + # Run tests + - vendor/bin/phpunit + +... +``` + +#### Deploy to production[](#deploy-to-production "Permalink") + +`deploy_production`作业会将应用程序部署到生产服务器. 要使用 Envoy 部署我们的应用程序,我们必须将`$SSH_PRIVATE_KEY`变量设置为[SSH 私钥](../../ssh_keys/README.html#ssh-keys-when-using-the-docker-executor) . 如果 SSH 密钥已成功添加,我们可以运行 Envoy. + +如前所述,GitLab 也支持[持续交付](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-delivery)方法. [环境](../../yaml/README.html#environment)关键字告诉 GitLab 该作业已部署到`production`环境. `url`关键字用于在 GitLab 环境页面上生成指向我们应用程序的链接. `only`关键字告诉 GitLab CI / CD 只有在管道正在构建`master`分支时才应执行作业. 最后, `when: manual`用于将作业从自动运行转变为手动操作. + +``` +... + +deploy_production: + script: + # Add the private SSH key to the build environment + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + - eval $(ssh-agent -s) + - ssh-add <(echo "$SSH_PRIVATE_KEY") + - mkdir -p ~/.ssh + - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' + + # Run Envoy + - ~/.composer/vendor/bin/envoy run deploy + + environment: + name: production + url: http://192.168.1.1 + when: manual + only: + - master +``` + +您可能还需要为[登台环境](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/)添加另一个作业,以便在部署到生产[环境](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/)之前对应用程序进行最终测试. + +### Turn on GitLab CI/CD[](#turn-on-gitlab-cicd "Permalink") + +我们已经准备好使用 GitLab CI / CD 测试和部署应用程序所需的一切. 为此,请提交`.gitlab-ci.yml`并将其推入`master`分支. 它将触发管道,您可以在项目的**Pipelines**下实时观看. + +[![pipelines page](img/3ca3bc9234ff248b19d9555bb5f1cff4.png)](img/pipelines_page.png) + +Here we see our **Test** and **Deploy** stages. The **Test** stage has the `unit_test` build running. click on it to see the Runner’s output. + +[![pipeline page](img/55c6a94e74c9a00da3a400ae60e3bf41.png)](img/pipeline_page.png) + +代码成功通过管道后,我们可以通过单击右侧的**播放**按钮将其部署到生产服务器. + +[![pipelines page deploy button](img/52c8f25cfabbe64b4ed7e579d9a27e4a.png)](img/pipelines_page_deploy_button.png) + +部署管道成功通过后,导航至" **管道">"环境"** . + +[![environments page](img/d0e9aaf43b9e19912342dddfb4b6be13.png)](img/environments_page.png) + +如果某些操作无法正常工作,则可以回滚到应用程序的最新工作版本. + +[![environment page](img/bd8c2bfd77b1834503e87e4dc5b58420.png)](img/environment_page.png) + +通过单击右侧指定的外部链接图标,GitLab 将打开生产网站. 我们的部署成功完成,我们可以看到该应用程序正在运行. + +[![Laravel welcome page](img/c6a214b87abe3ccc6a5287ea1d256834.png)](img/laravel_welcome_page.png) + +如果您想了解部署后生产服务器上的应用程序目录结构如何,这里有三个目录,分别名为`current` , `releases`和`storage` . 如您所知, `current`目录是指向最新版本的符号链接. `.env`文件包含我们的 Laravel 环境变量. + +[![production server app directory](img/262e648fe4e99ca02b386ebade539097.png)](img/production_server_app_directory.png) + +如果导航到`current`目录,则应该看到应用程序的内容. 如您所见, `.env`指向`/var/www/app/.env`文件, `storage`也指向`/var/www/app/storage/`目录. + +[![production server current directory](img/6ad15d363481e18f443e6709fc8d1368.png)](img/production_server_current_directory.png) + +## Conclusion[](#conclusion "Permalink") + +我们将 GitLab CI / CD 配置为执行自动化测试,并使用" [持续交付](https://continuousdelivery.com/) "方法直接从代码库部署到带有 Envoy 的 Laravel 应用程序. + +Envoy 也非常适合帮助我们在不编写自定义 bash 脚本和进行 Linux 魔术的情况下部署应用程序. \ No newline at end of file diff --git a/docs/238.md b/docs/238.md new file mode 100644 index 0000000000000000000000000000000000000000..53ddd23f9e79ed7dd8138ce1524bb469c0e583d5 --- /dev/null +++ b/docs/238.md @@ -0,0 +1,97 @@ +# Test and deploy a Python application with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/test-and-deploy-python-application-to-heroku.html](https://docs.gitlab.com/ee/ci/examples/test-and-deploy-python-application-to-heroku.html) + +* [Configure project](#configure-project) +* [Store API keys](#store-api-keys) +* [Create Heroku application](#create-heroku-application) +* [Create Runner](#create-runner) + +# Test and deploy a Python application with GitLab CI/CD[](#test-and-deploy-a-python-application-with-gitlab-cicd "Permalink") + +本示例将指导您如何在 Python 应用程序中运行测试,以及如何将其自动部署为 Heroku 应用程序. + +您也可以查看或生成完整的[示例源](https://gitlab.com/ayufan/python-getting-started) . + +## Configure project[](#configure-project "Permalink") + +这是此项目的`.gitlab-ci.yml`文件的外观: + +``` +stages: + - test + - deploy + +test: + stage: test + script: + # this configures Django application to use attached postgres database that is run on `postgres` host + - export DATABASE_URL=postgres://postgres:@postgres:5432/python-test-app + - apt-get update -qy + - apt-get install -y python-dev python-pip + - pip install -r requirements.txt + - python manage.py test + +staging: + stage: deploy + script: + - apt-get update -qy + - apt-get install -y ruby-dev + - gem install dpl + - dpl --provider=heroku --app=gitlab-ci-python-test-staging --api-key=$HEROKU_STAGING_API_KEY + only: + - master + +production: + stage: deploy + script: + - apt-get update -qy + - apt-get install -y ruby-dev + - gem install dpl + - dpl --provider=heroku --app=gitlab-ci-python-test-prod --api-key=$HEROKU_PRODUCTION_API_KEY + only: + - tags +``` + +这个项目有三个工作: + +* `test` -用于测试 Django 应用程序. +* `staging` -用于每次推送到`master`分支时自动部署登台环境. +* `production` -用于为每个创建的标签自动部署生产环境. + +## Store API keys[](#store-api-keys "Permalink") + +您需要在 GitLab 项目的**"设置">" CI / CD">"环境变量"**中创建两个变量: + +* `HEROKU_STAGING_API_KEY` -Heroku API 密钥,用于部署登台应用程序. +* `HEROKU_PRODUCTION_API_KEY` -Heroku API 密钥,用于部署生产应用程序. + +在" [管理帐户"中](https://dashboard.heroku.com/account)找到您的 Heroku API 密钥. + +## Create Heroku application[](#create-heroku-application "Permalink") + +对于每个环境,您都需要创建一个新的 Heroku 应用程序. 您可以通过[仪表板](https://dashboard.heroku.com/)执行此操作. + +## Create Runner[](#create-runner "Permalink") + +首先安装[Docker Engine](https://s0docs0docker0com.icopy.site/installation/) . + +要构建此项目,您还需要安装[GitLab Runner](https://docs.gitlab.com/runner/index.html) . 您可以使用`gitlab.com`上的公共跑步者,也可以注册自己的跑步者: + +``` +cat > /tmp/test-config.template.toml << EOF [[runners]] +[runners.docker] +[[runners.docker.services]] +name = "postgres:latest" EOF gitlab-runner register \ + --non-interactive \ + --url "https://gitlab.com/" \ + --registration-token "PROJECT_REGISTRATION_TOKEN" \ + --description "python-3.5" \ + --executor "docker" \ + --template-config /tmp/test-config.template.toml \ + --docker-image python:3.5 +``` + +使用上面的命令,您将创建一个使用[`python:3.5`](https://hub.docker.com/_/python)图像并使用[PostgreSQL](https://hub.docker.com/_/postgres)数据库的运行器. + +要访问 PostgreSQL 数据库,请以没有密码的用户`postgres`身份连接到`host: postgres` . \ No newline at end of file diff --git a/docs/239.md b/docs/239.md new file mode 100644 index 0000000000000000000000000000000000000000..9d9a7b7a174627eee18583ad49ac36418f945fd0 --- /dev/null +++ b/docs/239.md @@ -0,0 +1,94 @@ +# Test and deploy a Ruby application with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/examples/test-and-deploy-ruby-application-to-heroku.html](https://docs.gitlab.com/ee/ci/examples/test-and-deploy-ruby-application-to-heroku.html) + +* [Configure the project](#configure-the-project) +* [Store API keys](#store-api-keys) +* [Create Heroku application](#create-heroku-application) +* [Create Runner](#create-runner) + +# Test and deploy a Ruby application with GitLab CI/CD[](#test-and-deploy-a-ruby-application-with-gitlab-cicd "Permalink") + +该示例将指导您如何在 Ruby on Rails 应用程序中运行测试,以及如何将其自动部署为 Heroku 应用程序. + +您还可以查看或派生完整的[示例源,](https://gitlab.com/ayufan/ruby-getting-started)并查看其过去[CI 作业](https://gitlab.com/ayufan/ruby-getting-started/-/jobs?scope=finished)的日志. + +## Configure the project[](#configure-the-project "Permalink") + +这是此项目的`.gitlab-ci.yml`文件的外观: + +``` +test: + stage: test + script: + - apt-get update -qy + - apt-get install -y nodejs + - bundle install --path /cache + - bundle exec rake db:create RAILS_ENV=test + - bundle exec rake test + +staging: + stage: deploy + script: + - gem install dpl + - dpl --provider=heroku --app=gitlab-ci-ruby-test-staging --api-key=$HEROKU_STAGING_API_KEY + only: + - master + +production: + stage: deploy + script: + - gem install dpl + - dpl --provider=heroku --app=gitlab-ci-ruby-test-prod --api-key=$HEROKU_PRODUCTION_API_KEY + only: + - tags +``` + +这个项目有三个工作: + +* `test` -用于测试 Rails 应用程序. +* `staging` -用于每次推送到`master`分支时自动部署登台环境. +* `production` -用于为每个创建的标签自动部署生产环境. + +## Store API keys[](#store-api-keys "Permalink") + +您需要在项目的**设置> CI / CD>环境变量中**创建两个**变量** : + +* `HEROKU_STAGING_API_KEY` -Heroku API 密钥,用于部署登台应用程序. +* `HEROKU_PRODUCTION_API_KEY` -Heroku API 密钥,用于部署生产应用程序. + +Find your Heroku API key in [Manage Account](https://dashboard.heroku.com/account). + +## Create Heroku application[](#create-heroku-application "Permalink") + +对于每个环境,您都需要创建一个新的 Heroku 应用程序. 您可以通过[Heroku 仪表板](https://dashboard.heroku.com/)执行此操作. + +## Create Runner[](#create-runner "Permalink") + +首先安装[Docker Engine](https://s0docs0docker0com.icopy.site/installation/) . + +要构建此项目,您还需要安装[GitLab Runner](https://docs.gitlab.com/runner/) . 您可以使用`gitlab.com`上的公共跑步者或注册自己的跑步者. 首先创建模板配置文件以通过复杂的配置: + +``` +cat > /tmp/test-config.template.toml << EOF [[runners]] +[runners.docker] +[[runners.docker.services]] +name = "postgres:latest" EOF +``` + +最后,注册运行器,并传递新创建的模板配置文件: + +``` +gitlab-runner register \ + --non-interactive \ + --url "https://gitlab.com/" \ + --registration-token "PROJECT_REGISTRATION_TOKEN" \ + --description "ruby:2.6" \ + --executor "docker" \ + --template-config /tmp/test-config.template.toml \ + --docker-image ruby:2.6 +``` + +使用上面的命令,您将创建一个使用[`ruby:2.6`](https://hub.docker.com/_/ruby)图像并使用[PostgreSQL](https://hub.docker.com/_/postgres)数据库的 Runner. + +要访问 PostgreSQL 数据库,请以没有密码的用户`postgres`身份连接到`host: postgres` . \ No newline at end of file diff --git a/docs/240.md b/docs/240.md new file mode 100644 index 0000000000000000000000000000000000000000..c4cc0864baf52886caefa405f4500acbe51c1852 --- /dev/null +++ b/docs/240.md @@ -0,0 +1,70 @@ +# Test and deploy a Scala application to Heroku + +> 原文:[https://docs.gitlab.com/ee/ci/examples/test-scala-application.html](https://docs.gitlab.com/ee/ci/examples/test-scala-application.html) + +* [Add `.gitlab-ci.yml` file to project](#add-gitlab-ciyml-file-to-project) +* [Display test coverage in job](#display-test-coverage-in-job) +* [Heroku application](#heroku-application) +* [Heroku API key](#heroku-api-key) + +# Test and deploy a Scala application to Heroku[](#test-and-deploy-a-scala-application-to-heroku "Permalink") + +该示例演示了使用 SBT 将 GitLab CI / CD 与 Scala 应用程序集成. 您可以查看或创建[示例项目,](https://gitlab.com/gitlab-examples/scala-sbt)并查看其过去的[CI 作业](https://gitlab.com/gitlab-examples/scala-sbt/-/jobs?scope=finished)的日志. + +## Add `.gitlab-ci.yml` file to project[](#add-gitlab-ciyml-file-to-project "Permalink") + +以下`.gitlab-ci.yml`应该添加到存储库的根目录中以触发 CI: + +``` +image: openjdk:8 + +stages: + - test + - deploy + +before_script: + - apt-get update -y + - apt-get install apt-transport-https -y + ## Install SBT + - echo "deb http://dl.bintray.com/sbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list + - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823 + - apt-get update -y + - apt-get install sbt -y + - sbt sbtVersion + +test: + stage: test + script: + - sbt clean coverage test coverageReport + +deploy: + stage: deploy + script: + - apt-get update -yq + - apt-get install rubygems ruby-dev -y + - gem install dpl + - dpl --provider=heroku --app=gitlab-play-sample-app --api-key=$HEROKU_API_KEY +``` + +在以上配置中: + +* `before_script`将安装[SBT](https://www.scala-sbt.org/)并显示正在使用的版本. +* `test`阶段执行 SBT 来编译和测试项目. + * [sbt-scoverage](https://github.com/scoverage/sbt-scoverage)用作 SBT 插件来测量测试覆盖率. +* `deploy`阶段使用 dpl 将项目自动部署到 Heroku. + +您可以通过在`build.sbt`定义其他版本的 Scala 和 SBT 来使用它们. + +## Display test coverage in job[](#display-test-coverage-in-job "Permalink") + +在**设置➔管道➔覆盖率报告**项目设置中,将`Coverage was \[\d+.\d+\%\]`添加`Coverage was \[\d+.\d+\%\]`正则表达式,以从构建跟踪中检索[测试覆盖率](../pipelines/settings.html#test-coverage-report-badge)并将其与作业一起显示. + +必须启用**管道**才能显示此选项. + +## Heroku application[](#heroku-application "Permalink") + +需要 Heroku 应用程序. 您可以通过[仪表板](https://dashboard.heroku.com/)创建一个. 用您的应用程序名称`.gitlab-ci.yml`文件中的`gitlab-play-sample-app` . + +## Heroku API key[](#heroku-api-key "Permalink") + +您可以在[帐户中](https://dashboard.heroku.com/account)查找 Heroku API 密钥. 使用键`HEROKU_API_KEY`在**项目➔变量中**添加具有此值的[受保护变量](../variables/README.html#protect-a-custom-variable) . \ No newline at end of file diff --git a/docs/241.md b/docs/241.md new file mode 100644 index 0000000000000000000000000000000000000000..3c238ff41e268fb1762670e2b39cc2359f6bab0f --- /dev/null +++ b/docs/241.md @@ -0,0 +1,81 @@ +# GitLab CI/CD for external repositories + +> 原文:[https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/) + +* [Pipelines for external pull requests](#pipelines-for-external-pull-requests) + * [How it works](#how-it-works) + * [Additional predefined variables](#additional-predefined-variables) + * [Limitations](#limitations) + +# GitLab CI/CD for external repositories[](#gitlab-cicd-for-external-repositories-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4642) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.6. + +GitLab CI / CD 可用于: + +* [GitHub](github_integration.html). +* [Bitbucket Cloud](bitbucket_integration.html). +* 任何其他 Git 服务器. + +无需将整个项目移至 GitLab,您可以连接外部存储库以获得 GitLab CI / CD 的好处. + +连接外部存储库将建立[存储库镜像](../../user/project/repository/repository_mirroring.html)并创建一个轻型项目,其中禁用了问题,合并请求,Wiki 和代码片段. 这些功能[可以稍后重新启用](../../user/project/settings/index.html#sharing-and-permissions) . + +要连接到外部存储库: + +1. 在您的 GitLab 仪表板上,点击**新建项目** . +2. 切换到**CI / CD 的外部回购**标签. +3. Choose **GitHub** or **通过 URL 回购**. +4. 后续步骤类似于[导入流程](../../user/project/import/index.html) . + +[![CI/CD for external repository project creation](img/8855ae33dbb80420649c523afdf3fe8b.png)](img/ci_cd_for_external_repo.png) + +## Pipelines for external pull requests[](#pipelines-for-external-pull-requests "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/65139) in GitLab Premium 12.3. + +当将 GitLab CI / CD 与[GitHub 上](github_integration.html)的[外部存储库一起使用时](github_integration.html) ,可以在 Pull Request 上下文中运行管道. + +当您将更改推送到 GitHub 中的远程分支时,GitLab CI / CD 可以为该分支运行管道. 但是,当您打开或更新该分支的"拉取请求"时,您可能需要: + +* 运行额外的工作. +* 不运行特定作业. + +例如: + +``` +always-run: + script: echo 'this should always run' + +on-pull-requests: + script: echo 'this should run on pull requests' + only: + - external_pull_requests + +except-pull-requests: + script: echo 'this should not run on pull requests' + except: + - external_pull_requests +``` + +### How it works[](#how-it-works "Permalink") + +从 GitHub 导入存储库时,GitLab 会订阅 webhooks 的`push`和`pull_request`事件. 收到`pull_request`事件后,将存储请求请求数据并将其保留为参考. 如果刚刚创建了 Pull Request,则 GitLab 会立即为外部 Pull Request 创建管道. + +如果将更改推送到"拉取请求"所引用的分支,并且"拉取请求"仍处于打开状态,则会创建用于外部拉取请求的管道. + +**注意:**在这种情况下,GitLab CI / CD 将创建 2 条管道. 一种用于分支推送,另一种用于外部拉取请求. + +关闭"拉取请求"后,即使将新的更改推送到同一分支,也不会为外部拉取请求创建任何管道. + +### Additional predefined variables[](#additional-predefined-variables "Permalink") + +通过将管道用于外部拉取请求,GitLab 将其他[预定义变量](../variables/predefined_variables.html)公开给管道作业. + +变量名称以`CI_EXTERNAL_PULL_REQUEST_`为前缀. + +### Limitations[](#limitations "Permalink") + +此功能当前不支持来自派生存储库的拉取请求. 来自 fork 存储库的任何 Pull Requests 将被忽略. [阅读更多](https://gitlab.com/gitlab-org/gitlab/-/issues/5667) . + +鉴于 GitLab 将创建 2 条管道,如果将更改推送到引用了打开的 Pull Request 的远程分支,则两者都将通过 GitHub 集成促进 Pull Request 的状态. 如果要只在外部请求请求上而不是在分支上运行管道,则可以添加以下内容, `except: [branches]`到作业规范. [阅读更多](https://gitlab.com/gitlab-org/gitlab/-/issues/24089#workaround) . \ No newline at end of file diff --git a/docs/242.md b/docs/242.md new file mode 100644 index 0000000000000000000000000000000000000000..78c54e2be361f77edce7e59c8ff2e4c363b100fa --- /dev/null +++ b/docs/242.md @@ -0,0 +1,130 @@ +# Using GitLab CI/CD with a Bitbucket Cloud repository + +> 原文:[https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/bitbucket_integration.html](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/bitbucket_integration.html) + +# Using GitLab CI/CD with a Bitbucket Cloud repository[](#using-gitlab-cicd-with-a-bitbucket-cloud-repository-premium "Permalink") + +GitLab CI / CD 可以通过以下方式与 Bitbucket Cloud 一起使用: + +1. 创建一个[CI / CD 项目](../../user/project/ci_cd_for_external_repo.html) . +2. 通过 URL 连接您的 Git 存储库. + +要将 GitLab CI / CD 与 Bitbucket Cloud 存储库一起使用: + +1. 在 GitLab 中**为外部** **仓库**创建一个**CI / CD** ,选择" **按 URL 进行仓库"**并创建项目. + + [![Create project](img/d4fcdfd2497a9936b17469dbafbd320e.png)](img/external_repository.png) + + GitLab 将导入存储库并启用[Pull Mirroring](../../user/project/repository/repository_mirroring.html#pulling-from-a-remote-repository-starter) . + +2. 在 GitLab 中,创建具有`api`作用域的[个人访问令牌](../../user/profile/personal_access_tokens.html) . 这将用于验证来自 Web 钩子的请求,该请求将在 Bitbucket 中创建,以将新提交通知 GitLab. + +3. 在 Bitbucket 中,从**"设置">" Webhooks"**中创建一个新的 Web 挂钩,以将新的提交通知 GitLab. + + 应该使用我们刚刚生成的用于身份验证的个人访问令牌,将 Web 挂钩 URL 设置为 GitLab API 来触发拉镜像. + + ``` + https://gitlab.com/api/v4/projects/<PROJECT_ID>/mirror/pull?private_token=<PERSONAL_ACCESS_TOKEN> + ``` + + 网络挂钩触发器应设置为" Repository Push". + + [![Bitbucket Cloud webhook](img/3a328cbf9c83e567fa5921d3580a84cb.png)](img/bitbucket_webhook.png) + + 保存后,通过将更改推送到您的 Bitbucket 存储库来测试 Web 挂钩. + +4. 在 Bitbucket 中,从" **Bitbucket 设置">"应用程序密码"中**创建一个**应用** **程序密码,**以验证构建状态脚本设置来提交 Bitbucket 中的构建状态. 存储库写权限是必需的. + + [![Bitbucket Cloud webhook](img/0d3f7491de96f0f5d1d30a594ec42739.png)](img/bitbucket_app_password.png) + +5. 在 GitLab 中,从**设置> CI / CD>环境变量中** ,添加变量以允许通过 Bitbucket API 与 Bitbucket 通信: + + `BITBUCKET_ACCESS_TOKEN` :上面创建的 Bitbucket 应用密码. + + `BITBUCKET_USERNAME` :Bitbucket 帐户的用户名. + + `BITBUCKET_NAMESPACE` :如果您的 GitLab 和 Bitbucket 命名空间不同,请设置此项. + + `BITBUCKET_REPOSITORY` :如果您的 GitLab 和 Bitbucket 项目名称不同,请设置此项. + +6. 在 Bitbucket 中,添加脚本以将管道状态推送到 Bitbucket. + + > 注意:在 GitLab 中所做的更改将被 Bitbucket 在上游进行的任何更改所覆盖. + + 创建一个文件`build_status`并在下面插入脚本,然后在终端中运行`chmod +x build_status`以使脚本可执行. + + ``` + #!/usr/bin/env bash + + # Push GitLab CI/CD build status to Bitbucket Cloud + + if [ -z "$BITBUCKET_ACCESS_TOKEN" ]; then echo "ERROR: BITBUCKET_ACCESS_TOKEN is not set" + exit 1 + fi + if [ -z "$BITBUCKET_USERNAME" ]; then echo "ERROR: BITBUCKET_USERNAME is not set" + exit 1 + fi + if [ -z "$BITBUCKET_NAMESPACE" ]; then echo "Setting BITBUCKET_NAMESPACE to $CI_PROJECT_NAMESPACE" + BITBUCKET_NAMESPACE=$CI_PROJECT_NAMESPACE + fi + if [ -z "$BITBUCKET_REPOSITORY" ]; then echo "Setting BITBUCKET_REPOSITORY to $CI_PROJECT_NAME" + BITBUCKET_REPOSITORY=$CI_PROJECT_NAME + fi BITBUCKET_API_ROOT="https://api.bitbucket.org/2.0" + BITBUCKET_STATUS_API="$BITBUCKET_API_ROOT/repositories/$BITBUCKET_NAMESPACE/$BITBUCKET_REPOSITORY/commit/$CI_COMMIT_SHA/statuses/build" + BITBUCKET_KEY="ci/gitlab-ci/$CI_JOB_NAME" + + case "$BUILD_STATUS" in running) + BITBUCKET_STATE="INPROGRESS" + BITBUCKET_DESCRIPTION="The build is running!" + ;; + passed) + BITBUCKET_STATE="SUCCESSFUL" + BITBUCKET_DESCRIPTION="The build passed!" + ;; + failed) + BITBUCKET_STATE="FAILED" + BITBUCKET_DESCRIPTION="The build failed." + ;; + esac + + echo "Pushing status to $BITBUCKET_STATUS_API..." + curl --request POST $BITBUCKET_STATUS_API \ + --user $BITBUCKET_USERNAME:$BITBUCKET_ACCESS_TOKEN \ + --header "Content-Type:application/json" \ + --silent \ + --data "{ \"state\": \"$BITBUCKET_STATE\", \"key\": \"$BITBUCKET_KEY\", \"description\": \"$BITBUCKET_DESCRIPTION\",\"url\": \"$CI_PROJECT_URL/-/jobs/$CI_JOB_ID\" }" + ``` + +7. 仍在 Bitbucket 中,创建一个`.gitlab-ci.yml`文件以使用该脚本将管道成功与失败推送到 Bitbucket. + + ``` + stages: + - test + - ci_status + + unit-tests: + script: + - echo "Success. Add your tests!" + + success: + stage: ci_status + before_script: + - "" + after_script: + - "" + script: + - BUILD_STATUS=passed BUILD_KEY=push ./build_status + when: on_success + + failure: + stage: ci_status + before_script: + - "" + after_script: + - "" + script: + - BUILD_STATUS=failed BUILD_KEY=push ./build_status + when: on_failure + ``` + +现在已将 GitLab 配置为从 Bitbucket 镜像更改,运行在`.gitlab-ci.yml`配置的 CI / CD 管道,并将状态推送到 Bitbucket. \ No newline at end of file diff --git a/docs/243.md b/docs/243.md new file mode 100644 index 0000000000000000000000000000000000000000..ac3d52db88deadc18aa76c4d83759fb85ffcb80e --- /dev/null +++ b/docs/243.md @@ -0,0 +1,71 @@ +# Using GitLab CI/CD with a GitHub repository + +> 原文:[https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/github_integration.html](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/github_integration.html) + +* [Connect with Personal Access Token](#connect-with-personal-access-token) +* [Connect manually](#connect-manually) + +# Using GitLab CI/CD with a GitHub repository[](#using-gitlab-cicd-with-a-github-repository-premium "Permalink") + +通过创建[CI / CD 项目](index.html)将 GitHub 存储库连接到 GitLab,GitLab CI / CD 可与**GitHub.com**和**GitHub Enterprise**一起使用. + +观看有关在[GitHub 存储库中使用 GitLab CI / CD 管道](https://www.youtube.com/watch?v=qgl3F2j-1cI)的视频. + +**注意:**由于[GitHub 的限制](https://gitlab.com/gitlab-org/gitlab/-/issues/9147) ,不能将[GitHub OAuth](../../integration/github.html#enabling-github-oauth)用于作为外部 CI / CD 存储库的 GitHub 进行身份验证. + +## Connect with Personal Access Token[](#connect-with-personal-access-token "Permalink") + +**注意:**个人访问令牌只能用于将 GitHub.com 存储库连接到 GitLab,并且 GitHub 用户必须具有[owner 角色](https://help.github.com/en/github/getting-started-with-github/access-permissions-on-github) . + +要通过 GitHub 一次性授权以授予 GitLab 访问您的存储库的权限,请执行以下操作: + +1. 打开[https://github.com/settings/tokens/new](https://github.com/settings/tokens/new)来创建**个人访问令牌** . 该令牌将用于访问您的存储库并将提交状态推送到 GitHub. + + 应该启用`repo`和`admin:repo_hook`以允许 GitLab 访问您的项目,更新提交状态并创建 Web 挂钩以将新提交通知 GitLab. + +2. 在 GitLab 中,转到[新项目页面](../../gitlab-basics/create-project.html#create-a-project-in-gitlab) ,选择**CI / CD 作为外部仓库**选项卡,然后单击**GitHub** . + +3. 将令牌粘贴到" **个人访问令牌"**字段中,然后单击" **列出存储库"** . 单击" **连接"**以选择存储库. + +4. 在 GitHub 中,添加`.gitlab-ci.yml`以[配置 GitLab CI / CD](../quick_start/README.html) . + +GitLab 将: + +1. 导入项目. +2. Enable [Pull Mirroring](../../user/project/repository/repository_mirroring.html#pulling-from-a-remote-repository-starter) +3. Enable [GitHub project integration](../../user/project/integrations/github.html) +4. 在 GitHub 上创建一个 Web 挂钩,以通知 GitLab 新提交. + +## Connect manually[](#connect-manually "Permalink") + +**注意:**要将**GitHub Enterprise**与**GitLab.com 一起**使用,请使用此方法. + +要为您的存储库手动启用 GitLab CI / CD: + +1. 在 GitHub 中打开[https://github.com/settings/tokens/new](https://github.com/settings/tokens/new)创建**个人访问令牌.** GitLab 将使用此令牌访问您的存储库并推送提交状态. + + 输入**令牌描述**并更新范围以允许: + + `repo`以便 GitLab 可以访问您的项目并更新提交状态 + +2. 在 GitLab 中,使用 Git URL 选项和 GitHub 存储库的 HTTPS URL 创建一个**CI / CD 项目** . 如果您的项目是私人项目,请使用您刚创建的个人访问令牌进行身份验证. + + GitLab 将自动配置基于轮询的拉镜像. + +3. 仍在 GitLab 中,从**"设置">"集成"**启用[GitHub 项目](../../user/project/integrations/github.html) **集成.** + + 选中" **活动"**复选框以启用集成,将您的个人访问令牌和 HTTPS 存储库 URL 粘贴到表单中,然后**保存.** + +4. 仍在 GitLab 中,创建具有`API`范围的**个人访问令牌** ,以验证 GitHub Web 挂钩,以通知 GitLab 新提交. + +5. 在 GitHub 中的**"设置">" Webhooks"中**创建一个 Web 挂钩,以通知 GitLab 新提交. + + 应使用我们刚刚创建的 GitLab 个人访问令牌,将 Web 挂钩 URL 设置为 GitLab API 来[触发拉镜像](../../api/projects.html#start-the-pull-mirroring-process-for-a-project-starter) : + + ``` + https://gitlab.com/api/v4/projects/<NAMESPACE>%2F<PROJECT>/mirror/pull?private_token=<PERSONAL_ACCESS_TOKEN> + ``` + + 选择" **让我选择单个事件"**选项,然后选中" **拉**取**请求**和**推送"**复选框. [对于外部拉取请求的管道,](index.html#pipelines-for-external-pull-requests)需要这些设置. + +6. 在 GitHub 中添加`.gitlab-ci.yml`以配置 GitLab CI / CD. \ No newline at end of file diff --git a/docs/244.md b/docs/244.md new file mode 100644 index 0000000000000000000000000000000000000000..170ce5f9ce13f639981b251a1c10bd933d3e849f --- /dev/null +++ b/docs/244.md @@ -0,0 +1,101 @@ +# GitLab Pages + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/](https://docs.gitlab.com/ee/user/project/pages/) + +* [Getting started](#getting-started) +* [How it works](#how-it-works) +* [Access to your Pages site](#access-to-your-pages-site) +* [Pages examples](#pages-examples) +* [Administer GitLab Pages for self-managed instances](#administer-gitlab-pages-for-self-managed-instances) + +# GitLab Pages[](#gitlab-pages "Permalink") + +版本历史 + +* 在 GitLab 企业版 8.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80) . +* GitLab 企业版 8.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173)了具有 TLS 支持的自定义 CNAME. +* [移植](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14605)到 GitLab 8.17 中的 GitLab 社区版. +* 在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30548)了对子组项目网站的支持. +* 捆绑的项目模板在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47857) . + +借助 GitLab 页面,您可以直接从 GitLab 中的存储库发布静态网站. + +* 用于任何个人或企业网站. +* 使用任何静态站点生成器(SSG)或纯 HTML. +* 为您的项目,组或用户帐户创建网站. +* 免费在自己的 GitLab 实例或 GitLab.com 上托管您的网站. +* 连接您的自定义域和 TLS 证书. +* 将任何许可归于您的内容. + +![Examples of SSGs supported by Pages](img/50ffc4ae0babeef44a73e82cfe49bb30.png) + +要发布包含 Pages 的网站,您可以使用任何 SSG,例如 Gatsby,Jekyll,Hugo,Middleman,Harp,Hexo 和 Brunch 等. 您还可以发布直接用纯 HTML,CSS 和 JavaScript 编写的任何网站. + +网页**不**支持动态服务器端的处理,例如,作为`.php`和`.asp`需要. 了解更多有关[静态网站和动态网站的信息](https://about.gitlab.com/blog/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) . + +## Getting started[](#getting-started "Permalink") + +要创建一个 GitLab Pages 网站: + +| Document | Description | +| --- | --- | +| [Fork a sample project](getting_started/pages_forked_sample_project.html) | 通过分叉示例项目,使用已配置的 Pages 创建一个新项目. | +| [Use a new project template](getting_started/pages_new_project_template.html) | 使用已经使用新项目模板配置的 Pages 创建一个新项目. | +| [Use a `.gitlab-ci.yml` template](getting_started/pages_ci_cd_template.html) | 将 Pages 网站添加到现有项目. 使用预填充的 CI 模板文件. | +| [Create a `gitlab-ci.yml` file from scratch](getting_started/pages_from_scratch.html) | 将 Pages 网站添加到现有项目. 了解如何创建和配置自己的 CI 文件. | + +要更新 GitLab Pages 网站: + +| Document | Description | +| --- | --- | +| [GitLab Pages domain names, URLs, and base URLs](getting_started_part_one.html) | 了解有关 GitLab Pages 默认域的信息. | +| [Explore GitLab Pages](introduction.html) | 要求,技术方面,特定的 GitLab CI / CD 配置选项,访问控制,自定义 404 页面,限制,常见问题解答. | +| [Custom domains and SSL/TLS Certificates](custom_domains_ssl_tls_certification/index.html) | 自定义域和子域,DNS 记录和 SSL / TLS 证书. | +| [Let’s Encrypt integration](custom_domains_ssl_tls_certification/lets_encrypt_integration.html) | 使用 Let's Encrypt 证书保护您的 Pages 网站,该证书由 GitLab 自动获取并更新. | +| [CloudFlare certificates](https://about.gitlab.com/blog/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) | 使用 CloudFlare 证书保护您的 Pages 网站. | + +了解更多信息并查看示例: + +| Document | Description | +| --- | --- | +| [Static vs dynamic websites](https://about.gitlab.com/blog/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) | 静态与动态网站概述. | +| [Modern static site generators](https://about.gitlab.com/blog/2016/06/10/ssg-overview-gitlab-pages-part-2/) | SSG 概述. | +| [Build any SSG site with GitLab Pages](https://about.gitlab.com/blog/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/) | 对 GitLab 页面使用 SSG. | + +## How it works[](#how-it-works "Permalink") + +要使用 GitLab 页面,您必须在 GitLab 中创建一个项目以将您网站的文件上传到该项目. 这些项目可以是公共的,内部的或私人的. + +GitLab 始终从资源库中一个非常特定的文件夹`public`部署您的网站. 在 GitLab 中创建新项目时, [存储库](../repository/index.html)将自动可用. + +为了部署您的站点,GitLab 使用其内置工具[GitLab CI / CD](../../../ci/README.html)来构建您的站点并将其发布到 GitLab Pages 服务器. GitLab CI / CD 运行以完成此任务的脚本序列是从名为`.gitlab-ci.yml`的文件中[创建的](getting_started/pages_from_scratch.html) ,您可以随意[创建和修改](getting_started/pages_from_scratch.html) . 配置文件中称为`pages`的特定`job`会使 GitLab 知道您正在部署 GitLab Pages 网站. + +您可以将 GitLab 的[默认域用于](getting_started_part_one.html#gitlab-pages-default-domain-names) `*.gitlab.io` [GitLab Pages 网站](getting_started_part_one.html#gitlab-pages-default-domain-names) `*.gitlab.io` ,也可以使用自己的域( `example.com` ). 在这种情况下,您需要对您域的注册商(或控制面板)具有管理员权限,才能使用 Pages 对其进行设置. + +下图显示了开始使用 Pages 可能需要遵循的工作流程. + +![New projects for GitLab Pages](img/8db9ef3ba0d1153ab46b990e98372677.png) + +## Access to your Pages site[](#access-to-your-pages-site "Permalink") + +如果您使用的是 GitLab Pages 默认域( `.gitlab.io` ),则您的网站将自动安全并在 HTTPS 下可用. 如果您使用自己的自定义域,则可以选择使用 SSL / TLS 证书对其进行保护. + +If you’re using GitLab.com, your website will be publicly available to the internet. To restrict access to your website, enable [GitLab Pages Access Control](pages_access_control.html). + +如果您使用的是自我管理的实例(Core,Starter,Premium 或 Ultimate),则根据 sysadmin 选择的[Pages admin 设置](../../../administration/pages/index.html) ,您的网站将发布在您自己的服务器上,管理员可以将其设置为公开或内部. + +## Pages examples[](#pages-examples "Permalink") + +有一些因特定原因而建立的 GitLab Pages 网站的出色示例. 这些示例可以教您使用高级技术并适应您自己的需求: + +* [Posting to your GitLab Pages blog from iOS](https://about.gitlab.com/blog/2016/08/19/posting-to-your-gitlab-pages-blog-from-ios/). +* [GitLab CI: Run jobs sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/). +* [GitLab CI: Deployment & environments](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/). +* [Building a new GitLab docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/blog/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/). +* [Publish code coverage reports with GitLab Pages](https://about.gitlab.com/blog/2016/11/03/publish-code-coverage-report-with-gitlab-pages/). + +## Administer GitLab Pages for self-managed instances[](#administer-gitlab-pages-for-self-managed-instances "Permalink") + +如果您正在运行 GitLab 的自我管理实例(GitLab 社区版和企业版),请[按照管理步骤](../../../administration/pages/index.html)来配置页面. + +观看有关如何开始使用 GitLab 页面管理的[视频教程](https://www.youtube.com/watch?v=dD8c7WNcc6s) . \ No newline at end of file diff --git a/docs/245.md b/docs/245.md new file mode 100644 index 0000000000000000000000000000000000000000..23d47103ba183b0ca5c459527ab374e60067f567 --- /dev/null +++ b/docs/245.md @@ -0,0 +1,101 @@ +# GitLab Pages + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/#getting-started](https://docs.gitlab.com/ee/user/project/pages/#getting-started) + +* [Getting started](#getting-started) +* [How it works](#how-it-works) +* [Access to your Pages site](#access-to-your-pages-site) +* [Pages examples](#pages-examples) +* [Administer GitLab Pages for self-managed instances](#administer-gitlab-pages-for-self-managed-instances) + +# GitLab Pages[](#gitlab-pages "Permalink") + +版本历史 + +* 在 GitLab 企业版 8.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80) . +* GitLab 企业版 8.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173)了具有 TLS 支持的自定义 CNAME. +* [移植](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14605)到 GitLab 8.17 中的 GitLab 社区版. +* 在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30548)了对子组项目网站的支持. +* 捆绑的项目模板在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47857) . + +借助 GitLab 页面,您可以直接从 GitLab 中的存储库发布静态网站. + +* 用于任何个人或企业网站. +* 使用任何静态站点生成器(SSG)或纯 HTML. +* 为您的项目,组或用户帐户创建网站. +* 免费在自己的 GitLab 实例或 GitLab.com 上托管您的网站. +* 连接您的自定义域和 TLS 证书. +* 将任何许可归于您的内容. + +![Examples of SSGs supported by Pages](img/50ffc4ae0babeef44a73e82cfe49bb30.png) + +要发布包含 Pages 的网站,您可以使用任何 SSG,例如 Gatsby,Jekyll,Hugo,Middleman,Harp,Hexo 和 Brunch 等. 您还可以发布直接用纯 HTML,CSS 和 JavaScript 编写的任何网站. + +网页**不**支持动态服务器端的处理,例如,作为`.php`和`.asp`需要. 了解更多有关[静态网站和动态网站的信息](https://about.gitlab.com/blog/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) . + +## Getting started[](#getting-started "Permalink") + +要创建一个 GitLab Pages 网站: + +| Document | Description | +| --- | --- | +| [Fork a sample project](getting_started/pages_forked_sample_project.html) | 通过分叉示例项目,使用已配置的 Pages 创建一个新项目. | +| [Use a new project template](getting_started/pages_new_project_template.html) | 使用已经使用新项目模板配置的 Pages 创建一个新项目. | +| [Use a `.gitlab-ci.yml` template](getting_started/pages_ci_cd_template.html) | 将 Pages 网站添加到现有项目. 使用预填充的 CI 模板文件. | +| [Create a `gitlab-ci.yml` file from scratch](getting_started/pages_from_scratch.html) | 将 Pages 网站添加到现有项目. 了解如何创建和配置自己的 CI 文件. | + +要更新 GitLab Pages 网站: + +| Document | Description | +| --- | --- | +| [GitLab Pages domain names, URLs, and base URLs](getting_started_part_one.html) | 了解有关 GitLab Pages 默认域的信息. | +| [Explore GitLab Pages](introduction.html) | 要求,技术方面,特定的 GitLab CI / CD 配置选项,访问控制,自定义 404 页面,限制,常见问题解答. | +| [Custom domains and SSL/TLS Certificates](custom_domains_ssl_tls_certification/index.html) | 自定义域和子域,DNS 记录和 SSL / TLS 证书. | +| [Let’s Encrypt integration](custom_domains_ssl_tls_certification/lets_encrypt_integration.html) | 使用 Let's Encrypt 证书保护您的 Pages 网站,该证书由 GitLab 自动获取并更新. | +| [CloudFlare certificates](https://about.gitlab.com/blog/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) | 使用 CloudFlare 证书保护您的 Pages 网站. | + +了解更多信息并查看示例: + +| Document | Description | +| --- | --- | +| [Static vs dynamic websites](https://about.gitlab.com/blog/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) | 静态与动态网站概述. | +| [Modern static site generators](https://about.gitlab.com/blog/2016/06/10/ssg-overview-gitlab-pages-part-2/) | SSG 概述. | +| [Build any SSG site with GitLab Pages](https://about.gitlab.com/blog/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/) | 对 GitLab 页面使用 SSG. | + +## How it works[](#how-it-works "Permalink") + +要使用 GitLab 页面,您必须在 GitLab 中创建一个项目以将您网站的文件上传到该项目. 这些项目可以是公共的,内部的或私人的. + +GitLab 始终从资源库中一个非常特定的文件夹`public`部署您的网站. 在 GitLab 中创建新项目时, [存储库](../repository/index.html)将自动可用. + +为了部署您的站点,GitLab 使用其内置工具[GitLab CI / CD](../../../ci/README.html)来构建您的站点并将其发布到 GitLab Pages 服务器. GitLab CI / CD 运行以完成此任务的脚本序列是从名为`.gitlab-ci.yml`的文件中[创建的](getting_started/pages_from_scratch.html) ,您可以随意[创建和修改](getting_started/pages_from_scratch.html) . 配置文件中称为`pages`的特定`job`会使 GitLab 知道您正在部署 GitLab Pages 网站. + +您可以将 GitLab 的[默认域用于](getting_started_part_one.html#gitlab-pages-default-domain-names) `*.gitlab.io` [GitLab Pages 网站](getting_started_part_one.html#gitlab-pages-default-domain-names) `*.gitlab.io` ,也可以使用自己的域( `example.com` ). 在这种情况下,您需要对您域的注册商(或控制面板)具有管理员权限,才能使用 Pages 对其进行设置. + +下图显示了开始使用 Pages 可能需要遵循的工作流程. + +![New projects for GitLab Pages](img/8db9ef3ba0d1153ab46b990e98372677.png) + +## Access to your Pages site[](#access-to-your-pages-site "Permalink") + +如果您使用的是 GitLab Pages 默认域( `.gitlab.io` ),则您的网站将自动安全并在 HTTPS 下可用. 如果您使用自己的自定义域,则可以选择使用 SSL / TLS 证书对其进行保护. + +If you’re using GitLab.com, your website will be publicly available to the internet. To restrict access to your website, enable [GitLab Pages Access Control](pages_access_control.html). + +如果您使用的是自我管理的实例(Core,Starter,Premium 或 Ultimate),则根据 sysadmin 选择的[Pages admin 设置](../../../administration/pages/index.html) ,您的网站将发布在您自己的服务器上,管理员可以将其设置为公开或内部. + +## Pages examples[](#pages-examples "Permalink") + +有一些因特定原因而建立的 GitLab Pages 网站的出色示例. 这些示例可以教您使用高级技术并适应您自己的需求: + +* [Posting to your GitLab Pages blog from iOS](https://about.gitlab.com/blog/2016/08/19/posting-to-your-gitlab-pages-blog-from-ios/). +* [GitLab CI: Run jobs sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/). +* [GitLab CI: Deployment & environments](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/). +* [Building a new GitLab docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/blog/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/). +* [Publish code coverage reports with GitLab Pages](https://about.gitlab.com/blog/2016/11/03/publish-code-coverage-report-with-gitlab-pages/). + +## Administer GitLab Pages for self-managed instances[](#administer-gitlab-pages-for-self-managed-instances "Permalink") + +如果您正在运行 GitLab 的自我管理实例(GitLab 社区版和企业版),请[按照管理步骤](../../../administration/pages/index.html)来配置页面. + +观看有关如何开始使用 GitLab 页面管理的[视频教程](https://www.youtube.com/watch?v=dD8c7WNcc6s) . \ No newline at end of file diff --git a/docs/246.md b/docs/246.md new file mode 100644 index 0000000000000000000000000000000000000000..413c705f0389238faac70db80eccc60c169c4e28 --- /dev/null +++ b/docs/246.md @@ -0,0 +1,68 @@ +# GitLab Pages domain names, URLs, and baseurls + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/getting_started_part_one.html](https://docs.gitlab.com/ee/user/project/pages/getting_started_part_one.html) + +* [GitLab Pages default domain names](#gitlab-pages-default-domain-names) + * [Project website examples](#project-website-examples) + * [User and Group website examples](#user-and-group-website-examples) +* [URLs and baseurls](#urls-and-baseurls) +* [Custom domains](#custom-domains) + +# GitLab Pages domain names, URLs, and baseurls[](#gitlab-pages-domain-names-urls-and-baseurls "Permalink") + +在本文档中,了解如何根据所需网站的 URL 为 GitLab Pages 命名项目. + +## GitLab Pages default domain names[](#gitlab-pages-default-domain-names "Permalink") + +> **注意:**如果您使用自己的 GitLab 实例通过 GitLab Pages 部署站点,请与 sysadmin 一起检查什么是 Pages 通配符域. 本指南适用于任何 GitLab 实例,您只需要用自己的实例替换 GitLab.com( `*.gitlab.io` )上的 Pages 通配符域. + +如果您在 GitLab 上设置了 GitLab Pages 项目,则可以在`namespace.example.io`的子域下自动访问它. [`namespace`](../../group/index.html#namespaces)由您在 GitLab.com 上的用户名或在其下创建此项目的组名定义. 对于 GitLab 自我管理的实例,将`example.io`替换为实例的 Pages 域. 对于 GitLab.com,页面域为`*.gitlab.io` . + +| GitLab 页面的类型 | The name of the project created in GitLab | 网址 | +| --- | --- | --- | +| 用户页面 | `username.example.io` | `http(s)://username.example.io` | +| 组页面 | `groupname.example.io` | `http(s)://groupname.example.io` | +| 用户拥有的项目页面 | `projectname` | `http(s)://username.example.io/projectname` | +| 小组拥有的项目页面 | `projectname` | `http(s)://groupname.example.io/projectname` | +| 子组拥有的项目页面 | `subgroup/projectname` | `http(s)://groupname.example.io/subgroup/projectname` | + +**警告:**关于在通用域名和 HTTPS 下提供的名称空间存在一些已知[限制](introduction.html#limitations) . 确保阅读该部分. + +要清楚地了解 Pages 域,请阅读以下示例. + +### Project website examples[](#project-website-examples "Permalink") + +* 您在用户名`john`下创建了一个名为`blog`的项目,因此您的项目 URL 为`https://gitlab.com/john/blog/` . 为该项目启用 GitLab Pages 并构建您的网站后,即可在`https://john.gitlab.io/blog/`下找到该网站. +* 您为所有网站创建了一个组,称为`websites` ,该组中的一个项目称为`blog` . 您的项目 URL 为`https://gitlab.com/websites/blog/` . 为该项目启用 GitLab 页面后,该站点将位于`https://websites.gitlab.io/blog/`下. +* 您为工程部门创建了一个名为`engineering`的组,为所有文档网站创建了一个名为`docs`的子组,该子组中的一个项目称为`workflows` . 您的项目网址为`https://gitlab.com/engineering/docs/workflows/` . 为该项目启用 GitLab 页面后,该站点将位于`https://engineering.gitlab.io/docs/workflows`下. + +### User and Group website examples[](#user-and-group-website-examples "Permalink") + +* 在您的用户名`john` ,您创建了一个名为`john.gitlab.io`的项目. 您的项目 URL 将为`https://gitlab.com/john/john.gitlab.io` . 为项目启用 GitLab Pages 后,您的网站将发布在`https://john.gitlab.io`下. +* 在小组`websites` ,您创建了一个名为`websites.gitlab.io`的项目. 您项目的 URL 将为`https://gitlab.com/websites/websites.gitlab.io` . 为项目启用 GitLab Pages 后,您的网站将发布在`https://websites.gitlab.io`下. + +**一般示例:** + +* 在 GitLab.com 上,项目站点将始终在`https://namespace.gitlab.io/project-name`下可用 +* 在 GitLab.com 上,将在`https://namespace.gitlab.io/`下提供用户或组网站. +* 在您的 GitLab 实例上,将上述`gitlab.io`替换为 Pages 服务器域. 向您的系统管理员询问此信息. + +## URLs and baseurls[](#urls-and-baseurls "Permalink") + +每个静态网站发生器(SSG)的默认配置期望找到您的网站下一个(子)域( `example.com` ),而不是在该领域(的子目录`example.com/subdir` ). 因此,每当发布项目网站( `namespace.gitlab.io/project-name` )时,都必须在 SSG 文档中查找此配置(基本 URL)并进行设置以反映此模式. + +例如,对于 Jekyll 站点, `baseurl`是在 Jekyll 配置文件`_config.yml`定义的. 如果您的网站 URL 是`https://john.gitlab.io/blog/` ,则需要将此行添加到`_config.yml` : + +``` +baseurl: "/blog" +``` + +相反,如果您在派生我们的[默认示例](https://gitlab.com/pages)之一后部署网站,则已经以这种方式配置了 baseurl,因为所有示例都包含项目网站. 如果您决定将自己的网站设为用户或网上论坛,则必须从项目中删除此配置. 对于我们刚刚提到的 Jekyll 示例,您必须将 Jekyll 的`_config.yml`更改为: + +``` +baseurl: "" +``` + +## Custom domains[](#custom-domains "Permalink") + +GitLab 页面支持通过 HTTP 或 HTTPS 提供服务的自定义域和子域. 有关更多信息,请参见[GitLab Pages 自定义域和 SSL / TLS 证书](custom_domains_ssl_tls_certification/index.html) . \ No newline at end of file diff --git a/docs/247.md b/docs/247.md new file mode 100644 index 0000000000000000000000000000000000000000..75738768515df4883cace3f596b4b30369b44cb5 --- /dev/null +++ b/docs/247.md @@ -0,0 +1,362 @@ +# Create a GitLab Pages website from scratch + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/getting_started/pages_from_scratch.html](https://docs.gitlab.com/ee/user/project/pages/getting_started/pages_from_scratch.html) + +* [Prerequisites](#prerequisites) +* [Choose a Docker image](#choose-a-docker-image) +* [Install Jekyll](#install-jekyll) +* [Specify the `public` directory for output](#specify-the-public-directory-for-output) +* [Specify the `public` directory for artifacts](#specify-the-public-directory-for-artifacts) +* [Deploy specific branches to a Pages site](#deploy-specific-branches-to-a-pages-site) +* [Specify a stage to deploy](#specify-a-stage-to-deploy) +* [Remove duplicate commands](#remove-duplicate-commands) +* [Build faster with cached dependencies](#build-faster-with-cached-dependencies) +* [Related topics](#related-topics) + +# Create a GitLab Pages website from scratch[](#create-a-gitlab-pages-website-from-scratch "Permalink") + +本教程向您展示如何从头开始创建 Pages 站点. 您将从一个空白项目开始,并创建自己的 CI 文件,该文件向[GitLab Runner](https://docs.gitlab.com/runner/)提供指导. 当您的 CI / CD [管道](../../../../ci/pipelines/index.html)运行时,将创建 Pages 站点. + +本示例使用[Jekyll](https://jekyllrb.com/)静态站点生成器(SSG). 其他 SSG 遵循类似的步骤. 您无需熟悉 Jekyll 或 SSG 即可完成本教程. + +## Prerequisites[](#prerequisites "Permalink") + +要继续执行本示例,请从 GitLab 中的空白项目开始. 在根(顶级)目录中创建三个文件. + +* `.gitlab-ci.yml`一个 YAML 文件,其中包含要运行的命令. 现在,将文件内容保留为空白. + +* `index.html`您可以使用所需的 HTML 内容填充 HTML 文件,例如: + + ``` + <html> + <head> + <title>Home + + +

      Hello World!

      + + + ``` + +* [`Gemfile`](https://bundler.io/gemfile.html)一个描述 Ruby 程序依赖性的文件. 用以下内容填充它: + + ``` + source "https://rubygems.org" + + gem "jekyll" + ``` + +## Choose a Docker image[](#choose-a-docker-image "Permalink") + +In this example, the Runner uses a [Docker image](../../../../ci/docker/using_docker_images.html) to run scripts and deploy the site. + +这个特定的 Ruby 映像在[DockerHub](https://hub.docker.com/_/ruby)上[维护](https://hub.docker.com/_/ruby) . + +编辑您的`.gitlab-ci.yml`并将此文本添加为​​第一行. + +``` +image: ruby:2.7 +``` + +如果您的 SSG 需要构建[NodeJS](https://s0nodejs0org.icopy.site/) ,则必须指定一个包含 NodeJS 的映像作为其文件系统的一部分. 例如,对于[Hexo](https://gitlab.com/pages/hexo)网站,可以使用`image: node:12.17.0` . + +## Install Jekyll[](#install-jekyll "Permalink") + +要在本地运行[Jekyll](https://jekyllrb.com/) ,您需要打开终端并执行以下操作: + +* 通过运行`gem install bundler`安装[Bundler](https://bundler.io/) . +* 通过运行`bundle install`创建`Gemfile.lock` . +* 通过运行`bundle exec jekyll build`安装 Jekyll. + +在`.gitlab-ci.yml`文件中,其写为​​: + +``` +script: + - gem install bundler + - bundle install + - bundle exec jekyll build +``` + +此外,在`.gitlab-ci.yml`文件中,每个`script`均由`job`组织. `job`包括您要应用于该特定任务的脚本和设置. + +``` +job: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build +``` + +对于 GitLab Pages,此`job`有一个特定的名称,称为`pages` . 此设置告诉 Runner 您希望工作通过 GitLab Pages 部署您的网站: + +``` +pages: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build +``` + +## Specify the `public` directory for output[](#specify-the-public-directory-for-output "Permalink") + +Jekyll 需要知道在何处生成其输出. GitLab Pages 仅考虑名为`public`的目录中的文件. + +Jekyll 使用目标( `-d` )为构建的网站指定输出目录: + +``` +pages: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public +``` + +## Specify the `public` directory for artifacts[](#specify-the-public-directory-for-artifacts "Permalink") + +既然 Jekyll 已将文件输出到`public`目录,则 Runner 需要知道从何处获取文件. 工件存储在`public`目录中: + +``` +pages: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public +``` + +将其粘贴到`.gitlab-ci.yml`文件中,因此现在看起来像这样: + +``` +image: ruby:2.7 + +pages: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public +``` + +现在保存并提交`.gitlab-ci.yml`文件. 您可以转到**CI / CD>管道**来观看管道运行. + +成功后,请转到**"设置">"页面"**以查看您的网站现在可用的 URL. + +如果您想执行更多高级任务,则可以使用[任何可用设置](../../../../ci/yaml/README.html)更新`.gitlab-ci.yml`文件. 您可以使用[GitLab CI / CD Lint Tool](../../../../ci/yaml/README.html#validate-the-gitlab-ciyml)来检查 CI 语法. + +以下主题显示了可以添加到 CI / CD 文件中的其他选项的其他示例. + +## Deploy specific branches to a Pages site[](#deploy-specific-branches-to-a-pages-site "Permalink") + +您可能只想从特定分支部署到 Pages 站点. + +首先,添加`workflow`部分以强制管道仅在将更改推送到分支时才运行: + +``` +image: ruby:2.7 + +workflow: + rules: + - if: '$CI_COMMIT_BRANCH' + +pages: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public +``` + +然后将管道配置为仅运行 master 分支的作业. + +``` +image: ruby:2.7 + +workflow: + rules: + - if: '$CI_COMMIT_BRANCH' + +pages: + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public + rules: + - if: '$CI_COMMIT_BRANCH == "master"' +``` + +## Specify a stage to deploy[](#specify-a-stage-to-deploy "Permalink") + +GitLab CI / CD 有三个默认阶段:构建,测试和部署. + +如果要测试脚本并在部署到生产环境之前检查构建的站点,则可以完全按按`master`来运行测试. + +要为您的作业指定一个阶段,请在您的 CI 文件中添加一个`stage`行: + +``` +image: ruby:2.7 + +workflow: + rules: + - if: '$CI_COMMIT_BRANCH' + +pages: + stage: deploy + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public + rules: + - if: '$CI_COMMIT_BRANCH == "master"' +``` + +现在,将另一个作业添加到 CI 文件,告诉它测试**除** `master`分支**以外**的每个分支上的每次推送: + +``` +image: ruby:2.7 + +workflow: + rules: + - if: '$CI_COMMIT_BRANCH' + +pages: + stage: deploy + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public + rules: + - if: '$CI_COMMIT_BRANCH == "master"' + +test: + stage: test + script: + - gem install bundler + - bundle install + - bundle exec jekyll build -d test + artifacts: + paths: + - test + rules: + - if: '$CI_COMMIT_BRANCH != "master"' +``` + +当`test`作业在`test`阶段运行时,Jekyll 在名为`test`的目录中构建站点. 该工作影响除`master`之外的所有分支. + +将阶段应用于不同的作业时,同一阶段中的每个作业都是并行构建的. 如果您的 Web 应用程序在部署之前需要多个测试,则可以同时运行所有测试. + +## Remove duplicate commands[](#remove-duplicate-commands "Permalink") + +为了避免在每个作业中重复相同的脚本,可以将它们添加到`before_script`部分. + +在示例中, `gem install bundler`和`bundle install`对于作业, `pages`和`test`都在运行. + +将这些命令移至`before_script`部分: + +``` +image: ruby:2.7 + +workflow: + rules: + - if: '$CI_COMMIT_BRANCH' + +before_script: + - gem install bundler + - bundle install + +pages: + stage: deploy + script: + - bundle exec jekyll build -d public + artifacts: + paths: + - public + rules: + - if: '$CI_COMMIT_BRANCH == "master"' + +test: + stage: test + script: + - bundle exec jekyll build -d test + artifacts: + paths: + - test + rules: + - if: '$CI_COMMIT_BRANCH != "master"' +``` + +## Build faster with cached dependencies[](#build-faster-with-cached-dependencies "Permalink") + +为了加快构建速度,您可以使用`cache`参数为项目的依赖项缓存安装文件. + +此示例在运行`bundle install`时将 Jekyll 依赖项缓存在`vendor`目录中: + +``` +image: ruby:2.7 + +workflow: + rules: + - if: '$CI_COMMIT_BRANCH' + +cache: + paths: + - vendor/ + +before_script: + - gem install bundler + - bundle install --path vendor + +pages: + stage: deploy + script: + - bundle exec jekyll build -d public + artifacts: + paths: + - public + rules: + - if: '$CI_COMMIT_BRANCH == "master"' + +test: + stage: test + script: + - bundle exec jekyll build -d test + artifacts: + paths: + - test + rules: + - if: '$CI_COMMIT_BRANCH != "master"' +``` + +在这种情况下,您需要从 Jekyll 构建的文件夹列表中排除`/vendor`目录. 否则,Jekyll 将尝试与站点一起构建目录内容. + +在根目录中,创建一个名为`_config.yml`的文件并添加以下内容: + +``` +exclude: + - vendor +``` + +现在,GitLab CI / CD 不仅可以构建网站,还可以通过对功能分支的**连续测试**进行推送, **缓存**与 Bundler 一起安装的依赖项,并将每次推送**持续部署**到`master`分支. + +## Related topics[](#related-topics "Permalink") + +有关更多信息,请参见以下博客文章. + +* [Use GitLab CI/CD `environments` to deploy your web app to staging and production](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/). +* Learn [how to run jobs sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/). +* 了解[如何从不同项目中提取特定目录](https://about.gitlab.com/blog/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/)以部署此网站[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site) . +* Learn [how to use GitLab Pages to produce a code coverage report](https://about.gitlab.com/blog/2016/11/03/publish-code-coverage-report-with-gitlab-pages/). \ No newline at end of file diff --git a/docs/248.md b/docs/248.md new file mode 100644 index 0000000000000000000000000000000000000000..a4a095d9decb9d81aa4ba5371190956e3ca2b638 --- /dev/null +++ b/docs/248.md @@ -0,0 +1,236 @@ +# Custom domains and SSL/TLS Certificates + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/) + +* [Set up Pages with a custom domain](#set-up-pages-with-a-custom-domain) + * [Requirements](#requirements) + * [Steps](#steps) + * [1\. Add a custom domain to Pages](#1-add-a-custom-domain-to-pages) + * [2\. Get the verification code](#2-get-the-verification-code) + * [3\. Set up DNS records for Pages](#3-set-up-dns-records-for-pages) + * [For root domains](#for-root-domains) + * [For subdomains](#for-subdomains) + * [For both root and subdomains](#for-both-root-and-subdomains) + * [4\. Verify the domain’s ownership](#4-verify-the-domains-ownership) + * [Troubleshooting Pages domain verification](#troubleshooting-pages-domain-verification) + * [Adding more domain aliases](#adding-more-domain-aliases) + * [Redirecting `www.domain.com` to `domain.com` with Cloudflare](#redirecting-wwwdomaincom-to-domaincom-with-cloudflare) +* [Adding an SSL/TLS certificate to Pages](#adding-an-ssltls-certificate-to-pages) + * [Requirements](#requirements-1) + * [Steps](#steps-1) +* [Force HTTPS for GitLab Pages websites](#force-https-for-gitlab-pages-websites) + +# Custom domains and SSL/TLS Certificates[](#custom-domains-and-ssltls-certificates "Permalink") + +使用自定义域设置 GitLab 页面,并向其中添加 SSL / TLS 证书,是 GitLab 页面的可选功能. + +要将一个或多个自定义域名用于您的 Pages 网站,您可以: + +* 添加[自定义**根域**或**子域**](#set-up-pages-with-a-custom-domain) . +* Add [SSL/TLS certification](#adding-an-ssltls-certificate-to-pages). + +## Set up Pages with a custom domain[](#set-up-pages-with-a-custom-domain "Permalink") + +要使用自定义域名设置页面,请阅读以下要求和步骤. + +### Requirements[](#requirements "Permalink") + +* 在默认的 Pages 域( `*.gitlab.io` ,对于 GitLab.com)下运行的 GitLab Pages 网站已启动并正在运行. +* 自定义域名`example.com`或子`subdomain.example.com` . +* 访问您域的服务器控制面板以设置 DNS 记录: + * 将您的域指向 GitLab Pages 服务器的 DNS A 或 CNAME 记录. + * DNS TXT 记录以验证您的域的所有权. + +### Steps[](#steps "Permalink") + +请按照以下步骤将您的自定义域添加到 Pages. 另请参阅本文档,以获取[有关 DNS 记录](dns_concepts.html)的[概述](dns_concepts.html) . + +#### 1\. Add a custom domain to Pages[](#1-add-a-custom-domain-to-pages "Permalink") + +导航到项目的" **设置">"页面"** ,然后单击" **+新域"**将自定义域添加到 GitLab 页面. 您可以选择是否: + +* Add an [SSL/TLS certificate](#adding-an-ssltls-certificate-to-pages). +* 保留为空白(以后可以添加). + +Click **建立新网域**. + +[![Add new domain](img/78801b2f265bdecdb7a5ff7e8be47802.png)](img/add_certificate_to_pages.png) + +#### 2\. Get the verification code[](#2-get-the-verification-code "Permalink") + +将新域添加到 Pages 后,系统将提示您输入验证码. 从 GitLab 复制值,并将其作为下一步的 TXT 记录粘贴到您域的控制面板中. + +[![Get the verification code](img/137ac74ffc45b0c50cf354baa972ca89.png)](img/get_domain_verification_code_v12_0.png) + +#### 3\. Set up DNS records for Pages[](#3-set-up-dns-records-for-pages "Permalink") + +阅读本文档以[获取 Pages 的 DNS 记录概述](dns_concepts.html) . 如果您熟悉此主题,请根据您要与 Pages 网站一起使用的域类型,按照以下说明进行操作: + +* [For root domains](#for-root-domains), `example.com`. +* [For subdomains](#for-subdomains), `subdomain.example.com`. +* [For both](#for-both-root-and-subdomains). + +**注意:**您可以[在自管实例上配置 IPv6](../../../../administration/pages/index.html#advanced-configuration) ,但是 GitLab.com 上的 Pages 当前未配置 IPv6\. 有关详细信息,请关注[此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/214718) . + +##### For root domains[](#for-root-domains "Permalink") + +根域( `example.com` )要求: + +* 指向您的域指向 Pages 服务器的[DNS A 记录](dns_concepts.html#a-record) . +* [TXT 记录](dns_concepts.html#txt-record)以验证您的域的所有权. + +| From | DNS 记录 | To | +| --- | --- | --- | +| `example.com` | A | `35.185.44.232` | +| `_gitlab-pages-verification-code.example.com` | TXT | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` | + +对于 GitLab.com 上的项目,此 IP 为`35.185.44.232` . 对于位于其他 GitLab 实例(CE 或 EE)中的项目,请联系您的系统管理员以询问此信息(该 IP 地址是实例上运行的 Pages 服务器). + +[![DNS A record pointing to GitLab.com Pages server](img/2b38faa6a2c817e4d1b8b32f803db372.png)](img/dns_add_new_a_record_example_updated_2018.png) + +**注意:**请注意,如果**仅**将根域用于 GitLab Pages 网站,并且域注册商支持此功能,则可以添加 DNS 顶点`CNAME`记录而不是`A`记录. 这样做的主要优点是,当 GitLab.com 上的 GitLab Pages IP 出于任何原因更改时,您无需更新`A`记录. 可能会有一些例外,但是**不建议使用此方法,**因为如果您为根域设置[`MX`记录](dns_concepts.html#mx-record) ,则**该方法**很可能不起作用. + +##### For subdomains[](#for-subdomains "Permalink") + +子域( `subdomain.example.com` )要求: + +* 将您的子域指向 Pages 服务器的 DNS [CNAME 记录](dns_concepts.html#cname-record)记录. +* DNS [TXT 记录](dns_concepts.html#txt-record)以验证您的域的所有权. + +| From | DNS 记录 | To | +| --- | --- | --- | +| `subdomain.example.com` | CNAME | `namespace.gitlab.io` | +| `_gitlab-pages-verification-code.subdomain.example.com` | TXT | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` | + +请注意,无论是用户网站还是项目网站, `CNAME`都应指向您的 Pages 域( `namespace.gitlab.io` ),而不包含任何`/project-name` . + +[![DNS CNAME record pointing to GitLab.com project](img/00cb101eb824b3ede4fa4a3914f95c09.png)](img/dns_cname_record_example.png) + +##### For both root and subdomains[](#for-both-root-and-subdomains "Permalink") + +在某些情况下,您需要将子域和根域都指向同一个网站,例如`example.com`和`www.example.com` . + +他们要求: + +* 域的 DNS A 记录. +* 子域的 DNS CNAME 记录. +* 每个 DNS TXT 记录. + +| From | DNS 记录 | To | +| --- | --- | --- | +| `example.com` | A | `35.185.44.232` | +| `_gitlab-pages-verification-code.example.com` | TXT | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` | +| `www.example.com` | CNAME | `namespace.gitlab.io` | +| `_gitlab-pages-verification-code.www.example.com` | TXT | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` | + +如果您使用的是 CloudFlare,请选中[使用 Cloudflare 将`www.domain.com`重定向到`domain.com`](#redirecting-wwwdomaincom-to-domaincom-with-cloudflare) . + +> **Notes**: +> +> * 如果要将`domain.com`指向 GitLab Pages 网站,请**不要**使用 CNAME 记录. 请改用`A`记录. +> * **不要**在默认的 Pages 域之后添加任何特殊字符. 例如,不要将`subdomain.domain.com`指向或`namespace.gitlab.io/` . 但是,某些域托管服务提供商可能会请求结尾点( `namespace.gitlab.io.` ). +> * GitLab.com 上的 GitLab Pages IP 在 2017 年[进行了更改](https://about.gitlab.com/releases/2017/03/06/we-are-changing-the-ip-of-gitlab-pages-on-gitlab-com/) . +> * GitLab.com [上的](https://about.gitlab.com/blog/2018/07/19/gcp-move-update/#gitlab-pages-and-custom-domains) GitLab Pages IP `35.185.44.232` 2018 年的 52.167.214.135 [更改](https://about.gitlab.com/blog/2018/07/19/gcp-move-update/#gitlab-pages-and-custom-domains)为`52.167.214.135` . + +#### 4\. Verify the domain’s ownership[](#4-verify-the-domains-ownership "Permalink") + +添加所有 DNS 记录后: + +1. 返回项目的**设置>页面** . +2. 找到您的域名,然后单击" **详细信息"** . +3. 点击**重试验证**按钮以激活您的新域. + +[![Verify your domain](img/62b879dea0345cb8767d9cd4fb041f97.png)](img/retry_domain_verification_v12_0.png) + +一旦您的域名启用,您的网站就会通过您的域名可用. + +**注意:**考虑到启用了域验证的 GitLab 实例,如果该域不能在 7 天之内得到验证,它将被从 GitLab 项目中删除. + +> **Notes:** +> +> * **GitLab.com 用户必须进行**域验证; 对于 GitLab 自管实例,您的 GitLab 管理员可以选择[禁用自定义域验证](../../../../administration/pages/index.html#custom-domain-verification) . +> * [DNS 传播可能需要一些时间(最多 24 小时)](https://www.inmotionhosting.com/support/domain-names/dns-nameserver-changes/domain-names-dns-changes/) ,尽管通常只需几分钟即可完成. 否则,验证将失败,并且尝试访问您的域的尝试将以 404 响应. +> * 验证您的域后,请保留验证记录:您的域将定期重新验证,如果删除该记录,则可能会被禁用. + +##### Troubleshooting Pages domain verification[](#troubleshooting-pages-domain-verification "Permalink") + +要手动验证您已正确配置了域验证`TXT` DNS 条目,可以在终端中运行以下命令: + +``` +dig _gitlab-pages-verification-code. TXT +``` + +期望输出: + +``` +;; ANSWER SECTION: +_gitlab-pages-verification-code.. 300 IN TXT "gitlab-pages-verification-code=" +``` + +### Adding more domain aliases[](#adding-more-domain-aliases "Permalink") + +You can add more than one alias (custom domains and subdomains) to the same project. An alias can be understood as having many doors leading to the same room. + +您为网站设置的所有别名都将在" **设置">"页面"**上列出. 在该页面上,您可以查看,添加和删除它们. + +### Redirecting `www.domain.com` to `domain.com` with Cloudflare[](#redirecting-wwwdomaincom-to-domaincom-with-cloudflare "Permalink") + +如果您使用 Cloudflare,则可以将`www`重定向到`domain.com`而无需同时将`www.domain.com`和`domain.com`添加到 GitLab. + +为此,您可以使用与 CNAME 记录关联的 Cloudflare 的页面规则将`www.domain.com`重定向到`domain.com` . 您可以使用以下设置: + +1. 在 Cloudflare 中,创建一个 DNS `A`记录,将`domain.com`指向`35.185.44.232` . +2. 在 GitLab 中,将域添加到 GitLab 页面中并获取验证码. +3. 在 Cloudflare 中,创建 DNS `TXT`记录以验证您的域. +4. 在 GitLab 中,验证您的域. +5. 在 Cloudflare 中,创建将`www`指向`domain.com`的 DNS `CNAME`记录. +6. 在 Cloudflare 中,添加将`www.domain.com`指向`domain.com`的页面规则: + * 导航到您域的信息中心,然后点击顶部导航栏中的**页面规则** . + * 单击**创建页面规则** . + * 输入域名`www.domain.com` ,然后点击**+添加设置** . + * 从下拉菜单中,选择**转发 URL** ,然后选择状态代码**301-永久重定向** . + * 输入目标网址`https://domain.com` . + +## Adding an SSL/TLS certificate to Pages[](#adding-an-ssltls-certificate-to-pages "Permalink") + +阅读本文档以获取[有关 SSL / TLS 认证](ssl_tls_concepts.html)的[概述](ssl_tls_concepts.html) . + +要使用 GitLab 页面保护您的自定义域,您可以选择: + +* 使用[Let's Encrypt 与 GitLab Pages 的集成](lets_encrypt_integration.html) ,该[集成](lets_encrypt_integration.html)会自动获取和续订您 Pages 域的 SSL 证书. +* 遵循以下步骤,将 SSL / TLS 证书手动添加到 GitLab Pages 网站. + +### Requirements[](#requirements-1 "Permalink") + +* 可通过自定义域访问 GitLab Pages 网站并正在运行. +* **PEM 证书** :它是由 CA 生成的证书,需要将其添加到字段**Certificate(PEM)中** . +* **[中间证书](https://en.wikipedia.org/wiki/Intermediate_certificate_authority)** :(也称为"根证书"),它是标识 CA 的加密密钥链的一部分. 通常,它与 PEM 证书结合在一起,但是在某些情况下,您需要手动添加它们. [CloudFlare 证书](https://about.gitlab.com/blog/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/)就是其中一种. +* **私钥** ,这是一个加密密钥,可根据您的域验证您的 PEM. + +### Steps[](#steps-1 "Permalink") + +* 要在添加新域时添加证书,请转至项目的**"设置">"页面">"新域"** ,添加域名和证书. +* 要将证书添加到先前添加的域中,请转到项目的**"设置">"页面"** ,找到您的域名,单击" **详细信息"**和" **编辑"**以添加证书. + +[![Pages project - adding certificates](img/78801b2f265bdecdb7a5ff7e8be47802.png)](img/add_certificate_to_pages.png) + +1. 将 PEM 证书添加到其相应的字段. +2. 如果您的证书缺少中间证书,请复制并粘贴根证书(通常可从您的 CA 网站获得),然后将其粘贴到[与 PEM 证书相同的字段中](https://about.gitlab.com/blog/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) ,只需在它们之间跳过一行即可. +3. 复制您的私钥并将其粘贴到最后一个字段中. + +**注意:** **请勿**在常规文本编辑器中打开证书或加密密钥. 始终使用代码编辑器(例如 Sublime Text,Atom,Dreamweaver,括号等). + +## Force HTTPS for GitLab Pages websites[](#force-https-for-gitlab-pages-websites "Permalink") + +在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28857) . + +为了使您的网站访问者更加安全,您可以选择对 GitLab 页面强制使用 HTTPS. 这样,所有通过 HTTP 访问您的网站的尝试都会通过 301 自动重定向到 HTTPS. + +它既可以与 GitLab 的默认域一起使用,也可以与您的自定义域一起使用(只要您为其设置了有效的证书). + +要启用此设置: + +1. 导航到项目的**"设置">"页面"** . +2. 选中" **强制 HTTPS** "复选框**(需要有效的证书)** . + +**注意:**如果在 GitLab 页面前面使用 CloudFlare CDN,请确保将 SSL 连接设置设置为`full`而不是`flexible` . 有关更多详细信息,请参阅[CloudFlare CDN 指导](https://support.cloudflare.com/hc/en-us/articles/200170416-End-to-end-HTTPS-with-Cloudflare-Part-3-SSL-options#h_4e0d1a7c-eb71-4204-9e22-9d3ef9ef7fef) . \ No newline at end of file diff --git a/docs/249.md b/docs/249.md new file mode 100644 index 0000000000000000000000000000000000000000..d582de0453fe3c403ed310be8ecce97e8b6f0a82 --- /dev/null +++ b/docs/249.md @@ -0,0 +1,82 @@ +# GitLab Pages integration with Let's Encrypt + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html) + +* [Requirements](#requirements) +* [Enabling Let’s Encrypt integration for your custom domain](#enabling-lets-encrypt-integration-for-your-custom-domain) +* [Troubleshooting](#troubleshooting) + * [Error “Something went wrong while obtaining the Let’s Encrypt certificate”](#error-something-went-wrong-while-obtaining-the-lets-encrypt-certificate) + * [Message “GitLab is obtaining a Let’s Encrypt SSL certificate for this domain. This process can take some time. Please try again later.” hangs for more than an hour](#message-gitlab-is-obtaining-a-lets-encrypt-ssl-certificate-for-this-domain-this-process-can-take-some-time-please-try-again-later-hangs-for-more-than-an-hour) + +# GitLab Pages integration with Let’s Encrypt[](#gitlab-pages-integration-with-lets-encrypt "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28996) . 对于 GitLab 12.1 之前的版本,请参见[手册"让我们加密"说明](../lets_encrypt_for_gitlab_pages.html) . + +GitLab Pages 与 Let's Encrypt(LE)的集成使您可以将 LE 证书用于具有自定义域的 Pages 网站,而不必麻烦自己发行和更新它们. GitLab 现成的为您服务. + +[Let's Encrypt](https://letsencrypt.org)是一个免费,自动化和开源的证书颁发机构. + +**警告:**此功能仅涵盖**自定义域的**证书,而不包含运行[Pages 守护程序](../../../../administration/pages/index.html)所需的通配符证书 . 在[此问题中](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3342)跟踪通配符证书的生成. + +## Requirements[](#requirements "Permalink") + +在为您的域启用自动配置 SSL 证书之前,请确保您具有: + +* 创建一个[项目](../getting_started_part_two.html)在 GitLab 包含您的网站的源代码. +* 获取域( `example.com` )并添加一个[DNS 条目,](index.html)将其指向您的 Pages 网站. +* [将您的域添加到您的 Pages 项目](index.html#1-add-a-custom-domain-to-pages)并验证您的所有权. +* 确认您的网站已启动并且正在运行,可以通过您的自定义域进行访问. + +**注意:** GitLab 的"让我们加密"集成已启用,并在 GitLab.com 上可用. 对于**自我管理的** GitLab 实例,请确保您的管理员已[启用它](../../../../administration/pages/index.html#lets-encrypt-integration) . + +## Enabling Let’s Encrypt integration for your custom domain[](#enabling-lets-encrypt-integration-for-your-custom-domain "Permalink") + +满足要求后,启用"让我们加密"集成: + +1. 导航到项目的**"设置">"页面"** . +2. 找到您的域,然后单击**详细信息** . +3. 点击右上角的**编辑** . +4. 通过**使用 Let's Encrypt**切换**自动证书管理来**启用 Let's Encrypt 集成: + + [![Enable Let's Encrypt](img/b2499f834ff0e8252829dd96bad93d97.png)](img/lets_encrypt_integration_v12_1.png) + +5. Click **保存更改**. + +启用后,GitLab 将获得 LE 证书并将其添加到关联的 Pages 域中. 它也会由 GitLab 自动更新. + +> **Notes:** +> +> * 颁发证书和更新 Pages 配置**可能需要一个小时** . +> * 如果您在域设置中已经具有 SSL 证书,它将继续工作,直到被 Let's Encrypt 的证书替换为止. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Error “Something went wrong while obtaining the Let’s Encrypt certificate”[](#error-something-went-wrong-while-obtaining-the-lets-encrypt-certificate "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30146) . + +如果您遇到错误, **则在获取 Let's Encrypt 证书时出了点问题** ,您可以尝试按照以下步骤再次获取证书: + +1. 转到项目的**设置>页面** . +2. 在您的域上单击" **编辑** ". +3. Click **Retry**. +4. 如果您仍然看到相同的错误: + 1. 请确保您已正确设置只有一个`CNAME`或`A` DNS 记录为您的域. + 2. 确保您的域**没有** `AAAA` DNS 记录. + 3. 如果您的域或任何更高级别的域都有`CAA` DNS 记录,请确保[其中包含`letsencrypt.org`](https://letsencrypt.org/docs/caa/) . + 4. 确保[您的域已验证](index.html#1-add-a-custom-domain-to-pages) . + 5. 转到步骤 1\. + +### Message “GitLab is obtaining a Let’s Encrypt SSL certificate for this domain. This process can take some time. Please try again later.” hangs for more than an hour[](#message-gitlab-is-obtaining-a-lets-encrypt-ssl-certificate-for-this-domain-this-process-can-take-some-time-please-try-again-later-hangs-for-more-than-an-hour "Permalink") + +如果您启用了 Let's Encrypt 集成,但是一个小时后缺少证书,则会看到以下消息:" GitLab 正在为此域获取 Let's Encrypt SSL 证书. 此过程可能需要一些时间. 请稍后再试.",请按照以下步骤尝试删除并再次为 GitLab 页面添加域: + +1. 转到项目的**设置>页面** . +2. 在您的域上单击**删除** . +3. [Add the domain again and verify it](index.html#1-add-a-custom-domain-to-pages). +4. [Enable Let’s Encrypt integration for your domain](#enabling-lets-encrypt-integration-for-your-custom-domain). +5. 如果一段时间后仍然看到相同的消息: + 1. 请确保您已正确设置只有一个`CNAME`或`A` DNS 记录为您的域. + 2. 确保您的域**没有** `AAAA` DNS 记录. + 3. 如果您的域或任何更高级别的域都有`CAA` DNS 记录,请确保[其中包含`letsencrypt.org`](https://letsencrypt.org/docs/caa/) . + 4. 转到步骤 1\. \ No newline at end of file diff --git a/docs/250.md b/docs/250.md new file mode 100644 index 0000000000000000000000000000000000000000..d36ab73f06624b2d953a1b16813a483a2850840b --- /dev/null +++ b/docs/250.md @@ -0,0 +1,44 @@ +# GitLab Pages Access Control + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/pages_access_control.html](https://docs.gitlab.com/ee/user/project/pages/pages_access_control.html) + +* [Terminating a Pages session](#terminating-a-pages-session) + +# GitLab Pages Access Control[](#gitlab-pages-access-control "Permalink") + +版本历史 + +* 在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33422) . +* 在 GitLab 12.4 的 GitLab.com 上可用. + +您可以在项目上启用 Pages 访问控制,以便只有[项目成员](../../permissions.html#project-members-permissions) (至少是 Guest)才能访问您的网站: + +有关演示,请参阅[页面访问控制](https://www.youtube.com/watch?v=tSPAr5mQYc8) . + +1. 导航到项目的**"设置">"常规",**然后展开" **可见性","项目功能,权限"** . +2. 切换**页面**按钮以启用访问控制. + + **注意:**如果看不到切换按钮,则表示该按钮未启用. 请您的管理员[启用它](../../../administration/pages/index.html#access-control) . +3. 页面访问控制下拉菜单允许您设置谁可以查看 GitLab 页面托管的页面,具体取决于项目的可见性: + + * 如果您的项目是私人的: + * **只有项目成员** :只有项目成员才能浏览网站. + * **所有人** :无论登录或退出 GitLab 的**每个**人,无论其项目成员身份如何,都可以浏览该网站. + * 如果您的项目是内部项目: + * **只有项目成员** :只有项目成员才能浏览网站. + * **具有访问权限的**每个人:登录到 GitLab 的每个人都可以浏览该网站,无论其项目成员身份如何. + * **所有人** :无论登录或退出 GitLab 的**每个**人,无论其项目成员身份如何,都可以浏览该网站. + * 如果您的项目是公开的: + * **只有项目成员** :只有项目成员才能浏览网站. + * **具有访问权限的**所有人:无论登录或退出 GitLab 的每个人,无论其项目成员身份如何,都可以浏览该网站. +4. Click **保存更改**. + +下次有人尝试访问您的网站并启用访问控制时,将向他们显示一个页面,以登录 GitLab 并验证他们可以访问该网站. + +## Terminating a Pages session[](#terminating-a-pages-session "Permalink") + +如果要从 Pages 网站注销,可以通过撤销 GitLab Pages 的应用程序访问令牌来注销: + +1. 浏览至个人资料的**"设置">"应用程序"** . +2. 在页面底部找到**授权的应用程序** . +3. 查找**GitLab 页面** ,然后按**撤消**按钮. \ No newline at end of file diff --git a/docs/251.md b/docs/251.md new file mode 100644 index 0000000000000000000000000000000000000000..28a2dec9336841ea064d069b43cfb3f90d087833 --- /dev/null +++ b/docs/251.md @@ -0,0 +1,249 @@ +# Exploring GitLab Pages + +> 原文:[https://docs.gitlab.com/ee/user/project/pages/introduction.html](https://docs.gitlab.com/ee/user/project/pages/introduction.html) + +* [GitLab Pages requirements](#gitlab-pages-requirements) +* [GitLab Pages on GitLab.com](#gitlab-pages-on-gitlabcom) +* [Example projects](#example-projects) +* [Custom error codes Pages](#custom-error-codes-pages) +* [Redirects in GitLab Pages](#redirects-in-gitlab-pages) +* [GitLab Pages Access Control](#gitlab-pages-access-control-core) +* [Unpublishing your Pages](#unpublishing-your-pages) +* [Limitations](#limitations) +* [Specific configuration options for Pages](#specific-configuration-options-for-pages) + * [`.gitlab-ci.yml` for plain HTML websites](#gitlab-ciyml-for-plain-html-websites) + * [`.gitlab-ci.yml` for a static site generator](#gitlab-ciyml-for-a-static-site-generator) + * [`.gitlab-ci.yml` for a repository where there’s also actual code](#gitlab-ciyml-for-a-repository-where-theres-also-actual-code) + * [Serving compressed assets](#serving-compressed-assets) + * [Resolving ambiguous URLs](#resolving-ambiguous-urls) +* [Frequently Asked Questions](#frequently-asked-questions) + * [Can I download my generated pages?](#can-i-download-my-generated-pages) + * [Can I use GitLab Pages if my project is private?](#can-i-use-gitlab-pages-if-my-project-is-private) + * [Do I need to create a user/group website before creating a project website?](#do-i-need-to-create-a-usergroup-website-before-creating-a-project-website) +* [Known issues](#known-issues) + +# Exploring GitLab Pages[](#exploring-gitlab-pages "Permalink") + +本文档是用户指南,用于探索 GitLab Pages 提供的选项和设置. + +首先要熟悉 GitLab 页面: + +* 阅读[有关 GitLab Pages](index.html#overview)的[介绍](index.html#overview) . +* Learn [how to get started with Pages](index.html#getting-started). +* 在[管理员文档中](../../../administration/pages/index.html)了解如何在整个 GitLab 实例上启用 GitLab 页面. + +## GitLab Pages requirements[](#gitlab-pages-requirements "Permalink") + +简而言之,这是您需要在 GitLab 页面中上传网站的内容: + +1. 实例的域:用于 GitLab 页面的域名(询问管理员). +2. GitLab CI / CD:一个`.gitlab-ci.yml`文件,在存储库的根目录中有一个名为[`pages`](../../../ci/yaml/README.html#pages)的特定作业. +3. 您网站存储库中一个名为`public`的目录,其中包含要发布的内容. +4. 为项目启用了 GitLab Runner. + +## GitLab Pages on GitLab.com[](#gitlab-pages-on-gitlabcom "Permalink") + +如果您使用[GitLab.com](#gitlab-pages-on-gitlabcom)上的[GitLab 页面](#gitlab-pages-on-gitlabcom)来托管您的网站,则: + +* The domain name for GitLab Pages on GitLab.com is `gitlab.io`. +* 自定义域和 TLS 支持已启用. +* 共享运行器默认情况下处于启用状态,免费提供,可用于构建您的网站. 如果您愿意,仍然可以携带自己的跑步者. + +## Example projects[](#example-projects "Permalink") + +访问[GitLab 页面组](https://gitlab.com/groups/pages)以获得示例项目的完整列表. 欢迎捐款. + +## Custom error codes Pages[](#custom-error-codes-pages "Permalink") + +您可以通过在将包含在工件中的`public/`目录的根目录中分别创建`403.html`和`404.html`文件来提供自己的 403 和 404 错误页面. 通常,这是项目的根目录,但是根据您的静态生成器配置,它可能有所不同. + +如果是`404.html` ,则有不同的方案. 例如: + +* 如果您使用项目 Pages(在`/projectname/` )并尝试访问`/projectname/non/existing_file` ,则 GitLab Pages 将尝试首先提供`/projectname/404.html` ,然后提供`/404.html` . +* 如果您使用用户/组页面(在`/`下提供)并尝试访问`/non/existing_file` GitLab Pages 将尝试提供`/404.html` . +* 如果您使用自定义域并尝试访问`/non/existing_file` ,则 GitLab Pages 将尝试仅提供`/404.html` . + +## Redirects in GitLab Pages[](#redirects-in-gitlab-pages "Permalink") + +由于您不能使用任何自定义服务器配置文件(例如`.htaccess`或任何`.conf`文件),因此,如果要将页面重定向到其他位置,可以使用[HTTP meta refresh 标签](https://en.wikipedia.org/wiki/Meta_refresh) . + +一些静态网站生成器提供了该功能的插件,因此您不必手动创建和编辑 HTML 文件. 例如,Jekyll 具有[redirect-from 插件](https://github.com/jekyll/jekyll-redirect-from) . + +## GitLab Pages Access Control[](#gitlab-pages-access-control-core "Permalink") + +要限制对您网站的访问,请启用[GitLab 页面访问控制](pages_access_control.html) . + +## Unpublishing your Pages[](#unpublishing-your-pages "Permalink") + +如果您需要清除 Pages 内容,可以通过右上角的齿轮图标进入项目设置,然后导航至**Pages** . 点击**删除页面**按钮,您的页面网站将被删除. + +[![Remove pages](img/987208c515a3f2627904cc38b355dc15.png)](img/remove_pages.png) + +## Limitations[](#limitations "Permalink") + +在 GitLab 实例的常规域( `*.example.io` )下使用 Pages 时, *不能*将 HTTPS 与子子域一起使用. 这意味着,如果你的用户名或组名称中包含一个圆点,例如`foo.bar` ,域`https://foo.bar.example.io`将*无法*正常工作. 这是[HTTP Over TLS 协议](https://tools.ietf.org/html/rfc2818#section-3.1)的限制. 如果您不将 HTTP 重定向到 HTTPS,HTTP 页面将继续工作. + +GitLab 网页[**不**支持组为网站分组](../../group/subgroups/index.html#limitations) . 您只能创建最高级别的群组网站. + +## Specific configuration options for Pages[](#specific-configuration-options-for-pages "Permalink") + +了解如何针对特定用例设置 GitLab CI / CD. + +### `.gitlab-ci.yml` for plain HTML websites[](#gitlab-ciyml-for-plain-html-websites "Permalink") + +假设您的存储库包含以下文件: + +``` +├── index.html +├── css +│ └── main.css +└── js + └── main.js +``` + +然后,下面的`.gitlab-ci.yml`示例仅将所有文件从项目的根目录移至`public/`目录. `.public`解决方法是, `cp`不会在无限循环中将`public/`复制到自身: + +``` +pages: + script: + - mkdir .public + - cp -r * .public + - mv .public public + artifacts: + paths: + - public + only: + - master +``` + +### `.gitlab-ci.yml` for a static site generator[](#gitlab-ciyml-for-a-static-site-generator "Permalink") + +请参阅本文档,以获取[分步指南](getting_started/pages_from_scratch.html) . + +### `.gitlab-ci.yml` for a repository where there’s also actual code[](#gitlab-ciyml-for-a-repository-where-theres-also-actual-code "Permalink") + +请记住,默认情况下,GitLab 页面是分支/标签不可知的,它们的部署仅取决于您在`.gitlab-ci.yml`指定`.gitlab-ci.yml` . 每当将新的提交推送到专门用于页面的分支时,就可以使用[`only`参数](../../../ci/yaml/README.html#onlyexcept-basic)限制`pages`作业. + +这样,您可以将项目的代码保存在`master`分支中,并使用一个孤儿分支(将其命名为`pages` )来托管您的静态生成器站点. + +您可以这样创建一个新的空分支: + +``` +git checkout --orphan pages +``` + +在这个新分支上进行的第一次提交将没有父母,这将是与所有其他分支和提交完全脱节的新历史的根源. 在`pages`分支中推送静态生成器的源文件. + +以下是`.gitlab-ci.yml`的副本,其中最重要的一行是最后一行,指定要执行`pages`分支中的所有`pages` : + +``` +image: ruby:2.6 + +pages: + script: + - gem install jekyll + - jekyll build -d public/ + artifacts: + paths: + - public + only: + - pages +``` + +请参见一个示例,该示例在[`master`分支](https://gitlab.com/pages/jekyll-branched/tree/master)中具有不同的文件,而 Jekyll 的源文件在[`pages`分支中](https://gitlab.com/pages/jekyll-branched/tree/pages) ,该[分支](https://gitlab.com/pages/jekyll-branched/tree/pages)还包含`.gitlab-ci.yml` . + +### Serving compressed assets[](#serving-compressed-assets "Permalink") + +大多数现代的浏览器都支持下载压缩格式的文件. 通过减小文件大小,可以加快下载速度. + +Pages 将提供未压缩的文件之前,将检查是否存在扩展名为`.gz`的相同文件. 如果支持,并且浏览器支持接收压缩文件,它将使用该版本而不是未压缩版本. + +要利用此功能,您上传到页面的工件应具有以下结构: + +``` +public/ +├─┬ index.html +│ └ index.html.gz +│ +├── css/ +│ └─┬ main.css +│ └ main.css.gz +│ +└── js/ + └─┬ main.js + └ main.js.gz +``` + +这可以通过在`.gitlab-ci.yml`页面作业中包含以下`script:`来实现: + +``` +pages: + # Other directives + script: + # Build the public/ directory first + - find public -type f -regex '.*\.\(htm\|html\|txt\|text\|js\|css\)$' -exec gzip -f -k {} \; +``` + +通过预压缩文件并在工件中包括两个版本,Pages 可以处理对压缩和未压缩内容的请求,而无需按需压缩文件. + +### Resolving ambiguous URLs[](#resolving-ambiguous-urls "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/95) + +当接收到不包含扩展名的 URL 的请求时,GitLab Pages 会假设要提供哪些文件. + +考虑使用以下文件部署的 Pages 站点: + +``` +public/ +├─┬ index.html +│ ├ data.html +│ └ info.html +│ +├── data/ +│ └── index.html +├── info/ +│ └── details.html +└── other/ + └── index.html +``` + +页面支持通过几个不同的 URL 来访问每个文件. 特别是,如果 URL 仅指定目录,它将始终寻找`index.html`文件. 如果该 URL 引用了一个不存在的文件,但是将`.html`添加到该 URL 中会导致该文件*确实*存在,将改为提供该文件. 以下是在上述 Pages 网站上发生的情况的一些示例: + +| URL path | HTTP 响应 | 文件送达 | +| --- | --- | --- | +| `/` | `200 OK` | `public/index.html` | +| `/index.html` | `200 OK` | `public/index.html` | +| `/index` | `200 OK` | `public/index.html` | +| `/data` | `200 OK` | `public/data/index.html` | +| `/data/` | `200 OK` | `public/data/index.html` | +| `/data.html` | `200 OK` | `public/data.html` | +| `/info` | `200 OK` | `public/info.html` | +| `/info/` | `200 OK` | `public/info.html` | +| `/info.html` | `200 OK` | `public/info.html` | +| `/info/details` | `200 OK` | `public/info/details.html` | +| `/info/details.html` | `200 OK` | `public/info/details.html` | +| `/other` | `302 Found` | `public/other/index.html` | +| `/other/` | `200 OK` | `public/other/index.html` | +| `/other/index` | `200 OK` | `public/other/index.html` | +| `/other/index.html` | `200 OK` | `public/other/index.html` | + +**注意:**当存在`public/data/index.html`时,对于`/data`和`/data/` URL 路径,其优先于`public/data.html`文件. + +## Frequently Asked Questions[](#frequently-asked-questions "Permalink") + +### Can I download my generated pages?[](#can-i-download-my-generated-pages "Permalink") + +当然. 您需要做的就是从作业页面下载工件存档. + +### Can I use GitLab Pages if my project is private?[](#can-i-use-gitlab-pages-if-my-project-is-private "Permalink") + +是. GitLab Pages 不在乎将项目的可见性级别设置为私有,内部还是公共. + +### Do I need to create a user/group website before creating a project website?[](#do-i-need-to-create-a-usergroup-website-before-creating-a-project-website "Permalink") + +不,你没有. 您可以先创建您的项目,然后将在`http(s)://namespace.example.io/projectname`下对其进行访问. + +## Known issues[](#known-issues "Permalink") + +有关已知问题的列表,请访问 GitLab 的[公共问题跟踪器](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name[]=Category:Pages) . \ No newline at end of file diff --git a/docs/252.md b/docs/252.md new file mode 100644 index 0000000000000000000000000000000000000000..5f410fd0de4e381c2bca9f1348405e141ceb7241 --- /dev/null +++ b/docs/252.md @@ -0,0 +1,104 @@ +# Incremental Rollouts with GitLab CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/environments/incremental_rollouts.html](https://docs.gitlab.com/ee/ci/environments/incremental_rollouts.html) + +* [Manual Rollouts](#manual-rollouts) +* [Timed Rollouts](#timed-rollouts) +* [Blue-Green Deployment](#blue-green-deployment) + +# Incremental Rollouts with GitLab CI/CD[](#incremental-rollouts-with-gitlab-cicd "Permalink") + +在对应用程序进行更改时,可以将生产更改仅发布到 Kubernetes 吊舱的一部分,作为降低风险的策略. 通过逐步发布生产更改,可以监视错误率或性能下降,并且如果没有问题,则可以更新所有吊舱. + +manbetx 客户端打不开支持使用增量卷展到 Kubernetes 生产系统的手动触发和定时卷展. 使用"手动卷展"时,将手动触发每个吊舱的释放,而在"定时卷展"中,默认的暂停时间为 5 分钟,然后按批次进行释放. 也可以在暂停时间到期之前手动触发定时启动. + +手动和定时卷展栏自动包含在由[AutoDevOps](../../topics/autodevops/index.html)控制的项目中,但也可以通过 GitLab CI / CD 在`.gitlab-ci.yml`配置文件中`.gitlab-ci.yml`配置. + +可以使用" [持续交付"](../introduction/index.html#continuous-delivery)方法来实现手动触发的部署,而定时部署不需要干预,并且可以作为" [持续部署"](../introduction/index.html#continuous-deployment)策略的一部分. 您还可以通过自动部署应用程序的方式将两者结合在一起,除非最终在必要时进行手动干预. + +我们创建了示例应用程序来演示这三个选项,您可以将其用作构建自己的示例: + +* [Manual incremental rollouts](https://gitlab.com/gl-release/incremental-rollout-example/blob/master/.gitlab-ci.yml) +* [Timed incremental rollouts](https://gitlab.com/gl-release/timed-rollout-example/blob/master/.gitlab-ci.yml) +* [Both manual and timed rollouts](https://gitlab.com/gl-release/incremental-timed-rollout-example/blob/master/.gitlab-ci.yml) + +## Manual Rollouts[](#manual-rollouts "Permalink") + +在 GitLab 10.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/5415) . + +可以将 GitLab 配置为通过`.gitlab-ci.yml`手动进行增量部署. 手动配置允许对该功能进行更多控制. 增量部署的步骤取决于为部署定义的 Pod 数量,这些 Pod 是在创建 Kubernetes 集群时配置的. + +例如,如果您的应用程序有 10 个容器,并且运行了 10%的部署作业,则该应用程序的新实例将被部署到单个容器中,而其余 9 个将显示前一个实例. + +首先,我们[将模板定义为手动](https://gitlab.com/gl-release/incremental-rollout-example/blob/master/.gitlab-ci.yml#L100-103) : + +``` +.manual_rollout_template: &manual_rollout_template + <<: *rollout_template + stage: production + when: manual +``` + +然后,我们[定义每个步骤的推出量](https://gitlab.com/gl-release/incremental-rollout-example/blob/master/.gitlab-ci.yml#L152-155) : + +``` +rollout 10%: + <<: *manual_rollout_template + variables: + ROLLOUT_PERCENTAGE: 10 +``` + +When the jobs are built, a **play** button will appear next to the job’s name. Click the **play** button to release each stage of pods. You can also rollback by running a lower percentage job. Once 100% is reached, you cannot roll back using this method. It is still possible to roll back by redeploying the old version using the **Rollback** button on the environment page. + +[![Play button](img/184e7323733c8aa9331e3fbef102e17c.png)](img/incremental_rollouts_play_v12_7.png) + +一个[可部署的应用程序](https://gitlab.com/gl-release/incremental-rollout-example)可用,演示了手动触发的增量部署. + +## Timed Rollouts[](#timed-rollouts "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7545) . + +定时部署的行为与手动部署的行为相同,不同之处在于,每个作业在部署前都会延迟几分钟. 单击作业将显示倒计时. + +[![Timed rollout](img/261e6c6422bccbb978c24c0728f3a593.png)](img/timed_rollout_v12_7.png) + +可以将此功能与手动增量部署相结合,以便作业倒计时然后部署. + +首先,我们[将模板定义为 timed](https://gitlab.com/gl-release/timed-rollout-example/blob/master/.gitlab-ci.yml#L86-89) : + +``` +.timed_rollout_template: &timed_rollout_template + <<: *rollout_template + when: delayed + start_in: 1 minutes +``` + +我们可以使用`start_in`键定义延迟时间: + +``` +start_in: 1 minutes +``` + +然后,我们[定义每个步骤的推出量](https://gitlab.com/gl-release/timed-rollout-example/blob/master/.gitlab-ci.yml#L97-101) : + +``` +timed rollout 30%: + <<: *timed_rollout_template + stage: timed rollout 30% + variables: + ROLLOUT_PERCENTAGE: 30 +``` + +一个[可部署的应用程序](https://gitlab.com/gl-release/timed-rollout-example)可用, [演示了定时部署的配置](https://gitlab.com/gl-release/timed-rollout-example/blob/master/.gitlab-ci.yml#L86-95) . + +## Blue-Green Deployment[](#blue-green-deployment "Permalink") + +有时也称为 A / B 部署或红黑色部署,此技术用于减少部署期间的停机时间和风险. 当与增量推出结合使用时,您可以最大程度地减少导致问题的部署的影响. + +使用这种技术,有两种部署方式("蓝色"和"绿色",但是可以使用任何命名). 在任何给定时间,这些部署中只有一个处于活动状态,除非在增量部署期间. + +例如,您的蓝色部署当前可以在生产中处于活动状态,而绿色部署"处于活动状态"可以进行测试,但不能部署到生产中. 如果发现问题,则可以在不影响生产部署的情况下更新绿色部署(当前为蓝色). 如果测试没有问题,则将生产切换到绿色部署,并且蓝色现在可用于测试下一个版本. + +此过程减少了停机时间,因为无需停止生产部署即可切换到其他部署. 两种部署都并行运行,并且可以随时切换到. + +提供了一个[示例可部署应用程序](https://gitlab.com/gl-release/blue-green-example) ,带有一个[`gitlab-ci.yml` CI / CD 配置文件](https://gitlab.com/gl-release/blue-green-example/blob/master/.gitlab-ci.yml) ,该[文件](https://gitlab.com/gl-release/blue-green-example/blob/master/.gitlab-ci.yml)演示了蓝绿色的部署. \ No newline at end of file diff --git a/docs/253.md b/docs/253.md new file mode 100644 index 0000000000000000000000000000000000000000..7d9bfa0ba4e4b4cdac673a1df64901eced6be5da --- /dev/null +++ b/docs/253.md @@ -0,0 +1,45 @@ +# Interactive Web Terminals + +> 原文:[https://docs.gitlab.com/ee/ci/interactive_web_terminal/](https://docs.gitlab.com/ee/ci/interactive_web_terminal/) + +* [Configuration](#configuration) +* [Debugging a running job](#debugging-a-running-job) +* [Interactive Web Terminals for the Web IDE](#interactive-web-terminals-for-the-web-ide) + +# Interactive Web Terminals[](#interactive-web-terminals "Permalink") + +在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/50144) . + +交互式 Web 终端使用户可以访问 GitLab 中的终端,以为其 CI 管道运行一次性命令. 由于这使用户可以通过外壳访问[GitLab Runner](https://docs.gitlab.com/runner/)部署环境,因此采取了一些[安全预防](../../administration/integration/terminal.html#security)措施来保护用户. + +**注意:** [GitLab.com 上的共享跑步者](../quick_start/README.html#shared-runners)不提供交互式 Web 终端. 请遵循[此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/24674)以获取增加支持方面的进展. 对于在 GitLab.com 上托管的组和项目,使用自己的组或项目运行器时可以使用交互式 Web 终端. + +## Configuration[](#configuration "Permalink") + +为了使交互式 Web 终端正常工作,需要配置两件事: + +* 跑步者需要[正确配置`[session_server]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) +* 如果您在 GitLab 实例上使用反向代理,则需要[启用](../../administration/integration/terminal.html#enabling-and-disabling-terminal-support) Web 终端 + +**注意:** [`gitlab-runner` Helm chart](https://docs.gitlab.com/charts/charts/gitlab/gitlab-runner/index.html)尚不支持交互式 Web 终端,但[已计划](https://gitlab.com/gitlab-org/charts/gitlab-runner/-/issues/79)支持. + +## Debugging a running job[](#debugging-a-running-job "Permalink") + +**注意:**并非所有执行程序都[受支持](https://docs.gitlab.com/runner/executors/) .**注意:**构建脚本完成后, `docker` executor 不会继续运行. 届时,终端将自动断开连接,并且不会等待用户完成操作. 请关注[此问题,](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3605)以获取有关改进此行为的更新. + +有时,当一项作业正在运行时,事情并没有按您期望的那样进行,如果可以有一个外壳来帮助调试,这将很有帮助. 运行作业时,在右侧面板上可以看到一个`debug`按钮,它将打开当前作业的终端. + +[![Example of job running with terminal +available](img/206da14c2b9fd76390be58e7103b69c7.png)](img/interactive_web_terminal_running_job.png) + +单击后,新选项卡将打开到终端页面,您可以在其中访问终端并键入命令,如普通的 shell. + +[![terminal of the job](img/86b62f200c6aa129ed945d20ec0fbfa2.png)](img/interactive_web_terminal_page.png) + +如果您打开终端并且作业已完成其任务,则终端将在[`[session_server].session_timeout`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)配置的持续时间内阻止作业完成,直到关闭终端窗口. + +[![finished job with terminal open](img/2823aaef9502e47fb72734606099a98a.png)](img/finished_job_with_terminal_open.png) + +## Interactive Web Terminals for the Web IDE[](#interactive-web-terminals-for-the-web-ide "Permalink") + +阅读 Web IDE 文档,以了解如何[通过 Web IDE](../../user/project/web_ide/index.html#interactive-web-terminals-for-the-web-ide)运行[交互式终端](../../user/project/web_ide/index.html#interactive-web-terminals-for-the-web-ide) . \ No newline at end of file diff --git a/docs/254.md b/docs/254.md new file mode 100644 index 0000000000000000000000000000000000000000..6e84d270f17bb26de57606615cdb739f725892c3 --- /dev/null +++ b/docs/254.md @@ -0,0 +1,206 @@ +# Optimizing GitLab for large repositories + +> 原文:[https://docs.gitlab.com/ee/ci/large_repositories/](https://docs.gitlab.com/ee/ci/large_repositories/) + +* [Shallow cloning](#shallow-cloning) +* [Git strategy](#git-strategy) +* [Git clone path](#git-clone-path) +* [Git clean flags](#git-clean-flags) +* [Git fetch extra flags](#git-fetch-extra-flags) +* [Fork-based workflow](#fork-based-workflow) + * [`shell` executor example](#shell-executor-example) + * [`docker` executor example](#docker-executor-example) + * [Our `.gitlab-ci.yml`](#our-gitlab-ciyml) + * [Store custom clone options in `config.toml`](#store-custom-clone-options-in-configtoml) + +# Optimizing GitLab for large repositories[](#optimizing-gitlab-for-large-repositories "Permalink") + +通常,由于克隆和签出所需的时间,在工作树中包含超过 5 万个文件的大型存储库通常需要特别考虑. + +GitLab 和 GitLab Runner 可以很好地处理这种情况,但是需要优化的配置才能有效地执行其操作. + +处理大型存储库的一般准则很简单. 以下各节将更详细地描述每个准则: + +* 始终以增量方式获取. 请勿以导致重新创建所有工作树的方式进行克隆. +* 始终使用浅克隆来减少数据传输. 请注意,由于 CPU 影响更大,这给 GitLab 实例带来了更多负担. +* 如果您大量使用基于 fork 的工作流,请控制克隆目录. +* 优化`git clean`标志,以确保删除或保留可能影响或加快构建速度的数据. + +## Shallow cloning[](#shallow-cloning "Permalink") + +在 GitLab Runner 8.9 中引入. + +默认情况下,GitLab 和 GitLab Runner 始终执行完整克隆. 虽然这意味着已收到来自 GitLab 的所有更改,但通常会导致接收额外的提交日志. + +理想情况下,您应始终使用`GIT_DEPTH` ,该数字应较小,例如 10.这将指示 GitLab Runner 执行浅表克隆. 浅克隆使 Git 仅请求给定分支的最新一组更改,最多达到`GIT_DEPTH`变量定义的所需提交`GIT_DEPTH` . + +这极大地加快了从 Git 存储库获取更改的速度,特别是如果存储库积压的事务由很多个大文件组成的积压很长时,因为我们有效地减少了数据传输量. + +以下示例使 GitLab Runner 浅表克隆仅获取给定的分支; 它不会获取任何其他分支或标签. + +``` +variables: + GIT_DEPTH: 10 + +test: + script: + - ls -al +``` + +## Git strategy[](#git-strategy "Permalink") + +在 GitLab Runner 8.9 中引入. + +默认情况下,GitLab 配置为始终首选`GIT_STRATEGY: fetch`策略. 如果在磁盘上找到`GIT_STRATEGY: fetch`策略,则会重新使用现有的工作树. 这与`GIT_STRATEGY: clone`策略不同, `GIT_STRATEGY: clone`一样,如果找到了工作树,则会在克隆之前将其删除. + +首选使用`fetch` ,因为它会减少要传输的数据量,并且不会真正影响您可能会从 CI 对存储库执行的操作. + +但是, `fetch`确实需要访问以前的工作树. 使用时,这种运作良好, `shell`或`docker`执行,因为这些努力保持 worktrees,默认情况下尽量重复使用它们. + +目前不适用于`kubernetes`执行器,并且在使用`kubernetes` `docker+machine`时有限制. `kubernetes`执行器总是克隆到临时目录中. + +GitLab 还提供了`GIT_STRATEGY: none`策略. 这会禁用任何由 GitLab 完成的`fetch`和`checkout`命令,要求您执行这些操作. + +## Git clone path[](#git-clone-path "Permalink") + +在 GitLab Runner 11.10 中引入. + +[`GIT_CLONE_PATH`](../yaml/README.html#custom-build-directories)允许您控制在何处克隆源. 如果您在 fork 工作流中大量使用大型存储库,则可能会产生影响. + +从 GitLab Runner 的角度来看,前叉工作流存储为具有单独工作树的单独存储库. 这意味着 GitLab Runner 无法优化工作树的使用,您可能必须指示 GitLab Runner 使用它. + +在这种情况下,理想情况下,您希望使 GitLab Runner 执行程序仅用于给定项目,而不是在不同项目之间共享,以使此过程更高效. + +[`GIT_CLONE_PATH`](../yaml/README.html#custom-build-directories)必须在`$CI_BUILDS_DIR` . 当前,不可能从磁盘选择任何路径. + +## Git clean flags[](#git-clean-flags "Permalink") + +在 GitLab Runner 11.10 中引入. + +[`GIT_CLEAN_FLAGS`](../yaml/README.html#git-clean-flags)允许您控制是否要求对每个 CI 作业执行`git clean`命令. 默认情况下,GitLab 确保您的工作树在给定的 SHA 上,并且您的存储库是干净的. + +设置为`none`时,将禁用[`GIT_CLEAN_FLAGS`](../yaml/README.html#git-clean-flags) . 在非常大的存储库上,这可能是理想的,因为`git clean`是磁盘 I / O 密集型的. 使用`GIT_CLEAN_FLAGS: -ffdx -e .build/`控制`GIT_CLEAN_FLAGS: -ffdx -e .build/` (例如)使您可以控制和禁用后续运行之间工作树中某些目录的删除,这可以加快增量生成的速度. 如果您重复使用现有计算机并拥有可用于构建的现有工作树,则效果最大. + +有关[`GIT_CLEAN_FLAGS`](../yaml/README.html#git-clean-flags)接受的确切参数,请参见[`git clean`](https://git-scm.com/docs/git-clean)的文档. 可用参数取决于 Git 版本. + +## Git fetch extra flags[](#git-fetch-extra-flags "Permalink") + +在 GitLab Runner 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4142) . + +[`GIT_FETCH_EXTRA_FLAGS`](../yaml/README.html#git-fetch-extra-flags) allows you to modify `git fetch` behavior by passing extra flags. + +有关更多信息,请参见[`GIT_FETCH_EXTRA_FLAGS`文档](../yaml/README.html#git-fetch-extra-flags) . + +## Fork-based workflow[](#fork-based-workflow "Permalink") + +在 GitLab Runner 11.10 中引入. + +遵循以上准则,让我们假设我们想要: + +* 针对大型项目进行优化(目录中有超过 5 万个文件). +* 使用基于分叉的工作流进行贡献. +* 重用现有的工作树. 预先配置了存储库的预配置运行器. +* 赛跑者仅分配给项目和所有分叉. + +让我们考虑以下两个示例,一个使用`shell` executor,另一个使用`docker` executor. + +### `shell` executor example[](#shell-executor-example "Permalink") + +假设您具有以下[`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) . + +``` +concurrent = 4 + +[[runners]] + url = "GITLAB_URL" + token = "TOKEN" + executor = "shell" + builds_dir = "/builds" + cache_dir = "/cache" + + [runners.custom_build_dir] + enabled = true +``` + +This `config.toml`: + +* 使用`shell`执行器, +* 指定一个自定义`/builds`目录,其中将存储所有克隆. +* 启用指定`GIT_CLONE_PATH` , +* 一次最多运行 4 个作业. + +### `docker` executor example[](#docker-executor-example "Permalink") + +假设您具有以下[`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) . + +``` +concurrent = 4 + +[[runners]] + url = "GITLAB_URL" + token = "TOKEN" + executor = "docker" + builds_dir = "/builds" + cache_dir = "/cache" + + [runners.docker] + volumes = ["/builds:/builds", "/cache:/cache"] +``` + +This `config.toml`: + +* 使用`docker` executor, +* 在磁盘上指定将存储所有克隆的自定义`/builds`目录. 我们在主机上挂载`/builds`目录,以使其在后续运行之间可重复使用,并允许其覆盖克隆策略. +* 默认情况下已启用,因此未启用指定`GIT_CLONE_PATH`功能. +* 一次最多运行 4 个作业. + +### Our `.gitlab-ci.yml`[](#our-gitlab-ciyml "Permalink") + +一旦配置了执行程序,就需要微调`.gitlab-ci.yml` . + +Our pipeline will be most performant if we use the following `.gitlab-ci.yml`: + +``` +variables: + GIT_DEPTH: 10 + GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_NAME + +build: + script: ls -al +``` + +上面配置了: + +* 浅克隆 10,以加快后续`git fetch`命令的速度. +* 自定义克隆路径,使我们可以在父项目和所有分支之间重用工作树,因为我们对所有分支使用相同的克隆路径. + +为什么要使用`$CI_CONCURRENT_ID` ? 主要原因是要确保使用的工作树在项目之间不冲突. `$CI_CONCURRENT_ID`表示给定执行器中的唯一标识符,因此只要我们使用它来构造路径,就可以确保该目录不会与其他正在运行的并发作业冲突. + +### Store custom clone options in `config.toml`[](#store-custom-clone-options-in-configtoml "Permalink") + +理想情况下,所有与作业相关的配置都应存储在`.gitlab-ci.yml` . 但是,有时希望使这些方案成为 Runner 配置的一部分. + +在以上 Forks 的示例中,使此配置对于用户可发现可能是首选,但这会带来管理开销,因为需要为每个分支更新`.gitlab-ci.yml` . 在这种情况下,可能希望保持`.gitlab-ci.yml`克隆路径不可知,但是将其配置为 Runner. + +我们可以使用以下规范扩展[`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) ,如果`.gitlab-ci.yml`不覆盖它,它将由 Runner 使用: + +``` +concurrent = 4 + +[[runners]] + url = "GITLAB_URL" + token = "TOKEN" + executor = "docker" + builds_dir = "/builds" + cache_dir = "/cache" + + environment = [ + "GIT_DEPTH=10", + "GIT_CLONE_PATH=$CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_NAME" + ] + + [runners.docker] + volumes = ["/builds:/builds", "/cache:/cache"] +``` + +这使得克隆配置成为给定 Runner 的一部分,并且不需要我们更新每个`.gitlab-ci.yml` . \ No newline at end of file diff --git a/docs/255.md b/docs/255.md new file mode 100644 index 0000000000000000000000000000000000000000..e64cc6b42df354242b07d1bef877bbc1a711fb4a --- /dev/null +++ b/docs/255.md @@ -0,0 +1,60 @@ +# Metrics Reports + +> 原文:[https://docs.gitlab.com/ee/ci/metrics_reports.html](https://docs.gitlab.com/ee/ci/metrics_reports.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [How it works](#how-it-works) +* [How to set it up](#how-to-set-it-up) +* [Advanced Example](#advanced-example) + +# Metrics Reports[](#metrics-reports-premium "Permalink") + +在[GitLab Premium](https://about.gitlab.com/pricing/) 11.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9788) . 需要 GitLab Runner 11.10 及更高版本. + +## Overview[](#overview "Permalink") + +GitLab 提供了许多用于[合并请求](../user/project/merge_requests/index.html)的出色报告工具[-JUnit 报告](junit_test_reports.html) , [代码质量](../user/project/merge_requests/code_quality.html) ,性能测试等.尽管 JUnit 是用于"通过"或"失败"的测试的出色开放框架,但查看其他类型的测试也很重要.给定更改的指标. + +您可以将作业配置为使用自定义指标报告,并且 GitLab 会在合并请求上显示报告,以便更轻松,更快速地识别更改而无需检查整个日志. + +[![Metrics Reports](img/a6d06d0c4a54ff34856e0fbc07a50a60.png)](img/metrics_reports_v13_0.png) + +## Use cases[](#use-cases "Permalink") + +考虑以下可以利用指标报告的数据示例: + +1. 内存使用情况 +2. 负载测试结果 +3. 代码复杂度 +4. 代码覆盖率统计 + +## How it works[](#how-it-works "Permalink") + +从指标报告中读取指标(默认值: `metrics.txt` ). 它们被解析并显示在 MR 小部件中. + +所有值都视为字符串,并且使用字符串比较来查找来自以下各项的最新可用`metrics`工件之间的差异: + +* `master` +* 功能分支 + +## How to set it up[](#how-to-set-it-up "Permalink") + +添加一个创建[指标报告](pipelines/job_artifacts.html#artifactsreportsmetrics-premium)的作业(默认文件名: `metrics.txt` ). 该文件应符合[OpenMetrics](https://openmetrics.io/)格式. + +例如: + +``` +metrics: + script: + - echo 'metric_name metric_value' > metrics.txt + artifacts: + reports: + metrics: metrics.txt +``` + +## Advanced Example[](#advanced-example "Permalink") + +OpenMetrics 文本文件的高级示例(来自[Prometheus 文档](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-format-example) )在合并请求小部件中呈现为: + +[![Metrics Reports Advanced](img/1ab2181cd0be5aa7d8e96f16a1348ef9.png)](img/metrics_reports_advanced_v13_0.png) \ No newline at end of file diff --git a/docs/256.md b/docs/256.md new file mode 100644 index 0000000000000000000000000000000000000000..66dd12cbf8e6f84b77dea5452c83da471109cc3b --- /dev/null +++ b/docs/256.md @@ -0,0 +1,498 @@ +# CI/CD pipelines + +> 原文:[https://docs.gitlab.com/ee/ci/pipelines/](https://docs.gitlab.com/ee/ci/pipelines/) + +* [Types of pipelines](#types-of-pipelines) +* [Configure a pipeline](#configure-a-pipeline) + * [View pipelines](#view-pipelines) + * [Run a pipeline manually](#run-a-pipeline-manually) + * [Run a pipeline by using a URL query string](#run-a-pipeline-by-using-a-url-query-string) + * [Add manual interaction to your pipeline](#add-manual-interaction-to-your-pipeline) + * [Start multiple manual actions in a stage](#start-multiple-manual-actions-in-a-stage) + * [Delete a pipeline](#delete-a-pipeline) + * [Pipeline quotas](#pipeline-quotas) + * [How pipeline duration is calculated](#how-pipeline-duration-is-calculated) + * [Pipeline security on protected branches](#pipeline-security-on-protected-branches) +* [View jobs in a pipeline](#view-jobs-in-a-pipeline) + * [See why a job failed](#see-why-a-job-failed) + * [The order of jobs in a pipeline](#the-order-of-jobs-in-a-pipeline) + * [Group jobs in a pipeline](#group-jobs-in-a-pipeline) + * [Specifying variables when running manual jobs](#specifying-variables-when-running-manual-jobs) + * [Delay a job](#delay-a-job) + * [Expand and collapse job log sections](#expand-and-collapse-job-log-sections) + * [Custom collapsible sections](#custom-collapsible-sections) +* [Visualize pipelines](#visualize-pipelines) + * [Regular pipeline graphs](#regular-pipeline-graphs) + * [Pipeline mini graphs](#pipeline-mini-graphs) + * [Pipeline success and duration charts](#pipeline-success-and-duration-charts) + * [Pipeline badges](#pipeline-badges) +* [Pipelines API](#pipelines-api) +* [Troubleshooting `fatal: reference is not a tree:`](#troubleshooting-fatal-reference-is-not-a-tree) + +# CI/CD pipelines[](#cicd-pipelines "Permalink") + +在 GitLab 8.8 中引入. + +**提示:**观看["精通持续软件开发"](https://about.gitlab.com/webcast/mastering-ci-cd/)网络广播,以观看 GitLab CI / CD 管道的全面演示. + +管道是持续集成,交付和部署的顶级组件. + +Pipelines comprise: + +* 作业,定义*要做*什么. 例如,编译或测试代码的作业. +* 阶段,定义*何时*运行作业. 例如,在编译代码的阶段之后运行测试的阶段. + +作业由[Runners](../runners/README.html)执行. 如果有足够的并发运行程序,则可以并行执行同一阶段中的多个作业. + +如果一个阶段中的*所有*作业*都*成功,则管道将继续进行下一个阶段. + +If *any* job in a stage fails, the next stage is not (usually) executed and the pipeline ends early. + +通常,管道是自动执行的,创建后就无需干预. 但是,有时您还可以手动与管道进行交互. + +典型的管道可能包含四个阶段,按以下顺序执行: + +* 一个`build`阶段,其工作称为`compile` . +* 一个`test`阶段,具有两个作业,分别称为`test1`和`test2` . +* `staging`阶段,其工作称为`deploy-to-stage` . +* `production`阶段,其工作称为`deploy-to-prod` . + +**注意:**如果您有[从 GitLab 提取镜像的存储库,则](../../user/project/repository/repository_mirroring.html#pulling-from-a-remote-repository-starter)可能需要在项目的**"设置">"存储库">"从远程存储库中提取">"触发管道更新镜像"中**启用管道触发. + +## Types of pipelines[](#types-of-pipelines "Permalink") + +管道可以通过许多不同的方式进行配置: + +* [基本管道](pipeline_architectures.html#basic-pipelines)在每个阶段同时运行所有内容,随后是下一阶段. +* [定向非循环图管线(DAG)管线](../directed_acyclic_graph/index.html)基于作业之间的关系,并且比基本管线运行得更快. +* [多项目管道](../multi_project_pipelines.html)将不同项目的[管道](../multi_project_pipelines.html)组合在一起. +* [父子管道](../parent_child_pipelines.html)将复杂的管道分解为一个父管道,该管道可以触发多个子管道,这些子管道都在同一项目中并以相同的 SHA 运行. +* [合并请求的管道仅针对合并请求](../merge_request_pipelines/index.html)运行(而不是针对每次提交). +* [合并结果管道](../merge_request_pipelines/pipelines_for_merged_results/index.html)是合并请求管道,其作用就像源分支的更改已被合并到目标分支一样. +* [合并列车](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)使用管道获取合并结果,以使合并一个接一个地排队. + +## Configure a pipeline[](#configure-a-pipeline "Permalink") + +在 CI / CD 管道配置文件中为每个项目定义了管道及其组件作业和阶段. + +* 作业是[基本的配置](../yaml/README.html#introduction)组件. +* 阶段是通过使用[`stages`](../yaml/README.html#stages)关键字定义的. + +有关 CI 管道文件中配置选项的列表,请参见《 [GitLab CI / CD 管道配置参考》](../yaml/README.html) . + +您还可以通过 GitLab UI 配置管道的特定方面. 例如: + +* 每个项目的[管道设置](settings.html) . +* [Pipeline schedules](schedules.html). +* [Custom CI/CD variables](../variables/README.html#custom-environment-variables). + +### View pipelines[](#view-pipelines "Permalink") + +您可以在项目的**CI / CD>管道**页面下找到当前和历史管道运行. 您还可以通过导航到" **管道"**选项卡来访问合并请求的**管道** . + +[![Pipelines index page](img/44be1cce97f886ea1f1c93950d764041.png)](img/pipelines_index_v13_0.png) + +单击管道将带您进入" **管道详细信息"**页面,并显示为该管道运行的作业. 在这里,您可以取消正在运行的管道,在发生故障的管道上重试作业或[删除管道](#delete-a-pipeline) . + +[从 GitLab 12.3 开始,](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/50499)可以在`/project/pipelines/[branch]/latest`找到指向给定分支的最后提交的最新管道的链接. 另外, `/project/pipelines/latest`会将您重定向到项目默认分支上最后一次提交的最新管道. + +[从 GitLab 13.0 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/215367) ,您可以通过以下方式过滤管道列表: + +* 触发作者 +* 分店名称 +* 状态( [自 GitLab 13.1 起](https://gitlab.com/gitlab-org/gitlab/-/issues/217617) ) +* 标签( [自 GitLab 13.1 起](https://gitlab.com/gitlab-org/gitlab/-/issues/217617) ) + +### Run a pipeline manually[](#run-a-pipeline-manually "Permalink") + +可以使用预定义或手动指定的[变量](../variables/README.html)手动执行管道. + +如果在管道的正常操作之外需要管道的结果(例如,代码生成),则可以执行此操作. + +要手动执行管道: + +1. 导航到项目的**CI / CD>管道** . +2. 单击**运行管道**按钮. +3. 在" **运行管道"**页面上: + 1. 在" **创建位置"**字段中选择要为其运行管道的分支. + 2. 输入管道运行所需的任何[环境变量](../variables/README.html) . + 3. 单击**创建管道**按钮. + +管道将按照配置执行作业. + +### Run a pipeline by using a URL query string[](#run-a-pipeline-by-using-a-url-query-string "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/24146) . + +您可以使用查询字符串来预填充" **运行管道"**页面. 例如,查询字符串`.../pipelines/new?ref=my_branch&var[foo]=bar&file_var[file_foo]=file_bar`将使用以下内容预填充" **运行管道"**页面: + +* **竞选** field: `my_branch`. +* **Variables** section: + * Variable: + * Key: `foo` + * Value: `bar` + * File: + * Key: `file_foo` + * Value: `file_bar` + +`pipelines/new` URL 的格式为: + +``` +.../pipelines/new?ref=&var[]=&file_var[]= +``` + +支持以下参数: + +* `ref` :指定用于填充" **运行为"**字段的分支. +* `var` :指定一个`Variable`变量. +* `file_var` :指定一个`File`变量. + +对于每个`var`或`file_var` ,都需要一个键和一个值. + +### Add manual interaction to your pipeline[](#add-manual-interaction-to-your-pipeline "Permalink") + +在 GitLab 8.15 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7931) . + +使用[`when:manual`](../yaml/README.html#whenmanual)参数配置的手动操作使您可以要求手动交互,然后才能在管道中继续前进. + +您可以直接从管道图执行此操作. 只需单击播放按钮即可执行该特定作业. + +例如,您的管道可能会自动启动,但是需要手动操作才能[部署到生产中](../environments/index.html#configuring-manual-deployments) . 在下面的示例中, `production`阶段有一个需要手动操作的工作. + +[![Pipelines example](img/d2f0725099f8a66ed235d537ea6592a4.png)](img/pipelines.png) + +#### Start multiple manual actions in a stage[](#start-multiple-manual-actions-in-a-stage "Permalink") + +在 GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27188) . + +可以使用"全部播放手动"按钮同时启动一个阶段中的多个手动动作. 用户单击此按钮后,将触发每个单独的手动操作并将其刷新为更新状态. + +此功能仅可用: + +* 至少具有开发者访问权限的用户. +* 如果阶段包含[手动操作](#add-manual-interaction-to-your-pipeline) . + +### Delete a pipeline[](#delete-a-pipeline "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/24851) . + +在项目中具有[所有者权限的](../../user/permissions.html)用户可以通过以下方式删除管道:单击**CI / CD>管道中的管道**以转到" **管道详细信息"**页面,然后使用" **删除"**按钮. + +[![Pipeline Delete Button](img/86614ecfb76f8a91344d98d3effa7d2a.png)](img/pipeline-delete.png) + +**警告:**删除管道将使所有管道缓存失效,并删除所有相关对象,例如构建,日志,工件和触发器. **此操作无法撤消.** + +### Pipeline quotas[](#pipeline-quotas "Permalink") + +每个用户都有一个个人管道配额,该配额跟踪所有个人项目中共享运行者的使用情况. 每个组都有一个[使用配额](../../subscriptions/index.html#ci-pipeline-minutes) ,该[配额](../../subscriptions/index.html#ci-pipeline-minutes)跟踪该组内创建的所有项目的共享运行器的使用. + +触发管道时,无论是谁触发的,都会使用项目所有者的[名称空间](../../user/group/index.html#namespaces)的管道配额. 在这种情况下,名称空间可以是拥有项目的用户或组. + +#### How pipeline duration is calculated[](#how-pipeline-duration-is-calculated "Permalink") + +给定管道的总运行时间不包括重试和挂起(排队)时间. + +每个作业都表示为一个`Period` ,它包括: + +* `Period#first` (作业开始时). +* `Period#last` (作业完成时). + +一个简单的例子是: + +* A(1、3) +* B(2,4) +* C(6、7) + +在示例中: + +* A 从 1 开始到 3 结束. +* B 从 2 开始到 4 结束. +* C 从 6 开始到 7 结束. + +在视觉上,它可以被视为: + +``` +0 1 2 3 4 5 6 7 + AAAAAAA + BBBBBBB + CCCC +``` + +A,B 和 C 的并集是(1、4)和(6、7). 因此,总运行时间为: + +``` +(4 - 1) + (7 - 6) => 4 +``` + +### Pipeline security on protected branches[](#pipeline-security-on-protected-branches "Permalink") + +在[受保护的分支](../../user/project/protected_branches.html)上执行管道时,将强制执行严格的安全模型. + +仅当[允许](../../user/project/protected_branches.html#using-the-allowed-to-merge-and-allowed-to-push-settings)用户[合并或推送到](../../user/project/protected_branches.html#using-the-allowed-to-merge-and-allowed-to-push-settings)该特定分支时,才可以在受保护的分支上执行以下操作: + +* 运行手动管道(使用[Web UI](#run-a-pipeline-manually)或[管道 API](#pipelines-api) ). +* 运行预定的管道. +* 使用触发器运行管道. +* 在现有管道上触发手动操作. +* 重试或取消现有作业(使用 Web UI 或管道 API). + +标记为**受保护的** **变量**只能由在受保护的分支上运行的作业访问,从而防止不受信任的用户意外访问敏感信息,如部署凭据和令牌. + +**运动员**标记为**保护**只能保护分支机构运行的作业,防止不可信代码在受保护亚军执行和不小心被访问保护部署密钥和其它凭证. 为了确保打算在受保护的运行程序上执行的作业不会使用常规运行程序,必须对它们进行相应标记. + +## View jobs in a pipeline[](#view-jobs-in-a-pipeline "Permalink") + +访问管道时,可以看到该管道的相关作业. + +单击单个作业将向您显示其作业日志,并允许您: + +* 取消作业. +* 重试该作业. +* 删除作业日志. + +### See why a job failed[](#see-why-a-job-failed "Permalink") + +在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17782) . + +当管道发生故障或被允许失败时,可以在几个地方找到原因: + +* 在[管道图中](#visualize-pipelines) ,在管道详细信息视图上. +* 在管道小部件中,在合并请求和提交页面中. +* 在工作视图中,在工作的全局视图和详细视图中. + +在每个地方,如果将鼠标悬停在失败的作业上,都可以看到失败的原因. + +[![Pipeline detail](img/b6069220bf06467d1d434d3652c5d82a.png)](img/job_failure_reason.png) + +在[GitLab 10.8](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17814)及更高版本中,您还可以在"作业详细信息"页面上查看其失败的原因. + +### The order of jobs in a pipeline[](#the-order-of-jobs-in-a-pipeline "Permalink") + +管道中作业的顺序取决于管道图的类型. + +* 对于[常规管道图](#regular-pipeline-graphs) ,按名称对作业进行排序. +* 对于[管道微型图](#pipeline-mini-graphs) ,将按严重性然后按名称对作业进行排序. + +严重性顺序为: + +* failed +* warning +* pending +* running +* manual +* scheduled +* canceled +* success +* skipped +* created + +例如: + +[![Pipeline mini graph sorting](img/9abb23a34d42854b307382ef64d9a013.png)](img/pipelines_mini_graph_sorting.png) + +### Group jobs in a pipeline[](#group-jobs-in-a-pipeline "Permalink") + +在 GitLab 8.12 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6242) . + +如果您有许多类似的工作,则[管道图](#visualize-pipelines)将变得很长且难以阅读. + +您可以自动将相似的作业分组在一起. 如果以某种方式格式化作业名称,它们将在常规管道图(而不是迷你图)中折叠为一组. + +如果看不到管道中的重试或取消按钮,您将知道管道何时将其分组. 将鼠标悬停在它们上面将显示分组的作业数. 单击以展开它们. + +[![Grouped pipelines](img/0d6a90afbcbb1f9414d4a9a8437e49f8.png)](img/pipelines_grouped.png) + +要创建一组作业,请在[CI / CD 管道配置文件中](../yaml/README.html) ,用数字和以下其中一个分隔每个作业名称: + +* 斜线( `/` ),例如`test 1/3` , `test 2/3` , `test 3/3` . +* 冒号( `:` )中,例如, `test 1:3` , `test 2:3` , `test 3:3` . +* 一个空格,例如`test 0 3` , `test 1 3` , `test 2 3` . + +您可以互换使用这些符号. + +例如,这三个作业将在一个名为`build ruby`的组中: + +``` +build ruby 1/3: + stage: build + script: + - echo "ruby1" + +build ruby 2/3: + stage: build + script: + - echo "ruby2" + +build ruby 3/3: + stage: build + script: + - echo "ruby3" +``` + +在管道中,结果是一个名为`build ruby`的组,具有三个作业: + +[![Job group](img/7bcf8d15daa1fb25935d7638acd8eb43.png)](img/job_group_v12_10.png) + +作业将通过从左到右比较数字进行排序. 通常,您希望第一个数字为索引,第二个数字为总数. + +[此正则表达式](https://gitlab.com/gitlab-org/gitlab/blob/2f3dc314f42dbd79813e6251792853bc231e69dd/app/models/commit_status.rb#L99)计算作业名称: `\d+[\s:\/\\]+\d+\s*` . + +### Specifying variables when running manual jobs[](#specifying-variables-when-running-manual-jobs "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30485) . + +运行手动作业时,您可以提供其他特定于作业的变量. + +您可以从要运行其他变量的手动作业的作业页面执行此操作. 要访问此页面,请在管道视图中单击手动作业的**名称** , *而不是*播放( )按钮. + +当您想要更改使用[自定义环境变量](../variables/README.html#custom-environment-variables)的作业的执行时,这很有用. 在此处添加变量名称(键)和值将覆盖[UI 或`.gitlab-ci.yml`](../variables/README.html#custom-environment-variables)定义的值,以供手动运行一次. + +[![Manual job variables](img/185cfb126a59b17e7d802717876f8725.png)](img/manual_job_variables.png) + +### Delay a job[](#delay-a-job "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21767) . + +当您不想立即运行作业时,可以使用[`when:delayed`](../yaml/README.html#whendelayed)参数将作业的执行延迟一定时间. + +这对于定时增量式部署特别有用,在这种情况下,新代码将逐步推出. + +例如,如果您开始推出新代码并执行以下操作: + +* 用户不会遇到麻烦,GitLab 可以从 0%到 100%自动完成部署. +* 用户在使用新代码时会遇到麻烦,您可以通过取消管道并[回滚](../environments/index.html#retrying-and-rolling-back)到最后一个稳定版本来停止定时增量推出. + +[![Pipelines example](img/3444bd33319e0b2d996233cf9e1103c5.png)](img/pipeline_incremental_rollout.png) + +### Expand and collapse job log sections[](#expand-and-collapse-job-log-sections "Permalink") + +在 GitLab 12.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14664) . + +作业日志分为可折叠或扩展的部分. 每个部分将显示持续时间. + +在以下示例中: + +* 两个部分已折叠并且可以展开. +* 三个部分被展开并且可以折叠. + +[![Collapsible sections](img/53dc09446080b42329a76d4ecbb64aa3.png)](img/collapsible_log_v12_6.png) + +#### Custom collapsible sections[](#custom-collapsible-sections "Permalink") + +您可以通过手动输出特殊代码来在作业日志中创建可折叠部分,GitLab 将使用这些特殊代码来确定要折叠的部分: + +* 节开始标记: `section_start:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + `TEXT_OF_SECTION_HEADER` +* 节结束标记: `section_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + +您必须将这些代码添加到 CI 配置的脚本部分. 例如,使用`echo` : + +``` +job1: + script: + - echo -e "section_start:`date +%s`:my_first_section\r\e[0KHeader of the 1st collapsible section" + - echo 'this line should be hidden when collapsed' + - echo -e "section_end:`date +%s`:my_first_section\r\e[0K" +``` + +在上面的示例中: + +* `date +%s` :Unix 时间戳(例如`1560896352` ). +* `my_first_section` :为节指定的名称. +* `\r\e[0K` :阻止区域标记显示在渲染的(彩色)作业日志中,但它们显示在原始作业日志中. 要查看它们,请在作业日志的右上方,单击 ( **显示完整的原始文件** ). + * `\r` :回车. + * `\e[0K` :清除 ANSI 转义代码. + +原始作业日志样本: + +``` +section_start:1560896352:my_first_section\r\e[0KHeader of the 1st collapsible section +this line should be hidden when collapsed +section_end:1560896353:my_first_section\r\e[0K +``` + +## Visualize pipelines[](#visualize-pipelines "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5742) . + +管道可以是具有许多顺序和并行作业的复杂结构. + +为了更容易理解管道的流程,GitLab 提供了管道图来查看管道及其状态. + +管道图可以两种不同的方式显示,具体取决于您从中访问该图的页面. + +**注意:** GitLab 在管线图中将各阶段的名称大写. + +### Regular pipeline graphs[](#regular-pipeline-graphs "Permalink") + +常规管道图显示每个阶段的作业名称. 当您在[单个管道页面](#view-pipelines)上时,可以找到常规管道图. 例如: + +[![Pipelines example](img/d2f0725099f8a66ed235d537ea6592a4.png)](img/pipelines.png) + +[多项目管道图可](../multi_project_pipelines.html#multi-project-pipeline-visualization-premium)帮助您可视化整个管道,包括所有跨项目的相互依存关系. + +### Pipeline mini graphs[](#pipeline-mini-graphs "Permalink") + +管道微型图占用的空间更少,并且可以一眼告诉您所有作业都通过还是失败. 当您导航到以下位置时,可以找到管道迷你图: + +* 管道索引页面. +* 单个提交页面. +* 合并请求页面. + +管道微型图使您可以查看一次提交的所有相关作业以及管道每个阶段的最终结果. 这使您可以快速查看失败的原因并进行修复. + +管道微型图中的阶段是可折叠的. 将鼠标悬停在他们上方,然后单击以展开他们的工作. + +| 迷你图 | 迷你图展开 | +| --- | --- | +| [![Pipelines mini graph](img/12e557e74666b1c90827cdd5bfe4d87a.png)](img/pipelines_mini_graph_simple.png) | [![Pipelines mini graph extended](img/28ba73ced40f830058c21c46c8291bfe.png)](img/pipelines_mini_graph.png) | + +### Pipeline success and duration charts[](#pipeline-success-and-duration-charts "Permalink") + +版本历史 + +* 在 GitLab 3.1.1 中作为"提交统计信息"引入,后来更名为"管线图". +* 在 GitLab 12.8 中[重命名](https://gitlab.com/gitlab-org/gitlab/-/issues/38318)为 CI / CD Analytics. + +GitLab 跟踪您的管道成功与失败的历史记录,以及每个管道的运行时间. 要查看此信息,请转到**分析> CI / CD 分析** . + +查看成功的管道: + +[![Successful pipelines](img/a88692f85b1b05ca94199204a3cc1f00.png)](img/pipelines_success_chart.png) + +查看管道持续时间历史记录: + +[![Pipeline duration](img/6867e53bf251ef0cb0e190c2e702d188.png)](img/pipelines_duration_chart.png) + +### Pipeline badges[](#pipeline-badges "Permalink") + +管道状态和测试覆盖率报告标记可用于每个项目,并可对其进行配置. 有关将管道标记添加到项目的信息,请参见[管道标记](settings.html#pipeline-badges) . + +## Pipelines API[](#pipelines-api "Permalink") + +GitLab 提供 API 端点以: + +* 执行基本功能. 有关更多信息,请参见[Pipelines API](../../api/pipelines.html) . +* 维护管道时间表. 有关更多信息,请参见[管道时间表 API](../../api/pipeline_schedules.html) . +* 触发管道运行. 有关更多信息,请参见: + * [通过 API 触发管道](../triggers/README.html) . + * [管道触发器 API](../../api/pipeline_triggers.html) . + +## Troubleshooting `fatal: reference is not a tree:`[](#troubleshooting-fatal-reference-is-not-a-tree "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17043) . + +以前,当您强制将分支推入其远程存储库时,会遇到意外的管道故障. 为了说明问题,假设您已经拥有当前的工作流程: + +1. 用户创建一个名为`example`的功能分支并将其推送到远程存储库. +2. 新的管道开始在`example`分支上运行. +3. 用户将`example`分支基于最新的`master`分支,然后将其强制推送到其远程存储库. +4. 新的管道再次在`example`分支上运行,但是,先前的管道(2)由于`fatal: reference is not a tree:`错误`fatal: reference is not a tree:`失败. + +这是因为先前的管道无法从`example`分支中找到校验历史 SHA(与管道记录相关联),该历史历史已被强制推送覆盖. 同样,由于[相同的原因](../merge_request_pipelines/pipelines_for_merged_results/index.html#intermittently-pipelines-fail-by-fatal-reference-is-not-a-tree-error) [,合并结果的管道](../merge_request_pipelines/pipelines_for_merged_results/index.html)可能会间歇性地失败. + +从 GitLab 12.4 开始,我们通过专门保留管道引用来改善了这种行为. 为了说明其生命周期: + +1. 在名为`example`的功能分支上创建了管道. +2. 在`refs/pipelines/`创建一个持久的管道 ref,该`refs/pipelines/`保留相关管道记录的 checkout-SHA. 即使在`example`分支的提交历史记录已被强制推送覆盖的情况下,该持久引用在管道执行期间也保持不变. +3. GitLab Runner fetches the persistent pipeline ref and gets source code from the checkout-SHA. +4. 管道完成后,将在后台进程中清除其持久引用. \ No newline at end of file diff --git a/docs/257.md b/docs/257.md new file mode 100644 index 0000000000000000000000000000000000000000..afba6d3365b7f3261f1ec8dddaa784e53af3ec6e --- /dev/null +++ b/docs/257.md @@ -0,0 +1,217 @@ +# Pipeline Architecture + +> 原文:[https://docs.gitlab.com/ee/ci/pipelines/pipeline_architectures.html](https://docs.gitlab.com/ee/ci/pipelines/pipeline_architectures.html) + +* [Basic Pipelines](#basic-pipelines) +* [Directed Acyclic Graph Pipelines](#directed-acyclic-graph-pipelines) +* [Child / Parent Pipelines](#child--parent-pipelines) + +# Pipeline Architecture[](#pipeline-architecture "Permalink") + +管道是 GitLab 中 CI / CD 的基本构建块. 本页记录了一些与它们有关的重要概念. + +构造管道的主要方法有三种,每种都有自己的优势. 如果需要,可以混合使用以下方法: + +* [基本](#basic-pipelines) :适用于简单的项目,其中所有配置都在一个易于查找的位置. +* [有向无环图](#directed-acyclic-graph-pipelines) :适用于需要有效执行的大型,复杂项目. +* [子级/父级管道](#child--parent-pipelines) :适用于具有大量独立定义组件的 monorepos 和项目. + +有关下面使用的任何关键字的更多详细信息,请查看我们的[CI YAML 参考](../yaml/README.html)以获取详细信息. + +## Basic Pipelines[](#basic-pipelines "Permalink") + +这是 GitLab 中最简单的管道. 它会在构建阶段同时运行所有内容,一旦所有这些操作完成,它将以相同的方式在测试阶段运行所有内容,依此类推. 它不是最有效的,并且如果您有很多步骤,它可能会变得非常复杂,但更易于维护: + +图 LR 子图部署阶段部署-> deploy_a 部署-> deploy_b 结束子图测试阶段测试-> test_a 测试-> test_b 结束子图构建阶段构建-> build_a 构建-> build_b 结束 build_a -.->测试 build_b -.->测试 test_a -.->部署 test_b -.->部署 + +匹配该图的示例基本`/.gitlab-ci.yml`管道配置: + +``` +stages: + - build + - test + - deploy + +image: alpine + +build_a: + stage: build + script: + - echo "This job builds something." + +build_b: + stage: build + script: + - echo "This job builds something else." + +test_a: + stage: test + script: + - echo "This job tests something. It will only run when all jobs in the" + - echo "build stage are complete." + +test_b: + stage: test + script: + - echo "This job tests something else. It will only run when all jobs in the" + - echo "build stage are complete too. It will start at about the same time as test_a." + +deploy_a: + stage: deploy + script: + - echo "This job deploys something. It will only run when all jobs in the" + - echo "test stage complete." + +deploy_b: + stage: deploy + script: + - echo "This job deploys something else. It will only run when all jobs in the" + - echo "test stage complete. It will start at about the same time as deploy_a." +``` + +## Directed Acyclic Graph Pipelines[](#directed-acyclic-graph-pipelines "Permalink") + +如果效率对您很重要,并且您希望所有内容尽快运行,则可以使用有向无[环图(DAG)](../directed_acyclic_graph/index.html) . 使用[`needs`关键字](../yaml/README.html#needs)定义作业之间的依赖关系. 当 GitLab 知道您的工作之间的关系时,它可以尽快运行所有内容,甚至在可能的情况下跳入后续阶段. + +在下面的示例中,如果`build_a`和`test_a`的速度比`build_b`和`test_b` ,则即使`build_b`仍在运行,GitLab 也会启动`deploy_a` . + +使用 DAG build_a-> test_a-> deploy_a build_b-> test_b-> deploy_b 结束的图 LR 子图管道 + +匹配该图的示例 DAG `/.gitlab-ci.yml`配置: + +``` +stages: + - build + - test + - deploy + +image: alpine + +build_a: + stage: build + script: + - echo "This job builds something quickly." + +build_b: + stage: build + script: + - echo "This job builds something else slowly." + +test_a: + stage: test + needs: [build_a] + script: + - echo "This test job will start as soon as build_a finishes." + - echo "It will not wait for build_b, or other jobs in the build stage, to finish." + +test_b: + stage: test + needs: [build_b] + script: + - echo "This test job will start as soon as build_b finishes." + - echo "It will not wait for other jobs in the build stage to finish." + +deploy_a: + stage: deploy + needs: [test_a] + script: + - echo "Since build_a and test_a run quickly, this deploy job can run much earlier." + - echo "It does not need to wait for build_b or test_b." + +deploy_b: + stage: deploy + needs: [test_b] + script: + - echo "Since build_b and test_b run slowly, this deploy job will run much later." +``` + +## Child / Parent Pipelines[](#child--parent-pipelines "Permalink") + +在上面的示例中,很明显,我们可以独立构建两种类型的东西. 这是通过[`trigger`关键字](../yaml/README.html#trigger)使用" [子/父管道"](../parent_child_pipelines.html)的理想情况. 它将配置分成多个文件,使事情变得非常简单. 您还可以将其与: + +* [`rules`关键字](../yaml/README.html#rules) :例如,仅在对该区域进行更改时才触发子管道. +* [`include`关键字](../yaml/README.html#include) :引入常见行为,确保您不会重复自己. +* 子[管道](#directed-acyclic-graph-pipelines)内部的[DAG 管道](#directed-acyclic-graph-pipelines) ,实现了两者的好处. + +graph LR subgraph Parent pipeline trigger_a -.-> build_a trigger_b -.-> build_b subgraph child pipeline B build_b --> test_b --> deploy_b end subgraph child pipeline A build_a --> test_a --> deploy_a end end + +匹配该图的父管道的示例`/.gitlab-ci.yml`配置: + +``` +stages: + - triggers + +trigger_a: + stage: triggers + trigger: + include: a/.gitlab-ci.yml + rules: + - changes: + - a/* + +trigger_b: + stage: triggers + trigger: + include: b/.gitlab-ci.yml + rules: + - changes: + - b/* +``` + +例如孩子`a`管道配置,位于`/a/.gitlab-ci.yml` ,利用的 DAG `needs:`关键字: + +``` +stages: + - build + - test + - deploy + +image: alpine + +build_a: + stage: build + script: + - echo "This job builds something." + +test_a: + stage: test + needs: [build_a] + script: + - echo "This job tests something." + +deploy_a: + stage: deploy + needs: [test_a] + script: + - echo "This job deploys something." +``` + +子`b`管道配置示例位于`/b/.gitlab-ci.yml` ,利用 DAG `needs:`关键字: + +``` +stages: + - build + - test + - deploy + +image: alpine + +build_b: + stage: build + script: + - echo "This job builds something else." + +test_b: + stage: test + needs: [build_b] + script: + - echo "This job tests something else." + +deploy_b: + stage: deploy + needs: [test_b] + script: + - echo "This job deploys something else." +``` + +也可以将作业设置为在触发子管道之前或之后运行,例如,如果您具有通用的设置步骤或最后进行统一部署. \ No newline at end of file diff --git a/docs/258.md b/docs/258.md new file mode 100644 index 0000000000000000000000000000000000000000..a47dbd01d69b4558031df4584245ba0c9ffed6be --- /dev/null +++ b/docs/258.md @@ -0,0 +1,92 @@ +# Directed Acyclic Graph + +> 原文:[https://docs.gitlab.com/ee/ci/directed_acyclic_graph/](https://docs.gitlab.com/ee/ci/directed_acyclic_graph/) + +* [Use cases](#use-cases) +* [Usage](#usage) +* [Limitations](#limitations) +* [DAG Visualization](#dag-visualization) + * [Enable or disable DAG Visualization](#enable-or-disable-dag-visualization-core-only) + +# Directed Acyclic Graph[](#directed-acyclic-graph "Permalink") + +版本历史 + +* 在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47063) . +* 在 GitLab 12.10 中[已删除功能标记](https://gitlab.com/gitlab-org/gitlab/-/issues/206902) . + +可以在 CI / CD 管道的上下文中使用有[向无环图,](https://www.techopedia.com/definition/5739/directed-acyclic-graph-dag)以建立作业之间的关系,从而以最快的方式执行,而不管如何设置阶段. + +例如,您可能拥有特定的工具或单独的网站,这些网站是作为主项目的一部分而构建的. 使用 DAG,您可以指定这些作业之间的关系,然后 GitLab 将尽快执行作业,而不是等待每个阶段完成. + +与其他针对 CI / CD 的 DAG 解决方案不同,GitLab 不需要您选择其中一个. 您可以在单个管道中实现 DAG 和传统的基于阶段的操作的混合组合. 配置非常简单,只需一个关键字即可为任何作业启用该功能. + +考虑如下的 monorepo: + +``` +./service_a +./service_b +./service_c +./service_d +``` + +它具有如下所示的管道: + +| build | test | deploy | +| --- | --- | --- | +| build_a | test_a | deploy_a | +| build_b | test_b | deploy_b | +| build_c | test_c | deploy_c | +| build_d | test_d | deploy_d | + +使用 DAG,您可以将`_a`作业与`_b`作业彼此关联,即使服务`a`构建时间很长,服务`b`也不会等待它,并且会尽快完成. 在这个非常相同的管道中, `_c`和`_d`可以单独放置,并且可以像任何普通的 GitLab 管道一样以分段的顺序一起运行. + +## Use cases[](#use-cases "Permalink") + +DAG 可以帮助解决 CI / CD 管道中作业之间的几种不同类型的关系. 最典型的情况是,当作业需要展开或展开和/或合并回去时(钻石相关性),这可以解决. 当您处理多平台构建或复杂的依赖关系网时,例如在操作系统构建或可独立部署但相关的微服务的复杂部署图中,可能会发生这种情况. + +此外,DAG 可以帮助提高管道的总体速度,并有助于提供快速反馈. 通过创建不会相互阻塞的依赖关系,您的管道将尽可能快地运行,而不管管道的阶段如何,从而确保开发人员可以尽快获得输出(包括错误). + +## Usage[](#usage "Permalink") + +使用[`needs:`关键字](../yaml/README.html#needs)定义作业之间的关系. + +请注意, `needs:`也可与[parallel](../yaml/README.html#parallel)关键字一起使用,从而为管道内的[并行化](../yaml/README.html#parallel)提供了强大的选项. + +## Limitations[](#limitations "Permalink") + +有向无环图是一个复杂的功能,从最初的 MVC 开始,您可能需要解决某些用例. 想要查询更多的信息: + +* [`needs` requirements and limitations](../yaml/README.html#requirements-and-limitations). +* 相关的史诗[跟踪计划的改进](https://gitlab.com/groups/gitlab-org/-/epics/1716) . + +## DAG Visualization[](#dag-visualization "Permalink") + +版本历史 + +* 在 GitLab 13.1 中作为[Beta 功能](https://about.gitlab.com/handbook/product/#beta) [引入](https://gitlab.com/gitlab-org/gitlab/-/issues/215517) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* [默认情况下](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36802)在 13.2 中[启用](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36802) . +* 在 GitLab.com 上启用了它. +* 对于 GitLab 自我管理的实例,GitLab 管理员可以选择[禁用它](#enable-or-disable-dag-visualization-core-only) . + +通过 DAG 可视化,可以更轻松地可视化 DAG 中依赖作业之间的关系. 此图将显示管道中需要或其他作业需要的所有作业. 没有关系的作业不会显示在该视图中. + +[![DAG visualization example](img/33ae5f16a8ad7c683e894a2a3032cfa9.png)](img/dag_graph_example_v13_1.png) + +单击节点将突出显示其依赖的所有作业路径. + +[![DAG visualization with path highlight](img/61dd95f1efb048c48f6ab843e79120d0.png)](img/dag_graph_example_clicked_v13_1.png) + +### Enable or disable DAG Visualization[](#enable-or-disable-dag-visualization-core-only "Permalink") + +DAG 可视化正在开发中,但已作为 Beta 功能提供,因此用户可以检查其限制和用途. + +它部署在**默认情况下启用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../administration/feature_flags.html)可以选择为您的实例禁用它: + +``` +# Instance-wide +Feature.disable(:dag_pipeline_tab) +# or by project +Feature.disable(:dag_pipeline_tab, Project.find()) +``` \ No newline at end of file diff --git a/docs/259.md b/docs/259.md new file mode 100644 index 0000000000000000000000000000000000000000..c8ce11892168b9f762aaf982ff109107c3639fb1 --- /dev/null +++ b/docs/259.md @@ -0,0 +1,219 @@ +# Multi-project pipelines + +> 原文:[https://docs.gitlab.com/ee/ci/multi_project_pipelines.html](https://docs.gitlab.com/ee/ci/multi_project_pipelines.html) + +* [Use cases](#use-cases) +* [Multi-project pipeline visualization](#multi-project-pipeline-visualization-premium) +* [Triggering multi-project pipelines through API](#triggering-multi-project-pipelines-through-api) +* [Creating multi-project pipelines from `.gitlab-ci.yml`](#creating-multi-project-pipelines-from-gitlab-ciyml) + * [Triggering a downstream pipeline using a bridge job](#triggering-a-downstream-pipeline-using-a-bridge-job) + * [Specifying a downstream pipeline branch](#specifying-a-downstream-pipeline-branch) + * [Passing variables to a downstream pipeline](#passing-variables-to-a-downstream-pipeline) + * [Mirroring status from triggered pipeline](#mirroring-status-from-triggered-pipeline) + * [Mirroring status from upstream pipeline](#mirroring-status-from-upstream-pipeline) + * [Limitations](#limitations) +* [Trigger a pipeline when an upstream project is rebuilt](#trigger-a-pipeline-when-an-upstream-project-is-rebuilt) + +# Multi-project pipelines[](#multi-project-pipelines "Permalink") + +版本历史 + +* 在 GitLab 7.14 中作为构建触发器[引入](https://about.gitlab.com/releases/2015/08/22/gitlab-7-14-released/#build-triggers-api-gitlab-ci) . +* 在 GitLab 12.8 中的所有层中[均可](https://gitlab.com/gitlab-org/gitlab/-/issues/199224)用. + +您可以跨多个项目设置[GitLab CI / CD](README.html) ,以便一个项目中的管道可以触发另一个项目中的管道. + +GitLab CI / CD 是一个功能强大的持续集成工具,不仅适用于每个项目,而且适用于具有多项目管道的项目. + +多项目管道对于需要跨项目相互依赖的较大产品很有用,例如采用[微服务架构的产品](https://about.gitlab.com/blog/2016/08/16/trends-in-version-control-land-microservices/) . + +有关跨功能开发团队如何使用跨管道触发来为不同的微服务项目触发多个管道的演示,请参阅[跨项目管道触发和可视化](https://about.gitlab.com/handbook/marketing/product-marketing/demo/#cross-project-pipeline-triggering-and-visualization-may-2019---1110) . + +此外,还可以可视化整个管道,包括所有跨项目的相互依存关系. + +## Use cases[](#use-cases "Permalink") + +Let’s assume you deploy your web app from different projects in GitLab: + +* 一个免费版本,它有自己的管道来构建和测试您的应用 +* 一个用于付费版本的附加组件,还可以通过构建和测试 +* 一个用于文档的文档,该文档还使用 SSG 进行构建,测试和部署 + +使用多项目管道,您可以可视化整个管道,包括三个项目的所有构建和测试阶段. + +## Multi-project pipeline visualization[](#multi-project-pipeline-visualization-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2121) in [GitLab Premium 9.3](https://about.gitlab.com/releases/2017/06/22/gitlab-9-3-released/#multi-project-pipeline-graphs). + +为项目配置 GitLab CI / CD 时,可以在[管道图](pipelines/index.html#visualize-pipelines)上可视化[作业](pipelines/index.html#configure-a-pipeline)的阶段. + +[![Multi-project pipeline graph](img/8013884e699eb543397343ba53b7f107.png)](img/multi_project_pipeline_graph.png) + +在"合并请求"小组件中,将显示多项目管道微型图,并且当悬停或轻击(在触摸屏设备上)时,它们将展开并显示为彼此相邻. + +[![Multi-project mini graph](img/c4c2d27f307636160d5773556cb14345.png)](img/multi_pipeline_mini_graph.gif) + +## Triggering multi-project pipelines through API[](#triggering-multi-project-pipelines-through-api "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 9.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2017)了`CI_JOB_TOKEN`在多项目管道中的使用. +* 在 GitLab 12.4 的所有层中都[可以](https://gitlab.com/gitlab-org/gitlab/-/issues/31573)将`CI_JOB_TOKEN`用于多项目管道. + +当您使用[`CI_JOB_TOKEN`触发管道时](triggers/README.html#ci-job-token) ,GitLab 会识别作业令牌的来源,因此在内部将这些管道[`CI_JOB_TOKEN`](triggers/README.html#ci-job-token)在一起,从而可以在管道图上可视化它们的关系. + +通过显示上游和下游管道依存关系的入站和出站连接,可以在管道图中显示这些关系. + +## Creating multi-project pipelines from `.gitlab-ci.yml`[](#creating-multi-project-pipelines-from-gitlab-ciyml "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) . +* 在 12.8 中[可](https://gitlab.com/gitlab-org/gitlab/-/issues/199224)用于所有层. + +### Triggering a downstream pipeline using a bridge job[](#triggering-a-downstream-pipeline-using-a-bridge-job "Permalink") + +在 GitLab 11.8 之前,有必要实现一个管道作业,该作业负责发出 API 请求[以触​​发](#triggering-multi-project-pipelines-through-api)另一个项目中[的管道](#triggering-multi-project-pipelines-through-api) . + +在 GitLab 11.8 中,GitLab 提供了新的 CI / CD 配置语法,使此任务更容易,并且避免需要 GitLab Runner 来触发跨项目管道. 下图说明了配置桥接作业: + +``` +rspec: + stage: test + script: bundle exec rspec + +staging: + variables: + ENVIRONMENT: staging + stage: deploy + trigger: my/deployment +``` + +在上面的示例中,一旦`rspec`作业在`test`阶段成功完成,则将启动`staging`桥作业. 该作业的初始状态将`pending` . manbetx 客户端打不开将在`my/deployment`项目中创建一个下游管道,并且,一旦创建管道, `staging`作业将成功. `my/deployment`是该项目的完整路径. + +创建上游管道的用户需要具有对下游项目的访问权限(在本例中为`my/deployment` ). 如果找不到下游项目,或者用户没有访问权限以在其中创建管道,则`staging`作业将被标记为*failed* . + +**警告:**在该示例中,一旦创建了下游管道,该`staging`将被标记为成功. 如果要显示下游管道的状态,请参阅[从触发的管道镜像状态](#mirroring-status-from-triggered-pipeline) .**注意:**对于常规作业,网桥作业不支持用户可以使用的每个配置条目. Runner 不会选择 Bridge 作业,因此添加对`script`支持毫无意义. 如果用户尝试使用不受支持的配置语法,则在创建管道时,YAML 验证将失败. + +### Specifying a downstream pipeline branch[](#specifying-a-downstream-pipeline-branch "Permalink") + +可以指定下游管道将使用的分支名称: + +``` +rspec: + stage: test + script: bundle exec rspec + +staging: + stage: deploy + trigger: + project: my/deployment + branch: stable-11-2 +``` + +Use: + +* `project`关键字,用于指定下游项目的完整路径. +* 该`branch`关键字指定由指定的项目分支的名称`project` . [从 GitLab 12.4 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/10126) ,支持变量扩展. + +在创建下游管道时,GitLab 将使用当前在分支的 HEAD 上的提交. + +### Passing variables to a downstream pipeline[](#passing-variables-to-a-downstream-pipeline "Permalink") + +有时您可能想将变量传递到下游管道. 您可以使用`variables`关键字来执行此操作,就像定义常规作业时一样. + +``` +rspec: + stage: test + script: bundle exec rspec + +staging: + variables: + ENVIRONMENT: staging + stage: deploy + trigger: my/deployment +``` + +`ENVIRONMENT`变量将传递到下游管道中定义的每个作业. 当 GitLab Runner 选择工作时,它将作为环境变量使用. + +在以下配置中, `MY_VARIABLE`变量将传递到在`trigger-downstream`作业排队时创建的下游管道. 这是因为`trigger-downstream`作业继承了在全局变量块中声明的变量,然后将这些变量传递到下游管道. + +``` +variables: + MY_VARIABLE: my-value + +trigger-downstream: + variables: + ENVIRONMENT: something + trigger: my/project +``` + +您可能想使用例如预定义的变量传递有关上游管道的一些信息. 为此,您可以使用插值传递任何变量. 例如: + +``` +downstream-job: + variables: + UPSTREAM_BRANCH: $CI_COMMIT_REF_NAME + trigger: my/project +``` + +在这种情况下,具有与上游管道相关的值的`UPSTREAM_BRANCH`变量将传递到`downstream-job`作业,并在所有下游构建的上下文中可用. + +**提示:**上游管道优先于下游管道. 如果在上游和下游项目中定义了两个具有相同名称的变量,则在上游项目中定义的变量将优先. + +### Mirroring status from triggered pipeline[](#mirroring-status-from-triggered-pipeline "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/11238) . +* 在 12.8 中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) GitLab Core. + +您可以使用`strategy: depend`将镜像状态从触发的管道镜像到源网桥作业. 例如: + +``` +trigger_job: + trigger: + project: my/project + strategy: depend +``` + +### Mirroring status from upstream pipeline[](#mirroring-status-from-upstream-pipeline "Permalink") + +您可以使用`needs:pipeline`关键字将管道状态从上游管道镜像到桥作业. 来自主服务器的最新管道状态将复制到桥接作业. + +Example: + +``` +upstream_bridge: + stage: test + needs: + pipeline: other/project +``` + +### Limitations[](#limitations "Permalink") + +由于网桥作业与常规作业略有不同,因此此处无法使用完全相同的配置语法,就像在定义要由跑步者选择的常规作业时通常使用的配置语法一样. + +某些功能尚未实现. 例如,对环境的支持. + +可用于网桥作业的[配置关键字](yaml/README.html)是: + +* `trigger` (定义下游管道触发器) +* `stage` +* `allow_failure` +* [`rules`](yaml/README.html#rules) +* `only` and `except` +* `when` (仅适用于`on_success` , `on_failure`和`always`值为) +* `extends` + +## Trigger a pipeline when an upstream project is rebuilt[](#trigger-a-pipeline-when-an-upstream-project-is-rebuilt "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9045) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.8. + +You can trigger a pipeline in your project whenever a pipeline finishes for a new tag in a different project: + +1. 转到项目的**"设置">" CI / CD"**页面,然后展开" **管道订阅"**部分. +2. 输入您要订阅的项目的路径. +3. 单击订阅. + +现在,成功完成已订阅项目中新标签的任何管道都将在当前项目的默认分支上触发管道. 对于上游和下游项目,上游管道订阅的最大数量为 2. \ No newline at end of file diff --git a/docs/260.md b/docs/260.md new file mode 100644 index 0000000000000000000000000000000000000000..f817a4a7caba999eceac25dee1ede8ee2fd48902 --- /dev/null +++ b/docs/260.md @@ -0,0 +1,133 @@ +# Parent-child pipelines + +> 原文:[https://docs.gitlab.com/ee/ci/parent_child_pipelines.html](https://docs.gitlab.com/ee/ci/parent_child_pipelines.html) + +* [Examples](#examples) +* [Merge Request child pipelines](#merge-request-child-pipelines) +* [Dynamic child pipelines](#dynamic-child-pipelines) +* [Limitations](#limitations) + +# Parent-child pipelines[](#parent-child-pipelines "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/16094) . + +随着管道变得越来越复杂,一些相关的问题开始出现: + +* 分阶段的结构(其中一个阶段的所有步骤必须在下一阶段的第一个作业开始之前完成)会导致任意等待,从而使事情变慢. +* 单个全局管道的配置变得非常漫长和复杂,使其难以管理. +* 使用[`include`](yaml/README.html#include)导入会增加配置的复杂性,并可能在无意间复制作业的情况下发生名称空间冲突. +* 如此多的工作和阶段可以使流水线用户体验变得笨拙. + +此外,有时管道的行为需要更动态. 选择启动(或不启动)子管道的功能是一项强大的功能,尤其是在动态生成 YAML 的情况下. + +[![Parent pipeline graph expanded](img/c5d0cec2b61194796c06f7c2c5294294.png)](img/parent_pipeline_graph_expanded_v12_6.png) + +与[多项目管道](multi_project_pipelines.html)类似,管道可以触发一组同时运行的子管道,但是在同一项目中: + +* 子管道仍按阶段顺序执行其每个作业,但可以自由地继续执行各个阶段,而不必等待父管道中无关的作业完成. +* 该配置分为较小的子管道配置,这些子管道配置更易于理解. 这减少了理解整体配置的认知负担. +* 导入在子管道级别进行,从而减少了发生冲突的可能性. +* 每个管道只有相关的步骤,因此更容易理解正在发生的事情. + +子管道可与其他 GitLab CI / CD 功能配合使用: + +* [`only: changes`](yaml/README.html#onlychangesexceptchanges)仅在某些文件更改时才触发管道. 例如,这对于 monorepos 很有用. +* 由于`.gitlab-ci.yml`的父管道和子管道都像普通管道一样运行,因此它们可以具有自己的行为和与触发器相关的顺序. + +所有这些都将与[`include:`](yaml/README.html#include)功能一起使用,因此您可以组成子管道配置. + +有关概述,请参见[父子管道功能演示](https://youtu.be/n8KpBSqZNbk) . + +## Examples[](#examples "Permalink") + +最简单的情况是使用本地 YAML 文件定义管道配置来[触发子管道](yaml/README.html#trigger) . 在这种情况下,父管道将触发子管道,并继续运行而无需等待: + +``` +microservice_a: + trigger: + include: path/to/microservice_a.yml +``` + +组成子管道时可以包含多个文件: + +``` +microservice_a: + trigger: + include: + - local: path/to/microservice_a.yml + - template: SAST.gitlab-ci.yml +``` + +**注意:** `trigger:include:`可接受的最大条目数为三. + +类似于[多项目管道](multi_project_pipelines.html#mirroring-status-from-triggered-pipeline) ,我们可以在完成时将父管道设置为依赖于子管道的状​​态: + +``` +microservice_a: + trigger: + include: + - local: path/to/microservice_a.yml + - template: SAST.gitlab-ci.yml + strategy: depend +``` + +## Merge Request child pipelines[](#merge-request-child-pipelines "Permalink") + +要将子管道触发为[合并请求管道,](merge_request_pipelines/index.html)我们需要: + +* 将触发器作业设置为在合并请求上运行: + +``` +# parent .gitlab-ci.yml +microservice_a: + trigger: + include: path/to/microservice_a.yml + rules: + - if: $CI_MERGE_REQUEST_ID +``` + +* 通过以下任一方式配置子管道: + + * 设置子管道中的所有作业以在合并请求的上下文中进行评估: + + ``` + # child path/to/microservice_a.yml + workflow: + rules: + - if: $CI_MERGE_REQUEST_ID + + job1: + script: ... + + job2: + script: ... + ``` + + * Alternatively, setting the rule per job. For example, to create only `job1` in the context of merge request pipelines: + + ``` + # child path/to/microservice_a.yml + job1: + script: ... + rules: + - if: $CI_MERGE_REQUEST_ID + + job2: + script: ... + ``` + +## Dynamic child pipelines[](#dynamic-child-pipelines "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/35632) . + +您可以定义一个作业,该作业运行您自己的脚本来生成 YAML 文件,而不是从静态 YAML 文件运行子管道,然后将其[用于触发子管道](yaml/README.html#trigger-child-pipeline-with-generated-configuration-file) . + +该技术在生成针对更改内容的流水线或构建目标和体系结构矩阵方面可能非常强大. + +有关概述,请参阅[使用动态生成的配置创建子管道](https://youtu.be/nMdfus2JWHM) . + +在 GitLab 12.9 中,在某些情况下可能无法创建子管道,从而导致父管道失败. 这[在 GitLab 12.10 中](https://gitlab.com/gitlab-org/gitlab/-/issues/209070)已[解决](https://gitlab.com/gitlab-org/gitlab/-/issues/209070) . + +## Limitations[](#limitations "Permalink") + +父管道可以触发许多子管道,但是子管道不能触发其他子管道. 请参阅[相关问题,](https://gitlab.com/gitlab-org/gitlab/-/issues/29651)以获取有关未来可能改进的讨论. \ No newline at end of file diff --git a/docs/261.md b/docs/261.md new file mode 100644 index 0000000000000000000000000000000000000000..fac49c3451c026d1b3d6797e05525d962cf5c4ca --- /dev/null +++ b/docs/261.md @@ -0,0 +1,186 @@ +# Pipelines for Merge Requests + +> 原文:[https://docs.gitlab.com/ee/ci/merge_request_pipelines/](https://docs.gitlab.com/ee/ci/merge_request_pipelines/) + +* [Prerequisites](#prerequisites) +* [Configuring pipelines for merge requests](#configuring-pipelines-for-merge-requests) + * [Use `rules` to run pipelines for merge requests](#use-rules-to-run-pipelines-for-merge-requests) + * [Use `only` or `except` to run pipelines for merge requests](#use-only-or-except-to-run-pipelines-for-merge-requests) + * [Excluding certain jobs](#excluding-certain-jobs) + * [Excluding certain branches](#excluding-certain-branches) +* [Pipelines for Merged Results](#pipelines-for-merged-results-premium) + * [Merge Trains](#merge-trains-premium) +* [Important notes about merge requests from forked projects](#important-notes-about-merge-requests-from-forked-projects) +* [Additional predefined variables](#additional-predefined-variables) +* [Troubleshooting](#troubleshooting) + * [Two pipelines created when pushing to a merge request](#two-pipelines-created-when-pushing-to-a-merge-request) + * [Two pipelines created when pushing an invalid CI configuration file](#two-pipelines-created-when-pushing-an-invalid-ci-configuration-file) + +# Pipelines for Merge Requests[](#pipelines-for-merge-requests "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/15310) . + +在[基本配置中](../pipelines/pipeline_architectures.html#basic-pipelines) ,每次更改被推送到分支时,GitLab 都会运行管道. + +如果希望管道**仅**在创建或更新合并请求时运行作业,则可以将*管道用于合并请求* . + +在用户界面中,这些管道被标记为`detached` . 否则,这些管道看起来与其他管道相同. + +具有开发者[权限的](../../user/permissions.html)任何用户都可以为合并请求运行管道. + +[![Merge request page](img/d5a5a91fe5e2b490b9388b43801b6a39.png)](img/merge_request.png) + +**Note:** If you use this feature with [merge when pipeline succeeds](../../user/project/merge_requests/merge_when_pipeline_succeeds.html), pipelines for merge requests take precedence over the other regular pipelines. + +## Prerequisites[](#prerequisites "Permalink") + +要为合并请求启用管道: + +* 您的存储库必须是 GitLab 存储库,而不是[外部存储库](../ci_cd_for_external_repos/index.html) . +* [在 GitLab 11.10 和更高版本中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25504) ,您必须使用 GitLab Runner 11.9. + +## Configuring pipelines for merge requests[](#configuring-pipelines-for-merge-requests "Permalink") + +要为合并请求配置管道,您需要配置[CI / CD 配置文件](../yaml/README.html) . 有几种不同的方法可以做到这一点: + +### Use `rules` to run pipelines for merge requests[](#use-rules-to-run-pipelines-for-merge-requests "Permalink") + +当使用`rules` ,这是首选方法,我们建议从[`workflow:rules`模板开始,](../yaml/README.html#workflowrules-templates)以确保基本配置正确. 该链接提供了有关如何执行此操作以及如何进行自定义的说明. + +### Use `only` or `except` to run pipelines for merge requests[](#use-only-or-except-to-run-pipelines-for-merge-requests "Permalink") + +If you want to continue using `only/except`, this is possible but please review the drawbacks below. + +使用此方法时,只需指定`only: - merge_requests`每个作业的`only: - merge_requests` . 在此示例中,管道包含配置为在合并请求上运行的`test`作业. + +`build`和`deploy`作业没有`only: - merge_requests`参数,因此它们将不会在合并请求上运行. + +``` +build: + stage: build + script: ./build + only: + - master + +test: + stage: test + script: ./test + only: + - merge_requests + +deploy: + stage: deploy + script: ./deploy + only: + - master +``` + +#### Excluding certain jobs[](#excluding-certain-jobs "Permalink") + +`only: [merge_requests]`参数的行为是, *只有*具有该参数的作业*才*在合并请求的上下文中运行; 没有其他作业将运行. + +但是,您可以反转此行为,并运行*除*一两个*之外的*所有作业. + +考虑下面的管道,作业`A` , `B`和`C` 假设您要: + +* 所有管道始终运行`A`和`B` +* `C`仅针对合并请求运行. + +为此,可以如下配置`.gitlab-ci.yml`文件: + +``` +.only-default: &only-default + only: + - master + - merge_requests + - tags + +A: + <<: *only-default + script: + - ... + +B: + <<: *only-default + script: + - ... + +C: + script: + - ... + only: + - merge_requests +``` + +Therefore: + +* 由于`A`和`B`在所有情况下都具有`only:`执行规则,因此它们将始终运行. +* 由于`C`指定仅针对合并请求运行,因此它将不会针对除合并请求管道之外的任何管道运行. + +这可以帮助您避免为所有作业添加`only:`规则,以使其始终运行. 您可以使用这种格式来设置评论应用,以帮助节省资源. + +#### Excluding certain branches[](#excluding-certain-branches "Permalink") + +[`only`](../yaml/README.html#onlyexcept-basic)使用[/ `except`](../yaml/README.html#onlyexcept-basic)时,合并请求的管道需要特殊处理. 与普通的分支引用(例如`refs/heads/my-feature-branch` )不同,合并请求引用使用特殊的 Git 引用,看起来像`refs/merge-requests/:iid/head` . 因此,以下配置将**无法**正常工作: + +``` +# Does not exclude a branch named "docs-my-fix"! +test: + only: [merge_requests] + except: [/^docs-/] +``` + +相反,可以将[`$CI_COMMIT_REF_NAME`预定义环境变量](../variables/predefined_variables.html)与[`only:variables`](../yaml/README.html#onlyvariablesexceptvariables)结合使用以完成此行为: + +``` +test: + only: [merge_requests] + except: + variables: + - $CI_COMMIT_REF_NAME =~ /^docs-/ +``` + +## Pipelines for Merged Results[](#pipelines-for-merged-results-premium "Permalink") + +阅读[有关合并结果的管道](pipelines_for_merged_results/index.html)的[文档](pipelines_for_merged_results/index.html) . + +### Merge Trains[](#merge-trains-premium "Permalink") + +阅读[有关合并火车](pipelines_for_merged_results/merge_trains/index.html)的[文档](pipelines_for_merged_results/merge_trains/index.html) . + +## Important notes about merge requests from forked projects[](#important-notes-about-merge-requests-from-forked-projects "Permalink") + +请注意,当前行为可能会更改. 在通常的贡献流程中,外部贡献者遵循以下步骤: + +1. 分叉一个父项目. +2. 从分支项目中创建一个以父项目中的`master`分支为目标的合并请求. +3. 管道在合并请求上运行. +4. 父项目的维护者检查管道结果,如果最新的管道通过,则合并到目标分支. + +当前,这些管道是在**派生**项目中创建的,而不是在父项目中创建的. 这意味着您不能完全信任管道结果,因为从技术上讲,外部贡献者可以通过在派生项目中调整其 GitLab Runner 来掩盖其管道结果. + +GitLab 不允许在父项目中创建这些管道有多种原因,但是最大的原因之一是安全性问题. 外部用户可以通过修改`.gitlab-ci.yml` (可能是某种凭据)从父项目中窃取秘密变量. 这不应该发生. + +我们正在讨论一种安全的解决方案,该解决方案针对从分支项目提交的合并请求运行管道,请参阅[有关权限扩展的问题](https://gitlab.com/gitlab-org/gitlab/-/issues/11934) . + +## Additional predefined variables[](#additional-predefined-variables "Permalink") + +通过将管道用于合并请求,GitLab 将其他预定义变量公开给管道作业. 这些变量包含关联的合并请求的信息,因此将您的作业与[GitLab 合并请求 API](../../api/merge_requests.html)集成非常有用. + +您可以在[参考表中](../variables/predefined_variables.html)找到可用变量的列表. 变量名称以`CI_MERGE_REQUEST_`前缀开头. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Two pipelines created when pushing to a merge request[](#two-pipelines-created-when-pushing-to-a-merge-request "Permalink") + +如果使用`rules`时遇到重复的管道,请查看[`rules`和`only` / `except`之间](../yaml/README.html#differences-between-rules-and-onlyexcept)的[重要区别](../yaml/README.html#differences-between-rules-and-onlyexcept) ,这将帮助您正确设置起始配置. + +如果您在使用`only/except`时看到两个管道,请参见上述与`only/except`一起使用的注意事项(或者,考虑使用`rules` ). + +### Two pipelines created when pushing an invalid CI configuration file[](#two-pipelines-created-when-pushing-an-invalid-ci-configuration-file "Permalink") + +推送到具有无效 CI 配置文件的分支会触发两种类型的失败管道的创建. 一个管道是失败的合并请求管道,另一个管道是失败的分支管道,但两者都是由相同的无效配置引起的. + +在极少数情况下,会创建重复的管道. + +有关详细信息,请参[见此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/201845) . \ No newline at end of file diff --git a/docs/262.md b/docs/262.md new file mode 100644 index 0000000000000000000000000000000000000000..e6f379633e0963b8757c30e17bf67adba4240e69 --- /dev/null +++ b/docs/262.md @@ -0,0 +1,102 @@ +# Pipelines for Merged Results + +> 原文:[https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/) + +* [Prerequisites](#prerequisites) +* [Enable pipelines for merged results](#enable-pipelines-for-merged-results) +* [Using Merge Trains](#using-merge-trains) +* [Automatic pipeline cancellation](#automatic-pipeline-cancellation) +* [Troubleshooting](#troubleshooting) + * [Pipelines for merged results not created even with new change pushed to merge request](#pipelines-for-merged-results-not-created-even-with-new-change-pushed-to-merge-request) + * [Intermittently pipelines fail by `fatal: reference is not a tree:` error](#intermittently-pipelines-fail-by-fatal-reference-is-not-a-tree-error) + +# Pipelines for Merged Results[](#pipelines-for-merged-results-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7380) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.10. + +提交合并请求时,您正在请求将更改从源分支合并到目标分支. 默认情况下,CI 管道针对源分支运行作业. + +使用*用于合并结果*的管道,管道可以像源分支中的更改已被合并到目标分支中一样运行. + +如果管道由于目标分支中的问题而失败,则可以等到目标修复后再重新运行管道. 这个新管道将像源与已更新的目标合并一样运行,并且您无需重新设置基准. + +目标分支更改时,管道不会自动运行. 仅对源分支的更改会触发新的管道. 如果自上一个成功的管道以来已经过去了很长时间,则您可能需要在合并之前重新运行它,以确保源更改仍然可以成功合并到目标中. + +当合并请求无法合并时,管道仅针对源分支运行. 例如,当: + +* 目标分支的更改与源分支的更改冲突. +* 合并请求是[**草稿**合并请求](../../../user/project/merge_requests/work_in_progress_merge_requests.html) . + +在这些情况下,管道将作为[合并请求](../index.html)的管道运行,并标记为`detached` . 如果这些情况不再存在,则新管道将再次针对合并结果运行. + +具有开发者[权限的](../../../user/permissions.html)任何用户都可以运行管道以合并结果. + +## Prerequisites[](#prerequisites "Permalink") + +要启用管道以合并结果: + +* 您必须具有维护者[权限](../../../user/permissions.html) . +* 您必须使用[GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) 11.9 或更高版本. +* 您一定不要分叉或使用跨仓库工作流. 要跟踪进度,请参阅[#11934](https://gitlab.com/gitlab-org/gitlab/-/issues/11934) . +* 您一定不能使用[快速前进合并](../../../user/project/merge_requests/fast_forward_merge.html) . 要跟踪进度,请参阅[#58226](https://gitlab.com/gitlab-org/gitlab/-/issues/26996) . + +## Enable pipelines for merged results[](#enable-pipelines-for-merged-results "Permalink") + +要为项目的合并结果启用管道: + +1. [配置您的 CI / CD 配置文件,](../index.html#configuring-pipelines-for-merge-requests)以便为合并请求运行管道或单个作业. +2. 访问项目的**设置>常规,**然后展开**合并请求** . +3. Check **为合并结果启用合并训练和管道**. +4. Click **保存更改**. + +**警告:**如果选中该复选框,但未将 CI / CD 配置为使用管道处理合并请求,则合并请求可能会停留在未解决的状态,或者管道可能会被丢弃. + +## Using Merge Trains[](#using-merge-trains "Permalink") + +[为合并结果](#pipelines-for-merged-results-premium)启用[管道时](#pipelines-for-merged-results-premium) ,GitLab 会[自动显示"](merge_trains/index.html#add-a-merge-request-to-a-merge-train) **开始/添加合并训练"按钮** . + +通常,这是比立即合并合并请求更安全的选择,因为在实际合并发生之前,将使用预期的合并后结果评估合并请求. + +有关更多信息,请阅读[合并火车上](merge_trains/index.html)的[文档](merge_trains/index.html) . + +## Automatic pipeline cancellation[](#automatic-pipeline-cancellation "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12996) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3. + +GitLab CI / CD 可以检测到冗余管道的存在,并会自动取消它们以节省 CI 资源. + +当用户在进行中的合并列车中立即合并请求时,将重新构建该列车,因为它将重新创建预期的合并后提交和管道. 在这种情况下,合并序列可能已经具有针对先前预期的合并后提交运行的管道. 这些管道被认为是多余的,将被自动取消. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Pipelines for merged results not created even with new change pushed to merge request[](#pipelines-for-merged-results-not-created-even-with-new-change-pushed-to-merge-request "Permalink") + +可能是由于某些禁用的功能标志引起的. 请确保在您的 GitLab 实例上启用了以下功能标志: + +* `:merge_ref_auto_sync` + +要检查和设置这些功能标志值,请要求管理员: + +1. 登录到 GitLab 实例的 Rails 控制台: + + ``` + sudo gitlab-rails console + ``` + +2. 检查标志是否启用: + + ``` + Feature.enabled?(:merge_ref_auto_sync) + ``` + +3. 如果需要,启用功能标志: + + ``` + Feature.enable(:merge_ref_auto_sync) + ``` + +### Intermittently pipelines fail by `fatal: reference is not a tree:` error[](#intermittently-pipelines-fail-by-fatal-reference-is-not-a-tree-error "Permalink") + +由于用于合并结果的管道是在合并请求( `refs/merge-requests//merge` )的合并 ref 上运行的,因此 Git 引用可能会在意外的时间被覆盖. 例如,当源分支或目标分支是高级时. 在这种情况下,流水线由于`fatal: reference is not a tree:`错误而失败,这表明在合并引用中未找到 checkout-SHA. + +在 GitLab 12.4 上,通过引入[Persistent pipe refs](../../pipelines/index.html#troubleshooting-fatal-reference-is-not-a-tree)改进了此行为. 您应该能够在任何时候创建管道,而不必考虑错误. \ No newline at end of file diff --git a/docs/263.md b/docs/263.md new file mode 100644 index 0000000000000000000000000000000000000000..a9c83f69440d33cf9337210c02bc06eec6da978a --- /dev/null +++ b/docs/263.md @@ -0,0 +1,179 @@ +# Merge Trains + +> 原文:[https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/) + +* [Merge train example](#merge-train-example) +* [Prerequisites](#prerequisites) +* [Enable merge trains](#enable-merge-trains) +* [Start a merge train](#start-a-merge-train) +* [Add a merge request to a merge train](#add-a-merge-request-to-a-merge-train) +* [Remove a merge request from a merge train](#remove-a-merge-request-from-a-merge-train) +* [View a merge request’s current position on the merge train](#view-a-merge-requests-current-position-on-the-merge-train) +* [Immediately merge a merge request with a merge train](#immediately-merge-a-merge-request-with-a-merge-train) +* [Troubleshooting](#troubleshooting) + * [Merge request dropped from the merge train immediately](#merge-request-dropped-from-the-merge-train-immediately) + * [Merge When Pipeline Succeeds cannot be chosen](#merge-when-pipeline-succeeds-cannot-be-chosen) + * [Merge Train Pipeline cannot be retried](#merge-train-pipeline-cannot-be-retried) + * [Unable to add to merge train with message “The pipeline for this merge request failed.”](#unable-to-add-to-merge-train-with-message-the-pipeline-for-this-merge-request-failed) + * [Merge Trains feature flag](#merge-trains-feature-flag-premium-only) + +# Merge Trains[](#merge-trains-premium "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 12.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9186) . +* [GitLab Premium](https://about.gitlab.com/pricing/) 12.6 中[引入了压](https://gitlab.com/gitlab-org/gitlab/-/issues/13001)入[和合并](../../../../user/project/merge_requests/squash_and_merge.html)支持. + +启用[用于合并结果](../index.html#pipelines-for-merged-results-premium)的管道时,管道作业将运行,就好像源分支中的更改已被合并到目标分支中一样. + +但是,目标分支可能正在快速变化. 准备合并时,如果有一段时间没有运行管道,则目标分支可能已更改. 现在合并可能会带来重大变化. + +*合并列车*可以防止这种情况的发生. 合并列是合并请求的排队列表,每个请求都等待合并到目标分支中. + +可以将许多合并请求添加到火车. 每个合并请求都运行其自己的合并结果管道,该管道包括列车上位于其*前面*的所有其他合并请求的更改. 所有管道并行运行,以节省时间. + +如果合并请求的管道失败,则不会合并重大更改,并且目标分支不受影响. 合并请求已从火车中删除,并且其后面的所有管道都重新启动. + +如果火车前部用于合并请求的管道成功完成,则更改将合并到目标分支中,其他管道将继续运行. + +要将合并请求添加到合并系列,您需要具有[权限](../../../../user/permissions.html)才能推送到目标分支. + +**注意:**每个合并列车最多可以并行运行**20 条**管道. 如果将超过二十个合并请求添加到合并列,则合并请求将排队,直到合并列中的插槽可用为止. 可以排队的合并请求数量没有限制. + +## Merge train example[](#merge-train-example "Permalink") + +将三个合并请求( `A` , `B`和`C` )依次添加到合并序列中,这将创建三个并行运行的合并结果管道: + +1. 第一条管道基于`A`与目标分支组合的更改运行. +2. 第二个管道基于`A`和`B`的更改以及目标分支运行. +3. 第三条流水线基于`A` , `B`和`C`的更改以及目标分支. + +如果`B`的管道发生故障,则将其从火车上移除. `C`的管道将在`A`和`C`更改的情况下重新启动,但`B`不会更改. + +如果`A`然后成功完成,它将合并到目标分支中,并且`C`继续运行. 如果将更多合并请求添加到火车,它们现在将包括目标分支中包含的`A`更改,以及来自火车中已经存在的合并请求的`C`更改. + +阅读有关[合并火车如何使您的主人保持绿色的](https://about.gitlab.com/blog/2020/01/30/all-aboard-merge-trains/)更多信息. + +观看此视频,以获取有关[并行执行合并训练如何防止提交破坏默认分支](https://www.youtube.com/watch?v=D4qCqXgZkHQ)的演示. + +## Prerequisites[](#prerequisites "Permalink") + +要启用合并火车: + +* 您必须具有维护者[权限](../../../../user/permissions.html) . +* 您必须使用[GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) 11.9 或更高版本. +* 在 GitLab 12.0 和更高版本中,您需要[Redis](https://s0redis0io.icopy.site/) 3.2 或更高版本. + +## Enable merge trains[](#enable-merge-trains "Permalink") + +为您的项目启用合并火车: + +1. 如果您使用的是自我管理的 GitLab 实例,请确保正确设置了[功能标志](#merge-trains-feature-flag-premium-only) . +2. [配置您的 CI / CD 配置文件,](../../index.html#configuring-pipelines-for-merge-requests)以便为合并请求运行管道或单个作业. +3. 访问项目的**设置>常规,**然后展开**合并请求** . +4. Check **为合并结果启用合并训练和管道**. +5. Click **保存更改**. + +**警告:**如果选中该复选框,但未将 CI / CD 配置为使用管道处理合并请求,则合并请求可能会停留在未解决的状态,或者管道可能会被丢弃. + +## Start a merge train[](#start-a-merge-train "Permalink") + +要开始合并火车: + +1. 访问合并请求. +2. Click the **开始合并火车** button. + +[![Start merge train](img/7775f0c2ba5f85e61aae351b9939cdf2.png)](img/merge_train_start_v12_0.png) + +现在可以将其他合并请求添加到列车中. + +## Add a merge request to a merge train[](#add-a-merge-request-to-a-merge-train "Permalink") + +要将合并请求添加到合并火车: + +1. 访问合并请求. +2. 单击**添加以合并火车**按钮. + +如果用于合并请求的管道已经在运行,则无法将合并请求添加到列车. 相反,您可以计划**在最新管道成功时将**合并请求添加到合并**序列中** . + +[![Add to merge train when pipeline succeeds](img/1c78b1078232f166ee3d03d64f2b3907.png)](img/merge_train_start_when_pipeline_succeeds_v12_0.png) + +## Remove a merge request from a merge train[](#remove-a-merge-request-from-a-merge-train "Permalink") + +1. 访问合并请求. +2. 单击**从合并火车中删除**按钮. + +[![Cancel merge train](img/1a5840885de676ed33d7cdb688b26a12.png)](img/merge_train_cancel_v12_0.png) + +如果您想稍后再将合并请求添加到合并训练中,则可以. + +## View a merge request’s current position on the merge train[](#view-a-merge-requests-current-position-on-the-merge-train "Permalink") + +将合并请求添加到合并列之后,合并请求的当前位置显示在管道小部件下: + +[![Merge train position indicator](img/c3c7ade0ae9c901a64dedf780f4efdaf.png)](img/merge_train_position_v12_0.png) + +## Immediately merge a merge request with a merge train[](#immediately-merge-a-merge-request-with-a-merge-train "Permalink") + +如果您有必须紧急合并的高优先级合并请求(例如,重要补丁程序),则可以使用" **立即合并"**选项绕过合并程序. 这是将更改合并到目标分支的最快选项. + +[![Merge Immediately](img/5844f1567aec337f6ba990bc855c348a.png)](img/merge_train_immediate_merge_v12_6.png) + +**警告:**每次您立即合并一个合并请求时,都会重新创建当前的合并序列,并重新启动所有管道. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Merge request dropped from the merge train immediately[](#merge-request-dropped-from-the-merge-train-immediately "Permalink") + +如果合并请求不可合并(例如,在制品,存在合并冲突等),则您的合并请求将自动从合并列中删除. + +在这些情况下,删除合并请求的原因在**系统注释中** . + +检查原因: + +1. 打开从合并序列中删除的合并请求. +2. 打开**讨论**选项卡. +3. 查找包含以下任一内容的系统注释: + * 文本**…从合并列表中删除了此合并请求,因为…** + * **…中止了来自合并序列的合并请求,因为…**原因在" **…"**短语之后的文本中给出. + +[![Merge Train Failure](img/cdce9b0515678bb30cdd0e1173a30749.png)](img/merge_train_failure.png) + +### Merge When Pipeline Succeeds cannot be chosen[](#merge-when-pipeline-succeeds-cannot-be-chosen "Permalink") + +启用合并训练后,当前无法[在管道成功](../../../../user/project/merge_requests/merge_when_pipeline_succeeds.html)时合并. + +有关更多信息,请参见[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/12267) . + +### Merge Train Pipeline cannot be retried[](#merge-train-pipeline-cannot-be-retried "Permalink") + +合并火车管道无法重试,因为合并请求在失败后会从合并火车中删除. 因此,重试按钮不会出现在管道图标旁边. + +如果管道发生故障,则应将合并请求[重新排队](#add-a-merge-request-to-a-merge-train)到合并[序列中](#add-a-merge-request-to-a-merge-train) ,然后合并[序列](#add-a-merge-request-to-a-merge-train)将启动新的管道. + +### Unable to add to merge train with message “The pipeline for this merge request failed.”[](#unable-to-add-to-merge-train-with-message-the-pipeline-for-this-merge-request-failed "Permalink") + +有时" **开始/添加到合并训练"**按钮不可用,合并请求显示"此合并请求的管道失败. 请重试该作业或推送新的提交以修复故障." + +在**"设置">"常规">"合并请求"中**启用**"** [**管道必须成功"**](../../../../user/project/merge_requests/merge_when_pipeline_succeeds.html#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds)时,会发生此问题. 此选项要求您运行新的成功管道,然后才能将合并请求重新添加到合并系列. + +合并训练可确保在合并发生之前每个管道都已成功完成,因此您可以清除" **管道必须成功"**复选框,并保持**启用"启用合并训练和合并结果的管道** (合并训练)". + +如果要与合并训练一起保持启用" **管道必须成功"**选项,可以在发生此错误时为合并结果创建新管道,方法是转到" **管道"**选项卡,然后单击**"运行管道"** . 然后**在管道成功时**单击" **开始/添加"以合并火车** . + +有关更多信息,请参见[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/35135) . + +### Merge Trains feature flag[](#merge-trains-feature-flag-premium-only "Permalink") + +要启用和禁用合并训练功能,请使用`:disable_merge_trains`功能标志. + +要检查您的 GitLab 实例上是否启用了功能标志,请要求管理员执行以下命令: + +``` +> sudo gitlab-rails console # Login to Rails console of GitLab instance. +> Feature.enabled?(:disable_merge_trains) # Check if it's disabled or not. +> Feature.enable(:disable_merge_trains) # Disable Merge Trains. +> Feature.disable(:disable_merge_trains) # Enable Merge Trains. +``` + +禁用此功能后,所有现有的合并训练都将被取消,并且" **开始/添加到合并训练"**按钮不再出现在合并请求中. \ No newline at end of file diff --git a/docs/264.md b/docs/264.md new file mode 100644 index 0000000000000000000000000000000000000000..1d50e07a1ff6bc68c3b93a3556b0b8adf9f19038 --- /dev/null +++ b/docs/264.md @@ -0,0 +1,393 @@ +# Job artifacts + +> 原文:[https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html](https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html) + +* [Defining artifacts in `.gitlab-ci.yml`](#defining-artifacts-in-gitlab-ciyml) + * [`artifacts:reports`](#artifactsreports) + * [`artifacts:reports:junit`](#artifactsreportsjunit) + * [`artifacts:reports:dotenv`](#artifactsreportsdotenv) + * [`artifacts:reports:cobertura`](#artifactsreportscobertura) + * [`artifacts:reports:terraform`](#artifactsreportsterraform) + * [`artifacts:reports:codequality`](#artifactsreportscodequality-starter) + * [`artifacts:reports:sast`](#artifactsreportssast-ultimate) + * [`artifacts:reports:secret_detection`](#artifactsreportssecret_detection-ultimate) + * [`artifacts:reports:dependency_scanning`](#artifactsreportsdependency_scanning-ultimate) + * [`artifacts:reports:container_scanning`](#artifactsreportscontainer_scanning-ultimate) + * [`artifacts:reports:dast`](#artifactsreportsdast-ultimate) + * [`artifacts:reports:license_management`](#artifactsreportslicense_management-ultimate) + * [`artifacts:reports:license_scanning`](#artifactsreportslicense_scanning-ultimate) + * [`artifacts:reports:performance`](#artifactsreportsperformance-premium) + * [`artifacts:reports:load_performance`](#artifactsreportsload_performance-premium) + * [`artifacts:reports:metrics`](#artifactsreportsmetrics-premium) + * [`artifacts:reports:requirements`](#artifactsreportsrequirements-ultimate) +* [Browsing artifacts](#browsing-artifacts) +* [Downloading artifacts](#downloading-artifacts) +* [Downloading the latest artifacts](#downloading-the-latest-artifacts) +* [Erasing artifacts](#erasing-artifacts) +* [Retrieve artifacts of private projects when using GitLab CI](#retrieve-artifacts-of-private-projects-when-using-gitlab-ci) + +# Job artifacts[](#job-artifacts "Permalink") + +版本历史 + +* 在 GitLab 8.2 和 GitLab Runner 0.7.0 中引入. +* 从 GitLab 8.4 和 GitLab Runner 1.0 开始,工件存档格式已更改为`ZIP` ,现在可以浏览其内容,并具有分别下载文件的功能. +* 在 GitLab 8.17 中,将构建重命名为 job. +* 工件浏览器仅适用于使用 GitLab Runner 1.0 及更高版本发送到 GitLab 的新工件. 无法浏览已经上传到 GitLab 的旧工件. + +作业工件是作业完成后创建的文件和目录的列表. [默认情况下](../../administration/job_artifacts.html) ,所有 GitLab 安装中均[启用](../../administration/job_artifacts.html)此功能. + +由 GitLab Runner 创建的作业工件被上传到 GitLab,并可以使用 GitLab UI 或[GitLab API](../../api/jobs.html#get-job-artifacts)作为单个存档下载. + +有关概述,请观看视频[GitLab CI 管道,工件和环境](https://www.youtube.com/watch?v=PCKDICEe10s) . 也请观看[面向初学者的 GitLab CI 管道教程](https://www.youtube.com/watch?v=Jav4vbUrqII) . + +## Defining artifacts in `.gitlab-ci.yml`[](#defining-artifacts-in-gitlab-ciyml "Permalink") + +在`.gitlab-ci.yml`中使用工件定义的一个简单示例如下: + +``` +pdf: + script: xelatex mycv.tex + artifacts: + paths: + - mycv.pdf + expire_in: 1 week +``` + +名为`pdf`的作业会调用`xelatex`命令,以便从乳胶源文件`mycv.tex`生成 PDF 文件. 然后,我们定义`artifacts`路径,这些路径又用`paths`关键字定义. 文件和目录的所有路径都相对于在构建过程中克隆的存储库. + +默认情况下,当作业成功时将上传工件,但是可以将其设置为在作业失败时上传,或者如果使用[`artifacts:when`](../yaml/README.html#artifactswhen)参数,则始终设置为上传. 根据`expire_in`定义,这些上传的工件将在 GitLab 中保存 1 周. 您可以通过[Web 界面](#browsing-artifacts)防止工件过期. 如果未定义到期时间,则默认为[实例范围设置](../../user/admin_area/settings/continuous_integration.html#default-artifacts-expiration-core-only) . + +有关工件的更多示例,请遵循[`.gitlab-ci.yml`](../yaml/README.html#artifacts)的[工件参考](../yaml/README.html#artifacts) . + +### `artifacts:reports`[](#artifactsreports "Permalink") + +版本历史 + +* 在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20390) . +* 需要 GitLab Runner 11.2 及更高版本. + +`artifacts:reports`关键字用于从作业中收集测试报告,代码质量报告和安全性报告. 它还在 GitLab 的 UI 中显示这些报告(合并请求,管道视图和安全性仪表板). + +**注意:**无论作业结果(成功或失败),都将收集测试报告. 您可以使用[`artifacts:expire_in`](../yaml/README.html#artifactsexpire_in)设置其工件的到期日期.**注:**如果您还希望能够浏览报告输出文件,请包括[`artifacts:paths`](../yaml/README.html#artifactspaths)关键字. + +#### `artifacts:reports:junit`[](#artifactsreportsjunit "Permalink") + +版本历史 + +* 在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20390) . +* 需要 GitLab Runner 11.2 及更高版本. + +`junit`报告将[JUnit XML 文件](https://www.ibm.com/support/knowledgecenter/en/SSQ2R2_14.1.0/com.ibm.rsar.analysis.codereview.cobol.doc/topics/cac_useresults_junit.html)收集为工件. 尽管 JUnit 最初是用 Java 开发的,但是还有许多其他[端口可以](https://en.wikipedia.org/wiki/JUnit#Ports)用于其他语言,例如 JavaScript,Python,Ruby 等. + +有关更多详细信息和示例,请参见[JUnit 测试报告](../junit_test_reports.html) . 下面是从 Ruby 的 RSpec 测试工具收集 JUnit XML 文件的示例: + +``` +rspec: + stage: test + script: + - bundle install + - rspec --format RspecJunitFormatter --out rspec.xml + artifacts: + reports: + junit: rspec.xml +``` + +收集的 JUnit 报告将作为工件上传到 GitLab,并将自动显示在合并请求中. + +**注意:**如果您使用的 JUnit 工具导出到多个 XML 文件,则可以在一个作业中指定多个测试报告路径,它们将被自动串联到一个文件中. 使用文件名模式( `junit: rspec-*.xml` ),文件名数组( `junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]` )或其组合( `junit: [rspec.xml, test-results/TEST-*.xml]` ). + +#### `artifacts:reports:dotenv`[](#artifactsreportsdotenv "Permalink") + +版本历史 + +* 在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/17066) . +* 需要 GitLab Runner 11.5 及更高版本. + +`dotenv`报告收集一组环境变量作为工件. + +收集的变量注册为作业的运行时创建的变量,这对于[在作业完成后设置动态环境 URL](../environments/index.html#set-dynamic-environment-urls-after-a-job-finishes)很有用. + +[原始 dotenv 规则](https://github.com/motdotla/dotenv#rules)有两个例外: + +* 可变键只能包含字母,数字和下划线( `_` ). +* `.env`文件的最大大小为 5 KB. +* 变量的最大数量为 10. +* 不支持`.env`文件中的变量替换. +* `.env`文件不能包含空行或注释(以`#`开头). +* `env`文件中的键值不能包含空格或换行符( `\n` ),包括使用单引号或双引号时. +* 不支持在解析过程中使用引号转义( `key = 'value'` -> `{key: "value"}` ). + +#### `artifacts:reports:cobertura`[](#artifactsreportscobertura "Permalink") + +版本历史 + +* 在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) . +* 需要[GitLab Runner](https://docs.gitlab.com/runner/) 11.5 及更高版本. + +The `cobertura` report collects [Cobertura coverage XML files](../../user/project/merge_requests/test_coverage_visualization.html). The collected Cobertura coverage reports will be uploaded to GitLab as an artifact and will be automatically shown in merge requests. + +Cobertura 最初是为 Java 开发的,但是有许多第三方端口可用于其他语言,例如 JavaScript,Python,Ruby 等. + +#### `artifacts:reports:terraform`[](#artifactsreportsterraform "Permalink") + +版本历史 + +* 在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/207528) . +* 需要[GitLab Runner](https://docs.gitlab.com/runner/) 11.5 及更高版本. + +`terraform`报告获取 Terraform `tfplan.json`文件. [需要进行 JQ 处理才能删除凭据](../../user/infrastructure/index.html#output-terraform-plan-information-into-a-merge-request) . 收集的 Terraform 计划报告将作为工件上传到 GitLab,并将在合并请求中自动显示. 有关更多信息,请参见将[`terraform plan`信息输出到合并请求中](../../user/infrastructure/index.html#output-terraform-plan-information-into-a-merge-request) . + +#### `artifacts:reports:codequality`[](#artifactsreportscodequality-starter "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`codequality`报告将[CodeQuality 问题](../../user/project/merge_requests/code_quality.html)收集为工件. + +收集的代码质量报告将作为工件上传到 GitLab,并在合并请求中进行汇总. + +#### `artifacts:reports:sast`[](#artifactsreportssast-ultimate "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`sast`报告将[SAST 漏洞](../../user/application_security/sast/index.html)收集为工件. + +收集的 SAST 报告将作为工件上传到 GitLab,并将在合并请求和管道视图中进行汇总. 它还用于为安全仪表板提供数据. + +#### `artifacts:reports:secret_detection`[](#artifactsreportssecret_detection-ultimate "Permalink") + +版本历史 + +* 在 GitLab 13.1 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`secret-detection`报告将[检测到的机密](../../user/application_security/secret_detection/index.html)收集为伪像. + +收集的 Secret Detection 报告作为工件上传到 GitLab,并在合并请求和管道视图中进行汇总. 它还用于为安全仪表板提供数据. + +#### `artifacts:reports:dependency_scanning`[](#artifactsreportsdependency_scanning-ultimate "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`dependency_scanning`报告将" [依赖关系扫描"漏洞](../../user/application_security/dependency_scanning/index.html)收集为工件. + +收集的"依赖关系扫描"报告将作为工件上传到 GitLab,并将在合并请求和管道视图中进行汇总. 它还用于为安全仪表板提供数据. + +#### `artifacts:reports:container_scanning`[](#artifactsreportscontainer_scanning-ultimate "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`container_scanning`报告收集[容器扫描漏洞](../../user/application_security/container_scanning/index.html)作为工件. + +收集的"容器扫描"报告将作为工件上传到 GitLab,并将在合并请求和管道视图中进行汇总. 它还用于为安全仪表板提供数据. + +#### `artifacts:reports:dast`[](#artifactsreportsdast-ultimate "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`dast`报告将[DAST 漏洞](../../user/application_security/dast/index.html)收集为工件. + +收集的 DAST 报告将作为工件上传到 GitLab,并将在合并请求和管道视图中进行汇总. 它还用于为安全仪表板提供数据. + +#### `artifacts:reports:license_management`[](#artifactsreportslicense_management-ultimate "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +**警告:**此工件仍然有效,但**不推荐使用** ,而**推荐使用** GitLab 12.8 中引入的[artifacts:reports:license_scanning](../pipelines/job_artifacts.html#artifactsreportslicense_scanning-ultimate) . + +`license_management`报告收集[许可证](../../user/compliance/license_compliance/index.html)作为工件. + +The collected License Compliance report will be uploaded to GitLab as an artifact and will be summarized in the merge requests and pipeline view. It’s also used to provide data for security dashboards. + +#### `artifacts:reports:license_scanning`[](#artifactsreportslicense_scanning-ultimate "Permalink") + +版本历史 + +* 在 GitLab 12.8 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`license_scanning`报告收集[许可证](../../user/compliance/license_compliance/index.html)作为工件. + +许可证合规性报告将作为工件上传到 GitLab,并将自动显示在合并请求,管道视图中,并为安全仪表板提供数据. + +#### `artifacts:reports:performance`[](#artifactsreportsperformance-premium "Permalink") + +版本历史 + +* 在 GitLab 11.5 中引入. +* 需要 GitLab Runner 11.5 及更高版本. + +`performance`报告收集[浏览器性能测试指标](../../user/project/merge_requests/browser_performance_testing.html)作为工件. + +收集的浏览器性能报告将作为工件上传到 GitLab,并将自动显示在合并请求中. + +#### `artifacts:reports:load_performance`[](#artifactsreportsload_performance-premium "Permalink") + +版本历史 + +* 介绍了[GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35260)在[GitLab 溢价](https://about.gitlab.com/pricing/) 13.2\. +* 需要 GitLab Runner 11.5 及更高版本. + +`load_performance`报告收集工件的[负载性能测试指标](../../user/project/merge_requests/load_performance_testing.html) . + +该报告作为工件被上传到 GitLab,并自动显示在合并请求中. + +#### `artifacts:reports:metrics`[](#artifactsreportsmetrics-premium "Permalink") + +在 GitLab 11.10 中引入. + +`metrics`报告收集[指标](../metrics_reports.html)作为工件. + +收集的指标报告将作为工件上传到 GitLab,并将自动显示在合并请求中. + +#### `artifacts:reports:requirements`[](#artifactsreportsrequirements-ultimate "Permalink") + +版本历史 + +* 在 GitLab 13.1 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2859) . +* 需要 GitLab Runner 11.5 及更高版本. + +`requirements`报告收集工件的`requirements.json`文件. + +收集的需求报告将作为工件上传到 GitLab,现有[需求](../../user/project/requirements/index.html)将标记为"满意". + +## Browsing artifacts[](#browsing-artifacts "Permalink") + +版本历史 + +* 从 GitLab 9.2,可以直接在工作工件浏览器中预览 PDF,图像,视频和其他格式,而无需下载它们. +* 在[GitLab 10.1 中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14399)引入的公共项目中的 HTML 文件可以在新选项卡中直接预览,而在启用[GitLab Pages](../../administration/pages/index.html)时无需下载它们. 文本格式也是如此(当前支持的扩展名: `.txt` , `.json`和`.log` ). +* 在[GitLab 12.4 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16675)引入后,启用[GitLab 页面访问控制后,便](../../administration/pages/index.html#access-control)可以预览私有项目中的工件. + +作业完成后,如果您访问作业的特定页面,则有三个按钮. 您可以下载工件归档文件或浏览其内容,而" **保留"**按钮仅在您为工件设置了[有效日期](../yaml/README.html#artifactsexpire_in)的情况下出现,以防万一您改变主意并希望保留它们. + +[![Job artifacts browser button](img/ae307552914d8ff018365bbde4d23479.png)](img/job_artifacts_browser_button.png) + +存档浏览器显示存档中每个文件的名称和实际文件大小. 如果您的工件包含目录,那么您也可以在其中进行浏览. + +您可以在下面看到浏览的样子. 在这种情况下,我们浏览了档案内部,此时有一个目录,几个文件和一个 HTML 文件,启用[GitLab 页面](../../administration/pages/index.html) (在新选项卡中打开)后,您可以直接在线查看. + +[![Job artifacts browser](img/212946086e16f591c716728308d49ca3.png)](img/job_artifacts_browser.png) + +## Downloading artifacts[](#downloading-artifacts "Permalink") + +如果您需要下载工件或整个档案,请在 GitLab UI 的不同位置进行操作: + +1. 在管道页面上,您可以在右上角看到每个作业的工件和存档的下载图标: + + [![Job artifacts in Pipelines page](img/b22d9654d7ad1868d2368d7e3f82e9a3.png)](img/job_artifacts_pipelines_page.png) + +2. 在" **作业"**页面上,您可以在右上角看到每个作业的工件和存档的下载图标: + + [![Job artifacts in Builds page](img/82c2caa32c2aff60b744c3ede8725ac9.png)](img/job_artifacts_builds_page.png) + +3. While inside a specific job, you’re presented with a download button along with the one that browses the archive: + + [![Job artifacts browser button](img/ae307552914d8ff018365bbde4d23479.png)](img/job_artifacts_browser_button.png) + +4. 最后,在浏览档案时,您可以在右上角看到下载按钮: + + [![Job artifacts browser](img/212946086e16f591c716728308d49ca3.png)](img/job_artifacts_browser.png) + +## Downloading the latest artifacts[](#downloading-the-latest-artifacts "Permalink") + +可以通过众所周知的 URL 下载作业的最新工件,以便将其用于脚本目的. + +**注意:**最新工件是由作业在特定引用的**最新**成功管道中创建的. 如果您为相同的参考运行两种类型的管道,则最新的工件将通过计时来确定. 例如,如果通过合并合并请求创建的分支管道与计划的管道同时运行,则最新的工件将来自最近完成的管道. + +可以直接访问其他管道的工件. + +用于下载整个工件存档的 URL 的结构如下: + +``` +https://example.com///-/jobs/artifacts//download?job= +``` + +To download a single file from the artifacts use the following URL: + +``` +https://example.com///-/jobs/artifacts//raw/?job= +``` + +例如,要下载名为`gitlab`项目的`master`分支(属于`gitlab-org`命名空间)的`coverage`的作业的最新工件,URL 为: + +``` +https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/download?job=coverage +``` + +要从相同的工件下载文件`coverage/index.html` ,请使用以下 URL: + +``` +https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/raw/coverage/index.html?job=coverage +``` + +还有一个 URL 可浏览最新的作业工件: + +``` +https://example.com///-/jobs/artifacts//browse?job= +``` + +例如: + +``` +https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/browse?job=coverage +``` + +还有一个指向特定文件的 URL,包括在[GitLab 页面](../../administration/pages/index.html)中显示的 HTML 文件: + +``` +https://example.com///-/jobs/artifacts//file/?job= +``` + +例如,当一个作业`coverage`创建神器`htmlcov/index.html` ,你可以访问它: + +``` +https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/file/htmlcov/index.html?job=coverage +``` + +UI 的不同位置也公开了最新版本. 具体来说,请在以下位置查找下载按钮: + +* 主项目页面 +* 分支机构页面 +* 标签页面 + +如果最新作业未能上传工件,则可以在 UI 中看到该信息. + +[![Latest artifacts button](img/a3acce71246e984986cedc7a1cece8f9.png)](img/job_latest_artifacts_browser.png) + +## Erasing artifacts[](#erasing-artifacts "Permalink") + +**警告:**这是一种破坏性行为,会导致数据丢失. 请谨慎使用. + +您可以通过 UI 删除单个作业,如果您是以下情况,则它也将删除作业的工件和跟踪: + +* 工作的所有者. +* 项目的[维护者](../../user/permissions.html#gitlab-cicd-permissions) . + +删除作业: + +1. 导航到工作页面. +2. 单击作业跟踪右上方的垃圾桶图标. +3. 确认删除. + +## Retrieve artifacts of private projects when using GitLab CI[](#retrieve-artifacts-of-private-projects-when-using-gitlab-ci "Permalink") + +为了检索不同项目的作业工件,您可能需要使用专用令牌来[认证和下载](../../api/jobs.html#get-job-artifacts)工件. \ No newline at end of file diff --git a/docs/265.md b/docs/265.md new file mode 100644 index 0000000000000000000000000000000000000000..30a25e4d130e0ca79bcac4cf275d874f2c26f05c --- /dev/null +++ b/docs/265.md @@ -0,0 +1,133 @@ +# Pipeline schedules + +> 原文:[https://docs.gitlab.com/ee/ci/pipelines/schedules.html](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) + +* [Prerequisites](#prerequisites) +* [Configuring pipeline schedules](#configuring-pipeline-schedules) + * [Using variables](#using-variables) + * [Using only and except](#using-only-and-except) + * [Advanced configuration](#advanced-configuration) +* [Working with scheduled pipelines](#working-with-scheduled-pipelines) + * [Running manually](#running-manually) + * [Taking ownership](#taking-ownership) + +# Pipeline schedules[](#pipeline-schedules "Permalink") + +版本历史 + +* 在 GitLab 9.1 中作为[触发计划](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10533)引入. +* 在 GitLab 9.2 中[重命名为 Pipeline Schedule](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10853) . + +**注意:** Cron 表示法由[Fugit](https://github.com/floraison/fugit)解析. + +管道通常是在满足某些条件的情况下运行的. 例如,将分支推送到存储库时. + +管道计划可以用于以特定间隔运行[管道](index.html) . 例如: + +* 每个月的 22 号都有特定的分支机构. +* 每天一次. + +除了使用 GitLab UI 外,还可以使用[Pipeline schedules API](../../api/pipeline_schedules.html)维护[管道时间表](../../api/pipeline_schedules.html) . + +## Prerequisites[](#prerequisites "Permalink") + +为了成功创建计划的管道: + +* 计划所有者必须具有合并到目标分支的[权限](../../user/permissions.html) . +* 管道配置必须有效. + +否则,不会创建管道. + +## Configuring pipeline schedules[](#configuring-pipeline-schedules "Permalink") + +计划项目的管道: + +1. 导航到项目的**CI / CD>计划**页面. +2. 单击**新建计划**按钮. +3. 填写**计划表中的新管道**表单. +4. 单击**保存管道计划**按钮. + +[![New Schedule Form](img/b379b1821f4b3d10ab0be61a59bcd491.png)](img/pipeline_schedules_new_form.png) + +**注意:**管道执行[时间取决于](#advanced-configuration) Sidekiq 自己的时间表. + +在" **计划**索引"页面中,您可以看到计划运行的管道的列表. 下次运行由安装了 GitLab 的服务器自动计算. + +[![Schedules list](img/de408a3a079dceb2e72d044abac21ac3.png)](img/pipeline_schedules_list.png) + +### Using variables[](#using-variables "Permalink") + +在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12328) . + +您可以传递任意数量的任意变量,它们将在 GitLab CI / CD 中可用,以便可以在您的[`.gitlab-ci.yml`文件中使用](../../ci/yaml/README.html) . + +[![Scheduled pipeline variables](img/2e1001a11cd343049b87ebf60a315e9f.png)](img/pipeline_schedule_variables.png) + +### Using only and except[](#using-only-and-except "Permalink") + +要配置仅在计划了管道(或相反)时才可以执行作业,您只能使用[且](../yaml/README.html#onlyexcept-basic)不能使用配置关键字. + +For example: + +``` +job:on-schedule: + only: + - schedules + script: + - make world + +job: + except: + - schedules + script: + - make build +``` + +### Advanced configuration[](#advanced-configuration "Permalink") + +管道不会完全按计划执行,因为计划由 Sidekiq 处理,Sidekiq 根据其间隔运行. + +例如,如果满足以下条件,则每天只会创建两个管道: + +* 您设置时间表以每分钟( `* * * * *` )创建一条管道. +* Sidekiq 工作者每天在 00:00 和 12:00( `0 */12 * * *` )运行. + +更改 Sidekiq 工作人员的频率: + +1. 在实例的`gitlab.rb`文件中编辑`gitlab_rails['pipeline_schedule_worker_cron']`值. +2. [重新配置 GitLab,](../../administration/restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +对于 GitLab.com,请参阅[专用设置页面](../../user/gitlab_com/index.html#gitlab-cicd) . + +## Working with scheduled pipelines[](#working-with-scheduled-pipelines "Permalink") + +配置完成后,GitLab 将支持许多用于计划管道的功能. + +### Running manually[](#running-manually "Permalink") + +在 GitLab 10.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15700) . + +要手动触发管道计划,请单击"播放"按钮: + +[![Play Pipeline Schedule](img/4ffe26c8f949643669a5c295958616cf.png)](img/pipeline_schedule_play.png) + +这将安排一个后台作业来运行管道计划. 一条简短消息将提供指向 CI / CD 管道索引页面的链接. + +**注意:**为避免滥用,限制了用户每分钟触发一次管道的速率. + +### Taking ownership[](#taking-ownership "Permalink") + +管道以拥有日程表的用户身份执行. 这影响管道可以访问哪些项目和其他资源. + +如果用户不拥有管道,则可以通过单击" **获取所有权"**按钮**获取所有权** . 下次计划管道时,将使用您的凭据. + +[![Schedules list](img/94b9b90ebfb15979835f3e48d710cb45.png)](img/pipeline_schedules_ownership.png) + +如果管道计划的所有者没有能力在目标分支上创建管道,则该计划将停止创建新管道. + +例如,如果发生这种情况: + +* 所有者被阻止或从项目中删除. +* 目标分支或标签受保护. + +在这种情况下,具有足够特权的人必须拥有日程表的所有权. \ No newline at end of file diff --git a/docs/266.md b/docs/266.md new file mode 100644 index 0000000000000000000000000000000000000000..f696af833957f6da872358f0d1e058ff58afa3e1 --- /dev/null +++ b/docs/266.md @@ -0,0 +1,291 @@ +# Pipeline settings + +> 原文:[https://docs.gitlab.com/ee/ci/pipelines/settings.html](https://docs.gitlab.com/ee/ci/pipelines/settings.html) + +* [Git strategy](#git-strategy) +* [Git shallow clone](#git-shallow-clone) +* [Timeout](#timeout) + * [Timeout overriding on Runner level](#timeout-overriding-on-runner-level) +* [Maximum artifacts size](#maximum-artifacts-size-core-only) +* [Custom CI configuration path](#custom-ci-configuration-path) +* [Test coverage parsing](#test-coverage-parsing) + * [Code Coverage history](#code-coverage-history) + * [Removing color codes](#removing-color-codes) +* [Visibility of pipelines](#visibility-of-pipelines) +* [Auto-cancel pending pipelines](#auto-cancel-pending-pipelines) +* [Skip outdated deployment jobs](#skip-outdated-deployment-jobs) +* [Pipeline Badges](#pipeline-badges) + * [Pipeline status badge](#pipeline-status-badge) + * [Test coverage report badge](#test-coverage-report-badge) + * [Badge styles](#badge-styles) + * [Flat (default)](#flat-default) + * [Flat square](#flat-square) + * [Custom badge text](#custom-badge-text) +* [Environment Variables](#environment-variables) + +# Pipeline settings[](#pipeline-settings "Permalink") + +要达到管道设置,请导航至项目的**"设置">" CI / CD"** . + +可以为每个项目配置以下设置. + +有关概述,请观看视频[GitLab CI 管道,工件和环境](https://www.youtube.com/watch?v=PCKDICEe10s) . 也请观看[面向初学者的 GitLab CI 管道教程](https://www.youtube.com/watch?v=Jav4vbUrqII) . + +## Git strategy[](#git-strategy "Permalink") + +使用 Git 策略,您可以选择从作业中的 GitLab 提取存储库的默认方式. + +有两种选择. 使用: + +* `git clone` ,速度较慢,因为它会为每个作业从头开始克隆存储库,以确保本地工作副本始终是原始的. +* `git fetch` ,它更快地重新使用本地工作副本(如果不存在,则回退为克隆). + +默认的 Git 策略可以由`.gitlab-ci.yml`的[GIT_STRATEGY 变量](../yaml/README.html#git-strategy)覆盖. + +## Git shallow clone[](#git-shallow-clone "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28919) in GitLab 12.0. + +**注意:**从 GitLab 12.0 开始,新创建的项目将自动具有默认的`git depth`值`50` . + +克隆存储库时,可以限制 GitLab CI / CD 获取的更改数量. 设置`git depth`的限制可以加快管道的执行速度. 最大允许值为`1000` . + +要禁用浅表克隆并使 GitLab CI / CD 每次获取所有分支和标签,请将值保留为空或设置为`0` . + +`.gitlab-ci.yml`文件中的[`GIT_DEPTH`](../large_repositories/index.html#shallow-cloning)变量也可以[覆盖](../large_repositories/index.html#shallow-cloning)此值. + +## Timeout[](#timeout "Permalink") + +超时定义了作业可以运行的最长时间(以分钟为单位). 这可以在项目的**设置> CI / CD>常规管道设置下进行配置** . 默认值为 60 分钟. 如果要对作业的运行时间施加硬性限制,则减少时间限制,否则增加该限制. 无论如何,如果作业超过阈值,则将其标记为失败. + +### Timeout overriding on Runner level[](#timeout-overriding-on-runner-level "Permalink") + +在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17221) . + +项目定义的超时(用户设置的特定超时或默认的 60 分钟超时)可以[在 Runner 级别](../runners/README.html#set-maximum-job-timeout-for-a-runner)上[覆盖](../runners/README.html#set-maximum-job-timeout-for-a-runner) . + +## Maximum artifacts size[](#maximum-artifacts-size-core-only "Permalink") + +有关为项目设置最大工件大小的信息,请参见[最大工件大小](../../user/admin_area/settings/continuous_integration.html#maximum-artifacts-size-core-only) . + +## Custom CI configuration path[](#custom-ci-configuration-path "Permalink") + +版本历史 + +* 在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12509) . +* [支持](https://gitlab.com/gitlab-org/gitlab/-/issues/14376)在 GitLab 12.6 中引入的[外部`.gitlab-ci.yml`位置](https://gitlab.com/gitlab-org/gitlab/-/issues/14376) . + +默认情况下,我们在项目的根目录中查找`.gitlab-ci.yml`文件. 如果需要,您可以指定备用路径和文件名,包括项目外部的位置. + +要自定义路径: + +1. 转到项目的**设置> CI / CD** . +2. 展开**常规管道**部分. +3. 在" **定制 CI 配置路径"**字段中提供一个值. +4. Click **保存更改**. + +如果 CI 配置在非默认位置存储在资源库中,则该路径必须相对于根目录. 有效路径和文件名的示例包括: + +* `.gitlab-ci.yml` (default) +* `.my-custom-file.yml` +* `my/path/.gitlab-ci.yml` +* `my/path/.my-custom-file.yml` + +如果 CI 配置将托管在外部站点上,则 URL 链接必须以`.yml` : + +* `http://example.com/generate/ci/config.yml` + +如果 CI 配置将托管在 GitLab 中的其他项目中,则该路径必须相对于另一个项目中的根目录,并在最后添加组和项目名称: + +* `.gitlab-ci.yml@mygroup/another-project` +* `my/path/.my-custom-file.yml@mygroup/another-project` + +将配置文件托管在单独的项目中,可以更严格地控​​制配置文件. 例如: + +* 创建一个公共项目来承载配置文件. +* 仅向被允许编辑文件的用户授予对项目的写权限. + +其他用户和项目将能够访问配置文件而无需对其进行编辑. + +## Test coverage parsing[](#test-coverage-parsing "Permalink") + +如果您在代码中使用测试覆盖率,则 GitLab 可以使用正则表达式将其输出捕获到作业日志中. 在管道设置中,搜索"测试 coverage 解析"部分. + +[![Pipelines settings test coverage](img/1c1c9ba40bbb3c1ab789e70a4c4d42e6.png)](img/pipelines_settings_test_coverage.png) + +如果要禁用它或输入 Ruby 正则表达式,请保留空白. 您可以使用[https://rubular.com](https://rubular.com)来测试您的正则表达式. 正则表达式返回在输出中找到的**最后一个**匹配项. + +如果管道成功,则覆盖范围将显示在合并请求窗口小部件和作业表中. + +[![MR widget coverage](img/afec6ffec0973dba40a3e3bc2c244bad.png)](img/pipelines_test_coverage_mr_widget.png) + +[![Build status coverage](img/f81ccf2ef168880473496ad46b2d991f.png)](img/pipelines_test_coverage_build.png) + +可以在管道设置页面中找到一些针对多种语言的已知覆盖工具的示例. + +### Code Coverage history[](#code-coverage-history "Permalink") + +Version history + +* [引入](https://gitlab.com/gitlab-org/gitlab/-/issues/209121)了在 GitLab 12.10 中下载`.csv` . +* GitLab 13.1 中[引入的图](https://gitlab.com/gitlab-org/gitlab/-/issues/33743) . + +如果您想查看项目代码覆盖率随时间的变化,则可以查看图形或下载包含此数据的 CSV 文件. 从您的项目中: + +1. 去 **单击项目分析>存储库,**以查看图表上方下拉列表中列出的每个作业的历史数据. +2. 如果您想要该数据的 CSV 文件,请点击**下载原始数据(.csv)** + +[![Code coverage graph of a project over time](img/45c66aeb387e650cfe717047d1b78263.png)](img/code_coverage_graph_v13_1.png) + +### Removing color codes[](#removing-color-codes "Permalink") + +某些使用 ANSI 颜色代码输出的测试 coverage 工具无法通过正则表达式正确解析,并且会导致 coverage 解析失败. + +如果 Coverage 工具没有提供禁用输出中颜色代码的选项,则可以通过一个小的单行脚本通过管道传递 Coverage 工具的输出,该脚本将去除颜色代码. + +例如: + +``` +lein cloverage | perl -pe 's/\e\[?.*?[\@-~]//g' +``` + +## Visibility of pipelines[](#visibility-of-pipelines "Permalink") + +Pipeline visibility is determined by: + +* 您当前的[用户访问级别](../../user/permissions.html) . +* 项目**设置> CI / CD>常规管道**下的**公共管道**项目设置. + +**注意:**如果项目可见性设置为" **私有"** ,则" [**公共管道"**设置将无效](../enable_or_disable_ci.html#per-project-user-setting) . + +这也决定了这些相关功能的可见性: + +* 作业输出日志 +* 工作文物 +* The [pipeline security dashboard](../../user/application_security/security_dashboard/index.html#pipeline-security) + +**注意:**当前, [访客用户和非项目成员尚看不到](https://gitlab.com/gitlab-org/gitlab/-/issues/25649)作业日志和工件. + +如果启用了**公共管道** (默认): + +* 对于**公共**项目,任何人都可以查看管道和相关功能. +* 对于**内部**项目,任何登录的用户都可以查看管道和相关功能. +* 对于**私有**项目,任何项目成员(访客或更高级别)都可以查看管道和相关功能. + +如果禁用**公共管道** : + +* 对于**公共**项目,任何人都可以查看管道,但是只有成员(报告者或更高级别)可以访问相关功能. +* 对于**内部**项目,任何登录的用户都可以查看管道. 但是,只有成员(记者或更高级别)可以访问与工作相关的功能. +* 对于**私有**项目,只有项目成员(报告者或更高版本)才能查看管道或访问相关功能. + +## Auto-cancel pending pipelines[](#auto-cancel-pending-pipelines "Permalink") + +在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9362) . + +如果您希望每次创建新管道时(例如在 Git 推送之后或从 UI 手动创建)每次自动取消分支上所有未决的非 HEAD 管道,都可以在项目设置中启用此功能: + +1. 去 **设置> CI / CD** . +2. Expand **通用管道**. +3. 选中**自动取消冗余的未决管道**复选框. +4. Click **保存更改**. + +请注意,只有可[中断](../yaml/README.html#interruptible)设置为`true`作业才会被取消. + +## Skip outdated deployment jobs[](#skip-outdated-deployment-jobs "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/25276) . + +您的项目可能有多个并发部署作业,这些作业计划在同一时间范围内运行. + +这可能导致旧的部署作业在新的作业之后运行,而这可能不是您想要的. + +为了避免这种情况: + +1. 去 **设置> CI / CD** . +2. Expand **通用管道**. +3. 选中**跳过过期的部署作业**复选框. +4. Click **保存更改**. + +挂起的部署作业将被跳过. + +有关更多信息,请参阅[部署安全](../environments/deployment_safety.html) . + +## Pipeline Badges[](#pipeline-badges "Permalink") + +在管道设置页面中,您可以找到项目的管道状态和测试覆盖率标志. 最新成功的管道将用于读取管道状态和测试覆盖率值. + +访问项目中的管道设置页面,以查看指向徽章的确切链接,以及将徽章图像嵌入 HTML 或 Markdown 页面的方法. + +[![Pipelines badges](img/9fd7b49e564d04c79644e7fb8c7d7d5d.png)](img/pipelines_settings_badges.png) + +### Pipeline status badge[](#pipeline-status-badge "Permalink") + +根据您的工作状态,徽章可以具有以下值: + +* pending +* running +* passed +* failed +* skipped +* canceled +* unknown + +您可以使用以下链接访问管道状态标志图像: + +``` +https://example.gitlab.com///badges//pipeline.svg +``` + +### Test coverage report badge[](#test-coverage-report-badge "Permalink") + +GitLab 使定义[覆盖率报告](#test-coverage-parsing)的正则表达式成为可能,每个作业日志都将与之匹配. 这意味着管道中的每个作业都可以定义测试覆盖率百分比值. + +可以使用以下链接访问测试覆盖率徽章: + +``` +https://example.gitlab.com///badges//coverage.svg +``` + +如果要从特定作业获取覆盖率报告,可以将`job=coverage_job_name`参数添加到 URL. 例如,以下 Markdown 代码会将`coverage`作业的测试覆盖率报告标志嵌入到`README.md` : + +``` +![coverage](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=coverage) +``` + +### Badge styles[](#badge-styles "Permalink") + +通过向 URL 添加`style=style_name`参数,可以以不同的样式呈现管道标志. 当前有两种样式: + +#### Flat (default)[](#flat-default "Permalink") + +``` +https://example.gitlab.com///badges//coverage.svg?style=flat +``` + +[![Badge flat style](img/69a8b09a09599e563d1796eac13f945e.png)](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=coverage&style=flat) + +#### Flat square[](#flat-square "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30120) . + +``` +https://example.gitlab.com///badges//coverage.svg?style=flat-square +``` + +[![Badge flat square style](img/c7918abdac813cb6d0b57bb682269b93.png)](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=coverage&style=flat-square) + +### Custom badge text[](#custom-badge-text "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/17555) . + +徽章的文本可以自定义. 这有助于区分在同一管道中运行的多个 Coverage 作业. 通过将`key_text=custom_text`和`key_width=custom_key_width`参数添加到 URL 来定制徽章文本和宽度: + +``` +https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=karma&key_text=Frontend+Coverage&key_width=100 +``` + +[![Badge with custom text and width](img/8e5585152d153d9f1f4073f0cddba269.png)](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=karma&key_text=Frontend+Coverage&key_width=100) + +## Environment Variables[](#environment-variables "Permalink") + +可以在环境中设置[环境变量](../variables/README.html#gitlab-cicd-environment-variables)以供跑步者使用. \ No newline at end of file diff --git a/docs/267.md b/docs/267.md new file mode 100644 index 0000000000000000000000000000000000000000..78d7b9f730208be57c28de8816ec5ad222b6d851 --- /dev/null +++ b/docs/267.md @@ -0,0 +1,251 @@ +# Triggering pipelines through the API + +> 原文:[https://docs.gitlab.com/ee/ci/triggers/README.html](https://docs.gitlab.com/ee/ci/triggers/README.html) + +* [Authentication tokens](#authentication-tokens) + * [Trigger token](#trigger-token) + * [CI job token](#ci-job-token) + * [When used with multi-project pipelines](#when-used-with-multi-project-pipelines) + * [When a pipeline depends on the artifacts of another pipeline](#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium) +* [Adding a new trigger](#adding-a-new-trigger) +* [Revoking a trigger](#revoking-a-trigger) +* [Triggering a pipeline](#triggering-a-pipeline) +* [Triggering a pipeline from a webhook](#triggering-a-pipeline-from-a-webhook) +* [Making use of trigger variables](#making-use-of-trigger-variables) +* [Using cron to trigger nightly pipelines](#using-cron-to-trigger-nightly-pipelines) +* [Legacy triggers](#legacy-triggers) + +# Triggering pipelines through the API[](#triggering-pipelines-through-the-api "Permalink") + +版本历史 + +**注意事项** : + +* 在 GitLab 7.14 中[引入](https://about.gitlab.com/releases/2015/08/22/gitlab-7-14-released/) . +* GitLab 8.12 具有完全重新设计的工作权限系统. 阅读有关[新模型及其含义的](../../user/project/new_ci_build_permissions_model.html#pipeline-triggers)所有信息. + +触发器可用于通过 API 调用强制重新运行特定`ref` (分支或标签)的管道. + +## Authentication tokens[](#authentication-tokens "Permalink") + +支持以下身份验证方法: + +* [Trigger token](#trigger-token) +* [CI job token](#ci-job-token) + +如果使用`$CI_PIPELINE_SOURCE` [预定义环境变量](../variables/predefined_variables.html)来限制在管道中运行的作业,则值可以是`pipeline`或`trigger` ,具体取决于所使用的触发器方法. + +| `$CI_PIPELINE_SOURCE` value | 触发方式 | +| --- | --- | +| `pipeline` | 使用 CI / CD 配置文件中的`trigger:`关键字,或将触发器 API 与`$CI_JOB_TOKEN` . | +| `trigger` | 使用生成的触发令牌使用触发 API | + +当使用`pipelines`或使用[`only/except`](../yaml/README.html#onlyexcept-basic)传统[`only/except`基本语法`only/except`](../yaml/README.html#onlyexcept-basic) `triggers`关键字时,这也适用. + +### Trigger token[](#trigger-token "Permalink") + +A unique trigger token can be obtained when [adding a new trigger](#adding-a-new-trigger). + +**危险:**在公共项目中传递纯文本令牌是一个安全问题. 潜在的攻击者可以在`.gitlab-ci.yml`文件中假冒公开暴露其触发令牌的用户. 使用[变量](../variables/README.html#gitlab-cicd-environment-variables)来保护触发令牌. + +### CI job token[](#ci-job-token "Permalink") + +You can use the `CI_JOB_TOKEN` [variable](../variables/README.html#predefined-environment-variables) (used to authenticate with the [GitLab Container Registry](../../user/packages/container_registry/index.html)) in the following cases. + +#### When used with multi-project pipelines[](#when-used-with-multi-project-pipelines "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 9.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2017)了`CI_JOB_TOKEN`在多项目管道中的使用. +* 在 GitLab 12.4 的所有层中都[可以](https://gitlab.com/gitlab-org/gitlab/-/issues/31573)将`CI_JOB_TOKEN`用于多项目管道. + +这种触发方式只能在`.gitlab-ci.yml`内部调用时使用,并且会在[管道图](../multi_project_pipelines.html#overview)上创建可见的依赖管道关系. 例如: + +``` +build_docs: + stage: deploy + script: + - curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=master https://gitlab.example.com/api/v4/projects/9/trigger/pipeline + only: + - tags +``` + +以这种方式触发的管道还公开了一个特殊变量: `CI_PIPELINE_SOURCE=pipeline` . + +阅读有关[管道触发器 API 的](../../api/pipeline_triggers.html)更多信息. + +#### When a pipeline depends on the artifacts of another pipeline[](#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium "Permalink") + +在[GitLab Premium](https://about.gitlab.com/pricing/) 9.5 中[引入了](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2346)在工件下载 API 中使用`CI_JOB_TOKEN` . + +随着不同项目之间的依赖关系的引入,其中一个项目可能需要访问由前一个项目创建的工件. 必须为授权访问授予此过程,并且可以使用标识特定作业的`CI_JOB_TOKEN`变量完成此过程. 例如: + +``` +build_submodule: + image: debian + stage: test + script: + - apt update && apt install -y unzip + - curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test&job_token=$CI_JOB_TOKEN" + - unzip artifacts.zip + only: + - tags +``` + +这使您可以将其用于多项目管道,并从您有权访问的任何项目下载工件,因为这遵循与[权限模型](../../user/permissions.html#job-permissions)相同的原则. + +了解有关[Jobs API 的](../../api/jobs.html#download-the-artifacts-archive)更多信息. + +## Adding a new trigger[](#adding-a-new-trigger "Permalink") + +您可以通过在"触发器"下转到项目的**"设置"➔CI / CD**来添加新**触发器** . **添加触发器**按钮将创建一个新令牌,然后您可以使用该令牌来触发此特定项目管道的重新运行. + +您创建的每个新触发器都会被分配一个不同的令牌,然后您可以在脚本或`.gitlab-ci.yml`使用该令牌. 您还可以很好地了解上一次使用触发器的时间. + +[![Triggers page overview](img/d25fe780083ad8adbc24cf5fcc4feaf8.png)](img/triggers_page.png) + +## Revoking a trigger[](#revoking-a-trigger "Permalink") + +您可以随时通过单击" **触发器"**下项目的**"设置"➔CI / CD**并单击" **撤消"**按钮来**撤消** **触发器** . 动作是不可逆的. + +## Triggering a pipeline[](#triggering-a-pipeline "Permalink") + +> **Notes**: +> +> * 有效的引用只是分支和标签. 如果通过提交 SHA 作为参考,它将不会触发作业. + +要触发作业,您需要向 gitLab 的 API 端点发送`POST`请求: + +``` +POST /projects/:id/trigger/pipeline +``` + +必需的参数是[触发器的`token`](#authentication-tokens)和将在其上执行触发器的 Git `ref` . 有效的引用是分支和标签. 可以通过[查询 API](../../api/projects.html)或访问**CI / CD**设置页面(提供不言自明的示例)来找到项目的`:id` . + +触发管道的重新运行时,该信息会在 GitLab 的 UI 中显示在**Jobs**页面下,并且作业被标记为"由 API 触发". + +[![Marked rebuilds as on jobs page](img/a68a3a59d914e3b3ef4b3cd56a67c1e1.png)](img/builds_page.png) + +* * * + +您可以通过访问单个作业页面查看是哪个触发器导致了重建. 从下图中可以看到,触发器的令牌的一部分显示在 UI 中. + +[![Marked rebuilds as triggered on a single job page](img/74017afb9b6459aed36b4c4a53df62e9.png)](img/trigger_single_build.png) + +* * * + +通过使用 cURL,您可以以最小的努力触发管道重新运行,例如: + +``` +curl --request POST \ + --form token=TOKEN \ + --form ref=master \ + https://gitlab.example.com/api/v4/projects/9/trigger/pipeline +``` + +在这种情况下,ID `9`的项目将在`master`分支上重建. + +或者,您可以在查询字符串中传递`token`和`ref`参数: + +``` +curl --request POST \ + "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline?token=TOKEN&ref=master" +``` + +您还可以在`.gitlab-ci.yml`使用触发器来`.gitlab-ci.yml` . 假设您有两个项目 A 和 B,并且每当在项目 A 上创建标签时,您都希望在项目 B 的`master`分支上触发重建. 这是您需要在项目 A 的`.gitlab-ci.yml`添加的工作: + +``` +build_docs: + stage: deploy + script: + - "curl --request POST --form token=TOKEN --form ref=master https://gitlab.example.com/api/v4/projects/9/trigger/pipeline" + only: + - tags +``` + +这意味着每当在项目 A 上添加新标签时,该作业就会运行,并且`build_docs`作业将被执行,从而触发项目 B 的重建`build_docs` `stage: deploy`确保该作业仅在所有带有`stage: test`作业之后运行成功完成. + +## Triggering a pipeline from a webhook[](#triggering-a-pipeline-from-a-webhook "Permalink") + +版本历史 + +**注意事项** : + +* 在 GitLab 8.14 中引入. +* `ref`应该作为 URL 的一部分传递,以便优先于来自 Webhook 主体的`ref` ,该 Webhook 主体指定了触发源存储库中的触发器的分支 ref. +* `ref`包含斜杠,则应进行 URL 编码. + +要从另一个项目的 Webhook 触发作业,您需要为 Push 和 Tag 事件添加以下 Webhook URL(更改项目 ID,ref 和 token): + +``` +https://gitlab.example.com/api/v4/projects/9/ref/master/trigger/pipeline?token=TOKEN +``` + +## Making use of trigger variables[](#making-use-of-trigger-variables "Permalink") + +您可以在触发器 API 调用中传递任意数量的任意变量,这些变量将在 GitLab CI / CD 中可用,以便可以在您的`.gitlab-ci.yml`文件中使用. 参数的形式为: + +``` +variables[key]=value +``` + +此信息也显示在 UI 中. 请注意,只有所有者和维护者才能看到这些*值* . + +[![Job variables in UI](img/8a6c0fc733a099005b7f7f9bcfbfe2ff.png)](img/trigger_variables.png) + +出于多种原因,使用触发器变量可能被证明是有用的: + +* 可识别的工作. 由于该变量在 UI 中公开,因此您可以通过传递解释目的的变量来知道为什么触发了重建. +* 有条件的作业处理. 您可以让有条件的作业在存在某个变量时运行. + +考虑以下`.gitlab-ci.yml` ,我们在其中设置了三个[阶段](../yaml/README.html#stages) ,仅当测试和构建阶段中的所有作业都通过时, `upload_package`作业才运行. 当`UPLOAD_TO_S3`变量不为零时,运行`make upload` . + +``` +stages: + - test + - build + - package + +run_tests: + stage: test + script: + - make test + +build_package: + stage: build + script: + - make build + +upload_package: + stage: package + script: + - if [ -n "${UPLOAD_TO_S3}" ]; then make upload; fi +``` + +然后,您可以在传递`UPLOAD_TO_S3`变量时触发重建,并且`upload_package`作业的脚本将运行: + +``` +curl --request POST \ + --form token=TOKEN \ + --form ref=master \ + --form "variables[UPLOAD_TO_S3]=true" \ + https://gitlab.example.com/api/v4/projects/9/trigger/pipeline +``` + +触发变量在所有类型的变量中具有[最高优先级](../variables/README.html#priority-of-environment-variables) . + +## Using cron to trigger nightly pipelines[](#using-cron-to-trigger-nightly-pipelines "Permalink") + +> **注意:**以下行为也可以通过 GitLab 的 UI 与[管道计划一起实现](../pipelines/schedules.html) . + +无论您编写脚本还是直接运行 cURL,都可以与 cron 一起触发作业. 以下示例每晚`00:30`在 ID 为`9`的项目的`master`分支上触发一个作业: + +``` +30 0 * * * curl --request POST --form token=TOKEN --form ref=master https://gitlab.example.com/api/v4/projects/9/trigger/pipeline +``` + +## Legacy triggers[](#legacy-triggers "Permalink") + +在 GitLab 9.0 之前创建的旧触发器将被标记为旧触发器. + +具有旧标签的触发器没有关联的用户,只能访问当前项目. 它们被认为已弃用,并将在将来的 GitLab 版本中删除. \ No newline at end of file diff --git a/docs/268.md b/docs/268.md new file mode 100644 index 0000000000000000000000000000000000000000..fc0ccfc4dc2a724a782e0912699a9a38adc4f1f3 --- /dev/null +++ b/docs/268.md @@ -0,0 +1,261 @@ +# Review Apps + +> 原文:[https://docs.gitlab.com/ee/ci/review_apps/](https://docs.gitlab.com/ee/ci/review_apps/) + +* [Introduction](#introduction) +* [How Review Apps work](#how-review-apps-work) +* [Configuring Review Apps](#configuring-review-apps) + * [Enable Review Apps button](#enable-review-apps-button) +* [Review Apps auto-stop](#review-apps-auto-stop) +* [Review Apps examples](#review-apps-examples) +* [Route Maps](#route-maps) + * [Route Maps example](#route-maps-example) +* [Visual Reviews](#visual-reviews-starter) + * [Configuring Visual Reviews](#configuring-visual-reviews) + * [Determining merge request ID](#determining-merge-request-id) + * [Visual Reviews in private or internal projects](#visual-reviews-in-private-or-internal-projects) + * [Using Visual Reviews](#using-visual-reviews) +* [Limitations](#limitations) + +# Review Apps[](#review-apps "Permalink") + +版本历史 + +* 在 GitLab 8.12 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21971) . 在 GitLab 8.13 和 8.14 中进行了进一步添加. +* 受到[Heroku 的 Review Apps 的](https://devcenter.heroku.com/articles/github-integration-review-apps)启发,该[应用程序](https://devcenter.heroku.com/articles/github-integration-review-apps)本身也受到[Fourchette 的](https://github.com/rainforestapp/fourchette)启发. + +Review Apps 是一种协作工具,可消除提供展示产品更改环境的艰苦工作. + +## Introduction[](#introduction "Permalink") + +查看应用程序: + +* 通过为合并请求扩展动态环境,提供功能分支中所做更改的自动实时预览. +* 允许设计人员和产品经理查看您的更改,而无需检出分支机构并在沙盒环境中运行您的更改. +* 与[GitLab DevOps LifeCycle](../../README.html#the-entire-devops-lifecycle)完全集成. +* 允许您将更改部署到任何地方. + +[![Review Apps Workflow](img/45586bacf83042f9bfcdb01d5576fe3c.png)](img/continuous-delivery-review-apps.svg) + +在上面的示例中: + +* 每次将提交推送到`topic branch`时,都会构建一个 Review App. +* 审阅者在通过第三次审阅之前未通过两次审阅. +* 审核通过后, `topic branch`将合并到`master` `topic branch`中,并在该`topic branch`中进行部署. +* 在阶段中获得批准后,已合并到`master`中的更改将部署到生产中. + +## How Review Apps work[](#how-review-apps-work "Permalink") + +Review App 是分支与[环境](../environments/index.html)的映射. 通过与分支相关的[合并请求](../../user/project/merge_requests.html)上的链接,可以访问 Review App. + +以下是动态设置环境的合并请求的示例. + +[![Review App in merge request](img/a19f68ae0d29248e1f28009bfb10a89a.png)](img/review_apps_preview_in_mr.png) + +在此示例中,分支为: + +* 成功建立. +* 通过单击" **查看应用程序"**按钮可以到达的动态环境中进行部署. + +将 Review Apps 添加到您的工作流后,您将遵循分支的 Git 流. 那是: + +1. 推送一个分支,让 Runner 根据动态环境作业的`script`定义部署 Review App. +2. 等待 Runner 构建和部署您的 Web 应用程序. +3. 单击合并请求中与分支相关的链接,以实时查看更改. + +## Configuring Review Apps[](#configuring-review-apps "Permalink") + +Review Apps 建立在[动态环境上](../environments/index.html#configuring-dynamic-environments) ,可让您为每个分支动态创建一个新环境. + +配置 Review Apps 的过程如下: + +1. 设置基础结构以托管和部署 Review Apps(请查看下面的[示例](#review-apps-examples) ). +2. [安装](https://docs.gitlab.com/runner/install/)并[配置](https://docs.gitlab.com/runner/commands/) Runner 以进行部署. +3. 在`.gitlab-ci.yml`中设置一个作业,该作业使用[预定义的 CI 环境变量](../variables/README.html) `${CI_COMMIT_REF_NAME}`创建动态环境并将其限制为仅在分支上运行. 或者,您可以通过为项目[启用审阅应用程序](#enable-review-apps-button)来获得此工作的 YML 模板. +4. (可选)设置一个作业,以[手动停止](../environments/index.html#stopping-an-environment) Review Apps. + +### Enable Review Apps button[](#enable-review-apps-button "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/118844) . + +为项目配置 Review Apps 时,如上所述,您需要向`.gitlab-ci.yml`添加新作业. 为此,如果您正在使用 Kubernetes,则可以单击**Enable Review Apps**按钮,GitLab 会提示您一个模板代码块,您可以将该模板代码块复制并粘贴到`.gitlab-ci.yml`作为起点. 为此: + +1. 转到要为其创建 Review App 作业的项目. +2. 从左侧导航栏中,转到**运营** > **环境** . +3. 单击**启用审阅应用程序**按钮. 如果您对该项目具有开发人员或更高[权限,则](../../user/permissions.html)可以使用它. +4. 复制提供的代码段并将其粘贴到您的`.gitlab-ci.yml`文件中: + + [![Enable Review Apps modal](img/ced764ccc10657c7f37a1ffe8a7e338a.png)](img/enable_review_app_v12_8.png) + +5. 可以根据自己的需要随意调整此模板. + +## Review Apps auto-stop[](#review-apps-auto-stop "Permalink") + +了解如何在给定的时间段后将[Review Apps 环境配置为过期并自动停止](../environments/index.html#environments-auto-stop) . + +## Review Apps examples[](#review-apps-examples "Permalink") + +以下是演示 Review App 配置的示例项目: + +* [NGINX](https://gitlab.com/gitlab-examples/review-apps-nginx). +* [OpenShift](https://gitlab.com/gitlab-examples/review-apps-openshift). + +评论应用的其他示例: + +* [Cloud Native Development with GitLab](https://www.youtube.com/watch?v=jfIyQEwrocw). +* [Review Apps for Android](https://about.gitlab.com/blog/2020/05/06/how-to-create-review-apps-for-android-with-gitlab-fastlane-and-appetize-dot-io/). + +## Route Maps[](#route-maps "Permalink") + +Introduced in GitLab 8.17\. In GitLab 11.5, the file links are available in the merge request widget. + +借助路线图,您可以直接从源文件进入为 Review Apps 定义的[环境中的](../environments/index.html)公共页面. + +设置完成后,合并请求小部件中的审阅应用程序链接可以直接将您带到更改的页面,从而使预览建议的修改变得更加轻松快捷. + +配置路由图涉及到告诉 GitLab 使用路由图如何将存储库中文件的路径映射到网站上的页面路径. 设置后,GitLab 将**在" ..."**按钮**上**显示" **视图"** ,这将带您进入直接从合并请求更改的页面. + +要设置路线图,请在资源库中的`.gitlab/route-map.yml`添加一个文件,其中包含一个 YAML 数组,该数组将`source`路径(资源库中)映射到`public`路径(网站上). + +### Route Maps example[](#route-maps-example "Permalink") + +以下是[Middleman](https://middlemanapp.com)路线图的示例, [Middleman](https://middlemanapp.com)是用于构建[GitLab 网站](https://about.gitlab.com)的静态站点生成器(SSG),是从其[在 GitLab.com 上的项目](https://gitlab.com/gitlab-com/www-gitlab-com)部署的: + +``` +# Team data +- source: 'data/team.yml' # data/team.yml + public: 'team/' # team/ + +# Blogposts +- source: /source\/posts\/([0-9]{4})-([0-9]{2})-([0-9]{2})-(.+?)\..*/ # source/posts/2017-01-30-around-the-world-in-6-releases.html.md.erb + public: '\1/\2/\3/\4/' # 2017/01/30/around-the-world-in-6-releases/ + +# HTML files +- source: /source\/(.+?\.html).*/ # source/index.html.haml + public: '\1' # index.html + +# Other files +- source: /source\/(.*)/ # source/images/blogimages/around-the-world-in-6-releases-cover.png + public: '\1' # images/blogimages/around-the-world-in-6-releases-cover.png +``` + +映射定义为根 YAML 数组中的条目,并以`-`前缀标识. 在一个条目中,有一个带有两个键的哈希映射: + +* `source` + * 完全匹配的字符串,以`'`开头和结尾. + * 正则表达式,以`/`开头和结尾,用于模式匹配: + * 正则表达式需要匹配整个源路径-隐含`^`和`$`锚. + * 可以包括由`()`表示的捕获组,这些捕获组可以在`public`路径中引用. + * 斜杠( `/` )可以但不必转为`\/` . + * 文字句号( `.` )应转为`\.` . +* `public` ,一个以`'`开头和结尾的字符串. + * 可以包含`\N`表达式,从`source`正则表达式开始,以其出现的顺序引用捕获组,从`\1`开始. + +通过找到与之匹配的第一个`source`表达式,然后返回相应的`public`路径,并用`()`捕获组的值替换`\N`表达式,来确定源路径的`public`路径. + +在上面的示例中,按照定义顺序对映射进行求值的事实用于确保`source/index.html.haml`将匹配`/source\/(.+?\.html).*/`而不是`/source\/(.*)/` ,并将导致`index.html`的公共路径,而不是`index.html.haml` . + +设置路由映射后,它将在以下位置生效: + +* 在合并请求小部件中. 该: + * **"查看应用程序"**按钮将带您进入`.gitlab-ci.yml`设置的环境 URL. + * 下拉菜单将列出路线图中的前 5 个匹配项,但如果有 5 个以上可用项,则可以对其进行过滤. + + [![在合并请求小部件中查看应用程序文件列表](img/738413ec37e13f47706eeda5de3b9dfb.png)](img/view_on_mr_widget.png) + +* 在差异中进行合并请求,比较或提交. + + [!["View on env" button in merge request diff](img/ed8e7e034537074afe857aa208bd315c.png)](img/view_on_env_mr.png) + +* 在 Blob 文件视图中. + + [!["View on env" button in file view](img/1bb73cd8d699dd8fa617c328abafb76b.png)](img/view_on_env_blob.png) + +## Visual Reviews[](#visual-reviews-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10761) in GitLab Starter 12.0. + +使用视觉评论,您可以向您的评论应用程序提供反馈表单,以便评论者可以将评论直接从应用程序发布回产生评论应用程序的合并请求. + +### Configuring Visual Reviews[](#configuring-visual-reviews "Permalink") + +确保启用了`anonymous_visual_review_feedback`功能标志. 管理员可以使用 Rails 控制台启用,如下所示: + +``` +Feature.enable(:anonymous_visual_review_feedback) +``` + +反馈表单是通过您添加到 Review App 中页面的脚本提供的. 如果您拥有该项目的[开发人员权限](../../user/permissions.html) ,则可以通过单击合并请求的" **管道"**部分中的" **查看"**按钮来访问它. 如果在项目中配置了[路线图,](#route-maps)则表格模式还将显示更改页面的下拉列表. + +[![review button](img/4feb8b1885ea3a6c0945d7d32d15e8ff.png)](img/review_button.png) + +提供的脚本应添加到应用程序的``中,并由一些项目和合并请求特定的值组成. 看起来是这样的: + +``` + +``` + +理想情况下,创建每个审阅应用程序时,应在运行时使用[环境变量](../variables/predefined_variables.html)替换这些值: + +* `data-project-id`是项目 ID,可通过`CI_PROJECT_ID`变量找到. +* `data-merge-request-id`是合并请求 ID,可以通过`CI_MERGE_REQUEST_IID`变量找到它. `CI_MERGE_REQUEST_IID`仅当[`only: [merge_requests]`](../merge_request_pipelines/index.html)被使用并且在创建合并请求. +* `data-mr-url`是 GitLab 实例的 URL,并且对于所有评论应用程序都是相同的. +* `data-project-path`是项目的路径,可以通过`CI_PROJECT_PATH`找到. +* `data-require-auth`对于公共项目是可选的,但对于[私有和内部](#visual-reviews-in-private-or-internal-projects)项目则是必需[的](#visual-reviews-in-private-or-internal-projects) . 如果将其设置为`true` ,则将要求用户输入其[个人访问令牌,](../../user/profile/personal_access_tokens.html)而不是其名称和电子邮件. +* `id`始终是`review-app-toolbar-script` ,您无需更改它. +* `src`是审阅工具栏脚本的源代码,该脚本位于相应的 GitLab 实例中,并且对于所有审阅应用程序都是相同的. + +例如,在 Ruby 应用程序中,您需要具有以下脚本: + +``` + +``` + +然后,当通过 GitLab CI / CD 部署您的应用程序时,这些变量应替换为其实际值. + +### Determining merge request ID[](#determining-merge-request-id "Permalink") + +视觉审核工具从`script` HTML 标签中包含的`data-merge-request-id`数据属性中检索合并请求 ID,该`script` HTML 标签用于将视觉审核工具添加到您的审核应用中. + +确定合并请求以链接到可视评论应用程序的 ID 后,您可以通过以下任一方式提供 ID: + +* 通过应用程序的数据属性`data-merge-request-id`在 script 标签中对其进行硬编码. +* 在应用程序的构建过程中动态添加`data-merge-request-id`值. +* 通过应用中的视觉查看表单手动提供. + +### Visual Reviews in private or internal projects[](#visual-reviews-in-private-or-internal-projects "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/42750#note_317271120) . + +要对私有项目和内部项目启用可视化审阅,请将[`data-require-auth`变量设置](#configuring-visual-reviews)为`true` . 启用后,用户必须输入具有`api`范围的[个人访问令牌](../../user/profile/personal_access_tokens.html) ,然后才能提交反馈. + +### Using Visual Reviews[](#using-visual-reviews "Permalink") + +在为"评论"应用程序[启用](#configuring-visual-reviews) "视觉评论"后,"视觉评论"反馈表单将覆盖在应用程序页面的右下角. + +[![Visual review feedback form](img/482b8e23d226428516ae20fae41ca7cf.png)](img/toolbar_feeback_form.png) + +要使用反馈表: + +1. 对视觉评论发表评论. 您可以使用合并请求注释中所有可用的[Markdown 注释](../../user/markdown.html) . +2. 如果`data-require-auth`为`true` ,则必须输入[个人访问令牌](../../user/profile/personal_access_tokens.html) . 否则,您必须输入您的姓名,以及可选的电子邮件地址. +3. 最后,点击**发送反馈** . + +在视觉检查框中做出评论并提交评论后,评论将自动出现在相应的合并请求中. + +## Limitations[](#limitations "Permalink") + +Review App 限制与[环境限制](../environments/index.html#limitations)相同. \ No newline at end of file diff --git a/docs/269.md b/docs/269.md new file mode 100644 index 0000000000000000000000000000000000000000..40fb962b095b044da1b425473f67a6df30d5fa56 --- /dev/null +++ b/docs/269.md @@ -0,0 +1,401 @@ +# Configuring GitLab Runners + +> 原文:[https://docs.gitlab.com/ee/ci/runners/README.html](https://docs.gitlab.com/ee/ci/runners/README.html) + +* [Types of Runners](#types-of-runners) + * [Shared Runners](#shared-runners) + * [How shared Runners pick jobs](#how-shared-runners-pick-jobs) + * [Enable shared Runners](#enable-shared-runners) + * [Disable shared Runners](#disable-shared-runners) + * [Group Runners](#group-runners) + * [Create a group Runner](#create-a-group-runner) + * [View and manage group Runners](#view-and-manage-group-runners) + * [Pause or remove a group Runner](#pause-or-remove-a-group-runner) + * [Specific Runners](#specific-runners) + * [Create a specific Runner](#create-a-specific-runner) + * [Enable a specific Runner for a specific project](#enable-a-specific-runner-for-a-specific-project) + * [Prevent a specific Runner from being enabled for other projects](#prevent-a-specific-runner-from-being-enabled-for-other-projects) +* [Manually clear the Runner cache](#manually-clear-the-runner-cache) +* [Set maximum job timeout for a Runner](#set-maximum-job-timeout-for-a-runner) +* [Be careful with sensitive information](#be-careful-with-sensitive-information) + * [Prevent Runners from revealing sensitive information](#prevent-runners-from-revealing-sensitive-information) + * [Forks](#forks) + * [Attack vectors in Runners](#attack-vectors-in-runners) + * [Reset the Runner registration token for a project](#reset-the-runner-registration-token-for-a-project) +* [Determine the IP address of a Runner](#determine-the-ip-address-of-a-runner) + * [Determine the IP address of a shared Runner](#determine-the-ip-address-of-a-shared-runner) + * [Determine the IP address of a specific Runner](#determine-the-ip-address-of-a-specific-runner) +* [Use tags to limit the number of jobs using the Runner](#use-tags-to-limit-the-number-of-jobs-using-the-runner) + * [Runner runs only tagged jobs](#runner-runs-only-tagged-jobs) + * [Runner is allowed to run untagged jobs](#runner-is-allowed-to-run-untagged-jobs) + +# Configuring GitLab Runners[](#configuring-gitlab-runners "Permalink") + +在 GitLab CI / CD 中,运行程序运行[`.gitlab-ci.yml`](../yaml/README.html)定义的代码. GitLab Runner 是一种轻量级,高度可扩展的代理,它通过 GitLab CI / CD 的协调器 API 提取 CI 作业,运行该作业,并将结果发送回 GitLab 实例. + +运行程序由管理员创建,并在 GitLab UI 中可见. 运行者可以特定于某些项目,也可以适用于所有项目. + +## Types of Runners[](#types-of-runners "Permalink") + +跑步者共有三种类型: + +* [共享](#shared-runners) (对于所有项目) +* [组](#group-runners) (对于[组](#group-runners)中的所有项目) +* [具体](#specific-runners) (针对特定项目) + +如果您正在运行自我管理的 GitLab,则可以创建自己的 Runners. + +如果使用的是 GitLab.com,则可以使用 GitLab 提供的共享运行程序,也可以创建自己的组或特定运行程序. + +### Shared Runners[](#shared-runners "Permalink") + +GitLab 实例中的每个项目都可以使用*共享运行器* . + +当您有多个要求相似的作业时,请使用共享的运行器. 您可以让几个处理多个项目的 Runner 而不是让多个 Runner 空闲多个项目. + +如果您使用的是 GitLab 的自我管理实例: + +* 您的管理员可以通过查看[此处](https://docs.gitlab.com/runner/install/index.html)的说明来安装和注册共享运行程序. +* 管理员还可[以为每个组](../../user/admin_area/settings/continuous_integration.html#shared-runners-pipeline-minutes-quota-starter-only)配置最大的共享 Runner [管道分钟数](../../user/admin_area/settings/continuous_integration.html#shared-runners-pipeline-minutes-quota-starter-only) . + +如果您使用的是 GitLab.com: + +* 您可以从[GitLab 维护](../../user/gitlab_com/index.html#shared-runners)的[共享运行程序](../../user/gitlab_com/index.html#shared-runners)列表中进行选择. +* 共享的跑步者会消耗您帐户中包含的[管道分钟](../../subscriptions/index.html#ci-pipeline-minutes) . + +#### How shared Runners pick jobs[](#how-shared-runners-pick-jobs "Permalink") + +共享运行者通过使用合理使用队列来处理作业. 此队列可防止项目创建数百个作业并使用所有可用的共享 Runner 资源. + +合理使用队列算法根据已在共享 Runner 上运行的作业数量最少的项目分配作业. + +**Example 1** + +如果这些作业在队列中: + +* 项目 1 的工作 1 +* 项目 1 的工作 2 +* 项目 1 的工作 3 +* 项目 2 的工作 4 +* 项目 2 的工作 5 +* 项目 3 的工作 6 + +合理使用算法按以下顺序分配作业: + +1. 首先选择作业 1,因为它在没有正在运行的作业的项目(即所有项目)中具有最低的作业编号. +2. 接下来是作业 4,因为现在 4 是来自没有正在运行的作业的项目中最低的作业编号(项目 1 有正在运行的作业). +3. 接下来是作业 6,因为 6 现在是没有正在运行的作业的项目中最低的作业编号(项目 1 和 2 有正在运行的作业). +4. 接下来是作业 2,因为在运行的作业数量最少的项目(每个都有 1)中,它是最低的作业数量. +5. 接下来是作业 5,因为项目 1 现在有 2 个正在运行的作业,而作业 5 是项目 2 和项目 3 之间剩余的最低编号. +6. 最后是工作 3…,因为这是剩下的唯一工作. + +* * * + +**例子 2** + +如果这些作业在队列中: + +* 项目 1 的工作 1 +* 项目 1 的工作 2 +* 项目 1 的工作 3 +* 项目 2 的工作 4 +* 项目 2 的工作 5 +* 项目 3 的工作 6 + +合理使用算法按以下顺序分配作业: + +1. 首先选择作业 1,因为它在没有正在运行的作业的项目(即所有项目)中具有最低的作业编号. +2. 我们完成工作 1. +3. 接下来是作业 2,因为完成作业 1 后,所有项目都再次运行 0 个作业,而 2 是最低的可用作业号. +4. 接下来是作业 4,因为在项目 1 运行作业的情况下,项目 4 在没有运行作业的项目(项目 2 和 3)中是最低的. +5. 我们完成工作 4. +6. 接下来是作业 5,因为完成了作业 4,所以项目 2 没有再次运行的作业. +7. 接下来是作业 6,因为项目 3 是唯一没有运行作业的项目. +8. 最后,我们选择作业 3…,因为它再次是唯一剩下的作业. + +#### Enable shared Runners[](#enable-shared-runners "Permalink") + +在 GitLab.com 上,默认情况下在所有项目中启用[共享运行器](#shared-runners) . + +On self-managed instances of GitLab, an administrator must [install](https://docs.gitlab.com/runner/install/index.html) and [register](https://docs.gitlab.com/runner/register/index.html) them. + +您还可以为单个项目启用共享运行器. + +要启用共享跑步者: + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. Click **允许共享跑步者**. + +#### Disable shared Runners[](#disable-shared-runners "Permalink") + +您可以为单个项目禁用共享运行器. 您必须具有项目的所有者权限. + +要为项目禁用共享运行器: + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. 在" **共享运行程序"**区域中,单击" **禁用共享运行程序"** . + +### Group Runners[](#group-runners "Permalink") + +当您希望组中的所有项目都可以访问一组运行器时,请使用" *组运行器"* . + +Group Runners process jobs by using a first in, first out ([FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics))) queue. + +#### Create a group Runner[](#create-a-group-runner "Permalink") + +您可以为自己管理的 GitLab 实例或 GitLab.com 创建一个组 Runner. 您必须具有该组的[所有者权限](../../user/permissions.html#group-members-permissions) . + +创建组跑步者: + +1. [Install Runner](https://docs.gitlab.com/runner/install/). +2. 转到您要使 Runner 运行的组. +3. 去 **设置> CI / CD,**然后展开" **跑步者"**部分. +4. 注意 URL 和令牌. +5. [Register the Runner](https://docs.gitlab.com/runner/register/). + +#### View and manage group Runners[](#view-and-manage-group-runners "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/37366/) . + +您可以查看和管理组,其子组和项目的所有运行器. 您可以为自己管理的 GitLab 实例或 GitLab.com 执行此操作. 您必须具有该组的[所有者权限](../../user/permissions.html#group-members-permissions) . + +1. 转到要查看跑步者的组. +2. 去 **设置> CI / CD,**然后展开" **跑步者"**部分. +3. 显示以下字段. + + | Attribute | Description | + | --- | --- | + | Type | 以下一种或多种状态:共享,组,特定,锁定或暂停 | + | 赛跑者令牌 | 令牌用于标识 Runner,并且 Runner 用于与 GitLab 实例进行通信 | + | Description | 创建跑步者时的描述 | + | Version | GitLab Runner 版本 | + | IP 地址 | 注册了运行程序的主机的 IP 地址 | + | Projects | Runner 分配到的项目数 | + | Jobs | 跑步者所从事的工作总数 | + | Tags | 与跑步者相关的标签 | + | 最后联络人 | 指示 GitLab 实例最后一次与 Runner 联系的时间戳 | + +在此页面上,您可以编辑,暂停和从组,其子组和项目中删除"跑步者". + +#### Pause or remove a group Runner[](#pause-or-remove-a-group-runner "Permalink") + +您可以为自己管理的 GitLab 实例或 GitLab.com 暂停或删除组运行器. 您必须具有该组的[所有者权限](../../user/permissions.html#group-members-permissions) . + +1. 转到您要删除或暂停 Runner 的组. +2. 去 **设置> CI / CD,**然后展开" **跑步者"**部分. +3. Click **Pause** or **删除亚军**. + * 如果您暂停由多个项目使用的组 Runner,则 Runner 会暂停所有项目. + * 从组视图中,您无法删除分配给多个项目的运行器. 您必须先从每个项目中将其删除. +4. 在确认对话框中,单击**确定** . + +### Specific Runners[](#specific-runners "Permalink") + +当你想使用运动员的具体项目使用*特定的运动员* . 例如,当您拥有: + +* 有特定要求的作业,例如需要凭据的部署作业. +* CI 活动很多的项目可以从与其他运行者分离中受益. + +您可以设置一个特定的 Runner,以供多个项目使用. 必须为每个项目明确启用特定的运行器. + +特定运行程序通过使用[先进先出](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)) ( [FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)) )队列来处理作业. + +**注意:**特定运行器不会自动与分支项目共享. 分支*确实会*复制克隆存储库的 CI / CD 设置. + +#### Create a specific Runner[](#create-a-specific-runner "Permalink") + +您可以为自己管理的 GitLab 实例或 GitLab.com 创建特定的 Runner. 您必须具有项目的[所有者权限](../../user/permissions.html#project-members-permissions) . + +要创建特定的运行器: + +1. [Install Runner](https://docs.gitlab.com/runner/install/). +2. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +3. 注意 URL 和令牌. +4. [Register the Runner](https://docs.gitlab.com/runner/register/). + +#### Enable a specific Runner for a specific project[](#enable-a-specific-runner-for-a-specific-project "Permalink") + +在为其创建的项目中提供了特定的 Runner. 管理员可以使特定的 Runner 应用于其他项目. + +* 您必须具有项目的所有者权限. +* 特定的跑步者一定不能被[锁定](#prevent-a-specific-runner-from-being-enabled-for-other-projects) . + +要为项目启用或禁用特定的运行器: + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. Click **为此项目启用** or **为此项目禁用**. + +#### Prevent a specific Runner from being enabled for other projects[](#prevent-a-specific-runner-from-being-enabled-for-other-projects "Permalink") + +您可以配置一个特定的运行器,使其"锁定"并且不能为其他项目启用. 首次[注册 Runner](https://docs.gitlab.com/runner/register/)时可以启用此设置,但以后也可以更改. + +锁定或解锁跑步者: + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. 找到您想要锁定或解锁的亚军. 确保已启用. +3. 单击铅笔按钮. +4. 选中" **锁定到当前项目"**选项. +5. Click **保存更改**. + +## Manually clear the Runner cache[](#manually-clear-the-runner-cache "Permalink") + +Read [clearing the cache](../caching/index.html#clearing-the-cache). + +## Set maximum job timeout for a Runner[](#set-maximum-job-timeout-for-a-runner "Permalink") + +对于每个跑步者,您可以指定*最大作业超时时间* . 如果此超时时间小于[项目定义的超时时间](../pipelines/settings.html#timeout) ,则优先. + +此功能可用于防止共享的 Runner 被具有较长超时(例如,一个星期)的工作的项目淹没. + +未配置时,Runner 将不会覆盖项目超时. + +此功能的工作原理: + +**示例 1-运行程序超时大于项目超时** + +1. 您将跑步者的*最大作业超时*设置为 24 小时 +2. 您将项目的*CI / CD 超时*设置为**2 小时** +3. 你开始工作 +4. 如果工作时间更长,则**2 小时**后将超时 + +**示例 2-未配置运行程序超时** + +1. 您从运行器中删除*最大作业超时*配置 +2. 您将项目的*CI / CD 超时*设置为**2 小时** +3. 你开始工作 +4. 如果工作时间更长,则**2 小时**后将超时 + +**示例 3-运行程序超时小于项目超时** + +1. 您将跑步者的*最大作业超时*设置为**30 分钟** +2. 您将项目的*CI / CD 超时*设置为 2 小时 +3. 你开始工作 +4. 如果作业时间更长,则**30 分钟**后将超时 + +## Be careful with sensitive information[](#be-careful-with-sensitive-information "Permalink") + +使用某些[Runner Executors](https://docs.gitlab.com/runner/executors/README.html) ,如果可以在 Runner 上运行作业,则可以完全访问文件系统,从而可以运行该文件的任何代码以及 Runner 的令牌. 使用共享的运行程序,这意味着在运行程序上运行作业的任何人都可以访问在运行程序上运行的任何其他人的代码. + +另外,由于您可以访问 Runner 令牌,因此可以创建 Runner 的克隆并提交错误的作业. + +通过限制在大型公共 GitLab 实例上共享[Runner 的](https://docs.gitlab.com/runner/executors/README.html)使用,控制对 GitLab 实例的访问以及使用更安全的[Runner Executor](https://docs.gitlab.com/runner/executors/README.html) ,可以轻松避免上述情况. + +### Prevent Runners from revealing sensitive information[](#prevent-runners-from-revealing-sensitive-information "Permalink") + +在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13194) . + +您可以保护赛跑者,使他们不会泄露敏感信息. 当运行器受到保护时,运行器仅选择在[受保护分支](../../user/project/protected_branches.html)或[受保护标签](../../user/project/protected_tags.html)上创建的作业,而忽略其他作业. + +保护或取消保护跑步者: + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. 找到您要保护或取消保护的跑步者. 确保已启用. +3. 单击铅笔按钮. +4. 检查**受保护的**选项. +5. Click **保存更改**. + +[![specific Runners edit icon](img/91abd5be225ec3a5c131075cce857fb8.png)](img/protected_runners_check_box.png) + +### Forks[](#forks "Permalink") + +每当分支一个项目时,它都会复制与其相关的作业的设置. 这意味着,如果您已经为项目设置了共享的 Runners,并且有人分叉了该项目,则共享的 Runners 也将为该项目的工作提供服务. + +### Attack vectors in Runners[](#attack-vectors-in-runners "Permalink") + +前面已经简要提到过,但是可以利用 Runners 的以下功能. 我们一直在寻找可以减轻这些[安全注意事项的因素](https://docs.gitlab.com/runner/security/) . + +### Reset the Runner registration token for a project[](#reset-the-runner-registration-token-for-a-project "Permalink") + +如果您认为某个项目的注册令牌已公开,则应将其重置. 令牌可用于为该项目注册另一个 Runner. 然后可以使用该新 Runner 来获取秘密变量的值或克隆项目代码. + +重置令牌: + +1. 转到项目的 **设置> CI / CD** . +2. 展开**常规管道设置**部分. +3. 找到" **跑步者令牌"**表单字段,然后单击" **显示值"**按钮. +4. 删除值并保存表单. +5. 刷新页面后,展开" **跑步者设置"**部分并检查注册令牌-应该更改它. + +从现在开始,旧令牌将不再有效,并且不会在项目中注册任何新的运行者. 如果您使用任何工具来供应和注册新的运行器,则应更新这些工具中使用的令牌以反映新令牌的价值. + +## Determine the IP address of a Runner[](#determine-the-ip-address-of-a-runner "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17286) . + +知道 Runner 的 IP 地址可能很有用,以便您可以解决该 Runner 的问题. GitLab 通过在轮询作业时查看向 GitLab 发出的 HTTP 请求的源来存储和显示 IP 地址. IP 地址始终保持最新,因此,如果 Runner IP 更改,它将在 GitLab 中自动更新. + +共享运行程序和特定运行程序的 IP 地址可以在不同位置找到. + +### Determine the IP address of a shared Runner[](#determine-the-ip-address-of-a-shared-runner "Permalink") + +要查看共享运行器的 IP 地址,您必须具有对 GitLab 实例的管理员访问权限. 要确定这一点: + +1. Visit **管理区域>概述>跑步者**. +2. 在表中查找 Runner,您应该看到**IP Address**列. + +[![shared Runner IP address](img/d0b0b1ad83988d76ef9c42281782f961.png)](img/shared_runner_ip_address.png) + +### Determine the IP address of a specific Runner[](#determine-the-ip-address-of-a-specific-runner "Permalink") + +若要查找特定项目的运行程序的 IP 地址,您必须具有该项目的所有者[权限](../../user/permissions.html#project-members-permissions) . + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. 在详细信息页面上,您应该看到**IP 地址**行. + +[![specific Runner IP address](img/b6c59d6785a7941658315a7e8e148751.png)](img/specific_runner_ip_address.png) + +## Use tags to limit the number of jobs using the Runner[](#use-tags-to-limit-the-number-of-jobs-using-the-runner "Permalink") + +您必须设置一个 Runner 才能运行它在共享项目上可能遇到的所有不同类型的作业. 如果不是标签,这对于大量项目将是有问题的. + +通过将 Runner 标记为它可以处理的作业类型,可以确保共享的 Runners [仅运行其能够运行的作业](../yaml/README.html#tags) . + +例如,在 GitLab 上,如果 Runners 包含运行 Rails 测试套件的适当依赖项,我们会将它们标记为`rails` . + +[注册 Runner 时](https://docs.gitlab.com/runner/register/) ,其默认行为是**仅选择带** [标签的作业](../yaml/README.html#tags) . 要更改此设置,您必须具有项目的所有者[权限](../../user/permissions.html#project-members-permissions) . + +要使跑步者选择无标签的工作,请执行以下操作: + +1. 转到项目的 **设置> CI / CD,**然后展开" **跑步者"**部分. +2. 找到您要选择未加标签的作业的 Runner,并确保已启用它. +3. 单击铅笔按钮. +4. 选中**运行未加标签的作业**选项. +5. 单击**保存更改**按钮以使更改生效. + +**注意:**不允许选择未标记的作业时,"运行者标签"列表不能为空. + +以下是一些不同变化的示例场景. + +### Runner runs only tagged jobs[](#runner-runs-only-tagged-jobs "Permalink") + +以下示例说明了将 Runner 设置为仅运行带标签的作业的潜在影响. + +范例 1: + +1. Runner 配置为仅运行带标签的作业,并具有`docker`标签. +2. 具有`hello`标签的作业将被执行并卡住. + +Example 2: + +1. Runner 配置为仅运行带标签的作业,并具有`docker`标签. +2. 具有`docker`标签的作业将被执行并运行. + +范例 3: + +1. Runner 配置为仅运行带标签的作业,并具有`docker`标签. +2. 没有定义标签的作业将被执行并卡住. + +### Runner is allowed to run untagged jobs[](#runner-is-allowed-to-run-untagged-jobs "Permalink") + +以下示例说明了将 Runner 设置为运行带标签和未带标签的作业的潜在影响. + +范例 1: + +1. Runner 配置为运行未加标签的作业,并具有`docker`标签. +2. 没有定义标签的作业将被执行并运行. +3. 执行并运行定义了`docker`标签的第二项作业. + +范例 2: + +1. Runner 配置为运行未加标签的作业,并且未定义标签. +2. 没有定义标签的作业将被执行并运行. +3. 卡有定义了`docker`标签的第二项工作. \ No newline at end of file diff --git a/docs/270.md b/docs/270.md new file mode 100644 index 0000000000000000000000000000000000000000..60d75537429e5245d76951ac3b4f82e032dedf8f --- /dev/null +++ b/docs/270.md @@ -0,0 +1,13 @@ +# GitLab CI services examples + +> 原文:[https://docs.gitlab.com/ee/ci/services/README.html](https://docs.gitlab.com/ee/ci/services/README.html) + +# GitLab CI services examples[](#gitlab-ci-services-examples "Permalink") + +[`services`](../docker/using_docker_images.html#what-is-a-service)关键字定义了一个 Docker 映像,该映像在与 image 关键字定义的 Docker 映像链接的`job`中运行. 这样,您就可以在构建期间访问服务映像. + +服务映像可以运行任何应用程序,但是最常见的用例是运行数据库容器,例如: + +* [Using MySQL](mysql.html) +* [Using PostgreSQL](postgres.html) +* [Using Redis](redis.html) \ No newline at end of file diff --git a/docs/271.md b/docs/271.md new file mode 100644 index 0000000000000000000000000000000000000000..02831128f8e31db9a482fe8f649ba3718f2a48e4 --- /dev/null +++ b/docs/271.md @@ -0,0 +1,111 @@ +# Using MySQL + +> 原文:[https://docs.gitlab.com/ee/ci/services/mysql.html](https://docs.gitlab.com/ee/ci/services/mysql.html) + +* [Use MySQL with the Docker executor](#use-mysql-with-the-docker-executor) +* [Use MySQL with the Shell executor](#use-mysql-with-the-shell-executor) +* [Example project](#example-project) + +# Using MySQL[](#using-mysql "Permalink") + +由于许多应用程序都依赖 MySQL 作为其数据库,因此最终需要它才能运行测试. 下面将指导您如何使用 GitLab Runner 的 Docker 和 Shell 执行程序执行此操作. + +## Use MySQL with the Docker executor[](#use-mysql-with-the-docker-executor "Permalink") + +如果您将[GitLab Runner](../runners/README.html)与 Docker 执行程序一起使用,则基本上已经完成了所有设置. + +First, in your `.gitlab-ci.yml` add: + +``` +services: + - mysql:latest + +variables: + # Configure mysql environment variables (https://hub.docker.com/_/mysql/) + MYSQL_DATABASE: "" + MYSQL_ROOT_PASSWORD: "" +``` + +**注意:**无法在 GitLab UI 中设置`MYSQL_DATABASE`和`MYSQL_ROOT_PASSWORD`变量. 要设置它们,请将它们分配给[UI 中](../variables/README.html#create-a-custom-variable-in-the-ui)的变量,然后将该变量分配给`.gitlab-ci.yml`的`MYSQL_DATABASE`和`MYSQL_ROOT_PASSWORD`变量. + +然后将您的应用程序配置为使用数据库,例如: + +``` +Host: mysql +User: root +Password: +Database: +``` + +如果您想知道为什么我们对`Host`使用`mysql` ,请阅读[如何将服务链接到作业的更多信息](../docker/using_docker_images.html#how-services-are-linked-to-the-job) . + +您还可以使用[Docker Hub](https://hub.docker.com/_/mysql/)上可用的任何其他 Docker 映像. 例如,要使用 MySQL 5.5,服务将变为`mysql:5.5` . + +`mysql`映像可以接受一些环境变量. 有关更多详细信息,请参阅[Docker Hub](https://hub.docker.com/_/mysql/)上的文档. + +## Use MySQL with the Shell executor[](#use-mysql-with-the-shell-executor "Permalink") + +您还可以在手动配置的服务器上使用 MySQL,该服务器通过 Shell 执行程序使用 GitLab Runner. + +首先安装 MySQL 服务器: + +``` +sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev +``` + +选择一个 MySQL 根密码(可以是任何密码),并在询问时键入两次. + +*注意:作为一项安全措施,您可以运行`mysql_secure_installation`删除匿名用户,删除测试数据库并以 root 用户禁用远程登录.* + +下一步是创建用户,因此以 root 用户身份登录 MySQL: + +``` +mysql -u root -p +``` + +然后创建一个将由您的应用程序使用的用户(在我们的示例中为`runner` ). 将以下命令中的`$password`更改`$password`真实的强密码. + +*注意:请勿键入`mysql>` ,这是 MySQL 提示符的一部分.* + +``` +mysql> CREATE USER 'runner'@'localhost' IDENTIFIED BY '$password'; +``` + +创建数据库: + +``` +mysql> CREATE DATABASE IF NOT EXISTS `` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`; +``` + +授予对数据库的必要权限: + +``` +mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES ON ``.* TO 'runner'@'localhost'; +``` + +如果一切顺利,您现在可以退出数据库会话: + +``` +mysql> \q +``` + +现在,尝试连接到新创建的数据库以检查一切是否就绪: + +``` +mysql -u runner -p -D +``` + +最后,配置您的应用程序以使用数据库,例如: + +``` +Host: localhost +User: runner +Password: $password +Database: +``` + +## Example project[](#example-project "Permalink") + +为了方便起见,我们使用公共可[共享的](../runners/README.html)运行程序在[GitLab.com](https://gitlab.com)上运行了一个[MySQL 示例项目](https://gitlab.com/gitlab-examples/mysql) . + +想要破解吗? 只需对其进行分叉,提交并推送您的更改. 稍后,公共跑步者将选择更改并开始工作. \ No newline at end of file diff --git a/docs/272.md b/docs/272.md new file mode 100644 index 0000000000000000000000000000000000000000..9e1748a8c9e857e83976a37c80e059e917526e95 --- /dev/null +++ b/docs/272.md @@ -0,0 +1,106 @@ +# Using PostgreSQL + +> 原文:[https://docs.gitlab.com/ee/ci/services/postgres.html](https://docs.gitlab.com/ee/ci/services/postgres.html) + +* [Use PostgreSQL with the Docker executor](#use-postgresql-with-the-docker-executor) +* [Use PostgreSQL with the Shell executor](#use-postgresql-with-the-shell-executor) +* [Example project](#example-project) + +# Using PostgreSQL[](#using-postgresql "Permalink") + +由于许多应用程序都依赖 PostgreSQL 作为其数据库,因此最终需要它才能运行测试. 下面将指导您如何使用 GitLab Runner 的 Docker 和 Shell 执行程序执行此操作. + +## Use PostgreSQL with the Docker executor[](#use-postgresql-with-the-docker-executor "Permalink") + +如果您将[GitLab Runner](../runners/README.html)与 Docker 执行程序一起使用,则基本上已经完成了所有设置. + +首先,在您的`.gitlab-ci.yml`添加: + +``` +services: + - postgres:12.2-alpine + +variables: + POSTGRES_DB: nice_marmot + POSTGRES_USER: runner + POSTGRES_PASSWORD: "" + POSTGRES_HOST_AUTH_METHOD: trust +``` + +**注意:**不能在 GitLab UI 中设置`POSTGRES_DB` , `POSTGRES_USER` , `POSTGRES_PASSWORD`和`POSTGRES_HOST_AUTH_METHOD`变量. 要设置它们,请将它们分配给[UI 中](../variables/README.html#create-a-custom-variable-in-the-ui)的变量,然后将该变量分配给`.gitlab-ci.yml`的`POSTGRES_DB` , `POSTGRES_USER` , `POSTGRES_PASSWORD`和`POSTGRES_HOST_AUTH_METHOD`变量. + +然后将您的应用程序配置为使用数据库,例如: + +``` +Host: postgres +User: runner +Password: '' +Database: nice_marmot +``` + +如果您想知道为什么我们对`Host`使用`postgres` ,请阅读[如何将服务链接到作业的更多信息](../docker/using_docker_images.html#how-services-are-linked-to-the-job) . + +您还可以使用[Docker Hub](https://hub.docker.com/_/postgres)上可用的任何其他 Docker 映像. 例如,要使用 PostgreSQL 9.3,服务将变为`postgres:9.3` . + +`postgres`图像可以接受一些环境变量. 有关更多详细信息,请参阅[Docker Hub](https://hub.docker.com/_/postgres)上的文档. + +## Use PostgreSQL with the Shell executor[](#use-postgresql-with-the-shell-executor "Permalink") + +您还可以在手动配置的服务器上使用 PostgreSQL,这些服务器将 GitLab Runner 与 Shell 执行程序一起使用. + +首先安装 PostgreSQL 服务器: + +``` +sudo apt-get install -y postgresql postgresql-client libpq-dev +``` + +下一步是创建用户,因此登录 PostgreSQL: + +``` +sudo -u postgres psql -d template1 +``` + +然后创建一个将由您的应用程序使用的用户(在我们的示例中为`runner` ). 将以下命令中的`$password`更改`$password`真实的强密码. + +***注意:**不要输入`template1=#` ,这是 PostgreSQL 提示的一部分.* + +``` +template1=# CREATE USER runner WITH PASSWORD '$password' CREATEDB; +``` + +***注意:**请注意,我们创建的用户具有创建数据库的特权( `CREATEDB` ). 在以下步骤中,我们将为该用户显式创建一个数据库,但是如果在您的测试框架中有删除和创建数据库的工具,则具有该特权将很有用.* + +创建数据库,并授予其上的所有特权用户`runner` : + +``` +template1=# CREATE DATABASE nice_marmot OWNER runner; +``` + +如果一切顺利,您现在可以退出数据库会话: + +``` +template1=# \q +``` + +现在,尝试连接到与用户新创建的数据库`runner`检查一切就绪. + +``` +psql -U runner -h localhost -d nice_marmot -W +``` + +***注意:**我们明确告诉`psql`连接到 localhost 以便使用 md5 身份验证. 如果您省略此步骤,则将被拒绝访问.* + +最后,将您的应用程序配置为使用数据库,例如: + +``` +Host: localhost +User: runner +Password: $password +Database: nice_marmot +``` + +## Example project[](#example-project "Permalink") + +为了方便起见,我们使用公共可[共享的](../runners/README.html)运行程序在[GitLab.com](https://gitlab.com)上运行了一个[示例 PostgreSQL 项目](https://gitlab.com/gitlab-examples/postgres) . + +想要破解吗? 只需对其进行分叉,提交并推送您的更改. 稍后,公共跑步者将选择更改并开始工作. \ No newline at end of file diff --git a/docs/273.md b/docs/273.md new file mode 100644 index 0000000000000000000000000000000000000000..618b9ef1c1723e2d6caf917dc7d613fd8fe5d029 --- /dev/null +++ b/docs/273.md @@ -0,0 +1,64 @@ +# Using Redis + +> 原文:[https://docs.gitlab.com/ee/ci/services/redis.html](https://docs.gitlab.com/ee/ci/services/redis.html) + +* [Use Redis with the Docker executor](#use-redis-with-the-docker-executor) +* [Use Redis with the Shell executor](#use-redis-with-the-shell-executor) +* [Example project](#example-project) + +# Using Redis[](#using-redis "Permalink") + +由于许多应用程序都将 Redis 用作键值存储,因此最终需要它才能运行测试. 下面将指导您如何使用 GitLab Runner 的 Docker 和 Shell 执行程序执行此操作. + +## Use Redis with the Docker executor[](#use-redis-with-the-docker-executor "Permalink") + +如果您将[GitLab Runner](../runners/README.html)与 Docker 执行程序一起使用,则基本上已经完成了所有设置. + +首先,在您的`.gitlab-ci.yml`添加: + +``` +services: + - redis:latest +``` + +然后,您需要配置您的应用程序以使用 Redis 数据库,例如: + +``` +Host: redis +``` + +就是这样. 现在可以在您的测试框架中使用 Redis. + +您还可以使用[Docker Hub](https://hub.docker.com/_/redis)上可用的任何其他 Docker 映像. 例如,要使用 Redis 2.8,服务将变为`redis:2.8` . + +## Use Redis with the Shell executor[](#use-redis-with-the-shell-executor "Permalink") + +Redis 也可以在手动配置的服务器上使用,该服务器与 Shell 执行程序一起使用 GitLab Runner. + +在您的构建机器中安装 Redis 服务器: + +``` +sudo apt-get install redis-server +``` + +验证您可以使用`gitlab-runner`用户连接到服务器: + +``` +# Try connecting the Redis server +sudo -u gitlab-runner -H redis-cli + +# Quit the session +127.0.0.1:6379> quit +``` + +最后,将您的应用程序配置为使用数据库,例如: + +``` +Host: localhost +``` + +## Example project[](#example-project "Permalink") + +为了方便起见,我们使用公共可[共享的](../runners/README.html)运行程序在[GitLab.com](https://gitlab.com)上运行了[示例 Redis 项目](https://gitlab.com/gitlab-examples/redis) . + +想要破解吗? 只需对其进行分叉,提交并推送您的更改. 稍后,公共跑步者将选择更改并开始工作. \ No newline at end of file diff --git a/docs/274.md b/docs/274.md new file mode 100644 index 0000000000000000000000000000000000000000..4fd99cdea4fcd3d15007dc8ba14e373593e5ea04 --- /dev/null +++ b/docs/274.md @@ -0,0 +1,40 @@ +# Troubleshooting CI/CD + +> 原文:[https://docs.gitlab.com/ee/ci/troubleshooting.html](https://docs.gitlab.com/ee/ci/troubleshooting.html) + +* [Merge request pipeline widget](#merge-request-pipeline-widget) + * [“Checking pipeline status”](#checking-pipeline-status) +* [Merge request ability to merge widget](#merge-request-ability-to-merge-widget) + * [“A CI/CD pipeline must run and be successful before merge”](#a-cicd-pipeline-must-run-and-be-successful-before-merge) + +# Troubleshooting CI/CD[](#troubleshooting-cicd "Permalink") + +## Merge request pipeline widget[](#merge-request-pipeline-widget "Permalink") + +合并请求管道小部件在"合并请求"中显示有关管道状态的信息. [在合并小部件](#merge-request-ability-to-merge-widget)的[合并请求功能](#merge-request-ability-to-merge-widget)上方显示. + +根据管道的状态,可以显示几条消息. + +### “Checking pipeline status”[](#checking-pipeline-status "Permalink") + +This message is shown when the merge request has no pipeline associated with the latest commit yet and [Pipelines must succeed](../user/project/merge_requests/merge_when_pipeline_succeeds.html#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds) is turned on. This might be because: + +* GitLab 尚未完成创建管道. +* 您正在使用外部 CI 服务,但 GitLab 尚未收到该服务的回音. +* 您没有在项目中使用 CI / CD 管道. + +创建管道后,该消息将更新为管道状态. + +注意:当前,如果您删除合并请求的最新管道,则将显示此消息,而不是有意义的错误消息. 这是一个已知问题,应尽快解决. + +## Merge request ability to merge widget[](#merge-request-ability-to-merge-widget "Permalink") + +合并请求状态窗口小部件显示" **合并"**按钮以及合并请求是否准备就绪. 如果合并请求无法合并,则会显示原因. + +如果管道仍在运行,则将" **合并"**按钮替换为" **管道成功后合并"**按钮. + +如果[**合并火车**](merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)被启用,按钮要么**加入到合并列车**或**添加到合并火车时管道成功** . + +### “A CI/CD pipeline must run and be successful before merge”[](#a-cicd-pipeline-must-run-and-be-successful-before-merge "Permalink") + +如果在项目中启用了" [管道必须成功"](../user/project/merge_requests/merge_when_pipeline_succeeds.html#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds)设置,并且管道尚未成功运行,则会显示此消息. 如果尚未创建管道,或者正在等待外部 CI 服务,则这也适用. 如果您的项目不使用管道,则应禁用**管道必须成功**才能接受合并请求. \ No newline at end of file diff --git a/docs/275.md b/docs/275.md new file mode 100644 index 0000000000000000000000000000000000000000..ca98781ccc53d11ca2fe0b4aad258ea0065ab15b --- /dev/null +++ b/docs/275.md @@ -0,0 +1,120 @@ +# GitLab Package Registry + +> 原文:[https://docs.gitlab.com/ee/user/packages/](https://docs.gitlab.com/ee/user/packages/) + +* [View packages](#view-packages) +* [Use GitLab CI/CD to build packages](#use-gitlab-cicd-to-build-packages) +* [Download a package](#download-a-package) +* [Delete a package](#delete-a-package) +* [Disable the Package Registry](#disable-the-package-registry) +* [Package workflows](#package-workflows) +* [Suggested contributions](#suggested-contributions) + +# GitLab Package Registry[](#gitlab-package-registry "Permalink") + +借助 GitLab 软件包注册表,您可以将 GitLab 用作各种常见软件包管理器的私有或公共存储库. 您可以构建和发布程序包,这些程序包可以很容易地作为下游项目中的依赖项使用. + +GitLab 充当以下内容的存储库: + +| 软件库 | Description | 在 GitLab 版本中可用 | +| --- | --- | --- | +| [Container Registry](container_registry/index.html) | GitLab 容器注册表使 GitLab 中的每个项目都有自己的空间来存储[Docker](https://www.docker.com/)映像. | 8.8+ | +| [Dependency Proxy](dependency_proxy/index.html) | GitLab 依赖代理为经常使用的上游映像/软件包设置了本地代理. | 11.11+ | +| [Conan Repository](conan_repository/index.html) | GitLab 柯南存储库使 GitLab 中的每个项目都有自己的空间来存储[柯南](https://conan.io/)软件包. | 12.6+ | +| [Maven Repository](maven_repository/index.html) | GitLab Maven 存储库使 GitLab 中的每个项目都有自己的空间来存储[Maven](https://maven.apache.org/)软件包. | 11.3+ | +| [NPM Registry](npm_registry/index.html) | GitLab NPM 注册表使 GitLab 中的每个项目都有自己的空间来存储[NPM](https://s0www0npmjs0com.icopy.site/)软件包. | 11.7+ | +| [NuGet Repository](nuget_repository/index.html) | GitLab NuGet 存储库将使 GitLab 中的每个项目都有自己的空间来存储[NuGet](https://www.nuget.org/)软件包. | 12.8+ | +| [PyPi Repository](pypi_repository/index.html) | GitLab PyPi 存储库将使 GitLab 中的每个项目都有自己的空间来存储[PyPi](https://s0pypi0org.icopy.site/)软件包. | 12.10+ | +| [Go Proxy](go_proxy/index.html) | GitLab 的 Go 代理使 GitLab 中的每个项目都可以通过[Go 代理协议](https://proxy.golang.org/)获取. | 13.1+ | +| [Composer Repository](composer_repository/index.html) | GitLab Composer 存储库将使 GitLab 中的每个项目都有自己的空间来存储[Composer](https://s0getcomposer0org.icopy.site/)软件包. | 13.2+ | + +## View packages[](#view-packages "Permalink") + +您可以查看项目或组的软件包. + +1. 转到项目或组. +2. 去 **程序包和注册表>程序包注册表** . + +您可以在此页面上搜索,排序和过滤软件包. + +有关如何创建和上传软件包的信息,请查看您的软件包类型的 GitLab 文档. + +## Use GitLab CI/CD to build packages[](#use-gitlab-cicd-to-build-packages "Permalink") + +您可以使用[GitLab CI / CD](./../../ci/README.html)来构建软件包. 对于 Maven 和 NPM 软件包以及 Composer 依赖项,可以使用`CI_JOB_TOKEN`向 GitLab 进行身份验证. + +CI / CD 模板,你可以用它来上手,在[此回购](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates) . + +了解有关[使用 CI / CD 构建 Maven 软件包](maven_repository/index.html#creating-maven-packages-with-gitlab-cicd)和[NPM 软件包的更多信息](npm_registry/index.html#publishing-a-package-with-cicd) . + +如果使用 CI / CD 构建软件包,则在查看软件包详细信息时会显示扩展的活动信息: + +[![Package CI/CD activity](img/5d1d35707b32fd37e1e218e8b1df1771.png)](img/package_activity_v12_10.png) + +您可以查看哪个管道发布了程序包,以及触发该程序包的提交和用户. + +## Download a package[](#download-a-package "Permalink") + +要下载软件包: + +1. 去 **程序包和注册表>程序包注册表** . +2. 单击您要下载的软件包的名称. +3. 在" **活动"**部分中,单击要下载的程序包的名称. + +## Delete a package[](#delete-a-package "Permalink") + +在程序包注册表中发布程序包后,您将无法对其进行编辑. 相反,您必须删除并重新创建它. + +* 您无法从组视图中删除软件包. 您必须改为从项目视图中删除它们. 有关详细信息,请参[见此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/227714) . +* 您必须具有适当的[权限](../permissions.html) . + +您可以使用[API](../../api/packages.html#delete-a-project-package)或 UI 删除软件包. + +要在用户界面中删除程序包: + +1. 去 **程序包和注册表>程序包注册表** . +2. 查找您要删除的程序包的名称. +3. Click **Delete**. + +该软件包将被永久删除. + +## Disable the Package Registry[](#disable-the-package-registry "Permalink") + +程序包注册表自动启用. + +如果您使用的是 GitLab 的自我管理实例,则管理员可以删除菜单项, **软件包和注册表** ,位于 GitLab 侧边栏. 有关更多信息,请参阅[管理文档](../../administration/packages/index.html) . + +您还可以专门删除项目的 Package Registry: + +1. 在您的项目中,转到 **设置>常规** . +2. 展开" **可见性","项目功能","权限"**部分,并禁用" **软件包"**功能. +3. Click **Save changes**. + +的 **Packages&Registries> Package Registry**条目已从侧栏中删除. + +## Package workflows[](#package-workflows "Permalink") + +了解如何使用 GitLab 软件包注册表来构建自己的自定义软件包工作流程. + +* [使用项目作为程序包注册表](./workflows/project_registry.html)将所有[程序包](./workflows/project_registry.html)发布到一个项目. +* 从一个[monorepo 项目](./workflows/monorepo.html)发布多个不同的软件包. + +## Suggested contributions[](#suggested-contributions "Permalink") + +考虑为 GitLab 做贡献. 此[开发文档](../../development/packages.html)将指导您完成该过程. 或者查看社区的其他成员如何添加对[PHP](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17417)或[Terraform 的](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834)支持. + +| Format | 用例 | +| --- | --- | +| [Cargo](https://gitlab.com/gitlab-org/gitlab/-/issues/33060) | Cargo 是 Rust 的包裹经理. 构建,发布和共享 Rust 包 | +| [Chef](https://gitlab.com/gitlab-org/gitlab/-/issues/36889) | 使用 Chef 的配置管理,利用存储库管理器的所有优点. | +| [CocoaPods](https://gitlab.com/gitlab-org/gitlab/-/issues/36890) | 使用 Xcode 和 CocoaPods 加快开发速度. | +| [Conda](https://gitlab.com/gitlab-org/gitlab/-/issues/36891) | 安全和私有的本地 Conda 存储库. | +| [CRAN](https://gitlab.com/gitlab-org/gitlab/-/issues/36892) | 部署和解析 R 语言的 CRAN 软件包. | +| [Debian](https://gitlab.com/gitlab-org/gitlab/-/issues/5835) | 托管和设置 Debian 软件包. | +| [Opkg](https://gitlab.com/gitlab-org/gitlab/-/issues/36894) | 使用 Opkg 存储库优化 OpenWrt 的工作. | +| [P2](https://gitlab.com/gitlab-org/gitlab/-/issues/36895) | 将所有 Eclipse 插件托管在自己的 GitLab P2 存储库中. | +| [Puppet](https://gitlab.com/gitlab-org/gitlab/-/issues/36897) | 配置管理通过 Puppet 存储库满足存储库管理. | +| [RPM](https://gitlab.com/gitlab-org/gitlab/-/issues/5932) | 直接从 GitLab 分发 RPM. | +| [RubyGems](https://gitlab.com/gitlab-org/gitlab/-/issues/803) | 使用 GitLab 托管您自己的宝石. | +| [SBT](https://gitlab.com/gitlab-org/gitlab/-/issues/36898) | 运行 SBT 构建时,解析来自 SBT 存储库的依赖性并将构建输出部署到 SBT 存储库. | +| [Vagrant](https://gitlab.com/gitlab-org/gitlab/-/issues/36899) | 将您的 Vagrant 盒子安全地托管在本地存储库中. | \ No newline at end of file diff --git a/docs/276.md b/docs/276.md new file mode 100644 index 0000000000000000000000000000000000000000..ba7f9fdeee2ab01f3af0b21f4dad444d9568cda2 --- /dev/null +++ b/docs/276.md @@ -0,0 +1,580 @@ +# GitLab Container Registry + +> 原文:[https://docs.gitlab.com/ee/user/packages/container_registry/](https://docs.gitlab.com/ee/user/packages/container_registry/) + +* [Enable the Container Registry for your project](#enable-the-container-registry-for-your-project) +* [Control Container Registry from within GitLab](#control-container-registry-from-within-gitlab) + * [Control Container Registry for your project](#control-container-registry-for-your-project) + * [Control Container Registry for your group](#control-container-registry-for-your-group) + * [Image Repository details page](#image-repository-details-page) +* [Use images from GitLab Container Registry](#use-images-from-gitlab-container-registry) +* [Authenticating to the GitLab Container Registry](#authenticating-to-the-gitlab-container-registry) +* [Build and push images from your local machine](#build-and-push-images-from-your-local-machine) +* [Build and push images using GitLab CI/CD](#build-and-push-images-using-gitlab-cicd) + * [Authenticating to the Container Registry with GitLab CI/CD](#authenticating-to-the-container-registry-with-gitlab-cicd) + * [Container Registry examples with GitLab CI/CD](#container-registry-examples-with-gitlab-cicd) + * [Using a Docker-in-Docker image from your Container Registry](#using-a-docker-in-docker-image-from-your-container-registry) +* [Delete images](#delete-images) + * [Delete images from within GitLab](#delete-images-from-within-gitlab) + * [Delete images using the API](#delete-images-using-the-api) + * [Delete images using GitLab CI/CD](#delete-images-using-gitlab-cicd) + * [Delete images by using a cleanup policy](#delete-images-by-using-a-cleanup-policy) +* [Cleanup policy](#cleanup-policy) + * [Managing project cleanup policy through the UI](#managing-project-cleanup-policy-through-the-ui) + * [Troubleshooting cleanup policies](#troubleshooting-cleanup-policies) + * [Managing project cleanup policy through the API](#managing-project-cleanup-policy-through-the-api) + * [Use with external container registries](#use-with-external-container-registries) + * [Regex pattern examples](#regex-pattern-examples) +* [Use the Container Registry to store Helm Charts](#use-the-container-registry-to-store-helm-charts) +* [Limitations](#limitations) +* [Troubleshooting the GitLab Container Registry](#troubleshooting-the-gitlab-container-registry) + * [Docker connection error](#docker-connection-error) + * [Troubleshoot as a GitLab server admin](#troubleshoot-as-a-gitlab-server-admin) + * [Unable to change path or transfer a project](#unable-to-change-path-or-transfer-a-project) + +# GitLab Container Registry[](#gitlab-container-registry "Permalink") + +版本历史 + +* 在 GitLab 8.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4040) . +* 在 GitLab 8.9 中添加了 Docker Registry manifest `v1`支持,以支持 1.10 之前的 Docker 版本. +* 从 GitLab 8.12 开始,如果您的帐户中启用了 2FA,则需要传递[个人访问令牌(](../../profile/personal_access_tokens.html)而不是密码)才能登录到 GitLab 的 Container Registry. +* 在 GitLab 9.1 中添加了多级图像名称支持. +* 组级容器注册表是在 GitLab 12.10 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/issues/23315) . +* 在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31322)了按图像存储库名称搜索. + +**注意:**本文档是用户指南. 要了解如何在整个 GitLab 实例上启用 GitLab 容器注册表,请访问[管理员文档](../../../administration/packages/container_registry.html) . + +通过将 Docker 容器注册表集成到 GitLab 中,每个项目都可以拥有自己的空间来存储其 Docker 映像. + +您可以在[https://docs.docker.com/registry/introduction/上](https://s0docs0docker0com.icopy.site/registry/introduction/)了解有关 Docker Registry 的更多信息. + +[![Container Registry repositories](img/62073039b38c0dfa370251cfe07ca5e5.png)](img/container_registry_repositories_v13_1.png) + +## Enable the Container Registry for your project[](#enable-the-container-registry-for-your-project "Permalink") + +**警告:**容器注册表遵循项目的可见性设置. 如果项目是公开的,则容器注册表也是如此. + +If you cannot find the **包和注册表>容器注册表** entry under your project’s sidebar, it is not enabled in your GitLab instance. Ask your administrator to enable GitLab Container Registry following the [administration documentation](../../../administration/packages/container_registry.html). + +如果您使用的是 GitLab.com,则默认情况下启用此功能,因此您可以立即开始使用注册表. 当前,作为[存储库大小限制的](../../project/repository/index.html)一部分,GitLab.com 上的 Registry 有一个软的(10GB)大小限制. + +为您的 GitLab 实例启用后,要为您的项目启用 Container Registry: + +1. 转到项目的**"设置">"常规"**页面. +2. 展开" **可见性","项目功能","权限"**部分,并在项目上启用" **容器注册表"**功能. 对于新项目,默认情况下可以启用. 对于现有项目(GitLab 8.8 之前的版本),您必须显式启用它. +3. 按**保存更改**以使更改生效. 现在,您应该能够在侧栏中看到**Packages&Registries> Container Registry**链接. + +## Control Container Registry from within GitLab[](#control-container-registry-from-within-gitlab "Permalink") + +GitLab 提供了一个简单的 Container Registry 管理面板. 该管理面板可用于项目和组. + +### Control Container Registry for your project[](#control-container-registry-for-your-project "Permalink") + +导航到您项目的 **包裹和注册>集装箱注册** . + +[![Container Registry project repositories](img/8a2c3991978374372fe0370f27f4fad4.png)](img/container_registry_repositories_with_quickstart_v13_1.png) + +该视图将: + +* 显示属于该项目的所有图像存储库. +* 允许您按图像存储库的名称过滤. +* 允许您[删除](#delete-images-from-within-gitlab)一个或多个图像存储库. +* 允许您导航到图像存储库详细信息页面. +* 显示具有最常用命令的**快速入门**下拉列表,以登录,构建和推送 +* (可选)如果为该项目启用了[清理策略](#cleanup-policy) ,则将显示横幅. + +### Control Container Registry for your group[](#control-container-registry-for-your-group "Permalink") + +导航到您小组的 **包裹和注册>集装箱注册** . + +[![Container Registry group repositories](img/71c2f22b2aef83c58870637723d6f7ef.png)](img/container_registry_group_repositories_v13_1.png) + +该视图将: + +* Show all the image repositories of the projects that belong to this group. +* 允许[删除](#delete-images-from-within-gitlab)一个或多个图像存储库. +* 允许导航到特定的图像存储库详细信息页面. + +### Image Repository details page[](#image-repository-details-page "Permalink") + +单击任何图像存储库的名称将导航到详细信息. + +[![Container Registry project repository details](img/c3f7298c5f6d1b4dbd0a120ce98b9d06.png)](img/container_registry_repository_details_v13.0.png) + +**注意:**下一页在**组级别容器注册表**和**项目级别容器注册表中**具有相同的功能. + +此视图: + +* 显示所有图像存储库详细信息. +* 显示图像存储库的所有标记. +* 允许您快速复制标签路径(通过单击标签名称附近的剪贴板按钮). +* 允许您[删除一个或多个标签](#delete-images-from-within-gitlab) . + +## Use images from GitLab Container Registry[](#use-images-from-gitlab-container-registry "Permalink") + +要从 GitLab 容器注册表中托管的映像下载并运行容器,请使用`docker run` : + +``` +docker run [options] registry.example.com/group/project/image [arguments] +``` + +有关运行 Docker 容器的更多信息,请访问[Docker 文档](https://s0docs0docker0com.icopy.site/engine/userguide/intro/) . + +## Authenticating to the GitLab Container Registry[](#authenticating-to-the-gitlab-container-registry "Permalink") + +如果访问项目菜单下的**Packages&Registries> Container Registry**链接,则可以看到使用 GitLab 凭据登录到 Container Registry 的明确说明. + +例如,如果注册表的 URL 是`registry.example.com` ,那么您应该能够使用以下命令登录: + +``` +docker login registry.example.com +``` + +**注意:**如果您的帐户中启用了[2 因子身份验证](../../profile/account/two_factor_authentication.html) ,则需要传递[个人访问令牌(](../../profile/personal_access_tokens.html)而不是密码)才能登录到 GitLab 的 Container Registry. + +如果项目是私有项目,则需要提供凭据进行授权. 有两种方法可以做到这一点: + +* 通过使用[个人访问令牌](../../profile/personal_access_tokens.html) . +* 通过使用[部署令牌](../../project/deploy_tokens/index.html) . + +两者所需的最小范围是`read_registry` . + +使用令牌的示例: + +``` +docker login registry.example.com -u -p +``` + +## Build and push images from your local machine[](#build-and-push-images-from-your-local-machine "Permalink") + +建立和发布图像应该是一个简单的过程. 只需确保您将注册表 URL 与 GitLab 上托管的名称空间和项目名称一起使用即可: + +``` +docker build -t registry.example.com/group/project/image . +docker push registry.example.com/group/project/image +``` + +您的图片将按照以下方案命名: + +``` +/// +``` + +GitLab 最多支持三个级别的图像存储库名称. 以下图像标签示例有效: + +``` +registry.example.com/group/project:some-tag +registry.example.com/group/project/image:latest +registry.example.com/group/project/my/image:rc1 +``` + +## Build and push images using GitLab CI/CD[](#build-and-push-images-using-gitlab-cicd "Permalink") + +While you can build and push your images from your local machine, the true power of the Container Registry comes when you combine it with GitLab CI/CD. You can then create workflows and automate any processes that involve testing, building, and eventually deploying your project from the Docker image you created. + +在深入研究细节之前,您应该注意一些事项: + +* 运行任何命令之前,必须[先向容器注册表](#authenticating-to-the-container-registry-with-gitlab-cicd)进行[身份验证](#authenticating-to-the-container-registry-with-gitlab-cicd) . 如果有多个作业依赖于它,则可以在`before_script`执行此操作. +* 使用`docker build --pull`在构建之前获取对基础映像的所有更改,以防缓存过时. 它花费的时间稍长一些,但这意味着如果没有基础映像的安全补丁,您将不会陷入困境. +* 在每次`docker run` docker 之前进行显式`docker pull`都会获取刚刚构建的最新映像. 如果您正在使用多个在本地缓存图像的运行程序,则这一点尤其重要. 在图像标签中使用 Git SHA 使得此操作变得不必要,因为每个作业都是唯一的,并且您永远都不会过时的图像. 但是,如果在依赖项发生更改后重新构建给定的提交,则仍然可能会有陈旧的映像. +* 如果有多个作业同时发生,则您不想直接构建到`latest`标记. + +### Authenticating to the Container Registry with GitLab CI/CD[](#authenticating-to-the-container-registry-with-gitlab-cicd "Permalink") + +通过[GitLab CI / CD](../../../ci/yaml/README.html)向容器注册表进行身份验证的三种方法取决于您项目的可见性. + +适用于所有项目,但更适合公共项目: + +* **使用特殊的`CI_REGISTRY_USER`变量** :为您创建此变量指定的用户,以便推送到连接到您的项目的注册表. 它的密码是使用`CI_REGISTRY_PASSWORD`变量自动设置的. 这使您可以自动构建和部署 Docker 映像,并具有对注册表的读/写访问权限. 这是短暂的,因此仅适用于一项工作. 您可以按原样使用以下示例: + + ``` + docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + ``` + +对于私人和内部项目: + +* **使用个人访问令牌** :如果您的项目是私有的,则可以创建和使用[个人访问令牌](../../profile/personal_access_tokens.html) : + + * 对于读取(拉)访问,范围应为`read_registry` . + * 要进行读/写(拉/推)访问,请使用`api` . + + Replace the `` and `` in the following example: + + ``` + docker login -u -p $CI_REGISTRY + ``` + +* **使用 GitLab 部署令牌** :您可以在私有项目中创建和使用[特殊的部署令牌](../../project/deploy_tokens/index.html#gitlab-deploy-token) . 它提供对注册表的只读(拉)访问. 创建后,您可以使用特殊的环境变量,GitLab CI / CD 将为您填充它们. 您可以按原样使用以下示例: + + ``` + docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY + ``` + +### Container Registry examples with GitLab CI/CD[](#container-registry-examples-with-gitlab-cicd "Permalink") + +如果您在 Runners 上使用 Docker-in-Docker,则`.gitlab-ci.yml`外观应与此类似: + +``` +build: + image: docker:19.03.12 + stage: build + services: + - docker:19.03.12-dind + script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker build -t $CI_REGISTRY/group/project/image:latest . + - docker push $CI_REGISTRY/group/project/image:latest +``` + +您还可以利用[其他变量](../../../ci/variables/README.html)来避免硬编码: + +``` +build: + image: docker:19.03.12 + stage: build + services: + - docker:19.03.12-dind + variables: + IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker build -t $IMAGE_TAG . + - docker push $IMAGE_TAG +``` + +在这里, `$CI_REGISTRY_IMAGE`将解析为与此项目`$CI_REGISTRY_IMAGE`的注册表的地址. 由于`$CI_COMMIT_REF_NAME`解析为分支名称或标记名称,并且您的分支名称可以包含正斜杠(例如,feature / my-feature),因此将`$CI_COMMIT_REF_SLUG`用作图像标记`$CI_COMMIT_REF_SLUG`安全. 这是因为图像标记不能包含正斜杠. 我们还声明了自己的变量`$IMAGE_TAG` ,将两者结合起来可以节省一些在`script`部分键入的内容. + +这是一个更详细的示例,将任务分为 4 个管道阶段,包括两个并行运行的测试. 内部`build`存储在容器注册表中,供后续阶段使用,并在需要时下载映像. 对`master`所做的更改也将被标记为`latest`并使用特定于应用程序的部署脚本进行部署: + +``` +image: docker:19.03.12 +services: + - docker:19.03.12-dind + +stages: + - build + - test + - release + - deploy + +variables: + # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled + DOCKER_HOST: tcp://docker:2376 + DOCKER_TLS_CERTDIR: "/certs" + CONTAINER_TEST_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest + +before_script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + +build: + stage: build + script: + - docker build --pull -t $CONTAINER_TEST_IMAGE . + - docker push $CONTAINER_TEST_IMAGE + +test1: + stage: test + script: + - docker pull $CONTAINER_TEST_IMAGE + - docker run $CONTAINER_TEST_IMAGE /script/to/run/tests + +test2: + stage: test + script: + - docker pull $CONTAINER_TEST_IMAGE + - docker run $CONTAINER_TEST_IMAGE /script/to/run/another/test + +release-image: + stage: release + script: + - docker pull $CONTAINER_TEST_IMAGE + - docker tag $CONTAINER_TEST_IMAGE $CONTAINER_RELEASE_IMAGE + - docker push $CONTAINER_RELEASE_IMAGE + only: + - master + +deploy: + stage: deploy + script: + - ./deploy.sh + only: + - master +``` + +**注意:**此示例显式调用`docker pull` . 如果您希望使用`image:`隐式拉出构建的映像,并使用[Docker](https://docs.gitlab.com/runner/executors/docker.html)或[Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html)执行程序,请确保[`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html)设置为`always` . + +### Using a Docker-in-Docker image from your Container Registry[](#using-a-docker-in-docker-image-from-your-container-registry "Permalink") + +如果要为 Docker-in-Docker 使用自己的 Docker 映像,除了[Docker-in-Docker](../../../ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor)部分中的步骤外,还需要做一些其他事情: + +1. 更新`image`和`service`以指向您的注册表. +2. 添加服务[别名](../../../ci/yaml/README.html#servicesalias) . + +以下是您的`.gitlab-ci.yml`外观示例: + +``` + build: + image: $CI_REGISTRY/group/project/docker:19.03.12 + services: + - name: $CI_REGISTRY/group/project/docker:19.03.12-dind + alias: docker + stage: build + script: + - docker build -t my-docker-image . + - docker run my-docker-image /script/to/run/tests +``` + +如果您忘记设置服务别名,则`docker:19.03.12`映像将找不到`dind`服务,并且将引发类似以下的错误: + +``` +error during connect: Get http://docker:2376/v1.39/info: dial tcp: lookup docker on 192.168.0.1:53: no such host +``` + +## Delete images[](#delete-images "Permalink") + +您可以通过多种方式从 Container Registry 中删除图像. + +**警告:**删除图像是一种破坏性行为,无法撤消. 要还原已删除的图像,必须重建并重新上传它.**注意:**管理员应查看如何[垃圾收集](../../../administration/packages/container_registry.html#container-registry-garbage-collection)删除的图像. + +### Delete images from within GitLab[](#delete-images-from-within-gitlab "Permalink") + +要从 GitLab 中删除图像: + +1. Navigate to your project’s or group’s **包和注册表>容器注册表**. +2. 在" **容器注册表"**页面上,可以通过以下任一方法选择要删除的内容: + + * 通过单击红色删除整个存储库及其包含的所有标签 **垃圾桶**图标. + * 导航到存储库,然后通过单击红色单独或批量删除标签 您要删除的标签旁边的**垃圾桶**图标. +3. 在对话框中,点击**删除标签** . + + [![Container Registry tags](img/c3f7298c5f6d1b4dbd0a120ce98b9d06.png)](img/container_registry_repository_details_v13.0.png) + +### Delete images using the API[](#delete-images-using-the-api "Permalink") + +如果要自动执行删除图像的过程,GitLab 提供了一个 API. 有关更多信息,请参见以下端点: + +* [Delete a Registry repository](../../../api/container_registry.html#delete-registry-repository) +* [Delete an individual Registry repository tag](../../../api/container_registry.html#delete-a-registry-repository-tag) +* [Delete Registry repository tags in bulk](../../../api/container_registry.html#delete-registry-repository-tags-in-bulk) + +### Delete images using GitLab CI/CD[](#delete-images-using-gitlab-cicd "Permalink") + +**警告:** GitLab CI / CD 没有提供删除图像的内置方法,但是本示例使用了名为[reg](https://github.com/genuinetools/reg)的第三方工具,该工具与 GitLab Registry API 进行通信. 您应对自己的行为负责. 有关此工具的帮助,请参见[reg 的发行队列](https://github.com/genuinetools/reg/issues) . + +以下示例定义了两个阶段: `build`和`clean` . `build_image`作业将为分支构建 Docker 映像,而`delete_image`作业将其删除. `reg`可执行文件已下载并用于删除与`$CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG` [环境变量](../../../ci/variables/predefined_variables.html)匹配的映像. + +要使用此示例,请更改`IMAGE_TAG`变量以符合您的需求: + +``` +stages: + - build + - clean + +build_image: + image: docker:19.03.12 + stage: build + services: + - docker:19.03.12-dind + variables: + IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker build -t $IMAGE_TAG . + - docker push $IMAGE_TAG + only: + - branches + except: + - master + +delete_image: + image: docker:19.03.12 + stage: clean + services: + - docker:19.03.12-dind + variables: + IMAGE_TAG: $CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG + REG_SHA256: ade837fc5224acd8c34732bf54a94f579b47851cc6a7fd5899a98386b782e228 + REG_VERSION: 0.16.1 + before_script: + - apk add --no-cache curl + - curl --fail --show-error --location "https://github.com/genuinetools/reg/releases/download/v$REG_VERSION/reg-linux-amd64" --output /usr/local/bin/reg + - echo "$REG_SHA256 /usr/local/bin/reg" | sha256sum -c - + - chmod a+x /usr/local/bin/reg + script: + - /usr/local/bin/reg rm -d --auth-url $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $IMAGE_TAG + only: + - branches + except: + - master +``` + +**提示:**您可以从[发布页面](https://github.com/genuinetools/reg/releases)下载最新的`reg`版本,然后通过更改`delete_image`作业中定义的`REG_SHA256`和`REG_VERSION`变量来更新代码示例. + +### Delete images by using a cleanup policy[](#delete-images-by-using-a-cleanup-policy "Permalink") + +您可以创建每个项目的[清理策略,](#cleanup-policy)以确保定期从 Container Registry 中删除较旧的标记和图像. + +## Cleanup policy[](#cleanup-policy "Permalink") + +版本历史 + +* 在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/15398) . +* 在 GitLab 13.2 中从"过期策略" [重命名](https://gitlab.com/gitlab-org/gitlab/-/issues/218737)为"清理策略". + +对于特定项目,如果要删除不再需要的标签,则可以创建清除策略. 应用该策略时,将删除与正则表达式模式匹配的标记. 底层和图像仍然保留. + +要删除不再与任何标签关联的基础层和图像,实例管理员可以通过`-m`开关使用[垃圾回收](../../../administration/packages/container_registry.html#removing-unused-layers-not-referenced-by-manifests) . + +**注意:**对于 GitLab.com,清理策略不适用于将该功能部署到生产之前(2020 年 2 月)创建的项目. 计划在 GitLab.com 上[为](https://gitlab.com/gitlab-org/gitlab/-/issues/196124)现有项目提供支持. 对于自我管理的实例,管理员可以在[GitLab 应用程序设置中](../../../api/settings.html#change-application-settings)通过将`container_expiration_policies_enable_historic_entries`设置为 true 来启用清除策略. 注意[涉及](./index.html#use-with-external-container-registries)的固有[风险](./index.html#use-with-external-container-registries) . + +清理策略算法首先从列表中收集给定存储库的所有标记,然后进行从标记中排除标记的过程,直到仅保留要删除的标记为止: + +1. 在列表中收集给定存储库的所有标记. +2. 排除名为标签`latest`从列表中. +3. 评估`name_regex` ,从列表中排除不匹配的名称. +4. 排除所有没有清单的标签(不是选项的一部分). +5. 按`created_date`其余标签. +6. 从列表中排除基于`keep_n`值的 N 个标签(要保留的标签数). +7. 从列表中排除比`older_than`值(清除间隔)更新的标签. +8. 从列表中排除与`name_regex_keep`值匹配的所有标签(要保留的图像). +9. 最后,列表中的其余标签将从 Container Registry 中删除. + +### Managing project cleanup policy through the UI[](#managing-project-cleanup-policy-through-the-ui "Permalink") + +要管理项目清理策略,请导航至 **设置> CI / CD>容器注册表标记清除策略** . + +用户界面允许您配置以下内容: + +* **清理策略:**启用或禁用清理策略. +* **清除间隔:**标签可以删除多长时间. +* **清理计划:**检查标签的 cron 作业应运行的频率. +* **要保留的标签数量:**每个图像*始终*保留多少个标签. +* **名称与该正则表达式模式匹配的 Docker 标签将过期:**用于确定应清除哪些标签的正则表达式. 要使所有标签都合格,请使用默认值`.*` . +* **名称与该正则表达式模式匹配的 Docker 标签将被保留:**用于确定应保留哪些标签的正则表达式. 要保留所有标签,请使用默认值`.*` . + +#### Troubleshooting cleanup policies[](#troubleshooting-cleanup-policies "Permalink") + +如果看到以下消息: + +"更新清理策略时出了点问题." + +检查正则表达式模式以确保它们有效. + +您可以使用[Rubular](https://rubular.com/)检查您的正则表达式. 查看一些常见的[regex 模式示例](#regex-pattern-examples) . + +### Managing project cleanup policy through the API[](#managing-project-cleanup-policy-through-the-api "Permalink") + +您可以使用 GitLab API 设置,更新和禁用清理策略. + +Examples: + +* 选择所有标签,每个图像至少保留 1 个标签,清理超过 14 天的所有标签,每月运行一次,使用名称`master`保留所有图像并启用该策略: + + ``` + curl --request PUT --header 'Content-Type: application/json;charset=UTF-8' --header "PRIVATE-TOKEN: " --data-binary '{"container_expiration_policy_attributes":{"cadence":"1month","enabled":true,"keep_n":1,"older_than":"14d","name_regex":"","name_regex_delete":".*","name_regex_keep":".*-master"}}' 'https://gitlab.example.com/api/v4/projects/2' + ``` + +有关更多详细信息,请参见 API 文档: [编辑项目](../../../api/projects.html#edit-project) . + +### Use with external container registries[](#use-with-external-container-registries "Permalink") + +使用[外部容器注册表时](./../../../administration/packages/container_registry.html#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint) ,在项目上运行清除策略可能会带来性能风险. 如果项目要运行的策略将删除大量标签(成千上万个),则运行该策略的 GitLab 后台作业可能会备份或完全失败. 如果您确信要清除的标签数量很少,建议仅对在 GitLab 12.8 之前创建的项目启用容器清理策略. + +### Regex pattern examples[](#regex-pattern-examples "Permalink") + +清理策略使用正则表达式模式来确定应在 UI 和 API 中保留或删除哪些标签. + +以下是您可能要使用的正则表达式模式的示例: + +* 匹配所有标签: + + ``` + .* + ``` + +* 匹配以`v`开头的标签: + + ``` + v.+ + ``` + +* 匹配包含`master`标签: + + ``` + master + ``` + +* 匹配以`v`开头,包含`master`或包含`release`标签: + + ``` + (?:v.+|master|release) + ``` + +## Use the Container Registry to store Helm Charts[](#use-the-container-registry-to-store-helm-charts "Permalink") + +随着[Helm v3](https://helm.sh/docs/topics/registries/)的发布,您可以使用 Container Registry 存储 Helm Charts. 但是,由于 Docker 传递和存储元数据的方式,GitLab 无法解析此数据并达到性能标准. [本史诗](https://gitlab.com/groups/gitlab-org/-/epics/2313)更新了 Container Registry 的体系结构以支持 Helm Charts. + +您可以[在此处](https://gitlab.com/gitlab-org/gitlab/-/issues/38047#note_298842890)阅读有关上述挑战的更多信息. + +## Limitations[](#limitations "Permalink") + +* 推送图像后,不支持移动或重命名现有 Container Registry 存储库,因为图像已签名,并且签名包含存储库名称. 要使用 Container Registry 移动或重命名存储库,必须删除所有现有映像. +* 在 GitLab 12.10 之前,清理策略不会删除使用与`latest`标签相同的图像 ID 的任何标签. + +## Troubleshooting the GitLab Container Registry[](#troubleshooting-the-gitlab-container-registry "Permalink") + +### Docker connection error[](#docker-connection-error "Permalink") + +当组,项目或分支名​​称中包含特殊字符时,可能会发生 Docker 连接错误. 特殊字符可以包括: + +* 领先的下划线 +* 尾随连字符/破折号 + +为了解决这个问题,您可以[更改组路径](../../group/index.html#changing-a-groups-path) , [更改项目路径](../../project/settings/index.html#renaming-a-repository)或更改分支名称. + +### Troubleshoot as a GitLab server admin[](#troubleshoot-as-a-gitlab-server-admin "Permalink") + +大多数情况下,对 GitLab 容器注册表进行故障排除需要管理员对 GitLab 服务器的访问. + +[Read how to troubleshoot the Container Registry](../../../administration/packages/container_registry.html#troubleshooting). + +### Unable to change path or transfer a project[](#unable-to-change-path-or-transfer-a-project "Permalink") + +如果您尝试更改项目的路径或将项目转移到新的名称空间,则可能会收到以下错误之一: + +* "由于容器的注册表中存在标签,因此无法传输项目." +* "无法移动名称空间,因为至少一个项目在容器注册表中具有标签." + +当项目在容器注册表中有图像时,会发生此问题. 必须先删除或移动这些图像,然后才能更改路径或传输项目. + +以下过程使用这些样本项目名称: + +* 对于当前项目: `example.gitlab.com/org/build/sample_project/cr:v2.9.1` : `example.gitlab.com/org/build/sample_project/cr:v2.9.1` +* 对于新项目: `example.gitlab.com/new_org/build/new_sample_project/cr:v2.9.1` : `example.gitlab.com/new_org/build/new_sample_project/cr:v2.9.1` + +使用您自己的 URL 完成以下步骤: + +1. 将 Docker 映像下载到您的计算机上: + + ``` + docker login example.gitlab.com + docker pull example.gitlab.com/org/build/sample_project/cr:v2.9.1 + ``` + +2. 重命名图像以匹配新的项目名称: + + ``` + docker tag example.gitlab.com/org/build/sample_project/cr:v2.9.1 example.gitlab.com/new_org/build/new_sample_project/cr:v2.9.1 + ``` + +3. 使用[UI](#delete-images)或[API](../../../api/packages.html#delete-a-project-package)删除两个项目中的图像. 图像排队和删除时可能会有延迟. +4. 通过转到**"设置">"常规"**并展开" **高级"**来更改路径或传输项目. +5. 恢复图像: + + ``` + docker push example.gitlab.com/new_org/build/new_sample_project/cr:v2.9.1 + ``` + +有关详细信息,请关注[此问题](https://gitlab.com/gitlab-org/gitlab/-/issues/18383) . \ No newline at end of file diff --git a/docs/277.md b/docs/277.md new file mode 100644 index 0000000000000000000000000000000000000000..b5ae883df925814fcad23d3b1a9b450dd9f200f9 --- /dev/null +++ b/docs/277.md @@ -0,0 +1,71 @@ +# Dependency Proxy + +> 原文:[https://docs.gitlab.com/ee/user/packages/dependency_proxy/](https://docs.gitlab.com/ee/user/packages/dependency_proxy/) + +* [Supported dependency proxies](#supported-dependency-proxies) +* [Using the Docker dependency proxy](#using-the-docker-dependency-proxy) +* [Clearing the cache](#clearing-the-cache) +* [Limitations](#limitations) + +# Dependency Proxy[](#dependency-proxy-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7934) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.11. + +**注意:**这是用户指南. 为了使用依赖代理,管理员必须首先对其进行[配置](../../../administration/packages/dependency_proxy.html) . + +对于许多组织而言,希望为经常使用的上游映像/程序包提供本地代理. 在 CI / CD 的情况下,代理负责接收请求并从注册表中返回上游映像,并充当下拉缓存. + +依赖项代理在组级别可用. 要访问它,请导航到组的**Packages&Registries> Dependency Proxy** . + +[![Dependency Proxy group page](img/64d10619e1633359be63480f18d60b90.png)](img/group_dependency_proxy.png) + +## Supported dependency proxies[](#supported-dependency-proxies "Permalink") + +***注意:**有关代理即将添加的列表,请访问[指导页面](https://about.gitlab.com/direction/package/dependency_proxy/#top-vision-items) .* + +支持以下依赖代理. + +| 依赖代理 | GitLab 版本 | +| --- | --- | +| Docker | 11.11+ | + +## Using the Docker dependency proxy[](#using-the-docker-dependency-proxy "Permalink") + +借助 Docker 依赖项代理,您可以将 GitLab 用作 Docker 映像的源. 要将 Docker 映像放入依赖代理中: + +1. 在" **软件包和** `gitlab.com/groupname/dependency_proxy/containers` **>"依赖代理"**下的组页面上找到代理 URL,例如`gitlab.com/groupname/dependency_proxy/containers` . +2. 触发 GitLab 提取所需的 Docker 映像(例如`alpine:latest`或`linuxserver/nextcloud:latest` ),然后使用以下方法之一将其存储在代理存储中: + + * 手动拉 Docker 镜像: + + ``` + docker pull gitlab.com/groupname/dependency_proxy/containers/alpine:latest + ``` + + * 从`Dockerfile` : + + ``` + FROM gitlab.com/groupname/dependency_proxy/containers/alpine:latest + ``` + + * In [`.gitlab-ci.yml`](../../../ci/yaml/README.html#image): + + ``` + image: gitlab.com/groupname/dependency_proxy/containers/alpine:latest + ``` + +然后,GitLab 将从 Docker Hub 中提取 Docker 映像,并将 blob 缓存在 GitLab 服务器上. 下次您提取同一映像时,它将从 Docker Hub 获取有关该映像的最新信息,但将为 GitLab 提供的现有 Blob 服务. + +斑点被永久保存,并且可以存储多少数据没有硬性限制. + +## Clearing the cache[](#clearing-the-cache "Permalink") + +可以使用 GitLab API 清除给定组的依赖项代理缓存,以获取可能不再需要的图像 Blob 占用的磁盘空间. 有关更多详细信息,请参见[依赖项代理 API 文档](../../../api/dependency_proxy.html) . + +## Limitations[](#limitations "Permalink") + +适用以下限制: + +* 仅支持公共组(尚不支持身份验证). +* 仅支持 Docker Hub. +* 此功能需要 Docker Hub 可用. \ No newline at end of file diff --git a/docs/278.md b/docs/278.md new file mode 100644 index 0000000000000000000000000000000000000000..1502d9f5f4dc663c0e470800c582595f5a497c0d --- /dev/null +++ b/docs/278.md @@ -0,0 +1,126 @@ +# GitLab Composer Repository + +> 原文:[https://docs.gitlab.com/ee/user/packages/composer_repository/](https://docs.gitlab.com/ee/user/packages/composer_repository/) + +* [Enabling the Composer Repository](#enabling-the-composer-repository) +* [Getting started](#getting-started) + * [Creating a package project](#creating-a-package-project) + * [Publishing the package](#publishing-the-package) + * [Installing a package](#installing-a-package) + +# GitLab Composer Repository[](#gitlab-composer-repository-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15886) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + +使用 GitLab Composer 信息库,每个项目都可以有自己的空间来存储[Composer](https://s0getcomposer0org.icopy.site/)软件包. + +## Enabling the Composer Repository[](#enabling-the-composer-repository "Permalink") + +**注意:**仅当您的 GitLab 管理员[启用了对 Package Registry 的支持时,](../../../administration/packages/index.html)此选项才可用. + +启用 Composer 信息库后,默认情况下它将可用于所有新项目. 要为现有项目启用它,或者要禁用它: + +1. 导航到项目的**"设置">"常规">"可见性,项目功能,权限"** . +2. 找到"软件包"功能并启用或禁用它. +3. 单击**保存更改**以使更改生效. + +然后,您应该能够在左侧栏中看到" **程序包和注册表"**部分. + +## Getting started[](#getting-started "Permalink") + +本节将介绍如何创建一个新的示例 Composer 软件包进行发布. 这是测试**GitLab Composer 注册表**的快速入门. + +您将需要最新版本的[Composer](https://s0getcomposer0org.icopy.site/) . + +### Creating a package project[](#creating-a-package-project "Permalink") + +了解如何创建完整的 Composer 项目不在本指南的范围内,但是您可以创建一个小程序包来测试注册表. 首先创建一个名为`my-composer-package`的新目录: + +``` +mkdir my-composer-package && cd my-composer-package +``` + +在此目录中创建一个新的`composer.json`文件以设置基本项目: + +``` +touch composer.json +``` + +在`composer.json`内部,添加以下代码: + +``` +{ "name": "/composer-test", "type": "library", "license": "GPL-3.0-only", "version": "1.0.0" } +``` + +将``替换为唯一的命名空间,例如您的 GitLab 用户名或组名. + +在创建了基本的包结构之后,我们需要在 Git 中对其进行标记并将其推送到存储库中. + +``` +git init +git add composer.json +git commit -m 'Composer package test' +git tag v1.0.0 +git add origin git@gitlab.com:/.git +git push origin v1.0.0 +``` + +### Publishing the package[](#publishing-the-package "Permalink") + +现在,我们的项目基础已经完成,我们可以发布该软件包了. 为此,您将需要以下内容: + +* 个人访问令牌. 您可以生成范围设置为`api`的[个人访问令牌](../../../user/profile/personal_access_tokens.html) ,以进行存储库身份验证. +* 您的项目 ID,可以在项目的主页上找到. + +要发布托管在 GitLab 上的软件包,我们需要使用`curl`这样的工具对 GitLab 软件包 API 进行`POST` : + +``` +curl --data tag= 'https://__token__:@gitlab.com/api/v4/projects//packages/composer' +``` + +Where: + +* ``是您的个人访问令牌. +* ``是您的项目 ID. +* ``是您要发布的版本的 Git 标记名称. 在此示例中,它应为`v1.0.0` . 请注意,除了使用`tag=`您还可以使用`branch=`来发布分支. + +如果上面的命令成功执行,您现在应该可以在项目页面的" **程序包和注册表"**部分下看到该程序包. + +### Installing a package[](#installing-a-package "Permalink") + +要安装您的软件包,您需要: + +* 个人访问令牌. 您可以生成范围设置为`api`的[个人访问令牌](../../../user/profile/personal_access_tokens.html) ,以进行存储库身份验证. +* 您的组 ID,可在项目组的主页上找到. + +将 GitLab Composer 软件包存储库以及要安装的软件包名称和版本添加到现有项目的`composer.json`文件中,如下所示: + +``` +{ ... "repositories": [ { "type": "composer", "url": "https://gitlab.com/api/v4/group//-/packages/composer/packages.json" } ], "require": { ... "": "" }, ... } +``` + +Where: + +* ``是在项目的"组"页面下找到的组 ID. +* ``是软件包的`composer.json`文件中定义的软件包名称. +* ``是您的软件包版本(在此示例中为`1.0.0` ). + +您还需要使用 GitLab 凭据创建一个`auth.json`文件: + +``` +{ "http-basic": { "gitlab.com": { "username": "___token___", "password": "" } } } +``` + +Where: + +* ``是您的个人访问令牌. + +配置了`composer.json`和`auth.json`文件后,您可以通过运行`composer`安装软件包: + +``` +composer update +``` + +如果成功,您应该能够看到指示软件包已成功安装的输出. + +**重要提示:**请确保不要将`auth.json`文件提交到您的存储库. 要从 CI 作业安装软件包,请考虑将[`composer config`](https://s0getcomposer0org.icopy.site/doc/articles/handling-private-packages-with-satis.md)工具与您的个人访问令牌一起使用,并将其存储在[GitLab CI / CD 环境变量](../../../ci/variables/README.html)或[Hashicorp Vault 中](../../../ci/examples/authenticating-with-hashicorp-vault/index.html) . \ No newline at end of file diff --git a/docs/279.md b/docs/279.md new file mode 100644 index 0000000000000000000000000000000000000000..d776d6b24c05554ec8746a8d7c78090e8c29b8dc --- /dev/null +++ b/docs/279.md @@ -0,0 +1,290 @@ +# GitLab Conan Repository + +> 原文:[https://docs.gitlab.com/ee/user/packages/conan_repository/](https://docs.gitlab.com/ee/user/packages/conan_repository/) + +* [Enabling the Conan Repository](#enabling-the-conan-repository) +* [Getting started](#getting-started) + * [Installing Conan](#installing-conan) + * [Installing CMake](#installing-cmake) + * [Creating a project](#creating-a-project) + * [Building a package](#building-a-package) +* [Adding the GitLab Package Registry as a Conan remote](#adding-the-gitlab-package-registry-as-a-conan-remote) +* [Authenticating to the GitLab Conan Repository](#authenticating-to-the-gitlab-conan-repository) + * [Adding a Conan user to the GitLab remote](#adding-a-conan-user-to-the-gitlab-remote) + * [Setting a default remote to your project (optional)](#setting-a-default-remote-to-your-project-optional) +* [Uploading a package](#uploading-a-package) + * [Package recipe naming convention](#package-recipe-naming-convention) +* [Installing a package](#installing-a-package) +* [Removing a package](#removing-a-package) +* [Searching the GitLab Package Registry for Conan packages](#searching-the-gitlab-package-registry-for-conan-packages) +* [Fetching Conan package information from the GitLab Package Registry](#fetching-conan-package-information-from-the-gitlab-package-registry) +* [List of supported CLI commands](#list-of-supported-cli-commands) +* [Using GitLab CI with Conan packages](#using-gitlab-ci-with-conan-packages) + +# GitLab Conan Repository[](#gitlab-conan-repository-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8248) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.6. + +有了 GitLab 柯南存储库,每个项目都可以有自己的空间来存储柯南软件包. + +[![GitLab Conan Repository](img/5bf127e31dfc7f61e3134780f75114ff.png)](img/conan_package_view.png) + +## Enabling the Conan Repository[](#enabling-the-conan-repository "Permalink") + +**注意:**仅当您的 GitLab 管理员[启用了对 Conan Repository 的支持时,](../../../administration/packages/index.html)此选项才可用. + +启用柯南存储库后,默认情况下它将可用于所有新项目. 要为现有项目启用它,或者要禁用它: + +1. 导航到项目的**"设置">"常规">"可见性,项目功能,权限"** . +2. 找到"软件包"功能并启用或禁用它. +3. 单击**保存更改**以使更改生效. + +然后,您应该能够在左侧栏中看到" **程序包和注册表"**部分. + +## Getting started[](#getting-started "Permalink") + +本节将介绍如何安装 Conan 以及为 C / C ++项目构建软件包. 如果您不熟悉柯南,这是一个快速入门. 如果您已经在使用 Conan 并且了解如何构建自己的软件包,请继续[下一节](#adding-the-gitlab-package-registry-as-a-conan-remote) . + +### Installing Conan[](#installing-conan "Permalink") + +按照[conan.io](https://conan.io/downloads.html)上的说明将 Conan 软件包管理器下载到本地开发环境. + +安装完成后,通过运行以下命令验证您可以在终端中使用 Conan + +``` +conan --version +``` + +您应该在输出中看到柯南版本: + +``` +Conan version 1.20.5 +``` + +### Installing CMake[](#installing-cmake "Permalink") + +使用 C ++和 Conan 进行开发时,编译器有多种选择. 本教程将逐步介绍如何使用 cmake 编译器. 在您的终端中,运行命令 + +``` +cmake --version +``` + +您应该会在输出中看到 cmake 版本. 如果看到其他内容,则可能必须安装 cmake. + +在 Mac 上,您可以通过运行`brew install cmake`来使用[自制软件](https://brew.sh/) `brew install cmake` . 否则,请按照[cmake.org 中](https://cmake.org/install/)针对您的操作系统的说明进行操作. + +### Creating a project[](#creating-a-project "Permalink") + +了解创建有效且可编译的 C ++项目所需的内容不在本指南的范围之内,但是,如果您是 C ++的新手,并且想尝试 GitLab 软件包注册表,那么 Conan.io 会提供一个很棒的[Hello World 入门项目](https://github.com/conan-io/hello)可以克隆以开始使用. + +如果您没有自己的 C ++项目,请克隆该存储库,并将其用于本教程的其余部分. + +### Building a package[](#building-a-package "Permalink") + +在终端中,导航到项目的根文件夹. 通过运行`conan new`并为其提供程序包名称和版本来生成新配方: + +``` +conan new Hello/0.1 -t +``` + +接下来,您将通过运行提供 Conan 用户和频道的`conan create`来为该配方创建一个程序包: + +``` +conan create . my-org+my-group+my-project/beta +``` + +**注意:**当前的[命名限制](#package-recipe-naming-convention)要求您将`user`值[命名](#package-recipe-naming-convention)为项目在 GitLab 上的`+`分隔路径. + +上面的示例将创建一个属于该项目的软件包: `https://gitlab.com/my-org/my-group/my-project` : `https://gitlab.com/my-org/my-group/my-project` ,其通道为`beta` . + +这两个示例命令将使用配方`Hello/0.1@my-org+my-group+my-project/beta`生成最终软件包. + +有关创建和管理软件包的更多高级详细信息,请参阅[Conan docs](https://docs.conan.io/en/latest/creating_packages.html) . + +现在,您可以将软件包上传到 GitLab 注册表了. 首先,您需要将 GitLab 设置为远程,然后需要为该远程添加一个 Conan 用户以验证您的请求. + +## Adding the GitLab Package Registry as a Conan remote[](#adding-the-gitlab-package-registry-as-a-conan-remote "Permalink") + +Add a new remote to your Conan configuration: + +``` +conan remote add gitlab https://gitlab.example.com/api/v4/packages/conan +``` + +一旦设置了遥控器,您就可以在运行 Conan 命令时使用遥控器,方法是在命令末尾添加`--remote=gitlab` . + +例如: + +``` +conan search Hello* --all --remote=gitlab +``` + +## Authenticating to the GitLab Conan Repository[](#authenticating-to-the-gitlab-conan-repository "Permalink") + +您将需要一个个人访问令牌或部署令牌. + +对于存储库身份验证: + +* 您可以将范围设置为`api`来生成[个人访问令牌](../../../user/profile/personal_access_tokens.html) . +* 您可以生成[令牌部署](./../../project/deploy_tokens/index.html)与范围设置为`read_package_registry` , `write_package_registry` ,或两者兼而有之. + +### Adding a Conan user to the GitLab remote[](#adding-a-conan-user-to-the-gitlab-remote "Permalink") + +一旦有了个人访问令牌并[设置了 Conan remote](#adding-the-gitlab-package-registry-as-a-conan-remote) ,就可以将令牌与远程关联,因此您不必将它们显式添加到您运行的每个 Conan 命令中: + +``` +conan user -r gitlab -p +``` + +**注意:**如果您使用`gitlab`以外的名称来命名远程,则应在此命令中使用您的远程名称,而不是`gitlab` . + +从现在开始,当您使用`--remote=gitlab`运行命令时,您的用户名和密码将自动包含在请求中. + +**注意:**个人访问令牌不会随时存储在本地. Conan 使用 JWT,因此当您运行此命令时,Conan 将使用您的令牌从 GitLab 请求一个过期的令牌. JWT 确实会定期失效,因此您需要在这种情况下重新输入个人访问令牌. + +或者,您可以在任何给定命令中显式包括您的凭据. 例如: + +``` +CONAN_LOGIN_USERNAME= CONAN_PASSWORD= conan upload Hello/0.1@my-group+my-project/beta --all --remote=gitlab +``` + +### Setting a default remote to your project (optional)[](#setting-a-default-remote-to-your-project-optional "Permalink") + +如果您希望柯南始终使用 GitLab 作为软件包的注册表,则可以告诉柯南始终为给定的软件包配方引用 GitLab 远程: + +``` +conan remote add_ref Hello/0.1@my-group+my-project/beta gitlab +``` + +**注意:**软件包配方中确实包含该版本,因此为`Hello/0.1@user/channel`设置默认远程将不适用于`Hello/0.2@user/channel` . 此功能最适合需要从 GitLab 注册表使用或安装软件包而无需指定远程服务器的情况. + +本文档中其余的示例命令假定您已将具有凭据的 Conan 用户添加到`gitlab`远程,并且不包括显式凭据或远程选项,但是请注意,可以在不添加任何命令的情况下运行任何命令.用户或默认遥控器: + +``` +`CONAN_LOGIN_USERNAME= CONAN_PASSWORD= --remote=gitlab +``` + +## Uploading a package[](#uploading-a-package "Permalink") + +首先,您需要在[本地创建 Conan 软件包](https://docs.conan.io/en/latest/creating_packages/getting_started.html) . 为了使用 GitLab 软件包注册表,必须遵循特定的[命名约定](#package-recipe-naming-convention) . + +通过选择`api` [范围,](../../../user/profile/personal_access_tokens.html#limiting-scopes-of-a-personal-access-token)确保在 GitLab 上创建了一个项目,并且所使用的个人访问令牌具有对容器注册表进行写访问的正确权限. + +您可以使用`conan upload`命令将软件包上传到 GitLab 软件包注册表: + +``` +conan upload Hello/0.1@my-group+my-project/beta --all +``` + +### Package recipe naming convention[](#package-recipe-naming-convention "Permalink") + +标准柯南食谱约定看起来像`package_name/version@user/channel` . + +**配方用户必须是`+`分隔的项目路径** . 程序包名称可以是任何名称,但最好使用项目名称,除非由于命名冲突而无法使用. 例如: + +| Project | Package | Supported | +| --- | --- | --- | +| `foo/bar` | `my-package/1.0.0@foo+bar/stable` | Yes | +| `foo/bar-baz/buz` | `my-package/1.0.0@foo+bar-baz+buz/stable` | Yes | +| `gitlab-org/gitlab-ce` | `my-package/1.0.0@gitlab-org+gitlab-ce/stable` | Yes | +| `gitlab-org/gitlab-ce` | `my-package/1.0.0@foo/stable` | No | + +**注意:**将来的迭代将扩展对[项目和组级别](https://gitlab.com/gitlab-org/gitlab/-/issues/11679)远程服务器的支持,这将允许更灵活的命名约定. + +## Installing a package[](#installing-a-package "Permalink") + +通常使用`conanfile.txt`文件将 Conan 软件包作为依赖项安装. + +在要作为依赖项安装 Conan 软件包的项目中,打开`conanfile.txt`或在项目的根目录中创建一个名为`conanfile.txt`的空文件. + +将柯南食谱添加到文件的`[requires]`部分: + +``` + [requires] + Hello/0.1@my-group+my-project/beta + + [generators] + cmake +``` + +接下来,从您的项目的根目录创建一个构建目录并导航到它: + +``` +mkdir build && cd build +``` + +现在,您可以安装`conanfile.txt`列出的依赖`conanfile.txt` : + +``` +conan install .. +``` + +**注意:**如果您要安装在本教程中刚刚创建的软件包,则不会发生太多事情,因为该软件包已在本地计算机上存在. + +## Removing a package[](#removing-a-package "Permalink") + +有两种方法可以从 GitLab 软件包注册表中删除 Conan 软件包. + +* **在命令行中使用 Conan 客户端:** + + ``` + conan remove Hello/0.2@user/channel --remote=gitlab + ``` + + 您需要在此命令中明确包含遥控器,否则该程序包将仅从本地系统缓存中删除. + + **注意:**此命令将从软件包注册表中删除所有配方和二进制软件包文件. +* **GitLab 项目界面** :在项目页面的软件包视图中,您可以通过单击红色垃圾图标来删除软件包. + +## Searching the GitLab Package Registry for Conan packages[](#searching-the-gitlab-package-registry-for-conan-packages "Permalink") + +`conan search`命令可以按完整或部分软件包名称或精确配方进行搜索. + +要使用部分名称进行搜索,请使用通配符`*` ,该通配符应放在搜索的末尾(例如, `my-packa*` ): + +``` +conan search Hello --all --remote=gitlab +conan search He* --all --remote=gitlab +conan search Hello/0.1@my-group+my-project/beta --all --remote=gitlab +``` + +搜索范围将包括您有权访问的所有项目,包括私人项目以及所有公共项目. + +## Fetching Conan package information from the GitLab Package Registry[](#fetching-conan-package-information-from-the-gitlab-package-registry "Permalink") + +`conan info`命令将返回有关给定软件包的信息: + +``` +conan info Hello/0.1@my-group+my-project/beta +``` + +## List of supported CLI commands[](#list-of-supported-cli-commands "Permalink") + +GitLab Conan 存储库支持以下 Conan CLI 命令: + +* `conan upload` :将您的配方和包文件上载到 GitLab 包注册表. +* `conan install` :从 GitLab 软件包注册表中安装`conanfile.txt`软件包,包括使用`conanfile.txt`文件. +* `conan search`: Search the GitLab Package Registry for public packages, and private packages you have permission to view. +* `conan info` :从 GitLab 软件包注册表中查看有关给定软件包的信息. +* `conan remove` :从 GitLab 软件包注册表中删除该软件包. + +## Using GitLab CI with Conan packages[](#using-gitlab-ci-with-conan-packages "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11678) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7. + +要在[GitLab CI / CD 中](./../../../ci/README.html)使用柯南命令,可以在命令中使用`CI_JOB_TOKEN`代替个人访问令牌. + +在`.gitlab-ci.yml`文件中为每个柯南命令提供`CONAN_LOGIN_USERNAME`和`CONAN_PASSWORD`是最简单的: + +``` +image: conanio/gcc7 + +create_package: + stage: deploy + script: + - conan remote add gitlab https://gitlab.example.com/api/v4/packages/conan + - conan create . my-group+my-project/beta + - CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload Hello/0.1@root+ci-conan/beta1 --all --remote=gitlab +``` + +您可以在[Conan 文档中](https://docs.conan.io/en/latest/howtos/run_conan_in_docker.html#available-docker-images)找到其他柯南图像用作 CI 文件的基础. \ No newline at end of file diff --git a/docs/280.md b/docs/280.md new file mode 100644 index 0000000000000000000000000000000000000000..2fbb9a627598724b6e505ea3ceb2888d3c427908 --- /dev/null +++ b/docs/280.md @@ -0,0 +1,784 @@ +# GitLab Maven Repository + +> 原文:[https://docs.gitlab.com/ee/user/packages/maven_repository/](https://docs.gitlab.com/ee/user/packages/maven_repository/) + +* [Enabling the Maven Repository](#enabling-the-maven-repository) +* [Getting Started with Maven](#getting-started-with-maven) + * [Installing Maven](#installing-maven) + * [Creating a project](#creating-a-project) +* [Getting started with Gradle](#getting-started-with-gradle) + * [Installing Gradle](#installing-gradle) + * [Creating a project in Gradle](#creating-a-project-in-gradle) +* [Adding the GitLab Package Registry as a Maven remote](#adding-the-gitlab-package-registry-as-a-maven-remote) + * [Authenticating with a personal access token](#authenticating-with-a-personal-access-token) + * [Authenticating with a personal access token in Maven](#authenticating-with-a-personal-access-token-in-maven) + * [Authenticating with a personal access token in Gradle](#authenticating-with-a-personal-access-token-in-gradle) + * [Authenticating with a CI job token](#authenticating-with-a-ci-job-token) + * [Authenticating with a CI job token in Maven](#authenticating-with-a-ci-job-token-in-maven) + * [Authenticating with a CI job token in Gradle](#authenticating-with-a-ci-job-token-in-gradle) + * [Authenticating with a deploy token](#authenticating-with-a-deploy-token) + * [Authenticating with a deploy token in Maven](#authenticating-with-a-deploy-token-in-maven) + * [Authenticating with a deploy token in Gradle](#authenticating-with-a-deploy-token-in-gradle) +* [Configuring your project to use the GitLab Maven repository URL](#configuring-your-project-to-use-the-gitlab-maven-repository-url) + * [Project level Maven endpoint](#project-level-maven-endpoint) + * [Group level Maven endpoint](#group-level-maven-endpoint) + * [Instance level Maven endpoint](#instance-level-maven-endpoint) +* [Uploading packages](#uploading-packages) + * [Upload using Maven](#upload-using-maven) + * [Upload using Gradle](#upload-using-gradle) +* [Installing a package](#installing-a-package) + * [Install using Maven with `mvn install`](#install-using-maven-with-mvn-install) + * [Install with `mvn dependency:get`](#install-with-mvn-dependencyget) + * [Install using Gradle](#install-using-gradle) +* [Removing a package](#removing-a-package) +* [Creating Maven packages with GitLab CI/CD](#creating-maven-packages-with-gitlab-cicd) + * [Creating Maven packages with GitLab CI/CD using Maven](#creating-maven-packages-with-gitlab-cicd-using-maven) + * [Creating Maven packages with GitLab CI/CD using Gradle](#creating-maven-packages-with-gitlab-cicd-using-gradle) + * [Version validation](#version-validation) +* [Troubleshooting](#troubleshooting) + * [Useful Maven command line options](#useful-maven-command-line-options) + * [Verifying your Maven settings](#verifying-your-maven-settings) + +# GitLab Maven Repository[](#gitlab-maven-repository-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5811) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.3. + +使用 GitLab [Maven](https://maven.apache.org)存储库,每个项目都可以有自己的空间来存储其 Maven 工件. + +[![GitLab Maven Repository](img/243c1a9fc7dab75d6576c27470e73bf0.png)](img/maven_package_view_v12_6.png) + +## Enabling the Maven Repository[](#enabling-the-maven-repository "Permalink") + +**注意:**仅当您的 GitLab 管理员[启用了对 Maven 存储库的支持时,](../../../administration/packages/index.html)此选项才可用. + +启用"软件包"功能后,默认情况下,Maven 存储库将可用于所有新项目. 要为现有项目启用它,或者要禁用它: + +1. 导航到项目的**"设置">"常规">"可见性,项目功能,权限"** . +2. 找到"软件包"功能并启用或禁用它. +3. 单击**保存更改**以使更改生效. + +然后,您应该能够在左侧栏中看到" **程序包和注册表"**部分. 接下来,您必须配置您的项目以使用 GitLab Maven 存储库进行授权. + +## Getting Started with Maven[](#getting-started-with-maven "Permalink") + +本节将介绍安装 Maven 和构建软件包. 如果您不熟悉构建 Maven 软件包,这是一个快速入门. 如果您已经在使用 Maven 并且了解如何构建自己的软件包,请转到[下一节](#adding-the-gitlab-package-registry-as-a-maven-remote) . + +Maven 仓库也可以与 Gradle 一起很好地工作. 如果要设置 Gradle 项目,请继续[使用 Gradle 入门](#getting-started-with-gradle) . + +### Installing Maven[](#installing-maven "Permalink") + +所需的最低版本为: + +* Java 11.0.5 以上 +* Maven 3.6+ + +按照[maven.apache.org](https://maven.apache.org/install.html)上的说明下载并安装适用于您本地开发环境的 Maven. 安装完成后,通过运行以下命令验证您可以在终端中使用 Maven: + +``` +mvn --version +``` + +您应该在输出中看到类似于以下内容的内容: + +``` +Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-04T20:00:29+01:00) +Maven home: /Users//apache-maven-3.6.1 +Java version: 12.0.2, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-12.0.2.jdk/Contents/Home +Default locale: en_GB, platform encoding: UTF-8 +OS name: "mac os x", version: "10.15.2", arch: "x86_64", family: "mac" +``` + +### Creating a project[](#creating-a-project "Permalink") + +了解如何创建完整的 Java 项目不在本指南的范围内,但是您可以按照以下步骤创建一个新项目,该项目可以发布到 GitLab Package Registry. + +首先打开终端并创建一个目录,您要将目录存储在环境中. 从目录内部,您可以运行以下 Maven 命令来初始化新程序包: + +``` +mvn archetype:generate -DgroupId=com.mycompany.mydepartment -DartifactId=my-project -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false +``` + +参数如下: + +* `DgroupId` :标识您的包裹的唯一字符串. 您应该遵循[Maven 命名约定](https://maven.apache.org/guides/mini/guide-naming-conventions.html) . +* `DartifactId` :JAR 的名称,附加在`DgroupId`的末尾. +* `DarchetypeArtifactId` :用于创建项目初始结构的原型. +* `DinteractiveMode` :使用批处理模式(可选)创建项目. + +运行该命令后,您应该看到以下消息,表明您的项目已成功设置: + +``` +... +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 3.429 s +[INFO] Finished at: 2020-01-28T11:47:04Z +[INFO] ------------------------------------------------------------------------ +``` + +您应该看到一个新目录,在该目录中运行与`DartifactId`参数匹配的命令(在这种情况下,它应该是`my-project` ). + +## Getting started with Gradle[](#getting-started-with-gradle "Permalink") + +本节将介绍如何安装 Gradle 和初始化 Java 项目. 如果您不熟悉 Gradle,这是一个快速入门. 如果您已经在使用 Gradle 并且了解如何构建自己的软件包,请转到[下一部分](#adding-the-gitlab-package-registry-as-a-maven-remote) . + +### Installing Gradle[](#installing-gradle "Permalink") + +仅当您要创建新的 Gradle 项目时才需要安装. 按照[gradle.org](https://s0gradle0org.icopy.site/install/)上的说明为您的本地开发环境下载并安装 Gradle. + +通过运行以下命令验证您可以在终端中使用 Gradle: + +``` +gradle -version +``` + +如果要使用现有的 Gradle 项目,则不需要安装. 只需在项目目录中执行`gradlew` (在 Linux 上)或`gradlew.bat` (在 Windows 上)即可. + +You should see something imilar to the below printed in the output: + +``` +------------------------------------------------------------ +Gradle 6.0.1 +------------------------------------------------------------ + +Build time: 2019-11-18 20:25:01 UTC +Revision: fad121066a68c4701acd362daf4287a7c309a0f5 + +Kotlin: 1.3.50 +Groovy: 2.5.8 +Ant: Apache Ant(TM) version 1.10.7 compiled on September 1 2019 +JVM: 11.0.5 (Oracle Corporation 11.0.5+10) +OS: Windows 10 10.0 amd64 +``` + +### Creating a project in Gradle[](#creating-a-project-in-gradle "Permalink") + +了解如何在 Gradle 中创建完整的 Java 项目不在本指南的范围内,但是您可以按照以下步骤创建一个可以发布到 GitLab Package Registry 的新项目. + +首先打开终端并创建一个目录,您要将目录存储在环境中. 从目录内部,您可以运行以下 Maven 命令来初始化新程序包: + +``` +gradle init +``` + +输出应为 + +``` +Select type of project to generate: + 1: basic + 2: application + 3: library + 4: Gradle plugin +Enter selection (default: basic) [1..4] +``` + +输入`3`创建一个新的 Library 项目. 输出应为: + +``` +Select implementation language: + 1: C++ + 2: Groovy + 3: Java + 4: Kotlin + 5: Scala + 6: Swift +``` + +输入`3`创建一个新的 Java 库项目. 输出应为: + +``` +Select build script DSL: + 1: Groovy + 2: Kotlin +Enter selection (default: Groovy) [1..2] +``` + +选择`1`创建一个新的 Java 库项目,该项目将在 Groovy DSL 中进行描述. 输出应为: + +``` +Select test framework: + 1: JUnit 4 + 2: TestNG + 3: Spock + 4: JUnit Jupiter +``` + +选择`1`以使用 JUnit 4 测试库初始化项目. 输出应为: + +``` +Project name (default: test): +``` + +输入项目名称或按 Enter 键以使用目录名称作为项目名称. + +## Adding the GitLab Package Registry as a Maven remote[](#adding-the-gitlab-package-registry-as-a-maven-remote "Permalink") + +下一步是将 GitLab 软件包注册表添加为 Maven 遥控器. 如果项目是私有的,或者您想将 Maven 工件上传到 GitLab,则也需要提供凭据进行授权. 仅对[个人访问令牌](#authenticating-with-a-personal-access-token) , [CI 作业令牌](#authenticating-with-a-ci-job-token)和[部署令牌提供支持](../../project/deploy_tokens/index.html) . 常规的用户名/密码凭据不起作用. + +### Authenticating with a personal access token[](#authenticating-with-a-personal-access-token "Permalink") + +要使用[个人访问令牌进行](../../profile/personal_access_tokens.html)身份验证,请在创建[令牌](../../profile/personal_access_tokens.html)时将范围设置为`api` ,并将其添加到您的 Maven 或 Gradle 配置文件中. + +#### Authenticating with a personal access token in Maven[](#authenticating-with-a-personal-access-token-in-maven "Permalink") + +将相应的部分添加到[`settings.xml`](https://maven.apache.org/settings.html)文件中: + +``` + + + + gitlab-maven + + + + Private-Token + REPLACE_WITH_YOUR_PERSONAL_ACCESS_TOKEN + + + + + + +``` + +#### Authenticating with a personal access token in Gradle[](#authenticating-with-a-personal-access-token-in-gradle "Permalink") + +创建具有以下内容的文件`~/.gradle/gradle.properties` : + +``` +gitLabPrivateToken=REPLACE_WITH_YOUR_PERSONAL_ACCESS_TOKEN +``` + +在您的[`build.gradle`](https://s0docs0gradle0org.icopy.site/current/userguide/tutorial_using_tasks.html)文件中添加一个存储库部分: + +``` +repositories { + maven { + url "https:///api/v4/groups//-/packages/maven" + name "GitLab" + credentials(HttpHeaderCredentials) { + name = 'Private-Token' + value = gitLabPrivateToken + } + authentication { + header(HttpHeaderAuthentication) + } + } +} +``` + +You should now be able to upload Maven artifacts to your project. + +### Authenticating with a CI job token[](#authenticating-with-a-ci-job-token "Permalink") + +如果您使用的是 GitLab CI / CD,则可以使用 CI 作业令牌代替个人访问令牌. + +#### Authenticating with a CI job token in Maven[](#authenticating-with-a-ci-job-token-in-maven "Permalink") + +要使用 CI 作业令牌进行身份验证,请将相应部分添加到[`settings.xml`](https://maven.apache.org/settings.html)文件中: + +``` + + + + gitlab-maven + + + + Job-Token + ${env.CI_JOB_TOKEN} + + + + + + +``` + +您可以阅读有关[如何使用 GitLab CI / CD 创建 Maven 软件包的](#creating-maven-packages-with-gitlab-cicd)更多信息. + +#### Authenticating with a CI job token in Gradle[](#authenticating-with-a-ci-job-token-in-gradle "Permalink") + +要使用 CI 作业令牌进行身份验证,请在[`build.gradle`](https://s0docs0gradle0org.icopy.site/current/userguide/tutorial_using_tasks.html)文件中添加一个存储库部分: + +``` +repositories { + maven { + url "https:///api/v4/groups//-/packages/maven" + name "GitLab" + credentials(HttpHeaderCredentials) { + name = 'Job-Token' + value = '${CI_JOB_TOKEN}' + } + authentication { + header(HttpHeaderAuthentication) + } + } +} +``` + +### Authenticating with a deploy token[](#authenticating-with-a-deploy-token "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0. + +要使用[部署令牌进行](./../../project/deploy_tokens/index.html)身份验证,请在创建[令牌](./../../project/deploy_tokens/index.html)时将范围设置为`api` ,然后将其添加到您的 Maven 或 Gradle 配置文件中. + +#### Authenticating with a deploy token in Maven[](#authenticating-with-a-deploy-token-in-maven "Permalink") + +将相应的部分添加到[`settings.xml`](https://maven.apache.org/settings.html)文件中: + +``` + + + + gitlab-maven + + + + Deploy-Token + REPLACE_WITH_YOUR_DEPLOY_TOKEN + + + + + + +``` + +#### Authenticating with a deploy token in Gradle[](#authenticating-with-a-deploy-token-in-gradle "Permalink") + +要使用部署令牌进行身份验证,请将存储库部分添加到[`build.gradle`](https://s0docs0gradle0org.icopy.site/current/userguide/tutorial_using_tasks.html)文件中: + +``` +repositories { + maven { + url "https:///api/v4/groups//-/packages/maven" + name "GitLab" + credentials(HttpHeaderCredentials) { + name = 'Deploy-Token' + value = '' + } + authentication { + header(HttpHeaderAuthentication) + } + } +} +``` + +## Configuring your project to use the GitLab Maven repository URL[](#configuring-your-project-to-use-the-gitlab-maven-repository-url "Permalink") + +要从 GitLab 下载和上传软件包,您需要在`pom.xml`文件中的" `repository` and `distributionManagement`部分. 如果您按照上面的步骤操作,则需要将以下信息添加到`my-project/pom.xml`文件中. + +根据您的工作流程和所拥有的 Maven 软件包的数量,可以通过 3 种方式配置项目以将 GitLab 端点用于 Maven 软件包: + +* **项目级别** :当您有几个不在同一 GitLab 组中的 Maven 软件包时,此选项很有用. +* **组级别** :当您在同一个 GitLab 组中有多个 Maven 软件包时,此选项很有用. +* **实例级别** :当您在不同的 GitLab 组下或它们自己的名称空间上有许多 Maven 软件包时很有用. + +**注意:**在所有情况下,都需要一个项目特定的 URL 才能在`distributionManagement`部分中上载软件包. + +### Project level Maven endpoint[](#project-level-maven-endpoint "Permalink") + +下面的示例显示了`pom.xml`的相关`repository`部分在 Maven 中的样子: + +``` + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + +``` + +Gradle 中的相应部分如下所示: + +``` +repositories { + maven { + url "https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven" + name "GitLab" + } +} +``` + +该`id`必须与您[在`settings.xml`定义](#adding-the-gitlab-package-registry-as-a-maven-remote)的`id`相同. + +将`PROJECT_ID`替换为可以在项目主页上找到的项目 ID. + +如果您具有自行管理的 GitLab 安装, `gitlab.com`使用您的域名替换`gitlab.com` . + +**注意:**要检索工件,可以使用项目的[URL 编码](../../../api/README.html#namespaced-path-encoding)路径(例如`group/project` )或项目的 ID(例如`42` ). 但是,只能使用项目的 ID 进行上传. + +### Group level Maven endpoint[](#group-level-maven-endpoint "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8798) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7. + +如果您依赖于许多软件包,则在`repository`部分中为每个软件包添加唯一的 URL 可能效率不高. 相反,您可以将组级别端点用于存储在一个 GitLab 组中的所有 Maven 软件包. 只有您有权访问的软件包才可以下载. + +组级别端点可与任何程序包名称一起使用,这意味着与[实例级别端点](#instance-level-maven-endpoint)相比,您具有更大的命名灵活性. 但是,GitLab 不能保证软件包名称在组中的唯一性. 您可以有两个具有相同软件包名称和软件包版本的项目. 因此,GitLab 将服务于较新的那个. + +下面的示例显示`pom.xml`的相关`repository`部分的外观. 您仍需要一个特定于项目的 URL 来在`distributionManagement`部分中上传软件包: + +``` + + + gitlab-maven + https://gitlab.com/api/v4/groups/GROUP_ID/-/packages/maven + + + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + +``` + +对于 Gradle,相应的存储库部分如下所示: + +``` +repositories { + maven { + url "https://gitlab.com/api/v4/groups/GROUP_ID/-/packages/maven" + name "GitLab" + } +} +``` + +该`id`必须与您[在`settings.xml`定义](#adding-the-gitlab-package-registry-as-a-maven-remote)的`id`相同. + +在您的项目主页上可以找到您的组名,将`my-group`替换为您的组名,将`PROJECT_ID`替换为您的项目 ID. + +如果您具有自行管理的 GitLab 安装, `gitlab.com`使用您的域名替换`gitlab.com` . + +**注意:**对于检索工件,您可以使用组的[URL 编码](../../../api/README.html#namespaced-path-encoding)路径(例如`group/subgroup` )或组的 ID(例如`12` ). + +### Instance level Maven endpoint[](#instance-level-maven-endpoint "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8274) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7. + +如果您依赖于许多软件包,则在`repository`部分中为每个软件包添加唯一的 URL 可能效率不高. 相反,您可以对存储在 GitLab 中的所有 maven 程序包使用实例级别端点,并且可以访问您有权访问的程序包. + +请注意, **只有与项目路径相同的软件包才**通过实例级别端点公开. + +| Project | Package | 实例级别端点可用 | +| --- | --- | --- | +| `foo/bar` | `foo/bar/1.0-SNAPSHOT` | Yes | +| `gitlab-org/gitlab` | `foo/bar/1.0-SNAPSHOT` | No | +| `gitlab-org/gitlab` | `gitlab-org/gitlab/1.0-SNAPSHOT` | Yes | + +下面的示例显示`pom.xml`的相关`repository`部分的外观. 您仍需要一个特定于项目的 URL 来在`distributionManagement`部分中上传软件包: + +``` + + + gitlab-maven + https://gitlab.com/api/v4/packages/maven + + + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + + gitlab-maven + https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven + + +``` + +Gradle 中相应的存储库部分如下所示: + +``` +repositories { + maven { + url "https://gitlab.com/api/v4/packages/maven" + name "GitLab" + } +} +``` + +该`id`必须与您[在`settings.xml`定义](#adding-the-gitlab-package-registry-as-a-maven-remote)的`id`相同. + +将`PROJECT_ID`替换为可以在项目主页上找到的项目 ID. + +如果您具有自行管理的 GitLab 安装, `gitlab.com`使用您的域名替换`gitlab.com` . + +**Note:** For retrieving artifacts, you can use either the [URL encoded](../../../api/README.html#namespaced-path-encoding) path of the project (e.g., `group%2Fproject`) or the project’s ID (e.g., `42`). However, only the project’s ID can be used for uploading. + +## Uploading packages[](#uploading-packages "Permalink") + +一旦设置了[远程和身份验证](#adding-the-gitlab-package-registry-as-a-maven-remote)并[配置了项目](#configuring-your-project-to-use-the-gitlab-maven-repository-url) ,请测试以从[您的项目](#configuring-your-project-to-use-the-gitlab-maven-repository-url)中上传 Maven 工件. + +### Upload using Maven[](#upload-using-maven "Permalink") + +``` +mvn deploy +``` + +如果部署成功,您应该再次看到构建成功消息: + +``` +... +[INFO] BUILD SUCCESS +... +``` + +您还应该看到上传已上传到正确的注册表: + +``` +Uploading to gitlab-maven: https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.jar +``` + +### Upload using Gradle[](#upload-using-gradle "Permalink") + +将 Gradle 插件[`maven-publish`](https://s0docs0gradle0org.icopy.site/current/userguide/publishing_maven.html)添加到插件部分: + +``` +plugins { + id 'java' + id 'maven-publish' +} +``` + +添加`publishing`部分: + +``` +publishing { + publications { + library(MavenPublication) { + from components.java + } + } + repositories { + maven { + url "https://gitlab.com/api/v4/projects//packages/maven" + credentials(HttpHeaderCredentials) { + name = "Private-Token" + value = gitLabPrivateToken // the variable resides in ~/.gradle/gradle.properties + } + authentication { + header(HttpHeaderAuthentication) + } + } + } +} +``` + +将`PROJECT_ID`替换为可以在项目主页上找到的项目 ID. + +运行发布任务: + +``` +gradle publish +``` + +然后,您可以导航到项目的**Packages&Registries**页面,并查看上载的工件,甚至删除它们. + +## Installing a package[](#installing-a-package "Permalink") + +从 GitLab 程序包注册表安装程序包要求您如上所述设置[远程和身份验证](#adding-the-gitlab-package-registry-as-a-maven-remote) . 一旦完成,就有两种安装软件包的方法. + +### Install using Maven with `mvn install`[](#install-using-maven-with-mvn-install "Permalink") + +手动将依赖项添加到您的项目`pom.xml`文件中. 要添加上面创建的示例,XML 如下所示: + +``` + + com.mycompany.mydepartment + my-project + 1.0-SNAPSHOT + +``` + +然后,在您的项目中,运行以下命令: + +``` +mvn install +``` + +如果一切设置正确,您应该会看到从 GitLab 软件包注册表下载的依赖项: + +``` +Downloading from gitlab-maven: http://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.pom +``` + +#### Install with `mvn dependency:get`[](#install-with-mvn-dependencyget "Permalink") + +安装软件包的第二种方法是直接使用 Maven 命令. 在您的项目目录中,运行: + +``` +mvn dependency:get -Dartifact=com.nickkipling.app:nick-test-app:1.1-SNAPSHOT +``` + +您应该看到相同的下载消息,确认从 GitLab 软件包注册表中检索了该项目. + +**提示:** XML 块和 Maven 命令都可以从"软件包详细信息"页面中方便地复制和粘贴,从而可以快速简便地进行安装. + +### Install using Gradle[](#install-using-gradle "Permalink") + +添加[依赖](https://s0docs0gradle0org.icopy.site/current/userguide/declaring_dependencies.html)于依赖部分的 build.gradle: + +``` +dependencies { + implementation 'com.mycompany.mydepartment:my-project:1.0-SNAPSHOT' +} +``` + +## Removing a package[](#removing-a-package "Permalink") + +在项目页面的软件包视图中,您可以通过单击红色垃圾图标或单击软件包详细信息页面上的**删除**按钮来**删除**软件包. + +## Creating Maven packages with GitLab CI/CD[](#creating-maven-packages-with-gitlab-cicd "Permalink") + +一旦您的存储库配置为使用 GitLab Maven 存储库,就可以配置 GitLab CI / CD 来自动构建新软件包. + +### Creating Maven packages with GitLab CI/CD using Maven[](#creating-maven-packages-with-gitlab-cicd-using-maven "Permalink") + +下面的示例显示了每次更新`master`分支时如何创建新程序包: + +1. 创建一个`ci_settings.xml`文件,它将用作 Maven 的`settings.xml`文件. 添加与您在`pom.xml`文件中定义的 ID 相同的服务器部分. 例如,在我们的例子中是`gitlab-maven` : + + ``` + + + + gitlab-maven + + + + Job-Token + ${env.CI_JOB_TOKEN} + + + + + + + ``` + +2. 确保您的`pom.xml`文件包含以下内容: + + ``` + + + gitlab-maven + https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven + + + + + gitlab-maven + https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven + + + gitlab-maven + https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven + + + ``` + + **提示:**您可以让 Maven 利用 CI 环境变量,也可以硬编码项目的 ID. +3. 将`deploy`作业添加到您的`.gitlab-ci.yml`文件中: + + ``` + deploy: + image: maven:3.3.9-jdk-8 + script: + - 'mvn deploy -s ci_settings.xml' + only: + - master + ``` + +4. 将这些文件推送到您的存储库. + +下次运行`deploy`作业时,它将`ci_settings.xml`复制到用户的本地位置(在这种情况下,用户是`root`用户,因为它在 Docker 容器中运行),并且 Maven 将利用配置的 CI [环境变量](../../../ci/variables/README.html#predefined-environment-variables) . + +### Creating Maven packages with GitLab CI/CD using Gradle[](#creating-maven-packages-with-gitlab-cicd-using-gradle "Permalink") + +下面的示例显示了每次更新`master`分支时如何创建新程序包: + +1. 确保按照["使用 Gradle 中的 CI 作业令牌进行身份](#authenticating-with-a-ci-job-token-in-gradle)验证"中所述使用 Job-Token 身份[验证](#authenticating-with-a-ci-job-token-in-gradle) . + +2. 将`deploy`作业添加到您的`.gitlab-ci.yml`文件中: + + ``` + deploy: + image: gradle:latest + script: + - 'gradle publish' + only: + - master + ``` + +3. 将这些文件推送到您的存储库. + +下次运行`deploy`作业时,它将`ci_settings.xml`复制到用户的本地位置(在这种情况下,用户是`root`用户,因为它在 Docker 容器中运行),并且 Maven 将使用配置的 CI [环境变量](../../../ci/variables/README.html#predefined-environment-variables) . + +### Version validation[](#version-validation "Permalink") + +使用以下正则表达式验证版本字符串. + +``` +\A(\.?[\w\+-]+\.?)+\z +``` + +您可以使用正则表达式,并在[此正则表达式编辑器](https://rubular.com/r/rrLQqUXjfKEoL6)上尝试使用版本字符串. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Useful Maven command line options[](#useful-maven-command-line-options "Permalink") + +有一些[Maven 命令行选项](https://maven.apache.org/ref/current/maven-embedder/cli.html)在使用 GitLab CI / CD 执行任务时可能有用. + +* 文件传输进度会使 CI 日志难以阅读. 选项`-ntp,--no-transfer-progress`已在[3.6.1](https://maven.apache.org/docs/3.6.1/release-notes.html#User_visible_Changes)中添加. 或者,查看`-B,--batch-mode` [或较低级别的日志记录更改.](https://stackoverflow.com/questions/21638697/disable-maven-download-progress-indication) + +* 指定在哪里可以找到 POM 文件( `-f,--file` ): + + ``` + package: + script: + - 'mvn --no-transfer-progress -f helloworld/pom.xml package' + ``` + +* 指定在哪里可以找到用户设置( `-s,--settings` ),而不是[默认位置](https://maven.apache.org/settings.html) . 还有一个`-gs,--global-settings`选项: + + ``` + package: + script: + - 'mvn -s settings/ci.xml package' + ``` + +### Verifying your Maven settings[](#verifying-your-maven-settings "Permalink") + +如果您在 CI 中遇到与`settings.xml`文件有关的问题,则添加其他脚本任务或作业以[验证有效设置](https://maven.apache.org/plugins/maven-help-plugin/effective-settings-mojo.html)可能会很有用. + +帮助插件还可以提供[系统属性](https://maven.apache.org/plugins/maven-help-plugin/system-mojo.html) ,包括环境变量: + +``` +mvn-settings: + script: + - 'mvn help:effective-settings' + +package: + script: + - 'mvn help:system' + - 'mvn package' +``` \ No newline at end of file diff --git a/docs/281.md b/docs/281.md new file mode 100644 index 0000000000000000000000000000000000000000..a84123dd0133e4236c57d1cc279090956de61922 --- /dev/null +++ b/docs/281.md @@ -0,0 +1,367 @@ +# GitLab NPM Registry + +> 原文:[https://docs.gitlab.com/ee/user/packages/npm_registry/](https://docs.gitlab.com/ee/user/packages/npm_registry/) + +* [Enabling the NPM Registry](#enabling-the-npm-registry) +* [Getting started](#getting-started) + * [Installing NPM](#installing-npm) + * [Installing Yarn](#installing-yarn) + * [Creating a project](#creating-a-project) +* [Authenticating to the GitLab NPM Registry](#authenticating-to-the-gitlab-npm-registry) + * [Authenticating with a personal access token or deploy token](#authenticating-with-a-personal-access-token-or-deploy-token) + * [Using variables to avoid hard-coding auth token values](#using-variables-to-avoid-hard-coding-auth-token-values) + * [Authenticating with a CI job token](#authenticating-with-a-ci-job-token) +* [Uploading packages](#uploading-packages) +* [Uploading a package with the same version twice](#uploading-a-package-with-the-same-version-twice) +* [Package naming convention](#package-naming-convention) +* [Installing a package](#installing-a-package) + * [Forwarding requests to npmjs.org](#forwarding-requests-to-npmjsorg) +* [Removing a package](#removing-a-package) +* [Publishing a package with CI/CD](#publishing-a-package-with-cicd) +* [Troubleshooting](#troubleshooting) + * [Error running yarn with NPM registry](#error-running-yarn-with-npm-registry) + * [`npm publish` targets default NPM registry (`registry.npmjs.org`)](#npm-publish-targets-default-npm-registry-registrynpmjsorg) + * [`npm install` returns `Error: Failed to replace env in config: ${NPM_TOKEN}`](#npm-install-returns-error-failed-to-replace-env-in-config-npm_token) + * [`npm install` returns `npm ERR! 403 Forbidden`](#npm-install-returns-npm-err-403-forbidden) +* [NPM dependencies metadata](#npm-dependencies-metadata) +* [NPM distribution tags](#npm-distribution-tags) + +# GitLab NPM Registry[](#gitlab-npm-registry-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7. + +使用 GitLab NPM 注册表,每个项目都可以拥有自己的空间来存储 NPM 软件包. + +[![GitLab NPM Registry](img/72befe6a3da1a58465dbf55200aefd26.png)](img/npm_package_view_v12_5.png) + +**注意:**仅支持[作用域的](https://s0docs0npmjs0com.icopy.site/misc/scope)程序包. + +## Enabling the NPM Registry[](#enabling-the-npm-registry "Permalink") + +**注意:**仅当您的 GitLab 管理员[启用了对 NPM 注册表的支持时,](../../../administration/packages/index.html)此选项才可用. + +启用 NPM 注册表后,默认情况下它将可用于所有新项目. 要为现有项目启用它,或者要禁用它: + +1. 导航到项目的**"设置">"常规">"可见性,项目功能,权限"** . +2. 找到"软件包"功能并启用或禁用它. +3. 单击**保存更改**以使更改生效. + +然后,您应该能够在左侧栏中看到" **程序包和注册表"**部分. + +在继续使用 GitLab NPM 注册表进行身份验证之前,您应该熟悉软件包的命名约定. + +## Getting started[](#getting-started "Permalink") + +本节将介绍安装 NPM(或 Yarn)并为您的 JavaScript 项目构建软件包. 如果您不熟悉 NPM 软件包,这是一个快速入门. 如果您已经在使用 NPM 并了解如何构建自己的软件包,请继续[下一节](#authenticating-to-the-gitlab-npm-registry) . + +### Installing NPM[](#installing-npm "Permalink") + +按照[npmjs.com](https://s0docs0npmjs0com.icopy.site/downloading-and-installing-node-js-and-npm)上的说明下载 Node.js 和 NPM 并将其安装到本地开发环境. + +安装完成后,通过运行以下命令验证您可以在终端中使用 NPM: + +``` +npm --version +``` + +您应该会在输出中看到 NPM 版本: + +``` +6.10.3 +``` + +### Installing Yarn[](#installing-yarn "Permalink") + +您可能需要安装并使用 Yarn 替代 NPM. 请按照[yarnpkg.com](https://classic.yarnpkg.com/en/docs/install)上的说明在您的开发环境上进行安装. + +Once installed, you can verify that Yarn is available with the following command: + +``` +yarn --version +``` + +You should see the version printed like so: + +``` +1.19.1 +``` + +### Creating a project[](#creating-a-project "Permalink") + +了解如何创建完整的 JavaScript 项目不在本指南的范围内,但是您可以通过创建并导航到空目录并使用以下命令来初始化新的空包: + +``` +npm init +``` + +或者,如果您使用的是 Yarn: + +``` +yarn init +``` + +这将带您解决一系列问题,以产生`package.json`文件,这是所有 NPM 软件包所必需的. 最重要的问题是软件包名称. NPM 软件包必须[遵循命名约定,](#package-naming-convention)并且范围应限于注册表所在的项目或组. + +完成设置后,现在就可以将软件包上传到 GitLab 注册表了. 首先,您需要设置身份验证,然后将 GitLab 配置为远程注册表. + +## Authenticating to the GitLab NPM Registry[](#authenticating-to-the-gitlab-npm-registry "Permalink") + +如果项目是私有项目,或者您要将 NPM 软件包上传到 GitLab,则需要提供凭据进行身份验证. 首选[个人访问令牌](../../profile/personal_access_tokens.html)和[部署令牌](../../project/deploy_tokens/index.html) ,但支持[OAuth 令牌](../../../api/oauth2.html#resource-owner-password-credentials-flow) . + +**双因素认证(2FA)仅支持个人访问令牌:**如果你有 2FA 启用,你需要使用一个[令牌个人访问](../../profile/personal_access_tokens.html)使用 OAuth 标题与范围设置为`api`或[令牌部署](../../project/deploy_tokens/index.html)与`read_package_registry`或`write_package_registry`范围. 标准 OAuth 令牌将无法向 GitLab NPM 注册表进行身份验证. + +### Authenticating with a personal access token or deploy token[](#authenticating-with-a-personal-access-token-or-deploy-token "Permalink") + +要使用[个人访问令牌](../../profile/personal_access_tokens.html)或[部署令牌进行](../../project/deploy_tokens/index.html)身份验证,请设置 NPM 配置: + +``` +# Set URL for your scoped packages. +# For example package with name `@foo/bar` will use this URL for download +npm config set @foo:registry https://gitlab.com/api/v4/packages/npm/ + +# Add the token for the scoped packages URL. This will allow you to download +# `@foo/` packages from private projects. +npm config set '//gitlab.com/api/v4/packages/npm/:_authToken' "" + +# Add token for uploading to the registry. Replace +# with the project you want your package to be uploaded to. +npm config set '//gitlab.com/api/v4/projects//packages/npm/:_authToken' "" +``` + +将``替换为可以在项目主页上找到的项目 ID,并将``替换为个人访问令牌或部署令牌. + +如果您具有自行管理的 GitLab 安装, `gitlab.com`使用您的域名替换`gitlab.com` . + +现在,您应该能够将 NPM 软件包下载并上传到您的项目. + +**注意:**如果遇到有关[Yarn](https://classic.yarnpkg.com/en/)的错误消息,请参阅[故障排除部分](#troubleshooting) . + +### Using variables to avoid hard-coding auth token values[](#using-variables-to-avoid-hard-coding-auth-token-values "Permalink") + +为了避免对`authToken`值进行硬编码,可以在其位置使用变量: + +``` +npm config set '//gitlab.com/api/v4/projects//packages/npm/:_authToken' "${NPM_TOKEN}" +npm config set '//gitlab.com/api/v4/packages/npm/:_authToken' "${NPM_TOKEN}" +``` + +然后,您可以在本地或通过 GitLab CI / CD 运行`npm publish` : + +* **本地:**发布前导出`NPM_TOKEN` : + + ``` + NPM_TOKEN= npm publish + ``` + +* **GitLab CI / CD:**设置`NPM_TOKEN` [变量](../../../ci/variables/README.html)下,项目的**设置> CI / CD>变量** . + +### Authenticating with a CI job token[](#authenticating-with-a-ci-job-token "Permalink") + +在 GitLab Premium 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9104) . + +如果您将 NPM 与 GitLab CI / CD 一起使用,则可以使用 CI 作业令牌代替个人访问令牌或部署令牌. 令牌将继承生成管道的用户的权限. + +将相应的部分添加到您的`.npmrc`文件中: + +``` +@foo:registry=https://gitlab.com/api/v4/packages/npm/ +//gitlab.com/api/v4/packages/npm/:_authToken=${CI_JOB_TOKEN} +//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN} +``` + +## Uploading packages[](#uploading-packages "Permalink") + +在能够上载软件包之前,您需要为 NPM 指定注册表. 为此,将以下部分添加到`package.json`的底部: + +``` +"publishConfig": { "@foo:registry":"https://gitlab.com/api/v4/projects//packages/npm/" } +``` + +将``替换为您的项目 ID(可在项目的主页上找到),然后将`@foo`替换为您自己的作用域. + +如果您具有自行管理的 GitLab 安装, `gitlab.com`使用您的域名替换`gitlab.com` . + +启用它并设置[身份验证后](#authenticating-to-the-gitlab-npm-registry) ,您可以将 NPM 包上传到您的项目中: + +``` +npm publish +``` + +然后,您可以导航到项目的" **程序包和注册表"**页面,查看上载的程序包,甚至删除它们. + +如果尝试使用给定范围内已经存在的名称发布程序包,则会收到`403 Forbidden!` 错误. + +## Uploading a package with the same version twice[](#uploading-a-package-with-the-same-version-twice "Permalink") + +您不能两次上传相同名称和版本的软件包,除非先删除现有软件包. 这与 npmjs.org 的行为保持一致,但 npmjs.org 不允许用户多次发布同一版本,即使该版本已被删除也是如此. + +## Package naming convention[](#package-naming-convention "Permalink") + +**程序包的作用域必须在项目的根名称空间中** . 程序包名称可以是任何名称,但最好使用项目名称,除非由于命名冲突而无法使用. 例如: + +| Project | Package | Supported | +| --- | --- | --- | +| `foo/bar` | `@foo/bar` | Yes | +| `foo/bar/baz` | `@foo/baz` | Yes | +| `foo/bar/buz` | `@foo/anything` | Yes | +| `gitlab-org/gitlab` | `@gitlab-org/gitlab` | Yes | +| `gitlab-org/gitlab` | `@foo/bar` | No | + +用于命名的正则表达式正在验证来自所有程序包管理器的所有程序包名称: + +``` +/\A\@?(([\w\-\.\+]*)\/)*([\w\-\.]+)@?(([\w\-\.\+]*)\/)*([\w\-\.]*)\z/ +``` + +它允许使用大写字母,而 NPM 不允许,并且几乎允许 NPM 允许的所有字符,但有少数例外(不允许`~` ). + +**注意:**需要大写字母,因为要求范围必须与项目的顶级名称空间相同. 因此,例如,如果您的项目路径为`My-Group/project-foo` ,则您的程序包必须命名为`@My-Group/any-package-name` . `@my-group/any-package-name`不起作用.**在更新用户/组的路径或传输(子)组/项目时:**如果使用 NPM 包更新**项目**的根名称空间,则更改将被拒绝. 为此,请确保先删除所有 NPM 软件包. 不要忘记更新`.npmrc`文件以遵循上述命名约定,并在必要时运行`npm publish` . + +现在,您可以配置项目以通过 GitLab NPM 注册表进行身份验证. + +## Installing a package[](#installing-a-package "Permalink") + +NPM 软件包通常使用 JavaScript 项目中的`npm`或`yarn`命令安装. 如果尚未安装,则需要设置作用域软件包的 URL. 您可以使用以下命令执行此操作: + +``` +npm config set @foo:registry https://gitlab.com/api/v4/packages/npm/ +``` + +您将需要用您的作用域替换`@foo` . + +接下来,您需要确保已设置[身份验证](#authenticating-to-the-gitlab-npm-registry) ,以便成功安装软件包. 完成此操作后,您可以在项目中运行以下命令来安装软件包: + +``` +npm install @my-project-scope/my-package +``` + +或者,如果您使用的是 Yarn: + +``` +yarn add @my-project-scope/my-package +``` + +### Forwarding requests to npmjs.org[](#forwarding-requests-to-npmjsorg "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/55344) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.9. + +默认情况下,当在 GitLab NPM 注册表中找不到 NPM 软件包时,该请求将转发到[npmjs.com](https://s0www0npmjs0com.icopy.site/) . + +管理员可以在" [持续集成"设置中](../../admin_area/settings/continuous_integration.html)禁用此行为. + +## Removing a package[](#removing-a-package "Permalink") + +在项目页面的软件包视图中,您可以通过单击红色垃圾图标或单击软件包详细信息页面上的**删除**按钮来**删除**软件包. + +## Publishing a package with CI/CD[](#publishing-a-package-with-cicd "Permalink") + +要在[GitLab CI / CD 中](./../../../ci/README.html)使用 NPM 命令,可以使用`CI_JOB_TOKEN`代替个人访问令牌或在命令中部署令牌. + +一个简单的`.gitlab-ci.yml`文件示例,用于发布 NPM 软件包: + +``` +image: node:latest + +stages: + - deploy + +deploy: + stage: deploy + script: + - echo '//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}'>.npmrc + - npm publish +``` + +了解有关[使用`CI_JOB_TOKEN`验证 GitLab NPM 注册表的更多信息](#authenticating-with-a-ci-job-token) . + +## Troubleshooting[](#troubleshooting "Permalink") + +### Error running yarn with NPM registry[](#error-running-yarn-with-npm-registry "Permalink") + +如果您在 NPM 注册表中使用[yarn](https://classic.yarnpkg.com/en/) ,则可能会收到以下错误消息: + +``` +yarn install v1.15.2 +warning package.json: No license field +info No lockfile found. +warning XXX: No license field +[1/4] 🔍 Resolving packages... +[2/4] 🚚 Fetching packages... +error An unexpected error occurred: "https://gitlab.com/api/v4/projects/XXX/packages/npm/XXX/XXX/-/XXX/XXX-X.X.X.tgz: Request failed \"404 Not Found\"". +info If you think this is a bug, please open a bug report with the information provided in "/Users/XXX/gitlab-migration/module-util/yarn-error.log". +info Visit https://classic.yarnpkg.com/en/docs/cli/install for documentation about this command +``` + +在这种情况下,请尝试将其添加到您的`.npmrc`文件中(并将``替换为您的个人访问令牌或部署令牌): + +``` +//gitlab.com/api/v4/projects/:_authToken= +``` + +### `npm publish` targets default NPM registry (`registry.npmjs.org`)[](#npm-publish-targets-default-npm-registry-registrynpmjsorg "Permalink") + +确保在`package.json`和`.npmrc`文件中一致设置了包作用域. + +例如,如果您在 GitLab 中的项目名称为`foo/my-package` ,则`package.json`文件应如下所示: + +``` +{ "name": "@foo/my-package", "version": "1.0.0", "description": "Example package for GitLab NPM registry", "publishConfig": { "@foo:registry":"https://gitlab.com/api/v4/projects//packages/npm/" } } +``` + +`.npmrc`文件应如下所示: + +``` +//gitlab.com/api/v4/projects//packages/npm/:_authToken= +//gitlab.com/api/v4/packages/npm/:_authToken= +@foo:registry=https://gitlab.com/api/v4/packages/npm/ +``` + +### `npm install` returns `Error: Failed to replace env in config: ${NPM_TOKEN}`[](#npm-install-returns-error-failed-to-replace-env-in-config-npm_token "Permalink") + +除非您的项目是私有的,否则您不需要令牌即可运行`npm install` (仅要求发布令牌). 如果`.npmrc`文件是以`$NPM_TOKEN`的引用签`$NPM_TOKEN` ,则可以将其删除. 如果您希望保留参考,则需要在运行`npm install`之前设置一个值,或者使用[GitLab 环境变量](./../../../ci/variables/README.html)来设置该值: + +``` +NPM_TOKEN= npm install +``` + +### `npm install` returns `npm ERR! 403 Forbidden`[](#npm-install-returns-npm-err-403-forbidden "Permalink") + +* 检查您的令牌是否已过期并具有适当的权限. +* 检查您是否尝试发布名称在给定范围内已经存在的软件包. +* 确保作用域的软件包 URL 包含斜杠: + * 正确: `//gitlab.com/api/v4/packages/npm/` + * 错误的: `//gitlab.com/api/v4/packages/npm` + +## NPM dependencies metadata[](#npm-dependencies-metadata "Permalink") + +在 GitLab Premium 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/11867) . + +从 GitLab 12.6 开始,发布到 GitLab NPM 注册表的新软件包向 NPM 客户端公开了以下属性: + +* name +* version +* dist-tags +* dependencies + * dependencies + * devDependencies + * bundleDependencies + * peerDependencies + * deprecated + +## NPM distribution tags[](#npm-distribution-tags "Permalink") + +在 GitLab Premium 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9425) . + +您可以为新发布的软件包添加[分发标签](https://s0docs0npmjs0com.icopy.site/cli/dist-tag) . 它们遵循 NPM 的约定,在这些约定中它们是可选的,并且每个标签一次只能分配给一个软件包. 当发布没有标签的软件包时,默认情况下会添加`latest`标签. 在未指定标签或版本的情况下安装软件包也是如此. + +支持的`dist-tag`命令和通常使用标签的示例: + +``` +npm publish @scope/package --tag # Publish new package with new tag +npm dist-tag add @scope/package@version my-tag # Add a tag to an existing package +npm dist-tag ls @scope/package # List all tags under the package +npm dist-tag rm @scope/package@version my-tag # Delete a tag from the package +npm install @scope/package@my-tag # Install a specific tag +``` + +**警告:**由于 NPM 6.9.0 中的错误,删除 dist 标签失败. 确保您的 NPM 版本大于 6.9.1. \ No newline at end of file diff --git a/docs/282.md b/docs/282.md new file mode 100644 index 0000000000000000000000000000000000000000..97a3e60efbd14a3f18e7fa1f5df2c29bdfe55845 --- /dev/null +++ b/docs/282.md @@ -0,0 +1,227 @@ +# GitLab NuGet Repository + +> 原文:[https://docs.gitlab.com/ee/user/packages/nuget_repository/](https://docs.gitlab.com/ee/user/packages/nuget_repository/) + +* [Setting up your development environment](#setting-up-your-development-environment) + * [macOS support](#macos-support) +* [Enabling the NuGet Repository](#enabling-the-nuget-repository) +* [Adding the GitLab NuGet Repository as a source to NuGet](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget) + * [Add NuGet Repository source with NuGet CLI](#add-nuget-repository-source-with-nuget-cli) + * [Add NuGet Repository source with Visual Studio](#add-nuget-repository-source-with-visual-studio) + * [Add NuGet Repository source with .NET CLI](#add-nuget-repository-source-with-net-cli) +* [Uploading packages](#uploading-packages) + * [Upload packages with NuGet CLI](#upload-packages-with-nuget-cli) + * [Upload packages with .NET CLI](#upload-packages-with-net-cli) +* [Install packages](#install-packages) + * [Install a package with NuGet CLI](#install-a-package-with-nuget-cli) + * [Install a package with .NET CLI](#install-a-package-with-net-cli) + +# GitLab NuGet Repository[](#gitlab-nuget-repository-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20050) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.8. + +使用 GitLab NuGet 存储库,每个项目都可以拥有自己的空间来存储 NuGet 软件包. + +GitLab NuGet 存储库可用于: + +* [NuGet CLI](https://docs.microsoft.com/en-us/nuget/reference/nuget-exe-cli-reference) +* [.NET Core CLI](https://docs.microsoft.com/en-us/dotnet/core/tools/) +* [Visual Studio](https://visualstudio.microsoft.com/vs/) + +## Setting up your development environment[](#setting-up-your-development-environment "Permalink") + +您将需要[NuGet CLI 5.2 或更高版本](https://www.nuget.org/downloads) . 早期版本尚未针对 GitLab NuGet 存储库进行测试,因此可能无法正常工作. 如果您具有[Visual Studio](https://visualstudio.microsoft.com/vs/) ,则可能已经安装了 NuGet CLI. + +或者,您可以使用[.NET SDK 3.0 或更高版本](https://dotnet.microsoft.com/download/dotnet-core/3.0) ,该版本将安装 NuGet CLI. + +您可以通过以下方法确认已正确安装[NuGet CLI](https://www.nuget.org/) : + +``` +nuget help +``` + +您应该看到类似以下内容: + +``` +NuGet Version: 5.2.0.6090 +usage: NuGet [args] [options] +Type 'NuGet help ' for help on a specific command. + +Available commands: + +[output truncated] +``` + +### macOS support[](#macos-support "Permalink") + +对于 macOS,您还可以使用[Mono](https://www.mono-project.com/)运行 NuGet CLI. 对于 Homebrew 用户,请运行`brew install mono`来安装 Mono. 然后,您应该能够从[NuGet CLI 页面](https://www.nuget.org/downloads)下载 Windows C#二进制文件`nuget.exe`并运行: + +``` +mono nuget.exe +``` + +## Enabling the NuGet Repository[](#enabling-the-nuget-repository "Permalink") + +**注意:**仅当您的 GitLab 管理员[启用了对 Package Registry 的支持时,](../../../administration/packages/index.html)此选项才可用. + +启用 NuGet 存储库后,默认情况下它将可用于所有新项目. 要为现有项目启用它,或者要禁用它: + +1. 导航到项目的**"设置">"常规">"可见性,项目功能,权限"** . +2. 找到"软件包"功能并启用或禁用它. +3. 单击**保存更改**以使更改生效. + +然后,您应该能够在左侧栏中看到" **程序包和注册表"**部分. + +## Adding the GitLab NuGet Repository as a source to NuGet[](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget "Permalink") + +您将需要以下内容: + +* 您的 GitLab 用户名. +* 个人访问令牌或部署令牌. 对于存储库身份验证: + * 您可以将范围设置为`api`来生成[个人访问令牌](../../../user/profile/personal_access_tokens.html) . + * 您可以生成[令牌部署](./../../project/deploy_tokens/index.html)与范围设置为`read_package_registry` , `write_package_registry` ,或两者兼而有之. +* 您的来源的合适名称. +* 您的项目 ID,可以在项目的主页上找到. + +您现在可以使用以下方法向 NuGet 添加新的源: + +* [NuGet CLI](#add-nuget-repository-source-with-nuget-cli) +* [Visual Studio](#add-nuget-repository-source-with-visual-studio). +* [.NET CLI](#add-nuget-repository-source-with-net-cli) + +### Add NuGet Repository source with NuGet CLI[](#add-nuget-repository-source-with-nuget-cli "Permalink") + +要将 GitLab NuGet 存储库添加为带有`nuget`的源: + +``` +nuget source Add -Name -Source "https://gitlab-instance.example.com/api/v4/projects//packages/nuget/index.json" -UserName -Password +``` + +Where: + +* ``是所需的源名称. + +例如: + +``` +nuget source Add -Name "GitLab" -Source "https://gitlab.example/api/v4/projects/10/packages/nuget/index.json" -UserName carol -Password 12345678asdf +``` + +### Add NuGet Repository source with Visual Studio[](#add-nuget-repository-source-with-visual-studio "Permalink") + +1. Open [Visual Studio](https://visualstudio.microsoft.com/vs/). +2. 打开" **文件">"选项"** (Windows)或" **Visual Studio">"首选项"** (Mac OS). +3. 在**NuGet**部分中,打开**Sources** . 您将看到所有 NuGet 来源的列表. +4. Click **Add**. +5. 填写以下字段: + * **名称** :源的期望名称 + * **位置** : `https://gitlab.com/api/v4/projects//packages/nuget/index.json` : `https://gitlab.com/api/v4/projects//packages/nuget/index.json` + * 将``替换为您的项目 ID. + * 如果您具有自行管理的 GitLab 安装, `gitlab.com`使用您的域名替换`gitlab.com` . + * **用户**名:您的 GitLab 用户名或部署令牌用户名 + * **密码** :您的个人访问令牌或部署令牌 + + [![Visual Studio 添加 NuGet 源](img/a792de1a5441a31253d7a939dfd2de54.png)](img/visual_studio_adding_nuget_source.png) + +6. Click **Save**. + + [![Visual Studio NuGet source added](img/f6b1fbcae610d7e8b04ec117e32573f3.png)](img/visual_studio_nuget_source_added.png) + +如有任何警告,请确保**Location** , **Username**和**Password**正确. + +### Add NuGet Repository source with .NET CLI[](#add-nuget-repository-source-with-net-cli "Permalink") + +要将 GitLab NuGet 存储库添加为.NET 的源, `nuget.config`在项目的根目录中创建一个名为`nuget.config`的文件,其内容如下: + +``` + + + + + + + + + + + + + +``` + +## Uploading packages[](#uploading-packages "Permalink") + +上载套件时,请注意: + +* 允许的最大大小为 50 MB. +* 如果您多次上传具有相同版本的相同程序包,则每次连续上传都将保存为单独的文件. 安装软件包时,GitLab 将提供最新文件. +* 将软件包上传到 GitLab 时,它们不会立即显示在项目的软件包 UI 中. 处理包裹最多可能需要 10 分钟. + +### Upload packages with NuGet CLI[](#upload-packages-with-nuget-cli "Permalink") + +本部分假定您的项目已正确构建,并且已经[使用 NuGet CLI 创建了 NuGet 软件包](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package) . 使用以下命令上传软件包: + +``` +nuget push -Source +``` + +Where: + +* ``是您的软件包文件名,以`.nupkg`结尾. +* ``是[安装过程中使用](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget)的[源名称](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget) . + +### Upload packages with .NET CLI[](#upload-packages-with-net-cli "Permalink") + +本节假定您的项目已正确构建,并且已经[使用.NET CLI 创建了 NuGet 软件包](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package-dotnet-cli) . 使用以下命令上传软件包: + +``` +dotnet nuget push --source +``` + +Where: + +* ``是您的软件包文件名,以`.nupkg`结尾. +* ``是[安装过程中使用](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget)的[源名称](#adding-the-gitlab-nuget-repository-as-a-source-to-nuget) . + +例如: + +``` +dotnet nuget push MyPackage.1.0.0.nupkg --source gitlab +``` + +## Install packages[](#install-packages "Permalink") + +### Install a package with NuGet CLI[](#install-a-package-with-nuget-cli "Permalink") + +**警告:**默认情况下, `nuget`检查的官方消息`nuget.org`第一. 如果您在 GitLab NuGet 存储库中拥有与`nuget.org`的软件包同名的软件包, `nuget.org`必须指定源名称,否则将安装错误的软件包. + +使用以下命令安装最新版本的软件包: + +``` +nuget install -OutputDirectory \ + -Version \ + -Source +``` + +Where: + +* ``是软件包 ID. +* ``是将在其中安装软件包的输出目录. +* `` (可选)是软件包版本. +* `` (可选)是源名称. + +### Install a package with .NET CLI[](#install-a-package-with-net-cli "Permalink") + +**Warning:** If you have a package in the GitLab NuGet Repository with the same name as a package at a different source, you should verify the order in which `dotnet` checks sources during install. This is defined in the `nuget.config` file. + +使用以下命令安装最新版本的软件包: + +``` +dotnet add package \ + -v +``` + +Where: + +* ``是软件包 ID. +* `` (可选)是软件包版本. \ No newline at end of file diff --git a/docs/283.md b/docs/283.md new file mode 100644 index 0000000000000000000000000000000000000000..71392653e80d122b62ad9c6e7221942b88bf9432 --- /dev/null +++ b/docs/283.md @@ -0,0 +1,264 @@ +# GitLab PyPi Repository + +> 原文:[https://docs.gitlab.com/ee/user/packages/pypi_repository/](https://docs.gitlab.com/ee/user/packages/pypi_repository/) + +* [Setting up your development environment](#setting-up-your-development-environment) +* [Enabling the PyPi Repository](#enabling-the-pypi-repository) +* [Getting started](#getting-started) + * [Create a project](#create-a-project) + * [Create a package](#create-a-package) +* [Adding the GitLab PyPi Repository as a source](#adding-the-gitlab-pypi-repository-as-a-source) + * [Authenticating with a personal access token](#authenticating-with-a-personal-access-token) + * [Authenticating with a deploy token](#authenticating-with-a-deploy-token) +* [Uploading packages](#uploading-packages) + * [Upload packages with Twine](#upload-packages-with-twine) +* [Install packages](#install-packages) + +# GitLab PyPi Repository[](#gitlab-pypi-repository-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208747) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10. + +使用 GitLab PyPi 信息库,每个项目都可以有自己的空间来存储 PyPi 软件包. + +GitLab PyPi 存储库可用于: + +* [pip](https://s0pypi0org.icopy.site/project/pip/) +* [twine](https://s0pypi0org.icopy.site/project/twine/) + +## Setting up your development environment[](#setting-up-your-development-environment "Permalink") + +您将需要最新版本的[pip](https://s0pypi0org.icopy.site/project/pip/)和[twine](https://s0pypi0org.icopy.site/project/twine/) . + +## Enabling the PyPi Repository[](#enabling-the-pypi-repository "Permalink") + +**注意:**仅当您的 GitLab 管理员[启用了对 Package Registry 的支持时,](../../../administration/packages/index.html)此选项才可用. + +启用 PyPi 储存库后,默认情况下它将可用于所有新项目. 要为现有项目启用它,或者要禁用它: + +1. 导航到项目的**"设置">"常规">"可见性,项目功能,权限"** . +2. 找到"软件包"功能并启用或禁用它. +3. 单击**保存更改**以使更改生效. + +然后,您应该能够在左侧栏中看到" **程序包和注册表"**部分. + +## Getting started[](#getting-started "Permalink") + +本节将介绍如何创建一个新的示例 PyPi 包进行上传. 这是测试**GitLab PyPi Registry**的快速入门. 如果您已经了解如何构建和发布自己的软件包,请继续[下一节](#adding-the-gitlab-pypi-repository-as-a-source) . + +### Create a project[](#create-a-project "Permalink") + +了解如何创建完整的 Python 项目不在本指南的范围内,但是您可以创建一个小包来测试注册表. 首先创建一个名为`MyPyPiPackage`的新目录: + +``` +mkdir MyPyPiPackage && cd MyPyPiPackage +``` + +创建此目录后,在其中创建另一个目录: + +``` +mkdir mypypipackage && cd mypypipackage +``` + +在此目录中创建两个新文件以设置基本项目: + +``` +touch __init__.py +touch greet.py +``` + +在`greet.py` ,添加以下代码: + +``` +def SayHello(): + print("Hello from MyPyPiPackage") + return +``` + +在`__init__.py`文件中,添加以下内容: + +``` +from .greet import SayHello +``` + +现在,我们的项目基础已经完成,我们可以测试代码是否运行. 在顶部`MyPyPiPackage`目录中启动 Python 提示符. 然后运行: + +``` +>>> from mypypipackage import SayHello +>>> SayHello() +``` + +您应该看到类似于以下内容的输出: + +``` +Python 3.8.2 (v3.8.2:7b3ab5921f, Feb 24 2020, 17:52:18) +[Clang 6.0 (clang-600.0.57)] on darwin +Type "help", "copyright", "credits" or "license" for more information. +>>> from mypypipackage import SayHello +>>> SayHello() +Hello from MyPyPiPackage +``` + +验证示例项目是否按上述要求工作后,接下来就可以创建包了. + +### Create a package[](#create-a-package "Permalink") + +在您的`MyPyPiPackage`目录中,我们需要创建一个`setup.py`文件. 运行以下命令: + +``` +touch setup.py +``` + +该文件包含有关我们软件包的所有信息. 有关此文件的更多信息,请参见[创建 setup.py](https://packaging.python.org/tutorials/packaging-projects/#creating-setup-py) . 对于本指南,我们不需要大量填写此文件,只需将以下内容添加到您的`setup.py` : + +``` +import setuptools + +setuptools.setup( + name="mypypipackage", + version="0.0.1", + author="Example Author", + author_email="author@example.com", + description="A small example package", + packages=setuptools.find_packages(), + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], + python_requires='>=3.6', +) +``` + +保存文件,然后执行如下设置: + +``` +python3 setup.py sdist bdist_wheel +``` + +如果成功,您应该能够在新创建的`dist`文件夹中看到输出. 跑: + +``` +ls dist +``` + +并确认您的输出与以下内容匹配: + +``` +mypypipackage-0.0.1-py3-none-any.whl mypypipackage-0.0.1.tar.gz +``` + +现在,我们的软件包已全部设置好,可以上传到**GitLab PyPi 软件包注册中心** . 在此之前,我们接下来需要设置身份验证. + +## Adding the GitLab PyPi Repository as a source[](#adding-the-gitlab-pypi-repository-as-a-source "Permalink") + +### Authenticating with a personal access token[](#authenticating-with-a-personal-access-token "Permalink") + +您将需要以下内容: + +* 个人访问令牌. 您可以生成范围设置为`api`的[个人访问令牌](../../../user/profile/personal_access_tokens.html) ,以进行存储库身份验证. +* 您的来源的合适名称. +* 您的项目 ID,可以在项目的主页上找到. + +编辑`~/.pypirc`文件并添加以下内容: + +``` +[distutils] +index-servers = + gitlab + +[gitlab] +repository = https://gitlab.com/api/v4/projects//packages/pypi +username = __token__ +password = +``` + +### Authenticating with a deploy token[](#authenticating-with-a-deploy-token "Permalink") + +您将需要以下内容: + +* 部署令牌. 您可以生成[令牌部署](./../../project/deploy_tokens/index.html)与`read_package_registry`和/或`write_package_registry`范围为存储库认证. +* 您的来源的合适名称. +* 您的项目 ID,可以在项目的主页上找到. + +编辑`~/.pypirc`文件并添加以下内容: + +``` +[distutils] +index-servers = + gitlab + +[gitlab] +repository = https://gitlab.com/api/v4/projects//packages/pypi +username = +password = +``` + +## Uploading packages[](#uploading-packages "Permalink") + +上载套件时,请注意: + +* 允许的最大大小为 50 MB. +* 如果您多次上传具有相同版本的相同程序包,则每次连续上传都将保存为单独的文件. 安装软件包时,GitLab 将提供最新文件. + +### Upload packages with Twine[](#upload-packages-with-twine "Permalink") + +如果您按照上面的指南进行操作,则`MyPyPiPackage`软件包应已准备好上载. 运行以下命令: + +``` +python3 -m twine upload --repository gitlab dist/* +``` + +如果成功,您应该看到以下内容: + +``` +Uploading distributions to https://gitlab.com/api/v4/projects//packages/pypi +Uploading mypypipackage-0.0.1-py3-none-any.whl +100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.58k/4.58k [00:00<00:00, 10.9kB/s] +Uploading mypypipackage-0.0.1.tar.gz +100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.24k/4.24k [00:00<00:00, 11.0kB/s] +``` + +这表明该软件包已成功上传. 然后,您可以导航到项目的" **程序包和注册表"**页面,并查看上载的程序包. + +如果您没有遵循上述指南,则需要确保已正确构建[软件包,并使用 setuptools 创建了 PyPi 软件包](https://packaging.python.org/tutorials/packaging-projects/) . + +然后,您可以使用以下命令上传软件包: + +``` +python -m twine upload --repository dist/ +``` + +Where: + +* `` is your package filename, ending in `.tar.gz` or `.whl`. +* ``是[安装过程中使用](#adding-the-gitlab-pypi-repository-as-a-source)的[源名称](#adding-the-gitlab-pypi-repository-as-a-source) . + +## Install packages[](#install-packages "Permalink") + +使用以下命令安装最新版本的软件包: + +``` +pip install --index-url https://__token__:@gitlab.com/api/v4/projects//packages/pypi/simple --no-deps +``` + +Where: + +* ``是软件包名称. +* ``是具有`read_api`范围的个人访问令牌. +* ``是项目 ID. + +如果您遵循上面的指南,并且想测试安装`MyPyPiPackage`软件包,则可以运行以下命令: + +``` +pip install mypypipackage --no-deps --index-url https://__token__:@gitlab.com/api/v4/projects//packages/pypi/simple +``` + +这将导致以下结果: + +``` +Looking in indexes: https://__token__:****@gitlab.com/api/v4/projects//packages/pypi/simple +Collecting mypypipackage + Downloading https://gitlab.com/api/v4/projects//packages/pypi/files/d53334205552a355fee8ca35a164512ef7334f33d309e60240d57073ee4386e6/mypypipackage-0.0.1-py3-none-any.whl (1.6 kB) +Installing collected packages: mypypipackage +Successfully installed mypypipackage-0.0.1 +``` \ No newline at end of file diff --git a/docs/284.md b/docs/284.md new file mode 100644 index 0000000000000000000000000000000000000000..6efa8bd35b64410590558f0e0dc2465e4d8d318f --- /dev/null +++ b/docs/284.md @@ -0,0 +1,595 @@ +# API Docs + +> 原文:[https://docs.gitlab.com/ee/api/README.html](https://docs.gitlab.com/ee/api/README.html) + +* [Available API resources](#available-api-resources) +* [SCIM](#scim-silver-only) +* [Road to GraphQL](#road-to-graphql) +* [Compatibility guidelines](#compatibility-guidelines) + * [Current status](#current-status) +* [Basic usage](#basic-usage) +* [Authentication](#authentication) + * [OAuth2 tokens](#oauth2-tokens) + * [Personal/project access tokens](#personalproject-access-tokens) + * [Session cookie](#session-cookie) + * [GitLab CI job token](#gitlab-ci-job-token) + * [Impersonation tokens](#impersonation-tokens) + * [Disable impersonation](#disable-impersonation) + * [Sudo](#sudo) +* [Status codes](#status-codes) +* [Pagination](#pagination) + * [Offset-based pagination](#offset-based-pagination) + * [Pagination Link header](#pagination-link-header) + * [Other pagination headers](#other-pagination-headers) + * [Keyset-based pagination](#keyset-based-pagination) +* [Path parameters](#path-parameters) +* [Namespaced path encoding](#namespaced-path-encoding) +* [File path, branches, and tags name encoding](#file-path-branches-and-tags-name-encoding) +* [Request Payload](#request-payload) +* [Encoding API parameters of `array` and `hash` types](#encoding-api-parameters-of-array-and-hash-types) + * [`array`](#array) + * [`hash`](#hash) + * [Array of hashes](#array-of-hashes) +* [`id` vs `iid`](#id-vs-iid) +* [Data validation and error reporting](#data-validation-and-error-reporting) +* [Unknown route](#unknown-route) +* [Encoding `+` in ISO 8601 dates](#encoding--in-iso-8601-dates) +* [Clients](#clients) +* [Rate limits](#rate-limits) + +# API Docs[](#api-docs "Permalink") + +通过简单而强大的 API 自动化 GitLab. + +主要的 GitLab API 是[REST](https://en.wikipedia.org/wiki/Representational_state_transfer) API. 因此,本节中的文档假定您具有 REST 概念的知识. + +## Available API resources[](#available-api-resources "Permalink") + +有关可用资源及其端点的列表,请参阅[API 资源](api_resources.html) . + +## SCIM[](#scim-silver-only "Permalink") + +[GitLab.com Silver 和更高版本](https://about.gitlab.com/pricing/)提供了[SCIM API](scim.html) , [该](https://tools.ietf.org/html/rfc7644) [API](scim.html)实现[RFC7644 协议](https://tools.ietf.org/html/rfc7644)并提供`/Users`端点. 基本网址为: `/api/scim/v2/groups/:group_path/Users/` . + +## Road to GraphQL[](#road-to-graphql "Permalink") + +[GitLab](graphql/index.html)中提供了[GraphQL](graphql/index.html) ,它将允许弃用控制器特定的端点. + +GraphQL 具有许多优点: + +1. 我们避免维护两个不同的 API. +2. API 的调用者只能请求他们需要的东西. +3. 默认情况下为版本. + +它将与当前的 v4 REST API 共存. 如果我们有 v5 API,则这应该是 GraphQL 之上的兼容性层. + +尽管 GraphQL 存在一些专利和许可问题,但通过 MIT 下的参考实现的重新许可以及 GraphQL 规范使用 OWF 许可证,这些问题已得到我们的满意解决. + +## Compatibility guidelines[](#compatibility-guidelines "Permalink") + +HTTP API 使用单个数字进行版本控制,当前数字为 4.此数字与[SemVer](https://semver.org/)描述的主要版本号[相同](https://semver.org/) . 这意味着向后不兼容的更改将需要更改此版本号. 但是,次要版本不明确. 这可以实现稳定的 API 端点,但也意味着可以将新功能以相同的版本号添加到 API. + +新功能和错误修复与新的 GitLab 一起发布,除附带的修补程序和安全版本外,还于每月 22 日发布. 向后不兼容的更改(例如,端点删除,参数删除等)以及整个 API 版本的删除与 GitLab 本身的主要版本一起进行. 两个版本之间的所有弃用和更改都应在文档中列出. 对于 v3 和 v4 之间的更改; 请阅读[v3 至 v4 文档](v3_to_v4.html) + +### Current status[](#current-status "Permalink") + +当前仅提供 API 版本 v4\. v3 版本已在[GitLab 11.0](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36819)中删除. + +## Basic usage[](#basic-usage "Permalink") + +API 请求应以`api`和 API 版本为前缀. API 版本在[`lib/api.rb`](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/api/api.rb)定义. 例如,v4 API 的根位于`/api/v4` . + +使用 cURL 的有效 API 请求的示例: + +``` +curl "https://gitlab.example.com/api/v4/projects" +``` + +该 API 使用 JSON 序列化数据. 您无需在 API URL 的末尾指定`.json` . + +## Authentication[](#authentication "Permalink") + +大多数 API 请求都需要身份验证,或者仅在不提供身份验证时才返回公共数据. 对于不需要的情况,将在文档中针对每个端点进行提及. 例如, [`/projects/:id`端点](projects.html#get-single-project) . + +使用 GitLab API 进行身份验证的方法有几种: + +1. [OAuth2 tokens](#oauth2-tokens) +2. [Personal access tokens](../user/profile/personal_access_tokens.html) +3. [Project access tokens](../user/project/settings/project_access_tokens.html) +4. [Session cookie](#session-cookie) +5. [GitLab CI/CD job token](#gitlab-ci-job-token) **(仅特定端点)** + +对于想要以特定用户身份向 API 进行身份验证的管理员,或者想要构建执行此操作的应用程序或脚本的管理员,可以使用以下两种方法: + +1. [Impersonation tokens](#impersonation-tokens) +2. [Sudo](#sudo) + +如果身份验证信息无效或被忽略,将返回一条错误消息,状态码为`401` : + +``` +{ "message": "401 Unauthorized" } +``` + +### OAuth2 tokens[](#oauth2-tokens "Permalink") + +您可以通过在`access_token`参数或`Authorization`标头中传递[OAuth2 令牌](oauth2.html)来对 API 进行身份验证. + +在参数中使用 OAuth2 令牌的示例: + +``` +curl "https://gitlab.example.com/api/v4/projects?access_token=OAUTH-TOKEN" +``` + +在标头中使用 OAuth2 令牌的示例: + +``` +curl --header "Authorization: Bearer OAUTH-TOKEN" "https://gitlab.example.com/api/v4/projects" +``` + +阅读有关[GitLab 作为 OAuth2 提供程序的](oauth2.html)更多信息. + +### Personal/project access tokens[](#personalproject-access-tokens "Permalink") + +Access tokens can be used to authenticate with the API by passing it in either the `private_token` parameter or the `Private-Token` header. + +在参数中使用个人/项目访问令牌的示例: + +``` +curl "https://gitlab.example.com/api/v4/projects?private_token=" +``` + +在标头中使用个人/项目访问令牌的示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/projects" +``` + +您还可以将个人/项目访问令牌与 OAuth 兼容标头一起使用: + +``` +curl --header "Authorization: Bearer " "https://gitlab.example.com/api/v4/projects" +``` + +### Session cookie[](#session-cookie "Permalink") + +登录主 GitLab 应用程序时,将设置`_gitlab_session` cookie. 如果存在,API 将使用此 cookie 进行身份验证,但是当前不支持使用 API​​生成新的会话 cookie. + +这种身份验证方法的主要用户是 GitLab 本身的 Web 前端,它可以将 API 用作经过身份验证的用户来获取其项目列表,例如,而无需显式传递访问令牌. + +### GitLab CI job token[](#gitlab-ci-job-token "Permalink") + +通过一些 API 端点,您可以使用[GitLab CI / CD 作业令牌](../user/project/new_ci_build_permissions_model.html#job-token)来对该 API 进行身份验证: + +* [Get job artifacts](jobs.html#get-job-artifacts) +* [Pipeline triggers](pipeline_triggers.html) +* [Release creation](releases/index.html#create-a-release) + +### Impersonation tokens[](#impersonation-tokens "Permalink") + +在 GitLab 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9099) . 需要管理员权限. + +模拟令牌是一种[个人访问令牌](../user/profile/personal_access_tokens.html) ,只能由管理员为特定用户创建. 如果您要构建以特定用户身份通过​​API 进行身份验证的应用程序或脚本,则它们非常适合. + +它们是直接使用用户密码或他们的个人访问令牌之一以及使用[Sudo](#sudo)功能的替代方法,因为用户(或管理员,对于 Sudo 而言)的密码/令牌可能是未知的,或者可能随时间变化. + +有关更多信息,请参考[用户 API](users.html#create-an-impersonation-token)文档. + +模拟令牌的使用与常规个人访问令牌完全一样,并且可以在`private_token`参数或`Private-Token`标头中传递. + +#### Disable impersonation[](#disable-impersonation "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/40385) . + +默认情况下,模拟是启用的. 禁用模拟: + +**对于所有安装** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitlab_rails['impersonation_enabled'] = false + ``` + +2. 保存文件并[重新配置](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure) GitLab,以使更改生效. + +要重新启用模拟,请删除此配置并重新配置 GitLab. + +**对于源安装** + +1. Edit `config/gitlab.yml`: + + ``` + gitlab: + impersonation_enabled: false + ``` + +2. 保存文件并[重新启动](../administration/restart_gitlab.html#installations-from-source) GitLab,以使更改生效. + +要重新启用模拟,请删除此配置并重新启动 GitLab. + +### Sudo[](#sudo "Permalink") + +**注意:**仅对[管理员](../user/permissions.html)可用. + +如果已通过具有`sudo`范围的 OAuth 或 Personal Access Token 作为管理员进行身份验证,则所有 API 请求都支持执行 API 调用,就好像您是另一个用户一样. + +您需要通过查询字符串或带有您要执行操作的用户的 ID /用户名的标头传递`sudo`参数. 如果作为标题传递,则标题名称必须为`Sudo` . + +**注意:**用户名不区分大小写. + +如果提供了非管理访问令牌,将返回错误消息,状态码为`403` : + +``` +{ "message": "403 Forbidden - Must be admin to use sudo" } +``` + +如果提供了没有`sudo`范围的访问令牌,则将返回错误消息,状态码为`403` : + +``` +{ "error": "insufficient_scope", "error_description": "The request requires higher privileges than provided by the access token.", "scope": "sudo" } +``` + +如果找不到 sudo 用户 ID 或用户名,将返回错误消息,状态码为`404` : + +``` +{ "message": "404 User with ID or username '123' Not Found" } +``` + +有效的 API 调用和使用 cURL 和 sudo request(提供用户名)的请求的示例: + +``` +GET /projects?private_token=&sudo=username +``` + +``` +curl --header "Private-Token: " --header "Sudo: username" "https://gitlab.example.com/api/v4/projects" +``` + +提供 ID 的有效 API 调用和使用 cURL 和 sudo request 的请求的示例: + +``` +GET /projects?private_token=&sudo=23 +``` + +``` +curl --header "Private-Token: " --header "Sudo: 23" "https://gitlab.example.com/api/v4/projects" +``` + +## Status codes[](#status-codes "Permalink") + +该 API 旨在根据上下文和操作返回不同的状态代码. 这样,如果请求导致错误,则调用者可以洞悉出了什么问题. + +下表概述了 API 函数的一般行为. + +| 请求类型 | Description | +| --- | --- | +| `GET` | 访问一个或多个资源,并将结果作为 JSON 返回. | +| `POST` | 如果成功创建资源,则返回`201 Created` ,然后将新创建的资源作为 JSON 返回. | +| `GET` / `PUT` | 如果成功访问或修改了资源,则返回`200 OK` . (修改后的)结果作为 JSON 返回. | +| `DELETE` | 如果资源已成功删除,则返回`204 No Content` . | + +下表显示了 API 请求的可能返回码. + +| 返回值 | Description | +| --- | --- | +| `200 OK` | `GET` , `PUT`或`DELETE`请求成功,资源本身作为 JSON 返回. | +| `204 No Content` | 服务器已成功满足请求,并且响应有效载荷主体中没有其他要发送的内容. | +| `201 Created` | `POST`请求成功,资源作为 JSON 返回. | +| `304 Not Modified` | 指示自上次请求以来尚未修改资源. | +| `400 Bad Request` | API 请求的必需属性丢失,例如,未提供问题标题. | +| `401 Unauthorized` | 用户未通过身份验证,有效的[用户令牌](#authentication)是必需的. | +| `403 Forbidden` | 不允许该请求,例如,不允许用户删除项目. | +| `404 Not Found` | 无法访问资源,例如,找不到资源的 ID. | +| `405 Method Not Allowed` | The request is not supported. | +| `409 Conflict` | 已经存在冲突的资源,例如,使用已经存在的名称创建项目. | +| `412` | 表示请求被拒绝. `If-Unmodified-Since`尝试删除资源时提供了`If-Unmodified-Since`标头,则可能会发生这种情况. | +| `422 Unprocessable` | 无法处理该实体. | +| `500 Server Error` | 在处理请求时,服务器端出了点问题. | + +## Pagination[](#pagination "Permalink") + +我们支持两种分页方法: + +* 基于偏移的分页. 这是默认方法,并且在所有端点上都可用. +* 基于键集的分页. 已添加到选定的端点,但会[逐步推出](https://gitlab.com/groups/gitlab-org/-/epics/2039) . + +对于大型集合,出于性能原因,我们建议键集分页(如果有)而不是偏移分页. + +### Offset-based pagination[](#offset-based-pagination "Permalink") + +有时,返回的结果将跨越许多页面. 列出资源时,可以传递以下参数: + +| Parameter | Description | +| --- | --- | +| `page` | 页码(默认: `1` ) | +| `per_page` | 每页要列出的项目数(默认: `20` ,最大: `100` ) | + +在下面的示例中,我们每页列出 50 个[名称空间](namespaces.html) . + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/namespaces?per_page=50" +``` + +#### Pagination Link header[](#pagination-link-header "Permalink") + +[链接头](https://www.w3.org/wiki/LinkHeader)随每个响应一起发送回去. 它们的`rel`设置为 prev / next / first / last 并包含相关的 URL. 请使用这些链接,而不是生成自己的 URL. + +在下面的卷曲的例子,我们限制输出到每页 3 项( `per_page=3` ),我们要求的第二页( `page=2`的) [评论](notes.html)与 ID 问题的`8`属于与 ID 项目`8` : + +``` +curl --head --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/8/issues/8/notes?per_page=3&page=2" +``` + +响应将是: + +``` +HTTP/1.1 200 OK +Cache-Control: no-cache +Content-Length: 1103 +Content-Type: application/json +Date: Mon, 18 Jan 2016 09:43:18 GMT +Link: ; rel="prev", ; rel="next", ; rel="first", ; rel="last" +Status: 200 OK +Vary: Origin +X-Next-Page: 3 +X-Page: 2 +X-Per-Page: 3 +X-Prev-Page: 1 +X-Request-Id: 732ad4ee-9870-4866-a199-a9db0cde3c86 +X-Runtime: 0.108688 +X-Total: 8 +X-Total-Pages: 3 +``` + +#### Other pagination headers[](#other-pagination-headers "Permalink") + +其他分页标题也会发送回. + +| Header | Description | +| --- | --- | +| `X-Total` | 项目总数 | +| `X-Total-Pages` | 总页数 | +| `X-Per-Page` | 每页的项目数 | +| `X-Page` | 当前页面的索引(从 1 开始) | +| `X-Next-Page` | 下一页的索引 | +| `X-Prev-Page` | 前一页的索引 | + +**注意:**由于性能原因,自[GitLab 11.8 起](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23931)并**在`api_kaminari_count_with_limit` [功能标志](../development/feature_flags/index.html)后面** ,如果资源数量大于 10,000,则`X-Total`和`X-Total-Pages`标头以及`rel="last"` `Link`将不存在响应头. + +### Keyset-based pagination[](#keyset-based-pagination "Permalink") + +键集分页可以更有效地检索页面,并且与基于偏移的分页相比,运行时与集合的大小无关. + +此方法由以下参数控制: + +| Parameter | Description | +| --- | --- | +| `pagination` | `keyset` (启用键集分页) | +| `per_page` | 每页要列出的项目数(默认: `20` ,最大: `100` ) | + +在下面的示例中,我们每页列出 50 [个项目](projects.html) ,并按`id`升序排列. + +``` +curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects?pagination=keyset&per_page=50&order_by=id&sort=asc" +``` + +响应头包括指向下一页的链接. 例如: + +``` +HTTP/1.1 200 OK +... +Links: ; rel="next" +Link: ; rel="next" +Status: 200 OK +... +``` + +**弃用:** `Links`标题将在 GitLab 14.0 中删除,以符合[W3C `Link`规范](https://www.w3.org/wiki/LinkHeader) + +指向下一页的链接包含一个附加过滤器`id_after=42` ,该过滤器不包括我们已经检索到的记录. 请注意,过滤器的类型取决于所使用的`order_by`选项,我们可能有多个过滤器. + +当到达集合的末尾并且没有其他要检索的记录时,将没有`Links`头,并且结果数组为空. + +我们建议仅使用给定的链接来检索下一页,而不要构建自己的 URL. 除了显示的标题外,我们不公开其他分页标题. + +仅针对所选资源和订购选项支持基于键集的分页: + +| Resource | Order | +| --- | --- | +| [Projects](projects.html) | `order_by=id` only | + +## Path parameters[](#path-parameters "Permalink") + +如果端点具有路径参数,则文档将在它们前面加上冒号. + +例如: + +``` +DELETE /projects/:id/share/:group_id +``` + +`:id`路径参数需要替换为项目 ID,而`:group_id`需要替换为组的 ID. 冒号`:`不应包含在内. + +因此,对 ID 为`5` ,组 ID 为`17`的项目的 cURL 调用为: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/share/17" +``` + +**注意:**必须遵循要求进行 URL 编码的路径参数. 如果不是,它将与 API 端点不匹配并以 404 进行响应.如果 API 前面有某些内容(例如 Apache),请确保它不会对 URL 编码的路径参数进行解码. + +## Namespaced path encoding[](#namespaced-path-encoding "Permalink") + +如果使用命名空间的 API 调用,请确保`NAMESPACE/PROJECT_PATH`是 URL 编码的. + +例如, `/`由`/`表示: + +``` +GET /api/v4/projects/diaspora%2Fdiaspora +``` + +**注意:**项目的**路径**不必与**名称**相同. 可以在项目的 URL 或项目设置中的**常规>高级>更改路径**下找到项目的**路径** . + +## File path, branches, and tags name encoding[](#file-path-branches-and-tags-name-encoding "Permalink") + +如果文件路径,分支或标记包含`/` ,请确保其经过 URL 编码. + +例如, `/`由`/`表示: + +``` +GET /api/v4/projects/1/repository/files/src%2FREADME.md?ref=master +GET /api/v4/projects/1/branches/my%2Fbranch/commits +GET /api/v4/projects/1/repository/tags/my%2Ftag +``` + +## Request Payload[](#request-payload "Permalink") + +API 请求可以使用作为[查询字符串](https://en.wikipedia.org/wiki/Query_string)或[有效载荷主体](https://tools.ietf.org/html/draft-ietf-httpbis-p3-payload-14#section-3.2)发送的参数. GET 请求通常发送查询字符串,而 PUT / POST 请求通常发送有效内容正文: + +* 请求参数: + + ``` + curl --request POST "https://gitlab/api/v4/projects?name=&description=" + ``` + +* 请求有效载荷(JSON): + + ``` + curl --request POST --header "Content-Type: application/json" --data '{"name":"", "description":"" \ +-d "import_sources[]=github" \ +-d "import_sources[]=bitbucket" \ +https://gitlab.example.com/api/v4/some_endpoint +``` + +### `hash`[](#hash "Permalink") + +`override_params`是`hash`类型的参数: + +``` +curl --request POST --header "PRIVATE-TOKEN: " \ +--form "namespace=email" \ +--form "path=impapi" \ +--form "file=@/path/to/somefile.txt" +--form "override_params[visibility]=private" \ +--form "override_params[some_other_param]=some_value" \ +https://gitlab.example.com/api/v4/projects/import +``` + +### Array of hashes[](#array-of-hashes "Permalink") + +`variables`是包含哈希键/值对`[{ 'key' => 'UPLOAD_TO_S3', 'value' => 'true' }]` `array`类型的参数: + +``` +curl --globoff --request POST --header "PRIVATE-TOKEN: " \ +"https://gitlab.example.com/api/v4/projects/169/pipeline?ref=master&variables[][key]=VAR1&variables[][value]=hello&variables[][key]=VAR2&variables[][value]=world" + +curl --request POST --header "PRIVATE-TOKEN: " \ +--header "Content-Type: application/json" \ +--data '{ "ref": "master", "variables": [ {"key": "VAR1", "value": "hello"}, {"key": "VAR2", "value": "world"} ] }' \ +"https://gitlab.example.com/api/v4/projects/169/pipeline" +``` + +## `id` vs `iid`[](#id-vs-iid "Permalink") + +Some resources have two similarly-named fields. For example, [issues](issues.html), [merge requests](merge_requests.html), and [project milestones](merge_requests.html). The fields are: + +* `id` :在所有项目中唯一的 ID. +* `iid` :在单个项目范围内唯一的附加内部 ID. + +**注意:** `iid`显示在 Web UI 中. + +如果资源具有`iid`字段和`id`字段,则通常使用`iid`字段代替`id`来获取资源. + +例如,假设一个`id: 42`的项目有一个`id: 46`和`iid: 5` . 在这种情况下: + +* 检索问题的有效 API 调用是`GET /projects/42/issues/5` +* 检索问题的无效 API 调用是`GET /projects/42/issues/46` . + +**注意:**并非所有具有`iid`字段的资源都由`iid`获取. 有关使用哪个字段的指导,请参阅特定资源的文档. + +## Data validation and error reporting[](#data-validation-and-error-reporting "Permalink") + +使用 API​​时,您可能会遇到验证错误,在这种情况下,API 会以 HTTP `400`状态进行回答. + +这种错误在两种情况下出现: + +* API 请求的必需属性丢失,例如,未给出问题标题 +* 属性未通过验证,例如,用户简历太长 + +当缺少属性时,您将获得类似以下内容的信息: + +``` +HTTP/1.1 400 Bad Request +Content-Type: application/json +{ + "message":"400 (Bad request) \"title\" not given" +} +``` + +发生验证错误时,错误消息将有所不同. 它们将包含验证错误的所有详细信息: + +``` +HTTP/1.1 400 Bad Request +Content-Type: application/json +{ + "message": { + "bio": [ + "is too long (maximum is 255 characters)" + ] + } +} +``` + +这使错误消息更加机器可读. 格式可以描述如下: + +``` +{ "message": { "": [ "", "", ... ], "": { "": [ "", "", ... ], } } } +``` + +## Unknown route[](#unknown-route "Permalink") + +当您尝试访问不存在的 API URL 时,您将收到 404 Not Found. + +``` +HTTP/1.1 404 Not Found +Content-Type: application/json +{ + "error": "404 Not Found" +} +``` + +## Encoding `+` in ISO 8601 dates[](#encoding--in-iso-8601-dates "Permalink") + +如果需要在查询参数中包含`+` ,则由于[W3 建议](http://www.w3.org/Addressing/URL/4_URI_Recommentations.html)会将`+`解释为空格,因此可能需要使用`+`来代替. 例如,在一个 ISO 8601 日期中,您可能希望以"山区标准时间"传递时间,例如: + +``` +2017-10-17T23:11:13.000+05:30 +``` + +The correct encoding for the query parameter would be: + +``` +2017-10-17T23:11:13.000%2B05:30 +``` + +## Clients[](#clients "Permalink") + +大多数流行的编程语言都有许多非官方的 GitLab API 客户端. 访问[GitLab 网站](https://about.gitlab.com/partners/#api-clients)以获取完整列表. + +## Rate limits[](#rate-limits "Permalink") + +有关速率限制设置的管理员文档,请参阅[速率限制](../security/rate_limits.html) . 要查找 GitLab.com 专门使用的设置,请参阅[GitLab.com 特定的速率限制](../user/gitlab_com/index.html#gitlabcom-specific-rate-limits) . \ No newline at end of file diff --git a/docs/285.md b/docs/285.md new file mode 100644 index 0000000000000000000000000000000000000000..b94d28780f2bbbaf8f1568df77ee53e85e63930a --- /dev/null +++ b/docs/285.md @@ -0,0 +1,173 @@ +# API resources + +> 原文:[https://docs.gitlab.com/ee/api/api_resources.html](https://docs.gitlab.com/ee/api/api_resources.html) + +* [Project resources](#project-resources) +* [Group resources](#group-resources) +* [Standalone resources](#standalone-resources) +* [Templates API resources](#templates-api-resources) + +# API resources[](#api-resources "Permalink") + +可在以下上下文中对[GitLab API 的](README.html)可用资源进行分组: + +* [Projects](#project-resources). +* [Groups](#group-resources). +* [Standalone](#standalone-resources). + +也可以看看: + +* [V3 to V4](v3_to_v4.html). +* Adding [deploy keys for multiple projects](deploy_key_multiple_projects.html). +* [API Resources for various templates](#templates-api-resources). + +## Project resources[](#project-resources "Permalink") + +在项目上下文中可以使用以下 API 资源: + +| Resource | 可用端点 | +| --- | --- | +| [Access requests](access_requests.html) | `/projects/:id/access_requests` (也可用于组) | +| [Award emoji](award_emoji.html) | `/projects/:id/issues/.../award_emoji`, `/projects/:id/merge_requests/.../award_emoji`, `/projects/:id/snippets/.../award_emoji` | +| [Branches](branches.html) | `/projects/:id/repository/branches/`, `/projects/:id/repository/merged_branches` | +| [Commits](commits.html) | `/projects/:id/repository/commits`, `/projects/:id/statuses` | +| [Container Registry](container_registry.html) | `/projects/:id/registry/repositories` | +| [Custom attributes](custom_attributes.html) | `/projects/:id/custom_attributes` (也适用于组和用户) | +| [Dependencies](dependencies.html) | `/projects/:id/dependencies` | +| [Deploy keys](deploy_keys.html) | `/projects/:id/deploy_keys` (也可以独立使用) | +| [Freeze Periods](freeze_periods.html) | `/projects/:id/freeze_periods` | +| [Deployments](deployments.html) | `/projects/:id/deployments` | +| [讨论](discussions.html) (主题注释) | `/projects/:id/issues/.../discussions` , `/projects/:id/snippets/.../discussions` , `/projects/:id/merge_requests/.../discussions` , `/projects/:id/commits/.../discussions` (也适用于团体) | +| [Environments](environments.html) | `/projects/:id/environments` | +| [Error Tracking](error_tracking.html) | `/projects/:id/error_tracking/settings` | +| [Events](events.html) | `/projects/:id/events` (也可用于用户和独立用户) | +| [Feature Flags](feature_flags.html) | `/projects/:id/feature_flags` | +| [Feature Flag User Lists](feature_flag_user_lists.html) | `/projects/:id/feature_flags_user_lists` | +| [Issues](issues.html) | `/projects/:id/issues` (也可用于团体和独立团体) | +| [Issues Statistics](issues_statistics.html) | `/projects/:id/issues_statistics` (也适用于组和独立用户) | +| [Issue boards](boards.html) | `/projects/:id/boards` | +| [Issue links](issue_links.html) | `/projects/:id/issues/.../links` | +| [Jobs](jobs.html) | `/projects/:id/jobs`, `/projects/:id/pipelines/.../jobs` | +| [Labels](labels.html) | `/projects/:id/labels` | +| [Managed licenses](managed_licenses.html) | `/projects/:id/managed_licenses` | +| [Members](members.html) | `/projects/:id/members` (也可用于组) | +| [Merge request approvals](merge_request_approvals.html) | `/projects/:id/approvals`, `/projects/:id/merge_requests/.../approvals` | +| [Merge requests](merge_requests.html) | `/projects/:id/merge_requests` (也可用于组和独立) | +| [Notes](notes.html) (comments) | `/projects/:id/issues/.../notes` : `/projects/:id/snippets/.../notes` / `/projects/:id/merge_requests/.../notes` `/projects/:id/issues/.../notes` ,/ `/projects/:id/snippets/.../notes` : `/projects/:id/merge_requests/.../notes` `/projects/:id/issues/.../notes` ,/ `/projects/:id/snippets/.../notes` : `/projects/:id/merge_requests/.../notes` (也可用于团体) | +| [Notification settings](notification_settings.html) | `/projects/:id/notification_settings` (也可用于组和独立) | +| [Packages](packages.html) | `/projects/:id/packages` | +| [Pages domains](pages_domains.html) | `/projects/:id/pages` (也可以独立使用) | +| [Pipelines](pipelines.html) | `/projects/:id/pipelines` | +| [Pipeline schedules](pipeline_schedules.html) | `/projects/:id/pipeline_schedules` | +| [Pipeline triggers](pipeline_triggers.html) | `/projects/:id/triggers` | +| [项目](projects.html)包括设置 Webhooks | `/projects` , `/projects/:id/hooks` (也可供用户使用) | +| [Project badges](project_badges.html) | `/projects/:id/badges` | +| [Project clusters](project_clusters.html) | `/projects/:id/clusters` | +| [Project-level variables](project_level_variables.html) | `/projects/:id/variables` | +| [Project import/export](project_import_export.html) | `/projects/:id/export`, `/projects/import`, `/projects/:id/import` | +| [Project milestones](milestones.html) | `/projects/:id/milestones` | +| [Project snippets](project_snippets.html) | `/projects/:id/snippets` | +| [Project templates](project_templates.html) | `/projects/:id/templates` | +| [Protected environments](protected_environments.html) | `/projects/:id/protected_environments` | +| [Protected branches](protected_branches.html) | `/projects/:id/protected_branches` | +| [Protected tags](protected_tags.html) | `/projects/:id/protected_tags` | +| [Releases](releases/index.html) | `/projects/:id/releases` | +| [Release links](releases/links.html) | `/projects/:id/releases/.../assets/links` | +| [Remote mirrors](remote_mirrors.html) | `/projects/:id/remote_mirrors` | +| [Repositories](repositories.html) | `/projects/:id/repository` | +| [Repository files](repository_files.html) | `/projects/:id/repository/files` | +| [Repository submodules](repository_submodules.html) | `/projects/:id/repository/submodules` | +| [Resource label events](resource_label_events.html) | `/projects/:id/issues/.../resource_label_events` : `/projects/:id/merge_requests/.../resource_label_events` `/projects/:id/issues/.../resource_label_events` ,/ `/projects/:id/merge_requests/.../resource_label_events` : `/projects/:id/issues/.../resource_label_events` / `/projects/:id/merge_requests/.../resource_label_events` (也可用于团体) | +| [Runners](runners.html) | `/projects/:id/runners` (也可以独立使用) | +| [Search](search.html) | `/projects/:id/search` (also available for groups and standalone) | +| [Services](services.html) | `/projects/:id/services` | +| [Tags](tags.html) | `/projects/:id/repository/tags` | +| [User-starred metrics dashboards](metrics_user_starred_dashboards.html) | `/projects/:id/metrics/user_starred_dashboards` | +| [Visual Review discussions](visual_review_discussions.html) | `/projects/:id/merge_requests/:merge_request_id/visual_review_discussions` | +| [Vulnerabilities](vulnerabilities.html) | `/vulnerabilities/:id` | +| [Vulnerability exports](vulnerability_exports.html) | `/projects/:id/vulnerability_exports` | +| [Project vulnerabilities](project_vulnerabilities.html) | `/projects/:id/vulnerabilities` | +| [Vulnerability findings](vulnerability_findings.html) | `/projects/:id/vulnerability_findings` | +| [Wikis](wikis.html) | `/projects/:id/wikis` | + +## Group resources[](#group-resources "Permalink") + +组上下文中提供了以下 API 资源: + +| Resource | 可用端点 | +| --- | --- | +| [Access requests](access_requests.html) | `/groups/:id/access_requests/` (也可用于项目) | +| [Custom attributes](custom_attributes.html) | `/groups/:id/custom_attributes` (也适用于项目和用户) | +| [讨论](discussions.html) (主题注释) | `/groups/:id/epics/.../discussions` (也可用于项目) | +| [Epic issues](epic_issues.html) | `/groups/:id/epics/.../issues` | +| [Epic links](epic_links.html) | `/groups/:id/epics/.../epics` | +| [Epics](epics.html) | `/groups/:id/epics` | +| [Groups](groups.html) | `/groups`, `/groups/.../subgroups` | +| [Group badges](group_badges.html) | `/groups/:id/badges` | +| [Group issue boards](group_boards.html) | `/groups/:id/boards` | +| [Group labels](group_labels.html) | `/groups/:id/labels` | +| [Group-level variables](group_level_variables.html) | `/groups/:id/variables` | +| [Group milestones](group_milestones.html) | `/groups/:id/milestones` | +| [Issues](issues.html) | `/groups/:id/issues` (也可用于项目和独立版本) | +| [Issues Statistics](issues_statistics.html) | `/groups/:id/issues_statistics` (也可用于项目和独立版本) | +| [Members](members.html) | `/groups/:id/members` (也可用于项目) | +| [Merge requests](merge_requests.html) | `/groups/:id/merge_requests` (也可用于项目和独立版本) | +| [Notes](notes.html) (comments) | `/groups/:id/epics/.../notes` (也适用于项目) | +| [Notification settings](notification_settings.html) | `/groups/:id/notification_settings` (也可用于项目和独立版本) | +| [Resource label events](resource_label_events.html) | `/groups/:id/epics/.../resource_label_events` (也可用于项目) | +| [Search](search.html) | `/groups/:id/search` (也可用于项目和独立版本) | + +## Standalone resources[](#standalone-resources "Permalink") + +在项目和组上下文(包括`/users` )之外可以使用以下 API 资源: + +| Resource | 可用端点 | +| --- | --- | +| [Instance-level CI/CD variables](instance_level_ci_variables.html) | `/admin/ci/variables` | +| [Admin Sidekiq queues](admin_sidekiq_queues.html) | `/admin/sidekiq/queues/:queue_name` | +| [Appearance](appearance.html) | `/application/appearance` | +| [Applications](applications.html) | `/applications` | +| [Audit Events](audit_events.html) | `/audit_events` | +| [Avatar](avatar.html) | `/avatar` | +| [Broadcast messages](broadcast_messages.html) | `/broadcast_messages` | +| [Code snippets](snippets.html) | `/snippets` | +| [Custom attributes](custom_attributes.html) | `/users/:id/custom_attributes` (也可用于组和项目) | +| [Deploy keys](deploy_keys.html) | `/deploy_keys` (也可用于项目) | +| [Events](events.html) | `/events` , `/users/:id/events` (也可用于项目) | +| [Feature flags](features.html) | `/features` | +| [Geo Nodes](geo_nodes.html) | `/geo_nodes` | +| [Group Activity Analytics](group_activity_analytics.html) | `/analytics/group_activity/{issues_count | merge_requests_count | new_members_count }` | +| [Import repository from GitHub](import.html) | `/import/github` | +| [Instance clusters](instance_clusters.html) | `/admin/clusters` | +| [Issues](issues.html) | `/issues` (也可用于小组和项目) | +| [Issues Statistics](issues_statistics.html) | `/issues_statistics` (也适用于小组和项目) | +| [Keys](keys.html) | `/keys` | +| [License](license.html) | `/license` | +| [Markdown](markdown.html) | `/markdown` | +| [Merge requests](merge_requests.html) | `/merge_requests` (也适用于小组和项目) | +| [Metrics dashboard annotations](metrics_dashboard_annotations.html) | `/environments/:id/metrics_dashboard/annotations`, `/clusters/:id/metrics_dashboard/annotations` | +| [Namespaces](namespaces.html) | `/namespaces` | +| [Notification settings](notification_settings.html) | `/notification_settings` (也适用于小组和项目) | +| [Pages domains](pages_domains.html) | `/pages/domains` (也可用于项目) | +| [Projects](projects.html) | `/users/:id/projects` (也可用于项目) | +| [Project repository storage moves](project_repository_storage_moves.html) | `/project_repository_storage_moves` | +| [Runners](runners.html) | `/runners` (也可用于项目) | +| [Search](search.html) | `/search` (也可用于小组和项目) | +| [Settings](settings.html) | `/application/settings` | +| [Statistics](statistics.html) | `/application/statistics` | +| [Sidekiq metrics](sidekiq_metrics.html) | `/sidekiq` | +| [Suggestions](suggestions.html) | `/suggestions` | +| [System hooks](system_hooks.html) | `/hooks` | +| [Todos](todos.html) | `/todos` | +| [Users](users.html) | `/users` | +| [Validate `.gitlab-ci.yml` file](lint.html) | `/lint` | +| [Version](version.html) | `/version` | + +## Templates API resources[](#templates-api-resources "Permalink") + +端点可用于: + +* [Dockerfile templates](templates/dockerfiles.html). +* [`.gitignore` templates](templates/gitignores.html). +* [GitLab CI/CD YAML templates](templates/gitlab_ci_ymls.html). +* [Open source license templates](templates/licenses.html). \ No newline at end of file diff --git a/docs/286.md b/docs/286.md new file mode 100644 index 0000000000000000000000000000000000000000..8531818e2241a623599729145bd3f5424e79ed0d --- /dev/null +++ b/docs/286.md @@ -0,0 +1,54 @@ +# `.gitignore` API + +> 原文:[https://docs.gitlab.com/ee/api/templates/gitignores.html](https://docs.gitlab.com/ee/api/templates/gitignores.html) + +* [List `.gitignore` templates](#list-gitignore-templates) +* [Single `.gitignore` template](#single-gitignore-template) + +# `.gitignore` API[](#gitignore-api "Permalink") + +在 GitLab 中,有一个`.gitignore`可用的 API 端点. 有关`gitignore`更多信息,请参见[Git 文档](https://git-scm.com/docs/gitignore) . + +## List `.gitignore` templates[](#list-gitignore-templates "Permalink") + +获取所有`.gitignore`模板. + +``` +GET /templates/gitignores +``` + +请求示例: + +``` +curl https://gitlab.example.com/api/v4/templates/gitignores +``` + +响应示例: + +``` +[ { "key": "Actionscript", "name": "Actionscript" }, { "key": "Ada", "name": "Ada" }, { "key": "Agda", "name": "Agda" }, { "key": "Android", "name": "Android" }, { "key": "AppEngine", "name": "AppEngine" }, { "key": "AppceleratorTitanium", "name": "AppceleratorTitanium" }, { "key": "ArchLinuxPackages", "name": "ArchLinuxPackages" }, { "key": "Autotools", "name": "Autotools" }, { "key": "C", "name": "C" }, { "key": "C++", "name": "C++" }, { "key": "CFWheels", "name": "CFWheels" }, { "key": "CMake", "name": "CMake" }, { "key": "CUDA", "name": "CUDA" }, { "key": "CakePHP", "name": "CakePHP" }, { "key": "ChefCookbook", "name": "ChefCookbook" }, { "key": "Clojure", "name": "Clojure" }, { "key": "CodeIgniter", "name": "CodeIgniter" }, { "key": "CommonLisp", "name": "CommonLisp" }, { "key": "Composer", "name": "Composer" }, { "key": "Concrete5", "name": "Concrete5" } ] +``` + +## Single `.gitignore` template[](#single-gitignore-template "Permalink") + +获取单个`.gitignore`模板. + +``` +GET /templates/gitignores/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `key` | string | yes | `.gitignore`模板的键 | + +请求示例: + +``` +curl https://gitlab.example.com/api/v4/templates/gitignores/Ruby +``` + +响应示例: + +``` +{ "name": "Ruby", "content": "*.gem\n*.rbc\n/.config\n/coverage/\n/InstalledFiles\n/pkg/\n/spec/reports/\n/spec/examples.txt\n/test/tmp/\n/test/version_tmp/\n/tmp/\n\n# Used by dotenv library to load environment variables.\n# .env\n\n## Specific to RubyMotion:\n.dat*\n.repl_history\nbuild/\n*.bridgesupport\nbuild-iPhoneOS/\nbuild-iPhoneSimulator/\n\n## Specific to RubyMotion (use of CocoaPods):\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control\n#\n# vendor/Pods/\n\n## Documentation cache and generated files:\n/.yardoc/\n/_yardoc/\n/doc/\n/rdoc/\n\n## Environment normalization:\n/.bundle/\n/vendor/bundle\n/lib/bundler/man/\n\n# for a library or gem, you might want to ignore these files since the code is\n# intended to run in multiple environments; otherwise, check them in:\n# Gemfile.lock\n# .ruby-version\n# .ruby-gemset\n\n# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:\n.rvmrc\n" } +``` \ No newline at end of file diff --git a/docs/287.md b/docs/287.md new file mode 100644 index 0000000000000000000000000000000000000000..439b7d89f1b23d96123835794101331d207c31bd --- /dev/null +++ b/docs/287.md @@ -0,0 +1,54 @@ +# GitLab CI YMLs API + +> 原文:[https://docs.gitlab.com/ee/api/templates/gitlab_ci_ymls.html](https://docs.gitlab.com/ee/api/templates/gitlab_ci_ymls.html) + +* [List GitLab CI YML templates](#list-gitlab-ci-yml-templates) +* [Single GitLab CI YML template](#single-gitlab-ci-yml-template) + +# GitLab CI YMLs API[](#gitlab-ci-ymls-api "Permalink") + +在 GitLab 中,有一个 API 端点可用于 GitLab CI / CD YML. 有关 GitLab 中 CI / CD 管道配置的更多信息,请参阅[配置参考文档](../../ci/yaml/README.html) . + +## List GitLab CI YML templates[](#list-gitlab-ci-yml-templates "Permalink") + +获取所有的 GitLab CI / CD YML 模板. + +``` +GET /templates/gitlab_ci_ymls +``` + +请求示例: + +``` +curl https://gitlab.example.com/api/v4/templates/gitlab_ci_ymls +``` + +响应示例: + +``` +[ { "key": "Android", "name": "Android" }, { "key": "Android-Fastlane", "name": "Android-Fastlane" }, { "key": "Auto-DevOps", "name": "Auto-DevOps" }, { "key": "Bash", "name": "Bash" }, { "key": "C++", "name": "C++" }, { "key": "Chef", "name": "Chef" }, { "key": "Clojure", "name": "Clojure" }, { "key": "Code-Quality", "name": "Code-Quality" }, { "key": "Crystal", "name": "Crystal" }, { "key": "Django", "name": "Django" }, { "key": "Docker", "name": "Docker" }, { "key": "Elixir", "name": "Elixir" }, { "key": "Go", "name": "Go" }, { "key": "Gradle", "name": "Gradle" }, { "key": "Grails", "name": "Grails" }, { "key": "Julia", "name": "Julia" }, { "key": "LaTeX", "name": "LaTeX" }, { "key": "Laravel", "name": "Laravel" }, { "key": "Maven", "name": "Maven" }, { "key": "Mono", "name": "Mono" } ] +``` + +## Single GitLab CI YML template[](#single-gitlab-ci-yml-template "Permalink") + +获取单个 GitLab CI / CD YML 模板. + +``` +GET /templates/gitlab_ci_ymls/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `key` | string | yes | GitLab CI / CD YML 模板的密钥 | + +请求示例: + +``` +curl https://gitlab.example.com/api/v4/templates/gitlab_ci_ymls/Ruby +``` + +响应示例: + +``` +{ "name": "Ruby", "content": "# This file is a template, and might need editing before it works on your project.\n# Official language image. Look for the different tagged releases at:\n# https://hub.docker.com/r/library/ruby/tags/\nimage: \"ruby:2.5\"\n\n# Pick zero or more services to be used on all builds.\n# Only needed when using a docker container to run your tests in.\n# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service\nservices:\n - mysql:latest\n - redis:latest\n - postgres:latest\n\nvariables:\n POSTGRES_DB: database_name\n\n# Cache gems in between builds\ncache:\n paths:\n - vendor/ruby\n\n# This is a basic example for a gem or script which doesn't use\n# services such as redis or postgres\nbefore_script:\n - ruby -v # Print out ruby version for debugging\n # Uncomment next line if your rails app needs a JS runtime:\n # - apt-get update -q && apt-get install nodejs -yqq\n - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby\n\n# Optional - Delete if not using `rubocop`\nrubocop:\n script:\n - rubocop\n\nrspec:\n script:\n - rspec spec\n\nrails:\n variables:\n DATABASE_URL: \"postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB\"\n script:\n - rails db:migrate\n - rails db:seed\n - rails test\n\n# This deploy job uses a simple deploy flow to Heroku, other providers, e.g. AWS Elastic Beanstalk\n# are supported too: https://github.com/travis-ci/dpl\ndeploy:\n type: deploy\n environment: production\n script:\n - gem install dpl\n - dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_PRODUCTION_KEY\n" } +``` \ No newline at end of file diff --git a/docs/288.md b/docs/288.md new file mode 100644 index 0000000000000000000000000000000000000000..95389b2396f0f3bc5eddf52b44ad98fded6f8318 --- /dev/null +++ b/docs/288.md @@ -0,0 +1,125 @@ +# Group and project access requests API + +> 原文:[https://docs.gitlab.com/ee/api/access_requests.html](https://docs.gitlab.com/ee/api/access_requests.html) + +* [Valid access levels](#valid-access-levels) +* [List access requests for a group or project](#list-access-requests-for-a-group-or-project) +* [Request access to a group or project](#request-access-to-a-group-or-project) +* [Approve an access request](#approve-an-access-request) +* [Deny an access request](#deny-an-access-request) + +# Group and project access requests API[](#group-and-project-access-requests-api "Permalink") + +**注意:**此功能是在 GitLab 8.11 中引入的 + +## Valid access levels[](#valid-access-levels "Permalink") + +访问级别在`Gitlab::Access`模块中定义. 当前,这些级别被认可: + +* 无法访问( `0` ) +* 宾客( `10` ) +* 记者( `20` ) +* 显影剂( `30` ) +* 养护者( `40` ) +* 所有者( `50` )-仅对组有效 + +## List access requests for a group or project[](#list-access-requests-for-a-group-or-project "Permalink") + +获取认证用户可见的访问请求列表. + +``` +GET /groups/:id/access_requests +GET /projects/:id/access_requests +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/access_requests" +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/access_requests" +``` + +响应示例: + +``` +[ { "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "created_at": "2012-10-22T14:13:35Z", "requested_at": "2012-10-22T14:13:35Z" }, { "id": 2, "username": "john_doe", "name": "John Doe", "state": "active", "created_at": "2012-10-22T14:13:35Z", "requested_at": "2012-10-22T14:13:35Z" } ] +``` + +## Request access to a group or project[](#request-access-to-a-group-or-project "Permalink") + +请求已验证用户访问组或项目. + +``` +POST /groups/:id/access_requests +POST /projects/:id/access_requests +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/access_requests" +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/access_requests" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "created_at": "2012-10-22T14:13:35Z", "requested_at": "2012-10-22T14:13:35Z" } +``` + +## Approve an access request[](#approve-an-access-request "Permalink") + +批准给定用户的访问请求. + +``` +PUT /groups/:id/access_requests/:user_id/approve +PUT /projects/:id/access_requests/:user_id/approve +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 访问请求者的用户标识 | +| `access_level` | integer | no | 有效的访问级别(默认值: `30` ,开发人员访问级别) | + +请求示例: + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/access_requests/:user_id/approve?access_level=20" +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/access_requests/:user_id/approve?access_level=20" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "created_at": "2012-10-22T14:13:35Z", "access_level": 20 } +``` + +## Deny an access request[](#deny-an-access-request "Permalink") + +拒绝给定用户的访问请求. + +``` +DELETE /groups/:id/access_requests/:user_id +DELETE /projects/:id/access_requests/:user_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 访问请求者的用户标识 | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/access_requests/:user_id" +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/access_requests/:user_id" +``` \ No newline at end of file diff --git a/docs/289.md b/docs/289.md new file mode 100644 index 0000000000000000000000000000000000000000..43765222275a58f465f5598f16c89b461fa35c0c --- /dev/null +++ b/docs/289.md @@ -0,0 +1,63 @@ +# Appearance API + +> 原文:[https://docs.gitlab.com/ee/api/appearance.html](https://docs.gitlab.com/ee/api/appearance.html) + +* [Get current appearance configuration](#get-current-appearance-configuration) +* [Change appearance configuration](#change-appearance-configuration) + +# Appearance API[](#appearance-api-core-only "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/16647) . + +Appearance API 使您可以像在`/admin/appearance`使用 GitLab UI 一样维护 GitLab 的`/admin/appearance` . 该 API 需要管理员权限. + +## Get current appearance configuration[](#get-current-appearance-configuration "Permalink") + +列出 GitLab 实例的当前外观配置. + +``` +GET /application/appearance +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/application/appearance" +``` + +响应示例: + +``` +{ "title": "GitLab Test Instance", "description": "gitlab-test.example.com", "logo": "/uploads/-/system/appearance/logo/1/logo.png", "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", "favicon": "/uploads/-/system/appearance/favicon/1/favicon.png", "new_project_guidelines": "Please read the FAQs for help.", "profile_image_guidelines": "Custom profile image guidelines", "header_message": "", "footer_message": "", "message_background_color": "#e75e40", "message_font_color": "#ffffff", "email_header_and_footer_enabled": false } +``` + +## Change appearance configuration[](#change-appearance-configuration "Permalink") + +使用 API​​调用来修改 GitLab 实例外观配置. + +``` +PUT /application/appearance +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `title` | string | no | 登录/注册页面上的实例标题 | +| `description` | string | no | 降价文字显示在登录/注册页面上 | +| `logo` | mixed | no | 登录/注册页面上使用的实例图像 | +| `header_logo` | mixed | no | 用于主导航栏的实例图像 | +| `favicon` | mixed | no | `.ico`或`.png`格式的实例图标 | +| `new_project_guidelines` | string | no | 新项目页面上显示的降价文字 | +| `profile_image_guidelines` | string | no | 降价文字显示在个人头像下方的个人资料页面上 | +| `header_message` | string | no | 系统标题栏中的消息 | +| `footer_message` | string | no | 系统页脚栏中的消息 | +| `message_background_color` | string | no | 系统页眉/页脚栏的背景颜色 | +| `message_font_color` | string | no | 系统页眉/页脚栏的字体颜色 | +| `email_header_and_footer_enabled` | boolean | no | 如果启用,则在所有外发电子邮件中添加页眉和页脚 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/application/appearance?email_header_and_footer_enabled=true&header_message=test" +``` + +响应示例: + +``` +{ "title": "GitLab Test Instance", "description": "gitlab-test.example.com", "logo": "/uploads/-/system/appearance/logo/1/logo.png", "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", "favicon": "/uploads/-/system/appearance/favicon/1/favicon.png", "new_project_guidelines": "Please read the FAQs for help.", "profile_image_guidelines": "Custom profile image guidelines", "header_message": "test", "footer_message": "", "message_background_color": "#e75e40", "message_font_color": "#ffffff", "email_header_and_footer_enabled": true } +``` \ No newline at end of file diff --git a/docs/290.md b/docs/290.md new file mode 100644 index 0000000000000000000000000000000000000000..2c7066bde63fd10a24e1fc5cdb56d6eb7d530b99 --- /dev/null +++ b/docs/290.md @@ -0,0 +1,93 @@ +# Applications API + +> 原文:[https://docs.gitlab.com/ee/api/applications.html](https://docs.gitlab.com/ee/api/applications.html) + +* [Create an application](#create-an-application) +* [List all applications](#list-all-applications) +* [Delete an application](#delete-an-application) + +# Applications API[](#applications-api "Permalink") + +在 GitLab 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8160) . + +应用程序 API 在以下 OAuth 应用程序上运行: + +* [Using GitLab as an authentication provider](../integration/oauth_provider.html). +* [Allowing access to GitLab resources on a user’s behalf](oauth2.html). + +**注意:**只有管​​理员用户才能使用 Applications API. + +## Create an application[](#create-an-application "Permalink") + +通过发布 JSON 有效负载来创建应用程序. + +如果请求成功,则返回`200` . + +``` +POST /applications +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | string | yes | 应用程序的名称. | +| `redirect_uri` | string | yes | 重定向应用程序的 URI. | +| `scopes` | string | yes | 应用范围. | +| `confidential` | boolean | no | 该应用程序将在可以对客户机密保密的地方使用. 本机移动应用程序和单页应用程序被认为是非机密的. 如果未提供,则默认为`true` | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " --data "name=MyApplication&redirect_uri=http://redirect.uri&scopes=" "https://gitlab.example.com/api/v4/applications" +``` + +响应示例: + +``` +{ "id":1, "application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737", "application_name": "MyApplication", "secret": "ee1dd64b6adc89cf7e2c23099301ccc2c61b441064e9324d963c46902a85ec34", "callback_url": "http://redirect.uri", "confidential": true } +``` + +## List all applications[](#list-all-applications "Permalink") + +列出所有注册的应用程序. + +``` +GET /applications +``` + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/applications" +``` + +响应示例: + +``` +[ { "id":1, "application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737", "application_name": "MyApplication", "callback_url": "http://redirect.uri", "confidential": true } ] +``` + +**注意:**此 API 不会公开`secret`值. + +## Delete an application[](#delete-an-application "Permalink") + +删除特定的应用程序. + +如果请求成功,则返回`204` . + +``` +DELETE /applications/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 应用程序的 ID(不是 application_id). | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/applications/:id" +``` \ No newline at end of file diff --git a/docs/291.md b/docs/291.md new file mode 100644 index 0000000000000000000000000000000000000000..faa74b50ab2943fba035472e03c75b1c0feb9136 --- /dev/null +++ b/docs/291.md @@ -0,0 +1,182 @@ +# Audit Events API + +> 原文:[https://docs.gitlab.com/ee/api/audit_events.html](https://docs.gitlab.com/ee/api/audit_events.html) + +* [Instance Audit Events](#instance-audit-events-premium-only) + * [Retrieve all instance audit events](#retrieve-all-instance-audit-events) + * [Retrieve single instance audit event](#retrieve-single-instance-audit-event) +* [Group Audit Events](#group-audit-events-starter) + * [Retrieve all group audit events](#retrieve-all-group-audit-events) + * [Retrieve a specific group audit event](#retrieve-a-specific-group-audit-event) +* [Project Audit Events](#project-audit-events-starter) + * [Retrieve all project audit events](#retrieve-all-project-audit-events) + * [Retrieve a specific project audit event](#retrieve-a-specific-project-audit-event) + +# Audit Events API[](#audit-events-api "Permalink") + +## Instance Audit Events[](#instance-audit-events-premium-only "Permalink") + +Audit Events API 使您可以检索[实例审核事件](../administration/audit_events.html#instance-events-premium-only) . + +要使用 API​​检索审核事件,您必须以管理员[身份进行身份验证](README.html#authentication) . + +### Retrieve all instance audit events[](#retrieve-all-instance-audit-events "Permalink") + +``` +GET /audit_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `created_after` | string | no | 返回在给定时间或之后创建的审核事件. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `created_before` | string | no | 返回在给定时间或之前创建的审核事件. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `entity_type` | string | no | 返回给定实体类型的审核事件. 有效值为: `User` , `Group`或`Project` . | +| `entity_id` | integer | no | 返回给定实体 ID 的审核事件. 需要`entity_type`属性存在. | + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/audit_events" +``` + +响应示例: + +``` +[ { "id": 1, "author_id": 1, "entity_id": 6, "entity_type": "Project", "details": { "custom_message": "Project archived", "author_name": "Administrator", "target_id": "flightjs/flight", "target_type": "Project", "target_details": "flightjs/flight", "ip_address": "127.0.0.1", "entity_path": "flightjs/flight" }, "created_at": "2019-08-30T07:00:41.885Z" }, { "id": 2, "author_id": 1, "entity_id": 60, "entity_type": "Group", "details": { "add": "group", "author_name": "Administrator", "target_id": "flightjs", "target_type": "Group", "target_details": "flightjs", "ip_address": "127.0.0.1", "entity_path": "flightjs" }, "created_at": "2019-08-27T18:36:44.162Z" }, { "id": 3, "author_id": 51, "entity_id": 51, "entity_type": "User", "details": { "change": "email address", "from": "hello@flightjs.com", "to": "maintainer@flightjs.com", "author_name": "Andreas", "target_id": 51, "target_type": "User", "target_details": "Andreas", "ip_address": null, "entity_path": "Andreas" }, "created_at": "2019-08-22T16:34:25.639Z" } ] +``` + +### Retrieve single instance audit event[](#retrieve-single-instance-audit-event "Permalink") + +``` +GET /audit_events/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 审核事件的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/audit_events/1" +``` + +响应示例: + +``` +{ "id": 1, "author_id": 1, "entity_id": 6, "entity_type": "Project", "details": { "custom_message": "Project archived", "author_name": "Administrator", "target_id": "flightjs/flight", "target_type": "Project", "target_details": "flightjs/flight", "ip_address": "127.0.0.1", "entity_path": "flightjs/flight" }, "created_at": "2019-08-30T07:00:41.885Z" } +``` + +## Group Audit Events[](#group-audit-events-starter "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/34078) . + +组审核事件 API 使您可以检索[组审核事件](../administration/audit_events.html#group-events-starter) . + +要使用 API​​检索组审核事件,您必须通过管理员[身份](README.html#authentication)或组所有者[身份进行身份验证](README.html#authentication) . + +### Retrieve all group audit events[](#retrieve-all-group-audit-events "Permalink") + +``` +GET /groups/:id/audit_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `created_after` | string | no | 在给定时间或之后创建的返回组审核事件. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `created_before` | string | no | 返回在给定时间或之前创建的组审核事件. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/groups/60/audit_events" +``` + +响应示例: + +``` +[ { "id": 2, "author_id": 1, "entity_id": 60, "entity_type": "Group", "details": { "custom_message": "Group marked for deletion", "author_name": "Administrator", "target_id": "flightjs", "target_type": "Group", "target_details": "flightjs", "ip_address": "127.0.0.1", "entity_path": "flightjs" }, "created_at": "2019-08-28T19:36:44.162Z" }, { "id": 1, "author_id": 1, "entity_id": 60, "entity_type": "Group", "details": { "add": "group", "author_name": "Administrator", "target_id": "flightjs", "target_type": "Group", "target_details": "flightjs", "ip_address": "127.0.0.1", "entity_path": "flightjs" }, "created_at": "2019-08-27T18:36:44.162Z" } ] +``` + +### Retrieve a specific group audit event[](#retrieve-a-specific-group-audit-event "Permalink") + +仅对组所有者和管理员可用. + +``` +GET /groups/:id/audit_events/:audit_event_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `audit_event_id` | integer | yes | 审核事件的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/groups/60/audit_events/2" +``` + +响应示例: + +``` +{ "id": 2, "author_id": 1, "entity_id": 60, "entity_type": "Group", "details": { "custom_message": "Group marked for deletion", "author_name": "Administrator", "target_id": "flightjs", "target_type": "Group", "target_details": "flightjs", "ip_address": "127.0.0.1", "entity_path": "flightjs" }, "created_at": "2019-08-28T19:36:44.162Z" } +``` + +## Project Audit Events[](#project-audit-events-starter "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/219238) . + +通过 Project Audit Events API,您可以检索[项目审核事件](../administration/audit_events.html#project-events-starter) . + +To retrieve project audit events using the API, you must [authenticate yourself](README.html#authentication) as a Maintainer or an Owner of the project. + +### Retrieve all project audit events[](#retrieve-all-project-audit-events "Permalink") + +``` +GET /projects/:id/audit_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `created_after` | string | no | 返回在给定时间或之后创建的项目审核事件. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `created_before` | string | no | 返回在给定时间或之前创建的项目审核事件. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +``` +curl --header "PRIVATE-TOKEN: " https://primary.example.com/api/v4/projects/7/audit_events +``` + +响应示例: + +``` +[ { "id": 5, "author_id": 1, "entity_id": 7, "entity_type": "Project", "details": { "change": "prevent merge request approval from reviewers", "from": "", "to": "true", "author_name": "Administrator", "target_id": 7, "target_type": "Project", "target_details": "twitter/typeahead-js", "ip_address": "127.0.0.1", "entity_path": "twitter/typeahead-js" }, "created_at": "2020-05-26T22:55:04.230Z" }, { "id": 4, "author_id": 1, "entity_id": 7, "entity_type": "Project", "details": { "change": "prevent merge request approval from authors", "from": "false", "to": "true", "author_name": "Administrator", "target_id": 7, "target_type": "Project", "target_details": "twitter/typeahead-js", "ip_address": "127.0.0.1", "entity_path": "twitter/typeahead-js" }, "created_at": "2020-05-26T22:55:04.218Z" } ] +``` + +### Retrieve a specific project audit event[](#retrieve-a-specific-project-audit-event "Permalink") + +仅适用于项目维护者或所有者. + +``` +GET /projects/:id/audit_events/:audit_event_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `audit_event_id` | integer | yes | 审核事件的 ID | + +``` +curl --header "PRIVATE-TOKEN: " https://primary.example.com/api/v4/projects/7/audit_events/5 +``` + +响应示例: + +``` +{ "id": 5, "author_id": 1, "entity_id": 7, "entity_type": "Project", "details": { "change": "prevent merge request approval from reviewers", "from": "", "to": "true", "author_name": "Administrator", "target_id": 7, "target_type": "Project", "target_details": "twitter/typeahead-js", "ip_address": "127.0.0.1", "entity_path": "twitter/typeahead-js" }, "created_at": "2020-05-26T22:55:04.230Z" } +``` \ No newline at end of file diff --git a/docs/292.md b/docs/292.md new file mode 100644 index 0000000000000000000000000000000000000000..101b6cb11ed4f65dcc12d31632ebfbe614497045 --- /dev/null +++ b/docs/292.md @@ -0,0 +1,43 @@ +# Avatar API + +> 原文:[https://docs.gitlab.com/ee/api/avatar.html](https://docs.gitlab.com/ee/api/avatar.html) + +* [Get a single avatar URL](#get-a-single-avatar-url) + +# Avatar API[](#avatar-api "Permalink") + +在 GitLab 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19121) . + +## Get a single avatar URL[](#get-a-single-avatar-url "Permalink") + +使用给定的电子邮件地址为用户获取一个[头像](../user/profile/index.html#profile-settings) URL. + +If: + +* 找不到具有给定公共电子邮件地址的用户,返回来自外部化身服务的结果. +* 公开可见性受到限制,未经身份验证时,响应将为`403 Forbidden` . + +**注意:**无需身份验证即可访问此端点. + +``` +GET /avatar?email=admin@example.com +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `email` | string | yes | 用户的公共电子邮件地址. | +| `size` | integer | no | 单像素尺寸(因为图像是正方形). 仅用于在`Gravatar`或已配置的`Libravatar`服务器上的头像查找. | + +请求示例: + +``` +curl "https://gitlab.example.com/api/v4/avatar?email=admin@example.com&size=32" +``` + +响应示例: + +``` +{ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=64&d=identicon" } +``` \ No newline at end of file diff --git a/docs/293.md b/docs/293.md new file mode 100644 index 0000000000000000000000000000000000000000..570b37b33929db58a7b52122957c8dc042eafb90 --- /dev/null +++ b/docs/293.md @@ -0,0 +1,260 @@ +# Award Emoji API + +> 原文:[https://docs.gitlab.com/ee/api/award_emoji.html](https://docs.gitlab.com/ee/api/award_emoji.html) + +* [Issues, merge requests, and snippets](#issues-merge-requests-and-snippets) + * [List an awardable’s award emoji](#list-an-awardables-award-emoji) + * [Get single award emoji](#get-single-award-emoji) + * [Award a new emoji](#award-a-new-emoji) + * [Delete an award emoji](#delete-an-award-emoji) +* [Award Emoji on Comments](#award-emoji-on-comments) + * [List a comment’s award emoji](#list-a-comments-award-emoji) + * [Get an award emoji for a comment](#get-an-award-emoji-for-a-comment) + * [Award a new emoji on a comment](#award-a-new-emoji-on-a-comment) + * [Delete an award emoji from a comment](#delete-an-award-emoji-from-a-comment) + +# Award Emoji API[](#award-emoji-api "Permalink") + +在 GitLab 8.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4575) . 在 8.12 中添加了代码段支持. + +[获奖的表情符号](../user/award_emojis.html)讲出一千个单词. + +可以通过以下方式授予表情符号(称为"奖项"): + +* [Issues](../user/project/issues/index.html) ([API](issues.html)). +* [Merge requests](../user/project/merge_requests/index.html) ([API](merge_requests.html)). +* [Snippets](../user/snippets.html) ([API](snippets.html)). + +Emoji can also [be awarded](../user/award_emojis.html#award-emoji-for-comments) on comments (also known as notes). See also [Notes API](notes.html). + +## Issues, merge requests, and snippets[](#issues-merge-requests-and-snippets "Permalink") + +有关将这些端点与注释一起使用的信息,请参见[在注释](#award-emoji-on-comments)上[授予 Emoji 表情](#award-emoji-on-comments) . + +### List an awardable’s award emoji[](#list-an-awardables-award-emoji "Permalink") + +获取指定奖励的所有奖励表情符号的列表. + +``` +GET /projects/:id/issues/:issue_iid/award_emoji +GET /projects/:id/merge_requests/:merge_request_iid/award_emoji +GET /projects/:id/snippets/:snippet_id/award_emoji +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid`/`merge_request_iid`/`snippet_id` | integer | yes | `iid` ID(合并请求/问题的`id` ,摘要的`id` ). | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji" +``` + +响应示例: + +``` +[ { "id": 4, "name": "1234", "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2016-06-15T10:09:34.206Z", "updated_at": "2016-06-15T10:09:34.206Z", "awardable_id": 80, "awardable_type": "Issue" }, { "id": 1, "name": "microphone", "user": { "name": "User 4", "username": "user4", "id": 26, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/7e65550957227bd38fe2d7fbc6fd2f7b?s=80&d=identicon", "web_url": "http://gitlab.example.com/user4" }, "created_at": "2016-06-15T10:09:34.177Z", "updated_at": "2016-06-15T10:09:34.177Z", "awardable_id": 80, "awardable_type": "Issue" } ] +``` + +### Get single award emoji[](#get-single-award-emoji "Permalink") + +从问题,摘要或合并请求中获取单个奖励表情符号. + +``` +GET /projects/:id/issues/:issue_iid/award_emoji/:award_id +GET /projects/:id/merge_requests/:merge_request_iid/award_emoji/:award_id +GET /projects/:id/snippets/:snippet_id/award_emoji/:award_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid`/`merge_request_iid`/`snippet_id` | integer | yes | `iid` ID(合并请求/问题的`id` ,摘要的`id` ). | +| `award_id` | integer | yes | 奖励表情符号的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/1" +``` + +响应示例: + +``` +{ "id": 1, "name": "microphone", "user": { "name": "User 4", "username": "user4", "id": 26, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/7e65550957227bd38fe2d7fbc6fd2f7b?s=80&d=identicon", "web_url": "http://gitlab.example.com/user4" }, "created_at": "2016-06-15T10:09:34.177Z", "updated_at": "2016-06-15T10:09:34.177Z", "awardable_id": 80, "awardable_type": "Issue" } +``` + +### Award a new emoji[](#award-a-new-emoji "Permalink") + +在指定的奖励对象上创建奖励表情符号. + +``` +POST /projects/:id/issues/:issue_iid/award_emoji +POST /projects/:id/merge_requests/:merge_request_iid/award_emoji +POST /projects/:id/snippets/:snippet_id/award_emoji +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid`/`merge_request_iid`/`snippet_id` | integer | yes | `iid` ID(合并请求/问题的`id` ,摘要的`id` ). | +| `name` | string | yes | 不含冒号的表情符号名称. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji?name=blowfish" +``` + +示例响应: + +``` +{ "id": 344, "name": "blowfish", "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2016-06-17T17:47:29.266Z", "updated_at": "2016-06-17T17:47:29.266Z", "awardable_id": 80, "awardable_type": "Issue" } +``` + +### Delete an award emoji[](#delete-an-award-emoji "Permalink") + +有时候,这并不是必须的,您必须取消该奖项. + +**注意:**仅适用于管理员或奖项的作者. + +``` +DELETE /projects/:id/issues/:issue_iid/award_emoji/:award_id +DELETE /projects/:id/merge_requests/:merge_request_iid/award_emoji/:award_id +DELETE /projects/:id/snippets/:snippet_id/award_emoji/:award_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid`/`merge_request_iid`/`snippet_id` | integer | yes | `iid` ID(合并请求/问题的`id` ,摘要的`id` ). | +| `award_id` | integer | yes | 奖励表情符号的 ID. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/344" +``` + +## Award Emoji on Comments[](#award-emoji-on-comments "Permalink") + +注释(也称为注释)是问题,合并请求和摘要的子资源. + +**注意:**以下示例描述了如何使用奖励表情符号处理问题的注释,但可以轻松地将其用于合并请求或摘要中的注释. 因此,您必须用`merge_request_iid`或`snippet_id`替换`issue_iid` . + +### List a comment’s award emoji[](#list-a-comments-award-emoji "Permalink") + +获取所有奖励表情符号的评论(注释). + +``` +GET /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid` | integer | yes | 问题的内部 ID. | +| `note_id` | integer | yes | 注释(注释)的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji" +``` + +响应示例: + +``` +[ { "id": 2, "name": "mood_bubble_lightning", "user": { "name": "User 4", "username": "user4", "id": 26, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/7e65550957227bd38fe2d7fbc6fd2f7b?s=80&d=identicon", "web_url": "http://gitlab.example.com/user4" }, "created_at": "2016-06-15T10:09:34.197Z", "updated_at": "2016-06-15T10:09:34.197Z", "awardable_id": 1, "awardable_type": "Note" } ] +``` + +### Get an award emoji for a comment[](#get-an-award-emoji-for-a-comment "Permalink") + +获得单个奖励表情符号作为注释(注释). + +``` +GET /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji/:award_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid` | integer | yes | 问题的内部 ID. | +| `note_id` | integer | yes | 注释(注释)的 ID. | +| `award_id` | integer | yes | 奖励表情符号的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji/2" +``` + +响应示例: + +``` +{ "id": 2, "name": "mood_bubble_lightning", "user": { "name": "User 4", "username": "user4", "id": 26, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/7e65550957227bd38fe2d7fbc6fd2f7b?s=80&d=identicon", "web_url": "http://gitlab.example.com/user4" }, "created_at": "2016-06-15T10:09:34.197Z", "updated_at": "2016-06-15T10:09:34.197Z", "awardable_id": 1, "awardable_type": "Note" } +``` + +### Award a new emoji on a comment[](#award-a-new-emoji-on-a-comment "Permalink") + +在指定的注释(注释)上创建一个奖励表情符号. + +``` +POST /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid` | integer | yes | 问题的内部 ID. | +| `note_id` | integer | yes | 注释(注释)的 ID. | +| `name` | string | yes | 不含冒号的表情符号名称. | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji?name=rocket" +``` + +响应示例: + +``` +{ "id": 345, "name": "rocket", "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2016-06-17T19:59:55.888Z", "updated_at": "2016-06-17T19:59:55.888Z", "awardable_id": 1, "awardable_type": "Note" } +``` + +### Delete an award emoji from a comment[](#delete-an-award-emoji-from-a-comment "Permalink") + +有时候,这并不是必须的,您必须取消该奖项. + +**注意:**仅适用于管理员或奖项的作者. + +``` +DELETE /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji/:award_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `issue_iid` | integer | yes | 问题的内部 ID. | +| `note_id` | integer | yes | 注释(注释)的 ID. | +| `award_id` | integer | yes | award_emoji 的 ID. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/345" +``` \ No newline at end of file diff --git a/docs/294.md b/docs/294.md new file mode 100644 index 0000000000000000000000000000000000000000..90201afce148eed352697804380fc3708c370d5d --- /dev/null +++ b/docs/294.md @@ -0,0 +1,160 @@ +# Project badges API + +> 原文:[https://docs.gitlab.com/ee/api/project_badges.html](https://docs.gitlab.com/ee/api/project_badges.html) + +* [Placeholder tokens](#placeholder-tokens) +* [List all badges of a project](#list-all-badges-of-a-project) +* [Get a badge of a project](#get-a-badge-of-a-project) +* [Add a badge to a project](#add-a-badge-to-a-project) +* [Edit a badge of a project](#edit-a-badge-of-a-project) +* [Remove a badge from a project](#remove-a-badge-from-a-project) +* [Preview a badge from a project](#preview-a-badge-from-a-project) + +# Project badges API[](#project-badges-api "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17082) . + +## Placeholder tokens[](#placeholder-tokens "Permalink") + +徽章支持占位符,这些占位符将在链接和图像 URL 中被实时替换. 允许的占位符为: + +* **%{project_path}** :将被项目路径替换. +* **%{project_id}** :将被项目 ID 取代. +* **%{default_branch}** :将被项目默认分支替换. +* **%{commit_sha}** :将被上一个项目的提交 sha 取代. + +## List all badges of a project[](#list-all-badges-of-a-project "Permalink") + +获取项目徽章及其组徽章的列表. + +``` +GET /projects/:id/badges +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | no | 要返回的徽章名称(区分大小写). | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/badges" +``` + +响应示例: + +``` +[ { "name": "Coverage", "id": 1, "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", "kind": "project" }, { "name": "Pipeline", "id": 2, "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", "kind": "group" }, ] +``` + +## Get a badge of a project[](#get-a-badge-of-a-project "Permalink") + +获取项目的徽章. + +``` +GET /projects/:id/badges/:badge_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `badge_id` | integer | yes | 徽章 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id" +``` + +响应示例: + +``` +{ "id": 1, "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", "kind": "project" } +``` + +## Add a badge to a project[](#add-a-badge-to-a-project "Permalink") + +将徽章添加到项目. + +``` +POST /projects/:id/badges +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `link_url` | string | yes | 徽章链接的 URL | +| `image_url` | string | yes | 徽章图片的网址 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --data "link_url=https://gitlab.com/gitlab-org/gitlab-foss/commits/master&image_url=https://shields.io/my/badge1&position=0" "https://gitlab.example.com/api/v4/projects/:id/badges" +``` + +响应示例: + +``` +{ "id": 1, "link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "image_url": "https://shields.io/my/badge1", "rendered_link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "rendered_image_url": "https://shields.io/my/badge1", "kind": "project" } +``` + +## Edit a badge of a project[](#edit-a-badge-of-a-project "Permalink") + +更新项目的徽章. + +``` +PUT /projects/:id/badges/:badge_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `badge_id` | integer | yes | 徽章 ID | +| `link_url` | string | no | 徽章链接的 URL | +| `image_url` | string | no | 徽章图片的网址 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id" +``` + +响应示例: + +``` +{ "id": 1, "link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "image_url": "https://shields.io/my/badge", "rendered_link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "rendered_image_url": "https://shields.io/my/badge", "kind": "project" } +``` + +## Remove a badge from a project[](#remove-a-badge-from-a-project "Permalink") + +从项目中删除徽章. 使用此端点将仅删除项目的标志. + +``` +DELETE /projects/:id/badges/:badge_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `badge_id` | integer | yes | 徽章 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id" +``` + +## Preview a badge from a project[](#preview-a-badge-from-a-project "Permalink") + +返回解析占位符插值后的`link_url`和`image_url`最终 URL. + +``` +GET /projects/:id/badges/render +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `link_url` | string | yes | 徽章链接的 URL | +| `image_url` | string | yes | 徽章图片的网址 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/badges/render?link_url=http%3A%2F%2Fexample.com%2Fci_status.svg%3Fproject%3D%25%7Bproject_path%7D%26ref%3D%25%7Bdefault_branch%7D&image_url=https%3A%2F%2Fshields.io%2Fmy%2Fbadge" +``` + +响应示例: + +``` +{ "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", } +``` \ No newline at end of file diff --git a/docs/295.md b/docs/295.md new file mode 100644 index 0000000000000000000000000000000000000000..b4f207a702c613f22666101b2e6d7a1899b8b3af --- /dev/null +++ b/docs/295.md @@ -0,0 +1,162 @@ +# Group badges API + +> 原文:[https://docs.gitlab.com/ee/api/group_badges.html](https://docs.gitlab.com/ee/api/group_badges.html) + +* [Placeholder tokens](#placeholder-tokens) +* [List all badges of a group](#list-all-badges-of-a-group) +* [Get a badge of a group](#get-a-badge-of-a-group) +* [Add a badge to a group](#add-a-badge-to-a-group) +* [Edit a badge of a group](#edit-a-badge-of-a-group) +* [Remove a badge from a group](#remove-a-badge-from-a-group) +* [Preview a badge from a group](#preview-a-badge-from-a-group) + +# Group badges API[](#group-badges-api "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17082) . + +## Placeholder tokens[](#placeholder-tokens "Permalink") + +徽章支持占位符,这些占位符将在链接和图像 URL 中被实时替换. 允许的占位符为: + +* **%{project_path}** :将被项目路径替换. +* **%{project_id}** :将被项目 ID 取代. +* **%{default_branch}** :将被项目默认分支替换. +* **%{commit_sha}** :将由上一个项目的提交 SHA 替换. + +由于这些端点不在项目上下文中,因此用于替换占位符的信息将在创建日期之前来自第一组项目. 如果该组没有任何项目,则将返回带有占位符的原始 URL. + +## List all badges of a group[](#list-all-badges-of-a-group "Permalink") + +获取小组徽章的列表. + +``` +GET /groups/:id/badges +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | no | 要返回的徽章名称(区分大小写). | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/badges?name=Coverage" +``` + +响应示例: + +``` +[ { "name": "Coverage", "id": 1, "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", "kind": "group" } ] +``` + +## Get a badge of a group[](#get-a-badge-of-a-group "Permalink") + +获取组的徽章. + +``` +GET /groups/:id/badges/:badge_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `badge_id` | integer | yes | 徽章 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id" +``` + +响应示例: + +``` +{ "id": 1, "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", "kind": "group" } +``` + +## Add a badge to a group[](#add-a-badge-to-a-group "Permalink") + +将徽章添加到组. + +``` +POST /groups/:id/badges +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `link_url` | string | yes | 徽章链接的 URL | +| `image_url` | string | yes | 徽章图片的网址 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --data "link_url=https://gitlab.com/gitlab-org/gitlab-foss/commits/master&image_url=https://shields.io/my/badge1&position=0" "https://gitlab.example.com/api/v4/groups/:id/badges" +``` + +响应示例: + +``` +{ "id": 1, "link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "image_url": "https://shields.io/my/badge1", "rendered_link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "rendered_image_url": "https://shields.io/my/badge1", "kind": "group" } +``` + +## Edit a badge of a group[](#edit-a-badge-of-a-group "Permalink") + +Updates a badge of a group. + +``` +PUT /groups/:id/badges/:badge_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `badge_id` | integer | yes | 徽章 ID | +| `link_url` | string | no | 徽章链接的 URL | +| `image_url` | string | no | 徽章图片的网址 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id" +``` + +响应示例: + +``` +{ "id": 1, "link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "image_url": "https://shields.io/my/badge", "rendered_link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master", "rendered_image_url": "https://shields.io/my/badge", "kind": "group" } +``` + +## Remove a badge from a group[](#remove-a-badge-from-a-group "Permalink") + +从组中删除徽章. + +``` +DELETE /groups/:id/badges/:badge_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `badge_id` | integer | yes | 徽章 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id" +``` + +## Preview a badge from a group[](#preview-a-badge-from-a-group "Permalink") + +返回解析占位符插值后的`link_url`和`image_url`最终 URL. + +``` +GET /groups/:id/badges/render +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `link_url` | string | yes | 徽章链接的 URL | +| `image_url` | string | yes | 徽章图片的网址 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/badges/render?link_url=http%3A%2F%2Fexample.com%2Fci_status.svg%3Fproject%3D%25%7Bproject_path%7D%26ref%3D%25%7Bdefault_branch%7D&image_url=https%3A%2F%2Fshields.io%2Fmy%2Fbadge" +``` + +响应示例: + +``` +{ "link_url": "http://example.com/ci_status.svg?project=%{project_path}&ref=%{default_branch}", "image_url": "https://shields.io/my/badge", "rendered_link_url": "http://example.com/ci_status.svg?project=example-org/example-project&ref=master", "rendered_image_url": "https://shields.io/my/badge", } +``` \ No newline at end of file diff --git a/docs/296.md b/docs/296.md new file mode 100644 index 0000000000000000000000000000000000000000..7ed91667a58a1d73509e15dfc0f04a5d5a4ac6d7 --- /dev/null +++ b/docs/296.md @@ -0,0 +1,156 @@ +# Branches API + +> 原文:[https://docs.gitlab.com/ee/api/branches.html](https://docs.gitlab.com/ee/api/branches.html) + +* [List repository branches](#list-repository-branches) +* [Get single repository branch](#get-single-repository-branch) +* [Protect repository branch](#protect-repository-branch) +* [Unprotect repository branch](#unprotect-repository-branch) +* [Create repository branch](#create-repository-branch) +* [Delete repository branch](#delete-repository-branch) +* [Delete merged branches](#delete-merged-branches) + +# Branches API[](#branches-api "Permalink") + +该 API 在[存储库分支上运行](../user/project/repository/branches/index.html) . + +**提示:**另请参阅[受保护的分支机构 API](protected_branches.html) . + +## List repository branches[](#list-repository-branches "Permalink") + +从项目中获取存储库分支的列表,按名称的字母顺序排序. + +**注意:**如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/branches +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `search` | string | no | 返回包含搜索字符串的分支列表. 您可以使用`^term`和`term$`查找分别以`term`开头和结尾的分支. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/branches" +``` + +响应示例: + +``` +[ { "name": "master", "merged": false, "protected": true, "default": true, "developers_can_push": false, "developers_can_merge": false, "can_push": true, "web_url": "http://gitlab.example.com/my-group/my-project/-/tree/master", "commit": { "author_email": "john@example.com", "author_name": "John Smith", "authored_date": "2012-06-27T05:51:39-07:00", "committed_date": "2012-06-28T03:44:20-07:00", "committer_email": "john@example.com", "committer_name": "John Smith", "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c", "short_id": "7b5c3cc", "title": "add projects API", "message": "add projects API", "parent_ids": [ "4ad91d3c1144c406e50c7b33bae684bd6837faf8" ] } }, ... ] +``` + +## Get single repository branch[](#get-single-repository-branch "Permalink") + +获取单个项目存储库分支. + +**注意:**如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/branches/:branch +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `branch` | string | yes | 分支名称. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/branches/master" +``` + +响应示例: + +``` +{ "name": "master", "merged": false, "protected": true, "default": true, "developers_can_push": false, "developers_can_merge": false, "can_push": true, "web_url": "http://gitlab.example.com/my-group/my-project/-/tree/master", "commit": { "author_email": "john@example.com", "author_name": "John Smith", "authored_date": "2012-06-27T05:51:39-07:00", "committed_date": "2012-06-28T03:44:20-07:00", "committer_email": "john@example.com", "committer_name": "John Smith", "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c", "short_id": "7b5c3cc", "title": "add projects API", "message": "add projects API", "parent_ids": [ "4ad91d3c1144c406e50c7b33bae684bd6837faf8" ] } } +``` + +## Protect repository branch[](#protect-repository-branch "Permalink") + +有关保护存储库分支的信息,请参见[`POST /projects/:id/protected_branches`](protected_branches.html#protect-repository-branches) . + +## Unprotect repository branch[](#unprotect-repository-branch "Permalink") + +有关取消保护存储库分支的信息,请参见[`DELETE /projects/:id/protected_branches/:name`](protected_branches.html#unprotect-repository-branches) . + +## Create repository branch[](#create-repository-branch "Permalink") + +在存储库中创建一个新分支. + +``` +POST /projects/:id/repository/branches +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `branch` | string | yes | 分支名称. | +| `ref` | string | yes | 分支名称或提交 SHA 以从中创建分支. | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/branches?branch=newbranch&ref=master" +``` + +响应示例: + +``` +{ "commit": { "author_email": "john@example.com", "author_name": "John Smith", "authored_date": "2012-06-27T05:51:39-07:00", "committed_date": "2012-06-28T03:44:20-07:00", "committer_email": "john@example.com", "committer_name": "John Smith", "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c", "short_id": "7b5c3cc", "title": "add projects API", "message": "add projects API", "parent_ids": [ "4ad91d3c1144c406e50c7b33bae684bd6837faf8" ] }, "name": "newbranch", "merged": false, "protected": false, "default": false, "developers_can_push": false, "developers_can_merge": false, "can_push": true, "web_url": "http://gitlab.example.com/my-group/my-project/-/tree/newbranch" } +``` + +## Delete repository branch[](#delete-repository-branch "Permalink") + +从存储库中删除一个分支. + +**注意:**如果发生错误,将提供说明消息. + +``` +DELETE /projects/:id/repository/branches/:branch +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `branch` | string | yes | 分支名称. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/branches/newbranch" +``` + +## Delete merged branches[](#delete-merged-branches "Permalink") + +Will delete all branches that are merged into the project’s default branch. + +**注意:**此操作不会删除[受保护的分支](../user/project/protected_branches.html) . + +``` +DELETE /projects/:id/repository/merged_branches +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/merged_branches" +``` \ No newline at end of file diff --git a/docs/297.md b/docs/297.md new file mode 100644 index 0000000000000000000000000000000000000000..b2d427473e84f9e14f20e47034b405399dbcf64a --- /dev/null +++ b/docs/297.md @@ -0,0 +1,153 @@ +# Broadcast Messages API + +> 原文:[https://docs.gitlab.com/ee/api/broadcast_messages.html](https://docs.gitlab.com/ee/api/broadcast_messages.html) + +* [Get all broadcast messages](#get-all-broadcast-messages) +* [Get a specific broadcast message](#get-a-specific-broadcast-message) +* [Create a broadcast message](#create-a-broadcast-message) +* [Update a broadcast message](#update-a-broadcast-message) +* [Delete a broadcast message](#delete-a-broadcast-message) + +# Broadcast Messages API[](#broadcast-messages-api "Permalink") + +在 GitLab 8.12 中引入. + +广播消息 API 对[广播消息进行操作](../user/admin_area/broadcast_messages.html) . + +从 GitLab 12.8 开始,GET 请求不需要身份验证. 所有其他广播消息 API 终结点只能由管理员访问. 非 GET 请求者: + +* 来宾将导致`401 Unauthorized` . +* 普通用户将导致`403 Forbidden` . + +## Get all broadcast messages[](#get-all-broadcast-messages "Permalink") + +列出所有广播消息. + +``` +GET /broadcast_messages +``` + +请求示例: + +``` +curl "https://gitlab.example.com/api/v4/broadcast_messages" +``` + +响应示例: + +``` +[ { "message":"Example broadcast message", "starts_at":"2016-08-24T23:21:16.078Z", "ends_at":"2016-08-26T23:21:16.080Z", "color":"#E75E40", "font":"#FFFFFF", "id":1, "active": false, "target_path": "*/welcome", "broadcast_type": "banner", "dismissable": false } ] +``` + +## Get a specific broadcast message[](#get-a-specific-broadcast-message "Permalink") + +获取特定的广播消息. + +``` +GET /broadcast_messages/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要检索的广播消息的 ID. | + +请求示例: + +``` +curl "https://gitlab.example.com/api/v4/broadcast_messages/1" +``` + +响应示例: + +``` +{ "message":"Deploy in progress", "starts_at":"2016-08-24T23:21:16.078Z", "ends_at":"2016-08-26T23:21:16.080Z", "color":"#cecece", "font":"#FFFFFF", "id":1, "active":false, "target_path": "*/welcome", "broadcast_type": "banner", "dismissable": false } +``` + +## Create a broadcast message[](#create-a-broadcast-message "Permalink") + +创建一个新的广播消息. + +``` +POST /broadcast_messages +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `message` | string | yes | 显示的消息. | +| `starts_at` | datetime | no | 开始时间(默认为当前时间). | +| `ends_at` | datetime | no | 结束时间(默认为当前时间的一小时). | +| `color` | string | no | 背景色十六进制代码. | +| `font` | string | no | 前景颜色十六进制代码. | +| `target_path` | string | no | 广播消息的目标路径. | +| `broadcast_type` | string | no | 外观类型(默认为横幅) | +| `dismissable` | boolean | no | 用户可以关闭该消息吗? | + +请求示例: + +``` +curl --data "message=Deploy in progress&color=#cecece" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/broadcast_messages" +``` + +响应示例: + +``` +{ "message":"Deploy in progress", "starts_at":"2016-08-26T00:41:35.060Z", "ends_at":"2016-08-26T01:41:35.060Z", "color":"#cecece", "font":"#FFFFFF", "id":1, "active": true, "target_path": "*/welcome", "broadcast_type": "notification", "dismissable": false } +``` + +## Update a broadcast message[](#update-a-broadcast-message "Permalink") + +更新现有的广播消息. + +``` +PUT /broadcast_messages/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要更新的广播消息的 ID. | +| `message` | string | no | 显示的消息. | +| `starts_at` | datetime | no | 起始时间. | +| `ends_at` | datetime | no | 结束时间. | +| `color` | string | no | 背景色十六进制代码. | +| `font` | string | no | 前景颜色十六进制代码. | +| `target_path` | string | no | 广播消息的目标路径. | +| `broadcast_type` | string | no | 外观类型(默认为横幅) | +| `dismissable` | boolean | no | 用户可以关闭该消息吗? | + +请求示例: + +``` +curl --request PUT --data "message=Update message&color=#000" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/broadcast_messages/1" +``` + +响应示例: + +``` +{ "message":"Update message", "starts_at":"2016-08-26T00:41:35.060Z", "ends_at":"2016-08-26T01:41:35.060Z", "color":"#000", "font":"#FFFFFF", "id":1, "active": true, "target_path": "*/welcome", "broadcast_type": "notification", "dismissable": false } +``` + +## Delete a broadcast message[](#delete-a-broadcast-message "Permalink") + +删除广播消息. + +``` +DELETE /broadcast_messages/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要删除的广播消息的 ID. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/broadcast_messages/1" +``` \ No newline at end of file diff --git a/docs/298.md b/docs/298.md new file mode 100644 index 0000000000000000000000000000000000000000..13889a3a3662f61f2c471f21f36e5349d76b69b5 --- /dev/null +++ b/docs/298.md @@ -0,0 +1,168 @@ +# Project clusters API + +> 原文:[https://docs.gitlab.com/ee/api/project_clusters.html](https://docs.gitlab.com/ee/api/project_clusters.html) + +* [List project clusters](#list-project-clusters) +* [Get a single project cluster](#get-a-single-project-cluster) +* [Add existing cluster to project](#add-existing-cluster-to-project) +* [Edit project cluster](#edit-project-cluster) +* [Delete project cluster](#delete-project-cluster) + +# Project clusters API[](#project-clusters-api "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23922) . + +**注意:**用户将至少需要维护者访问权限才能使用这些端点. + +## List project clusters[](#list-project-clusters "Permalink") + +返回项目集群的列表. + +``` +GET /projects/:id/clusters +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 认证用户拥有的项目的 ID | + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/projects/26/clusters" +``` + +响应示例: + +``` +[ { "id":18, "name":"cluster-1", "domain":"example.com", "created_at":"2019-01-02T20:18:12.563Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"project_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://104.197.68.152", "namespace":"cluster-1-namespace", "authorization_type":"rbac", "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----" }, "management_project": { "id":2, "description":null, "name":"project2", "name_with_namespace":"John Doe8 / project2", "path":"project2", "path_with_namespace":"namespace2/project2", "created_at":"2019-10-11T02:55:54.138Z" } }, { "id":19, "name":"cluster-2", ... } ] +``` + +## Get a single project cluster[](#get-a-single-project-cluster "Permalink") + +获取单个项目集群. + +``` +GET /projects/:id/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 认证用户拥有的项目的 ID | +| `cluster_id` | integer | yes | 集群的 ID | + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/projects/26/clusters/18" +``` + +响应示例: + +``` +{ "id":18, "name":"cluster-1", "domain":"example.com", "created_at":"2019-01-02T20:18:12.563Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"project_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://104.197.68.152", "namespace":"cluster-1-namespace", "authorization_type":"rbac", "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----" }, "management_project": { "id":2, "description":null, "name":"project2", "name_with_namespace":"John Doe8 / project2", "path":"project2", "path_with_namespace":"namespace2/project2", "created_at":"2019-10-11T02:55:54.138Z" }, "project": { "id":26, "description":"", "name":"project-with-clusters-api", "name_with_namespace":"Administrator / project-with-clusters-api", "path":"project-with-clusters-api", "path_with_namespace":"root/project-with-clusters-api", "created_at":"2019-01-02T20:13:32.600Z", "default_branch":null, "tag_list":[], "ssh_url_to_repo":"ssh://gitlab.example.com/root/project-with-clusters-api.git", "http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git", "web_url":"https://gitlab.example.com/root/project-with-clusters-api", "readme_url":null, "avatar_url":null, "star_count":0, "forks_count":0, "last_activity_at":"2019-01-02T20:13:32.600Z", "namespace": { "id":1, "name":"root", "path":"root", "kind":"user", "full_path":"root", "parent_id":null } } } +``` + +## Add existing cluster to project[](#add-existing-cluster-to-project "Permalink") + +将现有的 Kubernetes 集群添加到项目中. + +``` +POST /projects/:id/clusters/user +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 认证用户拥有的项目的 ID | +| `name` | string | yes | 集群名称 | +| `domain` | string | no | 集群的[基础域](../user/project/clusters/index.html#base-domain) | +| `management_project_id` | integer | no | 集群[管理项目](../user/clusters/management_project.html)的 ID | +| `enabled` | boolean | no | 确定集群是否处于活动状态,默认为 true | +| `managed` | boolean | no | Determines if GitLab will manage namespaces and service accounts for this cluster, defaults to true | +| `platform_kubernetes_attributes[api_url]` | string | yes | 访问 Kubernetes API 的 URL | +| `platform_kubernetes_attributes[token]` | string | yes | 针对 Kubernetes 进行身份验证的令牌 | +| `platform_kubernetes_attributes[ca_cert]` | string | no | TLS 证书. 如果 API 使用自签名 TLS 证书,则为必填. | +| `platform_kubernetes_attributes[namespace]` | string | no | 与项目相关的唯一名称空间 | +| `platform_kubernetes_attributes[authorization_type]` | string | no | 集群授权类型: `rbac` , `abac`或`unknown_authorization` . 默认为`rbac` . | +| `environment_scope` | string | no | 集群的关联环境. 默认为`*` | + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/projects/26/clusters/user" \ +-H "Accept: application/json" \ +-H "Content-Type:application/json" \ +-X POST --data '{"name":"cluster-5", "platform_kubernetes_attributes":{"api_url":"https://35.111.51.20","token":"12345","namespace":"cluster-5-namespace","ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----"}}' +``` + +响应示例: + +``` +{ "id":24, "name":"cluster-5", "created_at":"2019-01-03T21:53:40.610Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"project_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://35.111.51.20", "namespace":"cluster-5-namespace", "authorization_type":"rbac", "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----" }, "management_project":null, "project": { "id":26, "description":"", "name":"project-with-clusters-api", "name_with_namespace":"Administrator / project-with-clusters-api", "path":"project-with-clusters-api", "path_with_namespace":"root/project-with-clusters-api", "created_at":"2019-01-02T20:13:32.600Z", "default_branch":null, "tag_list":[], "ssh_url_to_repo":"ssh:://gitlab.example.com/root/project-with-clusters-api.git", "http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git", "web_url":"https://gitlab.example.com/root/project-with-clusters-api", "readme_url":null, "avatar_url":null, "star_count":0, "forks_count":0, "last_activity_at":"2019-01-02T20:13:32.600Z", "namespace": { "id":1, "name":"root", "path":"root", "kind":"user", "full_path":"root", "parent_id":null } } } +``` + +## Edit project cluster[](#edit-project-cluster "Permalink") + +更新现有项目集群. + +``` +PUT /projects/:id/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 认证用户拥有的项目的 ID | +| `cluster_id` | integer | yes | 集群的 ID | +| `name` | string | no | 集群名称 | +| `domain` | string | no | 集群的[基础域](../user/project/clusters/index.html#base-domain) | +| `management_project_id` | integer | no | 集群[管理项目](../user/clusters/management_project.html)的 ID | +| `platform_kubernetes_attributes[api_url]` | string | no | 访问 Kubernetes API 的 URL | +| `platform_kubernetes_attributes[token]` | string | no | 针对 Kubernetes 进行身份验证的令牌 | +| `platform_kubernetes_attributes[ca_cert]` | string | no | TLS 证书. 如果 API 使用自签名 TLS 证书,则为必填. | +| `platform_kubernetes_attributes[namespace]` | string | no | 与项目相关的唯一名称空间 | +| `environment_scope` | string | no | 集群的关联环境 | + +**注意:**仅通过["添加现有 Kubernetes 群集"](../user/project/clusters/add_remove_clusters.html#add-existing-cluster)选项或通过["将现有群集添加到项目"](#add-existing-cluster-to-project)端点[添加群集时,](#add-existing-cluster-to-project)才能更新`name` , `api_url` , `ca_cert`和`token` . + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/projects/26/clusters/24" \ +-H "Content-Type:application/json" \ +-X PUT --data '{"name":"new-cluster-name","domain":"new-domain.com","api_url":"https://new-api-url.com"}' +``` + +响应示例: + +``` +{ "id":24, "name":"new-cluster-name", "domain":"new-domain.com", "created_at":"2019-01-03T21:53:40.610Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"project_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://new-api-url.com", "namespace":"cluster-5-namespace", "authorization_type":"rbac", "ca_cert":null }, "management_project": { "id":2, "description":null, "name":"project2", "name_with_namespace":"John Doe8 / project2", "path":"project2", "path_with_namespace":"namespace2/project2", "created_at":"2019-10-11T02:55:54.138Z" }, "project": { "id":26, "description":"", "name":"project-with-clusters-api", "name_with_namespace":"Administrator / project-with-clusters-api", "path":"project-with-clusters-api", "path_with_namespace":"root/project-with-clusters-api", "created_at":"2019-01-02T20:13:32.600Z", "default_branch":null, "tag_list":[], "ssh_url_to_repo":"ssh:://gitlab.example.com/root/project-with-clusters-api.git", "http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git", "web_url":"https://gitlab.example.com/root/project-with-clusters-api", "readme_url":null, "avatar_url":null, "star_count":0, "forks_count":0, "last_activity_at":"2019-01-02T20:13:32.600Z", "namespace": { "id":1, "name":"root", "path":"root", "kind":"user", "full_path":"root", "parent_id":null } } } +``` + +## Delete project cluster[](#delete-project-cluster "Permalink") + +删除现有项目集群. + +``` +DELETE /projects/:id/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 认证用户拥有的项目的 ID | +| `cluster_id` | integer | yes | 集群的 ID | + +请求示例: + +``` +curl --request DELETE --header "Private-Token: " "https://gitlab.example.com/api/v4/projects/26/clusters/23" +``` \ No newline at end of file diff --git a/docs/299.md b/docs/299.md new file mode 100644 index 0000000000000000000000000000000000000000..21aba4164edbe858cc8de7abde9a9d323194a33a --- /dev/null +++ b/docs/299.md @@ -0,0 +1,166 @@ +# Group clusters API + +> 原文:[https://docs.gitlab.com/ee/api/group_clusters.html](https://docs.gitlab.com/ee/api/group_clusters.html) + +* [List group clusters](#list-group-clusters) +* [Get a single group cluster](#get-a-single-group-cluster) +* [Add existing cluster to group](#add-existing-cluster-to-group) +* [Edit group cluster](#edit-group-cluster) +* [Delete group cluster](#delete-group-cluster) + +# Group clusters API[](#group-clusters-api "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30213) . + +**注意:组**将至少需要用户具有维护者访问权限才能使用这些端点. + +## List group clusters[](#list-group-clusters "Permalink") + +返回组集群的列表. + +``` +GET /groups/:id/clusters +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/groups/26/clusters" +``` + +响应示例: + +``` +[ { "id":18, "name":"cluster-1", "domain":"example.com", "created_at":"2019-01-02T20:18:12.563Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"group_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://104.197.68.152", "authorization_type":"rbac", "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----" }, "management_project": { "id":2, "description":null, "name":"project2", "name_with_namespace":"John Doe8 / project2", "path":"project2", "path_with_namespace":"namespace2/project2", "created_at":"2019-10-11T02:55:54.138Z" } }, { "id":19, "name":"cluster-2", ... } ] +``` + +## Get a single group cluster[](#get-a-single-group-cluster "Permalink") + +获取单个组集群. + +``` +GET /groups/:id/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cluster_id` | integer | yes | 集群的 ID | + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/groups/26/clusters/18" +``` + +响应示例: + +``` +{ "id":18, "name":"cluster-1", "domain":"example.com", "created_at":"2019-01-02T20:18:12.563Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"group_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://104.197.68.152", "authorization_type":"rbac", "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----" }, "management_project": { "id":2, "description":null, "name":"project2", "name_with_namespace":"John Doe8 / project2", "path":"project2", "path_with_namespace":"namespace2/project2", "created_at":"2019-10-11T02:55:54.138Z" }, "group": { "id":26, "name":"group-with-clusters-api", "web_url":"https://gitlab.example.com/group-with-clusters-api" } } +``` + +## Add existing cluster to group[](#add-existing-cluster-to-group "Permalink") + +将现有的 Kubernetes 集群添加到组中. + +``` +POST /groups/:id/clusters/user +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 集群名称 | +| `domain` | string | no | 集群的[基础域](../user/group/clusters/index.html#base-domain) | +| `management_project_id` | integer | no | 集群[管理项目](../user/clusters/management_project.html)的 ID | +| `enabled` | boolean | no | 确定集群是否处于活动状态,默认为 true | +| `managed` | boolean | no | 确定 GitLab 是否将管理该集群的名称空间和服务帐户,默认为 true | +| `platform_kubernetes_attributes[api_url]` | string | yes | 访问 Kubernetes API 的 URL | +| `platform_kubernetes_attributes[token]` | string | yes | 针对 Kubernetes 进行身份验证的令牌 | +| `platform_kubernetes_attributes[ca_cert]` | string | no | TLS 证书. 如果 API 使用自签名 TLS 证书,则为必填. | +| `platform_kubernetes_attributes[authorization_type]` | string | no | 集群授权类型: `rbac` , `abac`或`unknown_authorization` . 默认为`rbac` . | +| `environment_scope` | string | no | 集群的关联环境. 默认为`*` | + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/groups/26/clusters/user" \ +-H "Accept: application/json" \ +-H "Content-Type:application/json" \ +--request POST --data '{"name":"cluster-5", "platform_kubernetes_attributes":{"api_url":"https://35.111.51.20","token":"12345","ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----"}}' +``` + +响应示例: + +``` +{ "id":24, "name":"cluster-5", "created_at":"2019-01-03T21:53:40.610Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"group_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://35.111.51.20", "authorization_type":"rbac", "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----" }, "management_project":null, "group": { "id":26, "name":"group-with-clusters-api", "web_url":"https://gitlab.example.com/root/group-with-clusters-api" } } +``` + +## Edit group cluster[](#edit-group-cluster "Permalink") + +更新现有的组群集. + +``` +PUT /groups/:id/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cluster_id` | integer | yes | 集群的 ID | +| `name` | string | no | 集群名称 | +| `domain` | string | no | 集群的[基础域](../user/group/clusters/index.html#base-domain) | +| `management_project_id` | integer | no | 集群[管理项目](../user/clusters/management_project.html)的 ID | +| `platform_kubernetes_attributes[api_url]` | string | no | 访问 Kubernetes API 的 URL | +| `platform_kubernetes_attributes[token]` | string | no | 针对 Kubernetes 进行身份验证的令牌 | +| `platform_kubernetes_attributes[ca_cert]` | string | no | TLS 证书. 如果 API 使用自签名 TLS 证书,则为必填. | +| `environment_scope` | string | no | 集群的关联环境 | + +**注意:**仅通过["添加现有 Kubernetes 群集"](../user/project/clusters/add_remove_clusters.html#add-existing-cluster)选项或通过["将现有群集添加到组"](#add-existing-cluster-to-group)端点[添加群集时,](#add-existing-cluster-to-group)才能更新`name` , `api_url` , `ca_cert`和`token` . + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/groups/26/clusters/24" \ +-H "Content-Type:application/json" \ +--request PUT --data '{"name":"new-cluster-name","domain":"new-domain.com","api_url":"https://new-api-url.com"}' +``` + +响应示例: + +``` +{ "id":24, "name":"new-cluster-name", "domain":"new-domain.com", "created_at":"2019-01-03T21:53:40.610Z", "provider_type":"user", "platform_type":"kubernetes", "environment_scope":"*", "cluster_type":"group_type", "user": { "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..", "web_url":"https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url":"https://new-api-url.com", "authorization_type":"rbac", "ca_cert":null }, "management_project": { "id":2, "description":null, "name":"project2", "name_with_namespace":"John Doe8 / project2", "path":"project2", "path_with_namespace":"namespace2/project2", "created_at":"2019-10-11T02:55:54.138Z" }, "group": { "id":26, "name":"group-with-clusters-api", "web_url":"https://gitlab.example.com/group-with-clusters-api" } } +``` + +## Delete group cluster[](#delete-group-cluster "Permalink") + +删除现有的组群集. + +``` +DELETE /groups/:id/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cluster_id` | integer | yes | 集群的 ID | + +请求示例: + +``` +curl --request DELETE --header "Private-Token: " "https://gitlab.example.com/api/v4/groups/26/clusters/23" +``` \ No newline at end of file diff --git a/docs/300.md b/docs/300.md new file mode 100644 index 0000000000000000000000000000000000000000..03badc2b38ab4b5937b6ab437296ead554f41df4 --- /dev/null +++ b/docs/300.md @@ -0,0 +1,161 @@ +# Instance clusters API + +> 原文:[https://docs.gitlab.com/ee/api/instance_clusters.html](https://docs.gitlab.com/ee/api/instance_clusters.html) + +* [List instance clusters](#list-instance-clusters) +* [Get a single instance cluster](#get-a-single-instance-cluster) +* [Add existing instance cluster](#add-existing-instance-cluster) +* [Edit instance cluster](#edit-instance-cluster) +* [Delete instance cluster](#delete-instance-cluster) + +# Instance clusters API[](#instance-clusters-api "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36001) . + +**注意:**用户将需要管理员权限才能使用这些端点. + +将这些 API 端点与实例集群一起使用,使您可以在多个项目中使用同一集群. [更多信息](../user/instance/clusters/index.html) + +## List instance clusters[](#list-instance-clusters "Permalink") + +返回实例集群的列表. + +``` +GET /admin/clusters +``` + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/admin/clusters" +``` + +响应示例: + +``` +[ { "id": 9, "name": "cluster-1", "created_at": "2020-07-14T18:36:10.440Z", "domain": null, "provider_type": "user", "platform_type": "kubernetes", "environment_scope": "*", "cluster_type": "instance_type", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url": "https://example.com", "namespace": null, "authorization_type": "rbac", "ca_cert":"-----BEGIN CERTIFICATE-----IxMDM1MV0ZDJkZjM...-----END CERTIFICATE-----" }, "provider_gcp": null, "management_project": null }, { "id": 10, "name": "cluster-2", "created_at": "2020-07-14T18:39:05.383Z", "domain": null, "provider_type": "user", "platform_type": "kubernetes", "environment_scope": "staging", "cluster_type": "instance_type", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url": "https://example.com", "namespace": null, "authorization_type": "rbac", "ca_cert":"-----BEGIN CERTIFICATE-----LzEtMCadtaLGxcsGAZjM...-----END CERTIFICATE-----" }, "provider_gcp": null, "management_project": null } { "id": 11, "name": "cluster-3", ... } ] +``` + +## Get a single instance cluster[](#get-a-single-instance-cluster "Permalink") + +返回单个实例集群. + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `cluster_id` | integer | yes | 集群的 ID | + +``` +GET /admin/clusters/:cluster_id +``` + +请求示例: + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/admin/clusters/9" +``` + +响应示例: + +``` +{ "id": 9, "name": "cluster-1", "created_at": "2020-07-14T18:36:10.440Z", "domain": null, "provider_type": "user", "platform_type": "kubernetes", "environment_scope": "*", "cluster_type": "instance_type", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url": "https://example.com", "namespace": null, "authorization_type": "rbac", "ca_cert":"-----BEGIN CERTIFICATE-----IxMDM1MV0ZDJkZjM...-----END CERTIFICATE-----" }, "provider_gcp": null, "management_project": null } +``` + +## Add existing instance cluster[](#add-existing-instance-cluster "Permalink") + +添加现有的 Kubernetes 实例集群. + +``` +POST /admin/clusters/add +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | string | yes | 集群名称 | +| `domain` | string | no | 集群的[基础域](../user/project/clusters/index.html#base-domain) | +| `environment_scope` | string | no | 集群的关联环境. 默认为`*` | +| `management_project_id` | integer | no | The ID of the [management project](../user/clusters/management_project.html) for the cluster | +| `enabled` | boolean | no | 确定集群是否处于活动状态,默认为 true | +| `managed` | boolean | no | 确定 GitLab 是否将管理该集群的名称空间和服务帐户,默认为 true | +| `platform_kubernetes_attributes[api_url]` | string | yes | 访问 Kubernetes API 的 URL | +| `platform_kubernetes_attributes[token]` | string | yes | 针对 Kubernetes 进行身份验证的令牌 | +| `platform_kubernetes_attributes[ca_cert]` | string | no | TLS 证书. 如果 API 使用自签名 TLS 证书,则为必填. | +| `platform_kubernetes_attributes[namespace]` | string | no | 与项目相关的唯一名称空间 | +| `platform_kubernetes_attributes[authorization_type]` | string | no | 集群授权类型: `rbac` , `abac`或`unknown_authorization` . 默认为`rbac` . | + +请求示例: + +``` +curl --header "Private-Token:" "http://gitlab.example.com/api/v4/admin/clusters/add" \ +-H "Accept:application/json" \ +-H "Content-Type:application/json" \ +-X POST --data '{"name":"cluster-3", "environment_scope":"production", "platform_kubernetes_attributes":{"api_url":"https://example.com", "token":"12345", "ca_cert":"-----BEGIN CERTIFICATE-----qpoeiXXZafCM0ZDJkZjM...-----END CERTIFICATE-----"}}' +``` + +响应示例: + +``` +{ "id": 11, "name": "cluster-3", "created_at": "2020-07-14T18:42:50.805Z", "domain": null, "provider_type": "user", "platform_type": "kubernetes", "environment_scope": "production", "cluster_type": "instance_type", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com:3000/root" }, "platform_kubernetes": { "api_url": "https://example.com", "namespace": null, "authorization_type": "rbac", "ca_cert":"-----BEGIN CERTIFICATE-----qpoeiXXZafCM0ZDJkZjM...-----END CERTIFICATE-----" }, "provider_gcp": null, "management_project": null } +``` + +## Edit instance cluster[](#edit-instance-cluster "Permalink") + +更新现有的实例集群. + +``` +PUT /admin/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `cluster_id` | integer | yes | 集群的 ID | +| `name` | string | no | 集群名称 | +| `domain` | string | no | 集群的[基础域](../user/project/clusters/index.html#base-domain) | +| `environment_scope` | string | no | 集群的关联环境 | +| `management_project_id` | integer | no | 集群[管理项目](../user/clusters/management_project.html)的 ID | +| `enabled` | boolean | no | 确定集群是否处于活动状态,默认为 true | +| `platform_kubernetes_attributes[api_url]` | string | no | 访问 Kubernetes API 的 URL | +| `platform_kubernetes_attributes[token]` | string | no | 针对 Kubernetes 进行身份验证的令牌 | +| `platform_kubernetes_attributes[ca_cert]` | string | no | TLS 证书. 如果 API 使用自签名 TLS 证书,则为必填. | +| `platform_kubernetes_attributes[namespace]` | string | no | 与项目相关的唯一名称空间 | + +**注意:**仅通过通过[添加现有 Kubernetes 集群](../user/project/clusters/add_remove_clusters.html#add-existing-cluster)选项或通过[添加现有实例集群](#add-existing-instance-cluster)端点[添加](#add-existing-instance-cluster)集群时,才能更新`name` , `api_url` , `ca_cert`和`token` . + +请求示例: + +``` +curl --header "Private-Token: " "http://gitlab.example.com/api/v4/admin/clusters/9" \ +-H "Content-Type:application/json" \ +-X PUT --data '{"name":"update-cluster-name", "platform_kubernetes_attributes":{"api_url":"https://new-example.com","token":"new-token"}}' +``` + +响应示例: + +``` +{ "id": 9, "name": "update-cluster-name", "created_at": "2020-07-14T18:36:10.440Z", "domain": null, "provider_type": "user", "platform_type": "kubernetes", "environment_scope": "*", "cluster_type": "instance_type", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "platform_kubernetes": { "api_url": "https://new-example.com", "namespace": null, "authorization_type": "rbac", "ca_cert":"-----BEGIN CERTIFICATE-----IxMDM1MV0ZDJkZjM...-----END CERTIFICATE-----" }, "provider_gcp": null, "management_project": null, "project": null } +``` + +## Delete instance cluster[](#delete-instance-cluster "Permalink") + +删除现有的实例集群. + +``` +DELETE /admin/clusters/:cluster_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `cluster_id` | integer | yes | 集群的 ID | + +请求示例: + +``` +curl --request DELETE --header "Private-Token: " "https://gitlab.example.com/api/v4/admin/clusters/11" +``` \ No newline at end of file diff --git a/docs/301.md b/docs/301.md new file mode 100644 index 0000000000000000000000000000000000000000..ef16eb6110474bc010f6716322e676df2bc6792c --- /dev/null +++ b/docs/301.md @@ -0,0 +1,514 @@ +# Commits API + +> 原文:[https://docs.gitlab.com/ee/api/commits.html](https://docs.gitlab.com/ee/api/commits.html) + +* [List repository commits](#list-repository-commits) +* [Create a commit with multiple files and actions](#create-a-commit-with-multiple-files-and-actions) +* [Get a single commit](#get-a-single-commit) +* [Get references a commit is pushed to](#get-references-a-commit-is-pushed-to) +* [Cherry pick a commit](#cherry-pick-a-commit) +* [Revert a commit](#revert-a-commit) +* [Get the diff of a commit](#get-the-diff-of-a-commit) +* [Get the comments of a commit](#get-the-comments-of-a-commit) +* [Post comment to commit](#post-comment-to-commit) +* [Get the discussions of a commit](#get-the-discussions-of-a-commit) +* [Commit status](#commit-status) + * [List the statuses of a commit](#list-the-statuses-of-a-commit) + * [Post the build status to a commit](#post-the-build-status-to-a-commit) +* [List Merge Requests associated with a commit](#list-merge-requests-associated-with-a-commit) +* [Get GPG signature of a commit](#get-gpg-signature-of-a-commit) + +# Commits API[](#commits-api "Permalink") + +## List repository commits[](#list-repository-commits "Permalink") + +获取项目中存储库提交的列表. + +``` +GET /projects/:id/repository/commits +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `ref_name` | string | no | 存储库分支的名称,标签或修订范围,或者如果未提供默认分支 | +| `since` | string | no | 仅此日期之后的提交将以 ISO 8601 格式返回 YYYY-MM-DDTHH:MM:SSZ | +| `until` | string | no | 仅在此日期之前或当天的提交将以 ISO 8601 格式返回 YYYY-MM-DDTHH:MM:SSZ | +| `path` | string | no | 文件路径 | +| `all` | boolean | no | 从存储库中检索每个提交 | +| `with_stats` | boolean | no | 有关每次提交的统计信息将添加到响应中 | +| `first_parent` | boolean | no | 看到合并提交后,仅关注第一个父提交 | +| `order` | string | no | 按顺序列出提交. 可能的值: `default` , [`topo`](https://git-scm.com/docs/git-log#Documentation/git-log.txt---topo-order) . 默认设置为`default` ,提交按时间倒序显示. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits" +``` + +响应示例: + +``` +[ { "id": "ed899a2f4b50b4370feeea94676502b42383c746", "short_id": "ed899a2f4b5", "title": "Replace sanitize with escape once", "author_name": "Example User", "author_email": "user@example.com", "authored_date": "2012-09-20T11:50:22+03:00", "committer_name": "Administrator", "committer_email": "admin@example.com", "committed_date": "2012-09-20T11:50:22+03:00", "created_at": "2012-09-20T11:50:22+03:00", "message": "Replace sanitize with escape once", "parent_ids": [ "6104942438c14ec7bd21c6cd5bd995272b3faff6" ], "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746" }, { "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", "short_id": "6104942438c", "title": "Sanitize for network graph", "author_name": "randx", "author_email": "user@example.com", "committer_name": "ExampleName", "committer_email": "user@example.com", "created_at": "2012-09-20T09:06:12+03:00", "message": "Sanitize for network graph", "parent_ids": [ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" ], "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746" } ] +``` + +## Create a commit with multiple files and actions[](#create-a-commit-with-multiple-files-and-actions "Permalink") + +在 GitLab 8.13 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6096) . + +通过发布 JSON 有效负载来创建提交 + +``` +POST /projects/:id/repository/commits +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `branch` | string | yes | 要提交的分支名称. 要创建一个新分支,还提供`start_branch`或`start_sha` ,还可以提供`start_project` . | +| `commit_message` | string | yes | 提交讯息 | +| `start_branch` | string | no | 从中开始新分支的分支名称 | +| `start_sha` | string | no | 从以下位置启动新分支的提交的 SHA | +| `start_project` | integer/string | no | 从中开始新分支的项目 ID 或项目的[URL 编码路径](README.html#namespaced-path-encoding) . 默认为`id`的值. | +| `actions[]` | array | yes | 动作哈希数组要批量提交. 请参阅下表以了解它可以采用的属性. | +| `author_email` | string | no | 指定提交作者的电子邮件地址 | +| `author_name` | string | no | 指定提交作者的姓名 | +| `stats` | boolean | no | 包括提交统计信息. 默认为 true | +| `force` | boolean | no | 如果为`true`则基于`start_branch`或`start_sha`的新提交覆盖目标分支 | + +| `actions[]` Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `action` | string | yes | 执行, `create` , `delete` , `move` , `update` , `chmod` | +| `file_path` | string | yes | 文件的完整路径. 例如 `lib/class.rb` | +| `previous_path` | string | no | 要移动文件的原始完整路径. 例如 `lib/class1.rb` . 仅考虑`move`动作. | +| `content` | string | no | 除`delete` , `chmod`和`move`以外的所有文件所必需的文件内容. 未指定`content`移动动作将保留现有文件内容,而任何其他`content`值都将覆盖文件内容. | +| `encoding` | string | no | `text`或`base64` . `text`是默认值. | +| `last_commit_id` | string | no | 上次已知的文件提交 ID. 仅在更新,移动和删除操作中考虑. | +| `execute_filemode` | boolean | no | 当为`true/false`启用/禁用文件上的 execute 标志. 仅考虑用于`chmod`操作. | + +``` +PAYLOAD=$(cat << 'JSON' +{ + "branch": "master", + "commit_message": "some commit message", + "actions": [ + { + "action": "create", + "file_path": "foo/bar", + "content": "some content" + }, + { + "action": "delete", + "file_path": "foo/bar2" + }, + { + "action": "move", + "file_path": "foo/bar3", + "previous_path": "foo/bar4", + "content": "some content" + }, + { + "action": "update", + "file_path": "foo/bar5", + "content": "new content" + }, + { + "action": "chmod", + "file_path": "foo/bar5", + "execute_filemode": true + } + ] +} JSON ) +curl --request POST --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" --data "$PAYLOAD" "https://gitlab.example.com/api/v4/projects/1/repository/commits" +``` + +响应示例: + +``` +{ "id": "ed899a2f4b50b4370feeea94676502b42383c746", "short_id": "ed899a2f4b5", "title": "some commit message", "author_name": "Example User", "author_email": "user@example.com", "committer_name": "Example User", "committer_email": "user@example.com", "created_at": "2016-09-20T09:26:24.000-07:00", "message": "some commit message", "parent_ids": [ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" ], "committed_date": "2016-09-20T09:26:24.000-07:00", "authored_date": "2016-09-20T09:26:24.000-07:00", "stats": { "additions": 2, "deletions": 2, "total": 4 }, "status": null, "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746" } +``` + +GitLab 支持[表单编码](README.html#encoding-api-parameters-of-array-and-hash-types) . 以下是使用 Commit API 和表单编码的示例: + +``` +curl --request POST \ + --form "branch=master" \ + --form "commit_message=some commit message" \ + --form "start_branch=master" \ + --form "actions[][action]=create" \ + --form "actions[][file_path]=foo/bar" \ + --form "actions[][content]=" \ + "https://gitlab.example.com/api/v4/projects/1/repository/commits" +``` + +## Get a single commit[](#get-a-single-commit "Permalink") + +获取由提交哈希或分支或标记的名称标识的特定提交. + +``` +GET /projects/:id/repository/commits/:sha +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希或存储库分支或标记的名称 | +| `stats` | boolean | no | 包括提交统计信息. 默认为 true | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits/master" +``` + +响应示例: + +``` +{ "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", "short_id": "6104942438c", "title": "Sanitize for network graph", "author_name": "randx", "author_email": "user@example.com", "committer_name": "Dmitriy", "committer_email": "user@example.com", "created_at": "2012-09-20T09:06:12+03:00", "message": "Sanitize for network graph", "committed_date": "2012-09-20T09:06:12+03:00", "authored_date": "2012-09-20T09:06:12+03:00", "parent_ids": [ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" ], "last_pipeline" : { "id": 8, "ref": "master", "sha": "2dc6aa325a317eda67812f05600bdf0fcdc70ab0", "status": "created" }, "stats": { "additions": 15, "deletions": 10, "total": 25 }, "status": "running", "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/6104942438c14ec7bd21c6cd5bd995272b3faff6" } +``` + +## Get references a commit is pushed to[](#get-references-a-commit-is-pushed-to "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15026) + +获取提交已提交的所有引用(从分支或标签). 分页参数`page`和`per_page`可用于限制引用列表. + +``` +GET /projects/:id/repository/commits/:sha/refs +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希 | +| `type` | string | no | 提交范围. 可能的值是`branch` , `tag` , `all` . 默认为`all` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits/5937ac0a7beb003549fc5fd26fc247adbce4a52e/refs?type=all" +``` + +Example response: + +``` +[ {"type": "branch", "name": "'test'"}, {"type": "branch", "name": "add-balsamiq-file"}, {"type": "branch", "name": "wip"}, {"type": "tag", "name": "v1.1.0"} ] +``` + +## Cherry pick a commit[](#cherry-pick-a-commit "Permalink") + +在 GitLab 8.15 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8047) . + +Cherry 选择了对给定分支的提交. + +``` +POST /projects/:id/repository/commits/:sha/cherry_pick +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希 | +| `branch` | string | yes | 分支名称 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/cherry_pick" +``` + +响应示例: + +``` +{ "id": "8b090c1b79a14f2bd9e8a738f717824ff53aebad", "short_id": "8b090c1b", "title": "Feature added", "author_name": "Example User", "author_email": "user@example.com", "authored_date": "2016-12-12T20:10:39.000+01:00", "created_at": "2016-12-12T20:10:39.000+01:00", "committer_name": "Administrator", "committer_email": "admin@example.com", "committed_date": "2016-12-12T20:10:39.000+01:00", "title": "Feature added", "message": "Feature added\n\nSigned-off-by: Example User \n", "parent_ids": [ "a738f717824ff53aebad8b090c1b79a14f2bd9e8" ], "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/8b090c1b79a14f2bd9e8a738f717824ff53aebad" } +``` + +如果选择失败,响应将提供有关以下原因的上下文: + +``` +{ "message": "Sorry, we cannot cherry-pick this commit automatically. This commit may already have been cherry-picked, or a more recent commit may have updated some of its content.", "error_code": "empty" } +``` + +在这种情况下,cherry-pick 失败,因为变更集为空,并且很可能表明提交已存在于目标分支中. 另一个可能的错误代码是`conflict` ,表示存在合并冲突. + +## Revert a commit[](#revert-a-commit "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22919) . + +恢复给定分支中的提交. + +``` +POST /projects/:id/repository/commits/:sha/revert +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交 SHA 还原 | +| `branch` | string | yes | 目标分支名称 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/a738f717824ff53aebad8b090c1b79a14f2bd9e8/revert" +``` + +响应示例: + +``` +{ "id":"8b090c1b79a14f2bd9e8a738f717824ff53aebad", "short_id": "8b090c1b", "title":"Revert \"Feature added\"", "created_at":"2018-11-08T15:55:26.000Z", "parent_ids":["a738f717824ff53aebad8b090c1b79a14f2bd9e8"], "message":"Revert \"Feature added\"\n\nThis reverts commit a738f717824ff53aebad8b090c1b79a14f2bd9e8", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2018-11-08T15:55:26.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2018-11-08T15:55:26.000Z", "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/8b090c1b79a14f2bd9e8a738f717824ff53aebad" } +``` + +如果还原失败,则响应将提供有关以下原因的上下文: + +``` +{ "message": "Sorry, we cannot revert this commit automatically. This commit may already have been reverted, or a more recent commit may have updated some of its content.", "error_code": "conflict" } +``` + +在这种情况下,还原失败,因为尝试的还原产生了合并冲突. 另一个可能的错误代码为`empty` ,表明变更集为空,这可能是由于变更已被还原. + +## Get the diff of a commit[](#get-the-diff-of-a-commit "Permalink") + +获取项目中提交的差异. + +``` +GET /projects/:id/repository/commits/:sha/diff +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希或存储库分支或标记的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/diff" +``` + +响应示例: + +``` +[ { "diff": "--- a/doc/update/5.4-to-6.0.md\n+++ b/doc/update/5.4-to-6.0.md\n@@ -71,6 +71,8 @@\n sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production\n sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production\n \n+sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production\n+\n ```\n \n ### 6\. Update config files", "new_path": "doc/update/5.4-to-6.0.md", "old_path": "doc/update/5.4-to-6.0.md", "a_mode": null, "b_mode": "100644", "new_file": false, "renamed_file": false, "deleted_file": false } ] +``` + +## Get the comments of a commit[](#get-the-comments-of-a-commit "Permalink") + +获取项目中提交的注释. + +``` +GET /projects/:id/repository/commits/:sha/comments +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希或存储库分支或标记的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/comments" +``` + +响应示例: + +``` +[ { "note": "this code is really nice", "author": { "id": 11, "username": "admin", "email": "admin@local.host", "name": "Administrator", "state": "active", "created_at": "2014-03-06T08:17:35.000Z" } } ] +``` + +## Post comment to commit[](#post-comment-to-commit "Permalink") + +在提交中添加评论. + +为了在特定文件的特定行中发布评论,您必须指定完整的提交 SHA, `path` , `line`和`line_type`应该是`new` . + +如果以下至少一种情况有效,则注释将在最后一次提交的末尾添加: + +* 相反, `sha`是分支或标签,并且`line`或`path`无效 +* `line`号无效(不存在) +* `path`无效(不存在) + +在上述任何情况下, `line` , `line_type`和`path`的响应都设置为`null` . + +``` +POST /projects/:id/repository/commits/:sha/comments +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交 SHA 或存储库分支或标记的名称 | +| `note` | string | yes | 评论文字 | +| `path` | string | no | 相对于存储库的文件路径 | +| `line` | integer | no | 放置评论的行号 | +| `line_type` | string | no | 线型. 采用`new`或`old`的争论 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "note=Nice picture man\!" --form "path=dudeism.md" --form "line=11" --form "line_type=new" "https://gitlab.example.com/api/v4/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/comments" +``` + +响应示例: + +``` +{ "author" : { "web_url" : "https://gitlab.example.com/thedude", "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png", "username" : "thedude", "state" : "active", "name" : "Jeff Lebowski", "id" : 28 }, "created_at" : "2016-01-19T09:44:55.600Z", "line_type" : "new", "path" : "dudeism.md", "line" : 11, "note" : "Nice picture man!" } +``` + +## Get the discussions of a commit[](#get-the-discussions-of-a-commit "Permalink") + +获取项目中提交的讨论. + +``` +GET /projects/:id/repository/commits/:sha/discussions +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希或存储库分支或标记的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits/4604744a1c64de00ff62e1e8a6766919923d2b41/discussions" +``` + +响应示例: + +``` +[ { "id": "4604744a1c64de00ff62e1e8a6766919923d2b41", "individual_note": true, "notes": [ { "id": 334686748, "type": null, "body": "I'm the Dude, so that's what you call me.", "attachment": null, "author" : { "id" : 28, "name" : "Jeff Lebowski", "username" : "thedude", "web_url" : "https://gitlab.example.com/thedude", "state" : "active", "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png" }, "created_at": "2020-04-30T18:48:11.432Z", "updated_at": "2020-04-30T18:48:11.432Z", "system": false, "noteable_id": null, "noteable_type": "Commit", "resolvable": false, "confidential": null, "noteable_iid": null, "commands_changes": {} } ] } ] +``` + +## Commit status[](#commit-status "Permalink") + +从 GitLab 8.1 开始,这是新的提交状态 API. + +### List the statuses of a commit[](#list-the-statuses-of-a-commit "Permalink") + +列出项目中提交的状态. 分页参数`page`和`per_page`可用于限制引用列表. + +``` +GET /projects/:id/repository/commits/:sha/statuses +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交 SHA | +| `ref` | string | no | The name of a repository branch or tag or, if not given, the default branch | +| `stage` | string | no | 按[构建阶段](../ci/yaml/README.html#stages)过滤,例如`test` | +| `name` | string | no | 按[工作名称](../ci/yaml/README.html#introduction)过滤,例如`bundler:audit` | +| `all` | boolean | no | 返回所有状态,不仅是最新状态 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/statuses +``` + +响应示例: + +``` +[ ... { "status" : "pending", "created_at" : "2016-01-19T08:40:25.934Z", "started_at" : null, "name" : "bundler:audit", "allow_failure" : true, "author" : { "username" : "thedude", "state" : "active", "web_url" : "https://gitlab.example.com/thedude", "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png", "id" : 28, "name" : "Jeff Lebowski" }, "description" : null, "sha" : "18f3e63d05582537db6d183d9d557be09e1f90c8", "target_url" : "https://gitlab.example.com/thedude/gitlab-foss/builds/91", "finished_at" : null, "id" : 91, "ref" : "master" }, { "started_at" : null, "name" : "test", "allow_failure" : false, "status" : "pending", "created_at" : "2016-01-19T08:40:25.832Z", "target_url" : "https://gitlab.example.com/thedude/gitlab-foss/builds/90", "id" : 90, "finished_at" : null, "ref" : "master", "sha" : "18f3e63d05582537db6d183d9d557be09e1f90c8", "author" : { "id" : 28, "name" : "Jeff Lebowski", "username" : "thedude", "web_url" : "https://gitlab.example.com/thedude", "state" : "active", "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png" }, "description" : null }, ... ] +``` + +### Post the build status to a commit[](#post-the-build-status-to-a-commit "Permalink") + +添加或更新提交的构建状态. + +``` +POST /projects/:id/statuses/:sha +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交 SHA | +| `state` | string | yes | 状态的状态. 可以是以下之一: `pending` , `running` , `success` , `failed` , `canceled` | +| `ref` | string | no | 状态所`ref` (分支或标签) | +| `name` or `context` | string | no | 区分此状态和其他系统状态的标签. 默认值是`default` | +| `target_url` | string | no | 与该状态关联的目标 URL | +| `description` | string | no | 状态的简短描述 | +| `coverage` | float | no | 总代码覆盖率 | +| `pipeline_id` | integer | no | 要设置状态的管道的 ID. 在同一 SHA 上有多个管道的情况下使用. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/17/statuses/18f3e63d05582537db6d183d9d557be09e1f90c8?state=success" +``` + +响应示例: + +``` +{ "author" : { "web_url" : "https://gitlab.example.com/thedude", "name" : "Jeff Lebowski", "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png", "username" : "thedude", "state" : "active", "id" : 28 }, "name" : "default", "sha" : "18f3e63d05582537db6d183d9d557be09e1f90c8", "status" : "success", "coverage": 100.0, "description" : null, "id" : 93, "target_url" : null, "ref" : null, "started_at" : null, "created_at" : "2016-01-19T09:05:50.355Z", "allow_failure" : false, "finished_at" : "2016-01-19T09:05:50.365Z" } +``` + +## List Merge Requests associated with a commit[](#list-merge-requests-associated-with-a-commit "Permalink") + +在 GitLab 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18004) . + +获取与指定提交相关的合并请求列表. + +``` +GET /projects/:id/repository/commits/:sha/merge_requests +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交 SHA | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/commits/af5b13261899fb2c0db30abdd0af8b07cb44fdc5/merge_requests" +``` + +响应示例: + +``` +[ { "id":45, "iid":1, "project_id":35, "title":"Add new file", "description":"", "state":"opened", "created_at":"2018-03-26T17:26:30.916Z", "updated_at":"2018-03-26T17:26:30.916Z", "target_branch":"master", "source_branch":"test-branch", "upvotes":0, "downvotes":0, "author" : { "web_url" : "https://gitlab.example.com/thedude", "name" : "Jeff Lebowski", "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png", "username" : "thedude", "state" : "active", "id" : 28 }, "assignee":null, "source_project_id":35, "target_project_id":35, "labels":[ ], "work_in_progress":false, "milestone":null, "merge_when_pipeline_succeeds":false, "merge_status":"can_be_merged", "sha":"af5b13261899fb2c0db30abdd0af8b07cb44fdc5", "merge_commit_sha":null, "squash_commit_sha":null, "user_notes_count":0, "discussion_locked":null, "should_remove_source_branch":null, "force_remove_source_branch":false, "web_url":"http://https://gitlab.example.com/root/test-project/merge_requests/1", "time_stats":{ "time_estimate":0, "total_time_spent":0, "human_time_estimate":null, "human_total_time_spent":null } } ] +``` + +## Get GPG signature of a commit[](#get-gpg-signature-of-a-commit "Permalink") + +[从提交](../user/project/repository/gpg_signed_commits/index.html)获取[GPG 签名](../user/project/repository/gpg_signed_commits/index.html) (如果已签名). 对于未签名的提交,将导致 404 响应. + +``` +GET /projects/:id/repository/commits/:sha/signature +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `sha` | string | yes | 提交哈希或存储库分支或标记的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/repository/commits/da738facbc19eb2fc2cef57c49be0e6038570352/signature" +``` + +如果提交是由 GPG 签名的,则示例响应: + +``` +{ "signature_type": "PGP", "verification_status": "verified", "gpg_key_id": 1, "gpg_key_primary_keyid": "8254AAB3FBD54AC9", "gpg_key_user_name": "John Doe", "gpg_key_user_email": "johndoe@example.com", "gpg_key_subkey_id": null } +``` + +如果提交是 X.509 签名的示例响应: + +``` +{ "signature_type": "X509", "verification_status": "unverified", "x509_certificate": { "id": 1, "subject": "CN=gitlab@example.org,OU=Example,O=World", "subject_key_identifier": "BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC", "email": "gitlab@example.org", "serial_number": 278969561018901340486471282831158785578, "certificate_status": "good", "x509_issuer": { "id": 1, "subject": "CN=PKI,OU=Example,O=World", "subject_key_identifier": "AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB", "crl_url": "http://example.com/pki.crl" } } } +``` + +如果提交是未签名的,示例响应: + +``` +{ "message": "404 GPG Signature Not Found" } +``` \ No newline at end of file diff --git a/docs/302.md b/docs/302.md new file mode 100644 index 0000000000000000000000000000000000000000..8081312eb4a0b18d494f79578acaba93ef5406cc --- /dev/null +++ b/docs/302.md @@ -0,0 +1,218 @@ +# Container Registry API + +> 原文:[https://docs.gitlab.com/ee/api/container_registry.html](https://docs.gitlab.com/ee/api/container_registry.html) + +* [List registry repositories](#list-registry-repositories) + * [Within a project](#within-a-project) + * [Within a group](#within-a-group) +* [Delete registry repository](#delete-registry-repository) +* [List registry repository tags](#list-registry-repository-tags) + * [Within a project](#within-a-project-1) +* [Get details of a registry repository tag](#get-details-of-a-registry-repository-tag) +* [Delete a registry repository tag](#delete-a-registry-repository-tag) +* [Delete registry repository tags in bulk](#delete-registry-repository-tags-in-bulk) + +# Container Registry API[](#container-registry-api "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55978) . + +这是[GitLab 容器注册表](../user/packages/container_registry/index.html)的 API 文档. + +## List registry repositories[](#list-registry-repositories "Permalink") + +### Within a project[](#within-a-project "Permalink") + +获取项目中的注册表存储库列表. + +``` +GET /projects/:id/registry/repositories +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户可以访问[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `tags` | boolean | no | 如果参数包含为 true,则每个存储库在响应中都将包含一个`"tags"`数组. | +| `name` | string | no | 返回名称与值匹配的存储库列表. (在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29763) ). | +| `tags_count` | boolean | no | 如果参数包含为 true,则每个存储库的响应中都将包含`"tags_count"` (在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32141) ). | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories" +``` + +响应示例: + +``` +[ { "id": 1, "name": "", "path": "group/project", "project_id": 9, "location": "gitlab.example.com:5000/group/project", "created_at": "2019-01-10T13:38:57.391Z" }, { "id": 2, "name": "releases", "path": "group/project/releases", "project_id": 9, "location": "gitlab.example.com:5000/group/project/releases", "created_at": "2019-01-10T13:39:08.229Z" } ] +``` + +### Within a group[](#within-a-group "Permalink") + +获取组中的注册表存储库列表. + +``` +GET /groups/:id/registry/repositories +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户可以访问[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `tags` | boolean | no | 如果参数包含为 true,则每个存储库在响应中都将包含一个`"tags"`数组. | +| `name` | string | no | 返回名称与值匹配的存储库列表. (在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29763) ). | +| `tags_count` | boolean | no | 如果参数包含为 true,则每个存储库的响应中都将包含`"tags_count"` (在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32141) ). | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/2/registry/repositories?tags=1&tags_count=true" +``` + +响应示例: + +``` +[ { "id": 1, "name": "", "path": "group/project", "project_id": 9, "location": "gitlab.example.com:5000/group/project", "created_at": "2019-01-10T13:38:57.391Z", "tags_count": 1, "tags": [ { "name": "0.0.1", "path": "group/project:0.0.1", "location": "gitlab.example.com:5000/group/project:0.0.1" } ] }, { "id": 2, "name": "", "path": "group/other_project", "project_id": 11, "location": "gitlab.example.com:5000/group/other_project", "created_at": "2019-01-10T13:39:08.229Z", "tags_count": 3, "tags": [ { "name": "0.0.1", "path": "group/other_project:0.0.1", "location": "gitlab.example.com:5000/group/other_project:0.0.1" }, { "name": "0.0.2", "path": "group/other_project:0.0.2", "location": "gitlab.example.com:5000/group/other_project:0.0.2" }, { "name": "latest", "path": "group/other_project:latest", "location": "gitlab.example.com:5000/group/other_project:latest" } ] } ] +``` + +## Delete registry repository[](#delete-registry-repository "Permalink") + +删除注册表中的存储库. + +该操作是异步执行的,可能要花一些时间才能执行. + +``` +DELETE /projects/:id/registry/repositories/:repository_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.html#namespaced-path-encoding) owned by the authenticated user. | +| `repository_id` | integer | yes | 注册表存储库的标识. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2" +``` + +## List registry repository tags[](#list-registry-repository-tags "Permalink") + +### Within a project[](#within-a-project-1 "Permalink") + +获取给定注册表存储库的标签列表. + +``` +GET /projects/:id/registry/repositories/:repository_id/tags +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户可以访问[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `repository_id` | integer | yes | 注册表存储库的标识. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags" +``` + +响应示例: + +``` +[ { "name": "A", "path": "group/project:A", "location": "gitlab.example.com:5000/group/project:A" }, { "name": "latest", "path": "group/project:latest", "location": "gitlab.example.com:5000/group/project:latest" } ] +``` + +## Get details of a registry repository tag[](#get-details-of-a-registry-repository-tag "Permalink") + +获取注册表存储库标签的详细信息. + +``` +GET /projects/:id/registry/repositories/:repository_id/tags/:tag_name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户可以访问[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `repository_id` | integer | yes | 注册表存储库的标识. | +| `tag_name` | string | yes | 标签名称. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags/v10.0.0" +``` + +响应示例: + +``` +{ "name": "v10.0.0", "path": "group/project:latest", "location": "gitlab.example.com:5000/group/project:latest", "revision": "e9ed9d87c881d8c2fd3a31b41904d01ba0b836e7fd15240d774d811a1c248181", "short_revision": "e9ed9d87c", "digest": "sha256:c3490dcf10ffb6530c1303522a1405dfaf7daecd8f38d3e6a1ba19ea1f8a1751", "created_at": "2019-01-06T16:49:51.272+00:00", "total_size": 350224384 } +``` + +## Delete a registry repository tag[](#delete-a-registry-repository-tag "Permalink") + +删除注册表存储库标记. + +``` +DELETE /projects/:id/registry/repositories/:repository_id/tags/:tag_name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `repository_id` | integer | yes | 注册表存储库的标识. | +| `tag_name` | string | yes | 标签名称. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags/v10.0.0" +``` + +此操作不会删除 Blob. 为了删除它们并回收磁盘空间,请[运行垃圾回收](https://docs.gitlab.com/omnibus/maintenance/README.html) . + +## Delete registry repository tags in bulk[](#delete-registry-repository-tags-in-bulk "Permalink") + +根据给定的标准批量删除注册表存储库标签. + +有关概述,请参阅[利用 Container Registry API 删除除*之外的所有标签](https://youtu.be/Hi19bKe_xsg) . + +``` +DELETE /projects/:id/registry/repositories/:repository_id/tags +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `repository_id` | integer | yes | 注册表存储库的标识. | +| `name_regex` | string | no | 要删除的名称的[re2](https://github.com/google/re2/wiki/Syntax)正则表达式. 要删除所有标签,请指定`.*` . **注意:**不建议使用`name_regex`而建议使用`name_regex_delete` . 此字段已验证. | +| `name_regex_delete` | string | yes | 要删除的名称的[re2](https://github.com/google/re2/wiki/Syntax)正则表达式. 要删除所有标签,请指定`.*` . 此字段已验证. | +| `name_regex_keep` | string | no | 要保留名称的[re2](https://github.com/google/re2/wiki/Syntax)正则表达式. 此值将覆盖`name_regex_delete`所有匹配`name_regex_delete` . 此字段已验证. 注意:设置为`.*`将导致无操作. | +| `keep_n` | integer | no | 要保留的给定名称的最新标签的数量. | +| `older_than` | string | no | 早于给定时间的要删除的标签,以人类可读的格式`1h` , `1d` , `1month`编写. | + +此 API 调用执行以下操作: + +1. 它按创建日期排序所有标签. 创建日期是清单创建的时间,而不是标签推送的时间. +2. 它仅删除与给定`name_regex_delete` (或不`name_regex`使用的`name_regex` )匹配的标签,并保留所有与`name_regex_keep`匹配的`name_regex_keep` . +3. 它绝不会取消对标签命名`latest` . +4. 它保留 N 个最新的匹配标签(如果指定了`keep_n` ). +5. 它仅删除时间超过 X 时间的标签(如果指定了`older_than` ). +6. 它安排异步作业在后台执行. + +这些操作是异步执行的,可能要花一些时间才能执行. 对于给定的容器存储库,您最多可以每小时运行一次. 此操作不会删除 Blob. 为了删除它们并回收磁盘空间,请[运行垃圾回收](https://docs.gitlab.com/omnibus/maintenance/README.html) . + +**注意:**从 GitLab 12.4 开始,将删除各个标签. 有关更多详细信息,请参见[讨论](https://gitlab.com/gitlab-org/gitlab/-/issues/15737) . + +Examples: + +1. 删除与正则表达式(Git SHA)匹配的标记名,始终至少保留 5 个,并删除 2 天以上的标记名: + + ``` + curl --request DELETE --data 'name_regex_delete=[0-9a-z]{40}' --data 'keep_n=5' --data 'older_than=2d' --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags" + ``` + +2. 删除所有标签,但始终保留最新的 5 个标签: + + ``` + curl --request DELETE --data 'name_regex_delete=.*' --data 'keep_n=5' --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags" + ``` + +3. 删除所有标签,但始终保留以`stable`开头的标签: + + ``` + curl --request DELETE --data 'name_regex_delete=.*' --data 'name_regex_keep=stable.*' --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags" + ``` + +4. 删除所有超过 1 个月的标签: + + ``` + curl --request DELETE --data 'name_regex_delete=.*' --data 'older_than=1month' --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags" + ``` \ No newline at end of file diff --git a/docs/303.md b/docs/303.md new file mode 100644 index 0000000000000000000000000000000000000000..58fb56a6f3ea81d5ace64bb8c9eccd635301e319 --- /dev/null +++ b/docs/303.md @@ -0,0 +1,108 @@ +# Custom Attributes API + +> 原文:[https://docs.gitlab.com/ee/api/custom_attributes.html](https://docs.gitlab.com/ee/api/custom_attributes.html) + +* [List custom attributes](#list-custom-attributes) +* [Single custom attribute](#single-custom-attribute) +* [Set custom attribute](#set-custom-attribute) +* [Delete custom attribute](#delete-custom-attribute) + +# Custom Attributes API[](#custom-attributes-api "Permalink") + +每个对自定义属性的 API 调用都必须经过管理员身份验证. + +自定义属性当前可用于用户,组和项目,在本文档中将其称为"资源". + +## List custom attributes[](#list-custom-attributes "Permalink") + +获取资源上的所有自定义属性. + +``` +GET /users/:id/custom_attributes +GET /groups/:id/custom_attributes +GET /projects/:id/custom_attributes +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 资源的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/42/custom_attributes" +``` + +响应示例: + +``` +[ { "key": "location", "value": "Antarctica" }, { "key": "role", "value": "Developer" } ] +``` + +## Single custom attribute[](#single-custom-attribute "Permalink") + +在资源上获取单个自定义属性. + +``` +GET /users/:id/custom_attributes/:key +GET /groups/:id/custom_attributes/:key +GET /projects/:id/custom_attributes/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 资源的 ID | +| `key` | string | yes | 自定义属性的键 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/42/custom_attributes/location" +``` + +响应示例: + +``` +{ "key": "location", "value": "Antarctica" } +``` + +## Set custom attribute[](#set-custom-attribute "Permalink") + +在资源上设置自定义属性. 如果该属性已经存在,则将对其进行更新;否则,将重新创建该属性. + +``` +PUT /users/:id/custom_attributes/:key +PUT /groups/:id/custom_attributes/:key +PUT /projects/:id/custom_attributes/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 资源的 ID | +| `key` | string | yes | 自定义属性的键 | +| `value` | string | yes | 自定义属性的值 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --data "value=Greenland" "https://gitlab.example.com/api/v4/users/42/custom_attributes/location" +``` + +响应示例: + +``` +{ "key": "location", "value": "Greenland" } +``` + +## Delete custom attribute[](#delete-custom-attribute "Permalink") + +删除资源上的自定义属性. + +``` +DELETE /users/:id/custom_attributes/:key +DELETE /groups/:id/custom_attributes/:key +DELETE /projects/:id/custom_attributes/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 资源的 ID | +| `key` | string | yes | 自定义属性的键 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/42/custom_attributes/location" +``` \ No newline at end of file diff --git a/docs/304.md b/docs/304.md new file mode 100644 index 0000000000000000000000000000000000000000..2c36d326f99874396737a3fe276cb726b3ea9ee7 --- /dev/null +++ b/docs/304.md @@ -0,0 +1,44 @@ +# Dashboard annotations API + +> 原文:[https://docs.gitlab.com/ee/api/metrics_dashboard_annotations.html](https://docs.gitlab.com/ee/api/metrics_dashboard_annotations.html) + +* [Create a new annotation](#create-a-new-annotation) + +# Dashboard annotations API[](#dashboard-annotations-api "Permalink") + +版本历史 + +* 在 GitLab 12.10 中在禁用的功能标志后面[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29089) . + +指标仪表板注释使您可以在单个时间点或整个时间段内指示图形上的事件. + +## Create a new annotation[](#create-a-new-annotation "Permalink") + +``` +POST /environments/:id/metrics_dashboard/annotations/ +POST /clusters/:id/metrics_dashboard/annotations/ +``` + +**注意:** `dashboard_path`的值将被视为 CGI 转义的路径,并自动取消转义. + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `dashboard_path` | string | yes | 需要注释的仪表盘的 ID. | +| `starting_at` | string | yes | 日期时间字符串,ISO 8601 格式,例如`2016-03-11T03:45:40Z` . 注释的时间戳标记起点. | +| `ending_at` | string | no | 日期时间字符串,ISO 8601 格式,例如`2016-03-11T03:45:40Z` . 注释的时间戳标记终点. 如果未提供,注释将在起点显示为单个事件. | +| `description` | string | yes | 注释的描述. | + +``` +curl --header "Private-Token: " "https://gitlab.example.com/api/v4/environments/1/metrics_dashboard/annotations" \ + --data-urlencode "dashboard_path=.gitlab/dashboards/custom_metrics.yml" \ + --data-urlencode "starting_at=2016-03-11T03:45:40Z" \ + --data-urlencode "description=annotation description" +``` + +示例响应: + +``` +{ "id": 4, "starting_at": "2016-04-08T03:45:40.000Z", "ending_at": null, "dashboard_path": ".gitlab/dashboards/custom_metrics.yml", "description": "annotation description", "environment_id": 1, "cluster_id": null } +``` \ No newline at end of file diff --git a/docs/305.md b/docs/305.md new file mode 100644 index 0000000000000000000000000000000000000000..370727fc20a50e850246ad6772046beae9b798d5 --- /dev/null +++ b/docs/305.md @@ -0,0 +1,36 @@ +# Dependencies API + +> 原文:[https://docs.gitlab.com/ee/api/dependencies.html](https://docs.gitlab.com/ee/api/dependencies.html) + +* [List project dependencies](#list-project-dependencies) + +# Dependencies API[](#dependencies-api-ultimate "Permalink") + +**警告:**此 API 处于 alpha 阶段,被认为是不稳定的. 响应有效载荷可能会在 GitLab 版本之间发生更改或损坏. + +对此端点的每次调用都需要身份验证. 要执行此调用,应授权用户读取存储库. 要查看响应中的漏洞,应授权用户阅读[Project Security Dashboard](../user/application_security/security_dashboard/index.html#project-security-dashboard) . + +## List project dependencies[](#list-project-dependencies "Permalink") + +获取项目依赖项列表. 该 API 部分镜像了[依赖项列表](../user/application_security/dependency_list/index.html)功能. 只能为 Gemnasium 支持的[语言和程序包管理器](../user/application_security/dependency_scanning/index.html#supported-languages-and-package-managers)生成此列表. + +``` +GET /projects/:id/dependencies +GET /projects/:id/dependencies?package_manager=maven +GET /projects/:id/dependencies?package_manager=yarn,bundler +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `package_manager` | 字符串数组 | no | 返回属于指定程序包管理器的依赖项. 有效值: `bundler` , `composer` , `maven` , `npm` , `pip`或`yarn` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/dependencies" +``` + +响应示例: + +``` +[ { "name": "rails", "version": "5.0.1", "package_manager": "bundler", "dependency_file_path": "Gemfile.lock", "vulnerabilities": [{ "name": "DDoS", "severity": "unknown" }] }, { "name": "hanami", "version": "1.3.1", "package_manager": "bundler", "dependency_file_path": "Gemfile.lock", "vulnerabilities": [] } ] +``` \ No newline at end of file diff --git a/docs/306.md b/docs/306.md new file mode 100644 index 0000000000000000000000000000000000000000..6c223fcccfa6edd1fdf3ce71166432c00b34e30a --- /dev/null +++ b/docs/306.md @@ -0,0 +1,196 @@ +# Deploy Keys API + +> 原文:[https://docs.gitlab.com/ee/api/deploy_keys.html](https://docs.gitlab.com/ee/api/deploy_keys.html) + +* [List all deploy keys](#list-all-deploy-keys) +* [List project deploy keys](#list-project-deploy-keys) +* [Single deploy key](#single-deploy-key) +* [Add deploy key](#add-deploy-key) +* [Update deploy key](#update-deploy-key) +* [Delete deploy key](#delete-deploy-key) +* [Enable a deploy key](#enable-a-deploy-key) +* [Adding deploy keys to multiple projects](#adding-deploy-keys-to-multiple-projects) + +# Deploy Keys API[](#deploy-keys-api "Permalink") + +## List all deploy keys[](#list-all-deploy-keys "Permalink") + +获取 GitLab 实例的所有项目中所有部署密钥的列表. 该端点需要管理员访问权限,并且在 GitLab.com 上不可用. + +``` +GET /deploy_keys +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/deploy_keys" +``` + +响应示例: + +``` +[ { "id": 1, "title": "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2013-10-02T10:12:29Z" }, { "id": 3, "title": "Another Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2013-10-02T11:12:29Z" } ] +``` + +## List project deploy keys[](#list-project-deploy-keys "Permalink") + +获取项目的部署密钥的列表. + +``` +GET /projects/:id/deploy_keys +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/deploy_keys" +``` + +响应示例: + +``` +[ { "id": 1, "title": "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2013-10-02T10:12:29Z", "can_push": false }, { "id": 3, "title": "Another Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2013-10-02T11:12:29Z", "can_push": false } ] +``` + +## Single deploy key[](#single-deploy-key "Permalink") + +Get a single key. + +``` +GET /projects/:id/deploy_keys/:key_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `key_id` | integer | yes | 部署密钥的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/deploy_keys/11" +``` + +响应示例: + +``` +{ "id": 1, "title": "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2013-10-02T10:12:29Z", "can_push": false } +``` + +## Add deploy key[](#add-deploy-key "Permalink") + +为项目创建一个新的部署密钥. + +如果部署密钥已经存在于另一个项目中,则只有在同一用户可以访问原始密钥的情况下,它才会加入到当前项目中. + +``` +POST /projects/:id/deploy_keys +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `title` | string | yes | 新部署密钥的标题 | +| `key` | string | yes | 新的部署密钥 | +| `can_push` | boolean | no | 可以将按键推送部署到项目的存储库 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" --data '{"title": "My deploy key", "key": "ssh-rsa AAAA...", "can_push": "true"}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/" +``` + +响应示例: + +``` +{ "key" : "ssh-rsa AAAA...", "id" : 12, "title" : "My deploy key", "can_push": true, "created_at" : "2015-08-29T12:44:31.550Z" } +``` + +## Update deploy key[](#update-deploy-key "Permalink") + +更新项目的部署密钥. + +``` +PUT /projects/:id/deploy_keys/:key_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `title` | string | no | 新部署密钥的标题 | +| `can_push` | boolean | no | 可以将按键推送部署到项目的存储库 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" --data '{"title": "New deploy key", "can_push": true}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/11" +``` + +响应示例: + +``` +{ "id": 11, "title": "New deploy key", "key": "ssh-rsa AAAA...", "created_at": "2015-08-29T12:44:31.550Z", "can_push": true } +``` + +## Delete deploy key[](#delete-deploy-key "Permalink") + +从项目中删除部署密钥. 如果部署密钥仅用于该项目,则它将从系统中删除. + +``` +DELETE /projects/:id/deploy_keys/:key_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `key_id` | integer | yes | 部署密钥的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/deploy_keys/13" +``` + +## Enable a deploy key[](#enable-a-deploy-key "Permalink") + +为项目启用部署密钥,以便可以使用它. 返回成功的密钥,成功时返回状态码 201. + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/deploy_keys/13/enable" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `key_id` | integer | yes | 部署密钥的 ID | + +响应示例: + +``` +{ "key" : "ssh-rsa AAAA...", "id" : 12, "title" : "My deploy key", "created_at" : "2015-08-29T12:44:31.550Z" } +``` + +## Adding deploy keys to multiple projects[](#adding-deploy-keys-to-multiple-projects "Permalink") + +如果您想轻松地将相同的部署密钥添加到同一组中的多个项目中,则可以使用 API​​轻松实现. + +首先,通过列出所有项目来找到您感兴趣的项目的 ID: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects" +``` + +或查找组的 ID: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups" +``` + +然后列出该组中的所有项目(例如,组 1234): + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1234" +``` + +使用这些 ID,将相同的部署密钥添加到所有: + +``` +for project_id in 321 456 987; do curl --request POST --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" \ + --data '{"title": "my key", "key": "ssh-rsa AAAA..."}' "https://gitlab.example.com/api/v4/projects/${project_id}/deploy_keys" +done +``` \ No newline at end of file diff --git a/docs/307.md b/docs/307.md new file mode 100644 index 0000000000000000000000000000000000000000..905bc23c935b610877c3b5a7c19c2a0d24106843 --- /dev/null +++ b/docs/307.md @@ -0,0 +1,139 @@ +# Deployments API + +> 原文:[https://docs.gitlab.com/ee/api/deployments.html](https://docs.gitlab.com/ee/api/deployments.html) + +* [List project deployments](#list-project-deployments) +* [Get a specific deployment](#get-a-specific-deployment) +* [Create a deployment](#create-a-deployment) +* [Updating a deployment](#updating-a-deployment) +* [List of merge requests associated with a deployment](#list-of-merge-requests-associated-with-a-deployment) + +# Deployments API[](#deployments-api "Permalink") + +## List project deployments[](#list-project-deployments "Permalink") + +获取项目中的部署列表. + +``` +GET /projects/:id/deployments +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `order_by` | string | no | 返回按`id`或`iid`或`created_at`或`updated_at`或`ref`字段排序的部署. 默认为`id` | +| `sort` | string | no | 返回按`asc`或`desc`排列的部署. 默认为`asc` | +| `updated_after` | datetime | no | 返回指定日期之后更新的部署 | +| `updated_before` | datetime | no | 返回在指定日期之前更新的部署 | +| `environment` | string | no | 用于过滤部署的环境名称 | +| `status` | string | no | 用来过滤部署的状态 | + +status 属性可以是以下值之一: + +* created +* running +* success +* failed +* canceled + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/deployments" +``` + +回应范例 + +``` +[ { "created_at": "2016-08-11T07:36:40.222Z", "updated_at": "2016-08-11T07:38:12.414Z", "status": "created", "deployable": { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2016-08-11T09:36:01.000+02:00", "id": "99d03678b90d914dbb1b109132516d71a4a03ea8", "message": "Merge branch 'new-title' into 'master'\r\n\r\nUpdate README\r\n\r\n\r\n\r\nSee merge request !1", "short_id": "99d03678", "title": "Merge branch 'new-title' into 'master'\r" }, "coverage": null, "created_at": "2016-08-11T07:36:27.357Z", "finished_at": "2016-08-11T07:36:39.851Z", "id": 657, "name": "deploy", "ref": "master", "runner": null, "stage": "deploy", "started_at": null, "status": "success", "tag": false, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" }, "pipeline": { "created_at": "2016-08-11T02:12:10.222Z", "id": 36, "ref": "master", "sha": "99d03678b90d914dbb1b109132516d71a4a03ea8", "status": "success", "updated_at": "2016-08-11T02:12:10.222Z", "web_url": "http://gitlab.dev/root/project/pipelines/12" } }, "environment": { "external_url": "https://about.gitlab.com", "id": 9, "name": "production" }, "id": 41, "iid": 1, "ref": "master", "sha": "99d03678b90d914dbb1b109132516d71a4a03ea8", "user": { "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "id": 1, "name": "Administrator", "state": "active", "username": "root", "web_url": "http://localhost:3000/root" } }, { "created_at": "2016-08-11T11:32:35.444Z", "updated_at": "2016-08-11T11:34:01.123Z", "status": "created", "deployable": { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2016-08-11T13:28:26.000+02:00", "id": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "message": "Merge branch 'rename-readme' into 'master'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2", "short_id": "a91957a8", "title": "Merge branch 'rename-readme' into 'master'\r" }, "coverage": null, "created_at": "2016-08-11T11:32:24.456Z", "finished_at": "2016-08-11T11:32:35.145Z", "id": 664, "name": "deploy", "ref": "master", "runner": null, "stage": "deploy", "started_at": null, "status": "success", "tag": false, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" }, "pipeline": { "created_at": "2016-08-11T07:43:52.143Z", "id": 37, "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "status": "success", "updated_at": "2016-08-11T07:43:52.143Z", "web_url": "http://gitlab.dev/root/project/pipelines/13" } }, "environment": { "external_url": "https://about.gitlab.com", "id": 9, "name": "production" }, "id": 42, "iid": 2, "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "user": { "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "id": 1, "name": "Administrator", "state": "active", "username": "root", "web_url": "http://localhost:3000/root" } } ] +``` + +## Get a specific deployment[](#get-a-specific-deployment "Permalink") + +``` +GET /projects/:id/deployments/:deployment_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `deployment_id` | integer | yes | 部署的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/deployments/1" +``` + +回应范例 + +``` +{ "id": 42, "iid": 2, "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "created_at": "2016-08-11T11:32:35.444Z", "updated_at": "2016-08-11T11:34:01.123Z", "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "environment": { "id": 9, "name": "production", "external_url": "https://about.gitlab.com" }, "deployable": { "id": 664, "status": "success", "stage": "deploy", "name": "deploy", "ref": "master", "tag": false, "coverage": null, "created_at": "2016-08-11T11:32:24.456Z", "started_at": null, "finished_at": "2016-08-11T11:32:35.145Z", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" }, "commit": { "id": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "short_id": "a91957a8", "title": "Merge branch 'rename-readme' into 'master'\r", "author_name": "Administrator", "author_email": "admin@example.com", "created_at": "2016-08-11T13:28:26.000+02:00", "message": "Merge branch 'rename-readme' into 'master'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2" }, "pipeline": { "created_at": "2016-08-11T07:43:52.143Z", "id": 42, "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "status": "success", "updated_at": "2016-08-11T07:43:52.143Z", "web_url": "http://gitlab.dev/root/project/pipelines/5" } "runner": null } } +``` + +## Create a deployment[](#create-a-deployment "Permalink") + +``` +POST /projects/:id/deployments +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `environment` | string | yes | 要为其创建部署的环境的名称 | +| `sha` | string | yes | 部署的提交的 SHA | +| `ref` | string | yes | 部署的分支或标记的名称 | +| `tag` | boolean | yes | A boolean that indicates if the deployed ref is a tag (true) or not (false) | +| `status` | string | yes | 部署状态 | + +状态可以是以下值之一: + +* created +* running +* success +* failed +* canceled + +``` +curl --data "environment=production&sha=a91957a858320c0e17f3a0eca7cfacbff50ea29a&ref=master&tag=false&status=success" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/deployments" +``` + +响应示例: + +``` +{ "id": 42, "iid": 2, "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "created_at": "2016-08-11T11:32:35.444Z", "status": "success", "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "environment": { "id": 9, "name": "production", "external_url": "https://about.gitlab.com" }, "deployable": null } +``` + +## Updating a deployment[](#updating-a-deployment "Permalink") + +``` +PUT /projects/:id/deployments/:deployment_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `deployment_id` | integer | yes | 要更新的部署的 ID | +| `status` | string | yes | 部署的新状态 | + +``` +curl --request PUT --data "status=success" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/deployments/42" +``` + +响应示例: + +``` +{ "id": 42, "iid": 2, "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "created_at": "2016-08-11T11:32:35.444Z", "status": "success", "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "environment": { "id": 9, "name": "production", "external_url": "https://about.gitlab.com" }, "deployable": null } +``` + +## List of merge requests associated with a deployment[](#list-of-merge-requests-associated-with-a-deployment "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/35739) . + +此 API 检索给定部署附带的合并请求列表: + +``` +GET /projects/:id/deployments/:deployment_id/merge_requests +``` + +它支持与[Merge Requests API](./merge_requests.html#list-merge-requests)相同的参数,并将以相同的格式返回响应: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/deployments/42" +``` \ No newline at end of file diff --git a/docs/308.md b/docs/308.md new file mode 100644 index 0000000000000000000000000000000000000000..bd54101a3d25440a91d7b2205a777cbe3c66e3c7 --- /dev/null +++ b/docs/308.md @@ -0,0 +1,790 @@ +# Discussions API + +> 原文:[https://docs.gitlab.com/ee/api/discussions.html](https://docs.gitlab.com/ee/api/discussions.html) + +* [Discussions pagination](#discussions-pagination) +* [Issues](#issues) + * [List project issue discussion items](#list-project-issue-discussion-items) + * [Get single issue discussion item](#get-single-issue-discussion-item) + * [Create new issue thread](#create-new-issue-thread) + * [Add note to existing issue thread](#add-note-to-existing-issue-thread) + * [Modify existing issue thread note](#modify-existing-issue-thread-note) + * [Delete an issue thread note](#delete-an-issue-thread-note) +* [Snippets](#snippets) + * [List project snippet discussion items](#list-project-snippet-discussion-items) + * [Get single snippet discussion item](#get-single-snippet-discussion-item) + * [Create new snippet thread](#create-new-snippet-thread) + * [Add note to existing snippet thread](#add-note-to-existing-snippet-thread) + * [Modify existing snippet thread note](#modify-existing-snippet-thread-note) + * [Delete a snippet thread note](#delete-a-snippet-thread-note) +* [Epics](#epics-ultimate) + * [List group epic discussion items](#list-group-epic-discussion-items) + * [Get single epic discussion item](#get-single-epic-discussion-item) + * [Create new epic thread](#create-new-epic-thread) + * [Add note to existing epic thread](#add-note-to-existing-epic-thread) + * [Modify existing epic thread note](#modify-existing-epic-thread-note) + * [Delete an epic thread note](#delete-an-epic-thread-note) +* [Merge requests](#merge-requests) + * [List project merge request discussion items](#list-project-merge-request-discussion-items) + * [Get single merge request discussion item](#get-single-merge-request-discussion-item) + * [Create new merge request thread](#create-new-merge-request-thread) + * [Resolve a merge request thread](#resolve-a-merge-request-thread) + * [Add note to existing merge request thread](#add-note-to-existing-merge-request-thread) + * [Modify an existing merge request thread note](#modify-an-existing-merge-request-thread-note) + * [Delete a merge request thread note](#delete-a-merge-request-thread-note) +* [Commits](#commits) + * [List project commit discussion items](#list-project-commit-discussion-items) + * [Get single commit discussion item](#get-single-commit-discussion-item) + * [Create new commit thread](#create-new-commit-thread) + * [Add note to existing commit thread](#add-note-to-existing-commit-thread) + * [Modify an existing commit thread note](#modify-an-existing-commit-thread-note) + * [Delete a commit thread note](#delete-a-commit-thread-note) + +# Discussions API[](#discussions-api "Permalink") + +讨论是关于以下方面的一组相关注释: + +* Snippets +* Issues +* Epics +* 合并要求 +* Commits + +这包括系统注释,这些注释是有关对象更改的注释(例如,当里程碑更改时,将有相应的系统注释). 标签注释不是此 API 的一部分,而是在[资源标签事件中](resource_label_events.html)记录为单独的[事件](resource_label_events.html) . + +## Discussions pagination[](#discussions-pagination "Permalink") + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +## Issues[](#issues "Permalink") + +### List project issue discussion items[](#list-project-issue-discussion-items "Permalink") + +获取单个问题的所有讨论项目的列表. + +``` +GET /projects/:id/issues/:issue_iid/discussions +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | + +``` +[ { "id": "6a9c1750b37d513a43987b574953fceb50b03ce7", "individual_note": false, "notes": [ { "id": 1126, "type": "DiscussionNote", "body": "discussion text", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-03T21:54:39.668Z", "updated_at": "2018-03-03T21:54:39.668Z", "system": false, "noteable_id": 3, "noteable_type": "Issue", "noteable_iid": null }, { "id": 1129, "type": "DiscussionNote", "body": "reply to the discussion", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T13:38:02.127Z", "updated_at": "2018-03-04T13:38:02.127Z", "system": false, "noteable_id": 3, "noteable_type": "Issue", "noteable_iid": null, "resolvable": false } ] }, { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": true, "notes": [ { "id": 1128, "type": null, "body": "a single comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Issue", "noteable_iid": null, "resolvable": false } ] } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions" +``` + +### Get single issue discussion item[](#get-single-issue-discussion-item "Permalink") + +返回特定项目问题的单个讨论项 + +``` +GET /projects/:id/issues/:issue_iid/discussions/:discussion_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `discussion_id` | integer | yes | 讨论项目的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7" +``` + +### Create new issue thread[](#create-new-issue-thread "Permalink") + +为单个项目问题创建一个新线程. 这类似于创建便笺,但其他注释(回复)可以在以后添加. + +``` +POST /projects/:id/issues/:issue_iid/discussions +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `body` | string | yes | 线程的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions?body=comment" +``` + +### Add note to existing issue thread[](#add-note-to-existing-issue-thread "Permalink") + +向该线程添加新注释. 这也可以[从单个注释创建线程](../user/discussions/#start-a-thread-by-replying-to-a-standard-comment) . + +**警告**注释可以添加到注释(系统注释等)之外的其他项目中,从而使其成为主题. + +``` +POST /projects/:id/issues/:issue_iid/discussions/:discussion_id/notes +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment" +``` + +### Modify existing issue thread note[](#modify-existing-issue-thread-note "Permalink") + +修改问题的现有线程注释. + +``` +PUT /projects/:id/issues/:issue_iid/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment" +``` + +### Delete an issue thread note[](#delete-an-issue-thread-note "Permalink") + +删除问题的现有主题注释. + +``` +DELETE /projects/:id/issues/:issue_iid/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `discussion_id` | integer | yes | 讨论的 ID | +| `note_id` | integer | yes | 讨论记录的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/636" +``` + +## Snippets[](#snippets "Permalink") + +### List project snippet discussion items[](#list-project-snippet-discussion-items "Permalink") + +获取单个代码段的所有讨论项的列表. + +``` +GET /projects/:id/snippets/:snippet_id/discussions +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | + +``` +[ { "id": "6a9c1750b37d513a43987b574953fceb50b03ce7", "individual_note": false, "notes": [ { "id": 1126, "type": "DiscussionNote", "body": "discussion text", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-03T21:54:39.668Z", "updated_at": "2018-03-03T21:54:39.668Z", "system": false, "noteable_id": 3, "noteable_type": "Snippet", "noteable_id": null }, { "id": 1129, "type": "DiscussionNote", "body": "reply to the discussion", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T13:38:02.127Z", "updated_at": "2018-03-04T13:38:02.127Z", "system": false, "noteable_id": 3, "noteable_type": "Snippet", "noteable_id": null, "resolvable": false } ] }, { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": true, "notes": [ { "id": 1128, "type": null, "body": "a single comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Snippet", "noteable_id": null, "resolvable": false } ] } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions" +``` + +### Get single snippet discussion item[](#get-single-snippet-discussion-item "Permalink") + +返回特定项目片段的单个讨论项 + +``` +GET /projects/:id/snippets/:snippet_id/discussions/:discussion_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | +| `discussion_id` | integer | yes | 讨论项目的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7" +``` + +### Create new snippet thread[](#create-new-snippet-thread "Permalink") + +Creates a new thread to a single project snippet. This is similar to creating a note but other comments (replies) can be added to it later. + +``` +POST /projects/:id/snippets/:snippet_id/discussions +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | +| `body` | string | yes | 讨论内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions?body=comment" +``` + +### Add note to existing snippet thread[](#add-note-to-existing-snippet-thread "Permalink") + +向该线程添加新注释. + +``` +POST /projects/:id/snippets/:snippet_id/discussions/:discussion_id/notes +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment" +``` + +### Modify existing snippet thread note[](#modify-existing-snippet-thread-note "Permalink") + +修改代码段的现有线程注释. + +``` +PUT /projects/:id/snippets/:snippet_id/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment" +``` + +### Delete a snippet thread note[](#delete-a-snippet-thread-note "Permalink") + +删除代码段的现有线程注释. + +``` +DELETE /projects/:id/snippets/:snippet_id/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | +| `discussion_id` | integer | yes | 讨论的 ID | +| `note_id` | integer | yes | 讨论记录的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/636" +``` + +## Epics[](#epics-ultimate "Permalink") + +### List group epic discussion items[](#list-group-epic-discussion-items "Permalink") + +获取单个史诗的所有讨论项的列表. + +``` +GET /groups/:id/epics/:epic_id/discussions +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | + +``` +[ { "id": "6a9c1750b37d513a43987b574953fceb50b03ce7", "individual_note": false, "notes": [ { "id": 1126, "type": "DiscussionNote", "body": "discussion text", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-03T21:54:39.668Z", "updated_at": "2018-03-03T21:54:39.668Z", "system": false, "noteable_id": 3, "noteable_type": "Epic", "noteable_id": null, "resolvable": false }, { "id": 1129, "type": "DiscussionNote", "body": "reply to the discussion", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T13:38:02.127Z", "updated_at": "2018-03-04T13:38:02.127Z", "system": false, "noteable_id": 3, "noteable_type": "Epic", "noteable_id": null, "resolvable": false } ] }, { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": true, "notes": [ { "id": 1128, "type": null, "body": "a single comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Epic", "noteable_id": null, "resolvable": false } ] } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions" +``` + +### Get single epic discussion item[](#get-single-epic-discussion-item "Permalink") + +返回特定小组史诗的单个讨论项 + +``` +GET /groups/:id/epics/:epic_id/discussions/:discussion_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `discussion_id` | integer | yes | 讨论项目的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7" +``` + +### Create new epic thread[](#create-new-epic-thread "Permalink") + +Creates a new thread to a single group epic. This is similar to creating a note but other comments (replies) can be added to it later. + +``` +POST /groups/:id/epics/:epic_id/discussions +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `body` | string | yes | 线程的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions?body=comment" +``` + +### Add note to existing epic thread[](#add-note-to-existing-epic-thread "Permalink") + +向该线程添加新注释. 这也可以[从单个注释创建线程](../user/discussions/#start-a-thread-by-replying-to-a-standard-comment) . + +``` +POST /groups/:id/epics/:epic_id/discussions/:discussion_id/notes +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment" +``` + +### Modify existing epic thread note[](#modify-existing-epic-thread-note "Permalink") + +修改史诗的现有线程注释. + +``` +PUT /groups/:id/epics/:epic_id/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment" +``` + +### Delete an epic thread note[](#delete-an-epic-thread-note "Permalink") + +删除史诗的现有主题注释. + +``` +DELETE /groups/:id/epics/:epic_id/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/636" +``` + +## Merge requests[](#merge-requests "Permalink") + +### List project merge request discussion items[](#list-project-merge-request-discussion-items "Permalink") + +获取单个合并请求的所有讨论项的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/discussions +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | + +``` +[ { "id": "6a9c1750b37d513a43987b574953fceb50b03ce7", "individual_note": false, "notes": [ { "id": 1126, "type": "DiscussionNote", "body": "discussion text", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-03T21:54:39.668Z", "updated_at": "2018-03-03T21:54:39.668Z", "system": false, "noteable_id": 3, "noteable_type": "Merge request", "noteable_iid": null, "resolved": false, "resolvable": true, "resolved_by": null }, { "id": 1129, "type": "DiscussionNote", "body": "reply to the discussion", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T13:38:02.127Z", "updated_at": "2018-03-04T13:38:02.127Z", "system": false, "noteable_id": 3, "noteable_type": "Merge request", "noteable_iid": null, "resolved": false, "resolvable": true, "resolved_by": null } ] }, { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": true, "notes": [ { "id": 1128, "type": null, "body": "a single comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Merge request", "noteable_iid": null, "resolved": false, "resolvable": true, "resolved_by": null } ] } ] +``` + +差异评论还包含以下位置: + +``` +[ { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": false, "notes": [ { "id": 1128, "type": DiffNote, "body": "diff comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Merge request", "noteable_iid": null, "position": { "base_sha": "b5d6e7b1613fca24d250fa8e5bc7bcc3dd6002ef", "start_sha": "7c9c2ead8a320fb7ba0b4e234bd9529a2614e306", "head_sha": "4803c71e6b1833ca72b8b26ef2ecd5adc8a38031", "old_path": "package.json", "new_path": "package.json", "position_type": "text", "old_line": 27, "new_line": 27, "line_range": { "start": { "line_code": "588440f66559714280628a4f9799f0c4eb880a4a_10_10", "type": "new", }, "end": { "line_code": "588440f66559714280628a4f9799f0c4eb880a4a_11_11", "type": "old" }, } }, "resolved": false, "resolvable": true, "resolved_by": null } ] } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions" +``` + +### Get single merge request discussion item[](#get-single-merge-request-discussion-item "Permalink") + +返回特定项目合并请求的单个讨论项 + +``` +GET /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `discussion_id` | integer | yes | 讨论项目的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7 +``` + +### Create new merge request thread[](#create-new-merge-request-thread "Permalink") + +为单个项目合并请求创建一个新线程. 这类似于创建便笺,但其他注释(回复)可以在以后添加. + +``` +POST /projects/:id/merge_requests/:merge_request_iid/discussions +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `body` | string | yes | 线程的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | +| `position` | hash | no | 创建差异注释时的位置 | +| `position[base_sha]` | string | yes | 源分支中的基本提交 SHA | +| `position[start_sha]` | string | yes | SHA 引用目标分支中的提交 | +| `position[head_sha]` | string | yes | SHA 引用此合并请求的 HEAD | +| `position[position_type]` | string | yes | 位置参考的类型",允许的值:"文本"或"图像" | +| `position[new_path]` | string | no | 更改后的文件路径 | +| `position[new_line]` | integer | no | 更改后的行号(用于"文本"差异注释) | +| `position[old_path]` | string | no | 更改前的文件路径 | +| `position[old_line]` | integer | no | 更改前的行号(用于"文本"差异注释) | +| `position[line_range]` | hash | no | 多行差异注释的行范围 | +| `position[line_range][start]` | hash | no | 多行音符起始行 | +| `position[line_range][start][line_code]` | string | yes | 起始行的行代码 | +| `position[line_range][start][type]` | string | yes | 起始线的线型 | +| `position[line_range][end]` | hash | no | 多行注释结束行 | +| `position[line_range][end][line_code]` | string | yes | 结束行的行代码 | +| `position[line_range][end][type]` | string | yes | 终点线的线型 | +| `position[width]` | integer | no | 图片宽度(用于"图片"差异注释) | +| `position[height]` | integer | no | 图片的高度(用于"图片"差异注释) | +| `position[x]` | integer | no | X 坐标(用于"图像"差异注释) | +| `position[y]` | integer | no | Y 坐标(用于"图像"差异注释) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions?body=comment" +``` + +### Resolve a merge request thread[](#resolve-a-merge-request-thread "Permalink") + +解决/取消解决合并请求的整个线程. + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `discussion_id` | integer | yes | 线程的 ID | +| `resolved` | boolean | yes | 解决/取消讨论 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7?resolved=true" +``` + +### Add note to existing merge request thread[](#add-note-to-existing-merge-request-thread "Permalink") + +向该线程添加新注释. 这也可以[从单个注释创建线程](../user/discussions/#start-a-thread-by-replying-to-a-standard-comment) . + +``` +POST /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id/notes +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment" +``` + +### Modify an existing merge request thread note[](#modify-an-existing-merge-request-thread-note "Permalink") + +修改或解决合并请求的现有线程注释. + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | no | 备注/回复的内容(必须是`body`或已`resolved`的内容之一) | +| `resolved` | boolean | no | 解析/取消解析音符(必须设置为刚好为`body`或已`resolved` | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment" +``` + +解决注释: + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?resolved=true" +``` + +### Delete a merge request thread note[](#delete-a-merge-request-thread-note "Permalink") + +删除合并请求的现有线程注释. + +``` +DELETE /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/636" +``` + +## Commits[](#commits "Permalink") + +### List project commit discussion items[](#list-project-commit-discussion-items "Permalink") + +获取单个提交的所有讨论项的列表. + +``` +GET /projects/:id/commits/:commit_id/discussions +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `commit_id` | integer | yes | 提交的 ID | + +``` +[ { "id": "6a9c1750b37d513a43987b574953fceb50b03ce7", "individual_note": false, "notes": [ { "id": 1126, "type": "DiscussionNote", "body": "discussion text", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-03T21:54:39.668Z", "updated_at": "2018-03-03T21:54:39.668Z", "system": false, "noteable_id": 3, "noteable_type": "Commit", "noteable_iid": null, "resolvable": false }, { "id": 1129, "type": "DiscussionNote", "body": "reply to the discussion", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T13:38:02.127Z", "updated_at": "2018-03-04T13:38:02.127Z", "system": false, "noteable_id": 3, "noteable_type": "Commit", "noteable_iid": null, "resolvable": false } ] }, { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": true, "notes": [ { "id": 1128, "type": null, "body": "a single comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Commit", "noteable_iid": null, "resolvable": false } ] } ] +``` + +差异评论还包含以下位置: + +``` +[ { "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6", "individual_note": false, "notes": [ { "id": 1128, "type": DiffNote, "body": "diff comment", "attachment": null, "author": { "id": 1, "name": "root", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2018-03-04T09:17:22.520Z", "updated_at": "2018-03-04T09:17:22.520Z", "system": false, "noteable_id": 3, "noteable_type": "Commit", "noteable_iid": null, "position": { "base_sha": "b5d6e7b1613fca24d250fa8e5bc7bcc3dd6002ef", "start_sha": "7c9c2ead8a320fb7ba0b4e234bd9529a2614e306", "head_sha": "4803c71e6b1833ca72b8b26ef2ecd5adc8a38031", "old_path": "package.json", "new_path": "package.json", "position_type": "text", "old_line": 27, "new_line": 27 }, "resolvable": false } ] } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions" +``` + +### Get single commit discussion item[](#get-single-commit-discussion-item "Permalink") + +返回特定项目提交的单个讨论项 + +``` +GET /projects/:id/commits/:commit_id/discussions/:discussion_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `commit_id` | integer | yes | 提交的 ID | +| `discussion_id` | integer | yes | 讨论项目的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7" +``` + +### Create new commit thread[](#create-new-commit-thread "Permalink") + +为单个项目提交创建一个新线程. 这类似于创建便笺,但其他注释(回复)可以在以后添加. + +``` +POST /projects/:id/commits/:commit_id/discussions +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `commit_id` | integer | yes | 提交的 ID | +| `body` | string | yes | 线程的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | +| `position` | hash | no | 创建差异注释时的位置 | +| `position[base_sha]` | string | yes | 源分支中的基本提交 SHA | +| `position[start_sha]` | string | yes | SHA 引用目标分支中的提交 | +| `position[head_sha]` | string | yes | SHA 引用此提交的 HEAD | +| `position[position_type]` | string | yes | 位置参考的类型",允许的值:"文本"或"图像" | +| `position[new_path]` | string | no | 更改后的文件路径 | +| `position[new_line]` | integer | no | 变更后的行号 | +| `position[old_path]` | string | no | 更改前的文件路径 | +| `position[old_line]` | integer | no | 更改前的行号 | +| `position[width]` | integer | no | 图片宽度(用于"图片"差异注释) | +| `position[height]` | integer | no | 图片的高度(用于"图片"差异注释) | +| `position[x]` | integer | no | X 坐标(用于"图像"差异注释) | +| `position[y]` | integer | no | Y 坐标(用于"图像"差异注释) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions?body=comment" +``` + +### Add note to existing commit thread[](#add-note-to-existing-commit-thread "Permalink") + +向该线程添加新注释. + +``` +POST /projects/:id/commits/:commit_id/discussions/:discussion_id/notes +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `commit_id` | integer | yes | 提交的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | yes | 备注/回复的内容 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment +``` + +### Modify an existing commit thread note[](#modify-an-existing-commit-thread-note "Permalink") + +修改或解决提交的现有线程注释. + +``` +PUT /projects/:id/commits/:commit_id/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `commit_id` | integer | yes | 提交的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | +| `body` | string | no | 笔记内容 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment" +``` + +解决注释: + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?resolved=true" +``` + +### Delete a commit thread note[](#delete-a-commit-thread-note "Permalink") + +删除提交的现有线程注释. + +``` +DELETE /projects/:id/commits/:commit_id/discussions/:discussion_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `commit_id` | integer | yes | 提交的 ID | +| `discussion_id` | integer | yes | 线程的 ID | +| `note_id` | integer | yes | 线程注释的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/636" +``` \ No newline at end of file diff --git a/docs/309.md b/docs/309.md new file mode 100644 index 0000000000000000000000000000000000000000..78b448eb290678d4c25e95118d00947f442e178a --- /dev/null +++ b/docs/309.md @@ -0,0 +1,50 @@ +# Dockerfiles API + +> 原文:[https://docs.gitlab.com/ee/api/templates/dockerfiles.html](https://docs.gitlab.com/ee/api/templates/dockerfiles.html) + +* [List Dockerfile templates](#list-dockerfile-templates) +* [Single Dockerfile template](#single-dockerfile-template) + +# Dockerfiles API[](#dockerfiles-api "Permalink") + +在 GitLab 中,有一个可用于 Dockerfile 的 API 端点. 有关 Dockerfile 的更多信息,请参阅[Docker 文档](https://s0docs0docker0com.icopy.site/engine/reference/builder/) . + +## List Dockerfile templates[](#list-dockerfile-templates "Permalink") + +获取所有 Dockerfile 模板. + +``` +GET /templates/dockerfiles +``` + +``` +curl https://gitlab.example.com/api/v4/templates/dockerfiles +``` + +响应示例: + +``` +[ { "key": "Binary", "name": "Binary" }, { "key": "Binary-alpine", "name": "Binary-alpine" }, { "key": "Binary-scratch", "name": "Binary-scratch" }, { "key": "Golang", "name": "Golang" }, { "key": "Golang-alpine", "name": "Golang-alpine" }, { "key": "Golang-scratch", "name": "Golang-scratch" }, { "key": "HTTPd", "name": "HTTPd" }, { "key": "Node", "name": "Node" }, { "key": "Node-alpine", "name": "Node-alpine" }, { "key": "OpenJDK", "name": "OpenJDK" }, { "key": "OpenJDK-alpine", "name": "OpenJDK-alpine" }, { "key": "PHP", "name": "PHP" }, { "key": "Python", "name": "Python" }, { "key": "Python-alpine", "name": "Python-alpine" }, { "key": "Python2", "name": "Python2" }, { "key": "Ruby", "name": "Ruby" }, { "key": "Ruby-alpine", "name": "Ruby-alpine" }, { "key": "Swift", "name": "Swift" } ] +``` + +## Single Dockerfile template[](#single-dockerfile-template "Permalink") + +获取单个 Dockerfile 模板. + +``` +GET /templates/dockerfiles/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `key` | string | yes | Dockerfile 模板的关键 | + +``` +curl https://gitlab.example.com/api/v4/templates/dockerfiles/Binary +``` + +响应示例: + +``` +{ "name": "Binary", "content": "# This file is a template, and might need editing before it works on your project.\n# This Dockerfile installs a compiled binary into a bare system.\n# You must either commit your compiled binary into source control (not recommended)\n# or build the binary first as part of a CI/CD pipeline.\n\nFROM buildpack-deps:jessie\n\nWORKDIR /usr/local/bin\n\n# Change `app` to whatever your binary is called\nAdd app .\nCMD [\"./app\"]\n" } +``` \ No newline at end of file diff --git a/docs/310.md b/docs/310.md new file mode 100644 index 0000000000000000000000000000000000000000..5ef44bb2bf56f0288ea8b09e020c342791ba2e99 --- /dev/null +++ b/docs/310.md @@ -0,0 +1,151 @@ +# Environments API + +> 原文:[https://docs.gitlab.com/ee/api/environments.html](https://docs.gitlab.com/ee/api/environments.html) + +* [List environments](#list-environments) +* [Get a specific environment](#get-a-specific-environment) +* [Create a new environment](#create-a-new-environment) +* [Edit an existing environment](#edit-an-existing-environment) +* [Delete an environment](#delete-an-environment) +* [Stop an environment](#stop-an-environment) + +# Environments API[](#environments-api "Permalink") + +## List environments[](#list-environments "Permalink") + +获取给定项目的所有环境. + +``` +GET /projects/:id/environments +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | no | 使用此名称返回环境. 与`search`互斥 | +| `search` | string | no | 返回符合搜索条件的环境列表. 与`name`互斥 | +| `states` | string | no | 列出与特定状态匹配的所有环境. 接受的值: `available`或已`stopped` . 如果没有给出状态值,则返回所有环境. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments?name=review%2Ffix-foo" +``` + +响应示例: + +``` +[ { "id": 1, "name": "review/fix-foo", "slug": "review-fix-foo-dfjre3", "external_url": "https://review-fix-foo-dfjre3.example.gitlab.com", "state": "available" } ] +``` + +## Get a specific environment[](#get-a-specific-environment "Permalink") + +``` +GET /projects/:id/environments/:environment_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `environment_id` | integer | yes | 环境的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments/1" +``` + +回应范例 + +``` +{ "id": 1, "name": "review/fix-foo", "slug": "review-fix-foo-dfjre3", "external_url": "https://review-fix-foo-dfjre3.example.gitlab.com" "state": "available", "last_deployment": { "id": 100, "iid": 34, "ref": "fdroid", "sha": "416d8ea11849050d3d1f5104cf8cf51053e790ab", "created_at": "2019-03-25T18:55:13.252Z", "status": "success", "user": { "id": 1, "name": "Administrator", "state": "active", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" } "deployable": { "id": 710, "status": "success", "stage": "deploy", "name": "staging", "ref": "fdroid", "tag": false, "coverage": null, "created_at": "2019-03-25T18:55:13.215Z", "started_at": "2019-03-25T12:54:50.082Z", "finished_at": "2019-03-25T18:55:13.216Z", "duration": 21623.13423, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": null } "commit": { "id": "416d8ea11849050d3d1f5104cf8cf51053e790ab", "short_id": "416d8ea1", "created_at": "2016-01-02T15:39:18.000Z", "parent_ids": [ "e9a4449c95c64358840902508fc827f1a2eab7df" ], "title": "Removed fabric to fix #40", "message": "Removed fabric to fix #40\n", "author_name": "Administrator", "author_email": "admin@example.com", "authored_date": "2016-01-02T15:39:18.000Z", "committer_name": "Administrator", "committer_email": "admin@example.com", "committed_date": "2016-01-02T15:39:18.000Z" }, "pipeline": { "id": 34, "sha": "416d8ea11849050d3d1f5104cf8cf51053e790ab", "ref": "fdroid", "status": "success", "web_url": "http://localhost:3000/Commit451/lab-coat/pipelines/34" }, "web_url": "http://localhost:3000/Commit451/lab-coat/-/jobs/710", "artifacts": [ { "file_type": "trace", "size": 1305, "filename": "job.log", "file_format": null } ], "runner": null, "artifacts_expire_at": null } } } +``` + +## Create a new environment[](#create-a-new-environment "Permalink") + +使用给定名称和`external_url`创建一个新环境. + +如果成功创建了环境,则返回`201`否则返回`400` . + +``` +POST /projects/:id/environments +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 环境名称 | +| `external_url` | string | no | Place to link to for this environment | + +``` +curl --data "name=deploy&external_url=https://deploy.example.gitlab.com" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments" +``` + +响应示例: + +``` +{ "id": 1, "name": "deploy", "slug": "deploy", "external_url": "https://deploy.example.gitlab.com", "state": "available" } +``` + +## Edit an existing environment[](#edit-an-existing-environment "Permalink") + +更新现有环境的名称和/或`external_url` . + +如果成功更新了环境,它将返回`200` . 如果出现错误,则返回状态码`400` . + +``` +PUT /projects/:id/environments/:environments_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `environment_id` | integer | yes | 环境的 ID | +| `name` | string | no | 环境的新名称 | +| `external_url` | string | no | 新的`external_url` | + +``` +curl --request PUT --data "name=staging&external_url=https://staging.example.gitlab.com" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments/1" +``` + +响应示例: + +``` +{ "id": 1, "name": "staging", "slug": "staging", "external_url": "https://staging.example.gitlab.com", "state": "available" } +``` + +## Delete an environment[](#delete-an-environment "Permalink") + +如果成功删除了环境,则返回`204`如果环境不存在,则返回`404` . + +``` +DELETE /projects/:id/environments/:environment_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `environment_id` | integer | yes | 环境的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments/1" +``` + +## Stop an environment[](#stop-an-environment "Permalink") + +如果成功停止了环境,则返回`200`如果环境不存在,则返回`404` . + +``` +POST /projects/:id/environments/:environment_id/stop +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `environment_id` | integer | yes | 环境的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments/1/stop" +``` + +响应示例: + +``` +{ "id": 1, "name": "deploy", "slug": "deploy", "external_url": "https://deploy.example.gitlab.com", "state": "stopped" } +``` \ No newline at end of file diff --git a/docs/311.md b/docs/311.md new file mode 100644 index 0000000000000000000000000000000000000000..955fc44fe850e65750002a5b775723d41e7a4c43 --- /dev/null +++ b/docs/311.md @@ -0,0 +1,217 @@ +# Epics API + +> 原文:[https://docs.gitlab.com/ee/api/epics.html](https://docs.gitlab.com/ee/api/epics.html) + +* [Epic issues API](#epic-issues-api) +* [Milestone dates integration](#milestone-dates-integration) +* [Epics pagination](#epics-pagination) +* [List epics for a group](#list-epics-for-a-group) +* [Single epic](#single-epic) +* [New epic](#new-epic) +* [Update epic](#update-epic) +* [Delete epic](#delete-epic) +* [Create a todo](#create-a-todo) + +# Epics API[](#epics-api-premium "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 10.2 中引入. +* 单级史诗在 12.8 [中移至](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) [GitLab Premium](https://about.gitlab.com/pricing/) . + +对史诗的每个 API 调用都必须经过身份验证. + +如果用户不是组的成员,并且该组是私有的,则对该组的`GET`请求将导致`404`状态代码. + +如果没有史诗功能,将返回`403`状态代码. + +## Epic issues API[](#epic-issues-api "Permalink") + +[史诗问题 API](epic_issues.html)使您可以与[史诗相关的问题](epic_issues.html)进行交互. + +## Milestone dates integration[](#milestone-dates-integration "Permalink") + +在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6448) . + +由于可以从相关的发行里程碑动态地获取开始日期和截止日期,因此当用户具有编辑权限时,将显示其他字段. 其中包括两个布尔字段`start_date_is_fixed`和`due_date_is_fixed` ,以及四个日期字段`start_date_fixed` , `start_date_from_inherited_source` , `due_date_fixed`和`due_date_from_inherited_source` . + +* 不建议使用`end_date` ,而应使用`due_date` . +* 不赞成使用`start_date_from_milestones` ,而建议使用`start_date_from_inherited_source` +* 不建议使用`due_date_from_milestones` ,而应使用`due_date_from_inherited_source` + +## Epics pagination[](#epics-pagination "Permalink") + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +**弃用:不建议使用**响应中的`reference`属性,而推荐使用`references` . >推出了[GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354)**注意:** > `references.relative`相对于正在请求史诗的组. 从史诗组的原始组中提取史诗时, `relative`格式将与`short`格式相同,而在请求的交叉组中, `relative`格式应与`full`格式相同. + +## List epics for a group[](#list-epics-for-a-group "Permalink") + +获取请求的组及其子组的所有史诗. + +``` +GET /groups/:id/epics +GET /groups/:id/epics?author_id=5 +GET /groups/:id/epics?labels=bug,reproduced +GET /groups/:id/epics?state=opened +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.html#namespaced-path-encoding) owned by the authenticated user | +| `author_id` | integer | no | 返回由给定用户`id`创建的史诗 | +| `labels` | string | no | 返回与以逗号分隔的标签名称列表匹配的史诗. 可以使用史诗组或父组的标签名称 | +| `with_labels_details` | boolean | no | 如果为`true` ,则响应将为标签字段中的每个标签返回更多详细信息`:name` , `:color` , `:description` , `:description_html` , `:text_color` . 默认值为`false` . 在[GitLab 12.7 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)引入 | +| `order_by` | string | no | 返回按`created_at`或`updated_at`字段排序的史诗. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`排列的史诗. 默认为`desc` | +| `search` | string | no | 根据`title`和`description`搜索史诗 | +| `state` | string | no | 根据`state`搜索史诗,可能的过滤条件: `opened` , `closed`和`all` ,默认值: `all` | +| `created_after` | datetime | no | 返回在给定时间或之后创建的史诗 | +| `created_before` | datetime | no | 返回在给定时间或之前创建的史诗 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的史诗 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的史诗 | +| `include_ancestor_groups` | boolean | no | 包括请求组祖先的史诗. 默认为`false` | +| `include_descendant_groups` | boolean | no | 包括请求组后代的史诗. 默认为`true` | +| `my_reaction_emoji` | string | no | 返回给定表情符号由已认证用户做出反应的史诗. `None`返回没有反应的史诗. 给定至少一个反应, `Any`回报史诗. 在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31479)引入 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics" +``` + +响应示例: + +``` +[ { "id": 29, "iid": 4, "group_id": 7, "parent_id": 23, "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "state": "opened", "confidential": "false", "web_url": "http://localhost:3001/groups/test/-/epics/4", "reference": "&4", "references": { "short": "&4", "relative": "&4", "full": "test&4" }, "author": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, "downvotes": 0 }, { "id": 50, "iid": 35, "group_id": 17, "parent_id": 19, "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "state": "opened", "web_url": "http://localhost:3001/groups/test/sample/-/epics/4", "reference": "&4", "references": { "short": "&4", "relative": "sample&4", "full": "test/sample&4" }, "author": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, "downvotes": 0 } ] +``` + +## Single epic[](#single-epic "Permalink") + +取得史诗 + +``` +GET /groups/:id/epics/:epic_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5" +``` + +响应示例: + +``` +{ "id": 30, "iid": 5, "group_id": 7, "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "state": "opened", "web_url": "http://localhost:3001/groups/test/-/epics/5", "reference": "&5", "references": { "short": "&5", "relative": "&5", "full": "test&5" }, "author":{ "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, "downvotes": 0, "subscribed": true } +``` + +## New epic[](#new-epic "Permalink") + +创建一个新的史诗. + +**注意:**从 GitLab [11.3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6448)开始,不应再直接分配`start_date`和`end_date` ,因为它们现在表示复合值. 您可以改为通过`*_is_fixed`和`*_fixed`字段进行配置. + +``` +POST /groups/:id/epics +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `title` | string | yes | 史诗的标题 | +| `labels` | string | no | 以逗号分隔的标签列表 | +| `description` | string | no | 史诗般的描述. 限制为 1,048,576 个字符. | +| `confidential` | boolean | no | 史诗是否应该保密. 如果禁用`confidential_epics`功能标志,将被忽略. | +| `start_date_is_fixed` | boolean | no | 开始日期是从`start_date_fixed`还是从里程碑(自 11.3 开始) | +| `start_date_fixed` | string | no | 史诗的固定开始日期(自 11.3 开始) | +| `due_date_is_fixed` | boolean | no | 是否应从`due_date_fixed`或里程碑(从 11.3 开始)中`due_date_fixed`到期日期 | +| `due_date_fixed` | string | no | 史诗的固定到期日(自 11.3 开始) | +| `parent_id` | integer/string | no | 父级史诗的 ID(自 11.11 起) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics?title=Epic&description=Epic%20description" +``` + +响应示例: + +``` +{ "id": 33, "iid": 6, "group_id": 7, "title": "Epic", "description": "Epic description", "state": "opened", "confidential": "false", "web_url": "http://localhost:3001/groups/test/-/epics/6", "reference": "&6", "references": { "short": "&6", "relative": "&6", "full": "test&6" }, "author": { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, "downvotes": 0 } +``` + +## Update epic[](#update-epic "Permalink") + +更新史诗. + +**注意:**从 GitLab [11.3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6448)开始,不应再直接分配`start_date`和`end_date` ,因为它们现在表示复合值. 您可以改为通过`*_is_fixed`和`*_fixed`字段进行配置. + +``` +PUT /groups/:id/epics/:epic_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID | +| `title` | string | no | 史诗的标题 | +| `description` | string | no | 史诗的描述. 限制为 1,048,576 个字符. | +| `confidential` | boolean | no | 史诗是否应该保密. 如果禁用`confidential_epics`功能标志,将被忽略. | +| `labels` | string | no | 以逗号分隔的标签列表 | +| `start_date_is_fixed` | boolean | no | 开始日期是从`start_date_fixed`还是从里程碑(自 11.3 开始) | +| `start_date_fixed` | string | no | 史诗的固定开始日期(自 11.3 开始) | +| `due_date_is_fixed` | boolean | no | 是否应从`due_date_fixed`或里程碑(从 11.3 开始)中`due_date_fixed`到期日期 | +| `due_date_fixed` | string | no | 史诗的固定到期日(自 11.3 开始) | +| `state_event` | string | no | 史诗般的状态事件. 设置为`close`以关闭史诗,然后`reopen`以重新打开(自 11.4 开始) | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5?title=New%20Title" +``` + +响应示例: + +``` +{ "id": 33, "iid": 6, "group_id": 7, "title": "New Title", "description": "Epic description", "state": "opened", "confidential": "false", "web_url": "http://localhost:3001/groups/test/-/epics/6", "reference": "&6", "references": { "short": "&6", "relative": "&6", "full": "test&6" }, "author": { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, "downvotes": 0 } +``` + +## Delete epic[](#delete-epic "Permalink") + +删除史诗 + +``` +DELETE /groups/:id/epics/:epic_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5" +``` + +## Create a todo[](#create-a-todo "Permalink") + +在史诗上为当前用户手动创建待办事项. 如果该史诗上已经存在用户的待办事项,则返回状态码`304` . + +``` +POST /groups/:id/epics/:epic_iid/todo +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer | yes | 群组史诗的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/todo" +``` + +响应示例: + +``` +{ "id": 112, "group": { "id": 1, "name": "Gitlab", "path": "gitlab", "kind": "group", "full_path": "base/gitlab", "parent_id": null }, "author": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "action_name": "marked", "target_type": "epic", "target": { "id": 30, "iid": 5, "group_id": 1, "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author":{ "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }, "web_url": "http://localhost:3001/groups/test/-/epics/5", "reference": "&5", "references": { "short": "&5", "relative": "&5", "full": "test&5" }, "start_date": null, "end_date": null, "created_at": "2018-01-21T06:21:13.165Z", "updated_at": "2018-01-22T12:41:41.166Z", "closed_at": "2018-08-18T12:22:05.239Z" }, "target_url": "https://gitlab.example.com/groups/epics/5", "body": "Vel voluptas atque dicta mollitia adipisci qui at.", "state": "pending", "created_at": "2016-07-01T11:09:13.992Z" } +``` \ No newline at end of file diff --git a/docs/312.md b/docs/312.md new file mode 100644 index 0000000000000000000000000000000000000000..ab925710125313d08409ac572631809a2c9a999a --- /dev/null +++ b/docs/312.md @@ -0,0 +1,157 @@ +# Events + +> 原文:[https://docs.gitlab.com/ee/api/events.html](https://docs.gitlab.com/ee/api/events.html) + +* [Filter parameters](#filter-parameters) + * [Action Types](#action-types) + * [Target Types](#target-types) + * [Date formatting](#date-formatting) + * [Event Time Period Limit](#event-time-period-limit) +* [List currently authenticated user’s events](#list-currently-authenticated-users-events) + * [Get user contribution events](#get-user-contribution-events) +* [List a Project’s visible events](#list-a-projects-visible-events) + +# Events[](#events "Permalink") + +## Filter parameters[](#filter-parameters "Permalink") + +### Action Types[](#action-types "Permalink") + +`action`参数的可用操作类型为: + +* `created` +* `updated` +* `closed` +* `reopened` +* `pushed` +* `commented` +* `merged` +* `joined` +* `left` +* `destroyed` +* `expired` + +请注意,这些选项是小写的. + +### Target Types[](#target-types "Permalink") + +`target_type`参数的可用目标类型为: + +* `issue` +* `milestone` +* `merge_request` +* `note` +* `project` +* `snippet` +* `user` + +请注意,这些选项是小写的. + +### Date formatting[](#date-formatting "Permalink") + +`before`和`after`参数的日期应以以下格式提供: + +``` +YYYY-MM-DD +``` + +### Event Time Period Limit[](#event-time-period-limit "Permalink") + +GitLab removes events older than 2 years from the events table for performance reasons. + +## List currently authenticated user’s events[](#list-currently-authenticated-users-events "Permalink") + +**注意:**该端点是在 GitLab 9.3 中引入的. 在 GitLab 11.3 中引入了`read_user`访问. + +获取经过身份验证的用户的事件列表. 范围`read_user`或`api`是必需的. + +``` +GET /events +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `action` | string | no | 仅包括特定[动作类型的](#action-types)事件 | +| `target_type` | string | no | 仅包括特定[目标类型的](#target-types)事件 | +| `before` | date | no | 仅包括在特定日期之前创建的事件. 请[在此处查看受支持的格式](#date-formatting) | +| `after` | date | no | 仅包括在特定日期之后创建的事件. 请[在此处查看受支持的格式](#date-formatting) | +| `scope` | string | no | 包括用户项目中的所有事件. | +| `sort` | string | no | 按`created_at`对事件进行`asc`或`desc`排序. 默认为`desc` | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/events?target_type=issue&action=created&after=2017-01-31&before=2017-03-01&scope=all" +``` + +响应示例: + +``` +[ { "title":null, "project_id":1, "action_name":"opened", "target_id":160, "target_type":"Issue", "author_id":25, "target_title":"Qui natus eos odio tempore et quaerat consequuntur ducimus cupiditate quis.", "created_at":"2017-02-09T10:43:19.667Z", "author":{ "name":"User 3", "username":"user3", "id":25, "state":"active", "avatar_url":"http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/user3" }, "author_username":"user3" }, { "title":null, "project_id":1, "action_name":"opened", "target_id":159, "target_type":"Issue", "author_id":21, "target_title":"Nostrum enim non et sed optio illo deleniti non.", "created_at":"2017-02-09T10:43:19.426Z", "author":{ "name":"Test User", "username":"ted", "id":21, "state":"active", "avatar_url":"http://www.gravatar.com/avatar/80fb888c9a48b9a3f87477214acaa63f?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/ted" }, "author_username":"ted" } ] +``` + +### Get user contribution events[](#get-user-contribution-events "Permalink") + +**注意:**文档以前位于" [用户 API"页面中](users.html) . 在 GitLab 11.3 中引入了`read_user`访问. + +获取指定用户的贡献事件,从最新到最旧排序. 范围`read_user`或`api`是必需的. + +``` +GET /users/:id/events +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 用户的 ID 或用户名 | +| `action` | string | no | 仅包括特定[动作类型的](#action-types)事件 | +| `target_type` | string | no | 仅包括特定[目标类型的](#target-types)事件 | +| `before` | date | no | 仅包括在特定日期之前创建的事件. 请[在此处查看受支持的格式](#date-formatting) | +| `after` | date | no | 仅包括在特定日期之后创建的事件. 请[在此处查看受支持的格式](#date-formatting) | +| `sort` | string | no | 按`created_at`对事件进行`asc`或`desc`排序. 默认为`desc` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/:id/events" +``` + +响应示例: + +``` +[ { "title": null, "project_id": 15, "action_name": "closed", "target_id": 830, "target_type": "Issue", "author_id": 1, "target_title": "Public project search field", "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", "web_url": "http://localhost:3000/root" }, "author_username": "root" }, { "title": null, "project_id": 15, "action_name": "pushed", "target_id": null, "target_type": null, "author_id": 1, "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", "web_url": "http://localhost:3000/root" }, "author_username": "john", "push_data": { "commit_count": 1, "action": "pushed", "ref_type": "branch", "commit_from": "50d4420237a9de7be1304607147aec22e4a14af7", "commit_to": "c5feabde2d8cd023215af4d2ceeb7a64839fc428", "ref": "master", "commit_title": "Add simple search to projects in public area" }, "target_title": null }, { "title": null, "project_id": 15, "action_name": "closed", "target_id": 840, "target_type": "Issue", "author_id": 1, "target_title": "Finish & merge Code search PR", "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", "web_url": "http://localhost:3000/root" }, "author_username": "root" }, { "title": null, "project_id": 15, "action_name": "commented on", "target_id": 1312, "target_type": "Note", "author_id": 1, "target_title": null, "created_at": "2015-12-04T10:33:58.089Z", "note": { "id": 1312, "body": "What an awesome day!", "attachment": null, "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", "web_url": "http://localhost:3000/root" }, "created_at": "2015-12-04T10:33:56.698Z", "system": false, "noteable_id": 377, "noteable_type": "Issue" }, "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png", "web_url": "http://localhost:3000/root" }, "author_username": "root" } ] +``` + +## List a Project’s visible events[](#list-a-projects-visible-events "Permalink") + +> **注意:**此端点的时间比其他端点长. 文档以前位于[Projects API 页面中](projects.html) . + +获取特定项目的可见事件列表. + +``` +GET /projects/:project_id/events +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `project_id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `action` | string | no | 仅包括特定[动作类型的](#action-types)事件 | +| `target_type` | string | no | 仅包括特定[目标类型的](#target-types)事件 | +| `before` | date | no | 仅包括在特定日期之前创建的事件. 请[在此处查看受支持的格式](#date-formatting) | +| `after` | date | no | 仅包括在特定日期之后创建的事件. 请[在此处查看受支持的格式](#date-formatting) | +| `sort` | string | no | 按`created_at`对事件进行`asc`或`desc`排序. 默认为`desc` | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:project_id/events?target_type=issue&action=created&after=2017-01-31&before=2017-03-01" +``` + +响应示例: + +``` +[ { "title":null, "project_id":1, "action_name":"opened", "target_id":160, "target_iid":160, "target_type":"Issue", "author_id":25, "target_title":"Qui natus eos odio tempore et quaerat consequuntur ducimus cupiditate quis.", "created_at":"2017-02-09T10:43:19.667Z", "author":{ "name":"User 3", "username":"user3", "id":25, "state":"active", "avatar_url":"http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/user3" }, "author_username":"user3" }, { "title":null, "project_id":1, "action_name":"opened", "target_id":159, "target_iid":159, "target_type":"Issue", "author_id":21, "target_title":"Nostrum enim non et sed optio illo deleniti non.", "created_at":"2017-02-09T10:43:19.426Z", "author":{ "name":"Test User", "username":"ted", "id":21, "state":"active", "avatar_url":"http://www.gravatar.com/avatar/80fb888c9a48b9a3f87477214acaa63f?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/ted" }, "author_username":"ted" }, { "title": null, "project_id": 1, "action_name": "commented on", "target_id": 1312, "target_iid": 1312, "target_type": "Note", "author_id": 1, "data": null, "target_title": null, "created_at": "2015-12-04T10:33:58.089Z", "note": { "id": 1312, "body": "What an awesome day!", "attachment": null, "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "https://gitlab.example.com/uploads/user/avatar/1/fox_avatar.png", "web_url": "https://gitlab.example.com/root" }, "created_at": "2015-12-04T10:33:56.698Z", "system": false, "noteable_id": 377, "noteable_type": "Issue", "noteable_iid": 377 }, "author": { "name": "Dmitriy Zaporozhets", "username": "root", "id": 1, "state": "active", "avatar_url": "https://gitlab.example.com/uploads/user/avatar/1/fox_avatar.png", "web_url": "https://gitlab.example.com/root" }, "author_username": "root" } ] +``` \ No newline at end of file diff --git a/docs/313.md b/docs/313.md new file mode 100644 index 0000000000000000000000000000000000000000..a62c22d15fe46a1578426d736b17c33df8b3c5c4 --- /dev/null +++ b/docs/313.md @@ -0,0 +1,160 @@ +# Feature Flags API + +> 原文:[https://docs.gitlab.com/ee/api/feature_flags.html](https://docs.gitlab.com/ee/api/feature_flags.html) + +* [Feature Flags pagination](#feature-flags-pagination) +* [List feature flags for a project](#list-feature-flags-for-a-project) +* [Get a single feature flag](#get-a-single-feature-flag) +* [Create a feature flag](#create-a-feature-flag) +* [Update a feature flag](#update-a-feature-flag) +* [Delete a feature flag](#delete-a-feature-flag) + +# Feature Flags API[](#feature-flags-api-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5. + +**注意:**此 API 位于[功能标志的](../operations/feature_flags.html#enable-or-disable-feature-flag-strategies)后面. 如果您的环境中未启用此标志,则可以使用[旧功能标志 API](feature_flags_legacy.html) . + +用于访问[GitLab 功能标记](../operations/feature_flags.html)资源的 API. + +具有开发者或更高[权限的用户](../user/permissions.html)可以访问功能标记 API. + +## Feature Flags pagination[](#feature-flags-pagination "Permalink") + +默认情况下,因为 API 结果是[分页的](README.html#pagination) ,所以`GET`请求一次返回 20 个结果. + +## List feature flags for a project[](#list-feature-flags-for-a-project "Permalink") + +获取所请求项目的所有功能标志. + +``` +GET /projects/:id/feature_flags +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `scope` | string | no | 功能标志的条件,其中之一: `enabled` , `disabled` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/feature_flags" +``` + +响应示例: + +``` +[ { "name":"merge_train", "description":"This feature is about merge train", "version": "new_version_flag", "created_at":"2019-11-04T08:13:51.423Z", "updated_at":"2019-11-04T08:13:51.423Z", "scopes":[], "strategies": [ { "id": 1, "name": "userWithId", "parameters": { "userIds": "user1" }, "scopes": [ { "id": 1, "environment_scope": "production" } ] } ] }, { "name":"new_live_trace", "description":"This is a new live trace feature", "version": "new_version_flag", "created_at":"2019-11-04T08:13:10.507Z", "updated_at":"2019-11-04T08:13:10.507Z", "scopes":[] "strategies": [ { "id": 2, "name": "default", "parameters": {}, "scopes": [ { "id": 2, "environment_scope": "staging" } ] } ] } ] +``` + +## Get a single feature flag[](#get-a-single-feature-flag "Permalink") + +获取单个功能标志. + +``` +GET /projects/:id/feature_flags/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `name` | string | yes | The name of the feature flag. | + +``` +curl --header "PRIVATE-TOKEN: " https://gitlab.example.com/api/v4/projects/1/feature_flags/awesome_feature +``` + +响应示例: + +``` +{ "name": "awesome_feature", "description": null, "version": "new_version_flag", "created_at": "2020-05-13T19:56:33.119Z", "updated_at": "2020-05-13T19:56:33.119Z", "scopes": [], "strategies": [ { "id": 36, "name": "default", "parameters": {}, "scopes": [ { "id": 37, "environment_scope": "production" } ] } ] } +``` + +## Create a feature flag[](#create-a-feature-flag "Permalink") + +创建一个新的功能标志. + +``` +POST /projects/:id/feature_flags +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `name` | string | yes | 功能标志的名称. | +| `version` | string | yes | 功能标志的版本. 必须是`new_version_flag` . 省略或设置为`legacy_flag`即可创建[旧版功能标志](feature_flags_legacy.html) . | +| `description` | string | no | 功能标志的描述. | +| `strategies` | JSON | no | 特征标志[策略](../operations/feature_flags.html#feature-flag-strategies) . | +| `strategies:name` | JSON | no | 策略名称. | +| `strategies:parameters` | JSON | no | 策略参数. | +| `strategies:scopes` | JSON | no | 策略的范围. | +| `strategies:scopes:environment_scope` | string | no | 范围的环境规格. | + +``` +curl "https://gitlab.example.com/api/v4/projects/1/feature_flags" \ + --header "PRIVATE-TOKEN: " \ + --header "Content-type: application/json" \ + --data @- << EOF { + "name": "awesome_feature", + "version": "new_version_flag", + "strategies": [{ "name": "default", "parameters": {}, "scopes": [{ "environment_scope": "production" }] }] +} EOF +``` + +响应示例: + +``` +{ "name": "awesome_feature", "description": null, "version": "new_version_flag", "created_at": "2020-05-13T19:56:33.119Z", "updated_at": "2020-05-13T19:56:33.119Z", "scopes": [], "strategies": [ { "id": 36, "name": "default", "parameters": {}, "scopes": [ { "id": 37, "environment_scope": "production" } ] } ] } +``` + +## Update a feature flag[](#update-a-feature-flag "Permalink") + +更新功能标志. + +``` +PUT /projects/:id/feature_flags/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `name` | string | yes | 功能标志的名称. | +| `description` | string | no | 功能标志的描述. | +| `strategies` | JSON | no | 特征标志[策略](../operations/feature_flags.html#feature-flag-strategies) . | +| `strategies:id` | JSON | no | 功能标记策略 ID. | +| `strategies:name` | JSON | no | 策略名称. | +| `strategies:parameters` | JSON | no | 策略参数. | +| `strategies:scopes` | JSON | no | 策略的范围. | +| `strategies:scopes:id` | JSON | no | 范围 ID. | +| `strategies:scopes:environment_scope` | string | no | 范围的环境规格. | + +``` +curl "https://gitlab.example.com/api/v4/projects/1/feature_flags/awesome_feature" \ + --header "PRIVATE-TOKEN: " \ + --header "Content-type: application/json" \ + --data @- << EOF { + "strategies": [{ "name": "gradualRolloutUserId", "parameters": { "groupId": "default", "percentage": "25" }, "scopes": [{ "environment_scope": "staging" }] }] +} EOF +``` + +响应示例: + +``` +{ "name": "awesome_feature", "description": null, "version": "new_version_flag", "created_at": "2020-05-13T20:10:32.891Z", "updated_at": "2020-05-13T20:10:32.891Z", "scopes": [], "strategies": [ { "id": 38, "name": "gradualRolloutUserId", "parameters": { "groupId": "default", "percentage": "25" }, "scopes": [ { "id": 40, "environment_scope": "staging" } ] }, { "id": 37, "name": "default", "parameters": {}, "scopes": [ { "id": 39, "environment_scope": "production" } ] } ] } +``` + +## Delete a feature flag[](#delete-a-feature-flag "Permalink") + +删除功能标志. + +``` +DELETE /projects/:id/feature_flags/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `name` | string | yes | 功能标志的名称. | + +``` +curl --header "PRIVATE-TOKEN: " --request DELETE "https://gitlab.example.com/api/v4/projects/1/feature_flags/awesome_feature" +``` \ No newline at end of file diff --git a/docs/314.md b/docs/314.md new file mode 100644 index 0000000000000000000000000000000000000000..5127fc0288d4243b900553d132e9543afe99489d --- /dev/null +++ b/docs/314.md @@ -0,0 +1,142 @@ +# Feature flag user lists API + +> 原文:[https://docs.gitlab.com/ee/api/feature_flag_user_lists.html](https://docs.gitlab.com/ee/api/feature_flag_user_lists.html) + +* [List all feature flag user lists for a project](#list-all-feature-flag-user-lists-for-a-project) +* [Create a feature flag user list](#create-a-feature-flag-user-list) +* [Get a feature flag user list](#get-a-feature-flag-user-list) +* [Update a feature flag user list](#update-a-feature-flag-user-list) +* [Delete feature flag user list](#delete-feature-flag-user-list) + +# Feature flag user lists API[](#feature-flag-user-lists-api-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/205409) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10. + +用于访问 GitLab 功能标志用户列表的 API. + +具有开发者或更高[权限的用户](../user/permissions.html)可以访问功能标志用户列表 API. + +**注意:** `GET`请求一次返回 20 个结果,因为 API 结果是[分页的](README.html#pagination) . 您可以更改此值. + +## List all feature flag user lists for a project[](#list-all-feature-flag-user-lists-for-a-project "Permalink") + +获取所请求项目的所有功能标志用户列表. + +``` +GET /projects/:id/feature_flags_user_lists +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists" +``` + +响应示例: + +``` +[ { "name": "user_list", "user_xids": "user1,user2", "id": 1, "iid": 1, "project_id": 1, "created_at": "2020-02-04T08:13:51.423Z", "updated_at": "2020-02-04T08:13:51.423Z" }, { "name": "test_users", "user_xids": "user3,user4,user5", "id": 2, "iid": 2, "project_id": 1, "created_at": "2020-02-04T08:13:10.507Z", "updated_at": "2020-02-04T08:13:10.507Z" } ] +``` + +## Create a feature flag user list[](#create-a-feature-flag-user-list "Permalink") + +创建功能标记用户列表. + +``` +POST /projects/:id/feature_flags_user_lists +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `name` | string | yes | 功能标志的名称. | +| `user_xids` | string | yes | 以逗号分隔的用户 ID 列表. | + +``` +curl "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists" \ + --header "PRIVATE-TOKEN: " \ + --header "Content-type: application/json" \ + --data @- << EOF { + "name": "my_user_list", + "user_xids": "user1,user2,user3" +} EOF +``` + +响应示例: + +``` +{ "name": "my_user_list", "user_xids": "user1,user2,user3", "id": 1, "iid": 1, "project_id": 1, "created_at": "2020-02-04T08:32:27.288Z", "updated_at": "2020-02-04T08:32:27.288Z" } +``` + +## Get a feature flag user list[](#get-a-feature-flag-user-list "Permalink") + +获取功能标志用户列表. + +``` +GET /projects/:id/feature_flags_user_lists/:iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `iid` | integer/string | yes | 项目的功能标志用户列表的内部 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists/1" +``` + +响应示例: + +``` +{ "name": "my_user_list", "user_xids": "123,456", "id": 1, "iid": 1, "project_id": 1, "created_at": "2020-02-04T08:13:10.507Z", "updated_at": "2020-02-04T08:13:10.507Z", } +``` + +## Update a feature flag user list[](#update-a-feature-flag-user-list "Permalink") + +更新功能标志用户列表. + +``` +PUT /projects/:id/feature_flags_user_lists/:iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `iid` | integer/string | yes | 项目的功能标志用户列表的内部 ID. | +| `name` | string | no | 功能标志的名称. | +| `user_xids` | string | no | 以逗号分隔的用户 ID 列表. | + +``` +curl "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists/1" \ + --header "PRIVATE-TOKEN: " \ + --header "Content-type: application/json" \ + --request PUT \ + --data @- << EOF { + "user_xids": "user2,user3,user4" +} EOF +``` + +响应示例: + +``` +{ "name": "my_user_list", "user_xids": "user2,user3,user4", "id": 1, "iid": 1, "project_id": 1, "created_at": "2020-02-04T08:32:27.288Z", "updated_at": "2020-02-05T09:33:17.179Z" } +``` + +## Delete feature flag user list[](#delete-feature-flag-user-list "Permalink") + +删除功能标志用户列表. + +``` +DELETE /projects/:id/feature_flags_user_lists/:iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `iid` | integer/string | yes | 项目的功能标志用户列表的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " --request DELETE "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists/1" +``` \ No newline at end of file diff --git a/docs/315.md b/docs/315.md new file mode 100644 index 0000000000000000000000000000000000000000..25cd7e923c4f80a25ae79a5906e2aae2231269aa --- /dev/null +++ b/docs/315.md @@ -0,0 +1,147 @@ +# Freeze Periods API + +> 原文:[https://docs.gitlab.com/ee/api/freeze_periods.html](https://docs.gitlab.com/ee/api/freeze_periods.html) + +* [Permissions and security](#permissions-and-security) +* [List Freeze Periods](#list-freeze-periods) +* [Get a Freeze Period by a `freeze_period_id`](#get-a-freeze-period-by-a-freeze_period_id) +* [Create a Freeze Period](#create-a-freeze-period) +* [Update a Freeze Period](#update-a-freeze-period) +* [Delete a Freeze Period](#delete-a-freeze-period) + +# Freeze Periods API[](#freeze-periods-api "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29382) . + +您可以使用 Freeze Periods API 来操纵 GitLab 的[Freeze Period](../user/project/releases/index.html#prevent-unintentional-releases-by-setting-a-deploy-freeze)条目. + +## Permissions and security[](#permissions-and-security "Permalink") + +只有具有维护者[权限的](../user/permissions.html)用户才能与 Freeze Period API 端点进行交互. + +## List Freeze Periods[](#list-freeze-periods "Permalink") + +冻结期间的分页列表,按`created_at`升序排序. + +``` +GET /projects/:id/freeze_periods +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" "https://gitlab.example.com/api/v4/projects/19/freeze_periods" +``` + +响应示例: + +``` +[ { "id":1, "freeze_start":"0 23 * * 5", "freeze_end":"0 8 * * 1", "cron_timezone":"UTC", "created_at":"2020-05-15T17:03:35.702Z", "updated_at":"2020-05-15T17:06:41.566Z" } ] +``` + +## Get a Freeze Period by a `freeze_period_id`[](#get-a-freeze-period-by-a-freeze_period_id "Permalink") + +获取给定的`freeze_period_id`的冻结期. + +``` +GET /projects/:id/freeze_periods/:freeze_period_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `freeze_period_id` | string | yes | 冻结期的数据库 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" "https://gitlab.example.com/api/v4/projects/19/freeze_periods/1" +``` + +响应示例: + +``` +{ "id":1, "freeze_start":"0 23 * * 5", "freeze_end":"0 8 * * 1", "cron_timezone":"UTC", "created_at":"2020-05-15T17:03:35.702Z", "updated_at":"2020-05-15T17:06:41.566Z" } +``` + +## Create a Freeze Period[](#create-a-freeze-period "Permalink") + +创建冻结期. + +``` +POST /projects/:id/freeze_periods +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `freeze_start` | string | yes | [Cron](https://crontab.guru/)格式的冻结期开始. | +| `freeze_end` | string | yes | [Cron](https://crontab.guru/)格式的冻结期结束. | +| `cron_timezone` | string | no | cron 字段的时区,如果未提供,则默认为 UTC. | + +请求示例: + +``` +curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" \ + --data '{ "freeze_start": "0 23 * * 5", "freeze_end": "0 7 * * 1", "cron_timezone": "UTC" }' \ + --request POST https://gitlab.example.com/api/v4/projects/19/freeze_periods +``` + +响应示例: + +``` +{ "id":1, "freeze_start":"0 23 * * 5", "freeze_end":"0 7 * * 1", "cron_timezone":"UTC", "created_at":"2020-05-15T17:03:35.702Z", "updated_at":"2020-05-15T17:03:35.702Z" } +``` + +## Update a Freeze Period[](#update-a-freeze-period "Permalink") + +为给定的`freeze_period_id`更新冻结期. + +``` +PUT /projects/:id/freeze_periods/:tag_name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `freeze_period_id` | 整数或字符串 | yes | 冻结期的数据库 ID. | +| `freeze_start` | string | no | [Cron](https://crontab.guru/)格式的冻结期开始. | +| `freeze_end` | string | no | [Cron](https://crontab.guru/)格式的冻结期结束. | +| `cron_timezone` | string | no | cron 字段的时区. | + +请求示例: + +``` +curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" \ + --data '{ "freeze_end": "0 8 * * 1" }' \ + --request PUT https://gitlab.example.com/api/v4/projects/19/freeze_periods/1 +``` + +响应示例: + +``` +{ "id":1, "freeze_start":"0 23 * * 5", "freeze_end":"0 8 * * 1", "cron_timezone":"UTC", "created_at":"2020-05-15T17:03:35.702Z", "updated_at":"2020-05-15T17:06:41.566Z" } +``` + +## Delete a Freeze Period[](#delete-a-freeze-period "Permalink") + +删除给定的`freeze_period_id`的冻结期. + +``` +DELETE /projects/:id/freeze_periods/:freeze_period_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) . | +| `freeze_period_id` | string | yes | 冻结期的数据库 ID. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" "https://gitlab.example.com/api/v4/projects/19/freeze_periods/1" +``` \ No newline at end of file diff --git a/docs/316.md b/docs/316.md new file mode 100644 index 0000000000000000000000000000000000000000..1930d6cdec7c780dbea2111dce0874ac8929038c --- /dev/null +++ b/docs/316.md @@ -0,0 +1,213 @@ +# Geo Nodes API + +> 原文:[https://docs.gitlab.com/ee/api/geo_nodes.html](https://docs.gitlab.com/ee/api/geo_nodes.html) + +* [Create a new Geo node](#create-a-new-geo-node) +* [Retrieve configuration about all Geo nodes](#retrieve-configuration-about-all-geo-nodes) +* [Retrieve configuration about a specific Geo node](#retrieve-configuration-about-a-specific-geo-node) +* [Edit a Geo node](#edit-a-geo-node) +* [Delete a Geo node](#delete-a-geo-node) +* [Repair a Geo node](#repair-a-geo-node) +* [Retrieve status about all Geo nodes](#retrieve-status-about-all-geo-nodes) +* [Retrieve status about a specific Geo node](#retrieve-status-about-a-specific-geo-node) +* [Retrieve project sync or verification failures that occurred on the current node](#retrieve-project-sync-or-verification-failures-that-occurred-on-the-current-node) + +# Geo Nodes API[](#geo-nodes-api-premium-only "Permalink") + +为了与地理节点端点进行交互,您需要以管理员身份进行身份验证. + +## Create a new Geo node[](#create-a-new-geo-node "Permalink") + +创建一个新的地理节点. + +``` +POST /geo_nodes +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/geo_nodes" \ + --request POST \ + -d "name=himynameissomething" \ + -d "url=https://another-node.example.com/" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `primary` | boolean | no | 指定此节点是否为主节点. 默认为 false. | +| `enabled` | boolean | no | 指示是否启用地理节点的标志. 默认为 true. | +| `name` | string | yes | 地理节点的唯一标识符. 必须匹配`geo_node_name`如果在设定`gitlab.rb` ,否则必须匹配`external_url` | +| `url` | string | yes | Geo 节点的面向用户的 URL. | +| `internal_url` | string | no | 在主节点上定义的 URL,辅助节点应使用该 URL 与之联系. 如果未设置,则返回`url` . | +| `files_max_capacity` | integer | no | 控制此辅助节点的 LFS /附件回填的最大并发性. 默认为 10 | +| `repos_max_capacity` | integer | no | 控制此辅助节点的存储库回填的最大并发性. 默认为 25. | +| `verification_max_capacity` | integer | no | 控制此节点的存储库验证的最大并发性. 默认为 100. | +| `container_repositories_max_capacity` | integer | no | 控制此节点的容器存储库同步的最大并发性. 默认为 10 | +| `sync_object_storage` | boolean | no | 指示辅助 Geo 节点是否将复制对象存储中的 Blob 的标志. 默认为 false. | +| `selective_sync_type` | string | no | Limit syncing to only specific groups or shards. Valid values: `"namespaces"`, `"shards"`, or `null`. | +| `selective_sync_shards` | array | no | 如果`selective_sync_type` == `shards` ,则同步项目的存储库存储. | +| `selective_sync_namespace_ids` | array | no | 如果`selective_sync_type` == `namespaces` ,则应同步的组的 ID. | +| `minimum_reverification_interval` | integer | no | 存储库验证有效的时间间隔(以天为单位). 一旦过期,它将被重新验证. 在辅助节点上进行设置时,这无效. | + +响应示例: + +``` +{ "id": 3, "name": "Test Node 1", "url": "https://secondary.example.com/", "internal_url": "https://secondary.example.com/", "primary": false, "enabled": true, "current": false, "files_max_capacity": 10, "repos_max_capacity": 25, "verification_max_capacity": 100, "selective_sync_type": "namespaces", "selective_sync_shards": [], "selective_sync_namespace_ids": [1, 25], "minimum_reverification_interval": 7, "container_repositories_max_capacity": 10, "sync_object_storage": false, "clone_protocol": "http", "web_edit_url": "https://primary.example.com/admin/geo/nodes/3/edit", "web_geo_projects_url": "http://secondary.example.com/admin/geo/projects", "_links": { "self": "https://primary.example.com/api/v4/geo_nodes/3", "status": "https://primary.example.com/api/v4/geo_nodes/3/status", "repair": "https://primary.example.com/api/v4/geo_nodes/3/repair" } } +``` + +## Retrieve configuration about all Geo nodes[](#retrieve-configuration-about-all-geo-nodes "Permalink") + +``` +GET /geo_nodes +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/geo_nodes" +``` + +响应示例: + +``` +[ { "id": 1, "name": "us-node", "url": "https://primary.example.com/", "internal_url": "https://internal.example.com/", "primary": true, "enabled": true, "current": true, "files_max_capacity": 10, "repos_max_capacity": 25, "container_repositories_max_capacity": 10, "verification_max_capacity": 100, "selective_sync_type": "namespaces", "selective_sync_shards": [], "selective_sync_namespace_ids": [1, 25], "minimum_reverification_interval": 7, "clone_protocol": "http", "web_edit_url": "https://primary.example.com/admin/geo/nodes/1/edit", "_links": { "self": "https://primary.example.com/api/v4/geo_nodes/1", "status":"https://primary.example.com/api/v4/geo_nodes/1/status", "repair":"https://primary.example.com/api/v4/geo_nodes/1/repair" } }, { "id": 2, "name": "cn-node", "url": "https://secondary.example.com/", "internal_url": "https://secondary.example.com/", "primary": false, "enabled": true, "current": false, "files_max_capacity": 10, "repos_max_capacity": 25, "container_repositories_max_capacity": 10, "verification_max_capacity": 100, "selective_sync_type": "namespaces", "selective_sync_shards": [], "selective_sync_namespace_ids": [1, 25], "minimum_reverification_interval": 7, "sync_object_storage": true, "clone_protocol": "http", "web_edit_url": "https://primary.example.com/admin/geo/nodes/2/edit", "web_geo_projects_url": "https://secondary.example.com/admin/geo/projects", "_links": { "self":"https://primary.example.com/api/v4/geo_nodes/2", "status":"https://primary.example.com/api/v4/geo_nodes/2/status", "repair":"https://primary.example.com/api/v4/geo_nodes/2/repair" } } ] +``` + +## Retrieve configuration about a specific Geo node[](#retrieve-configuration-about-a-specific-geo-node "Permalink") + +``` +GET /geo_nodes/:id +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/geo_nodes/1" +``` + +响应示例: + +``` +{ "id": 1, "name": "us-node", "url": "https://primary.example.com/", "internal_url": "https://primary.example.com/", "primary": true, "enabled": true, "current": true, "files_max_capacity": 10, "repos_max_capacity": 25, "container_repositories_max_capacity": 10, "verification_max_capacity": 100, "selective_sync_type": "namespaces", "selective_sync_shards": [], "selective_sync_namespace_ids": [1, 25], "minimum_reverification_interval": 7, "clone_protocol": "http", "web_edit_url": "https://primary.example.com/admin/geo/nodes/1/edit", "_links": { "self": "https://primary.example.com/api/v4/geo_nodes/1", "status":"https://primary.example.com/api/v4/geo_nodes/1/status", "repair":"https://primary.example.com/api/v4/geo_nodes/1/repair" } } +``` + +## Edit a Geo node[](#edit-a-geo-node "Permalink") + +更新现有地理节点的设置. + +*这只能在主要的地理节点上运行.* + +``` +PUT /geo_nodes/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 地理位置节点的 ID. | +| `enabled` | boolean | no | 指示是否启用地理节点的标志. | +| `name` | string | yes | 地理节点的唯一标识符. 必须匹配`geo_node_name`如果在设定`gitlab.rb` ,否则必须匹配`external_url` . | +| `url` | string | yes | Geo 节点的面向用户的 URL. | +| `internal_url` | string | no | 在主节点上定义的 URL,辅助节点应使用该 URL 与之联系. 如果未设置,则返回`url` . | +| `files_max_capacity` | integer | no | 控制此辅助节点的 LFS /附件回填的最大并发性. | +| `repos_max_capacity` | integer | no | 控制此辅助节点的存储库回填的最大并发性. | +| `verification_max_capacity` | integer | no | 控制此节点的最大并发验证. | +| `container_repositories_max_capacity` | integer | no | 控制此节点的容器存储库同步的最大并发性. | +| `sync_object_storage` | boolean | no | 指示辅助 Geo 节点是否将复制对象存储中的 Blob 的标志. | +| `selective_sync_type` | string | no | 将同步限制为仅特定的组或碎片. 有效值: `"namespaces"` , `"shards"`或`null` . | +| `selective_sync_shards` | array | no | 如果`selective_sync_type` == `shards` ,则同步项目的存储库存储. | +| `selective_sync_namespace_ids` | array | no | 如果`selective_sync_type` == `namespaces` ,则应同步的组的 ID. | +| `minimum_reverification_interval` | integer | no | 存储库验证有效的时间间隔(以天为单位). 一旦过期,它将被重新验证. 在辅助节点上进行设置时,这无效. | + +响应示例: + +``` +{ "id": 1, "name": "cn-node", "url": "https://secondary.example.com/", "internal_url": "https://secondary.example.com/", "primary": false, "enabled": true, "current": true, "files_max_capacity": 10, "repos_max_capacity": 25, "container_repositories_max_capacity": 10, "verification_max_capacity": 100, "selective_sync_type": "namespaces", "selective_sync_shards": [], "selective_sync_namespace_ids": [1, 25], "minimum_reverification_interval": 7, "sync_object_storage": true, "clone_protocol": "http", "web_edit_url": "https://primary.example.com/admin/geo/nodes/2/edit", "web_geo_projects_url": "https://secondary.example.com/admin/geo/projects", "_links": { "self":"https://primary.example.com/api/v4/geo_nodes/2", "status":"https://primary.example.com/api/v4/geo_nodes/2/status", "repair":"https://primary.example.com/api/v4/geo_nodes/2/repair" } } +``` + +## Delete a Geo node[](#delete-a-geo-node "Permalink") + +删除地理节点. + +**注意:**只有 Geo 主节点将接受此请求. + +``` +DELETE /geo_nodes/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 地理位置节点的 ID. | + +## Repair a Geo node[](#repair-a-geo-node "Permalink") + +修复地理节点的 OAuth 身份验证. + +*这只能在主要的地理节点上运行.* + +``` +POST /geo_nodes/:id/repair +``` + +响应示例: + +``` +{ "id": 1, "name": "us-node", "url": "https://primary.example.com/", "internal_url": "https://primary.example.com/", "primary": true, "enabled": true, "current": true, "files_max_capacity": 10, "repos_max_capacity": 25, "container_repositories_max_capacity": 10, "verification_max_capacity": 100, "clone_protocol": "http", "web_edit_url": "https://primary.example.com/admin/geo/nodes/1/edit", "_links": { "self": "https://primary.example.com/api/v4/geo_nodes/1", "status":"https://primary.example.com/api/v4/geo_nodes/1/status", "repair":"https://primary.example.com/api/v4/geo_nodes/1/repair" } } +``` + +## Retrieve status about all Geo nodes[](#retrieve-status-about-all-geo-nodes "Permalink") + +``` +GET /geo_nodes/status +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/geo_nodes/status" +``` + +响应示例: + +``` +[ { "geo_node_id": 1, "healthy": true, "health": "Healthy", "health_status": "Healthy", "missing_oauth_application": false, "attachments_count": 1, "attachments_synced_count": nil, "attachments_failed_count": nil, "attachments_synced_missing_on_primary_count": 0, "attachments_synced_in_percentage": "0.00%", "db_replication_lag_seconds": nil, "lfs_objects_count": 0, "lfs_objects_synced_count": nil, "lfs_objects_failed_count": nil, "lfs_objects_synced_missing_on_primary_count": 0, "lfs_objects_synced_in_percentage": "0.00%", "job_artifacts_count": 2, "job_artifacts_synced_count": nil, "job_artifacts_failed_count": nil, "job_artifacts_synced_missing_on_primary_count": 0, "job_artifacts_synced_in_percentage": "0.00%", "container_repositories_count": 3, "container_repositories_synced_count": nil, "container_repositories_failed_count": nil, "container_repositories_synced_in_percentage": "0.00%", "design_repositories_count": 3, "design_repositories_synced_count": nil, "design_repositories_failed_count": nil, "design_repositories_synced_in_percentage": "0.00%", "projects_count": 41, "repositories_failed_count": nil, "repositories_synced_count": nil, "repositories_synced_in_percentage": "0.00%", "wikis_failed_count": nil, "wikis_synced_count": nil, "wikis_synced_in_percentage": "0.00%", "replication_slots_count": 1, "replication_slots_used_count": 1, "replication_slots_used_in_percentage": "100.00%", "replication_slots_max_retained_wal_bytes": 0, "repositories_checked_count": 20, "repositories_checked_failed_count": 20, "repositories_checked_in_percentage": "100.00%", "repositories_checksummed_count": 20, "repositories_checksum_failed_count": 5, "repositories_checksummed_in_percentage": "48.78%", "wikis_checksummed_count": 10, "wikis_checksum_failed_count": 3, "wikis_checksummed_in_percentage": "24.39%", "repositories_verified_count": 20, "repositories_verification_failed_count": 5, "repositories_verified_in_percentage": "48.78%", "repositories_checksum_mismatch_count": 3, "wikis_verified_count": 10, "wikis_verification_failed_count": 3, "wikis_verified_in_percentage": "24.39%", "wikis_checksum_mismatch_count": 1, "repositories_retrying_verification_count": 1, "wikis_retrying_verification_count": 3, "repositories_checked_count": 7, "repositories_checked_failed_count": 2, "repositories_checked_in_percentage": "17.07%", "last_event_id": 23, "last_event_timestamp": 1509681166, "cursor_last_event_id": nil, "cursor_last_event_timestamp": 0, "last_successful_status_check_timestamp": 1510125024, "version": "10.3.0", "revision": "33d33a096a", "package_files_count": 10, "package_files_checksummed_count": 10, "package_files_checksum_failed_count": 0, "package_files_registry_count": 10, "package_files_synced_count": 6, "package_files_failed_count": 3 }, { "geo_node_id": 2, "healthy": true, "health": "Healthy", "health_status": "Healthy", "missing_oauth_application": false, "attachments_count": 1, "attachments_synced_count": 1, "attachments_failed_count": 0, "attachments_synced_missing_on_primary_count": 0, "attachments_synced_in_percentage": "100.00%", "db_replication_lag_seconds": 0, "lfs_objects_count": 0, "lfs_objects_synced_count": 0, "lfs_objects_failed_count": 0, "lfs_objects_synced_missing_on_primary_count": 0, "lfs_objects_synced_in_percentage": "0.00%", "job_artifacts_count": 2, "job_artifacts_synced_count": 1, "job_artifacts_failed_count": 1, "job_artifacts_synced_missing_on_primary_count": 0, "job_artifacts_synced_in_percentage": "50.00%", "container_repositories_count": 3, "container_repositories_synced_count": nil, "container_repositories_failed_count": nil, "container_repositories_synced_in_percentage": "0.00%", "design_repositories_count": 3, "design_repositories_synced_count": nil, "design_repositories_failed_count": nil, "design_repositories_synced_in_percentage": "0.00%", "projects_count": 41, "repositories_failed_count": 1, "repositories_synced_count": 40, "repositories_synced_in_percentage": "97.56%", "wikis_failed_count": 0, "wikis_synced_count": 41, "wikis_synced_in_percentage": "100.00%", "replication_slots_count": nil, "replication_slots_used_count": nil, "replication_slots_used_in_percentage": "0.00%", "replication_slots_max_retained_wal_bytes": nil, "repositories_checksummed_count": 20, "repositories_checksum_failed_count": 5, "repositories_checksummed_in_percentage": "48.78%", "wikis_checksummed_count": 10, "wikis_checksum_failed_count": 3, "wikis_checksummed_in_percentage": "24.39%", "repositories_verified_count": 20, "repositories_verification_failed_count": 5, "repositories_verified_in_percentage": "48.78%", "repositories_checksum_mismatch_count": 3, "wikis_verified_count": 10, "wikis_verification_failed_count": 3, "wikis_verified_in_percentage": "24.39%", "wikis_checksum_mismatch_count": 1, "repositories_retrying_verification_count": 4, "wikis_retrying_verification_count": 2, "repositories_checked_count": 5, "repositories_checked_failed_count": 1, "repositories_checked_in_percentage": "12.20%", "last_event_id": 23, "last_event_timestamp": 1509681166, "cursor_last_event_id": 23, "cursor_last_event_timestamp": 1509681166, "last_successful_status_check_timestamp": 1510125024, "version": "10.3.0", "revision": "33d33a096a", "package_files_count": 10, "package_files_checksummed_count": 10, "package_files_checksum_failed_count": 0, "package_files_registry_count": 10, "package_files_synced_count": 6, "package_files_failed_count": 3 } ] +``` + +**注意:**在 GitLab 12.0 中,已弃用的字段`wikis_count`和`repositories_count`被删除. 请改用`projects_count` . + +## Retrieve status about a specific Geo node[](#retrieve-status-about-a-specific-geo-node "Permalink") + +``` +GET /geo_nodes/:id/status +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/geo_nodes/2/status" +``` + +响应示例: + +``` +{ "geo_node_id": 2, "healthy": true, "health": "Healthy", "health_status": "Healthy", "missing_oauth_application": false, "attachments_count": 1, "attachments_synced_count": 1, "attachments_failed_count": 0, "attachments_synced_missing_on_primary_count": 0, "attachments_synced_in_percentage": "100.00%", "db_replication_lag_seconds": 0, "lfs_objects_count": 0, "lfs_objects_synced_count": 0, "lfs_objects_failed_count": 0, "lfs_objects_synced_missing_on_primary_count": 0, "lfs_objects_synced_in_percentage": "0.00%", "job_artifacts_count": 2, "job_artifacts_synced_count": 1, "job_artifacts_failed_count": 1, "job_artifacts_synced_missing_on_primary_count": 0, "job_artifacts_synced_in_percentage": "50.00%", "container_repositories_count": 3, "container_repositories_synced_count": nil, "container_repositories_failed_count": nil, "container_repositories_synced_in_percentage": "0.00%", "design_repositories_count": 3, "design_repositories_synced_count": nil, "design_repositories_failed_count": nil, "design_repositories_synced_in_percentage": "0.00%", "projects_count": 41, "repositories_failed_count": 1, "repositories_synced_count": 40, "repositories_synced_in_percentage": "97.56%", "wikis_failed_count": 0, "wikis_synced_count": 41, "wikis_synced_in_percentage": "100.00%", "replication_slots_count": nil, "replication_slots_used_count": nil, "replication_slots_used_in_percentage": "0.00%", "replication_slots_max_retained_wal_bytes": nil, "last_event_id": 23, "last_event_timestamp": 1509681166, "cursor_last_event_id": 23, "cursor_last_event_timestamp": 1509681166, "last_successful_status_check_timestamp": 1510125268, "version": "10.3.0", "revision": "33d33a096a" } +``` + +注意: `health_status`参数只能处于"健康"或"不健康"状态,而`health`参数可以为空,"健康"或包含实际错误消息. + +**注意:**在 GitLab 12.0 中,已弃用的字段`wikis_count`和`repositories_count`被删除. 请改用`projects_count` . + +## Retrieve project sync or verification failures that occurred on the current node[](#retrieve-project-sync-or-verification-failures-that-occurred-on-the-current-node "Permalink") + +这仅适用于辅助节点. + +``` +GET /geo_nodes/current/failures +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | string | no | 失败对象的类型( `repository` / `wiki` ) | +| `failure_type` | string | no | 故障类型( `sync` / `checksum_mismatch` / `verification` ) | + +该端点使用[分页](README.html#pagination) . + +``` +curl --header "PRIVATE-TOKEN: " "https://primary.example.com/api/v4/geo_nodes/current/failures" +``` + +响应示例: + +``` +[ { "project_id": 3, "last_repository_synced_at": "2017-10-31 14:25:55 UTC", "last_repository_successful_sync_at": "2017-10-31 14:26:04 UTC", "last_wiki_synced_at": "2017-10-31 14:26:04 UTC", "last_wiki_successful_sync_at": "2017-10-31 14:26:11 UTC", "repository_retry_count": null, "wiki_retry_count": 1, "last_repository_sync_failure": null, "last_wiki_sync_failure": "Error syncing Wiki repository", "last_repository_verification_failure": "", "last_wiki_verification_failure": "", "repository_verification_checksum_sha": "da39a3ee5e6b4b0d32e5bfef9a601890afd80709", "wiki_verification_checksum_sha": "da39a3ee5e6b4b0d3255bfef9ef0189aafd80709", "repository_checksum_mismatch": false, "wiki_checksum_mismatch": false } ] +``` \ No newline at end of file diff --git a/docs/317.md b/docs/317.md new file mode 100644 index 0000000000000000000000000000000000000000..71de959c7994e6d07221e5cd324bdf9280db8bf9 --- /dev/null +++ b/docs/317.md @@ -0,0 +1,83 @@ +# Group Activity Analytics API + +> 原文:[https://docs.gitlab.com/ee/api/group_activity_analytics.html](https://docs.gitlab.com/ee/api/group_activity_analytics.html) + +* [Get count of recently created issues for group](#get-count-of-recently-created-issues-for-group) +* [Get count of recently created merge requests for group](#get-count-of-recently-created-merge-requests-for-group) +* [Get count of members recently added to group](#get-count-of-members-recently-added-to-group) + +# Group Activity Analytics API[](#group-activity-analytics-api "Permalink") + +**注意:**此功能是在 GitLab 12.9 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26460) . + +## Get count of recently created issues for group[](#get-count-of-recently-created-issues-for-group "Permalink") + +``` +GET /analytics/group_activity/issues_count +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `group_path` | string | yes | 组路径 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/analytics/group_activity/issues_count?group_path=gitlab-org" +``` + +响应示例: + +``` +{ "issues_count": 10 } +``` + +## Get count of recently created merge requests for group[](#get-count-of-recently-created-merge-requests-for-group "Permalink") + +``` +GET /analytics/group_activity/merge_requests_count +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `group_path` | string | yes | 组路径 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/analytics/group_activity/merge_requests_count?group_path=gitlab-org" +``` + +响应示例: + +``` +{ "merge_requests_count": 10 } +``` + +## Get count of members recently added to group[](#get-count-of-members-recently-added-to-group "Permalink") + +``` +GET /analytics/group_activity/new_members_count +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `group_path` | string | yes | 组路径 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/analytics/group_activity/new_members_count?group_path=gitlab-org" +``` + +响应示例: + +``` +{ "new_members_count": 10 } +``` \ No newline at end of file diff --git a/docs/318.md b/docs/318.md new file mode 100644 index 0000000000000000000000000000000000000000..f801dc8b2293ced5c7d764eaef495a2e73a47c78 --- /dev/null +++ b/docs/318.md @@ -0,0 +1,697 @@ +# Groups API + +> 原文:[https://docs.gitlab.com/ee/api/groups.html](https://docs.gitlab.com/ee/api/groups.html) + +* [List groups](#list-groups) +* [List a group’s subgroups](#list-a-groups-subgroups) +* [List a group’s projects](#list-a-groups-projects) +* [List a group’s shared projects](#list-a-groups-shared-projects) +* [Details of a group](#details-of-a-group) + * [Disabling the results limit](#disabling-the-results-limit) +* [New group](#new-group) + * [Options for `default_branch_protection`](#options-for-default_branch_protection) +* [New Subgroup](#new-subgroup) +* [Transfer project to group](#transfer-project-to-group) +* [Update group](#update-group) + * [Disabling the results limit](#disabling-the-results-limit-1) +* [Remove group](#remove-group) +* [Restore group marked for deletion](#restore-group-marked-for-deletion-premium) +* [Search for group](#search-for-group) +* [Hooks](#hooks) + * [List group hooks](#list-group-hooks) + * [Get group hook](#get-group-hook) + * [Add group hook](#add-group-hook) + * [Edit group hook](#edit-group-hook) + * [Delete group hook](#delete-group-hook) +* [Group Audit Events](#group-audit-events-starter) +* [Sync group with LDAP](#sync-group-with-ldap-starter) +* [Group members](#group-members) +* [LDAP Group Links](#ldap-group-links) + * [List LDAP group links](#list-ldap-group-links-starter) + * [Add LDAP group link with CN or filter](#add-ldap-group-link-with-cn-or-filter-starter) + * [Delete LDAP group link](#delete-ldap-group-link-starter) + * [Delete LDAP group link with CN or filter](#delete-ldap-group-link-with-cn-or-filter-starter) +* [Namespaces in groups](#namespaces-in-groups) +* [Group badges](#group-badges) +* [Group Import/Export](#group-importexport) +* [Share Groups with Groups](#share-groups-with-groups) + * [Create a link to share a group with another group](#create-a-link-to-share-a-group-with-another-group) + * [Delete link sharing group with another group](#delete-link-sharing-group-with-another-group) + +# Groups API[](#groups-api "Permalink") + +## List groups[](#list-groups "Permalink") + +获取已认证用户的可见组列表. 在未经身份验证的情况下访问时,仅返回公共组. + +默认情况下,此请求一次返回 20 个结果,因为 API 结果[是分页的](README.html#pagination) . + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `skip_groups` | 整数数组 | no | 跳过传递的组 ID | +| `all_available` | boolean | no | 显示您有权访问的所有组(对于经过身份验证的用户,默认值为`false` ;对于管理员,默认`false` `true` ); `owned`属性和`min_access_level`具有优先权 | +| `search` | string | no | 返回符合搜索条件的授权组列表 | +| `order_by` | string | no | 按`name` , `path`或`id` . 默认`name` | +| `sort` | string | no | 按`asc`或`desc`顺序排列组. 默认为`asc` | +| `statistics` | boolean | no | 包括组统计信息(仅管理员) | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | +| `owned` | boolean | no | 限制为当前用户明确拥有的组 | +| `min_access_level` | integer | no | 限制为当前用户至少具有此[访问级别的组](members.html#valid-access-levels) | +| `top_level_only` | boolean | no | 限于顶级组,不包括所有子组 | + +``` +GET /groups +``` + +``` +[ { "id": 1, "name": "Foobar Group", "path": "foo-bar", "description": "An interesting group", "visibility": "public", "share_with_group_lock": false, "require_two_factor_authentication": false, "two_factor_grace_period": 48, "project_creation_level": "developer", "auto_devops_enabled": null, "subgroup_creation_level": "owner", "emails_disabled": null, "mentions_disabled": null, "lfs_enabled": true, "default_branch_protection": 2, "avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg", "web_url": "http://localhost:3000/groups/foo-bar", "request_access_enabled": false, "full_name": "Foobar Group", "full_path": "foo-bar", "file_template_project_id": 1, "parent_id": null, "created_at": "2020-01-15T12:36:29.590Z" } ] +``` + +当添加参数`statistics=true`且经过身份验证的用户是管理员时,将返回其他组统计信息. + +``` +GET /groups?statistics=true +``` + +``` +[ { "id": 1, "name": "Foobar Group", "path": "foo-bar", "description": "An interesting group", "visibility": "public", "share_with_group_lock": false, "require_two_factor_authentication": false, "two_factor_grace_period": 48, "project_creation_level": "developer", "auto_devops_enabled": null, "subgroup_creation_level": "owner", "emails_disabled": null, "mentions_disabled": null, "lfs_enabled": true, "default_branch_protection": 2, "avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg", "web_url": "http://localhost:3000/groups/foo-bar", "request_access_enabled": false, "full_name": "Foobar Group", "full_path": "foo-bar", "file_template_project_id": 1, "parent_id": null, "created_at": "2020-01-15T12:36:29.590Z", "statistics": { "storage_size" : 212, "repository_size" : 33, "wiki_size" : 100, "lfs_objects_size" : 123, "job_artifacts_size" : 57, "packages_size": 0, "snippets_size" : 50, } } ] +``` + +您可以按名称或路径搜索组,请参见下文. + +您可以使用以下[自定义属性](custom_attributes.html)进行过滤: + +``` +GET /groups?custom_attributes[key]=value&custom_attributes[other_key]=other_value +``` + +## List a group’s subgroups[](#list-a-groups-subgroups "Permalink") + +在 GitLab 10.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15142) . + +获取此组中可见的直接子组的列表. 在未经身份验证的情况下访问时,仅返回公共组. + +默认情况下,此请求一次返回 20 个结果,因为 API 结果[是分页的](README.html#pagination) . + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 直接父组[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `skip_groups` | 整数数组 | no | 跳过传递的组 ID | +| `all_available` | boolean | no | 显示您有权访问的所有组(对于经过身份验证的用户,默认值为`false` ;对于管理员,默认`false` `true` ); `owned`属性和`min_access_level`具有优先权 | +| `search` | string | no | 返回符合搜索条件的授权组列表 | +| `order_by` | string | no | 按`name` , `path`或`id` . 默认`name` | +| `sort` | string | no | 按`asc`或`desc`顺序排列组. 默认为`asc` | +| `statistics` | boolean | no | 包括组统计信息(仅管理员) | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | +| `owned` | boolean | no | 限制为当前用户明确拥有的组 | +| `min_access_level` | integer | no | 限制为当前用户至少具有此[访问级别的组](members.html#valid-access-levels) | + +``` +GET /groups/:id/subgroups +``` + +``` +[ { "id": 1, "name": "Foobar Group", "path": "foo-bar", "description": "An interesting group", "visibility": "public", "share_with_group_lock": false, "require_two_factor_authentication": false, "two_factor_grace_period": 48, "project_creation_level": "developer", "auto_devops_enabled": null, "subgroup_creation_level": "owner", "emails_disabled": null, "mentions_disabled": null, "lfs_enabled": true, "default_branch_protection": 2, "avatar_url": "http://gitlab.example.com/uploads/group/avatar/1/foo.jpg", "web_url": "http://gitlab.example.com/groups/foo-bar", "request_access_enabled": false, "full_name": "Foobar Group", "full_path": "foo-bar", "file_template_project_id": 1, "parent_id": 123, "created_at": "2020-01-15T12:36:29.590Z" } ] +``` + +## List a group’s projects[](#list-a-groups-projects "Permalink") + +获取此组中的项目列表. 在未经身份验证的情况下访问时,仅返回公共项目. + +默认情况下,此请求一次返回 20 个结果,因为 API 结果[是分页的](README.html#pagination) . + +``` +GET /groups/:id/projects +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `archived` | boolean | no | 受存档状态限制 | +| `visibility` | string | no | 受`public` , `internal`或`private`可见性限制 | +| `order_by` | string | no | 返回按`id` , `name` , `path` , `created_at` , `updated_at`或`last_activity_at`字段排序的项目. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的项目. 默认为`desc` | +| `search` | string | no | 返回符合搜索条件的授权项目列表 | +| `simple` | boolean | no | 仅返回每个项目的 ID,URL,名称和路径 | +| `owned` | boolean | no | 受当前用户拥有的项目限制 | +| `starred` | boolean | no | 受当前用户加注星标的项目限制 | +| `with_issues_enabled` | boolean | no | 受具有问题功能的项目限制. 默认为`false` | +| `with_merge_requests_enabled` | boolean | no | 受启用合并请求功能的项目限制. 默认为`false` | +| `with_shared` | boolean | no | 包括共享给该组的项目. 默认为`true` | +| `include_subgroups` | boolean | no | 将项目包括在该组的子组中. 默认为`false` | +| `min_access_level` | integer | no | 限于当前用户至少具有此[访问级别的项目](members.html#valid-access-levels) | +| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.html) in response (admins only) | +| `with_security_reports` | boolean | no | 仅返回在任何版本中都存在安全报告工件的项目. 这意味着"启用了安全报告的项目". 默认为`false` | + +响应示例: + +``` +[ { "id": 9, "description": "foo", "default_branch": "master", "tag_list": [], "archived": false, "visibility": "internal", "ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git", "http_url_to_repo": "http://gitlab.example.com/h5bp/html5-boilerplate.git", "web_url": "http://gitlab.example.com/h5bp/html5-boilerplate", "name": "Html5 Boilerplate", "name_with_namespace": "Experimental / Html5 Boilerplate", "path": "html5-boilerplate", "path_with_namespace": "h5bp/html5-boilerplate", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, "jobs_enabled": true, "snippets_enabled": true, "created_at": "2016-04-05T21:40:50.169Z", "last_activity_at": "2016-04-06T16:52:08.432Z", "shared_runners_enabled": true, "creator_id": 1, "namespace": { "id": 5, "name": "Experimental", "path": "h5bp", "kind": "group" }, "avatar_url": null, "star_count": 1, "forks_count": 0, "open_issues_count": 3, "public_jobs": true, "shared_with_groups": [], "request_access_enabled": false } ] +``` + +**注意:**为了区分组中的项目和共享给组的项目,可以使用`namespace`属性. 将项目共享给组后,其`namespace`将与请求的组不同. + +## List a group’s shared projects[](#list-a-groups-shared-projects "Permalink") + +获取共享给该组的项目的列表. 未经身份验证访问时,仅返回公共共享项目. + +默认情况下,此请求一次返回 20 个结果,因为 API 结果[是分页的](README.html#pagination) . + +``` +GET /groups/:id/projects/shared +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `archived` | boolean | no | 受存档状态限制 | +| `visibility` | string | no | 受`public` , `internal`或`private`可见性限制 | +| `order_by` | string | no | 返回按`id` , `name` , `path` , `created_at` , `updated_at`或`last_activity_at`字段排序的项目. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的项目. 默认为`desc` | +| `search` | string | no | 返回符合搜索条件的授权项目列表 | +| `simple` | boolean | no | 仅返回每个项目的 ID,URL,名称和路径 | +| `starred` | boolean | no | 受当前用户加注星标的项目限制 | +| `with_issues_enabled` | boolean | no | 受具有问题功能的项目限制. 默认为`false` | +| `with_merge_requests_enabled` | boolean | no | 受启用合并请求功能的项目限制. 默认为`false` | +| `min_access_level` | integer | no | 限于当前用户至少具有此[访问级别的项目](members.html#valid-access-levels) | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | + +响应示例: + +``` +[ { "id":8, "description":"Shared project for Html5 Boilerplate", "name":"Html5 Boilerplate", "name_with_namespace":"H5bp / Html5 Boilerplate", "path":"html5-boilerplate", "path_with_namespace":"h5bp/html5-boilerplate", "created_at":"2020-04-27T06:13:22.642Z", "default_branch":"master", "tag_list":[ ], "ssh_url_to_repo":"ssh://git@gitlab.com/h5bp/html5-boilerplate.git", "http_url_to_repo":"http://gitlab.com/h5bp/html5-boilerplate.git", "web_url":"http://gitlab.com/h5bp/html5-boilerplate", "readme_url":"http://gitlab.com/h5bp/html5-boilerplate/-/blob/master/README.md", "avatar_url":null, "star_count":0, "forks_count":4, "last_activity_at":"2020-04-27T06:13:22.642Z", "namespace":{ "id":28, "name":"H5bp", "path":"h5bp", "kind":"group", "full_path":"h5bp", "parent_id":null, "avatar_url":null, "web_url":"http://gitlab.com/groups/h5bp" }, "_links":{ "self":"http://gitlab.com/api/v4/projects/8", "issues":"http://gitlab.com/api/v4/projects/8/issues", "merge_requests":"http://gitlab.com/api/v4/projects/8/merge_requests", "repo_branches":"http://gitlab.com/api/v4/projects/8/repository/branches", "labels":"http://gitlab.com/api/v4/projects/8/labels", "events":"http://gitlab.com/api/v4/projects/8/events", "members":"http://gitlab.com/api/v4/projects/8/members" }, "empty_repo":false, "archived":false, "visibility":"public", "resolve_outdated_diff_discussions":false, "container_registry_enabled":true, "container_expiration_policy":{ "cadence":"7d", "enabled":true, "keep_n":null, "older_than":null, "name_regex":null, "name_regex_keep":null, "next_run_at":"2020-05-04T06:13:22.654Z" }, "issues_enabled":true, "merge_requests_enabled":true, "wiki_enabled":true, "jobs_enabled":true, "snippets_enabled":true, "can_create_merge_request_in":true, "issues_access_level":"enabled", "repository_access_level":"enabled", "merge_requests_access_level":"enabled", "forking_access_level":"enabled", "wiki_access_level":"enabled", "builds_access_level":"enabled", "snippets_access_level":"enabled", "pages_access_level":"enabled", "emails_disabled":null, "shared_runners_enabled":true, "lfs_enabled":true, "creator_id":1, "import_status":"failed", "open_issues_count":10, "ci_default_git_depth":50, "public_jobs":true, "build_timeout":3600, "auto_cancel_pending_pipelines":"enabled", "build_coverage_regex":null, "ci_config_path":null, "shared_with_groups":[ { "group_id":24, "group_name":"Commit451", "group_full_path":"Commit451", "group_access_level":30, "expires_at":null } ], "only_allow_merge_if_pipeline_succeeds":false, "request_access_enabled":true, "only_allow_merge_if_all_discussions_are_resolved":false, "remove_source_branch_after_merge":true, "printing_merge_request_link_enabled":true, "merge_method":"merge", "suggestion_commit_message":null, "auto_devops_enabled":true, "auto_devops_deploy_strategy":"continuous", "autoclose_referenced_issues":true, "repository_storage":"default" } ] +``` + +## Details of a group[](#details-of-a-group "Permalink") + +获取组的所有详细信息. 如果可以公开访问该组,则无需身份验证即可访问该端点. 如果请求的用户是该组的管理员,它将也返回该组的`runners_token` . + +``` +GET /groups/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员). | +| `with_projects` | boolean | no | 包括属于指定组的项目的详细信息(默认为`true` ). (已弃用, [将在 API v5 中删除](https://gitlab.com/gitlab-org/gitlab/-/issues/213797) .要获取组中所有项目的详细信息,请使用[列出组的项目终结点](#list-a-groups-projects) .) | + +**注意:**响应中的`projects`和`shared_projects`属性已弃用,并将[在 API v5 中删除](https://gitlab.com/gitlab-org/gitlab/-/issues/213797) . 要获取组内所有项目的详细信息,请使用[列出组的项目](#list-a-groups-projects)或[列出组的共享项目](#list-a-groups-shared-projects)端点. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4" +``` + +该端点返回: + +* GitLab 12.5 和更早版本中的所有项目和共享项目. +* [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/31031)及更高版本中最多有 100 个项目和共享项目. 要获取组中所有项目的详细信息,请使用[列出组的项目端点](#list-a-groups-projects)的[列表](#list-a-groups-projects) . + +响应示例: + +``` +{ "id": 4, "name": "Twitter", "path": "twitter", "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.", "visibility": "public", "avatar_url": null, "web_url": "https://gitlab.example.com/groups/twitter", "request_access_enabled": false, "full_name": "Twitter", "full_path": "twitter", "runners_token": "ba324ca7b1c77fc20bb9", "file_template_project_id": 1, "parent_id": null, "created_at": "2020-01-15T12:36:29.590Z", "shared_with_groups": [ { "group_id": 28, "group_name": "H5bp", "group_full_path": "h5bp", "group_access_level": 20, "expires_at": null } ], "projects": [ // Deprecated and will be removed in API v5 { "id": 7, "description": "Voluptas veniam qui et beatae voluptas doloremque explicabo facilis.", "default_branch": "master", "tag_list": [], "archived": false, "visibility": "public", "ssh_url_to_repo": "git@gitlab.example.com:twitter/typeahead-js.git", "http_url_to_repo": "https://gitlab.example.com/twitter/typeahead-js.git", "web_url": "https://gitlab.example.com/twitter/typeahead-js", "name": "Typeahead.Js", "name_with_namespace": "Twitter / Typeahead.Js", "path": "typeahead-js", "path_with_namespace": "twitter/typeahead-js", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, "jobs_enabled": true, "snippets_enabled": false, "container_registry_enabled": true, "created_at": "2016-06-17T07:47:25.578Z", "last_activity_at": "2016-06-17T07:47:25.881Z", "shared_runners_enabled": true, "creator_id": 1, "namespace": { "id": 4, "name": "Twitter", "path": "twitter", "kind": "group" }, "avatar_url": null, "star_count": 0, "forks_count": 0, "open_issues_count": 3, "public_jobs": true, "shared_with_groups": [], "request_access_enabled": false }, { "id": 6, "description": "Aspernatur omnis repudiandae qui voluptatibus eaque.", "default_branch": "master", "tag_list": [], "archived": false, "visibility": "internal", "ssh_url_to_repo": "git@gitlab.example.com:twitter/flight.git", "http_url_to_repo": "https://gitlab.example.com/twitter/flight.git", "web_url": "https://gitlab.example.com/twitter/flight", "name": "Flight", "name_with_namespace": "Twitter / Flight", "path": "flight", "path_with_namespace": "twitter/flight", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, "jobs_enabled": true, "snippets_enabled": false, "container_registry_enabled": true, "created_at": "2016-06-17T07:47:24.661Z", "last_activity_at": "2016-06-17T07:47:24.838Z", "shared_runners_enabled": true, "creator_id": 1, "namespace": { "id": 4, "name": "Twitter", "path": "twitter", "kind": "group" }, "avatar_url": null, "star_count": 0, "forks_count": 0, "open_issues_count": 8, "public_jobs": true, "shared_with_groups": [], "request_access_enabled": false } ], "shared_projects": [ // Deprecated and will be removed in API v5 { "id": 8, "description": "Velit eveniet provident fugiat saepe eligendi autem.", "default_branch": "master", "tag_list": [], "archived": false, "visibility": "private", "ssh_url_to_repo": "git@gitlab.example.com:h5bp/html5-boilerplate.git", "http_url_to_repo": "https://gitlab.example.com/h5bp/html5-boilerplate.git", "web_url": "https://gitlab.example.com/h5bp/html5-boilerplate", "name": "Html5 Boilerplate", "name_with_namespace": "H5bp / Html5 Boilerplate", "path": "html5-boilerplate", "path_with_namespace": "h5bp/html5-boilerplate", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, "jobs_enabled": true, "snippets_enabled": false, "container_registry_enabled": true, "created_at": "2016-06-17T07:47:27.089Z", "last_activity_at": "2016-06-17T07:47:27.310Z", "shared_runners_enabled": true, "creator_id": 1, "namespace": { "id": 5, "name": "H5bp", "path": "h5bp", "kind": "group" }, "avatar_url": null, "star_count": 0, "forks_count": 0, "open_issues_count": 4, "public_jobs": true, "shared_with_groups": [ { "group_id": 4, "group_name": "Twitter", "group_full_path": "twitter", "group_access_level": 30, "expires_at": null }, { "group_id": 3, "group_name": "Gitlab Org", "group_full_path": "gitlab-org", "group_access_level": 10, "expires_at": "2018-08-14" } ] } ] } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`shared_runners_minutes_limit`和`extra_shared_runners_minutes_limit`参数: + +其他响应参数: + +``` +{ "id": 4, "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.", "shared_runners_minutes_limit": 133, "extra_shared_runners_minutes_limit": 133, ... } +``` + +Users on GitLab [Silver, Premium, or higher](https://about.gitlab.com/pricing/) will also see the `marked_for_deletion_on` attribute: + +``` +{ "id": 4, "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.", "marked_for_deletion_on": "2020-04-03", ... } +``` + +当添加参数`with_projects=false` ,将不返回项目. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4?with_projects=false" +``` + +响应示例: + +``` +{ "id": 4, "name": "Twitter", "path": "twitter", "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.", "visibility": "public", "avatar_url": null, "web_url": "https://gitlab.example.com/groups/twitter", "request_access_enabled": false, "full_name": "Twitter", "full_path": "twitter", "file_template_project_id": 1, "parent_id": null } +``` + +### Disabling the results limit[](#disabling-the-results-limit "Permalink") + +如果它破坏了使用 GitLab 12.4 和更早版本开发的集成,则可以禁用 100 个结果限制. + +要在迁移到使用[列表的组项目](#list-a-groups-projects)终结点时禁用限制,请要求具有 Rails 控制台访问权限的 GitLab 管理员运行以下命令: + +``` +Feature.disable(:limit_projects_in_groups_api) +``` + +## New group[](#new-group "Permalink") + +创建一个新的项目组. 仅适用于可以创建组的用户. + +``` +POST /groups +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | string | yes | 组的名称. | +| `path` | string | yes | 组的路径. | +| `description` | string | no | 组的描述. | +| `membership_lock` | boolean | no | 阻止将新成员添加到该组中的项目成员中. | +| `visibility` | string | no | 小组的知名度. 可以是`private` , `internal`或`public` . | +| `share_with_group_lock` | boolean | no | 防止与该组中的另一个组共享项目. | +| `require_two_factor_authentication` | boolean | no | 要求该组中的所有用户设置双重身份验证. | +| `two_factor_grace_period` | integer | no | 实施两因素身份验证之前的时间(以小时为单位). | +| `project_creation_level` | string | no | 确定开发人员是否可以在组中创建项目. 可`noone` (没有之一), `maintainer` (维护者),或`developer` (开发+维护者). | +| `auto_devops_enabled` | boolean | no | 对于该组中的所有项目,默认为 Auto DevOps 管道. | +| `subgroup_creation_level` | string | no | 允许创建子组. 可以是`owner` (所有者)或`maintainer` (维护者). | +| `emails_disabled` | boolean | no | 禁用电子邮件通知 | +| `avatar` | mixed | no | 该组头像的图像文件. [在 GitLab 12.9 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) | +| `mentions_disabled` | boolean | no | 禁止一个人被提及 | +| `lfs_enabled` | boolean | no | 为该组中的项目启用/禁用大文件存储(LFS). | +| `request_access_enabled` | boolean | no | 允许用户请求成员访问权限. | +| `parent_id` | integer | no | 用于创建嵌套组的父组 ID. | +| `default_branch_protection` | integer | no | 请参阅[`default_branch_protection`选项](#options-for-default_branch_protection) . 默认为全局级别的默认分支保护设置. | +| `shared_runners_minutes_limit` | integer | no | 该组的管道分钟配额(包括在计划中). 可以为`nil` (默认值;继承系统默认值), `0` (无限制)或`> 0` | +| `extra_shared_runners_minutes_limit` | integer | no | 该组的额外管道分钟配额(在计划中包括的分钟之外购买). | + +### Options for `default_branch_protection`[](#options-for-default_branch_protection "Permalink") + +`default_branch_protection`属性确定开发人员和维护人员是否可以推送到适用的 master 分支,如下表所示: + +| Value | Description | +| --- | --- | +| `0` | 没有保护. 开发人员和维护人员可以: +-推送新的提交 +-强制推送更改 +-删除分支 | +| `1` | 部分保护. 开发人员和维护人员可以: +-推送新的提交 | +| `2` | 全面保护. 只有维护者可以: +-推送新的提交 | + +## New Subgroup[](#new-subgroup "Permalink") + +这类似于创建" [新建"组](#new-group) . 您将需要" [列表"组](#list-groups)调用中的`parent_id` . 然后,您可以输入所需的内容: + +* `subgroup_path` +* `subgroup_name` + +``` +curl --request POST --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" \ + --data '{"path": "", "name": "", "parent_id": } \ + "https://gitlab.example.com/api/v4/groups/" +``` + +## Transfer project to group[](#transfer-project-to-group "Permalink") + +将项目传输到组名称空间. 尽管不需要实例管理员访问权限的[替代 API 端点](projects.html#transfer-a-project-to-a-new-namespace)可用,但仅对实例管理员可用. 当项目存储库中存在标记的程序包时,传输项目可能会失败. + +``` +POST /groups/:id/projects/:project_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](README.html#namespaced-path-encoding) | +| `project_id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4/projects/56" +``` + +## Update group[](#update-group "Permalink") + +更新项目组. 仅对组所有者和管理员可用. + +``` +PUT /groups/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 组的 ID. | +| `name` | string | no | 组的名称. | +| `path` | string | no | 组的路径. | +| `description` | string | no | 组的描述. | +| `membership_lock` | boolean | no | 阻止将新成员添加到该组中的项目成员中. | +| `share_with_group_lock` | boolean | no | 防止与该组中的另一个组共享项目. | +| `visibility` | string | no | 组的可见性级别. 可以是`private` , `internal`或`public` . | +| `require_two_factor_authentication` | boolean | no | 要求该组中的所有用户设置双重身份验证. | +| `two_factor_grace_period` | integer | no | 实施两因素身份验证之前的时间(以小时为单位). | +| `project_creation_level` | string | no | 确定开发人员是否可以在组中创建项目. 可`noone` (没有之一), `maintainer` (维护者),或`developer` (开发+维护者). | +| `auto_devops_enabled` | boolean | no | 对于该组中的所有项目,默认为 Auto DevOps 管道. | +| `subgroup_creation_level` | string | no | 允许创建子组. 可以是`owner` (所有者)或`maintainer` (维护者). | +| `emails_disabled` | boolean | no | 禁用电子邮件通知 | +| `avatar` | mixed | no | 该组头像的图像文件. [在 GitLab 12.9 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) | +| `mentions_disabled` | boolean | no | 禁止一个人被提及 | +| `lfs_enabled` (optional) | boolean | no | 为该组中的项目启用/禁用大文件存储(LFS). | +| `request_access_enabled` | boolean | no | 允许用户请求成员访问权限. | +| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). | +| `file_template_project_id` | integer | no | 从中加载自定义文件模板的项目的 ID. | +| `shared_runners_minutes_limit` | integer | no | 该组的管道分钟配额(包括在计划中). 可以为`nil` (默认值;继承系统默认值), `0` (无限制)或`> 0` | +| `extra_shared_runners_minutes_limit` | integer | no | 该组的额外管道分钟配额(在计划中包括的分钟之外购买). | + +**注意:**响应中的`projects`和`shared_projects`属性已弃用,并将[在 API v5 中删除](https://gitlab.com/gitlab-org/gitlab/-/issues/213797) . 要获取组内所有项目的详细信息,请使用[列出组的项目](#list-a-groups-projects)或[列出组的共享项目](#list-a-groups-shared-projects)端点. + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5?name=Experimental" +``` + +该端点返回: + +* GitLab 12.5 和更早版本中的所有项目和共享项目. +* [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/31031)及更高版本中最多有 100 个项目和共享项目. 要获取组中所有项目的详细信息,请使用[列出组的项目端点](#list-a-groups-projects)的[列表](#list-a-groups-projects) . + +响应示例: + +``` +{ "id": 5, "name": "Experimental", "path": "h5bp", "description": "foo", "visibility": "internal", "avatar_url": null, "web_url": "http://gitlab.example.com/groups/h5bp", "request_access_enabled": false, "full_name": "Foobar Group", "full_path": "foo-bar", "file_template_project_id": 1, "parent_id": null, "created_at": "2020-01-15T12:36:29.590Z", "projects": [ // Deprecated and will be removed in API v5 { "id": 9, "description": "foo", "default_branch": "master", "tag_list": [], "public": false, "archived": false, "visibility": "internal", "ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git", "http_url_to_repo": "http://gitlab.example.com/h5bp/html5-boilerplate.git", "web_url": "http://gitlab.example.com/h5bp/html5-boilerplate", "name": "Html5 Boilerplate", "name_with_namespace": "Experimental / Html5 Boilerplate", "path": "html5-boilerplate", "path_with_namespace": "h5bp/html5-boilerplate", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, "jobs_enabled": true, "snippets_enabled": true, "created_at": "2016-04-05T21:40:50.169Z", "last_activity_at": "2016-04-06T16:52:08.432Z", "shared_runners_enabled": true, "creator_id": 1, "namespace": { "id": 5, "name": "Experimental", "path": "h5bp", "kind": "group" }, "avatar_url": null, "star_count": 1, "forks_count": 0, "open_issues_count": 3, "public_jobs": true, "shared_with_groups": [], "request_access_enabled": false } ] } +``` + +### Disabling the results limit[](#disabling-the-results-limit-1 "Permalink") + +The 100 results limit can be disabled if it breaks integrations developed using GitLab 12.4 and earlier. + +要在迁移到使用[列表的组项目](#list-a-groups-projects)终结点时禁用限制,请要求具有 Rails 控制台访问权限的 GitLab 管理员运行以下命令: + +``` +Feature.disable(:limit_projects_in_groups_api) +``` + +## Remove group[](#remove-group "Permalink") + +仅对组所有者和管理员可用. + +该端点: + +* 删除组,并在后台作业中排队以删除该组中的所有项目. +* 从[GitLab 12.8 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/33257) ,在[Premium 或 Silver](https://about.gitlab.com/pricing/)或更高级别上,将一个组标记为删除. 默认情况下,删除将在 7 天后进行,但是可以在[实例设置中](../user/admin_area/settings/visibility_and_access_controls.html#default-deletion-adjourned-period-premium-only)进行更改. + +``` +DELETE /groups/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +如果用户具有授权,则响应将为`202 Accepted` . + +## Restore group marked for deletion[](#restore-group-marked-for-deletion-premium "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/33257) . + +恢复标记为删除的组. + +``` +POST /groups/:id/restore +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +## Search for group[](#search-for-group "Permalink") + +获取名称或路径中与您的字符串匹配的所有组. + +``` +GET /groups?search=foobar +``` + +``` +[ { "id": 1, "name": "Foobar Group", "path": "foo-bar", "description": "An interesting group" } ] +``` + +## Hooks[](#hooks "Permalink") + +也称为群组挂钩和 Webhooks. 这些不同于系统范围的[系统挂钩](system_hooks.html)和限于一个项目的[项目挂钩](projects.html#hooks) . + +### List group hooks[](#list-group-hooks "Permalink") + +获取组挂钩列表 + +``` +GET /groups/:id/hooks +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +### Get group hook[](#get-group-hook "Permalink") + +获取组的特定挂钩. + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `hook_id` | integer | yes | 组挂钩的 ID | + +``` +GET /groups/:id/hooks/:hook_id +``` + +``` +{ "id": 1, "url": "http://example.com/hook", "group_id": 3, "push_events": true, "issues_events": true, "confidential_issues_events": true, "merge_requests_events": true, "tag_push_events": true, "note_events": true, "confidential_note_events": true, "job_events": true, "pipeline_events": true, "wiki_page_events": true, "enable_ssl_verification": true, "created_at": "2012-10-12T17:04:47Z" } +``` + +### Add group hook[](#add-group-hook "Permalink") + +将钩子添加到指定的组. + +``` +POST /groups/:id/hooks +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `url` | string | yes | 挂钩网址 | +| `push_events` | boolean | no | 在推送事件上触发钩子 | +| `issues_events` | boolean | no | 触发问题事件挂钩 | +| `confidential_issues_events` | boolean | no | 触发机密问题事件的钩子 | +| `merge_requests_events` | boolean | no | 触发合并请求事件的钩子 | +| `tag_push_events` | boolean | no | 触发标签推送事件的钩子 | +| `note_events` | boolean | no | 在音符事件上触发钩子 | +| `confidential_note_events` | boolean | no | 触发机密笔记事件的钩子 | +| `job_events` | boolean | no | 触发工作事件挂钩 | +| `pipeline_events` | boolean | no | 触发管道事件钩子 | +| `wiki_page_events` | boolean | no | 触发 Wiki 事件的钩子 | +| `enable_ssl_verification` | boolean | no | 触发挂钩时执行 SSL 验证 | +| `token` | string | no | 用于验证收到的有效载荷的秘密令牌; 这将不会在响应中返回 | + +### Edit group hook[](#edit-group-hook "Permalink") + +编辑指定组的挂钩. + +``` +PUT /groups/:id/hooks/:hook_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `hook_id` | integer | yes | 组挂钩的 ID | +| `url` | string | yes | 挂钩网址 | +| `push_events` | boolean | no | 在推送事件上触发钩子 | +| `issues_events` | boolean | no | 触发问题事件挂钩 | +| `confidential_issues_events` | boolean | no | 触发机密问题事件的钩子 | +| `merge_requests_events` | boolean | no | 触发合并请求事件的钩子 | +| `tag_push_events` | boolean | no | 触发标签推送事件的钩子 | +| `note_events` | boolean | no | 在音符事件上触发钩子 | +| `confidential_note_events` | boolean | no | 触发机密笔记事件的钩子 | +| `job_events` | boolean | no | 触发工作事件挂钩 | +| `pipeline_events` | boolean | no | 触发管道事件钩子 | +| `wiki_events` | boolean | no | 触发 Wiki 事件的钩子 | +| `enable_ssl_verification` | boolean | no | 触发挂钩时执行 SSL 验证 | +| `token` | string | no | 用于验证收到的有效载荷的秘密令牌; 这将不会在响应中返回 | + +### Delete group hook[](#delete-group-hook "Permalink") + +从组中删除钩子. 这是幂等方法,可以多次调用. 挂钩是否可用. + +``` +DELETE /groups/:id/hooks/:hook_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `hook_id` | integer | yes | 组挂钩的 ID. | + +## Group Audit Events[](#group-audit-events-starter "Permalink") + +可以通过" [组审核事件" API](audit_events.html#group-audit-events-starter)访问[组审核事件](audit_events.html#group-audit-events-starter) + +## Sync group with LDAP[](#sync-group-with-ldap-starter "Permalink") + +将组与其链接的 LDAP 组同步. 仅对组所有者和管理员可用. + +``` +POST /groups/:id/ldap_sync +``` + +Parameters: + +* `id` (必填)-用户组的 ID 或路径 + +## Group members[](#group-members "Permalink") + +请查阅[小组成员](members.html)文档. + +## LDAP Group Links[](#ldap-group-links "Permalink") + +列出,添加和删除 LDAP 组链接. + +### List LDAP group links[](#list-ldap-group-links-starter "Permalink") + +列出 LDAP 组链接. + +``` +GET /groups/:id/ldap_group_links +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +### Add LDAP group link with CN or filter[](#add-ldap-group-link-with-cn-or-filter-starter "Permalink") + +使用 CN 或过滤器添加 LDAP 组链接. 仅在高级级别和更高级别中,才支持通过过滤器添加组链接. + +``` +POST /groups/:id/ldap_group_links +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cn` | string | no | LDAP 组的 CN | +| `filter` | string | no | 组的 LDAP 过滤器 | +| `group_access` | integer | yes | LDAP 组成员的最低[访问级别](members.html#valid-access-levels) | +| `provider` | string | yes | LDAP 组链接的 LDAP 提供程序 | + +**注意:**要定义 LDAP 组链接,请提供`cn`或`filter` ,但不能同时提供两者. + +### Delete LDAP group link[](#delete-ldap-group-link-starter "Permalink") + +删除 LDAP 组链接. 不推荐使用. 在将来的版本中将被删除. + +``` +DELETE /groups/:id/ldap_group_links/:cn +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cn` | string | yes | LDAP 组的 CN | + +删除特定 LDAP 提供程序的 LDAP 组链接. 不推荐使用. 在将来的版本中将被删除. + +``` +DELETE /groups/:id/ldap_group_links/:provider/:cn +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cn` | string | yes | LDAP 组的 CN | +| `provider` | string | yes | LDAP 组链接的 LDAP 提供程序 | + +### Delete LDAP group link with CN or filter[](#delete-ldap-group-link-with-cn-or-filter-starter "Permalink") + +使用 CN 或过滤器删除 LDAP 组链接. 仅高级级别和更高级别支持按过滤器删除. + +``` +DELETE /groups/:id/ldap_group_links +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `cn` | string | no | LDAP 组的 CN | +| `filter` | string | no | 组的 LDAP 过滤器 | +| `provider` | string | yes | LDAP 组链接的 LDAP 提供程序 | + +**注意:**要删除 LDAP 组链接,请提供`cn`或`filter` ,但不能同时提供两者. + +## Namespaces in groups[](#namespaces-in-groups "Permalink") + +默认情况下,由于 API 结果是分页的,因此组一次只能获得 20 个名称空间. + +要获得更多(最多 100 个),请将以下内容作为参数传递给 API 调用: + +``` +/groups?per_page=100 +``` + +并切换页面添加: + +``` +/groups?per_page=100&page=2 +``` + +## Group badges[](#group-badges "Permalink") + +在[组徽章](group_badges.html)文档中了解更多信息. + +## Group Import/Export[](#group-importexport "Permalink") + +在[组导入/导出](group_import_export.html)文档中了解更多信息. + +## Share Groups with Groups[](#share-groups-with-groups "Permalink") + +这些端点创建和删除用于与另一个组共享一个组的链接. 有关更多信息,请参见[GitLab 组](../user/group/index.html#sharing-a-group-with-another-group)页面中的相关讨论. + +### Create a link to share a group with another group[](#create-a-link-to-share-a-group-with-another-group "Permalink") + +与另一个群组共享群组. 返回`200`和成功的[组详细信息](#details-of-a-group) . + +``` +POST /groups/:id/share +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `group_id` | integer | yes | 与之共享的组的 ID | +| `group_access` | integer | yes | 授予组的[访问级别](members.html#valid-access-levels) | +| `expires_at` | string | no | ISO 8601 格式的股份到期日:2016-09-26 | + +### Delete link sharing group with another group[](#delete-link-sharing-group-with-another-group "Permalink") + +取消与其他群组共享该群组. 返回`204` ,成功则不返回任何内容. + +``` +DELETE /groups/:id/share/:group_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `group_id` | integer | yes | 与之共享的组的 ID | \ No newline at end of file diff --git a/docs/319.md b/docs/319.md new file mode 100644 index 0000000000000000000000000000000000000000..39220f8566a222046c581236386357080f1fcda4 --- /dev/null +++ b/docs/319.md @@ -0,0 +1,67 @@ +# Import API + +> 原文:[https://docs.gitlab.com/ee/api/import.html](https://docs.gitlab.com/ee/api/import.html) + +* [Import repository from GitHub](#import-repository-from-github) +* [Import repository from Bitbucket Server](#import-repository-from-bitbucket-server) + +# Import API[](#import-api "Permalink") + +## Import repository from GitHub[](#import-repository-from-github "Permalink") + +通过 API 将项目从 GitHub 导入到 GitLab. + +``` +POST /import/github +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `personal_access_token` | string | yes | GitHub 个人访问令牌 | +| `repo_id` | integer | yes | GitHub 存储库 ID | +| `new_name` | string | no | 新存储库名称 | +| `target_namespace` | string | yes | 要将存储库导入的命名空间 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --data "personal_access_token=abc123&repo_id=12345&target_namespace=root" "https://gitlab.example.com/api/v4/import/github" +``` + +响应示例: + +``` +{ "id": 27, "name": "my-repo", "full_path": "/root/my-repo", "full_name": "Administrator / my-repo" } +``` + +## Import repository from Bitbucket Server[](#import-repository-from-bitbucket-server "Permalink") + +通过 API 将项目从 Bitbucket Server 导入到 GitLab. + +**注意:** Bitbucket 项目密钥仅用于在 Bitbucket 中查找存储库. 如果要将存储库导入到 GitLab 组,则必须指定`target_namespace` . 如果您未指定`target_namespace` ,则项目将导入您的个人用户名称空间. + +``` +POST /import/bitbucket_server +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `bitbucket_server_url` | string | yes | Bitbucket 服务器网址 | +| `bitbucket_server_username` | string | yes | Bitbucket 服务器用户名 | +| `personal_access_token` | string | yes | Bitbucket 服务器个人访问令牌/密码 | +| `bitbucket_server_project` | string | yes | Bitbucket 项目密钥 | +| `bitbucket_server_repo` | string | yes | Bitbucket 存储库名称 | +| `new_name` | string | no | 新的回购名称 | +| `target_namespace` | string | no | 导入仓库的命名空间 | + +``` +curl --request POST \ + --url https://gitlab.example.com/api/v4/import/bitbucket_server \ + --header "content-type: application/json" \ + --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \ + --data '{ + "bitbucket_server_url": "http://bitbucket.example.com", + "bitbucket_server_username": "root", + "personal_access_token": "Nzk4MDcxODY4MDAyOiP8y410zF3tGAyLnHRv/E0+3xYs", + "bitbucket_server_project": "NEW", + "bitbucket_server_repo": "my-repo" +}' +``` \ No newline at end of file diff --git a/docs/320.md b/docs/320.md new file mode 100644 index 0000000000000000000000000000000000000000..8f0bbdee9babf1db8f3815e6a3e272ca970460e9 --- /dev/null +++ b/docs/320.md @@ -0,0 +1,253 @@ +# Issue Boards API + +> 原文:[https://docs.gitlab.com/ee/api/boards.html](https://docs.gitlab.com/ee/api/boards.html) + +* [Project Board](#project-board) +* [Single board](#single-board) +* [Create a board](#create-a-board-starter) +* [Update a board](#update-a-board-starter) +* [Delete a board](#delete-a-board-starter) +* [List board lists](#list-board-lists) +* [Single board list](#single-board-list) +* [New board list](#new-board-list) +* [Edit board list](#edit-board-list) +* [Delete a board list](#delete-a-board-list) + +# Issue Boards API[](#issue-boards-api "Permalink") + +对板的每个 API 调用都必须经过验证. + +如果用户不是项目成员,并且该项目是私有项目,则对该项目的`GET`请求将导致`404`状态代码. + +## Project Board[](#project-board "Permalink") + +列出给定项目中的发行板. + +``` +GET /projects/:id/boards +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards" +``` + +响应示例: + +``` +[ { "id" : 1, "project": { "id": 5, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site" }, "milestone": { "id": 12, "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } ] } ] +``` + +## Single board[](#single-board "Permalink") + +拿一块板. + +``` +GET /projects/:id/boards/:board_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1" +``` + +响应示例: + +``` + { "id": 1, "name": "project issue board", "project": { "id": 5, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site" }, "milestone": { "id": 12, "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } ] } +``` + +## Create a board[](#create-a-board-starter "Permalink") + +创建一个木板. + +``` +POST /projects/:id/boards +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 新板的名称 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards?name=newboard" +``` + +响应示例: + +``` + { "id": 1, "project": { "id": 5, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site" }, "name": "newboard", "milestone": { "id": 12 "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } ] } +``` + +## Update a board[](#update-a-board-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5954) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.1. + +更新板. + +``` +PUT /projects/:id/boards/:board_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `name` | string | no | 董事会的新名称 | +| `assignee_id` | integer | no | 董事会受让人的范围应为 | +| `milestone_id` | integer | no | 董事会应达到的里程碑 | +| `labels` | string | no | 以逗号分隔的标签名称列表,该范围应适用于板 | +| `weight` | integer | no | 重量范围从 0 到 9,该板的范围应为 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1?name=new_name&milestone_id=43&assignee_id=1&labels=Doing&weight=4" +``` + +响应示例: + +``` + { "id": 1, "project": { "id": 5, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "created_at": "2018-07-03T05:48:49.982Z", "default_branch": null, "tag_list": [], "ssh_url_to_repo": "ssh://user@example.com/diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": null, "avatar_url": null, "star_count": 0, "forks_count": 0, "last_activity_at": "2018-07-03T05:48:49.982Z" }, "lists": [], "name": "new_name", "group": null, "milestone": { "id": 43, "iid": 1, "project_id": 15, "title": "Milestone 1", "description": "Milestone 1 desc", "state": "active", "created_at": "2018-07-03T06:36:42.618Z", "updated_at": "2018-07-03T06:36:42.618Z", "due_date": null, "start_date": null, "web_url": "http://example.com/root/board1/milestones/1" }, "assignee": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://example.com/root" }, "labels": [{ "id": 10, "name": "Doing", "color": "#5CB85C", "description": null }], "weight": 4 } +``` + +## Delete a board[](#delete-a-board-starter "Permalink") + +删除板. + +``` +DELETE /projects/:id/boards/:board_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1" +``` + +## List board lists[](#list-board-lists "Permalink") + +获取董事会名单的清单. 不包括`open`和`closed`列表 + +``` +GET /projects/:id/boards/:board_id/lists +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1/lists" +``` + +响应示例: + +``` +[ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } ] +``` + +## Single board list[](#single-board-list "Permalink") + +获取单板列表. + +``` +GET /projects/:id/boards/:board_id/lists/:list_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `list_id` | integer | yes | 单板编号 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1" +``` + +响应示例: + +``` +{ "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } +``` + +## New board list[](#new-board-list "Permalink") + +创建一个新的发行委员会列表. + +``` +POST /projects/:id/boards/:board_id/lists +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `label_id` | integer | no | 标签的 ID | +| `assignee_id` | integer | no | 用户的 ID | +| `milestone_id` | integer | no | 里程碑的 ID | + +**注意:**标签,受让人和里程碑参数是互斥的,也就是说,请求中仅接受其中一个. 查看[发行委员会文档](../user/project/issue_board.html#summary-of-features-per-tier) ,以获取有关每种列表类型所需许可证的更多信息. + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1/lists?label_id=5" +``` + +响应示例: + +``` +{ "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } +``` + +## Edit board list[](#edit-board-list "Permalink") + +更新现有的发行委员会列表. 此调用用于更改列表位置. + +``` +PUT /projects/:id/boards/:board_id/lists/:list_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `list_id` | integer | yes | 单板编号 | +| `position` | integer | yes | The position of the list | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1?position=2" +``` + +响应示例: + +``` +{ "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1, "max_issue_count": 0, "max_issue_weight": 0, "limit_metric": null } +``` + +## Delete a board list[](#delete-a-board-list "Permalink") + +仅适用于管理员和项目所有者. 删除相关的单板列表. + +``` +DELETE /projects/:id/boards/:board_id/lists/:list_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `list_id` | integer | yes | 单板编号 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1" +``` \ No newline at end of file diff --git a/docs/321.md b/docs/321.md new file mode 100644 index 0000000000000000000000000000000000000000..1654badc4b2377c646c928d1c0b0480042ad0cc9 --- /dev/null +++ b/docs/321.md @@ -0,0 +1,265 @@ +# Group Issue Boards API + +> 原文:[https://docs.gitlab.com/ee/api/group_boards.html](https://docs.gitlab.com/ee/api/group_boards.html) + +* [List all group issue boards in a group](#list-all-group-issue-boards-in-a-group) +* [Single group issue board](#single-group-issue-board) +* [Create a group issue board](#create-a-group-issue-board-premium) +* [Update a group issue board](#update-a-group-issue-board-premium) +* [Delete a group issue board](#delete-a-group-issue-board-premium) +* [List group issue board lists](#list-group-issue-board-lists) +* [Single group issue board list](#single-group-issue-board-list) +* [New group issue board list](#new-group-issue-board-list) +* [Edit group issue board list](#edit-group-issue-board-list) +* [Delete a group issue board list](#delete-a-group-issue-board-list) + +# Group Issue Boards API[](#group-issue-boards-api "Permalink") + +对组板的每个 API 调用都必须经过身份验证. + +If a user is not a member of a group and the group is private, a `GET` request will result in `404` status code. + +## List all group issue boards in a group[](#list-all-group-issue-boards-in-a-group "Permalink") + +列出给定组中的发行板. + +``` +GET /groups/:id/boards +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards" +``` + +响应示例: + +``` +[ { "id": 1, "name:": "group issue board", "group": { "id": 5, "name": "Documentcloud", "web_url": "http://example.com/groups/documentcloud" }, "milestone": { "id": 12 "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2 }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3 } ] } ] +``` + +由于具有多个组板的能力,使用 GitLab [Premium,Silver 或更高版本的用户](https://about.gitlab.com/pricing/)将看到不同的参数. + +响应示例: + +``` +[ { "id": 1, "name:": "group issue board", "group": { "id": 5, "name": "Documentcloud", "web_url": "http://example.com/groups/documentcloud" }, "milestone": { "id": 12 "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2 }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3 } ] } ] +``` + +## Single group issue board[](#single-group-issue-board "Permalink") + +获取单个小组问题委员会. + +``` +GET /groups/:id/boards/:board_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards/1" +``` + +响应示例: + +``` + { "id": 1, "name:": "group issue board", "group": { "id": 5, "name": "Documentcloud", "web_url": "http://example.com/groups/documentcloud" }, "milestone": { "id": 12 "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2 }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3 } ] } +``` + +GitLab [Premium,Silver 或更高版本的用户](https://about.gitlab.com/pricing/)将看到不同的参数,这是因为它具有多个组发行板的功能. + +响应示例: + +``` + { "id": 1, "name:": "group issue board", "group": { "id": 5, "name": "Documentcloud", "web_url": "http://example.com/groups/documentcloud" }, "milestone": { "id": 12 "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2 }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3 } ] } +``` + +## Create a group issue board[](#create-a-group-issue-board-premium "Permalink") + +创建一个小组发行委员会. + +``` +POST /groups/:id/boards +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 新板的名称 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards?name=newboard" +``` + +响应示例: + +``` + { "id": 1, "name": "newboard", "group": { "id": 5, "name": "Documentcloud", "web_url": "http://example.com/groups/documentcloud" }, "milestone": { "id": 12 "title": "10.0" }, "lists" : [ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2 }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3 } ] } +``` + +## Update a group issue board[](#update-a-group-issue-board-premium "Permalink") + +在 GitLab 11.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5954) . + +更新组发行板. + +``` +PUT /groups/:id/boards/:board_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `name` | string | no | 董事会的新名称 | +| `assignee_id` | integer | no | 董事会受让人的范围应为 | +| `milestone_id` | integer | no | 董事会应达到的里程碑 | +| `labels` | string | no | 以逗号分隔的标签名称列表,该范围应适用于板 | +| `weight` | integer | no | 重量范围从 0 到 9,该板的范围应为 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards/1?name=new_name&milestone_id=44&assignee_id=1&labels=GroupLabel&weight=4" +``` + +响应示例: + +``` + { "id": 1, "project": null, "lists": [], "name": "new_name", "group": { "id": 5, "name": "Documentcloud", "web_url": "http://example.com/groups/documentcloud" }, "milestone": { "id": 44, "iid": 1, "group_id": 5, "title": "Group Milestone", "description": "Group Milestone Desc", "state": "active", "created_at": "2018-07-03T07:15:19.271Z", "updated_at": "2018-07-03T07:15:19.271Z", "due_date": null, "start_date": null, "web_url": "http://example.com/groups/documentcloud/-/milestones/1" }, "assignee": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://example.com/root" }, "labels": [{ "id": 11, "name": "GroupLabel", "color": "#428BCA", "description": "" }], "weight": 4 } +``` + +## Delete a group issue board[](#delete-a-group-issue-board-premium "Permalink") + +删除组发行板. + +``` +DELETE /groups/:id/boards/:board_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards/1" +``` + +## List group issue board lists[](#list-group-issue-board-lists "Permalink") + +获取董事会名单的清单. 不包括`open`和`closed`列表 + +``` +GET /groups/:id/boards/:board_id/lists +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards/1/lists" +``` + +响应示例: + +``` +[ { "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 }, { "id" : 2, "label" : { "name" : "Ready", "color" : "#FF0000", "description" : null }, "position" : 2 }, { "id" : 3, "label" : { "name" : "Production", "color" : "#FF5F00", "description" : null }, "position" : 3 } ] +``` + +## Single group issue board list[](#single-group-issue-board-list "Permalink") + +获取单板列表. + +``` +GET /groups/:id/boards/:board_id/lists/:list_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `list_id` | integer | yes | 单板编号 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards/1/lists/1" +``` + +响应示例: + +``` +{ "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 } +``` + +## New group issue board list[](#new-group-issue-board-list "Permalink") + +创建一个新的发行委员会列表. + +``` +POST /groups/:id/boards/:board_id/lists +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `label_id` | integer | yes | 标签的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4/boards/12/lists?milestone_id=7" +``` + +响应示例: + +``` +{ "id": 9, "label": null, "position": 0, "milestone": { "id": 7, "iid": 3, "group_id": 12, "title": "Milestone with due date", "description": "", "state": "active", "created_at": "2017-09-03T07:16:28.596Z", "updated_at": "2017-09-03T07:16:49.521Z", "due_date": null, "start_date": null, "web_url": "https://gitlab.example.com/groups/issue-reproduce/-/milestones/3" } } +``` + +## Edit group issue board list[](#edit-group-issue-board-list "Permalink") + +更新现有的发行委员会列表. 此调用用于更改列表位置. + +``` +PUT /groups/:id/boards/:board_id/lists/:list_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `list_id` | integer | yes | 单板编号 | +| `position` | integer | yes | 清单的位置 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/group/5/boards/1/lists/1?position=2" +``` + +响应示例: + +``` +{ "id" : 1, "label" : { "name" : "Testing", "color" : "#F0AD4E", "description" : null }, "position" : 1 } +``` + +## Delete a group issue board list[](#delete-a-group-issue-board-list "Permalink") + +仅适用于管理员和群组所有者. 删除相关的单板列表. + +``` +DELETE /groups/:id/boards/:board_id/lists/:list_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `board_id` | integer | yes | 单板编号 | +| `list_id` | integer | yes | 单板编号 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/boards/1/lists/1" +``` \ No newline at end of file diff --git a/docs/322.md b/docs/322.md new file mode 100644 index 0000000000000000000000000000000000000000..a612126453ea5b9021fee73a1782e2222b5e3451 --- /dev/null +++ b/docs/322.md @@ -0,0 +1,779 @@ +# Issues API + +> 原文:[https://docs.gitlab.com/ee/api/issues.html](https://docs.gitlab.com/ee/api/issues.html) + +* [Issues pagination](#issues-pagination) +* [List issues](#list-issues) +* [List group issues](#list-group-issues) +* [List project issues](#list-project-issues) +* [Single issue](#single-issue) +* [New issue](#new-issue) +* [Rate limits](#rate-limits) +* [Edit issue](#edit-issue) +* [Delete an issue](#delete-an-issue) +* [Reorder an issue](#reorder-an-issue) +* [Move an issue](#move-an-issue) +* [Subscribe to an issue](#subscribe-to-an-issue) +* [Unsubscribe from an issue](#unsubscribe-from-an-issue) +* [Create a todo](#create-a-todo) +* [Set a time estimate for an issue](#set-a-time-estimate-for-an-issue) +* [Reset the time estimate for an issue](#reset-the-time-estimate-for-an-issue) +* [Add spent time for an issue](#add-spent-time-for-an-issue) +* [Reset spent time for an issue](#reset-spent-time-for-an-issue) +* [Get time tracking stats](#get-time-tracking-stats) +* [List merge requests related to issue](#list-merge-requests-related-to-issue) +* [List merge requests that will close issue on merge](#list-merge-requests-that-will-close-issue-on-merge) +* [Participants on issues](#participants-on-issues) +* [Comments on issues](#comments-on-issues) +* [Get user agent details](#get-user-agent-details) + +# Issues API[](#issues-api "Permalink") + +如果用户不是项目成员,并且该项目是私有项目,则对该项目的`GET`请求将产生`404`状态代码. + +## Issues pagination[](#issues-pagination "Permalink") + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +**弃用:不建议使用**响应中的`reference`属性,而推荐使用`references` . >推出了[GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354)**注意:** > `references.relative`相对于正在请求问题的组/项目. 从其项目中获取问题时> `relative`格式将与`short`格式相同,并且在跨组/项目进行请求时, `relative`格式将与`full`格式相同. + +## List issues[](#list-issues "Permalink") + +获取经过身份验证的用户有权访问的所有问题. 默认情况下,它仅返回当前用户创建的问题. 要获取所有问题,请使用参数`scope=all` . + +``` +GET /issues +GET /issues?state=opened +GET /issues?state=closed +GET /issues?labels=foo +GET /issues?labels=foo,bar +GET /issues?labels=foo,bar&state=opened +GET /issues?milestone=1.0.0 +GET /issues?milestone=1.0.0&state=opened +GET /issues?iids[]=42&iids[]=43 +GET /issues?author_id=5 +GET /issues?assignee_id=5 +GET /issues?my_reaction_emoji=star +GET /issues?search=foo&in=title +GET /issues?confidential=true +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `state` | string | no | 返回`all`问题,或者仅返回已`opened`或`closed` | +| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. | +| `with_labels_details` | boolean | no | 如果为`true` ,则响应将为标签字段中的每个标签返回更多详细信息`:name` , `:color` , `:description` , `:description_html` , `:text_color` . 默认值为`false` . [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)中引入了`description_html`属性 | +| `milestone` | string | no | 里程碑标题. `None`列出没有里程碑的所有问题. `Any`列出具有指定里程碑的所有问题. | +| `scope` | string | no | 回到问题在给定范围: `created_by_me` , `assigned_to_me`或`all` . 默认为`created_by_me` +对于 11.0 之前的版本,请改用现在不建议使用`created-by-me`范围或`created-by-me` `assigned-to-me`范围. +*(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) .在 GitLab 11.0 中[更改为 snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) )* | +| `author_id` | integer | no | 返回由给定用户`id`创建的问题. 与`author_username` . 与`scope=all`或`scope=assigned_to_me`结合使用. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) )* | +| `author_username` | string | no | 返回由给定`username`创建的问题. 类似于`author_id`并且与`author_id` . | +| `assignee_id` | integer | no | 返回分配给给定用户`id` . 互斥与`assignee_username` . `None`返回未分配的问题. 受让人有`Any`退货问题. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) )* | +| `assignee_username` | 字符串数组 | no | 返回分配给给定`username` . 类似于`assignee_id`并且与`assignee_id`互斥. 在 GitLab CE 中, `assignee_username`数组应仅包含单个值,否则将返回无效的参数错误. | +| `my_reaction_emoji` | string | no | 返回的问题由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. *(在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) )* | +| `weight` | integer | no | 以指定的`weight`返回问题. `None`返回没有分配权重的问题. 分配了权重的`Any`退货问题. | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的问题 | +| `order_by` | string | no | 回到问题下令`created_at` , `updated_at` , `priority` , `due_date` , `relative_position` , `label_priority` , `milestone_due` , `popularity` , `weight`领域. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`排列的问题. 默认为`desc` | +| `search` | string | no | 根据`title`和`description`搜索问题 | +| `in` | string | no | 修改`search`属性的范围. `title` , `description`或以逗号将它们连接在一起的字符串. 默认为`title,description` | +| `created_after` | datetime | no | 返回在给定时间或之后创建的问题 | +| `created_before` | datetime | no | 返回在给定时间或之前创建的问题 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的问题 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的问题 | +| `confidential` | boolean | no | 过滤机密或公共问题. | +| `not` | Hash | no | 返回与提供的参数不匹配的问题. 接受: `labels` , `milestone` , `author_id` , `author_username` , `assignee_id` , `assignee_username` , `my_reaction_emoji` | +| `non_archived` | boolean | no | 仅从未归档的项目返回问题. 如果为`false` ,则响应将返回已归档和未归档项目中的问题. 默认值为`true` . *(在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/issues/197170)引入)* | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/issues" +``` + +响应示例: + +``` +[ { "state" : "opened", "description" : "Ratione dolores corrupti mollitia soluta quia.", "author" : { "state" : "active", "id" : 18, "web_url" : "https://gitlab.example.com/eileen.lowe", "name" : "Alexandra Bashirian", "avatar_url" : null, "username" : "eileen.lowe" }, "milestone" : { "project_id" : 1, "description" : "Ducimus nam enim ex consequatur cumque ratione.", "state" : "closed", "due_date" : null, "iid" : 2, "created_at" : "2016-01-04T15:31:39.996Z", "title" : "v4.0", "id" : 17, "updated_at" : "2016-01-04T15:31:39.996Z" }, "project_id" : 1, "assignees" : [{ "state" : "active", "id" : 1, "name" : "Administrator", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root" }], "assignee" : { "state" : "active", "id" : 1, "name" : "Administrator", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root" }, "updated_at" : "2016-01-04T15:31:51.081Z", "closed_at" : null, "closed_by" : null, "id" : 76, "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", "created_at" : "2016-01-04T15:31:51.081Z", "moved_to_id" : null, "iid" : 6, "labels" : ["foo", "bar"], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "user_notes_count": 1, "due_date": "2016-07-22", "web_url": "http://example.com/my-group/my-project/issues/6", "references": { "short": "#6", "relative": "my-group/my-project#6", "full": "my-group/my-project#6" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "has_tasks": true, "task_status": "10 of 15 tasks completed", "confidential": false, "discussion_locked": false, "_links":{ "self":"http://example.com/api/v4/projects/1/issues/76", "notes":"`http://example.com/`api/v4/projects/1/issues/76/notes", "award_emoji":"http://example.com/api/v4/projects/1/issues/76/award_emoji", "project":"http://example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, "completed_count":0 } } ] +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +[ { "state" : "opened", "description" : "Ratione dolores corrupti mollitia soluta quia.", "weight": null, ... } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## List group issues[](#list-group-issues "Permalink") + +获取小组问题的列表. + +如果该组是私有的,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /groups/:id/issues +GET /groups/:id/issues?state=opened +GET /groups/:id/issues?state=closed +GET /groups/:id/issues?labels=foo +GET /groups/:id/issues?labels=foo,bar +GET /groups/:id/issues?labels=foo,bar&state=opened +GET /groups/:id/issues?milestone=1.0.0 +GET /groups/:id/issues?milestone=1.0.0&state=opened +GET /groups/:id/issues?iids[]=42&iids[]=43 +GET /groups/:id/issues?search=issue+title+or+description +GET /groups/:id/issues?author_id=5 +GET /groups/:id/issues?assignee_id=5 +GET /groups/:id/issues?my_reaction_emoji=star +GET /groups/:id/issues?confidential=true +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `state` | string | no | 返回所有问题,或者仅返回已`opened`或`closed` | +| `labels` | string | no | 标签名称的逗号分隔列表,必须具有要返回的所有标签的问题. `None`列出所有没有标签的问题. `Any`列出至少带有一个标签的所有问题. `No+Label` (不推荐使用)列出所有问题且不带标签. 预定义名称不区分大小写. | +| `with_labels_details` | boolean | no | 如果为`true` ,则响应将为标签字段中的每个标签返回更多详细信息`:name` , `:color` , `:description` , `:description_html` , `:text_color` . 默认值为`false` . [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)中引入了`description_html`属性 | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的问题 | +| `milestone` | string | no | 里程碑标题. `None`列出没有里程碑的所有问题. `Any`列出具有指定里程碑的所有问题. | +| `scope` | string | no | 回到问题在给定范围: `created_by_me` , `assigned_to_me`或`all` . +对于 11.0 之前的版本,请改用现在不建议使用`created-by-me`范围或`created-by-me` `assigned-to-me`范围. +*(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) .在 GitLab 11.0 中[更改为 snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) )* | +| `author_id` | integer | no | 返回由给定用户`id`创建的问题. 与`author_username` . 与`scope=all`或`scope=assigned_to_me`结合使用. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) )* | +| `author_username` | string | no | 返回由给定`username`创建的问题. 类似于`author_id`并且与`author_id` . | +| `assignee_id` | integer | no | 返回分配给给定用户`id` . 互斥与`assignee_username` . `None`返回未分配的问题. 受让人有`Any`退货问题. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) )* | +| `assignee_username` | 字符串数组 | no | 返回分配给给定`username` . 类似于`assignee_id`并且与`assignee_id`互斥. 在 GitLab CE 中, `assignee_username`数组应仅包含单个值,否则将返回无效的参数错误. | +| `my_reaction_emoji` | string | no | 返回的问题由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. *(在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) )* | +| `weight` | integer | no | 以指定的`weight`返回问题. `None`返回没有分配权重的问题. 分配了权重的`Any`退货问题. | +| `order_by` | string | no | 回到问题下令`created_at` , `updated_at` , `priority` , `due_date` , `relative_position` , `label_priority` , `milestone_due` , `popularity` , `weight`领域. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`排列的问题. 默认为`desc` | +| `search` | string | no | 搜索组问题的`title`和`description` | +| `created_after` | datetime | no | 返回在给定时间或之后创建的问题 | +| `created_before` | datetime | no | 返回在给定时间或之前创建的问题 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的问题 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的问题 | +| `confidential` | boolean | no | 过滤机密或公共问题. | +| `not` | Hash | no | 返回与提供的参数不匹配的问题. 接受: `labels` , `milestone` , `author_id` , `author_username` , `assignee_id` , `assignee_username` , `my_reaction_emoji` , `search` , `in` | +| `non_archived` | boolean | no | 从未归档的项目返回问题. 默认为 true. *(在[GitLab 12.8 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23785)引入)* | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4/issues" +``` + +响应示例: + +``` +[ { "project_id" : 4, "milestone" : { "due_date" : null, "project_id" : 4, "state" : "closed", "description" : "Rerum est voluptatem provident consequuntur molestias similique ipsum dolor.", "iid" : 3, "id" : 11, "title" : "v3.0", "created_at" : "2016-01-04T15:31:39.788Z", "updated_at" : "2016-01-04T15:31:39.788Z" }, "author" : { "state" : "active", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root", "id" : 1, "name" : "Administrator" }, "description" : "Omnis vero earum sunt corporis dolor et placeat.", "state" : "closed", "iid" : 1, "assignees" : [{ "avatar_url" : null, "web_url" : "https://gitlab.example.com/lennie", "state" : "active", "username" : "lennie", "id" : 9, "name" : "Dr. Luella Kovacek" }], "assignee" : { "avatar_url" : null, "web_url" : "https://gitlab.example.com/lennie", "state" : "active", "username" : "lennie", "id" : 9, "name" : "Dr. Luella Kovacek" }, "labels" : ["foo", "bar"], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "id" : 41, "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "updated_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z", "closed_at" : null, "closed_by" : null, "user_notes_count": 1, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/1", "references": { "short": "#1", "relative": "my-project#1", "full": "my-group/my-project#1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "has_tasks": true, "task_status": "10 of 15 tasks completed", "confidential": false, "discussion_locked": false, "_links":{ "self":"http://example.com/api/v4/projects/4/issues/41", "notes":"`http://example.com/`api/v4/projects/4/issues/41/notes", "award_emoji":"http://example.com/api/v4/projects/4/issues/41/award_emoji", "project":"http://example.com/api/v4/projects/4" }, "task_completion_status":{ "count":0, "completed_count":0 } } ] +``` + +Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see the `weight` parameter: + +``` +[ { "project_id" : 4, "description" : "Omnis vero earum sunt corporis dolor et placeat.", "weight": null, ... } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## List project issues[](#list-project-issues "Permalink") + +Get a list of a project’s issues. + +如果项目为私人项目,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /projects/:id/issues +GET /projects/:id/issues?state=opened +GET /projects/:id/issues?state=closed +GET /projects/:id/issues?labels=foo +GET /projects/:id/issues?labels=foo,bar +GET /projects/:id/issues?labels=foo,bar&state=opened +GET /projects/:id/issues?milestone=1.0.0 +GET /projects/:id/issues?milestone=1.0.0&state=opened +GET /projects/:id/issues?iids[]=42&iids[]=43 +GET /projects/:id/issues?search=issue+title+or+description +GET /projects/:id/issues?author_id=5 +GET /projects/:id/issues?assignee_id=5 +GET /projects/:id/issues?my_reaction_emoji=star +GET /projects/:id/issues?confidential=true +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的问题 | +| `state` | string | no | 返回所有问题,或者仅返回已`opened`或`closed` | +| `labels` | string | no | 标签名称的逗号分隔列表,必须具有要返回的所有标签的问题. `None`列出所有没有标签的问题. `Any`列出至少带有一个标签的所有问题. `No+Label` (不推荐使用)列出所有问题且不带标签. 预定义名称不区分大小写. | +| `with_labels_details` | boolean | no | 如果为`true` ,则响应将为标签字段中的每个标签返回更多详细信息`:name` , `:color` , `:description` , `:description_html` , `:text_color` . 默认值为`false` . `description_html`在[GitLab 12.7 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)引入 | +| `milestone` | string | no | 里程碑标题. `None`列出没有里程碑的所有问题. `Any`列出具有指定里程碑的所有问题. | +| `scope` | string | no | 回到问题在给定范围: `created_by_me` , `assigned_to_me`或`all` . +对于 11.0 之前的版本,请改用现在不建议使用`created-by-me`范围或`created-by-me` `assigned-to-me`范围. +*(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) .在 GitLab 11.0 中[更改为 snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) )* | +| `author_id` | integer | no | 返回由给定用户`id`创建的问题. 与`author_username` . 与`scope=all`或`scope=assigned_to_me`结合使用. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) )* | +| `author_username` | string | no | 返回由给定`username`创建的问题. 类似于`author_id`并且与`author_id` . | +| `assignee_id` | integer | no | 返回分配给给定用户`id` . 互斥与`assignee_username` . `None`返回未分配的问题. 受让人有`Any`退货问题. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) )* | +| `assignee_username` | 字符串数组 | no | 返回分配给给定`username` . 类似于`assignee_id`并且与`assignee_id`互斥. 在 GitLab CE 中, `assignee_username`数组应仅包含单个值,否则将返回无效的参数错误. | +| `my_reaction_emoji` | string | no | 返回的问题由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. *(在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) )* | +| `weight` | integer | no | 以指定的`weight`返回问题. `None`返回没有分配权重的问题. 分配了权重的`Any`退货问题. | +| `order_by` | string | no | 回到问题下令`created_at` , `updated_at` , `priority` , `due_date` , `relative_position` , `label_priority` , `milestone_due` , `popularity` , `weight`领域. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`排列的问题. 默认为`desc` | +| `search` | string | no | 根据`title`和`description`搜索项目问题 | +| `created_after` | datetime | no | 返回在给定时间或之后创建的问题 | +| `created_before` | datetime | no | 返回在给定时间或之前创建的问题 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的问题 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的问题 | +| `confidential` | boolean | no | 过滤机密或公共问题. | +| `not` | Hash | no | 返回与提供的参数不匹配的问题. 接受: `labels` , `milestone` , `author_id` , `author_username` , `assignee_id` , `assignee_username` , `my_reaction_emoji` , `search` , `in` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues" +``` + +响应示例: + +``` +[ { "project_id" : 4, "milestone" : { "due_date" : null, "project_id" : 4, "state" : "closed", "description" : "Rerum est voluptatem provident consequuntur molestias similique ipsum dolor.", "iid" : 3, "id" : 11, "title" : "v3.0", "created_at" : "2016-01-04T15:31:39.788Z", "updated_at" : "2016-01-04T15:31:39.788Z" }, "author" : { "state" : "active", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root", "id" : 1, "name" : "Administrator" }, "description" : "Omnis vero earum sunt corporis dolor et placeat.", "state" : "closed", "iid" : 1, "assignees" : [{ "avatar_url" : null, "web_url" : "https://gitlab.example.com/lennie", "state" : "active", "username" : "lennie", "id" : 9, "name" : "Dr. Luella Kovacek" }], "assignee" : { "avatar_url" : null, "web_url" : "https://gitlab.example.com/lennie", "state" : "active", "username" : "lennie", "id" : 9, "name" : "Dr. Luella Kovacek" }, "labels" : ["foo", "bar"], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "id" : 41, "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "updated_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z", "closed_at" : "2016-01-05T15:31:46.176Z", "closed_by" : { "state" : "active", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root", "id" : 1, "name" : "Administrator" }, "user_notes_count": 1, "due_date": "2016-07-22", "web_url": "http://example.com/my-group/my-project/issues/1", "references": { "short": "#1", "relative": "#1", "full": "my-group/my-project#1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "has_tasks": true, "task_status": "10 of 15 tasks completed", "confidential": false, "discussion_locked": false, "_links":{ "self":"http://example.com/api/v4/projects/4/issues/41", "notes":"`http://example.com/`api/v4/projects/4/issues/41/notes", "award_emoji":"http://example.com/api/v4/projects/4/issues/41/award_emoji", "project":"http://example.com/api/v4/projects/4" }, "task_completion_status":{ "count":0, "completed_count":0 } } ] +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +[ { "project_id" : 4, "description" : "Omnis vero earum sunt corporis dolor et placeat.", "weight": null, ... } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## Single issue[](#single-issue "Permalink") + +获得单个项目问题. + +如果项目为私人项目或问题为机密,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /projects/:id/issues/:issue_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | The internal ID of a project’s issue | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues/41" +``` + +响应示例: + +``` +{ "project_id" : 4, "milestone" : { "due_date" : null, "project_id" : 4, "state" : "closed", "description" : "Rerum est voluptatem provident consequuntur molestias similique ipsum dolor.", "iid" : 3, "id" : 11, "title" : "v3.0", "created_at" : "2016-01-04T15:31:39.788Z", "updated_at" : "2016-01-04T15:31:39.788Z", "closed_at" : "2016-01-05T15:31:46.176Z" }, "author" : { "state" : "active", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root", "id" : 1, "name" : "Administrator" }, "description" : "Omnis vero earum sunt corporis dolor et placeat.", "state" : "closed", "iid" : 1, "assignees" : [{ "avatar_url" : null, "web_url" : "https://gitlab.example.com/lennie", "state" : "active", "username" : "lennie", "id" : 9, "name" : "Dr. Luella Kovacek" }], "assignee" : { "avatar_url" : null, "web_url" : "https://gitlab.example.com/lennie", "state" : "active", "username" : "lennie", "id" : 9, "name" : "Dr. Luella Kovacek" }, "labels" : [], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "id" : 41, "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "updated_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z", "closed_at" : null, "closed_by" : null, "subscribed": false, "user_notes_count": 1, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/1", "references": { "short": "#1", "relative": "#1", "full": "my-group/my-project#1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "confidential": false, "discussion_locked": false, "_links": { "self": "http://example.com/api/v4/projects/1/issues/2", "notes": "http://example.com/api/v4/projects/1/issues/2/notes", "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", "project": "http://example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +{ "project_id" : 4, "description" : "Omnis vero earum sunt corporis dolor et placeat.", "weight": null, ... } +``` + +使用 GitLab [Premium 的](https://about.gitlab.com/pricing/)用户还将看到`epic`属性: + +``` +{ + "project_id" : 4, + "description" : "Omnis vero earum sunt corporis dolor et placeat.", + "epic_iid" : 5, //deprecated, use `iid` of the `epic` attribute + "epic": { + "id" : 42, + "iid" : 5, + "title": "My epic epic", + "url" : "/groups/h5bp/-/epics/5", + "group_id": 8 + }, + // ... +} +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +**注意** : `epic_iid`属性已过时, [将在版本 5 中删除](https://gitlab.com/gitlab-org/gitlab/-/issues/35157) . 请改用`epic`属性的`iid` . + +## New issue[](#new-issue "Permalink") + +创建一个新的项目问题. + +``` +POST /projects/:id/issues +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `iid` | integer/string | no | 项目问题的内部 ID(需要管理员或项目所有者权限) | +| `title` | string | yes | 问题标题 | +| `description` | string | no | 问题的描述. 限制为 1,048,576 个字符. | +| `confidential` | boolean | no | 将问题设置为机密. 默认值为`false` . | +| `assignee_ids` | 整数数组 | no | 要分配问题的用户的 ID | +| `milestone_id` | integer | no | 分配问题的里程碑的全局 ID | +| `labels` | string | no | 问题的逗号分隔标签名称 | +| `created_at` | string | no | 日期时间字符串,ISO 8601 格式,例如`2016-03-11T03:45:40Z` (需要管理员或项目/组所有者权限) | +| `due_date` | string | no | 日期时间字符串,格式为 YEAR-MONTH-DAY,例如`2016-03-11` | +| `merge_request_to_resolve_discussions_of` | integer | no | 解决所有问题的合并请求的 IID. 这将使用默认描述填充问题,并将所有讨论标记为已解决. 传递描述或标题时,这些值将优先于默认值. | +| `discussion_to_resolve` | string | no | 要解决的讨论的​​ID. 这将使用默认描述填充问题,并将讨论标记为已解决. 与`merge_request_to_resolve_discussions_of`结合使用. | +| `weight` | integer | no | 问题的分量. 有效值大于或等于 0. | +| `epic_id` | integer | no | 要添加问题的史诗的 ID. 有效值大于或等于 0. | +| `epic_iid` | integer | no | 要添加问题的史诗的 IID. 有效值大于或等于 0.(不建议使用, [将在版本 5 中将其删除](https://gitlab.com/gitlab-org/gitlab/-/issues/35157) ) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues?title=Issues%20with%20auth&labels=bug" +``` + +响应示例: + +``` +{ "project_id" : 4, "id" : 84, "created_at" : "2016-01-07T12:44:33.959Z", "iid" : 14, "title" : "Issues with auth", "state" : "opened", "assignees" : [], "assignee" : null, "labels" : [ "bug" ], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "closed_at" : null, "closed_by" : null, "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/14", "references": { "short": "#14", "relative": "#14", "full": "my-group/my-project#14" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "confidential": false, "discussion_locked": false, "_links": { "self": "http://example.com/api/v4/projects/1/issues/2", "notes": "http://example.com/api/v4/projects/1/issues/2/notes", "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", "project": "http://example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +{ "project_id" : 4, "description" : null, "weight": null, ... } +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## Rate limits[](#rate-limits "Permalink") + +为了避免滥用,用户仅限于: + +| 请求类型 | Limit | +| --- | --- | +| Create | 每分钟 300 期 | + +## Edit issue[](#edit-issue "Permalink") + +更新现有项目问题. 此调用还用于将问题标记为已结束. + +``` +PUT /projects/:id/issues/:issue_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `title` | string | no | 问题标题 | +| `description` | string | no | 问题的描述. 限制为 1,048,576 个字符. | +| `confidential` | boolean | no | 将问题更新为机密 | +| `assignee_ids` | 整数数组 | no | 要分配问题的用户的 ID. 设置为`0`或提供一个空值以取消分配所有受让人. | +| `milestone_id` | integer | no | 要分配问题的里程碑的全局 ID. 设置为`0`或提供一个空值以取消分配里程碑. | +| `labels` | string | no | 问题的标签名称,以逗号分隔. 设置为空字符串以取消分配所有标签. | +| `add_labels` | string | no | 以逗号分隔的标签名称添加到问题中. | +| `remove_labels` | string | no | 逗号分隔的标签名称可从问题中删除. | +| `state_event` | string | no | 问题的状态事件. 设为`close`以关闭问题,然后`reopen`以重新打开它 | +| `updated_at` | string | no | 日期时间字符串,ISO 8601 格式,例如`2016-03-11T03:45:40Z` (需要管理员或项目所有者权限). 不接受空字符串或空值. | +| `due_date` | string | no | 日期时间字符串,格式为 YEAR-MONTH-DAY,例如`2016-03-11` | +| `weight` | integer | no | 问题的分量. 有效值大于或等于 0.0 | +| `discussion_locked` | boolean | no | 指示问题的讨论是否被锁定的标志. 如果讨论被锁定,则只有项目成员可以添加或编辑评论. | +| `epic_id` | integer | no | 要添加问题的史诗的 ID. 有效值大于或等于 0. | +| `epic_iid` | integer | no | 要添加问题的史诗的 IID. 有效值大于或等于 0.(不建议使用, [将在版本 5 中将其删除](https://gitlab.com/gitlab-org/gitlab/-/issues/35157) ) | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues/85?state_event=close" +``` + +响应示例: + +``` +{ "created_at" : "2016-01-07T12:46:01.410Z", "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "username" : "eileen.lowe", "id" : 18, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe" }, "state" : "closed", "title" : "Issues with auth", "project_id" : 4, "description" : null, "updated_at" : "2016-01-07T12:55:16.213Z", "closed_at" : "2016-01-08T12:55:16.213Z", "closed_by" : { "state" : "active", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root", "id" : 1, "name" : "Administrator" }, "iid" : 15, "labels" : [ "bug" ], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "id" : 85, "assignees" : [], "assignee" : null, "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": "2016-07-22", "web_url": "http://example.com/my-group/my-project/issues/15", "references": { "short": "#15", "relative": "#15", "full": "my-group/my-project#15" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "confidential": false, "discussion_locked": false, "_links": { "self": "http://example.com/api/v4/projects/1/issues/2", "notes": "http://example.com/api/v4/projects/1/issues/2/notes", "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", "project": "http://example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +{ "project_id" : 4, "description" : null, "weight": null, ... } +``` + +**注:**至少以下参数之一是需要传递的请求是成功的: `:assignee_id` , `:assignee_ids` , `:confidential` , `:created_at` , `:description` , `:discussion_locked` , `:due_date` , `:labels` , `:milestone_id` , `:state_event` ,或`:title` .**注意:**不建议使用`assignee`列. 现在,我们将其显示为符合 GitLab EE API 的单个大小的数组`assignees` .**注意:** `closed_by`属性是[在 GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入的](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) . 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## Delete an issue[](#delete-an-issue "Permalink") + +仅适用于管理员和项目所有者. 删除相关问题. + +``` +DELETE /projects/:id/issues/:issue_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues/85" +``` + +## Reorder an issue[](#reorder-an-issue "Permalink") + +> 作为[社区贡献](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35349) [引入](https://gitlab.com/gitlab-org/gitlab/-/issues/211864)到 GitLab 13.2 中. + +重新排序问题,手动排序问题时可以看到结果 + +``` +PUT /projects/:id/issues/:issue_iid/reorder +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `move_after_id` | integer | no | 一个项目的 ID,以便在以后移动此问题 | +| `move_before_id` | integer | no | 一个项目的 ID,以便在此之前移此问题 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues/85/reorder?move_after_id=51&move_before_id=92" +``` + +## Move an issue[](#move-an-issue "Permalink") + +将问题移到其他项目. 如果目标项目等于源项目,或者用户没有足够的权限来移动问题,则返回错误`400`和解释性错误消息. + +If a given label and/or milestone with the same name also exists in the target project, it will then be assigned to the issue that is being moved. + +``` +POST /projects/:id/issues/:issue_iid/move +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `to_project_id` | integer | yes | 新项目的 ID | + +``` +curl --header "PRIVATE-TOKEN: " --form to_project_id=5 "https://gitlab.example.com/api/v4/projects/4/issues/85/move" +``` + +Example response: + +``` +{ "id": 92, "iid": 11, "project_id": 5, "title": "Sit voluptas tempora quisquam aut doloribus et.", "description": "Repellat voluptas quibusdam voluptatem exercitationem.", "state": "opened", "created_at": "2016-04-05T21:41:45.652Z", "updated_at": "2016-04-07T12:20:17.596Z", "closed_at": null, "closed_by": null, "labels": [], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "milestone": null, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "assignee": { "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }, "author": { "name": "Kris Steuber", "username": "solon.cremin", "id": 10, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/7a190fecbaa68212a4b68aeb6e3acd10?s=80&d=identicon", "web_url": "https://gitlab.example.com/solon.cremin" }, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/11", "references": { "short": "#11", "relative": "#11", "full": "my-group/my-project#11" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "confidential": false, "discussion_locked": false, "_links": { "self": "http://example.com/api/v4/projects/1/issues/2", "notes": "http://example.com/api/v4/projects/1/issues/2/notes", "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", "project": "http://example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +{ "project_id": 5, "description": "Repellat voluptas quibusdam voluptatem exercitationem.", "weight": null, ... } +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## Subscribe to an issue[](#subscribe-to-an-issue "Permalink") + +为经过身份验证的用户订阅问题以接收通知. 如果用户已经订阅了该问题,则返回状态码`304` . + +``` +POST /projects/:id/issues/:issue_iid/subscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/subscribe" +``` + +响应示例: + +``` +{ "id": 92, "iid": 11, "project_id": 5, "title": "Sit voluptas tempora quisquam aut doloribus et.", "description": "Repellat voluptas quibusdam voluptatem exercitationem.", "state": "opened", "created_at": "2016-04-05T21:41:45.652Z", "updated_at": "2016-04-07T12:20:17.596Z", "closed_at": null, "closed_by": null, "labels": [], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "milestone": null, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "assignee": { "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }, "author": { "name": "Kris Steuber", "username": "solon.cremin", "id": 10, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/7a190fecbaa68212a4b68aeb6e3acd10?s=80&d=identicon", "web_url": "https://gitlab.example.com/solon.cremin" }, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/11", "references": { "short": "#11", "relative": "#11", "full": "my-group/my-project#11" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "confidential": false, "discussion_locked": false, "_links": { "self": "http://example.com/api/v4/projects/1/issues/2", "notes": "http://example.com/api/v4/projects/1/issues/2/notes", "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", "project": "http://example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`weight`参数: + +``` +{ "project_id": 5, "description": "Repellat voluptas quibusdam voluptatem exercitationem.", "weight": null, ... } +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## Unsubscribe from an issue[](#unsubscribe-from-an-issue "Permalink") + +从问题中退订已认证的用户,以不接收来自该问题的通知. 如果用户未订阅该问题,则返回状态码`304` . + +``` +POST /projects/:id/issues/:issue_iid/unsubscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/unsubscribe" +``` + +响应示例: + +``` +{ "id": 93, "iid": 12, "project_id": 5, "title": "Incidunt et rerum ea expedita iure quibusdam.", "description": "Et cumque architecto sed aut ipsam.", "state": "opened", "created_at": "2016-04-05T21:41:45.217Z", "updated_at": "2016-04-07T13:02:37.905Z", "labels": [], "upvotes": 4, "downvotes": 0, "merge_requests_count": 0, "milestone": null, "assignee": { "name": "Edwardo Grady", "username": "keyon", "id": 21, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/3e6f06a86cf27fa8b56f3f74f7615987?s=80&d=identicon", "web_url": "https://gitlab.example.com/keyon" }, "closed_at": null, "closed_by": null, "author": { "name": "Vivian Hermann", "username": "orville", "id": 11, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/5224fd70153710e92fb8bcf79ac29d67?s=80&d=identicon", "web_url": "https://gitlab.example.com/orville" }, "subscribed": false, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/12", "references": { "short": "#12", "relative": "#12", "full": "my-group/my-project#12" }, "confidential": false, "discussion_locked": false, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +## Create a todo[](#create-a-todo "Permalink") + +在问题上为当前用户手动创建待办事项. 如果在该问题上已经存在用户的待办事项,则返回状态码`304` . + +``` +POST /projects/:id/issues/:issue_iid/todo +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/todo" +``` + +响应示例: + +``` +{ "id": 112, "project": { "id": 5, "name": "GitLab CI/CD", "name_with_namespace": "GitLab Org / GitLab CI/CD", "path": "gitlab-ci", "path_with_namespace": "gitlab-org/gitlab-ci" }, "author": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "action_name": "marked", "target_type": "Issue", "target": { "id": 93, "iid": 10, "project_id": 5, "title": "Vel voluptas atque dicta mollitia adipisci qui at.", "description": "Tempora laboriosam sint magni sed voluptas similique.", "state": "closed", "created_at": "2016-06-17T07:47:39.486Z", "updated_at": "2016-07-01T11:09:13.998Z", "labels": [], "milestone": { "id": 26, "iid": 1, "project_id": 5, "title": "v0.0", "description": "Accusantium nostrum rerum quae quia quis nesciunt suscipit id.", "state": "closed", "created_at": "2016-06-17T07:47:33.832Z", "updated_at": "2016-06-17T07:47:33.832Z", "due_date": null }, "assignees": [{ "name": "Jarret O'Keefe", "username": "francisca", "id": 14, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a7fa515d53450023c83d62986d0658a8?s=80&d=identicon", "web_url": "https://gitlab.example.com/francisca" }], "assignee": { "name": "Jarret O'Keefe", "username": "francisca", "id": 14, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a7fa515d53450023c83d62986d0658a8?s=80&d=identicon", "web_url": "https://gitlab.example.com/francisca" }, "author": { "name": "Maxie Medhurst", "username": "craig_rutherford", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", "web_url": "https://gitlab.example.com/craig_rutherford" }, "subscribed": true, "user_notes_count": 7, "upvotes": 0, "downvotes": 0, "merge_requests_count": 0, "due_date": null, "web_url": "http://example.com/my-group/my-project/issues/10", "references": { "short": "#10", "relative": "#10", "full": "my-group/my-project#10" }, "confidential": false, "discussion_locked": false, "task_completion_status":{ "count":0, "completed_count":0 } }, "target_url": "https://gitlab.example.com/gitlab-org/gitlab-ci/issues/10", "body": "Vel voluptas atque dicta mollitia adipisci qui at.", "state": "pending", "created_at": "2016-07-01T11:09:13.992Z" } +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +**注意** : [GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042) `closed_by`属性. 只有在 GitLab 10.6 之后关闭的问题以及关闭问题的用户帐户仍然存在时,才会显示此值. + +## Set a time estimate for an issue[](#set-a-time-estimate-for-an-issue "Permalink") + +设置此问题的估计工作时间. + +``` +POST /projects/:id/issues/:issue_iid/time_estimate +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `duration` | string | yes | 以人类格式表示的持续时间. 例如:3h30m | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/time_estimate?duration=3h30m" +``` + +响应示例: + +``` +{ "human_time_estimate": "3h 30m", "human_total_time_spent": null, "time_estimate": 12600, "total_time_spent": 0 } +``` + +## Reset the time estimate for an issue[](#reset-the-time-estimate-for-an-issue "Permalink") + +将此问题的估计时间重置为 0 秒. + +``` +POST /projects/:id/issues/:issue_iid/reset_time_estimate +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/reset_time_estimate" +``` + +响应示例: + +``` +{ "human_time_estimate": null, "human_total_time_spent": null, "time_estimate": 0, "total_time_spent": 0 } +``` + +## Add spent time for an issue[](#add-spent-time-for-an-issue "Permalink") + +增加了解决此问题的时间 + +``` +POST /projects/:id/issues/:issue_iid/add_spent_time +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `duration` | string | yes | 以人类格式表示的持续时间. 例如:3h30m | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/add_spent_time?duration=1h" +``` + +Example response: + +``` +{ "human_time_estimate": null, "human_total_time_spent": "1h", "time_estimate": 0, "total_time_spent": 3600 } +``` + +## Reset spent time for an issue[](#reset-spent-time-for-an-issue "Permalink") + +将此问题的总花费时间重置为 0 秒. + +``` +POST /projects/:id/issues/:issue_iid/reset_spent_time +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/reset_spent_time" +``` + +响应示例: + +``` +{ "human_time_estimate": null, "human_total_time_spent": null, "time_estimate": 0, "total_time_spent": 0 } +``` + +## Get time tracking stats[](#get-time-tracking-stats "Permalink") + +如果项目为私人项目或问题为机密,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /projects/:id/issues/:issue_iid/time_stats +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/time_stats" +``` + +响应示例: + +``` +{ "human_time_estimate": "2h", "human_total_time_spent": "1h", "time_estimate": 7200, "total_time_spent": 3600 } +``` + +## List merge requests related to issue[](#list-merge-requests-related-to-issue "Permalink") + +获取与该问题相关的所有合并请求. + +如果项目为私人项目或问题为机密,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /projects/:id/issues/:issue_id/related_merge_requests +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/11/related_merge_requests" +``` + +响应示例: + +``` +[ { "id": 29, "iid": 11, "project_id": 1, "title": "Provident eius eos blanditiis consequatur neque odit.", "description": "Ut consequatur ipsa aspernatur quisquam voluptatum fugit. Qui harum corporis quo fuga ut incidunt veritatis. Autem necessitatibus et harum occaecati nihil ea.\r\n\r\ntwitter/flight#8", "state": "opened", "created_at": "2018-09-18T14:36:15.510Z", "updated_at": "2018-09-19T07:45:13.089Z", "closed_by": null, "closed_at": null, "target_branch": "v2.x", "source_branch": "so_long_jquery", "user_notes_count": 9, "upvotes": 0, "downvotes": 0, "author": { "id": 14, "name": "Verna Hills", "username": "lawanda_reinger", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/de68a91aeab1cff563795fb98a0c2cc0?s=80&d=identicon", "web_url": "https://gitlab.example.com/lawanda_reinger" }, "assignee": { "id": 19, "name": "Jody Baumbach", "username": "felipa.kuvalis", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/6541fc75fc4e87e203529bd275fafd07?s=80&d=identicon", "web_url": "https://gitlab.example.com/felipa.kuvalis" }, "source_project_id": 1, "target_project_id": 1, "labels": [], "work_in_progress": false, "milestone": { "id": 27, "iid": 2, "project_id": 1, "title": "v1.0", "description": "Et tenetur voluptatem minima doloribus vero dignissimos vitae.", "state": "active", "created_at": "2018-09-18T14:35:44.353Z", "updated_at": "2018-09-18T14:35:44.353Z", "due_date": null, "start_date": null, "web_url": "https://gitlab.example.com/twitter/flight/milestones/2" }, "merge_when_pipeline_succeeds": false, "merge_status": "cannot_be_merged", "sha": "3b7b528e9353295c1c125dad281ac5b5deae5f12", "merge_commit_sha": null, "squash_commit_sha": null, "discussion_locked": null, "should_remove_source_branch": null, "force_remove_source_branch": false, "reference": "!11", "web_url": "https://gitlab.example.com/twitter/flight/merge_requests/4", "references": { "short": "!4", "relative": "!4", "full": "twitter/flight!4" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "task_completion_status": { "count": 0, "completed_count": 0 }, "changes_count": "10", "latest_build_started_at": "2018-12-05T01:16:41.723Z", "latest_build_finished_at": "2018-12-05T02:35:54.046Z", "first_deployed_to_production_at": null, "pipeline": { "id": 38980952, "sha": "81c6a84c7aebd45a1ac2c654aa87f11e32338e0a", "ref": "test-branch", "status": "success", "web_url": "https://gitlab.com/gitlab-org/gitlab/pipelines/38980952" }, "head_pipeline": { "id": 38980952, "sha": "81c6a84c7aebd45a1ac2c654aa87f11e32338e0a", "ref": "test-branch", "status": "success", "web_url": "https://gitlab.example.com/twitter/flight/pipelines/38980952", "before_sha": "3c738a37eb23cf4c0ed0d45d6ddde8aad4a8da51", "tag": false, "yaml_errors": null, "user": { "id": 19, "name": "Jody Baumbach", "username": "felipa.kuvalis", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/6541fc75fc4e87e203529bd275fafd07?s=80&d=identicon", "web_url": "https://gitlab.example.com/felipa.kuvalis" }, "created_at": "2018-12-05T01:16:13.342Z", "updated_at": "2018-12-05T02:35:54.086Z", "started_at": "2018-12-05T01:16:41.723Z", "finished_at": "2018-12-05T02:35:54.046Z", "committed_at": null, "duration": 4436, "coverage": "46.68", "detailed_status": { "icon": "status_warning", "text": "passed", "label": "passed with warnings", "group": "success-with-warnings", "tooltip": "passed", "has_details": true, "details_path": "/twitter/flight/pipelines/38", "illustration": null, "favicon": "https://gitlab.example.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png" } }, "diff_refs": { "base_sha": "d052d768f0126e8cddf80afd8b1eb07f406a3fcb", "head_sha": "81c6a84c7aebd45a1ac2c654aa87f11e32338e0a", "start_sha": "d052d768f0126e8cddf80afd8b1eb07f406a3fcb" }, "merge_error": null, "user": { "can_merge": true } } ] +``` + +## List merge requests that will close issue on merge[](#list-merge-requests-that-will-close-issue-on-merge "Permalink") + +获取所有合并请求,这些合并请求将在合并时关闭问题. + +如果项目为私人项目或问题为机密,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /projects/:id/issues/:issue_iid/closed_by +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/issues/11/closed_by" +``` + +响应示例: + +``` +[ { "id": 6471, "iid": 6432, "project_id": 1, "title": "add a test for cgi lexer options", "description": "closes #11", "state": "opened", "created_at": "2017-04-06T18:33:34.168Z", "updated_at": "2017-04-09T20:10:24.983Z", "target_branch": "master", "source_branch": "feature.custom-highlighting", "upvotes": 0, "downvotes": 0, "author": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "assignee": null, "source_project_id": 1, "target_project_id": 1, "closed_at": null, "closed_by": null, "labels": [], "work_in_progress": false, "milestone": null, "merge_when_pipeline_succeeds": false, "merge_status": "unchecked", "sha": "5a62481d563af92b8e32d735f2fa63b94e806835", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "should_remove_source_branch": null, "force_remove_source_branch": false, "web_url": "https://gitlab.example.com/gitlab-org/gitlab-test/merge_requests/6432", "reference": "!6432", "references": { "short": "!6432", "relative": "!6432", "full": "gitlab-org/gitlab-test!6432" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +## Participants on issues[](#participants-on-issues "Permalink") + +如果项目为私人项目或问题为机密,则需要提供凭据进行授权. 首选的方法是使用[个人访问令牌](../user/profile/personal_access_tokens.html) . + +``` +GET /projects/:id/issues/:issue_iid/participants +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/participants" +``` + +响应示例: + +``` +[ { "id": 1, "name": "John Doe1", "username": "user1", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://localhost/user1" }, { "id": 5, "name": "John Doe5", "username": "user5", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/4aea8cf834ed91844a2da4ff7ae6b491?s=80&d=identicon", "web_url": "http://localhost/user5" } ] +``` + +## Comments on issues[](#comments-on-issues "Permalink") + +注释是通过[notes](notes.html)资源完成的. + +## Get user agent details[](#get-user-agent-details "Permalink") + +仅适用于管理员. + +``` +GET /projects/:id/issues/:issue_iid/user_agent_detail +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | The internal ID of a project’s issue | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/93/user_agent_detail" +``` + +响应示例: + +``` +{ "user_agent": "AppleWebKit/537.36", "ip_address": "127.0.0.1", "akismet_submitted": false } +``` \ No newline at end of file diff --git a/docs/323.md b/docs/323.md new file mode 100644 index 0000000000000000000000000000000000000000..e816f675bdb507aafd39465d2ab3bd68d9503cb1 --- /dev/null +++ b/docs/323.md @@ -0,0 +1,119 @@ +# Epic Issues API + +> 原文:[https://docs.gitlab.com/ee/api/epic_issues.html](https://docs.gitlab.com/ee/api/epic_issues.html) + +* [List issues for an epic](#list-issues-for-an-epic) +* [Assign an issue to the epic](#assign-an-issue-to-the-epic) +* [Remove an issue from the epic](#remove-an-issue-from-the-epic) +* [Update epic - issue association](#update-epic---issue-association) + +# Epic Issues API[](#epic-issues-api-premium "Permalink") + +每个对 epic_issues 的 API 调用都必须经过验证. + +如果用户不是组的成员,并且该组是私有的,则对该组的`GET`请求将产生`404`状态代码. + +Epics 仅在 GitLab [Premium 和更高版本](https://about.gitlab.com/pricing/)中可用. 如果 Epics 功能不可用,将返回`403`状态代码. + +## List issues for an epic[](#list-issues-for-an-epic "Permalink") + +获取分配给史诗且经过身份验证的用户有权访问的所有问题. + +``` +GET /groups/:id/epics/:epic_iid/issues +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/issues/" +``` + +响应示例: + +``` +[ { "id": 76, "iid": 6, "project_id": 8, "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", "description" : "Ratione dolores corrupti mollitia soluta quia.", "state": "opened", "created_at": "2017-11-15T13:39:24.670Z", "updated_at": "2018-01-04T10:49:19.506Z", "closed_at": null, "labels": [], "milestone": { "id": 38, "iid": 3, "project_id": 8, "title": "v2.0", "description": "In tempore culpa inventore quo accusantium.", "state": "closed", "created_at": "2017-11-15T13:39:13.825Z", "updated_at": "2017-11-15T13:39:13.825Z", "due_date": null, "start_date": null }, "assignees": [{ "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }], "assignee": { "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }, "author": { "id": 13, "name": "Michell Johns", "username": "chris_hahn", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/30e3b2122ccd6b8e45e8e14a3ffb58fc?s=80&d=identicon", "web_url": "http://localhost:3001/chris_hahn" }, "user_notes_count": 8, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "weight": null, "discussion_locked": null, "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/6", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "_links":{ "self": "http://localhost:3001/api/v4/projects/8/issues/6", "notes": "http://localhost:3001/api/v4/projects/8/issues/6/notes", "award_emoji": "http://localhost:3001/api/v4/projects/8/issues/6/award_emoji", "project": "http://localhost:3001/api/v4/projects/8" }, "subscribed": true, "epic_issue_id": 2 } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +## Assign an issue to the epic[](#assign-an-issue-to-the-epic "Permalink") + +创建史诗-事件关联. 如果所讨论的问题属于另一个史诗,则不会从该史诗中分配该问题. + +``` +POST /groups/:id/epics/:epic_iid/issues/:issue_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID. | +| `issue_id` | integer/string | yes | 问题的 ID. | + +``` +curl --header POST "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/issues/55" +``` + +响应示例: + +``` +{ "id": 11, "epic": { "id": 30, "iid": 5, "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author": { "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }, "start_date": null, "end_date": null }, "issue": { "id": 55, "iid": 13, "project_id": 8, "title": "Beatae laborum voluptatem voluptate eligendi ex accusamus.", "description": "Quam veritatis debitis omnis aliquam sit.", "state": "opened", "created_at": "2017-11-05T13:59:12.782Z", "updated_at": "2018-01-05T10:33:03.900Z", "closed_at": null, "labels": [], "milestone": { "id": 48, "iid": 6, "project_id": 8, "title": "Sprint - Sed sed maxime temporibus ipsa ullam qui sit.", "description": "Quos veritatis qui expedita sunt deleniti accusamus.", "state": "active", "created_at": "2017-11-05T13:59:12.445Z", "updated_at": "2017-11-05T13:59:12.445Z", "due_date": "2017-11-13", "start_date": "2017-11-05" }, "assignees": [{ "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }], "assignee": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "author": { "id": 25, "name": "User 3", "username": "user3", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80&d=identicon", "web_url": "http://localhost:3001/user3" }, "user_notes_count": 0, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "weight": null, "discussion_locked": null, "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/13", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } } +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +## Remove an issue from the epic[](#remove-an-issue-from-the-epic "Permalink") + +删除史诗-问题关联. + +``` +DELETE /groups/:id/epics/:epic_iid/issues/:epic_issue_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID. | +| `epic_issue_id` | integer/string | yes | 问题的 ID-史诗般的协会. | + +``` +curl --header DELETE "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/issues/11" +``` + +响应示例: + +``` +{ "id": 11, "epic": { "id": 30, "iid": 5, "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author": { "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }, "start_date": null, "end_date": null }, "issue": { "id": 223, "iid": 13, "project_id": 8, "title": "Beatae laborum voluptatem voluptate eligendi ex accusamus.", "description": "Quam veritatis debitis omnis aliquam sit.", "state": "opened", "created_at": "2017-11-05T13:59:12.782Z", "updated_at": "2018-01-05T10:33:03.900Z", "closed_at": null, "labels": [], "milestone": { "id": 48, "iid": 6, "project_id": 8, "title": "Sprint - Sed sed maxime temporibus ipsa ullam qui sit.", "description": "Quos veritatis qui expedita sunt deleniti accusamus.", "state": "active", "created_at": "2017-11-05T13:59:12.445Z", "updated_at": "2017-11-05T13:59:12.445Z", "due_date": "2017-11-13", "start_date": "2017-11-05" }, "assignees": [{ "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }], "assignee": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "author": { "id": 25, "name": "User 3", "username": "user3", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80&d=identicon", "web_url": "http://localhost:3001/user3" }, "user_notes_count": 0, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "weight": null, "discussion_locked": null, "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/13", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } } +``` + +**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. + +## Update epic - issue association[](#update-epic---issue-association "Permalink") + +更新史诗-问题关联. + +``` +PUT /groups/:id/epics/:epic_iid/issues/:epic_issue_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer/string | yes | 史诗的内部 ID. | +| `epic_issue_id` | integer/string | yes | 问题的 ID-史诗般的协会. | +| `move_before_id` | integer/string | no | 问题的 ID-史诗般的关联,应放在问题中的链接之前. | +| `move_after_id` | integer/string | no | 问题的 ID-史诗般的关联,应该放在问题中的链接之后. | + +``` +curl --header PUT "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/issues/11?move_before_id=20" +``` + +响应示例: + +``` +[ { "id": 30, "iid": 6, "project_id": 8, "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", "description" : "Ratione dolores corrupti mollitia soluta quia.", "state": "opened", "created_at": "2017-11-15T13:39:24.670Z", "updated_at": "2018-01-04T10:49:19.506Z", "closed_at": null, "labels": [], "milestone": { "id": 38, "iid": 3, "project_id": 8, "title": "v2.0", "description": "In tempore culpa inventore quo accusantium.", "state": "closed", "created_at": "2017-11-15T13:39:13.825Z", "updated_at": "2017-11-15T13:39:13.825Z", "due_date": null, "start_date": null }, "assignees": [{ "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }], "assignee": { "id": 7, "name": "Pamella Huel", "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", "web_url": "http://localhost:3001/arnita" }, "author": { "id": 13, "name": "Michell Johns", "username": "chris_hahn", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/30e3b2122ccd6b8e45e8e14a3ffb58fc?s=80&d=identicon", "web_url": "http://localhost:3001/chris_hahn" }, "user_notes_count": 8, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "weight": null, "discussion_locked": null, "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/6", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "_links":{ "self": "http://localhost:3001/api/v4/projects/8/issues/6", "notes": "http://localhost:3001/api/v4/projects/8/issues/6/notes", "award_emoji": "http://localhost:3001/api/v4/projects/8/issues/6/award_emoji", "project": "http://localhost:3001/api/v4/projects/8" }, "subscribed": true, "epic_issue_id": 11, "relative_position": 55 } ] +``` \ No newline at end of file diff --git a/docs/324.md b/docs/324.md new file mode 100644 index 0000000000000000000000000000000000000000..2daad0ba9a23a87a1eaa232494f435921f3d0674 --- /dev/null +++ b/docs/324.md @@ -0,0 +1,157 @@ +# Issues Statistics API + +> 原文:[https://docs.gitlab.com/ee/api/issues_statistics.html](https://docs.gitlab.com/ee/api/issues_statistics.html) + +* [Get issues statistics](#get-issues-statistics) +* [Get group issues statistics](#get-group-issues-statistics) +* [Get project issues statistics](#get-project-issues-statistics) + +# Issues Statistics API[](#issues-statistics-api "Permalink") + +每个对 issue_statistics 的 API 调用都必须经过身份验证. + +如果用户不是项目成员,并且该项目是私有项目,则对该项目的`GET`请求将导致`404`状态代码. + +## Get issues statistics[](#get-issues-statistics "Permalink") + +获取有关经过身份验证的用户有权访问的所有问题的问题计数统计信息. 默认情况下,它仅返回当前用户创建的问题. 要获取所有问题,请使用参数`scope=all` . + +``` +GET /issues_statistics +GET /issues_statistics?labels=foo +GET /issues_statistics?labels=foo,bar +GET /issues_statistics?labels=foo,bar&state=opened +GET /issues_statistics?milestone=1.0.0 +GET /issues_statistics?milestone=1.0.0&state=opened +GET /issues_statistics?iids[]=42&iids[]=43 +GET /issues_statistics?author_id=5 +GET /issues_statistics?assignee_id=5 +GET /issues_statistics?my_reaction_emoji=star +GET /issues_statistics?search=foo&in=title +GET /issues_statistics?confidential=true +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `labels` | string | no | 标签名称的逗号分隔列表,必须具有要返回的所有标签的问题. `None`列出所有没有标签的问题. `Any`列出至少带有一个标签的所有问题. | +| `milestone` | string | no | 里程碑标题. `None`列出没有里程碑的所有问题. `Any`列出具有指定里程碑的所有问题. | +| `scope` | string | no | 回到问题在给定范围: `created_by_me` , `assigned_to_me`或`all` . 默认为`created_by_me` | +| `author_id` | integer | no | 返回由给定用户`id`创建的问题. 与`author_username` . 与`scope=all`或`scope=assigned_to_me`结合使用. | +| `author_username` | string | no | 返回由给定`username`创建的问题. 类似于`author_id`并且与`author_id` . | +| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. | +| `assignee_username` | 字符串数组 | no | 返回分配给给定`username` . 类似于`assignee_id`并且与`assignee_id`互斥. 在 GitLab CE 中, `assignee_username`数组应仅包含单个值,否则将返回无效的参数错误. | +| `my_reaction_emoji` | string | no | 返回的问题由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的问题 | +| `search` | string | no | 根据`title`和`description`搜索问题 | +| `in` | string | no | 修改`search`属性的范围. `title` , `description`或以逗号将它们连接在一起的字符串. 默认为`title,description` | +| `created_after` | datetime | no | 返回在给定时间或之后创建的问题 | +| `created_before` | datetime | no | 返回在给定时间或之前创建的问题 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的问题 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的问题 | +| `confidential` | boolean | no | 过滤机密或公共问题. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/issues_statistics" +``` + +响应示例: + +``` +{ "statistics": { "counts": { "all": 20, "closed": 5, "opened": 15 } } } +``` + +## Get group issues statistics[](#get-group-issues-statistics "Permalink") + +获取给定组的问题计数统计信息. + +``` +GET /groups/:id/issues_statistics +GET /groups/:id/issues_statistics?labels=foo +GET /groups/:id/issues_statistics?labels=foo,bar +GET /groups/:id/issues_statistics?labels=foo,bar&state=opened +GET /groups/:id/issues_statistics?milestone=1.0.0 +GET /groups/:id/issues_statistics?milestone=1.0.0&state=opened +GET /groups/:id/issues_statistics?iids[]=42&iids[]=43 +GET /groups/:id/issues_statistics?search=issue+title+or+description +GET /groups/:id/issues_statistics?author_id=5 +GET /groups/:id/issues_statistics?assignee_id=5 +GET /groups/:id/issues_statistics?my_reaction_emoji=star +GET /groups/:id/issues_statistics?confidential=true +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `labels` | string | no | 标签名称的逗号分隔列表,必须具有要返回的所有标签的问题. `None`列出所有没有标签的问题. `Any`列出至少带有一个标签的所有问题. | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的问题 | +| `milestone` | string | no | 里程碑标题. `None`列出没有里程碑的所有问题. `Any`列出具有指定里程碑的所有问题. | +| `scope` | string | no | 回到问题在给定范围: `created_by_me` , `assigned_to_me`或`all` . | +| `author_id` | integer | no | 返回由给定用户`id`创建的问题. 与`author_username` . 与`scope=all`或`scope=assigned_to_me`结合使用. | +| `author_username` | string | no | 返回由给定`username`创建的问题. 类似于`author_id`并且与`author_id` . | +| `assignee_id` | integer | no | 返回分配给给定用户`id` . 互斥与`assignee_username` . `None`返回未分配的问题. 受让人有`Any`退货问题. | +| `assignee_username` | 字符串数组 | no | 返回分配给给定`username` . 类似于`assignee_id`并且与`assignee_id`互斥. 在 GitLab CE 中, `assignee_username`数组应仅包含单个值,否则将返回无效的参数错误. | +| `my_reaction_emoji` | string | no | 返回的问题由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. | +| `search` | string | no | 搜索组问题的`title`和`description` | +| `created_after` | datetime | no | 返回在给定时间或之后创建的问题 | +| `created_before` | datetime | no | 返回在给定时间或之前创建的问题 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的问题 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的问题 | +| `confidential` | boolean | no | 过滤机密或公共问题. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4/issues_statistics" +``` + +响应示例: + +``` +{ "statistics": { "counts": { "all": 20, "closed": 5, "opened": 15 } } } +``` + +## Get project issues statistics[](#get-project-issues-statistics "Permalink") + +获取给定项目的问题计数统计信息. + +``` +GET /projects/:id/issues_statistics +GET /projects/:id/issues_statistics?labels=foo +GET /projects/:id/issues_statistics?labels=foo,bar +GET /projects/:id/issues_statistics?labels=foo,bar&state=opened +GET /projects/:id/issues_statistics?milestone=1.0.0 +GET /projects/:id/issues_statistics?milestone=1.0.0&state=opened +GET /projects/:id/issues_statistics?iids[]=42&iids[]=43 +GET /projects/:id/issues_statistics?search=issue+title+or+description +GET /projects/:id/issues_statistics?author_id=5 +GET /projects/:id/issues_statistics?assignee_id=5 +GET /projects/:id/issues_statistics?my_reaction_emoji=star +GET /projects/:id/issues_statistics?confidential=true +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的里程碑 | +| `labels` | string | no | 标签名称的逗号分隔列表,必须具有要返回的所有标签的问题. `None`列出所有没有标签的问题. `Any`列出至少带有一个标签的所有问题. | +| `milestone` | string | no | 里程碑标题. `None`列出没有里程碑的所有问题. `Any`列出具有指定里程碑的所有问题. | +| `scope` | string | no | 回到问题在给定范围: `created_by_me` , `assigned_to_me`或`all` . | +| `author_id` | integer | no | 返回由给定用户`id`创建的问题. 与`author_username` . 与`scope=all`或`scope=assigned_to_me`结合使用. | +| `author_username` | string | no | 返回由给定`username`创建的问题. 类似于`author_id`并且与`author_id` . | +| `assignee_id` | integer | no | 返回分配给给定用户`id` . 互斥与`assignee_username` . `None`返回未分配的问题. 受让人有`Any`退货问题. | +| `assignee_username` | 字符串数组 | no | 返回分配给给定`username` . 类似于`assignee_id`并且与`assignee_id`互斥. 在 GitLab CE 中, `assignee_username`数组应仅包含单个值,否则将返回无效的参数错误. | +| `my_reaction_emoji` | string | no | 返回的问题由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. | +| `search` | string | no | 根据`title`和`description`搜索项目问题 | +| `created_after` | datetime | no | Return issues created on or after the given time | +| `created_before` | datetime | no | 返回在给定时间或之前创建的问题 | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的问题 | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的问题 | +| `confidential` | boolean | no | 过滤机密或公共问题. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues_statistics" +``` + +响应示例: + +``` +{ "statistics": { "counts": { "all": 20, "closed": 5, "opened": 15 } } } +``` \ No newline at end of file diff --git a/docs/325.md b/docs/325.md new file mode 100644 index 0000000000000000000000000000000000000000..5b3b373215debee4c84d544f65c6264f62d667d8 --- /dev/null +++ b/docs/325.md @@ -0,0 +1,465 @@ +# Jobs API + +> 原文:[https://docs.gitlab.com/ee/api/jobs.html](https://docs.gitlab.com/ee/api/jobs.html) + +* [List project jobs](#list-project-jobs) +* [List pipeline jobs](#list-pipeline-jobs) +* [List pipeline bridges](#list-pipeline-bridges) +* [Get a single job](#get-a-single-job) +* [Get job artifacts](#get-job-artifacts) +* [Download the artifacts archive](#download-the-artifacts-archive) +* [Download a single artifact file by job ID](#download-a-single-artifact-file-by-job-id) +* [Download a single artifact file from specific tag or branch](#download-a-single-artifact-file-from-specific-tag-or-branch) +* [Get a log file](#get-a-log-file) +* [Cancel a job](#cancel-a-job) +* [Retry a job](#retry-a-job) +* [Erase a job](#erase-a-job) +* [Keep artifacts](#keep-artifacts) +* [Delete artifacts](#delete-artifacts) +* [Play a job](#play-a-job) + +# Jobs API[](#jobs-api "Permalink") + +## List project jobs[](#list-project-jobs "Permalink") + +获取项目中的作业列表. 作业按 ID 的降序排列. + +``` +GET /projects/:id/jobs +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `scope` | 字符串**或**字符串数组 | no | 要显示的工作范围. 以下一项或多项: `created` , `pending` , `running` , `failed` , `success` , `canceled` , `skipped`或`manual` . 如果未提供`scope`则返回所有作业. | + +``` +curl --globoff --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs?scope[]=pending&scope[]=running" +``` + +回应范例 + +``` +[ { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2015-12-24T15:51:21.802Z", "started_at": "2015-12-24T17:54:27.722Z", "finished_at": "2015-12-24T17:54:27.895Z", "duration": 0.173, "artifacts_file": { "filename": "artifacts.zip", "size": 1000 }, "artifacts": [ {"file_type": "archive", "size": 1000, "filename": "artifacts.zip", "file_format": "zip"}, {"file_type": "metadata", "size": 186, "filename": "metadata.gz", "file_format": "gzip"}, {"file_type": "trace", "size": 1500, "filename": "job.log", "file_format": "raw"}, {"file_type": "junit", "size": 750, "filename": "junit.xml.gz", "file_format": "gzip"} ], "artifacts_expire_at": "2016-01-23T17:54:27.895Z", "id": 7, "name": "teaspoon", "pipeline": { "id": 6, "ref": "master", "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "status": "pending" }, "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/7", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" } }, { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2015-12-24T15:51:21.727Z", "started_at": "2015-12-24T17:54:24.729Z", "finished_at": "2015-12-24T17:54:24.921Z", "duration": 0.192, "artifacts_expire_at": "2016-01-23T17:54:24.921Z", "id": 6, "name": "rspec:other", "pipeline": { "id": 6, "ref": "master", "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "status": "pending" }, "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/6", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" } } ] +``` + +## List pipeline jobs[](#list-pipeline-jobs "Permalink") + +获取管道的作业列表. + +``` +GET /projects/:id/pipelines/:pipeline_id/jobs +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `pipeline_id` | integer | yes | 管道的 ID. | +| `scope` | 字符串**或**字符串数组 | no | 要显示的工作范围. 以下一项或多项: `created` , `pending` , `running` , `failed` , `success` , `canceled` , `skipped`或`manual` . 如果未提供`scope`则返回所有作业. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/6/jobs?scope[]=pending&scope[]=running" +``` + +回应范例 + +``` +[ { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2015-12-24T15:51:21.727Z", "started_at": "2015-12-24T17:54:24.729Z", "finished_at": "2015-12-24T17:54:24.921Z", "duration": 0.192, "artifacts_expire_at": "2016-01-23T17:54:24.921Z", "id": 6, "name": "rspec:other", "pipeline": { "id": 6, "ref": "master", "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "status": "pending" }, "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/6", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" } }, { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2015-12-24T15:51:21.802Z", "started_at": "2015-12-24T17:54:27.722Z", "finished_at": "2015-12-24T17:54:27.895Z", "duration": 0.173, "artifacts_file": { "filename": "artifacts.zip", "size": 1000 }, "artifacts": [ {"file_type": "archive", "size": 1000, "filename": "artifacts.zip", "file_format": "zip"}, {"file_type": "metadata", "size": 186, "filename": "metadata.gz", "file_format": "gzip"}, {"file_type": "trace", "size": 1500, "filename": "job.log", "file_format": "raw"}, {"file_type": "junit", "size": 750, "filename": "junit.xml.gz", "file_format": "gzip"} ], "artifacts_expire_at": "2016-01-23T17:54:27.895Z", "id": 7, "name": "teaspoon", "pipeline": { "id": 6, "ref": "master", "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "status": "pending" }, "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/7", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" } } ] +``` + +从 GitLab 13.2 开始,此端点[将返回任何管道(](pipelines.html#single-pipeline-requests)包括[子管道)的数据](../ci/parent_child_pipelines.html) . + +## List pipeline bridges[](#list-pipeline-bridges "Permalink") + +获取管道的桥作业列表. + +``` +GET /projects/:id/pipelines/:pipeline_id/bridges +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `pipeline_id` | integer | yes | 管道的 ID. | +| `scope` | 字符串**或**字符串数组 | no | 要显示的工作范围. 以下一项或多项: `created` , `pending` , `running` , `failed` , `success` , `canceled` , `skipped`或`manual` . 如果未提供`scope`则返回所有作业. | + +``` +curl --header "PRIVATE-TOKEN: " 'https://gitlab.example.com/api/v4/projects/1/pipelines/6/bridges?scope[]=pending&scope[]=running' +``` + +回应范例 + +``` +[ { "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2015-12-24T15:51:21.802Z", "started_at": "2015-12-24T17:54:27.722Z", "finished_at": "2015-12-24T17:58:27.895Z", "duration": 240, "id": 7, "name": "teaspoon", "pipeline": { "id": 6, "ref": "master", "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "status": "pending", "created_at": "2015-12-24T15:50:16.123Z", "updated_at": "2015-12-24T18:00:44.432Z", "web_url": "https://example.com/foo/bar/pipelines/6" }, "ref": "master", "stage": "test", "status": "pending", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/7", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" }, "downstream_pipeline": { "id": 5, "sha": "f62a4b2fb89754372a346f24659212eb8da13601", "ref": "master", "status": "pending", "created_at": "2015-12-24T17:54:27.722Z", "updated_at": "2015-12-24T17:58:27.896Z", "web_url": "https://example.com/diaspora/diaspora-client/pipelines/5" } } ] +``` + +## Get a single job[](#get-a-single-job "Permalink") + +获得项目的一份工作 + +``` +GET /projects/:id/jobs/:job_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/8" +``` + +回应范例 + +``` +{ "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2015-12-24T15:51:21.880Z", "started_at": "2015-12-24T17:54:30.733Z", "finished_at": "2015-12-24T17:54:31.198Z", "duration": 0.465, "artifacts_expire_at": "2016-01-23T17:54:31.198Z", "id": 8, "name": "rubocop", "pipeline": { "id": 6, "ref": "master", "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "status": "pending" }, "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/8", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.dev/root", "created_at": "2015-12-21T13:14:24.077Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "" } } +``` + +## Get job artifacts[](#get-job-artifacts "Permalink") + +版本历史 + +**注意事项** : + +* 在 GitLab 8.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2893) . +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 9.5 中[引入了](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2346)在工件下载 API 中使用`CI_JOB_TOKEN` . + +获取项目的工件压缩文件存档. + +``` +GET /projects/:id/jobs/:job_id/artifacts +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | +| `job_token` | string | no | 与多项目管道的[触发器](../ci/triggers/README.html#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium)一起使用. 它只能在`.gitlab-ci.yml`内部调用. 其值始终`$CI_JOB_TOKEN` . | + +使用`PRIVATE-TOKEN`标头的示例请求: + +``` +curl --output artifacts.zip --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts" +``` + +要在`.gitlab-ci.yml`中的[`script`定义中](../ci/yaml/README.html#script)使用它 ,您可以使用以下任一方法: + +* GitLab 提供的`CI_JOB_TOKEN`变量的`JOB-TOKEN`标头. 例如,以下作业将下载 ID 为`42`的作业工件. 注意,该命令被缠绕成单引号,因为它含有一个冒号( `:` ): + + ``` + artifact_download: + stage: test + script: + - 'curl --location --output artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts"' + ``` + +* 或带有 GitLab 提供的`CI_JOB_TOKEN`变量的`job_token`属性. 例如,以下作业将下载 ID 为`42`的作业的工件: + + ``` + artifact_download: + stage: test + script: + - 'curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts?job_token=$CI_JOB_TOKEN"' + ``` + +可能的响应状态代码: + +| Status | Description | +| --- | --- | +| 200 | Serves the artifacts file. | +| 404 | 找不到构建或没有工件. | + +## Download the artifacts archive[](#download-the-artifacts-archive "Permalink") + +版本历史 + +**注意事项** : + +* 在 GitLab 8.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5347) . +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 9.5 中[引入了](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2346)在工件下载 API 中使用`CI_JOB_TOKEN` . + +如果作业成功完成,请从最新成功的管道中下载给定参考名称和作业的工件压缩存档. 这与[获取作业的工件相同](#get-job-artifacts) ,但是通过定义作业的名称而不是其 ID. + +``` +GET /projects/:id/jobs/artifacts/:ref_name/download?job=name +``` + +Parameters + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `ref_name` | string | yes | 存储库中的分支或标记名称. 不支持 HEAD 或 SHA 引用. | +| `job` | string | yes | 工作名称. | +| `job_token` | string | no | 与多项目管道的[触发器](../ci/triggers/README.html#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium)一起使用. 它只能在`.gitlab-ci.yml`内部调用. 其值始终`$CI_JOB_TOKEN` . | + +使用`PRIVATE-TOKEN`标头的示例请求: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test" +``` + +要在`.gitlab-ci.yml`中的[`script`定义中](../ci/yaml/README.html#script)使用它 ,您可以使用以下任一方法: + +* GitLab 提供的`CI_JOB_TOKEN`变量的`JOB-TOKEN`标头. 例如,以下作业将下载`master`分支的`test`作业的工件. 注意,该命令被缠绕成单引号,因为它含有一个冒号( `:` ): + + ``` + artifact_download: + stage: test + script: + - 'curl --location --output artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/master/download?job=test"' + ``` + +* 或带有 GitLab 提供的`CI_JOB_TOKEN`变量的`job_token`属性. 例如,以下作业将下载`master`分支的`test`作业的工件: + + ``` + artifact_download: + stage: test + script: + - 'curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/master/download?job=test&job_token=$CI_JOB_TOKEN"' + ``` + +可能的响应状态代码: + +| Status | Description | +| --- | --- | +| 200 | 服务工件文件. | +| 404 | 找不到构建或没有工件. | + +## Download a single artifact file by job ID[](#download-a-single-artifact-file-by-job-id "Permalink") + +在 GitLab 10.0 中引入 + +从作业的工件压缩文件中以指定的 ID 下载作业中的单个工件文件. 从存档中提取文件,并将其流式传输到客户端. + +``` +GET /projects/:id/jobs/:job_id/artifacts/*artifact_path +``` + +Parameters + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 唯一的作业标识符. | +| `artifact_path` | string | yes | 工件存档内文件的路径. | + +请求示例: + +``` +curl --location --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/5/artifacts/some/release/file.pdf" +``` + +可能的响应状态代码: + +| Status | Description | +| --- | --- | +| 200 | 发送单个工件文件 | +| 400 | 提供的路径无效 | +| 404 | 找不到版本或没有文件/工件 | + +## Download a single artifact file from specific tag or branch[](#download-a-single-artifact-file-from-specific-tag-or-branch "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23538) . + +从作业的工件存档中为给定的参考名称下载最新成功管道的特定作业的单个工件文件. 从存档中提取文件,并将其流式传输到客户端. + +``` +GET /projects/:id/jobs/artifacts/:ref_name/raw/*artifact_path?job=name +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `ref_name` | string | yes | 存储库中的分支或标记名称. 不支持 HEAD 或 SHA 引用. | +| `artifact_path` | string | yes | 工件存档内文件的路径. | +| `job` | string | yes | 工作名称. | + +请求示例: + +``` +curl --location --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/raw/some/release/file.pdf?job=pdf" +``` + +可能的响应状态代码: + +| Status | Description | +| --- | --- | +| 200 | 发送单个工件文件 | +| 400 | 提供的路径无效 | +| 404 | 找不到版本或没有文件/工件 | + +## Get a log file[](#get-a-log-file "Permalink") + +获取项目的特定作业的日志(跟踪): + +``` +GET /projects/:id/jobs/:job_id/trace +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +``` +curl --location --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/8/trace" +``` + +可能的响应状态代码: + +| Status | Description | +| --- | --- | +| 200 | 服务日志文件 | +| 404 | 找不到作业或没有日志文件 | + +## Cancel a job[](#cancel-a-job "Permalink") + +取消项目的一项工作 + +``` +POST /projects/:id/jobs/:job_id/cancel +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/cancel" +``` + +回应范例 + +``` +{ "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2016-01-11T10:13:33.506Z", "started_at": "2016-01-11T10:14:09.526Z", "finished_at": null, "duration": 8, "id": 42, "name": "rubocop", "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "canceled", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/42", "user": null } +``` + +## Retry a job[](#retry-a-job "Permalink") + +重试项目的一项工作 + +``` +POST /projects/:id/jobs/:job_id/retry +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/retry" +``` + +回应范例 + +``` +{ "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2016-01-11T10:13:33.506Z", "started_at": null, "finished_at": null, "duration": null, "id": 42, "name": "rubocop", "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "pending", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/42", "user": null } +``` + +## Erase a job[](#erase-a-job "Permalink") + +擦除项目的单个作业(删除作业工件和作业日志) + +``` +POST /projects/:id/jobs/:job_id/erase +``` + +Parameters + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +Example of request + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/erase" +``` + +回应范例 + +``` +{ "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "download_url": null, "id": 42, "name": "rubocop", "ref": "master", "artifacts": [], "runner": null, "stage": "test", "created_at": "2016-01-11T10:13:33.506Z", "started_at": "2016-01-11T10:13:33.506Z", "finished_at": "2016-01-11T10:15:10.506Z", "duration": 97.0, "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/42", "user": null } +``` + +## Keep artifacts[](#keep-artifacts "Permalink") + +设置过期时,防止删除工件. + +``` +POST /projects/:id/jobs/:job_id/artifacts/keep +``` + +Parameters + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts/keep" +``` + +响应示例: + +``` +{ "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "download_url": null, "id": 42, "name": "rubocop", "ref": "master", "artifacts": [], "runner": null, "stage": "test", "created_at": "2016-01-11T10:13:33.506Z", "started_at": "2016-01-11T10:13:33.506Z", "finished_at": "2016-01-11T10:15:10.506Z", "duration": 97.0, "status": "failed", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/42", "user": null } +``` + +## Delete artifacts[](#delete-artifacts "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25522) . + +删除作业的工件. + +``` +DELETE /projects/:id/jobs/:job_id/artifacts +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `job_id` | integer | yes | 工作 ID. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts" +``` + +**注意:**至少需要具有维护者角色才能删除工件. + +如果工件被成功删除,则返回状态为`204 No Content`的响应. + +## Play a job[](#play-a-job "Permalink") + +触发手动操作以开始作业. + +``` +POST /projects/:id/jobs/:job_id/play +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 身份验证用户拥有[的项目的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `job_id` | integer | yes | 工作 ID. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/play" +``` + +回应范例 + +``` +{ "commit": { "author_email": "admin@example.com", "author_name": "Administrator", "created_at": "2015-12-24T16:51:14.000+01:00", "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", "message": "Test the CI integration.", "short_id": "0ff3ae19", "title": "Test the CI integration." }, "coverage": null, "allow_failure": false, "created_at": "2016-01-11T10:13:33.506Z", "started_at": null, "finished_at": null, "duration": null, "id": 42, "name": "rubocop", "ref": "master", "artifacts": [], "runner": null, "stage": "test", "status": "started", "tag": false, "web_url": "https://example.com/foo/bar/-/jobs/42", "user": null } +``` \ No newline at end of file diff --git a/docs/326.md b/docs/326.md new file mode 100644 index 0000000000000000000000000000000000000000..b10f6cb7872880d5c022c23aa671dc2727657374 --- /dev/null +++ b/docs/326.md @@ -0,0 +1,81 @@ +# Keys API + +> 原文:[https://docs.gitlab.com/ee/api/keys.html](https://docs.gitlab.com/ee/api/keys.html) + +* [Get SSH key with user by ID of an SSH key](#get-ssh-key-with-user-by-id-of-an-ssh-key) +* [Get user by fingerprint of SSH key](#get-user-by-fingerprint-of-ssh-key) +* [Get user by deploy key fingerprint](#get-user-by-deploy-key-fingerprint) + +# Keys API[](#keys-api "Permalink") + +## Get SSH key with user by ID of an SSH key[](#get-ssh-key-with-user-by-id-of-an-ssh-key "Permalink") + +通过 SSH 密钥的 ID 获取具有用户的 SSH 密钥. 请注意,只有管理员才能通过 SSH 密钥 ID 用用户查找 SSH 密钥. + +``` +GET /keys/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | SSH 密钥的 ID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/keys/1" +``` + +``` +{ "id": 1, "title": "Sample key 25", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt1256k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2015-09-03T07:24:44.627Z", "expires_at": "2020-05-05T00:00:00.000Z" "user": { "name": "John Smith", "username": "john_smith", "id": 25, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/cfa35b8cd2ec278026357769582fa563?s=40\u0026d=identicon", "web_url": "http://localhost:3000/john_smith", "created_at": "2015-09-03T07:24:01.670Z", "bio": null, "location": null, "public_email": "john@example.com", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": null, "last_sign_in_at": "2015-09-03T07:24:01.670Z", "confirmed_at": "2015-09-03T07:24:01.670Z", "last_activity_on": "2015-09-03", "email": "john@example.com", "theme_id": 2, "color_scheme_id": 1, "projects_limit": 10, "current_sign_in_at": null, "identities": [], "can_create_group": true, "can_create_project": true, "two_factor_enabled": false "external": false, "private_profile": null } } +``` + +## Get user by fingerprint of SSH key[](#get-user-by-fingerprint-of-ssh-key "Permalink") + +您可以搜索拥有特定 SSH 密钥的用户. 请注意,只有管理员才能使用 SSH 密钥的指纹查找 SSH 密钥. + +``` +GET /keys +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `fingerprint` | string | yes | SSH 密钥的指纹 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/keys?fingerprint=ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1" +``` + +如果使用 sha256 指纹 API 调用,请确保指纹经过 URL 编码. + +例如, `/`由`/`表示,而`:`由`:`表示: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/keys?fingerprint=SHA256%3AnUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo%2FlCg" +``` + +响应示例: + +``` +{ "id": 1, "title": "Sample key 1", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt1016k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2019-11-14T15:11:13.222Z", "expires_at": "2020-05-05T00:00:00.000Z" "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://0.0.0.0:3000/root", "created_at": "2019-11-14T15:09:34.831Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": null, "last_sign_in_at": "2019-11-16T22:41:26.663Z", "confirmed_at": "2019-11-14T15:09:34.575Z", "last_activity_on": "2019-11-20", "email": "admin@example.com", "theme_id": 1, "color_scheme_id": 1, "projects_limit": 100000, "current_sign_in_at": "2019-11-19T14:42:18.078Z", "identities": [ ], "can_create_group": true, "can_create_project": true, "two_factor_enabled": false, "external": false, "private_profile": false, "shared_runners_minutes_limit": null, "extra_shared_runners_minutes_limit": null } } +``` + +## Get user by deploy key fingerprint[](#get-user-by-deploy-key-fingerprint "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/119209) . + +部署密钥绑定到创建用户,因此,如果使用部署密钥指纹进行查询,则将获得有关使用该密钥的项目的其他信息. + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/keys?fingerprint=SHA256%3AnUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo%2FlCg" +``` + +响应示例: + +``` +{ "id": 1, "title": "Sample key 1", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt1016k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2019-11-14T15:11:13.222Z", "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://0.0.0.0:3000/root", "created_at": "2019-11-14T15:09:34.831Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": null, "last_sign_in_at": "2019-11-16T22:41:26.663Z", "confirmed_at": "2019-11-14T15:09:34.575Z", "last_activity_on": "2019-11-20", "email": "admin@example.com", "theme_id": 1, "color_scheme_id": 1, "projects_limit": 100000, "current_sign_in_at": "2019-11-19T14:42:18.078Z", "identities": [ ], "can_create_group": true, "can_create_project": true, "two_factor_enabled": false, "external": false, "private_profile": false, "shared_runners_minutes_limit": null, "extra_shared_runners_minutes_limit": null }, "deploy_keys_projects": [ { "id": 1, "deploy_key_id": 1, "project_id": 1, "created_at": "2020-01-09T07:32:52.453Z", "updated_at": "2020-01-09T07:32:52.453Z", "can_push": false } ] } +``` \ No newline at end of file diff --git a/docs/327.md b/docs/327.md new file mode 100644 index 0000000000000000000000000000000000000000..dd535dcfffabe4f0fd6abfc677a0649b23702b5b --- /dev/null +++ b/docs/327.md @@ -0,0 +1,207 @@ +# Labels API + +> 原文:[https://docs.gitlab.com/ee/api/labels.html](https://docs.gitlab.com/ee/api/labels.html) + +* [List labels](#list-labels) +* [Get a single project label](#get-a-single-project-label) +* [Create a new label](#create-a-new-label) +* [Delete a label](#delete-a-label) +* [Edit an existing label](#edit-an-existing-label) +* [Promote a project label to a group label](#promote-a-project-label-to-a-group-label) +* [Subscribe to a label](#subscribe-to-a-label) +* [Unsubscribe from a label](#unsubscribe-from-a-label) + +# Labels API[](#labels-api "Permalink") + +**注意:** `description_html`已添加到[GitLab 12.7 中的](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)响应 JSON. + +## List labels[](#list-labels "Permalink") + +获取给定项目的所有标签. + +默认情况下,此请求一次返回 20 个结果,因为 API 结果[是分页的](README.html#pagination) . + +``` +GET /projects/:id/labels +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `with_counts` | boolean | no | 是否包括发布和合并请求计数. 默认为`false` . *( [在 GitLab 12.2 中引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31543) )* | +| `include_ancestor_groups` | boolean | no | 包括祖先组. 默认为`true` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/labels?with_counts=true" +``` + +响应示例: + +``` +[ { "id" : 1, "name" : "bug", "color" : "#d9534f", "text_color" : "#FFFFFF", "description": "Bug reported by user", "description_html": "Bug reported by user", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 1, "subscribed": false, "priority": 10, "is_project_label": true }, { "id" : 4, "color" : "#d9534f", "text_color" : "#FFFFFF", "name" : "confirmed", "description": "Confirmed issue", "description_html": "Confirmed issue", "open_issues_count": 2, "closed_issues_count": 5, "open_merge_requests_count": 0, "subscribed": false, "priority": null, "is_project_label": true }, { "id" : 7, "name" : "critical", "color" : "#d9534f", "text_color" : "#FFFFFF", "description": "Critical issue. Need fix ASAP", "description_html": "Critical issue. Need fix ASAP", "open_issues_count": 1, "closed_issues_count": 3, "open_merge_requests_count": 1, "subscribed": false, "priority": null, "is_project_label": true }, { "id" : 8, "name" : "documentation", "color" : "#f0ad4e", "text_color" : "#FFFFFF", "description": "Issue about documentation", "description_html": "Issue about documentation", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 2, "subscribed": false, "priority": null, "is_project_label": false }, { "id" : 9, "color" : "#5cb85c", "text_color" : "#FFFFFF", "name" : "enhancement", "description": "Enhancement proposal", "description_html": "Enhancement proposal", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 1, "subscribed": true, "priority": null, "is_project_label": true } ] +``` + +## Get a single project label[](#get-a-single-project-label "Permalink") + +获取给定项目的单个标签. + +``` +GET /projects/:id/labels/:label_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 项目标签的 ID 或标题. | +| `include_ancestor_groups` | boolean | no | 包括祖先组. 默认为`true` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/labels/bug" +``` + +响应示例: + +``` +{ "id" : 1, "name" : "bug", "color" : "#d9534f", "text_color" : "#FFFFFF", "description": "Bug reported by user", "description_html": "Bug reported by user", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 1, "subscribed": false, "priority": 10, "is_project_label": true } +``` + +## Create a new label[](#create-a-new-label "Permalink") + +使用给定的名称和颜色为给定的存储库创建一个新标签. + +``` +POST /projects/:id/labels +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 标签名称 | +| `color` | string | yes | 标签的颜色以 6 位十六进制表示法加上前导"#"符号(例如#FFAABB)或[CSS 颜色名称之一给出](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/CSS/color_value) | +| `description` | string | no | 标签说明 | +| `priority` | integer | no | 标签的优先级. 必须大于或等于零或为`null`才能删除优先级. | + +``` +curl --data "name=feature&color=#5843AD" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/labels" +``` + +响应示例: + +``` +{ "id" : 10, "name" : "feature", "color" : "#5843AD", "text_color" : "#FFFFFF", "description":null, "description_html":null, "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false, "priority": null, "is_project_label": true } +``` + +## Delete a label[](#delete-a-label "Permalink") + +删除具有给定名称的标签. + +``` +DELETE /projects/:id/labels/:label_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/labels/bug" +``` + +**注意:**参数中带有`name`的较旧的端点`DELETE /projects/:id/labels`仍然可用,但已弃用. + +## Edit an existing label[](#edit-an-existing-label "Permalink") + +用新名称或新颜色更新现有标签. 至少需要一个参数来更新标签. + +``` +PUT /projects/:id/labels/:label_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | +| `new_name` | string | 是,如果未提供`color` | 标签的新名称 | +| `color` | string | 是,如果未提供`new_name` | 标签的颜色以 6 位十六进制表示法加上前导"#"符号(例如#FFAABB)或[CSS 颜色名称之一给出](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/CSS/color_value) | +| `description` | string | no | 标签的新说明 | +| `priority` | integer | no | 标签的新优先级. 必须大于或等于零或为`null`才能删除优先级. | + +``` +curl --request PUT --data "new_name=docs&color=#8E44AD&description=Documentation" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/labels/documentation" +``` + +响应示例: + +``` +{ "id" : 8, "name" : "docs", "color" : "#8E44AD", "text_color" : "#FFFFFF", "description": "Documentation", "description_html": "Documentation", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 2, "subscribed": false, "priority": null, "is_project_label": true } +``` + +**注意:**参数中带有`name`或`label_id`的较早的端点`PUT /projects/:id/labels`仍然可用,但已弃用. + +## Promote a project label to a group label[](#promote-a-project-label-to-a-group-label "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25218) . + +将项目标签提升为组标签. + +``` +PUT /projects/:id/labels/:label_id/promote +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/labels/documentation/promote" +``` + +响应示例: + +``` +{ "id" : 8, "name" : "documentation", "color" : "#8E44AD", "description": "Documentation", "description_html": "Documentation", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 2, "subscribed": false } +``` + +**注意:**在参数中带有`name`的较早的端点`PUT /projects/:id/labels/promote`仍然可用,但已弃用. + +## Subscribe to a label[](#subscribe-to-a-label "Permalink") + +将经过身份验证的用户订阅标签以接收通知. 如果用户已经订阅了标签,则返回状态码`304` . + +``` +POST /projects/:id/labels/:label_id/subscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 项目标签的 ID 或标题 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/labels/1/subscribe" +``` + +响应示例: + +``` +{ "id" : 1, "name" : "bug", "color" : "#d9534f", "text_color" : "#FFFFFF", "description": "Bug reported by user", "description_html": "Bug reported by user", "open_issues_count": 1, "closed_issues_count": 0, "open_merge_requests_count": 1, "subscribed": true, "priority": null, "is_project_label": true } +``` + +## Unsubscribe from a label[](#unsubscribe-from-a-label "Permalink") + +Unsubscribes the authenticated user from a label to not receive notifications from it. If the user is not subscribed to the label, the status code `304` is returned. + +``` +POST /projects/:id/labels/:label_id/unsubscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 项目标签的 ID 或标题 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/labels/1/unsubscribe" +``` \ No newline at end of file diff --git a/docs/328.md b/docs/328.md new file mode 100644 index 0000000000000000000000000000000000000000..a562127baa4304d43d52581cf0e33f96d0846d3e --- /dev/null +++ b/docs/328.md @@ -0,0 +1,185 @@ +# Group Labels API + +> 原文:[https://docs.gitlab.com/ee/api/group_labels.html](https://docs.gitlab.com/ee/api/group_labels.html) + +* [List group labels](#list-group-labels) +* [Get a single group label](#get-a-single-group-label) +* [Create a new group label](#create-a-new-group-label) +* [Update a group label](#update-a-group-label) +* [Delete a group label](#delete-a-group-label) +* [Subscribe to a group label](#subscribe-to-a-group-label) +* [Unsubscribe from a group label](#unsubscribe-from-a-group-label) + +# Group Labels API[](#group-labels-api "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21368) . + +该 API 支持[组标签的](../user/project/labels.html#project-labels-and-group-labels)管理. 它允许列出,创建,更新和删除组标签. 此外,用户可以订阅和取消订阅组标签. + +**注意:** `description_html`已添加到[GitLab 12.7 中的](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)响应 JSON. + +## List group labels[](#list-group-labels "Permalink") + +获取给定组的所有标签. + +``` +GET /groups/:id/labels +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `with_counts` | boolean | no | 是否包括发布和合并请求计数. 默认为`false` . *( [在 GitLab 12.2 中引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31543) )* | +| `include_ancestor_groups` | boolean | no | 包括祖先组. 默认为`true` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/labels?with_counts=true" +``` + +响应示例: + +``` +[ { "id": 7, "name": "bug", "color": "#FF0000", "text_color" : "#FFFFFF", "description": null, "description_html": null, "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false }, { "id": 4, "name": "feature", "color": "#228B22", "text_color" : "#FFFFFF", "description": null, "description_html": null, "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false } ] +``` + +## Get a single group label[](#get-a-single-group-label "Permalink") + +获取给定组的单个标签. + +``` +GET /groups/:id/labels/:label_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | +| `include_ancestor_groups` | boolean | no | 包括祖先组. 默认为`true` . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/labels/bug" +``` + +Example response: + +``` +{ "id": 7, "name": "bug", "color": "#FF0000", "text_color" : "#FFFFFF", "description": null, "description_html": null, "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false } +``` + +## Create a new group label[](#create-a-new-group-label "Permalink") + +为给定的组创建一个新的组标签. + +``` +POST /groups/:id/labels +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 标签名称 | +| `color` | string | yes | 标签的颜色以 6 位十六进制表示法加上前导"#"符号(例如#FFAABB)或[CSS 颜色名称之一给出](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/CSS/color_value) | +| `description` | string | no | 标签的说明, | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" --data '{"name": "Feature Proposal", "color": "#FFA500", "description": "Describes new ideas" }' "https://gitlab.example.com/api/v4/groups/5/labels" +``` + +响应示例: + +``` +{ "id": 9, "name": "Feature Proposal", "color": "#FFA500", "text_color" : "#FFFFFF", "description": "Describes new ideas", "description_html": "Describes new ideas", "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false } +``` + +## Update a group label[](#update-a-group-label "Permalink") + +更新现有的组标签. 至少需要一个参数来更新组标签. + +``` +PUT /groups/:id/labels/:label_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | +| `new_name` | string | no | 标签的新名称 | +| `color` | string | no | 标签的颜色以 6 位十六进制表示法加上前导"#"符号(例如#FFAABB)或[CSS 颜色名称之一给出](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/CSS/color_value) | +| `description` | string | no | 标签的描述. | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --header "Content-Type: application/json" --data '{"new_name": "Feature Idea" }' "https://gitlab.example.com/api/v4/groups/5/labels/Feature%20Proposal" +``` + +响应示例: + +``` +{ "id": 9, "name": "Feature Idea", "color": "#FFA500", "text_color" : "#FFFFFF", "description": "Describes new ideas", "description_html": "Describes new ideas", "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false } +``` + +**注意:**参数中带有`name`的较早的端点`PUT /groups/:id/labels`仍然可用,但已弃用. + +## Delete a group label[](#delete-a-group-label "Permalink") + +删除具有给定名称的组标签. + +``` +DELETE /groups/:id/labels/:label_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/labels/bug" +``` + +**注意:**参数中带有`name`的较旧的端点`DELETE /groups/:id/labels`仍然可用,但已弃用. + +## Subscribe to a group label[](#subscribe-to-a-group-label "Permalink") + +将经过身份验证的用户订阅到组标签以接收通知. 如果用户已经订阅了标签,则返回状态码`304` . + +``` +POST /groups/:id/labels/:label_id/subscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/labels/9/subscribe" +``` + +响应示例: + +``` +{ "id": 9, "name": "Feature Idea", "color": "#FFA500", "text_color" : "#FFFFFF", "description": "Describes new ideas", "description_html": "Describes new ideas", "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": true } +``` + +## Unsubscribe from a group label[](#unsubscribe-from-a-group-label "Permalink") + +从组标签退订已认证的用户以不接收来自该组标签的通知. 如果用户未订阅标签,则返回状态码`304` . + +``` +POST /groups/:id/labels/:label_id/unsubscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `label_id` | 整数或字符串 | yes | 群组标签的 ID 或标题. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/labels/9/unsubscribe" +``` + +响应示例: + +``` +{ "id": 9, "name": "Feature Idea", "color": "#FFA500", "text_color" : "#FFFFFF", "description": "Describes new ideas", "description_html": "Describes new ideas", "open_issues_count": 0, "closed_issues_count": 0, "open_merge_requests_count": 0, "subscribed": false } +``` \ No newline at end of file diff --git a/docs/329.md b/docs/329.md new file mode 100644 index 0000000000000000000000000000000000000000..3985c678d52e476fca0b323591a105655a1da00c --- /dev/null +++ b/docs/329.md @@ -0,0 +1,93 @@ +# License + +> 原文:[https://docs.gitlab.com/ee/api/license.html](https://docs.gitlab.com/ee/api/license.html) + +* [Retrieve information about the current license](#retrieve-information-about-the-current-license) +* [Retrieve information about all licenses](#retrieve-information-about-all-licenses) +* [Add a new license](#add-a-new-license) +* [Delete a license](#delete-a-license) + +# License[](#license-core-only "Permalink") + +为了与许可证端点进行交互,您需要以管理员身份进行身份验证. + +## Retrieve information about the current license[](#retrieve-information-about-the-current-license "Permalink") + +``` +GET /license +``` + +``` +{ "id": 2, "plan": "gold", "created_at": "2018-02-27T23:21:58.674Z", "starts_at": "2018-01-27", "expires_at": "2022-01-27", "historical_max": 300, "maximum_user_count": 300, "expired": false, "overage": 200, "user_limit": 100, "active_users": 300, "licensee": { "Name": "John Doe1" }, "add_ons": { "GitLab_FileLocks": 1, "GitLab_Auditor_User": 1 } } +``` + +## Retrieve information about all licenses[](#retrieve-information-about-all-licenses "Permalink") + +``` +GET /licenses +``` + +``` +[ { "id": 1, "plan": "silver", "created_at": "2018-02-27T23:21:58.674Z", "starts_at": "2018-01-27", "expires_at": "2022-01-27", "historical_max": 300, "maximum_user_count": 300, "expired": false, "overage": 200, "user_limit": 100, "licensee": { "Name": "John Doe1" }, "add_ons": { "GitLab_FileLocks": 1, "GitLab_Auditor_User": 1 } }, { "id": 2, "plan": "gold", "created_at": "2018-02-27T23:21:58.674Z", "starts_at": "2018-01-27", "expires_at": "2022-01-27", "historical_max": 300, "maximum_user_count": 300, "expired": false, "overage": 200, "user_limit": 100, "licensee": { "Name": "Doe John" }, "add_ons": { "GitLab_FileLocks": 1, } } ] +``` + +超出数是活动用户数与许可用户数之差. 根据许可证是否已过期,计算方法会有所不同. + +* 如果许可证已过期,则使用历史最大活动用户数( `historical_max` ). +* 如果许可证尚未过期,则使用当前活动用户数. + +Returns: + +* `200 OK` ,响应包含 JSON 格式的许可证. 如果没有许可证,这将是一个空的 JSON 数组. +* `403 Forbidden`如果当前用户不允许阅读许可证, `403 Forbidden` . + +## Add a new license[](#add-a-new-license "Permalink") + +``` +POST /license +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `license` | string | yes | 许可证字符串 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/license?license=eyJkYXRhIjoiMHM5Q...S01Udz09XG4ifQ==" +``` + +响应示例: + +``` +{ "id": 1, "plan": "gold", "created_at": "2018-02-27T23:21:58.674Z", "starts_at": "2018-01-27", "expires_at": "2022-01-27", "historical_max": 300, "maximum_user_count": 300, "expired": false, "overage": 200, "user_limit": 100, "active_users": 300, "licensee": { "Name": "John Doe1" }, "add_ons": { "GitLab_FileLocks": 1, "GitLab_Auditor_User": 1 } } +``` + +Returns: + +* `201 Created`如果成功添加许可证,则`201 Created` . +* `400 Bad Request`如果无法添加许可证),并附有一条错误消息,说明原因. + +## Delete a license[](#delete-a-license "Permalink") + +``` +DELETE /license/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | GitLab 许可证的 ID. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/license/:id" +``` + +响应示例: + +``` +{ "id": 2, "plan": "gold", "created_at": "2018-02-27T23:21:58.674Z", "starts_at": "2018-01-27", "expires_at": "2022-01-27", "historical_max": 300, "maximum_user_count": 300, "expired": false, "overage": 200, "user_limit": 100, "licensee": { "Name": "John Doe" }, "add_ons": { "GitLab_FileLocks": 1, "GitLab_Auditor_User": 1 } } +``` + +Returns: + +* `204 No Content`如果成功删除了许可证,则`204 No Content` . +* `403 Forbidden`如果当前用户不允许删除许可证,则禁止. +* 如果`404 Not Found`删除许可证,则`404 Not Found` . \ No newline at end of file diff --git a/docs/330.md b/docs/330.md new file mode 100644 index 0000000000000000000000000000000000000000..466b1255b82f4d05849552c176fbc6f9359422f2 --- /dev/null +++ b/docs/330.md @@ -0,0 +1,58 @@ +# Licenses API + +> 原文:[https://docs.gitlab.com/ee/api/templates/licenses.html](https://docs.gitlab.com/ee/api/templates/licenses.html) + +* [List license templates](#list-license-templates) +* [Single license template](#single-license-template) + +# Licenses API[](#licenses-api "Permalink") + +在 GitLab 中,有一个 API 端点可用于处理各种开源许可证模板. 有关各种许可条款的更多信息,请访问[此站点](https://choosealicense.com/)或在线提供的许多其他资源. + +## List license templates[](#list-license-templates "Permalink") + +获取所有许可证模板. + +``` +GET /templates/licenses +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `popular` | boolean | no | 如果通过,则仅返回常用许​​可证 | + +``` +curl https://gitlab.example.com/api/v4/templates/licenses?popular=1 +``` + +响应示例: + +``` +[ { "key": "apache-2.0", "name": "Apache License 2.0", "nickname": null, "featured": true, "html_url": "http://choosealicense.com/licenses/apache-2.0/", "source_url": "http://www.apache.org/licenses/LICENSE-2.0.html", "description": "A permissive license that also provides an express grant of patent rights from contributors to users.", "conditions": [ "include-copyright", "document-changes" ], "permissions": [ "commercial-use", "modifications", "distribution", "patent-use", "private-use" ], "limitations": [ "trademark-use", "no-liability" ], "content": " Apache License\n Version 2.0, January 2004\n [...]" }, { "key": "gpl-3.0", "name": "GNU General Public License v3.0", "nickname": "GNU GPLv3", "featured": true, "html_url": "http://choosealicense.com/licenses/gpl-3.0/", "source_url": "http://www.gnu.org/licenses/gpl-3.0.txt", "description": "The GNU GPL is the most widely used free software license and has a strong copyleft requirement. When distributing derived works, the source code of the work must be made available under the same license.", "conditions": [ "include-copyright", "document-changes", "disclose-source", "same-license" ], "permissions": [ "commercial-use", "modifications", "distribution", "patent-use", "private-use" ], "limitations": [ "no-liability" ], "content": " GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n [...]" }, { "key": "mit", "name": "MIT License", "nickname": null, "featured": true, "html_url": "http://choosealicense.com/licenses/mit/", "source_url": "http://opensource.org/licenses/MIT", "description": "A permissive license that is short and to the point. It lets people do anything with your code with proper attribution and without warranty.", "conditions": [ "include-copyright" ], "permissions": [ "commercial-use", "modifications", "distribution", "private-use" ], "limitations": [ "no-liability" ], "content": "The MIT License (MIT)\n\nCopyright (c) [year] [fullname]\n [...]" } ] +``` + +## Single license template[](#single-license-template "Permalink") + +获取单个许可证模板. 您可以传递参数来替换许可证占位符. + +``` +GET /templates/licenses/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `key` | string | yes | 许可证模板的密钥 | +| `project` | string | no | 受版权保护的项目名称 | +| `fullname` | string | no | 著作权人的全名 | + +> **注意:**如果省略`fullname`参数但对请求进行身份验证,则将使用经过身份验证的用户名来替换版权所有者占位符. + +``` +curl --header "PRIVATE-TOKEN: " https://gitlab.example.com/api/v4/templates/licenses/mit?project=My+Cool+Project +``` + +响应示例: + +``` +{ "key": "mit", "name": "MIT License", "nickname": null, "featured": true, "html_url": "http://choosealicense.com/licenses/mit/", "source_url": "http://opensource.org/licenses/MIT", "description": "A permissive license that is short and to the point. It lets people do anything with your code with proper attribution and without warranty.", "conditions": [ "include-copyright" ], "permissions": [ "commercial-use", "modifications", "distribution", "private-use" ], "limitations": [ "no-liability" ], "content": "The MIT License (MIT)\n\nCopyright (c) 2016 John Doe\n [...]" } +``` \ No newline at end of file diff --git a/docs/331.md b/docs/331.md new file mode 100644 index 0000000000000000000000000000000000000000..d719cd58865b6641495f02ed96fa2617720b23a8 --- /dev/null +++ b/docs/331.md @@ -0,0 +1,73 @@ +# Issue links API + +> 原文:[https://docs.gitlab.com/ee/api/issue_links.html](https://docs.gitlab.com/ee/api/issue_links.html) + +* [List issue relations](#list-issue-relations) +* [Create an issue link](#create-an-issue-link) +* [Delete an issue link](#delete-an-issue-link) + +# Issue links API[](#issue-links-api-starter "Permalink") + +## List issue relations[](#list-issue-relations "Permalink") + +获取给定问题的相关问题列表,按关系创建日期时间(升序)排序. 问题将根据用户授权进行过滤. + +``` +GET /projects/:id/issues/:issue_iid/links +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | + +``` +[ { "id" : 84, "iid" : 14, "issue_link_id": 1 "project_id" : 4, "created_at" : "2016-01-07T12:44:33.959Z", "title" : "Issues with auth", "state" : "opened", "assignees" : [], "assignee" : null, "labels" : [ "bug" ], "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": null, "web_url": "http://example.com/example/example/issues/14", "confidential": false, "weight": null, "link_type": "relates_to" } ] +``` + +## Create an issue link[](#create-an-issue-link "Permalink") + +在两个问题之间创建双向关系. 必须允许用户更新两个问题才能成功. + +``` +POST /projects/:id/issues/:issue_iid/links +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `target_project_id` | integer/string | yes | 目标项目[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `target_issue_iid` | integer/string | yes | 目标项目的内部 ID | +| `link_type` | string | no | 关系的类型(" relates_to"," blocks"," is_blocked_by")默认为" relates_to". | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues/1/links?target_project_id=5&target_issue_iid=1" +``` + +响应示例: + +``` +{ "source_issue" : { "id" : 83, "iid" : 11, "project_id" : 4, "created_at" : "2016-01-07T12:44:33.959Z", "title" : "Issues with auth", "state" : "opened", "assignees" : [], "assignee" : null, "labels" : [ "bug" ], "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": null, "web_url": "http://example.com/example/example/issues/11", "confidential": false, "weight": null, }, "target_issue" : { "id" : 84, "iid" : 14, "project_id" : 4, "created_at" : "2016-01-07T12:44:33.959Z", "title" : "Issues with auth", "state" : "opened", "assignees" : [], "assignee" : null, "labels" : [ "bug" ], "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": null, "web_url": "http://example.com/example/example/issues/14", "confidential": false, "weight": null, }, "link_type": "relates_to" } +``` + +## Delete an issue link[](#delete-an-issue-link "Permalink") + +删除问题链接,从而删除双向关系. + +``` +DELETE /projects/:id/issues/:issue_iid/links/:issue_link_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 项目问题的内部 ID | +| `issue_link_id` | integer/string | yes | 发行关系的 ID | +| `link_type` | string | no | 关系的类型(" relates_to"," blocks"," is_blocked_by")默认为" relates_to" | + +``` +{ "source_issue" : { "id" : 83, "iid" : 11, "project_id" : 4, "created_at" : "2016-01-07T12:44:33.959Z", "title" : "Issues with auth", "state" : "opened", "assignees" : [], "assignee" : null, "labels" : [ "bug" ], "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": null, "web_url": "http://example.com/example/example/issues/11", "confidential": false, "weight": null, }, "target_issue" : { "id" : 84, "iid" : 14, "project_id" : 4, "created_at" : "2016-01-07T12:44:33.959Z", "title" : "Issues with auth", "state" : "opened", "assignees" : [], "assignee" : null, "labels" : [ "bug" ], "author" : { "name" : "Alexandra Bashirian", "avatar_url" : null, "state" : "active", "web_url" : "https://gitlab.example.com/eileen.lowe", "id" : 18, "username" : "eileen.lowe" }, "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "milestone" : null, "subscribed" : true, "user_notes_count": 0, "due_date": null, "web_url": "http://example.com/example/example/issues/14", "confidential": false, "weight": null, }, "link_type": "relates_to" } +``` \ No newline at end of file diff --git a/docs/332.md b/docs/332.md new file mode 100644 index 0000000000000000000000000000000000000000..831ca06a9cd44d4e2f6b6e090fd4f72678fc92c7 --- /dev/null +++ b/docs/332.md @@ -0,0 +1,140 @@ +# Epic Links API + +> 原文:[https://docs.gitlab.com/ee/api/epic_links.html](https://docs.gitlab.com/ee/api/epic_links.html) + +* [List epics related to a given epic](#list-epics-related-to-a-given-epic) +* [Assign a child epic](#assign-a-child-epic) +* [Create and assign a child epic](#create-and-assign-a-child-epic) +* [Re-order a child epic](#re-order-a-child-epic) +* [Unassign a child epic](#unassign-a-child-epic) + +# Epic Links API[](#epic-links-api-ultimate "Permalink") + +**注意:**该端点是在 GitLab 11.8 中[引入的](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9188) . + +管理亲子[史诗般的关系](../user/group/epics/index.html#multi-level-child-epics-ultimate) . + +每个对`epic_links` API 调用`epic_links`必须经过身份验证. + +如果用户不是组的成员,并且该组是私有的,则对该组的`GET`请求将导致`404`状态代码. + +多级史诗仅在 GitLab [Ultimate / Gold](https://about.gitlab.com/pricing/)中可用. 如果"多级史诗"功能不可用,将返回`403`状态代码. + +## List epics related to a given epic[](#list-epics-related-to-a-given-epic "Permalink") + +获取史诗的所有子史诗. + +``` +GET /groups/:id/epics/:epic_iid/epics +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer | yes | 史诗的内部 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/epics/" +``` + +响应示例: + +``` +[ { "id": 29, "iid": 6, "group_id": 1, "parent_id": 5, "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "labels": [] } ] +``` + +## Assign a child epic[](#assign-a-child-epic "Permalink") + +在两个史诗之间创建关联,将一个史诗指定为父史诗,将另一个史诗指定为子史诗. 父史诗可以有多个子史诗. 如果新的子史诗已经属于另一个史诗,则该子史诗不会从先前的父史诗中分配. + +``` +POST /groups/:id/epics/:epic_iid/epics +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.html#namespaced-path-encoding) owned by the authenticated user | +| `epic_iid` | integer | yes | 史诗的内部 ID. | +| `child_epic_id` | integer | yes | 子史诗的全局 ID. 内部 ID 无法使用,因为它们可能与其他组的史诗冲突. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/epics/6" +``` + +响应示例: + +``` +{ "id": 6, "iid": 38, "group_id": 1, "parent_id": 5 "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "labels": [] } +``` + +## Create and assign a child epic[](#create-and-assign-a-child-epic "Permalink") + +创建一个新的史诗并将其与提供的父史诗相关联. 响应是 LinkedEpic 对象. + +``` +POST /groups/:id/epics/:epic_iid/epics +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `epic_iid` | integer | yes | (未来父级)史诗的内部 ID. | +| `title` | string | yes | 新创建的史诗的标题. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/5/epics?title=Newpic" +``` + +响应示例: + +``` +{ "id": 24, "iid": 2, "title": "child epic", "group_id": 49, "parent_id": 23, "has_children": false, "has_issues": false, "reference": "&2", "url": "http://localhost/groups/group16/-/epics/2", "relation_url": "http://localhost/groups/group16/-/epics/1/links/24" } +``` + +## Re-order a child epic[](#re-order-a-child-epic "Permalink") + +``` +PUT /groups/:id/epics/:epic_iid/epics/:child_epic_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `epic_iid` | integer | yes | 史诗的内部 ID. | +| `child_epic_id` | integer | yes | 子史诗的全局 ID. 内部 ID 无法使用,因为它们可能与其他组的史诗冲突. | +| `move_before_id` | integer | no | 同胞史诗的全局 ID,应放在子史诗之前. | +| `move_after_id` | integer | no | 同胞史诗的全局 ID,应放在子史诗之后. | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/4/epics/5" +``` + +响应示例: + +``` +[ { "id": 29, "iid": 6, "group_id": 1, "parent_id": 5, "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "labels": [] } ] +``` + +## Unassign a child epic[](#unassign-a-child-epic "Permalink") + +从父级史诗中取消分配子级史诗. + +``` +DELETE /groups/:id/epics/:epic_iid/epics/:child_epic_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `epic_iid` | integer | yes | 史诗的内部 ID. | +| `child_epic_id` | integer | yes | 子史诗的全局 ID. 内部 ID 无法使用,因为它们可能与其他组的史诗冲突. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/4/epics/5" +``` + +响应示例: + +``` +{ "id": 5, "iid": 38, "group_id": 1, "parent_id": null, "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "author": { "id": 10, "name": "Lu Mayer", "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", "web_url": "http://localhost:3001/kam" }, "start_date": null, "start_date_is_fixed": false, "start_date_fixed": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source "start_date_from_inherited_source": null, "end_date": "2018-07-31", //deprecated in favor of due_date "due_date": "2018-07-31", "due_date_is_fixed": false, "due_date_fixed": null, "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source "due_date_from_inherited_source": "2018-07-31", "created_at": "2018-07-17T13:36:22.770Z", "updated_at": "2018-07-18T12:22:05.239Z", "labels": [] } +``` \ No newline at end of file diff --git a/docs/333.md b/docs/333.md new file mode 100644 index 0000000000000000000000000000000000000000..f6808738c1d9fa0b3ddcedffc3fa711d5ad2eb1d --- /dev/null +++ b/docs/333.md @@ -0,0 +1,123 @@ +# Managed Licenses API + +> 原文:[https://docs.gitlab.com/ee/api/managed_licenses.html](https://docs.gitlab.com/ee/api/managed_licenses.html) + +* [List managed licenses](#list-managed-licenses) +* [Show an existing managed license](#show-an-existing-managed-license) +* [Create a new managed license](#create-a-new-managed-license) +* [Delete a managed license](#delete-a-managed-license) +* [Edit an existing managed license](#edit-an-existing-managed-license) + +# Managed Licenses API[](#managed-licenses-api-ultimate "Permalink") + +## List managed licenses[](#list-managed-licenses "Permalink") + +获取给定项目的所有托管许可证. + +``` +GET /projects/:id/managed_licenses +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/managed_licenses" +``` + +响应示例: + +``` +[ { "id": 1, "name": "MIT", "approval_status": "approved" }, { "id": 3, "name": "ISC", "approval_status": "blacklisted" } ] +``` + +## Show an existing managed license[](#show-an-existing-managed-license "Permalink") + +显示现有的托管许可证. + +``` +GET /projects/:id/managed_licenses/:managed_license_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `managed_license_id` | integer/string | yes | 属于项目的许可证的 ID 或 URL 编码名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6" +``` + +响应示例: + +``` +{ "id": 1, "name": "MIT", "approval_status": "blacklisted" } +``` + +## Create a new managed license[](#create-a-new-managed-license "Permalink") + +使用给定的名称和批准状态为给定的项目创建一个新的托管许可证. + +``` +POST /projects/:id/managed_licenses +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 托管许可证的名称 | +| `approval_status` | string | yes | 批准状态. "批准"或"列入黑名单" | + +``` +curl --data "name=MIT&approval_status=blacklisted" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/managed_licenses" +``` + +响应示例: + +``` +{ "id": 1, "name": "MIT", "approval_status": "approved" } +``` + +## Delete a managed license[](#delete-a-managed-license "Permalink") + +删除具有给定 ID 的托管许可证. + +``` +DELETE /projects/:id/managed_licenses/:managed_license_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `managed_license_id` | integer/string | yes | 属于项目的许可证的 ID 或 URL 编码名称 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/managed_licenses/4" +``` + +成功后,它将以 HTTP 204 响应进行回复. + +## Edit an existing managed license[](#edit-an-existing-managed-license "Permalink") + +使用新的批准状态更新现有的托管许可证. + +``` +PATCH /projects/:id/managed_licenses/:managed_license_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `managed_license_id` | integer/string | yes | 属于项目的许可证的 ID 或 URL 编码名称 | +| `approval_status` | string | yes | 批准状态. "批准"或"列入黑名单" | + +``` +curl --request PATCH --data "approval_status=blacklisted" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6" +``` + +响应示例: + +``` +{ "id": 1, "name": "MIT", "approval_status": "blacklisted" } +``` \ No newline at end of file diff --git a/docs/334.md b/docs/334.md new file mode 100644 index 0000000000000000000000000000000000000000..2fddbd1e238fa7eae31113cc11425c8168620cd4 --- /dev/null +++ b/docs/334.md @@ -0,0 +1,33 @@ +# Markdown API + +> 原文:[https://docs.gitlab.com/ee/api/markdown.html](https://docs.gitlab.com/ee/api/markdown.html) + +* [Render an arbitrary Markdown document](#render-an-arbitrary-markdown-document) + +# Markdown API[](#markdown-api "Permalink") + +在 GitLab 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18926) . + +仅在 APIv4 中可用. + +## Render an arbitrary Markdown document[](#render-an-arbitrary-markdown-document "Permalink") + +``` +POST /api/v4/markdown +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `text` | string | yes | Markdown 文本呈现 | +| `gfm` | boolean | 否(可选) | 使用 GitLab 风味 Markdown 渲染文本. 默认为`false` | +| `project` | string | 否(可选) | 使用 GitLab Flavored Markdown 创建引用时,请使用`project`作为上下文. 如果项目不是公开的,则需要[认证](README.html#authentication) . | + +``` +curl --header Content-Type:application/json --data '{"text":"Hello world! :tada:", "gfm":true, "project":"group_example/project_example"}' "https://gitlab.example.com/api/v4/markdown" +``` + +响应示例: + +``` +{ "html": "

      Hello world! 🎉

      " } +``` \ No newline at end of file diff --git a/docs/335.md b/docs/335.md new file mode 100644 index 0000000000000000000000000000000000000000..b2cf4d898c1f0765f5b0b58d1c58d43052f25a35 --- /dev/null +++ b/docs/335.md @@ -0,0 +1,266 @@ +# Group and project members API + +> 原文:[https://docs.gitlab.com/ee/api/members.html](https://docs.gitlab.com/ee/api/members.html) + +* [Valid access levels](#valid-access-levels) +* [List all members of a group or project](#list-all-members-of-a-group-or-project) +* [List all members of a group or project including inherited members](#list-all-members-of-a-group-or-project-including-inherited-members) +* [Get a member of a group or project](#get-a-member-of-a-group-or-project) +* [Get a member of a group or project, including inherited members](#get-a-member-of-a-group-or-project-including-inherited-members) +* [Add a member to a group or project](#add-a-member-to-a-group-or-project) +* [Edit a member of a group or project](#edit-a-member-of-a-group-or-project) + * [Set override flag for a member of a group](#set-override-flag-for-a-member-of-a-group) + * [Remove override for a member of a group](#remove-override-for-a-member-of-a-group) +* [Remove a member from a group or project](#remove-a-member-from-a-group-or-project) +* [Give a group access to a project](#give-a-group-access-to-a-project) + +# Group and project members API[](#group-and-project-members-api "Permalink") + +## Valid access levels[](#valid-access-levels "Permalink") + +访问级别在`Gitlab::Access`模块中定义. 当前,这些级别被认可: + +* 无法访问( `0` ) +* 宾客( `10` ) +* 记者( `20` ) +* 显影剂( `30` ) +* 养护者( `40` ) +* 所有者( `50` )-仅对组有效 + +**注意:**由于[存在问题](https://gitlab.com/gitlab-org/gitlab/-/issues/219299) ,个人名称空间中的项目将不会显示所有者( `50` )所有者的权限. + +## List all members of a group or project[](#list-all-members-of-a-group-or-project "Permalink") + +获取可通过身份验证的用户查看的组或项目成员的列表. 仅返回直接成员,而不返回通过祖先组继承的成员. + +此函数使用分页参数`page`和`per_page`来限制用户列表. + +``` +GET /groups/:id/members +GET /projects/:id/members +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `query` | string | no | 查询字符串以搜索成员 | +| `user_ids` | 整数数组 | no | 根据给定的用户 ID 过滤结果 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/members" +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/members" +``` + +响应示例: + +``` +[ { "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 30, "group_saml_identity": null }, { "id": 2, "username": "john_doe", "name": "John Doe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 30, "email": "john@example.com", "group_saml_identity": { "extern_uid":"ABC-1234567890", "provider": "group_saml", "saml_provider_id": 10 } } ] +``` + +## List all members of a group or project including inherited members[](#list-all-members-of-a-group-or-project-including-inherited-members "Permalink") + +获取可通过身份验证的用户查看的组或项目成员的列表,包括通过祖先组继承的成员. 当用户是项目/组和一个或多个祖先组的成员时,仅以项目`access_level` (如果存在)或用户所属项目组中第一个组的用户的`access_level`返回一次祖先链. + +此函数使用分页参数`page`和`per_page`来限制用户列表. + +``` +GET /groups/:id/members/all +GET /projects/:id/members/all +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `query` | string | no | 查询字符串以搜索成员 | +| `user_ids` | 整数数组 | no | 根据给定的用户 ID 过滤结果 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/members/all" +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/members/all" +``` + +响应示例: + +``` +[ { "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 30, "group_saml_identity": null }, { "id": 2, "username": "john_doe", "name": "John Doe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 30 "email": "john@example.com", "group_saml_identity": { "extern_uid":"ABC-1234567890", "provider": "group_saml", "saml_provider_id": 10 } }, { "id": 3, "username": "foo_bar", "name": "Foo bar", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-11-22T14:13:35Z", "access_level": 30, "group_saml_identity": null } ] +``` + +## Get a member of a group or project[](#get-a-member-of-a-group-or-project "Permalink") + +获取组或项目的成员. 仅返回直接成员,而不返回通过祖先组继承的成员. + +``` +GET /groups/:id/members/:user_id +GET /projects/:id/members/:user_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 成员的用户标识 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/members/:user_id" +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/members/:user_id" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "access_level": 30, "expires_at": null, "group_saml_identity": null } +``` + +## Get a member of a group or project, including inherited members[](#get-a-member-of-a-group-or-project-including-inherited-members "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17744) . + +获取组或项目的成员,包括通过祖先组继承的成员. 有关详细信息,请参见相应的[端点以列出所有继承的成员](#list-all-members-of-a-group-or-project-including-inherited-members) . + +``` +GET /groups/:id/members/all/:user_id +GET /projects/:id/members/all/:user_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 成员的用户标识 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/members/all/:user_id" +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/members/all/:user_id" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "access_level": 30, "expires_at": null, "group_saml_identity": null } +``` + +## Add a member to a group or project[](#add-a-member-to-a-group-or-project "Permalink") + +将成员添加到组或项目. + +``` +POST /groups/:id/members +POST /projects/:id/members +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 新成员的用户标识 | +| `access_level` | integer | yes | 有效的访问级别 | +| `expires_at` | string | no | 日期格式为 YEAR-MONTH-DAY 的日期字符串 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --data "user_id=1&access_level=30" "https://gitlab.example.com/api/v4/groups/:id/members" +curl --request POST --header "PRIVATE-TOKEN: " --data "user_id=1&access_level=30" "https://gitlab.example.com/api/v4/projects/:id/members" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 30, "group_saml_identity": null } +``` + +## Edit a member of a group or project[](#edit-a-member-of-a-group-or-project "Permalink") + +更新组或项目的成员. + +``` +PUT /groups/:id/members/:user_id +PUT /projects/:id/members/:user_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 成员的用户标识 | +| `access_level` | integer | yes | 有效的访问级别 | +| `expires_at` | string | no | 日期格式为 YEAR-MONTH-DAY 的日期字符串 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/members/:user_id?access_level=40" +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/members/:user_id?access_level=40" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 40, "group_saml_identity": null } +``` + +### Set override flag for a member of a group[](#set-override-flag-for-a-member-of-a-group "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4875) . + +默认情况下,LDAP 组成员的访问级别设置为 LDAP 通过组同步指定的值. 您可以通过调用此端点来允许访问级别替代. + +``` +POST /groups/:id/members/:user_id/override +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 成员的用户标识 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/override" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 40, "override": true } +``` + +### Remove override for a member of a group[](#remove-override-for-a-member-of-a-group "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4875) . + +将替代标志设置为 false,并允许 LDAP 组同步将访问级别重置为 LDAP 指定的值. + +``` +DELETE /groups/:id/members/:user_id/override +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 成员的用户标识 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/override" +``` + +响应示例: + +``` +{ "id": 1, "username": "raymond_smith", "name": "Raymond Smith", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 40, "override": false } +``` + +## Remove a member from a group or project[](#remove-a-member-from-a-group-or-project "Permalink") + +从组或项目中删除用户. + +``` +DELETE /groups/:id/members/:user_id +DELETE /projects/:id/members/:user_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目或组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `user_id` | integer | yes | 成员的用户标识 | +| `unassign_issuables` | boolean | false | 标志,指示是否应从给定的组或项目内取消分配任何问题或合并请求的已删除成员 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/members/:user_id" +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/members/:user_id" +``` + +## Give a group access to a project[](#give-a-group-access-to-a-project "Permalink") + +See [share project with group](projects.html#share-project-with-group) \ No newline at end of file diff --git a/docs/336.md b/docs/336.md new file mode 100644 index 0000000000000000000000000000000000000000..e36243f8c1014856aa12ffcd14c4802364b3596b --- /dev/null +++ b/docs/336.md @@ -0,0 +1,430 @@ +# Merge request approvals API + +> 原文:[https://docs.gitlab.com/ee/api/merge_request_approvals.html](https://docs.gitlab.com/ee/api/merge_request_approvals.html) + +* [Project-level MR approvals](#project-level-mr-approvals) + * [Get Configuration](#get-configuration) + * [Change configuration](#change-configuration) + * [Get project-level rules](#get-project-level-rules) + * [Create project-level rule](#create-project-level-rule) + * [Update project-level rule](#update-project-level-rule) + * [Delete project-level rule](#delete-project-level-rule) + * [Change allowed approvers](#change-allowed-approvers) +* [Merge Request-level MR approvals](#merge-request-level-mr-approvals) + * [Get Configuration](#get-configuration-1) + * [Change approval configuration](#change-approval-configuration) + * [Change allowed approvers for Merge Request](#change-allowed-approvers-for-merge-request) + * [Get the approval state of merge requests](#get-the-approval-state-of-merge-requests) + * [Get merge request level rules](#get-merge-request-level-rules) + * [Create merge request level rule](#create-merge-request-level-rule) + * [Update merge request level rule](#update-merge-request-level-rule) + * [Delete merge request level rule](#delete-merge-request-level-rule) +* [Approve Merge Request](#approve-merge-request) +* [Unapprove Merge Request](#unapprove-merge-request) + +# Merge request approvals API[](#merge-request-approvals-api-starter "Permalink") + +配置项目中所有合并请求(MR)的批准. 必须对所有端点进行身份验证. + +## Project-level MR approvals[](#project-level-mr-approvals "Permalink") + +### Get Configuration[](#get-configuration "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. + +您可以使用以下端点请求有关项目批准配置的信息: + +``` +GET /projects/:id/approvals +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | + +``` +{ "approvals_before_merge": 2, "reset_approvals_on_push": true, "disable_overriding_approvers_per_merge_request": false, "merge_requests_author_approval": true, "merge_requests_disable_committers_approval": false, "require_password_to_approve": true } +``` + +### Change configuration[](#change-configuration "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. + +如果允许,则可以使用以下端点更改批准配置: + +``` +POST /projects/:id/approvals +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `approvals_before_merge` | integer | no | MR 可以合并之前需要多少批准. 在 12.0 中已弃用,以支持批准规则 API. | +| `reset_approvals_on_push` | boolean | no | 重置批准以进行新的推送 | +| `disable_overriding_approvers_per_merge_request` | boolean | no | 允许/禁止每个 MR 的替代批准者 | +| `merge_requests_author_approval` | boolean | no | 允许/禁止作者自行批准合并请求; `true`表示作者可以自行批准 | +| `merge_requests_disable_committers_approval` | boolean | no | 允许/禁止提交者自我批准合并请求 | +| `require_password_to_approve` | boolean | no | 在添加批准之前,需要批准者输入密码才能进行身份验证 | + +``` +{ "approvals_before_merge": 2, "reset_approvals_on_push": true, "disable_overriding_approvers_per_merge_request": false, "merge_requests_author_approval": false, "merge_requests_disable_committers_approval": false, "require_password_to_approve": true } +``` + +### Get project-level rules[](#get-project-level-rules "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) . +* [GitLab Premium](https://about.gitlab.com/pricing/) 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/460)了`protected_branches`属性. + +您可以使用以下端点请求有关项目批准规则的信息: + +``` +GET /projects/:id/approval_rules +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | + +``` +[ { "id": 1, "name": "security", "rule_type": "regular", "eligible_approvers": [ { "id": 5, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" }, { "id": 50, "name": "Group Member 1", "username": "group_member_1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/group_member_1" } ], "approvals_required": 3, "users": [ { "id": 5, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [ { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } ], "protected_branches": [ { "id": 1, "name": "master", "push_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "merge_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "unprotect_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } ], "contains_hidden_groups": false } ] +``` + +### Create project-level rule[](#create-project-level-rule "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点创建项目批准规则: + +``` +POST /projects/:id/approval_rules +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `name` | string | yes | 批准规则的名称 | +| `approvals_required` | integer | yes | 此规则所需的批准数量 | +| `user_ids` | Array | no | 批准者的用户 ID | +| `group_ids` | Array | no | 小组的 ID 为批准者 | +| `protected_branch_ids` | Array | no | 受保护分支的 ID 范围 | + +``` +{ "id": 1, "name": "security", "rule_type": "regular", "eligible_approvers": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" }, { "id": 50, "name": "Group Member 1", "username": "group_member_1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/group_member_1" } ], "approvals_required": 1, "users": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [ { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } ], "protected_branches": [ { "id": 1, "name": "master", "push_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "merge_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "unprotect_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } ], "contains_hidden_groups": false } +``` + +### Update project-level rule[](#update-project-level-rule "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点更新项目批准规则: + +``` +PUT /projects/:id/approval_rules/:approval_rule_id +``` + +**重要提示:**不在`users` / `groups`参数中的批准者和组将被**删除** + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `approval_rule_id` | integer | yes | 批准规则的 ID | +| `name` | string | yes | 批准规则的名称 | +| `approvals_required` | integer | yes | 此规则所需的批准数量 | +| `user_ids` | Array | no | The ids of users as approvers | +| `group_ids` | Array | no | 小组的 ID 为批准者 | +| `protected_branch_ids` | Array | no | 受保护分支的 ID 范围 | + +``` +{ "id": 1, "name": "security", "rule_type": "regular", "eligible_approvers": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" }, { "id": 50, "name": "Group Member 1", "username": "group_member_1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/group_member_1" } ], "approvals_required": 1, "users": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [ { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } ], "protected_branches": [ { "id": 1, "name": "master", "push_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "merge_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "unprotect_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } ], "contains_hidden_groups": false } +``` + +### Delete project-level rule[](#delete-project-level-rule "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点删除项目批准规则: + +``` +DELETE /projects/:id/approval_rules/:approval_rule_id +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `approval_rule_id` | integer | yes | 批准规则的 ID | + +### Change allowed approvers[](#change-allowed-approvers "Permalink") + +**注意:**此 API 端点已被弃用. 请改用批准规则 API. 在[GitLab Starter](https://about.gitlab.com/pricing/) 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/183) . + +如果允许,则可以使用以下端点更改批准者和批准者组: + +``` +PUT /projects/:id/approvers +``` + +**重要提示:**不在请求中的批准者和组将被**删除** + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `approver_ids` | Array | yes | 可以批准 MR 的用户 ID 数组 | +| `approver_group_ids` | Array | yes | 一组可以批准 MR 的组 ID | + +``` +{ "approvers": [ { "user": { "id": 5, "name": "John Doe6", "username": "user5", "state":"active","avatar_url":"https://www.gravatar.com/avatar/4aea8cf834ed91844a2da4ff7ae6b491?s=80\u0026d=identicon","web_url":"http://localhost/user5" } } ], "approver_groups": [ { "group": { "id": 1, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } } ], "approvals_before_merge": 2, "reset_approvals_on_push": true, "disable_overriding_approvers_per_merge_request": false, "merge_requests_author_approval": true, "merge_requests_disable_committers_approval": false, "require_password_to_approve": true } +``` + +## Merge Request-level MR approvals[](#merge-request-level-mr-approvals "Permalink") + +配置特定合并请求的批准. 必须对所有端点进行身份验证. + +### Get Configuration[](#get-configuration-1 "Permalink") + +在[GitLab Starter](https://about.gitlab.com/pricing/) 8.9 中引入. + +您可以使用以下端点来请求有关合并请求的批准状态的信息: + +``` +GET /projects/:id/merge_requests/:merge_request_iid/approvals +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | + +``` +{ "id": 5, "iid": 5, "project_id": 1, "title": "Approvals API", "description": "Test", "state": "opened", "created_at": "2016-06-08T00:19:52.638Z", "updated_at": "2016-06-08T21:20:42.470Z", "merge_status": "cannot_be_merged", "approvals_required": 2, "approvals_left": 1, "approved_by": [ { "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url": "http://localhost:3000/root" } } ], } +``` + +### Change approval configuration[](#change-approval-configuration "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. + +如果你被允许,你可以改变`approvals_required`使用以下端点: + +``` +POST /projects/:id/merge_requests/:merge_request_iid/approvals +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | +| `approvals_required` | integer | yes | 可以合并 MR 之前需要获得批准. 在 12.0 中已弃用,以支持批准规则 API. | + +``` +{ "id": 5, "iid": 5, "project_id": 1, "title": "Approvals API", "description": "Test", "state": "opened", "created_at": "2016-06-08T00:19:52.638Z", "updated_at": "2016-06-08T21:20:42.470Z", "merge_status": "cannot_be_merged", "approvals_required": 2, "approvals_left": 2, "approved_by": [] } +``` + +### Change allowed approvers for Merge Request[](#change-allowed-approvers-for-merge-request "Permalink") + +**注意:**此 API 端点已被弃用. 请改用批准规则 API. 在[GitLab Starter](https://about.gitlab.com/pricing/) 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/183) . + +如果允许,则可以使用以下端点更改批准者和批准者组: + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/approvers +``` + +**重要提示:**不在请求中的批准者和组将被**删除** + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | +| `approver_ids` | Array | yes | 可以批准 MR 的用户 ID 数组 | +| `approver_group_ids` | Array | yes | 一组可以批准 MR 的组 ID | + +``` +{ "id": 5, "iid": 5, "project_id": 1, "title": "Approvals API", "description": "Test", "state": "opened", "created_at": "2016-06-08T00:19:52.638Z", "updated_at": "2016-06-08T21:20:42.470Z", "merge_status": "cannot_be_merged", "approvals_required": 2, "approvals_left": 2, "approved_by": [], "approvers": [ { "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url": "http://localhost:3000/root" } } ], "approver_groups": [ { "group": { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } } ] } +``` + +### Get the approval state of merge requests[](#get-the-approval-state-of-merge-requests "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13712) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点来请求有关合并请求的批准状态的信息: + +``` +GET /projects/:id/merge_requests/:merge_request_iid/approval_state +``` + +如果为合并请求创建了合并请求级别规则,则`approval_rules_overwritten`将为`true` . 如果不存在,则为`false` . + +这包括有关已经批准的用户的更多信息( `approved_by` ),以及规则是否已经批准的( `approved` ). + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | + +``` +{ "approval_rules_overwritten": true, "rules": [ { "id": 1, "name": "Ruby", "rule_type": "regular", "eligible_approvers": [ { "id": 4, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "approvals_required": 2, "users": [ { "id": 4, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [], "contains_hidden_groups": false, "approved_by": [ { "id": 4, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "source_rule": null, "approved": true, "overridden": false } ] } +``` + +### Get merge request level rules[](#get-merge-request-level-rules "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13712) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点来请求有关合并请求的批准规则的信息: + +``` +GET /projects/:id/merge_requests/:merge_request_iid/approval_rules +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | + +``` +[ { "id": 1, "name": "security", "rule_type": "regular", "eligible_approvers": [ { "id": 5, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" }, { "id": 50, "name": "Group Member 1", "username": "group_member_1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/group_member_1" } ], "approvals_required": 3, "source_rule": null, "users": [ { "id": 5, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [ { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } ], "contains_hidden_groups": false, "overridden": false } ] +``` + +### Create merge request level rule[](#create-merge-request-level-rule "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点创建合并请求批准规则: + +``` +POST /projects/:id/merge_requests/:merge_request_iid/approval_rules +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | +| `name` | string | yes | 批准规则的名称 | +| `approvals_required` | integer | yes | 此规则所需的批准数量 | +| `approval_project_rule_id` | integer | no | 项目级批准规则的 ID | +| `user_ids` | Array | no | 批准者的用户 ID | +| `group_ids` | Array | no | 小组的 ID 为批准者 | + +**重要提示:**当`approval_project_rule_id`被设置, `name` , `users`和`groups`项目级的规则将被复制. 该`approvals_required`指定将被使用. + +``` +{ "id": 1, "name": "security", "rule_type": "regular", "eligible_approvers": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" }, { "id": 50, "name": "Group Member 1", "username": "group_member_1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/group_member_1" } ], "approvals_required": 1, "source_rule": null, "users": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [ { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } ], "contains_hidden_groups": false, "overridden": false } +``` + +### Update merge request level rule[](#update-merge-request-level-rule "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点更新合并请求批准规则: + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/approval_rules/:approval_rule_id +``` + +**重要提示:**不在`users` / `groups`参数中的批准者和组将被**删除** + +**重要提示:**不允许更新`report_approver`或`code_owner`规则. 这些是系统生成的规则. + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 ID | +| `approval_rule_id` | integer | yes | 批准规则的 ID | +| `name` | string | yes | 批准规则的名称 | +| `approvals_required` | integer | yes | 此规则所需的批准数量 | +| `user_ids` | Array | no | 批准者的用户 ID | +| `group_ids` | Array | no | 小组的 ID 为批准者 | + +``` +{ "id": 1, "name": "security", "rule_type": "regular", "eligible_approvers": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" }, { "id": 50, "name": "Group Member 1", "username": "group_member_1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/group_member_1" } ], "approvals_required": 1, "source_rule": null, "users": [ { "id": 2, "name": "John Doe", "username": "jdoe", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon", "web_url": "http://localhost/jdoe" } ], "groups": [ { "id": 5, "name": "group1", "path": "group1", "description": "", "visibility": "public", "lfs_enabled": false, "avatar_url": null, "web_url": "http://localhost/groups/group1", "request_access_enabled": false, "full_name": "group1", "full_path": "group1", "parent_id": null, "ldap_cn": null, "ldap_access": null } ], "contains_hidden_groups": false, "overridden": false } +``` + +### Delete merge request level rule[](#delete-merge-request-level-rule "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +您可以使用以下端点删除合并请求批准规则: + +``` +DELETE /projects/:id/merge_requests/:merge_request_iid/approval_rules/:approval_rule_id +``` + +**重要提示:**不允许删除`report_approver`或`code_owner`规则. 这些是系统生成的规则. + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 ID | +| `approval_rule_id` | integer | yes | 批准规则的 ID | + +## Approve Merge Request[](#approve-merge-request "Permalink") + +在[GitLab Starter](https://about.gitlab.com/pricing/) 8.9 中引入. + +如果允许,则可以使用以下端点批准合并请求: + +``` +POST /projects/:id/merge_requests/:merge_request_iid/approve +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | +| `sha` | string | no | MR 的头 | +| `approval_password` | string | no | 当前用户的密码. 如果在项目设置中启用了" [**需要用户密码批准",**](../user/project/merge_requests/merge_request_approvals.html#require-authentication-when-approving-a-merge-request)则为必需. | + +`sha`参数的工作方式与[接受合并请求](merge_requests.html#accept-mr)时的工作方式相同:如果传递了它,则它必须与合并请求的当前 HEAD 匹配才能添加批准. 如果不匹配,则响应代码将为`409` . + +``` +{ "id": 5, "iid": 5, "project_id": 1, "title": "Approvals API", "description": "Test", "state": "opened", "created_at": "2016-06-08T00:19:52.638Z", "updated_at": "2016-06-09T21:32:14.105Z", "merge_status": "can_be_merged", "approvals_required": 2, "approvals_left": 0, "approved_by": [ { "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url": "http://localhost:3000/root" } }, { "user": { "name": "Nico Cartwright", "username": "ryley", "id": 2, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/cf7ad14b34162a76d593e3affca2adca?s=80\u0026d=identicon", "web_url": "http://localhost:3000/ryley" } } ], } +``` + +## Unapprove Merge Request[](#unapprove-merge-request "Permalink") + +在[GitLab Starter](https://about.gitlab.com/pricing/) 9.0 中引入. + +如果您确实批准了合并请求,则可以使用以下端点取消批准它: + +``` +POST /projects/:id/merge_requests/:merge_request_iid/unapprove +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID | +| `merge_request_iid` | integer | yes | MR 的 IID | \ No newline at end of file diff --git a/docs/337.md b/docs/337.md new file mode 100644 index 0000000000000000000000000000000000000000..ad4f7e7e31de6e841c2c882b8b896ae6500de8bf --- /dev/null +++ b/docs/337.md @@ -0,0 +1,854 @@ +# Merge requests API + +> 原文:[https://docs.gitlab.com/ee/api/merge_requests.html](https://docs.gitlab.com/ee/api/merge_requests.html) + +* [List merge requests](#list-merge-requests) +* [List project merge requests](#list-project-merge-requests) +* [List group merge requests](#list-group-merge-requests) +* [Get single MR](#get-single-mr) +* [Get single MR participants](#get-single-mr-participants) +* [Get single MR commits](#get-single-mr-commits) +* [Get single MR changes](#get-single-mr-changes) +* [List MR pipelines](#list-mr-pipelines) +* [Create MR Pipeline](#create-mr-pipeline) +* [Create MR](#create-mr) +* [Update MR](#update-mr) +* [Delete a merge request](#delete-a-merge-request) +* [Accept MR](#accept-mr) +* [Merge to default merge ref path](#merge-to-default-merge-ref-path) +* [Cancel Merge When Pipeline Succeeds](#cancel-merge-when-pipeline-succeeds) +* [Rebase a merge request](#rebase-a-merge-request) +* [Comments on merge requests](#comments-on-merge-requests) +* [List issues that will close on merge](#list-issues-that-will-close-on-merge) +* [Subscribe to a merge request](#subscribe-to-a-merge-request) +* [Unsubscribe from a merge request](#unsubscribe-from-a-merge-request) +* [Create a todo](#create-a-todo) +* [Get MR diff versions](#get-mr-diff-versions) +* [Get a single MR diff version](#get-a-single-mr-diff-version) +* [Set a time estimate for a merge request](#set-a-time-estimate-for-a-merge-request) +* [Reset the time estimate for a merge request](#reset-the-time-estimate-for-a-merge-request) +* [Add spent time for a merge request](#add-spent-time-for-a-merge-request) +* [Reset spent time for a merge request](#reset-spent-time-for-a-merge-request) +* [Get time tracking stats](#get-time-tracking-stats) +* [Approvals](#approvals-starter) + +# Merge requests API[](#merge-requests-api "Permalink") + +合并请求的每个 API 调用都必须经过验证. + +**弃用** > `reference`响应属性有利于已弃用`references` . >推出了[GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354)**注意** > `references.relative`相对于正在请求合并请求的组/项目. 当从其项目中获取合并请求时> `relative`格式将与`short`格式相同,并且在跨组/项目进行请求时, `relative`格式应与`full`格式相同. + +## List merge requests[](#list-merge-requests "Permalink") + +在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) . + +获取所有通过身份验证的用户有权访问的合并请求. 默认情况下,它仅返回当前用户创建的合并请求. 要获取所有合并请求,请使用参数`scope=all` . + +`state`参数可用于仅获取具有给定状态( `opened` , `closed` , `locked`或`merged` )或全部( `all` )的合并请求. 应该注意的是,通过`locked`进行搜索时,由于它是短暂的过渡状态,因此几乎不会返回任何结果. 分页参数`page`和`per_page`可用于限制合并请求的列表. + +``` +GET /merge_requests +GET /merge_requests?state=opened +GET /merge_requests?state=all +GET /merge_requests?milestone=release +GET /merge_requests?labels=bug,reproduced +GET /merge_requests?author_id=5 +GET /merge_requests?author_username=gitlab-bot +GET /merge_requests?my_reaction_emoji=star +GET /merge_requests?scope=assigned_to_me +GET /merge_requests?search=foo&in=title +``` + +Parameters: + +| Attribute | Type | Required | Description |   | +| --- | --- | --- | --- | --- | +| `state` | string | no | 返回所有合并请求,或者仅返回已`opened` , `closed` , `locked`或`merged`请求 |   | +| `order_by` | string | no | 返回由`created_at`或`updated_at`字段排序的请求. 默认为`created_at` |   | +| `sort` | string | no | 返回请求按`asc`或`desc`顺序排序. 默认为`desc` |   | +| `milestone` | string | no | 返回特定里程碑的合并请求. `None`返回没有里程碑的合并请求. `Any`返回将合并具有指定里程碑的请求. |   | +| `view` | string | no | 如果为`simple` ,则返回`iid` ,URL,标题,描述和合并请求的基本状态 |   | +| `labels` | string | no | 返回与逗号分隔的标签列表匹配的合并请求. `None`列出所有没有标签的合并请求. `Any`列出所有具有至少一个标签的合并请求. `No+Label` (不推荐使用)列出所有没有标签的合并请求. 预定义名称不区分大小写. |   | +| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) |   | +| `with_merge_status_recheck` | boolean | no | 如果为`true` ,则此投影请求(但不保证)异步地重新计算`merge_status`字段. 默认值为`false` . 在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890)引入 |   | +| `created_after` | datetime | no | 返回在给定时间或之后创建的合并请求 |   | +| `created_before` | datetime | no | 返回在给定时间或之前创建的合并请求 |   | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的合并请求 |   | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的合并请求 |   | +| `scope` | string | no | 对于给定的范围内返回的合并请求: `created_by_me` , `assigned_to_me`或`all` . 默认为`created_by_me` +对于 11.0 之前的版本,请改用现在不建议使用`created-by-me`范围或`created-by-me` `assigned-to-me`范围. |   | +| `author_id` | integer | no | 返回由给定用户`id`创建的合并请求. 与`author_username` . 与`scope=all`或`scope=assigned_to_me` |   | +| `author_username` | string | no | 返回由给定`username`创建的合并请求. 与`author_id` . *(在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `assignee_id` | integer | no | 返回分配给给定用户`id`合并请求. `None`将返回未分配的合并请求. `Any`退货将请求与受让人合并. |   | +| `approver_ids` | 整数数组 | no | 返回将所有具有给定`id`的用户指定为单独批准者的合并请求. `None`返回没有批准者的合并请求. `Any`退货将合并请求与批准人. |   | +| `approved_by_ids` | 整数数组 | no | 返回已被所有具有给定`id`的用户(最大:5)批准的合并请求. `None`返回没有批准的合并请求. `Any`退货将请求与批准合并. |   | +| `my_reaction_emoji` | string | no | 返回合并请求,该合并请求由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. *(在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) )* |   | +| `source_branch` | string | no | 返回具有给定源分支的合并请求 |   | +| `target_branch` | string | no | 返回具有给定目标分支的合并请求 |   | +| `search` | string | no | 根据`title`和`description`搜索合并请求 |   | +| `in` | string | no | 修改`search`属性的范围. `title` , `description`或以逗号将它们连接在一起的字符串. 默认为`title,description` |   | +| `wip` | string | no | 过滤合并请求对他们的`wip`状态. `yes` , *仅*返回 WIP 合并请求, `no` ,返回*非* WIP 合并请求 |   | +| `not` | Hash | no | 返回与提供的参数不匹配的合并请求. 接受: `labels` , `milestone` , `author_id` , `author_username` , `assignee_id` , `assignee_username` , `my_reaction_emoji` |   | + +**注意:** [从 GitLab 13.0 开始](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) ,列出合并请求可能不会主动更新`merge_status`字段(这也会影响`has_conflicts`字段),因为这可能是一项昂贵的操作. 如果您对此端点的这些字段的值感兴趣,请在查询`with_merge_status_recheck`参数设置为`true` .**注意:** [从 GitLab 12.8 开始,](https://gitlab.com/gitlab-org/gitlab/-/issues/29984)当对此端点发出请求时,将异步检查每个合并请求的可合并性( `merge_status` ). 轮询此 API 端点以获取更新状态. 这会影响`has_conflicts`属性,因为它取决于`merge_status` . 除非`merge_status`为`cannot_be_merged`否则它将返回`false` . + +``` +[ { "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "my-group/my-project!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "task_completion_status":{ "count":0, "completed_count":0 } } ] +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +[ { "id": 1, "title": "test1", "approvals_before_merge": null ... } ] +``` + +## List project merge requests[](#list-project-merge-requests "Permalink") + +获取此项目的所有合并请求. `state`参数可用于仅获取具有给定状态( `opened` , `closed` , `locked`或`merged` )或全部( `all` )的合并请求. 分页参数`page`和`per_page`可用于限制合并请求的列表. + +``` +GET /projects/:id/merge_requests +GET /projects/:id/merge_requests?state=opened +GET /projects/:id/merge_requests?state=all +GET /projects/:id/merge_requests?iids[]=42&iids[]=43 +GET /projects/:id/merge_requests?milestone=release +GET /projects/:id/merge_requests?labels=bug,reproduced +GET /projects/:id/merge_requests?my_reaction_emoji=star +``` + +`project_id`代表 MR 所在项目的 ID. `project_id`将始终等于`target_project_id` . + +如果来自同一项目的合并请求,则`source_project_id` , `target_project_id`和`project_id`将相同. 对于来自派生的合并请求, `target_project_id`和`project_id`将相同,并且`source_project_id`将是派生项目的 ID. + +Parameters: + +| Attribute | Type | Required | Description |   | +| --- | --- | --- | --- | --- | +| `id` | integer | yes | 项目 ID |   | +| `iids[]` | 整数数组 | no | 返回具有给定`iid`的请求 |   | +| `state` | string | no | 返回所有合并请求,或者仅返回已`opened` , `closed` , `locked`或`merged`请求 |   | +| `order_by` | string | no | 返回由`created_at`或`updated_at`字段排序的请求. 默认为`created_at` |   | +| `sort` | string | no | 返回请求按`asc`或`desc`顺序排序. 默认为`desc` |   | +| `milestone` | string | no | 返回特定里程碑的合并请求. `None`返回没有里程碑的合并请求. `Any`返回将合并具有指定里程碑的请求. |   | +| `view` | string | no | 如果为`simple` ,则返回`iid` ,URL,标题,描述和合并请求的基本状态 |   | +| `labels` | string | no | 返回与逗号分隔的标签列表匹配的合并请求. `None`列出所有没有标签的合并请求. `Any`列出所有具有至少一个标签的合并请求. `No+Label` (不推荐使用)列出所有没有标签的合并请求. 预定义名称不区分大小写. |   | +| `with_labels_details` | boolean | no | 如果为`true` ,则响应将为标签字段中的每个标签返回更多详细信息`:name` , `:color` , `:description` , `:description_html` , `:text_color` . 默认值为`false` . 在[GitLab 12.7 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)引入 |   | +| `with_merge_status_recheck` | boolean | no | 如果为`true` ,则此投影请求(但不保证)异步地重新计算`merge_status`字段. 默认值为`false` . 在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890)引入 |   | +| `created_after` | datetime | no | 返回在给定时间或之后创建的合并请求 |   | +| `created_before` | datetime | no | 返回在给定时间或之前创建的合并请求 |   | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的合并请求 |   | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的合并请求 |   | +| `scope` | string | no | 对于给定的范围内返回的合并请求: `created_by_me` , `assigned_to_me`或`all` . +对于 11.0 之前的版本,请改用现在不建议使用`created-by-me`范围或`created-by-me` `assigned-to-me`范围. +*(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) .在 GitLab 11.0 中[更改为 snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) )* |   | +| `author_id` | integer | no | 返回由给定用户`id`创建的合并请求. 与`author_username` . *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `author_username` | string | no | 返回由给定`username`创建的合并请求. 与`author_id` . *(在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `assignee_id` | integer | no | 返回分配给给定用户`id`合并请求. `None`将返回未分配的合并请求. `Any`退货将请求与受让人合并. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `approver_ids` | 整数数组 | no | 返回将所有具有给定`id`的用户指定为单独批准者的合并请求. `None`返回没有批准者的合并请求. `Any`退货将合并请求与批准人. |   | +| `approved_by_ids` | 整数数组 | no | 返回已被所有具有给定`id`的用户(最大:5)批准的合并请求. `None`返回没有批准的合并请求. `Any`退货将请求与批准合并. |   | +| `my_reaction_emoji` | string | no | 返回合并请求,该合并请求由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. *(在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) )* |   | +| `source_branch` | string | no | 返回具有给定源分支的合并请求 |   | +| `target_branch` | string | no | 返回具有给定目标分支的合并请求 |   | +| `search` | string | no | 根据`title`和`description`搜索合并请求 |   | +| `wip` | string | no | 过滤合并请求对他们的`wip`状态. `yes` , *仅*返回 WIP 合并请求, `no` ,返回*非* WIP 合并请求 |   | + +``` +[ { "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "task_completion_status":{ "count":0, "completed_count":0 }, "has_conflicts": false, "blocking_discussions_resolved": true } ] +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +[ { "id": 1, "title": "test1", "approvals_before_merge": null ... } ] +``` + +## List group merge requests[](#list-group-merge-requests "Permalink") + +获取该组及其子组的所有合并请求. `state`参数可用于仅获取具有给定状态( `opened` , `closed` , `locked`或`merged` )或全部( `all` )的合并请求. 分页参数`page`和`per_page`可用于限制合并请求的列表. + +``` +GET /groups/:id/merge_requests +GET /groups/:id/merge_requests?state=opened +GET /groups/:id/merge_requests?state=all +GET /groups/:id/merge_requests?milestone=release +GET /groups/:id/merge_requests?labels=bug,reproduced +GET /groups/:id/merge_requests?my_reaction_emoji=star +``` + +`group_id`代表包含 MR 所在项目的组的 ID. + +Parameters: + +| Attribute | Type | Required | Description |   | +| --- | --- | --- | --- | --- | +| `id` | integer | yes | 组的 ID |   | +| `state` | string | no | 返回所有合并请求,或者仅返回已`opened` , `closed` , `locked`或`merged`请求 |   | +| `order_by` | string | no | 返回由`created_at`或`updated_at`字段排序的合并请求. 默认为`created_at` |   | +| `sort` | string | no | 返回以`asc`或`desc`顺序排序的合并请求. 默认为`desc` |   | +| `milestone` | string | no | 返回特定里程碑的合并请求. `None`返回没有里程碑的合并请求. `Any`返回将合并具有指定里程碑的请求. |   | +| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request |   | +| `labels` | string | no | 返回与逗号分隔的标签列表匹配的合并请求. `None`列出所有没有标签的合并请求. `Any`列出所有具有至少一个标签的合并请求. `No+Label` (不推荐使用)列出所有没有标签的合并请求. 预定义名称不区分大小写. |   | +| `with_labels_details` | boolean | no | 如果为`true` ,则响应将为标签字段中的每个标签返回更多详细信息`:name` , `:color` , `:description` , `:description_html` , `:text_color` . 默认值为`false` . 在[GitLab 12.7 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)引入 |   | +| `with_merge_status_recheck` | boolean | no | 如果为`true` ,则此投影请求(但不保证)异步地重新计算`merge_status`字段. 默认值为`false` . 在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890)引入 |   | +| `created_after` | datetime | no | 返回在给定时间或之后创建的合并请求 |   | +| `created_before` | datetime | no | 返回在给定时间或之前创建的合并请求 |   | +| `updated_after` | datetime | no | 返回在给定时间或之后更新的合并请求 |   | +| `updated_before` | datetime | no | 返回在给定时间或之前更新的合并请求 |   | +| `scope` | string | no | 对于给定的范围内返回的合并请求: `created_by_me` , `assigned_to_me`或`all` . + |   | +| `author_id` | integer | no | 返回由给定用户`id`创建的合并请求. 与`author_username` . *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `author_username` | string | no | 返回由给定`username`创建的合并请求. 与`author_id` . *(在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `assignee_id` | integer | no | 返回分配给给定用户`id`合并请求. `None`将返回未分配的合并请求. `Any`退货将请求与受让人合并. *(在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) )* |   | +| `approver_ids` | 整数数组 | no | 返回将所有具有给定`id`的用户指定为单独批准者的合并请求. `None`返回没有批准者的合并请求. `Any`退货将合并请求与批准人. |   | +| `approved_by_ids` | 整数数组 | no | 返回已被所有具有给定`id`的用户(最大:5)批准的合并请求. `None`返回没有批准的合并请求. `Any`退货将请求与批准合并. |   | +| `my_reaction_emoji` | string | no | 返回合并请求,该合并请求由已验证的用户通过给定的`emoji`响应. `None`返回没有响应的问题. 至少有一个反应, `Any`回报问题. *(在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) )* |   | +| `source_branch` | string | no | 返回具有给定源分支的合并请求 |   | +| `target_branch` | string | no | 返回具有给定目标分支的合并请求 |   | +| `search` | string | no | 根据`title`和`description`搜索合并请求 |   | +| `non_archived` | boolean | no | 仅从非归档项目返回合并请求. 默认为 true. *(在[GitLab 12.8 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23809)引入)* |   | + +``` +[ { "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-10-22", "start_date": "2018-09-08", "web_url": "gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "my-project!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "task_completion_status":{ "count":0, "completed_count":0 }, "has_conflicts": false, "blocking_discussions_resolved": true } ] +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +[ { "id": 1, "title": "test1", "approvals_before_merge": null ... } ] +``` + +## Get single MR[](#get-single-mr "Permalink") + +显示有关单个合并请求的信息. + +**注意** :响应中的`changes_count`值是一个字符串,而不是整数. 这是因为当 MR 有太多要显示和存储的更改时,其上限为 1,000\. 在这种情况下,API 将为更改计数返回字符串`"1000+"` . + +``` +GET /projects/:id/merge_requests/:merge_request_iid +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需)-合并请求的内部 ID +* `render_html` (optional) - If `true` response includes rendered HTML for title and description +* `include_diverged_commits_count` (可选)-如果为`true`包括目标分支后面的提交 +* `include_rebase_in_progress` (可选)-如果为`true`包括是否正在进行 rebase 操作 + +**注意:** [从 GitLab 12.8 开始,](https://gitlab.com/gitlab-org/gitlab/-/issues/29984)当对此端点发出请求时,将异步检查合并请求的可合并性( `merge_status` ). 轮询此 API 端点以获取更新状态. 这会影响`has_conflicts`属性,因为它取决于`merge_status` . 除非`merge_status`为`cannot_be_merged`否则它将返回`false` . + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "user" : { "can_merge" : false }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "merge_error": null, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "rebase_in_progress": false, "first_contribution": false, "task_completion_status":{ "count":0, "completed_count":0 }, "has_conflicts": false, "blocking_discussions_resolved": true } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Get single MR participants[](#get-single-mr-participants "Permalink") + +获取合并请求参与者的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/participants +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需)-合并请求的内部 ID + +``` +[ { "id": 1, "name": "John Doe1", "username": "user1", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://localhost/user1" }, { "id": 2, "name": "John Doe2", "username": "user2", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/10fc7f102be8de7657fb4d80898bbfe3?s=80&d=identicon", "web_url": "http://localhost/user2" } ] +``` + +## Get single MR commits[](#get-single-mr-commits "Permalink") + +获取合并请求提交的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/commits +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需)-合并请求的内部 ID + +``` +[ { "id": "ed899a2f4b50b4370feeea94676502b42383c746", "short_id": "ed899a2f4b5", "title": "Replace sanitize with escape once", "author_name": "Example User", "author_email": "user@example.com", "created_at": "2012-09-20T11:50:22+03:00", "message": "Replace sanitize with escape once" }, { "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", "short_id": "6104942438c", "title": "Sanitize for network graph", "author_name": "Example User", "author_email": "user@example.com", "created_at": "2012-09-20T09:06:12+03:00", "message": "Sanitize for network graph" } ] +``` + +## Get single MR changes[](#get-single-mr-changes "Permalink") + +显示有关合并请求的信息,包括其文件和更改. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/changes +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需)-合并请求的内部 ID + +``` +{ "id": 21, "iid": 1, "project_id": 4, "title": "Blanditiis beatae suscipit hic assumenda et molestias nisi asperiores repellat et.", "state": "reopened", "created_at": "2015-02-02T19:49:39.159Z", "updated_at": "2015-02-02T20:08:49.959Z", "target_branch": "secret_token", "source_branch": "version-1-9", "upvotes": 0, "downvotes": 0, "author": { "name": "Chad Hamill", "username": "jarrett", "id": 5, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/b95567800f828948baf5f4160ebb2473?s=40&d=identicon", "web_url" : "https://gitlab.example.com/jarrett" }, "assignee": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40&d=identicon", "web_url" : "https://gitlab.example.com/root" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 4, "target_project_id": 4, "labels": [ ], "description": "Qui voluptatibus placeat ipsa alias quasi. Deleniti rem ut sint. Optio velit qui distinctio.", "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 4, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": null }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "subscribed" : true, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "changes_count": "1", "should_remove_source_branch": true, "force_remove_source_branch": false, "squash": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "discussion_locked": false, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "task_completion_status":{ "count":0, "completed_count":0 }, "changes": [ { "old_path": "VERSION", "new_path": "VERSION", "a_mode": "100644", "b_mode": "100644", "diff": "--- a/VERSION\ +++ b/VERSION\ @@ -1 +1 @@\ -1.9.7\ +1.9.8", "new_file": false, "renamed_file": false, "deleted_file": false } ] } +``` + +## List MR pipelines[](#list-mr-pipelines "Permalink") + +在 GitLab 10.5.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15454) . + +获取合并请求管道的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/pipelines +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需)-合并请求的内部 ID + +``` +[ { "id": 77, "sha": "959e04d7c7a30600c894bd3c0cd0e1ce7f42c11d", "ref": "master", "status": "success" } ] +``` + +## Create MR Pipeline[](#create-mr-pipeline "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31722) . + +[为合并请求](../ci/merge_request_pipelines/index.html)创建一个新[管道](../ci/merge_request_pipelines/index.html) . 通过这个端点创建的管道将无法运行常规的分支/标签的管道,它需要`.gitlab-ci.yml`与配置`only: [merge_requests]`创造就业机会. + +新管道可以是: + +* 分离的合并请求管道. +* A [pipeline for merged results](../ci/merge_request_pipelines/pipelines_for_merged_results/index.html) if the [project setting is enabled](../ci/merge_request_pipelines/pipelines_for_merged_results/index.html#enable-pipelines-for-merged-results). + +``` +POST /projects/:id/merge_requests/:merge_request_iid/pipelines +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需)-合并请求的内部 ID + +``` +{ "id": 2, "sha": "b83d6e391c22777fca1ed3012fce84f633d7fed0", "ref": "refs/merge-requests/1/head", "status": "pending", "web_url": "http://localhost/user1/project1/pipelines/2", "before_sha": "0000000000000000000000000000000000000000", "tag": false, "yaml_errors": null, "user": { "id": 1, "name": "John Doe1", "username": "user1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://example.com" }, "created_at": "2019-09-04T19:20:18.267Z", "updated_at": "2019-09-04T19:20:18.459Z", "started_at": null, "finished_at": null, "committed_at": null, "duration": null, "coverage": null, "detailed_status": { "icon": "status_pending", "text": "pending", "label": "pending", "group": "pending", "tooltip": "pending", "has_details": false, "details_path": "/user1/project1/pipelines/2", "illustration": null, "favicon": "/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png" } } +``` + +## Create MR[](#create-mr "Permalink") + +创建一个新的合并请求. + +``` +POST /projects/:id/merge_requests +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `source_branch` | string | yes | 源分支 | +| `target_branch` | string | yes | 目标分支 | +| `title` | string | yes | 先生的头衔 | +| `assignee_id` | integer | no | 受让人用户 ID | +| `assignee_ids` | 整数数组 | no | 要将 MR 分配给的用户的 ID. 设置为`0`或提供一个空值以取消分配所有受让人. | +| `description` | string | no | MR 的描述. 限制为 1,048,576 个字符. | +| `target_project_id` | integer | no | 目标项目(数字 ID) | +| `labels` | string | no | MR 的标签以逗号分隔的列表 | +| `milestone_id` | integer | no | 里程碑的全局 ID | +| `remove_source_branch` | boolean | no | 指示合并请求是否应在合并时删除源分支的标志 | +| `allow_collaboration` | boolean | no | 允许来自可以合并到目标分支的成员的提交 | +| `allow_maintainer_to_push` | boolean | no | Deprecated, see allow_collaboration | +| `squash` | boolean | no | 合并时将 Squash 提交到单个提交中 | + +如果`approvals_before_merge` 未提供,它将从目标项目继承值. 如果提供了它,则必须满足以下条件才能使其生效: + +1. 目标项目的`approvals_before_merge`必须大于零. 零值将禁用该项目的批准. +2. 所提供的价值`approvals_before_merge`必须比目标项目的更大`approvals_before_merge` . + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "merge_error": null, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Update MR[](#update-mr "Permalink") + +更新现有的合并请求. 您可以更改目标分支,标题,甚至关闭 MR. + +``` +PUT /projects/:id/merge_requests/:merge_request_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 ID | +| `target_branch` | string | no | 目标分支 | +| `title` | string | no | 先生的头衔 | +| `assignee_id` | integer | no | 要将合并请求分配给的用户的 ID. 设置为`0`或提供一个空值以取消分配所有受让人. | +| `assignee_ids` | 整数数组 | no | 要将 MR 分配给的用户的 ID. 设置为`0`或提供一个空值以取消分配所有受让人. | +| `milestone_id` | integer | no | 要将合并请求分配给的里程碑的全局 ID. 设置为`0`或提供一个空值以取消分配里程碑. | +| `labels` | string | no | 合并请求的逗号分隔标签名称. 设置为空字符串以取消分配所有标签. | +| `add_labels` | string | no | 以逗号分隔的标签名称,添加到合并请求中. | +| `remove_labels` | string | no | 逗号分隔的标签名称,可从合并请求中删除. | +| `description` | string | no | MR 的描述. 限制为 1,048,576 个字符. | +| `state_event` | string | no | 新状态(关闭/重新打开) | +| `remove_source_branch` | boolean | no | 指示合并请求是否应在合并时删除源分支的标志 | +| `squash` | boolean | no | 合并时将 Squash 提交到单个提交中 | +| `discussion_locked` | boolean | no | 指示合并请求的讨论是否已锁定的标志. 如果讨论被锁定,则只有项目成员可以添加,编辑或解决评论. | +| `allow_collaboration` | boolean | no | 允许来自可以合并到目标分支的成员的提交 | +| `allow_maintainer_to_push` | boolean | no | 已弃用,请参见 allow_collaboration | + +必须至少包含一个以上非必需的属性. + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "merge_error": null, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Delete a merge request[](#delete-a-merge-request "Permalink") + +仅适用于管理员和项目所有者. 删除相关合并请求. + +``` +DELETE /projects/:id/merge_requests/:merge_request_iid +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/merge_requests/85" +``` + +## Accept MR[](#accept-mr "Permalink") + +使用此 API 合并通过 MR 提交的更改. + +如果合并请求无法被接受(例如:进行中,已关闭,正在等待管道完成或在要求成功时失败)-您将收到`405`和错误消息"不允许使用方法" + +如果存在一些冲突且无法合并-您将收到`406` ,并且错误消息"分支无法合并" + +如果传递了`sha`参数,但与源头的 HEAD 不匹配-您将得到`409`且错误消息" SHA 与源分支的 HEAD 不匹配" + +如果您没有接受此合并请求的权限-您会收到`401` + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/merge +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需) `merge_request_iid`内部 ID +* `merge_commit_message` (optional) - Custom merge commit message +* `squash_commit_message` (可选)-自定义南瓜提交消息 +* `squash` (可选)-如果为`true`则提交将在合并时被压缩为单个提交 +* `should_remove_source_branch` (可选)-如果为`true`删除源分支 +* `merge_when_pipeline_succeeds` (可选)-如果为`true` ,则在管道成功时合并 MR +* `sha` (可选)-如果存在,则此 SHA 必须与源分支的 HEAD 匹配,否则合并将失败 + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "merge_error": null, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Merge to default merge ref path[](#merge-to-default-merge-ref-path "Permalink") + +如果可能,将合并请求源和目标分支之间的更改合并到目标项目存储库的`refs/merge-requests/:iid/merge` ref 中. 如果执行常规合并操作,此引用将具有目标分支将具有的状态. + +这不是常规的合并操作,因为它不会以任何方式更改合并请求目标分支的状态. + +向此 API 提交请求时,此 ref( `refs/merge-requests/:iid/merge` )不一定会被覆盖,尽管它可以确保 ref 具有最新的状态. + +如果合并请求有冲突,为空或已经合并,您将收到一条`400`和一个描述性错误消息. + +如果为`200`它将在响应正文中返回`refs/merge-requests/:iid/merge`的 HEAD 提交. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/merge_ref +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需) `merge_request_iid`内部 ID + +``` +{ "commit_id": "854a3a7a17acbcc0bbbea170986df1eb60435f34" } +``` + +## Cancel Merge When Pipeline Succeeds[](#cancel-merge-when-pipeline-succeeds "Permalink") + +如果您没有接受此合并请求的权限-您会收到`401` + +如果合并请求已被合并或关闭-您将收到`405`和错误消息"不允许使用方法" + +如果在管道成功时未将合并请求设置为要合并,则还会收到`406`错误. + +``` +POST /projects/:id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_succeeds +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必需) `merge_request_iid`内部 ID + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": false, "merge_status": "can_be_merged", "merge_error": null, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Rebase a merge request[](#rebase-a-merge-request "Permalink") + +自动将合并请求的`source_branch`与其`target_branch` . + +如果您无权推送到合并请求的源分支-您将收到`403 Forbidden`响应. + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/rebase +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | +| `skip_ci` | boolean | no | 设置为`true`以跳过创建 CI 管道 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/76/merge_requests/1/rebase" +``` + +这是一个异步请求. 如果请求成功入队,API 将返回`202 Accepted`响应,响应包含: + +``` +{ "rebase_in_progress": true } +``` + +您可以使用`include_rebase_in_progress`参数轮询" [获取单个 MR"](#get-single-mr)端点,以检查异步请求的状态. + +如果正在进行 rebase 操作,则响应将包括以下内容: + +``` +{ "rebase_in_progress": true, "merge_error": null } +``` + +一旦成功完成了变基操作,响应将包括以下内容: + +``` +{ "rebase_in_progress": false, "merge_error": null } +``` + +如果 rebase 操作失败,响应将包括以下内容: + +``` +{ "rebase_in_progress": false, "merge_error": "Rebase failed. Please rebase locally" } +``` + +## Comments on merge requests[](#comments-on-merge-requests "Permalink") + +注释是通过[notes](notes.html)资源完成的. + +## List issues that will close on merge[](#list-issues-that-will-close-on-merge "Permalink") + +通过合并提供的合并请求来获取所有将要解决的问题. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/closes_issues +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/76/merge_requests/1/closes_issues" +``` + +使用 GitLab 问题跟踪器时的示例响应: + +``` +[ { "state" : "opened", "description" : "Ratione dolores corrupti mollitia soluta quia.", "author" : { "state" : "active", "id" : 18, "web_url" : "https://gitlab.example.com/eileen.lowe", "name" : "Alexandra Bashirian", "avatar_url" : null, "username" : "eileen.lowe" }, "milestone" : { "project_id" : 1, "description" : "Ducimus nam enim ex consequatur cumque ratione.", "state" : "closed", "due_date" : null, "iid" : 2, "created_at" : "2016-01-04T15:31:39.996Z", "title" : "v4.0", "id" : 17, "updated_at" : "2016-01-04T15:31:39.996Z" }, "project_id" : 1, "assignee" : { "state" : "active", "id" : 1, "name" : "Administrator", "web_url" : "https://gitlab.example.com/root", "avatar_url" : null, "username" : "root" }, "updated_at" : "2016-01-04T15:31:51.081Z", "id" : 76, "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", "created_at" : "2016-01-04T15:31:51.081Z", "iid" : 6, "labels" : [], "user_notes_count": 1, "changes_count": "1" } ] +``` + +使用外部问题跟踪器(例如 Jira)时的示例响应: + +``` +[ { "id" : "PROJECT-123", "title" : "Title of this issue" } ] +``` + +## Subscribe to a merge request[](#subscribe-to-a-merge-request "Permalink") + +向已认证的用户订阅合并请求以接收通知. 如果用户已经订阅了合并请求,则返回状态码`304` . + +``` +POST /projects/:id/merge_requests/:merge_request_iid/subscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/17/subscribe" +``` + +响应示例: + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Unsubscribe from a merge request[](#unsubscribe-from-a-merge-request "Permalink") + +从合并请求中退订已认证的用户,以不接收来自该合并请求的通知. 如果用户未订阅合并请求,则返回状态码`304` . + +``` +POST /projects/:id/merge_requests/:merge_request_iid/unsubscribe +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/17/unsubscribe" +``` + +响应示例: + +``` +{ "id": 1, "iid": 1, "project_id": 3, "title": "test1", "description": "fixed login page css paddings", "state": "merged", "created_at": "2017-04-29T08:46:00Z", "updated_at": "2017-04-29T08:46:00Z", "target_branch": "master", "source_branch": "test1", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignee": { "id": 1, "name": "Administrator", "username": "admin", "state": "active", "avatar_url": null, "web_url" : "https://gitlab.example.com/admin" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 2, "target_project_id": 3, "labels": [ "Community contribution", "Manage" ], "work_in_progress": false, "milestone": { "id": 5, "iid": 1, "project_id": 3, "title": "v2.0", "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", "state": "closed", "created_at": "2015-02-02T19:49:26.013Z", "updated_at": "2015-02-02T19:49:26.013Z", "due_date": "2018-09-22", "start_date": "2018-08-08", "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" }, "merge_when_pipeline_succeeds": true, "merge_status": "can_be_merged", "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 1, "discussion_locked": null, "should_remove_source_branch": true, "force_remove_source_branch": false, "allow_collaboration": false, "allow_maintainer_to_push": false, "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null }, "squash": false, "subscribed": false, "changes_count": "1", "merged_by": { "id": 87854, "name": "Douwe Maan", "username": "DouweM", "state": "active", "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", "web_url": "https://gitlab.com/DouweM" }, "merged_at": "2018-09-07T11:16:17.520Z", "closed_by": null, "closed_at": null, "latest_build_started_at": "2018-09-07T07:27:38.472Z", "latest_build_finished_at": "2018-09-07T08:07:06.012Z", "first_deployed_to_production_at": null, "pipeline": { "id": 29626725, "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "ref": "patch-28", "status": "success", "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725" }, "diff_refs": { "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00", "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f", "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00" }, "diverged_commits_count": 2, "task_completion_status":{ "count":0, "completed_count":0 } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 1, "title": "test1", "approvals_before_merge": null ... } +``` + +## Create a todo[](#create-a-todo "Permalink") + +在合并请求上为当前用户手动创建待办事项. 如果在该合并请求上已经存在用户的待办事项,则返回状态码`304` . + +``` +POST /projects/:id/merge_requests/:merge_request_iid/todo +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/27/todo" +``` + +响应示例: + +``` +{ "id": 113, "project": { "id": 3, "name": "GitLab CI/CD", "name_with_namespace": "GitLab Org / GitLab CI/CD", "path": "gitlab-ci", "path_with_namespace": "gitlab-org/gitlab-ci" }, "author": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "action_name": "marked", "target_type": "MergeRequest", "target": { "id": 27, "iid": 7, "project_id": 3, "title": "Et voluptas laudantium minus nihil recusandae ut accusamus earum aut non.", "description": "Veniam sunt nihil modi earum cumque illum delectus. Nihil ad quis distinctio quia. Autem eligendi at quibusdam repellendus.", "state": "merged", "created_at": "2016-06-17T07:48:04.330Z", "updated_at": "2016-07-01T11:14:15.537Z", "target_branch": "allow_regex_for_project_skip_ref", "source_branch": "backup", "upvotes": 0, "downvotes": 0, "author": { "name": "Jarret O'Keefe", "username": "francisca", "id": 14, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a7fa515d53450023c83d62986d0658a8?s=80&d=identicon", "web_url": "https://gitlab.example.com/francisca", "discussion_locked": false }, "assignee": { "name": "Dr. Gabrielle Strosin", "username": "barrett.krajcik", "id": 4, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/733005fcd7e6df12d2d8580171ccb966?s=80&d=identicon", "web_url": "https://gitlab.example.com/barrett.krajcik" }, "assignees": [{ "name": "Miss Monserrate Beier", "username": "axel.block", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], "source_project_id": 3, "target_project_id": 3, "labels": [], "work_in_progress": false, "milestone": { "id": 27, "iid": 2, "project_id": 3, "title": "v1.0", "description": "Quis ea accusantium animi hic fuga assumenda.", "state": "active", "created_at": "2016-06-17T07:47:33.840Z", "updated_at": "2016-06-17T07:47:33.840Z", "due_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "unchecked", "subscribed": true, "sha": "8888888888888888888888888888888888888888", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 7, "changes_count": "1", "should_remove_source_branch": true, "force_remove_source_branch": false, "squash": false, "web_url": "http://example.com/my-group/my-project/merge_requests/1", "references": { "short": "!1", "relative": "!1", "full": "my-group/my-project!1" }, }, "target_url": "https://gitlab.example.com/gitlab-org/gitlab-ci/merge_requests/7", "body": "Et voluptas laudantium minus nihil recusandae ut accusamus earum aut non.", "state": "pending", "created_at": "2016-07-01T11:14:15.530Z" } +``` + +## Get MR diff versions[](#get-mr-diff-versions "Permalink") + +获取合并请求差异版本的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/versions +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | String | yes | 项目 ID | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions" +``` + +响应示例: + +``` +[{ "id": 110, "head_commit_sha": "33e2ee8579fda5bc36accc9c6fbd0b4fefda9e30", "base_commit_sha": "eeb57dffe83deb686a60a71c16c32f71046868fd", "start_commit_sha": "eeb57dffe83deb686a60a71c16c32f71046868fd", "created_at": "2016-07-26T14:44:48.926Z", "merge_request_id": 105, "state": "collected", "real_size": "1" }, { "id": 108, "head_commit_sha": "3eed087b29835c48015768f839d76e5ea8f07a24", "base_commit_sha": "eeb57dffe83deb686a60a71c16c32f71046868fd", "start_commit_sha": "eeb57dffe83deb686a60a71c16c32f71046868fd", "created_at": "2016-07-25T14:21:33.028Z", "merge_request_id": 105, "state": "collected", "real_size": "1" }] +``` + +## Get a single MR diff version[](#get-a-single-mr-diff-version "Permalink") + +获取单个合并请求的差异版本. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/versions/:version_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | String | yes | 项目 ID | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | +| `version_id` | integer | yes | 合并请求差异版本的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions/1" +``` + +响应示例: + +``` +{ "id": 110, "head_commit_sha": "33e2ee8579fda5bc36accc9c6fbd0b4fefda9e30", "base_commit_sha": "eeb57dffe83deb686a60a71c16c32f71046868fd", "start_commit_sha": "eeb57dffe83deb686a60a71c16c32f71046868fd", "created_at": "2016-07-26T14:44:48.926Z", "merge_request_id": 105, "state": "collected", "real_size": "1", "commits": [{ "id": "33e2ee8579fda5bc36accc9c6fbd0b4fefda9e30", "short_id": "33e2ee85", "title": "Change year to 2018", "author_name": "Administrator", "author_email": "admin@example.com", "created_at": "2016-07-26T17:44:29.000+03:00", "message": "Change year to 2018" }, { "id": "aa24655de48b36335556ac8a3cd8bb521f977cbd", "short_id": "aa24655d", "title": "Update LICENSE", "author_name": "Administrator", "author_email": "admin@example.com", "created_at": "2016-07-25T17:21:53.000+03:00", "message": "Update LICENSE" }, { "id": "3eed087b29835c48015768f839d76e5ea8f07a24", "short_id": "3eed087b", "title": "Add license", "author_name": "Administrator", "author_email": "admin@example.com", "created_at": "2016-07-25T17:21:20.000+03:00", "message": "Add license" }], "diffs": [{ "old_path": "LICENSE", "new_path": "LICENSE", "a_mode": "0", "b_mode": "100644", "diff": "--- /dev/null\n+++ b/LICENSE\n@@ -0,0 +1,21 @@\n+The MIT License (MIT)\n+\n+Copyright (c) 2018 Administrator\n+\n+Permission is hereby granted, free of charge, to any person obtaining a copy\n+of this software and associated documentation files (the \"Software\"), to deal\n+in the Software without restriction, including without limitation the rights\n+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n+copies of the Software, and to permit persons to whom the Software is\n+furnished to do so, subject to the following conditions:\n+\n+The above copyright notice and this permission notice shall be included in all\n+copies or substantial portions of the Software.\n+\n+THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n+SOFTWARE.\n", "new_file": true, "renamed_file": false, "deleted_file": false }] } +``` + +## Set a time estimate for a merge request[](#set-a-time-estimate-for-a-merge-request "Permalink") + +Sets an estimated time of work for this merge request. + +``` +POST /projects/:id/merge_requests/:merge_request_iid/time_estimate +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | +| `duration` | string | yes | 以人类格式表示的持续时间. 例如:3h30m | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_estimate?duration=3h30m" +``` + +响应示例: + +``` +{ "human_time_estimate": "3h 30m", "human_total_time_spent": null, "time_estimate": 12600, "total_time_spent": 0 } +``` + +## Reset the time estimate for a merge request[](#reset-the-time-estimate-for-a-merge-request "Permalink") + +将此合并请求的估计时间重置为 0 秒. + +``` +POST /projects/:id/merge_requests/:merge_request_iid/reset_time_estimate +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 项目的 merge_request 的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_time_estimate" +``` + +响应示例: + +``` +{ "human_time_estimate": null, "human_total_time_spent": null, "time_estimate": 0, "total_time_spent": 0 } +``` + +## Add spent time for a merge request[](#add-spent-time-for-a-merge-request "Permalink") + +增加此合并请求的时间 + +``` +POST /projects/:id/merge_requests/:merge_request_iid/add_spent_time +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | +| `duration` | string | yes | 以人类格式表示的持续时间. 例如:3h30m | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/add_spent_time?duration=1h" +``` + +响应示例: + +``` +{ "human_time_estimate": null, "human_total_time_spent": "1h", "time_estimate": 0, "total_time_spent": 3600 } +``` + +## Reset spent time for a merge request[](#reset-spent-time-for-a-merge-request "Permalink") + +将此合并请求的总花费时间重置为 0 秒. + +``` +POST /projects/:id/merge_requests/:merge_request_iid/reset_spent_time +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 项目的 merge_request 的内部 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_spent_time" +``` + +响应示例: + +``` +{ "human_time_estimate": null, "human_total_time_spent": null, "time_estimate": 0, "total_time_spent": 0 } +``` + +## Get time tracking stats[](#get-time-tracking-stats "Permalink") + +``` +GET /projects/:id/merge_requests/:merge_request_iid/time_stats +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的内部 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_stats" +``` + +响应示例: + +``` +{ "human_time_estimate": "2h", "human_total_time_spent": "1h", "time_estimate": 7200, "total_time_spent": 3600 } +``` + +## Approvals[](#approvals-starter "Permalink") + +有关批准,请参阅[合并请求批准](merge_request_approvals.html) \ No newline at end of file diff --git a/docs/338.md b/docs/338.md new file mode 100644 index 0000000000000000000000000000000000000000..a17013eef83f07590dce514792fe3ebcac443c4a --- /dev/null +++ b/docs/338.md @@ -0,0 +1,167 @@ +# Project milestones API + +> 原文:[https://docs.gitlab.com/ee/api/milestones.html](https://docs.gitlab.com/ee/api/milestones.html) + +* [List project milestones](#list-project-milestones) +* [Get single milestone](#get-single-milestone) +* [Create new milestone](#create-new-milestone) +* [Edit milestone](#edit-milestone) +* [Delete project milestone](#delete-project-milestone) +* [Get all issues assigned to a single milestone](#get-all-issues-assigned-to-a-single-milestone) +* [Get all merge requests assigned to a single milestone](#get-all-merge-requests-assigned-to-a-single-milestone) +* [Promote project milestone to a group milestone](#promote-project-milestone-to-a-group-milestone) +* [Get all burndown chart events for a single milestone](#get-all-burndown-chart-events-for-a-single-milestone-starter) + +# Project milestones API[](#project-milestones-api "Permalink") + +This page describes the project milestones API. There’s a separate [group milestones API](./group_milestones.html) page. + +## List project milestones[](#list-project-milestones "Permalink") + +返回项目里程碑的列表. + +``` +GET /projects/:id/milestones +GET /projects/:id/milestones?iids[]=42 +GET /projects/:id/milestones?iids[]=42&iids[]=43 +GET /projects/:id/milestones?state=active +GET /projects/:id/milestones?state=closed +GET /projects/:id/milestones?title=1.0 +GET /projects/:id/milestones?search=version +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `iids[]` | 整数数组 | optional | 仅返回具有给定`iid`的里程碑 | +| `state` | string | optional | 仅返回`active`或`closed`里程碑 | +| `title` | string | optional | 仅返回具有给定`title`的里程碑 | +| `search` | string | optional | 仅返回标题或描述与提供的字符串匹配的里程碑 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/milestones" +``` + +示例响应: + +``` +[ { "id": 12, "iid": 3, "project_id": 16, "title": "10.0", "description": "Version", "due_date": "2013-11-29", "start_date": "2013-11-10", "state": "active", "updated_at": "2013-10-02T09:24:18Z", "created_at": "2013-10-02T09:24:18Z" } ] +``` + +## Get single milestone[](#get-single-milestone "Permalink") + +获得单个项目里程碑. + +``` +GET /projects/:id/milestones/:milestone_id +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID + +## Create new milestone[](#create-new-milestone "Permalink") + +创建一个新的项目里程碑. + +``` +POST /projects/:id/milestones +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `title` (必填)-里程碑的标题 +* `description` (可选)-里程碑的说明 +* `due_date` (可选)-里程碑的截止日期 +* `start_date` (可选)-里程碑的开始日期 + +## Edit milestone[](#edit-milestone "Permalink") + +更新现有项目的里程碑. + +``` +PUT /projects/:id/milestones/:milestone_id +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID +* `title` (可选)-里程碑的标题 +* `description` (可选)-里程碑的说明 +* `due_date` (可选)-里程碑的截止日期 +* `start_date` (可选)-里程碑的开始日期 +* `state_event` (可选)-里程碑的状态事件(关闭或激活) + +## Delete project milestone[](#delete-project-milestone "Permalink") + +仅适用于具有开发人员访问项目权限的用户. + +``` +DELETE /projects/:id/milestones/:milestone_id +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID + +## Get all issues assigned to a single milestone[](#get-all-issues-assigned-to-a-single-milestone "Permalink") + +获取分配给单个项目里程碑的所有问题. + +``` +GET /projects/:id/milestones/:milestone_id/issues +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID + +## Get all merge requests assigned to a single milestone[](#get-all-merge-requests-assigned-to-a-single-milestone "Permalink") + +获取分配给单个项目里程碑的所有合并请求. + +``` +GET /projects/:id/milestones/:milestone_id/merge_requests +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID + +## Promote project milestone to a group milestone[](#promote-project-milestone-to-a-group-milestone "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53861) + +仅针对具有开发者访问权限的用户. + +``` +POST /projects/:id/milestones/:milestone_id/promote +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID + +## Get all burndown chart events for a single milestone[](#get-all-burndown-chart-events-for-a-single-milestone-starter "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4737) + +获取单个里程碑的所有燃尽图事件. + +``` +GET /projects/:id/milestones/:milestone_id/burndown_events +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `milestone_id` (必填)-项目里程碑的 ID \ No newline at end of file diff --git a/docs/339.md b/docs/339.md new file mode 100644 index 0000000000000000000000000000000000000000..721d2e5fec6d16859d54e4cc268d95e423ef882a --- /dev/null +++ b/docs/339.md @@ -0,0 +1,167 @@ +# Group milestones API + +> 原文:[https://docs.gitlab.com/ee/api/group_milestones.html](https://docs.gitlab.com/ee/api/group_milestones.html) + +* [List group milestones](#list-group-milestones) +* [Get single milestone](#get-single-milestone) +* [Create new milestone](#create-new-milestone) +* [Edit milestone](#edit-milestone) +* [Delete group milestone](#delete-group-milestone) +* [Get all issues assigned to a single milestone](#get-all-issues-assigned-to-a-single-milestone) +* [Get all merge requests assigned to a single milestone](#get-all-merge-requests-assigned-to-a-single-milestone) +* [Get all burndown chart events for a single milestone](#get-all-burndown-chart-events-for-a-single-milestone-starter) + +# Group milestones API[](#group-milestones-api "Permalink") + +在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12819) . + +此页面描述了组里程碑 API. 有一个单独的[项目里程碑 API](./group_milestones.html)页面. + +## List group milestones[](#list-group-milestones "Permalink") + +返回组里程碑列表. + +``` +GET /groups/:id/milestones +GET /groups/:id/milestones?iids[]=42 +GET /groups/:id/milestones?iids[]=42&iids[]=43 +GET /groups/:id/milestones?state=active +GET /groups/:id/milestones?state=closed +GET /groups/:id/milestones?title=1.0 +GET /groups/:id/milestones?search=version +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `iids[]` | 整数数组 | no | 仅返回具有给定`iid`的里程碑 | +| `state` | string | no | 仅返回`active`或`closed`里程碑 | +| `title` | string | no | 仅返回具有给定`title`的里程碑 | +| `search` | string | no | 仅返回标题或描述与提供的字符串匹配的里程碑 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/milestones" +``` + +示例响应: + +``` +[ { "id": 12, "iid": 3, "group_id": 16, "title": "10.0", "description": "Version", "due_date": "2013-11-29", "start_date": "2013-11-10", "state": "active", "updated_at": "2013-10-02T09:24:18Z", "created_at": "2013-10-02T09:24:18Z", "web_url": "https://gitlab.com/groups/gitlab-org/-/milestones/42" } ] +``` + +## Get single milestone[](#get-single-milestone "Permalink") + +获取单个组里程碑. + +``` +GET /groups/:id/milestones/:milestone_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `milestone_id` | integer | yes | 组里程碑的 ID | + +## Create new milestone[](#create-new-milestone "Permalink") + +创建一个新的组里程碑. + +``` +POST /groups/:id/milestones +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `title` | string | yes | 里程碑的标题 | +| `description` | string | no | 里程碑的描述 | +| `due_date` | date | no | 里程碑的到期日期,格式为 YYYY-MM-DD(ISO 8601) | +| `start_date` | date | no | 里程碑的开始日期,格式为 YYYY-MM-DD(ISO 8601) | + +## Edit milestone[](#edit-milestone "Permalink") + +更新现有的组里程碑. + +``` +PUT /groups/:id/milestones/:milestone_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `milestone_id` | integer | yes | 组里程碑的 ID | +| `title` | string | no | 里程碑的标题 | +| `description` | string | no | 里程碑的描述 | +| `due_date` | date | no | 里程碑的到期日期,格式为 YYYY-MM-DD(ISO 8601) | +| `start_date` | date | no | 里程碑的开始日期,格式为 YYYY-MM-DD(ISO 8601) | +| `state_event` | string | no | 里程碑的状态事件*( `close`或`activate` )* | + +## Delete group milestone[](#delete-group-milestone "Permalink") + +仅针对具有开发者访问权限的用户. + +``` +DELETE /groups/:id/milestones/:milestone_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `milestone_id` | integer | yes | 小组里程碑的 ID | + +## Get all issues assigned to a single milestone[](#get-all-issues-assigned-to-a-single-milestone "Permalink") + +获取分配给单个组里程碑的所有问题. + +``` +GET /groups/:id/milestones/:milestone_id/issues +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `milestone_id` | integer | yes | 组里程碑的 ID | + +## Get all merge requests assigned to a single milestone[](#get-all-merge-requests-assigned-to-a-single-milestone "Permalink") + +获取分配给单个组里程碑的所有合并请求. + +``` +GET /groups/:id/milestones/:milestone_id/merge_requests +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `milestone_id` | integer | yes | 组里程碑的 ID | + +## Get all burndown chart events for a single milestone[](#get-all-burndown-chart-events-for-a-single-milestone-starter "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/4737) + +获取单个里程碑的所有燃尽图事件. + +``` +GET /groups/:id/milestones/:milestone_id/burndown_events +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `milestone_id` | integer | yes | 组里程碑的 ID | \ No newline at end of file diff --git a/docs/340.md b/docs/340.md new file mode 100644 index 0000000000000000000000000000000000000000..2170615597d2b0708c00b806690a5370b75ea665 --- /dev/null +++ b/docs/340.md @@ -0,0 +1,103 @@ +# Namespaces API + +> 原文:[https://docs.gitlab.com/ee/api/namespaces.html](https://docs.gitlab.com/ee/api/namespaces.html) + +* [List namespaces](#list-namespaces) +* [Search for namespace](#search-for-namespace) +* [Get namespace by ID](#get-namespace-by-id) + +# Namespaces API[](#namespaces-api "Permalink") + +用户名和组名属于称为命名空间的特殊类别. + +对于用户和组支持的 API 调用,请分别参阅[用户](users.html)和[组](groups.html)文档. + +[使用分页](README.html#pagination) . + +## List namespaces[](#list-namespaces "Permalink") + +获取已认证用户的名称空间列表. 如果用户是管理员,则会显示 GitLab 实例中所有名称空间的列表. + +``` +GET /namespaces +``` + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/namespaces" +``` + +响应示例: + +``` +[ { "id": 1, "name": "user1", "path": "user1", "kind": "user", "full_path": "user1" }, { "id": 2, "name": "group1", "path": "group1", "kind": "group", "full_path": "group1", "parent_id": null, "members_count_with_descendants": 2 }, { "id": 3, "name": "bar", "path": "bar", "kind": "group", "full_path": "foo/bar", "parent_id": 9, "members_count_with_descendants": 5 } ] +``` + +GitLab.com [Bronze 或更高版本](https://about.gitlab.com/pricing/#gitlab-com)上的用户可能还会看到与名称空间关联的`plan`参数: + +``` +[ { "id": 1, "name": "user1", "plan": "bronze", ... } ] +``` + +**注意:**仅向组维护者/所有者提供了`members_count_with_descendants`和`plan` . + +## Search for namespace[](#search-for-namespace "Permalink") + +获取与名称或路径中的字符串匹配的所有名称空间. + +``` +GET /namespaces?search=foobar +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `search` | string | no | 返回基于搜索条件授权用户查看的名称空间列表 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/namespaces?search=twitter" +``` + +响应示例: + +``` +[ { "id": 4, "name": "twitter", "path": "twitter", "kind": "group", "full_path": "twitter", "parent_id": null, "members_count_with_descendants": 2 } ] +``` + +## Get namespace by ID[](#get-namespace-by-id "Permalink") + +通过 ID 获取名称空间. + +``` +GET /namespaces/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | [名称空间的](README.html#namespaced-path-encoding) ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/namespaces/2" +``` + +响应示例: + +``` +{ "id": 2, "name": "group1", "path": "group1", "kind": "group", "full_path": "group1", "parent_id": null, "members_count_with_descendants": 2 } +``` + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/namespaces/group1" +``` + +响应示例: + +``` +{ "id": 2, "name": "group1", "path": "group1", "kind": "group", "full_path": "group1", "parent_id": null, "members_count_with_descendants": 2 } +``` \ No newline at end of file diff --git a/docs/341.md b/docs/341.md new file mode 100644 index 0000000000000000000000000000000000000000..9395abce622f49c66c925d999bc879becd1ed20f --- /dev/null +++ b/docs/341.md @@ -0,0 +1,456 @@ +# Notes API + +> 原文:[https://docs.gitlab.com/ee/api/notes.html](https://docs.gitlab.com/ee/api/notes.html) + +* [Notes pagination](#notes-pagination) +* [Issues](#issues) + * [List project issue notes](#list-project-issue-notes) + * [Get single issue note](#get-single-issue-note) + * [Create new issue note](#create-new-issue-note) + * [Modify existing issue note](#modify-existing-issue-note) + * [Delete an issue note](#delete-an-issue-note) +* [Snippets](#snippets) + * [List all snippet notes](#list-all-snippet-notes) + * [Get single snippet note](#get-single-snippet-note) + * [Create new snippet note](#create-new-snippet-note) + * [Modify existing snippet note](#modify-existing-snippet-note) + * [Delete a snippet note](#delete-a-snippet-note) +* [Merge Requests](#merge-requests) + * [List all merge request notes](#list-all-merge-request-notes) + * [Get single merge request note](#get-single-merge-request-note) + * [Create new merge request note](#create-new-merge-request-note) + * [Modify existing merge request note](#modify-existing-merge-request-note) + * [Delete a merge request note](#delete-a-merge-request-note) +* [Epics](#epics-ultimate) + * [List all epic notes](#list-all-epic-notes) + * [Get single epic note](#get-single-epic-note) + * [Create new epic note](#create-new-epic-note) + * [Modify existing epic note](#modify-existing-epic-note) + * [Delete an epic note](#delete-an-epic-note) + +# Notes API[](#notes-api "Permalink") + +注释是对以下内容的评论: + +* Snippets +* Issues +* 合并要求 +* Epics + +这包括系统注释,这些注释是有关对象更改的注释(例如,当里程碑更改时,将有相应的系统注释). 标签注释不是此 API 的一部分,而是在[资源标签事件中](resource_label_events.html)记录为单独的[事件](resource_label_events.html) . + +## Notes pagination[](#notes-pagination "Permalink") + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +## Issues[](#issues "Permalink") + +### List project issue notes[](#list-project-issue-notes "Permalink") + +获取单个问题的所有注释的列表. + +``` +GET /projects/:id/issues/:issue_iid/notes +GET /projects/:id/issues/:issue_iid/notes?sort=asc&order_by=updated_at +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `sort` | string | no | 返回按`asc`或`desc`排列的发行说明. 默认为`desc` | +| `order_by` | string | no | 返回按`created_at`或`updated_at`字段排序的发行说明. 默认为`created_at` | + +``` +[ { "id": 302, "body": "closed", "attachment": null, "author": { "id": 1, "username": "pipin", "email": "admin@example.com", "name": "Pip", "state": "active", "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T09:22:45Z", "updated_at": "2013-10-02T10:22:45Z", "system": true, "noteable_id": 377, "noteable_type": "Issue", "noteable_iid": 377, "resolvable": false, "confidential": false }, { "id": 305, "body": "Text of the comment\r\n", "attachment": null, "author": { "id": 1, "username": "pipin", "email": "admin@example.com", "name": "Pip", "state": "active", "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T09:56:03Z", "updated_at": "2013-10-02T09:56:03Z", "system": true, "noteable_id": 121, "noteable_type": "Issue", "noteable_iid": 121, "resolvable": false, "confidential": true } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/notes" +``` + +### Get single issue note[](#get-single-issue-note "Permalink") + +返回有关特定项目问题的单个注释 + +``` +GET /projects/:id/issues/:issue_iid/notes/:note_id +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `issue_iid` (必填)-项目问题的 IID +* `note_id` (必填)-问题注释的 ID + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/notes/1" +``` + +### Create new issue note[](#create-new-issue-note "Permalink") + +为单个项目问题创建新的注释. + +``` +POST /projects/:id/issues/:issue_iid/notes +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `issue_iid` (必填)-问题的 IID +* `body` (必填)-注释的内容. 限制为 1,000,000 个字符. +* `confidential` (可选)-便笺的机密标志. 默认为 false. +* `created_at` (可选)-日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z(需要管理员或项目/组所有者权限) + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/notes?body=note" +``` + +### Modify existing issue note[](#modify-existing-issue-note "Permalink") + +修改问题的现有注释. + +``` +PUT /projects/:id/issues/:issue_iid/notes/:note_id +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `issue_iid` (必填)-问题的 IID +* `note_id` (必填)-注释的 ID +* `body` (必填)-注释的内容. 限制为 1,000,000 个字符. + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/notes?body=note" +``` + +### Delete an issue note[](#delete-an-issue-note "Permalink") + +删除问题的现有注释. + +``` +DELETE /projects/:id/issues/:issue_iid/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `note_id` | integer | yes | 笔记的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/notes/636" +``` + +## Snippets[](#snippets "Permalink") + +### List all snippet notes[](#list-all-snippet-notes "Permalink") + +获取单个代码段的所有注释的列表. 片段注释是用户可以发布到片段的注释. + +``` +GET /projects/:id/snippets/:snippet_id/notes +GET /projects/:id/snippets/:snippet_id/notes?sort=asc&order_by=updated_at +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 项目代码段的 ID | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的`asc`注释. 默认为`desc` | +| `order_by` | string | no | 返回按`created_at`或`updated_at`字段排序的`created_at`注释. 默认为`created_at` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/notes" +``` + +### Get single snippet note[](#get-single-snippet-note "Permalink") + +返回给定片段的单个音符. + +``` +GET /projects/:id/snippets/:snippet_id/notes/:note_id +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-项目代码段的 ID +* `note_id` (必填)- `note_id`的 ID + +``` +{ "id": 52, "title": "Snippet", "file_name": "snippet.rb", "author": { "id": 1, "username": "pipin", "email": "admin@example.com", "name": "Pip", "state": "active", "created_at": "2013-09-30T13:46:01Z" }, "expires_at": null, "updated_at": "2013-10-02T07:34:20Z", "created_at": "2013-10-02T07:34:20Z" } +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/notes/11" +``` + +### Create new snippet note[](#create-new-snippet-note "Permalink") + +为单个代码段创建新的音符. 片段注释是用户可以发布到片段的注释. 如果您在主体仅包含奖励表情符号的位置创建注释,则会收到该对象的回信. + +``` +POST /projects/:id/snippets/:snippet_id/notes +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-代码段的 ID +* `body` (必填)-注释的内容. 限制为 1,000,000 个字符. +* `created_at` (可选)-日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippet/11/notes?body=note" +``` + +### Modify existing snippet note[](#modify-existing-snippet-note "Permalink") + +修改代码段的现有注释. + +``` +PUT /projects/:id/snippets/:snippet_id/notes/:note_id +``` + +Parameters: + +* `id` (required) - The ID or [URL-encoded path of the project](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-代码段的 ID +* `note_id` (必填)-注释的 ID +* `body` (必填)-注释的内容. 限制为 1,000,000 个字符. + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/11/notes?body=note" +``` + +### Delete a snippet note[](#delete-a-snippet-note "Permalink") + +删除片段的现有注释. + +``` +DELETE /projects/:id/snippets/:snippet_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `snippet_id` | integer | yes | 片段的 ID | +| `note_id` | integer | yes | 笔记的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippets/52/notes/1659" +``` + +## Merge Requests[](#merge-requests "Permalink") + +### List all merge request notes[](#list-all-merge-request-notes "Permalink") + +获取单个合并请求的所有注释的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/notes +GET /projects/:id/merge_requests/:merge_request_iid/notes?sort=asc&order_by=updated_at +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 项目合并请求的 IID | +| `sort` | string | no | 返回以`asc`或`desc`顺序排序的合并请求注释. 默认为`desc` | +| `order_by` | string | no | 返回由`created_at`或`updated_at`字段排序的合并请求注释. 默认为`created_at` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes" +``` + +### Get single merge request note[](#get-single-merge-request-note "Permalink") + +返回给定合并请求的单个注释. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/notes/:note_id +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必填)-项目合并请求的 IID +* `note_id` (必需)-合并请求注释的 ID + +``` +{ "id": 301, "body": "Comment for MR", "attachment": null, "author": { "id": 1, "username": "pipin", "email": "admin@example.com", "name": "Pip", "state": "active", "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T08:57:14Z", "updated_at": "2013-10-02T08:57:14Z", "system": false, "noteable_id": 2, "noteable_type": "MergeRequest", "noteable_iid": 2, "resolvable": false, "confidential": false } +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes/1" +``` + +### Create new merge request note[](#create-new-merge-request-note "Permalink") + +为单个合并请求创建一个新注释. 如果您在主体仅包含奖励表情符号的位置创建注释,则会收到该对象的回信. + +``` +POST /projects/:id/merge_requests/:merge_request_iid/notes +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必填)-合并请求的 IID +* `body` (必填)-注释的内容. 限制为 1,000,000 个字符. +* `created_at` (可选)-日期时间字符串,ISO 8601 格式,例如 2016-03-11T03:45:40Z + +### Modify existing merge request note[](#modify-existing-merge-request-note "Permalink") + +修改合并请求的现有注释. + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/notes/:note_id +``` + +Parameters: + +* `id` (必填)-项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) +* `merge_request_iid` (必填)-合并请求的 IID +* `note_id` (必填)-注释的 ID +* `body` (必填)-注释的内容. 限制为 1,000,000 个字符. + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes?body=note" +``` + +### Delete a merge request note[](#delete-a-merge-request-note "Permalink") + +删除合并请求的现有注释. + +``` +DELETE /projects/:id/merge_requests/:merge_request_iid/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `note_id` | integer | yes | 笔记的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/7/notes/1602" +``` + +## Epics[](#epics-ultimate "Permalink") + +### List all epic notes[](#list-all-epic-notes "Permalink") + +获取单个史诗的所有注释的列表. 史诗笔记是用户可以发布到史诗中的评论. + +``` +GET /groups/:id/epics/:epic_id/notes +GET /groups/:id/epics/:epic_id/notes?sort=asc&order_by=updated_at +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 小组史诗的 ID | +| `sort` | string | no | 返回按`asc`或`desc`排列的史诗笔记. 默认为`desc` | +| `order_by` | string | no | 返回按`created_at`或`updated_at`字段排序的史诗笔记. 默认为`created_at` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/notes" +``` + +### Get single epic note[](#get-single-epic-note "Permalink") + +返回给定史诗的单个音符. + +``` +GET /groups/:id/epics/:epic_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `note_id` | integer | yes | 笔记的 ID | + +``` +{ "id": 52, "title": "Epic", "file_name": "epic.rb", "author": { "id": 1, "username": "pipin", "email": "admin@example.com", "name": "Pip", "state": "active", "created_at": "2013-09-30T13:46:01Z" }, "expires_at": null, "updated_at": "2013-10-02T07:34:20Z", "created_at": "2013-10-02T07:34:20Z", "confidential": false } +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/11/notes/1" +``` + +### Create new epic note[](#create-new-epic-note "Permalink") + +为单个史诗创建新的音符. 史诗笔记是用户可以发布到史诗中的评论. 如果您在主体仅包含奖励表情符号的位置创建注释,则会收到该对象的回信. + +``` +POST /groups/:id/epics/:epic_id/notes +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `body` | string | yes | 注释的内容. 限制为 1,000,000 个字符. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippet/11/notes?body=note" +``` + +### Modify existing epic note[](#modify-existing-epic-note "Permalink") + +修改史诗的现有注释. + +``` +PUT /groups/:id/epics/:epic_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `note_id` | integer | yes | 笔记的 ID | +| `body` | string | yes | 注释的内容. 限制为 1,000,000 个字符. | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/snippet/11/notes?body=note" +``` + +### Delete an epic note[](#delete-an-epic-note "Permalink") + +删除史诗的现有音符. + +``` +DELETE /groups/:id/epics/:epic_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `note_id` | integer | yes | 笔记的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/epics/52/notes/1659" +``` \ No newline at end of file diff --git a/docs/342.md b/docs/342.md new file mode 100644 index 0000000000000000000000000000000000000000..de74ec9ec0f0e0ba3ef18d12d4ffc9151d18478f --- /dev/null +++ b/docs/342.md @@ -0,0 +1,173 @@ +# Notification settings API + +> 原文:[https://docs.gitlab.com/ee/api/notification_settings.html](https://docs.gitlab.com/ee/api/notification_settings.html) + +* [Valid notification levels](#valid-notification-levels) +* [Global notification settings](#global-notification-settings) +* [Update global notification settings](#update-global-notification-settings) +* [Group / project level notification settings](#group--project-level-notification-settings) +* [Update group/project level notification settings](#update-groupproject-level-notification-settings) + +# Notification settings API[](#notification-settings-api "Permalink") + +在 GitLab 8.12 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5632) . + +## Valid notification levels[](#valid-notification-levels "Permalink") + +通知级别在`NotificationSetting.level`模型枚举中定义. 当前,这些级别被认可: + +``` +disabled +participating +watch +global +mention +custom +``` + +如果使用`custom`级别,则可以控制特定的电子邮件事件. 可用事件由`NotificationSetting.email_events`返回. 当前,这些事件被认可: + +* `new_note` +* `new_issue` +* `reopen_issue` +* `close_issue` +* `reassign_issue` +* `issue_due` +* `new_merge_request` +* `push_to_merge_request` +* `reopen_merge_request` +* `close_merge_request` +* `reassign_merge_request` +* `merge_merge_request` +* `failed_pipeline` +* `fixed_pipeline` +* `success_pipeline` +* `new_epic` + +## Global notification settings[](#global-notification-settings "Permalink") + +获取当前的通知设置和电子邮件地址. + +``` +GET /notification_settings +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/notification_settings" +``` + +响应示例: + +``` +{ "level": "participating", "notification_email": "admin@example.com" } +``` + +## Update global notification settings[](#update-global-notification-settings "Permalink") + +更新当前的通知设置和电子邮件地址. + +``` +PUT /notification_settings +``` + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/notification_settings?level=watch" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `level` | string | no | 全局通知级别 | +| `notification_email` | string | no | 发送通知的电子邮件地址 | +| `new_note` | boolean | no | 启用/禁用此通知 | +| `new_issue` | boolean | no | 启用/禁用此通知 | +| `reopen_issue` | boolean | no | 启用/禁用此通知 | +| `close_issue` | boolean | no | 启用/禁用此通知 | +| `reassign_issue` | boolean | no | 启用/禁用此通知 | +| `issue_due` | boolean | no | 启用/禁用此通知 | +| `new_merge_request` | boolean | no | 启用/禁用此通知 | +| `push_to_merge_request` | boolean | no | 启用/禁用此通知 | +| `reopen_merge_request` | boolean | no | 启用/禁用此通知 | +| `close_merge_request` | boolean | no | 启用/禁用此通知 | +| `reassign_merge_request` | boolean | no | 启用/禁用此通知 | +| `merge_merge_request` | boolean | no | 启用/禁用此通知 | +| `failed_pipeline` | boolean | no | 启用/禁用此通知 | +| `fixed_pipeline` | boolean | no | 启用/禁用此通知 | +| `success_pipeline` | boolean | no | 启用/禁用此通知 | +| `new_epic` | boolean | no | 启用/禁用此通知(在 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6626) ) | + +响应示例: + +``` +{ "level": "watch", "notification_email": "admin@example.com" } +``` + +## Group / project level notification settings[](#group--project-level-notification-settings "Permalink") + +获取当前的组或项目通知设置. + +``` +GET /groups/:id/notification_settings +GET /projects/:id/notification_settings +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/notification_settings" +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/8/notification_settings" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组/项目 ID 或路径 | + +响应示例: + +``` +{ "level": "global" } +``` + +## Update group/project level notification settings[](#update-groupproject-level-notification-settings "Permalink") + +更新当前的组/项目通知设置. + +``` +PUT /groups/:id/notification_settings +PUT /projects/:id/notification_settings +``` + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/notification_settings?level=watch" +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/8/notification_settings?level=custom&new_note=true" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组/项目 ID 或路径 | +| `level` | string | no | 全局通知级别 | +| `new_note` | boolean | no | 启用/禁用此通知 | +| `new_issue` | boolean | no | 启用/禁用此通知 | +| `reopen_issue` | boolean | no | 启用/禁用此通知 | +| `close_issue` | boolean | no | 启用/禁用此通知 | +| `reassign_issue` | boolean | no | 启用/禁用此通知 | +| `issue_due` | boolean | no | 启用/禁用此通知 | +| `new_merge_request` | boolean | no | 启用/禁用此通知 | +| `push_to_merge_request` | boolean | no | 启用/禁用此通知 | +| `reopen_merge_request` | boolean | no | 启用/禁用此通知 | +| `close_merge_request` | boolean | no | 启用/禁用此通知 | +| `reassign_merge_request` | boolean | no | 启用/禁用此通知 | +| `merge_merge_request` | boolean | no | 启用/禁用此通知 | +| `failed_pipeline` | boolean | no | 启用/禁用此通知 | +| `fixed_pipeline` | boolean | no | 启用/禁用此通知 | +| `success_pipeline` | boolean | no | 启用/禁用此通知 | +| `new_epic` | boolean | no | 启用/禁用此通知(在 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6626) ) | + +响应示例: + +``` +{ "level": "watch" } { "level": "custom", "events": { "new_note": true, "new_issue": false, "reopen_issue": false, "close_issue": false, "reassign_issue": false, "issue_due": false, "new_merge_request": false, "push_to_merge_request": false, "reopen_merge_request": false, "close_merge_request": false, "reassign_merge_request": false, "merge_merge_request": false, "failed_pipeline": false, "fixed_pipeline": false, "success_pipeline": false } } +``` + +使用 GitLab [Ultimate 或 Gold 的](https://about.gitlab.com/pricing/)用户还将看到`new_epic`参数: + +``` +{ "level": "custom", "events": { "new_note": true, "new_issue": false, "new_epic": false, ... } } +``` \ No newline at end of file diff --git a/docs/343.md b/docs/343.md new file mode 100644 index 0000000000000000000000000000000000000000..85f49c8547788c6e156a22688e32a2140a5ed980 --- /dev/null +++ b/docs/343.md @@ -0,0 +1,167 @@ +# Packages API + +> 原文:[https://docs.gitlab.com/ee/api/packages.html](https://docs.gitlab.com/ee/api/packages.html) + +* [List packages](#list-packages) + * [Within a project](#within-a-project) + * [Within a group](#within-a-group) +* [Get a project package](#get-a-project-package) +* [List package files](#list-package-files) +* [Delete a project package](#delete-a-project-package) + +# Packages API[](#packages-api-premium "Permalink") + +这是[GitLab 软件包](../administration/packages/index.html)的 API 文档. + +## List packages[](#list-packages "Permalink") + +### Within a project[](#within-a-project "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9259) . + +获取项目包列表. 结果中包括所有包装类型. 在未经身份验证的情况下访问时,仅返回公共项目的软件包. + +``` +GET /projects/:id/packages +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `order_by` | string | no | 用作订单的字段. `created_at` (默认), `name` , `version`或`type` . | +| `sort` | string | no | 顺序的方向, `asc` (默认)或`desc` (降序). | +| `package_type` | string | no | 按类型过滤返回的软件包. `conan` , `maven` , `npm` , `pypi` , `composer`或`nuget` . ( *在 GitLab 12.9 中引入* ) | +| `package_name` | string | no | 按名称用模糊搜索过滤项目包. ( *在 GitLab 12.9 中引入* ) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/packages" +``` + +响应示例: + +``` +[ { "id": 1, "name": "com/mycompany/my-app", "version": "1.0-SNAPSHOT", "package_type": "maven", "created_at": "2019-11-27T03:37:38.711Z" }, { "id": 2, "name": "@foo/bar", "version": "1.0.3", "package_type": "npm", "created_at": "2019-11-27T03:37:38.711Z" } ] +``` + +默认情况下,由于 API 是[分页的](README.html#pagination) ,因此`GET`请求将返回 20 个结果. + +### Within a group[](#within-a-group "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18871) . + +获取组级别的项目包列表. 在未经身份验证的情况下访问时,仅返回公共项目的软件包. + +``` +GET /groups/:id/packages +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | [群组的](README.html#namespaced-path-encoding) ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `exclude_subgroups` | boolean | false | 如果参数包含为 true,则不列出子组中项目的软件包. 默认值为`false` . | +| `order_by` | string | no | 用作订单的字段. `created_at` (默认), `name` , `version` , `type`或`project_path` . | +| `sort` | string | no | 顺序的方向, `asc` (默认)或`desc` (降序). | +| `package_type` | string | no | 按类型过滤返回的软件包. `conan` , `maven` , `npm` , `pypi` , `composer`或`nuget` . ( *在 GitLab 12.9 中引入* ) | +| `package_name` | string | no | 按名称用模糊搜索过滤项目包. ( *在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30980)* ) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/:id/packages?exclude_subgroups=true" +``` + +**弃用:>**的`build_info`在响应属性赞成不赞成`pipeline` . >引入了[GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040) . + +响应示例: + +``` +[ { "id": 1, "name": "com/mycompany/my-app", "version": "1.0-SNAPSHOT", "package_type": "maven", "_links": { "web_path": "/namespace1/project1/-/packages/1", "delete_api_path": "/namespace1/project1/-/packages/1" }, "created_at": "2019-11-27T03:37:38.711Z", "pipeline": { "id": 123, "status": "pending", "ref": "new-pipeline", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "web_url": "https://example.com/foo/bar/pipelines/47", "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "user": { "name": "Administrator", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" } } }, { "id": 2, "name": "@foo/bar", "version": "1.0.3", "package_type": "npm", "_links": { "web_path": "/namespace1/project1/-/packages/1", "delete_api_path": "/namespace1/project1/-/packages/1" }, "created_at": "2019-11-27T03:37:38.711Z", "pipeline": { "id": 123, "status": "pending", "ref": "new-pipeline", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "web_url": "https://example.com/foo/bar/pipelines/47", "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "user": { "name": "Administrator", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" } } } ] +``` + +默认情况下,由于 API 是[分页的](README.html#pagination) ,因此`GET`请求将返回 20 个结果. + +`_links`对象包含以下属性: + +* `web_path` :您可以在 GitLab 中访问并查看软件包详细信息的路径. +* `delete_api_path` :删除程序包的 API 路径. 仅在请求用户有权执行此操作时可用. + +## Get a project package[](#get-a-project-package "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9667) . + +获得一个项目包. + +``` +GET /projects/:id/packages/:package_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `package_id` | integer | yes | 包裹的 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/packages/:package_id" +``` + +**弃用:>**的`build_info`在响应属性赞成不赞成`pipeline` . >引入了[GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040) . + +Example response: + +``` +{ "id": 1, "name": "com/mycompany/my-app", "version": "1.0-SNAPSHOT", "package_type": "maven", "_links": { "web_path": "/namespace1/project1/-/packages/1", "delete_api_path": "/namespace1/project1/-/packages/1" }, "created_at": "2019-11-27T03:37:38.711Z", "pipeline": { "id": 123, "status": "pending", "ref": "new-pipeline", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "web_url": "https://example.com/foo/bar/pipelines/47", "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "user": { "name": "Administrator", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" } }, "versions": [ { "id":2, "version":"2.0-SNAPSHOT", "created_at":"2020-04-28T04:42:11.573Z", "pipeline": { "id": 234, "status": "pending", "ref": "new-pipeline", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "web_url": "https://example.com/foo/bar/pipelines/58", "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "user": { "name": "Administrator", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" } } } ] } +``` + +`_links`对象包含以下属性: + +* `web_path` :您可以在 GitLab 中访问并查看软件包详细信息的路径. +* `delete_api_path` :删除程序包的 API 路径. 仅在请求用户有权执行此操作时可用. + +## List package files[](#list-package-files "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9305) . + +获取单个软件包的软件包文件列表. + +``` +GET /projects/:id/packages/:package_id/package_files +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `package_id` | integer | yes | 包裹的 ID. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/packages/4/package_files" +``` + +响应示例: + +``` +[ { "id": 25, "package_id": 4, "created_at": "2018-11-07T15:25:52.199Z", "file_name": "my-app-1.5-20181107.152550-1.jar", "size": 2421, "file_md5": "58e6a45a629910c6ff99145a688971ac", "file_sha1": "ebd193463d3915d7e22219f52740056dfd26cbfe" }, { "id": 26, "package_id": 4, "created_at": "2018-11-07T15:25:56.776Z", "file_name": "my-app-1.5-20181107.152550-1.pom", "size": 1122, "file_md5": "d90f11d851e17c5513586b4a7e98f1b2", "file_sha1": "9608d068fe88aff85781811a42f32d97feb440b5" }, { "id": 27, "package_id": 4, "created_at": "2018-11-07T15:26:00.556Z", "file_name": "maven-metadata.xml", "size": 767, "file_md5": "6dfd0cce1203145a927fef5e3a1c650c", "file_sha1": "d25932de56052d320a8ac156f745ece73f6a8cd2" } ] +``` + +默认情况下,由于 API 是[分页的](README.html#pagination) ,因此`GET`请求将返回 20 个结果. + +## Delete a project package[](#delete-a-project-package "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9623) . + +删除项目包. + +``` +DELETE /projects/:id/packages/:package_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `package_id` | integer | yes | 包裹的 ID. | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/packages/:package_id" +``` + +可以返回以下状态码: + +* `204 No Content` ,如果软件包已成功删除. +* `404 Not Found` ,如果`404 Not Found`包. \ No newline at end of file diff --git a/docs/344.md b/docs/344.md new file mode 100644 index 0000000000000000000000000000000000000000..01dd248ad230e6d4af8f2eca03b7d62cda7422ab --- /dev/null +++ b/docs/344.md @@ -0,0 +1,185 @@ +# Pages domains API + +> 原文:[https://docs.gitlab.com/ee/api/pages_domains.html](https://docs.gitlab.com/ee/api/pages_domains.html) + +* [List all pages domains](#list-all-pages-domains) +* [List pages domains](#list-pages-domains) +* [Single pages domain](#single-pages-domain) +* [Create new pages domain](#create-new-pages-domain) +* [Update pages domain](#update-pages-domain) + * [Adding certificate](#adding-certificate) + * [Enabling Let’s Encrypt integration for Pages custom domains](#enabling-lets-encrypt-integration-for-pages-custom-domains) + * [Removing certificate](#removing-certificate) +* [Delete pages domain](#delete-pages-domain) + +# Pages domains API[](#pages-domains-api "Permalink") + +在[GitLab Pages 中](https://about.gitlab.com/stages-devops-lifecycle/pages/)连接自定义域和 TLS 证书的端点. + +必须启用 GitLab 页面功能才能使用这些端点. 了解有关[管理](../administration/pages/index.html)和[使用](../user/project/pages/index.html)功能的更多信息. + +## List all pages domains[](#list-all-pages-domains "Permalink") + +获取所有页面域的列表. 用户必须具有管理员权限. + +``` +GET /pages/domains +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/pages/domains" +``` + +``` +[ { "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "project_id": 1337, "auto_ssl_enabled": false, "certificate": { "expired": false, "expiration": "2020-04-12T14:32:00.000Z" } } ] +``` + +## List pages domains[](#list-pages-domains "Permalink") + +Get a list of project pages domains. The user must have permissions to view pages domains. + +``` +GET /projects/:id/pages/domains +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/pages/domains" +``` + +``` +[ { "domain": "www.domain.example", "url": "http://www.domain.example" }, { "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "auto_ssl_enabled": false, "certificate": { "subject": "/O=Example, Inc./OU=Example Origin CA/CN=Example Origin Certificate", "expired": false, "certificate": "-----BEGIN CERTIFICATE-----\n … \n-----END CERTIFICATE-----", "certificate_text": "Certificate:\n … \n" } } ] +``` + +## Single pages domain[](#single-pages-domain "Permalink") + +获取单个项目页面域. 用户必须具有查看页面域的权限. + +``` +GET /projects/:id/pages/domains/:domain +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `domain` | string | yes | 用户指定的自定义域 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/pages/domains/www.domain.example" +``` + +``` +{ "domain": "www.domain.example", "url": "http://www.domain.example" } +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example" +``` + +``` +{ "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "auto_ssl_enabled": false, "certificate": { "subject": "/O=Example, Inc./OU=Example Origin CA/CN=Example Origin Certificate", "expired": false, "certificate": "-----BEGIN CERTIFICATE-----\n … \n-----END CERTIFICATE-----", "certificate_text": "Certificate:\n … \n" } } +``` + +## Create new pages domain[](#create-new-pages-domain "Permalink") + +创建一个新的页面域. 用户必须具有创建新页面域的权限. + +``` +POST /projects/:id/pages/domains +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `domain` | string | yes | 用户指定的自定义域 | +| `auto_ssl_enabled` | boolean | no | 启用[自动生成](../user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html)由 Let's Encrypt 为自定义域颁发的 SSL 证书的功能. | +| `certificate` | file/string | no | PEM 格式的证书,其中的中间体按照从最高到最低的顺序排列. | +| `key` | file/string | no | PEM 格式的证书密钥. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "domain=ssl.domain.example" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" "https://gitlab.example.com/api/v4/projects/5/pages/domains" +``` + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "domain=ssl.domain.example" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" "https://gitlab.example.com/api/v4/projects/5/pages/domains" +``` + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "domain=ssl.domain.example" --form "auto_ssl_enabled=true" "https://gitlab.example.com/api/v4/projects/5/pages/domains" +``` + +``` +{ "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "auto_ssl_enabled": true, "certificate": { "subject": "/O=Example, Inc./OU=Example Origin CA/CN=Example Origin Certificate", "expired": false, "certificate": "-----BEGIN CERTIFICATE-----\n … \n-----END CERTIFICATE-----", "certificate_text": "Certificate:\n … \n" } } +``` + +## Update pages domain[](#update-pages-domain "Permalink") + +更新现有的项目页面域. 用户必须具有更改现有页面域的权限. + +``` +PUT /projects/:id/pages/domains/:domain +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `domain` | string | yes | 用户指定的自定义域 | +| `auto_ssl_enabled` | boolean | no | 启用[自动生成](../user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html)由 Let's Encrypt 为自定义域颁发的 SSL 证书的功能. | +| `certificate` | file/string | no | PEM 格式的证书,其中的中间体按照从最高到最低的顺序排列. | +| `key` | file/string | no | PEM 格式的证书密钥. | + +### Adding certificate[](#adding-certificate "Permalink") + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example" +``` + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example" +``` + +``` +{ "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "auto_ssl_enabled": false, "certificate": { "subject": "/O=Example, Inc./OU=Example Origin CA/CN=Example Origin Certificate", "expired": false, "certificate": "-----BEGIN CERTIFICATE-----\n … \n-----END CERTIFICATE-----", "certificate_text": "Certificate:\n … \n" } } +``` + +### Enabling Let’s Encrypt integration for Pages custom domains[](#enabling-lets-encrypt-integration-for-pages-custom-domains "Permalink") + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form "auto_ssl_enabled=true" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example" +``` + +``` +{ "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "auto_ssl_enabled": true } +``` + +### Removing certificate[](#removing-certificate "Permalink") + +要删除附加到 Pages 域的 SSL 证书,请运行: + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form "certificate=" --form "key=" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example" +``` + +``` +{ "domain": "ssl.domain.example", "url": "https://ssl.domain.example", "auto_ssl_enabled": false } +``` + +## Delete pages domain[](#delete-pages-domain "Permalink") + +删除现有的项目页面域. + +``` +DELETE /projects/:id/pages/domains/:domain +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `domain` | string | yes | 用户指定的自定义域 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example" +``` \ No newline at end of file diff --git a/docs/345.md b/docs/345.md new file mode 100644 index 0000000000000000000000000000000000000000..7d7636528a65edc9172ce2a147817b2f9d36ba74 --- /dev/null +++ b/docs/345.md @@ -0,0 +1,255 @@ +# Pipeline schedules API + +> 原文:[https://docs.gitlab.com/ee/api/pipeline_schedules.html](https://docs.gitlab.com/ee/api/pipeline_schedules.html) + +* [Get all pipeline schedules](#get-all-pipeline-schedules) +* [Get a single pipeline schedule](#get-a-single-pipeline-schedule) +* [Create a new pipeline schedule](#create-a-new-pipeline-schedule) +* [Edit a pipeline schedule](#edit-a-pipeline-schedule) +* [Take ownership of a pipeline schedule](#take-ownership-of-a-pipeline-schedule) +* [Delete a pipeline schedule](#delete-a-pipeline-schedule) +* [Run a scheduled pipeline immediately](#run-a-scheduled-pipeline-immediately) +* [Pipeline schedule variables](#pipeline-schedule-variables) +* [Create a new pipeline schedule variable](#create-a-new-pipeline-schedule-variable) +* [Edit a pipeline schedule variable](#edit-a-pipeline-schedule-variable) +* [Delete a pipeline schedule variable](#delete-a-pipeline-schedule-variable) + +# Pipeline schedules API[](#pipeline-schedules-api "Permalink") + +您可以阅读有关[管道计划的](../ci/pipelines/schedules.html)更多信息. + +## Get all pipeline schedules[](#get-all-pipeline-schedules "Permalink") + +获取项目的管道时间表的列表. + +``` +GET /projects/:id/pipeline_schedules +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.html#namespaced-path-encoding) owned by the authenticated user | +| `scope` | string | no | 管道计划的范围,其中之一: `active` , `inactive` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules" +``` + +``` +[ { "id": 13, "description": "Test schedule pipeline", "ref": "master", "cron": "* * * * *", "cron_timezone": "Asia/Tokyo", "next_run_at": "2017-05-19T13:41:00.000Z", "active": true, "created_at": "2017-05-19T13:31:08.849Z", "updated_at": "2017-05-19T13:40:17.727Z", "owner": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" } } ] +``` + +## Get a single pipeline schedule[](#get-a-single-pipeline-schedule "Permalink") + +获取项目的管道计划. + +``` +GET /projects/:id/pipeline_schedules/:pipeline_schedule_id +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13" +``` + +``` +{ "id": 13, "description": "Test schedule pipeline", "ref": "master", "cron": "* * * * *", "cron_timezone": "Asia/Tokyo", "next_run_at": "2017-05-19T13:41:00.000Z", "active": true, "created_at": "2017-05-19T13:31:08.849Z", "updated_at": "2017-05-19T13:40:17.727Z", "last_pipeline": { "id": 332, "sha": "0e788619d0b5ec17388dffb973ecd505946156db", "ref": "master", "status": "pending" }, "owner": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "variables": [ { "key": "TEST_VARIABLE_1", "variable_type": "env_var", "value": "TEST_1" } ] } +``` + +## Create a new pipeline schedule[](#create-a-new-pipeline-schedule "Permalink") + +创建一个新的项目管道计划. + +``` +POST /projects/:id/pipeline_schedules +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `description` | string | yes | 管道进度表的描述 | +| `ref` | string | yes | 分支/标签名称将被触发 | +| `cron` | string | yes | cron(例如`0 1 * * *` )( [Cron 语法](https://en.wikipedia.org/wiki/Cron) ) | +| `cron_timezone` | string | no | `ActiveSupport::TimeZone`支持的时`ActiveSupport::TimeZone` (例如`Pacific Time (US & Canada)` )(默认值: `'UTC'` ) | +| `active` | boolean | no | 激活管道计划. 如果设置为 false,则管道调度最初将被停用(默认值: `true` ) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form description="Build packages" --form ref="master" --form cron="0 1 * * 5" --form cron_timezone="UTC" --form active="true" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules" +``` + +``` +{ "id": 14, "description": "Build packages", "ref": "master", "cron": "0 1 * * 5", "cron_timezone": "UTC", "next_run_at": "2017-05-26T01:00:00.000Z", "active": true, "created_at": "2017-05-19T13:43:08.169Z", "updated_at": "2017-05-19T13:43:08.169Z", "last_pipeline": null, "owner": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" } } +``` + +## Edit a pipeline schedule[](#edit-a-pipeline-schedule "Permalink") + +更新项目的管道计划. 更新完成后,将自动重新安排. + +``` +PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | +| `description` | string | no | 管道进度表的描述 | +| `ref` | string | no | 分支/标签名称将被触发 | +| `cron` | string | no | cron(例如`0 1 * * *` )( [Cron 语法](https://en.wikipedia.org/wiki/Cron) ) | +| `cron_timezone` | string | no | `ActiveSupport::TimeZone` (例如`Pacific Time (US & Canada)` )或`TZInfo::Timezone` (例如`America/Los_Angeles` )支持的`TZInfo::Timezone` | +| `active` | boolean | no | 激活管道计划. 如果设置为 false,则管道计划将首先停用. | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form cron="0 2 * * *" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13" +``` + +``` +{ "id": 13, "description": "Test schedule pipeline", "ref": "master", "cron": "0 2 * * *", "cron_timezone": "Asia/Tokyo", "next_run_at": "2017-05-19T17:00:00.000Z", "active": true, "created_at": "2017-05-19T13:31:08.849Z", "updated_at": "2017-05-19T13:44:16.135Z", "last_pipeline": { "id": 332, "sha": "0e788619d0b5ec17388dffb973ecd505946156db", "ref": "master", "status": "pending" }, "owner": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" } } +``` + +## Take ownership of a pipeline schedule[](#take-ownership-of-a-pipeline-schedule "Permalink") + +更新项目的管道计划的所有者. + +``` +POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/take_ownership +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/take_ownership" +``` + +``` +{ "id": 13, "description": "Test schedule pipeline", "ref": "master", "cron": "0 2 * * *", "cron_timezone": "Asia/Tokyo", "next_run_at": "2017-05-19T17:00:00.000Z", "active": true, "created_at": "2017-05-19T13:31:08.849Z", "updated_at": "2017-05-19T13:46:37.468Z", "last_pipeline": { "id": 332, "sha": "0e788619d0b5ec17388dffb973ecd505946156db", "ref": "master", "status": "pending" }, "owner": { "name": "shinya", "username": "maeda", "id": 50, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/8ca0a796a679c292e3a11da50f99e801?s=80&d=identicon", "web_url": "https://gitlab.example.com/maeda" } } +``` + +## Delete a pipeline schedule[](#delete-a-pipeline-schedule "Permalink") + +删除项目的管道计划. + +``` +DELETE /projects/:id/pipeline_schedules/:pipeline_schedule_id +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13" +``` + +``` +{ "id": 13, "description": "Test schedule pipeline", "ref": "master", "cron": "0 2 * * *", "cron_timezone": "Asia/Tokyo", "next_run_at": "2017-05-19T17:00:00.000Z", "active": true, "created_at": "2017-05-19T13:31:08.849Z", "updated_at": "2017-05-19T13:46:37.468Z", "last_pipeline": { "id": 332, "sha": "0e788619d0b5ec17388dffb973ecd505946156db", "ref": "master", "status": "pending" }, "owner": { "name": "shinya", "username": "maeda", "id": 50, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/8ca0a796a679c292e3a11da50f99e801?s=80&d=identicon", "web_url": "https://gitlab.example.com/maeda" } } +``` + +## Run a scheduled pipeline immediately[](#run-a-scheduled-pipeline-immediately "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/201786) . + +触发一个新的计划管道,该管道将立即运行. 该管道的下一个计划运行不受影响. + +``` +POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/play +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/42/pipeline_schedules/1/play" +``` + +响应示例: + +``` +{ "message": "201 Created" } +``` + +## Pipeline schedule variables[](#pipeline-schedule-variables "Permalink") + +在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34518) . + +## Create a new pipeline schedule variable[](#create-a-new-pipeline-schedule-variable "Permalink") + +创建管道计划的新变量. + +``` +POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | +| `key` | string | yes | 变量的`key` ; 不得超过 255 个字符; 仅允许`AZ` , `az` , `0-9`和`_` | +| `value` | string | yes | 变量的`value` | +| `variable_type` | string | no | 变量的类型. 可用类型为: `env_var` (默认)和`file` | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "key=NEW_VARIABLE" --form "value=new value" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables" +``` + +``` +{ "key": "NEW_VARIABLE", "variable_type": "env_var", "value": "new value" } +``` + +## Edit a pipeline schedule variable[](#edit-a-pipeline-schedule-variable "Permalink") + +更新管道计划的变量. + +``` +PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | +| `key` | string | yes | 变量的`key` | +| `value` | string | yes | 变量的`value` | +| `variable_type` | string | no | 变量的类型. 可用类型为: `env_var` (默认)和`file` | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form "value=updated value" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables/NEW_VARIABLE" +``` + +``` +{ "key": "NEW_VARIABLE", "value": "updated value" "variable_type": "env_var", } +``` + +## Delete a pipeline schedule variable[](#delete-a-pipeline-schedule-variable "Permalink") + +删除管道计划的变量. + +``` +DELETE /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_schedule_id` | integer | yes | 管道时间表 ID | +| `key` | string | yes | 变量的`key` | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables/NEW_VARIABLE" +``` + +``` +{ "key": "NEW_VARIABLE", "value": "updated value" } +``` \ No newline at end of file diff --git a/docs/346.md b/docs/346.md new file mode 100644 index 0000000000000000000000000000000000000000..3d496d731698bc2143362b3049c45f002f7b233f --- /dev/null +++ b/docs/346.md @@ -0,0 +1,114 @@ +# Pipeline triggers API + +> 原文:[https://docs.gitlab.com/ee/api/pipeline_triggers.html](https://docs.gitlab.com/ee/api/pipeline_triggers.html) + +* [List project triggers](#list-project-triggers) +* [Get trigger details](#get-trigger-details) +* [Create a project trigger](#create-a-project-trigger) +* [Update a project trigger](#update-a-project-trigger) +* [Remove a project trigger](#remove-a-project-trigger) + +# Pipeline triggers API[](#pipeline-triggers-api "Permalink") + +您可以阅读有关[通过 API 触发管道的](../ci/triggers/README.html)更多信息. + +## List project triggers[](#list-project-triggers "Permalink") + +获取项目的构建触发器的列表. + +``` +GET /projects/:id/triggers +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/triggers" +``` + +``` +[ { "id": 10, "description": "my trigger", "created_at": "2016-01-07T09:53:58.235Z", "last_used": null, "token": "6d056f63e50fe6f8c5f8f4aa10edb7", "updated_at": "2016-01-07T09:53:58.235Z", "owner": null } ] +``` + +## Get trigger details[](#get-trigger-details "Permalink") + +获取项目构建触发器的详细信息. + +``` +GET /projects/:id/triggers/:trigger_id +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `trigger_id` | integer | yes | 触发 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/triggers/5" +``` + +``` +{ "id": 10, "description": "my trigger", "created_at": "2016-01-07T09:53:58.235Z", "last_used": null, "token": "6d056f63e50fe6f8c5f8f4aa10edb7", "updated_at": "2016-01-07T09:53:58.235Z", "owner": null } +``` + +## Create a project trigger[](#create-a-project-trigger "Permalink") + +为项目创建触发器. + +``` +POST /projects/:id/triggers +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `description` | string | yes | 触发名称 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers" +``` + +``` +{ "id": 10, "description": "my trigger", "created_at": "2016-01-07T09:53:58.235Z", "last_used": null, "token": "6d056f63e50fe6f8c5f8f4aa10edb7", "updated_at": "2016-01-07T09:53:58.235Z", "owner": null } +``` + +## Update a project trigger[](#update-a-project-trigger "Permalink") + +更新项目的触发器. + +``` +PUT /projects/:id/triggers/:trigger_id +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `trigger_id` | integer | yes | 触发 ID | +| `description` | string | no | 触发名称 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers/10" +``` + +``` +{ "id": 10, "description": "my trigger", "created_at": "2016-01-07T09:53:58.235Z", "last_used": null, "token": "6d056f63e50fe6f8c5f8f4aa10edb7", "updated_at": "2016-01-07T09:53:58.235Z", "owner": null } +``` + +## Remove a project trigger[](#remove-a-project-trigger "Permalink") + +删除项目的生成触发器. + +``` +DELETE /projects/:id/triggers/:trigger_id +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `trigger_id` | integer | yes | 触发 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/triggers/5" +``` \ No newline at end of file diff --git a/docs/347.md b/docs/347.md new file mode 100644 index 0000000000000000000000000000000000000000..84235d2fc1b98ef65229e1758929d9a96ab46620 --- /dev/null +++ b/docs/347.md @@ -0,0 +1,219 @@ +# Pipelines API + +> 原文:[https://docs.gitlab.com/ee/api/pipelines.html](https://docs.gitlab.com/ee/api/pipelines.html) + +* [Single Pipeline Requests](#single-pipeline-requests) +* [Pipelines pagination](#pipelines-pagination) +* [List project pipelines](#list-project-pipelines) +* [Get a single pipeline](#get-a-single-pipeline) + * [Get variables of a pipeline](#get-variables-of-a-pipeline) + * [Get a pipeline’s test report](#get-a-pipelines-test-report) +* [Create a new pipeline](#create-a-new-pipeline) +* [Retry jobs in a pipeline](#retry-jobs-in-a-pipeline) +* [Cancel a pipeline’s jobs](#cancel-a-pipelines-jobs) +* [Delete a pipeline](#delete-a-pipeline) + +# Pipelines API[](#pipelines-api "Permalink") + +## Single Pipeline Requests[](#single-pipeline-requests "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36494) . + +请求有关单个管道的信息的端点返回任何管道的数据. 在 13.2 之前, [对子管道的](../ci/parent_child_pipelines.html)请求返回了 404 错误. + +## Pipelines pagination[](#pipelines-pagination "Permalink") + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +## List project pipelines[](#list-project-pipelines "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) + +``` +GET /projects/:id/pipelines +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `scope` | string | no | 管道的范围,其中之一: `running` , `pending` , `finished` , `branches` , `tags` | +| `status` | string | no | 管道的状态,其中之一: `running` , `pending` , `success` , `failed` , `canceled` , `skipped` , `created` , `manual` | +| `ref` | string | no | 管道的引用 | +| `sha` | string | no | 管道的 SHA | +| `yaml_errors` | boolean | no | 返回无效配置的管道 | +| `name` | string | no | 触发管道的用户名 | +| `username` | string | no | 触发管道的用户的用户名 | +| `updated_after` | datetime | no | 返回在指定日期之后更新的管道. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `updated_before` | datetime | no | 返回在指定日期之前更新的管道. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `order_by` | string | no | 按`id` , `status` , `ref` , `updated_at`或`user_id` `updated_at`管道(默认值: `id` ) | +| `sort` | string | no | 按`asc`或`desc`顺序对管道进行排序(默认值: `desc` ) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines" +``` + +回应范例 + +``` +[ { "id": 47, "status": "pending", "ref": "new-pipeline", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "web_url": "https://example.com/foo/bar/pipelines/47", "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", }, { "id": 48, "status": "pending", "ref": "new-pipeline", "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a", "web_url": "https://example.com/foo/bar/pipelines/48", "created_at": "2016-08-12T10:06:04.561Z", "updated_at": "2016-08-12T10:09:56.223Z", } ] +``` + +## Get a single pipeline[](#get-a-single-pipeline "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) + +``` +GET /projects/:id/pipelines/:pipeline_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_id` | integer | yes | 管道的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/46" +``` + +回应范例 + +``` +{ "id": 46, "status": "success", "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "tag": false, "yaml_errors": null, "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "started_at": null, "finished_at": "2016-08-11T11:32:35.145Z", "committed_at": null, "duration": null, "coverage": "30.0", "web_url": "https://example.com/foo/bar/pipelines/46" } +``` + +### Get variables of a pipeline[](#get-variables-of-a-pipeline "Permalink") + +``` +GET /projects/:id/pipelines/:pipeline_id/variables +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_id` | integer | yes | 管道的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/46/variables" +``` + +回应范例 + +``` +[ { "key": "RUN_NIGHTLY_BUILD", "variable_type": "env_var", "value": "true" }, { "key": "foo", "value": "bar" } ] +``` + +### Get a pipeline’s test report[](#get-a-pipelines-test-report "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/202525) . + +**警告:**此 API 路由是[JUnit 测试报告](../ci/junit_test_reports.html)功能的一部分. 它受一个[功能标志](../development/feature_flags/index.html)保护,该[功能标志](../development/feature_flags/index.html)由于非常大的数据集的性能问题而被**禁用** . + +``` +GET /projects/:id/pipelines/:pipeline_id/test_report +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_id` | integer | yes | The ID of a pipeline | + +样品要求: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/46/test_report" +``` + +样本回复: + +``` +{ "total_time": 5, "total_count": 1, "success_count": 1, "failed_count": 0, "skipped_count": 0, "error_count": 0, "test_suites": [ { "name": "Secure", "total_time": 5, "total_count": 1, "success_count": 1, "failed_count": 0, "skipped_count": 0, "error_count": 0, "test_cases": [ { "status": "success", "name": "Security Reports can create an auto-remediation MR", "classname": "vulnerability_management_spec", "execution_time": 5, "system_output": null, "stack_trace": null } ] } ] } +``` + +## Create a new pipeline[](#create-a-new-pipeline "Permalink") + +在 GitLab 8.14 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7209) + +``` +POST /projects/:id/pipeline +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `ref` | string | yes | 提交参考 | +| `variables` | array | no | 包含管道中可用变量的数组,与结构`[{ 'key' => 'UPLOAD_TO_S3', 'variable_type' => 'file', 'value' => 'true' }]`匹配 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipeline?ref=master" +``` + +回应范例 + +``` +{ "id": 61, "sha": "384c444e840a515b23f21915ee5766b87068a70d", "ref": "master", "status": "pending", "before_sha": "0000000000000000000000000000000000000000", "tag": false, "yaml_errors": null, "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2016-11-04T09:36:13.747Z", "updated_at": "2016-11-04T09:36:13.977Z", "started_at": null, "finished_at": null, "committed_at": null, "duration": null, "coverage": null, "web_url": "https://example.com/foo/bar/pipelines/61" } +``` + +## Retry jobs in a pipeline[](#retry-jobs-in-a-pipeline "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) + +``` +POST /projects/:id/pipelines/:pipeline_id/retry +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_id` | integer | yes | 管道的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/46/retry" +``` + +Response: + +``` +{ "id": 46, "status": "pending", "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "tag": false, "yaml_errors": null, "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "started_at": null, "finished_at": "2016-08-11T11:32:35.145Z", "committed_at": null, "duration": null, "coverage": null, "web_url": "https://example.com/foo/bar/pipelines/46" } +``` + +## Cancel a pipeline’s jobs[](#cancel-a-pipelines-jobs "Permalink") + +在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) + +``` +POST /projects/:id/pipelines/:pipeline_id/cancel +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_id` | integer | yes | 管道的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/46/cancel" +``` + +Response: + +``` +{ "id": 46, "status": "canceled", "ref": "master", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "tag": false, "yaml_errors": null, "user": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "started_at": null, "finished_at": "2016-08-11T11:32:35.145Z", "committed_at": null, "duration": null, "coverage": null, "web_url": "https://example.com/foo/bar/pipelines/46" } +``` + +## Delete a pipeline[](#delete-a-pipeline "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22988) . + +``` +DELETE /projects/:id/pipelines/:pipeline_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `pipeline_id` | integer | yes | 管道的 ID | + +``` +curl --header "PRIVATE-TOKEN: " --request "DELETE" "https://gitlab.example.com/api/v4/projects/1/pipelines/46" +``` \ No newline at end of file diff --git a/docs/348.md b/docs/348.md new file mode 100644 index 0000000000000000000000000000000000000000..eddaf608261ae8152e4124e7b48c1b1d0f558cbd --- /dev/null +++ b/docs/348.md @@ -0,0 +1,99 @@ +# Project Aliases API + +> 原文:[https://docs.gitlab.com/ee/api/project_aliases.html](https://docs.gitlab.com/ee/api/project_aliases.html) + +* [List all project aliases](#list-all-project-aliases) +* [Get project alias’ details](#get-project-alias-details) +* [Create a project alias](#create-a-project-alias) +* [Delete a project alias](#delete-a-project-alias) + +# Project Aliases API[](#project-aliases-api-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3264) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.1. + +所有方法都需要管理员授权. + +## List all project aliases[](#list-all-project-aliases "Permalink") + +获取所有项目别名的列表: + +``` +GET /project_aliases +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_aliases" +``` + +响应示例: + +``` +[ { "id": 1, "project_id": 1, "name": "gitlab-foss" }, { "id": 2, "project_id": 2, "name": "gitlab" } ] +``` + +## Get project alias’ details[](#get-project-alias-details "Permalink") + +获取项目别名的详细信息: + +``` +GET /project_aliases/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | string | yes | 别名的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_aliases/gitlab" +``` + +响应示例: + +``` +{ "id": 1, "project_id": 1, "name": "gitlab" } +``` + +## Create a project alias[](#create-a-project-alias "Permalink") + +为项目添加新的别名. 成功时回应 201,当验证错误时回应 400(例如别名已经存在): + +``` +POST /project_aliases +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `project_id` | integer/string | yes | 项目的 ID 或路径. | +| `name` | string | yes | 别名的名称. 必须是唯一的. | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_aliases" --form "project_id=1" --form "name=gitlab" +``` + +or + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_aliases" --form "project_id=gitlab-org/gitlab" --form "name=gitlab" +``` + +响应示例: + +``` +{ "id": 1, "project_id": 1, "name": "gitlab" } +``` + +## Delete a project alias[](#delete-a-project-alias "Permalink") + +删除项目别名. 存在项目别名时以 204 响应,如果不存在则以 404 响应: + +``` +DELETE /project_aliases/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | string | yes | 别名的名称 | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_aliases/gitlab" +``` \ No newline at end of file diff --git a/docs/349.md b/docs/349.md new file mode 100644 index 0000000000000000000000000000000000000000..d40dd391e57b2ffa059f7465d1d05eb516136fb3 --- /dev/null +++ b/docs/349.md @@ -0,0 +1,191 @@ +# Project import/export API + +> 原文:[https://docs.gitlab.com/ee/api/project_import_export.html](https://docs.gitlab.com/ee/api/project_import_export.html) + +* [Schedule an export](#schedule-an-export) +* [Export status](#export-status) +* [Export download](#export-download) +* [Import a file](#import-a-file) +* [Import status](#import-status) + +# Project import/export API[](#project-importexport-api "Permalink") + +在 GitLab 10.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41899) . + +也可以看看: + +* [Project import/export documentation](../user/project/settings/import_export.html). +* [Project import/export administration Rake tasks](../administration/raketasks/project_import_export.html). + +## Schedule an export[](#schedule-an-export "Permalink") + +开始新的导出. + +端点还接受`upload`参数. 此参数是一个哈希,其中包含将导出的项目上载到 Web 服务器或任何 S3 兼容平台的所有必要信息. 目前,我们仅支持将二进制数据文件上传到最终服务器. + +从 GitLab 10.7 开始,如果存在`upload`参数,则需要`upload[url]`参数. + +``` +POST /projects/:id/export +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `description` | string | no | 覆盖项目描述 | +| `upload` | hash | no | Hash that contains the information to upload the exported project to a web server | +| `upload[url]` | string | yes | 上传项目的网址 | +| `upload[http_method]` | string | no | 上传输出项目的 HTTP 方法. 仅允许使用`PUT`和`POST`方法. 默认为`PUT` | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/export" \ + --data "upload[http_method]=PUT" \ + --data-urlencode "upload[url]=https://example-bucket.s3.eu-west-3.amazonaws.com/backup?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIMBJHN2O62W8IELQ%2F20180312%2Feu-west-3%2Fs3%2Faws4_request&X-Amz-Date=20180312T110328Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=8413facb20ff33a49a147a0b4abcff4c8487cc33ee1f7e450c46e8f695569dbd" +``` + +``` +{ "message": "202 Accepted" } +``` + +**注意:**上载请求将与`Content-Type: application/gzip`标头一起发送. 确保您的预签名 URL 将此内容作为签名的一部分. + +## Export status[](#export-status "Permalink") + +获取导出状态. + +``` +GET /projects/:id/export +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/export" +``` + +状态可以是以下之一: + +* `none` +* `queued` +* `started` +* `finished` +* `regeneration_in_progress` + +`queued`状态表示已接收到导出请求,并且当前处于要处理的队列中. + +`started`状态表示导出过程已开始并且当前正在进行中. 它包括导出过程,对生成的文件执行的操作,例如发送电子邮件通知用户下载文件,将导出的文件上传到 Web 服务器等. + +`finished`状态是在导出过程完成并且已通知用户之后. + +`regeneration_in_progress`是可以下载导出文件且正在处理生成新导出文件的请求. + +`_links`仅在导出完成时存在. + +``` +{ "id": 1, "description": "Itaque perspiciatis minima aspernatur corporis consequatur.", "name": "Gitlab Test", "name_with_namespace": "Gitlab Org / Gitlab Test", "path": "gitlab-test", "path_with_namespace": "gitlab-org/gitlab-test", "created_at": "2017-08-29T04:36:44.383Z", "export_status": "finished", "_links": { "api_url": "https://gitlab.example.com/api/v4/projects/1/export/download", "web_url": "https://gitlab.example.com/gitlab-org/gitlab-test/download_export", } } +``` + +## Export download[](#export-download "Permalink") + +下载完成的导出. + +``` +GET /projects/:id/export/download +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " --remote-header-name --remote-name "https://gitlab.example.com/api/v4/projects/5/export/download" +``` + +``` +ls *export.tar.gz +2017-12-05_22-11-148_namespace_project_export.tar.gz +``` + +## Import a file[](#import-a-file "Permalink") + +``` +POST /projects/import +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `namespace` | integer/string | no | 项目将导入到的名称空间的 ID 或路径. 默认为当前用户的名称空间 | +| `name` | string | no | 要导入的项目的名称. 如果未提供,则默认为项目的路径 | +| `file` | string | yes | 要上传的文件 | +| `path` | string | yes | 新项目的名称和路径 | +| `overwrite` | boolean | no | 如果存在具有相同路径的项目,则导入将覆盖它. 默认为假 | +| `override_params` | Hash | no | 支持在[Project API 中](projects.html)定义的所有字段 | + +传递的覆盖参数将优先于导出文件中定义的所有值. + +要从文件系统上载文件,请使用`--form`参数. 这将导致 cURL 使用标题`Content-Type: multipart/form-data` . `file=`参数必须指向文件系统上的文件,并以`@`开头. 例如: + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "path=api-project" --form "file=@/path/to/file" "https://gitlab.example.com/api/v4/projects/import" +``` + +cURL 不支持从远程服务器发布文件. 从远程服务器导入项目可以通过以下方式完成: + +``` +import requests +from io import BytesIO + +s3_file = requests.get(presigned_url) + +url = 'https://gitlab.example.com/api/v4/projects/import' +files = {'file': ('file.tar.gz', BytesIO(s3_file.content))} +data = { + "path": "example-project", + "namespace": "example-group" +} +headers = { + 'Private-Token': "" +} + +requests.post(url, headers=headers, data=data, files=files) +``` + +``` +{ "id": 1, "description": null, "name": "api-project", "name_with_namespace": "Administrator / api-project", "path": "api-project", "path_with_namespace": "root/api-project", "created_at": "2018-02-13T09:05:58.023Z", "import_status": "scheduled", "correlation_id": "mezklWso3Za", "failed_relations": [] } +``` + +**注意:**可以由管理员设置最大导入文件大小,默认为 50MB. 作为管理员,您可以修改最大导入文件大小. 为此,请在" [应用程序设置" API](settings.html#change-application-settings)或" [管理界面"中](../user/admin_area/settings/account_and_limit_settings.html)使用`max_import_size`选项. + +## Import status[](#import-status "Permalink") + +获取导入状态. + +``` +GET /projects/:id/import +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/import" +``` + +状态可以是以下之一: + +* `none` +* `scheduled` +* `failed` +* `started` +* `finished` + +如果状态`failed` ,它将在`import_error`下包含导入错误消息. 如果状态为`failed` , `started`或`finished`时, `failed_relations`阵列可能与关系的任何事件未能导入无论是由于不可恢复的错误或因重试次数已经用尽被填充(一个典型的例子是查询超时.) + +**注意:** `failed_relations`的元素的`id`字段引用失败记录,而不是关系.**注意:** `failed_relations`数组当前限制为 100 个项目. + +``` +{ "id": 1, "description": "Itaque perspiciatis minima aspernatur corporis consequatur.", "name": "Gitlab Test", "name_with_namespace": "Gitlab Org / Gitlab Test", "path": "gitlab-test", "path_with_namespace": "gitlab-org/gitlab-test", "created_at": "2017-08-29T04:36:44.383Z", "import_status": "started", "correlation_id": "mezklWso3Za", "failed_relations": [ { "id": 42, "created_at": "2020-04-02T14:48:59.526Z", "exception_class": "RuntimeError", "exception_message": "A failure occurred", "source": "custom error context", "relation_name": "merge_requests" } ] } +``` \ No newline at end of file diff --git a/docs/350.md b/docs/350.md new file mode 100644 index 0000000000000000000000000000000000000000..b81ac1e5cb6dd6aeb89bc47c80612f69464aaa21 --- /dev/null +++ b/docs/350.md @@ -0,0 +1,136 @@ +# Project repository storage moves API + +> 原文:[https://docs.gitlab.com/ee/api/project_repository_storage_moves.html](https://docs.gitlab.com/ee/api/project_repository_storage_moves.html) + +* [Retrieve all project repository storage moves](#retrieve-all-project-repository-storage-moves) +* [Retrieve all repository storage moves for a project](#retrieve-all-repository-storage-moves-for-a-project) +* [Get a single project repository storage move](#get-a-single-project-repository-storage-move) +* [Get a single repository storage move for a project](#get-a-single-repository-storage-move-for-a-project) +* [Schedule a repository storage move for a project](#schedule-a-repository-storage-move-for-a-project) + +# Project repository storage moves API[](#project-repository-storage-moves-api-core-only "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31285) . + +项目存储库存储可以移动. 要使用 API​​检索项目存储库存储移动,您必须以管理员[身份进行身份验证](README.html#authentication) . + +## Retrieve all project repository storage moves[](#retrieve-all-project-repository-storage-moves "Permalink") + +``` +GET /project_repository_storage_moves +``` + +默认情况下,因为 API 结果是[分页的](README.html#pagination) ,所以`GET`请求一次返回 20 个结果. + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_repository_storage_moves" +``` + +响应示例: + +``` +[ { "id": 1, "created_at": "2020-05-07T04:27:17.234Z", "state": "scheduled", "source_storage_name": "default", "destination_storage_name": "storage2", "project": { "id": 1, "description": null, "name": "project1", "name_with_namespace": "John Doe2 / project1", "path": "project1", "path_with_namespace": "namespace1/project1", "created_at": "2020-05-07T04:27:17.016Z" } ] +``` + +## Retrieve all repository storage moves for a project[](#retrieve-all-repository-storage-moves-for-a-project "Permalink") + +``` +GET /projects/:project_id/repository_storage_moves +``` + +默认情况下,因为 API 结果是[分页的](README.html#pagination) ,所以`GET`请求一次返回 20 个结果. + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `project_id` | integer | yes | 项目编号 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/repository_storage_moves" +``` + +响应示例: + +``` +[ { "id": 1, "created_at": "2020-05-07T04:27:17.234Z", "state": "scheduled", "source_storage_name": "default", "destination_storage_name": "storage2", "project": { "id": 1, "description": null, "name": "project1", "name_with_namespace": "John Doe2 / project1", "path": "project1", "path_with_namespace": "namespace1/project1", "created_at": "2020-05-07T04:27:17.016Z" } ] +``` + +## Get a single project repository storage move[](#get-a-single-project-repository-storage-move "Permalink") + +``` +GET /project_repository_storage_moves/:repository_storage_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `repository_storage_id` | integer | yes | 项目存储库存储移动的标识 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/project_repository_storage_moves/1" +``` + +响应示例: + +``` +{ "id": 1, "created_at": "2020-05-07T04:27:17.234Z", "state": "scheduled", "source_storage_name": "default", "destination_storage_name": "storage2", "project": { "id": 1, "description": null, "name": "project1", "name_with_namespace": "John Doe2 / project1", "path": "project1", "path_with_namespace": "namespace1/project1", "created_at": "2020-05-07T04:27:17.016Z" } +``` + +## Get a single repository storage move for a project[](#get-a-single-repository-storage-move-for-a-project "Permalink") + +``` +GET /projects/:project_id/repository_storage_moves/:repository_storage_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `project_id` | integer | yes | 项目编号 | +| `repository_storage_id` | integer | yes | 项目存储库存储移动的标识 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/repository_storage_moves/1" +``` + +响应示例: + +``` +{ "id": 1, "created_at": "2020-05-07T04:27:17.234Z", "state": "scheduled", "source_storage_name": "default", "destination_storage_name": "storage2", "project": { "id": 1, "description": null, "name": "project1", "name_with_namespace": "John Doe2 / project1", "path": "project1", "path_with_namespace": "namespace1/project1", "created_at": "2020-05-07T04:27:17.016Z" } +``` + +## Schedule a repository storage move for a project[](#schedule-a-repository-storage-move-for-a-project "Permalink") + +``` +POST /projects/:project_id/repository_storage_moves +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `project_id` | integer | yes | 项目编号 | +| `destination_storage_name` | string | yes | 目标存储分片的名称 | + +请求示例: + +``` +curl --request POST --header "PRIVATE_TOKEN: " --header "Content-Type: application/json" \ +--data '{"destination_storage_name":"storage2"}' "https://gitlab.example.com/api/v4/projects/1/repository_storage_moves" +``` + +响应示例: + +``` +{ "id": 1, "created_at": "2020-05-07T04:27:17.234Z", "state": "scheduled", "source_storage_name": "default", "destination_storage_name": "storage2", "project": { "id": 1, "description": null, "name": "project1", "name_with_namespace": "John Doe2 / project1", "path": "project1", "path_with_namespace": "namespace1/project1", "created_at": "2020-05-07T04:27:17.016Z" } +``` \ No newline at end of file diff --git a/docs/351.md b/docs/351.md new file mode 100644 index 0000000000000000000000000000000000000000..c9ac08338397420fd47bace46a3c716033af5204 --- /dev/null +++ b/docs/351.md @@ -0,0 +1,27 @@ +# Project statistics API + +> 原文:[https://docs.gitlab.com/ee/api/project_statistics.html](https://docs.gitlab.com/ee/api/project_statistics.html) + +* [Get the statistics of the last 30 days](#get-the-statistics-of-the-last-30-days) + +# Project statistics API[](#project-statistics-api "Permalink") + +每个对[项目](../user/project/index.html)统计信息的 API 调用都必须经过验证. + +## Get the statistics of the last 30 days[](#get-the-statistics-of-the-last-30-days "Permalink") + +检索统计信息需要对存储库的写权限. 当前仅返回 HTTP 提取统计信息. 提取统计信息包括克隆和提取计数,并且仅用于 HTTP,不包括 SSH 提取. + +``` +GET /projects/:id/statistics +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数/字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +响应示例: + +``` +{ "fetches": { "total": 50, "days": [ { "count": 10, "date": "2018-01-10" }, { "count": 10, "date": "2018-01-09" }, { "count": 10, "date": "2018-01-08" }, { "count": 10, "date": "2018-01-07" }, { "count": 10, "date": "2018-01-06" } ] } } +``` \ No newline at end of file diff --git a/docs/352.md b/docs/352.md new file mode 100644 index 0000000000000000000000000000000000000000..83ca4b1f6f17dede312511308c29e267442a70de --- /dev/null +++ b/docs/352.md @@ -0,0 +1,66 @@ +# Project templates API + +> 原文:[https://docs.gitlab.com/ee/api/project_templates.html](https://docs.gitlab.com/ee/api/project_templates.html) + +* [Get all templates of a particular type](#get-all-templates-of-a-particular-type) +* [Get one template of a particular type](#get-one-template-of-a-particular-type) + +# Project templates API[](#project-templates-api "Permalink") + +此 API 是这些端点的特定于项目的版本: + +* [Dockerfile templates](templates/dockerfiles.html) +* [Gitignore templates](templates/gitignores.html) +* [GitLab CI/CD Configuration templates](templates/gitlab_ci_ymls.html) +* [Open source license templates](templates/licenses.html) + +它不赞成使用这些端点,对​​于 API 版本 5 将会删除这些端点. + +除了整个实例通用的模板之外,该 API 端点还提供特定于项目的模板. + +在以后的[版本中,](../user/project/description_templates.html)将添加对[发布和合并请求模板的](../user/project/description_templates.html)支持. + +支持[组级文件模板](../user/group/index.html#group-file-templates-premium) 是在 GitLab 11.5 中[添加的](https://gitlab.com/gitlab-org/gitlab/-/issues/5987) + +## Get all templates of a particular type[](#get-all-templates-of-a-particular-type "Permalink") + +``` +GET /projects/:id/templates/:type +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数/字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `type` | string | yes | 模板的类型`(dockerfiles|gitignores|gitlab_ci_ymls|licenses)` | + +响应示例(许可证): + +``` +[ { "key": "epl-1.0", "name": "Eclipse Public License 1.0" }, { "key": "lgpl-3.0", "name": "GNU Lesser General Public License v3.0" }, { "key": "unlicense", "name": "The Unlicense" }, { "key": "agpl-3.0", "name": "GNU Affero General Public License v3.0" }, { "key": "gpl-3.0", "name": "GNU General Public License v3.0" }, { "key": "bsd-3-clause", "name": "BSD 3-clause \"New\" or \"Revised\" License" }, { "key": "lgpl-2.1", "name": "GNU Lesser General Public License v2.1" }, { "key": "mit", "name": "MIT License" }, { "key": "apache-2.0", "name": "Apache License 2.0" }, { "key": "bsd-2-clause", "name": "BSD 2-clause \"Simplified\" License" }, { "key": "mpl-2.0", "name": "Mozilla Public License 2.0" }, { "key": "gpl-2.0", "name": "GNU General Public License v2.0" } ] +``` + +## Get one template of a particular type[](#get-one-template-of-a-particular-type "Permalink") + +``` +GET /projects/:id/templates/:type/:key +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数/字符串 | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `type` | string | yes | 模板的类型`(dockerfiles|gitignores|gitlab_ci_ymls|licenses)` | +| `key` | string | yes | 从集合端点获取的模板的密钥 | +| `project` | string | no | 在模板中扩展占位符时要使用的项目名称. 仅影响许可证 | +| `fullname` | string | no | 在模板中扩展占位符时使用的版权所有者的全名. 仅影响许可证 | + +响应示例(Dockerfile): + +``` +{ "name": "Binary", "content": "# This file is a template, and might need editing before it works on your project.\n# This Dockerfile installs a compiled binary into a bare system.\n# You must either commit your compiled binary into source control (not recommended)\n# or build the binary first as part of a CI/CD pipeline.\n\nFROM buildpack-deps:jessie\n\nWORKDIR /usr/local/bin\n\n# Change `app` to whatever your binary is called\nAdd app .\nCMD [\"./app\"]\n" } +``` + +响应示例(许可证): + +``` +{ "key": "mit", "name": "MIT License", "nickname": null, "popular": true, "html_url": "http://choosealicense.com/licenses/mit/", "source_url": "https://opensource.org/licenses/MIT", "description": "A short and simple permissive license with conditions only requiring preservation of copyright and license notices. Licensed works, modifications, and larger works may be distributed under different terms and without source code.", "conditions": [ "include-copyright" ], "permissions": [ "commercial-use", "modifications", "distribution", "private-use" ], "limitations": [ "liability", "warranty" ], "content": "MIT License\n\nCopyright (c) 2018 [fullname]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" } +``` \ No newline at end of file diff --git a/docs/353.md b/docs/353.md new file mode 100644 index 0000000000000000000000000000000000000000..e098157aab143ab518f835b06845455153079db3 --- /dev/null +++ b/docs/353.md @@ -0,0 +1,1059 @@ +# Projects API + +> 原文:[https://docs.gitlab.com/ee/api/projects.html](https://docs.gitlab.com/ee/api/projects.html) + +* [Project visibility level](#project-visibility-level) +* [Project merge method](#project-merge-method) +* [List all projects](#list-all-projects) + * [Pagination limits](#pagination-limits) +* [List user projects](#list-user-projects) +* [List projects starred by a user](#list-projects-starred-by-a-user) +* [Get single project](#get-single-project) +* [Get project users](#get-project-users) +* [Get project events](#get-project-events) +* [Create project](#create-project) +* [Create project for user](#create-project-for-user) +* [Edit project](#edit-project) +* [Fork project](#fork-project) +* [List Forks of a project](#list-forks-of-a-project) +* [Star a project](#star-a-project) +* [Unstar a project](#unstar-a-project) +* [List Starrers of a project](#list-starrers-of-a-project) +* [Languages](#languages) +* [Archive a project](#archive-a-project) +* [Unarchive a project](#unarchive-a-project) +* [Remove project](#remove-project) +* [Restore project marked for deletion](#restore-project-marked-for-deletion-premium) +* [Upload a file](#upload-a-file) +* [Share project with group](#share-project-with-group) +* [Delete a shared project link within a group](#delete-a-shared-project-link-within-a-group) +* [Hooks](#hooks) + * [List project hooks](#list-project-hooks) + * [Get project hook](#get-project-hook) + * [Add project hook](#add-project-hook) + * [Edit project hook](#edit-project-hook) + * [Delete project hook](#delete-project-hook) +* [Fork relationship](#fork-relationship) + * [Create a forked from/to relation between existing projects](#create-a-forked-fromto-relation-between-existing-projects) + * [Delete an existing forked from relationship](#delete-an-existing-forked-from-relationship) +* [Search for projects by name](#search-for-projects-by-name) +* [Start the Housekeeping task for a Project](#start-the-housekeeping-task-for-a-project) +* [Push Rules](#push-rules-starter) + * [Get project push rules](#get-project-push-rules) + * [Add project push rule](#add-project-push-rule) + * [Edit project push rule](#edit-project-push-rule) + * [Delete project push rule](#delete-project-push-rule) +* [Transfer a project to a new namespace](#transfer-a-project-to-a-new-namespace) +* [Branches](#branches) +* [Project Import/Export](#project-importexport) +* [Project members](#project-members) +* [Start the pull mirroring process for a Project](#start-the-pull-mirroring-process-for-a-project-starter) +* [Project badges](#project-badges) +* [Issue and merge request description templates](#issue-and-merge-request-description-templates) +* [Download snapshot of a Git repository](#download-snapshot-of-a-git-repository) + +# Projects API[](#projects-api "Permalink") + +## Project visibility level[](#project-visibility-level "Permalink") + +GitLab 中的项目可以是私有的,内部的或公共的. 这由项目中的`visibility`字段确定. + +项目可见性级别的值为: + +* `private` :必须为每个用户显式授予项目访问权限. +* `internal` :任何登录的用户都可以克隆该项目. +* `public` :无需任何身份验证即可访问该项目. + +## Project merge method[](#project-merge-method "Permalink") + +`merge_method`当前有三个选项可供选择: + +* `merge` :为每个合并创建一个合并提交,只要没有冲突就允许合并. +* `rebase_merge` :为每个合并创建一个合并提交,但是仅当可能进行快速合并时才允许合并. 这样,您可以确保在合并到目标分支后,如果此合并请求将生成,则该请求也将生成. +* `ff` :没有创建合并提交,并且所有合并都被快速转发,这意味着仅当分支可以被快速转发时才允许合并. + +## List all projects[](#list-all-projects "Permalink") + +获取已认证用户跨 GitLab 的所有可见项目的列表. 在未经身份验证的情况下访问时,仅返回带有"简单"字段的公共项目. + +``` +GET /projects +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `archived` | boolean | no | 受存档状态限制 | +| `visibility` | string | no | 受`public` , `internal`或`private`可见性的限制 | +| `order_by` | string | no | 返回按`id` , `name` , `path` , `created_at` , `updated_at`或`last_activity_at`字段排序的项目. 只有管​​理员可以使用`repository_size` , `storage_size`或`wiki_size`字段. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的项目. 默认为`desc` | +| `search` | string | no | 返回符合搜索条件的项目列表 | +| `search_namespaces` | boolean | no | 匹配搜索条件时包括祖先名称空间. 默认为`false` | +| `simple` | boolean | no | 仅返回每个项目的有限字段. 这是没有身份验证的无操作操作,因为这样*只会*返回简单的字段. | +| `owned` | boolean | no | 受当前用户明确拥有的项目限制 | +| `membership` | boolean | no | 受当前用户是其成员的项目的限制 | +| `starred` | boolean | no | 受当前用户加注星标的项目限制 | +| `statistics` | boolean | no | 包括项目统计 | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | +| `with_issues_enabled` | boolean | no | 受启用的问题限制功能 | +| `with_merge_requests_enabled` | boolean | no | 通过启用的合并请求限制功能 | +| `with_programming_language` | string | no | 受使用给定编程语言的项目限制 | +| `wiki_checksum_failed` | boolean | no | 限制维基校验和计算失败的项目(在[GitLab Premium](https://about.gitlab.com/pricing/) 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) ) | +| `repository_checksum_failed` | boolean | no | 限制存储库校验和计算失败的项目(在[GitLab Premium](https://about.gitlab.com/pricing/) 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) ) | +| `min_access_level` | integer | no | 受当前用户的最小[访问权限](members.html)限制 | +| `id_after` | integer | no | 将结果限制为 ID 大于指定 ID 的项目 | +| `id_before` | integer | no | 将结果限制为 ID 小于指定 ID 的项目 | +| `last_activity_after` | datetime | no | 在指定时间后,将结果限制为具有 last_activity 的项目. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `last_activity_before` | datetime | no | 将结果限制为在指定时间之前具有 last_activity 的项目. 格式:ISO 8601 YYYY-MM-DDTHH:MM:SSZ | +| `repository_storage` | string | no | 将结果限制为存储在 repository_storage 上的项目. 仅适用于管理员. | + +**注意:**此端点支持所选`order_by`选项的[键集分页](README.html#keyset-based-pagination) . + +当`simple=true`或用户未经身份验证时,这将返回如下内容: + +``` +[ { "id": 4, "description": null, "default_branch": "master", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", "web_url": "http://example.com/diaspora/diaspora-client", "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md", "tag_list": [ "example", "disapora client" ], "name": "Diaspora Client", "name_with_namespace": "Diaspora / Diaspora Client", "path": "diaspora-client", "path_with_namespace": "diaspora/diaspora-client", "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "forks_count": 0, "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png", "star_count": 0, }, { "id": 6, "description": null, "default_branch": "master", ... +``` + +当用户通过身份验证且未设置`simple` ,将返回以下内容: + +``` +[ { "id": 4, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", "web_url": "http://example.com/diaspora/diaspora-client", "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md", "tag_list": [ "example", "disapora client" ], "owner": { "id": 3, "name": "Diaspora", "created_at": "2013-09-30T13:46:02Z" }, "name": "Diaspora Client", "name_with_namespace": "Diaspora / Diaspora Client", "path": "diaspora-client", "path_with_namespace": "diaspora/diaspora-client", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "archived": false, "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png", "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", "ci_default_git_depth": 50, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on "marked_for_deletion_on": "2020-04-03", "statistics": { "commit_count": 37, "storage_size": 1038090, "repository_size": 1038090, "wiki_size" : 0, "lfs_objects_size": 0, "job_artifacts_size": 0, "packages_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" }, }, { "id": 6, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:brightbox/puppet.git", "http_url_to_repo": "http://example.com/brightbox/puppet.git", "web_url": "http://example.com/brightbox/puppet", "readme_url": "http://example.com/brightbox/puppet/blob/master/README.md", "tag_list": [ "example", "puppet" ], "owner": { "id": 4, "name": "Brightbox", "created_at": "2013-09-30T13:46:02Z" }, "name": "Puppet", "name_with_namespace": "Brightbox / Puppet", "path": "puppet", "path_with_namespace": "brightbox/puppet", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 4, "name": "Brightbox", "path": "brightbox", "kind": "group", "full_path": "brightbox" }, "import_status": "none", "import_error": null, "permissions": { "project_access": { "access_level": 10, "notification_level": 3 }, "group_access": { "access_level": 50, "notification_level": 3 } }, "archived": false, "avatar_url": null, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", "ci_default_git_depth": 0, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "auto_devops_enabled": true, "auto_devops_deploy_strategy": "continuous", "repository_storage": "default", "approvals_before_merge": 0, "mirror": false, "mirror_user_id": 45, "mirror_trigger_builds": false, "only_mirror_protected_branches": false, "mirror_overwrites_diverged_branches": false, "external_authorization_classification_label": null, "packages_enabled": true, "service_desk_enabled": false, "service_desk_address": null, "autoclose_referenced_issues": true, "suggestion_commit_message": null, "statistics": { "commit_count": 12, "storage_size": 2066080, "repository_size": 2066080, "wiki_size" : 0, "lfs_objects_size": 0, "job_artifacts_size": 0, "packages_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } ] +``` + +**注意:**对于使用 GitLab [Silver,Premium 或更高版本](https://about.gitlab.com/pricing/)的用户[,](https://about.gitlab.com/pricing/)已不推荐使用`marked_for_deletion_at`属性,并将在 API v5 中将其删除,以支持`marked_for_deletion_on`属性. + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +[ { "id": 4, "description": null, "approvals_before_merge": 0, ... } ] +``` + +您可以使用以下[自定义属性](custom_attributes.html)进行过滤: + +``` +GET /projects?custom_attributes[key]=value&custom_attributes[other_key]=other_value +``` + +### Pagination limits[](#pagination-limits "Permalink") + +从 GitLab 13.0 开始, [基于偏移量的分页](README.html#offset-based-pagination)将被[限制为 50,000 条记录](https://gitlab.com/gitlab-org/gitlab/-/issues/34565) . 要检索超出此限制的项目,将需要进行[键集分页](README.html#keyset-based-pagination) . + +请注意,键集分页仅支持`order_by=id` . 其他排序选项不可用. + +## List user projects[](#list-user-projects "Permalink") + +获取给定用户拥有的可见项目的列表. 在未经身份验证的情况下访问时,仅返回公共项目. + +``` +GET /users/:user_id/projects +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | string | yes | 用户的 ID 或用户名 | +| `archived` | boolean | no | 受存档状态限制 | +| `visibility` | string | no | 受`public` , `internal`或`private`可见性的限制 | +| `order_by` | string | no | 返回按`id` , `name` , `path` , `created_at` , `updated_at`或`last_activity_at`字段排序的项目. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的项目. 默认为`desc` | +| `search` | string | no | 返回符合搜索条件的项目列表 | +| `simple` | boolean | no | 仅返回每个项目的有限字段. 这是没有身份验证的无操作操作,因为这样*只会*返回简单的字段. | +| `owned` | boolean | no | 受当前用户明确拥有的项目限制 | +| `membership` | boolean | no | 受当前用户是其成员的项目的限制 | +| `starred` | boolean | no | Limit by projects starred by the current user | +| `statistics` | boolean | no | 包括项目统计 | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | +| `with_issues_enabled` | boolean | no | 受启用的问题限制功能 | +| `with_merge_requests_enabled` | boolean | no | 通过启用的合并请求限制功能 | +| `with_programming_language` | string | no | 受使用给定编程语言的项目限制 | +| `min_access_level` | integer | no | 受当前用户的最小[访问权限](members.html)限制 | +| `id_after` | integer | no | 将结果限制为 ID 大于指定 ID 的项目 | +| `id_before` | integer | no | 将结果限制为 ID 小于指定 ID 的项目 | + +**注意:**此端点支持所选`order_by`选项的[键集分页](README.html#keyset-based-pagination) . + +``` +[ { "id": 4, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", "web_url": "http://example.com/diaspora/diaspora-client", "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md", "tag_list": [ "example", "disapora client" ], "owner": { "id": 3, "name": "Diaspora", "created_at": "2013-09-30T13:46:02Z" }, "name": "Diaspora Client", "name_with_namespace": "Diaspora / Diaspora Client", "path": "diaspora-client", "path_with_namespace": "diaspora/diaspora-client", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "archived": false, "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png", "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", "ci_default_git_depth": 50, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on "marked_for_deletion_on": "2020-04-03", "statistics": { "commit_count": 37, "storage_size": 1038090, "repository_size": 1038090, "wiki_size" : 0, "lfs_objects_size": 0, "job_artifacts_size": 0, "packages_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } }, { "id": 6, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:brightbox/puppet.git", "http_url_to_repo": "http://example.com/brightbox/puppet.git", "web_url": "http://example.com/brightbox/puppet", "readme_url": "http://example.com/brightbox/puppet/blob/master/README.md", "tag_list": [ "example", "puppet" ], "owner": { "id": 4, "name": "Brightbox", "created_at": "2013-09-30T13:46:02Z" }, "name": "Puppet", "name_with_namespace": "Brightbox / Puppet", "path": "puppet", "path_with_namespace": "brightbox/puppet", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 4, "name": "Brightbox", "path": "brightbox", "kind": "group", "full_path": "brightbox" }, "import_status": "none", "import_error": null, "permissions": { "project_access": { "access_level": 10, "notification_level": 3 }, "group_access": { "access_level": 50, "notification_level": 3 } }, "archived": false, "avatar_url": null, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", "ci_default_git_depth": 0, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "auto_devops_enabled": true, "auto_devops_deploy_strategy": "continuous", "repository_storage": "default", "approvals_before_merge": 0, "mirror": false, "mirror_user_id": 45, "mirror_trigger_builds": false, "only_mirror_protected_branches": false, "mirror_overwrites_diverged_branches": false, "external_authorization_classification_label": null, "packages_enabled": true, "service_desk_enabled": false, "service_desk_address": null, "autoclose_referenced_issues": true, "suggestion_commit_message": null, "statistics": { "commit_count": 12, "storage_size": 2066080, "repository_size": 2066080, "wiki_size" : 0, "lfs_objects_size": 0, "job_artifacts_size": 0, "packages_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } ] +``` + +## List projects starred by a user[](#list-projects-starred-by-a-user "Permalink") + +获取给定用户拥有的可见项目的列表. 在未经身份验证的情况下访问时,仅返回公共项目. + +``` +GET /users/:user_id/starred_projects +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | string | yes | 用户的 ID 或用户名. | +| `archived` | boolean | no | 受存档状态限制. | +| `visibility` | string | no | 受`public` , `internal`或`private`可见性的限制. | +| `order_by` | string | no | 返回按`id` , `name` , `path` , `created_at` , `updated_at`或`last_activity_at`字段排序的项目. 默认值为`created_at` . | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的项目. 默认为`desc` . | +| `search` | string | no | 返回符合搜索条件的项目列表. | +| `simple` | boolean | no | 仅返回每个项目的有限字段. 这是没有身份验证的无操作操作,因为*仅*返回简单字段. | +| `owned` | boolean | no | 受当前用户明确拥有的项目限制. | +| `membership` | boolean | no | 受当前用户所属项目的限制. | +| `starred` | boolean | no | 受当前用户加注星标的项目限制. | +| `statistics` | boolean | no | 包括项目统计信息. | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员). | +| `with_issues_enabled` | boolean | no | 受启用的问题限制功能. | +| `with_merge_requests_enabled` | boolean | no | 通过启用的合并请求限制功能. | +| `min_access_level` | integer | no | 受当前用户的最小[访问权限](members.html)限制. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/5/starred_projects" +``` + +响应示例: + +``` +[ { "id": 4, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", "web_url": "http://example.com/diaspora/diaspora-client", "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md", "tag_list": [ "example", "disapora client" ], "owner": { "id": 3, "name": "Diaspora", "created_at": "2013-09-30T13:46:02Z" }, "name": "Diaspora Client", "name_with_namespace": "Diaspora / Diaspora Client", "path": "diaspora-client", "path_with_namespace": "diaspora/diaspora-client", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "archived": false, "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png", "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "statistics": { "commit_count": 37, "storage_size": 1038090, "repository_size": 1038090, "lfs_objects_size": 0, "job_artifacts_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } }, { "id": 6, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:brightbox/puppet.git", "http_url_to_repo": "http://example.com/brightbox/puppet.git", "web_url": "http://example.com/brightbox/puppet", "readme_url": "http://example.com/brightbox/puppet/blob/master/README.md", "tag_list": [ "example", "puppet" ], "owner": { "id": 4, "name": "Brightbox", "created_at": "2013-09-30T13:46:02Z" }, "name": "Puppet", "name_with_namespace": "Brightbox / Puppet", "path": "puppet", "path_with_namespace": "brightbox/puppet", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 4, "name": "Brightbox", "path": "brightbox", "kind": "group", "full_path": "brightbox" }, "import_status": "none", "import_error": null, "permissions": { "project_access": { "access_level": 10, "notification_level": 3 }, "group_access": { "access_level": 50, "notification_level": 3 } }, "archived": false, "avatar_url": null, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "auto_devops_enabled": true, "auto_devops_deploy_strategy": "continuous", "repository_storage": "default", "approvals_before_merge": 0, "mirror": false, "mirror_user_id": 45, "mirror_trigger_builds": false, "only_mirror_protected_branches": false, "mirror_overwrites_diverged_branches": false, "external_authorization_classification_label": null, "packages_enabled": true, "service_desk_enabled": false, "service_desk_address": null, "autoclose_referenced_issues": true, "suggestion_commit_message": null, "statistics": { "commit_count": 12, "storage_size": 2066080, "repository_size": 2066080, "lfs_objects_size": 0, "job_artifacts_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } ] +``` + +## Get single project[](#get-single-project "Permalink") + +获取一个特定的项目. 如果可以公开访问该项目,则无需身份验证即可访问该端点. + +``` +GET /projects/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `statistics` | boolean | no | 包括项目统计 | +| `license` | boolean | no | 包括项目许可证数据 | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | + +``` +{ "id": 3, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ "example", "disapora project" ], "owner": { "id": 3, "name": "Diaspora", "created_at": "2013-09-30T13:46:02Z" }, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "container_expiration_policy": { "cadence": "7d", "enabled": false, "keep_n": null, "older_than": null, "name_regex": null, // to be deprecated in GitLab 13.0 in favor of `name_regex_delete` "name_regex_delete": null, "name_regex_keep": null, "next_run_at": "2020-01-07T21:42:58.658Z" }, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora", "avatar_url": "http://localhost:3000/uploads/group/avatar/3/foo.jpg", "web_url": "http://localhost:3000/groups/diaspora" }, "import_status": "none", "import_error": null, "permissions": { "project_access": { "access_level": 10, "notification_level": 3 }, "group_access": { "access_level": 50, "notification_level": 3 } }, "archived": false, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE", "license": { "key": "lgpl-3.0", "name": "GNU Lesser General Public License v3.0", "nickname": "GNU LGPLv3", "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" }, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b", "ci_default_git_depth": 50, "public_jobs": true, "shared_with_groups": [ { "group_id": 4, "group_name": "Twitter", "group_full_path": "twitter", "group_access_level": 30 }, { "group_id": 3, "group_name": "Gitlab Org", "group_full_path": "gitlab-org", "group_access_level": 10 } ], "repository_storage": "default", "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "printing_merge_requests_link_enabled": true, "request_access_enabled": false, "merge_method": "merge", "auto_devops_enabled": true, "auto_devops_deploy_strategy": "continuous", "repository_storage": "default", "approvals_before_merge": 0, "mirror": false, "mirror_user_id": 45, "mirror_trigger_builds": false, "only_mirror_protected_branches": false, "mirror_overwrites_diverged_branches": false, "external_authorization_classification_label": null, "packages_enabled": true, "service_desk_enabled": false, "service_desk_address": null, "autoclose_referenced_issues": true, "suggestion_commit_message": null, "marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on "marked_for_deletion_on": "2020-04-03", "compliance_frameworks": [ "sox" ], "statistics": { "commit_count": 37, "storage_size": 1038090, "repository_size": 1038090, "wiki_size" : 0, "lfs_objects_size": 0, "job_artifacts_size": 0, "packages_size": 0 }, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } +``` + +在 GitLab 用户[入门,青铜或更高](https://about.gitlab.com/pricing/)还会看到`approvals_before_merge`参数: + +``` +{ "id": 3, "description": null, "approvals_before_merge": 0, ... } +``` + +**注意** :GitLab 11.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27427)了`namespace`上的`web_url`和`avatar_url`属性. + +如果项目是 fork,并且您提供了有效的令牌进行身份验证,则`forked_from_project`字段将出现在响应中. + +``` +{ "id":3, ... "forked_from_project":{ "id":13083, "description":"GitLab Community Edition", "name":"GitLab Community Edition", "name_with_namespace":"GitLab.org / GitLab Community Edition", "path":"gitlab-foss", "path_with_namespace":"gitlab-org/gitlab-foss", "created_at":"2013-09-26T06:02:36.000Z", "default_branch":"master", "tag_list":[], "ssh_url_to_repo":"git@gitlab.com:gitlab-org/gitlab-foss.git", "http_url_to_repo":"https://gitlab.com/gitlab-org/gitlab-foss.git", "web_url":"https://gitlab.com/gitlab-org/gitlab-foss", "avatar_url":"https://assets.gitlab-static.net/uploads/-/system/project/avatar/13083/logo-extra-whitespace.png", "license_url": "https://gitlab.com/gitlab-org/gitlab/blob/master/LICENSE", "license": { "key": "mit", "name": "MIT License", "nickname": null, "html_url": "http://choosealicense.com/licenses/mit/", "source_url": "https://opensource.org/licenses/MIT", }, "star_count":3812, "forks_count":3561, "last_activity_at":"2018-01-02T11:40:26.570Z", "namespace": { "id": 72, "name": "GitLab.org", "path": "gitlab-org", "kind": "group", "full_path": "gitlab-org", "parent_id": null } } ... } +``` + +## Get project users[](#get-project-users "Permalink") + +获取项目的用户列表. + +``` +GET /projects/:id/users +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `search` | string | no | 搜索特定用户 | +| `skip_users` | 整数数组 | no | 筛选出具有指定 ID 的用户 | + +``` +[ { "id": 1, "username": "john_smith", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", "web_url": "http://localhost:3000/john_smith" }, { "id": 2, "username": "jack_smith", "name": "Jack Smith", "state": "blocked", "avatar_url": "http://gravatar.com/../e32131cd8.jpeg", "web_url": "http://localhost:3000/jack_smith" } ] +``` + +## Get project events[](#get-project-events "Permalink") + +请参考[Events API 文档](events.html#list-a-projects-visible-events) . + +## Create project[](#create-project "Permalink") + +创建一个经过身份验证的用户拥有的新项目. + +``` +POST /projects +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | string | 是,如果未提供路径 | 新项目的名称. 如果未提供,则等于路径. | +| `path` | string | 是,如果未提供名称 | 新项目的存储库名称. 如果未提供,则根据名称生成(生成的小写字母加短划线). | +| `namespace_id` | integer | no | 新项目的命名空间(默认为当前用户的命名空间) | +| `default_branch` | string | no | `master`默认 | +| `description` | string | no | 简短的项目说明 | +| `issues_enabled` | boolean | no | (不建议使用)为此项目启用问题. 改用`issues_access_level` | +| `merge_requests_enabled` | boolean | no | (不建议使用)为此项目启用合并请求. 改用`merge_requests_access_level` | +| `jobs_enabled` | boolean | no | (不建议使用)为此项目启用作业. 改用`builds_access_level` | +| `wiki_enabled` | boolean | no | (已弃用)为此项目启用 Wiki. 改用`wiki_access_level` | +| `snippets_enabled` | boolean | no | (不建议使用)为此项目启用摘要. 请改用`snippets_access_level` | +| `issues_access_level` | string | no | `disabled` , `private`或`enabled` | +| `repository_access_level` | string | no | `disabled` , `private`或`enabled` | +| `merge_requests_access_level` | string | no | `disabled` , `private`或`enabled` | +| `forking_access_level` | string | no | `disabled` , `private`或`enabled` | +| `builds_access_level` | string | no | `disabled` , `private`或`enabled` | +| `wiki_access_level` | string | no | `disabled` , `private`或`enabled` | +| `snippets_access_level` | string | no | `disabled` , `private`或`enabled` | +| `pages_access_level` | string | no | `disabled` , `private` , `enabled`或`public` | +| `emails_disabled` | boolean | no | 禁用电子邮件通知 | +| `show_default_award_emojis` | boolean | no | 显示默认的奖励表情符号 | +| `resolve_outdated_diff_discussions` | boolean | no | 自动解决合并请求差异讨论(通过推送更改) | +| `container_registry_enabled` | boolean | no | 为该项目启用容器注册表 | +| `container_expiration_policy_attributes` | hash | no | 更新此项目的图像过期策略. 接受: `cadence` (字符串), `keep_n` (字符串), `older_than` (字符串), `name_regex` (字符串), `name_regex_delete` (字符串), `name_regex_keep` (字符串), `enabled` (布尔值) | +| `shared_runners_enabled` | boolean | no | 为此项目启用共享跑步者 | +| `visibility` | string | no | See [project visibility level](#project-visibility-level) | +| `import_url` | string | no | 从中导入存储库的 URL | +| `public_builds` | boolean | no | 如果为`true` ,则非项目成员可以查看作业 | +| `only_allow_merge_if_pipeline_succeeds` | boolean | no | 设置是否只能将合并请求与成功的作业合并 | +| `allow_merge_on_skipped_pipeline` | boolean | no | 设置是否可以将合并请求与跳过的作业合并 | +| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | 设置是否仅在所有讨论都解决后才能合并合并请求 | +| `merge_method` | string | no | 设置使用的[合并方法](#project-merge-method) | +| `autoclose_referenced_issues` | boolean | no | 设置是否自动关闭默认分支上的引用问题 | +| `remove_source_branch_after_merge` | boolean | no | 默认情况下,为所有新合并请求启用" `Delete source branch`选项 | +| `lfs_enabled` | boolean | no | 启用 LFS | +| `request_access_enabled` | boolean | no | 允许用户请求成员访问 | +| `tag_list` | array | no | 项目标签列表; 放置标签数组,这些标签应最终分配给项目 | +| `avatar` | mixed | no | 项目头像的图像文件 | +| `printing_merge_request_link_enabled` | boolean | no | 从命令行推送时显示创建/查看合并请求的链接 | +| `build_git_strategy` | string | no | Git 策略. 默认为`fetch` | +| `build_timeout` | integer | no | 作业可以运行的最长时间(以分钟为单位)(以秒为单位) | +| `auto_cancel_pending_pipelines` | string | no | 自动取消挂起的管道(注意:这不是布尔值,但已启用/禁用 | +| `build_coverage_regex` | string | no | 测试覆盖率解析 | +| `ci_config_path` | string | no | CI 配置文件的路径 | +| `auto_devops_enabled` | boolean | no | 为该项目启用 Auto DevOps | +| `auto_devops_deploy_strategy` | string | no | 自动部署策略( `continuous` , `manual`或`timed_incremental` ) | +| `repository_storage` | string | no | 存储库位于哪个存储分片上. 仅适用于管理员 | +| `approvals_before_merge` | integer | no | 默认情况下,应有多少个批准者批准合并请求 | +| `external_authorization_classification_label` | string | no | 项目的分类标签 | +| `mirror` | boolean | no | 在项目中启用拉镜像 | +| `mirror_trigger_builds` | boolean | no | 拉镜像触发器构建 | +| `initialize_with_readme` | boolean | no | 默认为`false` | +| `template_name` | string | no | 不使用`use_custom_template` ,为[内置项目模板的名称](../gitlab-basics/create-project.html#built-in-templates) . 与`use_custom_template`使用时,自定义项目模板的名称 | +| `template_project_id` | integer | no | 与`use_custom_template`使用时,是自定义项目模板的项目 ID. 这比使用`template_name`更可取,因为`template_name`可能含糊. | +| `use_custom_template` | boolean | no | 使用自定义[实例](../user/admin_area/custom_project_templates.html)或[组](../user/group/custom_project_templates.html) (带有`group_with_project_templates_id` )项目模板 | +| `group_with_project_templates_id` | integer | no | 对于组级别的自定义模板,指定所有自定义项目模板所源自的组的 ID. 将实例级模板留空. 要求`use_custom_template`为 true | +| `packages_enabled` | boolean | no | 启用或禁用软件包存储库功能 | + +**注意:**如果您的 HTTP 存储库不可公开访问,请将身份验证信息添加到 URL: `https://username:password@gitlab.company.com/group/project.git` ,其中`password`是启用了`api`范围的公共访问密钥. + +## Create project for user[](#create-project-for-user "Permalink") + +创建一个由指定用户拥有的新项目. 仅适用于管理员. + +``` +POST /projects/user/:user_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | integer | yes | 项目所有者的用户标识 | +| `name` | string | yes | 新项目的名称 | +| `path` | string | no | 新项目的自定义存储库名称. 默认情况下根据名称生成 | +| `namespace_id` | integer | no | Namespace for the new project (defaults to the current user’s namespace) | +| `description` | string | no | 简短的项目说明 | +| `issues_enabled` | boolean | no | (不建议使用)为此项目启用问题. 改用`issues_access_level` | +| `merge_requests_enabled` | boolean | no | (不建议使用)为此项目启用合并请求. 改用`merge_requests_access_level` | +| `jobs_enabled` | boolean | no | (不建议使用)为此项目启用作业. 改用`builds_access_level` | +| `wiki_enabled` | boolean | no | (已弃用)为此项目启用 Wiki. 改用`wiki_access_level` | +| `snippets_enabled` | boolean | no | (不建议使用)为此项目启用摘要. 请改用`snippets_access_level` | +| `issues_access_level` | string | no | `disabled` , `private`或`enabled` | +| `repository_access_level` | string | no | `disabled` , `private`或`enabled` | +| `merge_requests_access_level` | string | no | `disabled` , `private`或`enabled` | +| `forking_access_level` | string | no | `disabled` , `private`或`enabled` | +| `builds_access_level` | string | no | `disabled` , `private`或`enabled` | +| `wiki_access_level` | string | no | `disabled` , `private`或`enabled` | +| `snippets_access_level` | string | no | `disabled` , `private`或`enabled` | +| `pages_access_level` | string | no | `disabled` , `private` , `enabled`或`public` | +| `emails_disabled` | boolean | no | 禁用电子邮件通知 | +| `show_default_award_emojis` | boolean | no | 显示默认的奖励表情符号 | +| `resolve_outdated_diff_discussions` | boolean | no | 自动解决合并请求差异讨论(通过推送更改) | +| `container_registry_enabled` | boolean | no | 为该项目启用容器注册表 | +| `shared_runners_enabled` | boolean | no | 为此项目启用共享跑步者 | +| `visibility` | string | no | See [project visibility level](#project-visibility-level) | +| `import_url` | string | no | 从中导入存储库的 URL | +| `public_builds` | boolean | no | 如果为`true` ,则非项目成员可以查看作业 | +| `only_allow_merge_if_pipeline_succeeds` | boolean | no | 设置是否只能将合并请求与成功的作业合并 | +| `allow_merge_on_skipped_pipeline` | boolean | no | 设置是否可以将合并请求与跳过的作业合并 | +| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | 设置是否仅在所有讨论都解决后才能合并合并请求 | +| `merge_method` | string | no | 设置使用的[合并方法](#project-merge-method) | +| `autoclose_referenced_issues` | boolean | no | 设置是否自动关闭默认分支上的引用问题 | +| `suggestion_commit_message` | string | no | 用于应用合并请求建议的提交消息 | +| `remove_source_branch_after_merge` | boolean | no | 默认情况下,为所有新合并请求启用" `Delete source branch`选项 | +| `lfs_enabled` | boolean | no | 启用 LFS | +| `request_access_enabled` | boolean | no | 允许用户请求成员访问 | +| `tag_list` | array | no | 项目标签列表; 放置标签数组,这些标签应最终分配给项目 | +| `avatar` | mixed | no | 项目头像的图像文件 | +| `printing_merge_request_link_enabled` | boolean | no | 从命令行推送时显示创建/查看合并请求的链接 | +| `build_git_strategy` | string | no | Git 策略. 默认为`fetch` | +| `build_timeout` | integer | no | 作业可以运行的最长时间(以分钟为单位)(以秒为单位) | +| `auto_cancel_pending_pipelines` | string | no | 自动取消挂起的管道(注意:这不是布尔值,但已启用/禁用 | +| `build_coverage_regex` | string | no | 测试覆盖率解析 | +| `ci_config_path` | string | no | CI 配置文件的路径 | +| `auto_devops_enabled` | boolean | no | 为该项目启用 Auto DevOps | +| `auto_devops_deploy_strategy` | string | no | 自动部署策略( `continuous` , `manual`或`timed_incremental` ) | +| `repository_storage` | string | no | 存储库位于哪个存储分片上. 仅适用于管理员 | +| `approvals_before_merge` | integer | no | 默认情况下,应有多少个批准者批准合并请求 | +| `external_authorization_classification_label` | string | no | 项目的分类标签 | +| `mirror` | boolean | no | 在项目中启用拉镜像 | +| `mirror_trigger_builds` | boolean | no | 拉镜像触发器构建 | +| `initialize_with_readme` | boolean | no | 默认为`false` | +| `template_name` | string | no | 不使用`use_custom_template` ,为[内置项目模板的名称](../gitlab-basics/create-project.html#built-in-templates) . 与`use_custom_template`使用时,自定义项目模板的名称 | +| `use_custom_template` | boolean | no | Use either custom [instance](../user/admin_area/custom_project_templates.html) or [group](../user/group/custom_project_templates.html) (with `group_with_project_templates_id`) project template | +| `group_with_project_templates_id` | integer | no | 对于组级别的自定义模板,指定所有自定义项目模板所源自的组的 ID. 将实例级模板留空. 要求`use_custom_template`为 true | +| `packages_enabled` | boolean | no | 启用或禁用软件包存储库功能 | + +**注意:**如果您的 HTTP 存储库不可公开访问,请将身份验证信息添加到 URL: `https://username:password@gitlab.company.com/group/project.git` ,其中`password`是启用了`api`范围的公共访问密钥. + +## Edit project[](#edit-project "Permalink") + +更新现有项目. + +``` +PUT /projects/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `name` | string | no | 项目名称 | +| `path` | string | no | 项目的自定义存储库名称. 默认情况下根据名称生成 | +| `default_branch` | string | no | `master`默认 | +| `description` | string | no | 简短的项目说明 | +| `issues_enabled` | boolean | no | (不建议使用)为此项目启用问题. 改用`issues_access_level` | +| `merge_requests_enabled` | boolean | no | (不建议使用)为此项目启用合并请求. 改用`merge_requests_access_level` | +| `jobs_enabled` | boolean | no | (不建议使用)为此项目启用作业. 改用`builds_access_level` | +| `wiki_enabled` | boolean | no | (已弃用)为此项目启用 Wiki. 改用`wiki_access_level` | +| `snippets_enabled` | boolean | no | (不建议使用)为此项目启用摘要. 请改用`snippets_access_level` | +| `issues_access_level` | string | no | `disabled` , `private`或`enabled` | +| `repository_access_level` | string | no | `disabled` , `private`或`enabled` | +| `merge_requests_access_level` | string | no | `disabled` , `private`或`enabled` | +| `forking_access_level` | string | no | `disabled` , `private`或`enabled` | +| `builds_access_level` | string | no | `disabled` , `private`或`enabled` | +| `wiki_access_level` | string | no | `disabled` , `private`或`enabled` | +| `snippets_access_level` | string | no | `disabled` , `private`或`enabled` | +| `pages_access_level` | string | no | `disabled` , `private` , `enabled`或`public` | +| `emails_disabled` | boolean | no | 禁用电子邮件通知 | +| `show_default_award_emojis` | boolean | no | 显示默认的奖励表情符号 | +| `resolve_outdated_diff_discussions` | boolean | no | 自动解决合并请求差异讨论(通过推送更改) | +| `container_registry_enabled` | boolean | no | 为该项目启用容器注册表 | +| `container_expiration_policy_attributes` | hash | no | 更新此项目的图像过期策略. 接受: `cadence` (字符串), `keep_n` (字符串), `older_than` (字符串), `name_regex` (字符串), `name_regex_delete` (字符串), `name_regex_keep` (字符串), `enabled` (布尔值) | +| `shared_runners_enabled` | boolean | no | 为此项目启用共享跑步者 | +| `visibility` | string | no | See [project visibility level](#project-visibility-level) | +| `import_url` | string | no | 从中导入存储库的 URL | +| `public_builds` | boolean | no | 如果为`true` ,则非项目成员可以查看作业 | +| `only_allow_merge_if_pipeline_succeeds` | boolean | no | 设置是否只能将合并请求与成功的作业合并 | +| `allow_merge_on_skipped_pipeline` | boolean | no | 设置是否可以将合并请求与跳过的作业合并 | +| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | 设置是否仅在所有讨论都解决后才能合并合并请求 | +| `merge_method` | string | no | 设置使用的[合并方法](#project-merge-method) | +| `autoclose_referenced_issues` | boolean | no | 设置是否自动关闭默认分支上的引用问题 | +| `suggestion_commit_message` | string | no | 用于应用合并请求建议的提交消息 | +| `remove_source_branch_after_merge` | boolean | no | 默认情况下,为所有新合并请求启用" `Delete source branch`选项 | +| `lfs_enabled` | boolean | no | 启用 LFS | +| `request_access_enabled` | boolean | no | 允许用户请求成员访问 | +| `tag_list` | array | no | 项目标签列表; 放置标签数组,这些标签应最终分配给项目 | +| `avatar` | mixed | no | 项目头像的图像文件 | +| `build_git_strategy` | string | no | Git 策略. 默认为`fetch` | +| `build_timeout` | integer | no | 作业可以运行的最长时间(以分钟为单位)(以秒为单位) | +| `auto_cancel_pending_pipelines` | string | no | 自动取消挂起的管道(注意:这不是布尔值,但已启用/禁用 | +| `build_coverage_regex` | string | no | 测试覆盖率解析 | +| `ci_config_path` | string | no | CI 配置文件的路径 | +| `ci_default_git_depth` | integer | no | [浅克隆的](../ci/pipelines/settings.html#git-shallow-clone)默认修订版本数 | +| `auto_devops_enabled` | boolean | no | 为该项目启用 Auto DevOps | +| `auto_devops_deploy_strategy` | string | no | 自动部署策略( `continuous` , `manual`或`timed_incremental` ) | +| `repository_storage` | string | no | 存储库位于哪个存储分片上. 仅适用于管理员 | +| `approvals_before_merge` | integer | no | How many approvers should approve merge request by default | +| `external_authorization_classification_label` | string | no | 项目的分类标签 | +| `mirror` | boolean | no | 在项目中启用拉镜像 | +| `mirror_user_id` | integer | no | 用户负责拉镜事件周围的所有活动. 只能由管理员设置. | +| `mirror_trigger_builds` | boolean | no | 拉镜像触发器构建 | +| `only_mirror_protected_branches` | boolean | no | 仅镜像保护的分支 | +| `mirror_overwrites_diverged_branches` | boolean | no | 拉镜将覆盖分散的分支 | +| `packages_enabled` | boolean | no | 启用或禁用软件包存储库功能 | +| `service_desk_enabled` | boolean | no | 启用或禁用服务台功能 | + +**注意:**如果您的 HTTP 存储库不可公开访问,请将身份验证信息添加到 URL: `https://username:password@gitlab.company.com/group/project.git` ,其中`password`是启用了`api`范围的公共访问密钥. + +## Fork project[](#fork-project "Permalink") + +将项目派生到已认证用户或提供的用户的用户名称空间中. + +项目的分叉操作是异步的,并在后台作业中完成. 该请求将立即返回. 要确定项目的分支是否已完成,请查询`import_status`以获取新项目. + +``` +POST /projects/:id/fork +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `namespace` | integer/string | no | (不建议使用)项目将分叉到的名称空间的 ID 或路径 | +| `namespace_id` | integer | no | 项目将分叉到的名称空间的 ID | +| `namespace_path` | string | no | 项目将分叉到的名称空间的路径 | +| `path` | string | no | 分叉后将分配给结果项目的路径 | +| `name` | string | no | 分叉后将分配给结果项目的名称 | + +## List Forks of a project[](#list-forks-of-a-project "Permalink") + +**注意:**此功能是在 GitLab 10.1 中引入的. + +列出呼叫用户可访问的与指定项目具有已建立的分叉关系的项目 + +``` +GET /projects/:id/forks +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `archived` | boolean | no | 受存档状态限制 | +| `visibility` | string | no | 受`public` , `internal`或`private`可见性的限制 | +| `order_by` | string | no | 返回按`id` , `name` , `path` , `created_at` , `updated_at`或`last_activity_at`字段排序的项目. 默认为`created_at` | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的项目. 默认为`desc` | +| `search` | string | no | 返回符合搜索条件的项目列表 | +| `simple` | boolean | no | 仅返回每个项目的有限字段. 这是没有身份验证的无操作操作,因为这样*只会*返回简单的字段. | +| `owned` | boolean | no | 受当前用户明确拥有的项目限制 | +| `membership` | boolean | no | 受当前用户是其成员的项目的限制 | +| `starred` | boolean | no | 受当前用户加注星标的项目限制 | +| `statistics` | boolean | no | 包括项目统计 | +| `with_custom_attributes` | boolean | no | 在响应中包括[自定义属性](custom_attributes.html) (仅管理员) | +| `with_issues_enabled` | boolean | no | 受启用的问题限制功能 | +| `with_merge_requests_enabled` | boolean | no | 通过启用的合并请求限制功能 | +| `min_access_level` | integer | no | 受当前用户的最小[访问权限](members.html)限制 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/forks" +``` + +响应示例: + +``` +[ { "id": 3, "description": null, "default_branch": "master", "visibility": "internal", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ "example", "disapora project" ], "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "archived": true, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "shared_runners_enabled": true, "forks_count": 0, "star_count": 1, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } ] +``` + +## Star a project[](#star-a-project "Permalink") + +明星给定的项目. 如果项目已加星标,则返回状态码`304` . + +``` +POST /projects/:id/star +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/star" +``` + +响应示例: + +``` +{ "id": 3, "description": null, "default_branch": "master", "visibility": "internal", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ "example", "disapora project" ], "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "archived": true, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE", "license": { "key": "lgpl-3.0", "name": "GNU Lesser General Public License v3.0", "nickname": "GNU LGPLv3", "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" }, "shared_runners_enabled": true, "forks_count": 0, "star_count": 1, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } +``` + +## Unstar a project[](#unstar-a-project "Permalink") + +取消给定项目的星标. 如果项目未加星标,则返回状态码`304` . + +``` +POST /projects/:id/unstar +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/unstar" +``` + +响应示例: + +``` +{ "id": 3, "description": null, "default_branch": "master", "visibility": "internal", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ "example", "disapora project" ], "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "archived": true, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE", "license": { "key": "lgpl-3.0", "name": "GNU Lesser General Public License v3.0", "nickname": "GNU LGPLv3", "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" }, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } +``` + +## List Starrers of a project[](#list-starrers-of-a-project "Permalink") + +列出为指定项目加注星标的用户. + +``` +GET /projects/:id/starrers +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `search` | string | no | 搜索特定用户. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/starrers" +``` + +响应示例: + +``` +[ { "starred_since": "2019-01-28T14:47:30.642Z", "user": { "id": 1, "username": "jane_smith", "name": "Jane Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", "web_url": "http://localhost:3000/jane_smith" } }, "starred_since": "2018-01-02T11:40:26.570Z", "user": { "id": 2, "username": "janine_smith", "name": "Janine Smith", "state": "blocked", "avatar_url": "http://gravatar.com/../e32131cd8.jpeg", "web_url": "http://localhost:3000/janine_smith" } ] +``` + +## Languages[](#languages "Permalink") + +获取具有百分比值的项目中使用的语言. + +``` +GET /projects/:id/languages +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/languages" +``` + +响应示例: + +``` +{ "Ruby": 66.69, "JavaScript": 22.98, "HTML": 7.91, "CoffeeScript": 2.42 } +``` + +## Archive a project[](#archive-a-project "Permalink") + +如果用户是该项目的管理员或项目所有者,则归档该项目. 此操作是幂等的,因此归档已归档的项目不会更改该项目. + +``` +POST /projects/:id/archive +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/archive" +``` + +响应示例: + +``` +{ "id": 3, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ "example", "disapora project" ], "owner": { "id": 3, "name": "Diaspora", "created_at": "2013-09-30T13:46:02Z" }, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "import_error": null, "permissions": { "project_access": { "access_level": 10, "notification_level": 3 }, "group_access": { "access_level": 50, "notification_level": 3 } }, "archived": true, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE", "license": { "key": "lgpl-3.0", "name": "GNU Lesser General Public License v3.0", "nickname": "GNU LGPLv3", "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" }, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b", "ci_default_git_depth": 50, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } +``` + +## Unarchive a project[](#unarchive-a-project "Permalink") + +如果用户是该项目的管理员或项目所有者,则取消归档该项目. 此操作是幂等的,因此取消存档未存档的项目不会更改该项目. + +``` +POST /projects/:id/unarchive +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/unarchive" +``` + +响应示例: + +``` +{ "id": 3, "description": null, "default_branch": "master", "visibility": "private", "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ "example", "disapora project" ], "owner": { "id": 3, "name": "Diaspora", "created_at": "2013-09-30T13:46:02Z" }, "name": "Diaspora Project Site", "name_with_namespace": "Diaspora / Diaspora Project Site", "path": "diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "open_issues_count": 1, "merge_requests_enabled": true, "jobs_enabled": true, "wiki_enabled": true, "snippets_enabled": false, "can_create_merge_request_in": true, "resolve_outdated_diff_discussions": false, "container_registry_enabled": false, "created_at": "2013-09-30T13:46:02Z", "last_activity_at": "2013-09-30T13:46:02Z", "creator_id": 3, "namespace": { "id": 3, "name": "Diaspora", "path": "diaspora", "kind": "group", "full_path": "diaspora" }, "import_status": "none", "import_error": null, "permissions": { "project_access": { "access_level": 10, "notification_level": 3 }, "group_access": { "access_level": 50, "notification_level": 3 } }, "archived": false, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE", "license": { "key": "lgpl-3.0", "name": "GNU Lesser General Public License v3.0", "nickname": "GNU LGPLv3", "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" }, "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b", "ci_default_git_depth": 50, "public_jobs": true, "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, "merge_method": "merge", "autoclose_referenced_issues": true, "suggestion_commit_message": null, "_links": { "self": "http://example.com/api/v4/projects", "issues": "http://example.com/api/v4/projects/1/issues", "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", "labels": "http://example.com/api/v4/projects/1/labels", "events": "http://example.com/api/v4/projects/1/events", "members": "http://example.com/api/v4/projects/1/members" } } +``` + +## Remove project[](#remove-project "Permalink") + +该端点: + +* 删除包含所有相关资源(问题,合并请求等)的项目. +* 从[Premium 或 Silver](https://about.gitlab.com/pricing/)或更高级别的[GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/32935)开始,将项目标记为删除. 实际删除发生在[实例设置中](../user/admin_area/settings/visibility_and_access_controls.html#default-deletion-adjourned-period-premium-only)指定的天数之后. + +``` +DELETE /projects/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +## Restore project marked for deletion[](#restore-project-marked-for-deletion-premium "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) . + +恢复标记为删除的项目. + +``` +POST /projects/:id/restore +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +## Upload a file[](#upload-a-file "Permalink") + +将文件上载到指定的项目,以在发布或合并请求描述或注释中使用. + +``` +POST /projects/:id/uploads +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `file` | string | yes | 要上传的文件 | + +要从文件系统上载文件,请使用`--form`参数. 这将导致 cURL 使用标题`Content-Type: multipart/form-data` . `file=`参数必须指向文件系统上的文件,并以`@`开头. 例如: + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "file=@dk.png" "https://gitlab.example.com/api/v4/projects/5/uploads" +``` + +Returned object: + +``` +{ "alt": "dk", "url": "/uploads/66dbcd21ec5d24ed6ea225176098d52b/dk.png", "full_path": "/namespace1/project1/uploads/66dbcd21ec5d24ed6ea225176098d52b/dk.png", "markdown": "![dk](/uploads/66dbcd21ec5d24ed6ea225176098d52b/dk.png)" } +``` + +> **注意** :返回的`url`是相对于项目路径的. 返回的`full_path`是文件的绝对路径. 在 Markdown 上下文中,当使用`markdown`的格式时,链接会自动展开. + +## Share project with group[](#share-project-with-group "Permalink") + +允许与小组共享项目. + +``` +POST /projects/:id/share +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `group_id` | integer | yes | 与之共享的组的 ID | +| `group_access` | integer | yes | 授予组的[权限级别](members.html) | +| `expires_at` | string | no | ISO 8601 格式的股份到期日:2016-09-26 | + +## Delete a shared project link within a group[](#delete-a-shared-project-link-within-a-group "Permalink") + +从小组取消共享项目. 返回`204` ,成功则不返回任何内容. + +``` +DELETE /projects/:id/share/:group_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `group_id` | integer | yes | 组的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/share/17" +``` + +## Hooks[](#hooks "Permalink") + +也称为 Project Hooks 和 Webhooks. 对于系统范围的[系统挂钩](system_hooks.html) ,这些是不同的. + +### List project hooks[](#list-project-hooks "Permalink") + +获取项目挂钩的列表. + +``` +GET /projects/:id/hooks +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +### Get project hook[](#get-project-hook "Permalink") + +获取项目的特定挂钩. + +``` +GET /projects/:id/hooks/:hook_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `hook_id` | integer | yes | 项目挂钩的 ID | + +``` +{ "id": 1, "url": "http://example.com/hook", "project_id": 3, "push_events": true, "push_events_branch_filter": "", "issues_events": true, "confidential_issues_events": true, "merge_requests_events": true, "tag_push_events": true, "note_events": true, "confidential_note_events": true, "job_events": true, "pipeline_events": true, "wiki_page_events": true, "enable_ssl_verification": true, "created_at": "2012-10-12T17:04:47Z" } +``` + +### Add project hook[](#add-project-hook "Permalink") + +将钩子添加到指定项目. + +``` +POST /projects/:id/hooks +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `url` | string | yes | 挂钩网址 | +| `push_events` | boolean | no | 在推送事件上触发钩子 | +| `push_events_branch_filter` | string | no | 触发推送事件上的钩子,仅用于匹配分支 | +| `issues_events` | boolean | no | 触发问题事件挂钩 | +| `confidential_issues_events` | boolean | no | 触发机密问题事件的钩子 | +| `merge_requests_events` | boolean | no | 触发合并请求事件的钩子 | +| `tag_push_events` | boolean | no | 触发标签推送事件的钩子 | +| `note_events` | boolean | no | 在音符事件上触发钩子 | +| `confidential_note_events` | boolean | no | 触发机密笔记事件的钩子 | +| `job_events` | boolean | no | 触发工作事件挂钩 | +| `pipeline_events` | boolean | no | 触发管道事件钩子 | +| `wiki_page_events` | boolean | no | 触发 Wiki 事件的钩子 | +| `enable_ssl_verification` | boolean | no | 触发挂钩时执行 SSL 验证 | +| `token` | string | no | 用于验证收到的有效载荷的秘密令牌; 这将不会在响应中返回 | + +### Edit project hook[](#edit-project-hook "Permalink") + +Edits a hook for a specified project. + +``` +PUT /projects/:id/hooks/:hook_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `hook_id` | integer | yes | 项目挂钩的 ID | +| `url` | string | yes | 挂钩网址 | +| `push_events` | boolean | no | 在推送事件上触发钩子 | +| `push_events_branch_filter` | string | no | 触发推送事件上的钩子,仅用于匹配分支 | +| `issues_events` | boolean | no | Trigger hook on issues events | +| `confidential_issues_events` | boolean | no | 触发机密问题事件的钩子 | +| `merge_requests_events` | boolean | no | 触发合并请求事件的钩子 | +| `tag_push_events` | boolean | no | 触发标签推送事件的钩子 | +| `note_events` | boolean | no | 在音符事件上触发钩子 | +| `confidential_note_events` | boolean | no | 触发机密笔记事件的钩子 | +| `job_events` | boolean | no | 触发工作事件挂钩 | +| `pipeline_events` | boolean | no | 触发管道事件钩子 | +| `wiki_events` | boolean | no | 触发 Wiki 事件的钩子 | +| `enable_ssl_verification` | boolean | no | 触发挂钩时执行 SSL 验证 | +| `token` | string | no | 用于验证收到的有效载荷的秘密令牌; 这将不会在响应中返回 | + +### Delete project hook[](#delete-project-hook "Permalink") + +从项目中删除一个钩子. 这是幂等方法,可以多次调用. 挂钩是否可用. + +``` +DELETE /projects/:id/hooks/:hook_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `hook_id` | integer | yes | 项目挂钩的 ID | + +请注意,无论挂钩是否可用,JSON 响应都会有所不同. 如果项目挂钩在 JSON 响应中返回之前可用,或者返回空响应. + +## Fork relationship[](#fork-relationship "Permalink") + +允许修改现有项目之间的分支关系. 仅适用于项目所有者和管理员. + +### Create a forked from/to relation between existing projects[](#create-a-forked-fromto-relation-between-existing-projects "Permalink") + +``` +POST /projects/:id/fork/:forked_from_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `forked_from_id` | ID | yes | 分叉的项目的 ID | + +### Delete an existing forked from relationship[](#delete-an-existing-forked-from-relationship "Permalink") + +``` +DELETE /projects/:id/fork +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +## Search for projects by name[](#search-for-projects-by-name "Permalink") + +通过名称搜索可通过身份验证的用户访问的项目. 如果可以公开访问该项目,则无需身份验证即可访问该端点. + +``` +GET /projects +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `search` | string | yes | 项目名称中包含的字符串 | +| `order_by` | string | no | 返回按`id` , `name` , `created_at`或`last_activity_at`字段排序的请求 | +| `sort` | string | no | 返回请求按`asc`或`desc`排序 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects?search=test" +``` + +## Start the Housekeeping task for a Project[](#start-the-housekeeping-task-for-a-project "Permalink") + +在 GitLab 9.0 中引入. + +``` +POST /projects/:id/housekeeping +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目或 NAMESPACE / PROJECT_NAME 的 ID | + +## Push Rules[](#push-rules-starter "Permalink") + +### Get project push rules[](#get-project-push-rules "Permalink") + +获取项目的推送规则. + +``` +GET /projects/:id/push_rule +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目或 NAMESPACE / PROJECT_NAME 的 ID | + +``` +{ "id": 1, "project_id": 3, "commit_message_regex": "Fixes \d+\..*", "commit_message_negative_regex": "ssh\:\/\/", "branch_name_regex": "", "deny_delete_tag": false, "created_at": "2012-10-12T17:04:47Z", "member_check": false, "prevent_secrets": false, "author_email_regex": "", "file_name_regex": "", "max_file_size": 5, "commit_committer_check": false, "reject_unsigned_commits": false } +``` + +使用 GitLab [Premium,Silver 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`commit_committer_check`和`reject_unsigned_commits`参数: + +``` +{ "id": 1, "project_id": 3, "commit_committer_check": false, "reject_unsigned_commits": false ... } +``` + +### Add project push rule[](#add-project-push-rule "Permalink") + +将推送规则添加到指定项目. + +``` +POST /projects/:id/push_rule +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目或 NAMESPACE / PROJECT_NAME 的 ID | +| `deny_delete_tag` | boolean | no | 拒绝删除标签 | +| `member_check` | boolean | no | 限制作者(电子邮件)对现有 GitLab 用户的提交 | +| `prevent_secrets` | boolean | no | GitLab 将拒绝任何可能包含机密的文件 | +| `commit_message_regex` | string | no | 所有提交消息都必须与此匹配,例如`Fixed \d+\..*` | +| `commit_message_negative_regex` | string | no | 不允许任何提交消息与此匹配,例如`ssh\:\/\/` | +| `branch_name_regex` | string | no | 所有分支名称必须与此匹配,例如`(feature|hotfix)\/*` | +| `author_email_regex` | string | no | 所有提交作者的电子邮件都必须与此匹配,例如`@my-company.com$` | +| `file_name_regex` | string | no | 所有提交的文件名都**不能**与此匹配,例如`(jar|exe)$` | +| `max_file_size` | integer | no | 档案大小上限(MB) | +| `commit_committer_check` | boolean | no | 用户只能将使用自己的已验证电子邮件之一提交的提交推送到该存储库. | +| `reject_unsigned_commits` | boolean | no | 如果未通过 GPG 签名,则拒绝提交. | + +### Edit project push rule[](#edit-project-push-rule "Permalink") + +编辑指定项目的推送规则. + +``` +PUT /projects/:id/push_rule +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目或 NAMESPACE / PROJECT_NAME 的 ID | +| `deny_delete_tag` | boolean | no | 拒绝删除标签 | +| `member_check` | boolean | no | 限制作者(电子邮件)对现有 GitLab 用户的提交 | +| `prevent_secrets` | boolean | no | GitLab will reject any files that are likely to contain secrets | +| `commit_message_regex` | string | no | 所有提交消息都必须与此匹配,例如`Fixed \d+\..*` | +| `commit_message_negative_regex` | string | no | 不允许任何提交消息与此匹配,例如`ssh\:\/\/` | +| `branch_name_regex` | string | no | 所有分支名称必须与此匹配,例如`(feature|hotfix)\/*` | +| `author_email_regex` | string | no | 所有提交作者的电子邮件都必须与此匹配,例如`@my-company.com$` | +| `file_name_regex` | string | no | 所有提交的文件名都**不能**与此匹配,例如`(jar|exe)$` | +| `max_file_size` | integer | no | 档案大小上限(MB) | +| `commit_committer_check` | boolean | no | 用户只能将使用自己的已验证电子邮件之一提交的提交推送到该存储库. | +| `reject_unsigned_commits` | boolean | no | 没有 GPG 签名时拒绝提交. | + +### Delete project push rule[](#delete-project-push-rule "Permalink") + +在[GitLab Starter](https://about.gitlab.com/pricing/) 9.0 中引入. + +从项目中删除推送规则. 这是幂等方法,可以多次调用. 推送规则是否可用. + +``` +DELETE /projects/:id/push_rule +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +## Transfer a project to a new namespace[](#transfer-a-project-to-a-new-namespace "Permalink") + +在 GitLab 11.1 中引入. + +``` +PUT /projects/:id/transfer +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `namespace` | integer/string | yes | 要转移到项目的名称空间的 ID 或路径 | + +## Branches[](#branches "Permalink") + +在" [分支机构"](branches.html)文档中了解更多信息. + +## Project Import/Export[](#project-importexport "Permalink") + +在[项目导入/导出](project_import_export.html)文档中了解更多信息. + +## Project members[](#project-members "Permalink") + +在[项目成员](members.html)文档中了解更多信息. + +## Start the pull mirroring process for a Project[](#start-the-pull-mirroring-process-for-a-project-starter "Permalink") + +在[GitLab Starter](https://about.gitlab.com/pricing/) 10.3 中引入. + +``` +POST /projects/:id/mirror/pull +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/mirror/pull" +``` + +## Project badges[](#project-badges "Permalink") + +在[Project Badges](project_badges.html)文档中了解更多信息. + +## Issue and merge request description templates[](#issue-and-merge-request-description-templates "Permalink") + +非默认的[问题和合并请求描述模板](../user/project/description_templates.html)在项目的存储库中进行管理. 因此,您可以通过[Repositories API](repositories.html)和[Repository Files API](repository_files.html)通过 API 管理它们. + +## Download snapshot of a Git repository[](#download-snapshot-of-a-git-repository "Permalink") + +在 GitLab 10.7 中引入 + +该端点只能由管理用户访问. + +下载项目(或 Wiki,如果需要)Git 存储库的快照. 该快照始终为未压缩的[tar](https://en.wikipedia.org/wiki/Tar_(computing))格式. + +如果存储库损坏到`git clone`不起作用的程度,则快照可能允许检索某些数据. + +``` +GET /projects/:id/snapshot +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `wiki` | boolean | no | 是否下载 Wiki,而不是项目存储库 | \ No newline at end of file diff --git a/docs/354.md b/docs/354.md new file mode 100644 index 0000000000000000000000000000000000000000..fbc6745000c29fc8c28ab04f4512f62792ae76cf --- /dev/null +++ b/docs/354.md @@ -0,0 +1,174 @@ +# Protected branches API + +> 原文:[https://docs.gitlab.com/ee/api/protected_branches.html](https://docs.gitlab.com/ee/api/protected_branches.html) + +* [List protected branches](#list-protected-branches) +* [Get a single protected branch or wildcard protected branch](#get-a-single-protected-branch-or-wildcard-protected-branch) +* [Protect repository branches](#protect-repository-branches) + * [Example with user / group level access](#example-with-user--group-level-access-starter) +* [Unprotect repository branches](#unprotect-repository-branches) +* [Require code owner approvals for a single branch](#require-code-owner-approvals-for-a-single-branch) + +# Protected branches API[](#protected-branches-api "Permalink") + +**注意:**此功能是在 GitLab 9.5 中引入的 + +**有效的访问级别** + +访问级别在`ProtectedRefAccess.allowed_access_levels`方法中定义. 当前,这些级别被认可: + +``` +0 => No access +30 => Developer access +40 => Maintainer access +60 => Admin access +``` + +## List protected branches[](#list-protected-branches "Permalink") + +从项目中获取受保护分支的列表. + +``` +GET /projects/:id/protected_branches +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `search` | string | no | 要搜索的受保护分支的名称或名称的一部分 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_branches" +``` + +响应示例: + +``` +[ { "id": 1, "name": "master", "push_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "merge_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" }, ... ] +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`user_id`和`group_id`参数: + +响应示例: + +``` +[ { "id": 1, "name": "master", "push_access_levels": [ { "access_level": 40, "user_id": null, "group_id": null, "access_level_description": "Maintainers" } ], "merge_access_levels": [ { "access_level": null, "user_id": null, "group_id": 1234, "access_level_description": "Example Merge Group" } ], "code_owner_approval_required": "false" }, ... ] +``` + +## Get a single protected branch or wildcard protected branch[](#get-a-single-protected-branch-or-wildcard-protected-branch "Permalink") + +获取单个受保护分支或通配符受保护分支. + +``` +GET /projects/:id/protected_branches/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 分支或通配符的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_branches/master" +``` + +响应示例: + +``` +{ "id": 1, "name": "master", "push_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "merge_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`user_id`和`group_id`参数: + +响应示例: + +``` +{ "id": 1, "name": "master", "push_access_levels": [ { "access_level": 40, "user_id": null, "group_id": null, "access_level_description": "Maintainers" } ], "merge_access_levels": [ { "access_level": null, "user_id": null, "group_id": 1234, "access_level_description": "Example Merge Group" } ], "code_owner_approval_required": "false" } +``` + +## Protect repository branches[](#protect-repository-branches "Permalink") + +使用通配符保护的分支来保护单个存储库分支或几个项目存储库分支. + +``` +POST /projects/:id/protected_branches +``` + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_branches?name=*-stable&push_access_level=30&merge_access_level=30&unprotect_access_level=40" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 分支或通配符的名称 | +| `push_access_level` | string | no | 允许推送的访问级别(默认值: `40` ,维护者访问级别) | +| `merge_access_level` | string | no | 允许合并的访问级别(默认值: `40` ,维护者访问级别) | +| `unprotect_access_level` | string | no | 允许取消保护的访问级别(默认值: `40` ,维护者访问级别) | +| `allowed_to_push` | array | no | 允许推送的访问级别数组,每个访问级别由一个哈希表描述 | +| `allowed_to_merge` | array | no | 允许合并的访问级别数组,每个访问级别由哈希描述 | +| `allowed_to_unprotect` | array | no | 允许取消保护的访问级别数组,每个访问级别由一个哈希表描述 | +| `code_owner_approval_required` | boolean | no | 如果它与[`CODEOWNERS`文件](../user/project/code_owners.html)中的项目匹配,则阻止推送到此分支. (默认值:false) | + +响应示例: + +``` +{ "id": 1, "name": "*-stable", "push_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "merge_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ], "unprotect_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`user_id`和`group_id`参数: + +响应示例: + +``` +{ "id": 1, "name": "*-stable", "push_access_levels": [ { "access_level": 30, "user_id": null, "group_id": null, "access_level_description": "Developers + Maintainers" } ], "merge_access_levels": [ { "access_level": 30, "user_id": null, "group_id": null, "access_level_description": "Developers + Maintainers" } ], "unprotect_access_levels": [ { "access_level": 40, "user_id": null, "group_id": null, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } +``` + +### Example with user / group level access[](#example-with-user--group-level-access-starter "Permalink") + +`allowed_to_push` / `allowed_to_merge` / `allowed_to_unprotect`数组中的元素应采用`{user_id: integer}` , `{group_id: integer}`或`{access_level: integer}` . 每个用户必须有权访问该项目,并且每个组都必须[共享该项目](../user/project/members/share_project_with_groups.html) . 这些访问级别允许[对受保护的分支访问](../user/project/protected_branches.html#restricting-push-and-merge-access-to-certain-users-starter)进行[更精细的控制,](../user/project/protected_branches.html#restricting-push-and-merge-access-to-certain-users-starter)并在 GitLab 10.3 EE [中将其添加到 API 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3516) . + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_branches?name=*-stable&allowed_to_push%5B%5D%5Buser_id%5D=1" +``` + +响应示例: + +``` +{ "id": 1, "name": "*-stable", "push_access_levels": [ { "access_level": null, "user_id": 1, "group_id": null, "access_level_description": "Administrator" } ], "merge_access_levels": [ { "access_level": 40, "user_id": null, "group_id": null, "access_level_description": "Maintainers" } ], "unprotect_access_levels": [ { "access_level": 40, "user_id": null, "group_id": null, "access_level_description": "Maintainers" } ], "code_owner_approval_required": "false" } +``` + +## Unprotect repository branches[](#unprotect-repository-branches "Permalink") + +取消保护给定的受保护分支或通配符受保护分支. + +``` +DELETE /projects/:id/protected_branches/:name +``` + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_branches/*-stable" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 分支名称 | + +## Require code owner approvals for a single branch[](#require-code-owner-approvals-for-a-single-branch "Permalink") + +为给定的受保护分支受保护分支更新"需要代码所有者批准"选项. + +``` +PATCH /projects/:id/protected_branches/:name +``` + +``` +curl --request PATCH --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_branches/feature-branch" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 分支名称 | +| `code_owner_approval_required` | boolean | no | 如果它与[`CODEOWNERS`文件](../user/project/code_owners.html)中的项目匹配,则阻止推送到此分支. (默认值:false) | \ No newline at end of file diff --git a/docs/355.md b/docs/355.md new file mode 100644 index 0000000000000000000000000000000000000000..db727351855489c47306b27be006e9f42cff4cae --- /dev/null +++ b/docs/355.md @@ -0,0 +1,108 @@ +# Protected tags API + +> 原文:[https://docs.gitlab.com/ee/api/protected_tags.html](https://docs.gitlab.com/ee/api/protected_tags.html) + +* [List protected tags](#list-protected-tags) +* [Get a single protected tag or wildcard protected tag](#get-a-single-protected-tag-or-wildcard-protected-tag) +* [Protect repository tags](#protect-repository-tags) +* [Unprotect repository tags](#unprotect-repository-tags) + +# Protected tags API[](#protected-tags-api "Permalink") + +**注意:**此功能是在 GitLab 11.3 中引入的 + +**有效的访问级别** + +当前,这些级别被认可: + +``` +0 => No access +30 => Developer access +40 => Maintainer access +``` + +## List protected tags[](#list-protected-tags "Permalink") + +从项目中获取受保护标签的列表. 此函数使用分页参数`page`和`per_page`来限制受保护标签的列表. + +``` +GET /projects/:id/protected_tags +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_tags" +``` + +响应示例: + +``` +[ { "name": "release-1-0", "create_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ] }, ... ] +``` + +## Get a single protected tag or wildcard protected tag[](#get-a-single-protected-tag-or-wildcard-protected-tag "Permalink") + +获取单个受保护标签或通配符受保护标签. 分页参数`page`和`per_page`可用于限制受保护标签的列表. + +``` +GET /projects/:id/protected_tags/:name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 标签或通配符的名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_tags/release-1-0" +``` + +响应示例: + +``` +{ "name": "release-1-0", "create_access_levels": [ { "access_level": 40, "access_level_description": "Maintainers" } ] } +``` + +## Protect repository tags[](#protect-repository-tags "Permalink") + +使用通配符保护的标签保护单个存储库标签或几个项目存储库标签. + +``` +POST /projects/:id/protected_tags +``` + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_tags?name=*-stable&create_access_level=30" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 标签或通配符的名称 | +| `create_access_level` | string | no | 允许创建的访问级别(默认值: `40` ,维护者访问级别) | + +响应示例: + +``` +{ "name": "*-stable", "create_access_levels": [ { "access_level": 30, "access_level_description": "Developers + Maintainers" } ] } +``` + +## Unprotect repository tags[](#unprotect-repository-tags "Permalink") + +取消保护给定的受保护标签或通配符受保护标签. + +``` +DELETE /projects/:id/protected_tags/:name +``` + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/protected_tags/*-stable" +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `name` | string | yes | 标签名称 | \ No newline at end of file diff --git a/docs/356.md b/docs/356.md new file mode 100644 index 0000000000000000000000000000000000000000..4da3b1bccf63a03875289155cf5f1c08ddb1afa4 --- /dev/null +++ b/docs/356.md @@ -0,0 +1,195 @@ +# Releases API + +> 原文:[https://docs.gitlab.com/ee/api/releases/](https://docs.gitlab.com/ee/api/releases/) + +* [List Releases](#list-releases) +* [Get a Release by a tag name](#get-a-release-by-a-tag-name) +* [Create a release](#create-a-release) +* [Collect release evidence](#collect-release-evidence-premium-only) +* [Update a release](#update-a-release) +* [Delete a Release](#delete-a-release) +* [Upcoming Releases](#upcoming-releases) + +# Releases API[](#releases-api "Permalink") + +版本历史 + +* 在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766) . +* 使用此 API,您可以操纵 GitLab 的[Release](../../user/project/releases/index.html)条目. +* 有关将链接作为发布资产进行操作,请参见[Release Links API](links.html) . +* 在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/26019)了发布证据. + +## List Releases[](#list-releases "Permalink") + +分页发布列表,按`released_at`排序. + +``` +GET /projects/:id/releases +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases" +``` + +响应示例: + +``` +[ { "tag_name":"v0.2", "description":"## CHANGELOG\r\n\r\n- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2740\r\n- Prevent private snippets from being embeddable.\r\n- Add subresources removal to member destroy service.", "name":"Awesome app v0.2 beta", "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eEscape label and milestone titles to prevent XSS in GFM autocomplete. !2740\u003c/li\u003e\n\u003cli\u003ePrevent private snippets from being embeddable.\u003c/li\u003e\n\u003cli\u003eAdd subresources removal to member destroy service.\u003c/li\u003e\n\u003c/ul\u003e", "created_at":"2019-01-03T01:56:19.539Z", "released_at":"2019-01-03T01:56:19.539Z", "author":{ "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/root" }, "commit":{ "id":"079e90101242458910cccd35eab0e211dfc359c0", "short_id":"079e9010", "title":"Update README.md", "created_at":"2019-01-03T01:55:38.000Z", "parent_ids":[ "f8d3d94cbd347e924aa7b715845e439d00e80ca4" ], "message":"Update README.md", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2019-01-03T01:55:38.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:55:38.000Z" }, "milestones": [ { "id":51, "iid":1, "project_id":24, "title":"v1.0-rc", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"closed", "created_at":"2019-07-12T19:45:44.256Z", "updated_at":"2019-07-12T19:45:44.256Z", "due_date":"2019-08-16T11:00:00.256Z", "start_date":"2019-07-30T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1", "issue_stats": { "total": 98, "closed": 76 } }, { "id":52, "iid":2, "project_id":24, "title":"v1.0", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"closed", "created_at":"2019-07-16T14:00:12.256Z", "updated_at":"2019-07-16T14:00:12.256Z", "due_date":"2019-08-16T11:00:00.256Z", "start_date":"2019-07-30T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2", "issue_stats": { "total": 24, "closed": 21 } } ], "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", "assets":{ "count":6, "sources":[ { "format":"zip", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.zip" }, { "format":"tar.gz", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar.gz" }, { "format":"tar.bz2", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar.bz2" }, { "format":"tar", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar" } ], "links":[ { "id":2, "name":"awesome-v0.2.msi", "url":"http://192.168.10.15:3000/msi", "external":true, "link_type":"other" }, { "id":1, "name":"awesome-v0.2.dmg", "url":"http://192.168.10.15:3000", "external":true, "link_type":"other" } ], "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.2/evidence.json" }, "evidences":[ { sha: "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", filepath: "https://gitlab.example.com/root/awesome-app/-/releases/v0.2/evidence.json", collected_at: "2019-01-03T01:56:19.539Z" } ] }, { "tag_name":"v0.1", "description":"## CHANGELOG\r\n\r\n-Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516", "name":"Awesome app v0.1 alpha", "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e", "created_at":"2019-01-03T01:55:18.203Z", "released_at":"2019-01-03T01:55:18.203Z", "author":{ "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/root" }, "commit":{ "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4", "short_id":"f8d3d94c", "title":"Initial commit", "created_at":"2019-01-03T01:53:28.000Z", "parent_ids":[ ], "message":"Initial commit", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2019-01-03T01:53:28.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:53:28.000Z" }, "assets":{ "count":4, "sources":[ { "format":"zip", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip" }, { "format":"tar.gz", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz" }, { "format":"tar.bz2", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2" }, { "format":"tar", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar" } ], "links":[ ], "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json" }, "evidences":[ { sha: "c3ffedec13af470e760d6cdfb08790f71cf52c6cde4d", filepath: "https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json", collected_at: "2019-01-03T01:55:18.203Z" } ] } ] +``` + +## Get a Release by a tag name[](#get-a-release-by-a-tag-name "Permalink") + +获取给定标签的发布. + +``` +GET /projects/:id/releases/:tag_name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 将在其中创建发行版的标签. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" +``` + +响应示例: + +``` +{ "tag_name":"v0.1", "description":"## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516", "name":"Awesome app v0.1 alpha", "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e", "created_at":"2019-01-03T01:55:18.203Z", "released_at":"2019-01-03T01:55:18.203Z", "author":{ "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/root" }, "commit":{ "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4", "short_id":"f8d3d94c", "title":"Initial commit", "created_at":"2019-01-03T01:53:28.000Z", "parent_ids":[ ], "message":"Initial commit", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2019-01-03T01:53:28.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:53:28.000Z" }, "milestones": [ { "id":51, "iid":1, "project_id":24, "title":"v1.0-rc", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"closed", "created_at":"2019-07-12T19:45:44.256Z", "updated_at":"2019-07-12T19:45:44.256Z", "due_date":"2019-08-16T11:00:00.256Z", "start_date":"2019-07-30T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1", "issue_stats": { "total": 98, "closed": 76 } }, { "id":52, "iid":2, "project_id":24, "title":"v1.0", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"closed", "created_at":"2019-07-16T14:00:12.256Z", "updated_at":"2019-07-16T14:00:12.256Z", "due_date":"2019-08-16T11:00:00.256Z", "start_date":"2019-07-30T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2", "issue_stats": { "total": 24, "closed": 21 } } ], "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", "assets":{ "count":5, "sources":[ { "format":"zip", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip" }, { "format":"tar.gz", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz" }, { "format":"tar.bz2", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2" }, { "format":"tar", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar" } ], "links":[ { "id":3, "name":"hoge", "url":"https://gitlab.example.com/root/awesome-app/-/tags/v0.11.1/binaries/linux-amd64", "external":true, "link_type":"other" } ] }, "evidences":[ { sha: "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", filepath: "https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json", collected_at: "2019-07-16T14:00:12.256Z" } ] } +``` + +## Create a release[](#create-a-release "Permalink") + +创建发布. 您需要对存储库的推送访问权限才能创建发行版. + +``` +POST /projects/:id/releases +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `name` | string | no | 发布名称. | +| `tag_name` | string | yes | 将在其中创建发行版的标签. | +| `description` | string | no | 版本说明. 您可以使用[Markdown](../../user/markdown.html) . | +| `ref` | string | 是的,如果`tag_name`不存在 | If `tag_name` doesn’t exist, the release will be created from `ref`. It can be a commit SHA, another tag name, or a branch name. | +| `milestones` | 字符串数组 | no | 与发行版关联的每个里程碑的标题. | +| `assets:links` | 哈希数组 | no | 一系列资产链接. | +| `assets:links:name` | string | 要求: `assets:links` | 链接的名称. | +| `assets:links:url` | string | 要求: `assets:links` | 链接的 URL. | +| `assets:links:filepath` | string | no | [直接资产链接的](../../user/project/releases.html)可选路径. | +| `assets:links:link_type` | string | no | 链接的类型: `other` , `runbook` , `image` , `package` . 默认为`other` . | +| `released_at` | datetime | no | 发布准备/准备就绪的日期. 默认为当前时间. 预期为 ISO 8601 格式( `2019-03-15T08:00:00Z` ). | + +请求示例: + +``` +curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" \ + --data '{ "name": "New release", "tag_name": "v0.3", "description": "Super nice release", "milestones": ["v1.0", "v1.0-rc"], "assets": { "links": [{ "name": "hoge", "url": "https://google.com", "filepath": "/binaries/linux-amd64", "link_type":"other" }] } }' \ + --request POST https://gitlab.example.com/api/v4/projects/24/releases +``` + +响应示例: + +``` +{ "tag_name":"v0.3", "description":"Super nice release", "name":"New release", "description_html":"\u003cp dir=\"auto\"\u003eSuper nice release\u003c/p\u003e", "created_at":"2019-01-03T02:22:45.118Z", "released_at":"2019-01-03T02:22:45.118Z", "author":{ "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/root" }, "commit":{ "id":"079e90101242458910cccd35eab0e211dfc359c0", "short_id":"079e9010", "title":"Update README.md", "created_at":"2019-01-03T01:55:38.000Z", "parent_ids":[ "f8d3d94cbd347e924aa7b715845e439d00e80ca4" ], "message":"Update README.md", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2019-01-03T01:55:38.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:55:38.000Z" }, "milestones": [ { "id":51, "iid":1, "project_id":24, "title":"v1.0-rc", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"closed", "created_at":"2019-07-12T19:45:44.256Z", "updated_at":"2019-07-12T19:45:44.256Z", "due_date":"2019-08-16T11:00:00.256Z", "start_date":"2019-07-30T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1", "issue_stats": { "total": 99, "closed": 76 } }, { "id":52, "iid":2, "project_id":24, "title":"v1.0", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"closed", "created_at":"2019-07-16T14:00:12.256Z", "updated_at":"2019-07-16T14:00:12.256Z", "due_date":"2019-08-16T11:00:00.256Z", "start_date":"2019-07-30T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2", "issue_stats": { "total": 24, "closed": 21 } } ], "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", "evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", "assets":{ "count":5, "sources":[ { "format":"zip", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.3/awesome-app-v0.3.zip" }, { "format":"tar.gz", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.3/awesome-app-v0.3.tar.gz" }, { "format":"tar.bz2", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.3/awesome-app-v0.3.tar.bz2" }, { "format":"tar", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.3/awesome-app-v0.3.tar" } ], "links":[ { "id":3, "name":"hoge", "url":"https://gitlab.example.com/root/awesome-app/-/tags/v0.11.1/binaries/linux-amd64", "external":true, "link_type":"other" } ], "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.3/evidence.json" }, } +``` + +## Collect release evidence[](#collect-release-evidence-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199065) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10. + +为现有版本创建证据. + +``` +POST /projects/:id/releases/:tag_name/evidence +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 将在其中创建发行版的标签. | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/evidence" +``` + +响应示例: + +``` +200 +``` + +## Update a release[](#update-a-release "Permalink") + +更新发行版. + +``` +PUT /projects/:id/releases/:tag_name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 将在其中创建发行版的标签. | +| `name` | string | no | 发布名称. | +| `description` | string | no | 版本说明. 您可以使用[Markdown](../../user/markdown.html) . | +| `milestones` | 字符串数组 | no | 与发布关联的每个里程碑的标题( `[]`从发布中删除所有里程碑). | +| `released_at` | datetime | no | 发布准备/准备就绪的日期. 预期为 ISO 8601 格式( `2019-03-15T08:00:00Z` ). | + +请求示例: + +``` +curl --header 'Content-Type: application/json' --request PUT --data '{"name": "new name", "milestones": ["v1.2"]}' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" +``` + +响应示例: + +``` +{ "tag_name":"v0.1", "description":"## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516", "name":"new name", "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e", "created_at":"2019-01-03T01:55:18.203Z", "released_at":"2019-01-03T01:55:18.203Z", "author":{ "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/root" }, "commit":{ "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4", "short_id":"f8d3d94c", "title":"Initial commit", "created_at":"2019-01-03T01:53:28.000Z", "parent_ids":[ ], "message":"Initial commit", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2019-01-03T01:53:28.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:53:28.000Z" }, "milestones": [ { "id":53, "iid":3, "project_id":24, "title":"v1.0", "description":"Voluptate fugiat possimus quis quod aliquam expedita.", "state":"active", "created_at":"2019-09-01T13:00:00.256Z", "updated_at":"2019-09-01T13:00:00.256Z", "due_date":"2019-09-20T13:00:00.256Z", "start_date":"2019-09-05T12:00:00.256Z", "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/3", "issue_stats": { "opened": 11, "closed": 78 } } ], "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", "evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", "assets":{ "count":4, "sources":[ { "format":"zip", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip" }, { "format":"tar.gz", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz" }, { "format":"tar.bz2", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2" }, { "format":"tar", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar" } ], "links":[ ], "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json" }, } +``` + +## Delete a Release[](#delete-a-release "Permalink") + +删除发行版. 删除发行版不会删除关联的标签. + +``` +DELETE /projects/:id/releases/:tag_name +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 将在其中创建发行版的标签. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" +``` + +响应示例: + +``` +{ "tag_name":"v0.1", "description":"## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516", "name":"new name", "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e", "created_at":"2019-01-03T01:55:18.203Z", "released_at":"2019-01-03T01:55:18.203Z", "author":{ "id":1, "name":"Administrator", "username":"root", "state":"active", "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", "web_url":"https://gitlab.example.com/root" }, "commit":{ "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4", "short_id":"f8d3d94c", "title":"Initial commit", "created_at":"2019-01-03T01:53:28.000Z", "parent_ids":[ ], "message":"Initial commit", "author_name":"Administrator", "author_email":"admin@example.com", "authored_date":"2019-01-03T01:53:28.000Z", "committer_name":"Administrator", "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:53:28.000Z" }, "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", "tag_path":"/root/awesome-app/-/tags/v0.11.1", "evidence_sha":"760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", "assets":{ "count":4, "sources":[ { "format":"zip", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip" }, { "format":"tar.gz", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz" }, { "format":"tar.bz2", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2" }, { "format":"tar", "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar" } ], "links":[ ], "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json" }, } +``` + +## Upcoming Releases[](#upcoming-releases "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/38105) . + +有一种剥离`released_at`属性设置为将来的日期将被标记在 UI **即将推出**的**版本** : + +[![Upcoming release](img/c1ff864dc0ff6749087bc64b4781d767.png)](img/upcoming_release_v12_1.png) \ No newline at end of file diff --git a/docs/357.md b/docs/357.md new file mode 100644 index 0000000000000000000000000000000000000000..fcd51acc20d0288ba448ae9f6f0b2ff52f0360b5 --- /dev/null +++ b/docs/357.md @@ -0,0 +1,155 @@ +# Release links API + +> 原文:[https://docs.gitlab.com/ee/api/releases/links.html](https://docs.gitlab.com/ee/api/releases/links.html) + +* [Get links](#get-links) +* [Get a link](#get-a-link) +* [Create a link](#create-a-link) +* [Update a link](#update-a-link) +* [Delete a link](#delete-a-link) + +# Release links API[](#release-links-api "Permalink") + +在 GitLab 11.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766) . + +使用此 API,您可以操纵 GitLab 的[Release](../../user/project/releases/index.html)链接. 有关操纵其他 Release 资产的信息,请参见[Release API](index.html) . GitLab 支持指向`http` , `https`和`ftp`资产的链接. + +## Get links[](#get-links "Permalink") + +从发布中获取资产作为链接. + +``` +GET /projects/:id/releases/:tag_name/assets/links +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 与发行版关联的标签. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links" +``` + +响应示例: + +``` +[ { "id":2, "name":"awesome-v0.2.msi", "url":"http://192.168.10.15:3000/msi", "external":true, "link_type":"other" }, { "id":1, "name":"awesome-v0.2.dmg", "url":"http://192.168.10.15:3000", "external":true, "link_type":"other" } ] +``` + +## Get a link[](#get-a-link "Permalink") + +从发布中获取资产作为链接. + +``` +GET /projects/:id/releases/:tag_name/assets/links/:link_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 与发行版关联的标签. | +| `link_id` | integer | yes | 链接的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1" +``` + +响应示例: + +``` +{ "id":1, "name":"awesome-v0.2.dmg", "url":"http://192.168.10.15:3000", "external":true, "link_type":"other" } +``` + +## Create a link[](#create-a-link "Permalink") + +从发布创建资产作为链接. + +``` +POST /projects/:id/releases/:tag_name/assets/links +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 与发行版关联的标签. | +| `name` | string | yes | 链接的名称. | +| `url` | string | yes | 链接的 URL. | +| `link_type` | string | no | 链接的类型: `other` , `runbook` , `image` , `package` . 默认为`other` . | + +请求示例: + +``` +curl --request POST \ + --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" \ + --data name="awesome-v0.2.dmg" \ + --data url="http://192.168.10.15:3000" \ + "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links" +``` + +响应示例: + +``` +{ "id":1, "name":"awesome-v0.2.dmg", "url":"http://192.168.10.15:3000", "external":true, "link_type":"other" } +``` + +## Update a link[](#update-a-link "Permalink") + +将资产更新为发布中的链接. + +``` +PUT /projects/:id/releases/:tag_name/assets/links/:link_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 与发行版关联的标签. | +| `link_id` | integer | yes | 链接的 ID. | +| `name` | string | no | 链接的名称. | +| `url` | string | no | 链接的 URL. | +| `link_type` | string | no | 链接的类型: `other` , `runbook` , `image` , `package` . 默认为`other` . | + +**注意**您必须至少指定`name`或`url` + +请求示例: + +``` +curl --request PUT --data name="new name" --data link_type="runbook" --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1" +``` + +响应示例: + +``` +{ "id":1, "name":"new name", "url":"http://192.168.10.15:3000", "external":true, "link_type":"runbook" } +``` + +## Delete a link[](#delete-a-link "Permalink") + +从发布中删除资产作为链接. + +``` +DELETE /projects/:id/releases/:tag_name/assets/links/:link_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](../README.html#namespaced-path-encoding) . | +| `tag_name` | string | yes | 与发行版关联的标签. | +| `link_id` | integer | yes | 链接的 ID. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1" +``` + +响应示例: + +``` +{ "id":1, "name":"new name", "url":"http://192.168.10.15:3000", "external":true, "link_type":"other" } +``` \ No newline at end of file diff --git a/docs/358.md b/docs/358.md new file mode 100644 index 0000000000000000000000000000000000000000..a58f425b845128e660f4a30d1d13b5b77765f007 --- /dev/null +++ b/docs/358.md @@ -0,0 +1,150 @@ +# Repositories API + +> 原文:[https://docs.gitlab.com/ee/api/repositories.html](https://docs.gitlab.com/ee/api/repositories.html) + +* [List repository tree](#list-repository-tree) +* [Get a blob from repository](#get-a-blob-from-repository) +* [Raw blob content](#raw-blob-content) +* [Get file archive](#get-file-archive) +* [Compare branches, tags or commits](#compare-branches-tags-or-commits) +* [Contributors](#contributors) +* [Merge Base](#merge-base) + +# Repositories API[](#repositories-api "Permalink") + +## List repository tree[](#list-repository-tree "Permalink") + +获取项目中存储库文件和目录的列表. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +此命令提供的功能与`git ls-tree`命令基本相同. 有关更多信息,请参阅[Git internals 文档](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects/#_tree_objects)中的*Tree Objects*部分. + +``` +GET /projects/:id/repository/tree +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `path` (可选)-存储库中的路径. 用于获取子目录的内容 +* `ref` (可选)-存储库分支或标记的名称,或者如果未提供默认分支的名称 +* `recursive` (可选)-用于获取递归树的布尔值(默认为 false) +* `per_page` (可选)-每页显示的结果数. 如果未指定,则默认为`20` + +``` +[ { "id": "a1e8f8d745cc87e3a9248358d9352bb7f9a0aeba", "name": "html", "type": "tree", "path": "files/html", "mode": "040000" }, { "id": "4535904260b1082e14f867f7a24fd8c21495bde3", "name": "images", "type": "tree", "path": "files/images", "mode": "040000" }, { "id": "31405c5ddef582c5a9b7a85230413ff90e2fe720", "name": "js", "type": "tree", "path": "files/js", "mode": "040000" }, { "id": "cc71111cfad871212dc99572599a568bfe1e7e00", "name": "lfs", "type": "tree", "path": "files/lfs", "mode": "040000" }, { "id": "fd581c619bf59cfdfa9c8282377bb09c2f897520", "name": "markdown", "type": "tree", "path": "files/markdown", "mode": "040000" }, { "id": "23ea4d11a4bdd960ee5320c5cb65b5b3fdbc60db", "name": "ruby", "type": "tree", "path": "files/ruby", "mode": "040000" }, { "id": "7d70e02340bac451f281cecf0a980907974bd8be", "name": "whitespace", "type": "blob", "path": "files/whitespace", "mode": "100644" } ] +``` + +## Get a blob from repository[](#get-a-blob-from-repository "Permalink") + +Allows you to receive information about blob in repository like size and content. Note that blob content is Base64 encoded. This endpoint can be accessed without authentication if the repository is publicly accessible. + +``` +GET /projects/:id/repository/blobs/:sha +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `sha` (必填)-Blob SHA + +## Raw blob content[](#raw-blob-content "Permalink") + +通过 blob SHA 获取 blob 的原始文件内容. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/blobs/:sha/raw +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `sha` (必填)-Blob SHA + +## Get file archive[](#get-file-archive "Permalink") + +获取存储库的存档. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +该端点的速率限制阈值为每分钟 5 个请求. + +``` +GET /projects/:id/repository/archive[.format] +``` + +`format`是归档格式的可选后缀. 默认值为`tar.gz` 选项是`tar.gz` , `tar.bz2` , `tbz` , `tbz2` , `tb2` , `bz2` , `tar`和`zip` . 例如,指定`archive.zip`将以 ZIP 格式发送存档. + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `sha` (可选)-提交要下载的 SHA. 可以使用标签,分支引用或 SHA. 如果未指定,则默认为默认分支的尖端. 例如: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.com/api/v4/projects//repository/archive?sha=" +``` + +## Compare branches, tags or commits[](#compare-branches-tags-or-commits "Permalink") + +如果可公开访问该存储库,则无需身份验证即可访问此端点. 请注意,如果达到[差异限制](../development/diffs.html#diff-limits) ,差异可能会有一个空的差异字符串. + +``` +GET /projects/:id/repository/compare +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `from` (必填)-提交 SHA 或分支名称 +* `to` (必需)-提交 SHA 或分支名称 +* `straight` (可选)-比较方法,对于`from`和`to`之间( `from` .. `to` )之间的直接比较,为`true`对于使用合并基数( `from` ... `to` )'比较`to` `false` . 默认值为`false` . + +``` +GET /projects/:id/repository/compare?from=master&to=feature +``` + +Response: + +``` + { "commit": { "id": "12d65c8dd2b2676fa3ac47d955accc085a37a9c1", "short_id": "12d65c8dd2b", "title": "JS fix", "author_name": "Example User", "author_email": "user@example.com", "created_at": "2014-02-27T10:27:00+02:00" }, "commits": [{ "id": "12d65c8dd2b2676fa3ac47d955accc085a37a9c1", "short_id": "12d65c8dd2b", "title": "JS fix", "author_name": "Example User", "author_email": "user@example.com", "created_at": "2014-02-27T10:27:00+02:00" }], "diffs": [{ "old_path": "files/js/application.js", "new_path": "files/js/application.js", "a_mode": null, "b_mode": "100644", "diff": "--- a/files/js/application.js\n+++ b/files/js/application.js\n@@ -24,8 +24,10 @@\n //= require g.raphael-min\n //= require g.bar-min\n //= require branch-graph\n-//= require highlightjs.min\n-//= require ace/ace\n //= require_tree .\n //= require d3\n //= require underscore\n+\n+function fix() { \n+ alert(\"Fixed\")\n+}", "new_file": false, "renamed_file": false, "deleted_file": false }], "compare_timeout": false, "compare_same_ref": false } +``` + +## Contributors[](#contributors "Permalink") + +获取存储库贡献者列表. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/contributors +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `order_by` (可选)-返回按`name` , `email`或`commits` (按提交日期排序)字段排序的贡献者. 默认为`commits` +* `sort` (可选)-返回贡献者按`asc`或`desc`顺序排序. 默认为`asc` + +Response: + +``` +[{ "name": "Example User", "email": "example@example.com", "commits": 117, "additions": 2097, "deletions": 517 }, { "name": "Sample User", "email": "sample@example.com", "commits": 33, "additions": 338, "deletions": 244 }] +``` + +## Merge Base[](#merge-base "Permalink") + +获取 2 个或更多引用(提交 SHA,分支名称或标签)的公共祖先. + +``` +GET /projects/:id/repository/merge_base +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `refs` | array | yes | 裁判找到共同的祖先,可以传递多个裁判 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/merge_base?refs[]=304d257dcb821665ab5110318fc58a007bd104ed&refs[]=0031876facac3f2b2702a0e53a26e89939a42209" +``` + +响应示例: + +``` +{ "id": "1a0b36b3cdad1d2ee32457c102a8c0b7056fa863", "short_id": "1a0b36b3", "title": "Initial commit", "created_at": "2014-02-27T08:03:18.000Z", "parent_ids": [], "message": "Initial commit\n", "author_name": "Example User", "author_email": "user@example.com", "authored_date": "2014-02-27T08:03:18.000Z", "committer_name": "Example User", "committer_email": "user@example.com", "committed_date": "2014-02-27T08:03:18.000Z" } +``` \ No newline at end of file diff --git a/docs/359.md b/docs/359.md new file mode 100644 index 0000000000000000000000000000000000000000..bece27cea359a6c2f36459d5455a75bd145127f8 --- /dev/null +++ b/docs/359.md @@ -0,0 +1,238 @@ +# Repository files API + +> 原文:[https://docs.gitlab.com/ee/api/repository_files.html](https://docs.gitlab.com/ee/api/repository_files.html) + +* [Get file from repository](#get-file-from-repository) +* [Get file blame from repository](#get-file-blame-from-repository) +* [Get raw file from repository](#get-raw-file-from-repository) +* [Create new file in repository](#create-new-file-in-repository) +* [Update existing file in repository](#update-existing-file-in-repository) +* [Delete existing file in repository](#delete-existing-file-in-repository) + +# Repository files API[](#repository-files-api "Permalink") + +**库文件的 CRUD** + +**使用此 API 创建,读取,更新和删除存储库文件** + +下表描述了使用[个人访问令牌](../user/profile/personal_access_tokens.html)可用的不同范围. + +| Scope | Description | +| --- | --- | +| `read_repository` | 允许对存储库文件进行读取访问. | +| `api` | 允许对存储库文件进行读写访问. | + +`read_repository` scope was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23534) in GitLab 11.6. + +## Get file from repository[](#get-file-from-repository "Permalink") + +允许您接收有关存储库中文件的信息,例如名称,大小,内容. 请注意,文件内容是 Base64 编码的. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/files/:file_path +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master" +``` + +响应示例: + +``` +{ "file_name": "key.rb", "file_path": "app/models/key.rb", "size": 1476, "encoding": "base64", "content": "IyA9PSBTY2hlbWEgSW5mb3...", "content_sha256": "4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481", "ref": "master", "blob_id": "79f7bbd25901e8334750839545a9bd021f0e4c83", "commit_id": "d5a3ff139356ce33e37e73add446f16869741b50", "last_commit_id": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d" } +``` + +Parameters: + +* `file_path` (必需)-URL 编码的新文件的完整路径. 例如 lib%2Fclass%2Erb +* `ref` (必填)-分支,标记或提交的名称 + +**注意:** `blob_id`是 blob SHA,请参见[存储库-从存储库获取 blob](repositories.html#get-a-blob-from-repository) + +除了`GET`方法外,您还可以使用`HEAD`来获取文件元数据. + +``` +HEAD /projects/:id/repository/files/:file_path +``` + +``` +curl --head --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master" +``` + +响应示例: + +``` +HTTP/1.1 200 OK +... +X-Gitlab-Blob-Id: 79f7bbd25901e8334750839545a9bd021f0e4c83 +X-Gitlab-Commit-Id: d5a3ff139356ce33e37e73add446f16869741b50 +X-Gitlab-Content-Sha256: 4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481 +X-Gitlab-Encoding: base64 +X-Gitlab-File-Name: key.rb +X-Gitlab-File-Path: app/models/key.rb +X-Gitlab-Last-Commit-Id: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d +X-Gitlab-Ref: master +X-Gitlab-Size: 1476 +... +``` + +## Get file blame from repository[](#get-file-blame-from-repository "Permalink") + +允许您接收责备信息. 每个责任范围包含行和相应的提交信息. + +``` +GET /projects/:id/repository/files/:file_path/blame +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/13083/repository/files/path%2Fto%2Ffile.rb/blame?ref=master" +``` + +响应示例: + +``` +[ { "commit": { "id": "d42409d56517157c48bf3bd97d3f75974dde19fb", "message": "Add feature\n\nalso fix bug\n", "parent_ids": [ "cc6e14f9328fa6d7b5a0d3c30dc2002a3f2a3822" ], "authored_date": "2015-12-18T08:12:22.000Z", "author_name": "John Doe", "author_email": "john.doe@example.com", "committed_date": "2015-12-18T08:12:22.000Z", "committer_name": "John Doe", "committer_email": "john.doe@example.com" }, "lines": [ "require 'fileutils'", "require 'open3'", "" ] }, ... ] +``` + +Parameters: + +* `file_path` (必需)-URL 编码的新文件的完整路径. 例如 lib%2Fclass%2Erb +* `ref` (必填)-分支,标记或提交的名称 + +**注意:** `HEAD`方法仅返回文件元数据,如[从存储库](repository_files.html#get-file-from-repository)中[获取文件中所示](repository_files.html#get-file-from-repository) . + +``` +curl --head --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/13083/repository/files/path%2Fto%2Ffile.rb/blame?ref=master" +``` + +响应示例: + +``` +HTTP/1.1 200 OK +... +X-Gitlab-Blob-Id: 79f7bbd25901e8334750839545a9bd021f0e4c83 +X-Gitlab-Commit-Id: d5a3ff139356ce33e37e73add446f16869741b50 +X-Gitlab-Content-Sha256: 4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481 +X-Gitlab-Encoding: base64 +X-Gitlab-File-Name: file.rb +X-Gitlab-File-Path: path/to/file.rb +X-Gitlab-Last-Commit-Id: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d +X-Gitlab-Ref: master +X-Gitlab-Size: 1476 +... +``` + +## Get raw file from repository[](#get-raw-file-from-repository "Permalink") + +``` +GET /projects/:id/repository/files/:file_path/raw +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb/raw?ref=master" +``` + +Parameters: + +* `file_path` (必需)-URL 编码的新文件的完整路径. 例如 lib%2Fclass%2Erb +* `ref` (必填)-分支,标记或提交的名称 + +**注意:**像[从存储库中获取文件](repository_files.html#get-file-from-repository)一样[,](repository_files.html#get-file-from-repository)您可以使用`HEAD`仅获取文件元数据. + +## Create new file in repository[](#create-new-file-in-repository "Permalink") + +这使您可以创建一个文件. 要使用一个请求创建多个文件,请参阅[commits API](commits.html#create-a-commit-with-multiple-files-and-actions) . + +``` +POST /projects/:id/repository/files/:file_path +``` + +``` +curl --request POST --header 'PRIVATE-TOKEN: ' --header "Content-Type: application/json" \ + --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \ + "content": "some content", "commit_message": "create a new file"}' \ + "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb" +``` + +响应示例: + +``` +{ "file_path": "app/project.rb", "branch": "master" } +``` + +Parameters: + +* `file_path` (必需)-URL 编码的新文件的完整路径. 例如 lib%2Fclass%2Erb +* `branch` (必填)-分支的名称 +* `start_branch` (可选)-从中开始新提交的分支名称 +* `encoding` (可选)-将编码更改为" base64". 默认为文本. +* `author_email` (可选)-指定提交作者的电子邮件地址 +* `author_name` (可选)-指定提交作者的姓名 +* `content` (必填)-文件内容 +* `commit_message` (必填)-提交消息 + +## Update existing file in repository[](#update-existing-file-in-repository "Permalink") + +这使您可以更新单个文件. 有关通过单个请求更新多个文件的信息,请参见[commits API](commits.html#create-a-commit-with-multiple-files-and-actions) . + +``` +PUT /projects/:id/repository/files/:file_path +``` + +``` +curl --request PUT --header 'PRIVATE-TOKEN: ' --header "Content-Type: application/json" \ + --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \ + "content": "some content", "commit_message": "update file"}' \ + "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb" +``` + +响应示例: + +``` +{ "file_path": "app/project.rb", "branch": "master" } +``` + +Parameters: + +* `file_path` (必需)-URL 编码的新文件的完整路径. 例如 lib%2Fclass%2Erb +* `branch` (必填)-分支的名称 +* `start_branch` (可选)-从中开始新提交的分支名称 +* `encoding` (可选)-将编码更改为" base64". 默认为文本. +* `author_email` (可选)-指定提交作者的电子邮件地址 +* `author_name` (可选)-指定提交作者的姓名 +* `content` (必填)-新文件内容 +* `commit_message` (必填)-提交消息 +* `last_commit_id` (可选)-已知文件的最新提交 ID + +如果提交由于任何原因失败,我们将返回 400 错误,并显示非特定错误消息. 提交失败的可能原因包括: + +* `file_path`包含`/../` (试图遍历目录); +* 新文件内容与当前文件内容相同. 也就是说,用户尝试进行空提交; +* 在进行文件编辑时,通过 Git 推送更新了分支. + +当前,GitLab Shell 具有布尔返回码,可防止 GitLab 指定错误. + +## Delete existing file in repository[](#delete-existing-file-in-repository "Permalink") + +这使您可以删除单个文件. 有关通过单个请求删除多个文件的信息,请参见[commits API](commits.html#create-a-commit-with-multiple-files-and-actions) . + +``` +DELETE /projects/:id/repository/files/:file_path +``` + +``` +curl --request DELETE --header 'PRIVATE-TOKEN: ' --header "Content-Type: application/json" \ + --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \ + "commit_message": "delete file"}' \ + "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb" +``` + +Parameters: + +* `file_path` (必需)-URL 编码的新文件的完整路径. 例如 lib%2Fclass%2Erb +* `branch` (必填)-分支的名称 +* `start_branch` (可选)-从中开始新提交的分支名称 +* `author_email` (可选)-指定提交作者的电子邮件地址 +* `author_name` (可选)-指定提交作者的姓名 +* `commit_message` (必填)-提交消息 +* `last_commit_id` (可选)-已知文件的最新提交 ID \ No newline at end of file diff --git a/docs/360.md b/docs/360.md new file mode 100644 index 0000000000000000000000000000000000000000..a12645ec7d7bbdc79d52209b2e36fa620086c94b --- /dev/null +++ b/docs/360.md @@ -0,0 +1,36 @@ +# Repository submodules API + +> 原文:[https://docs.gitlab.com/ee/api/repository_submodules.html](https://docs.gitlab.com/ee/api/repository_submodules.html) + +* [Update existing submodule reference in repository](#update-existing-submodule-reference-in-repository) + +# Repository submodules API[](#repository-submodules-api "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41213) + +## Update existing submodule reference in repository[](#update-existing-submodule-reference-in-repository "Permalink") + +在某些工作流程中,尤其是自动化的工作流程中,更新子模块的引用以使使用它的其他项目保持最新是很有用的. 该端点允许您在特定分支中更新[Git 子模块](https://git-scm.com/book/en/v2/Git-Tools-Submodules)引用. + +``` +PUT /projects/:id/repository/submodules/:submodule +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `submodule` | string | yes | URL 编码的子模块完整路径. 例如, `lib/class.rb` | +| `branch` | string | yes | 要提交的分支名称 | +| `commit_sha` | string | yes | 完全提交 SHA 以将子模块更新为 | +| `commit_message` | string | no | 提交消息. 如果未提供任何消息,则将设置默认消息 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/submodules/lib%2Fmodules%2Fexample" +--data "branch=master&commit_sha=3ddec28ea23acc5caa5d8331a6ecb2a65fc03e88&commit_message=Update submodule reference" +``` + +响应示例: + +``` +{ "id": "ed899a2f4b50b4370feeea94676502b42383c746", "short_id": "ed899a2f4b5", "title": "Updated submodule example_submodule with oid 3ddec28ea23acc5caa5d8331a6ecb2a65fc03e88", "author_name": "Dmitriy Zaporozhets", "author_email": "dzaporozhets@sphereconsultinginc.com", "committer_name": "Dmitriy Zaporozhets", "committer_email": "dzaporozhets@sphereconsultinginc.com", "created_at": "2018-09-20T09:26:24.000-07:00", "message": "Updated submodule example_submodule with oid 3ddec28ea23acc5caa5d8331a6ecb2a65fc03e88", "parent_ids": [ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" ], "committed_date": "2018-09-20T09:26:24.000-07:00", "authored_date": "2018-09-20T09:26:24.000-07:00", "status": null } +``` \ No newline at end of file diff --git a/docs/361.md b/docs/361.md new file mode 100644 index 0000000000000000000000000000000000000000..73ffe54f7b09ba150c70ef323e57d148efb81ca7 --- /dev/null +++ b/docs/361.md @@ -0,0 +1,146 @@ +# Resource label events API + +> 原文:[https://docs.gitlab.com/ee/api/resource_label_events.html](https://docs.gitlab.com/ee/api/resource_label_events.html) + +* [Issues](#issues) + * [List project issue label events](#list-project-issue-label-events) + * [Get single issue label event](#get-single-issue-label-event) +* [Epics](#epics-ultimate) + * [List group epic label events](#list-group-epic-label-events) + * [Get single epic label event](#get-single-epic-label-event) +* [Merge requests](#merge-requests) + * [List project merge request label events](#list-project-merge-request-label-events) + * [Get single merge request label event](#get-single-merge-request-label-event) + +# Resource label events API[](#resource-label-events-api "Permalink") + +资源标签事件可跟踪有关向可发行对象添加或删除对象的时间,对象和对象. + +## Issues[](#issues "Permalink") + +### List project issue label events[](#list-project-issue-label-events "Permalink") + +获取单个问题的所有标签事件的列表. + +``` +GET /projects/:id/issues/:issue_iid/resource_label_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | + +``` +[ { "id": 142, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T13:38:20.077Z", "resource_type": "Issue", "resource_id": 253, "label": { "id": 73, "name": "a1", "color": "#34495E", "description": "" }, "action": "add" }, { "id": 143, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T13:38:20.077Z", "resource_type": "Issue", "resource_id": 253, "label": { "id": 74, "name": "p1", "color": "#0033CC", "description": "" }, "action": "remove" } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_label_events" +``` + +### Get single issue label event[](#get-single-issue-label-event "Permalink") + +返回特定项目问题的单个标签事件 + +``` +GET /projects/:id/issues/:issue_iid/resource_label_events/:resource_label_event_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `resource_label_event_id` | integer | yes | 标签事件的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_label_events/1" +``` + +## Epics[](#epics-ultimate "Permalink") + +### List group epic label events[](#list-group-epic-label-events "Permalink") + +获取单个史诗的所有标签事件的列表. + +``` +GET /groups/:id/epics/:epic_id/resource_label_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | + +``` +[ { "id": 106, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-19T11:43:01.746Z", "resource_type": "Epic", "resource_id": 33, "label": { "id": 73, "name": "a1", "color": "#34495E", "description": "" }, "action": "add" }, { "id": 107, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-19T11:43:01.746Z", "resource_type": "Epic", "resource_id": 33, "label": { "id": 37, "name": "glabel2", "color": "#A8D695", "description": "" }, "action": "add" } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/11/resource_label_events" +``` + +### Get single epic label event[](#get-single-epic-label-event "Permalink") + +返回特定组史诗的单个标签事件 + +``` +GET /groups/:id/epics/:epic_id/resource_label_events/:resource_label_event_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `epic_id` | integer | yes | 史诗的 ID | +| `resource_label_event_id` | integer | yes | 标签事件的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/epics/11/resource_label_events/107" +``` + +## Merge requests[](#merge-requests "Permalink") + +### List project merge request label events[](#list-project-merge-request-label-events "Permalink") + +获取单个合并请求的所有标签事件的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/resource_label_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | + +``` +[ { "id": 119, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T06:17:28.394Z", "resource_type": "MergeRequest", "resource_id": 28, "label": { "id": 74, "name": "p1", "color": "#0033CC", "description": "" }, "action": "add" }, { "id": 120, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T06:17:28.394Z", "resource_type": "MergeRequest", "resource_id": 28, "label": { "id": 41, "name": "project", "color": "#D1D100", "description": "" }, "action": "add" } ] +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/resource_label_events" +``` + +### Get single merge request label event[](#get-single-merge-request-label-event "Permalink") + +返回特定项目合并请求的单个标签事件 + +``` +GET /projects/:id/merge_requests/:merge_request_iid/resource_label_events/:resource_label_event_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `resource_label_event_id` | integer | yes | 标签事件的 ID | + +``` +curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/resource_label_events/120" +``` \ No newline at end of file diff --git a/docs/362.md b/docs/362.md new file mode 100644 index 0000000000000000000000000000000000000000..b492b46c8bcef59ec72a7b2ce3fa1e3b913c63ba --- /dev/null +++ b/docs/362.md @@ -0,0 +1,114 @@ +# Resource milestone events API + +> 原文:[https://docs.gitlab.com/ee/api/resource_milestone_events.html](https://docs.gitlab.com/ee/api/resource_milestone_events.html) + +* [Issues](#issues) + * [List project issue milestone events](#list-project-issue-milestone-events) + * [Get single issue milestone event](#get-single-issue-milestone-event) +* [Merge requests](#merge-requests) + * [List project merge request milestone events](#list-project-merge-request-milestone-events) + * [Get single merge request milestone event](#get-single-merge-request-milestone-event) + +# Resource milestone events API[](#resource-milestone-events-api "Permalink") + +资源里程碑事件跟踪 GitLab [问题](../user/project/issues/)和[合并请求的处理情况](../user/project/merge_requests/) . + +使用它们来跟踪添加或删除了哪个里程碑,谁进行了里程碑以及何时发生. + +## Issues[](#issues "Permalink") + +### List project issue milestone events[](#list-project-issue-milestone-events "Permalink") + +获取单个问题的所有里程碑事件的列表. + +``` +GET /projects/:id/issues/:issue_iid/resource_milestone_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_milestone_events" +``` + +响应示例: + +``` +[ { "id": 142, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T13:38:20.077Z", "resource_type": "Issue", "resource_id": 253, "milestone": { "id": 61, "iid": 9, "project_id": 7, "title": "v1.2", "description": "Ipsum Lorem", "state": "active", "created_at": "2020-01-27T05:07:12.573Z", "updated_at": "2020-01-27T05:07:12.573Z", "due_date": null, "start_date": null, "web_url": "http://gitlab.example.com:3000/group/project/-/milestones/9" }, "action": "add" }, { "id": 143, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-21T14:38:20.077Z", "resource_type": "Issue", "resource_id": 253, "milestone": { "id": 61, "iid": 9, "project_id": 7, "title": "v1.2", "description": "Ipsum Lorem", "state": "active", "created_at": "2020-01-27T05:07:12.573Z", "updated_at": "2020-01-27T05:07:12.573Z", "due_date": null, "start_date": null, "web_url": "http://gitlab.example.com:3000/group/project/-/milestones/9" }, "action": "remove" } ] +``` + +### Get single issue milestone event[](#get-single-issue-milestone-event "Permalink") + +返回特定项目问题的单个里程碑事件 + +``` +GET /projects/:id/issues/:issue_iid/resource_milestone_events/:resource_milestone_event_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `resource_milestone_event_id` | integer | yes | 里程碑事件的 ID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_milestone_events/1" +``` + +## Merge requests[](#merge-requests "Permalink") + +### List project merge request milestone events[](#list-project-merge-request-milestone-events "Permalink") + +获取单个合并请求的所有里程碑事件的列表. + +``` +GET /projects/:id/merge_requests/:merge_request_iid/resource_milestone_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/resource_milestone_events" +``` + +响应示例: + +``` +[ { "id": 142, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T13:38:20.077Z", "resource_type": "MergeRequest", "resource_id": 142, "milestone": { "id": 61, "iid": 9, "project_id": 7, "title": "v1.2", "description": "Ipsum Lorem", "state": "active", "created_at": "2020-01-27T05:07:12.573Z", "updated_at": "2020-01-27T05:07:12.573Z", "due_date": null, "start_date": null, "web_url": "http://gitlab.example.com:3000/group/project/-/milestones/9" }, "action": "add" }, { "id": 143, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-21T14:38:20.077Z", "resource_type": "MergeRequest", "resource_id": 142, "milestone": { "id": 61, "iid": 9, "project_id": 7, "title": "v1.2", "description": "Ipsum Lorem", "state": "active", "created_at": "2020-01-27T05:07:12.573Z", "updated_at": "2020-01-27T05:07:12.573Z", "due_date": null, "start_date": null, "web_url": "http://gitlab.example.com:3000/group/project/-/milestones/9" }, "action": "remove" } ] +``` + +### Get single merge request milestone event[](#get-single-merge-request-milestone-event "Permalink") + +返回特定项目合并请求的单个里程碑事件 + +``` +GET /projects/:id/merge_requests/:merge_request_iid/resource_milestone_events/:resource_milestone_event_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | 合并请求的 IID | +| `resource_milestone_event_id` | integer | yes | 里程碑事件的 ID | + +请求示例: + +``` +curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/resource_milestone_events/120" +``` \ No newline at end of file diff --git a/docs/363.md b/docs/363.md new file mode 100644 index 0000000000000000000000000000000000000000..74ed5a7919cf09294face47920ab8ddcf3830a78 --- /dev/null +++ b/docs/363.md @@ -0,0 +1,68 @@ +# Resource weight events API + +> 原文:[https://docs.gitlab.com/ee/api/resource_weight_events.html](https://docs.gitlab.com/ee/api/resource_weight_events.html) + +* [Issues](#issues) + * [List project issue weight events](#list-project-issue-weight-events) + * [Get single issue weight event](#get-single-issue-weight-event) + +# Resource weight events API[](#resource-weight-events-api "Permalink") + +资源权重事件跟踪 GitLab [问题的](../user/project/issues/)发生情况. + +使用它们来跟踪设置了哪些权重,由谁进行权重以及何时发生. + +## Issues[](#issues "Permalink") + +### List project issue weight events[](#list-project-issue-weight-events "Permalink") + +获取单个问题的所有举重事件的列表. + +``` +GET /projects/:id/issues/:issue_iid/resource_weight_events +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_weight_events" +``` + +响应示例: + +``` +[ { "id": 142, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-20T13:38:20.077Z", "issue_id": 253, "weight": 3 }, { "id": 143, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-21T14:38:20.077Z", "issue_id": 253, "weight": 2 } ] +``` + +### Get single issue weight event[](#get-single-issue-weight-event "Permalink") + +返回特定项目问题的单个权重事件 + +``` +GET /projects/:id/issues/:issue_iid/resource_weight_events/:resource_weight_event_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `issue_iid` | integer | yes | 问题的 IID | +| `resource_weight_event_id` | integer | yes | 举重事件的 ID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_weight_events/143" +``` + +响应示例: + +``` +{ "id": 143, "user": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://gitlab.example.com/root" }, "created_at": "2018-08-21T14:38:20.077Z", "issue_id": 253, "weight": 2 } +``` \ No newline at end of file diff --git a/docs/364.md b/docs/364.md new file mode 100644 index 0000000000000000000000000000000000000000..1d0a259a294d446da9eb16697a99d99e1e8a80c6 --- /dev/null +++ b/docs/364.md @@ -0,0 +1,378 @@ +# Runners API + +> 原文:[https://docs.gitlab.com/ee/api/runners.html](https://docs.gitlab.com/ee/api/runners.html) + +* [Registration and authentication tokens](#registration-and-authentication-tokens) +* [List owned runners](#list-owned-runners) +* [List all runners](#list-all-runners) +* [Get runner’s details](#get-runners-details) +* [Update runner’s details](#update-runners-details) +* [Remove a runner](#remove-a-runner) +* [List runner’s jobs](#list-runners-jobs) +* [List project’s runners](#list-projects-runners) +* [Enable a runner in project](#enable-a-runner-in-project) +* [Disable a runner from project](#disable-a-runner-from-project) +* [List group’s runners](#list-groups-runners) +* [Register a new Runner](#register-a-new-runner) +* [Delete a registered Runner](#delete-a-registered-runner) +* [Verify authentication for a registered Runner](#verify-authentication-for-a-registered-runner) + +# Runners API[](#runners-api "Permalink") + +在 GitLab 8.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2640) + +## Registration and authentication tokens[](#registration-and-authentication-tokens "Permalink") + +将 Runner 与 GitLab 连接时要考虑两个标记. + +| Token | Description | +| --- | --- | +| 注册令牌 | 用于[注册 Runner 的](https://docs.gitlab.com/runner/register/)令牌. 可以[通过 GitLab 获得](../ci/runners/README.html) . | +| 认证令牌 | 用于通过 GitLab 实例对 Runner 进行身份验证的令牌. 它可以在[注册 Runner](https://docs.gitlab.com/runner/register/)时自动获得,也可以[通过 Runners API](#register-a-new-runner)手动[注册时获得](#register-a-new-runner) . | + +这是在 Runner 注册中如何使用两个令牌的示例: + +1. 您使用注册令牌通过 GitLab API 注册了 Runner,并返回了身份验证令牌. +2. 您使用该身份验证令牌并将其添加到[Runner 的配置文件中](https://docs.gitlab.com/runner/commands/) : + + ``` + [[runners]] + token = "" + ``` + +然后将 GitLab 和 Runner 连接起来. + +## List owned runners[](#list-owned-runners "Permalink") + +获取可供用户使用的特定跑步者的列表. + +``` +GET /runners +GET /runners?scope=active +GET /runners?type=project_type +GET /runners?status=active +GET /runners?tag_list=tag1,tag2 +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided | +| `type` | string | no | 要显示的跑步者的类型,其中之一: `instance_type` , `group_type` , `project_type` | +| `status` | string | no | 要显示的跑步者状态,其中之一: `active` , `paused` , `online` , `offline` | +| `tag_list` | 字符串数组 | no | 跑步者标签列表 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/runners" +``` + +响应示例: + +``` +[ { "active": true, "description": "test-1-20150125", "id": 6, "is_shared": false, "ip_address": "127.0.0.1", "name": null, "online": true, "status": "online" }, { "active": true, "description": "test-2-20150125", "id": 8, "ip_address": "127.0.0.1", "is_shared": false, "name": null, "online": false, "status": "offline" } ] +``` + +## List all runners[](#list-all-runners "Permalink") + +获取 GitLab 实例中所有跑步者的列表(特定的和共享的). 访问仅限于具有`admin`权限的用户. + +``` +GET /runners/all +GET /runners/all?scope=online +GET /runners/all?type=project_type +GET /runners/all?status=active +GET /runners/all?tag_list=tag1,tag2 +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `scope` | string | no | 不推荐使用:改为使用`type`或`status` . 参与者显示的范围,其中之一: `specific` , `shared` , `active` ,已`paused` , `online` , `offline` ; 显示所有跑步者(如果未提供) | +| `type` | string | no | 要显示的跑步者的类型,其中之一: `instance_type` , `group_type` , `project_type` | +| `status` | string | no | 要显示的跑步者状态,其中之一: `active` , `paused` , `online` , `offline` | +| `tag_list` | 字符串数组 | no | 跑步者标签列表 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/runners/all" +``` + +响应示例: + +``` +[ { "active": true, "description": "shared-runner-1", "id": 1, "ip_address": "127.0.0.1", "is_shared": true, "name": null, "online": true, "status": "online" }, { "active": true, "description": "shared-runner-2", "id": 3, "ip_address": "127.0.0.1", "is_shared": true, "name": null, "online": false "status": "offline" }, { "active": true, "description": "test-1-20150125", "id": 6, "ip_address": "127.0.0.1", "is_shared": false, "name": null, "online": true "status": "paused" }, { "active": true, "description": "test-2-20150125", "id": 8, "ip_address": "127.0.0.1", "is_shared": false, "name": null, "online": false, "status": "offline" } ] +``` + +## Get runner’s details[](#get-runners-details "Permalink") + +获取跑步者的详细信息. + +``` +GET /runners/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 跑步者 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/runners/6" +``` + +**注意:**响应中的`token`属性[在 GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/issues/214320)中已弃用. 并在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/issues/214322)删除. + +响应示例: + +``` +{ "active": true, "architecture": null, "description": "test-1-20150125", "id": 6, "ip_address": "127.0.0.1", "is_shared": false, "contacted_at": "2016-01-25T16:39:48.066Z", "name": null, "online": true, "status": "online", "platform": null, "projects": [ { "id": 1, "name": "GitLab Community Edition", "name_with_namespace": "GitLab.org / GitLab Community Edition", "path": "gitlab-foss", "path_with_namespace": "gitlab-org/gitlab-foss" } ], "revision": null, "tag_list": [ "ruby", "mysql" ], "version": null, "access_level": "ref_protected", "maximum_timeout": 3600 } +``` + +## Update runner’s details[](#update-runners-details "Permalink") + +更新跑步者的详细信息. + +``` +PUT /runners/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 跑步者 ID | +| `description` | string | no | 跑步者 | +| `active` | boolean | no | 跑步者的状态; 可以设置为`true`或`false` | +| `tag_list` | array | no | 跑步者的标签列表; 放置标签数组,这些标签应最终分配给跑步者 | +| `run_untagged` | boolean | no | 指示跑步者可以执行未加标签的作业的标志 | +| `locked` | boolean | no | 指示跑步者被锁定的标志 | +| `access_level` | string | no | 跑步者的 access_level; `not_protected`或`ref_protected` | +| `maximum_timeout` | integer | no | 此 Runner 处理作业的最大超时时间 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/runners/6" --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2" +``` + +**注意:**响应中的`token`属性[在 GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/issues/214320)中已弃用. 并在[GitLab 13.0 中](https://gitlab.com/gitlab-org/gitlab/-/issues/214322)删除. + +响应示例: + +``` +{ "active": true, "architecture": null, "description": "test-1-20150125-test", "id": 6, "ip_address": "127.0.0.1", "is_shared": false, "contacted_at": "2016-01-25T16:39:48.066Z", "name": null, "online": true, "status": "online", "platform": null, "projects": [ { "id": 1, "name": "GitLab Community Edition", "name_with_namespace": "GitLab.org / GitLab Community Edition", "path": "gitlab-foss", "path_with_namespace": "gitlab-org/gitlab-foss" } ], "revision": null, "tag_list": [ "ruby", "mysql", "tag1", "tag2" ], "version": null, "access_level": "ref_protected", "maximum_timeout": null } +``` + +## Remove a runner[](#remove-a-runner "Permalink") + +卸下流道. + +``` +DELETE /runners/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | The ID of a runner | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/runners/6" +``` + +## List runner’s jobs[](#list-runners-jobs "Permalink") + +在 GitLab 10.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15432) . + +列出正在处理或由指定运行程序处理的作业. + +``` +GET /runners/:id/jobs +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 跑步者 ID | +| `status` | string | no | 工作状态; 其中之一: `running` , `success` , `failed` , `canceled` | +| `order_by` | string | no | 按`id`订购工作. | +| `sort` | string | no | 按`asc`或`desc`顺序对作业进行排序(默认值: `desc` ) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/runners/1/jobs?status=running" +``` + +响应示例: + +``` +[ { "id": 2, "ip_address": "127.0.0.1", "status": "running", "stage": "test", "name": "test", "ref": "master", "tag": false, "coverage": null, "created_at": "2017-11-16T08:50:29.000Z", "started_at": "2017-11-16T08:51:29.000Z", "finished_at": "2017-11-16T08:53:29.000Z", "duration": 120, "user": { "id": 1, "name": "John Doe2", "username": "user2", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://localhost/user2", "created_at": "2017-11-16T18:38:46.000Z", "bio": null, "location": null, "public_email": "", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": null }, "commit": { "id": "97de212e80737a608d939f648d959671fb0a0142", "short_id": "97de212e", "title": "Update configuration\r", "created_at": "2017-11-16T08:50:28.000Z", "parent_ids": [ "1b12f15a11fc6e62177bef08f47bc7b5ce50b141", "498214de67004b1da3d820901307bed2a68a8ef6" ], "message": "See merge request !123", "author_name": "John Doe2", "author_email": "user2@example.org", "authored_date": "2017-11-16T08:50:27.000Z", "committer_name": "John Doe2", "committer_email": "user2@example.org", "committed_date": "2017-11-16T08:50:27.000Z" }, "pipeline": { "id": 2, "sha": "97de212e80737a608d939f648d959671fb0a0142", "ref": "master", "status": "running" }, "project": { "id": 1, "description": null, "name": "project1", "name_with_namespace": "John Doe2 / project1", "path": "project1", "path_with_namespace": "namespace1/project1", "created_at": "2017-11-16T18:38:46.620Z" } } ] +``` + +## List project’s runners[](#list-projects-runners "Permalink") + +List all runners (specific and shared) available in the project. 列出项目中所有可用的跑步者(特定的和共享的). Shared runners are listed if at least one shared runner is defined. 如果定义了至少一个共享运行程序,则列出共享运行程序. + +``` +GET /projects/:id/runners +GET /projects/:id/runners?scope=active +GET /projects/:id/runners?type=project_type +GET /projects/:id/runners?status=active +GET /projects/:id/runners?tag_list=tag1,tag2 +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `scope` | string | no | 不推荐使用:改为使用`type`或`status` . 要显示的特定跑步者的范围,其中之一: `active` , `paused` , `online` , `offline` ; 显示所有跑步者(如果未提供) | +| `type` | string | no | 要显示的跑步者的类型,其中之一: `instance_type` , `group_type` , `project_type` | +| `status` | string | no | 要显示的跑步者状态,其中之一: `active` , `paused` , `online` , `offline` | +| `tag_list` | 字符串数组 | no | 跑步者标签列表 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/9/runners" +``` + +响应示例: + +``` +[ { "active": true, "description": "test-2-20150125", "id": 8, "ip_address": "127.0.0.1", "is_shared": false, "name": null, "online": false, "status": "offline" }, { "active": true, "description": "development_runner", "id": 5, "ip_address": "127.0.0.1", "is_shared": true, "name": null, "online": true "status": "paused" } ] +``` + +## Enable a runner in project[](#enable-a-runner-in-project "Permalink") + +在项目中启用可用的特定运行器. + +``` +POST /projects/:id/runners +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `runner_id` | integer | yes | 跑步者 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/9/runners" --form "runner_id=9" +``` + +响应示例: + +``` +{ "active": true, "description": "test-2016-02-01", "id": 9, "ip_address": "127.0.0.1", "is_shared": false, "name": null, "online": true, "status": "online" } +``` + +## Disable a runner from project[](#disable-a-runner-from-project "Permalink") + +禁用项目中的特定运行器. 仅当该项目不是与指定运行器关联的唯一项目时,它才有效. 如果是这样,则返回错误. 改用" [删除亚军"](#remove-a-runner)电话. + +``` +DELETE /projects/:id/runners/:runner_id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `runner_id` | integer | yes | 跑步者 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/9/runners/9" +``` + +## List group’s runners[](#list-groups-runners "Permalink") + +列出组中的所有跑步者(特定的和共享的)以及其祖先组. 如果定义了至少一个共享运行程序,则列出共享运行程序. + +``` +GET /groups/:id/runners +GET /groups/:id/runners?type=group_type +GET /groups/:id/runners?status=active +GET /groups/:id/runners?tag_list=tag1,tag2 +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 认证用户拥有的组的 ID | +| `type` | string | no | 要显示的跑步者的类型,其中之一: `instance_type` , `group_type` , `project_type` | +| `status` | string | no | 要显示的跑步者状态,其中之一: `active` , `paused` , `online` , `offline` | +| `tag_list` | 字符串数组 | no | 跑步者标签列表 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/9/runners" +``` + +响应示例: + +``` +[ { "id": 3, "description": "Shared", "ip_address": "127.0.0.1", "active": true, "is_shared": true, "name": "gitlab-runner", "online": null, "status": "not_connected" }, { "id": 6, "description": "Test", "ip_address": "127.0.0.1", "active": true, "is_shared": true, "name": "gitlab-runner", "online": false, "status": "offline" }, { "id": 8, "description": "Test 2", "ip_address": "127.0.0.1", "active": true, "is_shared": false, "name": "gitlab-runner", "online": null, "status": "not_connected" } ] +``` + +## Register a new Runner[](#register-a-new-runner "Permalink") + +为该实例注册一个新的运行器. + +``` +POST /runners +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | yes | [Registration token](#registration-and-authentication-tokens). | +| `description` | string | no | 跑步者的描述 | +| `info` | hash | no | 跑步者的元数据 | +| `active` | boolean | no | 跑步者是否活跃 | +| `locked` | boolean | no | Runner 是否应该为当前项目锁定 | +| `run_untagged` | boolean | no | 跑步者是否应处理未加标签的工作 | +| `tag_list` | 字符串数组 | no | 跑步者标签列表 | +| `access_level` | string | no | 跑步者的 access_level; `not_protected`或`ref_protected` | +| `maximum_timeout` | integer | no | 此 Runner 处理作业的最大超时时间 | + +``` +curl --request POST "https://gitlab.example.com/api/v4/runners" --form "token=" --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2" +``` + +Response: + +| Status | Description | +| --- | --- | +| 201 | 跑步者已创建 | + +响应示例: + +``` +{ "id": "12345", "token": "6337ff461c94fd3fa32ba3b1ff4125" } +``` + +## Delete a registered Runner[](#delete-a-registered-runner "Permalink") + +删除注册的跑步者. + +``` +DELETE /runners +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | yes | Runner’s [authentication token](#registration-and-authentication-tokens). | + +``` +curl --request DELETE "https://gitlab.example.com/api/v4/runners" --form "token=" +``` + +Response: + +| Status | Description | +| --- | --- | +| 204 | 跑步者已被删除 | + +## Verify authentication for a registered Runner[](#verify-authentication-for-a-registered-runner "Permalink") + +验证注册的运行程序的身份验证凭据. + +``` +POST /runners/verify +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | yes | Runner’s [authentication token](#registration-and-authentication-tokens). | + +``` +curl --request POST "https://gitlab.example.com/api/v4/runners/verify" --form "token=" +``` + +Response: + +| Status | Description | +| --- | --- | +| 200 | 凭证有效 | +| 403 | 凭证无效 | \ No newline at end of file diff --git a/docs/365.md b/docs/365.md new file mode 100644 index 0000000000000000000000000000000000000000..34125a73853dd1bc91f52454f1fa851ef75b6166 --- /dev/null +++ b/docs/365.md @@ -0,0 +1,189 @@ +# SCIM API + +> 原文:[https://docs.gitlab.com/ee/api/scim.html](https://docs.gitlab.com/ee/api/scim.html) + +* [Get a list of SAML users](#get-a-list-of-saml-users) +* [Get a single SAML user](#get-a-single-saml-user) +* [Create a SAML user](#create-a-saml-user) +* [Update a single SAML user](#update-a-single-saml-user) +* [Remove a single SAML user](#remove-a-single-saml-user) +* [Available filters](#available-filters) +* [Available operations](#available-operations) + +# SCIM API[](#scim-api-silver-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in [GitLab Silver](https://about.gitlab.com/pricing/) 11.10. + +SCIM API 实现[RFC7644 协议](https://tools.ietf.org/html/rfc7644) . + +**警告:**此 API 供内部系统用于与 SCIM 提供程序连接. 虽然可以直接使用,但如有更改,恕不另行通知.**注意:**必须为组启用[组 SSO](../user/group/saml_sso/index.html) . 有关更多信息,请参见[SCIM 设置文档](../user/group/saml_sso/scim_setup.html#requirements) . + +## Get a list of SAML users[](#get-a-list-of-saml-users "Permalink") + +**注意:**此端点用作 SCIM 同步机制的一部分,并且它仅基于唯一 ID(应与用户的`extern_uid`相匹配)返回一个用户. + +``` +GET /api/scim/v2/groups/:group_path/Users +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `filter` | string | no | A [filter](#available-filters) expression. | +| `group_path` | string | yes | 组的完整路径. | +| `startIndex` | integer | no | 从 1 开始的索引,指示从何处开始返回结果. 小于 1 的值将被解释为 1. | +| `count` | integer | no | 所需的最大查询结果数. | + +**注意:**分页遵循[SCIM 规范,](https://tools.ietf.org/html/rfc7644#section-3.4.2.4)而不是其他地方使用的 GitLab 分页. 如果记录在请求之间更改,则页面可能丢失已移至其他页面的记录,或者重复上一个请求的记录. + +请求示例: + +``` +curl 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users?filter=id%20eq%20"0b1d561c-21ff-4092-beab-8154b17f82f2"' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +响应示例: + +``` +{ "schemas": [ "urn:ietf:params:scim:api:messages:2.0:ListResponse" ], "totalResults": 1, "itemsPerPage": 20, "startIndex": 1, "Resources": [ { "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User" ], "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", "active": true, "name.formatted": "Test User", "userName": "username", "meta": { "resourceType":"User" }, "emails": [ { "type": "work", "value": "name@example.com", "primary": true } ] } ] } +``` + +## Get a single SAML user[](#get-a-single-saml-user "Permalink") + +``` +GET /api/scim/v2/groups/:group_path/Users/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | string | yes | 用户的外部 UID. | +| `group_path` | string | yes | 组的完整路径. | + +请求示例: + +``` +curl "https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +响应示例: + +``` +{ "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User" ], "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", "active": true, "name.formatted": "Test User", "userName": "username", "meta": { "resourceType":"User" }, "emails": [ { "type": "work", "value": "name@example.com", "primary": true } ] } +``` + +## Create a SAML user[](#create-a-saml-user "Permalink") + +``` +POST /api/scim/v2/groups/:group_path/Users/ +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `externalId` | string | yes | 用户的外部 UID. | +| `userName` | string | yes | 用户的用户名. | +| `emails` | JSON 字符串 | yes | 工作电子邮件. | +| `name` | JSON 字符串 | yes | 用户名. | +| `meta` | string | no | 资源类型( `User` ). | + +请求示例: + +``` +curl --verbose --request POST "https://example.gitlab.com/api/scim/v2/groups/test_group/Users" --data '{"externalId":"test_uid","active":null,"userName":"username","emails":[{"primary":true,"type":"work","value":"name@example.com"}],"name":{"formatted":"Test User","familyName":"User","givenName":"Test"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"meta":{"resourceType":"User"}}' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +响应示例: + +``` +{ "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User" ], "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", "active": true, "name.formatted": "Test User", "userName": "username", "meta": { "resourceType":"User" }, "emails": [ { "type": "work", "value": "name@example.com", "primary": true } ] } +``` + +如果成功,则返回`201`状态代码. + +## Update a single SAML user[](#update-a-single-saml-user "Permalink") + +可以更新的字段是: + +| SCIM / IdP 字段 | GitLab 领域 | +| --- | --- | +| `id/externalId` | `extern_uid` | +| `name.formatted` | `name` | +| `emails\[type eq "work"\].value` | `email` | +| `active` | 如果`active` = `false`删除身份 | +| `userName` | `username` | + +``` +PATCH /api/scim/v2/groups/:group_path/Users/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | string | yes | 用户的外部 UID. | +| `group_path` | string | yes | 组的完整路径. | +| `Operations` | JSON 字符串 | yes | An [operations](#available-operations) expression. | + +请求示例: + +``` +curl --verbose --request PATCH "https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --data '{ "Operations": [{"op":"Add","path":"name.formatted","value":"New Name"}] }' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +如果成功,则返回带有`204`状态代码的空响应. + +## Remove a single SAML user[](#remove-a-single-saml-user "Permalink") + +删除用户的 SSO 身份和组成员身份. + +``` +DELETE /api/scim/v2/groups/:group_path/Users/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | string | yes | 用户的外部 UID. | +| `group_path` | string | yes | 组的完整路径. | + +请求示例: + +``` +curl --verbose --request DELETE "https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +如果成功,则返回带有`204`状态代码的空响应. + +## Available filters[](#available-filters "Permalink") + +它们与[RFC7644 过滤部分中](https://tools.ietf.org/html/rfc7644#section-3.4.2.2)指定的表达式匹配. + +| Filter | Description | +| --- | --- | +| `eq` | 该属性与指定值完全匹配. | + +Example: + +``` +id eq a-b-c-d +``` + +## Available operations[](#available-operations "Permalink") + +They perform an operation as specified in [the RFC7644 update section](https://tools.ietf.org/html/rfc7644#section-3.5.2). + +| Operator | Description | +| --- | --- | +| `Replace` | 该属性的值已更新. | +| `Add` | 该属性具有新值. | + +Example: + +``` +{ "op": "Add", "path": "name.formatted", "value": "New Name" } +``` \ No newline at end of file diff --git a/docs/366.md b/docs/366.md new file mode 100644 index 0000000000000000000000000000000000000000..f7dac4b36657dd5f503f541e83c344f783de6ae9 --- /dev/null +++ b/docs/366.md @@ -0,0 +1,476 @@ +# Search API + +> 原文:[https://docs.gitlab.com/ee/api/search.html](https://docs.gitlab.com/ee/api/search.html) + +* [Global Search API](#global-search-api) + * [Scope: projects](#scope-projects) + * [Scope: issues](#scope-issues) + * [Scope: merge_requests](#scope-merge_requests) + * [Scope: milestones](#scope-milestones) + * [Scope: snippet_titles](#scope-snippet_titles) + * [Scope: wiki_blobs](#scope-wiki_blobs-starter) + * [Scope: commits](#scope-commits-starter) + * [Scope: blobs](#scope-blobs-starter) + * [Scope: users](#scope-users) +* [Group Search API](#group-search-api) + * [Scope: projects](#scope-projects-1) + * [Scope: issues](#scope-issues-1) + * [Scope: merge_requests](#scope-merge_requests-1) + * [Scope: milestones](#scope-milestones-1) + * [Scope: wiki_blobs](#scope-wiki_blobs-starter-1) + * [Scope: commits](#scope-commits-starter-1) + * [Scope: blobs](#scope-blobs-starter-1) + * [Scope: users](#scope-users-1) +* [Project Search API](#project-search-api) + * [Scope: issues](#scope-issues-2) + * [Scope: merge_requests](#scope-merge_requests-2) + * [Scope: milestones](#scope-milestones-2) + * [Scope: notes](#scope-notes) + * [Scope: wiki_blobs](#scope-wiki_blobs) + * [Scope: commits](#scope-commits) + * [Scope: blobs](#scope-blobs) + * [Scope: users](#scope-users-2) + +# Search API[](#search-api "Permalink") + +在 GitLab 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41763) . + +搜索的每个 API 调用都必须经过验证. + +## Global Search API[](#global-search-api "Permalink") + +在整个 GitLab 实例中进行全局搜索. + +``` +GET /search +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `scope` | string | yes | 搜索范围 | +| `search` | string | yes | 搜索查询 | + +在指定范围内搜索表达式. 当前支持以下范围:项目,问题,merge_requests,里程碑,snippet_titles,用户. + +如果启用了 Elasticsearch,则其他可用范围是 blob,wiki_blobs 和 commits. 查找有关[该功能的](../integration/elasticsearch.html)更多信息. + +响应取决于请求的范围. + +### Scope: projects[](#scope-projects "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=projects&search=flight" +``` + +响应示例: + +``` +[ { "id": 6, "description": "Nobis sed ipsam vero quod cupiditate veritatis hic.", "name": "Flight", "name_with_namespace": "Twitter / Flight", "path": "flight", "path_with_namespace": "twitter/flight", "created_at": "2017-09-05T07:58:01.621Z", "default_branch": "master", "tag_list":[], "ssh_url_to_repo": "ssh://jarka@localhost:2222/twitter/flight.git", "http_url_to_repo": "http://localhost:3000/twitter/flight.git", "web_url": "http://localhost:3000/twitter/flight", "avatar_url": null, "star_count": 0, "forks_count": 0, "last_activity_at": "2018-01-31T09:56:30.902Z" } ] +``` + +### Scope: issues[](#scope-issues "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=issues&search=file" +``` + +响应示例: + +``` +[ { "id": 83, "iid": 1, "project_id": 12, "title": "Add file", "description": "Add first file", "state": "opened", "created_at": "2018-01-24T06:02:15.514Z", "updated_at": "2018-02-06T12:36:23.263Z", "closed_at": null, "labels":[], "milestone": null, "assignees": [{ "id": 20, "name": "Ceola Deckow", "username": "sammy.collier", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c23d85a4f50e0ea76ab739156c639231?s=80&d=identicon", "web_url": "http://localhost:3000/sammy.collier" }], "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "assignee": { "id": 20, "name": "Ceola Deckow", "username": "sammy.collier", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c23d85a4f50e0ea76ab739156c639231?s=80&d=identicon", "web_url": "http://localhost:3000/sammy.collier" }, "user_notes_count": 0, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "discussion_locked": null, "web_url": "http://localhost:3000/h5bp/7bp/subgroup-prj/issues/1", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +### Scope: merge_requests[](#scope-merge_requests "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=merge_requests&search=file" +``` + +响应示例: + +``` +[ { "id": 56, "iid": 8, "project_id": 6, "title": "Add first file", "description": "This is a test MR to add file", "state": "opened", "created_at": "2018-01-22T14:21:50.830Z", "updated_at": "2018-02-06T12:40:33.295Z", "target_branch": "master", "source_branch": "jaja-test", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "assignee": { "id": 5, "name": "Jacquelyn Kutch", "username": "abigail", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/3138c66095ee4bd11a508c2f7f7772da?s=80&d=identicon", "web_url": "http://localhost:3000/abigail" }, "source_project_id": 6, "target_project_id": 6, "labels": [ "ruby", "tests" ], "work_in_progress": false, "milestone": { "id": 13, "iid": 3, "project_id": 6, "title": "v2.0", "description": "Qui aut qui eos dolor beatae itaque tempore molestiae.", "state": "active", "created_at": "2017-09-05T07:58:29.099Z", "updated_at": "2017-09-05T07:58:29.099Z", "due_date": null, "start_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "can_be_merged", "sha": "78765a2d5e0a43585945c58e61ba2f822e4d090b", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 0, "discussion_locked": null, "should_remove_source_branch": null, "force_remove_source_branch": true, "web_url": "http://localhost:3000/twitter/flight/merge_requests/8", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +### Scope: milestones[](#scope-milestones "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=milestones&search=release" +``` + +响应示例: + +``` +[ { "id": 44, "iid": 1, "project_id": 12, "title": "next release", "description": "Next release milestone", "state": "active", "created_at": "2018-02-06T12:43:39.271Z", "updated_at": "2018-02-06T12:44:01.298Z", "due_date": "2018-04-18", "start_date": "2018-02-04" } ] +``` + +### Scope: snippet_titles[](#scope-snippet_titles "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=snippet_titles&search=sample" +``` + +响应示例: + +``` +[ { "id": 50, "title": "Sample file", "file_name": "file.rb", "description": "Simple ruby file", "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "updated_at": "2018-02-06T12:49:29.104Z", "created_at": "2017-11-28T08:20:18.071Z", "project_id": 9, "web_url": "http://localhost:3000/root/jira-test/snippets/50" } ] +``` + +### Scope: wiki_blobs[](#scope-wiki_blobs-starter "Permalink") + +仅当启用[Elasticsearch 时,](../integration/elasticsearch.html)此范围才可用. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=wiki_blobs&search=bye" +``` + +Example response: + +``` + [ { "basename": "home", "data": "hello\n\nand bye\n\nend", "path": "home.md", "filename": "home.md", "id": null, "ref": "master", "startline": 5, "project_id": 6 } ] +``` + +**注意:**不建议使用`filename`而推荐使用`path` . 两者都返回存储库中文件的完整路径,但将来`filename`名将仅是文件名,而不是完整路径. 有关详细信息,请参见[问题 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521) . + +### Scope: commits[](#scope-commits-starter "Permalink") + +仅当启用[Elasticsearch 时,](../integration/elasticsearch.html)此范围才可用. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=commits&search=bye" +``` + +响应示例: + +``` + [ { "id": "4109c2d872d5fdb1ed057400d103766aaea97f98", "short_id": "4109c2d8", "title": "goodbye $.browser", "created_at": "2013-02-18T22:02:54.000Z", "parent_ids": [ "59d05353ab575bcc2aa958fe1782e93297de64c9" ], "message": "goodbye $.browser\n", "author_name": "angus croll", "author_email": "anguscroll@gmail.com", "authored_date": "2013-02-18T22:02:54.000Z", "committer_name": "angus croll", "committer_email": "anguscroll@gmail.com", "committed_date": "2013-02-18T22:02:54.000Z", "project_id": 6 } ] +``` + +### Scope: blobs[](#scope-blobs-starter "Permalink") + +仅当启用[Elasticsearch 时,](../integration/elasticsearch.html)此范围才可用. + +过滤器可用于以下范围: + +* filename +* path +* extension + +要使用过滤器,只需将其包含在查询中,如下所示: `a query filename:some_name*` . + +您可以使用通配符( `*` )使用全局匹配. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=blobs&search=installation" +``` + +响应示例: + +``` + [ { "basename": "README", "data": "```\n\n## Installation\n\nQuick start using the [pre-built", "path": "README.md", "filename": "README.md", "id": null, "ref": "master", "startline": 46, "project_id": 6 } ] +``` + +**注意:**不建议使用`filename`而推荐使用`path` . 两者都返回存储库中文件的完整路径,但将来`filename`名将仅是文件名,而不是完整路径. 有关详细信息,请参见[问题 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521) . + +### Scope: users[](#scope-users "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/search?scope=users&search=doe" +``` + +响应示例: + +``` +[ { "id": 1, "name": "John Doe1", "username": "user1", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://localhost/user1" } ] +``` + +## Group Search API[](#group-search-api "Permalink") + +在指定的组中搜索. + +如果用户不是组的成员,并且该组是私有的,则对该组的`GET`请求将导致`404`状态代码. + +``` +GET /groups/:id/search +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 认证用户拥有[的组](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `scope` | string | yes | 搜索范围 | +| `search` | string | yes | 搜索查询 | + +在指定范围内搜索表达式. 当前支持以下范围:项目,问题,merge_requests,里程碑,用户. + +如果启用了 Elasticsearch,则其他可用范围是 blob,wiki_blobs 和 commits. 查找有关[该功能的](../integration/elasticsearch.html)更多信息. + +响应取决于请求的范围. + +### Scope: projects[](#scope-projects-1 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/3/search?scope=projects&search=flight" +``` + +响应示例: + +``` +[ { "id": 6, "description": "Nobis sed ipsam vero quod cupiditate veritatis hic.", "name": "Flight", "name_with_namespace": "Twitter / Flight", "path": "flight", "path_with_namespace": "twitter/flight", "created_at": "2017-09-05T07:58:01.621Z", "default_branch": "master", "tag_list":[], "ssh_url_to_repo": "ssh://jarka@localhost:2222/twitter/flight.git", "http_url_to_repo": "http://localhost:3000/twitter/flight.git", "web_url": "http://localhost:3000/twitter/flight", "avatar_url": null, "star_count": 0, "forks_count": 0, "last_activity_at": "2018-01-31T09:56:30.902Z" } ] +``` + +### Scope: issues[](#scope-issues-1 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/3/search?scope=issues&search=file" +``` + +响应示例: + +``` +[ { "id": 83, "iid": 1, "project_id": 12, "title": "Add file", "description": "Add first file", "state": "opened", "created_at": "2018-01-24T06:02:15.514Z", "updated_at": "2018-02-06T12:36:23.263Z", "closed_at": null, "labels":[], "milestone": null, "assignees": [{ "id": 20, "name": "Ceola Deckow", "username": "sammy.collier", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c23d85a4f50e0ea76ab739156c639231?s=80&d=identicon", "web_url": "http://localhost:3000/sammy.collier" }], "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "assignee": { "id": 20, "name": "Ceola Deckow", "username": "sammy.collier", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c23d85a4f50e0ea76ab739156c639231?s=80&d=identicon", "web_url": "http://localhost:3000/sammy.collier" }, "user_notes_count": 0, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "discussion_locked": null, "web_url": "http://localhost:3000/h5bp/7bp/subgroup-prj/issues/1", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +### Scope: merge_requests[](#scope-merge_requests-1 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/3/search?scope=merge_requests&search=file" +``` + +响应示例: + +``` +[ { "id": 56, "iid": 8, "project_id": 6, "title": "Add first file", "description": "This is a test MR to add file", "state": "opened", "created_at": "2018-01-22T14:21:50.830Z", "updated_at": "2018-02-06T12:40:33.295Z", "target_branch": "master", "source_branch": "jaja-test", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "assignee": { "id": 5, "name": "Jacquelyn Kutch", "username": "abigail", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/3138c66095ee4bd11a508c2f7f7772da?s=80&d=identicon", "web_url": "http://localhost:3000/abigail" }, "source_project_id": 6, "target_project_id": 6, "labels": [ "ruby", "tests" ], "work_in_progress": false, "milestone": { "id": 13, "iid": 3, "project_id": 6, "title": "v2.0", "description": "Qui aut qui eos dolor beatae itaque tempore molestiae.", "state": "active", "created_at": "2017-09-05T07:58:29.099Z", "updated_at": "2017-09-05T07:58:29.099Z", "due_date": null, "start_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "can_be_merged", "sha": "78765a2d5e0a43585945c58e61ba2f822e4d090b", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 0, "discussion_locked": null, "should_remove_source_branch": null, "force_remove_source_branch": true, "web_url": "http://localhost:3000/twitter/flight/merge_requests/8", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +### Scope: milestones[](#scope-milestones-1 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/3/search?scope=milestones&search=release" +``` + +响应示例: + +``` +[ { "id": 44, "iid": 1, "project_id": 12, "title": "next release", "description": "Next release milestone", "state": "active", "created_at": "2018-02-06T12:43:39.271Z", "updated_at": "2018-02-06T12:44:01.298Z", "due_date": "2018-04-18", "start_date": "2018-02-04" } ] +``` + +### Scope: wiki_blobs[](#scope-wiki_blobs-starter-1 "Permalink") + +仅当启用[Elasticsearch 时,](../integration/elasticsearch.html)此范围才可用. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/6/search?scope=wiki_blobs&search=bye" +``` + +响应示例: + +``` + [ { "basename": "home", "data": "hello\n\nand bye\n\nend", "path": "home.md", "filename": "home.md", "id": null, "ref": "master", "startline": 5, "project_id": 6 } ] +``` + +**注意:**不建议使用`filename`而推荐使用`path` . 两者都返回存储库中文件的完整路径,但将来`filename`名将仅是文件名,而不是完整路径. 有关详细信息,请参见[问题 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521) . + +### Scope: commits[](#scope-commits-starter-1 "Permalink") + +仅当启用[Elasticsearch 时,](../integration/elasticsearch.html)此范围才可用. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/6/search?scope=commits&search=bye" +``` + +响应示例: + +``` + [ { "id": "4109c2d872d5fdb1ed057400d103766aaea97f98", "short_id": "4109c2d8", "title": "goodbye $.browser", "created_at": "2013-02-18T22:02:54.000Z", "parent_ids": [ "59d05353ab575bcc2aa958fe1782e93297de64c9" ], "message": "goodbye $.browser\n", "author_name": "angus croll", "author_email": "anguscroll@gmail.com", "authored_date": "2013-02-18T22:02:54.000Z", "committer_name": "angus croll", "committer_email": "anguscroll@gmail.com", "committed_date": "2013-02-18T22:02:54.000Z", "project_id": 6 } ] +``` + +### Scope: blobs[](#scope-blobs-starter-1 "Permalink") + +仅当启用[Elasticsearch 时,](../integration/elasticsearch.html)此范围才可用. + +过滤器可用于以下范围: + +* filename +* path +* extension + +要使用过滤器,只需将其包含在查询中,如下所示: `a query filename:some_name*` . + +您可以使用通配符( `*` )使用全局匹配. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/6/search?scope=blobs&search=installation" +``` + +响应示例: + +``` + [ { "basename": "README", "data": "```\n\n## Installation\n\nQuick start using the [pre-built", "path": "README.md", "filename": "README.md", "id": null, "ref": "master", "startline": 46, "project_id": 6 } ] +``` + +**注意:**不建议使用`filename`而推荐使用`path` . 两者都返回存储库中文件的完整路径,但将来`filename`名将仅是文件名,而不是完整路径. 有关详细信息,请参见[问题 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521) . + +### Scope: users[](#scope-users-1 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/3/search?scope=users&search=doe" +``` + +响应示例: + +``` +[ { "id": 1, "name": "John Doe1", "username": "user1", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://localhost/user1" } ] +``` + +## Project Search API[](#project-search-api "Permalink") + +在指定项目中搜索. + +如果用户不是项目成员,并且该项目是私有项目,则对该项目的`GET`请求将导致`404`状态代码. + +``` +GET /projects/:id/search +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `scope` | string | yes | 搜索范围 | +| `search` | string | yes | 搜索查询 | +| `ref` | string | no | 要搜索的存储库分支或标记的名称. 默认情况下使用项目的默认分支. 这仅适用于范围:commit,blob 和 wiki_blobs. | + +在指定范围内搜索表达式. 当前支持以下范围:问题,merge_requests,里程碑,注释,wiki_blob,提交,blob,用户. + +响应取决于请求的范围. + +### Scope: issues[](#scope-issues-2 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/12/search?scope=issues&search=file" +``` + +响应示例: + +``` +[ { "id": 83, "iid": 1, "project_id": 12, "title": "Add file", "description": "Add first file", "state": "opened", "created_at": "2018-01-24T06:02:15.514Z", "updated_at": "2018-02-06T12:36:23.263Z", "closed_at": null, "labels":[], "milestone": null, "assignees": [{ "id": 20, "name": "Ceola Deckow", "username": "sammy.collier", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c23d85a4f50e0ea76ab739156c639231?s=80&d=identicon", "web_url": "http://localhost:3000/sammy.collier" }], "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "assignee": { "id": 20, "name": "Ceola Deckow", "username": "sammy.collier", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/c23d85a4f50e0ea76ab739156c639231?s=80&d=identicon", "web_url": "http://localhost:3000/sammy.collier" }, "user_notes_count": 0, "upvotes": 0, "downvotes": 0, "due_date": null, "confidential": false, "discussion_locked": null, "web_url": "http://localhost:3000/h5bp/7bp/subgroup-prj/issues/1", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +**注意** :不建议使用`assignee`列,现在我们将其显示为符合 GitLab EE API 的单一大小的数组`assignees` . + +### Scope: merge_requests[](#scope-merge_requests-2 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/6/search?scope=merge_requests&search=file" +``` + +响应示例: + +``` +[ { "id": 56, "iid": 8, "project_id": 6, "title": "Add first file", "description": "This is a test MR to add file", "state": "opened", "created_at": "2018-01-22T14:21:50.830Z", "updated_at": "2018-02-06T12:40:33.295Z", "target_branch": "master", "source_branch": "jaja-test", "upvotes": 0, "downvotes": 0, "author": { "id": 1, "name": "Administrator", "username": "root", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "assignee": { "id": 5, "name": "Jacquelyn Kutch", "username": "abigail", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/3138c66095ee4bd11a508c2f7f7772da?s=80&d=identicon", "web_url": "http://localhost:3000/abigail" }, "source_project_id": 6, "target_project_id": 6, "labels": [ "ruby", "tests" ], "work_in_progress": false, "milestone": { "id": 13, "iid": 3, "project_id": 6, "title": "v2.0", "description": "Qui aut qui eos dolor beatae itaque tempore molestiae.", "state": "active", "created_at": "2017-09-05T07:58:29.099Z", "updated_at": "2017-09-05T07:58:29.099Z", "due_date": null, "start_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "can_be_merged", "sha": "78765a2d5e0a43585945c58e61ba2f822e4d090b", "merge_commit_sha": null, "squash_commit_sha": null, "user_notes_count": 0, "discussion_locked": null, "should_remove_source_branch": null, "force_remove_source_branch": true, "web_url": "http://localhost:3000/twitter/flight/merge_requests/8", "time_stats": { "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, "human_total_time_spent": null } } ] +``` + +### Scope: milestones[](#scope-milestones-2 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/12/search?scope=milestones&search=release" +``` + +响应示例: + +``` +[ { "id": 44, "iid": 1, "project_id": 12, "title": "next release", "description": "Next release milestone", "state": "active", "created_at": "2018-02-06T12:43:39.271Z", "updated_at": "2018-02-06T12:44:01.298Z", "due_date": "2018-04-18", "start_date": "2018-02-04" } ] +``` + +### Scope: notes[](#scope-notes "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/6/search?scope=notes&search=maxime" +``` + +响应示例: + +``` +[ { "id": 191, "body": "Harum maxime consequuntur et et deleniti assumenda facilis.", "attachment": null, "author": { "id": 23, "name": "User 1", "username": "user1", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/111d68d06e2d317b5a59c2c6c5bad808?s=80&d=identicon", "web_url": "http://localhost:3000/user1" }, "created_at": "2017-09-05T08:01:32.068Z", "updated_at": "2017-09-05T08:01:32.068Z", "system": false, "noteable_id": 22, "noteable_type": "Issue", "noteable_iid": 2 } ] +``` + +### Scope: wiki_blobs[](#scope-wiki_blobs "Permalink") + +过滤器可用于以下范围: + +* filename +* path +* extension + +要使用过滤器,只需将其包含在查询中,例如: `a query filename:some_name*` . 您可以使用通配符( `*` )使用全局匹配. + +Wiki blobs searches are performed on both filenames and contents. Search results: + +* 在文件名中找到的结果显示在内容中之前. +* 可能包含同一 blob 的多个匹配项,因为可能在文件名和内容中都找到了搜索字符串,或者在内容中可能出现了多次. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/6/search?scope=wiki_blobs&search=bye" +``` + +响应示例: + +``` + [ { "basename": "home", "data": "hello\n\nand bye\n\nend", "path": "home.md", "filename": "home.md", "id": null, "ref": "master", "startline": 5, "project_id": 6 } ] +``` + +**注意:**不建议使用`filename`而推荐使用`path` . 两者都返回存储库中文件的完整路径,但将来`filename`名将仅是文件名,而不是完整路径. 有关详细信息,请参见[问题 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521) . + +### Scope: commits[](#scope-commits "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/6/search?scope=commits&search=bye" +``` + +响应示例: + +``` + [ { "id": "4109c2d872d5fdb1ed057400d103766aaea97f98", "short_id": "4109c2d8", "title": "goodbye $.browser", "created_at": "2013-02-18T22:02:54.000Z", "parent_ids": [ "59d05353ab575bcc2aa958fe1782e93297de64c9" ], "message": "goodbye $.browser\n", "author_name": "angus croll", "author_email": "anguscroll@gmail.com", "authored_date": "2013-02-18T22:02:54.000Z", "committer_name": "angus croll", "committer_email": "anguscroll@gmail.com", "committed_date": "2013-02-18T22:02:54.000Z", "project_id": 6 } ] +``` + +### Scope: blobs[](#scope-blobs "Permalink") + +过滤器可用于以下范围: + +* filename +* path +* extension + +要使用过滤器,只需将其包含在查询中,例如: `a query filename:some_name*` . 您可以使用通配符( `*` )使用全局匹配. + +对文件名和内容都进行 Blob 搜索. 搜索结果: + +* 在文件名中找到的结果显示在内容中之前. +* 可能包含同一 blob 的多个匹配项,因为可能在文件名和内容中都找到了搜索字符串,或者在内容中可能出现了多次. + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/6/search?scope=blobs&search=installation&ref=feature" +``` + +响应示例: + +``` + [ { "basename": "README", "data": "```\n\n## Installation\n\nQuick start using the [pre-built", "path": "README.md", "filename": "README.md", "id": null, "ref": "feature", "startline": 46, "project_id": 6 } ] +``` + +**注意:**不建议使用`filename`而推荐使用`path` . 两者都返回存储库中文件的完整路径,但将来`filename`名将仅是文件名,而不是完整路径. 有关详细信息,请参见[问题 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521) . + +### Scope: users[](#scope-users-2 "Permalink") + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/6/search?scope=users&search=doe" +``` + +响应示例: + +``` +[ { "id": 1, "name": "John Doe1", "username": "user1", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", "web_url": "http://localhost/user1" } ] +``` \ No newline at end of file diff --git a/docs/367.md b/docs/367.md new file mode 100644 index 0000000000000000000000000000000000000000..1cfc6353476802260ee5078711915088bd73182d --- /dev/null +++ b/docs/367.md @@ -0,0 +1,1578 @@ +# Services API + +> 原文:[https://docs.gitlab.com/ee/api/services.html](https://docs.gitlab.com/ee/api/services.html) + +* [List all active services](#list-all-active-services) +* [Asana](#asana) + * [Create/Edit Asana service](#createedit-asana-service) + * [Delete Asana service](#delete-asana-service) + * [Get Asana service settings](#get-asana-service-settings) +* [Assembla](#assembla) + * [Create/Edit Assembla service](#createedit-assembla-service) + * [Delete Assembla service](#delete-assembla-service) + * [Get Assembla service settings](#get-assembla-service-settings) +* [Atlassian Bamboo CI](#atlassian-bamboo-ci) + * [Create/Edit Atlassian Bamboo CI service](#createedit-atlassian-bamboo-ci-service) + * [Delete Atlassian Bamboo CI service](#delete-atlassian-bamboo-ci-service) + * [Get Atlassian Bamboo CI service settings](#get-atlassian-bamboo-ci-service-settings) +* [Bugzilla](#bugzilla) + * [Create/Edit Bugzilla service](#createedit-bugzilla-service) + * [Delete Bugzilla Service](#delete-bugzilla-service) + * [Get Bugzilla Service Settings](#get-bugzilla-service-settings) +* [Buildkite](#buildkite) + * [Create/Edit Buildkite service](#createedit-buildkite-service) + * [Delete Buildkite service](#delete-buildkite-service) + * [Get Buildkite service settings](#get-buildkite-service-settings) +* [Campfire](#campfire) + * [Create/Edit Campfire service](#createedit-campfire-service) + * [Delete Campfire service](#delete-campfire-service) + * [Get Campfire service settings](#get-campfire-service-settings) +* [Unify Circuit](#unify-circuit) + * [Create/Edit Unify Circuit service](#createedit-unify-circuit-service) + * [Delete Unify Circuit service](#delete-unify-circuit-service) + * [Get Unify Circuit service settings](#get-unify-circuit-service-settings) +* [Webex Teams](#webex-teams) + * [Create/Edit Webex Teams service](#createedit-webex-teams-service) + * [Delete Webex Teams service](#delete-webex-teams-service) + * [Get Webex Teams service settings](#get-webex-teams-service-settings) +* [Custom Issue Tracker](#custom-issue-tracker) + * [Create/Edit Custom Issue Tracker service](#createedit-custom-issue-tracker-service) + * [Delete Custom Issue Tracker service](#delete-custom-issue-tracker-service) + * [Get Custom Issue Tracker service settings](#get-custom-issue-tracker-service-settings) +* [Drone CI](#drone-ci) + * [Create/Edit Drone CI service](#createedit-drone-ci-service) + * [Delete Drone CI service](#delete-drone-ci-service) + * [Get Drone CI service settings](#get-drone-ci-service-settings) +* [Emails on push](#emails-on-push) + * [Create/Edit Emails on push service](#createedit-emails-on-push-service) + * [Delete Emails on push service](#delete-emails-on-push-service) + * [Get Emails on push service settings](#get-emails-on-push-service-settings) +* [Confluence service](#confluence-service) + * [Create/Edit Confluence service](#createedit-confluence-service) + * [Delete Confluence service](#delete-confluence-service) + * [Get Confluence service settings](#get-confluence-service-settings) +* [External Wiki](#external-wiki) + * [Create/Edit External Wiki service](#createedit-external-wiki-service) + * [Delete External Wiki service](#delete-external-wiki-service) + * [Get External Wiki service settings](#get-external-wiki-service-settings) +* [Flowdock](#flowdock) + * [Create/Edit Flowdock service](#createedit-flowdock-service) + * [Delete Flowdock service](#delete-flowdock-service) + * [Get Flowdock service settings](#get-flowdock-service-settings) +* [GitHub](#github-premium) + * [Create/Edit GitHub service](#createedit-github-service) + * [Delete GitHub service](#delete-github-service) + * [Get GitHub service settings](#get-github-service-settings) +* [Hangouts Chat](#hangouts-chat) + * [Create/Edit Hangouts Chat service](#createedit-hangouts-chat-service) + * [Delete Hangouts Chat service](#delete-hangouts-chat-service) + * [Get Hangouts Chat service settings](#get-hangouts-chat-service-settings) +* [HipChat](#hipchat) + * [Create/Edit HipChat service](#createedit-hipchat-service) + * [Delete HipChat service](#delete-hipchat-service) + * [Get HipChat service settings](#get-hipchat-service-settings) +* [Irker (IRC gateway)](#irker-irc-gateway) + * [Create/Edit Irker (IRC gateway) service](#createedit-irker-irc-gateway-service) + * [Delete Irker (IRC gateway) service](#delete-irker-irc-gateway-service) + * [Get Irker (IRC gateway) service settings](#get-irker-irc-gateway-service-settings) +* [Jira](#jira) + * [Get Jira service settings](#get-jira-service-settings) + * [Create/Edit Jira service](#createedit-jira-service) + * [Delete Jira service](#delete-jira-service) +* [Slack slash commands](#slack-slash-commands) + * [Get Slack slash command service settings](#get-slack-slash-command-service-settings) + * [Create/Edit Slack slash command service](#createedit-slack-slash-command-service) + * [Delete Slack slash command service](#delete-slack-slash-command-service) +* [Mattermost slash commands](#mattermost-slash-commands) + * [Get Mattermost slash command service settings](#get-mattermost-slash-command-service-settings) + * [Create/Edit Mattermost slash command service](#createedit-mattermost-slash-command-service) + * [Delete Mattermost slash command service](#delete-mattermost-slash-command-service) +* [Packagist](#packagist) + * [Create/Edit Packagist service](#createedit-packagist-service) + * [Delete Packagist service](#delete-packagist-service) + * [Get Packagist service settings](#get-packagist-service-settings) +* [Pipeline-Emails](#pipeline-emails) + * [Create/Edit Pipeline-Emails service](#createedit-pipeline-emails-service) + * [Delete Pipeline-Emails service](#delete-pipeline-emails-service) + * [Get Pipeline-Emails service settings](#get-pipeline-emails-service-settings) +* [PivotalTracker](#pivotaltracker) + * [Create/Edit PivotalTracker service](#createedit-pivotaltracker-service) + * [Delete PivotalTracker service](#delete-pivotaltracker-service) + * [Get PivotalTracker service settings](#get-pivotaltracker-service-settings) +* [Prometheus](#prometheus) + * [Create/Edit Prometheus service](#createedit-prometheus-service) + * [Delete Prometheus service](#delete-prometheus-service) + * [Get Prometheus service settings](#get-prometheus-service-settings) +* [Pushover](#pushover) + * [Create/Edit Pushover service](#createedit-pushover-service) + * [Delete Pushover service](#delete-pushover-service) + * [Get Pushover service settings](#get-pushover-service-settings) +* [Redmine](#redmine) + * [Create/Edit Redmine service](#createedit-redmine-service) + * [Delete Redmine service](#delete-redmine-service) + * [Get Redmine service settings](#get-redmine-service-settings) +* [Slack notifications](#slack-notifications) + * [Create/Edit Slack service](#createedit-slack-service) + * [Delete Slack service](#delete-slack-service) + * [Get Slack service settings](#get-slack-service-settings) +* [Microsoft Teams](#microsoft-teams) + * [Create/Edit Microsoft Teams service](#createedit-microsoft-teams-service) + * [Delete Microsoft Teams service](#delete-microsoft-teams-service) + * [Get Microsoft Teams service settings](#get-microsoft-teams-service-settings) +* [Mattermost notifications](#mattermost-notifications) + * [Create/Edit Mattermost notifications service](#createedit-mattermost-notifications-service) + * [Delete Mattermost notifications service](#delete-mattermost-notifications-service) + * [Get Mattermost notifications service settings](#get-mattermost-notifications-service-settings) +* [JetBrains TeamCity CI](#jetbrains-teamcity-ci) + * [Create/Edit JetBrains TeamCity CI service](#createedit-jetbrains-teamcity-ci-service) + * [Delete JetBrains TeamCity CI service](#delete-jetbrains-teamcity-ci-service) + * [Get JetBrains TeamCity CI service settings](#get-jetbrains-teamcity-ci-service-settings) +* [Jenkins CI](#jenkins-ci-starter) + * [Create/Edit Jenkins CI service](#createedit-jenkins-ci-service) + * [Delete Jenkins CI service](#delete-jenkins-ci-service) + * [Get Jenkins CI service settings](#get-jenkins-ci-service-settings) +* [Jenkins CI (Deprecated) Service](#jenkins-ci-deprecated-service) + * [Create/Edit Jenkins CI (Deprecated) service](#createedit-jenkins-ci-deprecated-service) + * [Delete Jenkins CI (Deprecated) service](#delete-jenkins-ci-deprecated-service) + * [Get Jenkins CI (Deprecated) service settings](#get-jenkins-ci-deprecated-service-settings) +* [MockCI](#mockci) + * [Create/Edit MockCI service](#createedit-mockci-service) + * [Delete MockCI service](#delete-mockci-service) + * [Get MockCI service settings](#get-mockci-service-settings) +* [YouTrack](#youtrack) + * [Create/Edit YouTrack service](#createedit-youtrack-service) + * [Delete YouTrack Service](#delete-youtrack-service) + * [Get YouTrack Service Settings](#get-youtrack-service-settings) + +# Services API[](#services-api "Permalink") + +> **注意:**此 API 需要具有维护者或所有者权限的访问令牌 + +## List all active services[](#list-all-active-services "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21330) . + +获取所有活动项目服务的列表. + +``` +GET /projects/:id/services +``` + +响应示例: + +``` +[ { "id": 75, "title": "Jenkins CI", "slug": "jenkins", "created_at": "2019-11-20T11:20:25.297Z", "updated_at": "2019-11-20T12:24:37.498Z", "active": true, "commit_events": true, "push_events": true, "issues_events": true, "confidential_issues_events": true, "merge_requests_events": true, "tag_push_events": false, "note_events": true, "confidential_note_events": true, "pipeline_events": true, "wiki_page_events": true, "job_events": true, "comment_on_event_enabled": true } { "id": 76, "title": "Alerts endpoint", "slug": "alerts", "created_at": "2019-11-20T11:20:25.297Z", "updated_at": "2019-11-20T12:24:37.498Z", "active": true, "commit_events": true, "push_events": true, "issues_events": true, "confidential_issues_events": true, "merge_requests_events": true, "tag_push_events": true, "note_events": true, "confidential_note_events": true, "pipeline_events": true, "wiki_page_events": true, "job_events": true, "comment_on_event_enabled": true } ] +``` + +## Asana[](#asana "Permalink") + +Asana-无需电子邮件的团队合作 + +### Create/Edit Asana service[](#createedit-asana-service "Permalink") + +为项目设置 Asana 服务. + +> 该服务将提交消息添加为 Asana 任务的注释. 启用后,将检查提交消息中的 Asana 任务 URL(例如`https://app.asana.com/0/123456/987654` )或以#开头的任务 ID(例如`#987654` ). 找到的每个任务 ID 都会在其中添加提交注释. 您还可以通过以下消息关闭任务: `fix #123456` . 您可以在以下位置找到您的 API 密钥: [https](https://developers.asana.com/docs/#authentication-basics) : [//developers.asana.com/docs/#authentication-basics](https://developers.asana.com/docs/#authentication-basics) . + +``` +PUT /projects/:id/services/asana +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `api_key` | string | true | 用户 API 令牌. 用户必须有权访问任务,所有评论都将归于该用户. | +| `restrict_to_branch` | string | false | 以逗号分隔的分支列表,将自动对其进行检查. 保留空白以包括所有分支. | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Asana service[](#delete-asana-service "Permalink") + +删除项目的 Asana 服务. + +``` +DELETE /projects/:id/services/asana +``` + +### Get Asana service settings[](#get-asana-service-settings "Permalink") + +获取项目的 Asana 服务设置. + +``` +GET /projects/:id/services/asana +``` + +## Assembla[](#assembla "Permalink") + +项目管理软件(源提交端点) + +### Create/Edit Assembla service[](#createedit-assembla-service "Permalink") + +为项目设置 Assembla 服务. + +``` +PUT /projects/:id/services/assembla +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | 认证令牌 | +| `subdomain` | string | false | 子域设置 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Assembla service[](#delete-assembla-service "Permalink") + +删除项目的 Assembla 服务. + +``` +DELETE /projects/:id/services/assembla +``` + +### Get Assembla service settings[](#get-assembla-service-settings "Permalink") + +获取项目的 Assembla 服务设置. + +``` +GET /projects/:id/services/assembla +``` + +## Atlassian Bamboo CI[](#atlassian-bamboo-ci "Permalink") + +持续集成和构建服务器 + +### Create/Edit Atlassian Bamboo CI service[](#createedit-atlassian-bamboo-ci-service "Permalink") + +为项目设置 Atlassian Bamboo CI 服务. + +> 您必须在 Bamboo 中设置自动修订标签和存储库触发器. + +``` +PUT /projects/:id/services/bamboo +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `bamboo_url` | string | true | 竹根 URL. 例如, `https://bamboo.example.com` . | +| `build_key` | string | true | 竹构建计划密钥,如 KEY | +| `username` | string | true | 具有 API 访问权限的用户(如果适用) | +| `password` | string | true | 用户密码 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Atlassian Bamboo CI service[](#delete-atlassian-bamboo-ci-service "Permalink") + +删除项目的 Atlassian Bamboo CI 服务. + +``` +DELETE /projects/:id/services/bamboo +``` + +### Get Atlassian Bamboo CI service settings[](#get-atlassian-bamboo-ci-service-settings "Permalink") + +获取项目的 Atlassian Bamboo CI 服务设置. + +``` +GET /projects/:id/services/bamboo +``` + +## Bugzilla[](#bugzilla "Permalink") + +Bugzilla 问题追踪器 + +### Create/Edit Bugzilla service[](#createedit-bugzilla-service "Permalink") + +为项目设置 Bugzilla 服务. + +``` +PUT /projects/:id/services/bugzilla +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `new_issue_url` | string | true | 新发行网址 | +| `issues_url` | string | true | 发行网址 | +| `project_url` | string | true | 项目网址 | +| `description` | string | false | Description | +| `title` | string | false | Title | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Bugzilla Service[](#delete-bugzilla-service "Permalink") + +删除项目的 Bugzilla 服务. + +``` +DELETE /projects/:id/services/bugzilla +``` + +### Get Bugzilla Service Settings[](#get-bugzilla-service-settings "Permalink") + +获取项目的 Bugzilla 服务设置. + +``` +GET /projects/:id/services/bugzilla +``` + +## Buildkite[](#buildkite "Permalink") + +持续集成和部署 + +### Create/Edit Buildkite service[](#createedit-buildkite-service "Permalink") + +为项目设置 Buildkite 服务. + +``` +PUT /projects/:id/services/buildkite +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | Buildkite 项目 GitLab 令牌 | +| `project_url` | string | true | `https://buildkite.com/example/project` | +| `enable_ssl_verification` | boolean | false | 启用 S​​SL 验证 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Buildkite service[](#delete-buildkite-service "Permalink") + +删除项目的 Buildkite 服务. + +``` +DELETE /projects/:id/services/buildkite +``` + +### Get Buildkite service settings[](#get-buildkite-service-settings "Permalink") + +获取项目的 Buildkite 服务设置. + +``` +GET /projects/:id/services/buildkite +``` + +## Campfire[](#campfire "Permalink") + +基于网络的简单实时群聊 + +### Create/Edit Campfire service[](#createedit-campfire-service "Permalink") + +为项目设置篝火服务. + +``` +PUT /projects/:id/services/campfire +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | 篝火令牌 | +| `subdomain` | string | false | 篝火子域 | +| `room` | string | false | 篝火室 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Campfire service[](#delete-campfire-service "Permalink") + +删除项目的 Campfire 服务. + +``` +DELETE /projects/:id/services/campfire +``` + +### Get Campfire service settings[](#get-campfire-service-settings "Permalink") + +获取项目的 Campfire 服务设置. + +``` +GET /projects/:id/services/campfire +``` + +## Unify Circuit[](#unify-circuit "Permalink") + +统一电路 RTC 和协作工具. + +### Create/Edit Unify Circuit service[](#createedit-unify-circuit-service "Permalink") + +为项目设置"统一电路"服务. + +``` +PUT /projects/:id/services/unify-circuit +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `webhook` | string | true | 统一电路网络挂钩. 例如, `https://circuit.com/rest/v2/webhooks/incoming/...` | +| `notify_only_broken_pipelines` | boolean | false | 发送有关管道中断的通知 | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `push_events` | boolean | false | 启用推送事件通知 | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `confidential_issues_events` | boolean | false | 启用机密问题事件的通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `note_events` | boolean | false | 启用笔记事件通知 | +| `confidential_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | +| `wiki_page_events` | boolean | false | 启用 Wiki 页面事件的通知 | + +### Delete Unify Circuit service[](#delete-unify-circuit-service "Permalink") + +删除项目的统一电路服务. + +``` +DELETE /projects/:id/services/unify-circuit +``` + +### Get Unify Circuit service settings[](#get-unify-circuit-service-settings "Permalink") + +获取项目的统一电路服务设置. + +``` +GET /projects/:id/services/unify-circuit +``` + +## Webex Teams[](#webex-teams "Permalink") + +Webex Teams 协作工具. + +### Create/Edit Webex Teams service[](#createedit-webex-teams-service "Permalink") + +为项目设置 Webex Teams 服务. + +``` +PUT /projects/:id/services/webex-teams +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `webhook` | string | true | Webex Teams Webhook. 例如, `https://api.ciscospark.com/v1/webhooks/incoming/...` | +| `notify_only_broken_pipelines` | boolean | false | 发送有关管道中断的通知 | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `push_events` | boolean | false | 启用推送事件通知 | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `confidential_issues_events` | boolean | false | 启用机密问题事件的通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `note_events` | boolean | false | 启用笔记事件通知 | +| `confidential_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | +| `wiki_page_events` | boolean | false | 启用 Wiki 页面事件的通知 | + +### Delete Webex Teams service[](#delete-webex-teams-service "Permalink") + +删除项目的 Webex Teams 服务. + +``` +DELETE /projects/:id/services/webex-teams +``` + +### Get Webex Teams service settings[](#get-webex-teams-service-settings "Permalink") + +获取项目的 Webex Teams 服务设置. + +``` +GET /projects/:id/services/webex-teams +``` + +## Custom Issue Tracker[](#custom-issue-tracker "Permalink") + +自定义问题跟踪器 + +### Create/Edit Custom Issue Tracker service[](#createedit-custom-issue-tracker-service "Permalink") + +为项目设置自定义问题跟踪服务. + +``` +PUT /projects/:id/services/custom-issue-tracker +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `new_issue_url` | string | true | 新发行网址 | +| `issues_url` | string | true | 发行网址 | +| `project_url` | string | true | 项目网址 | +| `description` | string | false | Description | +| `title` | string | false | Title | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Custom Issue Tracker service[](#delete-custom-issue-tracker-service "Permalink") + +删除项目的自定义问题跟踪服务. + +``` +DELETE /projects/:id/services/custom-issue-tracker +``` + +### Get Custom Issue Tracker service settings[](#get-custom-issue-tracker-service-settings "Permalink") + +获取项目的自定义问题跟踪服务设置. + +``` +GET /projects/:id/services/custom-issue-tracker +``` + +## Drone CI[](#drone-ci "Permalink") + +Drone 是一个基于 Go 编写的基于 Docker 的持续集成平台 + +### Create/Edit Drone CI service[](#createedit-drone-ci-service "Permalink") + +为项目设置 Drone CI 服务. + +``` +PUT /projects/:id/services/drone-ci +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | 无人机 CI 项目专用令牌 | +| `drone_url` | string | true | `http://drone.example.com` | +| `enable_ssl_verification` | boolean | false | 启用 S​​SL 验证 | +| `push_events` | boolean | false | 启用推送事件通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | + +### Delete Drone CI service[](#delete-drone-ci-service "Permalink") + +删除项目的 Drone CI 服务. + +``` +DELETE /projects/:id/services/drone-ci +``` + +### Get Drone CI service settings[](#get-drone-ci-service-settings "Permalink") + +获取项目的 Drone CI 服务设置. + +``` +GET /projects/:id/services/drone-ci +``` + +## Emails on push[](#emails-on-push "Permalink") + +通过电子邮件将每次推送的提交和差异发送到收件人列表. + +### Create/Edit Emails on push service[](#createedit-emails-on-push-service "Permalink") + +在项目的推送服务上设置电子邮件. + +``` +PUT /projects/:id/services/emails-on-push +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `recipients` | string | true | 用空格分隔的电子邮件 | +| `disable_diffs` | boolean | false | 禁用代码差异 | +| `send_from_committer_email` | boolean | false | 从提交者发送 | +| `push_events` | boolean | false | 启用推送事件通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected". 推送标签会始终触发通知. | + +### Delete Emails on push service[](#delete-emails-on-push-service "Permalink") + +删除项目的推送服务电子邮件. + +``` +DELETE /projects/:id/services/emails-on-push +``` + +### Get Emails on push service settings[](#get-emails-on-push-service-settings "Permalink") + +获取有关项目的推送服务设置的电子邮件. + +``` +GET /projects/:id/services/emails-on-push +``` + +## Confluence service[](#confluence-service "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/220934) . + +将到内部 Wiki 的链接替换为到 Confluence Cloud Workspace 的链接. + +### Create/Edit Confluence service[](#createedit-confluence-service "Permalink") + +为项目设置 Confluence 服务. + +``` +PUT /projects/:id/services/confluence +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `confluence_url` | string | true | Confluence Cloud Workspace 的 URL 托管在 atlassian.net 上. | + +### Delete Confluence service[](#delete-confluence-service "Permalink") + +删除项目的 Confluence 服务. + +``` +DELETE /projects/:id/services/confluence +``` + +### Get Confluence service settings[](#get-confluence-service-settings "Permalink") + +获取项目的 Confluence 服务设置. + +``` +GET /projects/:id/services/confluence +``` + +## External Wiki[](#external-wiki "Permalink") + +将指向内部 Wiki 的链接替换为指向外部 Wiki 的链接. + +### Create/Edit External Wiki service[](#createedit-external-wiki-service "Permalink") + +为项目设置外部 Wiki 服务. + +``` +PUT /projects/:id/services/external-wiki +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `external_wiki_url` | string | true | 外部 Wiki 的 URL | + +### Delete External Wiki service[](#delete-external-wiki-service "Permalink") + +删除项目的外部 Wiki 服务. + +``` +DELETE /projects/:id/services/external-wiki +``` + +### Get External Wiki service settings[](#get-external-wiki-service-settings "Permalink") + +获取项目的外部 Wiki 服务设置. + +``` +GET /projects/:id/services/external-wiki +``` + +## Flowdock[](#flowdock "Permalink") + +Flowdock 是面向技术团队的协作 Web 应用程序. + +### Create/Edit Flowdock service[](#createedit-flowdock-service "Permalink") + +为项目设置 Flowdock 服务. + +``` +PUT /projects/:id/services/flowdock +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | Flowdock Git 源令牌 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Flowdock service[](#delete-flowdock-service "Permalink") + +删除项目的 Flowdock 服务. + +``` +DELETE /projects/:id/services/flowdock +``` + +### Get Flowdock service settings[](#get-flowdock-service-settings "Permalink") + +获取项目的 Flowdock 服务设置. + +``` +GET /projects/:id/services/flowdock +``` + +## GitHub[](#github-premium "Permalink") + +代码协作软件. + +### Create/Edit GitHub service[](#createedit-github-service "Permalink") + +为项目设置 GitHub 服务. + +``` +PUT /projects/:id/services/github +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | 具有`repo:status` OAuth 范围的 GitHub API 令牌 | +| `repository_url` | string | true | GitHub 存储库 URL | +| `static_context` | boolean | false | 将实例名称而不是分支附加到[状态检查名称](../user/project/integrations/github.html#static--dynamic-status-check-names) | + +### Delete GitHub service[](#delete-github-service "Permalink") + +删除项目的 GitHub 服务. + +``` +DELETE /projects/:id/services/github +``` + +### Get GitHub service settings[](#get-github-service-settings "Permalink") + +获取项目的 GitHub 服务设置. + +``` +GET /projects/:id/services/github +``` + +## Hangouts Chat[](#hangouts-chat "Permalink") + +Google GSuite 团队协作工具. + +> **注意:**此服务是[在 v11.2](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20290)中[引入的](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20290) + +### Create/Edit Hangouts Chat service[](#createedit-hangouts-chat-service "Permalink") + +为项目设置环聊聊天服务. + +``` +PUT /projects/:id/services/hangouts-chat +``` + +> **注意:** [v10.4](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435)特定的事件参数(例如`push_events`标志) + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `webhook` | string | true | Hangouts 即时通讯网路挂钩. 例如, `https://chat.googleapis.com/v1/spaces...` | +| `notify_only_broken_pipelines` | boolean | false | 发送有关管道中断的通知 | +| `notify_only_default_branch` | boolean | false | 已弃用:此参数已替换为`branches_to_be_notified` | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `push_events` | boolean | false | 启用推送事件通知 | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `note_events` | boolean | false | 启用笔记事件通知 | +| `confidential_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | +| `wiki_page_events` | boolean | false | 启用 Wiki 页面事件的通知 | + +### Delete Hangouts Chat service[](#delete-hangouts-chat-service "Permalink") + +删除项目的环聊聊天服务. + +``` +DELETE /projects/:id/services/hangouts-chat +``` + +### Get Hangouts Chat service settings[](#get-hangouts-chat-service-settings "Permalink") + +获取项目的环聊聊天服务设置. + +``` +GET /projects/:id/services/hangouts-chat +``` + +## HipChat[](#hipchat "Permalink") + +私人群聊和即时消息 + +### Create/Edit HipChat service[](#createedit-hipchat-service "Permalink") + +为项目设置 HipChat 服务. + +``` +PUT /projects/:id/services/hipchat +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | 房间代币 | +| `color` | string | false | 房间颜色 | +| `notify` | boolean | false | 启用通知 | +| `room` | string | false | 房间名称或 ID | +| `api_version` | string | false | 默认保留空白(v2) | +| `server` | string | false | 默认保留空白. 例如, `https://hipchat.example.com` . | +| `push_events` | boolean | false | 启用推送事件通知 | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `confidential_issues_events` | boolean | false | 启用机密问题事件的通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `note_events` | boolean | false | Enable notifications for note events | +| `confidental_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | + +### Delete HipChat service[](#delete-hipchat-service "Permalink") + +删除项目的 HipChat 服务. + +``` +DELETE /projects/:id/services/hipchat +``` + +### Get HipChat service settings[](#get-hipchat-service-settings "Permalink") + +获取项目的 HipChat 服务设置. + +``` +GET /projects/:id/services/hipchat +``` + +## Irker (IRC gateway)[](#irker-irc-gateway "Permalink") + +通过 Irker 网关在更新后将 IRC 消息发送到收件人列表. + +### Create/Edit Irker (IRC gateway) service[](#createedit-irker-irc-gateway-service "Permalink") + +为项目设置 Irker(IRC 网关)服务. + +> Irker 没有内置的身份验证,如果托管在防火墙外部,则容易受到 IRC 垃圾邮件的攻击. 请确保在安全的网络中运行守护程序,以防止滥用. 有关更多详细信息,请阅读: [http](http://www.catb.org/~esr/irker/security.html) : [//www.catb.org/~esr/irker/security.html](http://www.catb.org/~esr/irker/security.html) . + +``` +PUT /projects/:id/services/irker +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `recipients` | string | true | 用空格分隔的收件人/渠道 | +| `default_irc_uri` | string | false | `irc://irc.network.net:6697/` | +| `server_host` | string | false | localhost | +| `server_port` | integer | false | 6659 | +| `colorize_messages` | boolean | false | 为邮件着色 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Irker (IRC gateway) service[](#delete-irker-irc-gateway-service "Permalink") + +删除项目的 Irker(IRC 网关)服务. + +``` +DELETE /projects/:id/services/irker +``` + +### Get Irker (IRC gateway) service settings[](#get-irker-irc-gateway-service-settings "Permalink") + +Get Irker (IRC gateway) service settings for a project. + +``` +GET /projects/:id/services/irker +``` + +## Jira[](#jira "Permalink") + +吉拉问题追踪器. + +### Get Jira service settings[](#get-jira-service-settings "Permalink") + +获取项目的 Jira 服务设置. + +``` +GET /projects/:id/services/jira +``` + +### Create/Edit Jira service[](#createedit-jira-service "Permalink") + +为项目设置 Jira 服务. + +> 与 GitLab 8.14 开始, `api_url` , `issues_url` , `new_issue_url`和`project_url`被替换`url` . 如果您使用的是旧版本,请[遵循此文档](https://gitlab.com/gitlab-org/gitlab/blob/8-13-stable-ee/doc/api/services.md#jira) . + +``` +PUT /projects/:id/services/jira +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `url` | string | yes | 链接到该 GitLab 项目的 Jira 项目的 URL. 例如, `https://jira.example.com` . | +| `api_url` | string | no | Jira 实例 API 的基本 URL. 如果未设置,将使用 Web URL 值. 例如, `https://jira-api.example.com` . | +| `username` | string | yes | 创建用于 GitLab / Jira 的用户的用户名. | +| `password` | string | yes | 创建的用于 GitLab / Jira 的用户密码. | +| `active` | boolean | no | 激活或停用服务. 默认为 false(停用). | +| `jira_issue_transition_id` | string | no | 将问题移到关闭状态的过渡的 ID. 您可以在 Jira 工作流管理( **管理>问题>工作流** )下找到该编号,方法是在所需项目工作流的" **操作** **"**下选择" **查看** **"** . 每个状态的 ID 可以在" **转换(id)"**列下每个转换名称的括号内找到. 默认情况下,此 ID 设置为`2` . | +| `commit_events` | boolean | false | 启用提交事件通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `comment_on_event_enabled` | boolean | false | 在每个 GitLab 事件(提交/合并请求)的 Jira 问题中启用评论 | + +### Delete Jira service[](#delete-jira-service "Permalink") + +从项目中删除所有以前的 Jira 设置. + +``` +DELETE /projects/:id/services/jira +``` + +## Slack slash commands[](#slack-slash-commands "Permalink") + +能够从 Slack 聊天实例接收斜线命令. + +### Get Slack slash command service settings[](#get-slack-slash-command-service-settings "Permalink") + +获取项目的 Slack 斜杠命令服务设置. + +``` +GET /projects/:id/services/slack-slash-commands +``` + +响应示例: + +``` +{ "id": 4, "title": "Slack slash commands", "slug": "slack-slash-commands", "created_at": "2017-06-27T05:51:39-07:00", "updated_at": "2017-06-27T05:51:39-07:00", "active": true, "push_events": true, "issues_events": true, "confidential_issues_events": true, "merge_requests_events": true, "tag_push_events": true, "note_events": true, "job_events": true, "pipeline_events": true, "comment_on_event_enabled": false, "properties": { "token": "" } } +``` + +### Create/Edit Slack slash command service[](#createedit-slack-slash-command-service "Permalink") + +为项目设置 Slack 斜杠命令. + +``` +PUT /projects/:id/services/slack-slash-commands +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | yes | Slack 令牌 | + +### Delete Slack slash command service[](#delete-slack-slash-command-service "Permalink") + +删除项目的 Slack 斜杠命令服务. + +``` +DELETE /projects/:id/services/slack-slash-commands +``` + +## Mattermost slash commands[](#mattermost-slash-commands "Permalink") + +能够从 Mattermost 聊天实例接收斜线命令. + +### Get Mattermost slash command service settings[](#get-mattermost-slash-command-service-settings "Permalink") + +获取项目的 Mattermost 斜杠命令服务设置. + +``` +GET /projects/:id/services/mattermost-slash-commands +``` + +### Create/Edit Mattermost slash command service[](#createedit-mattermost-slash-command-service "Permalink") + +为项目设置 Mattermost 斜杠命令. + +``` +PUT /projects/:id/services/mattermost-slash-commands +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | yes | 最重要的令牌 | +| `username` | string | no | 用于发布消息的用户名 | + +### Delete Mattermost slash command service[](#delete-mattermost-slash-command-service "Permalink") + +删除项目的 Mattermost 斜杠命令服务. + +``` +DELETE /projects/:id/services/mattermost-slash-commands +``` + +## Packagist[](#packagist "Permalink") + +当提交或标签被推送到 GitLab 时,在 Packagist(主要的 Composer 存储库)上更新您的项目. + +### Create/Edit Packagist service[](#createedit-packagist-service "Permalink") + +为项目设置 Packagist 服务. + +``` +PUT /projects/:id/services/packagist +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `username` | string | yes | Packagist 帐户的用户名 | +| `token` | string | yes | Packagist 服务器的 API 令牌 | +| `server` | boolean | no | Packagist 服务器的 URL. 默认保留空白: [https](https://packagist.org) : [//packagist.org](https://packagist.org) | +| `push_events` | boolean | false | 启用推送事件通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | + +### Delete Packagist service[](#delete-packagist-service "Permalink") + +删除项目的 Packagist 服务. + +``` +DELETE /projects/:id/services/packagist +``` + +### Get Packagist service settings[](#get-packagist-service-settings "Permalink") + +获取项目的 Packagist 服务设置. + +``` +GET /projects/:id/services/packagist +``` + +## Pipeline-Emails[](#pipeline-emails "Permalink") + +获取有关 GitLab CI / CD 管道的电子邮件. + +### Create/Edit Pipeline-Emails service[](#createedit-pipeline-emails-service "Permalink") + +设置项目的管道电子邮件服务. + +``` +PUT /projects/:id/services/pipelines-email +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `recipients` | string | yes | 以逗号分隔的收件人电子邮件地址列表 | +| `add_pusher` | boolean | no | 将推送器添加到收件人列表 | +| `notify_only_broken_pipelines` | boolean | no | 仅通知断开的管道 | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `notify_only_default_branch` | boolean | no | 仅针对默认分支发送通知( [在 GitLab 12.0 中引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28271) ) | +| `pipeline_events` | boolean | false | 启用管道事件通知 | + +### Delete Pipeline-Emails service[](#delete-pipeline-emails-service "Permalink") + +删除项目的管道电子邮件服务. + +``` +DELETE /projects/:id/services/pipelines-email +``` + +### Get Pipeline-Emails service settings[](#get-pipeline-emails-service-settings "Permalink") + +获取项目的管道电子邮件服务设置. + +``` +GET /projects/:id/services/pipelines-email +``` + +## PivotalTracker[](#pivotaltracker "Permalink") + +项目管理软件(源提交端点) + +### Create/Edit PivotalTracker service[](#createedit-pivotaltracker-service "Permalink") + +为项目设置 PivotalTracker 服务. + +``` +PUT /projects/:id/services/pivotaltracker +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `token` | string | true | PivotalTracker 令牌 | +| `restrict_to_branch` | boolean | false | 以逗号分隔的分支列表,将自动对其进行检查. 保留空白以包括所有分支. | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete PivotalTracker service[](#delete-pivotaltracker-service "Permalink") + +删除项目的 PivotalTracker 服务. + +``` +DELETE /projects/:id/services/pivotaltracker +``` + +### Get PivotalTracker service settings[](#get-pivotaltracker-service-settings "Permalink") + +获取项目的 PivotalTracker 服务设置. + +``` +GET /projects/:id/services/pivotaltracker +``` + +## Prometheus[](#prometheus "Permalink") + +Prometheus 是一项功能强大的时间序列监视服务. + +### Create/Edit Prometheus service[](#createedit-prometheus-service "Permalink") + +为项目设置 Prometheus 服务. + +``` +PUT /projects/:id/services/prometheus +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `api_url` | string | true | Prometheus API 基本 URL. 例如, `http://prometheus.example.com/` . | +| `google_iap_audience_client_id` | string | false | IAP 受保护资源的客户端 ID(看起来像 IAP_CLIENT_ID.apps.googleusercontent.com) | +| `google_iap_service_account_json` | string | false | 您的服务帐户的`credentials.json`文件,例如{" type":" service_account"," project_id":…} | + +### Delete Prometheus service[](#delete-prometheus-service "Permalink") + +删除项目的 Prometheus 服务. + +``` +DELETE /projects/:id/services/prometheus +``` + +### Get Prometheus service settings[](#get-prometheus-service-settings "Permalink") + +获取项目的 Prometheus 服务设置. + +``` +GET /projects/:id/services/prometheus +``` + +## Pushover[](#pushover "Permalink") + +通过 Pushover,可以轻松在 Android 设备,iPhone,iPad 和台式机上获取实时通知. + +### Create/Edit Pushover service[](#createedit-pushover-service "Permalink") + +为项目设置 Pushover 服务. + +``` +PUT /projects/:id/services/pushover +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `api_key` | string | true | Your application key | +| `user_key` | string | true | 您的用户密钥 | +| `priority` | string | true | 优先事项 | +| `device` | string | false | 对于所有活动设备保留空白 | +| `sound` | string | false | 通知的声音 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Pushover service[](#delete-pushover-service "Permalink") + +删除项目的 Pushover 服务. + +``` +DELETE /projects/:id/services/pushover +``` + +### Get Pushover service settings[](#get-pushover-service-settings "Permalink") + +获取项目的 Pushover 服务设置. + +``` +GET /projects/:id/services/pushover +``` + +## Redmine[](#redmine "Permalink") + +Redmine 问题追踪器 + +### Create/Edit Redmine service[](#createedit-redmine-service "Permalink") + +为项目设置 Redmine 服务. + +``` +PUT /projects/:id/services/redmine +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `new_issue_url` | string | true | 新发行网址 | +| `project_url` | string | true | 项目网址 | +| `issues_url` | string | true | 发行网址 | +| `description` | string | false | Description | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete Redmine service[](#delete-redmine-service "Permalink") + +删除项目的 Redmine 服务. + +``` +DELETE /projects/:id/services/redmine +``` + +### Get Redmine service settings[](#get-redmine-service-settings "Permalink") + +获取项目的 Redmine 服务设置. + +``` +GET /projects/:id/services/redmine +``` + +## Slack notifications[](#slack-notifications "Permalink") + +在 Slack 中接收事件通知 + +### Create/Edit Slack service[](#createedit-slack-service "Permalink") + +为项目设置 Slack 服务. + +``` +PUT /projects/:id/services/slack +``` + +> **注意:** [v10.4](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435)特定的事件参数(例如`push_events`标志和`push_channel` ) + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `webhook` | string | true | `https://hooks.slack.com/services/...` | +| `username` | string | false | username | +| `channel` | string | false | 如果未配置其他频道,则使用默认频道 | +| `notify_only_broken_pipelines` | boolean | false | 发送有关管道中断的通知 | +| `notify_only_default_branch` | boolean | false | 已弃用:此参数已替换为`branches_to_be_notified` | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `commit_events` | boolean | false | 启用提交事件通知 | +| `confidential_issue_channel` | string | false | 接收机密问题事件通知的渠道的名称 | +| `confidential_issues_events` | boolean | false | 启用机密问题事件的通知 | +| `confidential_note_channel` | string | false | 接收机密笔记事件通知的渠道的名称 | +| `confidential_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `deployment_channel` | string | false | 接收部署事件通知的通道的名称 | +| `deployment_events` | boolean | false | 启用部署事件通知 | +| `issue_channel` | string | false | 接收问题事件通知的渠道的名称 | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `job_events` | boolean | false | 启用工作事件通知 | +| `merge_request_channel` | string | false | 接收合并请求事件通知的通道的名称 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `note_channel` | string | false | 接收音符事件通知的频道名称 | +| `note_events` | boolean | false | 启用笔记事件通知 | +| `pipeline_channel` | string | false | 接收管道事件通知的通道的名称 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | +| `push_channel` | string | false | 接收推送事件通知的通道的名称 | +| `push_events` | boolean | false | 启用推送事件通知 | +| `tag_push_channel` | string | false | 接收标签推送事件通知的通道的名称 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `wiki_page_channel` | string | false | 接收维基页面事件通知的频道名称 | +| `wiki_page_events` | boolean | false | 启用 Wiki 页面事件的通知 | + +### Delete Slack service[](#delete-slack-service "Permalink") + +删除项目的 Slack 服务. + +``` +DELETE /projects/:id/services/slack +``` + +### Get Slack service settings[](#get-slack-service-settings "Permalink") + +获取项目的 Slack 服务设置. + +``` +GET /projects/:id/services/slack +``` + +## Microsoft Teams[](#microsoft-teams "Permalink") + +群聊软件 + +### Create/Edit Microsoft Teams service[](#createedit-microsoft-teams-service "Permalink") + +为项目设置 Microsoft Teams 服务. + +``` +PUT /projects/:id/services/microsoft-teams +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `webhook` | string | true | Microsoft Teams 网络挂钩. 例如, `https://outlook.office.com/webhook/...` | +| `notify_only_broken_pipelines` | boolean | false | 发送有关管道中断的通知 | +| `notify_only_default_branch` | boolean | false | 已弃用:此参数已替换为`branches_to_be_notified` | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `push_events` | boolean | false | Enable notifications for push events | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `confidential_issues_events` | boolean | false | 启用机密问题事件的通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `note_events` | boolean | false | 启用笔记事件通知 | +| `confidential_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | +| `wiki_page_events` | boolean | false | 启用 Wiki 页面事件的通知 | + +### Delete Microsoft Teams service[](#delete-microsoft-teams-service "Permalink") + +删除项目的 Microsoft Teams 服务. + +``` +DELETE /projects/:id/services/microsoft-teams +``` + +### Get Microsoft Teams service settings[](#get-microsoft-teams-service-settings "Permalink") + +获取项目的 Microsoft Teams 服务设置. + +``` +GET /projects/:id/services/microsoft-teams +``` + +## Mattermost notifications[](#mattermost-notifications "Permalink") + +在 Mattermost 接收事件通知 + +### Create/Edit Mattermost notifications service[](#createedit-mattermost-notifications-service "Permalink") + +为项目设置 Mattermost 服务. + +``` +PUT /projects/:id/services/mattermost +``` + +> **注意:** [v10.4](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435)中[引入了](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435)特定的事件参数(例如`push_events`标志和`push_channel` ) + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `webhook` | string | true | 最重要的网络挂钩. 例如, `http://mattermost_host/hooks/...` | +| `username` | string | false | username | +| `channel` | string | false | 如果未配置其他频道,则使用默认频道 | +| `notify_only_broken_pipelines` | boolean | false | 发送有关管道中断的通知 | +| `notify_only_default_branch` | boolean | false | 已弃用:此参数已替换为`branches_to_be_notified` | +| `branches_to_be_notified` | string | all | 发送通知的分支. 有效选项为"所有","默认","受保护"和" default_and_protected" | +| `push_events` | boolean | false | 启用推送事件通知 | +| `issues_events` | boolean | false | 启用问题事件通知 | +| `confidential_issues_events` | boolean | false | 启用机密问题事件的通知 | +| `merge_requests_events` | boolean | false | 启用合并请求事件的通知 | +| `tag_push_events` | boolean | false | 启用标签推送事件的通知 | +| `note_events` | boolean | false | 启用笔记事件通知 | +| `confidential_note_events` | boolean | false | 启用机密笔记事件的通知 | +| `pipeline_events` | boolean | false | 启用管道事件通知 | +| `wiki_page_events` | boolean | false | 启用 Wiki 页面事件的通知 | +| `push_channel` | string | false | 接收推送事件通知的通道的名称 | +| `issue_channel` | string | false | 接收问题事件通知的渠道的名称 | +| `confidential_issue_channel` | string | false | 接收机密问题事件通知的渠道的名称 | +| `merge_request_channel` | string | false | 接收合并请求事件通知的通道的名称 | +| `note_channel` | string | false | 接收音符事件通知的频道名称 | +| `confidential_note_channel` | boolean | 接收机密笔记事件通知的渠道的名称 |   | +| `tag_push_channel` | string | false | 接收标签推送事件通知的通道的名称 | +| `pipeline_channel` | string | false | 接收管道事件通知的通道的名称 | +| `wiki_page_channel` | string | false | 接收维基页面事件通知的频道名称 | + +### Delete Mattermost notifications service[](#delete-mattermost-notifications-service "Permalink") + +删除项目的 Mattermost Notifications 服务. + +``` +DELETE /projects/:id/services/mattermost +``` + +### Get Mattermost notifications service settings[](#get-mattermost-notifications-service-settings "Permalink") + +获取项目的"最重要的通知"服务设置. + +``` +GET /projects/:id/services/mattermost +``` + +## JetBrains TeamCity CI[](#jetbrains-teamcity-ci "Permalink") + +持续集成和构建服务器 + +### Create/Edit JetBrains TeamCity CI service[](#createedit-jetbrains-teamcity-ci-service "Permalink") + +为项目设置 JetBrains TeamCity CI 服务. + +> TeamCity 中的构建配置必须使用构建格式编号`%build.vcs.number%`您还将要配置对所有分支的监视,以便合并请求得以构建,该设置位于 VSC 根高级设置中. + +``` +PUT /projects/:id/services/teamcity +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `teamcity_url` | string | true | TeamCity 根 URL. 例如, `https://teamcity.example.com` | +| `build_type` | string | true | 构建配置 ID | +| `username` | string | true | 有权触发手动构建的用户 | +| `password` | string | true | 用户密码 | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete JetBrains TeamCity CI service[](#delete-jetbrains-teamcity-ci-service "Permalink") + +删除项目的 JetBrains TeamCity CI 服务. + +``` +DELETE /projects/:id/services/teamcity +``` + +### Get JetBrains TeamCity CI service settings[](#get-jetbrains-teamcity-ci-service-settings "Permalink") + +获取项目的 JetBrains TeamCity CI 服务设置. + +``` +GET /projects/:id/services/teamcity +``` + +## Jenkins CI[](#jenkins-ci-starter "Permalink") + +持续集成和构建服务器 + +### Create/Edit Jenkins CI service[](#createedit-jenkins-ci-service "Permalink") + +为项目设置 Jenkins CI 服务. + +``` +PUT /projects/:id/services/jenkins +``` + +Parameters: + +* `jenkins_url` ( **必填** ) `jenkins_url` URL,例如`http://jenkins.example.com` +* `project_name` ( **必需** )-URL 友好的项目名称. 示例:my_project_name +* `username` (可选)-有权访问 Jenkins 服务器的`username` (如果适用) +* `password` (可选)-用户的密码 + +### Delete Jenkins CI service[](#delete-jenkins-ci-service "Permalink") + +删除项目的 Jenkins CI 服务. + +``` +DELETE /projects/:id/services/jenkins +``` + +### Get Jenkins CI service settings[](#get-jenkins-ci-service-settings "Permalink") + +获取项目的 Jenkins CI 服务设置. + +``` +GET /projects/:id/services/jenkins +``` + +## Jenkins CI (Deprecated) Service[](#jenkins-ci-deprecated-service "Permalink") + +持续集成和构建服务器 + +**注意:**此服务已[在 v13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/1600)中[删除](https://gitlab.com/gitlab-org/gitlab/-/issues/1600) + +### Create/Edit Jenkins CI (Deprecated) service[](#createedit-jenkins-ci-deprecated-service "Permalink") + +为项目设置 Jenkins CI(不推荐使用)服务. + +``` +PUT /projects/:id/services/jenkins-deprecated +``` + +Parameters: + +* `project_url` ( **必填** )-Jenkins 项目网址,例如`http://jenkins.example.com/job/my-project/` +* `multiproject_enabled` (可选)-在 Jenkins GitLab Hook 插件中配置了多项目模式 +* `pass_unstable` (可选)-不稳定的版本将被视为通过 + +### Delete Jenkins CI (Deprecated) service[](#delete-jenkins-ci-deprecated-service "Permalink") + +删除项目的 Jenkins CI(不推荐使用)服务. + +``` +DELETE /projects/:id/services/jenkins-deprecated +``` + +### Get Jenkins CI (Deprecated) service settings[](#get-jenkins-ci-deprecated-service-settings "Permalink") + +获取项目的 Jenkins CI(不推荐使用)服务设置. + +``` +GET /projects/:id/services/jenkins-deprecated +``` + +## MockCI[](#mockci "Permalink") + +模拟一个外部配置项. 有关伴随模拟服务的示例,请参见[`gitlab-org/gitlab-mock-ci-service`](https://gitlab.com/gitlab-org/gitlab-mock-ci-service) service. + +仅当您的环境设置为开发时,此服务才可用. + +### Create/Edit MockCI service[](#createedit-mockci-service "Permalink") + +为项目设置 MockCI 服务. + +``` +PUT /projects/:id/services/mock-ci +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `mock_service_url` | string | true | `http://localhost:4004` | + +### Delete MockCI service[](#delete-mockci-service "Permalink") + +删除项目的 MockCI 服务. + +``` +DELETE /projects/:id/services/mock-ci +``` + +### Get MockCI service settings[](#get-mockci-service-settings "Permalink") + +获取项目的 MockCI 服务设置. + +``` +GET /projects/:id/services/mock-ci +``` + +## YouTrack[](#youtrack "Permalink") + +YouTrack 问题追踪器 + +### Create/Edit YouTrack service[](#createedit-youtrack-service "Permalink") + +为项目设置 YouTrack 服务. + +``` +PUT /projects/:id/services/youtrack +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --- | --- | --- | --- | +| `issues_url` | string | true | 发行网址 | +| `project_url` | string | true | 项目网址 | +| `description` | string | false | Description | +| `push_events` | boolean | false | 启用推送事件通知 | + +### Delete YouTrack Service[](#delete-youtrack-service "Permalink") + +删除项目的 YouTrack 服务. + +``` +DELETE /projects/:id/services/youtrack +``` + +### Get YouTrack Service Settings[](#get-youtrack-service-settings "Permalink") + +获取项目的 YouTrack 服务设置. + +``` +GET /projects/:id/services/youtrack +``` \ No newline at end of file diff --git a/docs/368.md b/docs/368.md new file mode 100644 index 0000000000000000000000000000000000000000..91bfc325f748e319f26a6a54c0f4507ef721ed62 --- /dev/null +++ b/docs/368.md @@ -0,0 +1,254 @@ +# Application settings API + +> 原文:[https://docs.gitlab.com/ee/api/settings.html](https://docs.gitlab.com/ee/api/settings.html) + +* [Get current application settings](#get-current-application-settings) +* [Change application settings](#change-application-settings) +* [List of settings that can be accessed via API calls](#list-of-settings-that-can-be-accessed-via-api-calls) + +# Application settings API[](#application-settings-api-core-only "Permalink") + +这些 API 调用使您可以阅读和修改`/admin/application_settings/general`显示的 GitLab 实例[应用程序设置](#list-of-settings-that-can-be-accessed-via-api-calls) . 您必须是管理员才能执行此操作. + +## Get current application settings[](#get-current-application-settings "Permalink") + +列出 GitLab 实例的当前[应用程序设置](#list-of-settings-that-can-be-accessed-via-api-calls) . + +``` +GET /application/settings +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/application/settings" +``` + +响应示例: + +``` +{ "default_projects_limit" : 100000, "signup_enabled" : true, "id" : 1, "default_branch_protection" : 2, "restricted_visibility_levels" : [], "password_authentication_enabled_for_web" : true, "after_sign_out_path" : null, "max_attachment_size" : 10, "max_import_size": 50, "user_oauth_applications" : true, "updated_at" : "2016-01-04T15:44:55.176Z", "session_expire_delay" : 10080, "home_page_url" : null, "default_snippet_visibility" : "private", "outbound_local_requests_whitelist": [], "domain_whitelist" : [], "domain_blacklist_enabled" : false, "domain_blacklist" : [], "created_at" : "2016-01-04T15:44:55.176Z", "default_ci_config_path" : null, "default_project_visibility" : "private", "default_group_visibility" : "private", "gravatar_enabled" : true, "sign_in_text" : null, "container_expiration_policies_enable_historic_entries": true, "container_registry_token_expire_delay": 5, "repository_storages_weighted": {"default": 100}, "plantuml_enabled": false, "plantuml_url": null, "terminal_max_session_time": 0, "polling_interval_multiplier": 1.0, "rsa_key_restriction": 0, "dsa_key_restriction": 0, "ecdsa_key_restriction": 0, "ed25519_key_restriction": 0, "first_day_of_week": 0, "enforce_terms": true, "terms": "Hello world!", "performance_bar_allowed_group_id": 42, "instance_statistics_visibility_private": false, "user_show_add_ssh_key_message": true, "local_markdown_version": 0, "allow_local_requests_from_hooks_and_services": true, "allow_local_requests_from_web_hooks_and_services": true, "allow_local_requests_from_system_hooks": false, "asset_proxy_enabled": true, "asset_proxy_url": "https://assets.example.com", "asset_proxy_whitelist": ["example.com", "*.example.com", "your-instance.com"], "npm_package_requests_forwarding": true, "snippet_size_limit": 52428800, "issues_create_limit": 300, "raw_blob_request_limit": 300, "wiki_page_max_content_bytes": 52428800 } +``` + +在 GitLab 用户[高级版或旗舰](https://about.gitlab.com/pricing/)也可以看到`file_template_project_id` , `deletion_adjourned_period` ,或`geo_node_allowed_ips`参数: + +``` +{ "id" : 1, "signup_enabled" : true, "file_template_project_id": 1, "geo_node_allowed_ips": "0.0.0.0/0, ::/0", "deletion_adjourned_period": 7, ... } +``` + +## Change application settings[](#change-application-settings "Permalink") + +使用 API​​调用来修改 GitLab 实例[应用程序设置](#list-of-settings-that-can-be-accessed-via-api-calls) . + +``` +PUT /application/settings +``` + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/application/settings?signup_enabled=false&default_project_visibility=internal" +``` + +响应示例: + +``` +{ "id": 1, "default_projects_limit": 100000, "signup_enabled": false, "password_authentication_enabled_for_web": true, "gravatar_enabled": true, "sign_in_text": "", "created_at": "2015-06-12T15:51:55.432Z", "updated_at": "2015-06-30T13:22:42.210Z", "home_page_url": "", "default_branch_protection": 2, "restricted_visibility_levels": [], "max_attachment_size": 10, "max_import_size": 50, "session_expire_delay": 10080, "default_ci_config_path" : null, "default_project_visibility": "internal", "default_snippet_visibility": "private", "default_group_visibility": "private", "outbound_local_requests_whitelist": [], "domain_whitelist": [], "domain_blacklist_enabled" : false, "domain_blacklist" : [], "external_authorization_service_enabled": true, "external_authorization_service_url": "https://authorize.me", "external_authorization_service_default_label": "default", "external_authorization_service_timeout": 0.5, "user_oauth_applications": true, "after_sign_out_path": "", "container_registry_token_expire_delay": 5, "repository_storages": ["default"], "plantuml_enabled": false, "plantuml_url": null, "terminal_max_session_time": 0, "polling_interval_multiplier": 1.0, "rsa_key_restriction": 0, "dsa_key_restriction": 0, "ecdsa_key_restriction": 0, "ed25519_key_restriction": 0, "first_day_of_week": 0, "enforce_terms": true, "terms": "Hello world!", "performance_bar_allowed_group_id": 42, "instance_statistics_visibility_private": false, "user_show_add_ssh_key_message": true, "file_template_project_id": 1, "local_markdown_version": 0, "asset_proxy_enabled": true, "asset_proxy_url": "https://assets.example.com", "asset_proxy_whitelist": ["example.com", "*.example.com", "your-instance.com"], "geo_node_allowed_ips": "0.0.0.0/0, ::/0", "allow_local_requests_from_hooks_and_services": true, "allow_local_requests_from_web_hooks_and_services": true, "allow_local_requests_from_system_hooks": false, "npm_package_requests_forwarding": true, "snippet_size_limit": 52428800, "issues_create_limit": 300, "raw_blob_request_limit": 300, "wiki_page_max_content_bytes": 52428800 } +``` + +使用 GitLab [Premium 或 Ultimate 的](https://about.gitlab.com/pricing/)用户可能还会看到以下参数: + +* `file_template_project_id` +* `geo_node_allowed_ips` +* `geo_status_timeout` +* `deletion_adjourned_period` + +响应示例: + +``` + "file_template_project_id": 1, "geo_node_allowed_ips": "0.0.0.0/0, ::/0" +``` + +## List of settings that can be accessed via API calls[](#list-of-settings-that-can-be-accessed-via-api-calls "Permalink") + +通常,所有设置都是可选的. 但是,如果启用了某些设置,则需要设置其他设置才能正常运行. 这些要求在相关设置的说明中列出. + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `admin_notification_email` | string | no | 如果设置了滥用报告,它将发送到该地址. 滥用报告始终在管理区域中可用. | +| `after_sign_out_path` | string | no | 注销后将用户重定向到的位置. | +| `after_sign_up_text` | string | no | 注册后向用户显示的文字 | +| `akismet_api_key` | string | 要求: `akismet_enabled` | Akismet 垃圾邮件防护的 API 密钥. | +| `akismet_enabled` | boolean | no | ( **如果启用,则要求:** `akismet_api_key` )启用或禁用 Akismet 垃圾邮件防护. | +| `allow_group_owners_to_manage_ldap` | boolean | no | 设置为`true`以允许组所有者管理 LDAP | +| `allow_local_requests_from_hooks_and_services` | boolean | no | (不建议使用:改用`allow_local_requests_from_web_hooks_and_services` )允许从挂钩和服务到本地网络的请求. | +| `allow_local_requests_from_system_hooks` | boolean | no | 允许从系统挂钩向本地网络发出请求. | +| `allow_local_requests_from_web_hooks_and_services` | boolean | no | 允许从 Web 挂钩和服务到本地网络的请求. | +| `archive_builds_in_human_readable` | string | no | 设置将作业视为过期和过期的持续时间. 一旦超过该时间,作业将被存档,并且不再能够重试. 将其设为空以永不过期作业. 它必须不少于 1 天,例如: `15 days` , `1 month` , `2 years` . | +| `asset_proxy_enabled` | boolean | no | ( **如果启用,则要求:** `asset_proxy_url` )启用资产代理. 需要重启 GitLab 才能应用更改. | +| `asset_proxy_secret_key` | string | no | 与资产代理服务器共享的机密. 需要重启 GitLab 才能应用更改. | +| `asset_proxy_url` | string | no | 资产代理服务器的 URL. 需要重启 GitLab 才能应用更改. | +| `asset_proxy_whitelist` | 字符串或字符串数​​组 | no | 与这些域匹配的资产将不会被代理. 允许使用通配符. 您的 GitLab 安装网址会自动列入白名单. 需要重启 GitLab 才能应用更改. | +| `authorized_keys_enabled` | boolean | no | 默认情况下,我们无需经过其他配置即可写入`authorized_keys`文件以通过 SSH 支持 Git. 可以对 GitLab 进行优化,以通过数据库文件对 SSH 密钥进行身份验证. 仅当您已将 OpenSSH 服务器配置为使用 AuthorizedKeysCommand 时,才禁用此功能. | +| `auto_devops_domain` | string | no | 指定默认情况下用于每个项目的 Auto Review Apps 和 Auto Deploy 阶段的域. | +| `auto_devops_enabled` | boolean | no | 默认情况下,为项目启用 Auto DevOps. 它将基于预定义的 CI / CD 配置自动构建,测试和部署应用程序. | +| `check_namespace_plan` | boolean | no | 如果项目名称空间的计划包括该功能或项目为公共项目,则启用此选项将仅使许可的 EE 功能可用于项目. | +| `commit_email_hostname` | string | no | 自定义主机名(用于私人提交电子邮件). | +| `container_registry_token_expire_delay` | integer | no | 容器注册表令牌持续时间(以分钟为单位). | +| `default_artifacts_expire_in` | string | no | 设置每个作业的工件的默认到期时间. | +| `default_branch_protection` | integer | no | 确定开发者是否可以掌握. 可以采用: `0` *(不受保护,开发人员和维护人员都可以推送新的提交,强制推送或删除分支)* , `1` *(部分受保护的开发人员和维护人员可以推送新的提交,但是不能强制推送或删除分支)*或`2` *(受完全保护的开发人员无法推送新的提交,但维护者可以;没有人可以强制推送或删除分支)*作为参数. 默认值为`2` . | +| `default_ci_config_path` | string | no | 新项目的默认 CI 配置路径(如果未设置, `.gitlab-ci.yml` ). | +| `default_group_visibility` | string | no | 新群组获得的可见度级别. 可以将`private` , `internal`和`public`作为参数. 默认值为`private` . | +| `default_project_creation` | integer | no | 默认的项目创建保护. 可以采用: `0` *(无人)* , `1` *(维护者)*或`2` *(开发人员+维护者)* | +| `default_projects_limit` | integer | no | 每个用户的项目限制. 默认值为`100000` . | +| `default_project_visibility` | string | no | 新项目获得什么可见度级别. 可以将`private` , `internal`和`public`作为参数. 默认值为`private` . | +| `default_snippet_visibility` | string | no | 新摘要的可见性级别是多少. 可以将`private` , `internal`和`public`作为参数. 默认值为`private` . | +| `diff_max_patch_bytes` | integer | no | 最大差异补丁大小(字节). | +| `disabled_oauth_sign_in_sources` | 字符串数组 | no | 禁用的 OAuth 登录源. | +| `dns_rebinding_protection_enabled` | boolean | no | 实施 DNS 重新绑定攻击保护. | +| `domain_blacklist` | 字符串数组 | no | 电子邮件地址与这些域匹配的用户将无法注册. 允许使用通配符. 对多个条目使用单独的行. 例如: `domain.com` , `*.domain.com` . | +| `domain_blacklist_enabled` | boolean | no | ( **如果启用,则要求:** `domain_blacklist` )允许阻止来自特定域的电子邮件的注册. | +| `domain_whitelist` | 字符串数组 | no | 强迫人们仅使用公司电子邮件进行注册. 默认值为`null` ,表示没有限制. | +| `dsa_key_restriction` | integer | no | 上载 DSA 密钥的最小允许位长. 默认值为`0` (无限制). `-1`禁用 DSA 密钥. | +| `ecdsa_key_restriction` | integer | no | 上载的 ECDSA 密钥的最小允许曲线大小(以位为单位). 默认值为`0` (无限制). `-1`禁用 ECDSA 密钥. | +| `ed25519_key_restriction` | integer | no | 上载的 ED25519 密钥的最小允许曲线大小(以位为单位). 默认值为`0` (无限制). `-1`禁用 ED25519 键. | +| `eks_integration_enabled` | boolean | no | 启用与 Amazon EKS 的集成 | +| `eks_account_id` | string | no | 亚马逊帐号 | +| `eks_access_key_id` | string | no | AWS IAM 访问密钥 ID | +| `eks_secret_access_key` | string | no | AWS IAM 秘密访问密钥 | +| `elasticsearch_aws_access_key` | string | no | AWS IAM 访问密钥 | +| `elasticsearch_aws` | boolean | no | 启用使用 AWS 托管的 Elasticsearch | +| `elasticsearch_aws_region` | string | no | 配置 Elasticsearch 域的 AWS 区域 | +| `elasticsearch_aws_secret_access_key` | string | no | AWS IAM 秘密访问密钥 | +| `elasticsearch_indexed_field_length_limit` | integer | no | Elasticsearch 将索引的文本字段的最大大小. 0 值表示没有限制. 这不适用于存储库和 Wiki 索引. | +| `elasticsearch_indexing` | boolean | no | 启用 Elasticsearch 索引 | +| `elasticsearch_limit_indexing` | boolean | no | 限制 Elasticsearch 索引某些命名空间和项目 | +| `elasticsearch_max_bulk_concurrency` | integer | no | 每个索引操作的 Elasticsearch 批量请求的最大并发性. 这仅适用于存储库索引操作. | +| `elasticsearch_max_bulk_size_mb` | integer | no | Maximum size of Elasticsearch bulk indexing requests in MB. This only applies to repository indexing operations. | +| `elasticsearch_namespace_ids` | 整数数组 | no | 如果启用 elasticsearch_limit_indexing, `elasticsearch_limit_indexing`通过 Elasticsearch 进行索引的名称空间. | +| `elasticsearch_project_ids` | 整数数组 | no | 如果启用了 elasticsearch_limit_indexing, `elasticsearch_limit_indexing`通过 Elasticsearch 进行索引的项目. | +| `elasticsearch_search` | boolean | no | 启用 Elasticsearch 搜索 | +| `elasticsearch_url` | string | no | 用于连接到 Elasticsearch 的 URL. 使用逗号分隔的列表来支持集群(例如, `http://localhost:9200, http://localhost:9201"` ).如果您的 Elasticsearch 实例受密码保护,请在 URL 中传递`username:password` (例如, `http://:@:9200/` ). | +| `email_additional_text` | string | no | 出于法律/审核/合规原因,在每封电子邮件的底部添加了其他文本 | +| `email_author_in_body` | boolean | no | 某些电子邮件服务器不支持覆盖电子邮件发件人名称. 启用此选项可在邮件正文中包含问题作者的名称,合并请求或评论. | +| `enabled_git_access_protocol` | string | no | 已启用 Git 访问协议. 允许的值为: `ssh` , `http`和`nil`以允许两种协议. | +| `enforce_terms` | boolean | no | ( **如果启用,则要求:** `terms` )对所有用户强制应用 ToS. | +| `external_auth_client_cert` | string | no | ( **如果启用,则要求:** `external_auth_client_key` )用于与外部授权服务进行身份验证的证书 | +| `external_auth_client_key_pass` | string | no | 与外部服务进行身份验证时用于私钥的密码,存储时会加密 | +| `external_auth_client_key` | string | 要求: `external_auth_client_cert` | 外部授权服务需要身份验证时证书的私钥,存储时将被加密 | +| `external_authorization_service_default_label` | string | 所需者: `external_authorization_service_enabled` | 请求授权时使用的默认分类标签,并且在项目上未指定任何分类标签 | +| `external_authorization_service_enabled` | boolean | no | ( **如果启用,则要求:** `external_authorization_service_default_label` , `external_authorization_service_timeout`和`external_authorization_service_url` )启用使用外部授权服务访问项目 | +| `external_authorization_service_timeout` | float | 所需者: `external_authorization_service_enabled` | 授权请求终止后的超时时间(以秒为单位). 当请求超时时,将拒绝用户访问. (最小值:0.001,最大值:10,步长:0.001) | +| `external_authorization_service_url` | string | 所需者: `external_authorization_service_enabled` | 授权请求将定向到的 URL | +| `file_template_project_id` | integer | no | 从中加载自定义文件模板的项目的 ID | +| `first_day_of_week` | integer | no | 日历视图和日期选择器的星期几开始. 有效值为星期日( `0` (默认),星期一( `1` )和星期六( `6` . | +| `geo_node_allowed_ips` | string | yes | 允许的辅助节点的 IP 和 CIDR 的逗号分隔列表. 例如`1.1.1.1, 2.2.2.0/24` . | +| `geo_status_timeout` | integer | no | 请求获取辅助节点状态的超时时间(秒). | +| `gitaly_timeout_default` | integer | no | 默认 Gitaly 超时(以秒为单位). 对于 Git 提取/推送操作或 Sidekiq 作业,不会强制使用此超时. 设置为`0`以禁用超时. | +| `gitaly_timeout_fast` | integer | no | 快速运行超时,以秒为单位. 预计某些 Gitaly 行动会很快. 如果它们超过此阈值,则存储碎片可能存在问题,并且"快速失败"可以帮助维护 GitLab 实例的稳定性. 设置为`0`以禁用超时. | +| `gitaly_timeout_medium` | integer | no | Gitaly 中度超时,以秒为单位. 这应该是快速超时和默认超时之间的一个值. 设置为`0`以禁用超时. | +| `grafana_enabled` | boolean | no | 启用 Grafana. | +| `grafana_url` | string | no | Grafana URL. | +| `gravatar_enabled` | boolean | no | 启用 Gravatar. | +| `hashed_storage_enabled` | boolean | no | 使用哈希存储路径创建新项目:启用基于哈希的不可变路径和存储库名称,以将存储库存储在磁盘上. 这样可以避免在项目 URL 更改时必须移动或重命名存储库,并可以提高磁盘 I / O 性能. (从 13.0 开始始终启用,在 14.0 中将删除配置) | +| `help_page_hide_commercial_content` | boolean | no | 隐藏帮助中与营销相关的条目. | +| `help_page_support_url` | string | no | 帮助页面和帮助下拉列表的备用支持 URL. | +| `help_page_text` | string | no | 帮助页面上显示的自定义文本. | +| `help_text` | string | no | GitLab 服务器管理员信息 | +| `hide_third_party_offers` | boolean | no | 不要在 GitLab 中显示来自第三方的报价. | +| `home_page_url` | string | no | 未登录时重定向到该 URL. | +| `housekeeping_bitmaps_enabled` | boolean | 要求: `housekeeping_enabled` | 启用 Git 包文件位图创建. | +| `housekeeping_enabled` | boolean | no | ( **如果启用,则要求:** `housekeeping_bitmaps_enabled` , `housekeeping_full_repack_period` , `housekeeping_gc_period`和`housekeeping_incremental_repack_period` ).启用或禁用 Git 整理. | +| `housekeeping_full_repack_period` | integer | 要求: `housekeeping_enabled` | Git 推送的次数,之后运行增量`git repack` . | +| `housekeeping_gc_period` | integer | 要求: `housekeeping_enabled` | 运行`git gc`之后的 Git 推送次数. | +| `housekeeping_incremental_repack_period` | integer | 要求: `housekeeping_enabled` | Git 推送的次数,之后运行增量`git repack` . | +| `html_emails_enabled` | boolean | no | 启用 HTML 电子邮件. | +| `import_sources` | 字符串数组 | no | 允许从中导入项目的来源,可能的值包括: `github` , `bitbucket` , `bitbucket_server` , `gitlab` , `google_code` , `fogbugz` , `git` , `gitlab_project` , `gitea` , `manifest`和`phabricator` . | +| `instance_statistics_visibility_private` | boolean | no | 设置为`true`实例统计信息仅对管理员可用. | +| `local_markdown_version` | integer | no | 当任何缓存的 Markdown 无效时,请增加此值. | +| `max_artifacts_size` | integer | no | 最大工件大小(MB) | +| `max_attachment_size` | integer | no | 限制附件大小(MB) | +| `max_import_size` | integer | no | 最大导入大小(MB). 0 代表无限. 默认值= 50 | +| `max_pages_size` | integer | no | 页面存储库的最大大小(MB) | +| `max_personal_access_token_lifetime` | integer | no | 个人访问令牌的最大允许寿命(天) | +| `metrics_method_call_threshold` | integer | no | 仅当方法调用花费的时间超过给定的毫秒数时,才会跟踪该方法调用. | +| `mirror_available` | boolean | no | 允许存储库镜像由项目维护者配置. 如果禁用,则只有管理员可以配置存储库镜像. | +| `mirror_capacity_threshold` | integer | no | 抢先计划更多镜像之前需要提供的最小容量 | +| `mirror_max_capacity` | integer | no | 可以同时同步的最大镜像数. | +| `mirror_max_delay` | integer | no | 计划进行同步时,镜像可以具有的两次更新之间的最长时间(以分钟为单位). | +| `npm_package_requests_forwarding` | boolean | no | 在 GitLab NPM 注册表中找不到软件包时,请使用 npmjs.org 作为默认的远程存储库 | +| `maintenance_mode` | boolean | no | 实例处于维护模式时,非管理员用户可以使用只读访问权限登录并发出只读 API 请求 | +| `maintenance_mode_message` | string | no | 实例处于维护模式时显示的消息 | +| `outbound_local_requests_whitelist` | 字符串数组 | no | 定义在禁用对钩子和服务的本地请求时允许对本地请求的信任域或 ip 地址的列表. | +| `pages_domain_verification_enabled` | boolean | no | 要求用户证明自定义域的所有权. 域验证是公共 GitLab 站点必不可少的安全措施. 在启用域之前,要求用户证明他们控制着域. | +| `password_authentication_enabled_for_git` | boolean | no | 通过 GitLab 帐户密码启用基于 HTTP(S)的 Git 身份验证. 默认值为`true` . | +| `password_authentication_enabled_for_web` | boolean | no | 通过 GitLab 帐户密码启用 Web 界面的身份验证. 默认值为`true` . | +| `performance_bar_allowed_group_id` | string | no | (不建议使用:改用`performance_bar_allowed_group_path` )允许切换性能栏的组的路径. | +| `performance_bar_allowed_group_path` | string | no | Path of the group that is allowed to toggle the performance bar. | +| `performance_bar_enabled` | boolean | no | (不建议使用:传递`performance_bar_allowed_group_path: nil`代替)允许启用性能栏. | +| `plantuml_enabled` | boolean | no | ( **如果启用,则要求:** `plantuml_url` )启用 PlantUML 集成. 默认值为`false` . | +| `plantuml_url` | string | 要求: `plantuml_enabled` | 用于集成的 PlantUML 实例 URL. | +| `polling_interval_multiplier` | decimal | no | Interval multiplier used by endpoints that perform polling. Set to `0` to disable polling. | +| `deletion_adjourned_period` | integer | no | 删除标记为删除的项目或组之前要等待的天数. 值必须介于 0 到 90 之间. | +| `project_export_enabled` | boolean | no | 启用项目导出. | +| `prometheus_metrics_enabled` | boolean | no | 启用 Prometheus 指标. | +| `protected_ci_variables` | boolean | no | 默认情况下,环境变量受保护. | +| `pseudonymizer_enabled` | boolean | no | 启用后,GitLab 将运行一个后台作业,该作业将生成 GitLab 数据库的假名化 CSV,并将其上传到您配置的对象存储目录中. | +| `push_event_hooks_limit` | integer | no | 一次按下更改(分支或标签)的次数,以确定是否将触发 Webhook 和服务. 如果超过该值,则不会提交 Webhooks 和服务. | +| `push_event_activities_limit` | integer | no | 一次推送中更改(分支或标签)的数量,以确定将创建单个推送事件还是批量推送事件. [如果批量推送事件](../user/admin_area/settings/push_event_activities_limit.html)超过该值, [则会创建](../user/admin_area/settings/push_event_activities_limit.html)该[事件](../user/admin_area/settings/push_event_activities_limit.html) . | +| `recaptcha_enabled` | boolean | no | ( **如果启用,则要求:** `recaptcha_private_key`和`recaptcha_site_key` )启用 reCAPTCHA. | +| `recaptcha_private_key` | string | 要求: `recaptcha_enabled` | reCAPTCHA 的私钥. | +| `recaptcha_site_key` | string | 要求: `recaptcha_enabled` | reCAPTCHA 的站点密钥. | +| `receive_max_input_size` | integer | no | 最大推送大小(MB). | +| `repository_checks_enabled` | boolean | no | GitLab 将在所有项目和 Wiki 存储库中定期运行`git fsck` ,以查找静默磁盘损坏问题. | +| `repository_size_limit` | integer | no | 每个存储库的大小限制(MB) | +| `repository_storages` | 字符串数组 | no | (GitLab 13.0 和更早版本)已启用的存储路径的名称列表,取自`gitlab.yml` . 在这些商店之一中创建新项目,这些项目是随机选择的. | +| `repository_storages_weighted` | 字符串哈希到整数 | no | (GitLab 13.1 和更高版本)从`gitlab.yml`到权重的名称的哈希值. 在这些存储库之一中创建新项目,并通过加权随机选择进行选择. | +| `require_two_factor_authentication` | boolean | no | ( **如果启用,则要求:** `two_factor_grace_period` )要求所有用户设置两因素身份验证. | +| `restricted_visibility_levels` | 字符串数组 | no | 非管理员用户不能将所选级别用于组,项目或摘要. 可以将`private` , `internal`和`public`作为参数. 默认值为`null` ,表示没有限制. | +| `rsa_key_restriction` | integer | no | 上载 RSA 密钥的最小允许比特长度. 默认值为`0` (无限制). `-1`禁用 RSA 密钥. | +| `send_user_confirmation_email` | boolean | no | 在注册时发送确认电子邮件. | +| `session_expire_delay` | integer | no | 会话持续时间(以分钟为单位). 需要重启 GitLab 才能应用更改 | +| `shared_runners_enabled` | boolean | no | ( **如果启用,则要求:** `shared_runners_text`和`shared_runners_minutes` )为新项目启用共享运行器. | +| `shared_runners_minutes` | integer | 所需者: `shared_runners_enabled` | 设置组每月可以在共享运行者上使用的最大管道分钟数. | +| `shared_runners_text` | string | 所需者: `shared_runners_enabled` | 共享跑步者文字. | +| `signin_enabled` | string | no | (不建议使用:改为使用`password_authentication_enabled_for_web` )该标志指示是否为 Web 界面启用了密码认证. | +| `sign_in_text` | string | no | 登录页面上的文本. | +| `signup_enabled` | boolean | no | 启用注册. 默认值为`true` . | +| `slack_app_enabled` | boolean | no | ( **如果启用,则要求:** `slack_app_id` , `slack_app_secret`和`slack_app_secret` )启用 Slack 应用. | +| `slack_app_id` | string | 所需者: `slack_app_enabled` | The app ID of the Slack-app. | +| `slack_app_secret` | string | 所需者: `slack_app_enabled` | Slack-app 的应用程序秘诀. | +| `slack_app_verification_token` | string | 所需者: `slack_app_enabled` | Slack-app 的验证令牌. | +| `snowplow_collector_hostname` | string | 所需者: `snowplow_enabled` | 扫雪机收集器主机名. (例如, `snowplow.trx.gitlab.net` ) | +| `snowplow_cookie_domain` | string | no | Snowplow cookie 域. (例如, `.gitlab.com` ) | +| `snowplow_enabled` | boolean | no | 启用扫雪机跟踪. | +| `snowplow_app_id` | string | no | Snowplow 站点名称/应用程序 ID. (例如`gitlab` ) | +| `snowplow_iglu_registry_url` | string | no | Snowplow 基本 Iglu Schema 注册表 URL,用于自定义上下文和自我描述事件' | +| `sourcegraph_enabled` | boolean | no | 启用 S​​ourcegraph 集成. 默认值为`false` . **如果启用,则需要** `sourcegraph_url` . | +| `sourcegraph_url` | string | 要求: `sourcegraph_enabled` | 用于集成的 Sourcegraph 实例 URL. | +| `sourcegraph_public_only` | boolean | no | 阻止将 Sourcegraph 加载到私有和内部项目中. 默认值为`true` . | +| `spam_check_endpoint_enabled` | boolean | no | 通过外部 API 端点启用垃圾邮件检查. 默认值为`false` . | +| `spam_check_endpoint_url` | string | no | 外部垃圾邮件检查服务端点的 URL. | +| `terminal_max_session_time` | integer | no | Web 终端 websocket 连接的最长时间(以秒为单位). 设置为`0`表示无限时间. | +| `terms` | text | 要求: `enforce_terms` | ( **要求:** `enforce_terms` )ToS 的降价内容. | +| `throttle_authenticated_api_enabled` | boolean | no | ( **如果启用,则要求:** `throttle_authenticated_api_period_in_seconds`和`throttle_authenticated_api_requests_per_period` )启用经过身份验证的 API 请求速率限制. 帮助减少请求量(例如,来自爬虫或恶意机器人的请求量). | +| `throttle_authenticated_api_period_in_seconds` | integer | 所需者: `throttle_authenticated_api_enabled` _ 已验证`throttle_authenticated_api_enabled` | 限速时间(秒). | +| `throttle_authenticated_api_requests_per_period` | integer | 所需者: `throttle_authenticated_api_enabled` _ 已验证`throttle_authenticated_api_enabled` | 每个用户每个时段的最大请求数. | +| `throttle_authenticated_web_enabled` | boolean | no | ( **如果启用,则要求:** `throttle_authenticated_web_period_in_seconds`和`throttle_authenticated_web_requests_per_period` )启用经过身份验证的 Web 请求速率限制. 帮助减少请求量(例如,来自爬虫或恶意机器人的请求量). | +| `throttle_authenticated_web_period_in_seconds` | integer | 所需者: `throttle_authenticated_web_enabled` _ 已验证网络 _ 已`throttle_authenticated_web_enabled` | 限速时间(秒). | +| `throttle_authenticated_web_requests_per_period` | integer | 所需者: `throttle_authenticated_web_enabled` _ 已验证网络 _ 已`throttle_authenticated_web_enabled` | 每个用户每个时段的最大请求数. | +| `throttle_unauthenticated_enabled` | boolean | no | ( **如果启用,则要求:** `throttle_unauthenticated_period_in_seconds`和`throttle_unauthenticated_requests_per_period` )启用未认证的请求速率限制. 帮助减少请求量(例如,来自爬虫或恶意机器人的请求量). | +| `throttle_unauthenticated_period_in_seconds` | integer | 所需者: `throttle_unauthenticated_enabled` _ 未`throttle_unauthenticated_enabled`的 _ `throttle_unauthenticated_enabled` | 限速时间(秒). | +| `throttle_unauthenticated_requests_per_period` | integer | required by: `throttle_unauthenticated_enabled` | 每个 IP 的每个周期的最大请求数. | +| `time_tracking_limit_to_hours` | boolean | no | 将时间跟踪单位的显示限制为小时. 默认值为`false` . | +| `two_factor_grace_period` | integer | 要求者: `require_two_factor_authentication` | 允许用户跳过两因素身份验证的强制配置的时间(以小时为单位). | +| `unique_ips_limit_enabled` | boolean | no | ( **如果启用,则要求:** `unique_ips_limit_per_user`和`unique_ips_limit_time_window` )限制从多个`unique_ips_limit_time_window`登录. | +| `unique_ips_limit_per_user` | integer | 所需者: `unique_ips_limit_enabled` | 每个用户的最大 IP 数. | +| `unique_ips_limit_time_window` | integer | 所需者: `unique_ips_limit_enabled` | IP 将计入限制多少秒. | +| `usage_ping_enabled` | boolean | no | GitLab 每周都会向 GitLab,Inc.报告许可证使用情况. | +| `user_default_external` | boolean | no | 默认情况下,新注册的用户将是外部用户. | +| `user_default_internal_regex` | string | no | 指定电子邮件地址正则表达式模式以标识默认的内部用户. | +| `user_oauth_applications` | boolean | no | 允许用户注册任何应用程序以将 GitLab 用作 OAuth 提供程序. | +| `user_show_add_ssh_key_message` | boolean | no | 设置为`false`时,向没有上载 SSH 密钥的用户显示"您将无法通过 SSH 推送或推送项目代码"警告. | +| `version_check_enabled` | boolean | no | 让 GitLab 在更新可用时通知您. | +| `web_ide_clientside_preview_enabled` | boolean | no | 实时预览(允许使用 CodeSandbox 实时预览在 Web IDE 中对 JavaScript 项目进行实时预览). | +| `snippet_size_limit` | integer | no | 摘录内容的最大大小(以**字节为单位)** . 默认值:52428800 字节(50MB). | +| `issues_create_limit` | integer | no | 每位用户每分钟每分钟最多可创建问题的请求数. 默认值:300.要禁用限制,请将其设置为 0. | +| `raw_blob_request_limit` | integer | no | 每条原始路径每分钟的最大请求数. 默认值:300.要禁用限制,请将其设置为 0. | +| `wiki_page_max_content_bytes` | integer | no | Wiki 页面的最大内容大小(以**字节为单位)** . 默认值:52428800 字节(50MB). | \ No newline at end of file diff --git a/docs/369.md b/docs/369.md new file mode 100644 index 0000000000000000000000000000000000000000..d393a7c7f38e681c6eb176f6193288795d245f8b --- /dev/null +++ b/docs/369.md @@ -0,0 +1,86 @@ +# Sidekiq Metrics API + +> 原文:[https://docs.gitlab.com/ee/api/sidekiq_metrics.html](https://docs.gitlab.com/ee/api/sidekiq_metrics.html) + +* [Get the current Queue Metrics](#get-the-current-queue-metrics) +* [Get the current Process Metrics](#get-the-current-process-metrics) +* [Get the current Job Statistics](#get-the-current-job-statistics) +* [Get a compound response of all the previously mentioned metrics](#get-a-compound-response-of-all-the-previously-mentioned-metrics) + +# Sidekiq Metrics API[](#sidekiq-metrics-api "Permalink") + +> **注意:**此端点仅在 GitLab 8.9 及更高版本上可用. + +通过此 API 端点,您可以检索有关 Sidekiq 当前状态,其作业,队列和进程的一些信息. + +## Get the current Queue Metrics[](#get-the-current-queue-metrics "Permalink") + +列出有关所有已注册队列,其积压和延迟的信息. + +``` +GET /sidekiq/queue_metrics +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/sidekiq/queue_metrics" +``` + +响应示例: + +``` +{ "queues": { "default": { "backlog": 0, "latency": 0 } } } +``` + +## Get the current Process Metrics[](#get-the-current-process-metrics "Permalink") + +列出有关所有注册来处理您的队列的 Sidekiq 工作者的信息. + +``` +GET /sidekiq/process_metrics +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/sidekiq/process_metrics" +``` + +响应示例: + +``` +{ "processes": [ { "hostname": "gitlab.example.com", "pid": 5649, "tag": "gitlab", "started_at": "2016-06-14T10:45:07.159-05:00", "queues": [ "post_receive", "mailers", "archive_repo", "system_hook", "project_web_hook", "gitlab_shell", "incoming_email", "runner", "common", "default" ], "labels": [], "concurrency": 25, "busy": 0 } ] } +``` + +## Get the current Job Statistics[](#get-the-current-job-statistics "Permalink") + +列出有关 Sidekiq 执行的作业的信息. + +``` +GET /sidekiq/job_stats +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/sidekiq/job_stats" +``` + +响应示例: + +``` +{ "jobs": { "processed": 2, "failed": 0, "enqueued": 0, "dead": 0 } } +``` + +## Get a compound response of all the previously mentioned metrics[](#get-a-compound-response-of-all-the-previously-mentioned-metrics "Permalink") + +列出有关 Sidekiq 的所有当前可用信息. + +``` +GET /sidekiq/compound_metrics +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/sidekiq/compound_metrics" +``` + +响应示例: + +``` +{ "queues": { "default": { "backlog": 0, "latency": 0 } }, "processes": [ { "hostname": "gitlab.example.com", "pid": 5649, "tag": "gitlab", "started_at": "2016-06-14T10:45:07.159-05:00", "queues": [ "post_receive", "mailers", "archive_repo", "system_hook", "project_web_hook", "gitlab_shell", "incoming_email", "runner", "common", "default" ], "labels": [], "concurrency": 25, "busy": 0 } ], "jobs": { "processed": 2, "failed": 0, "enqueued": 0, "dead": 0 } } +``` \ No newline at end of file diff --git a/docs/370.md b/docs/370.md new file mode 100644 index 0000000000000000000000000000000000000000..a302d7f9df61a3e42c47f816599198276316487b --- /dev/null +++ b/docs/370.md @@ -0,0 +1,285 @@ +# Snippets API + +> 原文:[https://docs.gitlab.com/ee/api/snippets.html](https://docs.gitlab.com/ee/api/snippets.html) + +* [Snippet visibility level](#snippet-visibility-level) +* [List all snippets for a user](#list-all-snippets-for-a-user) +* [Get a single snippet](#get-a-single-snippet) +* [Single snippet contents](#single-snippet-contents) +* [Snippet repository file content](#snippet-repository-file-content) +* [Create new snippet](#create-new-snippet) +* [Update snippet](#update-snippet) +* [Delete snippet](#delete-snippet) +* [List all public snippets](#list-all-public-snippets) +* [Get user agent details](#get-user-agent-details) + +# Snippets API[](#snippets-api "Permalink") + +在 GitLab 8.15 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6373) . + +片段 API 在[片段上](../user/snippets.html)运行. + +## Snippet visibility level[](#snippet-visibility-level "Permalink") + +GitLab 中的代码段可以是私有的,内部的或公共的. 您可以使用代码段中的`visibility`字段进行设置. + +代码段可见性级别的有效值为: + +| Visibility | Description | +| --- | --- | +| `private` | 摘要仅对摘要创建者可见. | +| `internal` | 所有已登录用户都可以看到该代码段. | +| `public` | 无需任何身份验证即可访问代码段. | + +## List all snippets for a user[](#list-all-snippets-for-a-user "Permalink") + +获取当前用户的片段列表. + +``` +GET /snippets +``` + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets" +``` + +响应示例: + +``` +[ { "id": 42, "title": "Voluptatem iure ut qui aut et consequatur quaerat.", "file_name": "mclaughlin.rb", "description": null, "visibility": "internal", "author": { "id": 22, "name": "User 0", "username": "user0", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/52e4ce24a915fb7e51e1ad3b57f4b00a?s=80&d=identicon", "web_url": "http://example.com/user0" }, "updated_at": "2018-09-18T01:12:26.383Z", "created_at": "2018-09-18T01:12:26.383Z", "project_id": null, "web_url": "http://example.com/snippets/42", "raw_url": "http://example.com/snippets/42/raw" }, { "id": 41, "title": "Ut praesentium non et atque.", "file_name": "ondrickaemard.rb", "description": null, "visibility": "internal", "author": { "id": 22, "name": "User 0", "username": "user0", "state": "active", "avatar_url": "https://www.gravatar.com/avatar/52e4ce24a915fb7e51e1ad3b57f4b00a?s=80&d=identicon", "web_url": "http://example.com/user0" }, "updated_at": "2018-09-18T01:12:26.360Z", "created_at": "2018-09-18T01:12:26.360Z", "project_id": 1, "web_url": "http://example.com/gitlab-org/gitlab-test/snippets/41", "raw_url": "http://example.com/gitlab-org/gitlab-test/snippets/41/raw" } ] +``` + +## Get a single snippet[](#get-a-single-snippet "Permalink") + +取得一个摘要. + +``` +GET /snippets/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要检索的代码段的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets/1" +``` + +响应示例: + +``` +{ "id": 1, "title": "test", "file_name": "add.rb", "description": "Ruby test snippet", "visibility": "private", "author": { "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "created_at": "2012-05-23T08:00:58Z" }, "expires_at": null, "updated_at": "2012-06-28T10:52:04Z", "created_at": "2012-06-28T10:52:04Z", "project_id": null, "web_url": "http://example.com/snippets/1", "raw_url": "http://example.com/snippets/1/raw" } +``` + +## Single snippet contents[](#single-snippet-contents "Permalink") + +获取单个代码段的原始内容. + +``` +GET /snippets/:id/raw +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要检索的代码段的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets/1/raw" +``` + +响应示例: + +``` +Hello World snippet +``` + +## Snippet repository file content[](#snippet-repository-file-content "Permalink") + +以纯文本形式返回原始文件的内容. + +``` +GET /snippets/:id/files/:ref/:file_path/raw +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要检索的代码段 ID | +| `ref` | string | yes | 引用标签,分支或提交 | +| `file_path` | string | yes | 文件的 URL 编码路径 | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets/1/files/master/snippet%2Erb/raw" +``` + +响应示例: + +``` +Hello World snippet +``` + +## Create new snippet[](#create-new-snippet "Permalink") + +创建一个新的代码段. + +**注意:**用户必须具有创建新代码段的权限. + +``` +POST /snippets +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `title` | string | yes | 摘要的标题. | +| `file_name` | string | yes | 片段文件的名称. | +| `content` | string | yes | 摘要的内容. | +| `description` | string | no | 片段说明. | +| `visibility` | string | no | Snippet’s [visibility](#snippet-visibility-level). | + +请求示例: + +``` +curl --request POST \ + --data '{"title": "This is a snippet", "content": "Hello world", "description": "Hello World snippet", "file_name": "test.txt", "visibility": "internal" }' \ + --header 'Content-Type: application/json' \ + --header "PRIVATE-TOKEN: " \ + "https://gitlab.example.com/api/v4/snippets" +``` + +响应示例: + +``` +{ "id": 1, "title": "This is a snippet", "file_name": "test.txt", "description": "Hello World snippet", "visibility": "internal", "author": { "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "created_at": "2012-05-23T08:00:58Z" }, "expires_at": null, "updated_at": "2012-06-28T10:52:04Z", "created_at": "2012-06-28T10:52:04Z", "project_id": null, "web_url": "http://example.com/snippets/1", "raw_url": "http://example.com/snippets/1/raw" } +``` + +## Update snippet[](#update-snippet "Permalink") + +更新现有代码段. + +**注意:**用户必须具有更改现有代码段的权限. + +``` +PUT /snippets/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要更新的代码段 ID. | +| `title` | string | no | 摘要的标题. | +| `file_name` | string | no | 片段文件的名称. | +| `description` | string | no | 片段说明. | +| `content` | string | no | 摘要的内容. | +| `visibility` | string | no | Snippet’s [visibility](#snippet-visibility-level). | + +请求示例: + +``` +curl --request PUT \ + --data '{"title": "foo", "content": "bar"}' \ + --header 'Content-Type: application/json' \ + --header "PRIVATE-TOKEN: " \ + "https://gitlab.example.com/api/v4/snippets/1" +``` + +响应示例: + +``` +{ "id": 1, "title": "test", "file_name": "add.rb", "description": "description of snippet", "visibility": "internal", "author": { "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "created_at": "2012-05-23T08:00:58Z" }, "expires_at": null, "updated_at": "2012-06-28T10:52:04Z", "created_at": "2012-06-28T10:52:04Z", "project_id": null, "web_url": "http://example.com/snippets/1", "raw_url": "http://example.com/snippets/1/raw" } +``` + +## Delete snippet[](#delete-snippet "Permalink") + +删除现有的代码段. + +``` +DELETE /snippets/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 要删除的代码段的 ID. | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets/1" +``` + +以下是可能的返回码: + +| Code | Description | +| --- | --- | +| `204` | 删除成功. 没有数据返回. | +| `404` | 找不到该代码段. | + +## List all public snippets[](#list-all-public-snippets "Permalink") + +列出所有公共摘要. + +``` +GET /snippets/public +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `per_page` | integer | no | 每页要返回的代码段数. | +| `page` | integer | no | 要检索的页面. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets/public?per_page=2&page=1" +``` + +响应示例: + +``` +[ { "author": { "avatar_url": "http://www.gravatar.com/avatar/edaf55a9e363ea263e3b981d09e0f7f7?s=80&d=identicon", "id": 12, "name": "Libby Rolfson", "state": "active", "username": "elton_wehner", "web_url": "http://example.com/elton_wehner" }, "created_at": "2016-11-25T16:53:34.504Z", "file_name": "oconnerrice.rb", "id": 49, "title": "Ratione cupiditate et laborum temporibus.", "updated_at": "2016-11-25T16:53:34.504Z", "project_id": null, "web_url": "http://example.com/snippets/49", "raw_url": "http://example.com/snippets/49/raw" }, { "author": { "avatar_url": "http://www.gravatar.com/avatar/36583b28626de71061e6e5a77972c3bd?s=80&d=identicon", "id": 16, "name": "Llewellyn Flatley", "state": "active", "username": "adaline", "web_url": "http://example.com/adaline" }, "created_at": "2016-11-25T16:53:34.479Z", "file_name": "muellershields.rb", "id": 48, "title": "Minus similique nesciunt vel fugiat qui ullam sunt.", "updated_at": "2016-11-25T16:53:34.479Z", "project_id": null, "web_url": "http://example.com/snippets/48", "raw_url": "http://example.com/snippets/49/raw", "visibility": "public" } ] +``` + +## Get user agent details[](#get-user-agent-details "Permalink") + +在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12655) . + +**注意:**仅适用于管理员. + +``` +GET /snippets/:id/user_agent_detail +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 摘要的 ID. | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/snippets/1/user_agent_detail" +``` + +响应示例: + +``` +{ "user_agent": "AppleWebKit/537.36", "ip_address": "127.0.0.1", "akismet_submitted": false } +``` \ No newline at end of file diff --git a/docs/371.md b/docs/371.md new file mode 100644 index 0000000000000000000000000000000000000000..5b493ac8262fd4dbc96d63b157e2ea2ab0bd9ac1 --- /dev/null +++ b/docs/371.md @@ -0,0 +1,212 @@ +# Project snippets + +> 原文:[https://docs.gitlab.com/ee/api/project_snippets.html](https://docs.gitlab.com/ee/api/project_snippets.html) + +* [Snippet visibility level](#snippet-visibility-level) +* [List snippets](#list-snippets) +* [Single snippet](#single-snippet) +* [Create new snippet](#create-new-snippet) +* [Update snippet](#update-snippet) +* [Delete snippet](#delete-snippet) +* [Snippet content](#snippet-content) +* [Snippet repository file content](#snippet-repository-file-content) +* [Get user agent details](#get-user-agent-details) + +# Project snippets[](#project-snippets "Permalink") + +## Snippet visibility level[](#snippet-visibility-level "Permalink") + +GitLab 中的片段可以是私有的,内部的或公共的. 您可以使用代码段中的`visibility`字段进行设置. + +摘要可见性级别的常量为: + +| visibility | Description | +| --- | --- | +| `private` | 该代码段仅在代码段创建者中可见 | +| `internal` | 所有已登录的用户都可以看到该代码段 | +| `public` | 无需任何身份验证即可访问该代码段 | + +**注意:**从 2019 年 7 月开始,GitLab.com 上的新项目,组和摘要的`` `Internal`可见性''设置被禁用. 使用" `Internal`可见性"设置的现有项目,组和摘录保留此设置. 您可以在[相关问题中](https://gitlab.com/gitlab-org/gitlab/-/issues/12388)阅读有关更改的更多信息. + +## List snippets[](#list-snippets "Permalink") + +获取项目摘要列表. + +``` +GET /projects/:id/snippets +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) + +## Single snippet[](#single-snippet "Permalink") + +获得一个项目片段. + +``` +GET /projects/:id/snippets/:snippet_id +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-项目代码段的 ID + +``` +{ "id": 1, "title": "test", "file_name": "add.rb", "description": "Ruby test snippet", "author": { "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "created_at": "2012-05-23T08:00:58Z" }, "updated_at": "2012-06-28T10:52:04Z", "created_at": "2012-06-28T10:52:04Z", "project_id": 1, "web_url": "http://example.com/example/example/snippets/1", "raw_url": "http://example.com/example/example/snippets/1/raw" } +``` + +## Create new snippet[](#create-new-snippet "Permalink") + +创建一个新的项目片段. 用户必须具有创建新代码段的权限. + +``` +POST /projects/:id/snippets +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `title` (required) - The title of a snippet +* `file_name` (必填)-代码段文件的名称 +* `description` (可选)-代码段的说明 +* `content` (必填)-代码段的内容 +* `visibility` (必填)-代码段的可见性 + +请求示例: + +``` +curl --request POST "https://gitlab.com/api/v4/projects/:id/snippets" \ + --header "PRIVATE-TOKEN: " \ + --header "Content-Type: application/json" \ + -d @snippet.json +``` + +上面的示例请求中使用的`snippet.json` : + +``` +{ "title" : "Example Snippet Title", "description" : "More verbose snippet description", "file_name" : "example.txt", "content" : "source code \n with multiple lines\n", "visibility" : "private" } +``` + +## Update snippet[](#update-snippet "Permalink") + +更新现有的项目代码段. 用户必须具有更改现有代码段的权限. + +``` +PUT /projects/:id/snippets/:snippet_id +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-项目代码段的 ID +* `title` (可选)-摘要的标题 +* `file_name` (可选)-代码段文件的名称 +* `description` (可选)-代码段的说明 +* `content` (可选)-代码段的内容 +* `visibility` (可选)-代码段的可见性 + +请求示例: + +``` +curl --request PUT "https://gitlab.com/api/v4/projects/:id/snippets/:snippet_id" \ + --header "PRIVATE-TOKEN: " \ + --header "Content-Type: application/json" \ + -d @snippet.json +``` + +上面的示例请求中使用的`snippet.json` : + +``` +{ "title" : "Updated Snippet Title", "description" : "More verbose snippet description", "file_name" : "new_filename.txt", "content" : "updated source code \n with multiple lines\n", "visibility" : "private" } +``` + +## Delete snippet[](#delete-snippet "Permalink") + +删除现有项目片段. 如果操作成功,则返回`204 No Content`状态代码;如果找不到资源,则返回`404` . + +``` +DELETE /projects/:id/snippets/:snippet_id +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-项目代码段的 ID + +请求示例: + +``` +curl --request DELETE "https://gitlab.com/api/v4/projects/:id/snippets/:snippet_id" \ + --header "PRIVATE-TOKEN: " +``` + +## Snippet content[](#snippet-content "Permalink") + +以纯文本形式返回原始项目代码段. + +``` +GET /projects/:id/snippets/:snippet_id/raw +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-项目代码段的 ID + +请求示例: + +``` +curl "https://gitlab.com/api/v4/projects/:id/snippets/:snippet_id/raw" \ + --header "PRIVATE-TOKEN: " +``` + +## Snippet repository file content[](#snippet-repository-file-content "Permalink") + +以纯文本形式返回原始文件的内容. + +``` +GET /projects/:id/snippets/:snippet_id/files/:ref/:file_path/raw +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `snippet_id` (必填)-项目代码段的 ID +* `ref` (必填)-分支,标记或提交的名称,例如 master +* `file_path` (必填)-文件的 URL 编码路径,例如 snippet%2Erb + +请求示例: + +``` +curl "https://gitlab.com/api/v4/projects/1/snippets/2/files/master/snippet%2Erb/raw" \ + --header "PRIVATE-TOKEN: " +``` + +## Get user agent details[](#get-user-agent-details "Permalink") + +在 GitLab 9.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29508) . + +仅适用于管理员. + +``` +GET /projects/:id/snippets/:snippet_id/user_agent_detail +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | Integer | yes | 项目 ID | +| `snippet_id` | Integer | yes | 片段的 ID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/snippets/2/user_agent_detail" +``` + +响应示例: + +``` +{ "user_agent": "AppleWebKit/537.36", "ip_address": "127.0.0.1", "akismet_submitted": false } +``` \ No newline at end of file diff --git a/docs/372.md b/docs/372.md new file mode 100644 index 0000000000000000000000000000000000000000..1d2c9f9ed88f0c7e336b4aa8298fa7dfa70f6aaa --- /dev/null +++ b/docs/372.md @@ -0,0 +1,27 @@ +# Application statistics API + +> 原文:[https://docs.gitlab.com/ee/api/statistics.html](https://docs.gitlab.com/ee/api/statistics.html) + +* [Get current application statistics](#get-current-application-statistics) + +# Application statistics API[](#application-statistics-api "Permalink") + +## Get current application statistics[](#get-current-application-statistics "Permalink") + +列出 GitLab 实例的当前统计信息. 您必须是管理员才能执行此操作. + +**注意:**这些统计数据是近似的. + +``` +GET /application/statistics +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/application/statistics" +``` + +响应示例: + +``` +{ "forks": "10", "issues": "76", "merge_requests": "27", "notes": "954", "snippets": "50", "ssh_keys": "10", "milestones": "40", "users": "50", "groups": "10", "projects": "20", "active_users": "50" } +``` \ No newline at end of file diff --git a/docs/373.md b/docs/373.md new file mode 100644 index 0000000000000000000000000000000000000000..e40ea7e2a620d119f42ce42c5ca752ed5a0e629d --- /dev/null +++ b/docs/373.md @@ -0,0 +1,31 @@ +# Suggest Changes API + +> 原文:[https://docs.gitlab.com/ee/api/suggestions.html](https://docs.gitlab.com/ee/api/suggestions.html) + +* [Applying suggestions](#applying-suggestions) + +# Suggest Changes API[](#suggest-changes-api "Permalink") + +每个对建议的 API 调用都必须经过验证. + +## Applying suggestions[](#applying-suggestions "Permalink") + +在合并请求中应用建议的补丁. 用户必须至少是[Developer](../user/permissions.html)才能执行此操作. + +``` +PUT /suggestions/:id/apply +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 建议的 ID | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/suggestions/5/apply" +``` + +响应示例: + +``` + { "id": 36, "from_line": 10, "to_line": 10, "appliable": false, "applied": true, "from_content": " \"--talk-name=org.freedesktop.\",\n", "to_content": " \"--talk-name=org.free.\",\n \"--talk-name=org.desktop.\",\n" } +``` \ No newline at end of file diff --git a/docs/374.md b/docs/374.md new file mode 100644 index 0000000000000000000000000000000000000000..2a673adcc7e18658d75fcc7ee09e17659cc7561e --- /dev/null +++ b/docs/374.md @@ -0,0 +1,106 @@ +# System hooks API + +> 原文:[https://docs.gitlab.com/ee/api/system_hooks.html](https://docs.gitlab.com/ee/api/system_hooks.html) + +* [List system hooks](#list-system-hooks) +* [Add new system hook](#add-new-system-hook) +* [Test system hook](#test-system-hook) +* [Delete system hook](#delete-system-hook) + +# System hooks API[](#system-hooks-api "Permalink") + +所有方法都需要管理员授权. + +也可以使用**Admin Area> System Hooks** ( `/admin/hooks` )中的 UI 来配置系统挂钩的 URL 端点. + +阅读有关[系统挂钩的](../system_hooks/system_hooks.html)更多信息. + +## List system hooks[](#list-system-hooks "Permalink") + +获取所有系统挂钩的列表. + +``` +GET /hooks +``` + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/hooks" +``` + +响应示例: + +``` +[ { "id":1, "url":"https://gitlab.example.com/hook", "created_at":"2016-10-31T12:32:15.192Z", "push_events":true, "tag_push_events":false, "merge_requests_events": true, "repository_update_events": true, "enable_ssl_verification":true } ] +``` + +## Add new system hook[](#add-new-system-hook "Permalink") + +添加一个新的系统挂钩. + +``` +POST /hooks +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `url` | string | yes | 挂钩网址 | +| `token` | string | no | 用于验证收到的有效载荷的秘密令牌; 这将不会在响应中返回 | +| `push_events` | boolean | no | 设置为 true 时,挂钩将在推送事件时触发 | +| `tag_push_events` | boolean | no | 设置为 true 时,挂钩将在被推送的新标签上触发 | +| `merge_requests_events` | boolean | no | 触发合并请求事件的钩子 | +| `repository_update_events` | boolean | no | 触发挂钩存储库更新事件 | +| `enable_ssl_verification` | boolean | no | 触发挂钩时执行 SSL 验证 | + +请求示例: + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/hooks?url=https://gitlab.example.com/hook" +``` + +响应示例: + +``` +[ { "id":1, "url":"https://gitlab.example.com/hook", "created_at":"2016-10-31T12:32:15.192Z", "push_events":true, "tag_push_events":false, "merge_requests_events": true, "repository_update_events": true, "enable_ssl_verification":true } ] +``` + +## Test system hook[](#test-system-hook "Permalink") + +``` +GET /hooks/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 钩子的 ID | + +请求示例: + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/hooks/2" +``` + +响应示例: + +``` +{ "project_id" : 1, "owner_email" : "example@gitlabhq.com", "owner_name" : "Someone", "name" : "Ruby", "path" : "ruby", "event_name" : "project_create" } +``` + +## Delete system hook[](#delete-system-hook "Permalink") + +删除系统挂钩. + +``` +DELETE /hooks/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 钩子的 ID | + +请求示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/hooks/2" +``` \ No newline at end of file diff --git a/docs/375.md b/docs/375.md new file mode 100644 index 0000000000000000000000000000000000000000..16e6ccc3f9f47c1feb69f425f172e9cdcc5f70d3 --- /dev/null +++ b/docs/375.md @@ -0,0 +1,159 @@ +# Tags API + +> 原文:[https://docs.gitlab.com/ee/api/tags.html](https://docs.gitlab.com/ee/api/tags.html) + +* [List project repository tags](#list-project-repository-tags) +* [Get a single repository tag](#get-a-single-repository-tag) +* [Create a new tag](#create-a-new-tag) +* [Delete a tag](#delete-a-tag) +* [Create a new release](#create-a-new-release) +* [Update a release](#update-a-release) + +# Tags API[](#tags-api "Permalink") + +## List project repository tags[](#list-project-repository-tags "Permalink") + +从项目中获取存储库标签的列表,按名称以相反的字母顺序排序. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/tags +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `order_by` | string | no | 返回按`name`或`updated`字段排序的标签. 默认值已`updated` | +| `sort` | string | no | 返回按`asc`或`desc`顺序排序的标签. 默认为`desc` | +| `search` | string | no | 返回符合搜索条件的标签列表. 您可以使用`^term`和`term$`查找分别以`term`开头和结尾的标签. | + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54401)了对`search`支持. + +``` +[ { "commit": { "id": "2695effb5807a22ff3d138d593fd856244e155e7", "short_id": "2695effb", "title": "Initial commit", "created_at": "2017-07-26T11:08:53.000+02:00", "parent_ids": [ "2a4b78934375d7f53875269ffd4f45fd83a84ebe" ], "message": "Initial commit", "author_name": "John Smith", "author_email": "john@example.com", "authored_date": "2012-05-28T04:42:42-07:00", "committer_name": "Jack Smith", "committer_email": "jack@example.com", "committed_date": "2012-05-28T04:42:42-07:00" }, "release": { "tag_name": "1.0.0", "description": "Amazing release. Wow" }, "name": "v1.0.0", "target": "2695effb5807a22ff3d138d593fd856244e155e7", "message": null, "protected": true } ] +``` + +## Get a single repository tag[](#get-a-single-repository-tag "Permalink") + +获取由其名称确定的特定存储库标签. 如果可公开访问该存储库,则无需身份验证即可访问此端点. + +``` +GET /projects/:id/repository/tags/:tag_name +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) | +| `tag_name` | string | yes | 标签名称 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/tags/v1.0.0" +``` + +示例响应: + +``` +{ "name": "v5.0.0", "message": null, "target": "60a8ff033665e1207714d6670fcd7b65304ec02f", "commit": { "id": "60a8ff033665e1207714d6670fcd7b65304ec02f", "short_id": "60a8ff03", "title": "Initial commit", "created_at": "2017-07-26T11:08:53.000+02:00", "parent_ids": [ "f61c062ff8bcbdb00e0a1b3317a91aed6ceee06b" ], "message": "v5.0.0\n", "author_name": "Arthur Verschaeve", "author_email": "contact@arthurverschaeve.be", "authored_date": "2015-02-01T21:56:31.000+01:00", "committer_name": "Arthur Verschaeve", "committer_email": "contact@arthurverschaeve.be", "committed_date": "2015-02-01T21:56:31.000+01:00" }, "release": null, "protected": false } +``` + +## Create a new tag[](#create-a-new-tag "Permalink") + +在存储库中创建一个新标签,该标签指向提供的参考. + +``` +POST /projects/:id/repository/tags +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `tag_name` (必需)-标签的名称 +* `ref` (必需)-使用提交 SHA,另一个标签名称或分支名称创建标签. +* `message` (可选)-创建带注释的标签. +* `release_description` (可选)-将发行说明添加到 Git 标签并将其存储在 GitLab 数据库中. + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/repository/tags?tag_name=test&ref=master" +``` + +响应示例: + +``` +{ "commit": { "id": "2695effb5807a22ff3d138d593fd856244e155e7", "short_id": "2695effb", "title": "Initial commit", "created_at": "2017-07-26T11:08:53.000+02:00", "parent_ids": [ "2a4b78934375d7f53875269ffd4f45fd83a84ebe" ], "message": "Initial commit", "author_name": "John Smith", "author_email": "john@example.com", "authored_date": "2012-05-28T04:42:42-07:00", "committer_name": "Jack Smith", "committer_email": "jack@example.com", "committed_date": "2012-05-28T04:42:42-07:00" }, "release": { "tag_name": "1.0.0", "description": "Amazing release. Wow" }, "name": "v1.0.0", "target": "2695effb5807a22ff3d138d593fd856244e155e7", "message": null, "protected": false } +``` + +创建轻量级标签时,该消息将为`null` ,否则将包含注释. + +在创建带注释的标签时,目标将包含标签对象 ID,否则在创建轻量级标签时将包含提交 ID. + +如果出现错误,则返回带有解释性错误消息的状态代码`405` . + +## Delete a tag[](#delete-a-tag "Permalink") + +删除具有给定名称的存储库的标记. + +``` +DELETE /projects/:id/repository/tags/:tag_name +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `tag_name` (必需)-标签的名称 + +## Create a new release[](#create-a-new-release "Permalink") + +将发行说明添加到现有的 Git 标签. 如果给定标签已经存在发行版,则返回状态码`409` . + +``` +POST /projects/:id/repository/tags/:tag_name/release +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `tag_name` (必需)-标签的名称 + +要求正文: + +* `description` (必需)-具有 Markdown 支持的发行说明 + +``` +{ "description": "Amazing release. Wow" } +``` + +Response: + +``` +{ "tag_name": "1.0.0", "description": "Amazing release. Wow" } +``` + +## Update a release[](#update-a-release "Permalink") + +更新给定发行版的发行说明. + +``` +PUT /projects/:id/repository/tags/:tag_name/release +``` + +Parameters: + +* `id` (必填)-经过身份验证的用户拥有[的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) +* `tag_name` (必需)-标签的名称 + +要求正文: + +* `description` (必需)-具有 Markdown 支持的发行说明 + +``` +{ "description": "Amazing release. Wow" } +``` + +Response: + +``` +{ "tag_name": "1.0.0", "description": "Amazing release. Wow" } +``` \ No newline at end of file diff --git a/docs/376.md b/docs/376.md new file mode 100644 index 0000000000000000000000000000000000000000..02548615c7b9cc0f3f651e360ef8adee9c1d9bd2 --- /dev/null +++ b/docs/376.md @@ -0,0 +1,76 @@ +# Todos API + +> 原文:[https://docs.gitlab.com/ee/api/todos.html](https://docs.gitlab.com/ee/api/todos.html) + +* [Get a list of todos](#get-a-list-of-todos) +* [Mark a todo as done](#mark-a-todo-as-done) +* [Mark all todos as done](#mark-all-todos-as-done) + +# Todos API[](#todos-api "Permalink") + +在 GitLab 8.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3188) . + +## Get a list of todos[](#get-a-list-of-todos "Permalink") + +返回待办事项列表. 如果未应用任何过滤器,它将返回当前用户的所有待处理的待办事项. 不同的过滤器使用户可以精确地处理请求. + +``` +GET /todos +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `action` | string | no | 要过滤的动作. 可以`assigned` , `mentioned` , `build_failed` , `marked` , `approval_required` , `unmergeable`或`directly_addressed` `unmergeable` . | +| `author_id` | integer | no | 作者的 ID | +| `project_id` | integer | no | 项目 ID | +| `group_id` | integer | no | 组的 ID | +| `state` | string | no | 待办事项的状态. 可以`pending`或`done` | +| `type` | string | no | 待办事项的类型. 可以是`Issue`或`MergeRequest` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/todos" +``` + +示例响应: + +``` +[ { "id": 102, "project": { "id": 2, "name": "Gitlab Ce", "name_with_namespace": "Gitlab Org / Gitlab Ce", "path": "gitlab-foss", "path_with_namespace": "gitlab-org/gitlab-foss" }, "author": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "action_name": "marked", "target_type": "MergeRequest", "target": { "id": 34, "iid": 7, "project_id": 2, "title": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", "description": "Et ea et omnis illum cupiditate. Dolor aspernatur tenetur ducimus facilis est nihil. Quo esse cupiditate molestiae illo corrupti qui quidem dolor.", "state": "opened", "created_at": "2016-06-17T07:49:24.419Z", "updated_at": "2016-06-17T07:52:43.484Z", "target_branch": "tutorials_git_tricks", "source_branch": "DNSBL_docs", "upvotes": 0, "downvotes": 0, "author": { "name": "Maxie Medhurst", "username": "craig_rutherford", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", "web_url": "https://gitlab.example.com/craig_rutherford" }, "assignee": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "source_project_id": 2, "target_project_id": 2, "labels": [], "work_in_progress": false, "milestone": { "id": 32, "iid": 2, "project_id": 2, "title": "v1.0", "description": "Assumenda placeat ea voluptatem voluptate qui.", "state": "active", "created_at": "2016-06-17T07:47:34.163Z", "updated_at": "2016-06-17T07:47:34.163Z", "due_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "cannot_be_merged", "subscribed": true, "user_notes_count": 7 }, "target_url": "https://gitlab.example.com/gitlab-org/gitlab-foss/-/merge_requests/7", "body": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", "state": "pending", "created_at": "2016-06-17T07:52:35.225Z", "updated_at": "2016-06-17T07:52:35.225Z" }, { "id": 98, "project": { "id": 2, "name": "Gitlab Ce", "name_with_namespace": "Gitlab Org / Gitlab Ce", "path": "gitlab-foss", "path_with_namespace": "gitlab-org/gitlab-foss" }, "author": { "name": "Maxie Medhurst", "username": "craig_rutherford", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", "web_url": "https://gitlab.example.com/craig_rutherford" }, "action_name": "assigned", "target_type": "MergeRequest", "target": { "id": 34, "iid": 7, "project_id": 2, "title": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", "description": "Et ea et omnis illum cupiditate. Dolor aspernatur tenetur ducimus facilis est nihil. Quo esse cupiditate molestiae illo corrupti qui quidem dolor.", "state": "opened", "created_at": "2016-06-17T07:49:24.419Z", "updated_at": "2016-06-17T07:52:43.484Z", "target_branch": "tutorials_git_tricks", "source_branch": "DNSBL_docs", "upvotes": 0, "downvotes": 0, "author": { "name": "Maxie Medhurst", "username": "craig_rutherford", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", "web_url": "https://gitlab.example.com/craig_rutherford" }, "assignee": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "source_project_id": 2, "target_project_id": 2, "labels": [], "work_in_progress": false, "milestone": { "id": 32, "iid": 2, "project_id": 2, "title": "v1.0", "description": "Assumenda placeat ea voluptatem voluptate qui.", "state": "active", "created_at": "2016-06-17T07:47:34.163Z", "updated_at": "2016-06-17T07:47:34.163Z", "due_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "cannot_be_merged", "subscribed": true, "user_notes_count": 7 }, "target_url": "https://gitlab.example.com/gitlab-org/gitlab-foss/-/merge_requests/7", "body": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", "state": "pending", "created_at": "2016-06-17T07:49:24.624Z", "updated_at": "2016-06-17T07:49:24.624Z" } ] +``` + +## Mark a todo as done[](#mark-a-todo-as-done "Permalink") + +将其 ID 给当前用户的单个待处理待办事项标记为已完成. 标记为已完成的待办事项在响应中返回. + +``` +POST /todos/:id/mark_as_done +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 待办事项编号 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/todos/130/mark_as_done" +``` + +示例响应: + +``` +{ "id": 102, "project": { "id": 2, "name": "Gitlab Ce", "name_with_namespace": "Gitlab Org / Gitlab Ce", "path": "gitlab-foss", "path_with_namespace": "gitlab-org/gitlab-foss" }, "author": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "action_name": "marked", "target_type": "MergeRequest", "target": { "id": 34, "iid": 7, "project_id": 2, "title": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", "description": "Et ea et omnis illum cupiditate. Dolor aspernatur tenetur ducimus facilis est nihil. Quo esse cupiditate molestiae illo corrupti qui quidem dolor.", "state": "opened", "created_at": "2016-06-17T07:49:24.419Z", "updated_at": "2016-06-17T07:52:43.484Z", "target_branch": "tutorials_git_tricks", "source_branch": "DNSBL_docs", "upvotes": 0, "downvotes": 0, "author": { "name": "Maxie Medhurst", "username": "craig_rutherford", "id": 12, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", "web_url": "https://gitlab.example.com/craig_rutherford" }, "assignee": { "name": "Administrator", "username": "root", "id": 1, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "https://gitlab.example.com/root" }, "source_project_id": 2, "target_project_id": 2, "labels": [], "work_in_progress": false, "milestone": { "id": 32, "iid": 2, "project_id": 2, "title": "v1.0", "description": "Assumenda placeat ea voluptatem voluptate qui.", "state": "active", "created_at": "2016-06-17T07:47:34.163Z", "updated_at": "2016-06-17T07:47:34.163Z", "due_date": null }, "merge_when_pipeline_succeeds": false, "merge_status": "cannot_be_merged", "subscribed": true, "user_notes_count": 7 }, "target_url": "https://gitlab.example.com/gitlab-org/gitlab-foss/-/merge_requests/7", "body": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", "state": "done", "created_at": "2016-06-17T07:52:35.225Z", "updated_at": "2016-06-17T07:52:35.225Z" } +``` + +## Mark all todos as done[](#mark-all-todos-as-done "Permalink") + +将当前用户的所有待处理待办事项标记为已完成. 它返回带有空响应的 HTTP 状态代码`204` . + +``` +POST /todos/mark_as_done +``` + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/todos/mark_as_done" +``` \ No newline at end of file diff --git a/docs/377.md b/docs/377.md new file mode 100644 index 0000000000000000000000000000000000000000..d1a4af3143959ce56fc9ed98a40bfaf2b0c687ce --- /dev/null +++ b/docs/377.md @@ -0,0 +1,1095 @@ +# Users API + +> 原文:[https://docs.gitlab.com/ee/api/users.html](https://docs.gitlab.com/ee/api/users.html) + +* [List users](#list-users) + * [For normal users](#for-normal-users) + * [For admins](#for-admins) +* [Single user](#single-user) + * [For user](#for-user) + * [For admin](#for-admin) +* [User creation](#user-creation) +* [User modification](#user-modification) +* [Delete authentication identity from user](#delete-authentication-identity-from-user) +* [User deletion](#user-deletion) +* [List current user (for normal users)](#list-current-user-for-normal-users) +* [List current user (for admins)](#list-current-user-for-admins) +* [User status](#user-status) +* [Get the status of a user](#get-the-status-of-a-user) +* [Set user status](#set-user-status) +* [User counts](#user-counts) +* [List user projects](#list-user-projects) +* [List SSH keys](#list-ssh-keys) +* [List SSH keys for user](#list-ssh-keys-for-user) +* [Single SSH key](#single-ssh-key) +* [Add SSH key](#add-ssh-key) +* [Add SSH key for user](#add-ssh-key-for-user) +* [Delete SSH key for current user](#delete-ssh-key-for-current-user) +* [Delete SSH key for given user](#delete-ssh-key-for-given-user) +* [List all GPG keys](#list-all-gpg-keys) +* [Get a specific GPG key](#get-a-specific-gpg-key) +* [Add a GPG key](#add-a-gpg-key) +* [Delete a GPG key](#delete-a-gpg-key) +* [List all GPG keys for given user](#list-all-gpg-keys-for-given-user) +* [Get a specific GPG key for a given user](#get-a-specific-gpg-key-for-a-given-user) +* [Add a GPG key for a given user](#add-a-gpg-key-for-a-given-user) +* [Delete a GPG key for a given user](#delete-a-gpg-key-for-a-given-user) +* [List emails](#list-emails) +* [List emails for user](#list-emails-for-user) +* [Single email](#single-email) +* [Add email](#add-email) +* [Add email for user](#add-email-for-user) +* [Delete email for current user](#delete-email-for-current-user) +* [Delete email for given user](#delete-email-for-given-user) +* [Block user](#block-user) +* [Unblock user](#unblock-user) +* [Deactivate user](#deactivate-user) +* [Activate user](#activate-user) + * [Get user contribution events](#get-user-contribution-events) +* [Get all impersonation tokens of a user](#get-all-impersonation-tokens-of-a-user) +* [Get an impersonation token of a user](#get-an-impersonation-token-of-a-user) +* [Create an impersonation token](#create-an-impersonation-token) +* [Revoke an impersonation token](#revoke-an-impersonation-token) + * [Get user activities (admin only)](#get-user-activities-admin-only) +* [User memberships (admin only)](#user-memberships-admin-only) + +# Users API[](#users-api "Permalink") + +## List users[](#list-users "Permalink") + +活动用户=帐户总数-被阻止的用户 + +获取用户列表. + +此函数使用分页参数`page`和`per_page`来限制用户列表. + +### For normal users[](#for-normal-users "Permalink") + +``` +GET /users +``` + +``` +[ { "id": 1, "username": "john_smith", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", "web_url": "http://localhost:3000/john_smith" }, { "id": 2, "username": "jack_smith", "name": "Jack Smith", "state": "blocked", "avatar_url": "http://gravatar.com/../e32131cd8.jpeg", "web_url": "http://localhost:3000/jack_smith" } ] +``` + +您还可以使用`?search=`通过名称或主要电子邮件搜索用户. 例如. `/users?search=John` . + +另外,您可以按用户名查找用户: + +``` +GET /users?username=:username +``` + +例如: + +``` +GET /users?username=jack_smith +``` + +另外,您可以根据状态过滤用户,例如. `blocked` , `active`此选项仅用于过滤被`blocked`或`active`用户. 它不支持`active=false`或`blocked=false` . + +``` +GET /users?active=true +``` + +``` +GET /users?blocked=true +``` + +**注意:**用户名搜索不区分大小写. + +### For admins[](#for-admins "Permalink") + +``` +GET /users +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `order_by` | string | no | 返回按`id` , `name` , `username` , `created_at`或`updated_at`字段排序的`username` . 默认为`id` | +| `sort` | string | no | 返回用户按`asc`或`desc`排列. 默认为`desc` | +| `two_factor` | string | no | 通过两因素身份验证过滤用户. `enabled`或`disabled`过滤器值. 默认情况下,它返回所有用户 | +| `without_projects` | boolean | no | 过滤没有项目的用户. 默认为`false` | + +``` +[ { "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "is_admin": false, "bio": null, "bio_html": null, "location": null, "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "", "job_title": "", "last_sign_in_at": "2012-06-01T11:41:01Z", "confirmed_at": "2012-05-23T09:05:22Z", "theme_id": 1, "last_activity_on": "2012-05-23", "color_scheme_id": 2, "projects_limit": 100, "current_sign_in_at": "2012-06-02T06:36:55Z", "note": "DMCA Request: 2018-11-05 | DMCA Violation | Abuse | https://gitlab.zendesk.com/agent/tickets/123", "identities": [ {"provider": "github", "extern_uid": "2435223452345"}, {"provider": "bitbucket", "extern_uid": "john.smith"}, {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"} ], "can_create_group": true, "can_create_project": true, "two_factor_enabled": true, "external": false, "private_profile": false, "current_sign_in_ip": "196.165.1.102", "last_sign_in_ip": "172.127.2.22" }, { "id": 2, "username": "jack_smith", "email": "jack@example.com", "name": "Jack Smith", "state": "blocked", "avatar_url": "http://localhost:3000/uploads/user/avatar/2/index.jpg", "web_url": "http://localhost:3000/jack_smith", "created_at": "2012-05-23T08:01:01Z", "is_admin": false, "bio": null, "bio_html": null, "location": null, "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "", "job_title": "", "last_sign_in_at": null, "confirmed_at": "2012-05-30T16:53:06.148Z", "theme_id": 1, "last_activity_on": "2012-05-23", "color_scheme_id": 3, "projects_limit": 100, "current_sign_in_at": "2014-03-19T17:54:13Z", "identities": [], "can_create_group": true, "can_create_project": true, "two_factor_enabled": true, "external": false, "private_profile": false, "current_sign_in_ip": "10.165.1.102", "last_sign_in_ip": "172.127.2.22" } ] +``` + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`shared_runners_minutes_limit`和`extra_shared_runners_minutes_limit`参数. + +``` +[ { "id": 1, ... "shared_runners_minutes_limit": 133, "extra_shared_runners_minutes_limit": 133, ... } ] +``` + +使用 GitLab [Silver 或更高版本的](https://about.gitlab.com/pricing/)用户还将看到`group_saml`提供程序选项: + +``` +[ { "id": 1, ... "identities": [ {"provider": "github", "extern_uid": "2435223452345"}, {"provider": "bitbucket", "extern_uid": "john.smith"}, {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"}, {"provider": "group_saml", "extern_uid": "123789", "saml_provider_id": 10} ], ... } ] +``` + +您可以通过外部 UID 和提供程序查找用户: + +``` +GET /users?extern_uid=:extern_uid&provider=:provider +``` + +例如: + +``` +GET /users?extern_uid=1234567&provider=github +``` + +您可以使用`/users?external=true`搜索外部`/users?external=true` + +您可以使用以下创建日期时间范围来搜索用户: + +``` +GET /users?created_before=2001-01-02T00:00:00.060Z&created_after=1999-01-02T00:00:00.060 +``` + +您可以使用`/users?without_projects=true`搜索没有项目的`/users?without_projects=true` + +您可以使用以下[自定义属性](custom_attributes.html)进行过滤: + +``` +GET /users?custom_attributes[key]=value&custom_attributes[other_key]=other_value +``` + +您可以通过以下方式在响应中包括用户的[自定义属性](custom_attributes.html) : + +``` +GET /users?with_custom_attributes=true +``` + +## Single user[](#single-user "Permalink") + +获得一个用户. + +### For user[](#for-user "Permalink") + +``` +GET /users/:id +``` + +Parameters: + +* `id` (必填)-用户的 ID + +``` +{ "id": 1, "username": "john_smith", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "bio": null, "bio_html": null, "location": null, "public_email": "john@example.com", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "", "job_title": "Operations Specialist" } +``` + +### For admin[](#for-admin "Permalink") + +``` +GET /users/:id +``` + +Parameters: + +* `id` (必填)-用户的 ID + +响应示例: + +``` +{ "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "is_admin": false, "bio": null, "bio_html": null, "location": null, "public_email": "john@example.com", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "", "job_title": "Operations Specialist", "last_sign_in_at": "2012-06-01T11:41:01Z", "confirmed_at": "2012-05-23T09:05:22Z", "theme_id": 1, "last_activity_on": "2012-05-23", "color_scheme_id": 2, "projects_limit": 100, "current_sign_in_at": "2012-06-02T06:36:55Z", "note": "DMCA Request: 2018-11-05 | DMCA Violation | Abuse | https://gitlab.zendesk.com/agent/tickets/123", "identities": [ {"provider": "github", "extern_uid": "2435223452345"}, {"provider": "bitbucket", "extern_uid": "john.smith"}, {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"} ], "can_create_group": true, "can_create_project": true, "two_factor_enabled": true, "external": false, "private_profile": false, "current_sign_in_ip": "196.165.1.102", "last_sign_in_ip": "172.127.2.22", "plan": "gold", "trial": true } +``` + +**注意:** `plan`和`trial`参数仅在 GitLab 企业版上可用. + +使用 GitLab [Starter,Bronze 或更高版本的用户](https://about.gitlab.com/pricing/)还将看到`shared_runners_minutes_limit`和`extra_shared_runners_minutes_limit`参数. + +``` +{ "id": 1, "username": "john_smith", "shared_runners_minutes_limit": 133, "extra_shared_runners_minutes_limit": 133, ... } +``` + +GitLab.com [Silver 或更高版本](https://about.gitlab.com/pricing/)上的用户还将看到`group_saml`选项: + +``` +{ "id": 1, "username": "john_smith", "shared_runners_minutes_limit": 133, "extra_shared_runners_minutes_limit": 133, "identities": [ {"provider": "github", "extern_uid": "2435223452345"}, {"provider": "bitbucket", "extern_uid": "john.smith"}, {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"}, {"provider": "group_saml", "extern_uid": "123789", "saml_provider_id": 10} ], ... } +``` + +您可以通过以下方式在响应中包括用户的[自定义属性](custom_attributes.html) : + +``` +GET /users/:id?with_custom_attributes=true +``` + +## User creation[](#user-creation "Permalink") + +Creates a new user. Note only administrators can create new users. Either `password`, `reset_password`, or `force_random_password` must be specified. If `reset_password` and `force_random_password` are both `false`, then `password` is required. + +请注意, `force_random_password`和`reset_password`优先级高于`password` . 此外, `reset_password`和`force_random_password`可以一起使用. + +**注意:**从[GitLab 12.1 开始](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29888/) , `private_profile`将默认为`false` . + +``` +POST /users +``` + +Parameters: + +| Attribute | Required | Description | +| --- | --- | --- | +| `admin` | No | 用户是管理员-正确或错误(默认) | +| `avatar` | No | 用户头像的图像文件 | +| `bio` | No | 用户的传记 | +| `can_create_group` | No | 用户可以创建组-正确或错误 | +| `color_scheme_id` | No | 用户针对文件查看器的配色方案(有关更多信息,请参见[用户首选项文档](../user/profile/preferences.html#syntax-highlighting-theme) ) | +| `email` | Yes | Email | +| `extern_uid` | No | 外部 UID | +| `external` | No | 将用户标记为外部用户-true 或 false(默认) | +| `extra_shared_runners_minutes_limit` | No | 该用户的额外管道分钟配额(在计划中包括的分钟之外购买) | +| `force_random_password` | No | 将用户密码设置为随机值-正确或错误(默认) | +| `group_id_for_saml` | No | 已配置 SAML 的组的 ID | +| `linkedin` | No | LinkedIn | +| `location` | No | 用户位置 | +| `name` | Yes | Name | +| `note` | No | 该用户的管理说明 | +| `organization` | No | 机构名称 | +| `password` | No | Password | +| `private_profile` | No | 用户的个人资料是私有的-true,false(默认)或 null(将转换为 false) | +| `projects_limit` | No | 用户可以创建的项目数 | +| `provider` | No | 外部提供商名称 | +| `public_email` | No | 用户的公开电子邮件 | +| `reset_password` | No | 发送用户密码重置链接-正确或错误(默认) | +| `shared_runners_minutes_limit` | No | 该用户的管道分钟配额(包括在计划中). 可以为`nil` (默认值;继承系统默认值), `0` (无限制)或`> 0` | +| `skip_confirmation` | No | 跳过确认-正确或错误(默认) | +| `skype` | No | Skype 帐号 | +| `theme_id` | No | 用户的 GitLab 主题(有关更多信息,请参见[用户首选项文档](../user/profile/preferences.html#navigation-theme) ) | +| `twitter` | No | Twitter 账号 | +| `username` | Yes | Username | +| `website_url` | No | 网址 | + +## User modification[](#user-modification "Permalink") + +修改现有用户. 只有管​​理员可以更改用户的属性. + +``` +PUT /users/:id +``` + +Parameters: + +| Attribute | Required | Description | +| --- | --- | --- | +| `admin` | No | 用户是管理员-正确或错误(默认) | +| `avatar` | No | 用户头像的图像文件 | +| `bio` | No | 用户的传记 | +| `can_create_group` | No | 用户可以创建组-正确或错误 | +| `color_scheme_id` | No | 用户针对文件查看器的配色方案(有关更多信息,请参见[用户首选项文档](../user/profile/preferences.html#syntax-highlighting-theme) ) | +| `email` | No | Email | +| `extern_uid` | No | 外部 UID | +| `external` | No | 将用户标记为外部用户-true 或 false(默认) | +| `extra_shared_runners_minutes_limit` | No | 该用户的额外管道分钟配额(在计划中包括的分钟之外购买) | +| `group_id_for_saml` | No | 已配置 SAML 的组的 ID | +| `id` | Yes | 用户的 ID | +| `linkedin` | No | LinkedIn | +| `location` | No | 用户位置 | +| `name` | No | Name | +| `note` | No | 该用户的管理说明 | +| `organization` | No | 机构名称 | +| `password` | No | Password | +| `private_profile` | No | 用户的个人资料是私有的-true,false(默认)或 null(将转换为 false) | +| `projects_limit` | No | 限制每个用户可以创建的项目 | +| `provider` | No | 外部提供商名称 | +| `public_email` | No | 用户的公开电子邮件 | +| `shared_runners_minutes_limit` | No | 该用户的管道分钟配额(包括在计划中). 可以为`nil` (默认值;继承系统默认值), `0` (无限制)或`> 0` | +| `skip_reconfirmation` | No | 跳过确认-正确或错误(默认) | +| `skype` | No | Skype 帐号 | +| `theme_id` | No | 用户的 GitLab 主题(有关更多信息,请参见[用户首选项文档](../user/profile/preferences.html#navigation-theme) ) | +| `twitter` | No | Twitter 账号 | +| `username` | No | Username | +| `website_url` | No | 网址 | + +密码更新时,用户将被迫在下次登录时进行更改. 请注意,此方法目前仅返回`404`错误,即使在`409` (冲突)更为合适的情况下也是如此. 例如,将电子邮件地址重命名为某个现有地址时. + +## Delete authentication identity from user[](#delete-authentication-identity-from-user "Permalink") + +使用与该身份关联的提供者名称删除用户的身份验证身份. 仅适用于管理员. + +``` +DELETE /users/:id/identities/:provider +``` + +Parameters: + +* `id` (必填)-用户的 ID +* `provider` (必填)-外部提供程序名称 + +## User deletion[](#user-deletion "Permalink") + +删除用户. 仅适用于管理员. 如果操作成功,则返回`204 No Content`状态代码;如果找不到资源,则返回`404`如果无法软删除用户,则返回`409` . + +``` +DELETE /users/:id +``` + +Parameters: + +* `id` (必填)-用户的 ID +* `hard_delete` (可选)-如果为 true,则通常会[移至](../user/profile/account/delete_account.html#associated-records) `hard_delete` [用户的](../user/profile/account/delete_account.html#associated-records)贡献以及该用户`hard_delete`组将被删除. + +## List current user (for normal users)[](#list-current-user-for-normal-users "Permalink") + +获取当前经过身份验证的用户. + +``` +GET /user +``` + +``` +{ "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "bio": null, "bio_html": null, "location": null, "public_email": "john@example.com", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "", "last_sign_in_at": "2012-06-01T11:41:01Z", "confirmed_at": "2012-05-23T09:05:22Z", "theme_id": 1, "last_activity_on": "2012-05-23", "color_scheme_id": 2, "projects_limit": 100, "current_sign_in_at": "2012-06-02T06:36:55Z", "identities": [ {"provider": "github", "extern_uid": "2435223452345"}, {"provider": "bitbucket", "extern_uid": "john_smith"}, {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"} ], "can_create_group": true, "can_create_project": true, "two_factor_enabled": true, "external": false, "private_profile": false } +``` + +## List current user (for admins)[](#list-current-user-for-admins "Permalink") + +Parameters: + +* `sudo` (可选)-在其位置进行呼叫的用户的 ID + +``` +GET /user +``` + +``` +{ "id": 1, "username": "john_smith", "email": "john@example.com", "name": "John Smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "is_admin": false, "bio": null, "bio_html": null, "location": null, "public_email": "john@example.com", "skype": "", "linkedin": "", "twitter": "", "website_url": "", "organization": "", "job_title": "", "last_sign_in_at": "2012-06-01T11:41:01Z", "confirmed_at": "2012-05-23T09:05:22Z", "theme_id": 1, "last_activity_on": "2012-05-23", "color_scheme_id": 2, "projects_limit": 100, "current_sign_in_at": "2012-06-02T06:36:55Z", "identities": [ {"provider": "github", "extern_uid": "2435223452345"}, {"provider": "bitbucket", "extern_uid": "john_smith"}, {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"} ], "can_create_group": true, "can_create_project": true, "two_factor_enabled": true, "external": false, "private_profile": false, "current_sign_in_ip": "196.165.1.102", "last_sign_in_ip": "172.127.2.22" } +``` + +## User status[](#user-status "Permalink") + +获取当前登录用户的状态. + +``` +GET /user/status +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/user/status" +``` + +响应示例: + +``` +{ "emoji":"coffee", "message":"I crave coffee :coffee:", "message_html": "I crave coffee " } +``` + +## Get the status of a user[](#get-the-status-of-a-user "Permalink") + +获取用户的状态. + +``` +GET /users/:id_or_username/status +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id_or_username` | string | yes | 用户的 ID 或用户名,以获取状态 | + +``` +curl "https://gitlab.example.com/users/janedoe/status" +``` + +响应示例: + +``` +{ "emoji":"coffee", "message":"I crave coffee :coffee:", "message_html": "I crave coffee " } +``` + +## Set user status[](#set-user-status "Permalink") + +设置当前用户的状态. + +``` +PUT /user/status +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `emoji` | string | no | 用作状态的表情符号名称. 如果省略,则使用`speech_balloon` . 表情符号名称可以是[Gemojione 索引中](https://github.com/bonusly/gemojione/blob/master/config/index.json)指定的名称之一. | +| `message` | string | no | 设置为状态的消息. 它还可以包含表情符号代码. | + +当参数`emoji`和`message`都为空时,状态将被清除. + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --data "emoji=coffee" --data "message=I crave coffee" "https://gitlab.example.com/api/v4/user/status" +``` + +回应范例 + +``` +{ "emoji":"coffee", "message":"I crave coffee", "message_html": "I crave coffee" } +``` + +## User counts[](#user-counts "Permalink") + +获取当前登录用户的计数(与右上角菜单相同). + +| Attribute | Type | Description | +| --- | --- | --- | +| `merge_requests` | number | 合并活动的请求并分配给当前用户. | + +``` +GET /user_counts +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/user_counts" +``` + +响应示例: + +``` +{ "merge_requests": 4 } +``` + +## List user projects[](#list-user-projects "Permalink") + +请参考[用户项目列表](projects.html#list-user-projects) . + +## List SSH keys[](#list-ssh-keys "Permalink") + +获取当前经过身份验证的用户的 SSH 密钥的列表. + +``` +GET /user/keys +``` + +``` +[ { "id": 1, "title": "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2014-08-01T14:47:39.080Z" }, { "id": 3, "title": "Another Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2014-08-01T14:47:39.080Z" } ] +``` + +Parameters: + +* **none** + +## List SSH keys for user[](#list-ssh-keys-for-user "Permalink") + +获取指定用户的 SSH 密钥的列表. + +``` +GET /users/:id_or_username/keys +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id_or_username` | string | yes | 要为其获取 SSH 密钥的用户的 ID 或用户名. | + +## Single SSH key[](#single-ssh-key "Permalink") + +获取一个密钥. + +``` +GET /user/keys/:key_id +``` + +Parameters: + +* `key_id` (必填) `key_id`密钥的 ID + +``` +{ "id": 1, "title": "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2014-08-01T14:47:39.080Z" } +``` + +## Add SSH key[](#add-ssh-key "Permalink") + +创建当前经过身份验证的用户拥有的新密钥. + +``` +POST /user/keys +``` + +Parameters: + +* `title` (必填)-新的 SSH 密钥的标题 +* `key` (必填)-新的 SSH 密钥 +* `expires_at` (可选)-ISO 8601 格式的 SSH 密钥的到期日期( `YYYY-MM-DDTHH:MM:SSZ` ) + +``` +{ "title": "ABC", "key": "ssh-dss AAAAB3NzaC1kc3MAAACBAMLrhYgI3atfrSD6KDas1b/3n6R/HP+bLaHHX6oh+L1vg31mdUqK0Ac/NjZoQunavoyzqdPYhFz9zzOezCrZKjuJDS3NRK9rspvjgM0xYR4d47oNZbdZbwkI4cTv/gcMlquRy0OvpfIvJtjtaJWMwTLtM5VhRusRuUlpH99UUVeXAAAAFQCVyX+92hBEjInEKL0v13c/egDCTQAAAIEAvFdWGq0ccOPbw4f/F8LpZqvWDydAcpXHV3thwb7WkFfppvm4SZte0zds1FJ+Hr8Xzzc5zMHe6J4Nlay/rP4ewmIW7iFKNBEYb/yWa+ceLrs+TfR672TaAgO6o7iSRofEq5YLdwgrwkMmIawa21FrZ2D9SPao/IwvENzk/xcHu7YAAACAQFXQH6HQnxOrw4dqf0NqeKy1tfIPxYYUZhPJfo9O0AmBW2S36pD2l14kS89fvz6Y1g8gN/FwFnRncMzlLY/hX70FSc/3hKBSbH6C6j8hwlgFKfizav21eS358JJz93leOakJZnGb8XlWvz1UJbwCsnR2VEY8Dz90uIk1l/UqHkA= loic@call", "expires_at": "2016-01-21T00:00:00.000Z" } +``` + +将返回状态为`201 Created`成功的已创建密钥. 如果发生错误,则会返回`400 Bad Request` ,并附有一条解释该错误的消息: + +``` +{ "message": { "fingerprint": [ "has already been taken" ], "key": [ "has already been taken" ] } } +``` + +## Add SSH key for user[](#add-ssh-key-for-user "Permalink") + +创建指定用户拥有的新密钥. 仅适用于管理员 + +``` +POST /users/:id/keys +``` + +Parameters: + +* `id` (必填)-指定用户的 ID +* `title` (必填)-新的 SSH 密钥的标题 +* `key` (必填)-新的 SSH 密钥 +* `expires_at` (可选)-ISO 8601 格式的 SSH 密钥的到期日期( `YYYY-MM-DDTHH:MM:SSZ` ) + +**注意:**这还会添加一个审核事件,如[审核实例事件中所述](../administration/audit_events.html#instance-events-premium-only) . + +## Delete SSH key for current user[](#delete-ssh-key-for-current-user "Permalink") + +删除当前经过身份验证的用户拥有的密钥. 如果操作成功,则返回`204 No Content`状态代码;如果找不到资源,则返回`404` . + +``` +DELETE /user/keys/:key_id +``` + +Parameters: + +* `key_id` (必填) `key_id`密钥 ID + +## Delete SSH key for given user[](#delete-ssh-key-for-given-user "Permalink") + +删除指定用户拥有的密钥. 仅适用于管理员. + +``` +DELETE /users/:id/keys/:key_id +``` + +Parameters: + +* `id` (必填)-指定用户的 ID +* `key_id` (必填) `key_id`密钥 ID + +## List all GPG keys[](#list-all-gpg-keys "Permalink") + +获取当前已验证用户的 GPG 密钥的列表. + +``` +GET /user/gpg_keys +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/user/gpg_keys" +``` + +响应示例: + +``` +[ { "id": 1, "key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj\r\nt1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O\r\nCfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa\r\nqKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO\r\nVaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57\r\nvilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp\r\nIDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV\r\nCAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/\r\noO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5\r\ncrfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4\r\nbjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn\r\niE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp\r\no4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=\r\n=XQoy\r\n-----END PGP PUBLIC KEY BLOCK-----", "created_at": "2017-09-05T09:17:46.264Z" } ] +``` + +## Get a specific GPG key[](#get-a-specific-gpg-key "Permalink") + +获取当前已认证用户的特定 GPG 密钥. + +``` +GET /user/gpg_keys/:key_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `key_id` | integer | yes | GPG 密钥的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/user/gpg_keys/1" +``` + +响应示例: + +``` + { "id": 1, "key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj\r\nt1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O\r\nCfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa\r\nqKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO\r\nVaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57\r\nvilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp\r\nIDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV\r\nCAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/\r\noO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5\r\ncrfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4\r\nbjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn\r\niE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp\r\no4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=\r\n=XQoy\r\n-----END PGP PUBLIC KEY BLOCK-----", "created_at": "2017-09-05T09:17:46.264Z" } +``` + +## Add a GPG key[](#add-a-gpg-key "Permalink") + +创建由当前身份验证用户拥有的新 GPG 密钥. + +``` +POST /user/gpg_keys +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| key | string | yes | 新的 GPG 密钥 | + +``` +curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/user/gpg_keys" +``` + +响应示例: + +``` +[ { "id": 1, "key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj\r\nt1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O\r\nCfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa\r\nqKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO\r\nVaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57\r\nvilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp\r\nIDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV\r\nCAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/\r\noO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5\r\ncrfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4\r\nbjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn\r\niE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp\r\no4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=\r\n=XQoy\r\n-----END PGP PUBLIC KEY BLOCK-----", "created_at": "2017-09-05T09:17:46.264Z" } ] +``` + +## Delete a GPG key[](#delete-a-gpg-key "Permalink") + +删除当前经过身份验证的用户拥有的 GPG 密钥. + +``` +DELETE /user/gpg_keys/:key_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `key_id` | integer | yes | GPG 密钥的 ID | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/user/gpg_keys/1" +``` + +成功时返回`204 No Content` ,如果`404 Not found`密钥,则返回`404 Not found` found. + +## List all GPG keys for given user[](#list-all-gpg-keys-for-given-user "Permalink") + +获取指定用户的 GPG 密钥的列表. 仅适用于管理员. + +``` +GET /users/:id/gpg_keys +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 用户的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/2/gpg_keys" +``` + +响应示例: + +``` +[ { "id": 1, "key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj\r\nt1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O\r\nCfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa\r\nqKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO\r\nVaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57\r\nvilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp\r\nIDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV\r\nCAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/\r\noO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5\r\ncrfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4\r\nbjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn\r\niE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp\r\no4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=\r\n=XQoy\r\n-----END PGP PUBLIC KEY BLOCK-----", "created_at": "2017-09-05T09:17:46.264Z" } ] +``` + +## Get a specific GPG key for a given user[](#get-a-specific-gpg-key-for-a-given-user "Permalink") + +获取给定用户的特定 GPG 密钥. 仅适用于管理员. + +``` +GET /users/:id/gpg_keys/:key_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 用户的 ID | +| `key_id` | integer | yes | GPG 密钥的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/2/gpg_keys/1" +``` + +响应示例: + +``` + { "id": 1, "key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj\r\nt1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O\r\nCfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa\r\nqKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO\r\nVaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57\r\nvilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp\r\nIDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV\r\nCAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/\r\noO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5\r\ncrfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4\r\nbjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn\r\niE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp\r\no4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=\r\n=XQoy\r\n-----END PGP PUBLIC KEY BLOCK-----", "created_at": "2017-09-05T09:17:46.264Z" } +``` + +## Add a GPG key for a given user[](#add-a-gpg-key-for-a-given-user "Permalink") + +创建指定用户拥有的新 GPG 密钥. 仅适用于管理员. + +``` +POST /users/:id/gpg_keys +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 用户的 ID | +| `key_id` | integer | yes | GPG 密钥的 ID | + +``` +curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/2/gpg_keys" +``` + +响应示例: + +``` +[ { "id": 1, "key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj\r\nt1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O\r\nCfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa\r\nqKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO\r\nVaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57\r\nvilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp\r\nIDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV\r\nCAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/\r\noO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5\r\ncrfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4\r\nbjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn\r\niE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp\r\no4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=\r\n=XQoy\r\n-----END PGP PUBLIC KEY BLOCK-----", "created_at": "2017-09-05T09:17:46.264Z" } ] +``` + +## Delete a GPG key for a given user[](#delete-a-gpg-key-for-a-given-user "Permalink") + +删除指定用户拥有的 GPG 密钥. 仅适用于管理员. + +``` +DELETE /users/:id/gpg_keys/:key_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 用户的 ID | +| `key_id` | integer | yes | The ID of the GPG key | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/2/gpg_keys/1" +``` + +## List emails[](#list-emails "Permalink") + +获取当前经过身份验证的用户电子邮件列表. + +``` +GET /user/emails +``` + +``` +[ { "id": 1, "email": "email@example.com" }, { "id": 3, "email": "email2@example.com" } ] +``` + +Parameters: + +* **none** + +## List emails for user[](#list-emails-for-user "Permalink") + +获取指定用户的电子邮件列表. 仅适用于管理员 + +``` +GET /users/:id/emails +``` + +Parameters: + +* `id` (必填)-指定用户的 ID + +## Single email[](#single-email "Permalink") + +收到一封电子邮件. + +``` +GET /user/emails/:email_id +``` + +Parameters: + +* `email_id` (必填)-电子邮件 ID + +``` +{ "id": 1, "email": "email@example.com" } +``` + +## Add email[](#add-email "Permalink") + +创建由当前身份验证用户拥有的新电子邮件. + +``` +POST /user/emails +``` + +Parameters: + +* `email` (必填)-电子邮件地址 + +``` +{ "id": 4, "email": "email@example.com" } +``` + +将返回状态为`201 Created`成功的已创建电子邮件. 如果发生错误,则会返回`400 Bad Request` ,并附有一条解释该错误的消息: + +``` +{ "message": { "email": [ "has already been taken" ] } } +``` + +## Add email for user[](#add-email-for-user "Permalink") + +创建指定用户拥有的新电子邮件. 仅适用于管理员 + +``` +POST /users/:id/emails +``` + +Parameters: + +* `id` (必填)-指定用户的 ID +* `email` (必填)-电子邮件地址 +* `skip_confirmation` (可选)-跳过确认并假定电子邮件已通过验证`skip_confirmation`或 false(默认) + +## Delete email for current user[](#delete-email-for-current-user "Permalink") + +删除当前经过身份验证的用户拥有的电子邮件. 如果操作成功,则返回`204 No Content`状态代码;如果找不到资源,则返回`404` . + +``` +DELETE /user/emails/:email_id +``` + +Parameters: + +* `email_id` (必填)-电子邮件 ID + +## Delete email for given user[](#delete-email-for-given-user "Permalink") + +删除指定用户拥有的电子邮件. 仅适用于管理员. + +``` +DELETE /users/:id/emails/:email_id +``` + +Parameters: + +* `id` (必填)-指定用户的 ID +* `email_id` (必填)-电子邮件 ID + +## Block user[](#block-user "Permalink") + +阻止指定的用户. 仅适用于管理员. + +``` +POST /users/:id/block +``` + +Parameters: + +* `id` (必填)-指定用户的 ID + +Returns: + +* `201 OK`成功成功. +* `404 User Not Found`如果`404 User Not Found`用户,则`404 User Not Found`用户. +* `403 Forbidden`尝试通过 LDAP 同步阻止已阻止的用户时禁止. + +## Unblock user[](#unblock-user "Permalink") + +取消阻止指定的用户. 仅适用于管理员. + +``` +POST /users/:id/unblock +``` + +Parameters: + +* `id` (必填)-指定用户的 ID + +尝试取消阻止被 LDAP 同步阻止的用户时,成功返回`201 OK` ,成功返回`404 User Not Found`或`403 Forbidden` . + +## Deactivate user[](#deactivate-user "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) . + +停用指定的用户. 仅适用于管理员. + +``` +POST /users/:id/deactivate +``` + +Parameters: + +* `id` (必填)-指定用户的 ID + +Returns: + +* `201 OK`成功成功. +* `404 User Not Found`如果`404 User Not Found`用户,则`404 User Not Found`用户. +* `403 Forbidden`尝试停用用户时被禁止: + * 被管理员或 LDAP 同步阻止. + * 在过去 180 天内没有任何活动. 这些用户无法停用. + +## Activate user[](#activate-user "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) . + +激活指定的用户. 仅适用于管理员. + +``` +POST /users/:id/activate +``` + +Parameters: + +* `id` (必填)-指定用户的 ID + +Returns: + +* `201 OK`成功成功. +* `404 User Not Found`如果`404 User Not Found`用户,则`404 User Not Found`用户. +* `403 Forbidden`尝试激活被管理员或 LDAP 同步阻止的用户时禁止. + +### Get user contribution events[](#get-user-contribution-events "Permalink") + +请参阅[事件 API 文档](events.html#get-user-contribution-events) + +## Get all impersonation tokens of a user[](#get-all-impersonation-tokens-of-a-user "Permalink") + +> 需要管理员权限. + +它检索用户的每个模拟令牌. 使用分页参数`page`和`per_page`可以限制模拟令牌的列表. + +``` +GET /users/:user_id/impersonation_tokens +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | integer | yes | 用户的 ID | +| `state` | string | no | 根据状态( `all` , `active` , `inactive` )过滤令牌 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/42/impersonation_tokens" +``` + +响应示例: + +``` +[ { "active" : true, "scopes" : [ "api" ], "revoked" : false, "name" : "mytoken", "id" : 2, "created_at" : "2017-03-17T17:18:09.283Z", "impersonation" : true, "expires_at" : "2017-04-04" }, { "active" : false, "scopes" : [ "read_user" ], "revoked" : true, "name" : "mytoken2", "created_at" : "2017-03-17T17:19:28.697Z", "id" : 3, "impersonation" : true, "expires_at" : "2017-04-14" } ] +``` + +## Get an impersonation token of a user[](#get-an-impersonation-token-of-a-user "Permalink") + +> 需要管理员权限. + +它显示了用户的模拟令牌. + +``` +GET /users/:user_id/impersonation_tokens/:impersonation_token_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | integer | yes | 用户的 ID | +| `impersonation_token_id` | integer | yes | 模拟令牌的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/42/impersonation_tokens/2" +``` + +响应示例: + +``` +{ "active" : true, "scopes" : [ "api" ], "revoked" : false, "name" : "mytoken", "id" : 2, "created_at" : "2017-03-17T17:18:09.283Z", "impersonation" : true, "expires_at" : "2017-04-04" } +``` + +## Create an impersonation token[](#create-an-impersonation-token "Permalink") + +> 需要管理员权限. 令牌值返回一次. 确保将其保存-您将无法再次访问它. + +它创建一个新的模拟令牌. 请注意,只有管理员可以执行此操作. 您只能创建模拟令牌来模拟用户,并执行 API 调用和 Git 读写. 用户将不会在其个人资料设置页面中看到这些令牌. + +``` +POST /users/:user_id/impersonation_tokens +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | integer | yes | 用户的 ID | +| `name` | string | yes | 模拟令牌的名称 | +| `expires_at` | date | no | ISO 格式( `YYYY-MM-DD` )的模拟令牌的到期日期 | +| `scopes` | array | yes | 模拟令牌作用域的数组( `api` , `read_user` ) | + +``` +curl --request POST --header "PRIVATE-TOKEN: " --data "name=mytoken" --data "expires_at=2017-04-04" --data "scopes[]=api" "https://gitlab.example.com/api/v4/users/42/impersonation_tokens" +``` + +响应示例: + +``` +{ "id" : 2, "revoked" : false, "scopes" : [ "api" ], "token" : "EsMo-vhKfXGwX9RKrwiy", "active" : true, "impersonation" : true, "name" : "mytoken", "created_at" : "2017-03-17T17:18:09.283Z", "expires_at" : "2017-04-04" } +``` + +## Revoke an impersonation token[](#revoke-an-impersonation-token "Permalink") + +> 需要管理员权限. + +它撤销模拟令牌. + +``` +DELETE /users/:user_id/impersonation_tokens/:impersonation_token_id +``` + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/42/impersonation_tokens/1" +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user_id` | integer | yes | 用户的 ID | +| `impersonation_token_id` | integer | yes | 模拟令牌的 ID | + +### Get user activities (admin only)[](#get-user-activities-admin-only "Permalink") + +**注意:**此 API 端点仅在 8.15(EE)和 9.1(CE)及更高版本上可用. + +获取所有用户的上次活动日期,从最旧到最新. + +更新时间戳记的活动是: + +* Git HTTP / SSH 活动(例如克隆,推送) +* 用户登录 GitLab +* 与仪表板,项目,问题和合并请求相关的用户访问页面(在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54947) ) +* 用户使用 API +* 用户使用 GraphQL API + +默认情况下,它显示最近 6 个月内所有用户的活动,但是可以使用`from`参数进行修改. + +``` +GET /user/activities +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `from` | string | no | 日期字符串,格式为 YEAR-MONTH-DAY. 例如, `2016-03-11` . 默认为 6 个月前. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/user/activities" +``` + +响应示例: + +``` +[ { "username": "user1", "last_activity_on": "2015-12-14", "last_activity_at": "2015-12-14" }, { "username": "user2", "last_activity_on": "2015-12-15", "last_activity_at": "2015-12-15" }, { "username": "user3", "last_activity_on": "2015-12-16", "last_activity_at": "2015-12-16" } ] +``` + +请注意, `last_activity_at`已过时,请使用`last_activity_on` . + +## User memberships (admin only)[](#user-memberships-admin-only "Permalink") + +在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/20532) . + +列出用户所属的所有项目和组. 该端点仅适用于管理员. 它返回成员资格的`source_id` , `source_name` , `source_type`和`access_level` . 源可以是`Namespace` (代表一个组)或`Project` . 响应仅代表直接成员身份. 不包括继承的成员资格,例如在子组中. 访问级别由整数值表示. 有关更多详细信息,请阅读有关[访问级别值](access_requests.html#valid-access-levels)的含义. + +``` +GET /users/:id/memberships +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer | yes | 指定用户的 ID | +| `type` | string | no | 按类型过滤成员资格. 可以是`Project`或`Namespace` | + +Returns: + +* `200 OK`成功. +* `404 User Not Found` if user can’t be found. +* `403 Forbidden`管理员未要求时禁止. +* 不支持请求的类型时出现`400 Bad Request` . + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/users/:user_id/memberships" +``` + +响应示例: + +``` +[ { "source_id": 1, "source_name": "Project one", "source_type": "Project", "access_level": "20" }, { "source_id": 3, "source_name": "Group three", "source_type": "Namespace", "access_level": "20" }, ] +``` \ No newline at end of file diff --git a/docs/378.md b/docs/378.md new file mode 100644 index 0000000000000000000000000000000000000000..76e2cea8ba0695f5cbd398678490fa90a2bb1bbd --- /dev/null +++ b/docs/378.md @@ -0,0 +1,159 @@ +# Project-level Variables API + +> 原文:[https://docs.gitlab.com/ee/api/project_level_variables.html](https://docs.gitlab.com/ee/api/project_level_variables.html) + +* [List project variables](#list-project-variables) +* [Show variable details](#show-variable-details) +* [Create variable](#create-variable) +* [Update variable](#update-variable) +* [Remove variable](#remove-variable) +* [The `filter` parameter](#the-filter-parameter) + * [Enable or disable](#enable-or-disable) + +# Project-level Variables API[](#project-level-variables-api "Permalink") + +## List project variables[](#list-project-variables "Permalink") + +获取项目变量的列表. + +``` +GET /projects/:id/variables +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 一个项目的 ID 或经过身份验证的用户拥有[的该项目的 Urlencoded NAMESPACE / PROJECT_NAME](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/variables" +``` + +``` +[ { "key": "TEST_VARIABLE_1", "variable_type": "env_var", "value": "TEST_1" }, { "key": "TEST_VARIABLE_2", "variable_type": "env_var", "value": "TEST_2" } ] +``` + +## Show variable details[](#show-variable-details "Permalink") + +获取项目特定变量的详细信息. + +``` +GET /projects/:id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 一个项目的 ID 或经过身份验证的用户拥有[的该项目的 Urlencoded NAMESPACE / PROJECT_NAME](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` | +| `filter` | hash | no | 可用的过滤器: `[environment_scope]` . 请参阅[`filter`参数详细信息](#the-filter-parameter) . | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/variables/TEST_VARIABLE_1" +``` + +``` +{ "key": "TEST_VARIABLE_1", "variable_type": "env_var", "value": "TEST_1", "protected": false, "masked": true } +``` + +## Create variable[](#create-variable "Permalink") + +创建一个新变量. + +``` +POST /projects/:id/variables +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 一个项目的 ID 或经过身份验证的用户拥有[的该项目的 Urlencoded NAMESPACE / PROJECT_NAME](README.html#namespaced-path-encoding) | +| `key` | string | yes | The `key` of a variable; must have no more than 255 characters; only `A-Z`, `a-z`, `0-9`, and `_` are allowed | +| `value` | string | yes | 变量的`value` | +| `variable_type` | string | no | 变量的类型. 可用类型为: `env_var` (默认)和`file` | +| `protected` | boolean | no | 变量是否受保护 | +| `masked` | boolean | no | 变量是否被屏蔽 | +| `environment_scope` | string | no | 变量的`environment_scope` | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/variables" --form "key=NEW_VARIABLE" --form "value=new value" +``` + +``` +{ "key": "NEW_VARIABLE", "value": "new value", "protected": false, "variable_type": "env_var", "masked": false, "environment_scope": "*" } +``` + +## Update variable[](#update-variable "Permalink") + +更新项目的变量. + +``` +PUT /projects/:id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 一个项目的 ID 或经过身份验证的用户拥有[的该项目的 Urlencoded NAMESPACE / PROJECT_NAME](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` | +| `value` | string | yes | 变量的`value` | +| `variable_type` | string | no | 变量的类型. 可用类型为: `env_var` (默认)和`file` | +| `protected` | boolean | no | 变量是否受保护 | +| `masked` | boolean | no | 变量是否被屏蔽 | +| `environment_scope` | string | no | 变量的`environment_scope` | +| `filter` | hash | no | 可用的过滤器: `[environment_scope]` . 请参阅[`filter`参数详细信息](#the-filter-parameter) . | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/variables/NEW_VARIABLE" --form "value=updated value" +``` + +``` +{ "key": "NEW_VARIABLE", "value": "updated value", "variable_type": "env_var", "protected": true, "masked": false, "environment_scope": "*" } +``` + +## Remove variable[](#remove-variable "Permalink") + +删除项目的变量. + +``` +DELETE /projects/:id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 一个项目的 ID 或经过身份验证的用户拥有[的该项目的 Urlencoded NAMESPACE / PROJECT_NAME](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` | +| `filter` | hash | no | 可用的过滤器: `[environment_scope]` . 请参阅[`filter`参数详细信息](#the-filter-parameter) . | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/variables/VARIABLE_1" +``` + +## The `filter` parameter[](#the-filter-parameter "Permalink") + +版本历史 + +* 在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34490) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上已禁用. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员启用它. + +此参数用于按属性(例如`environment_scope`进行过滤. + +用法示例: + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/variables/VARIABLE_1?filter[environment_scope]=production" +``` + +### Enable or disable[](#enable-or-disable "Permalink") + +[有权访问 GitLab Rails 控制台的 GitLab 管理员](../administration/feature_flags.html)可以为您的实例启用它. + +要启用它: + +``` +Feature.enable(:ci_variables_api_filter_environment_scope) +``` + +禁用它: + +``` +Feature.disable(:ci_variables_api_filter_environment_scope) +``` \ No newline at end of file diff --git a/docs/379.md b/docs/379.md new file mode 100644 index 0000000000000000000000000000000000000000..b6410d0b1091e5fb0a46f893d60c55efc2b23a1a --- /dev/null +++ b/docs/379.md @@ -0,0 +1,121 @@ +# Group-level Variables API + +> 原文:[https://docs.gitlab.com/ee/api/group_level_variables.html](https://docs.gitlab.com/ee/api/group_level_variables.html) + +* [List group variables](#list-group-variables) +* [Show variable details](#show-variable-details) +* [Create variable](#create-variable) +* [Update variable](#update-variable) +* [Remove variable](#remove-variable) + +# Group-level Variables API[](#group-level-variables-api "Permalink") + +在 GitLab 9.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34519) + +## List group variables[](#list-group-variables "Permalink") + +获取组变量的列表. + +``` +GET /groups/:id/variables +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有的组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/variables" +``` + +``` +[ { "key": "TEST_VARIABLE_1", "variable_type": "env_var", "value": "TEST_1", "protected": false, "masked": false }, { "key": "TEST_VARIABLE_2", "variable_type": "env_var", "value": "TEST_2", "protected": false, "masked": false } ] +``` + +## Show variable details[](#show-variable-details "Permalink") + +获取组特定变量的详细信息. + +``` +GET /groups/:id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有的组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/variables/TEST_VARIABLE_1" +``` + +``` +{ "key": "TEST_VARIABLE_1", "variable_type": "env_var", "value": "TEST_1", "protected": false, "masked": false } +``` + +## Create variable[](#create-variable "Permalink") + +创建一个新变量. + +``` +POST /groups/:id/variables +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有的组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` ; 不得超过 255 个字符; 仅允许`AZ` , `az` , `0-9`和`_` | +| `value` | string | yes | 变量的`value` | +| `variable_type` | string | no | 变量的类型. 可用类型为: `env_var` (默认)和`file` | +| `protected` | boolean | no | 变量是否受保护 | +| `masked` | boolean | no | 变量是否被屏蔽 | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/variables" --form "key=NEW_VARIABLE" --form "value=new value" +``` + +``` +{ "key": "NEW_VARIABLE", "value": "new value", "variable_type": "env_var", "protected": false, "masked": false } +``` + +## Update variable[](#update-variable "Permalink") + +更新组的变量. + +``` +PUT /groups/:id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有的组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` | +| `value` | string | yes | 变量的`value` | +| `variable_type` | string | no | 变量的类型. 可用类型为: `env_var` (默认)和`file` | +| `protected` | boolean | no | 变量是否受保护 | +| `masked` | boolean | no | 变量是否被屏蔽 | + +``` +curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/variables/NEW_VARIABLE" --form "value=updated value" +``` + +``` +{ "key": "NEW_VARIABLE", "value": "updated value", "variable_type": "env_var", "protected": true, "masked": true } +``` + +## Remove variable[](#remove-variable "Permalink") + +删除组的变量. + +``` +DELETE /groups/:id/variables/:key +``` + +| Attribute | Type | required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户拥有的组的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `key` | string | yes | 变量的`key` | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/1/variables/VARIABLE_1" +``` \ No newline at end of file diff --git a/docs/380.md b/docs/380.md new file mode 100644 index 0000000000000000000000000000000000000000..af745d25421b333b1ea5f8634bd8d9ac500f3bf7 --- /dev/null +++ b/docs/380.md @@ -0,0 +1,23 @@ +# Version API + +> 原文:[https://docs.gitlab.com/ee/api/version.html](https://docs.gitlab.com/ee/api/version.html) + +# Version API[](#version-api "Permalink") + +**注意:**此功能是在 GitLab 8.13 中引入的 + +检索此 GitLab 实例的版本信息. 对已认证的用户响应`200 OK` . + +``` +GET /version +``` + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/version" +``` + +响应示例: + +``` +{ "version": "8.13.0-pre", "revision": "4e963fe" } +``` \ No newline at end of file diff --git a/docs/381.md b/docs/381.md new file mode 100644 index 0000000000000000000000000000000000000000..e9b70c80abfc83455648ecb04d09a495c5a03acf --- /dev/null +++ b/docs/381.md @@ -0,0 +1,112 @@ +# Vulnerabilities API + +> 原文:[https://docs.gitlab.com/ee/api/vulnerabilities.html](https://docs.gitlab.com/ee/api/vulnerabilities.html) + +* [Single vulnerability](#single-vulnerability) +* [Confirm vulnerability](#confirm-vulnerability) +* [Resolve vulnerability](#resolve-vulnerability) +* [Dismiss vulnerability](#dismiss-vulnerability) + +# Vulnerabilities API[](#vulnerabilities-api-ultimate "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10242) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6. + +**注意:**以前的 Vulnerabilities API 已重命名为 Vulnerability Findings API,其文档已移至[其他位置](vulnerability_findings.html) . 现在,本文描述了新的漏洞 API,该 API 提供对[独立漏洞的](https://gitlab.com/groups/gitlab-org/-/epics/634)访问.**警告:**此 API 处于 alpha 阶段,被认为是不稳定的. 响应有效载荷可能会在 GitLab 版本之间发生更改或损坏. + +每个对漏洞的 API 调用都必须经过[身份验证](README.html#authentication) . + +漏洞权限从其项目继承权限. 如果项目是私有项目,并且用户不是该漏洞所属项目的成员,则对该项目的请求将返回`404 Not Found`状态代码. + +## Single vulnerability[](#single-vulnerability "Permalink") + +获得一个漏洞 + +``` +GET /vulnerabilities/:id +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 要获取的漏洞的 ID | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/vulnerabilities/1" +``` + +响应示例: + +``` +{ "id": 1, "title": "Predictable pseudorandom number generator", "description": null, "state": "opened", "severity": "medium", "confidence": "medium", "report_type": "sast", "project": { "id": 32, "name": "security-reports", "full_path": "/gitlab-examples/security/security-reports", "full_name": "gitlab-examples / security / security-reports" }, "author_id": 1, "updated_by_id": null, "last_edited_by_id": null, "closed_by_id": null, "start_date": null, "due_date": null, "created_at": "2019-10-13T15:08:40.219Z", "updated_at": "2019-10-13T15:09:40.382Z", "last_edited_at": null, "closed_at": null } +``` + +## Confirm vulnerability[](#confirm-vulnerability "Permalink") + +确认给定漏洞. 如果已经确认该漏洞,则返回状态码`304` . + +如果经过身份验证的用户无权[确认漏洞](../user/permissions.html#project-members-permissions) ,则此请求将导致`403`状态代码. + +``` +POST /vulnerabilities/:id/confirm +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 确认漏洞的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/vulnerabilities/5/confirm" +``` + +响应示例: + +``` +{ "id": 2, "title": "Predictable pseudorandom number generator", "description": null, "state": "confirmed", "severity": "medium", "confidence": "medium", "report_type": "sast", "project": { "id": 32, "name": "security-reports", "full_path": "/gitlab-examples/security/security-reports", "full_name": "gitlab-examples / security / security-reports" }, "author_id": 1, "updated_by_id": null, "last_edited_by_id": null, "closed_by_id": null, "start_date": null, "due_date": null, "created_at": "2019-10-13T15:08:40.219Z", "updated_at": "2019-10-13T15:09:40.382Z", "last_edited_at": null, "closed_at": null } +``` + +## Resolve vulnerability[](#resolve-vulnerability "Permalink") + +解决给定漏洞. 如果漏洞已解决,则返回状态码`304` . + +如果经过身份验证的用户无权[解决漏洞](../user/permissions.html#project-members-permissions) ,则此请求将导致`403`状态代码. + +``` +POST /vulnerabilities/:id/resolve +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 解决的漏洞的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/vulnerabilities/5/resolve" +``` + +响应示例: + +``` +{ "id": 2, "title": "Predictable pseudorandom number generator", "description": null, "state": "resolved", "severity": "medium", "confidence": "medium", "report_type": "sast", "project": { "id": 32, "name": "security-reports", "full_path": "/gitlab-examples/security/security-reports", "full_name": "gitlab-examples / security / security-reports" }, "author_id": 1, "updated_by_id": null, "last_edited_by_id": null, "closed_by_id": null, "start_date": null, "due_date": null, "created_at": "2019-10-13T15:08:40.219Z", "updated_at": "2019-10-13T15:09:40.382Z", "last_edited_at": null, "closed_at": null } +``` + +## Dismiss vulnerability[](#dismiss-vulnerability "Permalink") + +消除给定的漏洞. 如果漏洞已被`304`则返回状态码`304` . + +If an authenticated user does not have permission to [dismiss vulnerabilities](../user/permissions.html#project-members-permissions), this request will result in a `403` status code. + +``` +POST /vulnerabilities/:id/dismiss +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | 整数或字符串 | yes | 消除漏洞的 ID | + +``` +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/vulnerabilities/5/dismiss" +``` + +响应示例: + +``` +{ "id": 2, "title": "Predictable pseudorandom number generator", "description": null, "state": "closed", "severity": "medium", "confidence": "medium", "report_type": "sast", "project": { "id": 32, "name": "security-reports", "full_path": "/gitlab-examples/security/security-reports", "full_name": "gitlab-examples / security / security-reports" }, "author_id": 1, "updated_by_id": null, "last_edited_by_id": null, "closed_by_id": null, "start_date": null, "due_date": null, "created_at": "2019-10-13T15:08:40.219Z", "updated_at": "2019-10-13T15:09:40.382Z", "last_edited_at": null, "closed_at": null } +``` \ No newline at end of file diff --git a/docs/382.md b/docs/382.md new file mode 100644 index 0000000000000000000000000000000000000000..e7acf908a72a714b3fa2844bc28380fcbd03082b --- /dev/null +++ b/docs/382.md @@ -0,0 +1,65 @@ +# Vulnerability Findings API + +> 原文:[https://docs.gitlab.com/ee/api/vulnerability_findings.html](https://docs.gitlab.com/ee/api/vulnerability_findings.html) + +* [Vulnerability findings pagination](#vulnerability-findings-pagination) +* [List project vulnerability findings](#list-project-vulnerability-findings) + +# Vulnerability Findings API[](#vulnerability-findings-api-ultimate "Permalink") + +在 GitLab Ultimate 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19029) . + +**注意:**此 API 资源已从"漏洞"重命名为"漏洞发现",因为这些漏洞是为服务即将到来的[独立漏洞对象](https://gitlab.com/gitlab-org/gitlab/-/issues/13561)而保留的. 要修复与以前的 Vulnerabilities API 的任何损坏的集成,请将`vulnerabilities` URL 部分更改为`vulnerabilities` _ `vulnerability_findings` . + +每个对漏洞发现的 API 调用都必须经过[身份验证](README.html#authentication) . + +漏洞发现是项目约束的实体. 如果用户不是项目成员,并且该项目是私有项目,则对该项目的请求将产生`404`状态代码. + +如果用户能够访问该项目但无权[使用 Project Security 仪表板](../user/permissions.html#project-members-permissions) ,则任何对此项目的漏洞发现的请求都将生成`403`状态代码. + +**警告:**此 API 处于 alpha 阶段,被认为是不稳定的. 响应有效载荷可能会在 GitLab 版本之间发生更改或损坏. + +## Vulnerability findings pagination[](#vulnerability-findings-pagination "Permalink") + +默认情况下,因为 API 结果是分页的,所以`GET`请求一次返回 20 个结果. + +阅读有关[分页的](README.html#pagination)更多信息. + +## List project vulnerability findings[](#list-project-vulnerability-findings "Permalink") + +列出项目的所有漏洞发现. + +``` +GET /projects/:id/vulnerability_findings +GET /projects/:id/vulnerability_findings?report_type=sast +GET /projects/:id/vulnerability_findings?report_type=container_scanning +GET /projects/:id/vulnerability_findings?report_type=sast,dast +GET /projects/:id/vulnerability_findings?scope=all +GET /projects/:id/vulnerability_findings?scope=dismissed +GET /projects/:id/vulnerability_findings?severity=high +GET /projects/:id/vulnerability_findings?confidence=unknown,experimental +GET /projects/:id/vulnerability_findings?scanner=bandit,find_sec_bugs +GET /projects/:id/vulnerability_findings?pipeline_id=42 +``` + +**弃用:**从 GitLab 12.9 开始,不再报告`undefined`严重性和可信度级别. + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 经过身份验证的用户[所属的项目](README.html#namespaced-path-encoding)的 ID 或[URL 编码路径](README.html#namespaced-path-encoding) . | +| `report_type` | 字符串数组 | no | 返回属于指定报告类型的漏洞发现. 有效值: `sast` , `dast` , `dependency_scanning`或`container_scanning` . 默认为全部. | +| `scope` | string | no | 返回给定范围内的漏洞发现结果: `all`或已`dismissed` . 默认为`dismissed` . | +| `severity` | 字符串数组 | no | 返回属于指定严重性级别的漏洞发现: `info` , `unknown` , `low` , `medium` , `high`或`critical` . 默认为全部. | +| `confidence` | 字符串数组 | no | 返回属于指定置信度的漏洞发现: `ignore` , `unknown` , `experimental` , `low` , `medium` , `high`或`confirmed` . 默认为全部. | +| `scanner` | 字符串数组 | no | 返回指定扫描程序检测到的漏洞发现. | +| `pipeline_id` | integer/string | no | 返回属于指定管道的漏洞发现. | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/vulnerability_findings" +``` + +Example response: + +``` +[ { "id": null, "report_type": "dependency_scanning", "name": "Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js", "severity": "unknown", "confidence": "undefined", "scanner": { "external_id": "gemnasium", "name": "Gemnasium" }, "identifiers": [ { "external_type": "gemnasium", "external_id": "9952e574-7b5b-46fa-a270-aeb694198a98", "name": "Gemnasium-9952e574-7b5b-46fa-a270-aeb694198a98", "url": "https://deps.sec.gitlab.com/packages/npm/saml2-js/versions/1.5.0/advisories" }, { "external_type": "cve", "external_id": "CVE-2017-11429", "name": "CVE-2017-11429", "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429" } ], "project_fingerprint": "fa6f5b6c5d240b834ac5e901dc69f9484cef89ec", "create_vulnerability_feedback_issue_path": "/tests/yarn-remediation-test/vulnerability_feedback", "create_vulnerability_feedback_merge_request_path": "/tests/yarn-remediation-test/vulnerability_feedback", "create_vulnerability_feedback_dismissal_path": "/tests/yarn-remediation-test/vulnerability_feedback", "project": { "id": 31, "name": "yarn-remediation-test", "full_path": "/tests/yarn-remediation-test", "full_name": "tests / yarn-remediation-test" }, "dismissal_feedback": null, "issue_feedback": null, "merge_request_feedback": null, "description": "Some XML DOM traversal and canonicalization APIs may be inconsistent in handling of comments within XML nodes. Incorrect use of these APIs by some SAML libraries results in incorrect parsing of the inner text of XML nodes such that any inner text after the comment is lost prior to cryptographically signing the SAML message. Text after the comment therefore has no impact on the signature on the SAML message.\r\n\r\nA remote attacker can modify SAML content for a SAML service provider without invalidating the cryptographic signature, which may allow attackers to bypass primary authentication for the affected SAML service provider.", "links": [ { "url": "https://github.com/Clever/saml2/commit/3546cb61fd541f219abda364c5b919633609ef3d#diff-af730f9f738de1c9ad87596df3f6de84R279" }, { "url": "https://www.kb.cert.org/vuls/id/475445" }, { "url": "https://github.com/Clever/saml2/issues/127" } ], "location": { "file": "yarn.lock", "dependency": { "package": { "name": "saml2-js" }, "version": "1.5.0" } }, "solution": "Upgrade to fixed version.\r\n", "blob_path": "/tests/yarn-remediation-test/blob/cc6c4a0778460455ae5d16ca7025ca9ca1ca75ac/yarn.lock" } ] +``` \ No newline at end of file diff --git a/docs/383.md b/docs/383.md new file mode 100644 index 0000000000000000000000000000000000000000..6dd92f491b4727c6702594a3dfce815b8cbdfe6f --- /dev/null +++ b/docs/383.md @@ -0,0 +1,158 @@ +# Wikis API + +> 原文:[https://docs.gitlab.com/ee/api/wikis.html](https://docs.gitlab.com/ee/api/wikis.html) + +* [List wiki pages](#list-wiki-pages) +* [Get a wiki page](#get-a-wiki-page) +* [Create a new wiki page](#create-a-new-wiki-page) +* [Edit an existing wiki page](#edit-an-existing-wiki-page) +* [Delete a wiki page](#delete-a-wiki-page) +* [Upload an attachment to the wiki repository](#upload-an-attachment-to-the-wiki-repository) + +# Wikis API[](#wikis-api "Permalink") + +在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13372) . + +仅在 APIv4 中可用. + +## List wiki pages[](#list-wiki-pages "Permalink") + +获取给定项目的所有 Wiki 页面. + +``` +GET /projects/:id/wikis +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `with_content` | boolean | no | 包含页面内容 | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/wikis?with_content=1" +``` + +响应示例: + +``` +[ { "content" : "Here is an instruction how to deploy this project.", "format" : "markdown", "slug" : "deploy", "title" : "deploy" }, { "content" : "Our development process is described here.", "format" : "markdown", "slug" : "development", "title" : "development" },{ "content" : "* [Deploy](deploy)\n* [Development](development)", "format" : "markdown", "slug" : "home", "title" : "home" } ] +``` + +## Get a wiki page[](#get-a-wiki-page "Permalink") + +获取给定项目的 Wiki 页面. + +``` +GET /projects/:id/wikis/:slug +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `slug` | string | yes | Wiki 页面的段(唯一字符串) | + +``` +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/wikis/home" +``` + +响应示例: + +``` +{ "content" : "home page", "format" : "markdown", "slug" : "home", "title" : "home" } +``` + +## Create a new wiki page[](#create-a-new-wiki-page "Permalink") + +使用给定的标题,条目和内容为给定的存储库创建一个新的 Wiki 页面. + +``` +POST /projects/:id/wikis +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `content` | string | yes | Wiki 页面的内容 | +| `title` | string | yes | 维基页面的标题 | +| `format` | string | no | Wiki 页面的格式. 可用格式为: `markdown` (默认), `rdoc` , `asciidoc`和`org` | + +``` +curl --data "format=rdoc&title=Hello&content=Hello world" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/wikis" +``` + +响应示例: + +``` +{ "content" : "Hello world", "format" : "markdown", "slug" : "Hello", "title" : "Hello" } +``` + +## Edit an existing wiki page[](#edit-an-existing-wiki-page "Permalink") + +更新现有的 Wiki 页面. 至少需要一个参数才能更新 Wiki 页面. + +``` +PUT /projects/:id/wikis/:slug +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `content` | string | 是,如果未提供`title` | Wiki 页面的内容 | +| `title` | string | 是,如果未提供`content` | 维基页面的标题 | +| `format` | string | no | Wiki 页面的格式. 可用格式为: `markdown` (默认), `rdoc` , `asciidoc`和`org` | +| `slug` | string | yes | Wiki 页面的段(唯一字符串) | + +``` +curl --request PUT --data "format=rdoc&content=documentation&title=Docs" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/wikis/foo" +``` + +响应示例: + +``` +{ "content" : "documentation", "format" : "markdown", "slug" : "Docs", "title" : "Docs" } +``` + +## Delete a wiki page[](#delete-a-wiki-page "Permalink") + +删除带有给定子弹的 Wiki 页面. + +``` +DELETE /projects/:id/wikis/:slug +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `slug` | string | yes | Wiki 页面的段(唯一字符串) | + +``` +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/wikis/foo" +``` + +成功时,HTTP 状态代码为`204`并且不需要 JSON 响应. + +## Upload an attachment to the wiki repository[](#upload-an-attachment-to-the-wiki-repository "Permalink") + +将文件上传到 Wiki 信息库中的附件文件夹. 附件文件夹是`uploads`文件夹. + +``` +POST /projects/:id/wikis/attachments +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | integer/string | yes | 项目的 ID 或[URL 编码的路径](README.html#namespaced-path-encoding) | +| `file` | string | yes | 要上传的附件 | +| `branch` | string | no | 分支的名称. 默认为 Wiki 存储库默认分支 | + +要从文件系统上载文件,请使用`--form`参数. 这将导致 cURL 使用标题`Content-Type: multipart/form-data` . `file=`参数必须指向文件系统上的文件,并以`@`开头. 例如: + +``` +curl --request POST --header "PRIVATE-TOKEN: " --form "file=@dk.png" "https://gitlab.example.com/api/v4/projects/1/wikis/attachments" +``` + +响应示例: + +``` +{ "file_name" : "dk.png", "file_path" : "uploads/6a061c4cf9f1c28cb22c384b4b8d4e3c/dk.png", "branch" : "master", "link" : { "url" : "uploads/6a061c4cf9f1c28cb22c384b4b8d4e3c/dk.png", "markdown" : "![dk](uploads/6a061c4cf9f1c28cb22c384b4b8d4e3c/dk.png)" } } +``` \ No newline at end of file diff --git a/docs/384.md b/docs/384.md new file mode 100644 index 0000000000000000000000000000000000000000..d23f9437ea12cbd583049696fe92155b3dde10a9 --- /dev/null +++ b/docs/384.md @@ -0,0 +1,83 @@ +# GraphQL API + +> 原文:[https://docs.gitlab.com/ee/api/graphql/](https://docs.gitlab.com/ee/api/graphql/) + +* [Getting Started](#getting-started) + * [Quick Reference](#quick-reference) + * [GraphiQL](#graphiql) +* [What is GraphQL?](#what-is-graphql) +* [Vision](#vision) +* [Available queries](#available-queries) + * [Multiplex queries](#multiplex-queries) +* [Reference](#reference) + +# GraphQL API[](#graphql-api "Permalink") + +版本历史 + +* 在 GitLab 11.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19008) (由功能标志`graphql`启用). +* [始终](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30444)在 GitLab 12.1 中[启用](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30444) . + +## Getting Started[](#getting-started "Permalink") + +有关 GitLab GraphQL API 的新知识,请参见 GitLab GraphQL API [入门](getting_started.html) . + +### Quick Reference[](#quick-reference "Permalink") + +* GitLab 的 GraphQL API 端点位于`/api/graphql` . +* [从 graphql.org](https://s0graphql0org.icopy.site/)获得[GraphQL 的简介](https://s0graphql0org.icopy.site/) . +* GitLab 支持广泛的资源,在[GraphQL API Reference 中](reference/index.html)列出. + +#### GraphiQL[](#graphiql "Permalink") + +使用交互式[GraphiQL](https://gitlab.com/-/graphql-explorer)浏览器浏览 GraphQL API,或在`https:///-/graphql-explorer`上的自管理 GitLab 实例上`https:///-/graphql-explorer` . + +有关 GraphiQL Explorer 的更多信息,请参见[GitLab GraphQL 概述](getting_started.html#graphiql) . + +## What is GraphQL?[](#what-is-graphql "Permalink") + +[GraphQL](https://s0graphql0org.icopy.site/)是 API 的查询语言,它允许客户端准确地请求他们所需的数据,从而有可能在有限数量的请求中获得所有必需的数据. + +可以以类型的形式描述 GraphQL 数据(字段),从而允许客户端使用[客户端 GraphQL 库](https://s0graphql0org.icopy.site/code/)来使用 API​​并避免手动解析. + +由于没有固定的端点和数据模型,因此可以在不进行重大更改的情况下将新功能添加到 API. 这使我们可以拥有[GraphQL 文档](https://s0graphql0org.icopy.site/learn/best-practices/)中[所述的无](https://s0graphql0org.icopy.site/learn/best-practices/)版本 API. + +## Vision[](#vision "Permalink") + +我们希望 GraphQL API 是与 GitLab 进行编程交互的**主要**方式. 为此,它需要全面覆盖-REST API 中可能的一切在 GraphQL API 中也应该可行. + +为了帮助我们实现这一愿景,前端应优先使用 GraphQL 而不是 REST API 的新功能. + +There are no plans to deprecate the REST API. To reduce the technical burden of supporting two APIs in parallel, they should share implementations as much as possible. + +## Available queries[](#available-queries "Permalink") + +GraphQL API 在根级别包含以下查询: + +1. `project` :项目信息及其许多关联,例如问题和合并请求. +2. `group` :基本组信息和史诗 目前受支持. +3. `user` :有关特定用户的信息. +4. `namespace` :在名称空间内,也可以提取`projects` . +5. `currentUser` :有关当前登录用户的信息. +6. `users` :有关用户集合的信息. +7. `metaData` :有关 GitLab 和 GraphQL API 的元数据. +8. `snippets` :当前登录用户可见的`snippets` . + +新的关联和根级别对象正在不断添加. 有关最新信息,请参见《 [GraphQL API 参考](reference/index.html) 》. + +根级查询在[`app/graphql/types/query_type.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/graphql/types/query_type.rb) . + +### Multiplex queries[](#multiplex-queries "Permalink") + +GitLab 支持使用[apollo-link-batch-http 将](https://www.apollographql.com/docs/link/links/batch-http/)查询批量处理为单个请求. GitLab 在后端使用的库[GraphQL Ruby](https://graphql-ruby.org/queries/multiplex.html)也提供了有关多路查询的更多信息. + +## Reference[](#reference "Permalink") + +GitLab 的 GraphQL 参考[可用](reference/index.html) . + +它是从 GitLab 的 GraphQL 模式自动生成的,并嵌入到 Markdown 文件中. + +机器可读版本也可用: + +* [JSON format](reference/gitlab_schema.json) +* [IDL format](reference/gitlab_schema.graphql) \ No newline at end of file diff --git a/docs/385.md b/docs/385.md new file mode 100644 index 0000000000000000000000000000000000000000..73759a09113438879de555180bc62a17f195f1ea --- /dev/null +++ b/docs/385.md @@ -0,0 +1,203 @@ +# Getting started with GitLab GraphQL API + +> 原文:[https://docs.gitlab.com/ee/api/graphql/getting_started.html](https://docs.gitlab.com/ee/api/graphql/getting_started.html) + +* [Running examples](#running-examples) + * [Command line](#command-line) + * [GraphiQL](#graphiql) +* [Queries and mutations](#queries-and-mutations) + * [Graph traversal](#graph-traversal) + * [Authorization](#authorization) + * [Mutations](#mutations) + * [Creation mutations](#creation-mutations) + * [Update mutations](#update-mutations) + * [Deletion mutations](#deletion-mutations) + * [Introspective queries](#introspective-queries) +* [Sorting](#sorting) +* [Pagination](#pagination) + +# Getting started with GitLab GraphQL API[](#getting-started-with-gitlab-graphql-api "Permalink") + +本指南演示了 GitLab 的 GraphQL API 的基本用法. + +请参见[GraphQL API 样式指南,](../../development/api_graphql_styleguide.html)以了解针对希望开发 API 本身的开发人员的实现细节. + +## Running examples[](#running-examples "Permalink") + +此处记录的示例可以使用以下命令运行: + +* 命令行. +* GraphiQL. + +### Command line[](#command-line "Permalink") + +您可以在本地计算机上的命令行中的`curl`请求中运行 GraphQL 查询. 可以将 GraphQL 请求作为对`/api/graphql`的`POST`请求,并将查询作为有效负载. 您可以通过生成[个人访问令牌](../../user/profile/personal_access_tokens.html)以用作承载令牌来授权您的请求. + +Example: + +``` +GRAPHQL_TOKEN= +curl 'https://gitlab.com/api/graphql' --header "Authorization: Bearer $GRAPHQL_TOKEN" --header "Content-Type: application/json" --request POST --data "{\"query\": \"query {currentUser {name}}\"}" +``` + +### GraphiQL[](#graphiql "Permalink") + +GraphiQL(发音为"图形")允许您使用语法突出显示和自动完成功能直接针对服务器端点运行查询. 它还允许您探索模式和类型. + +下面的例子: + +* 可以直接在 GitLab 11.0 或更高版本上运行,尽管某些类型和字段在较早的版本中可能不受支持. +* 无需任何进一步设置即可在 GitLab.com 上运行. 确保您已登录并导航到[GraphiQL Explorer](https://gitlab.com/-/graphql-explorer) . + +如果要在本地或在自管实例上运行查询,则需要执行以下任一操作: + +* 创建`gitlab-org`组,并在其下创建一个名为`graphql-sandbox`的项目. 在项目中创建多个问题. +* 编辑查询以将`gitlab-org/graphql-sandbox`替换为您自己的组和项目. + +有关更多信息,请参考[运行 GraphiQL](index.html#graphiql) . + +**注意:**如果您正在运行 GitLab 11.0 到 12.0,请启用`graphql` [功能标记](../features.html#set-or-create-a-feature) . + +## Queries and mutations[](#queries-and-mutations "Permalink") + +GitLab GraphQL API 可用于执行: + +* 数据检索查询. +* 用于创建,更新和删除数据的[突变](#mutations) . + +**注意:**在 GitLab GraphQL API 中, `id`通常是指全局 ID,它是对象标识符,格式为`gid://gitlab/Issue/123` . + +[GitLab 的 GraphQL Schema](reference/index.html)概述了哪些对象和字段可供客户端查询以及它们对应的数据类型. + +示例:在`gitlab-org`组中,仅获取当前登录用户可以访问的所有项目的名称(最大限制,稍后再介绍). + +``` +query { group(fullPath: "gitlab-org") { id name projects { nodes { name } } } } +``` + +示例:获得一个特定的项目和标题#2. + +``` +query { project(fullPath: "gitlab-org/graphql-sandbox") { name issue(iid: "2") { title } } } +``` + +### Graph traversal[](#graph-traversal "Permalink") + +检索子节点时,请使用: + +* the `edges { node { } }` syntax. +* 缩写形式`nodes { }`语法. + +在它的下面是一个我们正在遍历的图,因此命名为 GraphQL. + +示例:获得一个项目(仅名称)及其所有期刊的标题. + +``` +query { project(fullPath: "gitlab-org/graphql-sandbox") { name issues { nodes { title description } } } } +``` + +有关查询的更多信息: [GraphQL 文档](https://s0graphql0org.icopy.site/learn/queries/) + +### Authorization[](#authorization "Permalink") + +授权使用与 GitLab 应用程序(和 GitLab.com)相同的引擎. 因此,如果您已经登录到 GitLab 并使用 GraphiQL,则所有查询都将以您(登录用户)的身份执行. 有关更多信息,请参见[GitLab API 文档](../README.html#authentication) . + +### Mutations[](#mutations "Permalink") + +变异会改变数据. 我们可以更新,删除或创建新记录. 变异通常使用 InputTypes 和变量,在此都不会出现. + +变异有: + +* 输入. 例如,参数,例如您想要授予的表情符号以及对象. +* 返回语句. 也就是说,成功后您希望获得什么. +* 错误. 总是问出什么问题了,以防万一. + +#### Creation mutations[](#creation-mutations "Permalink") + +示例:让我们喝点茶-在问题中添加`:tea:`反应表情符号. + +``` +mutation { awardEmojiAdd(input: { awardableId: "gid://gitlab/Issue/27039960", name: "tea" }) { awardEmoji { name description unicode emoji unicodeVersion user { name } } errors } } +``` + +示例:在问题上添加评论(我们使用的是`GitLab.com`问题的 ID,但是如果您使用的是本地实例,则需要获取可以写入的问题的 ID). + +``` +mutation { createNote(input: { noteableId: "gid://gitlab/Issue/27039960", body: "*sips tea*" }) { note { id body discussion { id } } errors } } +``` + +#### Update mutations[](#update-mutations "Permalink") + +当您看到创建的注释的结果`id`时,请记下它. 现在,让我们对其进行编辑以更快地 ip 饮! + +``` +mutation { updateNote(input: { id: "gid://gitlab/Note/", body: "*SIPS TEA*" }) { note { id body } errors } } +``` + +#### Deletion mutations[](#deletion-mutations "Permalink") + +让我们删除评论,因为我们的茶都没了. + +``` +mutation { destroyNote(input: { id: "gid://gitlab/Note/" }) { note { id body } errors } } +``` + +您应该得到类似以下输出的内容: + +``` +{ "data": { "destroyNote": { "errors": [], "note": null } } } +``` + +我们已经要求提供注释的详细信息,但是它不再存在,因此我们得到`null` . + +有关突变的更多信息: [GraphQL Docs](https://s0graphql0org.icopy.site/learn/queries/) . + +### Introspective queries[](#introspective-queries "Permalink") + +客户端可以查询 GraphQL 端点以获取有关其自身架构的信息. 通过进行[内省性查询](https://s0graphql0org.icopy.site/learn/introspection/) . + +通过自省查询, [GraphiQL 查询资源管理器](https://gitlab.com/-/graphql-explorer)获得了有关我们的 GraphQL 模式的所有知识,以执行自动补全并提供其交互式`Docs`选项卡. + +示例:获取架构中的所有类型名称. + +``` +{ __schema { types { name } } } +``` + +示例:获取与 Issue 相关的所有字段. `kind`告诉我们该类型的枚举值,例如`OBJECT` , `SCALAR`或`INTERFACE` . + +``` +query IssueTypes { __type(name: "Issue") { kind name fields { name description type { name } } } } +``` + +有关自省的更多信息: [GraphQL 文档](https://s0graphql0org.icopy.site/learn/introspection/) + +## Sorting[](#sorting "Permalink") + +GitLab 的一些 GraphQL 端点允许您指定想要对对象集合进行排序的方式. 您只能按架构允许的排序. + +示例:可以按创建日期对问题进行排序: + +``` +query { project(fullPath: "gitlab-org/graphql-sandbox") { name issues(sort: created_asc) { nodes { title createdAt } } } } +``` + +## Pagination[](#pagination "Permalink") + +分页是仅询问记录子集(例如前 10 个)的一种方法. 如果我们想要更多,我们可以从服务器再次请求下 10 条记录(例如"请给我下 10 条记录"). + +默认情况下,GitLab 的 GraphQL API 将仅返回任何集合的前 100 条记录. 可以使用`first`或`last`参数来更改. 这两个参数都有一个值,因此`first: 10`将返回前 10 条记录, `last: 10`将最后 10 条记录. + +示例:仅检索前两个问题(切片). `cursor`字段为我们提供了一个位置,从中可以检索相对于该位置的其他记录. + +``` +query { project(fullPath: "gitlab-org/graphql-sandbox") { name issues(first: 2) { edges { node { title } } pageInfo { endCursor hasNextPage } } } } +``` + +示例:检索下一个 3.(游标值`eyJpZCI6IjI3MDM4OTMzIiwiY3JlYXRlZF9hdCI6IjIwMTktMTEtMTQgMDU6NTY6NDQgVVRDIn0`可能有所不同,但它是上面返回的第二个问题返回的`cursor`值.) + +``` +query { project(fullPath: "gitlab-org/graphql-sandbox") { name issues(first: 3, after: "eyJpZCI6IjI3MDM4OTMzIiwiY3JlYXRlZF9hdCI6IjIwMTktMTEtMTQgMDU6NTY6NDQgVVRDIn0") { edges { node { title } cursor } pageInfo { endCursor hasNextPage } } } } +``` + +有关分页和游标的更多信息: [GraphQL 文档](https://s0graphql0org.icopy.site/learn/pagination/) \ No newline at end of file diff --git a/docs/386.md b/docs/386.md new file mode 100644 index 0000000000000000000000000000000000000000..02674e78ac009e07067101b1c52c47407c3e3168 --- /dev/null +++ b/docs/386.md @@ -0,0 +1,2524 @@ +# GraphQL API Resources + +> 原文:[https://docs.gitlab.com/ee/api/graphql/reference/](https://docs.gitlab.com/ee/api/graphql/reference/) + +* [AccessLevel](#accesslevel) +* [AddAwardEmojiPayload](#addawardemojipayload) +* [AddProjectToSecurityDashboardPayload](#addprojecttosecuritydashboardpayload) +* [AdminSidekiqQueuesDeleteJobsPayload](#adminsidekiqqueuesdeletejobspayload) +* [AlertManagementAlert](#alertmanagementalert) +* [AlertManagementAlertStatusCountsType](#alertmanagementalertstatuscountstype) +* [AlertSetAssigneesPayload](#alertsetassigneespayload) +* [AlertTodoCreatePayload](#alerttodocreatepayload) +* [AwardEmoji](#awardemoji) +* [AwardEmojiAddPayload](#awardemojiaddpayload) +* [AwardEmojiRemovePayload](#awardemojiremovepayload) +* [AwardEmojiTogglePayload](#awardemojitogglepayload) +* [BaseService](#baseservice) +* [Blob](#blob) +* [Board](#board) +* [BoardList](#boardlist) +* [BoardListUpdateLimitMetricsPayload](#boardlistupdatelimitmetricspayload) +* [Branch](#branch) +* [Commit](#commit) +* [CommitCreatePayload](#commitcreatepayload) +* [ComplianceFramework](#complianceframework) +* [ContainerExpirationPolicy](#containerexpirationpolicy) +* [CreateAlertIssuePayload](#createalertissuepayload) +* [CreateAnnotationPayload](#createannotationpayload) +* [CreateBranchPayload](#createbranchpayload) +* [CreateDiffNotePayload](#creatediffnotepayload) +* [CreateEpicPayload](#createepicpayload) +* [CreateImageDiffNotePayload](#createimagediffnotepayload) +* [CreateIterationPayload](#createiterationpayload) +* [CreateNotePayload](#createnotepayload) +* [CreateRequirementPayload](#createrequirementpayload) +* [CreateSnippetPayload](#createsnippetpayload) +* [DastSiteProfileCreatePayload](#dastsiteprofilecreatepayload) +* [DeleteAnnotationPayload](#deleteannotationpayload) +* [DeleteJobsResponse](#deletejobsresponse) +* [Design](#design) +* [DesignAtVersion](#designatversion) +* [DesignCollection](#designcollection) +* [DesignManagement](#designmanagement) +* [DesignManagementDeletePayload](#designmanagementdeletepayload) +* [DesignManagementUploadPayload](#designmanagementuploadpayload) +* [DesignVersion](#designversion) +* [DestroyNotePayload](#destroynotepayload) +* [DestroySnippetPayload](#destroysnippetpayload) +* [DetailedStatus](#detailedstatus) +* [DiffPosition](#diffposition) +* [DiffRefs](#diffrefs) +* [DiffStats](#diffstats) +* [DiffStatsSummary](#diffstatssummary) +* [Discussion](#discussion) +* [DiscussionToggleResolvePayload](#discussiontoggleresolvepayload) +* [DismissVulnerabilityPayload](#dismissvulnerabilitypayload) +* [Environment](#environment) +* [Epic](#epic) +* [EpicAddIssuePayload](#epicaddissuepayload) +* [EpicDescendantCount](#epicdescendantcount) +* [EpicDescendantWeights](#epicdescendantweights) +* [EpicHealthStatus](#epichealthstatus) +* [EpicIssue](#epicissue) +* [EpicPermissions](#epicpermissions) +* [EpicSetSubscriptionPayload](#epicsetsubscriptionpayload) +* [EpicTreeReorderPayload](#epictreereorderpayload) +* [GeoNode](#geonode) +* [GrafanaIntegration](#grafanaintegration) +* [Group](#group) +* [GroupMember](#groupmember) +* [GroupPermissions](#grouppermissions) +* [Issue](#issue) +* [IssuePermissions](#issuepermissions) +* [IssueSetConfidentialPayload](#issuesetconfidentialpayload) +* [IssueSetDueDatePayload](#issuesetduedatepayload) +* [IssueSetIterationPayload](#issuesetiterationpayload) +* [IssueSetLockedPayload](#issuesetlockedpayload) +* [IssueSetWeightPayload](#issuesetweightpayload) +* [Iteration](#iteration) +* [JiraImport](#jiraimport) +* [JiraImportStartPayload](#jiraimportstartpayload) +* [JiraImportUsersPayload](#jiraimportuserspayload) +* [JiraProject](#jiraproject) +* [JiraService](#jiraservice) +* [JiraUser](#jirauser) +* [Label](#label) +* [MarkAsSpamSnippetPayload](#markasspamsnippetpayload) +* [MergeRequest](#mergerequest) +* [MergeRequestCreatePayload](#mergerequestcreatepayload) +* [MergeRequestPermissions](#mergerequestpermissions) +* [MergeRequestSetAssigneesPayload](#mergerequestsetassigneespayload) +* [MergeRequestSetLabelsPayload](#mergerequestsetlabelspayload) +* [MergeRequestSetLockedPayload](#mergerequestsetlockedpayload) +* [MergeRequestSetMilestonePayload](#mergerequestsetmilestonepayload) +* [MergeRequestSetSubscriptionPayload](#mergerequestsetsubscriptionpayload) +* [MergeRequestSetWipPayload](#mergerequestsetwippayload) +* [MergeRequestUpdatePayload](#mergerequestupdatepayload) +* [Metadata](#metadata) +* [MetricsDashboard](#metricsdashboard) +* [MetricsDashboardAnnotation](#metricsdashboardannotation) +* [Milestone](#milestone) +* [MilestoneStats](#milestonestats) +* [Namespace](#namespace) +* [Note](#note) +* [NotePermissions](#notepermissions) +* [Package](#package) +* [PackageFileRegistry](#packagefileregistry) +* [PageInfo](#pageinfo) +* [Pipeline](#pipeline) +* [PipelinePermissions](#pipelinepermissions) +* [Project](#project) +* [ProjectMember](#projectmember) +* [ProjectPermissions](#projectpermissions) +* [ProjectStatistics](#projectstatistics) +* [Release](#release) +* [ReleaseAssetLink](#releaseassetlink) +* [ReleaseAssets](#releaseassets) +* [ReleaseEvidence](#releaseevidence) +* [ReleaseLinks](#releaselinks) +* [ReleaseSource](#releasesource) +* [RemoveAwardEmojiPayload](#removeawardemojipayload) +* [RemoveProjectFromSecurityDashboardPayload](#removeprojectfromsecuritydashboardpayload) +* [Repository](#repository) +* [Requirement](#requirement) +* [RequirementPermissions](#requirementpermissions) +* [RequirementStatesCount](#requirementstatescount) +* [RootStorageStatistics](#rootstoragestatistics) +* [RunDASTScanPayload](#rundastscanpayload) +* [SastCiConfigurationAnalyzersEntity](#sastciconfigurationanalyzersentity) +* [SastCiConfigurationEntity](#sastciconfigurationentity) +* [SastCiConfigurationOptionsEntity](#sastciconfigurationoptionsentity) +* [ScannedResource](#scannedresource) +* [SecurityReportSummary](#securityreportsummary) +* [SecurityReportSummarySection](#securityreportsummarysection) +* [SecurityScanners](#securityscanners) +* [SentryDetailedError](#sentrydetailederror) +* [SentryError](#sentryerror) +* [SentryErrorCollection](#sentryerrorcollection) +* [SentryErrorFrequency](#sentryerrorfrequency) +* [SentryErrorStackTrace](#sentryerrorstacktrace) +* [SentryErrorStackTraceContext](#sentryerrorstacktracecontext) +* [SentryErrorStackTraceEntry](#sentryerrorstacktraceentry) +* [SentryErrorTags](#sentryerrortags) +* [Snippet](#snippet) +* [SnippetBlob](#snippetblob) +* [SnippetBlobViewer](#snippetblobviewer) +* [SnippetPermissions](#snippetpermissions) +* [Submodule](#submodule) +* [TaskCompletionStatus](#taskcompletionstatus) +* [TestReport](#testreport) +* [Timelog](#timelog) +* [Todo](#todo) +* [TodoMarkDonePayload](#todomarkdonepayload) +* [TodoRestoreManyPayload](#todorestoremanypayload) +* [TodoRestorePayload](#todorestorepayload) +* [TodosMarkAllDonePayload](#todosmarkalldonepayload) +* [ToggleAwardEmojiPayload](#toggleawardemojipayload) +* [Tree](#tree) +* [TreeEntry](#treeentry) +* [UpdateAlertStatusPayload](#updatealertstatuspayload) +* [UpdateContainerExpirationPolicyPayload](#updatecontainerexpirationpolicypayload) +* [UpdateEpicPayload](#updateepicpayload) +* [UpdateImageDiffNotePayload](#updateimagediffnotepayload) +* [UpdateIssuePayload](#updateissuepayload) +* [UpdateIterationPayload](#updateiterationpayload) +* [UpdateNotePayload](#updatenotepayload) +* [UpdateRequirementPayload](#updaterequirementpayload) +* [UpdateSnippetPayload](#updatesnippetpayload) +* [User](#user) +* [UserPermissions](#userpermissions) +* [VulnerabilitiesCountByDayAndSeverity](#vulnerabilitiescountbydayandseverity) +* [Vulnerability](#vulnerability) +* [VulnerabilityIdentifier](#vulnerabilityidentifier) +* [VulnerabilityIssueLink](#vulnerabilityissuelink) +* [VulnerabilityLocationContainerScanning](#vulnerabilitylocationcontainerscanning) +* [VulnerabilityLocationDast](#vulnerabilitylocationdast) +* [VulnerabilityLocationDependencyScanning](#vulnerabilitylocationdependencyscanning) +* [VulnerabilityLocationSast](#vulnerabilitylocationsast) +* [VulnerabilityLocationSecretDetection](#vulnerabilitylocationsecretdetection) +* [VulnerabilityPermissions](#vulnerabilitypermissions) +* [VulnerabilityScanner](#vulnerabilityscanner) +* [VulnerabilitySeveritiesCount](#vulnerabilityseveritiescount) +* [VulnerableDependency](#vulnerabledependency) +* [VulnerablePackage](#vulnerablepackage) + +# GraphQL API Resources[](#graphql-api-resources "Permalink") + +本文档是基于 GitLab 当前的 GraphQL 模式自行生成的. + +可以使用[GraphiQL IDE](../index.html#graphiql)交互式地探索该 API. + +下表每个都记录了 GraphQL 类型. 类型可以轻松地与模型匹配,但是并非所有的字段和方法都可以通过 GraphQL 获得. + +**警告:**不推荐使用的字段标有 . + +## AccessLevel[](#accesslevel "Permalink") + +表示用户与之相关的对象之间的关系的访问级别 + +| Name | Type | Description | +| --- | --- | --- | +| `integerValue` | Int | 访问级别的整数表示 | +| `stringValue` | AccessLevelEnum | 访问级别的字符串表示形式 | + +## AddAwardEmojiPayload[](#addawardemojipayload "Permalink") + +自动生成的 AddAwardEmoji 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `awardEmoji` | AwardEmoji | 突变后的奖励表情符号 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## AddProjectToSecurityDashboardPayload[](#addprojecttosecuritydashboardpayload "Permalink") + +自动生成的 AddProjectToSecurityDashboard 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `project` | Project | 添加到 Instance Security 仪表盘的项目 | + +## AdminSidekiqQueuesDeleteJobsPayload[](#adminsidekiqqueuesdeletejobspayload "Permalink") + +自动生成的 AdminSidekiqQueuesDeleteJobs 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `result` | DeleteJobsResponse | 有关删除请求状态的信息 | + +## AlertManagementAlert[](#alertmanagementalert "Permalink") + +描述来自项目警报管理的警报 + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time | 创建警报的时间戳 | +| `description` | String | 警报说明 | +| `details` | JSON | 警报详细信息 | +| `endedAt` | Time | 警报结束的时间戳记 | +| `eventCount` | Int | 此警报的事件数 | +| `hosts` | 串! =>数组 | 警报来自的主机列表 | +| `iid` | ID! | 警报的内部 ID | +| `issueIid` | ID | 警报附带的 GitLab 问题的内部 ID | +| `metricsDashboardUrl` | String | 嵌入警报的指标的 URL | +| `monitoringTool` | String | 警报来自的监视工具 | +| `service` | String | 服务警报来自 | +| `severity` | AlertManagementSeverity | 警报的严重程度 | +| `startedAt` | Time | 发出警报的时间戳记 | +| `status` | AlertManagementStatus | 警报状态 | +| `title` | String | 警报标题 | +| `updatedAt` | Time | 警报的时间戳记最新更新 | + +## AlertManagementAlertStatusCountsType[](#alertmanagementalertstatuscountstype "Permalink") + +代表所代表类别的警报总数 + +| Name | Type | Description | +| --- | --- | --- | +| `acknowledged` | Int | 项目状态为 ACKNOWLEDGED 的警报数 | +| `all` | Int | 项目警报总数 | +| `ignored` | Int | 项目状态为 IGNORED 的警报数 | +| `open` | Int | 项目状态为 TRIGGERED 或 ACKNOWLEDGED 的警报数 | +| `resolved` | Int | 项目状态为"已解决"的警报数 | +| `triggered` | Int | 项目状态为 TRIGGERED 的警报数 | + +## AlertSetAssigneesPayload[](#alertsetassigneespayload "Permalink") + +自动生成的 AlertSetAssignees 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `alert` | AlertManagementAlert | 突变后的警报 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后产生的问题 | +| `todo` | Todo | 突变后的待办事项 | + +## AlertTodoCreatePayload[](#alerttodocreatepayload "Permalink") + +自动生成的 AlertTodoCreate 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `alert` | AlertManagementAlert | 突变后的警报 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后产生的问题 | +| `todo` | Todo | 突变后的待办事项 | + +## AwardEmoji[](#awardemoji "Permalink") + +用户授予的表情符号. + +| Name | Type | Description | +| --- | --- | --- | +| `description` | String! | 表情符号说明 | +| `emoji` | String! | 表情符号作为图标 | +| `name` | String! | 表情符号名称 | +| `unicode` | String! | Unicode 中的表情符号 | +| `unicodeVersion` | String! | 此表情符号的 unicode 版本 | +| `user` | User! | 授予表情符号的用户 | + +## AwardEmojiAddPayload[](#awardemojiaddpayload "Permalink") + +自动生成的 AwardEmojiAdd 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `awardEmoji` | AwardEmoji | 突变后的奖励表情符号 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## AwardEmojiRemovePayload[](#awardemojiremovepayload "Permalink") + +自动生成的 AwardEmoji 退货类型 + +| Name | Type | Description | +| --- | --- | --- | +| `awardEmoji` | AwardEmoji | The award emoji after mutation | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## AwardEmojiTogglePayload[](#awardemojitogglepayload "Permalink") + +自动生成的 AwardEmojiToggle 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `awardEmoji` | AwardEmoji | 突变后的奖励表情符号 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `toggledOn` | Boolean! | 指示表情符号的状态. 如果切换开关授予表情符号,则为 true;如果切换开关删除了表情符号,则为 false. | + +## BaseService[](#baseservice "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `active` | Boolean | 指示服务是否处于活动状态 | +| `type` | String | 服务的类别名称 | + +## Blob[](#blob "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `flatPath` | String! | 条目的平坦路径 | +| `id` | ID! | 条目 ID | +| `lfsOid` | String | Blob 的 LFS ID | +| `mode` | String | 数字格式的 Blob 模式 | +| `name` | String! | 条目名称 | +| `path` | String! | 条目路径 | +| `sha` | String! | 提交的最后提交 sha | +| `type` | EntryType! | 树条目的类型 | +| `webUrl` | String | Blob 的网址 | + +## Board[](#board "Permalink") + +代表一个项目或小组委员会 + +| Name | Type | Description | +| --- | --- | --- | +| `id` | ID! | 单板的 ID(全局 ID) | +| `name` | String | 董事会名称 | +| `weight` | Int | 木板重量 | + +## BoardList[](#boardlist "Permalink") + +代表发行板的列表 + +| Name | Type | Description | +| --- | --- | --- | +| `assignee` | User | 列表中的受让人 | +| `collapsed` | Boolean | 指示此用户的列表是否折叠 | +| `id` | ID! | 列表的 ID(全局 ID) | +| `label` | Label | 清单标签 | +| `limitMetric` | ListLimitMetric | 列表的当前限制指标 | +| `listType` | String! | 清单类型 | +| `maxIssueCount` | Int | 列表中的最大问题数 | +| `maxIssueWeight` | Int | 清单中的最大问题权重 | +| `milestone` | Milestone | 名单的里程碑 | +| `position` | Int | 名单在董事会中的位置 | +| `title` | String! | 清单标题 | + +## BoardListUpdateLimitMetricsPayload[](#boardlistupdatelimitmetricspayload "Permalink") + +自动生成的 BoardListUpdateLimitMetrics 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `list` | BoardList | 更新清单 | + +## Branch[](#branch "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `commit` | Commit | 提交分支 | +| `name` | String! | 分行名称 | + +## Commit[](#commit "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User | 提交的作者 | +| `authorGravatar` | String | 提交作者 | +| `authorName` | String | 提交作者姓名 | +| `authoredDate` | Time | 提交提交的时间戳 | +| `description` | String | 提交消息的描述 | +| `id` | ID! | 提交的 ID(全局 ID) | +| `latestPipeline` | Pipeline | **不推荐使用:**使用`pipelines` . 在 12.5 中弃用 | +| `message` | String | 原始提交消息 | +| `sha` | String! | 提交的 SHA1 ID | +| `signatureHtml` | String | 提交签名的 HTML | +| `title` | String | 提交消息的标题 | +| `titleHtml` | String | GitLab 风味 Markdown `title`渲染 | +| `webUrl` | String! | 提交的 Web URL | + +## CommitCreatePayload[](#commitcreatepayload "Permalink") + +自动生成的 CommitCreate 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `commit` | Commit | 突变后的提交 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## ComplianceFramework[](#complianceframework "Permalink") + +表示与项目关联的 ComplianceFramework + +| Name | Type | Description | +| --- | --- | --- | +| `name` | ProjectSettingEnum! | 合规框架名称 | + +## ContainerExpirationPolicy[](#containerexpirationpolicy "Permalink") + +标签过期策略旨在仅保留最重要的图像 + +| Name | Type | Description | +| --- | --- | --- | +| `cadence` | ContainerExpirationPolicyCadenceEnum! | 该容器到期政策时间表 | +| `createdAt` | Time! | 创建容器到期策略的时间戳 | +| `enabled` | Boolean! | 指示是否启用了此容器过期策略 | +| `keepN` | ContainerExpirationPolicyKeepEnum | 要保留的标签数 | +| `nameRegex` | UntrustedRegexp | 名称与此正则表达式模式匹配的标签将过期 | +| `nameRegexKeep` | UntrustedRegexp | 名称与该正则表达式模式匹配的标签将被保留 | +| `nextRunAt` | Time | 下次该容器到期策略将被执行 | +| `olderThan` | ContainerExpirationPolicyOlderThanEnum | Tags older that this will expire | +| `updatedAt` | Time! | 容器过期策略更新的时间戳 | + +## CreateAlertIssuePayload[](#createalertissuepayload "Permalink") + +自动生成的 CreateAlertIssue 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `alert` | AlertManagementAlert | 突变后的警报 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后产生的问题 | +| `todo` | Todo | 突变后的待办事项 | + +## CreateAnnotationPayload[](#createannotationpayload "Permalink") + +自动生成的 CreateAnnotation 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `annotation` | MetricsDashboardAnnotation | 创建的注释 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## CreateBranchPayload[](#createbranchpayload "Permalink") + +自动生成的 CreateBranch 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `branch` | Branch | 突变后分支 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## CreateDiffNotePayload[](#creatediffnotepayload "Permalink") + +自动生成的 CreateDiffNote 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `note` | Note | 突变后的音符 | + +## CreateEpicPayload[](#createepicpayload "Permalink") + +自动生成的 CreateEpic 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `epic` | Epic | 创造的史诗 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## CreateImageDiffNotePayload[](#createimagediffnotepayload "Permalink") + +自动生成的 CreateImageDiffNote 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `note` | Note | 突变后的音符 | + +## CreateIterationPayload[](#createiterationpayload "Permalink") + +自动生成的 CreateIteration 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `iteration` | Iteration | 创建的迭代 | + +## CreateNotePayload[](#createnotepayload "Permalink") + +自动生成的 CreateNote 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `note` | Note | 突变后的音符 | + +## CreateRequirementPayload[](#createrequirementpayload "Permalink") + +自动生成的 CreateRequirement 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `requirement` | Requirement | 突变后的要求 | + +## CreateSnippetPayload[](#createsnippetpayload "Permalink") + +自动生成的 CreateSnippet 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `snippet` | Snippet | 突变后的代码段 | + +## DastSiteProfileCreatePayload[](#dastsiteprofilecreatepayload "Permalink") + +自动生成的 DastSiteProfileCreate 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `id` | ID | 网站配置文件的 ID. | + +## DeleteAnnotationPayload[](#deleteannotationpayload "Permalink") + +自动生成的 DeleteAnnotation 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## DeleteJobsResponse[](#deletejobsresponse "Permalink") + +来自 AdminSidekiqQueuesDeleteJobs 突变的响应. + +| Name | Type | Description | +| --- | --- | --- | +| `completed` | Boolean | 是否及时处理了整个队列; 如果没有,重试相同的请求是安全的 | +| `deletedJobs` | Int | 删除的匹配作业数 | +| `queueSize` | Int | 处理后的队列大小 | + +## Design[](#design "Permalink") + +单一设计 + +| Name | Type | Description | +| --- | --- | --- | +| `diffRefs` | DiffRefs! | 此设计的差异参考 | +| `event` | DesignVersionEvent! | 当前版本中该设计的更改方式 | +| `filename` | String! | 设计的文件名 | +| `fullPath` | String! | 设计文件的完整路径 | +| `id` | ID! | 此设计的 ID | +| `image` | String! | 完整尺寸图片的网址 | +| `imageV432x230` | String | 调整了设计网址的大小,以适合 432x230 的范围. 如果尚未生成图像,则为`null` | +| `issue` | Issue! | 设计属于的问题 | +| `notesCount` | Int! | 用户为此设计创建的注释总数 | +| `project` | Project! | 设计所属的项目 | + +## DesignAtVersion[](#designatversion "Permalink") + +固定到特定版本的设计. 图像字段反映了相关版本的设计. + +| Name | Type | Description | +| --- | --- | --- | +| `design` | Design! | 基础设计. | +| `diffRefs` | DiffRefs! | 此设计的差异参考 | +| `event` | DesignVersionEvent! | 当前版本中该设计的更改方式 | +| `filename` | String! | 设计的文件名 | +| `fullPath` | String! | 设计文件的完整路径 | +| `id` | ID! | 此设计的 ID | +| `image` | String! | 完整尺寸图片的网址 | +| `imageV432x230` | String | 调整了设计网址的大小,以适合 432x230 的范围. 如果尚未生成图像,则为`null` | +| `issue` | Issue! | 设计属于的问题 | +| `notesCount` | Int! | 用户为此设计创建的注释总数 | +| `project` | Project! | 设计所属的项目 | +| `version` | DesignVersion! | 此版本设计版本固定到的版本 | + +## DesignCollection[](#designcollection "Permalink") + +设计的集合. + +| Name | Type | Description | +| --- | --- | --- | +| `design` | Design | 查找特定的设计 | +| `designAtVersion` | DesignAtVersion | 查找版本设计 | +| `issue` | Issue! | 与设计收藏相关的问题 | +| `project` | Project! | 与设计收藏关联的项目 | +| `version` | DesignVersion | 特定版本 | + +## DesignManagement[](#designmanagement "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `designAtVersion` | DesignAtVersion | 查找版本设计 | +| `version` | DesignVersion | 查找版本 | + +## DesignManagementDeletePayload[](#designmanagementdeletepayload "Permalink") + +自动生成的 DesignManagementDelete 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `version` | DesignVersion | 删除了设计的新版本 | + +## DesignManagementUploadPayload[](#designmanagementuploadpayload "Permalink") + +自动生成的 DesignManagementUpload 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `designs` | 设计! =>数组 | 突变上传的设计 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `skippedDesigns` | 设计! =>数组 | 由于上一版本以来其内容没有更改,因此从上载中跳过的任何设计 | + +## DesignVersion[](#designversion "Permalink") + +在其中添加,修改或删除设计的特定版本 + +| Name | Type | Description | +| --- | --- | --- | +| `designAtVersion` | DesignAtVersion! | 此版本的特定设计,只要该版本可见 | +| `id` | ID! | 设计版本号 | +| `sha` | ID! | 设计版本的 SHA | + +## DestroyNotePayload[](#destroynotepayload "Permalink") + +自动生成的销毁返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `note` | Note | 突变后的音符 | + +## DestroySnippetPayload[](#destroysnippetpayload "Permalink") + +自动生成的 DestroySnippet 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `snippet` | Snippet | 突变后的代码段 | + +## DetailedStatus[](#detailedstatus "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `detailsPath` | String! | 管道状态的详细信息路径 | +| `favicon` | String! | 管道状态图标 | +| `group` | String! | 组管道状态 | +| `hasDetails` | Boolean! | 指示管道状态是否有更多详细信息 | +| `icon` | String! | 管道状态图标 | +| `label` | String! | 管道状态标签 | +| `text` | String! | 管道状态文字 | +| `tooltip` | String! | 与管道状态相关的工具提示 | + +## DiffPosition[](#diffposition "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `diffRefs` | DiffRefs! | 评论时有关分支,HEAD 和基础的信息 | +| `filePath` | String! | 更改文件的路径 | +| `height` | Int | 图片总高度 | +| `newLine` | Int | HEAD SHA 上的线已更改 | +| `newPath` | String | HEAD SHA 上文件的路径 | +| `oldLine` | Int | 起始 SHA 上已更改的行 | +| `oldPath` | String | 起始 SHA 上文件的路径 | +| `positionType` | DiffPositionType! | 位置所指的文件类型 | +| `width` | Int | 图片总宽度 | +| `x` | Int | 笔记的 X 位置 | +| `y` | Int | 音符的 Y 位置 | + +## DiffRefs[](#diffrefs "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `baseSha` | String | Merge base of the branch the comment was made on | +| `headSha` | String! | 发表评论时,HEAD 的 SHA | +| `startSha` | String! | 与之比较的分支的 SHA | + +## DiffStats[](#diffstats "Permalink") + +更改为单个文件 + +| Name | Type | Description | +| --- | --- | --- | +| `additions` | Int! | 添加到此文件的行数 | +| `deletions` | Int! | 从此文件中删除的行数 | +| `path` | String! | 相对于存储库根的文件路径 | + +## DiffStatsSummary[](#diffstatssummary "Permalink") + +汇总汇总 + +| Name | Type | Description | +| --- | --- | --- | +| `additions` | Int! | 添加的行数 | +| `changes` | Int! | 行数已更改 | +| `deletions` | Int! | 删除的行数 | +| `fileCount` | Int! | 文件数量已更改 | + +## Discussion[](#discussion "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time! | 讨论创建的时间戳 | +| `id` | ID! | 讨论的 ID | +| `replyId` | ID! | 用来回复此讨论的 ID | +| `resolvable` | Boolean! | 指示对象是否可以解析 | +| `resolved` | Boolean! | 指示对象是否已解析 | +| `resolvedAt` | Time | 解析对象的时间戳 | +| `resolvedBy` | User | 解决对象的用户 | + +## DiscussionToggleResolvePayload[](#discussiontoggleresolvepayload "Permalink") + +自动生成的 DiscussionToggleResolve 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `discussion` | Discussion | 突变后的讨论 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## DismissVulnerabilityPayload[](#dismissvulnerabilitypayload "Permalink") + +自动生成的 DismissVulnerability 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `vulnerability` | Vulnerability | 解雇后的漏洞 | + +## Environment[](#environment "Permalink") + +描述项目的代码部署位置 + +| Name | Type | Description | +| --- | --- | --- | +| `id` | ID! | 环境 ID | +| `metricsDashboard` | MetricsDashboard | 环境的指标仪表板架构 | +| `name` | String! | 易读的环境名称 | +| `state` | String! | 环境状态,例如:可用/已停止 | + +## Epic[](#epic "Permalink") + +代表史诗. + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User! | 史诗的作者 | +| `closedAt` | Time | 史诗关闭的时间戳 | +| `confidential` | Boolean | 指示该史诗是否为机密 | +| `createdAt` | Time | 史诗创作的时间戳 | +| `descendantCounts` | EpicDescendantCount | 打开和关闭的后代史诗和问题的数量 | +| `descendantWeightSum` | EpicDescendantWeights | 史诗及其后代中未解决和未解决问题的总权重 | +| `description` | String | 史诗的描述 | +| `downvotes` | Int! | 史诗获得的降票数 | +| `dueDate` | Time | 史诗的截止日期 | +| `dueDateFixed` | Time | 史诗的固定截止日期 | +| `dueDateFromMilestones` | Time | 从里程碑继承了史诗的到期日 | +| `dueDateIsFixed` | Boolean | 指示是否已手动设置截止日期 | +| `group` | Group! | 史诗所属的组 | +| `hasChildren` | Boolean! | 指示史诗是否有孩子 | +| `hasIssues` | Boolean! | 指示史诗是否有直接问题 | +| `hasParent` | Boolean! | 指示该史诗是否具有父史诗 | +| `healthStatus` | EpicHealthStatus | Current health status of the epic | +| `id` | ID! | 史诗编号 | +| `iid` | ID! | 史诗的内部 ID | +| `parent` | Epic | 史诗的父史诗 | +| `reference` | String! | 史诗的内部参考. 默认以缩写形式返回 | +| `relationPath` | String | 史诗问题的 URI 路径 | +| `relativePosition` | Int | 史诗在史诗树中的相对位置 | +| `startDate` | Time | 史诗的开始日期 | +| `startDateFixed` | Time | 固定的史诗开始日期 | +| `startDateFromMilestones` | Time | 从里程碑继承了史诗的开始日期 | +| `startDateIsFixed` | Boolean | 指示开始日期是否已手动设置 | +| `state` | EpicState! | 史诗般的状态 | +| `subscribed` | Boolean! | 指示当前登录的用户已订阅史诗 | +| `title` | String | 史诗的标题 | +| `updatedAt` | Time | 史诗最后一次活动的时间戳 | +| `upvotes` | Int! | 史诗已收到的投票数 | +| `userPermissions` | EpicPermissions! | 当前用户对该资源的权限 | +| `webPath` | String! | 史诗的网络路径 | +| `webUrl` | String! | 史诗的网址 | + +## EpicAddIssuePayload[](#epicaddissuepayload "Permalink") + +自动生成的 EpicAddIssue 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `epic` | Epic | 突变后的史诗 | +| `epicIssue` | EpicIssue | 史诗般的关系 | +| `errors` | 串! =>数组 | Errors encountered during execution of the mutation. | + +## EpicDescendantCount[](#epicdescendantcount "Permalink") + +后代史诗的计数. + +| Name | Type | Description | +| --- | --- | --- | +| `closedEpics` | Int | 封闭亚史诗数量 | +| `closedIssues` | Int | 已解决的史诗问题的数量 | +| `openedEpics` | Int | 打开的子史诗数量 | +| `openedIssues` | Int | 公开史诗问题的数量 | + +## EpicDescendantWeights[](#epicdescendantweights "Permalink") + +开放和封闭后代问题的总权重 + +| Name | Type | Description | +| --- | --- | --- | +| `closedIssues` | Int | 此史诗(包括史诗后代)中已完成(已关闭)期刊的总权重 | +| `openedIssues` | Int | 此史诗(包括史诗后代)中未解决问题的总权重 | + +## EpicHealthStatus[](#epichealthstatus "Permalink") + +儿童健康状况 + +| Name | Type | Description | +| --- | --- | --- | +| `issuesAtRisk` | Int | 有风险的问题数量 | +| `issuesNeedingAttention` | Int | 需要注意的问题数量 | +| `issuesOnTrack` | Int | 进行中的问题数量 | + +## EpicIssue[](#epicissue "Permalink") + +史诗与问题之间的关系 + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User! | 造成问题的使用者 | +| `closedAt` | Time | 该问题何时结束的时间戳 | +| `confidential` | Boolean! | 表示问题是机密的 | +| `createdAt` | Time! | 问题创建时间的时间戳记 | +| `description` | String | 问题说明 | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `designCollection` | DesignCollection | 与此问题相关的设计图像的收集 | +| `designs` | DesignCollection | **不推荐使用:**使用`designCollection` . 在 12.2 中弃用 | +| `discussionLocked` | Boolean! | 表示讨论已锁定在该问题上 | +| `downvotes` | Int! | 问题已收到的否决票数 | +| `dueDate` | Time | 发行日期 | +| `epic` | Epic | 此问题所属的史诗 | +| `epicIssueId` | ID! | 史诗般的关系的 ID | +| `healthStatus` | HealthStatus | 当前的健康状况. 如果禁用了`save_issuable_health_status`功能标志,则返回 null. | +| `id` | ID | 史诗关系的全局 ID | +| `iid` | ID! | 问题的内部 ID | +| `iteration` | Iteration | 迭代问题 | +| `milestone` | Milestone | 问题的里程碑 | +| `reference` | String! | 内部参考的问题. 默认以缩写形式返回 | +| `relationPath` | String | 史诗问题的 URI 路径 | +| `relativePosition` | Int | 问题的相对位置(用于在史诗树和问题板上定位) | +| `state` | IssueState! | 问题状态 | +| `subscribed` | Boolean! | 指示当前登录的用户已订阅该问题 | +| `taskCompletionStatus` | TaskCompletionStatus! | 问题的任务完成状态 | +| `timeEstimate` | Int! | 问题的时间估算 | +| `title` | String! | 问题标题 | +| `titleHtml` | String | GitLab 风味 Markdown `title`渲染 | +| `totalTimeSpent` | Int! | 报告在此问题上花费的总时间 | +| `updatedAt` | Time! | 问题上次更新的时间戳 | +| `upvotes` | Int! | 问题已收到的投票数 | +| `userNotesCount` | Int! | 用户对此问题的注释数 | +| `userPermissions` | IssuePermissions! | 当前用户对该资源的权限 | +| `webPath` | String! | 问题的网络路径 | +| `webUrl` | String! | 问题的网址 | +| `weight` | Int | 问题的权重 | + +## EpicPermissions[](#epicpermissions "Permalink") + +检查史诗级当前用户的权限 + +| Name | Type | Description | +| --- | --- | --- | +| `adminEpic` | Boolean! | 指示用户可以对此资源执行`admin_epic` | +| `awardEmoji` | Boolean! | 表示用户可以在此资源上执行`award_emoji` | +| `createEpic` | Boolean! | 指示用户可以在此资源上执行`create_epic` | +| `createNote` | Boolean! | 指示用户可以在此资源上执行`create_note` | +| `destroyEpic` | Boolean! | 指示用户可以对此资源执行`destroy_epic` | +| `readEpic` | Boolean! | 指示用户可以对此资源执行`read_epic` | +| `readEpicIid` | Boolean! | 指示用户可以对此资源执行`read_epic_iid` | +| `updateEpic` | Boolean! | 指示用户可以对此资源执行`update_epic` | + +## EpicSetSubscriptionPayload[](#epicsetsubscriptionpayload "Permalink") + +自动生成的 EpicSetSubscription 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `epic` | Epic | 突变后的史诗 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## EpicTreeReorderPayload[](#epictreereorderpayload "Permalink") + +自动生成的 EpicTreeReorder 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## GeoNode[](#geonode "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `containerRepositoriesMaxCapacity` | Int | 此辅助节点的容器存储库同步的最大并发性 | +| `enabled` | Boolean | 指示是否启用了此地理节点 | +| `filesMaxCapacity` | Int | 此辅助节点的 LFS /附件回填的最大并发性 | +| `id` | ID! | 此 GeoNode 的 ID | +| `internalUrl` | String | 在主节点上定义的 URL,辅助节点应使用该 URL 与之联系 | +| `minimumReverificationInterval` | Int | 存储库验证有效的时间间隔(以天为单位). 一旦过期,它将被重新验证 | +| `name` | String | 此地理节点的唯一标识符 | +| `primary` | Boolean | 指示此地理节点是否为主要节点 | +| `reposMaxCapacity` | Int | 此辅助节点的存储库回填的最大并发性 | +| `selectiveSyncShards` | 串! =>数组 | 如果`selective_sync_type` == `shards` ,应同步其项目的存储库存储 | +| `selectiveSyncType` | String | 指示同步是否仅限于特定的组或分片 | +| `syncObjectStorage` | Boolean | 指示此辅助节点是否将复制对象存储中的 Blob | +| `url` | String | 此地理位置节点的面向用户的网址 | +| `verificationMaxCapacity` | Int | 此辅助节点的存储库验证的最大并发性 | + +## GrafanaIntegration[](#grafanaintegration "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time! | 问题创建的时间戳 | +| `enabled` | Boolean! | 指示是否启用 Grafana 集成 | +| `grafanaUrl` | String! | 用于 Grafana 集成的 Grafana 主机的 URL | +| `id` | ID! | Grafana 集成的内部 ID | +| `token` | String! | **不推荐使用:**出于安全原因,纯文本令牌已被屏蔽. 在 12.7 中弃用 | +| `updatedAt` | Time! | 问题上次活动的时间戳 | + +## Group[](#group "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `autoDevopsEnabled` | Boolean | 指示是否为该组内的所有项目启用了 Auto DevOps | +| `avatarUrl` | String | 群组的头像网址 | +| `board` | Board | 小组的一个董事会 | +| `description` | String | 命名空间的描述 | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `emailsDisabled` | Boolean | 指示组是否禁用了电子邮件通知 | +| `epic` | Epic | 查找单个史诗 | +| `epicsEnabled` | Boolean | 指示是否为名称空间启用了 Epics | +| `fullName` | String! | 命名空间的全名 | +| `fullPath` | ID! | 命名空间的完整路径 | +| `groupTimelogsEnabled` | Boolean | 指示是否为名称空间启用了组时间日志 | +| `id` | ID! | 命名空间的 ID | +| `label` | Label | 该组可用的标签 | +| `lfsEnabled` | Boolean | 指示是否为名称空间启用了大文件存储(LFS) | +| `mentionsDisabled` | Boolean | 指示是否禁止某人被提及 | +| `name` | String! | 命名空间的名称 | +| `parent` | Group | 家长组 | +| `path` | String! | 命名空间的路径 | +| `projectCreationLevel` | String | 在组中创建项目所需的权限级别 | +| `requestAccessEnabled` | Boolean | 指示用户是否可以请求访问名称空间 | +| `requireTwoFactorAuthentication` | Boolean | 指示是否需要该组中的所有用户来设置两因素身份验证 | +| `rootStorageStatistics` | RootStorageStatistics | 命名空间的聚合存储统计信息. 仅适用于根名称空间 | +| `shareWithGroupLock` | Boolean | 指示是否禁止与该组中的另一个组共享项目 | +| `storageSizeLimit` | Float | 根名称空间的总存储限制(以字节为单位) | +| `subgroupCreationLevel` | String | 在组内创建子组所需的权限级别 | +| `temporaryStorageIncreaseEndsOn` | Time | 直到临时存储增加生效的日期 | +| `twoFactorGracePeriod` | Int | 强制执行两因素身份验证的时间 | +| `userPermissions` | GroupPermissions! | 当前用户对该资源的权限 | +| `visibility` | String | 名称空间的可见性 | +| `webUrl` | String! | 网上论坛网址 | + +## GroupMember[](#groupmember "Permalink") + +代表小组成员 + +| Name | Type | Description | +| --- | --- | --- | +| `accessLevel` | AccessLevel | GitLab ::访问级别 | +| `createdAt` | Time | 创建成员的日期和时间 | +| `createdBy` | User | 授权会员的用户 | +| `expiresAt` | Time | 成员资格到期的日期和时间 | +| `group` | Group | 用户所属的组 | +| `updatedAt` | Time | 成员的最新更新日期和时间 | +| `userPermissions` | GroupPermissions! | 当前用户对该资源的权限 | + +## GroupPermissions[](#grouppermissions "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `readGroup` | Boolean! | 指示用户可以对此资源执行`read_group` | + +## Issue[](#issue "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User! | 造成问题的使用者 | +| `closedAt` | Time | 该问题何时结束的时间戳 | +| `confidential` | Boolean! | 表示问题是机密的 | +| `createdAt` | Time! | 问题创建时间的时间戳记 | +| `description` | String | 问题说明 | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `designCollection` | DesignCollection | 与此问题相关的设计图像的收集 | +| `designs` | DesignCollection | **不推荐使用:**使用`designCollection` . 在 12.2 中弃用 | +| `discussionLocked` | Boolean! | 表示讨论已锁定在该问题上 | +| `downvotes` | Int! | 问题已收到的否决票数 | +| `dueDate` | Time | 发行日期 | +| `epic` | Epic | 此问题所属的史诗 | +| `healthStatus` | HealthStatus | 当前的健康状况. 如果禁用了`save_issuable_health_status`功能标志,则返回 null. | +| `id` | ID! | 问题编号 | +| `iid` | ID! | 问题的内部 ID | +| `iteration` | Iteration | 迭代问题 | +| `milestone` | Milestone | 问题的里程碑 | +| `reference` | String! | 内部参考的问题. 默认以缩写形式返回 | +| `relativePosition` | Int | 问题的相对位置(用于在史诗树和问题板上定位) | +| `state` | IssueState! | 问题状态 | +| `subscribed` | Boolean! | 指示当前登录的用户已订阅该问题 | +| `taskCompletionStatus` | TaskCompletionStatus! | 问题的任务完成状态 | +| `timeEstimate` | Int! | 问题的时间估算 | +| `title` | String! | 问题标题 | +| `titleHtml` | String | GitLab 风味 Markdown `title`渲染 | +| `totalTimeSpent` | Int! | 报告在此问题上花费的总时间 | +| `updatedAt` | Time! | 问题上次更新的时间戳 | +| `upvotes` | Int! | 问题已收到的投票数 | +| `userNotesCount` | Int! | 用户对此问题的注释数 | +| `userPermissions` | IssuePermissions! | 当前用户对该资源的权限 | +| `webPath` | String! | 问题的网络路径 | +| `webUrl` | String! | 问题的网址 | +| `weight` | Int | 问题的权重 | + +## IssuePermissions[](#issuepermissions "Permalink") + +检查当前用户在问题上的权限 + +| Name | Type | Description | +| --- | --- | --- | +| `adminIssue` | Boolean! | 指示用户可以对此资源执行`admin_issue` | +| `createDesign` | Boolean! | 指示用户可以对此资源执行`create_design` | +| `createNote` | Boolean! | 指示用户可以在此资源上执行`create_note` | +| `destroyDesign` | Boolean! | 指示用户可以对此资源执行`destroy_design` | +| `readDesign` | Boolean! | 指示用户可以对此资源执行`read_design` | +| `readIssue` | Boolean! | 指示用户可以对此资源执行`read_issue` | +| `reopenIssue` | Boolean! | 指示用户可以对此资源执行`reopen_issue` | +| `updateIssue` | Boolean! | 指示用户可以对此资源执行`update_issue` | + +## IssueSetConfidentialPayload[](#issuesetconfidentialpayload "Permalink") + +自动生成的 IssueSetConfidential 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后的问题 | + +## IssueSetDueDatePayload[](#issuesetduedatepayload "Permalink") + +自动生成的 IssueSetDueDate 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后的问题 | + +## IssueSetIterationPayload[](#issuesetiterationpayload "Permalink") + +自动生成的 IssueSetIteration 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后的问题 | + +## IssueSetLockedPayload[](#issuesetlockedpayload "Permalink") + +自动生成的 IssueSetLocked 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后的问题 | + +## IssueSetWeightPayload[](#issuesetweightpayload "Permalink") + +自动生成的 IssueSetWeight 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后的问题 | + +## Iteration[](#iteration "Permalink") + +表示一个迭代对象. + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time! | 迭代创建的时间戳 | +| `description` | String | 迭代描述 | +| `dueDate` | Time | 迭代到期日期的时间戳 | +| `id` | ID! | 迭代 ID | +| `iid` | ID! | 迭代的内部 ID | +| `startDate` | Time | 迭代开始日期的时间戳 | +| `state` | IterationState! | 迭代状态 | +| `title` | String! | 迭代标题 | +| `updatedAt` | Time! | 上次迭代更新的时间戳 | +| `webPath` | String! | 迭代的 Web 路径 | +| `webUrl` | String! | 迭代的 Web URL | + +## JiraImport[](#jiraimport "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time | 创建 Jira 导入的时间戳 | +| `failedToImportCount` | Int! | 导入失败的问题数 | +| `importedIssuesCount` | Int! | 成功导入的问题数 | +| `jiraProjectKey` | String! | 导入的 Jira 项目的项目密钥 | +| `scheduledAt` | Time | 计划导入 Jira 的时间戳 | +| `scheduledBy` | User | 开始导入 Jira 的用户 | +| `totalIssueCount` | Int! | 尝试导入的问题总数 | + +## JiraImportStartPayload[](#jiraimportstartpayload "Permalink") + +自动生成的 JiraImportStart 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | Errors encountered during execution of the mutation. | +| `jiraImport` | JiraImport | 突变后的 Jira 导入数据 | + +## JiraImportUsersPayload[](#jiraimportuserspayload "Permalink") + +自动生成的 JiraImportUsers 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `jiraUsers` | JiraUser! =>数组 | 从 Jira 返回的用户,并通过电子邮件和姓名进行匹配(如果可能). | + +## JiraProject[](#jiraproject "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `key` | String! | 吉拉项目的关键 | +| `name` | String | Jira 项目的名称 | +| `projectId` | Int! | Jira 项目的 ID | + +## JiraService[](#jiraservice "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `active` | Boolean | 指示服务是否处于活动状态 | +| `projects` | JiraProjectConnection | 通过 Jira REST API 获取的所有 Jira 项目的列表 | +| `type` | String | 服务的类别名称 | + +## JiraUser[](#jirauser "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `gitlabId` | Int | 匹配的 GitLab 用户的 ID | +| `gitlabName` | String | 匹配的 GitLab 用户名 | +| `gitlabUsername` | String | 匹配的 GitLab 用户的用户名 | +| `jiraAccountId` | String! | Jira 用户的帐户 ID | +| `jiraDisplayName` | String! | Jira 用户的显示名称 | +| `jiraEmail` | String | Jira 用户的电子邮件,仅针对具有公共电子邮件的用户返回 | + +## Label[](#label "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `color` | String! | 标签的背景色 | +| `description` | String | 标签的说明(Markdown 呈现为 HTML 以进行缓存) | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `id` | ID! | 标签编号 | +| `textColor` | String! | 标签的文字颜色 | +| `title` | String! | 标签内容 | + +## MarkAsSpamSnippetPayload[](#markasspamsnippetpayload "Permalink") + +自动生成的 MarkAsSpamSnippet 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `snippet` | Snippet | 突变后的代码段 | + +## MergeRequest[](#mergerequest "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `allowCollaboration` | Boolean | 指示目标项目的成员是否可以推送到分叉 | +| `author` | User | 创建此合并请求的用户 | +| `createdAt` | Time! | 创建合并请求的时间戳 | +| `defaultMergeCommitMessage` | String | 合并请求的默认合并提交消息 | +| `description` | String | 合并请求的描述(Markdown 渲染为 HTML 以进行缓存) | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `diffHeadSha` | String | 合并请求的不同头 SHA | +| `diffRefs` | DiffRefs | 此合并请求的基础 SHA,头部 SHA 和起始 SHA 的引用 | +| `diffStats` | DiffStats! =>数组 | 有关在此合并请求中更改了哪些文件的详细信息 | +| `diffStatsSummary` | DiffStatsSummary | 在此合并请求中更改了哪些文件的摘要 | +| `discussionLocked` | Boolean! | 指示是否仅将对合并请求的注释锁定为成员 | +| `downvotes` | Int! | 合并请求的否决票数 | +| `forceRemoveSourceBranch` | Boolean | 指示合并后项目设置是否会导致源分支删除 | +| `headPipeline` | Pipeline | 在合并请求的分支 HEAD 上运行的管道 | +| `id` | ID! | 合并请求的 ID | +| `iid` | String! | 合并请求的内部 ID | +| `inProgressMergeCommitSha` | String | 如果合并正在进行,则提交合并请求的 SHA | +| `mergeCommitMessage` | String | **不推荐使用:**使用`defaultMergeCommitMessage` . 在 11.8 中已弃用 | +| `mergeCommitSha` | String | 合并请求提交的 SHA(一旦合并就设置) | +| `mergeError` | String | 由于合并错误而导致的错误消息 | +| `mergeOngoing` | Boolean! | 指示当前是否正在发生合并 | +| `mergeStatus` | String | 合并请求的状态 | +| `mergeWhenPipelineSucceeds` | Boolean | 指示在管道成功(MWPS)时是否已将合并设置为要合并 | +| `mergeableDiscussionsState` | Boolean | 指示合并请求中的所有讨论是否都已解决,从而允许合并请求被合并 | +| `mergedAt` | Time | 合并请求合并的时间戳记;如果未合并,则为 null | +| `milestone` | Milestone | 合并请求的里程碑 | +| `project` | Project! | target_project 的别名 | +| `projectId` | Int! | 合并请求项目的 ID | +| `rebaseCommitSha` | String | 重新设置合并请求的提交 SHA | +| `rebaseInProgress` | Boolean! | 指示合并请求当前是否正在进行重新设置 | +| `reference` | String! | 合并请求的内部参考. 默认以缩写形式返回 | +| `shouldBeRebased` | Boolean! | 指示合并请求是否将被重定基础 | +| `shouldRemoveSourceBranch` | Boolean | 指示在合并后是否会删除合并请求的源分支 | +| `sourceBranch` | String! | 合并请求的源分支 | +| `sourceBranchExists` | Boolean! | 指示合并请求的源分支是否存在 | +| `sourceProject` | Project | 合并请求的源项目 | +| `sourceProjectId` | Int | 合并请求源项目的 ID | +| `state` | MergeRequestState! | 合并请求的状态 | +| `subscribed` | Boolean! | 指示当前登录的用户是否订阅了此合并请求 | +| `targetBranch` | String! | 合并请求的目标分支 | +| `targetBranchExists` | Boolean! | 指示合并请求的目标分支是否存在 | +| `targetProject` | Project! | 合并请求的目标项目 | +| `targetProjectId` | Int! | 合并请求目标项目的 ID | +| `taskCompletionStatus` | TaskCompletionStatus! | 任务的完成状态 | +| `timeEstimate` | Int! | 合并请求的时间估算 | +| `title` | String! | 合并请求的标题 | +| `titleHtml` | String | GitLab 风味 Markdown `title`渲染 | +| `totalTimeSpent` | Int! | 报告为在合并请求上花费的总时间 | +| `updatedAt` | Time! | 合并请求上次更新的时间戳 | +| `upvotes` | Int! | 合并请求的投票数 | +| `userNotesCount` | Int | 用户记录合并请求的数量 | +| `userPermissions` | MergeRequestPermissions! | 当前用户对该资源的权限 | +| `webUrl` | String | 合并请求的网址 | +| `workInProgress` | Boolean! | 指示合并请求是否正在进行中(WIP) | + +## MergeRequestCreatePayload[](#mergerequestcreatepayload "Permalink") + +自动生成的 MergeRequestCreate 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestPermissions[](#mergerequestpermissions "Permalink") + +检查合并请求中当前用户的权限 + +| Name | Type | Description | +| --- | --- | --- | +| `adminMergeRequest` | Boolean! | 指示用户可以对此资源执行`admin_merge_request` | +| `cherryPickOnCurrentMergeRequest` | Boolean! | 表示用户可以对此资源执行`cherry_pick_on_current_merge_request` | +| `createNote` | Boolean! | 指示用户可以在此资源上执行`create_note` | +| `pushToSourceBranch` | Boolean! | 指示用户可以对此资源执行`push_to_source_branch` | +| `readMergeRequest` | Boolean! | 指示用户可以对此资源执行`read_merge_request` | +| `removeSourceBranch` | Boolean! | 指示用户可以对此资源执行`remove_source_branch` | +| `revertOnCurrentMergeRequest` | Boolean! | 指示用户可以对此资源执行`revert_on_current_merge_request` | +| `updateMergeRequest` | Boolean! | 指示用户可以对此资源执行`update_merge_request` | + +## MergeRequestSetAssigneesPayload[](#mergerequestsetassigneespayload "Permalink") + +自动生成的 MergeRequestSetAssignees 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestSetLabelsPayload[](#mergerequestsetlabelspayload "Permalink") + +自动生成的 MergeRequestSetLabels 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestSetLockedPayload[](#mergerequestsetlockedpayload "Permalink") + +自动生成的 MergeRequestSetLocked 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestSetMilestonePayload[](#mergerequestsetmilestonepayload "Permalink") + +自动生成的 MergeRequestSetMilestone 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestSetSubscriptionPayload[](#mergerequestsetsubscriptionpayload "Permalink") + +自动生成的 MergeRequestSetSubscription 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestSetWipPayload[](#mergerequestsetwippayload "Permalink") + +自动生成的 MergeRequestSetWip 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## MergeRequestUpdatePayload[](#mergerequestupdatepayload "Permalink") + +自动生成的 MergeRequestUpdate 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `mergeRequest` | MergeRequest | 突变后的合并请求 | + +## Metadata[](#metadata "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `revision` | String! | Revision | +| `version` | String! | Version | + +## MetricsDashboard[](#metricsdashboard "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `path` | String | 具有仪表板定义的文件的路径 | +| `schemaValidationWarnings` | 串! =>数组 | 仪表板架构验证警告 | + +## MetricsDashboardAnnotation[](#metricsdashboardannotation "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `description` | String | 注释说明 | +| `endingAt` | Time | 注释时间跨度的时间戳标记结束 | +| `id` | ID! | 注释的 ID | +| `panelId` | String | 注释应作用于的仪表板面板的 ID | +| `startingAt` | Time | 带注释的时间跨度的时间戳标记开始 | + +## Milestone[](#milestone "Permalink") + +代表一个里程碑. + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time! | 里程碑创建的时间戳 | +| `description` | String | 里程碑说明 | +| `dueDate` | Time | 里程碑到期日期的时间戳记 | +| `groupMilestone` | Boolean! | 指示里程碑是否在组级别 | +| `id` | ID! | 里程碑的 ID | +| `projectMilestone` | Boolean! | 指示里程碑是否在项目级别 | +| `startDate` | Time | 里程碑开始日期的时间戳记 | +| `state` | MilestoneStateEnum! | 里程碑状态 | +| `stats` | MilestoneStats | 里程碑统计 | +| `subgroupMilestone` | Boolean! | 指示里程碑是否在子组级别 | +| `title` | String! | 里程碑标题 | +| `updatedAt` | Time! | 最近里程碑更新的时间戳 | +| `webPath` | String! | 里程碑的 Web 路径 | + +## MilestoneStats[](#milestonestats "Permalink") + +包含有关里程碑的统计信息 + +| Name | Type | Description | +| --- | --- | --- | +| `closedIssuesCount` | Int | 与里程碑相关的已解决问题的数量 | +| `totalIssuesCount` | Int | 与里程碑相关的总问题数 | + +## Namespace[](#namespace "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `description` | String | 命名空间的描述 | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `fullName` | String! | 命名空间的全名 | +| `fullPath` | ID! | 命名空间的完整路径 | +| `id` | ID! | 命名空间的 ID | +| `lfsEnabled` | Boolean | 指示是否为名称空间启用了大文件存储(LFS) | +| `name` | String! | 命名空间的名称 | +| `path` | String! | 命名空间的路径 | +| `requestAccessEnabled` | Boolean | 指示用户是否可以请求访问名称空间 | +| `rootStorageStatistics` | RootStorageStatistics | 命名空间的聚合存储统计信息. 仅适用于根名称空间 | +| `storageSizeLimit` | Float | 根名称空间的总存储限制(以字节为单位) | +| `temporaryStorageIncreaseEndsOn` | Time | 直到临时存储增加生效的日期 | +| `visibility` | String | 名称空间的可见性 | + +## Note[](#note "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User! | 撰写此笔记的用户 | +| `body` | String! | 注释内容 | +| `bodyHtml` | String | GitLab 风味 Markdown 渲染`note` | +| `confidential` | Boolean | 指示此注释是否保密 | +| `createdAt` | Time! | 笔记创建的时间戳 | +| `discussion` | Discussion | 本说明的讨论属于 | +| `id` | ID! | 笔记编号 | +| `position` | DiffPosition | 此注释在差异上的位置 | +| `project` | Project | 与笔记相关的项目 | +| `resolvable` | Boolean! | 指示对象是否可以解析 | +| `resolved` | Boolean! | 指示对象是否已解析 | +| `resolvedAt` | Time | 解析对象的时间戳 | +| `resolvedBy` | User | 解决对象的用户 | +| `system` | Boolean! | 指示此注释是由系统还是由用户创建的 | +| `systemNoteIconName` | String | 系统注释对应的图标名称 | +| `updatedAt` | Time! | 笔记上一次活动的时间戳 | +| `userPermissions` | NotePermissions! | 当前用户对该资源的权限 | + +## NotePermissions[](#notepermissions "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `adminNote` | Boolean! | 指示用户可以对此资源执行`admin_note` | +| `awardEmoji` | Boolean! | 表示用户可以在此资源上执行`award_emoji` | +| `createNote` | Boolean! | 指示用户可以在此资源上执行`create_note` | +| `readNote` | Boolean! | 指示用户可以对此资源执行`read_note` | +| `resolveNote` | Boolean! | 指示用户可以对此资源执行`resolve_note` | + +## Package[](#package "Permalink") + +代表包裹 + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time! | 创建日期 | +| `id` | ID! | 包裹 ID | +| `name` | String! | 包装名称 | +| `packageType` | PackageTypeEnum! | 包装类型 | +| `updatedAt` | Time! | 更新日期 | +| `version` | String | 包的版本 | + +## PackageFileRegistry[](#packagefileregistry "Permalink") + +表示软件包文件的同步和验证状态 + +| Name | Type | Description | +| --- | --- | --- | +| `createdAt` | Time | PackageFileRegistry 创建时的时间戳记 | +| `id` | ID! | PackageFileRegistry 的 ID | +| `lastSyncFailure` | String | PackageFileRegistry 同步期间的错误消息 | +| `lastSyncedAt` | Time | PackageFileRegistry 最近一次成功同步的时间戳 | +| `packageFileId` | ID! | PackageFile 的 ID | +| `retryAt` | Time | 时间戳,之后 PackageFileRegistry 应该重新同步 | +| `retryCount` | Int | PackageFileRegistry 连续失败的同步尝试次数 | +| `state` | RegistryState | PackageFileRegistry 的同步状态 | + +## PageInfo[](#pageinfo "Permalink") + +有关连接中的分页的信息. + +| Name | Type | Description | +| --- | --- | --- | +| `endCursor` | String | 向前分页时,光标继续. | +| `hasNextPage` | Boolean! | 在向前分页时,还有更多项目吗? | +| `hasPreviousPage` | Boolean! | 向后分页时,还有更多项目吗? | +| `startCursor` | String | 向后分页时,光标继续. | + +## Pipeline[](#pipeline "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `beforeSha` | String | 源分支的基本 SHA | +| `committedAt` | Time | 管道提交的时间戳 | +| `coverage` | Float | 覆盖率 | +| `createdAt` | Time! | 管道创建的时间戳 | +| `detailedStatus` | DetailedStatus! | 管道的详细状态 | +| `duration` | Int | 管道持续时间(以秒为单位) | +| `finishedAt` | Time | 管道完成的时间戳 | +| `id` | ID! | 管道 ID | +| `iid` | String! | 管道的内部 ID | +| `securityReportSummary` | SecurityReportSummary | 管道的每个安全扫描程序的漏洞和扫描的资源计数 | +| `sha` | String! | 管道提交的 SHA | +| `startedAt` | Time | 管道启动的时间戳 | +| `status` | PipelineStatusEnum! | 管道的状态(已创建,正在等待 _ 资源,正在准备,正在挂起,正在运行,失败,成功,已取消,已跳过,已手动,已计划) | +| `updatedAt` | Time! | 管道上次活动的时间戳 | +| `userPermissions` | PipelinePermissions! | 当前用户对该资源的权限 | + +## PipelinePermissions[](#pipelinepermissions "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `adminPipeline` | Boolean! | 指示用户可以对此资源执行`admin_pipeline` | +| `destroyPipeline` | Boolean! | 指示用户可以在此资源上执行`destroy_pipeline` | +| `updatePipeline` | Boolean! | 指示用户可以对此资源执行`update_pipeline` | + +## Project[](#project "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `alertManagementAlert` | AlertManagementAlert | 项目的单个警报管理警报 | +| `alertManagementAlertStatusCounts` | AlertManagementAlertStatusCountsType | 按项目状态的警报计数 | +| `allowMergeOnSkippedPipeline` | Boolean | 如果`only_allow_merge_if_pipeline_succeeds`为 true,则指示是否还可以将项目的合并请求与跳过的作业合并 | +| `archived` | Boolean | 指示项目的存档状态 | +| `autocloseReferencedIssues` | Boolean | 指示是否自动关闭默认分支中的合并请求和提交引用的问题 | +| `avatarUrl` | String | 项目头像图像文件的 URL | +| `board` | Board | 该项目的一块板 | +| `containerExpirationPolicy` | ContainerExpirationPolicy | 项目的集装箱过期政策 | +| `containerRegistryEnabled` | Boolean | 指示项目是否在容器注册表中存储 Docker 容器映像 | +| `createdAt` | Time | 项目创建的时间戳 | +| `description` | String | 项目简介 | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `forksCount` | Int! | 分叉项目的次数 | +| `fullPath` | ID! | 项目的完整路径 | +| `grafanaIntegration` | GrafanaIntegration | 该项目的 Grafana 集成详细信息 | +| `group` | Group | 项目组 | +| `httpUrlToRepo` | String | 通过 HTTPS 连接到项目的 URL | +| `id` | ID! | 项目编号 | +| `importStatus` | String | Status of import background job of the project | +| `issue` | Issue | 该项目的一期 | +| `issuesEnabled` | Boolean | 指示是否为当前用户启用了问题 | +| `jiraImportStatus` | String | 项目的 Jira 导入后台作业的状态 | +| `jobsEnabled` | Boolean | 指示是否为当前用户启用 CI / CD 管道作业 | +| `label` | Label | 此项目上可用的标签 | +| `lastActivityAt` | Time | 项目上次活动的时间戳 | +| `lfsEnabled` | Boolean | 指示项目是否启用了大文件存储(LFS) | +| `mergeRequest` | MergeRequest | 项目的单个合并请求 | +| `mergeRequestsEnabled` | Boolean | 指示是否为当前用户启用了合并请求 | +| `mergeRequestsFfOnlyEnabled` | Boolean | 指示是否不应该创建合并提交,而应该快速转发所有合并,这意味着仅当分支可以快速转发时才允许合并. | +| `name` | String! | 项目名称(无名称空间) | +| `nameWithNamespace` | String! | 项目的全名及其名称空间 | +| `namespace` | Namespace | 项目的命名空间 | +| `onlyAllowMergeIfAllDiscussionsAreResolved` | Boolean | 指示是否只有在解决所有讨论后才能合并项目的合并请求 | +| `onlyAllowMergeIfPipelineSucceeds` | Boolean | 指示项目的合并请求是否只能与成功的作业合并 | +| `openIssuesCount` | Int | 项目未解决的问题数 | +| `path` | String! | 项目路径 | +| `pipeline` | Pipeline | 建立项目管道 | +| `printingMergeRequestLinkEnabled` | Boolean | 指示从命令行推送到项目的 Git 存储库后是否显示用于创建或查看合并请求的链接 | +| `publicJobs` | Boolean | 指示是否可以公共访问项目的管道和作业详细信息,包括输出日志和工件 | +| `release` | Release | 该项目的一个版本 | +| `removeSourceBranchAfterMerge` | Boolean | 指示默认情况下是否应为项目的所有新合并请求启用" `Delete source branch`选项 | +| `repository` | Repository | 项目的 Git 存储库 | +| `requestAccessEnabled` | Boolean | 指示用户是否可以请求成员访问项目 | +| `requirement` | Requirement | 查找单个需求. 仅在启用功能标志`requirements_management`可用. | +| `requirementStatesCount` | RequirementStatesCount | 按状态列出的项目需求数量 | +| `sastCiConfiguration` | SastCiConfiguration | 项目的 SAST CI 配置 | +| `securityScanners` | SecurityScanners | 有关项目中使用的安全分析器的信息 | +| `sentryDetailedError` | SentryDetailedError | 该项目的 Sentry 错误的详细版本 | +| `sentryErrors` | SentryErrorCollection | 分批收集 Sentry 错误的项目 | +| `serviceDeskAddress` | String | 服务台的电子邮件地址. | +| `serviceDeskEnabled` | Boolean | 指示项目是否启用了服务台. | +| `sharedRunnersEnabled` | Boolean | 指示是否为项目启用了共享运行器 | +| `snippetsEnabled` | Boolean | 指示是否为当前用户启用了代码片段 | +| `sshUrlToRepo` | String | 通过 SSH 连接到项目的 URL | +| `starCount` | Int! | 已加注星标的次数 | +| `statistics` | ProjectStatistics | 项目统计 | +| `suggestionCommitMessage` | String | 用于应用合并请求建议的提交消息 | +| `tagList` | String | 项目主题列表(不是 Git 标签) | +| `userPermissions` | ProjectPermissions! | 当前用户对该资源的权限 | +| `visibility` | String | 项目的可见性 | +| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | 计算项目漏洞的每个严重程度 | +| `webUrl` | String | 项目的网址 | +| `wikiEnabled` | Boolean | 指示是否为当前用户启用了 Wiki | + +## ProjectMember[](#projectmember "Permalink") + +代表项目成员 + +| Name | Type | Description | +| --- | --- | --- | +| `accessLevel` | AccessLevel | GitLab ::访问级别 | +| `createdAt` | Time | 创建成员的日期和时间 | +| `createdBy` | User | 授权会员的用户 | +| `expiresAt` | Time | 成员资格到期的日期和时间 | +| `id` | ID! | 会员编号 | +| `project` | Project | 用户是其成员的项目 | +| `updatedAt` | Time | 成员的最新更新日期和时间 | +| `user` | User! | 与成员对象关联的用户 | +| `userPermissions` | ProjectPermissions! | 当前用户对该资源的权限 | + +## ProjectPermissions[](#projectpermissions "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `adminOperations` | Boolean! | 指示用户可以对此资源执行`admin_operations` | +| `adminProject` | Boolean! | 指示用户可以对此资源执行`admin_project` | +| `adminRemoteMirror` | Boolean! | 指示用户可以对此资源执行`admin_remote_mirror` | +| `adminWiki` | Boolean! | 指示用户可以对此资源执行`admin_wiki` | +| `archiveProject` | Boolean! | 指示用户可以对此资源执行`archive_project` | +| `changeNamespace` | Boolean! | 指示用户可以在此资源上执行`change_namespace` | +| `changeVisibilityLevel` | Boolean! | 指示用户可以对此资源执行`change_visibility_level` | +| `createDeployment` | Boolean! | 指示用户可以对此资源执行`create_deployment` | +| `createDesign` | Boolean! | 指示用户可以对此资源执行`create_design` | +| `createIssue` | Boolean! | 指示用户可以对此资源执行`create_issue` | +| `createLabel` | Boolean! | 指示用户可以在此资源上执行`create_label` | +| `createMergeRequestFrom` | Boolean! | 指示用户可以在此资源上执行`create_merge_request_from` | +| `createMergeRequestIn` | Boolean! | 指示用户可以在此资源上执行`create_merge_request_in` | +| `createPages` | Boolean! | 指示用户可以在此资源上执行`create_pages` | +| `createPipeline` | Boolean! | Indicates the user can perform `create_pipeline` on this resource | +| `createPipelineSchedule` | Boolean! | 指示用户可以对此资源执行`create_pipeline_schedule` | +| `createSnippet` | Boolean! | 指示用户可以对此资源执行`create_snippet` | +| `createWiki` | Boolean! | 指示用户可以在此资源上执行`create_wiki` | +| `destroyDesign` | Boolean! | 指示用户可以对此资源执行`destroy_design` | +| `destroyPages` | Boolean! | 指示用户可以在此资源上执行`destroy_pages` | +| `destroyWiki` | Boolean! | 指示用户可以对此资源执行`destroy_wiki` | +| `downloadCode` | Boolean! | 指示用户可以对此资源执行`download_code` | +| `downloadWikiCode` | Boolean! | 指示用户可以在此资源上执行`download_wiki_code` | +| `forkProject` | Boolean! | 指示用户可以对此资源执行`fork_project` | +| `pushCode` | Boolean! | 指示用户可以对此资源执行`push_code` | +| `pushToDeleteProtectedBranch` | Boolean! | 指示用户可以对此资源执行`push_to_delete_protected_branch` | +| `readCommitStatus` | Boolean! | 指示用户可以对此资源执行`read_commit_status` | +| `readCycleAnalytics` | Boolean! | 指示用户可以对此资源执行`read_cycle_analytics` | +| `readDesign` | Boolean! | 指示用户可以对此资源执行`read_design` | +| `readMergeRequest` | Boolean! | 指示用户可以对此资源执行`read_merge_request` | +| `readPagesContent` | Boolean! | 指示用户可以对此资源执行`read_pages_content` | +| `readProject` | Boolean! | 指示用户可以对此资源执行`read_project` | +| `readProjectMember` | Boolean! | 指示用户可以对此资源执行`read_project_member` | +| `readWiki` | Boolean! | 指示用户可以对此资源执行`read_wiki` | +| `removeForkProject` | Boolean! | 指示用户可以对此资源执行`remove_fork_project` | +| `removePages` | Boolean! | 指示用户可以对此资源执行`remove_pages` | +| `removeProject` | Boolean! | 指示用户可以对此资源执行`remove_project` | +| `renameProject` | Boolean! | 指示用户可以对此资源执行`rename_project` | +| `requestAccess` | Boolean! | 指示用户可以对此资源执行`request_access` | +| `updatePages` | Boolean! | 指示用户可以对此资源执行`update_pages` | +| `updateWiki` | Boolean! | 指示用户可以对此资源执行`update_wiki` | +| `uploadFile` | Boolean! | 指示用户可以在此资源上执行`upload_file` | + +## ProjectStatistics[](#projectstatistics "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `buildArtifactsSize` | Float! | 构建项目的工件大小 | +| `commitCount` | Float! | 提交项目数 | +| `lfsObjectsSize` | Float! | 项目的大文件存储(LFS)对象大小 | +| `packagesSize` | Float! | 项目包装尺寸 | +| `repositorySize` | Float! | 项目的存储库大小 | +| `snippetsSize` | Float | 项目片段大小 | +| `storageSize` | Float! | 项目的存储大小 | +| `wikiSize` | Float | 项目的 Wiki 大小 | + +## Release[](#release "Permalink") + +代表发行 + +| Name | Type | Description | +| --- | --- | --- | +| `assets` | ReleaseAssets | 发行资产 | +| `author` | User | 创建发布的用户 | +| `commit` | Commit | 与发布相关的提交 | +| `createdAt` | Time | 创建版本的时间戳 | +| `description` | String | 版本说明(也称为"发行说明") | +| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | +| `links` | ReleaseLinks | 版本链接 | +| `name` | String | 发布名称 | +| `releasedAt` | Time | 发布版本的时间戳 | +| `tagName` | String | 与版本关联的标签名称 | +| `tagPath` | String | 与版本关联的标签的相对 Web 路径 | + +## ReleaseAssetLink[](#releaseassetlink "Permalink") + +表示与版本关联的资产链接 + +| Name | Type | Description | +| --- | --- | --- | +| `external` | Boolean | 表示链接指向外部资源 | +| `id` | ID! | 链接 ID | +| `linkType` | ReleaseAssetLinkType | 链接的类型: `other` , `runbook` , `image` , `package` ; 默认为`other` | +| `name` | String | Name of the link | +| `url` | String | 链接的 URL | + +## ReleaseAssets[](#releaseassets "Permalink") + +与发布相关的所有资产的容器 + +| Name | Type | Description | +| --- | --- | --- | +| `count` | Int | 发布的资产数量 | + +## ReleaseEvidence[](#releaseevidence "Permalink") + +释放证据 + +| Name | Type | Description | +| --- | --- | --- | +| `collectedAt` | Time | 证据收集的时间戳 | +| `filepath` | String | 可从中下载证据的 URL | +| `id` | ID! | 证据编号 | +| `sha` | String | 证据哈希的 SHA1 ID | + +## ReleaseLinks[](#releaselinks "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `editUrl` | String | 版本的编辑页面的 HTTP URL | +| `issuesUrl` | String | 此版本过滤的问题页面的 HTTP URL | +| `mergeRequestsUrl` | String | 此版本过滤的合并请求页面的 HTTP URL | +| `selfUrl` | String | 版本的 HTTP URL | + +## ReleaseSource[](#releasesource "Permalink") + +表示特定格式附加到发行版的源代码 + +| Name | Type | Description | +| --- | --- | --- | +| `format` | String | 来源格式 | +| `url` | String | 源代码下载 URL | + +## RemoveAwardEmojiPayload[](#removeawardemojipayload "Permalink") + +自动生成的 RemoveAwardEmoji 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `awardEmoji` | AwardEmoji | 突变后的奖励表情符号 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## RemoveProjectFromSecurityDashboardPayload[](#removeprojectfromsecuritydashboardpayload "Permalink") + +自动生成的 RemoveProjectFromSecurityDashboard 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## Repository[](#repository "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `empty` | Boolean! | 表示存储库中没有可见的内容 | +| `exists` | Boolean! | 表示磁盘上存在相应的 Git 存储库 | +| `rootRef` | String | 存储库的默认分支 | +| `tree` | Tree | 仓库的树 | + +## Requirement[](#requirement "Permalink") + +代表一个要求 + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User! | 需求的作者 | +| `createdAt` | Time! | 创建需求的时间戳 | +| `id` | ID! | 需求 ID | +| `iid` | ID! | 需求的内部 ID | +| `project` | Project! | 需求所属的项目 | +| `state` | RequirementState! | 需求状态 | +| `title` | String | 要求的标题 | +| `updatedAt` | Time! | 上一次更新需求的时间戳 | +| `userPermissions` | RequirementPermissions! | 当前用户对该资源的权限 | + +## RequirementPermissions[](#requirementpermissions "Permalink") + +根据需要检查当前用户的权限 + +| Name | Type | Description | +| --- | --- | --- | +| `adminRequirement` | Boolean! | 指示用户可以对此资源执行`admin_requirement` | +| `createRequirement` | Boolean! | 指示用户可以对此资源执行`create_requirement` | +| `destroyRequirement` | Boolean! | 指示用户可以对此资源执行`destroy_requirement` | +| `readRequirement` | Boolean! | 指示用户可以对此资源执行`read_requirement` | +| `updateRequirement` | Boolean! | 指示用户可以对此资源执行`update_requirement` | + +## RequirementStatesCount[](#requirementstatescount "Permalink") + +需求状态的计数. + +| Name | Type | Description | +| --- | --- | --- | +| `archived` | Int | 已归档需求数 | +| `opened` | Int | 打开的需求数 | + +## RootStorageStatistics[](#rootstoragestatistics "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `buildArtifactsSize` | Float! | CI 工件大小(以字节为单位) | +| `lfsObjectsSize` | Float! | LFS 对象大小(以字节为单位) | +| `packagesSize` | Float! | 包大小(以字节为单位) | +| `repositorySize` | Float! | Git 存储库大小(以字节为单位) | +| `snippetsSize` | Float! | 片段大小(以字节为单位) | +| `storageSize` | Float! | 总存储字节数 | +| `wikiSize` | Float! | Wiki 大小(以字节为单位) | + +## RunDASTScanPayload[](#rundastscanpayload "Permalink") + +自动生成的 RunDASTScan 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `pipelineUrl` | String | 创建的管道的 URL. | + +## SastCiConfigurationAnalyzersEntity[](#sastciconfigurationanalyzersentity "Permalink") + +代表 SAST CI 配置中的分析器实体 + +| Name | Type | Description | +| --- | --- | --- | +| `description` | String | 表单上显示的分析器描述. | +| `enabled` | Boolean | 指示是否启用分析仪. | +| `label` | String | 配置 UI 中使用的分析器标签. | +| `name` | String | 分析仪的名称. | + +## SastCiConfigurationEntity[](#sastciconfigurationentity "Permalink") + +代表 SAST CI 配置中的实体 + +| Name | Type | Description | +| --- | --- | --- | +| `defaultValue` | String | 如果值为空,则使用默认值. | +| `description` | String | 表单上显示的实体描述. | +| `field` | String | 实体的 CI 关键字. | +| `label` | String | 表单中使用的实体的标签. | +| `type` | String | 字段值的类型. | +| `value` | String | 实体的当前值. | + +## SastCiConfigurationOptionsEntity[](#sastciconfigurationoptionsentity "Permalink") + +代表 SAST CI 配置中选项的实体 + +| Name | Type | Description | +| --- | --- | --- | +| `label` | String | 期权实体的标签. | +| `value` | String | 期权实体的价值. | + +## ScannedResource[](#scannedresource "Permalink") + +表示通过安全扫描扫描的资源 + +| Name | Type | Description | +| --- | --- | --- | +| `requestMethod` | String | 用于访问 URL 的 HTTP 请求方法 | +| `url` | String | 扫描仪扫描的 URL | + +## SecurityReportSummary[](#securityreportsummary "Permalink") + +代表安全报告摘要 + +| Name | Type | Description | +| --- | --- | --- | +| `containerScanning` | SecurityReportSummarySection | container_scanning 扫描的汇总计数 | +| `coverageFuzzing` | SecurityReportSummarySection | coverage_fuzzing 扫描的总计数 | +| `dast` | SecurityReportSummarySection | Dast 扫描的累计计数 | +| `dependencyScanning` | SecurityReportSummarySection | dependency_scanning 扫描的汇总计数 | +| `sast` | SecurityReportSummarySection | sast 扫描的累计计数 | +| `secretDetection` | SecurityReportSummarySection | secret_detection 扫描的总计计数 | + +## SecurityReportSummarySection[](#securityreportsummarysection "Permalink") + +代表安全报告摘要的一部分 + +| Name | Type | Description | +| --- | --- | --- | +| `scannedResourcesCount` | Int | 扫描资源总数 | +| `scannedResourcesCsvPath` | String | 以 CSV 格式下载所有扫描资源的路径 | +| `vulnerabilitiesCount` | Int | 漏洞总数 | + +## SecurityScanners[](#securityscanners "Permalink") + +代表安全扫描器列表 + +| Name | Type | Description | +| --- | --- | --- | +| `available` | SecurityScannerType! =>数组 | 可用于项目的分析仪列表. | +| `enabled` | SecurityScannerType! =>数组 | 为项目启用的分析器列表. | +| `pipelineRun` | SecurityScannerType! => Array | 在最新管道中成功运行的分析仪列表. | + +## SentryDetailedError[](#sentrydetailederror "Permalink") + +哨兵错误. + +| Name | Type | Description | +| --- | --- | --- | +| `count` | Int! | 发生次数 | +| `culprit` | String! | 错误的罪魁祸首 | +| `externalBaseUrl` | String! | Sentry 实例的外部基本 URL | +| `externalUrl` | String! | 错误的外部网址 | +| `firstReleaseLastCommit` | String | 提交错误是第一次被发现 | +| `firstReleaseShortVersion` | String | 发布简短版本错误首次被发现 | +| `firstReleaseVersion` | String | 发布版本错误首次被发现 | +| `firstSeen` | Time! | 首次发现错误的时间戳 | +| `frequency` | SentryErrorFrequency! =>数组 | 最近 24 小时的错误统计信息 | +| `gitlabCommit` | String | 基于发行版的 GitLab 提交 SHA 归因于 Error | +| `gitlabCommitPath` | String | 错误归因于 GitLab 提交的 GitLab 页面的路径 | +| `gitlabIssuePath` | String | GitLab 问题的网址 | +| `id` | ID! | ID (global ID) of the error | +| `lastReleaseLastCommit` | String | 提交错误最后一次出现 | +| `lastReleaseShortVersion` | String | 发布简短版本错误最后一次出现 | +| `lastReleaseVersion` | String | 发布版本错误最后一次出现 | +| `lastSeen` | Time! | 上次出现错误的时间戳 | +| `message` | String | 错误的哨兵元数据消息 | +| `sentryId` | String! | 错误的 ID(哨兵 ID) | +| `sentryProjectId` | ID! | 项目的 ID(哨兵项目) | +| `sentryProjectName` | String! | 受错误影响的项目名称 | +| `sentryProjectSlug` | String! | 错误造成的项目影响 | +| `shortId` | String! | 错误的简称(Sentry ID) | +| `status` | SentryErrorStatus! | 错误状态 | +| `tags` | SentryErrorTags! | 与哨兵错误相关的标签 | +| `title` | String! | 错误标题 | +| `type` | String! | 错误类型 | +| `userCount` | Int! | 受错误影响的用户数 | + +## SentryError[](#sentryerror "Permalink") + +哨兵错误. SentryDetailedError 的简化版本. + +| Name | Type | Description | +| --- | --- | --- | +| `count` | Int! | 发生次数 | +| `culprit` | String! | 错误的罪魁祸首 | +| `externalUrl` | String! | 错误的外部网址 | +| `firstSeen` | Time! | 首次发现错误的时间戳 | +| `frequency` | SentryErrorFrequency! =>数组 | 最近 24 小时的错误统计信息 | +| `id` | ID! | 错误的 ID(全局 ID) | +| `lastSeen` | Time! | 上次出现错误的时间戳 | +| `message` | String | 错误的哨兵元数据消息 | +| `sentryId` | String! | 错误的 ID(哨兵 ID) | +| `sentryProjectId` | ID! | 项目的 ID(哨兵项目) | +| `sentryProjectName` | String! | 受错误影响的项目名称 | +| `sentryProjectSlug` | String! | 错误造成的项目影响 | +| `shortId` | String! | 错误的简称(Sentry ID) | +| `status` | SentryErrorStatus! | 错误状态 | +| `title` | String! | 错误标题 | +| `type` | String! | 错误类型 | +| `userCount` | Int! | 受错误影响的用户数 | + +## SentryErrorCollection[](#sentryerrorcollection "Permalink") + +包含 Sentry 错误和详细错误的集合的对象. + +| Name | Type | Description | +| --- | --- | --- | +| `detailedError` | SentryDetailedError | 该项目的 Sentry 错误的详细版本 | +| `errorStackTrace` | SentryErrorStackTrace | 哨兵错误的堆栈跟踪 | +| `errors` | SentryErrorConnection | 哨兵错误的收集 | +| `externalUrl` | String | 哨兵的外部网址 | + +## SentryErrorFrequency[](#sentryerrorfrequency "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `count` | Int! | 自先前记录的时间以来收到的错误计数 | +| `time` | Time! | 记录错误频率统计信息的时间 | + +## SentryErrorStackTrace[](#sentryerrorstacktrace "Permalink") + +包含用于 Sentry 错误的堆栈跟踪条目的对象. + +| Name | Type | Description | +| --- | --- | --- | +| `dateReceived` | String! | Sentry 收到堆栈跟踪的时间 | +| `issueId` | String! | Sentry 错误的 ID | +| `stackTraceEntries` | SentryErrorStackTraceEntry! =>数组 | 堆栈跟踪条目的 Sentry 错误 | + +## SentryErrorStackTraceContext[](#sentryerrorstacktracecontext "Permalink") + +Sentry 错误堆栈跟踪的对象上下文 + +| Name | Type | Description | +| --- | --- | --- | +| `code` | String! | 上下文的代码号 | +| `line` | Int! | 上下文的行号 | + +## SentryErrorStackTraceEntry[](#sentryerrorstacktraceentry "Permalink") + +包含用于 Sentry 错误的堆栈跟踪条目的对象. + +| Name | Type | Description | +| --- | --- | --- | +| `col` | String | 发生哨兵错误的功能 | +| `fileName` | String | 发生 Sentry 错误的文件 | +| `function` | String | 发生哨兵错误的功能 | +| `line` | String | 发生哨兵错误的功能 | +| `traceContext` | SentryErrorStackTraceContext! =>数组 | Sentry 错误的上下文 | + +## SentryErrorTags[](#sentryerrortags "Permalink") + +哨兵状态错误 + +| Name | Type | Description | +| --- | --- | --- | +| `level` | String | 哨兵错误的严重程度 | +| `logger` | String | 哨兵记录仪错误 | + +## Snippet[](#snippet "Permalink") + +代表代码段条目 + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User | 摘要的所有者 | +| `blob` | SnippetBlob! | 摘要片段 | +| `blobs` | SnippetBlob! =>数组 | 摘要片段 | +| `createdAt` | Time! | 创建此片段的时间戳 | +| `description` | String | 片段说明 | +| `descriptionHtml` | String | GitLab 风味 Markdown 渲染`description` | +| `fileName` | String | 片段的文件名 | +| `httpUrlToRepo` | String | 片段存储库的 HTTP URL | +| `id` | ID! | 摘要的 ID | +| `project` | Project | 代码段与之关联的项目 | +| `rawUrl` | String! | 代码段的原始 URL | +| `sshUrlToRepo` | String | 到代码段存储库的 SSH URL | +| `title` | String! | 摘要标题 | +| `updatedAt` | Time! | 此代码段的时间戳已更新 | +| `userPermissions` | SnippetPermissions! | 当前用户对该资源的权限 | +| `visibilityLevel` | VisibilityLevelsEnum! | 摘要的可见度级别 | +| `webUrl` | String! | 代码段的网址 | + +## SnippetBlob[](#snippetblob "Permalink") + +代表代码段 Blob + +| Name | Type | Description | +| --- | --- | --- | +| `binary` | Boolean! | 显示 Blob 是否为二进制 | +| `externalStorage` | String | Blob 外部存储 | +| `mode` | String | 斑点模式 | +| `name` | String | Blob 名称 | +| `path` | String | 斑点路径 | +| `plainData` | String | Blob 普通高亮数据 | +| `rawPath` | String! | Blob 原始内容端点路径 | +| `renderedAsText` | Boolean! | 显示 Blob 是否呈现为文本 | +| `richData` | String | Blob 高亮显示的数据 | +| `richViewer` | SnippetBlobViewer | Blob 内容丰富的查看器 | +| `simpleViewer` | SnippetBlobViewer! | Blob 内容简单查看器 | +| `size` | Int! | 斑点大小 | + +## SnippetBlobViewer[](#snippetblobviewer "Permalink") + +表示应如何显示 Blob 内容 + +| Name | Type | Description | +| --- | --- | --- | +| `collapsed` | Boolean! | 显示是否应折叠显示 Blob | +| `fileType` | String! | 内容文件类型 | +| `loadAsync` | Boolean! | 显示 blob 内容是否异步加载 | +| `loadingPartialName` | String! | 载入部分名称 | +| `renderError` | String | 呈现 Blob 内容时出错 | +| `tooLarge` | Boolean! | 显示斑点是否太大而无法显示 | +| `type` | BlobViewersType! | Blob 查看器类型 | + +## SnippetPermissions[](#snippetpermissions "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `adminSnippet` | Boolean! | 指示用户可以对此资源执行`admin_snippet` | +| `awardEmoji` | Boolean! | 表示用户可以在此资源上执行`award_emoji` | +| `createNote` | Boolean! | 指示用户可以在此资源上执行`create_note` | +| `readSnippet` | Boolean! | 指示用户可以对此资源执行`read_snippet` | +| `reportSnippet` | Boolean! | 指示用户可以对此资源执行`report_snippet` | +| `updateSnippet` | Boolean! | 指示用户可以对此资源执行`update_snippet` | + +## Submodule[](#submodule "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `flatPath` | String! | 条目的平坦路径 | +| `id` | ID! | 条目 ID | +| `name` | String! | 条目名称 | +| `path` | String! | 条目路径 | +| `sha` | String! | 提交的最后提交 sha | +| `treeUrl` | String | 子模块的树 URL | +| `type` | EntryType! | 树条目的类型 | +| `webUrl` | String | 子模块的 Web URL | + +## TaskCompletionStatus[](#taskcompletionstatus "Permalink") + +任务的完成状态 + +| Name | Type | Description | +| --- | --- | --- | +| `completedCount` | Int! | 完成的任务数 | +| `count` | Int! | 总任务数 | + +## TestReport[](#testreport "Permalink") + +表示需求测试报告. + +| Name | Type | Description | +| --- | --- | --- | +| `author` | User | 测试报告的作者 | +| `createdAt` | Time! | 创建测试报告的时间戳 | +| `id` | ID! | 测试报告编号 | +| `state` | TestReportState! | 测试报告的状态 | + +## Timelog[](#timelog "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `date` | Time! | **不推荐使用:**使用`spentAt` . 在 12.10 中弃用 | +| `issue` | Issue | 记录时间已添加到的问题 | +| `spentAt` | Time | 跟踪时间的时间戳记 | +| `timeSpent` | Int! | 显示的时间(以秒为单位) | +| `user` | User! | 记录时间的用户 | + +## Todo[](#todo "Permalink") + +代表待办事项 + +| Name | Type | Description | +| --- | --- | --- | +| `action` | TodoActionEnum! | 待办事项的动作 | +| `author` | User! | 此待办事项的所有者 | +| `body` | String! | 待办事项的正文 | +| `createdAt` | Time! | 待办事项的时间戳记已创建 | +| `group` | Group | 与该待办事项相关的组 | +| `id` | ID! | 待办事项编号 | +| `project` | Project | 此待办事项与之相关的项目 | +| `state` | TodoStateEnum! | 待办事项的状态 | +| `targetType` | TodoTargetEnum! | 待办事项的目标类型 | + +## TodoMarkDonePayload[](#todomarkdonepayload "Permalink") + +自动生成的 TodoMarkDone 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `todo` | Todo! | 要求的待办事项 | + +## TodoRestoreManyPayload[](#todorestoremanypayload "Permalink") + +自动生成的 TodoRestoreMany 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `todos` | 一切! =>数组 | 全部更新 | +| `updatedIds` | ID! =>数组 | **不推荐使用:**使用待办事项. 在 13.2 中已弃用 | + +## TodoRestorePayload[](#todorestorepayload "Permalink") + +自动生成的 TodoRestore 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `todo` | Todo! | 要求的待办事项 | + +## TodosMarkAllDonePayload[](#todosmarkalldonepayload "Permalink") + +自动生成的 TodosMarkAllDone 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `todos` | 一切! =>数组 | 全部更新 | +| `updatedIds` | ID! =>数组 | **不推荐使用:**使用待办事项. 在 13.2 中已弃用 | + +## ToggleAwardEmojiPayload[](#toggleawardemojipayload "Permalink") + +自动生成的 ToggleAwardEmoji 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `awardEmoji` | AwardEmoji | 突变后的奖励表情符号 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `toggledOn` | Boolean! | 指示表情符号的状态. 如果切换开关授予表情符号,则为 true;如果切换开关删除了表情符号,则为 false. | + +## Tree[](#tree "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `lastCommit` | Commit | 树的最后提交 | + +## TreeEntry[](#treeentry "Permalink") + +代表目录 + +| Name | Type | Description | +| --- | --- | --- | +| `flatPath` | String! | 条目的平坦路径 | +| `id` | ID! | 条目 ID | +| `name` | String! | 条目名称 | +| `path` | String! | 条目路径 | +| `sha` | String! | 提交的最后提交 sha | +| `type` | EntryType! | 树条目的类型 | +| `webUrl` | String | 树条目(目录)的 Web URL | + +## UpdateAlertStatusPayload[](#updatealertstatuspayload "Permalink") + +自动生成的 UpdateAlertStatus 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `alert` | AlertManagementAlert | 突变后的警报 | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后产生的问题 | +| `todo` | Todo | 突变后的待办事项 | + +## UpdateContainerExpirationPolicyPayload[](#updatecontainerexpirationpolicypayload "Permalink") + +自动生成的 UpdateContainerExpirationPolicy 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `containerExpirationPolicy` | ContainerExpirationPolicy | 变更后的容器到期政策 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## UpdateEpicPayload[](#updateepicpayload "Permalink") + +自动生成的 UpdateEpic 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `epic` | Epic | 突变后的史诗 | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | + +## UpdateImageDiffNotePayload[](#updateimagediffnotepayload "Permalink") + +自动生成的 UpdateImageDiffNote 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `note` | Note | 突变后的音符 | + +## UpdateIssuePayload[](#updateissuepayload "Permalink") + +自动生成的 UpdateIssue 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `issue` | Issue | 突变后的问题 | + +## UpdateIterationPayload[](#updateiterationpayload "Permalink") + +自动生成的 UpdateIteration 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `iteration` | Iteration | 更新的迭代 | + +## UpdateNotePayload[](#updatenotepayload "Permalink") + +自动生成的 UpdateNote 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `note` | Note | 突变后的音符 | + +## UpdateRequirementPayload[](#updaterequirementpayload "Permalink") + +自动生成的 UpdateRequirement 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `requirement` | Requirement | 突变后的要求 | + +## UpdateSnippetPayload[](#updatesnippetpayload "Permalink") + +自动生成的 UpdateSnippet 返回类型 + +| Name | Type | Description | +| --- | --- | --- | +| `clientMutationId` | String | 进行突变的客户的唯一标识符. | +| `errors` | 串! =>数组 | 执行突变期间遇到的错误. | +| `snippet` | Snippet | 突变后的代码段 | + +## User[](#user "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `avatarUrl` | String | URL of the user’s avatar | +| `id` | ID! | 用户 ID | +| `name` | String! | 用户易读的名称 | +| `state` | UserState! | 用户状态 | +| `userPermissions` | UserPermissions! | 当前用户对该资源的权限 | +| `username` | String! | 用户的用户名. 在此 GitLab 实例中是唯一的 | +| `webUrl` | String! | 用户的网址 | + +## UserPermissions[](#userpermissions "Permalink") + +| Name | Type | Description | +| --- | --- | --- | +| `createSnippet` | Boolean! | 指示用户可以对此资源执行`create_snippet` | + +## VulnerabilitiesCountByDayAndSeverity[](#vulnerabilitiescountbydayandseverity "Permalink") + +表示在特定日期的特定严重性的漏洞数量 + +| Name | Type | Description | +| --- | --- | --- | +| `count` | Int | 漏洞数量 | +| `day` | ISO8601Date | 计数日期 | +| `severity` | VulnerabilitySeverity | 所计算漏洞的严重性 | + +## Vulnerability[](#vulnerability "Permalink") + +表示漏洞. + +| Name | Type | Description | +| --- | --- | --- | +| `description` | String | 漏洞描述 | +| `id` | ID! | 漏洞的 GraphQL ID | +| `identifiers` | 漏洞标识符! =>数组 | 漏洞的标识符. | +| `location` | VulnerabilityLocation | 漏洞的位置元数据. 其字段取决于发现漏洞的安全扫描的类型 | +| `primaryIdentifier` | VulnerabilityIdentifier | 漏洞的主要标识符. | +| `project` | Project | 发现漏洞的项目 | +| `reportType` | VulnerabilityReportType | 发现漏洞的安全报告的类型(SAST,DEPENDENCY_SCANNING,CONTAINER_SCANNING,DAST,SECRET_DETECTION,COVERAGE_FUZZING) | +| `scanner` | VulnerabilityScanner | 漏洞的扫描程序元数据. | +| `severity` | VulnerabilitySeverity | 漏洞的严重程度(INFO,未知,LOW,MEDIUM,HIGH,CRITICAL) | +| `state` | VulnerabilityState | 漏洞状态(检测,已拒绝,已解决,已确认) | +| `title` | String | 漏洞标题 | +| `userNotesCount` | Int! | 漏洞附带的用户注释数 | +| `userPermissions` | VulnerabilityPermissions! | 当前用户对该资源的权限 | +| `vulnerabilityPath` | String | 漏洞详细信息页面的 URL | + +## VulnerabilityIdentifier[](#vulnerabilityidentifier "Permalink") + +表示漏洞标识符. + +| Name | Type | Description | +| --- | --- | --- | +| `externalId` | String | 漏洞标识符的外部 ID | +| `externalType` | String | 漏洞标识符的外部类型 | +| `name` | String | 漏洞标识符的名称 | +| `url` | String | 漏洞标识符的 URL | + +## VulnerabilityIssueLink[](#vulnerabilityissuelink "Permalink") + +表示漏洞的问题链接. + +| Name | Type | Description | +| --- | --- | --- | +| `id` | ID! | 漏洞的 GraphQL ID | +| `issue` | Issue! | 问题附在问题链接上 | +| `linkType` | VulnerabilityIssueLinkType! | 问题链接的类型 | + +## VulnerabilityLocationContainerScanning[](#vulnerabilitylocationcontainerscanning "Permalink") + +表示通过容器安全扫描发现的漏洞的位置 + +| Name | Type | Description | +| --- | --- | --- | +| `dependency` | VulnerableDependency | 包含漏洞的依赖项 | +| `image` | String | 易受攻击的容器映像的名称 | +| `operatingSystem` | String | 在易受攻击的容器映像上运行的操作系统 | + +## VulnerabilityLocationDast[](#vulnerabilitylocationdast "Permalink") + +表示通过 DAST 扫描发现的漏洞的位置 + +| Name | Type | Description | +| --- | --- | --- | +| `hostname` | String | 漏洞请求的域名 | +| `param` | String | 发生漏洞的 URL 的查询参数 | +| `path` | String | 漏洞请求的 URL 路径和查询字符串 | +| `requestMethod` | String | 易受攻击请求的 HTTP 方法 | + +## VulnerabilityLocationDependencyScanning[](#vulnerabilitylocationdependencyscanning "Permalink") + +表示依赖关系安全扫描发现的漏洞的位置 + +| Name | Type | Description | +| --- | --- | --- | +| `dependency` | VulnerableDependency | 包含漏洞的依赖项 | +| `file` | String | 易受攻击文件的路径 | + +## VulnerabilityLocationSast[](#vulnerabilitylocationsast "Permalink") + +表示通过 SAST 扫描发现的漏洞的位置 + +| Name | Type | Description | +| --- | --- | --- | +| `endLine` | String | 易受攻击的文件中最后相关的行号 | +| `file` | String | 易受攻击文件的路径 | +| `startLine` | String | 漏洞文件中第一相关行的编号 | +| `vulnerableClass` | String | 包含漏洞的类 | +| `vulnerableMethod` | String | 包含漏洞的方法 | + +## VulnerabilityLocationSecretDetection[](#vulnerabilitylocationsecretdetection "Permalink") + +表示通过秘密检测扫描发现的漏洞的位置 + +| Name | Type | Description | +| --- | --- | --- | +| `endLine` | String | 易受攻击的文件中最后相关的行号 | +| `file` | String | 易受攻击文件的路径 | +| `startLine` | String | 漏洞文件中第一相关行的编号 | +| `vulnerableClass` | String | 包含漏洞的类 | +| `vulnerableMethod` | String | 包含漏洞的方法 | + +## VulnerabilityPermissions[](#vulnerabilitypermissions "Permalink") + +检查当前用户对漏洞的权限 + +| Name | Type | Description | +| --- | --- | --- | +| `adminVulnerability` | Boolean! | 指示用户可以对此资源执行`admin_vulnerability` | +| `adminVulnerabilityIssueLink` | Boolean! | 指示用户可以对此资源执行`admin_vulnerability_issue_link` | +| `createVulnerability` | Boolean! | 指示用户可以对此资源执行`create_vulnerability` | +| `createVulnerabilityExport` | Boolean! | 指示用户可以对此资源执行`create_vulnerability_export` | +| `createVulnerabilityFeedback` | Boolean! | 指示用户可以对此资源执行`create_vulnerability_feedback` | +| `destroyVulnerabilityFeedback` | Boolean! | 指示用户可以对此资源执行`destroy_vulnerability_feedback` | +| `readVulnerabilityFeedback` | Boolean! | 指示用户可以对此资源执行`read_vulnerability_feedback` | +| `updateVulnerabilityFeedback` | Boolean! | 指示用户可以对此资源执行`update_vulnerability_feedback` | + +## VulnerabilityScanner[](#vulnerabilityscanner "Permalink") + +表示漏洞扫描程序. + +| Name | Type | Description | +| --- | --- | --- | +| `externalId` | String | 漏洞扫描器的外部 ID | +| `name` | String | 漏洞扫描程序的名称 | +| `reportType` | VulnerabilityReportType | 漏洞报告的类型 | +| `vendor` | String | 漏洞扫描程序的供应商 | + +## VulnerabilitySeveritiesCount[](#vulnerabilityseveritiescount "Permalink") + +按严重性表示漏洞计数 + +| Name | Type | Description | +| --- | --- | --- | +| `critical` | Int | 项目严重程度的漏洞数量 | +| `high` | Int | 项目严重性高的漏洞数量 | +| `info` | Int | 项目的 INFO 严重性漏洞数量 | +| `low` | Int | 项目严重性为 LOW 的漏洞数量 | +| `medium` | Int | 项目 MEDIUM 严重程度的漏洞数量 | +| `unknown` | Int | 该项目严重程度未知的漏洞数量 | + +## VulnerableDependency[](#vulnerabledependency "Permalink") + +表示脆弱的依赖关系. 用于漏洞位置数据 + +| Name | Type | Description | +| --- | --- | --- | +| `package` | VulnerablePackage | 与弱势依赖项相关的软件包 | +| `version` | String | 脆弱依赖的版本 | + +## VulnerablePackage[](#vulnerablepackage "Permalink") + +表示易受攻击的程序包. 用于漏洞依赖性数据 + +| Name | Type | Description | +| --- | --- | --- | +| `name` | String | 易受攻击软件包的名称 | \ No newline at end of file diff --git a/docs/387.md b/docs/387.md new file mode 100644 index 0000000000000000000000000000000000000000..e083ab6cb171fc028f5f8e796f02a32c2af5c52c --- /dev/null +++ b/docs/387.md @@ -0,0 +1,87 @@ +# API V3 to API V4 + +> 原文:[https://docs.gitlab.com/ee/api/v3_to_v4.html](https://docs.gitlab.com/ee/api/v3_to_v4.html) + +* [8.17](#817) +* [9.0](#90) + +# API V3 to API V4[](#api-v3-to-api-v4 "Permalink") + +从 GitLab 9.0 开始,API V4 是首选的版本. + +API V3 从 GitLab 9.5 不支持的,在 8 月 22 日公布,2017 年 API V3 中取出[GitLab 11.0](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36819) . V3 API 文档仍然[可用](https://gitlab.com/gitlab-org/gitlab-foss/blob/8-16-stable/doc/api/README.md) . + +以下是 V3 和 V4 之间所做的更改. + +## 8.17[](#817 "Permalink") + +* Removed `GET /projects/:search` (use: `GET /projects?search=x`) [!8877](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8877) +* `iid`过滤器已从`GET /projects/:id/issues` [!8967 中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8967)删除[.](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8967) +* `GET /projects/:id/merge_requests?iid[]=x&iid[]=y`数组过滤器已重命名为`iids` [!8793](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8793) +* `GET /projects/merge_request/:id`下的端点已被删除(使用: `GET /projects/merge_requests/:id` ) [!8793](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8793) +* 项目摘要不返回不建议使用的字段`expires_at` [!8723](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8723) +* `GET /projects/:id/keys`下的端点已被删除(使用`GET /projects/:id/deploy_keys` ) [!8716](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8716) + +## 9.0[](#90 "Permalink") + +* 当成员已经存在时,为`POST /projects/:id/members`返回状态 409 [!9093](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9093) +* Moved `DELETE /projects/:id/star` to `POST /projects/:id/unstar` [!9328](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9328) +* 删除了以下不建议使用的模板端点(仍然可以使用`/templates`前缀访问这些端点) [!8853](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8853) + * `/licenses` + * `/licenses/:key` + * `/gitignores` + * `/gitlab_ci_ymls` + * `/dockerfiles` + * `/gitignores/:key` + * `/gitlab_ci_ymls/:key` + * `/dockerfiles/:key` +* Moved `POST /projects/fork/:id` to `POST /projects/:id/fork` [!8940](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8940) +* Moved `DELETE /todos` to `POST /todos/mark_as_done` and `DELETE /todos/:todo_id` to `POST /todos/:todo_id/mark_as_done` [!9410](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9410) +* 项目过滤器不再作为`GET /projects/foo` ,而是作为`GET /projects?foo=true`代替[!8962](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8962) + * `GET /projects/visible`和`GET /projects/all`合并到`GET /projects` ,可以在有或没有授权的情况下使用 + * `GET /projects/owned`移至`GET /projects?owned=true` + * `GET /projects/starred`移至`GET /projects?starred=true` +* `GET /projects`返回当前用户可见的所有项目,即使该用户不是成员[!9674](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9674) + * 要获取用户所属的`GET /projects?membership=true` ,请使用`GET /projects?membership=true` +* 返回所有返回数组的端点的分页头[!8606](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8606) +* 添加了`POST /environments/:environment_id/stop`以停止环境[!8808](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8808) +* 删除了`DELETE /projects/:id/deploy_keys/:key_id/disable` 使用`DELETE /projects/:id/deploy_keys/:key_id`代替[!9366](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9366) +* Moved `PUT /users/:id/(block|unblock)` to `POST /users/:id/(block|unblock)` [!9371](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9371) +* 使订阅 API 更 RESTful. 使用`POST /projects/:id/:subscribable_type/:subscribable_id/subscribe`进行订阅,并使用`POST /projects/:id/:subscribable_type/:subscribable_id/unsubscribe`取消订阅资源. [!9325](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9325) +* 标签在`GET /projects/:id/issues`上过滤,并且`GET /issues`现在仅匹配包含所有标签的问题(即:逻辑 AND,而非 OR) [!8849](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8849) +* 将参数`branch_name`重命名为在以下端点上`branch` [!8936](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8936) + * `POST /projects/:id/repository/branches` + * `POST /projects/:id/repository/commits` + * `POST/PUT/DELETE :id/repository/files` +* 改名`merge_when_build_succeeds`参数`merge_when_pipeline_succeeds`以下端点: [!9335](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/) + * `PUT /projects/:id/merge_requests/:merge_request_id/merge` + * `POST /projects/:id/merge_requests/:merge_request_id/cancel_merge_when_pipeline_succeeds` + * `POST /projects` + * `POST /projects/user/:user_id` + * `PUT /projects/:id` +* Renamed `branch_name` to `branch` on `DELETE /projects/:id/repository/branches/:branch` response [!8936](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8936) +* 从项目的创建和编辑操作中删除`public`参数[!8736](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8736) +* 从返回问题列表或合并请求的响应中删除已`subscribed`字段. 获取单个问题或合并请求以获取已`subscribed` [!9661](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9661)的值 +* 在各处使用`visibility`作为字符串参数[!9337](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9337) +* Notes do not return deprecated field `upvote` and `downvote` [!9384](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9384) +* 创建或更新成员时,针对所有验证错误返回 HTTP 状态代码`400` ,而不是有时为`422`错误. [!9523](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9523) +* 删除`GET /groups/owned` . 使用`GET /groups?owned=true`代替[!9505](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9505) +* 在 V4 API 上以异步删除方式返回带有 JSON 正文的 202( `DELETE /projects/:id/repository/merged_branches`和`DELETE /projects/:id` ) [!9449](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9449) +* `GET /projects/:id/milestones?iid[]=x&iid[]=y`数组过滤器已重命名为`iids` [!9096](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9096) +* 在`GET /projects/:id/pipelines`返回有关管道的基本信息[!8875](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8875) +* 将所有`build`参考重命名为`job` [!9463](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9463) +* Drop `GET /projects/:id/repository/commits/:sha/jobs` [!9463](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9463) +* Rename Build Triggers to be Pipeline Triggers API [!9713](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9713) 将构建触发器重命名为管道触发器 API [!9713](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9713) + * `POST /projects/:id/trigger/builds` to `POST /projects/:id/trigger/pipeline` `POST /projects/:id/trigger/builds`到`POST /projects/:id/trigger/pipeline` + * Require description when creating a new trigger `POST /projects/:id/triggers` 创建新触发器`POST /projects/:id/triggers`时需要说明`POST /projects/:id/triggers` +* 简化环境端点上暴露的项目有效负载[!9675](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9675) +* API uses merge request `IID`s (internal ID, as in the web UI) rather than `ID`s. This affects the merge requests, award emoji, todos, and time tracking APIs. [!9530](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9530) +* API 使用问题`IID` (内部 ID,如 Web UI),而不使用`ID` . 这会影响问题,奖励表情符号,待办事项和时间跟踪 API. [!9530](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9530) +* 将`GET /projects/:id/repository/commits`上的初始页面从`0`更改为`1` (类似于 API 的其余部分) [!9679](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9679) +* 返回正确的`GET /projects/:id/repository/commits` `Link`标头数据[!9679](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9679) +* 更新存储库文件的端点[!9637](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9637) + * 将`GET /projects/:id/repository/files?file_path=:file_path`移到`GET /projects/:id/repository/files/:file_path` ( `:file_path`应该用 URL 编码) + * `GET /projects/:id/repository/blobs/:sha`现在返回由`:sha`标识的 blob 的 JSON 属性,而不是查找由`:sha`标识的提交,并在必需的`?filepath=:filepath`标识的那个提交中返回 blob 的原始内容`?filepath=:filepath` + * 将`GET /projects/:id/repository/commits/:sha/blob?file_path=:file_path`和`GET /projects/:id/repository/blobs/:sha?file_path=:file_path`移至`GET /projects/:id/repository/files/:file_path/raw?ref=:sha` + * `GET /projects/:id/repository/tree`参数`ref_name`已重命名为`ref`以保持一致性 +* `confirm`为参数`POST /users`已被弃用,取而代之的`skip_confirmation`参数 \ No newline at end of file diff --git a/docs/388.md b/docs/388.md new file mode 100644 index 0000000000000000000000000000000000000000..cce2b23ddea7c347afb4002fe759d0c97bf047b6 --- /dev/null +++ b/docs/388.md @@ -0,0 +1,43 @@ +# Validate the `.gitlab-ci.yml` (API) + +> 原文:[https://docs.gitlab.com/ee/api/lint.html](https://docs.gitlab.com/ee/api/lint.html) + +# Validate the `.gitlab-ci.yml` (API)[](#validate-the-gitlab-ciyml-api "Permalink") + +在 GitLab 8.12 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5953) . + +检查您的`.gitlab-ci.yml`文件是否有效. + +``` +POST /ci/lint +``` + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `content` | string | yes | the `.gitlab-ci.yaml` content | + +``` +curl --header "Content-Type: application/json" "https://gitlab.example.com/api/v4/ci/lint" --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}' +``` + +请务必复制并粘贴`.gitlab-ci.yml`的确切内容,因为 YAML 对于缩进和空格非常挑剔. + +响应示例: + +* 有效内容: + + ``` + { "status": "valid", "errors": [] } + ``` + +* 无效的内容: + + ``` + { "status": "invalid", "errors": [ "variables config should be a hash of key value pairs" ] } + ``` + +* 没有 content 属性: + + ``` + { "error": "content is missing" } + ``` \ No newline at end of file diff --git a/docs/389.md b/docs/389.md new file mode 100644 index 0000000000000000000000000000000000000000..4788610e5c046492f5f20a9ad136ae5f587c1b0f --- /dev/null +++ b/docs/389.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/api/oauth2.html](https://docs.gitlab.com/ee/api/oauth2.html) \ No newline at end of file diff --git a/docs/390.md b/docs/390.md new file mode 100644 index 0000000000000000000000000000000000000000..f78cfbb934bcd083545ec5ea4e3031b311231e0c --- /dev/null +++ b/docs/390.md @@ -0,0 +1,167 @@ +# User Docs + +> 原文:[https://docs.gitlab.com/ee/user/](https://docs.gitlab.com/ee/user/) + +* [Overview](#overview) + * [Concepts](#concepts) +* [Use cases](#use-cases) +* [Projects](#projects) +* [GitLab CI/CD](#gitlab-cicd) +* [Account](#account) +* [Groups](#groups) +* [Discussions](#discussions) + * [GitLab Flavored Markdown (GFM)](#gitlab-flavored-markdown-gfm) +* [Todos](#todos) +* [Search](#search) +* [Snippets](#snippets) +* [Keyboard shortcuts](#keyboard-shortcuts) +* [Integrations](#integrations) +* [Webhooks](#webhooks) +* [API](#api) +* [Git and GitLab](#git-and-gitlab) +* [Instance statistics](#instance-statistics) +* [Operations Dashboard](#operations-dashboard-premium) + +# User Docs[](#user-docs "Permalink") + +欢迎来到 GitLab! 我们很高兴您在这里! + +作为 GitLab 用户,您将有权访问您的[订阅](https://about.gitlab.com/pricing/)包括的所有功能,但[GitLab 管理员](../administration/index.html)设置除外,除非您具有安装,配置和升级 GitLab 实例的管理员权限. + +[GitLab.com 的](https://gitlab.com/)管理员特权仅限于 GitLab 团队. + +有关配置 GitLab 自管理实例的更多信息,请参阅[管理员文档](../administration/index.html) . + +## Overview[](#overview "Permalink") + +GitLab 是一个完全集成的软件开发平台,使您的团队能够在同一平台上保持透明,快速,有效和凝聚力,从讨论新想法到正式生产. + +有关更多信息,请参见[所有 GitLab 功能](https://about.gitlab.com/features/) . + +### Concepts[](#concepts "Permalink") + +要熟悉在 GitLab 上开发代码所需的概念,请阅读以下文章: + +* [Demo: Mastering Code Review With GitLab](https://about.gitlab.com/blog/2017/03/17/demo-mastering-code-review-with-gitlab/). +* [GitLab Workflow: An Overview](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/#gitlab-workflow-use-case-scenario). +* [教程:在 GitLab 中都已连接](https://about.gitlab.com/blog/2016/03/08/gitlab-tutorial-its-all-connected/) :与 GitLab 进行代码协作的概述. +* [Trends in Version Control Land: Microservices](https://about.gitlab.com/blog/2016/08/16/trends-in-version-control-land-microservices/). +* [Trends in Version Control Land: Innersourcing](https://about.gitlab.com/blog/2016/07/07/trends-version-control-innersourcing/). + +## Use cases[](#use-cases "Permalink") + +GitLab 是一个基于 Git 的平台,它集成了许多用于软件开发和部署以及项目管理的基本工具: + +* 通过版本控制在存储库中托管代码. +* 使用功能齐全的[问题跟踪器](project/issues/index.html#issues-list)跟踪有关新实现,错误报告和反馈的建议. +* 组织和[发行委员会的](project/issues/index.html#issue-boards)优先次序. +* 使用[Review Apps](../ci/review_apps/index.html)查看[合并请求中](project/merge_requests/index.html)每个分支的实时预览更改中的代码. +* 使用内置的[持续集成进行](../ci/README.html)构建,测试和部署. +* 使用[GitLab Pages](project/pages/index.html)部署个人和专业静态网站. +* 通过使用[GitLab 容器注册表](packages/container_registry/index.html)与 Docker 集成. +* 通过使用[GitLab 价值流分析](project/cycle_analytics.html)跟踪开发生命周期. +* 提供[服务台](project/service_desk.html)支持. + +使用 GitLab 企业版,您还可以: + +* 通过以下方式改善协作: + * [合并请求批准](project/merge_requests/merge_request_approvals.html) . + * [问题的多个受让人](project/issues/multiple_assignees_for_issues.html) . + * [多个发行委员会](project/issue_board.html#multiple-issue-boards) . +* 在[相关问题](project/issues/related_issues.html)之间创建正式关系. +* 使用[Burndown Charts](project/milestones/burndown_charts.html)可以在冲刺期间或在使用其新版本软件时跟踪进度. +* 利用[Elasticsearch](../integration/elasticsearch.html)和[Advanced Global Search](search/advanced_global_search.html)和[Advanced Syntax Search](search/advanced_search_syntax.html)在整个 GitLab 实例上进行更快,更高级的代码搜索. +* [Authenticate users with Kerberos](../integration/kerberos.html). +* 从本地服务器上的其他地方[镜像存储库](project/repository/repository_mirroring.html) . +* [Export issues as CSV](project/issues/csv_export.html). +* 使用[Multiple-Project Pipelines](../ci/multi_project_pipeline_graphs.html)查看涉及多个项目的整个 CI / CD [管道](../ci/multi_project_pipeline_graphs.html) . +* [锁定文件](project/file_lock.html)以防止冲突. +* 使用[Deploy Boards](project/deploy_boards.html)查看在 Kubernetes 上运行的每个 CI 环境的当前运行状况和状态. +* 利用[Canary 部署的](project/canary_deployments.html)连续交付方法. +* 扫描您的代码中的漏洞, [并在合并请求中显示它们](application_security/sast/index.html) . + +您还可以[将](project/integrations/overview.html) GitLab 与众多第三方应用程序[集成](project/integrations/overview.html) ,例如 Mattermost,Microsoft Teams,HipChat,Trello,Slack,Bamboo CI,Jira 等. + +## Projects[](#projects "Permalink") + +在 GitLab 中,您可以创建[项目](project/index.html)来托管代码,跟踪问题,在代码上进行协作以及使用内置的 GitLab CI / CD 持续构建,测试和部署应用程序. 或者,您可以从一个项目中一次完成所有操作. + +* [存储库](project/repository/index.html) :将代码[库](project/repository/index.html)托管在具有版本控制的存储库中,并作为完全集成平台的一部分. +* [问题](project/issues/index.html) :探索 GitLab 问题的最佳功能. +* [合并请求](project/merge_requests/index.html) :在代码,评论,每个分支的实时预览更改方面进行协作,并通过合并请求请求批准. +* [里程碑](project/milestones/index.html) :处理多个问题,并与里程碑在同一目标日期合并请求. + +## GitLab CI/CD[](#gitlab-cicd "Permalink") + +使用内置的[GitLab CI / CD](../ci/README.html)直接从 GitLab 测试,构建和部署应用程序. 无需第三方集成. + +* [GitLab Auto Deploy](../topics/autodevops/stages.html#auto-deploy) :通过 GitLab Auto Deploy 开箱即用地部署您的应用程序. +* [Review Apps](../ci/review_apps/index.html) :实时预览带有 Review Apps 的合并请求所引入的更改. +* [GitLab 页面](project/pages/index.html) :使用 GitLab 页面直接从 GitLab 发布您的静态站点. 您可以使用 Pages 构建,测试和部署任何静态站点生成器. +* [GitLab Container Registry](packages/container_registry/index.html) :使用 Container Registry 构建和部署 Docker 映像. + +## Account[](#account "Permalink") + +您可以自定义和配置很多东西,以享受 GitLab 的最佳体验. + +* [设置](profile/index.html) :管理用户设置以更改您的个人信息,个人访问令牌,授权的应用程序等. +* [身份验证](../topics/authentication/index.html) :通读 GitLab 中可用的身份验证方法. +* [权限](permissions.html) :了解每种用户类型(访客,记者,开发人员,维护人员,所有者)的不同权限级别集. +* [功能亮点](feature_highlight.html) :了解有关应用周围的小蓝点的更多信息,这些小点可以解释某些功能. +* [滥用报告](abuse_reports.html) :向 GitLab 管理员报告用户的[滥用情况](abuse_reports.html) . + +## Groups[](#groups "Permalink") + +使用 GitLab [组,](group/index.html)您可以将相关项目组合在一起,并授予成员一次访问多个项目的权限. + +组也可以嵌套在[子组中](group/subgroups/index.html) . + +## Discussions[](#discussions "Permalink") + +在 GitLab 中,您可以在问题,合并请求,代码段和提交中注释和提及合作者. + +通过合并请求对代码库的实现执行内联检查时,可以通过[可解析的线程](discussions/index.html#resolvable-comments-and-threads)收集反馈. + +### GitLab Flavored Markdown (GFM)[](#gitlab-flavored-markdown-gfm "Permalink") + +通读[GFM 文档,](markdown.html)以了解如何在线程,注释,问题和合并请求描述以及所有支持 GFM 的其他地方应用最好的 GitLab 风味 Markdown. + +## Todos[](#todos "Permalink") + +Never forget to reply to your collaborators. [GitLab Todos](todos.html) are a tool for working faster and more effectively with your team, by listing all user or group mentions, as well as issues and merge requests you’re assigned to. + +## Search[](#search "Permalink") + +[搜索和筛选](search/index.html)组,项目,问题,合并请求,文件,代码等. + +## Snippets[](#snippets "Permalink") + +[片段](snippets.html)是您要存储在 GitLab 中的代码块,您可以从中快速访问它们. 您还可以通过" [讨论"](#discussions)收集有关它们的反馈. + +## Keyboard shortcuts[](#keyboard-shortcuts "Permalink") + +GitLab 中有许多[键盘快捷键](shortcuts.html) ,可帮助您在页面之间导航并更快地完成任务. + +## Integrations[](#integrations "Permalink") + +[将 GitLab](../integration/README.html)与您喜欢的工具(例如 Trello,Jira 等) [集成](../integration/README.html) . + +## Webhooks[](#webhooks "Permalink") + +配置[webhook](project/integrations/webhooks.html)以侦听特定事件,例如推送,问题或合并请求. GitLab 会将带有数据的 POST 请求发送到 webhook URL. + +## API[](#api "Permalink") + +通过[API](../api/README.html)自动化 GitLab. + +## Git and GitLab[](#git-and-gitlab "Permalink") + +了解什么是[Git](../topics/git/index.html)及其最佳实践. + +## Instance statistics[](#instance-statistics "Permalink") + +查看您的 GitLab 实例的[各种统计信息](instance_statistics/index.html) . + +## Operations Dashboard[](#operations-dashboard-premium "Permalink") + +See [Operations Dashboard](operations_dashboard/index.html) for a summary of each project’s operational health. \ No newline at end of file diff --git a/docs/391.md b/docs/391.md new file mode 100644 index 0000000000000000000000000000000000000000..c59744cfd180826c893636e0dfbd02cb528331bc --- /dev/null +++ b/docs/391.md @@ -0,0 +1,62 @@ +# Abuse reports + +> 原文:[https://docs.gitlab.com/ee/user/abuse_reports.html](https://docs.gitlab.com/ee/user/abuse_reports.html) + +* [Reporting abuse through a user’s profile](#reporting-abuse-through-a-users-profile) +* [Reporting abuse through a user’s comment](#reporting-abuse-through-a-users-comment) +* [Reporting abuse through a user’s issue or merge request](#reporting-abuse-through-a-users-issue-or-merge-request) +* [Managing abuse reports](#managing-abuse-reports) + +# Abuse reports[](#abuse-reports "Permalink") + +您可以将其他 GitLab 用户的滥用情况报告给 GitLab 管理员. + +然后,GitLab 管理员[可以选择](admin_area/abuse_reports.html) : + +* 删除用户,这会将其从实例中删除. +* 阻止用户,这将拒绝他们访问实例. +* 或删除报告,以保留用户对实例的访问权限. + +您可以通过以下方式报告用户: + +* [Profile](#reporting-abuse-through-a-users-profile) +* [Comments](#reporting-abuse-through-a-users-comment) +* [Issues and Merge requests](#reporting-abuse-through-a-users-issue-or-merge-request) + +## Reporting abuse through a user’s profile[](#reporting-abuse-through-a-users-profile "Permalink") + +要从用户的个人资料页面举报滥用行为,请执行以下操作: + +1. 单击用户个人资料右上方的感叹号报告滥用按钮. +2. 完成滥用情况报告. +3. Click the **发送报告** button. + +## Reporting abuse through a user’s comment[](#reporting-abuse-through-a-users-comment "Permalink") + +要报告用户评论中的滥用行为,请执行以下操作: + +1. 单击垂直省略号(⋮)其他操作按钮以打开下拉列表. +2. Select **举报为滥用**. +3. 完成滥用情况报告. +4. 点击**发送报告**按钮. + +**注意:**在滥用情况报告的" **消息"**字段中,将预先填写报告用户评论的 URL. + +## Reporting abuse through a user’s issue or merge request[](#reporting-abuse-through-a-users-issue-or-merge-request "Permalink") + +**报告滥用**按钮显示在问题或合并请求的右上方: + +* 对于单击有权关闭问题或合并请求的用户,从单击" **关闭问题"**或" **关闭合并请求"**按钮时出现的菜单中选择**"报告滥用**情况". +* 查看问题或合并请求时,对于没有权限关闭问题或合并请求的用户. + +显示" **举报滥用行为"**按钮后,要提交滥用行为报告: + +1. 点击**举报滥用行为**按钮. +2. 提交滥用情况报告. +3. 点击**发送报告**按钮. + +**注意:**在滥用情况报告的" **消息"**字段中,将预先填写报告用户的问题或合并请求的 URL. + +## Managing abuse reports[](#managing-abuse-reports "Permalink") + +管理员能够查看和解决滥用报告. 有关更多信息,请参阅[滥用报告管理文档](admin_area/abuse_reports.html) . \ No newline at end of file diff --git a/docs/392.md b/docs/392.md new file mode 100644 index 0000000000000000000000000000000000000000..91c404f217544cca8344dc3a2d3ae6fb4d389922 --- /dev/null +++ b/docs/392.md @@ -0,0 +1,248 @@ +# User account + +> 原文:[https://docs.gitlab.com/ee/user/profile/](https://docs.gitlab.com/ee/user/profile/) + +* [Creating users](#creating-users) +* [Signing in](#signing-in) + * [Unknown sign-in](#unknown-sign-in) +* [User profile](#user-profile) +* [Profile settings](#profile-settings) +* [Changing your password](#changing-your-password) +* [Changing your username](#changing-your-username) +* [Private profile](#private-profile) +* [Add details of external accounts](#add-details-of-external-accounts) +* [Private contributions](#private-contributions) +* [Current status](#current-status) +* [Commit email](#commit-email) + * [Private commit email](#private-commit-email) +* [Troubleshooting](#troubleshooting) + * [Why do I keep getting signed out?](#why-do-i-keep-getting-signed-out) + * [Increased sign-in time](#increased-sign-in-time) + +# User account[](#user-account "Permalink") + +每个 GitLab 帐户都有一个用户个人资料和设置. 您的[个人资料](#user-profile)包含有关您以及您的 GitLab 活动的信息. 您的[设置](#profile-settings)允许您自定义 GitLab 的某些方面以适合自己. + +## Creating users[](#creating-users "Permalink") + +在 GitLab 上有几种创建用户的方法. 有关更多详细信息,请参见[创建用户文档](account/create_accounts.html) . + +## Signing in[](#signing-in "Permalink") + +有几种方法可以登录您的 GitLab 帐户. 有关更多详细信息,请参见[身份验证主题](../../topics/authentication/index.html) . + +### Unknown sign-in[](#unknown-sign-in "Permalink") + +GitLab will notify you if a sign-in occurs that is from an unknown IP address or device. See [Unknown Sign-In Notification](unknown_sign_in_notification.html) for more details. + +## User profile[](#user-profile "Permalink") + +要访问您的个人资料: + +1. 单击您的头像. +2. Select **Profile**. + +在您的个人资料页面上,您将看到以下信息: + +* 个人信息 +* 活动流:查看您的活动流线和贡献历史 +* 组: [组](../group/index.html)你的成员 +* 参与的项目:您参与的[项目](../project/index.html) +* 个人项目:您的个人项目(尊重项目的可见性级别) +* 已加星标的项目:您已加星标的项目 +* 片段:您的个人代码[片段](../snippets.html#personal-snippets) + +## Profile settings[](#profile-settings "Permalink") + +要访问您的个人资料设置: + +1. 单击您的头像. +2. Select **Settings**. + +从那里,您可以: + +* 更新您的个人信息 +* 修改[密码](#changing-your-password) +* 为您的个人资料设置[自定义状态](#current-status) +* 管理您的个人资料的[提交电子邮件](#commit-email) +* Manage [2FA](account/two_factor_authentication.html) +* 添加[外部帐户的](#add-details-of-external-accounts)详细信息. +* 更改您的用户名并[删除您的帐户](account/delete_account.html) +* 管理可以[将 GitLab 用作 OAuth 提供](../../integration/oauth_provider.html#introduction-to-oauth)程序的应用[程序](../../integration/oauth_provider.html#introduction-to-oauth) +* 管理[个人访问令牌](personal_access_tokens.html)以通过 API 和授权的应用程序访问您的帐户 +* 添加和删​​除链接到您帐户的电子邮件 +* 选择用于[通知](notifications.html) ,基于 Web 的提交并显示在您的公开个人资料上的电子邮件 +* 管理[SSH 密钥](../../ssh/README.html)以通过 SSH 访问您的帐户 +* 管理您的[首选项](preferences.html#syntax-highlighting-theme)以自定义自己的 GitLab 体验 +* [查看您的活动会话](active_sessions.html)并在必要时撤消其中的任何一个 +* 访问审核日志,这是涉及您帐户的重要事件的安全日志 + +## Changing your password[](#changing-your-password "Permalink") + +1. 导航到您的[个人资料的](#profile-settings) **设置>密码** . +2. 在"当前密码"字段中输入您的当前密码. +3. 两次输入所需的新密码,一次在"新密码"字段中,一次在"密码确认"字段中. +4. 点击"保存密码"按钮. + +如果您不知道当前密码,请选择"我忘记了密码"链接. + +[![Change your password](img/87be547831d2207399009a0f9dd4b91a.png)](./img/change_password_v13_0.png) + +## Changing your username[](#changing-your-username "Permalink") + +`username`是与用户 ID 相关的唯一[`namespace`](../group/index.html#namespaces) . 对其进行更改可能会产生意想不到的副作用,请在继续之前阅读[重定向的行为](../project/index.html#redirects-when-changing-repository-paths) . + +更改`username` : + +1. 导航到您的[个人资料的](#profile-settings) **设置>帐户** . +2. 在**更改用户**名下输入新的用户**名** . +3. Click **更新用户名**. + +**注意:**如果用户名包含带有[Container Registry](../packages/container_registry/index.html)标签的项目,则当前无法更改用户名,因为该项目无法移动.**提示:**如果要保留对原始名称空间的所有权并保护 URL 重定向,则可以更改一个组并向其传输项目,而无需更改组的路径或重命名用户名. 另外,您可以按照[《 GitLab 团队手册》中的详细步骤进行操作,该手册](https://about.gitlab.com/handbook/tools-and-tips/#how-to-change-your-username-at-gitlabcom)还介绍了使用[GitLab Pages](../project/pages/index.html)托管项目的情况. + +## Private profile[](#private-profile "Permalink") + +如果启用了此功能,将从用户配置文件页面( `https://gitlab.example.com/username` )中隐藏以下信息: + +* 原子饲料 +* 创建帐户的日期 +* 活动标签 +* 组选项卡 +* 参与项目标签 +* 个人项目标签 +* 已加星标的项目标签 +* 片段标签 + +要启用私人资料: + +1. 单击您的头像. +2. Select **Profile**. +3. 单击**编辑配置文件** (铅笔图标). +4. 在" **主要设置"**部分中选中" **私人个人资料"**选项. +5. Click **更新配置文件设置**. + +**Note:** All your profile information can be seen by yourself, and GitLab admins, even if the **私人简介** option is enabled. + +## Add details of external accounts[](#add-details-of-external-accounts "Permalink") + +GitLab 允许您将链接添加到您可能拥有的某些其他外部帐户,例如 Skype 和 Twitter. 他们可以帮助其他用户在其他平台上与您建立联系. + +要将链接添加到其他帐户: + +1. 单击您的头像. +2. Select **Profile**. +3. 单击**编辑配置文件** (铅笔图标). +4. 在" **主要设置"**部分中完成外部帐户的所需字段: + * Skype 的 + * 推特 + * 领英 +5. Click **更新配置文件设置**. + +## Private contributions[](#private-contributions "Permalink") + +在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14078) . + +启用私人捐款将包括对私人项目的捐款,用户捐款日历图和用户最近的活动. + +要启用私人捐款: + +1. 单击您的头像. +2. Select **Profile**. +3. 单击**编辑配置文件** (铅笔图标). +4. 选中**私人捐款**选项. +5. Click **更新配置文件设置**. + +## Current status[](#current-status "Permalink") + +在 GitLab 11.2 中引入. + +您可以为用户个人资料提供自定义状态消息以及描述它的表情符号. 当您不在办公室或不在家时,这可能会有所帮助. 然后,其他用户可以在回答您的问题或为您分配工作时考虑您的身份. 请注意,即使您的[个人资料是私人的](#private-profile) ,您的状态也是公开可见的. + +状态消息限制为 100 个纯文本字符. 但是,它们可能包含表情符号代码,例如" `I'm on vacation :palm_tree:` . + +设置当前状态: + +1. 单击您的头像. +2. 点击**设置状态** ,或点击**编辑状态(**如果您已经设置了状态). +3. 设置所需的表情符号和/或状态消息. +4. 点击**设置状态** . 或者,您可以单击" **删除状态"**以完全删除您的用户状态. + +or + +1. 单击您的头像. +2. Select **Profile**. +3. 单击**编辑配置文件** (铅笔图标). +4. 在**您的状态**文本字段中输入您的状态消息. +5. 点击**添加状态表情符号** (笑脸),然后选择所需的表情符号. +6. Click **更新配置文件设置**. + +您还可以[使用 API](../../api/users.html#user-status)设置当前状态. + +## Commit email[](#commit-email "Permalink") + +在 GitLab 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21598) . + +提交电子邮件是在通过 GitLab 界面执行的每个与 Git 相关的操作中显示的电子邮件地址. + +您自己的任何已验证电子邮件地址都可以用作提交电子邮件. + +要更改您的提交电子邮件: + +1. 单击您的头像. +2. Select **Profile**. +3. 单击**编辑配置文件** (铅笔图标). +4. Click **提交电子邮件** dropdown. +5. 选择任何已验证的电子邮件. +6. Click **更新配置文件设置**. + +### Private commit email[](#private-commit-email "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22560) . + +GitLab 为用户提供了一个自动生成的私人提交电子邮件选项,该选项允许用户将其电子邮件信息保密. + +要启用此选项: + +1. 单击您的头像. +2. Select **Profile**. +3. 单击**编辑配置文件** (铅笔图标). +4. Click **提交电子邮件** dropdown. +5. Select **使用私人电子邮件** option. +6. Click **更新配置文件设置**. + +启用此选项后,将使用私有提交电子邮件执行与 Git 相关的所有操作. + +要保持完全匿名,您还可以复制此私人提交电子邮件,并使用以下命令在本地计算机上对其进行配置: + +``` +git config --global user.email +``` + +## Troubleshooting[](#troubleshooting "Permalink") + +### Why do I keep getting signed out?[](#why-do-i-keep-getting-signed-out "Permalink") + +登录主 GitLab 应用程序时,将设置`_gitlab_session` cookie. `_gitlab_session`在您关闭浏览器时在客户端清除,并在"应用程序设置->会话持续时间(分钟)" / `session_expire_delay` (默认为`10080`分钟= 7 天)后过期. + +登录到主要的 GitLab 应用程序时,您还可以选中" Remember me"选项,该选项设置了`remember_user_token` cookie(通过[`devise`](https://github.com/heartcombo/devise) ). `remember_user_token`之后到期`config/initializers/devise.rb` > - `config.remember_for` (默认为 2 周). + +当`_gitlab_session`过期或不可用,GitLab 使用`remember_user_token`让你一个新的`_gitlab_session` ,让你在浏览器中通过重新签署. + +你的后`remember_user_token`到期,你的`_gitlab_session`清/过期,你会被要求再次登录验证您的身份出于安全原因. + +### Increased sign-in time[](#increased-sign-in-time "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/20340) . + +该`remember_user_token`一个 cookie 的寿命,现在可以通过超出期限延长集`config.remember_for` ,作为`config.extend_remember_period`标志现在设置为 true. + +GitLab 使用会话和持久性 Cookie: + +* 会话 cookie:通常,在关闭浏览器后,会话 cookie 会在浏览器会话结束时删除. `_gitlab_session` cookie 没有到期日期. +* 永久性 cookie: `remember_me_token`是有效期为两周的 cookie. 如果您在登录时单击"记住我",则 GitLab 会激活此 cookie. + +默认情况下,服务器在使用的任何会话上将生存时间(TTL)设置为 1 周. + +当您关闭浏览器时,会话 cookie 可能仍然保留. 例如,Chrome 具有"恢复上次退出的位置"选项,该选项可还原会话 Cookie. 换句话说,只要您每两周至少访问 GitLab 一次,只要打开浏览器选项卡,就可以保持登录状态. 无论是否安装了 2FA,服务器都会继续为该会话重置 TTL.如果关闭浏览器并再次打开它,则`remember_user_token`用户令牌 cookie 允许您的用户重新进行身份验证. + +如果没有`config.extend_remember_period`标志,则两周后您将被迫再次登录. \ No newline at end of file diff --git a/docs/393.md b/docs/393.md new file mode 100644 index 0000000000000000000000000000000000000000..a1f86b48349efe0ba22f3eaf42bb8d146d186ca9 --- /dev/null +++ b/docs/393.md @@ -0,0 +1,32 @@ +# Active sessions + +> 原文:[https://docs.gitlab.com/ee/user/profile/active_sessions.html](https://docs.gitlab.com/ee/user/profile/active_sessions.html) + +* [Listing all active sessions](#listing-all-active-sessions) +* [Active sessions limit](#active-sessions-limit) +* [Revoking a session](#revoking-a-session) + +# Active sessions[](#active-sessions "Permalink") + +在 GitLab 10.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17867) . + +GitLab 列出了已登录到您帐户的所有设备. 这使您可以查看会话,并撤销所有您不认识的会话. + +## Listing all active sessions[](#listing-all-active-sessions "Permalink") + +1. 单击您的头像. +2. Select **Settings**. +3. 点击边栏中的**活动会话** . + +[![Active sessions list](img/2d1845503f8ff90d4dc71459313e4e62.png)](img/active_sessions_list.png) + +## Active sessions limit[](#active-sessions-limit "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/31611) . + +GitLab 允许用户一次拥有多达 100 个活动会话. 如果活动会话数超过 100,则最早的会话将被删除. + +## Revoking a session[](#revoking-a-session "Permalink") + +1. 使用前面的步骤导航到" **活动会话"** . +2. 单击除会话外的**撤消** . 当前会话无法撤消,因为这将使您退出 GitLab. \ No newline at end of file diff --git a/docs/394.md b/docs/394.md new file mode 100644 index 0000000000000000000000000000000000000000..1d57720712c71d3336c854d982e4c4d5770779d8 --- /dev/null +++ b/docs/394.md @@ -0,0 +1,63 @@ +# Deleting a User account + +> 原文:[https://docs.gitlab.com/ee/user/profile/account/delete_account.html](https://docs.gitlab.com/ee/user/profile/account/delete_account.html) + +* [As a user](#as-a-user) +* [As an administrator](#as-an-administrator) +* [Associated Records](#associated-records) + +# Deleting a User account[](#deleting-a-user-account "Permalink") + +可以通过以下方法从 GitLab 实例中删除用户: + +* 用户自己. +* 管理员. + +**注意:**删除用户将删除该用户名称空间中的所有项目. + +## As a user[](#as-a-user "Permalink") + +作为用户,您可以通过以下方式删除自己的帐户: + +1. 点击您的头像. +2. 导航至**设置>帐户** . +3. Selecting **删除帐户**. + +## As an administrator[](#as-an-administrator "Permalink") + +作为管理员,您可以通过以下方式删除用户帐户: + +1. 导航到**管理区域>概述>用户** . +2. 选择一个用户. +3. 在" **帐户"**标签下,单击: + * **删除用户**仅**删除用户** ,但保留其[相关记录](#associated-records) . + * **删除用户和贡献**以删除用户及其相关记录. + +**危险:**使用" **删除用户和贡献"**选项可能会导致删除的数据超出预期. [有关](#associated-records)其他详细信息,请参见下面的[关联记录](#associated-records) . + +## Associated Records[](#associated-records "Permalink") + +版本历史 + +* 针对[GitLab 9.0 中的](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7393)问题进行了介绍. +* 在[GitLab 9.1 中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10467)引入了合并请求,奖励表情符号,注释和滥用报告. +* 从滥用报告和垃圾邮件日志中进行硬删除是在[GitLab 9.1](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10273)中以及从[GitLab 9.3 中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11853)的 API 中引入的. + +有两种删除用户的选项: + +* **Delete user** +* **删除用户和贡献** + +使用" **删除用户"**选项时,并非所有关联记录都随用户一起删除. 以下是**不会**删除的内容的列表: + +* 用户创建的问题. +* 合并用户创建的请求. +* 注意用户创建的. +* 用户报告了滥用报告. +* 用户创建的奖励表情符号. + +这些记录将被删除,而不是被删除,而是被移至用户名" Ghost User"的系统级用户,其唯一目的是充当此类记录的容器. 删除的用户所做的任何提交仍将显示原始用户的用户名. + +使用" **删除用户和贡献"**选项时,将**删除** **所有**关联的记录. 这包括上面提到的所有项目,包括问题,合并请求,注释/评论等等. 考虑[阻止用户](../../admin_area/blocking_unblocking_users.html)或使用" **删除用户"**选项. + +从[滥用情况报告](../../admin_area/abuse_reports.html)或垃圾邮件日志中删除用户时,这些关联的记录不会被重影,并且会与该用户的唯一所有者一起删除. 从[API](../../../api/users.html#user-deletion)或管理区域中删除用户时,管理员也可以请求此行为. \ No newline at end of file diff --git a/docs/395.md b/docs/395.md new file mode 100644 index 0000000000000000000000000000000000000000..4ad2b1e87d86ddf9ca076baa9cdde9428c5103c8 --- /dev/null +++ b/docs/395.md @@ -0,0 +1,419 @@ +# Permissions + +> 原文:[https://docs.gitlab.com/ee/user/permissions.html](https://docs.gitlab.com/ee/user/permissions.html) + +* [Principles behind permissions](#principles-behind-permissions) +* [Instance-wide user permissions](#instance-wide-user-permissions) +* [Project members permissions](#project-members-permissions) +* [Project features permissions](#project-features-permissions) + * [Wiki and issues](#wiki-and-issues) + * [Protected branches](#protected-branches) + * [Value Stream Analytics permissions](#value-stream-analytics-permissions) + * [Issue Board permissions](#issue-board-permissions) + * [File Locking permissions](#file-locking-permissions-premium) + * [Confidential Issues permissions](#confidential-issues-permissions) +* [Group members permissions](#group-members-permissions) + * [Subgroup permissions](#subgroup-permissions) +* [External users](#external-users-core-only) + * [Setting new users to external](#setting-new-users-to-external) +* [Free Guest users](#free-guest-users-ultimate) +* [Auditor users](#auditor-users-premium-only) +* [Project features](#project-features) +* [GitLab CI/CD permissions](#gitlab-cicd-permissions) + * [Job permissions](#job-permissions) + * [New CI job permissions model](#new-ci-job-permissions-model) +* [Running pipelines on protected branches](#running-pipelines-on-protected-branches) +* [LDAP users permissions](#ldap-users-permissions) +* [Project aliases](#project-aliases) + +# Permissions[](#permissions "Permalink") + +用户具有不同的能力,具体取决于他们在特定组或项目中具有的访问级别. 如果用户既属于项目组又属于项目本身,则使用最高权限级别. + +在公共和内部项目上,不执行来宾角色. 所有用户将能够: + +* 创造问题. +* 留言. +* 克隆或下载项目代码. + +当成员离开团队的项目时,所有分配的" [问题"](project/issues/index.html)和" [合并请求"](project/merge_requests/index.html)将自动取消分配. + +GitLab [管理员拥有](../administration/index.html)所有权限. + +要添加或导入用户,可以遵循[项目成员文档](project/members/index.html) . + +## Principles behind permissions[](#principles-behind-permissions "Permalink") + +有关[权限的信息,](https://about.gitlab.com/handbook/product/gitlab-the-product/#permissions-in-gitlab)请参见我们的[产品手册](https://about.gitlab.com/handbook/product/gitlab-the-product/#permissions-in-gitlab) . + +## Instance-wide user permissions[](#instance-wide-user-permissions "Permalink") + +默认情况下,用户可以创建顶级组并更改其用户名. GitLab 管理员可以配置 GitLab 实例来[修改此行为](../administration/user_settings.html) . + +## Project members permissions[](#project-members-permissions "Permalink") + +**注意:**在 GitLab 11.0 中,"主"角色已重命名为"维护者". + +虽然维护者是项目级别的最高角色,但是某些操作只能由拥有所有权限的个人名称空间或组所有者或实例管理员执行. 有关更多信息,请参阅[项目成员文档](project/members/index.html) . + +下表描述了项目中的各种用户权限级别. + +| Action | Guest | Reporter | Developer | Maintainer | Owner* | +| --- | --- | --- | --- | --- | --- | +| 下载专案 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 留言 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看允许和拒绝的许可证 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看许可证合规性报告 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看安全报告 | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | +| 查看相关性列表 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看许可证列表 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 在相关性列表中查看许可证 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| View [Design Management](project/issues/design_management.html) pages | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看项目代码 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 拉项目代码 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看受[访问控制](project/pages/introduction.html#gitlab-pages-access-control-core)保护的 GitLab 页面 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看维基页面 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看工作清单 | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | +| 查看工作日志 | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | +| 下载和浏览工作工件 | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | +| 创刊号 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看相关问题 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 创建机密问题 | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| 查看机密问题 | (*2*) | ✓ | ✓ | ✓ | ✓ | +| View [Releases](project/releases/index.html) | ✓ (*6*) | ✓ | ✓ | ✓ | ✓ | +| 查看要求 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 管理用户加星标的指标仪表板( *7* ) | ✓ | ✓ | ✓ | ✓ | ✓ | +| 分配问题 |   | ✓ | ✓ | ✓ | ✓ | +| 标签问题 |   | ✓ | ✓ | ✓ | ✓ | +| 设定发行权重 |   | ✓ | ✓ | ✓ | ✓ | +| 锁定问题线程 |   | ✓ | ✓ | ✓ | ✓ | +| 管理问题追踪器 |   | ✓ | ✓ | ✓ | ✓ | +| 管理相关问题 |   | ✓ | ✓ | ✓ | ✓ | +| 管理标签 |   | ✓ | ✓ | ✓ | ✓ | +| 创建代码段 |   | ✓ | ✓ | ✓ | ✓ | +| 查看提交状态 |   | ✓ | ✓ | ✓ | ✓ | +| 查看容器注册表 |   | ✓ | ✓ | ✓ | ✓ | +| 查看环境 |   | ✓ | ✓ | ✓ | ✓ | +| 查看合并请求列表 |   | ✓ | ✓ | ✓ | ✓ | +| 查看项目统计 |   |   | ✓ | ✓ | ✓ | +| 查看错误跟踪列表 |   | ✓ | ✓ | ✓ | ✓ | +| 创建新的合并请求 |   | ✓ | ✓ | ✓ | ✓ | +| 查看指标仪表板注释 |   | ✓ | ✓ | ✓ | ✓ | +| 创建/编辑需求 |   | ✓ | ✓ | ✓ | ✓ | +| Pull [packages](packages/index.html) |   | ✓ | ✓ | ✓ | ✓ | +| Publish [packages](packages/index.html) |   |   | ✓ | ✓ | ✓ | +| Upload [Design Management](project/issues/design_management.html) files |   |   | ✓ | ✓ | ✓ | +| Create/edit/delete [Releases](project/releases/index.html) |   |   | ✓ | ✓ | ✓ | +| 创建新分支 |   |   | ✓ | ✓ | ✓ | +| 推送到不受保护的分支 |   |   | ✓ | ✓ | ✓ | +| 强制推送到不受保护的分支 |   |   | ✓ | ✓ | ✓ | +| 删除不受保护的分支 |   |   | ✓ | ✓ | ✓ | +| 分配合并请求 |   |   | ✓ | ✓ | ✓ | +| 标签合并请求 |   |   | ✓ | ✓ | ✓ | +| 锁定合并请求线程 |   |   | ✓ | ✓ | ✓ | +| 批准合并请求( *9* ) |   |   | ✓ | ✓ | ✓ | +| 管理/接受合并请求 |   |   | ✓ | ✓ | ✓ | +| 创建新环境 |   |   | ✓ | ✓ | ✓ | +| 停止环境 |   |   | ✓ | ✓ | ✓ | +| 启用评论应用 |   |   | ✓ | ✓ | ✓ | +| 添加标签 |   |   | ✓ | ✓ | ✓ | +| 取消并重试作业 |   |   | ✓ | ✓ | ✓ | +| 创建或更新提交状态 |   |   | ✓ (*5*) | ✓ | ✓ | +| 更新容器注册表 |   |   | ✓ | ✓ | ✓ | +| 删除容器注册表映像 |   |   | ✓ | ✓ | ✓ | +| 创建/编辑/删除项目里程碑 |   |   | ✓ | ✓ | ✓ | +| 使用安全仪表板 |   |   | ✓ | ✓ | ✓ | +| 在"依赖关系"列表中查看漏洞发现 |   |   | ✓ | ✓ | ✓ | +| 从漏洞发现中创建问题 |   |   | ✓ | ✓ | ✓ | +| 消除漏洞发现 |   |   | ✓ | ✓ | ✓ | +| 查看漏洞 |   |   | ✓ | ✓ | ✓ | +| 通过漏洞发现创建漏洞 |   |   | ✓ | ✓ | ✓ | +| 解决漏洞 |   |   | ✓ | ✓ | ✓ | +| 消除漏洞 |   |   | ✓ | ✓ | ✓ | +| 应用代码更改建议 |   |   | ✓ | ✓ | ✓ | +| 创建和编辑 Wiki 页面 |   |   | ✓ | ✓ | ✓ | +| 重写/删除 Git 标签 |   |   | ✓ | ✓ | ✓ | +| 管理功能标记 |   |   | ✓ | ✓ | ✓ | +| 创建/编辑/删除指标仪表板注释 |   |   | ✓ | ✓ | ✓ | +| 针对受保护的分支运行 CI / CD 管道 |   |   | ✓ (*5*) | ✓ | ✓ | +| 使用环境终端 |   |   |   | ✓ | ✓ | +| 运行 Web IDE 的交互式 Web 终端 |   |   |   | ✓ | ✓ | +| 添加新的团队成员 |   |   |   | ✓ | ✓ | +| 启用/禁用分支保护 |   |   |   | ✓ | ✓ | +| 推送到受保护的分支 |   |   |   | ✓ | ✓ | +| 为开发人员打开/关闭受保护的分支推送 |   |   |   | ✓ | ✓ | +| 启用/禁用标签保护 |   |   |   | ✓ | ✓ | +| 编辑专案 |   |   |   | ✓ | ✓ | +| 编辑项目徽章 |   |   |   | ✓ | ✓ | +| 与小组共享(邀请)项目 |   |   |   | ✓ (*8*) | ✓ (*8*) | +| 将部署密钥添加到项目 |   |   |   | ✓ | ✓ | +| 配置项目挂钩 |   |   |   | ✓ | ✓ | +| 管理跑步者 |   |   |   | ✓ | ✓ | +| 管理工作触发器 |   |   |   | ✓ | ✓ | +| 管理 CI / CD 变量 |   |   |   | ✓ | ✓ | +| 管理 GitLab 页面 |   |   |   | ✓ | ✓ | +| 管理 GitLab Pages 域和证书 |   |   |   | ✓ | ✓ | +| 删除 GitLab 页面 |   |   |   | ✓ | ✓ | +| 管理集群 |   |   |   | ✓ | ✓ | +| 管理项目运作 |   |   |   | ✓ | ✓ | +| 查看 Pod 日志 |   |   |   | ✓ | ✓ | +| 管理许可政策 |   |   |   | ✓ | ✓ | +| 编辑评论(由任何用户发布) |   |   |   | ✓ | ✓ | +| 管理错误跟踪 |   |   |   | ✓ | ✓ | +| 删除维基页面 |   |   |   | ✓ | ✓ | +| 查看项目审核事件 |   |   |   | ✓ | ✓ | +| Manage [push rules](../push_rules/push_rules.html) |   |   |   | ✓ | ✓ | +| Manage [project access tokens](./project/settings/project_access_tokens.html) |   |   |   | ✓ | ✓ | +| Switch visibility level |   |   |   |   | ✓ | +| 将项目转移到另一个名称空间 |   |   |   |   | ✓ | +| 重命名项目 |   |   |   |   | ✓ | +| 删除分叉关系 |   |   |   |   | ✓ | +| 移除专案 |   |   |   |   | ✓ | +| 存档项目 |   |   |   |   | ✓ | +| 删除问题 |   |   |   |   | ✓ | +| 删除管道 |   |   |   |   | ✓ | +| 删除合并请求 |   |   |   |   | ✓ | +| 禁用通知电子邮件 |   |   |   |   | ✓ | +| 用力推动到受保护的分支( *4* ) |   |   |   |   |   | +| 卸下受保护的分支( *4* ) |   |   |   |   |   | +| 查看 CI \ CD 分析 |   | ✓ | ✓ | ✓ | ✓ | +| 查看代码审查分析 |   | ✓ | ✓ | ✓ | ✓ | +| 查看见解 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看问题分析 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看存储库分析 |   | ✓ | ✓ | ✓ | ✓ | +| 查看价值流分析 | ✓ | ✓ | ✓ | ✓ | ✓ | + +*所有者权限仅在组或个人名称空间级别(例如,管理员)可用,并由其项目继承. + +1. 来宾用户能够对公共和内部项目执行此操作,但不能对私有项目执行此操作. +2. 来宾用户只能查看他们自己创建的机密问题. +3. 如果在**项目设置> CI / CD 中**启用了**公共管道** . +4. 不允许访客,记者,开发人员,维护人员或所有者使用. 请参阅[受保护的分支](./project/protected_branches.html) . +5. 如果[分支受保护](./project/protected_branches.html#using-the-allowed-to-merge-and-allowed-to-push-settings) ,则取决于授予开发人员和维护人员的权限. +6. 来宾用户可以访问 GitLab [**版本**](project/releases/index.html)来下载资产,但不能下载源代码,也不能查看存储库信息(例如标签和提交). +7. 操作仅限于用户拥有(引用)的记录​​. +8. 启用" [共享组锁定"后](./group/index.html#share-with-group-lock) ,该项目将无法与其他组共享. 它不影响具有组共享的组. +9. 有关合并请求的[合格批准人的](project/merge_requests/merge_request_approvals.html#eligible-approvers)信息,请参阅[合格](project/merge_requests/merge_request_approvals.html#eligible-approvers)合并[人](project/merge_requests/merge_request_approvals.html#eligible-approvers) . + +## Project features permissions[](#project-features-permissions "Permalink") + +### Wiki and issues[](#wiki-and-issues "Permalink") + +可以根据用户在项目设置上选择的可见性级别对用户隐藏 Wiki 和问题等项目功能. + +* 禁用:所有人禁用 +* 仅团队成员:即使您的项目是公开的或内部的,也只有团队成员才能看到 +* 有访问权限的所有人:每个人都可以看到,具体取决于您的项目可见性级别 +* 每个人:为所有人启用(仅适用于 GitLab 页面) + +### Protected branches[](#protected-branches "Permalink") + +可以在每个分支的[受保护](project/protected_branches.html)分支上应用其他限制. 此外,您可以自定义权限,以允许或阻止项目维护者和开发者推送到受保护的分支. 阅读有关" [允许合并"和"允许推送"设置](project/protected_branches.html#using-the-allowed-to-merge-and-allowed-to-push-settings)的文档以了解更多信息. + +### Value Stream Analytics permissions[](#value-stream-analytics-permissions "Permalink") + +如[相关文档](analytics/value_stream_analytics.html#permissions)所述,在 Value Stream Analytics 仪表板上找到当前权限. + +### Issue Board permissions[](#issue-board-permissions "Permalink") + +具有较高权限级别的开发人员和用户可以使用发行版的所有功能,即创建/删除列表并拖动发行版. 通读[有关发行板权限](project/issue_board.html#permissions)的[文档](project/issue_board.html#permissions)以了解更多信息. + +### File Locking permissions[](#file-locking-permissions-premium "Permalink") + +锁定文件或目录的用户是唯一可以编辑并将其更改推回锁定对象所在存储库的用户. + +通读[有关文件锁定权限的文档](project/file_lock.html#permissions-on-file-locking)以了解更多信息. + +### Confidential Issues permissions[](#confidential-issues-permissions "Permalink") + +报告者和更高的权限级别以及创建机密问题的来宾用户都可以访问机密问题. 要了解更多信息,请通读有关[权限和访问机密问题](project/issues/confidential_issues.html#permissions-and-access-to-confidential-issues)的文档. + +## Group members permissions[](#group-members-permissions "Permalink") + +**注意:**在 GitLab 11.0 中,"主"角色已重命名为"维护者". + +任何用户都可以将自己从组中删除,除非他们是该组的最后一个所有者. 下表描述了组中的各种用户权限级别. + +| Action | Guest | Reporter | Developer | Maintainer | Owner | +| --- | --- | --- | --- | --- | --- | +| 浏览组 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看见解图表 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看小组史诗 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 创建/编辑小组史诗 |   | ✓ | ✓ | ✓ | ✓ | +| 管理群组标签 |   | ✓ | ✓ | ✓ | ✓ | +| 查看容器注册表 |   | ✓ | ✓ | ✓ | ✓ | +| Pull [packages](packages/index.html) |   | ✓ | ✓ | ✓ | ✓ | +| Publish [packages](packages/index.html) |   |   | ✓ | ✓ | ✓ | +| 查看指标仪表板注释 |   | ✓ | ✓ | ✓ | ✓ | +| 分组创建项目 |   |   | ✓ (3) | ✓ (3) | ✓ (3) | +| 与群组分享(邀请)群组 |   |   |   |   | ✓ | +| 创建/编辑/删除组里程碑 |   |   | ✓ | ✓ | ✓ | +| 创建/编辑/删除迭代 |   |   | ✓ | ✓ | ✓ | +| 启用/禁用依赖项代理 |   |   | ✓ | ✓ | ✓ | +| 使用安全仪表板 |   |   | ✓ | ✓ | ✓ | +| 创建/编辑/删除指标仪表板注释 |   |   | ✓ | ✓ | ✓ | +| 查看/管理组级别的 Kubernetes 集群 |   |   |   | ✓ | ✓ | +| 创建子组 |   |   |   | ✓ (1) | ✓ | +| 编辑史诗般的评论(由任何用户发布) |   |   |   | ✓ (2) | ✓ (2) | +| 编辑群组设定 |   |   |   |   | ✓ | +| 管理组级 CI / CD 变量 |   |   |   |   | ✓ | +| 列出组部署令牌 |   |   |   | ✓ | ✓ | +| 创建/删除组部署令牌 |   |   |   |   | ✓ | +| 管理小组成员 |   |   |   |   | ✓ | +| 删除群组 |   |   |   |   | ✓ | +| 删除组史诗 |   |   |   |   | ✓ | +| 编辑 SAML SSO 帐单 | ✓ | ✓ | ✓ | ✓ | ✓ (4) | +| 查看组审核事件 |   |   |   |   | ✓ | +| 禁用通知电子邮件 |   |   |   |   | ✓ | +| 查看贡献分析 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看见解 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看问题分析 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看生产力分析 |   | ✓ | ✓ | ✓ | ✓ | +| 查看价值流分析 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 查看帐单 |   |   |   |   | ✓ (4) | +| 查看使用配额 |   |   |   |   | ✓ (4) | + +1. 可以设置组以[允许所有者或所有者和维护者创建子组](group/subgroups/index.html#creating-a-subgroup) +2. 在 GitLab 12.2 中引入. +3. 可以在以下位置更改默认项目创建角色: + * [实例级别](admin_area/settings/visibility_and_access_controls.html#default-project-creation-protection) . + * [小组级别](group/index.html#default-project-creation-level) . +4. 不适用于子组. + +### Subgroup permissions[](#subgroup-permissions "Permalink") + +将成员添加到子组时,它们将从父组继承成员资格和权限级别. 如果您是其父级成员之一,则该模型允许访问嵌套组. + +To learn more, read through the documentation on [subgroups memberships](group/subgroups/index.html#membership). + +## External users[](#external-users-core-only "Permalink") + +如果希望用户只能访问某些内部或私有项目,则可以选择创建**外部用户** . 例如,当承包商在给定项目上工作且仅应访问该项目时,此功能可能很有用. + +外部用户: + +* 无法创建群组,项目或个人摘要. +* 只能访问公共项目和显式授予其访问权限的项目,从而对它们隐藏所有其他内部或私有项目(例如注销). + +可以通过将用户添加为项目或组的成员来授予访问权限. 与普通用户一样,他们将在项目或组中获得角色,具有[上面权限表](#project-members-permissions)中提到的所有功能. 例如,如果将外部用户添加为 Guest,而您的项目是私有项目,则他们将无权访问该代码; 如果您希望外部用户具有访问代码的权限,则需要授予其外部访问权限. 您应始终考虑[项目的可见性和权限设置](project/settings/index.html#sharing-and-permissions)以及用户的权限级别. + +**注意:**外部用户仍然计入许可证席位. + +管理员可以通过以下两种方法之一将用户标记为外部用户: + +* Either [through the API](../api/users.html#user-modification). +* 或通过导航到**管理区域>概述>用户**来创建新用户或编辑现有用户. 在那里,您将找到将用户标记为外部的选项. + +### Setting new users to external[](#setting-new-users-to-external "Permalink") + +默认情况下,新用户未设置为外部用户. 管理员可以在" **帐户和限制"**下的" **管理区域">"设置">"常规"**页面上更改此行为. + +如果更改了将新用户创建为外部用户的默认行为,则可以选择通过定义一组内部用户来缩小范围. **内部用户**字段允许指定电子邮件地址正则表达式模式以标识默认内部用户. 默认情况下,其电子邮件地址与正则表达式模式匹配的新用户将设置为内部用户,而不是外部协作者. + +正则表达式模式格式为 Ruby,但需要将其转换为 JavaScript,并将设置大小写忽略标志( `/regex pattern/i` ). 这里有些例子: + +* 使用`\.internal@domain\.com$`将以`.internal@domain.com`结尾的电子邮件地址标记为内部. +* 使用`^(?:(?!\.ext@domain\.com).)*$\r?` 使用不包含`.ext@domain.com`电子邮件地址标记用户为内部用户. + +**警告:**请注意,此正则表达式可能导致[正则表达式拒绝服务(ReDoS)攻击](https://en.wikipedia.org/wiki/ReDoS) . + +## Free Guest users[](#free-guest-users-ultimate "Permalink") + +如果为用户授予了项目,组或组或两者的来宾权限,并且对 GitLab 实例上的任何其他项目或组均没有更高的权限级别,则该用户被 GitLab 视为来宾用户,并且不会占用许可证席位. 对于新创建的用户,没有其他特定的"来宾"指定. + +如果在任何项目或组上为用户分配了更高的角色,则该用户将获得许可席位. 如果用户创建项目,则该用户将成为该项目的维护者,从而导致使用许可证席位. 另外,请注意,如果您的项目是内部项目或私有项目,则来宾用户将具有[上面](#project-members-permissions)的[权限表](#project-members-permissions)中提到的所有功能(例如,他们将无法浏览项目的存储库). + +**提示:**为防止访客用户创建项目,请以管理员身份编辑用户的个人资料,以将该用户标记为[external](#external-users-core-only) . 请注意,即使用户是外部用户,如果他们在任何项目或组中已经具有 Reporter 或更高权限, **也不**会将其计为免费的来宾用户. + +## Auditor users[](#auditor-users-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/998) in [GitLab Premium](https://about.gitlab.com/pricing/) 8.17. + +审核员用户被授予对 GitLab 实例上所有项目,组和其他资源的只读访问权限. + +审核员用户应能够使用[审核员用户权限](../administration/auditor_users.html#permissions-and-restrictions-of-an-auditor-user)文档中所述的权限访问 GitLab 实例的所有项目和组. + +[Read more about Auditor users.](../administration/auditor_users.html) + +## Project features[](#project-features "Permalink") + +可以根据用户在项目设置上选择的可见性级别对用户隐藏 Wiki 和问题等项目功能. + +* 禁用:所有人禁用 +* 仅团队成员:即使您的项目是公开的或内部的,也只有团队成员才能看到 +* 有访问权限的所有人:每个人都可以看到,具体取决于您的项目可见性级别 +* 每个人:为所有人启用(仅适用于 GitLab 页面) + +## GitLab CI/CD permissions[](#gitlab-cicd-permissions "Permalink") + +**注意:**在 GitLab 11.0 中,"主"角色已重命名为"维护者". + +GitLab CI / CD 权限取决于用户在 GitLab 中的角色. 共有四个权限级别: + +* admin +* maintainer +* developer +* guest/reporter + +管理员用户可以在 GitLab 实例和项目范围内对 GitLab CI / CD 执行任何操作. 此外,所有管理员都可以使用`/admin/runners`下的管理界面. + +| Action | 来宾,记者 | Developer | Maintainer | Admin | +| --- | --- | --- | --- | --- | +| 查看提交和工作 | ✓ | ✓ | ✓ | ✓ | +| 重试或取消作业 |   | ✓ | ✓ | ✓ | +| 擦除工件和跟踪 |   | ✓ (*1*) | ✓ | ✓ | +| 移除专案 |   |   | ✓ | ✓ | +| 建立专案 |   |   | ✓ | ✓ | +| 更改项目配置 |   |   | ✓ | ✓ | +| 添加特定跑步者 |   |   | ✓ | ✓ | +| 添加共享的跑步者 |   |   |   | ✓ | +| 查看系统中的事件 |   |   |   | ✓ | +| 管理界面 |   |   |   | ✓ | + +1. 仅当工作是: + * 由用户触发 + * [从 GitLab 13.0 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/35069) ,不为受保护的分支运行 + +### Job permissions[](#job-permissions "Permalink") + +**注意:**在 GitLab 11.0 中,"主"角色已重命名为"维护者". + +> **注意:** GitLab 8.12 具有完全重新设计的作业权限系统. 阅读有关[新模型及其含义的](project/new_ci_build_permissions_model.html)所有信息. + +下表显示了由特定类型的用户触发的作业的授予特权: + +| Action | 来宾,记者 | Developer | Maintainer | Admin | +| --- | --- | --- | --- | --- | +| 运行 CI 作业 |   | ✓ | ✓ | ✓ | +| 从当前项目克隆源和 LFS |   | ✓ | ✓ | ✓ | +| 从公共项目克隆源和 LFS |   | ✓ | ✓ | ✓ | +| 从内部项目克隆源和 LFS |   | ✓ (*1*) | ✓ (*1*) | ✓ | +| 从私有项目克隆源和 LFS |   | ✓ (*2*) | ✓ (*2*) | ✓ (*2*) | +| 从当前项目中提取容器图像 |   | ✓ | ✓ | ✓ | +| 从公共项目中提取容器图像 |   | ✓ | ✓ | ✓ | +| 从内部项目中提取容器图像 |   | ✓ (*1*) | ✓ (*1*) | ✓ | +| 从私有项目中提取容器图像 |   | ✓ (*2*) | ✓ (*2*) | ✓ (*2*) | +| 将容器图像推送到当前项目 |   | ✓ | ✓ | ✓ | +| 将容器图像推送到其他项目 |   |   |   |   | +| 推送源和 LFS |   |   |   |   | + +1. 仅当用户不是外部用户时 +2. 仅当用户是项目成员时 + +### New CI job permissions model[](#new-ci-job-permissions-model "Permalink") + +GitLab 8.12 具有完全重新设计的工作权限系统. 要了解更多信息,请通读有关[新 CI / CD 权限模型](project/new_ci_build_permissions_model.html#new-ci-job-permissions-model)的文档. + +## Running pipelines on protected branches[](#running-pipelines-on-protected-branches "Permalink") + +合并或推送到受保护分支的权限用于定义用户是否可以运行 CI / CD 管道并在与那些分支相关的作业上执行操作. + +有关管道安全模型的详细信息,请参阅[受保护分支上](../ci/pipelines/index.html#pipeline-security-on-protected-branches)的安全性. + +## LDAP users permissions[](#ldap-users-permissions "Permalink") + +从 GitLab 8.15 开始,LDAP 用户权限现在可以由管理员用户手动覆盖. 通读有关[LDAP 用户权限](group/index.html#manage-group-memberships-via-ldap)的文档以了解更多信息. + +## Project aliases[](#project-aliases "Permalink") + +项目别名只能由 GitLab 管理员读取,创建和删除. 通读有关[项目别名](../user/project/index.html#project-aliases-premium-only)的文档以了解更多信息. \ No newline at end of file diff --git a/docs/396.md b/docs/396.md new file mode 100644 index 0000000000000000000000000000000000000000..1c22f5247f2515a893dbe819f6e3486c85089967 --- /dev/null +++ b/docs/396.md @@ -0,0 +1,106 @@ +# Personal access tokens + +> 原文:[https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) + +* [Creating a personal access token](#creating-a-personal-access-token) + * [Revoking a personal access token](#revoking-a-personal-access-token) + * [Token activity](#token-activity) +* [Limiting scopes of a personal access token](#limiting-scopes-of-a-personal-access-token) +* [Programmatically creating a personal access token](#programmatically-creating-a-personal-access-token) +* [Programmatically revoking a personal access token](#programmatically-revoking-a-personal-access-token) + +# Personal access tokens[](#personal-access-tokens "Permalink") + +版本历史 + +* 在 GitLab 8.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3749) . +* 在 GitLab 12.6 中添加了[有关令牌过期的通知](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) . +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6 中添加了[令牌生存期限制](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) . + +If you’re unable to use [OAuth2](../../api/oauth2.html), you can use a personal access token to authenticate with the [GitLab API](../../api/README.html#personalproject-access-tokens). + +您还可以将个人访问令牌与 Git 一起使用,以通过 HTTP 或 SSH 进行身份验证. 启用[两因素身份验证(2FA)](../account/two_factor_authentication.html)时,需要个人访问令牌. 在这两种情况下,都可以使用令牌代替密码进行身份验证. + +个人访问令牌在您定义的日期 UTC 午夜到期. + +* GitLab 每天在世界标准时间 01:00 AM 进行检查,以识别将在 7 天内到期的个人访问令牌. 这些令牌的所有者通过电子邮件通知. +* 在 GitLab Ultimate 中,管理员可以[限制个人访问令牌的寿命](../admin_area/settings/account_and_limit_settings.html#limiting-lifetime-of-personal-access-tokens-ultimate-only) . +* 在 GitLab Ultimate 中,管理员可以[切换个人访问令牌到期的执行](../admin_area/settings/account_and_limit_settings.html#optional-enforcement-of-personal-access-token-expiry-ultimate-only) . + +有关如何使用个人访问令牌向 API 进行身份验证的示例,请参见[API 文档中](../../api/README.html#personalproject-access-tokens)的以下部分. + +GitLab 还提供了[模拟令牌](../../api/README.html#impersonation-tokens) ,这些[令牌](../../api/README.html#impersonation-tokens)是管理员通过 API 创建的. 它们非常适合作为特定用户的自动身份验证. + +## Creating a personal access token[](#creating-a-personal-access-token "Permalink") + +您可以在 GitLab 个人资料中创建任意数量的个人访问令牌. + +1. 登录到 GitLab. +2. 点击右上角的头像,然后选择**设置** . +3. 在" **用户设置"**菜单上,选择" **访问令牌"** . +4. 选择令牌的名称和可选的到期日期. +5. 选择[所需的范围](#limiting-scopes-of-a-personal-access-token) . +6. 单击**创建个人访问令牌**按钮. +7. 将个人访问令牌保存在安全的地方. 离开或刷新页面后,将无法再次访问它. + +### Revoking a personal access token[](#revoking-a-personal-access-token "Permalink") + +您可以随时单击" **活动个人访问令牌"**区域下的相应" **撤消"**按钮来撤消任何个人访问令牌. + +### Token activity[](#token-activity "Permalink") + +您可以从" **个人访问令牌"**页面**查看**上次使用**令牌的时间** . 令牌使用情况的更新每 24 小时固定一次. 对[API 资源](../../api/api_resources.html)和[GraphQL API 的](../../api/graphql/index.html)请求将更新令牌的用法. + +## Limiting scopes of a personal access token[](#limiting-scopes-of-a-personal-access-token "Permalink") + +可以使用一个或多个范围创建个人访问令牌,这些范围允许给定令牌可以执行各种操作. 下表描述了可用范围. + +| Scope | 引入 | Description | +| --- | --- | --- | +| `read_user` | [GitLab 8.15](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5951) | 允许访问`/users`下的只读端点. 本质上,允许[用户 API](../../api/users.html)中的任何`GET`请求. | +| `api` | [GitLab 8.15](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5951) | 授予对 API 的完全读写访问权限,包括所有组和项目,容器注册表和程序包注册表. | +| `read_api` | [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28944) | 授予对 API 的读取权限,包括所有组和项目,容器注册表和程序包注册表. | +| `read_registry` | [GitLab 9.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11845) | 如果项目是私有的并且需要授权,则允许读取(拉出) [容器注册表](../packages/container_registry/index.html)图像. | +| `sudo` | [GitLab 10.2](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14838) | 允许以系统中的任何用户身份执行 API 操作(如果经过身份验证的用户是管理员). | +| `read_repository` | [GitLab 10.7](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17894) | 允许通过`git clone`对存储库进行只读访问(拉). | +| `write_repository` | [GitLab 11.11](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26021) | 允许通过`git clone`对存储库进行读写访问(拉,推). 启用 2FA 时,通过 HTTP 访问 Git 存储库是必需的. | + +## Programmatically creating a personal access token[](#programmatically-creating-a-personal-access-token "Permalink") + +您可以以编程方式创建预定的个人访问令牌,以用于自动化或测试. 您将需要足够的访问权限才能为 GitLab 实例运行[Rails 控制台会话](../../administration/troubleshooting/debug.html#starting-a-rails-console-session) . + +要使用用户名`automation-bot`创建属于用户的令牌,请在 Rails 控制台( `sudo gitlab-rails console` )中运行以下`sudo gitlab-rails console` : + +``` +user = User.find_by_username('automation-bot') +token = user.personal_access_tokens.create(scopes: [:read_user, :read_repository], name: 'Automation token') +token.set_token('token-string-here123') +token.save! +``` + +使用[GitLab Rails Runner](../../administration/troubleshooting/debug.html#using-the-rails-runner)可以将其简化为单行 shell 命令: + +``` +sudo gitlab-rails runner "token = User.find_by_username('automation-bot').personal_access_tokens.create(scopes: [:read_user, :read_repository], name: 'Automation token'); token.set_token('token-string-here123'); token.save!" +``` + +**注意:**令牌字符串的长度必须为 20 个字符,否则将不会被识别为个人访问令牌. + +有效范围的列表及其作用可以[在源代码中](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/auth.rb)找到. + +## Programmatically revoking a personal access token[](#programmatically-revoking-a-personal-access-token "Permalink") + +您可以通过编程方式撤消个人访问令牌. 您将需要足够的访问权限才能为 GitLab 实例运行[Rails 控制台会话](../../administration/troubleshooting/debug.html#starting-a-rails-console-session) . + +要撤销已知令牌`token-string-here123` ,请在 Rails 控制台( `sudo gitlab-rails console` )中运行以下`sudo gitlab-rails console` : + +``` +token = PersonalAccessToken.find_by_token('token-string-here123') +token.revoke! +``` + +可以使用[GitLab Rails Runner](../../administration/troubleshooting/debug.html#using-the-rails-runner)将其[简化](../../administration/troubleshooting/debug.html#using-the-rails-runner)为单行 shell 命令: + +``` +sudo gitlab-rails runner "PersonalAccessToken.find_by_token('token-string-here123').revoke!" +``` \ No newline at end of file diff --git a/docs/397.md b/docs/397.md new file mode 100644 index 0000000000000000000000000000000000000000..231666c92dc07a9647f7b0292db980dd5ddf6c66 --- /dev/null +++ b/docs/397.md @@ -0,0 +1,163 @@ +# Profile preferences + +> 原文:[https://docs.gitlab.com/ee/user/profile/preferences.html](https://docs.gitlab.com/ee/user/profile/preferences.html) + +* [Navigation theme](#navigation-theme) +* [Dark mode](#dark-mode) +* [Syntax highlighting theme](#syntax-highlighting-theme) +* [Behavior](#behavior) + * [Layout width](#layout-width) + * [Default dashboard](#default-dashboard) + * [Group overview content](#group-overview-content) + * [Project overview content](#project-overview-content) + * [Tab width](#tab-width) +* [Localization](#localization) + * [Language](#language) + * [First day of the week](#first-day-of-the-week) +* [Integrations](#integrations) + * [Sourcegraph](#sourcegraph) + +# Profile preferences[](#profile-preferences "Permalink") + +用户的个人资料首选项页面允许用户自定义 GitLab 的各个方面. + +要导航至个人资料的首选项,请执行以下操作: + +1. 单击您的头像. +2. Select **Settings**. +3. 单击边栏中的**首选项** . + +## Navigation theme[](#navigation-theme "Permalink") + +GitLab 导航主题设置可让您个性化 GitLab 体验. 您可以从多个颜色主题中进行选择,这些主题可以为顶部导航和左侧导航添加独特的颜色. 使用单独的颜色主题可以帮助您区分不同的 GitLab 实例. + +默认主题为 Indigo. 您可以选择 10 个主题: + +* Indigo +* 浅靛蓝 +* Blue +* 浅蓝 +* Green +* 浅绿色 +* Red +* 红灯 +* Dark +* Light + +[![Profile preferences navigation themes](img/c6c38f70c273cc4412f6d3bd29af3829.png)](img/profil-preferences-navigation-theme.png) + +## Dark mode[](#dark-mode "Permalink") + +[介绍](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28252)在 GitLab 13.1 作为一个 alpha 版本. + +manbetx 客户端打不开已经开始在黑暗模式下工作! 深色[版本](https://about.gitlab.com/handbook/product/#alpha)的[Alpha 版本](https://about.gitlab.com/handbook/product/#alpha)本着迭代的精神和[Alpha 版本](https://about.gitlab.com/handbook/product/#alpha)的较低期望提供. + +[黑暗主题史诗中](https://gitlab.com/groups/gitlab-org/-/epics/2902)追踪了黑暗模式的进展. 见史诗: + +* 已知问题列表. +* 我们计划的方向和下一步. + +如果发现未列出的问题,请在史诗上发表评论或创建新的问题. + +出于 MVC 和兼容性原因,暗模式可用作导航主题. 将来,我们计划使其在自己的部分中可配置,同时支持[不同的导航主题](https://gitlab.com/gitlab-org/gitlab/-/issues/219512) . + +**注意:**深色主题当前仅适用于"深色"语法突出显示. + +## Syntax highlighting theme[](#syntax-highlighting-theme "Permalink") + +**注意:** GitLab 使用[rouge Ruby 库](http://rouge.jneen.net/ "胭脂网站")在任何 Editor 上下文之外突出显示语法. WebIDE(如代码片段)使用[Monaco Editor](https://microsoft.github.io/monaco-editor/) ,并提供了[Monarch](https://microsoft.github.io/monaco-editor/monarch.html)库以突出显示语法. 有关支持的语言的列表,请访问相应库的文档. + +更改此设置可让您在 GitLab 上查看语法突出显示的代码时自定义颜色主题. + +默认语法主题为"白色",您可以在 5 个不同的主题中进行选择: + +* White +* Dark +* 日光灯 +* 日光暗 +* Monokai + +[![Profile preferences syntax highlighting themes](img/bde796b0c195045db9849eef2842bd0e.png)](img/profile-preferences-syntax-themes.png) + +您在 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2389)的主题也适用于[Web IDE](../project/web_ide/index.html)的代码编辑器和[Snippets](../snippets.html) . 主题仅在 Web IDE 文件编辑器中可用, [深色主题](https://gitlab.com/gitlab-org/gitlab/-/issues/209808)和[日光化深色主题](https://gitlab.com/gitlab-org/gitlab/-/issues/219228)除外,它们适用于整个 Web IDE 屏幕. + +## Behavior[](#behavior "Permalink") + +以下设置可让您自定义 GitLab 布局的行为以及仪表板和项目登录页面的默认视图. + +### Layout width[](#layout-width "Permalink") + +可以根据喜好将 GitLab 设置为使用不同的宽度. 在固定(最大`1280px` )和流畅( `100%` )应用程序布局之间选择. + +**注意:**虽然使用固定版式时`1280px`是标准最大宽度,但是某些页面仍根据内容使用 100%宽度. + +### Default dashboard[](#default-dashboard "Permalink") + +对于有权访问大量项目但仅能跟上少数项目的用户,默认"仪表板"页面上的活动量可能会很大. 更改此设置可让您重新定义默认的仪表板. + +您可以在此处使用 8 个选项作为默认仪表板视图: + +* 您的项目(默认) +* 已加星标的项目 +* 您的项目活动 +* 已加星标项目的活动 +* 您的团体 +* Your [Todos](../todos.html) +* 分配的问题 +* 分配的合并请求 +* 操作仪表板 + +### Group overview content[](#group-overview-content "Permalink") + +网上**论坛概述内容**下拉菜单允许您选择网上论坛首页上显示的信息. + +您可以选择 2 个选项: + +* 详细信息(默认) +* [Security dashboard](../application_security/security_dashboard/index.html) + +### Project overview content[](#project-overview-content "Permalink") + +项目概述内容设置允许您选择想要在项目主页上看到的内容. + +您可以选择 3 个选项: + +* 文件和自述文件(默认) +* Readme +* Activity + +### Tab width[](#tab-width "Permalink") + +您可以在 GitLab 的各个部分设置标签字符的显示宽度,例如 blob,diff 和片段. + +**注意:** GitLab 的某些部分不遵守此设置,包括 WebIDE,文件编辑器和 Markdown 编辑器. + +## Localization[](#localization "Permalink") + +### Language[](#language "Permalink") + +从支持的语言列表中选择首选语言. + +*此功能是实验性的,翻译尚未完成.* + +### First day of the week[](#first-day-of-the-week "Permalink") + +可以针对日历视图和日期选择器自定义一周的第一天. + +您可以选择以下选项之一作为一周的第一天: + +* Saturday +* Sunday +* Monday + +如果选择**System Default** ,则将使用系统范围的默认设置. + +## Integrations[](#integrations "Permalink") + +使用第三方服务配置您的首选项,这些服务可增强您的 GitLab 体验. + +### Sourcegraph[](#sourcegraph "Permalink") + +**注意:**仅当 GitLab 管理员已启用 Sourcegraph 时,此设置才可见. + +管理由 Sourcegraph 支持的集成代码智能功能的可用性. 查看[Sourcegraph 功能文档](../../integration/sourcegraph.html#enable-sourcegraph-in-user-preferences)以获取更多信息. \ No newline at end of file diff --git a/docs/398.md b/docs/398.md new file mode 100644 index 0000000000000000000000000000000000000000..0fec52eeae6545c505d517087656d1cf33aebb4e --- /dev/null +++ b/docs/398.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html) \ No newline at end of file diff --git a/docs/399.md b/docs/399.md new file mode 100644 index 0000000000000000000000000000000000000000..e88667ae9a5c57927e4db687a44733868110ccdf --- /dev/null +++ b/docs/399.md @@ -0,0 +1,475 @@ +# Threads + +> 原文:[https://docs.gitlab.com/ee/user/discussions/](https://docs.gitlab.com/ee/user/discussions/) + +* [Resolvable comments and threads](#resolvable-comments-and-threads) + * [Commit threads in the context of a merge request](#commit-threads-in-the-context-of-a-merge-request) + * [Jumping between unresolved threads](#jumping-between-unresolved-threads) + * [Marking a comment or thread as resolved](#marking-a-comment-or-thread-as-resolved) + * [Move all unresolved threads in a merge request to an issue](#move-all-unresolved-threads-in-a-merge-request-to-an-issue) + * [Moving a single thread to a new issue](#moving-a-single-thread-to-a-new-issue) + * [Only allow merge requests to be merged if all threads are resolved](#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved) + * [Automatically resolve merge request diff threads when they become outdated](#automatically-resolve-merge-request-diff-threads-when-they-become-outdated) +* [Commit threads](#commit-threads) +* [Threaded discussions](#threaded-discussions) +* [Image threads](#image-threads) +* [Lock discussions](#lock-discussions) +* [Merge Request Reviews](#merge-request-reviews) + * [Starting a review](#starting-a-review) + * [Resolving/Unresolving threads](#resolvingunresolving-threads) + * [Submitting a review](#submitting-a-review) +* [Filtering notes](#filtering-notes) +* [Suggest Changes](#suggest-changes) + * [Multi-line Suggestions](#multi-line-suggestions) + * [Code block nested in Suggestions](#code-block-nested-in-suggestions) + * [Configure the commit message for applied Suggestions](#configure-the-commit-message-for-applied-suggestions) + * [Batch Suggestions](#batch-suggestions) + * [Enable or disable Batch Suggestions](#enable-or-disable-batch-suggestions) +* [Start a thread by replying to a standard comment](#start-a-thread-by-replying-to-a-standard-comment) +* [Assign an issue to the commenting user](#assign-an-issue-to-the-commenting-user) + +# Threads[](#threads "Permalink") + +整个 GitLab 都提供了进行对话的能力. + +您可以在以下位置发表评论: + +* Issues +* Epics +* 合并要求 +* Snippets +* Commits +* 提交差异 + +有标准注释,您还可以选择以线程形式创建注释. 收到回复后,评论也可以[变成主题](#start-a-thread-by-replying-to-a-standard-comment) . + +评论区域支持[Markdown](../markdown.html)和[快速操作](../project/quick_actions.html) . 您可以随时编辑自己的评论,拥有" [维护者"访问级别](../permissions.html)或更高[权限的](../permissions.html)任何人也可以编辑其他人的评论. + +如果为您的 GitLab 实例配置了" [通过电子邮件回复",](../../administration/reply_by_email.html)您还可以回复评论通知电子邮件以回复评论. 回复标准评论会创建另一个标准评论. 回复主题注释会在主题中创建回复. 电子邮件回复支持[Markdown](../markdown.html)和[快速操作](../project/quick_actions.html) ,就像您从网络上回复一样. + +**注意:**每个对象最多只能有 5,000 条注释,例如:issue,epic 和 merge request. + +## Resolvable comments and threads[](#resolvable-comments-and-threads "Permalink") + +版本历史 + +* 在 GitLab 8.11 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5022) . +* 可解决的线程只能添加到合并请求差异中. + +线程解析有助于跟踪计划或代码审查期间的进度. + +合并请求,提交,提交差异和摘要中的每个标准注释或线程最初都显示为未解决. 然后,至少具有开发人员访问项目权限的任何人或所检查的更改的作者都可以单独解决这些问题. 如果该线程已解决,并且非成员取消了他们自己的响应,则这也将取消解决讨论线程. 如果非成员然后解决了相同的答复,则将解决讨论线程. + +解决所有标准注释或线程的需求可以防止您忘记处理反馈,并可以隐藏不再相关的线程. + +[!["A thread between two people on a piece of code"](img/18f2b22b7daf0beab9074c6695c99960.png)](img/thread_view.png) + +### Commit threads in the context of a merge request[](#commit-threads-in-the-context-of-a-merge-request "Permalink") + +在 GitLab 10.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/31847) . + +对于具有基于提交的工作流的审阅者,在合并请求的上下文中将线程添加到特定的提交差异可能很有用. 在以下情况下,这些线程将通过更改提交 ID 保持不变: + +* 重新设置后强制推动 +* 修改提交 + +创建提交差异线程: + +1. 导航到合并请求的" **提交"**选项卡. 将显示构成合并请求的提交列表. + + [![Merge request commits tab](img/b061980557a1e04fe2a2f3836b8dd9c1.png)](img/merge_request_commits_tab.png) + +2. 导航到特定的提交,单击" **更改"**选项卡(在该选项卡中,将仅显示与所选提交不同的内容),并留下评论. + + [![Commit diff discussion in merge request context](img/fc09af9303f629aff49a9a4dc5327e65.png)](img/commit_comment_mr_context.png) + +3. 以这种方式创建的任何线程都将显示在合并请求的" **讨论"**选项卡中,并且可以解决. + + [![Merge request Discussions tab](img/033c41dc1122d52872dcb67228037524.png)](img/commit_comment_mr_discussions_tab.png) + +以这种方式创建的线程将仅出现在原始合并请求中,而不是导航到项目的" **存储库">"提交"**页面下的**提交时** . + +**提示:**在合并请求内的线程中找到提交引用的链接时,它将在当前合并请求的上下文中自动转换为链接. + +### Jumping between unresolved threads[](#jumping-between-unresolved-threads "Permalink") + +当合并请求中包含大量注释时,可能很难跟踪仍未解决的问题. 您可以使用线程上"回复"字段旁边的"跳转"按钮在未解决的线程之间跳转. + +您也可以从已解决的线程跟踪器旁边的按钮跳转到下一个未解决的线程. + +您还可以使用键盘快捷键在线程之间导航: + +* 使用`n`跳到下一个未解决的线程. +* 使用`p`跳到上一个未解决的线程. + +[!["8/9 threads resolved"](img/27b77c1cf5861234d7e06b742e7cbf58.png)](img/threads_resolved.png) + +### Marking a comment or thread as resolved[](#marking-a-comment-or-thread-as-resolved "Permalink") + +您可以通过单击**线程**底部的" **解决线程"**按钮将其标记为已解决. + +[!["Resolve thread" button](img/f94efd219528f7641e29dbca3bc215ad.png)](img/resolve_thread_button.png) + +或者,您可以将每个评论标记为单独解决. + +[!["Resolve comment" button](img/9246e597493024c10e4f678f7de7318e.png)](img/resolve_comment_button.png) + +### Move all unresolved threads in a merge request to an issue[](#move-all-unresolved-threads-in-a-merge-request-to-an-issue "Permalink") + +在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8266) + +要在新问题中继续执行来自合并请求的所有打开的线程,请单击" **解决新问题中的所有线程"**按钮. + +[![Open new issue for all unresolved threads](img/c7b2f6ed12531da21a4512becdf843af.png)](img/btn_new_issue_for_all_threads.png) + +或者,当您的项目仅[在解决所有线程](#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved)后才接受合并请求[时](#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved) ,将存在**一个问题,即以后**在合并请求小部件中**解决它们的**链接. + +[![Link in merge request widget](img/4e480a29eb679b62ed97f748fc9acdd7.png)](img/resolve_thread_open_issue.png) + +这将准备一个问题,其内容涉及合并请求和未解决的线程. + +[![Issue mentioning threads in a merge request](img/cbf589a2c41bb518f8f2da56b76a59dc.png)](img/preview_issue_for_threads.png) + +击中" **提交"问题**将导致所有线程被标记为已解决,并添加注释以引用新创建的问题. + +[![Mark threads as resolved notice](img/b36e59e0da065f17e34891efef2ee0a1.png)](img/resolve_thread_issue_notice.png) + +现在,您可以继续从 UI 合并合并请求. + +### Moving a single thread to a new issue[](#moving-a-single-thread-to-a-new-issue "Permalink") + +在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8266) + +要为单个线程创建新问题,可以使用" **在新问题中解决此线程"**按钮. + +[![Create issue for thread](img/c3948ae724d699cf1ec0da64ab3e6a14.png)](img/new_issue_for_thread.png) + +这会将您定向到预填充了线程内容的新问题,类似于为一次委派多个线程而创建的问题. 保存问题将把该线程标记为已解决,并在合并请求线程中添加引用新问题的注释. + +[![New issue for a single thread](img/e5d9c1be329fa86c36614dea613f69a3.png)](img/preview_issue_for_thread.png) + +### Only allow merge requests to be merged if all threads are resolved[](#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved "Permalink") + +在 GitLab 8.14 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7125) . + +在解决所有线程之前,可以阻止合并请求. + +导航到项目的设置页面,选中" **仅在解决所有线程后才允许合并请求"**复选框,然后单击" **保存"**以使更改生效. + +[![Only allow merge if all the threads are resolved settings](img/9bc04e4a71e5ed3917efabdca45725c7.png)](img/only_allow_merge_if_all_threads_are_resolved.png) + +从现在开始,直到所有线程解决后,您才能从 UI 进行合并. + +[![Only allow merge if all the threads are resolved message](img/4e480a29eb679b62ed97f748fc9acdd7.png)](img/resolve_thread_open_issue.png) + +### Automatically resolve merge request diff threads when they become outdated[](#automatically-resolve-merge-request-diff-threads-when-they-become-outdated "Permalink") + +在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14053) . + +您可以在使用新的推送修改的行上自动解决合并请求差异线程. + +导航到您的项目的设置页面,选中" **使用推送更改的行上**的**自动解析合并请求差异线程"**复选框,然后单击" **保存"**以使更改生效. + +[![Automatically resolve merge request diff threads when they become outdated](img/a283d966822ac6a760d1a650273fbb3b.png)](img/automatically_resolve_outdated_discussions.png) + +从现在开始,如果推送使 diff 部分过时,默认情况下将解决 diff 上的所有线程. 不变的线上线程和顶级可解析线程不会自动解析. + +## Commit threads[](#commit-threads "Permalink") + +您可以在项目的**Repository> Commits**下向特定提交添加注释和线程. + +**注意:**如果在强制推送后更改了提交 ID,则以这种方式创建的线程将丢失. + +## Threaded discussions[](#threaded-discussions "Permalink") + +在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7527) . + +尽管可解析线程仅可用于合并请求差异,但也可以添加没有差异的线程. 您可以针对问题,提交,摘要和合并请求启动一个看起来像线程的特定线程. + +要开始主题讨论,请单击" **评论"**按钮切换下拉列表,选择" **开始主题",**并在准备发布评论时单击" **开始主题** ". + +[![Comment type toggle](img/66e7cbbe98ed69a6154c1adcd7ec4f6e.png)](img/comment_type_toggle.gif) + +这将以单个线程发布评论,使您可以更详细地讨论特定评论. + +[![Thread comment](img/d3cc00bf5599be56b0b3154ca2751cbc.png)](img/discussion_comment.png) + +## Image threads[](#image-threads "Permalink") + +在 GitLab 10.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14061) . + +有时线程围绕图像旋转. 使用图像线程,您可以轻松地定位图像的特定坐标并在其周围启动线程. 图像线程在合并请求和提交详细信息视图中可用. + +要启动图像线程,请将鼠标悬停在图像上. 您的鼠标指针应转换为图标,表示该图像可用于注释. 只需单击图像上的任意位置以创建新线程. + +[![Start image thread](img/72a8c3cb5bafa1e02d93f68a624b6094.png)](img/start_image_discussion.gif) + +单击图像后,将显示注释表单,该注释表单将成为您线程的开始. 保存评论后,您会在图像顶部看到一个新的徽章. 此徽章代表您的话题. + +> **注意:**该线程标志通常与一个数字关联,该数字仅用作每个线程的可视参考. 在合并请求线程选项卡中,此标记将带有注释图标,因为每个线程都会呈现一个新的图像部分. + +图像线程还可以在替换现有图像的差异上工作. 在此差异查看模式下,您可以切换不同的查看模式,但仍可以看到线点标记. + +| 2-up | Swipe | 洋葱皮 | +| --- | --- | --- | +| [![2-up view](img/be7e963d6561756bb87f6fea0cd245fa.png)](img/two_up_view.png) | [![swipe view](img/14110c067c5c98646bcad82dbd3be10b.png)](img/swipe_view.png) | [![onion skin view](img/5113c12752dd029f29a28c6f0660cde1.png)](img/onion_skin_view.png) | + +映像线程也可与可解析线程一起很好地工作. 差异上的已解析线程(不在"合并请求讨论"选项卡上)在页面加载时将显示为折叠状态,并且将具有对应的标记计数器以匹配图像上的计数器. + +[![Image resolved thread](img/fc692dde7a0c9ce30f0036b1a05b2768.png)](img/image_resolved_discussion.png) + +## Lock discussions[](#lock-discussions "Permalink") + +在 GitLab 10.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14531) . + +For large projects with many contributors, it may be useful to stop threads in issues or merge requests in these scenarios: + +* 项目维护者已经解决了该线程,对于继续反馈没有帮助. +* 项目维护者已经将新对话指向新问题或合并请求. +* 参与线程的人正在拖钓,辱骂或没有生产力. + +在这些情况下,项目中具有开发者权限或更高权限的用户可以使用边栏中的"锁定"部分来锁定(和解锁)问题或合并请求. 对于问题,具有记者权限的用户可以锁定(和解锁). + +| Unlock | Lock | +| --- | --- | +| [![Turn off discussion lock](img/e7d7b1c5ccf121da6fcfbbc1eb78bbcd.png)](img/turn_off_lock.png) | [![Turn on discussion lock](img/3ed7ccf7499687536cf254fc6f47d5e7.png)](img/turn_on_lock.png) | + +系统注释指示锁定和解锁. + +[![Discussion lock system notes](img/2629e4ef9252e4970d626ca424e88dd2.png)](img/discussion_lock_system_notes.png) + +在锁定的问题或合并请求中,只有团队成员才能添加新评论和编辑现有评论. 禁止非团队成员添加或编辑评论. + +| 队员 | 非团队成员 | +| --- | --- | +| [![Comment form member](img/5c0acf7979c7bc1e89dc413017b70870.png)](img/lock_form_member.png) | [![Comment form non-member](img/94675a32947787d4e216a44e3047d0b5.png)](img/lock_form_non_member.png) | + +此外,无法重新打开锁定的问题和合并请求. + +## Merge Request Reviews[](#merge-request-reviews "Permalink") + +版本历史 + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 11.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4213) . +* 在 13.1 版中[移至](https://gitlab.com/gitlab-org/gitlab/-/issues/28154) GitLab Core. + +查看"合并请求"差异时,您可以开始审阅. 这样,您便可以在"合并请求"中创建**仅**在发布之前才对**您可见的**注释,以便您可以将所有注释作为单个操作提交. + +### Starting a review[](#starting-a-review "Permalink") + +为了开始审阅,只需像往常一样在 MR 的" **更改"**选项卡下对差异添加注释,然后单击" **开始审阅"**按钮. + +[![Starting a review](img/40dbd9d2f1f965f42a1c417a258da575.png)](img/mr_review_start.png) + +Once a review is started, you will see any comments that are part of this review marked `Pending`. All comments that are part of a review show two buttons: + +* **完成审阅** :提交**审阅中的**所有评论,使其他用户可以看到它们. +* **立即添加评论** :提交特定评论作为常规评论,而不是审阅的一部分. + +[![A comment that is part of a review](img/9fa9d16dd2302ab20167b7ff1ca62575.png)](img/pending_review_comment.png) + +您可以在评论中使用[快速操作](../project/quick_actions.html) . 注释将显示发布后将执行的操作. + +[![A review comment with quick actions](img/2927b047cacec2945671ab2484aafe9d.png)](img/review_comment_quickactions.png) + +要向评论添加更多评论,请照常开始写评论,然后单击**添加到评论**按钮. + +[![Adding a second comment to a review](img/996ea860188e6458fe761cf86b2b72b1.png)](img/mr_review_second_comment.png) + +这会将评论添加到评论中. + +[![Second review comment](img/a102a1abbf4c760dba4b8b3daef8fe26.png)](img/mr_review_second_comment_added.png) + +### Resolving/Unresolving threads[](#resolvingunresolving-threads "Permalink") + +评论注释也可以解决/无法解决[可解决的线程](#resolvable-comments-and-threads) . 回复评论时,您将看到一个复选框,您可以单击该复选框以在发布后解决或取消解决线程. + +[![Resolve checkbox](img/865329b4b113d6de44cf382bd77178fa.png)](img/mr_review_resolve.png) + +如果特定的待处理注释将解决或取消解决该线程,它将显示在待处理注释本身上. + +[![Resolve status](img/83da8fe833233875ee4fe28fa21eb1dd.png)](img/mr_review_resolve2.png) + +[![Unresolve status](img/ce6315abe3d0bf8a315febe4ab497312.png)](img/mr_review_unresolve.png) + +### Submitting a review[](#submitting-a-review "Permalink") + +If you have any comments that have not been submitted, you will see a bar at the bottom of the screen with two buttons: + +* **舍弃** : **舍弃**所有尚未提交的评论. +* **完成审阅** :打开准备提交审阅的评论列表. 单击**提交评论**将发布所有评论. 此时将执行所有提交的快速操作. + +另外,要通过待审核的评论完成整个审核,请执行以下操作: + +* 单击**评论**上的" **完成审阅"**按钮. +* 在非评论注释的文本中使用`/submit_review` [快速操作](../project/quick_actions.html) . + +[![Review submission](img/c6daa1e81d653cfd0b476144f1f71874.png)](img/review_preview.png) + +提交审阅将向合并请求的每个应通知用户发送一封电子邮件,其中包含与之相关的所有注释. + +因此,回复此电子邮件将在关联的合并请求上创建一个新注释. + +## Filtering notes[](#filtering-notes "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26723) . + +对于活动注释和用户注释等具有许多注释的问题,有时很难找到有用的信息. 有一种方法可以针对合并请求和问题从单个注释和线程中过滤注释. + +从合并请求的" **讨论"**选项卡,或史诗/问题概述中,找到页面右侧的过滤器下拉菜单,您可以从中选择以下选项之一: + +* **显示所有活动** :显示所有用户评论和系统注释(问题更新,对其他问题的提及,对描述的更改等). +* **仅显示评论** :仅在列表中显示用户评论. +* **仅显示历史记录** :仅显示活动记录. + +[![Notes filters dropdown options](img/5a26f77375b52645c2387aec1f77a777.png)](img/index_notes_filters.png) + +在给定问题或 MR 中选择过滤器之一后,GitLab 将保存您的首选项,这样当您从已登录的任何设备再次访问同一页面时,该首选项将保持不变. + +## Suggest Changes[](#suggest-changes "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/18008) . + +作为审阅者,您可以在 Merge Request Diff 线程中使用简单的 Markdown 语法建议代码更改. 然后,合并请求作者(或具有适当[权限的](../permissions.html)其他用户)能够通过单击来应用这些建议,这将在应用了这些建议的用户创作的合并请求中生成提交. + +1. 选择要更改的代码行,添加新注释,然后单击工具栏中的" **插入建议"**图标: + + [![Add a new comment](img/d7cb226977bb46d9aaa1c1d7e195025a.png)](img/suggestion_button_v12_7.png) + +2. 在注释中,将您的建议添加到预填充的代码块中: + + [![Add a suggestion into a code block tagged properly](img/44cad341f814ae94da18480c3dc1d2be.png)](img/make_suggestion_v12_7.png) + +3. 单击**开始审查**或**加入审查** ,以您的评论添加到[审查](#merge-request-reviews) ,或者**现在添加注释** ,注释立即加入到线程. + + 注释中的"建议"可由合并请求作者直接从合并请求中应用: + + [![Apply suggestions](img/0dd0fc53dcaa34b76a16be18538c1a35.png)](img/apply_suggestion_v12_7.png) + +一旦作者应用了一个建议,它将被标记为"已**应用"**标签,该线程将被自动解析,并且 GitLab 将创建一个新的提交,并将建议的更改直接推送到合并请求分支中的代码库中. 这样做需要[开发人员许可](../permissions.html) . + +### Multi-line Suggestions[](#multi-line-suggestions "Permalink") + +在 GitLab 11.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53310) . + +审阅者还可以通过调整范围偏移,在合并请求差异线程中使用单个"建议"来建议对多行进行更改. 偏移量相对于 diff 线程的位置,并指定应用建议时要被建议替换的范围. + +[![Multi-line suggestion syntax](img/317167b85f9604b741e71e57b1702b6c.png)](img/multi-line-suggestion-syntax.png) + +在上面的示例中,建议涵盖了注释行上方的三行和注释行下方的四行. 应用时,它将用建议的更改从注释行*上方的* 3 行替换为注释行*下方*的 4 行. + +[![Multi-line suggestion preview](img/590715bab1c8704d5a4c16437c011ed5.png)](img/multi-line-suggestion-preview.png) + +**注意:**涵盖多行的建议仅限于已注释差异行*上方的* 100 行和*下方*的差异行*下方*的 100 行,每个建议最多可更改 200 行. + +### Code block nested in Suggestions[](#code-block-nested-in-suggestions "Permalink") + +如果您需要提出涉及[受限制的代码块](../markdown.html#code-spans-and-blocks)的建议,请将您的建议换成四个反引号,而不是通常的三个. + +[![A comment editor with a suggestion with a fenced code block](img/a4e7c4f55411323814dd3b9cb30ab9f8.png)](img/suggestion_code_block_editor_v12_8.png) + +[![Output of a comment with a suggestion with a fenced code block](img/db0182b2e43670178e35b1a3485ca25e.png)](img/suggestion_code_block_output_v12_8.png) + +### Configure the commit message for applied Suggestions[](#configure-the-commit-message-for-applied-suggestions "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/13086) . + +GitLab 在应用建议时使用默认的提交消息: `Apply %{suggestions_count} suggestion(s) to %{files_count} file(s)` + +例如,假设用户将 3 条建议应用于 2 个不同的文件,则默认的提交消息将是: **将 3 条建议应用于 2 个文件** + +可以自定义这些提交消息,以遵循您可能拥有的任何准则. 为此, **请**在项目的" **常规"**设置中展开" **合并请求"**选项卡,然后更改" **合并建议"**文本: + +[![Custom commit message for applied Suggestions](img/182928c540d17ccf275438850fc7592d.png)](img/suggestions_custom_commit_messages_v13_1.jpg) + +除了静态文本,您还可以使用以下变量: + +| Variable | Description | 输出示例 | +| --- | --- | --- | +| `%{branch_name}` | 建议所应用到的分支的名称. | `my-feature-branch` | +| `%{files_count}` | 应用了建议的文件数. | **2** | +| `%{file_paths}` | 应用了建议文件的路径. 路径用逗号分隔. | `docs/index.md, docs/about.md` | +| `%{project_path}` | 项目路径. | `my-group/my-project` | +| `%{project_name}` | 项目的可读名称. | **我的项目** | +| `%{suggestions_count}` | 应用的建议数. | **3** | +| `%{username}` | 应用建议的用户的用户名. | `user_1` | +| `%{user_full_name}` | 应用建议的用户的全名. | **用户 1** | + +例如,要自定义提交消息以输出**Addresses user_1 的评论** ,请将自定义文本设置为`Addresses %{username}'s review` . + +**注意:** [#25381](https://gitlab.com/gitlab-org/gitlab/-/issues/25381)将为每个应用的建议(以及批量建议)引入自定义提交消息. + +### Batch Suggestions[](#batch-suggestions "Permalink") + +版本历史 + +* 在 GitLab 13.1 中作为[Alpha 功能](https://about.gitlab.com/handbook/product/#alpha) [引入](https://gitlab.com/gitlab-org/gitlab/-/issues/25486) . +* 它部署在功能标记后面,默认情况下处于禁用状态. +* 在 GitLab.com 上已禁用. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-batch-suggestions) . + +您可以一次应用多个建议,以减少为满足审阅者的请求而添加到分支的提交数量. + +1. 要启动将在一次提交中应用的一批建议,请单击" **将建议添加到批处理"** : + + [![A code change suggestion displayed, with the button to add the suggestion to a batch highlighted.](img/f12701028e6548c505318ef2d4e378db.png "Add a suggestion to a batch")](img/add_first_suggestion_to_batch_v13_1.jpg) + +2. 根据需要向批处理中添加尽可能多的其他建议: + + [![A code change suggestion displayed, with the button to add an additional suggestion to a batch highlighted.](img/f60803ec89d6ae84310e181507eb2ad8.png "Add another suggestion to a batch")](img/add_another_suggestion_to_batch_v13_1.jpg) + +3. 要删除建议,请单击" **从批处理中删除"** : + + [![A code change suggestion displayed, with the button to remove that suggestion from its batch highlighted.](img/e28a69b4996ee400ca3df4431df0ab13.png "Remove a suggestion from a batch")](img/remove_suggestion_from_batch_v13_1.jpg) + +4. 将所有建议添加到您的喜好中后,准备好后,请点击**应用建议** : + + [![A code change suggestion displayed, with the button to apply the batch of suggestions highlighted.](img/ed8bdb5d349320bc1d470f096578dfe7.png "Apply a batch of suggestions")](img/apply_batch_of_suggestions_v13_1.jpg) + +#### Enable or disable Batch Suggestions[](#enable-or-disable-batch-suggestions "Permalink") + +批处理建议部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../administration/feature_flags.html)可以为您的实例启用它. + +要启用它: + +``` +# Instance-wide +Feature.enable(:batch_suggestions) +``` + +禁用它: + +``` +# Instance-wide +Feature.disable(:batch_suggestions) +``` + +## Start a thread by replying to a standard comment[](#start-a-thread-by-replying-to-a-standard-comment "Permalink") + +在 GitLab 11.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30299) + +要回复标准(非线程)评论,可以使用" **回复评论"**按钮. + +[![Reply to comment button](img/d198d958fcf8be60727c232ff69b9713.png)](img/reply_to_comment_button.png) + +仅当您有权回复现有主题或从标准评论启动主题时,才会显示" **回复评论"**按钮. + +单击" **回复评论"**按钮将使回复区域成为焦点,您可以键入回复. + +[![Reply to comment feature](img/9f29552692cfb04d323dc62cc4bc1d1e.png)](img/reply_to_comment.gif) + +提交回复后,回复非线程注释将把非线程注释转换为线程. 该转换被认为是对原始评论的修改,因此在其下方会出现一条有关上次编辑时间的注释. + +此功能仅适用于"问题","合并请求"和"事件". 尚不支持提交,摘要和合并请求差异线程. + +## Assign an issue to the commenting user[](#assign-an-issue-to-the-commenting-user "Permalink") + +在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/191455) . + +您可以将问题分配给发表评论的用户. + +在评论中,单击" **更多操作"**菜单,然后单击" **分配给评论用户"** . + +再次单击按钮以取消分配评论者. + +[![Assign to commenting user](img/9b6a8d0d96113fcaadd766cecfbecdbc.png)](img/quickly_assign_commenter_v13_1.png) \ No newline at end of file diff --git a/docs/400.md b/docs/400.md new file mode 100644 index 0000000000000000000000000000000000000000..78df8124308ef04e7c771c58a15b44eeb18c6a0b --- /dev/null +++ b/docs/400.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/topics/authentication/](https://docs.gitlab.com/ee/topics/authentication/) \ No newline at end of file diff --git a/docs/401.md b/docs/401.md new file mode 100644 index 0000000000000000000000000000000000000000..78df8124308ef04e7c771c58a15b44eeb18c6a0b --- /dev/null +++ b/docs/401.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/topics/authentication/](https://docs.gitlab.com/ee/topics/authentication/) \ No newline at end of file diff --git a/docs/402.md b/docs/402.md new file mode 100644 index 0000000000000000000000000000000000000000..4712fda47542d4bc7c4a04b9f09c47d70f0fa590 --- /dev/null +++ b/docs/402.md @@ -0,0 +1,368 @@ +# GitLab and SSH keys + +> 原文:[https://docs.gitlab.com/ee/ssh/README.html](https://docs.gitlab.com/ee/ssh/README.html) + +* [Requirements](#requirements) +* [Options for SSH keys](#options-for-ssh-keys) +* [Review existing SSH keys](#review-existing-ssh-keys) +* [Generating a new SSH key pair](#generating-a-new-ssh-key-pair) + * [ED25519 SSH keys](#ed25519-ssh-keys) + * [RSA SSH keys](#rsa-ssh-keys) + * [Common steps for generating an SSH key pair](#common-steps-for-generating-an-ssh-key-pair) + * [RSA keys and OpenSSH from versions 6.5 to 7.8](#rsa-keys-and-openssh-from-versions-65-to-78) +* [Adding an SSH key to your GitLab account](#adding-an-ssh-key-to-your-gitlab-account) +* [Testing that everything is set up correctly](#testing-that-everything-is-set-up-correctly) +* [Working with non-default SSH key pair paths](#working-with-non-default-ssh-key-pair-paths) +* [Per-repository SSH keys](#per-repository-ssh-keys) +* [Multiple accounts on a single GitLab instance](#multiple-accounts-on-a-single-gitlab-instance) +* [Deploy keys](#deploy-keys) +* [Applications](#applications) + * [Eclipse](#eclipse) +* [SSH on the GitLab server](#ssh-on-the-gitlab-server) + * [Options for Microsoft Windows](#options-for-microsoft-windows) +* [Troubleshooting](#troubleshooting) + +# GitLab and SSH keys[](#gitlab-and-ssh-keys "Permalink") + +Git 是一个分布式版本控制系统,这意味着您可以在本地工作. 此外,您还可以将更改共享或"推送"到其他服务器. GitLab 支持使用 SSH 密钥在 Git 及其服务器之间进行安全通信. + +SSH 协议提供了这种安全性,并允许您向 GitLab 远程服务器进行身份验证,而无需每次都提供用户名或密码. + +该页面可以帮助您配置安全的 SSH 密钥,这些密钥可用于帮助保护与 GitLab 存储库的连接. + +* 如果您需要有关创建 SSH 密钥的信息,请从我们[的 SSH 密钥选项](#options-for-ssh-keys)开始. +* 如果您有专用于 GitLab 帐户的 SSH 密钥,则可能对[使用非默认 SSH 密钥对路径](#working-with-non-default-ssh-key-pair-paths)感兴趣. +* 如果您已经有了 SSH 密钥对,则可以转到[将 SSH 密钥添加到 GitLab 帐户的方法](#adding-an-ssh-key-to-your-gitlab-account) . + +## Requirements[](#requirements "Permalink") + +为了支持 SSH,GitLab 需要安装 OpenSSH 客户端,该客户端已预安装在 GNU / Linux 和 macOS 上,但未预先安装在 Windows 上. + +确保您的系统包括 SSH 6.5 或更高版本,因为它不包括现在不安全的 MD5 签名方案. 以下命令返回系统上安装的 SSH 版本: + +``` +ssh -V +``` + +尽管 GitLab 不[支持在 Microsoft Windows 上进行安装](../install/requirements.html#microsoft-windows) ,但是您可以设置 SSH 密钥以将 Windows 设置[为客户端](#options-for-microsoft-windows) . + +## Options for SSH keys[](#options-for-ssh-keys "Permalink") + +GitLab 支持使用 RSA,DSA,ECDSA 和 ED25519 密钥. + +* GitLab 在 GitLab 11.0 中已[弃用](https://about.gitlab.com/releases/2018/06/22/gitlab-11-0-released/#support-for-dsa-ssh-keys) DSA 密钥. +* 如[Go 实用密码术中](https://leanpub.com/gocrypto/read#leanpub-auto-ecdsa)所述,与 DSA 相关的安全性问题也适用于 ECDSA. + +**提示:**现有文档表明 ED25519 更安全. 如果使用 RSA 密钥,则美国国家科学技术研究院[出版物 800-57 第 3 部分(PDF)](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf)建议密钥大小至少为 2048 位. + +因此,我们的文档集中在 ED25519 和 RSA 密钥的使用上. + +管理员可以[限制应允许的密钥及其最小长度](../security/ssh_keys_restrictions.html) . + +## Review existing SSH keys[](#review-existing-ssh-keys "Permalink") + +如果您已有 SSH 密钥,则可以使用它们来帮助保护与 GitLab 存储库的连接. 默认情况下,Linux 和 macOS 系统上的 SSH 密钥存储在用户的主目录中的`.ssh/`子目录中. 下表包括每种 SSH 密钥算法的默认文件名: + +| Algorithm | 公钥 | 私钥 | +| --- | --- | --- | +| ED25519(首选) | `id_ed25519.pub` | `id_ed25519` | +| RSA(至少 2048 位密钥大小) | `id_rsa.pub` | `id_rsa` | +| DSA(已弃用) | `id_dsa.pub` | `id_dsa` | +| ECDSA | `id_ecdsa.pub` | `id_ecdsa` | + +有关建议,请参阅[SSH 密钥的选项](#options-for-ssh-keys) . + +## Generating a new SSH key pair[](#generating-a-new-ssh-key-pair "Permalink") + +如果要创建: + +* ED25519 密钥,请阅读[ED25519 SSH 密钥](#ed25519-ssh-keys) . +* RSA 密钥,请阅读[RSA SSH 密钥](#rsa-ssh-keys) . + +### ED25519 SSH keys[](#ed25519-ssh-keys "Permalink") + +The book [Practical Cryptography With Go](https://leanpub.com/gocrypto/read#leanpub-auto-chapter-5-digital-signatures) suggests that [ED25519](https://ed25519.cr.yp.to/) keys are more secure and performant than RSA keys. + +随着 OpenSSH 6.5 在 2014 年引入 ED25519 SSH 密钥,它们应该在任何当前操作系统上都可用. + +您可以使用以下命令创建和配置 ED25519 密钥: + +``` +ssh-keygen -t ed25519 -C "" +``` + +`-C`标志(带引号的注释,例如电子邮件地址)是标记 SSH 密钥的可选方法. + +您将看到类似于以下内容的响应: + +``` +Generating public/private ed25519 key pair. +Enter file in which to save the key (/home/user/.ssh/id_ed25519): +``` + +要获得指导,请继续执行[常见步骤](#common-steps-for-generating-an-ssh-key-pair) . + +### RSA SSH keys[](#rsa-ssh-keys "Permalink") + +如果您将 RSA 密钥用于 SSH,则美国国家标准技术研究院建议您使用[至少 2048 位](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf)的密钥大小. 缺省情况下, `ssh-keygen`命令创建一个 1024 位 RSA 密钥. + +您可以使用以下命令创建和配置 RSA 密钥,如果需要,可以使用建议的最小密钥大小`2048`代替: + +``` +ssh-keygen -t rsa -b 2048 -C "email@example.com" +``` + +`-C`标志(带引号的注释,例如电子邮件地址)是标记 SSH 密钥的可选方法. + +您将看到类似于以下内容的响应: + +``` +Generating public/private rsa key pair. +Enter file in which to save the key (/home/user/.ssh/id_rsa): +``` + +要获得指导,请继续执行[常见步骤](#common-steps-for-generating-an-ssh-key-pair) . + +**注意:**如果您具有 7.8 或更低版本的 OpenSSH,请考虑与[编码](#rsa-keys-and-openssh-from-versions-65-to-78)相关的问题. + +### Common steps for generating an SSH key pair[](#common-steps-for-generating-an-ssh-key-pair "Permalink") + +无论是创建[ED25519](#ed25519-ssh-keys)还是创建[RSA](#rsa-ssh-keys)密钥,您都从`ssh-keygen`命令开始. 此时,您将在命令行中看到以下消息(用于 ED25519 键): + +``` +Generating public/private ed25519 key pair. +Enter file in which to save the key (/home/user/.ssh/id_rsa): +``` + +如果您还没有 SSH 密钥对并且没有生成[部署密钥](#deploy-keys) ,请接受建议的文件和目录. 您的 SSH 客户端将使用生成的 SSH 密钥对,而无需其他配置. + +或者,您可以将新的 SSH 密钥对保存在其他位置. 您可以分配您选择的目录和文件名. 您还可以将 SSH 密钥对专用于[特定主机](#working-with-non-default-ssh-key-pair-paths) . + +分配文件以保存 SSH 密钥后,您将有机会为 SSH 密钥设置[密码](https://www.ssh.com/ssh/passphrase/) : + +``` +Enter passphrase (empty for no passphrase): +Enter same passphrase again: +``` + +如果成功,您将看到有关`ssh-keygen`命令将标识和私钥保存在何处的确认. + +需要时,可以使用以下命令更新密码: + +``` +ssh-keygen -p -f /path/to/ssh_key +``` + +### RSA keys and OpenSSH from versions 6.5 to 7.8[](#rsa-keys-and-openssh-from-versions-65-to-78 "Permalink") + +在 OpenSSH 7.8 之前,RSA 密钥的默认公共密钥指纹基于 MD5,因此不安全. + +如果您的 OpenSSH 版本介于 6.5 至 7.8(含)之间,请使用`-o`选项运行`ssh-keygen` ,以更安全的 OpenSSH 格式保存您的私人 SSH 密钥. + +如果您已经具有可用于 GitLab 的 RSA SSH 密钥对,请考虑对其进行升级以使用更安全的密码加密格式. 您可以使用以下命令进行操作: + +``` +ssh-keygen -o -f ~/.ssh/id_rsa +``` + +或者,您可以使用以下命令以更安全的加密格式生成新的 RSA 密钥: + +``` +ssh-keygen -o -t rsa -b 4096 -C "email@example.com" +``` + +**注意:**如`ssh-keygen`手册页所述,ED25519 已将密钥加密为更安全的 OpenSSH 格式. + +## Adding an SSH key to your GitLab account[](#adding-an-ssh-key-to-your-gitlab-account "Permalink") + +现在,您可以将创建的 SSH 密钥复制到您的 GitLab 帐户. 这样做,请按照下列步骤操作: + +1. 将您的**公共** SSH 密钥复制到以文本格式保存信息的位置. 以下选项将 ED25519 键的信息保存到指定操作系统的剪贴板中: + + **macOS:** + + ``` + pbcopy < ~/.ssh/id_ed25519.pub + ``` + + **Linux(需要 xclip 软件包):** + + ``` + xclip -sel clip < ~/.ssh/id_ed25519.pub + ``` + + **Windows 上的 Git Bash:** + + ``` + cat ~/.ssh/id_ed25519.pub | clip + ``` + + 如果您使用的是 RSA 密钥,请相应地进行替换. + +2. 导航到`http://gitlab.com`并登录. +3. 选择右上角的头像,然后单击**设置** +4. Click **SSH 密钥**. +5. 将复制的公共密钥粘贴到" **密钥"**文本框中. +6. 确保您的密钥在" **标题"**文本框中包含描述性名称,例如" *工作笔记本电脑"*或" *家用工作站"* . +7. 在"过期时间"部分下包含密钥的(可选)过期日期. (在[GitLab 12.9 中](https://gitlab.com/gitlab-org/gitlab/-/issues/36243)引入.) +8. 单击**添加键**按钮. + +使用此过程"过期"的 SSH 密钥在 GitLab 工作流程中仍然有效. 由于 GitLab 配置的到期日期不包含在 SSH 密钥本身中,因此您仍然可以根据需要导出公共 SSH 密钥. + +**注意:**如果您手动复制了公共 SSH 密钥,请确保复制了整个密钥,以`ssh-ed25519` (或`ssh-rsa` )开头,并以您的电子邮件地址结尾. + +## Testing that everything is set up correctly[](#testing-that-everything-is-set-up-correctly "Permalink") + +要测试是否正确添加了 SSH 密钥,请在终端中运行以下命令(将`gitlab.com`替换为 GitLab 的实例域): + +``` +ssh -T git@gitlab.com +``` + +The first time you connect to GitLab via SSH, you will be asked to verify the authenticity of the GitLab host that you’re connecting to. For example, when connecting to GitLab.com, answer `yes` to add GitLab.com to the list of trusted hosts: + +``` +The authenticity of host 'gitlab.com (35.231.145.151)' can't be established. +ECDSA key fingerprint is SHA256:HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw. +Are you sure you want to continue connecting (yes/no)? yes +Warning: Permanently added 'gitlab.com' (ECDSA) to the list of known hosts. +``` + +**注意:**对于 GitLab.com,请查阅[SSH 主机密钥指纹](../user/gitlab_com/index.html#ssh-host-keys-fingerprints)一节,以确保您连接到正确的服务器. 例如,您会在链接的部分中看到上面显示的 ECDSA 密钥指纹. + +一旦添加到已知主机列表中,将不再要求您再次验证 GitLab 主机的真实性. 再次运行以上命令,您将只收到*欢迎使用 GitLab 的`@username` !* 信息. + +如果未出现欢迎消息,则可以通过使用以下命令在详细模式下运行`ssh`来解决问题: + +``` +ssh -Tvvv git@gitlab.com +``` + +## Working with non-default SSH key pair paths[](#working-with-non-default-ssh-key-pair-paths "Permalink") + +如果您为 GitLab SSH 密钥对使用了非默认文件路径,请配置 SSH 客户端以指向 GitLab 私有 SSH 密钥. + +要进行这些更改,请运行以下命令: + +``` +eval $(ssh-agent -s) +ssh-add +``` + +现在将这些设置保存到`~/.ssh/config`文件中. 这里显示了两个专用于 GitLab 的 SSH 密钥示例: + +``` +# GitLab.com Host gitlab.com + Preferredauthentications publickey + IdentityFile ~/.ssh/gitlab_com_rsa + +# Private GitLab instance Host gitlab.company.com + Preferredauthentications publickey + IdentityFile ~/.ssh/example_com_rsa +``` + +公用 SSH 密钥对于 GitLab 必须是唯一的,因为它们将绑定到您的帐户. SSH 密钥是通过 SSH 推送代码时唯一的标识符,这就是为什么它需要唯一地映射到单个用户的原因. + +## Per-repository SSH keys[](#per-repository-ssh-keys "Permalink") + +如果要根据正在使用的存储库使用不同的密钥,则可以在存储库中发出以下命令: + +``` +git config core.sshCommand "ssh -o IdentitiesOnly=yes -i ~/.ssh/private-key-filename-for-this-repository -F /dev/null" +``` + +这将不使用 SSH 代理,并且至少需要 Git 2.10. + +## Multiple accounts on a single GitLab instance[](#multiple-accounts-on-a-single-gitlab-instance "Permalink") + +[每个存储库](#per-repository-ssh-keys)方法还适用于在单个 GitLab 实例中使用多个帐户. + +或者,可以直接在`~.ssh/config`为主机分配别名. 如果在`.ssh/config`中的`Host`块之外设置了`IdentityFile` ,则 SSH 和作为扩展的 Git 将无法登录. 这是由于 SSH 组装`IdentityFile`条目的方式,因此不能通过将`IdentitiesOnly`设置为`yes`来更改. `IdentityFile`条目应指向 SSH 密钥对的私钥. + +**注意:**私钥和公用密钥应仅由用户读取. 通过运行以下`chmod 0400 ~/.ssh/`在 Linux 和 macOS 上完成此操作: `chmod 0400 ~/.ssh/`和`chmod 0400 ~/.ssh/` . + +``` +# User1 Account Identity Host + Hostname gitlab.com + PreferredAuthentications publickey + IdentityFile ~/.ssh/ + +# User2 Account Identity Host + Hostname gitlab.com + PreferredAuthentications publickey + IdentityFile ~/.ssh/ +``` + +**注意:**为提高效率和透明度,示例`Host`别名定义为`user_1.gitlab.com`和`user_2.gitlab.com` . 高级配置更难以维护. 使用这种别名使使用其他工具(如`git remote`子命令)时更容易理解. SSH 可以将任何字符串理解为`Host`别名,因此`Tanuki1`和`Tanuki2`尽管提供了很少的上下文指向它们,也可以使用. + +克隆`gitlab`存储库通常如下所示: + +``` +git clone git@gitlab.com:gitlab-org/gitlab.git +``` + +要为`user_1`克隆它,请将`gitlab.com`替换为 SSH 别名`user_1.gitlab.com` : + +``` +git clone git@:gitlab-org/gitlab.git +``` + +使用`git remote`命令修复以前克隆的存储库. + +下面的示例假定远程存储库被别名为`origin` . + +``` +git remote set-url origin git@:gitlab-org/gitlab.git +``` + +## Deploy keys[](#deploy-keys "Permalink") + +阅读[有关部署密钥](../user/project/deploy_keys/index.html)的[文档](../user/project/deploy_keys/index.html) . + +## Applications[](#applications "Permalink") + +### Eclipse[](#eclipse "Permalink") + +如果使用的是[EGit](https://www.eclipse.org/egit/) ,则可以[将 SSH 密钥添加到 Eclipse](https://wiki.eclipse.org/EGit/User_Guide#Eclipse_SSH_Configuration) . + +## SSH on the GitLab server[](#ssh-on-the-gitlab-server "Permalink") + +GitLab 与系统安装的 SSH 守护程序集成,指定一个用户(通常名为`git` )来处理所有访问请求. 通过 SSH 连接到 GitLab 服务器的用户由其 SSH 密钥而不是其用户名标识. + +在 GitLab 服务器上执行的 SSH *客户端*操作将以该用户身份执行. 尽管可以修改此用户的 SSH 配置,例如提供专用 SSH 密钥来验证这些请求,但是这种做法**不受支持** ,并且强烈建议这样做,因为这样做会带来重大的安全风险. + +GitLab 检查过程包括对这种情况的检查,如果您的服务器配置如下,它将引导您进入本节,例如: + +``` +$ gitlab-rake gitlab:check + +Git user has default SSH configuration? ... no + Try fixing it: + mkdir ~/gitlab-check-backup-1504540051 + sudo mv /var/lib/git/.ssh/id_rsa ~/gitlab-check-backup-1504540051 + sudo mv /var/lib/git/.ssh/id_rsa.pub ~/gitlab-check-backup-1504540051 + For more information see: + doc/ssh/README.md in section "SSH on the GitLab server" + Please fix the error above and rerun the checks. +``` + +尽快删除自定义配置. 这些自定义项*明确不受支持,*并且可能随时停止工作. + +### Options for Microsoft Windows[](#options-for-microsoft-windows "Permalink") + +如果您运行的是 Windows 10, [适用于 Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10)的[Windows 子系统(WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10)及其最新的[WSL 2](https://docs.microsoft.com/en-us/windows/wsl/install-win10#update-to-wsl-2)版本,则支持安装不同的 Linux 发行版,其中包括 Git 和 SSH 客户端. + +对于当前版本的 Windows,您还可以通过[Git for Windows](https://gitforwindows.org)安装 Git 和 SSH 客户端. + +替代工具包括: + +* [Cygwin](https://www.cygwin.com) +* [PuttyGen](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) + +## Troubleshooting[](#troubleshooting "Permalink") + +如果在 Git 克隆上,系统会提示您输入密码,例如`git@gitlab.com's password:` SSH 设置有问题. + +* 确保您正确生成了 SSH 密钥对,并将公共 SSH 密钥添加到了 GitLab 配置文件 +* 尝试使用`ssh-agent`手动注册您的私有 SSH 密钥,如本文档前面所述 +* 尝试通过运行`ssh -Tv git@example.com`调试连接(将 GitLab 域替换为`example.com` ) \ No newline at end of file diff --git a/docs/403.md b/docs/403.md new file mode 100644 index 0000000000000000000000000000000000000000..5fa604d27549b679c78b4a628b000efd2dc8725f --- /dev/null +++ b/docs/403.md @@ -0,0 +1,104 @@ +# GitLab integrations + +> 原文:[https://docs.gitlab.com/ee/integration/README.html](https://docs.gitlab.com/ee/integration/README.html) + +* [Issue trackers](#issue-trackers) +* [Authentication sources](#authentication-sources) +* [Security enhancements](#security-enhancements) +* [Continuous integration](#continuous-integration) +* [Feature enhancements](#feature-enhancements) +* [Integrations](#integrations) +* [Troubleshooting](#troubleshooting) + * [SSL certificate errors](#ssl-certificate-errors) + +# GitLab integrations[](#gitlab-integrations "Permalink") + +GitLab can be integrated with external services for enhanced functionality. + +## Issue trackers[](#issue-trackers "Permalink") + +您可以与 GitLab 问题跟踪器同时使用[外部问题跟踪](external-issue-tracker.html)器,也可以仅使用外部问题跟踪器. + +GitLab 可以与以下外部问题跟踪器集成: + +* Jira +* Redmine +* Bugzilla +* YouTrack + +## Authentication sources[](#authentication-sources "Permalink") + +可以将 GitLab 配置为使用以下身份验证源对访问请求进行身份验证: + +* 启用[Auth0 OmniAuth](auth0.html)提供程序. +* 启用使用[Bitbucket](bitbucket.html)帐户登录. +* 配置 GitLab 以使用[CAS 登录](cas.html) . +* 与[Kerberos](kerberos.html)集成. +* 启用通过[LDAP](ldap.html)登录. +* 启用[OAuth2 提供](oauth_provider.html)程序应用程序创建. +* 使用[OmniAuth](omniauth.html)可以通过 Twitter,GitHub,GitLab.com,Google,Bitbucket,Facebook,Shibboleth,SAML,Crowd,Azure 或 Authentiq ID 启用登录. +* 使用 GitLab 作为[OpenID Connect](openid_connect_provider.html)身份提供者. +* 通过 GitLab OpenID Connect 对[保险柜](vault.html)进行身份验证. +* 将 GitLab 配置为[SAML](saml.html) 2.0 服务提供商. + +## Security enhancements[](#security-enhancements "Permalink") + +GitLab 可以与以下外部服务集成以增强安全性: + +* [Akismet](akismet.html)有助于减少垃圾邮件. +* Google [reCAPTCHA](recaptcha.html)有助于验证新用户. + +manbetx 客户端打不开还提供功能来提高您自己的应用程序的安全性. 有关更多详细信息,请参见[GitLab Secure](../user/application_security/index.html) . + +## Continuous integration[](#continuous-integration "Permalink") + +GitLab 可以与以下外部服务集成以实现持续集成: + +* [Jenkins](jenkins.html) CI. + +## Feature enhancements[](#feature-enhancements "Permalink") + +GitLab 可以集成以下增强功能: + +* 将 GitLab 操作添加到[Gmail 操作按钮](gmail_action_buttons_for_gitlab.html) . +* 配置[PlantUML](../administration/integration/plantuml.html)以使用 AsciiDoc 文档中的图. +* 将合并请求附加到[Trello](trello_power_up.html)卡. +* 启用由[Sourcegraph](sourcegraph.html)支持的集成代码智能. +* 添加[Elasticsearch](elasticsearch.html)进行[Advanced Global Search](../user/search/advanced_global_search.html) , [Advanced System Search](../user/search/advanced_search_syntax.html)和更快的搜索. + +## Integrations[](#integrations "Permalink") + +可以与 Campfire,Flowdock,HipChat,Pivotal Tracker 和 Slack 等服务[集成](../user/project/integrations/overview.html) . + +## Troubleshooting[](#troubleshooting "Permalink") + +### SSL certificate errors[](#ssl-certificate-errors "Permalink") + +当尝试将 GitLab 与使用自签名证书的服务集成时,很可能在应用程序的不同部分(最可能是 Sidekiq)会发生 SSL 证书错误. + +您可以采用两种方法来解决此问题: + +1. 将根证书添加到操作系统的受信任链. +2. 如果使用 Omnibus,则可以将证书添加到 GitLab 的可信证书中. + +**操作系统主要信任链** + +此[资源](https://manuals.gfi.com/en/kerio/connect/content/server-configuration/ssl-certificates/adding-trusted-root-certificates-to-the-server-1605.html)包含将证书添加到主信任链所需的所有信息. + +超级用户的此[答案](https://superuser.com/questions/437330/how-do-you-add-a-certificate-authority-ca-to-ubuntu)也具有相关信息. + +**所有可信任链** + +[将自签名证书或自定义证书颁发机构安装](https://docs.gitlab.com/omnibus/common_installation_problems/README.html)到 Omnibus GitLab. + +将证书连接到主要的受信任证书就足够了,但是在升级过程中它可能会被覆盖: + +``` +cat jira.pem >> /opt/gitlab/embedded/ssl/certs/cacert.pem +``` + +之后,使用以下命令重新启动 GitLab: + +``` +sudo gitlab-ctl restart +``` \ No newline at end of file diff --git a/docs/404.md b/docs/404.md new file mode 100644 index 0000000000000000000000000000000000000000..e10d3d3dcec26d3fec6d83acae199f4d7b9851bc --- /dev/null +++ b/docs/404.md @@ -0,0 +1,103 @@ +# Git + +> 原文:[https://docs.gitlab.com/ee/topics/git/](https://docs.gitlab.com/ee/topics/git/) + +* [Getting started](#getting-started) + * [Concepts](#concepts) +* [Git tips](#git-tips) +* [Troubleshooting Git](#troubleshooting-git) +* [Branching strategies](#branching-strategies) +* [Advanced use](#advanced-use) +* [API](#api) +* [Git Large File Storage (LFS)](#git-large-file-storage-lfs) + +# Git[](#git "Permalink") + +Git 是一个[免费的开源](https://git-scm.com/about/free-and-open-source)分布式版本控制系统,旨在快速高效地处理从小型项目到大型项目的所有内容. + +[GitLab](https://about.gitlab.com)是用于软件开发的基于 Git 的完全集成平台. 除了 Git 的功能外,GitLab 还具有许多强大的[功能](https://about.gitlab.com/features/)来增强您的[工作流程](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/) . + +我们已经收集了一些资源,可帮助您通过 GitLab 从 Git 中获得最大收益. + +还可以在[Git 网站](https://git-scm.com)上获得更多信息. + +## Getting started[](#getting-started "Permalink") + +以下资源将帮助您开始使用 Git: + +* [Git-ing 从 Git](https://www.youtube.com/watch?v=Ce5nz5n41z4)的视频介绍开始. +* [Git Basics](https://git-scm.com/book/en/v2/Getting-Started-Git-Basics) +* [Git on the Server - GitLab](https://git-scm.com/book/en/v2/Git-on-the-Server-GitLab) +* [How to install Git](how_to_install_git/index.html) +* [Git terminology](../../gitlab-basics/start-using-git.html#git-terminology) +* [Start using Git on the command line](../../gitlab-basics/start-using-git.html) +* [Edit files through the command line](../../gitlab-basics/command-line-commands.html) +* [GitLab Git Cheat Sheet (download)](https://about.gitlab.com/images/press/git-cheat-sheet.pdf) +* Commits: + * [Revert a commit](../../user/project/merge_requests/revert_changes.html#reverting-a-commit) + * [Cherry-picking a commit](../../user/project/merge_requests/cherry_pick_changes.html#cherry-picking-a-commit) + * [Squashing commits](../gitlab_flow.html#squashing-commits-with-rebase) + * [Squash-and-merge](../../user/project/merge_requests/squash_and_merge.html) + * [Signing commits](../../user/project/repository/gpg_signed_commits/index.html) +* [Git stash](../../university/training/topics/stash.html) +* [Git file blame](../../user/project/repository/git_blame.html) +* [Git file history](../../user/project/repository/git_history.html) +* [Git tags](../../university/training/user_training.html#tags) + +### Concepts[](#concepts "Permalink") + +以下是有关版本控制概念的资源: + +* [Git concepts](../../university/training/user_training.html#git-concepts) +* [Why Git is Worth the Learning Curve](https://about.gitlab.com/blog/2017/05/17/learning-curve-is-the-biggest-challenge-developers-face-with-git/) +* [The future of SaaS hosted Git repository pricing](https://about.gitlab.com/blog/2016/05/11/git-repository-pricing/) +* [Git website on version control](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control) +* [GitLab University presentation about Version Control](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit?usp=sharing) + +## Git tips[](#git-tips "Permalink") + +以下资源可以帮助您提高使用 Git 的效率: + +* GitLab 支持团队收集的[有用的 Git 命令](useful_git_commands.html) . +* [Git Tips & Tricks](https://about.gitlab.com/blog/2016/12/08/git-tips-and-tricks/) +* [Eight Tips to help you work better with Git](https://about.gitlab.com/blog/2015/02/19/8-tips-to-help-you-work-better-with-git/) + +## Troubleshooting Git[](#troubleshooting-git "Permalink") + +如果您在使用 Git 时遇到问题,以下方法可能会有所帮助: + +* [Numerous *undo* possibilities in Git](numerous_undo_possibilities_in_git/index.html) +* 了解一些[Git 故障排除](troubleshooting_git.html)技术 + +## Branching strategies[](#branching-strategies "Permalink") + +* [Feature branch workflow](../../gitlab-basics/feature_branch_workflow.html) +* [Develop on a feature branch](feature_branch_development.html) +* [GitLab Flow](../gitlab_flow.html) +* [Git Branching - Branches in a Nutshell](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell) +* [Git Branching - Branching Workflows](https://git-scm.com/book/en/v2/Git-Branching-Branching-Workflows) + +## Advanced use[](#advanced-use "Permalink") + +以下是针对那些想充分利用 Git 的人的高级主题: + +* [Server Hooks](../../administration/server_hooks.html) +* [Git Attributes](../../user/project/git_attributes.html) +* Git 子模块: [将 Git 子模块与 GitLab CI 一起使用](../../ci/git_submodules.html#using-git-submodules-with-gitlab-ci) +* [Partial Clone](partial_clone.html) + +## API[](#api "Permalink") + +[Gitignore 模板](../../api/templates/gitignores.html) API 允许来自 GitLab 的与 Git 相关的查询. + +## Git Large File Storage (LFS)[](#git-large-file-storage-lfs "Permalink") + +以下与 Git 大文件存储有关: + +* [Getting Started with Git LFS](https://about.gitlab.com/blog/2017/01/30/getting-started-with-git-lfs-tutorial/) +* [Migrate an existing Git repository with Git LFS](lfs/migrate_to_git_lfs.html) +* [Removing objects from LFS](lfs/index.html#removing-objects-from-lfs) +* [GitLab Git LFS user documentation](lfs/index.html) +* [GitLab Git LFS admin documentation](../../administration/lfs/index.html) +* [Git Annex to Git LFS migration guide](lfs/migrate_from_git_annex_to_git_lfs.html) +* [Towards a production quality open source Git LFS server](https://about.gitlab.com/blog/2015/08/13/towards-a-production-quality-open-source-git-lfs-server/) \ No newline at end of file diff --git a/docs/405.md b/docs/405.md new file mode 100644 index 0000000000000000000000000000000000000000..71a8d67b702484beab949c2c6233dd1aedcab18a --- /dev/null +++ b/docs/405.md @@ -0,0 +1,576 @@ +# GitLab.com settings + +> 原文:[https://docs.gitlab.com/ee/user/gitlab_com/](https://docs.gitlab.com/ee/user/gitlab_com/) + +* [SSH host keys fingerprints](#ssh-host-keys-fingerprints) +* [SSH `known_hosts` entries](#ssh-known_hosts-entries) +* [Mail configuration](#mail-configuration) +* [Backups](#backups) +* [Alternative SSH port](#alternative-ssh-port) +* [GitLab Pages](#gitlab-pages) +* [GitLab CI/CD](#gitlab-cicd) +* [Repository size limit](#repository-size-limit) +* [IP range](#ip-range) +* [Maximum number of webhooks](#maximum-number-of-webhooks) +* [Shared Runners](#shared-runners) + * [Linux Shared Runners](#linux-shared-runners) + * [Pre-clone script](#pre-clone-script) + * [`config.toml`](#configtoml) + * [Windows Shared Runners (beta)](#windows-shared-runners-beta) + * [Configuration](#configuration) + * [Example](#example) + * [Limitations and known issues](#limitations-and-known-issues) +* [Sidekiq](#sidekiq) +* [PostgreSQL](#postgresql) +* [Unicorn](#unicorn) +* [GitLab.com-specific rate limits](#gitlabcom-specific-rate-limits) + * [HAProxy API throttle](#haproxy-api-throttle) + * [Rack Attack initializer](#rack-attack-initializer) + * [Protected paths throttle](#protected-paths-throttle) + * [Git and container registry failed authentication ban](#git-and-container-registry-failed-authentication-ban) + * [Admin Area settings](#admin-area-settings) + * [Visibility settings](#visibility-settings) + * [SSH maximum number of connections](#ssh-maximum-number-of-connections) + * [Import/export](#importexport) +* [GitLab.com Logging](#gitlabcom-logging) +* [GitLab.com at scale](#gitlabcom-at-scale) + * [Elastic Cluster](#elastic-cluster) + * [Fluentd](#fluentd) + * [Prometheus](#prometheus) + * [Grafana](#grafana) + * [Sentry](#sentry) + * [Consul](#consul) + * [HAProxy](#haproxy) + +# GitLab.com settings[](#gitlabcom-settings "Permalink") + +在此页面中,您将找到有关[GitLab.com](https://about.gitlab.com/pricing/)上使用的设置的信息. + +## SSH host keys fingerprints[](#ssh-host-keys-fingerprints "Permalink") + +以下是 GitLab.com 的 SSH 主机密钥的指纹. 首次连接到 GitLab.com 存储库时,您将在输出中看到这些键之一. + +| Algorithm | MD5(已弃用) | SHA256 | +| --- | --- | --- | +| DSA(已弃用) | `7a:47:81:3a:ee:89:89:64:33:ca:44:52:3d:30:d4:87` | `p8vZBUOR0XQz6sYiaWSMLmh0t9i8srqYKool/Xfdfqw` | +| ECDSA | `f1:d0:fb:46:73:7a:70:92:5a:ab:5d:ef:43:e2:1c:35` | `HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw` | +| ED25519 | `2e:65:6a:c8:cf:bf:b2:8b:9a:bd:6d:9f:11:5c:12:16` | `eUXGGm1YGsMAS7vkcx6JOJdOGHPem5gQp4taiCfCLB8` | +| RSA | `b6:03:0e:39:97:9e:d0:e7:24:ce:a3:77:3e:01:42:09` | `ROQFvPThGrW4RuWLoL9tq9I9zJ42fK4XywyRtbOz/EQ` | + +## SSH `known_hosts` entries[](#ssh-known_hosts-entries "Permalink") + +将以下内容添加到`.ssh/known_hosts`以跳过 SSH 中的手动指纹确认: + +``` +gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf +gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9 +gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY= +``` + +## Mail configuration[](#mail-configuration "Permalink") + +GitLab.com 通过[Mailgun](https://www.mailgun.com/)从`mg.gitlab.com`域发送电子邮件,并拥有自己的专用 IP 地址( `192.237.158.143` ). + +**注意:** `mg.gitlab.com`的 IP 地址可能随时更改. + +## Backups[](#backups "Permalink") + +[See our backup strategy](https://about.gitlab.com/handbook/engineering/infrastructure/production/#backups). + +## Alternative SSH port[](#alternative-ssh-port "Permalink") + +可以通过`git+ssh`的[其他 SSH 端口](https://about.gitlab.com/blog/2016/02/18/gitlab-dot-com-now-supports-an-alternate-git-plus-ssh-port/)访问 GitLab.com. + +| Setting | Value | +| --- | --- | +| `Hostname` | `altssh.gitlab.com` | +| `Port` | `443` | + +以下是`~/.ssh/config`的示例: + +``` +Host gitlab.com + Hostname altssh.gitlab.com + User git + Port 443 + PreferredAuthentications publickey + IdentityFile ~/.ssh/gitlab +``` + +## GitLab Pages[](#gitlab-pages "Permalink") + +以下是[GitLab 页面](https://about.gitlab.com/stages-devops-lifecycle/pages/)的设置. + +| Setting | GitLab.com | Default | +| --- | --- | --- | +| 域名 | `gitlab.io` | - | +| IP 地址 | `35.185.44.232` | - | +| 自定义域支持 | yes | no | +| TLS 证书支持 | yes | no | +| 最大大小(未压缩) | 1G | 100M | + +**注意:** Pages 站点的最大大小由[GitLab CI / CD 中](#gitlab-cicd)的工件最大大小决定. + +## GitLab CI/CD[](#gitlab-cicd "Permalink") + +以下是有关[GitLab CI / CD](../../ci/README.html)的当前设置. + +| Setting | GitLab.com | Default | +| --- | --- | --- | +| 工件最大尺寸(未压缩) | 1G | 100M | +| Artifacts [expiry time](../../ci/yaml/README.html#artifactsexpire_in) | 从 2020 年 6 月 22 日开始,除非另有说明,否则在 30 天后删除(该日期之前创建的工件没有过期). | 除非另有说明,否则 30 天后删除 | +| 预定管道计划 | `*/5 * * * *` | `19 * * * *` | +| [Max jobs in active pipelines](../../administration/instance_limits.html#number-of-jobs-in-active-pipelines) | 免费套餐为`500` ,否则为无限制 | Unlimited | +| [Max pipeline schedules in projects](../../administration/instance_limits.html#number-of-pipeline-schedules) | 免费套餐`10` `50` ,所有付费套餐`50` | Unlimited | +| [Max number of instance level variables](../../administration/instance_limits.html#number-of-instance-level-variables) | `25` | `25` | +| [Scheduled Job Archival](../../user/admin_area/settings/continuous_integration.html#archive-jobs-core-only) | 3 个月 | Never | + +## Repository size limit[](#repository-size-limit "Permalink") + +GitLab.com 已启用以下[帐户限制](../admin_area/settings/account_and_limit_settings.html) . 如果未列出设置,则将其设置为默认值. + +如果您接近或超过存储库大小限制,则可以[使用 Git 减小存储库大小](../project/repository/reducing_the_repo_size_using_git.html) . + +| Setting | GitLab.com | Default | +| --- | --- | --- | +| 资料库大小,包括 LFS | 10 GB | Unlimited | + +**注意:**每个请求通过 Cloudflare 的`git push`和 GitLab 项目导入限制为 5 GB. Git LFS 和文件上传以外的导入不受此限制的影响. + +## IP range[](#ip-range "Permalink") + +GitLab.com 将 IP 范围`34.74.90.64/28`用于其 Web / API `34.74.90.64/28`的流量. 这整个范围仅分配给 GitLab. 您可以期望来自 Webhooks 或存储库镜像的连接来自这些 IP 并允许它们. + +GitLab.com 由 Cloudflare 领导. 对于与 GitLab.com 的传入连接,您可能需要允许 Cloudflare 的 CIDR 块( [IPv4](https://www.cloudflare.com/ips-v4)和[IPv6](https://www.cloudflare.com/ips-v6) ). + +对于 CI / CD 运行程序的传出连接,我们不提供静态 IP 地址. 我们所有的运行程序都已部署到 Google Cloud Platform(GCP)中-通过查找[GCP 的](https://cloud.google.com/compute/docs/faq#where_can_i_find_product_name_short_ip_ranges)所有[IP 地址范围或 CIDR 块,](https://cloud.google.com/compute/docs/faq#where_can_i_find_product_name_short_ip_ranges)可以配置任何基于 IP 的防火墙. + +## Maximum number of webhooks[](#maximum-number-of-webhooks "Permalink") + +限制: + +* 100 个 webhooks 适用于项目. +* 50 个 webhooks 适用于组. + +## Shared Runners[](#shared-runners "Permalink") + +GitLab 提供在 GitLab.com 上托管的 Linux 和 Windows 共享运行程序,用于执行管道. + +**注意:** GitLab 提供的共享运行器**不可**配置. 如果您有特定的配置需求,请考虑[安装自己的 Runner](https://docs.gitlab.com/runner/install/) . + +### Linux Shared Runners[](#linux-shared-runners "Permalink") + +Linux Shared Runners on GitLab.com run in [autoscale mode](https://docs.gitlab.com/runner/configuration/autoscale.html) and are powered by Google Cloud Platform. Autoscaling means reduced waiting times to spin up CI/CD jobs, and isolated VMs for each project, thus maximizing security. They’re free to use for public open source projects and limited to 2000 CI minutes per month per group for private projects. More minutes [can be purchased](../../subscriptions/index.html#purchasing-additional-ci-minutes), if needed. Read about all [GitLab.com plans](https://about.gitlab.com/pricing/). + +您的所有 CI / CD 作业都在具有 3.75GB RAM,CoreOS 和最新 Docker Engine 的[n1-standard-1 实例](https://cloud.google.com/compute/docs/machine-types)上运行. 实例提供 1 个 vCPU 和 25GB 的 HDD 磁盘空间. VM 的默认区域是 US East1\. 每个实例仅用于一项作业,这确保了其他人无法访问其 CI 作业访问系统上剩余的任何敏感数据. + +`gitlab-shared-runners-manager-X.gitlab.com`专用于 GitLab 项目以及它们的社区分支. 它们使用稍大的计算机类型(n1-standard-2),并且具有更大的 SSD 磁盘大小. 它们将不会运行未加标签的作业,并且与共享赛跑者的一般团队不同,这些实例最多可重复使用 40 次. + +由 GitLab.com( `shared-runners-manager-X.gitlab.com` )上的共享 Runner 处理的作业**将在 3 小时后**超时,无论项目中配置的超时时间如何. 检查问题[4010](https://gitlab.com/gitlab-com/infrastructure/-/issues/4010)和[4070,](https://gitlab.com/gitlab-com/infrastructure/-/issues/4070)以供参考. + +以下是共享的"跑步者"设置. + +| Setting | GitLab.com | Default | +| --- | --- | --- | +| [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) | [Runner versions dashboard](https://dashboards.gitlab.com/d/000000159/ci?from=now-1h&to=now&refresh=5m&orgId=1&panelId=12&fullscreen&theme=light) | - | +| Executor | `docker+machine` | - | +| 默认 Docker 映像 | `ruby:2.5` | - | +| `privileged` (run [Docker in Docker](https://hub.docker.com/_/docker/)) | `true` | `false` | + +#### Pre-clone script[](#pre-clone-script "Permalink") + +在 Runner 尝试运行`git init`和`git fetch`下载 GitLab 存储库之前,GitLab.com 上的 Linux Shared Runner 提供了一种在 CI 作业中运行命令的方法. [`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)可用于: + +* 用存储库数据播种构建目录 +* 向服务器发送请求 +* 从 CDN 下载资产 +* `git init`之前必须运行的任何其他命令 + +要使用此功能,请定义一个包含 bash 脚本的[CI / CD 变量](../../ci/variables/README.html#create-a-custom-variable-in-the-ui) `CI_PRE_CLONE_SCRIPT` . + +[本示例](../../development/pipelines.html#pre-clone-step)演示了如何使用预克隆步骤为构建目录添加种子. + +#### `config.toml`[](#configtoml "Permalink") + +我们的`config.toml`的完整内容是: + +**注意:**非公开的设置显示为`X` + +**Google Cloud Platform** + +``` +concurrent = X +check_interval = 1 +metrics_server = "X" +sentry_dsn = "X" + +[[runners]] + name = "docker-auto-scale" + request_concurrency = X + url = "https://gitlab.com/" + token = "SHARED_RUNNER_TOKEN" + pre_clone_script = "eval \"$CI_PRE_CLONE_SCRIPT\"" + executor = "docker+machine" + environment = [ + "DOCKER_DRIVER=overlay2", + "DOCKER_TLS_CERTDIR=" + ] + limit = X + [runners.docker] + image = "ruby:2.5" + privileged = true + volumes = [ + "/certs/client", + "/dummy-sys-class-dmi-id:/sys/class/dmi/id:ro" # Make kaniko builds work on GCP. + ] + [runners.machine] + IdleCount = 50 + IdleTime = 3600 + OffPeakPeriods = ["* * * * * sat,sun *"] + OffPeakTimezone = "UTC" + OffPeakIdleCount = 15 + OffPeakIdleTime = 3600 + MaxBuilds = 1 # For security reasons we delete the VM after job has finished so it's not reused. + MachineName = "srm-%s" + MachineDriver = "google" + MachineOptions = [ + "google-project=PROJECT", + "google-disk-size=25", + "google-machine-type=n1-standard-1", + "google-username=core", + "google-tags=gitlab-com,srm", + "google-use-internal-ip", + "google-zone=us-east1-d", + "engine-opt=mtu=1460", # Set MTU for container interface, for more information check https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3214#note_82892928 + "google-machine-image=PROJECT/global/images/IMAGE", + "engine-opt=ipv6", # This will create IPv6 interfaces in the containers. + "engine-opt=fixed-cidr-v6=fc00::/7", + "google-operation-backoff-initial-interval=2" # Custom flag from forked docker-machine, for more information check https://github.com/docker/machine/pull/4600 + ] + [runners.cache] + Type = "gcs" + Shared = true + [runners.cache.gcs] + CredentialsFile = "/path/to/file" + BucketName = "bucket-name" +``` + +### Windows Shared Runners (beta)[](#windows-shared-runners-beta "Permalink") + +Windows Shared Runners 当前处于[beta 中](https://about.gitlab.com/handbook/product/#beta) ,不应用于生产工作负载. + +在测试版期间, [共享运行程序管道配额](../admin_area/settings/continuous_integration.html#shared-runners-pipeline-minutes-quota-starter-only)将以与 Linux Runners 相同的方式应用于组和项目. 如本[相关问题所述](https://gitlab.com/gitlab-org/gitlab/-/issues/30834) ,当 beta 时期结束时,这可能会改变. + +通过在 Google Cloud Platform 上启动虚拟机,GitLab.com 上的 Windows Shared Runners 可以自动自动缩放. 此解决方案使用 GitLab 为[自定义执行](https://docs.gitlab.com/runner/executors/custom.html) [程序](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md)开发的新[自动缩放驱动程序](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md) . Windows 共享运行程序在具有 2 个 vCPU 和 7.5GB RAM 的`n1-standard-2`实例上执行 CI / CD 作业. 您可以在[软件包文档中](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/master/cookbooks/preinstalled-software/README.md)找到可用的 Windows 软件包的完整列表. + +我们希望不断进行迭代,以使 Windows Shared Runners 处于稳定状态并[普遍可用](https://about.gitlab.com/handbook/product/#generally-available-ga) . 您可以在[相关的史诗中](https://gitlab.com/groups/gitlab-org/-/epics/2162)按照我们的工作朝着这个目标迈进. + +#### Configuration[](#configuration "Permalink") + +The full contents of our `config.toml` are: + +**注意:**非公开的设置显示为`X` + +``` +concurrent = X +check_interval = 3 + +[[runners]] + name = "windows-runner" + url = "https://gitlab.com/" + token = "TOKEN" + executor = "custom" + builds_dir = "C:\\GitLab-Runner\\builds" + cache_dir = "C:\\GitLab-Runner\\cache" + shell = "powershell" + [runners.custom] + config_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe" + config_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "config"] + prepare_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe" + prepare_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "prepare"] + run_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe" + run_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "run"] + cleanup_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe" + cleanup_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "cleanup"] +``` + +我们的`autoscaler/config.toml`的完整内容是: + +``` +Provider = "gcp" +Executor = "winrm" +OS = "windows" +LogLevel = "info" +LogFormat = "text" +LogFile = "C:\\GitLab-Runner\\autoscaler\\autoscaler.log" +VMTag = "windows" + +[GCP] + ServiceAccountFile = "PATH" + Project = "some-project-df9323" + Zone = "us-east1-c" + MachineType = "n1-standard-2" + Image = "IMAGE" + DiskSize = 50 + DiskType = "pd-standard" + Subnetwork = "default" + Network = "default" + Tags = ["TAGS"] + Username = "gitlab_runner" + +[WinRM] + MaximumTimeout = 3600 + ExecutionMaxRetries = 0 + +[ProviderCache] + Enabled = true + Directory = "C:\\GitLab-Runner\\autoscaler\\machines" +``` + +#### Example[](#example "Permalink") + +下面是一个简单的`.gitlab-ci.yml`文件,以显示如何开始使用 Windows Shared Runners: + +``` +.shared_windows_runners: + tags: + - shared-windows + - windows + - windows-1809 + +stages: + - build + - test + +before_script: + - Set-Variable -Name "time" -Value (date -Format "%H:%m") + - echo ${time} + - echo "started by ${GITLAB_USER_NAME}" + +build: + extends: + - .shared_windows_runners + stage: build + script: + - echo "running scripts in the build job" + +test: + extends: + - .shared_windows_runners + stage: test + script: + - echo "running scripts in the test job" +``` + +#### Limitations and known issues[](#limitations-and-known-issues "Permalink") + +* [Beta 定义中](https://about.gitlab.com/handbook/product/#beta)提到的所有限制. +* 新 Windows VM 的平均配置时间为 5 分钟. 这意味着在测试期间,您可能会注意到 Windows Shared Runner 机群上的构建开始时间变慢. 在将来的版本中,我们将更新自动缩放器以启用虚拟机的预配置. 这将大大减少在 Windows 机群上配置 VM 所花费的时间. 您可以按照[相关问题进行操作](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/-/issues/32) . +* Windows Shared Runner 舰队可能偶尔不可用进行维护或更新. +* Windows Shared Runner 虚拟机实例不使用 GitLab Docker 执行器. 这意味着您将无法在管道配置中指定[`image`](../../ci/yaml/README.html#image)或[`services`](../../ci/yaml/README.html#services) . +* 对于 Beta 版本,我们在基本 VM 映像中包含了一组软件包. 如果您的 CI 作业需要此列表中未包含的其他软件,那么您将需要在[`before_script`](../../ci/yaml/README.html#before_script-and-after_script)或[`script`](../../ci/yaml/README.html#script)添加安装命令以安装所需的软件. 请注意,每个作业都在新的 VM 实例上运行,因此需要为管道中的每个作业重复安装其他软件包. +* 作业在等待状态中的停留时间可能比 Linux 共享运行器更长. +* 我们有可能引入重大更改,这将需要更新使用 Windows Shared Runner 组件的管道. + +## Sidekiq[](#sidekiq "Permalink") + +GitLab.com 使用参数`--timeout=4 --concurrency=4`和以下环境变量运行[Sidekiq](https://sidekiq.org) : + +| Setting | GitLab.com | Default | +| --- | --- | --- | +| `SIDEKIQ_DAEMON_MEMORY_KILLER` | - | - | +| `SIDEKIQ_MEMORY_KILLER_MAX_RSS` | `2000000` | `2000000` | +| `SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS` | - | - | +| `SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL` | - | `3` | +| `SIDEKIQ_MEMORY_KILLER_GRACE_TIME` | - | `900` | +| `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT` | - | `30` | +| `SIDEKIQ_LOG_ARGUMENTS` | `1` | - | + +**注意:**在 Sidekiq 导入节点和 Sidekiq 导出节点上, `SIDEKIQ_MEMORY_KILLER_MAX_RSS`设置为`16000000` . + +## PostgreSQL[](#postgresql "Permalink") + +GitLab.com being a fairly large installation of GitLab means we have changed various PostgreSQL settings to better suit our needs. For example, we use streaming replication and servers in hot-standby mode to balance queries across different database servers. + +GitLab.com 特定设置(及其默认设置)的列表如下: + +| Setting | GitLab.com | Default | +| --- | --- | --- | +| `archive_command` | `/usr/bin/envdir /etc/wal-e.d/env /opt/wal-e/bin/wal-e wal-push %p` | empty | +| `archive_mode` | on | off | +| `autovacuum_analyze_scale_factor` | 0.01 | 0.01 | +| `autovacuum_max_workers` | 6 | 3 | +| `autovacuum_vacuum_cost_limit` | 1000 | -1 | +| `autovacuum_vacuum_scale_factor` | 0.01 | 0.02 | +| `checkpoint_completion_target` | 0.7 | 0.9 | +| `checkpoint_segments` | 32 | 10 | +| `effective_cache_size` | 338688MB | 基于可用内存量 | +| `hot_standby` | on | off | +| `hot_standby_feedback` | on | off | +| `log_autovacuum_min_duration` | 0 | -1 | +| `log_checkpoints` | on | off | +| `log_line_prefix` | `%t [%p]: [%l-1]` | empty | +| `log_min_duration_statement` | 1000 | -1 | +| `log_temp_files` | 0 | -1 | +| `maintenance_work_mem` | 2048MB | 16 兆字节 | +| `max_replication_slots` | 5 | 0 | +| `max_wal_senders` | 32 | 0 | +| `max_wal_size` | 5GB | 1GB | +| `shared_buffers` | 112896MB | 基于可用内存量 | +| `shared_preload_libraries` | pg_stat_statements | empty | +| `shmall` | 30146560 | 基于服务器的功能 | +| `shmmax` | 123480309760 | 基于服务器的功能 | +| `wal_buffers` | 16MB | -1 | +| `wal_keep_segments` | 512 | 10 | +| `wal_level` | replica | minimal | +| `statement_timeout` | 15s | 60s | +| `idle_in_transaction_session_timeout` | 60s | 60s | + +其中一些设置正在调整过程中. 例如, `shared_buffers`的值很高,因此我们正在考虑对其进行调整. 有关此特定更改的更多信息,请参见[https://gitlab.com/gitlab-com/infrastructure/-/issues/1555](https://gitlab.com/gitlab-com/infrastructure/-/issues/1555) . 可以在[https://gitlab.com/gitlab-com/infrastructure/-/issues?scope=all&utf8=✓&state=opened&label_name[]=database&label_name[]=change](https://gitlab.com/gitlab-com/infrastructure/-/issues?scope=all&utf8=✓&state=opened&label_name[]=database&label_name[]=change)找到最新的建议更改列表. + +## Unicorn[](#unicorn "Permalink") + +GitLab.com 调整了[独角兽杀手级](https://rubygems.org/gems/unicorn-worker-killer)宝石的内存限制. + +基本默认值: + +* `memory_limit_min` = 750MiB +* `memory_limit_max` = 1024MiB + +Web 前端: + +* `memory_limit_min` = 1024MiB +* `memory_limit_max` = 1280MiB + +## GitLab.com-specific rate limits[](#gitlabcom-specific-rate-limits "Permalink") + +**注意:**有关管理员文档,请参阅[速率限制](../../security/rate_limits.html) . + +当 GitLab.com 从单个 IP 地址接收到异常流量时,通常会发生 IP 阻止,系统根据速率限制设置将其视为潜在恶意软件. 在异常流量停止后,IP 地址将根据阻止类型自动释放,如下所述. + +如果您对 GitLab.com 的所有请求均收到`403 Forbidden`错误,请检查是否有任何自动流程可能触发了阻止. 要获得帮助,请与[GitLab 支持人员](https://support.gitlab.com/hc/en-us)联系,以获取详细信息,例如受影响的 IP 地址. + +### HAProxy API throttle[](#haproxy-api-throttle "Permalink") + +对于每个 IP 地址每秒超过 10 个请求的 API 请求,GitLab.com 会以 HTTP 状态代码`429`进行响应. + +所有 API 请求均包含以下示例标头: + +``` +RateLimit-Limit: 600 +RateLimit-Observed: 6 +RateLimit-Remaining: 594 +RateLimit-Reset: 1563325137 +RateLimit-ResetTime: Wed, 17 Jul 2019 00:58:57 GMT +``` + +Source: + +* 在[GitLab.com 的当前 HAProxy 设置中](https://gitlab.com/gitlab-cookbooks/gitlab-haproxy/blob/master/attributes/default.rb)搜索`rate_limit_http_rate_per_minute`和`rate_limit_sessions_per_second` . + +### Rack Attack initializer[](#rack-attack-initializer "Permalink") + +[机架攻击](../../security/rack_attack.html)实施的速率限制的详细信息. + +#### Protected paths throttle[](#protected-paths-throttle "Permalink") + +GitLab.com 以 HTTP 状态代码`429`响应在每个 IP 地址每**分钟**超过 10 个请求的受保护路径上的 POST 请求. + +请参阅下面的源,了解哪些路径受保护. 这包括用户创建,用户确认,用户登录和密码重置. + +此标头包含在对阻止的请求的响应中: + +``` +Retry-After: 60 +``` + +有关更多详细信息,请参见[受保护的路径](../admin_area/settings/protected_paths.html) . + +#### Git and container registry failed authentication ban[](#git-and-container-registry-failed-authentication-ban "Permalink") + +如果在 3 分钟内从一个 IP 地址收到 30 个失败的身份验证请求,则 GitLab.com 会以 HTTP 状态代码`403`响应 1 小时. + +这仅适用于 Git 请求和容器注册表( `/jwt/auth` )请求(组合). + +此限制: + +* 由成功认证的请求重置. 例如,29 个失败的身份验证请求后跟 1 个成功的请求,然后再有 29 个失败的身份验证请求不会触发禁止. +* 不适用于`gitlab-ci-token`认证的 JWT 请求. + +没有提供响应头. + +### Admin Area settings[](#admin-area-settings "Permalink") + +GitLab.com: + +* [将原始端点的速率限制](../../user/admin_area/settings/rate_limits_on_raw_endpoints.html)设置为默认值. +* 没有启用用户和 IP 速率限制设置. + +### Visibility settings[](#visibility-settings "Permalink") + +在 GitLab.com 上,自 GitLab 12.2(2019 年 7 月)起创建的项目,组和代码段[在 GitLab.com 上禁用](https://gitlab.com/gitlab-org/gitlab/-/issues/12388)了[**内部**可见性](../../public_access/public_access.html#internal-projects)设置. + +### SSH maximum number of connections[](#ssh-maximum-number-of-connections "Permalink") + +GitLab.com 通过使用[MaxStartups 设置](http://man.openbsd.org/sshd_config.5#MaxStartups)来定义并发,未经[身份](http://man.openbsd.org/sshd_config.5#MaxStartups)验证的 SSH 连接的最大数量. 如果同时发生的连接数超过了允许的最大连接数,则会将其丢弃,并且用户会收到[`ssh_exchange_identification`错误](../../topics/git/troubleshooting_git.html#ssh_exchange_identification-error) . + +### Import/export[](#importexport "Permalink") + +为了避免滥用,对项目和组的导入,导出和导出下载进行了速率限制. 有关详细信息,请参见[项目导入/导出速率限制](../../user/project/settings/import_export.html#rate-limits)和[组导入/导出速率限制](../../user/group/settings/import_export.html#rate-limits) . + +## GitLab.com Logging[](#gitlabcom-logging "Permalink") + +我们使用[Fluentd](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#fluentd)解析日志. Fluentd 将我们的日志发送到 Stackdriver [Logging](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#stackdriver)和[Cloud Pub / Sub](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#cloud-pubsub) . Stackdriver 用于将日志长期存储在 Google Cold Storage(GCS)中. Cloud Pub / Sub 用于使用[pubsubbeat](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#pubsubbeat-vms)将日志转发到[Elastic 集群](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#elastic) . + +您可以在我们的运行手册中查看更多信息,例如: + +* A [detailed list of what we’re logging](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging#what-are-we-logging) +* Our [current log retention policies](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging#retention) +* A [diagram of our logging infrastructure](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging#logging-infrastructure-overview) + +## GitLab.com at scale[](#gitlabcom-at-scale "Permalink") + +In addition to the GitLab Enterprise Edition Omnibus install, GitLab.com uses the following applications and settings to achieve scale. All settings are publicly available at [chef cookbooks](https://gitlab.com/gitlab-cookbooks). + +### Elastic Cluster[](#elastic-cluster "Permalink") + +我们使用 Elasticsearch 和 Kibana 作为我们的监控解决方案的一部分: + +* [`gitlab-cookbooks` / `gitlab-elk` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab-elk) +* [`gitlab-cookbooks` / `gitlab_elasticsearch` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab_elasticsearch) + +### Fluentd[](#fluentd "Permalink") + +我们使用 Fluentd 统一我们的 GitLab 日志: + +* [`gitlab-cookbooks` / `gitlab_fluentd` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab_fluentd) + +### Prometheus[](#prometheus "Permalink") + +Prometheus 完成了我们的监视堆栈: + +* [`gitlab-cookbooks` / `gitlab-prometheus` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab-prometheus) + +### Grafana[](#grafana "Permalink") + +为了可视化监视数据: + +* [`gitlab-cookbooks` / `gitlab-grafana` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab-grafana) + +### Sentry[](#sentry "Permalink") + +开源错误跟踪: + +* [`gitlab-cookbooks` / `gitlab-sentry` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab-sentry) + +### Consul[](#consul "Permalink") + +服务发现: + +* [`gitlab-cookbooks` / `gitlab_consul` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab_consul) + +### HAProxy[](#haproxy "Permalink") + +高性能 TCP / HTTP 负载均衡器: + +* [`gitlab-cookbooks` / `gitlab-haproxy` · GitLab](https://gitlab.com/gitlab-cookbooks/gitlab-haproxy) \ No newline at end of file diff --git a/docs/406.md b/docs/406.md new file mode 100644 index 0000000000000000000000000000000000000000..3fabd96e316d92bf5de307b7ced4895231e8ec26 --- /dev/null +++ b/docs/406.md @@ -0,0 +1,338 @@ +# Infrastructure as code with Terraform and GitLab + +> 原文:[https://docs.gitlab.com/ee/user/infrastructure/index.html](https://docs.gitlab.com/ee/user/infrastructure/index.html) + +* [Motivation](#motivation) +* [GitLab managed Terraform State](#gitlab-managed-terraform-state) +* [Permissions for using Terraform](#permissions-for-using-terraform) +* [Get started using local development](#get-started-using-local-development) +* [Get started using GitLab CI](#get-started-using-gitlab-ci) +* [Configure the backend](#configure-the-backend) +* [Example project](#example-project) +* [Output Terraform Plan information into a merge request](#output-terraform-plan-information-into-a-merge-request) + * [Example `.gitlab-ci.yaml` file](#example-gitlab-ciyaml-file) + * [Multiple Terraform Plan reports](#multiple-terraform-plan-reports) + +# Infrastructure as code with Terraform and GitLab[](#infrastructure-as-code-with-terraform-and-gitlab "Permalink") + +## Motivation[](#motivation "Permalink") + +GitLab 中的 Terraform 集成功能使您的 GitOps /基础设施即代码(IaC)工作流能够与 GitLab 的身份验证和授权结合在一起. 这些功能着重于降低团队采用 Terraform,在 GitLab 中有效协作以及支持 Terraform 最佳实践的准入门槛. + +## GitLab managed Terraform State[](#gitlab-managed-terraform-state "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2673) . + +[Terraform 远程后端](https://www.terraform.io/docs/backends/index.html)使您可以将状态文件存储在远程共享存储中. GitLab 使用[Terraform HTTP 后端](https://www.terraform.io/docs/backends/types/http.html)将状态文件安全地存储在本地存储(默认)或[您选择的远程存储中](../../administration/terraform_state.html) . + +由 GitLab 管理的 Terraform 状态后端可以轻松安全地存储 Terraform 状态,并使您免于设置其他远程资源(如 Amazon S3 或 Google Cloud Storage). 其功能包括: + +* 在传输和静止时都支持状态文件的加密. +* 锁定和解锁状态. +* 远程 Terraform 计划并执行. + +要开始使用 GitLab 管理的 Terraform State,有两种不同的选择: + +* [Use a local machine](#get-started-using-local-development). +* [Use GitLab CI](#get-started-using-gitlab-ci). + +## Permissions for using Terraform[](#permissions-for-using-terraform "Permalink") + +在 GitLab 版本 13.1 中,需要[维护者访问权限](../permissions.html)才能使用 GitLab 管理的 Terraform 状态后端. 在 GitLab 版本 13.2 和更高版本中,需要[维护者访问权限](../permissions.html)才能锁定,解锁和写入状态(使用`terraform apply` ),而需要[开发人员访问权限](../permissions.html)来读取状态(使用`terraform plan -lock=false` ). + +## Get started using local development[](#get-started-using-local-development "Permalink") + +如果您计划仅运行`terraform plan`并从本地计算机上执行`terraform plan` `terraform apply`命令,这是一种入门的简单方法: + +1. 在您的 GitLab 实例上创建项目. +2. 导航 **设置>常规,**并记下您的**项目名称**和**项目 ID** . +3. Define the Terraform backend in your Terraform project to be: + + ``` + terraform { + backend "http" { + } + } + ``` + +4. 使用`api`范围创建一个[个人访问令牌](../profile/personal_access_tokens.html) . + +5. 在本地计算机上,运行`terraform init` ,传入以下选项,并用相关值替换`` , `` , ``和`` . 此命令将初始化 Terraform 状态,并将该状态存储在 GitLab 项目中. 这个例子使用`gitlab.com` : + + ``` + terraform init \ + -backend-config="address=https://gitlab.com/api/v4/projects//terraform/state/" \ + -backend-config="lock_address=https://gitlab.com/api/v4/projects//terraform/state//lock" \ + -backend-config="unlock_address=https://gitlab.com/api/v4/projects//terraform/state//lock" \ + -backend-config="username=" \ + -backend-config="password=" \ + -backend-config="lock_method=POST" \ + -backend-config="unlock_method=DELETE" \ + -backend-config="retry_wait_min=5" + ``` + +Next, [configure the backend](#configure-the-backend). + +## Get started using GitLab CI[](#get-started-using-gitlab-ci "Permalink") + +如果您不想开始本地开发,也可以使用 GitLab CI 来运行`terraform plan`和`terraform apply`命令. + +Next, [configure the backend](#configure-the-backend). + +## Configure the backend[](#configure-the-backend "Permalink") + +执行`terraform init`命令后,必须配置 Terraform 后端和 CI YAML 文件: + +1. 在 Terraform 项目中,通过在`.tf`文件(例如`backend.tf` )中添加以下代码块来定义远程后端,以定义[HTTP](https://www.terraform.io/docs/backends/types/http.html)后端: + + ``` + terraform { + backend "http" { + } + } + ``` + +2. 在项目存储库的根目录中,配置`.gitlab-ci.yaml`文件. 本示例使用一个包含`gitlab-terraform`帮助器的预构建图像. 有关受支持的 Terraform 版本,请参见[GitLab Terraform Images 项目](https://gitlab.com/gitlab-org/terraform-images) . + + ``` + image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest + ``` + +3. 在`.gitlab-ci.yaml`文件中,定义一些环境变量以简化开发. 在此示例中, `TF_ROOT`是必须执行 Terraform 命令的目录, `TF_ADDRESS`是该管道在其上运行的 GitLab 实例上的状态的 URL,并且`TF_ADDRESS`的最后路径段是 Terraform 状态的名称. 项目可能具有多个状态,并且该名称是任意的,因此在此示例中,我们将其设置为项目的名称,并确保使用基于缓存的缓存键在管道中的作业之间缓存`.terraform`目录.州名: + + ``` + variables: + TF_ROOT: ${CI_PROJECT_DIR}/environments/cloudflare/production + TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_PROJECT_NAME} + + cache: + key: ${CI_PROJECT_NAME} + paths: + - ${TF_ROOT}/.terraform + ``` + +4. 在`before_script` ,更改为`TF_ROOT` : + + ``` + before_script: + - cd ${TF_ROOT} + + stages: + - prepare + - validate + - build + - deploy + + init: + stage: prepare + script: + - gitlab-terraform init + + validate: + stage: validate + script: + - gitlab-terraform validate + + plan: + stage: build + script: + - gitlab-terraform plan + - gitlab-terraform plan-json + artifacts: + name: plan + paths: + - ${TF_ROOT}/plan.cache + reports: + terraform: ${TF_ROOT}/plan.json + + apply: + stage: deploy + environment: + name: production + script: + - gitlab-terraform apply + dependencies: + - plan + when: manual + only: + - master + ``` + +5. 将项目推送到 GitLab,这将触发 CI 作业管道. 该管道运行`gitlab-terraform init` , `gitlab-terraform validate`和`gitlab-terraform plan`命令. + +以上`terraform`命令的输出应在作业日志中可见. + +## Example project[](#example-project "Permalink") + +请参阅使用 GitLab 和 Terraform 在自定义 VPC 中部署基本 AWS EC2 的[参考项目](https://gitlab.com/nicholasklick/gitlab-terraform-aws) . + +## Output Terraform Plan information into a merge request[](#output-terraform-plan-information-into-a-merge-request "Permalink") + +使用[GitLab Terraform Report 工件](../../ci/pipelines/job_artifacts.html#artifactsreportsterraform) ,您可以将`terraform plan`运行中的详细信息直接暴露到合并请求小部件中,使您能够查看有关 Terraform 将创建,修改或销毁的资源的统计信息. + +让我们探索如何配置 GitLab Terraform Report 工件. 您可以使用包含上述`gitlab-terraform`帮助器的预构建映像,其中`gitlab-terraform plan-json`输出所需的工件,或者您可以按以下方式手动进行配置: + +1. 为简单起见,让我们定义一些可重用的变量,以允许我们多次引用这些文件: + + ``` + variables: + PLAN: plan.cache + PLAN_JSON: plan.json + ``` + +2. 安装`jq` ,这是一种[轻巧灵活的命令行 JSON 处理器](https://stedolan.github.io/jq/) . +3. 为特定的`jq`命令创建一个别名,该别名解析出我们要从`terraform plan`输出中提取的信息: + + ``` + before_script: + - apk --no-cache add jq + - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'" + ``` + + **注意:**在使用 Bash 的发行版(例如,Ubuntu)中, `alias`语句不会在非交互模式下扩展. 如果您的管道失败并显示错误`convert_report: command not found` ,则可以通过在脚本中添加`shopt`命令来明确激活别名扩展: + + ``` + before_script: + - shopt -s expand_aliases + - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'" + ``` + +4. 定义运行`terraform plan`和`terraform show`的`script` . 这些命令通过管道`PLAN_JSON`输出并将相关位转换为存储变量`PLAN_JSON` . 此 JSON 用于创建[GitLab Terraform Report 工件](../../ci/pipelines/job_artifacts.html#artifactsreportsterraform) . Terraform 报告获取 Terraform `tfplan.json`文件. 收集的 Terraform 计划报告作为工件上传到 GitLab,并在合并请求中显示. + + ``` + plan: + stage: build + script: + - terraform plan -out=$PLAN + - terraform show --json $PLAN | convert_report > $PLAN_JSON + artifacts: + reports: + terraform: $PLAN_JSON + ``` + + 有关使用预构建图像的完整示例,请参见[Example `.gitlab-ci.yaml`文件](#example-gitlab-ciyaml-file) . + + 有关显示多个报告的示例,请参见[`.gitlab-ci.yaml`多个报告文件](#multiple-terraform-plan-reports) . + +5. 运行管道会在合并请求中显示小部件,如下所示: + + [![Merge Request Terraform widget](img/f3550bb5a4a6074ef46ae27848adc308.png)](img/terraform_plan_widget_v13_2.png) + +6. Clicking the **查看完整日志** button in the widget takes you directly to the plan output present in the pipeline logs: + + [![Terraform plan logs](img/0a8c15f1fa2c2e0a210d9baae9fff372.png)](img/terraform_plan_log_v13_0.png) + +### Example `.gitlab-ci.yaml` file[](#example-gitlab-ciyaml-file "Permalink") + +``` +image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest + +variables: + TF_ROOT: ${CI_PROJECT_DIR}/environments/cloudflare/production + TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_PROJECT_NAME} + +cache: + key: ${CI_PROJECT_NAME} + paths: + - ${TF_ROOT}/.terraform + +before_script: + - cd ${TF_ROOT} + +stages: + - prepare + - validate + - build + - deploy + +init: + stage: prepare + script: + - gitlab-terraform init + +validate: + stage: validate + script: + - gitlab-terraform validate + +plan: + stage: build + script: + - gitlab-terraform plan + - gitlab-terraform plan-json + artifacts: + name: plan + paths: + - ${TF_ROOT}/plan.cache + reports: + terraform: ${TF_ROOT}/plan.json + +apply: + stage: deploy + environment: + name: production + script: + - gitlab-terraform apply + dependencies: + - plan + when: manual + only: + - master +``` + +### Multiple Terraform Plan reports[](#multiple-terraform-plan-reports "Permalink") + +从 13.2 开始,您可以在"合并请求"页面上显示多个报告. 报告还将显示`artifact: name:` 有关建议的设置,请参见下面的示例. + +``` +image: + name: registry.gitlab.com/gitlab-org/gitlab-build-images:terraform + entrypoint: + - '/usr/bin/env' + - 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' + +cache: + paths: + - .terraform + +stages: + - build + +.terraform-plan-generation: + stage: build + variables: + PLAN: plan.tfplan + JSON_PLAN_FILE: tfplan.json + before_script: + - cd ${TERRAFORM_DIRECTORY} + - terraform --version + - terraform init + - apk --no-cache add jq + script: + - terraform validate + - terraform plan -out=${PLAN} + - terraform show --json ${PLAN} | jq -r '([.resource_changes[]?.change.actions?]|flatten)|{"create":(map(select(.=="create"))|length),"update":(map(select(.=="update"))|length),"delete":(map(select(.=="delete"))|length)}' > ${JSON_PLAN_FILE} + artifacts: + reports: + terraform: ${TERRAFORM_DIRECTORY}/${JSON_PLAN_FILE} + +review_plan: + extends: .terraform-plan-generation + variables: + TERRAFORM_DIRECTORY: "review/" + # Review will not include an artifact name + +staging_plan: + extends: .terraform-plan-generation + variables: + TERRAFORM_DIRECTORY: "staging/" + artifacts: + name: Staging + +production_plan: + extends: .terraform-plan-generation + variables: + TERRAFORM_DIRECTORY: "production/" + artifacts: + name: Production +``` \ No newline at end of file diff --git a/docs/407.md b/docs/407.md new file mode 100644 index 0000000000000000000000000000000000000000..02c759136d79a0fb5acfa2c0f7a68dea8eb5ce4d --- /dev/null +++ b/docs/407.md @@ -0,0 +1,147 @@ +# GitLab keyboard shortcuts + +> 原文:[https://docs.gitlab.com/ee/user/shortcuts.html](https://docs.gitlab.com/ee/user/shortcuts.html) + +* [Global Shortcuts](#global-shortcuts) +* [Project](#project) + * [Issues and Merge Requests](#issues-and-merge-requests) + * [Project Files](#project-files) + * [Web IDE](#web-ide) + * [Repository Graph](#repository-graph) + * [Wiki pages](#wiki-pages) + * [Filtered Search](#filtered-search) +* [Epics](#epics-ultimate) + +# GitLab keyboard shortcuts[](#gitlab-keyboard-shortcuts "Permalink") + +GitLab 有许多有用的键盘快捷键,使您可以更轻松地访问不同的功能. 您可以通过按`?`在 GitLab 本身中看到模式列表键盘快捷键`.` ,或单击右上角"帮助"菜单中的" **键盘快捷键"** . 在[GitLab 12.8 和更高版本中](https://gitlab.com/gitlab-org/gitlab/-/issues/22113) ,可以使用此模式窗口中的" **启用** / **禁用"**切换来禁用键盘快捷键. + +[全局快捷方式](#global-shortcuts)可在 GitLab 的任何区域使用,但是您必须在特定页面中才能使用其他快捷方式,如以下各节所述. + +## Global Shortcuts[](#global-shortcuts "Permalink") + +在 GitLab 的大多数区域中都可以使用这些快捷方式 + +| 键盘快捷键 | Description | +| --- | --- | +| `?` | 显示/隐藏快捷方式参考表. | +| `Shift` + `p` | 转到您的项目页面. | +| `Shift` + `g` | 转到您的网上论坛页面. | +| `Shift` + `a` | 转到"活动"页面. | +| `Shift` + `l` | 转到您的里程碑页面. | +| `Shift` + `s` | 转到您的代码段页面. | +| `s` | 将光标放在问题/合并请求搜索中. | +| `Shift` + `i` | 转到您的问题页面. | +| `Shift` + `m` | 转到"合并请求"页面. | +| `Shift` + `t` | 转到待办事项列表页面. | +| `p` + `b` | 显示/隐藏性能栏. | + +此外,在文本字段中编辑文本时,可以使用以下快捷方式,例如,注释,回复,问题描述和合并请求描述: + +| 键盘快捷键 | Description | +| --- | --- | +| `↑` | 编辑您的最后评论. 您必须在线程下方的空白文本字段中,并且该线程中必须已经至少有一个注释. | +| `⌘` (Mac)/ `Ctrl` + `Shift` + `p` | 在顶部具有" **编写"**和" **预览"**选项卡的文本字段中编辑文本时,切换 Markdown 预览. | + +## Project[](#project "Permalink") + +这些快捷方式可从项目中的任何页面获得. 您必须相对快速地键入它们才能工作,并且它们会将您带到项目中的另一个页面. + +| 键盘快捷键 | Description | +| --- | --- | +| `g` + `p` | 转到项目主页(" **项目">"详细信息"** ). | +| `g` + `v` | 转到项目活动提要(" **项目">"活动"** ). | +| `g` + `r` | 转到项目发布列表(" **项目">"发布"** ). | +| `g` + `f` | 转到[项目文件](#project-files)列表(" **存储库">"文件"** ). | +| `t` | 转到项目文件搜索页面. (" **存储库">"文件"** ,单击" **查找文件"** ). | +| `g` + `c` | 转到项目提交列表( **存储库>提交** ). | +| `g` + `n` | 转到[存储库图](#repository-graph)页面( **Repository> Graph** ). | +| `g` + `d` | Go to repository charts (**分析>存储库分析**). | +| `g` + `i` | 转到项目问题列表( **问题>列表** ). | +| `i` | 转到"新问题"页面(" **问题"** ,单击" **新问题"** ). | +| `g` + `b` | 转到项目问题委员会列表( **问题>委员会** ). | +| `g` + `m` | 转到项目合并请求列表( **合并请求** ). | +| `g` + `j` | 转到 CI / CD 作业列表( **CI / CD>作业** ). | +| `g` + `l` | 转到项目指标(" **操作">"指标"** ). | +| `g` + `e` | 转到项目环境(" **操作">"环境"** ). | +| `g` + `k` | 转到项目 Kubernetes 集群集成页面( **操作> Kubernetes** ). 请注意,您必须至少具有[`maintainer`权限](permissions.html)才能访问此页面. | +| `g` + `s` | 转到项目片段列表( **片段** ). | +| `g` + `w` | 转到项目 Wiki( **Wiki** )(如果已启用). | + +### Issues and Merge Requests[](#issues-and-merge-requests "Permalink") + +这些快捷方式在查看问题和合并请求时可用. + +| 键盘快捷键 | Description | +| --- | --- | +| `e` | 编辑说明. | +| `a` | 更改受让人. | +| `m` | 更改里程碑. | +| `l` | 更改标签. | +| `r` | 开始写评论. 如果选择了任何文本,它将在注释中引用. 不能用于在线程内回复. | +| `n` | 移至下一个未解决的讨论(仅合并请求). | +| `p` | 移至上一个未解决的讨论(仅合并请求). | +| `]` or `j` | 移至下一个文件(仅合并请求). | +| `[` or `k` | 移至上一个文件(仅合并请求). | +| `b` | 复制源分支名称(仅合并请求). | + +### Project Files[](#project-files "Permalink") + +这些快捷方式在浏览项目中的文件时可用(导航至**Repository** > **Files** ): + +| 键盘快捷键 | Description | +| --- | --- | +| `↑` | 向上移动选择. | +| `↓` | 向下移动选择. | +| `enter` | 打开选择. | +| `esc` | 返回文件列表屏幕(仅在搜索文件时," **存储库">"文件",**然后单击" **查找文件"** ). | +| `y` | 转到文件永久链接(仅在查看文件时). | + +### Web IDE[](#web-ide "Permalink") + +使用[Web IDE](project/web_ide/index.html)编辑文件时,可以使用以下快捷方式: + +| 键盘快捷键 | Description | +| --- | --- | +| `⌘` (Mac)/ `Ctrl` + `p` | 搜索,然后打开另一个文件进行编辑. | +| `⌘` (Mac)/ `Ctrl` + `Enter` | 提交(在编辑提交消息时). | + +### Repository Graph[](#repository-graph "Permalink") + +这些快捷方式在查看项目[存储库图形](project/repository/index.html#repository-graph)页面时可用(导航至**Repository> Graph** ): + +| 键盘快捷键 | Description | +| --- | --- | +| `←` or `h` | 向左滚动. | +| `→` or `l` | 向右滚动. | +| `↑` or `k` | 向上滚动. | +| `↓` or `j` | 向下滚动. | +| `Shift` + `↑` or `Shift` + `k` | 滚动到顶部. | +| `Shift` + `↓` or `Shift` + `j` | 滚动到底部. | + +### Wiki pages[](#wiki-pages "Permalink") + +查看[维基页面](project/wiki/index.html)时,可以使用此快捷方式: + +| 键盘快捷键 | Description | +| --- | --- | +| `e` | 编辑 Wiki 页面. | + +### Filtered Search[](#filtered-search "Permalink") + +这些快捷方式在使用[过滤的搜索输入](search/index.html)时可用: + +| 键盘快捷键 | Description | +| --- | --- | +| `⌘` (Mac)+ `⌫` | 清除整个搜索过滤器. | +| `⌥` (Mac)/ `Ctrl` + `⌫` | 一次清除一个令牌. | + +## Epics[](#epics-ultimate "Permalink") + +这些快捷方式在查看[Epics](group/epics/index.html)时可用: + +| 键盘快捷键 | Description | +| --- | --- | +| `r` | 开始写评论. 如果选择了任何文本,它将在注释中引用. 不能用于在线程内回复. | +| `e` | 编辑说明. | +| `l` | 更改标签. | \ No newline at end of file diff --git a/docs/408.md b/docs/408.md new file mode 100644 index 0000000000000000000000000000000000000000..671115e21a47f70b81b16b2da8f0689bffa63b88 --- /dev/null +++ b/docs/408.md @@ -0,0 +1,1277 @@ +# GitLab Markdown + +> 原文:[https://docs.gitlab.com/ee/user/markdown.html](https://docs.gitlab.com/ee/user/markdown.html) + +* [GitLab Flavored Markdown (GFM)](#gitlab-flavored-markdown-gfm) + * [Transition from Redcarpet to CommonMark](#transition-from-redcarpet-to-commonmark) + * [GFM extends standard Markdown](#gfm-extends-standard-markdown) +* [New GFM Markdown extensions](#new-gfm-markdown-extensions) + * [Colors](#colors) + * [Diagrams and flowcharts](#diagrams-and-flowcharts) + * [Mermaid](#mermaid) + * [PlantUML](#plantuml) + * [Emoji](#emoji) + * [Front matter](#front-matter) + * [Inline diff](#inline-diff) + * [Math](#math) + * [Special GitLab references](#special-gitlab-references) + * [Task lists](#task-lists) + * [Table of contents](#table-of-contents) + * [Wiki-specific Markdown](#wiki-specific-markdown) + * [Wiki - direct page link](#wiki---direct-page-link) + * [Wiki - direct file link](#wiki---direct-file-link) + * [Wiki - hierarchical link](#wiki---hierarchical-link) + * [Wiki - root link](#wiki---root-link) + * [Embedding metrics in GitLab Flavored Markdown](#embedding-metrics-in-gitlab-flavored-markdown) +* [Standard Markdown and extensions in GitLab](#standard-markdown-and-extensions-in-gitlab) + * [Blockquotes](#blockquotes) + * [Multiline blockquote](#multiline-blockquote) + * [Code spans and blocks](#code-spans-and-blocks) + * [Colored code and syntax highlighting](#colored-code-and-syntax-highlighting) + * [Emphasis](#emphasis) + * [Multiple underscores in words and mid-word emphasis](#multiple-underscores-in-words-and-mid-word-emphasis) + * [Footnotes](#footnotes) + * [Headers](#headers) + * [Header IDs and links](#header-ids-and-links) + * [Horizontal Rule](#horizontal-rule) + * [Images](#images) + * [Videos](#videos) + * [Audio](#audio) + * [Inline HTML](#inline-html) + * [Details and summary](#details-and-summary) + * [Line breaks](#line-breaks) + * [Newlines](#newlines) + * [Links](#links) + * [URL auto-linking](#url-auto-linking) + * [Lists](#lists) + * [Superscripts / Subscripts](#superscripts--subscripts) + * [Tables](#tables) + * [Copy from spreadsheet and paste in Markdown](#copy-from-spreadsheet-and-paste-in-markdown) +* [References](#references) + +# GitLab Markdown[](#gitlab-markdown "Permalink") + +该 Markdown 指南**仅对 GitLab 的内部 Markdown 渲染系统的条目和文件有效** . 它是**无效**的[GitLab 文档,网站](https://s0docs0gitlab0com.icopy.site)或[GitLab 的主要网站](https://about.gitlab.com) ,因为它们都使用[Kramdown](https://kramdown.gettalong.org)作为他们的降价引擎. 文档网站使用扩展的 Kramdown 宝石[GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown) . 有关完整的 Kramdown 参考,请查阅《 [GitLab Kramdown 指南》](https://about.gitlab.com/handbook/markdown-guide/) . + +**注意:**我们建议您查看[GitLab 本身提供的](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md)此文档. + +## GitLab Flavored Markdown (GFM)[](#gitlab-flavored-markdown-gfm "Permalink") + +GitLab 使用" GitLab 风味降价"(GFM). 它以几种方式扩展了[CommonMark 规范](https://spec.commonmark.org/current/) (基于标准 Markdown),以添加其他有用的功能. 它的灵感来自[GitHub Flavored Markdown](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax) . + +您可以在以下区域使用 GFM: + +* Comments +* Issues +* 合并要求 +* Milestones +* 代码段(代码段必须以`.md`扩展名命名) +* 维基页面 +* 仓库中的 Markdown 文档 +* Epics + +您还可以在 GitLab 中使用其他 RTF 文件. 您可能必须安装依赖项才能这样做. 请参阅[`gitlab-markup` gem 项目](https://gitlab.com/gitlab-org/gitlab-markup)以获取更多信息. + +### Transition from Redcarpet to CommonMark[](#transition-from-redcarpet-to-commonmark "Permalink") + +从 11.1 开始,GitLab 使用[CommonMark Ruby 库](https://github.com/gjtorikian/commonmarker)对[Markit](https://github.com/gjtorikian/commonmarker)处理 GitLab 系统中的所有新问题,合并请求,注释和其他 Markdown 内容. 从 11.3 开始,存储库中的 Wiki 页面和 Markdown 文件( `*.md` )也将通过 CommonMark 处理. 从 11.8 开始, [Redcarpet Ruby 库](https://github.com/vmg/redcarpet)已被删除,所有问题和注释,包括 11.1 之前的问题和注释,现在都可以使用[CommonMark Ruby Library 处理](https://github.com/gjtorikian/commonmarker) . + +该文档网站的[Markdown 引擎](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/108)已于 2018 年 10 月[从 Redcarpet 迁移到 Kramdown](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/108) . + +您的存储库中可能存在较旧的问题,合并请求或 Markdown 文档,这些文档是使用 GitLab 的 RedCarpet 版本的 Markdown 的细微差别编写的. 由于 CommonMark 使用了稍微严格的语法,因此自我们过渡到 CommonMark 以来,这些文档现在看起来可能会有所不同. + +通常很容易修复. 例如,带嵌套列表的编号列表可能会错误显示: + +``` +1. Chocolate + - dark + - milk +``` + +只需在每个嵌套项目中添加一个空格即可使`-`与顶部列表项的第一个字符对齐(本例中为`C` ): + +``` +1. Chocolate + - dark + - milk +``` + +1. Chocolate + * dark + * milk + +**注意:**我们将在本文档中标记 Redcarpet 和 CommonMark Markdown 之间的任何重大差异. + +如果您有大量的 Markdown 文件,确定它们是否正确显示可能很繁琐. 您可以使用[diff_redcarpet_cmark](https://gitlab.com/digitalmoksha/diff_redcarpet_cmark)工具(不是官方支持的产品)来生成文件列表以及 RedCarpet 和 CommonMark 呈现文件的方式之间的差异. 它可以指示是否需要更改任何内容-通常不需要更改. + +### GFM extends standard Markdown[](#gfm-extends-standard-markdown "Permalink") + +GitLab 充分利用了标准(CommonMark)格式,但还包括对 GitLab 用户有用的附加功能. + +它利用了[Markdown](#new-GFM-markdown-extensions)的[新功能](#new-GFM-markdown-extensions) ,这些[功能](#new-GFM-markdown-extensions)是标准 Markdown 所没有的: + +* [Color “chips” written in HEX, RGB or HSL](#colors) +* [Diagrams and flowcharts](#diagrams-and-flowcharts) +* [Emoji](#emoji) +* [Front matter](#front-matter) +* [Inline diffs](#inline-diff) +* [Math equations and symbols written in LaTeX](#math) +* [Special GitLab references](#special-gitlab-references) +* [Task Lists](#task-lists) +* [Table of Contents](#table-of-contents) +* [Wiki specific Markdown](#wiki-specific-markdown) + +它还具有[扩展的 Markdown 功能](#standard-markdown-and-extensions-in-gitlab) ,而无需更改标准 Markdown 的使用方式: + +| 标准减价 | 在 GitLab 中扩展 Markdown | +| --- | --- | +| [blockquotes](#blockquotes) | [multi-line blockquotes](#multiline-blockquote) | +| [code blocks](#code-spans-and-blocks) | [colored code and syntax highlighting](#colored-code-and-syntax-highlighting) | +| [emphasis](#emphasis) | [multiple underscores in words](#multiple-underscores-in-words-and-mid-word-emphasis) | +| [headers](#headers) | [linkable Header IDs](#header-ids-and-links) | +| [images](#images) | [embedded videos](#videos) and [audio](#audio) | +| [line breaks](#line-breaks) | [more line break control](#newlines) | +| [links](#links) | [automatically linking URLs](#url-auto-linking) | + +## New GFM Markdown extensions[](#new-gfm-markdown-extensions "Permalink") + +### Colors[](#colors "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#colors) . + +可以使用颜色指示器呈现以 HEX,RGB 或 HSL 格式书写的颜色. + +支持的格式(不支持命名的颜色): + +* HEX: ``#RGB[A]`` or ``#RRGGBB[AA]`` +* RGB: ``RGB[A](R, G, B[, A])`` +* HSL: ``HSL[A](H, S, L[, A])`` + +反引号内的颜色后面将带有颜色"碎片": + +``` +- `#F00` +- `#F00A` +- `#FF0000` +- `#FF0000AA` +- `RGB(0,255,0)` +- `RGB(0%,100%,0%)` +- `RGBA(0,255,0,0.3)` +- `HSL(540,70%,50%)` +- `HSLA(540,70%,50%,0.3)` +``` + +* `#F00` +* `#F00A` +* `#FF0000` +* `#FF0000AA` +* `RGB(0,255,0)` +* `RGB(0%,100%,0%)` +* `RGBA(0,255,0,0.3)` +* `HSL(540,70%,50%)` +* `HSLA(540,70%,50%,0.3)` + +### Diagrams and flowcharts[](#diagrams-and-flowcharts "Permalink") + +可以使用[Mermaid](https://s0mermaidjs0github0io.icopy.site/)或[PlantUML](https://plantuml.com)从 GitLab 中的文本生成图表和流程图. + +#### Mermaid[](#mermaid "Permalink") + +在 GitLab 10.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15107) . + +访问[官方页面](https://s0mermaidjs0github0io.icopy.site/)以获取更多详细信息. 如果您不熟悉使用 Mermaid,或者需要帮助来确定 Mermaid 代码中的问题,则[Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/)是一个有用的工具,可用于在 Mermaid 图中创建和解决问题. + +为了生成图表或流程图,您应该在`mermaid`块内编写文本: + +``` +```mermaid graph TD; + A-->B; + A-->C; + B-->D; + C-->D; +``` +``` + +图 TD; A-> B; A-> C; B-> D; C-> D; + +子图也可以包括: + +``` +```mermaid graph TB + + SubGraph1 --> SubGraph1Flow + subgraph "SubGraph 1 Flow" + SubGraph1Flow(SubNode 1) + SubGraph1Flow -- Choice1 --> DoChoice1 + SubGraph1Flow -- Choice2 --> DoChoice2 + end + + subgraph "Main Graph" + Node1[Node 1] --> Node2[Node 2] + Node2 --> SubGraph1[Jump to SubGraph1] + SubGraph1 --> FinalThing[Final Thing] +end +``` +``` + +图 TB SubGraph1-> SubGraph1Flow 子图" SubGraph 1 Flow" SubGraph1Flow(SubNode 1)SubGraph1Flow-Choice1-> DoChoice1 SubGraph1Flow-Choice2-> DoChoice2 结束子图" Main Graph" Node1 [Node 1]-> Node2 [ Node 2] Node2-> SubGraph1 [Jump to SubGraph1] SubGraph1-> FinalThing [Final Thing]结束 + +#### PlantUML[](#plantuml "Permalink") + +为了使 PlantUML 在 GitLab 中可用,GitLab 管理员需要首先启用它. 在[PlantUML&GitLab 中](../administration/integration/plantuml.html)了解更多[信息](../administration/integration/plantuml.html) . + +### Emoji[](#emoji "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#emoji) . + +``` +Sometimes you want to :monkey: around a bit and add some :star2: to your :speech_balloon:. Well we have a gift for you: + +:zap: You can use emoji anywhere GFM is supported. :v: + +You can use it to point out a :bug: or warn about :speak_no_evil: patches. And if someone improves your really :snail: code, send them some :birthday:. People will :heart: you for that. + +If you're new to this, don't be :fearful:. You can easily join the emoji :family:. All you need to do is to look up one of the supported codes. + +Consult the [Emoji Cheat Sheet](https://www.emojicopy.com) for a list of all supported emoji codes. :thumbsup: +``` + +有时候你想 ![](img/a5023ba03c96276e989dc4dbff1ca8dd.png) 大约添加一些 ![](img/bb7ff3b17ad66e05a64ee12def63524b.png) 给你 ![](img/49d46d08d1ca6c3cd3d0b0ef98472512.png) . 好吧,我们有礼物送给您: + +![](img/13b2b9b44dbf46de0243edc068ecab42.png)您可以在支持 GFM 的任何地方使用表情符号. ![](img/cff0e046ac8eca2d9fde8f13a3365d66.png) + +您可以使用它指出一个 ![](img/7710cb575c3aefd0769c3f6aadb6e879.png) 或警告 ![](img/773702223af81c9872bccd88d63ad3a5.png) 补丁. 如果有人真的改善了你 ![](img/17e23e08ff33b405e039adae1f73cb83.png) 代码,给他们发送一些 ![](img/fd7124974fcca5463d2ce7385bfb700e.png) . 人们会 ![](img/bab86c57be5bd24c1329a7de56df456a.png) 为此. + +如果您是新手,请不要 ![](img/e41f9ac1eea140d12bc83ea9312e71d0.png) . 您可以轻松加入表情符号 ![](img/d5171d012a8ff616032035f890d8dbd5.png) . 您需要做的只是查找受支持的代码之一. + +有关所有受支持的表情符号代码的列表,请查阅[表情符号备忘单](https://www.webfx.com/tools/emoji-cheat-sheet/) . ![](img/d0b9fcc8669d772a04d7d72ccb5a82cc.png) + +> **注意:**以上表情符号示例在本文档中使用了硬编码图像. 在 GitLab 中呈现时,表情符号可能会出现不同,具体取决于所使用的操作系统和浏览器. + +大多数 emoji 表情在 macOS,Windows,iOS,Android 上均受本机支持,并且将退回到不支持图像的基于图像的表情上. + +**注意:**在 Linux 上,您可以下载[Noto Color Emoji](https://www.google.com/get/noto/help/emoji/)以获得完整的本机表情符号支持. Ubuntu 18.04(与许多现代 Linux 发行版一样)默认情况下已安装此字体. + +### Front matter[](#front-matter "Permalink") + +在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23331) . + +首要事项是 Markdown 文档开头,内容之前的元数据. 静态站点生成器(例如[Jekyll](https://jekyllrb.com/docs/front-matter/) , [Hugo](https://s0gohugo0io.icopy.site/content-management/front-matter/)和许多其他应用程序)可以使用此数据. + +当您查看由 GitLab 渲染的 Markdown 文件时,任何前端问题都会按原样显示在文档顶部的框中,位于渲染的 HTML 内容之前. 要查看示例,可以在[GitLab 文档文件](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/README.md)的源版本和渲染版本之间切换. + +在 GitLab 中,仅在 Markdown 文件和 Wiki 页面中使用前题,而不在支持 Markdown 格式的其他地方使用. 它必须在文档的最顶部,并且必须在定界符之间,如下所述. + +支持以下定界符: + +* YAML( `---` ): + + ``` + --- + title: About Front Matter + example: + language: yaml + --- + ``` + +* TOML( `+++` ): + + ``` + +++ + title = "About Front Matter" + [example] + language = "toml" + +++ + ``` + +* JSON( `;;;` ): + + ``` + ;;; { "title": "About Front Matter" "example": { "language": "json" } } ;;; + ``` + +通过向任何现有定界符添加说明符来支持其他语言. 例如: + +``` +---php +$title = "About Front Matter"; +$example = array( + 'language' => "php", +); +--- +``` + +### Inline diff[](#inline-diff "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#inline-diff) . + +使用内联 diff 标签,您可以显示`{+ additions +}`或`[- deletions -]` . + +包装标签可以是大括号或方括号: + +``` +- {+ addition 1 +} +- [+ addition 2 +] +- {- deletion 3 -} +- [- deletion 4 -] +``` + +* {+加法 1 +} +* [+加法 2 +] +* {-删除 3-} +* [-删除 4-] + +* * * + +但是,包装标签不能混合使用: + +``` +- {+ addition +] +- [+ addition +} +- {- deletion -] +- [- deletion -} +``` + +如果您的差异包含``code``字体的单词,请确保使用反斜杠`\`来转义每个反引号``` ,否则差异突出显示将无法正确呈现: + +``` +- {+ Just regular text +} +- {+ Text with `backticks` inside +} +- {+ Text with escaped \`backticks\` inside +} +``` + +* {+普通文字+} +* {+带有`backticks`文字+} +* {+内含转义的`反引号'的文字+} + +### Math[](#math "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#math) . + +可以使用[KaTeX](https://github.com/KaTeX/KaTeX)渲染用 LaTeX 语法编写的数学运算. + +在美元符号`$`之间写的数学将与文本内嵌. 用声明为`math`的语言在[代码块中](#code-spans-and-blocks)编写的`math`将在单独的行上呈现: + +``` +This math is inline $`a^2+b^2=c^2`$. + +This is on a separate line + +```math a^2+b^2=c^2 +``` +``` + +此数学`a^2+b^2=c^2`为内联$ `a^2+b^2=c^2` $. + +这是在单独的行上 + +``` +a^2+b^2=c^2 +``` + +*请注意,KaTeX 仅支持 LaTeX 的[子集](https://katex.org/docs/supported.html) .* + +**注意:**这也适用于 Asciidoctor `:stem: latexmath` . 有关详细信息,请参见[Asciidoctor 用户手册](https://asciidoctor.org/docs/user-manual/#activating-stem-support) . + +### Special GitLab references[](#special-gitlab-references "Permalink") + +GFM 可以识别与 GitLab 相关的特殊参考. 例如,您可以轻松地引用项目中的问题,提交,团队成员甚至整个团队. GFM 会将引用转换为链接,以便您可以轻松地在它们之间导航. + +此外,GFM 可以识别某些跨项目引用,并且还具有一个速记版本,可以引用同一名称空间中的其他项目. + +GFM 将识别以下内容: + +| references | input | 跨项目参考 | shortcut within same namespace | +| --- | --- | --- | --- | +| 特定使用者 | `@user_name` |   |   | +| 特定人群 | `@group_name` |   |   | +| 整个团队 | `@all` |   |   | +| project | `namespace/project>` |   |   | +| issue | `#123` | `namespace/project#123` | `project#123` | +| 合并要求 | `!123` | `namespace/project!123` | `project!123` | +| snippet | `$123` | `namespace/project$123` | `project$123` | +| epic | `&123` | `group1/subgroup&123` |   | +| 通过 ID 标签 | `~123` | `namespace/project~123` | `project~123` | +| 一词标签名称 | `~bug` | `namespace/project~bug` | `project~bug` | +| 多词标签名称 | `~"feature request"` | `namespace/project~"feature request"` | `project~"feature request"` | +| 范围标签按名称 | `~"priority::high"` | `namespace/project~"priority::high"` | `project~"priority::high"` | +| ID 项目里程碑 | `%123` | `namespace/project%123` | `project%123` | +| 一词里程碑 | `%v1.23` | `namespace/project%v1.23` | `project%v1.23` | +| 多词里程碑 | `%"release candidate"` | `namespace/project%"release candidate"` | `project%"release candidate"` | +| 具体提交 | `9ba12248` | `namespace/project@9ba12248` | `project@9ba12248` | +| 提交范围比较 | `9ba12248...b19a04f5` | `namespace/project@9ba12248...b19a04f5` | `project@9ba12248...b19a04f5` | +| 仓库文件参考 | `[README](doc/README)` |   |   | +| 存储库文件行参考 | `[README](doc/README#L13)` |   |   | + +除此之外,还可以识别和格式化指向某些对象的链接. 这些示例包括: + +* 对问题的评论: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234#note_101075757"` ,它将呈现为`#1234 (note1)` +* 问题设计标签: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234/designs"` ,该标签将显示为`#1234 (designs)` . +* 链接到各个设计: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234/designs/layout.png"` ,它将呈现为`#1234[layout.png]` . + +### Task lists[](#task-lists "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#task-lists) . + +您可以在支持 Markdown 的任何位置添加任务列表,但是如果它们处于问题,合并请求或注释中,则只能"单击"以切换它们. 在其他地方,您必须手动编辑 Markdown 以通过在方括号内添加或删除`x`来更改状态. + +要创建任务列表,请添加特殊格式的 Markdown 列表. 您可以使用无序列表或有序列表: + +``` +- [x] Completed task +- [ ] Incomplete task + - [ ] Sub-task 1 + - [x] Sub-task 2 + - [ ] Sub-task 3 + 1. [x] Completed task +1. [ ] Incomplete task + 1. [ ] Sub-task 1 + 1. [x] Sub-task 2 +``` + +* [x]完成的任务 +* []未完成的任务 + * []子任务 1 + * [x]子任务 2 + * []子任务 3 + +1. [x] Completed task +2. []未完成的任务 + 1. []子任务 1 + 2. [x]子任务 2 + +### Table of contents[](#table-of-contents "Permalink") + +通过在标记行`[[_TOC_]]`上添加标记,您可以将目录添加到 Markdown 文件,Wiki 页面或发布/合并请求描述中. 它将显示为链接到各种标题的无序列表. + +``` +This is an intro sentence to my Wiki page. + +[[_TOC_]] + +## My first heading + +First section content. + +## My second heading + +Second section content. +``` + +[![Preview of an auto-generated TOC in a Wiki](img/77707dedee5c3b669fd992a327698362.png)](img/markdown_toc_preview_v12_9.png) + +### Wiki-specific Markdown[](#wiki-specific-markdown "Permalink") + +以下示例显示了 Wiki 内部链接的行为. + +#### Wiki - direct page link[](#wiki---direct-page-link "Permalink") + +仅包含页面的子弹的链接将指向该页面, *位于 Wiki 的基本级别* . + +该代码段将链接到 Wiki 根目录下的`documentation`页面: + +``` +[Link to Documentation](documentation) +``` + +#### Wiki - direct file link[](#wiki---direct-file-link "Permalink") + +*相对于当前页面* ,带有文件扩展名的链接指向该文件. + +如果下面的代码段放在`/documentation/related`的页面上,它将链接到`/documentation/file.md` : + +``` +[Link to File](file.md) +``` + +#### Wiki - hierarchical link[](#wiki---hierarchical-link "Permalink") + +可以使用`./` , `../`来相对于当前 Wiki 页面构建链接. + +如果此代码段放在`/documentation/main`的页面上,它将链接到`/documentation/related` : + +``` +[Link to Related Page](./related) +``` + +如果此代码段放在`/documentation/related/content`的页面上,它将链接到`/documentation/main` : + +``` +[Link to Related Page](../main) +``` + +如果此代码段放在`/documentation/main`的页面上,它将链接到`/documentation/related.md` : + +``` +[Link to Related Page](./related.md) +``` + +如果此代码段放在`/documentation/related/content`的页面上,它将链接到`/documentation/main.md` : + +``` +[Link to Related Page](../main.md) +``` + +#### Wiki - root link[](#wiki---root-link "Permalink") + +以`/`开头的链接是相对于 Wiki 根目录的. + +该代码段链接到`/documentation` : + +``` +[Link to Related Page](/documentation) +``` + +该代码段链接到`/miscellaneous.md` : + +``` +[Link to Related Page](/miscellaneous.md) +``` + +### Embedding metrics in GitLab Flavored Markdown[](#embedding-metrics-in-gitlab-flavored-markdown "Permalink") + +公制图表可以嵌入到 GitLab 风味 Markdown 中. 有关更多详细信息,请参见[在 GitLab 风格的 Markdown 中嵌入度量标准](../user/project/integrations/prometheus.html#embedding-metric-charts-within-gitlab-flavored-markdown) . + +## Standard Markdown and extensions in GitLab[](#standard-markdown-and-extensions-in-gitlab "Permalink") + +所有标准 Markdown 格式均应在 GitLab 中按预期工作. 一些标准功能通过附加功能进行了扩展,而不会影响标准用法. 如果扩展了功能,则新选项将作为子节列出. + +### Blockquotes[](#blockquotes "Permalink") + +块引号是突出显示信息(如边注)的简便方法. 它是通过以`>`开头的 blockquote 行来生成的: + +``` +> Blockquotes are very handy to emulate reply text. +> This line is part of the same quote. + +Quote break. + > This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote. +``` + +> 块引用非常容易模拟回复文本. 该行是同一报价的一部分. + +报价中断. + +> 这是一条很长的行,当它换行时仍会被正确引用. 哦,男孩,让我们继续写作,以确保它足够长,可以实际包裹所有人. 哦,您可以*将* **Markdown**放入 blockquote 中. + +#### Multiline blockquote[](#multiline-blockquote "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#multiline-blockquote) . + +GFM 还支持`>>>`围起来的多行块引用,从而扩展了标准的 Markdown 标准: + +``` +>>> +If you paste a message from somewhere else + +that spans multiple lines, + +you can quote that without having to manually prepend `>` to every line! +>>> +``` + +> 如果您从其他地方粘贴消息 +> +> 跨越多行, +> +> 您可以引用它,而不必手动在每行前面加上`>` ! + +### Code spans and blocks[](#code-spans-and-blocks "Permalink") + +您可以轻松突出显示应视为代码而非简单文本的任何内容. + +简单的内联代码很容易用单个反引号```突出显示: + +``` +Inline `code` has `back-ticks around` it. +``` + +Inline `code` has `back-ticks around` it. + +* * * + +同样,整个代码块可以用三个反引号( ````` ),三个波浪号( `~~~` )或缩进 4 个或更多的空格来围起来,以实现较大代码体的相似效果. + +``` +```python def function(): + #indenting works just fine in the fenced code block + s = "Python code" + print s +``` Using 4 spaces + is like using + 3-backtick fences. +``` + +``` +~~~ +Tildes are OK too. +~~~ +``` + +上面的三个示例呈现为: + +``` +def function(): + #indenting works just fine in the fenced code block + s = "Python code" + print s +``` + +``` +Using 4 spaces +is like using +3-backtick fences. +``` + +``` +Tildes are OK too. +``` + +#### Colored code and syntax highlighting[](#colored-code-and-syntax-highlighting "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#colored-code-and-syntax-highlighting) . + +GitLab 使用[Rouge Ruby 库](http://rouge.jneen.net/)在代码块中突出显示了更加丰富多彩的语法. 有关支持的语言的列表,请访问[Rouge 项目 Wiki](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers) . 语法突出显示仅在代码块中受支持,因此在内联时无法突出显示代码. + +代码块由带有三个反引号( ````` )或三个波浪号( `~~~` )的行围起来,并在第一个围栏的末尾标识了语言: + +``` +```javascript var s = "JavaScript syntax highlighting"; +alert(s); +``` + +```python def function(): + #indenting works just fine in the fenced code block + s = "Python syntax highlighting" + print s +``` + +```ruby require 'redcarpet' +markdown = Redcarpet.new("Hello World!") +puts markdown.to_html +``` + +``` No language indicated, so no syntax highlighting. +s = "There is no highlighting for this." +But let's throw in a tag. +``` +``` + +上面的四个示例呈现为: + +``` +var s = "JavaScript syntax highlighting"; +alert(s); +``` + +``` +def function(): + #indenting works just fine in the fenced code block + s = "Python syntax highlighting" + print s +``` + +``` +require 'redcarpet' +markdown = Redcarpet.new("Hello World!") +puts markdown.to_html +``` + +``` +No language indicated, so no syntax highlighting. +s = "There is no highlighting for this." +But let's throw in a tag. +``` + +### Emphasis[](#emphasis "Permalink") + +在 Markdown 中有多种强调文本的方法. 您可以斜体,粗体,删除线,以及将这些强调样式结合在一起. + +Examples: + +``` +Emphasis, aka italics, with *asterisks* or _underscores_. + +Strong emphasis, aka bold, with double **asterisks** or __underscores__. + +Combined emphasis with **asterisks and _underscores_**. + +Strikethrough uses two tildes. ~~Scratch this.~~ +``` + +强调,又称斜体,带有*星号*或*下划线* . + +重点突出,又大胆,带有双星**号**或**下划线** . + +结合强调与**星号和*下划线*** . + +删除线使用两个波浪号. ~~抓这个.~~ + +**注意:**删除线不是 Markdown 核心标准的一部分,而是 GFM 的一部分. + +#### Multiple underscores in words and mid-word emphasis[](#multiple-underscores-in-words-and-mid-word-emphasis "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#multiple-underscores-in-words) . + +仅将单词的*一部分*斜体化通常是没有用的,尤其是当您要处理经常带有多个下划线的代码和名称时. 结果,GFM 通过忽略单词中的多个下划线来扩展了标准的 Markdown 标准,以更好地呈现讨论代码的 Markdown 文档: + +``` +perform_complicated_task + +do_this_and_do_that_and_another_thing + +but_emphasis is_desired _here_ +``` + +perform_complicated_task + +do_this_and_do_that_and_another_thing + +但是*在这里需要重点* + +* * * + +如果您只想强调单词的一部分,仍然可以使用星号来完成: + +``` +perform*complicated*task + +do*this*and*do*that*and*another thing +``` + +perform*complicated*task + +做*这个* , *做*那个*和*另一件事 + +### Footnotes[](#footnotes "Permalink") + +脚注会添加指向注释的链接,该链接将在 Markdown 文件的末尾呈现. + +要创建脚注,您既需要参考标记,又需要带有注释内容的单独行(文件中的任何地方). + +无论标签名称如何,参考标签的相对顺序都决定了呈现的编号. + +参考标记可以使用字母和其他字符. 在解决[此错误](https://gitlab.com/gitlab-org/gitlab/-/issues/24423)之前,请避免在脚注标签名称中使用小写`w`或下划线( `_` ). + +``` +A footnote reference tag looks like this: [^1] + +This reference tag is a mix of letters and numbers. [^footnote-42] + +[^1]: This is the text inside a footnote. + +[^footnote-42]: This is another footnote. +``` + +脚注参考标记如下所示: [1](#fn:1) + +此参考标记是字母和数字的组合. [2](#fn:footnote-42) + +### Headers[](#headers "Permalink") + +``` +# H1 +## H2 +### H3 +#### H4 +##### H5 +###### H6 + +Alternatively, for H1 and H2, an underline-ish style: + +Alt-H1 +====== +Alt-H2 +------ +``` + +#### Header IDs and links[](#header-ids-and-links "Permalink") + +GFM 扩展了标准 Markdown 标准,以便所有 Markdown 呈现的标头都自动获取 ID,可以将 ID 链接到该 ID,注释中除外. + +悬停时,将显示到这些 ID 的链接,从而可以更轻松地将链接复制到标头以在其他地方使用. + +根据以下规则从标头的内容生成 ID: + +1. 所有文本都将转换为小写. +2. 删除所有非单词文本(例如标点符号或 HTML). +3. 所有空格都将转换为连字符. +4. 连续的两个或多个连字符转换为 1. +5. If a header with the same ID has already been generated, a unique incrementing number is appended, starting at 1. + +Example: + +``` +# This header has spaces in it +## This header has a :thumbsup: in it +# This header has Unicode in it: 한글 +## This header has spaces in it +### This header has spaces in it +## This header has 3.5 in it (and parentheses) +``` + +将生成以下链接 ID: + +1. `this-header-has-spaces-in-it` +2. `this-header-has-a-in-it` +3. `this-header-has-unicode-in-it-한글` +4. `this-header-has-spaces-in-it-1` +5. `this-header-has-spaces-in-it-2` +6. `this-header-has-3-5-in-it-and-parentheses` + +请注意,表情符号处理是在生成标题 ID 之前进行的,因此表情符号将转换为图像,然后从 ID 中删除. + +### Horizontal Rule[](#horizontal-rule "Permalink") + +使用三个或多个连字符,星号或下划线来创建水平尺非常简单: + +``` +Three or more hyphens, + --- +asterisks, + *** +or underscores + +___ +``` + +### Images[](#images "Permalink") + +Examples: + +``` +Inline-style (hover to see title text): + +![alt text](img/markdown_logo.png "Title Text") + +Reference-style (hover to see title text): + +![alt text1][logo] + +[logo]: img/markdown_logo.png "Title Text" +``` + +Inline-style (hover to see title text): + +[![alt text](img/c5c16791538bd6838d6196a0b4ec5bb7.png "Title Text")](img/markdown_logo.png) + +参考样式(悬停以查看标题文本): + +[![alt text](img/c5c16791538bd6838d6196a0b4ec5bb7.png "Title Text")](img/markdown_logo.png) + +#### Videos[](#videos "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#videos) . + +链接到带有视频扩展名的文件的图像标签会自动转换为视频播放器. 有效的视频扩展名是`.mp4` , `.m4v` , `.mov` , `.webm`和`.ogv` : + +``` +Here's a sample video: + +![Sample Video](img/markdown_video.mp4) +``` + +这是一个示例视频: + +[![Sample Video](img/bf99e217a01388f7c11df39626ab9e22.png)](img/markdown_video.mp4) + +#### Audio[](#audio "Permalink") + +> 如果未正确呈现,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#audio) . + +与视频类似,带有音频扩展名的文件的链接标签会自动转换为音频播放器. 有效的音频扩展名是`.mp3` , `.oga` , `.ogg` , `.spx`和`.wav` : + +``` +Here's a sample audio clip: + +![Sample Audio](img/markdown_audio.mp3) +``` + +这是一个示例音频剪辑: + +[![Sample Audio](img/8095440bd29d634de897ae56f76a4969.png)](img/markdown_audio.mp3) + +### Inline HTML[](#inline-html "Permalink") + +> 要在第二个示例中[查看](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#inline-html)在 HTML 中呈现的 Markdown,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#inline-html) . + +您还可以在 Markdown 中使用原始 HTML,通常效果很好. + +有关允许的 HTML 标记和属性的列表,请参见 HTML :: Pipeline 的[SanitizationFilter](https://github.com/jch/html-pipeline/blob/v2.12.3/lib/html/pipeline/sanitization_filter.rb#L42)类的文档. 除了默认`SanitizationFilter`允许列表,GitLab 允许`span` , `abbr` , `details`和`summary`元素. + +``` +
      +
      Definition list
      +
      Is something people use sometimes.
      + +
      Markdown in HTML
      +
      Does *not* work **very** well. HTML tags will work, in most cases.
      +
      +``` + +Definition list + +人们有时会用到的东西. + +Markdown in HTML + +*不是*很好**. HTML *标签*将工作 ,在大多数情况下. + +* * * + +仍然可以在 HTML 标记内使用 Markdown,但前提是包含 Markdown 的行分为各自的行: + +``` +
      +
      Markdown in HTML
      +
      Does *not* work **very** well. HTML tags will work, in most cases.
      + +
      Markdown in HTML
      +
      + + Does *not* work **very** well. HTML tags will work, in most cases. + +
      +
      +``` + +Markdown in HTML + +*不是*很好**. HTML 标记在大多数情况下都可以使用. + +Markdown in HTML + +*不能* 很好地工作. HTML 标记在大多数情况下都可以使用. + +#### Details and summary[](#details-and-summary "Permalink") + +> 要在第二个示例中[查看](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#details-and-summary)在 HTML 中呈现的 Markdown,请[在 GitLab 本身中查看它](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#details-and-summary) . + +可以使用 HTML 的[`
      `](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/HTML/Element/details)和[``](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/HTML/Element/summary)标记折叠内容. 这对于折叠长日志特别有用,因为它们占用更少的屏幕空间. + +``` +

      +

      +Click this to collapse/fold. + +These details will remain hidden until expanded. + +
      PASTE LOGS HERE
      + +
      +

      +``` + +
      单击以折叠/折叠. 这些细节*将*保持**隐藏,**直到扩展. + +``` + PASTE LOGS HERE +```
      + +* * * + +这些标记内的 Markdown 也受支持. + +**注意:**如果 Markdown 无法正确呈现,请尝试在页面顶部添加`{::options parse_block_html="true" /}` ,然后将`markdown="span"`添加到开头的摘要标记中,如下所示: `` . + +请记住,在``标记之后和`
      `标记之前留空行,如示例所示: + +``` +
      +Click this to collapse/fold. + +These details _will_ remain **hidden** until expanded. + +``` +PASTE LOGS HERE +``` + +
      +``` + +
      单击以折叠/折叠. 这些细节*将*保持隐藏,直到扩展. + +``` + PASTE LOGS HERE +```
      + +### Line breaks[](#line-breaks "Permalink") + +如果先前的文本以两个换行符结尾,则会插入一个换行符(将开始一个新的段落),例如当您连续两次按`Enter 键`时. 如果仅使用一个换行符( `按`一次`Enter 键` ),则下一个句子将成为同一段落的一部分. 如果要避免长行换行并使它们易于编辑,这很有用: + +``` +Here's a line for us to start with. + +This longer line is separated from the one above by two newlines, so it will be a *separate paragraph*. + +This line is also a separate paragraph, but... +These lines are only separated by single newlines, +so they *do not break* and just follow the previous lines +in the *same paragraph*. +``` + +这是我们要开始的一行. + +该较长的行与上面的一行由两个换行符*隔开* ,因此它将是一个*单独的段落* . + +该行也是一个单独的段落,但是…这些行仅由单个换行符分隔,因此它们*不会中断*并且仅遵循*同一段落中*的前几行. + +#### Newlines[](#newlines "Permalink") + +GFM 在[处理段落和换行符方面](https://spec.commonmark.org/current/)遵循 Markdown 规范. + +段落是一个或多个连续的文本行,由一个或多个空行分隔(第一段末尾有两个新行), [如上所述](#line-breaks) . + +如果您需要对换行符或换行符进行更多控制,则可以通过以反斜杠或两个或多个空格结束一行来添加单个换行符. 连续两个换行符将创建一个新的段落,中间有一个空行: + +``` +First paragraph. +Another line in the same paragraph. +A third line in the same paragraph, but this time ending with two spaces.{space}{space} +A new line directly under the first paragraph. + +Second paragraph. +Another line, this time ending with a backslash.\ +A new line due to the previous backslash. +``` + +### Links[](#links "Permalink") + +有两种创建链接的方法,即内联样式和引用样式: + +``` +- This is an [inline-style link](https://www.google.com) +- This is a [link to a repository file in the same directory](index.md) +- This is a [relative link to a readme one directory higher](../README.md) +- This is a [link that also has title text](https://www.google.com "This link takes you to Google!") + +Using header ID anchors: + +- This links to [a section on a different Markdown page, using a "#" and the header ID](index.md#overview) +- This links to [a different section on the same page, using a "#" and the header ID](#header-ids-and-links) + +Using references: + +- This is a [reference-style link, see below][Arbitrary case-insensitive reference text] +- You can [use numbers for reference-style link definitions, see below][1] +- Or leave it empty and use the [link text itself][], see below. + +Some text to show that the reference links can follow later. + +[arbitrary case-insensitive reference text]: https://www.mozilla.org/en-US/ +[1]: https://slashdot.org +[link text itself]: https://www.reddit.com +``` + +* 这是一个[内联样式的链接](https://www.google.com) +* 这是[指向同一目录中存储库文件](index.html)的[链接](index.html) +* 这是[指向自述文件的上一级目录](../README.html)的[相对链接](../README.html) +* 这是一个[也有标题文字](https://www.google.com "此链接将您带到 Google!")的[链接](https://www.google.com "此链接将您带到 Google!") + +使用标头 ID 锚点: + +* 该链接[使用"#"和标题 ID](index.html#overview)链接到[另一个 Markdown 页面上的部分](index.html#overview) +* 这[使用"#"和标题 ID](#header-ids-and-links)链接到[同一页面上的不同部分.](#header-ids-and-links) + +使用参考: + +* 这是[参考样式的链接,请参见下文](https://www.mozilla.org/en-US/) +* 您可以[将数字用于引用样式的链接定义,请参见下文](https://slashdot.org) +* 或将其保留为空,并使用[链接文本本身](https://www.reddit.com) ,请参见下文. + +一些文本表明参考链接可以在以后使用. + +**注意:**相对链接不允许引用 Wiki 页面或项目文件中的 Wiki 页面中的项目文件. 这样做的原因是,Wiki 始终位于 GitLab 中的单独 Git 存储库中. 例如,仅当链接位于 Wiki Markdown 文件内部时, `[I'm a reference-style link](style)`才会将链接指向`wikis/style` . + +#### URL auto-linking[](#url-auto-linking "Permalink") + +GFM will auto-link almost any URL you put into your text: + +``` +- https://www.google.com +- https://www.google.com +- ftp://ftp.us.debian.org/debian/ +- smb://foo/bar/baz +- irc://irc.freenode.net/ +- http://localhost:3000 +``` + +* [https://www.google.com](https://www.google.com) +* [https://www.google.com](https://www.google.com) +* [ftp://ftp.us.debian.org/debian/](ftp://ftp.us.debian.org/debian/) +* +* +* [http://localhost:3000](http://localhost:3000) + +### Lists[](#lists "Permalink") + +可以轻松创建有序列表和无序列表. + +对于有序列表,请在有序列表的每一行的开头添加希望列表以其开头的数字,例如`1.` ,后跟一个空格. 在第一个数字之后,使用什么数字都没有关系,有序列表将按垂直顺序自动编号,因此对同一列表中的所有项目重复`1.` .. 如果你开始以外的其他数字`1.` ,它会用它作为第一个数字,并从那里计数. + +Examples: + +``` +1. First ordered list item +2. Another item + - Unordered sub-list. +1. Actual numbers don't matter, just that it's a number + 1. Ordered sub-list + 1. Next ordered sub-list item +4. And another item. +``` + +1. 首先订购的清单项目 +2. 另一个项目 + * 无序子列表. +3. 实际数字并不重要,只是一个数字 + 1. 订购子清单 + 2. 下一个订购的子清单项目 +4. 还有另一个项目. + +对于无序列表,请在无序列表的每一行的开头添加`-` , `*`或`+` ,然后加上一个空格,但是您不能混合使用它们. + +``` +Unordered lists can: + - use +- minuses + +They can also: + * use +* asterisks + +They can even: + + use ++ pluses +``` + +无序列表可以: + +* use +* minuses + +他们还可以: + +* use +* asterisks + +They can even: + +* use +* pluses + +* * * + +如果列表项包含多个段落,则每个后续段落都应缩进到与列表项文本开头相同的级别. + +Example: + +``` +1. First ordered list item + + Second paragraph of first item. + 1. Another item +``` + +1. 首先订购的清单项目 + + 第一项第二段. + +2. Another item + +* * * + +如果第一项的段落没有缩进适当的空格数,则该段落将出现在列表外部,而不是在列表项下方正确缩进. + +Example: + +``` +1. First ordered list item + + Paragraph of first item. + 1. Another item +``` + +1. 首先订购的清单项目 + +第一项的段落. + +1. 另一个项目 + +### Superscripts / Subscripts[](#superscripts--subscripts "Permalink") + +当前,CommonMark 和 GFM 不支持 Redcarpet 支持的上标语法( `x^2` ). 您可以对上标和下标使用标准的 HTML 语法: + +``` +The formula for water is H2O +while the equation for the theory of relativity is E = mc2. +``` + +水的公式为 H 2 O,而相对论的公式为 E = mc 2 . + +### Tables[](#tables "Permalink") + +表不是 Markdown 核心规范的一部分,但它们是 GFM 的一部分. + +1. 第一行包含标头,并用"竖线"( `|` )分隔. +2. 第二行将标题与单元格分开,并且必须包含三个或更多破折号. +3. 第三行以及随后的任何行均包含单元格值. + * 您**不能**在 Markdown 中将单元格分隔成多行,它们必须保持为单行,但它们可能会很长. 如果需要,还可以包含 HTML `
      `标记以强制换行. + * 像元大小**不必**彼此匹配. 它们很灵活,但必须用管道( `|` )分隔. + * 您**可以**有空白单元格. + +Example: + +``` +| header 1 | header 2 | header 3 | +| --- | ------ |---------:| +| cell 1 | cell 2 | cell 3 | +| cell 4 | cell 5 is longer | cell 6 is much longer than the others, but that's ok. It will eventually wrap the text when the cell is too large for the display size. | +| cell 7 | | cell
      9 | +``` + +| 标题 1 | 标头 2 | 标头 3 | +| --- | --- | --- | +| 单元格 1 | 单元格 2 | 单元格 3 | +| 单元格 4 | 单元格 5 更长 | 单元格 6 比其他单元格长得多,但这没关系. 当单元格太大而无法显示时,它将最终包裹文本. | +| 单元格 7 |   | cell +9 | + +(另外,你可以通过添加冒号选择文本列中的对齐`:`第二行中的"破折号"线条的两侧). 这将影响列中的每个单元格. + +**注意:** [在 GitLab 本身中](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#tables) ,标题始终在 Chrome 和 Firefox 中左对齐,并在 Safari 中居中. + +``` +| Left Aligned | Centered | Right Aligned | Left Aligned | Centered | Right Aligned | +| :--- | :---: | ---: | :----------- | :------: | ------------: | +| Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | +| Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | +``` + +| 左对齐 | Centered | 右对齐 | 左对齐 | Centered | 右对齐 | +| --- | --- | --- | --- | --- | --- | +| 单元格 1 | 单元格 2 | 单元格 3 | 单元格 4 | 单元格 5 | 单元格 6 | +| 单元格 7 | 单元格 8 | 单元格 9 | 单元格 10 | 单元格 11 | 单元格 12 | + +#### Copy from spreadsheet and paste in Markdown[](#copy-from-spreadsheet-and-paste-in-markdown "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/27205) . + +如果您使用电子表格软件(例如 Microsoft Excel,Google 表格或 Apple Numbers),则可以从电子表格中进行复制,GitLab 会将其粘贴为 Markdown 表. 例如,假设您具有以下电子表格: + +[![Copy from spreadsheet](img/c2f9cb2f2c88244b3dbf094572214a02.png)](img/markdown_copy_from_spreadsheet_v12_7.png) + +选择单元格并将其复制到剪贴板. 打开一个 GitLab Markdown 条目并粘贴电子表格: + +[![Paste to Markdown table](img/56c21932bdeb67b5407d18238e8ec7f3.png)](img/markdown_paste_table_v12_7.png) + +## References[](#references "Permalink") + +* 该文档从[Markdown-Cheatsheet 中](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)大量利用. +* Daring Fireball 上的原始[Markdown 语法指南](https://daringfireball.net/projects/markdown/syntax)是详细解释标准 Markdown 的绝佳资源. +* 有关 CommonMark 的详细规范,请参见[CommonMark 规范.](https://spec.commonmark.org/current/) +* [CommonMark Dingus](http://try.commonmark.org)是用于测试 CommonMark 语法的便捷工具. + +1. 这是脚注中的文本. [↩](#fnref:1) + +2. 这是另一个脚注. [↩](#fnref:footnote-42) \ No newline at end of file diff --git a/docs/409.md b/docs/409.md new file mode 100644 index 0000000000000000000000000000000000000000..cadc95682467e24fb8b5ed711168ac376f8ccad5 --- /dev/null +++ b/docs/409.md @@ -0,0 +1,409 @@ +# AsciiDoc + +> 原文:[https://docs.gitlab.com/ee/user/asciidoc.html](https://docs.gitlab.com/ee/user/asciidoc.html) + +* [Syntax](#syntax) + * [Paragraphs](#paragraphs) + * [Text Formatting](#text-formatting) + * [Attributes](#attributes) + * [Links](#links) + * [Anchors](#anchors) + * [Lists](#lists) + * [Unordered](#unordered) + * [Ordered](#ordered) + * [Checklist](#checklist) + * [Callout](#callout) + * [Description](#description) + * [Document Structure](#document-structure) + * [Header](#header) + * [Sections](#sections) + * [Includes](#includes) + * [Blocks](#blocks) + * [Tables](#tables) + * [Multimedia](#multimedia) + * [Breaks](#breaks) + +# AsciiDoc[](#asciidoc "Permalink") + +GitLab 使用[Asciidoctor](https://asciidoctor.org) gem 将 AsciiDoc 内容转换为 HTML5\. 有关完整的 Asciidoctor 参考,请查阅《 [Asciidoctor 用户手册](https://asciidoctor.org/docs/user-manual/) 》. + +## Syntax[](#syntax "Permalink") + +这是最常用的 AsciiDoc 语法的简要参考. 您可以在[https://asciidoctor.org/docs/上](https://asciidoctor.org/docs/)找到有关 AsciiDoc 语法的完整文档. + +### Paragraphs[](#paragraphs "Permalink") + +``` +A normal paragraph. +Line breaks are not preserved. +``` + +跳过以`//`开头的行注释: + +``` +// this is a comment +``` + +空白行分隔段落. + +带有`[%hardbreaks]`选项的段落将保留换行符: + +``` +[%hardbreaks] +This paragraph carries the `hardbreaks` option. +Notice how line breaks are now preserved. +``` + +缩进(文字)段落会禁用文本格式,保留空格和换行符,并以等宽字体显示: + +``` + This literal paragraph is indented with one space. + As a consequence, *text formatting*, spaces, + and lines breaks will be preserved. +``` + +一条警告段落引起了读者的注意: + +``` +NOTE: This is a brief reference, please read the full documentation at https://asciidoctor.org/docs/. + +TIP: Lists can be indented. Leading whitespace is not significant. +``` + +### Text Formatting[](#text-formatting "Permalink") + +**受约束的(应用于单词边界)** + +``` +*strong importance* (aka bold) +_stress emphasis_ (aka italic) +`monospaced` (aka typewriter text) +"`double`" and '`single`' typographic quotes ++passthrough text+ (substitutions disabled) +`+literal text+` (monospaced with substitutions disabled) +``` + +**不受限制(适用于任何地方)** + +``` +**C**reate+**R**ead+**U**pdate+**D**elete +fan__freakin__tastic +``mono``culture +``` + +**Replacements** + +``` +A long time ago in a galaxy far, far away... +(C) 1976 Arty Artisan +I believe I shall--no, actually I won't. +``` + +**Macros** + +``` +// where c=specialchars, q=quotes, a=attributes, r=replacements, m=macros, p=post_replacements, etc. +The European icon:flag[role=blue] is blue & contains pass:[************] arranged in a icon:circle-o[role=yellow]. +The pass:c[->] operator is often referred to as the stabby lambda. +Since `pass:[++]` has strong priority in AsciiDoc, you can rewrite pass:c,a,r[C++ => C{pp}]. +// activate stem support by adding `:stem:` to the document header +stem:[sqrt(4) = 2] +``` + +### Attributes[](#attributes "Permalink") + +**用户定义的属性** + +``` +// define attributes in the document header +:name: value +``` + +``` +:url-gem: https://rubygems.org/gems/asciidoctor + +You can download and install Asciidoctor {asciidoctor-version} from {url-gem}. +C{pp} is not required, only Ruby. +Use a leading backslash to output a word enclosed in curly braces, like \{name}. +``` + +**环境属性** + +GitLab 设置以下环境属性: + +| Attribute | Description | +| --- | --- | +| `docname` | 源文档的根名称(无前导路径或文件扩展名). | +| `outfilesuffix` | 对应于后端输出的文件扩展名(默认为`.adoc`以使文档间的交叉引用起作用). | + +### Links[](#links "Permalink") + +``` +https://example.org/page[A webpage] +link:../path/to/file.txt[A local file] +xref:document.adoc[A sibling document] +mailto:hello@example.org[Email to say hello!] +``` + +### Anchors[](#anchors "Permalink") + +``` +[[idname,reference text]] +// or written using normal block attributes as `[#idname,reftext=reference text]` +A paragraph (or any block) with an anchor (aka ID) and reftext. + +See <> or <>. + +xref:document.adoc#idname[Jumps to anchor in another document]. + +This paragraph has a footnote.footnote:[This is the text of the footnote.] +``` + +### Lists[](#lists "Permalink") + +#### Unordered[](#unordered "Permalink") + +``` +* level 1 +** level 2 +*** level 3 +**** level 4 +***** etc. +* back at level 1 ++ +Attach a block or paragraph to a list item using a list continuation (which you can enclose in an open block). + +.Some Authors +[circle] +- Edgar Allen Poe +- Sheri S. Tepper +- Bill Bryson +``` + +#### Ordered[](#ordered "Permalink") + +``` +. Step 1 +. Step 2 +.. Step 2a +.. Step 2b +. Step 3 + +.Remember your Roman numerals? +[upperroman] +. is one +. is two +. is three +``` + +#### Checklist[](#checklist "Permalink") + +``` +* [x] checked +* [ ] not checked +``` + +#### Callout[](#callout "Permalink") + +``` +// enable callout bubbles by adding `:icons: font` to the document header +[,ruby] +---- +puts 'Hello, World!' # <1> +---- +<1> Prints `Hello, World!` to the console. +``` + +#### Description[](#description "Permalink") + +``` +first term:: description of first term +second term:: +description of second term +``` + +### Document Structure[](#document-structure "Permalink") + +#### Header[](#header "Permalink") + +``` += Document Title +Author Name +v1.0, 2019-01-01 +``` + +#### Sections[](#sections "Permalink") + +``` += Document Title (Level 0) +== Level 1 +=== Level 2 +==== Level 3 +===== Level 4 +====== Level 5 +== Back at Level 1 +``` + +#### Includes[](#includes "Permalink") + +``` +include::basics.adoc[] + +// define -a allow-uri-read to allow content to be read from URI +include::https://example.org/installation.adoc[] +``` + +为了保证良好的系统性能并防止恶意文档引起问题,GitLab 对任何一个文档中处理的 include 指令的数量实施了**最大限制** . 当前总共可以包含 32 个文档,其中包括传递依赖项. + +### Blocks[](#blocks "Permalink") + +``` +-- +open - a general-purpose content wrapper; useful for enclosing content to attach to a list item +-- +``` + +``` +// recognized types include CAUTION, IMPORTANT, NOTE, TIP, and WARNING +// enable admonition icons by setting `:icons: font` in the document header +[NOTE] +==== +admonition - a notice for the reader, ranging in severity from a tip to an alert +==== +``` + +``` +==== +example - a demonstration of the concept being documented +==== +``` + +``` +.Toggle Me +[%collapsible] +==== +collapsible - these details are revealed by clicking the title +==== +``` + +``` +**** +sidebar - auxiliary content that can be read independently of the main content +**** +``` + +``` +.... +literal - an exhibit that features program output +.... +``` + +``` +---- +listing - an exhibit that features program input, source code, or the contents of a file +---- +``` + +``` +[,language] +---- +source - a listing that is embellished with (colorized) syntax highlighting +---- +``` + +``` +\```language +fenced code - a shorthand syntax for the source block +\``` +``` + +``` +[,attribution,citetitle] +____ +quote - a quotation or excerpt; attribution with title of source are optional +____ +``` + +``` +[verse,attribution,citetitle] +____ +verse - a literary excerpt, often a poem; attribution with title of source are optional +____ +``` + +``` +++++ +pass - content passed directly to the output document; often raw HTML +++++ +``` + +``` +// activate stem support by adding `:stem:` to the document header +[stem] +++++ +x = y^2 +++++ +``` + +``` +//// +comment - content which is not included in the output document +//// +``` + +### Tables[](#tables "Permalink") + +``` +.Table Attributes +[cols=>1h;2d,width=50%,frame=topbot] +|=== +| Attribute Name | Values + +| options +| header,footer,autowidth + +| cols +| colspec[;colspec;...] + +| grid +| all \| cols \| rows \| none + +| frame +| all \| sides \| topbot \| none + +| stripes +| all \| even \| odd \| none + +| width +| (0%..100%) + +| format +| psv {vbar} csv {vbar} dsv +|=== +``` + +### Multimedia[](#multimedia "Permalink") + +``` +image::screenshot.png[block image,800,450] + +Press image:reload.svg[reload,16,opts=interactive] to reload the page. + +video::movie.mp4[width=640,start=60,end=140,options=autoplay] + +video::aHjpOzsQ9YI[youtube] + +video::300817511[vimeo] +``` + +### Breaks[](#breaks "Permalink") + +``` +// thematic break (aka horizontal rule) +--- +``` + +``` +// page break +<<< +``` \ No newline at end of file diff --git a/docs/410.md b/docs/410.md new file mode 100644 index 0000000000000000000000000000000000000000..58aedae74fa6e76313dd6e7c1f74796da7c7399a --- /dev/null +++ b/docs/410.md @@ -0,0 +1,243 @@ +# GitLab Notification Emails + +> 原文:[https://docs.gitlab.com/ee/user/profile/notifications.html](https://docs.gitlab.com/ee/user/profile/notifications.html) + +* [Receiving notifications](#receiving-notifications) +* [Tuning your notifications](#tuning-your-notifications) + * [Editing notification settings](#editing-notification-settings) +* [Global notification settings](#global-notification-settings) + * [Notification scope](#notification-scope) + * [Project notifications](#project-notifications) + * [Group notifications](#group-notifications) + * [Group notification level](#group-notification-level) + * [Group notification email address](#group-notification-email-address) + * [Notification levels](#notification-levels) +* [Notification events](#notification-events) +* [Issue / Epics / Merge request events](#issue--epics--merge-request-events) +* [Filtering email](#filtering-email) + * [X-GitLab-NotificationReason](#x-gitlab-notificationreason) + +# GitLab Notification Emails[](#gitlab-notification-emails "Permalink") + +GitLab 通知使您可以随时了解 GitLab 中发生的事情. 启用通知后,您可以接收有关问题,合并请求和史诗活动的更新. 通知通过电子邮件发送. + +## Receiving notifications[](#receiving-notifications "Permalink") + +您将由于以下原因之一收到通知: + +* 您参与发行,合并请求或史诗. 在这种情况下, *参与*意味着评论或编辑. +* You enable notifications in an issue, merge request, or epic. To enable notifications, click the **Notifications** toggle in the sidebar to *on*. + +启用通知后,您将收到有关该问题,合并请求或史诗中发生的操作的通知. + +**注意:**通知可能会被管理员阻止,从而阻止发送通知. + +## Tuning your notifications[](#tuning-your-notifications "Permalink") + +通知的数量可能是巨大的. GitLab 允许您调整收到的通知. 例如,您可能希望收到有关特定项目中所有活动的通知,而对于其他项目,仅当您的名字被提及时才得到通知. + +您可以通过组合通知设置来调整收到的通知: + +* [Global notification settings](#global-notification-settings) +* [Notification scope](#notification-scope) +* [Notification levels](#notification-levels) + +### Editing notification settings[](#editing-notification-settings "Permalink") + +编辑通知设置: + +1. 点击您的个人资料图片,然后选择**设置** . +2. 点击左侧边栏中的**通知** . +3. 编辑所需的通知设置. 编辑的设置将自动保存并启用. + +这些通知设置仅适用于您. 它们不会影响同一项目或组中其他任何人收到的通知. + +[![notification settings](img/81fe297de1dccaedd3340735454273bc.png)](img/notification_global_settings.png) + +## Global notification settings[](#global-notification-settings "Permalink") + +**全局通知设置**是默认设置,除非您为项目或组选择不同的值. + +* 通知电子邮件 + * 这是您的通知将发送到的电子邮件地址. +* 全局通知级别 + * 这是适用于所有通知的默认[通知级别](#notification-levels) . +* 接收有关您自己的活动的通知. + * 如果您想接收有关自己活动的通知,请选中此复选框. 默认值:未选中. + +### Notification scope[](#notification-scope "Permalink") + +您可以通过为每个项目和组选择不同的通知级别来调整通知的范围. + +通知范围按优先级顺序应用(从高到低): + +* Project + * 对于每个项目,您可以选择一个通知级别. 您的项目设置将覆盖组设置. +* Group + * 对于每个组,您可以选择一个通知级别. 您的群组设置会覆盖您的默认设置. +* 全局(默认) + * 如果尚未为发生活动的项目或组选择通知级别,则将应用全局或*默认*通知级别. + +#### Project notifications[](#project-notifications "Permalink") + +您可以为每个项目选择一个通知级别. 如果您需要密切监视选定项目中的活动,这将很有用. + +[![notification settings](img/bab81ba0a915cec8b039166d2defc074.png)](img/notification_project_settings_v12_8.png) + +要为项目选择通知级别,请使用以下两种方法之一: + +1. 点击您的个人资料图片,然后选择**设置** . +2. 点击左侧边栏中的**通知** . +3. 在" **项目"**部分中找到该项目. +4. 选择所需的[通知级别](#notification-levels) . + +Or: + +1. 导航到项目页面. +2. 单击带有下拉图标的通知下拉列表. +3. 选择所需的[通知级别](#notification-levels) . + +有关如何在有新版本发布时通知的演示,请参阅[发布通知](https://www.youtube.com/watch?v=qyeNkGgqmH4) . + +#### Group notifications[](#group-notifications "Permalink") + +您可以为每个组选择通知级别和电子邮件地址. + +[![notification settings](img/c39dc466882289b42ad827dbbc05b39f.png)](img/notification_group_settings_v12_8.png) + +##### Group notification level[](#group-notification-level "Permalink") + +要为组选择通知级别,请使用以下两种方法之一: + +1. 点击您的个人资料图片,然后选择**设置** . +2. 点击左侧边栏中的**通知** . +3. 在" **组"**部分中找到该项目. +4. 选择所需的[通知级别](#notification-levels) . + +* * * + +1. 导航到组的页面. +2. 单击带有下拉图标的通知下拉列表. +3. 选择所需的[通知级别](#notification-levels) . + +##### Group notification email address[](#group-notification-email-address "Permalink") + +在 GitLab 12.0 中引入 + +您可以选择一个电子邮件地址,以接收您所属的每个组的通知. 例如,如果您是自由职业者,并且希望将有关客户项目的电子邮件分开存放,这可能会很有用. + +1. 点击您的个人资料图片,然后选择**设置** . +2. 点击左侧边栏中的**通知** . +3. 在" **组"**部分中找到该项目. +4. 选择所需的电子邮件地址. + +### Notification levels[](#notification-levels "Permalink") + +对于每个项目和组,您可以选择以下级别之一: + +| Level | Description | +| --- | --- | +| Global | 您的全局设置适用. | +| Watch | 接收任何活动的通知. | +| 提一下 | `@mentioned`在评论中`@mentioned`接收通知. | +| Participate | 接收有关您参与的线程的通知. | +| Disabled | 关闭通知. | +| Custom | 接收有关自定义选定事件的通知. | + +## Notification events[](#notification-events "Permalink") + +将通知用户以下事件: + +| Event | 发给 | 设定等级 | +| --- | --- | --- | +| 添加了新的 SSH 密钥 | User | 安全电子邮件,始终发送. | +| 添加了新电子邮件 | User | 安全电子邮件,始终发送. | +| 电邮已变更 | User | 安全电子邮件,始终发送. | +| 密码已更改 | User | 安全电子邮件,始终发送. | +| 新用户创建 | User | 在创建用户时发送,但 OmniAuth(LDAP)除外 | +| 用户已添加到项目 | User | 将用户添加到项目时发送 | +| 项目访问权限级别已更改 | User | 更改用户项目访问级别时发送 | +| 用户已添加到组 | User | 将用户添加到组时发送 | +| 群组访问权限级别已更改 | User | 更改用户组访问级别时发送 | +| 项目已移 | 项目成员(1) | (1)不禁用 | +| 新品发布 | 项目成员 | 自定义通知 | + +## Issue / Epics / Merge request events[](#issue--epics--merge-request-events "Permalink") + +在以下大多数情况下,通知将发送到: + +* Participants: + * 发行/合并请求的作者和受让人 + * 关于问题/合并请求的评论的作者 + * `@username`在问题,合并请求或史诗的标题或描述中提到的任何人 + * `@username`在有关问题,合并请求或史诗的任何评论中提及的"参与"或更高通知级别的任何人 +* 观察者:通知级别为"观察"的用户 +* 订阅者:手动订阅问题,合并请求或史诗的任何人 +* 自定义:通知级别为"自定义"的用户针对下表中显示的任何事件打开了通知 + +**注意:**为了最大程度地减少不需要任何操作的通知的数量,从[GitLab 12.9 起](https://gitlab.com/gitlab-org/gitlab/-/issues/616) ,不再为项目中的所有活动通知合格的批准者. 要接收它们,他们必须将其用户通知设置更改为" **观看"** . + +| Event | 发给 | +| --- | --- | +| 新问题 |   | +| 结束期 |   | +| 重新分配问题 | 以上,加上旧的受让人 | +| 重新打开问题 |   | +| 到期问题 | 选择此事件的参与者和自定义通知级别 | +| 更改里程碑问题 | 选择了此事件的订户,提及的参与者和自定义通知级别 | +| 消除里程碑问题 | 选择了此事件的订户,提及的参与者和自定义通知级别 | +| 新合并请求 |   | +| 推送合并请求 | 选择此事件的参与者和自定义通知级别 | +| 重新分配合并请求 | 以上,加上旧的受让人 | +| 关闭合并请求 |   | +| 重新打开合并请求 |   | +| 合并合并请求 |   | +| 更改里程碑合并请求 | 选择了此事件的订户,提及的参与者和自定义通知级别 | +| 删除里程碑合并请求 | 选择了此事件的订户,提及的参与者和自定义通知级别 | +| 新评论 | 以上内容,加上评论中`@username`提及的任何人,通知级别为"提及"或更高 | +| 管道失败 | 管道的作者 | +| 固定管道 | 管道的作者. 默认启用. 在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/24309) . 管理员可以使用`ci_pipeline_fixed_notifications` [功能标记](../../administration/feature_flags.html)禁用此通知选项. | +| 成功的管道 | 管道的作者(如果他们具有成功管道的自定义通知设置). 如果管道先前失败,则将为失败后的第一个成功管道发送`Fixed pipeline`消息,然后为任何进一步成功的管道发送`Successful pipeline`消息. | +| 新史诗 |   | +| 接近史诗 |   | +| 重新开启史诗 |   | + +此外,如果发布或合并请求的标题或描述发生了更改,则通知将通过`@username`发送到任何**新**提及的内容,就像在原始文本中提到的一样. + +您不会收到有关您自己创建的问题,合并请求或里程碑的通知(除非由于问题而定). 仅当其他人对您创建或提及的内容进行评论或添加更改时,您才会收到自动通知. + +如果开放的合并请求由于冲突而变得不可合并,则将通知其原因. 如果用户还将合并请求设置为一旦管道成功就自动合并,则该用户也会收到通知. + +## Filtering email[](#filtering-email "Permalink") + +通知电子邮件包括特定于 GitLab 的标题. 您可以根据这些标头的内容过滤通知电子邮件,以更好地管理您的通知. 例如,您可以过滤特定项目的所有电子邮件,在该项目中您将被分配合并请求或问题. + +下表列出了所有特定于 GitLab 的电子邮件标题: + +| Header | Description | +| --- | --- | +| `X-GitLab-Group-Id` | 组的 ID. 仅在史诗的通知电子邮件中显示. | +| `X-GitLab-Group-Path` | 组的路径. 仅在史诗的通知电子邮件中显示. | +| `X-GitLab-Project` | 通知所属的项目的名称. | +| `X-GitLab-Project-Id` | 项目的 ID. | +| `X-GitLab-Project-Path` | 项目的路径. | +| `X-GitLab-(Resource)-ID` | 通知所针对的资源的 ID. 该资源例如可以是`Issue` , `MergeRequest` , `Commit`或其他此类资源. | +| `X-GitLab-Discussion-ID` | 注释所属的线程的 ID,用于注释的通知电子邮件中. | +| `X-GitLab-Pipeline-Id` | 通知所针对的管道的 ID,在管道的通知电子邮件中. | +| `X-GitLab-Reply-Key` | 支持通过电子邮件回复的唯一令牌. | +| `X-GitLab-NotificationReason` | 通知原因. 可以`mentioned` , `assigned`或`own_activity` . | +| `List-Id` | The path of the project in an RFC 2919 mailing list identifier. This is useful for email organization with filters, for example. | + +### X-GitLab-NotificationReason[](#x-gitlab-notificationreason "Permalink") + +`X-GitLab-NotificationReason`标头包含`X-GitLab-NotificationReason`的原因. 该值是按优先级顺序的以下值之一: + +* `own_activity` +* `assigned` +* `mentioned` + +通知的原因也包含在通知电子邮件的页脚中. 例如有原因的电子邮件`assigned`都会有这句话的注脚: + +* `You are receiving this email because you have been assigned an item on .` + +**注意:**正在考虑将其他事件的通知包含在`X-GitLab-NotificationReason`标头中. 有关详细信息,请参见此[相关问题](https://gitlab.com/gitlab-org/gitlab/-/issues/20689) . \ No newline at end of file diff --git a/docs/411.md b/docs/411.md new file mode 100644 index 0000000000000000000000000000000000000000..240ac323635d29bc6e1542eb7c9eb6dac0a39072 --- /dev/null +++ b/docs/411.md @@ -0,0 +1,106 @@ +# GitLab Quick Actions + +> 原文:[https://docs.gitlab.com/ee/user/project/quick_actions.html](https://docs.gitlab.com/ee/user/project/quick_actions.html) + +* [Quick Actions for issues, merge requests and epics](#quick-actions-for-issues-merge-requests-and-epics) +* [Autocomplete characters](#autocomplete-characters) +* [Quick actions parameters](#quick-actions-parameters) +* [Quick actions for commit messages](#quick-actions-for-commit-messages) + +# GitLab Quick Actions[](#gitlab-quick-actions "Permalink") + +版本历史 + +* 在[GitLab 12.1 中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26672)引入:一旦执行了一项操作,成功执行快速操作后将显示一条警报. +* 在[GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/16877)和更高版本中,您可以在更新问题,史诗和合并请求的描述时使用快速操作. + +快速操作是针对问题,史诗,合并请求和提交的常见操作的文本快捷方式,通常可通过在 GitLab 用户界面中单击按钮或下拉菜单来完成. 您可以在说明中或问题,史诗,合并请求和提交的注释中输入这些命令. 每个命令应放在单独的行上,以便正确检测和执行. + +## Quick Actions for issues, merge requests and epics[](#quick-actions-for-issues-merge-requests-and-epics "Permalink") + +以下快速操作适用于其中的描述,讨论和主题: + +* Issues +* 合并要求 +* Epics + +| Command | Issue | 合并要求 | Epic | Action | +| --- | --- | --- | --- | --- | +| `/approve` |   | ✓ |   | 批准合并请求. | +| `/assign @user` | ✓ | ✓ |   | 分配一个用户. | +| `/assign @user1 @user2` | ✓ | ✓ |   | 分配多个用户. | +| `/assign me` | ✓ | ✓ |   | 分配自己. | +| `/award :emoji:` | ✓ | ✓ | ✓ | 切换表情符号奖. | +| `/child_epic ` |   |   | ✓ | 将子史诗添加到`` . ``值的格式应为`&epic` , `group&epic`或`group&epic`的 URL( [在 GitLab 12.0 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7330) ). | +| `/clear_weight` | ✓ |   |   | 净重. | +| `/close` | ✓ | ✓ | ✓ | Close. | +| `/confidential` | ✓ |   |   | 保密. | +| `/copy_metadata ` | ✓ | ✓ |   | 从项目中的另一个合并请求中复制标签和里程碑. | +| `/copy_metadata <#issue>` | ✓ | ✓ |   | Copy labels and milestone from another issue in the project. | +| `/create_merge_request ` | ✓ |   |   | 从当前问题开始创建一个新的合并请求. | +| `/done` | ✓ | ✓ | ✓ | 将待办事项标记为已完成. | +| `/due ` | ✓ |   |   | 设置截止日期. 有效的``示例包括`in 2 days` ( `this Friday`和`December 31st` . | +| `/duplicate <#issue>` | ✓ |   |   | 关闭此问题,并将其标记为另一个问题的副本. 另外,将两者都标记为相关. | +| `/epic ` | ✓ |   |   | 添加到史诗`` . ``值的格式应为`&epic` , `group&epic`或`group&epic`的 URL. | +| `/estimate <w
      d h m>` | ✓ | ✓ |   | 设置时间估计. 例如, `/estimate 1w 3d 2h 14m` . | +| `/iteration *iteration:iteration` | ✓ |   |   | 设置迭代( [在 GitLab 13.1 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/196795) ) | +| `/label ~label1 ~label2` | ✓ | ✓ | ✓ | 添加一个或多个标签. 标签名称也可以不使用波浪号( `~` )开头,但是不支持混合语法. | +| `/lock` | ✓ | ✓ |   | 锁定螺纹. | +| `/merge` |   | ✓ |   | 合并更改. 根据项目设置,这可能是[管道成功](merge_requests/merge_when_pipeline_succeeds.html) ,添加到" [合并火车](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html) "等时. | +| `/milestone %milestone` | ✓ | ✓ |   | 设定里程碑. | +| `/move ` | ✓ |   |   | 将此问题移到另一个项目. | +| `/parent_epic ` |   |   | ✓ | 将父级史诗设置为`` . ``值的格式应为`&epic` , `group&epic`或`group&epic`的 URL( [在 GitLab 12.1 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/10556) ). | +| `/promote` | ✓ |   |   | 将问题升级为史诗. | +| `/publish` | ✓ |   |   | 将问题发布到关联的[状态页](status_page/index.html) ( [在 GitLab 13.0 中引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30906) ) | +| `/reassign @user1 @user2` | ✓ | ✓ |   | 更改受让人. | +| `/relabel ~label1 ~label2` | ✓ | ✓ | ✓ | 用指定的标签替换现有的标签. | +| `/relate #issue1 #issue2` | ✓ |   |   | 将问题标记为相关. | +| `/remove_child_epic ` |   |   | ✓ | 从``删除儿童史诗. ``值的格式应为`&epic` , `group&epic`或`group&epic`的 URL( [在 GitLab 12.0 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7330) ). | +| `/remove_due_date` | ✓ |   |   | 删除到期日. | +| `/remove_epic` | ✓ |   |   | 从史诗中删除. | +| `/remove_estimate` | ✓ | ✓ |   | 删除时间估计. | +| `/remove_iteration` | ✓ |   |   | 删除迭代( [在 GitLab 13.1 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/196795) ) | +| `/remove_milestone` | ✓ | ✓ |   | 删除里程碑. | +| `/remove_parent_epic` |   |   | ✓ | 从史诗中删除父史诗( [在 GitLab 12.1 中引入](https://gitlab.com/gitlab-org/gitlab/-/issues/10556) ). | +| `/remove_time_spent` | ✓ | ✓ |   | 消除花费的时间. | +| `/remove_zoom` | ✓ |   |   | 从此问题中删除 Zoom 会议( [在 GitLab 12.4 中引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16609) ). | +| `/reopen` | ✓ | ✓ | ✓ | Reopen. | +| `/shrug ` | ✓ | ✓ | ✓ | 将注释附加到`¯\_(ツ)_/¯` . | +| `/spend h m)> )>` | ✓ | ✓ |   | 减去花费的时间. (可选)指定花费时间的日期. 例如`/spend time(-1h 30m)`或`/spend time(-1h 30m) date(2018-08-26)` . | +| `/spend h m)> )>` | ✓ | ✓ |   | 增加花费的时间. (可选)指定花费时间的日期. 例如`/spend time(1h 30m)`或`/spend time(1h 30m) date(2018-08-26)` . | +| `/submit_review` |   | ✓ |   | Submit a pending review ([introduced in GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/issues/8041)). | +| `/subscribe` | ✓ | ✓ | ✓ | 订阅通知. | +| `/tableflip ` | ✓ | ✓ | ✓ | 在`(╯°□°)╯︵ ┻━┻`添加注释. | +| `/target_branch ` |   | ✓ |   | 设置目标分支. | +| `/title ` | ✓ | ✓ | ✓ | 更改标题. | +| `/todo` | ✓ | ✓ | ✓ | 添加待办事项. | +| `/unassign @user1 @user2` | ✓ | ✓ |   | 删除特定的受让人. | +| `/unassign` | ✓ | ✓ |   | 删除所有受让人. | +| `/unlabel ~label1 ~label2` or `/remove_label ~label1 ~label2` | ✓ | ✓ | ✓ | 删除所有或特定标签. | +| `/unlock` | ✓ | ✓ |   | 解锁线程. | +| `/unsubscribe` | ✓ | ✓ | ✓ | 退订通知. | +| `/weight ` | ✓ |   |   | 设定重量. 为有效选项``包括`0` , `1` , `2` ,依此类推. | +| `/wip` |   | ✓ |   | 切换"进行中"状态. | +| `/zoom ` | ✓ |   |   | 将 Zoom [Meeting](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16609)添加到此问题( [在 GitLab 12.4 中引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16609) ). | + +## Autocomplete characters[](#autocomplete-characters "Permalink") + +许多快速操作都需要一个参数,例如:用户名,里程碑和标签. 与从列表中选择项目相比, [自动完成字符](autocomplete_characters.html)可以使输入参数更加容易. + +## Quick actions parameters[](#quick-actions-parameters "Permalink") + +设置快速操作参数的最简单方法是使用自动完成功能. 如果您手动输入参数,则该参数必须用双引号( `"` )括起来,除非它仅包含以下字符: + +1. ASCII 字母. +2. 数字(0-9). +3. 下划线( `_` ),连字符( `-` ),问号( `?` ),点( `.` )或`&` ( `&` ). + +参数也区分大小写. 自动完成功能会自动处理此问题,并自动插入引号. + +## Quick actions for commit messages[](#quick-actions-for-commit-messages "Permalink") + +以下快速操作适用于提交消息: + +| Command | Action | +| --- | --- | +| `/tag v1.2.3 ` | 使用可选消息标记此提交 | \ No newline at end of file diff --git a/docs/412.md b/docs/412.md new file mode 100644 index 0000000000000000000000000000000000000000..3635b2e3935b0a8e751d1828e06c610c8cd2ddeb --- /dev/null +++ b/docs/412.md @@ -0,0 +1,45 @@ +# Autocomplete characters + +> 原文:[https://docs.gitlab.com/ee/user/project/autocomplete_characters.html](https://docs.gitlab.com/ee/user/project/autocomplete_characters.html) + +* [Example](#example) + +# Autocomplete characters[](#autocomplete-characters "Permalink") + +自动完成字符提供了一种在 Markdown 字段中输入字段值的快速方法. 当您开始在 Markdown 字段中使用以下字符之一键入单词时,GitLab 将针对一组匹配值逐步自动完成. 字符串匹配不区分大小写. + +| Character | Autocompletes | +| --- | --- | +| `~` | Labels | +| `%` | Milestones | +| `@` | 用户和组 | +| `#` | Issues | +| `!` | 合并要求 | +| `&` | Epics | +| `$` | Snippets | +| `:` | Emoji | +| `/` | 快速行动 | + +弹出列表中最多显示 5 个最相关的匹配项. 当您从列表中选择一个项目时,该值将输入到该字段中. 输入的字符越多,匹配项就越精确. + +与" [快速操作"](quick_actions.html)结合使用时,自动完成字符很有用. + +## Example[](#example "Permalink") + +假设您的 GitLab 实例包括以下用户: + +| Username | Name | +| --- | --- | +| alessandra | 罗斯·格兰特 | +| lawrence.white | 凯尔西·克鲁克 | +| leanna | 罗斯玛丽·罗甘(Rosemarie Rogahn) | +| logan_gutkowski | 李·沃克特 | +| shelba | 约瑟芬·海利 | + +在"问题"注释中,输入`@l`将显示以下弹出列表. 请注意,不包括用户`shelba` ,因为该列表仅包含与问题最相关的 5 个用户. + +[![Popup list which includes users whose username or name contains the letter `l`](img/7b1af71091089deb54dbd357d9679d9c.png)](img/autocomplete_characters_example1_v12_0.png) + +如果继续输入`@le` ,弹出列表将更改为以下内容. 现在,弹出窗口仅包括用户名中出现`le`或用户名中的单词的用户. + +[![Popup list which includes users whose username or name contains the string `le`](img/09a583a4343d2359d87040afc14139dd.png)](img/autocomplete_characters_example2_v12_0.png) \ No newline at end of file diff --git a/docs/413.md b/docs/413.md new file mode 100644 index 0000000000000000000000000000000000000000..305f9b1b62feddd8594b890515f9cf50447c9332 --- /dev/null +++ b/docs/413.md @@ -0,0 +1,92 @@ +# Reserved project and group names + +> 原文:[https://docs.gitlab.com/ee/user/reserved_names.html](https://docs.gitlab.com/ee/user/reserved_names.html) + +* [Reserved project names](#reserved-project-names) +* [Reserved group names](#reserved-group-names) + +# Reserved project and group names[](#reserved-project-and-group-names "Permalink") + +并非所有项目和组名都被允许,因为它们会与 GitLab 使用的现有路由冲突. + +有关不允许用作组名或项目名的单词的列表,请参阅`TOP_LEVEL_ROUTES` , `PROJECT_WILDCARD_ROUTES`和`GROUP_ROUTES`列表下的[`path_regex.rb`文件](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/path_regex.rb) : + +* `TOP_LEVEL_ROUTES` :是保留为用户名或顶级组的名称 +* `PROJECT_WILDCARD_ROUTES` :是为子组或项目保留的名称. +* `GROUP_ROUTES` :是为所有组或项目保留的名称. + +## Reserved project names[](#reserved-project-names "Permalink") + +当前无法创建具有以下名称的项目: + +* `\-` +* `badges` +* `blame` +* `blob` +* `builds` +* `commits` +* `create` +* `create_dir` +* `edit` +* `environments/folders` +* `files` +* `find_file` +* `gitlab-lfs/objects` +* `info/lfs/objects` +* `new` +* `preview` +* `raw` +* `refs` +* `tree` +* `update` +* `wikis` + +## Reserved group names[](#reserved-group-names "Permalink") + +当前,以下名称保留为顶级组: + +* `\-` +* `.well-known` +* `404.html` +* `422.html` +* `500.html` +* `502.html` +* `503.html` +* `abuse_reports` +* `admin` +* `api` +* `apple-touch-icon-precomposed.png` +* `apple-touch-icon.png` +* `assets` +* `autocomplete` +* `dashboard` +* `deploy.html` +* `explore` +* `favicon.ico` +* `favicon.png` +* `files` +* `groups` +* `health_check` +* `help` +* `import` +* `invites` +* `jwt` +* `login` +* `oauth` +* `profile` +* `projects` +* `public` +* `robots.txt` +* `s` +* `search` +* `sent_notifications` +* `slash-command-logo.png` +* `snippets` +* `unsubscribes` +* `uploads` +* `users` +* `v2` + +这些组名不能用作子组名: + +* `\-` \ No newline at end of file diff --git a/docs/414.md b/docs/414.md new file mode 100644 index 0000000000000000000000000000000000000000..179795c525a219da28846844b658b99fbeb92366 --- /dev/null +++ b/docs/414.md @@ -0,0 +1,193 @@ +# Search through GitLab + +> 原文:[https://docs.gitlab.com/ee/user/search/](https://docs.gitlab.com/ee/user/search/) + +* [Issues and merge requests](#issues-and-merge-requests) + * [Issues and MRs assigned to you or created by you](#issues-and-mrs-assigned-to-you-or-created-by-you) + * [Filtering issue and merge request lists](#filtering-issue-and-merge-request-lists) + * [Filtering by **None** / **Any**](#filtering-by-none--any) + * [Searching for specific terms](#searching-for-specific-terms) + * [Filtering by ID](#filtering-by-id) + * [Filtering merge requests by approvers](#filtering-merge-requests-by-approvers-starter) + * [Filtering merge requests by “approved by”](#filtering-merge-requests-by-approved-by-starter) +* [Filters autocomplete](#filters-autocomplete) +* [Search history](#search-history) +* [Removing search filters](#removing-search-filters) +* [Filtering with multiple filters of the same type](#filtering-with-multiple-filters-of-the-same-type) +* [Shortcut](#shortcut) +* [To-Do List](#to-do-list) +* [Projects](#projects) +* [Groups](#groups) +* [Issue Boards](#issue-boards) +* [Advanced Global Search](#advanced-global-search-starter) +* [Advanced Syntax Search](#advanced-syntax-search-starter) + +# Search through GitLab[](#search-through-gitlab "Permalink") + +## Issues and merge requests[](#issues-and-merge-requests "Permalink") + +要搜索问题并合并多个项目中的请求,可以使用屏幕右上角的" **问题"**或" **合并请求"**链接. + +它们两者都以相同的方式工作,因此,以下说明对两者均有效. + +右边显示的数字代表分配给您的问题和合并请求的数量. + +[![issues and MRs dashboard links](img/d0143a44aad793332527a786d79524f7.png)](img/dashboard_links.png) + +点击**问题时** ,您会立即看到分配给您的未解决问题: + +[![Issues assigned to you](img/41371f9efeaf03eb888ba8e19a486185.png)](img/issues_assigned_to_you.png) + +You can search through **Open**, **Closed**, or **All** issues. + +您还可以使用搜索和过滤器字段过滤结果,如下面的[过滤问题和合并请求列表中所述](#filtering-issue-and-merge-request-lists) . + +### Issues and MRs assigned to you or created by you[](#issues-and-mrs-assigned-to-you-or-created-by-you "Permalink") + +您还可以在屏幕右上角的搜索字段中找到问题的快捷方式,并合并由您创建或分配给您的请求: + +[![shortcut to your issues and mrs](img/a223e320ef570ec303a4e7346a899af7.png)](img/issues_mrs_shortcut.png) + +### Filtering issue and merge request lists[](#filtering-issue-and-merge-request-lists "Permalink") + +请按照以下步骤筛选项目和组中的" **问题**和**合并请求"**列表页面: + +1. 单击字段**搜索或过滤结果…** . +2. 在出现的下拉菜单中,选择您要过滤的属性: + * 作者 + * 受让人 + * [里程碑](../project/milestones/index.html) + * 释放 + * [标签](../project/labels.html) + * 我的反应 + * 机密 + * Epic(在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) ),包括[儿童史诗](../group/epics/index.html#multi-level-child-epics-ultimate) (在[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) ) + * 搜索此文字 +3. 选择或键入用于过滤属性的运算符. 可以使用以下运算符: + * `=` :是 + * `!=` :不是(在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/18059) ) +4. 输入文本以按[过滤属性](#filters-autocomplete) . +5. 重复此过程以按多个属性进行过滤. 多个属性通过逻辑`AND` . + +例如,按作者`=` Jane 和 Milestone `!=` 12.6 进行过滤,以解决 Jane 是作者而里程碑不是 12.6 的问题. + +[![filter issues in a project](img/9570df3750a76ee8a88eddb48512daa3.png)](img/issue_search_filter_v12_7.png) + +### Filtering by **None** / **Any**[](#filtering-by-none--any "Permalink") + +一些过滤字段(例如里程碑和受让人)允许您按**None**或**Any**进行过滤. + +[![filter by none any](img/e1f4f357a93d9362f282810a575d73e3.png)](img/issues_filter_none_any.png) + +选择" **无"**将返回该字段为空值的结果. 例如:没有里程碑,没有受让人. + +选择" **任意** "则相反. 它返回该字段具有非空值的结果. + +### Searching for specific terms[](#searching-for-specific-terms "Permalink") + +您可以按标题或说明中包含的特定术语过滤问题并合并请求. + +* Syntax + * 搜索以任何顺序查找查询中的所有单词. 例如:搜索问题以寻找`display bug` ,将以任何顺序返回匹配这两个单词的所有问题. + * 要找到确切的术语,请使用双引号: `"display bug"` +* Limitation + * 出于性能原因,少于 3 个字符的术语将被忽略. 例如:搜索问题`included in titles`是一样`included titles` + * 每个查询只能搜索 4096 个字符和 64 个字词. + +[![filter issues by specific terms](img/e336833accfac93c8ed18718b667dab5.png)](img/issue_search_by_term.png) + +### Filtering by ID[](#filtering-by-id "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39908) . + +您可以按 ID 将" **问题"**列表过滤到单个实例. 例如,输入过滤器`#10`仅返回问题 10.这同样适用于" **合并请求"**列表. 输入过滤器`#30`以仅返回合并请求 30. + +[![filter issues by specific id](img/1dcfd40d9306c4cfb80013c0cebdcac0.png)](img/issue_search_by_id.png) + +### Filtering merge requests by approvers[](#filtering-merge-requests-by-approvers-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9468) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.9. + +要过滤单个批准者的合并请求,您可以键入(或从下拉列表中选择) **批准者**并选择用户. + +[![Filter MRs by an approver](img/5ec08a62b534de16956701e85c41e6b5.png)](img/filter_approver_merge_requests.png) + +### Filtering merge requests by “approved by”[](#filtering-merge-requests-by-approved-by-starter "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30335) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.0. + +要过滤已由特定个人批准的合并请求,您可以键入(或从下拉列表中选择)" **批准",**然后选择用户. + +[![Filter MRs by approved by](img/fe213f080418c1bd6d92faa7e49770d3.png)](img/filter_approved_by_merge_requests_v13_0.png) + +## Filters autocomplete[](#filters-autocomplete "Permalink") + +GitLab 在许多页面(问题,合并请求,史诗和管道等)中提供了许多过滤器,您可以使用它们来缩小搜索范围. 使用过滤器功能时,可以开始键入字符以显示相关用户或其他属性. + +为了优化性能,至少需要三个字符才能开始搜索. 例如,如果您要搜索受让人" Simone Presley"的问题,则您需要至少键入" Sim",然后自动完成才能给出任何相关结果. + +## Search history[](#search-history "Permalink") + +您可以通过单击搜索输入左侧的小箭头图标来查看最近的搜索. 单击搜索条目以再次运行该搜索. 此功能可用于问题和合并请求. 搜索结果存储在本地浏览器中. + +[![search history](img/3863add8513c90ad786112f7a200a568.png)](img/search_history.gif) + +## Removing search filters[](#removing-search-filters "Permalink") + +单击过滤器的(x)按钮或退格可以删除单个过滤器. 整个搜索过滤器可以通过点击搜索框的(X)按钮,或通过`⌘`键`(Mac)+⌫`被清除. + +要一次删除一个过滤器令牌,可以使用`⌥` (Mac)/ `Ctrl` + `⌫`键盘组合. + +## Filtering with multiple filters of the same type[](#filtering-with-multiple-filters-of-the-same-type "Permalink") + +某些过滤器可以多次添加. 这些包括但不限于受让人和标签. 当使用相同类型的多个过滤器进行过滤时,将应用"与"逻辑. 例如,如果您要过滤`assignee:@sam assignee:@sarah` ,那么您的结果将仅包含将受让人分配给 Sam 和 Sarah 的条目. + +[![multiple assignees filtering](img/1165fee2238c55848aeb09d59c76cf7b.png)](img/multiple_assignees.png) + +## Shortcut[](#shortcut "Permalink") + +您还可以在项目仪表板右上方的搜索字段中找到快捷方式,以快速访问问题并合并在该项目中创建或分配给您的请求: + +[![search per project - shortcut](img/3001efd4ffb849af0c15eb8dda4d4050.png)](img/project_search.png) + +## To-Do List[](#to-do-list "Permalink") + +可以通过"待办事项"和"完成"来搜索您[的待办事项列表](../todos.html#gitlab-to-do-list) . 您可以按项目,作者,类型和操作[过滤](../todos.html#filtering-your-to-do-list)它们. 另外,您可以按[**标签优先级**](../../user/project/labels.html#label-priority) , **最后创建**和**最早创建**对其进行排序. + +## Projects[](#projects "Permalink") + +您可以从左侧菜单中搜索项目,方法是依次点击菜单栏和**项目** . 在" **按名称过滤** "字段上,输入要查找的项目或组名称,GitLab 会在您键入时为您过滤它们. + +你也可以去找你的项目[出演](../project/index.html#star-a-project) ( **加星标的项目** ),并**探索**所有的公共和内部项目 GitLab.com 可用,从中你可以通过可视性筛选,通过**趋势** ,最好与**大多数明星**评分,或他们的**全部** . + +您还可以按**名称** , **最后创建** , **最旧创建** , **最后更新** , **最新更新** , **所有者**对它们进行排序,并选择隐藏或显示**已归档的项目** : + +[![sort projects](img/7ff67c276870da733a9bc04b2aa9d969.png)](img/sort_projects.png) + +## Groups[](#groups "Permalink") + +Similarly to [projects search](#projects), you can search through your groups from the left menu, by clicking the menu bar, then **Groups**. + +在" **按名称过滤** "字段上,输入要查找的组名,GitLab 将在您键入时为您过滤它们. + +您也可以**浏览**所有的公共和 GitLab.com 可用的内部组,您可以按照**最新创建的** , **最早建立** , **最后更新** ,或**最早的更新** . + +## Issue Boards[](#issue-boards "Permalink") + +在[问题板上](../../user/project/issue_board.html) ,您可以按**作者** , **受让人** , **里程碑**和**标签**过滤问题. 您还可以从键入时加载的字段中**按名称过滤** (按名称)(问题标题). + +当您要搜索要添加到**问题**面板中列表中的问题时,请点击屏幕右上角的**添加问题**按钮,打开一个模态窗口,除了按**名称**过滤它们之外,您还可以从中找到一个模式窗口**作者** , **受让人** , **里程碑**和**标签** ,选择多个问题以添加到您选择的列表中: + +[![search and select issues to add to board](img/e57526dd100a1b0a33bdae55e3bf32c7.png)](img/search_issues_board.png) + +## Advanced Global Search[](#advanced-global-search-starter "Permalink") + +利用 Elasticsearch 在整个 GitLab 实例上进行更快,更高级的代码搜索. + +[Learn how to use the Advanced Global Search.](advanced_global_search.html) + +## Advanced Syntax Search[](#advanced-syntax-search-starter "Permalink") + +使用高级查询获得更具针对性的搜索结果. + +[Learn how to use the Advanced Syntax Search.](advanced_search_syntax.html) \ No newline at end of file diff --git a/docs/415.md b/docs/415.md new file mode 100644 index 0000000000000000000000000000000000000000..93e6acbba1d41a7c1e08704776b5cd8b2f1432b9 --- /dev/null +++ b/docs/415.md @@ -0,0 +1,59 @@ +# Advanced Global Search + +> 原文:[https://docs.gitlab.com/ee/user/search/advanced_global_search.html](https://docs.gitlab.com/ee/user/search/advanced_global_search.html) + +* [Overview](#overview) +* [Use cases](#use-cases) + * [Faster searches](#faster-searches) + * [Promote innersourcing](#promote-innersourcing) +* [Searching globally](#searching-globally) + +# Advanced Global Search[](#advanced-global-search-starter-only "Permalink") + +版本历史 + +* 在 GitLab [Starter](https://about.gitlab.com/pricing/) 8.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109) . + +**GitLab.com 的可用性:**高级全局搜索(由 Elasticsearch 支持)在 GitLab.com 上尚不可用. 它将在 2020 年第三季度为所有付费群体逐步启用.请[遵循此史诗](https://gitlab.com/groups/gitlab-com/-/epics/649) ,以获取时间表上的最新更新. + +利用 Elasticsearch 在整个 GitLab 实例上进行更快,更高级的代码搜索. + +这是用户文档. 要安装和配置 Elasticsearch,请访问[管理员文档](../../integration/elasticsearch.html) . + +## Overview[](#overview "Permalink") + +GitLab 中的 Advanced Global Search 是一项功能强大的搜索服务,可以节省您的时间. 现在,您可以在其他团队中搜索可以为您自己的项目提供帮助的代码,而不必创建重复的代码和浪费时间. + +manbetx 客户端打不开利用[Elasticsearch](https://www.elastic.co/elasticsearch/)的搜索功能,并在搜索时启用它: + +* Projects +* Repositories +* Commits +* Issues +* 合并要求 +* Milestones +* 注释(评论) +* Snippets +* Wiki + +## Use cases[](#use-cases "Permalink") + +高级全局搜索在各种情况下都非常有用. + +### Faster searches[](#faster-searches "Permalink") + +如果您要处理大量数据,并希望保持 GitLab 的快速搜索,高级全局搜索将帮助您实现这一目标. + +### Promote innersourcing[](#promote-innersourcing "Permalink") + +您的公司可能由许多不同的开发人员团队组成,每个开发人员团队都有各自的团队来托管各种项目. 您的某些应用程序可能会相互连接,因此您的开发人员需要立即在整个 GitLab 实例中进行搜索并找到他们搜索的代码. + +## Searching globally[](#searching-globally "Permalink") + +像以前一样使用搜索,GitLab 会向您显示您有权访问的每个项目中的匹配代码. + +[![Advanced Global Search](img/a3626522e1409168b7c977ecebbaee6e.png)](img/advanced_global_search.png) + +您还可以使用提供一些有用查询的[高级语法搜索](advanced_search_syntax.html) . + +**注意:** Elasticsearch 仅具有默认分支的数据. 这意味着,如果您转到存储库树并将分支从默认分支切换到其他分支,那么即使启用了 Elasticsearch,常规搜索也会提供搜索结果页面中的"代码"选项卡. \ No newline at end of file diff --git a/docs/416.md b/docs/416.md new file mode 100644 index 0000000000000000000000000000000000000000..b317aded91bfb32efaaeb4c2a604d1746f036e3e --- /dev/null +++ b/docs/416.md @@ -0,0 +1,66 @@ +# Advanced Syntax Search + +> 原文:[https://docs.gitlab.com/ee/user/search/advanced_search_syntax.html](https://docs.gitlab.com/ee/user/search/advanced_search_syntax.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [Using the Advanced Syntax Search](#using-the-advanced-syntax-search) + * [Syntax search filters](#syntax-search-filters) + +# Advanced Syntax Search[](#advanced-syntax-search-starter "Permalink") + +版本历史 + +* 在[GitLab Enterprise Starter](https://about.gitlab.com/pricing/) 9.2 中引入 + +**GitLab.com 可用性:**自 2020-07-10 起,在 GitLab.com 上启用了 Bronze 及更高版本的 Advanced Global Search(由 Elasticsearch 支持). + +使用高级查询获得更具针对性的搜索结果. + +这是用户文档. 要安装和配置 Elasticsearch,请访问[管理员文档](../../integration/elasticsearch.html) . + +## Overview[](#overview "Permalink") + +"高级语法搜索"是" [高级全局搜索"](advanced_global_search.html)的子集,如果您想要更具体的搜索结果,可以使用它. + +Advanced Global Search 仅支持搜索[默认分支](../project/repository/branches/index.html#default-branch) . + +## Use cases[](#use-cases "Permalink") + +例如,假设您开发的产品依赖于另一个组中托管的另一种产品的代码. + +由于在您的 GitLab 实例下托管了数百个不同的项目,因此您需要搜索结果尽可能地高效. 您对要查找的内容有感觉(例如,函数名),但是同时您也不太确定. + +在这种情况下,在查询中使用高级搜索语法将产生更好的结果. + +## Using the Advanced Syntax Search[](#using-the-advanced-syntax-search "Permalink") + +高级语法搜索支持带有前缀,布尔运算符等的模糊或精确搜索查询. + +可以在[Elasticsearch 文档中](https://www.elastic.co/guide/en/elasticsearch/reference/5.3/query-dsl-simple-query-string-query.html#_simple_query_string_syntax)找到完整的详细信息,但是这里有一个快速指南: + +* 搜索以任何顺序搜索查询中的所有单词,例如:搜索`display bug`问题将以任何顺序返回匹配这两个单词的所有问题. +* 要查找确切的词组(仍然适用词干),请使用双引号: `"display bug"` +* 要查找未提及显示的错误,请使用`-` : `bug -display` +* 要查找显示或声音中的错误,请使用`|` : `bug display | sound` `bug display | sound` +* 要组术语一起,使用括号: `bug | (display +sound)` `bug | (display +sound)` +* 要匹配部分单词,请使用`*` : `bug find_by_*` +* 要查找包含这些符号之一的术语,请使用`\` : `argument \-last` + +### Syntax search filters[](#syntax-search-filters "Permalink") + +高级语法搜索还支持使用过滤器. 可用的过滤器是: + +* filename:按文件名过滤. 您可以使用 glob( `*` )运算符进行模糊匹配. +* path:按路径过滤. 您可以使用 glob( `*` )运算符进行模糊匹配. +* 扩展名:按扩展名过滤文件名. 请写扩展名,不要带引号. 仅完全匹配. + +要使用它们,只需将它们添加到您的查询格式`:`没有冒号之间的空格( `:` )和值. + +Examples: + +* 查找包含任何名为`hello_world.rb`内容的文件: `* filename:hello_world.rb` +* 查找一个名为`hello_world`的文件,其中包含文本`whatever` : `whatever filename:hello_world` +* 在扩展名为`.rb`文件中查找文本" def create": `def create extension:rb` +* 在名为`encryption`的文件夹中的文件内查找文本`sha` : `sha path:encryption` +* 查找任何以`hello`开头的文件,其中包含`world`并带有`.js`扩展名: `world filename:hello* extension:js` \ No newline at end of file diff --git a/docs/417.md b/docs/417.md new file mode 100644 index 0000000000000000000000000000000000000000..ccba4d2186540c05d73f79f0bf64bfa7f0d5dd68 --- /dev/null +++ b/docs/417.md @@ -0,0 +1,84 @@ +# Time Tracking + +> 原文:[https://docs.gitlab.com/ee/user/project/time_tracking.html](https://docs.gitlab.com/ee/user/project/time_tracking.html) + +* [Overview](#overview) +* [How to enter data](#how-to-enter-data) + * [Estimates](#estimates) + * [Time spent](#time-spent) +* [Configuration](#configuration) + * [Limit displayed units to hours](#limit-displayed-units-to-hours-core-only) +* [Other interesting links](#other-interesting-links) + +# Time Tracking[](#time-tracking "Permalink") + +在 GitLab 8.14 中引入. + +时间跟踪允许您跟踪估计和花费在问题上的时间以及在 GitLab 中合并请求. + +## Overview[](#overview "Permalink") + +时间跟踪使您能够: + +* 记录处理问题或合并请求所花费的时间. +* 添加完成问题或合并请求所需时间的估计. + +您不必输入估算值即可输入花费的时间,反之亦然. + +有关时间跟踪的数据显示在问题/合并请求侧栏上,如下所示. + +[![Time tracking in the sidebar](img/05a0790512923394006a9c3face18d58.png)](img/time_tracking_sidebar_v8_16.png) + +## How to enter data[](#how-to-enter-data "Permalink") + +时间跟踪使用了 GitLab 通过此新功能引入的两个[快速操作](quick_actions.html) : `/spend`和`/estimate` . + +快速操作既可以用于问题或合并请求的正文中,也可以用于问题或合并请求的注释中. + +下面是一个示例,说明如何在评论中使用这些新的快速操作. + +[![Time tracking example in a comment](img/37cb6e38ded4ec606f9bc7776f765e70.png)](img/time_tracking_example_v12_2.png) + +添加时间条目(花费的时间或估计的时间)仅限于项目成员. + +### Estimates[](#estimates "Permalink") + +要输入估算值,请输入`/estimate` ,然后输入时间. 例如,如果您需要输入 3 天 5 小时 10 分钟的估算值,则可以输入`/estimate 3d 5h 10m` . 我们支持的时间单位列在此帮助页面的底部. + +每次输入新的时间估算值时,任何先前的时间估算值都将被该新值覆盖. 在发布或合并请求中应该只有一个有效的估计. + +要完全删除估算,请使用`/remove_estimate` . + +### Time spent[](#time-spent "Permalink") + +要输入花费的时间,请使用`/spend 3d 5h 10m` . + +每个新花费的时间条目将被添加到当前用于发布或合并请求的总时间中. + +您可以通过输入负数来减少时间: `/spend -3d`将从总花费时间中删除 3 天. 您所花费的时间不能少于 0 分钟,因此,如果您删除的时间量与已输入的时间相比更长,则 GitLab 将自动重置所花费的时间. + +要删除一次花费的所有时间,请使用`/remove_time_spent` . + +## Configuration[](#configuration "Permalink") + +以下时间单位可用: + +* 月(mo) +* 周(w) +* Days (d) +* 小时(h) +* 分钟(米) + +默认转换率是 1mo = 4w,1w = 5d 和 1d = 8h. + +### Limit displayed units to hours[](#limit-displayed-units-to-hours-core-only "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29469/) . + +在 GitLab 自我管理实例中,可以通过**"** **本地化** **"**下**"管理">"设置">"首**选项"中的选项将时间单位的显示限制为小时. + +启用此选项后,将显示`75h`而不是`1w 4d 3h` . + +## Other interesting links[](#other-interesting-links "Permalink") + +* [Time Tracking landing page in the GitLab handbook](https://about.gitlab.com/solutions/time-tracking/) \ No newline at end of file diff --git a/docs/418.md b/docs/418.md new file mode 100644 index 0000000000000000000000000000000000000000..55e1daba40cc512edc65b372402bac9de1b5ef2a --- /dev/null +++ b/docs/418.md @@ -0,0 +1,136 @@ +# GitLab To-Do List + +> 原文:[https://docs.gitlab.com/ee/user/todos.html](https://docs.gitlab.com/ee/user/todos.html) + +* [What triggers a To Do](#what-triggers-a-to-do) + * [Directly addressing a To Do](#directly-addressing-a-to-do) + * [Manually creating a To Do](#manually-creating-a-to-do) +* [Marking a To Do as done](#marking-a-to-do-as-done) +* [Filtering your To-Do List](#filtering-your-to-do-list) + +# GitLab To-Do List[](#gitlab-to-do-list "Permalink") + +在 GitLab 8.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2817) . + +当您登录到 GitLab 时,通常需要查看应该花些时间在哪里,采取一些措施或知道需要注意什么而无需大量电子邮件通知. GitLab 是您工作的地方,因此快速入门非常重要. + +待办事项列表在一个简单的仪表板中按时间顺序列出了等待您输入的项目. + +[![To Do screenshot showing a list of items to check on](img/aafa273009fd04415444f040f8b4c6cc.png)](img/todos_index.png) + +通过单击顶部导航中搜索栏旁边的对勾图标,可以快速访问待办事项列表. 如果计数为: + +* 小于 100 的蓝色数字是待办事项的数量. +* 大于或等于 100,则数字显示为 99+. 确切的数字显示在"任务列表"上. 你还有空. 否则,该数字将显示为 99+. 确切的数字显示在"任务列表"上. + +[![To Do icon](img/7f8f5e942a32629817a87b08e33d9071.png)](img/todos_icon.png) + +## What triggers a To Do[](#what-triggers-a-to-do "Permalink") + +在以下情况下,待办事项会显示在您的待办事项列表中: + +* 分配或合并请求已分配给您 +* 在以下内容的描述或评论中`@mentioned`您`@mentioned` : + * 问题 + * 合并请求 + * 史诗 +* 在以下评论中`@mentioned`您: + * 承诺 + * 设计 +* 您的合并请求的 CI / CD 管道失败 +* 由于冲突,一个打开的合并请求变得不可合并,并且满足以下条件之一: + * 你是作者 + * 您是将其设置为在管道成功后自动合并的用户 +* [从 GitLab 13.2 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/12136) ,合并请求将从[合并火车中](../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)删除,您是添加请求的用户. + +待办事项触发器不受[GitLab 通知电子邮件设置的影响](profile/notifications.html) . + +**注意:**当用户不再有权访问与待办事项相关的资源(例如问题,合并请求,项目或组)时,出于安全原因,相关的待办事项将在下一小时内删除. 如果用户的访问被错误地取消,则删除操作会延迟以防止数据丢失. + +### Directly addressing a To Do[](#directly-addressing-a-to-do "Permalink") + +在 GitLab 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7926) . + +如果在一行的开头提到您,则您收到的待办事项将列为"直接处理". 例如,在此注释中: + +``` +@alice What do you think? cc: @bob + - @carol can you please have a look? + >>> +@dan what do you think? +>>> + +@erin @frank thank you! +``` + +接收直接处理的待办事项的人是`@alice` , `@erin`和`@frank` . 直接寻址的待办事项仅出于过滤目的而与提及事项有所不同; 否则,它们显示为正常. + +### Manually creating a To Do[](#manually-creating-a-to-do "Permalink") + +您还可以通过在以下位置单击" **添加待办事项"**按钮,将以下内容添加到"待办事项列表": + +* Issue +* 合并请求 +* Epic + +[![Adding a To Do from the issuable sidebar](img/f44886a0dc98ed48e0854c7d2ac6a220.png)](img/todos_add_todo_sidebar.png) + +## Marking a To Do as done[](#marking-a-to-do-as-done "Permalink") + +采取以下任何措施都会将相应的待办事项标记为已完成: + +* Issue +* 合并请求 +* Epic + +取消待办事项的动作包括: + +* 更换受让人 +* 改变里程碑 +* 添加/删除标签 +* 对这个问题发表评论 + +Your To-Do List is personal, and items are only marked as done if the action comes from you. If you close the issue or merge request, your To Do is automatically marked as done. + +为防止其他用户在不通知您的情况下关闭问题,如果其他人关闭,合并或对以下任何一项采取了措施,则您的待办事项将保持待处理状态: + +* Issue +* 合并要求 +* Epic + +每种情况只有一个待办事项,因此在一个问题中提到用户一百次只会触发一个待办事项. + +如果不需要采取任何措施,您可以通过单击相应的**"完成"**按钮来手动将"待办事项"标记为已完成,该按钮将从您的"待办事项列表"中消失. + +[![A To Do in the To-Do List](img/235fdd047e32990019bc08c92ced8299.png)](img/todos_todo_list_item.png) + +您还可以通过单击以下边栏中的" **标记为已完成"**按钮将"待办事项" **标记为已完成** : + +* Issue +* 合并请求 +* Epic + +[![Mark as done from the issuable sidebar](img/5e63fee9a28bb3e02eb772646de82b5c.png)](img/todos_mark_done_sidebar.png) + +您可以通过单击**全部标记为已完成**按钮将所有待办事项**标记为已完成** . + +## Filtering your To-Do List[](#filtering-your-to-do-list "Permalink") + +您可以在待办事项列表中使用四种过滤器. + +| Filter | Description | +| --- | --- | +| Project | 按项目筛选 | +| Group | 按组筛选 | +| Author | 按触发待办事项的作者过滤 | +| Type | 按问题,合并请求,设计或史诗过滤 | +| Action | 按触发待办事项的动作过滤 | + +您还可以同时按多个过滤条件之一进行过滤. [上面描述了](#what-triggers-a-to-do)可能的操作,包括: + +* 任何行动 +* Assigned +* Mentioned +* Added +* Pipelines +* 直接寻址 \ No newline at end of file diff --git a/docs/419.md b/docs/419.md new file mode 100644 index 0000000000000000000000000000000000000000..9511acca74037624440b708d20758dc38983cd66 --- /dev/null +++ b/docs/419.md @@ -0,0 +1,234 @@ +# Administrator Docs + +> 原文:[https://docs.gitlab.com/ee/administration/](https://docs.gitlab.com/ee/administration/) + +* [Installing and maintaining GitLab](#installing-and-maintaining-gitlab) + * [Installing GitLab](#installing-gitlab) + * [Configuring GitLab](#configuring-gitlab) + * [Customizing GitLab’s appearance](#customizing-gitlabs-appearance) + * [Maintaining GitLab](#maintaining-gitlab) + * [Updating GitLab](#updating-gitlab) + * [Upgrading or downgrading GitLab](#upgrading-or-downgrading-gitlab) + * [GitLab platform integrations](#gitlab-platform-integrations) +* [User settings and permissions](#user-settings-and-permissions) +* [Project settings](#project-settings) +* [Package Registry administration](#package-registry-administration) + * [Repository settings](#repository-settings) +* [Continuous Integration settings](#continuous-integration-settings) +* [Snippet settings](#snippet-settings) +* [Git configuration options](#git-configuration-options) +* [Monitoring GitLab](#monitoring-gitlab) + * [Performance Monitoring](#performance-monitoring) +* [Analytics](#analytics) +* [Troubleshooting](#troubleshooting) + * [Support Team Docs](#support-team-docs) + +# Administrator Docs[](#administrator-docs-core-only "Permalink") + +了解如何管理自己的 GitLab 实例. + +manbetx 客户端打不开有两个产品发行版可以通过[不同的订阅获得](https://about.gitlab.com/pricing/) : + +* 开源[GitLab 社区版(CE)](https://gitlab.com/gitlab-org/gitlab-foss) . +* The open core [GitLab Enterprise Edition (EE)](https://gitlab.com/gitlab-org/gitlab). + +您可以[安装 GitLab CE 或 GitLab EE](https://about.gitlab.com/install/ce-or-ee/) . 但是,您可以使用的功能取决于您选择的订阅(Core,Starter,Premium 或 Ultimate). + +**注意:** GitLab 社区版安装只能访问核心功能. + +GitLab.com 由 GitLab,Inc.管理,因此,只有 GitLab 团队成员才能访问其管理配置. 如果您是 GitLab.com 用户,请检查[用户文档](../user/index.html) . + +**注意:**非管理员用户无权访问 GitLab 管理工具和设置. + +## Installing and maintaining GitLab[](#installing-and-maintaining-gitlab "Permalink") + +了解如何安装,配置,更新和维护您的 GitLab 实例. + +### Installing GitLab[](#installing-gitlab "Permalink") + +* [安装](../install/README.html) :要求,目录结构和安装方法. + * [数据库负载平衡](database_load_balancing.html) :在多个数据库服务器之间分配数据库查询. + * [Omnibus 支持日志转发](https://docs.gitlab.com/omnibus/settings/logs.html) +* [参考体系结构](reference_architectures/index.html) :添加其他资源以支持更多用户. + * [在 Amazon Web Services(AWS)上安装 GitLab](../install/aws/index.html) :在 Amazon AWS 上设置 GitLab. +* [地理位置](geo/replication/index.html) :将 GitLab 实例复制到其他地理位置,作为只读的完全可操作版本. +* [灾难恢复](geo/disaster_recovery/index.html) :在灾难情况下,只需最少的精力即可快速故障转移到其他站点. +* [Pivotal Tile](../install/pivotal/index.html) :使用用于 Pivotal Cloud Foundry 的 Ops Manager(BOSH)将 GitLab 部署为预配置的设备. +* [添加许可证](../user/admin_area/license.html) :在安装时上传许可证以解锁 GitLab 付费层中的功能. + +### Configuring GitLab[](#configuring-gitlab "Permalink") + +* [调整实例的时区](timezone.html) :定制 GitLab 的默认时区. +* [系统挂钩](../system_hooks/system_hooks.html) :更改用户,项目和键时的通知. +* [安全性](../security/README.html) :了解如何进一步保护 GitLab 实例. +* [使用情况统计信息,版本检查和使用情况 ping](../user/admin_area/settings/usage_statistics.html) :启用或禁用有关要发送到 GitLab,Inc.的实例的信息. +* [全局用户设置](user_settings.html) :配置实例范围的用户权限. +* [轮询](polling.html) :配置 GitLab UI 轮询更新的频率. +* [GitLab 页面配置](pages/index.html) :启用和配置 GitLab 页面. +* [用于 GitLab 源代码安装的 GitLab Pages 配置](pages/source.html) :在[源代码安装](../install/installation.html#installation-from-source)上启用和配置 GitLab Pages. +* [上传管理](uploads.html) :配置 GitLab 上传存储. +* [环境变量](environment_variables.html) :受支持的环境变量,可用于覆盖其默认值以配置 GitLab. +* [插件](plugins.html) :使用自定义插件,GitLab 管理员可以引入自定义集成,而无需修改 GitLab 的源代码. +* [Enforcing Terms of Service](../user/admin_area/settings/terms.html) +* [Third party offers](../user/admin_area/settings/third_party_offers.html) +* [合规性](compliance.html) :您可以配置整个应用程序中的功能集合,以帮助确保您的 GitLab 实例和 DevOps 工作流程符合合规性标准. +* 差异[限制](../user/admin_area/diff_limits.html) :配置分支比较页面的差异渲染大小限制. +* [合并请求差异存储](merge_request_diffs.html) :配置合并请求差异外部存储. +* [广播消息](../user/admin_area/broadcast_messages.html) :通过 UI 向 GitLab 用户发送消息. +* [Elasticsearch](../integration/elasticsearch.html) :使 Elasticsearch 能够授权 GitLab 的 Advanced Global Search. 当您处理大量数据时很有用. +* [External Classification Policy Authorization](../user/admin_area/settings/external_authorization.html) +* [上载许可证](../user/admin_area/license.html) :上载许可证以解锁 GitLab 付费层中的功能. +* [管理区域](../user/admin_area/index.html) :用于自我管理的实例范围内的配置和维护. +* [S / MIME 签名](smime_signing_email.html) :如何使用 S / MIME 对所有传出的通知电子邮件进行签名. +* [启用和禁用功能标志](feature_flags.html) :如何启用和禁用部署在功能标志后面的 GitLab 功能. + +#### Customizing GitLab’s appearance[](#customizing-gitlabs-appearance "Permalink") + +* [标头徽标](../user/admin_area/appearance.html#navigation-bar) :更改所有页面和电子邮件标头上的徽标. +* [网站](../user/admin_area/appearance.html#favicon)图标:将默认网站图标更改为您自己的徽标. +* [品牌登录页面](../user/admin_area/appearance.html#sign-in--sign-up-pages) :使用您自己的徽标,标题和描述来自定义登录页面. +* ["新项目"页面](../user/admin_area/appearance.html#new-project-pages) :自定义在用户创建新项目时打开的页面上显示的文本. +* [其他自定义电子邮件文本](../user/admin_area/settings/email.html#custom-additional-text-premium-only) :将其他自定义文本添加到从 GitLab 发送的电子邮件中. + +### Maintaining GitLab[](#maintaining-gitlab "Permalink") + +* [瑞克任务](../raketasks/README.html) :执行各种维护,备份,自动 Webhooks 设置等任务. + * [备份和还原](../raketasks/backup_restore.html) :备份和还原您的 GitLab 实例. +* [操作](operations/index.html) :保持 GitLab 正常运行(清理 Redis 会话,移动存储库,Sidekiq MemoryKiller,Puma). +* [重新启动 GitLab](restart_gitlab.html) :了解如何重新启动 GitLab 及其组件. +* [使 Markdown 缓存](invalidate_markdown_cache.html)无效:使所有缓存的 Markdown 无效. + +#### Updating GitLab[](#updating-gitlab "Permalink") + +* [GitLab 版本和维护策略](../policy/maintenance.html) :了解 GitLab 版本和发行版(主要,次要,补丁,安全)以及更新建议. +* [更新 GitLab](../update/README.html) :更新指南将您的安装升级到新版本. +* [无需停机](../update/README.html#upgrading-without-downtime)即可进行[升级:无需中断](../update/README.html#upgrading-without-downtime) GitLab 实例即可升级到较新的主要,次要或补丁版本的 GitLab. +* [将您的 GitLab CI / CD 数据迁移到另一个版本的 GitLab](../migrate_ci_to_ce/README.html) :如果您安装的是旧的 GitLab(版本低于 8.0),请按照本指南将现有的 GitLab CI / CD 数据迁移到另一个版本的 GitLab. + +### Upgrading or downgrading GitLab[](#upgrading-or-downgrading-gitlab "Permalink") + +* [从 GitLab CE 升级到 GitLab EE](../update/README.html#upgrading-between-editions) :了解如何将 GitLab 社区版升级到 GitLab 企业版. +* [从 GitLab EE 降级到 GitLab CE](../downgrade_ee_to_ce/README.html) :了解如何将 GitLab 企业版降级到社区版. + +### GitLab platform integrations[](#gitlab-platform-integrations "Permalink") + +* [Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/) :与[Mattermost](https://mattermost.com)集成, [后者](https://mattermost.com)是一个用于 Web 消息传递的开源私有云工作场所. +* [PlantUML](integration/plantuml.html) :在片段,Wiki 和存储库中创建的 AsciiDoc 和 Markdown 文档中创建简单图. +* [Web 终端](integration/terminal.html) :从 GitLab 的 CI / CD [环境中](../ci/environments/index.html#web-terminals)提供对部署到 Kubernetes 的应用程序的终端访问. + +## User settings and permissions[](#user-settings-and-permissions "Permalink") + +* [创建用户](../user/profile/account/create_accounts.html) :手动或通过身份验证集成创建用户. +* [Libravatar](libravatar.html) :使用 Libravatar 代替 Gravatar 进行用户化身. +* [注册限制](../user/admin_area/settings/sign_up_restrictions.html) :阻止特定域的电子邮件地址,或仅将特定域列入白名单. +* [访问限制](../user/admin_area/settings/visibility_and_access_controls.html#enabled-git-access-protocols) :定义可用于与 GitLab 进行通信的 Git 访问协议(SSH,HTTP,HTTPS). +* [身份验证和授权](auth/README.html) :使用 LDAP,SAML,CAS 和其他提供程序配置外部身份验证. + * [同步 LDAP](auth/ldap/index.html) + * [Kerberos 身份验证](../integration/kerberos.html) + * 另请参阅其他[身份验证](../topics/authentication/index.html#gitlab-administrators)主题(例如,实施 2FA). +* [电子邮件用户](../tools/email.html) :从 GitLab 内部向 GitLab 用户发送电子邮件. +* [用户群组](../user/admin_area/user_cohorts.html) :显示新用户及其在一段时间内的活动的每月群组. +* [审核日志和事件](audit_events.html) :查看在 GitLab 服务器中对以下内容所做的更改: + * 小组和项目. + * 实例. +* [Auditor 用户](auditor_users.html) :对 GitLab 实例上的所有项目,组和其他资源具有只读访问权限的用户. +* [传入电子邮件](incoming_email.html) :配置传入电子邮件,以允许用户[通过电子邮件](reply_by_email.html)进行[答复,通过电子邮件](reply_by_email.html)创建[问题](../user/project/issues/managing_issues.html#new-issue-via-email)以及[通过电子邮件](../user/project/issues/managing_issues.html#new-issue-via-email) [合并请求](../user/project/merge_requests/creating_merge_requests.html#new-merge-request-by-email-core-only) ,以及启用[Service Desk](../user/project/service_desk.html) . + * [传入电子邮件的 Postfix](reply_by_email_postfix_setup.html) :在 Ubuntu 上为传入电子邮件设置具有 IMAP 身份验证的基本 Postfix 邮件服务器. +* [滥用情况报告](../user/admin_area/abuse_reports.html) :查看和解决用户的滥用情况报告. +* [凭证清单](../user/admin_area/credentials_inventory.html) :通过凭证清单,GitLab 管理员可以在其 GitLab 自我管理实例中跟踪其用户使用的凭证. + +## Project settings[](#project-settings "Permalink") + +* [问题关闭模式](issue_closing_pattern.html) :自定义如何从提交消息中关闭问题. +* [Gitaly](gitaly/index.html) :配置 GitLab 的 Git 仓库存储服务 Gitaly. +* [默认标签](../user/admin_area/labels.html) :创建将自动添加到每个新项目的标签. +* [限制使用公共或内部项目](../public_access/public_access.html#restricting-the-use-of-public-or-internal-projects) :限制用户在创建项目或代码段时使用可见性级别. +* [自定义项目模板](../user/admin_area/custom_project_templates.html) :配置一组项目,以在创建新项目时用作自定义模板. + +## Package Registry administration[](#package-registry-administration "Permalink") + +* [容器注册表](packages/container_registry.html) :使用 GitLab 配置容器注册表. +* [软件包注册表](packages/index.html) :使 GitLab 可以充当 NPM 注册表和 Maven 存储库. +* [Dependency Proxy](packages/dependency_proxy.html): Configure the Dependency Proxy, a local proxy for frequently used upstream images/packages. + +### Repository settings[](#repository-settings "Permalink") + +* [仓库检查](repository_checks.html) :定期的 Git 仓库检查. +* [存储库存储路径](repository_storage_paths.html) :管理用于存储存储库的路径. +* [存储库存储类型](repository_storage_types.html) :有关不同存储库存储类型的信息. +* [存储库存储 Rake 任务](raketasks/storage.html) :一组 Rake 任务,用于列出并将与之关联的现有项目和附件从旧版存储迁移到哈希存储. +* [限制存储库大小](../user/admin_area/settings/account_and_limit_settings.html) :设置[存储库大小](../user/admin_area/settings/account_and_limit_settings.html)的硬限制. +* [静态对象外部存储](static_objects_external_storage.html) :为存储库中的静态对象设置外部存储. + +## Continuous Integration settings[](#continuous-integration-settings "Permalink") + +* [启用/禁用 GitLab CI / CD](../ci/enable_or_disable_ci.html#site-wide-admin-setting) :为您的实例启用或禁用 GitLab CI / CD. +* [GitLab CI / CD 管理员设置](../user/admin_area/settings/continuous_integration.html) :在整个站点范围内启用或禁用 Auto DevOps 并定义工件的最大大小和有效时间. +* [外部管道验证](external_pipeline_validation.html) :启用,禁用和配置外部管道验证. +* [作业工件](job_artifacts.html) :启用,禁用和配置作业工件(作业成功完成时输出的一组文件和目录). +* [作业日志](job_logs.html) :有关作业日志的信息. +* [注册跑步者](../ci/runners/README.html#types-of-runners) :了解如何注册和配置跑步者. +* [共享运行程序管道配额](../user/admin_area/settings/continuous_integration.html#shared-runners-pipeline-minutes-quota-starter-only) :限制共享运行程序的管道分钟的使用. +* [启用/禁用 Auto DevOps](../topics/autodevops/index.html#enablingdisabling-auto-devops) :为您的实例启用或禁用 Auto DevOps. + +## Snippet settings[](#snippet-settings "Permalink") + +* [设置](snippets/index.html)摘要[内容的大小限制](snippets/index.html) :设置摘要内容的最大大小限制. + +## Git configuration options[](#git-configuration-options "Permalink") + +* [服务器挂钩](server_hooks.html) :服务器挂钩(在文件系统上),用于当 Webhooks 不够用时. +* [Git LFS 配置](lfs/index.html) :了解如何为 GitLab 配置 LFS. +* [客房整理](housekeeping.html) :保持您的 Git 存储库整洁,快速. +* [配置 Git 协议 v2](git_protocol.html) :支持 Git 协议版本 2. +* [Manage large files with `git-annex` (Deprecated)](git_annex.html) + +## Monitoring GitLab[](#monitoring-gitlab "Permalink") + +* [Monitoring GitLab](monitoring/index.html): + * [监视正常运行时间](../user/admin_area/monitoring/health_check.html) :使用运行状况检查端点检查服务器状态. + * [IP 白名单](monitoring/ip_whitelist.html) :监视在探查时提供健康检查信息的端点. + * [监视 GitHub 导入](monitoring/github_imports.html) :GitLab 的 GitHub 导入器显示 Prometheus 指标以监视导入器的运行状况和进度. + +### Performance Monitoring[](#performance-monitoring "Permalink") + +* [GitLab Performance Monitoring](monitoring/performance/index.html): + * [启用性能监控](monitoring/performance/gitlab_configuration.html) :启用 GitLab 性能监控. + * [使用 Prometheus 监视 GitLab 性能](monitoring/prometheus/index.html) :配置 GitLab 和 Prometheus 以测量性能指标. + * [使用 Grafana 进行 GitLab 性能监视](monitoring/performance/grafana_configuration.html) :配置 GitLab 以通过图形和仪表板可视化时间序列指标. + * [请求分析](monitoring/performance/request_profiling.html) :获取有关慢速请求的详细资料. + * [效果栏](monitoring/performance/performance_bar.html) :获取当前页面的性能信息. + +## Analytics[](#analytics "Permalink") + +* [Pseudonymizer](pseudonymizer.html) :以安全的方式将数据从 GitLab 的数据库导出到 CSV 文件. + +## Troubleshooting[](#troubleshooting "Permalink") + +* [Debugging tips](troubleshooting/debug.html): Tips to debug problems when things go wrong +* [日志系统](logs.html) :在哪里查找日志. +* [Sidekiq 故障排除](troubleshooting/sidekiq.html) :在 Sidekiq 挂起且不处理作业时进行调试. +* [Troubleshooting Elasticsearch](troubleshooting/elasticsearch.html) +* [Navigating GitLab via Rails console](troubleshooting/navigating_gitlab_via_rails_console.html) +* [GitLab application limits](instance_limits.html) + +### Support Team Docs[](#support-team-docs "Permalink") + +GitLab 支持团队已经收集了许多有关对 GitLab 实例进行故障排除的信息. 这些文档通常由支持团队本身使用,或由客户在支持团队成员的直接指导下使用. GitLab 管理员可能会找到有用的信息来进行故障排除,但是如果您在使用 GitLab 实例时遇到麻烦,则应在参考这些文档之前检查[支持选项](https://about.gitlab.com/support/) . + +**警告:**使用下面文档中列出的命令可能会导致数据丢失或对 GitLab 实例的其他损坏,并且仅应由意识到风险的有经验的管理员使用. + +* [Useful diagnostics tools](troubleshooting/diagnostics_tools.html) +* [Useful Linux commands](troubleshooting/linux_cheat_sheet.html) +* [Troubleshooting Kubernetes](troubleshooting/kubernetes_cheat_sheet.html) +* [Troubleshooting PostgreSQL](troubleshooting/postgresql.html) +* [Guide to test environments](troubleshooting/test_environments.html) (for Support Engineers) +* [GitLab Rails 控制台命令](troubleshooting/gitlab_rails_cheat_sheet.html) (适用于支持工程师) +* [Troubleshooting SSL](troubleshooting/ssl.html) +* 有用的链接: + * [GitLab 开发人员文档](../development/README.html) + * [修复和恢复损坏的 Git 存储库](https://git.seveas.net/repairing-and-recovering-broken-git-repositories.html) + * [使用 OpenSSL 进行测试](https://www.feistyduck.com/library/openssl-cookbook/online/ch-testing-with-openssl.html) + * [`Strace`杂志](https://wizardzines.com/zines/strace/) +* GitLab.com 专用资源: + * [组 SAML / SCIM 设置](troubleshooting/group_saml_scim.html) \ No newline at end of file diff --git a/docs/420.md b/docs/420.md new file mode 100644 index 0000000000000000000000000000000000000000..effd4008cf620778b94c993b01f2c6170fbc7e97 --- /dev/null +++ b/docs/420.md @@ -0,0 +1,167 @@ +# Reference architectures + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/](https://docs.gitlab.com/ee/administration/reference_architectures/) + +* [Available reference architectures](#available-reference-architectures) +* [Availability Components](#availability-components) + * [Automated backups](#automated-backups-core-only) + * [Traffic load balancer](#traffic-load-balancer-starter-only) + * [Zero downtime updates](#zero-downtime-updates-starter-only) + * [Automated database failover](#automated-database-failover-premium-only) + * [Instance level replication with GitLab Geo](#instance-level-replication-with-gitlab-geo-premium-only) +* [Configure GitLab to scale](#configure-gitlab-to-scale) + * [Configuring select components with Cloud Native Helm](#configuring-select-components-with-cloud-native-helm) +* [Footnotes](#footnotes) + +# Reference architectures[](#reference-architectures "Permalink") + +您可以在单个服务器上设置 GitLab 或扩展它以服务许多用户. 本页详细介绍了由 GitLab 的质量和支持团队构建和验证的推荐参考架构. + +下面的图表表示每个体系结构层及其可处理的用户数量. 随着用户数量的增长,建议您相应地调整 GitLab. + +[![Reference Architectures](img/eec4d73b57835f2caa3ad88d45260b49.png)](img/reference-architectures.png) + +这些参考架构的测试是使用[GitLab 的 Performance Tool](https://gitlab.com/gitlab-org/quality/performance)在特定的编码工作负载下进行的,用于测试的吞吐量是根据样本客户数据计算得出的. 选择适合您规模的参考架构后,请参考将[GitLab 配置为可缩放](#configure-gitlab-to-scale)以查看所涉及的组件以及如何配置它们. + +每 1000 个用户使用以下每秒请求数(RPS)测试每种端点类型: + +* API:20 RPS +* 网络:2 RPS +* 转到:2 RPS + +对于用户数少于 2,000 的 GitLab 实例,建议您通过在单个计算机上[安装 GitLab](../../install/README.html)来使用[默认设置](#automated-backups-core-only) ,以最大程度地减少维护和资源成本. + +如果您的组织有 2000 多名用户,则建议将 GitLab 的组件扩展到多个机器节点. 机器节点按组件分组. 这些节点的增加提高了您的 GitLab 实例的性能和可伸缩性. + +扩展 GitLab 时,需要考虑以下几个因素: + +* 多个应用程序节点来处理前端流量. +* 前面添加了一个负载均衡器,以在应用程序节点之间分配流量. +* 应用程序节点连接到共享文件服务器以及后端的 PostgreSQL 和 Redis 服务. + +**注意:**根据您的工作流程,以下建议的参考体系结构可能需要进行相应的调整. 您的工作负载受以下因素影响,这些因素包括用户的活跃程度,使用的自动化程度,镜像和存储库/更改大小. 此外,显示的内存值由[GCP 机器类型提供](https://cloud.google.com/compute/docs/machine-types) . 对于不同的云供应商,请尝试选择最匹配所提供架构的选项. + +## Available reference architectures[](#available-reference-architectures "Permalink") + +提供以下参考体系结构: + +* [Up to 1,000 users](1k_users.html) +* [Up to 2,000 users](2k_users.html) +* [Up to 3,000 users](3k_users.html) +* [Up to 5,000 users](5k_users.html) +* [Up to 10,000 users](10k_users.html) +* [Up to 25,000 users](25k_users.html) +* [Up to 50,000 users](50k_users.html) + +## Availability Components[](#availability-components "Permalink") + +GitLab 随附以下组件供您使用,从最小到最复杂列出: + +1. [Automated backups](#automated-backups-core-only) +2. [Traffic load balancer](#traffic-load-balancer-starter-only) +3. [Zero downtime updates](#zero-downtime-updates-starter-only) +4. [Automated database failover](#automated-database-failover-premium-only) +5. [Instance level replication with GitLab Geo](#instance-level-replication-with-gitlab-geo-premium-only) + +在实现这些组件时,请从单个服务器开始,然后再进行备份. 仅在完成第一台服务器后,才可以继续执行下一个. + +此外,不为 GitLab 实施额外的服务器并不一定意味着您将有更多的停机时间. 根据您的需求和经验水平,单个服务器可以为用户带来更多实际的正常运行时间. + +### Automated backups[](#automated-backups-core-only "Permalink") + +> * 复杂程度: **低** +> * 必需的领域知识:PostgreSQL,GitLab 配置,Git +> * 支持的级别: [GitLab Core,Starter,Premium 和 Ultimate](https://about.gitlab.com/pricing/) + +该解决方案适用于具有默认 GitLab 安装的许多团队. 通过自动备份 GitLab 存储库,配置和数据库,如果您没有严格的要求,这可能是最佳的解决方案. [自动备份](../../raketasks/backup_restore.html#configuring-cron-to-make-daily-backups)的设置最简单. 这提供了预定时间表的时间点恢复. + +### Traffic load balancer[](#traffic-load-balancer-starter-only "Permalink") + +> * 复杂程度: **中** +> * 必需的领域知识:HAProxy,共享存储,分布式系统 +> * 支持的级别: [GitLab Starter,Premium 和 Ultimate](https://about.gitlab.com/pricing/) + +这需要使用添加的[负载平衡器](../high_availability/load_balancer.html)将 GitLab 分离为多个应用程序节点. 负载平衡器将在 GitLab 应用程序节点之间分配流量. 同时,每个应用程序节点都连接到后端的共享文件服务器和数据库系统. 这样,如果其中一台应用程序服务器发生故障,则工作流不会中断. 建议使用[HAProxy](https://www.haproxy.org/)作为负载平衡器. + +与默认安装相比,有了此添加的组件,您具有许多优点: + +* 增加用户数量. +* 启用零停机时间升级. +* 提高可用性. + +### Zero downtime updates[](#zero-downtime-updates-starter-only "Permalink") + +> * 复杂程度: **中** +> * 必需的领域知识:PostgreSQL,HAProxy,共享存储,分布式系统 +> * 支持的级别: [GitLab Starter,Premium 和 Ultimate](https://about.gitlab.com/pricing/) + +GitLab 支持[零停机时间更新](https://docs.gitlab.com/omnibus/update/) . 尽管您可以使用单个 GitLab 节点执行零停机时间更新,但是建议将 GitLab 分为几个应用程序节点. 只要每个组件中的至少一个在线且能够处理实例的使用负载,您的团队的生产力就不会在更新期间被打断. + +### Automated database failover[](#automated-database-failover-premium-only "Permalink") + +> * 复杂程度: **高** +> * 必需的领域知识:PgBouncer,Repmgr 或 Patroni,共享存储,分布式系统 +> * 支持的级别: [GitLab Premium 和 Ultimate](https://about.gitlab.com/pricing/) + +通过为数据库系统添加自动故障转移,可以通过其他数据库节点来提高正常运行时间. 这将使用群集管理和故障转移策略扩展默认数据库. [建议将 PgBouncer 与 Repmgr 或 Patroni 结合使用](../postgresql/replication_and_failover.html) . + +### Instance level replication with GitLab Geo[](#instance-level-replication-with-gitlab-geo-premium-only "Permalink") + +> * 复杂程度: **很高** +> * 必需的域知识:存储复制 +> * 支持的级别: [GitLab Premium 和 Ultimate](https://about.gitlab.com/pricing/) + +[GitLab Geo](../geo/replication/index.html)允许您将 GitLab 实例复制到其他地理位置,作为只读的完全可操作实例,如果发生灾难,也可以升级它. + +## Configure GitLab to scale[](#configure-gitlab-to-scale "Permalink") + +**Note:** From GitLab 13.0, using NFS for Git repositories is deprecated. In GitLab 14.0, support for NFS for Git repositories is scheduled to be removed. Upgrade to [Gitaly Cluster](../gitaly/praefect.html) as soon as possible. + +以下组件是您需要配置以扩展 GitLab 的组件. 如果您选择的[参考体系结构](#reference-architectures)要求它们,则按照通常配置它们的顺序列出它们. + +它们大多数捆绑在 GitLab deb / rpm 软件包(称为 Omnibus GitLab)中,但是根据您的系统架构,您可能需要其中未包含的某些组件. 如果需要,应在设置 GitLab 提供的组件之前对其进行配置. 配置说明列中提供了有关如何为您的组织选择正确的解决方案的建议. + +| Component | Description | 配置说明 | 与 Omnibus GitLab 捆绑在一起 | +| --- | --- | --- | --- | +| 负载均衡器( [6](#footnotes) ) | 处理负载平衡,通常在您有多个 GitLab 应用程序服务节点时 | [Load balancer configuration](../high_availability/load_balancer.html) ([6](#footnotes)) | No | +| 对象存储服务( [4](#footnotes) ) | 推荐的共享数据对象存储 | [Object Storage configuration](../object_storage.html) | No | +| NFS( [5](#footnotes) )( [7](#footnotes) ) | 共享磁盘存储服务. 可以用作备用对象存储. GitLab 页面必需 | [NFS configuration](../high_availability/nfs.html) | No | +| [Consul](../../development/architecture.html#consul) ([3](#footnotes)) | Service discovery and health checks/failover | [Consul configuration](../high_availability/consul.html) | Yes | +| [PostgreSQL](../../development/architecture.html#postgresql) | Database | [PostgreSQL configuration](https://docs.gitlab.com/omnibus/settings/database.html) | Yes | +| [PgBouncer](../../development/architecture.html#pgbouncer) | 数据库连接池 | [PgBouncer configuration](../high_availability/pgbouncer.html#running-pgbouncer-as-part-of-a-non-ha-gitlab-installation) | Yes | +| Repmgr | PostgreSQL 集群管理和故障转移 | [PostgreSQL and Repmgr configuration](../postgresql/replication_and_failover.html) | Yes | +| Patroni | 替代的 PostgreSQL 集群管理和故障转移 | [PostgreSQL and Patroni configuration](../postgresql/replication_and_failover.html#patroni) | Yes | +| [Redis](../../development/architecture.html#redis) ([3](#footnotes)) | 键/值存储,用于快速查找和缓存数据 | [Redis configuration](../high_availability/redis.html) | Yes | +| Redis 前哨 | Redis | [Redis Sentinel configuration](../high_availability/redis.html) | Yes | +| [吉塔利](../../development/architecture.html#gitaly) ( [2](#footnotes) )( [7](#footnotes) ) | 提供对 Git 存储库的访问 | [Gitaly configuration](../gitaly/index.html#run-gitaly-on-its-own-server) | Yes | +| [Sidekiq](../../development/architecture.html#sidekiq) | 异步/后台作业 | [Sidekiq configuration](../high_availability/sidekiq.html) | Yes | +| [GitLab application services](../../development/architecture.html#unicorn)([1](#footnotes)) | Puma / Unicorn,Workhorse,GitLab Shell-服务于前端请求(UI,API,基于 HTTP / SSH 的 Git) | [GitLab app scaling configuration](../high_availability/gitlab.html) | Yes | +| [Prometheus](../../development/architecture.html#prometheus) and [Grafana](../../development/architecture.html#grafana) | GitLab 环境监控 | [Monitoring node for scaling](../high_availability/monitoring_node.html) | Yes | + +### Configuring select components with Cloud Native Helm[](#configuring-select-components-with-cloud-native-helm "Permalink") + +我们还提供[Helm 图表](https://docs.gitlab.com/charts/)作为 GitLab 的 Cloud Native 安装方法. 对于参考体系结构,如果需要,可以以这种方式设置选择组件. + +对于此类设置,我们支持在[高级配置](https://docs.gitlab.com/charts/)中使用图表,在这些[高级配置中](https://docs.gitlab.com/charts/) ,有状态后端组件(例如数据库或 Gitaly)可通过 Omnibus 或信誉良好的第三方服务在外部运行. 请注意,我们目前不支持通过 Helm *大规模*运行有状态组件. + +设计这些环境时,应[参考](#available-reference-architectures)上面的相应[参考体系结构](#available-reference-architectures)以获取有关大小调整的指导. 通过 Helm 运行的组件将按类似比例缩放到其 Omnibus 规格,仅转换为 Kubernetes 资源. + +例如,如果您要设置一个 50k 的安装,并且 Rails 节点在 Helm 中运行,那么应该为 Kubernetes 集群提供与 Omnibus 相同数量的资源,并且将 Rails 节点分解为多个较小的 Pod 跨集群. + +## Footnotes[](#footnotes "Permalink") + +1. 在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数量设置为 90%的可用 CPU 以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +2. Gitaly 节点的要求取决于客户数据,特别是项目数量及其规模. 我们建议每个 Gitaly 节点应存储不超过 5TB 的数据,并且将[`gitaly-ruby`工作者](../gitaly/index.html#gitaly-ruby)的数量设置为可用 CPU 的 20%. 根据以上建议,应结合其他节点并结合对预期数据大小和分布的审查. + +3. 推荐的 Redis 设置因架构的大小而异. 对于较小的体系结构(少于 3000 个用户),一个实例就足够了. 对于中型安装(3,000-5,000),我们建议为所有课程使用一个 Redis 集群,并且 Redis Sentinel 与 Consul 一起托管. 对于较大的体系结构(10,000 个或更多用户),我们建议分别为 Cache 类和队列和 Shared State 类运行一个单独的[Redis 群集](../redis/replication_and_failover.html#running-multiple-redis-clusters) . 我们还建议您为每个 Redis 群集分别运行 Redis Sentinel 群集. + +4. 对于 LFS,Uploads,Artifacts 等数据对象.由于性能更好,我们建议尽可能在 NFS 上使用[对象存储服务](../object_storage.html) . + +5. NFS 可以用作对象存储的替代方法,但是出于性能考虑,通常不建议使用 NFS. 请注意,但是[GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)是必需的. + +6. 我们的架构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +7. 我们强烈建议为任何 Gitaly 或 NFS 节点设置 HDD 之上的 SSD 磁盘,其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS,因为这些组件的 I / O 繁重. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您正在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +8. 这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. \ No newline at end of file diff --git a/docs/421.md b/docs/421.md new file mode 100644 index 0000000000000000000000000000000000000000..5a41f039d2cb0afa142b9731f00a805d98baaa19 --- /dev/null +++ b/docs/421.md @@ -0,0 +1,46 @@ +# Reference architecture: up to 1,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/1k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/1k_users.html) + +* [Setup instructions](#setup-instructions) +* [Footnotes](#footnotes) + +# Reference architecture: up to 1,000 users[](#reference-architecture-up-to-1000-users "Permalink") + +该页面描述了最多可容纳 1,000 位用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +> * **支持的用户(大约):** 1,000 +> * **高可用性:** False + +| Users | Configuration([8](#footnotes)) | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | +| 500 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | +| 1000 | 8 个 vCPU,7.2GB 内存 | `n1-highcpu-8` | `c5.2xlarge` | F8s v2 | + +除上述之外,即使您当前有足够的可用 RAM,我们也建议您在服务器上至少有 2GB 的交换空间. 如果您的可用内存发生更改,那么进行交换将有助于减少发生错误的机会. 我们还建议将内核的 swappiness 设置配置为较低的值(例如`10`以充分利用您的 RAM,同时在需要时仍可使用交换功能. + +对于需要服务多达 1,000 个用户的情况,具有[频繁备份](index.html#automated-backups-core-only)的单节点解决方案适用于许多组织. 通过自动备份 GitLab 存储库,配置和数据库,如果您对可用性没有严格的要求,这是理想的解决方案. + +## Setup instructions[](#setup-instructions "Permalink") + +* 对于此默认参考体系结构,请使用标准[安装说明](../../install/README.html)来安装 GitLab. + +**注意:**您还可以选择将 GitLab 配置为使用[外部 PostgreSQL 服务](../postgresql/external.html)或[外部对象存储服务](../high_availability/object_storage.html) ,从而以降低的复杂性成本来提高性能和可靠性. + +## Footnotes[](#footnotes "Permalink") + +1. 在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数量设置为 90%的可用 CPU 以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +2. Gitaly 节点的要求取决于客户数据,特别是项目数量及其规模. 对于 HA 环境,我们建议绝对最少使用两个节点,并且在支持 50,000 个或更多用户时,至少应使用四个节点. 我们还建议每个 Gitaly 节点存储的数据不得超过 5TB,并且将[`gitaly-ruby`工作者](../gitaly/index.html#gitaly-ruby)的数量设置为可用 CPU 的 20%. 根据以上建议,应结合其他节点并结合对预期数据大小和分布的审查. + +3. Recommended Redis setup differs depending on the size of the architecture. For smaller architectures (less than 3,000 users) a single instance should suffice. For medium sized installs (3,000 - 5,000) we suggest one Redis cluster for all classes and that Redis Sentinel is hosted alongside Consul. For larger architectures (10,000 users or more) we suggest running a separate [Redis Cluster](../redis/replication_and_failover.html#running-multiple-redis-clusters) for the Cache class and another for the Queues and Shared State classes respectively. We also recommend that you run the Redis Sentinel clusters separately for each Redis Cluster. + +4. 对于 LFS,Uploads,Artifacts 等数据对象.由于性能和可用性更好,我们建议尽可能在 NFS 上使用[对象存储服务](../object_storage.html) . + +5. NFS 可以用作存储库数据(替代 Gitaly)和对象存储的替代方法,但是出于性能原因,通常不建议使用 NFS. 请注意,但是[GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)是必需的. + +6. 我们的架构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +7. 我们强烈建议为任何 Gitaly 或 NFS 节点设置 HDD 之上的 SSD 磁盘,其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS,因为这些组件的 I / O 繁重. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您正在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +8. 这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. \ No newline at end of file diff --git a/docs/422.md b/docs/422.md new file mode 100644 index 0000000000000000000000000000000000000000..ee6dea952f1c18cb2e2bcb5bdb6b2f98e9e0041d --- /dev/null +++ b/docs/422.md @@ -0,0 +1,657 @@ +# Reference architecture: up to 2,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/2k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/2k_users.html) + +* [Setup components](#setup-components) +* [Configure the load balancer](#configure-the-load-balancer) + * [Application node terminates SSL](#application-node-terminates-ssl) + * [Load balancer terminates SSL without backend SSL](#load-balancer-terminates-ssl-without-backend-ssl) + * [Load balancer terminates SSL with backend SSL](#load-balancer-terminates-ssl-with-backend-ssl) + * [Ports](#ports) + * [Alternate SSH Port](#alternate-ssh-port) +* [Configure PostgreSQL](#configure-postgresql) + * [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance) + * [Standalone PostgreSQL using Omnibus GitLab](#standalone-postgresql-using-omnibus-gitlab) +* [Configure Redis](#configure-redis) + * [Provide your own Redis instance](#provide-your-own-redis-instance) + * [Standalone Redis using Omnibus GitLab](#standalone-redis-using-omnibus-gitlab) +* [Configure Gitaly](#configure-gitaly) + * [Gitaly TLS support](#gitaly-tls-support) +* [Configure GitLab Rails](#configure-gitlab-rails) +* [Configure Prometheus](#configure-prometheus) +* [Configure the object storage](#configure-the-object-storage) +* [Configure NFS (optional)](#configure-nfs-optional) +* [Troubleshooting](#troubleshooting) + +# Reference architecture: up to 2,000 users[](#reference-architecture-up-to-2000-users "Permalink") + +该页面描述了最多可容纳 2,000 位用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +> * **支持的用户(大约):** 2,000 +> * **高可用性:** False +> * **每秒测试请求(RPS)速率:** API:40 RPS,Web:4 RPS,Git:4 RPS + +| Service | Nodes | Configuration | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | --- | +| 负载均衡器 | 1 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| PostgreSQL | 1 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| Redis | 1 | 1 个 vCPU,3.75GB 内存 | `n1-standard-1` | `m5.large` | `D2s v3` | +| Gitaly | 1 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | `D4s v3` | +| 亚搏体育 app Rails | 2 | 8 个 vCPU,7.2GB 内存 | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` | +| 监控节点 | 1 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| 对象存储 | n/a | n/a | n/a | n/a | n/a | +| NFS 服务器(可选,不推荐) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` | + +Google Cloud Platform(GCP)架构是使用[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行更低或更高的调整. 有关更多信息,请参见我们基于[Sysbench](https://github.com/akopytov/sysbench)的[CPU 基准测试](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks) . + +由于具有更好的性能和可用性,对于数据对象(例如 LFS,上载或工件),建议使用[对象存储服务](#configure-the-object-storage)而不是 NFS. 使用对象存储服务也不需要您配置和维护节点. + +## Setup components[](#setup-components "Permalink") + +设置 GitLab 及其组件以容纳多达 2,000 个用户: + +1. [配置外部负载平衡节点](#configure-the-load-balancer)以处理两个 GitLab 应用程序服务节点的负载平衡. +2. [配置 PostgreSQL](#configure-postgresql) (GitLab 的数据库). +3. [Configure Redis](#configure-redis). +4. [配置 Gitaly](#configure-gitaly) ,它提供对 Git 存储库的访问. +5. [配置主要的 GitLab Rails 应用程序](#configure-gitlab-rails)以运行 Puma / Unicorn,Workhorse,GitLab Shell,并满足所有前端请求(包括 UI,API 和基于 HTTP / SSH 的 Git). +6. [配置 Prometheus](#configure-prometheus)来监视您的 GitLab 环境. +7. [配置](#configure-the-object-storage)用于共享数据对象[的对象存储](#configure-the-object-storage) . +8. [配置 NFS](#configure-nfs-optional) (可选,不建议使用)以具有共享磁盘存储服务,以替代 Gitaly 或对象存储. 如果您不使用 GitLab 页面(需要 NFS),则可以跳过此步骤. + +## Configure the load balancer[](#configure-the-load-balancer "Permalink") + +**注意:**此体系结构已经过[HAProxy 的](https://www.haproxy.org/)测试和验证. 尽管您可以使用具有类似功能的负载均衡器,但 GitLab 尚未验证其他负载均衡器. + +在主动/主动 GitLab 配置中,您需要一个负载平衡器才能将流量路由到应用程序服务器. GitLab 文档超出了使用负载平衡器或其确切配置的详细信息. 如果要管理多节点系统(包括 GitLab),则可能已经选择了负载均衡器. 一些示例包括 HAProxy(开源),F5 Big-IP LTM 和 Citrix Net Scaler. 本文档包括与 GitLab 一起使用的端口和协议. + +下一个问题是如何在环境中处理 SSL. 有几种不同的选择: + +* [The application node terminates SSL](#application-node-terminates-ssl). +* [负载平衡器终止没有后端 SSL 的 SSL,](#load-balancer-terminates-ssl-without-backend-ssl)并且负载平衡器与应用程序节点之间的通信不安全. +* [负载均衡器使用后端 SSL 终止 SSL,](#load-balancer-terminates-ssl-with-backend-ssl)并且负载均衡器与应用程序节点之间的通信是*安全*的. + +### Application node terminates SSL[](#application-node-terminates-ssl "Permalink") + +配置您的负载均衡器以将端口 443 上的连接作为`TCP`而不是`HTTP(S)`传递. 这会将连接保持不变地传递到应用程序节点的 NGINX 服务,该服务具有 SSL 证书并侦听端口 443. + +有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load balancer terminates SSL without backend SSL[](#load-balancer-terminates-ssl-without-backend-ssl "Permalink") + +将负载平衡器配置为使用`HTTP(S)`协议而不是`TCP` . 负载平衡器将负责管理 SSL 证书和终止 SSL. + +由于负载平衡器和 GitLab 之间的通信不安全,因此您需要完成一些其他配置. 有关详细信息,请参见[NGINX 代理的 SSL 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load balancer terminates SSL with backend SSL[](#load-balancer-terminates-ssl-with-backend-ssl "Permalink") + +配置您的负载平衡器(如果只有一个,则为单个平衡器)以使用`HTTP(S)`协议而不是`TCP` . 负载平衡器将负责为最终用户管理 SSL 证书. + +在这种情况下,负载平衡器和 NGINX 之间的流量将是安全的,并且无需为代理 SSL 添加配置. 但是,您需要向 GitLab 添加配置以配置 SSL 证书. 有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Ports[](#ports "Permalink") + +The basic load balancer ports you should use are described in the following table: + +| Port | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 80 | HTTP( *1* ) | +| 443 | 443 | TCP 或 HTTPS( *1* )( *2* ) | +| 22 | 22 | TCP | + +* ( *1* ): [Web 终端](../../ci/environments/index.html#web-terminals)支持要求您的负载平衡器正确处理 WebSocket 连接. 当使用 HTTP 或 HTTPS 代理,负载平衡器必须被配置为通过`Connection`和`Upgrade`逐跳头. 有关详细信息,请参见[Web 终端](../integration/terminal.html)集成指南. +* ( *2* ):在端口 443 上使用 HTTPS 协议时,您需要向负载均衡器添加 SSL 证书. 如果需要在 GitLab 应用程序服务器上终止 SSL,请使用 TCP 协议. + +如果您使用具有自定义域支持的 GitLab 页面,则将需要一些其他端口配置. GitLab 页面需要一个单独的虚拟 IP 地址. 配置 DNS,以将`pages_external_url`的`/etc/gitlab/gitlab.rb`指向新的虚拟 IP 地址. 有关更多信息,请参见[GitLab 页面文档](../pages/index.html) . + +| Port | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 变化( *1* ) | HTTP | +| 443 | 变化( *1* ) | TCP( *2* ) | + +* ( *1* ):GitLab 页面的后端端口取决于`gitlab_pages['external_http']`和`gitlab_pages['external_https']`设置. 有关详细信息,请参见[GitLab 页面文档](../pages/index.html) . +* ( *2* ):GitLab 页面的端口 443 必须使用 TCP 协议. 用户可以使用自定义 SSL 配置自定义域,如果 SSL 在负载均衡器处终止,则无法实现. + +#### Alternate SSH Port[](#alternate-ssh-port "Permalink") + +某些组织有禁止打开 SSH 端口 22 的策略.在这种情况下,配置备用 SSH 主机名可能会有所帮助,该主机名改为允许用户通过端口 443 使用 SSH.与先前描述的相比,备用 SSH 主机名需要新的虚拟 IP 地址. GitLab HTTP 配置. + +为备用 SSH 主机名配置 DNS,例如`altssh.gitlab.example.com` : + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 443 | 22 | TCP | + +[Back to setup components](#setup-components) + +## Configure PostgreSQL[](#configure-postgresql "Permalink") + +在本节中,将指导您配置与 GitLab 一起使用的外部 PostgreSQL 数据库. + +### Provide your own PostgreSQL instance[](#provide-your-own-postgresql-instance "Permalink") + +如果您将 GitLab 托管在云提供商上,则可以选择将托管服务用于 PostgreSQL. 例如,AWS 提供了运行 PostgreSQL 的托管关系数据库服务(RDS). + +如果您使用云托管服务,或提供自己的 PostgreSQL: + +1. 根据[数据库要求文档](../../install/requirements.html#database)设置 PostgreSQL. +2. 使用您选择的密码创建一个`gitlab`用户名. `gitlab`用户需要特权才能创建`gitlabhq_production`数据库. +3. 使用适当的详细信息配置 GitLab 应用程序服务器. [配置 GitLab Rails 应用程序](#configure-gitlab-rails)涵盖了此步骤. + +### Standalone PostgreSQL using Omnibus GitLab[](#standalone-postgresql-using-omnibus-gitlab "Permalink") + +1. SSH 进入 PostgreSQL 服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 不要完成下载页面上的任何其他步骤. +3. 为 PostgreSQL 生成密码哈希. 假设您将使用默认用户名`gitlab` (推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作`POSTGRESQL_PASSWORD_HASH`的值. + + ``` + sudo gitlab-ctl pg-password-md5 gitlab + ``` + +4. 编辑`/etc/gitlab/gitlab.rb`并添加以下内容,以适当地更新占位符值. + + * `POSTGRESQL_PASSWORD_HASH`上一步的输出值 + * `APPLICATION_SERVER_IP_BLOCKS`将连接到数据库的 GitLab 应用程序服务器的 IP 子网或 IP 地址的空格分隔列表. 示例: `%w(123.123.123.123/32 123.123.123.234/32)` + + ``` + # Disable all components except PostgreSQL + roles ['postgres_role'] + repmgr['enable'] = false + consul['enable'] = false + prometheus['enable'] = false + alertmanager['enable'] = false + pgbouncer_exporter['enable'] = false + redis_exporter['enable'] = false + gitlab_exporter['enable'] = false + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + postgres_exporter['dbname'] = 'gitlabhq_production' + postgres_exporter['password'] = 'POSTGRESQL_PASSWORD_HASH' + + # Set the PostgreSQL address and port + postgresql['listen_address'] = '0.0.0.0' + postgresql['port'] = 5432 + + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH' + + # Replace APPLICATION_SERVER_IP_BLOCK with the CIDR address of the application node + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 APPLICATION_SERVER_IP_BLOCK) + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + ``` + +5. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +6. 注意 PostgreSQL 节点的 IP 地址或主机名,端口和纯文本密码. 这些在以后配置[GitLab 应用程序服务器](#configure-gitlab-rails)时是必需的. + +支持高级[配置选项](https://docs.gitlab.com/omnibus/settings/database.html) ,可以根据需要添加. + +[Back to setup components](#setup-components) + +## Configure Redis[](#configure-redis "Permalink") + +在本节中,将指导您配置与 GitLab 一起使用的外部 Redis 实例. + +### Provide your own Redis instance[](#provide-your-own-redis-instance "Permalink") + +需要 Redis 5.0 或更高版本,因为这是从 GitLab 13.0 开始的 Omnibus GitLab 软件包附带的版本. 较旧的 Redis 版本不支持 SPOP 的可选 count 参数,这对于[合并火车](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)现在是必需的. + +此外,GitLab 还利用了某些命令,例如`UNLINK`和`USAGE` ,这些命令仅在 Redis 4 中引入. + +来自云提供商(例如 AWS ElastiCache)的托管 Redis 将可以使用. 如果这些服务支持高可用性,请确保它不是 Redis 群集类型. + +注意 Redis 节点的 IP 地址或主机名,端口和密码(如果需要). 这些在以后配置[GitLab 应用程序服务器](#configure-gitlab-rails)时是必需的. + +### Standalone Redis using Omnibus GitLab[](#standalone-redis-using-omnibus-gitlab "Permalink") + +Omnibus GitLab 软件包可用于配置独立的 Redis 服务器. 以下步骤是使用 Omnibus 配置 Redis 服务器的最低必需步骤: + +1. SSH 进入 Redis 服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + ## Enable Redis + redis['enable'] = true + + ## Disable all other services + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + postgresql['enable'] = false + nginx['enable'] = false + prometheus['enable'] = false + alertmanager['enable'] = false + pgbouncer_exporter['enable'] = false + gitlab_exporter['enable'] = false + gitaly['enable'] = false + grafana['enable'] = false + + redis['bind'] = '0.0.0.0' + redis['port'] = 6379 + redis['password'] = 'SECRET_PASSWORD_HERE' + + gitlab_rails['enable'] = false + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + redis_exporter['flags'] = { + 'redis.addr' => 'redis://0.0.0.0:6379', + 'redis.password' => 'SECRET_PASSWORD_HERE', + } + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +5. 注意 Redis 节点的 IP 地址或主机名,端口和 Redis 密码. 这些在以后[配置 GitLab 应用程序服务器](#configure-gitlab-rails)时是必需的. + +支持高级[配置选项](https://docs.gitlab.com/omnibus/settings/redis.html) ,可以根据需要添加. + +[Back to setup components](#setup-components) + +## Configure Gitaly[](#configure-gitaly "Permalink") + +在自己的服务器上部署 Gitaly 可以使大于单个计算机的 GitLab 安装受益. Gitaly 节点的要求取决于数据,特别是项目的数量及其大小. 建议每个 Gitaly 节点存储的数据量不得超过 5TB. 您的 2K 设置可能需要一个或多个节点,具体取决于您的存储库存储要求. + +我们强烈建议所有 Gitaly 节点都安装 SSD 磁盘,因为 Gitaly I / O 繁重,因此其读取操作的吞吐量至少为 8,000 IOPS,写入操作的吞吐量至少为 2,000 IOPS. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您正在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +Some things to note: + +* GitLab Rails 应用程序将[存储库分](../repository_storage_paths.html)片到[存储库中](../repository_storage_paths.html) . +* A Gitaly server can host one or more storages. +* 一个 GitLab 服务器可以使用一个或多个 Gitaly 服务器. +* 必须以对所有 Gitaly 客户端正确解析的方式指定 Gitaly 地址. +* Gitaly 服务器一定不能暴露在公共互联网上,因为默认情况下,Gitaly 的网络流量是未加密的. 强烈建议使用防火墙以限制对 Gitaly 服务器的访问. 另一种选择是[使用 TLS](#gitaly-tls-support) . + +**提示:**有关 Gitaly 历史和网络体系结构的更多信息,请参见[独立的 Gitaly 文档](../gitaly/index.html) . + +注意: **注意:** Gitaly 文档中引用的令牌只是管理员选择的任意密码. 它与为 GitLab API 创建的令牌或其他类似的 Web API 令牌无关. + +下面我们将介绍如何配置一个 Gitaly 服务器`gitaly1.internal`与秘密令牌`gitalysecret` . 我们假设您的 GitLab 安装有两个存储库存储: `default`和`storage1` . + +要配置 Gitaly 服务器: + +1. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包,但**不**提供`EXTERNAL_URL`值. +2. 编辑`/etc/gitlab/gitlab.rb`以配置存储路径,启用网络侦听器并配置令牌: + + ``` + # /etc/gitlab/gitlab.rb + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the GitLab Rails application setup + gitaly['auth_token'] = 'gitlaysecret' + gitlab_shell['secret_token'] = 'shellsecret' + + # Avoid running unnecessary services on the Gitaly server + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + grafana['enable'] = false + + # If you run a seperate monitoring node you can disable these services + alertmanager['enable'] = false + prometheus['enable'] = false + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your 'front door' GitLab URL or an internal load + # balancer. + # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server. + gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' + + # Make Gitaly accept connections on all network interfaces. You must use + # firewalls to restrict access to this address/port. + # Comment out following line if you only want to support TLS connections + gitaly['listen_addr'] = "0.0.0.0:8075" + gitaly['prometheus_listen_addr'] = "0.0.0.0:9236" + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + ``` + +3. 将以下内容添加到`/etc/gitlab/gitlab.rb`上的`gitaly1.internal` : + + ``` + git_data_dirs({ + 'default' => { + 'path' => '/var/opt/gitlab/git-data' + }, + 'storage1' => { + 'path' => '/mnt/gitlab/git-data' + }, + }) + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 确认 Gitaly 可以执行对内部 API 的回调: + + ``` + sudo /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml + ``` + +### Gitaly TLS support[](#gitaly-tls-support "Permalink") + +Gitaly 支持 TLS 加密. 为了能够与侦听安全连接的 Gitaly 实例进行通信,您将需要在 GitLab 配置中相应存储条目的`gitaly_address`中使用`tls://` URL 方案. + +您将需要携带自己的证书,因为该证书不会自动提供. 证书或其证书颁发机构必须按照[GitLab 自定义证书配置中](https://docs.gitlab.com/omnibus/settings/ssl.html)所述的步骤,安装在所有 Gitaly 节点(包括使用证书的 Gitaly 节点)上,以及与之通信的所有客户端节点上. + +**注意:**自签名证书必须指定用于访问 Gitaly 服务器的地址. 如果要通过主机名寻址 Gitaly 服务器,则可以为此使用"公用名"字段,也可以将其添加为"使用者备用名". 如果要通过 Gitaly 服务器的 IP 地址对其进行寻址,则必须将其作为主题备用名称添加到证书中. [gRPC 不支持在证书中使用 IP 地址作为公用名](https://github.com/grpc/grpc/issues/2691) .**注意:**可以同时为 Gitaly 服务器配置未加密的侦听地址`listen_addr`和已加密的侦听地址`tls_listen_addr` . 如果需要,这使您可以从未加密的流量逐渐过渡到加密的流量. + +要使用 TLS 配置 Gitaly: + +1. 创建`/etc/gitlab/ssl`目录,并在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +2. 将证书复制到`/etc/gitlab/trusted-certs`以便 Gitaly 在调用自身时信任该证书: + + ``` + sudo cp /etc/gitlab/ssl/cert.pem /etc/gitlab/trusted-certs/ + ``` + +3. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + gitaly['tls_listen_addr'] = "0.0.0.0:9999" + gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + gitaly['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +4. Delete `gitaly['listen_addr']` to allow only encrypted connections. +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +[Back to setup components](#setup-components) + +## Configure GitLab Rails[](#configure-gitlab-rails "Permalink") + +**注意:**在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数设置为可用 CPU 的 90%以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +本节介绍如何配置 GitLab 应用程序(Rails)组件. 在每个节点上执行以下操作: + +1. 如果您[使用的是 NFS](#configure-nfs-optional) : + + 1. 如有必要,请使用以下命令安装 NFS 客户端实用程序软件包: + + ``` + # Ubuntu/Debian + apt-get install nfs-common + + # CentOS/Red Hat + yum install nfs-utils nfs-utils-lib + ``` + + 2. 在`/etc/fstab`指定必要的 NFS 挂载. `/etc/fstab`的确切内容取决于您选择配置 NFS 服务器的方式. 有关示例和各种选项,请参见[NFS 文档](../high_availability/nfs.html) . + + 3. 创建共享目录. 这些可能会有所不同,具体取决于您的 NFS 安装位置. + + ``` + mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data + ``` + +2. 使用[GitLab 下载中的](https://about.gitlab.com/install/) **步骤 1 和 2**下载/安装 Omnibus GitLab. 不要完成下载页面上的其他步骤. +3. 创建/编辑`/etc/gitlab/gitlab.rb`并使用以下配置. 为了保持整个节点的链接均匀性, `external_url`在应用服务器上应指向外部 URL,用户将用来访问 GitLab. 这将是[负载均衡器](#configure-the-load-balancer)的 URL,它将把流量路由到 GitLab 应用程序服务器: + + ``` + external_url 'https://gitlab.example.com' + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the Gitaly setup + gitlab_rails['gitaly_token'] = 'gitalyecret' + gitlab_shell['secret_token'] = 'shellsecret' + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + + ## Disable components that will not be on the GitLab application server + roles ['application_role'] + gitaly['enable'] = false + nginx['enable'] = true + + ## PostgreSQL connection details + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['db_host'] = '10.1.0.5' # IP/hostname of database server + gitlab_rails['db_password'] = 'DB password' + + ## Redis connection details + gitlab_rails['redis_port'] = '6379' + gitlab_rails['redis_host'] = '10.1.0.6' # IP/hostname of Redis server + gitlab_rails['redis_password'] = 'Redis Password' + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' + sidekiq['listen_address'] = "0.0.0.0" + puma['listen'] = '0.0.0.0' + + # Add the monitoring node's IP address to the monitoring whitelist and allow it to + # scrape the NGINX metrics. Replace placeholder `monitoring.gitlab.example.com` with + # the address and/or subnets gathered from the monitoring node + gitlab_rails['monitoring_whitelist'] = ['/32', '127.0.0.0/8'] + nginx['status']['options']['allow'] = ['/32', '127.0.0.0/8'] + + ## Uncomment and edit the following options if you have set up NFS + ## + ## Prevent GitLab from starting if NFS data mounts are not available + ## + #high_availability['mountpoint'] = '/var/opt/gitlab/git-data' + ## + ## Ensure UIDs and GIDs match between servers for permissions via NFS + ## + #user['uid'] = 9000 + #user['gid'] = 9000 + #web_server['uid'] = 9001 + #web_server['gid'] = 9001 + #registry['uid'] = 9002 + #registry['gid'] = 9002 + ``` + +4. 如果您正在使用[具有 TLS 支持](#gitaly-tls-support)的`git_data_dirs` ,请确保`git_data_dirs`条目配置了`tls`而不是`tcp` : + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' }, + }) + ``` + + 1. 将证书复制到`/etc/gitlab/trusted-certs` : + + ``` + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +6. 运行`sudo gitlab-rake gitlab:gitaly:check`确认节点可以连接到 Gitaly. +7. 拖尾日志以查看请求: + + ``` + sudo gitlab-ctl tail gitaly + ``` + +**注意:**如上例所示,当在`external_url`指定`https`时,GitLab 会假定您在`/etc/gitlab/ssl/`具有 SSL 证书. 如果没有证书,NGINX 将无法启动. 有关更多信息,请参见[NGINX 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) .[Back to setup components](#setup-components) + +## Configure Prometheus[](#configure-prometheus "Permalink") + +The Omnibus GitLab package can be used to configure a standalone Monitoring node running [Prometheus](../monitoring/prometheus/index.html) and [Grafana](../monitoring/performance/grafana_configuration.html): + +1. SSH 进入"监视"节点. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + external_url 'http://gitlab.example.com' + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Login form + grafana['disable_login_form'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = 'toomanysecrets' + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + node_exporter['enable'] = false + gitlab_exporter['enable'] = false + ``` + +4. Prometheus 还需要一些抓取配置,以从我们配置了导出器的各个节点中提取所有数据. 假设您节点的 IP 为: + + ``` + 1.1.1.1: postgres + 1.1.1.2: redis + 1.1.1.3: gitaly1 + 1.1.1.4: rails1 + 1.1.1.5: rails2 + ``` + + 将以下内容添加到`/etc/gitlab/gitlab.rb` : + + ``` + prometheus['scrape_configs'] = [ + { + 'job_name': 'postgres', + 'static_configs' => [ + 'targets' => ['1.1.1.1:9187'], + ], + }, + { + 'job_name': 'redis', + 'static_configs' => [ + 'targets' => ['1.1.1.2:9121'], + ], + }, + { + 'job_name': 'gitaly', + 'static_configs' => [ + 'targets' => ['1.1.1.3:9236'], + ], + }, + { + 'job_name': 'gitlab-nginx', + 'static_configs' => [ + 'targets' => ['1.1.1.4:8060', '1.1.1.5:8060'], + ], + }, + { + 'job_name': 'gitlab-workhorse', + 'static_configs' => [ + 'targets' => ['1.1.1.4:9229', '1.1.1.5:9229'], + ], + }, + { + 'job_name': 'gitlab-rails', + 'metrics_path': '/-/metrics', + 'static_configs' => [ + 'targets' => ['1.1.1.4:8080', '1.1.1.5:8080'], + ], + }, + { + 'job_name': 'gitlab-sidekiq', + 'static_configs' => [ + 'targets' => ['1.1.1.4:8082', '1.1.1.5:8082'], + ], + }, + { + 'job_name': 'node', + 'static_configs' => [ + 'targets' => ['1.1.1.1:9100', '1.1.1.2:9100', '1.1.1.3:9100', '1.1.1.4:9100', '1.1.1.5:9100'], + ], + }, + ] + ``` + +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +6. 在 GitLab 用户界面中,将`admin/application_settings/metrics_and_profiling` >指标-Grafana 设置为`/-/grafana`到`http[s]:///-/grafana` + +[Back to setup components](#setup-components) + +## Configure the object storage[](#configure-the-object-storage "Permalink") + +GitLab 支持使用对象存储服务来保存多种类型的数据,建议在[NFS 上使用](#configure-nfs-optional) . 通常,对象存储服务更适合较大的环境,因为对象存储通常具有更高的性能,可靠性和可伸缩性. + +GitLab 已测试或了解客户使用的对象存储选项包括: + +* SaaS / Cloud 解决方案(例如[Amazon S3](https://aws.amazon.com/s3/)或[Google Cloud Storage](https://cloud.google.com/storage) ). +* 来自各种存储供应商的本地硬件和设备. +* MinIO( [部署指南](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) ). + +要将 GitLab 配置为使用对象存储,请根据要使用的功能参考以下指南: + +1. [Object storage for backups](../../raketasks/backup_restore.html#uploading-backups-to-a-remote-cloud-storage). +2. [Object storage for job artifacts](../job_artifacts.html#using-object-storage) including [incremental logging](../job_logs.html#new-incremental-logging-architecture). +3. [Object storage for LFS objects](../lfs/index.html#storing-lfs-objects-in-remote-object-storage). +4. [Object storage for uploads](../uploads.html#using-object-storage-core-only). +5. [Object storage for merge request diffs](../merge_request_diffs.html#using-object-storage). +6. [容器注册表的对象存储](../packages/container_registry.html#use-object-storage) (可选功能). +7. [Mattermost 的对象存储](https://docs.mattermost.com/administration/config-settings.html#file-storage) (可选功能). +8. [包的对象存储](../packages/index.html#using-object-storage) (可选功能). +9. [依赖代理的对象存储](../packages/dependency_proxy.html#using-object-storage) (可选功能). +10. [Pseudonymizer 的对象存储](../pseudonymizer.html#configuration) (可选功能). +11. [用于自动缩放 Runner 缓存的对象存储](https://docs.gitlab.com/runner/configuration/autoscale.html) (可选,以提高性能). +12. [Object storage for Terraform state files](../terraform_state.html#using-object-storage-core-only). + +对于 GitLab,建议为每种数据类型使用单独的存储桶. + +我们的配置的局限性是对象存储的每次使用都是单独配置的. 我们有一个[问题](https://gitlab.com/gitlab-org/gitlab/-/issues/23345)需要改进,那就是允许一个存储桶具有单独的文件夹. + +在通过 Helm 图表部署 GitLab 时使用单个存储桶会导致从备份还原[无法正常运行](https://docs.gitlab.com/charts/advanced/external-object-storage/) . 尽管您可能暂时不使用 Helm 部署,但是如果稍后将 GitLab 迁移到 Helm 部署,GitLab 仍然可以工作,但是您可能不会意识到备份无法正常工作,直到遇到对备份起作用的关键要求. + +[Back to setup components](#setup-components) + +## Configure NFS (optional)[](#configure-nfs-optional "Permalink") + +为了提高性能,建议尽可能使用[对象存储](#configure-the-object-storage)以及[Gitaly](#configure-gitaly) ,而不是使用 NFS. 但是,如果您打算使用 GitLab 页面,则[必须使用 NFS](troubleshooting.html#gitlab-pages-requires-nfs) . + +有关配置 NFS 的信息,请参阅[NFS 文档页面](../high_availability/nfs.html) . + +[Back to setup components](#setup-components) + +## Troubleshooting[](#troubleshooting "Permalink") + +请参阅[故障排除文档](troubleshooting.html) . + +[Back to setup components](#setup-components) \ No newline at end of file diff --git a/docs/423.md b/docs/423.md new file mode 100644 index 0000000000000000000000000000000000000000..414f222a6bbfd280f938da39e94b4de2f43de7c0 --- /dev/null +++ b/docs/423.md @@ -0,0 +1,1451 @@ +# Reference architecture: up to 3,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/3k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/3k_users.html) + +* [Setup components](#setup-components) +* [Configure the external load balancer](#configure-the-external-load-balancer) + * [Application node terminates SSL](#application-node-terminates-ssl) + * [Load balancer terminates SSL without backend SSL](#load-balancer-terminates-ssl-without-backend-ssl) + * [Load balancer terminates SSL with backend SSL](#load-balancer-terminates-ssl-with-backend-ssl) + * [Ports](#ports) + * [Alternate SSH Port](#alternate-ssh-port) +* [Configure Redis](#configure-redis) + * [Provide your own Redis instance](#provide-your-own-redis-instance) + * [Standalone Redis using Omnibus GitLab](#standalone-redis-using-omnibus-gitlab) + * [Configuring the primary Redis instance](#configuring-the-primary-redis-instance) + * [Configuring the replica Redis instances](#configuring-the-replica-redis-instances) +* [Configure Consul and Sentinel](#configure-consul-and-sentinel) +* [Configure PostgreSQL](#configure-postgresql) + * [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance) + * [Standalone PostgreSQL using Omnibus GitLab](#standalone-postgresql-using-omnibus-gitlab) + * [PostgreSQL primary node](#postgresql-primary-node) + * [PostgreSQL secondary nodes](#postgresql-secondary-nodes) + * [PostgreSQL post-configuration](#postgresql-post-configuration) +* [Configure PgBouncer](#configure-pgbouncer) + * [Configure the internal load balancer](#configure-the-internal-load-balancer) +* [Configure Gitaly](#configure-gitaly) + * [Gitaly TLS support](#gitaly-tls-support) +* [Configure Sidekiq](#configure-sidekiq) +* [Configure GitLab Rails](#configure-gitlab-rails) + * [GitLab Rails post-configuration](#gitlab-rails-post-configuration) +* [Configure Prometheus](#configure-prometheus) +* [Configure the object storage](#configure-the-object-storage) +* [Configure NFS (optional)](#configure-nfs-optional) +* [Troubleshooting](#troubleshooting) + +# Reference architecture: up to 3,000 users[](#reference-architecture-up-to-3000-users "Permalink") + +此页面描述了最多 3,000 个用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +**注意:**下面记录的 3,000 个用户参考体系结构旨在帮助您的组织实现高度可用的 GitLab 部署. 如果您没有专业知识或需要维护高度可用的环境,则可以遵循[2,000 个用户的参考体系结构](2k_users.html) ,从而拥有一个更简单且成本更低的操作环境. + +> * **支持的用户(大约):** 3,000 +> * **高可用性:** True +> * **测试 RPS 速率:** API:60 RPS,网站:6 RPS,Git:6 RPS + +| Service | Nodes | Configuration | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | --- | +| 外部负载平衡节点 | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| Redis | 3 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| 领事+前哨 | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| PostgreSQL | 3 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| PgBouncer | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| 内部负载平衡节点 | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| Gitaly | 最少 2 个 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | `D4s v3` | +| Sidekiq | 4 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| 亚搏体育 app Rails | 3 | 8 个 vCPU,7.2GB 内存 | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` | +| 监控节点 | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| 对象存储 | n/a | n/a | n/a | n/a | n/a | +| NFS 服务器(可选,不推荐) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` | + +这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. + +对于 LFS,Uploads,Artifacts 等数据对象,由于性能和可用性更好,建议在 NFS 上尽可能使用[对象存储服务](#configure-the-object-storage) . 由于这不需要设置节点,因此在上表中将其标记为不适用(n / a). + +## Setup components[](#setup-components "Permalink") + +设置 GitLab 及其组件以容纳多达 3,000 个用户: + +1. [配置外部负载平衡节点](#configure-the-external-load-balancer) ,该[节点](#configure-the-external-load-balancer)将处理两个 GitLab 应用程序服务节点的负载平衡. +2. [Configure Redis](#configure-redis). +3. [Configure Consul and Sentinel](#configure-consul-and-sentinel). +4. [配置 PostgreSQL](#configure-postgresql) (GitLab 的数据库). +5. [Configure PgBouncer](#configure-pgbouncer). +6. [Configure the internal load balancing node](#configure-the-internal-load-balancer) +7. [配置 Gitaly](#configure-gitaly) ,它提供对 Git 存储库的访问. +8. [Configure Sidekiq](#configure-sidekiq). +9. [配置主 GitLab Rails 应用程序](#configure-gitlab-rails)以运行 Puma / Unicorn,Workhorse,GitLab Shell,并服务所有前端请求(UI,API,基于 HTTP / SSH 的 Git). +10. [配置 Prometheus](#configure-prometheus)来监视您的 GitLab 环境. +11. [配置](#configure-the-object-storage)用于共享数据对象[的对象存储](#configure-the-object-storage) . +12. [将 NFS(可选)配置](#configure-nfs-optional)为具有共享磁盘存储服务,以替代 Gitaly 和/或对象存储(尽管不建议这样做). GitLab 页面需要 NFS,如果不使用该功能,则可以跳过此步骤. + +我们从同一 10.6.0.0/16 专用网络范围内的所有服务器开始,它们可以在这些地址上自由地相互连接. + +这是每台机器和分配的 IP 的列表和说明: + +* `10.6.0.10` :外部负载平衡器 +* `10.6.0.61`主要 +* `10.6.0.62` :返回副本 1 +* `10.6.0.63` :返回副本 2 +* `10.6.0.11` :领事/前哨 1 +* `10.6.0.12` :领事/前哨 2 +* `10.6.0.13` :领事/前哨 3 +* `10.6.0.31`主 +* `10.6.0.32`中学 1 +* `10.6.0.33`中学 2 +* `10.6.0.21` :PgBouncer 1 +* `10.6.0.22` :PgBouncer 2 +* `10.6.0.23` :PgBouncer 3 +* `10.6.0.20` :内部负载均衡器 +* `10.6.0.51` :Gitaly 1 +* `10.6.0.52` :Gitaly 2 +* `10.6.0.71` :Sidekiq 1 +* `10.6.0.72` :Sidekiq 2 +* `10.6.0.73` :Sidekiq 3 +* `10.6.0.74` :Sidekiq 4 +* `10.6.0.41`应用程序 1 +* `10.6.0.42`应用程序 2 +* `10.6.0.43`应用程序 3 +* `10.6.0.81` :普罗米修斯 + +## Configure the external load balancer[](#configure-the-external-load-balancer "Permalink") + +**注意:**此体系结构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +在主动/主动 GitLab 配置中,您将需要一个负载均衡器来将流量路由到应用程序服务器. 有关使用负载均衡器或进行确切配置的细节超出了 GitLab 文档的范围. 我们希望,如果您要管理像 GitLab 这样的多节点系统,那么已经选择了负载均衡器. 一些示例包括 HAProxy(开源),F5 Big-IP LTM 和 Citrix Net Scaler. 本文档将概述需要在 GitLab 上使用哪些端口和协议. + +下一个问题是如何在环境中处理 SSL. 有几种不同的选择: + +* [The application node terminates SSL](#application-node-terminates-ssl). +* [负载平衡器终止没有后端 SSL 的 SSL,](#load-balancer-terminates-ssl-without-backend-ssl)并且负载平衡器与应用程序节点之间的通信不安全. +* [负载均衡器使用后端 SSL 终止 SSL,](#load-balancer-terminates-ssl-with-backend-ssl)并且负载均衡器与应用程序节点之间的通信是*安全*的. + +### Application node terminates SSL[](#application-node-terminates-ssl "Permalink") + +配置您的负载均衡器以将端口 443 上的连接作为`TCP`而不是`HTTP(S)`协议进行传递. 这会将连接直接传递到应用程序节点的 NGINX 服务. NGINX 将具有 SSL 证书并在端口 443 上侦听. + +有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load balancer terminates SSL without backend SSL[](#load-balancer-terminates-ssl-without-backend-ssl "Permalink") + +将您的负载均衡器配置为使用`HTTP(S)`协议而不是`TCP` . 然后,负载平衡器将负责管理 SSL 证书和终止 SSL. + +由于负载均衡器和 GitLab 之间的通信将不安全,因此需要一些其他配置. 有关详细信息,请参见[NGINX 代理的 SSL 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load balancer terminates SSL with backend SSL[](#load-balancer-terminates-ssl-with-backend-ssl "Permalink") + +Configure your load balancer(s) to use the ‘HTTP(S)’ protocol rather than ‘TCP’. The load balancer(s) will be responsible for managing SSL certificates that end users will see. + +在这种情况下,负载均衡器和 NGINX 之间的流量也将是安全的. 无需为代理 SSL 添加配置,因为连接将一直保持安全. 但是,需要将配置添加到 GitLab 来配置 SSL 证书. 有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Ports[](#ports "Permalink") + +下表显示了要使用的基本端口. + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 80 | HTTP( *1* ) | +| 443 | 443 | TCP 或 HTTPS( *1* )( *2* ) | +| 22 | 22 | TCP | + +* ( *1* ): [Web 终端](../../ci/environments/index.html#web-terminals)支持要求您的负载平衡器正确处理 WebSocket 连接. 当使用 HTTP 或 HTTPS 代理,这意味着负载平衡器必须被配置为通过`Connection`和`Upgrade`逐跳头. 有关更多详细信息,请参见[Web 终端](../integration/terminal.html)集成指南. +* ( *2* ):当对端口 443 使用 HTTPS 协议时,需要向负载均衡器添加 SSL 证书. 如果您想在 GitLab 应用程序服务器上终止 SSL,请使用 TCP 协议. + +如果您使用具有自定义域支持的 GitLab 页面,则将需要一些其他端口配置. GitLab 页面需要一个单独的虚拟 IP 地址. 配置 DNS,将`pages_external_url`的`/etc/gitlab/gitlab.rb`指向新的虚拟 IP 地址. 有关更多信息,请参见[GitLab 页面文档](../pages/index.html) . + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 变化( *1* ) | HTTP | +| 443 | 变化( *1* ) | TCP( *2* ) | + +* ( *1* ):GitLab 页面的后端端口取决于`gitlab_pages['external_http']`和`gitlab_pages['external_https']`设置. 有关更多详细信息,请参见[GitLab Pages 文档](../pages/index.html) . +* ( *2* ):GitLab 页面的端口 443 应该始终使用 TCP 协议. 用户可以使用自定义 SSL 配置自定义域,如果 SSL 在负载均衡器处终止,则不可能. + +#### Alternate SSH Port[](#alternate-ssh-port "Permalink") + +某些组织有禁止打开 SSH 端口 22 的策略.在这种情况下,配置允许用户在端口 443 上使用 SSH 的备用 SSH 主机名可能会有所帮助.与其他 GitLab 相比,备用 SSH 主机名将需要一个新的虚拟 IP 地址.上面的 HTTP 配置. + +为备用 SSH 主机名(例如`altssh.gitlab.example.com`配置 DNS. + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 443 | 22 | TCP | + +[Back to setup components](#setup-components) + +## Configure Redis[](#configure-redis "Permalink") + +使用[Redis 的](https://s0redis0io.icopy.site/)可扩展环境,可以使用**一次** X **副本**拓扑与[Redis 的哨兵](https://s0redis0io.icopy.site/topics/sentinel)服务来观看,并自动启动故障转移过程. + +如果与 Sentinel 一起使用,Redis 需要身份验证. 有关更多信息,请参见[Redis 安全性](https://s0redis0io.icopy.site/topics/security)文档. 我们建议结合使用 Redis 密码和严格的防火墙规则来保护您的 Redis 服务. 强烈建议您在使用 GitLab 配置 Redis 之前阅读[Redis Sentinel](https://s0redis0io.icopy.site/topics/sentinel)文档,以充分了解拓扑和体系结构. + +在本节中,将指导您配置与 GitLab 一起使用的外部 Redis 实例. 以下 IP 将作为示例: + +* `10.6.0.61`主要 +* `10.6.0.62` :返回副本 1 +* `10.6.0.63` :返回副本 2 + +### Provide your own Redis instance[](#provide-your-own-redis-instance "Permalink") + +来自云提供商(例如 AWS ElastiCache)的托管 Redis 将可以使用. 如果这些服务支持高可用性,请确保它**不是** Redis 群集类型. + +需要 Redis 5.0 或更高版本,因为这是从 GitLab 13.0 开始的 Omnibus GitLab 软件包附带的版本. 较旧的 Redis 版本不支持 SPOP 的可选 count 参数,这对于[合并火车](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)现在是必需的. + +注意 Redis 节点的 IP 地址或主机名,端口和密码(如果需要). 这些在以后配置[GitLab 应用程序服务器](#configure-gitlab-rails)时是必需的. + +### Standalone Redis using Omnibus GitLab[](#standalone-redis-using-omnibus-gitlab "Permalink") + +这是我们安装和设置新 Redis 实例的部分. + +Redis 设置的要求如下: + +1. 所有 Redis 节点必须能够互相通信并接受通过 Redis( `6379` )和 Sentinel( `26379` )端口的传入连接(除非您更改默认端口). +2. 托管 GitLab 应用程序的服务器必须能够访问 Redis 节点. +3. 使用防火墙保护节点免受来自外部网络( [Internet](https://gitlab.com/gitlab-org/gitlab-foss/uploads/c4cc8cd353604bd80315f9384035ff9e/The_Internet_IT_Crowd.png) )的访问. + +**注意:** Redis 节点(主节点和副本节点)将需要使用`redis['password']`定义的相同密码. 在故障转移期间的任何时间,Sentinels 都可以重新配置节点并将其状态从主节点更改为副本节点,反之亦然. + +#### Configuring the primary Redis instance[](#configuring-the-primary-redis-instance "Permalink") + +1. SSH 进入**主** Redis 服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 确保选择正确的 Omnibus 软件包,并使用与当前安装相同的版本和类型(社区版,企业版). + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + # Specify server role as 'redis_master_role' + roles ['redis_master_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.61' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Set up password authentication for Redis (use the same password in all nodes). + redis['password'] = 'redis-password-goes-here' + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + redis_exporter['flags'] = { + 'redis.addr' => 'redis://10.6.0.61:6379', + 'redis.password' => 'redis-password-goes-here', + } + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**注意:**您可以将多个角色(如哨兵和 Redis)指定为: `roles ['redis_sentinel_role', 'redis_master_role']` . 阅读有关[角色的](https://docs.gitlab.com/omnibus/roles/)更多信息. + +您可以通过以下方式列出当前 Redis 主副本服务器状态: + +``` +/opt/gitlab/embedded/bin/redis-cli -h -a 'redis-password-goes-here' info replication +``` + +通过以下方式显示正在运行的 GitLab 服务: + +``` +gitlab-ctl status +``` + +输出应类似于以下内容: + +``` +run: consul: (pid 30043) 76863s; run: log: (pid 29691) 76892s +run: logrotate: (pid 31152) 3070s; run: log: (pid 29595) 76908s +run: node-exporter: (pid 30064) 76862s; run: log: (pid 29624) 76904s +run: redis: (pid 30070) 76861s; run: log: (pid 29573) 76914s +run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s +``` + +#### Configuring the replica Redis instances[](#configuring-the-replica-redis-instances "Permalink") + +1. SSH 进入**副本** Redis 服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 确保选择正确的 Omnibus 软件包,并使用与当前安装相同的版本和类型(社区版,企业版). + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + # Specify server role as 'redis_replica_role' + roles ['redis_replica_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.62' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # The same password for Redis authentication you set up for the primary node. + redis['password'] = 'redis-password-goes-here' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + redis_exporter['flags'] = { + 'redis.addr' => 'redis://10.6.0.62:6379', + 'redis.password' => 'redis-password-goes-here', + } + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +5. 对于所有其他副本节点,请再次执行该步骤,并确保正确设置 IP. + +**注意:**您可以将多个角色(如哨兵和 Redis)指定为: `roles ['redis_sentinel_role', 'redis_master_role']` . 阅读有关[角色的](https://docs.gitlab.com/omnibus/roles/)更多信息. + +故障转移后, `/etc/gitlab/gitlab.rb`在`/etc/gitlab/gitlab.rb`再次更改这些值,因为节点将由[Sentinels](#configure-consul-and-sentinel)管理,即使在`gitlab-ctl reconfigure` ,它们也将通过恢复配置恢复.同样的哨兵 + +支持高级[配置选项](https://docs.gitlab.com/omnibus/settings/redis.html) ,可以根据需要添加. + +[Back to setup components](#setup-components) + +## Configure Consul and Sentinel[](#configure-consul-and-sentinel "Permalink") + +**注意:**如果您使用的是外部 Redis Sentinel 实例,请确保从 Sentinel 配置中排除`requirepass`参数. 此参数将导致客户端报告`NOAUTH Authentication required.` . [Redis Sentinel 3.2.x 不支持密码身份验证](https://github.com/antirez/redis/issues/3279) . + +现在已经全部安装了 Redis 服务器,让我们配置 Sentinel 服务器. 以下 IP 将作为示例: + +* `10.6.0.11` :领事/前哨 1 +* `10.6.0.12` :领事/前哨 2 +* `10.6.0.13` :领事/前哨 3 + +要配置 Sentinel: + +1. SSH 进入将托管 Consul / Sentinel 的服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/) Omnibus GitLab 企业版软件包. + * 确保选择正确的 Omnibus 软件包,并且与 GitLab 应用程序正在运行的版本相同. + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + roles ['redis_sentinel_role', 'consul_role'] + + # Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + # The same password for Redis authentication you set up for the primary node. + redis['master_password'] = 'redis-password-goes-here' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Configure Sentinel + sentinel['bind'] = '10.6.0.11' + + # Port that Sentinel listens on, uncomment to change to non default. Defaults + # to `26379`. + # sentinel['port'] = 26379 + + ## Quorum must reflect the amount of voting sentinels it take to start a failover. + ## Value must NOT be greater then the amount of sentinels. + ## + ## The quorum can be used to tune Sentinel in two ways: + ## 1\. If a the quorum is set to a value smaller than the majority of Sentinels + ## we deploy, we are basically making Sentinel more sensible to primary failures, + ## triggering a failover as soon as even just a minority of Sentinels is no longer + ## able to talk with the primary. + ## 1\. If a quorum is set to a value greater than the majority of Sentinels, we are + ## making Sentinel able to failover only when there are a very large number (larger + ## than majority) of well connected Sentinels which agree about the primary being down.s + sentinel['quorum'] = 2 + + ## Consider unresponsive server down after x amount of ms. + # sentinel['down_after_milliseconds'] = 10000 + + ## Specifies the failover timeout in milliseconds. It is used in many ways: + ## + ## - The time needed to re-start a failover after a previous failover was + ## already tried against the same primary by a given Sentinel, is two + ## times the failover timeout. + ## + ## - The time needed for a replica replicating to a wrong primary according + ## to a Sentinel current configuration, to be forced to replicate + ## with the right primary, is exactly the failover timeout (counting since + ## the moment a Sentinel detected the misconfiguration). + ## + ## - The time needed to cancel a failover that is already in progress but + ## did not produced any configuration change (REPLICAOF NO ONE yet not + ## acknowledged by the promoted replica). + ## + ## - The maximum time a failover in progress waits for all the replica to be + ## reconfigured as replicas of the new primary. However even after this time + ## the replicas will be reconfigured by the Sentinels anyway, but not with + ## the exact parallel-syncs progression as specified. + # sentinel['failover_timeout'] = 60000 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + server: true, + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +5. 对于其他所有 Consul / Sentinel 节点,请再次执行步骤,并确保设置了正确的 IP. + +**注意:**第三个 Consul 服务器的配置完成后,将选举 Consul 负责人. 查看领事日志`sudo gitlab-ctl tail consul`将显示`...[INFO] consul: New leader elected: ...` + +You can list the current Consul members (server, client): + +``` +sudo /opt/gitlab/embedded/bin/consul members +``` + +您可以验证 GitLab 服务正在运行: + +``` +sudo gitlab-ctl status +``` + +输出应类似于以下内容: + +``` +run: consul: (pid 30074) 76834s; run: log: (pid 29740) 76844s +run: logrotate: (pid 30925) 3041s; run: log: (pid 29649) 76861s +run: node-exporter: (pid 30093) 76833s; run: log: (pid 29663) 76855s +run: sentinel: (pid 30098) 76832s; run: log: (pid 29704) 76850s +``` + +[Back to setup components](#setup-components) + +## Configure PostgreSQL[](#configure-postgresql "Permalink") + +在本节中,将指导您配置与 GitLab 一起使用的外部 PostgreSQL 数据库. + +### Provide your own PostgreSQL instance[](#provide-your-own-postgresql-instance "Permalink") + +如果您将 GitLab 托管在云提供商上,则可以选择将托管服务用于 PostgreSQL. 例如,AWS 提供了运行 PostgreSQL 的托管关系数据库服务(RDS). + +如果您使用云托管服务,或提供自己的 PostgreSQL: + +1. 根据[数据库要求文档](../../install/requirements.html#database)设置 PostgreSQL. +2. 使用您选择的密码设置一个`gitlab`用户名. `gitlab`用户需要特权才能创建`gitlabhq_production`数据库. +3. 使用适当的详细信息配置 GitLab 应用程序服务器. [配置 GitLab Rails 应用程序](#configure-gitlab-rails)涵盖了此步骤. + +### Standalone PostgreSQL using Omnibus GitLab[](#standalone-postgresql-using-omnibus-gitlab "Permalink") + +以下 IP 将作为示例: + +* `10.6.0.31`主 +* `10.6.0.32`中学 1 +* `10.6.0.33`中学 2 + +首先,请确保**在每个节点上** [安装](https://about.gitlab.com/install/) Linux GitLab 软件包. 按照以下步骤,从步骤 1 安装必需的依赖项,并从步骤 2 添加 GitLab 软件包存储库.在第二步中安装 GitLab 时,请勿提供`EXTERNAL_URL`值. + +#### PostgreSQL primary node[](#postgresql-primary-node "Permalink") + +1. SSH 进入 PostgreSQL 主节点. +2. 为 PostgreSQL 用户名/密码对生成密码哈希. 假设您将使用默认用户名`gitlab` (推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作``的值: + + ``` + sudo gitlab-ctl pg-password-md5 gitlab + ``` + +3. 为 PgBouncer 用户名/密码对生成密码哈希. 假设您将使用`pgbouncer`的默认用户名(推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作``的值: + + ``` + sudo gitlab-ctl pg-password-md5 pgbouncer + ``` + +4. 为 Consul 数据库用户名/密码对生成密码哈希. 假设您将使用默认用户名`gitlab-consul` (推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作``的值: + + ``` + sudo gitlab-ctl pg-password-md5 gitlab-consul + ``` + +5. 在主数据库节点上,编辑`/etc/gitlab/gitlab.rb`替换`/etc/gitlab/gitlab.rb` `# START user configuration`部分中记录的值: + + ``` + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # START user configuration + # Please set the real values as explained in Required Information section + # + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace XXX.XXX.XXX.XXX/YY with Network Address + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + postgres_exporter['dbname'] = 'gitlabhq_production' + postgres_exporter['password'] = '' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + # + # END user configuration + ``` + +6. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +7. 您可以通过以下方式列出当前 PostgreSQL 主,辅助节点的状态: + + ``` + sudo /opt/gitlab/bin/gitlab-ctl repmgr cluster show + ``` + +8. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 30593) 77133s; run: log: (pid 29912) 77156s + run: logrotate: (pid 23449) 3341s; run: log: (pid 29794) 77175s + run: node-exporter: (pid 30613) 77133s; run: log: (pid 29824) 77170s + run: postgres-exporter: (pid 30620) 77132s; run: log: (pid 29894) 77163s + run: postgresql: (pid 30630) 77132s; run: log: (pid 29618) 77181s + run: repmgrd: (pid 30639) 77132s; run: log: (pid 29985) 77150s + ``` + +[Back to setup components](#setup-components) + +#### PostgreSQL secondary nodes[](#postgresql-secondary-nodes "Permalink") + +1. 在两个辅助节点上,添加与上面为主要节点指定的配置相同的附加设置,该设置将告知`gitlab-ctl`最初它们是备用节点,无需尝试将它们注册为主要节点: + + ``` + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # Specify if a node should attempt to be primary on initialization. + repmgr['master_on_initialization'] = false + + # START user configuration + # Please set the real values as explained in Required Information section + # + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace XXX.XXX.XXX.XXX/YY with Network Address + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + postgres_exporter['dbname'] = 'gitlabhq_production' + postgres_exporter['password'] = '' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + # END user configuration + ``` + +2. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +支持高级[配置选项](https://docs.gitlab.com/omnibus/settings/database.html) ,可以根据需要添加. + +[Back to setup components](#setup-components) + +#### PostgreSQL post-configuration[](#postgresql-post-configuration "Permalink") + +SSH 进入**主节点** : + +1. 打开数据库提示: + + ``` + gitlab-psql -d gitlabhq_production + ``` + +2. Enable the `pg_trgm` extension: + + ``` + CREATE EXTENSION pg_trgm; + ``` + +3. 键入`\q`并按 Enter 退出数据库提示. + +4. 验证集群是否已用一个节点初始化: + + ``` + gitlab-ctl repmgr cluster show + ``` + + 输出应类似于以下内容: + + ``` + Role | Name | Upstream | Connection String + ----------+----------|----------|---------------------------------------- + * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr + ``` + +5. 在连接字符串中记下主机名或 IP 地址: `host=HOSTNAME` . 在下一节中,我们将主机名称为`` . 如果该值不是 IP 地址,则必须是可解析的名称(通过 DNS 或`/etc/hosts` ) + +SSH 进入**辅助节点** : + +1. 设置 repmgr 备用数据库: + + ``` + gitlab-ctl repmgr standby setup + ``` + + Do note that this will remove the existing data on the node. The command has a wait time. + + 输出应类似于以下内容: + + ``` + Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data + If this is not what you want, hit Ctrl-C now to exit + To skip waiting, rerun with the -w option + Sleeping for 30 seconds + Stopping the database + Removing the data + Cloning the data + Starting the database + Registering the node with the cluster + ok: run: repmgrd: (pid 19068) 0s + ``` + +在继续之前,请确保正确配置了数据库. 在**主**节点上运行以下命令以验证复制是否正常工作,并且辅助节点是否出现在群集中: + +``` +gitlab-ctl repmgr cluster show +``` + +输出应类似于以下内容: + +``` +Role | Name | Upstream | Connection String +----------+---------|-----------|------------------------------------------------ +* master | MASTER | | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr +``` + +如果任何节点的"角色"列显示"失败",请在继续操作之前检查" [故障排除"部分](troubleshooting.html) . + +另外,请检查`repmgr-check-master`命令在每个节点上是否都能正常工作: + +``` +su - gitlab-consul +gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' +``` + +此命令依靠退出代码来告诉 Consul 特定节点是主节点还是辅助节点. 这里最重要的是该命令不会产生错误. 如果有错误,很可能是由于`gitlab-consul`数据库用户权限不正确`gitlab-consul` . 在继续之前,请检查" [故障排除"部分](troubleshooting.html) . + +[Back to setup components](#setup-components) + +## Configure PgBouncer[](#configure-pgbouncer "Permalink") + +现在已经安装了 PostgreSQL 服务器,让我们配置 PgBouncer. 以下 IP 将作为示例: + +* `10.6.0.21` :PgBouncer 1 +* `10.6.0.22` :PgBouncer 2 +* `10.6.0.23` :PgBouncer 3 + +1. 在每个 PgBouncer 节点上,编辑`/etc/gitlab/gitlab.rb` ,并将``和``替换为[之前设置](#postgresql-primary-node)的密码哈希: + + ``` + # Disable all components except Pgbouncer and Consul agent + roles ['pgbouncer_role'] + + # Configure PgBouncer + pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) + + pgbouncer['users'] = { + 'gitlab-consul': { + password: '' + }, + 'pgbouncer': { + password: '' + } + } + + # Configure Consul agent + consul['watchers'] = %w(postgresql) + consul['enable'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + pgbouncer_exporter['listen_address'] = '0.0.0.0:9188' + ``` + +2. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +3. 创建一个`.pgpass`文件,以便 Consul 能够重新加载 PgBouncer. 询问时两次输入 PgBouncer 密码: + + ``` + gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul + ``` + +4. 确保每个节点都在与当前主节点通信: + + ``` + gitlab-ctl pgb-console # You will be prompted for PGBOUNCER_PASSWORD + ``` + + 如果出现错误`psql: ERROR: Auth failed`输入密码后`psql: ERROR: Auth failed` ,请确保您以前以正确的格式生成了 MD5 密码哈希. 正确的格式是连接密码和用户名`PASSWORDUSERNAME` . 例如, `Sup3rS3cr3tpgbouncer`将是为`pgbouncer`用户生成 MD5 密码哈希所需的文本. + +5. 控制台提示可用后,请运行以下查询: + + ``` + show databases ; show clients ; + ``` + + 输出应类似于以下内容: + + ``` + name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections + ---------------------+-------------+------+---------------------+------------+-----------+--------------+-----------+-----------------+--------------------- + gitlabhq_production | MASTER_HOST | 5432 | gitlabhq_production | | 20 | 0 | | 0 | 0 + pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0 + (2 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | remote_pid | tls + ------+-----------+---------------------+---------+----------------+-------+------------+------------+---------------------+---------------------+-----------+------+------------+----- + C | pgbouncer | pgbouncer | active | 127.0.0.1 | 56846 | 127.0.0.1 | 6432 | 2017-08-21 18:09:59 | 2017-08-21 18:10:48 | 0x22b3880 | | 0 | + (2 rows) + ``` + +6. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + The output should be similar to the following: + + ``` + run: consul: (pid 31530) 77150s; run: log: (pid 31106) 77182s + run: logrotate: (pid 32613) 3357s; run: log: (pid 30107) 77500s + run: node-exporter: (pid 31550) 77149s; run: log: (pid 30138) 77493s + run: pgbouncer: (pid 32033) 75593s; run: log: (pid 31117) 77175s + run: pgbouncer-exporter: (pid 31558) 77148s; run: log: (pid 31498) 77156s + ``` + +[Back to setup components](#setup-components) + +### Configure the internal load balancer[](#configure-the-internal-load-balancer "Permalink") + +如果按照建议运行多个 PgBouncer 节点,那么此时,您将需要设置一个 TCP 内部负载均衡器以正确地服务每个负载均衡器. + +以下 IP 将作为示例: + +* `10.6.0.20` :内部负载均衡器 + +使用[HAProxy 的方法](https://www.haproxy.org/)如下: + +``` +global + log /dev/log local0 + log localhost local1 notice + log stdout format raw local0 + +defaults + log global + default-server inter 10s fall 3 rise 2 + balance leastconn + +frontend internal-pgbouncer-tcp-in + bind *:6432 + mode tcp + option tcplog + + default_backend pgbouncer + +backend pgbouncer + mode tcp + option tcp-check + + server pgbouncer1 10.6.0.21:6432 check + server pgbouncer2 10.6.0.22:6432 check + server pgbouncer3 10.6.0.23:6432 check +``` + +请参阅您首选的负载均衡器的文档以获取更多指导. + +[Back to setup components](#setup-components) + +## Configure Gitaly[](#configure-gitaly "Permalink") + +在自己的服务器上部署 Gitaly 可以使大于单个计算机的 GitLab 安装受益. + +Gitaly 节点要求取决于客户数据,特别是项目数量及其存储库大小. 建议将两个节点作为绝对最小值. 每个 Gitaly 节点应存储的数据不超过 5TB,并将[`gitaly-ruby`工作者](../gitaly/index.html#gitaly-ruby)的数量设置为可用 CPU 的 20%. 根据以上建议,应结合其他节点并结合对预期数据大小和分布的审查. + +强烈建议所有 Gitaly 节点都安装 SSD 磁盘,因为 Gitaly I / O 繁重,因此其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +注意事项: + +* GitLab Rails 应用程序将[存储库分](../repository_storage_paths.html)片到[存储库中](../repository_storage_paths.html) . +* Gitaly 服务器可以托管一个或多个存储. +* 一个 GitLab 服务器可以使用一个或多个 Gitaly 服务器. +* 必须以对所有 Gitaly 客户端正确解析的方式指定 Gitaly 地址. +* Gitaly 服务器一定不能暴露在公共互联网上,因为默认情况下,Gitaly 的网络流量是未加密的. 强烈建议使用防火墙以限制对 Gitaly 服务器的访问. 另一种选择是[使用 TLS](#gitaly-tls-support) . + +**提示:**有关 Gitaly 历史和网络体系结构的更多信息,请参见[独立的 Gitaly 文档](../gitaly/index.html) . + +注意: **注意:** Gitaly 文档中引用的令牌只是管理员选择的任意密码. 它与为 GitLab API 创建的令牌或其他类似的 Web API 令牌无关. + +下面我们描述如何配置两个具有 IP 和域名的 Gitaly 服务器: + +* `10.6.0.51` 1( `gitaly1.internal` ) +* `10.6.0.52` 2( `gitaly2.internal` ) + +假定该秘密令牌为`gitalysecret` ,并且您的 GitLab 安装具有三个存储库存储: + +* `default`为 Gitaly 1 +* `storage1`在 Gitaly 1 +* `storage2`上 Gitaly 2 + +在每个节点上: + +1. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包,但**不**提供`EXTERNAL_URL`值. +2. 编辑`/etc/gitlab/gitlab.rb`以配置存储路径,启用网络侦听器并配置令牌: + + ``` + # /etc/gitlab/gitlab.rb + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the GitLab Rails application setup + gitaly['auth_token'] = 'gitlaysecret' + gitlab_shell['secret_token'] = 'shellsecret' + + # Avoid running unnecessary services on the Gitaly server + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + grafana['enable'] = false + gitlab_exporter['enable'] = false + + # If you run a seperate monitoring node you can disable these services + alertmanager['enable'] = false + prometheus['enable'] = false + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your 'front door' GitLab URL or an internal load + # balancer. + # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server. + gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' + + # Make Gitaly accept connections on all network interfaces. You must use + # firewalls to restrict access to this address/port. + # Comment out following line if you only want to support TLS connections + gitaly['listen_addr'] = "0.0.0.0:8075" + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + gitaly['prometheus_listen_addr'] = "0.0.0.0:9236" + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_rails['prometheus_address'] = '10.6.0.81:9090' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + ``` + +3. 对于每个服务器,将以下内容附加到`/etc/gitlab/gitlab.rb` : + 1. 在`gitaly1.internal` : + + ``` + git_data_dirs ({ 'default' => { 'path' => '/var/opt/gitlab/git-data' }, 'storage1' => { 'path' => '/mnt/gitlab/git-data' }, }) + ``` + + 2. 在`gitaly2.internal` : + + ``` + git_data_dirs ({ 'storage2' => { 'path' => '/mnt/gitlab/git-data' }, }) + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 确认 Gitaly 可以执行对内部 API 的回调: + + ``` + sudo /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml + ``` + +6. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 30339) 77006s; run: log: (pid 29878) 77020s + run: gitaly: (pid 30351) 77005s; run: log: (pid 29660) 77040s + run: logrotate: (pid 7760) 3213s; run: log: (pid 29782) 77032s + run: node-exporter: (pid 30378) 77004s; run: log: (pid 29812) 77026s + ``` + +### Gitaly TLS support[](#gitaly-tls-support "Permalink") + +Gitaly 支持 TLS 加密. 为了能够与侦听安全连接的 Gitaly 实例进行通信,您将需要在 GitLab 配置中相应存储条目的`gitaly_address`中使用`tls://` URL 方案. + +您将需要携带自己的证书,因为该证书不会自动提供. 证书或其证书颁发机构必须按照[GitLab 自定义证书配置中](https://docs.gitlab.com/omnibus/settings/ssl.html)所述的步骤,安装在所有 Gitaly 节点(包括使用证书的 Gitaly 节点)上,以及与之通信的所有客户端节点上. + +**注意:**自签名证书必须指定用于访问 Gitaly 服务器的地址. 如果要通过主机名寻址 Gitaly 服务器,则可以为此使用"公用名"字段,也可以将其添加为"使用者备用名". 如果要通过 Gitaly 服务器的 IP 地址对其进行寻址,则必须将其作为主题备用名称添加到证书中. [gRPC 不支持在证书中使用 IP 地址作为公用名](https://github.com/grpc/grpc/issues/2691) .**注意:**可以同时为 Gitaly 服务器配置未加密的侦听地址`listen_addr`和已加密的侦听地址`tls_listen_addr` . 如果需要,这使您可以从未加密的流量逐渐过渡到加密的流量. + +要使用 TLS 配置 Gitaly: + +1. 创建`/etc/gitlab/ssl`目录,并在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +2. 将证书复制到`/etc/gitlab/trusted-certs`以便 Gitaly 在调用自身时信任该证书: + + ``` + sudo cp /etc/gitlab/ssl/cert.pem /etc/gitlab/trusted-certs/ + ``` + +3. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + gitaly['tls_listen_addr'] = "0.0.0.0:9999" + gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + gitaly['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +4. 删除`gitaly['listen_addr']`以仅允许加密连接. +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +[Back to setup components](#setup-components) + +## Configure Sidekiq[](#configure-sidekiq "Permalink") + +Sidekiq 需要连接到 Redis,PostgreSQL 和 Gitaly 实例. 以下 IP 将作为示例: + +* `10.6.0.71` :Sidekiq 1 +* `10.6.0.72` :Sidekiq 2 +* `10.6.0.73` :Sidekiq 3 +* `10.6.0.74` :Sidekiq 4 + +要配置 Sidekiq 节点,每个节点一个: + +1. SSH 到 Sidekiq 服务器. +2. 从 GitLab 下载页面使用步骤 1 和 2 [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. **不要完成下载页面上的任何其他步骤.** +3. 使用编辑器打开`/etc/gitlab/gitlab.rb` : + + ``` + ######################################## + ##### Services Disabled ### + ######################################## + + nginx['enable'] = false + grafana['enable'] = false + prometheus['enable'] = false + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + puma['enable'] = false + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + gitlab_exporter['enable'] = false + + ######################################## + #### Redis ### + ######################################## + + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + ## The same password for Redis authentication you set up for the master node. + redis['master_password'] = '' + + ## A list of sentinels with `host` and `port` + gitlab_rails['redis_sentinels'] = [ + {'host' => '10.6.0.11', 'port' => 26379}, + {'host' => '10.6.0.12', 'port' => 26379}, + {'host' => '10.6.0.13', 'port' => 26379}, + ] + + ####################################### + ### Gitaly ### + ####################################### + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + + ####################################### + ### Postgres ### + ####################################### + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['auto_migrate'] = false + + ####################################### + ### Sidekiq configuration ### + ####################################### + sidekiq['listen_address'] = "0.0.0.0" + + ####################################### + ### Monitoring configuration ### + ####################################### + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + + # Rails Status for prometheus + gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8'] + gitlab_rails['prometheus_address'] = '10.6.0.81:9090' + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 30114) 77353s; run: log: (pid 29756) 77367s + run: logrotate: (pid 9898) 3561s; run: log: (pid 29653) 77380s + run: node-exporter: (pid 30134) 77353s; run: log: (pid 29706) 77372s + run: sidekiq: (pid 30142) 77351s; run: log: (pid 29638) 77386s + ``` + +**提示:**您还可以运行[多个 Sidekiq 进程](../operations/extra_sidekiq_processes.html) .[Back to setup components](#setup-components) + +## Configure GitLab Rails[](#configure-gitlab-rails "Permalink") + +**注意:**在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数设置为可用 CPU 的 90%以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +本节介绍如何配置 GitLab 应用程序(Rails)组件. 在每个节点上执行以下操作: + +1. 如果您[使用的是 NFS](#configure-nfs-optional) : + + 1. 如有必要,请使用以下命令安装 NFS 客户端实用程序软件包: + + ``` + # Ubuntu/Debian + apt-get install nfs-common + + # CentOS/Red Hat + yum install nfs-utils nfs-utils-lib + ``` + + 2. 在`/etc/fstab`指定必要的 NFS 挂载. `/etc/fstab`的确切内容取决于您选择配置 NFS 服务器的方式. 有关示例和各种选项,请参见[NFS 文档](../high_availability/nfs.html) . + + 3. 创建共享目录. 这些可能会有所不同,具体取决于您的 NFS 安装位置. + + ``` + mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data + ``` + +2. 使用[GitLab 下载中的](https://about.gitlab.com/install/) **步骤 1 和 2**下载/安装 Omnibus GitLab. 不要完成下载页面上的其他步骤. +3. 创建/编辑`/etc/gitlab/gitlab.rb`并使用以下配置. 为了保持整个节点的链接均匀性, `external_url`在应用服务器上应指向外部 URL,用户将用来访问 GitLab. 这将是[外部负载平衡器](#configure-the-external-load-balancer)的 URL,它将[负载](#configure-the-external-load-balancer)流量路由到 GitLab 应用程序服务器: + + ``` + external_url 'https://gitlab.example.com' + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the Gitaly setup + gitlab_rails['gitaly_token'] = 'gitalyecret' + gitlab_shell['secret_token'] = 'shellsecret' + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + + ## Disable components that will not be on the GitLab application server + roles ['application_role'] + gitaly['enable'] = false + nginx['enable'] = true + sidekiq['enable'] = false + + ## PostgreSQL connection details + # Disable PostgreSQL on the application node + postgresql['enable'] = false + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['auto_migrate'] = false + + ## Redis connection details + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + ## The same password for Redis authentication you set up for the Redis primary node. + redis['master_password'] = '' + + ## A list of sentinels with `host` and `port` + gitlab_rails['redis_sentinels'] = [ + {'host' => '10.6.0.11', 'port' => 26379}, + {'host' => '10.6.0.12', 'port' => 26379}, + {'host' => '10.6.0.13', 'port' => 26379} + ] + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' + sidekiq['listen_address'] = "0.0.0.0" + puma['listen'] = '0.0.0.0' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Add the monitoring node's IP address to the monitoring whitelist and allow it to + # scrape the NGINX metrics + gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8'] + nginx['status']['options']['allow'] = ['10.6.0.81/32', '127.0.0.0/8'] + gitlab_rails['prometheus_address'] = '10.6.0.81:9090' + + ## Uncomment and edit the following options if you have set up NFS + ## + ## Prevent GitLab from starting if NFS data mounts are not available + ## + #high_availability['mountpoint'] = '/var/opt/gitlab/git-data' + ## + ## Ensure UIDs and GIDs match between servers for permissions via NFS + ## + #user['uid'] = 9000 + #user['gid'] = 9000 + #web_server['uid'] = 9001 + #web_server['gid'] = 9001 + #registry['uid'] = 9002 + #registry['gid'] = 9002 + ``` + +4. 如果您正在使用[具有 TLS 支持](#gitaly-tls-support)的`git_data_dirs` ,请确保`git_data_dirs`条目配置了`tls`而不是`tcp` : + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' }, + }) + ``` + + 1. 将证书复制到`/etc/gitlab/trusted-certs` : + + ``` + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +6. 运行`sudo gitlab-rake gitlab:gitaly:check`确认节点可以连接到 Gitaly. +7. 拖尾日志以查看请求: + + ``` + sudo gitlab-ctl tail gitaly + ``` + +8. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 4890) 8647s; run: log: (pid 29962) 79128s + run: gitlab-exporter: (pid 4902) 8647s; run: log: (pid 29913) 79134s + run: gitlab-workhorse: (pid 4904) 8646s; run: log: (pid 29713) 79155s + run: logrotate: (pid 12425) 1446s; run: log: (pid 29798) 79146s + run: nginx: (pid 4925) 8646s; run: log: (pid 29726) 79152s + run: node-exporter: (pid 4931) 8645s; run: log: (pid 29855) 79140s + run: puma: (pid 4936) 8645s; run: log: (pid 29656) 79161s + ``` + +**注意:**如上例所示,当在`external_url`指定`https`时,GitLab 会假定您在`/etc/gitlab/ssl/`具有 SSL 证书. 如果没有证书,NGINX 将无法启动. 有关更多信息,请参见[NGINX 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### GitLab Rails post-configuration[](#gitlab-rails-post-configuration "Permalink") + +1. 确保运行所有迁移: + + ``` + gitlab-rake gitlab:db:configure + ``` + + **注意:**如果遇到`rake aborted!` 错误,指出 PgBouncer 是无法连接到 PostgreSQL 也可能是您的 PgBouncer 节点的 IP 地址是从 PostgreSQL 的缺失`trust_auth_cidr_addresses`在`gitlab.rb`你的数据库节点. 请参阅"故障排除"部分中的[PgBouncer 错误`ERROR: pgbouncer cannot connect to server`](troubleshooting.html#pgbouncer-error-error-pgbouncer-cannot-connect-to-server) ,然后再继续. +2. [Configure fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.html). + +[Back to setup components](#setup-components) + +## Configure Prometheus[](#configure-prometheus "Permalink") + +Omnibus GitLab 软件包可用于配置运行[Prometheus](../monitoring/prometheus/index.html)和[Grafana](../monitoring/performance/grafana_configuration.html)的独立 Monitoring 节点: + +1. SSH 进入"监视"节点. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + external_url 'http://gitlab.example.com' + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + node_exporter['enable'] = false + gitlab_exporter['enable'] = false + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Login form + grafana['disable_login_form'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = '' + + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 在 GitLab 用户界面中,将`admin/application_settings/metrics_and_profiling` >指标-Grafana 设置为`/-/grafana`到`http[s]:///-/grafana` . +6. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 31637) 17337s; run: log: (pid 29748) 78432s + run: grafana: (pid 31644) 17337s; run: log: (pid 29719) 78438s + run: logrotate: (pid 31809) 2936s; run: log: (pid 29581) 78462s + run: nginx: (pid 31665) 17335s; run: log: (pid 29556) 78468s + run: prometheus: (pid 31672) 17335s; run: log: (pid 29633) 78456s + ``` + +[Back to setup components](#setup-components) + +## Configure the object storage[](#configure-the-object-storage "Permalink") + +GitLab 支持使用对象存储服务来保存多种类型的数据. 建议在[NFS](#configure-nfs-optional)上使用它,并且通常在较大的设置中更好,因为对象存储通常具有更高的性能,可靠性和可伸缩性. + +manbetx 客户端打不开已经测试过或知道使用的客户的对象存储选项包括: + +* SaaS / Cloud 解决方案,例如[Amazon S3](https://aws.amazon.com/s3/) , [Google 云存储](https://cloud.google.com/storage) . +* 来自各种存储供应商的本地硬件和设备. +* MinIO. 我们的 Helm Chart 文档中[提供了有关部署的指南](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) . + +要配置 GitLab 以使用对象存储,请根据要使用的功能参考以下指南: + +1. Configure [object storage for backups](../../raketasks/backup_restore.html#uploading-backups-to-a-remote-cloud-storage). +2. Configure [object storage for job artifacts](../job_artifacts.html#using-object-storage) including [incremental logging](../job_logs.html#new-incremental-logging-architecture). +3. Configure [object storage for LFS objects](../lfs/index.html#storing-lfs-objects-in-remote-object-storage). +4. Configure [object storage for uploads](../uploads.html#using-object-storage-core-only). +5. Configure [object storage for merge request diffs](../merge_request_diffs.html#using-object-storage). +6. 配置[容器注册表的对象存储](../packages/container_registry.html#use-object-storage) (可选功能). +7. [为 Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)配置[对象存储](https://docs.mattermost.com/administration/config-settings.html#file-storage) (可选功能). +8. 配置[软件包的对象存储](../packages/index.html#using-object-storage) (可选功能). +9. 配置[依赖项代理的对象存储](../packages/dependency_proxy.html#using-object-storage) (可选功能). +10. [为 Pseudonymizer](../pseudonymizer.html#configuration) (可选功能)配置[对象存储](../pseudonymizer.html#configuration) . +11. 配置[对象存储以自动缩放 Runner 缓存](https://docs.gitlab.com/runner/configuration/autoscale.html) (可选-为了提高性能). +12. Configure [object storage for Terraform state files](../terraform_state.html#using-object-storage-core-only). + +对于 GitLab,建议为每种数据类型使用单独的存储桶. + +我们的配置的局限性是对象存储的每次使用都是单独配置的. [我们有一个需要改进的问题](https://gitlab.com/gitlab-org/gitlab/-/issues/23345) ,轻松地将一个存储桶与单独的文件夹一起使用可能会带来一个改进. + +使用同一个存储桶至少有一个特定的问题:当使用 Helm 图表部署 GitLab 时,除非使用单独的存储桶,否则从备份还原[将无法正常工作](https://docs.gitlab.com/charts/advanced/external-object-storage/) . + +如果您的组织将来决定将 GitLab 迁移到 Helm 部署,则使用单个存储桶的一种风险是. GitLab 可以运行,但是直到组织对备份起作用的关键要求之前,备份的情况可能无法实现. + +[Back to setup components](#setup-components) + +## Configure NFS (optional)[](#configure-nfs-optional "Permalink") + +建议尽可能在 NFS 上使用[对象存储](#configure-the-object-storage)以及[Gitaly](#configure-gitaly) ,以提高性能. 如果您打算使用 GitLab 页面,则当前[需要 NFS](troubleshooting.html#gitlab-pages-requires-nfs) . + +请参阅如何[配置 NFS](../high_availability/nfs.html) . + +[Back to setup components](#setup-components) + +## Troubleshooting[](#troubleshooting "Permalink") + +请参阅[故障排除文档](troubleshooting.html) . + +[Back to setup components](#setup-components) \ No newline at end of file diff --git a/docs/424.md b/docs/424.md new file mode 100644 index 0000000000000000000000000000000000000000..d80495f7a08268f1f8d8f78354cb5fc519d31fae --- /dev/null +++ b/docs/424.md @@ -0,0 +1,1451 @@ +# Reference architecture: up to 5,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/5k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/5k_users.html) + +* [Setup components](#setup-components) +* [Configure the external load balancer](#configure-the-external-load-balancer) + * [Application node terminates SSL](#application-node-terminates-ssl) + * [Load balancer terminates SSL without backend SSL](#load-balancer-terminates-ssl-without-backend-ssl) + * [Load balancer terminates SSL with backend SSL](#load-balancer-terminates-ssl-with-backend-ssl) + * [Ports](#ports) + * [Alternate SSH Port](#alternate-ssh-port) +* [Configure Redis](#configure-redis) + * [Provide your own Redis instance](#provide-your-own-redis-instance) + * [Standalone Redis using Omnibus GitLab](#standalone-redis-using-omnibus-gitlab) + * [Configuring the primary Redis instance](#configuring-the-primary-redis-instance) + * [Configuring the replica Redis instances](#configuring-the-replica-redis-instances) +* [Configure Consul and Sentinel](#configure-consul-and-sentinel) +* [Configure PostgreSQL](#configure-postgresql) + * [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance) + * [Standalone PostgreSQL using Omnibus GitLab](#standalone-postgresql-using-omnibus-gitlab) + * [PostgreSQL primary node](#postgresql-primary-node) + * [PostgreSQL secondary nodes](#postgresql-secondary-nodes) + * [PostgreSQL post-configuration](#postgresql-post-configuration) +* [Configure PgBouncer](#configure-pgbouncer) + * [Configure the internal load balancer](#configure-the-internal-load-balancer) +* [Configure Gitaly](#configure-gitaly) + * [Gitaly TLS support](#gitaly-tls-support) +* [Configure Sidekiq](#configure-sidekiq) +* [Configure GitLab Rails](#configure-gitlab-rails) + * [GitLab Rails post-configuration](#gitlab-rails-post-configuration) +* [Configure Prometheus](#configure-prometheus) +* [Configure the object storage](#configure-the-object-storage) +* [Configure NFS (optional)](#configure-nfs-optional) +* [Troubleshooting](#troubleshooting) + +# Reference architecture: up to 5,000 users[](#reference-architecture-up-to-5000-users "Permalink") + +该页面描述了最多可容纳 5,000 个用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +**注意:**下面记录的 5,000 个用户参考体系结构旨在帮助您的组织实现高度可用的 GitLab 部署. 如果您没有专业知识或需要维护高度可用的环境,则可以遵循[2,000 个用户的参考体系结构](2k_users.html) ,从而拥有一个更简单且成本更低的操作环境. + +> * **支持的用户(大约):** 5,000 +> * **高可用性:** True +> * **测试 RPS 速率:** API:100 RPS,网站:10 RPS,Git:10 RPS + +| Service | Nodes | Configuration | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | --- | +| 外部负载平衡节点 | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| Redis | 3 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| 领事+前哨 | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| PostgreSQL | 3 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| PgBouncer | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| 内部负载平衡节点 | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| Gitaly | 最少 2 个 | 8 个 vCPU,30GB 内存 | `n1-standard-8` | `m5.2xlarge` | `D8s v3` | +| Sidekiq | 4 | 2 个 vCPU,7.5GB 内存 | `n1-standard-2` | `m5.large` | `D2s v3` | +| 亚搏体育 app Rails | 3 | 16 个 vCPU,14.4GB 内存 | `n1-highcpu-16` | `c5.4xlarge` | `F16s v2` | +| 监控节点 | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | +| 对象存储 | n/a | n/a | n/a | n/a | n/a | +| NFS 服务器(可选,不推荐) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` | + +这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. + +对于 LFS,Uploads,Artifacts 等数据对象,由于性能和可用性更好,建议在 NFS 上尽可能使用[对象存储服务](#configure-the-object-storage) . 由于这不需要设置节点,因此在上表中将其标记为不适用(n / a). + +## Setup components[](#setup-components "Permalink") + +设置 GitLab 及其组件以容纳多达 5,000 个用户: + +1. [配置外部负载平衡节点](#configure-the-external-load-balancer) ,该[节点](#configure-the-external-load-balancer)将处理两个 GitLab 应用程序服务节点的负载平衡. +2. [Configure Redis](#configure-redis). +3. [Configure Consul and Sentinel](#configure-consul-and-sentinel). +4. [配置 PostgreSQL](#configure-postgresql) (GitLab 的数据库). +5. [Configure PgBouncer](#configure-pgbouncer). +6. [Configure the internal load balancing node](#configure-the-internal-load-balancer) +7. [配置 Gitaly](#configure-gitaly) ,它提供对 Git 存储库的访问. +8. [Configure Sidekiq](#configure-sidekiq). +9. [配置主 GitLab Rails 应用程序](#configure-gitlab-rails)以运行 Puma / Unicorn,Workhorse,GitLab Shell,并服务所有前端请求(UI,API,基于 HTTP / SSH 的 Git). +10. [配置 Prometheus](#configure-prometheus)来监视您的 GitLab 环境. +11. [配置](#configure-the-object-storage)用于共享数据对象[的对象存储](#configure-the-object-storage) . +12. [将 NFS(可选)配置](#configure-nfs-optional)为具有共享磁盘存储服务,以替代 Gitaly 和/或对象存储(尽管不建议这样做). GitLab 页面需要 NFS,如果不使用该功能,则可以跳过此步骤. + +我们从同一 10.6.0.0/16 专用网络范围内的所有服务器开始,它们可以在这些地址上自由地相互连接. + +这是每台机器和分配的 IP 的列表和说明: + +* `10.6.0.10` :外部负载平衡器 +* `10.6.0.61`主要 +* `10.6.0.62` :返回副本 1 +* `10.6.0.63` :返回副本 2 +* `10.6.0.11` :领事/前哨 1 +* `10.6.0.12` :领事/前哨 2 +* `10.6.0.13` :领事/前哨 3 +* `10.6.0.31`主 +* `10.6.0.32`中学 1 +* `10.6.0.33`中学 2 +* `10.6.0.21` :PgBouncer 1 +* `10.6.0.22` :PgBouncer 2 +* `10.6.0.23` :PgBouncer 3 +* `10.6.0.20` :内部负载均衡器 +* `10.6.0.51` :Gitaly 1 +* `10.6.0.52` :Gitaly 2 +* `10.6.0.71` :Sidekiq 1 +* `10.6.0.72` :Sidekiq 2 +* `10.6.0.73` :Sidekiq 3 +* `10.6.0.74` :Sidekiq 4 +* `10.6.0.41`应用程序 1 +* `10.6.0.42`应用程序 2 +* `10.6.0.43`应用程序 3 +* `10.6.0.81` :普罗米修斯 + +## Configure the external load balancer[](#configure-the-external-load-balancer "Permalink") + +**注意:**此体系结构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +在主动/主动 GitLab 配置中,您将需要一个负载均衡器来将流量路由到应用程序服务器. 有关使用负载均衡器或进行确切配置的细节超出了 GitLab 文档的范围. 我们希望,如果您要管理像 GitLab 这样的多节点系统,那么已经选择了负载均衡器. 一些示例包括 HAProxy(开源),F5 Big-IP LTM 和 Citrix Net Scaler. 本文档将概述需要在 GitLab 上使用哪些端口和协议. + +下一个问题是如何在环境中处理 SSL. 有几种不同的选择: + +* [The application node terminates SSL](#application-node-terminates-ssl). +* [负载平衡器终止没有后端 SSL 的 SSL,](#load-balancer-terminates-ssl-without-backend-ssl)并且负载平衡器与应用程序节点之间的通信不安全. +* [负载均衡器使用后端 SSL 终止 SSL,](#load-balancer-terminates-ssl-with-backend-ssl)并且负载均衡器与应用程序节点之间的通信是*安全*的. + +### Application node terminates SSL[](#application-node-terminates-ssl "Permalink") + +配置您的负载均衡器以将端口 443 上的连接作为`TCP`而不是`HTTP(S)`协议进行传递. 这会将连接直接传递到应用程序节点的 NGINX 服务. NGINX 将具有 SSL 证书并在端口 443 上侦听. + +有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load balancer terminates SSL without backend SSL[](#load-balancer-terminates-ssl-without-backend-ssl "Permalink") + +将您的负载均衡器配置为使用`HTTP(S)`协议而不是`TCP` . 然后,负载平衡器将负责管理 SSL 证书和终止 SSL. + +由于负载均衡器和 GitLab 之间的通信将不安全,因此需要一些其他配置. 有关详细信息,请参见[NGINX 代理的 SSL 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load balancer terminates SSL with backend SSL[](#load-balancer-terminates-ssl-with-backend-ssl "Permalink") + +Configure your load balancer(s) to use the ‘HTTP(S)’ protocol rather than ‘TCP’. The load balancer(s) will be responsible for managing SSL certificates that end users will see. + +在这种情况下,负载均衡器和 NGINX 之间的流量也将是安全的. 无需为代理 SSL 添加配置,因为连接将一直保持安全. 但是,需要将配置添加到 GitLab 来配置 SSL 证书. 有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Ports[](#ports "Permalink") + +下表显示了要使用的基本端口. + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 80 | HTTP( *1* ) | +| 443 | 443 | TCP 或 HTTPS( *1* )( *2* ) | +| 22 | 22 | TCP | + +* ( *1* ): [Web 终端](../../ci/environments/index.html#web-terminals)支持要求您的负载平衡器正确处理 WebSocket 连接. 当使用 HTTP 或 HTTPS 代理,这意味着负载平衡器必须被配置为通过`Connection`和`Upgrade`逐跳头. 有关更多详细信息,请参见[Web 终端](../integration/terminal.html)集成指南. +* ( *2* ):当对端口 443 使用 HTTPS 协议时,需要向负载均衡器添加 SSL 证书. 如果您想在 GitLab 应用程序服务器上终止 SSL,请使用 TCP 协议. + +如果您使用具有自定义域支持的 GitLab 页面,则将需要一些其他端口配置. GitLab 页面需要一个单独的虚拟 IP 地址. 配置 DNS,将`pages_external_url`的`/etc/gitlab/gitlab.rb`指向新的虚拟 IP 地址. 有关更多信息,请参见[GitLab 页面文档](../pages/index.html) . + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 变化( *1* ) | HTTP | +| 443 | 变化( *1* ) | TCP( *2* ) | + +* ( *1* ):GitLab 页面的后端端口取决于`gitlab_pages['external_http']`和`gitlab_pages['external_https']`设置. 有关更多详细信息,请参见[GitLab Pages 文档](../pages/index.html) . +* ( *2* ):GitLab 页面的端口 443 应该始终使用 TCP 协议. 用户可以使用自定义 SSL 配置自定义域,如果 SSL 在负载均衡器处终止,则不可能. + +#### Alternate SSH Port[](#alternate-ssh-port "Permalink") + +某些组织有禁止打开 SSH 端口 22 的策略.在这种情况下,配置允许用户在端口 443 上使用 SSH 的备用 SSH 主机名可能会有所帮助.与其他 GitLab 相比,备用 SSH 主机名将需要一个新的虚拟 IP 地址.上面的 HTTP 配置. + +为备用 SSH 主机名(例如`altssh.gitlab.example.com`配置 DNS. + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 443 | 22 | TCP | + +[Back to setup components](#setup-components) + +## Configure Redis[](#configure-redis "Permalink") + +使用[Redis 的](https://s0redis0io.icopy.site/)可扩展环境,可以使用**一次** X **副本**拓扑与[Redis 的哨兵](https://s0redis0io.icopy.site/topics/sentinel)服务来观看,并自动启动故障转移过程. + +如果与 Sentinel 一起使用,Redis 需要身份验证. 有关更多信息,请参见[Redis 安全性](https://s0redis0io.icopy.site/topics/security)文档. 我们建议结合使用 Redis 密码和严格的防火墙规则来保护您的 Redis 服务. 强烈建议您在使用 GitLab 配置 Redis 之前阅读[Redis Sentinel](https://s0redis0io.icopy.site/topics/sentinel)文档,以充分了解拓扑和体系结构. + +在本节中,将指导您配置与 GitLab 一起使用的外部 Redis 实例. 以下 IP 将作为示例: + +* `10.6.0.61`主要 +* `10.6.0.62` :返回副本 1 +* `10.6.0.63` :返回副本 2 + +### Provide your own Redis instance[](#provide-your-own-redis-instance "Permalink") + +来自云提供商(例如 AWS ElastiCache)的托管 Redis 将可以使用. 如果这些服务支持高可用性,请确保它**不是** Redis 群集类型. + +需要 Redis 5.0 或更高版本,因为这是从 GitLab 13.0 开始的 Omnibus GitLab 软件包附带的版本. 较旧的 Redis 版本不支持 SPOP 的可选 count 参数,这对于[合并火车](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html)现在是必需的. + +注意 Redis 节点的 IP 地址或主机名,端口和密码(如果需要). 这些在以后配置[GitLab 应用程序服务器](#configure-gitlab-rails)时是必需的. + +### Standalone Redis using Omnibus GitLab[](#standalone-redis-using-omnibus-gitlab "Permalink") + +这是我们安装和设置新 Redis 实例的部分. + +Redis 设置的要求如下: + +1. 所有 Redis 节点必须能够互相通信并接受通过 Redis( `6379` )和 Sentinel( `26379` )端口的传入连接(除非您更改默认端口). +2. 托管 GitLab 应用程序的服务器必须能够访问 Redis 节点. +3. 使用防火墙保护节点免受来自外部网络( [Internet](https://gitlab.com/gitlab-org/gitlab-foss/uploads/c4cc8cd353604bd80315f9384035ff9e/The_Internet_IT_Crowd.png) )的访问. + +**注意:** Redis 节点(主节点和副本节点)将需要使用`redis['password']`定义的相同密码. 在故障转移期间的任何时间,Sentinels 都可以重新配置节点并将其状态从主节点更改为副本节点,反之亦然. + +#### Configuring the primary Redis instance[](#configuring-the-primary-redis-instance "Permalink") + +1. SSH 进入**主** Redis 服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 确保选择正确的 Omnibus 软件包,并使用与当前安装相同的版本和类型(社区版,企业版). + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + # Specify server role as 'redis_master_role' + roles ['redis_master_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.61' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Set up password authentication for Redis (use the same password in all nodes). + redis['password'] = 'redis-password-goes-here' + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + redis_exporter['flags'] = { + 'redis.addr' => 'redis://10.6.0.61:6379', + 'redis.password' => 'redis-password-goes-here', + } + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**注意:**您可以将多个角色(如哨兵和 Redis)指定为: `roles ['redis_sentinel_role', 'redis_master_role']` . 阅读有关[角色的](https://docs.gitlab.com/omnibus/roles/)更多信息. + +您可以通过以下方式列出当前 Redis 主副本服务器状态: + +``` +/opt/gitlab/embedded/bin/redis-cli -h -a 'redis-password-goes-here' info replication +``` + +通过以下方式显示正在运行的 GitLab 服务: + +``` +gitlab-ctl status +``` + +输出应类似于以下内容: + +``` +run: consul: (pid 30043) 76863s; run: log: (pid 29691) 76892s +run: logrotate: (pid 31152) 3070s; run: log: (pid 29595) 76908s +run: node-exporter: (pid 30064) 76862s; run: log: (pid 29624) 76904s +run: redis: (pid 30070) 76861s; run: log: (pid 29573) 76914s +run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s +``` + +#### Configuring the replica Redis instances[](#configuring-the-replica-redis-instances "Permalink") + +1. SSH 进入**副本** Redis 服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 确保选择正确的 Omnibus 软件包,并使用与当前安装相同的版本和类型(社区版,企业版). + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + # Specify server role as 'redis_replica_role' + roles ['redis_replica_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.62' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # The same password for Redis authentication you set up for the primary node. + redis['password'] = 'redis-password-goes-here' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + redis_exporter['flags'] = { + 'redis.addr' => 'redis://10.6.0.62:6379', + 'redis.password' => 'redis-password-goes-here', + } + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +5. 对于所有其他副本节点,请再次执行该步骤,并确保正确设置 IP. + +**注意:**您可以将多个角色(如哨兵和 Redis)指定为: `roles ['redis_sentinel_role', 'redis_master_role']` . 阅读有关[角色的](https://docs.gitlab.com/omnibus/roles/)更多信息. + +故障转移后, `/etc/gitlab/gitlab.rb`在`/etc/gitlab/gitlab.rb`再次更改这些值,因为节点将由[Sentinels](#configure-consul-and-sentinel)管理,即使在`gitlab-ctl reconfigure` ,它们也将通过恢复配置恢复.同样的哨兵 + +支持高级[配置选项](https://docs.gitlab.com/omnibus/settings/redis.html) ,可以根据需要添加. + +[Back to setup components](#setup-components) + +## Configure Consul and Sentinel[](#configure-consul-and-sentinel "Permalink") + +**注意:**如果您使用的是外部 Redis Sentinel 实例,请确保从 Sentinel 配置中排除`requirepass`参数. 此参数将导致客户端报告`NOAUTH Authentication required.` . [Redis Sentinel 3.2.x 不支持密码身份验证](https://github.com/antirez/redis/issues/3279) . + +现在已经全部安装了 Redis 服务器,让我们配置 Sentinel 服务器. 以下 IP 将作为示例: + +* `10.6.0.11` :领事/前哨 1 +* `10.6.0.12` :领事/前哨 2 +* `10.6.0.13` :领事/前哨 3 + +要配置 Sentinel: + +1. SSH 进入将托管 Consul / Sentinel 的服务器. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/) Omnibus GitLab 企业版软件包. + * 确保选择正确的 Omnibus 软件包,并且与 GitLab 应用程序正在运行的版本相同. + * 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + roles ['redis_sentinel_role', 'consul_role'] + + # Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + # The same password for Redis authentication you set up for the primary node. + redis['master_password'] = 'redis-password-goes-here' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Configure Sentinel + sentinel['bind'] = '10.6.0.11' + + # Port that Sentinel listens on, uncomment to change to non default. Defaults + # to `26379`. + # sentinel['port'] = 26379 + + ## Quorum must reflect the amount of voting sentinels it take to start a failover. + ## Value must NOT be greater then the amount of sentinels. + ## + ## The quorum can be used to tune Sentinel in two ways: + ## 1\. If a the quorum is set to a value smaller than the majority of Sentinels + ## we deploy, we are basically making Sentinel more sensible to primary failures, + ## triggering a failover as soon as even just a minority of Sentinels is no longer + ## able to talk with the primary. + ## 1\. If a quorum is set to a value greater than the majority of Sentinels, we are + ## making Sentinel able to failover only when there are a very large number (larger + ## than majority) of well connected Sentinels which agree about the primary being down.s + sentinel['quorum'] = 2 + + ## Consider unresponsive server down after x amount of ms. + # sentinel['down_after_milliseconds'] = 10000 + + ## Specifies the failover timeout in milliseconds. It is used in many ways: + ## + ## - The time needed to re-start a failover after a previous failover was + ## already tried against the same primary by a given Sentinel, is two + ## times the failover timeout. + ## + ## - The time needed for a replica replicating to a wrong primary according + ## to a Sentinel current configuration, to be forced to replicate + ## with the right primary, is exactly the failover timeout (counting since + ## the moment a Sentinel detected the misconfiguration). + ## + ## - The time needed to cancel a failover that is already in progress but + ## did not produced any configuration change (REPLICAOF NO ONE yet not + ## acknowledged by the promoted replica). + ## + ## - The maximum time a failover in progress waits for all the replica to be + ## reconfigured as replicas of the new primary. However even after this time + ## the replicas will be reconfigured by the Sentinels anyway, but not with + ## the exact parallel-syncs progression as specified. + # sentinel['failover_timeout'] = 60000 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + server: true, + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +4. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +5. 对于其他所有 Consul / Sentinel 节点,请再次执行步骤,并确保设置了正确的 IP. + +**注意:**第三个 Consul 服务器的配置完成后,将选举 Consul 负责人. 查看领事日志`sudo gitlab-ctl tail consul`将显示`...[INFO] consul: New leader elected: ...` + +You can list the current Consul members (server, client): + +``` +sudo /opt/gitlab/embedded/bin/consul members +``` + +您可以验证 GitLab 服务正在运行: + +``` +sudo gitlab-ctl status +``` + +输出应类似于以下内容: + +``` +run: consul: (pid 30074) 76834s; run: log: (pid 29740) 76844s +run: logrotate: (pid 30925) 3041s; run: log: (pid 29649) 76861s +run: node-exporter: (pid 30093) 76833s; run: log: (pid 29663) 76855s +run: sentinel: (pid 30098) 76832s; run: log: (pid 29704) 76850s +``` + +[Back to setup components](#setup-components) + +## Configure PostgreSQL[](#configure-postgresql "Permalink") + +在本节中,将指导您配置与 GitLab 一起使用的外部 PostgreSQL 数据库. + +### Provide your own PostgreSQL instance[](#provide-your-own-postgresql-instance "Permalink") + +如果您将 GitLab 托管在云提供商上,则可以选择将托管服务用于 PostgreSQL. 例如,AWS 提供了运行 PostgreSQL 的托管关系数据库服务(RDS). + +如果您使用云托管服务,或提供自己的 PostgreSQL: + +1. 根据[数据库要求文档](../../install/requirements.html#database)设置 PostgreSQL. +2. 使用您选择的密码设置一个`gitlab`用户名. `gitlab`用户需要特权才能创建`gitlabhq_production`数据库. +3. 使用适当的详细信息配置 GitLab 应用程序服务器. [配置 GitLab Rails 应用程序](#configure-gitlab-rails)涵盖了此步骤. + +### Standalone PostgreSQL using Omnibus GitLab[](#standalone-postgresql-using-omnibus-gitlab "Permalink") + +以下 IP 将作为示例: + +* `10.6.0.31`主 +* `10.6.0.32`中学 1 +* `10.6.0.33`中学 2 + +首先,请确保**在每个节点上** [安装](https://about.gitlab.com/install/) Linux GitLab 软件包. 按照以下步骤,从步骤 1 安装必需的依赖项,并从步骤 2 添加 GitLab 软件包存储库.在第二步中安装 GitLab 时,请勿提供`EXTERNAL_URL`值. + +#### PostgreSQL primary node[](#postgresql-primary-node "Permalink") + +1. SSH 进入 PostgreSQL 主节点. +2. 为 PostgreSQL 用户名/密码对生成密码哈希. 假设您将使用默认用户名`gitlab` (推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作``的值: + + ``` + sudo gitlab-ctl pg-password-md5 gitlab + ``` + +3. 为 PgBouncer 用户名/密码对生成密码哈希. 假设您将使用`pgbouncer`的默认用户名(推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作``的值: + + ``` + sudo gitlab-ctl pg-password-md5 pgbouncer + ``` + +4. 为 Consul 数据库用户名/密码对生成密码哈希. 假设您将使用默认用户名`gitlab-consul` (推荐). 该命令将要求输入密码和确认. 将此命令在下一步中输出的值用作``的值: + + ``` + sudo gitlab-ctl pg-password-md5 gitlab-consul + ``` + +5. 在主数据库节点上,编辑`/etc/gitlab/gitlab.rb`替换`/etc/gitlab/gitlab.rb` `# START user configuration`部分中记录的值: + + ``` + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # START user configuration + # Please set the real values as explained in Required Information section + # + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace XXX.XXX.XXX.XXX/YY with Network Address + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + postgres_exporter['dbname'] = 'gitlabhq_production' + postgres_exporter['password'] = '' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + # + # END user configuration + ``` + +6. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +7. 您可以通过以下方式列出当前 PostgreSQL 主,辅助节点的状态: + + ``` + sudo /opt/gitlab/bin/gitlab-ctl repmgr cluster show + ``` + +8. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 30593) 77133s; run: log: (pid 29912) 77156s + run: logrotate: (pid 23449) 3341s; run: log: (pid 29794) 77175s + run: node-exporter: (pid 30613) 77133s; run: log: (pid 29824) 77170s + run: postgres-exporter: (pid 30620) 77132s; run: log: (pid 29894) 77163s + run: postgresql: (pid 30630) 77132s; run: log: (pid 29618) 77181s + run: repmgrd: (pid 30639) 77132s; run: log: (pid 29985) 77150s + ``` + +[Back to setup components](#setup-components) + +#### PostgreSQL secondary nodes[](#postgresql-secondary-nodes "Permalink") + +1. 在两个辅助节点上,添加与上面为主要节点指定的配置相同的附加设置,该设置将告知`gitlab-ctl`最初它们是备用节点,无需尝试将它们注册为主要节点: + + ``` + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # Specify if a node should attempt to be primary on initialization. + repmgr['master_on_initialization'] = false + + # START user configuration + # Please set the real values as explained in Required Information section + # + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace XXX.XXX.XXX.XXX/YY with Network Address + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + postgres_exporter['dbname'] = 'gitlabhq_production' + postgres_exporter['password'] = '' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + # END user configuration + ``` + +2. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +支持高级[配置选项](https://docs.gitlab.com/omnibus/settings/database.html) ,可以根据需要添加. + +[Back to setup components](#setup-components) + +#### PostgreSQL post-configuration[](#postgresql-post-configuration "Permalink") + +SSH 进入**主节点** : + +1. 打开数据库提示: + + ``` + gitlab-psql -d gitlabhq_production + ``` + +2. Enable the `pg_trgm` extension: + + ``` + CREATE EXTENSION pg_trgm; + ``` + +3. 键入`\q`并按 Enter 退出数据库提示. + +4. 验证集群是否已用一个节点初始化: + + ``` + gitlab-ctl repmgr cluster show + ``` + + 输出应类似于以下内容: + + ``` + Role | Name | Upstream | Connection String + ----------+----------|----------|---------------------------------------- + * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr + ``` + +5. 在连接字符串中记下主机名或 IP 地址: `host=HOSTNAME` . 在下一节中,我们将主机名称为`` . 如果该值不是 IP 地址,则必须是可解析的名称(通过 DNS 或`/etc/hosts` ) + +SSH 进入**辅助节点** : + +1. 设置 repmgr 备用数据库: + + ``` + gitlab-ctl repmgr standby setup + ``` + + Do note that this will remove the existing data on the node. The command has a wait time. + + 输出应类似于以下内容: + + ``` + Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data + If this is not what you want, hit Ctrl-C now to exit + To skip waiting, rerun with the -w option + Sleeping for 30 seconds + Stopping the database + Removing the data + Cloning the data + Starting the database + Registering the node with the cluster + ok: run: repmgrd: (pid 19068) 0s + ``` + +在继续之前,请确保正确配置了数据库. 在**主**节点上运行以下命令以验证复制是否正常工作,并且辅助节点是否出现在群集中: + +``` +gitlab-ctl repmgr cluster show +``` + +输出应类似于以下内容: + +``` +Role | Name | Upstream | Connection String +----------+---------|-----------|------------------------------------------------ +* master | MASTER | | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr +``` + +如果任何节点的"角色"列显示"失败",请在继续操作之前检查" [故障排除"部分](troubleshooting.html) . + +另外,请检查`repmgr-check-master`命令在每个节点上是否都能正常工作: + +``` +su - gitlab-consul +gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' +``` + +此命令依靠退出代码来告诉 Consul 特定节点是主节点还是辅助节点. 这里最重要的是该命令不会产生错误. 如果有错误,很可能是由于`gitlab-consul`数据库用户权限不正确`gitlab-consul` . 在继续之前,请检查" [故障排除"部分](troubleshooting.html) . + +[Back to setup components](#setup-components) + +## Configure PgBouncer[](#configure-pgbouncer "Permalink") + +现在已经安装了 PostgreSQL 服务器,让我们配置 PgBouncer. 以下 IP 将作为示例: + +* `10.6.0.21` :PgBouncer 1 +* `10.6.0.22` :PgBouncer 2 +* `10.6.0.23` :PgBouncer 3 + +1. 在每个 PgBouncer 节点上,编辑`/etc/gitlab/gitlab.rb` ,并将``和``替换为[之前设置](#postgresql-primary-node)的密码哈希: + + ``` + # Disable all components except Pgbouncer and Consul agent + roles ['pgbouncer_role'] + + # Configure PgBouncer + pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) + + pgbouncer['users'] = { + 'gitlab-consul': { + password: '' + }, + 'pgbouncer': { + password: '' + } + } + + # Configure Consul agent + consul['watchers'] = %w(postgresql) + consul['enable'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + pgbouncer_exporter['listen_address'] = '0.0.0.0:9188' + ``` + +2. [重新配置 Omnibus GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +3. 创建一个`.pgpass`文件,以便 Consul 能够重新加载 PgBouncer. 询问时两次输入 PgBouncer 密码: + + ``` + gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul + ``` + +4. 确保每个节点都在与当前主节点通信: + + ``` + gitlab-ctl pgb-console # You will be prompted for PGBOUNCER_PASSWORD + ``` + + 如果出现错误`psql: ERROR: Auth failed`输入密码后`psql: ERROR: Auth failed` ,请确保您以前以正确的格式生成了 MD5 密码哈希. 正确的格式是连接密码和用户名`PASSWORDUSERNAME` . 例如, `Sup3rS3cr3tpgbouncer`将是为`pgbouncer`用户生成 MD5 密码哈希所需的文本. + +5. 控制台提示可用后,请运行以下查询: + + ``` + show databases ; show clients ; + ``` + + 输出应类似于以下内容: + + ``` + name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections + ---------------------+-------------+------+---------------------+------------+-----------+--------------+-----------+-----------------+--------------------- + gitlabhq_production | MASTER_HOST | 5432 | gitlabhq_production | | 20 | 0 | | 0 | 0 + pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0 + (2 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | remote_pid | tls + ------+-----------+---------------------+---------+----------------+-------+------------+------------+---------------------+---------------------+-----------+------+------------+----- + C | pgbouncer | pgbouncer | active | 127.0.0.1 | 56846 | 127.0.0.1 | 6432 | 2017-08-21 18:09:59 | 2017-08-21 18:10:48 | 0x22b3880 | | 0 | + (2 rows) + ``` + +6. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + The output should be similar to the following: + + ``` + run: consul: (pid 31530) 77150s; run: log: (pid 31106) 77182s + run: logrotate: (pid 32613) 3357s; run: log: (pid 30107) 77500s + run: node-exporter: (pid 31550) 77149s; run: log: (pid 30138) 77493s + run: pgbouncer: (pid 32033) 75593s; run: log: (pid 31117) 77175s + run: pgbouncer-exporter: (pid 31558) 77148s; run: log: (pid 31498) 77156s + ``` + +[Back to setup components](#setup-components) + +### Configure the internal load balancer[](#configure-the-internal-load-balancer "Permalink") + +如果按照建议运行多个 PgBouncer 节点,那么此时,您将需要设置一个 TCP 内部负载均衡器以正确地服务每个负载均衡器. + +以下 IP 将作为示例: + +* `10.6.0.20` :内部负载均衡器 + +使用[HAProxy 的方法](https://www.haproxy.org/)如下: + +``` +global + log /dev/log local0 + log localhost local1 notice + log stdout format raw local0 + +defaults + log global + default-server inter 10s fall 3 rise 2 + balance leastconn + +frontend internal-pgbouncer-tcp-in + bind *:6432 + mode tcp + option tcplog + + default_backend pgbouncer + +backend pgbouncer + mode tcp + option tcp-check + + server pgbouncer1 10.6.0.21:6432 check + server pgbouncer2 10.6.0.22:6432 check + server pgbouncer3 10.6.0.23:6432 check +``` + +请参阅您首选的负载均衡器的文档以获取更多指导. + +[Back to setup components](#setup-components) + +## Configure Gitaly[](#configure-gitaly "Permalink") + +在自己的服务器上部署 Gitaly 可以使大于单个计算机的 GitLab 安装受益. + +Gitaly 节点要求取决于客户数据,特别是项目数量及其存储库大小. 建议将两个节点作为绝对最小值. 每个 Gitaly 节点应存储的数据不超过 5TB,并将[`gitaly-ruby`工作者](../gitaly/index.html#gitaly-ruby)的数量设置为可用 CPU 的 20%. 根据以上建议,应结合其他节点并结合对预期数据大小和分布的审查. + +强烈建议所有 Gitaly 节点都安装 SSD 磁盘,因为 Gitaly I / O 繁重,因此其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +注意事项: + +* GitLab Rails 应用程序将[存储库分](../repository_storage_paths.html)片到[存储库中](../repository_storage_paths.html) . +* Gitaly 服务器可以托管一个或多个存储. +* 一个 GitLab 服务器可以使用一个或多个 Gitaly 服务器. +* 必须以对所有 Gitaly 客户端正确解析的方式指定 Gitaly 地址. +* Gitaly 服务器一定不能暴露在公共互联网上,因为默认情况下,Gitaly 的网络流量是未加密的. 强烈建议使用防火墙以限制对 Gitaly 服务器的访问. 另一种选择是[使用 TLS](#gitaly-tls-support) . + +**提示:**有关 Gitaly 历史和网络体系结构的更多信息,请参见[独立的 Gitaly 文档](../gitaly/index.html) . + +注意: **注意:** Gitaly 文档中引用的令牌只是管理员选择的任意密码. 它与为 GitLab API 创建的令牌或其他类似的 Web API 令牌无关. + +下面我们描述如何配置两个具有 IP 和域名的 Gitaly 服务器: + +* `10.6.0.51` 1( `gitaly1.internal` ) +* `10.6.0.52` 2( `gitaly2.internal` ) + +假定该秘密令牌为`gitalysecret` ,并且您的 GitLab 安装具有三个存储库存储: + +* `default`为 Gitaly 1 +* `storage1`在 Gitaly 1 +* `storage2`上 Gitaly 2 + +在每个节点上: + +1. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包,但**不**提供`EXTERNAL_URL`值. +2. 编辑`/etc/gitlab/gitlab.rb`以配置存储路径,启用网络侦听器并配置令牌: + + ``` + # /etc/gitlab/gitlab.rb + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the GitLab Rails application setup + gitaly['auth_token'] = 'gitlaysecret' + gitlab_shell['secret_token'] = 'shellsecret' + + # Avoid running unnecessary services on the Gitaly server + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + grafana['enable'] = false + gitlab_exporter['enable'] = false + + # If you run a seperate monitoring node you can disable these services + alertmanager['enable'] = false + prometheus['enable'] = false + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your 'front door' GitLab URL or an internal load + # balancer. + # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server. + gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' + + # Make Gitaly accept connections on all network interfaces. You must use + # firewalls to restrict access to this address/port. + # Comment out following line if you only want to support TLS connections + gitaly['listen_addr'] = "0.0.0.0:8075" + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + gitaly['prometheus_listen_addr'] = "0.0.0.0:9236" + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_rails['prometheus_address'] = '10.6.0.81:9090' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + ``` + +3. 对于每个服务器,将以下内容附加到`/etc/gitlab/gitlab.rb` : + 1. 在`gitaly1.internal` : + + ``` + git_data_dirs ({ 'default' => { 'path' => '/var/opt/gitlab/git-data' }, 'storage1' => { 'path' => '/mnt/gitlab/git-data' }, }) + ``` + + 2. 在`gitaly2.internal` : + + ``` + git_data_dirs ({ 'storage2' => { 'path' => '/mnt/gitlab/git-data' }, }) + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 确认 Gitaly 可以执行对内部 API 的回调: + + ``` + sudo /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml + ``` + +6. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 30339) 77006s; run: log: (pid 29878) 77020s + run: gitaly: (pid 30351) 77005s; run: log: (pid 29660) 77040s + run: logrotate: (pid 7760) 3213s; run: log: (pid 29782) 77032s + run: node-exporter: (pid 30378) 77004s; run: log: (pid 29812) 77026s + ``` + +### Gitaly TLS support[](#gitaly-tls-support "Permalink") + +Gitaly 支持 TLS 加密. 为了能够与侦听安全连接的 Gitaly 实例进行通信,您将需要在 GitLab 配置中相应存储条目的`gitaly_address`中使用`tls://` URL 方案. + +您将需要携带自己的证书,因为该证书不会自动提供. 证书或其证书颁发机构必须按照[GitLab 自定义证书配置中](https://docs.gitlab.com/omnibus/settings/ssl.html)所述的步骤,安装在所有 Gitaly 节点(包括使用证书的 Gitaly 节点)上,以及与之通信的所有客户端节点上. + +**注意:**自签名证书必须指定用于访问 Gitaly 服务器的地址. 如果要通过主机名寻址 Gitaly 服务器,则可以为此使用"公用名"字段,也可以将其添加为"使用者备用名". 如果要通过 Gitaly 服务器的 IP 地址对其进行寻址,则必须将其作为主题备用名称添加到证书中. [gRPC 不支持在证书中使用 IP 地址作为公用名](https://github.com/grpc/grpc/issues/2691) .**注意:**可以同时为 Gitaly 服务器配置未加密的侦听地址`listen_addr`和已加密的侦听地址`tls_listen_addr` . 如果需要,这使您可以从未加密的流量逐渐过渡到加密的流量. + +要使用 TLS 配置 Gitaly: + +1. 创建`/etc/gitlab/ssl`目录,并在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +2. 将证书复制到`/etc/gitlab/trusted-certs`以便 Gitaly 在调用自身时信任该证书: + + ``` + sudo cp /etc/gitlab/ssl/cert.pem /etc/gitlab/trusted-certs/ + ``` + +3. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + gitaly['tls_listen_addr'] = "0.0.0.0:9999" + gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + gitaly['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +4. 删除`gitaly['listen_addr']`以仅允许加密连接. +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +[Back to setup components](#setup-components) + +## Configure Sidekiq[](#configure-sidekiq "Permalink") + +Sidekiq 需要连接到 Redis,PostgreSQL 和 Gitaly 实例. 以下 IP 将作为示例: + +* `10.6.0.71` :Sidekiq 1 +* `10.6.0.72` :Sidekiq 2 +* `10.6.0.73` :Sidekiq 3 +* `10.6.0.74` :Sidekiq 4 + +要配置 Sidekiq 节点,每个节点一个: + +1. SSH 到 Sidekiq 服务器. +2. 从 GitLab 下载页面使用步骤 1 和 2 [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. **不要完成下载页面上的任何其他步骤.** +3. 使用编辑器打开`/etc/gitlab/gitlab.rb` : + + ``` + ######################################## + ##### Services Disabled ### + ######################################## + + nginx['enable'] = false + grafana['enable'] = false + prometheus['enable'] = false + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + puma['enable'] = false + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + gitlab_exporter['enable'] = false + + ######################################## + #### Redis ### + ######################################## + + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + ## The same password for Redis authentication you set up for the master node. + redis['master_password'] = '' + + ## A list of sentinels with `host` and `port` + gitlab_rails['redis_sentinels'] = [ + {'host' => '10.6.0.11', 'port' => 26379}, + {'host' => '10.6.0.12', 'port' => 26379}, + {'host' => '10.6.0.13', 'port' => 26379}, + ] + + ####################################### + ### Gitaly ### + ####################################### + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + + ####################################### + ### Postgres ### + ####################################### + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['auto_migrate'] = false + + ####################################### + ### Sidekiq configuration ### + ####################################### + sidekiq['listen_address'] = "0.0.0.0" + + ####################################### + ### Monitoring configuration ### + ####################################### + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + + # Rails Status for prometheus + gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8'] + gitlab_rails['prometheus_address'] = '10.6.0.81:9090' + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 30114) 77353s; run: log: (pid 29756) 77367s + run: logrotate: (pid 9898) 3561s; run: log: (pid 29653) 77380s + run: node-exporter: (pid 30134) 77353s; run: log: (pid 29706) 77372s + run: sidekiq: (pid 30142) 77351s; run: log: (pid 29638) 77386s + ``` + +**提示:**您还可以运行[多个 Sidekiq 进程](../operations/extra_sidekiq_processes.html) .[Back to setup components](#setup-components) + +## Configure GitLab Rails[](#configure-gitlab-rails "Permalink") + +**注意:**在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数设置为可用 CPU 的 90%以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +本节介绍如何配置 GitLab 应用程序(Rails)组件. 在每个节点上执行以下操作: + +1. 如果您[使用的是 NFS](#configure-nfs-optional) : + + 1. 如有必要,请使用以下命令安装 NFS 客户端实用程序软件包: + + ``` + # Ubuntu/Debian + apt-get install nfs-common + + # CentOS/Red Hat + yum install nfs-utils nfs-utils-lib + ``` + + 2. 在`/etc/fstab`指定必要的 NFS 挂载. `/etc/fstab`的确切内容取决于您选择配置 NFS 服务器的方式. 有关示例和各种选项,请参见[NFS 文档](../high_availability/nfs.html) . + + 3. 创建共享目录. 这些可能会有所不同,具体取决于您的 NFS 安装位置. + + ``` + mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data + ``` + +2. 使用[GitLab 下载中的](https://about.gitlab.com/install/) **步骤 1 和 2**下载/安装 Omnibus GitLab. 不要完成下载页面上的其他步骤. +3. 创建/编辑`/etc/gitlab/gitlab.rb`并使用以下配置. 为了保持整个节点的链接均匀性, `external_url`在应用服务器上应指向外部 URL,用户将用来访问 GitLab. 这将是[外部负载平衡器](#configure-the-external-load-balancer)的 URL,它将[负载](#configure-the-external-load-balancer)流量路由到 GitLab 应用程序服务器: + + ``` + external_url 'https://gitlab.example.com' + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the Gitaly setup + gitlab_rails['gitaly_token'] = 'gitalyecret' + gitlab_shell['secret_token'] = 'shellsecret' + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + + ## Disable components that will not be on the GitLab application server + roles ['application_role'] + gitaly['enable'] = false + nginx['enable'] = true + sidekiq['enable'] = false + + ## PostgreSQL connection details + # Disable PostgreSQL on the application node + postgresql['enable'] = false + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['auto_migrate'] = false + + ## Redis connection details + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + ## The same password for Redis authentication you set up for the Redis primary node. + redis['master_password'] = '' + + ## A list of sentinels with `host` and `port` + gitlab_rails['redis_sentinels'] = [ + {'host' => '10.6.0.11', 'port' => 26379}, + {'host' => '10.6.0.12', 'port' => 26379}, + {'host' => '10.6.0.13', 'port' => 26379} + ] + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' + sidekiq['listen_address'] = "0.0.0.0" + puma['listen'] = '0.0.0.0' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Add the monitoring node's IP address to the monitoring whitelist and allow it to + # scrape the NGINX metrics + gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8'] + nginx['status']['options']['allow'] = ['10.6.0.81/32', '127.0.0.0/8'] + gitlab_rails['prometheus_address'] = '10.6.0.81:9090' + + ## Uncomment and edit the following options if you have set up NFS + ## + ## Prevent GitLab from starting if NFS data mounts are not available + ## + #high_availability['mountpoint'] = '/var/opt/gitlab/git-data' + ## + ## Ensure UIDs and GIDs match between servers for permissions via NFS + ## + #user['uid'] = 9000 + #user['gid'] = 9000 + #web_server['uid'] = 9001 + #web_server['gid'] = 9001 + #registry['uid'] = 9002 + #registry['gid'] = 9002 + ``` + +4. 如果您正在使用[具有 TLS 支持](#gitaly-tls-support)的`git_data_dirs` ,请确保`git_data_dirs`条目配置了`tls`而不是`tcp` : + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' }, + }) + ``` + + 1. 将证书复制到`/etc/gitlab/trusted-certs` : + + ``` + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +5. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +6. 运行`sudo gitlab-rake gitlab:gitaly:check`确认节点可以连接到 Gitaly. +7. 拖尾日志以查看请求: + + ``` + sudo gitlab-ctl tail gitaly + ``` + +8. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 4890) 8647s; run: log: (pid 29962) 79128s + run: gitlab-exporter: (pid 4902) 8647s; run: log: (pid 29913) 79134s + run: gitlab-workhorse: (pid 4904) 8646s; run: log: (pid 29713) 79155s + run: logrotate: (pid 12425) 1446s; run: log: (pid 29798) 79146s + run: nginx: (pid 4925) 8646s; run: log: (pid 29726) 79152s + run: node-exporter: (pid 4931) 8645s; run: log: (pid 29855) 79140s + run: puma: (pid 4936) 8645s; run: log: (pid 29656) 79161s + ``` + +**注意:**如上例所示,当在`external_url`指定`https`时,GitLab 会假定您在`/etc/gitlab/ssl/`具有 SSL 证书. 如果没有证书,NGINX 将无法启动. 有关更多信息,请参见[NGINX 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### GitLab Rails post-configuration[](#gitlab-rails-post-configuration "Permalink") + +1. 确保运行所有迁移: + + ``` + gitlab-rake gitlab:db:configure + ``` + + **注意:**如果遇到`rake aborted!` 错误,指出 PgBouncer 是无法连接到 PostgreSQL 也可能是您的 PgBouncer 节点的 IP 地址是从 PostgreSQL 的缺失`trust_auth_cidr_addresses`在`gitlab.rb`你的数据库节点. 请参阅"故障排除"部分中的[PgBouncer 错误`ERROR: pgbouncer cannot connect to server`](troubleshooting.html#pgbouncer-error-error-pgbouncer-cannot-connect-to-server) ,然后再继续. +2. [Configure fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.html). + +[Back to setup components](#setup-components) + +## Configure Prometheus[](#configure-prometheus "Permalink") + +Omnibus GitLab 软件包可用于配置运行[Prometheus](../monitoring/prometheus/index.html)和[Grafana](../monitoring/performance/grafana_configuration.html)的独立 Monitoring 节点: + +1. SSH 进入"监视"节点. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. 不要完成下载页面上的任何其他步骤. +3. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + external_url 'http://gitlab.example.com' + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + node_exporter['enable'] = false + gitlab_exporter['enable'] = false + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Login form + grafana['disable_login_form'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = '' + + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 在 GitLab 用户界面中,将`admin/application_settings/metrics_and_profiling` >指标-Grafana 设置为`/-/grafana`到`http[s]:///-/grafana` . +6. 验证 GitLab 服务正在运行: + + ``` + sudo gitlab-ctl status + ``` + + 输出应类似于以下内容: + + ``` + run: consul: (pid 31637) 17337s; run: log: (pid 29748) 78432s + run: grafana: (pid 31644) 17337s; run: log: (pid 29719) 78438s + run: logrotate: (pid 31809) 2936s; run: log: (pid 29581) 78462s + run: nginx: (pid 31665) 17335s; run: log: (pid 29556) 78468s + run: prometheus: (pid 31672) 17335s; run: log: (pid 29633) 78456s + ``` + +[Back to setup components](#setup-components) + +## Configure the object storage[](#configure-the-object-storage "Permalink") + +GitLab 支持使用对象存储服务来保存多种类型的数据. 建议在[NFS](#configure-nfs-optional)上使用它,并且通常在较大的设置中更好,因为对象存储通常具有更高的性能,可靠性和可伸缩性. + +manbetx 客户端打不开已经测试过或知道使用的客户的对象存储选项包括: + +* SaaS / Cloud 解决方案,例如[Amazon S3](https://aws.amazon.com/s3/) , [Google 云存储](https://cloud.google.com/storage) . +* 来自各种存储供应商的本地硬件和设备. +* MinIO. 我们的 Helm Chart 文档中[提供了有关部署的指南](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) . + +要配置 GitLab 以使用对象存储,请根据要使用的功能参考以下指南: + +1. Configure [object storage for backups](../../raketasks/backup_restore.html#uploading-backups-to-a-remote-cloud-storage). +2. Configure [object storage for job artifacts](../job_artifacts.html#using-object-storage) including [incremental logging](../job_logs.html#new-incremental-logging-architecture). +3. Configure [object storage for LFS objects](../lfs/index.html#storing-lfs-objects-in-remote-object-storage). +4. Configure [object storage for uploads](../uploads.html#using-object-storage-core-only). +5. Configure [object storage for merge request diffs](../merge_request_diffs.html#using-object-storage). +6. 配置[容器注册表的对象存储](../packages/container_registry.html#use-object-storage) (可选功能). +7. [为 Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)配置[对象存储](https://docs.mattermost.com/administration/config-settings.html#file-storage) (可选功能). +8. 配置[软件包的对象存储](../packages/index.html#using-object-storage) (可选功能). +9. 配置[依赖项代理的对象存储](../packages/dependency_proxy.html#using-object-storage) (可选功能). +10. [为 Pseudonymizer](../pseudonymizer.html#configuration) (可选功能)配置[对象存储](../pseudonymizer.html#configuration) . +11. 配置[对象存储以自动缩放 Runner 缓存](https://docs.gitlab.com/runner/configuration/autoscale.html) (可选-为了提高性能). +12. Configure [object storage for Terraform state files](../terraform_state.html#using-object-storage-core-only). + +对于 GitLab,建议为每种数据类型使用单独的存储桶. + +我们的配置的局限性是对象存储的每次使用都是单独配置的. [我们有一个需要改进的问题](https://gitlab.com/gitlab-org/gitlab/-/issues/23345) ,轻松地将一个存储桶与单独的文件夹一起使用可能会带来一个改进. + +使用同一个存储桶至少有一个特定的问题:当使用 Helm 图表部署 GitLab 时,除非使用单独的存储桶,否则从备份还原[将无法正常工作](https://docs.gitlab.com/charts/advanced/external-object-storage/) . + +如果您的组织将来决定将 GitLab 迁移到 Helm 部署,则使用单个存储桶的一种风险是. GitLab 可以运行,但是直到组织对备份起作用的关键要求之前,备份的情况可能无法实现. + +[Back to setup components](#setup-components) + +## Configure NFS (optional)[](#configure-nfs-optional "Permalink") + +建议尽可能在 NFS 上使用[对象存储](#configure-the-object-storage)以及[Gitaly](#configure-gitaly) ,以提高性能. 如果您打算使用 GitLab 页面,则当前[需要 NFS](troubleshooting.html#gitlab-pages-requires-nfs) . + +请参阅如何[配置 NFS](../high_availability/nfs.html) . + +[Back to setup components](#setup-components) + +## Troubleshooting[](#troubleshooting "Permalink") + +请参阅[故障排除文档](troubleshooting.html) . + +[Back to setup components](#setup-components) \ No newline at end of file diff --git a/docs/425.md b/docs/425.md new file mode 100644 index 0000000000000000000000000000000000000000..31e7e894d45a91f47c423cb724633ff2b0e0ed6e --- /dev/null +++ b/docs/425.md @@ -0,0 +1,49 @@ +# Reference architecture: up to 10,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/10k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/10k_users.html) + +* [Footnotes](#footnotes) + +# Reference architecture: up to 10,000 users[](#reference-architecture-up-to-10000-users "Permalink") + +该页面描述了多达 10,000 个用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +> * **支持的用户(大约):** 10,000 +> * **高可用性:** True +> * **测试 RPS 速率:** API:200 RPS,网站:20 RPS,Git:20 RPS + +| Service | Nodes | 配置( [8](#footnotes) ) | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | --- | +| 亚搏体育应用程序轨道( [1](#footnotes) ) | 3 | 32 个 vCPU,28.8GB 内存 | n1-highcpu-32 | c5.9xlarge | F32s v2 | +| PostgreSQL | 3 | 4 个 vCPU,15GB 内存 | n1-standard-4 | m5.xlarge | D4s v3 | +| PgBouncer | 3 | 2 个 vCPU,1.8GB 内存 | n1-highcpu-2 | c5.large | F2s v2 | +| 吉塔利( [2](#footnotes) )( [5](#footnotes) )( [7](#footnotes) ) | X | 16 个 vCPU,60GB 内存 | n1-standard-16 | m5.4xlarge | D16s v3 | +| Redis( [3](#footnotes) )-缓存 | 3 | 4 个 vCPU,15GB 内存 | n1-standard-4 | m5.xlarge | D4s v3 | +| Redis( [3](#footnotes) )-队列/共享状态 | 3 | 4 个 vCPU,15GB 内存 | n1-standard-4 | m5.xlarge | D4s v3 | +| Redis 前哨( [3](#footnotes) )-缓存 | 3 | 1 个 vCPU,1.7GB 内存 | g1-small | t2.small | B1MS | +| Redis 前哨( [3](#footnotes) )-队列/共享状态 | 3 | 1 个 vCPU,1.7GB 内存 | g1-small | t2.small | B1MS | +| Consul | 3 | 2 个 vCPU,1.8GB 内存 | n1-highcpu-2 | c5.large | F2s v2 | +| Sidekiq | 4 | 4 个 vCPU,15GB 内存 | n1-standard-4 | m5.xlarge | D4s v3 | +| 对象存储( [4](#footnotes) ) | - | - | - | - | - | +| NFS 服务器( [5](#footnotes) )( [7](#footnotes) ) | 1 | 4 个 vCPU,3.6GB 内存 | n1-highcpu-4 | c5.xlarge | F4s v2 | +| 监控节点 | 1 | 4 个 vCPU,3.6GB 内存 | n1-highcpu-4 | c5.xlarge | F4s v2 | +| 外部负载平衡节点( [6](#footnotes) ) | 1 | 2 个 vCPU,1.8GB 内存 | n1-highcpu-2 | c5.large | F2s v2 | +| 内部负载平衡节点( [6](#footnotes) ) | 1 | 2 个 vCPU,1.8GB 内存 | n1-highcpu-2 | c5.large | F2s v2 | + +## Footnotes[](#footnotes "Permalink") + +1. 在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数量设置为 90%的可用 CPU 以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +2. Gitaly 节点的要求取决于客户数据,特别是项目数量及其规模. 对于 HA 环境,我们建议绝对最少使用两个节点,并且在支持 50,000 个或更多用户时,至少应使用四个节点. 我们还建议每个 Gitaly 节点存储的数据不得超过 5TB,并且将[`gitaly-ruby`工作者](../gitaly/index.html#gitaly-ruby)的数量设置为可用 CPU 的 20%. 根据以上建议,应结合其他节点并结合对预期数据大小和分布的审查. + +3. 推荐的 Redis 设置因架构的大小而异. 对于较小的体系结构(少于 3000 个用户),一个实例就足够了. 对于中型安装(3,000-5,000),我们建议为所有课程使用一个 Redis 集群,并且 Redis Sentinel 与 Consul 一起托管. 对于较大的体系结构(10,000 个或更多用户),我们建议分别为 Cache 类和队列和 Shared State 类运行一个单独的[Redis 群集](../redis/replication_and_failover.html#running-multiple-redis-clusters) . 我们还建议您为每个 Redis 群集分别运行 Redis Sentinel 群集. + +4. 对于 LFS,Uploads,Artifacts 等数据对象.由于性能和可用性更好,我们建议尽可能在 NFS 上使用[对象存储服务](../object_storage.html) . + +5. NFS 可以用作存储库数据(替代 Gitaly)和对象存储的替代方法,但是出于性能原因,通常不建议使用 NFS. 请注意,但是[GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)是必需的. + +6. 我们的架构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +7. 我们强烈建议为任何 Gitaly 或 NFS 节点设置 HDD 之上的 SSD 磁盘,其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS,因为这些组件的 I / O 繁重. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您正在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +8. 这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. \ No newline at end of file diff --git a/docs/426.md b/docs/426.md new file mode 100644 index 0000000000000000000000000000000000000000..b344de569b6c80c8f42285d8c1ea2d0501c96a1c --- /dev/null +++ b/docs/426.md @@ -0,0 +1,49 @@ +# Reference architecture: up to 25,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/25k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/25k_users.html) + +* [Footnotes](#footnotes) + +# Reference architecture: up to 25,000 users[](#reference-architecture-up-to-25000-users "Permalink") + +本页描述了最多 25,000 个用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +> * **支持的用户(大约):** 25,000 +> * **高可用性:** True +> * **测试 RPS 速率:** API:500 RPS,网站:50 RPS,Git:50 RPS + +| Service | Nodes | 配置( [8](#footnotes) ) | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | --- | +| 亚搏体育应用程序轨道( [1](#footnotes) ) | 5 | 32 个 vCPU,28.8GB 内存 | `n1-highcpu-32` | `c5.9xlarge` | F32s v2 | +| PostgreSQL | 3 | 8 个 vCPU,30GB 内存 | `n1-standard-8` | `m5.2xlarge` | D8s v3 | +| PgBouncer | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | F2s v2 | +| 吉塔利( [2](#footnotes) )( [5](#footnotes) )( [7](#footnotes) ) | X | 32 个 vCPU,120GB 内存 | `n1-standard-32` | `m5.8xlarge` | D32s v3 | +| Redis( [3](#footnotes) )-缓存 | 3 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | D4s v3 | +| Redis( [3](#footnotes) )-队列/共享状态 | 3 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | D4s v3 | +| Redis 前哨( [3](#footnotes) )-缓存 | 3 | 1 个 vCPU,1.7GB 内存 | `g1-small` | `t2.small` | B1MS | +| Redis 前哨( [3](#footnotes) )-队列/共享状态 | 3 | 1 个 vCPU,1.7GB 内存 | `g1-small` | `t2.small` | B1MS | +| Consul | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | F2s v2 | +| Sidekiq | 4 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | D4s v3 | +| 对象存储( [4](#footnotes) ) | - | - | - | - | - | +| NFS 服务器( [5](#footnotes) )( [7](#footnotes) ) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | +| 监控节点 | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | +| 外部负载平衡节点( [6](#footnotes) ) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | +| 内部负载平衡节点( [6](#footnotes) ) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | + +## Footnotes[](#footnotes "Permalink") + +1. 在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数量设置为 90%的可用 CPU 以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +2. Gitaly node requirements are dependent on customer data, specifically the number of projects and their sizes. We recommend two nodes as an absolute minimum for HA environments and at least four nodes should be used when supporting 50,000 or more users. We also recommend that each Gitaly node should store no more than 5TB of data and have the number of [`gitaly-ruby` workers](../gitaly/index.html#gitaly-ruby) set to 20% of available CPUs. Additional nodes should be considered in conjunction with a review of expected data size and spread based on the recommendations above. + +3. 推荐的 Redis 设置因架构的大小而异. 对于较小的体系结构(少于 3000 个用户),一个实例就足够了. 对于中型安装(3,000-5,000),我们建议为所有课程使用一个 Redis 集群,并且 Redis Sentinel 与 Consul 一起托管. 对于较大的体系结构(10,000 个或更多用户),我们建议分别为 Cache 类和队列和 Shared State 类运行一个单独的[Redis 群集](../redis/replication_and_failover.html#running-multiple-redis-clusters) . 我们还建议您为每个 Redis 群集分别运行 Redis Sentinel 群集. + +4. 对于 LFS,Uploads,Artifacts 等数据对象.由于性能和可用性更好,我们建议尽可能在 NFS 上使用[对象存储服务](../object_storage.html) . + +5. NFS 可以用作存储库数据(替代 Gitaly)和对象存储的替代方法,但是出于性能原因,通常不建议使用 NFS. 请注意,但是[GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)是必需的. + +6. 我们的架构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +7. 我们强烈建议为任何 Gitaly 或 NFS 节点设置 HDD 之上的 SSD 磁盘,其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS,因为这些组件的 I / O 繁重. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您正在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +8. 这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. \ No newline at end of file diff --git a/docs/427.md b/docs/427.md new file mode 100644 index 0000000000000000000000000000000000000000..081ef0daef2fea0cdb75348353faeb3fee6a2a01 --- /dev/null +++ b/docs/427.md @@ -0,0 +1,49 @@ +# Reference architecture: up to 50,000 users + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/50k_users.html](https://docs.gitlab.com/ee/administration/reference_architectures/50k_users.html) + +* [Footnotes](#footnotes) + +# Reference architecture: up to 50,000 users[](#reference-architecture-up-to-50000-users "Permalink") + +此页面描述了多达 50,000 个用户的 GitLab 参考架构. 有关参考架构的完整列表,请参见[可用参考架构](index.html#available-reference-architectures) . + +> * **支持的用户(大约):** 50,000 +> * **高可用性:** True +> * **测试 RPS 速率:** API:1000 RPS,网站:100 RPS,Git:100 RPS + +| Service | Nodes | 配置( [8](#footnotes) ) | GCP | AWS | Azure | +| --- | --- | --- | --- | --- | --- | +| 亚搏体育应用程序轨道( [1](#footnotes) ) | 12 | 32 个 vCPU,28.8GB 内存 | `n1-highcpu-32` | `c5.9xlarge` | F32s v2 | +| PostgreSQL | 3 | 16 个 vCPU,60GB 内存 | `n1-standard-16` | `m5.4xlarge` | D16s v3 | +| PgBouncer | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | F2s v2 | +| 吉塔利( [2](#footnotes) )( [5](#footnotes) )( [7](#footnotes) ) | X | 64 个 vCPU,240GB 内存 | `n1-standard-64` | `m5.16xlarge` | D64s v3 | +| Redis( [3](#footnotes) )-缓存 | 3 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | D4s v3 | +| Redis( [3](#footnotes) )-队列/共享状态 | 3 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | D4s v3 | +| Redis 前哨( [3](#footnotes) )-缓存 | 3 | 1 个 vCPU,1.7GB 内存 | `g1-small` | `t2.small` | B1MS | +| Redis 前哨( [3](#footnotes) )-队列/共享状态 | 3 | 1 个 vCPU,1.7GB 内存 | `g1-small` | `t2.small` | B1MS | +| Consul | 3 | 2 个 vCPU,1.8GB 内存 | `n1-highcpu-2` | `c5.large` | F2s v2 | +| Sidekiq | 4 | 4 个 vCPU,15GB 内存 | `n1-standard-4` | `m5.xlarge` | D4s v3 | +| NFS 服务器( [5](#footnotes) )( [7](#footnotes) ) | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | +| 对象存储( [4](#footnotes) ) | - | - | - | - | - | +| 监控节点 | 1 | 4 个 vCPU,3.6GB 内存 | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | +| 外部负载平衡节点( [6](#footnotes) ) | 1 | 8 个 vCPU,7.2GB 内存 | `n1-highcpu-8` | `c5.2xlarge` | F8s v2 | +| 内部负载平衡节点( [6](#footnotes) ) | 1 | 8 个 vCPU,7.2GB 内存 | `n1-highcpu-8` | `c5.2xlarge` | F8s v2 | + +## Footnotes[](#footnotes "Permalink") + +1. 在我们的体系结构中,我们使用 Puma Web 服务器运行每个 GitLab Rails 节点,并将其工作程序数量设置为 90%的可用 CPU 以及四个线程. 对于运行带有其他组件的 Rails 的节点,应该相应地降低 worker 的值,我们发现 50%达到了很好的平衡,但这取决于工作量. + +2. Gitaly node requirements are dependent on customer data, specifically the number of projects and their sizes. We recommend two nodes as an absolute minimum for HA environments and at least four nodes should be used when supporting 50,000 or more users. We also recommend that each Gitaly node should store no more than 5TB of data and have the number of [`gitaly-ruby` workers](../gitaly/index.html#gitaly-ruby) set to 20% of available CPUs. Additional nodes should be considered in conjunction with a review of expected data size and spread based on the recommendations above. + +3. 推荐的 Redis 设置因架构的大小而异. 对于较小的体系结构(少于 3000 个用户),一个实例就足够了. 对于中型安装(3,000-5,000),我们建议为所有课程使用一个 Redis 集群,并且 Redis Sentinel 与 Consul 一起托管. 对于较大的体系结构(10,000 个或更多用户),我们建议分别为 Cache 类和队列和 Shared State 类运行一个单独的[Redis 群集](../redis/replication_and_failover.html#running-multiple-redis-clusters) . 我们还建议您为每个 Redis 群集分别运行 Redis Sentinel 群集. + +4. 对于 LFS,Uploads,Artifacts 等数据对象.由于性能和可用性更好,我们建议尽可能在 NFS 上使用[对象存储服务](../object_storage.html) . + +5. NFS 可以用作存储库数据(替代 Gitaly)和对象存储的替代方法,但是出于性能原因,通常不建议使用 NFS. 请注意,但是[GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)是必需的. + +6. 我们的架构已通过[HAProxy](https://www.haproxy.org/)作为负载均衡器进行了测试和验证. 尽管也可以使用具有类似功能集的其他负载均衡器,但这些负载均衡器尚未经过验证. + +7. 我们强烈建议为任何 Gitaly 或 NFS 节点设置 HDD 之上的 SSD 磁盘,其读操作的吞吐量至少为 8000 IOPS,写操作的吞吐量至少为 2,000 IOPS,因为这些组件的 I / O 繁重. 这些 IOPS 值仅建议作为启动器使用,因为随着时间的推移,它们可能会根据环境工作负载的规模而调整得更高或更低. 如果您正在 Cloud provider 上运行环境,则可能需要参考其文档以了解如何正确配置 IOPS. + +8. 这些架构是使用 GCP 上的[Intel Xeon E5 v3(Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) CPU 平台构建和测试的. 在不同的硬件上,您可能会发现需要对 CPU 或节点数进行相应的调整,无论是较低还是较高. 有关更多信息,请在[此处](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks)找到 CPU 的[Sysbench](https://github.com/akopytov/sysbench)基准. \ No newline at end of file diff --git a/docs/428.md b/docs/428.md new file mode 100644 index 0000000000000000000000000000000000000000..ff368d89adef68064adbc5fc43251362c24b43f7 --- /dev/null +++ b/docs/428.md @@ -0,0 +1,289 @@ +# Troubleshooting a reference architecture set up + +> 原文:[https://docs.gitlab.com/ee/administration/reference_architectures/troubleshooting.html](https://docs.gitlab.com/ee/administration/reference_architectures/troubleshooting.html) + +* [Troubleshooting object storage](#troubleshooting-object-storage) + * [S3 API compatibility issues](#s3-api-compatibility-issues) + * [GitLab Pages requires NFS](#gitlab-pages-requires-nfs) + * [Incremental logging is required for CI to use object storage](#incremental-logging-is-required-for-ci-to-use-object-storage) + * [Proxy Download](#proxy-download) + * [ETag mismatch](#etag-mismatch) +* [Troubleshooting Redis](#troubleshooting-redis) +* [Troubleshooting Gitaly](#troubleshooting-gitaly) + * [Checking versions when using standalone Gitaly nodes](#checking-versions-when-using-standalone-gitaly-nodes) + * [`gitaly-debug`](#gitaly-debug) + * [Commits, pushes, and clones return a 401](#commits-pushes-and-clones-return-a-401) + * [Client side gRPC logs](#client-side-grpc-logs) + * [Observing `gitaly-ruby` traffic](#observing-gitaly-ruby-traffic) + * [Repository changes fail with a `401 Unauthorized` error](#repository-changes-fail-with-a-401-unauthorized-error) + * [Command line tools cannot connect to Gitaly](#command-line-tools-cannot-connect-to-gitaly) + * [Gitaly not listening on new address after reconfiguring](#gitaly-not-listening-on-new-address-after-reconfiguring) + * [Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly node](#permission-denied-errors-appearing-in-gitaly-logs-when-accessing-repositories-from-a-standalone-gitaly-node) +* [Troubleshooting the GitLab Rails application](#troubleshooting-the-gitlab-rails-application) +* [Troubleshooting Monitoring](#troubleshooting-monitoring) + +# Troubleshooting a reference architecture set up[](#troubleshooting-a-reference-architecture-set-up "Permalink") + +如果您遵循一种[参考体系结构,](index.html#reference-architectures)则此页面可作为故障排除文档. + +## Troubleshooting object storage[](#troubleshooting-object-storage "Permalink") + +### S3 API compatibility issues[](#s3-api-compatibility-issues "Permalink") + +并非所有 S3 提供程序[都](../../raketasks/backup_restore.html#other-s3-providers)与 GitLab 使用的 Fog 库[完全兼容](../../raketasks/backup_restore.html#other-s3-providers) . 症状包括: + +``` +411 Length Required +``` + +### GitLab Pages requires NFS[](#gitlab-pages-requires-nfs "Permalink") + +如果您打算使用[GitLab 页面](../../user/project/pages/index.html) ,则当前需要[NFS](../high_availability/nfs.html) . 有[工作正在进行中](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)去除这种依赖性. 将来,GitLab 页面可能会使用[对象存储](https://gitlab.com/gitlab-org/gitlab/-/issues/208135) . + +对磁盘存储的依赖性还阻止了使用[GitLab Helm 图表](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/37)部署 Pages. + +### Incremental logging is required for CI to use object storage[](#incremental-logging-is-required-for-ci-to-use-object-storage "Permalink") + +如果将 GitLab 配置为将对象存储用于 CI 日志和工件,则[还必须启用增量日志记录](../job_logs.html#new-incremental-logging-architecture) . + +### Proxy Download[](#proxy-download "Permalink") + +对象存储的许多使用情况都允许将客户端流量重定向到对象存储后端,例如当 Git 客户端通过 LFS 请求大文件时或在下载 CI 工件和日志时. + +当文件存储在本地块存储或 NFS 上时,GitLab 必须充当代理. 对于对象存储,GitLab 的默认行为是重定向到对象存储设备,而不是代理请求. + +`proxy_download`设置控制此行为:默认设置通常为`false` . 在每个用例的文档中对此进行验证. 将其设置为`true`可使 GitLab 代理文件而不是重定向. + +当不代理文件时,GitLab 将返回[HTTP 302 重定向,该重定向带有预先签名的有时间限制的对象存储 URL](https://gitlab.com/gitlab-org/gitlab/-/issues/32117#note_218532298) . 这可能会导致以下一些问题: + +* 如果 GitLab 使用非安全的 HTTP 访问对象存储,则客户端可能会生成`https->http`降级错误,并拒绝处理重定向. 解决方案是让 GitLab 使用 HTTPS. 例如,LFS 将产生此错误: + + ``` + LFS: lfsapi/client: refusing insecure redirect, https->http + ``` + +* 客户端将需要信任颁发对象存储证书的证书颁发机构,或者可能返回常见的 TLS 错误,例如: + + ``` + x509: certificate signed by unknown authority + ``` + +* 客户端将需要网络访问对象存储. 如果没有此访问权限,则可能导致的错误包括: + + ``` + Received status code 403 from server: Forbidden + ``` + +### ETag mismatch[](#etag-mismatch "Permalink") + +Using the default GitLab settings, some object storage back-ends such as [MinIO](https://gitlab.com/gitlab-org/gitlab/-/issues/23188) and [Alibaba](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564) might generate `ETag mismatch` errors. + +使用 GitLab 直接上传时, [MinIO](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564#note_244497658)的[解决方法](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564#note_244497658)是在服务器上使用`--compat`参数. + +我们正在致力于 GitLab 组件 Workhorse 的修复,同时,也正在尝试一种解决方法,以[允许禁用 ETag 验证](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18175) . + +## Troubleshooting Redis[](#troubleshooting-redis "Permalink") + +如果应用程序节点无法连接到 Redis 节点,请检查您的防火墙规则,并确保 Redis 可以接受端口`6379`下的 TCP 连接. + +## Troubleshooting Gitaly[](#troubleshooting-gitaly "Permalink") + +### Checking versions when using standalone Gitaly nodes[](#checking-versions-when-using-standalone-gitaly-nodes "Permalink") + +使用独立的 Gitaly 节点时,必须确保它们与 GitLab 的版本相同,以确保完全兼容. 检查您的 GitLab 实例上的**管理区域> Gitaly 服务器** ,并确认所有 Gitaly 服务器都是`Up to date` . + +[![Gitaly standalone software versions diagram](img/ba685b05a8bb7c09fe3b58048ac4884e.png)](../gitaly/img/gitlab_gitaly_version_mismatch_v12_4.png) + +### `gitaly-debug`[](#gitaly-debug "Permalink") + +`gitaly-debug`命令提供用于" Gitaly"和" Git"性能的"生产调试"工具. 它旨在帮助生产工程师和支持工程师调查 Gitaly 性能问题. + +如果您使用的是 GitLab 11.6 或更高版本,则此工具应已安装在您的 GitLab / Gitaly 服务器上,位于`/opt/gitlab/embedded/bin/gitaly-debug` . 如果要研究旧版本的 GitLab,可以离线编译此工具,然后将可执行文件复制到服务器: + +``` +git clone https://gitlab.com/gitlab-org/gitaly.git +cd cmd/gitaly-debug +GOOS=linux GOARCH=amd64 go build -o gitaly-debug +``` + +要查看`gitaly-debug`的帮助页面以`gitaly-debug`受支持的子命令列表,请运行: + +``` +gitaly-debug -h +``` + +### Commits, pushes, and clones return a 401[](#commits-pushes-and-clones-return-a-401 "Permalink") + +``` +remote: GitLab: 401 Unauthorized +``` + +您将需要将`gitlab-secrets.json`文件与 GitLab 应用程序节点同步. + +### Client side gRPC logs[](#client-side-grpc-logs "Permalink") + +Gitaly 使用[gRPC](https://grpc.io/) RPC 框架. Ruby gRPC 客户端具有自己的日志文件,当您看到 Gitaly 错误时,该文件可能包含有用的信息. 您可以使用`GRPC_LOG_LEVEL`环境变量控制 gRPC 客户端的日志级别. 默认级别为`WARN` . + +您可以使用以下命令运行 gRPC 跟踪: + +``` +sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check +``` + +### Observing `gitaly-ruby` traffic[](#observing-gitaly-ruby-traffic "Permalink") + +[`gitaly-ruby`](../gitaly/index.html#gitaly-ruby)是[`gitaly-ruby`](../gitaly/index.html#gitaly-ruby)的内部实现细节,因此,对`gitaly-ruby`流程内部发生的情况`gitaly-ruby` . + +如果已设置 Prometheus 来抓取 Gitaly 进程,则可以通过查询`grpc_client_handled_total`来`grpc_client_handled_total` `gitaly-ruby`各个 RPC 的请求率和错误代码. 严格来说,此度量标准并未区分`gitaly-ruby`和其他 RPC,但实际上(自 GitLab 11.9 起),Gitaly 本身进行的所有 gRPC 调用都是从 Gitaly 主过程到其`gitaly-ruby`边车之一的内部调用. + +假设您的`grpc_client_handled_total`计数器仅观察到 Gitaly,以下查询将显示 RPC 在内部(最有可能)实现为对`gitaly-ruby`调用: + +``` +sum(rate(grpc_client_handled_total[5m])) by (grpc_method) > 0 +``` + +### Repository changes fail with a `401 Unauthorized` error[](#repository-changes-fail-with-a-401-unauthorized-error "Permalink") + +If you’re running Gitaly on its own server and notice that users can successfully clone and fetch repositories (via both SSH and HTTPS), but can’t push to them or make changes to the repository in the web UI without getting a `401 Unauthorized` message, then it’s possible Gitaly is failing to authenticate with the other nodes due to having the wrong secrets file. + +确认以下所有内容均正确: + +* 当任何用户向该 Gitaly 节点上的任何存储库执行`git push` ,它都会失败,并显示以下错误(请注意`401 Unauthorized` ): + + ``` + remote: GitLab: 401 Unauthorized + To + ! [remote rejected] branch-name -> branch-name (pre-receive hook declined) + error: failed to push some refs to '' + ``` + +* 当任何用户使用 GitLab UI 从存储库添加或修改文件时,该文件都会立即失败,并显示红色`401 Unauthorized`横幅. +* 创建一个新项目并[使用 README 对其进行初始化会](../../gitlab-basics/create-project.html#blank-projects)成功创建该项目,但不会创建 README. +* [将日志拖到](https://docs.gitlab.com/omnibus/settings/logs.html)应用程序节点上并重现错误时,到达`/api/v4/internal/allowed`端点时会出现`401`错误: + + ``` + # api_json.log + { + "time": "2019-07-18T00:30:14.967Z", + "severity": "INFO", + "duration": 0.57, + "db": 0, + "view": 0.57, + "status": 401, + "method": "POST", + "path": "\/api\/v4\/internal\/allowed", + "params": [ + { + "key": "action", + "value": "git-receive-pack" + }, + { + "key": "changes", + "value": "REDACTED" + }, + { + "key": "gl_repository", + "value": "REDACTED" + }, + { + "key": "project", + "value": "\/path\/to\/project.git" + }, + { + "key": "protocol", + "value": "web" + }, + { + "key": "env", + "value": "{\"GIT_ALTERNATE_OBJECT_DIRECTORIES\":[],\"GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE\":[],\"GIT_OBJECT_DIRECTORY\":null,\"GIT_OBJECT_DIRECTORY_RELATIVE\":null}" + }, + { + "key": "user_id", + "value": "2" + }, + { + "key": "secret_token", + "value": "[FILTERED]" + } + ], + "host": "gitlab.example.com", + "ip": "REDACTED", + "ua": "Ruby", + "route": "\/api\/:version\/internal\/allowed", + "queue_duration": 4.24, + "gitaly_calls": 0, + "gitaly_duration": 0, + "correlation_id": "XPUZqTukaP3" + } + + # nginx_access.log + [IP] - - [18/Jul/2019:00:30:14 +0000] "POST /api/v4/internal/allowed HTTP/1.1" 401 30 "" "Ruby" + ``` + +要解决此问题,请确认 Gitaly 节点上的 gitlab `gitlab-secrets.json`文件与所有其他节点上的 gitlab `gitlab-secrets.json`文件匹配. 如果不匹配,请更新 Gitaly 节点上的 secrets 文件以使其与其他文件匹配,然后[重新配置该节点](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +### Command line tools cannot connect to Gitaly[](#command-line-tools-cannot-connect-to-gitaly "Permalink") + +如果使用命令行(CLI)工具连接到 Gitaly 节点时遇到问题,并且某些操作导致出现`14: Connect Failed`错误消息,则表明 gRPC 无法到达您的 Gitaly 节点. + +确认您可以通过 TCP 到达 Gitaly: + +``` +sudo gitlab-rake gitlab:tcp_check[GITALY_SERVER_IP,GITALY_LISTEN_PORT] +``` + +如果 TCP 连接失败,请检查您的网络设置和防火墙规则. 如果 TCP 连接成功,则您的网络和防火墙规则正确. + +如果您在命令行环境(例如 Bash)中使用代理服务器,则这些代理服务器可能会干扰您的 gRPC 通信. + +如果使用 Bash 或兼容的命令行环境,请运行以下命令来确定是否配置了代理服务器: + +``` +echo $http_proxy +echo $https_proxy +``` + +如果这些变量中的任何一个都有值,则您的 Gitaly CLI 连接可能正在通过无法连接到 Gitaly 的代理进行路由. + +要删除代理设置,请运行以下命令(取决于哪些变量具有值): + +``` +unset http_proxy +unset https_proxy +``` + +### Gitaly not listening on new address after reconfiguring[](#gitaly-not-listening-on-new-address-after-reconfiguring "Permalink") + +当更新`gitaly['listen_addr']`或`gitaly['prometheus_listen_addr']`值时,Gitaly 可能会在`sudo gitlab-ctl reconfigure`后继续侦听旧地址. + +发生这种情况时,执行`sudo gitlab-ctl restart`将解决此问题. 解决[此问题](https://gitlab.com/gitlab-org/gitaly/-/issues/2521)后,将不再需要[此操作](https://gitlab.com/gitlab-org/gitaly/-/issues/2521) . + +### Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly node[](#permission-denied-errors-appearing-in-gitaly-logs-when-accessing-repositories-from-a-standalone-gitaly-node "Permalink") + +如果即使文件许可权正确也发生此错误,则 Gitaly 节点很可能正在发生[时钟漂移](https://en.wikipedia.org/wiki/Clock_drift) . + +请确保 GitLab 和 Gitaly 节点已同步,并在可能的情况下使用 NTP 时间服务器使其保持同步. + +## Troubleshooting the GitLab Rails application[](#troubleshooting-the-gitlab-rails-application "Permalink") + +* `mount: wrong fs type, bad option, bad superblock on` + +您尚未安装必要的 NFS 客户端实用程序. 请参阅上面的步骤 1. + +* `mount: mount point /var/opt/gitlab/... does not exist` + +NFS 服务器上不存在此特定目录. 确保共享已导出并且存在于 NFS 服务器上,然后尝试重新安装. + +## Troubleshooting Monitoring[](#troubleshooting-monitoring "Permalink") + +如果监视节点未接收到任何数据,请检查导出器是否正在捕获数据. + +``` +curl http[s]://localhost:/metric +``` + +or + +``` +curl http[s]://localhost:/-/metric +``` \ No newline at end of file diff --git a/docs/429.md b/docs/429.md new file mode 100644 index 0000000000000000000000000000000000000000..84f8ba2760426b3cd680b6a3f0e60b94c2ba71aa --- /dev/null +++ b/docs/429.md @@ -0,0 +1,205 @@ +# Working with the bundled Consul service + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/consul.html](https://docs.gitlab.com/ee/administration/high_availability/consul.html) + +* [Prerequisites](#prerequisites) +* [Configuring the Consul nodes](#configuring-the-consul-nodes) + * [Consul checkpoint](#consul-checkpoint) +* [Operations](#operations) + * [Checking cluster membership](#checking-cluster-membership) + * [Restarting the server cluster](#restarting-the-server-cluster) +* [Upgrades for bundled Consul](#upgrades-for-bundled-consul) +* [Troubleshooting](#troubleshooting) + * [Consul server agents unable to communicate](#consul-server-agents-unable-to-communicate) + * [Consul agents do not start - Multiple private IPs](#consul-agents-do-not-start---multiple-private-ips) + * [Outage recovery](#outage-recovery) + * [Recreate from scratch](#recreate-from-scratch) + * [Recover a failed cluster](#recover-a-failed-cluster) + +# Working with the bundled Consul service[](#working-with-the-bundled-consul-service-premium-only "Permalink") + +作为其高可用性堆栈的一部分,GitLab Premium 包含可通过`/etc/gitlab/gitlab.rb`管理的捆绑版本的[Consul](https://www.consul.io/) . Consul 是服务网络解决方案. 对于[GitLab Architecture](../../development/architecture.html) ,支持 Consul 利用来配置: + +1. [Monitoring in Scaled and Highly Available environments](monitoring_node.html) +2. [PostgreSQL High Availability with Omnibus](../postgresql/replication_and_failover.html) + +Consul 群集由多个服务器代理以及在其他需要与 Consul 群集通信的节点上运行的客户端代理组成. + +## Prerequisites[](#prerequisites "Permalink") + +首先,请确保**在每个节点上** [下载/安装](https://about.gitlab.com/install/) Omnibus GitLab. + +选择一种安装方法,然后确保完成以下步骤: + +1. 安装和配置必要的依赖项. +2. 添加 GitLab 软件包存储库并安装软件包. + +安装 GitLab 软件包时,请勿提供`EXTERNAL_URL`值. + +## Configuring the Consul nodes[](#configuring-the-consul-nodes "Permalink") + +在每个 Consul 节点上执行以下操作: + +1. 在执行下一步之前,请确保为[`CONSUL_SERVER_NODES`](../postgresql/replication_and_failover.html#consul-information)收集[`CONSUL_SERVER_NODES`](../postgresql/replication_and_failover.html#consul-information) ,它们是 Consul 服务器节点的 IP 地址或 DNS 记录. + +2. 编辑`/etc/gitlab/gitlab.rb`替换`/etc/gitlab/gitlab.rb` `# START user configuration`部分中记录的值: + + ``` + # Disable all components except Consul + roles ['consul_role'] + + # START user configuration + # Replace placeholders: + # + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses gathered for CONSUL_SERVER_NODES + consul['configuration'] = { + server: true, + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z) + } + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + # + # END user configuration + ``` + + > `consul_role`在 GitLab 10.3 中引入 + +3. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +### Consul checkpoint[](#consul-checkpoint "Permalink") + +在继续之前,请确保 Consul 配置正确. 运行以下命令以验证所有服务器节点都在通信: + +``` +/opt/gitlab/embedded/bin/consul members +``` + +输出应类似于: + +``` +Node Address Status Type Build Protocol DC +CONSUL_NODE_ONE XXX.XXX.XXX.YYY:8301 alive server 0.9.2 2 gitlab_consul +CONSUL_NODE_TWO XXX.XXX.XXX.YYY:8301 alive server 0.9.2 2 gitlab_consul +CONSUL_NODE_THREE XXX.XXX.XXX.YYY:8301 alive server 0.9.2 2 gitlab_consul +``` + +如果任何一个节点都不`alive`或三个节点中的任何一个都不`alive` ,请在继续操作之前检查" [疑难解答"部分](#troubleshooting) . + +## Operations[](#operations "Permalink") + +### Checking cluster membership[](#checking-cluster-membership "Permalink") + +要查看哪些节点是集群的一部分,请在集群中的任何成员上运行以下命令 + +``` +$ /opt/gitlab/embedded/bin/consul members +Node Address Status Type Build Protocol DC +consul-b XX.XX.X.Y:8301 alive server 0.9.0 2 gitlab_consul +consul-c XX.XX.X.Y:8301 alive server 0.9.0 2 gitlab_consul +consul-c XX.XX.X.Y:8301 alive server 0.9.0 2 gitlab_consul +db-a XX.XX.X.Y:8301 alive client 0.9.0 2 gitlab_consul +db-b XX.XX.X.Y:8301 alive client 0.9.0 2 gitlab_consul +``` + +Ideally all nodes will have a `Status` of `alive`. + +### Restarting the server cluster[](#restarting-the-server-cluster "Permalink") + +**注意:**本部分仅适用于服务器代理. 在需要时重新启动客户端代理是安全的. + +如果有必要重新启动服务器群集,则以受控方式进行此操作很重要,以保持仲裁. 如果仲裁丢失,则需要遵循 Consul [中断恢复](#outage-recovery)过程来恢复群集. + +为了安全起见,建议您一次仅重新启动一个服务器代理,以确保群集保持完整. + +对于较大的群集,可以一次重新启动多个代理. 请参阅[领事共识文档,](https://www.consul.io/docs/internals/consensus.html#deployment-table)以了解可以容忍多少次失败. 这是它可以承受的同时重启的次数. + +## Upgrades for bundled Consul[](#upgrades-for-bundled-consul "Permalink") + +运行 GitLab 捆绑的 Consul 的节点应为: + +* 升级 Omnibus GitLab 软件包之前,健康集群的成员. +* 一次升级一个节点. + +**注意:**从任何 Consul 节点运行`curl http://127.0.0.1:8500/v1/health/state/critical` ,将识别群集中的现有运行状况问题. 如果群集运行状况良好,该命令将返回一个空数组. + +领事群集使用筏协议进行通信. 如果当前领导者下线,则需要进行领导者选举. 必须存在一个领导者节点,以促进整个集群之间的同步. 如果同时有太多节点脱机,则由于[共识破裂](https://www.consul.io/docs/internals/consensus.html) ,群集将失去仲裁且不会选举领导者. + +如果群集在升级后无法恢复,请参考[故障排除部分](#troubleshooting) . [中断恢复](#outage-recovery)可能特别有意义. + +**注意:** GitLab 仅使用 Consul 来存储易于重新生成的瞬态数据. 如果捆绑包的 Consul 除了 GitLab 本身以外没有被其他进程使用,那么[从头开始重建集群](#recreate-from-scratch)就可以了. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Consul server agents unable to communicate[](#consul-server-agents-unable-to-communicate "Permalink") + +默认情况下,服务器代理将尝试[绑定](https://www.consul.io/docs/agent/options.html#_bind)到" 0.0.0.0",但是它们将通告节点上的第一个私有 IP 地址,以供其他代理与其通信. 如果其他节点无法与此地址上的节点通信,则群集将处于故障状态. + +如果遇到此问题,您将在`gitlab-ctl tail consul`输出中看到类似以下的消息: + +``` +2017-09-25_19:53:39.90821 2017/09/25 19:53:39 [WARN] raft: no known peers, aborting election +2017-09-25_19:53:41.74356 2017/09/25 19:53:41 [ERR] agent: failed to sync remote state: No cluster leader +``` + +要解决此问题: + +1. 在每个其他节点都可以到达的节点上选择一个地址. +2. 更新您的`/etc/gitlab/gitlab.rb` + + ``` + consul['configuration'] = { + ... + bind_addr: 'IP ADDRESS' + } + ``` + +3. Run `gitlab-ctl reconfigure` + +如果仍然看到错误,则可能必须[删除 Consul 数据库并](#recreate-from-scratch)在受影响的节点上[重新初始化](#recreate-from-scratch) . + +### Consul agents do not start - Multiple private IPs[](#consul-agents-do-not-start---multiple-private-ips "Permalink") + +如果一个节点具有多个专用 IP,则代理会混淆要播发哪个专用地址,然后在启动时立即退出. + +如果遇到此问题,您将在`gitlab-ctl tail consul`输出中看到类似以下的消息: + +``` +2017-11-09_17:41:45.52876 ==> Starting Consul agent... +2017-11-09_17:41:45.53057 ==> Error creating agent: Failed to get advertise address: Multiple private IPs found. Please configure one. +``` + +要解决此问题: + +1. 在该节点上选择一个地址,所有其他节点都可以通过该地址到达该节点. +2. 更新您的`/etc/gitlab/gitlab.rb` + + ``` + consul['configuration'] = { + ... + bind_addr: 'IP ADDRESS' + } + ``` + +3. Run `gitlab-ctl reconfigure` + +### Outage recovery[](#outage-recovery "Permalink") + +如果您在群集中丢失了足够的服务器代理以破坏仲裁,则该群集将被视为失败,并且如果没有手动干预,它将无法运行. + +#### Recreate from scratch[](#recreate-from-scratch "Permalink") + +默认情况下,GitLab 不会在 Consul 群集中存储任何无法重新创建的内容. 删除 Consul 数据库并重新初始化 + +``` +gitlab-ctl stop consul +rm -rf /var/opt/gitlab/consul/data +gitlab-ctl start consul +``` + +此后,群集应开始备份,并且服务器代理重新加入. 之后不久,客户代理也应重新加入. + +#### Recover a failed cluster[](#recover-a-failed-cluster "Permalink") + +如果您已利用 Consul 来存储其他数据,并想还原发生故障的群集,请按照[Consul 指南](https://learn.hashicorp.com/consul/day-2-operations/outage)来恢复发生故障的群集. \ No newline at end of file diff --git a/docs/430.md b/docs/430.md new file mode 100644 index 0000000000000000000000000000000000000000..fa72dca9827f5f429c4bf890aa9bdc8947fd425a --- /dev/null +++ b/docs/430.md @@ -0,0 +1,31 @@ +# Configuring PostgreSQL for scaling + +> 原文:[https://docs.gitlab.com/ee/administration/postgresql/](https://docs.gitlab.com/ee/administration/postgresql/) + +* [PostgreSQL replication and failover with Omnibus GitLab](#postgresql-replication-and-failover-with-omnibus-gitlab-premium-only) +* [Standalone PostgreSQL using Omnibus GitLab](#standalone-postgresql-using-omnibus-gitlab-core-only) +* [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance-core-only) + +# Configuring PostgreSQL for scaling[](#configuring-postgresql-for-scaling "Permalink") + +在本节中,将指导您配置 PostgreSQL 数据库,以在我们的[可扩展和高度可用的设置](../reference_architectures/index.html)之一中与 GitLab 一起使用. 基本上有三种设置可供选择. + +## PostgreSQL replication and failover with Omnibus GitLab[](#postgresql-replication-and-failover-with-omnibus-gitlab-premium-only "Permalink") + +此设置适用于使用[Omnibus GitLab **企业版** (EE)软件包](https://about.gitlab.com/install/?version=ee)安装 GitLab 的情况. + +所有必需的工具(如 PostgreSQL,PgBouncer,Repmgr)都捆绑在软件包中,因此您可以用它来设置整个 PostgreSQL 基础结构(主数据库,副本数据库). + +[> Read how to set up PostgreSQL replication and failover using Omnibus GitLab](replication_and_failover.html) + +## Standalone PostgreSQL using Omnibus GitLab[](#standalone-postgresql-using-omnibus-gitlab-core-only "Permalink") + +此设置适用于您安装[Omnibus GitLab 软件包](https://about.gitlab.com/install/) (CE 或 EE)时使用仅启用了服务的捆绑 PostgreSQL 的情况. + +[> Read how to set up a standalone PostgreSQL instance using Omnibus GitLab](standalone.html) + +## Provide your own PostgreSQL instance[](#provide-your-own-postgresql-instance-core-only "Permalink") + +此设置适用于使用[Omnibus GitLab 软件包](https://about.gitlab.com/install/) (CE 或 EE)安装 GitLab 或[从源代码](../../install/installation.html)安装 GitLab 的情况,但您想使用自己的外部 PostgreSQL 服务器. + +[> Read how to set up an external PostgreSQL instance](external.html) \ No newline at end of file diff --git a/docs/431.md b/docs/431.md new file mode 100644 index 0000000000000000000000000000000000000000..0bb165ea01025aadbad45172214762e9eaab4a39 --- /dev/null +++ b/docs/431.md @@ -0,0 +1,163 @@ +# Configuring GitLab application (Rails) + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/gitlab.html](https://docs.gitlab.com/ee/administration/high_availability/gitlab.html) + +* [First GitLab application server](#first-gitlab-application-server) +* [Extra configuration for additional GitLab application servers](#extra-configuration-for-additional-gitlab-application-servers) +* [Enable Monitoring](#enable-monitoring) +* [Troubleshooting](#troubleshooting) +* [Upgrading GitLab HA](#upgrading-gitlab-ha) + +# Configuring GitLab application (Rails)[](#configuring-gitlab-application-rails "Permalink") + +本节介绍如何配置 GitLab 应用程序(Rails)组件. + +**注意:**底部附近还有一些其他配置,用于其他 GitLab 应用程序服务器. 在继续安装 GitLab 之前,阅读并理解这些其他步骤非常重要.**注意:**建议尽可能通过[NFS](nfs.html)使用[Gitaly 的](gitaly.html) [Cloud Object Storage 服务](object_storage.html) ,以提高性能. + +1. 如有必要,请使用以下命令安装 NFS 客户端实用程序软件包: + + ``` + # Ubuntu/Debian + apt-get install nfs-common + + # CentOS/Red Hat + yum install nfs-utils nfs-utils-lib + ``` + +2. 在`/etc/fstab`指定必要的 NFS 导出. `/etc/fstab`的确切内容取决于您选择配置 NFS 服务器的方式. 有关示例和各种选项,请参见[NFS 文档](nfs.html#nfs-client-mount-options) . + +3. 创建共享目录. 这些可能会有所不同,具体取决于您的 NFS 安装位置. + + ``` + mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data + ``` + +4. 使用[GitLab 下载中的](https://about.gitlab.com/install/) **步骤 1 和 2**下载/安装 Omnibus GitLab. 不要完成下载页面上的其他步骤. +5. 创建/编辑`/etc/gitlab/gitlab.rb`并使用以下配置. 确保更改`external_url`以匹配最终的 GitLab 前端 URL. 根据您的 NFS 配置,您可能需要更改某些 GitLab 数据位置. 有关各种情况的`/etc/gitlab/gitlab.rb`配置值,请参见[NFS 文档](nfs.html) . 下面的示例假定您已在默认数据位置中添加了 NFS 挂载. 此外,给出的 UID 和 GID 只是示例,您应该使用首选值进行配置. + + ``` + external_url 'https://gitlab.example.com' + + # Prevent GitLab from starting if NFS data mounts are not available + high_availability['mountpoint'] = '/var/opt/gitlab/git-data' + + # Disable components that will not be on the GitLab application server + roles ['application_role'] + nginx['enable'] = true + + # PostgreSQL connection details + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['db_host'] = '10.1.0.5' # IP/hostname of database server + gitlab_rails['db_password'] = 'DB password' + + # Redis connection details + gitlab_rails['redis_port'] = '6379' + gitlab_rails['redis_host'] = '10.1.0.6' # IP/hostname of Redis server + gitlab_rails['redis_password'] = 'Redis Password' + + # Ensure UIDs and GIDs match between servers for permissions via NFS + user['uid'] = 9000 + user['gid'] = 9000 + web_server['uid'] = 9001 + web_server['gid'] = 9001 + registry['uid'] = 9002 + registry['gid'] = 9002 + ``` + +6. [Enable monitoring](#enable-monitoring) + + **注意:**为了保持 HA 群集之间链接的统一性,第一个应用程序服务器上的`external_url`以及其他应用程序服务器应指向用户将用来访问 GitLab 的外部 URL. 在典型的 HA 设置中,这将是负载平衡器的 URL,它将把流量路由到 HA 群集中的所有 GitLab 应用程序服务器.**注意:**如上例所示,当在`external_url`指定`https`时,GitLab 会假定您在`/etc/gitlab/ssl/`具有 SSL 证书. 如果没有证书,NGINX 将无法启动. 有关更多信息,请参见[NGINX 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) .**注意:**最好在初始重新配置 GitLab 之前设置`uid`和`gid` . 如果在初始重新配置后设置,Omnibus 将不会递归`chown`目录. + +## First GitLab application server[](#first-gitlab-application-server "Permalink") + +在第一台应用程序服务器上,运行: + +``` +sudo gitlab-ctl reconfigure +``` + +这应该编译配置并初始化数据库. 在下一步之前,不要在其他应用程序服务器上运行此命令. + +## Extra configuration for additional GitLab application servers[](#extra-configuration-for-additional-gitlab-application-servers "Permalink") + +其他的 GitLab 服务器( **在**第一个 GitLab 服务器**之后**配置的服务器)需要一些额外的配置. + +1. 配置共享机密. 这些值可以从`/etc/gitlab/gitlab-secrets.json`的主要 GitLab 服务器`/etc/gitlab/gitlab-secrets.json` . **在**运行上述步骤中的第一次`reconfigure` **之前,**将此文件复制到辅助服务器. + + ``` + gitlab_shell['secret_token'] = 'fbfb19c355066a9afb030992231c4a363357f77345edd0f2e772359e5be59b02538e1fa6cae8f93f7d23355341cea2b93600dab6d6c3edcdced558fc6d739860' + gitlab_rails['otp_key_base'] = 'b719fe119132c7810908bba18315259ed12888d4f5ee5430c42a776d840a396799b0a5ef0a801348c8a357f07aa72bbd58e25a84b8f247a25c72f539c7a6c5fa' + gitlab_rails['secret_key_base'] = '6e657410d57c71b4fc3ed0d694e7842b1895a8b401d812c17fe61caf95b48a6d703cb53c112bc01ebd197a85da81b18e29682040e99b4f26594772a4a2c98c6d' + gitlab_rails['db_key_base'] = 'bf2e47b68d6cafaef1d767e628b619365becf27571e10f196f98dc85e7771042b9203199d39aff91fcb6837c8ed83f2a912b278da50999bb11a2fbc0fba52964' + ``` + +2. 运行`touch /etc/gitlab/skip-auto-reconfigure`以防止数据库迁移在升级时运行. 只有主 GitLab 应用程序服务器才能处理迁移. + +3. **推荐**配置主机密钥. 将主应用程序服务器上`/etc/ssh/`的内容(私钥和公钥)复制到所有辅助服务器上的`/etc/ssh` . 这样可以防止访问负载平衡器后面的高可用性群集中的服务器时出现虚假的中间人攻击警报. + +4. 运行`sudo gitlab-ctl reconfigure`来编译配置. + +**注意:**发生更新并执行数据库迁移后,您将需要重新启动 GitLab 应用程序节点. + +## Enable Monitoring[](#enable-monitoring "Permalink") + +在 GitLab 12.0 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) . + +如果启用了监视,则必须在**所有** GitLab 服务器上将其启用. + +1. Make sure to collect [`CONSUL_SERVER_NODES`](../postgresql/replication_and_failover.html#consul-information), which are the IP addresses or DNS records of the Consul server nodes, for the next step. Note they are presented as `Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z` + +2. 创建/编辑`/etc/gitlab/gitlab.rb`并添加以下配置: + + ``` + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Replace placeholders + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses of the Consul server nodes + consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' + sidekiq['listen_address'] = "0.0.0.0" + puma['listen'] = '0.0.0.0' + + # Add the monitoring node's IP address to the monitoring list that allows it to + # scrape the NGINX metrics. Replace placeholder `monitoring.gitlab.example.com` with + # the address and/or subnets gathered from the monitoring node(s). + gitlab_rails['monitoring_whitelist'] = ['monitoring.gitlab.example.com', '127.0.0.0/8'] + nginx['status']['options']['allow'] = ['monitoring.gitlab.example.com', '127.0.0.0/8'] + ``` + +3. 运行`sudo gitlab-ctl reconfigure`来编译配置. + + **警告:**如果运行 Unicorn,则在`gitlab.rb`更改`unicorn['listen']`并运行`sudo gitlab-ctl reconfigure`后,收到`HUP`后,Unicorn 可能需要较长的时间才能完成重新加载. 有关更多信息,请参见[问题](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4401) . + +## Troubleshooting[](#troubleshooting "Permalink") + +* `mount: wrong fs type, bad option, bad superblock on` + +您尚未安装必要的 NFS 客户端实用程序. 请参阅上面的步骤 1. + +* `mount: mount point /var/opt/gitlab/... does not exist` + +NFS 服务器上不存在此特定目录. 确保共享已导出并且存在于 NFS 服务器上,然后尝试重新安装. + +* * * + +## Upgrading GitLab HA[](#upgrading-gitlab-ha "Permalink") + +可以在不停机的情况下升级 GitLab HA 安装,但是必须仔细协调升级过程,以免发生故障. 有关更多详细信息,请参见[Omnibus GitLab 多节点升级文档](https://docs.gitlab.com/omnibus/update/) . + +阅读更多有关高可用性配置的信息: + +1. [Configure the database](../postgresql/replication_and_failover.html) +2. [Configure Redis](redis.html) +3. [Configure NFS](nfs.html) +4. [Configure the load balancers](load_balancer.html) \ No newline at end of file diff --git a/docs/432.md b/docs/432.md new file mode 100644 index 0000000000000000000000000000000000000000..439cd599fb7b887dd522b5ca26294cbac0f60797 --- /dev/null +++ b/docs/432.md @@ -0,0 +1,91 @@ +# Load Balancer for multi-node GitLab + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/load_balancer.html](https://docs.gitlab.com/ee/administration/high_availability/load_balancer.html) + +* [SSL](#ssl) + * [Application nodes terminate SSL](#application-nodes-terminate-ssl) + * [Load Balancer(s) terminate SSL without backend SSL](#load-balancers-terminate-ssl-without-backend-ssl) + * [Load Balancer(s) terminate SSL with backend SSL](#load-balancers-terminate-ssl-with-backend-ssl) +* [Ports](#ports) + * [Basic ports](#basic-ports) + * [GitLab Pages Ports](#gitlab-pages-ports) + * [Alternate SSH Port](#alternate-ssh-port) +* [Readiness check](#readiness-check) + +# Load Balancer for multi-node GitLab[](#load-balancer-for-multi-node-gitlab "Permalink") + +在多节点 GitLab 配置中,您将需要一个负载平衡器才能将流量路由到应用程序服务器. 有关使用负载均衡器或进行确切配置的细节超出了 GitLab 文档的范围. 我们希望,如果您要管理像 GitLab 这样的 HA 系统,那么已经选择了负载均衡器. 一些示例包括 HAProxy(开源),F5 Big-IP LTM 和 Citrix Net Scaler. 本文档将概述需要在 GitLab 上使用哪些端口和协议. + +## SSL[](#ssl "Permalink") + +您将如何在多节点环境中处理 SSL? 有几种不同的选择: + +* 每个应用程序节点终止 SSL +* 负载平衡器终止 SSL,并且负载平衡器与应用程序节点之间的通信不安全 +* 负载平衡器终止 SSL,并且负载平衡器与应用程序节点之间的通信是*安全*的 + +### Application nodes terminate SSL[](#application-nodes-terminate-ssl "Permalink") + +将您的负载均衡器配置为以" TCP"而不是" HTTP(S)"协议的形式在端口 443 上传递连接. 这会将连接保持不变地传递到应用程序节点 NGINX 服务. NGINX 将具有 SSL 证书并在端口 443 上侦听. + +有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load Balancer(s) terminate SSL without backend SSL[](#load-balancers-terminate-ssl-without-backend-ssl "Permalink") + +将您的负载均衡器配置为使用" HTTP(S)"协议而不是" TCP". 然后,负载均衡器将负责管理 SSL 证书和终止 SSL. + +由于负载均衡器和 GitLab 之间的通信将不安全,因此需要一些其他配置. 有关详细信息,请参见[NGINX 代理的 SSL 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +### Load Balancer(s) terminate SSL with backend SSL[](#load-balancers-terminate-ssl-with-backend-ssl "Permalink") + +将您的负载均衡器配置为使用" HTTP(S)"协议而不是" TCP". 负载平衡器将负责管理最终用户将看到的 SSL 证书. + +在这种情况下,负载均衡器和 NGINX 之间的流量也将是安全的. 无需为代理 SSL 添加配置,因为连接将一直保持安全. 但是,需要将配置添加到 GitLab 来配置 SSL 证书. 有关管理 SSL 证书和配置 NGINX 的详细信息,请参见[NGINX HTTPS 文档](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +## Ports[](#ports "Permalink") + +### Basic ports[](#basic-ports "Permalink") + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 80 | HTTP( *1* ) | +| 443 | 443 | TCP 或 HTTPS( *1* )( *2* ) | +| 22 | 22 | TCP | + +* ( *1* ): [Web 终端](../../ci/environments/index.html#web-terminals)支持要求您的负载平衡器正确处理 WebSocket 连接. 当使用 HTTP 或 HTTPS 代理,这意味着负载平衡器必须被配置为通过`Connection`和`Upgrade`逐跳头. 有关更多详细信息,请参见[Web 终端](../integration/terminal.html)集成指南. +* ( *2* ):当对端口 443 使用 HTTPS 协议时,需要向负载均衡器添加 SSL 证书. 如果您想在 GitLab 应用程序服务器上终止 SSL,请使用 TCP 协议. + +### GitLab Pages Ports[](#gitlab-pages-ports "Permalink") + +如果您使用具有自定义域支持的 GitLab 页面,则将需要一些其他端口配置. GitLab 页面需要一个单独的虚拟 IP 地址. 配置 DNS,将`pages_external_url`的`/etc/gitlab/gitlab.rb`指向新的虚拟 IP 地址. 有关更多信息,请参见[GitLab 页面文档](../pages/index.html) . + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 80 | 变化( *1* ) | HTTP | +| 443 | 变化( *1* ) | TCP( *2* ) | + +* ( *1* ):GitLab 页面的后端端口取决于`gitlab_pages['external_http']`和`gitlab_pages['external_https']`设置. 有关更多详细信息,请参见[GitLab Pages 文档](../pages/index.html) . +* ( *2* ):GitLab 页面的端口 443 应该始终使用 TCP 协议. 用户可以使用自定义 SSL 配置自定义域,如果 SSL 在负载均衡器处终止,则不可能. + +### Alternate SSH Port[](#alternate-ssh-port "Permalink") + +某些组织有禁止打开 SSH 端口 22 的策略.在这种情况下,配置允许用户在端口 443 上使用 SSH 的备用 SSH 主机名可能会有所帮助.与其他 GitLab 相比,备用 SSH 主机名将需要一个新的虚拟 IP 地址.上面的 HTTP 配置. + +为备用 SSH 主机名(例如`altssh.gitlab.example.com`配置 DNS. + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 443 | 22 | TCP | + +## Readiness check[](#readiness-check "Permalink") + +强烈建议多节点部署将负载平衡器配置为利用[就绪检查,](../../user/admin_area/monitoring/health_check.html#readiness)以确保在将流量路由到节点之前准备好接受流量. 在使用 Puma 时,这一点尤其重要,因为在重新启动过程中会有短暂的一段时间,Puma 将不接受请求. + +* * * + +阅读更多有关高可用性配置的信息: + +1. [Configure the database](../postgresql/replication_and_failover.html) +2. [Configure Redis](redis.html) +3. [Configure NFS](nfs.html) +4. [Configure the GitLab application servers](gitlab.html) \ No newline at end of file diff --git a/docs/433.md b/docs/433.md new file mode 100644 index 0000000000000000000000000000000000000000..267d104ebe0867a919cd54ac111959b5b0b8b073 --- /dev/null +++ b/docs/433.md @@ -0,0 +1,86 @@ +# Configuring a Monitoring node for Scaling and High Availability + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/monitoring_node.html](https://docs.gitlab.com/ee/administration/high_availability/monitoring_node.html) + +* [Standalone Monitoring node using Omnibus GitLab](#standalone-monitoring-node-using-omnibus-gitlab) +* [Migrating to Service Discovery](#migrating-to-service-discovery) + +# Configuring a Monitoring node for Scaling and High Availability[](#configuring-a-monitoring-node-for-scaling-and-high-availability "Permalink") + +在 GitLab 12.0 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) . + +您可以配置 Prometheus 节点以监视 GitLab. + +## Standalone Monitoring node using Omnibus GitLab[](#standalone-monitoring-node-using-omnibus-gitlab "Permalink") + +Omnibus GitLab 软件包可用于配置运行[Prometheus](../monitoring/prometheus/index.html)和[Grafana](../monitoring/performance/grafana_configuration.html)的独立 Monitoring 节点. 监视节点不是高度可用. 请参阅[缩放和高可用性](../reference_architectures/index.html)的 GitLab 扩展和高可用性选项的概述. + +以下步骤是使用 Omnibus 配置运行 Prometheus 和 Grafana 的 Monitoring 节点的最低必需步骤: + +1. SSH 进入"监视"节点. +2. 从 GitLab 下载页面使用**步骤 1 和 2** [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. + * 不要完成下载页面上的任何其他步骤. +3. [`CONSUL_SERVER_NODES`](../postgresql/replication_and_failover.html#consul-information) ,请确保收集[`CONSUL_SERVER_NODES`](../postgresql/replication_and_failover.html#consul-information) ,它们是 Consul 服务器节点的 IP 地址或 DNS 记录. 请注意,它们显示为`YYYY consul1.gitlab.example.com ZZZZ` + +4. 编辑`/etc/gitlab/gitlab.rb`并添加内容: + + ``` + external_url 'http://gitlab.example.com' + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Login form + grafana['disable_login_form'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = 'toomanysecrets' + + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Replace placeholders + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses of the Consul server nodes + consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), + } + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + node_exporter['enable'] = false + gitlab_exporter['enable'] = false + ``` + +5. 运行`sudo gitlab-ctl reconfigure`来编译配置. + +下一步是告诉所有其他节点监视节点在哪里: + +1. 编辑`/etc/gitlab/gitlab.rb` ,然后添加或查找并取消注释以下行: + + ``` + gitlab_rails['prometheus_address'] = '10.0.0.1:9090' + ``` + + 其中`10.0.0.1:9090`是 Prometheus 节点的 IP 地址和端口. + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +## Migrating to Service Discovery[](#migrating-to-service-discovery "Permalink") + +使用`consul['monitoring_service_discovery'] = true`启用使用服务发现进行`consul['monitoring_service_discovery'] = true` ,请确保未在`/etc/gitlab/gitlab.rb`设置`prometheus['scrape_configs']` . 在`/etc/gitlab/gitlab.rb`同时设置`consul['monitoring_service_discovery'] = true`和`prometheus['scrape_configs']`都会导致错误. \ No newline at end of file diff --git a/docs/434.md b/docs/434.md new file mode 100644 index 0000000000000000000000000000000000000000..b134a5f003ae40b70f2e55a83bc41ccbbe2a7b09 --- /dev/null +++ b/docs/434.md @@ -0,0 +1,237 @@ +# NFS + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/nfs.html](https://docs.gitlab.com/ee/administration/high_availability/nfs.html) + +* [Known kernel version incompatibilities](#known-kernel-version-incompatibilities) +* [NFS Server features](#nfs-server-features) + * [Required features](#required-features) + * [Recommended options](#recommended-options) + * [Disable NFS server delegation](#disable-nfs-server-delegation) + * [Important notes](#important-notes) + * [Improving NFS performance with GitLab](#improving-nfs-performance-with-gitlab) + * [Improving NFS performance with Unicorn](#improving-nfs-performance-with-unicorn) + * [Improving NFS performance with Puma](#improving-nfs-performance-with-puma) + * [Known issues](#known-issues) + * [Avoid using AWS’s Elastic File System (EFS)](#avoid-using-awss-elastic-file-system-efs) + * [Avoid using CephFS and GlusterFS](#avoid-using-cephfs-and-glusterfs) + * [Avoid using PostgreSQL with NFS](#avoid-using-postgresql-with-nfs) +* [NFS Client mount options](#nfs-client-mount-options) + * [soft mount option](#soft-mount-option) +* [A single NFS mount](#a-single-nfs-mount) +* [Bind mounts](#bind-mounts) +* [Multiple NFS mounts](#multiple-nfs-mounts) + +# NFS[](#nfs "Permalink") + +您可以通过运行`nfsstat -m`和`cat /etc/fstab`来查看每个已安装的 NFS 文件系统的信息和选项集. + +**注意:**从 GitLab 13.0 开始,不建议将 NFS 用于 Git 存储库. 在 GitLab 14.0 中,计划删除对 Nit for Git 存储库的支持. 尽快升级到[Gitaly Cluster](../gitaly/praefect.html) .**注意:**文件系统的性能对整体 GitLab 的性能有很大的影响,特别是对于读取或写入 Git 存储库的操作. 有关测试文件系统性能的步骤,请参见[文件系统性能基准](../operations/filesystem_benchmarking.html)测试. + +## Known kernel version incompatibilities[](#known-kernel-version-incompatibilities "Permalink") + +RedHat Enterprise Linux(RHEL)和 CentOS v7.7 和 v7.8 附带了内核版本`3.10.0-1127` ,该版本[包含一个错误](https://bugzilla.redhat.com/show_bug.cgi?id=1783554) , [该错误](https://bugzilla.redhat.com/show_bug.cgi?id=1783554)会导致[上传无法通过 NFS 复制](https://gitlab.com/gitlab-org/gitlab/-/issues/218999) . 以下 GitLab 版本包含一个可与该内核版本一起正常使用的修复程序: + +1. [12.10.12](https://about.gitlab.com/releases/2020/06/25/gitlab-12-10-12-released/) +2. [13.0.7](https://about.gitlab.com/releases/2020/06/25/gitlab-13-0-7-released/) +3. [13.1.1](https://about.gitlab.com/releases/2020/06/24/gitlab-13-1-1-released/) +4. 13.2 以上 + +如果使用的是该内核版本,请确保升级 GitLab 以避免错误. + +## NFS Server features[](#nfs-server-features "Permalink") + +### Required features[](#required-features "Permalink") + +**文件锁定** :GitLab **需要**咨询性文件锁定,只有 NFS 版本 4 才支持该功能.只要使用 Linux Kernel 2.6.5 +,NFSv3 还支持锁定. 我们建议使用版本 4,并且不要专门测试 NFSv3. + +### Recommended options[](#recommended-options "Permalink") + +定义 NFS 导出时,建议您还添加以下选项: + +* `no_root_squash` -NFS 通常将`root`用户更改为`nobody` . 当许多不同的用户将访问 NFS 共享时,这是一个很好的安全措施. 但是,在这种情况下,只有 GitLab 会使用 NFS 共享,因此很安全. GitLab 建议使用`no_root_squash`设置,因为我们需要自动管理文件权限. 如果没有该设置,则当 Omnibus 软件包尝试更改权限时,您可能会收到错误消息. 请注意,GitLab 和其他捆绑组件**不是**以`root`用户身份运行,而是以非特权用户身份运行. 对于`no_root_squash`的建议是允许 Omnibus 软件包根据需要设置文件的所有权和权限. 在`no_root_squash`选项不可用的某些情况下, `root`标志可以实现相同的结果. +* `sync`强制同步行为. 默认值是异步的,在某些情况下,如果在同步数据之前发生故障,则可能导致数据丢失. + +由于使用 LDAP 运行 Omnibus 的复杂性和不使用 LDAP 维护 ID 映射的复杂性,在大多数情况下,应启用数字 UID 和 GID(在某些情况下默认情况下处于禁用状态),以简化系统之间的权限管理: + +* [NetApp instructions](https://library.netapp.com/ecmdocs/ECMP1401220/html/GUID-24367A9F-E17B-4725-ADC1-02D86F56F78E.html) +* 对于非 NetApp 设备,请执行与[启用 NFSv4 idmapper](https://wiki.archlinux.org/index.php/NFS#Enabling_NFSv4_idmapping)相反的`idmapping`来禁用[NFSv4 idmapping](https://wiki.archlinux.org/index.php/NFS#Enabling_NFSv4_idmapping) + +### Disable NFS server delegation[](#disable-nfs-server-delegation "Permalink") + +我们建议所有 NFS 用户禁用 NFS 服务器委派功能. 这是为了避免[Linux 内核错误](https://bugzilla.redhat.com/show_bug.cgi?id=1552203) ,该[错误](https://bugzilla.redhat.com/show_bug.cgi?id=1552203)会由于[来自大量`TEST_STATEID` NFS 消息的过多网络流量](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52017)而导致 NFS 客户端急剧减速. + +要禁用 NFS 服务器委派,请执行以下操作: + +1. 在 NFS 服务器上,运行: + + ``` + echo 0 > /proc/sys/fs/leases-enable + sysctl -w fs.leases-enable=0 + ``` + +2. 重新启动 NFS 服务器进程. 例如,在 CentOS 上运行`service nfs restart` . + +#### Important notes[](#important-notes "Permalink") + +[此提交](https://github.com/torvalds/linux/commit/95da1b3a5aded124dd1bda1e3cdb876184813140)可能会在[较新的内核中](https://github.com/torvalds/linux/commit/95da1b3a5aded124dd1bda1e3cdb876184813140)修复内核错误. + +Red Hat Enterprise 7 于 2019 年 8 月 6 日[发布了内核更新](https://access.redhat.com/errata/RHSA-2019:2029) , [该更新](https://access.redhat.com/errata/RHSA-2019:2029)也可能已解决了该问题. + +如果您知道使用的是已修复的 Linux 内核版本,则可能不需要禁用 NFS 服务器委派. 也就是说,GitLab 仍然鼓励实例管理员保持 NFS 服务器委派禁用. + +### Improving NFS performance with GitLab[](#improving-nfs-performance-with-gitlab "Permalink") + +#### Improving NFS performance with Unicorn[](#improving-nfs-performance-with-unicorn "Permalink") + +**注意:**从 GitLab 12.1 开始,如果可以并且应该为每个存储使用 Rugged,它将自动检测到它. + +如果先前使用功能标记启用了 Rugged,则需要使用以下方法取消设置功能标记: + +``` +sudo gitlab-rake gitlab:features:unset_rugged +``` + +如果将 Rugged 功能标志显式设置为 true 或 false,则 GitLab 将使用显式设置的值. + +#### Improving NFS performance with Puma[](#improving-nfs-performance-with-puma "Permalink") + +**注意:**从 GitLab 12.7 开始,如果 Puma 线程数大于 1,则将禁用 Rugged 自动检测. + +如果要将 Rugged 与 Puma 一起使用,建议[将 Puma 线程数设置为 1](https://docs.gitlab.com/omnibus/settings/puma.html) . + +如果您想使用 Rugged 且 Puma 线程数大于 1,则可以使用[功能标志](../../development/gitaly.html#legacy-rugged-code)启用 Rugged + +如果将 Rugged 功能标志显式设置为 true 或 false,则 GitLab 将使用显式设置的值. + +### Known issues[](#known-issues "Permalink") + +#### Avoid using AWS’s Elastic File System (EFS)[](#avoid-using-awss-elastic-file-system-efs "Permalink") + +GitLab 强烈建议您不要使用 AWS Elastic File System(EFS). 我们的支持团队将无法协助解决与文件系统访问相关的性能问题. + +客户和用户报告说,AWS EFS 在 GitLab 的用例中表现不佳. 以串行化方式写入许多小文件的工作负载(例如`git` )不适合 EFS. 顶部带有 NFS 服务器的 EBS 的性能会好得多. + +如果确实选择使用 EFS,请避免在其中存储 GitLab 日志文件(例如`/var/log/gitlab` ),因为这也会影响性能. 我们建议将日志文件存储在本地卷上. + +有关其他人使用 EFS 的经验的更多详细信息,请参阅此[Commit Brooklyn 2019 视频](https://youtu.be/K6OS8WodRBQ?t=313) . + +#### Avoid using CephFS and GlusterFS[](#avoid-using-cephfs-and-glusterfs "Permalink") + +GitLab 强烈建议不要使用 CephFS 和 GlusterFS. 这些分布式文件系统不适用于 GitLab 的输入/输出访问模式,因为 Git 使用许多小文件,并且传播的访问时间和文件锁定时间会使 Git 活动非常缓慢. + +#### Avoid using PostgreSQL with NFS[](#avoid-using-postgresql-with-nfs "Permalink") + +GitLab 强烈建议不要跨 NFS 运行 PostgreSQL 数据库. GitLab 支持团队将无法协助解决与该配置有关的性能问题. + +此外,该配置在[PostgreSQL 文档中](https://s0www0postgresql0org.icopy.site/docs/current/creating-cluster.html)特别警告: + +> PostgreSQL does nothing special for NFS file systems, meaning it assumes NFS behaves exactly like locally-connected drives. If the client or server NFS implementation does not provide standard file system semantics, this can cause reliability problems. Specifically, delayed (asynchronous) writes to the NFS server can cause data corruption problems. + +有关受支持的数据库体系结构,请参阅有关[为 GitLab HA 配置数据库的](../postgresql/replication_and_failover.html)文档. + +## NFS Client mount options[](#nfs-client-mount-options "Permalink") + +这是添加到`/etc/fstab`的示例片段: + +``` + 10.1.0.1:/var/opt/gitlab/.ssh /var/opt/gitlab/.ssh nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 + 10.1.0.1:/var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/uploads nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 + 10.1.0.1:/var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-rails/shared nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 + 10.1.0.1:/var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/gitlab-ci/builds nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 + 10.1.0.1:/var/opt/gitlab/git-data /var/opt/gitlab/git-data nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 +``` + +请注意,您应该考虑使用几个选项: + +| Setting | Description | +| --- | --- | +| `vers=4.1` | 应该使用 NFS v4.1 代替 v4.0,因为 v4.0 中存在一个 Linux [NFS 客户端错误,](https://gitlab.com/gitlab-org/gitaly/-/issues/1339)由于过时的数据可能导致严重的问题. | +| `nofail` | 不要停止启动过程,等待此挂载可用 | +| `lookupcache=positive` | Tells the NFS client to honor `positive` cache results but invalidates any `negative` cache results. Negative cache results cause problems with Git. Specifically, a `git push` can fail to register uniformly across all NFS clients. The negative cache causes the clients to ‘remember’ that the files did not exist previously. | +| `hard` | 而不是`soft` . [进一步的细节](#soft-mount-option) . | + +### soft mount option[](#soft-mount-option "Permalink") + +我们建议您在安装选项中使用`hard` ,除非您出于特殊原因使用`soft` . + +在 GitLab.com,我们使用`soft` ,因为有些时候我们不得不 NFS 服务器重新启动和`soft`改进的可用性,但每个人的基础不同. 例如,如果您的 NFS 由带有冗余控制器的本地存储阵列提供,则无需担心 NFS 服务器的可用性. + +NFS 手册页指出: + +> 在某些情况下,"软"超时可能会导致无提示数据损坏 + +阅读[Linux 手册页](https://linux.die.net/man/5/nfs)以了解它们之间的区别,如果您确实使用`soft` ,请确保已采取步骤减轻风险. + +如果您遇到的问题可能是由于未发生对 NFS 服务器的磁盘写入而导致的,例如丢失了提交,请使用`hard`选项,因为(在手册页中): + +> 仅当客户端响应能力比数据完整性更重要时才使用 soft 选项 + +其他供应商也提出了类似的建议,包括[SAP](http://wiki.scn.sap.com/wiki/x/PARnFQ)和 NetApp 的[知识库](https://kb.netapp.com/Advice_and_Troubleshooting/Data_Storage_Software/ONTAP_OS/What_are_the_differences_between_hard_mount_and_soft_mount) ,他们强调说,如果 NFS 客户端驱动程序缓存数据,则`soft`意味着无法确定 GitLab 的写操作是否确实在磁盘上. + +使用`hard`选项设置的安装点可能无法正常运行,并且如果 NFS 服务器关闭,则`hard`会导致与安装点进行交互时挂起进程. 使用`SIGKILL` ( `kill -9` )处理挂起的进程. `intr`选项[在 2.6 内核中停止工作](https://access.redhat.com/solutions/157873) . + +## A single NFS mount[](#a-single-nfs-mount "Permalink") + +建议将所有 GitLab 数据目录嵌套在一个装载中,这样可以自动还原备份而无需手动移动现有数据. + +``` +mountpoint +└── gitlab-data + ├── builds + ├── git-data + ├── shared + └── uploads +``` + +为此,我们需要使用嵌套在安装点中的每个目录的路径来配置 Omnibus,如下所示: + +然后挂载`/gitlab-nfs`使用以下 Omnibus 配置将每个数据位置移动到子目录: + +``` +git_data_dirs({"default" => { "path" => "/gitlab-nfs/gitlab-data/git-data"} }) +gitlab_rails['uploads_directory'] = '/gitlab-nfs/gitlab-data/uploads' +gitlab_rails['shared_path'] = '/gitlab-nfs/gitlab-data/shared' +gitlab_ci['builds_directory'] = '/gitlab-nfs/gitlab-data/builds' +``` + +运行`sudo gitlab-ctl reconfigure`以开始使用中心位置. 请注意,如果您已有数据,则需要手动将其复制/同步到这些新位置,然后重新启动 GitLab. + +## Bind mounts[](#bind-mounts "Permalink") + +除了更改 Omnibus 中的配置外,绑定挂载还可用于将数据存储在 NFS 挂载上. + +绑定挂载提供一种仅指定一个 NFS 挂载,然后将默认的 GitLab 数据位置绑定到 NFS 挂载的方法. 首先定义您的单个 NFS 挂载点,就像通常在`/etc/fstab` . 假设您的 NFS 挂载点是`/gitlab-nfs` . 然后,在`/etc/fstab`添加以下绑定安装: + +``` +/gitlab-nfs/gitlab-data/git-data /var/opt/gitlab/git-data none bind 0 0 +/gitlab-nfs/gitlab-data/.ssh /var/opt/gitlab/.ssh none bind 0 0 +/gitlab-nfs/gitlab-data/uploads /var/opt/gitlab/gitlab-rails/uploads none bind 0 0 +/gitlab-nfs/gitlab-data/shared /var/opt/gitlab/gitlab-rails/shared none bind 0 0 +/gitlab-nfs/gitlab-data/builds /var/opt/gitlab/gitlab-ci/builds none bind 0 0 +``` + +使用绑定安装将需要手动确保数据目录为空,然后再尝试还原. 阅读有关[还原先决条件的](../../raketasks/backup_restore.html)更多信息. + +## Multiple NFS mounts[](#multiple-nfs-mounts "Permalink") + +使用默认的 Omnibus 配置时,您将需要在所有 GitLab 群集节点之间共享 4 个数据位置. 没有其他位置可以共享. 以下是需要共享的四个位置: + +| Location | Description | 默认配置 | +| --- | --- | --- | +| `/var/opt/gitlab/git-data` | Git 存储库数据. 这将占您数据的很大一部分 | `git_data_dirs({"default" => { "path" => "/var/opt/gitlab/git-data"} })` | +| `/var/opt/gitlab/gitlab-rails/uploads` | 用户上传的附件 | `gitlab_rails['uploads_directory'] = '/var/opt/gitlab/gitlab-rails/uploads'` | +| `/var/opt/gitlab/gitlab-rails/shared` | Build artifacts, GitLab Pages, LFS objects, temp files, etc. If you’re using LFS this may also account for a large portion of your data | `gitlab_rails['shared_path'] = '/var/opt/gitlab/gitlab-rails/shared'` | +| `/var/opt/gitlab/gitlab-ci/builds` | GitLab CI / CD 构建跟踪 | `gitlab_ci['builds_directory'] = '/var/opt/gitlab/gitlab-ci/builds'` | + +其他 GitLab 目录不应在节点之间共享. 它们包含特定于节点的文件和不需要共享的 GitLab 代码. 要将日志发送到中央位置,请考虑使用远程 syslog. Omnibus GitLab 软件包提供了[UDP 日志传送的](https://docs.gitlab.com/omnibus/settings/logs.html)配置. + +具有多个 NFS 挂载将需要手动确保数据目录为空,然后再尝试还原. 阅读有关[还原先决条件的](../../raketasks/backup_restore.html)更多信息. + +* * * + +阅读更多有关高可用性配置的信息: + +1. [Configure the database](../postgresql/replication_and_failover.html) +2. [Configure Redis](redis.html) +3. [Configure the GitLab application servers](gitlab.html) +4. [Configure the load balancers](load_balancer.html) \ No newline at end of file diff --git a/docs/435.md b/docs/435.md new file mode 100644 index 0000000000000000000000000000000000000000..a6c53aa3028a2a554d7ba54a5f45888fd33a05d2 --- /dev/null +++ b/docs/435.md @@ -0,0 +1,176 @@ +# Working with the bundled PgBouncer service + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/pgbouncer.html](https://docs.gitlab.com/ee/administration/high_availability/pgbouncer.html) + +* [Operations](#operations) + * [Running PgBouncer as part of an HA GitLab installation](#running-pgbouncer-as-part-of-an-ha-gitlab-installation) + * [Running PgBouncer as part of a non-HA GitLab installation](#running-pgbouncer-as-part-of-a-non-ha-gitlab-installation) +* [Enable Monitoring](#enable-monitoring) + * [Interacting with PgBouncer](#interacting-with-pgbouncer) + * [Administrative console](#administrative-console) +* [Troubleshooting](#troubleshooting) + * [Message: `LOG: invalid CIDR mask in address`](#message-log--invalid-cidr-mask-in-address) + * [Message: `LOG: invalid IP mask "md5": Name or service not known`](#message-log--invalid-ip-mask-md5-name-or-service-not-known) + +# Working with the bundled PgBouncer service[](#working-with-the-bundled-pgbouncer-service-premium-only "Permalink") + +由于它的高可用性堆栈的一部分,GitLab Premium 包含的捆绑版本[PgBouncer](http://www.pgbouncer.org/)可以通过管理`/etc/gitlab/gitlab.rb` . PgBouncer 用于在故障转移方案中在服务器之间无缝迁移数据库连接. 此外,它可以用于非 HA 设置中以建立连接池,从而加快响​​应时间,同时减少资源使用. + +在高可用性设置中,建议为每个数据库节点分别运行一个 PgBouncer 节点,并使用一个内部负载均衡器(TCP)相应地为其服务. + +## Operations[](#operations "Permalink") + +### Running PgBouncer as part of an HA GitLab installation[](#running-pgbouncer-as-part-of-an-ha-gitlab-installation "Permalink") + +该内容已移至[新位置](../postgresql/replication_and_failover.html#configuring-the-pgbouncer-node) . + +### Running PgBouncer as part of a non-HA GitLab installation[](#running-pgbouncer-as-part-of-a-non-ha-gitlab-installation "Permalink") + +1. 使用命令`gitlab-ctl pg-password-md5 pgbouncer`生成 PGBOUNCER_USER_PASSWORD_HASH + +2. 使用命令`gitlab-ctl pg-password-md5 gitlab` . 稍后我们还需要输入纯文本 SQL_USER_PASSWORD + +3. 在数据库节点上,确保在`/etc/gitlab/gitlab.rb`设置了以下`/etc/gitlab/gitlab.rb` + + ``` + postgresql['pgbouncer_user_password'] = 'PGBOUNCER_USER_PASSWORD_HASH' + postgresql['sql_user_password'] = 'SQL_USER_PASSWORD_HASH' + postgresql['listen_address'] = 'XX.XX.XX.Y' # Where XX.XX.XX.Y is the ip address on the node postgresql should listen on + postgresql['md5_auth_cidr_addresses'] = %w(AA.AA.AA.B/32) # Where AA.AA.AA.B is the IP address of the pgbouncer node + ``` + +4. Run `gitlab-ctl reconfigure` + + **注意:**如果数据库已经在运行,则需要在重新配置后通过运行`gitlab-ctl restart postgresql`来重新启动数据库. + +5. 在运行 PgBouncer 的节点上,确保在`/etc/gitlab/gitlab.rb`设置了以下`/etc/gitlab/gitlab.rb` + + ``` + pgbouncer['enable'] = true + pgbouncer['databases'] = { + gitlabhq_production: { + host: 'DATABASE_HOST', + user: 'pgbouncer', + password: 'PGBOUNCER_USER_PASSWORD_HASH' + } + } + ``` + +6. Run `gitlab-ctl reconfigure` + +7. 在运行 Puma 的节点上,确保在`/etc/gitlab/gitlab.rb`设置了以下`/etc/gitlab/gitlab.rb` + + ``` + gitlab_rails['db_host'] = 'PGBOUNCER_HOST' + gitlab_rails['db_port'] = '6432' + gitlab_rails['db_password'] = 'SQL_USER_PASSWORD' + ``` + +8. Run `gitlab-ctl reconfigure` + +9. 此时,您的实例应通过 PgBouncer 连接到数据库. 如果遇到问题,请参阅" [故障排除"](#troubleshooting)部分 + +## Enable Monitoring[](#enable-monitoring "Permalink") + +在 GitLab 12.0 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) . + +If you enable Monitoring, it must be enabled on **all** PgBouncer servers. + +1. 创建/编辑`/etc/gitlab/gitlab.rb`并添加以下配置: + + ``` + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Replace placeholders + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses of the Consul server nodes + consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + pgbouncer_exporter['listen_address'] = '0.0.0.0:9188' + ``` + +2. 运行`sudo gitlab-ctl reconfigure`来编译配置. + +### Interacting with PgBouncer[](#interacting-with-pgbouncer "Permalink") + +#### Administrative console[](#administrative-console "Permalink") + +作为 Omnibus GitLab 的一部分,我们提供了一个`gitlab-ctl pgb-console`命令,以自动连接到 PgBouncer 管理控制台. 请参阅[PgBouncer 文档](https://www.pgbouncer.org/usage.html#admin-console)以获取有关如何与控制台进行交互的详细说明. + +要开始会话,请运行 + +``` +# gitlab-ctl pgb-console +Password for user pgbouncer: +psql (11.7, server 1.7.2/bouncer) +Type "help" for help. + +pgbouncer=# +``` + +将提示您输入的密码是 PGBOUNCER_USER_PASSWORD + +要获取有关实例的一些基本信息,请运行 + +``` +pgbouncer=# show databases; show clients; show servers; + name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections +---------------------+-----------+------+---------------------+------------+-----------+--------------+-----------+-----------------+--------------------- + gitlabhq_production | 127.0.0.1 | 5432 | gitlabhq_production | | 100 | 5 | | 0 | 1 + pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0 +(2 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link +| remote_pid | tls +------+-----------+---------------------+--------+-----------+-------+------------+------------+---------------------+---------------------+-----------+------ ++------------+----- + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44590 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x12444c0 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44592 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x12447c0 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44594 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x1244940 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44706 | 127.0.0.1 | 6432 | 2018-04-24 22:14:22 | 2018-04-24 22:16:31 | 0x1244ac0 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44708 | 127.0.0.1 | 6432 | 2018-04-24 22:14:22 | 2018-04-24 22:15:15 | 0x1244c40 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44794 | 127.0.0.1 | 6432 | 2018-04-24 22:15:15 | 2018-04-24 22:15:15 | 0x1244dc0 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44798 | 127.0.0.1 | 6432 | 2018-04-24 22:15:15 | 2018-04-24 22:16:31 | 0x1244f40 | +| 0 | + C | pgbouncer | pgbouncer | active | 127.0.0.1 | 44660 | 127.0.0.1 | 6432 | 2018-04-24 22:13:51 | 2018-04-24 22:17:12 | 0x1244640 | +| 0 | +(8 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | rem +ote_pid | tls +------+--------+---------------------+-------+-----------+------+------------+------------+---------------------+---------------------+-----------+------+---- +--------+----- + S | gitlab | gitlabhq_production | idle | 127.0.0.1 | 5432 | 127.0.0.1 | 35646 | 2018-04-24 22:15:15 | 2018-04-24 22:17:10 | 0x124dca0 | | + 19980 | +(1 row) +``` + +## Troubleshooting[](#troubleshooting "Permalink") + +如果您遇到通过 PgBouncer 连接的任何问题,则首先检查的始终是日志: + +``` +# gitlab-ctl tail pgbouncer +``` + +另外,您可以在[管理控制台中](#administrative-console)检查`show databases`的输出. 在输出中,您期望在`gitlabhq_production`数据库的`host`字段中看到值. 此外, `current_connections`应该大于 1. + +### Message: `LOG: invalid CIDR mask in address`[](#message-log--invalid-cidr-mask-in-address "Permalink") + +请参阅[Geo 文档中](../geo/replication/troubleshooting.html#message-log--invalid-cidr-mask-in-address)建议的修复程序. + +### Message: `LOG: invalid IP mask "md5": Name or service not known`[](#message-log--invalid-ip-mask-md5-name-or-service-not-known "Permalink") + +请参阅[Geo 文档中](../geo/replication/troubleshooting.html#message-log--invalid-ip-mask-md5-name-or-service-not-known)建议的修复程序. \ No newline at end of file diff --git a/docs/436.md b/docs/436.md new file mode 100644 index 0000000000000000000000000000000000000000..6402a61010ad48715eaf18e7f706b5d5c5883eea --- /dev/null +++ b/docs/436.md @@ -0,0 +1,33 @@ +# Configuring Redis for scaling + +> 原文:[https://docs.gitlab.com/ee/administration/redis/](https://docs.gitlab.com/ee/administration/redis/) + +* [Redis replication and failover using Omnibus GitLab](#redis-replication-and-failover-using-omnibus-gitlab) +* [Redis replication and failover using the non-bundled Redis](#redis-replication-and-failover-using-the-non-bundled-redis) +* [Standalone Redis using Omnibus GitLab](#standalone-redis-using-omnibus-gitlab) + +# Configuring Redis for scaling[](#configuring-redis-for-scaling "Permalink") + +根据您的基础架构设置以及如何安装 GitLab,有多种方法来配置 Redis. + +您可以选择自己安装和管理 Redis 和 Sentinel,使用托管的云解决方案,也可以使用 Omnibus GitLab 软件包随附的软件包,因此您只需要关注配置. 选择一个适合您的需求. + +## Redis replication and failover using Omnibus GitLab[](#redis-replication-and-failover-using-omnibus-gitlab "Permalink") + +此设置适用于使用[Omnibus GitLab **企业版** (EE)软件包](https://about.gitlab.com/install/?version=ee)安装 GitLab 的情况. + +Redis 和 Sentinel 都捆绑在软件包中,因此您可以使用它来设置整个 Redis 基础架构(主要,副本和哨兵). + +[> Read how to set up Redis replication and failover using Omnibus GitLab](replication_and_failover.html) + +## Redis replication and failover using the non-bundled Redis[](#redis-replication-and-failover-using-the-non-bundled-redis "Permalink") + +此设置适用于使用[Omnibus GitLab 软件包](https://about.gitlab.com/install/) (CE 或 EE)安装 GitLab 或[从源代码](../../install/installation.html)安装 GitLab 的情况,但您想使用自己的外部 Redis 和哨兵服务器. + +[> Read how to set up Redis replication and failover using the non-bundled Redis](replication_and_failover_external.html) + +## Standalone Redis using Omnibus GitLab[](#standalone-redis-using-omnibus-gitlab "Permalink") + +此设置适用于您安装了[Omnibus GitLab **社区版** (CE)软件包](https://about.gitlab.com/install/?version=ce)以使用捆绑的 Redis 的情况,因此您可以在仅启用 Redis 服务的情况下使用该软件包. + +[> Read how to set up a standalone Redis instance using Omnibus GitLab](standalone.html) \ No newline at end of file diff --git a/docs/437.md b/docs/437.md new file mode 100644 index 0000000000000000000000000000000000000000..6f4b2dbb1f1c560d1d2cd2d9d50b9fc11d547ec5 --- /dev/null +++ b/docs/437.md @@ -0,0 +1,188 @@ +# Configuring Sidekiq + +> 原文:[https://docs.gitlab.com/ee/administration/high_availability/sidekiq.html](https://docs.gitlab.com/ee/administration/high_availability/sidekiq.html) + +* [Example configuration](#example-configuration) +* [Further reading](#further-reading) + +# Configuring Sidekiq[](#configuring-sidekiq "Permalink") + +本节讨论如何配置外部 Sidekiq 实例. + +Sidekiq 需要连接到 Redis,PostgreSQL 和 Gitaly 实例. 要配置 Sidekiq 节点: + +1. SSH 到 Sidekiq 服务器. + +2. 从 GitLab 下载页面使用步骤 1 和 2 [下载/安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包. **不要完成下载页面上的任何其他步骤.** + +3. 使用编辑器打开`/etc/gitlab/gitlab.rb` . + +4. 生成 Sidekiq 配置: + + ``` + sidekiq['listen_address'] = "10.10.1.48" + + ## Optional: Enable extra Sidekiq processes + sidekiq_cluster['enable'] = true + sidekiq_cluster['enable'] = true + "elastic_indexer" + ] + ``` + +5. 设置 Sidekiq 与 Redis 的连接: + + ``` + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + ## The same password for Redis authentication you set up for the master node. + redis['master_password'] = 'YOUR_PASSOWORD' + + ## A list of sentinels with `host` and `port` + gitlab_rails['redis_sentinels'] = [ + {'host' => '10.10.1.34', 'port' => 26379}, + {'host' => '10.10.1.35', 'port' => 26379}, + {'host' => '10.10.1.36', 'port' => 26379}, + ] + ``` + +6. 设置 Sidekiq 与 Gitaly 的连接: + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly:8075' }, + }) + gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + ``` + +7. 设置 Sidekiq 与 PostgreSQL 的连接: + + ``` + gitlab_rails['db_host'] = '10.10.1.30' + gitlab_rails['db_password'] = 'YOUR_PASSOWORD' + gitlab_rails['db_port'] = '5432' + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['auto_migrate'] = false + ``` + + 请记住将 Sidekiq 节点添加到 PostgreSQL 的受信任地址中: + + ``` + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32 10.10.1.31/32 10.10.1.32/32 10.10.1.33/32 10.10.1.38/32) + ``` + +8. 禁用其他服务: + + ``` + nginx['enable'] = false + grafana['enable'] = false + prometheus['enable'] = false + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_monitor['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + puma['enable'] = false + gitlab_exporter['enable'] = false + ``` + +9. Run `gitlab-ctl reconfigure`. + +**注意:**发生更新并执行数据库迁移后,您将需要重新启动 Sidekiq 节点. + +## Example configuration[](#example-configuration "Permalink") + +这是结尾的`/etc/gitlab/gitlab.rb`样子: + +``` +######################################## +##### Services Disabled ### +######################################## + +nginx['enable'] = false +grafana['enable'] = false +prometheus['enable'] = false +gitlab_rails['auto_migrate'] = false +alertmanager['enable'] = false +gitaly['enable'] = false +gitlab_monitor['enable'] = false +gitlab_workhorse['enable'] = false +nginx['enable'] = false +postgres_exporter['enable'] = false +postgresql['enable'] = false +redis['enable'] = false +redis_exporter['enable'] = false +puma['enable'] = false +gitlab_exporter['enable'] = false + +######################################## +#### Redis ### +######################################## + +## Must be the same in every sentinel node +redis['master_name'] = 'gitlab-redis' + +## The same password for Redis authentication you set up for the master node. +redis['master_password'] = 'YOUR_PASSOWORD' + +## A list of sentinels with `host` and `port` +gitlab_rails['redis_sentinels'] = [ + {'host' => '10.10.1.34', 'port' => 26379}, + {'host' => '10.10.1.35', 'port' => 26379}, + {'host' => '10.10.1.36', 'port' => 26379}, + ] + +####################################### +### Gitaly ### +####################################### + +git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly:8075' }, +}) +gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + +####################################### +### Postgres ### +####################################### +gitlab_rails['db_host'] = '10.10.1.30' +gitlab_rails['db_password'] = 'YOUR_PASSOWORD' +gitlab_rails['db_port'] = '5432' +gitlab_rails['db_adapter'] = 'postgresql' +gitlab_rails['db_encoding'] = 'unicode' +gitlab_rails['auto_migrate'] = false + +####################################### +### Sidekiq configuration ### +####################################### +sidekiq['listen_address'] = "10.10.1.48" + +####################################### +### Monitoring configuration ### +####################################### +consul['enable'] = true +consul['monitoring_service_discovery'] = true + +consul['configuration'] = { + bind_addr: '10.10.1.48', + retry_join: %w(10.10.1.34 10.10.1.35 10.10.1.36) +} + +# Set the network addresses that the exporters will listen on +node_exporter['listen_address'] = '10.10.1.48:9100' + +# Rails Status for prometheus +gitlab_rails['monitoring_whitelist'] = ['10.10.1.42', '127.0.0.1'] +``` + +## Further reading[](#further-reading "Permalink") + +相关的 Sidekiq 配置: + +1. [Extra Sidekiq processes](../operations/extra_sidekiq_processes.html) +2. [Using the GitLab-Sidekiq chart](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/) \ No newline at end of file diff --git a/docs/438.md b/docs/438.md new file mode 100644 index 0000000000000000000000000000000000000000..6190ae279d6443debe4f3c2511eb1a5e6536121f --- /dev/null +++ b/docs/438.md @@ -0,0 +1,120 @@ +# Admin Area settings + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/settings/](https://docs.gitlab.com/ee/user/admin_area/settings/) + +* [General](#general) +* [Integrations](#integrations) +* [Repository](#repository) +* [Templates](#templates-premium-only) +* [CI/CD](#cicd) +* [Reporting](#reporting) +* [Metrics and profiling](#metrics-and-profiling) +* [Network](#network) +* [Geo](#geo) +* [Preferences](#preferences) + +# Admin Area settings[](#admin-area-settings-core-only "Permalink") + +作为 GitLab 自我管理实例的管理员,您可以管理部署的行为. 为此,请选择 **管理区域>设置** . + +在 GitLab.com 上无法访问管理区域,并且只能由 GitLab.com 管理员更改设置. 有关 GitLab.com 实例上的所有当前设置和限制,请参阅[GitLab.com 设置](../../gitlab_com/index.html)文档. + +## General[](#general "Permalink") + +通过导航到来访问管理区域设置的默认页面 **管理区域>设置>常规** : + +| Option | Description | +| --- | --- | +| [Visibility and access controls](visibility_and_access_controls.html) | 设置默认值并限制可见性级别. 配置导入源和 Git 访问协议. | +| [Account and limit](account_and_limit_settings.html) | 设置项目和最大大小限制,会话持续时间,用户选项,并检查名称空间计划的功能可用性. | +| [Diff limits](../diff_limits.html) | 差异含量限制. | +| [Sign-up restrictions](sign_up_restrictions.html) | 配置用户创建新帐户的方式. | +| [Sign in restrictions](sign_in_restrictions.html) | 设置用户登录要求. 启用强制性两因素身份验证. | +| [Terms of Service and Privacy Policy](terms.html) | 包括所有用户必须接受的服务条款协议和隐私政策. | +| [External Authentication](external_authorization.html#configuration) | 外部分类政策授权 | +| [Web terminal](../../../administration/integration/terminal.html#limiting-websocket-connection-time) | 设置 Web 终端的最大会话时间. | +| [Web IDE](../../project/web_ide/index.html#enabling-live-preview) | 管理 Web IDE 功能. | + +## Integrations[](#integrations "Permalink") + +| Option | Description | +| --- | --- | +| [Elasticsearch](../../../integration/elasticsearch.html#enabling-elasticsearch) | Elasticsearch 集成. Elasticsearch AWS IAM. | +| [PlantUML](../../../administration/integration/plantuml.html#gitlab) | 允许在 AsciiDoc 文档中呈现 PlantUML 图. | +| [Slack application](../../../user/project/integrations/gitlab_slack_application.html#configuration) | Slack 集成使您可以通过聊天窗口中的斜杠命令与 GitLab 进行交互. 此选项仅在 GitLab.com 上可用,尽管[将来](https://gitlab.com/gitlab-org/gitlab/-/issues/28164)可能会[用于自我管理的实例](https://gitlab.com/gitlab-org/gitlab/-/issues/28164) . | +| [Third party offers](third_party_offers.html) | 控制第三方报价的显示. | +| [Snowplow](../../../development/telemetry/snowplow.html) | 配置 Snowplow 集成. | +| [Google GKE](../../project/clusters/add_gke_clusters.html) | Google GKE 集成使您可以从 GitLab 配置 GKE 集群. | +| [Amazon EKS](../../project/clusters/add_eks_clusters.html) | Amazon EKS 集成允许您从 GitLab 预置 EKS 集群. | + +## Repository[](#repository "Permalink") + +| Option | Description | +| --- | --- | +| [Repository’s custom initial branch name](../../project/repository/branches/index.html#custom-initial-branch-name-core-only) | 为您实例中创建的所有新存储库设置一个自定义分支名称而不是 master. | +| [Repository mirror](visibility_and_access_controls.html#allow-mirrors-to-be-set-up-for-projects) | 配置存储库镜像. | +| [Repository storage](../../../administration/repository_storage_types.html) | 配置存储路径设置. | +| 仓库维护 | ( [存储库检查](../../../administration/repository_checks.html)和[内务处理](../../../administration/housekeeping.html) ). 在存储库上配置自动 Git 检查和内务处理. | +| [Repository static objects](../../../administration/static_objects_external_storage.html) | 从外部存储(例如 CDN)提供存储库静态对象(例如,归档文件,blob 等). | + +## Templates[](#templates-premium-only "Permalink") + +| Option | Description | +| --- | --- | +| [Templates](instance_template_repository.html#configuration) | 设置实例范围的模板存储库. | +| [Custom project templates](../custom_project_templates.html) | 选择自定义项目模板源组. | + +## CI/CD[](#cicd "Permalink") + +| Option | Description | +| --- | --- | +| [Continuous Integration and Deployment](continuous_integration.html) | Auto DevOps,跑步者和工作工件. | +| [Required pipeline configuration](continuous_integration.html#required-pipeline-configuration-premium-only) | 设置实例范围的自动包含[管道配置](../../../ci/yaml/README.html) . 该管道配置将在项目自己的配置之后运行. | +| [Package Registry](continuous_integration.html#package-registry-configuration-premium-only) | 与使用 GitLab 的 Package Registry 的使用和体验有关的设置. 请注意,启用其中一些设置会[涉及风险](./../../packages/container_registry/index.html#use-with-external-container-registries) . | + +## Reporting[](#reporting "Permalink") + +| Option | Description | +| --- | --- | +| [Spam and Anti-bot Protection](../../../integration/recaptcha.html) | 启用 reCAPTCHA 或 Akismet 并设置 IP 限制. 对于 reCAPTCHA,我们目前仅支持[v2](https://developers.google.com/recaptcha/docs/versions) . | +| [Abuse reports](../abuse_reports.html) | 为滥用情况报告设置通知电子邮件. | + +## Metrics and profiling[](#metrics-and-profiling "Permalink") + +| Option | Description | +| --- | --- | +| [Metrics - Prometheus](../../../administration/monitoring/prometheus/gitlab_metrics.html) | 启用和配置 Prometheus 指标. | +| [Metrics - Grafana](../../../administration/monitoring/performance/grafana_configuration.html#integration-with-gitlab-ui) | 启用并配置 Grafana. | +| [Profiling - Performance bar](../../../administration/monitoring/performance/performance_bar.html#enable-the-performance-bar-via-the-admin-panel) | 启用对给定组的性能栏的访问. | +| [Self monitoring](../../../administration/monitoring/gitlab_self_monitoring_project/index.html#creating-the-self-monitoring-project) | Enable or disable instance self monitoring. | +| [Usage statistics](usage_statistics.html) | 启用或禁用版本检查和用法 ping. | +| [Pseudonymizer data collection](../../../administration/pseudonymizer.html) | 启用或禁用 Pseudonymizer 数据收集. | + +## Network[](#network "Permalink") + +| Option | Description | +| --- | --- | +| 性能优化 | [写入" authorized_keys"文件,](../../../administration/operations/fast_ssh_key_lookup.html#setting-up-fast-lookup-via-gitlab-shell)并执行[Push 事件活动限制和批量 push 事件](push_event_activities_limit.html) . 影响 GitLab 性能的各种设置. | +| [User and IP rate limits](user_and_ip_rate_limits.html) | 配置 Web 和 API 请求的限制. | +| [Outbound requests](../../../security/webhooks.html) | 允许从挂钩和服务到本地网络的请求. | +| [Protected Paths](protected_paths.html) | 配置路径以受机架攻击保护. | +| [Incident Management](../../incident_management/index.html) Limits | 配置可以发送到项目的入站警报数量的限制. | + +## Geo[](#geo "Permalink") + +| Option | Description | +| --- | --- | +| Geo | Geo 允许您将 GitLab 实例复制到其他地理位置. 重定向到 **管理区>** **地理位置>** **设置** ,并且将不再提供 **管理区>** **设置>** [GitLab 13.0 中的](https://gitlab.com/gitlab-org/gitlab/-/issues/36896) **Geo** . | + +## Preferences[](#preferences "Permalink") + +| Option | Description | +| --- | --- | +| [Email](email.html) | 各种电子邮件设置. | +| [Help page](../../../customization/help_message.html) | 帮助页面文本和支持页面 URL. | +| [Pages](../../../administration/pages/index.html#custom-domain-verification) | 静态网站的大小和域设置 | +| [Real-time features](../../../administration/polling.html) | 更改此值可影响 GitLab UI 轮询更新的频率. | +| [Gitaly timeouts](gitaly_timeouts.html) | 配置 Gitaly 超时. | +| Localization | [Default first day of the week](../../profile/preferences.html) and [Time tracking](../../project/time_tracking.html#limit-displayed-units-to-hours-core-only). | + +**注意:**您可以在**管理区域>设置>首选项**的**本地化**部分中更改整个 GitLab 实例的[默认一周的第一天](../../profile/preferences.html) . \ No newline at end of file diff --git a/docs/439.md b/docs/439.md new file mode 100644 index 0000000000000000000000000000000000000000..bd19b706ee07b8849faff9affab90e5bd74479bd --- /dev/null +++ b/docs/439.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/customization/](https://docs.gitlab.com/ee/customization/) \ No newline at end of file diff --git a/docs/440.md b/docs/440.md new file mode 100644 index 0000000000000000000000000000000000000000..8c27a7c0555f93822b0111dd75e91e4432d3bea7 --- /dev/null +++ b/docs/440.md @@ -0,0 +1,164 @@ +# Continuous Integration and Deployment Admin settings + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html) + +* [Auto DevOps](#auto-devops-core-only) +* [Maximum artifacts size](#maximum-artifacts-size-core-only) +* [Default artifacts expiration](#default-artifacts-expiration-core-only) +* [Shared Runners pipeline minutes quota](#shared-runners-pipeline-minutes-quota-starter-only) +* [Archive jobs](#archive-jobs-core-only) +* [Default CI configuration path](#default-ci-configuration-path) +* [Required pipeline configuration](#required-pipeline-configuration-premium-only) +* [Package Registry configuration](#package-registry-configuration-premium-only) + +# Continuous Integration and Deployment Admin settings[](#continuous-integration-and-deployment-admin-settings-core-only "Permalink") + +在此区域中,您将找到 Auto DevOps,Runners 和作业工件的设置. 您可以在**管理区域>设置> CI / CD 中**找到它. + +[![Admin Area settings button](img/7355fc1627be101cc5ed59387d36b6a3.png)](../img/admin_area_settings_button.png) + +## Auto DevOps[](#auto-devops-core-only "Permalink") + +要为所有项目启用(或禁用) [Auto DevOps](../../../topics/autodevops/index.html) : + +1. 转到**管理区域>设置> CI / CD** . +2. 选中(或取消选中以禁用) **所有项目的默认为 Auto DevOps 管道**的框. +3. (可选)设置将用于 Auto Deploy 和 Auto Review Apps 的[Auto DevOps 基本域](../../../topics/autodevops/index.html#auto-devops-base-domain) . +4. 点击**保存更改**以使更改生效. + +从现在开始,每个不带`.gitlab-ci.yml`现有项目和新创建的项目都将使用 Auto DevOps 管道. + +如果要为特定项目禁用它,可以在[其设置中](../../../topics/autodevops/index.html#enablingdisabling-auto-devops)禁用它. + +## Maximum artifacts size[](#maximum-artifacts-size-core-only "Permalink") + +可以将[作业工件](../../../administration/job_artifacts.html)的最大大小设置为: + +* 实例级别. +* [从 GitLab 12.4 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/21688) ,为项目和组级别. + +值是: + +* 以*MB*为单位,每个作业的默认值为 100MB. +* 在 GitLab.com 上[设置为 1G](../../gitlab_com/index.html#gitlab-cicd) . + +要在以下位置进行更改: + +* 实例级别: + + 1. Go to **管理区域>设置> CI / CD**. + 2. 更改最大工件大小的值(以 MB 为单位). + 3. 单击**保存更改**以使更改生效. +* [组级别](../../group/index.html#group-settings) (这将覆盖实例设置): + + 1. 转到组的**设置> CI / CD>常规管道** . + 2. 更改**最大工件大小**的值**(以 MB 为单位)** . + 3. 单击**保存更改**以使更改生效. +* [项目级别](../../../ci/pipelines/settings.html) (这将覆盖实例和组设置): + + 1. 转到项目的**设置> CI / CD>常规管道** . + 2. 更改**最大工件大小**的值**(以 MB 为单位)** . + 3. 单击**保存更改**以使更改生效. + +**注意:**所有级别的设置仅对 GitLab 管理员可用. + +## Default artifacts expiration[](#default-artifacts-expiration-core-only "Permalink") + +可以在 GitLab 实例的"管理区域"中设置[作业工件](../../../administration/job_artifacts.html)的默认过期时间. 持续时间的语法在[`artifacts:expire_in`](../../../ci/yaml/README.html#artifactsexpire_in)描述,缺省值为`30 days` . + +1. 转到**管理区域>设置> CI / CD** . +2. 更改默认到期时间的值. +3. 单击**保存更改**以使更改生效. + +此设置是[`.gitlab-ci.yml`](../../../ci/yaml/README.html#artifactsexpire_in)每个作业设置的,可以在[`.gitlab-ci.yml`](../../../ci/yaml/README.html#artifactsexpire_in)覆盖. 要禁用到期时间,请将其设置为`0` . 默认单位是秒. + +**注意:**对此设置的任何更改将仅适用于新工件. 更改此设置之前创建的工件的过期时间将不会更新. 管理员可能需要手动搜索并终止先前创建的工件,如[故障排除文档中所述](../../../administration/troubleshooting/gitlab_rails_cheat_sheet.html#remove-artifacts-more-than-a-week-old) . + +## Shared Runners pipeline minutes quota[](#shared-runners-pipeline-minutes-quota-starter-only "Permalink") + +在 GitLab Starter 8.16 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1078) . + +如果已为 GitLab 实例启用共享运行程序,则可以通过设置组每月可以在共享运行程序上使用的最大管道分钟数来限制其使用. 将此设置为`0` (默认值)将授予无限制的管道分钟数. 尽管构建限制以分钟存储,但计数以秒为单位. 使用情况会在每个月的第一天重置. 在 GitLab.com 上,配额是根据您的[订阅计划](https://about.gitlab.com/pricing/#gitlab-com)计算的. + +要更改管道分钟配额: + +1. 转到**管理区域>设置> CI / CD** . +2. Expand **持续集成和部署**. +3. 在" **管道分钟数"配额**框中,输入最大分钟数. +4. 单击**保存更改**以使更改生效. + +* * * + +尽管"管理区域"中的设置具有全局作用,但作为管理员,您也可以更改每个组的管道分钟配额以覆盖全局值. + +1. 导航到" **管理区域">"概述">"组",**然后单击您要更改管道分钟配额的组的" **编辑"**按钮. +2. 在" **管道分钟配额"**框中,输入最大分钟数. +3. 单击**保存更改**以使更改生效. + +保存后,您可以在组管理员视图中查看构建配额. 如果启用了共享运行器,也可以在项目管理视图中查看配额. + +[![Project admin information](img/a33f8dce89b50020e90de33ed9a1e78e.png)](img/admin_project_quota_view.png) + +您可以在组页面设置列表可用的" **使用配额"**页面中查看该组所有项目的管道分钟配额的概述. + +[![Group pipelines quota](img/a9b252d8a3c25b1c5166799c2233c569.png)](img/group_pipelines_quota.png) + +## Archive jobs[](#archive-jobs-core-only "Permalink") + +归档作业通过删除作业的某些功能(运行作业所需的元数据)来减少系统上的 CI / CD 占用空间,但保留迹线和工件以供审核时很有用. + +设置作业将被视为过期和过期的持续时间: + +1. 转到**管理区域>设置> CI / CD** . +2. 展开**持续集成和部署**部分. +3. 设置**存档作业**的值. +4. 点击**保存更改**以使更改生效. + +一旦超过该时间,作业将被存档,并且不再能够重试. 将其设为空以永不过期作业. 它必须不少于 1 天,例如: `15 days` , `1 month` , `2 years` . + +截至 2020 年 6 月 22 日,该[值](../../gitlab_com/index.html#gitlab-cicd)在 GitLab.com 上[设置](../../gitlab_com/index.html#gitlab-cicd)为 3 个月. 在此日期之前创建的作业将在 2020 年 9 月 22 日之后存档. + +## Default CI configuration path[](#default-ci-configuration-path "Permalink") + +在 GitLab 12.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18073) . + +可以在您的 GitLab 实例的"管理"区域中设置新项目的默认 CI 配置文件路径(如果未设置, `.gitlab-ci.yml` ): + +1. 转到**管理区域>设置> CI / CD** . +2. 在**默认 CI 配置路径**字段中输入新路径. +3. 点击**保存更改**以使更改生效. + +也可以[为特定项目](../../../ci/pipelines/settings.html#custom-ci-configuration-path)指定[自定义 CI 配置路径](../../../ci/pipelines/settings.html#custom-ci-configuration-path) . + +## Required pipeline configuration[](#required-pipeline-configuration-premium-only "Permalink") + +**警告:**此功能正在重新评估,以支持其他[合规性解决方案](https://gitlab.com/gitlab-org/gitlab/-/issues/34830) . 我们建议尚未实施此功能的用户等待新解决方案. + +GitLab 管理员可以强制管道配置在每个管道上运行. + +该配置适用于 GitLab 实例的所有管道,其来源为: + +* The [instance template repository](instance_template_repository.html). +* GitLab 提供的配置. + +设置所需的管道配置: + +1. 转到**管理区域>设置> CI / CD** . +2. 展开" **所需管道配置"**部分. +3. 从提供的下拉列表中选择所需的配置. +4. Click **保存更改**. + +[![Required pipeline](img/ad8ac82c77beb415e901040df8d93b17.png)](img/admin_required_pipeline.png) + +## Package Registry configuration[](#package-registry-configuration-premium-only "Permalink") + +GitLab 管理员可以禁用将 NPM 请求转发到[npmjs.com](https://s0www0npmjs0com.icopy.site/) . + +To disable it: + +1. 转到**管理区域>设置> CI / CD** . +2. 展开" **程序包注册表"**部分. +3. Uncheck **启用将 NPM 软件包请求转发到 npmjs.org**. +4. Click **保存更改**. + +[![NPM package requests forwarding](img/8e301ace1928e93f6138075596994c18.png)](img/admin_package_registry_npm_package_requests_forward.png) \ No newline at end of file diff --git a/docs/441.md b/docs/441.md new file mode 100644 index 0000000000000000000000000000000000000000..6d00ad8dff9cb846796e2b250a1e33cddf2f1052 --- /dev/null +++ b/docs/441.md @@ -0,0 +1,31 @@ +# Custom instance-level project templates + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/custom_project_templates.html](https://docs.gitlab.com/ee/user/admin_area/custom_project_templates.html) + +* [Configuring](#configuring) + +# Custom instance-level project templates[](#custom-instance-level-project-templates-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6860) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2. + +GitLab 管理员可以配置所有自定义项目模板的来源组. + +如果用户有权访问组命名空间下的每个项目,则它们将对用户可用. 例如: + +* 组中的公共项目将对每个登录用户可用. +* 仅当用户是项目成员时,私有项目才可用. + +复制到每个新项目的存储库和数据库信息与使用[GitLab 的项目导入/导出导出](../project/settings/import_export.html)的数据相同. + +**注意:**要在组级别设置项目模板,请参阅[自定义组级别项目模板](../group/custom_project_templates.html) . + +## Configuring[](#configuring "Permalink") + +GitLab 管理员可以通过以下方式配置一个 GitLab 组作为整个 GitLab 实例的模板源: + +1. 导航到**管理区域>设置>模板** . +2. Expanding **自定义项目模板**. +3. 选择要使用的组. +4. Pressing **保存更改**. + +**注意:** **不**支持模板组子组下的项目. \ No newline at end of file diff --git a/docs/442.md b/docs/442.md new file mode 100644 index 0000000000000000000000000000000000000000..5096c54f1091584f603b92e887bfa962af25ae8c --- /dev/null +++ b/docs/442.md @@ -0,0 +1,24 @@ +# Diff limits administration + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/diff_limits.html](https://docs.gitlab.com/ee/user/admin_area/diff_limits.html) + +* [Maximum diff patch size](#maximum-diff-patch-size) + +# Diff limits administration[](#diff-limits-administration-core-only "Permalink") + +您可以设置差异文件(补丁)显示的最大大小. + +有关差异文件的详细信息,请[查看文件之间的更改](../project/merge_requests/reviewing_and_managing_merge_requests.html#view-changes-between-file-versions) . + +## Maximum diff patch size[](#maximum-diff-patch-size "Permalink") + +超过此值的差异文件将显示为"太大",并且无法扩展. 将显示到斑点视图的链接,而不是展开视图. + +大于此大小的 10%的修补程序将自动折叠,并且将显示扩展差异的链接. + +**注意:**合并请求和分支比较视图将受到影响.**警告:**此设置是实验性的. 增加的最大值将增加实例的资源消耗. 调整最大值时请记住这一点. + +1. 转到**管理区域>设置>常规** . +2. Expand **差异限制**. +3. 输入**最大差异补丁大小**的值,以字节为单位. +4. 点击**保存更改** . \ No newline at end of file diff --git a/docs/443.md b/docs/443.md new file mode 100644 index 0000000000000000000000000000000000000000..5d16b0e9f62716d943a312b88d3c1309154830a9 --- /dev/null +++ b/docs/443.md @@ -0,0 +1,41 @@ +# Email + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/settings/email.html](https://docs.gitlab.com/ee/user/admin_area/settings/email.html) + +* [Custom logo](#custom-logo) +* [Custom additional text](#custom-additional-text-premium-only) +* [Custom hostname for private commit emails](#custom-hostname-for-private-commit-emails) + +# Email[](#email-core-only "Permalink") + +您可以自定义 GitLab 实例发送的电子邮件中的某些内容. + +## Custom logo[](#custom-logo "Permalink") + +可以自定义某些电子邮件标题中的[徽标](../appearance.html#navigation-bar) ,请参阅[徽标自定义部分](../appearance.html#navigation-bar) . + +## Custom additional text[](#custom-additional-text-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5031) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.7. + +附加文本将出现在任何电子邮件的底部,并且可出于法律/审核/合规性原因使用. + +1. 转到**管理区域>设置>首选项** ( `/admin/application_settings/preferences` ). +2. 展开**电子邮件**部分. +3. 在**其他文本**字段中输入您的文本. +4. Click **Save**. + +## Custom hostname for private commit emails[](#custom-hostname-for-private-commit-emails "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22560) . + +此配置选项设置[专用提交电子邮件](../../profile/index.html#private-commit-email)的电子邮件主机名. 默认情况下,它设置为`users.noreply.YOUR_CONFIGURED_HOSTNAME` . + +为了更改此选项: + +1. 转到**管理区域>设置>首选项** ( `/admin/application_settings/preferences` ). +2. 展开**电子邮件**部分. +3. 在" **自定义主机名(用于私人提交电子邮件)"**字段中输入所需的主机**名** . +4. Click **保存更改**. + +**注意:**一旦配置了主机名,GitLab 将无法识别使用先前主机名的每封私人提交电子邮件. 这可能会与某些[Push 规则](../../../push_rules/push_rules.html)直接冲突,例如, `Check whether author is a GitLab user`以及`Check whether committer is the current authenticated user` . \ No newline at end of file diff --git a/docs/444.md b/docs/444.md new file mode 100644 index 0000000000000000000000000000000000000000..ff7ffd6c54fa06618a3ac1d74442a127f631e100 --- /dev/null +++ b/docs/444.md @@ -0,0 +1,117 @@ +# Enable and disable GitLab features deployed behind feature flags + +> 原文:[https://docs.gitlab.com/ee/administration/feature_flags.html](https://docs.gitlab.com/ee/administration/feature_flags.html) + +* [How to enable and disable features behind flags](#how-to-enable-and-disable-features-behind-flags) + * [Start the GitLab Rails console](#start-the-gitlab-rails-console) + * [Enable or disable the feature](#enable-or-disable-the-feature) + +# Enable and disable GitLab features deployed behind feature flags[](#enable-and-disable-gitlab-features-deployed-behind-feature-flags-core-only "Permalink") + +GitLab 采用[功能标记策略](../development/feature_flags/index.html)在开发的早期阶段部署功能,以便可以逐步推出它们. + +在使它们永久可用之前,出于[多种原因](../development/feature_flags/process.html#when-to-use-feature-flags) ,可以将功能部署在标志的后面,例如: + +* 测试功能. +* 在功能开发的早期阶段获得用户和客户的反馈. +* 评估用户采用率. +* 评估它如何影响 GitLab 的性能. +* 在整个发行版中以较小的部分构建它. + +标记后面的功能通常可以逐步推出: + +1. 默认情况下,该功能开始禁用. +2. 该功能默认情况下处于启用状态. +3. 功能标记已删除. + +可以启用和禁用这些功能,以允许或禁止用户使用它们. GitLab 管理员可以访问 GitLab Rails 控制台来完成此操作. + +如果您使用了某个功能并发现了错误,不正常行为或错误,那么尽快向 GitLab [**提供反馈**](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue[title]=Docs - feature flag feedback: Feature Name&issue[description]=Describe the problem you've encountered. + + + +/label ~)非常重要,这样我们就可以在标记后改进或修复它. 当您将 GitLab 升级到早期版本时,功能标志状态可能会更改. + +**注意:请**注意,部署在功能标记后面的功能可能尚未准备好用于生产. 但是,禁用默认情况下已启用的已部署标志后面的功能也可能带来风险. 如果启用了它们,我们建议您保持原样. + +## How to enable and disable features behind flags[](#how-to-enable-and-disable-features-behind-flags "Permalink") + +每个功能都有其自己的标志,应使用该标志来启用和禁用它. 标志后面的每个功能的文档都包括一个部分,通知标志的状态以及启用或禁用标志的命令. + +### Start the GitLab Rails console[](#start-the-gitlab-rails-console "Permalink") + +启用或禁用标志后面的功能的第一件事是在 GitLab Rails 控制台上启动会话. + +对于所有安装; + +``` +sudo gitlab-rails console +``` + +对于源安装: + +``` +sudo -u git -H bundle exec rails console -e production +``` + +有关详细信息,请参见[启动 Rails 控制台会话](troubleshooting/debug.html#starting-a-rails-console-session) . + +### Enable or disable the feature[](#enable-or-disable-the-feature "Permalink") + +一旦启动 Rails 控制台会话,请相应地运行`Feature.enable`或`Feature.disable`命令. 特定标志可以在功能文档中找到. + +要启用功能,请运行: + +``` +Feature.enable(:) +``` + +例如,启用证据收集: + +``` +Feature.enable(:release_evidence_collection) +``` + +要禁用功能,请运行: + +``` +Feature.disable(:) +``` + +Example, to disable Evidence Collection: + +``` +Feature.disable(:release_evidence_collection) +``` + +可以基于每个项目启用或禁用某些功能标志: + +``` +Feature.enable(:, Project.find()) +``` + +例如,要为项目`1234`启用[`:junit_pipeline_view`](../ci/junit_test_reports.html#enabling-the-junit-test-reports-feature-core-only)功能标记: + +``` +Feature.enable(:junit_pipeline_view, Project.find(1234)) +``` + +`Feature.enable`和`Feature.disable`始终返回`nil` ,这并不表示命令失败: + +``` +irb(main):001:0> Feature.enable(:release_evidence_collection) +=> nil +``` + +要检查标志是启用还是禁用,可以使用`Feature.enabled?` 或`Feature.disabled?` : + +``` +Feature.enable(:release_evidence_collection) +=> nil +Feature.enabled?(:release_evidence_collection) +=> true +Feature.disabled?(:release_evidence_collection) +=> false +``` + +功能就绪后,GitLab 将删除功能标志,启用和禁用该功能的选项将不再存在,并且该功能将在所有实例中可用. \ No newline at end of file diff --git a/docs/445.md b/docs/445.md new file mode 100644 index 0000000000000000000000000000000000000000..ac53b49d07cb51103e42f29e6ebc99d37745e0de --- /dev/null +++ b/docs/445.md @@ -0,0 +1,62 @@ +# Geo nodes Admin Area + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/geo_nodes.html](https://docs.gitlab.com/ee/user/admin_area/geo_nodes.html) + +* [Common settings](#common-settings) +* [**Secondary** node settings](#secondary-node-settings) +* [Geo backfill](#geo-backfill) +* [Using a different URL for synchronization](#using-a-different-url-for-synchronization) +* [Multiple secondary nodes behind a load balancer](#multiple-secondary-nodes-behind-a-load-balancer) + +# Geo nodes Admin Area[](#geo-nodes-admin-area-premium-only "Permalink") + +您可以为 GitLab Geo 节点配置各种设置. 有关更多信息,请参阅[地理文档](../../administration/geo/replication/index.html) . + +在主节点上,转到" **管理区域">"地理位置"** . 在辅助节点上,转到" **管理区域">"地理位置">"节点"** . + +## Common settings[](#common-settings "Permalink") + +所有地理节点均具有以下设置: + +| Setting | Description | +| --- | --- | +| Primary | 这会将地理节点标记为**主要**节点. 只能有一个**主**节点. 确保首先添加**主**节点,然后再添加所有其他节点. | +| Name | 地理节点的唯一标识符. 必须与`gitlab_rails['geo_node_name']`中的设置`gitlab_rails['geo_node_name']`相`/etc/gitlab/gitlab.rb` . 该设置默认为`external_url`并带有斜杠. | +| URL | 实例的面向用户的 URL. | + +您正在读取的节点带有绿色的`Current node`标签, **主**节点被赋予蓝色的`Primary`标签. 请记住,您只能在**主**节点上进行更改! + +## **Secondary** node settings[](#secondary-node-settings "Permalink") + +**辅助**节点具有许多可用的其他设置: + +| Setting | Description | +| --- | --- | +| 选择性同步 | 为此**辅助**节点启用地理位置[选择性同步](../../administration/geo/replication/configuration.html#selective-synchronization) . | +| 储存库同步容量 | 回填存储库时,此**辅助**节点将向**主**节点发出的并发请求数. | +| File sync capacity | 回填文件时,此**辅助**节点将向**主**节点发出的并发请求数. | + +## Geo backfill[](#geo-backfill "Permalink") + +**二级**节点通知由**主**节点更改存储库和文件,并总是试图对这些变化尽快同步. + +回填是使用**辅助**节点添加到数据库*之前*存在的存储库和文件填充**辅助**节点的操作. 由于可能存在大量的存储库和文件,因此一次尝试全部下载它们是不可行的,因此,GitLab 对这些操作的并发性设置了上限. + +回填所需的时间是最大并发的函数,但是值越高, **主**节点上的负担就越大. 从[GitLab 10.2 开始](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3107) ,限制是可配置的. 如果**主**节点有很多剩余容量,则可以增加值以在更短的时间内完成回填. 如果它的负载很重,回填会降低其正常请求的可用性,则可以减少这些请求. + +## Using a different URL for synchronization[](#using-a-different-url-for-synchronization "Permalink") + +**次要**节点使用**主**节点的内部 URL 与之联系(例如,同步存储库). 内部 URL 名称将其与用户使用的[外部](https://docs.gitlab.com/omnibus/settings/configuration.html) URL 区别开来. 内部 URL 不必是私有地址. + +内部 URL 默认为外部 URL,但是您可以在**管理区域>地理位置>节点**下对其进行自定义. + +**警告:**我们建议在配置 Geo 节点时使用 HTTPS 连接. 为了避免在使用 HTTPS 时中断**主**节点和**辅助**节点之间的通信,请自定义内部 URL 以指向负载均衡器,且 TLS 终止于负载均衡器. + +## Multiple secondary nodes behind a load balancer[](#multiple-secondary-nodes-behind-a-load-balancer "Permalink") + +在 GitLab 11.11 中,只要为每个地理节点设置了唯一的`name` , **辅助**节点就可以使用相同的外部 URL. `gitlab.rb`设置`gitlab_rails['geo_node_name']`必须: + +* 为每个运行`unicorn` , `sidekiq`或`geo_logcursor` GitLab 实例设置. +* 匹配地理节点名称. + +负载平衡器必须使用粘性会话,以避免身份验证失败和跨站点请求错误. \ No newline at end of file diff --git a/docs/446.md b/docs/446.md new file mode 100644 index 0000000000000000000000000000000000000000..4da770c104a751045349dc9ede48803c15fec437 --- /dev/null +++ b/docs/446.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/administration/lfs/lfs_administration.html](https://docs.gitlab.com/ee/administration/lfs/lfs_administration.html) \ No newline at end of file diff --git a/docs/447.md b/docs/447.md new file mode 100644 index 0000000000000000000000000000000000000000..a893714d0b50214f135043c054c01f124adb7f10 --- /dev/null +++ b/docs/447.md @@ -0,0 +1,566 @@ +# GitLab Pages administration + +> 原文:[https://docs.gitlab.com/ee/administration/pages/](https://docs.gitlab.com/ee/administration/pages/) + +* [Overview](#overview) +* [Prerequisites](#prerequisites) + * [Add the domain to the Public Suffix List](#add-the-domain-to-the-public-suffix-list) + * [DNS configuration](#dns-configuration) +* [Configuration](#configuration) + * [Wildcard domains](#wildcard-domains) + * [Wildcard domains with TLS support](#wildcard-domains-with-tls-support) + * [Additional configuration for Docker container](#additional-configuration-for-docker-container) + * [Global settings](#global-settings) +* [Advanced configuration](#advanced-configuration) + * [Custom domains](#custom-domains) + * [Custom domains with TLS support](#custom-domains-with-tls-support) + * [Custom domain verification](#custom-domain-verification) + * [Let’s Encrypt integration](#lets-encrypt-integration) + * [Access control](#access-control) + * [Disabling public access to all Pages websites](#disabling-public-access-to-all-pages-websites) + * [Running behind a proxy](#running-behind-a-proxy) + * [Using a custom Certificate Authority (CA)](#using-a-custom-certificate-authority-ca) +* [Activate verbose logging for daemon](#activate-verbose-logging-for-daemon) +* [Change storage path](#change-storage-path) +* [Configure listener for reverse proxy requests](#configure-listener-for-reverse-proxy-requests) +* [Set maximum pages size](#set-maximum-pages-size) + * [Override maximum pages size per project or group](#override-maximum-pages-size-per-project-or-group-premium-only) +* [Running GitLab Pages on a separate server](#running-gitlab-pages-on-a-separate-server) +* [Backup](#backup) +* [Security](#security) +* [Troubleshooting](#troubleshooting) + * [`open /etc/ssl/ca-bundle.pem: permission denied`](#open-etcsslca-bundlepem-permission-denied) + * [`dial tcp: lookup gitlab.example.com` and `x509: certificate signed by unknown authority`](#dial-tcp-lookup-gitlabexamplecom-and-x509-certificate-signed-by-unknown-authority) + * [404 error after transferring project to a different group or user](#404-error-after-transferring-project-to-a-different-group-or-user) + +# GitLab Pages administration[](#gitlab-pages-administration "Permalink") + +版本历史 + +* 在 GitLab EE 8.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80) . +* GitLab EE 8.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173)了具有 TLS 支持的自定义 CNAME. +* GitLab 页面[已移植](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14605)到 GitLab 8.17 中的 Community Edition. +* 在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30548)了对子组项目网站的支持. + +GitLab 页面允许托管静态站点. 它必须由管理员配置. 提供了单独的[用户文档](../../user/project/pages/index.html) . + +**注意:**本指南适用于 Omnibus GitLab 安装. 如果您从源代码安装了 GitLab,请参见[GitLab 页面管理以了解源代码安装](source.html) . + +## Overview[](#overview "Permalink") + +GitLab Pages 使用[GitLab Pages 守护程序](https://gitlab.com/gitlab-org/gitlab-pages) ,这是一个用 Go 编写的简单 HTTP 服务器,可以侦听外部 IP 地址并提供对自定义域和自定义证书的支持. 它通过 SNI 支持动态证书,并且默认情况下使用 HTTP2 公开页面. 我们鼓励您阅读其[自述文件](https://gitlab.com/gitlab-org/gitlab-pages/blob/master/README.md)以全面了解其工作原理. + +对于[自定义域](#custom-domains) (而不是[通配符域](#wildcard-domains) ),Pages 守护程序需要在端口`80`和/或`443` . 因此,设置方式具有一定的灵活性: + +* 在与 GitLab 相同的服务器上运行 Pages 守护程序,侦听**辅助 IP** . +* 在[单独的服务器上](#running-gitlab-pages-on-a-separate-server)运行 Pages 守护程序. 在这种情况下, [Pages 路径](#change-storage-path)也必须存在于安装 Pages 守护程序的服务器中,因此您必须通过网络共享它. +* 在与 GitLab 相同的服务器上运行 Pages 守护程序,侦听相同的 IP,但侦听不同的端口. 在这种情况下,您将不得不使用负载平衡器代理流量. 如果选择该路由,请注意,应将 TCP 负载平衡用于 HTTPS. 如果您使用 TLS 终止(HTTPS 负载平衡),则将无法使用用户提供的证书来提供页面. 对于 HTTP,可以使用 HTTP 或 TCP 负载平衡. + +在本文档中,我们将假设第一个选项继续进行. 如果您不支持自定义域,则不需要辅助 IP. + +## Prerequisites[](#prerequisites "Permalink") + +在进行页面配置之前,您需要: + +1. 具有用于服务 GitLab 页面的专有根域. 请注意,您不能使用 GitLab 实例域的子域. +2. 配置**通配符 DNS 记录** . +3. (可选)如果您决定在 HTTPS 下提供 Pages,则具有该域的**通配符证书** . +4. (可选,但建议使用)启用[共享运行器,](../../ci/runners/README.html)以便您的用户不必自己携带. +5. (仅用于自定义域)具有**辅助 IP** . + +**注意:**如果您的 GitLab 实例和 Pages 守护程序部署在专用网络中或防火墙后面,则只有有权访问专用网络的设备/用户才能访问 GitLab Pages 网站. + +### Add the domain to the Public Suffix List[](#add-the-domain-to-the-public-suffix-list "Permalink") + +浏览器使用" [公共后缀列表"](https://publicsuffix.org)来决定如何对待子域. 如果您的 GitLab 实例允许公众创建 GitLab Pages 网站,那么它还允许这些用户在 pages 域( `example.io` )上创建子域. 将域添加到"公共后缀列表"中可防止浏览器接受[超级 cookie](https://en.wikipedia.org/wiki/HTTP_cookie#Supercookie)等. + +请按照[以下说明](https://publicsuffix.org/submit/)提交您的 GitLab 页面子域. 例如,如果您的域是`example.io` ,则应请求将`example.io`添加到公共后缀列表中. `gitlab.io` [在 2016 年](https://gitlab.com/gitlab-com/infrastructure/-/issues/230)添加了`gitlab.io` . + +### DNS configuration[](#dns-configuration "Permalink") + +GitLab 页面期望在其自己的虚拟主机上运行. 在您的 DNS 服务器/提供程序中,您需要添加[通配符 DNS A 记录](https://en.wikipedia.org/wiki/Wildcard_DNS_record) ,该[记录](https://en.wikipedia.org/wiki/Wildcard_DNS_record)指向 GitLab 运行的主机. 例如,条目如下所示: + +``` +*.example.io. 1800 IN A 192.0.2.1 +*.example.io. 1800 IN AAAA 2001::1 +``` + +其中`example.io`是将在其下提供 GitLab 页面的域, `192.0.2.1`是您的 GitLab 实例的 IPv4 地址,而`2001::1`是 IPv6 地址. 如果没有 IPv6,则可以省略 AAAA 记录. + +**注意:**您不应使用 GitLab 域来服务用户页面. 有关更多信息,请参见[安全性部分](#security) . + +## Configuration[](#configuration "Permalink") + +根据您的需要,您可以通过 4 种不同的方式设置 GitLab 页面. + +从最简单的设置到最高级的设置,列出了以下示例. 绝对最低要求是设置通配符 DNS,因为在所有配置中都需要这样做. + +### Wildcard domains[](#wildcard-domains "Permalink") + +**Requirements:** + +* [Wildcard DNS setup](#dns-configuration) + +* * * + +网址方案: `http://page.example.io` : `http://page.example.io` + +这是可以与 Pages 一起使用的最小设置. 如下所述,它是所有其他设置的基础. NGINX 将把所有请求代理到守护程序. Pages 守护程序不收听外界. + +1. Set the external URL for GitLab Pages in `/etc/gitlab/gitlab.rb`: + + ``` + pages_external_url 'http://example.io' + ``` + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +观看[视频教程](https://youtu.be/dD8c7WNcc6s)以了解此配置. + +### Wildcard domains with TLS support[](#wildcard-domains-with-tls-support "Permalink") + +**Requirements:** + +* [Wildcard DNS setup](#dns-configuration) +* 通配 TLS 证书 + +* * * + +网址方案: `https://page.example.io` : `https://page.example.io` + +NGINX 将把所有请求代理到守护程序. Pages 守护程序不收听外界. + +1. 将证书和密钥放在`/etc/gitlab/ssl` +2. 在`/etc/gitlab/gitlab.rb`指定以下配置: + + ``` + pages_external_url 'https://example.io' + + pages_nginx['redirect_http_to_https'] = true + pages_nginx['ssl_certificate'] = "/etc/gitlab/ssl/pages-nginx.crt" + pages_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/pages-nginx.key" + ``` + + 其中`pages-nginx.crt`和`pages-nginx.key`分别是 SSL 证书和密钥. + +3. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +### Additional configuration for Docker container[](#additional-configuration-for-docker-container "Permalink") + +当它在 Docker 容器中运行时,GitLab Pages 守护程序将没有绑定绑定的权限. 要解决此问题,您需要更改 chroot 行为: + +1. Edit `/etc/gitlab/gitlab.rb`. +2. 将 GitLab 页面的`inplace_chroot`设置为`true` : + + ``` + gitlab_pages['inplace_chroot'] = true + ``` + +3. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +**注意:** `inplace_chroot`选项可能不适用于其他功能,例如[Pages Access Control](#access-control) . [GitLab 页面自述文件](https://gitlab.com/gitlab-org/gitlab-pages#caveats)包含有关警告和解决方法的更多信息. + +### Global settings[](#global-settings "Permalink") + +下表是 Omnibus GitLab 中 Pages 已知的所有配置设置及其作用. 这些选项可以在`/etc/gitlab/gitlab.rb`进行调整,并在[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure)之后生效. 这些设置中的大多数不需要手动配置,除非您需要对 Pages 守护程序在环境中如何运行和提供内容的方式进行更精细的控制. + +| Setting | Description | +| --- | --- | +| `pages_external_url` | 可访问 GitLab 页面的 URL,包括协议(HTTP / HTTPS). 如果使用`https://` ,则还必须设置`gitlab_pages['ssl_certificate']`和`gitlab_pages['ssl_certificate_key']` . | +| `gitlab_pages[]` |   | +| `access_control` | 是否启用[访问控制](index.html#access-control) . | +| `api_secret_key` | 具有用于通过 GitLab API 进行身份验证的密钥的文件的完整路径. 未设置时自动生成. | +| `artifacts_server` | 在 GitLab 页面中启用查看[工件](../job_artifacts.html) . | +| `artifacts_server_timeout` | 对工件服务器的代理请求超时(以秒为单位). | +| `artifacts_server_url` | 用于代理工件请求的 API URL. 默认为 GitLab `external URL` + `/api/v4` ,例如`https://gitlab.com/api/v4` . | +| `auth_redirect_uri` | 用于通过 GitLab 进行身份验证的回调 URL. 默认为`pages_external_url` + `/auth`项目子域. | +| `auth_secret` | Secret key for signing authentication requests. Leave blank to pull automatically from GitLab during OAuth registration. | +| `dir` | 配置和机密文件的工作目录. | +| `enable` | 在当前系统上启用或禁用 GitLab 页面. | +| `external_http` | 将页面配置为绑定到一个或多个辅助 IP 地址,以服务 HTTP 请求. 可以将多个地址以及确切的端口作为数组给出,例如`['1.2.3.4', '1.2.3.5:8063']` . 设置`listen_http`值. | +| `external_https` | 将页面配置为绑定到一个或多个辅助 IP 地址,以服务 HTTPS 请求. 可以将多个地址以及确切的端口作为数组给出,例如`['1.2.3.4', '1.2.3.5:8063']` . 设置`listen_https`值. | +| `gitlab_client_http_timeout` | GitLab API HTTP 客户端连接超时(以秒为单位)(默认值:10s). | +| `gitlab_client_jwt_expiry` | JWT 令牌的到期时间,以秒为单位(默认值:30s). | +| `gitlab_id` | OAuth 应用程序公共 ID. 当 Pages 通过 GitLab 进行身份验证时,请保留空白以自动填充. | +| `gitlab_secret` | OAuth 应用程序密码. 当 Pages 通过 GitLab 进行身份验证时,请保留空白以自动填充. | +| `gitlab_server` | 启用访问控制时用于身份验证的服务器; 默认为 GitLab `external_url` . | +| `headers` | 指定应随每个响应发送给客户端的任何其他 http 标头. | +| `inplace_chroot` | 在[不支持 bind-mounts 的系统上](index.html#additional-configuration-for-docker-container) ,这会指示 GitLab Pages chroot 进入其`pages_path`目录. 使用就地 chroot 时,存在一些注意事项; 有关更多信息,请参考 GitLab 页面[自述文件](https://gitlab.com/gitlab-org/gitlab-pages/blob/master/README.md#caveats) . | +| `insecure_ciphers` | 使用默认的密码套件列表,其中可能包含不安全的密码套件,例如 3DES 和 RC4. | +| `internal_gitlab_server` | 内部 GitLab 服务器地址专门用于 API 请求. 如果要通过内部负载均衡器发送该流量,则很有用. 默认为 GitLab `external_url` . | +| `listen_proxy` | 侦听反向代理请求的地址. 页面将绑定到这些地址的网络套接字,并从中接收传入的请求. 在`$nginx-dir/conf/gitlab-pages.conf`设置`proxy_pass`的值. | +| `log_directory` | 日志目录的绝对路径. | +| `log_format` | 日志输出格式: `text`或`json` . | +| `log_verbose` | 详细记录,对/错. | +| `max_connections` | 限制与 HTTP,HTTPS 或代理侦听器的并发连接数. | +| `metrics_address` | 用于监听指标请求的地址. | +| `redirect_http` | 将页面从 HTTP 重定向到 HTTPS,是/否. | +| `sentry_dsn` | 用于发送 Sentry 崩溃报告的地址. | +| `sentry_enabled` | 使用 Sentry(真/假)启用报告和日志记录. | +| `sentry_environment` | Sentry 崩溃报告的环境. | +| `status_uri` | 状态页面的 URL 路径,例如`/@status` . | +| `tls_max_version` | 指定最大 SSL / TLS 版本(" ssl3"," tls1.0"," tls1.1"或" tls1.2"). | +| `tls_min_version` | 指定最低 SSL / TLS 版本(" ssl3"," tls1.0"," tls1.1"或" tls1.2"). | +| `use_http2` | 启用 HTTP2 支持. | +| `gitlab_pages['env'][]` |   | +| `http_proxy` | 配置 GitLab 页面以使用 HTTP 代理来调解页面和 GitLab 之间的流量. 启动 Pages 守护程序时设置环境变量`http_proxy` . | +| `gitlab_rails[]` |   | +| `pages_domain_verification_cron_worker` | 验证自定义 GitLab 页面域的时间表. | +| `pages_domain_ssl_renewal_cron_worker` | 通过 Let's Encrypt for GitLab Pages 域获取和更新 SSL 证书的时间表. | +| `pages_domain_removal_cron_worker` | 删除未验证的自定义 GitLab 页面域的时间表. | +| `pages_path` | 磁盘上存储页面的目录,默认为`GITLAB-RAILS/shared/pages` . | +| `pages_nginx[]` |   | +| `enable` | 在 NGINX 内部包含一个用于页面的虚拟主机`server{}`块. NGINX 需要将流量代理回 Pages 守护程序. 如果 Pages 守护程序应直接接收所有请求(例如在使用[自定义域](index.html#custom-domains)时),则设置为`false` . | + +* * * + +## Advanced configuration[](#advanced-configuration "Permalink") + +除了通配符域,您还可以选择配置 GitLab 页面以与自定义域一起使用. 同样,这里有两个选项:支持带有和不带有 TLS 证书的自定义域. 最简单的设置是没有 TLS 证书. 无论哪种情况,都需要一个**辅助 IP** . 如果同时具有 IPv6 和 IPv4 地址,则可以同时使用它们. + +### Custom domains[](#custom-domains "Permalink") + +**Requirements:** + +* [Wildcard DNS setup](#dns-configuration) +* 次要 IP + +* * * + +URL 方案: `http://page.example.io` : `http://page.example.io`和`http://domain.com` + +在这种情况下,Pages 守护程序正在运行,NGINX 仍将请求代理到该守护程序,但该守护程序也能够接收来自外界的请求. 支持自定义域,但不支持 TLS. + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + pages_external_url "http://example.io" + nginx['listen_addresses'] = ['192.0.2.1'] + pages_nginx['enable'] = false + gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001::2]:80'] + ``` + + 其中`192.0.2.1`是 GitLab 侦听的主要 IP 地址,而`192.0.2.2`和`2001::2`是 GitLab Pages 守护程序侦听的辅助 IP. 如果没有 IPv6,则可以省略 IPv6 地址. + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +### Custom domains with TLS support[](#custom-domains-with-tls-support "Permalink") + +**Requirements:** + +* [Wildcard DNS setup](#dns-configuration) +* 通配 TLS 证书 +* 次要 IP + +* * * + +网址方案: `https://page.example.io` : `https://page.example.io`和`https://domain.com` + +在这种情况下,Pages 守护程序正在运行,NGINX 仍将请求代理到该守护程序,但该守护程序也能够接收来自外界的请求. 支持自定义域和 TLS. + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + pages_external_url "https://example.io" + nginx['listen_addresses'] = ['192.0.2.1'] + pages_nginx['enable'] = false + gitlab_pages['cert'] = "/etc/gitlab/ssl/example.io.crt" + gitlab_pages['cert_key'] = "/etc/gitlab/ssl/example.io.key" + gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001::2]:80'] + gitlab_pages['external_https'] = ['192.0.2.2:443', '[2001::2]:443'] + ``` + + 其中`192.0.2.1`是 GitLab 侦听的主要 IP 地址,而`192.0.2.2`和`2001::2`是 GitLab Pages 守护程序侦听的辅助 IP. 如果没有 IPv6,则可以省略 IPv6 地址. + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +### Custom domain verification[](#custom-domain-verification "Permalink") + +为了防止恶意用户劫持不属于他们的[域](../../user/project/pages/custom_domains_ssl_tls_certification/index.html#steps) ,GitLab 支持[自定义域验证](../../user/project/pages/custom_domains_ssl_tls_certification/index.html#steps) . 添加自定义域时,将要求用户通过在该域的 DNS 记录中添加 GitLab 控制的验证码来证明自己拥有该域. + +如果您的用户群是私有的或受其他方式信任,则可以禁用验证要求. 导航到**管理区域>设置>首选项,**然后在**页面**部分中取消选中**要求用户证明自定义域的所有权** . 默认情况下启用此设置. + +### Let’s Encrypt integration[](#lets-encrypt-integration "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28996) . + +[GitLab Pages 的 Let's Encrypt 集成](../../user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html)允许用户为在自定义域下提供服务的 GitLab Pages 网站添加 Let's Encrypt SSL 证书. + +要启用它,您需要: + +1. 选择一封电子邮件,在该电子邮件上您将收到有关域过期的通知. +2. 导航到实例的" **管理区域">"设置">"首选项",**然后展开" **页面"**设置. +3. 输入用于接收通知的电子邮件,并接受" Let's Encrypt 的服务条款",如下所示. +4. Click **保存更改**. + +[![Let's Encrypt settings](img/cd210f00f72fcb8f7b00750457b0ab2c.png)](img/lets_encrypt_integration_v12_1.png) + +### Access control[](#access-control "Permalink") + +在 GitLab 11.5 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33422) . + +GitLab Pages 访问控制可以针对每个项目进行配置,并允许根据用户对该项目的成员资格来控制对 Pages 站点的访问. + +访问控制通过在 GitLab 上将 Pages 守护程序注册为 OAuth 应用程序来工作. 每当未经身份验证的用户发出访问私有 Pages 站点的请求时,Pages 守护程序都会将该用户重定向到 GitLab. 如果身份验证成功,则使用令牌将用户重定向回 Pages,该令牌将保留在 cookie 中. 这些 Cookie 均用密钥签名,因此可以检测到篡改. + +Pages 使用该令牌对每个查看私有站点中的资源的请求进行身份验证. 对于收到的每个请求,它都会向 GitLab API 发出请求,以检查用户是否有权读取该站点. + +默认情况下,页面访问控制是禁用的. 要启用它: + +1. 在`/etc/gitlab/gitlab.rb`启用它: + + ``` + gitlab_pages['access_control'] = true + ``` + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). +3. 用户现在可以在其[项目的设置](../../user/project/pages/pages_access_control.html)中对其进行[配置](../../user/project/pages/pages_access_control.html) . + +**重要说明:**对于多节点设置,要使此设置生效,必须将其应用于所有 App 节点以及 Sidekiq 节点. + +#### Disabling public access to all Pages websites[](#disabling-public-access-to-all-pages-websites "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/32095) . + +您可以对 GitLab 实例上托管的所有 GitLab Pages 网站实施[访问控制](#access-control) . 这样,只有登录用户才能访问它们. 此设置将覆盖用户在单个项目中设置的访问控制. + +这对于将通过 Pages 网站发布的信息仅保留给您实例的用户很有用. 要做到这一点: + +1. 导航到实例的" **管理区域">"设置">"首选项",**然后展开" **页面"**设置. +2. 选中**禁用对页面站点的公共访问**复选框. +3. Click **保存更改**. + +**警告:**此操作将不会重新部署当前所有公开的网站. 通过[更改 GitLab 页面配置机制,](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/282)可以解决此问题. + +### Running behind a proxy[](#running-behind-a-proxy "Permalink") + +与其他 GitLab 一样,Pages 可以用于由代理控制外部 Internet 连接的那些环境. 为了对 GitLab 页面使用代理: + +1. 在`/etc/gitlab/gitlab.rb`配置: + + ``` + gitlab_pages['env']['http_proxy'] = 'http://example:8080' + ``` + +2. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +### Using a custom Certificate Authority (CA)[](#using-a-custom-certificate-authority-ca "Permalink") + +**注意:** [在 13.2 之前](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4289) ,使用 Omnibus 时, [需要](https://docs.gitlab.com/13.1/ee/administration/pages/index.html)一种[解决方法](https://docs.gitlab.com/13.1/ee/administration/pages/index.html) . + +使用自定义 CA 颁发的证书时,如果无法识别自定义 CA,则[访问控制](../../user/project/pages/pages_access_control.html#gitlab-pages-access-control)和[HTML 作业工件](../../ci/pipelines/job_artifacts.html#browsing-artifacts)的[联机视图](../../ci/pipelines/job_artifacts.html#browsing-artifacts)将无法工作. + +这通常会导致以下错误: `Post /oauth/token: x509: certificate signed by unknown authority` . + +对于从源安装,可以通过在系统证书存储中安装自定义证书颁发机构(CA)来解决. + +对于 Omnibus,可以通过[在 Omnibus GitLab 中安装自定义 CA 来解决](https://docs.gitlab.com/omnibus/settings/ssl.html) . + +## Activate verbose logging for daemon[](#activate-verbose-logging-for-daemon "Permalink") + +详细日志记录是在 Omnibus GitLab 11.1 中[引入的](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2533) . + +请按照以下步骤配置 GitLab Pages 守护程序的详细日志记录. + +1. 缺省情况下,守护程序仅记录`INFO`级别的日志. 如果要使其以`DEBUG`级别记录事件,则必须在`/etc/gitlab/gitlab.rb`配置: + + ``` + gitlab_pages['log_verbose'] = true + ``` + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +## Change storage path[](#change-storage-path "Permalink") + +请按照以下步骤更改 GitLab 页面内容的默认存储路径. + +1. 默认情况下,页面存储在`/var/opt/gitlab/gitlab-rails/shared/pages` . 如果要将它们存储在其他位置,则必须在`/etc/gitlab/gitlab.rb`设置: + + ``` + gitlab_rails['pages_path'] = "/mnt/storage/pages" + ``` + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +## Configure listener for reverse proxy requests[](#configure-listener-for-reverse-proxy-requests "Permalink") + +请按照以下步骤配置 GitLab 页面的代理侦听器. 在 Omnibus GitLab 11.1 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2533) . + +1. 默认情况下,侦听器配置为侦听`localhost:8090`上的请求. + + 如果要禁用它,则必须在`/etc/gitlab/gitlab.rb`配置: + + ``` + gitlab_pages['listen_proxy'] = nil + ``` + + 如果您希望它在其他端口上侦听,则必须在`/etc/gitlab/gitlab.rb`也进行`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_pages['listen_proxy'] = "localhost:10080" + ``` + +2. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +## Set maximum pages size[](#set-maximum-pages-size "Permalink") + +您可以在**管理区域>设置>首选项>页面**中的**最大页面大小(MB)中**配置每个项目的解压缩存档的**最大大小** . 默认值为 100MB. + +### Override maximum pages size per project or group[](#override-maximum-pages-size-per-project-or-group-premium-only "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/16610) . + +要覆盖特定项目的全局最大页面大小: + +1. 导航到项目的**"设置">"页面"**页面. +2. 编辑**最大页面大小** . +3. Click **保存更改**. + +覆盖特定组的全局最大页面大小: + +1. 导航至论坛的**"设置">"常规"**页面,然后展开" **页面"** . +2. 编辑**最大页面大小** . +3. Click **保存更改**. + +## Running GitLab Pages on a separate server[](#running-gitlab-pages-on-a-separate-server "Permalink") + +您可以在单独的服务器上运行 GitLab Pages 守护程序,以减少主应用程序服务器上的负载. + +要在单独的服务器上配置 GitLab 页面: + +**危险:**以下过程包括备份和编辑`gitlab-secrets.json`文件的步骤. 此文件包含控制数据库加密的机密. 请谨慎操作. + +1. 在**GitLab 服务器上** ,要启用 Pages,请将以下内容添加到`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_pages['enable'] = true + ``` + +2. (可选)要启用[访问控制](#access-control) ,请将以下内容添加到`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_pages['access_control'] = true + ``` + +3. [重新配置**GitLab 服务器,**](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. `gitlab-secrets.json`文件现在已使用新配置进行更新. + +4. 在**GitLab 服务器**上创建 secrets 文件的备份: + + ``` + cp /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json.bak + ``` + +5. 设置一个新服务器. 这将成为**Pages 服务器** . + +6. 在新服务器上创建一个[NFS 共享](../high_availability/nfs_host_client_setup.html) ,并配置该共享以允许从您的主**GitLab 服务器**进行访问. 在此示例中,我们使用默认的 GitLab Pages 文件夹`/var/opt/gitlab/gitlab-rails/shared/pages`作为新服务器上的共享文件夹,并将其安装到**GitLab 服务器**上的`/mnt/pages` . + +7. 在**Pages 服务器上** ,安装 Omnibus GitLab 并修改`/etc/gitlab/gitlab.rb`以包括: + + ``` + external_url 'http://' + pages_external_url "http://" + postgresql['enable'] = false + redis['enable'] = false + prometheus['enable'] = false + puma['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + gitaly['enable'] = false + alertmanager['enable'] = false + node_exporter['enable'] = false + gitlab_rails['auto_migrate'] = false + ``` + +8. 在**Pages 服务器**上创建 secrets 文件的备份: + + ``` + cp /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json.bak + ``` + +9. 将`/etc/gitlab/gitlab-secrets.json`文件从**GitLab 服务器**复制到**Pages 服务器** . + +10. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +11. 在**GitLab 服务器上** ,对`/etc/gitlab/gitlab.rb`进行以下更改: + + ``` + gitlab_pages['enable'] = false + pages_external_url "http://" + gitlab_rails['pages_path'] = "/mnt/pages" + ``` + +12. [重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +如果您希望分配负载,则可以在多台服务器上运行 GitLab Pages. 您可以通过标准的负载平衡做法来做到这一点,例如将 DNS 服务器配置为为 Pages 服务器返回多个 IP,将负载平衡器配置为在 IP 级别工作等等. 如果要在多台服务器上设置 GitLab 页面,请对每台 Pages 服务器执行上述过程. + +## Backup[](#backup "Permalink") + +GitLab 页面是[常规备份的](../../raketasks/backup_restore.html)一部分,因此无需配置单独的备份. + +## Security[](#security "Permalink") + +您应该强烈考虑以与 GitLab 不同的主机名运行 GitLab 页面,以防止 XSS 攻击. + +## Troubleshooting[](#troubleshooting "Permalink") + +### `open /etc/ssl/ca-bundle.pem: permission denied`[](#open-etcsslca-bundlepem-permission-denied "Permalink") + +GitLab Pages 在 chroot 监狱中运行,通常在`/tmp/gitlab-pages-*`等唯一编号的目录中. + +在监狱内,/ `/etc/ssl/ca-bundle.pem`提供了`/etc/ssl/ca-bundle.pem`受信任的证书. 作为启动 Pages 的一部分,它从`/opt/gitlab/embedded/ssl/certs/cacert.pem` [复制到那里](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/51) . + +如果源文件上的权限不正确(应为`0644` ),那么 chroot 监狱中的文件也将错误. + +页面将在`/var/log/gitlab/gitlab-pages/current`记录错误,例如: + +``` +x509: failed to load system roots and no roots provided +open /etc/ssl/ca-bundle.pem: permission denied +``` + +使用 chroot 监狱会使此错误产生误导,因为它没有引用根文件系统上的`/etc/ssl` . + +解决方法是更正源文件权限并重新启动 Pages: + +``` +sudo chmod 644 /opt/gitlab/embedded/ssl/certs/cacert.pem +sudo gitlab-ctl restart gitlab-pages +``` + +### `dial tcp: lookup gitlab.example.com` and `x509: certificate signed by unknown authority`[](#dial-tcp-lookup-gitlabexamplecom-and-x509-certificate-signed-by-unknown-authority "Permalink") + +同时设置`inplace_chroot`和`access_control`至`true` ,你可能会遇到类似的错误: + +``` +dial tcp: lookup gitlab.example.com on [::1]:53: dial udp [::1]:53: connect: cannot assign requested address +``` + +Or: + +``` +open /opt/gitlab/embedded/ssl/certs/cacert.pem: no such file or directory +x509: certificate signed by unknown authority +``` + +这些错误的原因是 chroot 中缺少文件`resolv.conf`和`ca-bundle.pem` . 解决方法是在 chroot 中复制主机的`/etc/resolv.conf`和 GitLab 的证书包: + +``` +sudo mkdir -p /var/opt/gitlab/gitlab-rails/shared/pages/etc/ssl +sudo mkdir -p /var/opt/gitlab/gitlab-rails/shared/pages/opt/gitlab/embedded/ssl/certs/ + +sudo cp /etc/resolv.conf /var/opt/gitlab/gitlab-rails/shared/pages/etc +sudo cp /opt/gitlab/embedded/ssl/certs/cacert.pem /var/opt/gitlab/gitlab-rails/shared/pages/opt/gitlab/embedded/ssl/certs/ +sudo cp /opt/gitlab/embedded/ssl/certs/cacert.pem /var/opt/gitlab/gitlab-rails/shared/pages/etc/ssl/ca-bundle.pem +``` + +### 404 error after transferring project to a different group or user[](#404-error-after-transferring-project-to-a-different-group-or-user "Permalink") + +如果在将项目转移到另一个组或用户后在 Pages 网站上遇到`404 Not Found`错误,则必须触发 Pages 的域配置更新. 为此,请在`.update`文件中写一些`.update` . Pages 守护程序监视此文件的更改,并在发生更改时重新加载配置. + +使用以下示例来解决使用 Pages 传输项目后修复`404 Not Found`错误: + +``` +date > /var/opt/gitlab/gitlab-rails/shared/pages/.update +``` + +如果您已自定义 Pages 存储路径,请调整上面的命令以使用自定义路径. \ No newline at end of file diff --git a/docs/448.md b/docs/448.md new file mode 100644 index 0000000000000000000000000000000000000000..5dbe6d6f12267857560f946b6edf2b87e7cb7f72 --- /dev/null +++ b/docs/448.md @@ -0,0 +1,133 @@ +# Health Check + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/monitoring/health_check.html](https://docs.gitlab.com/ee/user/admin_area/monitoring/health_check.html) + +* [IP whitelist](#ip-whitelist) +* [Using the endpoints locally](#using-the-endpoints-locally) +* [Health](#health) +* [Readiness](#readiness) +* [Liveness](#liveness) +* [Access token (Deprecated)](#access-token-deprecated) + +# Health Check[](#health-check-core-only "Permalink") + +版本历史 + +* 在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10416)了活动性和就绪性探针. +* `health_check`端点是在 GitLab 8.8 中[引入的](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3888) ,在 GitLab 9.1 中已弃用. +* 在 GitLab 9.4 中不赞成使用[访问令牌](#access-token-deprecated) ,而推荐使用[IP 白名单](#ip-whitelist) . + +manbetx 客户端打不开提供活跃度和准备情况探针,以指示服务的健康状况和对所需服务的可达性. 这些探针报告数据库连接,Redis 连接和对文件系统的访问状态. [可以将](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)这些端点[提供给 Kubernetes 之类的调度程序](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)以保持流量,直到系统准备就绪或根据需要重新启动容器. + +## IP whitelist[](#ip-whitelist "Permalink") + +要访问监视资源,需要将发出请求的客户端 IP 包含在白名单中. 有关详细信息,请参阅[如何将 IP 添加到监视端点的白名单](../../../administration/monitoring/ip_whitelist.html) . + +## Using the endpoints locally[](#using-the-endpoints-locally "Permalink") + +使用默认白名单设置,可以使用以下 URL 从本地主机访问探针: + +``` +GET http://localhost/-/health +``` + +``` +GET http://localhost/-/readiness +``` + +``` +GET http://localhost/-/liveness +``` + +## Health[](#health "Permalink") + +检查应用服务器是否正在运行. 它不会验证数据库或其他服务是否正在运行. 该端点绕过了 Rails Controller,并在请求处理生命周期的早期就作为附加的中间件`BasicHealthCheck`实现. + +``` +GET /-/health +``` + +请求示例: + +``` +curl 'https://gitlab.example.com/-/health' +``` + +响应示例: + +``` +GitLab OK +``` + +## Readiness[](#readiness "Permalink") + +就绪探针会检查 GitLab 实例是否准备好通过 Rails Controller 接受流量. 默认情况下,该检查仅验证实例检查. + +如果指定了`all=1`参数,则检查还将验证相关服务(数据库,Redis,Gitaly 等)并为每个服务提供状态. + +``` +GET /-/readiness +GET /-/readiness?all=1 +``` + +请求示例: + +``` +curl 'https://gitlab.example.com/-/readiness' +``` + +Example response: + +``` +{ "master_check":[{ "status":"failed", "message": "unexpected Master check result: false" }], ... } +``` + +失败时,端点将返回`503` HTTP 状态代码. + +如果通过`token`身份验证,则此检查确实会命中数据库,并且会重做 Redis. + +此检查不受机架攻击. + +## Liveness[](#liveness "Permalink") + +**警告:**在 GitLab [12.4](https://about.gitlab.com/upcoming-releases/)中,"活动性"检查的响应主体已更改为与以下示例匹配. + +检查应用服务器是否正在运行. 该探针用于了解 Rails 控制器是否不会由于多线程而死锁. + +``` +GET /-/liveness +``` + +请求示例: + +``` +curl 'https://gitlab.example.com/-/liveness' +``` + +响应示例: + +成功后,端点将返回`200` HTTP 状态代码和如下响应. + +``` +{ "status": "ok" } +``` + +失败时,端点将返回`503` HTTP 状态代码. + +此检查不受机架攻击. + +## Access token (Deprecated)[](#access-token-deprecated "Permalink") + +**注意:**在 GitLab 9.4 中不赞成使用访问令牌,而推荐使用[IP 白名单](#ip-whitelist) . + +访问探针端点时需要提供访问令牌. 当前接受的令牌可以在您的 GitLab 实例的**管理区域>监视>运行状况检查** ( `admin/health_check` )页面下找到. + +[![access token](img/f313f74b73573e7a2449aa6d00ae7934.png)](img/health_check_token.png) + +可以将访问令牌作为 URL 参数传递: + +``` +https://gitlab.example.com/-/readiness?token=ACCESS_TOKEN +``` + +**注意:**如果无法访问数据库或 Redis 服务,则不能保证探针端点响应正确. 您应该从已弃用的访问令牌切换到[IP 白名单](#ip-whitelist) ,以避免出现这种情况. \ No newline at end of file diff --git a/docs/449.md b/docs/449.md new file mode 100644 index 0000000000000000000000000000000000000000..52f942412e8c6ba7ea8608c6923b6739872abd46 --- /dev/null +++ b/docs/449.md @@ -0,0 +1,149 @@ +# Job logs + +> 原文:[https://docs.gitlab.com/ee/administration/job_logs.html](https://docs.gitlab.com/ee/administration/job_logs.html) + +* [Data flow](#data-flow) +* [Changing the job logs local location](#changing-the-job-logs-local-location) +* [Uploading logs to object storage](#uploading-logs-to-object-storage) +* [How to remove job logs](#how-to-remove-job-logs) +* [New incremental logging architecture](#new-incremental-logging-architecture) + * [Enabling incremental logging](#enabling-incremental-logging) + * [Potential implications](#potential-implications) + +# Job logs[](#job-logs "Permalink") + +> 在 GitLab 12.5 中[从作业跟踪重命名为作业日志](https://gitlab.com/gitlab-org/gitlab/-/issues/29121) . + +作业日志由 GitLab Runner 在处理作业时发送. 您可以在作业页面,管道,电子邮件通知等中查看日志. + +## Data flow[](#data-flow "Permalink") + +通常,作业日志有两种状态: `log`和`archived log` . 在下表中,您可以看到日志经过的阶段: + +| Phase | State | Condition | 数据流 | 储存路径 | +| --- | --- | --- | --- | --- | +| 1:打补丁 | log | 作业运行时 | GitLab Runner => Puma =>文件存储 | `#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log` | +| 2:覆盖 | log | 工作完成后 | GitLab Runner => Puma =>文件存储 | `#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log` | +| 3:归档 | 存档日志 | 工作完成后 | Sidekiq 将日志移至工件文件夹 | `#{ROOT_PATH}/gitlab-rails/shared/artifacts/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log` | +| 4:上传 | 存档日志 | 归档日志后 | Sidekiq 将存档日志移至[对象存储](#uploading-logs-to-object-storage) (如果已配置) | `#{bucket_name}/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log` | + +`ROOT_PATH`因环境而异. 对于 Omnibus GitLab,它将是`/var/opt/gitlab` ;对于从源代码进行的安装,它将是`/home/git/gitlab` . + +## Changing the job logs local location[](#changing-the-job-logs-local-location "Permalink") + +要更改作业日志的存储位置,请执行以下步骤. + +**在所有安装中;** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加或修改以下行: + + ``` + gitlab_ci['builds_directory'] = '/mnt/to/gitlab-ci/builds' + ``` + +2. 保存文件并[重新配置 GitLab,](restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**在源安装中:** + +1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines: + + ``` + gitlab_ci: + # The location where build logs are stored (default: builds/). + # Relative paths are relative to Rails.root. + builds_path: path/to/builds/ + ``` + +2. 保存文件并[重新启动 GitLab,](restart_gitlab.html#installations-from-source)以使更改生效. + +## Uploading logs to object storage[](#uploading-logs-to-object-storage "Permalink") + +归档日志被视为[作业工件](job_artifacts.html) . 因此,当您[设置对象存储集成时](job_artifacts.html#object-storage-settings) ,作业日志将与其他作业工件一起自动迁移到[该对象](job_artifacts.html#object-storage-settings) . + +请参阅[数据流中的](#data-flow) "阶段 4:上传"以了解该过程. + +## How to remove job logs[](#how-to-remove-job-logs "Permalink") + +没有办法自动使旧的作业日志过期,但是如果它们占用太多空间,可以安全地将其删除. 如果您手动删除日志,则 UI 中的作业输出将为空. + +例如,要删除所有超过 60 天的作业日志,请在您的 GitLab 实例中的 Shell 中运行以下命令: + +**危险:**此命令将永久删除日志文件,并且是不可逆的. + +``` +find /var/opt/gitlab/gitlab-rails/shared/artifacts -name "job.log" -mtime +60 -delete +``` + +## New incremental logging architecture[](#new-incremental-logging-architecture "Permalink") + +版本历史 + +* 在 GitLab 10.4 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18169) . +* [公布为一般可](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46097)在 GitLab 11.0\. + +**注意:**此功能默认为关闭. 有关如何[启用或禁用](#enabling-incremental-logging)它的信息,请参见下文. + +通过将过程与对象存储设置相结合,我们可以完全绕过本地文件存储. 如果将 GitLab 安装为云原生,例如在 Kubernetes 上,这是一个有用的选项. + +数据流与[数据流部分中](#data-flow)描述的相同,只是有所变化: *前两个阶段的存储路径不同* . 这种增量日志架构将日志块存储在 Redis 中,并将其存储在持久性存储(对象存储或数据库)中,而不是文件存储中. Redis 用作一流的存储,它最多可存储 128KB 数据. 一旦发送了完整的块,就将其刷新到持久性存储(对象存储(临时目录)或数据库). 一段时间后,Redis 和持久性存储中的数据将被归档到[对象存储](#uploading-logs-to-object-storage) . + +数据存储在以下 Redis 命名空间中: `Gitlab::Redis::SharedState` . + +这是详细的数据流: + +1. GitLab Runner 从 GitLab 选择工作 +2. GitLab Runner 向 GitLab 发送一条日志 +3. GitLab 将数据追加到 Redis +4. 一旦 Redis 中的数据达到 128KB,就将数据刷新到持久性存储(对象存储或数据库). +5. 重复上述步骤,直到作业完成. +6. 作业完成后,GitLab 会安排 Sidekiq 工作人员存档日志. +7. Sidekiq worker 将日志归档到对象存储,并在 Redis 和永久存储(对象存储或数据库)中清除日志. + +### Enabling incremental logging[](#enabling-incremental-logging "Permalink") + +在 Rails 控制台中将发出以下命令: + +``` +# Omnibus GitLab +gitlab-rails console + +# Installation from source +cd /home/git/gitlab +sudo -u git -H bin/rails console -e production +``` + +**要检查是否启用了增量日志记录(跟踪):** + +``` +Feature.enabled?(:ci_enable_live_trace) +``` + +**要启用增量日志记录(跟踪):** + +``` +Feature.enable(:ci_enable_live_trace) +``` + +**注意:**过渡期将得到适当处理. 即将到来的日志将使用增量体系结构生成,而正在进行的日志将保留在旧体系结构中,这意味着将不会使用增量体系结构强制重新生成正在进行的日志. + +**要禁用增量日志记录(跟踪):** + +``` +Feature.disable('ci_enable_live_trace') +``` + +**注意:**过渡期将得到适当处理. 即将发生的日志将使用旧体系结构生成,而持续的增量日志将保留在增量体系结构中,这意味着持续的增量日志将不会用旧体系结构强制重新生成. + +### Potential implications[](#potential-implications "Permalink") + +在某些情况下,将数据存储在 Redis 上可能会导致数据丢失: + +1. **情况 1:Redis 中的所有数据被意外刷新** + * 可以通过重新发送日志来恢复增量日志(所有版本的 GitLab Runner 均支持此功能). + * 未归档增量日志的已完成作业将丢失日志数据的最后一部分(〜128KB). +2. **情况 2:当 Sidekiq 工作人员无法归档时(例如,存在一个阻止归档过程,Sidekiq 不一致等的错误)** + * 当前,Redis 中的所有日志数据将在一周后删除. 如果 Sidekiq 工作人员无法在到期日之前完成操作,则部分日志数据将丢失. + +可能出现的另一个问题是,它可能会消耗 Redis 实例上的所有内存. 如果作业数为 1000,则将消耗 128MB(128KB * 1000). + +而且,它可能会给数据库复制带来压力. 生成`INSERT`以表明我们有日志块. 一旦我们收到多个数据块,便发出具有 128KB 数据的`UPDATE` . \ No newline at end of file diff --git a/docs/450.md b/docs/450.md new file mode 100644 index 0000000000000000000000000000000000000000..efa003a63025b768348f45bc8bfc1439fb1869f8 --- /dev/null +++ b/docs/450.md @@ -0,0 +1,15 @@ +# Labels administration + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/labels.html](https://docs.gitlab.com/ee/user/admin_area/labels.html) + +* [Default Labels](#default-labels) + +# Labels administration[](#labels-administration-core-only "Permalink") + +在管理区域中,您可以管理 GitLab 实例的标签. 有关更多详细信息,请参见[标签](../project/labels.html) . + +## Default Labels[](#default-labels "Permalink") + +在管理区域中创建的标签可用于每个*新*项目. + +[![Default label set](img/ba294e1cb39daadf43b81f113e5ef506.png)](img/admin_labels.png) \ No newline at end of file diff --git a/docs/451.md b/docs/451.md new file mode 100644 index 0000000000000000000000000000000000000000..a60fe847cafadd36b208a2ea699059a04f98eef4 --- /dev/null +++ b/docs/451.md @@ -0,0 +1,588 @@ +# Log system + +> 原文:[https://docs.gitlab.com/ee/administration/logs.html](https://docs.gitlab.com/ee/administration/logs.html) + +* [`production_json.log`](#production_jsonlog) +* [`production.log`](#productionlog) +* [`api_json.log`](#api_jsonlog) +* [`application.log`](#applicationlog) +* [`application_json.log`](#application_jsonlog) +* [`integrations_json.log`](#integrations_jsonlog) +* [`kubernetes.log`](#kuberneteslog) +* [`git_json.log`](#git_jsonlog) +* [`audit_json.log`](#audit_jsonlog) +* [Sidekiq Logs](#sidekiq-logs) + * [`sidekiq.log`](#sidekiqlog) + * [`sidekiq_client.log`](#sidekiq_clientlog) +* [`gitlab-shell.log`](#gitlab-shelllog) + * [For GitLab versions 12.10 and up](#for-gitlab-versions-1210-and-up) + * [For GitLab versions 12.5 through 12.9](#for-gitlab-versions-125-through-129) + * [For GitLab 12.5 and earlier](#for-gitlab-125-and-earlier) +* [Gitaly Logs](#gitaly-logs) + * [`grpc.log`](#grpclog) +* [Puma Logs](#puma-logs) + * [`puma_stdout.log`](#puma_stdoutlog) + * [`puma_stderr.log`](#puma_stderrlog) +* [Unicorn Logs](#unicorn-logs) + * [`unicorn_stdout.log`](#unicorn_stdoutlog) + * [`unicorn_stderr.log`](#unicorn_stderrlog) +* [`repocheck.log`](#repochecklog) +* [`importer.log`](#importerlog) +* [`exporter.log`](#exporterlog) +* [`auth.log`](#authlog) +* [`graphql_json.log`](#graphql_jsonlog) +* [`migrations.log`](#migrationslog) +* [`mail_room_json.log` (default)](#mail_room_jsonlog-default) +* [Reconfigure Logs](#reconfigure-logs) +* [`sidekiq_exporter.log` and `web_exporter.log`](#sidekiq_exporterlog-and-web_exporterlog) +* [`database_load_balancing.log`](#database_load_balancinglog-premium-only) +* [`elasticsearch.log`](#elasticsearchlog-starter-only) +* [`exceptions_json.log`](#exceptions_jsonlog) +* [`service_measurement.log`](#service_measurementlog) +* [`geo.log`](#geolog-premium-only) +* [Registry Logs](#registry-logs) +* [NGINX Logs](#nginx-logs) +* [Pages Logs](#pages-logs) +* [Mattermost Logs](#mattermost-logs) +* [Workhorse Logs](#workhorse-logs) +* [PostgreSQL Logs](#postgresql-logs) +* [Prometheus Logs](#prometheus-logs) +* [Redis Logs](#redis-logs) +* [Alertmanager Logs](#alertmanager-logs) +* [Crond Logs](#crond-logs) +* [Grafana Logs](#grafana-logs) +* [LogRotate Logs](#logrotate-logs) +* [GitLab Monitor Logs](#gitlab-monitor-logs) +* [GitLab Exporter](#gitlab-exporter) + +# Log system[](#log-system "Permalink") + +GitLab 具有一个高级日志系统,可以记录所有内容,因此您可以使用各种系统日志文件分析实例. 除了系统日志文件,GitLab 企业版还提供审核事件. [在审核事件文档中](audit_events.html)找到有关它们的更多信息. + +系统日志文件通常是标准日志文件格式的纯文本. 本指南讨论如何读取和使用这些系统日志文件. + +## `production_json.log`[](#production_jsonlog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/production_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/production_json.log`中. 当 GitLab 在生产环境以外的环境中运行时,此处将显示相应的日志文件. + +由于[Lograge](https://github.com/roidrage/lograge/) ,它包含从 GitLab 接收到的 Rails 控制器请求的结构化日志. 请注意,来自 API 的请求将记录到`api_json.log`的单独文件中. + +每行包含一个可以由 Elasticsearch 和 Splunk 之类的服务提取的 JSON 行. 为了便于阅读,在示例中添加了换行符: + +``` +{ "method":"GET", "path":"/gitlab/gitlab-foss/issues/1234", "format":"html", "controller":"Projects::IssuesController", "action":"show", "status":200, "time":"2017-08-08T20:15:54.821Z", "params":[{"key":"param_key","value":"param_value"}], "remote_ip":"18.245.0.1", "user_id":1, "username":"admin", "queue_duration_s":0.0, "gitaly_calls":16, "gitaly_duration_s":0.16, "redis_calls":115, "redis_duration_s":0.13, "redis_read_bytes":1507378, "redis_write_bytes":2920, "correlation_id":"O1SdybnnIq7", "cpu_s":17.50, "db_duration_s":0.08, "view_duration_s":2.39, "duration_s":20.54 } +``` + +此示例是针对特定问题的 GET 请求. 每行还包含性能数据,时间以秒为单位: + +1. `duration_s` :检索请求所花费的总时间 +2. `queue_duration_s` :请求在 GitLab Workhorse 中排队的总时间 +3. `view_duration_s` :在 Rails 视图中`view_duration_s`总时间 +4. `db_duration_s` :从 PostgreSQL 检索数据的总时间 +5. `cpu_s` :在 CPU 上花费的总时间 +6. `gitaly_duration_s` :Gitaly 调用花费的总时间 +7. `gitaly_calls` :拨打 Gitaly 的电话总数 +8. `redis_calls` :对 Redis 的呼叫总数 +9. `redis_duration_s` :从 Redis 检索数据的总时间 +10. `redis_read_bytes` :从 Redis 读取的总字节 +11. `redis_write_bytes` :写入 Redis 的总字节数 +12. `redis__calls`: total number of calls made to a Redis instance +13. `redis__duration_s` :从 Redis 实例检索数据的总时间 +14. `redis__read_bytes` :从 Redis 实例读取的总字节数 +15. `redis__write_bytes` :写入 Redis 实例的总字节数 + +使用 HTTP 传输的用户克隆和获取活动作为`action: git_upload_pack`出现在此日志中`action: git_upload_pack` . + +此外,日志还包含原始 IP 地址( `remote_ip` ),用户 ID( `user_id` )和用户名( `username` ). + +如果使用[Advanced Global Search,](../user/search/advanced_global_search.html)则某些端点(例如`/search`可能会向 Elasticsearch 发出请求. 这些将另外记录`elasticsearch_calls`和`elasticsearch_call_duration_s` ,它们对应于: + +1. `elasticsearch_calls` :对 Elasticsearch 的调用总数 +2. `elasticsearch_duration_s` :Elasticsearch 调用花费的总时间 + +ActionCable 连接和订阅事件也记录到此文件中,它们遵循上面相同的格式. `method` , `path`和`format`字段不适用,并且始终为空. ActionCable 连接或通道类用作`controller` . + +``` +{ "method":{}, "path":{}, "format":{}, "controller":"IssuesChannel", "action":"subscribe", "status":200, "time":"2020-05-14T19:46:22.008Z", "params":[{"key":"project_path","value":"gitlab/gitlab-foss"},{"key":"iid","value":"1"}], "remote_ip":"127.0.0.1", "user_id":1, "username":"admin", "ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:76.0) Gecko/20100101 Firefox/76.0", "correlation_id":"jSOIEynHCUa", "duration_s":0.32566 } +``` + +**注意:**从 GitLab 12.5 开始,如果发生错误,则`class` , `message`和`backtrace`包含一个`exception`字段. 以前的版本包含一个`error`字段,而不是`exception.class`和`exception.message` . 例如: + +``` +{ "method": "GET", "path": "/admin", "format": "html", "controller": "Admin::DashboardController", "action": "index", "status": 500, "time": "2019-11-14T13:12:46.156Z", "params": [], "remote_ip": "127.0.0.1", "user_id": 1, "username": "root", "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:70.0) Gecko/20100101 Firefox/70.0", "queue_duration": 274.35, "correlation_id": "KjDVUhNvvV3", "queue_duration_s":0.0, "gitaly_calls":16, "gitaly_duration_s":0.16, "redis_calls":115, "redis_duration_s":0.13, "correlation_id":"O1SdybnnIq7", "cpu_s":17.50, "db_duration_s":0.08, "view_duration_s":2.39, "duration_s":20.54 "exception.class": "NameError", "exception.message": "undefined local variable or method `adsf' for #", "exception.backtrace": [ "app/controllers/admin/dashboard_controller.rb:11:in `index'", "ee/app/controllers/ee/admin/dashboard_controller.rb:14:in `index'", "ee/lib/gitlab/ip_address_state.rb:10:in `with'", "ee/app/controllers/ee/application_controller.rb:43:in `set_current_ip_address'", "lib/gitlab/session.rb:11:in `with_session'", "app/controllers/application_controller.rb:450:in `set_session_storage'", "app/controllers/application_controller.rb:444:in `set_locale'", "ee/lib/gitlab/jira/middleware.rb:19:in `call'" ] } +``` + +## `production.log`[](#productionlog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/production.log` ,对于从源代码进行安装,该文件位于`/home/git/gitlab/log/production.log`中. (当 GitLab 在生产环境以外的环境中运行时,此处将显示相应的日志文件.) + +它包含有关所有已执行请求的信息. 您可以查看 URL 和请求类型,IP 地址,以及涉及哪些代码部分来满足此特定请求. 此外,您还可以查看所有执行的 SQL 请求以及每个请求花费的时间. 对于 GitLab 贡献者和开发人员来说,此任务更有用. 报告错误时,请使用此日志文件的一部分. 例如: + +``` +Started GET "/gitlabhq/yaml_db/tree/master" for 168.111.56.1 at 2015-02-12 19:34:53 +0200 +Processing by Projects::TreeController#show as HTML + Parameters: {"project_id"=>"gitlabhq/yaml_db", "id"=>"master"} + + ... [CUT OUT] + + Namespaces"."created_at" DESC, "namespaces"."id" DESC LIMIT 1 [["id", 26]] + CACHE (0.0ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $1 AND "members"."source_type" = $2 AND "members"."user_id" = 1 ORDER BY "members"."created_at" DESC, "members"."id" DESC LIMIT 1 [["source_id", 18], ["source_type", "Project"]] + CACHE (0.0ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members". + (1.4ms) SELECT COUNT(*) FROM "merge_requests" WHERE "merge_requests"."target_project_id" = $1 AND ("merge_requests"."state" IN ('opened','reopened')) [["target_project_id", 18]] + Rendered layouts/nav/_project.html.haml (28.0ms) + Rendered layouts/_collapse_button.html.haml (0.2ms) + Rendered layouts/_flash.html.haml (0.1ms) + Rendered layouts/_page.html.haml (32.9ms) +Completed 200 OK in 166ms (Views: 117.4ms | ActiveRecord: 27.2ms) +``` + +在此示例中,服务器在`2015-02-12 19:34:53 +0200`处处理了来自 IP `168.111.56.1` URL `/gitlabhq/yaml_db/tree/master`的 HTTP 请求. 该请求已由`Projects::TreeController` . + +## `api_json.log`[](#api_jsonlog "Permalink") + +在 GitLab 10.0 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/api_json.log`中,对于从源代码进行安装则位于`/home/git/gitlab/log/api_json.log`中. + +它可以帮助您查看直接向 API 发出的请求. 例如: + +``` +{ "time":"2018-10-29T12:49:42.123Z", "severity":"INFO", "duration":709.08, "db":14.59, "view":694.49, "status":200, "method":"GET", "path":"/api/v4/projects", "params":[{"key":"action","value":"git-upload-pack"},{"key":"changes","value":"_any"},{"key":"key_id","value":"secret"},{"key":"secret_token","value":"[FILTERED]"}], "host":"localhost", "remote_ip":"::1", "ua":"Ruby", "route":"/api/:version/projects", "user_id":1, "username":"root", "queue_duration":100.31, "gitaly_calls":30, "gitaly_duration":5.36 } +``` + +此项显示一个内部端点,该端点被访问以检查关联的 SSH 密钥是否可以通过`git fetch`或`git clone`下载有问题的项目. 在此示例中,我们看到: + +1. `duration` :检索请求所花费的总时间(以毫秒为单位) +2. `queue_duration` :请求在 GitLab Workhorse 中排队的总时间(以毫秒为单位) +3. `method` :用于发出请求的 HTTP 方法 +4. `path` :查询的相对路径 +5. `params` :在查询字符串或 HTTP 正文中传递的键/值对. 敏感参数(例如密码和令牌)被过滤掉. +6. `ua` :请求者的用户代理 + +## `application.log`[](#applicationlog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/application.log` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/application.log`中. + +它可以帮助您发现实例中发生的事件,例如用户创建,项目删除等. 例如: + +``` +October 06, 2014 11:56: User "Administrator" (admin@example.com) was created +October 06, 2014 11:56: Documentcloud created a new project "Documentcloud / Underscore" +October 06, 2014 11:56: Gitlab Org created a new project "Gitlab Org / Gitlab Ce" +October 07, 2014 11:25: User "Claudie Hodkiewicz" (nasir_stehr@olson.co.uk) was removed +October 07, 2014 11:25: Project "project133" was removed +``` + +## `application_json.log`[](#application_jsonlog "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22812) . + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/application_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/application_json.log`中. + +它包含`application.log`日志的 JSON 版本,如下例所示: + +``` +{ "severity":"INFO", "time":"2020-01-14T13:35:15.466Z", "correlation_id":"3823a1550b64417f9c9ed8ee0f48087e", "message":"User \"Administrator\" (admin@example.com) was created" } { "severity":"INFO", "time":"2020-01-14T13:35:15.466Z", "correlation_id":"78e3df10c9a18745243d524540bd5be4", "message":"Project \"project133\" was removed" } +``` + +## `integrations_json.log`[](#integrations_jsonlog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/integrations_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/integrations_json.log`中. + +它包含有关[集成](../user/project/integrations/overview.html)活动的信息,例如 Jira,Asana 和 Irker 服务. 它使用 JSON 格式,如下例所示: + +``` +{ "severity":"ERROR", "time":"2018-09-06T14:56:20.439Z", "service_class":"JiraService", "project_id":8, "project_path":"h5bp/html5-boilerplate", "message":"Error sending message", "client_url":"http://jira.gitlap.com:8080", "error":"execution expired" } { "severity":"INFO", "time":"2018-09-06T17:15:16.365Z", "service_class":"JiraService", "project_id":3, "project_path":"namespace2/project2", "message":"Successfully posted", "client_url":"http://jira.example.com" } +``` + +## `kubernetes.log`[](#kuberneteslog "Permalink") + +在 GitLab 11.6 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/kubernetes.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/kubernetes.log`中. + +它记录与 Kubernetes 集成相关的信息,包括在托管的 Kubernetes 集群上安装集群应用程序期间的错误. + +每行包含一个可以由 Elasticsearch 和 Splunk 之类的服务提取的 JSON 行. 为了清楚起见,在以下示例中添加了换行符: + +``` +{ "severity":"ERROR", "time":"2018-11-23T15:14:54.652Z", "exception":"Kubeclient::HttpError", "error_code":401, "service":"Clusters::Applications::CheckInstallationProgressService", "app_id":14, "project_ids":[1], "group_ids":[], "message":"Unauthorized" } { "severity":"ERROR", "time":"2018-11-23T15:42:11.647Z", "exception":"Kubeclient::HttpError", "error_code":null, "service":"Clusters::Applications::InstallService", "app_id":2, "project_ids":[19], "group_ids":[], "message":"SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)" } +``` + +## `git_json.log`[](#git_jsonlog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/git_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/git_json.log`中. + +**注意:**在 12.2 之后,此文件从`githost.log`重命名为`git_json.log`并以 JSON 格式存储. + +GitLab 必须与 Git 存储库进行交互,但是在极少数情况下可能会出问题,在这种情况下,您可能需要知道到底发生了什么. 该日志文件包含从 GitLab 到 Git 存储库的所有失败请求. 在大多数情况下,此文件仅对开发人员有用. 例如: + +``` +{ "severity":"ERROR", "time":"2019-07-19T22:16:12.528Z", "correlation_id":"FeGxww5Hj64", "message":"Command failed [1]: /usr/bin/git --git-dir=/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/group184/gitlabhq/.git --work-tree=/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/group184/gitlabhq merge --no-ff -mMerge branch 'feature_conflict' into 'feature' source/feature_conflict\n\nerror: failed to push some refs to '/Users/vsizov/gitlab-development-kit/repositories/gitlabhq/gitlab_git.git'" } +``` + +## `audit_json.log`[](#audit_jsonlog "Permalink") + +**注意:**大多数日志条目仅存在于[GitLab Starter 中](https://about.gitlab.com/pricing/) ,而少数存在于 GitLab Core 中. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/audit_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/audit_json.log`中. + +组或项目设置的更改将记录到该文件中. 例如: + +``` +{ "severity":"INFO", "time":"2018-10-17T17:38:22.523Z", "author_id":3, "entity_id":2, "entity_type":"Project", "change":"visibility", "from":"Private", "to":"Public", "author_name":"John Doe4", "target_id":2, "target_type":"Project", "target_details":"namespace2/project2" } +``` + +## Sidekiq Logs[](#sidekiq-logs "Permalink") + +对于 Omnibus 安装,一些 Sidekiq 日志位于`/var/log/gitlab/sidekiq/current` ,如下所示. + +### `sidekiq.log`[](#sidekiqlog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/sidekiq.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/sidekiq.log`中. + +GitLab 使用后台作业来处理可能需要很长时间的任务. 有关处理这些作业的所有信息都记录到该文件中. 例如: + +``` +2014-06-10T07:55:20Z 2037 TID-tm504 ERROR: /opt/bitnami/apps/discourse/htdocs/vendor/bundle/ruby/1.9.1/gems/redis-3.0.7/lib/redis/client.rb:228:in `read' +2014-06-10T18:18:26Z 14299 TID-55uqo INFO: Booting Sidekiq 3.0.0 with redis options {:url=>"redis://localhost:6379/0", :namespace=>"sidekiq"} +``` + +除了上面的格式,您可以选择为 Sidekiq 生成 JSON 日志. 例如: + +``` +{ "severity":"INFO", "time":"2018-04-03T22:57:22.071Z", "queue":"cronjob:update_all_mirrors", "args":[], "class":"UpdateAllMirrorsWorker", "retry":false, "queue_namespace":"cronjob", "jid":"06aeaa3b0aadacf9981f368e", "created_at":"2018-04-03T22:57:21.930Z", "enqueued_at":"2018-04-03T22:57:21.931Z", "pid":10077, "message":"UpdateAllMirrorsWorker JID-06aeaa3b0aadacf9981f368e: done: 0.139 sec", "job_status":"done", "duration":0.139, "completed_at":"2018-04-03T22:57:22.071Z", "db_duration":0.05, "db_duration_s":0.0005, "gitaly_duration":0, "gitaly_calls":0 } +``` + +对于 Omnibus GitLab 安装,请添加配置选项: + +``` +sidekiq['log_format'] = 'json' +``` + +对于源代码安装,请编辑`gitlab.yml`并设置 Sidekiq `log_format`配置选项: + +``` + ## Sidekiq + sidekiq: + log_format: json +``` + +### `sidekiq_client.log`[](#sidekiq_clientlog "Permalink") + +在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26586) . + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/sidekiq_client.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/sidekiq_client.log`中. + +该文件包含有关 Sidekiq 开始处理作业之前(例如,入队前)的日志信息. + +该日志文件采用与[`sidekiq.log`](#sidekiqlog)相同的结构,因此,如果您如上所述为 Sidekiq 配置了此文件,则该文件将构造为 JSON. + +## `gitlab-shell.log`[](#gitlab-shelllog "Permalink") + +GitLab 使用 GitLab Shell 执行 Git 命令,并提供对 Git 存储库的 SSH 访问. + +### For GitLab versions 12.10 and up[](#for-gitlab-versions-1210-and-up "Permalink") + +对于 GitLab 版本 12.10 和更高版本,有 2 个`gitlab-shell.log`文件. 包含`git-{upload-pack,receive-pack}`请求的信息位于`/var/log/gitlab/gitlab-shell/gitlab-shell.log` . 来自 Gitaly 的与 GitLab Shell 挂钩的信息位于`/var/log/gitlab/gitaly/gitlab-shell.log` . + +`/var/log/gitlab/gitlab-shell/gitlab-shell.log`示例日志条目: + +``` +{ "duration_ms": 74.104, "level": "info", "method": "POST", "msg": "Finished HTTP request", "time": "2020-04-17T20:28:46Z", "url": "http://127.0.0.1:8080/api/v4/internal/allowed" } { "command": "git-upload-pack", "git_protocol": "", "gl_project_path": "root/example", "gl_repository": "project-1", "level": "info", "msg": "executing git command", "time": "2020-04-17T20:28:46Z", "user_id": "user-1", "username": "root" } +``` + +`/var/log/gitlab/gitaly/gitlab-shell.log`示例日志条目: + +``` +{ "method": "POST", "url": "http://127.0.0.1:8080/api/v4/internal/allowed", "duration": 0.058012959, "gitaly_embedded": true, "pid": 16636, "level": "info", "msg": "finished HTTP request", "time": "2020-04-17T20:29:08+00:00" } { "method": "POST", "url": "http://127.0.0.1:8080/api/v4/internal/pre_receive", "duration": 0.031022552, "gitaly_embedded": true, "pid": 16636, "level": "info", "msg": "finished HTTP request", "time": "2020-04-17T20:29:08+00:00" } +``` + +### For GitLab versions 12.5 through 12.9[](#for-gitlab-versions-125-through-129 "Permalink") + +对于 GitLab 12.5 至 12.9,对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitaly/gitlab-shell.log` ,对于从源代码进行安装则位于`/home/git/gitaly/gitlab-shell.log`中. + +Example log entries: + +``` +{ "method": "POST", "url": "http://127.0.0.1:8080/api/v4/internal/post_receive", "duration": 0.031809164, "gitaly_embedded": true, "pid": 27056, "level": "info", "msg": "finished HTTP request", "time": "2020-04-17T16:24:38+00:00" } +``` + +### For GitLab 12.5 and earlier[](#for-gitlab-125-and-earlier "Permalink") + +对于 GitLab 12.5 和更早版本,该文件位于`/var/log/gitlab/gitlab-shell/gitlab-shell.log` . + +示例日志条目: + +``` +I, [2015-02-13T06:17:00.671315 #9291] INFO -- : Adding project root/example.git at . +I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory and symlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git. +``` + +`executing git command : worker (pid: 9094) exceeds memory limit (320626688 bytes > 247066940 bytes) +W, [2015-02-13T07:16:01.313000 #9094] WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 9094) alive: 3621 sec (trial 1) +I, [2015-02-13T07:16:01.530733 #9047] INFO -- : reaped # worker=1 +I, [2015-02-13T07:16:01.534501 #13379] INFO -- : worker=1 spawned pid=13379 +I, [2015-02-13T07:16:01.534848 #13379] INFO -- : worker=1 ready +``` + +## `repocheck.log`[](#repochecklog "Permalink") + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/repocheck.log` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/repocheck.log`中. + +每当在项目上[运行存储库检查](repository_checks.html)时,它都会记录信息. + +## `importer.log`[](#importerlog "Permalink") + +在 GitLab 11.3 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/importer.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/importer.log`中. + +它记录导入过程的进度. + +## `exporter.log`[](#exporterlog "Permalink") + +在 GitLab 13.1 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/exporter.log` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/exporter.log`中. + +它记录导出过程的进度. + +## `auth.log`[](#authlog "Permalink") + +在 GitLab 12.0 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/auth.log` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/auth.log`中. + +该日志记录: + +* 每当[Rack Attack](../security/rack_attack.html)注册滥用请求时提供的信息. +* 请求超过原始端点上的[速率限制](../user/admin_area/settings/rate_limits_on_raw_endpoints.html) . +* [受保护的路径](../user/admin_area/settings/protected_paths.html)滥用请求. + +**注意:**在 GitLab [12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/29239)和更高版本中,用户 ID 和用户名也会记录在该日志中(如果有). + +## `graphql_json.log`[](#graphql_jsonlog "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/59587) in GitLab 12.0. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/graphql_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/graphql_json.log`中. + +GraphQL 查询记录在该文件中. 例如: + +``` +{"query_string":"query IntrospectionQuery{__schema {queryType { name },mutationType { name }}}...(etc)","variables":{"a":1,"b":2},"complexity":181,"depth":1,"duration_s":7} +``` + +## `migrations.log`[](#migrationslog "Permalink") + +在 GitLab 12.3 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/migrations.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/migrations.log`中. + +## `mail_room_json.log` (default)[](#mail_room_jsonlog-default "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19186) . + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/mailroom/current` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/mail_room_json.log`中. + +这个结构化的日志文件将内部活动记录在`mail_room` gem 中. 它的名称和路径是可配置的,因此名称和路径可能与上面的不匹配. + +## Reconfigure Logs[](#reconfigure-logs "Permalink") + +为 Omnibus GitLab 软件包`/var/log/gitlab/reconfigure`日志文件. 从源安装没有重新配置日志. 每当手动或作为升级的一部分运行`gitlab-ctl reconfigure`时, `gitlab-ctl reconfigure`填充一个重配置日志. + +根据启动重新配置的 UNIX 时间戳记来命名重新配置日志文件,例如`1509705644.log` + +## `sidekiq_exporter.log` and `web_exporter.log`[](#sidekiq_exporterlog-and-web_exporterlog "Permalink") + +如果同时启用了 Prometheus 指标和 Sidekiq 导出器,则 Sidekiq 将启动 Web 服务器并侦听定义的端口(默认值: `8082` ). 对于 Omnibus GitLab 软件包,访问日志将在`/var/log/gitlab/gitlab-rails/sidekiq_exporter.log`中生成,对于从源代码进行的安装,将在`/home/git/gitlab/log/sidekiq_exporter.log`生成. + +如果同时启用了 Prometheus 指标和 Web 导出器,则 Puma / Unicorn 将启动 Web 服务器并侦听定义的端口(默认值: `8083` ). 对于 Omnibus GitLab 软件包,访问日志将在`/var/log/gitlab/gitlab-rails/web_exporter.log`中生成,对于源安装,将在`/home/git/gitlab/log/web_exporter.log`生成. + +## `database_load_balancing.log`[](#database_load_balancinglog-premium-only "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15442) . + +包含 GitLab 的[数据库负载平衡的](database_load_balancing.html)详细信息. 它存储在: + +* `/var/log/gitlab/gitlab-rails/database_load_balancing.log`用于 Omnibus GitLab 软件包. +* `/home/git/gitlab/log/database_load_balancing.log`用于从源代码进行安装. + +## `elasticsearch.log`[](#elasticsearchlog-starter-only "Permalink") + +在 GitLab 12.6 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/elasticsearch.log` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/elasticsearch.log`中. + +它记录与 Elasticsearch Integration 相关的信息,包括在索引或搜索 Elasticsearch 期间发生的错误. + +每行包含一个可以由 Elasticsearch 和 Splunk 之类的服务提取的 JSON 行. 为了清楚起见,在以下示例行中添加了换行符: + +``` +{ "severity":"DEBUG", "time":"2019-10-17T06:23:13.227Z", "correlation_id":null, "message":"redacted_search_result", "class_name":"Milestone", "id":2, "ability":"read_milestone", "current_user_id":2, "query":"project" } +``` + +## `exceptions_json.log`[](#exceptions_jsonlog "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17819) . + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/exceptions_json.log` ,对于从源代码进行安装则位于`/home/git/gitlab/log/exceptions_json.log`中. + +它记录有关`Gitlab::ErrorTracking`跟踪的异常的信息,该信息提供了一种标准且一致的方式来[处理已获救的异常](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/logging.md#exception-handling) . + +每行包含一个可由 Elasticsearch 摄取的 JSON 行. 例如: + +``` +{ "severity": "ERROR", "time": "2019-12-17T11:49:29.485Z", "correlation_id": "AbDVUrrTvM1", "extra.project_id": 55, "extra.relation_key": "milestones", "extra.relation_index": 1, "exception.class": "NoMethodError", "exception.message": "undefined method `strong_memoize' for #", "exception.backtrace": [ "lib/gitlab/import_export/relation_factory.rb:329:in `unique_relation?'", "lib/gitlab/import_export/relation_factory.rb:345:in `find_or_create_object!'" ] } +``` + +## `service_measurement.log`[](#service_measurementlog "Permalink") + +在 GitLab 13.0 中引入. + +对于 Omnibus GitLab 软件包,此文件位于`/var/log/gitlab/gitlab-rails/service_measurement.log` ,对于来自源的安装,该文件位于`/home/git/gitlab/log/service_measurement.log`中. + +它仅包含一个结构化日志,其中包含每个服务执行的度量. 它将包含诸如 SQL 调用数, `execution_time` , `gc_stats`和`memory usage` `gc_stats` . + +例如: + +``` +{ "severity":"INFO", "time":"2020-04-22T16:04:50.691Z","correlation_id":"04f1366e-57a1-45b8-88c1-b00b23dc3616","class":"Projects::ImportExport::ExportService","current_user":"John Doe","project_full_path":"group1/test-export","file_path":"/path/to/archive","gc_stats":{"count":{"before":127,"after":127,"diff":0},"heap_allocated_pages":{"before":10369,"after":10369,"diff":0},"heap_sorted_length":{"before":10369,"after":10369,"diff":0},"heap_allocatable_pages":{"before":0,"after":0,"diff":0},"heap_available_slots":{"before":4226409,"after":4226409,"diff":0},"heap_live_slots":{"before":2542709,"after":2641420,"diff":98711},"heap_free_slots":{"before":1683700,"after":1584989,"diff":-98711},"heap_final_slots":{"before":0,"after":0,"diff":0},"heap_marked_slots":{"before":2542704,"after":2542704,"diff":0},"heap_eden_pages":{"before":10369,"after":10369,"diff":0},"heap_tomb_pages":{"before":0,"after":0,"diff":0},"total_allocated_pages":{"before":10369,"after":10369,"diff":0},"total_freed_pages":{"before":0,"after":0,"diff":0},"total_allocated_objects":{"before":24896308,"after":24995019,"diff":98711},"total_freed_objects":{"before":22353599,"after":22353599,"diff":0},"malloc_increase_bytes":{"before":140032,"after":6650240,"diff":6510208},"malloc_increase_bytes_limit":{"before":25804104,"after":25804104,"diff":0},"minor_gc_count":{"before":94,"after":94,"diff":0},"major_gc_count":{"before":33,"after":33,"diff":0},"remembered_wb_unprotected_objects":{"before":34284,"after":34284,"diff":0},"remembered_wb_unprotected_objects_limit":{"before":68568,"after":68568,"diff":0},"old_objects":{"before":2404725,"after":2404725,"diff":0},"old_objects_limit":{"before":4809450,"after":4809450,"diff":0},"oldmalloc_increase_bytes":{"before":140032,"after":6650240,"diff":6510208},"oldmalloc_increase_bytes_limit":{"before":68537556,"after":68537556,"diff":0}},"time_to_finish":0.12298400001600385,"number_of_sql_calls":70,"memory_usage":"0.0 MiB","label":"process_48616"} +``` + +## `geo.log`[](#geolog-premium-only "Permalink") + +> 在 9.5 中引入. + +Geo 将结构化日志消息存储在`geo.log`文件中. 对于 Omnibus 安装,此文件位于`/var/log/gitlab/gitlab-rails/geo.log` . + +该文件包含有关 Geo 何时尝试同步存储库和文件的信息. 文件中的每一行都包含一个可以提取的单独的 JSON 条目. 例如,Elasticsearch 或 Splunk. + +For example: + +``` +{"severity":"INFO","time":"2017-08-06T05:40:16.104Z","message":"Repository update","project_id":1,"source":"repository","resync_repository":true,"resync_wiki":true,"class":"Gitlab::Geo::LogCursor::Daemon","cursor_delay_s":0.038} +``` + +此消息表明,Geo 检测到项目`1`需要存储库更新. + +## Registry Logs[](#registry-logs "Permalink") + +对于 Omnibus 安装,容器注册表日志位于`/var/log/gitlab/registry/current` . + +## NGINX Logs[](#nginx-logs "Permalink") + +对于 Omnibus 安装,NGINX 日志位于: + +* `/var/log/gitlab/nginx/gitlab_access.log`包含对 GitLab 的请求的日志. +* `/var/log/gitlab/nginx/gitlab_error.log`包含有关 GitLab 的 NGINX 错误的日志. +* `/var/log/gitlab/nginx/gitlab_pages_access.log`包含对 Pages 静态站点的请求的日志. +* `/var/log/gitlab/nginx/gitlab_pages_error.log`包含 Pages 静态站点的 NGINX 错误日志. +* `/var/log/gitlab/nginx/gitlab_registry_access.log`包含对容器注册表进行的请求的日志. +* `/var/log/gitlab/nginx/gitlab_registry_error.log`包含容器注册表的 NGINX 错误日志. +* `/var/log/gitlab/nginx/gitlab_mattermost_access.log`包含对 Mattermost 的请求日志. +* `/var/log/gitlab/nginx/gitlab_mattermost_error.log`包含 Mattermost 的 NGINX 错误日志. + +以下是默认的 GitLab NGINX 访问日志格式: + +``` +$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" +``` + +## Pages Logs[](#pages-logs "Permalink") + +对于 Omnibus 安装,Pages 日志位于`/var/log/gitlab/gitlab-pages/current` . + +例如: + +``` +{ "level": "info", "msg": "GitLab Pages Daemon", "revision": "52b2899", "time": "2020-04-22T17:53:12Z", "version": "1.17.0" } { "level": "info", "msg": "URL: https://gitlab.com/gitlab-org/gitlab-pages", "time": "2020-04-22T17:53:12Z" } { "gid": 998, "in-place": false, "level": "info", "msg": "running the daemon as unprivileged user", "time": "2020-04-22T17:53:12Z", "uid": 998 } +``` + +## Mattermost Logs[](#mattermost-logs "Permalink") + +For Omnibus GitLab installations, Mattermost logs reside in `/var/log/gitlab/mattermost/mattermost.log`. + +## Workhorse Logs[](#workhorse-logs "Permalink") + +对于 Omnibus GitLab 安装,Workhorse 日志位于`/var/log/gitlab/gitlab-workhorse/` . + +## PostgreSQL Logs[](#postgresql-logs "Permalink") + +对于 Omnibus GitLab 安装,PostgreSQL 日志位于`/var/log/gitlab/postgresql/` . + +## Prometheus Logs[](#prometheus-logs "Permalink") + +对于 Omnibus GitLab 安装,Prometheus 日志位于`/var/log/gitlab/prometheus/` . + +## Redis Logs[](#redis-logs "Permalink") + +对于所有安装的 GitLab,它返回的日志位于`/var/log/gitlab/redis/` . + +## Alertmanager Logs[](#alertmanager-logs "Permalink") + +对于 Omnibus GitLab 安装,Alertmanager 日志位于`/var/log/gitlab/alertmanager/` . + +## Crond Logs[](#crond-logs "Permalink") + +对于 Omnibus GitLab 安装,crond 日志位于`/var/log/gitlab/crond/` . + +## Grafana Logs[](#grafana-logs "Permalink") + +对于 Omnibus GitLab 安装,Grafana 日志位于`/var/log/gitlab/grafana/` . + +## LogRotate Logs[](#logrotate-logs "Permalink") + +对于 Omnibus GitLab 安装,logrotate 日志位于`/var/log/gitlab/logrotate/` . + +## GitLab Monitor Logs[](#gitlab-monitor-logs "Permalink") + +对于 Omnibus GitLab 安装,GitLab Monitor 日志位于`/var/log/gitlab/gitlab-monitor/` . + +## GitLab Exporter[](#gitlab-exporter "Permalink") + +对于 Omnibus GitLab 安装,GitLab Exporter 日志位于`/var/log/gitlab/gitlab-exporter/` . \ No newline at end of file diff --git a/docs/452.md b/docs/452.md new file mode 100644 index 0000000000000000000000000000000000000000..e0522df80108620e3f48ac5a8a8b7f723589a0da --- /dev/null +++ b/docs/452.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/administration/auth/README.html](https://docs.gitlab.com/ee/administration/auth/README.html) \ No newline at end of file diff --git a/docs/453.md b/docs/453.md new file mode 100644 index 0000000000000000000000000000000000000000..3afcd0f4097e4f57fd0752944ab411cad6f9d7ef --- /dev/null +++ b/docs/453.md @@ -0,0 +1,186 @@ +# PlantUML & GitLab + +> 原文:[https://docs.gitlab.com/ee/administration/integration/plantuml.html](https://docs.gitlab.com/ee/administration/integration/plantuml.html) + +* [PlantUML Server](#plantuml-server) + * [Docker](#docker) + * [Debian/Ubuntu](#debianubuntu) + * [Making local PlantUML accessible using custom GitLab setup](#making-local-plantuml-accessible-using-custom-gitlab-setup) + * [Security](#security) +* [GitLab](#gitlab) +* [Creating Diagrams](#creating-diagrams) + +# PlantUML & GitLab[](#plantuml--gitlab "Permalink") + +在 GitLab 8.16 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8537) . + +在 GitLab 中启用并配置[PlantUML](https://plantuml.com)集成后,我们便能够在片段,Wiki 和存储库中创建的 AsciiDoc 和 Markdown 文档中创建简单的图表. + +## PlantUML Server[](#plantuml-server "Permalink") + +在 GitLab 中启用 PlantUML 之前; 您需要设置自己的 PlantUML 服务器以生成图表. + +### Docker[](#docker "Permalink") + +使用 Docker,您可以仅运行如下容器: + +``` +docker run -d --name plantuml -p 8080:8080 plantuml/plantuml-server:tomcat +``` + +**PlantUML URL**将是运行容器的服务器的主机名. + +在 Docker 中运行 GitLab 时,它将需要有权访问 PlantUML 容器. 最简单的方法是使用[Docker Compose](https://s0docs0docker0com.icopy.site/compose/) . + +一个简单`docker-compose.yml`文件将是: + +``` +version: "3" +services: + gitlab: + image: 'gitlab/gitlab-ce:12.2.5-ce.0' + environment: + GITLAB_OMNIBUS_CONFIG: | + nginx['custom_gitlab_server_config'] = "location /-/plantuml/ { \n proxy_cache off; \n proxy_pass http://plantuml:8080/; \n}\n" + + plantuml: + image: 'plantuml/plantuml-server:tomcat' + container_name: plantuml +``` + +在这种情况下,可以通过 URL `http://plantuml:8080/`访问 GitLab 的`http://plantuml:8080/` . + +### Debian/Ubuntu[](#debianubuntu "Permalink") + +在使用 Tomcat 的 Debian / Ubuntu 发行版中,安装和配置自己的 PlantUML 服务器非常容易. + +首先,您需要从源代码创建一个`plantuml.war`文件: + +``` +sudo apt-get install graphviz openjdk-8-jdk git-core maven +git clone https://github.com/plantuml/plantuml-server.git +cd plantuml-server +mvn package +``` + +上面的命令序列将生成可以使用 Tomcat 部署的 WAR 文件: + +``` +sudo apt-get install tomcat8 +sudo cp target/plantuml.war /var/lib/tomcat8/webapps/plantuml.war +sudo chown tomcat8:tomcat8 /var/lib/tomcat8/webapps/plantuml.war +sudo service tomcat8 restart +``` + +Tomcat 服务重新启动后,PlantUML 服务将准备就绪,并在端口 8080 上侦听请求: + +``` +http://localhost:8080/plantuml +``` + +您可以通过编辑`/etc/tomcat8/server.xml`文件来更改这些默认值. + +请注意,默认 URL 与使用基于 Docker 的映像时不同,后者在 URL 的根目录中提供服务,而没有相对路径. 相应地调整以下配置. + +### Making local PlantUML accessible using custom GitLab setup[](#making-local-plantuml-accessible-using-custom-gitlab-setup "Permalink") + +PlantUML 服务器在您的服务器上本地运行,因此无法从外部访问. 因此,有必要捕获外部 PlantUML 调用并将其重定向到本地服务器. + +想法是将每次调用`https://gitlab.example.com/-/plantuml/`重定向到本地 PlantUML 服务器`http://plantuml:8080/`或`http://localhost:8080/plantuml/` ,具体取决于您的建立. + +要启用重定向,请在`/etc/gitlab/gitlab.rb`添加以下行: + +``` +# Docker deployment +nginx['custom_gitlab_server_config'] = "location /-/plantuml/ { \n proxy_cache off; \n proxy_pass http://plantuml:8080/; \n}\n" + +# Built from source +nginx['custom_gitlab_server_config'] = "location /-/plantuml { \n rewrite ^/-/(plantuml.*) /$1 break;\n proxy_cache off; \n proxy_pass http://localhost:8080/plantuml; \n}\n" +``` + +要激活更改,请运行以下命令: + +``` +sudo gitlab-ctl reconfigure +``` + +### Security[](#security "Permalink") + +PlantUML 具有允许获取网络资源的功能. + +``` +@startuml +start + ' ... + !include http://localhost/ +stop; +@enduml +``` + +**如果您自行托管 PlantUML 服务器,则应放置网络控件以隔离它.** + +## GitLab[](#gitlab "Permalink") + +您需要从"管理"区域下的"设置"启用 PlantUML 集成. 为此,请使用管理员帐户登录并执行以下操作: + +* 在 GitLab 中,转到**管理区域>设置>集成** . +* 展开**PlantUML**部分. +* Check **启用 PlantUML** checkbox. +* Set the PlantUML instance as `https://gitlab.example.com/-/plantuml/`. + +**注意:**如果使用的是运行 v1.2020.9 及更高版本的 PlantUML 服务器(例如[plantuml.com](https://plantuml.com) ),请设置`PLANTUML_ENCODING`环境变量以启用`deflate`压缩. 在 Omnibus 上,可以在`/etc/gitlab.rb`进行设置: + +``` +gitlab_rails['env'] = { 'PLANTUML_ENCODING' => 'deflate' } +``` + +从 GitLab 13.1 和更高版本开始,PlantUML 集成现在[需要 URL 中的标头前缀](https://github.com/plantuml/plantuml/issues/117#issuecomment-6235450160)来区分不同的编码类型. + +## Creating Diagrams[](#creating-diagrams "Permalink") + +启用并配置 PlantUML 集成后,我们可以开始使用分隔的块向我们的 AsciiDoc 代码片段,Wiki 和存储库添加图表: + +* **Markdown** + + ``` + ```plantuml Bob -> Alice : hello + Alice -> Bob : hi + ``` + ``` + +* **AsciiDoc** + + ``` + [plantuml, format="png", id="myDiagram", width="200px"] + ---- + Bob->Alice : hello + Alice -> Bob : hi + ---- + ``` + +* **reStructuredText** + + ``` + .. plantuml:: + :caption: Caption with **bold** and *italic* + + Bob -> Alice: hello + Alice -> Bob: hi + ``` + + 您也可以使用`uml::`指令与[`sphinxcontrib-plantuml`](https://s0pypi0org.icopy.site/project/sphinxcontrib-plantuml/)兼容,但是请注意,我们目前仅支持`caption`选项. + +上面的块将被转换为 HTML 图像标签,其源指向 PlantUML 实例. 如果已正确配置 PlantUML 服务器,则应呈现一个不错的图而不是块: + +![](img/d19e6203a8567c2d6be7d878dd653654.png) + +在块内,您可以通过 PlantUML 添加任何受支持的图,例如[Sequence](https://plantuml.com/sequence-diagram) , [Use Case](https://plantuml.com/use-case-diagram) , [Class](https://plantuml.com/class-diagram) , [Activity](https://plantuml.com/activity-diagram-legacy) , [Component](https://plantuml.com/component-diagram) , [State](https://plantuml.com/state-diagram)和[Object](https://plantuml.com/object-diagram)图. 您不需要使用 PlantUML 图定界符`@startuml` / `@enduml`因为它们已被 AsciiDoc `plantuml`块替换. + +可以将一些参数添加到 AsciiDoc 块定义中: + +* `format` :可以是`png`或`svg` . 请注意,并非所有浏览器都支持`svg` ,因此请谨慎使用. 默认值为`png` . +* `id` :添加到图 HTML 标记的 CSS ID. +* `width` :宽度属性添加到图像标签. +* `height` :高度属性添加到图像标签. + +Markdown 不支持任何参数,并且将始终使用 PNG 格式. \ No newline at end of file diff --git a/docs/454.md b/docs/454.md new file mode 100644 index 0000000000000000000000000000000000000000..a3b0da4f102e701d5ab7eb7f39fab6b2457959bc --- /dev/null +++ b/docs/454.md @@ -0,0 +1,32 @@ +# Repository checks + +> 原文:[https://docs.gitlab.com/ee/administration/repository_checks.html](https://docs.gitlab.com/ee/administration/repository_checks.html) + +* [Periodic checks](#periodic-checks) +* [Disabling periodic checks](#disabling-periodic-checks) +* [What to do if a check failed](#what-to-do-if-a-check-failed) + +# Repository checks[](#repository-checks "Permalink") + +在 GitLab 8.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3232) . + +Git 具有内置机制[`git fsck`](https://git-scm.com/docs/git-fsck) ,以验证提交到存储库的所有数据的完整性. GitLab 管理员可以通过管理面板下的项目页面触发对项目的检查. 由于检查是异步进行的,因此可能需要几分钟才能在项目管理页面上看到检查结果. 如果检查失败,则可以在[`repocheck.log`文件中](logs.html#repochecklog)看到其输出[.](logs.html#repochecklog) + +**注意:**默认情况下为 OFF,因为它仍然会导致过多的错误警报. + +## Periodic checks[](#periodic-checks "Permalink") + +启用后,GitLab 会定期在所有项目存储库和 Wiki 存储库上运行存储库检查,以检测数据损坏. 一个项目每月检查不超过一次. 如果任何项目未能通过其存储库检查,则所有 GitLab 管理员都将收到有关情况的电子邮件通知. 默认情况下,该通知每周一次发送,默认为星期日开始的午夜. 可以在`/admin/projects?last_repository_check_failed=1`找到具有已知检查失败的存储库. + +## Disabling periodic checks[](#disabling-periodic-checks "Permalink") + +You can disable the periodic checks on the ‘Settings’ page of the admin panel. + +## What to do if a check failed[](#what-to-do-if-a-check-failed "Permalink") + +如果某个存储库的存储库检查失败,则应在磁盘上的[`repocheck.log`文件中](logs.html#repochecklog)查找错误: + +* `/var/log/gitlab/gitlab-rails`用于所有安装 +* `/home/git/gitlab/log`用于从源代码进行安装 + +如果定期的存储库检查导致错误警报,则可以通过导航到" **管理区域">"设置">"存储库"** ( `/admin/application_settings/repository` )并单击" **清除所有存储库检查"**来**清除所有存储库检查状态** . \ No newline at end of file diff --git a/docs/455.md b/docs/455.md new file mode 100644 index 0000000000000000000000000000000000000000..115cfc9cc238c7a3b0fa16679e2939271f5b7e80 --- /dev/null +++ b/docs/455.md @@ -0,0 +1,94 @@ +# Repository storage paths + +> 原文:[https://docs.gitlab.com/ee/administration/repository_storage_paths.html](https://docs.gitlab.com/ee/administration/repository_storage_paths.html) + +* [Configure GitLab](#configure-gitlab) +* [Choose where new repositories will be stored](#choose-where-new-repositories-will-be-stored) + +# Repository storage paths[](#repository-storage-paths "Permalink") + +在 GitLab 8.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4578) . + +GitLab 允许您定义多个存储库存储路径(有时称为存储碎片),以在多个安装点之间分配存储负载. + +> **Notes:** +> +> * 您必须至少有一个名为`default`存储路径. +> * 路径在键值对中定义. 密钥是一个任意名称,您可以选择该名称来命名文件路径. +> * 目标目录及其任何子路径不得为符号链接. +> * 目标目录不能是另一个目录的子目录. 没有嵌套. + +示例:这可以: + +``` +default: + path: /mnt/git-storage-1 +storage2: + path: /mnt/git-storage-2 +``` + +这不行,因为它嵌套了存储路径: + +``` +default: + path: /mnt/git-storage-1 +storage2: + path: /mnt/git-storage-1/git-storage-2 # <- NOT OK because of nesting +``` + +## Configure GitLab[](#configure-gitlab "Permalink") + +> **警告:**为了使[备份](../raketasks/backup_restore.html)正常工作,存储路径**不得**为挂载点,并且 GitLab 用户应对该路径的父目录具有正确的权限. 在 Omnibus GitLab 中,这是自动处理的,但是对于源代码安装,您应该格外小心. +> +> 事实是,出于兼容性原因, `gitlab.yml`与 Omnibus 具有不同的结构. 在`gitlab.yml`您指示存储库的路径,例如`/home/git/repositories` ,而在 Omnibus 中,您指示`git_data_dirs` ,对于上面的示例,它是`/home/git` . 然后,Omnibus 将在该路径下创建一个`repositories`目录,以与`gitlab.yml`一起使用. +> +> 这个小细节很重要,因为在还原备份时, `/home/git/repositories`的当前内容[已移至](https://gitlab.com/gitlab-org/gitlab/blob/033e5423a2594e08a7ebcd2379bd2331f4c39032/lib/backup/repository.rb#L54-56) `/home/git/repositories.old` ,因此,如果`/home/git/repositories`是安装点,则`mv`会移动挂载点之间发生故障,并且可能发生不良情况. 理想情况下, `/home/git`是挂载点,因此事情将在同一挂载点内移动. Omnibus 安装可以保证这一点(因为它们没有指定完整的存储库路径,而是指定父路径),但对于源安装则没有保证. + +现在,您已经阅读了上面的警告提示,让我们编辑配置文件并添加备用存储库存储路径的完整路径. 在下面的示例中,我们添加了另外两个挂载点,分别称为`nfs_1`和`nfs_2` . + +**Note:** This example uses NFS. We do not recommend using EFS for storage as it may impact GitLab’s performance. See the [relevant documentation](high_availability/nfs.html#avoid-using-awss-elastic-file-system-efs) for more details. + +**对于源安装** + +1. 编辑`gitlab.yml`并添加存储路径: + + ``` + repositories: + # Paths where repositories can be stored. Give the canonicalized absolute pathname. + # NOTE: REPOS PATHS MUST NOT CONTAIN ANY SYMLINK!!! + storages: # You must have at least a 'default' storage path. + default: + path: /home/git/repositories + nfs_1: + path: /mnt/nfs1/repositories + nfs_2: + path: /mnt/nfs2/repositories + ``` + +2. [重新启动 GitLab,](restart_gitlab.html#installations-from-source)以使更改生效. + +> **注:** [`gitlab_shell: repos_path`条目](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/8-9-stable/config/gitlab.yml.example#L457)中`gitlab.yml`将被弃用,取而代之的是`repositories: storages`在未来,所以如果你是从之前的版本升级 8.10,确保如在上述步骤中所描述的添加配置. 进行更改并确认它们可以使用之后,可以删除`repos_path`行. + +**对于所有安装** + +1. 通过将其余路径附加到默认路径中来编辑`/etc/gitlab/gitlab.rb` : + + ``` + git_data_dirs({ + "default" => { "path" => "/var/opt/gitlab/git-data" }, + "nfs_1" => { "path" => "/mnt/nfs1/git-data" }, + "nfs_2" => { "path" => "/mnt/nfs2/git-data" } + }) + ``` + + 请注意,Omnibus 将存储库存储在`git-data`目录的`repositories`子目录中. + +## Choose where new repositories will be stored[](#choose-where-new-repositories-will-be-stored "Permalink") + +设置了多个存储路径后,您可以在**管理区域>设置>存储库>存储库存储>新存储库的存储节点下选择新存储库的存储位置** . + +可以为每个存储分配 0 到 100 的权重. 创建新项目时,将使用这些权重来确定将在其上创建存储库的存储位置. + +[![Choose repository storage path in Admin Area](img/fc80ee243381890526471d6fc360f7cf.png)](img/repository_storages_admin_ui_v13_1.png) + +从 GitLab 8.13.4 开始,可以选择多个路径. 新存储库将随机放置在所选路径之一上. \ No newline at end of file diff --git a/docs/456.md b/docs/456.md new file mode 100644 index 0000000000000000000000000000000000000000..c33c9b3cfeee5f0ab0e392d0269b5ffd2bc0fed0 --- /dev/null +++ b/docs/456.md @@ -0,0 +1,166 @@ +# Repository storage types + +> 原文:[https://docs.gitlab.com/ee/administration/repository_storage_types.html](https://docs.gitlab.com/ee/administration/repository_storage_types.html) + +* [Hashed storage](#hashed-storage) + * [Translating hashed storage paths](#translating-hashed-storage-paths) + * [From project name to hashed path](#from-project-name-to-hashed-path) + * [From hashed path to project name](#from-hashed-path-to-project-name) + * [Hashed object pools](#hashed-object-pools) + * [Hashed storage coverage migration](#hashed-storage-coverage-migration) + * [Avatars](#avatars) + * [CI artifacts](#ci-artifacts) + * [LFS objects](#lfs-objects) +* [Legacy storage](#legacy-storage) + +# Repository storage types[](#repository-storage-types-core-only "Permalink") + +版本历史 + +* 在 GitLab 10.0 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28283) . +* 静默存储已成为 GitLab 12.0 中新安装的默认存储 +* 默认情况下,在 GitLab 13.0 中为新项目和重命名项目启用了哈希存储. + +可以将 GitLab 配置为使用一个或多个存储库存储路径/碎片位置,它们可以是: + +* 挂载到本地磁盘 +* 公开为 NFS 共享卷 +* 在自己的计算机上通过[Gitaly](gitaly/index.html)访问. + +在 GitLab 中,这是通过`git_data_dirs({})`配置哈希值在`/etc/gitlab/gitlab.rb`进行配置的. 此处讨论的存储布局将适用于其中定义的所有分片. + +在未自定义它的任何安装中可用的`default`存储库碎片指向本地文件夹: `/var/opt/gitlab/git-data` . 下面讨论的所有内容都应属于该文件夹. + +## Hashed storage[](#hashed-storage "Permalink") + +**注意:**在 GitLab 13.0 中,默认情况下启用了哈希存储,并且不建议使用旧存储. 在 GitLab 14.0 中将删除对旧存储的支持. 如果您尚未迁移,请查看[迁移说明](raketasks/storage.html#migrate-to-hashed-storage) . 在管理区域中的哈希存储和旧存储之间进行选择的选项已被禁用. + +哈希存储是我们从 10.0 开始推出的存储行为. 与其耦合项目 URL 和将存储库存储在磁盘上的文件夹结构,不如基于项目 ID 耦合散列. 这使得文件夹结构不可变,因此消除了将状态从 URL 同步到磁盘结构的任何要求. 这意味着重命名组,用户或项目将仅花费数据库事务的费用,并且将立即生效. + +哈希还有助于将存储库更均匀地分布在磁盘上,因此顶层目录包含的文件夹少于顶层命名空间的总数. + +哈希格式基于 SHA256 的十六进制表示形式: `SHA256(project.id)` . 顶级文件夹使用前两个字符,然后是另一个文件夹,其后两个字符. 它们都存储在特殊的`@hashed`文件夹中,以便能够与现有的 Legacy Storage 项目共存: + +``` +# Project's repository: +"@hashed/#{hash[0..1]}/#{hash[2..3]}/#{hash}.git" + +# Wiki's repository: +"@hashed/#{hash[0..1]}/#{hash[2..3]}/#{hash}.wiki.git" +``` + +### Translating hashed storage paths[](#translating-hashed-storage-paths "Permalink") + +对 Git 存储库中的问题进行故障排除,添加挂钩和其他任务,将需要您在人类可读的项目名称和哈希存储路径之间进行转换. + +#### From project name to hashed path[](#from-project-name-to-hashed-path "Permalink") + +哈希路径显示在项目页面的[admin 区域中](../user/admin_area/index.html#administering-projects) . + +要访问"项目"页面,请转到" **管理区域">"概述">"项目"** ,然后打开该项目的页面. + +此处显示" Gitaly 相对路径",例如: + +``` +"@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git" +``` + +这是默认 Omnibus 安装中`/var/opt/gitlab/git-data/repositories/`下的路径. + +在[Rails 控制台中](troubleshooting/debug.html#starting-a-rails-console-session) ,使用数字项目 ID 或完整路径获取此信息: + +``` +Project.find(16).disk_path +Project.find_by_full_path('group/project').disk_path +``` + +#### From hashed path to project name[](#from-hashed-path-to-project-name "Permalink") + +要将哈希存储路径转换为项目名称,请执行以下操作: + +1. 启动[Rails 控制台](troubleshooting/debug.html#starting-a-rails-console-session) . +2. 运行以下命令: + +``` +ProjectRepository.find_by(disk_path: '@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9').project +``` + +该命令中带引号的字符串是您在 GitLab 服务器上找到的目录树. 例如,在默认的 Omnibus 安装上,该`.git`将是`/var/opt/gitlab/git-data/repositories/@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git`从目录名称的末尾删除. + +输出包括项目 ID 和项目名称: + +``` +=> # +``` + +### Hashed object pools[](#hashed-object-pools "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitaly/-/issues/1606) . + +**危险:**不要在池存储库中运行`git prune`或`git gc` ! 这可能会导致依赖于相关池的"实际"存储库中的数据丢失. + +通过创建第三个存储库(对象池)对公共项目的分支进行重复数据删除,其中包含来自源项目的对象. 使用`objects/info/alternates` ,源项目和派生将对象池用于共享对象. 当在源项目上运行内务管理时,会将对象从源项目移动到对象池. + +``` +# object pool paths +"@pools/#{hash[0..1]}/#{hash[2..3]}/#{hash}.git" +``` + +### Hashed storage coverage migration[](#hashed-storage-coverage-migration "Permalink") + +如果存储在 S3 兼容端点中的文件没有前缀`#{namespace}/#{project_name}` (对于 CI Cache 和 LFS 对象是正确的`#{namespace}/#{project_name}` ,则不会有前面提到的缺点. + +在下表中,您可以找到迁移到哈希存储的范围. + +| 可存储对象 | 旧版存储 | 杂物箱 | 兼容 S3 | GitLab 版本 | +| --- | --- | --- | --- | --- | +| Repository | Yes | Yes | - | 10.0 | +| Attachments | Yes | Yes | - | 10.2 | +| Avatars | Yes | No | - | - | +| Pages | Yes | No | - | - | +| Docker 注册表 | Yes | No | - | - | +| CI 构建日志 | No | No | - | - | +| CI Artifacts | No | No | Yes | 9.4 / 10.6 | +| CI 缓存 | No | No | Yes | - | +| LFS 对象 | Yes | Similar | Yes | 10.0 / 10.7 | +| 储存库 | No | Yes | - | 11.6 | + +#### Avatars[](#avatars "Permalink") + +每个文件都以其`id`来自数据库的形式存储在一个文件夹中. 用户头像的文件名始终为`avatar.png` . 替换头像后, `Upload`模型将被销毁,并使用另一个`id`进行替换. + +#### CI artifacts[](#ci-artifacts "Permalink") + +CI Artifacts 从**9.4** (GitLab Premium)开始兼容 S3,从**10.6**开始在 GitLab Core 中可用. + +#### LFS objects[](#lfs-objects "Permalink") + +[GitLab 中的 LFS 对象](../topics/git/lfs/index.html)遵循 Git 自己的实现,使用 2 个字符,2 个级别的文件夹实现了类似的存储模式: + +``` +"shared/lfs-objects/#{oid[0..1}/#{oid[2..3]}/#{oid[4..-1]}" + +# Based on object `oid`: `8909029eb962194cfb326259411b22ae3f4a814b5be4f80651735aeef9f3229c`, path will be: +"shared/lfs-objects/89/09/029eb962194cfb326259411b22ae3f4a814b5be4f80651735aeef9f3229c" +``` + +LFS 对象也与[S3 兼容](lfs/index.html#storing-lfs-objects-in-remote-object-storage) . + +## Legacy storage[](#legacy-storage "Permalink") + +**不建议使用:**在 GitLab 13.0 中,默认情况下启用了哈希存储,并且不建议使用旧存储. 如果您尚未迁移,请查看[迁移说明](raketasks/storage.html#migrate-to-hashed-storage) . 在 GitLab 14.0 中将删除对旧存储的支持. 如果您使用的是 GitLab 13.0 及更高版本,则无法将新项目切换到旧版存储. 在管理区域中的哈希存储和旧存储之间进行选择的选项已被禁用. + +旧版存储是 10.0 版之前的存储行为. 由于历史原因,GitLab 从项目 URL 复制了相同的映射结构: + +* 项目的存储库: `#{namespace}/#{project_name}.git` +* 项目的 Wiki: `#{namespace}/#{project_name}.wiki.git` + +这种结构使从现有解决方案到 GitLab 的迁移变得简单,并且管理员可以轻松找到存储库的存储位置. + +On the other hand this has some drawbacks: + +存储位置将集中大量的顶级名称空间. 可以通过引入[多个存储路径](repository_storage_paths.html)来减少影响. + +由于备份是相同 URL 映射的快照,因此,如果您尝试恢复非常旧的备份,则需要验证是否有任何项目代替了共享相同 URL 的旧项目或已重命名的项目. 这意味着您备份中的`mygroup/myproject`可能与今天使用相同 URL 的原始项目不同. + +URL 的任何更改都需要反映在磁盘上(重命名组/用户或项目时). 在大型安装中,这可能会增加很多负载,尤其是在使用任何类型的基于网络的文件系统时. \ No newline at end of file diff --git a/docs/457.md b/docs/457.md new file mode 100644 index 0000000000000000000000000000000000000000..1d3596689adfe40c420088648d525051dfeb75fd --- /dev/null +++ b/docs/457.md @@ -0,0 +1,167 @@ +# Account and limit settings + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/settings/account_and_limit_settings.html](https://docs.gitlab.com/ee/user/admin_area/settings/account_and_limit_settings.html) + +* [Max attachment size](#max-attachment-size) +* [Max import size](#max-import-size) +* [Maximum namespace storage size](#maximum-namespace-storage-size) +* [Repository size limit](#repository-size-limit-starter-only) + * [How it works](#how-it-works) +* [Troubleshooting](#troubleshooting) + * [413 Request Entity Too Large](#413-request-entity-too-large) +* [Limiting lifetime of personal access tokens](#limiting-lifetime-of-personal-access-tokens-ultimate-only) + * [Setting a limit](#setting-a-limit) +* [Optional enforcement of Personal Access Token expiry](#optional-enforcement-of-personal-access-token-expiry-ultimate-only) + * [Enable or disable optional enforcement of Personal Access Token expiry Feature](#enable-or-disable-optional-enforcement-of-personal-access-token-expiry-feature-core-only) +* [Disabling user profile name changes](#disabling-user-profile-name-changes-premium-only) + +# Account and limit settings[](#account-and-limit-settings-core-only "Permalink") + +## Max attachment size[](#max-attachment-size "Permalink") + +您可以在 GitLab 中更改评论和回复中附件的最大文件大小. 导航至**管理区域(扳手图标)>设置>常规** ,然后展开**帐户和限制** . 在此处,您可以通过更改`Maximum attachment size (MB)`的值来增加或减少. + +**注意:**如果选择的大小大于当前为 Web 服务器配置的大小,则可能会出现错误. 有关更多详细信息,请参见[故障排除部分](#troubleshooting) . + +## Max import size[](#max-import-size "Permalink") + +您可以在 GitLab 中更改导入的最大文件大小. 导航至**管理区域(扳手图标)>设置>常规** ,然后展开**帐户和限制** . 在这里,您可以通过更改`Maximum import size (MB)`的值来增加或减少. + +**注意:**如果选择的大小大于当前为 Web 服务器配置的大小,则可能会出现错误. 有关更多详细信息,请参见[故障排除部分](#troubleshooting) . + +## Maximum namespace storage size[](#maximum-namespace-storage-size "Permalink") + +这为每个名称空间设置了最大大小限制. 名称空间大小包括以下内容: + +* repository +* wiki +* LFS 对象 +* 建立工件 +* packages + +**注意:**此限制当前未实施,但将在将来的版本中使用. + +## Repository size limit[](#repository-size-limit-starter-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/740) in [GitLab Enterprise Edition 8.12](https://about.gitlab.com/releases/2016/09/22/gitlab-8-12-released/#limit-project-size-ee). + +GitLab 实例中的存储库可以快速增长,尤其是在使用 LFS 的情况下. 它们的大小可以成倍增长,迅速消耗可用的存储空间. + +为避免这种情况发生,您可以为存储库的大小设置硬限制. 可以在全局,每个组或每个项目中设置此限制,其中每个项目的限制为最高优先级. + +在许多用例中,您可能会设置存储库大小的限制. 例如,考虑以下工作流程: + +1. 您的团队开发的应用程序需要将大文件存储在应用程序存储库中. +2. 尽管您已为项目启用了[Git LFS](../../../topics/git/lfs/index.html#git-large-file-storage-lfs) ,但您的存储量已显着增长. +3. 在超出可用存储空间之前,每个存储库设置的最大限制为 10 GB. + +### How it works[](#how-it-works "Permalink") + +只有 GitLab 管理员才能设置这些限制. 将限制设置为`0`表示没有限制. + +这些设置可以在以下位置找到: + +* 每个项目的设置: + 1. 在项目的主页上,导航至**"设置">"常规"** . + 2. 在" **命名,主题,头像"**部分中填写" **存储库大小限制(MB)"**字段. + 3. 点击**保存更改** . +* 每个组的设置: + 1. 在网上论坛的主页上,导航至**设置>常规** . + 2. 填写" **命名,可见性"**部分中的" **存储库大小限制(MB)"**字段. + 3. 点击**保存更改** . +* GitLab 的全局设置: + 1. 在控制台中,导航至**管理区域>设置>常规** . + 2. 展开**帐户和限制**部分. + 3. 填写**每个存储库**的**大小限制(MB)**字段. + 4. 点击**保存更改** . + +包括 LFS 对象在内的新项目的第一次推送将进行大小检查,如果它们的大小总和超过允许的最大存储库大小, **则将**拒绝该推送. + +**注意:**存储库大小限制包括存储库文件和 LFS,并且不包括工件. + +有关手动清除文件的详细信息,请参阅[使用 Git 减小存储库大小](../../project/repository/reducing_the_repo_size_using_git.html) . + +**注意:** GitLab.com 存储库大小[由 GitLab 设置](../../gitlab_com/index.html#repository-size-limit) . + +## Troubleshooting[](#troubleshooting "Permalink") + +### 413 Request Entity Too Large[](#413-request-entity-too-large "Permalink") + +如果您在 GitLab 中将文件附加到评论或回复并收到`413 Request Entity Too Large`错误,则可能是由于[最大附件大小](#max-attachment-size)大于 Web 服务器配置允许的[最大附件大小](#max-attachment-size)引起的. + +例如,如果要在 GitLab [Omnibus](https://docs.gitlab.com/omnibus/)安装中将最大附件大小增加到 200m,则可能需要在增加最大附件大小之前`/etc/gitlab/gitlab.rb`添加到`/etc/gitlab/gitlab.rb` : + +``` +nginx['client_max_body_size'] = "200m" +``` + +## Limiting lifetime of personal access tokens[](#limiting-lifetime-of-personal-access-tokens-ultimate-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6. + +用户可以选择指定[个人访问令牌](../../profile/personal_access_tokens.html)的到期日期. 该到期日期不是必需的,可以将其设置为任意日期. + +由于个人访问令牌是通过编程访问 GitLab 所需的唯一令牌,因此具有安全性要求的组织可能希望加强保护,以要求定期循环使用这些令牌. + +### Setting a limit[](#setting-a-limit "Permalink") + +只有 GitLab 管理员才能设置限制. 将其保留为空意味着没有任何限制. + +设置有效的个人访问令牌限制: + +1. 导航到**管理区域>设置>常规** . +2. 展开**帐户和限制**部分. +3. Fill in the **个人访问令牌的最大允许生命周期(天)** field. +4. Click **保存更改**. + +一旦设置了个人访问令牌的生存期,GitLab 将: + +* 将生存期应用于新的个人访问令牌,并要求用户设置到期日期,并且日期不得晚于允许的生存期. +* 三个小时后,请吊销没有过期日期或寿命超过允许寿命的旧令牌. 允许三个小时的时间,以便管理员在撤销之前更改或删除允许的生存期. + +## Optional enforcement of Personal Access Token expiry[](#optional-enforcement-of-personal-access-token-expiry-ultimate-only "Permalink") + +版本历史 + +* 在[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/214723) . +* 它部署在功能标志后面,默认情况下处于禁用状态. +* 它在 GitLab.com 上被禁用. +* 不建议将其用于生产. +* 要在 GitLab 自管实例中使用它,请让 GitLab 管理员[启用它](#enable-or-disable-optional-enforcement-of-personal-access-token-expiry-feature-core-only) . + +GitLab 管理员可以选择防止个人访问令牌自动过期. 令牌将在到期日期之后可用,除非已将其明确吊销. + +去做这个: + +1. 导航到**管理区域>设置>常规** . +2. 展开**帐户和限制**部分. +3. 取消选中" **强制个人访问令牌到期"**复选框. + +### Enable or disable optional enforcement of Personal Access Token expiry Feature[](#enable-or-disable-optional-enforcement-of-personal-access-token-expiry-feature-core-only "Permalink") + +正在开发可选的"强制执行个人访问令牌到期",尚未准备好用于生产. 它部署在**默认情况下禁用**的功能标志的后面. [有权访问 GitLab Rails 控制台的 GitLab 管理员](../../../administration/feature_flags.html)可以从[rails 控制台](../../../administration/feature_flags.html#start-the-gitlab-rails-console)为您的实例启用它. + +要启用它: + +``` +Feature.enable(:enforce_personal_access_token_expiration) +``` + +禁用它: + +``` +Feature.disable(:enforce_personal_access_token_expiration) +``` + +## Disabling user profile name changes[](#disabling-user-profile-name-changes-premium-only "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/24605) . + +为了维护[Audit Events](../../../administration/audit_events.html)中用户详细信息的完整性,GitLab 管理员可以选择禁用用户更改其配置文件名称的功能. + +去做这个: + +1. 导航到" **管理区域">"设置">"常规"** ,然后展开" **帐户和限制"** . +2. 选中**阻止用户更改其个人资料名称**复选框. + +**注意:**禁用此功能后,GitLab 管理员仍将能够通过[管理界面](../index.html#administering-users)或[API](../../../api/users.html#user-modification)更新其实例中任何用户的名称. \ No newline at end of file diff --git a/docs/458.md b/docs/458.md new file mode 100644 index 0000000000000000000000000000000000000000..c8b69dda7a4865c95530910a3aa24699a43c682b --- /dev/null +++ b/docs/458.md @@ -0,0 +1,26 @@ +# Service templates + +> 原文:[https://docs.gitlab.com/ee/user/project/integrations/services_templates.html](https://docs.gitlab.com/ee/user/project/integrations/services_templates.html) + +* [Enable a service template](#enable-a-service-template) +* [Service for external issue trackers](#service-for-external-issue-trackers) + +# Service templates[](#service-templates "Permalink") + +使用服务模板,GitLab 管理员可以提供用于在项目级别配置集成的默认值. + +启用服务模板时,默认值将应用于**所有**尚未启用集成或未保存自定义值的项目. 这些值已预先填充在每个项目的配置页面上,以进行适用的集成. + +如果禁用模板,这些值将不再显示为默认值,而已为集成保存的所有值将保持不变. + +## Enable a service template[](#enable-a-service-template "Permalink") + +导航到**管理区域>服务模板,**然后选择要创建的服务模板. + +## Service for external issue trackers[](#service-for-external-issue-trackers "Permalink") + +下图显示了 Redmine 的示例服务模板. + +[![Redmine service template](img/1b109b486c41c14a03eea4127cec2351.png)](img/services_templates_redmine_example.png) + +对于每个项目,您仍然需要通过将上述屏幕快照中的`:issues_tracker_id`替换为外部问题跟踪器使用的 ID 来配置问题跟踪 URL. \ No newline at end of file diff --git a/docs/459.md b/docs/459.md new file mode 100644 index 0000000000000000000000000000000000000000..0ed3ad03b70ad6fe35f434dab848482f5e7732dc --- /dev/null +++ b/docs/459.md @@ -0,0 +1,247 @@ +# System hooks + +> 原文:[https://docs.gitlab.com/ee/system_hooks/system_hooks.html](https://docs.gitlab.com/ee/system_hooks/system_hooks.html) + +* [Hooks request example](#hooks-request-example) +* [Push events](#push-events) +* [Tag events](#tag-events) + * [Merge request events](#merge-request-events) +* [Repository Update events](#repository-update-events) +* [Local requests in system hooks](#local-requests-in-system-hooks) + +# System hooks[](#system-hooks "Permalink") + +您的 GitLab 实例可以对以下事件执行 HTTP POST 请求: + +* `project_create` +* `project_destroy` +* `project_rename` +* `project_transfer` +* `project_update` +* `user_add_to_team` +* `user_remove_from_team` +* `user_update_for_team` +* `user_create` +* `user_destroy` +* `user_failed_login` +* `user_rename` +* `key_create` +* `key_destroy` +* `group_create` +* `group_destroy` +* `group_rename` +* `user_add_to_group` +* `user_remove_from_group` +* `user_update_for_group` + +这些触发器中的大多数触发器是不言自明的,但是应该澄清一下`project_update`和`project_rename` : `project_update`项目的属性(名称,描述,标签等)发生更改,就会随时触发`project_update` , *除非* `path`属性也发生更改. 在这种情况下,将触发`project_rename` (例如,如果您只关心存储库 URL,则可以只监听`project_rename` ). + +每当**被阻止的**用户尝试登录并拒绝访问时,都会发送`user_failed_login` . + +可以使用系统挂钩,例如,用于在 LDAP 服务器中记录或更改信息. + +**注意:**对于 Push 和 Tag 事件,我们采用与[Webhooks](../user/project/integrations/webhooks.html)相同的结构和弃用方式,但是我们从不显示提交. + +## Hooks request example[](#hooks-request-example "Permalink") + +**请求标头**: + +``` +X-Gitlab-Event: System Hook +``` + +**创建的项目:** + +``` +{ "created_at": "2012-07-21T07:30:54Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "project_create", "name": "StoreCloud", "owner_email": "johnsmith@gmail.com", "owner_name": "John Smith", "path": "storecloud", "path_with_namespace": "jsmith/storecloud", "project_id": 74, "project_visibility": "private" } +``` + +**项目已销毁:** + +``` +{ "created_at": "2012-07-21T07:30:58Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "project_destroy", "name": "Underscore", "owner_email": "johnsmith@gmail.com", "owner_name": "John Smith", "path": "underscore", "path_with_namespace": "jsmith/underscore", "project_id": 73, "project_visibility": "internal" } +``` + +**项目更名:** + +``` +{ "created_at": "2012-07-21T07:30:58Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "project_rename", "name": "Underscore", "path": "underscore", "path_with_namespace": "jsmith/underscore", "project_id": 73, "owner_name": "John Smith", "owner_email": "johnsmith@gmail.com", "project_visibility": "internal", "old_path_with_namespace": "jsmith/overscore" } +``` + +请注意,如果命名空间发生更改,则不会触发`project_rename` . 在这种情况下,请参考`group_rename`和`user_rename` . + +**项目转移:** + +``` +{ "created_at": "2012-07-21T07:30:58Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "project_transfer", "name": "Underscore", "path": "underscore", "path_with_namespace": "scores/underscore", "project_id": 73, "owner_name": "John Smith", "owner_email": "johnsmith@gmail.com", "project_visibility": "internal", "old_path_with_namespace": "jsmith/overscore" } +``` + +**项目已更新:** + +``` +{ "created_at": "2012-07-21T07:30:54Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "project_update", "name": "StoreCloud", "owner_email": "johnsmith@gmail.com", "owner_name": "John Smith", "path": "storecloud", "path_with_namespace": "jsmith/storecloud", "project_id": 74, "project_visibility": "private" } +``` + +**新团队成员:** + +``` +{ "created_at": "2012-07-21T07:30:56Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "user_add_to_team", "access_level": "Maintainer", "project_id": 74, "project_name": "StoreCloud", "project_path": "storecloud", "project_path_with_namespace": "jsmith/storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", "user_username": "johnsmith", "user_id": 41, "project_visibility": "visibilitylevel|private" } +``` + +**团队成员已删除:** + +``` +{ "created_at": "2012-07-21T07:30:56Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "user_remove_from_team", "access_level": "Maintainer", "project_id": 74, "project_name": "StoreCloud", "project_path": "storecloud", "project_path_with_namespace": "jsmith/storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", "user_username": "johnsmith", "user_id": 41, "project_visibility": "visibilitylevel|private" } +``` + +**团队成员已更新:** + +``` +{ "created_at": "2012-07-21T07:30:56Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "user_update_for_team", "access_level": "Maintainer", "project_id": 74, "project_name": "StoreCloud", "project_path": "storecloud", "project_path_with_namespace": "jsmith/storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", "user_username": "johnsmith", "user_id": 41, "project_visibility": "visibilitylevel|private" } +``` + +**用户创建:** + +``` +{ "created_at": "2012-07-21T07:44:07Z", "updated_at": "2012-07-21T07:38:22Z", "email": "js@gitlabhq.com", "event_name": "user_create", "name": "John Smith", "username": "js", "user_id": 41 } +``` + +**用户已删除:** + +``` +{ "created_at": "2012-07-21T07:44:07Z", "updated_at": "2012-07-21T07:38:22Z", "email": "js@gitlabhq.com", "event_name": "user_destroy", "name": "John Smith", "username": "js", "user_id": 41 } +``` + +**用户登录失败:** + +``` +{ "event_name": "user_failed_login", "created_at": "2017-10-03T06:08:48Z", "updated_at": "2018-01-15T04:52:06Z", "name": "John Smith", "email": "user4@example.com", "user_id": 26, "username": "user4", "state": "blocked" } +``` + +如果通过 LDAP 阻止了用户,则`state`将为`ldap_blocked` . + +**用户重命名:** + +``` +{ "event_name": "user_rename", "created_at": "2017-11-01T11:21:04Z", "updated_at": "2017-11-01T14:04:47Z", "name": "new-name", "email": "best-email@example.tld", "user_id": 58, "username": "new-exciting-name", "old_username": "old-boring-name" } +``` + +**密钥已添加** + +``` +{ "event_name": "key_create", "created_at": "2014-08-18 18:45:16 UTC", "updated_at": "2012-07-21T07:38:22Z", "username": "root", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC58FwqHUbebw2SdT7SP4FxZ0w+lAO/erhy2ylhlcW/tZ3GY3mBu9VeeiSGoGz8hCx80Zrz+aQv28xfFfKlC8XQFpCWwsnWnQqO2Lv9bS8V1fIHgMxOHIt5Vs+9CAWGCCvUOAurjsUDoE2ALIXLDMKnJxcxD13XjWdK54j6ZXDB4syLF0C2PnAQSVY9X7MfCYwtuFmhQhKaBussAXpaVMRHltie3UYSBUUuZaB3J4cg/7TxlmxcNd+ppPRIpSZAB0NI6aOnqoBCpimscO/VpQRJMVLr3XiSYeT6HBiDXWHnIVPfQc03OGcaFqOit6p8lYKMaP/iUQLm+pgpZqrXZ9vB john@localhost", "id": 4 } +``` + +**密钥已删除** + +``` +{ "event_name": "key_destroy", "created_at": "2014-08-18 18:45:16 UTC", "updated_at": "2012-07-21T07:38:22Z", "username": "root", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC58FwqHUbebw2SdT7SP4FxZ0w+lAO/erhy2ylhlcW/tZ3GY3mBu9VeeiSGoGz8hCx80Zrz+aQv28xfFfKlC8XQFpCWwsnWnQqO2Lv9bS8V1fIHgMxOHIt5Vs+9CAWGCCvUOAurjsUDoE2ALIXLDMKnJxcxD13XjWdK54j6ZXDB4syLF0C2PnAQSVY9X7MfCYwtuFmhQhKaBussAXpaVMRHltie3UYSBUUuZaB3J4cg/7TxlmxcNd+ppPRIpSZAB0NI6aOnqoBCpimscO/VpQRJMVLr3XiSYeT6HBiDXWHnIVPfQc03OGcaFqOit6p8lYKMaP/iUQLm+pgpZqrXZ9vB john@localhost", "id": 4 } +``` + +**组创建:** + +``` +{ "created_at": "2012-07-21T07:30:54Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "group_create", "name": "StoreCloud", "owner_email": null, "owner_name": null, "path": "storecloud", "group_id": 78 } +``` + +`owner_name`和`owner_email`始终为`null` . 请参阅[https://gitlab.com/gitlab-org/gitlab/-/issues/20011](https://gitlab.com/gitlab-org/gitlab/-/issues/20011) . + +**组已删除:** + +``` +{ "created_at": "2012-07-21T07:30:54Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "group_destroy", "name": "StoreCloud", "owner_email": null, "owner_name": null, "path": "storecloud", "group_id": 78 } +``` + +`owner_name`和`owner_email`始终为`null` . 请参阅[问题#20011](https://gitlab.com/gitlab-org/gitlab/-/issues/20011) . + +**组重命名:** + +``` +{ "event_name": "group_rename", "created_at": "2017-10-30T15:09:00Z", "updated_at": "2017-11-01T10:23:52Z", "name": "Better Name", "path": "better-name", "full_path": "parent-group/better-name", "group_id": 64, "owner_name": null, "owner_email": null, "old_path": "old-name", "old_full_path": "parent-group/old-name" } +``` + +`owner_name`和`owner_email`始终为`null` . 请参阅[https://gitlab.com/gitlab-org/gitlab/-/issues/20011](https://gitlab.com/gitlab-org/gitlab/-/issues/20011) . + +**新组成员:** + +``` +{ "created_at": "2012-07-21T07:30:56Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "user_add_to_group", "group_access": "Maintainer", "group_id": 78, "group_name": "StoreCloud", "group_path": "storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", "user_username": "johnsmith", "user_id": 41 } +``` + +**组成员已删除:** + +``` +{ "created_at": "2012-07-21T07:30:56Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "user_remove_from_group", "group_access": "Maintainer", "group_id": 78, "group_name": "StoreCloud", "group_path": "storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", "user_username": "johnsmith", "user_id": 41 } +``` + +**小组成员已更新:** + +``` +{ "created_at": "2012-07-21T07:30:56Z", "updated_at": "2012-07-21T07:38:22Z", "event_name": "user_update_for_group", "group_access": "Maintainer", "group_id": 78, "group_name": "StoreCloud", "group_path": "storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", "user_username": "johnsmith", "user_id": 41 } +``` + +## Push events[](#push-events "Permalink") + +当您推送到存储库时(在推送标签时除外)触发. 它为每个修改的分支生成一个事件. + +**请求标头**: + +``` +X-Gitlab-Event: System Hook +``` + +**要求正文:** + +``` +{ "event_name": "push", "before": "95790bf891e76fee5e1747ab589903a6a1f80f22", "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "ref": "refs/heads/master", "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "user_id": 4, "user_name": "John Smith", "user_email": "john@example.com", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 15, "project":{ "name":"Diaspora", "description":"", "web_url":"http://example.com/mike/diaspora", "avatar_url":null, "git_ssh_url":"git@example.com:mike/diaspora.git", "git_http_url":"http://example.com/mike/diaspora.git", "namespace":"Mike", "visibility_level":0, "path_with_namespace":"mike/diaspora", "default_branch":"master", "homepage":"http://example.com/mike/diaspora", "url":"git@example.com:mike/diaspora.git", "ssh_url":"git@example.com:mike/diaspora.git", "http_url":"http://example.com/mike/diaspora.git" }, "repository":{ "name": "Diaspora", "url": "git@example.com:mike/diaspora.git", "description": "", "homepage": "http://example.com/mike/diaspora", "git_http_url":"http://example.com/mike/diaspora.git", "git_ssh_url":"git@example.com:mike/diaspora.git", "visibility_level":0 }, "commits": [ { "id": "c5feabde2d8cd023215af4d2ceeb7a64839fc428", "message": "Add simple search to projects in public area", "timestamp": "2013-05-13T18:18:08+00:00", "url": "https://dev.gitlab.org/gitlab/gitlabhq/commit/c5feabde2d8cd023215af4d2ceeb7a64839fc428", "author": { "name": "Example User", "email": "user@example.com" } } ], "total_commits_count": 1 } +``` + +## Tag events[](#tag-events "Permalink") + +在创建(或删除)存储库标签时触发. 每个修改后的标签会生成一个事件. + +**请求标头**: + +``` +X-Gitlab-Event: System Hook +``` + +**要求正文:** + +``` +{ "event_name": "tag_push", "before": "0000000000000000000000000000000000000000", "after": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7", "ref": "refs/tags/v1.0.0", "checkout_sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", "user_id": 1, "user_name": "John Smith", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 1, "project":{ "name":"Example", "description":"", "web_url":"http://example.com/jsmith/example", "avatar_url":null, "git_ssh_url":"git@example.com:jsmith/example.git", "git_http_url":"http://example.com/jsmith/example.git", "namespace":"Jsmith", "visibility_level":0, "path_with_namespace":"jsmith/example", "default_branch":"master", "homepage":"http://example.com/jsmith/example", "url":"git@example.com:jsmith/example.git", "ssh_url":"git@example.com:jsmith/example.git", "http_url":"http://example.com/jsmith/example.git" }, "repository":{ "name": "Example", "url": "ssh://git@example.com/jsmith/example.git", "description": "", "homepage": "http://example.com/jsmith/example", "git_http_url":"http://example.com/jsmith/example.git", "git_ssh_url":"git@example.com:jsmith/example.git", "visibility_level":0 }, "commits": [], "total_commits_count": 0 } +``` + +### Merge request events[](#merge-request-events "Permalink") + +在创建新的合并请求,更新/合并/关闭现有合并请求或在源分支中添加提交时触发. + +**请求标头**: + +``` +X-Gitlab-Event: System Hook +``` + +``` +{ "object_kind": "merge_request", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" }, "project": { "name": "Example", "description": "", "web_url": "http://example.com/jsmith/example", "avatar_url": null, "git_ssh_url": "git@example.com:jsmith/example.git", "git_http_url": "http://example.com/jsmith/example.git", "namespace": "Jsmith", "visibility_level": 0, "path_with_namespace": "jsmith/example", "default_branch": "master", "ci_config_path": "", "homepage": "http://example.com/jsmith/example", "url": "git@example.com:jsmith/example.git", "ssh_url": "git@example.com:jsmith/example.git", "http_url": "http://example.com/jsmith/example.git" }, "object_attributes": { "id": 90, "target_branch": "master", "source_branch": "ms-viewport", "source_project_id": 14, "author_id": 51, "assignee_id": 6, "title": "MS-Viewport", "created_at": "2017-09-20T08:31:45.944Z", "updated_at": "2017-09-28T12:23:42.365Z", "milestone_id": null, "state": "opened", "merge_status": "unchecked", "target_project_id": 14, "iid": 1, "description": "", "updated_by_id": 1, "merge_error": null, "merge_params": { "force_remove_source_branch": "0" }, "merge_when_pipeline_succeeds": false, "merge_user_id": null, "merge_commit_sha": null, "deleted_at": null, "in_progress_merge_commit_sha": null, "lock_version": 5, "time_estimate": 0, "last_edited_at": "2017-09-27T12:43:37.558Z", "last_edited_by_id": 1, "head_pipeline_id": 61, "ref_fetched": true, "merge_jid": null, "source": { "name": "Awesome Project", "description": "", "web_url": "http://example.com/awesome_space/awesome_project", "avatar_url": null, "git_ssh_url": "git@example.com:awesome_space/awesome_project.git", "git_http_url": "http://example.com/awesome_space/awesome_project.git", "namespace": "root", "visibility_level": 0, "path_with_namespace": "awesome_space/awesome_project", "default_branch": "master", "ci_config_path": "", "homepage": "http://example.com/awesome_space/awesome_project", "url": "http://example.com/awesome_space/awesome_project.git", "ssh_url": "git@example.com:awesome_space/awesome_project.git", "http_url": "http://example.com/awesome_space/awesome_project.git" }, "target": { "name": "Awesome Project", "description": "Aut reprehenderit ut est.", "web_url": "http://example.com/awesome_space/awesome_project", "avatar_url": null, "git_ssh_url": "git@example.com:awesome_space/awesome_project.git", "git_http_url": "http://example.com/awesome_space/awesome_project.git", "namespace": "Awesome Space", "visibility_level": 0, "path_with_namespace": "awesome_space/awesome_project", "default_branch": "master", "ci_config_path": "", "homepage": "http://example.com/awesome_space/awesome_project", "url": "http://example.com/awesome_space/awesome_project.git", "ssh_url": "git@example.com:awesome_space/awesome_project.git", "http_url": "http://example.com/awesome_space/awesome_project.git" }, "last_commit": { "id": "ba3e0d8ff79c80d5b0bbb4f3e2e343e0aaa662b7", "message": "fixed readme", "timestamp": "2017-09-26T16:12:57Z", "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "author": { "name": "GitLab dev user", "email": "gitlabdev@dv6700.(none)" } }, "work_in_progress": false, "total_time_spent": 0, "human_total_time_spent": null, "human_time_estimate": null }, "labels": null, "repository": { "name": "git-gpg-test", "url": "git@example.com:awesome_space/awesome_project.git", "description": "", "homepage": "http://example.com/awesome_space/awesome_project" } } +``` + +## Repository Update events[](#repository-update-events "Permalink") + +当您推送到存储库(包括标签)时仅触发一次. + +**Request header**: + +``` +X-Gitlab-Event: System Hook +``` + +**要求正文:** + +``` +{ "event_name": "repository_update", "user_id": 1, "user_name": "John Smith", "user_email": "admin@example.com", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 1, "project": { "name":"Example", "description":"", "web_url":"http://example.com/jsmith/example", "avatar_url":null, "git_ssh_url":"git@example.com:jsmith/example.git", "git_http_url":"http://example.com/jsmith/example.git", "namespace":"Jsmith", "visibility_level":0, "path_with_namespace":"jsmith/example", "default_branch":"master", "homepage":"http://example.com/jsmith/example", "url":"git@example.com:jsmith/example.git", "ssh_url":"git@example.com:jsmith/example.git", "http_url":"http://example.com/jsmith/example.git", }, "changes": [ { "before":"8205ea8d81ce0c6b90fbe8280d118cc9fdad6130", "after":"4045ea7a3df38697b3730a20fb73c8bed8a3e69e", "ref":"refs/heads/master" } ], "refs":["refs/heads/master"] } +``` + +## Local requests in system hooks[](#local-requests-in-system-hooks "Permalink") + +管理员可以允许或阻止通过[系统挂钩对本地网络的请求](../security/webhooks.html) . \ No newline at end of file diff --git a/docs/460.md b/docs/460.md new file mode 100644 index 0000000000000000000000000000000000000000..5b1ec9c294e995e11a4d459f41ab246c96972c2b --- /dev/null +++ b/docs/460.md @@ -0,0 +1,43 @@ +# Changing your time zone + +> 原文:[https://docs.gitlab.com/ee/administration/timezone.html](https://docs.gitlab.com/ee/administration/timezone.html) + +* [Viewing available timezones](#viewing-available-timezones) +* [Changing time zone in Omnibus installations](#changing-time-zone-in-omnibus-installations) + +# Changing your time zone[](#changing-your-time-zone "Permalink") + +可以在`config/gitlab.yml`更改全局时区配置参数: + +``` +# time_zone: 'UTC' +``` + +如果要更改 GitLab 应用程序的默认时区,请取消注释并自定义. + +## Viewing available timezones[](#viewing-available-timezones "Permalink") + +要查看所有可用时区,请运行`bundle exec rake time:zones:all` . + +对于 Omnibus 安装,请运行`gitlab-rake time:zones:all` . + +**注意:**当前,此 Rake 任务未列出重新配置过程中 Omnibus GitLab 所需的 TZInfo 格式的时区: [#27209](https://gitlab.com/gitlab-org/gitlab/-/issues/27209) . + +## Changing time zone in Omnibus installations[](#changing-time-zone-in-omnibus-installations "Permalink") + +GitLab 将其时区默认为 UTC. 它在`/etc/gitlab/gitlab.rb`具有全局时区配置参数. + +要获取时区列表,请登录到 GitLab 应用程序服务器并运行一个命令,该命令为服务器生成 TZInfo 格式的时区列表. 例如,安装`timedatectl`并运行`timedatectl list-timezones` . + +要进行更新,请添加最适合您所在位置的时区. 例如: + +``` +gitlab_rails['time_zone'] = 'America/New_York' +``` + +添加配置参数后,重新配置并重新启动您的 GitLab 实例: + +``` +gitlab-ctl reconfigure +gitlab-ctl restart +``` \ No newline at end of file diff --git a/docs/461.md b/docs/461.md new file mode 100644 index 0000000000000000000000000000000000000000..d5766052fc4a6725b98ec924c4aff5091ad34b31 --- /dev/null +++ b/docs/461.md @@ -0,0 +1,185 @@ +# Uploads administration + +> 原文:[https://docs.gitlab.com/ee/administration/uploads.html](https://docs.gitlab.com/ee/administration/uploads.html) + +* [Using local storage](#using-local-storage) +* [Using object storage](#using-object-storage-core-only) +* [Object Storage Settings](#object-storage-settings) + * [Connection settings](#connection-settings) + * [OpenStack example](#openstack-example) + +# Uploads administration[](#uploads-administration "Permalink") + +上传代表可以作为单个文件发送到 GitLab 的所有用户数据. 例如,化身和笔记的附件就是上载. 上传是 GitLab 功能不可或缺的,因此不能被禁用. + +## Using local storage[](#using-local-storage "Permalink") + +**注意:**这是默认配置 + +要更改上传内容在本地存储的位置,请按照以下步骤操作. + +**在所有安装中;** + +**注意:**由于历史原因,上载存储在基本目录中,默认情况下该目录为`uploads/-/system` . 不建议在现有的 GitLab 安装上更改此配置选项. + +*上载默认情况下存储在`/var/opt/gitlab/gitlab-rails/uploads` .* + +1. 要将存储路径更改为例如`/mnt/storage/uploads` ,请编辑`/etc/gitlab/gitlab.rb`并添加以下行: + + ``` + gitlab_rails['uploads_storage_path'] = "/mnt/storage/" + gitlab_rails['uploads_base_dir'] = "uploads" + ``` + +2. 保存文件并[重新配置 GitLab,](restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**在源安装中:** + +*上载默认存储在`/home/git/gitlab/public/uploads/-/system` .* + +1. 要将存储路径更改为例如`/mnt/storage/uploads` ,请编辑`/home/git/gitlab/config/gitlab.yml`并添加或修改以下行: + + ``` + uploads: + storage_path: /mnt/storage + base_dir: uploads + ``` + +2. 保存文件并[重新启动 GitLab,](restart_gitlab.html#installations-from-source)以使更改生效. + +## Using object storage[](#using-object-storage-core-only "Permalink") + +版本历史 + +**笔记:** + +* 在[GitLab Premium](https://about.gitlab.com/pricing/) 10.5 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3867) . +* 在[GitLab Core](https://about.gitlab.com/pricing/) 10.7 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17358) . +* 从 11.1 版开始,我们支持 direct_upload 到 S3\. + +如果您不想使用安装了 GitLab 的本地磁盘来存储上载,则可以改用 AWS S3 之类的对象存储提供程序. 此配置依赖于已经配置的有效 AWS 凭证. + +[Read more about using object storage with GitLab](object_storage.html). + +**注意:**我们建议使用[统一对象存储设置](object_storage.html#consolidated-object-storage-configuration) . 以下说明适用于原始配置格式. + +## Object Storage Settings[](#object-storage-settings "Permalink") + +对于源安装,以下设置嵌套在`uploads:`下,然后是`object_store:` 在 Omnibus GitLab 安装上,它们的前缀是`uploads_object_store_` . + +| Setting | Description | Default | +| --- | --- | --- | +| `enabled` | 启用/禁用对象存储 | `false` | +| `remote_directory` | 存储上传文件的存储桶名称 |   | +| `direct_upload` | 设置为 true 可从上载路径中删除 Puma. Workhorse 处理实际的工件上传到对象存储,而 Puma 进行最少的处理以跟踪上传. 无需本地共享存储. 如果引入了对所有文件的单一存储类型的支持,则可以删除该选项. 了解更多有关[直接上传的信息](../development/uploads.html#direct-upload) . | `false` | +| `background_upload` | 设置为 false 可禁用自动上传. 一旦直接上传到 S3,就可以删除该选项(如果`direct_upload`设置为`true` ,它将覆盖`background_upload` ) | `true` | +| `proxy_download` | 设置为 true 以启用代理服务的所有文件. Option 可以减少出口流量,因为这允许客户端直接从远程存储下载而不是代理所有数据 | `false` | +| `connection` | 下述各种连接选项 |   | + +### Connection settings[](#connection-settings "Permalink") + +See [the available connection settings for different providers](object_storage.html#connection-settings). + +**在所有安装中;** + +*上载默认情况下存储在`/var/opt/gitlab/gitlab-rails/public/uploads/-/system` .* + +1. 编辑`/etc/gitlab/gitlab.rb`并通过替换为所需的值添加以下行: + + ``` + gitlab_rails['uploads_object_store_enabled'] = true + gitlab_rails['uploads_object_store_remote_directory'] = "uploads" + gitlab_rails['uploads_object_store_connection'] = { + 'provider' => 'AWS', + 'region' => 'eu-central-1', + 'aws_access_key_id' => 'AWS_ACCESS_KEY_ID', + 'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY' + } + ``` + + **注意:**如果您使用的是 AWS IAM 配置文件,请确保省略 AWS 访问密钥和秘密访问密钥/值对. + + ``` + gitlab_rails['uploads_object_store_connection'] = { + 'provider' => 'AWS', + 'region' => 'eu-central-1', + 'use_iam_profile' => true + } + ``` + +2. 保存文件并[重新配置 GitLab,](restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +3. 使用[`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.html)迁移所有现有的本地上传到对象存储. + +**在源安装中:** + +*上载默认存储在`/home/git/gitlab/public/uploads/-/system` .* + +1. 编辑`/home/git/gitlab/config/gitlab.yml`并添加或修改以下行: + + ``` + uploads: + object_store: + enabled: true + remote_directory: "uploads" # The bucket name + connection: + provider: AWS # Only AWS supported at the moment + aws_access_key_id: AWS_ACESS_KEY_ID + aws_secret_access_key: AWS_SECRET_ACCESS_KEY + region: eu-central-1 + ``` + +2. 保存文件并[重新启动 GitLab,](restart_gitlab.html#installations-from-source)以使更改生效. +3. 使用[`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.html)迁移所有现有的本地上传到对象存储. + +### OpenStack example[](#openstack-example "Permalink") + +**在所有安装中;** + +*上载默认情况下存储在`/var/opt/gitlab/gitlab-rails/public/uploads/-/system` .* + +1. Edit `/etc/gitlab/gitlab.rb` and add the following lines by replacing with the values you want: + + ``` + gitlab_rails['uploads_object_store_remote_directory'] = "OPENSTACK_OBJECT_CONTAINER_NAME" + gitlab_rails['uploads_object_store_connection'] = { + 'provider' => 'OpenStack', + 'openstack_username' => 'OPENSTACK_USERNAME', + 'openstack_api_key' => 'OPENSTACK_PASSWORD', + 'openstack_temp_url_key' => 'OPENSTACK_TEMP_URL_KEY', + 'openstack_auth_url' => 'https://auth.cloud.ovh.net/v2.0/', + 'openstack_region' => 'DE1', + 'openstack_tenant' => 'TENANT_ID', + } + ``` + +2. 保存文件并[重新配置 GitLab,](restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +3. 使用[`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.html)迁移所有现有的本地上传到对象存储. + +* * * + +**在源安装中:** + +*上载默认存储在`/home/git/gitlab/public/uploads/-/system` .* + +1. 编辑`/home/git/gitlab/config/gitlab.yml`并添加或修改以下行: + + ``` + uploads: + object_store: + enabled: true + direct_upload: false + background_upload: true + proxy_download: false + remote_directory: OPENSTACK_OBJECT_CONTAINER_NAME + connection: + provider: OpenStack + openstack_username: OPENSTACK_USERNAME + openstack_api_key: OPENSTACK_PASSWORD + openstack_temp_url_key: OPENSTACK_TEMP_URL_KEY + openstack_auth_url: 'https://auth.cloud.ovh.net/v2.0/' + openstack_region: DE1 + openstack_tenant: 'TENANT_ID' + ``` + +2. 保存文件并[重新配置 GitLab,](restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. +3. 使用[`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.html)迁移所有现有的本地上传到对象存储. \ No newline at end of file diff --git a/docs/462.md b/docs/462.md new file mode 100644 index 0000000000000000000000000000000000000000..8d5e5cc3a8dbcc89a3725c1cbb4467cde92529b4 --- /dev/null +++ b/docs/462.md @@ -0,0 +1,61 @@ +# Abuse reports + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/abuse_reports.html](https://docs.gitlab.com/ee/user/admin_area/abuse_reports.html) + +* [Reporting abuse](#reporting-abuse) +* [Resolving abuse reports](#resolving-abuse-reports) + * [Blocking users](#blocking-users) + +# Abuse reports[](#abuse-reports-core-only "Permalink") + +查看和解决来自 GitLab 用户的滥用情况报告. + +GitLab 管理员可以在管理区域中查看和[解决](#resolving-abuse-reports)滥用报告. + +## Reporting abuse[](#reporting-abuse "Permalink") + +要了解有关报告滥用情况的更多信息,请参阅[滥用报告用户文档](../abuse_reports.html) . + +## Resolving abuse reports[](#resolving-abuse-reports "Permalink") + +要访问滥用报告,请进入**管理区域>滥用报告** . + +解决滥用情况报告的方法有 3 种,每种方法都有一个按钮: + +* 删除用户和报告. 这将: + * 从实例中[删除报告的用户](../profile/account/delete_account.html) . + * 从列表中删除滥用报告. +* [Block user](#blocking-users). +* 删除报告. 这将: + * 从列表中删除滥用报告. + * 删除报告用户的访问限制. + +以下是" **滥用情况报告"**页面的示例: + +[![abuse-reports-page-image](img/31c7821d41281d527a8ee4f058bafaca.png)](img/abuse_reports_page.png) + +### Blocking users[](#blocking-users "Permalink") + +被阻止的用户无法登录或访问任何存储库,但是保留了他们的所有数据. + +阻止用户: + +* Leaves them in the abuse report list. +* 将**阻止用户**按钮更改为禁用的**已阻止**按钮. + +将通过[以下消息](https://gitlab.com/gitlab-org/gitlab/blob/master/app/workers/email_receiver_worker.rb#L38)通知用户: + +``` +Your account has been blocked. If you believe this is in error, contact a staff member. +``` + +屏蔽后,您仍然可以: + +* 删除用户并在必要时报告. +* 删除报告. + +以下是" **滥用报告"**页面上列出的被阻止用户的示例: + +[![abuse-report-blocked-user-image](img/517f5b10646cf257d0fd0413cb54c3e9.png)](img/abuse_report_blocked_user.png) + +**注意:**用户可以[阻止](../../api/users.html#block-user)和[畅通](../../api/users.html#unblock-user)使用 GitLab API. \ No newline at end of file diff --git a/docs/463.md b/docs/463.md new file mode 100644 index 0000000000000000000000000000000000000000..71b34bb6e44521de71eed786ab1201f6066b7d04 --- /dev/null +++ b/docs/463.md @@ -0,0 +1,61 @@ +# Activating and deactivating users + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/activating_deactivating_users.html](https://docs.gitlab.com/ee/user/admin_area/activating_deactivating_users.html) + +* [Deactivating a user](#deactivating-a-user) +* [Activating a user](#activating-a-user) + +# Activating and deactivating users[](#activating-and-deactivating-users "Permalink") + +GitLab 管理员可以停用和激活用户. + +## Deactivating a user[](#deactivating-a-user "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) . + +为了临时阻止没有最近活动的 GitLab 用户访问,管理员可以选择停用该用户. + +停用用户在功能上与[阻止用户](blocking_unblocking_users.html)相同,但有以下区别: + +* 它不禁止用户通过 UI 重新登录. +* 一旦停用的用户重新登录到 GitLab UI,其帐户将被设置为活动状态. + +停用的用户: + +* 无法访问 Git 存储库或 API. +* 不会从 GitLab 收到任何通知. +* 将无法使用[斜杠命令](../../integration/slash_commands.html) . + +个人项目以及已停用用户的组和用户历史记录将保持不变. + +可以从管理区域中停用用户. 去做这个: + +1. 导航到**管理区域>概述>用户** . +2. 选择一个用户. +3. 在**帐户**标签下,点击**停用用户** . + +请注意,要使停用选项对管理员可见,用户: + +* 必须当前处于活动状态. +* 最近 180 天内不得登录或进行任何活动. + +也可以使用[GitLab API](../../api/users.html#deactivate-user)停用用户. + +**注意:**停用的用户不会消耗[座位](../../subscriptions/index.html#choosing-the-number-of-users) . + +## Activating a user[](#activating-a-user "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) . + +可以从管理区域激活停用的用户. + +去做这个: + +1. 导航到**管理区域>概述>用户** . +2. 单击**停用**选项卡. +3. 选择一个用户. +4. 在**帐户**标签下,点击**激活用户** . + +也可以使用[GitLab API](../../api/users.html#activate-user)激活用户. + +**注意:**激活用户将把用户状态更改为活动状态,这将占用一个[席位](../../subscriptions/index.html#choosing-the-number-of-users) .**提示:**停用的用户还可以通过简单地通过 UI 重新登录来自己激活帐户. \ No newline at end of file diff --git a/docs/464.md b/docs/464.md new file mode 100644 index 0000000000000000000000000000000000000000..d72389e409253fe26057b16ad59c05c27763ac01 --- /dev/null +++ b/docs/464.md @@ -0,0 +1,157 @@ +# Audit Events + +> 原文:[https://docs.gitlab.com/ee/administration/audit_events.html](https://docs.gitlab.com/ee/administration/audit_events.html) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [List of events](#list-of-events) + * [Impersonation data](#impersonation-data-premium) + * [Group events](#group-events-starter) + * [Project events](#project-events-starter) + * [Instance events](#instance-events-premium-only) + * [Missing events](#missing-events) + * [Disabled events](#disabled-events) + * [Repository push](#repository-push) + +# Audit Events[](#audit-events-starter "Permalink") + +GitLab 为拥有者和管理员提供了一种在[付费计划中](https://about.gitlab.com/pricing/)查看 GitLab 服务器中所做的更改的方法. + +GitLab 系统管理员还可以利用文件系统上的日志. 有关更多详细信息,请参见[日志系统文档](logs.html) . + +## Overview[](#overview "Permalink") + +**审核事件**是 GitLab 所有者和管理员用于跟踪重要事件的工具,例如谁执行了某些操作及其发生的时间. 例如,这些操作可以是更改用户权限级别,添加新用户或删除用户. + +## Use cases[](#use-cases "Permalink") + +* 检查谁更改了 GitLab 项目的特定用户的权限级别. +* 跟踪哪些用户有权访问 GitLab 中的特定项目组,以及谁授予他们该权限级别. + +## List of events[](#list-of-events "Permalink") + +记录了两种事件: + +* 事件范围为组或项目,组和项目经理使用这些事件来查找谁进行了更改. +* 实例事件的范围涵盖整个 GitLab 实例,由合规团队用于执行正式审核. + +### Impersonation data[](#impersonation-data-premium "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/536) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0. + +模拟是管理员使用凭据以其他用户身份执行操作的地方. + +### Group events[](#group-events-starter "Permalink") + +**注意:**您需要拥有者[权限](../user/permissions.html)才能查看组"审核事件"页面. + +要查看组的审核事件,请导航至**组>设置>审核事件** . 从那里,您可以看到以下操作: + +* 组名或路径已更改 +* 组存储库大小限制已更改 +* 创建或删除组 +* 组更改可见性 +* 用户已添加到组中并具有哪些[权限](../user/permissions.html) +* 用户通过[组 SAML](../user/group/saml_sso/index.html)登录 +* 分配给组的用户的权限更改 +* 从群组中删除了用户 +* 项目存储库已导入组 +* [与组共享](../user/project/members/share_project_with_groups.html)并具有[权限的项目](../user/permissions.html) +* 删除项目中先前共享的组 +* 启用或禁用 LFS +* 共享跑步者的分钟数限制已更改 +* 启用或禁用会员锁定 +* 请求访问已启用或已禁用 +* 2FA 执行或宽限期已更改 +* 允许创建项目的角色已更改 + +组事件也可以通过[组审核事件 API](../api/audit_events.html#group-audit-events-starter)访问 + +### Project events[](#project-events-starter "Permalink") + +**注意:**您需要维护者[权限](../user/permissions.html)或更高[权限](../user/permissions.html)才能查看项目"审核事件"页面. + +要查看项目的审核事件,请导航至**项目>设置>审核事件** . 从那里,您可以看到以下操作: + +* 添加或删除了部署密钥 +* 创建,删除,重命名,移动(转移),更改路径的项目 +* 项目更改的可见性级别 +* 用户已添加到项目中并具有哪些[权限](../user/permissions.html) +* 分配给项目的用户的权限更改 +* 用户已从项目中删除 +* 已下载项目导出 +* 项目资源库已下载 +* 项目已存档 +* 项目未归档 +* 添加,删除或更新的受保护分支 +* 版本已添加到项目 +* 版本已更新 +* 发布里程碑关联已更改 +* 更新了批准提交者合并请求的权限(在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) ) +* 更新了批准作者合并请求的权限(在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) ) +* 更新了所需的批准数量(在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) ) +* 在项目批准组中添加或删除用户和组(在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/213603) ) + +也可以通过[Project Audit Events API](../api/audit_events.html#project-audit-events-starter)访问[项目事件](../api/audit_events.html#project-audit-events-starter) + +### Instance events[](#instance-events-premium-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2336) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.3. + +服务器范围的审核日志记录引入了在 GitLab 服务器的整个实例中观察用户操作的功能,从而易于了解谁为审核目的以及何时更改了内容. + +要查看服务器范围的管理日志,请访问**管理区域>监视>审核日志** . + +除了组和项目事件,还记录以下用户操作: + +* 登录失败 +* 登录事件和身份验证类型(例如标准,LDAP 或 OmniAuth) +* 添加了 SSH 密钥 +* 添加或删除电子邮件 +* 修改密码 +* 要求重设密码 +* 授予 OAuth 访问权限 +* 开始或停止模拟用户 +* 更改的用户名(在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/7797) ) +* 用户已删除(在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/251) ) +* 添加了用户(在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/251) ) +* 通过管理区(在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/251) )阻止了用户 +* 通过 API(在 GitLab 12.9 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25872) )阻止了用户 + +通过从过滤器下拉框中选择审核数据类型,可以过滤特定的操作. 您可以进一步按特定的组,项目或用户筛选(用于身份验证事件). + +[![audit log](img/7151cdf5255313b82b775852ed2aef73.png)](img/audit_log.png) + +实例事件也可以通过[Instance Audit Events API](../api/audit_events.html#instance-audit-events-premium-only)访问 + +### Missing events[](#missing-events "Permalink") + +在审核事件中未跟踪某些事件. 有关未跟踪哪些事件的更多详细信息,以及将这些事件添加到 GitLab 中的进展,请参见以下史诗: + +* [Project settings and activity](https://gitlab.com/groups/gitlab-org/-/epics/474) +* [Group settings and activity](https://gitlab.com/groups/gitlab-org/-/epics/475) +* [Instance-level settings and activity](https://gitlab.com/groups/gitlab-org/-/epics/476) + +### Disabled events[](#disabled-events "Permalink") + +#### Repository push[](#repository-push "Permalink") + +当前的审计事件体系结构不准备接收大量记录. 这可能会使您的项目或审核日志的用户界面非常繁忙,并且`audit_events` PostgreSQL 表占用的磁盘空间将大大增加. 默认情况下禁用它,以防止 GitLab 实例具有很高的 Git 写入流量时性能降低. + +在即将发布的版本中,默认情况下将启用 Git 推送事件的审核日志. 请按照[#7865](https://gitlab.com/gitlab-org/gitlab/-/issues/7865)进行更新. + +如果您仍然希望在实例中启用**存储库推送**事件,请执行以下步骤. + +**在所有安装中;** + +1. 进入 Rails 控制台: + + ``` + sudo gitlab-rails console + ``` + +2. Flip the switch and enable the feature flag: + + ``` + Feature.enable(:repository_push_audit_event) + ``` \ No newline at end of file diff --git a/docs/465.md b/docs/465.md new file mode 100644 index 0000000000000000000000000000000000000000..bcf3f874f403b8cbcf8413ef1a0434d454fa17d5 --- /dev/null +++ b/docs/465.md @@ -0,0 +1,46 @@ +# Blocking and unblocking users + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/blocking_unblocking_users.html](https://docs.gitlab.com/ee/user/admin_area/blocking_unblocking_users.html) + +* [Blocking a user](#blocking-a-user) +* [Unblocking a user](#unblocking-a-user) + +# Blocking and unblocking users[](#blocking-and-unblocking-users "Permalink") + +GitLab 管理员阻止和取消阻止用户. + +## Blocking a user[](#blocking-a-user "Permalink") + +为了完全阻止用户访问 GitLab 实例,管理员可以选择阻止该用户. + +可以[通过滥用报告](abuse_reports.html#blocking-users)或直接从管理区域来阻止用户. 去做这个: + +1. 导航到**管理区域>概述>用户** . +2. 选择一个用户. +3. 在**帐户**标签下,点击**阻止用户** . + +被阻止的用户: + +* 将无法登录. +* 无法访问 Git 存储库或 API. +* 不会从 GitLab 收到任何通知. +* 将无法使用[斜杠命令](../../integration/slash_commands.html) . + +个人项目以及被阻止用户的组和用户历史记录将保持不变. + +也可以使用[GitLab API](../../api/users.html#block-user)阻止用户. + +**注意:**被封锁的用户不会占用[座位](../../subscriptions/index.html#choosing-the-number-of-users) . + +## Unblocking a user[](#unblocking-a-user "Permalink") + +可以从管理区域中取消阻止被阻止的用户. 去做这个: + +1. 导航到**管理区域>概述>用户** . +2. 单击" **阻止"**选项卡. +3. 选择一个用户. +4. 在**帐户**标签下,点击**取消阻止用户** . + +也可以使用[GitLab API](../../api/users.html#unblock-user)解除对用户的阻止. + +**注意:**取消禁止用户进入会将用户状态更改为"活动",这将占用一个[席位](../../subscriptions/index.html#choosing-the-number-of-users) . \ No newline at end of file diff --git a/docs/466.md b/docs/466.md new file mode 100644 index 0000000000000000000000000000000000000000..38833e699b5ae5ffc31157ef1a719e7c4e6d3dd8 --- /dev/null +++ b/docs/466.md @@ -0,0 +1,98 @@ +# Broadcast Messages + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/broadcast_messages.html](https://docs.gitlab.com/ee/user/admin_area/broadcast_messages.html) + +* [Banners](#banners) +* [Notifications](#notifications) +* [Adding a broadcast message](#adding-a-broadcast-message) +* [Editing a broadcast message](#editing-a-broadcast-message) +* [Deleting a broadcast message](#deleting-a-broadcast-message) + +# Broadcast Messages[](#broadcast-messages-core-only "Permalink") + +GitLab 可以向 GitLab 实例的所有用户显示广播消息. 广播消息有两种类型: + +* banners +* notifications + +您可以使用`a`和`br` HTML 标记来设置消息内容的样式. `br`标签插入换行符. `a` HTML 标记接受具有以下 CSS 属性的`class`和`style`属性: + +* `color` +* `border` +* `background` +* `padding` +* `margin` +* `text-decoration` + +## Banners[](#banners "Permalink") + +标语显示在页面顶部和 Git 远程响应中. + +[![Broadcast Message Banner](img/5665233091dd783791b6dd32107e61ec.png)](img/broadcast_messages_banner_v12_10.png) + +``` +$ git push +... +remote: +remote: **Welcome** to GitLab :wave: +remote: +... +``` + +## Notifications[](#notifications "Permalink") + +通知显示在页面的右下角,并且可以包含占位符. 占位符替换为活动用户的属性. 占位符必须用花括号括起来,例如`{{name}}` . 可用的占位符是: + +* `{{email}}` +* `{{name}}` +* `{{user_id}}` +* `{{username}}` +* `{{instance_id}}` + +如果用户未登录,则与用户相关的值将为空. + +[![Broadcast Message Notification](img/eaa74cb66b0dd1b45f9b312af76c23fb.png)](img/broadcast_messages_notification_v12_10.png) + +广播消息可以使用[广播消息 API](../../api/broadcast_messages.html)进行管理. + +**注意:**如果一次激活了多个横幅消息,则会按创建顺序将它们显示在堆栈中. 如果一次激活了多个通知消息,则仅显示最新消息. + +## Adding a broadcast message[](#adding-a-broadcast-message "Permalink") + +要向您的 GitLab 实例上的用户显示消息,请添加广播消息. + +要添加广播消息: + +1. 导航到" **管理区域">"消息"**页面. +2. 将消息的文本添加到" **消息"**字段. 支持 Markdown 和表情符号. +3. 如果需要,请单击" **自定义颜色"**链接以编辑消息的背景颜色和字体颜色. +4. 如果需要,添加**目标路径**以仅在与该路径匹配的 URL 上显示广播消息. 您可以使用通配符`*`来匹配多个 URL,例如`/users/*/issues` . +5. 选择消息的开始日期和结束日期. +6. 单击**添加广播消息**按钮. + +**注意:**广播消息过期后,将不再显示在 UI 中,而是仍列在广播消息列表中. 如果设置了"可**禁用** "选项,则用户还可以关闭广播消息. + +## Editing a broadcast message[](#editing-a-broadcast-message "Permalink") + +如果需要更改广播消息,则可以对其进行编辑. + +要编辑广播消息: + +1. 导航到" **管理区域">"消息"**页面. +2. 从广播消息列表中,单击相应的按钮以编辑消息. +3. 进行所需的更改后,单击" **更新广播消息"**按钮. + +**提示:**过期的邮件可以通过更改其结束日期来再次激活. + +## Deleting a broadcast message[](#deleting-a-broadcast-message "Permalink") + +可以删除不再需要的广播消息. + +要删除广播消息: + +1. 导航到" **管理区域">"消息"**页面. +2. 从广播消息列表中,单击相应的按钮以删除该消息. + +删除后,广播消息将从广播消息列表中删除. + +**注意:**广播消息可以在激活时删除. \ No newline at end of file diff --git a/docs/467.md b/docs/467.md new file mode 100644 index 0000000000000000000000000000000000000000..7efba32686652f753f135729d6b7c94be50aa6c1 --- /dev/null +++ b/docs/467.md @@ -0,0 +1,633 @@ +# Elasticsearch integration + +> 原文:[https://docs.gitlab.com/ee/integration/elasticsearch.html](https://docs.gitlab.com/ee/integration/elasticsearch.html) + +* [Version Requirements](#version-requirements) +* [Installing Elasticsearch](#installing-elasticsearch) +* [Elasticsearch repository indexer](#elasticsearch-repository-indexer) + * [Omnibus GitLab](#omnibus-gitlab) + * [From source](#from-source) + * [Debian / Ubuntu](#debian--ubuntu) + * [CentOS / RHEL](#centos--rhel) + * [Mac OSX](#mac-osx) + * [Building and installing](#building-and-installing) +* [System Requirements](#system-requirements) +* [Enabling Elasticsearch](#enabling-elasticsearch) + * [Limiting namespaces and projects](#limiting-namespaces-and-projects) +* [Disabling Elasticsearch](#disabling-elasticsearch) +* [Adding GitLab’s data to the Elasticsearch index](#adding-gitlabs-data-to-the-elasticsearch-index) + * [Indexing through the administration UI](#indexing-through-the-administration-ui) + * [Indexing through Rake tasks](#indexing-through-rake-tasks) + * [Indexing small instances](#indexing-small-instances) + * [Indexing large instances](#indexing-large-instances) + * [Indexing limitations](#indexing-limitations) +* [GitLab Elasticsearch Rake tasks](#gitlab-elasticsearch-rake-tasks) + * [Environment variables](#environment-variables) + * [Indexing a specific project](#indexing-a-specific-project) +* [Elasticsearch index scopes](#elasticsearch-index-scopes) +* [Tuning](#tuning) + * [Guidance on choosing optimal cluster configuration](#guidance-on-choosing-optimal-cluster-configuration) + * [Elasticsearch integration settings guidance](#elasticsearch-integration-settings-guidance) + * [Deleted documents](#deleted-documents) +* [Troubleshooting](#troubleshooting) + * [Common issues](#common-issues) + * [Low-level troubleshooting](#low-level-troubleshooting) + * [Known Issues](#known-issues) + * [Reverting to basic search](#reverting-to-basic-search) + +# Elasticsearch integration[](#elasticsearch-integration-starter-only "Permalink") + +版本历史 + +* 在 GitLab [Starter](https://about.gitlab.com/pricing/) 8.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109 "Elasticsearch 合并请求") . +* 在 GitLab [Starter](https://about.gitlab.com/pricing/) 9.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1305)了对[Amazon Elasticsearch 的](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg.html)支持. + +本文档介绍了如何使用 GitLab 设置 Elasticsearch. 启用后,您将受益于快速的搜索响应时间以及两个特殊搜索的优点: + +* [Advanced Global Search](../user/search/advanced_global_search.html) +* [Advanced Syntax Search](../user/search/advanced_search_syntax.html) + +## Version Requirements[](#version-requirements "Permalink") + +| GitLab 版本 | Elasticsearch 版本 | +| --- | --- | +| GitLab 企业版 8.4-8.17 | Elasticsearch 2.4 with [Delete By Query Plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/2.4/plugins-delete-by-query.html) installed | +| GitLab 企业版 9.0-11.4 | 弹性搜索 5.1-5.5 | +| GitLab 企业版 11.5-12.6 | Elasticsearch 5.6-6.x | +| manbetx 客户端打不开企业版 12.7+ | Elasticsearch 6.x-7.x | + +## Installing Elasticsearch[](#installing-elasticsearch "Permalink") + +Omnibus 软件包中*不*包括 Elasticsearch. 无论您使用的是 Omnibus 软件包还是从源代码安装的 GitLab,您都必须[自行安装](https://www.elastic.co/guide/en/elasticsearch/reference/6.8/install-elasticsearch.html "Elasticsearch 6.8 安装文档") . 提供有关安装 Elasticsearch 的详细信息超出了本文档的范围. + +**注意:** Elasticsearch 应该安装在单独的服务器上,无论您自己安装还是使用云托管产品,例如 Elastic 的[Elasticsearch Service](https://www.elastic.co/elasticsearch/service) (在 AWS,GCP 或 Azure 上可用)或[Amazon Elasticsearch](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg.html) Service. 不建议在与 GitLab 相同的服务器上运行 Elasticsearch,这可能会导致 GitLab 实例性能下降.**注意:** **对于单节点 Elasticsearch 集群,功能集群的运行状况为黄色** (永远不会为绿色),因为已分配了主要分片,但副本却无法存在,因为没有其他节点可以为 Elasticsearch 分配副本. + +将数据添加到数据库或存储库中并[在管理区域中启用 Elasticsearch 后](#enabling-elasticsearch) ,搜索索引将自动更新. + +## Elasticsearch repository indexer[](#elasticsearch-repository-indexer "Permalink") + +为了索引 Git 存储库数据,GitLab 使用了[Go 语言编写](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer)的[索引器](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer) . + +Go 索引器的安装方式取决于您的 GitLab 版本: + +* 对于 Omnibus GitLab 11.8 及更高版本,请参见[Omnibus GitLab](#omnibus-gitlab) . +* For installations from source or older versions of Omnibus GitLab, install the indexer [From Source](#from-source). + +### Omnibus GitLab[](#omnibus-gitlab "Permalink") + +从 GitLab 11.8 开始,Omnibus GitLab 中包含了 Go 索引器. 以前的基于 Ruby 的索引器已在[GitLab 12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/6481)中删除. + +### From source[](#from-source "Permalink") + +首先,我们需要安装一些依赖项,然后构建并安装索引器本身. + +该项目依靠[ICU](http://site.icu-project.org/)进行文本编码,因此我们需要确保在运行`make`之前安装了适用于您平台的开发包. + +#### Debian / Ubuntu[](#debian--ubuntu "Permalink") + +要在 Debian 或 Ubuntu 上安装,请运行: + +``` +sudo apt install libicu-dev +``` + +#### CentOS / RHEL[](#centos--rhel "Permalink") + +要在 CentOS 或 RHEL 上安装,请运行: + +``` +sudo yum install libicu-devel +``` + +##### Mac OSX[](#mac-osx "Permalink") + +要在 macOS 上安装,请运行: + +``` +brew install icu4c +export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:$PKG_CONFIG_PATH" +``` + +### Building and installing[](#building-and-installing "Permalink") + +要构建和安装索引器,请运行: + +``` +indexer_path=/home/git/gitlab-elasticsearch-indexer + +# Run the installation task for gitlab-elasticsearch-indexer: +sudo -u git -H bundle exec rake gitlab:indexer:install[$indexer_path] RAILS_ENV=production +cd $indexer_path && sudo make install +``` + +The `gitlab-elasticsearch-indexer` will be installed to `/usr/local/bin`. + +您可以使用`PREFIX` env 变量更改安装路径. 如果这样做,请记住将`-E`标志传递给`sudo` . + +Example: + +``` +PREFIX=/usr sudo -E make install +``` + +安装完成后,请在您实例的 Elasticsearch 设置下启用, [如下所述](#enabling-elasticsearch) . + +## System Requirements[](#system-requirements "Permalink") + +Elasticsearch 需要的资源超出了[GitLab 系统要求中](../install/requirements.html)记录的资源. 这些会因安装大小而异,但是,根据[官方指南](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html) ,您应确保每个 Elasticsearch 节点**至少至少**有**8 GiB RAM** . + +请记住,这是 Elasticsearch 的**最低要求** . 对于生产实例,他们建议使用更多的资源. + +所需的存储空间在很大程度上取决于要存储在 GitLab 中的存储库的大小,但是根据经验,由于所有存储库加起来,您应该至少有 50%的可用空间. + +## Enabling Elasticsearch[](#enabling-elasticsearch "Permalink") + +为了启用 Elasticsearch,您需要具有管理员权限. 导航到**管理区域** (扳手图标),然后导航到**设置>集成**并展开**Elasticsearch**部分. + +单击**保存更改**以使更改生效. + +可以使用以下 Elasticsearch 设置: + +| Parameter | Description | +| --- | --- | +| `Elasticsearch indexing` | 启用/禁用 Elasticsearch 索引编制. 例如,您可能想要启用索引编制但禁用搜索以使索引有时间完全完成. 另外,请记住,此选项对现有数据没有任何影响,仅启用/禁用跟踪数据更改的后台索引器. 因此,通过启用此功能,您将不会为现有数据建立索引,请按照[将 GitLab 的数据添加到 Elasticsearch 索引中所述的](#adding-gitlabs-data-to-the-elasticsearch-index)那样,使用特殊的 Rake 任务. | +| `Elasticsearch pause indexing` | 启用/禁用临时索引暂停. 这对于群集迁移/重新索引很有用. 仍会跟踪所有更改,但是直到未暂停它们才提交给 Elasticsearch 索引. | +| `Search with Elasticsearch enabled` | 在搜索中使用 Elasticsearch 启用/禁用. | +| `URL` | 用于连接到 Elasticsearch 的 URL. 使用逗号分隔的列表来支持群集(例如, `http://host1, https://host2:9200` ). 如果您的 Elasticsearch 实例受密码保护,请在 URL 中传递`username:password` (例如, `http://:@:9200/` ). | +| `Number of Elasticsearch shards` | 出于性能原因,Elasticsearch 索引分为多个碎片. 通常,较大的索引需要具有更多的分片. 在重新创建索引之前,对该值所做的更改才会生效. 您可以在[Elasticsearch 文档中](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html#create-index-settings)阅读有关权衡的更多信息 | +| `Number of Elasticsearch replicas` | 每个 Elasticsearch 分片可以具有多个副本. 这些是分片的完整副本,可以提高查询性能或抵御硬件故障. 增大该值将大大增加索引所需的总磁盘空间. | +| `Limit namespaces and projects that can be indexed` | 启用此选项将允许您选择要索引的名称空间和项目. 所有其他名称空间和项目将改为使用数据库搜索. 请注意,如果启用此选项但未选择任何名称空间或项目,则不会为它们建立索引. [在下面阅读更多内容](#limiting-namespaces-and-projects) . | +| `Using AWS hosted Elasticsearch with IAM credentials` | 使用[AWS IAM 授权](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html)或[AWS EC2 实例配置文件凭证](https://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html#getting-started-create-iam-instance-profile-cli)对 Elasticsearch 请求进行签名. 必须将策略配置为允许`es:*`操作. | +| `AWS Region` | 您的 Elasticsearch 服务所在的 AWS 区域. | +| `AWS Access Key` | AWS 访问密钥. | +| `AWS Secret Access Key` | AWS 秘密访问密钥. | +| `Maximum field length` | See [the explanation in instance limits.](../administration/instance_limits.html#maximum-field-length). | +| `Maximum bulk request size (MiB)` | 最大批量请求大小由 GitLab 基于 Golang 的索引器流程使用,并指示在将有效负载提交给 Elasticsearch 的批量 API 之前,它应在给定的索引过程中收集(并存储在内存中)多少数据. 此设置应与批量请求并发设置一起使用(请参见下文),并且需要通过`gitlab-rake`命令或通过`gitlab-rake`命令来适应 Elasticsearch 主机和运行 GitLab 基于 Golang 的索引器的主机的资源限制. Sidekiq 任务. | +| `Bulk request concurrency` | 批量请求并发指示可以并行运行多少个 GitLab 基于 Golang 的索引器进程(或线程)来收集数据,然后将其提交给 Elasticsearch 的批量 API. 这可以提高索引编制性能,但可以更快地填充 Elasticsearch 批量请求队列. 此设置应与最大批量请求大小设置(请参见上文)一起使用,并且需要容纳`gitlab-rake`的 Elasticsearch 主机和运行 GitLab 基于 Golang 的索引器的主机的资源限制命令或 Sidekiq 任务. | + +### Limiting namespaces and projects[](#limiting-namespaces-and-projects "Permalink") + +如果选择" `Limit namespaces and projects that can be indexed`更多选项可用 [![限制名称空间和项目选项](img/39b4809628ba97edb93621d6eefa5135.png)](img/limit_namespaces_projects_options.png) + +您可以选择名称空间和项目以排他索引. 请注意,如果名称空间是一个组,它将包括所有子组以及属于这些子组的要被索引的项目. + +如果所有名称空间都已建立索引,Elasticsearch 仅提供跨组代码/提交搜索(全局). 在仅对名称空间的子集进行索引的特定情况下,全局搜索将不提供代码或提交范围. 这仅在索引命名空间的范围内才有可能. 当前,无法对多个已索引的名称空间进行编码/提交搜索(当仅对名称空间的子集进行索引时). 例如,如果两个组都已建立索引,则无法在两个组上运行单个代码搜索. 您只能在第一组上然后在第二组上运行代码搜索. + +您可以通过编写感兴趣的部分名称空间或项目名称来过滤选择下拉列表. + +[![limit namespace filter](img/471bcfe6a44b22703662997289b517c9.png)](img/limit_namespace_filter.png) + +**注意:**如果未选择名称空间或项目,则不会进行 Elasticsearch 索引.**警告:**如果您已经为实例建立索引,则必须重新生成索引,才能删除所有现有数据以进行过滤以使其正常工作. 为此,请运行 Rake 任务`gitlab:elastic:recreate_index`和`gitlab:elastic:clear_index_status` . 然后,从列表中删除名称空间或项目将按预期从 Elasticsearch 索引中删除数据. + +## Disabling Elasticsearch[](#disabling-elasticsearch "Permalink") + +要禁用 Elasticsearch 集成: + +1. 导航到**管理区域** (扳手图标),然后导航到**设置>集成** . +2. 展开**Elasticsearch**部分,然后取消选中**Elasticsearch 索引**和**启用** **Elasticsearch 的** **搜索** . +3. 单击**保存更改**以使更改生效. +4. (可选)删除现有索引: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:delete_index + + # Installations from source + bundle exec rake gitlab:elastic:delete_index RAILS_ENV=production + ``` + +## Adding GitLab’s data to the Elasticsearch index[](#adding-gitlabs-data-to-the-elasticsearch-index "Permalink") + +启用 Elasticsearch 索引编制后,您的 GitLab 实例中的新更改将在发生更改时自动进行索引. 要回填现有数据,可以使用以下方法之一在后台作业中对其进行索引. + +### Indexing through the administration UI[](#indexing-through-the-administration-ui "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15390) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3. + +通过管理区域建立索引: + +1. [Configure your Elasticsearch host and port](#enabling-elasticsearch). +2. 创建空索引: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:create_empty_index + + # Installations from source + bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production + ``` + +3. [Enable **Elasticsearch indexing**](#enabling-elasticsearch). +4. Click **索引所有项目** in **管理区域>设置>集成> Elasticsearch**. +5. 单击确认消息中的**检查进度** ,以查看后台作业的状态. +6. 个人摘要需要手动编制索引: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index_snippets + + # Installations from source + bundle exec rake gitlab:elastic:index_snippets RAILS_ENV=production + ``` + +7. 索引完成后,启用[**Search with Elasticsearch**](#enabling-elasticsearch) . + +### Indexing through Rake tasks[](#indexing-through-rake-tasks "Permalink") + +可以使用 Rake 任务执行索引. + +#### Indexing small instances[](#indexing-small-instances "Permalink") + +**警告:**这将删除您现有的索引. + +如果数据库大小小于 500 MiB,并且所有托管存储库的大小小于 5 GiB: + +1. [Configure your Elasticsearch host and port](#enabling-elasticsearch). +2. 索引您的数据: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index + + # Installations from source + bundle exec rake gitlab:elastic:index RAILS_ENV=production + ``` + +3. 索引完成后,启用[**Search with Elasticsearch**](#enabling-elasticsearch) . + +#### Indexing large instances[](#indexing-large-instances "Permalink") + +**警告:**执行异步索引编制将生成很多 Sidekiq 作业. 确保具有[可扩展和高度可用的设置](README.html)或创建[额外的 Sidekiq 进程](../administration/operations/extra_sidekiq_processes.html)以为该任务做准备 + +1. [Configure your Elasticsearch host and port](#enabling-elasticsearch). +2. 创建空索引: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:create_empty_index + + # Installations from source + bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production + ``` + +3. 如果这是您的 GitLab 实例的重新索引,请清除索引状态: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:clear_index_status + + # Installations from source + bundle exec rake gitlab:elastic:clear_index_status RAILS_ENV=production + ``` + +4. [Enable **Elasticsearch indexing**](#enabling-elasticsearch). +5. 索引大型 Git 存储库可能需要一段时间. 为了加快此过程,您可以暂时禁用自动刷新和复制. 根据我们的经验,您可以预期索引编制时间将减少 20%. 索引完成后,我们将启用它们. 此步骤是可选的! + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{ + "index" : { + "refresh_interval" : "-1", + "number_of_replicas" : 0 + } }' + ``` + +6. 索引项目及其相关数据: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index_projects + + # Installations from source + bundle exec rake gitlab:elastic:index_projects RAILS_ENV=production + ``` + + 这为需要索引的每个项目加入了一个 Sidekiq 作业. 您可以在**管理区域>监视>后台作业>队列选项卡中**查看作业,然后单击`elastic_indexer` ,也可以使用 Rake 任务查询索引状态: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index_projects_status + + # Installations from source + bundle exec rake gitlab:elastic:index_projects_status RAILS_ENV=production + + Indexing is 65.55% complete (6555/10000 projects) + ``` + + 如果要将索引限制为一定范围的项目,可以提供`ID_FROM`和`ID_TO`参数: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index_projects ID_FROM=1001 ID_TO=2000 + + # Installations from source + bundle exec rake gitlab:elastic:index_projects ID_FROM=1001 ID_TO=2000 RAILS_ENV=production + ``` + + 其中`ID_FROM`和`ID_TO`是项目 ID. 这两个参数都是可选的. 上面的示例将索引从 ID `1001`到(并包括)ID `2000`所有项目. + + **故障排除:**有时`gitlab:elastic:index_projects`排队的项目索引作业可能会中断. 出于多种原因可能会发生这种情况,但是再次运行索引任务始终是安全的. 它将跳过已经建立索引的存储库. + + 当索引器在数据库中存储每个已索引存储库的最后一次提交 SHA 时,您可以使用特殊参数`UPDATE_INDEX`运行索引器,它将再次检查每个项目存储库以确保对存储库中的每个提交都进行了索引,这很有用.如果您的索引已过时: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index_projects UPDATE_INDEX=true ID_TO=1000 + + # Installations from source + bundle exec rake gitlab:elastic:index_projects UPDATE_INDEX=true ID_TO=1000 RAILS_ENV=production + ``` + + 您还可以使用`gitlab:elastic:clear_index_status` Rake 任务来强制索引器"忘记"所有进度,因此它将从头开始重试索引过程. + +7. 个人代码段与项目无关,需要单独编制索引: + + ``` + # Omnibus installations + sudo gitlab-rake gitlab:elastic:index_snippets + + # Installations from source + bundle exec rake gitlab:elastic:index_snippets RAILS_ENV=production + ``` + +8. 在建立索引后再次启用复制和刷新(仅在您之前禁用它的情况下): + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{ + "index" : { + "number_of_replicas" : 1, + "refresh_interval" : "1s" + } }' + ``` + + 启用上述刷新后,应调用强制合并. + + 对于 Elasticsearch 6.x,在进行强制合并之前,索引应处于只读模式: + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{ + "settings": { + "index.blocks.write": true + } }' + ``` + + 然后,启动强制合并: + + ``` + curl --request POST 'localhost:9200/gitlab-production/_forcemerge?max_num_segments=5' + ``` + + 此后,如果索引处于只读模式,请切换回读写模式: + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{ + "settings": { + "index.blocks.write": false + } }' + ``` + +9. 索引完成后,启用[**Search with Elasticsearch**](#enabling-elasticsearch) . + +### Indexing limitations[](#indexing-limitations "Permalink") + +对于存储库和摘要文件,GitLab 最多只能索引 1 MiB 的内容,以避免索引超时. + +## GitLab Elasticsearch Rake tasks[](#gitlab-elasticsearch-rake-tasks "Permalink") + +耙任务可用于: + +* [生成并安装](#building-and-installing)索引器. +* [禁用 Elasticsearch](#disabling-elasticsearch)时删除索引. +* [将 GitLab 数据添加](#adding-gitlabs-data-to-the-elasticsearch-index)到索引. + +以下是一些可用的 Rake 任务: + +| Task | Description | +| --- | --- | +| [`sudo gitlab-rake gitlab:elastic:index`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 启用 Elasticsearch 索引并运行`gitlab:elastic:create_empty_index` , `gitlab:elastic:clear_index_status` , `gitlab:elastic:index_projects`和`gitlab:elastic:index_snippets` . | +| [`sudo gitlab-rake gitlab:elastic:index_projects`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 遍历所有项目并在 Sidekiq 作业中排队以在后台对它们进行索引. | +| [`sudo gitlab-rake gitlab:elastic:index_projects_status`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 确定索引的总体状态. 通过计算索引项目的总数,除以项目总数,然后乘以 100 即可完成. | +| [`sudo gitlab-rake gitlab:elastic:clear_index_status`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 删除所有项目的 IndexStatus 的所有实例. | +| [`sudo gitlab-rake gitlab:elastic:create_empty_index[]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 生成一个空索引,并为该索引分配一个别名(仅当该索引不存在时). | +| [`sudo gitlab-rake gitlab:elastic:delete_index[]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 删除 Elasticsearch 实例上的 GitLab 索引和别名(如果存在). | +| [`sudo gitlab-rake gitlab:elastic:recreate_index[]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | `gitlab:elastic:delete_index[]`和`gitlab:elastic:create_empty_index[]`包装器任务. | +| [`sudo gitlab-rake gitlab:elastic:index_snippets`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 执行 Elasticsearch 导入,对片段数据进行索引. | +| [`sudo gitlab-rake gitlab:elastic:projects_not_indexed`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 显示未索引的项目. | +| [`sudo gitlab-rake gitlab:elastic:reindex_cluster`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | 安排零停机群集重新索引编制任务. 此功能应与在 GitLab 13.0 之后创建的索引一起使用. | + +**注意:** `TARGET_NAME`参数是可选的,如果未设置,它将使用当前`RAILS_ENV`的默认索引/别名. + +### Environment variables[](#environment-variables "Permalink") + +除了 Rake 任务,还有一些环境变量可用于修改过程: + +| 环境变量 | 数据类型 | 它能做什么 | +| --- | --- | --- | +| `UPDATE_INDEX` | Boolean | 告诉索引器覆盖任何现有索引数据(对/错). | +| `ID_TO` | Integer | 告诉索引器仅索引小于或等于该值的项目. | +| `ID_FROM` | Integer | 告诉索引器仅索引大于或等于该值的项目. | + +### Indexing a specific project[](#indexing-a-specific-project "Permalink") + +因为`ID_TO`和`ID_FROM`环境变量使用`or equal to`比较,所以您可以通过使用两个具有相同项目 ID 号的变量来仅索引一个项目: + +``` +root@git:~# sudo gitlab-rake gitlab:elastic:index_projects ID_TO=5 ID_FROM=5 +Indexing project repositories...I, [2019-03-04T21:27:03.083410 #3384] INFO -- : Indexing GitLab User / test (ID=33)... +I, [2019-03-04T21:27:05.215266 #3384] INFO -- : Indexing GitLab User / test (ID=33) is done! +``` + +## Elasticsearch index scopes[](#elasticsearch-index-scopes "Permalink") + +执行搜索时,GitLab 索引将使用以下范围: + +| 范围名称 | What it searches | +| --- | --- | +| `commits` | 提交数据 | +| `projects` | 项目数据(默认) | +| `blobs` | Code | +| `issues` | 发行数据 | +| `merge_requests` | 合并请求数据 | +| `milestones` | 里程碑数据 | +| `notes` | 笔记数据 | +| `snippets` | 片段数据 | +| `wiki_blobs` | 维基内容 | + +## Tuning[](#tuning "Permalink") + +### Guidance on choosing optimal cluster configuration[](#guidance-on-choosing-optimal-cluster-configuration "Permalink") + +有关选择集群配置的基本指导,请参考[Elastic Cloud Calculator](https://cloud.elastic.co/pricing) . 您可以在下面找到更多信息. + +* 通常,您将希望至少将一个 2 节点群集配置与一个副本一起使用,这将使您具有弹性. 如果存储使用量快速增长,则可能需要预先计划水平扩展(添加更多节点). +* 不建议将 HDD 存储与搜索群集一起使用,因为它会影响性能. 最好使用 SSD 存储(例如 NVMe 或 SATA SSD 驱动器). +* 您可以使用[GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance)来对不同搜索集群大小和配置的搜索性能进行基准测试. +* `Heap size`应设置为不超过物理 RAM 的 50%. 此外,不应将其设置为超过基于零的压缩 oop 的阈值. 确切的阈值会有所不同,但是在大多数系统上 26 GB 是安全的,但在某些系统上也可能高达 30 GB. 有关更多详细信息,请参见[设置堆大小](https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html#heap-size) . +* 每个节点的 CPU(CPU 核心)数通常对应于以下所述`Number of Elasticsearch shards`设置. +* 一个好的指导方针是确保每个节点的已配置 GB 堆中的碎片数保持在 20 个以下. 因此,具有 30GB 堆的节点最多应具有 600 个分片,但是越低于此限制,您可以使其越好. 通常,这将有助于群集保持良好的运行状况. +* 小碎片会导致小段,这会增加开销. 旨在将平均分片大小保持在至少几 GB 到几十 GB 之间. 另一个考虑因素是文档数量,您应该针对此简单的分片`number of expected documents / 5M +1`公式: `number of expected documents / 5M +1` . +* `refresh_interval`是每个索引设置. 如果您不需要实时数据,则可能需要将其从默认的`1s`调整为更大的值. 这将改变您看到新结果的时间. 如果这对您很重要,则应使其尽可能接近默认值. +* 如果您有大量繁重的索引操作,则可能需要将[`indices.memory.index_buffer_size`](https://www.elastic.co/guide/en/elasticsearch/reference/current/indexing-buffer.html)提高到 30%或 40%. + +### Elasticsearch integration settings guidance[](#elasticsearch-integration-settings-guidance "Permalink") + +* The `Number of Elasticsearch shards` setting usually corresponds with the number of CPUs available in your cluster. For example, if you have a 3-node cluster with 4 cores each, this means you will benefit from having at least 3*4=12 shards in the cluster. Please note, it’s only possible to change the shards number by using [Split index API](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-split-index.html) or by reindexing to a different index with a changed number of shards. +* `Number of Elasticsearch replicas`设置在大多数情况下应等于`1` (每个分片将具有 1 个副本). 不建议使用`0` ,因为丢失一个节点会破坏索引. + +### Deleted documents[](#deleted-documents "Permalink") + +每当对索引的 GitLab 对象进行更改或删除时(合并请求描述发生更改,从存储库中的 master 分支中删除文件,删除项目等),索引中的文档也会被删除. 但是,由于这些是"软"删除,因此"已删除文档"的总数增加了,因此浪费了空间. Elasticsearch 进行段的智能合并,以删除这些已删除的文档. 但是,根据 GitLab 安装中活动的数量和类型,可能会在索引中看到多达 50%的浪费空间. + +通常,我们建议仅使用默认设置让 Elasticsearch 自动合并和回收空间. 在[Lucene 的"已删除文档处理"中](https://www.elastic.co/blog/lucenes-handling-of-deleted-documents "Lucene 处理已删除文件的方法") , *"总的来说,除了减小最大段大小外,最好将 Lucene 的默认值保持原样,并且不要对回收删除时感到担心."* + +但是,某些较大的安装可能希望调整合并策略设置: + +* 考虑将`index.merge.policy.max_merged_segment`大小从默认的 5 GB 减小到 2 GB 或 3 GB. 仅当段中至少有 50%的删除时才进行合并. 较小的段大小将允许合并更频繁地发生. + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings ---header 'Content-Type: application/json' --data '{ + "index" : { + "merge.policy.max_merged_segment": "2gb" + } + }' + ``` + +* 您还可以调整`index.merge.policy.reclaim_deletes_weight` ,它控制如何积极地定位删除. 但是,这可能会导致代价高昂的合并决策,因此,除非您了解取舍,否则我们建议不要更改此决策. + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings ---header 'Content-Type: application/json' --data '{ + "index" : { + "merge.policy.reclaim_deletes_weight": "3.0" + } + }' + ``` + +* 不要[强制合并](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html "强制合并")以删除已删除的文档. [文档中](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html "强制合并")的警告指出,这可能导致很大的网段,这些网段可能永远都无法收回,并且还可能导致严重的性能或可用性问题. + +## Troubleshooting[](#troubleshooting "Permalink") + +### Common issues[](#common-issues "Permalink") + +以下是一些常见的陷阱以及如何克服它们: + +* **如何验证我的 GitLab 实例正在使用 Elasticsearch?** + + 最简单的方法是通过运行以下`sudo gitlab-rails console`通过 rails 控制台( `sudo gitlab-rails console` ): + + ``` + u = User.find_by_username('your-username') + s = SearchService.new(u, {:search => 'search_term'}) + pp s.search_objects.class.name + ``` + + 如果看到`"ActiveRecord::Relation"` ,则说明您**未**使用 Elasticsearch. + + If you see `"Kaminari::PaginatableArray"` you are using Elasticsearch. + + **注意:**以上说明仅用于在索引所有名称空间时验证 GitLab 是否正在使用 Elasticsearch. 这仅用于仅索引[命名空间子集的](#limiting-namespaces-and-projects)方案. +* **我更新了 GitLab,现在找不到任何东西** + + 我们会不断更新索引策略,并致力于支持新版本的 Elasticsearch. 进行索引更改时,更新 GitLab 后可能需要重新编制[索引](#adding-gitlabs-data-to-the-elasticsearch-index) . + +* **我索引了所有存储库,但找不到任何内容** + + 确保[如上所述对](#adding-gitlabs-data-to-the-elasticsearch-index)所有数据库数据建立索引. + + 除此之外,通过[Elasticsearch Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html)检查数据是否在 Elasticsearch 端显示. + + 如果通过[Elasticsearch Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html)显示,请检查是否通过 rails 控制台( `sudo gitlab-rails console` )显示: + + ``` + u = User.find_by_username('your-username') + s = SearchService.new(u, {:search => 'search_term', :scope => 'blobs'}) + pp s.search_objects.to_a + ``` + + **注意:**以上说明不适用于仅索引[命名空间子集的情况](#limiting-namespaces-and-projects) . + + 有关搜索特定数据类型的更多信息,请参见[Elasticsearch 索引范围](#elasticsearch-index-scopes) . + +* **我索引了所有存储库,但随后切换了 Elasticsearch 服务器,现在什么也找不到** + + 您将需要重新运行所有 Rake 任务,以重新索引数据库,存储库和 Wiki. + +* **索引过程需要很长时间** + + GitLab 实例中存在的数据越多,索引过程花费的时间就越长. + +* **有些项目未编入索引,但我们不知道哪些项目** + + 您可以运行`sudo gitlab-rake gitlab:elastic:projects_not_indexed`以显示未建立索引的项目. + +* **"如果未配置父字段,则无法指定父"** + + 如果您在 GitLab 8.12 之前启用了 Elasticsearch 并且尚未重建索引,则在许多不同情况下,您将获得异常: + + ``` + Elasticsearch::Transport::Transport::Errors::BadRequest([400] { + "error": { + "root_cause": [{ + "type": "illegal_argument_exception", + "reason": "Can't specify parent if no parent field has been configured" + }], + "type": "illegal_argument_exception", + "reason": "Can't specify parent if no parent field has been configured" + }, + "status": 400 + }): + ``` + + 这是因为我们在 GitLab 8.12 中更改了索引映射,并且应该删除旧索引并再次从头开始构建,请参阅[8-11-to-8-12 更新指南中的](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/update/8.11-to-8.12.md#11-elasticsearch-index-update-if-you-currently-use-elasticsearch)详细信息. + +* Exception `Elasticsearch::Transport::Transport::Errors::BadRequest` + + 如果您有此例外情况(就像上面的情况一样,但实际消息有所不同),请检查您是否具有正确的 Elasticsearch 版本并满足其他[要求](#system-requirements) . 还有一种简单的方法可以使用`sudo gitlab-rake gitlab:check`命令自动检查它. + +* Exception `Elasticsearch::Transport::Transport::Errors::RequestEntityTooLarge` + + ``` + [413] {"Message":"Request size exceeded 10485760 bytes"} + ``` + + 当您将 Elasticsearch 集群配置为拒绝某个大小以上的请求(在这种情况下为 10MiB)时,会看到此异常. 这相当于`http.max_content_length`在设置`elasticsearch.yml` . 将其增大到更大的大小,然后重新启动您的 Elasticsearch 集群. + + AWS 根据基础实例的大小对此设置有[固定的限制](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/aes-limits.html) (" HTTP 请求有效负载的最大大小"). + +* **即使一切似乎都正常运行,我的单节点 Elasticsearch 集群状态也从未从`yellow`变为`green`** + + **对于单节点 Elasticsearch 集群,功能集群的运行状况为黄色** (永远不会为绿色),因为已分配了主要分片,但副本却无法存在,因为没有其他节点可为 Elasticsearch 分配副本. 如果您使用的是[Amazon Elasticsearch](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/aes-handling-errors.html#aes-handling-errors-yellow-cluster-status) Service,这也适用. + + **警告:**建议不要将副本数设置为`0` (GitLab Elasticsearch 集成菜单中不允许这样做). 如果您计划添加更多的 Elasticsearch 节点(总共超过 1 个 Elasticsearch 节点),则副本数将需要设置为大于`0`的整数值. 否则,将导致缺乏冗余(丢失一个节点将破坏索引). + + 如果您**对单节点 Elasticsearch 集群有绿色状态**的**严格要求** ,请确保您了解上一段概述的风险,然后只需运行以下查询将副本数设置为`0` (集群将不会再尝试创建任何碎片副本): + + ``` + curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{ + "index" : { + "number_of_replicas" : 0 + } + }' + ``` + +* **我正在`health check timeout: no Elasticsearch node available`索引编制过程中 Sidekiq 中`health check timeout: no Elasticsearch node available`错误** + + ``` + Gitlab::Elastic::Indexer::Error: time="2020-01-23T09:13:00Z" level=fatal msg="health check timeout: no Elasticsearch node available" + ``` + + 您可能没有在 Elasticsearch 集成菜单的**" URL"**字段中使用`http://`或`https://`作为值的一部分. 请确保在此字段中使用`http://`或`https://`作为我们使用的[Go](https://github.com/olivere/elastic)的[Elasticsearch 客户端,](https://github.com/olivere/elastic) [需要将该 URL 的前缀接受为有效](https://github.com/olivere/elastic/commit/a80af35aa41856dc2c986204e2b64eab81ccac3a) . 更正了网址格式后,请删除索引(通过[专用的 Rake 任务](#gitlab-elasticsearch-rake-tasks) ),然后[为实例的内容重新编制索引](#adding-gitlabs-data-to-the-elasticsearch-index) . + +### Low-level troubleshooting[](#low-level-troubleshooting "Permalink") + +当您遇到其他问题(包括性能不佳)时[,](../administration/troubleshooting/elasticsearch.html)可以使用[结构化的低级故障排除文档](../administration/troubleshooting/elasticsearch.html) . + +### Known Issues[](#known-issues "Permalink") + +* **[Elasticsearch `code_analyzer` doesn’t account for all code cases](https://gitlab.com/gitlab-org/gitlab/-/issues/10693)** + + 正在评估`code_analyzer`模式和过滤器配置以进行改进. 我们注意到由于我们的模式和过滤器配置, [一些边缘情况](https://gitlab.com/gitlab-org/gitlab/-/issues/10693#note_158382332)未返回预期的搜索结果. + + 在[问题 29443](https://gitlab.com/gitlab-org/gitlab/-/issues/29443)中,讨论了`code_analyzer`模式和过滤器的改进策略. + +### Reverting to basic search[](#reverting-to-basic-search "Permalink") + +有时,您的 Elasticsearch 索引数据可能存在问题,因此,如果没有搜索结果并且假定该范围内支持基本搜索,则 GitLab 将允许您恢复为"基本搜索". 这种"基本搜索"的行为就像您根本没有为实例启用 Elasticsearch 并使用其他数据源(即 PostgreSQL 数据和 Git 数据)进行搜索一样. \ No newline at end of file diff --git a/docs/468.md b/docs/468.md new file mode 100644 index 0000000000000000000000000000000000000000..b1f732e7445712c4ce6a53931c348fddbce35bce --- /dev/null +++ b/docs/468.md @@ -0,0 +1,1068 @@ +# Gitaly + +> 原文:[https://docs.gitlab.com/ee/administration/gitaly/](https://docs.gitlab.com/ee/administration/gitaly/) + +* [Architecture](#architecture) +* [Configure Gitaly](#configure-gitaly) +* [Run Gitaly on its own server](#run-gitaly-on-its-own-server) + * [Network architecture](#network-architecture) + * [Install Gitaly](#install-gitaly) + * [Configure authentication](#configure-authentication) + * [Configure Gitaly servers](#configure-gitaly-servers) + * [Configure Gitaly clients](#configure-gitaly-clients) + * [Mixed configuration](#mixed-configuration) + * [Disable Gitaly where not required (optional)](#disable-gitaly-where-not-required-optional) +* [Enable TLS support](#enable-tls-support) + * [Observe type of Gitaly connections](#observe-type-of-gitaly-connections) +* [`gitaly-ruby`](#gitaly-ruby) + * [Configure number of `gitaly-ruby` workers](#configure-number-of-gitaly-ruby-workers) +* [Limit RPC concurrency](#limit-rpc-concurrency) +* [Rotate Gitaly authentication token](#rotate-gitaly-authentication-token) + * [Verify authentication monitoring](#verify-authentication-monitoring) + * [Enable “auth transitioning” mode](#enable-auth-transitioning-mode) + * [Update Gitaly authentication token](#update-gitaly-authentication-token) + * [Ensure there are no authentication failures](#ensure-there-are-no-authentication-failures) + * [Disable “auth transitioning” mode](#disable-auth-transitioning-mode) + * [Verify authentication is enforced](#verify-authentication-is-enforced) +* [Direct Git access bypassing Gitaly](#direct-git-access-bypassing-gitaly) +* [Direct access to Git in GitLab](#direct-access-to-git-in-gitlab) + * [History](#history) + * [How it works](#how-it-works) + * [Transition to Gitaly Cluster](#transition-to-gitaly-cluster) +* [Troubleshooting Gitaly](#troubleshooting-gitaly) + * [Checking versions when using standalone Gitaly servers](#checking-versions-when-using-standalone-gitaly-servers) + * [`gitaly-debug`](#gitaly-debug) + * [Commits, pushes, and clones return a 401](#commits-pushes-and-clones-return-a-401) + * [Client side gRPC logs](#client-side-grpc-logs) + * [Observing `gitaly-ruby` traffic](#observing-gitaly-ruby-traffic) + * [Repository changes fail with a `401 Unauthorized` error](#repository-changes-fail-with-a-401-unauthorized-error) + * [Command line tools cannot connect to Gitaly](#command-line-tools-cannot-connect-to-gitaly) + * [Gitaly not listening on new address after reconfiguring](#gitaly-not-listening-on-new-address-after-reconfiguring) + * [Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly server](#permission-denied-errors-appearing-in-gitaly-logs-when-accessing-repositories-from-a-standalone-gitaly-server) + * [Praefect](#praefect) + +# Gitaly[](#gitaly "Permalink") + +[Gitaly](https://gitlab.com/gitlab-org/gitaly)是提供对 Git 存储库的高级 RPC 访问的服务. 没有它,任何 GitLab 组件都无法读取或写入 Git 数据. + +在 Gitaly 文档中: + +* **Gitaly 服务器**是指任何本身运行 Gitaly 的节点. +* **Gitaly 客户端**指的是任何运行向 Gitaly 服务器发出请求的进程的节点. 流程包括但不限于: + * [GitLab Rails 应用程序](https://gitlab.com/gitlab-org/gitlab) . + * [GitLab 外壳](https://gitlab.com/gitlab-org/gitlab-shell) . + * [亚搏体育 app Labhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) . + +GitLab 最终用户无法直接访问 Gitaly. Gitaly 仅管理 GitLab 的 Git 存储库访问. 其他类型的 GitLab 数据无法使用 Gitaly 访问. + +**警告:**从 GitLab 13.0 起,不支持 Gitaly 对 NFS 的支持. 在 GitLab 14.0 中,计划删除对 NFS 的 Gitaly 支持. 尽快升级到[Gitaly Cluster](praefect.html) . + +## Architecture[](#architecture "Permalink") + +以下是有关如何使用 Gitaly 的高级体系结构概述. + +[![Gitaly architecture diagram](img/eb93aca89ce7486ca89aa5a9f4357617.png)](img/architecture_v12_4.png) + +## Configure Gitaly[](#configure-gitaly "Permalink") + +Gitaly 服务本身是通过[TOML 配置文件配置的](reference.html) . + +要更改 Gitaly 设置,请执行以下操作: + +**对于所有 GitLab** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加或更改[Gitaly 设置](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/1dd07197c7e5ae23626aad5a4a070a800b670380/files/gitlab-config-template/gitlab.rb.template#L1622-1676) . +2. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +**对于源安装** + +1. 编辑`/home/git/gitaly/config.toml`并添加或更改[Gitaly 设置](https://gitlab.com/gitlab-org/gitaly/blob/master/config.toml.example) . +2. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . + +以下配置选项也可用: + +* Enabling [TLS support](#enable-tls-support). +* 配置[`gitaly-ruby`工人](#configure-number-of-gitaly-ruby-workers)的[数量](#configure-number-of-gitaly-ruby-workers) . +* Limiting [RPC concurrency](#limit-rpc-concurrency). + +## Run Gitaly on its own server[](#run-gitaly-on-its-own-server "Permalink") + +默认情况下,Gitaly 与 Gitaly 客户端在同一服务器上运行,并按[上述配置](#configure-gitaly) . 单服务器安装最好由以下默认配置使用: + +* [Omnibus GitLab](https://docs.gitlab.com/omnibus/). +* GitLab [源代码安装指南](../../install/installation.html) . + +However, Gitaly can be deployed to its own server, which can benefit GitLab installations that span multiple machines. + +**注意:**配置为在自己的服务器上运行时, [必须先升级](https://docs.gitlab.com/omnibus/update/) Gitaly 服务器,然后才能在群集中的 Gitaly 客户端上[进行升级](https://docs.gitlab.com/omnibus/update/) . + +在自己的服务器上设置 Gitaly 的过程是: + +1. [Install Gitaly](#install-gitaly). +2. [Configure authentication](#configure-authentication). +3. [Configure Gitaly servers](#configure-gitaly-servers). +4. [Configure Gitaly clients](#configure-gitaly-clients). +5. [Disable Gitaly where not required](#disable-gitaly-where-not-required-optional) (optional). + +在自己的服务器上运行 Gitaly 时,请注意有关 GitLab 版本的以下内容: + +* 从 GitLab 11.4 起,除了[Elasticsearch indexer](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer)之外,Gitaly 能够满足所有 Git 请求,而无需为 Git 存储库数据共享 NFS 挂载. +* 从 GitLab 11.8 开始,Elasticsearch 索引器还使用 Gitaly 进行数据访问. NFS 仍可用于块级 Git 数据的冗余,但仅需安装在 Gitaly 服务器上. +* 从 GitLab 11.8 到 12.2,可以在不使用 NFS 的 Gitaly 设置中使用 Elasticsearch. 为了在这些版本中使用 Elasticsearch,必须在您的 GitLab 配置中启用[存储库索引器](../../integration/elasticsearch.html#elasticsearch-repository-indexer) . +* [从 GitLab 12.3 开始](https://gitlab.com/gitlab-org/gitlab/-/issues/6481) ,新的索引器是默认的,不需要任何配置. + +### Network architecture[](#network-architecture "Permalink") + +以下列表描述了 Gitaly 的网络体系结构: + +* GitLab Rails shards repositories into [repository storages](../repository_storage_paths.html). +* `/config/gitlab.yml`包含从存储名称到`(Gitaly address, Gitaly token)`对的`(Gitaly address, Gitaly token)` . +* `/config/gitlab.yml`的`storage name` -> `(Gitaly address, Gitaly token)`映射是 Gitaly 网络拓扑的唯一事实来源. +* `(Gitaly address, Gitaly token)`对应于 Gitaly 服务器. +* Gitaly 服务器托管一个或多个存储. +* 一个 Gitaly 客户端可以使用一个或多个 Gitaly 服务器. +* 必须以对**所有** Gitaly 客户端正确解析的方式指定 Gitaly 地址. +* Gitaly 客户包括: + * 美洲狮或独角兽. + * Sidekiq. + * 亚搏体育 app Labhorse. + * GitLab 外壳. + * Elasticsearch 索引器. + * Gitaly 本身. +* 一个 Gitaly 服务器必须能够通过其自身发出 RPC 调用**本身** `(Gitaly address, Gitaly token)`在指定的一对`/config/gitlab.yml` . +* 认证通过静态令牌完成,该令牌在 Gitaly 和 GitLab Rails 节点之间共享. + +**危险:** Gitaly 服务器不得暴露于公共互联网,因为默认情况下 Gitaly 的网络流量未加密. 强烈建议使用防火墙,以限制对 Gitaly 服务器的访问. 另一种选择是[使用 TLS](#enable-tls-support) . + +在以下各节中,我们描述如何使用秘密令牌`abc123secret`配置两个 Gitaly 服务器: + +* `gitaly1.internal`. +* `gitaly2.internal`. + +我们假设您的 GitLab 安装具有三个存储库存储: + +* `default`. +* `storage1`. +* `storage2`. + +如果需要,一台服务器最多只能使用一个存储库. + +**注意:** Gitaly 文档中引用的令牌只是管理员选择的任意密码. 它与为 GitLab API 创建的令牌或其他类似的 Web API 令牌无关. + +### Install Gitaly[](#install-gitaly "Permalink") + +使用 Omnibus GitLab 在每台 Gitaly 服务器上安装 Gitaly 或从源代码安装它: + +* 对于 Omnibus GitLab,请[下载并安装](https://about.gitlab.com/install/)所需的 Omnibus GitLab 软件包,但**不要**提供`EXTERNAL_URL=`值. +* 要从源代码安装,请遵循[Install Gitaly 上](../../install/installation.html#install-gitaly)的步骤. + +### Configure authentication[](#configure-authentication "Permalink") + +Gitaly 和 GitLab 使用两个共享的机密进行身份验证: + +* 一种用于向 Gitaly 验证 gRPC 请求的身份. +* A second for authentication callbacks from GitLab Shell to the GitLab internal API. + +**对于所有 GitLab** + +要配置 Gitaly 令牌: + +1. 在 Gitaly 客户端上,编辑`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_rails['gitaly_token'] = 'abc123secret' + ``` + +2. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +3. 在 Gitaly 服务器上,编辑`/etc/gitlab/gitlab.rb` : + + ``` + gitaly['auth_token'] = 'abc123secret' + ``` + +4. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +有两种方法可以配置 GitLab Shell 令牌. + +方法 1: + +1. 将`/etc/gitlab/gitlab-secrets.json`从 Gitaly 客户端复制到 Gitaly 服务器(和任何其他 Gitaly 客户端)上的相同路径. +2. 在 Gitaly 服务器上[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +方法 2: + +1. 在 Gitaly 客户端上,编辑`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_shell['secret_token'] = 'shellsecret' + ``` + +2. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +3. 在 Gitaly 服务器上,编辑`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_shell['secret_token'] = 'shellsecret' + ``` + +4. [Reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +**对于源安装** + +1. 将`/home/git/gitlab/.gitlab_shell_secret`从 Gitaly 客户端复制到 Gitaly 服务器(和任何其他 Gitaly 客户端)上的相同路径. +2. 在 Gitaly 客户端上,编辑`/home/git/gitlab/config/gitlab.yml` : + + ``` + gitlab: + gitaly: + token: 'abc123secret' + ``` + +3. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . +4. 在 Gitaly 服务器上,编辑`/home/git/gitaly/config.toml` : + + ``` + [auth] + token = 'abc123secret' + ``` + +5. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . + +### Configure Gitaly servers[](#configure-gitaly-servers "Permalink") + +在 Gitaly 服务器上,您必须配置存储路径并启用网络侦听器. + +如果要减少启用身份验证时发生停机的风险,可以暂时禁用强制实施. 有关更多信息,请参阅有关配置[Gitaly 身份验证](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/configuration/README.md#authentication)的文档. + +**对于所有 GitLab** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + # /etc/gitlab/gitlab.rb + + # Avoid running unnecessary services on the Gitaly server + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + puma['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + grafana['enable'] = false + gitlab_exporter['enable'] = false + + # If you run a separate monitoring node you can disable these services + alertmanager['enable'] = false + prometheus['enable'] = false + + # If you don't run a separate monitoring node you can + # enable Prometheus access & disable these extra services. + # This makes Prometheus listen on all interfaces. You must use firewalls to restrict access to this address/port. + # prometheus['listen_address'] = '0.0.0.0:9090' + # prometheus['monitor_kubernetes'] = false + + # If you don't want to run monitoring services uncomment the following (not recommended) + # node_exporter['enable'] = false + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your 'front door' GitLab URL or an internal load + # balancer. + # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from Gitaly client to Gitaly server. + gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' + + # Make Gitaly accept connections on all network interfaces. You must use + # firewalls to restrict access to this address/port. + # Comment out following line if you only want to support TLS connections + gitaly['listen_addr'] = "0.0.0.0:8075" + ``` + +2. 对于每个相应的 Gitaly 服务器,将以下内容附加到`/etc/gitlab/gitlab.rb` : + + On `gitaly1.internal`: + + ``` + git_data_dirs({ + 'default' => { + 'path' => '/var/opt/gitlab/git-data' + }, + 'storage1' => { + 'path' => '/mnt/gitlab/git-data' + }, + }) + ``` + + On `gitaly2.internal`: + + ``` + git_data_dirs({ + 'storage2' => { + 'path' => '/srv/gitlab/git-data' + }, + }) + ``` + +3. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +4. 运行`sudo /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml`以确认 Gitaly 可以执行对 GitLab 内部 API 的回调. + +**对于源安装** + +1. Edit `/home/git/gitaly/config.toml`: + + ``` + listen_addr = '0.0.0.0:8075' + + internal_socket_dir = '/var/opt/gitlab/gitaly' + + [logging] + format = 'json' + level = 'info' + dir = '/var/log/gitaly' + ``` + +2. 对于每个相应的 Gitaly 服务器,将以下内容附加到`/home/git/gitaly/config.toml` : + + On `gitaly1.internal`: + + ``` + [[storage]] + name = 'default' + path = '/var/opt/gitlab/git-data/repositories' + + [[storage]] + name = 'storage1' + path = '/mnt/gitlab/git-data/repositories' + ``` + + On `gitaly2.internal`: + + ``` + [[storage]] + name = 'storage2' + path = '/srv/gitlab/git-data/repositories' + ``` + +3. Edit `/home/git/gitlab-shell/config.yml`: + + ``` + gitlab_url: https://gitlab.example.com + ``` + +4. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . +5. 运行`sudo -u git /home/git/gitlab-shell/bin/check -config /home/git/gitlab-shell/config.yml`以确认 Gitaly 可以执行对 GitLab 内部 API 的回调. + +### Configure Gitaly clients[](#configure-gitaly-clients "Permalink") + +最后一步,您必须更新 Gitaly 客户端,使其从使用本地 Gitaly 服务切换为使用刚配置的 Gitaly 服务器. + +这可能会有风险,因为任何阻止您的 Gitaly 客户端访问 Gitaly 服务器的操作都将导致所有 Gitaly 请求失败. 例如,任何类型的网络,防火墙或名称解析问题. + +此外,如果以前手动启用,则必须[禁用 Rugged](../high_availability/nfs.html#improving-nfs-performance-with-gitlab) . + +Gitaly 作以下假设: + +* 你`gitaly1.internal` Gitaly 服务器可以达到`gitaly1.internal:8075`从 Gitaly 客户端,以及 Gitaly 服务器可以读取和写入`/mnt/gitlab/default`和`/mnt/gitlab/storage1` . +* 你`gitaly2.internal` Gitaly 服务器可以达到`gitaly2.internal:8075`从 Gitaly 客户端,以及 Gitaly 服务器可以读取和写入`/mnt/gitlab/storage2` . +* 您的`gitaly1.internal`和`gitaly2.internal` Gitaly 服务器可以相互访问. + +除非您使用特殊的[混合配置进行](#mixed-configuration)设置,否则不能将 Gitaly 服务器定义为本地 Gitaly 服务器(不带`gitaly_address` ),而`gitaly_address`一些服务器定义为远程服务器(带`gitaly_address` ). + +**对于所有 GitLab** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + ``` + +2. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +3. 运行`sudo gitlab-rake gitlab:gitaly:check`确认 Gitaly 客户端可以连接到 Gitaly 服务器. +4. 拖尾日志以查看请求: + + ``` + sudo gitlab-ctl tail gitaly + ``` + +**对于源安装** + +1. Edit `/home/git/gitlab/config/gitlab.yml`: + + ``` + gitlab: + repositories: + storages: + default: + gitaly_address: tcp://gitaly1.internal:8075 + path: /some/dummy/path + storage1: + gitaly_address: tcp://gitaly1.internal:8075 + path: /some/dummy/path + storage2: + gitaly_address: tcp://gitaly2.internal:8075 + path: /some/dummy/path + ``` + + **注意:** `/some/dummy/path`应该设置为存在的本地文件夹,但是该文件夹中不会存储任何数据. 解决[此问题](https://gitlab.com/gitlab-org/gitaly/-/issues/1282)后,将不再需要[此操作](https://gitlab.com/gitlab-org/gitaly/-/issues/1282) . +2. Save the file and [restart GitLab](../restart_gitlab.html#installations-from-source). +3. 运行`sudo -u git -H bundle exec rake gitlab:gitaly:check RAILS_ENV=production`确认 Gitaly 客户端可以连接到 Gitaly 服务器. +4. 拖尾日志以查看请求: + + ``` + tail -f /home/git/gitlab/log/gitaly.log + ``` + +尾随 Gitaly 服务器上的 Gitaly 登录时,您应该会看到请求进入.触发 Gitaly 请求的一种可靠方法是通过 HTTP 或 HTTPS 从 GitLab 克隆存储库. + +**危险:**如果已针对每个存储库或全局配置了[服务器挂钩](../server_hooks.html) ,则必须将它们移至 Gitaly 服务器. 如果您有多个 Gitaly 服务器,则将服务器挂钩复制到所有 Gitaly 服务器. + +#### Mixed configuration[](#mixed-configuration "Permalink") + +GitLab 可以与许多 Gitaly 服务器之一驻留在同一服务器上,但是不支持混合本地和远程配置的配置. 以下设置不正确,因为: + +* 所有地址都必须可从其他 Gitaly 服务器访问. +* `storage1`分配了一个`gitaly_address` Unix 套接字,该套接字对于某些 Gitaly 服务器无效. + +``` +git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'path' => '/mnt/gitlab/git-data' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, +}) +``` + +要组合本地和远程 Gitaly 服务器,请为本地 Gitaly 服务器使用一个外部地址. 例如: + +``` +git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + # Address of the GitLab server that has Gitaly running on it + 'storage1' => { 'gitaly_address' => 'tcp://gitlab.internal:8075', 'path' => '/mnt/gitlab/git-data' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, +}) +``` + +`path`只能包含在本地 Gitaly 服务器上的存储分片中. 如果不包含,则默认的 Git 存储目录将用于该存储碎片. + +### Disable Gitaly where not required (optional)[](#disable-gitaly-where-not-required-optional "Permalink") + +如果您将 Gitaly [作为远程服务](#run-gitaly-on-its-own-server)运行,则可能要禁用默认情况下在您的 GitLab 服务器上运行的本地 Gitaly 服务,而仅在需要时运行它. + +仅当您在自定义群集配置中运行 GitLab 时,才在 GitLab 实例上禁用 Gitaly 才有意义,在该配置中,Gitaly 在与 GitLab 实例不同的机器上运行. 在群集中的所有计算机上禁用 Gitaly 并不是有效的配置(某些计算机充当 Gitaly 服务器). + +To disable Gitaly on a GitLab server: + +**对于所有 GitLab** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitaly['enable'] = false + ``` + +2. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +**对于源安装** + +1. Edit `/etc/default/gitlab`: + + ``` + gitaly_enabled=false + ``` + +2. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . + +## Enable TLS support[](#enable-tls-support "Permalink") + +在 GitLab 11.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22602) . + +Gitaly 支持 TLS 加密. 要与侦听安全连接的 Gitaly 实例进行通信,必须在 GitLab 配置中相应存储条目的`gitaly_address`中使用`tls://` URL 方案. + +您必须提供自己的证书,因为不会自动提供. 与每个 Gitaly 服务器相对应的证书必须安装在该 Gitaly 服务器上. + +此外,证书(或其证书颁发机构)必须安装在所有以下组件上: + +* Gitaly 服务器,包括使用证书的 Gitaly 服务器. +* 与之通信的 Gitaly 客户. + +该过程记录在[GitLab 自定义证书配置中,](https://docs.gitlab.com/omnibus/settings/ssl.html)并在下面重复进行. + +请注意以下几点: + +* 证书必须指定用于访问 Gitaly 服务器的地址. 如果你是: + * 通过主机名寻址 Gitaly 服务器,您可以为此使用"公用名"字段,也可以将其添加为"使用者备用名". + * 通过其 IP 地址寻址 Gitaly 服务器,必须将其作为主题备用名称添加到证书中. [gRPC 不支持在证书中使用 IP 地址作为公用名](https://github.com/grpc/grpc/issues/2691) . +* 您可以同时为 Gitaly 服务器配置未加密的侦听地址`listen_addr`和已加密的侦听地址`tls_listen_addr` . 这使您可以根据需要从未加密的流量逐渐过渡到加密的流量. + +要使用 TLS 配置 Gitaly: + +**对于所有 GitLab** + +1. 为 Gitaly 服务器创建证书. +2. 在 Gitaly 客户端上,将证书(或其证书颁发机构)复制到`/etc/gitlab/trusted-certs` : + + ``` + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +3. 在 Gitaly 客户端上,如下所示在`/etc/gitlab/gitlab.rb`编辑`git_data_dirs` : + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' }, + }) + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 在 Gitaly 服务器上,创建`/etc/gitlab/ssl`目录,然后在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +6. 将所有 Gitaly 服务器证书(或其证书颁发机构)复制到`/etc/gitlab/trusted-certs`以便 Gitaly 服务器在调用自身或其他 Gitaly 服务器时将信任该证书: + + ``` + sudo cp cert1.pem cert2.pem /etc/gitlab/trusted-certs/ + ``` + +7. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + gitaly['tls_listen_addr'] = "0.0.0.0:9999" + gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + gitaly['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +8. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +9. 通过[观察 Gitaly 连接的类型,](#observe-type-of-gitaly-connections)验证通过 TLS 提供服务的 Gitaly 通信. +10. (可选)通过以下方式提高安全性: + 1. 通过注释或删除禁用非 TLS 连接`gitaly['listen_addr']`中`/etc/gitlab/gitlab.rb` . + 2. 保存文件. + 3. [重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +**对于源安装** + +1. 为 Gitaly 服务器创建证书. +2. 在 Gitaly 客户端上,将证书复制到系统受信任的证书中: + + ``` + sudo cp cert.pem /usr/local/share/ca-certificates/gitaly.crt + sudo update-ca-certificates + ``` + +3. 在 Gitaly 客户端上,如下所示在`/home/git/gitlab/config/gitlab.yml`编辑`storages` : + + ``` + gitlab: + repositories: + storages: + default: + gitaly_address: tls://gitaly1.internal:9999 + path: /some/dummy/path + storage1: + gitaly_address: tls://gitaly1.internal:9999 + path: /some/dummy/path + storage2: + gitaly_address: tls://gitaly2.internal:9999 + path: /some/dummy/path + ``` + + **注意:** `/some/dummy/path`应该设置为存在的本地文件夹,但是该文件夹中不会存储任何数据. 解决[Gitaly 问题#1282](https://gitlab.com/gitlab-org/gitaly/-/issues/1282)之后,将不再需要此操作. +4. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . +5. 在 Gitaly 服务器上,创建或编辑`/etc/default/gitlab`并添加: + + ``` + export SSL_CERT_DIR=/etc/gitlab/ssl + ``` + +6. 在 Gitaly 服务器上,创建`/etc/gitlab/ssl`目录,然后在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +7. 将所有 Gitaly 服务器证书(或其证书颁发机构)复制到系统受信任证书文件夹,以便 Gitaly 服务器在调用自身或其他 Gitaly 服务器时将信任该证书. + + ``` + sudo cp cert.pem /usr/local/share/ca-certificates/gitaly.crt + sudo update-ca-certificates + ``` + +8. 编辑`/home/git/gitaly/config.toml`并添加: + + ``` + tls_listen_addr = '0.0.0.0:9999' + + [tls] + certificate_path = '/etc/gitlab/ssl/cert.pem' + key_path = '/etc/gitlab/ssl/key.pem' + ``` + +9. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . +10. 通过[观察 Gitaly 连接的类型,](#observe-type-of-gitaly-connections)验证通过 TLS 提供服务的 Gitaly 通信. +11. (可选)通过以下方式提高安全性: + 1. 通过注释掉或删除`/home/git/gitaly/config.toml` `listen_addr`来禁用非 TLS 连接. + 2. 保存文件. + 3. [重新启动 GitLab](../restart_gitlab.html#installations-from-source) . + +### Observe type of Gitaly connections[](#observe-type-of-gitaly-connections "Permalink") + +可以使用[Prometheus](../monitoring/prometheus/index.html)观察 Gitaly 为生产环境提供服务的连接类型. 使用以下 Prometheus 查询: + +``` +sum(rate(gitaly_connections_total[5m])) by (type) +``` + +## `gitaly-ruby`[](#gitaly-ruby "Permalink") + +开发 Gitaly 是为了替代 GitLab 中的 Ruby 应用程序代码. + +为了节省时间并避免重写现有应用程序逻辑的风险,我们选择将一些应用程序代码从 GitLab 复制到 Gitaly. + +为了能够运行该代码,创建了`gitaly-ruby` ,它是主要 Gitaly Go 流程的" sidecar"流程. 在`gitaly-ruby`中实现的一些示例如下: + +* 处理 Wiki 的 RPC. +* 代表用户创建提交的 RPC,例如合并提交. + +### Configure number of `gitaly-ruby` workers[](#configure-number-of-gitaly-ruby-workers "Permalink") + +`gitaly-ruby`容量比 Go 中实现的 Gitaly 少得多. 如果您的 Gitaly 服务器必须处理大量请求,则仅设置一个活动的`gitaly-ruby`车的默认设置可能不够. + +如果您看到 Gitaly 出现`ResourceExhausted`错误,则很可能是您的`gitaly-ruby`能力不足. + +您可以使用以下设置来增加 Gitaly 服务器上的`gitaly-ruby`进程数: + +**对于所有 GitLab** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + # Default is 2 workers. The minimum is 2; 1 worker is always reserved as + # a passive stand-by. + gitaly['ruby_num_workers'] = 4 + ``` + +2. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +**对于源安装** + +1. Edit `/home/git/gitaly/config.toml`: + + ``` + [gitaly-ruby] + num_workers = 4 + ``` + +2. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . + +## Limit RPC concurrency[](#limit-rpc-concurrency "Permalink") + +克隆流量可能会对您的 Gitaly 服务造成很大的压力. 大部分工作在以下任一 RPC 中完成: + +* `SSHUploadPack` (用于 Git SSH). +* `PostUploadPack` (用于 Git HTTP). + +为了防止此类工作负载使您的 Gitaly 服务器不堪重负,您可以在 Gitaly 的配置文件中设置并发限制. 例如: + +``` +# in /etc/gitlab/gitlab.rb + +gitaly['concurrency'] = [ + { + 'rpc' => "/gitaly.SmartHTTPService/PostUploadPack", + 'max_per_repo' => 20 + }, + { + 'rpc' => "/gitaly.SSHService/SSHUploadPack", + 'max_per_repo' => 20 + } +] +``` + +这限制了给定 RPC 正在进行的 RPC 调用的数量. 该限制适用于每个存储库. 在上面的示例中: + +* Gitaly 服务器提供服务的每个存储库最多可以同时`PostUploadPack` 20 个`PostUploadPack` RPC 调用,而`SSHUploadPack`则相同. +* 如果另一个请求进入了已用完其 20 个插槽的存储库,则该请求将排队. + +您可以使用 Gitaly 日志和 Prometheus 观察此队列的行为: + +* 在 Gitaly 日志中,查找字符串(或结构化日志字段) `acquire_ms` . 具有此字段的消息正在报告有关并发限制器的信息. +* 在 Prometheus 中,查找以下指标: + + * `gitaly_rate_limiting_in_progress`. + * `gitaly_rate_limiting_queued`. + * `gitaly_rate_limiting_seconds`. + +**注意:**尽管 Prometheus 度量标准的名称包含`rate_limiting` ,但它是并发限制器,而不是速率限制器. 如果 Gitaly 客户端非常快地连续发出 1000 个请求,则并发不会超过 1,并且并发限制器无效. + +## Rotate Gitaly authentication token[](#rotate-gitaly-authentication-token "Permalink") + +在生产环境中轮换凭证通常需要停机,导致停机或两者兼而有之. + +但是,您可以旋转 Gitaly 凭据而不会中断服务. 旋转 Gitaly 身份验证令牌涉及: + +* [Verifying authentication monitoring](#verify-authentication-monitoring). +* [Enabling “auth transitioning” mode](#enable-auth-transitioning-mode). +* [Updating Gitaly authentication tokens](#update-gitaly-authentication-token). +* [Ensuring there are no authentication failures](#ensure-there-are-no-authentication-failures). +* [Disabling “auth transitioning” mode](#disable-auth-transitioning-mode). +* [Verifying authentication is enforced](#verify-authentication-is-enforced). + +如果您在单个服务器上运行 GitLab,则此过程也适用. 在这种情况下," Gitaly 服务器"和" Gitaly 客户端"是指同一台计算机. + +### Verify authentication monitoring[](#verify-authentication-monitoring "Permalink") + +旋转 Gitaly 身份验证令牌之前,请验证您可以使用 Prometheus 监视 GitLab 安装的身份验证行为. 使用以下 Prometheus 查询: + +``` +sum(rate(gitaly_authentications_total[5m])) by (enforced, status) +``` + +在正确配置了身份验证并且您拥有实时流量的系统中,您将看到以下内容: + +``` +{enforced="true",status="ok"} 4424.985419441742 +``` + +可能还存在速率为 0 的其他数字.我们只关心非零数字. + +唯一的非零数字应具有`enforced="true",status="ok"` . 如果您还有其他非零数字,则说明您的配置有问题. + +`status="ok"`数字反映您当前的请求率. 在上面的示例中,Gitaly 每秒处理大约 4000 个请求. + +既然您已经确定可以监视 GitLab 安装的 Gitaly 身份验证行为,则可以开始其余过程. + +### Enable “auth transitioning” mode[](#enable-auth-transitioning-mode "Permalink") + +通过将 Gitaly 服务器置于"身份验证过渡"模式,从而暂时禁用 Gitaly 服务器上的 Gitaly 身份验证,如下所示: + +``` +# in /etc/gitlab/gitlab.rb +gitaly['auth_transitioning'] = true +``` + +进行此更改后,您的[Prometheus 查询](#verify-authentication-monitoring)应返回如下内容: + +``` +{enforced="false",status="would be ok"} 4424.985419441742 +``` + +因为`enforced="false"` ,所以可以安全地开始部署新令牌. + +### Update Gitaly authentication token[](#update-gitaly-authentication-token "Permalink") + +要在每个 Gitaly 客户端**和** Gitaly 服务器上更新为新的 Gitaly 身份验证令牌,请执行以下操作: + +1. 更新配置: + + ``` + # in /etc/gitlab/gitlab.rb + + gitaly['auth_token'] = '' + ``` + +2. 重新启动 Gitaly: + + ``` + gitlab-ctl restart gitaly + ``` + +如果在实施此更改的同时运行[Prometheus 查询](#verify-authentication-monitoring) ,您将看到被`enforced="false",status="denied"`计数器的非零值. + +### Ensure there are no authentication failures[](#ensure-there-are-no-authentication-failures "Permalink") + +设置新令牌并重新启动所有涉及的服务之后,您将[临时看到以下内容](#verify-authentication-monitoring)的组合: + +* `status="would be ok"`. +* `status="denied"`. + +在所有 Gitaly 客户端和 Gitaly 服务器获取了新令牌之后,应`enforced="false",status="would be ok"` **唯一的非零费率** `enforced="false",status="would be ok"` . + +### Disable “auth transitioning” mode[](#disable-auth-transitioning-mode "Permalink") + +要重新启用 Gitaly 身份验证,请禁用"身份验证转换"模式. 如下更新您的 Gitaly 服务器上的配置: + +``` +# in /etc/gitlab/gitlab.rb +gitaly['auth_transitioning'] = false +``` + +**警告:**如果不完成此步骤,则**没有 Gitaly 身份验证** . + +### Verify authentication is enforced[](#verify-authentication-is-enforced "Permalink") + +刷新您的[Prometheus 查询](#verify-authentication-monitoring) . 现在,您应该会看到与开始时相似的结果. 例如: + +``` +{enforced="true",status="ok"} 4424.985419441742 +``` + +请注意, `enforced="true"`表示正在执行身份验证. + +## Direct Git access bypassing Gitaly[](#direct-git-access-bypassing-gitaly "Permalink") + +虽然可以使用 Git 客户端直接访问磁盘上存储的 Gitaly 存储库,但由于不断改进和更改 Gitaly,因此不建议这样做. 这些改进可能会使假设无效,从而导致性能下降,不稳定甚至数据丢失. + +Gitaly 进行了优化,例如[`info/refs`广告缓存](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/design_diskcache.md) ,它依赖于 Gitaly 通过官方 gRPC 接口控制和监视对存储库的访问. 同样,Praefect 具有优化功能,例如容错和分布式读取,这些优化取决于 gRPC 接口和数据库来确定存储库状态. + +由于这些原因, **直接访问存储库需要您自担风险,并且不受支持** . + +## Direct access to Git in GitLab[](#direct-access-to-git-in-gitlab "Permalink") + +直接访问 Git 使用 GitLab 中称为" Rugged patch"的代码. + +### History[](#history "Permalink") + +在 Gitaly 存在之前,现在 Gitaly 客户端用来直接访问 Git 存储库的是: + +* 如果是单机 Omnibus GitLab 安装,则在本地磁盘上 +* 如果是水平缩放的 GitLab 安装,请使用 NFS. + +除了运行简单的`git`命令之外,GitLab 还使用了一个名为[Rugged](https://github.com/libgit2/rugged)的 Ruby 库. Rugged 是围绕[libgit2](https://libgit2.org/)的包装, [libgit2](https://libgit2.org/)是 C 库形式的 Git 的独立实现. + +随着时间的流逝,很明显 Rugged(特别是与[Unicorn](https://yhbt.net/unicorn/)结合使用)非常有效. 因为`libgit2`是一个库而不是一个外部进程,所以之间的开销很小: + +* GitLab 应用程序代码试图在 Git 存储库中查找数据. +* Git 实现本身. + +由于 Rugged 和 Unicorn 的组合是如此有效,因此 GitLab 的应用程序代码最终会进行大量重复的 Git 对象查找. 例如,查找`master`在一个请求中提交了十几次. 我们可以编写效率低下的代码而不会降低性能. + +当我们将这些 Git 查找迁移到 Gitaly 调用时,我们突然发现每个 Git 查找的固定成本要高得多. 即使 Gitaly 能够重新使用已经在运行的`git`进程(例如,查找提交),您仍然可以: + +* 往返于 Gitaly 的网络费用. +* 在 Gitaly 中,是将 Gitaly 连接到`git`进程的 Unix 管道上的写入/读取往返. + +使用 GitLab.com 进行测量,我们减少了每个请求的 Gitaly 呼叫次数,直到不再感觉到 Rugged 效率的下降. 这也有助于我们直接在 Git 文件服务器上运行 Gitaly 本身,而不是通过 NFS 挂载. 这给了我们提速,抵消了不再使用 Rugged 带来的负面影响. + +不幸的是,GitLab 的其他部署无法像我们在 GitLab.com 上那样删除 NFS,这两个方面都是最糟糕的: + +* NFS 的速度较慢. +* The increased inherent overhead of Gitaly. + +在 Gitaly 迁移项目期间从 GitLab 中删除的代码影响了这些部署. 作为这些基于 NFS 的部署的性能变通办法,我们重新引入了一些旧的 Rugged 代码. 重新引入的代码被非正式地称为" Rugged patch". + +### How it works[](#how-it-works "Permalink") + +执行直接 Git 访问的 Ruby 方法位于[功能标志的](../../development/gitaly.html#legacy-rugged-code)后面,默认情况下处于禁用状态. 设置功能标记以获得最佳性能并不方便,因此我们添加了一种自动机制,可以直接访问 Git. + +当 GitLab 调用具有"加固补丁"的函数时,它将执行两项检查: + +* 数据库中是否设置了此补丁程序的功能标志? 如果是这样,功能标记设置将控制 GitLab 对"坚固补丁"代码的使用. +* 如果未设置功能标志,则 GitLab 尝试直接访问 Gitaly 服务器下方的文件系统. 如果可以,它将使用" Rugged patch". + +这两个检查的结果都被缓存. + +为了查看 GitLab 是否可以直接访问存储库文件系统,我们使用以下启发式: + +* Gitaly 确保文件系统在其根目录中具有一个带有 UUID 的元数据文件. +* Gitaly 通过`ServerInfo` RPC 将此 UUID 报告给 GitLab. +* GitLab Rails 尝试直接读取元数据文件. 如果存在,并且 UUID 匹配,则假定我们具有直接访问权限. + +默认情况下,在 Omnibus GitLab 中启用直接 Git 访问,因为它会在 GitLab 配置文件`config/gitlab.yml`填写正确的存储库路径. 这满足了 UUID 检查. + +### Transition to Gitaly Cluster[](#transition-to-gitaly-cluster "Permalink") + +为了消除复杂性,我们必须删除 GitLab 中的直接 Git 访问. 但是,只要某些 GitLab 安装需要 NFS 上的 Git 存储库,我们就无法删除它. + +我们在 GitLab 中删除直接 Git 访问的工作有两个方面: + +* 减少 GitLab 进行的低效率 Gitaly 查询的数量. +* 说服容错或水平扩展的 GitLab 实例的管理员从 NFS 迁移. + +第二个方面是唯一真正的解决方案. 为此,我们开发了[Gitaly Cluster](praefect.html) . + +## Troubleshooting Gitaly[](#troubleshooting-gitaly "Permalink") + +### Checking versions when using standalone Gitaly servers[](#checking-versions-when-using-standalone-gitaly-servers "Permalink") + +使用独立的 Gitaly 服务器时,必须确保它们与 GitLab 的版本相同,以确保完全兼容. 检查您的 GitLab 实例上的**管理区域> Gitaly 服务器** ,并确认所有 Gitaly 服务器都是`Up to date` . + +[![Gitaly standalone software versions diagram](img/ba685b05a8bb7c09fe3b58048ac4884e.png)](img/gitlab_gitaly_version_mismatch_v12_4.png) + +### `gitaly-debug`[](#gitaly-debug "Permalink") + +`gitaly-debug`命令提供用于" Gitaly"和" Git"性能的"生产调试"工具. 它旨在帮助生产工程师和支持工程师调查 Gitaly 性能问题. + +如果您使用的是 GitLab 11.6 或更高版本,则此工具应已安装在您的 GitLab / Gitaly 服务器上,位于`/opt/gitlab/embedded/bin/gitaly-debug` . 如果要研究旧版本的 GitLab,可以离线编译此工具,然后将可执行文件复制到服务器: + +``` +git clone https://gitlab.com/gitlab-org/gitaly.git +cd cmd/gitaly-debug +GOOS=linux GOARCH=amd64 go build -o gitaly-debug +``` + +要查看`gitaly-debug`的帮助页面以`gitaly-debug`受支持的子命令列表,请运行: + +``` +gitaly-debug -h +``` + +### Commits, pushes, and clones return a 401[](#commits-pushes-and-clones-return-a-401 "Permalink") + +``` +remote: GitLab: 401 Unauthorized +``` + +您将需要将`gitlab-secrets.json`文件与 Gitaly 客户端(GitLab 应用程序节点)同步. + +### Client side gRPC logs[](#client-side-grpc-logs "Permalink") + +Gitaly 使用[gRPC](https://grpc.io/) RPC 框架. Ruby gRPC 客户端具有自己的日志文件,当您看到 Gitaly 错误时,该文件可能包含有用的信息. 您可以使用`GRPC_LOG_LEVEL`环境变量控制 gRPC 客户端的日志级别. 默认级别为`WARN` . + +您可以使用以下命令运行 gRPC 跟踪: + +``` +sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check +``` + +### Observing `gitaly-ruby` traffic[](#observing-gitaly-ruby-traffic "Permalink") + +[`gitaly-ruby`](#gitaly-ruby)是[`gitaly-ruby`](#gitaly-ruby)的内部实现细节,因此,对`gitaly-ruby`流程内部发生的情况`gitaly-ruby` . + +如果已设置 Prometheus 来抓取 Gitaly 进程,则可以通过查询`grpc_client_handled_total`来`grpc_client_handled_total` `gitaly-ruby`各个 RPC 的请求率和错误代码. 严格来说,此度量标准并未区分`gitaly-ruby`和其他 RPC,但实际上(自 GitLab 11.9 起),Gitaly 本身进行的所有 gRPC 调用都是从 Gitaly 主过程到其`gitaly-ruby`边车之一的内部调用. + +假设您的`grpc_client_handled_total`计数器仅观察到 Gitaly,以下查询将显示 RPC 在内部(最有可能)实现为对`gitaly-ruby`调用: + +``` +sum(rate(grpc_client_handled_total[5m])) by (grpc_method) > 0 +``` + +### Repository changes fail with a `401 Unauthorized` error[](#repository-changes-fail-with-a-401-unauthorized-error "Permalink") + +如果您在自己的服务器上运行 Gitaly,并注意到用户可以成功克隆和获取存储库(通过 SSH 和 HTTPS),但是在未获得`401 Unauthorized`情况下,无法推送到它们或在 Web UI 中对存储库进行更改消息,那么 Gitaly 可能由于拥有[错误的 secrets 文件](#configure-gitaly-servers)而无法通过 Gitaly 客户端进行身份验证. + +确认以下所有内容均正确: + +* When any user performs a `git push` to any repository on this Gitaly server, it fails with the following error (note the `401 Unauthorized`): + + ``` + remote: GitLab: 401 Unauthorized + To + ! [remote rejected] branch-name -> branch-name (pre-receive hook declined) + error: failed to push some refs to '' + ``` + +* 当任何用户使用 GitLab UI 从存储库添加或修改文件时,该文件都会立即失败,并显示红色`401 Unauthorized`横幅. +* 创建一个新项目并[使用 README 对其进行初始化会](../../gitlab-basics/create-project.html#blank-projects)成功创建该项目,但不会创建 README. +* [将日志尾随在](https://docs.gitlab.com/omnibus/settings/logs.html) Gitaly 客户端上并重现该错误时,到达`/api/v4/internal/allowed`端点时会出现`401`错误: + + ``` + # api_json.log + { + "time": "2019-07-18T00:30:14.967Z", + "severity": "INFO", + "duration": 0.57, + "db": 0, + "view": 0.57, + "status": 401, + "method": "POST", + "path": "\/api\/v4\/internal\/allowed", + "params": [ + { + "key": "action", + "value": "git-receive-pack" + }, + { + "key": "changes", + "value": "REDACTED" + }, + { + "key": "gl_repository", + "value": "REDACTED" + }, + { + "key": "project", + "value": "\/path\/to\/project.git" + }, + { + "key": "protocol", + "value": "web" + }, + { + "key": "env", + "value": "{\"GIT_ALTERNATE_OBJECT_DIRECTORIES\":[],\"GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE\":[],\"GIT_OBJECT_DIRECTORY\":null,\"GIT_OBJECT_DIRECTORY_RELATIVE\":null}" + }, + { + "key": "user_id", + "value": "2" + }, + { + "key": "secret_token", + "value": "[FILTERED]" + } + ], + "host": "gitlab.example.com", + "ip": "REDACTED", + "ua": "Ruby", + "route": "\/api\/:version\/internal\/allowed", + "queue_duration": 4.24, + "gitaly_calls": 0, + "gitaly_duration": 0, + "correlation_id": "XPUZqTukaP3" + } + + # nginx_access.log + [IP] - - [18/Jul/2019:00:30:14 +0000] "POST /api/v4/internal/allowed HTTP/1.1" 401 30 "" "Ruby" + ``` + +要解决此问题,请确认 Gitaly 服务器上的 gitlab [`gitlab-secrets.json`文件](#configure-gitaly-servers)与 Gitaly 客户端上的[文件](#configure-gitaly-servers)匹配. 如果不匹配,请更新 Gitaly 服务器上的密码文件以匹配 Gitaly 客户端,然后[重新配置](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +### Command line tools cannot connect to Gitaly[](#command-line-tools-cannot-connect-to-gitaly "Permalink") + +如果使用命令行(CLI)工具连接到 Gitaly 服务器时遇到问题,并且某些操作导致出现`14: Connect Failed`错误消息,则意味着 gRPC 无法访问您的 Gitaly 服务器. + +确认您可以通过 TCP 到达 Gitaly: + +``` +sudo gitlab-rake gitlab:tcp_check[GITALY_SERVER_IP,GITALY_LISTEN_PORT] +``` + +如果 TCP 连接失败,请检查您的网络设置和防火墙规则. 如果 TCP 连接成功,则您的网络和防火墙规则正确. + +如果您在命令行环境(例如 Bash)中使用代理服务器,则这些代理服务器可能会干扰您的 gRPC 通信. + +如果使用 Bash 或兼容的命令行环境,请运行以下命令来确定是否配置了代理服务器: + +``` +echo $http_proxy +echo $https_proxy +``` + +如果这些变量中的任何一个都有值,则您的 Gitaly CLI 连接可能正在通过无法连接到 Gitaly 的代理进行路由. + +要删除代理设置,请运行以下命令(取决于哪些变量具有值): + +``` +unset http_proxy +unset https_proxy +``` + +### Gitaly not listening on new address after reconfiguring[](#gitaly-not-listening-on-new-address-after-reconfiguring "Permalink") + +当更新`gitaly['listen_addr']`或`gitaly['prometheus_listen_addr']`值时,Gitaly 可能会在`sudo gitlab-ctl reconfigure`后继续侦听旧地址. + +发生这种情况时,执行`sudo gitlab-ctl restart`将解决此问题. 解决[此问题](https://gitlab.com/gitlab-org/gitaly/-/issues/2521)后,将不再需要[此操作](https://gitlab.com/gitlab-org/gitaly/-/issues/2521) . + +### Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly server[](#permission-denied-errors-appearing-in-gitaly-logs-when-accessing-repositories-from-a-standalone-gitaly-server "Permalink") + +如果即使文件权限正确也发生此错误,则 Gitaly 服务器可能正在发生[时钟漂移](https://en.wikipedia.org/wiki/Clock_drift) . + +请确保 Gitaly 客户端和服务器已同步,并在可能的情况下使用 NTP 时间服务器保持同步. + +### Praefect[](#praefect "Permalink") + +Praefect 是 Gitaly 的路由器和事务管理器,并且是运行 Gitaly 集群的必需组件. 有关更多信息,请参见[Gitaly Cluster](praefect.html) . \ No newline at end of file diff --git a/docs/469.md b/docs/469.md new file mode 100644 index 0000000000000000000000000000000000000000..bf6c6b3833293c12d84cf719a7d009d5a4342515 --- /dev/null +++ b/docs/469.md @@ -0,0 +1,847 @@ +# Gitaly Cluster + +> 原文:[https://docs.gitlab.com/ee/administration/gitaly/praefect.html](https://docs.gitlab.com/ee/administration/gitaly/praefect.html) + +* [Requirements for configuring a Gitaly Cluster](#requirements-for-configuring-a-gitaly-cluster) +* [Setup Instructions](#setup-instructions) + * [Preparation](#preparation) + * [Secrets](#secrets) + * [PostgreSQL](#postgresql) + * [Praefect](#praefect) +* [Enabling TLS support](#enabling-tls-support) + * [Gitaly](#gitaly) + * [Load Balancer](#load-balancer) + * [GitLab](#gitlab) + * [Grafana](#grafana) +* [Distributed reads](#distributed-reads) +* [Automatic failover and leader election](#automatic-failover-and-leader-election) +* [Primary Node Failure](#primary-node-failure) + * [Checking for data loss](#checking-for-data-loss) + * [Checking repository checksums](#checking-repository-checksums) + * [Recovering lost writes](#recovering-lost-writes) + * [Enabling Writes](#enabling-writes) +* [Backend Node Recovery](#backend-node-recovery) +* [Migrating existing repositories to Praefect](#migrating-existing-repositories-to-praefect) +* [Debugging Praefect](#debugging-praefect) + +# Gitaly Cluster[](#gitaly-cluster "Permalink") + +[Gitaly](index.html) (为 Git 存储库提供存储的服务)可以在群集配置中运行,以提高容错能力. 在这种配置中,每个 Git 存储库都存储在集群中的每个 Gitaly 节点上. 可以配置多个集群(或分片). + +**注意:**可以使用[GitLab Core](https://about.gitlab.com/pricing/#self-managed)和更高层来创建 Gitaly 群集. 但是,技术支持仅限于 GitLab Premium 和 Ultimate 客户. 在 GitLab.com 中不可用. + +Praefect 是 Gitaly 的路由器和事务管理器,并且是运行 Gitaly 集群的必需组件. + +[![Architecture diagram](img/ff949c9ca6d0d99318f68a1784db7950.png)](img/praefect_architecture_v12_10.png) + +使用 Gitaly 群集可通过以下方式提高容错能力: + +* 复制写操作以预热备用 Gitaly 节点. +* 检测 Gitaly 节点故障. +* 自动将 Git 请求路由到可用的 Gitaly 节点. + +Gitaly 群集的可用性目标是: + +* **恢复点目标(RPO):**不到 1 分钟. + + 写入异步复制. 尚未复制到新提升的主数据库的所有写入都将丢失. + + 计划实现[高度一致性,](https://gitlab.com/groups/gitlab-org/-/epics/1189)以将其改进为"无损失". + +* **恢复时间目标(RTO):**少于 10 秒. + + 每秒通过每个 Praefect 节点运行的运行状况检查来检测中断. 故障转移要求每个 Praefect 节点上连续十次失败的运行状况检查. + + 计划进行[更快的中断检测](https://gitlab.com/gitlab-org/gitaly/-/issues/2608) ,以将其[缩短](https://gitlab.com/gitlab-org/gitaly/-/issues/2608)到不到 1 秒. + +当前版本支持: + +* 辅助副本的最终一致性. +* Automatic failover from the primary to the secondary. +* 如果复制队列不为空,则报告可能的数据丢失. +* 仅当检测到可能的数据丢失时,才将新升级的主要读标记为标记. + +遵循[HA Gitaly 史诗](https://gitlab.com/groups/gitlab-org/-/epics/1489)进行的改进,包括[横向分发读取](https://gitlab.com/groups/gitlab-org/-/epics/2013) . + +## Requirements for configuring a Gitaly Cluster[](#requirements-for-configuring-a-gitaly-cluster "Permalink") + +建议的 Gitaly 群集最低配置要求: + +* 1 个负载均衡器 +* 1 个 PostgreSQL 服务器(PostgreSQL 11 或更高版本) +* 节点长官 3 +* 3 个 Gitaly 节点(1 个主要节点,2 个辅助节点) + +有关实现的详细信息,请参见[设计文档](https://gitlab.com/gitlab-org/gitaly/-/blob/master/doc/design_ha.md) . + +## Setup Instructions[](#setup-instructions "Permalink") + +如果使用 Omnibus 软件包[安装了](https://about.gitlab.com/install/) GitLab(强烈建议),请按照以下步骤操作: + +1. [Preparation](#preparation) +2. [Configuring the Praefect database](#postgresql) +3. [Configuring the Praefect proxy/router](#praefect) +4. [配置每个 Gitaly 节点](#gitaly) ( [每个 Gitaly 节点](#gitaly)一次) +5. [Configure the load balancer](#load-balancer) +6. [Updating the GitLab server configuration](#gitlab) +7. [Configure Grafana](#grafana) + +### Preparation[](#preparation "Permalink") + +在开始之前,您应该已经有一个正常的 GitLab 实例. [了解如何安装 GitLab](https://about.gitlab.com/install/) . + +设置 PostgreSQL 服务器(PostgreSQL 11 或更高版本). 尚不支持通过 Omnibus GitLab 发行版进行配置. 请关注此[问题](https://gitlab.com/gitlab-org/gitaly/-/issues/2476)以进行更新. + +通过[安装 GitLab](https://about.gitlab.com/install/)准备所有新节点. + +* 1 个 Praefect 节点(需要最少的存储) +* 3 个 Gitaly 节点(高 CPU,高内存,快速存储) +* 1 个 GitLab 服务器 + +您将需要每个节点的 IP /主机地址. + +1. `LOAD_BALANCER_SERVER_ADDRESS` :负载均衡器的 IP /主机地址 +2. `POSTGRESQL_SERVER_ADDRESS` :PostgreSQL 服务器的 IP /主机地址 +3. `PRAEFECT_HOST` :Praefect 服务器的 IP /主机地址 +4. `GITALY_HOST` :每个 Gitaly 服务器的 IP /主机地址 +5. `GITLAB_HOST` :GitLab 服务器的 IP /主机地址 + +如果使用的是云提供商,则可以通过云提供商的管理控制台查找每个服务器的地址. + +如果您使用的是 Google Cloud Platform,SoftLayer 或提供虚拟私有云(VPC)的任何其他供应商,则可以将每个云实例的私有地址(对应于 Google Cloud Platform 的"内部地址")用于`PRAEFECT_HOST` , `GITALY_HOST` ,和`GITLAB_HOST` . + +#### Secrets[](#secrets "Permalink") + +组件之间的通信由不同的秘密保护,下面将对此进行描述. 在开始之前,请为每个密钥生成一个唯一的秘密,并记录下来. 在完成设置过程时,这将很容易用安全令牌替换这些占位符令牌. + +1. `GITLAB_SHELL_SECRET_TOKEN` :当接受 Git 推送时,Git 挂钩将其用于向 GitLab 发出回调 HTTP API 请求. 出于遗留原因,此秘密已与 GitLab Shell 共享. +2. `PRAEFECT_EXTERNAL_TOKEN` :承载此令牌的 Gitaly 客户端只能访问 Praefect 群集上托管的存储库. +3. `PRAEFECT_INTERNAL_TOKEN` :此令牌用于 Praefect 群集内的复制流量. 这与`PRAEFECT_EXTERNAL_TOKEN`不同,因为 Gitaly 客户端必须不能直接访问 Praefect 群集的内部节点. 可能导致数据丢失. +4. `PRAEFECT_SQL_PASSWORD` :Praefect 使用此密码连接到 PostgreSQL. + +我们将在以下说明中指出需要这些秘密的地方. + +### PostgreSQL[](#postgresql "Permalink") + +**注意:**如果使用[Geo,](../geo/replication/index.html)请勿将 GitLab 应用程序数据库和 Praefect 数据库存储在同一 PostgreSQL 服务器上. 复制状态是每个 GitLab 实例的内部状态,不应复制. + +要完成本节,您将需要: + +* 完美节点 1 +* 1 个 PostgreSQL 服务器(PostgreSQL 11 或更高版本) + * 具有创建数据库权限的 SQL 用户 + +在本节中,我们将使用 Omnibus GitLab 安装的`psql`从 Praefect 节点配置 PostgreSQL 服务器. + +1. SSH 进入**Praefect**节点并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 以管理员权限连接到 PostgreSQL 服务器. 这可能是`postgres`用户. 使用数据库`template1`是因为它默认在所有 PostgreSQL 服务器上创建. + + ``` + /opt/gitlab/embedded/bin/psql -U postgres -d template1 -h POSTGRESQL_SERVER_ADDRESS + ``` + + 创建一个将由 Praefect 使用的新用户`praefect` . 将`PRAEFECT_SQL_PASSWORD`替换为您在准备步骤中生成的强密码. + + ``` + CREATE ROLE praefect WITH LOGIN CREATEDB PASSWORD 'PRAEFECT_SQL_PASSWORD'; + ``` + +3. 这次以`praefect`用户身份重新连接到 PostgreSQL 服务器: + + ``` + /opt/gitlab/embedded/bin/psql -U praefect -d template1 -h POSTGRESQL_SERVER_ADDRESS + ``` + + 创建一个新的数据库`praefect_production` . 通过同时连接为创建数据库`praefect`的用户,我们有信心,他们有机会. + + ``` + CREATE DATABASE praefect_production WITH ENCODING=UTF8; + ``` + +现在已配置 Praefect 使用的数据库. + +### Praefect[](#praefect "Permalink") + +要完成本节,您将需要: + +* [配置的 PostgreSQL 服务器](#postgresql) ,包括: + * IP /主机地址( `POSTGRESQL_SERVER_ADDRESS` ) + * 密码( `PRAEFECT_SQL_PASSWORD` ) + +Praefect 应该在专用节点上运行. 不要在应用程序服务器或 Gitaly 节点上运行 Praefect. + +1. SSH 进入**Praefect**节点并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 通过编辑`/etc/gitlab/gitlab.rb`禁用所有其他服务: + + ``` + # Disable all other services on the Praefect node + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + prometheus['enable'] = false + grafana['enable'] = false + puma['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + gitaly['enable'] = false + + # Enable only the Praefect service + praefect['enable'] = true + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + ``` + +3. 通过编辑`/etc/gitlab/gitlab.rb` **Praefect**配置为侦听网络接口: + + ``` + praefect['listen_addr'] = '0.0.0.0:2305' + + # Enable Prometheus metrics access to Praefect. You must use firewalls + # to restrict access to this address/port. + praefect['prometheus_listen_addr'] = '0.0.0.0:9652' + ``` + +4. 配置强劲`auth_token`通过编辑**提督** `/etc/gitlab/gitlab.rb` . 群集外部的客户端(如 GitLab Shell)将需要与 Praefect 群集进行通信: + + ``` + praefect['auth_token'] = 'PRAEFECT_EXTERNAL_TOKEN' + ``` + +5. 通过编辑`/etc/gitlab/gitlab.rb`将**Praefect**配置为连接到 PostgreSQL 数据库. + + 您将需要用数据库的 IP /主机地址替换`POSTGRESQL_SERVER_ADDRESS` ,并用上面设置的强密码`PRAEFECT_SQL_PASSWORD` . + + ``` + praefect['database_host'] = 'POSTGRESQL_SERVER_ADDRESS' + praefect['database_port'] = 5432 + praefect['database_user'] = 'praefect' + praefect['database_password'] = 'PRAEFECT_SQL_PASSWORD' + praefect['database_dbname'] = 'praefect_production' + ``` + + 如果要使用 TLS 客户端证书,则可以使用以下选项: + + ``` + # Connect to PostreSQL using a TLS client certificate + # praefect['database_sslcert'] = '/path/to/client-cert' + # praefect['database_sslkey'] = '/path/to/client-key' + + # Trust a custom certificate authority + # praefect['database_sslrootcert'] = '/path/to/rootcert' + ``` + + 默认情况下,Praefect 将拒绝与 PostgreSQL 建立未加密的连接. 您可以通过取消注释以下行来覆盖它: + + ``` + # praefect['database_sslmode'] = 'disable' + ``` + +6. 通过编辑`/etc/gitlab/gitlab.rb`将**Praefect**群集配置为连接到群集中的每个 Gitaly 节点. + + 虚拟存储的名称必须与 GitLab 配置中配置的存储名称匹配. 在随后的步骤中,我们将存储名称配置为`default`名称,因此我们也在此处使用`default`名称. 该集群具有三个 Gitaly 节点`gitaly-1` , `gitaly-2`和`gitaly-3` ,它们将是彼此的副本. + + **注意:**如果您已经在名为`default`现有存储上存储了数据,则应使用其他名称配置虚拟存储,然后[将数据迁移到 Praefect 存储](#migrating-existing-repositories-to-praefect) . + + 将`PRAEFECT_INTERNAL_TOKEN`替换为一个强秘密,Praefect 将在与集群中的 Gitaly 节点通信时使用此秘密. 此令牌与`PRAEFECT_EXTERNAL_TOKEN` . + + 将`GITALY_HOST`替换为每个 Gitaly 节点的 IP /主机地址. + + 可以将更多 Gitaly 节点添加到群集以增加副本数. 还可以为大型 GitLab 实例添加更多集群. + + **注意:** `gitaly-1`节点当前称为主要节点. 这可用于从一个节点到另一个节点的手动故障. 这将在被删除[的未来](https://gitlab.com/gitlab-org/gitaly/-/issues/2634) . + + ``` + # Name of storage hash must match storage name in git_data_dirs on GitLab + # server ('praefect') and in git_data_dirs on Gitaly nodes ('gitaly-1') + praefect['virtual_storages'] = { + 'default' => { + 'gitaly-1' => { + 'address' => 'tcp://GITALY_HOST:8075', + 'token' => 'PRAEFECT_INTERNAL_TOKEN', + 'primary' => true + }, + 'gitaly-2' => { + 'address' => 'tcp://GITALY_HOST:8075', + 'token' => 'PRAEFECT_INTERNAL_TOKEN' + }, + 'gitaly-3' => { + 'address' => 'tcp://GITALY_HOST:8075', + 'token' => 'PRAEFECT_INTERNAL_TOKEN' + } + } + } + ``` + +7. 在 GitLab 13.1 和更高版本中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2013) ,启用了 read 的[分发](#distributed-reads) . + +8. 将更改保存到`/etc/gitlab/gitlab.rb`并[重新配置 Praefect](../restart_gitlab.html#omnibus-gitlab-reconfigure) : + + ``` + gitlab-ctl reconfigure + ``` + +9. 为了确保 Praefect [已更新其 Prometheus 监听地址](https://gitlab.com/gitlab-org/gitaly/-/issues/2734) ,请[重新启动 Gitaly](../restart_gitlab.html#omnibus-gitlab-restart) : + + ``` + gitlab-ctl restart praefect + ``` + +10. 验证 Praefect 可以到达 PostgreSQL: + + ``` + sudo -u git /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-ping + ``` + + 如果检查失败,请确保已正确执行了步骤. 如果您编辑`/etc/gitlab/gitlab.rb` ,请记住在尝试`sql-ping`命令之前再次运行`sudo gitlab-ctl reconfigure` . + +**必须为每个 Praefect 节点完成上述步骤!** + +## Enabling TLS support[](#enabling-tls-support "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitaly/-/issues/1698) . + +Praefect 支持 TLS 加密. 要与侦听安全连接的 Praefect 实例进行通信,您必须: + +* 在 GitLab 配置中相应存储条目的`gitaly_address`中使用`tls://` URL 方案. +* 带上您自己的证书,因为这不会自动提供. 与每个 Praefect 服务器相对应的证书必须安装在该 Praefect 服务器上. + +此外,必须按照[GitLab 自定义证书配置中](https://docs.gitlab.com/omnibus/settings/ssl.html)所述的过程(并在下面重复),将证书或其证书颁发机构安装在所有 Gitaly 服务器和与其通信的所有 Praefect 客户端上. + +请注意以下几点: + +* 证书必须指定用于访问 Praefect 服务器的地址. 如果通过以下方式寻址 Praefect 服务器: + + * 主机名,您可以为此使用"公用名"字段,也可以将其添加为"使用者备用名". + * IP 地址,您必须将其添加为证书的使用者备用名称. +* 您可以同时为 Praefect 服务器配置未加密的侦听地址`listen_addr`和已加密的侦听地址`tls_listen_addr` . 如果需要,这使您可以从未加密的流量逐渐过渡到加密的流量. + +要使用 TLS 配置 Praefect: + +**对于所有 GitLab** + +1. Prefect 为服务器创建证书. +2. 在 Praefect 服务器上,创建`/etc/gitlab/ssl`目录,然后在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +3. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + praefect['tls_listen_addr'] = "0.0.0.0:3305" + praefect['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + praefect['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +4. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +5. 在 Praefect 客户端(包括每个 Gitaly 服务器)上,将证书或其证书颁发机构复制到`/etc/gitlab/trusted-certs` : + + ``` + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +6. 在 Praefect 客户端(Gitaly 服务器除外)上,在`/etc/gitlab/gitlab.rb`编辑`git_data_dirs` ,如下所示: + + ``` + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://praefect1.internal:3305' }, + 'storage1' => { 'gitaly_address' => 'tls://praefect2.internal:3305' }, + }) + ``` + +7. 保存文件并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . + +**对于源安装** + +1. Prefect 为服务器创建证书. +2. 在 Praefect 服务器上,创建`/etc/gitlab/ssl`目录,然后在其中复制密钥和证书: + + ``` + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +3. 在 Praefect 客户端(包括每个 Gitaly 服务器)上,将证书或其证书颁发机构复制到系统信任的证书中: + + ``` + sudo cp cert.pem /usr/local/share/ca-certificates/praefect.crt + sudo update-ca-certificates + ``` + +4. 在 Praefect 客户端(Gitaly 服务器除外)上,按如下所示编辑`/home/git/gitlab/config/gitlab.yml` `storages` : + + ``` + gitlab: + repositories: + storages: + default: + gitaly_address: tls://praefect1.internal:3305 + path: /some/dummy/path + storage1: + gitaly_address: tls://praefect2.internal:3305 + path: /some/dummy/path + ``` + + **注意:** `/some/dummy/path`应该设置为存在的本地文件夹,但是该文件夹中不会存储任何数据. 解决[此问题](https://gitlab.com/gitlab-org/gitaly/-/issues/1282)后,将不再需要[此操作](https://gitlab.com/gitlab-org/gitaly/-/issues/1282) . +5. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . +6. 将所有 Praefect 服务器证书或其证书颁发机构复制到每台 Gitaly 服务器上的系统受信任证书,以便 Praefect 服务器在被 Gitaly 服务器调用时将信任该证书: + + ``` + sudo cp cert.pem /usr/local/share/ca-certificates/praefect.crt + sudo update-ca-certificates + ``` + +7. 编辑`/home/git/praefect/config.toml`并添加: + + ``` + tls_listen_addr = '0.0.0.0:3305' + + [tls] + certificate_path = '/etc/gitlab/ssl/cert.pem' + key_path = '/etc/gitlab/ssl/key.pem' + ``` + +8. 保存文件并[重新启动 GitLab](../restart_gitlab.html#installations-from-source) . + +### Gitaly[](#gitaly "Permalink") + +**注意:**为**每个** Gitaly 节点完成这些步骤. + +要完成本节,您将需要: + +* [Configured Praefect node](#praefect) +* 将 3 个(或更多)安装了 GitLab 的服务器配置为 Gitaly 节点. 这些应该是专用节点,不要在这些节点上运行其他服务. + +分配给 Praefect 群集的每个 Gitaly 服务器都需要配置. 该配置与普通的[独立 Gitaly 服务器相同](index.html) ,除了: + +* 存储名称公开给 Praefect,而不是 GitLab +* 秘密令牌是与 Praefect 共享的,而不是与 GitLab 共享的 + +Praefect 群集中所有 Gitaly 节点的配置可以相同,因为我们依靠 Praefect 正确地路由操作. + +应特别注意: + +* 本节中配置的`gitaly['auth_token']`必须与 Praefect 节点上`praefect['virtual_storages']`下的`token`值匹配. 这是在上[一节中](#praefect)设置的. 本文档始终使用占位符`PRAEFECT_INTERNAL_TOKEN` . +* 本节中配置的`git_data_dirs`中的存储名称必须与 Praefect 节点上`praefect['virtual_storages']`下的存储名称匹配. 这是在上[一节中](#praefect)设置的. 本文档使用`gitaly-1` , `gitaly-2`和`gitaly-3`作为 Gitaly 存储名称. + +有关 Gitaly 服务器配置的更多信息,请参阅我们的[Gitaly 文档](index.html#configure-gitaly-servers) . + +1. SSH 进入**Gitaly**节点并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. Disable all other services by editing `/etc/gitlab/gitlab.rb`: + + ``` + # Disable all other services on the Praefect node + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + grafana['enable'] = false + puma['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + prometheus_monitoring['enable'] = false + + # Enable only the Gitaly service + gitaly['enable'] = true + + # Enable Prometheus if needed + prometheus['enable'] = true + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + ``` + +3. 配置**Gitaly**通过编辑来听网络接口`/etc/gitlab/gitlab.rb` : + + ``` + # Make Gitaly accept connections on all network interfaces. + # Use firewalls to restrict access to this address/port. + gitaly['listen_addr'] = '0.0.0.0:8075' + + # Enable Prometheus metrics access to Gitaly. You must use firewalls + # to restrict access to this address/port. + gitaly['prometheus_listen_addr'] = '0.0.0.0:9236' + ``` + +4. 配置强劲`auth_token`通过编辑**Gitaly** `/etc/gitlab/gitlab.rb` . 客户端将需要与该 Gitaly 节点进行通信. 通常,此令牌对于所有 Gitaly 节点都是相同的. + + ``` + gitaly['auth_token'] = 'PRAEFECT_INTERNAL_TOKEN' + ``` + +5. 配置`git push`操作所需的 GitLab Shell `secret_token`和`internal_api_url` . + + 如果您已经[在自己的服务器上](index.html)配置了[Gitaly](index.html) + + ``` + gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN' + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your front door GitLab URL or an internal load balancer. + # Examples: 'https://example.gitlab.com', 'http://1.2.3.4' + gitlab_rails['internal_api_url'] = 'http://GITLAB_HOST' + ``` + +6. 通过在`/etc/gitlab/gitlab.rb`设置`git_data_dirs`来配置 Git 数据的存储位置. 每个 Gitaly 节点应具有唯一的存储名称(例如`gitaly-1` ). + + 与其为每个 Gitaly 节点唯一地配置`git_data_dirs`将每个 Gitaly 节点上所有 Gitaly 节点的配置都包括在内通常会更容易. 由于 Praefect `virtual_storages`配置将每个存储名称(例如`gitaly-1` )映射到特定节点,并且相应地路由了请求,因此支持此操作. 这意味着舰队中的每个 Gitaly 节点都可以共享相同的配置. + + ``` + # You can include the data dirs for all nodes in the same config, because + # Praefect will only route requests according to the addresses provided in the + # prior step. + git_data_dirs({ + "gitaly-1" => { + "path" => "/var/opt/gitlab/git-data" + }, + "gitaly-2" => { + "path" => "/var/opt/gitlab/git-data" + }, + "gitaly-3" => { + "path" => "/var/opt/gitlab/git-data" + } + }) + ``` + +7. 将更改保存到`/etc/gitlab/gitlab.rb`并[重新配置 Gitaly](../restart_gitlab.html#omnibus-gitlab-reconfigure) : + + ``` + gitlab-ctl reconfigure + ``` + +8. 为了确保 Gitaly [更新了其 Prometheus 监听地址](https://gitlab.com/gitlab-org/gitaly/-/issues/2734) ,请[重新启动 Gitaly](../restart_gitlab.html#omnibus-gitlab-restart) : + + ``` + gitlab-ctl restart gitaly + ``` + +**必须对每个 Gitaly 节点完成上述步骤!** + +配置完所有 Gitaly 节点后,您可以运行 Praefect 连接检查器以验证 Praefect 可以连接到 Praefect 配置中的所有 Gitaly 服务器. + +1. SSH into the **Praefect** node and run the Praefect connection checker: + + ``` + sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes + ``` + +### Load Balancer[](#load-balancer "Permalink") + +在高可用的 Gitaly 配置中,需要一个负载平衡器来将内部流量从 GitLab 应用程序路由到 Praefect 节点. 有关使用负载均衡器或进行确切配置的细节超出了 GitLab 文档的范围. + +我们希望,如果您要管理像 GitLab 这样的 HA 系统,那么您已经选择了负载均衡器. 一些示例包括[HAProxy](https://www.haproxy.org/) (开源), [Google 内部负载均衡器](https://cloud.google.com/load-balancing/docs/internal/) , [AWS Elastic 负载均衡器](https://aws.amazon.com/elasticloadbalancing/) ,F5 Big-IP LTM 和 Citrix Net Scaler. 本文档将概述您需要配置哪些端口和协议. + +| LB 端口 | 后端端口 | Protocol | +| --- | --- | --- | +| 2305 | 2305 | TCP | + +### GitLab[](#gitlab "Permalink") + +要完成本节,您将需要: + +* [Configured Praefect node](#praefect) +* [Configured Gitaly nodes](#gitaly) + +Praefect 集群需要作为存储位置公开给 GitLab 应用程序. 这是通过更新`git_data_dirs`完成的. + +应特别注意: + +* 本节中添加到`git_data_dirs`的存储名称必须与 Praefect 节点上`praefect['virtual_storages']`下的存储名称匹配. 这是在本指南的[Praefect](#praefect)部分中设置的. 本文档使用`storage-1`作为 Praefect 存储名称. + +1. SSH 进入**GitLab**节点并以 root 身份登录: + + ``` + sudo -i + ``` + +2. 配置`external_url`以便可以通过编辑`/etc/gitlab/gitlab.rb`通过适当的端点访问`/etc/gitlab/gitlab.rb` GitLab 提供文件: + + 您需要将`GITLAB_SERVER_URL`替换为当前 GitLab 实例所服务的实际外部 URL: + + ``` + external_url 'GITLAB_SERVER_URL' + ``` + +3. 禁用在 GitLab 主机上运行的默认 Gitaly 服务. 不需要它,因为 GitLab 将连接到配置的集群. + + **注意**如果现有数据存储在默认的 Gitaly 存储中,则应首先[迁移 Praefect 存储中的数据](#migrating-existing-repositories-to-praefect) . + + ``` + gitaly['enable'] = false + ``` + +4. 通过编辑`/etc/gitlab/gitlab.rb`将 Praefect 集群添加为存储位置. + + 您将需要更换: + + * 带有负载均衡器的 IP 地址或主机名的`LOAD_BALANCER_SERVER_ADDRESS` . + * `PRAEFECT_EXTERNAL_TOKEN`带有真正的秘密 + + ``` + git_data_dirs({ + "default" => { + "gitaly_address" => "tcp://LOAD_BALANCER_SERVER_ADDRESS:2305", + "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN' + } + }) + ``` + +5. 配置`gitlab_shell['secret_token']`以便通过编辑`/etc/gitlab/gitlab.rb`正确验证`git push`期间来自 Gitaly 节点的回调: + + 您将需要用真实的机密替换`GITLAB_SHELL_SECRET_TOKEN` . + + ``` + gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN' + ``` + +6. 通过编辑`/etc/gitlab/gitlab.rb`添加 Prometheus 监视设置. + + 您将需要更换: + + * `PRAEFECT_HOST`带有 Praefect 节点的 IP 地址或主机名 + * `GITALY_HOST` ,每个 Gitaly 节点的 IP 地址或主机名 + + ``` + prometheus['scrape_configs'] = [ + { + 'job_name' => 'praefect', + 'static_configs' => [ + 'targets' => [ + 'PRAEFECT_HOST:9652', # praefect-1 + 'PRAEFECT_HOST:9652', # praefect-2 + 'PRAEFECT_HOST:9652', # praefect-3 + ] + ] + }, + { + 'job_name' => 'praefect-gitaly', + 'static_configs' => [ + 'targets' => [ + 'GITALY_HOST:9236', # gitaly-1 + 'GITALY_HOST:9236', # gitaly-2 + 'GITALY_HOST:9236', # gitaly-3 + ] + ] + } + ] + ``` + +7. 将更改保存到`/etc/gitlab/gitlab.rb`并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) : + + ``` + gitlab-ctl reconfigure + ``` + +8. 验证每个`gitlab-shell`实例上的每个`gitlab-shell`都可以到达 GitLab. 在每个 Gitaly 实例上运行: + + ``` + /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml + ``` + +9. 验证 GitLab 是否可以达到 Praefect: + + ``` + gitlab-rake gitlab:gitaly:check + ``` + +10. 在**管理区域>设置>存储库>存储库**中检查 Praefect 存储已配置为存储新存储库. 按照本指南, `default`存储应具有权重 100 以存储所有新存储库. + +11. 通过创建一个新项目来验证一切正常. 选中"使用自述文件初始化存储库"框,以使存储库中包含已查看的内容. 如果项目已创建,并且您可以看到 README 文件,那么它将起作用! + +### Grafana[](#grafana "Permalink") + +Grafana 包含在 GitLab 中,可用于监视您的 Praefect 集群. 有关详细文档,请参见[Grafana 仪表板服务](https://docs.gitlab.com/omnibus/settings/grafana.html) . + +快速入门: + +1. SSH into the **GitLab** node and login as root: + + ``` + sudo -i + ``` + +2. 通过编辑`/etc/gitlab/gitlab.rb`启用 Grafana 登录表单. + + ``` + grafana['disable_login_form'] = false + ``` + +3. 将更改保存到`/etc/gitlab/gitlab.rb`并[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) : + + ``` + gitlab-ctl reconfigure + ``` + +4. 设置 Grafana 管理员密码. 此命令将提示您输入新密码: + + ``` + gitlab-ctl set-grafana-password + ``` + +5. 在您的 Web 浏览器中,在您的 GitLab 服务器上打开`/-/grafana` (例如`https://gitlab.example.com/-/grafana` ). + + 使用您设置的密码和用户名`admin`登录. + +6. 转到**浏览**并查询`gitlab_build_info`以验证您是否正在从所有计算机中获取指标. + +恭喜你! 您已经配置了可观察的高可用性 Praefect 集群. + +## Distributed reads[](#distributed-reads "Permalink") + +在[beta 版本的](https://about.gitlab.com/handbook/product/#alpha-beta-ga) GitLab 13.1 中引入,功能标志`gitaly_distributed_reads`设置为禁用. + +Praefect supports distribution of read operations across Gitaly nodes that are configured for the virtual node. + +为了进行[性能测试](https://gitlab.com/gitlab-org/quality/performance/-/issues/231) ,分布式读取当前处于[beta 状态](https://about.gitlab.com/handbook/product/#alpha-beta-ga) ,默认情况下处于禁用状态. 要启用分布式读取,必须在 Ruby 控制台中启用`gitaly_distributed_reads` [功能标志](../feature_flags.html) : + +``` +Feature.enable(:gitaly_distributed_reads) +``` + +如果启用,则所有带有`ACCESSOR`选项(如[GetBlob)的](https://gitlab.com/gitlab-org/gitaly/-/blob/v12.10.6/proto/blob.proto#L16) RPC 都将重定向到最新且运行状况良好的 Gitaly 节点. + +在这种情况下*,最新*意味着: + +* 没有为此节点安排任何复制操作. +* 最后的复制操作处于*完成*状态. + +如果没有这样的节点,或者在选择节点期间发生任何其他错误,那么将选择主节点来处理请求. + +要跟踪读取操作的分布,可以使用`gitaly_praefect_read_distribution` Prometheus 计数器度量. 它有两个标签: + +* `virtual_storage`. +* `storage`. + +它们反映了为此 Praefect 实例定义的配置. + +## Automatic failover and leader election[](#automatic-failover-and-leader-election "Permalink") + +Praefect 会定期检查每个后端 Gitaly 节点的运行状况. 如果发现当前主节点运行状况不佳,此信息可用于自动故障转移到新的主节点. + +* **PostgreSQL(推荐):**默认启用,等效于: `praefect['failover_election_strategy'] = sql` . 此配置选项将允许多个 Praefect 节点通过 PostgreSQL 数据库进行协调,以选择一个主要的 Gitaly 节点. 如果大多数 Praefect 节点在 10 秒内仍无法访问当前主节点,此配置将导致 Praefect 节点选择一个新的主节点,监视其运行状况,并选择一个新的主节点. +* **手动:**禁用自动故障转移. 可以在 Praefect 节点上的`/etc/gitlab/gitlab.rb`重新配置主节点. 通过将`primary = true`移至另一个 Gitaly 节点,将其修改为`praefect['virtual_storages']`字段. 在上述步骤中,将`gitaly-1`设置为主数据库. 在配置中需要`praefect['failover_enabled'] = false` . +* **内存:**通过在 Praefect 节点上的`/etc/gitlab/gitlab.rb`设置`praefect['failover_election_strategy'] = 'local'` `/etc/gitlab/gitlab.rb` . 如果对于当前的主后端 Gitaly 节点,足够数量的运行状况检查失败,则将选择新的主节点. **不要与多个 Praefect 节点一起使用!** 与多个 Praefect 节点一起使用可能会导致大脑分裂. + +将来我们可能会实施对 Consul 的支持以及云原生策略. + +## Primary Node Failure[](#primary-node-failure "Permalink") + +Praefect 通过将健康的辅助节点升级为新的主节点来从发生故障的主 Gitaly 节点中恢复. 为了最大程度地减少数据丢失,Praefect 会选择从主节点进行最少重复写入的辅助节点. 仍然会有一些未复制的写入,从而导致数据丢失. + +故障转移事件发生后,Praefect 会将虚拟存储切换为只读模式. 通过防止对新选举的主数据库进行新的可能冲突的写入,这可以简化数据恢复工作. 这使管理员可以尝试在允许新写入之前恢复丢失的数据. + +如果您更喜欢写可用性而不是一致性,则可以通过在`/etc/gitlab/gitlab.rb`设置`praefect['failover_read_only_after_failover'] = false`并[重新配置 Praefect](../restart_gitlab.html#omnibus-gitlab-reconfigure)来关闭此行为. + +### Checking for data loss[](#checking-for-data-loss "Permalink") + +Praefect `dataloss`子命令可通过检查未完成的复制作业来帮助识别丢失的写操作. 这对于确定故障转移后可能的数据丢失情况很有用. 此命令必须在 Praefect 节点上执行. + +``` +sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage ] +``` + +如果未指定虚拟存储,则将检查每个已配置的虚拟存储的数据丢失. + +``` +sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss +``` + +``` +Virtual storage: default + Current read-only primary: gitaly-2 + Previous write-enabled primary: gitaly-1 + Nodes with data loss from failing over from gitaly-1: + @hashed/2c/62/2c624232cdd221771294dfbb310aca000a0df6ac8b66b696d90ef06fdefb64a3.git: gitaly-0 + @hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.git: gitaly-0, gitaly-2 +``` + +当前,如果已直接从先前启用写操作的主数据库复制到该`dataloss`仅考虑该存储库为最新. 虽然从最新的辅助数据库进行协调可以恢复数据,但在数据丢失报告中不可见. 这是通过[Gitaly#2866](https://gitlab.com/gitlab-org/gitaly/-/issues/2866)进行的改进. + +**注意数据** `dataloss`仍处于 beta 状态,并且输出格式可能会更改. + +### Checking repository checksums[](#checking-repository-checksums "Permalink") + +要在所有 Gitaly 节点上检查项目的存储库校验和,请在主 GitLab 节点上运行[副本 Rake 任务](../raketasks/praefect.html#replica-checksums) . + +### Recovering lost writes[](#recovering-lost-writes "Permalink") + +Praefect `reconcile`子命令可用于恢复先前的主数据库恢复联机后丢失的写入. 仅当虚拟存储仍处于只读模式时才有可能. + +``` +sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual -reference -target -f +``` + +有关`reconcile`子命令的更多详细信息,请参阅" [后端节点恢复"](#backend-node-recovery)部分. + +### Enabling Writes[](#enabling-writes "Permalink") + +在启用写入之前,应该进行任何数据恢复尝试,以消除冲突写入的任何可能性. 可以使用 Praefect `enable-writes`子命令为写入重新启用虚拟存储. + +``` +sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml enable-writes -virtual-storage +``` + +## Backend Node Recovery[](#backend-node-recovery "Permalink") + +当 Praefect 后端节点发生故障并且不再能够复制更改时,后端节点将开始从主节点开始漂移. 如果该节点最终恢复,则需要将其与当前主节点协调. 主节点被视为分片状态的唯一真实来源. Praefect `reconcile`子命令允许在后端节点和当前主节点之间进行手动协调. + +Run the following command on the Praefect server after all placeholders (`` and ``) have been replaced: + +``` +sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual -target +``` + +* 将占位符``替换为包含要检查的后端节点存储的虚拟存储. +* 将占位符``替换为后端存储名称. + +该命令将返回与当前主数据库不一致的存储库列表. 这些不一致性中的每一个还将与随附的复制作业 ID 一起记录. + +## Migrating existing repositories to Praefect[](#migrating-existing-repositories-to-praefect "Permalink") + +如果您的 GitLab 实例已经有存储库,则不会自动迁移它们. + +可以使用[Repository API](../../api/projects.html#edit-project)从一个存储位置移动存储[库](../../api/projects.html#edit-project) : + +``` +curl --request PUT --header "PRIVATE-TOKEN: " --data "repository_storage=praefect" https://example.gitlab.com/api/v4/projects/123 +``` + +## Debugging Praefect[](#debugging-praefect "Permalink") + +如果收到错误,请检查`/var/log/gitlab/gitlab-rails/production.log` . + +以下是常见的错误和潜在原因: + +* 500 响应码 + * **ActionView :: Template :: Error(7:权限被拒绝)** + * `praefect['auth_token']`和`gitlab_rails['gitaly_token']`在 GitLab 服务器上不匹配. + * **无法保存项目.** **错误:7:权限被拒绝** + * GitLab 服务器上的`praefect['storage_nodes']`秘密令牌与一台或多台 Gitaly 服务器上的`gitaly['auth_token']`中的值不匹配. +* 503 响应码 + * **GRPC ::不可用(14:无法连接到所有地址)** + * GitLab 无法到达 Praefect. + * **GRPC ::不可用(14:所有 SubCon 都在 TransientFailure 中...)** + * Praefect 无法到达其一个或多个子 Gitaly 节点. 尝试运行 Praefect 连接检查器进行诊断. \ No newline at end of file diff --git a/docs/470.md b/docs/470.md new file mode 100644 index 0000000000000000000000000000000000000000..5810df2f3a5d2bc0ea8f702b042fb74cd12e61c1 --- /dev/null +++ b/docs/470.md @@ -0,0 +1,234 @@ +# Gitaly reference + +> 原文:[https://docs.gitlab.com/ee/administration/gitaly/reference.html](https://docs.gitlab.com/ee/administration/gitaly/reference.html) + +* [Format](#format) + * [Authentication](#authentication) + * [TLS](#tls) + * [Storage](#storage) + * [Git](#git) + * [`cat-file` cache](#cat-file-cache) + * [`gitaly-ruby`](#gitaly-ruby) + * [GitLab Shell](#gitlab-shell) + * [Prometheus](#prometheus) + * [Logging](#logging) +* [Concurrency](#concurrency) + +# Gitaly reference[](#gitaly-reference "Permalink") + +通过[TOML](https://github.com/toml-lang/toml)配置文件配置 Gitaly. 与源安装不同,在 Omnibus GitLab 中,您不会直接编辑此文件. + +配置文件作为参数传递给`gitaly`可执行文件. 通常由 Omnibus GitLab 或您的[init](https://en.wikipedia.org/wiki/Init)脚本完成. + +可以在 Gitaly 项目中找到[示例配置文件](https://gitlab.com/gitlab-org/gitaly/blob/master/config.toml.example) . + +## Format[](#format "Permalink") + +在顶层, `config.toml`定义下表中描述的项目. + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `socket_path` | string | 是(如果未设置`listen_addr` ) | Gitaly 应该打开 Unix 套接字的路径. | +| `listen_addr` | string | 是(如果未设置`socket_path` ) | Gitaly 侦听的 TCP 地址. | +| `tls_listen_addr` | string | no | TCP over TLS 地址供 Gitaly 侦听. | +| `bin_dir` | string | yes | 包含 Gitaly 可执行文件的目录. | +| `prometheus_listen_addr` | string | no | Prometheus 指标的 TCP 侦听地址. 如果未设置,则不会启动 Prometheus 侦听器. | + +例如: + +``` +socket_path = "/home/git/gitlab/tmp/sockets/private/gitaly.socket" +listen_addr = "localhost:9999" +tls_listen_addr = "localhost:8888" +bin_dir = "/home/git/gitaly" +prometheus_listen_addr = "localhost:9236" +``` + +### Authentication[](#authentication "Permalink") + +可以将 Gitaly 配置为拒绝标头中不包含特定承载令牌的请求. 这是通过 TCP 服务请求时要使用的一种安全措施: + +``` +[auth] +# A non-empty token enables authentication. +token = "the secret token" +``` + +当`config.toml`的令牌设置不存在或为空字符串时,将禁用身份验证. + +可以使用`transitioning`设置暂时禁用身份验证. 这使您可以监视所有客户端是否都在正确认证,而不会导致尚未正确配置的客户端的服务中断: + +``` +[auth] +token = "the secret token" +transitioning = true +``` + +**警告:**完成更改令牌设置后,切记禁用`transitioning` . + +所有身份验证尝试均以`gitaly_authentications_total`指标在 Prometheus 中进行计数. + +### TLS[](#tls "Permalink") + +Gitaly 支持 TLS 加密. 您将需要携带自己的证书,因为该证书不会自动提供. + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `certificate_path` | string | no | 证书的路径. | +| `key_path` | string | no | 密钥的路径. | + +``` +tls_listen_addr = "localhost:8888" + +[tls] +certificate_path = '/home/git/cert.cert' +key_path = '/home/git/key.pem' +``` + +在 Gitaly 中[了解](index.html#enable-tls-support)有关 TLS 的[更多](index.html#enable-tls-support)信息. + +### Storage[](#storage "Permalink") + +GitLab 存储库被分组到称为"存储"的目录中(例如`/home/git/repositories` ),其中包含由 GitLab 管理的裸存储库,其名称(例如`default` ). + +这些名称和路径也在 GitLab 的`gitlab.yml`配置文件中定义. 当你在同一台机器 GitLab,这是默认和推荐的配置上运行 Gitaly,在 Gitaly 的定义存储路径`config.toml`必须与在`gitlab.yml` . + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `storage` | array | yes | 一组存储分片. | +| `path` | string | yes | 存储分片的路径. | +| `name` | string | yes | 存储分片的名称. | + +例如: + +``` +[[storage]] +path = "/path/to/storage/repositories" +name = "my_shard" + +[[storage]] +path = "/path/to/other/repositories" +name = "other_storage" +``` + +### Git[](#git "Permalink") + +可以在配置文件的`[git]`部分中设置以下值. + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `bin_path` | string | no | Git 二进制文件的路径. 如果未设置,将使用`PATH`进行解析. | +| `catfile_cache_size` | integer | no | 缓存的[cat 文件进程的](#cat-file-cache)最大数量. 默认值为`100` . | + +#### `cat-file` cache[](#cat-file-cache "Permalink") + +许多 Gitaly RPC 需要从存储库中查找 Git 对象. 大多数时候,我们使用`git cat-file --batch`进程. 为了获得更好的性能,Gitaly 可以在 RPC 调用之间重用这些`git cat-file`过程. 先前使用的进程保留在[" Git cat-file 缓存"中](https://about.gitlab.com/blog/2019/07/08/git-performance-on-nfs/#enter-cat-file-cache) . 为了控制其使用多少系统资源,我们拥有可进入高速缓存的 cat 文件进程的最大数量. + +默认限制是 100 个`cat-file` ,它们构成了一对`git cat-file --batch`和`git cat-file --batch-check`进程. 如果您看到抱怨"打开的文件太多"或无法创建新进程的错误,则可以降低此限制. + +理想情况下,该数量应该足够大以处理正常流量. 如果提高该限制,则应在前后测量缓存命中率. 如果命中率没有提高,则上限可能不会产生有意义的变化. 这是一个 Prometheus 查询示例,用于查看命中率: + +``` +sum(rate(gitaly_catfile_cache_total{type="hit"}[5m])) / sum(rate(gitaly_catfile_cache_total{type=~"(hit)|(miss)"}[5m])) +``` + +### `gitaly-ruby`[](#gitaly-ruby "Permalink") + +一个 Gitaly 进程使用一个或多个`gitaly-ruby`帮助程序进程来执行在 Ruby 中而非 Go 中实现的 RPC. 配置文件的`[gitaly-ruby]`部分包含这些帮助程序的设置. + +已知这些进程有时会遭受内存泄漏. 当其内存超过`max_rss`限制时,Gitaly 将重新启动其`gitaly-ruby`帮助`max_rss` . + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `dir` | string | yes | 安装`gitaly-ruby`路径(需要引导该进程). | +| `max_rss` | integer | no | 触发`gitaly-ruby`重新启动的驻留集大小限制(以字节为单位). 默认值为`200000000` (200MB). | +| `graceful_restart_timeout` | string | no | 超出`max_rss`后,强制执行`gitaly-ruby`进程之前的`max_rss` . 默认值为`10m` (10 分钟). | +| `restart_delay` | string | no | 重新启动之前, `gitaly-ruby`内存必须保持高电平的时间. 默认值为`5m` (5 分钟). | +| `num_workers` | integer | no | Number of `gitaly-ruby` worker processes. Try increasing this number in case of `ResourceExhausted` errors. Default is `2`, minimum is `2`. | +| `linguist_languages_path` | string | no | 动态`languages.json` .json 发现的替代. 默认为空字符串(使用动态发现). | + +Example: + +``` +[gitaly-ruby] +dir = "/home/git/gitaly/ruby" +max_rss = 200000000 +graceful_restart_timeout = "10m" +restart_delay = "5m" +num_workers = 2 +``` + +### GitLab Shell[](#gitlab-shell "Permalink") + +出于历史原因, [GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell)包含 Git 挂钩,这些挂钩允许 GitLab 验证并响应 Git 推送. 由于 Gitaly 拥有 Git 推送,因此必须在 Gitaly 旁边安装 GitLab Shell. 将来会[简化](https://gitlab.com/gitlab-org/gitaly/-/issues/1226) . + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `dir` | string | yes | 安装 GitLab Shell 的目录. | + +Example: + +``` +[gitlab-shell] +dir = "/home/git/gitlab-shell" +``` + +### Prometheus[](#prometheus "Permalink") + +您可以选择配置 Gitaly 以记录 Prometheus 中 GRPC 方法调用的直方图延迟. + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `grpc_latency_buckets` | array | no | Prometheus 将每个观察值存储在一个存储桶中,这意味着您将获得延迟的近似值. 优化铲斗可更好地控制逼近精度. | + +Example: + +``` +prometheus_listen_addr = "localhost:9236" + +[prometheus] +grpc_latency_buckets = [0.001, 0.005, 0.025, 0.1, 0.5, 1.0, 10.0, 30.0, 60.0, 300.0, 1500.0] +``` + +### Logging[](#logging "Permalink") + +以下值在`[logging]`部分下的 Gitaly 中配置日志`[logging]` . + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `format` | string | no | 日志格式: `text`或`json` . 默认值: `text` . | +| `level` | string | no | 日志级别: `debug` , `info` , `warn` , `error` , `fatal`或`panic` . 默认值: `info` . | +| `sentry_dsn` | string | no | Sentry DSN 用于异常监视. | +| `sentry_environment` | string | no | [Sentry Environment](https://docs.sentry.io/enriching-error-data/environments/)用于异常监视. | +| `ruby_sentry_dsn` | string | no | Sentry DSN 用于`gitaly-ruby`异常监视. | + +While the main Gitaly application logs go to `stdout`, there are some extra log files that go to a configured directory, like the GitLab Shell logs. GitLab Shell does not support `panic` or `trace` level logs. `panic` will fall back to `error`, while `trace` will fall back to `debug`. Any other invalid log levels will default to `info`. + +Example: + +``` +[logging] +level = "warn" +dir = "/home/gitaly/logs" +format = "json" +sentry_dsn = "https://:@sentry.io/" +ruby_sentry_dsn = "https://:@sentry.io/" +``` + +## Concurrency[](#concurrency "Permalink") + +您可以调整每个 RPC 端点的`concurrency`性. + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `concurrency` | array | yes | RPC 端点数组. | +| `rpc` | string | no | RPC 端点的名称( `/gitaly.RepositoryService/GarbageCollect` ). | +| `max_per_repo` | integer | no | 每个存储库的每个 RPC 的并发性. | + +Example: + +``` +[[concurrency]] +rpc = "/gitaly.RepositoryService/GarbageCollect" +max_per_repo = 1 +``` \ No newline at end of file diff --git a/docs/471.md b/docs/471.md new file mode 100644 index 0000000000000000000000000000000000000000..67949d2e08b9e189bea1e0c1a4f06b6e1ce1a32d --- /dev/null +++ b/docs/471.md @@ -0,0 +1,15 @@ +# Monitoring GitLab + +> 原文:[https://docs.gitlab.com/ee/administration/monitoring/](https://docs.gitlab.com/ee/administration/monitoring/) + +# Monitoring GitLab[](#monitoring-gitlab "Permalink") + +探索我们的功能来监视您的 GitLab 实例: + +* [GitLab 自我监视](gitlab_self_monitoring_project/index.html) :GitLab 实例管理项目有助于监视 GitLab 实例并对警报采取措施. +* [性能监视](performance/index.html) :GitLab 性能监视可以测量您实例的各种统计信息. +* [Prometheus](prometheus/index.html) :Prometheus 是一项功能强大的时间序列监视服务,为监视 GitLab 和其他软件产品提供了灵活的平台. +* [GitHub 导入](github_imports.html) :使用各种 Prometheus 指标监控 GitLab [GitHub 导入](github_imports.html)器的运行状况和进度. +* [监视正常运行时间](../../user/admin_area/monitoring/health_check.html) :使用运行状况检查端点检查服务器状态. + * [IP 白名单](ip_whitelist.html) :配置 GitLab 以监视在探测时提供健康检查信息的端点. +* [`nginx_status`](https://docs.gitlab.com/omnibus/settings/nginx.html) :监视您的 NGINX 服务器状态 \ No newline at end of file diff --git a/docs/472.md b/docs/472.md new file mode 100644 index 0000000000000000000000000000000000000000..60802f2e96f5ca6ecc8eec9b8ab1f38e21b03f28 --- /dev/null +++ b/docs/472.md @@ -0,0 +1,302 @@ +# Monitoring GitLab with Prometheus + +> 原文:[https://docs.gitlab.com/ee/administration/monitoring/prometheus/](https://docs.gitlab.com/ee/administration/monitoring/prometheus/) + +* [Overview](#overview) +* [Configuring Prometheus](#configuring-prometheus) + * [Changing the port and address Prometheus listens on](#changing-the-port-and-address-prometheus-listens-on) + * [Adding custom scrape configurations](#adding-custom-scrape-configurations) + * [Using an external Prometheus server](#using-an-external-prometheus-server) +* [Viewing performance metrics](#viewing-performance-metrics) +* [Prometheus as a Grafana data source](#prometheus-as-a-grafana-data-source) +* [GitLab metrics](#gitlab-metrics) +* [Bundled software metrics](#bundled-software-metrics) + * [Node exporter](#node-exporter) + * [Redis exporter](#redis-exporter) + * [PostgreSQL exporter](#postgresql-exporter) + * [PgBouncer exporter](#pgbouncer-exporter) + * [Registry exporter](#registry-exporter) + * [GitLab exporter](#gitlab-exporter) +* [Configuring Prometheus to monitor Kubernetes](#configuring-prometheus-to-monitor-kubernetes) + +# Monitoring GitLab with Prometheus[](#monitoring-gitlab-with-prometheus "Permalink") + +> **Notes:** +> +> * 本页中列出的 Prometheus 和各种出口商都捆绑在 Omnibus GitLab 软件包中. 查看每个出口商的文档以了解添加的时间表. 对于源安装,您必须自己安装. 在后续版本中,将捕获其他的 GitLab 指标. +> * GitLab 9.0 默认情况下会启用 Prometheus 服务. +> * Prometheus 及其出口商不对用户进行身份验证,任何可以访问它们的人都可以使用. + +[Prometheus](https://s0prometheus0io.icopy.site)是一项功能强大的时间序列监视服务,为监视 GitLab 和其他软件产品提供了灵活的平台. GitLab 提供了 Prometheus 的开箱即用监视功能,可轻松访问 GitLab 服务的高质量时间序列监视. + +## Overview[](#overview "Permalink") + +Prometheus 的工作方式是定期连接到数据源,并通过[各种出口商](#bundled-software-metrics)收集其绩效指标. 要查看和使用监视数据,您可以[直接连接到 Prometheus](#viewing-performance-metrics)或使用仪表板工具(例如[Grafana)](https://grafana.com) . + +## Configuring Prometheus[](#configuring-prometheus "Permalink") + +**注意:**对于源安装,您必须自己安装和配置. + +从 GitLab 9.0 开始,Prometheus 及其出口商默认情况下处于打开状态. Prometheus 将以`gitlab-prometheus`用户身份运行,并监听`http://localhost:9090` . 默认情况下,只能从 GitLab 服务器本身访问 Prometheus. 除非单独禁用,否则每个出口商将自动设置为 Prometheus 的监视目标. + +要禁用 Prometheus 及其所有出口商以及将来添加的任何出口商,请执行以下操作: + +1. Edit `/etc/gitlab/gitlab.rb` +2. 添加或查找并取消注释以下行,确保将其设置为`false` : + + ``` + prometheus_monitoring['enable'] = false + ``` + +3. 保存文件并[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +### Changing the port and address Prometheus listens on[](#changing-the-port-and-address-prometheus-listens-on "Permalink") + +**注意:** [Omnibus GitLab 8.17 中](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/1261)添加了以下更改. 尽管可能,但不建议更改 Prometheus 监听的端口,因为这可能会影响 GitLab 服务器上运行的其他服务或与之冲突. 继续需要您自担风险. + +为了从 GitLab 服务器外部访问 Prometheus,您需要在`prometheus['listen_address']`设置 FQDN 或 IP. 更改 Prometheus 监听的地址/端口: + +1. Edit `/etc/gitlab/gitlab.rb` +2. 添加或查找并取消注释以下行: + + ``` + prometheus['listen_address'] = 'localhost:9090' + ``` + + 将`localhost:9090`替换为您希望 Prometheus 监听的地址或端口. 如果要允许除`localhost`以外的其他主机访问 Prometheus,请忽略该主机,或使用`0.0.0.0`允许公共访问: + + ``` + prometheus['listen_address'] = ':9090' + # or + prometheus['listen_address'] = '0.0.0.0:9090' + ``` + +3. 保存文件并[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效 + +### Adding custom scrape configurations[](#adding-custom-scrape-configurations "Permalink") + +您可以使用[Prometheus 刮擦目标配置](https://s0prometheus0io.icopy.site/docs/prometheus/latest/configuration/configuration/)语法在`/etc/gitlab/gitlab.rb`编辑`prometheus['scrape_configs']` , `/etc/gitlab/gitlab.rb`为 Omnibus GitLab 捆绑的 Prometheus 配置其他刮擦目标. + +这是刮取`http://1.1.1.1:8060/probe?param_a=test¶m_b=additional_test`的示例配置: + +``` +prometheus['scrape_configs'] = [ + { + 'job_name': 'custom-scrape', + 'metrics_path': '/probe', + 'params' => { + 'param_a' => ['test'], + 'param_b' => ['additional_test'] + }, + 'static_configs' => [ + 'targets' => ['1.1.1.1:8060'], + ], + }, +] +``` + +### Using an external Prometheus server[](#using-an-external-prometheus-server "Permalink") + +**注意:** Prometheus 和大多数导出器不支持身份验证. 我们不建议将它们公开在本地网络之外. + +需要进行一些配置更改,才能由外部 Prometheus 服务器监视 GitLab. 对于[具有多个节点的 GitLab 部署,](../../reference_architectures/index.html)建议使用外部服务器. + +要使用外部 Prometheus 服务器: + +1. Edit `/etc/gitlab/gitlab.rb`. +2. 禁用捆绑的 Prometheus: + + ``` + prometheus['enable'] = false + ``` + +3. 将每个捆绑服务的[导出器设置](#bundled-software-metrics)为侦听网络地址,例如: + + ``` + gitlab_exporter['listen_address'] = '0.0.0.0' + sidekiq['listen_address'] = '0.0.0.0' + gitlab_exporter['listen_port'] = '9168' + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + gitaly['prometheus_listen_addr'] = "0.0.0.0:9236" + gitlab_workhorse['prometheus_listen_addr'] = "0.0.0.0:9229" + ``` + +4. 如有必要,请使用[官方安装说明](https://s0prometheus0io.icopy.site/docs/prometheus/latest/installation/)安装并设置专用的 Prometheus 实例. +5. 将 Prometheus 服务器 IP 地址添加到[监视 IP 白名单](../ip_whitelist.html) . 例如: + + ``` + gitlab_rails['monitoring_whitelist'] = ['127.0.0.0/8', '192.168.0.1'] + ``` + +6. 在**所有** GitLab Rails(Puma / Unicorn,Sidekiq)服务器上,设置 Prometheus 服务器 IP 地址和监听端口. 例如: + + ``` + gitlab_rails['prometheus_address'] = '192.168.0.1:9090' + ``` + +7. 要抓取 NGINX 指标,您还需要配置 NGINX 以允许 Prometheus 服务器 IP. 例如: + + ``` + nginx['status']['options'] = { + "server_tokens" => "off", + "access_log" => "off", + "allow" => "192.168.0.1", + "deny" => "all", + } + ``` + +8. [重新配置 GitLab](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以应用更改. +9. 编辑 Prometheus 服务器的配置文件. +10. 将每个节点的导出器添加到 Prometheus 服务器的[抓取目标配置中](https://s0prometheus0io.icopy.site/docs/prometheus/latest/configuration/configuration/) . 例如,使用`static_configs`的样本片段: + + ``` + scrape_configs: + - job_name: nginx + static_configs: + - targets: + - 1.1.1.1:8060 + - job_name: redis + static_configs: + - targets: + - 1.1.1.1:9121 + - job_name: postgres + static_configs: + - targets: + - 1.1.1.1:9187 + - job_name: node + static_configs: + - targets: + - 1.1.1.1:9100 + - job_name: gitlab-workhorse + static_configs: + - targets: + - 1.1.1.1:9229 + - job_name: gitlab-rails + metrics_path: "/-/metrics" + static_configs: + - targets: + - 1.1.1.1:8080 + - job_name: gitlab-sidekiq + static_configs: + - targets: + - 1.1.1.1:8082 + - job_name: gitlab_exporter_database + metrics_path: "/database" + static_configs: + - targets: + - 1.1.1.1:9168 + - job_name: gitlab_exporter_sidekiq + metrics_path: "/sidekiq" + static_configs: + - targets: + - 1.1.1.1:9168 + - job_name: gitlab_exporter_process + metrics_path: "/process" + static_configs: + - targets: + - 1.1.1.1:9168 + - job_name: gitaly + static_configs: + - targets: + - 1.1.1.1:9236 + ``` + +11. 重新加载 Prometheus 服务器. + +## Viewing performance metrics[](#viewing-performance-metrics "Permalink") + +您可以访问`http://localhost:9090` ,以获取 Prometheus 默认提供的仪表板. + +> **注意:**如果在您的 GitLab 实例上启用了 SSL,由于[HSTS,](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security)如果使用相同的 FQDN,则可能无法在与 GitLab 相同的浏览器上访问 Prometheus. 我们计划[通过 GitLab 提供访问](https://gitlab.com/gitlab-org/multi-user-prometheus) ,但是在此期间,有一些解决方法:使用单独的 FQDN,使用服务器 IP,使用单独的 Prometheus 浏览器,重置 HSTS 或使用[NGINX 代理](https://docs.gitlab.com/omnibus/settings/nginx.html) . + +Prometheus 收集的性能数据可以在 Prometheus 控制台中直接查看,也可以通过兼容的仪表板工具查看. Prometheus 界面提供了一种[灵活的查询语言](https://s0prometheus0io.icopy.site/docs/prometheus/latest/querying/basics/) ,可与收集的数据一起使用,您可以在其中可视化输出. 要获得功能更全面的仪表板,可以使用 Grafana 并已[对 Prometheus 进行了官方支持](https://s0prometheus0io.icopy.site/docs/visualization/grafana/) . + +普罗米修斯样本查询: + +* **可用内存百分比:** `((node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) or ((node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes) / node_memory_MemTotal_bytes)) * 100` +* **CPU 使用率百分比:** `1 - avg without (mode,cpu) (rate(node_cpu_seconds_total{mode="idle"}[5m]))` +* **传输的数据:** `rate(node_network_transmit_bytes_total{device!="lo"}[5m])` +* **收到的数据:** `rate(node_network_receive_bytes_total{device!="lo"}[5m])` + +## Prometheus as a Grafana data source[](#prometheus-as-a-grafana-data-source "Permalink") + +Grafana 允许您导入 Prometheus 性能指标作为数据源,并将指标呈现为图形和仪表板,这有助于可视化. + +To add a Prometheus dashboard for a single server GitLab setup: + +1. 在 Grafana 中创建一个新的数据源. +2. 命名您的数据源(如 GitLab). +3. 在类型下拉框中选择`Prometheus` . +4. 将您的 Prometheus 侦听地址添加为 URL,并设置对`Browser`访问权限. +5. 将 HTTP 方法设置为`GET` . +6. 保存并测试您的配置以验证其是否有效. + +## GitLab metrics[](#gitlab-metrics "Permalink") + +在 GitLab 9.3 中引入. + +GitLab 监视其自身的内部服务指标,并使其在`/-/metrics`端点可用. 与其他导出器不同,此终结点需要身份验证,因为它可以在与用户流量相同的 URL 和端口上使用. + +[➔ Read more about the GitLab Metrics.](gitlab_metrics.html) + +## Bundled software metrics[](#bundled-software-metrics "Permalink") + +Omnibus GitLab 中捆绑的许多 GitLab 依赖项都已预先配置为导出 Prometheus 指标. + +### Node exporter[](#node-exporter "Permalink") + +节点导出器允许您测量各种机器资源,例如内存,磁盘和 CPU 利用率. + +[Read more about the node exporter](node_exporter.html). + +### Redis exporter[](#redis-exporter "Permalink") + +Redis 导出器允许您测量各种 Redis 指标. + +[Read more about the Redis exporter](redis_exporter.html). + +### PostgreSQL exporter[](#postgresql-exporter "Permalink") + +PostgreSQL 导出器允许您测量各种 PostgreSQL 指标. + +[Read more about the PostgreSQL exporter](postgres_exporter.html). + +### PgBouncer exporter[](#pgbouncer-exporter "Permalink") + +PgBouncer 导出器允许您测量各种 PgBouncer 指标. + +[Read more about the PgBouncer exporter](pgbouncer_exporter.html). + +### Registry exporter[](#registry-exporter "Permalink") + +注册表导出器允许您测量各种注册表指标. + +[Read more about the Registry exporter](registry_exporter.html). + +### GitLab exporter[](#gitlab-exporter "Permalink") + +GitLab 导出器允许您测量从 Redis 和数据库中提取的各种 GitLab 指标. + +[Read more about the GitLab exporter](gitlab_exporter.html). + +## Configuring Prometheus to monitor Kubernetes[](#configuring-prometheus-to-monitor-kubernetes "Permalink") + +版本历史 + +* 在 GitLab 9.0 中引入. +* 在 GitLab 9.4 中引入了 Pod 监控. + +如果您的 GitLab 服务器在 Kubernetes 中运行,则 Prometheus 将从群集中的节点和带[注释的](https://s0prometheus0io.icopy.site/docs/prometheus/latest/configuration/configuration/) Pod 收集指标,包括每个容器上的性能数据. 如果您的 CI / CD 环境在同一群集中运行,这将特别有用,因为您可以使用[Prometheus 项目集成](../../../user/project/integrations/prometheus.html)来监视它们. + +要禁用对 Kubernetes 的监视: + +1. Edit `/etc/gitlab/gitlab.rb`. +2. 添加(或查找并取消注释)以下行并将其设置为`false` : + + ``` + prometheus['monitor_kubernetes'] = false + ``` + +3. 保存文件并[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. \ No newline at end of file diff --git a/docs/473.md b/docs/473.md new file mode 100644 index 0000000000000000000000000000000000000000..7c8d4242b190b9d3963e8af2c838c7f1b2f15c99 --- /dev/null +++ b/docs/473.md @@ -0,0 +1,60 @@ +# Performance Bar + +> 原文:[https://docs.gitlab.com/ee/administration/monitoring/performance/performance_bar.html](https://docs.gitlab.com/ee/administration/monitoring/performance/performance_bar.html) + +* [Request warnings](#request-warnings) +* [Enable the Performance Bar via the Admin panel](#enable-the-performance-bar-via-the-admin-panel) +* [Keyboard shortcut for the Performance Bar](#keyboard-shortcut-for-the-performance-bar) + +# Performance Bar[](#performance-bar "Permalink") + +您可以显示 GitLab 性能栏以查看页面性能的统计信息. 激活后,其外观如下: + +[![Performance Bar](img/a87cd8265a25e22c9a715c6372ff047a.png)](img/performance_bar.png) + +从左到右,它显示: + +* **当前主机** :服务于该页面的当前主机. +* **数据库查询** :花费的时间(毫秒)和数据库查询的总数,以`00ms / 00pg`的格式显示. 单击以显示更多信息的模式窗口: [![使用性能栏进行 SQL 分析](img/631b8ad9816cfdd87ba106377c86c7a4.png)](img/performance_bar_sql_queries.png) +* **Gitaly 通话** :所花费的时间(以毫秒为单位)和[Gitaly](../../gitaly/index.html)通话的总数. 单击以显示更多信息的模式窗口: [![使用性能栏进行 Gitaly 分析](img/aeccb5cc55fc430d8645e67086388300.png)](img/performance_bar_gitaly_calls.png) +* **坚固通话** :花费的时间(以毫秒为单位)和[坚固](../../high_availability/nfs.html#improving-nfs-performance-with-gitlab)通话的总数. 单击以显示更多信息的模式窗口: [![使用性能栏进行坚固的性能分析](img/35fbd0a23d3b20913cb4490a3957d8b3.png)](img/performance_bar_rugged_calls.png) +* **Redis 呼叫** :花费的时间(以毫秒为单位)和 Redis 呼叫的总数. 单击以显示更多信息的模式窗口: [![使用性能栏进行 Redis 分析](img/b6696ad0d59c74a9a3974493085915f9.png)](img/performance_bar_redis_calls.png) +* **Elasticsearch 调用** :花费的时间(以毫秒为单位)和 Elasticsearch 调用的总数. 单击以显示更多信息的模式窗口. +* 页面的**加载时间** :如果您的浏览器支持加载时间(Chromium 和 Chrome),则以毫秒为单位的多个值(以斜杠分隔). 单击以显示更多信息的模式窗口. 值从左到右: + * **后端** :加载基本页面所需的时间. + * [**First Contentful Paint**](https://s0web0dev.icopy.site/first-contentful-paint/) :直到用户看到某些东西为止的时间. + * [**DomContentLoaded**](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/measure-crp)事件. + * 页面加载**的请求总数** : [![使用性能栏的前端请求](img/ca66569a1f77e8f2d208a42e0fee1794.png)](img/performance_bar_frontend.png) +* **跟踪** :如果集成了 Jaeger,则**Trace**链接到 Jaeger 跟踪页面,其中包含当前请求的`correlation_id` . +* **+** :用于将请求的详细信息添加到性能栏的链接. 可以通过其完整 URL(已认证为当前用户)或其`X-Request-Id`标头的值来添加`X-Request-Id` . +* **下载** :下载用于生成 Performance Bar 报告的原始 JSON 的链接. +* **请求选择器** :显示在性能栏右侧的选择框,通过该选择框,您可以查看当前页面打开时发出的所有请求的这些指标. 每个唯一 URL 仅捕获前两个请求. + +## Request warnings[](#request-warnings "Permalink") + +超出预定义限制的请求显示警告 指标旁边的图标和说明. 在此示例中,Gitaly 通话时间超过了阈值: + +[![Gitaly call duration exceeded threshold](img/dd6b38427a8d14832104464d1603afed.png)](img/performance_bar_gitaly_threshold.png) + +如果当前页面上的任何请求生成警告,则警告图标将显示在" **请求"选择器**旁边: + +[![Request selector showing two requests with warnings](img/874270632cfad28b99af65b5d0275fee.png)](img/performance_bar_request_selector_warning.png) + +带有警告的**请求**在**请求选择器中**的路径后显示`(!)` : + +[![Request selector showing dropdown](img/02f288cad0ff70d293c035d6dc434f34.png)](img/performance_bar_request_selector_warning_expanded.png) + +## Enable the Performance Bar via the Admin panel[](#enable-the-performance-bar-via-the-admin-panel "Permalink") + +默认情况下,GitLab 性能栏是禁用的. 要为给定的组启用它: + +1. 以具有管理员[权限](../../../user/permissions.html)的用户身份登录. +2. 在菜单栏中,单击 **管理区域**图标. +3. 导航 **设置>指标和分析** ( `admin/application_settings/metrics_and_profiling` ),然后展开" **分析-性能栏** "部分. +4. Click **启用对性能栏的访问**. +5. 在**允许的组**字段中,提供允许访问 GitLab 性能栏的组的完整路径. +6. Click **保存更改**. + +## Keyboard shortcut for the Performance Bar[](#keyboard-shortcut-for-the-performance-bar "Permalink") + +启用 GitLab 性能栏后,按[`p` + `b`键盘快捷键](../../../user/shortcuts.html)将其显示,然后再次将其隐藏. \ No newline at end of file diff --git a/docs/474.md b/docs/474.md new file mode 100644 index 0000000000000000000000000000000000000000..cf859f1e9398a108b02c45de3aa075384ad8313b --- /dev/null +++ b/docs/474.md @@ -0,0 +1,53 @@ +# Usage statistics + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/settings/usage_statistics.html](https://docs.gitlab.com/ee/user/admin_area/settings/usage_statistics.html) + +* [Network configuration](#network-configuration) +* [Version Check](#version-check-core-only) + * [Request flow example](#request-flow-example) +* [Usage Ping](#usage-ping-core-only) +* [Instance statistics visibility](#instance-statistics-visibility-core-only) + +# Usage statistics[](#usage-statistics-core-only "Permalink") + +GitLab Inc.将定期收集有关您的实例的信息,以执行各种操作. + +所有统计信息均已退出. 您可以在**管理区域>设置>指标和配置文件** **使用情况统计信息中**启用/禁用它们. + +## Network configuration[](#network-configuration "Permalink") + +允许从您的 GitLab 实例到 IP 地址`104.196.17.203:443`网络流量将使用情况统计信息发送到 GitLab Inc. + +如果您的 GitLab 实例位于代理之后,请设置适当的[代理配置变量](https://docs.gitlab.com/omnibus/settings/environment-variables.html) . + +## Version Check[](#version-check-core-only "Permalink") + +如果启用,版本检查将通过状态通知您是否有新版本以及其重要性. 这显示在所有登录用户的帮助页面(即`/help` )和管理页面上. 状态为: + +* 绿色:您正在运行最新版本的 GitLab. +* 橙色:提供了 GitLab 的更新版本. +* 红色:您正在运行的 GitLab 版本容易受到攻击. 您应该尽快安装具有安全修复程序的最新版本. + +[![Orange version check example](img/aec2abca2644938484258f63a3df71d2.png)](img/update-available.png) + +GitLab Inc.收集您实例的版本和主机名(通过 HTTP 引用),作为版本检查的一部分. 没有收集其他信息. + +除其他事项外,该信息还用于标识需要将补丁反向移植到哪些版本,以确保活动的 GitLab 实例保持安全. + +如果禁用版本检查,则不会收集此信息. 在**管理区域>设置>度量标准和性能分析>使用情况统计信息中**启用或禁用版本检查. + +### Request flow example[](#request-flow-example "Permalink") + +以下示例显示了自我管理的 GitLab 实例与 GitLab 版本应用程序之间的基本请求/响应流: + +sequenceDiagram 参与者 GitLab 实例参与者版本应用程序 GitLab 实例->>版本应用程序:是否有版本更新? 循环版本检查版本应用程序->>版本应用程序:记录版本信息结束版本应用程序->> GitLab 实例:响应(PNG / SVG) + +## Usage Ping[](#usage-ping-core-only "Permalink") + +See [Usage Ping guide](../../../development/telemetry/usage_ping.html). + +## Instance statistics visibility[](#instance-statistics-visibility-core-only "Permalink") + +启用使用情况 ping 后,GitLab 将从其他实例收集数据,并能够向用户显示您实例的[使用情况统计信息](../../instance_statistics/index.html) . + +要使其仅对管理员可见,请进入**管理区域>设置>指标和分析** ,展开**使用情况统计信息** ,然后将**实例统计信息可见性**选项设置为**仅管理员** . \ No newline at end of file diff --git a/docs/475.md b/docs/475.md new file mode 100644 index 0000000000000000000000000000000000000000..1e44b8713c0b0bfec6bfdceead1797cf2473ed97 --- /dev/null +++ b/docs/475.md @@ -0,0 +1,524 @@ +# Object Storage + +> 原文:[https://docs.gitlab.com/ee/administration/object_storage.html](https://docs.gitlab.com/ee/administration/object_storage.html) + +* [Options](#options) +* [Configuration guides](#configuration-guides) + * [Consolidated object storage configuration](#consolidated-object-storage-configuration) + * [Common parameters](#common-parameters) + * [Connection settings](#connection-settings) + * [S3-compatible connection settings](#s3-compatible-connection-settings) + * [Oracle Cloud S3 connection settings](#oracle-cloud-s3-connection-settings) + * [Google Cloud Storage (GCS)](#google-cloud-storage-gcs) + * [Google example (consolidated form)](#google-example-consolidated-form) + * [OpenStack-compatible connection settings](#openstack-compatible-connection-settings) + * [Rackspace Cloud Files](#rackspace-cloud-files) + * [Object-specific configuration](#object-specific-configuration) + * [Selectively disabling object storage](#selectively-disabling-object-storage) + * [Transition to consolidated form](#transition-to-consolidated-form) +* [Storage-specific configuration](#storage-specific-configuration) + * [Other alternatives to filesystem storage](#other-alternatives-to-filesystem-storage) +* [Warnings, limitations, and known issues](#warnings-limitations-and-known-issues) + * [Use separate buckets](#use-separate-buckets) + * [S3 API compatibility issues](#s3-api-compatibility-issues) + * [GitLab Pages requires NFS](#gitlab-pages-requires-nfs) + * [Incremental logging is required for CI to use object storage](#incremental-logging-is-required-for-ci-to-use-object-storage) + * [Proxy Download](#proxy-download) + * [ETag mismatch](#etag-mismatch) + * [Using Amazon instance profiles](#using-amazon-instance-profiles) + * [Encrypted S3 buckets](#encrypted-s3-buckets) + * [Disabling the feature](#disabling-the-feature) + * [IAM Permissions](#iam-permissions) + +# Object Storage[](#object-storage "Permalink") + +GitLab 支持使用对象存储服务来保存多种类型的数据. 建议在 NFS 上使用它,并且通常在较大的设置中更好,因为对象存储通常具有更高的性能,可靠性和可伸缩性. + +## Options[](#options "Permalink") + +GitLab 已在许多对象存储提供程序上进行了测试: + +* [Amazon S3](https://aws.amazon.com/s3/) +* [Google Cloud Storage](https://cloud.google.com/storage) +* [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces) +* [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm) +* [Openstack Swift](https://s0docs0openstack0org.icopy.site/swift/latest/s3_compat.html) +* 来自各种存储供应商的本地硬件和设备. +* MinIO. 我们在 Helm Chart 文档中提供[了有关部署此配置的指南](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) . + +## Configuration guides[](#configuration-guides "Permalink") + +在 GitLab 中有两种指定对象存储配置的方式: + +* [合并形式](#consolidated-object-storage-configuration) :所有支持的对象类型都共享一个凭证. +* [Storage-specific form](#storage-specific-configuration): Every object defines its own object storage [connection and configuration](#connection-settings). + +有关差异以及从一种形式过渡到另一种形式的更多信息,请参见[过渡到合并形式](#transition-to-consolidated-form) . + +### Consolidated object storage configuration[](#consolidated-object-storage-configuration "Permalink") + +在[GitLab 13.2 中](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4368)引入. + +使用合并对象存储配置具有许多优点: + +* 由于连接详细信息在对象类型之间共享,因此可以简化您的 GitLab 配置. +* 它允许使用[加密的 S3 存储桶](#encrypted-s3-buckets) . +* It [uploads files to S3 with proper `Content-MD5` headers](https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/222). + +**注意:**由于必须使用[直接上载模式](../development/uploads.html#direct-upload) ,目前仅支持与 AWS S3 兼容的提供商和 Google. 此模式不支持后台上传. 我们建议直接上传模式,因为它不需要共享文件夹,并且[此设置可能成为默认设置](https://gitlab.com/gitlab-org/gitlab/-/issues/27331) .**注意:**合并对象存储配置不能用于备份或 Mattermost. 有关[完整列表,](#storage-specific-configuration)请参见[完整表](#storage-specific-configuration) . + +通过为具有多个存储桶的对象存储指定单个凭证,可以将大多数类型的对象(例如 CI 工件,LFS 文件,上传附件等)保存在对象存储中. [每种类型必须使用不同的存储桶](#use-separate-buckets) . + +当合并形式为: + +* 通过与 S3 兼容的对象存储一起使用,Workhorse 使用其内部的 S3 客户端上载文件. +* 不与 S3 兼容的对象存储一起使用,Workhorse 退回到使用预签名的 URL. + +有关更多详细信息,请参见" [ETag 不匹配错误](#etag-mismatch) "部分. + +**在所有安装中;** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下行,以替换所需的值: + + ``` + # Consolidated object storage configuration + gitlab_rails['object_store']['enabled'] = true + gitlab_rails['object_store']['proxy_download'] = true + gitlab_rails['object_store']['connection'] = { + 'provider' => 'AWS', + 'region' => '', + 'aws_access_key_id' => '', + 'aws_secret_access_key' => '' + } + gitlab_rails['object_store']['objects']['artifacts']['bucket'] = '' + gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = '' + gitlab_rails['object_store']['objects']['lfs']['bucket'] = '' + gitlab_rails['object_store']['objects']['uploads']['bucket'] = '' + gitlab_rails['object_store']['objects']['packages']['bucket'] = '' + gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = '' + gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = '' + ``` + + 对于 GitLab 9.4 或更高版本,如果您使用的是 AWS IAM 配置文件,请确保省略 AWS 访问密钥和秘密访问密钥/值对. 例如: + + ``` + gitlab_rails['object_store_connection'] = { + 'provider' => 'AWS', + 'region' => '', + 'use_iam_profile' => true + } + ``` + +2. 保存文件并[重新配置 GitLab,](restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**在源安装中:** + +1. 编辑`/home/git/gitlab/config/gitlab.yml`并添加或修改以下行: + + ``` + object_store: + enabled: true + proxy_download: true + connection: + provider: AWS + aws_access_key_id: + aws_secret_access_key: + region: + objects: + artifacts: + bucket: + external_diffs: + bucket: + lfs: + bucket: + uploads: + bucket: + packages: + bucket: + dependency_proxy: + bucket: + terraform_state: + bucket: + ``` + +2. 编辑`/home/git/gitlab-workhorse/config.toml`并添加或修改以下行: + + ``` + [object_storage] + enabled = true + provider = "AWS" + + [object_storage.s3] + aws_access_key_id = "" + aws_secret_access_key = "" + ``` + +3. 保存文件并[重新启动 GitLab,](restart_gitlab.html#installations-from-source)以使更改生效. + +#### Common parameters[](#common-parameters "Permalink") + +在统一配置中, `object_store`部分定义了一组公共参数. 在这里,我们使用源安装中的 YAML,因为它更容易看到继承: + +``` + object_store: + enabled: true + proxy_download: true + connection: + provider: AWS + aws_access_key_id: + aws_secret_access_key: + objects: + ... +``` + +Omnibus 配置直接映射到此: + +``` +gitlab_rails['object_store']['enabled'] = true +gitlab_rails['object_store']['proxy_download'] = true +gitlab_rails['object_store']['connection'] = { + 'provider' => 'AWS', + 'aws_access_key_id' => ' '' +} +``` + +| Setting | Description | +| --- | --- | +| `enabled` | 启用/禁用对象存储 | +| `proxy_download` | 设置为`true`以[启用代理服务的所有文件](#proxy-download) . Option 可以减少出口流量,因为这允许客户端直接从远程存储下载而不是代理所有数据 | +| `connection` | 下述各种连接选项 | +| `objects` | [Object-specific configuration](#object-specific-configuration) | + +### Connection settings[](#connection-settings "Permalink") + +合并配置表单和特定于存储的配置表单都必须配置连接. 以下各节介绍可在`connection`设置中使用的参数. + +#### S3-compatible connection settings[](#s3-compatible-connection-settings "Permalink") + +连接设置与[fog-aws](https://github.com/fog/fog-aws)提供的设置匹配: + +| Setting | Description | Default | +| --- | --- | --- | +| `provider` | 始终适用于兼容主机的`AWS` | `AWS` | +| `aws_access_key_id` | AWS 凭证或兼容 |   | +| `aws_secret_access_key` | AWS 凭证或兼容 |   | +| `aws_signature_version` | 要使用的 AWS 签名版本. `2`或`4`是有效选项. 数字海洋空间和其他提供商可能需要`2` . | `4` | +| `enable_signature_v4_streaming` | 设置为`true`以启用具有[AWS v4 签名的](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html) HTTP 分块传输. Oracle Cloud S3 需要将此设置为`false` . | `true` | +| `region` | AWS 区域 | us-east-1 | +| `host` | 不使用 AWS 时与 S3 兼容的主机,例如`localhost`或`storage.example.com` . 假定使用 HTTPS 和端口 443. | `s3.amazonaws.com` | +| `endpoint` | 在配置 S3 兼容服务(例如[MinIO)时](https://min.io) ,可以通过输入 URL(例如`http://127.0.0.1:9000` . 这优先于`host` . | (optional) | +| `path_style` | 设置为`true`以使用`host/bucket_name/object`样式路径而不是`bucket_name.host/object` . 对于 AWS S3,保留为`false` . | `false` | +| `use_iam_profile` | Set to `true` to use IAM profile instead of access keys | `false` | + +#### Oracle Cloud S3 connection settings[](#oracle-cloud-s3-connection-settings "Permalink") + +请注意,Oracle Cloud S3 必须确保使用以下设置: + +| Setting | Value | +| --- | --- | +| `enable_signature_v4_streaming` | `false` | +| `path_style` | `true` | + +如果将`enable_signature_v4_streaming`设置为`true` ,那么您可能会在`production.log`看到以下错误: + +``` +STREAMING-AWS4-HMAC-SHA256-PAYLOAD is not supported +``` + +#### Google Cloud Storage (GCS)[](#google-cloud-storage-gcs "Permalink") + +这是 GCS 的有效连接参数: + +| Setting | Description | example | +| --- | --- | --- | +| `provider` | 提供者名称 | `Google` | +| `google_project` | GCP 项目名称 | `gcp-project-12345` | +| `google_client_email` | 服务帐户的电子邮件地址 | `foo@gcp-project-12345.iam.gserviceaccount.com` | +| `google_json_key_location` | JSON 密钥路径 | `/path/to/gcp-project-12345-abcde.json` | + +**注意:**服务帐户必须具有访问存储桶的权限. [看更多](https://cloud.google.com/storage/docs/authentication) + +##### Google example (consolidated form)[](#google-example-consolidated-form "Permalink") + +对于 Omnibus 安装,这是`connection`设置的示例: + +``` +gitlab_rails['object_store']['connection'] = { + 'provider' => 'Google', + 'google_project' => '', + 'google_client_email' => '', + 'google_json_key_location' => '' +} +``` + +#### OpenStack-compatible connection settings[](#openstack-compatible-connection-settings "Permalink") + +**注意**这与统一对象存储表单不兼容. 仅特定于存储的表单支持 OpenStack Swift. 如果要使用合并表格,请参阅[S3 设置](#s3-compatible-connection-settings) . + +尽管 OpenStack Swift 提供了 S3 兼容性,但某些用户可能希望使用[Swift API](https://s0docs0openstack0org.icopy.site/swift/latest/api/object_api_v1_overview.html) . 这是以下由[swift-openstack](https://github.com/fog/fog-openstack)提供的 Swift API 的有效连接设置: + +| Setting | Description | Default | +| --- | --- | --- | +| `provider` | 始终使用`OpenStack`兼容主机 | `OpenStack` | +| `openstack_username` | OpenStack 用户名 |   | +| `openstack_api_key` | OpenStack API key |   | +| `openstack_temp_url_key` | 用于生成临时 URL 的 OpenStack 密钥 |   | +| `openstack_auth_url` | OpenStack 身份验证端点 |   | +| `openstack_region` | OpenStack 区域 |   | +| `openstack_tenant` | OpenStack 租户 ID |   | + +#### Rackspace Cloud Files[](#rackspace-cloud-files "Permalink") + +**注意**这与统一对象存储表单不兼容. 仅特定于存储的表单支持 Rackspace Cloud. + +这是[fog-rackspace](https://github.com/fog/fog-rackspace/)提供的 Rackspace Cloud 的有效连接参数: + +| Setting | Description | example | +| --- | --- | --- | +| `provider` | 提供者名称 | `Rackspace` | +| `rackspace_username` | 可访问容器的 Rackspace 帐户的用户名 | `joe.smith` | +| `rackspace_api_key` | 可访问容器的 Rackspace 帐户的 API 密钥 | `ABC123DEF456ABC123DEF456ABC123DE` | +| `rackspace_region` | 要使用的 Rackspace 存储区域,来自[服务访问端点列表的](https://developer.rackspace.com/docs/cloud-files/v1/general-api-info/service-access/)三个字母代码 | `iad` | +| `rackspace_temp_url_key` | 您在 Rackspace API 中为临时 URL 设置的私钥. [在这里](https://developer.rackspace.com/docs/cloud-files/v1/use-cases/public-access-to-your-cloud-files-account/#tempurl)阅读更多 | `ABC123DEF456ABC123DEF456ABC123DE` | + +**注意:**无论容器启用还是禁用了公共访问,Fog 都会使用 TempURL 方法来授予对 LFS 对象的访问权限. 如果您在引用使用`temp-url-key`实例化存储的日志中看到错误,请确保已在 Rackspace API 和`gitlab.rb`正确设置了密钥. 您可以通过将带有令牌标头的 GET 请求发送到服务访问端点 URL 并比较返回的标头的输出,来验证 Rackspace 密钥的设置值. + +### Object-specific configuration[](#object-specific-configuration "Permalink") + +以下 YAML 显示了`object_store`部分如何定义特定于对象的配置块,以及如何覆盖`enabled`和`proxy_download`标志. `bucket`是每种类型中唯一需要的参数: + +``` + object_store: + connection: + ... + objects: + artifacts: + bucket: artifacts + proxy_download: false + external_diffs: + bucket: external-diffs + lfs: + bucket: lfs-objects + uploads: + bucket: uploads + packages: + bucket: packages + dependency_proxy: + enabled: false + bucket: dependency_proxy + terraform_state: + bucket: terraform +``` + +这映射到此 Omnibus GitLab 配置: + +``` +gitlab_rails['object_store']['objects']['artifacts']['bucket'] = 'artifacts' +gitlab_rails['object_store']['objects']['artifacts']['proxy_download'] = false +gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = 'external-diffs' +gitlab_rails['object_store']['objects']['lfs']['bucket'] = 'lfs-objects' +gitlab_rails['object_store']['objects']['uploads']['bucket'] = 'uploads' +gitlab_rails['object_store']['objects']['packages']['bucket'] = 'packages' +gitlab_rails['object_store']['objects']['dependency_proxy']['enabled'] = false +gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = 'dependency-proxy' +gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = 'terraform-state' +``` + +这是可以使用的有效`objects`的列表: + +| Type | Description | +| --- | --- | +| `artifacts` | [CI artifacts](job_artifacts.html) | +| `external_diffs` | [Merge request diffs](merge_request_diffs.html) | +| `uploads` | [User uploads](uploads.html) | +| `lfs` | [Git Large File Storage objects](lfs/index.html) | +| `packages` | [Project packages (e.g. PyPI, Maven, NuGet, etc.)](packages/index.html) | +| `dependency_proxy` | [GitLab Dependency Proxy](packages/dependency_proxy.html) | +| `terraform_state` | [Terraform state files](terraform_state.html) | + +在每种对象类型中,可以定义三个参数: + +| Setting | Required? | Description | +| --- | --- | --- | +| `bucket` | Yes | 对象存储的存储桶名称. | +| `enabled` | No | 覆盖通用参数 | +| `proxy_download` | No | 覆盖通用参数 | + +#### Selectively disabling object storage[](#selectively-disabling-object-storage "Permalink") + +如上所示,可以通过将`enabled`标志设置为`false`来禁用特定类型的对象存储. 例如,要禁用 CI 工件的对象存储: + +``` +gitlab_rails['object_store']['objects']['artifacts']['enabled'] = false +``` + +如果功能完全禁用,则不需要存储桶. 例如,如果使用此设置禁用了 CI 构件,则不需要存储桶: + +``` +gitlab_rails['artifacts_enabled'] = false +``` + +### Transition to consolidated form[](#transition-to-consolidated-form "Permalink") + +在 GitLab 13.2 之前: + +* 所有类型的对象(例如 CI / CD 工件,LFS 文件,上载附件等)的对象存储配置都必须独立配置. +* 对于每种类型,必须复制对象存储连接参数,例如密码和端点 URL. + +例如,Omnibus GitLab 安装可能具有以下配置: + +``` +# Original object storage configuration +gitlab_rails['artifacts_object_store_enabled'] = true +gitlab_rails['artifacts_object_store_direct_upload'] = true +gitlab_rails['artifacts_object_store_proxy_download'] = true +gitlab_rails['artifacts_object_store_remote_directory'] = 'artifacts' +gitlab_rails['artifacts_object_store_connection'] = { 'provider' => 'AWS', 'aws_access_key_id' => 'access_key', 'aws_secret_access_key' => 'secret' } +gitlab_rails['uploads_object_store_enabled'] = true +gitlab_rails['uploads_object_store_direct_upload'] = true +gitlab_rails['uploads_object_store_proxy_download'] = true +gitlab_rails['uploads_object_store_remote_directory'] = 'uploads' +gitlab_rails['uploads_object_store_connection'] = { 'provider' => 'AWS', 'aws_access_key_id' => 'access_key', 'aws_secret_access_key' => 'secret' } +``` + +尽管这样做提供了灵活性,但它使得 GitLab 可以跨不同的云提供商存储对象,但同时也带来了额外的复杂性和不必要的冗余. 由于 GitLab Rails 和 Workhorse 组件都需要访问对象存储,因此合并后的表单避免了过多的凭据重复. + +**注意** **仅**当省略原始表单中的所有行时, **才**使用合并对象存储配置. 要移至合并的表单,请除去原始配置(例如, `artifacts_object_store_enabled` , `uploads_object_store_connection`等). + +## Storage-specific configuration[](#storage-specific-configuration "Permalink") + +有关在 GitLab 13.1 和更早版本中配置对象存储的信息,或对于统一配置表单不支持的存储类型的信息,请参阅以下指南: + +| 对象存储类型 | 支持统一配置吗? | +| --- | --- | +| [Backups](../raketasks/backup_restore.html#uploading-backups-to-a-remote-cloud-storage) | No | +| [Job artifacts](job_artifacts.html#using-object-storage) and [incremental logging](job_logs.html#new-incremental-logging-architecture) | Yes | +| [LFS objects](lfs/index.html#storing-lfs-objects-in-remote-object-storage) | Yes | +| [Uploads](uploads.html#using-object-storage-core-only) | Yes | +| [容器注册表](packages/container_registry.html#container-registry-storage-driver) (可选功能) | No | +| [Merge request diffs](merge_request_diffs.html#using-object-storage) | Yes | +| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage) | No | +| [软件包](packages/index.html#using-object-storage) (可选功能) | Yes | +| [依赖代理](packages/dependency_proxy.html#using-object-storage) (可选功能) | Yes | +| [假名生成器](pseudonymizer.html#configuration) (可选功能) | No | +| [Autoscale Runner 缓存](https://docs.gitlab.com/runner/configuration/autoscale.html) (可选以提高性能) | No | +| [Terraform state files](terraform_state.html#using-object-storage-core-only) | Yes | + +### Other alternatives to filesystem storage[](#other-alternatives-to-filesystem-storage "Permalink") + +如果您正在努力[扩展](reference_architectures/index.html) GitLab 实施,或增加容错能力和冗余性,则可能正在考虑消除对块或网络文件系统的依赖. 请参阅以下指南,并[注意 Pages 需要磁盘存储](#gitlab-pages-requires-nfs) : + +1. 确保[`git`用户主目录](https://docs.gitlab.com/omnibus/settings/configuration.html)位于本地磁盘上. +2. 配置[SSH 密钥的数据库查找,](operations/fast_ssh_key_lookup.html)以消除对共享的`authorized_keys`文件的需要. + +## Warnings, limitations, and known issues[](#warnings-limitations-and-known-issues "Permalink") + +### Use separate buckets[](#use-separate-buckets "Permalink") + +对于 GitLab,建议为每种数据类型使用单独的存储桶. + +我们的配置的局限性是对象存储的每次使用都是单独配置的. [我们有一个需要改进的问题](https://gitlab.com/gitlab-org/gitlab/-/issues/23345) ,轻松地将一个存储桶与单独的文件夹一起使用可能会带来一个改进. + +使用同一个存储桶至少有一个特定的问题:当使用 Helm 图表部署 GitLab 时,除非使用单独的存储桶,否则从备份还原[将无法正常工作](https://docs.gitlab.com/charts/advanced/external-object-storage/) . + +使用单个存储桶的风险之一是,如果您的组织将来决定将 GitLab 迁移到 Helm 部署. GitLab 可以运行,但是直到组织对备份起作用的关键要求之前,备份的情况可能无法实现. + +### S3 API compatibility issues[](#s3-api-compatibility-issues "Permalink") + +并非所有 S3 提供程序[都](../raketasks/backup_restore.html#other-s3-providers)与 GitLab 使用的 Fog 库[完全兼容](../raketasks/backup_restore.html#other-s3-providers) . 症状包括`production.log`的错误: + +``` +411 Length Required +``` + +### GitLab Pages requires NFS[](#gitlab-pages-requires-nfs "Permalink") + +如果您要添加更多的 GitLab 服务器以进行[缩放或容错,](reference_architectures/index.html)并且您的要求之一是[GitLab 页面,](../user/project/pages/index.html)则当前需要 NFS. 有[工作正在进行中](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)去除这种依赖性. 将来,GitLab 页面可能会使用[对象存储](https://gitlab.com/gitlab-org/gitlab/-/issues/208135) . + +对磁盘存储的依赖性还阻止了使用[GitLab Helm 图表](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/37)部署 Pages. + +### Incremental logging is required for CI to use object storage[](#incremental-logging-is-required-for-ci-to-use-object-storage "Permalink") + +如果将 GitLab 配置为将对象存储用于 CI 日志和工件,则[还必须启用增量日志记录](job_artifacts.html#using-object-storage) . + +### Proxy Download[](#proxy-download "Permalink") + +对象存储的许多使用情况都允许将客户端流量重定向到对象存储后端,例如当 Git 客户端通过 LFS 请求大文件时或在下载 CI 工件和日志时. + +When the files are stored on local block storage or NFS, GitLab has to act as a proxy. This is not the default behavior with object storage. + +`proxy_download`设置控制此行为:默认设置通常为`false` . 在每个用例的文档中对此进行验证. 将其设置为`true`以便 GitLab 代理文件. + +当不代理文件时,GitLab 将返回[HTTP 302 重定向,该重定向带有预先签名的有时间限制的对象存储 URL](https://gitlab.com/gitlab-org/gitlab/-/issues/32117#note_218532298) . 这可能会导致以下一些问题: + +* 如果 GitLab 使用非安全的 HTTP 访问对象存储,则客户端可能会生成`https->http`降级错误,并拒绝处理重定向. 解决方案是让 GitLab 使用 HTTPS. 例如,LFS 将产生此错误: + + ``` + LFS: lfsapi/client: refusing insecure redirect, https->http + ``` + +* 客户端将需要信任颁发对象存储证书的证书颁发机构,或者可能返回常见的 TLS 错误,例如: + + ``` + x509: certificate signed by unknown authority + ``` + +* 客户端将需要网络访问对象存储. 如果没有此访问权限,则可能导致的错误包括: + + ``` + Received status code 403 from server: Forbidden + ``` + +[软件包存储库文档中](packages/index.html#using-object-storage)特别注明了获取" `403 Forbidden`响应",这是某些构建工具的工作方式的副作用. + +### ETag mismatch[](#etag-mismatch "Permalink") + +使用默认的 GitLab 设置,某些对象存储后端(例如[MinIO](https://gitlab.com/gitlab-org/gitlab/-/issues/23188)和[Alibaba)](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564)可能会生成`ETag mismatch`错误. + +如果您在 Amazon Web Services S3 中看到此 ETag 不匹配错误,则可能是由于[存储桶上的加密设置](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTCommonResponseHeaders.html)所致. 要解决此问题,您有两种选择: + +* [Use the consolidated object configuration](#consolidated-object-storage-configuration). +* [Use Amazon instance profiles](#using-amazon-instance-profiles). + +对于 MinIO,建议使用第一个选项. 否则, [MinIO](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564#note_244497658)的[解决方法](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564#note_244497658)是在服务器上使用`--compat`参数. + +在未启用统一对象存储配置或实例配置文件的情况下,GitLab Workhorse 将使用没有为它们计算出`Content-MD5` HTTP 标头的预签名 URL 将文件上传到 S3\. 为了确保数据没有损坏,Workhorse 检查发送的数据的 MD5 哈希值是否等于从 S3 服务器返回的 ETag 标头. 启用加密后,情况并非如此,这将导致 Workhorse 在上传期间报告`ETag mismatch`错误. + +通过整合的对象配置和实例配置文件,Workhorse 具有 S3 凭据,因此可以计算`Content-MD5`标头. 这样就无需比较从 S3 服务器返回的 ETag 标头. + +### Using Amazon instance profiles[](#using-amazon-instance-profiles "Permalink") + +可以将 GitLab 配置为使用 IAM 角色来设置[Amazon 实例配置文件](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html) ,而不是在对象存储配置中提供 AWS 访问和秘密密钥. 使用此功能时,每次访问 S3 存储桶时,GitLab 都会获取临时凭证,因此配置中不需要硬编码的值. + +#### Encrypted S3 buckets[](#encrypted-s3-buckets "Permalink") + +版本历史 + +* 在[GitLab 13.1](https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/466)中仅针对实例配置文件引入. +* 使用[整合对象存储配置](#consolidated-object-storage-configuration)时,在[GitLab 13.2 中](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34460)引入了用于静态证书的功能. + +使用实例概要文件或统一对象配置进行配置时,GitLab Workhorse 可以将文件正确上载到[默认情况下启用 SSE-S3 或 SSE-KMS 加密的](https://docs.aws.amazon.com/kms/latest/developerguide/services-s3.html) S3 存储桶. 请注意, [尚不支持](https://gitlab.com/gitlab-org/gitlab/-/issues/226006)客户主密钥(CMK)和 SSE-C 加密, [因为这需要向 GitLab 配置提供密钥](https://gitlab.com/gitlab-org/gitlab/-/issues/226006) . + +##### Disabling the feature[](#disabling-the-feature "Permalink") + +当[`use_iam_profile`配置选项](#iam-permissions)设置为`true`时,默认情况下启用 Workhorse S3 客户端. + +可以使用`:use_workhorse_s3_client`功能标记禁用该功能. 要禁用该功能,请要求具有[Rails 控制台访问权限](feature_flags.html#how-to-enable-and-disable-features-behind-flags)的 GitLab 管理员运行以下命令: + +``` +Feature.disable(:use_workhorse_s3_client) +``` + +#### IAM Permissions[](#iam-permissions "Permalink") + +设置实例配置文件: + +1. 创建具有必要权限的 Amazon Identity Access and Management(IAM)角色. 以下示例是名为`test-bucket`的 S3 存储桶的角色: + + ``` + { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:AbortMultipartUpload", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::test-bucket/*" } ] } + ``` + +2. [将此角色附加](https://aws.amazon.com/premiumsupport/knowledge-center/attach-replace-ec2-instance-profile/)到托管您的 GitLab 实例的 EC2 实例. +3. 通过`use_iam_profile`配置选项配置 GitLab 以使用它. \ No newline at end of file diff --git a/docs/476.md b/docs/476.md new file mode 100644 index 0000000000000000000000000000000000000000..67b4b03c31ea541e7d196661d8b3f5ba04b346d6 --- /dev/null +++ b/docs/476.md @@ -0,0 +1,17 @@ +# Performing Operations in GitLab + +> 原文:[https://docs.gitlab.com/ee/administration/operations/](https://docs.gitlab.com/ee/administration/operations/) + +# Performing Operations in GitLab[](#performing-operations-in-gitlab "Permalink") + +保持您的 GitLab 实例正常运行. + +* [清理 Redis 会话](cleaning_up_redis_sessions.html) :在 GitLab 7.3 之前,用户会话不会自动从 Redis 过期. 如果从 GitLab 7.3 之前开始就一直在运行大型的 GitLab 服务器(成千上万的用户),我们建议在升级到 GitLab 7.3 之后清理陈旧的会话以压缩 Redis 数据库. +* [移动存储库](moving_repositories.html) :将 GitLab 管理的所有存储[库](moving_repositories.html)移动到另一个文件系统或另一个服务器. +* [Sidekiq MemoryKiller](sidekiq_memory_killer.html) :配置 Sidekiq MemoryKiller 以重新启动 Sidekiq. +* [多个 Sidekiq 进程](extra_sidekiq_processes.html) :配置多个 Sidekiq 进程以确保某些队列始终具有专用的工作程序,而不管需要处理的作业数量如何. +* [美洲狮](puma.html) :了解美洲狮和美洲狮杀手. +* [独角兽](unicorn.html) :了解独角兽和独角兽工人杀手. +* [通过对 GitLab 数据库进行快速的索引查找来授权 SSH 用户](fast_ssh_key_lookup.html) ,和/或通过[完全放弃 SSH 证书而完全放弃存储在 GitLab 上的用户 SSH 密钥](ssh_certificates.html) ,可以加快 SSH 操作. +* [文件系统性能基准测试](filesystem_benchmarking.html) :文件系统性能可能会对 GitLab 性能产生重大影响,尤其是对于读取或写入 Git 存储库的操作. 这些信息将有助于根据已知的好坏系统对基准文件系统的性能进行基准测试. +* [ChatOps 脚本](https://gitlab.com/gitlab-com/chatops) :GitLab.com 基础架构团队使用此存储库来存储常见的 ChatOps 脚本,以用于对 GitLab.com 的生产实例进行故障排除和维护. 这些脚本可能对各种规模的 GitLab 实例的管理员有用. \ No newline at end of file diff --git a/docs/477.md b/docs/477.md new file mode 100644 index 0000000000000000000000000000000000000000..49dab05071ab70feff32c062514d55d8c9d1c9c7 --- /dev/null +++ b/docs/477.md @@ -0,0 +1,42 @@ +# Cleaning up stale Redis sessions + +> 原文:[https://docs.gitlab.com/ee/administration/operations/cleaning_up_redis_sessions.html](https://docs.gitlab.com/ee/administration/operations/cleaning_up_redis_sessions.html) + +# Cleaning up stale Redis sessions[](#cleaning-up-stale-redis-sessions "Permalink") + +从 6.2 版开始,GitLab 将 Web 用户会话存储为 Redis 中的键值对. 在 GitLab 7.3 之前,用户会话不会自动从 Redis 终止. 如果从 GitLab 7.3 之前开始就一直在运行大型的 GitLab 服务器(成千上万的用户),我们建议在升级到 GitLab 7.3 之后清理陈旧的会话以压缩 Redis 数据库. 您还可以在仍运行 GitLab 7.2 或更早版本的情况下执行清理,但是在这种情况下,清理后新的陈旧会话将再次开始建立. + +在 7.3.0 之前的 GitLab 版本中,Redis 中的会话密钥是 16 字节的十六进制值,例如'976aa289e2189b17d7ef525a6702ace9'. 从 GitLab 7.3.0 开始,键的前缀为`session:gitlab:`因此它们看起来像`session:gitlab:976aa289e2189b17d7ef525a6702ace9` . 下面我们描述如何删除旧格式的密钥. + +**注意:**如果您使用了" [配置文件文档"中](https://gitlab.com/gitlab-org/gitlab/blob/master/config/README.md)概述的高级 Redis 设置,则必须根据您的配置设置修改以下说明. + +首先,我们定义具有适当 Redis 连接详细信息的 shell 函数. + +``` +rcli() { + # This example works for Omnibus installations of GitLab 7.3 or newer. For an + # installation from source you will have to change the socket path and the + # path to redis-cli. + sudo /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.shared_state.socket "$@" +} + +# test the new shell function; the response should be PONG +rcli ping +``` + +现在,我们进行搜索以查看是否有旧格式的会话密钥供我们清理. + +``` +# returns the number of old-format session keys in Redis +rcli keys '*' | grep '^[a-f0-9]\{32\}$' | wc -l +``` + +如果数字大于零,则可以使 Redis 的密钥失效. 如果数字为零,则没有任何清理内容. + +``` +# Tell Redis to expire each matched key after 600 seconds. +rcli keys '*' | grep '^[a-f0-9]\{32\}$' | awk '{ print "expire", $0, 600 }' | rcli +# This will print '(integer) 1' for each key that gets expired. +``` + +在接下来的 15 分钟内(10 分钟的到期时间加上 5 分钟的 Redis 后台保存间隔),您的 Redis 数据库将被压缩. 如果您仍在使用 GitLab 7.2,则在 10 分钟的有效期内未在 GitLab 中四处点击的用户将退出 GitLab. \ No newline at end of file diff --git a/docs/478.md b/docs/478.md new file mode 100644 index 0000000000000000000000000000000000000000..acadc967af9c393462fe87c3e9ef1dfdb9a9e14f --- /dev/null +++ b/docs/478.md @@ -0,0 +1,172 @@ +# Fast lookup of authorized SSH keys in the database + +> 原文:[https://docs.gitlab.com/ee/administration/operations/fast_ssh_key_lookup.html](https://docs.gitlab.com/ee/administration/operations/fast_ssh_key_lookup.html) + +* [Fast lookup is required for Geo](#fast-lookup-is-required-for-geo-premium) +* [Setting up fast lookup via GitLab Shell](#setting-up-fast-lookup-via-gitlab-shell) +* [How to go back to using the `authorized_keys` file](#how-to-go-back-to-using-the-authorized_keys-file) +* [Compiling a custom version of OpenSSH for CentOS 6](#compiling-a-custom-version-of-openssh-for-centos-6) +* [SELinux support and limitations](#selinux-support-and-limitations) + +# Fast lookup of authorized SSH keys in the database[](#fast-lookup-of-authorized-ssh-keys-in-the-database "Permalink") + +版本历史 + +* 在[GitLab Starter](https://about.gitlab.com/pricing/) 9.3 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/1631) . +* [在](https://gitlab.com/gitlab-org/gitlab/-/issues/3953) GitLab 社区版 10.4 中[可用](https://gitlab.com/gitlab-org/gitlab/-/issues/3953) . + +**注意:**本文档介绍了`authorized_keys`文件的替代品. 对于普通(非部署密钥)用户,请考虑使用[SSH 证书](ssh_certificates.html) . 它们甚至更快,但不是临时替代品. + +随着用户数量的增加,常规的 SSH 操作变得缓慢,这是因为 OpenSSH 通过线性搜索来搜索授权用户的密钥. 在最坏的情况下,例如,当用户无权访问 GitLab 时,OpenSSH 将扫描整个文件以搜索密钥. 这会花费大量时间和磁盘 I / O,这将延迟用户尝试推送或拉到存储库的时间. 更糟糕的是,如果用户频繁添加或删除密钥,则操作系统可能无法缓存`authorized_keys`文件,这将导致磁盘被重复访问. + +GitLab Shell 通过提供一种通过 GitLab 数据库中的快速索引查找来授权 SSH 用户的方法来解决此问题. 本页介绍如何启用快速查找授权的 SSH 密钥. + +> **警告:**由于`AuthorizedKeysCommand`必须能够接受指纹,因此需要 OpenSSH 6.9+版本. 这些说明将中断使用较旧版本的 OpenSSH 的安装,例如截至 2017 年 9 月的 CentOS 6 附带的安装.如果要将此功能用于 CentOS 6,请遵循[有关如何构建和安装自定义 OpenSSH 软件包的说明](#compiling-a-custom-version-of-openssh-for-centos-6) . + +## Fast lookup is required for Geo[](#fast-lookup-is-required-for-geo-premium "Permalink") + +默认情况下,GitLab 管理一个`authorized_keys`文件,其中包含允许访问 GitLab 的用户的所有公共 SSH 密钥. 但是,为了维护单个事实来源,需要将[Geo](../geo/replication/index.html)配置为通过数据库查找执行 SSH 指纹查找. + +作为[设置 Geo 的](../geo/replication/index.html#setup-instructions)一部分,您将需要对主节点和辅助节点都遵循以下概述的步骤,但是请注意,只需在主节点上取消选中`Write to "authorized keys" file`复选框,因为它将被选中.如果数据库复制正在工作,则会自动在辅助服务器上反映出来. + +## Setting up fast lookup via GitLab Shell[](#setting-up-fast-lookup-via-gitlab-shell "Permalink") + +GitLab Shell 提供了一种通过对 GitLab 数据库进行快速索引查找来授权 SSH 用户的方法. GitLab Shell 使用 SSH 密钥的指纹来检查用户是否有权访问 GitLab. + +将以下内容添加到您的`sshd_config`文件中. 通常位于`/etc/ssh/sshd_config` ,但如果使用 Omnibus Docker,它将为`/assets/sshd_config` : + +``` +Match User git # Apply the AuthorizedKeysCommands to the git user only + AuthorizedKeysCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-keys-check git %u %k + AuthorizedKeysCommandUser git +Match all # End match, settings apply to all users again +``` + +重新加载 OpenSSH: + +``` +# Debian or Ubuntu installations +sudo service ssh reload + +# CentOS installations +sudo service sshd reload +``` + +通过注释掉您在`authorized_keys`中的用户密钥(以`#`开头以对其进行注释),并尝试拉出存储库来确认 SSH 是否正常工作. + +A successful pull would mean that GitLab was able to find the key in the database, since it is not present in the file anymore. + +**注意:**对于 Omnibus Docker,默认情况下在 GitLab 11.11 及更高版本中设置了`AuthorizedKeysCommand` .**注意:**对于从源安装,该命令位于`/home/git/gitlab-shell/bin/gitlab-shell-authorized-keys-check`是否遵循[从源安装的](../../install/installation.html#install-gitlab-shell)说明. 您可能要考虑在其他地方创建包装脚本,因为此命令需要由`root`拥有,而不能由 group 或其他用户写入. 您也可以考虑根据需要更改此命令的所有权,但这可能需要在`gitlab-shell`升级期间临时更改所有权.**注意:**在确认 SSH 可以正常工作之前,请不要禁用写操作,因为该文件很快就会过时. + +In the case of lookup failures (which are common), the `authorized_keys` file will still be scanned. So Git SSH performance will still be slow for many users as long as a large file exists. + +您可以通过取消选中 GitLab 安装的`Write to "authorized_keys" file` **管理区域">"设置">"网络">"性能优化** `Write to "authorized_keys" file`中的`Write to "authorized_keys" file`来禁用对`authorized_keys`文件的更多写入. + +[![Write to authorized keys setting](img/f9144e03cf945bcf549c131e2816298f.png)](img/write_to_authorized_keys_setting.png) + +再次,通过在 UI 中删除用户的 SSH 密钥,添加一个新的 SSH 密钥,然后尝试提取存储库来确认 SSH 是否正常工作. + +然后,您可以备份和删除您的`authorized_keys`文件以获得最佳性能. 当前用户的密钥已经存在于数据库中,因此无需迁移或要求用户重新添加其密钥. + +## How to go back to using the `authorized_keys` file[](#how-to-go-back-to-using-the-authorized_keys-file "Permalink") + +这是一个简短的概述. 请参阅以上说明以获取更多上下文. + +1. [Rebuild the `authorized_keys` file](../raketasks/maintenance.html#rebuild-authorized_keys-file) +2. 启用对"应用程序设置"中的`authorized_keys`文件的写入 +3. 如果使用的是 Omnibus Docker,请从`/etc/ssh/sshd_config`或`/assets/sshd_config`删除`AuthorizedKeysCommand`行. +4. Reload `sshd`: `sudo service sshd reload` +5. 删除`/opt/gitlab-shell/authorized_keys`文件 + +## Compiling a custom version of OpenSSH for CentOS 6[](#compiling-a-custom-version-of-openssh-for-centos-6 "Permalink") + +对于 Ubuntu 16.04 用户而言,无需构建自定义版本的 OpenSSH,因为 Ubuntu 16.04 随 OpenSSH 7.2 一起提供. + +CentOS 7.4 用户也不需要,因为该版本随 OpenSSH 7.4 一起提供. 如果您使用的是 CentOS 7.0-7.3,我们强烈建议您升级到 CentOS 7.4,而不要遵循此过程. 这应该和运行`yum update`一样简单. + +CentOS 6 用户必须构建自己的 OpenSSH 软件包才能通过数据库启用 SSH 查找. 以下说明可用于构建 OpenSSH 7.5: + +1. 首先,下载软件包并安装所需的软件包: + + ``` + sudo su - + cd /tmp + curl --remote-name https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-7.5p1.tar.gz + tar xzvf openssh-7.5p1.tar.gz + yum install rpm-build gcc make wget openssl-devel krb5-devel pam-devel libX11-devel xmkmf libXt-devel + ``` + +2. 通过将文件复制到正确的位置来准备构建: + + ``` + mkdir -p /root/rpmbuild/{SOURCES,SPECS} + cp ./openssh-7.5p1/contrib/redhat/openssh.spec /root/rpmbuild/SPECS/ + cp openssh-7.5p1.tar.gz /root/rpmbuild/SOURCES/ + cd /root/rpmbuild/SPECS + ``` + +3. 接下来,正确设置规格设置: + + ``` + sed -i -e "s/%define no_gnome_askpass 0/%define no_gnome_askpass 1/g" openssh.spec + sed -i -e "s/%define no_x11_askpass 0/%define no_x11_askpass 1/g" openssh.spec + sed -i -e "s/BuildPreReq/BuildRequires/g" openssh.spec + ``` + +4. 建立 RPM: + + ``` + rpmbuild -bb openssh.spec + ``` + +5. 确保已构建 RPM: + + ``` + ls -al /root/rpmbuild/RPMS/x86_64/ + ``` + + 您应该看到以下内容: + + ``` + total 1324 + drwxr-xr-x. 2 root root 4096 Jun 20 19:37 . + drwxr-xr-x. 3 root root 19 Jun 20 19:37 .. + -rw-r--r--. 1 root root 470828 Jun 20 19:37 openssh-7.5p1-1.x86_64.rpm + -rw-r--r--. 1 root root 490716 Jun 20 19:37 openssh-clients-7.5p1-1.x86_64.rpm + -rw-r--r--. 1 root root 17020 Jun 20 19:37 openssh-debuginfo-7.5p1-1.x86_64.rpm + -rw-r--r--. 1 root root 367516 Jun 20 19:37 openssh-server-7.5p1-1.x86_64.rpm + ``` + +6. 安装软件包. OpenSSH 软件包将用其自己的版本替换`/etc/pam.d/sshd` ,这可能会阻止用户登录,因此请确保在安装后备份并还原了该文件: + + ``` + timestamp=$(date +%s) + cp /etc/pam.d/sshd pam-ssh-conf-$timestamp + rpm -Uvh /root/rpmbuild/RPMS/x86_64/*.rpm + yes | cp pam-ssh-conf-$timestamp /etc/pam.d/sshd + ``` + +7. 验证安装的版本. 在另一个窗口中,尝试登录到服务器: + + ``` + ssh -v + ``` + + 您应该看到以下一行:" debug1:远程协议版本 2.0,远程软件版本 OpenSSH_7.5" + + 如果没有,则可能需要重新启动`sshd` (例如`systemctl restart sshd.service` ). + +8. *重要!* 退出之前,请打开与服务器的新 SSH 会话,以确保一切正常! 如果您需要降级,只需安装较旧的软件包即可: + + ``` + # Only run this if you run into a problem logging in + yum downgrade openssh-server openssh openssh-clients + ``` + +## SELinux support and limitations[](#selinux-support-and-limitations "Permalink") + +在 GitLab 10.5 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/2855) . + +GitLab 支持[SELinux 的](https://en.wikipedia.org/wiki/Security-Enhanced_Linux) `authorized_keys`数据库查询. + +由于 SELinux 策略是静态的,因此 GitLab 目前不支持更改内部 Unicorn 端口的功能. 管理员必须为环境创建一个特殊的`.te`文件,因为它不是动态生成的. \ No newline at end of file diff --git a/docs/479.md b/docs/479.md new file mode 100644 index 0000000000000000000000000000000000000000..f9439a95d94965a8fe8d15eb64f32733f12b7d8e --- /dev/null +++ b/docs/479.md @@ -0,0 +1,102 @@ +# Filesystem Performance Benchmarking + +> 原文:[https://docs.gitlab.com/ee/administration/operations/filesystem_benchmarking.html](https://docs.gitlab.com/ee/administration/operations/filesystem_benchmarking.html) + +* [Executing benchmarks](#executing-benchmarks) + * [Benchmarking with `fio`](#benchmarking-with-fio) + * [Simple benchmarking](#simple-benchmarking) + +# Filesystem Performance Benchmarking[](#filesystem-performance-benchmarking "Permalink") + +Filesystem performance has a big impact on overall GitLab performance, especially for actions that read or write to Git repositories. This information will help benchmark filesystem performance against known good and bad real-world systems. + +通常,在谈论文件系统性能时,最大的顾虑是网络文件系统(NFS). 但是,即使某些本地磁盘也可能具有缓慢的 I / O. 此页面上的信息可用于两种情况. + +## Executing benchmarks[](#executing-benchmarks "Permalink") + +### Benchmarking with `fio`[](#benchmarking-with-fio "Permalink") + +我们建议使用[Fio](https://fio.readthedocs.io/en/latest/fio_doc.html)测试 I / O 性能. 该测试应该在 NFS 服务器和与 NFS 服务器通信的应用程序节点上都运行. + +安装: + +* 在 Ubuntu 上: `apt install fio` . +* 在`yum`管理的环境中: `yum install fio` . + +然后运行以下命令: + +``` +fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=/path/to/git-data/testfile --bs=4k --iodepth=64 --size=4G --readwrite=randrw --rwmixread=75 +``` + +这将在`/path/to/git-data/testfile`创建一个 4GB 的文件. 它使用文件中的 75%/ 25%的拆分来执行 4KB 读取和写入,一次运行 64 个操作. 测试完成后,请确保删除文件. + +输出将根据所安装的`fio`版本而有所不同. 以下是网络固态驱动器(SSD)上`fio` v2.2.10 的输出示例: + +``` +test: (g=0): rw=randrw, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=64 + fio-2.2.10 + Starting 1 process + test: Laying out IO file(s) (1 file(s) / 1024MB) + Jobs: 1 (f=1): [m(1)] [100.0% done] [131.4MB/44868KB/0KB /s] [33.7K/11.3K/0 iops] [eta 00m:00s] + test: (groupid=0, jobs=1): err= 0: pid=10287: Sat Feb 2 17:40:10 2019 + read : io=784996KB, bw=133662KB/s, iops=33415, runt= 5873msec + write: io=263580KB, bw=44880KB/s, iops=11219, runt= 5873msec + cpu : usr=6.56%, sys=23.11%, ctx=266267, majf=0, minf=8 + IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0% + submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% + complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0% + issued : total=r=196249/w=65895/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0 + latency : target=0, window=0, percentile=100.00%, depth=64 + + Run status group 0 (all jobs): + READ: io=784996KB, aggrb=133661KB/s, minb=133661KB/s, maxb=133661KB/s, mint=5873msec, maxt=5873msec + WRITE: io=263580KB, aggrb=44879KB/s, minb=44879KB/s, maxb=44879KB/s, mint=5873msec, maxt=5873msec +``` + +注意此输出中的`iops`值. 在此示例中,SSD 每秒执行 33,415 次读操作和每秒 11,219 次写操作. 旋转磁盘可能每秒产生 2,000 和 700 的读取和写入操作. + +### Simple benchmarking[](#simple-benchmarking "Permalink") + +**注意:**此测试是幼稚的,但如果系统上没有`fio`可能有用. 在此测试中可能会收到不错的结果,但由于读取速度和其他各种因素,性能仍然很差. + +以下单行命令为文件系统的读写性能提供了快速基准. 这会将 1,000 个小文件写入执行该文件的目录,然后读取相同的 1,000 个文件. + +1. 更改为适当的[存储库存储路径](../repository_storage_paths.html)的根目录. +2. 为测试创建一个临时目录,以便以后轻松删除文件: + + ``` + mkdir test; cd test + ``` + +3. 运行命令: + + ``` + time for i in {0..1000}; do echo 'test' > "test${i}.txt"; done + ``` + +4. 要测试读取性能,请运行以下命令: + + ``` + time for i in {0..1000}; do cat "test${i}.txt" > /dev/null; done + ``` + +5. 删除测试文件: + +``` + cd ../; rm -rf test +``` + +`time for ...`命令的`time for ...`输出将类似于以下内容. 重要指标是`real` . + +``` +$ time for i in {0..1000}; do echo 'test' > "test${i}.txt"; done real 0m0.116s +user 0m0.025s +sys 0m0.091s + +$ time for i in {0..1000}; do cat "test${i}.txt" > /dev/null; done real 0m3.118s +user 0m1.267s +sys 0m1.663s +``` + +根据与多个客户的经验,此任务应花费 10 秒以表明文件系统性能良好. \ No newline at end of file diff --git a/docs/480.md b/docs/480.md new file mode 100644 index 0000000000000000000000000000000000000000..fd99b14e71acd04f42cf820cd7f3a5d3788219f5 --- /dev/null +++ b/docs/480.md @@ -0,0 +1,145 @@ +# Moving repositories managed by GitLab + +> 原文:[https://docs.gitlab.com/ee/administration/operations/moving_repositories.html](https://docs.gitlab.com/ee/administration/operations/moving_repositories.html) + +* [Target directory is empty: use a tar pipe](#target-directory-is-empty-use-a-tar-pipe) + * [Tar pipe to another server](#tar-pipe-to-another-server) +* [The target directory contains an outdated copy of the repositories: use rsync](#the-target-directory-contains-an-outdated-copy-of-the-repositories-use-rsync) + * [Single rsync to another server](#single-rsync-to-another-server) +* [Thousands of Git repositories: use one rsync per repository](#thousands-of-git-repositories-use-one-rsync-per-repository) + * [Parallel rsync for all repositories known to GitLab](#parallel-rsync-for-all-repositories-known-to-gitlab) + * [Parallel rsync only for repositories with recent activity](#parallel-rsync-only-for-repositories-with-recent-activity) + +# Moving repositories managed by GitLab[](#moving-repositories-managed-by-gitlab "Permalink") + +有时,您需要将 GitLab 管理的所有存储库移至另一个文件系统或另一个服务器. 在本文档中,我们将介绍将所有存储库从`/var/opt/gitlab/git-data/repositories` `/mnt/gitlab/repositories`到`/mnt/gitlab/repositories` . + +我们将研究三种情况:目标目录为空,目标目录包含版本库的过时副本,以及如何处理数千个版本库. + +**我们列出的每种方法都可以/将覆盖目标目录`/mnt/gitlab/repositories` . 不要混淆源和目标.** + +## Target directory is empty: use a tar pipe[](#target-directory-is-empty-use-a-tar-pipe "Permalink") + +如果目标目录`/mnt/gitlab/repositories`为空,则最简单的操作是使用 tar 管道. 此方法的开销很低,并且 tar 几乎总是已安装在系统上. 但是,无法恢复中断的 tar 管道:如果发生这种情况,则必须再次复制所有数据. + +``` +sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\ + tar -C /mnt/gitlab/repositories -xf -' +``` + +如果要查看进度,请用`-xvf`替换`-xf` . + +### Tar pipe to another server[](#tar-pipe-to-another-server "Permalink") + +You can also use a tar pipe to copy data to another server. If your `git` user has SSH access to the new server as `git@newserver`, you can pipe the data through SSH. + +``` +sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\ + ssh git@newserver tar -C /mnt/gitlab/repositories -xf -' +``` + +如果您想在数据通过网络之前进行压缩(这将花费您的 CPU 周期),则可以将`ssh`替换为`ssh -C` . + +## The target directory contains an outdated copy of the repositories: use rsync[](#the-target-directory-contains-an-outdated-copy-of-the-repositories-use-rsync "Permalink") + +如果目标目录已经包含部分/过时的存储库副本,那么再次用 tar 复制所有数据可能会很浪费. 在这种情况下,最好使用 rsync. 该实用程序已经安装在系统上,也可以通过 apt,yum 等轻松安装. + +``` +sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \ + /mnt/gitlab/repositories' +``` + +`/.` 在上面的命令中非常重要,没有它,您很容易在目标目录中获得错误的目录结构. 如果要查看进度,请用`-av`替换`-a` . + +### Single rsync to another server[](#single-rsync-to-another-server "Permalink") + +如果源系统上的`git`用户对目标服务器具有 SSH 访问权限,则可以使用 rsync 通过网络发送存储库. + +``` +sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \ + git@newserver:/mnt/gitlab/repositories' +``` + +## Thousands of Git repositories: use one rsync per repository[](#thousands-of-git-repositories-use-one-rsync-per-repository "Permalink") + +每次启动 rsync 作业时,它都必须检查源目录中的所有文件,目标目录中的所有文件,然后确定要复制或不复制哪些文件. 如果源目录或目标目录中包含许多内容,则 rsync 的启动阶段可能会成为您的 GitLab 服务器的负担. 在这种情况下,可以通过将 rsync 的工作分成较小的部分来使 rsync 的工作变得更轻松,并一次同步一个存储库. + +除了 rsync 之外,我们还将使用[GNU Parallel](http://www.gnu.org/software/parallel/) . 该实用程序未包含在 GitLab 中,因此您需要使用 apt 或 yum 自己安装. 还要注意,我们在下面使用的 GitLab 脚本是在 GitLab 8.1 中添加的. + +**此过程不会清理源位置不再存在的目标位置的存储库.** 如果您开始在`/mnt/gitlab/repositories`使用 GitLab 实例,则需要在切换到新的存储库存储目录后运行`gitlab-rake gitlab:cleanup:repos` . + +### Parallel rsync for all repositories known to GitLab[](#parallel-rsync-for-all-repositories-known-to-gitlab "Permalink") + +这将一次将存储库与 10 个 rsync 进程同步. 我们会跟踪进度,以便在必要时可以重新开始传输. + +首先,我们创建一个新目录,由`git`拥有,以保存传输日志. 在开始传输过程之前,我们假定目录为空,并且我们是唯一在其中写入文件的目录. + +``` +# Omnibus +sudo mkdir /var/opt/gitlab/transfer-logs +sudo chown git:git /var/opt/gitlab/transfer-logs + +# Source +sudo -u git -H mkdir /home/git/transfer-logs +``` + +我们使用要复制的目录列表为该过程添加种子. + +``` +# Omnibus +sudo -u git sh -c 'gitlab-rake gitlab:list_repos > /var/opt/gitlab/transfer-logs/all-repos-$(date +%s).txt' + +# Source +cd /home/git/gitlab +sudo -u git -H sh -c 'bundle exec rake gitlab:list_repos > /home/git/transfer-logs/all-repos-$(date +%s).txt' +``` + +现在我们可以开始传输了. 下面的命令是幂等的,并且 GNU Parallel 完成的作业数应收敛为零. 如果不是这样,则`all-repos-1234.txt`列出的某些存储库在被复制之前可能已被删除/重命名. + +``` +# Omnibus +sudo -u git sh -c ' +cat /var/opt/gitlab/transfer-logs/* | sort | uniq -u |\ + /usr/bin/env JOBS=10 \ + /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \ + /var/opt/gitlab/transfer-logs/success-$(date +%s).log \ + /var/opt/gitlab/git-data/repositories \ + /mnt/gitlab/repositories +' + +# Source +cd /home/git/gitlab +sudo -u git -H sh -c ' +cat /home/git/transfer-logs/* | sort | uniq -u |\ + /usr/bin/env JOBS=10 \ + bin/parallel-rsync-repos \ + /home/git/transfer-logs/success-$(date +%s).log \ + /home/git/repositories \ + /mnt/gitlab/repositories +` +``` + +### Parallel rsync only for repositories with recent activity[](#parallel-rsync-only-for-repositories-with-recent-activity "Permalink") + +假设您已经完成了一次在 2015 年 10 月 1 日 12:00 UTC 之后开始的同步. 然后,您可能只想同步*在*那*之后*通过 GitLab 更改的存储库. 您可以使用`SINCE`变量告诉`rake gitlab:list_repos`仅打印具有最近活动的存储库. + +``` +# Omnibus +sudo gitlab-rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\ + sudo -u git \ + /usr/bin/env JOBS=10 \ + /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \ + success-$(date +%s).log \ + /var/opt/gitlab/git-data/repositories \ + /mnt/gitlab/repositories + +# Source +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\ + sudo -u git -H \ + /usr/bin/env JOBS=10 \ + bin/parallel-rsync-repos \ + success-$(date +%s).log \ + /home/git/repositories \ + /mnt/gitlab/repositories +``` \ No newline at end of file diff --git a/docs/481.md b/docs/481.md new file mode 100644 index 0000000000000000000000000000000000000000..2dccfd20a46ffe2e879f82a6518dcceb891e4acc --- /dev/null +++ b/docs/481.md @@ -0,0 +1,365 @@ +# Run multiple Sidekiq processes + +> 原文:[https://docs.gitlab.com/ee/administration/operations/extra_sidekiq_processes.html](https://docs.gitlab.com/ee/administration/operations/extra_sidekiq_processes.html) + +* [Available Sidekiq queues](#available-sidekiq-queues) +* [Start multiple processes](#start-multiple-processes) +* [Negate settings](#negate-settings) +* [Queue selector (experimental)](#queue-selector-experimental) + * [Available attributes](#available-attributes) + * [Available operators](#available-operators) + * [Example queries](#example-queries) + * [Disable Sidekiq cluster](#disable-sidekiq-cluster) +* [Ignore all GitHub import queues](#ignore-all-github-import-queues) +* [Number of threads](#number-of-threads) +* [Manage concurrency](#manage-concurrency) + * [When running Sidekiq cluster (default)](#when-running-sidekiq-cluster-default) + * [When running a single Sidekiq process](#when-running-a-single-sidekiq-process) +* [Modify the check interval](#modify-the-check-interval) +* [Troubleshoot using the CLI](#troubleshoot-using-the-cli) + * [Monitor the `sidekiq-cluster` command](#monitor-the-sidekiq-cluster-command) + * [PID files](#pid-files) + * [Environment](#environment) + +# Run multiple Sidekiq processes[](#run-multiple-sidekiq-processes-core-only "Permalink") + +GitLab 允许您启动多个 Sidekiq 进程. 这些过程可用于消耗一组专用队列. 这可以用来确保某些队列始终具有专用的工作程序,而不管需要处理的作业数量如何. + +**注意:**此页面中的信息仅适用于 Omnibus GitLab. + +## Available Sidekiq queues[](#available-sidekiq-queues "Permalink") + +For a list of the existing Sidekiq queues, check the following files: + +* [Queues for both GitLab Community and Enterprise Editions](https://gitlab.com/gitlab-org/gitlab/blob/master/app/workers/all_queues.yml) +* [Queues for GitLab Enterprise Editions only](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/all_queues.yml) + +以上文件中的每个条目都代表一个队列,可以在其上启动 Sidekiq 进程. + +## Start multiple processes[](#start-multiple-processes "Permalink") + +版本历史 + +* 在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4006) ,使用 Sidekiq 集群启动多个进程. +* [Sidekiq 集群移至](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) GitLab 12.10 中的 GitLab [Core](https://about.gitlab.com/pricing/#self-managed) . +* [Sidekiq 集群](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4140)在 GitLab 13.0 中[成为默认设置](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4140) . + +To start multiple processes: + +1. 使用`sidekiq['queue_groups']`数组设置,指定使用`sidekiq-cluster`创建多少个进程以及它们应处理的队列. 数组中的每个项目都相当于一个附加的 Sidekiq 进程,并且每个项目中的值确定了它要处理的队列. + + 例如,以下设置创建三个 Sidekiq 过程,一到上运行`elastic_indexer` ,一到上运行`mailers` ,以及一个进程中运行的所有的队列: + + ``` + sidekiq['queue_groups'] = [ + "elastic_indexer", + "mailers", + "*" + ] + ``` + + 要让附加的 Sidekiq 进程处理多个队列,请将多个队列名称添加到其项目中,并以逗号分隔. 例如: + + ``` + sidekiq['queue_groups'] = [ + "elastic_indexer, elastic_commit_indexer", + "mailers", + "*" + ] + ``` + + [在 GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26594)和更高版本中,特殊队列名称`*`表示所有队列. 这将启动两个进程,每个进程处理所有队列: + + ``` + sidekiq['queue_groups'] = [ + "*", + "*" + ] + ``` + + `*`不能与具体的队列名称结合使用- `*, mailers`将只处理`mailers`队列. + + 当`sidekiq-cluster`仅在单个节点上运行时,请使用`*`确保在所有队列上至少运行一个进程. 这意味着一个进程将自动在将来创建的队列中拾取作业. + + 如果`sidekiq-cluster`在多个节点上运行,则还可以使用[`--negate`](#negate-settings)并列出所有已在处理的队列. + +2. 保存文件并重新配置 GitLab,以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +添加了额外的 Sidekiq 进程后,导航至 GitLab 中的**管理区域>监视>后台作业** ( `/admin/background_jobs` ). + +[![Multiple Sidekiq processes](img/705d87c5c620f8ade251682fceb074e3.png)](img/sidekiq-cluster.png) + +## Negate settings[](#negate-settings "Permalink") + +若要使其他 Sidekiq 进程在您列出的队列**之外**的每个队列上工作: + +1. 在按照步骤[启动额外的流程之后](#start-multiple-processes) ,请编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + sidekiq['negate'] = true + ``` + +2. 保存文件并重新配置 GitLab,以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +## Queue selector (experimental)[](#queue-selector-experimental "Permalink") + +[Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/45) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.8. + +**注意:**由于这被标记为**实验性的** ,因此随时可能更改,包括**破坏向后兼容性** . 这样我们就可以对 GitLab.com 部署所需的更改做出反应. 我们存在一个跟踪问题,希望从此功能中[删除实验性名称](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/147) ; 如果您有兴趣在自己的部署中使用它,请在此处发表评论. + +除了按名称选择队列之外,如上所述, `experimental_queue_selector`选项还允许使用以下组件以更通用的方式选择队列组: + +* 可以选择的属性. +* 用于构造查询的运算符. + +### Available attributes[](#available-attributes "Permalink") + +* 在 GitLab 13.1 中[引入](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/261) , `tags` . + +从[所有可用属性](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml)的[列表中](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml) , `experimental_queue_selector`允许通过以下属性选择队列: + +* `feature_category`队列所属的[GitLab 功能类别](https://about.gitlab.com/direction/maturity/#category-maturity) . 例如, `merge`队列属于`source_code_management`类别. +* `has_external_dependencies`队列是否连接到外部服务. 例如,所有进口商都将此设置为`true` . +* `urgency` -快速运行此队列的重要性. 可以`high` , `low`或`throttled` . 例如, `authorized_projects`队列用于刷新用户权限,并且紧急度很高. +* `name` -队列名. 其他属性通常更有用,因为它们更通用,但这在需要选择特定队列的情况下可用. +* `resource_boundary`如果队列受`cpu` , `memory`或`unknown`绑定. 例如, `project_export`队列受内存限制,因为它必须先将数据加载到内存中,然后再保存以进行导出. +* `tags` -队列的短暂注释. 预计这些版本会在发行版本之间频繁更改,并且可能会完全删除. + +`has_external_dependencies`是布尔值属性:只有确切的字符串`true`才被视为 true,其他所有内容都被视为 false. + +`tags`是一个集合,这意味着`=`检查相交的集合,而`!=`检查不相交的集合. 例如, `tags=a,b`选择具有标签`a` , `b`或两者都有的队列. `tags!=a,b`选择没有这些标签的队列. + +### Available operators[](#available-operators "Permalink") + +`experimental_queue_selector`支持以下运算符,从最高优先级到最低优先级列出: + +* `|` -逻辑或运算符. 例如, `query_a|query_b` (此处的`query_a`和`query_b`是由其他运算符组成的查询)将包括与任一查询匹配的队列. +* `&` -逻辑 AND 运算符. 例如, `query_a&query_b` (此处的`query_a`和`query_b`是由其他运算符组成的查询)将仅包括与两个查询均匹配的队列. +* `!=` -NOT IN 运算符. 例如, `feature_category!=issue_tracking`将所有队列排除在`issue_tracking`功能类别之外. +* `=` -IN 运算符. 例如, `resource_boundary=cpu`包括所有受 CPU 约束的队列. +* `,` -串联集合运算符. 例如, `feature_category=continuous_integration,pages`包含来自`continuous_integration`类别或`pages`类别的所有队列. 使用 OR 运算符也可以使用此示例,但是它具有更高的简洁性,并且具有较低的优先级. + +此语法的运算符优先级是固定的:不可能使 AND 的优先级高于 OR. + +[In GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26594) and later, as with the standard queue group syntax above, a single `*` as the entire queue group selects all queues. + +### Example queries[](#example-queries "Permalink") + +In `/etc/gitlab/gitlab.rb`: + +``` +sidekiq['enable'] = true +sidekiq['experimental_queue_selector'] = true +sidekiq['queue_groups'] = [ + # Run all non-CPU-bound queues that are high urgency + 'resource_boundary!=cpu&urgency=high', + # Run all continuous integration and pages queues that are not high urgency + 'feature_category=continuous_integration,pages&urgency!=high', + # Run all queues + '*' +] +``` + +### Disable Sidekiq cluster[](#disable-sidekiq-cluster "Permalink") + +**警告:**在 GitLab 14.0 中, [计划](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/240)将 Sidekiq 群集作为启动 Sidekiq 的唯一方法. + +默认情况下,Sidekiq 服务将运行`sidekiq-cluster` . 若要禁用此行为,请将以下内容添加到 Sidekiq 配置中: + +``` +sidekiq['enable'] = true +sidekiq['cluster'] = false +``` + +所有上述提及的`sidekiq`配置选项均可用. 默认情况下,它们的配置如下: + +``` +sidekiq['experimental_queue_selector'] = false +sidekiq['interval'] = nil +sidekiq['max_concurrency'] = 50 +sidekiq['min_concurrency'] = nil +sidekiq['negate'] = false +sidekiq['queue_groups'] = ['*'] +sidekiq['shutdown_timeout'] = 25 +``` + +如果您决定如上所述配置集群,则必须禁用`sidekiq_cluster` . + +禁用`sidekiq_cluster` ,必须将`sidekiq_cluster`的配置复制到`sidekiq` . 任何配置成用于`sidekiq_cluster`将被覆盖由用于选项`sidekiq`设定时`sidekiq['cluster'] = true` . + +使用此功能时,名为`sidekiq`的服务现在将在运行`sidekiq-cluster` . + +将遵守为 Sidekiq 配置的[并发](#manage-concurrency)和其他选项. + +默认情况下, `sidekiq-cluster` `/var/log/gitlab/sidekiq`像常规的 Sidekiq 日志一样进入`/var/log/gitlab/sidekiq` . + +## Ignore all GitHub import queues[](#ignore-all-github-import-queues "Permalink") + +[从 GitHub 导入时](../../user/project/import/github.html) ,Sidekiq 可能会使用其所有资源来执行那些操作. 要设置一个单独的`sidekiq-cluster`进程以忽略所有与 GitHub 导入相关的队列: + +1. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + sidekiq['enable'] = true + sidekiq['negate'] = true + sidekiq['queue_groups'] = [ + "github_import_advance_stage", + "github_importer:github_import_import_diff_note", + "github_importer:github_import_import_issue", + "github_importer:github_import_import_note", + "github_importer:github_import_import_lfs_object", + "github_importer:github_import_import_pull_request", + "github_importer:github_import_refresh_import_jid", + "github_importer:github_import_stage_finish_import", + "github_importer:github_import_stage_import_base_data", + "github_importer:github_import_stage_import_issues_and_diff_notes", + "github_importer:github_import_stage_import_notes", + "github_importer:github_import_stage_import_lfs_objects", + "github_importer:github_import_stage_import_pull_requests", + "github_importer:github_import_stage_import_repository" + ] + ``` + +2. 保存文件并重新配置 GitLab,以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +## Number of threads[](#number-of-threads "Permalink") + +在`sidekiq`下定义的每个进程都以等于队列数的线程数开始,再加上一个备用线程. 例如,处理`process_commit`和`post_receive`队列的进程将总共使用三个线程. + +## Manage concurrency[](#manage-concurrency "Permalink") + +设置最大并发数时,请记住,这通常不应超过可用的 CPU 内核数. 以下示例中的值是任意的,不是特别的建议. + +Each thread requires a Redis connection, so adding threads may increase Redis latency and potentially cause client timeouts. See the [Sidekiq documentation about Redis](https://github.com/mperham/sidekiq/wiki/Using-Redis) for more details. + +### When running Sidekiq cluster (default)[](#when-running-sidekiq-cluster-default "Permalink") + +在 GitLab 13.0 和更高版本中,默认运行 Sidekiq 群集. + +1. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + sidekiq['min_concurrency'] = 15 + sidekiq['max_concurrency'] = 25 + ``` + +2. 保存文件并重新配置 GitLab,以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +`min_concurrency`和`max_concurrency`是独立的; 一个可以不设置另一个. 将`min_concurrency`设置为 0 将禁用该限制. + +对于每个队列组,令 N 为队列数多一. 并发因子将设置为: + +1. `N` ,如果它介于`min_concurrency`和`max_concurrency`之间. +2. `max_concurrency` ,如果`N`超过此值. +3. `min_concurrency` ,如果`N`小于此值. + +如果`min_concurrency`等于`max_concurrency` ,那么无论队列数量如何,都将使用此值. + +当`min_concurrency`大于`max_concurrency` ,它将被视为等于`max_concurrency` . + +### When running a single Sidekiq process[](#when-running-a-single-sidekiq-process "Permalink") + +在 GitLab 12.10 及更早版本中,默认运行单个 Sidekiq 进程. + +**警告:**计划在 GitLab [14.0 中](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/240)删除直接运行 Sidekiq. + +1. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + sidekiq['cluster'] = false + sidekiq['concurrency'] = 25 + ``` + +2. 保存文件并重新配置 GitLab,以使更改生效: + + ``` + sudo gitlab-ctl reconfigure + ``` + +这将设置 Sidekiq 进程的并发性(线程数). + +## Modify the check interval[](#modify-the-check-interval "Permalink") + +修改其他 Sidekiq 进程的检查间隔: + +1. 编辑`/etc/gitlab/gitlab.rb`并添加: + + ``` + sidekiq['interval'] = 5 + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +这告诉其他进程多久检查一次排队的作业. + +## Troubleshoot using the CLI[](#troubleshoot-using-the-cli "Permalink") + +**警告:**建议使用`/etc/gitlab/gitlab.rb`来配置 Sidekiq 进程. 如果遇到问题,应联系 GitLab 支持. 使用命令行需要您自担风险. + +为了进行调试,可以使用命令`/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster`启动额外的 Sidekiq 进程. 此命令使用以下语法获取参数: + +``` +/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster [QUEUE,QUEUE,...] [QUEUE, ...] +``` + +每个单独的参数表示一组必须由 Sidekiq 进程处理的队列. 多个队列可以通过相同的过程来处理,方法是用逗号而不是空格将它们分开. + +除了队列,还可以提供队列名称空间,以使进程自动侦听该名称空间中的所有队列,而无需显式列出所有队列名称. 有关队列名称空间的更多信息,请参见[Sidekiq 样式指南中](../../development/sidekiq_style_guide.html#queue-namespaces)的相关部分. + +例如,假设您要启动两个额外的进程:一个进程处理`process_commit`队列,另一个进程处理`post_receive`队列. 可以按以下步骤完成: + +``` +/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster process_commit post_receive +``` + +如果您想启动一个处理两个队列的进程,则可以使用以下语法: + +``` +/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster process_commit,post_receive +``` + +如果您想让一个 Sidekiq 进程处理`process_commit`和`post_receive`队列,以及一个进程来处理`gitlab_shell`队列,则可以使用以下命令: + +``` +/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster process_commit,post_receive gitlab_shell +``` + +### Monitor the `sidekiq-cluster` command[](#monitor-the-sidekiq-cluster-command "Permalink") + +一旦启动了所需数量的 Sidekiq 进程, `sidekiq-cluster`命令将不会终止. 相反,该进程将继续运行并将所有信号转发到子进程. 这使停止所有 Sidekiq 进程变得容易,因为您只需将信号发送到`sidekiq-cluster`进程即可,而不必将其发送到各个进程. + +如果`sidekiq-cluster`进程崩溃或收到`SIGKILL` ,则子进程将在几秒钟后终止. 这样可以确保您不会遇到僵尸 Sidekiq 进程. + +所有这些使监视过程变得相当容易. 只需将`sidekiq-cluster`到您选择的主管(例如 runit),就可以了. + +如果子进程死亡, `sidekiq-cluster`命令将发出信号通知所有剩余进程终止,然后终止自身. 这样就不需要`sidekiq-cluster`来重新实现复杂的过程监控/重新启动代码. 相反,您应该确保主管在必要时重新启动`sidekiq-cluster`过程. + +### PID files[](#pid-files "Permalink") + +`sidekiq-cluster`命令可以将其 PID 存储在文件中. 默认情况下,不会写入任何 PID 文件,但是可以通过将`--pidfile`选项传递给`sidekiq-cluster`来更改此文件. 例如: + +``` +/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster --pidfile /var/run/gitlab/sidekiq_cluster.pid process_commit +``` + +请记住,PID 文件将包含`sidekiq-cluster`命令的 PID,而不包含已启动的 Sidekiq 进程的 PID. + +### Environment[](#environment "Permalink") + +可以通过将`--environment`标志传递给`sidekiq-cluster`命令或将`RAILS_ENV`设置为非空值来设置 Rails 环境. 可以在`/opt/gitlab/etc/gitlab-rails/env/RAILS_ENV`找到默认值. \ No newline at end of file diff --git a/docs/482.md b/docs/482.md new file mode 100644 index 0000000000000000000000000000000000000000..5ded9bfde0065e6c3b36871245670dd64ef835ad --- /dev/null +++ b/docs/482.md @@ -0,0 +1,47 @@ +# Sidekiq MemoryKiller + +> 原文:[https://docs.gitlab.com/ee/administration/operations/sidekiq_memory_killer.html](https://docs.gitlab.com/ee/administration/operations/sidekiq_memory_killer.html) + +* [Configuring the MemoryKiller](#configuring-the-memorykiller) + +# Sidekiq MemoryKiller[](#sidekiq-memorykiller "Permalink") + +GitLab Rails 应用程序代码遭受内存泄漏. 对于 Web 请求,可以使用[`puma-worker-killer`](https://github.com/schneems/puma_worker_killer)来解决此问题,如果超过内存限制,它将重新启动 Puma worker 进程. Sidekiq MemoryKiller 对 GitLab 用来处理后台作业的 Sidekiq 进程采用相同的方法. + +与 puma-worker-killer(自 GitLab 13.0 起默认对所有 GitLab 安装启用)不同,Sidekiq MemoryKiller 默认*仅对* Omnibus 软件包启用. 这样做的原因是,MemoryKiller 依赖于 runit 在内存引起的关闭之后重新启动 Sidekiq,并且从源头安装 GitLab 并不全部使用 runit 或等效版本. + +使用默认设置,MemoryKiller 将使 Sidekiq 重新启动的频率不超过每 15 分钟一次,并且重新启动会为传入的后台作业造成大约一分钟的延迟. + +一些后台作业依赖于长时间运行的外部流程. 为确保在重启 Sidekiq 时将它们彻底终止,每个 Sidekiq 进程应以进程组负责人的身份运行(例如,使用`chpst -P` ). 如果使用 Omnibus 或安装了`runit`的`bin/background_jobs`脚本, `runit`为您处理. + +## Configuring the MemoryKiller[](#configuring-the-memorykiller "Permalink") + +使用环境变量控制 MemoryKiller. + +* `SIDEKIQ_DAEMON_MEMORY_KILLER` :默认为 0.设置为 1 时,MemoryKiller 在*守护程序*模式下工作. 否则,MemoryKiller 将在*旧*模式下工作. + + 在*传统*模式下,MemoryKiller 在每个作业后检查 Sidekiq 进程 RSS. + + 在*守护程序*模式下,MemoryKiller 每 3 秒检查一次 Sidekiq 进程 RSS(由`SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL`定义). + +* `SIDEKIQ_MEMORY_KILLER_MAX_RSS` (KB):如果设置了此变量,并且其值大于 0,则启用 MemoryKiller. 否则,将禁用 MemoryKiller. + + `SIDEKIQ_MEMORY_KILLER_MAX_RSS`定义了 Sidekiq 进程允许的 RSS. + + 在*传统*模式下,如果 Sidekiq 进程超出允许的 RSS,则将触发不可逆的延迟正常重启. Sidekiq 的重启将在`SIDEKIQ_MEMORY_KILLER_GRACE_TIME`秒后发生. + + 在*守护程序*模式下,如果 Sidekiq 进程超出允许的 RSS 的时间超过`SIDEKIQ_MEMORY_KILLER_GRACE_TIME` ,则将触发正常重启. 如果 Sidekiq 进程在`SIDEKIQ_MEMORY_KILLER_GRACE_TIME`内低于允许的 RSS,则重新启动将被中止. + + Omnibus 软件包的默认值[在 Omnibus GitLab 存储库中设置](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/attributes/default.rb) . + +* `SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS` (KB):由*守护程序*模式使用. 如果 Sidekiq 进程 RSS(以千字节为单位)超过`SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS` ,则会立即立即正常重启 Sidekiq. + +* `SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL` :在*守护程序*模式下用于定义检查进程 RSS 的频率,默认为 3 秒. + +* `SIDEKIQ_MEMORY_KILLER_GRACE_TIME` :默认为 900 秒(15 分钟). 此变量的用法描述为`SIDEKIQ_MEMORY_KILLER_MAX_RSS`一部分. + +* `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT` :默认为 30 秒. 这定义了所有 Sidekiq 作业完成所允许的最长时间. 在此期间将不接受任何新作业,并且所有作业完成后该过程将立即退出. + + 如果作业在此期间未完成,则 MemoryKiller 将通过将`SIGTERM`发送到 Sidekiq 进程来中断所有当前正在运行的作业. + + If the process hard shutdown/restart is not performed by Sidekiq, the Sidekiq process will be forcefully terminated after `Sidekiq.options[:timeout] * 2` seconds. An external supervision mechanism (e.g. runit) must restart Sidekiq afterwards. \ No newline at end of file diff --git a/docs/483.md b/docs/483.md new file mode 100644 index 0000000000000000000000000000000000000000..d086535b5fa5f5ff1af11cb8c61d52c4c9d69a36 --- /dev/null +++ b/docs/483.md @@ -0,0 +1,46 @@ +# Switching to Puma + +> 原文:[https://docs.gitlab.com/ee/administration/operations/puma.html](https://docs.gitlab.com/ee/administration/operations/puma.html) + +* [Why switch to Puma?](#why-switch-to-puma) +* [Configuring Puma to replace Unicorn](#configuring-puma-to-replace-unicorn) +* [Performance caveat when using Puma with Rugged](#performance-caveat-when-using-puma-with-rugged) + +# Switching to Puma[](#switching-to-puma "Permalink") + +从 GitLab 12.9 开始, [Puma](https://github.com/puma/puma)取代了[Unicorn](https://yhbt.net/unicorn/) . 作为默认的 Web 服务器. 在 GitLab 13.0 中,除非明确配置为不运行,否则以下命令将运行 Puma 而不是 Unicorn: + +* 基于软件包的多合一安装. +* 基于舵图的安装. + +## Why switch to Puma?[](#why-switch-to-puma "Permalink") + +Puma 具有多线程体系结构,与像 Unicorn 这样的多进程应用程序服务器相比,它使用的内存更少. 在 GitLab.com 上,我们发现内存消耗减少了 40%. + +大多数 Rails 应用程序请求通常都包含一定比例的 I / O 等待时间. 在 I / O 等待时间内,MRI Ruby 将释放 GVL(全局 VM 锁定)到其他线程. 因此,多线程 Puma 仍然可以处理比单个进程更多的请求. + +## Configuring Puma to replace Unicorn[](#configuring-puma-to-replace-unicorn "Permalink") + +从 GitLab 13.0 开始,Puma 是默认的应用程序服务器. 我们计划在 GitLab 14.0 中删除对 Unicorn 的支持. + +切换到 Puma 时,由于两个应用程序服务器之间的差异,Unicorn 服务器配置将*不会*自动继承. 对于基于 Omnibus 的部署,请参阅" [配置 Puma 设置"](https://docs.gitlab.com/omnibus/settings/puma.html) . 对于基于 Helm 的部署,请参阅[Webservice Chart 文档](https://docs.gitlab.com/charts/charts/gitlab/webservice/index.html) . + +此外,由于 Unicorn 和 Puma 在重新启动服务期间如何处理连接方面存在差异,因此我们强烈建议多节点部署[将其负载平衡器配置为利用就绪检查](../high_availability/load_balancer.html#readiness-check) . + +## Performance caveat when using Puma with Rugged[](#performance-caveat-when-using-puma-with-rugged "Permalink") + +对于使用 NFS 存储 Git 存储库的部署,我们允许 GitLab 使用[直接 Git 访问](../gitaly/index.html#direct-access-to-git-in-gitlab)来使用[Rugged](https://github.com/libgit2/rugged)来提高性能. + +坚固耐用的使用,将自动启用,如果直接 Git 的访问[可用](../gitaly/index.html#how-it-works) ,除非它被禁用[的功能标志](../../development/gitaly.html#legacy-rugged-code) . + +MRI Ruby 使用 GVL. 这使得 MRI Ruby 可以是多线程的,但最多只能在单个内核上运行. 由于 Rugged 可以长时间使用线程(由于 Git 访问的密集 I / O 操作),因此这可能会使可能正在处理请求的其他线程饿死. 对于在单线程模式下运行的 Unicorn 或 Puma 而言,情况并非如此,因为最多同时处理一个请求. + +我们正在积极致力于消除 Rugged 的使用. 即使没有 Rugged 的性能今天已经可以接受,但在某些情况下使用它仍然可能是有益的. + +考虑到使用多线程 Puma 运行 Rugged 的警告,以及 Gitaly 可接受的性能,如果使用 Puma 多线程(当 Puma 配置为使用多个线程运行时),我们将禁用 Rugged 的使用. + +在某些情况下,此默认行为可能不是最佳配置. 如果 Rugged 在您的部署中起着重要作用,我们建议您进行基准测试以找到最佳配置: + +* 最安全的选择是从单线程 Puma 开始. 与 Rugged 一起使用时,单线程 Puma 的工作原理与 Unicorn 相同. + +* 要对多线程 Puma 进行 Rugged 自动检测,可以使用[功能标志](../../development/gitaly.html#legacy-rugged-code) . \ No newline at end of file diff --git a/docs/484.md b/docs/484.md new file mode 100644 index 0000000000000000000000000000000000000000..65d31037ada3159809d0df85da4d518d842230e3 --- /dev/null +++ b/docs/484.md @@ -0,0 +1,70 @@ +# Understanding Unicorn and unicorn-worker-killer + +> 原文:[https://docs.gitlab.com/ee/administration/operations/unicorn.html](https://docs.gitlab.com/ee/administration/operations/unicorn.html) + +* [Unicorn](#unicorn) + * [Tunable options](#tunable-options) +* [unicorn-worker-killer](#unicorn-worker-killer) + +# Understanding Unicorn and unicorn-worker-killer[](#understanding-unicorn-and-unicorn-worker-killer "Permalink") + +**注意:**从 GitLab 13.0 开始,Puma 是基于 GitLab 多合一软件包的安装以及 GitLab Helm 图表部署中使用的默认 Web 服务器. + +## Unicorn[](#unicorn "Permalink") + +GitLab uses [Unicorn](https://yhbt.net/unicorn/), a pre-forking Ruby web server, to handle web requests (web browsers and Git HTTP clients). Unicorn is a daemon written in Ruby and C that can load and run a Ruby on Rails application; in our case the Rails application is GitLab Community Edition or GitLab Enterprise Edition. + +Unicorn 具有多进程架构,可以更好地利用可用的 CPU 内核(进程可以在不同的内核上运行),并具有更强的容错能力(大多数故障仅隔离在一个进程中,无法完全关闭 GitLab). 启动时,Unicorn 的"主"进程使用 GitLab 应用程序代码加载一个干净的 Ruby 环境,然后生成继承此干净的初始环境的"工人". "主人"从不处理任何留给工人的请求. 操作系统网络堆栈将传入的请求排队,并在工作进程之间分配它们. + +在一个理想的世界中,主服务器将生成一个工人池,然后工人依次处理传入的 Web 请求,直到时间结束. 实际上,工作进程可能崩溃或超时:如果主服务器注意到工作时间过长,无法处理请求,它将以 SIGKILL(" kill -9")终止工作进程. 无论工作进程如何结束,主进程都将再次用新的"干净"进程替换它. Unicorn 的设计宗旨是能够替换"崩溃的"工人,而无需放弃用户的要求. + +这就是`unicorn_stderr.log`的 Unicorn worker 超时. 主过程具有下面的 PID 56227. + +``` +[2015-06-05T10:58:08.660325 #56227] ERROR -- : worker=10 PID:53009 timeout (61s > 60s), killing +[2015-06-05T10:58:08.699360 #56227] ERROR -- : reaped # worker=10 +[2015-06-05T10:58:08.708141 #62538] INFO -- : worker=10 spawned pid=62538 +[2015-06-05T10:58:08.708824 #62538] INFO -- : worker=10 ready +``` + +### Tunable options[](#tunable-options "Permalink") + +Unicorn 的主要可调选项是工作进程数和请求超时,之后 Unicorn 主服务器终止工作进程. 如果要调整这些设置,请参见[Omnibus GitLab Unicorn 设置文档](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/unicorn.html) . + +## unicorn-worker-killer[](#unicorn-worker-killer "Permalink") + +GitLab 内存泄漏. 这些内存泄漏在长时间运行的进程(例如 Unicorn 工作者)中表现出来. (不知道 Unicorn 主进程会泄漏内存,可能是因为它无法处理用户请求.) + +为了使这些内存泄漏易于管理,GitLab 随附了[unicorn-worker-killer gem](https://github.com/kzk/unicorn-worker-killer) . 每隔 16 个请求,这只宝石[猴就会](https://en.wikipedia.org/wiki/Monkey_patch)给独角兽工人打[补丁](https://en.wikipedia.org/wiki/Monkey_patch)以进行内存自检. 如果 Unicorn worker 的内存超过预设限制,则退出 worker 进程. 然后,Unicorn 主服务器自动替换工作进程. + +这是处理内存泄漏的可靠方法:Unicorn 旨在处理"崩溃"的工作程序,因此不会丢弃任何用户请求. unicorn-worker-killer gem 被设计为仅*在请求之间*终止工作进程,因此不会影响用户请求. 您可以通过设置以下值`/etc/gitlab/gitlab.rb`来设置 Unicorn worker killer 的最小和最大内存阈值(以字节为单位): + +* 对于 GitLab **12.7**及更高版本: + + ``` + unicorn['worker_memory_limit_min'] = "1024 * 1 << 20" + unicorn['worker_memory_limit_max'] = "1280 * 1 << 20" + ``` + +* 对于 GitLab **12.6**及更高版本: + + ``` + unicorn['worker_memory_limit_min'] = "400 * 1 << 20" + unicorn['worker_memory_limit_max'] = "650 * 1 << 20" + ``` + +否则,您可以设置`GITLAB_UNICORN_MEMORY_MIN`和`GITLAB_UNICORN_MEMORY_MAX` [环境变量](../environment_variables.html) . + +这就是 Unicorn_stderr.log 中的 Unicorn 工作程序内存重新启动的样子. 您看到工作程序 4(PID 125918)正在检查自己并决定退出. 内存阈值是 254802235 字节,大约 250MB. 对于 GitLab,此阈值是 200 到 250 MB 之间的随机值. 然后,主进程(PID 117565)接收工作进程,并生成具有 PID 127549 的新"工作进程 4". + +``` +[2015-06-05T12:07:41.828374 #125918] WARN -- : #: worker (pid: 125918) exceeds memory limit (256413696 bytes > 254802235 bytes) +[2015-06-05T12:07:41.828472 #125918] WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 125918) alive: 23 sec (trial 1) +[2015-06-05T12:07:42.025916 #117565] INFO -- : reaped # worker=4 +[2015-06-05T12:07:42.034527 #127549] INFO -- : worker=4 spawned pid=127549 +[2015-06-05T12:07:42.035217 #127549] INFO -- : worker=4 ready +``` + +从 GitLab.com 上摘录的另一段日志摘要是," worker 4"仅在 23 秒内处理请求. 对于我们当前的 GitLab.com 设置和流量,这是正常值. + +在某些 GitLab 网站上,独角兽内存重新启动的频率很高,可能会使管理员感到困惑. 通常他们是[红鲱鱼](https://en.wikipedia.org/wiki/Red_herring) . \ No newline at end of file diff --git a/docs/485.md b/docs/485.md new file mode 100644 index 0000000000000000000000000000000000000000..54978c3dc9e6c69a9a84712704196f2608050c94 --- /dev/null +++ b/docs/485.md @@ -0,0 +1,119 @@ +# User lookup via OpenSSH's AuthorizedPrincipalsCommand + +> 原文:[https://docs.gitlab.com/ee/administration/operations/ssh_certificates.html](https://docs.gitlab.com/ee/administration/operations/ssh_certificates.html) + +* [Why use OpenSSH certificates?](#why-use-openssh-certificates) +* [Setting up SSH certificate lookup via GitLab Shell](#setting-up-ssh-certificate-lookup-via-gitlab-shell) +* [Principals and security](#principals-and-security) +* [Interaction with the `authorized_keys` file](#interaction-with-the-authorized_keys-file) +* [Other security caveats](#other-security-caveats) +* [Disabling the global warning about users lacking SSH keys](#disabling-the-global-warning-about-users-lacking-ssh-keys) + +# User lookup via OpenSSH’s AuthorizedPrincipalsCommand[](#user-lookup-via-opensshs-authorizedprincipalscommand "Permalink") + +> [在](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19911) GitLab 社区版 11.2 中[可用](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19911) . + +GitLab 的默认 SSH 身份验证要求用户上载 SSH 公钥,然后才能使用 SSH 传输. + +在集中式(例如公司)环境中,这在操作上可能会很麻烦,特别是如果 SSH 密钥是颁发给用户的临时密钥,例如在发行后 24 小时过期的临时密钥. + +在这种设置中,需要一些外部自动化过程来不断将新密钥上载到 GitLab. + +> **警告:需要** OpenSSH 6.9+版本,因为该版本引入了`AuthorizedPrincipalsCommand`配置选项. 如果使用 CentOS 6,则可以[按照以下说明](fast_ssh_key_lookup.html#compiling-a-custom-version-of-openssh-for-centos-6)来编译最新版本. + +## Why use OpenSSH certificates?[](#why-use-openssh-certificates "Permalink") + +通过使用 OpenSSH 证书,有关 GitLab 上用户拥有密钥的所有信息都被编码在密钥本身中,并且 OpenSSH 自身保证用户无法伪造此信息,因为他们需要访问私有 CA 签名密钥. + +正确设置后,就不需要完全将用户 SSH 密钥上传到 GitLab. + +## Setting up SSH certificate lookup via GitLab Shell[](#setting-up-ssh-certificate-lookup-via-gitlab-shell "Permalink") + +如何完全设置 SSH 证书不在本文档的范围之内. 请参阅[OpenSSH 的`PROTOCOL.certkeys`](https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD)了解其工作方式,例如[RedHat 的文档](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/sec-using_openssh_certificate_authentication) . + +我们假设您已经设置了 SSH 证书,并且已经将 CA 的`TrustedUserCAKeys`添加到了`sshd_config` ,例如: + +``` +TrustedUserCAKeys /etc/security/mycompany_user_ca.pub +``` + +通常,在这种设置中, `TrustedUserCAKeys`不会在" `Match User git`范围内,因为它也将用于系统登录到 GitLab 服务器本身,但是您的设置可能会有所不同. 如果 CA 仅用于 GitLab,请考虑将其放在" `Match User git`部分(如下所述). + +由该 CA 颁发的 SSH 证书**务必**具有与该用户在 GitLab 上的用户名相对应的"密钥 ID",例如(为简洁起见,省略了一些输出): + +``` +$ ssh-add -L | grep cert | ssh-keygen -L -f - + +(stdin):1: + Type: ssh-rsa-cert-v01@openssh.com user certificate + Public key: RSA-CERT SHA256:[...] + Signing CA: RSA SHA256:[...] + Key ID: "aearnfjord" + Serial: 8289829611021396489 + Valid: from 2018-07-18T09:49:00 to 2018-07-19T09:50:34 + Principals: + sshUsers + [...] + [...] +``` + +从技术上讲,这不是完全正确,例如,它可以`prod-aearnfjord`如果它是你通常会登录到服务器作为一个 SSH 证书`prod-aearnfjord`用户,但你必须指定自己的`AuthorizedPrincipalsCommand`做映射,而不是使用我们提供的默认. + +重要的是, `AuthorizedPrincipalsCommand`必须能够以某种方式从"密钥 ID"映射到 GitLab 用户名,我们提供的默认命令假设两者之间存在 1 = 1 的映射,因为这样做的重点是允许我们从密钥本身提取 GitLab 用户名,而不是依赖默认的公共密钥到用户名的映射. + +然后,在您的`sshd_config`为`git`用户设置`AuthorizedPrincipalsCommand` . 希望您可以使用 GitLab 随附的默认值: + +``` +Match User git + AuthorizedPrincipalsCommandUser root + AuthorizedPrincipalsCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-principals-check %i sshUsers +``` + +该命令将发出类似于以下内容的输出: + +``` +command="/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell username-{KEY_ID}",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty {PRINCIPAL} +``` + +其中`{KEY_ID}`是传递给脚本的`%i`参数(例如`aeanfjord` ),而`{PRINCIPAL}`是传递给脚本的主体(例如`sshUsers` ). + +您将需要自定义其中的`sshUsers`部分. 对于可以登录到 GitLab 的所有用户,它应该是一定要保证是密钥的一部分的主体,或者您必须提供一个主体列表,其中一个将提供给用户,例如: + +``` + [...] + AuthorizedPrincipalsCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-principals-check %i sshUsers windowsUsers +``` + +## Principals and security[](#principals-and-security "Permalink") + +您可以根据需要提供任意数量的委托人,这些委托人将变成多行`authorized_keys`输出,如`sshd_config(5)`中的`AuthorizedPrincipalsFile`文档中所述. + +通常,将`AuthorizedKeysCommand`与 OpenSSH 一起使用时,主体是允许登录到该服务器的某个"组". 但是,在 GitLab 中,它仅用于满足 OpenSSH 的要求,我们实际上只关心"密钥 ID"的正确性. 一旦解压缩,GitLab 将为该用户强制执行自己的 ACL(例如,用户可以访问哪些项目). + +因此,例如对用户接受的内容过分慷慨是可以的,因为如果用户(例如)根本无法访问 GitLab,它只会出错并显示一条有关该用户无效的消息. + +## Interaction with the `authorized_keys` file[](#interaction-with-the-authorized_keys-file "Permalink") + +SSH 证书可以与`authorized_keys`文件结合使用,并且如果按照上述`authorized_keys`文件的配置进行设置,它仍将作为后备. + +这是因为,如果`AuthorizedPrincipalsCommand`无法对用户进行身份验证,则 OpenSSH 将回退到`~/.ssh/authorized_keys` (或`AuthorizedKeysCommand` )上. + +因此,仍然有理由结合使用["在数据库中快速查找授权的 SSH 密钥"](fast_ssh_key_lookup.html)方法. 由于您将对所有普通用户使用 SSH 证书,并且如果使用密钥,则依靠`~/.ssh/authorized_keys`后备来部署密钥. + +但是您可能会发现没有必要这样做,因为所有普通用户都将使用快速的`AuthorizedPrincipalsCommand`路径,并且只有自动部署密钥访问才会落在`~/.ssh/authorized_keys` ,或者您还有更多的密钥可以使用普通用户(尤其是续订的用户)比您拥有的部署密钥. + +## Other security caveats[](#other-security-caveats "Permalink") + +用户仍然可以通过手动将 SSH 公钥上载到他们的配置文件中来绕过 SSH 证书身份验证,依靠`~/.ssh/authorized_keys`后备来对其进行身份验证. 当前没有阻止它的功能, [但是有一个添加它的公开请求](https://gitlab.com/gitlab-org/gitlab/-/issues/23260) . + +当前,可以通过提供一个自定义的`AuthorizedKeysCommand`来破解这种限制,该命令可检查从`gitlab-shell-authorized-keys-check`返回的已发现密钥 ID `gitlab-shell-authorized-keys-check`为部署密钥(应拒绝所有非部署密钥). + +## Disabling the global warning about users lacking SSH keys[](#disabling-the-global-warning-about-users-lacking-ssh-keys "Permalink") + +默认情况下,GitLab 将向尚未将 SSH 密钥上载到其配置文件的用户显示"您将无法通过 SSH 推送或推送项目代码"警告. + +This is counterproductive when using SSH certificates, since users aren’t expected to upload their own keys. + +要全局禁用此警告,请转到"应用程序设置->帐户和限制设置",然后禁用"显示用户添加 SSH 密钥消息"设置. + +This setting was added specifically for use with SSH certificates, but can be turned off without using them if you’d like to hide the warning for some other reason. \ No newline at end of file diff --git a/docs/486.md b/docs/486.md new file mode 100644 index 0000000000000000000000000000000000000000..9acddd8defebcb8d2c1f77f4266c7aa10e2ddbb2 --- /dev/null +++ b/docs/486.md @@ -0,0 +1,176 @@ +# GitLab Package Registry administration + +> 原文:[https://docs.gitlab.com/ee/administration/packages/](https://docs.gitlab.com/ee/administration/packages/) + +* [Enabling the Packages feature](#enabling-the-packages-feature) +* [Changing the storage path](#changing-the-storage-path) + * [Changing the local storage path](#changing-the-local-storage-path) + * [Using object storage](#using-object-storage) + * [Migrating local packages to object storage](#migrating-local-packages-to-object-storage) + +# GitLab Package Registry administration[](#gitlab-package-registry-administration-premium-only "Permalink") + +GitLab 软件包允许组织将 GitLab 用作各种常见软件包管理器的私有存储库. 用户能够构建和发布程序包,这些程序包可以很容易地作为下游项目中的依赖项使用. + +软件包功能允许 GitLab 充当以下内容的存储库: + +| 软件库 | Description | 在 GitLab 版本中可用 | +| --- | --- | --- | +| [PyPi Repository](../../user/packages/pypi_repository/index.html) | GitLab PyPi 存储库使 GitLab 中的每个项目都有自己的空间来存储[PyPi](https://s0pypi0org.icopy.site/)软件包. | 12.10+ | +| [Composer Repository](../../user/packages/composer_repository/index.html) | GitLab Composer 存储库使 GitLab 中的每个项目都有自己的空间来存储[Composer](https://s0getcomposer0org.icopy.site/)软件包. | 13.1+ | +| [NuGet Repository](../../user/packages/nuget_repository/index.html) | GitLab NuGet 存储库使 GitLab 中的每个项目都有自己的空间来存储[NuGet](https://www.nuget.org/)软件包. | 12.8+ | +| [Conan Repository](../../user/packages/conan_repository/index.html) | GitLab 柯南存储库使 GitLab 中的每个项目都有自己的空间来存储[柯南](https://conan.io/)软件包. | 12.4+ | +| [Maven Repository](../../user/packages/maven_repository/index.html) | GitLab Maven 存储库使 GitLab 中的每个项目都有自己的空间来存储[Maven](https://maven.apache.org/)软件包. | 11.3+ | +| [NPM Registry](../../user/packages/npm_registry/index.html) | GitLab NPM 注册表使 GitLab 中的每个项目都有自己的空间来存储[NPM](https://s0www0npmjs0com.icopy.site/)软件包. | 11.7+ | +| [Go Proxy](../../user/packages/go_proxy/index.html) | GitLab 的 Go 代理使 GitLab 中的每个项目都可以通过[Go 代理协议](https://proxy.golang.org/)获取. | 13.1+ | + +您没有看到您的包裹管理系统受支持吗? 请考虑为 GitLab 做贡献. 此[开发文档](../../development/packages.html)将指导您完成该过程. + +## Enabling the Packages feature[](#enabling-the-packages-feature "Permalink") + +**注意:**启用"软件包"功能后,默认情况下,存储库可用于所有新项目. 要为现有项目启用它,用户将必须在项目的设置中明确启用它. + +要启用包功能: + +**所有装置 GitLab** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下行: + + ``` + gitlab_rails['packages_enabled'] = true + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure "如何重新配置​​Omnibus GitLab")以使更改生效. + +**从源安装** + +1. 安装完成后,您将必须在`config/gitlab.yml`中`config/gitlab.yml` `packages`部分. 设置为`true`以启用它: + + ``` + packages: + enabled: true + ``` + +2. [重新启动 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure "如何重新配置​​Omnibus GitLab")以使更改生效. + +## Changing the storage path[](#changing-the-storage-path "Permalink") + +默认情况下,程序包存储在本地,但是您可以更改默认的本地位置,甚至使用对象存储. + +### Changing the local storage path[](#changing-the-local-storage-path "Permalink") + +用于 Omnibus GitLab 安装的软件包存储在`/var/opt/gitlab/gitlab-rails/shared/packages/`而用于源安装的`shared/packages/`在`shared/packages/` (相对于 Git 主目录). 更改本地存储路径: + +**所有装置 GitLab** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下行: + + ``` + gitlab_rails['packages_storage_path'] = "/mnt/packages" + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 编辑`config/gitlab.yml`的`packages`部分: + + ``` + packages: + enabled: true + storage_path: shared/packages + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +### Using object storage[](#using-object-storage "Permalink") + +您可以使用对象存储来存储程序包,而不必依赖于本地存储. + +[Read more about using object storage with GitLab](../object_storage.html). + +**注意:**我们建议使用[统一对象存储设置](../object_storage.html#consolidated-object-storage-configuration) . 以下说明适用于原始配置格式. + +**Omnibus GitLab installations** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下行(必要时取消注释): + + ``` + gitlab_rails['packages_enabled'] = true + gitlab_rails['packages_storage_path'] = "/var/opt/gitlab/gitlab-rails/shared/packages" + gitlab_rails['packages_object_store_enabled'] = true + gitlab_rails['packages_object_store_remote_directory'] = "packages" # The bucket name. + gitlab_rails['packages_object_store_direct_upload'] = false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false). + gitlab_rails['packages_object_store_background_upload'] = true # Temporary option to limit automatic upload (Default: true). + gitlab_rails['packages_object_store_proxy_download'] = false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage. + gitlab_rails['packages_object_store_connection'] = { + ## + ## If the provider is AWS S3, uncomment the following + ## + #'provider' => 'AWS', + #'region' => 'eu-west-1', + #'aws_access_key_id' => 'AWS_ACCESS_KEY_ID', + #'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY', + ## + ## If the provider is other than AWS (an S3-compatible one), uncomment the following + ## + #'host' => 's3.amazonaws.com', + #'aws_signature_version' => 4 # For creation of signed URLs. Set to 2 if provider does not support v4. + #'endpoint' => 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces. + #'path_style' => false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'. + } + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 编辑`config/gitlab.yml`的`packages`部分(必要时取消注释): + + ``` + packages: + enabled: true + ## + ## The location where build packages are stored (default: shared/packages). + ## + #storage_path: shared/packages + object_store: + enabled: false + remote_directory: packages # The bucket name. + #direct_upload: false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false). + #background_upload: true # Temporary option to limit automatic upload (Default: true). + #proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage. + connection: + ## + ## If the provider is AWS S3, uncomment the following + ## + #provider: AWS + #region: us-east-1 + #aws_access_key_id: AWS_ACCESS_KEY_ID + #aws_secret_access_key: AWS_SECRET_ACCESS_KEY + ## + ## If the provider is other than AWS (an S3-compatible one), uncomment the following + ## + #host: 's3.amazonaws.com' # default: s3.amazonaws.com. + #aws_signature_version: 4 # For creation of signed URLs. Set to 2 if provider does not support v4. + #endpoint: 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces. + #path_style: false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'. + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +### Migrating local packages to object storage[](#migrating-local-packages-to-object-storage "Permalink") + +[配置对象存储后](#using-object-storage) ,您可以使用以下任务将现有程序包从本地存储迁移到远程存储. 该处理将在后台工作人员中完成, **无需停机** . + +对于所有 GitLab; + +``` +sudo gitlab-rake "gitlab:packages:migrate" +``` + +对于源安装: + +``` +RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:packages:migrate +``` \ No newline at end of file diff --git a/docs/487.md b/docs/487.md new file mode 100644 index 0000000000000000000000000000000000000000..0fd5007c876aa1bfa1ba92a74f26c7172d3b8178 --- /dev/null +++ b/docs/487.md @@ -0,0 +1,1041 @@ +# GitLab Container Registry administration + +> 原文:[https://docs.gitlab.com/ee/administration/packages/container_registry.html](https://docs.gitlab.com/ee/administration/packages/container_registry.html) + +* [Enable the Container Registry](#enable-the-container-registry) +* [Container Registry domain configuration](#container-registry-domain-configuration) + * [Configure Container Registry under an existing GitLab domain](#configure-container-registry-under-an-existing-gitlab-domain) + * [Configure Container Registry under its own domain](#configure-container-registry-under-its-own-domain) +* [Disable Container Registry site-wide](#disable-container-registry-site-wide) +* [Disable Container Registry for new projects site-wide](#disable-container-registry-for-new-projects-site-wide) +* [Configure storage for the Container Registry](#configure-storage-for-the-container-registry) + * [Use filesystem](#use-filesystem) + * [Use object storage](#use-object-storage) + * [Migrate to object storage without downtime](#migrate-to-object-storage-without-downtime) + * [Disable redirect for storage driver](#disable-redirect-for-storage-driver) + * [Storage limitations](#storage-limitations) +* [Change the registry’s internal port](#change-the-registrys-internal-port) +* [Disable Container Registry per project](#disable-container-registry-per-project) +* [Use an external container registry with GitLab as an auth endpoint](#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint) +* [Configure Container Registry notifications](#configure-container-registry-notifications) +* [Container Registry garbage collection](#container-registry-garbage-collection) + * [Understanding the content-addressable layers](#understanding-the-content-addressable-layers) + * [Recycling unused tags](#recycling-unused-tags) + * [Removing unused layers not referenced by manifests](#removing-unused-layers-not-referenced-by-manifests) + * [Performing garbage collection without downtime](#performing-garbage-collection-without-downtime) + * [Running the garbage collection on schedule](#running-the-garbage-collection-on-schedule) +* [Troubleshooting](#troubleshooting) + * [Using self-signed certificates with Container Registry](#using-self-signed-certificates-with-container-registry) + * [`unauthorized: authentication required` when pushing large images](#unauthorized-authentication-required-when-pushing-large-images) + * [AWS S3 with the GitLab registry error when pushing large images](#aws-s3-with-the-gitlab-registry-error-when-pushing-large-images) + * [Supporting older Docker clients](#supporting-older-docker-clients) + * [Docker connection error](#docker-connection-error) + * [Image push errors](#image-push-errors) + * [Enable the Registry debug server](#enable-the-registry-debug-server) + * [Advanced Troubleshooting](#advanced-troubleshooting) + * [Unexpected 403 error during push](#unexpected-403-error-during-push) + * [mitmproxy](#mitmproxy) + * [Running the Docker daemon with a proxy](#running-the-docker-daemon-with-a-proxy) + * [Running the Docker client](#running-the-docker-client) + +# GitLab Container Registry administration[](#gitlab-container-registry-administration "Permalink") + +Version history + +* 在 GitLab 8.8 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4040) . +* 在 GitLab 8.9 中添加了对 Container Registry manifest `v1`支持,以支持 1.10 之前的 Docker 版本. + +**注意:**本文档是管理员指南. 要了解如何使用 GitLab 容器注册表,请参阅[用户文档](../../user/packages/container_registry/index.html) . + +通过将容器注册表集成到 GitLab 中,每个项目都可以拥有自己的空间来存储其 Docker 映像. + +您可以在[https://docs.docker.com/registry/introduction/上](https://s0docs0docker0com.icopy.site/registry/introduction/)了解有关 Docker 注册表的更多信息. + +## Enable the Container Registry[](#enable-the-container-registry "Permalink") + +**所有装置 GitLab** + +如果您使用 Omnibus 安装包安装了 GitLab,则默认情况下容器注册表可能可用或可能不可用. + +如果出现以下情况,容器注册表将自动启用,并在您的 GitLab 域上的端口 5050 上可用: + +* 您正在使用内置的[Let's Encrypt 集成](https://docs.gitlab.com/omnibus/settings/ssl.html) ,并且 +* 您使用的是 GitLab 12.5 或更高版本. + +否则,不会启用容器注册表. 要启用它: + +* 您可以为您的[GitLab 域](#configure-container-registry-under-an-existing-gitlab-domain)配置它,或者 +* 您可以为[其他域](#configure-container-registry-under-its-own-domain)配置它. + +**注意:**默认情况下,容器注册表在 HTTPS 下工作. 您可以使用 HTTP,但不建议使用 HTTP,它不在本文档的讨论范围之内. 如果要实现此目的,请阅读[不安全的注册表文档](https://s0docs0docker0com.icopy.site/registry/insecure/) . + +**从源安装** + +如果您从源代码安装了 GitLab: + +1. 您将必须自己[安装注册表](https://s0docs0docker0com.icopy.site/registry/deploying/) . +2. 安装完成后,您必须在`gitlab.yml`中配置注册表的设置才能启用它. +3. 使用在[`lib/support/nginx/registry-ssl`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/support/nginx/registry-ssl)下找到的示例 NGINX 配置文件,并对其进行编辑以匹配`host` , `port`和 TLS 证书路径. + +`gitlab.yml`的内容是: + +``` +registry: + enabled: true + host: registry.gitlab.example.com + port: 5005 + api_url: http://localhost:5000/ + key: config/registry.key + path: shared/registry + issuer: gitlab-issuer +``` + +where: + +| Parameter | Description | +| --- | --- | +| `enabled` | `true` `false` . 在 GitLab 中启用注册表. 默认情况下为`false` . | +| `host` | 注册表将在其下运行的主机 URL,并且用户将可以使用该 URL. | +| `port` | 外部注册表域将在其上侦听的端口. | +| `api_url` | The internal API URL under which the Registry is exposed to. It defaults to `http://localhost:5000`. | +| `key` | 私钥位置是一对 Registry 的`rootcertbundle` . 阅读[令牌身份验证配置文档](https://s0docs0docker0com.icopy.site/registry/configuration/) . | +| `path` | 该目录应与 Registry 的`rootdirectory`指定的目录相同. 阅读[存储配置文档](https://s0docs0docker0com.icopy.site/registry/configuration/) . GitLab 用户,Web 服务器用户和注册表用户必须可读此路径. 在[#configure-container-for-container-registry 中](#configure-storage-for-the-container-registry)了解更多信息. | +| `issuer` | This should be the same value as configured in Registry’s `issuer`. Read the [token auth configuration documentation](https://s0docs0docker0com.icopy.site/registry/configuration/). | + +**注意:**如果从源代码安装,则 GitLab 不会随附注册表初始化文件. 因此,如果您修改注册表, [重新启动 GitLab](../restart_gitlab.html#installations-from-source)将不会重新启动注册表. 阅读有关如何实现这一目标的上游文档. + +**绝对**要确保您的[注册表配置](https://s0docs0docker0com.icopy.site/registry/configuration/)将`container_registry`作为服务,并将`https://gitlab.example.com/jwt/auth`作为领域: + +``` +auth: + token: + realm: https://gitlab.example.com/jwt/auth + service: container_registry + issuer: gitlab-issuer + rootcertbundle: /root/certs/certbundle +``` + +**注意:**如果未设置`auth` ,则用户无需身份验证即可拉取 Docker 映像. + +## Container Registry domain configuration[](#container-registry-domain-configuration "Permalink") + +There are two ways you can configure the Registry’s external domain. Either: + +* [使用现有的 GitLab 域](#configure-container-registry-under-an-existing-gitlab-domain) ,在这种情况下,注册表将不得不侦听端口并重用 GitLab 的 TLS 证书, +* [将完全独立的域](#configure-container-registry-under-its-own-domain)与该[域](#configure-container-registry-under-its-own-domain)的新 TLS 证书一起使用. + +由于容器注册表需要 TLS 证书,所以最终归结为获得新证书的难易程度或代价. + +在首次配置 Container Registry 之前,请考虑到这一点. + +### Configure Container Registry under an existing GitLab domain[](#configure-container-registry-under-an-existing-gitlab-domain "Permalink") + +如果将注册表配置为使用现有的 GitLab 域,则可以在端口上公开注册表,以便可以重复使用现有的 GitLab TLS 证书. + +假设 GitLab 域是`https://gitlab.example.com` ,注册表暴露给外界的端口是`5050` ,如果您正在使用 Omnibus GitLab,则需要在`gitlab.rb`或`gitlab.yml`进行设置或分别从源代码安装 GitLab. + +**注意:**请小心选择与注册表侦听的端口不同的端口(默认为`5000` ),否则您将遇到冲突. + +**所有装置 GitLab** + +1. 您的`/etc/gitlab/gitlab.rb`应该包含注册表 URL 以及 GitLab 使用的现有 TLS 证书和密钥的路径: + + ``` + registry_external_url 'https://gitlab.example.com:5050' + ``` + + 请注意, `registry_external_url`如何在现有 GitLab URL 下的 HTTPS 上侦听,但在其他端口上. + + 如果您的 TLS 证书不在`/etc/gitlab/ssl/gitlab.example.com.crt`并且密钥不在`/etc/gitlab/ssl/gitlab.example.com.key`取消注释以下行: + + ``` + registry_nginx['ssl_certificate'] = "/path/to/certificate.pem" + registry_nginx['ssl_certificate_key'] = "/path/to/certificate.key" + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +3. 验证使用: + + ``` + openssl s_client -showcerts -servername gitlab.example.com -connect gitlab.example.com:5050 > cacert.pem + ``` + +**注意:**如果您的证书提供者提供了 CA Bundle 证书,则将它们附加到 TLS 证书文件中. + +**从源安装** + +1. 打开`/home/git/gitlab/config/gitlab.yml` ,找到`registry`项,并使用以下设置进行配置: + + ``` + registry: + enabled: true + host: gitlab.example.com + port: 5050 + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. +3. 还要在 NGINX 中进行相关更改(域,端口,TLS 证书路径). + +用户现在应该可以使用以下命令使用其 GitLab 凭据登录到 Container Registry: + +``` +docker login gitlab.example.com:5050 +``` + +### Configure Container Registry under its own domain[](#configure-container-registry-under-its-own-domain "Permalink") + +如果将注册表配置为使用其自己的域,则将需要该特定域的 TLS 证书(例如, `registry.example.com` ),或者如果托管在现有 GitLab 域的子域(例如, `registry.example.com` )下,则可能需要通配符证书`registry.gitlab.example.com` ). + +**注意:**除手动生成的 SSL 证书(在此处说明)外, [Omnibus 安装](https://docs.gitlab.com/omnibus/settings/ssl.html)还[支持](https://docs.gitlab.com/omnibus/settings/ssl.html)由 Let's Encrypt 自动生成的证书. + +假设您希望在`https://registry.gitlab.example.com`上访问容器注册表. + +**所有装置 GitLab** + +1. 将您的 TLS 证书和密钥放在`/etc/gitlab/ssl/registry.gitlab.example.com.crt`和`/etc/gitlab/ssl/registry.gitlab.example.com.key` ,并确保它们具有正确的权限: + + ``` + chmod 600 /etc/gitlab/ssl/registry.gitlab.example.com.* + ``` + +2. TLS 证书到位后,使用以下命令编辑`/etc/gitlab/gitlab.rb` : + + ``` + registry_external_url 'https://registry.gitlab.example.com' + ``` + + 请注意, `registry_external_url`如何在 HTTPS 上进行侦听. + +3. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +如果您具有[通配符证书](https://en.wikipedia.org/wiki/Wildcard_certificate) ,则除了 URL 外,还需要指定证书的路径,在这种情况下,/ `/etc/gitlab/gitlab.rb`将如下所示: + +``` +registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/certificate.pem" +registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/certificate.key" +``` + +**从源安装** + +1. 打开`/home/git/gitlab/config/gitlab.yml` ,找到`registry`项,并使用以下设置进行配置: + + ``` + registry: + enabled: true + host: registry.gitlab.example.com + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. +3. 还要在 NGINX 中进行相关更改(域,端口,TLS 证书路径). + +用户现在应该能够使用其 GitLab 凭据登录到 Container Registry: + +``` +docker login registry.gitlab.example.com +``` + +## Disable Container Registry site-wide[](#disable-container-registry-site-wide "Permalink") + +**注意:**按照以下步骤在 Rails GitLab 应用程序中禁用注册表,不会删除任何现有的 Docker 映像. 这由注册表应用程序本身处理. + +**所有的 GitLab** + +1. 打开`/etc/gitlab/gitlab.rb`并将`registry['enable']`为`false` : + + ``` + registry['enable'] = false + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 打开`/home/git/gitlab/config/gitlab.yml` ,找到`registry`项并将其设置`enabled`以`false` : + + ``` + registry: + enabled: false + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +## Disable Container Registry for new projects site-wide[](#disable-container-registry-for-new-projects-site-wide "Permalink") + +如果启用了容器注册表,那么它将在所有新项目中可用. 要禁用此功能并使项目的所有者自行启用容器注册表,请按照以下步骤操作. + +**所有装置 GitLab** + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下行: + + ``` + gitlab_rails['gitlab_default_projects_features_container_registry'] = false + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 打开`/home/git/gitlab/config/gitlab.yml` ,找到`default_projects_features`条目并进行配置,以便`container_registry`设置为`false` : + + ``` + ## Default project features settings + default_projects_features: + issues: true + merge_requests: true + wiki: true + snippets: false + builds: true + container_registry: false + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +## Configure storage for the Container Registry[](#configure-storage-for-the-container-registry "Permalink") + +您可以通过配置存储驱动程序来将 Container Registry 配置为使用各种存储后端. 默认情况下,GitLab 容器注册表配置为使用[文件系统驱动程序](#use-filesystem)配置. + +支持的不同驱动程序是: + +| Driver | Description | +| --- | --- | +| filesystem | 使用本地文件系统上的路径 | +| Azure | Microsoft Azure Blob 存储 | +| gcs | 谷歌云存储 | +| s3 | Amazon Simple Storage Service. 确保使用正确的[S3 权限范围](https://s0docs0docker0com.icopy.site/registry/storage-drivers/s3/)配置存储桶. | +| swift | OpenStack Swift 对象存储 | +| oss | 阿里云 OSS | + +在[Docker Registry 文档中](https://s0docs0docker0com.icopy.site/registry/configuration/)阅读有关单个驱动程序配置选项的更多信息. + +### Use filesystem[](#use-filesystem "Permalink") + +如果要将图像存储在文件系统上,则可以更改 Container Registry 的存储路径,请按照以下步骤操作. + +此路径可用于: + +* 运行容器注册表守护程序的用户. +* 运行 GitLab 的用户. + +**警告:**您应该确认所有的 GitLab,注册表和 Web 服务器用户都可以访问该目录. + +**所有装置 GitLab** + +在 Omnibus 中存储图像的默认位置是`/var/opt/gitlab/gitlab-rails/shared/registry` . 要更改它: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitlab_rails['registry_path'] = "/path/to/registry/storage" + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +在源安装中存储映像的默认位置是`/home/git/gitlab/shared/registry` . 要更改它: + +1. 打开`/home/git/gitlab/config/gitlab.yml` ,找到`registry`项并更改`path`设置: + + ``` + registry: + path: shared/registry + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +### Use object storage[](#use-object-storage "Permalink") + +如果要将图像存储在对象存储中,则可以更改 Container Registry 的存储驱动程序. + +[Read more about using object storage with GitLab](../object_storage.html). + +**警告:** GitLab 不会备份未存储在文件系统上的 Docker 映像. 请记住,如果需要,请与您的对象存储提供程序一起启用备份.**注:** `regionendpoint`配置 S3 兼容的服务,如 MinIO 时才需要. 它采用一个 URL,例如`http://127.0.0.1:9000` . + +**所有装置 GitLab** + +在 Omnibus 中配置`s3`存储驱动程序: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['storage'] = { + 's3' => { + 'accesskey' => 's3-access-key', + 'secretkey' => 's3-secret-key-for-access-key', + 'bucket' => 'your-s3-bucket', + 'region' => 'your-s3-region', + 'regionendpoint' => 'your-s3-regionendpoint' + } + } + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**注意:** `your-s3-bucket`应该仅是存在的存储桶的名称,并且不能包含子目录. + +**从源安装** + +存储驱动程序的配置在[部署 Docker 注册表](https://s0docs0docker0com.icopy.site/registry/deploying/)时创建的注册表配置 YML 文件中完成. + +`s3`存储驱动程序示例: + +``` +storage: + s3: + accesskey: 's3-access-key' + secretkey: 's3-secret-key-for-access-key' + bucket: 'your-s3-bucket' + region: 'your-s3-region' + regionendpoint: 'your-s3-regionendpoint' + cache: + blobdescriptor: inmemory + delete: + enabled: true +``` + +**注意:** `your-s3-bucket`应该仅是存在的存储桶的名称,并且不能包含子目录. + +#### Migrate to object storage without downtime[](#migrate-to-object-storage-without-downtime "Permalink") + +若要在不停止 Container Registry 的情况下迁移存储,请将 Container Registry 设置为只读模式. 在大型实例上,这可能需要将 Container Registry 置于只读模式一段时间. 在此期间,您可以从 Container Registry 中拉出,但不能推送. + +1. 可选:要减少要迁移的数据量,请运行[垃圾收集工具,而无需停机](#performing-garbage-collection-without-downtime) . +2. 例如,使用 AWS CLI [`cp`](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/cp.html)或[`sync`](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/sync.html)命令将初始数据复制到 S3 存储桶. 确保将`docker`文件夹保留为存储桶中的顶级文件夹. + + ``` + aws s3 sync registry s3://mybucket + ``` + +3. 为了使更改生效, [请将 Container Registry 设置为`read-only`模式,](#performing-garbage-collection-without-downtime)然后[重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure) . +4. 将自初始数据加载以来的所有更改同步到 S3 存储桶,并删除目标存储桶中存在但源文件中不存在的文件: + + ``` + aws s3 sync registry s3://mybucket --delete + ``` + + **危险:** `--delete`标志将删除存在于目标而不是在源文件中. 确保不交换源和目标,否则您将删除注册表中的所有数据. +5. 将注册表配置为使用 S3 存储桶进行存储. +6. For the changes to take effect, set the Registry back to `read-write` mode and [reconfigure GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure). + +### Disable redirect for storage driver[](#disable-redirect-for-storage-driver "Permalink") + +默认情况下,访问配置了远程后端的注册表的用户将重定向到存储驱动程序的默认后端. 例如,可以使用`s3`存储驱动程序配置注册表,该驱动程序将请求重定向到远程 S3 存储桶以减轻 GitLab 服务器上的负载. + +但是,对于通常无法访问公共服务器的内部主机使用的注册表,此行为是不希望的. 要禁用重定向和[代理下载](../object_storage.html#proxy-download) ,请按如下所示将`disable`标志设置为 true. 这使得所有流量始终通过注册表服务. 这样可以提高安全性(由于无法公开访问存储后端,从而减少了表面攻击),但性能却较差(所有流量都通过服务重定向). + +**所有装置 GitLab** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['storage'] = { + 's3' => { + 'accesskey' => 's3-access-key', + 'secretkey' => 's3-secret-key-for-access-key', + 'bucket' => 'your-s3-bucket', + 'region' => 'your-s3-region', + 'regionendpoint' => 'your-s3-regionendpoint' + }, + 'redirect' => { + 'disable' => true + } + } + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 将`redirect`标志添加到您的注册表配置 YML 文件中: + + ``` + storage: + s3: + accesskey: 'AKIAKIAKI' + secretkey: 'secret123' + bucket: 'gitlab-registry-bucket-AKIAKIAKI' + region: 'your-s3-region' + regionendpoint: 'your-s3-regionendpoint' + redirect: + disable: true + cache: + blobdescriptor: inmemory + delete: + enabled: true + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +### Storage limitations[](#storage-limitations "Permalink") + +当前,没有存储限制,这意味着用户可以上传无限数量的任意大小的 Docker 映像. 此设置将在以后的版本中进行配置. + +## Change the registry’s internal port[](#change-the-registrys-internal-port "Permalink") + +**注意:**请勿将此与 GitLab 本身用于向世界展示注册表的端口混淆. + +默认情况下,Registry Server 在端口`5000`上的 localhost 上侦听,这是 Registry Server 应接受其连接的地址. 在下面的示例中,我们将注册表的端口设置为`5001` . + +**所有的 GitLab** + +1. 打开`/etc/gitlab/gitlab.rb`并设置`registry['registry_http_addr']` : + + ``` + registry['registry_http_addr'] = "localhost:5001" + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 打开您的注册表服务器的配置文件,然后编辑[`http:addr`](https://s0docs0docker0com.icopy.site/registry/configuration/)值: + + ``` + http + addr: localhost:5001 + ``` + +2. 保存文件并重新启动注册表服务器. + +## Disable Container Registry per project[](#disable-container-registry-per-project "Permalink") + +如果在您的 GitLab 实例中启用了注册表,但是您的项目不需要它,则可以从项目的设置中禁用它. 阅读有关如何实现此目的的用户指南. + +## Use an external container registry with GitLab as an auth endpoint[](#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint "Permalink") + +**注意:**在使用外部容器注册表时,与容器注册表相关联的某些功能可能不可用或存在[固有风险](./../../user/packages/container_registry/index.html#use-with-external-container-registries) + +**所有的 GitLab** + +您可以将 GitLab 用作具有外部容器注册表的身份验证端点. + +1. 打开`/etc/gitlab/gitlab.rb`并设置必要的配置: + + ``` + gitlab_rails['registry_enabled'] = true + gitlab_rails['registry_api_url'] = "http://localhost:5000" + gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer" + ``` + + **注意:**启用 GitLab 的 Container Registry 功能和身份验证端点需要`gitlab_rails['registry_enabled'] = true` . 即使启用了它,也不会启动 GitLab 捆绑的 Container Registry 服务. +2. 证书密钥对是 GitLab 和外部容器注册表进行安全通信所必需的. 您将需要创建一个证书密钥对,使用公共证书配置外部容器注册表,并使用私钥配置 GitLab. 为此,将以下内容添加到`/etc/gitlab/gitlab.rb` : + + ``` + # registry['internal_key'] should contain the contents of the custom key + # file. Line breaks in the key file should be marked using `\n` character + # Example: + registry['internal_key'] = "---BEGIN RSA PRIVATE KEY---\nMIIEpQIBAA\n" + + # Optionally define a custom file for Omnibus GitLab to write the contents + # of registry['internal_key'] to. + gitlab_rails['registry_key_path'] = "/custom/path/to/registry-key.key" + ``` + + **注意:**每次执行重新配置时,都会使用`internal_key`指定的内容填充`registry_key_path`指定的文件. 如果未指定文件,则 Omnibus GitLab 会将其默认设置为`/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key`并将其填充. +3. 要更改在 GitLab 容器注册表页面中显示的容器注册表 URL,请设置以下配置: + + ``` + gitlab_rails['registry_host'] = "registry.gitlab.example.com" + gitlab_rails['registry_port'] = "5005" + ``` + +4. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +1. 打开`/home/git/gitlab/config/gitlab.yml` ,然后在`registry`下编辑配置设置: + + ``` + ## Container Registry + + registry: + enabled: true + host: "registry.gitlab.example.com" + port: "5005" + api_url: "http://localhost:5000" + path: /var/opt/gitlab/gitlab-rails/shared/registry + key: /var/opt/gitlab/gitlab-rails/certificate.key + issuer: omnibus-gitlab-issuer + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +## Configure Container Registry notifications[](#configure-container-registry-notifications "Permalink") + +您可以将 Container Registry 配置为发送 Webhook 通知,以响应注册表中发生的事件. + +在[Docker Registry 通知文档中](https://s0docs0docker0com.icopy.site/registry/notifications/)阅读有关 Container Registry 通知配置选项的更多信息. + +**注意:**可以为 Container Registry 配置多个端点. + +**所有装置 GitLab** + +要在 Omnibus 中配置通知端点: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['notifications'] = [ + { + 'name' => 'test_endpoint', + 'url' => 'https://gitlab.example.com/notify', + 'timeout' => '500ms', + 'threshold' => 5, + 'backoff' => '1s', + 'headers' => { + "Authorization" => ["AUTHORIZATION_EXAMPLE_TOKEN"] + } + } + ] + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**从源安装** + +在[部署 Docker 注册表](https://s0docs0docker0com.icopy.site/registry/deploying/)时创建的注册表配置 YML 文件中完成了通知端点的配置. + +Example: + +``` +notifications: + endpoints: + - name: alistener + disabled: false + url: https://my.listener.com/event + headers: + timeout: 500 + threshold: 5 + backoff: 1000 +``` + +## Container Registry garbage collection[](#container-registry-garbage-collection "Permalink") + +**注意:**仅当您通过 Omnibus 软件包或[云本机图表](https://docs.gitlab.com/charts/charts/registry/)安装了 GitLab 时,垃圾收集工具才可用.**危险:**通过运行内置的垃圾收集命令,将导致 Container Registry 停机. 如果在其他实例之一仍在写入注册表存储的环境中的某个实例上运行此命令,则将删除引用的清单. 为避免这种情况,请确保在继续[操作](#performing-garbage-collection-without-downtime)之前将注册表设置为[只读模式](#performing-garbage-collection-without-downtime) . + +容器注册表可以使用大量的磁盘空间. 为了清除一些未使用的层,注册表包括一个垃圾收集命令. + +GitLab 提供了一组 API 来操作 Container Registry 并协助删除未使用标签的过程. 当前,这是使用 API​​公开的,但是将来,这些控件将被迁移到 GitLab 接口. + +项目维护者可以根据自己的标准定期[删除大量的 Container Registry 标签](../../api/container_registry.html#delete-registry-repository-tags-in-bulk) ,但是,这本身并不会回收数据,它只会使清单和图像斑点之间的链接断开. 要在整个 GitLab 实例中回收 Container Registry 数据,可以使用`gitlab-ctl`提供的内置命令. + +### Understanding the content-addressable layers[](#understanding-the-content-addressable-layers "Permalink") + +请考虑以下示例,该示例是您首先构建映像的地方: + +``` +# This builds a image with content of sha256:111111 +docker build -t my.registry.com/my.group/my.project:latest . +docker push my.registry.com/my.group/my.project:latest +``` + +现在,您要使用新版本覆盖`:latest` : + +``` +# This builds a image with content of sha256:222222 +docker build -t my.registry.com/my.group/my.project:latest . +docker push my.registry.com/my.group/my.project:latest +``` + +现在, `:latest`标记指向`sha256:222222` . 但是,由于注册表的体系结构,即使不再通过`:latest`标记也可以直接访问图像`my.registry.com/my.group/my.project@sha256:111111` ,仍可以访问此数据. + +### Recycling unused tags[](#recycling-unused-tags "Permalink") + +> 在所有 GitLab 8.12 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/987) . + +在运行内置命令之前,需要注意一些注意事项: + +* 内置命令将在启动垃圾收集之前停止注册表. +* 垃圾收集命令需要一些时间才能完成,具体取决于存在的数据量. +* 如果更改了注册表配置文件的位置,则需要指定其路径. +* After the garbage collection is done, the registry should start up automatically. + +如果未更改配置文件的默认位置,请运行: + +``` +sudo gitlab-ctl registry-garbage-collect +``` + +该命令将花费一些时间来完成,具体取决于您存储的层数. + +如果更改了 Container Registry `config.yml`的位置: + +``` +sudo gitlab-ctl registry-garbage-collect /path/to/config.yml +``` + +您也可以[删除所有未引用的清单](#removing-unused-layers-not-referenced-by-manifests) ,尽管这是一种更具破坏性的操作,您应该首先了解其含义. + +### Removing unused layers not referenced by manifests[](#removing-unused-layers-not-referenced-by-manifests "Permalink") + +> 在所有 GitLab 11.10 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/3097) . + +**危险:**这是破坏性的操作. + +GitLab 容器注册表遵循与 Docker Distribution 相同的默认工作流程:保留所有层,即使是未直接引用的层也允许使用上下文可寻址标识符访问所有内容. + +但是,在大多数工作流程中,如果注册表标记未直接引用旧层,则您不必在意这些旧层. `registry-garbage-collect`命令支持`-m`开关,以允许您删除所有不能通过`tag`直接访问的未引用清单和层: + +``` +sudo gitlab-ctl registry-garbage-collect -m +``` + +由于这是更具破坏性的操作,因此默认情况下将禁用此行为. 您可能期望这种操作方式,但是在执行此操作之前,请确保已备份所有注册表数据. + +### Performing garbage collection without downtime[](#performing-garbage-collection-without-downtime "Permalink") + +在 GitLab 8.8 中[引入](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/764) . + +通过将其置于只读模式并且不使用内置命令,可以在不停止 Container Registry 的情况下执行垃圾回收. 在大型实例中,这可能需要 Container Registry 处于只读模式一段时间. 在这段时间中,您将能够从 Container Registry 中拉出,但不能进行推送. + +**注意:**默认情况下, [注册表存储路径](#configure-storage-for-the-container-registry)为`/var/opt/gitlab/gitlab-rails/shared/registry` . + +要启用只读模式: + +1. 在`/etc/gitlab/gitlab.rb` ,指定只读模式: + + ``` + registry['storage'] = { + 'filesystem' => { + 'rootdirectory' => "" + }, + 'maintenance' => { + 'readonly' => { + 'enabled' => true + } + } + } + ``` + +2. 保存并重新配置 GitLab: + + ``` + sudo gitlab-ctl reconfigure + ``` + + 这会将 Container Registry 设置为只读模式. + +3. 接下来,触发垃圾收集命令之一: + + ``` + # Recycling unused tags + sudo /opt/gitlab/embedded/bin/registry garbage-collect /var/opt/gitlab/registry/config.yml + + # Removing unused layers not referenced by manifests + sudo /opt/gitlab/embedded/bin/registry garbage-collect -m /var/opt/gitlab/registry/config.yml + ``` + + 这将开始垃圾收集,这可能需要一些时间才能完成. + +4. 完成后,在`/etc/gitlab/gitlab.rb`更改回读写模式: + + ``` + registry['storage'] = { + 'filesystem' => { + 'rootdirectory' => "" + }, + 'maintenance' => { + 'readonly' => { + 'enabled' => false + } + } + } + ``` + +5. 保存并重新配置 GitLab: + + ``` + sudo gitlab-ctl reconfigure + ``` + +### Running the garbage collection on schedule[](#running-the-garbage-collection-on-schedule "Permalink") + +理想情况下,您希望在不使用注册表的情况下每周定期运行注册表的垃圾回收. 最简单的方法是添加一个新的 crontab 作业,该作业将每周定期运行一次. + +在`/etc/cron.d/registry-garbage-collect`下创建一个文件: + +``` +SHELL=/bin/sh +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +# Run every Sunday at 04:05am +5 4 * * 0 root gitlab-ctl registry-garbage-collect +``` + +## Troubleshooting[](#troubleshooting "Permalink") + +在深入探讨以下部分之前,请先进行一些基本的故障排除: + +1. 检查并确保 Docker 客户端和 GitLab 服务器上的系统时钟已同步(例如,通过 NTP). + +2. 如果使用的是 S3 支持的注册表,请仔细检查 IAM 权限和 S3 凭据(包括区域)是否正确. 有关更多详细信息,请参阅[示例 IAM 策略](https://s0docs0docker0com.icopy.site/registry/storage-drivers/s3/) . + +3. 检查注册表日志(例如`/var/log/gitlab/registry/current` )和 GitLab 生产日志中的错误(例如`/var/log/gitlab/gitlab-rails/production.log` ). 您也许可以在那里找到线索. + +### Using self-signed certificates with Container Registry[](#using-self-signed-certificates-with-container-registry "Permalink") + +如果您在容器注册表中使用自签名证书,则在 CI 作业期间可能会遇到如下问题: + +``` +Error response from daemon: Get registry.example.com/v1/users/: x509: certificate signed by unknown authority +``` + +运行该命令的 Docker 守护程序需要由公认的 CA 签名的证书,因此会出现上述错误. + +虽然 GitLab 不使用自签名的证书与集装箱注册表支持开箱即用,它可以使其工作的[指示多克尔守护信任自签名证书](https://s0docs0docker0com.icopy.site/registry/insecure/) ,安装多克尔守护进程,并设置`privileged = false`的跑步者的`config.toml` . 设置`privileged = true`优先于 Docker 守护程序: + +``` + [runners.docker] + image = "ruby:2.6" + privileged = false + volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"] +``` + +有关此的其他信息: [发行 18239](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/18239) . + +### `unauthorized: authentication required` when pushing large images[](#unauthorized-authentication-required-when-pushing-large-images "Permalink") + +错误示例: + +``` +docker push gitlab.example.com/myproject/docs:latest +The push refers to a repository [gitlab.example.com/myproject/docs] +630816f32edb: Preparing +530d5553aec8: Preparing +... +4b0bab9ff599: Waiting +d1c800db26c7: Waiting +42755cf4ee95: Waiting +unauthorized: authentication required +``` + +GitLab 的注册表默认令牌有效期为 5 分钟. 当推送较大的图像或推送时间超过 5 分钟的图像时,用户可能会遇到此错误. + +管理员可以在**管理区域>设置> CI / CD>容器注册表>授权令牌持续时间(分钟)中增加令牌持续时间** . + +### AWS S3 with the GitLab registry error when pushing large images[](#aws-s3-with-the-gitlab-registry-error-when-pushing-large-images "Permalink") + +将 AWS S3 与 GitLab 注册表一起使用时,推送大图像时可能会发生错误. 在注册表日志中查找以下错误: + +``` +level=error msg="response completed with error" err.code=unknown err.detail="unexpected EOF" err.message="unknown error" +``` + +要解决该错误,请在注册表配置中指定一个`chunksize`值. 从`25000000` (25MB)到`50000000` (50MB)之间的值开始. + +**对于所有安装** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['storage'] = { + 's3' => { + 'accesskey' => 'AKIAKIAKI', + 'secretkey' => 'secret123', + 'bucket' => 'gitlab-registry-bucket-AKIAKIAKI', + 'chunksize' => 25000000 + } + } + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**对于源安装** + +1. Edit `config/gitlab.yml`: + + ``` + storage: + s3: + accesskey: 'AKIAKIAKI' + secretkey: 'secret123' + bucket: 'gitlab-registry-bucket-AKIAKIAKI' + chunksize: 25000000 + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +### Supporting older Docker clients[](#supporting-older-docker-clients "Permalink") + +从 GitLab 11.9 开始,我们开始提供 Docker 容器注册表的 2.7.1 版本,默认情况下会禁用 schema1 清单. 如果您仍在使用较旧的 Docker 客户端(1.9 或更早版本),则在推送映像时可能会遇到错误. 有关更多详细信息,请参见[omn​​ibus-4145](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4145) . + +您可以添加配置选项以实现向后兼容. + +**对于所有安装** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['compatibility_schema1_enabled'] = true + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**对于源安装** + +1. 编辑[部署注册表](https://s0docs0docker0com.icopy.site/registry/deploying/)时创建的 YML 配置文件. 添加以下代码段: + + ``` + compatibility: + schema1: + enabled: true + ``` + +2. 重新启动注册表以使更改生效. + +### Docker connection error[](#docker-connection-error "Permalink") + +当组,项目或分支名​​称中包含特殊字符时,可能会发生 Docker 连接错误. 特殊字符可以包括: + +* Leading underscore +* 尾随连字符/破折号 +* 双连字符/破折号 + +为了解决这个问题,您可以[更改组路径](../../user/group/index.html#changing-a-groups-path) , [更改项目路径](../../user/project/settings/index.html#renaming-a-repository)或更改分支名称. 另一种选择是创建一个[推送规则,](../../push_rules/push_rules.html)以防止在实例级别上发生这种情况. + +### Image push errors[](#image-push-errors "Permalink") + +当遇到错误或"重试"循环以尝试推送映像但`docker login`正常时,NGINX 将标头转发到注册表可能存在问题. 推荐的默认 NGINX 配置应该可以解决此问题,但是它可能发生在将 SSL 卸载到第三方反向代理的自定义设置中. + +在[Docker 项目](https://github.com/docker/distribution/issues/970)问题中讨论了此问题,一个简单的解决方案是在注册表中启用相对 URL. + +**对于所有安装** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['env'] = { + "REGISTRY_HTTP_RELATIVEURLS" => true + } + ``` + +2. 保存文件并[重新配置 GitLab,](../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**对于源安装** + +1. 编辑[部署注册表](https://s0docs0docker0com.icopy.site/registry/deploying/)时创建的 YML 配置文件. 添加以下代码段: + + ``` + http: + relativeurls: true + ``` + +2. 保存文件并[重新启动 GitLab,](../restart_gitlab.html#installations-from-source)以使更改生效. + +### Enable the Registry debug server[](#enable-the-registry-debug-server "Permalink") + +可以通过在`gitlab.rb`配置中设置注册表调试地址来启用可选的调试服务器. + +``` +registry['debug_addr'] = "localhost:5001" +``` + +添加设置后, [重新配置 GitLab](../restart_gitlab.html#omnibus-gitlab-reconfigure)以应用更改. + +使用 curl 来请求调试服务器的调试输出: + +``` +curl localhost:5001/debug/health +curl localhost:5001/debug/vars +``` + +### Advanced Troubleshooting[](#advanced-troubleshooting "Permalink") + +**注意:**以下部分仅建议专家使用. + +有时,不清楚什么地方出了问题,您可能需要更深入地研究 Docker 客户端与 Registry 之间的通信,以找出问题所在. 过去我们将使用一个具体示例来说明如何诊断 S3 设置中的问题. + +#### Unexpected 403 error during push[](#unexpected-403-error-during-push "Permalink") + +用户试图启用 S3 支持的注册表. `docker login`步骤很好. 但是,推送图像时,输出显示: + +``` +The push refers to a repository [s3-testing.myregistry.com:5050/root/docker-test/docker-image] +dc5e59c14160: Pushing [==================================================>] 14.85 kB +03c20c1a019a: Pushing [==================================================>] 2.048 kB +a08f14ef632e: Pushing [==================================================>] 2.048 kB +228950524c88: Pushing 2.048 kB +6a8ecde4cc03: Pushing [==> ] 9.901 MB/205.7 MB +5f70bf18a086: Pushing 1.024 kB +737f40e80b7f: Waiting +82b57dbc5385: Waiting +19429b698a22: Waiting +9436069b92a3: Waiting +error parsing HTTP 403 response body: unexpected end of JSON input: "" +``` + +这个错误是模棱两可的,因为尚不清楚 403 是来自 GitLab Rails 应用程序,Docker Registry 还是其他东西. 在这种情况下,由于我们知道自成功登录以来,我们可能需要查看客户端与注册表之间的通信. + +[此处描述](https://s0docs0docker0com.icopy.site/registry/spec/api/)了 Docker 客户端和 Registry 之间的 REST API. 通常,人们只会使用 Wireshark 或 tcpdump 捕获流量并查看问题出在哪里. 但是,由于 Docker 客户端和服务器之间的所有通信都是通过 HTTPS 完成的,因此即使您知道私钥,也很难快速解密流量. 我们该怎么办呢? + +一种方法是通过设置[不安全的注册表](https://s0docs0docker0com.icopy.site/registry/insecure/)来禁用 HTTPS. 这可能会引入安全漏洞,仅建议用于本地测试. 如果您有生产系统并且不能或不想这样做,则可以采用另一种方法:使用 mitmproxy,它代表中间代理. + +#### mitmproxy[](#mitmproxy "Permalink") + +[mitmproxy](https://mitmproxy.org/)允许您在客户端和服务器之间放置代理以检查所有流量. 一种麻烦是您的系统需要信任 mitmproxy SSL 证书才能起作用. + +以下安装说明假定您正在运行 Ubuntu: + +1. [Install mitmproxy](https://docs.mitmproxy.org/stable/overview-installation/). +2. 运行`mitmproxy --port 9000`生成其证书. 输入`CTRL` - `C`退出. +3. 将证书从`~/.mitmproxy`安装到您的系统中: + + ``` + sudo cp ~/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/mitmproxy-ca-cert.crt + sudo update-ca-certificates + ``` + +如果成功,输出应表明已添加证书: + +``` +Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done. +Running hooks in /etc/ca-certificates/update.d....done. +``` + +要验证证书是否正确安装,请运行: + +``` +mitmproxy --port 9000 +``` + +这将在端口`9000`上运行 mitmproxy. 在另一个窗口中,运行: + +``` +curl --proxy http://localhost:9000 https://httpbin.org/status/200 +``` + +如果一切设置正确,您将在 mitmproxy 窗口上看到信息,并且 curl 命令没有错误. + +#### Running the Docker daemon with a proxy[](#running-the-docker-daemon-with-a-proxy "Permalink") + +为了使 Docker 通过代理连接,您必须使用适当的环境变量启动 Docker 守护程序. 最简单的方法是关闭 Docker(例如`sudo initctl stop docker` ),然后手动运行 Docker. 以超级用户身份运行: + +``` +export HTTP_PROXY="http://localhost:9000" +export HTTPS_PROXY="https://localhost:9000" +docker daemon --debug +``` + +这将启动 Docker 守护程序并通过 mitmproxy 代理所有连接. + +#### Running the Docker client[](#running-the-docker-client "Permalink") + +现在我们已经运行了 mitmproxy 和 Docker,我们可以尝试登录并推送容器映像. 您可能需要以 root 身份运行才能执行此操作. 例如: + +``` +docker login s3-testing.myregistry.com:5050 +docker push s3-testing.myregistry.com:5050/root/docker-test/docker-image +``` + +In the example above, we see the following trace on the mitmproxy window: + +[![mitmproxy output from Docker](img/c73475715fce01bf6b51edda84064d67.png)](img/mitmproxy-docker.png) + +上图显示: + +* 初始的 PUT 请求可以顺利通过 201 状态代码. +* 201 将客户端重定向到 S3 存储桶. +* 向 AWS 存储桶的 HEAD 请求报告了 403 未经授权. + +这是什么意思? 这强烈表明 S3 用户没有[执行 HEAD 请求](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html)的正确[权限](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html) . 解决方案: [再次](https://s0docs0docker0com.icopy.site/registry/storage-drivers/s3/)检查[IAM 权限](https://s0docs0docker0com.icopy.site/registry/storage-drivers/s3/) . 设置正确的权限后,错误将消失. \ No newline at end of file diff --git a/docs/488.md b/docs/488.md new file mode 100644 index 0000000000000000000000000000000000000000..636c6329e760944e7a62aeafe3de1f57a5fccec7 --- /dev/null +++ b/docs/488.md @@ -0,0 +1,324 @@ +# Replication (Geo) + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/](https://docs.gitlab.com/ee/administration/geo/replication/) + +* [Overview](#overview) +* [Use cases](#use-cases) +* [How it works](#how-it-works) + * [Architecture](#architecture) +* [Requirements for running Geo](#requirements-for-running-geo) + * [Firewall rules](#firewall-rules) + * [LDAP](#ldap) + * [Geo Tracking Database](#geo-tracking-database) + * [Geo Log Cursor](#geo-log-cursor) +* [Setup instructions](#setup-instructions) + * [Using Omnibus GitLab](#using-omnibus-gitlab) +* [Post-installation documentation](#post-installation-documentation) + * [Configuring Geo](#configuring-geo) + * [Updating Geo](#updating-geo) + * [Pausing and resuming replication](#pausing-and-resuming-replication) + * [Configuring Geo for multiple nodes](#configuring-geo-for-multiple-nodes) + * [Configuring Geo with Object Storage](#configuring-geo-with-object-storage) + * [Disaster Recovery](#disaster-recovery) + * [Replicating the Container Registry](#replicating-the-container-registry) + * [Security Review](#security-review) + * [Tuning Geo](#tuning-geo) + * [Set up a location-aware Git URL](#set-up-a-location-aware-git-url) +* [Remove Geo node](#remove-geo-node) +* [Disable Geo](#disable-geo) +* [Current limitations](#current-limitations) + * [Limitations on replication/verification](#limitations-on-replicationverification) +* [Frequently Asked Questions](#frequently-asked-questions) +* [Log files](#log-files) +* [Troubleshooting](#troubleshooting) + +# Replication (Geo)[](#replication-geo-premium-only "Permalink") + +版本历史 + +* 在 GitLab 企业版 8.9 中引入. +* 与组合使用地理[多节点架构](../../reference_architectures/index.html)在考虑**一般可用** (GA) [GitLab 高级](https://about.gitlab.com/pricing/) 10.4\. + +使用 Geo 复制是广泛分布的开发团队的解决方案. + +## Overview[](#overview "Permalink") + +对于远离单个 GitLab 实例的团队而言,获取大型存储库可能需要很长时间. + +Geo 提供您的 GitLab 实例的本地只读实例. 这样可以减少克隆和获取大型存储库所需的时间,从而加快开发速度. + +**注意:**在设置 Geo 之前,请仔细检查[要求](#requirements-for-running-geo) . + +有关 Geo 的视频介绍,请参见[GitLab Geo-GitLab 功能介绍](https://www.youtube.com/watch?v=-HDLxSjEh6w) . + +**注意:**从发布到发布,Geo 进行了重大更改. **支持**升级和[记录](#updating-geo) ,但你应该确保您使用的文件的正确的版本进行安装. + +为确保您使用的文档版本正确,请[在 GitLab.com 上](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/index.md)导航[至此页面的源版本](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/index.md) ,然后从**Switch 分支/标签**下拉列表中选择适当的版本. 例如, [`v11.2.3-ee`](https://gitlab.com/gitlab-org/gitlab/blob/v11.2.3-ee/doc/administration/geo/replication/index.md) . + +## Use cases[](#use-cases "Permalink") + +实施 Geo 具有以下好处: + +* 将分布式开发人员克隆和获取大型存储库和项目所需的时间从几分钟减少到几秒钟. +* 无论您身在何处,都可以使所有开发人员共同贡献想法并并行工作. +* 平衡**主**节点和**辅助**节点之间的只读负载. + +此外,它: + +* 除读取 GitLab Web 界面中可用的任何数据外,还可用于克隆和获取项目(请参阅[当前限制](#current-limitations) ). +* 克服远程办公室之间的慢速连接,通过提高分布式团队的速度来节省时间. +* 帮助减少自动任务,自定义集成和内部工作流程的加载时间. +* 可以在[灾难恢复](../disaster_recovery/index.html)方案中快速故障转移到**辅助**节点. +* 允许[计划的故障转移](../disaster_recovery/planned_failover.html)到**辅助**节点. + +地理位置提供: + +* 只读**辅助**节点:维护一个**主** GitLab 节点,同时仍为每个分布式团队启用只读**辅助**节点. +* 身份验证系统挂钩: **辅助**节点从**主**实例接收所有身份验证数据(例如用户帐户和登录名). +* 直观的用户界面: **辅助**节点使用团队已习惯的相同 Web 界面. 此外,还有可视通知会阻止写操作,并清楚表明用户在**辅助**节点上. + +## How it works[](#how-it-works "Permalink") + +除了读取任何数据外,您的 Geo 实例还可用于克隆和获取项目. 这将使在较大距离上使用大型存储库的速度更快. + +[![Geo overview](img/c17db26d06341055b4834c8be77c604b.png)](img/geo_overview.png) + +启用地理位置后,: + +* 原始实例称为**主要**节点. +* 复制的只读节点称为**辅助**节点. + +请记住: + +* **辅助**节点与**主**节点对话以: + * 获取用于登录的用户数据(API). + * 复制存储库,LFS 对象和附件(HTTPS + JWT). +* 从 GitLab Premium 10.0 开始, **主**节点不再与**辅助**节点对话以通知更改(API). +* [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3 中[引入](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/)了直接推送到**辅助**节点(对于 HTTP 和 SSH,包括 Git LFS). +* 当前的实施存在[局限性](#current-limitations) . + +### Architecture[](#architecture "Permalink") + +下图说明了 Geo 的基础体系结构. + +[![Geo architecture](img/5f13fe556b8940c2e698facdc219d16a.png)](img/geo_architecture.png) + +在此图中: + +* 有**主**节点和一个**辅助**节点的详细信息. +* 只能在**主**节点上执行对数据库的写入. **辅助**节点通过 PostgreSQL 流复制接收数据库更新. +* 如果存在,则应将[LDAP 服务器](#ldap)配置为针对[灾难恢复](../disaster_recovery/index.html)方案进行复制. +* **辅助**节点使用受 JWT 保护的特殊授权对**主要**节点执行不同类型的同步: + * 存储库是通过 HTTPS 上的 Git 克隆/更新的. + * 使用专用 API 端点通过 HTTPS 下载附件,LFS 对象和其他文件. + +从用户执行 Git 操作的角度来看: + +* **主**节点的行为就像一个完整的读写 GitLab 实例. +* **辅助**节点是只读的,但代理 Git 将操作推送到**主**节点. 这使得**辅助**节点似乎本身就支持推送操作. + +为了简化该图,省略了一些必要的组件. 注意: + +* SSH 上的 Git 需要[`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell)和 OpenSSH. +* 通过 HTTPS 进行 Git 时需要[`gitlab-workhorse`](https://gitlab.com/gitlab-org/gitlab-workhorse) . + +请注意, **辅助**节点需要两个不同的 PostgreSQL 数据库: + +* 一个只读数据库实例,用于从 GitLab 主数据库中流式传输数据. +* **辅助**节点在内部使用的[另一个数据库实例](#geo-tracking-database)记录已复制的数据. + +在**辅助**节点中,还有一个附加的守护进程: [Geo Log Cursor](#geo-log-cursor) . + +## Requirements for running Geo[](#requirements-for-running-geo "Permalink") + +要运行 Geo,必须具备以下条件: + +* 支持 OpenSSH 6.9+的操作系统(需要[在数据库中快速查找授权的 SSH 密钥](../../operations/fast_ssh_key_lookup.html) )当前已知版本的 OpenSSH 随附了以下操作系统: + * [CentOS](https://www.centos.org) 7.4 以上 + * [Ubuntu](https://ubuntu.com) 16.04 以上 +* PostgreSQL 11+ with [FDW](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html) support and [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication) +* 转到 2.9+ +* 所有节点必须运行相同的 GitLab 版本. + +此外,请检查 GitLab 的[最低要求](../../../install/requirements.html) ,我们建议您使用: + +* 至少具有 GitLab 企业版 10.0 的基本地理功能. +* 最新版本以获得更好的体验. + +### Firewall rules[](#firewall-rules "Permalink") + +下表列出了在 Geo 的**主**节点和**辅助**节点之间必须打开的基本端口. + +| **Primary** node | **Secondary** node | Protocol | +| --- | --- | --- | +| 80 | 80 | HTTP | +| 443 | 443 | TCP 或 HTTPS | +| 22 | 22 | TCP | +| 5432 |   | PostgreSQL | + +在[Package 默认值中](https://docs.gitlab.com/omnibus/package-information/defaults.html)查看 GitLab 使用的端口的完整列表 + +**注意:** [Web 终端](../../../ci/environments/index.html#web-terminals)支持要求您的负载平衡器正确处理 WebSocket 连接. 当使用 HTTP 或 HTTPS 代理,负载平衡器必须被配置为通过`Connection`和`Upgrade`逐跳头. 有关更多详细信息,请参见[Web 终端](../../integration/terminal.html)集成指南.**注意:**将 HTTPS 协议用于端口 443 时,您需要向负载均衡器添加 SSL 证书. 如果您想在 GitLab 应用程序服务器上终止 SSL,请使用 TCP 协议. + +### LDAP[](#ldap "Permalink") + +We recommend that if you use LDAP on your **primary** node, you also set up secondary LDAP servers on each **secondary** node. Otherwise, users will not be able to perform Git operations over HTTP(s) on the **secondary** node using HTTP Basic Authentication. However, Git via SSH and personal access tokens will still work. + +**注意:**所有**辅助**节点都可以共享 LDAP 服务器,但是额外的延迟可能是一个问题. 另外,如果将**辅助**节点提升为**主要**节点,请考虑在[灾难恢复](../disaster_recovery/index.html)方案中将使用哪些 LDAP 服务器. + +查看有关如何在 LDAP 服务中设置复制的说明. 根据使用的软件或服务,说明会有所不同. 例如,OpenLDAP 提供了[这些说明](https://www.openldap.org/doc/admin24/replication.html) . + +### Geo Tracking Database[](#geo-tracking-database "Permalink") + +跟踪数据库实例用作元数据,以控制需要在本地实例的磁盘上更新的内容. 例如: + +* 下载新资产. +* 提取新的 LFS 对象. +* 从最近更新的存储库中获取更改. + +因为复制的数据库实例是只读的,所以每个**辅助**节点都需要这个额外的数据库实例. 跟踪数据库需要`postgres_fdw`扩展名. + +### Geo Log Cursor[](#geo-log-cursor "Permalink") + +该守护程序: + +* 读取由**主**节点复制到**辅助**数据库实例的事件的日志. +* 使用需要执行的更改更新地理跟踪数据库实例. + +在跟踪数据库实例中将某些内容标记为要更新时,在**辅助**节点上运行的异步作业将执行所需的操作并更新状态. + +这种新的体系结构使 GitLab 能够应对节点之间的连接问题. **辅助**节点与**主**节点断开连接的时间无关紧要,因为它将能够以正确的顺序重放所有事件并再次与**主**节点同步. + +## Setup instructions[](#setup-instructions "Permalink") + +这些说明假定您有一个 GitLab 的工作实例. 他们指导您: + +1. 将现有实例设为**主要**节点. +2. Adding **secondary** nodes. + +**Caution:** The steps below should be followed in the order they appear. **确保所有节点上的 GitLab 版本均相同.** + +### Using Omnibus GitLab[](#using-omnibus-gitlab "Permalink") + +如果您使用 Omnibus 软件包安装了 GitLab(强烈建议): + +1. 在将用作**辅助**节点的服务器上[安装 GitLab 企业版](https://about.gitlab.com/install/) . 不要创建帐户或登录到新的**辅助**节点. +2. 在**主**节点上[载 GitLab 许可](../../../user/admin_area/license.html)以解锁 Geo. 该许可证必须适用于[GitLab Premium](https://about.gitlab.com/pricing/)或更高版本. +3. [Set up the database replication](database.html) (`primary (read-write) <-> secondary (read-only)` topology). +4. [在数据库中配置快速查找授权的 SSH 密钥](../../operations/fast_ssh_key_lookup.html) . 此步骤是必需的,并且必须**同时**在**主**节点和**辅助**节点上完成. +5. [配置 GitLab](configuration.html)以设置**主**节点和**辅助**节点. +6. 可选:为**辅助**节点[配置辅助 LDAP 服务器](../../auth/ldap/index.html) . 请参阅[LDAP 上的注释](#ldap) . +7. [Follow the “Using a Geo Server” guide](using_a_geo_server.html). + +## Post-installation documentation[](#post-installation-documentation "Permalink") + +在**辅助**节点上安装 GitLab 并执行初始配置后,请参阅以下文档以获取安装后信息. + +### Configuring Geo[](#configuring-geo "Permalink") + +有关配置 Geo 的信息,请参见[Geo 配置](configuration.html) . + +### Updating Geo[](#updating-geo "Permalink") + +有关如何将 Geo 节点更新到最新的 GitLab 版本的信息,请参见[更新 Geo 节点](updating_the_geo_nodes.html) . + +### Pausing and resuming replication[](#pausing-and-resuming-replication "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35913) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + +在某些情况下,例如在[升级](updating_the_geo_nodes.html)或[计划的故障转移](../disaster_recovery/planned_failover.html)期间,最好暂停主数据库和辅助数据库之间的复制. + +暂停和恢复复制是通过辅助节点上的命令行工具完成的. + +**暂停:(从中学开始)** + +``` +gitlab-ctl geo-replication-pause +``` + +**恢复:(从中学开始)** + +``` +gitlab-ctl geo-replication-resume +``` + +### Configuring Geo for multiple nodes[](#configuring-geo-for-multiple-nodes "Permalink") + +有关为多个节点配置 Geo 的信息,请参阅[针对多个服务器的 Geo](multiple_servers.html) . + +### Configuring Geo with Object Storage[](#configuring-geo-with-object-storage "Permalink") + +有关配置带对象存储的 Geo 的信息,请参阅[带对象存储的 Geo](object_storage.html) . + +### Disaster Recovery[](#disaster-recovery "Permalink") + +有关在灾难恢复情况下使用 Geo 减轻数据丢失和恢复服务的信息,请参阅[灾难恢复](../disaster_recovery/index.html) . + +### Replicating the Container Registry[](#replicating-the-container-registry "Permalink") + +有关如何复制 Container Registry 的更多信息,请参阅[**辅助**节点的 Docker Registry](docker_registry.html) . + +### Security Review[](#security-review "Permalink") + +有关地理安全的更多信息,请参阅[地理安全审阅](security_review.html) . + +### Tuning Geo[](#tuning-geo "Permalink") + +有关调整 Geo 的更多信息,请参见[调整 Geo](tuning.html) . + +### Set up a location-aware Git URL[](#set-up-a-location-aware-git-url "Permalink") + +有关如何使用 AWS Route53 设置位置感知的 Git 远程 URL 的示例,请参阅使用 AWS Route53 [感知位置的 Git 远程 URL](location_aware_git_url.html) . + +## Remove Geo node[](#remove-geo-node "Permalink") + +For more information on removing a Geo node, see [Removing **secondary** Geo nodes](remove_geo_node.html). + +## Disable Geo[](#disable-geo "Permalink") + +要了解如何禁用地理位置,请参阅[禁用地理位置](disable_geo.html) . + +## Current limitations[](#current-limitations "Permalink") + +**注意:**此限制列表仅反映最新版本的 GitLab. 如果您使用的是旧版本,则可能存在其他限制. + +* 将请求直接推送到**辅助**节点(对于 HTTP)或代理(对于 SSH)​​会将请求重定向到**主要**节点,而不是[直接处理它](https://gitlab.com/gitlab-org/gitlab/-/issues/1381) ,除非在 HTTP 中使用 Git over HTTP 并在 URI 中嵌入凭据. 例如, `https://user:password@secondary.tld` . +* 克隆,拉动或推送存在于**主**节点上但不存在于**辅助**节点上的存储库,这些存储库中的[选择性同步](configuration.html#selective-synchronization)不包括项目,因此不支持通过 SSH 进行, [但已计划进行支持](https://gitlab.com/groups/gitlab-org/-/epics/2562) . 支持 HTTP(S). +* **主**节点必须在线才能进行 OAuth 登录. 现有会话和 Git 均不受影响. [正在计划](https://gitlab.com/gitlab-org/gitlab/-/issues/208465)支持**辅助**节点使用独立于主节点的 OAuth 提供程序. +* 安装过程需要执行多个手动步骤,根据具体情况,总共可能需要一个小时的时间. 我们正在努力改善这种体验. 有关详细信息,请参见[Omnibus GitLab 第 2978](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/2978)期. +* 问题/合并请求的实时更新(例如,通过长轮询)在**辅助**节点上不起作用. +* [选择性同步](configuration.html#selective-synchronization)仅适用于文件和存储库. 其他数据集已完全复制到**辅助**节点,使其不适合用作访问控制机制. +* 用于分支项目重复数据删除的对象池仅在**主**节点上工作,并在**辅助**节点上重复. +* [如果外部合并请求差异](../../merge_request_diffs.html)在磁盘上,则将不会复制它们,并且查看合并请求将失败. 但是,支持对象存储**中的**外部 MR 差异. 默认配置(数据库中)起作用. +* GitLab Runners 无法向**辅助**节点注册. [计划在将来](https://gitlab.com/gitlab-org/gitlab/-/issues/3294)对此提供支持. + +### Limitations on replication/verification[](#limitations-on-replicationverification "Permalink") + +您可以跟踪实现这些史诗/问题中缺少的项目的进度: + +* [Unreplicated Data Types](https://gitlab.com/groups/gitlab-org/-/epics/893) +* [Verify all replicated data](https://gitlab.com/groups/gitlab-org/-/epics/1430) + +这里有所有 GitLab [数据类型](datatypes.html)的完整列表以及[对复制和验证的现有支持](datatypes.html#limitations-on-replicationverification) . + +## Frequently Asked Questions[](#frequently-asked-questions "Permalink") + +有关常见问题的答案,请参见[地理位置常见问题解答](faq.html) . + +## Log files[](#log-files "Permalink") + +自 GitLab 9.5 起,Geo 将结构化日志消息存储在`geo.log`文件中. 对于 Omnibus 安装,此文件位于`/var/log/gitlab/gitlab-rails/geo.log` . + +该文件包含有关 Geo 何时尝试同步存储库和文件的信息. 文件中的每一行都包含一个可以提取的单独的 JSON 条目. 例如,Elasticsearch 或 Splunk. + +例如: + +``` +{"severity":"INFO","time":"2017-08-06T05:40:16.104Z","message":"Repository update","project_id":1,"source":"repository","resync_repository":true,"resync_wiki":true,"class":"Gitlab::Geo::LogCursor::Daemon","cursor_delay_s":0.038} +``` + +此消息表明,Geo 检测到项目`1`需要存储库更新. + +## Troubleshooting[](#troubleshooting "Permalink") + +有关故障排除步骤,请参阅[地理故障排除](troubleshooting.html) . \ No newline at end of file diff --git a/docs/489.md b/docs/489.md new file mode 100644 index 0000000000000000000000000000000000000000..735ab9f87c494fd7465fb5e1090b1321a564d985 --- /dev/null +++ b/docs/489.md @@ -0,0 +1,414 @@ +# Geo database replication + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/database.html](https://docs.gitlab.com/ee/administration/geo/replication/database.html) + +* [PostgreSQL replication](#postgresql-replication) + * [Step 1\. Configure the **primary** server](#step-1-configure-the-primary-server) + * [Step 2\. Configure the **secondary** server](#step-2-configure-the-secondary-server) + * [Step 3\. Initiate the replication process](#step-3-initiate-the-replication-process) +* [PgBouncer support (optional)](#pgbouncer-support-optional) +* [Troubleshooting](#troubleshooting) + +# Geo database replication[](#geo-database-replication-premium-only "Permalink") + +**注意:**如果您的 GitLab 安装使用外部(不受 Omnibus 管理)PostgreSQL 实例,则 Omnibus 角色将无法执行所有必要的配置步骤. 在这种情况下,请[改用 Geo with external PostgreSQL instances 文档](external_database.html) .**Note:** The stages of the setup process must be completed in the documented order. Before attempting the steps in this stage, [complete all prior stages](index.html#using-omnibus-gitlab). + +本文档介绍了将**主** GitLab 数据库复制到**辅助**节点的数据库时必须执行的最少步骤. 您可能需要根据数据库设置,数据库大小等来更改一些值. + +我们鼓励您先阅读所有步骤,然后再在测试/生产环境中执行这些步骤. + +## PostgreSQL replication[](#postgresql-replication "Permalink") + +进行写操作的 GitLab **主**节点将连接到**主**数据库服务器, **辅助**节点将连接到他们自己的数据库服务器(也是只读的). + +我们建议使用[PostgreSQL 复制插槽,](https://medium.com/@tk512/replication-slots-in-postgresql-b4b03d277c75)以确保**主**节点保留恢复**次**节点所需的所有数据. 请参阅下面的更多细节. + +The following guide assumes that: + +* 您使用的是 Omnibus,因此使用的是 PostgreSQL 11 或更高版本,其中包括[`pg_basebackup`工具](https://s0www0postgresql0org.icopy.site/docs/11/app-pgbasebackup.html)和改进的[Foreign Data Wrapper](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html)支持. +* 您已经设置了一个**主**节点(您要从中复制的 GitLab 服务器),并且正在运行 Omnibus 的 PostgreSQL(或等效版本),并且已经设置了一个新的**辅助**服务器,并且具有相同版本的 OS,PostgreSQL 和 GitLab.所有节点. + +**警告:** Geo 可用于流复制. 目前不支持逻辑复制. 在[讨论支持问题](https://gitlab.com/gitlab-org/gitlab/-/issues/7420) . + +### Step 1\. Configure the **primary** server[](#step-1-configure-the-primary-server "Permalink") + +1. SSH 到您的 GitLab **主**服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 编辑`/etc/gitlab/gitlab.rb`并为您的节点添加一个**唯一的**名称: + + ``` + # The unique identifier for the Geo node. + gitlab_rails['geo_node_name'] = '' + ``` + +3. 重新配置**主**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +4. 执行以下命令以将节点定义**为主**节点: + + ``` + gitlab-ctl set-geo-primary-node + ``` + + 该命令将使用您在`/etc/gitlab/gitlab.rb`定义的`external_url` . + +5. 仅限于 GitLab 10.4 及更高版本:执行以下操作以确保`gitlab`数据库用户已定义密码: + + 生成所需密码的 MD5 哈希值: + + ``` + gitlab-ctl pg-password-md5 gitlab + # Enter password: + # Confirm password: + # fca0b89a972d69f00eb3ec98a5838484 + ``` + + Edit `/etc/gitlab/gitlab.rb`: + + ``` + # Fill with the hash generated by `gitlab-ctl pg-password-md5 gitlab` + postgresql['sql_user_password'] = '' + + # Every node that runs Puma or Sidekiq needs to have the database + # password specified as below. If you have a high-availability setup, this + # must be present in all application nodes. + gitlab_rails['db_password'] = '' + ``` + +6. Omnibus GitLab 已经有一个名为`gitlab_replicator`的[复制用户](https://wiki.postgresql.org/wiki/Streaming_Replication) . 您必须手动设置该用户的密码. 系统将提示您输入密码: + + ``` + gitlab-ctl set-replication-password + ``` + + 如果您已将`gitlab_replicator`用户名更改为其他名称,则此命令还将读取`postgresql['sql_replication_user']` Omnibus 设置. + + 如果您使用的不是由 Omnibus GitLab 管理的外部数据库,则需要创建复制器用户并手动为其定义密码: + + ``` + --- Create a new user 'replicator' + CREATE USER gitlab_replicator; + + --- Set/change a password and grants replication privilege + ALTER USER gitlab_replicator WITH REPLICATION ENCRYPTED PASSWORD ''; + ``` + +7. 配置 PostgreSQL 以侦听网络接口: + + 出于安全原因,PostgreSQL 默认情况下不侦听任何网络接口. 但是,Geo 要求**辅助**节点能够连接到**主**节点的数据库. 因此,我们需要每个节点的地址. + + **注意:**对于外部 PostgreSQL 实例,请参见[其他说明](external_database.html) . + + 如果使用的是云提供商,则可以通过云提供商的管理控制台查找每个地理节点的地址. + + 要查找 Geo 节点的地址,请 SSH 到 Geo 节点并执行: + + ``` + ## + ## Private address + ## + ip route get 255.255.255.255 | awk '{print "Private address:", $NF; exit}' + + ## + ## Public address + ## + echo "External address: $(curl --silent ipinfo.io/ip)" + ``` + + 在大多数情况下,以下地址将用于配置 GitLab Geo: + + | Configuration | Address | + | --- | --- | + | `postgresql['listen_address']` | **主**节点的公用或 VPC 专用地址. | + | `postgresql['md5_auth_cidr_addresses']` | **辅助**节点的公用或 VPC 专用地址. | + + 如果您使用的是 Google Cloud Platform,SoftLayer 或提供虚拟私有云(VPC)的任何其他供应商,则可以将**主**节点和**辅助**节点的私有地址(对应于 Google Cloud Platform 的"内部地址")用于`postgresql['md5_auth_cidr_addresses']`和`postgresql['listen_address']` . + + `listen_address`选项打开 PostgreSQL 直至与给定地址对应的接口的网络连接. 有关更多详细信息,请参见[PostgreSQL 文档](https://s0www0postgresql0org.icopy.site/docs/11/runtime-config-connection.html) . + + 根据您的网络配置,建议的地址可能不正确. 如果您的**主**节点和**辅助**节点通过局域网或连接可用性区域的虚拟网络(例如[Amazon 的 VPC](https://aws.amazon.com/vpc/)或[Google 的 VPC)进行连接](https://cloud.google.com/vpc/) ,则应将**辅助**节点的私有地址用于`postgresql['md5_auth_cidr_addresses']` . + + 编辑`/etc/gitlab/gitlab.rb`并添加以下内容,将 IP 地址替换为适合您的网络配置的地址: + + ``` + ## + ## Geo Primary role + ## - configure dependent flags automatically to enable Geo + ## + roles ['geo_primary_role'] + + ## + ## Primary address + ## - replace '' with the public or VPC address of your Geo primary node + ## + postgresql['listen_address'] = '' + + ## + # Allow PostgreSQL client authentication from the primary and secondary IPs. These IPs may be + # public or VPC addresses in CIDR format, for example ['198.51.100.1/32', '198.51.100.2/32'] + ## + postgresql['md5_auth_cidr_addresses'] = ['/32', '/32'] + + ## + ## Replication settings + ## - set this to be the number of Geo secondary nodes you have + ## + postgresql['max_replication_slots'] = 1 + # postgresql['max_wal_senders'] = 10 + # postgresql['wal_keep_segments'] = 10 + + ## + ## Disable automatic database migrations temporarily + ## (until PostgreSQL is restarted and listening on the private address). + ## + gitlab_rails['auto_migrate'] = false + ``` + +8. 可选:如果要添加另一个**辅助**节点,则相关设置应如下所示: + + ``` + postgresql['md5_auth_cidr_addresses'] = ['/32', '/32', '/32'] + ``` + + 您可能还需要编辑`wal_keep_segments`和`max_wal_senders`以匹配您的数据库复制要求. 有关更多信息,请查阅[PostgreSQL-复制文档](https://s0www0postgresql0org.icopy.site/docs/11/runtime-config-replication.html) . + +9. 保存文件并重新配置 GitLab,以进行数据库侦听更改和要应用的复制插槽更改: + + ``` + gitlab-ctl reconfigure + ``` + + 重新启动 PostgreSQL 以使其更改生效: + + ``` + gitlab-ctl restart postgresql + ``` + +10. 现在,重新启动 PostgreSQL 并重新侦听私有地址,即可重新启用迁移. + + 编辑`/etc/gitlab/gitlab.rb`并将配置**更改**为`true` : + + ``` + gitlab_rails['auto_migrate'] = true + ``` + + 保存文件并重新配置 GitLab: + + ``` + gitlab-ctl reconfigure + ``` + +11. 现在,PostgreSQL 服务器已设置为接受远程连接,请运行`netstat -plnt | grep 5432` `netstat -plnt | grep 5432` ,以确保 PostgreSQL 在端口`5432`上侦听**主**服务器的私有地址. + +12. 重新配置 GitLab 时会自动生成一个证书. 这将自动用于保护 PostgreSQL 流量免遭窃听,但是为了防止主动(中间人)攻击者, **辅助**节点需要证书的副本. 通过运行以下命令,在**主**节点上复制 PostgreSQL `server.crt`文件: + + ``` + cat ~gitlab-psql/data/server.crt + ``` + + 将输出复制到剪贴板或本地文件中. 设置**辅助**节点时将需要它! 证书不是敏感数据. + +### Step 2\. Configure the **secondary** server[](#step-2-configure-the-secondary-server "Permalink") + +1. SSH 到您的 GitLab **辅助**服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 停止应用程序服务器和 Sidekiq + + ``` + gitlab-ctl stop puma + gitlab-ctl stop sidekiq + ``` + + **注意:**此步骤很重要,因此在完全配置节点之前,我们不要尝试执行任何操作. +3. [检查](../../raketasks/maintenance.html)与**主**节点的 PostgreSQL 服务器的[TCP 连接](../../raketasks/maintenance.html) : + + ``` + gitlab-rake gitlab:tcp_check[,5432] + ``` + + **注意:**如果此步骤失败,则可能是您使用了错误的 IP 地址,或者防火墙可能阻止了对服务器的访问. 检查 IP 地址,并密切注意公用地址和专用地址之间的区别,并确保(如果存在防火墙)允许**次**节点连接到端口 5432 上的**主**节点. +4. 在**辅助**服务器上创建文件`server.crt` ,其中包含在**主**节点设置的最后一步中获得的内容: + + ``` + editor server.crt + ``` + +5. 在**辅助**节点上设置 PostgreSQL TLS 验证: + + 安装`server.crt`文件: + + ``` + install \ + -D \ + -o gitlab-psql \ + -g gitlab-psql \ + -m 0400 \ + -T server.crt ~gitlab-psql/.postgresql/root.crt + ``` + + 现在,PostgreSQL 将仅在验证 TLS 连接时识别该确切证书. 只能由有权访问私钥的人复制证书,该私钥**仅存**在于**主**节点上. + +6. 测试`gitlab-psql`用户可以连接到**主**节点的数据库(默认的 Omnibus 数据库名称为`gitlabhq_production` ): + + ``` + sudo \ + -u gitlab-psql /opt/gitlab/embedded/bin/psql \ + --list \ + -U gitlab_replicator \ + -d "dbname=gitlabhq_production sslmode=verify-ca" \ + -W \ + -h + ``` + + 出现提示时,输入您在第一步中为`gitlab_replicator`用户设置的密码. 如果所有方法均正常工作,则应该看到**主**节点数据库的列表. + + 此处连接失败表示 TLS 配置不正确. 确保**主**节点上`~gitlab-psql/data/server.crt`的内容与**辅助**节点上`~gitlab-psql/.postgresql/root.crt`的内容匹配. + +7. 配置 PostgreSQL 以启用 FDW 支持: + + 此步骤类似于我们配置**主**实例的方式. 我们需要启用它,以启用 FDW 支持,即使使用单个节点也是如此. + + 编辑`/etc/gitlab/gitlab.rb`并添加以下内容,将 IP 地址替换为适合您的网络配置的地址: + + ``` + ## + ## Geo Secondary role + ## - configure dependent flags automatically to enable Geo + ## + roles ['geo_secondary_role'] + + ## + ## Secondary address + ## - replace '' with the public or VPC address of your Geo secondary node + ## + postgresql['listen_address'] = '' + postgresql['md5_auth_cidr_addresses'] = ['/32'] + + ## + ## Database credentials password (defined previously in primary node) + ## - replicate same values here as defined in primary node + ## + postgresql['sql_user_password'] = '' + gitlab_rails['db_password'] = '' + + ## + ## Enable FDW support for the Geo Tracking Database (improves performance) + ## + geo_secondary['db_fdw'] = true + ``` + + 对于外部 PostgreSQL 实例,请参见[其他说明](external_database.html) . 如果您使以前的**主**节点重新联机以用作**辅助**节点,则还需要删除`roles ['geo_primary_role']`或`geo_primary_role['enable'] = true` . + +8. 重新配置 GitLab,以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +9. 重新启动 PostgreSQL 以使 IP 更改生效并再次重新配置: + + ``` + gitlab-ctl restart postgresql + gitlab-ctl reconfigure + ``` + + 最后的重新配置将提供 FDW 配置并启用它. + +### Step 3\. Initiate the replication process[](#step-3-initiate-the-replication-process "Permalink") + +在下面,我们提供了一个脚本,该脚本将**辅助**节点上的数据库连接到**主要**节点上的数据库,复制数据库,并创建流复制所需的文件. + +使用的目录是在 Omnibus 中设置的默认目录. 如果更改了任何默认值,请根据需要配置它,替换目录和路径. + +**警告:**确保在**辅助**服务器上运行此命令,因为它会在运行`pg_basebackup`之前删除所有 PostgreSQL 的数据. + +1. SSH 到您的 GitLab **辅助**服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 选择一个数据库友好名称,以供您的**辅助**节点用作复制插槽名称. 例如,如果您的域是`secondary.geo.example.com` ,则可以使用`secondary_example`作为插槽名称,如以下命令所示. + +3. 执行以下命令以开始备份/还原并开始复制 + + **警告:**每个 Geo **辅助**节点必须具有自己的唯一复制插槽名称. 在两个辅助节点之间使用相同的插槽名称将破坏 PostgreSQL 复制. + + ``` + gitlab-ctl replicate-geo-database \ + --slot-name= \ + --host= + ``` + + **注意:**复制插槽名称只能包含小写字母,数字和下划线字符. + + 出现提示时,输入第一步中为`gitlab_replicator`用户设置的*纯文本*密码. + + 此命令还带有许多其他选项. 您可以使用`--help`列出所有内容,但是这里有一些提示: + + * 如果 PostgreSQL 在非标准端口上侦听,则还要添加`--port=` . + * 如果数据库太大而无法在 30 分钟内传输,则需要增加超时,例如`--backup-timeout=3600`如果您希望初始复制花费一个小时以下的话. + * 通过`--sslmode=disable`可以完全跳过 PostgreSQL TLS 身份验证(例如,您知道网络路径是安全的,或者您使用的是站点到站点 VPN). 这**不是**通过公共互联网安全! + * 您可以在[PostgreSQL 文档中](https://s0www0postgresql0org.icopy.site/docs/11/libpq-ssl.html)阅读有关每个`sslmode`更多详细信息; 上面的说明均经过精心编写,以确保既能防御被动的窃听者,又能防御主动的"中间人"攻击者. + * 将`--slot-name`更改为要在**主**数据库上使用的复制插槽的名称. 该脚本将尝试自动创建复制插槽(如果不存在). + * If you’re repurposing an old server into a Geo **secondary** node, you’ll need to add `--force` to the command line. + * 如果不在生产机器中,则可以通过添加`--skip-backup`确保确实`--skip-backup`从而禁用备份步骤 + +复制过程现已完成. + +## PgBouncer support (optional)[](#pgbouncer-support-optional "Permalink") + +[PgBouncer](https://www.pgbouncer.org/)可以与 GitLab Geo 一起使用来合并 PostgreSQL 连接. 如果您在高可用性配置中使用 GitLab,且该群集的节点集群支持 Geo **主**节点,而另一个节点集群支持 Geo **辅助**节点,则建议使用 PgBouncer. 有关更多信息,请参见[Omnibus GitLab 的高可用性](../../postgresql/replication_and_failover.html) . + +为了使 Geo **辅助**节点能够与数据库前面的 PgBouncer 一起正常使用,它将需要一个单独的只读用户才能使[PostgreSQL FDW 查询](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html)起作用: + +1. 在**主要的**地理数据库上,以管理员用户身份在控制台上输入 PostgreSQL. 如果使用的是 Omnibus 管理的数据库,请登录到运行 PostgreSQL 数据库的**主**节点(默认的 Omnibus 数据库名称为`gitlabhq_production` ): + + ``` + sudo \ + -u gitlab-psql /opt/gitlab/embedded/bin/psql \ + -h /var/opt/gitlab/postgresql gitlabhq_production + ``` + +2. 然后创建只读用户: + + ``` + -- NOTE: Use the password defined earlier + CREATE USER gitlab_geo_fdw WITH password 'mypassword'; + GRANT CONNECT ON DATABASE gitlabhq_production to gitlab_geo_fdw; + GRANT USAGE ON SCHEMA public TO gitlab_geo_fdw; + GRANT SELECT ON ALL TABLES IN SCHEMA public TO gitlab_geo_fdw; + GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO gitlab_geo_fdw; + + -- Tables created by "gitlab" should be made read-only for "gitlab_geo_fdw" + -- automatically. + ALTER DEFAULT PRIVILEGES FOR USER gitlab IN SCHEMA public GRANT SELECT ON TABLES TO gitlab_geo_fdw; + ALTER DEFAULT PRIVILEGES FOR USER gitlab IN SCHEMA public GRANT SELECT ON SEQUENCES TO gitlab_geo_fdw; + ``` + +3. 在**辅助**节点上,更改`/etc/gitlab/gitlab.rb` : + + ``` + geo_postgresql['fdw_external_user'] = 'gitlab_geo_fdw' + ``` + +4. 保存文件并重新配置 GitLab 以应用更改: + + ``` + gitlab-ctl reconfigure + ``` + +## Troubleshooting[](#troubleshooting "Permalink") + +阅读[故障排除文档](troubleshooting.html) . \ No newline at end of file diff --git a/docs/490.md b/docs/490.md new file mode 100644 index 0000000000000000000000000000000000000000..6be995317e586e585037185cfc008f1e10cfd8f4 --- /dev/null +++ b/docs/490.md @@ -0,0 +1,250 @@ +# Geo with external PostgreSQL instances + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/external_database.html](https://docs.gitlab.com/ee/administration/geo/replication/external_database.html) + +* [**Primary** node](#primary-node) + * [Configure the external database to be replicated](#configure-the-external-database-to-be-replicated) + * [Leverage your cloud provider’s tools to replicate the primary database](#leverage-your-cloud-providers-tools-to-replicate-the-primary-database) + * [Manually configure the primary database for replication](#manually-configure-the-primary-database-for-replication) +* [**Secondary** nodes](#secondary-nodes) + * [Manually configure the replica database](#manually-configure-the-replica-database) + * [Configure **secondary** application nodes to use the external read-replica](#configure-secondary-application-nodes-to-use-the-external-read-replica) + * [Configure the tracking database](#configure-the-tracking-database) + +# Geo with external PostgreSQL instances[](#geo-with-external-postgresql-instances-premium-only "Permalink") + +如果您使用的*不是由 Omnibus 管理*的 PostgreSQL 实例,则此文档很重要. 这包括 AWS RDS 之类的云托管实例,或者手动安装和配置的 PostgreSQL 实例. + +**注意:**我们强烈建议运行 Omnibus 管理的实例,因为它们是积极开发和测试的. 我们的目标是与大多数外部数据库(不受 Omnibus 管理)兼容,但我们不保证兼容性. + +## **Primary** node[](#primary-node "Permalink") + +1. SSH 到 GitLab **主**应用程序服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 编辑`/etc/gitlab/gitlab.rb`并为您的节点添加一个**唯一的** ID(任意值): + + ``` + # The unique identifier for the Geo node. + gitlab_rails['geo_node_name'] = '' + ``` + +3. 重新配置**主**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +4. 执行以下命令以将节点定义**为主**节点: + + ``` + gitlab-ctl set-geo-primary-node + ``` + + 该命令将使用您在`/etc/gitlab/gitlab.rb`定义的`external_url` . + +### Configure the external database to be replicated[](#configure-the-external-database-to-be-replicated "Permalink") + +要设置外部数据库,您可以: + +* 自己设置流复制(例如,在 AWS RDS 中). +* 手动执行 Omnibus 配置,如下所示. + +#### Leverage your cloud provider’s tools to replicate the primary database[](#leverage-your-cloud-providers-tools-to-replicate-the-primary-database "Permalink") + +假设您在使用 RDS 的 AWS EC2 上设置了一个主节点. 现在,您仅可以在其他区域中创建只读副本,复制过程将由 AWS 管理. 确保已根据需要设置了网络 ACL,子网和安全组,以便辅助应用程序节点可以访问数据库. + +以下说明详细说明了如何为常见的云提供程序创建只读副本: + +* Amazon RDS- [创建只读副本](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Create) +* PostgreSQL 的 Azure 数据库-在 PostgreSQL 的 Azure 数据库中[创建和管理只读副本](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal) + +设置只读副本后,您可以跳过以[配置辅助应用程序节点](#configure-secondary-application-nodes-to-use-the-external-read-replica) . + +#### Manually configure the primary database for replication[](#manually-configure-the-primary-database-for-replication "Permalink") + +[`geo_primary_role`](https://docs.gitlab.com/omnibus/roles/)通过更改`pg_hba.conf`和`postgresql.conf`来配置要复制的**主**节点数据库. 手动对外部数据库配置进行以下配置更改,并确保稍后重新启动 PostgreSQL 才能使更改生效: + +``` +## +## Geo Primary Role +## - pg_hba.conf +## +host all all /32 md5 +host replication gitlab_replicator /32 md5 +host all all /32 md5 +host replication gitlab_replicator /32 md5 +``` + +``` +## +## Geo Primary Role +## - postgresql.conf +## +wal_level = hot_standby +max_wal_senders = 10 +wal_keep_segments = 50 +max_replication_slots = 1 # number of secondary instances +hot_standby = on +``` + +## **Secondary** nodes[](#secondary-nodes "Permalink") + +### Manually configure the replica database[](#manually-configure-the-replica-database "Permalink") + +手动对外部副本数据库的`pg_hba.conf`和`postgresql.conf`进行以下配置更改,并确保之后重新启动 PostgreSQL 才能使更改生效: + +``` +## +## Geo Secondary Role +## - pg_hba.conf +## +host all all /32 md5 +host replication gitlab_replicator /32 md5 +host all all /24 md5 +``` + +``` +## +## Geo Secondary Role +## - postgresql.conf +## +wal_level = hot_standby +max_wal_senders = 10 +wal_keep_segments = 10 +hot_standby = on +``` + +### Configure **secondary** application nodes to use the external read-replica[](#configure-secondary-application-nodes-to-use-the-external-read-replica "Permalink") + +对于 Omnibus, [`geo_secondary_role`](https://docs.gitlab.com/omnibus/roles/)具有三个主要功能: + +1. 配置副本数据库. +2. 配置跟踪数据库. +3. 启用[地理日志光标](index.html#geo-log-cursor) (本节未介绍). + +要配置与外部只读副本数据库的连接并启用 Log Cursor,请执行以下操作: + +1. SSH 到 GitLab **辅助**应用程序服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 编辑`/etc/gitlab/gitlab.rb`并添加以下内容 + + ``` + ## + ## Geo Secondary role + ## - configure dependent flags automatically to enable Geo + ## + roles ['geo_secondary_role'] + + # note this is shared between both databases, + # make sure you define the same password in both + gitlab_rails['db_password'] = '' + + gitlab_rails['db_username'] = 'gitlab' + gitlab_rails['db_host'] = '' + + # Disable the bundled Omnibus PostgreSQL, since we are + # using an external PostgreSQL + postgresql['enable'] = false + ``` + +3. 保存文件并[重新配置 GitLab](../../restart_gitlab.html#omnibus-gitlab-reconfigure) + +### Configure the tracking database[](#configure-the-tracking-database "Permalink") + +**辅助**节点使用单独的 PostgreSQL 安装作为跟踪数据库,以跟踪复制状态并自动从潜在的复制问题中恢复. 设置了`roles ['geo_secondary_role']` Omnibus 会自动配置跟踪数据库. 如果要在 Omnibus 外部运行此数据库,请按照以下说明进行操作. + +如果您将云托管服务用于跟踪数据库,则可能需要向跟踪数据库用户授予其他角色(默认情况下,这是`gitlab_geo` ): + +* Amazon RDS 需要[`rds_superuser`](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Roles)角色. +* PostgreSQL 的 Azure 数据库需要[`azure_pg_admin`](https://docs.microsoft.com/en-us/azure/postgresql/howto-create-users#how-to-create-additional-admin-users-in-azure-database-for-postgresql)角色. + +跟踪数据库需要与**辅助**副本数据库建立[FDW](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html)连接以提高性能. + +如果您准备好将外部数据库用作跟踪数据库,请按照以下说明使用它: + +**注意:**如果您要将 AWS RDS 用作跟踪数据库,请确保其有权访问辅助数据库. 不幸的是,仅分配相同的安全组是不够的,因为出站规则不适用于 RDS PostgreSQL 数据库. 因此,您需要将入站规则显式添加到只读副本的安全组,以允许来自跟踪数据库的端口 5432 上的所有 TCP 通信. + +1. 通过手动更改与跟踪数据库关联的`pg_hba.conf` ,确保辅助节点可以与跟踪数据库通信. 请记住,之后要重新启动 PostgreSQL 才能使更改生效: + + ``` + ## + ## Geo Tracking Database Role + ## - pg_hba.conf + ## + host all all /32 md5 + host all all /32 md5 + ``` + +2. SSH 到 GitLab **辅助**服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +3. 使用 PostgreSQL 实例的机器的连接参数和凭据编辑`/etc/gitlab/gitlab.rb` : + + ``` + geo_secondary['db_username'] = 'gitlab_geo' + geo_secondary['db_password'] = '' + + geo_secondary['db_host'] = '' + geo_secondary['db_port'] = # change to the correct port + geo_secondary['db_fdw'] = true # enable FDW + geo_postgresql['enable'] = false # don't use internal managed instance + ``` + +4. 保存文件并[重新配置 GitLab](../../restart_gitlab.html#omnibus-gitlab-reconfigure) + +5. 运行跟踪数据库迁移: + + ``` + gitlab-rake geo:db:create + gitlab-rake geo:db:migrate + ``` + +6. 配置[PostgreSQL FDW](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html)连接和凭据: + + 将下面的脚本保存在一个文件中,例如. `/tmp/geo_fdw.sh`并修改连接参数以匹配您的环境. 执行它以建立 FDW 连接. + + ``` + #!/bin/bash + + # Secondary Database connection params: + DB_HOST="" + DB_NAME="gitlabhq_production" + DB_USER="gitlab" + DB_PASS="" + DB_PORT="5432" + + # Tracking Database connection params: + GEO_DB_HOST="" + GEO_DB_NAME="gitlabhq_geo_production" + GEO_DB_USER="gitlab_geo" + GEO_DB_PORT="5432" + + query_exec () { + gitlab-psql -h $GEO_DB_HOST -U $GEO_DB_USER -d $GEO_DB_NAME -p $GEO_DB_PORT -c "${1}" + } + + query_exec "CREATE EXTENSION postgres_fdw;" + query_exec "CREATE SERVER gitlab_secondary FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '${DB_HOST}', dbname '${DB_NAME}', port '${DB_PORT}');" + query_exec "CREATE USER MAPPING FOR ${GEO_DB_USER} SERVER gitlab_secondary OPTIONS (user '${DB_USER}', password '${DB_PASS}');" + query_exec "CREATE SCHEMA gitlab_secondary;" + query_exec "GRANT USAGE ON FOREIGN SERVER gitlab_secondary TO ${GEO_DB_USER};" + ``` + + **注意:**上面的脚本模板使用`gitlab-psql`因为它打算从 Geo 机器上执行,但是您可以将其更改为`psql`并从任何有权访问数据库的机器上运行. 我们还建议将`psql`用于 AWS RDS. +7. 保存文件并[重新启动 GitLab](../../restart_gitlab.html#omnibus-gitlab-restart) +8. Populate the FDW tables: + + ``` + gitlab-rake geo:db:refresh_foreign_tables + ``` \ No newline at end of file diff --git a/docs/491.md b/docs/491.md new file mode 100644 index 0000000000000000000000000000000000000000..b348e980d3f7811da0cc627dbfd2cb08623beb68 --- /dev/null +++ b/docs/491.md @@ -0,0 +1,291 @@ +# Geo configuration + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/configuration.html](https://docs.gitlab.com/ee/administration/geo/replication/configuration.html) + +* [Configuring a new **secondary** node](#configuring-a-new-secondary-node) + * [Step 1\. Manually replicate secret GitLab values](#step-1-manually-replicate-secret-gitlab-values) + * [Step 2\. Manually replicate the **primary** node’s SSH host keys](#step-2-manually-replicate-the-primary-nodes-ssh-host-keys) + * [Step 3\. Add the **secondary** node](#step-3-add-the-secondary-node) + * [Step 4\. Enabling Hashed Storage](#step-4-enabling-hashed-storage) + * [Step 5\. (Optional) Configuring the **secondary** node to trust the **primary** node](#step-5-optional-configuring-the-secondary-node-to-trust-the-primary-node) + * [Step 6\. Enable Git access over HTTP/HTTPS](#step-6-enable-git-access-over-httphttps) + * [Step 7\. Verify proper functioning of the **secondary** node](#step-7-verify-proper-functioning-of-the-secondary-node) +* [Selective synchronization](#selective-synchronization) + * [Git operations on unreplicated repositories](#git-operations-on-unreplicated-repositories) +* [Upgrading Geo](#upgrading-geo) +* [Troubleshooting](#troubleshooting) + +# Geo configuration[](#geo-configuration-premium-only "Permalink") + +## Configuring a new **secondary** node[](#configuring-a-new-secondary-node "Permalink") + +**注意:**这是设置**辅助**地理节点的最后一步. 设置过程的各个阶段必须按记录的顺序完成. 在尝试此阶段中的步骤之前,请[完成所有之前的阶段](index.html#using-omnibus-gitlab) . + +配置**辅助**节点的基本步骤是: + +* 在**主**节点和**辅助**节点之间复制所需的配置. +* 在每个**辅助**节点上配置跟踪数据库. +* 在每个**辅助**节点上启动 GitLab. + +我们鼓励您先阅读所有步骤,然后再在测试/生产环境中执行这些步骤. + +**注意:** **不要**为**辅助**节点设置任何自定义身份验证. 这将由**主**节点处理. 任何需要访问" **管理区域"的**更改都必须在**主**节点中完成,因为**辅助**节点是只读副本. + +### Step 1\. Manually replicate secret GitLab values[](#step-1-manually-replicate-secret-gitlab-values "Permalink") + +GitLab 在`/etc/gitlab/gitlab-secrets.json`文件中存储了许多秘密值,这些秘密值在所有节点上都*必须*相同. 除非有一种方法可以在节点之间自动复制它们(请参阅[问题#3789](https://gitlab.com/gitlab-org/gitlab/-/issues/3789) ),否则必须将它们手动复制到**辅助**节点. + +1. SSH 进入**主**节点,并执行以下命令: + + ``` + sudo cat /etc/gitlab/gitlab-secrets.json + ``` + + 这将以 JSON 格式显示需要复制的机密. + +2. SSH 进入**辅助**节点并以`root`用户身份登录: + + ``` + sudo -i + ``` + +3. 备份所有现有机密: + + ``` + mv /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json.`date +%F` + ``` + +4. 将`/etc/gitlab/gitlab-secrets.json`从**主**节点复制到**辅助**节点,或在节点之间复制并粘贴文件内容: + + ``` + sudo editor /etc/gitlab/gitlab-secrets.json + + # paste the output of the `cat` command you ran on the primary + # save and exit + ``` + +5. 确保文件权限正确: + + ``` + chown root:root /etc/gitlab/gitlab-secrets.json + chmod 0600 /etc/gitlab/gitlab-secrets.json + ``` + +6. 重新配置**辅助**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + gitlab-ctl restart + ``` + +### Step 2\. Manually replicate the **primary** node’s SSH host keys[](#step-2-manually-replicate-the-primary-nodes-ssh-host-keys "Permalink") + +GitLab 与系统安装的 SSH 守护程序集成,指定一个用户(通常名为`git` )来处理所有访问请求. + +在[灾难恢复](../disaster_recovery/index.html)情况下,GitLab 系统管理员会将**辅助**节点升级为**主要**节点. **主**域的 DNS 记录也应更新为指向新的**主**节点(以前是**辅助**节点). 这样做可以避免更新 Git 遥控器和 API URL 的麻烦. + +由于 SSH 主机密钥不匹配,这将导致对新提升的**主**节点的所有 SSH 请求失败. 为防止这种情况,必须将主 SSH 主机密钥手动复制到**辅助**节点. + +1. SSH 进入**辅助**节点并以`root`用户身份登录: + + ``` + sudo -i + ``` + +2. 备份所有现有的 SSH 主机密钥: + + ``` + find /etc/ssh -iname ssh_host_* -exec cp {} {}.backup.`date +%F` \; + ``` + +3. 从**主**节点复制 OpenSSH 主机密钥: + + 如果可以使用**root**用户访问**主**节点: + + ``` + # Run this from the secondary node, change `` for the IP or FQDN of the server + scp root@:/etc/ssh/ssh_host_*_key* /etc/ssh + ``` + + 如果您只能通过具有`sudo`特权的用户访问: + + ``` + # Run this from your primary node: + sudo tar --transform 's/.*\///g' -zcvf ~/geo-host-key.tar.gz /etc/ssh/ssh_host_*_key* + + # Run this from your secondary node: + scp @:geo-host-key.tar.gz . + tar zxvf ~/geo-host-key.tar.gz -C /etc/ssh + ``` + +4. 在**辅助**节点上,确保文件权限正确: + + ``` + chown root:root /etc/ssh/ssh_host_*_key* + chmod 0600 /etc/ssh/ssh_host_*_key* + ``` + +5. 要验证密钥指纹是否匹配,请在两个节点上执行以下命令: + + ``` + for file in /etc/ssh/ssh_host_*_key; do ssh-keygen -lf $file; done + ``` + + 您应该获得与此输出类似的输出,并且两个节点上的输出应该相同: + + ``` + 1024 SHA256:FEZX2jQa2bcsd/fn/uxBzxhKdx4Imc4raXrHwsbtP0M root@serverhostname (DSA) + 256 SHA256:uw98R35Uf+fYEQ/UnJD9Br4NXUFPv7JAUln5uHlgSeY root@serverhostname (ECDSA) + 256 SHA256:sqOUWcraZQKd89y/QQv/iynPTOGQxcOTIXU/LsoPmnM root@serverhostname (ED25519) + 2048 SHA256:qwa+rgir2Oy86QI+PZi/QVR+MSmrdrpsuH7YyKknC+s root@serverhostname (RSA) + ``` + +6. 验证您对现有的私钥具有正确的公钥: + + ``` + # This will print the fingerprint for private keys: + for file in /etc/ssh/ssh_host_*_key; do ssh-keygen -lf $file; done + + # This will print the fingerprint for public keys: + for file in /etc/ssh/ssh_host_*_key.pub; do ssh-keygen -lf $file; done + ``` + + **注意:**私钥和公钥命令的输出应生成相同的指纹. +7. 在**辅助**节点上重新启动`sshd` : + + ``` + # Debian or Ubuntu installations + sudo service ssh reload + + # CentOS installations + sudo service sshd reload + ``` + +### Step 3\. Add the **secondary** node[](#step-3-add-the-secondary-node "Permalink") + +1. SSH 到您的 GitLab **辅助**服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 编辑`/etc/gitlab/gitlab.rb`并为您的节点添加一个**唯一的**名称. 在接下来的步骤中,您将需要此: + + ``` + # The unique identifier for the Geo node. + gitlab_rails['geo_node_name'] = '' + ``` + +3. 重新配置**辅助**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +4. 访问**主**节点的 **管理区>** 浏览器中的**地理位置** ( `/admin/geo/nodes` ). +5. 单击**新建节点**按钮. [![添加辅助节点](img/ce7d1dd63f95f0330b281fd577aaa8d4.png)](img/adding_a_secondary_node.png) +6. 填写**姓名**与`gitlab_rails['geo_node_name']`在`/etc/gitlab/gitlab.rb` . 这些值必须始终*完全*匹配,一个字符一个字符. +7. 在`/etc/gitlab/gitlab.rb` `external_url`填写**URL** . 这些值必须始终匹配,但是一个以`/`结尾而另一个不以`/`无关紧要. +8. **不要**选中" **这是主节点"**复选框. +9. (可选)选择**辅助**节点应复制的组或存储分片. 保留空白以复制所有内容. 阅读更多有关[选择性同步的信息](#selective-synchronization) . +10. 单击**添加节点**按钮以添加**辅助**节点. +11. SSH 到您的 GitLab **辅助**服务器并重新启动服务: + + ``` + gitlab-ctl restart + ``` + + 通过运行以下命令,检查您的地理设置是否存在任何常见问题: + + ``` + gitlab-rake gitlab:geo:check + ``` + +12. SSH 到您的**主**服务器中,并以 root 用户身份登录以验证**辅助**节点是否可以访问或您的地理设置存在任何常见问题: + + ``` + gitlab-rake gitlab:geo:check + ``` + +一旦添加到管理面板并重新启动, **辅助**节点将在称为**backfill**的过程中自动开始从**主**节点复制丢失的数据. 同时, **主**节点将开始将每个更改通知每个**辅助**节点,以便**辅助**节点可以立即对那些通知进行操作. + +确保**辅助**节点正在运行并且可访问. 您可以使用与**主**节点相同的凭据登录到**辅助**节点. + +### Step 4\. Enabling Hashed Storage[](#step-4-enabling-hashed-storage "Permalink") + +使用哈希存储可显着改善地理复制. 项目和组重命名不再需要节点之间的同步. + +1. 访问**主**节点的 **管理区>** 浏览器中的**设置>存储库** ( `/admin/application_settings/repository` ). +2. 在" **存储库存储"**部分中,选中" **对新创建和重命名的项目使用哈希存储路径"** . + +### Step 5\. (Optional) Configuring the **secondary** node to trust the **primary** node[](#step-5-optional-configuring-the-secondary-node-to-trust-the-primary-node "Permalink") + +如果您的**主**节点使用 CA 颁发的 HTTPS 证书,则可以安全地跳过此步骤. + +如果**主**节点正在使用自签名证书以获得*HTTPS*支持,则需要将该证书添加到**辅助**节点的信任存储中. 从**主**节点上检索证书,然后在**辅助**节点上遵循[这些说明](https://docs.gitlab.com/omnibus/settings/ssl.html) . + +### Step 6\. Enable Git access over HTTP/HTTPS[](#step-6-enable-git-access-over-httphttps "Permalink") + +Geo 通过 HTTP / HTTPS 同步存储库,因此需要启用此克隆方法. 导航 **管理区>** 在**主**节点上进行**设置** ( `/admin/application_settings/general` ),并将`Enabled Git access protocols`设置为`Both SSH and HTTP(S)`或`Only HTTP(S)` . + +### Step 7\. Verify proper functioning of the **secondary** node[](#step-7-verify-proper-functioning-of-the-secondary-node "Permalink") + +现在已配置**辅助**节点! + +您可以使用与**主**节点相同的凭据登录到**辅助**节点. 访问**辅助**节点的 **管理区>** 浏览器中的**Geo** ( `/admin/geo/nodes` ),以检查是否正确地将其标识为**辅助** Geo 节点,以及是否启用了 Geo. + +初始复制或"回填"可能仍在进行中. 您可以从浏览器中**主**节点的" **地理节点"**仪表板监视每个地理节点上的同步过程. + +[![Geo dashboard](img/337891c1885c756f35968127a8050c21.png)](img/geo_node_dashboard.png) + +如果您的安装无法正常工作,请查看[故障排除文档](troubleshooting.html) . + +仪表板中最明显的两个最明显的问题是: + +1. 数据库复制无法正常工作. +2. 实例间实例通知不起作用. 在这种情况下,可能是以下情况: + * 您正在使用自定义证书或自定义 CA(请参阅[故障排除文档](troubleshooting.html) ). + * 该实例已进行防火墙保护(请检查您的防火墙规则). + +请注意,禁用**辅助**节点将停止同步过程. + +请注意,如果在**主**节点上为多个存储库分片定制了`git_data_dirs`则必须在每个**辅助**节点上复制相同的配置. + +将您的用户指向["使用地理服务器"指南](using_a_geo_server.html) . + +当前,这是同步的: + +* Git 存储库. +* Wikis. +* LFS 对象. +* 问题,合并请求,摘要和评论附件. +* 用户,组和项目化身. + +## Selective synchronization[](#selective-synchronization "Permalink") + +Geo 支持选择性同步,这使管理员可以选择**辅助**节点应同步哪些项目. 可以按组或按存储碎片选择项目的子集. 前者是复制属于用户子集的数据的理想选择,而后者更适合将 Geo 逐步推广到大型 GitLab 实例. + +重要的是要注意选择性同步: + +1. 不限制来自**辅助**节点的权限. +2. 不从**辅助**节点隐藏项目元数据. + * 由于 Geo 当前依赖于 PostgreSQL 复制,因此所有项目元数据都将复制到**辅助**节点,但是尚未选择的存储库将为空. +3. 不减少为地理事件日志生成的事件数. + * 只要存在任何**辅助**节点, **主**节点都会生成事件. 选择性同步限制是在**辅助**节点而非**主**节点上实现的. + +### Git operations on unreplicated repositories[](#git-operations-on-unreplicated-repositories "Permalink") + +在 HTTP(S)的 GitLab 12.10 和 SSH 的 GitLab 13.0 中[引入](https://gitlab.com/groups/gitlab-org/-/epics/2562) . + +存在于**主**节点上但不存在于**辅助**节点上的存储库支持通过 HTTP(S)和 SSH 进行 Git 克隆,拉入和推送操作. 在以下情况下可能会发生这种情况: + +* 选择性同步不包括附加到存储库的项目. +* 存储库正在积极地复制,但尚未完成. + +## Upgrading Geo[](#upgrading-geo "Permalink") + +请参阅[更新地理节点文档](updating_the_geo_nodes.html) . + +## Troubleshooting[](#troubleshooting "Permalink") + +请参阅[故障排除文档](troubleshooting.html) . \ No newline at end of file diff --git a/docs/492.md b/docs/492.md new file mode 100644 index 0000000000000000000000000000000000000000..6dfc116856f45abc33eea8313c1d26ce505d57db --- /dev/null +++ b/docs/492.md @@ -0,0 +1,22 @@ +# Using a Geo Server + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/using_a_geo_server.html](https://docs.gitlab.com/ee/administration/geo/replication/using_a_geo_server.html) + +# Using a Geo Server[](#using-a-geo-server-premium-only "Permalink") + +设置[数据库复制并配置 Geo 节点后](index.html#setup-instructions) ,请像使用普通的独立 GitLab 实例一样使用最近的 GitLab 节点. + +在[GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3 中[引入](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/)了直接推送到**辅助**节点(对于 HTTP,包括 Git LFS 的 SSH). + +推送到**辅助**节点时将看到的输出示例: + +``` +$ git push +remote: +remote: You're pushing to a Geo secondary. We'll help you by proxying this +remote: request to the primary: +remote: +remote: ssh://git@primary.geo/user/repo.git +remote: +Everything up-to-date +``` \ No newline at end of file diff --git a/docs/493.md b/docs/493.md new file mode 100644 index 0000000000000000000000000000000000000000..26cf582636885683777224a1919cafb54fd0d8bf --- /dev/null +++ b/docs/493.md @@ -0,0 +1,63 @@ +# Updating the Geo nodes + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/updating_the_geo_nodes.html](https://docs.gitlab.com/ee/administration/geo/replication/updating_the_geo_nodes.html) + +* [Version specific update steps](#version-specific-update-steps) +* [General update steps](#general-update-steps) + * [Check status after updating](#check-status-after-updating) + +# Updating the Geo nodes[](#updating-the-geo-nodes-premium-only "Permalink") + +更新地理节点涉及执行: + +1. [特定](#version-specific-update-steps)于版本的[更新步骤](#version-specific-update-steps) ,具体取决于要与之进行更新的版本. +2. [常规更新步骤](#general-update-steps) ,适用于所有更新. + +## Version specific update steps[](#version-specific-update-steps "Permalink") + +根据您要更新或更新的 Geo 版本,可能会有不同的步骤. + +* [Updating to GitLab 12.9](version_specific_updates.html#updating-to-gitlab-129) +* [Updating to GitLab 12.7](version_specific_updates.html#updating-to-gitlab-127) +* [Updating to GitLab 12.2](version_specific_updates.html#updating-to-gitlab-122) +* [Updating to GitLab 12.1](version_specific_updates.html#updating-to-gitlab-121) +* [Updating to GitLab 12.0](version_specific_updates.html#updating-to-gitlab-120) +* [Updating to GitLab 11.11](version_specific_updates.html#updating-to-gitlab-1111) +* [Updating to GitLab 10.8](version_specific_updates.html#updating-to-gitlab-108) +* [Updating to GitLab 10.6](version_specific_updates.html#updating-to-gitlab-106) +* [Updating to GitLab 10.5](version_specific_updates.html#updating-to-gitlab-105) +* [Updating to GitLab 10.3](version_specific_updates.html#updating-to-gitlab-103) +* [Updating to GitLab 10.2](version_specific_updates.html#updating-to-gitlab-102) +* [Updating to GitLab 10.1](version_specific_updates.html#updating-to-gitlab-101) +* [Updating to GitLab 10.0](version_specific_updates.html#updating-to-gitlab-100) +* [Updating from GitLab 9.3 or older](version_specific_updates.html#updating-from-gitlab-93-or-older) +* [Updating to GitLab 9.0](version_specific_updates.html#updating-to-gitlab-90) + +## General update steps[](#general-update-steps "Permalink") + +**注意:**这些常规更新步骤不适用于[高可用性部署](https://docs.gitlab.com/omnibus/update/README.html) ,并且会导致停机. 如果要避免停机,请考虑使用[零停机更新](https://docs.gitlab.com/omnibus/update/README.html) . + +要在发布新的 GitLab 版本时更新 Geo 节点,请更新**主**节点和所有**辅助**节点: + +1. **Optional:** [Pause replication on each **secondary** node.](./index.html#pausing-and-resuming-replication) +2. 登录到**主**节点. +3. [Update GitLab on the **primary** node using Omnibus](https://docs.gitlab.com/omnibus/update/README.html). +4. 登录到每个**辅助**节点. +5. [Update GitLab on each **secondary** node using Omnibus](https://docs.gitlab.com/omnibus/update/README.html). +6. 如果您在步骤 1 中暂停了复制,则[在每个**辅助**节点上继续复制](./index.html#pausing-and-resuming-replication) +7. [测试](#check-status-after-updating) **主**节点和**辅助**节点,并检查每个节点的版本. + +### Check status after updating[](#check-status-after-updating "Permalink") + +现在,更新过程已完成,您可能要检查一切是否正常运行: + +1. 在所有节点上运行 Geo Rake 任务,所有内容应为绿色: + + ``` + sudo gitlab-rake gitlab:geo:check + ``` + +2. 检查**主**节点的地理仪表板是否有任何错误. +3. 通过将代码推送到**主**节点来测试数据复制,并查看**辅助**节点是否接收到该复制. + +如果您遇到任何问题,请查阅《 [地理位置疑难解答指南》](troubleshooting.html) . \ No newline at end of file diff --git a/docs/494.md b/docs/494.md new file mode 100644 index 0000000000000000000000000000000000000000..f120b771772d88d699fbe5a1bf649a9fad3b0799 --- /dev/null +++ b/docs/494.md @@ -0,0 +1,64 @@ +# Geo with Object storage + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/object_storage.html](https://docs.gitlab.com/ee/administration/geo/replication/object_storage.html) + +* [Enabling GitLab managed object storage replication](#enabling-gitlab-managed-object-storage-replication) +* [Third-party replication services](#third-party-replication-services) + +# Geo with Object storage[](#geo-with-object-storage-premium-only "Permalink") + +Geo 可与对象存储(AWS S3 或其他兼容的对象存储)结合使用. + +当前, **辅助**节点可以使用以下任一方式: + +* 与**主**节点相同的存储桶. +* 复制的存储桶. + +具有: + +* GitLab 管理复制,遵循[启用 GitLab 复制](#enabling-gitlab-managed-object-storage-replication) . +* 第三方服务管理复制,请遵循[第三方复制服务](#third-party-replication-services) . + +[Read more about using object storage with GitLab](../../object_storage.html). + +## Enabling GitLab managed object storage replication[](#enabling-gitlab-managed-object-storage-replication "Permalink") + +在 GitLab 12.4 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/10586) . + +**警告:**这是[**Beta 版**功能](https://about.gitlab.com/handbook/product/#beta) ,尚未准备好用于任何规模的生产. + +**辅助**节点可以复制存储在**主**节点上的文件,而不管它们是存储在本地文件系统还是对象存储中. + +要启用 GitLab 复制,您必须: + +1. 去 **管理区>** **地理位置** . +2. 在**辅助**节点上按**编辑** . +3. 启用" **允许此辅助节点在对象存储上复制内容"**复选框. + +对于 LFS,请按照文档[设置 LFS 对象存储](../../lfs/index.html#storing-lfs-objects-in-remote-object-storage) . + +对于 CI 作业工件,有类似的文档可以配置[作业工件对象存储](../../job_artifacts.html#using-object-storage) + +对于用户上传,有类似的文档可配置[上传对象存储](../../uploads.html#using-object-storage-core-only) + +如果要将**主**节点的文件迁移到对象存储,则可以通过以下几种方式配置**辅助**节点: + +* 使用完全相同的对象存储. +* 使用单独的对象存储,但可以利用对象存储解决方案的内置复制. +* 使用单独的对象存储,并启用" **允许此辅助节点在对象存储上复制内容"**设置. + +GitLab 当前不支持以下两种情况: + +* **主**节点使用本地存储. +* **辅助**节点使用对象存储. + +## Third-party replication services[](#third-party-replication-services "Permalink") + +使用 Amazon S3 时,您可以使用[CRR](https://docs.aws.amazon.com/AmazonS3/latest/dev/crr.html)在**主**节点使用的存储桶和**辅助**节点使用的存储桶之间进行自动复制. + +如果您使用的是 Google Cloud Storage,请考虑使用[Multi-Regional Storage](https://cloud.google.com/storage/docs/storage-classes#multi-regional) . 或者,您可以使用" [存储传输服务"](https://cloud.google.com/storage-transfer/docs/) ,尽管该[服务](https://cloud.google.com/storage-transfer/docs/)仅支持每日同步. + +对于手动同步,或由`cron`安排,请查看: + +* [`s3cmd sync`](https://s3tools.org/s3cmd-sync) +* [`gsutil rsync`](https://cloud.google.com/storage/docs/gsutil/commands/rsync) \ No newline at end of file diff --git a/docs/495.md b/docs/495.md new file mode 100644 index 0000000000000000000000000000000000000000..8d922f18c840c84f70ce1f016ca9eb5e294c13f6 --- /dev/null +++ b/docs/495.md @@ -0,0 +1,96 @@ +# Docker Registry for a secondary node + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/docker_registry.html](https://docs.gitlab.com/ee/administration/geo/replication/docker_registry.html) + +* [Storage support](#storage-support) +* [Replicating Docker Registry](#replicating-docker-registry) + * [Configure **primary** node](#configure-primary-node) + * [Configure **secondary** node](#configure-secondary-node) + * [Verify replication](#verify-replication) + +# Docker Registry for a secondary node[](#docker-registry-for-a-secondary-node-premium-only "Permalink") + +您可以在**次要** Geo 节点上设置一个[Docker Registry](https://s0docs0docker0com.icopy.site/registry/) ,以镜像**主** Geo 节点上的[Docker Registry](https://s0docs0docker0com.icopy.site/registry/) . + +## Storage support[](#storage-support "Permalink") + +Docker Registry 当前支持几种类型的存储. 如果您在**主**节点上为 Docker 注册表选择分布式存储( `azure` , `gcs` , `s3` , `swift`或`oss` ),则也可以将相同的存储用于**辅助** Docker 注册表. 有关更多信息,请阅读部署注册表时的[负载平衡注意事项](https://s0docs0docker0com.icopy.site/registry/deploying/) ,以及如何为 GitLab 的集成[Container Registry](../../packages/container_registry.html#use-object-storage)设置存储驱动程序. + +## Replicating Docker Registry[](#replicating-docker-registry "Permalink") + +您可以启用与存储无关的复制,以便将其用于云或本地存储. 每当将新映像推送到**主**节点时,每个**辅助**节点都会将其拖到其自己的容器存储库中. + +要配置 Docker Registry 复制: + +1. 配置[**主**节点](#configure-primary-node) . +2. 配置[**辅助**节点](#configure-secondary-node) . +3. 验证 Docker Registry [复制](#verify-replication) . + +### Configure **primary** node[](#configure-primary-node "Permalink") + +在执行下一步之前,请确保已设置 Container Registry 并在**主**节点上工作. + +我们需要使 Docker Registry 将通知事件发送到**主**节点. + +1. SSH 到您的 GitLab **主**服务器并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. Edit `/etc/gitlab/gitlab.rb`: + + ``` + registry['notifications'] = [ + { + 'name' => 'geo_event', + 'url' => 'https://example.com/api/v4/container_registry_event/events', + 'timeout' => '500ms', + 'threshold' => 5, + 'backoff' => '1s', + 'headers' => { + 'Authorization' => [''] + } + } + ] + ``` + + **注意:**将``替换为以字母开头的区分大小写的字母数字字符串. 您可以使用`< /dev/urandom tr -dc _A-Zaz-0-9 | head -c 32 | sed "s/^[0-9]*//"; echo`生成一个`< /dev/urandom tr -dc _A-Zaz-0-9 | head -c 32 | sed "s/^[0-9]*//"; echo` `< /dev/urandom tr -dc _A-Zaz-0-9 | head -c 32 | sed "s/^[0-9]*//"; echo`**注意:**如果使用外部注册表(而不是与 GitLab 集成的注册表),则必须将这些设置自己添加到其配置中. 在这种情况下,您还必须在`/etc/gitlab/gitlab.rb`文件的`registry.notification_secret`部分中指定通知密钥.**注意:**如果使用 GitLab HA,则还必须在`/etc/gitlab/gitlab.rb`文件的`registry.notification_secret`部分中为每个 Web 节点指定通知密钥. +3. 重新配置**主**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +### Configure **secondary** node[](#configure-secondary-node "Permalink") + +Make sure you have Container Registry set up and working on the **secondary** node before following the next steps. + +在希望看到复制的 Docker 映像的每个**辅助**节点上,应执行以下步骤. + +因为我们需要允许**辅助**节点与**主**节点容器注册表安全通信,所以我们需要为所有节点使用单个密钥对. **辅助**节点将使用此密钥来生成短暂的 JWT,该 JWT 具有仅拉功能,可以访问**主**节点 Container Registry. + +1. SSH 进入**辅助**节点并以`root`用户身份登录: + + ``` + sudo -i + ``` + +2. 将`/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key`从**主**节点复制到**辅助**节点. + +3. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitlab_rails['geo_registry_replication_enabled'] = true + gitlab_rails['geo_registry_replication_primary_api_url'] = 'https://primary.example.com:5050/' # Primary registry address, it will be used by the secondary node to directly communicate to primary registry + ``` + +4. 重新配置**辅助**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +### Verify replication[](#verify-replication "Permalink") + +要验证 Container Registry 复制是否正常工作,请转到 **管理区>** **辅助**节点上的**地理位置** ( `/admin/geo/nodes` ). 初始复制或"回填"可能仍在进行中. 您可以从浏览器中**主**节点的" **地理节点"**仪表板监视每个地理节点上的同步过程. \ No newline at end of file diff --git a/docs/496.md b/docs/496.md new file mode 100644 index 0000000000000000000000000000000000000000..d9c880ff16c3813c37a5feecbc8ef08864e36ed9 --- /dev/null +++ b/docs/496.md @@ -0,0 +1,404 @@ +# Geo for multiple nodes + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/multiple_servers.html](https://docs.gitlab.com/ee/administration/geo/replication/multiple_servers.html) + +* [Architecture overview](#architecture-overview) +* [Redis and PostgreSQL for multiple nodes](#redis-and-postgresql-for-multiple-nodes) +* [Prerequisites: Two working GitLab multi-node clusters](#prerequisites-two-working-gitlab-multi-node-clusters) +* [Configure the GitLab cluster to be the **primary** node](#configure-the-gitlab-cluster-to-be-the-primary-node) + * [Step 1: Configure the **primary** frontend servers](#step-1-configure-the-primary-frontend-servers) + * [Step 2: Configure the **primary** database](#step-2-configure-the-primary-database) +* [Configure a **secondary** node](#configure-a-secondary-node) + * [Step 1: Configure the Redis and Gitaly services on the **secondary** node](#step-1-configure-the-redis-and-gitaly-services-on-the-secondary-node) + * [Step 2: Configure the main read-only replica PostgreSQL database on the **secondary** node](#step-2-configure-the-main-read-only-replica-postgresql-database-on-the-secondary-node) + * [Step 3: Configure the tracking database on the **secondary** node](#step-3-configure-the-tracking-database-on-the-secondary-node) + * [Step 4: Configure the frontend application servers on the **secondary** node](#step-4-configure-the-frontend-application-servers-on-the-secondary-node) + * [Step 5: Set up the LoadBalancer for the **secondary** node](#step-5-set-up-the-loadbalancer-for-the-secondary-node) + * [Step 6: Configure the backend application servers on the **secondary** node](#step-6-configure-the-backend-application-servers-on-the-secondary-node) + +# Geo for multiple nodes[](#geo-for-multiple-nodes-premium-only "Permalink") + +本文档介绍了用于在多节点配置中运行 Geo 的最小参考架构. 如果您的多节点设置与所描述的不同,则可以根据需要调整这些说明. + +## Architecture overview[](#architecture-overview "Permalink") + +[![Geo multi-node diagram](img/e28a59687a00b33f8174f2bcba18ac5d.png)](../../high_availability/img/geo-ha-diagram.png) + +*[diagram source - GitLab employees only](https://docs.google.com/drawings/d/1z0VlizKiLNXVVVaERFwgsIOuEgjcUqDTWPdQYsE7Z4c/edit)* + +上面的拓扑假定**主要**和**辅助**地理集群位于两个单独的位置,位于它们自己的具有专用 IP 地址的虚拟网络上. 网络配置为使一个地理位置内的所有计算机都可以使用其专用 IP 地址相互通信. 给出的 IP 地址只是示例,可能会因部署的网络拓扑而有所不同. + +在上述示例中,访问这两个 Geo 部署的唯一外部方法是通过 HTTPS 分别位于`gitlab.us.example.com`和`gitlab.eu.example.com` . + +**注意:** **主要**和**辅助** Geo 部署必须能够通过 HTTPS 相互通信. + +## Redis and PostgreSQL for multiple nodes[](#redis-and-postgresql-for-multiple-nodes "Permalink") + +地理位置支持: + +* Redis 和 PostgreSQL 在**为主**节点上配置了多个节点. +* Redis 在为多个节点配置的**辅助**节点上. + +**注意:** [已计划](https://gitlab.com/groups/gitlab-org/-/epics/2536)在多节点配置中在**辅助**节点上支持 PostgreSQL. + +由于为 PostgreSQL 和 Redis 设置此配置涉及额外的复杂性,因此此 Geo 多节点文档未涵盖该配置. + +有关使用 omnibus 软件包设置多节点 PostgreSQL 集群和 Redis 集群的更多信息,请分别参见[PostgreSQL](../../postgresql/replication_and_failover.html)和[Redis](../../redis/replication_and_failover.html)的多节点文档. + +**注意:**可以将云托管服务用于 PostgreSQL 和 Redis,但这不在本文档的范围之内. + +## Prerequisites: Two working GitLab multi-node clusters[](#prerequisites-two-working-gitlab-multi-node-clusters "Permalink") + +一个群集将充当**主**节点. 使用[GitLab 多节点文档](../../reference_architectures/index.html)进行设置. 如果您已经有一个正在使用的工作 GitLab 实例,则可以将其用作**primary** . + +The second cluster will serve as the **secondary** node. Again, use the [GitLab multi-node documentation](../../reference_architectures/index.html) to set this up. It’s a good idea to log in and test it, however, note that its data will be wiped out as part of the process of replicating from the **primary**. + +## Configure the GitLab cluster to be the **primary** node[](#configure-the-gitlab-cluster-to-be-the-primary-node "Permalink") + +通过以下步骤,GitLab 集群可以用**作主**节点. + +### Step 1: Configure the **primary** frontend servers[](#step-1-configure-the-primary-frontend-servers "Permalink") + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下内容: + + ``` + ## + ## Enable the Geo primary role + ## + roles ['geo_primary_role'] + + ## + ## The unique identifier for the Geo node. + ## + gitlab_rails['geo_node_name'] = '' + + ## + ## Disable automatic migrations + ## + gitlab_rails['auto_migrate'] = false + ``` + +进行这些更改后,请[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +**注意:**在正常的 GitLab 多节点设置过程中,应已在应用程序服务器上禁用 PostgreSQL 和 Redis,并且已配置从应用程序服务器到后端服务器上的那些服务的连接. 请参阅[PostgreSQL](../../postgresql/replication_and_failover.html#configuring-the-application-nodes)和[Redis 的](../../redis/replication_and_failover.html#example-configuration-for-the-gitlab-application)多节点配置文档. + +### Step 2: Configure the **primary** database[](#step-2-configure-the-primary-database "Permalink") + +1. 编辑`/etc/gitlab/gitlab.rb`并添加以下内容: + + ``` + ## + ## Configure the Geo primary role and the PostgreSQL role + ## + roles ['geo_primary_role', 'postgres_role'] + ``` + +## Configure a **secondary** node[](#configure-a-secondary-node "Permalink") + +**辅助**群集与任何其他 GitLab 多节点群集相似,但有两个主要区别: + +* 主 PostgreSQL 数据库是**主**节点的 PostgreSQL 数据库的只读副本. +* **辅助**集群还有一个单独的 PostgreSQL 数据库,称为"跟踪数据库",该数据库跟踪各种资源的同步状态. + +因此,我们将一个接一个地设置多节点组件,并包括与常规多节点设置的偏差. 但是,我们强烈建议您首先配置一个全新的群集,就像它不是地理设置一样,以便可以对其进行测试和验证. 只有这样,才可以对其进行修改以用作 Geo **辅助对象** . 这有助于分离与地理设置无关的问题. + +### Step 1: Configure the Redis and Gitaly services on the **secondary** node[](#step-1-configure-the-redis-and-gitaly-services-on-the-secondary-node "Permalink") + +再次使用非 Geo 多节点文档配置以下服务: + +* 为多个节点[配置 Redis for GitLab](../../redis/replication_and_failover.html#example-configuration-for-the-gitlab-application) . +* [Gitaly](../../high_availability/gitaly.html) ,它将存储从**主**节点同步的数据. + +**注意:** [NFS](../../high_availability/nfs.html)可以代替 Gitaly 使用,但不建议使用. + +### Step 2: Configure the main read-only replica PostgreSQL database on the **secondary** node[](#step-2-configure-the-main-read-only-replica-postgresql-database-on-the-secondary-node "Permalink") + +**注意:**以下文档假定数据库将仅在单个节点上运行. [当前不支持](https://gitlab.com/groups/gitlab-org/-/epics/2536) **辅助**节点上的多节点 PostgreSQL. + +配置[**辅助**数据库](database.html)作为**主**数据库的一个只读副本. 使用以下内容作为指导. + +1. 为数据库用户生成所需密码的 MD5 哈希,GitLab 应用程序将使用该密码来访问只读副本数据库: + + 请注意,用户名(默认情况下为`gitlab` )已合并到哈希中. + + ``` + gitlab-ctl pg-password-md5 gitlab + # Enter password: + # Confirm password: + # fca0b89a972d69f00eb3ec98a5838484 + ``` + + 在下一步中使用此哈希值填写`` . + +2. 在副本数据库计算机中编辑`/etc/gitlab/gitlab.rb` ,并添加以下内容: + + ``` + ## + ## Configure the Geo secondary role and the PostgreSQL role + ## + roles ['geo_secondary_role', 'postgres_role'] + + ## + ## Secondary address + ## - replace '' with the public or VPC address of your Geo secondary node + ## - replace '' with the public or VPC address of your Geo tracking database node + ## + postgresql['listen_address'] = '' + postgresql['md5_auth_cidr_addresses'] = ['/32', '/32'] + + ## + ## Database credentials password (defined previously in primary node) + ## - replicate same values here as defined in primary node + ## + postgresql['sql_user_password'] = '' + gitlab_rails['db_password'] = '' + + ## + ## When running the Geo tracking database on a separate machine, disable it + ## here and allow connections from the tracking database host. And ensure + ## the tracking database IP is in postgresql['md5_auth_cidr_addresses'] above. + ## + geo_postgresql['enable'] = false + + ## + ## Disable `geo_logcursor` service so Rails doesn't get configured here + ## + geo_logcursor['enable'] = false + ``` + +进行这些更改后,请[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +如果使用外部 PostgreSQL 实例,另请参阅使用外部 PostgreSQL 实例的[Geo](external_database.html) . + +### Step 3: Configure the tracking database on the **secondary** node[](#step-3-configure-the-tracking-database-on-the-secondary-node "Permalink") + +**注意:**本文档假定跟踪数据库将仅在一台计算机上运行,​​而不是作为 PostgreSQL 集群运行. + +配置跟踪数据库. + +1. Generate an MD5 hash of the desired password for the database user that the GitLab application will use to access the tracking database: + + 请注意,用户名(默认为`gitlab_geo` )已合并到哈希中. + + ``` + gitlab-ctl pg-password-md5 gitlab_geo + # Enter password: + # Confirm password: + # fca0b89a972d69f00eb3ec98a5838484 + ``` + + 在下一步中,使用此哈希值填写`` . + +2. 在跟踪数据库计算机中编辑`/etc/gitlab/gitlab.rb` ,并添加以下内容: + + ``` + ## + ## Enable the Geo secondary tracking database + ## + geo_postgresql['enable'] = true + geo_postgresql['listen_address'] = '' + geo_postgresql['sql_user_password'] = '' + + ## + ## Configure FDW connection to the replica database + ## + geo_secondary['db_fdw'] = true + geo_postgresql['fdw_external_password'] = '' + geo_postgresql['md5_auth_cidr_addresses'] = ['/32'] + gitlab_rails['db_host'] = '' + + # Prevent reconfigure from attempting to run migrations on the replica DB + gitlab_rails['auto_migrate'] = false + + ## + ## Disable all other services that aren't needed, since we don't have a role + ## that does this. + ## + alertmanager['enable'] = false + consul['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + node_exporter['enable'] = false + pgbouncer_exporter['enable'] = false + postgresql['enable'] = false + prometheus['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + repmgr['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + ``` + +进行这些更改后,请[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +如果使用外部 PostgreSQL 实例,另请参阅使用外部 PostgreSQL 实例的[Geo](external_database.html) . + +### Step 4: Configure the frontend application servers on the **secondary** node[](#step-4-configure-the-frontend-application-servers-on-the-secondary-node "Permalink") + +在体系结构概述中,有两台机器运行 GitLab 应用程序服务. 这些服务在配置中有选择地启用. + +在[为多个节点配置 GitLab](../../high_availability/gitlab.html)之后, [配置](../../high_availability/gitlab.html)应用程序服务器,然后进行以下修改: + +1. 在**辅助**集群中的每个应用程序服务器上编辑`/etc/gitlab/gitlab.rb` ,并添加以下内容: + + ``` + ## + ## Enable the Geo secondary role + ## + roles ['geo_secondary_role', 'application_role'] + + ## + ## The unique identifier for the Geo node. + ## + gitlab_rails['geo_node_name'] = '' + + ## + ## Disable automatic migrations + ## + gitlab_rails['auto_migrate'] = false + + ## + ## Configure the connection to the tracking DB. And disable application + ## servers from running tracking databases. + ## + geo_secondary['db_host'] = '' + geo_secondary['db_password'] = '' + geo_postgresql['enable'] = false + + ## + ## Configure connection to the streaming replica database, if you haven't + ## already + ## + gitlab_rails['db_host'] = '' + gitlab_rails['db_password'] = '' + + ## + ## Configure connection to Redis, if you haven't already + ## + gitlab_rails['redis_host'] = '' + gitlab_rails['redis_password'] = '' + + ## + ## If you are using custom users not managed by Omnibus, you need to specify + ## UIDs and GIDs like below, and ensure they match between servers in a + ## cluster to avoid permissions issues + ## + user['uid'] = 9000 + user['gid'] = 9000 + web_server['uid'] = 9001 + web_server['gid'] = 9001 + registry['uid'] = 9002 + registry['gid'] = 9002 + ``` + +**注意:**如果使用 omnibus 软件包设置了 PostgreSQL 集群,并且设置了`postgresql['sql_user_password'] = 'md5 digest of secret'`设置,请记住`gitlab_rails['db_password']`和`geo_secondary['db_password']`上面提到的包含明文密码. 这用于让 Rails 服务器连接到数据库.**注意:**确保在远程数据库的`postgresql['md5_auth_cidr_addresses']`设置中列出了当前节点 IP. + +进行这些更改后,请[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +在辅助服务器上,将启用以下 GitLab 前端服务: + +* `geo-logcursor` +* `gitlab-pages` +* `gitlab-workhorse` +* `logrotate` +* `nginx` +* `registry` +* `remote-syslog` +* `sidekiq` +* `puma` + +通过在前端应用程序服务器上运行`sudo gitlab-ctl status`来验证这些服务. + +### Step 5: Set up the LoadBalancer for the **secondary** node[](#step-5-set-up-the-loadbalancer-for-the-secondary-node "Permalink") + +在这种拓扑中,每个地理位置都需要一个负载平衡器,以将流量路由到应用程序服务器. + +有关更多信息,请参见[具有多个节点的 GitLab 的 Load Balancer](../../high_availability/load_balancer.html) . + +### Step 6: Configure the backend application servers on the **secondary** node[](#step-6-configure-the-backend-application-servers-on-the-secondary-node "Permalink") + +上面的最小参考体系结构图显示了在同一台计算机上一起运行的所有应用程序服务. 但是,对于多个节点,我们[强烈建议单独运行所有服务](../../reference_architectures/index.html) . + +例如,可以将 Sidekiq 服务器配置为与上面的前端应用程序服务器类似,但要进行一些更改以仅运行`sidekiq`服务: + +1. 在**辅助**群集中的每个 Sidekiq 服务器上编辑`/etc/gitlab/gitlab.rb` ,并添加以下内容: + + ``` + ## + ## Enable the Geo secondary role + ## + roles ['geo_secondary_role'] + + ## + ## Enable the Sidekiq service + ## + sidekiq['enable'] = true + + ## + ## Ensure unnecessary services are disabled + ## + alertmanager['enable'] = false + consul['enable'] = false + geo_logcursor['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + node_exporter['enable'] = false + pgbouncer_exporter['enable'] = false + postgresql['enable'] = false + prometheus['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + repmgr['enable'] = false + puma['enable'] = false + + ## + ## The unique identifier for the Geo node. + ## + gitlab_rails['geo_node_name'] = '' + + ## + ## Disable automatic migrations + ## + gitlab_rails['auto_migrate'] = false + + ## + ## Configure the connection to the tracking DB. And disable application + ## servers from running tracking databases. + ## + geo_secondary['db_host'] = '' + geo_secondary['db_password'] = '' + geo_postgresql['enable'] = false + + ## + ## Configure connection to the streaming replica database, if you haven't + ## already + ## + gitlab_rails['db_host'] = '' + gitlab_rails['db_password'] = '' + + ## + ## Configure connection to Redis, if you haven't already + ## + gitlab_rails['redis_host'] = '' + gitlab_rails['redis_password'] = '' + + ## + ## If you are using custom users not managed by Omnibus, you need to specify + ## UIDs and GIDs like below, and ensure they match between servers in a + ## cluster to avoid permissions issues + ## + user['uid'] = 9000 + user['gid'] = 9000 + web_server['uid'] = 9001 + web_server['gid'] = 9001 + registry['uid'] = 9002 + registry['gid'] = 9002 + ``` + + 您可以类似地将服务器配置为仅运行`geo_logcursor['enable'] = true`的`geo-logcursor`服务,并使用`sidekiq['enable'] = false`禁用 Sidekiq. + + 这些服务器不需要连接到负载平衡器. \ No newline at end of file diff --git a/docs/497.md b/docs/497.md new file mode 100644 index 0000000000000000000000000000000000000000..16372a8b74b6671c838aa4c79771a27894176b30 --- /dev/null +++ b/docs/497.md @@ -0,0 +1,266 @@ +# Geo security review (Q&A) + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/security_review.html](https://docs.gitlab.com/ee/administration/geo/replication/security_review.html) + +* [Business Model](#business-model) + * [What geographic areas does the application service?](#what-geographic-areas-does-the-application-service) +* [Data Essentials](#data-essentials) + * [What data does the application receive, produce, and process?](#what-data-does-the-application-receive-produce-and-process) + * [How can the data be classified into categories according to its sensitivity?](#how-can-the-data-be-classified-into-categories-according-to-its-sensitivity) + * [What data backup and retention requirements have been defined for the application?](#what-data-backup-and-retention-requirements-have-been-defined-for-the-application) +* [End-Users](#end-users) + * [Who are the application’s end‐users?](#who-are-the-applications-endusers) + * [How do the end‐users interact with the application?](#how-do-the-endusers-interact-with-the-application) + * [What security expectations do the end‐users have?](#what-security-expectations-do-the-endusers-have) +* [Administrators](#administrators) + * [Who has administrative capabilities in the application?](#who-has-administrative-capabilities-in-the-application) + * [What administrative capabilities does the application offer?](#what-administrative-capabilities-does-the-application-offer) +* [Network](#network) + * [What details regarding routing, switching, firewalling, and load‐balancing have been defined?](#what-details-regarding-routing-switching-firewalling-and-loadbalancing-have-been-defined) + * [What core network devices support the application?](#what-core-network-devices-support-the-application) + * [What network performance requirements exist?](#what-network-performance-requirements-exist) + * [What private and public network links support the application?](#what-private-and-public-network-links-support-the-application) +* [Systems](#systems) + * [What operating systems support the application?](#what-operating-systems-support-the-application) + * [What details regarding required OS components and lock‐down needs have been defined?](#what-details-regarding-required-os-components-and-lockdown-needs-have-been-defined) +* [Infrastructure Monitoring](#infrastructure-monitoring) + * [What network and system performance monitoring requirements have been defined?](#what-network-and-system-performance-monitoring-requirements-have-been-defined) + * [What mechanisms exist to detect malicious code or compromised application components?](#what-mechanisms-exist-to-detect-malicious-code-or-compromised-application-components) + * [What network and system security monitoring requirements have been defined?](#what-network-and-system-security-monitoring-requirements-have-been-defined) +* [Virtualization and Externalization](#virtualization-and-externalization) + * [What aspects of the application lend themselves to virtualization?](#what-aspects-of-the-application-lend-themselves-to-virtualization) +* [What virtualization requirements have been defined for the application?](#what-virtualization-requirements-have-been-defined-for-the-application) + * [What aspects of the product may or may not be hosted via the cloud computing model?](#what-aspects-of-the-product-may-or-may-not-be-hosted-via-the-cloud-computing-model) +* [If applicable, what approach(es) to cloud computing will be taken (Managed Hosting versus “Pure” Cloud, a “full machine” approach such as AWS-EC2 versus a “hosted database” approach such as AWS-RDS and Azure, etc)?](#if-applicable-what-approaches-to-cloud-computing-will-be-taken-managed-hosting-versus-pure-cloud-a-full-machine-approach-such-as-aws-ec2-versus-a-hosted-database-approach-such-as-aws-rds-and-azure-etc) +* [Environment](#environment) + * [What frameworks and programming languages have been used to create the application?](#what-frameworks-and-programming-languages-have-been-used-to-create-the-application) + * [What process, code, or infrastructure dependencies have been defined for the application?](#what-process-code-or-infrastructure-dependencies-have-been-defined-for-the-application) + * [What databases and application servers support the application?](#what-databases-and-application-servers-support-the-application) + * [How will database connection strings, encryption keys, and other sensitive components be stored, accessed, and protected from unauthorized detection?](#how-will-database-connection-strings-encryption-keys-and-other-sensitive-components-be-stored-accessed-and-protected-from-unauthorized-detection) +* [Data Processing](#data-processing) + * [What data entry paths does the application support?](#what-data-entry-paths-does-the-application-support) + * [What data output paths does the application support?](#what-data-output-paths-does-the-application-support) + * [How does data flow across the application’s internal components?](#how-does-data-flow-across-the-applications-internal-components) + * [What data input validation requirements have been defined?](#what-data-input-validation-requirements-have-been-defined) + * [What data does the application store and how?](#what-data-does-the-application-store-and-how) + * [What data is or may need to be encrypted and what key management requirements have been defined?](#what-data-is-or-may-need-to-be-encrypted-and-what-key-management-requirements-have-been-defined) + * [What capabilities exist to detect the leakage of sensitive data?](#what-capabilities-exist-to-detect-the-leakage-of-sensitive-data) + * [What encryption requirements have been defined for data in transit - including transmission over WAN, LAN, SecureFTP, or publicly accessible protocols such as http: and https:?](#what-encryption-requirements-have-been-defined-for-data-in-transit---including-transmission-over-wan-lan-secureftp-or-publicly-accessible-protocols-such-as-http-and-https) +* [Access](#access) + * [What user privilege levels does the application support?](#what-user-privilege-levels-does-the-application-support) + * [What user identification and authentication requirements have been defined?](#what-user-identification-and-authentication-requirements-have-been-defined) + * [What user authorization requirements have been defined?](#what-user-authorization-requirements-have-been-defined) + * [What session management requirements have been defined?](#what-session-management-requirements-have-been-defined) + * [What access requirements have been defined for URI and Service calls?](#what-access-requirements-have-been-defined-for-uri-and-service-calls) +* [Application Monitoring](#application-monitoring) + * [What application auditing requirements have been defined? How are audit and debug logs accessed, stored, and secured?](#what-application-auditing-requirements-have-been-defined-how-are-audit-and-debug-logs-accessed-stored-and-secured) + +# Geo security review (Q&A)[](#geo-security-review-qa-premium-only "Permalink") + +以下对地理功能集的安全性审查集中于该功能的安全性方面,因为它们适用于运行自己的 GitLab 实例的客户. 复习题部分基于[owasp.org](https://owasp.org/)的[OWASP 应用程序安全验证标准项目](https://owasp.org/www-project-application-security-verification-standard/) . + +## Business Model[](#business-model "Permalink") + +### What geographic areas does the application service?[](#what-geographic-areas-does-the-application-service "Permalink") + +* 这因客户而异. Geo 使客户可以部署到多个区域,然后他们可以选择自己的位置. +* 区域和节点选择完全是手动的. + +## Data Essentials[](#data-essentials "Permalink") + +### What data does the application receive, produce, and process?[](#what-data-does-the-application-receive-produce-and-process "Permalink") + +* Geo 几乎在站点之间流传输 GitLab 实例保存的所有数据. 这包括完整的数据库复制,大多数文件(用户上传的附件等)以及存储库+ Wiki 数据. 在典型的配置中,这将在公共 Internet 上发生,并经过 TLS 加密. +* PostgreSQL 复制是 TLS 加密的. +* 另请参阅: [仅应支持 TLSv1.2](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/2948) + +### How can the data be classified into categories according to its sensitivity?[](#how-can-the-data-be-classified-into-categories-according-to-its-sensitivity "Permalink") + +* GitLab’s model of sensitivity is centered around public vs. internal vs. private projects. Geo replicates them all indiscriminately. “Selective sync” exists for files and repositories (but not database content), which would permit only less-sensitive projects to be replicated to a **secondary** node if desired. +* 另请参阅: [GitLab 数据分类策略](https://about.gitlab.com/handbook/engineering/security/data-classification-policy.html) . + +### What data backup and retention requirements have been defined for the application?[](#what-data-backup-and-retention-requirements-have-been-defined-for-the-application "Permalink") + +* Geo 旨在提供应用程序数据的某些子集的复制. 它是解决方案的一部分,而不是问题的一部分. + +## End-Users[](#end-users "Permalink") + +### Who are the application’s end‐users?[](#who-are-the-applications-endusers "Permalink") + +* **辅助**节点在是遥远(在互联网延迟而言)从主 GitLab 安装( **主**节点)区创建. 打算由通常使用**主**节点的任何人使用它们,他们发现**辅助**节点距离它们更近(就 Internet 延迟而言). + +### How do the end‐users interact with the application?[](#how-do-the-endusers-interact-with-the-application "Permalink") + +* **辅助**节点提供了**主**节点执行的所有接口(特别是 HTTP / HTTPS Web 应用程序以及 HTTP / HTTPS 或 SSH Git 存储库访问),但仅限于只读活动. 设想主要用例是从**辅助**节点克隆 Git 存储库以支持**主**节点,但是最终用户可以使用 GitLab Web 界面查看项目,问题,合并请求,摘要等. + +### What security expectations do the end‐users have?[](#what-security-expectations-do-the-endusers-have "Permalink") + +* 复制过程必须是安全的. 例如,在整个公共 Internet 上以纯文本格式传输整个数据库内容或所有文件和存储库通常是不可接受的. +* **辅助**节点必须对其内容具有与**主**节点相同的访问控制-未经身份验证的用户不能通过查询**辅助**节点来获得对**主**节点上特权信息的访问. +* 攻击者必须不能将**辅助**节点模拟为**主要**节点,从而不能访问特权信息. + +## Administrators[](#administrators "Permalink") + +### Who has administrative capabilities in the application?[](#who-has-administrative-capabilities-in-the-application "Permalink") + +* 没有特定于地理位置的信息. 在数据库中设置了`admin: true`任何用户都被视为具有超级用户特权的 admin. +* 另请参阅: [更详细的访问控制](https://gitlab.com/gitlab-org/gitlab/-/issues/18242) (不是特定于地理位置的). +* Geo 的许多集成(例如,数据库复制)必须由应用程序配置,通常由系统管理员配置. + +### What administrative capabilities does the application offer?[](#what-administrative-capabilities-does-the-application-offer "Permalink") + +* 具有管理访问权限的用户可以添加,修改或删除**辅助**节点. +* 复制过程可以通过 Sidekiq 管理控件进行控制(启动/停止). + +## Network[](#network "Permalink") + +### What details regarding routing, switching, firewalling, and load‐balancing have been defined?[](#what-details-regarding-routing-switching-firewalling-and-loadbalancing-have-been-defined "Permalink") + +* Geo 要求**主要**节点和**次要**节点能够通过 TCP / IP 网络相互通信. 特别是, **辅助**节点必须能够访问**主**节点上的 HTTP / HTTPS 和 PostgreSQL 服务. + +### What core network devices support the application?[](#what-core-network-devices-support-the-application "Permalink") + +* 因客户而异. + +### What network performance requirements exist?[](#what-network-performance-requirements-exist "Permalink") + +* **主**节点和**辅助**节点之间的最大复制速度受到站点之间可用带宽的限制. 没有硬性要求-完成复制的时间(以及跟上**主**节点的更改的能力)取决于数据集的大小,对延迟的容忍度以及可用的网络容量. + +### What private and public network links support the application?[](#what-private-and-public-network-links-support-the-application "Permalink") + +* 客户选择自己的网络. 由于打算将站点在地理位置上分开,因此可以设想,复制流量将在典型部署中通过公共 Internet 传递,但这不是必需的. + +## Systems[](#systems "Permalink") + +### What operating systems support the application?[](#what-operating-systems-support-the-application "Permalink") + +* Geo 对操作系统没有任何其他限制(有关更多详细信息,请参见[GitLab 安装](https://about.gitlab.com/install/)页面),但是我们建议您使用[Geo 文档中](index.html#requirements-for-running-geo)列出的操作系统. + +### What details regarding required OS components and lock‐down needs have been defined?[](#what-details-regarding-required-os-components-and-lockdown-needs-have-been-defined "Permalink") + +* 受支持的安装方法(Omnibus)打包了大多数组件本身. +* 系统安装的 OpenSSH 守护程序(Geo 要求用户设置自定义身份验证方法)和 omnibus 或系统提供的 PostgreSQL 守护程序(必须配置为侦听 TCP,必须添加其他用户和复制插槽)之间存在很大的依赖关系,等等). +* 处理安全更新的过程(例如,如果 OpenSSH 或其他服务中存在重大漏洞,并且客户希望在 OS 上修补这些服务)与非 Geo 情况相同:对 OpenSSH 的安全更新为通过通常的分发渠道提供给用户. Geo 在那里没有延迟. + +## Infrastructure Monitoring[](#infrastructure-monitoring "Permalink") + +### What network and system performance monitoring requirements have been defined?[](#what-network-and-system-performance-monitoring-requirements-have-been-defined "Permalink") + +* 没有特定于 Ge​​o 的内容. + +### What mechanisms exist to detect malicious code or compromised application components?[](#what-mechanisms-exist-to-detect-malicious-code-or-compromised-application-components "Permalink") + +* 没有特定于 Ge​​o 的内容. + +### What network and system security monitoring requirements have been defined?[](#what-network-and-system-security-monitoring-requirements-have-been-defined "Permalink") + +* 没有特定于 Ge​​o 的内容. + +## Virtualization and Externalization[](#virtualization-and-externalization "Permalink") + +### What aspects of the application lend themselves to virtualization?[](#what-aspects-of-the-application-lend-themselves-to-virtualization "Permalink") + +* All. + +## What virtualization requirements have been defined for the application?[](#what-virtualization-requirements-have-been-defined-for-the-application "Permalink") + +* 没有特定于地理位置的信息,但是在这样的环境中,GitLab 中的所有内容都需要具有完整的功能. + +### What aspects of the product may or may not be hosted via the cloud computing model?[](#what-aspects-of-the-product-may-or-may-not-be-hosted-via-the-cloud-computing-model "Permalink") + +* GitLab 是"云原生"的,这不仅适用于 Geo,还适用于产品的其余部分. 在云中进行部署是常见且受支持的方案. + +## If applicable, what approach(es) to cloud computing will be taken (Managed Hosting versus “Pure” Cloud, a “full machine” approach such as AWS-EC2 versus a “hosted database” approach such as AWS-RDS and Azure, etc)?[](#if-applicable-what-approaches-to-cloud-computing-will-be-taken-managed-hosting-versus-pure-cloud-a-full-machine-approach-such-as-aws-ec2-versus-a-hosted-database-approach-such-as-aws-rds-and-azure-etc "Permalink") + +* 由我们的客户根据他们的运营需求来决定. + +## Environment[](#environment "Permalink") + +### What frameworks and programming languages have been used to create the application?[](#what-frameworks-and-programming-languages-have-been-used-to-create-the-application "Permalink") + +* Ruby on Rails,Ruby. + +### What process, code, or infrastructure dependencies have been defined for the application?[](#what-process-code-or-infrastructure-dependencies-have-been-defined-for-the-application "Permalink") + +* 没有特定于 Ge​​o 的内容. + +### What databases and application servers support the application?[](#what-databases-and-application-servers-support-the-application "Permalink") + +* PostgreSQL> = 11,Redis,Sidekiq,Puma. + +### How will database connection strings, encryption keys, and other sensitive components be stored, accessed, and protected from unauthorized detection?[](#how-will-database-connection-strings-encryption-keys-and-other-sensitive-components-be-stored-accessed-and-protected-from-unauthorized-detection "Permalink") + +* 有一些特定于地理位置的值. 有些是共享机密,必须在设置时将其从**主**节点安全地传输到**辅助**节点. 我们的文档建议通过 SSH 将它们从**主**节点传输到系统管理员,然后以相同方式回传到**辅助**节点. 特别是,这包括 PostgreSQL 复制凭证和一个秘密密钥( `db_key_base` ),该密钥用于解密数据库中的某些列. `db_key_base`秘密与其他许多秘密一起未加密地存储在文件系统中的`/etc/gitlab/gitlab-secrets.json` . 他们没有休息保护. + +## Data Processing[](#data-processing "Permalink") + +### What data entry paths does the application support?[](#what-data-entry-paths-does-the-application-support "Permalink") + +* 数据是通过 GitLab 本身公开的 Web 应用程序输入的. 使用 GitLab 服务器上的系统管理命令(例如`gitlab-ctl set-primary-node` )也输入了一些数据. +* **辅助**节点还通过 PostgreSQL 流复制从**主**节点接收输入. + +### What data output paths does the application support?[](#what-data-output-paths-does-the-application-support "Permalink") + +* **主**节点通过 PostgreSQL 流复制输出到**辅助**节点. 否则,主要是通过 GitLab 本身公开的 Web 应用程序以及最终用户启动的 SSH `git clone`操作. + +### How does data flow across the application’s internal components?[](#how-does-data-flow-across-the-applications-internal-components "Permalink") + +* **辅助**节点和**主**节点通过 HTTP / HTTPS(受 JSON Web 令牌保护)和 PostgreSQL 流复制进行交互. +* 在**主**节点或**辅助**节点内,SSOT 是文件系统和数据库(包括**辅助**节点上的 Geo 跟踪数据库). 精心安排了各种内部组件以对这些存储进行更改. + +### What data input validation requirements have been defined?[](#what-data-input-validation-requirements-have-been-defined "Permalink") + +* **辅助**节点必须忠实地复制**主**节点的数据. + +### What data does the application store and how?[](#what-data-does-the-application-store-and-how "Permalink") + +* Git 存储库和文件,与它们相关的跟踪信息以及 GitLab 数据库内容. + +### What data is or may need to be encrypted and what key management requirements have been defined?[](#what-data-is-or-may-need-to-be-encrypted-and-what-key-management-requirements-have-been-defined "Permalink") + +* **主**节点或**辅助**节点都不会加密静态的 Git 存储库或文件系统数据. 数据库列的子集使用`db_otp_key`加密. +* 在 GitLab 部署中的所有主机之间共享的静态机密. +* 在传输过程中,尽管应用程序确实允许通信以未加密的方式进行,但是数据应该被加密. 两个主要过程是 PostgreSQL 和 Git 存储库/文件的**辅助**节点复制过程. 两者均应使用 TLS 保护,并通过现有配置通过 Omnibus 管理该密钥,以供最终用户访问 GitLab. + +### What capabilities exist to detect the leakage of sensitive data?[](#what-capabilities-exist-to-detect-the-leakage-of-sensitive-data "Permalink") + +* 存在全面的系统日志,跟踪与 GitLab 和 PostgreSQL 的每个连接. + +### What encryption requirements have been defined for data in transit - including transmission over WAN, LAN, SecureFTP, or publicly accessible protocols such as http: and https:?[](#what-encryption-requirements-have-been-defined-for-data-in-transit---including-transmission-over-wan-lan-secureftp-or-publicly-accessible-protocols-such-as-http-and-https "Permalink") + +* 数据必须具有在传输过程中进行加密的选项,并且必须能够抵抗被动和主动攻击(例如,不可能进行 MITM 攻击). + +## Access[](#access "Permalink") + +### What user privilege levels does the application support?[](#what-user-privilege-levels-does-the-application-support "Permalink") + +* Geo 添加了一种类型的特权: **辅助**节点可以访问特殊的 Geo API,以通过 HTTP / HTTPS 下载文件,以及使用 HTTP / HTTPS 克隆存储库. + +### What user identification and authentication requirements have been defined?[](#what-user-identification-and-authentication-requirements-have-been-defined "Permalink") + +* **辅助**节点基于共享数据库(HTTP 访问)或 PostgreSQL 复制用户(用于数据库复制)通过 OAuth 或 JWT 身份验证向 Geo **主**节点标识. 数据库复制还需要定义基于 IP 的访问控制. + +### What user authorization requirements have been defined?[](#what-user-authorization-requirements-have-been-defined "Permalink") + +* **辅助**节点只能*读取*数据. 他们当前无法对**主**节点上的数据进行突变. + +### What session management requirements have been defined?[](#what-session-management-requirements-have-been-defined "Permalink") + +* 地理 JWT 被定义为仅持续两分钟,然后需要重新生成. +* Geo JWT 是为以下特定范围之一生成的: + * Geo API 访问. + * Git 访问. + * LFS 和文件 ID. + * 上传和文件 ID. + * 作业工件和文件 ID. + +### What access requirements have been defined for URI and Service calls?[](#what-access-requirements-have-been-defined-for-uri-and-service-calls "Permalink") + +* **辅助**节点对**主**节点的 API 进行了许多调用. 例如,这就是文件复制的进行方式. 只能使用 JWT 令牌访问此端点. +* **主**节点还调用**辅助**节点以获取状态信息. + +## Application Monitoring[](#application-monitoring "Permalink") + +### What application auditing requirements have been defined? How are audit and debug logs accessed, stored, and secured?[](#what-application-auditing-requirements-have-been-defined-how-are-audit-and-debug-logs-accessed-stored-and-secured "Permalink") + +* 结构化 JSON 日志将写入文件系统,也可以将其提取到 Kibana 安装中以进行进一步分析. \ No newline at end of file diff --git a/docs/498.md b/docs/498.md new file mode 100644 index 0000000000000000000000000000000000000000..6ee1fd250d9db21f9017199d1f30996427ad2db1 --- /dev/null +++ b/docs/498.md @@ -0,0 +1,106 @@ +# Location-aware Git remote URL with AWS Route53 + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/location_aware_git_url.html](https://docs.gitlab.com/ee/administration/geo/replication/location_aware_git_url.html) + +* [Prerequisites](#prerequisites) +* [Create a traffic policy](#create-a-traffic-policy) +* [Configure Git clone URLs to use the special Git URL](#configure-git-clone-urls-to-use-the-special-git-url) +* [Example Git request handling behavior](#example-git-request-handling-behavior) + +# Location-aware Git remote URL with AWS Route53[](#location-aware-git-remote-url-with-aws-route53-premium-only "Permalink") + +您可以为 GitLab 用户提供一个远程 URL,该 URL 自动使用距离他们最近的 Geo 节点. 这意味着用户在移动时无需更新其 Git 配置即可利用更近的 Geo 节点. + +这是可能的,因为 Git 推送请求可以从**辅助**节点自动重定向(HTTP)或代理(SSH)到**主**节点. + +尽管这些说明使用[AWS Route53](https://aws.amazon.com/route53/) ,但也可以使用其他服务,例如[Cloudflare](https://www.cloudflare.com/) . + +**注意:**您还可以使用负载平衡器将 Web UI 或 API 流量分配到[多个 Geo **辅助**节点](../../../user/admin_area/geo_nodes.html#multiple-secondary-nodes-behind-a-load-balancer) . 重要的是,尚不能包含**主**节点. 请参阅功能请求. [支持将**主数据库**放置在 Geo 节点负载均衡器之后](https://gitlab.com/gitlab-org/gitlab/-/issues/10888) . + +## Prerequisites[](#prerequisites "Permalink") + +在此示例中,我们已经设置: + +* `primary.example.com`作为地理**主要**节点. +* `secondary.example.com`作为地理**辅助**节点. + +我们将创建一个`git.example.com`子域,该子域将自动定向请求: + +* 从欧洲到**次要**节点. +* 从所有其他位置到**主**节点. + +无论如何,您都需要: + +* 一个可工作的 GitLab **主**节点,可以在其自己的地址访问. +* 运行中的 GitLab **辅助**节点. +* 一个 Route53 托管区域管理您的域. + +如果尚未设置 Geo **主**节点和**辅助**节点,请查阅[Geo 设置说明](index.html#setup-instructions) . + +## Create a traffic policy[](#create-a-traffic-policy "Permalink") + +在 Route53 托管区域中,可以使用流策略来设置各种路由配置. + +1. 导航到[Route53 仪表板](https://console.aws.amazon.com/route53/home) ,然后单击" **流量策略"** . + + [![Traffic policies](img/05dd8439c1da77198297616b4c4f8458.png)](img/single_git_traffic_policies.png) + +2. 单击**创建流量策略**按钮. + + [![Name policy](img/481f18ff2e4575d1c38d4c93631bd23c.png)](img/single_git_name_policy.png) + +3. 在`Single Git Host`填充**Policy Name**字段,然后单击**Next** . + + [![Policy diagram](img/f8c3e75c59db0de2544d73c590e98696.png)](img/single_git_policy_diagram.png) + +4. Leave **DNS 类型** as `A: IP Address in IPv4 format`. +5. 点击**连接到...,**然后选择**地理位置规则** . + + [![Add geolocation rule](img/ec9eebd0b49b9f0b94eb6d12fadd7cf5.png)](img/single_git_add_geolocation_rule.png) + +6. 对于第一个**位置** ,请将其保留为`Default` . +7. 单击" **连接到...",**然后选择" **新建端点"** . +8. 选择**类型** `value`并用``填写. +9. 对于第二个**位置** ,选择" `Europe` . +10. 单击" **连接到...",**然后选择" **新建端点"** . +11. 选择**类型** `value`并用``填写. + + [![Add traffic policy endpoints](img/bb46a964436bb5fa1becb0900b9b0fc3.png)](img/single_git_add_traffic_policy_endpoints.png) + +12. Click **创建流量策略**. + + [![Create policy records with traffic policy](img/d1e835585272f821d777f384eed6a832.png)](img/single_git_create_policy_records_with_traffic_policy.png) + +13. 使用`git`填写**策略记录 DNS 名称** . +14. Click **创建策略记录**. + + [![Created policy record](img/b62968cd49816ab794ddd37a7dcfb7a2.png)](img/single_git_created_policy_record.png) + +您已经成功设置了一个主机,例如`git.example.com` ,它通过地理位置将流量分配到您的 Geo 节点! + +## Configure Git clone URLs to use the special Git URL[](#configure-git-clone-urls-to-use-the-special-git-url "Permalink") + +用户首次克隆存储库时,通常会从项目页面复制 Git 远程 URL. 默认情况下,这些 SSH 和 HTTP URL 基于当前主机的外部 URL. 例如: + +* `git@secondary.example.com:group1/project1.git` +* `https://secondary.example.com/group1/project1.git` + +[![Clone panel](img/8ec36cbe2f746b6b6cc0d28e1620899a.png)](img/single_git_clone_panel.png) + +您可以自定义: + +* SSH 远程 URL 以使用可`git.example.com`位置的`git.example.com` . 为此,通过在 Web 节点的`gitlab.rb`中设置`gitlab_rails['gitlab_ssh_host']`来更改 SSH 远程 URL 的主机. +* HTTP 远程 URL,如[HTTP(S)的 Custom Git 克隆 URL 中](../../../user/admin_area/settings/visibility_and_access_controls.html#custom-git-clone-url-for-https)所示. + +## Example Git request handling behavior[](#example-git-request-handling-behavior "Permalink") + +完成上述配置步骤后,现在可以识别 Git 请求的位置. 要求: + +* 在欧洲以外,所有请求都定向到**主**节点. +* 在欧洲范围内: + * HTTP: + * `git clone http://git.example.com/foo/bar.git`定向到**辅助**节点. + * `git push`最初定向到**辅助服务器** , **辅助服务器**自动重定向到`primary.example.com` . + * SSH: + * `git clone git@git.example.com:foo/bar.git`被定向到**辅助目录** . + * `git push`首先指向**辅助**服务器, **辅助**服务器自动将请求代理到`primary.example.com` . \ No newline at end of file diff --git a/docs/499.md b/docs/499.md new file mode 100644 index 0000000000000000000000000000000000000000..a8b1dd471f04714855e5d2a0dae29160bc772622 --- /dev/null +++ b/docs/499.md @@ -0,0 +1,16 @@ +# Tuning Geo + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/tuning.html](https://docs.gitlab.com/ee/administration/geo/replication/tuning.html) + +* [Changing the sync capacity values](#changing-the-sync-capacity-values) + +# Tuning Geo[](#tuning-geo-premium-only "Permalink") + +## Changing the sync capacity values[](#changing-the-sync-capacity-values "Permalink") + +在以下位置的"地理管理员"页面中 **管理区>** **Geo** ( `/admin/geo/nodes` ),可以调整一些变量来提高 Geo 的性能: + +* 存储库同步容量. +* 文件同步容量. + +增加这些值将增加计划的作业数量. 但是,除非还增加了可用的 Sidekiq 线程数,否则这可能不会导致更多并行下载. 例如,如果存储库同步容量从 25 增加到 50,您可能还希望将 Sidekiq 线程的数量从 25 增加到 50.有关更多详细信息,请参见[Sidekiq 并发文档](../../operations/extra_sidekiq_processes.html#number-of-threads) . \ No newline at end of file diff --git a/docs/500.md b/docs/500.md new file mode 100644 index 0000000000000000000000000000000000000000..2da4d16fafa3078740a1340ed2f19bfb611a4366 --- /dev/null +++ b/docs/500.md @@ -0,0 +1,53 @@ +# Removing secondary Geo nodes + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/remove_geo_node.html](https://docs.gitlab.com/ee/administration/geo/replication/remove_geo_node.html) + +# Removing secondary Geo nodes[](#removing-secondary-geo-nodes-premium-only "Permalink") + +可以使用**主**节点的地理管理页面从地理集群中删除**辅助**节点. 删除**辅助**节点: + +1. 导航 **管理区>** **地理位置** ( `/admin/geo/nodes` ). +2. 单击要**删除**的**辅助**节点的" **删除"**按钮. +3. 出现提示时,单击" **删除"进行**确认. + +从"地理管理员"页面中删除后,您必须停止并卸载**辅助**节点: + +1. 在**辅助**节点上,停止 GitLab: + + ``` + sudo gitlab-ctl stop + ``` + +2. 在**辅助**节点上,卸载 GitLab: + + ``` + # Stop gitlab and remove its supervision process + sudo gitlab-ctl uninstall + + # Debian/Ubuntu + sudo dpkg --remove gitlab-ee + + # Redhat/Centos + sudo rpm --erase gitlab-ee + ``` + +从**辅助**节点上卸载了 GitLab 之后,必须如下所示从**主**节点的数据库中删除复制插槽: + +1. 在**主**节点上,启动 PostgreSQL 控制台会话: + + ``` + sudo gitlab-psql + ``` + + **注意:**使用`gitlab-rails dbconsole`将不起作用,因为管理复制插槽需要超级用户权限. +2. 查找相关复制插槽的名称. 这是运行复制命令`gitlab-ctl replicate-geo-database`时用`--slot-name`指定的插槽. + + ``` + SELECT * FROM pg_replication_slots; + ``` + +3. 删除**辅助**节点的复制插槽: + + ``` + SELECT pg_drop_replication_slot(''); + ``` \ No newline at end of file diff --git a/docs/501.md b/docs/501.md new file mode 100644 index 0000000000000000000000000000000000000000..61711bc1004f6f039aaa673c64c1f965841ef337 --- /dev/null +++ b/docs/501.md @@ -0,0 +1,148 @@ +# Geo data types support + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/datatypes.html](https://docs.gitlab.com/ee/administration/geo/replication/datatypes.html) + +* [Data types](#data-types) + * [Git repositories](#git-repositories) + * [Blobs](#blobs) + * [Database](#database) +* [Limitations on replication/verification](#limitations-on-replicationverification) + +# Geo data types support[](#geo-data-types-support-premium-only "Permalink") + +地理数据类型是一个或多个 GitLab 功能存储相关信息所需的特定数据类别. + +要使用 Geo 复制这些功能生成的数据,我们使用几种策略来访问,传输和验证它们. + +## Data types[](#data-types "Permalink") + +当前,我们区分三种不同的数据类型: + +* [Git repositories](#git-repositories) +* [Blobs](#blobs) +* [Database](#database) + +请参阅下面列出的我们复制的每个功能或组件,其对应的数据类型,复制和验证方法的列表: + +| Type | 功能/组件 | 复制方式 | 验证方式 | +| --- | --- | --- | --- | +| Database | PostgreSQL 中的应用程序数据 | Native | Native | +| Database | Redis | *N/A* (*1*) | *N/A* | +| Database | Elasticsearch | Native | Native | +| Database | 个人摘要 | PostgreSQL 复制 | PostgreSQL 复制 | +| Database | 项目摘要 | PostgreSQL 复制 | PostgreSQL 复制 | +| Database | SSH 公钥 | PostgreSQL 复制 | PostgreSQL 复制 | +| Git | 项目资料库 | 地理与吉塔利 | Gitaly 校验和 | +| Git | 项目 Wiki 资料库 | 地理与吉塔利 | Gitaly 校验和 | +| Git | 项目设计资料库 | 地理与吉塔利 | Gitaly 校验和 | +| Git | 用于分支项目重复数据删除的对象池 | 地理与吉塔利 | *未实现* | +| Blobs | User uploads *(filesystem)* | 带有 API 的地理位置 | *未实现* | +| Blobs | 用户上传*(对象存储)* | 具有 API /托管的地理区域( *2* ) | *未实现* | +| Blobs | LFS 对象*(文件系统)* | 带有 API 的地理位置 | *未实现* | +| Blobs | LFS 对象*(对象存储)* | 具有 API /托管的地理区域( *2* ) | *未实现* | +| Blobs | CI 作业工件*(文件系统)* | 带有 API 的地理位置 | *未实现* | +| Blobs | CI 作业工件*(对象存储)* | 具有 API /托管的地理区域( *2* ) | *未实现* | +| Blobs | 归档的 CI 构建跟踪*(文件系统)* | 带有 API 的地理位置 | *未实现* | +| Blobs | 归档的 CI 构建跟踪*(对象存储)* | 具有 API /托管的地理区域( *2* ) | *未实现* | +| Blobs | 容器注册表*(文件系统)* | 使用 API​​ / Docker API 进行地理定位 | *未实现* | +| Blobs | 容器注册表*(对象存储)* | 带有 API / Managed / Docker API 的 Geo( *2* ) | *未实现* | +| Blobs | 程序包注册表*(文件系统)* | 带有 API 的地理位置 | *未实现* | +| Blobs | 程序包注册表*(对象存储)* | 具有 API /托管的地理区域( *2* ) | *未实现* | + +* ( *1* ):Redis 复制可与 Redis 前哨一起用作 HA 的一部分. 在地理节点之间不使用它. +* ( *2* ):对象存储复制可以通过 Geo 或您的对象存储提供者/设备本机复制功能来执行. + +### Git repositories[](#git-repositories "Permalink") + +一个 GitLab 实例可以具有一个或多个存储库分片. 每个分片都有一个 Gitaly 实例,该实例负责允许对本地存储的 Git 存储库进行访问和操作. 它可以在具有单个磁盘,作为单个安装点安装多个磁盘(如 RAID 阵列)或使用 LVM 的计算机上运行. + +它不需要特殊的文件系统,并且可以与 NFS 或已安装的 Storage Appliance 一起使用(使用远程文件系统时可能会有性能限制). + +通过 Gitaly 自己的 gRPC API 完成通信. 有三种可能的同步方式: + +* 使用常规的 Git 从一个 Geo 节点到另一个 Geo 节点的克隆/获取(具有特殊身份验证). +* 使用存储库快照(用于第一种方法失败或存储库损坏时). +* 从管理界面手动触发(上述两者的组合). + +每个项目最多可以有 3 个不同的存储库: + +* 一个项目存储库,其中存储了源代码. +* Wiki 存储库,用于存储 Wiki 内容. +* 一个设计库,在其中对设计工件进行索引(资产实际上在 LFS 中). + +他们都住在同一个碎片,并用共享相同的基础名称`-wiki`和`-design`用于 Wiki 以及设计资源库的情况下后缀. + +### Blobs[](#blobs "Permalink") + +GitLab 将文件和 Blob(例如 Issue 附件或 LFS 对象)存储到以下任一位置: + +* 特定位置的文件系统. +* [对象存储](../../object_storage.html)解决方案. 对象存储解决方案可以是: + * 像 Amazon S3 Google Cloud Storage 一样基于云. + * 由您托管(如 MinIO). + * 公开与对象存储兼容的 API 的存储设备. + +当使用文件系统存储而不是对象存储时,如果使用多个服务器,则需要使用网络安装的文件系统来运行 GitLab. + +关于复制和验证: + +* 我们使用内部 API 请求传输文件和 Blob. +* 使用对象存储,您可以: + * 使用云提供程序复制功能. + * 让 GitLab 为您复制它. + +### Database[](#database "Permalink") + +对于不同的用例,GitLab 依赖于存储在多个数据库中的数据. PostgreSQL 是 Web 界面中用户生成的内容(例如问题内容,​​注释以及权限和凭据)的唯一事实. + +PostgreSQL 还可以保存某种程度的缓存数据,例如 HTML 呈现的 Markdown,缓存的合并请求差异(也可以配置为卸载到对象存储中). + +我们使用 PostgreSQL 自己的复制功能将数据从**主**节点复制到**辅助**节点. + +我们将 Redis 用作缓存存储并为我们的后台作业系统保留持久性数据. 由于这两个用例都具有同一地理节点专有的数据,因此我们不在节点之间复制它. + +Elasticsearch 是一个可选数据库,可以启用高级搜索功能,例如源代码级别的改进的全局搜索以及"问题/合并请求"和讨论中用户生成的内容. 目前,Geo 不支持此功能. + +## Limitations on replication/verification[](#limitations-on-replicationverification "Permalink") + +下表列出了 GitLab 功能及其在**辅助**节点上的复制和验证状态. + +您可以跟踪实现这些史诗/问题中缺少的项目的进度: + +* [Unreplicated Data Types](https://gitlab.com/groups/gitlab-org/-/epics/893) +* [Verify all replicated data](https://gitlab.com/groups/gitlab-org/-/epics/1430) + +**危险:**不在此列表上或"已**复制"**列中具有" **否"的**功能不会在**辅助**节点上复制. 如果不从这些功能中手动复制数据而进行故障转移,将导致数据**丢失** . 如果希望在**辅助**节点上使用这些功能或成功执行故障转移,则必须使用其他方法复制它们的数据. + +| Feature | 复制(在 GitLab 版本中添加) | 已验证(在 GitLab 版本中添加) | Notes |   | +| --- | --- | --- | --- | --- | +| PostgreSQL 中的应用程序数据 | **Yes** (10.2) | **Yes** (10.2) |   |   | +| 项目资料库 | **Yes** (10.2) | **Yes** (10.7) |   |   | +| 项目 Wiki 资料库 | **Yes** (10.2) | **Yes** (10.7) |   |   | +| 项目设计资料库 | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) |   |   | +| Uploads | **Yes** (10.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | 仅在转移时验证,或手动验证( *1* ) |   | +| LFS 对象 | **Yes** (10.2) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8922) | 仅在转移时验证,或手动验证( *1* ). 在 11.11.x 和 12.0.x( *2* )中的新 LFS 对象不可用. |   | +| CI 作业工件(痕迹除外) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | 仅手动验证( *1* ) |   | +| 存档的痕迹 | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | 仅在转移时验证,或手动验证( *1* ) |   | +| 个人摘要 | **Yes** (10.2) | **Yes** (10.2) |   |   | +| [Versioned snippets](../../../user/snippets.html#versioned-snippets) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2810) |   |   | +| 项目摘要 | **Yes** (10.2) | **Yes** (10.2) |   |   | +| 用于分支项目重复数据删除的对象池 | **Yes** | No |   |   | +| [Server-side Git hooks](../../server_hooks.html) | No | No |   |   | +| [Elasticsearch integration](../../../integration/elasticsearch.html) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No |   |   | +| [GitLab Pages](../../pages/index.html) | [No](https://gitlab.com/groups/gitlab-org/-/epics/589) | No |   |   | +| [Container Registry](../../packages/container_registry.html) | **Yes** (12.3) | No |   |   | +| [NPM Registry](../../../user/packages/npm_registry/index.html) | **Yes** (13.2) | No |   |   | +| [Maven Repository](../../../user/packages/maven_repository/index.html) | **Yes** (13.2) | No |   |   | +| [Conan Repository](../../../user/packages/conan_repository/index.html) | **Yes** (13.2) | No |   |   | +| [NuGet Repository](../../../user/packages/nuget_repository/index.html) | **Yes** (13.2) | No |   |   | +| [PyPi Repository](../../../user/packages/pypi_repository/index.html) | **Yes** (13.2) | No |   |   | +| [Composer Repository](../../../user/packages/composer_repository/index.html) | **Yes** (13.2) | No |   |   | +| [External merge request diffs](../../merge_request_diffs.html) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/33817) | No |   |   | +| [Terraform State](../../terraform_state.html) | [No](https://gitlab.com/groups/gitlab-org/-/epics/3112)(*3*) | No |   |   | +| [Vulnerability Export](../../../user/application_security/security_dashboard/#export-vulnerabilities) | [No](https://gitlab.com/groups/gitlab-org/-/epics/3111)(*3*) | No |   |   | +| 对象存储中的内容 | **Yes** (12.4) | No |   |   | + +* ( *1* ):可以使用两个节点上的[完整性检查瑞克任务](../../raketasks/check.html)并比较它们之间的输出来手动验证[完整性](../../raketasks/check.html) . +* ( *2* ):GitLab 版本 11.11.x 和 12.0.x 受到[一个错误的](https://gitlab.com/gitlab-org/gitlab/-/issues/32696)影响, [该错误阻止了任何新的 LFS 对象的复制](https://gitlab.com/gitlab-org/gitlab/-/issues/32696) . +* ( *3* ):如果使用的是对象存储,则可以通过对象存储提供程序执行复制(如果支持). 请参阅[带有对象存储的地理位置](object_storage.html) \ No newline at end of file diff --git a/docs/502.md b/docs/502.md new file mode 100644 index 0000000000000000000000000000000000000000..95d07b14c2bfcbcf6cec5e97eee64a4e2479683d --- /dev/null +++ b/docs/502.md @@ -0,0 +1,62 @@ +# Geo Frequently Asked Questions + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/faq.html](https://docs.gitlab.com/ee/administration/geo/replication/faq.html) + +* [What are the minimum requirements to run Geo?](#what-are-the-minimum-requirements-to-run-geo) +* [How does Geo know which projects to sync?](#how-does-geo-know-which-projects-to-sync) +* [Can I use Geo in a disaster recovery situation?](#can-i-use-geo-in-a-disaster-recovery-situation) +* [What data is replicated to a **secondary** node?](#what-data-is-replicated-to-a-secondary-node) +* [Can I `git push` to a **secondary** node?](#can-i-git-push-to-a-secondary-node) +* [How long does it take to have a commit replicated to a **secondary** node?](#how-long-does-it-take-to-have-a-commit-replicated-to-a-secondary-node) +* [What if the SSH server runs at a different port?](#what-if-the-ssh-server-runs-at-a-different-port) +* [Is this possible to set up a Docker Registry for a **secondary** node that mirrors the one on the **primary** node?](#is-this-possible-to-set-up-a-docker-registry-for-a-secondary-node-that-mirrors-the-one-on-the-primary-node) + +# Geo Frequently Asked Questions[](#geo-frequently-asked-questions-premium-only "Permalink") + +## What are the minimum requirements to run Geo?[](#what-are-the-minimum-requirements-to-run-geo "Permalink") + +要求[在索引页面](index.html#requirements-for-running-geo)上列出 + +## How does Geo know which projects to sync?[](#how-does-geo-know-which-projects-to-sync "Permalink") + +在每个**辅助**节点上,都有一个 GitLab 数据库的只读复制副本. **辅助**节点还具有跟踪数据库,其中存储了已同步的项目. Geo 比较这两个数据库以查找尚未跟踪的项目. + +首先,此跟踪数据库为空,因此 Geo 将开始尝试从它在 GitLab 数据库中可以看到的每个项目中进行更新. + +对于每个要同步的项目: + +1. Geo 将发出`git fetch geo --mirror`来从**主**节点获取最新信息. 如果没有更改,则同步将很快并快速结束. 否则,它将提取最新的提交. +2. **辅助**节点将更新跟踪数据库,以存储它已同步项目 A,B,C 等的事实. +3. 重复直到所有项目都同步. + +当有人将提交推送到**主**节点时,它将在 GitLab 数据库中生成一个事件,说明存储库已更改. **辅助**节点看到此事件,将有问题的项目标记为脏,并计划重新同步该项目. + +为确保管道问题(例如,同步失败太多或丢失的作业)不会永久停止项目同步,Geo 还会定期检查跟踪数据库中是否有标记为脏的项目. 当并发同步数降到`repos_max_capacity`以下并且没有新的项目等待同步时,将进行此检查. + +Geo 还具有校验和功能,可在所有对 SHA 值的 Git 引用中运行 SHA256 和. 如果**主**节点和**辅助**节点之间的引用不匹配,则**辅助**节点会将项目标记为脏项目,然后尝试重新同步. 因此,即使我们拥有一个过时的跟踪数据库,验证也应激活并找到存储库状态中的差异并重新同步. + +## Can I use Geo in a disaster recovery situation?[](#can-i-use-geo-in-a-disaster-recovery-situation "Permalink") + +是的,但是我们复制的内容有局限性(请参阅将[哪些数据复制到**辅助**节点?](#what-data-is-replicated-to-a-secondary-node) ). + +阅读[灾难恢复](../disaster_recovery/index.html)文档. + +## What data is replicated to a **secondary** node?[](#what-data-is-replicated-to-a-secondary-node "Permalink") + +当前,我们复制项目存储库,LFS 对象,生成的附件/化身以及整个数据库. 这意味着用户帐户,问题,合并请求,组,项目数据等将可用于查询. + +## Can I `git push` to a **secondary** node?[](#can-i-git-push-to-a-secondary-node "Permalink") + +是! [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3 中[引入](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/)了直接推送到**辅助**节点(对于 HTTP 和 SSH,包括 Git LFS). + +## How long does it take to have a commit replicated to a **secondary** node?[](#how-long-does-it-take-to-have-a-commit-replicated-to-a-secondary-node "Permalink") + +所有复制操作都是异步的,并排队等待分派. 因此,这取决于很多因素,包括流量,提交的大小,节点之间的连接,硬件等. + +## What if the SSH server runs at a different port?[](#what-if-the-ssh-server-runs-at-a-different-port "Permalink") + +很好 我们使用 HTTP 来获取从**主**节点到所有**辅助**节点的存储库更改. + +## Is this possible to set up a Docker Registry for a **secondary** node that mirrors the one on the **primary** node?[](#is-this-possible-to-set-up-a-docker-registry-for-a-secondary-node-that-mirrors-the-one-on-the-primary-node "Permalink") + +是. 有关[**辅助**节点,](docker_registry.html)请参见[Docker Registry](docker_registry.html) . \ No newline at end of file diff --git a/docs/503.md b/docs/503.md new file mode 100644 index 0000000000000000000000000000000000000000..c174199326cc56018ba18e963712f29b83381abf --- /dev/null +++ b/docs/503.md @@ -0,0 +1,844 @@ +# Geo Troubleshooting + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/troubleshooting.html](https://docs.gitlab.com/ee/administration/geo/replication/troubleshooting.html) + +* [Basic troubleshooting](#basic-troubleshooting) + * [Check the health of the **secondary** node](#check-the-health-of-the-secondary-node) + * [Check if PostgreSQL replication is working](#check-if-postgresql-replication-is-working) + * [Are nodes pointing to the correct database instance?](#are-nodes-pointing-to-the-correct-database-instance) + * [Can Geo detect the current node correctly?](#can-geo-detect-the-current-node-correctly) +* [Fixing errors found when running the Geo check Rake task](#fixing-errors-found-when-running-the-geo-check-rake-task) +* [Fixing replication errors](#fixing-replication-errors) + * [Message: `ERROR: replication slots can only be used if max_replication_slots > 0`?](#message-error--replication-slots-can-only-be-used-if-max_replication_slots--0) + * [Message: `FATAL: could not start WAL streaming: ERROR: replication slot "geo_secondary_my_domain_com" does not exist`?](#message-fatal--could-not-start-wal-streaming-error--replication-slot-geo_secondary_my_domain_com-does-not-exist) + * [Message: “Command exceeded allowed execution time” when setting up replication?](#message-command-exceeded-allowed-execution-time-when-setting-up-replication) + * [Message: “PANIC: could not write to file `pg_xlog/xlogtemp.123`: No space left on device”](#message-panic-could-not-write-to-file-pg_xlogxlogtemp123-no-space-left-on-device) + * [Message: “ERROR: canceling statement due to conflict with recovery”](#message-error-canceling-statement-due-to-conflict-with-recovery) + * [Message: `LOG: invalid CIDR mask in address`](#message-log--invalid-cidr-mask-in-address) + * [Message: `LOG: invalid IP mask "md5": Name or service not known`](#message-log--invalid-ip-mask-md5-name-or-service-not-known) + * [Very large repositories never successfully synchronize on the **secondary** node](#very-large-repositories-never-successfully-synchronize-on-the-secondary-node) + * [New LFS objects are never replicated](#new-lfs-objects-are-never-replicated) + * [Resetting Geo **secondary** node replication](#resetting-geo-secondary-node-replication) +* [Fixing errors during a failover or when promoting a secondary to a primary node](#fixing-errors-during-a-failover-or-when-promoting-a-secondary-to-a-primary-node) + * [Message: ActiveRecord::RecordInvalid: Validation failed: Name has already been taken](#message-activerecordrecordinvalid-validation-failed-name-has-already-been-taken) + * [Message: `NoMethodError: undefined method `secondary?' for nil:NilClass`](#message-nomethoderror-undefined-method-secondary-for-nilnilclass) + * [Message: `sudo: gitlab-pg-ctl: command not found`](#message-sudo-gitlab-pg-ctl-command-not-found) +* [Fixing Foreign Data Wrapper errors](#fixing-foreign-data-wrapper-errors) + * [“Foreign Data Wrapper (FDW) is not configured” error](#foreign-data-wrapper-fdw-is-not-configured-error) + * [Checking configuration](#checking-configuration) + * [Manual reload of FDW schema](#manual-reload-of-fdw-schema) + * [“Geo database has an outdated FDW remote schema” error](#geo-database-has-an-outdated-fdw-remote-schema-error) +* [Expired artifacts](#expired-artifacts) +* [Fixing sign in errors](#fixing-sign-in-errors) + * [Message: The redirect URI included is not valid](#message-the-redirect-uri-included-is-not-valid) +* [Fixing common errors](#fixing-common-errors) + * [Geo database configuration file is missing](#geo-database-configuration-file-is-missing) + * [An existing tracking database cannot be reused](#an-existing-tracking-database-cannot-be-reused) + * [Geo node has a database that is writable which is an indication it is not configured for replication with the primary node](#geo-node-has-a-database-that-is-writable-which-is-an-indication-it-is-not-configured-for-replication-with-the-primary-node) + * [Geo node does not appear to be replicating the database from the primary node](#geo-node-does-not-appear-to-be-replicating-the-database-from-the-primary-node) + * [Geo database version (…) does not match latest migration (…)](#geo-database-version--does-not-match-latest-migration-) + * [Geo database is not configured to use Foreign Data Wrapper](#geo-database-is-not-configured-to-use-foreign-data-wrapper) + * [GitLab indicates that more than 100% of repositories were synced](#gitlab-indicates-that-more-than-100-of-repositories-were-synced) + * [Geo Admin Area returns 404 error for a secondary node](#geo-admin-area-returns-404-error-for-a-secondary-node) + +# Geo Troubleshooting[](#geo-troubleshooting-premium-only "Permalink") + +设置地理位置需要仔细注意细节,有时很容易错过一个步骤. + +这是您尝试解决问题应采取的步骤的列表: + +* Perform [basic troubleshooting](#basic-troubleshooting). +* 修复所有[复制错误](#fixing-replication-errors) . +* 修复任何[外部数据包装程序](#fixing-foreign-data-wrapper-errors)错误. +* 修复所有[常见](#fixing-common-errors)错误. + +## Basic troubleshooting[](#basic-troubleshooting "Permalink") + +在尝试更高级的故障排除之前: + +* Check [the health of the **secondary** node](#check-the-health-of-the-secondary-node). +* Check [if PostgreSQL replication is working](#check-if-postgresql-replication-is-working). + +### Check the health of the **secondary** node[](#check-the-health-of-the-secondary-node "Permalink") + +访问**主**节点的 **管理区>** 浏览器中的**地理位置** ( `/admin/geo/nodes` ). 我们在每个**辅助**节点上执行以下运行状况检查,以帮助识别是否存在问题: + +* 节点是否在运行? +* 节点的辅助数据库是否已配置用于流复制? +* 是否已配置节点的辅助跟踪数据库? +* 节点的辅助跟踪数据库是否已连接? +* 节点的辅助跟踪数据库是否是最新的? + +[![Geo health check](img/11728974fe5385112311ab02ea56783e.png)](img/geo_node_healthcheck.png) + +有关如何解决从 UI 报告的常见错误的信息,请参阅" [修复常见错误"](#fixing-common-errors) . + +如果用户界面无法正常工作,或者您无法登录,则可以手动运行地理健康检查以获取此信息以及更多详细信息. + +此 Rake 任务可以在**主要**或**辅助** Geo 节点中的应用程序节点上运行: + +``` +sudo gitlab-rake gitlab:geo:check +``` + +输出示例: + +``` +Checking Geo ... + +GitLab Geo is available ... yes +GitLab Geo is enabled ... yes +This machine's Geo node name matches a database record ... yes, found a secondary node named "Shanghai" +GitLab Geo secondary database is correctly configured ... yes +Database replication enabled? ... yes +Database replication working? ... yes +GitLab Geo tracking database is configured to use Foreign Data Wrapper? ... yes +GitLab Geo tracking database Foreign Data Wrapper schema is up-to-date? ... yes +GitLab Geo HTTP(S) connectivity ... +* Can connect to the primary node ... yes +HTTP/HTTPS repository cloning is enabled ... yes +Machine clock is synchronized ... yes +Git user has default SSH configuration? ... yes +OpenSSH configured to use AuthorizedKeysCommand ... yes +GitLab configured to disable writing to authorized_keys file ... yes +GitLab configured to store new projects in hashed storage? ... yes +All projects are in hashed storage? ... yes + +Checking Geo ... Finished +``` + +通过在任何**辅助**应用程序节点上运行以下 Rake 任务,可以手动找到当前同步信息: + +``` +sudo gitlab-rake geo:status +``` + +输出示例: + +``` +http://secondary.example.com/ +----------------------------------------------------- + GitLab Version: 11.10.4-ee + Geo Role: Secondary + Health Status: Healthy + Repositories: 289/289 (100%) + Verified Repositories: 289/289 (100%) + Wikis: 289/289 (100%) + Verified Wikis: 289/289 (100%) + LFS Objects: 8/8 (100%) + Attachments: 5/5 (100%) + CI job artifacts: 0/0 (0%) + Repositories Checked: 0/289 (0%) + Sync Settings: Full + Database replication lag: 0 seconds + Last event ID seen from primary: 10215 (about 2 minutes ago) + Last event ID processed by cursor: 10215 (about 2 minutes ago) + Last status report was: 2 minutes ago +``` + +### Check if PostgreSQL replication is working[](#check-if-postgresql-replication-is-working "Permalink") + +要检查 PostgreSQL 复制是否正常,请检查: + +* [Nodes are pointing to the correct database instance](#are-nodes-pointing-to-the-correct-database-instance). +* [Geo can detect the current node correctly](#can-geo-detect-the-current-node-correctly). + +#### Are nodes pointing to the correct database instance?[](#are-nodes-pointing-to-the-correct-database-instance "Permalink") + +您应确保**主**地理节点指向具有写入权限的实例. + +任何**辅助**节点都应仅指向只读实例. + +#### Can Geo detect the current node correctly?[](#can-geo-detect-the-current-node-correctly "Permalink") + +Geo 通过以下方式在`/etc/gitlab/gitlab.rb`找到当前计算机的 Geo 节点名称: + +* 使用`gitlab_rails['geo_node_name']`设置. +* 如果未定义,请使用`external_url`设置. + +该名称用于在其中查找具有相同**名称**的节点 **管理区>** **地理位置** . + +要检查当前计算机的节点名称是否与数据库中的节点匹配,请运行检查任务: + +``` +sudo gitlab-rake gitlab:geo:check +``` + +它显示当前计算机的节点名称以及匹配的数据库记录是**主**节点还是**辅助**节点. + +``` +This machine's Geo node name matches a database record ... yes, found a secondary node named "Shanghai" +``` + +``` +This machine's Geo node name matches a database record ... no + Try fixing it: + You could add or update a Geo node database record, setting the name to "https://example.com/". + Or you could set this machine's Geo node name to match the name of an existing database record: "London", "Shanghai" + For more information see: + doc/administration/geo/replication/troubleshooting.md#can-geo-detect-the-current-node-correctly +``` + +## Fixing errors found when running the Geo check Rake task[](#fixing-errors-found-when-running-the-geo-check-rake-task "Permalink") + +运行此 Rake 任务时,如果未正确配置节点,则可能会看到错误: + +``` +sudo gitlab-rake gitlab:geo:check +``` + +1. 连接到数据库时,Rails 没有提供密码 + + ``` + Checking Geo ... + + GitLab Geo is available ... Exception: fe_sendauth: no password supplied + GitLab Geo is enabled ... Exception: fe_sendauth: no password supplied + ... + Checking Geo ... Finished + ``` + + * 确保将`gitlab_rails['db_password']`设置为为`postgresql['sql_user_password']`创建哈希时使用的纯文本密码. +2. Rails 无法连接到数据库 + + ``` + Checking Geo ... + + GitLab Geo is available ... Exception: FATAL: no pg_hba.conf entry for host "1.1.1.1", user "gitlab", database "gitlabhq_production", SSL on + FATAL: no pg_hba.conf entry for host "1.1.1.1", user "gitlab", database "gitlabhq_production", SSL off + GitLab Geo is enabled ... Exception: FATAL: no pg_hba.conf entry for host "1.1.1.1", user "gitlab", database "gitlabhq_production", SSL on + FATAL: no pg_hba.conf entry for host "1.1.1.1", user "gitlab", database "gitlabhq_production", SSL off + ... + Checking Geo ... Finished + ``` + + * 确保您具有`postgresql['md5_auth_cidr_addresses']`包含的 rails 节点的 IP 地址. + * 确保在 IP 地址上包括子网掩码: `postgresql['md5_auth_cidr_addresses'] = ['1.1.1.1/32']` . +3. Rails 提供了错误的密码 + + ``` + Checking Geo ... + GitLab Geo is available ... Exception: FATAL: password authentication failed for user "gitlab" + FATAL: password authentication failed for user "gitlab" + GitLab Geo is enabled ... Exception: FATAL: password authentication failed for user "gitlab" + FATAL: password authentication failed for user "gitlab" + ... + Checking Geo ... Finished + ``` + + * 验证正确的密码设置为`gitlab_rails['db_password']`创建中的散列时所使用`postgresql['sql_user_password']`通过运行`gitlab-ctl pg-password-md5 gitlab`并输入密码. +4. 检查返回的不是辅助节点 + + ``` + Checking Geo ... + + GitLab Geo is available ... yes + GitLab Geo is enabled ... yes + GitLab Geo secondary database is correctly configured ... not a secondary node + Database replication enabled? ... not a secondary node + ... + Checking Geo ... Finished + ``` + + * 确保您已在**主**节点的管理区添加辅助节点. + * 在管理节点中添加辅助节点属于**主**节点时,请确保输入了`external_url`或`gitlab_rails['geo_node_name']` . + * 之前 GitLab 12.4,编辑中的**主**节点的管理区的二次节点,并确保有一个尾随`/`在`Name`字段中. +5. 检查返回`Exception: PG::UndefinedTable: ERROR: relation "geo_nodes" does not exist` + + ``` + Checking Geo ... + + GitLab Geo is available ... no + Try fixing it: + Upload a new license that includes the GitLab Geo feature + For more information see: + https://about.gitlab.com/features/gitlab-geo/ + GitLab Geo is enabled ... Exception: PG::UndefinedTable: ERROR: relation "geo_nodes" does not exist + LINE 8: WHERE a.attrelid = '"geo_nodes"'::regclass + ^ + : SELECT a.attname, format_type(a.atttypid, a.atttypmod), + pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod, + c.collname, col_description(a.attrelid, a.attnum) AS comment + FROM pg_attribute a + LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum + LEFT JOIN pg_type t ON a.atttypid = t.oid + LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation + WHERE a.attrelid = '"geo_nodes"'::regclass + AND a.attnum > 0 AND NOT a.attisdropped + ORDER BY a.attnum + ... + Checking Geo ... Finished + ``` + + 在执行 PostgreSQL 主版本(9> 10)时,这是预期的. 跟随: + + * [initiate-the-replication-process](database.html#step-3-initiate-the-replication-process) + * [Geo database has an outdated FDW remote schema](troubleshooting.html#geo-database-has-an-outdated-fdw-remote-schema-error) + +## Fixing replication errors[](#fixing-replication-errors "Permalink") + +以下各节概述了解决复制错误的疑难解答步骤. + +### Message: `ERROR: replication slots can only be used if max_replication_slots > 0`?[](#message-error--replication-slots-can-only-be-used-if-max_replication_slots--0 "Permalink") + +这意味着需要在**主**数据库上设置`max_replication_slots` PostgreSQL 变量. 在 GitLab 9.4 中,我们将此设置默认设置为 1.如果您有更多**辅助**节点,则可能需要增加该值. + +确保重新启动 PostgreSQL 才能生效. 有关更多详细信息,请参见《 [PostgreSQL 复制设置](database.html#postgresql-replication)指南》. + +### Message: `FATAL: could not start WAL streaming: ERROR: replication slot "geo_secondary_my_domain_com" does not exist`?[](#message-fatal--could-not-start-wal-streaming-error--replication-slot-geo_secondary_my_domain_com-does-not-exist "Permalink") + +当 PostgreSQL 没有该名称的**辅助**节点的复制插槽时,会发生这种情况. + +您可能需要在**辅助**节点上重新运行[复制过程](database.html) . + +### Message: “Command exceeded allowed execution time” when setting up replication?[](#message-command-exceeded-allowed-execution-time-when-setting-up-replication "Permalink") + +在**辅助**节点上[启动复制过程](database.html#step-3-initiate-the-replication-process)时可能会发生这种情况,并表明您的初始数据集太大,无法在默认超时(30 分钟)内进行复制. + +重新运行`gitlab-ctl replicate-geo-database` ,但是为`--backup-timeout`包含一个更大的值: + +``` +sudo gitlab-ctl \ + replicate-geo-database \ + --host= \ + --slot-name= \ + --backup-timeout=21600 +``` + +这将使初始复制最多需要六个小时才能完成,而不是默认的三十分钟. 根据安装要求进行调整. + +### Message: “PANIC: could not write to file `pg_xlog/xlogtemp.123`: No space left on device”[](#message-panic-could-not-write-to-file-pg_xlogxlogtemp123-no-space-left-on-device "Permalink") + +确定**主**数据库中是否有未使用的复制插槽. 这可能导致在`pg_xlog`建立大量的日志数据. 删除未使用的插槽可以减少`pg_xlog`使用的空间. + +1. 启动 PostgreSQL 控制台会话: + + ``` + sudo gitlab-psql + ``` + + 注意: **注意:**使用`gitlab-rails dbconsole`无效,因为管理复制插槽需要超级用户权限. + +2. 使用以下方法查看您的复制插槽: + + ``` + SELECT * FROM pg_replication_slots; + ``` + +`active`为`f`插槽不活动. + +* 当该插槽应处于活动状态时,因为您已使用该插槽配置了**辅助**节点,请登录到该**辅助**节点,并检查 PostgreSQL 日志为什么复制未运行. + +* 如果您不再使用该插槽(例如,您不再启用地理位置),则可以在 PostgreSQL 控制台会话中将其删除: + + ``` + SELECT pg_drop_replication_slot(''); + ``` + +### Message: “ERROR: canceling statement due to conflict with recovery”[](#message-error-canceling-statement-due-to-conflict-with-recovery "Permalink") + +在正常使用情况下,此错误很少会发生,并且系统具有足够的恢复能力. + +但是,在某些情况下,辅助数据库上的某些数据库查询可能运行时间过长,从而增加了此错误的发生频率. 在某些时候,其中某些查询由于每次都会被取消而永远无法完成. + +这些长期运行的查询[计划在将来删除](https://gitlab.com/gitlab-org/gitlab/-/issues/34269) ,但作为解决方法,我们建议启用[hot_standby_feedback](https://s0www0postgresql0org.icopy.site/docs/10/hot-standby.html) . 这增加了**主**节点上发生膨胀的可能性,因为它阻止了`VACUUM`删除最近失效的行. 但是,它已在 GitLab.com 上成功用于生产中. + +要启用`hot_standby_feedback` ,请将以下内容添加到**辅助**节点上的`/etc/gitlab/gitlab.rb` : + +``` +postgresql['hot_standby_feedback'] = 'on' +``` + +然后重新配置 GitLab: + +``` +sudo gitlab-ctl reconfigure +``` + +为了帮助我们解决这个问题,可以考虑在评论[这个问题](https://gitlab.com/gitlab-org/gitlab/-/issues/4489) . + +### Message: `LOG: invalid CIDR mask in address`[](#message-log--invalid-cidr-mask-in-address "Permalink") + +这发生在`postgresql['md5_auth_cidr_addresses']`格式错误的地址上. + +``` +2020-03-20_23:59:57.60499 LOG: invalid CIDR mask in address "***" +2020-03-20_23:59:57.60501 CONTEXT: line 74 of configuration file "/var/opt/gitlab/postgresql/data/pg_hba.conf" +``` + +要解决此问题,请更新`postgresql['md5_auth_cidr_addresses']`下`/etc/gitlab/gitlab.rb`的 IP 地址,以遵守 CIDR 格式(即`1.2.3.4/32` ). + +### Message: `LOG: invalid IP mask "md5": Name or service not known`[](#message-log--invalid-ip-mask-md5-name-or-service-not-known "Permalink") + +当您在`postgresql['md5_auth_cidr_addresses']`添加了没有子网掩码的 IP 地址时,就会发生这种情况. + +``` +2020-03-21_00:23:01.97353 LOG: invalid IP mask "md5": Name or service not known +2020-03-21_00:23:01.97354 CONTEXT: line 75 of configuration file "/var/opt/gitlab/postgresql/data/pg_hba.conf" +``` + +要解决此问题, `/etc/gitlab/gitlab.rb`在`postgresql['md5_auth_cidr_addresses']`下`postgresql['md5_auth_cidr_addresses']`添加子网掩码,以遵守 CIDR 格式(即`1.2.3.4/32` ). + +### Very large repositories never successfully synchronize on the **secondary** node[](#very-large-repositories-never-successfully-synchronize-on-the-secondary-node "Permalink") + +GitLab 对所有存储库克隆都设置了超时,包括项目导入和地理同步操作. 如果**主数据库**上的存储库的新`git clone`花费几分钟以上,则您可能会受到此影响. + +要增加超时,请将以下行添加到**辅助**节点上的`/etc/gitlab/gitlab.rb` : + +``` +gitlab_rails['gitlab_shell_git_timeout'] = 10800 +``` + +然后重新配置 GitLab: + +``` +sudo gitlab-ctl reconfigure +``` + +这会将超时增加到三个小时(10800 秒). 选择足够长的时间来容纳您最大的存储库的完整克隆. + +### New LFS objects are never replicated[](#new-lfs-objects-are-never-replicated "Permalink") + +如果新的 LFS 对象永远不会复制到辅助 Geo 节点,请检查您正在运行的 GitLab 版本. GitLab 版本 11.11.x 或 12.0.x 受[错误](https://gitlab.com/gitlab-org/gitlab/-/issues/32696)影响, [该错误导致新的 LFS 对象无法复制到 Geo 辅助节点](https://gitlab.com/gitlab-org/gitlab/-/issues/32696) . + +要解决此问题,请升级到 GitLab 12.1 或更高版本. + +### Resetting Geo **secondary** node replication[](#resetting-geo-secondary-node-replication "Permalink") + +如果您使**辅助**节点处于损坏状态,并且想要重置复制状态(从头开始),那么可以采取以下步骤来帮助您: + +1. 停止 Sidekiq 和 Geo LogCursor + + 可以使 Sidekiq 正常停止,但可以使其停止获取新作业,并等到当前作业完成处理为止. + + 您需要在第一阶段发送**SIGTSTP 终止**信号,并在所有作业完成后向它们发送**SIGTERM** . 否则,只需使用`gitlab-ctl stop`命令. + + ``` + gitlab-ctl status sidekiq + # run: sidekiq: (pid 10180) <- this is the PID you will use + kill -TSTP 10180 # change to the correct PID + + gitlab-ctl stop sidekiq + gitlab-ctl stop geo-logcursor + ``` + + 您可以查看 Sidekiq 日志以了解 Sidekiq 作业处理何时完成: + + ``` + gitlab-ctl tail sidekiq + ``` + +2. 重命名存储库存储文件夹并创建新的. 如果您不担心可能的孤立目录和文件,则只需跳过此步骤. + + ``` + mv /var/opt/gitlab/git-data/repositories /var/opt/gitlab/git-data/repositories.old + mkdir -p /var/opt/gitlab/git-data/repositories + chown git:git /var/opt/gitlab/git-data/repositories + ``` + + **提示**您可能希望将来在确认不再需要`/var/opt/gitlab/git-data/repositories.old`时将其删除,以节省磁盘空间. +3. *(可选)*重命名其他数据文件夹并创建新的 + + **警告** : **辅助**节点上可能仍有文件已从**主**节点中删除,但未反映出删除情况. 如果您跳过此步骤,它们将永远不会从此 Geo 节点中删除. + + 任何上载的内容(如文件附件,化身或 LFS 对象)都存储在以下两个路径之一的子文件夹中: + + * `/var/opt/gitlab/gitlab-rails/shared` + * `/var/opt/gitlab/gitlab-rails/uploads` + + 要重命名它们: + + ``` + gitlab-ctl stop + + mv /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-rails/shared.old + mkdir -p /var/opt/gitlab/gitlab-rails/shared + + mv /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/uploads.old + mkdir -p /var/opt/gitlab/gitlab-rails/uploads + + gitlab-ctl start geo-postgresql + ``` + + 重新配置以便重新创建文件夹并确保权限和所有权正确 + + ``` + gitlab-ctl reconfigure + ``` + +4. 重置跟踪数据库 + + ``` + gitlab-rake geo:db:drop # on a secondary app node + gitlab-ctl reconfigure # on the tracking database node + gitlab-rake geo:db:setup # on a secondary app node + ``` + +5. 重新启动先前停止的服务 + + ``` + gitlab-ctl start + ``` + +6. 刷新外部数据包装器表 + + ``` + gitlab-rake geo:db:refresh_foreign_tables + ``` + +## Fixing errors during a failover or when promoting a secondary to a primary node[](#fixing-errors-during-a-failover-or-when-promoting-a-secondary-to-a-primary-node "Permalink") + +以下是故障转移期间或通过解决策略将辅助节点提升为主节点时可能遇到的错误. + +### Message: ActiveRecord::RecordInvalid: Validation failed: Name has already been taken[](#message-activerecordrecordinvalid-validation-failed-name-has-already-been-taken "Permalink") + +[升级**辅助**节点时](../disaster_recovery/index.html#step-3-promoting-a-secondary-node) ,您可能会遇到以下错误: + +``` +Running gitlab-rake geo:set_secondary_as_primary... + +rake aborted! +ActiveRecord::RecordInvalid: Validation failed: Name has already been taken +/opt/gitlab/embedded/service/gitlab-rails/ee/lib/tasks/geo.rake:236:in `block (3 levels) in ' +/opt/gitlab/embedded/service/gitlab-rails/ee/lib/tasks/geo.rake:221:in `block (2 levels) in ' +/opt/gitlab/embedded/bin/bundle:23:in `load' +/opt/gitlab/embedded/bin/bundle:23:in `
      ' +Tasks: TOP => geo:set_secondary_as_primary +(See full trace by running task with --trace) + +You successfully promoted this node! +``` + +如果您在运行`gitlab-rake geo:set_secondary_as_primary`或`gitlab-ctl promote-to-primary-node`时遇到此消息,请执行`gitlab-rake geo:set_secondary_as_primary`任一操作: + +* 输入 Rails 控制台并运行: + + ``` + Rails.application.load_tasks; nil + Gitlab::Geo.expire_cache! + Rake::Task['geo:set_secondary_as_primary'].invoke + ``` + +* 如果安全的话,升级到 GitLab 12.6.3 或更高版本. 例如,如果故障转移只是一个测试. [缓存相关的错误](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22021)是固定的. + +### Message: `NoMethodError: undefined method `secondary?' for nil:NilClass`[](#message-nomethoderror-undefined-method-secondary-for-nilnilclass "Permalink") + +[升级**辅助**节点时](../disaster_recovery/index.html#step-3-promoting-a-secondary-node) ,您可能会遇到以下错误: + +``` +sudo gitlab-rake geo:set_secondary_as_primary + +rake aborted! +NoMethodError: undefined method `secondary?' for nil:NilClass +/opt/gitlab/embedded/service/gitlab-rails/ee/lib/tasks/geo.rake:232:in `block (3 levels) in ' +/opt/gitlab/embedded/service/gitlab-rails/ee/lib/tasks/geo.rake:221:in `block (2 levels) in ' +/opt/gitlab/embedded/bin/bundle:23:in `load' +/opt/gitlab/embedded/bin/bundle:23:in `
      ' +Tasks: TOP => geo:set_secondary_as_primary +(See full trace by running task with --trace) +``` + +该命令仅应在辅助节点上执行,如果尝试在主节点上运行此命令,则会显示此错误. + +### Message: `sudo: gitlab-pg-ctl: command not found`[](#message-sudo-gitlab-pg-ctl-command-not-found "Permalink") + +When [promoting a **secondary** node with multiple servers](../disaster_recovery/index.html#promoting-a-secondary-node-with-multiple-servers), you need to run the `gitlab-pg-ctl` command to promote the PostgreSQL read-replica database. + +在 GitLab 12.8 和更早版本中,此命令将失败,并显示以下消息: + +``` +sudo: gitlab-pg-ctl: command not found +``` + +在这种情况下,解决方法是使用二进制文件的完整路径,例如: + +``` +sudo /opt/gitlab/embedded/bin/gitlab-pg-ctl promote +``` + +GitLab 12.9 及更高版本[不受此错误影响](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5147) . + +## Fixing Foreign Data Wrapper errors[](#fixing-foreign-data-wrapper-errors "Permalink") + +本节介绍解决潜在的外部数据包装器错误的方法. + +### “Foreign Data Wrapper (FDW) is not configured” error[](#foreign-data-wrapper-fdw-is-not-configured-error "Permalink") + +When setting up Geo, you might see this warning in the `gitlab-rake gitlab:geo:check` output: + +``` +GitLab Geo tracking database Foreign Data Wrapper schema is up-to-date? ... foreign data wrapper is not configured +``` + +有几点要记住: + +1. FDW 设置在地理**跟踪**数据库上配置. +2. 配置的外部服务器允许登录到 Geo **二级**只读数据库. + +默认情况下,Geo 辅助数据库和跟踪数据库在不同端口上的同一主机上运行. 即分别是 5432 和 5431. + +#### Checking configuration[](#checking-configuration "Permalink") + +**注意:**以下步骤仅适用于 Omnibus 安装. 在 GitLab 11.5 中**已不建议**在基于源的安装中使用 Geo. + +要检查配置: + +1. SSH 进入**辅助**节点中的应用程序节点: + + ``` + sudo -i + ``` + + 注意:应用程序节点是指至少运行以下服务之一的任何计算机: + + * `puma` + * `unicorn` + * `sidekiq` + * `geo-logcursor` +2. 输入数据库控制台: + + 如果跟踪数据库在同一节点上运行: + + ``` + gitlab-geo-psql + ``` + + 或者,如果跟踪数据库在其他节点上运行,则在进入数据库控制台时必须指定用户和主机: + + ``` + gitlab-geo-psql -U gitlab_geo -h + ``` + + 系统将提示您输入`gitlab_geo`用户的密码. 您可以在`/etc/gitlab/gitlab.rb`以纯文本`/etc/gitlab/gitlab.rb`找到它: + + ``` + geo_secondary['db_password'] = '' + ``` + + 通常在[步骤 3:在辅助节点上配置跟踪数据库时在跟踪数据库上](multiple_servers.html#step-3-configure-the-tracking-database-on-the-secondary-node)设置此密码,而在[步骤 4:在辅助节点上配置前端应用程序服务器](multiple_servers.html#step-4-configure-the-frontend-application-servers-on-the-secondary-node)期间在应用程序节点上设置该密码. + +3. 使用以下语句检查是否存在任何表: + + ``` + SELECT * from information_schema.foreign_tables; + ``` + + 如果一切正常,您应该看到类似以下内容: + + ``` + gitlabhq_geo_production=# SELECT * from information_schema.foreign_tables; + foreign_table_catalog | foreign_table_schema | foreign_table_name | foreign_server_catalog | foreign_server_name + -------------------------+----------------------+-------------------------------------------------+-------------------------+--------------------- + gitlabhq_geo_production | gitlab_secondary | abuse_reports | gitlabhq_geo_production | gitlab_secondary + gitlabhq_geo_production | gitlab_secondary | appearances | gitlabhq_geo_production | gitlab_secondary + gitlabhq_geo_production | gitlab_secondary | application_setting_terms | gitlabhq_geo_production | gitlab_secondary + gitlabhq_geo_production | gitlab_secondary | application_settings | gitlabhq_geo_production | gitlab_secondary + + ``` + + 但是,如果查询返回`0 rows` ,则继续进行下一步. + +4. 通过`\des+`检查外部服务器映射是否正确. 结果应如下所示: + + ``` + gitlabhq_geo_production=# \des+ + List of foreign servers + -[ RECORD 1 ]--------+------------------------------------------------------------ + Name | gitlab_secondary + Owner | gitlab-psql + Foreign-data wrapper | postgres_fdw + Access privileges | "gitlab-psql"=U/"gitlab-psql" + + | gitlab_geo=U/"gitlab-psql" + Type | + Version | + FDW Options | (host '0.0.0.0', port '5432', dbname 'gitlabhq_production') + Description | + ``` + + **注意:请**特别注意 FDW 选项下的主机和端口. 该配置应指向地理辅助数据库. + + 如果需要尝试更改主机或密码,则以下查询演示了如何: + + ``` + ALTER SERVER gitlab_secondary OPTIONS (SET host ''); + ALTER SERVER gitlab_secondary OPTIONS (SET port 5432); + ``` + + 如果更改主机和/或端口,则还必须在`/etc/gitlab/gitlab.rb`调整以下设置并运行`gitlab-ctl reconfigure` : + + * `gitlab_rails['db_host']` + * `gitlab_rails['db_port']` +5. 检查通过`\deu+`是否正确配置了用户映射: + + ``` + gitlabhq_geo_production=# \deu+ + List of user mappings + Server | User name | FDW Options + ------------------+------------+-------------------------------------------------------------------------------- + gitlab_secondary | gitlab_geo | ("user" 'gitlab', password 'YOUR-PASSWORD-HERE') + (1 row) + ``` + + 确保密码正确. 您可以通过运行`psql`来测试登录是否有效: + + ``` + # Connect to the tracking database as the `gitlab_geo` user + sudo \ + -u git /opt/gitlab/embedded/bin/psql \ + -h /var/opt/gitlab/geo-postgresql \ + -p 5431 \ + -U gitlab_geo \ + -W \ + -d gitlabhq_geo_production + ``` + + 如果需要更正密码,以下查询将显示如何: + + ``` + ALTER USER MAPPING FOR gitlab_geo SERVER gitlab_secondary OPTIONS (SET password ''); + ``` + + 如果更改用户或密码,则还必须在`/etc/gitlab/gitlab.rb`调整以下设置并运行`gitlab-ctl reconfigure` : + + * `gitlab_rails['db_username']` + * `gitlab_rails['db_password']` + + 如果要[在辅助数据库前面](database.html#pgbouncer-support-optional)使用[PgBouncer](database.html#pgbouncer-support-optional) ,请确保更新以下设置: + + * `geo_postgresql['fdw_external_user']` + * `geo_postgresql['fdw_external_password']` + +#### Manual reload of FDW schema[](#manual-reload-of-fdw-schema "Permalink") + +如果仍然无法使 FDW 正常工作,则可能需要尝试手动重新加载 FDW 模式. 手动重新加载 FDW 模式: + +1. 在运行 Geo 跟踪数据库的节点上,通过`gitlab_geo`用户进入 PostgreSQL 控制台: + + ``` + sudo \ + -u git /opt/gitlab/embedded/bin/psql \ + -h /var/opt/gitlab/geo-postgresql \ + -p 5431 \ + -U gitlab_geo \ + -W \ + -d gitlabhq_geo_production + ``` + + 确保为您的配置调整端口和主机名. 可能会要求您输入密码. + +2. 通过以下方式重新加载架构: + + ``` + DROP SCHEMA IF EXISTS gitlab_secondary CASCADE; + CREATE SCHEMA gitlab_secondary; + GRANT USAGE ON FOREIGN SERVER gitlab_secondary TO gitlab_geo; + IMPORT FOREIGN SCHEMA public FROM SERVER gitlab_secondary INTO gitlab_secondary; + ``` + +3. 测试查询是否有效: + + ``` + SELECT * from information_schema.foreign_tables; + SELECT * FROM gitlab_secondary.projects limit 1; + ``` + +### “Geo database has an outdated FDW remote schema” error[](#geo-database-has-an-outdated-fdw-remote-schema-error "Permalink") + +GitLab 可能会因`Geo database has an outdated FDW remote schema`错误`Geo database has an outdated FDW remote schema`消息而出错. + +例如: + +``` +Geo database has an outdated FDW remote schema. It contains 229 of 236 expected tables. Please refer to Geo Troubleshooting. +``` + +要解决此问题,请在**辅助服务器**上运行以下命令: + +``` +sudo gitlab-rake geo:db:refresh_foreign_tables +``` + +## Expired artifacts[](#expired-artifacts "Permalink") + +如果您出于某种原因注意到,地理辅助节点上的工件比地理主节点上的工件更多,则可以使用 Rake 任务来[清理孤立的工件文件](../../../raketasks/cleanup.html#remove-orphan-artifact-files) . + +在 Geo **辅助**节点上,此命令还将清除与磁盘上的孤立文件有关的所有 Geo 注册表记录. + +## Fixing sign in errors[](#fixing-sign-in-errors "Permalink") + +### Message: The redirect URI included is not valid[](#message-the-redirect-uri-included-is-not-valid "Permalink") + +如果您能够登录到**主**节点,但是在尝试登录到**辅助**节点时收到此错误,则应检查 Geo 节点的 URL 是否与其外部 URL 匹配. + +1. 首先,访问 **管理区>** **地理位置** . +2. 找到受影响的**辅助节点** ,然后单击" **编辑"** . +3. 确保**URL**字段与在**辅助**节点的前端服务器上`external_url "https://gitlab.example.com"`中的`/etc/gitlab/gitlab.rb`中找到的值匹配. + +## Fixing common errors[](#fixing-common-errors "Permalink") + +本部分介绍了管理界面中报告的常见错误以及如何修复它们. + +### Geo database configuration file is missing[](#geo-database-configuration-file-is-missing "Permalink") + +GitLab 找不到或没有访问`database_geo.yml`配置文件的权限. + +在 Omnibus GitLab 安装中,该文件应位于`/var/opt/gitlab/gitlab-rails/etc` . 如果它不存在或对其进行了无意的更改,请运行`sudo gitlab-ctl reconfigure`将其恢复到正确的状态. + +如果此路径安装在远程卷上,请检查您的卷配置,并具有正确的权限. + +### An existing tracking database cannot be reused[](#an-existing-tracking-database-cannot-be-reused "Permalink") + +Geo cannot reuse an existing tracking database. + +最安全的方式是使用全新的[辅助节点](#resetting-geo-secondary-node-replication) ,或通过遵循[重置地理辅助节点复制来重置](#resetting-geo-secondary-node-replication)整个[辅助节点](#resetting-geo-secondary-node-replication) . + +### Geo node has a database that is writable which is an indication it is not configured for replication with the primary node[](#geo-node-has-a-database-that-is-writable-which-is-an-indication-it-is-not-configured-for-replication-with-the-primary-node "Permalink") + +此错误是指 Geo 希望**辅助**节点上的数据库副本存在问题. 它通常意味着: + +* 使用了不受支持的复制方法(例如,逻辑复制). +* 设置[地理数据库复制](database.html)的说明未正确遵循. +* 您的数据库连接详细信息不正确,即您在`/etc/gitlab/gitlab.rb`文件中指定了错误的用户. + +与**辅助**节点混淆的一个常见原因是它需要两个单独的 PostgreSQL 实例: + +* **主**节点的只读副本. +* 包含复制元数据的常规可写实例. 即,地理位置跟踪数据库. + +### Geo node does not appear to be replicating the database from the primary node[](#geo-node-does-not-appear-to-be-replicating-the-database-from-the-primary-node "Permalink") + +导致数据库无法正确复制的最常见问题是: + +* **Secondary** nodes cannot reach the **primary** node. Check credentials, firewall rules, etc. +* SSL 证书问题. 确保从**主**节点复制了`/etc/gitlab/gitlab-secrets.json` . +* 数据库存储磁盘已满. +* 数据库复制插槽配置错误. +* 数据库未使用复制插槽或其他替代方法,由于已清除 WAL 文件,因此无法追赶. + +确保按照[地理数据库复制](database.html)说明进行支持的配置. + +### Geo database version (…) does not match latest migration (…)[](#geo-database-version--does-not-match-latest-migration- "Permalink") + +如果您使用的是 Omnibus GitLab 安装,则升级期间可能会失败. 您可以: + +* Run `sudo gitlab-ctl reconfigure`. +* 通过运行以下`sudo gitlab-rake geo:db:migrate`手动触发数据库迁移: `sudo gitlab-rake geo:db:migrate`作为**辅助**节点上的 root 用户. + +### Geo database is not configured to use Foreign Data Wrapper[](#geo-database-is-not-configured-to-use-foreign-data-wrapper "Permalink") + +此错误表示地理位置跟踪数据库未配置 FDW 服务器和凭据. + +See [“Foreign Data Wrapper (FDW) is not configured” error?](#foreign-data-wrapper-fdw-is-not-configured-error). + +### GitLab indicates that more than 100% of repositories were synced[](#gitlab-indicates-that-more-than-100-of-repositories-were-synced "Permalink") + +这可能是由项目注册表中的孤立记录引起的. 您可以[使用 Rake 任务](../../../administration/raketasks/geo.html#remove-orphaned-project-registries)清除它们. + +### Geo Admin Area returns 404 error for a secondary node[](#geo-admin-area-returns-404-error-for-a-secondary-node "Permalink") + +有时`sudo gitlab-rake gitlab:geo:check`指示**辅助**节点运行`sudo gitlab-rake gitlab:geo:check` ,但是在**主**节点的地理管理区域中返回了**辅助**节点 404 错误. + +解决此问题的方法: + +* 尝试使用`sudo gitlab-ctl restart` **辅助** `sudo gitlab-ctl restart` . +* 检查`/var/log/gitlab/gitlab-rails/geo.log`以查看**辅助**节点是否正在使用 IPv6 将其状态发送到**主要**节点. 如果是这样,请使用`/etc/hosts`文件中的 IPv4 将条目添加到**主**节点. 或者,您应该[在**主**节点上启用 IPv6](https://docs.gitlab.com/omnibus/settings/nginx.html) . \ No newline at end of file diff --git a/docs/504.md b/docs/504.md new file mode 100644 index 0000000000000000000000000000000000000000..996418b37d442ff1c13f1202bd813ce4668ae7b4 --- /dev/null +++ b/docs/504.md @@ -0,0 +1,122 @@ +# Geo validation tests + +> 原文:[https://docs.gitlab.com/ee/administration/geo/replication/geo_validation_tests.html](https://docs.gitlab.com/ee/administration/geo/replication/geo_validation_tests.html) + +* [GitLab upgrades](#gitlab-upgrades) + * [June 2020](#june-2020) + * [February 2020](#february-2020) + * [January 2020](#january-2020) + * [October 2019](#october-2019) +* [PostgreSQL upgrades](#postgresql-upgrades) + * [April 2020](#april-2020) + * [September 2019](#september-2019) + +# Geo validation tests[](#geo-validation-tests "Permalink") + +Geo 团队对常见的部署配置执行手动测试和验证,以确保在次要的 GitLab 版本和主要的 PostgreSQL 数据库版本之间升级时,Geo 可以正常工作. + +本部分包含近期验证测试的日记以及相关问题的链接. + +## GitLab upgrades[](#gitlab-upgrades "Permalink") + +以下是我们执行的 GitLab 升级验证测试. + +### June 2020[](#june-2020 "Permalink") + +[Upgrade Geo multi-server installation](https://gitlab.com/gitlab-org/gitlab/-/issues/223284): + +* 说明:在多服务器配置中测试了从 GitLab 12.9.10 升级到 12.10.12 软件包的过程. 使用循环管道和 HAProxy 统计信息显示板监视停机时间. +* 结果:部分成功,因为我们在主站点和辅助站点的升级过程中观察到停机时间. +* 跟进问题/行动: + * [修复多节点 Geo 部署的零停机升级过程/说明](https://gitlab.com/gitlab-org/gitlab/-/issues/225684) + * [Geo:check Rake 任务:排除 AuthorizedKeysCommand 检查节点是否未运行 Puma / Unicorn](https://gitlab.com/gitlab-org/gitlab/-/issues/225454) + * [在下一个升级问题中更新说明,以包括监视 HAProxy 仪表板](https://gitlab.com/gitlab-org/gitlab/-/issues/225359) + +[Upgrade Geo multi-server installation](https://gitlab.com/gitlab-org/gitlab/-/issues/208104): + +* 描述:在多服务器配置中测试了从 GitLab 12.8.1 到 12.9.10 软件包的升级. +* 结果:部分成功,因为我们在演示过程中没有运行循环管道来验证零停机时间. +* 后续问题: + * [阐明 hup Puma / Unicorn 应该包含部署节点](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5460) + * [升级到 12.9.10 后调查 MR 创建失败](https://gitlab.com/gitlab-org/gitlab/-/issues/223282) . + +### February 2020[](#february-2020 "Permalink") + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/201837): + +* 说明:在多节点配置中测试了从 GitLab 12.7.5 升级到最新的 GitLab 12.8 软件包的过程. +* 结果:部分成功,因为我们在演示过程中没有运行循环管道来监视停机时间. + +### January 2020[](#january-2020 "Permalink") + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/200085): + +* 说明:在多节点配置中测试了从 GitLab 12.6.x 升级到最新的 GitLab 12.7 软件包的过程. +* 结果:升级测试成功. +* 后续问题: + * [调查 Geo 端到端测试失败](https://gitlab.com/gitlab-org/gitlab/-/issues/201823) . + * [将更多日志记录添加到 Geo 端到端测试中](https://gitlab.com/gitlab-org/gitlab/-/issues/201830) . + * [零停机升级期间,多余的服务会重新启动](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5047) . + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/199836): + +* 描述:在多节点配置中测试了从 GitLab 12.5.7 到 GitLab 12.6.6 的升级. +* Outcome: Upgrade test was successful. +* 后续问题: [更新文档以实现零停机时间升级,以确保未使用部署节点](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5046) . + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/37044): + +* 说明:在多节点配置中测试了从 GitLab 12.4.x 升级到最新的 GitLab 12.5 软件包的过程. +* 结果:升级测试成功. +* 后续问题: + * [研究为什么 HTTP 推送规范在主节点上失败](https://gitlab.com/gitlab-org/gitlab/-/issues/199825) . + * [研究是否应修改文档以包括刷新外部表任务](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5041) . + +### October 2019[](#october-2019 "Permalink") + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/35262): + +* 说明:在多节点配置中测试了从 GitLab 12.3.5 升级到 GitLab 12.4.1 的过程. +* 结果:升级测试成功. + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/32437): + +* 说明:已测试从 GitLab 12.2.8 升级到 GitLab 12.3.5. +* 结果:升级测试成功. + +[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/32435): + +* 说明:已测试从 GitLab 12.1.9 升级到 GitLab 12.2.8 的过程. +* 结果:由于可能的配置错误问题而部分成功. + +## PostgreSQL upgrades[](#postgresql-upgrades "Permalink") + +以下是我们执行的 PostgreSQL 升级验证测试. + +### April 2020[](#april-2020 "Permalink") + +[PostgreSQL 11 upgrade procedure for Geo installations](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4975): + +* 描述:在将 PostgreSQL 11 设为 GitLab 12.10 中的默认 PostgreSQL 版本之前,我们在 GitLab 12.9 的 Geo 部署中测试了升级到 PostgreSQL 11 的能力. +* 结果:部分成功. 在具有单独的跟踪数据库的多节点配置中发现了问题,并提出了在启用 Geo 时允许自动升级的问题. +* 后续问题: + * [`replicate-geo-database`错误地尝试备份存储库](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5241) . + * [`pg-upgrade`无法升级独立的 Geo 跟踪数据库](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5242) . + * [`revert-pg-upgrade`无法降级 Geo Secondary 的独立跟踪数据库的 PostgreSQL 数据](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5243) . + * [`gitlab-ctl pg-upgrade`结束时,Geo 辅助只读副本上的超时错误](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5235) . + +[Verify Geo installation with PostgreSQL 11](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4971): + +* 说明:在将 PostgreSQL 11 设置为 GitLab 12.10 中的 PostgreSQL 的默认版本之前,我们测试了 GitLab 12.9 的全新安装以及在 PostgreSQL 11 中安装了 Geo 的情况. +* 结果:安装测试成功. + +### September 2019[](#september-2019 "Permalink") + +[Test and validate PostgreSQL 10.0 upgrade for Geo](https://gitlab.com/gitlab-org/gitlab/-/issues/12092): + +* 说明:在 12.0 版本中,GitLab 需要升级到 PostgreSQL 10.0\. 我们测试了从 GitLab 11.11.5 到 GitLab 12.1.8 的各种升级方案. +* 结果:升级时发现了多个问题,并在后续问题中得到解决. +* 后续问题: + * [在多节点 Geo 设置中的 Redis 节点上, `gitlab-ctl`重新配置失败](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4706) . + * [从 12.0.9 到 12.1.9 的地理多节点升级不会升级 PostgreSQL](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4705) . + * [升级到 12.1.9 后,在多节点设置中的应用服务器上刷新外部表失败](https://gitlab.com/gitlab-org/gitlab/-/issues/32119) . \ No newline at end of file diff --git a/docs/505.md b/docs/505.md new file mode 100644 index 0000000000000000000000000000000000000000..048df4ebabc67ad132f1b8459a7475da2a3a5b1d --- /dev/null +++ b/docs/505.md @@ -0,0 +1,339 @@ +# Disaster Recovery (Geo) + +> 原文:[https://docs.gitlab.com/ee/administration/geo/disaster_recovery/](https://docs.gitlab.com/ee/administration/geo/disaster_recovery/) + +* [Promoting a **secondary** Geo node in single-secondary configurations](#promoting-a-secondary-geo-node-in-single-secondary-configurations) + * [Step 1\. Allow replication to finish if possible](#step-1-allow-replication-to-finish-if-possible) + * [Step 2\. Permanently disable the **primary** node](#step-2-permanently-disable-the-primary-node) + * [Step 3\. Promoting a **secondary** node](#step-3-promoting-a-secondary-node) + * [Promoting a **secondary** node running on a single machine](#promoting-a-secondary-node-running-on-a-single-machine) + * [Promoting a **secondary** node with multiple servers](#promoting-a-secondary-node-with-multiple-servers) + * [Promoting a **secondary** node with an external PostgreSQL database](#promoting-a-secondary-node-with-an-external-postgresql-database) + * [Step 4\. (Optional) Updating the primary domain DNS record](#step-4-optional-updating-the-primary-domain-dns-record) + * [Step 5\. (Optional) Add **secondary** Geo node to a promoted **primary** node](#step-5-optional-add-secondary-geo-node-to-a-promoted-primary-node) + * [Step 6\. (Optional) Removing the secondary’s tracking database](#step-6-optional-removing-the-secondarys-tracking-database) +* [Promoting secondary Geo replica in multi-secondary configurations](#promoting-secondary-geo-replica-in-multi-secondary-configurations) + * [Step 1\. Prepare the new **primary** node to serve one or more **secondary** nodes](#step-1-prepare-the-new-primary-node-to-serve-one-or-more-secondary-nodes) + * [Step 2\. Initiate the replication process](#step-2-initiate-the-replication-process) +* [Troubleshooting](#troubleshooting) + * [I followed the disaster recovery instructions and now two-factor auth is broken](#i-followed-the-disaster-recovery-instructions-and-now-two-factor-auth-is-broken) + +# Disaster Recovery (Geo)[](#disaster-recovery-geo-premium-only "Permalink") + +Geo 复制您的数据库,Git 存储库和其他少量资产. 将来,我们将支持和复制更多数据,使您能够在灾难情况下以最少的精力进行故障转移. + +有关更多信息,请参见地[电流限制](../replication/index.html#current-limitations) . + +**警告:**多辅助配置的灾难恢复在**Alpha 中** . 有关最新更新,请查看多级[灾难恢复史诗](https://gitlab.com/groups/gitlab-org/-/epics/65) . + +## Promoting a **secondary** Geo node in single-secondary configurations[](#promoting-a-secondary-geo-node-in-single-secondary-configurations "Permalink") + +目前,我们不提供自动方式来升级 Geo 副本并进行故障转移,但是如果您具有对该计算机的`root`访问权,则可以手动进行. + +此过程将**辅助**地理节点升级为**主要**节点. 为了尽快恢复地理冗余,应在遵循这些说明后立即添加新的**辅助**节点. + +### Step 1\. Allow replication to finish if possible[](#step-1-allow-replication-to-finish-if-possible "Permalink") + +如果**辅助**节点仍在从**主**节点复制数据,请尽可能严格遵循[计划的故障转移文档](planned_failover.html) ,以避免不必要的数据丢失. + +### Step 2\. Permanently disable the **primary** node[](#step-2-permanently-disable-the-primary-node "Permalink") + +**警告:**如果**主**节点脱机,则可能是**主**节点上保存的数据尚未复制到**辅助**节点. 如果继续,此数据应视为丢失. + +如果**主**节点发生故障,则应尽一切可能避免发生裂脑情况,即在两个不同的 GitLab 实例中可能发生写操作,从而使恢复工作复杂化. 因此,为故障转移做准备,我们必须禁用**主**节点. + +1. SSH 进入**主**节点以停止并禁用 GitLab,如果可能的话: + + ``` + sudo gitlab-ctl stop + ``` + + 如果服务器意外重启,请阻止 GitLab 重新启动: + + ``` + sudo systemctl disable gitlab-runsvdir + ``` + + **注意:(** **仅 CentOS** )在 CentOS 6 或更旧的版本中,如果没有可用的机器重启,没有简单的方法可以阻止启动[GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3058) (请参阅[Omnibus GitLab 问题#3058](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3058) ). 完全卸载 GitLab 软件包可能是最安全的: + + ``` + yum remove gitlab-ee + ``` + + **注意:** ( **Ubuntu 14.04 LTS** )如果您使用的是较旧版本的 Ubuntu 或基于 Upstart init 系统的任何其他发行版,则可以通过以下操作来阻止 GitLab 在计算机重启时启动: + + ``` + initctl stop gitlab-runsvvdir + echo 'manual' > /etc/init/gitlab-runsvdir.override + initctl reload-configuration + ``` + +2. 如果您没有对**主**节点的 SSH 访问权限,请使计算机脱机并通过任何方式阻止其重启. 由于您可能有很多方法可以完成此操作,因此我们将避免使用单个建议. 您可能需要: + + * 重新配置负载均衡器. + * 更改 DNS 记录(例如,将主要 DNS 记录指向**辅助**节点,以停止使用**主要**节点). + * 停止虚拟服务器. + * 阻止通过防火墙的流量. + * 从**主**节点撤消对象存储权限. + * 物理断开机器连接. +3. 如果您打算[更新主域 DNS 记录](#step-4-optional-updating-the-primary-domain-dns-record) ,则可能希望立即降低 TTL,以加快传播速度. + +### Step 3\. Promoting a **secondary** node[](#step-3-promoting-a-secondary-node "Permalink") + +升级辅助服务器时,请注意以下事项: + +* A new **secondary** should not be added at this time. If you want to add a new **secondary**, do this after you have completed the entire process of promoting the **secondary** to the **primary**. +* 如果遇到`ActiveRecord::RecordInvalid: Validation failed: Name has already been taken`在此过程中, `ActiveRecord::RecordInvalid: Validation failed: Name has already been taken`错误,请阅读[故障排除建议](../replication/troubleshooting.html#fixing-errors-during-a-failover-or-when-promoting-a-secondary-to-a-primary-node) . + +#### Promoting a **secondary** node running on a single machine[](#promoting-a-secondary-node-running-on-a-single-machine "Permalink") + +1. SSH 登录到**辅助**节点并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 编辑`/etc/gitlab/gitlab.rb`以通过删除启用`geo_secondary_role`所有行来反映其新的**主要**状态: + + ``` + ## In pre-11.5 documentation, the role was enabled as follows. Remove this line. + geo_secondary_role['enable'] = true + + ## In 11.5+ documentation, the role was enabled as follows. Remove this line. + roles ['geo_secondary_role'] + ``` + +3. 将**辅助**节点升级为**主要**节点. + + 在将辅助节点升级为主节点之前,应运行飞行前检查. 它们可以单独运行,也可以与升级脚本一起运行. + + 要将辅助节点与预检检查一起提升为主节点: + + ``` + gitlab-ctl promote-to-primary-node + ``` + + **警告:**跳过飞行前检查将把辅助设备升级为主要设备,而无需进一步确认! + + 如果您已经运行了[预检检查,](planned_failover.html#preflight-checks)或者不想运行它们,则可以使用以下方法跳过预检检查: + + ``` + gitlab-ctl promote-to-primary-node --skip-preflight-check + ``` + + 您还可以单独运行飞行前检查: + + ``` + gitlab-ctl promotion-preflight-checks + ``` + +4. 验证您可以使用先前用于**辅助**节点的 URL 连接到新提升的**主**节点. +5. 如果成功,则**辅助**节点现在已提升为**主要**节点. + +#### Promoting a **secondary** node with multiple servers[](#promoting-a-secondary-node-with-multiple-servers "Permalink") + +`gitlab-ctl promote-to-primary-node`命令尚不能与多台服务器一起使用,因为它只能在仅一台机器的**辅助** `gitlab-ctl promote-to-primary-node`上执行更改. 相反,您必须手动执行此操作. + +1. SSH 进入**辅助**数据库中的数据库节点,并触发 PostgreSQL 升级为可读写: + + ``` + sudo gitlab-pg-ctl promote + ``` + + 在 GitLab 12.8 及更早版本中,请参阅[消息: `sudo: gitlab-pg-ctl: command not found`](../replication/troubleshooting.html#message-sudo-gitlab-pg-ctl-command-not-found) . + +2. 在**辅助**计算机上的每台计算机上编辑`/etc/gitlab/gitlab.rb` ,以通过删除启用`geo_secondary_role`所有行来将其新状态反映为**主要** `geo_secondary_role` : + + ``` + ## In pre-11.5 documentation, the role was enabled as follows. Remove this line. + geo_secondary_role['enable'] = true + + ## In 11.5+ documentation, the role was enabled as follows. Remove this line. + roles ['geo_secondary_role'] + ``` + + 进行这些更改后,请在每台机器上[重新配置 GitLab,](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +3. 将**中学**提升到**小学** . SSH 进入单个应用程序服务器并执行: + + ``` + sudo gitlab-rake geo:set_secondary_as_primary + ``` + +4. 验证您可以使用先前用于**辅助服务器**的 URL 连接到新升级的**主**服务器. +5. 成功! **中学**已升格为**小学** . + +#### Promoting a **secondary** node with an external PostgreSQL database[](#promoting-a-secondary-node-with-an-external-postgresql-database "Permalink") + +`gitlab-ctl promote-to-primary-node`命令不能与外部 PostgreSQL 数据库一起使用,因为它只能在使用 GitLab 的**辅助**节点和数据库在同一台机器上执行更改. 结果,需要手动处理: + +1. 升级与**辅助**站点关联的副本数据库. 这会将数据库设置为可读写: + * Amazon RDS- [将只读副本提升为独立数据库实例](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Promote) + * PostgreSQL 的 Azure 数据库- [停止复制](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal#stop-replication) + * 其他外部 PostgreSQL 数据库-将以下脚本保存在辅助节点中,例如`/tmp/geo_promote.sh` ,然后修改连接参数以匹配您的环境. 然后,执行它以提升副本: + + ``` + #!/bin/bash PG_SUPERUSER = postgres # The path to your pg_ctl binary. You may need to adjust this path to match # your PostgreSQL installation PG_CTL_BINARY = /usr/lib/postgresql/10/bin/pg_ctl # The path to your PostgreSQL data directory. You may need to adjust this # path to match your PostgreSQL installation. You can also run # `SHOW data_directory;` from PostgreSQL to find your data directory PG_DATA_DIRECTORY = /etc/postgresql/10/main # Promote the PostgreSQL database and allow read/write operations sudo -u $PG_SUPERUSER $PG_CTL_BINARY -D $PG_DATA_DIRECTORY promote + ``` + +2. 在**辅助**站点中的每个节点上编辑`/etc/gitlab/gitlab.rb` ,以通过删除启用`geo_secondary_role`所有行来将其新状态反映**为主** `geo_secondary_role` : + + ``` + ## In GitLab 11.4 and earlier, remove this line. + geo_secondary_role['enable'] = true + + ## In GitLab 11.5 and later, remove this line. + roles ['geo_secondary_role'] + ``` + + 进行这些更改后,请在每个节点上[重新配置 GitLab](../../restart_gitlab.html#omnibus-gitlab-reconfigure) ,以使更改生效. + +3. 将**中学**提升到**小学** . SSH 进入单个辅助应用程序节点并执行: + + ``` + sudo gitlab-rake geo:set_secondary_as_primary + ``` + +4. 验证您可以使用先前用于**辅助**站点的 URL 连接到新升级的**主**站点. + +成功! **辅助**站点现在已提升为**主要**站点. + +### Step 4\. (Optional) Updating the primary domain DNS record[](#step-4-optional-updating-the-primary-domain-dns-record "Permalink") + +将主域的 DNS 记录更新为指向**辅助**节点将避免需要将对主域的所有引用更新为辅助域,例如更改 Git 远程服务器和 API URL. + +1. SSH 进入**辅助**节点并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. 更新主域的 DNS 记录. 更新主域名的 DNS 记录指向**辅助**节点后,编辑`/etc/gitlab/gitlab.rb` **辅助**节点上,以反映新的网址: + + ``` + # Change the existing external_url configuration + external_url 'https://' + ``` + + **Note:** Changing `external_url` won’t prevent access via the old secondary URL, as long as the secondary DNS records are still intact. +3. 重新配置**辅助**节点以使更改生效: + + ``` + gitlab-ctl reconfigure + ``` + +4. 执行以下命令以更新新提升的**主**节点 URL: + + ``` + gitlab-rake geo:update_primary_node_url + ``` + + 此命令将使用`/etc/gitlab/gitlab.rb`定义的更改的`external_url`配置. + +5. 仅对于 GitLab 11.11 到 12.7,您可能需要更新数据库中的**主**节点名称. 此错误已在 GitLab 12.8 中修复. + + 要确定是否需要执行此操作,请在`/etc/gitlab/gitlab.rb`文件中搜索`gitlab_rails["geo_node_name"]`设置. 如果用`#`注释掉或根本找不到它,则您将需要更新数据库中**主**节点的名称. 您可以像这样搜索它: + + ``` + grep "geo_node_name" /etc/gitlab/gitlab.rb + ``` + + 要更新数据库中**主**节点的名称: + + ``` + gitlab-rails runner 'Gitlab::Geo.primary_node.update!(name: GeoNode.current_node_name)' + ``` + +6. 验证您可以使用其 URL 连接到新升级的**主数据库** . 如果您更新了主域的 DNS 记录,则这些更改可能尚未传播,具体取决于以前的 DNS 记录 TTL. + +### Step 5\. (Optional) Add **secondary** Geo node to a promoted **primary** node[](#step-5-optional-add-secondary-geo-node-to-a-promoted-primary-node "Permalink") + +使用上述过程将**辅助**节点提升为**主要**节点不会在新的**主要**节点上启用 Geo. + +要使新的**辅助**节点在线,请按照[Geo 设置说明进行操作](../replication/index.html#setup-instructions) . + +### Step 6\. (Optional) Removing the secondary’s tracking database[](#step-6-optional-removing-the-secondarys-tracking-database "Permalink") + +每个**次级**有一个用于保存从**初级**的所有项目的同步状态的特殊的跟踪数据库. 由于**辅助服务器**已经升级,因此不再需要跟踪数据库中的数据. + +可以使用以下命令删除数据: + +``` +sudo rm -rf /var/opt/gitlab/geo-postgresql +``` + +如果您在`gitlab.rb`文件中启用了任何`geo_secondary[]`配置选项,则可以安全地注释掉这些选项或将其删除,然后[重新配置 GitLab](../../restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +## Promoting secondary Geo replica in multi-secondary configurations[](#promoting-secondary-geo-replica-in-multi-secondary-configurations "Permalink") + +如果您有多个**辅助**节点,并且需要升级其中一个,建议您按照[单辅助配置中的"](#promoting-a-secondary-geo-node-in-single-secondary-configurations)升级[**辅助** Geo"节点进行操作](#promoting-a-secondary-geo-node-in-single-secondary-configurations) ,之后还需要执行两个额外步骤. + +### Step 1\. Prepare the new **primary** node to serve one or more **secondary** nodes[](#step-1-prepare-the-new-primary-node-to-serve-one-or-more-secondary-nodes "Permalink") + +1. SSH 进入新的**主**节点并以 root 用户身份登录: + + ``` + sudo -i + ``` + +2. Edit `/etc/gitlab/gitlab.rb` + + ``` + ## Enable a Geo Primary role (if you haven't yet) + roles ['geo_primary_role'] + + ## + # Allow PostgreSQL client authentication from the primary and secondary IPs. These IPs may be + # public or VPC addresses in CIDR format, for example ['198.51.100.1/32', '198.51.100.2/32'] + ## + postgresql['md5_auth_cidr_addresses'] = ['/32', '/32'] + + # Every secondary server needs to have its own slot so specify the number of secondary nodes you're going to have + postgresql['max_replication_slots'] = 1 + + ## + ## Disable automatic database migrations temporarily + ## (until PostgreSQL is restarted and listening on the private address). + ## + gitlab_rails['auto_migrate'] = false + ``` + + (有关这些设置的更多详细信息,您可以阅读[配置主服务器](../replication/database.html#step-1-configure-the-primary-server) ) + +3. 保存文件并重新配置 GitLab,以进行数据库侦听更改和要应用的复制插槽更改. + + ``` + gitlab-ctl reconfigure + ``` + + 重新启动 PostgreSQL 以使其更改生效: + + ``` + gitlab-ctl restart postgresql + ``` + +4. 现在,重新启动 PostgreSQL 并重新侦听私有地址,即可重新启用迁移. + + 编辑`/etc/gitlab/gitlab.rb`并将配置**更改**为`true` : + + ``` + gitlab_rails['auto_migrate'] = true + ``` + + 保存文件并重新配置 GitLab: + + ``` + gitlab-ctl reconfigure + ``` + +### Step 2\. Initiate the replication process[](#step-2-initiate-the-replication-process "Permalink") + +现在,我们需要使每个**辅助**节点侦听新的**主要**节点上的更改. 为此,您需要再次[启动复制过程](../replication/database.html#step-3-initiate-the-replication-process) ,但这一次是针对另一个**主**节点. 所有旧的复制设置将被覆盖. + +## Troubleshooting[](#troubleshooting "Permalink") + +### I followed the disaster recovery instructions and now two-factor auth is broken[](#i-followed-the-disaster-recovery-instructions-and-now-two-factor-auth-is-broken "Permalink") + +10.5 之前的 Geo 的安装说明无法复制`otp_key_base`机密,该机密用于加密存储在数据库中的两因素身份验证机密. 如果**主**节点和**辅助**节点之间的设置不同,启用了双重身份验证的用户将无法在故障转移后登录. + +如果您仍然可以访问旧的**主**节点,则可以按照" [升级到 GitLab 10.5"](../replication/version_specific_updates.html#updating-to-gitlab-105)部分中的说明解决错误. 否则,密码将丢失,您需要[为所有用户重置两步验证](../../../security/two_factor_authentication.html#disabling-2fa-for-everyone) . \ No newline at end of file diff --git a/docs/506.md b/docs/506.md new file mode 100644 index 0000000000000000000000000000000000000000..ffdfb3d5bda491e9effd4ba0e469a5889c47b6a2 --- /dev/null +++ b/docs/506.md @@ -0,0 +1,158 @@ +# Disaster recovery for planned failover + +> 原文:[https://docs.gitlab.com/ee/administration/geo/disaster_recovery/planned_failover.html](https://docs.gitlab.com/ee/administration/geo/disaster_recovery/planned_failover.html) + +* [Not all data is automatically replicated](#not-all-data-is-automatically-replicated) +* [Preflight checks](#preflight-checks) + * [Object storage](#object-storage) + * [Review the configuration of each **secondary** node](#review-the-configuration-of-each-secondary-node) + * [Run system checks](#run-system-checks) + * [Check that secrets match between nodes](#check-that-secrets-match-between-nodes) + * [Ensure Geo replication is up-to-date](#ensure-geo-replication-is-up-to-date) + * [Verify the integrity of replicated data](#verify-the-integrity-of-replicated-data) + * [Notify users of scheduled maintenance](#notify-users-of-scheduled-maintenance) +* [Prevent updates to the **primary** node](#prevent-updates-to-the-primary-node) +* [Finish replicating and verifying all data](#finish-replicating-and-verifying-all-data) +* [Promote the **secondary** node](#promote-the-secondary-node) + +# Disaster recovery for planned failover[](#disaster-recovery-for-planned-failover-premium-only "Permalink") + +The primary use-case of Disaster Recovery is to ensure business continuity in the event of unplanned outage, but it can be used in conjunction with a planned failover to migrate your GitLab instance between regions without extended downtime. + +由于 Geo 节点之间的复制是异步的,因此计划中的故障转移需要一个维护窗口,该窗口中阻止了对**主**节点的更新. 该窗口的长度取决于您的复制能力-一旦**辅助**节点与**主**节点完全同步,就可以进行故障转移而不会丢失数据. + +本文档假定您已经具有完整配置的,可以正常使用的 Geo 设置. 在继续之前,请完整阅读它和[Disaster Recovery](index.html)故障转移文档. 计划内的故障转移是一项主要操作,如果执行不正确,则存在很高的数据丢失风险. 考虑对程序进行排练,直到您对必要的步骤感到满意并且对能够准确执行它们有高度的信心. + +## Not all data is automatically replicated[](#not-all-data-is-automatically-replicated "Permalink") + +如果您使用的是 Geo [不支持的](../replication/index.html#current-limitations)任何 GitLab 功能, [则](../replication/index.html#current-limitations)必须单独进行准备,以确保**辅助**节点具有与该功能关联的任何数据的最新副本. 这可能会大大延长所需的计划维护时间. + +使文件中存储的数据的时间尽可能短的常见策略是使用`rsync`传输数据. 可以在维护窗口之前执行初始`rsync` . 随后的`rsync` s(包括维护窗口内的最终传输)将仅传输**主**节点和**辅助**节点之间的*更改* . + +在[移动存储库](../../operations/moving_repositories.html)文档中可以找到有效使用`rsync`的以存储库为中心的策略. 这些策略可以调整为与任何其他基于文件的数据一起使用,例如 GitLab 页面(如果使用 Omnibus,则可在`/var/opt/gitlab/gitlab-rails/shared/pages` ). + +## Preflight checks[](#preflight-checks "Permalink") + +运行此命令以列出所有预检检查,并在计划计划的故障转移之前自动检查复制和验证是否完成,以确保过程顺利进行: + +``` +gitlab-ctl promotion-preflight-checks +``` + +即使预检检查失败,也可以以`force`模式运行此命令以升级为主要命令: + +``` +sudo gitlab-ctl promotion-preflight-checks --force +``` + +每个步骤将在下面更详细地描述. + +### Object storage[](#object-storage "Permalink") + +如果您有大量的 GitLab 安装或无法忍受停机,请**在**计划计划的故障转移**之前**考虑[迁移到对象存储](../replication/object_storage.html) . 这样做既可以减少维护窗口的长度,又可以减少由于计划内故障转移执行不当而导致的数据丢失风险. + +In GitLab 12.4, you can optionally allow GitLab to manage replication of Object Storage for **secondary** nodes. For more information, see [Object Storage replication](../replication/object_storage.html). + +### Review the configuration of each **secondary** node[](#review-the-configuration-of-each-secondary-node "Permalink") + +数据库设置会自动复制到**辅助**节点,但是`/etc/gitlab/gitlab.rb`文件必须手动设置,并且在节点之间有所不同. 如果在**主要**节点上启用了 Mattermost,OAuth 或 LDAP 集成等功能,但在**次要**节点上未启用这些功能,则它们将在故障转移期间丢失. + +查看两个节点的`/etc/gitlab/gitlab.rb`文件,并确保**辅助**节点支持**主**节点**在**计划计划的故障转移**之前**所做的一切. + +### Run system checks[](#run-system-checks "Permalink") + +在**主**节点和**辅助**节点上运行以下命令: + +``` +gitlab-rake gitlab:check +gitlab-rake gitlab:geo:check +``` + +如果在任一节点上报告了任何故障,则应**在**计划计划的故障转移**之前**解决这些故障. + +### Check that secrets match between nodes[](#check-that-secrets-match-between-nodes "Permalink") + +SSH 主机密钥和`/etc/gitlab/gitlab-secrets.json`文件在所有节点上均应相同. 通过在所有节点上运行以下命令并比较输出来进行检查: + +``` +sudo sha256sum /etc/ssh/ssh_host* /etc/gitlab/gitlab-secrets.json +``` + +如果有任何文件不同,请用**主**节点中的内容替换**辅助**节点上的内容. + +### Ensure Geo replication is up-to-date[](#ensure-geo-replication-is-up-to-date "Permalink") + +直到地理复制和验证完成,维护窗口才会结束. 为了使窗口尽可能短,在使用过程中,应确保这些过程尽可能接近 100%. + +导航到 **管理区>** **辅助**节点上的**地理**仪表板以查看状态. 复制的对象(以绿色显示)应接近 100%,并且不应出现故障(以红色显示). 如果尚未复制大量对象(显示为灰色),请考虑给节点更多时间来完成 + +[![Replication status](img/5574e9e4660196e59606fe9d673097b7.png)](img/replication-status.png) + +如果有任何对象无法复制,则应在安排维护窗口之前进行调查. 在计划好的故障转移之后,所有无法复制的内容都会**丢失** . + +您可以使用[地理状态 API](../../../api/geo_nodes.html#retrieve-project-sync-or-verification-failures-that-occurred-on-the-current-node)查看失败的对象以及失败的原因. + +复制失败的常见原因是**主**节点上缺少数据-您可以通过从备份还原数据或删除对丢失数据的引用来解决这些故障. + +### Verify the integrity of replicated data[](#verify-the-integrity-of-replicated-data "Permalink") + +This [content was moved to another location](background_verification.html). + +### Notify users of scheduled maintenance[](#notify-users-of-scheduled-maintenance "Permalink") + +在**主**节点上,导航到 **管理区>** **消息** ,添加广播消息. 你可以检查下 **管理区>** **地理位置,**以估算完成同步需要多长时间. 一个示例消息是: + +> 计划的维护将在世界标准时间 XX:XX 进行. 我们预计将花费不到 1 个小时. + +## Prevent updates to the **primary** node[](#prevent-updates-to-the-primary-node "Permalink") + +在实施[只读模式](https://gitlab.com/gitlab-org/gitlab/-/issues/14609)之前,必须防止手动进行更新. 请注意,在维护窗口期间, **辅助**节点仍需要对**主**节点具有只读访问权限. + +1. 在计划的时间,使用您的云提供商或节点的防火墙,阻止去往/来自**主**节点的所有 HTTP,HTTPS 和 SSH 通信, **但** IP 和**辅助**节点的 IP **除外** . + + 例如,您可能在组成**主**节点的服务器上运行以下命令: + + ``` + sudo iptables -A INPUT -p tcp -s --destination-port 22 -j ACCEPT + sudo iptables -A INPUT -p tcp -s --destination-port 22 -j ACCEPT + sudo iptables -A INPUT --destination-port 22 -j REJECT + + sudo iptables -A INPUT -p tcp -s --destination-port 80 -j ACCEPT + sudo iptables -A INPUT -p tcp -s --destination-port 80 -j ACCEPT + sudo iptables -A INPUT --tcp-dport 80 -j REJECT + + sudo iptables -A INPUT -p tcp -s --destination-port 443 -j ACCEPT + sudo iptables -A INPUT -p tcp -s --destination-port 443 -j ACCEPT + sudo iptables -A INPUT --tcp-dport 443 -j REJECT + ``` + + 从这一点来看,用户将无法查看其数据或在**主**节点上进行更改. 他们也将无法登录到**辅助**节点. 但是,现有的会话将在维护期间的剩余时间内起作用,并且可以在整个维护期间访问公共数据. + +2. 通过使用其他 IP 在浏览器中访问**主**节点,验证**主**节点是否受到 HTTP 流量的阻止. 服务器应拒绝连接. + +3. 尝试通过使用 SSH 远程 URL 提取现有的 Git 存储库,来验证**主**节点是否已通过 SSH 流量阻止 Git. 服务器应拒绝连接. + +4. 通过导航到禁用**主要**节点上的非 Geo 定期后台作业 **管理区>** **监视>后台作业> Cron** ,按`Disable All` ,然后为`geo_sidekiq_cron_config_worker` cron 作业按`Enable` . 该作业将重新启用其他几个 cron 作业,这些作业对于计划的故障转移成功完成至关重要. + +## Finish replicating and verifying all data[](#finish-replicating-and-verifying-all-data "Permalink") + +1. 如果您要手动复制不是由 Geo 管理的任何数据,请立即触发最终复制过程. +2. 在**主**节点上,导航到 **管理区>** **监视>后台作业>队列,**并等待所有队列(名称中带有`geo`的队列降至 0).这些队列包含用户提交的工作; 在完成之前进行故障转移将导致工作丢失. +3. 在**主**节点上,导航到 **管理区>** **地理位置,**并等待您要故障转移到的**辅助**节点满足以下条件: + + * 所有复制计量到 100%复制,0%失败. + * 所有验证仪表均达到 100%验证,0%失败. + * 数据库复制滞后为 0ms. + * 地理日志光标是最新的(落后 0 个事件). +4. 在**辅助**节点上,导航到 **管理区>** **监视>后台作业>队列,**然后等待所有`geo`队列下降到 0 个已排队的作业和 0 个正在运行的作业. +5. 在**辅助**节点上,使用[以下说明](../../raketasks/check.html)来验证 CI 工件,LFS 对象以及文件存储中的上载的完整性. + +此时, **辅助**节点将包含**主**节点拥有的所有内容的最新副本,这意味着在进行故障转移时不会丢失任何内容. + +## Promote the **secondary** node[](#promote-the-secondary-node "Permalink") + +最后,按照[灾难恢复文档](index.html)将**辅助**节点升级为**主要**节点. 此过程将导致**辅助**节点发生短暂中断,并且用户可能需要再次登录. + +一旦完成,维护窗口就结束了! 新的**主**节点现在开始发散,从旧的. 如果确实出现在这一点上的问题,没有回到原来的**主**节点[是可能](bring_primary_back.html)的,但可能会导致在此期间上传到新的**主**任何数据丢失. + +故障转移完成后,请不要忘记删除广播消息. \ No newline at end of file diff --git a/docs/507.md b/docs/507.md new file mode 100644 index 0000000000000000000000000000000000000000..780bc71a71e00b303119e6651d9a94ec611b27ed --- /dev/null +++ b/docs/507.md @@ -0,0 +1,42 @@ +# Bring a demoted primary node back online + +> 原文:[https://docs.gitlab.com/ee/administration/geo/disaster_recovery/bring_primary_back.html](https://docs.gitlab.com/ee/administration/geo/disaster_recovery/bring_primary_back.html) + +* [Configure the former **primary** node to be a **secondary** node](#configure-the-former-primary-node-to-be-a-secondary-node) +* [Promote the **secondary** node to **primary** node](#promote-the-secondary-node-to-primary-node) +* [Restore the **secondary** node](#restore-the-secondary-node) + +# Bring a demoted primary node back online[](#bring-a-demoted-primary-node-back-online-premium-only "Permalink") + +故障转移后,可以故障回复到降级的**主**节点以还原原始配置. 此过程包括两个步骤: + +1. 使旧的**主**节点成为**辅助**节点. +2. 将**辅助**节点提升为**主要**节点. + +**警告:**如果您对该节点上的数据一致性有任何疑问,我们建议从头开始进行设置. + +## Configure the former **primary** node to be a **secondary** node[](#configure-the-former-primary-node-to-be-a-secondary-node "Permalink") + +由于先前的**主要**节点将与当前的**主要**节点不同步,因此第一步是使先前的**主要**节点保持最新. 请注意,将先前的**主**节点重新同步后,不会重播存储在磁盘上的数据(如存储库和上载),这可能会导致磁盘使用率增加. 或者,您可以[设置一个新的**辅助** GitLab 实例](../replication/index.html#setup-instructions)来避免这种情况. + +要使以前的**主**节点保持最新状态: + +1. SSH 进入落后的前**主**节点. +2. 确保所有服务都已启动: + + ``` + sudo gitlab-ctl start + ``` + + **注意:**如果[永久禁用了**主**节点](index.html#step-2-permanently-disable-the-primary-node) ,则需要立即撤消这些步骤. 对于 Debian / Ubuntu,您只需要运行`sudo systemctl enable gitlab-runsvdir` . 对于 CentOS 6,您需要从头开始安装 GitLab 实例,并按照[安装说明](../replication/index.html#setup-instructions)将其设置为**辅助**节点. 在这种情况下,您无需执行下一步.**注意:**如果在灾难恢复过程中[更改了](index.html#step-4-optional-updating-the-primary-domain-dns-record)该节点[的 DNS 记录](index.html#step-4-optional-updating-the-primary-domain-dns-record) ,则可能需要在此过程中[阻止对该节点的所有写操作](planned_failover.html#prevent-updates-to-the-primary-node) . +3. [设置数据库复制](../replication/database.html) . 请注意,在这种情况下, **主**节点是指当前的**主**节点, **辅助**节点是指先前的**主**节点. + +如果丢失了原始**主**节点,请按照[设置说明](../replication/index.html#setup-instructions)设置新的**辅助**节点. + +## Promote the **secondary** node to **primary** node[](#promote-the-secondary-node-to-primary-node "Permalink") + +初始复制完成并且**主**节点和**辅助**节点紧密同步后,您可以执行[计划的故障转移](planned_failover.html) . + +## Restore the **secondary** node[](#restore-the-secondary-node "Permalink") + +如果你的目标是再有两个节点,你需要把你的**辅助**节点重新联机,以及通过重复第一步( [配置前**主**节点是**辅助**节点](#configure-the-former-primary-node-to-be-a-secondary-node) )为**辅助**节点. \ No newline at end of file diff --git a/docs/508.md b/docs/508.md new file mode 100644 index 0000000000000000000000000000000000000000..8c8e4744d404cbc2c5b024412ce5a3b4d0c93cd8 --- /dev/null +++ b/docs/508.md @@ -0,0 +1,149 @@ +# Automatic background verification + +> 原文:[https://docs.gitlab.com/ee/administration/geo/disaster_recovery/background_verification.html](https://docs.gitlab.com/ee/administration/geo/disaster_recovery/background_verification.html) + +* [Disabling or enabling the automatic background verification](#disabling-or-enabling-the-automatic-background-verification) +* [Repository verification](#repository-verification) +* [Using checksums to compare Geo nodes](#using-checksums-to-compare-geo-nodes) +* [Repository re-verification](#repository-re-verification) +* [Reset verification for projects where verification has failed](#reset-verification-for-projects-where-verification-has-failed) +* [Reconcile differences with checksum mismatches](#reconcile-differences-with-checksum-mismatches) +* [Current limitations](#current-limitations) + +# Automatic background verification[](#automatic-background-verification-premium-only "Permalink") + +**注意:**在 GitLab EE 10.6 中添加了存储库和 Wiki 的自动背景验证,但默认情况下仅在 GitLab EE 11.1 上启用了该功能. 您可以按照[以下说明](#disabling-or-enabling-the-automatic-background-verification)手动禁用或启用此功能. + +自动背景验证可确保传输的数据与计算出的校验和匹配. 如果**主**节点上数据的校验和与**辅助**节点上数据的校验和匹配,则数据传输成功. 在计划的故障转移之后,根据损坏的程度,任何损坏的数据都可能**丢失** . + +如果在**主**节点上验证失败,则表明 Geo 正在复制损坏的对象. 您可以从备份中还原它,也可以从**主**节点中将其删除以解决问题. + +如果验证在**主**节点上成功,但在**辅助**节点上失败,则表明在复制过程中对象已损坏. Geo 积极尝试纠正验证失败,将存储库标记为有退避期重新同步. 如果您想重置这些失败的验证,则应遵循[以下说明](background_verification.html#reset-verification-for-projects-where-verification-has-failed) . + +如果验证明显落后于复制,请考虑在安排计划的故障转移之前给节点更多时间. + +## Disabling or enabling the automatic background verification[](#disabling-or-enabling-the-automatic-background-verification "Permalink") + +在**主**节点上的 Rails 控制台中运行以下命令: + +``` +gitlab-rails console +``` + +要检查是否启用了自动背景验证: + +``` +Gitlab::Geo.repository_verification_enabled? +``` + +要禁用自动背景验证: + +``` +Feature.disable('geo_repository_verification') +``` + +要启用自动背景验证: + +``` +Feature.enable('geo_repository_verification') +``` + +## Repository verification[](#repository-verification "Permalink") + +导航到 **管理区>** 在**主**节点上的**地理**仪表板,并展开该节点的" **验证信息"**选项卡以查看存储库和 Wiki 的自动校验和状态. 成功以绿色显示,待处理的工作以灰色显示,失败以红色显示. + +[![Verification status](img/283011f90b0969b60cd202dd293525ca.png)](img/verification-status-primary.png) + +导航到 **管理区>** **辅助**节点上的**地理**仪表板,并展开该节点的" **验证信息"**选项卡,以查看存储库和 Wiki 的自动验证状态. 与校验和一样,成功显示为绿色,待处理工作显示为灰色,失败显示为红色. + +[![Verification status](img/38d4db85b589523cbab105da53e5fb09.png)](img/verification-status-secondary.png) + +## Using checksums to compare Geo nodes[](#using-checksums-to-compare-geo-nodes "Permalink") + +要检查 Geo **辅助**节点的运行状况,我们在 Git 引用及其值的列表上使用校验和. 校验和包括`HEAD` , `heads` , `tags` , `notes`和特定于 GitLab 的引用,以确保真正的一致性. 如果两个节点具有相同的校验和,则它们肯定拥有相同的引用. 我们在每次更新后为每个节点计算校验和,以确保它们都同步. + +## Repository re-verification[](#repository-re-verification "Permalink") + +在 GitLab 企业版 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8550) . 在[GitLab Premium 中](https://about.gitlab.com/pricing/)可用. + +由于错误或临时基础架构故障,Git 存储库可能会发生意外更改,而不会被标记为要进行验证. Geo 会不断重新验证存储库以确保数据的完整性. 尽管可以设置短至 1 天的间隔,但默认和建议的重新验证间隔是 7 天. 较短的时间间隔可以降低风险,但会增加负载,反之亦然. + +导航到 **管理区>** 在**主**节点上**的地理**信息中心,并单击**编辑**按钮为所述**主**节点来定制最小重新验证间隔: + +[![Re-verification interval](img/e3eeb697453d582cf0ec4a746f30ed31.png)](img/reverification-interval.png) + +默认情况下,自动后台重新验证处于启用状态,但是如果需要,您可以将其禁用. 在**主**节点上的 Rails 控制台中运行以下命令: + +``` +gitlab-rails console +``` + +要禁用自动后台重新验证: + +``` +Feature.disable('geo_repository_reverification') +``` + +要启用自动后台重新验证: + +``` +Feature.enable('geo_repository_reverification') +``` + +## Reset verification for projects where verification has failed[](#reset-verification-for-projects-where-verification-has-failed "Permalink") + +Geo 积极尝试纠正验证失败,将存储库标记为有退避期重新同步. 如果要手动重置它们,此 Rake 任务会将项目标记为验证失败或校验和不匹配的项目重新同步而没有退避期: + +对于存储库: + +``` +sudo gitlab-rake geo:verification:repository:reset +``` + +对于 Wiki: + +``` +sudo gitlab-rake geo:verification:wiki:reset +``` + +## Reconcile differences with checksum mismatches[](#reconcile-differences-with-checksum-mismatches "Permalink") + +如果**主**节点和**辅助**节点的校验和验证不匹配,则原因可能不明显. 要查找校验和不匹配的原因: + +1. 导航到 **管理区>** 在**主**节点上的" **概述">"项目"**仪表板中,找到要检查校验和差异的项目,然后单击" **编辑"**按钮: [![项目仪表板](img/655bbae75a3608d2016397c70682f7d4.png)](img/checksum-differences-admin-projects.png) + +2. 在项目管理页面上,获取**Gitaly 存储名称**和**Gitaly 相对路径** : [![项目管理页面](img/43c1d4f646051452c436962222af114b.png)](img/checksum-differences-admin-project-page.png) + +3. 导航到**主**节点和**辅助**节点上的项目的存储库目录(路径通常是`/var/opt/gitlab/git-data/repositories` ). 请注意,如果`git_data_dirs`是自定义的,请确保检查服务器上的目录布局. + + ``` + cd /var/opt/gitlab/git-data/repositories + ``` + +4. 在**主**节点上运行以下命令,将输出重定向到文件: + + ``` + git show-ref --head | grep -E "HEAD|(refs/(heads|tags|keep-around|merge-requests|environments|notes)/)" > primary-node-refs + ``` + +5. 在**辅助**节点上运行以下命令,将输出重定向到文件: + + ``` + git show-ref --head | grep -E "HEAD|(refs/(heads|tags|keep-around|merge-requests|environments|notes)/)" > secondary-node-refs + ``` + +6. 复制同一系统上先前步骤中的文件,并在内容之间进行区分: + + ``` + diff primary-node-refs secondary-node-refs + ``` + +## Current limitations[](#current-limitations "Permalink") + +自动后台验证不包括附件,LFS 对象,作业工件以及文件存储中的用户上传. 您可以跟踪进度,以将其包括在" [地理位置"中:验证所有复制的数据](https://gitlab.com/groups/gitlab-org/-/epics/1430) . + +现在,您可以通过在两个节点上遵循[以下说明](../../raketasks/check.html)并比较它们之间的输出来手动验证其完整性. + +在 GitLab EE 12.1 中,Geo 会在传输后计算辅助节点上的附件,LFS 对象和已归档跟踪的校验和,并将其与存储的校验和进行比较,如果不匹配则拒绝传输. 请注意,如果在 GitLab EE 12.1 之前已经同步了这些数据,Geo 当前不支持自动验证这些数据的方法. + +对象存储中的数据**未经验证** ,因为对象存储负责确保数据的完整性. \ No newline at end of file diff --git a/docs/509.md b/docs/509.md new file mode 100644 index 0000000000000000000000000000000000000000..3810bdd6dfcfc6b37f390f3a3e8e771474a39073 --- /dev/null +++ b/docs/509.md @@ -0,0 +1,45 @@ +# Rake tasks + +> 原文:[https://docs.gitlab.com/ee/raketasks/README.html](https://docs.gitlab.com/ee/raketasks/README.html) + +* [Available Rake tasks](#available-rake-tasks) + +# Rake tasks[](#rake-tasks-core-only "Permalink") + +GitLab 为常见的管理和操作流程提供[Rake](https://ruby.github.io/rake/)任务. + +使用以下命令执行 GitLab Rake 任务: + +* `gitlab-rake ` for [Omnibus GitLab](https://docs.gitlab.com/omnibus/README.html) installations. +* `bundle exec rake ` for [source](../install/installation.html) installations. + +## Available Rake tasks[](#available-rake-tasks "Permalink") + +以下是可用的 Rake 任务: + +| Tasks | Description | +| --- | --- | +| [Back up and restore](backup_restore.html) | 在服务器之间备份,还原和迁移 GitLab 实例. | +| [Clean up](cleanup.html) | 从 GitLab 实例中清除不需要的项目. | +| [Development](../development/rake_tasks.html) | GitLab 贡献者的任务. | +| [Doctor tasks](../administration/raketasks/doctor.html) | 检查数据完整性问题. | +| [Elasticsearch](../integration/elasticsearch.html#gitlab-elasticsearch-rake-tasks) | 在 GitLab 实例中维护 Elasticsearch. | +| [Enable namespaces](features.html) | 为用户项目启用用户名和名称空间. | +| [General maintenance](../administration/raketasks/maintenance.html) | 常规维护和自检任务. | +| [Geo maintenance](../administration/raketasks/geo.html) | [与地理](../administration/geo/replication/index.html)相关的维护. | +| [GitHub import](../administration/raketasks/github_import.html) | 从 GitHub 检索和导入存储库. | +| [Import repositories](import.html) | 将裸仓库导入您的 GitLab 实例. | +| [Import large project exports](../development/import_project.html#importing-via-a-rake-task) | 导入大型 GitLab [项目出口](../user/project/settings/import_export.html) . | +| [Integrity checks](../administration/raketasks/check.html) | 检查存储库,文件和 LDAP 的完整性. | +| [LDAP maintenance](../administration/raketasks/ldap.html) | [LDAP](../administration/auth/ldap/index.html)相关任务. | +| [List repositories](list_repos.html) | 磁盘上所有由 GitLab 管理的 Git 存储库的列表. | +| [Migrate Snippets to Git](migrate_snippets.html) | 将 GitLab 代码片段迁移到 Git 存储库并显示迁移状态 | +| [Praefect Rake tasks](../administration/raketasks/praefect.html) | [与 Praefect](../administration/gitaly/praefect.html)相关的任务. | +| [Project import/export](../administration/raketasks/project_import_export.html) | 准备[项目的进出口](../user/project/settings/import_export.html) . | +| [Sample Prometheus data](generate_sample_prometheus_data.html) | 生成样本 Prometheus 数据. | +| [Repository storage](../administration/raketasks/storage.html) | 列出现有项目和附件并将其从旧存储迁移到哈希存储. | +| [Uploads migrate](../administration/raketasks/uploads/migrate.html) | 在本地存储和对象存储之间迁移上载. | +| [Uploads sanitize](../administration/raketasks/uploads/sanitize.html) | 从上传到早期版本的 GitLab 的图像中删除 EXIF 数据. | +| [User management](user_management.html) | 执行用户管理任务. | +| [Webhooks administration](web_hooks.html) | 维护项目 Webhooks. | +| [X.509 signatures](x509_signatures.html) | 更新 X.509 提交签名,如果证书存储已更改,则很有用. | \ No newline at end of file diff --git a/docs/510.md b/docs/510.md new file mode 100644 index 0000000000000000000000000000000000000000..fc9caefdf88fa78dd7cd673bb7844c7a306ff536 --- /dev/null +++ b/docs/510.md @@ -0,0 +1,904 @@ +# Back up and restore GitLab + +> 原文:[https://docs.gitlab.com/ee/raketasks/backup_restore.html](https://docs.gitlab.com/ee/raketasks/backup_restore.html) + +* [Requirements](#requirements) +* [Backup timestamp](#backup-timestamp) +* [Back up GitLab](#back-up-gitlab) + * [Storing configuration files](#storing-configuration-files) + * [Backup options](#backup-options) + * [Backup strategy option](#backup-strategy-option) + * [Backup filename](#backup-filename) + * [Rsyncable](#rsyncable) + * [Excluding specific directories from the backup](#excluding-specific-directories-from-the-backup) + * [Skipping tar creation](#skipping-tar-creation) + * [Uploading backups to a remote (cloud) storage](#uploading-backups-to-a-remote-cloud-storage) + * [Using Amazon S3](#using-amazon-s3) + * [Digital Ocean Spaces](#digital-ocean-spaces) + * [Other S3 Providers](#other-s3-providers) + * [Using Google Cloud Storage](#using-google-cloud-storage) + * [Specifying a custom directory for backups](#specifying-a-custom-directory-for-backups) + * [Uploading to locally mounted shares](#uploading-to-locally-mounted-shares) + * [Backup archive permissions](#backup-archive-permissions) + * [Configuring cron to make daily backups](#configuring-cron-to-make-daily-backups) + * [Limit backup lifetime for local files (prune old backups)](#limit-backup-lifetime-for-local-files-prune-old-backups) +* [Restore GitLab](#restore-gitlab) + * [Restore prerequisites](#restore-prerequisites) + * [Restore for installation from source](#restore-for-installation-from-source) + * [Restore for Omnibus GitLab installations](#restore-for-omnibus-gitlab-installations) + * [Restore for Docker image and GitLab Helm chart installations](#restore-for-docker-image-and-gitlab-helm-chart-installations) + * [Restoring only one or a few project(s) or group(s) from a backup](#restoring-only-one-or-a-few-projects-or-groups-from-a-backup) +* [Alternative backup strategies](#alternative-backup-strategies) +* [Additional notes](#additional-notes) +* [Troubleshooting](#troubleshooting) + * [Restoring database backup using Omnibus packages outputs warnings](#restoring-database-backup-using-omnibus-packages-outputs-warnings) + * [When the secrets file is lost](#when-the-secrets-file-is-lost) + * [Reset CI/CD variables](#reset-cicd-variables) + * [Reset Runner registration tokens](#reset-runner-registration-tokens) + * [Reset pending pipeline jobs](#reset-pending-pipeline-jobs) + * [Container Registry push failures after restoring from a backup](#container-registry-push-failures-after-restoring-from-a-backup) + * [Backup fails to complete with Gzip error](#backup-fails-to-complete-with-gzip-error) + +# Back up and restore GitLab[](#back-up-and-restore-gitlab-core-only "Permalink") + +GitLab 提供了 Rake 任务来备份和还原 GitLab 实例. + +应用程序数据备份将创建一个包含数据库,所有存储库和所有附件的存档文件. + +您只能将备份还原到与其创建时**完全相同的** GitLab **版本和类型(CE / EE)** . 将存储库从一台服务器迁移到另一台服务器的最佳方法是通过备份还原. + +## Requirements[](#requirements "Permalink") + +为了能够进行备份和还原,您需要在系统上安装两个基本工具. + +* **Rsync** :如果您安装了 GitLab: + * 使用 Omnibus 软件包,您已经准备就绪. + * 从源代码中,确保已安装`rsync` . 例如: + + ``` + # Debian/Ubuntu sudo apt-get install rsync # RHEL/CentOS sudo yum install rsync + ``` + +## Backup timestamp[](#backup-timestamp "Permalink") + +**注意:**在 GitLab 9.2 中,时间戳格式从`EPOCH_YYYY_MM_DD`更改为`EPOCH_YYYY_MM_DD_GitLab_version` ,例如`1493107454_2018_04_25`将变为`1493107454_2018_04_25_10.6.4-ce` . + +备份存档将保存在`config/gitlab.yml`文件中指定的`backup_path`中. 文件名将为`[TIMESTAMP]_gitlab_backup.tar` ,其中`TIMESTAMP`标识创建每个备份的时间以及 GitLab 版本. 如果您需要还原 GitLab 并且有多个备份可用,则需要时间戳. + +例如,如果备份名称为`1493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar` ,则时间戳为`1493107454_2018_04_25_10.6.4-ce` . + +## Back up GitLab[](#back-up-gitlab "Permalink") + +GitLab 提供了一个简单的命令行界面来备份整个实例. 它备份您的: + +* Database +* Attachments +* Git 存储库数据 +* CI / CD 作业输出日志 +* CI / CD 作业工件 +* LFS 对象 +* 容器注册表图像 +* GitLab 页面内容 + +**警告:** GitLab 不会备份任何配置文件,SSL 证书或系统文件. 强烈建议您[阅读有关存储配置文件的信息](#storing-configuration-files) . + +如果您已通过 Omnibus 软件包安装了 GitLab,请使用以下命令: + +``` +sudo gitlab-backup create +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +如果您已经从源代码安装了 GitLab,请使用以下命令: + +``` +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production +``` + +如果您正在 Docker 容器中运行 GitLab,则可以从主机运行备份: + +``` +docker exec -t gitlab-backup create +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +如果您正在 Kubernetes 集群上使用[GitLab Helm 图表](https://gitlab.com/gitlab-org/charts/gitlab) ,则可以通过`kubectl`在 GitLab 任务运行`backup-utility`窗格上使用`backup-utility`脚本运行备份任务. 有关更多详细信息,请参考[备份 GitLab 安装](https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/backup-restore/backup.md#backing-up-a-gitlab-installation) : + +``` +kubectl exec -it backup-utility +``` + +与 Kubernetes 情况类似,如果已扩展 GitLab 集群以使用多个应用程序服务器,则应选择一个指定节点(不会自动扩展)以运行备份 Rake 任务. 由于备份 Rake 任务与主 Rails 应用程序紧密相连,因此通常在该节点上您还运行 Unicorn / Puma 和/或 Sidekiq. + +输出示例: + +``` +Dumping database tables: +- Dumping table events... [DONE] +- Dumping table issues... [DONE] +- Dumping table keys... [DONE] +- Dumping table merge_requests... [DONE] +- Dumping table milestones... [DONE] +- Dumping table namespaces... [DONE] +- Dumping table notes... [DONE] +- Dumping table projects... [DONE] +- Dumping table protected_branches... [DONE] +- Dumping table schema_migrations... [DONE] +- Dumping table services... [DONE] +- Dumping table snippets... [DONE] +- Dumping table taggings... [DONE] +- Dumping table tags... [DONE] +- Dumping table users... [DONE] +- Dumping table users_projects... [DONE] +- Dumping table web_hooks... [DONE] +- Dumping table wikis... [DONE] +Dumping repositories: +- Dumping repository abcd... [DONE] +Creating backup archive: $TIMESTAMP_gitlab_backup.tar [DONE] +Deleting tmp directories...[DONE] +Deleting old backups... [SKIPPING] +``` + +### Storing configuration files[](#storing-configuration-files "Permalink") + +The [backup Rake task](#back-up-gitlab) GitLab provides does **not** store your configuration files. The primary reason for this is that your database contains encrypted information for two-factor authentication, the CI/CD ‘secure variables’, and so on. Storing encrypted information along with its key in the same place defeats the purpose of using encryption in the first place. + +**警告:**机密文件对于保留数据库加密密钥至关重要. + +**至少** ,您必须备份: + +对所有人; + +* `/etc/gitlab/gitlab-secrets.json` +* `/etc/gitlab/gitlab.rb` + +从源安装: + +* `/home/git/gitlab/config/secrets.yml` +* `/home/git/gitlab/config/gitlab.yml` + +For [Docker installations](https://docs.gitlab.com/omnibus/docker/), you must back up the volume where the configuration files are stored. If you have created the GitLab container according to the documentation, it should be under `/srv/gitlab/config`. + +对于 Kubernetes 集群上的[GitLab Helm 图表安装](https://gitlab.com/gitlab-org/charts/gitlab) ,必须遵循[备份机密](https://docs.gitlab.com/charts/backup-restore/backup.html)说明. + +您可能还想备份所有 TLS 密钥和证书以及[SSH 主机密钥](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079) . + +如果您使用 Omnibus GitLab,请参阅一些其他信息[来备份您的配置](https://docs.gitlab.com/omnibus/settings/backups.html) . + +万一机密文件丢失,请参阅[故障排除部分](#when-the-secrets-file-is-lost) . + +### Backup options[](#backup-options "Permalink") + +GitLab 提供的用于备份实例的命令行工具可以使用更多选项. + +#### Backup strategy option[](#backup-strategy-option "Permalink") + +在 GitLab 8.17 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8728) . + +默认的备份策略实际上是使用 Linux 命令`tar`和`gzip`将数据从相应的数据位置流式传输到备份. 在大多数情况下,这可以正常工作,但是在数据快速变化时可能会引起问题. + +当`tar`读取数据时更改数据时,错误`file changed as we read it`可能会`file changed as we read it`发生`file changed as we read it`将导致备份过程失败. 为了解决这个问题,8.17 引入了一种名为`copy`的新备份策略. 该策略在调用`tar`和`gzip`之前将数据文件复制到一个临时位置,从而避免了错误. + +副作用是备份过程将占用额外的 1X 磁盘空间. 该过程尽力在每个阶段清理临时文件,这样问题就不会复杂化,但是对于大型安装而言,这可能是一个相当大的变化. 这就是为什么`copy`策略不是 8.17 中的默认策略的原因. + +要使用`copy`策略而不是默认的流策略,请在 Rake task 命令中指定`STRATEGY=copy` . 例如: + +``` +sudo gitlab-backup create STRATEGY=copy +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +#### Backup filename[](#backup-filename "Permalink") + +**警告:**如果使用自定义备份文件名,则将无法[限制备份的寿命](#limit-backup-lifetime-for-local-files-prune-old-backups) . + +默认情况下,将根据上面["备份时间戳记"](#backup-timestamp)部分中的规范创建一个备份文件. 但是,可以通过设置`BACKUP`环境变量来覆盖文件名的`[TIMESTAMP]`部分. 例如: + +``` +sudo gitlab-backup create BACKUP=dump +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +生成的文件将是`dump_gitlab_backup.tar` . 这对于使用 rsync 和增量备份的系统很有用,并且将导致更快的传输速度. + +#### Rsyncable[](#rsyncable "Permalink") + +为了确保生成的归档文件可以通过 rsync 智能传输,可以设置`GZIP_RSYNCABLE=yes`选项. 这会将`--rsyncable`选项设置为`gzip` . 这仅在与设置["备份文件名"选项](#backup-filename)结合使用时才有用. + +注意,不能保证`gzip`中的`--rsyncable`选项在所有发行版中都可用. 要验证它在您的发行版中是否可用,您可以运行`gzip --help`或查阅手册页. + +``` +sudo gitlab-backup create BACKUP=dump GZIP_RSYNCABLE=yes +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +#### Excluding specific directories from the backup[](#excluding-specific-directories-from-the-backup "Permalink") + +您可以通过添加环境变量`SKIP`选择从备份中免除的内容. 可用的选项有: + +* `db` (database) +* `uploads` (attachments) +* `repositories` (Git 仓库数据) +* `builds` (CI 作业输出日志) +* `artifacts` (CI 作业工件) +* `lfs` (LFS 对象) +* `registry` (容器注册表图像) +* `pages` (页面内容) + +使用逗号同时指定多个选项: + +所有 Wiki 将作为`repositories`组的一部分进行备份. 备份期间将跳过不存在的 Wiki. + +对于 Omnibus GitLab 软件包: + +``` +sudo gitlab-backup create SKIP=db,uploads +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +对于源安装: + +``` +sudo -u git -H bundle exec rake gitlab:backup:create SKIP=db,uploads RAILS_ENV=production +``` + +#### Skipping tar creation[](#skipping-tar-creation "Permalink") + +创建备份的最后一部分是生成包含所有部分的`.tar`文件. 在某些情况下(例如,如果备份是由其他备份软件获取的),创建`.tar`文件可能会浪费精力,甚至直接有害,因此可以通过将`tar`添加到`SKIP`环境变量中来跳过此步骤. + +将`tar`添加到`SKIP`变量`SKIP`包含备份的文件和目录保留在用于中间文件的目录中. 创建新备份时,这些文件将被覆盖,因此您应确保将它们复制到其他位置,因为系统上只能有一个备份. + +对于 Omnibus GitLab 软件包: + +``` +sudo gitlab-backup create SKIP=tar +``` + +对于源安装: + +``` +sudo -u git -H bundle exec rake gitlab:backup:create SKIP=tar RAILS_ENV=production +``` + +#### Uploading backups to a remote (cloud) storage[](#uploading-backups-to-a-remote-cloud-storage "Permalink") + +从 GitLab 7.4 开始,您可以让备份脚本上载它创建的`.tar`文件. 它使用[Fog 库](http://fog.io/)执行上传. 在下面的示例中,我们使用 Amazon S3 进行存储,但是 Fog 还允许您使用[其他存储提供商](http://fog.io/storage/) . GitLab 也为 AWS,Google,OpenStack Swift,Rackspace 和 Aliyun [导入了云驱动程序](https://gitlab.com/gitlab-org/gitlab/blob/30f5b9a5b711b46f1065baf755e413ceced5646b/Gemfile#L88) . [也可以使用](#uploading-to-locally-mounted-shares)本地驱动程序. + +[Read more about using object storage with GitLab](../administration/object_storage.html). + +##### Using Amazon S3[](#using-amazon-s3 "Permalink") + +对于 Omnibus GitLab 软件包: + +1. 将以下内容添加到`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_rails['backup_upload_connection'] = { + 'provider' => 'AWS', + 'region' => 'eu-west-1', + 'aws_access_key_id' => 'AKIAKIAKI', + 'aws_secret_access_key' => 'secret123' + # If using an IAM Profile, don't configure aws_access_key_id & aws_secret_access_key + # 'use_iam_profile' => true + } + gitlab_rails['backup_upload_remote_directory'] = 'my.s3.bucket' + ``` + +2. [Reconfigure GitLab](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure) for the changes to take effect + +##### Digital Ocean Spaces[](#digital-ocean-spaces "Permalink") + +该示例可用于阿姆斯特丹(AMS3)中的存储桶. + +1. 将以下内容添加到`/etc/gitlab/gitlab.rb` : + + ``` + gitlab_rails['backup_upload_connection'] = { + 'provider' => 'AWS', + 'region' => 'ams3', + 'aws_access_key_id' => 'AKIAKIAKI', + 'aws_secret_access_key' => 'secret123', + 'endpoint' => 'https://ams3.digitaloceanspaces.com' + } + gitlab_rails['backup_upload_remote_directory'] = 'my.s3.bucket' + ``` + +2. [重新配置 GitLab](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效 + +**注意:**如果通过使用 Digital Ocean Spaces 看到`400 Bad Request` ,则可能是由于使用了备份加密. 由于 Digital Ocean Spaces 不支持加密,因此删除或注释包含`gitlab_rails['backup_encryption']`的行. + +##### Other S3 Providers[](#other-s3-providers "Permalink") + +并非所有 S3 提供程序都与 Fog 库完全兼容. 例如,如果尝试上传后看到`411 Length Required`错误, `aws_signature_version` [于此问题](https://github.com/fog/fog-aws/issues/428) ,您可能需要将`aws_signature_version`值从默认值降级为 2. + +对于源安装: + +1. Edit `home/git/gitlab/config/gitlab.yml`: + + ``` + backup: + # snip + upload: + # Fog storage connection settings, see http://fog.io/storage/ . + connection: + provider: AWS + region: eu-west-1 + aws_access_key_id: AKIAKIAKI + aws_secret_access_key: 'secret123' + # If using an IAM Profile, leave aws_access_key_id & aws_secret_access_key empty + # ie. aws_access_key_id: '' + # use_iam_profile: 'true' + # The remote 'directory' to store your backups. For S3, this would be the bucket name. + remote_directory: 'my.s3.bucket' + # Turns on AWS Server-Side Encryption with Amazon S3-Managed Keys for backups, this is optional + # encryption: 'AES256' + # Turns on AWS Server-Side Encryption with Amazon Customer-Provided Encryption Keys for backups, this is optional + # This should be set to the encryption key for Amazon S3 to use to encrypt or decrypt your data. + # 'encryption' must also be set in order for this to have any effect. + # To avoid storing the key on disk, the key can also be specified via the `GITLAB_BACKUP_ENCRYPTION_KEY` environment variable. + # encryption_key: '' + # Specifies Amazon S3 storage class to use for backups, this is optional + # storage_class: 'STANDARD' + ``` + +2. [重新启动 GitLab](../administration/restart_gitlab.html#installations-from-source)以使更改生效 + +如果要将备份上传到 S3,则可能需要创建具有受限访问权限的新 IAM 用户. 要使上载用户仅能上载备份,请创建以下 IAM 配置文件,将`my.s3.bucket`替换为存储桶的名称: + +``` +{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1412062044000", "Effect": "Allow", "Action": [ "s3:AbortMultipartUpload", "s3:GetBucketAcl", "s3:GetBucketLocation", "s3:GetObject", "s3:GetObjectAcl", "s3:ListBucketMultipartUploads", "s3:PutObject", "s3:PutObjectAcl" ], "Resource": [ "arn:aws:s3:::my.s3.bucket/*" ] }, { "Sid": "Stmt1412062097000", "Effect": "Allow", "Action": [ "s3:GetBucketLocation", "s3:ListAllMyBuckets" ], "Resource": [ "*" ] }, { "Sid": "Stmt1412062128000", "Effect": "Allow", "Action": [ "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::my.s3.bucket" ] } ] } +``` + +##### Using Google Cloud Storage[](#using-google-cloud-storage "Permalink") + +如果要使用 Google Cloud Storage 保存备份,则必须首先从 Google 控制台创建访问密钥: + +1. 转到存储设置页面[https://console.cloud.google.com/storage/settings](https://console.cloud.google.com/storage/settings) +2. 选择"互操作性"并创建访问密钥 +3. 记下"访问密钥"和"秘密"并将其替换为以下配置 +4. 在存储桶高级设置中,确保选择了访问控制选项"设置对象级别和存储桶级别权限" +5. 确保您已经创建了存储桶 + +对于 Omnibus GitLab 软件包: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitlab_rails['backup_upload_connection'] = { + 'provider' => 'Google', + 'google_storage_access_key_id' => 'Access Key', + 'google_storage_secret_access_key' => 'Secret', + + ## If you have CNAME buckets (foo.example.com), you might run into SSL issues + ## when uploading backups ("hostname foo.example.com.storage.googleapis.com + ## does not match the server certificate"). In that case, uncomnent the following + ## setting. See: https://github.com/fog/fog/issues/2834 + #'path_style' => true + } + gitlab_rails['backup_upload_remote_directory'] = 'my.google.bucket' + ``` + +2. [重新配置 GitLab](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效 + +对于源安装: + +1. Edit `home/git/gitlab/config/gitlab.yml`: + + ``` + backup: + upload: + connection: + provider: 'Google' + google_storage_access_key_id: 'Access Key' + google_storage_secret_access_key: 'Secret' + remote_directory: 'my.google.bucket' + ``` + +2. [重新启动 GitLab](../administration/restart_gitlab.html#installations-from-source)以使更改生效 + +##### Specifying a custom directory for backups[](#specifying-a-custom-directory-for-backups "Permalink") + +Note: This option only works for remote storage. If you want to group your backups you can pass a `DIRECTORY` environment variable: + +``` +sudo gitlab-backup create DIRECTORY=daily +sudo gitlab-backup create DIRECTORY=weekly +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +#### Uploading to locally mounted shares[](#uploading-to-locally-mounted-shares "Permalink") + +You may also send backups to a mounted share (for example, `NFS`,`CIFS`, or `SMB`) by using the Fog [`Local`](https://github.com/fog/fog-local#usage) storage provider. The directory pointed to by the `local_root` key **must** be owned by the `git` user **安装时** (mounting with the `uid=` of the `git` user for `CIFS` and `SMB`) or the user that you are executing the backup tasks under (for Omnibus packages, this is the `git` user). + +除`local_root`密钥外, `backup_upload_remote_directory` **必须**设置`local_root` . 这是已安装目录中的子目录,备份将被复制到该子目录,如果不存在,则会创建备份. 如果要将压缩文件复制到的目录是已安装目录的根目录,请使用`.` 代替. + +**注意:**由于文件系统性能可能会影响 GitLab 的整体性能,因此我们不建议使用 EFS 进行存储. [有关](../administration/high_availability/nfs.html#avoid-using-awss-elastic-file-system-efs)更多详细信息,请参见[相关文档](../administration/high_availability/nfs.html#avoid-using-awss-elastic-file-system-efs) . + +对于 Omnibus GitLab 软件包: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitlab_rails['backup_upload_connection'] = { + :provider => 'Local', + :local_root => '/mnt/backups' + } + + # The directory inside the mounted folder to copy backups to + # Use '.' to store them in the root directory + gitlab_rails['backup_upload_remote_directory'] = 'gitlab_backups' + ``` + +2. [重新配置 GitLab,](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +对于源安装: + +1. Edit `home/git/gitlab/config/gitlab.yml`: + + ``` + backup: + upload: + # Fog storage connection settings, see http://fog.io/storage/ . + connection: + provider: Local + local_root: '/mnt/backups' + # The directory inside the mounted folder to copy backups to + # Use '.' to store them in the root directory + remote_directory: 'gitlab_backups' + ``` + +2. [重新启动 GitLab,](../administration/restart_gitlab.html#installations-from-source)以使更改生效. + +#### Backup archive permissions[](#backup-archive-permissions "Permalink") + +由 GitLab 创建的备份存档( `1393513186_2014_02_27_gitlab_backup.tar` )默认情况下将具有所有者/组`git` / `git`和 0600 权限. 这是为了避免其他系统用户读取 GitLab 的数据. 如果您需要备份存档具有不同的权限,则可以使用" archive_permissions"设置. + +对于 Omnibus GitLab 软件包: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + gitlab_rails['backup_archive_permissions'] = 0644 # Makes the backup archives world-readable + ``` + +2. [重新配置 GitLab,](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +对于源安装: + +1. Edit `/home/git/gitlab/config/gitlab.yml`: + + ``` + backup: + archive_permissions: 0644 # Makes the backup archives world-readable + ``` + +2. [重新启动 GitLab,](../administration/restart_gitlab.html#installations-from-source)以使更改生效. + +#### Configuring cron to make daily backups[](#configuring-cron-to-make-daily-backups "Permalink") + +**警告:**以下 cron 作业不会[备份您的 GitLab 配置文件](#storing-configuration-files)或[SSH 主机密钥](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079) . + +您可以安排一个 cron 作业来备份您的存储库和 GitLab 元数据. + +对于 Omnibus GitLab 软件包: + +1. 编辑`root`用户的 crontab: + + ``` + sudo su - + crontab -e + ``` + +2. 在那里,添加以下行以安排每天凌晨 2 点进行备份: + + ``` + 0 2 * * * /opt/gitlab/bin/gitlab-backup create CRON=1 + ``` + + **注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:create` . + +对于源安装: + +1. 编辑`git`用户的 crontab: + + ``` + sudo -u git crontab -e + ``` + +2. 在底部添加以下行: + + ``` + # Create a full backup of the GitLab repositories and SQL database every day at 2am + 0 2 * * * cd /home/git/gitlab && PATH=/usr/local/bin:/usr/bin:/bin bundle exec rake gitlab:backup:create RAILS_ENV=production CRON=1 + ``` + +**注意:**如果没有错误, `CRON=1`环境设置将告诉备份脚本禁止所有进度输出. 建议减少 Cron 垃圾邮件. + +### Limit backup lifetime for local files (prune old backups)[](#limit-backup-lifetime-for-local-files-prune-old-backups "Permalink") + +**警告:**如果您使用[自定义文件名](#backup-filename)进行备份,则此操作将无效.**注意:**此配置选项仅管理本地文件. GitLab 不会自动修剪存储在第三方[对象](#uploading-backups-to-a-remote-cloud-storage)存储中的旧文件,因为用户可能没有列出和删除文件的权限. 建议您为对象存储配置适当的保留策略(例如[AWS S3](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/create-lifecycle.html) ). + +您可能希望为备份设置有限的生命周期,以防止使用所有磁盘空间进行常规备份. 下次运行备份任务时,将修剪早于`backup_keep_time`备份. + +对于 Omnibus GitLab 软件包: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ``` + ## Limit backup lifetime to 7 days - 604800 seconds + gitlab_rails['backup_keep_time'] = 604800 + ``` + +2. [重新配置 GitLab,](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure)以使更改生效. + +对于源安装: + +1. Edit `/home/git/gitlab/config/gitlab.yml`: + + ``` + backup: + ## Limit backup lifetime to 7 days - 604800 seconds + keep_time: 604800 + ``` + +2. [重新启动 GitLab,](../administration/restart_gitlab.html#installations-from-source)以使更改生效. + +## Restore GitLab[](#restore-gitlab "Permalink") + +GitLab 提供了一个简单的命令行界面来还原整个安装过程,并且足够灵活,可以满足您的需求. + +[还原先决条件部分](#restore-prerequisites)包括关键信息. 在尝试在生产环境中执行还原过程之前,请确保至少阅读并测试整个还原过程一次. + +您只能将备份还原到**与**您在其上创建备份的 GitLab **版本和类型(CE / EE)完全相同的**备份,例如 CE 9.1.0. + +如果备份的版本与当前安装的版本不同,则在还原备份之前,您需要[降级 GitLab 安装](https://docs.gitlab.com/omnibus/update/README.html) . + +### Restore prerequisites[](#restore-prerequisites "Permalink") + +您需要先进行有效的 GitLab 安装,然后才能执行还原. 这主要是因为通常不允许执行还原操作( `git` )的系统用户创建或删除将数据导入到( `gitlabhq_production` )所需的 SQL 数据库. 所有现有数据将被擦除(SQL)或移动到单独的目录(存储库,上载). + +要还原备份,您还需要还原`/etc/gitlab/gitlab-secrets.json` (对于 Omnibus 软件包)或`/home/git/gitlab/.secret` (对于从源安装). 该文件包含数据库加密密钥, [CI / CD 变量](../ci/variables/README.html#gitlab-cicd-environment-variables)以及用于[两因素身份验证的](../user/profile/account/two_factor_authentication.html)变量. 如果您无法通过应用程序数据备份还原此加密密钥文件,则启用了双重身份验证和 GitLab Runners 的用户将无法访问您的 GitLab 服务器. + +您可能还想还原所有 TLS 密钥,证书或[SSH 主机密钥](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079) . + +从 GitLab 12.9 开始,如果找到了未取消备份(如使用`SKIP=tar`备份),并且未使用`BACKUP=`选择任何备份,则将使用未取消备份. + +根据您的情况,您可能需要使用以下一个或多个选项来运行 restore 命令: + +* `BACKUP=timestamp_of_backup`如果存在多个备份,则为必需. 阅读有关[备份时间戳记的内容](#backup-timestamp) . +* `force=yes` yes-不询问是否应重新生成 authorized_keys 文件,并假设" yes"以警告将删除数据库表,启用"写入 authorized_keys 文件"设置并更新 LDAP 提供程序. + +如果要还原到作为挂载点的目录,则在尝试还原之前,需要确保这些目录为空. 否则,GitLab 将在恢复新数据之前尝试移动这些目录,这将导致错误. + +阅读有关[配置 NFS 挂载的](../administration/high_availability/nfs.html)更多信息 + +### Restore for installation from source[](#restore-for-installation-from-source "Permalink") + +``` +# Stop processes that are connected to the database +sudo service gitlab stop + +bundle exec rake gitlab:backup:restore RAILS_ENV=production +``` + +输出示例: + +``` +Unpacking backup... [DONE] +Restoring database tables: +-- create_table("events", {:force=>true}) + -> 0.2231s +[...] +- Loading fixture events...[DONE] +- Loading fixture issues...[DONE] +- Loading fixture keys...[SKIPPING] +- Loading fixture merge_requests...[DONE] +- Loading fixture milestones...[DONE] +- Loading fixture namespaces...[DONE] +- Loading fixture notes...[DONE] +- Loading fixture projects...[DONE] +- Loading fixture protected_branches...[SKIPPING] +- Loading fixture schema_migrations...[DONE] +- Loading fixture services...[SKIPPING] +- Loading fixture snippets...[SKIPPING] +- Loading fixture taggings...[SKIPPING] +- Loading fixture tags...[SKIPPING] +- Loading fixture users...[DONE] +- Loading fixture users_projects...[DONE] +- Loading fixture web_hooks...[SKIPPING] +- Loading fixture wikis...[SKIPPING] +Restoring repositories: +- Restoring repository abcd... [DONE] +- Object pool 1 ... +Deleting tmp directories...[DONE] +``` + +接下来,如果需要,请如上所述恢复`/home/git/gitlab/.secret` . + +重新启动 GitLab: + +``` +sudo service gitlab restart +``` + +### Restore for Omnibus GitLab installations[](#restore-for-omnibus-gitlab-installations "Permalink") + +此过程假定: + +* 您已经安装了与创建备份**完全相同**的 GitLab Omnibus **版本和类型(CE / EE)** . +* 您已经至少运行过`sudo gitlab-ctl reconfigure`一次. +* GitLab 正在运行. 如果没有,请使用`sudo gitlab-ctl start`启动它. + +首先,请确保您的备份 tar 文件位于`gitlab.rb`配置`gitlab_rails['backup_path']`描述的备份目录中. 默认值为`/var/opt/gitlab/backups` . 它必须由`git`用户拥有. + +``` +sudo cp 11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar /var/opt/gitlab/backups/ +sudo chown git.git /var/opt/gitlab/backups/11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar +``` + +停止连接到数据库的进程. 保持其余的 GitLab 运行: + +``` +sudo gitlab-ctl stop unicorn +sudo gitlab-ctl stop puma +sudo gitlab-ctl stop sidekiq +# Verify +sudo gitlab-ctl status +``` + +接下来,还原备份,并指定要还原的备份的时间戳记: + +``` +# This command will overwrite the contents of your GitLab database! +sudo gitlab-backup restore BACKUP=11493107454_2018_04_25_10.6.4-ce +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:restore` .**警告:** `gitlab-rake gitlab:backup:restore`没有在您的注册表目录上设置正确的文件系统权限. 这是一个[已知问题](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62759) . 在 GitLab 12.2 或更高版本上,您可以使用`gitlab-backup restore`来避免此问题. + +接下来,根据需要如上所述恢复`/etc/gitlab/gitlab-secrets.json` . + +重新配置,重启并检查 GitLab: + +``` +sudo gitlab-ctl reconfigure +sudo gitlab-ctl restart +sudo gitlab-rake gitlab:check SANITIZE=true +``` + +如果您的备份 tar 文件和已安装的 GitLab 版本之间的 GitLab 版本不匹配,则 restore 命令将中止并显示错误. 安装[正确的 GitLab 版本,](https://packages.gitlab.com/gitlab/)然后重试. + +**注意**当前存在一个与`pgbouncer`不兼容的还原[问题](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3470) . 为了解决该问题,Rails 节点将需要绕过`pgbouncer`并直接连接到主数据库节点. 这可以通过设置`gitlab_rails['db_host']`和`gitlab_rails['port']`连接到主数据库节点并[重新配置 GitLab 来完成](../administration/restart_gitlab.html#omnibus-gitlab-reconfigure) . + +### Restore for Docker image and GitLab Helm chart installations[](#restore-for-docker-image-and-gitlab-helm-chart-installations "Permalink") + +对于使用 Kubernetes 集群上的 Docker 映像或 GitLab Helm 图表进行的 GitLab 安装,还原任务期望还原目录为空. 但是,使用 Docker 和 Kubernetes 卷挂载,可能会在卷根目录上创建一些系统级目录,例如 Linux 操作系统中找到的`lost+found`目录. 这些目录通常归`root`拥有,因为 restore Rake 任务以`git`用户身份运行,因此可能导致访问权限错误. 因此,要还原 GitLab 安装,用户必须确认还原目标目录为空. + +对于这两种安装类型,备份 tarball 必须在备份位置(默认位置为`/var/opt/gitlab/backups` )中`/var/opt/gitlab/backups` . + +对于 Docker 安装,可以从主机运行还原任务: + +``` +docker exec -it gitlab-backup restore +``` + +**注意**对于 GitLab 12.1 和更早版本,请使用`gitlab-rake gitlab:backup:restore` .**警告:** `gitlab-rake gitlab:backup:restore`没有在您的注册表目录上设置正确的文件系统权限. 这是一个[已知问题](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62759) . 在 GitLab 12.2 或更高版本上,您可以使用`gitlab-backup restore`来避免此问题. + +GitLab Helm 图表使用不同的过程,在[恢复 GitLab Helm 图表安装中](https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/backup-restore/restore.md)记录了该过程. + +### Restoring only one or a few project(s) or group(s) from a backup[](#restoring-only-one-or-a-few-projects-or-groups-from-a-backup "Permalink") + +尽管用于还原 GitLab 实例的 Rake 任务不支持还原单个项目或组,但是您可以使用一种解决方法,将备份还原到单独的临时 GitLab 实例,然后从那里导出您的项目或组: + +1. 以与要还原的备份实例相同的版本[安装新的 GitLab](../install/README.html)实例. +2. [将备份还原](#restore-gitlab)到此新实例中,然后导出您的[项目](../user/project/settings/import_export.html)或[组](../user/group/settings/import_export.html) . 确保阅读任一导出功能文档上的**重要说明** ,以了解将导出什么内容,不导出什么内容. +3. 导出完成后,转到旧实例并导入它. +4. 仅在完成所需的项目或组的导入后,您可以删除新的临时 GitLab 实例. + +**注意**在[问题#17517 中](https://gitlab.com/gitlab-org/gitlab/-/issues/17517)讨论了提供直接还原单个项目或组的功能请求. + +## Alternative backup strategies[](#alternative-backup-strategies "Permalink") + +如果您的 GitLab 服务器包含很多 Git 存储库数据,您可能会发现 GitLab 备份脚本太慢. 在这种情况下,您可以考虑将文件系统快照用作备份策略的一部分. + +示例:Amazon EBS + +> A GitLab server using Omnibus GitLab hosted on Amazon AWS. An EBS drive containing an ext4 filesystem is mounted at `/var/opt/gitlab`. In this case you could make an application backup by taking an EBS snapshot. The backup includes all repositories, uploads and PostgreSQL data. + +示例:LVM 快照+ rsync + +> 使用 Omnibus GitLab 的 GitLab 服务器,其 LVM 逻辑卷安装在`/var/opt/gitlab` . 使用 rsync 复制`/var/opt/gitlab`目录将不可靠,因为运行 rsync 时会更改太多文件. 而不是 rsync-ing `/var/opt/gitlab` ,我们创建一个临时 LVM 快照,将其作为只读文件系统安装在`/mnt/gitlab_backup` . 现在,我们可以运行更长的 rsync 作业,它将在远程服务器上创建一致的副本. 副本包括所有存储库,上载和 PostgreSQL 数据. + +如果您在虚拟服务器上运行 GitLab,则还可以创建整个 GitLab 服务器的 VM 快照. 但是,VM 快照要求您关闭服务器电源的情况并不少见,因此这种方法的实际使用可能受到限制. + +## Additional notes[](#additional-notes "Permalink") + +本文档适用于 GitLab 社区和企业版. 我们备份 GitLab.com 并确保您的数据安全,但是您不能使用这些方法自己从 GitLab.com 导出/备份数据. + +问题存储在数据库中. 它们不能存储在 Git 本身中. + +要使用最新版本的 GitLab 将存储库从一台服务器迁移到另一台服务器,可以使用[import Rake 任务](import.html)来批量导入存储库. 请注意,如果您执行导入 Rake 任务而不是备份还原,则将拥有所有存储库,但没有其他任何数据. + +## Troubleshooting[](#troubleshooting "Permalink") + +以下是可能的解决方案可能遇到的问题. + +### Restoring database backup using Omnibus packages outputs warnings[](#restoring-database-backup-using-omnibus-packages-outputs-warnings "Permalink") + +如果使用备份还原过程,则可能会遇到以下警告: + +``` +psql:/var/opt/gitlab/backups/db/database.sql:22: ERROR: must be owner of extension plpgsql +psql:/var/opt/gitlab/backups/db/database.sql:2931: WARNING: no privileges could be revoked for "public" (two occurrences) +psql:/var/opt/gitlab/backups/db/database.sql:2933: WARNING: no privileges were granted for "public" (two occurrences) +``` + +请注意,尽管有这些警告,备份仍成功还原. + +Rake 任务以`gitlab`用户身份运行,该用户没有对数据库的超级用户访问权限. 启动还原时,它还将以`gitlab`用户身份运行,但也会尝试更改其无权访问的对象. 这些对象对数据库的备份/还原没有影响,但是它们发出此烦人的警告. + +有关更多信息,请参见[此处](https://s0www0postgresql0org.icopy.site/message-id/201110220712.30886.adrian.klaver@gmail.com)和[此处](https://s0www0postgresql0org.icopy.site/message-id/2039.1177339749@sss.pgh.pa.us)有关 PostgreSQL 问题跟踪器的类似问题以及[堆栈溢出](https://stackoverflow.com/questions/4368789/error-must-be-owner-of-language-plpgsql) . + +### When the secrets file is lost[](#when-the-secrets-file-is-lost "Permalink") + +如果您无法[备份 secrets 文件](#storing-configuration-files) ,则启用 2FA 的用户将无法登录 GitLab. 在这种情况下,您需要[为所有人禁用 2FA](../security/two_factor_authentication.html#disabling-2fa-for-everyone) . + +机密文件还负责为包含敏感信息的几列存储加密密钥. 如果密钥丢失,GitLab 将无法解密这些列. 这将破坏广泛的功能,包括(但不限于): + +* [CI/CD variables](../ci/variables/README.html) +* [Kubernetes / GCP integration](../user/project/clusters/index.html) +* [Custom Pages domains](../user/project/pages/custom_domains_ssl_tls_certification/index.html) +* [Project error tracking](../user/project/operations/error_tracking.html) +* [Runner authentication](../ci/runners/README.html) +* [Project mirroring](../user/project/repository/repository_mirroring.html) +* [Web hooks](../user/project/integrations/webhooks.html) + +在 CI / CD 变量和 Runner 身份验证之类的情况下,您可能会遇到一些意外行为,例如: + +* 卡住了工作. +* 500 个错误. + +您可以使用[Secrets Doctor Rake 任务](../administration/raketasks/doctor.html)检查数据库中是否具有不可解密的值. + +在这种情况下,您需要重置 CI / CD 变量和运行程序身份验证的所有令牌,下面将对此进行详细说明. 重置令牌后,您应该能够访问您的项目,并且作业将重新开始运行. + +**警告:**使用以下命令需要您自担风险,并确保事先进行了备份. + +#### Reset CI/CD variables[](#reset-cicd-variables "Permalink") + +1. 输入数据库控制台: + + 对于 Omnibus GitLab 软件包: + + ``` + sudo gitlab-rails dbconsole + ``` + + 对于源安装: + + ``` + sudo -u git -H bundle exec rails dbconsole -e production + ``` + +2. 检查`ci_group_variables`和`ci_variables`表: + + ``` + SELECT * FROM public."ci_group_variables"; + SELECT * FROM public."ci_variables"; + ``` + + 这些是您需要删除的变量. + +3. 放下桌子: + + ``` + DELETE FROM ci_group_variables; + DELETE FROM ci_variables; + ``` + +4. 您可能需要重新配置或重新启动 GitLab 才能使更改生效. + +#### Reset Runner registration tokens[](#reset-runner-registration-tokens "Permalink") + +1. 输入数据库控制台: + + 对于 Omnibus GitLab 软件包: + + ``` + sudo gitlab-rails dbconsole + ``` + + 对于源安装: + + ``` + sudo -u git -H bundle exec rails dbconsole -e production + ``` + +2. 清除项目,组和整个实例的所有令牌: + + **Caution:** The last UPDATE operation will stop the runners being able to pick up new jobs. You must register new runners. + + ``` + -- Clear project tokens + UPDATE projects SET runners_token = null, runners_token_encrypted = null; + -- Clear group tokens + UPDATE namespaces SET runners_token = null, runners_token_encrypted = null; + -- Clear instance tokens + UPDATE application_settings SET runners_registration_token_encrypted = null; + -- Clear runner tokens + UPDATE ci_runners SET token = null, token_encrypted = null; + ``` + +#### Reset pending pipeline jobs[](#reset-pending-pipeline-jobs "Permalink") + +1. 输入数据库控制台: + + 对于 Omnibus GitLab 软件包: + + ``` + sudo gitlab-rails dbconsole + ``` + + 对于源安装: + + ``` + sudo -u git -H bundle exec rails dbconsole -e production + ``` + +2. 清除所有待处理作业的令牌: + + ``` + -- Clear build tokens + UPDATE ci_builds SET token = null, token_encrypted = null; + ``` + +其余功能也可以采用类似的策略-通过删除无法解密的数据,GitLab 可以恢复工作状态,并且可以手动替换丢失的数据. + +### Container Registry push failures after restoring from a backup[](#container-registry-push-failures-after-restoring-from-a-backup "Permalink") + +如果使用[Container Registry](../user/packages/container_registry/index.html) ,则在还原注册表数据后,在 Omnibus GitLab 实例上还原备份后,可能会推送到注册表失败. + +这些失败将在注册表日志中提及权限问题,例如: + +``` +level=error +msg="response completed with error" +err.code=unknown +err.detail="filesystem: mkdir /var/opt/gitlab/gitlab-rails/shared/registry/docker/registry/v2/repositories/...: permission denied" +err.message="unknown error" +``` + +这是由于还原以非特权用户`git`身份运行的,该用户在还原期间无法将正确的所有权分配给注册表文件( [问题 62759](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62759 "还原后对注册表文件系统的权限不正确") ). + +要使您的注册表再次起作用: + +``` +sudo chown -R registry:registry /var/opt/gitlab/gitlab-rails/shared/registry/docker +``` + +**注意:**如果您更改了注册表的默认文件系统位置,则需要对定制位置而不是`/var/opt/gitlab/gitlab-rails/shared/registry/docker`运行`chown` . + +### Backup fails to complete with Gzip error[](#backup-fails-to-complete-with-gzip-error "Permalink") + +运行备份时,您可能会收到 Gzip 错误: + +``` +sudo /opt/gitlab/bin/gitlab-backup create +... +Dumping ... +... +gzip: stdout: Input/output error + +Backup failed +``` + +如果发生这种情况,请检查以下内容: + +1. 确认有足够的磁盘空间用于 Gzip 操作. +2. 如果正在使用 NFS,请检查是否设置了安装选项`timeout` . 默认值为`600` ,并将其更改为较小的值会导致此错误. \ No newline at end of file diff --git a/docs/511.md b/docs/511.md new file mode 100644 index 0000000000000000000000000000000000000000..87e39ad7a1cc48d667a07328bd6698751a1b3333 --- /dev/null +++ b/docs/511.md @@ -0,0 +1,195 @@ +# Clean up + +> 原文:[https://docs.gitlab.com/ee/raketasks/cleanup.html](https://docs.gitlab.com/ee/raketasks/cleanup.html) + +* [Remove unreferenced LFS files](#remove-unreferenced-lfs-files) + * [Remove unreferenced LFS files immediately](#remove-unreferenced-lfs-files-immediately) +* [Clean up project upload files](#clean-up-project-upload-files) + * [Clean up project upload files from filesystem](#clean-up-project-upload-files-from-filesystem) + * [Clean up project upload files from object storage](#clean-up-project-upload-files-from-object-storage) +* [Remove orphan artifact files](#remove-orphan-artifact-files) +* [Remove expired ActiveSession lookup keys](#remove-expired-activesession-lookup-keys) +* [Container Registry garbage collection](#container-registry-garbage-collection) + +# Clean up[](#clean-up-core-only "Permalink") + +GitLab 提供 Rake 任务来清理 GitLab 实例. + +## Remove unreferenced LFS files[](#remove-unreferenced-lfs-files "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36628) . + +**危险:**不要在 GitLab 升级后的 12 小时内运行此程序. 这是为了确保所有后台迁移均已完成,否则可能导致数据丢失. + +当您从存储库的历史记录中删除 LFS 文件时,它们将变成孤立文件并继续占用磁盘空间. 使用此 Rake 任务,您可以从数据库中删除无效的引用,这将允许对 LFS 文件进行垃圾回收. + +例如: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:cleanup:orphan_lfs_file_references PROJECT_PATH="gitlab-org/gitlab-foss" + +# installation from source +bundle exec rake gitlab:cleanup:orphan_lfs_file_references RAILS_ENV=production PROJECT_PATH="gitlab-org/gitlab-foss" +``` + +您也可以使用`PROJECT_ID`而不是`PROJECT_PATH`指定项目. + +例如: + +``` +$ sudo gitlab-rake gitlab:cleanup:orphan_lfs_file_references PROJECT_PATH="gitlab-org/gitlab-foss" +I, [2019-12-13T16:35:31.764962 #82356] INFO -- : Looking for orphan LFS files for project GitLab Org / GitLab Foss +I, [2019-12-13T16:35:31.923659 #82356] INFO -- : Removed invalid references: 12 +``` + +默认情况下,此任务不会删除任何内容,但会显示它可以删除多少个文件引用. 如果您确实要删除引用,请运行`DRY_RUN=false`的命令. 您还可以使用`LIMIT={number}`参数来限制已删除引用的数量. + +请注意,此 Rake 任务仅删除对 LFS 文件的引用. 未引用的 LFS 文件将在以后(每天一次)进行垃圾收集. 如果您需要立即进行垃圾回收,请运行以下描述的`rake gitlab:cleanup:orphan_lfs_files` . + +### Remove unreferenced LFS files immediately[](#remove-unreferenced-lfs-files-immediately "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/36628) . + +每天都会删除未引用的 LFS 文件,但是如果需要,您可以立即删除它们. 例如: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:cleanup:orphan_lfs_files + +# installation from source +bundle exec rake gitlab:cleanup:orphan_lfs_files +``` + +输出示例: + +``` +$ sudo gitlab-rake gitlab:cleanup:orphan_lfs_files +I, [2020-01-08T20:51:17.148765 #43765] INFO -- : Removed unreferenced LFS files: 12 +``` + +## Clean up project upload files[](#clean-up-project-upload-files "Permalink") + +如果项目上传文件在 GitLab 数据库中不存在,请清理它们. + +### Clean up project upload files from filesystem[](#clean-up-project-upload-files-from-filesystem "Permalink") + +在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20863) . + +如果本地项目上传文件在 GitLab 数据库中不存在,请清理它们. 如果该任务可以找到其项目,则该任务将尝试修复该文件,否则,它将文件移至丢失并找到的目录. + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:cleanup:project_uploads + +# installation from source +bundle exec rake gitlab:cleanup:project_uploads RAILS_ENV=production +``` + +输出示例: + +``` +$ sudo gitlab-rake gitlab:cleanup:project_uploads + +I, [2018-07-27T12:08:27.671559 #89817] INFO -- : Looking for orphaned project uploads to clean up. Dry run... +D, [2018-07-27T12:08:28.293568 #89817] DEBUG -- : Processing batch of 500 project upload file paths, starting with /opt/gitlab/embedded/service/gitlab-rails/public/uploads/test.out +I, [2018-07-27T12:08:28.689869 #89817] INFO -- : Can move to lost and found /opt/gitlab/embedded/service/gitlab-rails/public/uploads/test.out -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/project-lost-found/test.out +I, [2018-07-27T12:08:28.755624 #89817] INFO -- : Can fix /opt/gitlab/embedded/service/gitlab-rails/public/uploads/foo/bar/89a0f7b0b97008a4a18cedccfdcd93fb/foo.txt -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/qux/foo/bar/89a0f7b0b97008a4a18cedccfdcd93fb/foo.txt +I, [2018-07-27T12:08:28.760257 #89817] INFO -- : Can move to lost and found /opt/gitlab/embedded/service/gitlab-rails/public/uploads/foo/bar/1dd6f0f7eefd2acc4c2233f89a0f7b0b/image.png -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/project-lost-found/foo/bar/1dd6f0f7eefd2acc4c2233f89a0f7b0b/image.png +I, [2018-07-27T12:08:28.764470 #89817] INFO -- : To cleanup these files run this command with DRY_RUN=false + +$ sudo gitlab-rake gitlab:cleanup:project_uploads DRY_RUN=false I, [2018-07-27T12:08:32.944414 #89936] INFO -- : Looking for orphaned project uploads to clean up... +D, [2018-07-27T12:08:33.293568 #89817] DEBUG -- : Processing batch of 500 project upload file paths, starting with /opt/gitlab/embedded/service/gitlab-rails/public/uploads/test.out +I, [2018-07-27T12:08:33.689869 #89817] INFO -- : Did move to lost and found /opt/gitlab/embedded/service/gitlab-rails/public/uploads/test.out -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/project-lost-found/test.out +I, [2018-07-27T12:08:33.755624 #89817] INFO -- : Did fix /opt/gitlab/embedded/service/gitlab-rails/public/uploads/foo/bar/89a0f7b0b97008a4a18cedccfdcd93fb/foo.txt -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/qux/foo/bar/89a0f7b0b97008a4a18cedccfdcd93fb/foo.txt +I, [2018-07-27T12:08:33.760257 #89817] INFO -- : Did move to lost and found /opt/gitlab/embedded/service/gitlab-rails/public/uploads/foo/bar/1dd6f0f7eefd2acc4c2233f89a0f7b0b/image.png -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/project-lost-found/foo/bar/1dd6f0f7eefd2acc4c2233f89a0f7b0b/image.png +``` + +### Clean up project upload files from object storage[](#clean-up-project-upload-files-from-object-storage "Permalink") + +在 GitLab 11.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20918) . + +如果对象存储库上载文件在 GitLab 数据库中不存在,请将其移动到丢失和找到的目录中. + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:cleanup:remote_upload_files + +# installation from source +bundle exec rake gitlab:cleanup:remote_upload_files RAILS_ENV=production +``` + +Example output: + +``` +$ sudo gitlab-rake gitlab:cleanup:remote_upload_files + +I, [2018-08-02T10:26:13.995978 #45011] INFO -- : Looking for orphaned remote uploads to remove. Dry run... +I, [2018-08-02T10:26:14.120400 #45011] INFO -- : Can be moved to lost and found: @hashed/6b/DSC_6152.JPG +I, [2018-08-02T10:26:14.120482 #45011] INFO -- : Can be moved to lost and found: @hashed/79/02/7902699be42c8a8e46fbbb4501726517e86b22c56a189f7625a6da49081b2451/711491b29d3eb08837798c4909e2aa4d/DSC00314.jpg +I, [2018-08-02T10:26:14.120634 #45011] INFO -- : To cleanup these files run this command with DRY_RUN=false +``` + +``` +$ sudo gitlab-rake gitlab:cleanup:remote_upload_files DRY_RUN=false I, [2018-08-02T10:26:47.598424 #45087] INFO -- : Looking for orphaned remote uploads to remove... +I, [2018-08-02T10:26:47.753131 #45087] INFO -- : Moved to lost and found: @hashed/6b/DSC_6152.JPG -> lost_and_found/@hashed/6b/DSC_6152.JPG +I, [2018-08-02T10:26:47.764356 #45087] INFO -- : Moved to lost and found: @hashed/79/02/7902699be42c8a8e46fbbb4501726517e86b22c56a189f7625a6da49081b2451/711491b29d3eb08837798c4909e2aa4d/DSC00314.jpg -> lost_and_found/@hashed/79/02/7902699be42c8a8e46fbbb4501726517e86b22c56a189f7625a6da49081b2451/711491b29d3eb08837798c4909e2aa4d/DSC00314.jpg +``` + +## Remove orphan artifact files[](#remove-orphan-artifact-files "Permalink") + +版本历史 + +* 在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29681) . +* 在 GitLab 12.10 中[修复](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28023)了[`ionice`支持](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28023) . + +如果发现磁盘上的作业工件文件多于应有的数量,则可以运行: + +``` +sudo gitlab-rake gitlab:cleanup:orphan_job_artifact_files +``` + +该命令: + +* 扫描整个工件文件夹. +* 检查哪些文件在数据库中仍然有记录. +* 如果找不到数据库记录,那么将从磁盘中删除该文件. + +默认情况下,此任务不会删除任何内容,但会显示它可以删除的内容. 如果您实际上要删除文件,请运行`DRY_RUN=false`的命令: + +``` +sudo gitlab-rake gitlab:cleanup:orphan_job_artifact_files DRY_RUN=false +``` + +您还可以使用`LIMIT`要删除的文件数: + +``` +sudo gitlab-rake gitlab:cleanup:orphan_job_artifact_files LIMIT=100 +``` + +这只会从磁盘上删除多达 100 个文件. 您可以使用此功能删除一小集以进行测试. + +如果提供`DEBUG=1` ,则将看到被检测为孤立文件的每个文件的完整路径. + +如果安装了`ionice` ,则任务将使用它来确保命令不会在磁盘上造成太大的负载. 您可以使用`NICENESS`配置`NICENESS`级别. 以下是有效水平,但请务必咨询`man 1 ionice` . + +* `0` or `None` +* `1` or `Realtime` +* `2` or `Best-effort` (default) +* `3` or `Idle` + +## Remove expired ActiveSession lookup keys[](#remove-expired-activesession-lookup-keys "Permalink") + +在 GitLab 12.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30668) . + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:cleanup:sessions:active_sessions_lookup_keys + +# installation from source +bundle exec rake gitlab:cleanup:sessions:active_sessions_lookup_keys RAILS_ENV=production +``` + +## Container Registry garbage collection[](#container-registry-garbage-collection "Permalink") + +容器注册表可以使用大量的磁盘空间. 为了清除未使用的层,注册表包括一个[垃圾收集命令](../administration/packages/container_registry.html#container-registry-garbage-collection) . \ No newline at end of file diff --git a/docs/512.md b/docs/512.md new file mode 100644 index 0000000000000000000000000000000000000000..0c1ec48e8b7c8addf89e1b8c7f6c9b0c9e9becbc --- /dev/null +++ b/docs/512.md @@ -0,0 +1,27 @@ +# Namespaces + +> 原文:[https://docs.gitlab.com/ee/raketasks/features.html](https://docs.gitlab.com/ee/raketasks/features.html) + +* [Enable usernames and namespaces for user projects](#enable-usernames-and-namespaces-for-user-projects) + +# Namespaces[](#namespaces-core-only "Permalink") + +此 Rake 任务为项目启用[名称空间](../user/group/index.html#namespaces) . + +## Enable usernames and namespaces for user projects[](#enable-usernames-and-namespaces-for-user-projects "Permalink") + +此命令将启用 GitLab 4.0 中引入的名称空间功能. 它将移动每个项目在其名称空间文件夹中. + +Note: + +* **存储库位置将更改** ,因此您将需要**更新所有 Git URL**以指向新位置. +* 可以在**个人资料>帐户中**更改用户名. + +例如: + +* 旧路径: `git@example.org:myrepo.git` . +* 新路径: `git@example.org:username/myrepo.git`或`git@example.org:groupname/myrepo.git` . + +``` +bundle exec rake gitlab:enable_namespaces RAILS_ENV=production +``` \ No newline at end of file diff --git a/docs/513.md b/docs/513.md new file mode 100644 index 0000000000000000000000000000000000000000..329a902a4c74389359a30fb688f0a2daad9d5dbc --- /dev/null +++ b/docs/513.md @@ -0,0 +1,317 @@ +# Maintenance Rake tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/maintenance.html](https://docs.gitlab.com/ee/administration/raketasks/maintenance.html) + +* [Gather GitLab and system information](#gather-gitlab-and-system-information) +* [Show GitLab license information](#show-gitlab-license-information-starter-only) +* [Check GitLab configuration](#check-gitlab-configuration) +* [Rebuild authorized_keys file](#rebuild-authorized_keys-file) +* [Clear Redis cache](#clear-redis-cache) +* [Precompile the assets](#precompile-the-assets) +* [Check TCP connectivity to a remote site](#check-tcp-connectivity-to-a-remote-site) +* [Clear exclusive lease (DANGER)](#clear-exclusive-lease-danger) +* [Display status of database migrations](#display-status-of-database-migrations) +* [Run incomplete database migrations](#run-incomplete-database-migrations) +* [Import common metrics](#import-common-metrics) + +# Maintenance Rake tasks[](#maintenance-rake-tasks-core-only "Permalink") + +GitLab 提供 Rake 任务进行常规维护. + +## Gather GitLab and system information[](#gather-gitlab-and-system-information "Permalink") + +该命令收集有关您的 GitLab 安装及其运行系统的信息. 这些在寻求帮助或报告问题时可能很有用. + +**全部安装** + +``` +sudo gitlab-rake gitlab:env:info +``` + +**源安装** + +``` +bundle exec rake gitlab:env:info RAILS_ENV=production +``` + +输出示例: + +``` +System information +System: Debian 7.8 +Current User: git +Using RVM: no +Ruby Version: 2.1.5p273 +Gem Version: 2.4.3 +Bundler Version: 1.7.6 +Rake Version: 10.3.2 +Redis Version: 3.2.5 +Sidekiq Version: 2.17.8 + +GitLab information +Version: 7.7.1 +Revision: 41ab9e1 +Directory: /home/git/gitlab +DB Adapter: postgresql +URL: https://gitlab.example.com +HTTP Clone URL: https://gitlab.example.com/some-project.git +SSH Clone URL: git@gitlab.example.com:some-project.git +Using LDAP: no +Using Omniauth: no + +GitLab Shell +Version: 2.4.1 +Repositories: /home/git/repositories/ +Hooks: /home/git/gitlab-shell/hooks/ +Git: /usr/bin/git +``` + +## Show GitLab license information[](#show-gitlab-license-information-starter-only "Permalink") + +在 GitLab Starter 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20501) . + +该命令显示有关您的[GitLab 许可证](../../user/admin_area/license.html)以及使用了多少个席位的信息. 它仅在 GitLab Enterprise 安装中可用:许可证无法安装到 GitLab Community Edition 中. + +当通过支持人员举票或以编程方式检查许可证参数时,这些选项可能很有用. + +**全部安装** + +``` +sudo gitlab-rake gitlab:license:info +``` + +**源安装** + +``` +bundle exec rake gitlab:license:info RAILS_ENV=production +``` + +输出示例: + +``` +Today's Date: 2020-02-29 +Current User Count: 30 +Max Historical Count: 30 +Max Users in License: 40 +License valid from: 2019-11-29 to 2020-11-28 +Email associated with license: user@example.com +``` + +## Check GitLab configuration[](#check-gitlab-configuration "Permalink") + +`gitlab:check` Rake 任务运行以下 Rake 任务: + +* `gitlab:gitlab_shell:check` +* `gitlab:gitaly:check` +* `gitlab:sidekiq:check` +* `gitlab:app:check` + +它将检查是否已根据安装指南设置了每个组件,并针对发现的问题提出了修复建议. 此命令必须从您的应用程序服务器运行,并且在[Gitaly 之](../gitaly/index.html#run-gitaly-on-its-own-server)类的组件服务器上将无法正常运行. + +您还可以查看我们的故障排除指南,以了解: + +* [GitLab](../index.html#troubleshooting) +* [Omnibus GitLab](https://docs.gitlab.com/omnibus/README.html) + +要运行`gitlab:check` ,请运行: + +**全部安装** + +``` +sudo gitlab-rake gitlab:check +``` + +**源安装** + +``` +bundle exec rake gitlab:check RAILS_ENV=production +``` + +**注意:**对`gitlab:check`使用`SANITIZE=true` `gitlab:check`是否要从输出中省略项目名称. + +输出示例: + +``` +Checking Environment ... + +Git configured for git user? ... yes +Has python2? ... yes +python2 is supported version? ... yes + +Checking Environment ... Finished + +Checking GitLab Shell ... + +GitLab Shell version? ... OK (1.2.0) +Repo base directory exists? ... yes +Repo base directory is a symlink? ... no +Repo base owned by git:git? ... yes +Repo base access is drwxrws---? ... yes +post-receive hook up-to-date? ... yes +post-receive hooks in repos are links: ... yes + +Checking GitLab Shell ... Finished + +Checking Sidekiq ... + +Running? ... yes + +Checking Sidekiq ... Finished + +Checking GitLab ... + +Database config exists? ... yes +Database is SQLite ... no +All migrations up? ... yes +GitLab config exists? ... yes +GitLab config outdated? ... no +Log directory writable? ... yes +Tmp directory writable? ... yes +Init script exists? ... yes +Init script up-to-date? ... yes +Redis version >= 2.0.0? ... yes + +Checking GitLab ... Finished +``` + +## Rebuild authorized_keys file[](#rebuild-authorized_keys-file "Permalink") + +在某些情况下,有必要重建`authorized_keys`文件. 为此,请运行: + +**全部安装** + +``` +sudo gitlab-rake gitlab:shell:setup +``` + +**源安装** + +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production +``` + +输出示例: + +``` +This will rebuild an authorized_keys file. +You will lose any data stored in authorized_keys file. +Do you want to continue (yes/no)? yes +``` + +## Clear Redis cache[](#clear-redis-cache "Permalink") + +如果出于某种原因,仪表板显示了错误的信息,则可能需要清除 Redis 的缓存. 为此,请运行: + +**全部安装** + +``` +sudo gitlab-rake cache:clear +``` + +**源安装** + +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production +``` + +## Precompile the assets[](#precompile-the-assets "Permalink") + +有时,在版本升级期间,您可能会遇到一些错误的 CSS 或缺少某些图标的情况. 在这种情况下,请尝试再次重新编译资产. + +这仅适用于源安装,不适用于 Omnibus 软件包. + +**源安装** + +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production +``` + +对于多功能版本,未优化的资产(JavaScript,CSS)在上游 GitLab 发行时被冻结. 多功能版本包括这些资产的优化版本. 除非在安装软件包之后在生产机器上修改 JavaScript / CSS 代码,否则应该没有理由在生产机器上重做`rake gitlab:assets:compile` . 如果您怀疑资产已损坏,则应重新安装 omnibus 软件包. + +## Check TCP connectivity to a remote site[](#check-tcp-connectivity-to-a-remote-site "Permalink") + +有时您需要知道您的 GitLab 安装是否可以连接到另一台机器上的 TCP 服务-也许是 PostgreSQL 或 HTTPS 服务器. 包含一个 Rake 任务可以帮助您: + +**全部安装** + +``` +sudo gitlab-rake gitlab:tcp_check[example.com,80] +``` + +**源安装** + +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:tcp_check[example.com,80] RAILS_ENV=production +``` + +## Clear exclusive lease (DANGER)[](#clear-exclusive-lease-danger "Permalink") + +GitLab 使用共享锁机制: `ExclusiveLease`防止共享资源中的同时操作. 一个示例是在存储库上运行定期垃圾收集. + +在非常特殊的情况下,如果不释放锁定,则由专有租赁锁定的操作可能会失败. 如果您不能等待它过期,可以运行此任务以手动清除它. + +要清除所有专有租赁: + +**危险:**请勿在 GitLab 或 Sidekiq 运行时运行它 + +``` +sudo gitlab-rake gitlab:exclusive_lease:clear +``` + +要指定租约`type`或租约`type + id` ,请指定范围: + +``` +# to clear all leases for repository garbage collection: +sudo gitlab-rake gitlab:exclusive_lease:clear[project_housekeeping:*] + +# to clear a lease for repository garbage collection in a specific project: (id=4) +sudo gitlab-rake gitlab:exclusive_lease:clear[project_housekeeping:4] +``` + +## Display status of database migrations[](#display-status-of-database-migrations "Permalink") + +请参阅[升级文档](../../update/README.html#checking-for-background-migrations-before-upgrading) ,以了解在升级 GitLab 时如何检查迁移是否完成. + +要检查特定迁移的状态,可以使用以下 Rake 任务: + +``` +sudo gitlab-rake db:migrate:status +``` + +这将为每个迁移 ID 输出一个`Status`为`up`或`down`的表. + +``` +database: gitlabhq_production + + Status Migration ID Migration Name +-------------------------------------------------- + up migration_id migration_name +``` + +## Run incomplete database migrations[](#run-incomplete-database-migrations "Permalink") + +数据库迁移可能会停留在不完整的状态. 也就是说,它们在`sudo gitlab-rake db:migrate:status`命令的输出中将处于`down`状态. + +要完成这些迁移,请使用以下 Rake 任务: + +``` +sudo gitlab-rake db:migrate +``` + +命令完成后,运行`sudo gitlab-rake db:migrate:status`来检查是否所有迁移都已完成(具有`up`状态). + +## Import common metrics[](#import-common-metrics "Permalink") + +有时,您可能需要重新导入为"指标"仪表板提供动力的通用指标. + +这可能是由于[更新现有指标](../../development/prometheus_metrics.html#update-existing-metrics)或作为[故障排除措施的结果](../../operations/metrics/dashboards/index.html#troubleshooting) . + +要重新导入指标,可以运行: + +``` +sudo gitlab-rake metrics:setup_common_metrics +``` \ No newline at end of file diff --git a/docs/514.md b/docs/514.md new file mode 100644 index 0000000000000000000000000000000000000000..1fbeffa72eb31537b7e756729638a7fb4326b1ce --- /dev/null +++ b/docs/514.md @@ -0,0 +1,81 @@ +# Geo Rake Tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/geo.html](https://docs.gitlab.com/ee/administration/raketasks/geo.html) + +* [Git housekeeping](#git-housekeeping) + * [Incremental Repack](#incremental-repack) + * [Full Repack](#full-repack) + * [GC](#gc) +* [Remove orphaned project registries](#remove-orphaned-project-registries) + +# Geo Rake Tasks[](#geo-rake-tasks-premium-only "Permalink") + +以下 Rake 任务适用于[Geo 安装](../geo/replication/index.html) . + +## Git housekeeping[](#git-housekeeping "Permalink") + +您可以执行一些任务来调度 Git 内务处理,以从**辅助**节点中的下一个存储库同步开始: + +### Incremental Repack[](#incremental-repack "Permalink") + +这等效于在*裸*仓库上运行`git repack -d` . + +**全部安装** + +``` +sudo gitlab-rake geo:git:housekeeping:incremental_repack +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake geo:git:housekeeping:incremental_repack RAILS_ENV=production +``` + +### Full Repack[](#full-repack "Permalink") + +这等效于在*裸*仓库上运行`git repack -d -A --pack-kept-objects` ,可以选择在 GitLab 中启用它时写入可达性位图索引. + +**全部安装** + +``` +sudo gitlab-rake geo:git:housekeeping:full_repack +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake geo:git:housekeeping:full_repack RAILS_ENV=production +``` + +### GC[](#gc "Permalink") + +这等效于在*裸*仓库上运行`git gc` ,如果在 GitLab 中启用了此功能,则可以选择编写可达性位图索引. + +**全部安装** + +``` +sudo gitlab-rake geo:git:housekeeping:gc +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake geo:git:housekeeping:gc RAILS_ENV=production +``` + +## Remove orphaned project registries[](#remove-orphaned-project-registries "Permalink") + +在某些情况下,您的项目注册表可能包含过时的记录,您可以使用 Rake 任务`geo:run_orphaned_project_registry_cleaner`删除它们: + +**全部安装** + +``` +sudo gitlab-rake geo:run_orphaned_project_registry_cleaner +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake geo:run_orphaned_project_registry_cleaner RAILS_ENV=production +``` \ No newline at end of file diff --git a/docs/515.md b/docs/515.md new file mode 100644 index 0000000000000000000000000000000000000000..fc2b3abf02c0712854caf111dfd8c517054331db --- /dev/null +++ b/docs/515.md @@ -0,0 +1,45 @@ +# GitHub import + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/github_import.html](https://docs.gitlab.com/ee/administration/raketasks/github_import.html) + +* [Caveats](#caveats) +* [Importing multiple projects](#importing-multiple-projects) +* [Importing a single project](#importing-a-single-project) + +# GitHub import[](#github-import-core-only "Permalink") + +在 GitLab 9.1 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10308) . + +为了检索和导入 GitHub 存储库,您将需要一个[GitHub 个人访问令牌](https://github.com/settings/tokens) . 用户名应作为 Rake 任务的第二个参数传递,该任务将成为项目的所有者. 您可以使用相同的命令恢复导入. + +请记住,语法非常具体. 删除参数块内以及方括号之前/之后的所有空格. 此外,某些外壳程序(例如`zsh` )可以分别解释开/关括号( `[]` ). 您可能需要转义括号或使用双引号. + +## Caveats[](#caveats "Permalink") + +如果在导入时达到 GitHub [速率限制](https://developer.github.com/v3/#rate-limiting) ,则导入过程将等待( `sleep()` ),直到可以继续导入为止. + +## Importing multiple projects[](#importing-multiple-projects "Permalink") + +要从可用的 GitHub 项目列表中导入项目,请执行以下操作: + +``` +# Omnibus installations +sudo gitlab-rake "import:github[access_token,root,foo/bar]" + +# Installations from source +bundle exec rake "import:github[access_token,root,foo/bar]" RAILS_ENV=production +``` + +在这种情况下, `access_token`是您的 GitHub 个人访问令牌, `root`是您的 GitLab 用户名,而`foo/bar`是将从您的 GitHub 项目创建的新 GitLab 名称空间/项目. 子组也是可能的: `foo/foo/bar` . + +## Importing a single project[](#importing-a-single-project "Permalink") + +要导入特定的 GitHub 项目(在此处名为`foo/github_repo` ): + +``` +# Omnibus installations +sudo gitlab-rake "import:github[access_token,root,foo/bar,foo/github_repo]" + +# Installations from source +bundle exec rake "import:github[access_token,root,foo/bar,foo/github_repo]" RAILS_ENV=production +``` \ No newline at end of file diff --git a/docs/516.md b/docs/516.md new file mode 100644 index 0000000000000000000000000000000000000000..0da21b979c19f2b79babcaa2110dfbc8264c5868 --- /dev/null +++ b/docs/516.md @@ -0,0 +1,132 @@ +# Import bare repositories + +> 原文:[https://docs.gitlab.com/ee/raketasks/import.html](https://docs.gitlab.com/ee/raketasks/import.html) + +* [Example output](#example-output) +* [Importing bare repositories from hashed storage](#importing-bare-repositories-from-hashed-storage) + * [GitLab 10.3 or earlier](#gitlab-103-or-earlier) + * [GitLab 10.4 and later](#gitlab-104-and-later) + +# Import bare repositories[](#import-bare-repositories-core-only "Permalink") + +Rake 任务可用于将裸仓库导入 GitLab 实例. + +注意: + +* 项目的所有者将是第一位管理员. +* 将根据需要创建组,包括子组. +* 组的所有者将是第一位管理员. +* 现有项目将被跳过. +* 散列存储中的项目可能会被跳过. 有关更多信息,请参阅[从哈希存储导入裸存储库](#importing-bare-repositories-from-hashed-storage) . +* 现有的 Git 存储库将从磁盘中移出(从原始路径中移出). + +要将裸仓库导入 GitLab 实例: + +1. 创建一个新文件夹以从中导入您的 Git 存储库. 新文件夹需要具有 Git 用户所有权,并且需要对 Git 用户及其组具有读/写/执行访问权限: + + ``` + sudo -u git mkdir -p /var/opt/gitlab/git-data/repository-import-/new_group + ``` + +2. 将裸存储库复制到此新创建的文件夹中. 注意: + + * 在任何子文件夹中找到的所有`.git`存储库都将作为项目导入. + * 将根据需要创建组,这些组可以是嵌套文件夹. + + 例如,如果我们将存储库复制到`/var/opt/gitlab/git-data/repository-import-` ,并且存储库`A`必须位于组`G1`和`G2` ,则必须在以下文件夹下创建它: `/var/opt/gitlab/git-data/repository-import-/G1/G2/A.git` . + + ``` + sudo cp -r /old/git/foo.git /var/opt/gitlab/git-data/repository-import-/new_group/ + + # Do this once when you are done copying git repositories + sudo chown -R git:git /var/opt/gitlab/git-data/repository-import- + ``` + + `foo.git`必须由`git`用户和`git`用户组拥有. + + 如果您使用源安装,请用`/home/git`替换`/var/opt/gitlab/` . + +3. 根据您的安装类型运行以下命令: + + * 全部安装 + + ``` + sudo gitlab-rake gitlab:import:repos['/var/opt/gitlab/git-data/repository-import-'] + ``` + + * 从源安装. 在运行此命令之前,您需要切换到 GitLab 安装所在的目录: + + ``` + cd /home/git/gitlab + sudo -u git -H bundle exec rake gitlab:import:repos['/var/opt/gitlab/git-data/repository-import-'] RAILS_ENV=production + ``` + +## Example output[](#example-output "Permalink") + +``` +Processing /var/opt/gitlab/git-data/repository-import-1/a/b/c/blah.git + * Using namespace: a/b/c + * Created blah (a/b/c/blah) + * Skipping repo /var/opt/gitlab/git-data/repository-import-1/a/b/c/blah.wiki.git +Processing /var/opt/gitlab/git-data/repository-import-1/abcd.git + * Created abcd (abcd.git) +Processing /var/opt/gitlab/git-data/repository-import-1/group/xyz.git + * Using namespace: group (2) + * Created xyz (group/xyz.git) + * Skipping repo /var/opt/gitlab/git-data/repository-import-1/@shared/a/b/abcd.git +[...] +``` + +## Importing bare repositories from hashed storage[](#importing-bare-repositories-from-hashed-storage "Permalink") + +旧版存储中的项目具有目录结构,该目录结构反映了 GitLab 中完整的项目路径,包括名称空间结构. 裸存储库导入程序将利用此信息将项目导入到正确的位置. 每个项目及其父名称空间均有意义地命名. + +但是,哈希存储中项目的目录结构不包含此信息. 由于多种原因,这是有益的,尤其是改善的性能和数据完整性. 有关更多详细信息,请参见[存储库存储类型](../administration/repository_storage_types.html) . + +可导入的存储库取决于 GitLab 的版本. + +### GitLab 10.3 or earlier[](#gitlab-103-or-earlier "Permalink") + +不支持从哈希存储导入裸存储库. + +### GitLab 10.4 and later[](#gitlab-104-and-later "Permalink") + +为了支持从哈希存储中导入裸存储库,GitLab 10.4 和更高版本将每个存储库的完整项目路径存储在 Git 存储库配置文件的特殊部分. 本节的格式如下: + +``` +[gitlab] + fullpath = gitlab-org/gitlab +``` + +但是,现有存储库并未迁移为包括此路径. + +如果 GitLab 10.4 和更高版本中的存储库发生以下事件,则裸存储库是可导入的: + +* Created +* 迁移到哈希存储 +* Renamed +* 转移到另一个名称空间 +* 祖先更名 +* 祖先转移到另一个名称空间 + +如果仓库满足以下所有条件,则裸仓库**无法**通过 GitLab 10.4 导入到 GitLab 11.6: + +* 它是在 GitLab 10.3 或更早版本中创建的. +* 它没有重命名,传输或迁移到 GitLab 10.4 的[哈希存储](../administration/repository_storage_types.html#hashed-storage)中,也没有迁移到 GitLab 11.6. +* 它的祖先名称空间未在 GitLab 10.4 中重命名或传输到 GitLab 11.6. + +[从 GitLab 11.6 开始](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41776) ,所有裸仓库都可以导入. + +要自己手动迁移存储库(对于从 GitLab 10.4 到 GitLab 11.6 的迁移),可以使用[Rails 控制台](../administration/troubleshooting/debug.html#starting-a-rails-console-session)进行. 在 Rails 控制台会话中,运行以下命令来迁移项目: + +``` +project = Project.find_by_full_path('gitlab-org/gitlab') +project.write_repository_config +``` + +在 Rails 控制台会话中,运行以下命令以迁移名称空间的所有项目(如果名称空间中有数千个项目,则可能需要一段时间): + +``` +namespace = Namespace.find_by_full_path('gitlab-org') +namespace.send(:write_projects_repository_config) +``` \ No newline at end of file diff --git a/docs/517.md b/docs/517.md new file mode 100644 index 0000000000000000000000000000000000000000..34c991764b103ef0007045ccf7ff8101ff763163 --- /dev/null +++ b/docs/517.md @@ -0,0 +1,129 @@ +# Integrity check Rake task + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/check.html](https://docs.gitlab.com/ee/administration/raketasks/check.html) + +* [Repository integrity](#repository-integrity) + * [Check all GitLab repositories](#check-all-gitlab-repositories) +* [Uploaded files integrity](#uploaded-files-integrity) +* [LDAP check](#ldap-check) + +# Integrity check Rake task[](#integrity-check-rake-task-core-only "Permalink") + +GitLab 提供了 Rake 任务来检查各种组件的完整性. + +## Repository integrity[](#repository-integrity "Permalink") + +尽管 Git 非常灵活,并试图防止数据完整性问题,但有时还是会出错. 以下 Rake 任务旨在帮助 GitLab 管理员诊断问题存储库,以便对其进行修复. + +需要检查 3 件事以确定完整性. + +1. Git 存储库文件系统检查( [`git fsck`](https://git-scm.com/docs/git-fsck) ). 此步骤验证存储库中对象的连接性和有效性. +2. 在存储库目录中检查`config.lock` . +3. 检查`refs/heads`是否有任何分支/引用锁定文件. + +重要的是要注意,仅存在`config.lock`或引用锁并不一定表示问题. 当 Git 和 GitLab 在存储库上执行操作时,会定期创建和删除锁定文件. 它们用于防止数据完整性问题. 但是,如果 Git 操作被中断,则这些锁可能无法正确清理. + +以下症状可能表明存储库完整性有问题. 如果用户遇到这些症状,则可以使用下面介绍的 Rake 任务来确定导致问题的确切存储库. + +* 尝试推送代码时收到错误- `remote: error: cannot lock ref` +* 查看 GitLab 仪表板或访问特定项目时出现 500 错误. + +### Check all GitLab repositories[](#check-all-gitlab-repositories "Permalink") + +此任务循环遍历 GitLab 服务器上的所有存储库,并运行前面所述的完整性检查. + +**全部安装** + +``` +sudo gitlab-rake gitlab:git:fsck +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake gitlab:git:fsck RAILS_ENV=production +``` + +## Uploaded files integrity[](#uploaded-files-integrity "Permalink") + +用户可以将各种类型的文件上传到 GitLab 安装. 这些完整性检查可以检测丢失的文件. 此外,对于本地存储的文件,会在上载时生成校验和并将其存储在数据库中,这些校验将针对当前文件进行校验. + +当前,以下类型的文件支持完整性检查: + +* CI 工件(从版本 10.7.0 起可用) +* LFS 对象(从版本 10.6.0 起可用) +* 用户上传(从版本 10.6.0 起可用) + +**全部安装** + +``` +sudo gitlab-rake gitlab:artifacts:check +sudo gitlab-rake gitlab:lfs:check +sudo gitlab-rake gitlab:uploads:check +``` + +**Source Installation** + +``` +sudo -u git -H bundle exec rake gitlab:artifacts:check RAILS_ENV=production +sudo -u git -H bundle exec rake gitlab:lfs:check RAILS_ENV=production +sudo -u git -H bundle exec rake gitlab:uploads:check RAILS_ENV=production +``` + +这些任务还接受一些环境变量,可用于覆盖某些值: + +| Variable | Type | Description | +| --- | --- | --- | +| `BATCH` | integer | 指定批处理的大小. 默认为 200. | +| `ID_FROM` | integer | 指定从其开始的 ID,包括值. | +| `ID_TO` | integer | 指定以 ID 结尾的 ID 值(包括该值). | +| `VERBOSE` | boolean | 导致失败被单独列出,而不是被汇总. | + +``` +sudo gitlab-rake gitlab:artifacts:check BATCH=100 ID_FROM=50 ID_TO=250 +sudo gitlab-rake gitlab:lfs:check BATCH=100 ID_FROM=50 ID_TO=250 +sudo gitlab-rake gitlab:uploads:check BATCH=100 ID_FROM=50 ID_TO=250 +``` + +输出示例: + +``` +$ sudo gitlab-rake gitlab:uploads:check +Checking integrity of Uploads +- 1..1350: Failures: 0 +- 1351..2743: Failures: 0 +- 2745..4349: Failures: 2 +- 4357..5762: Failures: 1 +- 5764..7140: Failures: 2 +- 7142..8651: Failures: 0 +- 8653..10134: Failures: 0 +- 10135..11773: Failures: 0 +- 11777..13315: Failures: 0 +Done! +``` + +详细输出示例: + +``` +$ sudo gitlab-rake gitlab:uploads:check VERBOSE=1 +Checking integrity of Uploads +- 1..1350: Failures: 0 +- 1351..2743: Failures: 0 +- 2745..4349: Failures: 2 + - Upload: 3573: # + - Upload: 3580: # +- 4357..5762: Failures: 1 + - Upload: 4636: # +- 5764..7140: Failures: 2 + - Upload: 5812: # + - Upload: 5837: # +- 7142..8651: Failures: 0 +- 8653..10134: Failures: 0 +- 10135..11773: Failures: 0 +- 11777..13315: Failures: 0 +Done! +``` + +## LDAP check[](#ldap-check "Permalink") + +LDAP 检查 Rake 任务将测试绑定 DN 和密码凭据(如果已配置),并将列出 LDAP 用户的样本. 此任务也作为`gitlab:check`任务的一部分执行,但可以独立运行. 有关详细信息,请参见[LDAP Rake 任务-LDAP 检查](ldap.html#check) . \ No newline at end of file diff --git a/docs/518.md b/docs/518.md new file mode 100644 index 0000000000000000000000000000000000000000..cef49e6f0711b82fb297c2150fd4faeb2e234ee2 --- /dev/null +++ b/docs/518.md @@ -0,0 +1,133 @@ +# LDAP Rake tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/ldap.html](https://docs.gitlab.com/ee/administration/raketasks/ldap.html) + +* [Check](#check) +* [Run a group sync](#run-a-group-sync-starter-only) +* [Rename a provider](#rename-a-provider) + * [Example](#example) + * [Other options](#other-options) + +# LDAP Rake tasks[](#ldap-rake-tasks-core-only "Permalink") + +以下是与 LDAP 相关的 Rake 任务. + +## Check[](#check "Permalink") + +LDAP 检查 Rake 任务将测试`bind_dn`和`password`凭据(如果已配置),并将列出 LDAP 用户的样本. 此任务也作为`gitlab:check`任务的一部分执行,但可以使用以下命令独立运行. + +**全部安装** + +``` +sudo gitlab-rake gitlab:ldap:check +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake gitlab:ldap:check RAILS_ENV=production +``` + +默认情况下,该任务将返回 100 个 LDAP 用户的样本. 通过将数字传递给检查任务来更改此限制: + +``` +rake gitlab:ldap:check[50] +``` + +## Run a group sync[](#run-a-group-sync-starter-only "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14735) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.2. + +The following task will run a [group sync](../auth/ldap/index.html#group-sync-starter-only) immediately. This is valuable when you’d like to update all configured group memberships against LDAP without waiting for the next scheduled group sync to be run. + +**注意:**如果您想更改执行群组同步的频率,请改为[调整 Cron 时间表](../auth/ldap/index.html#adjusting-ldap-group-sync-schedule-starter-only) . + +**全部安装** + +``` +sudo gitlab-rake gitlab:ldap:group_sync +``` + +**源安装** + +``` +bundle exec rake gitlab:ldap:group_sync +``` + +## Rename a provider[](#rename-a-provider "Permalink") + +如果您在`gitlab.yml`或`gitlab.rb`更改 LDAP 服务器 ID,则将需要更新所有用户身份,否则用户将无法登录.输入新旧提供者,此任务将更新数据库中所有匹配的身份. + +`old_provider`和`new_provider`是从前缀`ldap`加上配置文件中的 LDAP 服务器 ID 派生的. 例如,在`gitlab.yml`或`gitlab.rb`您可能会看到 LDAP 配置,如下所示: + +``` +main: + label: 'LDAP' + host: '_your_ldap_server' + port: 389 + uid: 'sAMAccountName' + ... +``` + +`main`是 LDAP 服务器 ID. 唯一的提供者在一起就是`ldapmain` . + +> **警告** :如果输入了错误的新提供程序,用户将无法登录.如果发生这种情况,请使用错误的提供程序作为`old_provider`并使用正确的提供程序作为`new_provider`再次运行任务. + +**全部安装** + +``` +sudo gitlab-rake gitlab:ldap:rename_provider[old_provider,new_provider] +``` + +**源安装** + +``` +bundle exec rake gitlab:ldap:rename_provider[old_provider,new_provider] RAILS_ENV=production +``` + +### Example[](#example "Permalink") + +考虑从默认服务器 ID `main` (完整提供程序`ldapmain` )开始. 如果将`main`更改为`mycompany` ,则`new_provider`为`ldapmycompany` . 要重命名所有用户身份,请运行以下命令: + +``` +sudo gitlab-rake gitlab:ldap:rename_provider[ldapmain,ldapmycompany] +``` + +输出示例: + +``` +100 users with provider 'ldapmain' will be updated to 'ldapmycompany'. +If the new provider is incorrect, users will be unable to sign in. +Do you want to continue (yes/no)? yes + +User identities were successfully updated +``` + +### Other options[](#other-options "Permalink") + +如果您未指定`old_provider`和`new_provider` ,则会提示您输入它们: + +**全部安装** + +``` +sudo gitlab-rake gitlab:ldap:rename_provider +``` + +**源安装** + +``` +bundle exec rake gitlab:ldap:rename_provider RAILS_ENV=production +``` + +**输出示例:** + +``` +What is the old provider? Ex. 'ldapmain': ldapmain +What is the new provider? Ex. 'ldapcustom': ldapmycompany +``` + +此任务还接受`force`环境变量,该变量将跳过确认对话框: + +``` +sudo gitlab-rake gitlab:ldap:rename_provider[old_provider,new_provider] force=yes +``` \ No newline at end of file diff --git a/docs/519.md b/docs/519.md new file mode 100644 index 0000000000000000000000000000000000000000..be9743f049b4b6b3dc6e54e0294e15b1bcf985f8 --- /dev/null +++ b/docs/519.md @@ -0,0 +1,35 @@ +# Listing repository directories + +> 原文:[https://docs.gitlab.com/ee/raketasks/list_repos.html](https://docs.gitlab.com/ee/raketasks/list_repos.html) + +* [Limit search results](#limit-search-results) + +# Listing repository directories[](#listing-repository-directories-core-only "Permalink") + +您可以在 GitLab 管理的磁盘上打印所有 Git 存储库的列表. + +要打印列表,请运行以下命令: + +``` +# Omnibus +sudo gitlab-rake gitlab:list_repos + +# Source +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:list_repos RAILS_ENV=production +``` + +**注意:**结果使用 GitLab Rails 应用程序的默认顺序. + +## Limit search results[](#limit-search-results "Permalink") + +要仅列出具有最近活动的项目,请传递带有`SINCE`环境变量的日期. 您指定的时间由 Rails [TimeZone#parse 函数解析](https://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html#method-i-parse) . + +``` +# Omnibus +sudo gitlab-rake gitlab:list_repos SINCE='Sep 1 2015' + +# Source +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:list_repos RAILS_ENV=production SINCE='Sep 1 2015' +``` \ No newline at end of file diff --git a/docs/520.md b/docs/520.md new file mode 100644 index 0000000000000000000000000000000000000000..19f0b2bc6b254e2b42a024967e74f04f07c7ada2 --- /dev/null +++ b/docs/520.md @@ -0,0 +1,30 @@ +# Praefect Rake tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/praefect.html](https://docs.gitlab.com/ee/administration/raketasks/praefect.html) + +* [Replica checksums](#replica-checksums) + +# Praefect Rake tasks[](#praefect-rake-tasks-core-only "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28369) . + +瑞克任务可用于在 Praefect 存储上创建的项目. 有关配置 Praefect 的信息,请参见[Praefect 文档](../gitaly/praefect.html) . + +## Replica checksums[](#replica-checksums "Permalink") + +`gitlab:praefect:replicas`打印给定`project_id`的存储库的校验和: + +* 主要的 Gitaly 节点. +* 次要内部 Gitaly 节点. + +**全部安装** + +``` +sudo gitlab-rake "gitlab:praefect:replicas[project_id]" +``` + +**源安装** + +``` +sudo -u git -H bundle exec rake "gitlab:praefect:replicas[project_id]" RAILS_ENV=production +``` \ No newline at end of file diff --git a/docs/521.md b/docs/521.md new file mode 100644 index 0000000000000000000000000000000000000000..a4e07e542782c050661d7a4941bc542b6b3fa6fa --- /dev/null +++ b/docs/521.md @@ -0,0 +1,56 @@ +# Project import/export administration + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/project_import_export.html](https://docs.gitlab.com/ee/administration/raketasks/project_import_export.html) + +* [Project import status](#project-import-status) +* [Import large projects](#import-large-projects) +* [Import/export tasks](#importexport-tasks) + +# Project import/export administration[](#project-importexport-administration-core-only "Permalink") + +版本历史 + +* 在 GitLab 8.9 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3050) . +* 从 GitLab 11.3 起,导入/导出可以自动使用对象存储. + +GitLab 提供与项目导入和导出有关的 Rake 任务. 有关更多信息,请参见: + +* [Project import/export documentation](../../user/project/settings/import_export.html). +* [Project import/export API](../../api/project_import_export.html). +* [Developer documentation: project import/export](../../development/import_export.html) + +## Project import status[](#project-import-status "Permalink") + +您可以通过[Project import / export API](../../api/project_import_export.html#import-status)查询导入. 如 API 文档中所述,查询可能返回导入错误或异常. + +## Import large projects[](#import-large-projects "Permalink") + +如果您的项目较大,请考虑使用 Rake 任务,如[开发人员文档中所述](../../development/import_project.html#importing-via-a-rake-task) . + +## Import/export tasks[](#importexport-tasks "Permalink") + +可以使用以下命令检查 GitLab 导入/导出版本: + +``` +# Omnibus installations +sudo gitlab-rake gitlab:import_export:version + +# Installations from source +bundle exec rake gitlab:import_export:version RAILS_ENV=production +``` + +可以使用以下命令列出要导出的数据库表的当前列表: + +``` +# Omnibus installations +sudo gitlab-rake gitlab:import_export:data + +# Installations from source +bundle exec rake gitlab:import_export:data RAILS_ENV=production +``` + +请注意以下几点: + +* 仅当导入和导出 GitLab 实例的[版本](../../user/project/settings/import_export.html#version-history)与[版本历史记录中](../../user/project/settings/import_export.html#version-history)描述的[版本](../../user/project/settings/import_export.html#version-history)兼容时,才可以导入. +* 必须在" **导入源"**下的应用程序设置( `/admin/application_settings/general` )中启用项目导入选项. **管理区>** **设置>可见性和访问控制** . +* 导出存储在一个临时[共享目录中](../../development/shared_files.html) ,并由特定工作人员每 24 小时删除一次. \ No newline at end of file diff --git a/docs/522.md b/docs/522.md new file mode 100644 index 0000000000000000000000000000000000000000..0e49312f0dc285e140ec686ef2a5883e3ad2bbf7 --- /dev/null +++ b/docs/522.md @@ -0,0 +1,137 @@ +# Repository storage Rake tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/storage.html](https://docs.gitlab.com/ee/administration/raketasks/storage.html) + +* [List projects and attachments](#list-projects-and-attachments) + * [On legacy storage](#on-legacy-storage) + * [On hashed storage](#on-hashed-storage) +* [Migrate to hashed storage](#migrate-to-hashed-storage) +* [Rollback from hashed storage to legacy storage](#rollback-from-hashed-storage-to-legacy-storage) + +# Repository storage Rake tasks[](#repository-storage-rake-tasks-core-only "Permalink") + +这是 Rake 任务的集合,可帮助您列出现有项目及其附件并将其迁移到新的[哈希存储中](../repository_storage_types.html) ,GitLab 用于组织 Git 数据. + +## List projects and attachments[](#list-projects-and-attachments "Permalink") + +以下 Rake 任务将列出旧版存储和哈希存储上可用的项目和附件. + +### On legacy storage[](#on-legacy-storage "Permalink") + +要使用旧式存储获得摘要,然后列出项目及其附件: + +* **全部安装** + + ``` + # Projects + sudo gitlab-rake gitlab:storage:legacy_projects + sudo gitlab-rake gitlab:storage:list_legacy_projects + + # Attachments + sudo gitlab-rake gitlab:storage:legacy_attachments + sudo gitlab-rake gitlab:storage:list_legacy_attachments + ``` + +* **源码安装** + + ``` + # Projects + sudo -u git -H bundle exec rake gitlab:storage:legacy_projects RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:storage:list_legacy_projects RAILS_ENV=production + + # Attachments + sudo -u git -H bundle exec rake gitlab:storage:legacy_attachments RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:storage:list_legacy_attachments RAILS_ENV=production + ``` + +### On hashed storage[](#on-hashed-storage "Permalink") + +要使用散列存储来获得项目及其附件的摘要和列表,请执行以下操作: + +* **全部安装** + + ``` + # Projects + sudo gitlab-rake gitlab:storage:hashed_projects + sudo gitlab-rake gitlab:storage:list_hashed_projects + + # Attachments + sudo gitlab-rake gitlab:storage:hashed_attachments + sudo gitlab-rake gitlab:storage:list_hashed_attachments + ``` + +* **源码安装** + + ``` + # Projects + sudo -u git -H bundle exec rake gitlab:storage:hashed_projects RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:storage:list_hashed_projects RAILS_ENV=production + + # Attachments + sudo -u git -H bundle exec rake gitlab:storage:hashed_attachments RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:storage:list_hashed_attachments RAILS_ENV=production + ``` + +## Migrate to hashed storage[](#migrate-to-hashed-storage "Permalink") + +**注意:**在 GitLab 13.0 中,默认情况下启用了[哈希存储](../repository_storage_types.html#hashed-storage) ,并且不建议使用旧存储. 在 GitLab 14.0 中将删除对旧存储的支持. 如果您使用的是 GitLab 13.0 及更高版本,则无法将新项目切换到旧版存储. 在管理区域中的哈希存储和旧存储之间进行选择的选项已被禁用. + +此任务将安排您所有与之关联的现有项目和附件,以迁移到**Hashed**存储类型: + +* **全部安装** + + ``` + sudo gitlab-rake gitlab:storage:migrate_to_hashed + ``` + +* **源码安装** + + ``` + sudo -u git -H bundle exec rake gitlab:storage:migrate_to_hashed RAILS_ENV=production + ``` + +如果您有任何现有的集成,则可能需要先进行少量部署以进行验证. 您可以通过使用环境变量`ID_FROM`和`ID_TO`在操作中指定 ID 范围来`ID_TO` . 例如,要在 Omnibus GitLab 安装中将项目 ID 限制为项目 ID 50 到 100: + +``` +sudo gitlab-rake gitlab:storage:migrate_to_hashed ID_FROM=50 ID_TO=100 +``` + +您可以在 **管理区域>监视>后台作业**页面. 您可以观看一个特定的队列,以了解完成需要多长时间: `hashed_storage:hashed_storage_project_migrate` . + +达到零后,您可以通过运行以下命令确认每个项目都已迁移. 如果发现有必要,则可以再次运行此迁移脚本以计划丢失的项目. + +任何错误或警告将记录在 Sidekiq 的日志文件中. + +**注意:**如果启用了" [地理"](../geo/replication/index.html) ,则成功迁移的每个项目都会生成一个事件,以复制任何**辅助**节点上的更改. + +您只需要`gitlab:storage:migrate_to_hashed` Rake 任务即可迁移存储库,但是下面还有其他命令可帮助您检查旧版存储和哈希存储中的项目和附件. + +## Rollback from hashed storage to legacy storage[](#rollback-from-hashed-storage-to-legacy-storage "Permalink") + +**不建议使用:**在 GitLab 13.0 中,默认情况下启用了[哈希存储](../repository_storage_types.html#hashed-storage) ,并且不建议使用旧存储. 在 GitLab 14.0 中将删除对旧存储的支持. 如果您使用的是 GitLab 13.0 及更高版本,则无法将新项目切换到旧版存储. 在管理区域中的哈希存储和旧存储之间进行选择的选项已被禁用. + +This task will schedule all your existing projects and associated attachments to be rolled back to the legacy storage type. + +* **全部安装** + + ``` + sudo gitlab-rake gitlab:storage:rollback_to_legacy + ``` + +* **源码安装** + + ``` + sudo -u git -H bundle exec rake gitlab:storage:rollback_to_legacy RAILS_ENV=production + ``` + +如果您有任何现有的集成,则可能需要先进行少量回滚以进行验证. 您可以通过使用环境变量`ID_FROM`和`ID_TO`在操作中指定 ID 范围来`ID_TO` . 例如,要在 Omnibus GitLab 安装中将项目 ID 限制为项目 ID 50 到 100: + +``` +sudo gitlab-rake gitlab:storage:rollback_to_legacy ID_FROM=50 ID_TO=100 +``` + +您可以在 **管理区域>监视>后台作业**页面. 在" **队列"**选项卡上,您可以查看`hashed_storage:hashed_storage_project_rollback`队列以查看该过程将花费多长时间. + +达到零后,您可以通过以下命令确认每个项目都已回滚. 如果某些项目没有回滚,则可以再次运行此回滚脚本以安排进一步的回滚. 任何错误或警告将记录在 Sidekiq 的日志文件中. + +如果您具有地理设置,则回滚将不会自动反映在**辅助**节点上. 您可能需要等待回填操作才能启动,并手动从特殊的`@hashed/`文件夹中删除剩余的存储库. \ No newline at end of file diff --git a/docs/523.md b/docs/523.md new file mode 100644 index 0000000000000000000000000000000000000000..fbd0f15391b90272251765567b0a0b1e9ca491a5 --- /dev/null +++ b/docs/523.md @@ -0,0 +1,28 @@ +# Generate sample Prometheus data + +> 原文:[https://docs.gitlab.com/ee/raketasks/generate_sample_prometheus_data.html](https://docs.gitlab.com/ee/raketasks/generate_sample_prometheus_data.html) + +* [Example](#example) + +# Generate sample Prometheus data[](#generate-sample-prometheus-data-core-only "Permalink") + +到现在为止,此命令将针对特定环境的每个指标运行 Prometheus 查询,时间间隔为一系列时间: + +* 30 分钟 +* 3 小时 +* 8 小时 +* 24 小时 +* 72 小时 +* 7 天 + +每个查询的结果都存储在`sample_metrics`目录下,作为一个以 metric 的`identifier`命名的 YAML 文件. 设置环境变量`USE_SAMPLE_METRICS` ,Prometheus API 查询将重新路由到`Projects::Environments::SampleMetricsController` ,如果`sample_metrics`目录中存在适当的数据集,则该`sample_metrics`会加载相应的数据集. + +此命令需要安装了 Prometheus 的环境中的 ID. + +## Example[](#example "Permalink") + +下面的示例演示如何运行 Rake 任务: + +``` +bundle exec rake gitlab:generate_sample_prometheus_data[21] +``` \ No newline at end of file diff --git a/docs/524.md b/docs/524.md new file mode 100644 index 0000000000000000000000000000000000000000..62a55836022e7400a644013c897ade71923f8251 --- /dev/null +++ b/docs/524.md @@ -0,0 +1,152 @@ +# Uploads migrate Rake tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/uploads/migrate.html](https://docs.gitlab.com/ee/administration/raketasks/uploads/migrate.html) + +* [Migrate to object storage](#migrate-to-object-storage) + * [All-in-one Rake task](#all-in-one-rake-task) + * [Individual Rake tasks](#individual-rake-tasks) +* [Migrate to local storage](#migrate-to-local-storage) + * [All-in-one Rake task](#all-in-one-rake-task-1) + +# Uploads migrate Rake tasks[](#uploads-migrate-rake-tasks-core-only "Permalink") + +`gitlab:uploads:migrate`在不同的存储类型之间迁移上载. + +## Migrate to object storage[](#migrate-to-object-storage "Permalink") + +在为 GitLab 的上传[配置对象存储](../../uploads.html#using-object-storage-core-only)后,使用此任务将现有的上传从本地存储迁移到远程存储. + +阅读有关[在 GitLab 上](../../object_storage.html)使用[对象存储的](../../object_storage.html)更多信息. + +**注意:**所有处理将在后台工作人员中完成, **无需停机** . + +### All-in-one Rake task[](#all-in-one-rake-task "Permalink") + +GitLab 提供了一个包装 Rake 任务,可将所有上载的文件(例如,头像,徽标,附件和网站图标)迁移到对象存储中. 包装器任务调用各个 Rake 任务来逐一迁移属于这些类别的文件. + +这些[单独的 Rake 任务](#individual-rake-tasks)将在下一部分中介绍. + +要将所有上载从本地存储迁移到对象存储,请运行: + +**全部安装** + +``` +gitlab-rake "gitlab:uploads:migrate:all" +``` + +**源安装** + +``` +sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:migrate:all +``` + +### Individual Rake tasks[](#individual-rake-tasks "Permalink") + +如果您已经运行了[多合一 Rake 任务](#all-in-one-rake-task) ,则无需运行这些单独的任务. + +Rake 任务使用三个参数来查找要迁移的上载: + +| Parameter | Type | Description | +| --- | --- | --- | +| `uploader_class` | string | 要从中迁移的上传者的类型. | +| `model_class` | string | 要迁移的模型的类型. | +| `mount_point` | string/symbol | 上传器安装在其上的模型列的名称. | + +**注意:**这些参数主要是在 GitLab 结构的内部,您可能想参考下面的任务列表. + +此任务还接受一个环境变量,您可以使用它来覆盖默认的批处理大小: + +| Variable | Type | Description | +| --- | --- | --- | +| `BATCH` | integer | 指定批处理的大小. 默认为 200. | + +下面显示了如何针对各种类型的上传运行`gitlab:uploads:migrate` . + +**全部安装** + +``` +# gitlab-rake gitlab:uploads:migrate[uploader_class, model_class, mount_point] + +# Avatars +gitlab-rake "gitlab:uploads:migrate[AvatarUploader, Project, :avatar]" +gitlab-rake "gitlab:uploads:migrate[AvatarUploader, Group, :avatar]" +gitlab-rake "gitlab:uploads:migrate[AvatarUploader, User, :avatar]" + +# Attachments +gitlab-rake "gitlab:uploads:migrate[AttachmentUploader, Note, :attachment]" +gitlab-rake "gitlab:uploads:migrate[AttachmentUploader, Appearance, :logo]" +gitlab-rake "gitlab:uploads:migrate[AttachmentUploader, Appearance, :header_logo]" + +# Favicon +gitlab-rake "gitlab:uploads:migrate[FaviconUploader, Appearance, :favicon]" + +# Markdown +gitlab-rake "gitlab:uploads:migrate[FileUploader, Project]" +gitlab-rake "gitlab:uploads:migrate[PersonalFileUploader, Snippet]" +gitlab-rake "gitlab:uploads:migrate[NamespaceFileUploader, Snippet]" +gitlab-rake "gitlab:uploads:migrate[FileUploader, MergeRequest]" + +# Design Management design thumbnails +gitlab-rake "gitlab:uploads:migrate[DesignManagement::DesignV432x230Uploader, DesignManagement::Action, :image_v432x230]" +``` + +**源安装** + +**注意:**为每个任务使用`RAILS_ENV=production` . + +``` +# sudo -u git -H bundle exec rake gitlab:uploads:migrate + +# Avatars +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AvatarUploader, Project, :avatar]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AvatarUploader, Group, :avatar]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AvatarUploader, User, :avatar]" + +# Attachments +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AttachmentUploader, Note, :attachment]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AttachmentUploader, Appearance, :logo]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AttachmentUploader, Appearance, :header_logo]" + +# Favicon +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[FaviconUploader, Appearance, :favicon]" + +# Markdown +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[FileUploader, Project]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[PersonalFileUploader, Snippet]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[NamespaceFileUploader, Snippet]" +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[FileUploader, MergeRequest]" + +# Design Management design thumbnails +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[DesignManagement::DesignV432x230Uploader, DesignManagement::Action]" +``` + +## Migrate to local storage[](#migrate-to-local-storage "Permalink") + +如果出于任何原因需要禁用[对象存储](../../object_storage.html) ,则必须首先将数据从对象存储中迁移出来,然后再迁移回本地存储中. + +**Warning:** **需要延长停机时间** so no new files are created in object storage during the migration. A configuration setting will be added soon to allow migrating from object storage to local files with only a brief moment of downtime for configuration changes. To follow progress, see the [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/30979). + +### All-in-one Rake task[](#all-in-one-rake-task-1 "Permalink") + +GitLab 提供了一个包装 Rake 任务,可将所有上载的文件(例如,头像,徽标,附件和网站图标)迁移到本地存储中. 包装器任务调用各个 Rake 任务来逐一迁移属于这些类别的文件. + +有关这些 Rake 任务的详细信息,请参阅" [个人 Rake 任务"](#individual-rake-tasks) ,请记住,在这种情况下,任务名称为`gitlab:uploads:migrate_to_local` . + +要将上传从对象存储迁移到本地存储: + +1. 同时禁用`direct_upload`和`background_upload`下`uploads`的设置`gitlab.rb` . +2. 运行 Rake 任务: + + **全部安装** + + ``` + gitlab-rake "gitlab:uploads:migrate_to_local:all" + ``` + + **源安装** + + ``` + sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:migrate_to_local:all + ``` + +运行 Rake 任务后,您可以通过撤消[配置对象存储](../../uploads.html#using-object-storage-core-only)的说明中所述的更改来禁用[对象存储](../../uploads.html#using-object-storage-core-only) . \ No newline at end of file diff --git a/docs/525.md b/docs/525.md new file mode 100644 index 0000000000000000000000000000000000000000..d02172184da6fbfc3a239aead033f427ba92f762 --- /dev/null +++ b/docs/525.md @@ -0,0 +1,71 @@ +# Uploads sanitize Rake tasks + +> 原文:[https://docs.gitlab.com/ee/administration/raketasks/uploads/sanitize.html](https://docs.gitlab.com/ee/administration/raketasks/uploads/sanitize.html) + +* [Requirements](#requirements) +* [Remove EXIF data from existing uploads](#remove-exif-data-from-existing-uploads) + +# Uploads sanitize Rake tasks[](#uploads-sanitize-rake-tasks-core-only "Permalink") + +从 GitLab 11.9 开始,EXIF 数据会自动从 JPG 或 TIFF 图像上传中删除. + +EXIF 数据可能包含敏感信息(例如 GPS 位置),因此您可以从上传到 GitLab 早期版本的现有图像中删除 EXIF 数据. + +## Requirements[](#requirements "Permalink") + +要运行此 Rake 任务,需要在系统上安装`exiftool` . 如果安装了 GitLab: + +* 使用 Omnibus 软件包,您已经准备就绪. +* 从源代码中,确保已安装`exiftool` : + + ``` + # Debian/Ubuntu + sudo apt-get install libimage-exiftool-perl + + # RHEL/CentOS + sudo yum install perl-Image-ExifTool + ``` + +## Remove EXIF data from existing uploads[](#remove-exif-data-from-existing-uploads "Permalink") + +要从现有的上载中删除 EXIF 数据,请运行以下命令: + +``` +sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:sanitize:remove_exif +``` + +默认情况下,此命令以"空运行"模式运行,并且不会删除 EXIF 数据. 它可用于检查是否应清理图像(以及多少). + +Rake 任务接受以下参数. + +| Parameter | Type | Description | +| --- | --- | --- | +| `start_id` | integer | 仅处理 ID 相同或更大的上载 | +| `stop_id` | integer | 仅处理 ID 等于或小于 ID 的上传 | +| `dry_run` | boolean | 不要删除 EXIF 数据,仅检查是否存在 EXIF 数据. 默认为`true` | +| `sleep_time` | float | 处理每个图像后暂停几秒钟. 默认为 0.3 秒 | +| `uploader` | string | 仅对给定上传者的上传运行清理: `FileUploader` , `PersonalFileUploader`或`NamespaceFileUploader` | +| `since` | date | 仅对早于给定日期的上传文件进行清理. 例如`2019-05-01` | + +如果上传的文件过多,则可以通过以下方法加快清理速度: + +* 将`sleep_time`设置为较低的值. +* 并行运行多个 Rake 任务,每个任务都有单独的上传 ID 范围(通过设置`start_id`和`stop_id` ). + +要从所有上传中删除 EXIF 数据,请使用: + +``` +sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:sanitize:remove_exif[,,false,] 2>&1 | tee exif.log +``` + +To remove EXIF data on uploads with an ID between 100 and 5000 and pause for 0.1 second after each file, use: + +``` +sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:sanitize:remove_exif[100,5000,false,0.1] 2>&1 | tee exif.log +``` + +输出将被写入`exif.log`文件,因为它可能很长. + +如果上载的清理失败,则 Rake 任务的输出中将出现一条错误消息. 典型的原因包括文件在存储中丢失或不是有效的映像. + +[报告](https://gitlab.com/gitlab-org/gitlab/-/issues/new)所有问题,并在问题标题中使用前缀" EXIF",以及错误输出和(如果可能)图像. \ No newline at end of file diff --git a/docs/526.md b/docs/526.md new file mode 100644 index 0000000000000000000000000000000000000000..1be56ffc463ba57347a734347f1e27a6818f61aa --- /dev/null +++ b/docs/526.md @@ -0,0 +1,156 @@ +# User management + +> 原文:[https://docs.gitlab.com/ee/raketasks/user_management.html](https://docs.gitlab.com/ee/raketasks/user_management.html) + +* [Add user as a developer to all projects](#add-user-as-a-developer-to-all-projects) +* [Add all users to all projects](#add-all-users-to-all-projects) +* [Add user as a developer to all groups](#add-user-as-a-developer-to-all-groups) +* [Add all users to all groups](#add-all-users-to-all-groups) +* [Control the number of active users](#control-the-number-of-active-users) +* [Disable two-factor authentication for all users](#disable-two-factor-authentication-for-all-users) +* [Rotate two-factor authentication encryption key](#rotate-two-factor-authentication-encryption-key) + +# User management[](#user-management-core-only "Permalink") + +GitLab 提供 Rake 任务用于用户管理. + +## Add user as a developer to all projects[](#add-user-as-a-developer-to-all-projects "Permalink") + +要将用户作为开发人员添加到所有项目中,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:import:user_to_projects[username@domain.tld] + +# installation from source +bundle exec rake gitlab:import:user_to_projects[username@domain.tld] RAILS_ENV=production +``` + +## Add all users to all projects[](#add-all-users-to-all-projects "Permalink") + +要将所有用户添加到所有项目,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:import:all_users_to_all_projects + +# installation from source +bundle exec rake gitlab:import:all_users_to_all_projects RAILS_ENV=production +``` + +**注意:**管理员用户被添加为维护者. + +## Add user as a developer to all groups[](#add-user-as-a-developer-to-all-groups "Permalink") + +要将用户作为开发人员添加到所有组,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:import:user_to_groups[username@domain.tld] + +# installation from source +bundle exec rake gitlab:import:user_to_groups[username@domain.tld] RAILS_ENV=production +``` + +## Add all users to all groups[](#add-all-users-to-all-groups "Permalink") + +要将所有用户添加到所有组,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:import:all_users_to_all_groups + +# installation from source +bundle exec rake gitlab:import:all_users_to_all_groups RAILS_ENV=production +``` + +**注意:**管理员用户被添加为所有者,因此他们可以将其他用户添加到组中. + +## Control the number of active users[](#control-the-number-of-active-users "Permalink") + +启用此设置可以阻止新用户被阻止,直到管理员将其清除为止. 默认为`false` : + +``` +block_auto_created_users: false +``` + +## Disable two-factor authentication for all users[](#disable-two-factor-authentication-for-all-users "Permalink") + +此任务为所有启用了双重身份验证的用户禁用两因素身份验证(2FA). 例如,如果 GitLab 的`config/secrets.yml`文件丢失并且用户无法登录,这将很有用. + +要为所有用户禁用双重身份验证,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:two_factor:disable_for_all_users + +# installation from source +bundle exec rake gitlab:two_factor:disable_for_all_users RAILS_ENV=production +``` + +## Rotate two-factor authentication encryption key[](#rotate-two-factor-authentication-encryption-key "Permalink") + +GitLab 将两因素身份验证(2FA)所需的机密数据存储在加密的数据库列中. 此数据的加密密钥称为`otp_key_base` ,存储在`config/secrets.yml` . + +如果该文件泄漏了,但单个 2FA 机密没有泄漏,则可以使用新的加密密钥重新加密这些机密. 这使您可以更改泄漏的密钥,而不必强制所有用户更改其 2FA 详细信息. + +旋转两因素身份验证加密密钥: + +1. 查找旧密钥. 该文件位于`config/secrets.yml`文件中,但请**确保您正在使用 Production 部分** . 您感兴趣的行将如下所示: + + ``` + production: + otp_key_base: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + ``` + +2. 生成一个新的秘密: + + ``` + # omnibus-gitlab + sudo gitlab-rake secret + + # installation from source + bundle exec rake secret RAILS_ENV=production + ``` + +3. 停止 GitLab 服务器,备份现有的机密文件,然后更新数据库: + + ``` + # omnibus-gitlab + sudo gitlab-ctl stop + sudo cp config/secrets.yml config/secrets.yml.bak + sudo gitlab-rake gitlab:two_factor:rotate_key:apply filename=backup.csv old_key= new_key= + + # installation from source + sudo /etc/init.d/gitlab stop + cp config/secrets.yml config/secrets.yml.bak + bundle exec rake gitlab:two_factor:rotate_key:apply filename=backup.csv old_key= new_key= RAILS_ENV=production + ``` + + 可以从`config/secrets.yml`读取``值( ``是先前生成的). 用户 2FA 机密的**加密**值将被写入指定的`filename` . 如果发生错误,可以使用它进行回滚. + +4. 更改`config/secrets.yml` `otp_key_base`以将`otp_key_base`设置为``并重新启动. 同样,请确保您在**生产**部分中进行操作. + + ``` + # omnibus-gitlab + sudo gitlab-ctl start + + # installation from source + sudo /etc/init.d/gitlab start + ``` + +如果有任何问题(也许为`old_key`使用了错误的值),则可以还原`config/secrets.yml` `old_key`的备份并回滚更改: + +``` +# omnibus-gitlab +sudo gitlab-ctl stop +sudo gitlab-rake gitlab:two_factor:rotate_key:rollback filename=backup.csv +sudo cp config/secrets.yml.bak config/secrets.yml +sudo gitlab-ctl start + +# installation from source +sudo /etc/init.d/gitlab start +bundle exec rake gitlab:two_factor:rotate_key:rollback filename=backup.csv RAILS_ENV=production +cp config/secrets.yml.bak config/secrets.yml +sudo /etc/init.d/gitlab start +``` \ No newline at end of file diff --git a/docs/527.md b/docs/527.md new file mode 100644 index 0000000000000000000000000000000000000000..2a8122f5a3d09ed4b00d7ccd4aad6f5cb450db65 --- /dev/null +++ b/docs/527.md @@ -0,0 +1,88 @@ +# Webhooks administration + +> 原文:[https://docs.gitlab.com/ee/raketasks/web_hooks.html](https://docs.gitlab.com/ee/raketasks/web_hooks.html) + +* [Add a webhook to all projects](#add-a-webhook-to-all-projects) +* [Add a webhook to projects in a namespace](#add-a-webhook-to-projects-in-a-namespace) +* [Remove a webhook from projects](#remove-a-webhook-from-projects) +* [Remove a webhook from projects in a namespace](#remove-a-webhook-from-projects-in-a-namespace) +* [List all webhooks](#list-all-webhooks) +* [List webhooks for projects in a namespace](#list-webhooks-for-projects-in-a-namespace) + +# Webhooks administration[](#webhooks-administration-core-only "Permalink") + +GitLab 提供用于 Webhooks 管理的 Rake 任务. + +[管理员](../security/webhooks.html)可以允许或阻止通过[Webhook](../security/webhooks.html)向[本地网络发出的](../security/webhooks.html)请求. + +## Add a webhook to all projects[](#add-a-webhook-to-all-projects "Permalink") + +要将 webhook 添加到所有项目,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:web_hook:add URL="http://example.com/hook" + +# source installations +bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" RAILS_ENV=production +``` + +## Add a webhook to projects in a namespace[](#add-a-webhook-to-projects-in-a-namespace "Permalink") + +要将 Webhook 添加到特定名称空间中的所有项目,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:web_hook:add URL="http://example.com/hook" NAMESPACE= + +# source installations +bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" NAMESPACE= RAILS_ENV=production +``` + +## Remove a webhook from projects[](#remove-a-webhook-from-projects "Permalink") + +要从所有项目中删除 Webhook,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:web_hook:rm URL="http://example.com/hook" + +# source installations +bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" RAILS_ENV=production +``` + +## Remove a webhook from projects in a namespace[](#remove-a-webhook-from-projects-in-a-namespace "Permalink") + +要从特定名称空间的项目中删除 Webhook,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE= + +# source installations +bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE= RAILS_ENV=production +``` + +## List all webhooks[](#list-all-webhooks "Permalink") + +要列出所有 webhooks,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:web_hook:list + +# source installations +bundle exec rake gitlab:web_hook:list RAILS_ENV=production +``` + +## List webhooks for projects in a namespace[](#list-webhooks-for-projects-in-a-namespace "Permalink") + +要列出指定名称空间中项目的所有 webhook,请运行: + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:web_hook:list NAMESPACE= + +# source installations +bundle exec rake gitlab:web_hook:list NAMESPACE= RAILS_ENV=production +``` \ No newline at end of file diff --git a/docs/528.md b/docs/528.md new file mode 100644 index 0000000000000000000000000000000000000000..ff6ae73b3ccdf24048078e1971bd6e056cff2dd4 --- /dev/null +++ b/docs/528.md @@ -0,0 +1,29 @@ +# X.509 signatures + +> 原文:[https://docs.gitlab.com/ee/raketasks/x509_signatures.html](https://docs.gitlab.com/ee/raketasks/x509_signatures.html) + +* [Update all X.509 signatures](#update-all-x509-signatures) + +# X.509 signatures[](#x509-signatures-core-only "Permalink") + +在 GitLab 12.10 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/122159) . + +[使用 X.509](../user/project/repository/x509_signed_commits/index.html)对[提交进行签名时](../user/project/repository/x509_signed_commits/index.html) ,信任锚可能会更改,并且必须更新数据库中存储的签名. + +## Update all X.509 signatures[](#update-all-x509-signatures "Permalink") + +此任务遍历所有 X.509 签名的提交,并根据当前证书存储更新其验证. + +要更新所有 X.509 签名,请运行: + +**所有安装:** + +``` +sudo gitlab-rake gitlab:x509:update_signatures +``` + +**源安装:** + +``` +sudo -u git -H bundle exec rake gitlab:x509:update_signatures RAILS_ENV=production +``` \ No newline at end of file diff --git a/docs/529.md b/docs/529.md new file mode 100644 index 0000000000000000000000000000000000000000..6d3c3f078f58520beadee5d8fca9585e69d5c5d5 --- /dev/null +++ b/docs/529.md @@ -0,0 +1,161 @@ +# Server hooks + +> 原文:[https://docs.gitlab.com/ee/administration/server_hooks.html](https://docs.gitlab.com/ee/administration/server_hooks.html) + +* [Create a server hook for a repository](#create-a-server-hook-for-a-repository) +* [Create a global server hook for all repositories](#create-a-global-server-hook-for-all-repositories) +* [Chained hooks](#chained-hooks) +* [Environment Variables](#environment-variables) +* [Transition to Go](#transition-to-go) +* [Custom error messages](#custom-error-messages) + * [Example custom error message](#example-custom-error-message) + +# Server hooks[](#server-hooks-core-only "Permalink") + +在 GitLab 12.8 中[引入,](https://gitlab.com/gitlab-org/gitlab/-/issues/196051)以取代"自定义挂钩". + +Git 支持在不同动作上执行的钩子. 这些挂钩在服务器上运行,可用于执行特定的提交策略或基于存储库的状态执行其他任务. + +Git 支持以下钩子: + +* `pre-receive` +* `post-receive` +* `update` + +有关每种钩子类型的更多信息,请参见[Git 文档](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#_server_side_hooks) . + +服务器端 Git 挂钩可以配置为: + +* [A single repository](#create-a-server-hook-for-a-repository). +* [All repositories](#create-a-global-server-hook-for-all-repositories). + +Note the following about server hooks: + +* 必须在 GitLab 服务器的文件系统上配置服务器挂钩. 只有 GitLab 服务器管理员才能完成这些任务. 如果您没有文件系统访问权限,请参见以下替代方法: + * [Webhooks](../user/project/integrations/webhooks.html) . + * [亚搏体育 app CI / CD](../ci/README.html) . + * [推送规则](../push_rules/push_rules.html) ,用于用户可配置的 Git 挂钩界面. +* 服务器挂钩不会复制到[Geo](geo/replication/index.html)辅助节点. + +## Create a server hook for a repository[](#create-a-server-hook-for-a-repository "Permalink") + +如果您不使用[哈希存储](repository_storage_types.html#hashed-storage) ,则项目的存储库目录可能与以下说明不完全匹配. 在这种情况下: + +* 对于从源进行的安装,路径通常是`/home/git/repositories//.git` . +* 对于 Omnibus GitLab 安装,路径通常为`/var/opt/gitlab/git-data/repositories//.git` . + +请按照以下步骤为存储库设置服务器端挂钩: + +1. 导航到" **管理"区域>"项目"** ,然后单击要向其添加服务器挂钩的项目. +2. 在出现的页面上找到**Gitaly 相对路径** . 这是必须实现服务器挂钩的地方. 有关解释相对路径的信息,请参阅[翻译哈希存储路径](repository_storage_types.html#translating-hashed-storage-paths) . +3. 在文件系统上,在此位置创建一个名为`custom_hooks`的新目录. +4. 在新的`custom_hooks`目录中,创建一个名称与钩子类型匹配的文件. 例如,对于预接收钩子,文件名应该是`pre-receive` ,没有扩展名. +5. 使挂钩文件可执行,并确保它由 Git 用户拥有. +6. 编写代码以使服务器挂钩功能按预期方式运行. 挂钩可以使用任何语言. 确保顶部的[" shebang"](https://en.wikipedia.org/wiki/Shebang_(Unix))正确反映语言类型. 例如,如果脚本在 Ruby 中,则 shebang 可能是`#!/usr/bin/env ruby` . + +假设正确执行了挂钩代码,则将适当地执行挂钩代码. + +## Create a global server hook for all repositories[](#create-a-global-server-hook-for-all-repositories "Permalink") + +要创建适用于您实例中所有存储库的 Git 挂钩,请设置一个全局服务器挂钩. 默认的全局服务器挂钩目录位于 GitLab Shell 目录中. 在那里添加的任何钩子都适用于所有存储库. + +默认目录: + +* 对于从源代码进行的安装,通常是`/home/git/gitlab-shell/hooks` . +* 对于 Omnibus GitLab,安装通常是`/opt/gitlab/embedded/service/gitlab-shell/hooks` . + +要将其他目录用于全局服务器挂钩, `custom_hooks_dir`在 Gitaly 配置中设置`custom_hooks_dir` : + +* 对于 Omnibus 安装,此设置在`gitlab.rb` . +* 对于源代码安装,配置位置取决于 GitLab 版本. 对于: + * GitLab 13.0 及更早版本,在`gitlab-shell/config.yml` . + * GitLab 13.1 及更高版本,在`[hooks]`部分的`gitaly/config.toml`进行设置. + +**注意:** `gitlab-shell/config.yml`的`custom_hooks_dir`值在 GitLab 13.1 和更高版本中仍然被接受,如果`gitaly/config.toml`的值是空白或不存在. + +请按照以下步骤为所有存储库设置全局服务器挂钩: + +1. 在 GitLab 服务器上,导航到配置的全局服务器挂钩目录. +2. 在此位置创建一个新目录. 根据挂钩的类型,它可以是`pre-receive.d` , `post-receive.d`或`update.d`目录. +3. 在这个新目录中,添加您的钩子. 挂钩可以使用任何语言. 确保顶部的[" shebang"](https://en.wikipedia.org/wiki/Shebang_(Unix))正确反映语言类型. 例如,如果脚本在 Ruby 中,则 shebang 可能是`#!/usr/bin/env ruby` . +4. 使挂钩文件可执行,并确保它由 Git 用户拥有. + +现在,测试挂钩以检查其是否正常运行. + +## Chained hooks[](#chained-hooks "Permalink") + +在 GitLab Shell 4.1.0 和 GitLab 8.15 中[引入](https://gitlab.com/gitlab-org/gitlab-shell/-/merge_requests/93) . + +可以按链执行[每个项目](#create-a-server-hook-for-a-repository)或[全局](#create-a-global-server-hook-for-all-repositories)设置的服务器挂钩. + +搜索服务器挂钩并按以下优先级顺序执行: + +* 内置的 GitLab 服务器挂钩. 这些不是用户可定制的. +* `.git/custom_hooks/` :每个项目的挂钩. 保留它是为了向后兼容. +* `.git/custom_hooks/.d/*` :每个项目挂钩的位置. +* `/.d/*` :除编辑器备份文件之外的所有可执行全局挂钩文件的位置. + +在目录中,服务器挂钩: + +* 按字母顺序执行. +* 当钩子以非零值退出时,停止执行. + +Note: + +* `.d`必须为`pre-receive.d` , `post-receive.d`或`update.d`才能正常工作. 其他任何名称都将被忽略. +* `.d`目录中的文件必须是可执行文件,并且与备份文件模式( `*~` )不匹配. +* 对于`.git` ,你需要[翻译](repository_storage_types.html#translating-hashed-storage-paths)你的项目名称为散列存储格式 GitLab 用途. + +## Environment Variables[](#environment-variables "Permalink") + +以下环境变量集可用于服务器挂钩. + +| 环境变量 | Description | +| --- | --- | +| `GL_ID` | 启动推送的用户的 GitLab 标识符. 例如, `user-2234` | +| `GL_PROJECT_PATH` | (GitLab 13.2 和更高版本)GitLab 项目路径 | +| `GL_PROTOCOL` | (GitLab 13.2 和更高版本)与 push 一起使用的协议 | +| `GL_REPOSITORY` | `project-` ,其中`id`是项目的 ID | +| `GL_USERNAME` | 启动推送的用户的 GitLab 用户名 | + +接收前和接收后服务器挂钩也可以访问以下 Git 环境变量. + +| 环境变量 | Description | +| --- | --- | +| `GIT_ALTERNATE_OBJECT_DIRECTORIES` | 隔离环境中的备用对象目录. 请参阅[Git `receive-pack`文档](https://git-scm.com/docs/git-receive-pack#_quarantine_environment) . | +| `GIT_OBJECT_DIRECTORY` | GitLab project path in the quarantine environment. See [Git `receive-pack` documentation](https://git-scm.com/docs/git-receive-pack#_quarantine_environment). | +| `GIT_PUSH_OPTION_COUNT` | 推送选项的数量. 请参阅[Git `pre-receive`文档](https://git-scm.com/docs/githooks#pre-receive) . | +| `GIT_PUSH_OPTION_` | `i`从`0`到`GIT_PUSH_OPTION_COUNT - 1`的推送选项的值. 请参阅[Git `pre-receive`文档](https://git-scm.com/docs/githooks#pre-receive) . | + +**注意:**虽然其他环境变量可以传递给服务器挂钩,但是您的应用程序不应依赖它们,因为它们可以更改. + +## Transition to Go[](#transition-to-go "Permalink") + +在 GitLab 13.2 中使用功能标记引入. + +以下服务器挂钩已在 Go 中重新实现: + +* `pre-receive` ,默认情况下使用 Go 实现. 要改用 Ruby 实现,请[禁用](../operations/feature_flags.html#enable-or-disable-feature-flag-strategies) `:gitaly_go_preceive_hook`功能标记. +* `update` ,默认使用 Go 实现. 要改用 Ruby 实现,请[禁用](../operations/feature_flags.html#enable-or-disable-feature-flag-strategies) `:gitaly_go_update_hook`功能标志. +* `post-receive` ,但是默认情况下使用 Ruby 实现. 要改用 Go 实现,请[启用](../operations/feature_flags.html#enable-or-disable-feature-flag-strategies) `:gitaly_go_postreceive_hook`功能标志. + +## Custom error messages[](#custom-error-messages "Permalink") + +在 GitLab 8.10 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5073) . + +要在拒绝提交或在 Git 挂钩期间发生错误时在 GitLab 的 UI 中显示自定义错误消息,您的脚本应: + +* 将自定义错误消息发送到脚本的`stdout`或`stderr` . +* 给每条消息加上`GL-HOOK-ERR:`前缀,前缀前没有字符. + +### Example custom error message[](#example-custom-error-message "Permalink") + +用 Bash 编写的该钩子脚本在 GitLab 的 UI 中生成以下消息: + +``` +#!/bin/sh +echo "GL-HOOK-ERR: My custom error message."; +exit 1 +``` + +[![Custom message from custom Git hook](img/4d9fbb6b23cf91f72dd201cf3a52f475.png)](img/custom_hooks_error_msg.png) \ No newline at end of file diff --git a/docs/530.md b/docs/530.md new file mode 100644 index 0000000000000000000000000000000000000000..367c7d4a695611a8d3c42d8a801a684bdf88e91b --- /dev/null +++ b/docs/530.md @@ -0,0 +1,203 @@ +# Static objects external storage + +> 原文:[https://docs.gitlab.com/ee/administration/static_objects_external_storage.html](https://docs.gitlab.com/ee/administration/static_objects_external_storage.html) + +* [Configuring](#configuring) +* [Serving private static objects](#serving-private-static-objects) +* [Requests flow example](#requests-flow-example) +* [Set up external storage](#set-up-external-storage) + +# Static objects external storage[](#static-objects-external-storage "Permalink") + +在 GitLab 12.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31025) . + +可以将 GitLab 配置为从外部存储(例如内容交付网络(CDN))为存储库静态对象(例如,存档或原始 Blob)提供服务. + +## Configuring[](#configuring "Permalink") + +要为静态对象配置外部存储,请执行以下操作: + +1. 导航到" **管理区域">"设置">"存储库"** . +2. 展开" **存储库静态对象"**部分. +3. 输入基本 URL 和任意令牌. [设置外部存储时](#set-up-external-storage) ,您将使用一个脚本,将这些值用作`ORIGIN_HOSTNAME`和`STORAGE_TOKEN` . + +需要使用令牌来区分来自外部存储的请求,因此用户无需绕过外部存储就可以直接前往应用程序. 令牌应在来自外部存储的请求中的`X-Gitlab-External-Storage-Token`标头中设置. + +## Serving private static objects[](#serving-private-static-objects "Permalink") + +GitLab 将为属于私有项目的静态对象 URL 附加一个用户特定的令牌,因此可以代表用户对外部存储进行身份验证. 当处理来自外部存储的请求时,GitLab 将在`token`查询参数或`X-Gitlab-Static-Object-Token`标头中查找`X-Gitlab-Static-Object-Token`以检查用户访问所请求对象的能力. + +## Requests flow example[](#requests-flow-example "Permalink") + +以下示例显示了用户,GitLab 和 CDN 之间的一系列请求和响应: + +sequenceDiagram User->> GitLab:GET /project/-/archive/master.zip GitLab->>用户:302 找到有关 User,GitLab 的注释:位置:https://cdn.com/project/-/archive/master. zip?token =安全用户令牌用户->> CDN:GET /project/-/archive/master.zip?token=安全用户令牌替代对象不在缓存 CDN->> GitLab:GET / project /- /archive/master.zip 关于 CDN,GitLab 的说明:X-Gitlab-External-Storage-Token:secure-cdn-token +X-Gitlab-Static-Object-Token:安全用户令牌 GitLab->> CDN:200 OK CDN->>用户:master.zip 其他对象在缓存 CDN->> GitLab:GET / project /-/ a​​rchive / master.zip 关于 CDN,GitLab 的说明:X-Gitlab-External-Storage-Token:secure-cdn-token +X-Gitlab-Static-Object-Token:安全用户令牌 +如果不匹配:etag 值 GitLab->> CDN:304 未修改 CDN->>用户:master.zip 结束 + +## Set up external storage[](#set-up-external-storage "Permalink") + +尽管此过程使用[CloudFlare Workers](https://workers.cloudflare.com)进行外部存储,但其他 CDN 或功能即服务(FaaS)系统应使用相同的原理工作. + +1. 如果还没有,请选择一个 CloudFlare Worker 域. +2. 在以下脚本中,为前两个常量设置以下值: + + * `ORIGIN_HOSTNAME` :GitLab 安装的主机名. + * `STORAGE_TOKEN` :任何任意的安全令牌(例如,您可以通过在 UNIX 计算机上运行`pwgen -cn1 64`来获得一个). 按照[配置](#configuring)部分中的说明将此令牌保存到管理面板. + + ``` + const ORIGIN_HOSTNAME = 'gitlab.installation.com' // FIXME: SET CORRECT VALUE + const STORAGE_TOKEN = 'very-secure-token' // FIXME: SET CORRECT VALUE + const CACHE_PRIVATE_OBJECTS = false + + const CORS_HEADERS = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS', + 'Access-Control-Allow-Headers': 'X-Csrf-Token, X-Requested-With', + } + + self.addEventListener('fetch', event => event.respondWith(handle(event))) + + async function handle(event) { + try { + let response = await verifyAndHandle(event); + + // responses returned from cache are immutable, so we recreate them + // to set CORS headers + response = new Response(response.body, response) + response.headers.set('Access-Control-Allow-Origin', '*') + + return response + } catch (e) { + return new Response('An error occurred!', {status: e.statusCode || 500}) + } + } + + async function verifyAndHandle(event) { + if (!validRequest(event.request)) { + return new Response(null, {status: 400}) + } + + if (event.request.method === 'OPTIONS') { + return handleOptions(event.request) + } + + return handleRequest(event) + } + + function handleOptions(request) { + // Make sure the necessary headers are present + // for this to be a valid pre-flight request + if ( + request.headers.get('Origin') !== null && + request.headers.get('Access-Control-Request-Method') !== null && + request.headers.get('Access-Control-Request-Headers') !== null + ) { + // Handle CORS pre-flight request + return new Response(null, { + headers: CORS_HEADERS, + }) + } else { + // Handle standard OPTIONS request + return new Response(null, { + headers: { + Allow: 'GET, HEAD, OPTIONS', + }, + }) + } + } + + async function handleRequest(event) { + let cache = caches.default + let url = new URL(event.request.url) + let static_object_token = url.searchParams.get('token') + let headers = new Headers(event.request.headers) + + url.host = ORIGIN_HOSTNAME + url = normalizeQuery(url) + + headers.set('X-Gitlab-External-Storage-Token', STORAGE_TOKEN) + if (static_object_token !== null) { + headers.set('X-Gitlab-Static-Object-Token', static_object_token) + } + + let request = new Request(url, { headers: headers }) + let cached_response = await cache.match(request) + let is_conditional_header_set = headers.has('If-None-Match') + + if (cached_response) { + return cached_response + } + + // We don't want to override If-None-Match that is set on the original request + if (cached_response && !is_conditional_header_set) { + headers.set('If-None-Match', cached_response.headers.get('ETag')) + } + + let response = await fetch(request, { + headers: headers, + redirect: 'manual' + }) + + if (response.status == 304) { + if (is_conditional_header_set) { + return response + } else { + return cached_response + } + } else if (response.ok) { + response = new Response(response.body, response) + + // cache.put will never cache any response with a Set-Cookie header + response.headers.delete('Set-Cookie') + + if (CACHE_PRIVATE_OBJECTS) { + response.headers.delete('Cache-Control') + } + + event.waitUntil(cache.put(request, response.clone())) + } + + return response + } + + function normalizeQuery(url) { + let searchParams = url.searchParams + url = new URL(url.toString().split('?')[0]) + + if (url.pathname.includes('/raw/')) { + let inline = searchParams.get('inline') + + if (inline == 'false' || inline == 'true') { + url.searchParams.set('inline', inline) + } + } else if (url.pathname.includes('/-/archive/')) { + let append_sha = searchParams.get('append_sha') + let path = searchParams.get('path') + + if (append_sha == 'false' || append_sha == 'true') { + url.searchParams.set('append_sha', append_sha) + } + if (path) { + url.searchParams.set('path', path) + } + } + + return url + } + + function validRequest(request) { + let url = new URL(request.url) + let path = url.pathname + + if (/^(.+)(\/raw\/|\/-\/archive\/)/.test(path)) { + return true + } + + return false + } + ``` + +3. 使用此脚本创建一个新的工作程序. +4. 复制`ORIGIN_HOSTNAME`和`STORAGE_TOKEN`值. 使用这些值为[静态对象配置外部存储](#configuring) . \ No newline at end of file diff --git a/docs/531.md b/docs/531.md new file mode 100644 index 0000000000000000000000000000000000000000..730eaede8aec3913a2334f9701c53359130586e8 --- /dev/null +++ b/docs/531.md @@ -0,0 +1,225 @@ +# Updating GitLab + +> 原文:[https://docs.gitlab.com/ee/update/README.html](https://docs.gitlab.com/ee/update/README.html) + +* [Omnibus Packages](#omnibus-packages) +* [Installation from source](#installation-from-source) +* [Installation using Docker](#installation-using-docker) +* [Upgrading without downtime](#upgrading-without-downtime) + * [Examples](#examples) + * [Steps](#steps) +* [Checking for background migrations before upgrading](#checking-for-background-migrations-before-upgrading) + * [What do I do if my background migrations are stuck?](#what-do-i-do-if-my-background-migrations-are-stuck) +* [Upgrading to a new major version](#upgrading-to-a-new-major-version) +* [Upgrading between editions](#upgrading-between-editions) + * [Community to Enterprise Edition](#community-to-enterprise-edition) + * [Enterprise to Community Edition](#enterprise-to-community-edition) +* [Version specific upgrading instructions](#version-specific-upgrading-instructions) + * [13.2.0](#1320) + * [13.1.0](#1310) + * [12.2.0](#1220) + * [12.0.0](#1200) +* [Miscellaneous](#miscellaneous) + +# Updating GitLab[](#updating-gitlab "Permalink") + +根据安装方法和您的 GitLab 版本,有多个更新指南. + +当前有 3 种官方方法来安装 GitLab: + +* [Omnibus packages](#omnibus-packages) +* [Source installation](#installation-from-source) +* [Docker installation](#installation-using-docker) + +根据您的安装,在下面选择适合您需要的部分. + +## Omnibus Packages[](#omnibus-packages "Permalink") + +* [Omnibus 更新指南](https://docs.gitlab.com/omnibus/update/README.html)包含更新 Omnibus GitLab 软件包所需的步骤. + +## Installation from source[](#installation-from-source "Permalink") + +* [从源代码升级社区版和企业版-从源代码升级社区版和企业版](upgrading_from_source.html)的指南. +* [修补程序版本](patch_versions.html)指南包括修补程序版本(如 6.2.0 至 6.2.1)所需的步骤,并且适用于社区版和企业版. + +过去,我们使用单独的文档来进行升级说明,但是此后我们切换为使用单个文档. 仍然可以在 Git 存储库中找到旧的升级准则: + +* [Old upgrading guidelines for Community Edition](https://gitlab.com/gitlab-org/gitlab-foss/tree/11-8-stable/doc/update) +* [Old upgrading guidelines for Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/tree/11-8-stable-ee/doc/update) + +## Installation using Docker[](#installation-using-docker "Permalink") + +GitLab 提供了针对社区和企业版的官方 Docker 映像. 它们基于 Omnibus 软件包,有关如何更新它们的说明在[单独的文档中](https://docs.gitlab.com/omnibus/docker/README.html) . + +## Upgrading without downtime[](#upgrading-without-downtime "Permalink") + +从 GitLab 9.1.0 开始,可以升级到较新的主要,次要或补丁版本的 GitLab,而无需使 GitLab 实例脱机. 但是,要使其正常工作,必须满足以下要求: + +* 您一次只能升级 1 个次要版本. 所以从 9.1 到 9.2,而不是 9.3. +* 您必须使用[部署后迁移](../development/post_deployment_migrations.html) (包含在下面的零停机时间更新步骤中). +* 您正在使用 PostgreSQL. 从 GitLab 12.1 开始,不支持 MySQL. +* 多节点 GitLab 实例. 随着服务重启,单节点实例可能会经历短暂的中断. + +大多数情况下,如果该修补程序版本不是最新的,则可以从该修补程序版本安全地升级到下一个次要版本. 例如,即使已发布 9.1.2,从 9.1.1 升级到 9.2.0 也应该是安全的. 我们建议您检查当前版本和目标版本之间的所有发行版本,以防它们包含可能需要一次升级 1 个发行版本的任何迁移. + +一些版本可能还包含所谓的"后台迁移". 这些迁移是由 Sidekiq 在后台执行的,通常用于迁移数据. 仅在每月发行版中添加后台迁移. + +某些主要/次要版本可能需要完成一组后台迁移. 为了保证这一点,此版本将在继续升级过程之前处理所有剩余的作业. 虽然这不需要停机(如果满足上述条件),但我们建议用户在升级主要/次要版本之间至少保留 1 周,以完成后台迁移. 通过增加可以处理`background_migration`队列中的作业的 Sidekiq 工作者的数量,可以减少完成这些迁移所需的时间. 要查看此队列的大小, [请在升级之前检查后台迁移](#checking-for-background-migrations-before-upgrading) . + +根据经验,任何小于 10 GB 的数据库都不会花费太多时间进行升级. 每个次要版本最多可能需要一个小时. 但是,较大的数据库可能需要更多时间,但这在很大程度上取决于数据库的大小和正在执行的迁移. + +### Examples[](#examples "Permalink") + +为了帮助解释这一点,让我们看一些示例. + +**示例 1:**您正在使用版本 9.4.2(这是 9.4 的最新修补程序版本)运行大型的 GitLab 安装. 如果满足上述要求,则在发布 GitLab 9.5.0 时,可以安全地将此安装升级到 9.5.0,而无需停机. 您也可以跳过 9.5.0 并在其发布后升级到 9.5.1,但是**不能**直接升级到 9.6.0\. 您*必须*先升级到 9.5.x 版本. + +**范例 2:** You are running a large GitLab installation using version 9.4.2, which is the latest patch release of 9.4\. GitLab 9.5 includes some background migrations, and 10.0 will require these to be completed (processing any remaining jobs for you). Skipping 9.5 is not possible without downtime, and due to the background migrations would require potentially hours of downtime depending on how long it takes for the background migrations to complete. To work around this you will have to upgrade to 9.5.x first, then wait at least a week before upgrading to 10.0. + +**示例 3:**您将 MySQL 用作 GitLab 的数据库. 对新的主要/次要版本的任何升级都将需要停机. 如果发行版包含任何后台迁移,则可能会导致数小时的停机时间,具体取决于数据库的大小. 要解决此问题,您将必须使用 PostgreSQL 并满足上述其他在线升级要求. + +### Steps[](#steps "Permalink") + +[无需停机](https://docs.gitlab.com/omnibus/update/README.html)即可进行[升级的](https://docs.gitlab.com/omnibus/update/README.html)步骤. + +## Checking for background migrations before upgrading[](#checking-for-background-migrations-before-upgrading "Permalink") + +某些主要/次要版本可能需要完成一组后台迁移. 可以通过运行以下命令找到剩余的迁移作业数: + +**对于所有安装** + +如果使用的是 GitLab 12.9 及更高版本,请运行: + +``` +sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.remaining' +``` + +如果使用的是 GitLab 12.8 及更早版本,请使用[Rails 控制台](../administration/troubleshooting/debug.html#starting-a-rails-console-session)运行以下命令: + +``` +puts Sidekiq::Queue.new("background_migration").size +Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size +``` + +* * * + +**对于源安装** + +如果使用的是 GitLab 12.9 及更高版本,请运行: + +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::BackgroundMigration.remaining' +``` + +如果使用的是 GitLab 12.8 及更早版本,请使用[Rails 控制台](../administration/troubleshooting/debug.html#starting-a-rails-console-session)运行以下命令: + +``` +puts Sidekiq::Queue.new("background_migration").size +Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size +``` + +### What do I do if my background migrations are stuck?[](#what-do-i-do-if-my-background-migrations-are-stuck "Permalink") + +**警告:**以下操作可能会破坏您的 GitLab 性能.**注意:**重新执行这些命令是安全的,尤其是当您有 1000 个以上的挂起作业可能会溢出运行时内存时. + +**对于所有安装** + +``` +# Start the rails console +sudo gitlab-rails c + +# Execute the following in the rails console +scheduled_queue = Sidekiq::ScheduledSet.new +pending_job_classes = scheduled_queue.select { |job| job["class"] == "BackgroundMigrationWorker" }.map { |job| job["args"].first }.uniq +pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) } +``` + +**对于源安装** + +``` +# Start the rails console +sudo -u git -H bundle exec rails RAILS_ENV=production + +# Execute the following in the rails console +scheduled_queue = Sidekiq::ScheduledSet.new +pending_job_classes = scheduled_queue.select { |job| job["class"] == "BackgroundMigrationWorker" }.map { |job| job["args"].first }.uniq +pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) } +``` + +## Upgrading to a new major version[](#upgrading-to-a-new-major-version "Permalink") + +主要版本保留用于向后不兼容的更改. 我们建议您首先升级到主要版本中的最新可用次要版本. 请按照[升级建议](../policy/maintenance.html#upgrade-recommendations)确定支持的升级路径. + +升级到新的主要版本之前,您应确保已完成以前版本的所有后台迁移作业. 要查看`background_migration`队列的当前大小, [请在升级之前检查后台迁移](#checking-for-background-migrations-before-upgrading) . + +## Upgrading between editions[](#upgrading-between-editions "Permalink") + +GitLab 有两个版本: [社区版](https://about.gitlab.com/features/#community)是 MIT 许可,以及[企业版](https://about.gitlab.com/features/#enterprise) ,其基于社区版的顶部,包括额外的功能,主要是针对机构拥有超过 100 个用户. + +您可以在下面找到一些指南,以帮助您轻松更改版本. + +### Community to Enterprise Edition[](#community-to-enterprise-edition "Permalink") + +> **注意:**以下指南仅适用于企业版的订户. + +如果您希望将 GitLab 安装从 Community 升级到 Enterprise Edition,请根据安装方法遵循以下指南: + +* [从 CE 到 EE 的源更新指南](upgrading_from_ce_to_ee.html) -步骤与版本升级非常相似:停止服务器,获取代码,更新新功能的配置文件,安装库并进行迁移,更新初始化脚本,启动应用程序并检查其功能状态. +* [Omnibus CE to EE-](https://docs.gitlab.com/omnibus/update/README.html)按照本指南将您的 Omnibus GitLab 社区版更新为企业版. + +### Enterprise to Community Edition[](#enterprise-to-community-edition "Permalink") + +如果您需要将 Enterprise Edition 安装降级回 Community Edition,则可以按照[本指南](../downgrade_ee_to_ce/README.html)进行操作,以使过程尽可能的顺利. + +## Version specific upgrading instructions[](#version-specific-upgrading-instructions "Permalink") + +### 13.2.0[](#1320 "Permalink") + +由于 Rails 的重大更改可能会导致授权问题,因此具有多个 Web 节点的 GitLab 安装将需要先[升级到 13.1,](#1310)然后再升级到 13.2(及更高版本). + +### 13.1.0[](#1310 "Permalink") + +在 13.1.0 中,您必须升级到以下任一版本: + +* 至少是 Git v2.24(以前,最低要求是 Git v2.22). +* 推荐的 Git v2.26. + +否则,由于使用新的`--end-of-options` Git 标志,某些 RPC 中的 Gitaly 服务将导致内部错误. + +此外,在 GitLab 13.1.0 中, [Rails](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33454)的版本[从 6.0.3 升级到 6.0.3.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33454) . Rails 升级包括对 CSRF 令牌生成的更改,此更改不向后兼容-具有新 Rails 版本的 GitLab 服务器将生成 CSRF 令牌,而具有较旧 Rails 版本的 GitLab 服务器无法识别-这可能导致非 GET 请求失败用于[多节点 GitLab 安装](https://docs.gitlab.com/omnibus/update/) . + +因此,如果您正在使用多个 Rails 服务器,并专门从 13.0 升级,则必须先将所有服务器升级到 13.1.0,然后再升级到更高版本: + +1. 确保所有 GitLab Web 节点都在 GitLab 13.1.0 上. +2. (可选)启用`global_csrf_token`功能标记以启用 CSRF 令牌生成的新方法: + + ``` + Feature.enable(:global_csrf_token) + ``` + +3. 只有这样,才能继续升级到更高版本的 GitLab. + +### 12.2.0[](#1220 "Permalink") + +在 12.2.0 中,我们启用了 Rails 的身份验证 cookie 加密. 旧会话将自动升级. + +但是,不支持会话 cookie 降级. 因此,升级到 12.2.0 后,任何降级都将导致所有会话无效,并且用户将注销. + +### 12.0.0[](#1200 "Permalink") + +在 12.0.0 中,我们进行了各种与数据库相关的更改. 这些更改要求用户首先升级到最新的 11.11 修补程序版本. 升级到 11.11.x 之后,用户可以升级到 12.0.x. 否则可能导致未应用数据库迁移,这可能导致应用程序错误. + +还需要先升级到 12.0.x,然后再升级到 12.x 的更高版本. + +示例 1:您当前正在使用 GitLab 11.11.8,它是 11.11.x 的最新补丁程序版本. 您可以照常升级到 12.0.x. + +示例 2:您当前使用的是 GitLab 10.x 版本. 要升级,请先升级到最新的 10.x 版本(10.8.7),然后再升级到最新的 11.x 版本(11.11.8). 升级到 11.11.8 后,您可以安全地升级到 12.0.x. + +有关更多信息,请参见我们的[升级路径文档](../policy/maintenance.html#upgrade-recommendations) . + +## Miscellaneous[](#miscellaneous "Permalink") + +* [MySQL 到 PostgreSQL](mysql_to_postgresql.html)指导您完成从 MySQL 到 PostgreSQL 的数据库迁移. +* [Restoring from backup after a failed upgrade](restore_after_failure.html) +* [使用 Slony 升级 PostgreSQL](upgrading_postgresql_using_slony.html) ,以最少的停机时间升级 PostgreSQL 数据库. \ No newline at end of file diff --git a/docs/532.md b/docs/532.md new file mode 100644 index 0000000000000000000000000000000000000000..37d4ecb906cf253b38605f3b11ef2366badbb553 --- /dev/null +++ b/docs/532.md @@ -0,0 +1,185 @@ +# GitLab release and maintenance policy + +> 原文:[https://docs.gitlab.com/ee/policy/maintenance.html](https://docs.gitlab.com/ee/policy/maintenance.html) + +* [Versioning](#versioning) +* [Upgrade recommendations](#upgrade-recommendations) + * [Upgrading major versions](#upgrading-major-versions) + * [Version 12 onward: Extra step for major upgrades](#version-12-onward-extra-step-for-major-upgrades) + * [Example upgrade paths](#example-upgrade-paths) + * [Upgrades from versions earlier than 8.12](#upgrades-from-versions-earlier-than-812) + * [Multi-step upgrade paths with GitLab all-in-one Linux package repository](#multi-step-upgrade-paths-with-gitlab-all-in-one-linux-package-repository) +* [Patch releases](#patch-releases) + * [Backporting to older releases](#backporting-to-older-releases) + * [Security releases](#security-releases) +* [More information](#more-information) + +# GitLab release and maintenance policy[](#gitlab-release-and-maintenance-policy "Permalink") + +GitLab 拥有严格的政策来管理版本命名,以及主要,次要,补丁和安全发布的发布速度. 新版本在[GitLab 博客](https://about.gitlab.com/releases/categories/releases/)上宣布. + +我们目前的政策是: + +* 在任何给定时间, **仅针对当前稳定版本**进行向后移植错误修复. (请参阅[修补程序版本](#patch-releases) .) +* **除了当前的稳定版本之外,还将**安全修复程序反向移植**到前两个月的版本中** . (请参阅[安全性发布](#security-releases) .) + +在极少数情况下,版本管理者可能会例外,并向后移植到最近两个月以上的版本. 有关更多信息,请参见[向旧版本的移植](#backporting-to-older-releases) . + +## Versioning[](#versioning "Permalink") + +GitLab 在其发行版中使用了[语义版本控制](https://semver.org/) :( `(Major).(Minor).(Patch)` . + +例如,对于 GitLab 版本 12.10.6: + +* `12`代表主要版本. 主要版本是 12.0.0,但通常称为 12.0. +* `10`代表次要版本. 次要版本为 12.10.0,但通常称为 12.10. +* `6`代表补丁号码. + +版本号的任何部分都可以递增为多个数字,例如 13.10.11. + +下表描述了版本类型及其发布节奏: + +| 版本类型 | Description | Cadence | +| --- | --- | --- | +| Major | 对于重大更改,或向公共 API 引入任何向后不兼容的更改时. | 每年. 下一个主要版本是 2021 年 5 月 22 日的 GitLab 14.0.默认情况下,后续主要版本计划于每年 5 月 22 日发布. | +| Minor | 当将新的向后兼容功能引入公共 API 时,将引入次要功能,或者推出一组较小的功能. | 每月 22 日. | +| Patch | 对于向后兼容的错误修复程序,用于修复错误的行为. 请参阅[修补程序版本](#patch-releases) . | 如所须. | + +## Upgrade recommendations[](#upgrade-recommendations "Permalink") + +我们鼓励所有人运行[最新的稳定版,](https://about.gitlab.com/releases/categories/releases/)以确保您可以轻松升级到最安全,功能最丰富的 GitLab 体验. 为确保您可以轻松运行最新的稳定版本,我们正在努力使更新过程简单可靠. + +如果您无法遵循我们的每月发布周期,则需要考虑几种情况. + +在一个主要版本中的补丁版本和次要版本之间跳转是安全的. 例如,安全的是: + +* 升级*次要*版本. 例如: + + * `12.7.5` -> `12.10.5` + * `11.3.4` -> `11.11.1` + * `10.6.6` -> `10.8.3` + * `11.3.4` -> `11.11.8` + * `10.6.6` -> `10.8.7` + * `9.2.3` -> `9.5.5` + * `8.9.4` -> `8.12.3` +* 升级*补丁程序*版本. 例如: + + * `12.0.4` -> `12.0.12` + * `11.11.1` -> `11.11.8` + * `10.6.3` -> `10.6.6` + * `11.11.1` -> `11.11.8` + * `10.6.3` -> `10.6.6` + * `9.5.5` -> `9.5.9` + * `8.9.2` -> `8.9.6` + +**注意:** Omnibus GitLab Linux 软件包中特定于版本的更改可在[Omnibus GitLab 文档中找到](https://docs.gitlab.com/omnibus/update/README.html) .**注意:**有关在本地下载 Omnibus GitLab Linux 软件包以及[手动安装的](https://docs.gitlab.com/omnibus/manual_install.html)说明. + +### Upgrading major versions[](#upgrading-major-versions "Permalink") + +升级*主要*版本需要更多注意. 向后不兼容的更改和迁移保留用于主要版本. 我们不能保证主要版本之间的升级是无缝的. 我们建议在升级到下一个主要版本之前,先升级到主要版本中的最新可用*次要*版本. 这样做将解决所有向后不兼容的更改或弃用,以帮助确保成功升级到下一个主要版本. + +同样重要的是,在升级到新的主要版本之前,请确保所有后台迁移已完全完成. 要查看`background_migration`队列的当前大小, [请在升级前检查后台迁移](../update/README.html#checking-for-background-migrations-before-upgrading) . + +如果您的 GitLab 实例具有与之关联的任何 GitLab Runner,则升级 GitLab Runners 以匹配已升级到的 GitLab 次要版本非常重要. 这是为了确保[与 GitLab 版本兼容](https://docs.gitlab.com/runner/) . + +### Version 12 onward: Extra step for major upgrades[](#version-12-onward-extra-step-for-major-upgrades "Permalink") + +从版本 12 开始,还需要执行其他步骤. 在主要版本升级期间,可能会发生更重要的迁移. + +为确保这些成功: + +1. 在主要版本跳转期间递增到第一个次要版本( `x.0.x` ). +2. 继续升级到较新的版本. + +**例如: `11.5.x` - > `11.11.x` - > `12.0.x` - > `12.10.x` - > `13.0.x`** + +### Example upgrade paths[](#example-upgrade-paths "Permalink") + +Please see the table below for some examples: + +| 目标版本 | 您的版本 | 推荐升级路径 | Note | +| --- | --- | --- | --- | +| `13.2.0` | `11.5.0` | `11.5.0` -> `11.11.8` -> `12.0.12` -> `12.10.6` -> `13.0.0` -> `13.2.0` | 四个中间版本是必需的:最终的`11.11` , `12.0`和`12.10`的版本,再加上`13.0` . | +| `13.0.1` | `11.10.8` | `11.10.5` -> `11.11.8` -> `12.0.12` -> `12.10.6` -> `13.0.1` | 三个中间版本是必需的: `11.11` , `12.0`和`12.10` . | +| `12.10.6` | `11.3.4` | `11.3.4` -> `11.11.8` -> `12.0.12` -> `12.10.6` | 需要两个中间版本: `11.11`和`12.0` | +| `12.9.5` | `10.4.5` | `10.4.5` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.9.5` | 三个中间版本是必需的: `10.8` , `11.11`和`12.0` ,然后`12.9.5` | +| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.2.5` | 四个中间版本是必需的: `9.5` , `10.8` , `11.11` , `12.0` ,然后`12.2` . | +| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7`是版本 8 的最新版本, `9.5.10`是版本 9 的最新版本, `10.8.7`是版本 10 的最新版本. | + +### Upgrades from versions earlier than 8.12[](#upgrades-from-versions-earlier-than-812 "Permalink") + +* `8.11.x`和更早版本:您可能必须先升级到`8.12.0`然后才能升级到`8.17.7` . 这是[在一个问题](https://gitlab.com/gitlab-org/gitlab/-/issues/207259)中[报道的](https://gitlab.com/gitlab-org/gitlab/-/issues/207259) . +* [将 8.0](https://docs.gitlab.com/omnibus/update/README.html)合并到 GitLab 时, [CI 会在 8.0 版之前更改](https://docs.gitlab.com/omnibus/update/README.html) . + +### Multi-step upgrade paths with GitLab all-in-one Linux package repository[](#multi-step-upgrade-paths-with-gitlab-all-in-one-linux-package-repository "Permalink") + +Linux 软件包管理器默认安装用于安装和升级的软件包的最新可用版本. 对于需要多阶段升级路径的旧版 GitLab 版本,直接升级到最新的主要版本可能会出现问题. + +当遵循跨多个版本的升级路径时,对于每次升级,请在软件包管理器的 install 或 upgrade 命令中指定所需的 GitLab 版本号. + +Examples: + +``` +# apt-get (Ubuntu/Debian) +sudo apt-get upgrade gitlab-ee=12.0.12-ee.0 +# yum (RHEL/CentOS 6 and 7) +yum install gitlab-ee-12.0.12-ee.0.el7 +# dnf (RHEL/CentOS 8) +dnf install gitlab-ee-12.0.12-ee.0.el8 +# zypper (SUSE) +zypper install gitlab-ee=12.0.12-ee.0 +``` + +## Patch releases[](#patch-releases "Permalink") + +补丁程序发行版**仅包含**针对当前稳定发行版 GitLab 的**错误修复** . + +制定这两项政策是因为: + +1. GitLab 拥有社区和企业发行版,使测试/发布软件所需的工作量加倍. +2. 向多个版本进行反向移植会产生很高的开发,质量保证和支持成本. +3. 支持并行版本不鼓励逐步升级,随着时间的推移,升级会越来越复杂,并给所有用户带来升级挑战. manbetx 客户端打不开有一个专门的团队,以确保增量升级(和安装)尽可能简单. +4. 在 GitLab 应用程序中创建的更改数量很多,这有助于将复杂性向后移植到较旧的版本. 在某些情况下,向后移植必须经过相同的审核过程,然后才能进行新的更改. +5. 在某些情况下,确保测试能够通过旧版本是一个相当大的挑战,因此非常耗时. + +无法在补丁程序发行版中包含新功能,因为这会破坏[语义版本控制](https://semver.org/) . 对于必须遵守各种内部要求(例如,组织合规性,验证新功能等)的用户,破坏[语义版本控制](https://semver.org/)具有以下后果: + +1. 无法快速升级以利用补丁程序版本中包含的错误修复程序. +2. 无法快速升级以利用补丁程序版本中包含的安全修复程序. +3. 要求包括对稳定的 GitLab 版本以及每个补丁版本的广泛测试. + +如果战略用户需要在正式发布功能之前对其进行测试,我们可以提供创建包含特定功能的候选发布(RC)版本的功能. 仅在极端情况下才需要这样做,并且可以通过在[发布/任务](https://gitlab.com/gitlab-org/release/tasks/-/issues/new?issuable_template=Backporting-request)问题跟踪器中提出问题来请求考虑. 重要的是要注意,发布候选版本还将包含其他功能和更改,因为无法轻松隔离特定功能(如上所述的类似原因). 候选发布版本与部署到 GitLab.com 或可公开访问的任何代码没有什么不同. + +### Backporting to older releases[](#backporting-to-older-releases "Permalink") + +向后移植到多个稳定版本通常是为[安全版本](#security-releases)保留的. 但是,在某些情况下,我们可能需要将*错误修复程序*回移植到多个稳定版本中,具体取决于错误的严重性. + +[当前版本管理者](https://about.gitlab.com/community/release-managers/)将决定是否执行向后移植更改,这与[管理 bug](https://gitlab.com/gitlab-org/gitlab/blob/master/PROCESS.md#managing-bugs)流程中所述类似,基于以下*所有条件* : + +1. 错误的估计[严重性](../development/contributing/issue_workflow.html#severity-labels) :根据当前的严重性定义,对用户的最大影响. +2. 错误的估计[优先级](../development/contributing/issue_workflow.html#priority-labels) :根据上述估计的严重性,立即对所有受影响的用户产生影响. +3. 潜在的数据丢失和/或安全漏洞. +4. 由于用户证明无法升级到当前的稳定版本,因此可能影响一个或多个战略帐户. + +如果满足以上*所有条件* ,则可以为当前的稳定版本和两个先前的每月版本创建反向版本. 在极少数情况下,发行经理可以授予例外,以向后移植到两个以上的先前每月发行中. 例如,如果我们发布`11.2.1`并包含`11.0.0`引入的严重错误的修复程序,则可以将该修复程序`11.1.x`移植到新的`11.0.x`和`11.1.x`补丁程序版本. + +To request backporting to more than one stable release for consideration, raise an issue in the [release/tasks](https://gitlab.com/gitlab-org/release/tasks/-/issues/new?issuable_template=Backporting-request) issue tracker. + +### Security releases[](#security-releases "Permalink") + +安全版本是一种特殊的修补程序版本,除了当前的稳定版本之外,仅包括前两个月版本的安全修补程序和修补程序(请参见下文). + +对于非常严重的安全问题, [有先例](https://about.gitlab.com/releases/2016/05/02/cve-2016-4340-patches/)将安全修复程序向后移植到 GitLab 的每月发布版本. 该决定是根据具体情况做出的. + +## More information[](#more-information "Permalink") + +Check [our release posts](https://about.gitlab.com/releases/categories/releases/). + +每个月,我们都会发布 GitLab 的主要版本或次要版本. 在这些发行文章的末尾,有三个部分可供查找:弃用,删除和有关升级的重要说明. 这些将包括: + +* 升级过程中需要执行的步骤. 例如, [8.12](https://about.gitlab.com/releases/2016/09/22/gitlab-8-12-released/#upgrade-barometer)需要重新创建 Elasticsearch 索引. 任何较旧版本的 GitLab 升级到 8.12 或更高版本都需要此功能. +* 对我们支持的软件版本的更改,例如[在 GitLab 13 中不再支持 IE11](https://about.gitlab.com/releases/2020/03/22/gitlab-12-9-released/#ending-support-for-internet-explorer-11) . + +You should check all the major and minor versions you’re passing over. + +有关发行过程的更多信息,请参见我们的[发行文档](https://gitlab.com/gitlab-org/release/docs) . 您可能还需要阅读我们的《 [负责任的披露政策》](https://about.gitlab.com/security/disclosure/) . \ No newline at end of file diff --git a/docs/533.md b/docs/533.md new file mode 100644 index 0000000000000000000000000000000000000000..8ecb2facede4830194f06813a5ee0326b3af378e --- /dev/null +++ b/docs/533.md @@ -0,0 +1,27 @@ +# Security + +> 原文:[https://docs.gitlab.com/ee/security/README.html](https://docs.gitlab.com/ee/security/README.html) + +* [Securing your GitLab installation](#securing-your-gitlab-installation) + +# Security[](#security "Permalink") + +* [Password storage](password_storage.html) +* [Password length limits](password_length_limits.html) +* [Restrict SSH key technologies and minimum length](ssh_keys_restrictions.html) +* [Rate limits](rate_limits.html) +* [Webhooks and insecure internal web services](webhooks.html) +* [Information exclusivity](information_exclusivity.html) +* [Reset your root password](reset_root_password.html) +* [Unlock a locked user](unlock_user.html) +* [User File Uploads](user_file_uploads.html) +* [How we manage the CRIME vulnerability](crime_vulnerability.html) +* [Enforce Two-factor authentication](two_factor_authentication.html) +* [Send email confirmation on sign-up](user_email_confirmation.html) +* [Security of running jobs](https://docs.gitlab.com/runner/security/) +* [Proxying images](asset_proxy.html) +* [CI/CD environment variables](cicd_environment_variables.html) + +## Securing your GitLab installation[](#securing-your-gitlab-installation "Permalink") + +考虑使用诸如[注册限制](../user/admin_area/settings/sign_up_restrictions.html)和[身份验证选项之](../topics/authentication/)类的访问控制功能来强化您的 GitLab 实例,并最大程度地减少不必要的用户帐户创建风险. \ No newline at end of file diff --git a/docs/534.md b/docs/534.md new file mode 100644 index 0000000000000000000000000000000000000000..33cc73c1db4b4a3fbefd14d81d77900a051f3142 --- /dev/null +++ b/docs/534.md @@ -0,0 +1,13 @@ +# Password Storage + +> 原文:[https://docs.gitlab.com/ee/security/password_storage.html](https://docs.gitlab.com/ee/security/password_storage.html) + +# Password Storage[](#password-storage "Permalink") + +GitLab 以散列格式存储用户密码,以防止密码可见. + +GitLab 使用[Devise](https://github.com/heartcombo/devise)身份验证库,该库处理用户密码的哈希. 使用以下属性创建密码哈希: + +* **散列** : [bcrypt](https://en.wikipedia.org/wiki/Bcrypt)散列函数用于生成所提供密码的散列. 这是一种强大的,行业标准的加密哈希函数. +* **拉伸** :密码哈希值, [拉伸](https://en.wikipedia.org/wiki/Key_stretching)打击蛮力攻击硬化. GitLab 默认使用 10 的拉伸因子. +* **盐析** :一个[加密盐](https://en.wikipedia.org/wiki/Salt_(cryptography))被添加到每个口令以针对预先计算的散列值和字典攻击硬化. 每个密码都会随机生成一个盐,因此不会有两个密码共享一个盐,以进一步提高安全性. \ No newline at end of file diff --git a/docs/535.md b/docs/535.md new file mode 100644 index 0000000000000000000000000000000000000000..b4f17b13efcdb8b89e037bc3c5b46580f4d68190 --- /dev/null +++ b/docs/535.md @@ -0,0 +1,56 @@ +# Custom password length limits + +> 原文:[https://docs.gitlab.com/ee/security/password_length_limits.html](https://docs.gitlab.com/ee/security/password_length_limits.html) + +* [Modify maximum password length using configuration file](#modify-maximum-password-length-using-configuration-file) +* [Modify minimum password length using GitLab UI](#modify-minimum-password-length-using-gitlab-ui) + +# Custom password length limits[](#custom-password-length-limits "Permalink") + +默认情况下,GitLab 支持以下密码: + +* 最小长度为 8. +* 最大长度为 128. + +GitLab 管理员可以修改密码长度: + +* 使用配置文件. +* [从](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20661) GitLab 12.6 使用 GitLab UI. + +## Modify maximum password length using configuration file[](#modify-maximum-password-length-using-configuration-file "Permalink") + +默认情况下,用户密码长度设置为最多 128 个字符. 要从源代码更改安装: + +1. Edit `devise_password_length.rb`: + + ``` + cd /home/git/gitlab + sudo -u git -H cp config/initializers/devise_password_length.rb.example config/initializers/devise_password_length.rb + sudo -u git -H editor config/initializers/devise_password_length.rb + ``` + +2. 更改新的密码长度限制: + + ``` + config.password_length = 12..135 + ``` + + 在此示例中,最小长度为 12 个字符,最大长度为 135 个字符. + +3. [重新启动 GitLab,](../administration/restart_gitlab.html#installations-from-source)以使更改生效. + +**注意:**从 GitLab 12.6 起,此配置文件中设置的最小密码长度将被忽略. 现在必须通过[GitLab UI](#modify-minimum-password-length-using-gitlab-ui)修改最小密码长度. + +## Modify minimum password length using GitLab UI[](#modify-minimum-password-length-using-gitlab-ui "Permalink") + +在 GitLab 12.6 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20661) + +默认情况下,用户密码长度设置为至少 8 个字符. 要使用 GitLab UI 进行更改,请执行以下操作: + +在**管理区域>设置** ( `/admin/application_settings/general` )中,转到**注册限制部分** . + +[Minimum password length settings](../user/admin_area/img/minimum_password_length_settings_v12_6.png) + +将" **最小密码长度"**设置为大于或等于 8 的值,然后单击" **保存更改"**以保存更改. + +**警告:**更改最小或最大限制不会以任何方式影响现有的用户密码. 将不要求现有用户重设密码以遵守新限制. 新的限制限制仅适用于新用户注册以及现有用户执行密码重置时. \ No newline at end of file diff --git a/docs/536.md b/docs/536.md new file mode 100644 index 0000000000000000000000000000000000000000..18ea2fa2ac867f2e1b411b3af63fc97bf1bfead7 --- /dev/null +++ b/docs/536.md @@ -0,0 +1,23 @@ +# Restrict allowed SSH key technologies and minimum length + +> 原文:[https://docs.gitlab.com/ee/security/ssh_keys_restrictions.html](https://docs.gitlab.com/ee/security/ssh_keys_restrictions.html) + +# Restrict allowed SSH key technologies and minimum length[](#restrict-allowed-ssh-key-technologies-and-minimum-length "Permalink") + +`ssh-keygen`允许用户创建低至 768 位的 RSA 密钥,这远低于某些标准组(例如 US NIST)的建议. 一些部署 GitLab 的组织将需要增强最低密钥强度,以满足内部安全策略或法规遵从性. + +同样,某些标准组建议在较旧的 DSA 上使用 RSA,ECDSA 或 ED25519,并且管理员可能需要限制允许的 SSH 密钥算法. + +GitLab 允许您限制允许的 SSH 密钥技术,并指定每种技术的最小密钥长度. + +在**管理区域>设置** ( `/admin/application_settings/general` )中,展开**可见性和访问控制**部分: + +[![SSH keys restriction admin settings](img/f9be0028bdcfdf495f7fd0f148de5214.png)](img/ssh_keys_restrictions_settings.png) + +如果对任何密钥类型施加了限制,则用户将无法上载不符合要求的新 SSH 密钥. 现有的不符合要求的键将被禁用但不会被删除,用户将无法使用它们来拉入或推入代码. + +用户的个人资料的" SSH 密钥"部分中的受限密钥图标将对用户可见: + +[![Restricted SSH key icon](img/0a8b584e09781bad1c374f8badc0a12c.png)](img/ssh_keys_restricted_key_icon.png) + +将鼠标悬停在此图标上会告诉您为什么限制按键. \ No newline at end of file diff --git a/docs/537.md b/docs/537.md new file mode 100644 index 0000000000000000000000000000000000000000..af02299685ba0eaef5fef5d6101879b233b56e76 --- /dev/null +++ b/docs/537.md @@ -0,0 +1,28 @@ +# Rate limits + +> 原文:[https://docs.gitlab.com/ee/security/rate_limits.html](https://docs.gitlab.com/ee/security/rate_limits.html) + +* [Admin Area settings](#admin-area-settings) +* [Rack Attack initializer](#rack-attack-initializer) + +# Rate limits[](#rate-limits "Permalink") + +**注意:**对于 GitLab.com,请参阅[GitLab.com 特定的速率限制](../user/gitlab_com/index.html#gitlabcom-specific-rate-limits) . + +速率限制是用于提高 Web 应用程序的安全性和耐用性的常用技术. + +例如,一个简单的脚本每秒可以发出数千个 Web 请求. 无论是恶意的,冷漠的还是仅是错误的,您的应用程序和基础架构都可能无法应付负载. 有关更多详细信息,请参阅[拒绝服务攻击](https://en.wikipedia.org/wiki/Denial-of-service_attack) . 通过限制来自单个 IP 地址的请求速率,可以缓解大多数情况. + +速率限制可以缓解大多数[暴力攻击](https://en.wikipedia.org/wiki/Brute-force_attack) . + +## Admin Area settings[](#admin-area-settings "Permalink") + +* [Issues rate limits](../user/admin_area/settings/rate_limit_on_issues_creation.html). +* [User and IP rate limits](../user/admin_area/settings/user_and_ip_rate_limits.html). +* [Raw endpoints rate limits](../user/admin_area/settings/rate_limits_on_raw_endpoints.html). +* [Protected paths](../user/admin_area/settings/protected_paths.html). +* [Import/Export rate limits](../user/admin_area/settings/import_export_rate_limits.html). + +## Rack Attack initializer[](#rack-attack-initializer "Permalink") + +这种限制速率的方法很麻烦,但是具有一些优点. 它允许限制特定路径,并且还集成到 Git 和容器注册表请求中. 请参阅[机架攻击初始化程序](rack_attack.html) . \ No newline at end of file diff --git a/docs/538.md b/docs/538.md new file mode 100644 index 0000000000000000000000000000000000000000..12fe3c5fdcaedb661f8b899d048d53c7b42ae476 --- /dev/null +++ b/docs/538.md @@ -0,0 +1,54 @@ +# Webhooks and insecure internal web services + +> 原文:[https://docs.gitlab.com/ee/security/webhooks.html](https://docs.gitlab.com/ee/security/webhooks.html) + +* [Allowlist for local requests](#allowlist-for-local-requests) + +# Webhooks and insecure internal web services[](#webhooks-and-insecure-internal-web-services "Permalink") + +**注意:**在 GitLab.com 上[,](../user/gitlab_com/index.html#maximum-number-of-webhooks)每个项目的[最大](../user/gitlab_com/index.html#maximum-number-of-webhooks) Webhooks [数量](../user/gitlab_com/index.html#maximum-number-of-webhooks)是有限的. + +如果您在 GitLab 服务器上或其本地网络中运行了非 GitLab Web 服务,则可能容易受到 Webhooks 的利用. + +使用[Webhooks](../user/project/integrations/webhooks.html) ,您以及您的项目维护者和所有者可以设置 URL,以便在项目中发生特定更改时触发该 URL. 通常,这些请求将发送到专门为此目的设置的外部 Web 服务,该服务以某种适当的方式处理该请求及其附加数据. + +但是,当 Webhook 设置的 URL 不是指向外部服务而是指向内部服务时,事情变得很麻烦,当触发 Webhook 和发送 POST 请求时,这可能会做完全不希望的事情. + +Webhook 请求由 GitLab 服务器本身发出,并且每个钩子使用一个(可选)秘密令牌进行授权(而不是用户或特定于仓库的令牌). 结果,它们可能比托管 Webhook 的服务器(可能包括 GitLab 服务器或 API 本身,例如`http://localhost:123` )上运行的所有对象具有更广泛的访问权限. 根据所调用的 Webhook,这也可能导致对该 Webhook 服务器的本地网络(例如, `http://192.168.1.12:345` : `http://192.168.1.12:345` : `http://192.168.1.12:345` )内的其他服务器的网络访问,即使这些服务受到其他保护并且无法从外界访问. + +如果 Web 服务不需要身份验证,则可以通过使 GitLab 服务器向诸如`http://localhost:123/some-resource/delete`类的端点发出 POST 请求,来使用 Webhooks 触发破坏性命令. + +为了防止发生这种类型的攻击,从 GitLab 10.6 开始,默认情况下将禁止对当前 GitLab 实例服务器地址和/或专用网络中的所有 Webhook 请求. 这意味着,所有的请求作出`127.0.0.1` , `::1`和`0.0.0.0` ,以及 IPv4 的`10.0.0.0/8` , `172.16.0.0/12` , `192.168.0.0/16`和 IPv6 站点本地( `ffc0::/10` )地址将不被允许. + +通过在**管理区域>设置** ( `/admin/application_settings/network` )内*"出站请求"*部分中启用选项*"允许从 Web 挂钩和服务到本地网络的请求",*可以覆盖此行为: + +[![Outbound requests admin settings](img/95cf4cb85bf824cf0817d4d93d93934d.png)](img/outbound_requests_section_v12_2.png) + +**注意:由于** *系统挂钩*是由管理员设置的,因此默认情况下启用它们来向本地网络发出请求. 但是,可以通过禁用" **允许从系统挂钩向本地网络发送请求"**选项来关闭此功能. + +## Allowlist for local requests[](#allowlist-for-local-requests "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44496) in GitLab 12.2 + +通过将某些域和 IP 地址添加到允许*列表中,*即使不允许本地请求,也可以允许某些域和 IP 地址可供*系统挂钩*和*Web* *挂钩*访问. 导航到**管理区域>设置>网络** ( `/admin/application_settings/network` )并展开**出站请求** : + +[![Outbound local requests allowlist](img/77a2b247e60ad05b022cfd3f3a62c069.png)](img/allowlist_v13_0.png) + +允许的条目可以用分号,逗号或空格(包括换行符)分隔,并且可以采用不同的格式,例如主机名,IP 地址和/或 IP 范围. 支持 IPv6\. 包含 Unicode 字符的主机名应使用 IDNA 编码. + +允许列表最多可容纳 1000 个条目. 每个条目最多可以包含 255 个字符. + +您可以通过在允许列表条目中指定特定端口来允许它. 例如`127.0.0.1:8080`将仅允许连接到`127.0.0.1`上的端口 8080\. 如果未提及任何端口,则允许该 IP /域上的所有端口. IP 范围将允许该范围内所有 IP 上的所有端口. + +Example: + +``` +example.com;gitlab.example.com +127.0.0.1,1:0:0:0:0:0:0:1 +127.0.0.0/8 1:0:0:0:0:0:0:0/124 +[1:0:0:0:0:0:0:1]:8080 +127.0.0.1:8080 +example.com:8080 +``` + +**注意:**当前不支持通配符( `*.example.com` ). \ No newline at end of file diff --git a/docs/539.md b/docs/539.md new file mode 100644 index 0000000000000000000000000000000000000000..a77061294199389396b9beb1388c54dc1dfb5449 --- /dev/null +++ b/docs/539.md @@ -0,0 +1,15 @@ +# Information exclusivity + +> 原文:[https://docs.gitlab.com/ee/security/information_exclusivity.html](https://docs.gitlab.com/ee/security/information_exclusivity.html) + +# Information exclusivity[](#information-exclusivity "Permalink") + +Git 是一个分布式版本控制系统(DVCS). 这意味着使用源代码的每个人都有完整存储库的本地副本. + +在 GitLab 中,每个不是来宾的项目成员(报告者,开发者和维护者)都可以克隆存储库以创建本地副本. 获取本地副本后,用户可以将完整的存储库上传到任何地方,包括上传到他们控制下的另一个项目或另一个服务器上. + +因此,不可能建立阻止访问源代码的用户有意共享源代码的访问控制. + +这是 DVCS 的固有功能. 所有 Git 管理系统都有此限制. + +您可以采取措施防止意外共享和信息破坏. 此限制是为什么只允许某些人[向项目添加用户,](../user/project/members/index.html)以及为什么只有 GitLab 管理员才能[强制推送受保护的分支的原因](../user/project/protected_branches.html) . \ No newline at end of file diff --git a/docs/540.md b/docs/540.md new file mode 100644 index 0000000000000000000000000000000000000000..9f93e2b0664af1bd1aca73c32962e1a6ca0ba967 --- /dev/null +++ b/docs/540.md @@ -0,0 +1,44 @@ +# How to reset your root password + +> 原文:[https://docs.gitlab.com/ee/security/reset_root_password.html](https://docs.gitlab.com/ee/security/reset_root_password.html) + +# How to reset your root password[](#how-to-reset-your-root-password "Permalink") + +要重置您的 root 密码,请首先使用 root 特权登录到服务器. + +使用以下命令启动 Ruby on Rails 控制台: + +``` +gitlab-rails console -e production +``` + +等待控制台加载完毕. + +有多种找到用户的方法. 您可以搜索电子邮件或用户名. + +``` +user = User.where(id: 1).first +``` + +or + +``` +user = User.find_by(email: 'admin@example.com') +``` + +现在,您可以更改密码: + +``` +user.password = 'secret_pass' +user.password_confirmation = 'secret_pass' +``` + +更改 password 和 password_confirmation 以使其正常工作很重要. + +不要忘记保存更改. + +``` +user.save! +``` + +退出控制台,然后尝试使用新密码登录. \ No newline at end of file diff --git a/docs/541.md b/docs/541.md new file mode 100644 index 0000000000000000000000000000000000000000..f1fa18909a4e2f09686eddfa826e78f3533f8270 --- /dev/null +++ b/docs/541.md @@ -0,0 +1,42 @@ +# How to unlock a locked user from the command line + +> 原文:[https://docs.gitlab.com/ee/security/unlock_user.html](https://docs.gitlab.com/ee/security/unlock_user.html) + +# How to unlock a locked user from the command line[](#how-to-unlock-a-locked-user-from-the-command-line "Permalink") + +十次失败的登录尝试后,用户将进入锁定状态. + +要解锁锁定的用户: + +1. SSH 到您的 GitLab 服务器. +2. 启动 Ruby on Rails 控制台: + + ``` + ## For Omnibus GitLab + sudo gitlab-rails console -e production + + ## For installations from source + sudo -u git -H bundle exec rails console -e production + ``` + +3. 查找要解锁的用户. 您可以通过电子邮件或 ID 进行搜索. + + ``` + user = User.find_by(email: 'admin@local.host') + ``` + + or + + ``` + user = User.where(id: 1).first + ``` + +4. 解锁用户: + + ``` + user.unlock_access! + ``` + +5. 使用`Ctrl` + `d`退出控制台 + +用户现在应该可以登录了. \ No newline at end of file diff --git a/docs/542.md b/docs/542.md new file mode 100644 index 0000000000000000000000000000000000000000..d1aa2e3c0a116d4e611dfe37381d5e24a623fc61 --- /dev/null +++ b/docs/542.md @@ -0,0 +1,11 @@ +# User File Uploads + +> 原文:[https://docs.gitlab.com/ee/security/user_file_uploads.html](https://docs.gitlab.com/ee/security/user_file_uploads.html) + +# User File Uploads[](#user-file-uploads "Permalink") + +如果通过 URL 直接访问附加到问题,合并请求或注释中的图像,则无需查看身份验证. 该直接 URL 包含一个随机的 32 个字符的 ID,该 ID 可以防止未经授权的人员猜测图像的 URL,因此,如果图像包含敏感信息,则可以提供一定的保护. + +未启用身份验证,因为通知电子邮件的正文中必须显示图像,这些电子邮件通常是从未经 GitLab 身份验证的电子邮件客户端读取的,例如 Outlook,Apple Mail 或移动设备上的 Mail 应用程序. + +> **注意:**非图像附件确实需要进行身份验证才能查看. \ No newline at end of file diff --git a/docs/543.md b/docs/543.md new file mode 100644 index 0000000000000000000000000000000000000000..e72359c0b4038eeee89667186f358c81f4ca5cbd --- /dev/null +++ b/docs/543.md @@ -0,0 +1,49 @@ +# How we manage the TLS protocol CRIME vulnerability + +> 原文:[https://docs.gitlab.com/ee/security/crime_vulnerability.html](https://docs.gitlab.com/ee/security/crime_vulnerability.html) + +* [Description](#description) +* [Nessus](#nessus) +* [References](#references) + +# How we manage the TLS protocol CRIME vulnerability[](#how-we-manage-the-tls-protocol-crime-vulnerability "Permalink") + +[CRIME](https://en.wikipedia.org/w/index.php?title=CRIME&oldid=692423806)是利用 HTTPS 和 SPDY 协议(也使用数据压缩)通过连接对秘密 Web Cookie 进行安全性攻击的方法. 当用于恢复秘密身份验证 Cookie 的内容时,它允许攻击者在经过身份验证的 Web 会话上执行会话劫持,从而允许发起进一步的攻击. + +## Description[](#description "Permalink") + +TLS 协议 CRIME 漏洞影响使用 HTTPS 进行数据压缩的系统. 如果使用 SSL 压缩(例如 Gzip)或 SPDY(可以选择使用压缩),则系统可能容易受到 CRIME 漏洞的攻击. + +GitLab 支持 Gzip 和[SPDY,](http://nginx0org.icopy.site/en/docs/http/ngx_http_spdy_module.html)并通过在启用 HTTPS 时禁用 Gzip 来缓解 CRIME 漏洞. 文件的来源在这里: + +* [Source installation NGINX file](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/support/nginx/gitlab-ssl) +* [Omnibus installation NGINX file](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/templates/default/nginx-gitlab-http.conf.erb) + +尽管在 Omnibus 安装中启用了 SPDY,但 CRIME 依赖于压缩(" C"),NGINX 的 SPDY 模块中的默认压缩级别为 0(无压缩). + +## Nessus[](#nessus "Permalink") + +Nessus 扫描仪[报告](https://www.tenable.com/plugins/index.php?view=single&id=62565) GitLab 中[可能存在的 CRIME 漏洞](https://www.tenable.com/plugins/index.php?view=single&id=62565) ,类似于以下格式: + +``` +Description + +This remote service has one of two configurations that are known to be required for the CRIME attack: +SSL/TLS compression is enabled. +TLS advertises the SPDY protocol earlier than version 4. + +... + +Output + +The following configuration indicates that the remote service may be vulnerable to the CRIME attack: +SPDY support earlier than version 4 is advertised. +``` + +从上面的报告中,需要特别注意的是,Nessus 仅检查 TLS 是否在版本 4 之前发布了 SPDY 协议.它不执行攻击,也不检查是否启用了压缩. 仅 Nessus 扫描程序无法告知 SPDY 的压缩已禁用并且不受 CRIME 漏洞的影响. + +## References[](#references "Permalink") + +* NGINX [“Module ngx_http_spdy_module”](http://nginx0org.icopy.site/en/docs/http/ngx_http_spdy_module.html) +* Tenable Network Security,Inc. ["传输层安全性(TLS)协议 CRIME 漏洞"](https://www.tenable.com/plugins/index.php?view=single&id=62565) +* Wikipedia 的贡献者, [" CRIME"](https://en.wikipedia.org/wiki/CRIME) Wikipedia,免费的百科全书 \ No newline at end of file diff --git a/docs/544.md b/docs/544.md new file mode 100644 index 0000000000000000000000000000000000000000..313f52acc10ff03d7d81327b23a9430de7930aae --- /dev/null +++ b/docs/544.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/security/two_factor_authentication.html](https://docs.gitlab.com/ee/security/two_factor_authentication.html) \ No newline at end of file diff --git a/docs/545.md b/docs/545.md new file mode 100644 index 0000000000000000000000000000000000000000..0b602c6e6d2adc5b16d190ded27e5f7b25fb1ed5 --- /dev/null +++ b/docs/545.md @@ -0,0 +1,9 @@ +# User email confirmation at sign-up + +> 原文:[https://docs.gitlab.com/ee/security/user_email_confirmation.html](https://docs.gitlab.com/ee/security/user_email_confirmation.html) + +# User email confirmation at sign-up[](#user-email-confirmation-at-sign-up "Permalink") + +可以将 GitLab 配置为在用户注册时要求确认用户的电子邮件地址. 启用此设置后,用户只有在确认电子邮件地址后才能登录. + +在**管理区域>设置** ( `/admin/application_settings/general` )中,转到" **注册限制** "部分**,**然后查找" **在注册时发送确认电子邮件"**选项. \ No newline at end of file diff --git a/docs/546.md b/docs/546.md new file mode 100644 index 0000000000000000000000000000000000000000..3a29dcbfc9833b764ba96585777acc30ecaa7115 --- /dev/null +++ b/docs/546.md @@ -0,0 +1,66 @@ +# Security of running jobs + +> 原文:[https://docs.gitlab.com/runner/security/](https://docs.gitlab.com/runner/security/) + +* [Usage of Shell executor](#usage-of-shell-executor) +* [Usage of Docker executor](#usage-of-docker-executor) +* [Usage of private Docker images with `if-not-present` pull policy](#usage-of-private-docker-images-with-if-not-present-pull-policy) +* [Systems with Docker installed](#systems-with-docker-installed) +* [Usage of SSH executor](#usage-of-ssh-executor) +* [Usage of Parallels executor](#usage-of-parallels-executor) +* [Cloning a runner](#cloning-a-runner) + +# Security of running jobs[](#security-of-running-jobs "Permalink") + +使用 GitLab Runner 时,您应该在运行作业时意识到潜在的安全隐患. + +## Usage of Shell executor[](#usage-of-shell-executor "Permalink") + +**通常,使用`shell`执行程序运行测试是不安全的.** 这些作业在用户权限(GitLab Runner 的权限)下运行,并且可以从此服务器上运行的其他项目中窃取代码. 仅将其用于运行受信任的构建. + +## Usage of Docker executor[](#usage-of-docker-executor "Permalink") + +**在非特权模式下运行时,可以认为 Docker 是安全的.** 为了使这种设置更加安全,建议在 sudo 禁用或`SETUID`和`SETGID`功能已禁用的 Docker 容器中以用户(非 root 用户)身份运行作业. + +另一方面,存在特权模式,该模式允许对主机系统的完全访问权限,安装和卸载卷的权限以及运行嵌套容器. 不建议在特权模式下运行容器. + +可以通过`cap_add` / `cap_drop`设置在非特权模式下配置更精细的权限. + +## Usage of private Docker images with `if-not-present` pull policy[](#usage-of-private-docker-images-with-if-not-present-pull-policy "Permalink") + +使用[高级配置中](../configuration/advanced-configuration.html#using-a-private-container-registry)描述的私有 Docker 映像支持时[:使用私有容器注册表时](../configuration/advanced-configuration.html#using-a-private-container-registry) ,应`always`将其`pull_policy`值. 尤其是你应该使用`always`拉的政策,如果你正在主持一个公共,共享亚军与泊坞窗或 Kubernetes 执行人. + +让我们来看一个将拉策略设置为`if-not-present`的示例: + +1. 用户 A 在`registry.example.com/image/name`具有私有映像. +2. 用户 A 在共享运行器上启动构建:该构建接收注册表凭据,并在注册表中授权后提取映像. +3. 图像存储在共享的 Runner 主机上. +4. 用户 B 无法访问`registry.example.com/image/name`上的私有映像. +5. 用户 B 在与用户 A 相同的共享 Runner 上启动使用此映像的构建:Runner 找到该映像的本地版本并使用它, **即使由于缺少凭据也无法提取该映像** . + +因此,如果托管的 Runner 可以由不同的用户和不同的项目使用(具有私有和公共访问权限的混合级别),则永远不要使用`if-not-present`作为拉策略值,而应使用: + +* `never` -如果您想限制用户使用您预先下载的唯一图像. +* `always` -如果您想让用户可以从任何注册表下载任何图像. + +`if-not-present`拉策略**仅**应用于受信任的构建和用户使用的特定运行器. + +阅读[拉取策略文档](../executors/docker.html#how-pull-policies-work)以获取更多信息. + +## Systems with Docker installed[](#systems-with-docker-installed "Permalink") + +> **注意:**这适用于低于 0.5.0 的安装或已升级到较新版本的安装. + +在安装了 Docker 的 Linux 系统上安装软件包时, `gitlab-runner`将创建一个有权访问`Docker`守护程序的用户. 这使使用`shell` executor 运行的作业能够以完全权限访问`docker` ,并可能允许对服务器的根访问. + +## Usage of SSH executor[](#usage-of-ssh-executor "Permalink") + +由于缺少`StrictHostKeyChecking`选项, **SSH 执行程序容易受到 MITM 攻击(中间人)** . 这将在将来的版本之一中修复. + +## Usage of Parallels executor[](#usage-of-parallels-executor "Permalink") + +**Parallels executor 是最安全的选择,**因为它使用完整的系统虚拟化,并且配置为在隔离虚拟化中运行的 VM 机器和配置为以隔离模式运行的 VM 机器. 它阻止访问所有外围设备和共享文件夹. + +## Cloning a runner[](#cloning-a-runner "Permalink") + +跑步者使用令牌来标识 GitLab 服务器. 如果克隆一个运行程序,则克隆的运行程序可能正在为该令牌选择相同的作业. 这是"窃取"跑步者工作的一种可能的攻击手段. \ No newline at end of file diff --git a/docs/547.md b/docs/547.md new file mode 100644 index 0000000000000000000000000000000000000000..d8efc2908e4c4a12932c4f4a5a58c304c159da7c --- /dev/null +++ b/docs/547.md @@ -0,0 +1,60 @@ +# Proxying assets + +> 原文:[https://docs.gitlab.com/ee/security/asset_proxy.html](https://docs.gitlab.com/ee/security/asset_proxy.html) + +* [Installing Camo server](#installing-camo-server) +* [Using the Camo server](#using-the-camo-server) + +# Proxying assets[](#proxying-assets "Permalink") + +在管理面向公众的 GitLab 实例时,可能存在的安全隐患是通过引用问题,评论等中的图像来窃取用户 IP 地址的能力. + +例如,在问题描述中添加`![Example image](http://example.com/example.png)`将导致从外部服务器加载图像以便显示. 但是,这也允许外部服务器记录用户的 IP 地址. + +减轻这种情况的一种方法是将所有外部映像代理到您控制的服务器. + +可以将 GitLab 配置为在问题,评论等中请求外部图像/视频/音频时使用资产代理服务器.这有助于确保恶意图像在获取时不会暴露用户的 IP 地址. + +当前,我们建议使用[cactus / go-camo,](https://github.com/cactus/go-camo#how-it-works)因为它支持代理视频,音频并且更可配置. + +## Installing Camo server[](#installing-camo-server "Permalink") + +一台 Camo 服务器用作代理. + +要将 Camo 服务器安装为资产代理,请执行以下操作: + +1. 部署`go-camo`服务器. 有用的说明可以在[建立 catus / go-camo 中找到](https://github.com/cactus/go-camo#building) . + +2. 确保您的 GitLab 实例正在运行,并且您已经创建了私有 API 令牌. 使用 API​​,在您的 GitLab 实例上配置资产代理设置. 例如: + + ``` + curl --request "PUT" "https://gitlab.example.com/api/v4/application/settings?\ asset_proxy_enabled=true&\ asset_proxy_url=https://proxy.gitlab.example.com&\ asset_proxy_secret_key=" \ + --header 'PRIVATE-TOKEN: ' + ``` + + 支持以下设置: + + | Attribute | Description | + | --- | --- | + | `asset_proxy_enabled` | 启用资产代理. 如果启用,则要求: `asset_proxy_url` ). | + | `asset_proxy_secret_key` | 与资产代理服务器共享的机密. | + | `asset_proxy_url` | 资产代理服务器的 URL. | + | `asset_proxy_whitelist` | 与这些域匹配的资产将不会被代理. 允许使用通配符. 您的 GitLab 安装网址会自动列入白名单. | + +3. 重新启动服务器,以使更改生效. 每次更改资产代理的任何值时,都需要重新启动服务器. + +## Using the Camo server[](#using-the-camo-server "Permalink") + +一旦 Camo 服务器运行并且启用了 GitLab 设置,任何引用外部源的图像,视频或音频都将被代理到 Camo 服务器. + +例如,以下是 Markdown 中图像的链接: + +``` +![logo](https://about.gitlab.com/images/press/logo/jpg/gitlab-icon-rgb.jpg) +``` + +以下是可能导致源链接的示例: + +``` +http://proxy.gitlab.example.com/f9dd2b40157757eb82afeedbf1290ffb67a3aeeb/68747470733a2f2f61626f75742e6769746c61622e636f6d2f696d616765732f70726573732f6c6f676f2f6a70672f6769746c61622d69636f6e2d7267622e6a7067 +``` \ No newline at end of file diff --git a/docs/548.md b/docs/548.md new file mode 100644 index 0000000000000000000000000000000000000000..b29777aa618bcaec13634db2c5c41964a5b8058a --- /dev/null +++ b/docs/548.md @@ -0,0 +1,11 @@ +# CI/CD Environment Variables + +> 原文:[https://docs.gitlab.com/ee/security/cicd_environment_variables.html](https://docs.gitlab.com/ee/security/cicd_environment_variables.html) + +# CI/CD Environment Variables[](#cicd-environment-variables "Permalink") + +环境变量通过运行程序应用于环境,可以从项目的**"设置">" CI / CD"**页面进行**设置** . + +这些值使用[aes-256-cbc](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard)加密并存储在数据库中. + +只能使用有效的[机密文件](../raketasks/backup_restore.html#when-the-secrets-file-is-lost)解密此数据. \ No newline at end of file diff --git a/docs/549.md b/docs/549.md new file mode 100644 index 0000000000000000000000000000000000000000..60834619044a42a43b5c3637cc8f63ab930eac8d --- /dev/null +++ b/docs/549.md @@ -0,0 +1,204 @@ +# Contributor and Development Docs + +> 原文:[https://docs.gitlab.com/ee/development/README.html](https://docs.gitlab.com/ee/development/README.html) + +* [Get started](#get-started) +* [Processes](#processes) +* [UX and Frontend guides](#ux-and-frontend-guides) +* [Backend guides](#backend-guides) +* [Performance guides](#performance-guides) +* [Database guides](#database-guides) +* [Integration guides](#integration-guides) +* [Testing guides](#testing-guides) +* [Refactoring guides](#refactoring-guides) +* [Documentation guides](#documentation-guides) +* [Internationalization (i18n) guides](#internationalization-i18n-guides) +* [Telemetry guides](#telemetry-guides) +* [Experiment guide](#experiment-guide) +* [Build guides](#build-guides) +* [Compliance](#compliance) +* [Go guides](#go-guides) +* [Shell Scripting guides](#shell-scripting-guides) +* [Domain-specific guides](#domain-specific-guides) +* [Other Development guides](#other-development-guides) +* [Other GitLab Development Kit (GDK) guides](#other-gitlab-development-kit-gdk-guides) + +# Contributor and Development Docs[](#contributor-and-development-docs "Permalink") + +## Get started[](#get-started "Permalink") + +* 使用[GitLab 开发套件(GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/README.md)设置 GitLab 的开发环境 +* [GitLab contributing guide](contributing/index.html) + * [发出工作流](contributing/issue_workflow.html)以获取有关以下方面的更多信息: + * 问题追踪器指南. + * 分流. + * 标签. + * 功能建议. + * 发行权重. + * 回归问题. + * 技术或用户体验债务. + * [合并请求工作流](contributing/merge_request_workflow.html)以获取有关以下方面的更多信息: + * 合并请求准则. + * 捐款接受标准. + * 完成的定义. + * 依赖关系. + * [Style guides](contributing/style_guides.html) + * [Implement design & UI elements](contributing/design.html) +* [GitLab Architecture Overview](architecture.html) +* [耙](rake_tasks.html)开发[任务](rake_tasks.html) + +## Processes[](#processes "Permalink") + +**Must-reads:** + +* [代码审查指南,](code_review.html)用于审查代码和审查代码 +* [数据库审阅指南,](database_review.html)用于审阅与数据库有关的更改和复杂的 SQL 查询,并进行审阅 +* [Secure coding guidelines](secure_coding_guidelines.html) +* [Pipelines for the GitLab project](pipelines.html) + +互补读物: + +* [GitLab core team & GitLab Inc. contribution process](https://gitlab.com/gitlab-org/gitlab/blob/master/PROCESS.md) +* [Security process for developers](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#security-releases-critical-non-critical-as-a-developer) +* [Guidelines for implementing Enterprise Edition features](ee_features.html) +* [Danger bot](dangerbot.html) +* [Generate a changelog entry with `bin/changelog`](changelog.html) +* [在 GitLab.com 上请求访问 Chatops](chatops_on_gitlabcom.html#requesting-access) (适用于 GitLab 团队成员) + +## UX and Frontend guides[](#ux-and-frontend-guides "Permalink") + +* 用于使用现有 CSS 样式和元素构建 GitLab 的[GitLab 设计系统](https://design.gitlab.com/) +* [Frontend guidelines](fe_guide/index.html) +* [Emoji guide](fe_guide/emojis.html) + +## Backend guides[](#backend-guides "Permalink") + +* [GitLab utilities](utilities.html) +* [Issuable-like Rails models](issuable-like-models.html) +* [Logging](logging.html) +* [API 样式指南,](api_styleguide.html)用于贡献 API +* [GraphQL API 样式指南,](api_graphql_styleguide.html)用于为[GraphQL API](../api/graphql/index.html)做出贡献 +* [Sidekiq guidelines](sidekiq_style_guide.html) for working with Sidekiq workers +* [Working with Gitaly](gitaly.html) +* [Manage feature flags](feature_flags/index.html) +* [Licensed feature availability](licensed_feature_availability.html) +* [Dealing with email/mailers](emails.html) +* GitLab 代码库中的[Shell 命令](shell_commands.html) +* [`Gemfile` guidelines](gemfile.html) +* [Pry debugging](pry_debugging.html) +* [Sidekiq debugging](sidekiq_debugging.html) +* [Accessing session data](session.html) +* 要避免的[陷阱](gotchas.html) +* 尽可能[避免使用带有实例变量的模块](module_with_instance_variables.html) +* [How to dump production data to staging](db_dump.html) +* [Working with the GitHub importer](github_importer.html) +* [Import/Export development documentation](import_export.html) +* [Test Import Project](import_project.html) +* [Elasticsearch integration docs](elasticsearch.html) +* [Working with Merge Request diffs](diffs.html) +* [Kubernetes integration guidelines](kubernetes.html) +* [Permissions](permissions.html) +* [Prometheus](prometheus.html) +* [Guidelines for reusing abstractions](reusing_abstractions.html) +* [DeclarativePolicy framework](policies.html) +* [How Git object deduplication works in GitLab](git_object_deduplication.html) +* [Geo development](geo.html) +* [Routing](routing.html) +* [Repository mirroring](repository_mirroring.html) +* [Git LFS](lfs.html) +* [Developing against interacting components or features](interacting_components.html) +* [File uploads](uploads.html) +* [Auto DevOps development guide](auto_devops.html) +* [Mass Inserting Models](mass_insert.html) +* [Value Stream Analytics development guide](value_stream_analytics.html) +* [Issue types vs first-class types](issue_types.html) +* [Application limits](application_limits.html) +* [Redis guidelines](redis.html) +* [Rails initializers](rails_initializers.html) +* [Code comments](code_comments.html) +* [Renaming features](renaming_features.html) +* [Windows Development on GCP](windows.html) +* [Code Intelligence](code_intelligence/index.html) +* [Approval Rules](approval_rules.html) +* [Feature categorization](feature_categorization/index.html) + +## Performance guides[](#performance-guides "Permalink") + +* [仪器](instrumentation.html)用于 Ruby 代码在生产环境中运行 +* 用于编写代码,基准测试和避免某些模式的[性能准则](performance.html) +* [合并请求性能准则,](merge_request_performance_guidelines.html)以确保合并请求不会对 GitLab 性能产生负面影响 +* [分析](profiling.html) URL,使用 Sherlock 评估性能或使用 Bullet 跟踪 N + 1 查询 + +## Database guides[](#database-guides "Permalink") + +See [database guidelines](database/index.html). + +## Integration guides[](#integration-guides "Permalink") + +* [Jira Connect app](integrations/jira_connect.html) +* [Security Scanners](integrations/secure.html) +* [Secure Partner Integration](integrations/secure_partner_integration.html) +* [How to run Jenkins in development environment](integrations/jenkins.html) + +## Testing guides[](#testing-guides "Permalink") + +* [Testing standards and style guidelines](testing_guide/index.html) +* [Frontend testing standards and style guidelines](testing_guide/frontend_testing.html) + +## Refactoring guides[](#refactoring-guides "Permalink") + +* [Refactoring guidelines](refactoring_guide/index.html) + +## Documentation guides[](#documentation-guides "Permalink") + +* [Writing documentation](documentation/index.html) +* [Documentation style guide](documentation/styleguide.html) +* [Markdown](../user/markdown.html) + +## Internationalization (i18n) guides[](#internationalization-i18n-guides "Permalink") + +* [Introduction](i18n/index.html) +* [Externalization](i18n/externalization.html) +* [Translation](i18n/translation.html) + +## Telemetry guides[](#telemetry-guides "Permalink") + +* [Telemetry guide](telemetry/index.html) +* [Usage Ping guide](telemetry/usage_ping.html) +* [Snowplow guide](telemetry/snowplow.html) + +## Experiment guide[](#experiment-guide "Permalink") + +* [Introduction](experiment_guide/index.html) + +## Build guides[](#build-guides "Permalink") + +* [Building a package for testing purposes](build_test_package.html) + +## Compliance[](#compliance "Permalink") + +* [许可](licensing.html)确保许可证合规性 + +## Go guides[](#go-guides "Permalink") + +* [Go Guidelines](go_guide/index.html) + +## Shell Scripting guides[](#shell-scripting-guides "Permalink") + +* [Shell scripting standards and style guidelines](shell_scripting_guide/index.html) + +## Domain-specific guides[](#domain-specific-guides "Permalink") + +* [CI/CD development documentation](cicd/index.html) + +## Other Development guides[](#other-development-guides "Permalink") + +* [Defining relations between files using projections](projections.html) +* [Reference processing](./reference_processing.html) +* [Compatibility with multiple versions of the application running at the same time](multi_version_compatibility.html) + +## Other GitLab Development Kit (GDK) guides[](#other-gitlab-development-kit-gdk-guides "Permalink") + +* [Run full Auto DevOps cycle in a GDK instance](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/auto_devops.md) +* [Using GitLab Runner with the GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/runner.md) +* [Using the Web IDE terminal with the GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/web_ide_terminal_gdk_setup.md) \ No newline at end of file diff --git a/docs/550.md b/docs/550.md new file mode 100644 index 0000000000000000000000000000000000000000..bdb34695b888d9172f61fe2296d663840047aed0 --- /dev/null +++ b/docs/550.md @@ -0,0 +1,169 @@ +# Contribute to GitLab + +> 原文:[https://docs.gitlab.com/ee/development/contributing/](https://docs.gitlab.com/ee/development/contributing/) + +* [Security vulnerability disclosure](#security-vulnerability-disclosure) +* [Code of conduct](#code-of-conduct) +* [Closing policy for issues and merge requests](#closing-policy-for-issues-and-merge-requests) +* [Helping others](#helping-others) +* [How to contribute](#how-to-contribute) + * [GitLab Development Kit](#gitlab-development-kit) + * [Contribution flow](#contribution-flow) + * [Issues workflow](#issues-workflow) + * [Merge requests workflow](#merge-requests-workflow) +* [Style guides](#style-guides) +* [Implement design & UI elements](#implement-design--ui-elements) +* [Contribute documentation](#contribute-documentation) +* [Getting an Enterprise Edition License](#getting-an-enterprise-edition-license) + +# Contribute to GitLab[](#contribute-to-gitlab "Permalink") + +感谢您有兴趣为 GitLab 做贡献. 本指南详细介绍了如何以每个人都容易的方式为 GitLab 做出贡献. + +For a first-time step-by-step guide to the contribution process, see our [Contributing to GitLab](https://about.gitlab.com/community/contribute/) page. + +寻找工作吗? 有关更多信息,请参见[如何贡献](#how-to-contribute)部分. + +GitLab 有两种口味: + +* GitLab 社区版(CE),我们的免费和开源版本. +* GitLab 企业版(EE),这是我们的商业版. + +在本指南中,您将看到对 CE 和 EE 的缩写的引用. + +要获得 GitLab 社区成员资格的概述,包括那些会审核或合并您的贡献的成员,请访问[社区角色页面](community_roles.html) . + +如果您想知道 GitLab [核心团队的](https://about.gitlab.com/community/core-team/)运作方式,请参阅[GitLab 贡献过程](https://gitlab.com/gitlab-org/gitlab/blob/master/PROCESS.md) . + +GitLab Inc 工程师应参考[工程工作流程文档](https://about.gitlab.com/handbook/engineering/workflow/) . + +## Security vulnerability disclosure[](#security-vulnerability-disclosure "Permalink") + +将可疑的安全漏洞[秘密](https://about.gitlab.com/security/disclosure/)报告给`support@gitlab.com` ,另请参阅[GitLab.com 网站上的](https://about.gitlab.com/security/disclosure/) " [披露"部分](https://about.gitlab.com/security/disclosure/) . + +**危险:** **不要**为疑似安全漏洞公开可见的问题. + +## Code of conduct[](#code-of-conduct "Permalink") + +我们希望为每个有志于贡献的人营造一个温馨的环境. 请访问我们的[《行为准则》页面,](https://about.gitlab.com/community/contribute/code-of-conduct/)以了解有关我们对开放友好环境的承诺的更多信息. + +## Closing policy for issues and merge requests[](#closing-policy-for-issues-and-merge-requests "Permalink") + +GitLab 是一个受欢迎的开源项目,处理问题和合并请求的能力有限. 出于对我们志愿者的尊重,不符合本文档所列准则的问题和合并请求可能会被关闭,恕不另行通知. + +以礼貌和尊重的态度对待我们的志愿者,这将大大有助于您解决问题. + +发行和合并请求应使用英语,并包含适合所有年龄段受众的语言. + +如果贡献者不再主动处理提交的合并请求,我们可以: + +* 决定合并请求将由我们的[合并请求指导者之一完成](https://about.gitlab.com/company/team/) . +* 关闭合并请求. + +我们根据更改对我们的产品愿景的重要性来做出此决定. 如果合并请求教练将要完成合并请求,我们指定`~coach will finish`标签. + +当团队成员选择社区贡献时,我们会通过添加一个记入作者的更改日志条目来记入原始作者,并有选择地将原始作者包括在 MR 中的至少一项提交中. + +## Helping others[](#helping-others "Permalink") + +可以的话,请帮助其他 GitLab 用户. 人们用于寻求帮助的方法可以在" [获得帮助"页面](https://about.gitlab.com/get-help/)上找到. + +注册邮件列表,在 StackOverflow 上回答 GitLab 问题,或在 IRC 频道中回复. + +## How to contribute[](#how-to-contribute "Permalink") + +如果您想为 GitLab 做出贡献: + +* [`~Accepting merge requests`标签的问题](issue_workflow.html#label-for-community-contributors)是一个很好的起点. +* 请查阅" [贡献流"](#contribution-flow)部分以了解该过程. + +如果您有任何疑问或需要帮助,请访问" [获得帮助"](https://about.gitlab.com/get-help/)以了解如何与 GitLab 进行通信. 我们有一个[供参与者](https://gitter.im/gitlab/contributors)使用的[Gitter 通道](https://gitter.im/gitlab/contributors) ,但是相对于实时通信,我们更喜欢[异步](https://about.gitlab.com/handbook/communication/#internal-communication)通信. + +感谢您的贡献! + +### GitLab Development Kit[](#gitlab-development-kit "Permalink") + +GitLab 开发套件(GDK)可帮助贡献者使用所有必需的依赖项来运行本地 GitLab 实例. 在提出合并请求之前,它可以用于测试对 GitLab 和相关项目的更改. + +有关更多信息,请参见[`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit)项目. + +### Contribution flow[](#contribution-flow "Permalink") + +对 GitLab 进行贡献的一般流程是: + +1. [创建一个](../../user/project/repository/forking_workflow.html#creating-a-fork) GitLab [的叉子](../../user/project/repository/forking_workflow.html#creating-a-fork) . 在某些情况下,您将需要设置[GitLab 开发套件](https://gitlab.com/gitlab-org/gitlab-development-kit)以[针对 fork](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/index.md#develop-in-your-own-gitlab-fork)进行[开发](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/index.md#develop-in-your-own-gitlab-fork) . +2. 在叉子上进行更改. +3. 准备就绪后, [创建一个新的合并请求](../../user/project/merge_requests/creating_merge_requests.html) . +4. 在合并请求的描述中: + * 确保您提供完整而准确的信息. + * 查看提供的清单. +5. 将合并请求(如果可能)分配给相关项目的[代码所有者](../../user/project/code_owners.html)之一或`@mention` ,并说明您已准备好进行审查. + +当您向 GitLab 提交代码时,我们真的希望它被合并! 但是,我们始终会仔细审查提交的内容,这需要时间. 合并之前,代码提交通常会由两位[领域专家](../code_review.html#domain-experts)进行审核: + +* A [reviewer](../code_review.html#the-responsibility-of-the-reviewer). +* A [maintainer](../code_review.html#the-responsibility-of-the-maintainer). + +提交合并请求时,请牢记以下几点: + +* 当审阅者阅读合并请求时,他们可能会要求其他审阅者提供指导. +* 如果发现代码质量不符合 GitLab 的标准,则合并请求审阅者将提供指导,并将作者推荐给我们: + * [文档](../documentation/styleguide.html)样式指南. + * 代码样式指南. +* 有时会遵循样式指南,但是代码将缺乏结构完整性,或者审阅者会对​​代码的整体质量有所保留. 如有保留,审阅者将通知作者并提供一些指导. +* 尽管 GitLab 通常允许任何人表明对合并请求的[批准](../../user/project/merge_requests/merge_request_approvals.html) ,但是维护者在合并合并请求之前可能需要[获得某些审阅者的批准](../code_review.html#approval-guidelines) . +* 审核后,可能会要求作者更新合并请求. 合并请求更新并重新分配给审阅者后,他们将再次审阅代码. 在合并之前,此过程可以重复任意次数,以帮助做出最佳的贡献. + +有时,维护者可能会选择关闭合并请求. 他们将充分披露为什么不合并的原因以及一些指导. 维护人员将公开讨论如何更改代码,以便将来可以批准和合并. + +manbetx 客户端打不开将尽其所能尽快审查社区贡献. 专门任命的开发人员每天审查社区贡献. 在[团队页面上](https://about.gitlab.com/company/team/)查看合并请求指导者,他专门研究您编写的代码类型,并在合并请求中提及他们. 例如,如果您编写了一些前端代码,则应`@mention`前端合并请求指导程序. 如果您的代码具有多个学科,则可以`@mention`多个合并请求指导. + +GitLab 收到了很多社区的贡献. 如果您的代码在其初次提交后的两个工作日内仍未得到审查,请`@mention`与`@gitlab-org/coaches`合并的所有请求`@gitlab-org/coaches`引起他们的注意. + +在向 GitLab 提交代码时,您可能会觉得您的贡献需要外部库的帮助. 如果您的代码包含外部库,请提供该库的链接,以及包含该库的原因. + +`@mention`维护者在合并请求中包含: + +* 超过 500 种变化. +* 任何重大变化. +* 外部库. + +如果您不确定要提及谁,则审阅者将在合并请求过程的早期为您完成此操作. + +#### Issues workflow[](#issues-workflow "Permalink") + +This [documentation](issue_workflow.html) outlines the current issue workflow: + +* [Issue tracker guidelines](issue_workflow.html#issue-tracker-guidelines) +* [Issue triaging](issue_workflow.html#issue-triaging) +* [Labels](issue_workflow.html#labels) +* [Feature proposals](issue_workflow.html#feature-proposals) +* [Issue weight](issue_workflow.html#issue-weight) +* [Regression issues](issue_workflow.html#regression-issues) +* [Technical and UX debt](issue_workflow.html#technical-and-ux-debt) +* [Technical debt in follow-up issues](issue_workflow.html#technical-debt-in-follow-up-issues) + +#### Merge requests workflow[](#merge-requests-workflow "Permalink") + +本[文档](merge_request_workflow.html)概述了当前的合并请求过程. + +* [Merge request guidelines](merge_request_workflow.html#merge-request-guidelines) +* [Contribution acceptance criteria](merge_request_workflow.html#contribution-acceptance-criteria) +* [Definition of done](merge_request_workflow.html#definition-of-done) +* [Dependencies](merge_request_workflow.html#dependencies) + +## Style guides[](#style-guides "Permalink") + +本[文档](style_guides.html)概述了当前的样式准则. + +## Implement design & UI elements[](#implement-design--ui-elements "Permalink") + +本[设计文档](design.html)概述了实现设计和 UI 元素的当前过程. + +## Contribute documentation[](#contribute-documentation "Permalink") + +有关如何编写文档的信息,请参见 GitLab [文档指南](../documentation/index.html) . + +## Getting an Enterprise Edition License[](#getting-an-enterprise-edition-license "Permalink") + +如果您需要用于贡献 EE 功能的许可证,请参阅[相关信息](https://about.gitlab.com/handbook/marketing/community-relations/code-contributor-program/#for-contributors-to-the-gitlab-enterprise-edition-ee) . \ No newline at end of file diff --git a/docs/551.md b/docs/551.md new file mode 100644 index 0000000000000000000000000000000000000000..e45d42b60f42831f088ea5fafcfdb31ab8e7160a --- /dev/null +++ b/docs/551.md @@ -0,0 +1,20 @@ +# Community members & roles + +> 原文:[https://docs.gitlab.com/ee/development/contributing/community_roles.html](https://docs.gitlab.com/ee/development/contributing/community_roles.html) + +# Community members & roles[](#community-members--roles "Permalink") + +GitLab 社区成员及其特权/责任. + +| Roles | Responsibilities | Requirements | +| --- | --- | --- | +| Maintainer | 接受多个 GitLab 项目的合并请求 | 添加到[团队页面](https://about.gitlab.com/company/team/) . 代码审查专家并了解产品/代码库 | +| Reviewer | 在 MR 上执行代码审查 | 添加到[团队页面](https://about.gitlab.com/company/team/) | +| Developer | 可以访问 GitLab 内部基础设施和问题(例如与 HR 相关的问题) | GitLab 员工或核心团队成员(具有 NDA) | +| Contributor | 可以为所有 GitLab 公共项目做出贡献 | 有一个 GitLab.com 帐户 | + +[List of current reviewers/maintainers](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce). + +* * * + +[Return to Contributing documentation](index.html) \ No newline at end of file diff --git a/docs/552.md b/docs/552.md new file mode 100644 index 0000000000000000000000000000000000000000..b5fc9831e74a62ba5a7d5d5d6d579c34e6e95d00 --- /dev/null +++ b/docs/552.md @@ -0,0 +1,30 @@ +# Implement design & UI elements + +> 原文:[https://docs.gitlab.com/ee/development/contributing/design.html](https://docs.gitlab.com/ee/development/contributing/design.html) + +# Implement design & UI elements[](#implement-design--ui-elements "Permalink") + +有关在 GitLab 上实现 UX 的指导,请参阅我们的[设计系统](https://design.gitlab.com/) . + +The UX team uses labels to manage their workflow. + +问题上的〜" UX"标签向 UX 团队发出信号,表明它将需要 UX 注意. 为了更好地了解 UX 解决问题的优先级,请参阅手册的[UX 部分](https://about.gitlab.com/handbook/engineering/ux/) . + +解决问题并准备好进行开发后,UXer 会删除〜" UX"标签,并将〜" UX ready"标签应用于该问题. + +有一个特殊类型的标签,称为〜"产品发现",用于 UX,PM,FE 和 BE. 它代表讨论问题和潜在解决方案的发现问题. 该问题的最终输出可能是需求文档,设计工件,甚至是原型. 该解决方案将在随后的里程碑中开发. + +〜"产品发现"问题与其他任何问题一样,并且在当前里程碑中安排时,应包含里程碑标签,〜"可交付成果"或〜"伸展". + +The initial issue should be about the problem we are solving. 最初的问题应该与我们正在解决的问题有关. If a separate [product discovery issue](https://about.gitlab.com/handbook/engineering/ux/ux-department-workflow/#how-we-use-labels) is needed for additional research and design work, it will be created by a PM or UX person. 如果需要其他[产品发现问题](https://about.gitlab.com/handbook/engineering/ux/ux-department-workflow/#how-we-use-labels)来进行其他研究和设计工作,则将由 PM 或 UX 用户创建. Assign the ~UX, ~"product discovery" and ~"Deliverable" labels, add a milestone and use a title that makes it clear that the scheduled issue is product discovery (for example, `Product discovery for XYZ` ). 分配〜UX,〜"产品发现"和〜"可交付成果"标签,添加一个里程碑,并使用标题清楚地表明计划的问题是产品发现(例如, `Product discovery for XYZ` ). + +为了解决发行版中的产品发现问题,您必须完成以下操作: + +1. UXer 删除〜UX 标签,添加〜" UX ready"标签. +2. 修改产品发现问题中的问题描述以包含最终设计. 如果有道理,可以将指示设计需求的原始信息移至下部的"原始信息"部分. +3. 将设计复制到为其创建了产品发现问题的交付问题的描述中. 不要简单地将产品发现问题称为独立的事实来源. +4. 在某些情况下,产品发现问题还标识了将来的增强功能,这些增强功能不会包含在起源产品发现问题的问题中. 对于这些项目,请创建包含设计的新问题,以确保它们不会丢失. 如果这些问题是好的想法,则将这些问题放在待办事项中. 否则,将它们分类. + +* * * + +[Return to Contributing documentation](index.html) \ No newline at end of file diff --git a/docs/553.md b/docs/553.md new file mode 100644 index 0000000000000000000000000000000000000000..f12dd9299a43c8234e74a72caaa2838b572e4095 --- /dev/null +++ b/docs/553.md @@ -0,0 +1 @@ +> 原文:[https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/README.md](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/README.md) \ No newline at end of file diff --git a/docs/554.md b/docs/554.md new file mode 100644 index 0000000000000000000000000000000000000000..7ee906595f646d6539733eeffb0fa41ad2ee4c9b --- /dev/null +++ b/docs/554.md @@ -0,0 +1,338 @@ +# Issues workflow + +> 原文:[https://docs.gitlab.com/ee/development/contributing/issue_workflow.html](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html) + +* [Issue tracker guidelines](#issue-tracker-guidelines) +* [Issue triaging](#issue-triaging) +* [Labels](#labels) + * [Type labels](#type-labels) + * [Facet labels](#facet-labels) + * [Stage labels](#stage-labels) + * [Naming and color convention](#naming-and-color-convention) + * [Group labels](#group-labels) + * [Naming and color convention](#naming-and-color-convention-1) + * [Category labels](#category-labels) + * [Naming and color convention](#naming-and-color-convention-2) + * [Feature labels](#feature-labels) + * [Naming and color convention](#naming-and-color-convention-3) + * [Department labels](#department-labels) + * [Team labels](#team-labels) + * [Naming and color convention](#naming-and-color-convention-4) + * [Specialization labels](#specialization-labels) + * [Release scoping labels](#release-scoping-labels) + * [Priority labels](#priority-labels) + * [Severity labels](#severity-labels) + * [Label for community contributors](#label-for-community-contributors) + * [Stewardship label](#stewardship-label) +* [Feature proposals](#feature-proposals) +* [Issue weight](#issue-weight) +* [Regression issues](#regression-issues) +* [Technical and UX debt](#technical-and-ux-debt) +* [Technical debt in follow-up issues](#technical-debt-in-follow-up-issues) + +# Issues workflow[](#issues-workflow "Permalink") + +## Issue tracker guidelines[](#issue-tracker-guidelines "Permalink") + +在提交您自己**[的问题](https://gitlab.com/gitlab-org/gitlab/-/issues)**之前,请**[在问题跟踪器中](https://gitlab.com/gitlab-org/gitlab/-/issues)**搜索类似的条目,否则很有可能其他人也有相同的问题或功能建议. 通过奖励表情符号显示您的支持和/或参加讨论. + +请使用问题跟踪器提供的["错误"问题模板](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/issue_templates/Bug.md)提交错误. 括号中的文字可以帮助您添加内容. 提交实际问题时将其忽略. 您可以复制粘贴它,然后根据需要进行编辑. + +## Issue triaging[](#issue-triaging "Permalink") + +我们的问题分诊政策[在手册中](https://about.gitlab.com/handbook/engineering/quality/issue-triage/)有所[描述](https://about.gitlab.com/handbook/engineering/quality/issue-triage/) . 非常欢迎您帮助 GitLab 团队分类问题. 我们还每季度组织一次[bash 事件](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/17815) . + +最重要的是确保有效问题得到开发团队的反馈. 因此,优先考虑的是可以为这些问题提供帮助的开发人员. 请从[GitLab 团队中](https://about.gitlab.com/company/team/)选择具有相关经验的[人员](https://about.gitlab.com/company/team/) . 如果没有人提到这种专业知识,请在提交历史中查找受影响的文件以找到某人. + +我们还使用[GitLab Triage](https://gitlab.com/gitlab-org/gitlab-triage)来自动化一些分类策略. 当前已将其设置为在其上运行的计划管道( `https://gitlab.com/gitlab-org/quality/triage-ops/pipeline_schedules/10512/editpipeline_schedules/10512/edit` ,必须至少具有开发人员访问项目的权限) [质量/分类操作](https://gitlab.com/gitlab-org/quality/triage-ops)项目. + +## Labels[](#labels "Permalink") + +To allow for asynchronous issue handling, we use [milestones](https://gitlab.com/groups/gitlab-org/-/milestones) and [labels](https://gitlab.com/gitlab-org/gitlab/-/labels). Leads and product managers handle most of the scheduling into milestones. Labeling is a task for everyone. + +大多数问题的标签至少包含以下之一: + +* 类型: `~feature` , `~bug` , `~backstage` , `~documentation`等. +* 阶段: `~"devops::plan"` , `~"devops::create"`等 +* 组: `~"group::source code"` , `~"group::knowledge"` , `~"group::editor"`等 +* 类别: `~"Category:Code Analytics"` , `~"Category:DevOps Score"` , `~"Category:Templates"`等 +* 特点: `~wiki` , `~ldap` , `~api` , `~issues` , `~"merge requests"` ,等等. +* Department: `~UX`, `~Quality` +* Team: `~"Technical Writing"`, `~Delivery` +* Specialization: `~frontend`, `~backend`, `~documentation` +* 发布范围: `~Deliverable` , `~Stretch` , `~"Next Patch Release"` +* Priority: `~P1`, `~P2`, `~P3`, `~P4` +* 严重性: `S1` , `~S2` , `~S3` , `~S4` + +所有标签,其含义和优先级均在[标签页面](https://gitlab.com/gitlab-org/gitlab/-/labels)上定义. + +如果您遇到的问题都不存在,并且可以设置标签,则可以*随时*添加类型,阶段,组以及类别/功能标签. + +### Type labels[](#type-labels "Permalink") + +类型标签非常重要. 他们定义了这是什么类型的问题. 每个问题都应该只有一个. + +当前的类型标签为: + +* ~feature +* ~bug +* ~backstage +* 〜"支持请求" +* ~meta +* ~documentation + +许多类型标签都分配了优先级,这会根据其重要性自动使它们浮动到顶部. + +类型标签始终是小写字母,并且可以具有除蓝色(已为类别标签保留)以外的任何颜色. + +[标签页面](https://gitlab.com/groups/gitlab-org/-/labels)上的描述说明了每种类型标签下的内容. + +GitLab 手册记录了[什么是错误](https://about.gitlab.com/handbook/product/product-processes/#bug-issues)以及[什么是功能请求](https://about.gitlab.com/handbook/product/product-processes/#feature-issues) . + +### Facet labels[](#facet-labels "Permalink") + +有时,改进问题的类型很有用. 在这种情况下,您可以添加构面标签. + +以下是构面标签的非详尽列表: + +* 增强功能:此标签可以完善具有功能标签的问题. +* 〜" master:broken":此标签可以细化带有〜bug 标签的问题. +* 〜" failure :: flaky-test":此标签可以细化带有〜bug 标签的问题. +* 〜"技术债务":此标签可以完善具有〜后台标签的问题. +* 〜"静态分析":此标签可以细化具有〜backstage 标签的问题. +* 〜" ci-build":此标签可以优化具有〜backstage 标签的问题. +* 〜性能:性能问题可能描述〜错误或〜功能. +* 〜安全性:一个安全性问题可以描述一个 bug 或一个功能. +* 数据库:数据库问题可能描述错误或功能. +* 〜customer:这与客户创建的或客户感兴趣的问题有关. +* 〜" UI 文本":在 UI 内添加或修改任何文本的问题,例如用户辅助显微镜,按钮/菜单标签或错误消息. + +### Stage labels[](#stage-labels "Permalink") + +阶段标签指定问题属于哪个[阶段](https://about.gitlab.com/handbook/product/product-categories/#hierarchy) . + +#### Naming and color convention[](#naming-and-color-convention "Permalink") + +舞台标签遵守`devops::`命名约定. ``是阶段密钥,因为它位于[https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml)的单个真相来源中,其中`_`替换为空间. + +例如," Manage"阶段由`gitlab-org`组中的`~"devops::manage"`标签表示,因为它的关键`stages`是`manage` . + +通过[在标签列表中搜索`devops::`](https://gitlab.com/groups/gitlab-org/-/labels?search=devops::)可以找到当前阶段的标签. + +这些标签是[作用域标签](../../user/project/labels.html#scoped-labels-premium) ,因此是互斥的. + +舞台标签用于自动生成[方向页面](https://about.gitlab.com/direction/) . + +### Group labels[](#group-labels "Permalink") + +组标签指定了问题所属的[组](https://about.gitlab.com/company/team/structure/#product-groups) . + +强烈建议添加一个组标签,因为我们的分类自动化会使用它来[推断正确的舞台标签](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#auto-labelling-of-issues) . + +#### Naming and color convention[](#naming-and-color-convention-1 "Permalink") + +组标签遵循`group::`命名约定,其颜色为`#A8D695` . ``是组密钥,因为它位于[https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml 的](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml)组的单个真实来源中,其中已替换`_`与空间. + +例如," Continuous Integration"组由`gitlab-org`组中的〜" group :: continuous integration"标签表示,因为它的关键在`stages.manage.groups`下是`continuous_integration` . + +通过[在标签列表中搜索`group::`](https://gitlab.com/groups/gitlab-org/-/labels?search=group::)可以找到当前的组标签. + +这些标签是[作用域标签](../../user/project/labels.html#scoped-labels-premium) ,因此是互斥的. + +您可以在" [产品阶段","组"和"类别"](https://about.gitlab.com/handbook/product/product-categories/)页面中找到列出的[组](https://about.gitlab.com/handbook/product/product-categories/) . + +我们使用术语组来映射产品阶段中的产品需求. 当团队需要某种方式来收集其成员计划分配的工作时,我们可以使用`~group::`标签来完成. + +通常,舞台标签和组标签之间存在 1:1 的关系. 本着"人人都可以贡献"的精神,任何问题都可以由任何团体根据当前的优先事项来解决. 拾取属于其他组的问题时,应重新标记. 例如,如果计划阶段的"访问"组中的某人拾取了标有`~"devops::create"`和`~"group::knowledge"`的问题,则应在发布该问题时将其重新标记为`~"group::access"`保持原始`~"devops::create"`不变. + +我们还使用阶段标签和组标签来帮助量化[吞吐量](https://about.gitlab.com/handbook/engineering/management/throughput/) . 请阅读[吞吐量中的阶段和组标签,](https://about.gitlab.com/handbook/engineering/management/throughput/#stage-and-group-labels-in-throughput)以获取有关在这种情况下如何使用标签的更多信息. + +### Category labels[](#category-labels "Permalink") + +在手册的" [产品阶段,组和类别"](https://about.gitlab.com/handbook/product/product-categories/#hierarchy)页面中: + +> 类别是高级功能,可能是另一家公司的独立产品. 例如投资组合管理. + +强烈建议添加类别标签,因为我们的分类自动化会使用它来[推断正确的组和阶段标签](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#auto-labelling-of-issues) . + +如果您是特定领域的专家,则可以更轻松地找到要解决的问题. 您还可以订阅这些标签,以在每次用与您的专业知识相对应的类别标签标记问题时接收电子邮件. + +#### Naming and color convention[](#naming-and-color-convention-2 "Permalink") + +类别标签遵循" `Category:`命名约定,其颜色为`#428BCA` . ``是类别名称,因为它位于[https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml 的](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml)类别的唯一真实来源中. + +例如," DevOps 分数"类别由`gitlab-org`组中的〜" Category:DevOps 分数"标签表示,因为其`devops_score.name`值为" DevOps 分数". + +如果类别的标签不遵守此命名约定,则应在[https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml 中](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml)使用[`label`属性](https://about.gitlab.com/handbook/marketing/website/#category-attributes)指定它. + +### Feature labels[](#feature-labels "Permalink") + +From the handbook’s [Product stages, groups, and categories](https://about.gitlab.com/handbook/product/product-categories/#hierarchy) page: + +> 特点:小型,离散功能. 例如发行权重. 括号中列出了一些常用功能,以帮助通过关键字查找负责任的 PM. + +如果没有类别标签,强烈建议添加功能标签,因为我们的分类自动分类系统会使用该功能标签来[推断正确的组和阶段标签](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#auto-labelling-of-issues) . + +如果您是特定领域的专家,则可以更轻松地找到要解决的问题. 您还可以订阅这些标签,以在每次问题被标记有与您的专业知识相对应的功能标签时接收电子邮件. + +特征标签的例子是`~wiki` , `~ldap` , `~api` , `~issues` , `~"merge requests"`等. + +#### Naming and color convention[](#naming-and-color-convention-3 "Permalink") + +功能标签全部为小写. + +### Department labels[](#department-labels "Permalink") + +当前部门标签为: + +* ~UX +* ~Quality + +### Team labels[](#team-labels "Permalink") + +**重要提示** :现在不推荐使用大多数历史团队标签(例如"管理","计划"等),而推荐使用" [组"标签](#group-labels)和" [阶段"标签](#stage-labels) . + +团队标签指定负责此问题的团队. 分配团队标签可确保问题引起适当人员的注意. + +当前的团队标签为: + +* ~Delivery +* 〜"技术写作" + +#### Naming and color convention[](#naming-and-color-convention-4 "Permalink") + +团队标签始终大写,以便显示为任何问题的第一个标签. + +### Specialization labels[](#specialization-labels "Permalink") + +这些标签缩小了工作单元的[专业](https://about.gitlab.com/company/team/structure/#specialist)范围. + +* ~frontend +* ~backend +* ~documentation + +### Release scoping labels[](#release-scoping-labels "Permalink") + +发布范围界定标签有助于我们清楚地传达对发布工作的期望. 发行范围界定标签分为三个级别: + +* 〜可交付成果:预期在当前里程碑中交付的问题. +* 〜延伸:问题是实现当前里程碑的延伸目标. 如果当前发行版中未解决这些问题,则强烈考虑将它们用于下一个发行版. +* 〜"下一个补丁程序发行版":下一个补丁程序发行版中的问题. 首先进行处理,然后将`~"Pick into XY"`标签添加到合并请求中,并添加适当的里程碑. + +为当前里程碑计划的每个发行都应标记为〜Deliverable 或〜" Stretch". 上一个里程碑的所有未解决问题都应标记为"下一个补丁发布",或以其他方式重新安排到另一个里程碑. + +### Priority labels[](#priority-labels "Permalink") + +我们具有以下优先级标签: + +* ~P1 +* ~P2 +* ~P3 +* ~P4 + +请参阅手册中的问题分类[优先级标签](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#priority)部分,以了解其用法. + +### Severity labels[](#severity-labels "Permalink") + +我们具有以下严重性标签: + +* ~S1 +* ~S2 +* ~S3 +* ~S4 + +请参阅手册中的问题分类[优先级标签](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#severity)部分,以了解其用法. + +### Label for community contributors[](#label-for-community-contributors "Permalink") + +我们目前没有能力或不想给予优先考虑的对用户有益的问题" nice to haves"被标记为"正在接受合并请求",以便社区可以做出贡献. + +社区贡献者可以针对他们想要的任何问题提交合并请求,但是〜"接受合并请求"标签具有特殊含义. 它指出了以下变化: + +1. 我们已经达成共识, +2. 定义明确 +3. 可能会被维护者接受. + +我们希望避免出现以下情况:投稿人选择〜"接受合并请求"问题,然后关闭他们的合并请求,因为我们意识到它不符合我们的愿景,或者我们想以其他方式解决它. + +我们会自动将〜"接受合并请求"标签添加到与[分类策略](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#accepting-merge-requests)匹配的问题. + +我们建议从未参与过任何开源项目的人员寻找标有`~"Accepting merge requests"`且[权重为 1](https://gitlab.com/groups/gitlab-org/-/issues?state=opened&label_name[]=Accepting+merge+requests&assignee_id=None&sort=weight&weight=1)或带有`~"Good for 1st time contributors"` [标签的](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=✓&state=opened&label_name[]=Good for 1st time contributors&assignee_id=None)问题. 我们欢迎更多有经验的贡献者[与他们](https://gitlab.com/groups/gitlab-org/-/issues?state=opened&label_name[]=Accepting+merge+requests&assignee_id=None)一起解决. + +如果您决定要解决某个问题,请@-提及[适当的产品经理](https://about.gitlab.com/handbook/product/#who-to-talk-to-for-what) . 然后,产品经理将邀请适当的 GitLab 团队成员进一步讨论范围,设计和技术注意事项. 这将确保您的贡献与 GitLab 产品保持一致,并最大程度地减少返工和将其合并到 master 中的延迟. + +在问题上贴上"接受合并请求"标签的 GitLab 团队成员应与负责任的产品经理一起更新问题描述,并邀请上述任何潜在的社区贡献者加入@提及. + +### Stewardship label[](#stewardship-label "Permalink") + +对于与 GitLab 的开源管理有关的问题,有〜"管理"标签. + +该标签将用于解决有关 GitLab 管理问题的问题. 例如,如果 GitLab Inc.计划将 GitLab EE 中的功能添加到 GitLab CE 中,则相关问题将标记为"管理". + +最近的一个例子是[将时间跟踪 API 引入 GitLab CE 的问题](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/25517#note_20019084) . + +## Feature proposals[](#feature-proposals "Permalink") + +要创建功能建议,请在[问题跟踪器](https://gitlab.com/gitlab-org/gitlab/-/issues)上打开[问题](https://gitlab.com/gitlab-org/gitlab/-/issues) . + +为了帮助跟踪功能建议,我们创建了[`feature`](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name=feature)标签. 目前,不是项目成员的用户无法添加标签. 您可以改为要求[核心团队](https://about.gitlab.com/community/core-team/)成员之一在问题上添加标签〜feature,或在描述后的新行中添加以下代码段: `~feature` . + +请使功能建议尽可能小而简单,复杂的建议可能会被编辑以使其小而简单. + +请使用问题跟踪器上提供的["功能建议"问题模板](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/issue_templates/Feature proposal.md)提交功能建议. + +For changes in the interface, it is helpful to include a mockup. Issues that add to, or change, the interface should be given the ~”UX” label. This will allow the UX team to provide input and guidance. You may need to ask one of the [core team](https://about.gitlab.com/community/core-team/) members to add the label, if you do not have permissions to do it by yourself. + +如果您想自己创建一些东西,请考虑首先打开一个问题,讨论将其包含在 GitLab 中是否有趣. + +## Issue weight[](#issue-weight "Permalink") + +问题权重使我们对解决一个或多个问题所需的工作量有所了解. 这样可以更准确地安排工作. + +鼓励您设置任何问题的权重. 遵循以下准则将使其易于管理,而没有不必要的开销. + +1. 尽早设置任何问题的权重 +2. 如果您不同意设定的权重,请与其他开发人员讨论,直到就权重达成共识 +3. 问题权重是问题复杂性的抽象度量. 不要将发行权重直接与时间相关. 这称为[锚定](https://en.wikipedia.org/wiki/Anchoring) ,是您要避免的事情. +4. 权重为 1(或无权重)的东西确实很小而简单. 9 表示正在重写 GitLab 的一个很大的基本部分,这可能会导致许多难以解决的问题. 在 GitLab 中更改某些文本可能是 1,添加新的 Git Hook 可能是 4 或 5,大功能是 7-9. +5. 如果某事物非常大,则应将其拆分为多个问题或大块. 您不能简单地设置父问题的权重,而不能设置子问题的权重. + +## Regression issues[](#regression-issues "Permalink") + +每个月度发行版的 CE 问题跟踪器上都有一个相应的发行版,以跟踪该发行版所破坏的功能以及修补程序发行版中需要包含的所有修补程序(请参阅[8.3 回归](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/4127)示例). + +如问题描述中所概述的那样,预期的工作流程是发布一个注释,其中包含对描述回归的问题的引用,然后通过对合并请求的引用来更新该注释,该合并请求将在发布后对其进行修复. + +如果您是贡献者,没有所需的权限来更新其他用户的注释,请发布新注释,同时提及问题和合并请求. + +发布经理将在解决补丁程序后[更新](https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue)回归问题中[的注释](https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue) . + +## Technical and UX debt[](#technical-and-ux-debt "Permalink") + +为了跟踪可以在 GitLab 的代码库中改进的事物,我们在[GitLab 的问题跟踪器中](https://gitlab.com/gitlab-org/gitlab/-/issues)使用〜"技术债务"标签. 对于错过的用户体验要求,我们使用〜" UX 债务"标签. + +这些标签应添加到描述可以改进的问题,已采取的捷径,需要额外注意的功能以及由于高速发展而遗留下来的所有其他事项的问题上. 例如,需要重构的代码应使用〜"技术债务"标签,根据我们的设计系统准则,未交付的某些产品应使用〜" UX 债务"标签. + +每个人都可以创建一个问题,但是如果您没有权限自行添加,则可能需要请求添加特定标签. 可以将其他标签与这些标签结合使用,以更轻松地计划发布的改进. + +用这些标签标记的问题具有与描述要在 GitLab 中引入的新功能的问题相同的优先级,并且应该安排由适当的人员发布. + +请确保在问题的描述中提及与"技术债务"问题或" UX 债务"问题相关的合并请求. + +## Technical debt in follow-up issues[](#technical-debt-in-follow-up-issues "Permalink") + +在开发新功能时通常会发现技术债务. 本着"最小可行的改变"的精神,通常将解决方案推迟到后续问题上. 但是,这不能用作合并劣质代码的借口,否则这些劣质代码将无法通过审阅,或者忽略了琐事,这些琐事不值得单独安排,最好在原始合并请求中解决-否则完全追踪! + +The overheads of scheduling, and rate of change in the GitLab codebase, mean that the cost of a trivial technical debt issue can quickly exceed the value of tracking it. This generally means we should resolve these in the original merge request - or simply not create a follow-up issue at all. + +例如,在文件之间复制的注释中的错字值得在同一 MR 中修复,但不值得为其创建后续问题. 重命名在许多地方使用的方法以使其意图更清晰可能是值得修复的,但是这种方法不应在同一 MR 中发生,并且通常不值得自己解决. 如果我们要创建这些问题,这些问题将始终标记为`~P4 ~S4` . + +更严重的技术债务可能对发展速度产生影响. 如果不能及时解决,那么代码库将变得不必要地难以更改,新功能也将难以添加,并且大量回归. + +应该认真对待此类技术债务的发现,尽管在后续问题中解决问题可能是适当的,但维护人员通常应从原始 MR 的作者或相关领域的工程或产品经理那里获得调度承诺. . 这可以采取在问题上使用适当的优先级/严重性标签的形式,也可以采用明确的里程碑和受让人的形式. + +维护者必须始终同意,以这种方式解决一个悬而未决的讨论,并且它将是引发问题的人. 标题和描述的质量应[与通常](#technical-and-ux-debt)创建的标题和描述的质量相同-特别是,问题标题**不能**以" `Follow-up`开头! 创建维护者还应该期望在后续问题上开始工作时会有所参与. + +* * * + +[Return to Contributing documentation](index.html) \ No newline at end of file diff --git a/docs/555.md b/docs/555.md new file mode 100644 index 0000000000000000000000000000000000000000..85799fc5d4adf37fbda07aa0b7f723e45d165674 --- /dev/null +++ b/docs/555.md @@ -0,0 +1,176 @@ +# Merge requests workflow + +> 原文:[https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html](https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html) + +* [Merge request guidelines](#merge-request-guidelines) + * [Keep it simple](#keep-it-simple) + * [Commit messages guidelines](#commit-messages-guidelines) +* [Contribution acceptance criteria](#contribution-acceptance-criteria) +* [Definition of done](#definition-of-done) +* [Dependencies](#dependencies) +* [Incremental improvements](#incremental-improvements) + +# Merge requests workflow[](#merge-requests-workflow "Permalink") + +We welcome merge requests from everyone, with fixes and improvements to GitLab code, tests, and documentation. The issues that are specifically suitable for community contributions are listed with the [`Accepting merge requests`](issue_workflow.html#label-for-community-contributors) label, but you are free to contribute to any issue you want. + +请注意,如果在任何时候都为当前里程碑标记了一个问题,即使您正在处理它,则 GitLab Inc.团队成员可能会接管合并请求,以确保工作在发布日期之前完成. + +如果要添加未标记的新功能,最好首先创建一个问题(如果还没有一个问题)并发表评论,要求将其标记为" `Accepting Merge Requests` . 如果还可以更改用户界面,请提供建议功能的屏幕截图或线框. + +合并请求应提交到 GitLab.com 上的相应项目,例如[GitLab](https://gitlab.com/gitlab-org/gitlab/-/merge_requests) , [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests) , [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests)等. + +如果您不熟悉 GitLab 开发(或一般而言的 Web 开发),请参阅" [如何做出贡献"](index.html#how-to-contribute)部分,以开始解决一些潜在的简单问题. + +要开始开发 GitLab,请下载[GitLab 开发套件,](https://gitlab.com/gitlab-org/gitlab-development-kit)并参阅" [开发"部分](../../README.html)以获取所需指南. + +## Merge request guidelines[](#merge-request-guidelines "Permalink") + +如果发现问题,请提交包含修复或改进的合并请求(如果可以),并包括测试. 如果您不知道如何解决该问题,但是可以编写暴露该问题的测试,我们也将接受. 通常,包含回归测试的错误修复将快速合并,而没有适当测试的新功能可能会更慢地接收反馈. 进行合并请求的工作流程如下: + +1. [叉](../../user/project/repository/forking_workflow.html)项目插入 GitLab.com 您的个人命名空间(或一组). +2. 在 fork 中创建一个功能分支(不要使用`master` ). +3. 编写[测试](../rake_tasks.html#run-tests)和代码. +4. [Generate a changelog entry with `bin/changelog`](../changelog.html) +5. 如果要编写文档,请确保遵循[文档准则](../documentation/index.html) . +6. 遵循[提交消息准则](#commit-messages-guidelines) . +7. 如果您有多个提交,请通过[压缩它们](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#_squashing)将它们组合为几个逻辑组织的提交,但是如果您正在共享分支上,则不要更改提交历史记录. +8. 将提交推送到 fork 中的工作分支. +9. 向主 GitLab 项目中的`master`分支提交合并请求(MR). + 1. 您的合并请求至少需要 1 个批准,但是根据您的更改,您可能需要其他批准. 请参阅[批准准则](../code_review.html#approval-guidelines) . + 2. 您不必选择任何特定的批准人,但是如果您确实希望特定的人批准您的合并请求,则可以选择. +10. MR 标题应描述您要进行的更改. +11. MR 说明应说明您进行更改的原因. + 1. 如果您要提供代码,请根据"描述"字段中已经提供的默认模板填写描述. + 2. 如果您要提供文档,请从"选择模板"菜单中选择" `Documentation` ",然后根据模板填写说明. + 3. 提及合并请求解决的问题,合并请求合并后,使用" `Solves #XXX`或" `Closes #XXX`语法[自动关闭](../../user/project/issues/managing_issues.html#closing-issues-automatically)问题. +12. 如果允许,请设置相关的里程碑和[标签](issue_workflow.html) . +13. UI 更改应使用 GitLab 设计系统" [睡衣"中的](https://design.gitlab.com/)可用组件. MR 必须包含" *之前*和*之后"*屏幕截图. +14. 如果 MR 更改了 CSS 类,请包括受影响页面的列表,可以通过运行`grep css-class ./app -R`来找到. +15. 如果您的 MR 触摸了执行 Shell 命令,读取或打开文件或处理磁盘上文件路径的代码,请确保它符合[Shell 命令准则](../shell_commands.html) +16. 如果您的代码在磁盘上创建了新文件,请阅读[共享文件准则](../shared_files.html) . +17. 如果您的合并请求添加了一个或多个迁移,请确保在审阅 MR 之前对新数据库执行所有迁移. 如果检查导致 MR 发生较大变化,请在检查完成后再次执行迁移. +18. 为更复杂的迁移编写测试. +19. 合并请求**必须**遵守[合并请求性能准则](../merge_request_performance_guidelines.html) . +20. 对于使用 Capybara 的测试,请阅读[如何编写可靠的异步集成测试](https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara) . +21. 如果从源安装 GitLab 时,合并请求中引入的更改需要其他步骤, `doc/install/installation.md`在同一合并请求中将它们添加到`doc/install/installation.md`中. +22. 如果您的合并请求引入了从源代码升级 GitLab 时需要其他步骤的更改,请在同一合并请求中将它们添加到`doc/update/upgrading_from_source.md`中. 如果这些说明是特定于版本的,请将它们添加到"特定于版本的升级说明"部分. +23. 阅读并遵守[合并请求作者的责任](../code_review.html#the-responsibility-of-the-merge-request-author) . +24. 阅读并关注[审核您的合并请求](../code_review.html#having-your-merge-request-reviewed) . + +如果您想对合并请求提供快速反馈,请随时提及[核心团队](https://about.gitlab.com/community/core-team/)或[合并请求指导者之一](https://about.gitlab.com/company/team/) . 在审查您的代码以及审查合并请求时,请牢记[代码审查准则](../code_review.html) . 并且,如果您的代码也对数据库进行了更改或进行了昂贵的查询,请查看[数据库复审指南](../database_review.html) . + +### Keep it simple[](#keep-it-simple "Permalink") + +*进行较小的迭代.* 请保持单个 MR 中的更改量**尽可能小** . 如果您想提供较大的功能,请仔细考虑[最小的可行更改](https://about.gitlab.com/handbook/product/#the-minimally-viable-change) . 您可以将功能分为两个较小的 MR 吗? 您只能提交后端/ API 代码吗? 您可以从一个非常简单的 UI 开始吗? 您可以只做一部分重构吗? + +小型 MR 更易于查看,从而导致更高的代码质量,对于 GitLab 而言,这比具有最少的提交日志更为重要. MR 越小,合并的可能性就越大. 之后,您可以发送更多 MR,以增强和扩展功能. Kubernetes 团队的《 [如何获得更快的 PR 评论》](https://github.com/kubernetes/kubernetes/blob/release-1.5/docs/devel/faster_reviews.md)文档也对此有一些建议. + +### Commit messages guidelines[](#commit-messages-guidelines "Permalink") + +编写提交消息时,请遵循以下准则: + +* 提交主题必须包含至少 3 个字. +* 提交主题不得超过 72 个字符. +* 提交主题必须以大写字母开头. +* 提交主题不得以句号结尾. +* 提交主题和正文必须用空白行分隔. +* 提交正文每行不得包含超过 72 个字符. +* 在至少 3 个文件中更改 30 行或更多行的提交必须在提交正文中描述这些更改. +* 提交主题或正文不得包含表情符号. +* 使用问题并合并请求的完整 URL 而不是简短参考,因为它们在 GitLab 之外显示为纯文本. +* 合并请求不得包含超过 10 条提交消息. + +如果不符合指导原则,MR 将不会通过[危险检查](https://gitlab.com/gitlab-org/gitlab/blob/master/danger/commit_messages/Dangerfile) . 有关更多信息,请参见[如何编写 Git 提交消息](https://chris.beams.io/posts/git-commit/) . + +可以在您的计算机上使用的体现以上内容的示例提交消息模板(有关[如何应用 template 的](https://codeinthehole.com/tips/a-useful-template-for-commit-messages/)指南): + +``` +# (If applied, this commit will...) (Max 50 char) +# |<---- Using a Maximum Of 50 Characters ---->| + +# Explain why this change is being made +# |<---- Try To Limit Each Line to a Maximum Of 72 Characters ---->| + +# Provide links or keys to any relevant tickets, articles or other resources +# Use issues and merge requests' full URLs instead of short references, +# as they are displayed as plain text outside of GitLab + +# --- COMMIT END --- +# -------------------- +# Remember to +# Capitalize the subject line +# Use the imperative mood in the subject line +# Do not end the subject line with a period +# Subject must contain at least 3 words +# Separate subject from body with a blank line +# Commits that change 30 or more lines across at least 3 files must +# describe these changes in the commit body +# Do not use Emojis +# Use the body to explain what and why vs. how +# Can use multiple lines with "-" for bullet points in body +# For more information: https://chris.beams.io/posts/git-commit/ +# -------------------- +``` + +## Contribution acceptance criteria[](#contribution-acceptance-criteria "Permalink") + +为确保您的合并请求能够获得批准,请确保其符合以下捐款接受标准: + +1. 更改尽可能小. +2. 包括适当的测试并使所有测试通过(除非它包含暴露现有代码中的错误的测试). 每个新类都应具有相应的单元测试,即使该类是在较高级别上进行的,例如功能测试. + * 如果失败的 CI 构建似乎与您的贡献无关,则可以尝试重新启动失败的 CI 作业,从主服务器重新部署以引入可以解决该失败的更新,或者如果尚未解决,请请开发人员来帮助您修复测试. +3. MR 最初包含一些按逻辑组织的提交. +4. 更改可以合并而不会出现问题. 否则,如果您是功能分支上的唯一成员,则应重新设置基准,否则合并`master` . +5. 仅解决了一个特定问题或实现了一个特定功能. 不要结合东西; 针对每个问题或功能发送单独的合并请求. +6. 迁移应仅做一件事(例如,创建表,将数据移动到新表或删除旧表),以帮助重试失败. +7. 包含其他用户将从中受益的功能. +8. 不要添加配置选项或设置选项,因为它们会使进行和测试将来的更改复杂化. +9. 更改不会降低性能: + * 避免重复轮询需要大量开销的端点. + * 通过 SQL 日志或[`QueryRecorder`](../merge_request_performance_guidelines.html)检查 N + 1 个查询. + * 避免重复访问文件系统. + * 如果需要支持实时功能,可将[轮询与 ETag 缓存一起](../polling.html)使用. +10. 如果合并请求添加了任何新库(宝石,JavaScript 库等),则它们应符合我们的[许可准则](../licensing.html) . 如果" license-finder"测试失败,并且`Dependencies that need approval`错误`Dependencies that need approval`请参阅那些说明. 另外,使审阅者了解新库并解释为什么需要它. +11. 合并请求符合下面的 GitLab [对 done](#definition-of-done)的[定义](#definition-of-done) . + +## Definition of done[](#definition-of-done "Permalink") + +如果您为 GitLab 做贡献,请知道更改不仅涉及代码. 我们使用以下[完成的定义](https://www.agilealliance.org/glossary/definition-of-done) . 在您确定满足所有这些要求之前,您的贡献不会*完成* . + +1. 清晰的说明,说明捐款的相关性. +2. 工作并清理需要注释的代码. +3. 所有通过 CI 服务器的[单元测试,集成测试和系统测试](../testing_guide/index.html) . +4. 测试涵盖了回归和错误,可降低问题再次发生的风险. +5. 遵循[性能准则](../merge_request_performance_guidelines.html) . +6. 遵循[安全编码准则](https://gitlab.com/gitlab-com/gl-security/security-guidelines) . +7. [记录](../documentation/index.html)在`/doc`目录中. +8. 如有必要, [添加了 Changelog 条目](../changelog.html) . +9. 由相关(UX / FE / BE /技术写作)审稿人审阅,并解决所有问题. +10. 由项目维护者合并. +11. 在[基础结构问题跟踪器中](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues)创建问题,以在您的文稿更改默认设置或引入新设置(如果相关)时通知基础结构部门. +12. 部署贡献后,确认已在[Canary 阶段](https://about.gitlab.com/handbook/engineering/#canary-testing)或 GitLab.com 上工作. +13. 添加到[发布中](https://about.gitlab.com/handbook/marketing/blog/release-posts/) (如果相关). +14. 添加到[网站](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/features.yml) (如果相关). +15. 如果需要, [可以](../testing_guide/testing_levels.html#black-box-tests-at-the-system-level-aka-end-to-end-tests)添加[黑盒测试/端到端测试](../testing_guide/testing_levels.html#black-box-tests-at-the-system-level-aka-end-to-end-tests) . 如有任何疑问,请联系[质量团队](https://about.gitlab.com/handbook/engineering/quality/#teams) . + +## Dependencies[](#dependencies "Permalink") + +如果您在 GitLab 中添加了一个依赖项(例如操作系统软件包),请考虑更新以下内容,并在合并请求中注意每个依赖项的适用性: + +1. 请注意[发布博客文章中](https://about.gitlab.com/handbook/marketing/blog/release-posts/)的附加内容(如果尚不存在,请创建一个). +2. [The upgrade guide](../../update/upgrading_from_source.html). +3. The [GitLab Installation Guide](../../install/installation.html#1-packages-and-dependencies). +4. The [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit). +5. The [CI environment preparation](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/prepare_build.sh). +6. The [Omnibus package creator](https://gitlab.com/gitlab-org/omnibus-gitlab). + +## Incremental improvements[](#incremental-improvements "Permalink") + +我们会在工程上花费一些时间来解决小问题(有或没有问题),这些小问题是逐步改进的,例如: + +1. 未经优先考虑的错误修复(例如[,到处都显示有关项目移动的横幅警报](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18985) ) +2. 文档改进 +3. Rubocop 或代码质量改进 + +用〜"应该工作的东西"标记合并请求,以跟踪该区域中的工作. \ No newline at end of file diff --git a/docs/556.md b/docs/556.md new file mode 100644 index 0000000000000000000000000000000000000000..ec5783a0b019e7da856e5a5559ebbc8cc5bd20e6 --- /dev/null +++ b/docs/556.md @@ -0,0 +1,346 @@ +# Code Review Guidelines + +> 原文:[https://docs.gitlab.com/ee/development/code_review.html](https://docs.gitlab.com/ee/development/code_review.html) + +* [Getting your merge request reviewed, approved, and merged](#getting-your-merge-request-reviewed-approved-and-merged) + * [Domain experts](#domain-experts) + * [Reviewer roulette](#reviewer-roulette) + * [Approval guidelines](#approval-guidelines) + * [Security requirements](#security-requirements) + * [The responsibility of the merge request author](#the-responsibility-of-the-merge-request-author) + * [The responsibility of the reviewer](#the-responsibility-of-the-reviewer) + * [The responsibility of the maintainer](#the-responsibility-of-the-maintainer) +* [Best practices](#best-practices) + * [Everyone](#everyone) + * [Having your merge request reviewed](#having-your-merge-request-reviewed) + * [Assigning a merge request for a review](#assigning-a-merge-request-for-a-review) + * [List of merge requests ready for review](#list-of-merge-requests-ready-for-review) + * [Reviewing a merge request](#reviewing-a-merge-request) + * [Merging a merge request](#merging-a-merge-request) + * [The right balance](#the-right-balance) + * [GitLab-specific concerns](#gitlab-specific-concerns) + * [Review turnaround time](#review-turnaround-time) + * [Review-response SLO](#review-response-slo) + * [Customer critical merge requests](#customer-critical-merge-requests) +* [Examples](#examples) + * [Credits](#credits) + +# Code Review Guidelines[](#code-review-guidelines "Permalink") + +本指南包含有关执行代码审查和代码审查的建议和最佳实践. + +无论是由 GitLab 团队成员还是志愿者贡献者编写的所有对 GitLab CE 和 EE 的合并请求,都必须经过代码审查流程,以确保代码有效,可理解,可维护和安全. + +## Getting your merge request reviewed, approved, and merged[](#getting-your-merge-request-reviewed-approved-and-merged "Permalink") + +强烈建议您让您的代码通过**审核** [评审](https://about.gitlab.com/handbook/engineering/workflow/code-review/#reviewer) ,一旦有任何代码评审,获得所选择的解决方案和实施,和一个额外的一双眼睛寻找错误,逻辑问题,或裸露边缘的第二意见案件. + +默认方法是从您的小组或团队中选择一名审阅者进行第一次审阅. 这只是一个建议,审阅者可能来自其他团队. 但是,建议选择一个[领域专家](#domain-experts) . + +您可以在下面有关作者责任的部分中详细了解让审稿人参与的重要性. + +如果您需要一些指导(例如,这是您的第一个合并请求),请随时咨询一位[合并请求教练](https://about.gitlab.com/company/team/) . + +如果您需要有关安全扫描或注释的帮助,请随时在评论中包括安全团队( `@gitlab-com/gl-security` ). + +根据您的合并请求涉及的领域,它必须由一个或多个[维护者](https://about.gitlab.com/handbook/engineering/workflow/code-review/#maintainer) **批准** : + +对于批准,我们使用合并请求小部件中的批准功能. 审阅者可以通过[额外](../user/project/merge_requests/merge_request_approvals.html#adding-or-removing-an-approval)批准来添加其批准. + +让您的合并请求也**合并**需要一个维护者. 如果需要多个批准,则最后一个对其进行审核的维护者也会将其合并. + +### Domain experts[](#domain-experts "Permalink") + +领域专家是在特定技术,产品功能或代码库领域具有丰富经验的团队成员. 鼓励团队成员自认是领域专家,并将其添加到他们的[团队资料中](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/team.yml) + +当自我确定为领域专家时,建议分配更改`team.yml`的 MR,以由已经建立的领域专家或相应的工程经理进行合并. + +对于自动被视为领域专家,我们做出以下假设: + +* 在特定阶段/小组中工作的团队成员(例如,创建:源代码)被视为他们所从事的应用程序领域的领域专家 +* 从事特定功能(例如搜索)的团队成员被视为该功能的领域专家 + +我们默认为具有领域专业知识的团队成员分配评论. 如果没有合适的[领域专家](#domain-experts) ,您可以选择任何团队成员来审核 MR,也可以按照" [审核者"轮盘赌的](#reviewer-roulette)建议进行操作. + +可以在[工程项目](https://about.gitlab.com/handbook/engineering/projects/)页面或[GitLab 团队页面](https://about.gitlab.com/company/team/)上查看团队成员的领域专业知识. + +### Reviewer roulette[](#reviewer-roulette "Permalink") + +[Danger 机器人会](dangerbot.html)为您的合并请求似乎接触的每个代码库区域随机选择一个审阅者和一个维护者. 它仅提出**建议** ,如果您认为其他人更适合,则应予以覆盖! + +它从[工程项目](https://about.gitlab.com/handbook/engineering/projects/)页面的列表中选择审阅者和维护者,具有以下行为: + +1. 它不会选择[GitLab 状态](../user/profile/index.html#current-status)包含字符串'OOO'或表情符号为`:palm_tree:`或`:beach:` . +2. [培训生的维护者](https://about.gitlab.com/handbook/engineering/workflow/code-review/#trainee-maintainer)被[选拔的](https://about.gitlab.com/handbook/engineering/workflow/code-review/#trainee-maintainer)可能性是其他审阅者的三倍. +3. 它始终为相同的分支名称选择相同的审阅者和维护者(除非他们的 OOO 状态更改,如第 1 点所示). 它消除导致`ce-`和`ee-`和尾`-ce`和`-ee` ,以便它可以为反向移植分支稳定. + +### Approval guidelines[](#approval-guidelines "Permalink") + +如下面有关维护者职责的部分所述,建议您让合并请求由具有[域专业知识的](#domain-experts)维护者批准并合并. + +1. 如果您的合并请求包含后端更改( *1* ),则必须**由[后端维护者](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_backend)批准** . +2. 如果您的合并请求包括数据库迁移或对昂贵查询的更改( *2* ),则必须得到**[数据库维护者的](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_database)批准** . 阅读[数据库复查指南](database_review.html)以获取更多详细信息. +3. 如果您的合并请求包含前端更改( *1* ),则必须得到**[前端维护者的](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_frontend)批准** . +4. 如果您的合并请求包括用户体验更改( *1* ),则必须得到用户**[体验团队成员的](https://about.gitlab.com/company/team/)批准** . +5. 如果您的合并请求包括添加新的 JavaScript 库( *1* ),则必须得到**[前端领导的](https://about.gitlab.com/company/team/)批准** . +6. 如果您的合并请求包括添加新的 UI / UX 范例( *1* ),则必须**由[UX 主管](https://about.gitlab.com/company/team/)批准** . +7. 如果您的合并请求包含新的依赖项或文件系统更改,则必须得到**[分发团队成员的](https://about.gitlab.com/company/team/)批准** . 有关更多详细信息,请参见如何与[发行团队](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/#how-to-work-with-distribution)合作. +8. 如果您的合并请求中包含文档更改,则必须根据相应的[产品类别](https://about.gitlab.com/handbook/product/product-categories/) **由[技术撰稿人](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers)批准** . +9. 如果您的合并请求包含端到端**和**非端到端更改( *3* ),则必须**经过[测试中](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors)的[软件工程师的](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors)批准** . +10. 如果您的合并请求仅包含端到端更改( *3* ), **或者**如果 MR 作者是[测试中](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors)的[软件工程师](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) ,则必须得到**[质量维护人员的](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa)批准** + +* ( *1* ):请注意,除 JavaScript 规范以外的其他规范均被视为后端代码. +* ( *2* ):如果您的合并请求可能引入昂贵的查询,我们鼓励您从数据库维护者那里寻求指导. 用 SQL 查询在相关代码行中注释是最有效的,这样他们就可以给出建议. +* ( *3* ):端到端更改包括`qa`目录中的所有文件. + +#### Security requirements[](#security-requirements "Permalink") + +View the updated documentation regarding [internal application security reviews](https://about.gitlab.com/handbook/engineering/security/#internal-application-security-reviews) for **when** and **how** to request a security review. + +### The responsibility of the merge request author[](#the-responsibility-of-the-merge-request-author "Permalink") + +找到最佳解决方案并实施该解决方案的责任在于合并请求作者. + +在将合并请求分配给维护者进行批准和合并之前,他们应该确信: + +* 它实际上解决了本应解决的问题. +* 它以最合适的方式这样做. +* 满足所有要求. +* 没有剩余的错误,逻辑问题,未发现的极端情况或已知的漏洞. + +做到这一点并避免与审阅者不必要的来回交流的最佳方法是,按照[代码审阅](#reviewing-a-merge-request)指南对自己的合并请求进行自审. + +为了使他们的解决方案达到所需的置信度,作者应酌情让其他人参与调查和实施过程. + +鼓励他们与[领域专家联系](#domain-experts) ,讨论不同的解决方案或对实现进行审查,与产品经理和 UX 设计师联系,以消除混乱或验证最终结果是否与他们的想法相符,并与数据库专家联系,以获取有关数据模型或特定查询,或者让任何其他开发人员深入了解该解决方案. + +如果作者不确定合并请求是否需要[领域专家的](#domain-experts)意见,这通常是一个很好的信号,因为如果没有合并请求,将无法达到他们对解决方案所要求的置信度. + +在审阅之前,请作者针对合并请求差异提交评论,以提醒审阅者重要的事项以及需要进一步解释或关注的事项. 可能需要发表评论的内容示例包括: + +* 增加了起毛规则(Rubocop,JS 等). +* 增加了一个库(Ruby gem,JS lib 等). +* 如果不明显,则指向父类或方法的链接. +* 进行任何基准测试以补充变更. +* 潜在的不安全代码. + +Avoid: + +* 除非审阅者要求您将注释(上面引用的或 TODO 项)直接添加到源代码中. 如果由于可执行的任务而添加了注释,则必须包含指向问题的链接. +* 将测试失败的合并请求分配给维护人员. 如果测试失败,则必须分配,请确保在评论中留下说明. +* 通过电子邮件或 Slack 过多提及维护者(如果可以通过 Slack 与维护者联系). 如果您不能分配合并请求,则`@`可以在注释中提及维护者,在所有其他情况下,分配合并请求就足够了. + +This [saves reviewers time and helps authors catch mistakes earlier](https://www.ibm.com/developerworks/rational/library/11-proven-practices-for-peer-review/index.html#__RefHeading__97_174136755). + +### The responsibility of the reviewer[](#the-responsibility-of-the-reviewer "Permalink") + +彻底[检查合并请求](#reviewing-a-merge-request) . 当您确信它满足所有要求时,您应该: + +* Click the Approve button. +* 告知作者他们的合并请求已经过审核和批准. +* 将合并请求分配给维护者. 默认情况下,将其分配给具有[领域专业知识](#domain-experts)的维护者,但是,如果不可用,或者您认为合并请求不需要[领域专家](#domain-experts)的审查,请随时遵循" [审阅者"轮盘赌的](#reviewer-roulette)建议. + +### The responsibility of the maintainer[](#the-responsibility-of-the-maintainer "Permalink") + +维护人员负责跨领域和产品领域的 GitLab 代码库的总体运行状况,质量和一致性. + +因此,他们的审查将主要集中在总体架构,代码组织,关注点分离,测试,DRYness,一致性和可读性等方面. + +由于维护人员的工作仅取决于他们对整个 GitLab 代码库的了解,而不取决于任何特定领域的知识,因此他们可以查看,批准和合并来自任何团队和任何产品领域的合并请求. + +维护人员将尽最大努力在合并之前检查所选解决方案的详细信息,但是由于他们不一定是[领域专家](#domain-experts) ,因此他们可能没有太多时间来浪费很多时间. 在这种情况下,他们将服从作者和早期审稿人的判断,而将精力放在他们的主要职责上. + +如果维护者认为 MR 足够重要,足以保证需要由[域专家](#domain-experts)进行审查,并且目前尚不清楚域专家是否参与了审查,则他们可以在合并 MR 之前要求[域专家进行](#domain-experts)审查. + +如果恰好也是维护者的开发人员作为审阅者参与了合并请求,则建议不要同时选择他们作为维护者来最终批准并合并它. + +维护人员应在合并之前检查合并请求是否已被所需批准者批准. + +维护人员必须在合并之前检查合并请求[安全性小部件中](../user/application_security/index.html)的列表,以检查合并请求是否引入了新的漏洞. 如有疑问,可以请[安全工程师](https://about.gitlab.com/company/team/)参与. 检测到的漏洞列表必须为空或包含以下内容: + +* 在出现误报的情况下消除漏洞 +* 漏洞转化为问题 + +维护人员**切勿**在没有适当验证的情况下消除漏洞以"清空"列表. + +请注意,某些合并请求可能会针对稳定分支. 这些是罕见的事件. 维护者无法合并这些类型的合并请求. 相反,这些应该发送到[版本管理器](https://about.gitlab.com/community/release-managers/) . + +## Best practices[](#best-practices "Permalink") + +### Everyone[](#everyone "Permalink") + +* 善待. +* 接受许多编程决策是意见. 讨论您喜欢的折衷方案,并迅速解决. +* 问问题; 不要提出要求. ("您如何命名这个`:user_id` ?") +* 要求澄清. ("我听不懂.您能澄清一下吗?") +* 避免有选择地拥有代码. ("我的","不是我的","您的") +* 避免使用可能被视为涉及个人特质的术语. ("哑巴","愚蠢"). 假设每个人都是有吸引力,聪明和善良的. +* 要明确. 请记住,人们并不总是在线了解您的意图. +* 要谦虚. ("我不确定-让我们看一下.") +* 不要夸张. ("始终","从不","无限","无") +* 使用讽刺时要小心. 我们所做的一切都是公开的; 对于您和长期的同事而言,似乎很老套的话可能会很卑鄙,不欢迎新加入该项目的人. +* 如果"我听不懂"或"替代解决方案:"注释过多,请考虑一对一聊天或视频通话. 发表后续评论,总结一对一的讨论. +* 如果您向特定人员提出问题,请务必先提及他们,然后再开始评论; 如果将通知级别设置为"提及",这将确保他们看到该消息,并且其他人将理解他们不必响应. + +### Having your merge request reviewed[](#having-your-merge-request-reviewed "Permalink") + +请记住,代码审阅是一个可能需要多次迭代的过程,审阅者可能会在以后发现他们第一次看不到的东西. + +* 您的代码的第一位审阅者是*you* . 在对闪亮的新分支进行第一次推送之前,请通读整个差异. 是否有意义? 您是否包含与变更的总体目的无关的内容? 您是否忘记删除任何调试代码? +* 感谢审阅者的建议. ("好电话.我会进行更改.") +* 不要亲自去做. 审阅的是代码,而不是您的. +* 说明代码为何存在. ("由于这些原因就这样.如果重命名这个类/文件/方法/变量,是否更清楚?") +* 将不相关的更改和重构提取到将来的合并请求/问题中. +* 试图了解审稿人的观点. +* 尝试回应每个评论. +* 合并请求作者仅解析他们已完全解决的线程. 如果有公开的答复,公开的话题,建议,问题或其他任何内容,则该话题应留待审阅者解决. +* 不应假定所有反馈都要求在合并之前将其建议的更改合并到 MR 中. 这是 MR 作者和审阅者对是否需要这样做的判断,或者是在合并有问题的 MR 之后是否应创建后续问题以解决将来的反馈. +* 基于较早回馈的推送提交作为对分支的独立提交. 在分支准备好合并之前,请勿压扁. 审阅者应该能够根据他们先前的反馈来阅读各个更新. +* 准备好进行另一轮审核后,将合并请求分配回审核者. 如果您无法分配合并请求,请`@`提及审阅者. + +### Assigning a merge request for a review[](#assigning-a-merge-request-for-a-review "Permalink") + +准备好要审核合并请求时,默认应将其分配给小组或团队中的审阅者以进行第一次审阅,但是,您也可以将其分配给任何审阅者. 审阅者列表可以在" [工程项目"](https://about.gitlab.com/handbook/engineering/projects/)页面上找到. + +You can also use `workflow::ready for review` label. That means that your merge request is ready to be reviewed and any reviewer can pick it. It is recommended to use that label only if there isn’t time pressure and make sure the merge request is assigned to a reviewer. + +在审核合并请求并将其传递给维护者后,您应该默认选择具有[领域专业知识](#domain-experts)的维护者,否则应遵循 Reviewer Roulette 的建议或使用`ready for merge`的标签. + +合并请求的作者有责任审查合并请求. 如果`ready for review`状态太长时间,建议将其分配给特定的审阅者. + +#### List of merge requests ready for review[](#list-of-merge-requests-ready-for-review "Permalink") + +有能力的开发人员可以定期检查[合并请求](https://gitlab.com/groups/gitlab-org/-/merge_requests?state=opened&label_name[]=workflow::ready for review)列表[以进行审核,](https://gitlab.com/groups/gitlab-org/-/merge_requests?state=opened&label_name[]=workflow::ready for review)并分配他们要审核的任何合并请求. + +### Reviewing a merge request[](#reviewing-a-merge-request "Permalink") + +了解为什么需要进行更改(修复错误,改善用户体验,重构现有代码). 然后: + +* 尝试在您的评论中做到周密,以减少迭代次数. +* 交流您对哪些想法有强烈的想法,而哪些想法则没有. +* 确定在解决问题的同时简化代码的方法. +* 提供替代的实现,但是假设作者已经考虑了它们. ("您在这里对使用自定义验证器有何看法?") +* 试图了解作者的观点. +* 如果您不懂一段代码,请*这样说* . 很有可能其他人也会对此感到困惑. +* 确保作者清楚他们需要什么来解决/解决该建议. + * 考虑使用[常规注释格式](https://conventionalcomments.org#format)来传达您的意图. + * 对于非强制性建议,请使用(非阻塞)修饰,以便作者知道可以选择在合并请求中解决该问题,或者在以后进行后续操作. +* 经过几行注释后,发布摘要注释(例如"对我很好"或"仅几件要解决的问题")会很有帮助. +* 如果审阅后需要更改,则将合并请求分配给作者. + +### Merging a merge request[](#merging-a-merge-request "Permalink") + +在决定合并之前: + +* 设置里程碑. +* 考虑来自危险漫游器,代码质量和其他报告的警告和错误. 除非有充分的理由证明违规,否则应在合并前解决这些问题. 如果 MR 与任何失败的作业合并,则必须发布评论. +* 如果 MR 既包含与质量相关的变更,又包含与非质量无关的变更,则应由相关维护人员合并 MR,以便在测试中软件工程师批准与质量相关的变更后,将其面向用户的变更(后端,前端或数据库). + +如果合并请求从根本上准备就绪,但仅需要简单的修正(例如拼写错误),则可以考虑通过直接进行更改而不向作者证明是[对行动](https://about.gitlab.com/handbook/values/#bias-for-action)的[偏见](https://about.gitlab.com/handbook/values/#bias-for-action) . 您可以通过使用" [建议更改"](../user/discussions/index.html#suggest-changes)功能将自己的建议应用于合并请求来实现. 注意: + +* 如果更改不直接,请优先将合并请求分配回作者. +* **在应用建议之前** ,请编辑合并请求以确保启用了[压缩和合并](../user/project/merge_requests/squash_and_merge.html#squash-and-merge) ,否则,管道的"危险"作业将失败. + * 如果合并请求未启用压缩和合并,并且具有多个提交,则请参阅以下有关重写提交历史记录的注释. + +准备合并时: + +* 当合并请求包含大量提交时,请考虑使用[Squash 和合并](../user/project/merge_requests/squash_and_merge.html#squash-and-merge)功能. 合并代码时,维护者仅应在作者已设置此选项或合并请求中明确包含要压缩的混乱提交历史记录时使用 squash 功能. +* **使用合并请求的"管道"选项卡中的" `Run Pipeline`按钮启动新的合并请求管道,并启用"管道成功时合并"(MWPS).** 注意: + * 如果**最新[的合并结果管道](../ci/merge_request_pipelines/pipelines_for_merged_results/#pipelines-for-merged-results-premium)**不到 2 小时前完成,则由于合并请求足够接近`master` ,您可能无需启动新管道就可以合并. + * 如果**合并请求来自 fork** ,则我们不能将[管道用于合并结果](../ci/merge_request_pipelines/pipelines_for_merged_results/index.html#prerequisites) ,因此,它们更容易破坏`master` . 检查源分支在`master` . 如果超过 100 次提交,请在合并之前要求作者重新设置基础. + * 如果[master 已损坏](https://about.gitlab.com/handbook/engineering/workflow/#broken-master) ,除了上述两个规则外,请检查`master`是否也发生任何故障,并在单击红色的" Merge"(合并)按钮之前发布指向〜" master:broken"问题的链接. +* 当将 MR 设置为"管道成功合并时"时,您应该接管后续修订,以应对之后发现的所有问题. + +**注意:**感谢"合并结果管道",由于合并结果管道已经合并了`master`的最新更改,因此作者不必再频繁地重新建立分支基础(仅当发生冲突时). 由于维护人员不必要求最终的重新定基,因此可以加快审核/合并周期:相反,他们只需要启动 MR 管道并设置 MWPS. 通过在创建管道时针对最新`master`测试合并结果,此步骤使我们非常接近实际的合并训练功能. + +### The right balance[](#the-right-balance "Permalink") + +在代码审查期间,最困难的事情之一是在审查者可以干扰作者创建的代码的深度上找到适当的平衡. + +* 学习如何找到合适的平衡点需要花费时间. 这就是为什么我们花了一些时间审核合并请求后使审核员成为维护者的原因. +* 查找错误很重要,但是考虑良好的设计也很重要. 建立抽象和良好的设计可以隐藏复杂性并使将来的更改变得容易. +* 强制和改进[代码样式](contributing/style_guides.html)应主要通过[自动化](https://about.gitlab.com/handbook/values/#cleanup-over-sign-off)而不是评论注释来完成. +* 要求作者更改设计有时意味着完全重写贡献的代码. 通常,在进行此操作之前先询问其他维护者或审阅者是一个好主意,但是当您认为重要时,要有勇气去做. +* 为了[Iteration](https://about.gitlab.com/handbook/values/#iteration)的利益,如果您的审查建议是非阻塞性更改或个人喜好(不是书面或约定的要求),请考虑批准合并请求,然后再将其传递回作者. 如果他们同意,这将使他们能够实施您的建议,或者使他们立即将其传递给维护者以供审核. 这可以帮助减少我们的整体合并时间. +* 做正确的事和立即做事有区别. 理想情况下,我们应该做前者,但在现实世界中,我们也需要后者. 一个很好的例子是安全修复程序,应尽快发布. 应该避免要求作者在合并请求中进行重大重构,这是一个紧急解决方案. +* 今天做好事通常比明天做好事更好. 今天运送垃圾通常比明天做好事更糟. 当您找不到合适的平衡时,请向其他人询问他们的意见. + +### GitLab-specific concerns[](#gitlab-specific-concerns "Permalink") + +GitLab 在很多地方都使用过. 许多用户使用我们的[Omnibus 软件包](https://about.gitlab.com/install/) ,但有些用户使用[Docker 映像](https://docs.gitlab.com/omnibus/docker/) ,有些是[从源代码安装的](../install/installation.html) ,还有其他可用的安装方法. GitLab.com 本身是一个大型企业版实例. 这有一些含义: + +1. 应该对**查询更改**进行测试,以确保在 GitLab.com 规模上不会导致性能下降: + 1. 在本地生成大量数据会有所帮助. + 2. 从 GitLab.com 询问查询计划是验证这些计划的最可靠方法. +2. **数据库迁移**必须是: + 1. 可逆的. + 2. 性能达到 GitLab.com 的规模-如果不确定,请维护人员在登台环境中测试迁移. + 3. 正确分类: + * 常规迁移在新代码在实例上运行之前运行. + * 将实例配置为执行新[部署](post_deployment_migrations.html) *后* ,便会进行部署*后* [迁移](post_deployment_migrations.html) . + * [后台迁移](background_migrations.html)在 Sidekiq 中运行,并且仅应在 GitLab.com 规模上花费大量时间进行迁移. +3. **Sidekiq 工人** [cannot change in a backwards-incompatible way](sidekiq_style_guide.html#sidekiq-compatibility-across-updates): + 1. 在部署发生之前,不会耗尽 Sidekiq 队列,因此队列中会有来自上一版 GitLab 的工作线程. + 2. 如果需要更改方法签名,请尝试在两个版本中进行更改,并在第一个版本中同时接受新旧参数. + 3. 同样,如果您需要删除一个工作程序,请停止在一个版本中计划它,然后在下一个版本中将其删除. 这将允许现有作业执行. + 4. Don’t forget, not every instance will upgrade to every intermediate version (some people may go from X.1.0 to X.10.0, or even try bigger upgrades!), so try to be liberal in accepting the old format if it is cheap to do so. +4. **缓存的值**可能会在各个发行版中持续存在. 如果要更改缓存值返回的类型(例如,从字符串或 nil 到数组),请同时更改缓存键. +5. **设置**应作为[最后的手段](https://about.gitlab.com/handbook/product/#convention-over-configuration)添加. 如果要在`gitlab.yml`添加新设置: + 1. 尝试避免这种情况,而是添加到`ApplicationSetting` . + 2. 确保它也已[添加到 Omnibus 中](https://docs.gitlab.com/omnibus/settings/gitlab.yml.html) . +6. **文件系统访问**可能很慢,因此,在有替代解决方案可用时,请尝试避免[共享文件](shared_files.html) . + +### Review turnaround time[](#review-turnaround-time "Permalink") + +由于[取消阻止其他人始终是头等大事](https://about.gitlab.com/handbook/values/#global-optimization) ,因此,即使这可能会对他们的其他任务和优先事项产生不利影响,审阅者也应及时查看分配的合并请求. + +这样做使合并请求中涉及的每个人都可以在上下文处于内存中新鲜时更快地进行迭代,并显着改善了贡献者的体验. + +#### Review-response SLO[](#review-response-slo "Permalink") + +为了确保快速反馈到准备就绪的代码,我们维护了一个`Review-response`服务级别目标(SLO). SLO 定义为: + +> * 审核响应 SLO =(提供第一次审核响应的时间)-(将 MR 分配给审核者的时间)<2 个工作日 + +如果您认为您无法在" `Review-response` SLO 期限内审阅合并请求,请让作者尽快知道,并尝试帮助他们找到其他能够审阅的审阅者或维护者,因此他们可以畅通无阻,并迅速开始工作. + +如果您认为自己有能力并且在完成一些评论之前无法接受其他评论,请通过设置`:red_circle:`表情符号并在状态文本中提及您有能力,通过 GitLab 状态传达此信息. 这将指导撰稿人选择其他审稿人,从而帮助我们满足 SLO. + +当然,如果您不在办公室并且已通过 GitLab.com 状态[传达了](https://about.gitlab.com/handbook/paid-time-off/#communicating-your-time-off)此信息,则作者应意识到这一点,并自己找一位不同的审稿人. + +当合并请求作者的阻止时间超过`Review-response` SLO 时,他们可以自由地通过 Slack 提醒审阅者或分配其他审阅者. + +### Customer critical merge requests[](#customer-critical-merge-requests "Permalink") + +合并请求可能会因为被视为客户关键优先级而受益,因为这样做会使企业受益匪浅. + +客户关键合并请求的属性: + +* [发展高级总监](https://about.gitlab.com/job-families/engineering/engineering-management/#senior-director-engineering) ( [](https://gitlab.com/clefelhocz1)[@ clefelhocz1](https://gitlab.com/clefelhocz1) )是用于确定合并请求是否对客户至关重要的 DRI. +* DRI 将`customer-critical-merge-request`标签分配给合并请求. +* 要求与客户关键合并请求相关的审阅者和维护者一经做出此决定,便立即参与. +* 需要优先处理涉及客户关键合并请求的人员的工作,以便他们有足够的时间专注于此. +* 在处理客户关键的合并请求时,必须遵守 GitLab 的[价值观](https://about.gitlab.com/handbook/values/)和流程,首先要特别注意家人和朋友,其次要注意,完成的定义,迭代以及准备就绪时发布. +* 需要客户关键的合并请求,以免降低安全性,引入数据丢失风险,降低可用性或破坏每个流程的现有功能,从而[优先考虑技术决策](https://about.gitlab.com/handbook/engineering/#prioritizing-technical-decisions.md) . +* 对于客户的关键请求,如果他们认为这将减少花费的合并时间(即使这*可能*会降低[效率](https://about.gitlab.com/company/culture/all-remote/asynchronous/#evaluating-efficiency.md) ),则*建议*相关人员*考虑*除了异步(合并请求注释)之外,还同步进行协调(Zoom,Slack). +* 合并客户关键合并请求后,必须完成回顾,以减少将来的客户关键合并请求的频率. + +## Examples[](#examples "Permalink") + +如何进行代码审查可能会使新的参与者感到惊讶. 以下是一些代码审查示例,它们可以帮助您确定期望的方向. + +**["修改`DiffNote`以便将其重新用于设计"](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/13703) :**它包含了从换行符转折点到设计版本的推理,如果没有某个文件的先前版本,我们应该如何比较它们的所有内容(父级 vs.空白`sha`空白树) ). + +**["支持多行建议"](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25211)** :MR 本身由 FE 和 BE 之间的协作组成,并记录了作者对审阅者的评论. 有一些缺点,一些有关信息的问题,最后还有一个安全漏洞. + +**["每个项目允许有多个存储库"](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10251)** :ZJ 提到了这可能会影响的其他项目(工作马),并建议进行一些改进以保持一致性. James 的评论帮助我们提高了整体代码质量(使用委派`&.`这些类型的事情),并使代码更加健壮. + +**["支持多个受让人进行合并请求"](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10161)** :MR 接触代码库多个部分的一个很好的示例. 尼克指出了一些有趣的例子,詹姆斯·洛佩兹(James Lopez)也加入了对进出口功能的关注. + +### Credits[](#credits "Permalink") + +很大程度上基于[thinkbot 代码的审查指南](https://github.com/thoughtbot/guides/tree/master/code-review) . + +* * * + +[Return to Development documentation](README.html) \ No newline at end of file diff --git a/docs/557.md b/docs/557.md new file mode 100644 index 0000000000000000000000000000000000000000..1ff98eef09520dba1ae4bebb583c654a15cd25f4 --- /dev/null +++ b/docs/557.md @@ -0,0 +1,104 @@ +# Style guides + +> 原文:[https://docs.gitlab.com/ee/development/contributing/style_guides.html](https://docs.gitlab.com/ee/development/contributing/style_guides.html) + +* [Editor/IDE styling standardization](#editoride-styling-standardization) +* [Pre-commit static analysis](#pre-commit-static-analysis) +* [Ruby, Rails, RSpec](#ruby-rails-rspec) + * [Creating new RuboCop cops](#creating-new-rubocop-cops) +* [Database migrations](#database-migrations) +* [JavaScript](#javascript) +* [SCSS](#scss) +* [Go](#go) +* [Shell commands (Ruby)](#shell-commands-ruby) +* [Shell scripting](#shell-scripting) +* [Markdown](#markdown) +* [Documentation](#documentation) +* [Python](#python) +* [Misc](#misc) + +# Style guides[](#style-guides "Permalink") + +## Editor/IDE styling standardization[](#editoride-styling-standardization "Permalink") + +在将文件保存到本地之前,我们使用[EditorConfig](https://editorconfig.org/)自动应用某些样式标准. 默认情况下,大多数编辑器/ IDE 都会自动接受`.editorconfig`设置. 如果您的编辑器/ IDE 不自动支持`.editorconfig` ,建议您进行调查以查看是否存在插件. 例如,这里是[vim](https://github.com/editorconfig/editorconfig-vim)的[插件](https://github.com/editorconfig/editorconfig-vim) . + +## Pre-commit static analysis[](#pre-commit-static-analysis "Permalink") + +强烈建议您安装[Overcommit](https://github.com/sds/overcommit) ,以便在本地提交之前自动检查静态分析违规. + +在您的 GitLab 源目录中运行: + +``` +make -C tooling/overcommit +``` + +Then before a commit is created, Overcommit will automatically check for RuboCop (and other checks) offenses on every modified file. + +这样可以节省您的时间,因为您不必等待配置项检测到相同的错误. + +过量提交依赖于预提交钩子,以防止违反其规则集的提交. 如果您想覆盖此行为,可以通过传递 ENV 变量`OVERCOMMIT_DISABLE`来完成. 即`OVERCOMMIT_DISABLE=1 git rebase master`在禁用 Git 钩子的同时进行 rebase. + +## Ruby, Rails, RSpec[](#ruby-rails-rspec "Permalink") + +我们的代码库样式由[RuboCop](https://github.com/rubocop-hq/rubocop)定义和执行. + +您可以使用`bundle exec rubocop --parallel`在本地检查任何违规行为. 在配置项上,这将由`static-analysis`作业自动检查. + +对于尚未决定的 RuboCop 规则,我们遵循[Ruby Style Guide](https://github.com/rubocop-hq/ruby-style-guide) , [Rails Style Guide](https://github.com/rubocop-hq/rails-style-guide)和[RSpec Style Guide](https://github.com/rubocop-hq/rspec-style-guide)作为编写惯用 Ruby / Rails / RSpec 的通用准则,但是审阅者/维护者应该宽容而不是太宽容关于风格的书呆子. + +同样,当前已禁用某些 RuboCop 规则,对于这些规则,审阅者/维护者不得要求作者使用一种或另一种样式,因为这两种样式均被接受. 这不是理想的情况,因为这为[骑车](https://en.wiktionary.org/wiki/bikeshedding)留下了空间,并且理想情况下,我们应该启用所有 RuboCop 规则,以避免在评论中进行与样式相关的讨论/挑剔/来回. + +此外,我们还有专门的[换行样式指南](../newlines_styleguide.html) ,以及专门针对[测试的样式指南和最佳实践](../testing_guide/index.html) . + +### Creating new RuboCop cops[](#creating-new-rubocop-cops "Permalink") + +通常,最好通过编程方式执行起毛规则,因为它可以减少前述的[自行车脱落](https://en.wiktionary.org/wiki/bikeshedding) . + +为此,我们鼓励在代码库中创建新的 RuboCop 规则. + +当创建可以应用于多个应用程序的新警察时,我们建议您将其添加到我们的[GitLab Styles](https://gitlab.com/gitlab-org/gitlab-styles)宝石中. + +## Database migrations[](#database-migrations "Permalink") + +请参阅专用的《 [数据库迁移样式指南》](../migration_style_guide.html) . + +## JavaScript[](#javascript "Permalink") + +请参阅专用的[JS 样式指南](../fe_guide/style/javascript.html) . + +## SCSS[](#scss "Permalink") + +请参阅专用的[SCSS 样式指南](../fe_guide/style/scss.html) . + +## Go[](#go "Permalink") + +请参阅专用的[Go 标准和样式指南](../go_guide/index.html) . + +## Shell commands (Ruby)[](#shell-commands-ruby "Permalink") + +请参阅[GitLab 代码库中有关 shell 命令](../shell_commands.html)的专用[准则](../shell_commands.html) . + +## Shell scripting[](#shell-scripting "Permalink") + +请参阅专用的[Shell 脚本标准和样式指南](../shell_scripting_guide/index.html) . + +## Markdown[](#markdown "Permalink") + +我们正在遵循[Ciro Santilli 的 Markdown 样式指南](https://cirosantilli.com/markdown-style-guide/) . + +## Documentation[](#documentation "Permalink") + +请参阅专用的[文档样式指南](../documentation/styleguide.html) . + +## Python[](#python "Permalink") + +请参阅专用的[Python 开发指南](../python_guide/index.html) . + +## Misc[](#misc "Permalink") + +代码应使用[美国英语](https://en.wikipedia.org/wiki/American_English)书写. + +* * * + +[Return to Contributing documentation](index.html) \ No newline at end of file diff --git a/docs/558.md b/docs/558.md new file mode 100644 index 0000000000000000000000000000000000000000..4878c49a0da8812f4b4eedec8ff4c5802e6f6a5d --- /dev/null +++ b/docs/558.md @@ -0,0 +1,799 @@ +# GitLab Architecture Overview + +> 原文:[https://docs.gitlab.com/ee/development/architecture.html](https://docs.gitlab.com/ee/development/architecture.html) + +* [Software delivery](#software-delivery) +* [Components](#components) + * [Simplified Component Overview](#simplified-component-overview) + * [Component diagram](#component-diagram) + * [Component legend](#component-legend) + * [Component list](#component-list) + * [Component details](#component-details) + * [Alertmanager](#alertmanager) + * [Certificate management](#certificate-management) + * [Consul](#consul) + * [Database migrations](#database-migrations) + * [Elasticsearch](#elasticsearch) + * [Gitaly](#gitaly) + * [Praefect](#praefect) + * [GitLab Geo](#gitlab-geo) + * [GitLab Exporter](#gitlab-exporter) + * [GitLab Pages](#gitlab-pages) + * [GitLab Runner](#gitlab-runner) + * [GitLab Shell](#gitlab-shell) + * [GitLab Workhorse](#gitlab-workhorse) + * [Grafana](#grafana) + * [Jaeger](#jaeger) + * [Logrotate](#logrotate) + * [Mattermost](#mattermost) + * [MinIO](#minio) + * [NGINX](#nginx) + * [Node Exporter](#node-exporter) + * [PgBouncer](#pgbouncer) + * [PgBouncer Exporter](#pgbouncer-exporter) + * [PostgreSQL](#postgresql) + * [PostgreSQL Exporter](#postgresql-exporter) + * [Prometheus](#prometheus) + * [Redis](#redis) + * [Redis Exporter](#redis-exporter) + * [Registry](#registry) + * [Sentry](#sentry) + * [Sidekiq](#sidekiq) + * [Unicorn](#unicorn) + * [LDAP Authentication](#ldap-authentication) + * [Outbound Email](#outbound-email) + * [Inbound Email](#inbound-email) + * [GitLab Managed Apps](#gitlab-managed-apps) +* [GitLab by Request Type](#gitlab-by-request-type) + * [GitLab Web HTTP Request Cycle](#gitlab-web-http-request-cycle) + * [GitLab Git Request Cycle](#gitlab-git-request-cycle) + * [Web Request (80/443)](#web-request-80443) + * [SSH Request (22)](#ssh-request-22) +* [System Layout](#system-layout) + * [Installation Folder Summary](#installation-folder-summary) + * [Processes](#processes) + * [Repository access](#repository-access) +* [Troubleshooting](#troubleshooting) + * [Init scripts of the services](#init-scripts-of-the-services) + * [Log locations of the services](#log-locations-of-the-services) + * [GitLab specific configuration files](#gitlab-specific-configuration-files) + * [Maintenance Tasks](#maintenance-tasks) +* [GitLab.com](#gitlabcom) + +# GitLab Architecture Overview[](#gitlab-architecture-overview "Permalink") + +## Software delivery[](#software-delivery "Permalink") + +GitLab 有两种软件发行[版](https://gitlab.com/gitlab-org/gitlab-foss/) :开源[社区版](https://gitlab.com/gitlab-org/gitlab-foss/) (CE)和开放核心[企业版](https://gitlab.com/gitlab-org/gitlab/) (EE). GitLab 在[不同的订阅下](https://about.gitlab.com/pricing/)可用. + +GitLab 的新版本在稳定的分支中发布,而 master 分支则用于前沿开发. + +有关信息,请参见[GitLab 发布过程](https://gitlab.com/gitlab-org/release/docs/-/tree/master#gitlab-release-process) . + +EE 和 CE 都需要一些名为 GitLab Shell 和 Gitaly 的附加组件. 这些组件分别可从[GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell/-/tree/master)和[Gitaly](https://gitlab.com/gitlab-org/gitaly/-/tree/master)存储库中获得. 新版本通常是标签,但是停留在 master 分支上将为您提供最新的稳定版本. 新版本通常与 GitLab CE 发布大约相同的时间,但非正式的安全更新被认为很重要. + +## Components[](#components "Permalink") + +A typical install of GitLab will be on GNU/Linux. It uses NGINX or Apache as a web front end to proxypass the Unicorn web server. By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and pre-compiled assets. GitLab serves web pages and the [GitLab API](../api/README.html) using the Unicorn web server. It uses Sidekiq as a job queue which, in turn, uses Redis as a non-persistent database backend for job information, meta data, and incoming jobs. + +我们还支持使用我们的[GitLab Helm 图表](https://docs.gitlab.com/charts/)在 Kubernetes 上部署 GitLab. + +GitLab Web 应用程序将 PostgreSQL 用于持久数据库信息(例如,用户,权限,问题,其他元数据). GitLab 默认将其服务的裸 Git 存储库存储在`/home/git/repositories` . 它还使用裸存储库保留默认的分支和挂钩信息. + +通过 HTTP / HTTPS 提供存储库时,GitLab 利用 GitLab API 来解析授权和访问以及提供 Git 对象. + +附加组件 GitLab Shell 通过 SSH 提供存储库. 它管理`/home/git/.ssh/authorized_keys`的 SSH 密钥,不应手动对其进行编辑. GitLab Shell 通过 Gitaly 访问裸仓库以提供 Git 对象,并与 Redis 进行通信以将作业提交给 Sidekiq,以供 GitLab 处理. GitLab Shell 查询 GitLab API 以确定授权和访问权限. + +Gitaly 从 GitLab Shell 和 GitLab Web 应用程序执行 Git 操作,并向 GitLab Web 应用程序提供 API,以从 Git 获取属性(例如标题,分支,标签,其他元数据),并获取 Blob(例如 diff,commit,文件). + +您可能也[对 GitLab.com](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/)的[生产体系结构感兴趣](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/) . + +### Simplified Component Overview[](#simplified-component-overview "Permalink") + +这是一个简化的架构图,可用于了解 GitLab 的架构. + +下面的[组件图](#component-diagram)中提供了完整的架构图. + +[![Simplified Component Overview](img/7ddc19b18c20bfa78acb7fe9dd2ede4b.png)](img/architecture_simplified.png) + +### Component diagram[](#component-diagram "Permalink") + +图 TB HTTP [HTTP / HTTPS]-TCP 80、443-> NGINX [NGINX] SSH-TCP 22-> GitLabShell [GitLab Shell] SMTP [SMTP Gateway] Geo [GitLab Geo Node]-TCP 22, 80,443-> NGINX GitLabShell --TCP 8080-> Unicorn [" Unicorn(GitLab Rails)"] GitLabShell-> Praefect GitLabShell-> Redis Unicorn-> PgBouncer [PgBouncer] Unicorn-> Redis Unicorn- -> Praefect Sidekiq-> Redis Sidekiq-> PgBouncer Sidekiq-> Praefect GitLabWorkhorse [GitLab Workhorse]-> Unicorn GitLabWorkhorse-> Redis GitLabWorkhorse-> Praefect Praefect-> Gitaly NGINX-> GitLabWorkhorse NGINX- TCP 8090-> GitLabPages [GitLab 页面] NGINX-> Grafana [Grafana] Grafana-TCP 9090-> Prometheus [Prometheus] Prometheus-TCP 80,443-> Unicorn RedisExporter [Redis Exporter]-> Redis Prometheus-TCP 9121-> RedisExporter PostgreSQLExporter [PostgreSQL 导出器]-> PostgreSQL PgBouncerExporter [PgBouncer 导出器]-> PgBouncer Prometheus-TCP 9187-> PostgreSQLExporter Prometheus-TCP 9100-> NodeExporter [Node Exp orter] Prometheus-TCP 9168-> GitLabExporter [GitLab Exporter] Prometheus-TCP 9127-> PgBouncerExporter GitLabExporter-> PostgreSQL GitLabExporter-> GitLabShell GitLabExporter-> Sidekiq PgBouncer-> Consul PostgreSQL-> Consul PgBouncer -> PostgreSQL NGINX->注册表 Unicorn->注册表 NGINX-> Mattermost Mattermost --- Unicorn Prometheus-> Alertmanager 迁移-> PostgreSQL Runner-TCP 443-> NGINX Unicorn-TCP 9200- > Elasticsearch Sidekiq-TCP 9200-> Elasticsearch Sidekiq-TCP 80,443-> Sentry Unicorn-TCP 80,443-> Sentry Sidekiq-UDP 6831-> Jaeger Unicorn-UDP 6831-> Jaeger Gitaly-UDP 6831-> Jaeger GitLabShell-UDP 6831-> Jaeger GitLabWorkhorse-UDP 6831-> Jaeger Alertmanager-TCP 25-> SMTP Sidekiq-TCP 25-> SMTP Unicorn-TCP 25-> SMTP Unicorn-TCP 369-> LDAP Sidekiq-TCP 369-> LDAP Unicorn-TCP 443-> ObjectStorage [" Object Storage"] Sidekiq-TCP 443-> ObjectStorage GitLabWorkhorse- TCP 协议 443-> ObjectStorage 注册表-TCP 443-> ObjectStorage Geo-TCP 5432-> PostgreSQL + +### Component legend[](#component-legend "Permalink") + +* ✅-默认安装 +* ⚙-需要其他配置或 GitLab 托管应用 +* ⤓-需要手动安装 +* ❌-不支持或无可用说明 +* 不适用-不适用 + +组件状态链接到每个组件的配置文档. + +### Component list[](#component-list "Permalink") + +表描述链接: + +* [Omnibus GitLab](https://docs.gitlab.com/omnibus/) +* [GitLab chart](https://docs.gitlab.com/charts/) +* [Minikube Minimal](https://docs.gitlab.com/charts/development/minikube/) +* [GitLab.com](https://gitlab.com) +* [Source](../install/installation.html) +* [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) + +| Component | Description | 所有的 GitLab | GitLab 图表 | Minikube 最小 | GitLab.com | Source | GDK | CE/EE | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | +| [Certificate Management](#certificate-management) | TLS 设置,让我们加密 | ✅ | ✅ | ⚙ | ✅ | ⚙ | ⚙ | CE 和 EE | +| [Consul](#consul) | 数据库节点发现,故障转移 | ⚙ | ❌ | ❌ | ✅ | ❌ | ❌ | 仅 EE | +| [Database Migrations](#database-migrations) | 数据库迁移 | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE 和 EE | +| [Elasticsearch](#elasticsearch) | 改进了 GitLab 中的搜索 | ⤓ | ⤓ | ⤓ | ❌ | ⤓ | ⤓ | 仅 EE | +| [Gitaly](#gitaly) | Git RPC 服务,用于处理 GitLab 进行的所有 Git 调用 | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE 和 EE | +| [GitLab Exporter](#gitlab-exporter) | 生成各种 GitLab 指标 | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | CE 和 EE | +| [GitLab Geo Node](#gitlab-geo) | 地理分布的 GitLab 节点 | ⚙ | ⚙ | ❌ | ✅ | ❌ | ⚙ | 仅 EE | +| [GitLab Managed Apps](#gitlab-managed-apps) | 将 Helm,Ingress,Cert-Manager,Prometheus,Runner,JupyterHub 或 Knative 部署到集群 | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | CE 和 EE | +| [GitLab Pages](#gitlab-pages) | 托管静态网站 | ⚙ | ❌ | ❌ | ✅ | ⚙ | ⚙ | CE 和 EE | +| [GitLab self-monitoring: Alertmanager](#alertmanager) | 来自 Prometheus 的重复数据删除,分组和路由警报 | ⚙ | ✅ | ⚙ | ✅ | ❌ | ❌ | CE 和 EE | +| [GitLab self-monitoring: Grafana](#grafana) | 指标仪表板 | ✅ | ⚙ | ⤓ | ✅ | ❌ | ❌ | CE & EE | +| [GitLab self-monitoring: Jaeger](#jaeger) | 查看由 GitLab 实例生成的跟踪 | ❌ | ⚙ | ❌ | ❌ | ⤓ | ⚙ | CE 和 EE | +| [GitLab self-monitoring: Prometheus](#prometheus) | 时间序列数据库,指标收集和查询服务 | ✅ | ✅ | ⚙ | ✅ | ❌ | ❌ | CE 和 EE | +| [GitLab self-monitoring: Sentry](#sentry) | 跟踪 GitLab 实例生成的错误 | ⤓ | ⤓ | ❌ | ✅ | ⤓ | ⤓ | CE 和 EE | +| [GitLab Shell](#gitlab-shell) | 通过 SSH 会话处理`git` | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE 和 EE | +| [GitLab Workhorse](#gitlab-workhorse) | 智能反向代理,处理大型 HTTP 请求 | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE | +| [Inbound email (SMTP)](#inbound-email) | 接收消息以更新问题 | ⤓ | ⚙ | ⤓ | ✅ | ⤓ | ⤓ | CE 和 EE | +| [Jaeger integration](#jaeger) | 部署的应用程序的分布式跟踪 | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | 仅 EE | +| [LDAP Authentication](#ldap-authentication) | 根据集中的 LDAP 目录对用户进行身份验证 | ⤓ | ⤓ | ⤓ | ❌ | ⤓ | ⤓ | CE 和 EE | +| [Mattermost](#mattermost) | 开源 Slack 替代方案 | ⚙ | ⤓ | ⤓ | ⤓ | ❌ | ❌ | CE 和 EE | +| [MinIO](#minio) | 对象存储服务 | ⤓ | ✅ | ✅ | ✅ | ❌ | ⚙ | CE 和 EE | +| [NGINX](#nginx) | 将请求路由到适当的组件,终止 SSL | ✅ | ✅ | ⚙ | ✅ | ⤓ | ❌ | CE 和 EE | +| [Node Exporter](#node-exporter) | 具有系统指标的 Prometheus 端点 | ✅ | N/A | N/A | ✅ | ❌ | ❌ | CE 和 EE | +| [Outbound email (SMTP)](#outbound-email) | 向用户发送电子邮件 | ⤓ | ⚙ | ⤓ | ✅ | ⤓ | ⤓ | CE 和 EE | +| [PgBouncer Exporter](#pgbouncer-exporter) | 具有 PgBouncer 指标的 Prometheus 端点 | ⚙ | ❌ | ❌ | ✅ | ❌ | ❌ | CE 和 EE | +| [PgBouncer](#pgbouncer) | 数据库连接池,故障转移 | ⚙ | ❌ | ❌ | ✅ | ❌ | ❌ | 仅 EE | +| [PostgreSQL Exporter](#postgresql-exporter) | 带有 PostgreSQL 指标的 Prometheus 端点 | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | CE 和 EE | +| [PostgreSQL](#postgresql) | Database | ✅ | ✅ | ✅ | ✅ | ⤓ | ✅ | CE 和 EE | +| [Praefect](#praefect) | 任何 Git 客户端和 Gitaly 存储节点之间的透明代理. | ✅ | ⚙ | ❌ | ✅ | ⚙ | ✅ | CE 和 EE | +| [Redis Exporter](#redis-exporter) | 具有 Redis 指标的 Prometheus 端点 | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | CE 和 EE | +| [Redis](#redis) | 缓存服务 | ✅ | ✅ | ✅ | ✅ | ⤓ | ✅ | CE 和 EE | +| [Registry](#registry) | 容器注册表,允许推和拉图像 | ⚙ | ✅ | ✅ | ✅ | ⤓ | ⚙ | CE 和 EE | +| [Runner](#gitlab-runner) | 执行 GitLab CI / CD 作业 | ⤓ | ✅ | ⚙ | ✅ | ⚙ | ⚙ | CE 和 EE | +| [Sentry integration](#sentry) | 跟踪已部署应用程序的错误 | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | CE 和 EE | +| [Sidekiq](#sidekiq) | 后台作业处理器 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | CE 和 EE | +| [Unicorn (GitLab Rails)](#unicorn) | 处理对 Web 界面和 API 的请求 | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE 和 EE | + +### Component details[](#component-details "Permalink") + +本文档供系统管理员和 GitLab 支持工程师使用,他们希望进一步了解 GitLab 的内部结构以及如何协同工作. + +部署后,应将 GitLab 视为以下过程的合并. 在进行故障排除或调试时,请尽可能明确地指出要引用的组件. 那应该增加清晰度并减少混乱. + +**Layers** + +从流程的角度来看,可以认为 GitLab 具有两层: + +* **监视** :不需要任何层来交付 GitLab 应用程序,但是它将允许管理员更深入地了解他们的基础结构以及整个服务在做什么. +* **核心** :对 GitLab 作为平台交付至关重要的任何过程. 如果这些过程中的任何一个停止,都将导致 GitLab 中断. 对于核心层,您可以进一步分为: + * **处理器** :这些进程负责实际执行操作并提供服务. + * **数据** :这些服务为 GitLab 服务存储/公开结构化数据. + +#### Alertmanager[](#alertmanager "Permalink") + +* [Project page](https://github.com/prometheus/alertmanager/blob/master/README.md) +* Configuration: + * [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template) + * [Charts](https://github.com/helm/charts/tree/master/stable/prometheus) +* 层:监控 +* Process: `alertmanager` +* GitLab.com: [Monitoring of GitLab.com](https://about.gitlab.com/handbook/engineering/monitoring/) + +[警报管理器](https://s0prometheus0io.icopy.site/docs/alerting/latest/alertmanager/)是 Prometheus 提供的工具,用于*"处理由客户端应用程序(例如 Prometheus 服务器)发送的警报.* *它负责将重复数据删除,分组和路由到正确的接收者集成,例如电子邮件,PagerDuty 或 Opsgenie.* *它还负责沉默和禁止警报."* 您可以在[问题#45740 中](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45740)阅读更多有关我们将要[发出](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45740)警报的内容. + +#### Certificate management[](#certificate-management "Permalink") + +* 项目页面: + * [综合巴士](https://github.com/certbot/certbot/blob/master/README.rst) + * [图表](https://github.com/jetstack/cert-manager/blob/master/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/ssl.html) + * [Charts](https://docs.gitlab.com/charts/installation/tls.html) + * [Source](../install/installation.html#using-https) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/https.md) +* 层:核心服务(处理器) +* GitLab.com: [Secrets Management](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#secrets-management) + +#### Consul[](#consul "Permalink") + +* [Project page](https://github.com/hashicorp/consul/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/high_availability/consul.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) +* 层:核心服务(数据) +* GitLab.com: [Consul](../user/gitlab_com/index.html#consul) + +Consul 是用于服务发现和配置的工具. Consul 是分布式的,高度可用的,并且具有极高的可伸缩性. + +#### Database migrations[](#database-migrations "Permalink") + +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/database.html) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/migrations/) + * [Source](../update/upgrading_from_source.html#13-install-libraries-migrations-etc) +* Layer: Core Service (Data) + +#### Elasticsearch[](#elasticsearch "Permalink") + +* [Project page](https://github.com/elastic/elasticsearch/) +* Configuration: + * [Omnibus](../integration/elasticsearch.html) + * [Charts](../integration/elasticsearch.html) + * [Source](../integration/elasticsearch.html) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/elasticsearch.md) +* 层:核心服务(数据) +* GitLab.com: [Get Advanced Global Search working on GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/153) epic. + +Elasticsearch 是为云构建的分布式 RESTful 搜索引擎. + +#### Gitaly[](#gitaly "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitaly/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/gitaly/index.html) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/gitaly/) + * [Source](../install/installation.html#install-gitaly) +* 层:核心服务(数据) +* Process: `gitaly` +* GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture) + +Gitaly 是一项由 GitLab 设计的服务,旨在消除我们在 GitLab 的分布式部署(请考虑 GitLab.com 或高可用性部署)中对 Git 存储使用 NFS 的需求. 从 11.3.0 开始,此服务处理 GitLab 中的所有 Git 级别访问. 您可以[在项目的 README 中](https://gitlab.com/gitlab-org/gitaly)阅读有关该项目的更多信息. + +#### Praefect[](#praefect "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitaly/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/gitaly/index.html) + * [Source](../install/installation.html#install-gitaly) +* 层:核心服务(数据) +* Process: `praefect` +* GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture) + +Praefect 是每个 Git 客户端和 Gitaly 之间的透明代理,用于协调将存储库更新复制到辅助节点. + +#### GitLab Geo[](#gitlab-geo "Permalink") + +* Configuration: + * [Omnibus](../administration/geo/replication/index.html#setup-instructions) + * [Charts](https://docs.gitlab.com/charts/advanced/geo/) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/geo.md) +* 层:核心服务(处理器) + +#### GitLab Exporter[](#gitlab-exporter "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitlab-exporter) +* Configuration: + * [Omnibus](../administration/monitoring/prometheus/gitlab_exporter.html) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/gitlab-exporter/index.html) +* 层:监控 +* Process: `gitlab-exporter` +* GitLab.com: [Monitoring of GitLab.com](https://about.gitlab.com/handbook/engineering/monitoring/) + +GitLab Exporter 是一个内部设计的流程,允许我们将有关 GitLab 应用程序内部的度量导出到 Prometheus. 您可以[在项目的 README 中](https://gitlab.com/gitlab-org/gitlab-exporter)阅读更多内容. + +#### GitLab Pages[](#gitlab-pages "Permalink") + +* Configuration: + * [Omnibus](../administration/pages/index.html) + * [Charts](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/37) + * [Source](../install/installation.html#install-gitlab-pages) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/pages.md) +* 层:核心服务(处理器) +* GitLab.com: [GitLab Pages](../user/gitlab_com/index.html#gitlab-pages) + +GitLab 页面是一项功能,可让您直接从 GitLab 中的存储库发布静态网站. + +您可以将其用于个人或企业网站,例如投资组合,文档,清单和业务演示. 您还可以将任何许可证归于您的内容. + +#### GitLab Runner[](#gitlab-runner "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/runner/) + * [Charts](https://docs.gitlab.com/runner/install/kubernetes.html) + * [Source](https://docs.gitlab.com/runner/) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/runner.md) +* 层:核心服务(处理器) +* GitLab.com: [Runner](../user/gitlab_com/index.html#shared-runners) + +GitLab Runner 运行作业并将结果发送到 GitLab. + +GitLab CI / CD 是 GitLab 附带的开源持续集成服务,用于协调测试. 该项目的旧名称是`GitLab CI Multi Runner`但从现在开始,请使用`GitLab Runner` (不带 CI). + +#### GitLab Shell[](#gitlab-shell "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitlab-shell/blob/master/README.md) +* Configuration: + * [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/gitlab-shell/) + * [Source](../install/installation.html#install-gitlab-shell) + * [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) +* 层:核心服务(处理器) +* GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture) + +[GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell)是[GitLab](https://gitlab.com/gitlab-org/gitlab-shell)设计的程序,用于处理基于 SSH 的`git`会话,并修改授权密钥的列表. GitLab Shell 不是 Unix Shell,也不是 Bash 或 Zsh 的替代品. + +#### GitLab Workhorse[](#gitlab-workhorse "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitlab-workhorse/blob/master/README.md) +* Configuration: + * [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/unicorn/) + * [Source](../install/installation.html#install-gitlab-workhorse) +* 层:核心服务(处理器) +* Process: `gitlab-workhorse` +* GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture) + +[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse)是由 GitLab 设计的程序,可帮助缓解 Unicorn 的压力. 您可以阅读有关发展的[历史原因的](https://about.gitlab.com/blog/2016/04/12/a-brief-history-of-gitlab-workhorse/)更多信息. 它旨在充当智能反向代理,以帮助整体上加快 GitLab 的速度. + +#### Grafana[](#grafana "Permalink") + +* [Project page](https://github.com/grafana/grafana/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/monitoring/performance/grafana_configuration.html) + * [Charts](https://docs.gitlab.com/charts/charts/globals) +* 层:监控 +* GitLab.com: [GitLab triage Grafana dashboard](https://dashboards.gitlab.com/d/RZmbBr7mk/gitlab-triage?refresh=30s) + +Grafana 是适用于 Graphite,Elasticsearch,OpenTSDB,Prometheus 和 InfluxDB 的开源,功能丰富的指标仪表板和图形编辑器. + +#### Jaeger[](#jaeger "Permalink") + +* [Project page](https://github.com/jaegertracing/jaeger/blob/master/README.md) +* Configuration: + * [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4104) + * [Charts](https://docs.gitlab.com/charts/charts/globals) + * [Source](../development/distributed_tracing.html#enabling-distributed-tracing) + * [GDK](../development/distributed_tracing.html#using-jaeger-in-the-gitlab-development-kit) +* 层:监控 +* GitLab.com: [Configuration to enable Tracing for a GitLab instance](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4104) issue. + +受到 Dapper 和 OpenZipkin 启发的 Jaeger 是一个分布式跟踪系统. 它可以用于监视基于微服务的分布式系统. + +有关监视已部署的应用程序,请参阅[Jaeger 跟踪文档.](../operations/tracing.html) + +#### Logrotate[](#logrotate "Permalink") + +* [Project page](https://github.com/logrotate/logrotate/blob/master/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/logs.html) +* 层:核心服务 +* Process: `logrotate` + +GitLab 包含大量全部记录的服务. 从 7.4 开始,我们开始捆绑自己的 logrotate,以确保我们负责任地进行日志记录. 这只是普通开源产品的打包版本. + +#### Mattermost[](#mattermost "Permalink") + +* [Project page](https://github.com/mattermost/mattermost-server/blob/master/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/gitlab-mattermost/) + * [Charts](https://docs.mattermost.com/install/install-mmte-helm-gitlab-helm.html) +* 层:核心服务(处理器) +* GitLab.com: [Mattermost](../user/project/integrations/mattermost.html) + +Mattermost 是一种开放源代码的私有云,是[https://mattermost.com 上的](https://mattermost.com) Slack 替代品. + +#### MinIO[](#minio "Permalink") + +* [Project page](https://github.com/minio/minio/blob/master/README.md) +* Configuration: + * [Omnibus](https://min.io/download) + * [Charts](https://docs.gitlab.com/charts/charts/minio/) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/object_storage.md) +* 层:核心服务(数据) +* GitLab.com: [Storage Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#storage-architecture) + +MinIO 是根据 Apache License v2.0 发布的对象存储服务器. 它与 Amazon S3 云存储服务兼容. 它最适合存储非结构化数据,例如照片,视频,日志文件,备份和容器/ VM 映像. 一个对象的大小范围可以从几个 KB 到最大 5TB. + +#### NGINX[](#nginx "Permalink") + +* 项目页面: + * [综合巴士](https://github.com/nginx/nginx) + * [图表](https://github.com/kubernetes/ingress-nginx/blob/master/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/) + * [Charts](https://docs.gitlab.com/charts/charts/nginx/) + * [Source](../install/installation.html#9-nginx) +* 层:核心服务(处理器) +* Process: `nginx` +* GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture) + +NGINX 有一个用于所有 HTTP 请求的 Ingress 端口,并将它们路由到 GitLab 中的相应子系统. 我们捆绑了流行的开源 Web 服务器的未修改版本. + +#### Node Exporter[](#node-exporter "Permalink") + +* [Project page](https://github.com/prometheus/node_exporter/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/monitoring/prometheus/node_exporter.html) + * [Charts](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1332) +* 层:监控 +* Process: `node-exporter` +* GitLab.com: [Monitoring of GitLab.com](https://about.gitlab.com/handbook/engineering/monitoring/) + +[Node Exporter](https://github.com/prometheus/node_exporter)是 Prometheus 工具,可为我们提供底层计算机的指标(以 CPU /磁盘/负载为例). 它只是 Prometheus 项目中常见开源产品的打包版本. + +#### PgBouncer[](#pgbouncer "Permalink") + +* [Project page](https://github.com/pgbouncer/pgbouncer/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/high_availability/pgbouncer.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) +* 层:核心服务(数据) +* GitLab.com: [Database Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#database-architecture) + +PostgreSQL 的轻量级连接池. + +#### PgBouncer Exporter[](#pgbouncer-exporter "Permalink") + +* [Project page](https://github.com/prometheus-community/pgbouncer_exporter/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/monitoring/prometheus/pgbouncer_exporter.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) +* 层:监控 +* GitLab.com: [Monitoring of GitLab.com](https://about.gitlab.com/handbook/engineering/monitoring/) + +Prometheus PgBouncer 的出口商. 导出指标为 9127 / metrics. + +#### PostgreSQL[](#postgresql "Permalink") + +* [Project page](https://github.com/postgres/postgres/blob/master/README) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/database.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) + * [Source](../install/installation.html#6-database) +* 层:核心服务(数据) +* Process: `postgresql` +* GitLab.com: [PostgreSQL](../user/gitlab_com/index.html#postgresql) + +GitLab 打包了流行的数据库,以存储应用程序元数据和用户信息. + +#### PostgreSQL Exporter[](#postgresql-exporter "Permalink") + +* [Project page](https://github.com/wrouesnel/postgres_exporter/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/monitoring/prometheus/postgres_exporter.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) +* 层:监控 +* Process: `postgres-exporter` +* GitLab.com: [Monitoring of GitLab.com](https://about.gitlab.com/handbook/engineering/monitoring/) + +[`postgres_exporter`](https://github.com/wrouesnel/postgres_exporter)是社区提供的 Prometheus 导出器,它将 PostgreSQL 的有关数据传递给 Prometheus,以在 Grafana 仪表板中使用. + +#### Prometheus[](#prometheus "Permalink") + +* [Project page](https://github.com/prometheus/prometheus/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/monitoring/prometheus/index.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) +* 层:监控 +* Process: `prometheus` +* GitLab.com: [Prometheus](../user/gitlab_com/index.html#prometheus) + +Prometheus 是一个时序工具,可帮助 GitLab 管理员公开有关用于向 GitLab 提供服务的各个流程的指标. + +#### Redis[](#redis "Permalink") + +* [Project page](https://github.com/antirez/redis/blob/unstable/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/redis.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) + * [Source](../install/installation.html#7-redis) +* 层:核心服务(数据) +* Process: `redis` +* GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture) + +Redis 被打包以提供存储位置: + +* 会话数据 +* 临时缓存信息 +* 后台作业队列 + +#### Redis Exporter[](#redis-exporter "Permalink") + +* [Project page](https://github.com/oliver006/redis_exporter/blob/master/README.md) +* Configuration: + * [Omnibus](../administration/monitoring/prometheus/redis_exporter.html) + * [Charts](https://docs.gitlab.com/charts/installation/deployment.html) +* 层:监控 +* Process: `redis-exporter` +* GitLab.com: [Monitoring of GitLab.com](https://about.gitlab.com/handbook/engineering/monitoring/) + +[Redis Exporter](https://github.com/oliver006/redis_exporter)旨在向 Prometheus 提供有关 Redis 流程的特定指标,以便我们可以在 Grafana 中绘制这些指标. + +#### Registry[](#registry "Permalink") + +* [Project page](https://github.com/docker/distribution/blob/master/README.md) +* Configuration: + * [Omnibus](../update/upgrading_from_source.html#13-install-libraries-migrations-etc) + * [Charts](https://docs.gitlab.com/charts/charts/registry/) + * [Source](../administration/packages/container_registry.html#enable-the-container-registry) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/registry.md) +* 层:核心服务(处理器) +* GitLab.com: [GitLab Container Registry](../user/packages/container_registry/index.html#build-and-push-images-using-gitlab-cicd) + +用户使用注册表来存储自己的 Docker 映像. 捆绑的注册表使用 NGINX 作为负载平衡器,并使用 Gi​​tLab 作为身份验证管理器. 每当客户端请求从注册表中拉出或推送图像时,客户端都会返回`401`响应以及标头,其中详细说明了从何处获取身份验证令牌(在本例中为 GitLab 实例). 然后,客户端将向 GitLab 请求"拉"或"推"身份验证令牌,然后将原始请求重试到注册表. 了解有关[令牌认证的](https://docs.docker.com/registry/spec/auth/token/)更多信息. + +也可以将外部注册表配置为将 GitLab 用作身份验证端点. + +#### Sentry[](#sentry "Permalink") + +* [Project page](https://github.com/getsentry/sentry/) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/configuration.html) + * [Charts](https://docs.gitlab.com/charts/charts/globals) + * [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) + * [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) +* 层:监控 +* GitLab.com: [Searching Sentry](https://about.gitlab.com/handbook/support/workflows/500_errors.html#searching-sentry) + +从根本上说,Sentry 是一项服务,可帮助您实时监视和修复崩溃. 该服务器使用 Python,但是它包含用于在任何应用程序中从任何语言发送事件的完整 API. + +有关监视已部署的应用程序,请参阅[Sentry 集成文档](../user/project/operations/error_tracking.html) + +#### Sidekiq[](#sidekiq "Permalink") + +* [Project page](https://github.com/mperham/sidekiq/blob/master/README.md) +* Configuration: + * [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/) + * [Minikube Minimal](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/index.html) + * [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) + * [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) +* 层:核心服务(处理器) +* Process: `sidekiq` +* GitLab.com: [Sidekiq](../user/gitlab_com/index.html#sidekiq) + +Sidekiq 是 Ruby 后台作业处理器,可从 Redis 队列中提取作业并进行处理. 后台作业使 GitLab 通过将工作移至后台来提供更快的请求/响应周期. + +#### Unicorn[](#unicorn "Permalink") + +* [Project page](https://gitlab.com/gitlab-org/gitlab/blob/master/README.md) +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/unicorn.html) + * [Charts](https://docs.gitlab.com/charts/charts/gitlab/webservice/) + * [Source](../install/installation.html#configure-it) + * [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) +* 层:核心服务(处理器) +* Process: `unicorn` +* GitLab.com: [Unicorn](../user/gitlab_com/index.html#unicorn) + +[Unicorn](https://yhbt.net/unicorn/)是一个 Ruby 应用程序服务器,用于运行核心的 Rails 应用程序,该应用程序在 GitLab 中提供面向用户的功能. 通常,根据 GitLab 版本,您会看到此输出为`bundle`或`config.ru` . + +#### LDAP Authentication[](#ldap-authentication "Permalink") + +* Configuration: + * [Omnibus](../administration/auth/ldap/index.html) + * [Charts](https://docs.gitlab.com/charts/charts/globals.html) + * [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) + * [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/ldap.md) +* 层:核心服务(处理器) +* GitLab.com: [Product Tiers](https://about.gitlab.com/pricing/#gitlab-com) + +#### Outbound Email[](#outbound-email "Permalink") + +* Configuration: + * [Omnibus](https://docs.gitlab.com/omnibus/settings/smtp.html) + * [Charts](https://docs.gitlab.com/charts/installation/command-line-options.html) + * [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) + * [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) +* 层:核心服务(处理器) +* GitLab.com: [Mail configuration](../user/gitlab_com/index.html#mail-configuration) + +#### Inbound Email[](#inbound-email "Permalink") + +* Configuration: + * [Omnibus](../administration/incoming_email.html) + * [Charts](https://docs.gitlab.com/charts/installation/command-line-options.html) + * [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) + * [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) +* 层:核心服务(处理器) +* GitLab.com: [Mail configuration](../user/gitlab_com/index.html#mail-configuration) + +#### GitLab Managed Apps[](#gitlab-managed-apps "Permalink") + +* Configuration: + * [Omnibus](../user/project/clusters/index.html#installing-applications) + * [Charts](../user/project/clusters/index.html#installing-applications) + * [Source](../user/project/clusters/index.html#installing-applications) + * [GDK](../user/project/clusters/index.html#installing-applications) +* 层:核心服务(处理器) + +GitLab 提供[GitLab 托管应用程序](../user/project/clusters/index.html#installing-applications) ,一键安装各种应用程序,可以直接将其添加到配置的集群中. 使用 Auto DevOps 时,Review Apps 和部署需要这些应用程序. 您可以在创建集群后安装它们. 这包括: + +* [Helm](https://helm.sh/docs/) +* [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) +* [Cert-Manager](https://cert-manager.io/docs/) +* [Prometheus](https://s0prometheus0io.icopy.site/docs/introduction/overview/) +* a [Runner](https://docs.gitlab.com/runner/) +* [JupyterHub](https://jupyter.org) +* [Knative](https://cloud.google.com/knative/) + +## GitLab by Request Type[](#gitlab-by-request-type "Permalink") + +GitLab 为最终用户提供了两个"接口"来访问服务: + +* Web HTTP 请求(查看 UI / API) +* Git HTTP / SSH 请求(推/拉 Git 数据) + +了解两者之间的区别很重要,因为某些过程在两种过程中都使用,而另一些过程则是特定请求类型所独有的. + +### GitLab Web HTTP Request Cycle[](#gitlab-web-http-request-cycle "Permalink") + +向 HTTP 端点发出请求(认为`/users/sign_in` )时,请求将通过 GitLab 服务采用以下路径: + +* NGINX-充当我们的第一线反向代理. +* GitLab Workhorse-确定是否需要转到 Rails 应用程序或其他地方以减少 Unicorn 上的负载. +* Unicorn-由于这是一个 Web 请求,并且需要访问该应用程序,因此它将转到 Unicorn. +* PostgreSQL / Gitaly / Redis-根据请求的类型,它可能会通过这些服务来存储或检索数据. + +### GitLab Git Request Cycle[](#gitlab-git-request-cycle "Permalink") + +下面我们描述 HTTP 与 SSH Git 请求将采用的不同路径. Web 请求周期有一些重叠,但也有一些差异. + +### Web Request (80/443)[](#web-request-80443 "Permalink") + +通过 HTTP 进行的 Git 操作使用[Git 文档中](https://git-scm.com/docs/http-protocol)描述的无状态"智能"协议,但处理这些操作的职责分散在多个 GitLab 组件中. + +这是`git fetch`的序列图. 请注意,所有请求都会通过 NGINX 以及任何其他 HTTP 负载平衡器传递,但不会以任何方式进行转换. 所有路径都相对于`/namespace/project.git` URL 呈现. + +sequenceDiagram 参与者客户端参与者上的 Git NGINX 参与者 Workhorse 参与者 Rails 参与者 Gitaly 参与者服务器上的 Git 注意客户端上的 Git 左侧:git fetch +客户端上的 info-refs Git->> + Workhorse:GET / info / refs?service = git-upload-pack Workhorse->> + Rails:GET / info / refs?service = git-upload-pack 注意 Rails 的右侧:验证检查 Rails->>-Workhorse:Gitlab :: Workhorse.git_http_ok​​ Workhorse->> + Gitaly:SmartHTTPService.InfoRefsUploadPack 请求服务器上的 Gitaly->> + Git:git upload-pack --stateless-rpc --advertise-refs 服务器上的 Git->>-Gitaly:git upload-pack 响应 Gitaly->>-工作马:SmartHTTPService.InfoRefsUploadPack 响应 Workhorse->>-客户端上的 Git:200 OK 注意客户端上的 Git 左侧:git fetch +在客户端上获取包装 Git->> + Workhorse:POST / git-upload-pack Workhorse->> + Rails:POST / git-upload-pack 注意 Rails 的权利:Auth check Rails->>-Workhorse:Gitlab: :Workhorse.git_http_ok​​ Workhorse->> + Gitaly:SmartHTTPService.PostUploadPack 请求 Gitaly->> + Git 在服务器上:git upload-pack --stateless-rpc 服务器上的 Git->>-Gitaly:git upload-pack 响应 Gitaly- ->>-Workhorse:SmartHTTPService.PostUploadPack 响应 Workhorse->>-客户端上的 Git:200 OK + +该序列与`git push`相似,除了使用`git-receive-pack`代替`git-upload-pack` . + +### SSH Request (22)[](#ssh-request-22 "Permalink") + +通过 SSH 进行的 Git 操作可以使用[Git 文档中](https://git-scm.com/docs/pack-protocol#_ssh_transport)描述的有状态协议,但是处理它们的职责分散在多个 GitLab 组件中. + +没有任何 GitLab 组件直接使用 SSH-所有 SSH 连接都是在客户端计算机上的 Git 与 SSH 服务器之间建立的,从而终止了连接. 对于 SSH 服务器,所有连接均以`git`用户身份进行身份验证; GitLab 用户通过客户端提供的 SSH 密钥来区分. + +这是`git fetch`的序列图,假设启用了[快速 SSH 密钥查找](../administration/operations/fast_ssh_key_lookup.html) . 请注意, `AuthorizedKeysCommand`是[GitLab Shell](#gitlab-shell)提供的可执行文件: + +sequenceDiagram 参与者客户端参与者上的 Git SSH 服务器参与者 AuthorizedKeysCommand 参与者 GitLab Shell 参与者 Rails 参与者 Gitaly 参与者服务器上的 Git 注意客户端上的 Git 左侧:git fetch 客户端上的 Git->> + SSH 服务器:ssh git fetch-pack request SSH 服务器-> > + AuthorizedKeysCommand:gitlab-shell-authorized-keys-check git AAAA ... AuthorizedKeysCommand->> + Rails:GET / internal / api / authorized_keys?key = AAAA ...注意 Rails 的右边:查找密钥 ID Rails-- >>-AuthorizedKeysCommand:200 OK,command =" gitlab-shell upload-pack key_id = 1" AuthorizedKeysCommand->>-SSH 服务器:command =" gitlab-shell upload-pack key_id = 1" SSH 服务器->> + GitLab Shell:gitlab-shell upload-pack key_id = 1 GitLab Shell->> + Rails:GET / internal / api / allowed?action = upload_pack&key_id = 1 注意 Rails 的权利:Auth check Rails->>-GitLab Shell:200 OK ,{gitaly:...} GitLab Shell->> + Gitaly:SSHService.SSHUploadPack 请求服务器上的 Gitaly->> + Git:git upload-pack 请求注意客户端上的 Git,Git on 服务器:Git 客户端和服务器上服务器 Git 之间的双向通信->>-Gitaly:git upload-pack 响应 Gitaly->>-GitLab Shell:SSHService.SSHUploadPack 响应 GitLab Shell->>-SSH 服务器:gitlab-shell 上载 SSH 伺服器的上载回应->>-Git 使用者:ssh git fetch-pack 回应 + +`git push`操作非常相似,除了使用`git receive-pack`代替`git upload-pack` . + +如果未启用快速 SSH 密钥查找,则 SSH 服务器将从`~git/.ssh/authorized_keys`文件读取,以确定为给定的 SSH 会话运行什么命令. 它由 Rails 中的[`AuthorizedKeysWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/workers/authorized_keys_worker.rb)保持最新状态,并计划在用户修改 SSH 密钥时运行. + +可以使用[SSH 证书](../administration/operations/ssh_certificates.html)代替密钥. 在这种情况下, `AuthorizedKeysCommand`替换为`AuthorizedPrincipalsCommand` . 这将从证书中提取用户名,而无需使用 Rails 内部 API,该 API 稍后将代替`/api/internal/allowed`调用中的`key_id`使用. + +GitLab Shell 还具有一些不涉及 Gitaly 的操作,例如重置两因素身份验证代码. 这些操作以相同的方式处理,除了没有往返 Gitaly 的往返-Rails 作为[内部 API](internal_api.html)调用的一部分执行操作,并且 GitLab Shell 将响应直接流回用户. + +## System Layout[](#system-layout "Permalink") + +在图片中引用`~git`时,它表示 Git 用户的主目录,通常是`/home/git` . + +GitLab 主要以`git`用户身份安装在`/home/git`用户主目录中. GitLab 服务器软件以及存储库都位于主目录中(尽管存储库位置是可配置的). + +裸存储库位于`/home/git/repositories` . GitLab 是 Ruby on Rails 应用程序,因此可以通过研究 Ruby on Rails 应用程序的工作方式来了解内部工作的细节. + +为了通过 SSH 提供存储库,有一个名为 GitLab Shell 的附加应用程序,它安装在`/home/git/gitlab-shell` . + +### Installation Folder Summary[](#installation-folder-summary "Permalink") + +总结一下,这里是[`git`用户主目录](../install/structure.html)的[目录结构](../install/structure.html) . + +### Processes[](#processes "Permalink") + +``` +ps aux | grep '^git' +``` + +GitLab 有几个要运行的组件. 它需要一个持久数据库(PostgreSQL)和 Redis 数据库,并使用 Apache `httpd`或 NGINX 代理传递 Unicorn. 所有这些组件都应以与 GitLab 不同的系统用户身份运行(例如, `postgres` , `redis`和`www-data` ,而不是`git` ). + +作为`git`用户,它将启动 Sidekiq 和 Unicorn(默认情况下在端口`8080`上运行的简单 Ruby HTTP 服务器). 在 GitLab 用户下,通常有 4 个进程: `unicorn_rails master` (1 个进程), `unicorn_rails worker` (2 个进程), `sidekiq` (1 个进程). + +### Repository access[](#repository-access "Permalink") + +可以通过 HTTP 或 SSH 访问存储库. HTTP 克隆/推/拉使用 GitLab API,而 SSH 克隆由 GitLab Shell 处理(先前已说明). + +## Troubleshooting[](#troubleshooting "Permalink") + +有关更多信息,请参见自述文件. + +### Init scripts of the services[](#init-scripts-of-the-services "Permalink") + +GitLab 初始化脚本启动和停止 Unicorn 和 Sidekiq: + +``` +/etc/init.d/gitlab +Usage: service gitlab {start|stop|restart|reload|status} +``` + +Redis(键值存储/非持久数据库): + +``` +/etc/init.d/redis +Usage: /etc/init.d/redis {start|stop|status|restart|condrestart|try-restart} +``` + +SSH daemon: + +``` +/etc/init.d/sshd +Usage: /etc/init.d/sshd {start|stop|restart|reload|force-reload|condrestart|try-restart|status} +``` + +Web 服务器(以下之一): + +``` +/etc/init.d/httpd +Usage: httpd {start|stop|restart|condrestart|try-restart|force-reload|reload|status|fullstatus|graceful|help|configtest} + +$ /etc/init.d/nginx +Usage: nginx {start|stop|restart|reload|force-reload|status|configtest} +``` + +永久数据库: + +``` +$ /etc/init.d/postgresql +Usage: /etc/init.d/postgresql {start|stop|restart|reload|force-reload|status} [version ..] +``` + +### Log locations of the services[](#log-locations-of-the-services "Permalink") + +GitLab(包括 Unicorn 和 Sidekiq 日志): + +* `/home/git/gitlab/log/` contains `application.log`, `production.log`, `sidekiq.log`, `unicorn.stdout.log`, `git_json.log` and `unicorn.stderr.log` normally. + +GitLab 外壳: + +* `/home/git/gitlab-shell/gitlab-shell.log` + +SSH: + +* `/var/log/auth.log`身份验证日志(在 Ubuntu 上). +* `/var/log/secure`身份验证日志(在 RHEL 上). + +NGINX: + +* `/var/log/nginx/`包含错误和访问日志. + +Apache `httpd`: + +* [Explanation of Apache logs](https://httpd.apache.org/docs/2.2/logs.html). +* `/var/log/apache2/`包含错误和输出日志(在 Ubuntu 上). +* `/var/log/httpd/`包含错误和输出日志(在 RHEL 上). + +Redis: + +* `/var/log/redis/redis.log`那里还有日志循环日志. + +PostgreSQL: + +* `/var/log/postgresql/*` + +### GitLab specific configuration files[](#gitlab-specific-configuration-files "Permalink") + +GitLab 的配置文件位于`/home/git/gitlab/config/*` . 常用的配置文件包括: + +* `gitlab.yml` -GitLab 配置. +* `unicorn.rb` -Unicorn Web 服务器设置. +* `database.yml`数据库连接设置. + +GitLab Shell 在`/home/git/gitlab-shell/config.yml`有一个配置文件. + +### Maintenance Tasks[](#maintenance-tasks "Permalink") + +[GitLab](https://gitlab.com/gitlab-org/gitlab/tree/master)提供 Rake 任务,您可以在其中查看版本信息,并对配置进行快速检查以确保在应用程序中正确配置了它. 请参阅[维护 Rake 任务](../raketasks/maintenance.html) . 简而言之,请执行以下操作: + +``` +sudo -i -u git +cd gitlab +bundle exec rake gitlab:env:info RAILS_ENV=production +bundle exec rake gitlab:check RAILS_ENV=production +``` + +注意:建议使用`sudo -i -u git`或`sudo su - git`登录`git`用户. 尽管 GitLab 提供的 sudo 命令可在 Ubuntu 中运行,但它们并不总是在 RHEL 中运行. + +## GitLab.com[](#gitlabcom "Permalink") + +我们还详细介绍[了 GitLab.com 的体系结构,](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/)但是除非您拥有数百万的用户,否则这可能是最重要的. \ No newline at end of file diff --git a/docs/559.md b/docs/559.md new file mode 100644 index 0000000000000000000000000000000000000000..bab22d8e7dfa439f21cb846d5c8611c58089eb79 --- /dev/null +++ b/docs/559.md @@ -0,0 +1,111 @@ +# CI/CD development documentation + +> 原文:[https://docs.gitlab.com/ee/development/cicd/](https://docs.gitlab.com/ee/development/cicd/) + +* [CI Architecture overview](#ci-architecture-overview) +* [Job scheduling](#job-scheduling) + * [Communication between Runner and GitLab server](#communication-between-runner-and-gitlab-server) + * [`Ci::RegisterJobService`](#ciregisterjobservice) + +# CI/CD development documentation[](#cicd-development-documentation "Permalink") + +此处列出了特定于 CI / CD 的开发指南. + +如果要创建新的 CI / CD 模板,请阅读[GitLab CI / CD 模板的开发指南](templates.html) . + +## CI Architecture overview[](#ci-architecture-overview "Permalink") + +以下是 CI 体系结构的简化图. 为了集中在主要组件上,省略了一些细节. + +[![CI software architecture](img/8069500bf085102224933129529dfa12.png)](img/ci_architecture.png) + +在左侧,我们有一些事件可以根据各种事件触发管道(由用户或自动化触发): + +* `git push`是触发管道的最常见事件. +* The [Web API](../../api/pipelines.html#create-a-new-pipeline). +* 用户单击 UI 中的"运行管道"按钮. +* [创建或更新合并请求时](../../ci/merge_request_pipelines/index.html#pipelines-for-merge-requests) . +* 将 MR 添加到[合并列车时](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html#merge-trains-premium) . +* A [scheduled pipeline](../../ci/pipelines/schedules.html#pipeline-schedules). +* 当项目被[订阅到上游项目时](../../ci/multi_project_pipelines.html#trigger-a-pipeline-when-an-upstream-project-is-rebuilt) . +* 启用[自动 DevOps 时](../../topics/autodevops/index.html) . +* 当 GitHub 集成用于[外部请求请求时](../../ci/ci_cd_for_external_repos/index.html#pipelines-for-external-pull-requests) . +* 当上游管道包含[桥接作业时](../../ci/yaml/README.html#trigger) ,该[作业](../../ci/yaml/README.html#trigger)会触发下游管道. + +触发任何这些事件将调用[`CreatePipelineService`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/ci/create_pipeline_service.rb) ,后者将输入事件数据并触发用户,然后尝试创建管道. + +`CreatePipelineService`很大程度上依赖于[`YAML Processor`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/yaml_processor.rb)组件,该组件负责将 YAML Blob 作为输入并返回管道的抽象数据结构(包括阶段和所有作业). 该组件还可以在处理 YAML 时验证其结构,并返回任何语法或语义错误. 在`YAML Processor`组件中,我们定义了[所有](../../ci/yaml/README.html)可用于构建管道[的关键字](../../ci/yaml/README.html) . + +`CreatePipelineService`接收`YAML Processor`返回的抽象数据结构,然后将其转换为持久化模型(管道,阶段,作业等). 之后,就可以处理管道了. 处理管道意味着按执行顺序(阶段或 DAG)运行作业,直到以下任一情况为止: + +* 所有预期的作业均已执行. +* 故障会中断管道执行. + +处理管道的组件是[`ProcessPipelineService`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/ci/process_pipeline_service.rb) ,它负责将所有管道的作业移至完成状态. 创建管道时,其所有作业最初都处于`created`状态. 该服务根据流水线结构查看在`created`阶段可以处理哪些作业. 然后,它们将它们移到`pending`状态,这意味着它们现在[可以被 Runner 拾取](#job-scheduling) . 执行作业后,它可以成功完成或失败. 管道中作业的每个状态转换都会再次触发此服务,该服务会寻找下一个要转换为完成的作业. 在此过程中, `ProcessPipelineService`更新作业,阶段和整个管道的状态. + +在图的右侧,我们有一个列表[运动员](../../ci/runners/README.html#configuring-gitlab-runners)连接到 GitLab 实例. 这些可以是共享运行者,组运行者或项目特定的运行者. Runners 与 Rails 服务器之间的通信通过一组 API 端点(称为`Runner API Gateway` . + +我们可以注册,删除和验证运行器,这也将导致对数据库的读/写查询. 连接了 Runner 之后,它会继续询问要执行的下一个作业. 这将调用[`RegisterJobService`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/services/ci/register_job_service.rb) ,后者将选择下一个作业并将其分配给 Runner. 此时,作业将转换为`running`状态,由于状态更改,该状态再次触发`ProcessPipelineService` . 有关更多详细信息,请参阅" [作业调度"](#job-scheduling) . + +在执行作业时,运行程序将日志以及任何可能需要存储的工件发送回服务器. 此外,作业可能依赖于先前作业中的工件才能运行. 在这种情况下,Runner 将使用专用的 API 端点下载它们. + +工件存储在对象存储中,而元数据保留在数据库中. 工件的重要示例是报表(JUnit,SAST,DAST 等),这些报表在合并请求中进行了解析和呈现. + +作业状态转换并非全部自动化. 用户可以运行[手动作业](../../ci/yaml/README.html#whenmanual) ,取消管道,重试特定的失败作业或整个管道. 导致作业更改状态的任何事件都将触发`ProcessPipelineService` ,因为它负责跟踪整个管道的状态. + +一种特殊类型的作业是[桥接作业](../../ci/yaml/README.html#trigger) ,当过渡到`pending`状态时,该[作业](../../ci/yaml/README.html#trigger)在服务器端执行. 这项工作负责创建下游管道,例如多项目或子管道. 每次触发下游管道时,工作流程循环都将从`CreatePipelineService`重新开始. + +## Job scheduling[](#job-scheduling "Permalink") + +创建管道时,将为所有阶段一次创建所有作业,初始状态为`created` . 这使得可视化管道的全部内容成为可能. + +跑步者将不会看到具有`created`状态的作业. 为了能够将作业分配给 Runner,该作业必须首先转换为`pending`状态,这在以下情况下可能发生: + +1. 作业是在管道的第一阶段创建的. +2. 该作业需要手动启动,并且已被触发. +3. 前一阶段的所有作业均已成功完成. 在这种情况下,我们将所有工作从下一阶段过渡到`pending` . +4. 该作业使用`needs:`指定了 DAG 依赖项`needs:`并且所有依赖项都已完成. + +连接了 Runner 时,它将通过连续轮询服务器来请求下一个`pending`作业运行. + +**注意:** Runner 用于与 GitLab 交互的 API 端点在[`lib/api/runner.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/runner.rb)中定义 + +服务器收到请求后,将根据[`Ci::RegisterJobService`算法](#ciregisterjobservice)选择`pending`作业,然后将其分配并发送给 Runner. + +在当前阶段完成所有作业后,服务器通过将其状态更改为" `pending` ",从下一阶段"解锁"所有作业. 现在,当 Runner 请求新作业时,可以由调度算法选择这些内容,并像这样继续进行,直到完成所有阶段. + +### Communication between Runner and GitLab server[](#communication-between-runner-and-gitlab-server "Permalink") + +使用注册令牌[注册](https://docs.gitlab.com/runner/register/)了 Runner 之后,服务器便知道其可以执行的作业类型. 这取决于: + +* 它注册的赛跑者类型为: + * 共享跑步者 + * 团体赛跑者 + * 项目特定的跑步者 +* 任何关联的标签. + +跑步者通过请求作业执行`POST /api/v4/jobs/request`来启动通信. 尽管轮询通常每隔几秒钟发生一次,但如果作业队列不变,我们将通过 HTTP 标头利用缓存来减少服务器端的工作量. + +该 API 端点运行[`Ci::RegisterJobService`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/services/ci/register_job_service.rb) ,该命令: + +1. 从`pending`作业池中选择要运行的下一个作业 +2. 分配给跑步者 +3. 通过 API 响应将其呈现给 Runner + +### `Ci::RegisterJobService`[](#ciregisterjobservice "Permalink") + +此服务使用 3 个顶级查询来收集大多数作业,并且根据 Runner 注册到的级别选择它们: + +* 选择共享的 Runner(实例级别)的作业 +* 选择组级别运行器的作业 +* 选择项目亚军的工作 + +This list of jobs is then filtered further by matching tags between job and Runner tags. + +**注意:**如果作业包含标签,则与**所有**标签都不匹配的跑步者将不会选择该作业. 跑步者可能具有比该工作定义的标签更多的标签,但反之则没有. + +最后,如果 Runner 仅能选择带标签的作业,则所有未带标签的作业都会被过滤掉. + +在这一点上,我们遍历剩余的`pending`作业,然后尝试根据其他策略分配"可以选择" Runner 可以选择的第一个作业. 例如,标记为`protected`运行者只能选择针对受保护的分支(例如生产部署)运行的作业. + +当我们增加池中的"奔跑者"数量时,如果将同一工作分配给不同"奔跑者",也会增加发生冲突的机会. 为防止这种情况,我们会适当地挽救冲突错误并在列表中分配下一个作业. \ No newline at end of file diff --git a/docs/560.md b/docs/560.md new file mode 100644 index 0000000000000000000000000000000000000000..10cc66941110f938c882b7cb1bc6d49e968d208c --- /dev/null +++ b/docs/560.md @@ -0,0 +1,67 @@ +# Database guides + +> 原文:[https://docs.gitlab.com/ee/development/database/](https://docs.gitlab.com/ee/development/database/) + +* [Database Reviews](#database-reviews) +* [Tooling](#tooling) +* [Migrations](#migrations) +* [Debugging](#debugging) +* [Best practices](#best-practices) +* [Case studies](#case-studies) + +# Database guides[](#database-guides "Permalink") + +## Database Reviews[](#database-reviews "Permalink") + +* 如果您要创建数据库 MR 进行审查,请查看我们的[数据库审查指南](../database_review.html) . + + 它介绍了与数据库相关的更改,迁移和复杂的 SQL 查询. + +* 如果您是数据库审阅者或想成为一名数据库审阅者,请查看我们的数据库审阅[简介](database_reviewer_guidelines.html) . + +## Tooling[](#tooling "Permalink") + +* [Understanding EXPLAIN plans](../understanding_explain_plans.html) +* [explain.depesz.com](https://explain.depesz.com/)或[explain.dalibo.com,](https://explain.dalibo.com/)用于可视化`EXPLAIN`的输出 +* [pgFormatter](http://sqlformat.darold.net/) PostgreSQL SQL 语法美化器 + +## Migrations[](#migrations "Permalink") + +* [What requires downtime?](../what_requires_downtime.html) +* 用于 SQL 查询的[SQL 准则](../sql.html) +* 用于创建安全的 SQL 迁移的[迁移样式指南](../migration_style_guide.html) +* [Testing Rails migrations](../testing_guide/testing_migrations_guide.html) guide +* [Post deployment migrations](../post_deployment_migrations.html) +* [Background migrations](../background_migrations.html) +* [Swapping tables](../swapping_tables.html) +* [Deleting migrations](../deleting_migrations.html) + +## Debugging[](#debugging "Permalink") + +* 使用带有[Marginalia 的](../database_query_comments.html)查询注释来跟踪 SQL 查询的源 +* 使用[详细查询日志](https://guides.rubyonrails.org/debugging_rails_applications.html#verbose-query-logs)在 Rails 控制台中跟踪 SQL 查询的源 + +## Best practices[](#best-practices "Permalink") + +* [Adding database indexes](../adding_database_indexes.html) +* [Foreign keys & associations](../foreign_keys.html) +* [Adding a foreign key constraint to an existing column](add_foreign_key_to_existing_column.html) +* [`NOT NULL` constraints](not_null_constraints.html) +* [Strings and the Text data type](strings_and_the_text_data_type.html) +* [Single table inheritance](../single_table_inheritance.html) +* [Polymorphic associations](../polymorphic_associations.html) +* [Serializing data](../serializing_data.html) +* [Hash indexes](../hash_indexes.html) +* [Storing SHA1 hashes as binary](../sha1_as_binary.html) +* [Iterating tables in batches](../iterating_tables_in_batches.html) +* [Insert into tables in batches](../insert_into_tables_in_batches.html) +* [Ordering table columns](../ordering_table_columns.html) +* [Verifying database capabilities](../verifying_database_capabilities.html) +* [Database Debugging and Troubleshooting](../database_debugging.html) +* [Query Count Limits](../query_count_limits.html) +* [Creating enums](../creating_enums.html) + +## Case studies[](#case-studies "Permalink") + +* [Database case study: Filtering by label](../filtering_by_label.html) +* [Database case study: Namespaces storage statistics](../namespaces_storage_statistics.html) \ No newline at end of file diff --git a/docs/561.md b/docs/561.md new file mode 100644 index 0000000000000000000000000000000000000000..0765bf894d5b4cc72578c6bf43b7758fa545d328 --- /dev/null +++ b/docs/561.md @@ -0,0 +1,157 @@ +# Database Review Guidelines + +> 原文:[https://docs.gitlab.com/ee/development/database_review.html](https://docs.gitlab.com/ee/development/database_review.html) + +* [General process](#general-process) + * [Roles and process](#roles-and-process) + * [Distributing review workload](#distributing-review-workload) + * [How to prepare the merge request for a database review](#how-to-prepare-the-merge-request-for-a-database-review) + * [Preparation when adding migrations](#preparation-when-adding-migrations) + * [Preparation when adding or modifying queries](#preparation-when-adding-or-modifying-queries) + * [Preparation when adding foreign keys to existing tables](#preparation-when-adding-foreign-keys-to-existing-tables) + * [Preparation when adding tables](#preparation-when-adding-tables) + * [Preparation when removing columns, tables, indexes, or other structures](#preparation-when-removing-columns-tables-indexes-or-other-structures) + * [How to review for database](#how-to-review-for-database) + * [Timing guidelines for migrations](#timing-guidelines-for-migrations) + +# Database Review Guidelines[](#database-review-guidelines "Permalink") + +此页面特定于数据库评论. 请参阅我们的[代码审查指南](code_review.html) ,以获取有关[代码审查](code_review.html)的更广泛建议和最佳实践. + +## General process[](#general-process "Permalink") + +A database review is required for: + +* 涉及数据库架构或执行数据迁移的更改,包括以下文件: + * `db/` + * `lib/gitlab/background_migration/` +* 对数据库工具的更改. 例如: + * `lib/gitlab/database/`迁移或 ActiveRecord 助手 + * 负载均衡 +* 产生 SQL 查询的更改超出了显而易见的范围. 通常由合并请求的作者决定是否引入复杂查询以及是否需要数据库审查. + +期望数据库审阅者在更改中查找明显复杂的查询,并仔细检查那些查询. 如果作者没有指出要审核的特定查询,并且没有明显复杂的查询,那么仅专注于审核迁移就足够了. + +最好以 SQL 形式复审查询,并且通常要求作者翻译 SQL 形式的任何 ActiveRecord 查询以复审. + +### Roles and process[](#roles-and-process "Permalink") + +合并请求**作者**的角色是: + +* 确定是否需要数据库审查. +* 如果需要数据库检查,请添加〜database 标签. +* [Prepare the merge request for a database review](#how-to-prepare-the-merge-request-for-a-database-review). + +数据库**审阅者**的角色是: + +* 对 MR 进行一次初审,并向作者提出改进建议. +* 一旦满意,请用〜" database :: reviewed"重新标记 MR,批准,然后将 MR 重新分配给 Reviewer Roulette 建议的数据库**维护者** . + +数据库**维护者**的作用是: + +* 在 MR 上执行最终数据库审查. +* 与数据库审阅者和 MR 作者讨论进一步的改进或其他相关更改. +* 最后批准 MR,并使用〜" database :: approved"重新标记 MR +* 如果没有其他待批准的批准,则合并 MR,或根据需要将其传递给其他维护者(前端,后端,文档). + +### Distributing review workload[](#distributing-review-workload "Permalink") + +使用[审阅者轮盘](code_review.html#reviewer-roulette) ( [示例](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25181#note_147551725) )分配[审阅](code_review.html#reviewer-roulette)工作量. 然后,MR 作者应共同指派建议的数据库**审阅者** . 当他们批准时,他们将移交给建议的数据库**维护者** . + +如果审阅者轮盘赌没有建议数据库审阅者和维护者,请确保已应用〜database 标签并重新运行`danger-review` CI 作业,或从[`@gl-database`团队中](https://gitlab.com/groups/gl-database/-/group_members)选择某人. + +### How to prepare the merge request for a database review[](#how-to-prepare-the-merge-request-for-a-database-review "Permalink") + +为了使审核更加轻松快捷,请考虑以下准备工作. + +#### Preparation when adding migrations[](#preparation-when-adding-migrations "Permalink") + +* 确保`db/structure.sql`已按照[记录进行](migration_style_guide.html#schema-changes)更新. +* 通过使用`change`方法使迁移可逆,或者在使用`up`时包括`down`方法. + * 包括回滚过程或描述如何回滚更改. +* 将所有迁移的迁移和回滚的输出添加到 MR 描述中. + * 确保 down 方法还原`db/structure.sql`的更改. + * 在查看过程中,只要您修改迁移,就更新迁移输出. +* 如有必要,在`spec/migrations`添加迁移测试. 有关更多详细信息,请参见[在 GitLab 上测试 Rails 迁移](testing_guide/testing_migrations_guide.html) . +* 当迁移中涉及[高流量](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3)表时,请使用[`with_lock_retries`](migration_style_guide.html#retry-mechanism-when-acquiring-database-locks)帮助程序方法. 请查看[我们文档中](migration_style_guide.html#examples)的相关[示例以](migration_style_guide.html#examples)获取用例和解决方案. +* Ensure RuboCop checks are not disabled unless there’s a valid reason to. +* 将索引添加到[大表时](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3) ,请在`#database-lab` Slack 通道中使用`CREATE INDEX CONCURRENTLY`测试其执行,并将执行时间添加到 MR 描述中: + * `#database-lab`和 GitLab.com 之间的执行时间差异很大,但是`#database-lab`执行时间增加,可能暗示 GitLab.com 上的执行量也很高. + * 如果`#database-lab`的执行时间超过`1h` ,则应将索引移至[迁移后](post_deployment_migrations.html) . 请记住,在这种情况下,您可能需要将迁移和应用程序更改分为不同的版本,以确保在部署需要索引的代码时索引就位. + +#### Preparation when adding or modifying queries[](#preparation-when-adding-or-modifying-queries "Permalink") + +* 在 MR 说明中编写原始 SQL. 最好用[pgFormatter](https://sqlformat.darold.net)或[paste.depesz.com](https://paste.depesz.com)很好地格式化. +* 在描述中包括相关查询的`EXPLAIN (ANALYZE, BUFFERS)`输出. 如果输出太长,请将其包装在`
      `块中,将其粘贴到 GitLab 代码片段中,或在以下位置提供指向计划的链接: [explain.depesz.com](https://explain.depesz.com) . +* 提供查询计划时,请确保其命中足够的数据: + * 您可以通过`#database-lab` Slack 通道或[chatops](understanding_explain_plans.html#chatops)使用 GitLab 生产副本大规模测试查询. + * 通常, `gitlab-org`命名空间( `namespace_id = 9970` )和`gitlab-org/gitlab-foss` ( `project_id = 13083` )或`gitlab-org/gitlab` ( `project_id = 278964` )项目提供了足够的数据作为一个很好的例子. +* 对于查询的变化,最好是与*前*和变更*后*的方案一起提供的 SQL 查询. 这有助于快速发现差异. +* 包括显示性能改善的数据,最好以基准形式显示. + +#### Preparation when adding foreign keys to existing tables[](#preparation-when-adding-foreign-keys-to-existing-tables "Permalink") + +* **在**添加外键**之前,**进行迁移以删除源表中的孤立行. +* 删除所有`dependent: ...`实例`dependent: ...`可能不再需要. + +#### Preparation when adding tables[](#preparation-when-adding-tables "Permalink") + +* 根据" [订购表列"](ordering_table_columns.html)准则[订购列](ordering_table_columns.html) . +* 将外键添加到指向其他表中数据的任何列,包括[index](migration_style_guide.html#adding-foreign-key-constraints) . +* 为在诸如`WHERE` , `ORDER BY` , `GROUP BY`和`JOIN`的语句中使用的字段添加索引. + +#### Preparation when removing columns, tables, indexes, or other structures[](#preparation-when-removing-columns-tables-indexes-or-other-structures "Permalink") + +* 遵循[有关删除列](what_requires_downtime.html#dropping-columns)的[准则](what_requires_downtime.html#dropping-columns) . +* 通常,最佳实践(但不是硬性规定)是在部署后迁移中删除索引和外键. + * 例外包括删除小型表的索引和外键. +* 如果要添加复合索引,则另一个索引可能会变得多余,因此请在同一迁移中将其删除. 例如,添加`index(column_A, column_B, column_C)`会使索引`index(column_A, column_B)`和`index(column_A)`冗余. + +### How to review for database[](#how-to-review-for-database "Permalink") + +* 检查迁移 + * 审查关系建模和设计选择 + * 查看迁移遵循[数据库迁移样式指南](migration_style_guide.html) ,例如 + * [检查列的顺序](ordering_table_columns.html) + * [检查索引是否存在外键](migration_style_guide.html#adding-foreign-key-constraints) + * 确保迁移在事务中执行,或仅包含并发索引/外键助手(已禁用事务) + * 如果在`#database-lab`上添加了指向大表的索引,并且其执行时间增加了(超过 1h): + * 确保在迁移后将其添加. + * 维护者:合并请求合并后,在`#f_upcoming_release` Slack 频道`#f_upcoming_release`其通知发布管理器. + * 检查与`db/structure.sql`一致性,并且迁移是[可逆的](migration_style_guide.html#reversibility) + * 检查查询时间(如果有的话):在迁移中执行的查询需要在 GitLab.com 上适应`15s`以内(最好比`15s`少). + * 对于列删除,请确保[在先前版本中](what_requires_downtime.html#dropping-columns)已[忽略](what_requires_downtime.html#dropping-columns)该列 +* Check [background migrations](background_migrations.html): + * 建立在 GitLab.com 上执行的时间估计. 出于历史目的,强烈建议在合并请求描述中包括此估计. + * 如果单个`update`低于`1s` ,则可以将查询直接放入常规迁移中(在`db/migrate`内部). + * 通常使用后台迁移,但不限于: + * 在较大的表中迁移数据. + * 对数据集中的每条记录进行大量 SQL 查询. + * 查看查询(例如,确保批次大小合适) + * 因为执行时间可能比常规迁移要长,所以建议将后台迁移视为后期迁移:将它们放在`db/post_migrate`而不是`db/migrate` . 请记住,后迁移是在生产中的部署后执行的. +* Check [timing guidelines for migrations](#timing-guidelines-for-migrations) +* 检查迁移是可逆的,并实现`#down`方法 +* 检查数据迁移: + * 建立在 GitLab.com 上执行的时间估计. + * 根据时间的不同,可以将数据迁移放在常规,部署后或后台迁移上. + * 数据迁移也应该是可逆的,或者在可能的情况下附带有关如何逆向的描述. 这适用于所有类型的迁移(常规,部署后,后台). +* 查询效果 + * 检查是否有任何明显复杂的查询,以及作者特别指出要进行审查的查询(如果有) + * 如果尚不存在,请要求作者提供 SQL 查询和查询计划(例如,通过使用[chatops](understanding_explain_plans.html#chatops)或直接数据库访问) + * 对于给定的查询,请查看有关数据分配的参数 + * [检查查询计划](understanding_explain_plans.html)并提出对查询的改进建议(更改查询,架构或添加索引等) + * 一般准则是查询执行时间少于 100 毫秒 + * 如果查询依赖于尚未在生产环境中进行的先前迁移(例如,索引,列),则可以使用[还原管道](https://ops.gitlab.net/gitlab-com/gl-infra/gitlab-restore/postgres-gprd)中[的一次性实例](https://ops.gitlab.net/gitlab-com/gl-infra/gitlab-restore/postgres-gprd)来建立适当的测试环境. 如果您无权访问此项目,请访问 Slack 上的#database 以获取有关如何进行的建议. + * 避免 N + 1 问题并最大程度地减少[查询数](merge_request_performance_guidelines.html#query-counts) . + +### Timing guidelines for migrations[](#timing-guidelines-for-migrations "Permalink") + +通常,对于单个部署,GitLab.com 的迁移时间不应超过 1 个小时. 以下准则不是硬性规定,据估计,这些准则可将迁移时间降到最低. + +**注意:**请记住,所有运行时均应根据 GitLab.com 进行测量. + +| 迁移类型 | 建议执行时间 | Notes | +| --- | --- | --- | +| 定期迁移`db/migrate` | `3 minutes` | 一个有效的例外是创建索引,因为这可能需要很长时间. | +| 在`db/post_migrate`上发布迁移 | `10 minutes` |   | +| 后台迁移 |  — | 由于它们适用于较大的表,因此无法设置精确的时序准则,但是,任何单个查询的冷缓存都必须保持在`1 second`以下的执行时间. | \ No newline at end of file diff --git a/docs/562.md b/docs/562.md new file mode 100644 index 0000000000000000000000000000000000000000..0765bf894d5b4cc72578c6bf43b7758fa545d328 --- /dev/null +++ b/docs/562.md @@ -0,0 +1,157 @@ +# Database Review Guidelines + +> 原文:[https://docs.gitlab.com/ee/development/database_review.html](https://docs.gitlab.com/ee/development/database_review.html) + +* [General process](#general-process) + * [Roles and process](#roles-and-process) + * [Distributing review workload](#distributing-review-workload) + * [How to prepare the merge request for a database review](#how-to-prepare-the-merge-request-for-a-database-review) + * [Preparation when adding migrations](#preparation-when-adding-migrations) + * [Preparation when adding or modifying queries](#preparation-when-adding-or-modifying-queries) + * [Preparation when adding foreign keys to existing tables](#preparation-when-adding-foreign-keys-to-existing-tables) + * [Preparation when adding tables](#preparation-when-adding-tables) + * [Preparation when removing columns, tables, indexes, or other structures](#preparation-when-removing-columns-tables-indexes-or-other-structures) + * [How to review for database](#how-to-review-for-database) + * [Timing guidelines for migrations](#timing-guidelines-for-migrations) + +# Database Review Guidelines[](#database-review-guidelines "Permalink") + +此页面特定于数据库评论. 请参阅我们的[代码审查指南](code_review.html) ,以获取有关[代码审查](code_review.html)的更广泛建议和最佳实践. + +## General process[](#general-process "Permalink") + +A database review is required for: + +* 涉及数据库架构或执行数据迁移的更改,包括以下文件: + * `db/` + * `lib/gitlab/background_migration/` +* 对数据库工具的更改. 例如: + * `lib/gitlab/database/`迁移或 ActiveRecord 助手 + * 负载均衡 +* 产生 SQL 查询的更改超出了显而易见的范围. 通常由合并请求的作者决定是否引入复杂查询以及是否需要数据库审查. + +期望数据库审阅者在更改中查找明显复杂的查询,并仔细检查那些查询. 如果作者没有指出要审核的特定查询,并且没有明显复杂的查询,那么仅专注于审核迁移就足够了. + +最好以 SQL 形式复审查询,并且通常要求作者翻译 SQL 形式的任何 ActiveRecord 查询以复审. + +### Roles and process[](#roles-and-process "Permalink") + +合并请求**作者**的角色是: + +* 确定是否需要数据库审查. +* 如果需要数据库检查,请添加〜database 标签. +* [Prepare the merge request for a database review](#how-to-prepare-the-merge-request-for-a-database-review). + +数据库**审阅者**的角色是: + +* 对 MR 进行一次初审,并向作者提出改进建议. +* 一旦满意,请用〜" database :: reviewed"重新标记 MR,批准,然后将 MR 重新分配给 Reviewer Roulette 建议的数据库**维护者** . + +数据库**维护者**的作用是: + +* 在 MR 上执行最终数据库审查. +* 与数据库审阅者和 MR 作者讨论进一步的改进或其他相关更改. +* 最后批准 MR,并使用〜" database :: approved"重新标记 MR +* 如果没有其他待批准的批准,则合并 MR,或根据需要将其传递给其他维护者(前端,后端,文档). + +### Distributing review workload[](#distributing-review-workload "Permalink") + +使用[审阅者轮盘](code_review.html#reviewer-roulette) ( [示例](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25181#note_147551725) )分配[审阅](code_review.html#reviewer-roulette)工作量. 然后,MR 作者应共同指派建议的数据库**审阅者** . 当他们批准时,他们将移交给建议的数据库**维护者** . + +如果审阅者轮盘赌没有建议数据库审阅者和维护者,请确保已应用〜database 标签并重新运行`danger-review` CI 作业,或从[`@gl-database`团队中](https://gitlab.com/groups/gl-database/-/group_members)选择某人. + +### How to prepare the merge request for a database review[](#how-to-prepare-the-merge-request-for-a-database-review "Permalink") + +为了使审核更加轻松快捷,请考虑以下准备工作. + +#### Preparation when adding migrations[](#preparation-when-adding-migrations "Permalink") + +* 确保`db/structure.sql`已按照[记录进行](migration_style_guide.html#schema-changes)更新. +* 通过使用`change`方法使迁移可逆,或者在使用`up`时包括`down`方法. + * 包括回滚过程或描述如何回滚更改. +* 将所有迁移的迁移和回滚的输出添加到 MR 描述中. + * 确保 down 方法还原`db/structure.sql`的更改. + * 在查看过程中,只要您修改迁移,就更新迁移输出. +* 如有必要,在`spec/migrations`添加迁移测试. 有关更多详细信息,请参见[在 GitLab 上测试 Rails 迁移](testing_guide/testing_migrations_guide.html) . +* 当迁移中涉及[高流量](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3)表时,请使用[`with_lock_retries`](migration_style_guide.html#retry-mechanism-when-acquiring-database-locks)帮助程序方法. 请查看[我们文档中](migration_style_guide.html#examples)的相关[示例以](migration_style_guide.html#examples)获取用例和解决方案. +* Ensure RuboCop checks are not disabled unless there’s a valid reason to. +* 将索引添加到[大表时](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3) ,请在`#database-lab` Slack 通道中使用`CREATE INDEX CONCURRENTLY`测试其执行,并将执行时间添加到 MR 描述中: + * `#database-lab`和 GitLab.com 之间的执行时间差异很大,但是`#database-lab`执行时间增加,可能暗示 GitLab.com 上的执行量也很高. + * 如果`#database-lab`的执行时间超过`1h` ,则应将索引移至[迁移后](post_deployment_migrations.html) . 请记住,在这种情况下,您可能需要将迁移和应用程序更改分为不同的版本,以确保在部署需要索引的代码时索引就位. + +#### Preparation when adding or modifying queries[](#preparation-when-adding-or-modifying-queries "Permalink") + +* 在 MR 说明中编写原始 SQL. 最好用[pgFormatter](https://sqlformat.darold.net)或[paste.depesz.com](https://paste.depesz.com)很好地格式化. +* 在描述中包括相关查询的`EXPLAIN (ANALYZE, BUFFERS)`输出. 如果输出太长,请将其包装在`
      `块中,将其粘贴到 GitLab 代码片段中,或在以下位置提供指向计划的链接: [explain.depesz.com](https://explain.depesz.com) . +* 提供查询计划时,请确保其命中足够的数据: + * 您可以通过`#database-lab` Slack 通道或[chatops](understanding_explain_plans.html#chatops)使用 GitLab 生产副本大规模测试查询. + * 通常, `gitlab-org`命名空间( `namespace_id = 9970` )和`gitlab-org/gitlab-foss` ( `project_id = 13083` )或`gitlab-org/gitlab` ( `project_id = 278964` )项目提供了足够的数据作为一个很好的例子. +* 对于查询的变化,最好是与*前*和变更*后*的方案一起提供的 SQL 查询. 这有助于快速发现差异. +* 包括显示性能改善的数据,最好以基准形式显示. + +#### Preparation when adding foreign keys to existing tables[](#preparation-when-adding-foreign-keys-to-existing-tables "Permalink") + +* **在**添加外键**之前,**进行迁移以删除源表中的孤立行. +* 删除所有`dependent: ...`实例`dependent: ...`可能不再需要. + +#### Preparation when adding tables[](#preparation-when-adding-tables "Permalink") + +* 根据" [订购表列"](ordering_table_columns.html)准则[订购列](ordering_table_columns.html) . +* 将外键添加到指向其他表中数据的任何列,包括[index](migration_style_guide.html#adding-foreign-key-constraints) . +* 为在诸如`WHERE` , `ORDER BY` , `GROUP BY`和`JOIN`的语句中使用的字段添加索引. + +#### Preparation when removing columns, tables, indexes, or other structures[](#preparation-when-removing-columns-tables-indexes-or-other-structures "Permalink") + +* 遵循[有关删除列](what_requires_downtime.html#dropping-columns)的[准则](what_requires_downtime.html#dropping-columns) . +* 通常,最佳实践(但不是硬性规定)是在部署后迁移中删除索引和外键. + * 例外包括删除小型表的索引和外键. +* 如果要添加复合索引,则另一个索引可能会变得多余,因此请在同一迁移中将其删除. 例如,添加`index(column_A, column_B, column_C)`会使索引`index(column_A, column_B)`和`index(column_A)`冗余. + +### How to review for database[](#how-to-review-for-database "Permalink") + +* 检查迁移 + * 审查关系建模和设计选择 + * 查看迁移遵循[数据库迁移样式指南](migration_style_guide.html) ,例如 + * [检查列的顺序](ordering_table_columns.html) + * [检查索引是否存在外键](migration_style_guide.html#adding-foreign-key-constraints) + * 确保迁移在事务中执行,或仅包含并发索引/外键助手(已禁用事务) + * 如果在`#database-lab`上添加了指向大表的索引,并且其执行时间增加了(超过 1h): + * 确保在迁移后将其添加. + * 维护者:合并请求合并后,在`#f_upcoming_release` Slack 频道`#f_upcoming_release`其通知发布管理器. + * 检查与`db/structure.sql`一致性,并且迁移是[可逆的](migration_style_guide.html#reversibility) + * 检查查询时间(如果有的话):在迁移中执行的查询需要在 GitLab.com 上适应`15s`以内(最好比`15s`少). + * 对于列删除,请确保[在先前版本中](what_requires_downtime.html#dropping-columns)已[忽略](what_requires_downtime.html#dropping-columns)该列 +* Check [background migrations](background_migrations.html): + * 建立在 GitLab.com 上执行的时间估计. 出于历史目的,强烈建议在合并请求描述中包括此估计. + * 如果单个`update`低于`1s` ,则可以将查询直接放入常规迁移中(在`db/migrate`内部). + * 通常使用后台迁移,但不限于: + * 在较大的表中迁移数据. + * 对数据集中的每条记录进行大量 SQL 查询. + * 查看查询(例如,确保批次大小合适) + * 因为执行时间可能比常规迁移要长,所以建议将后台迁移视为后期迁移:将它们放在`db/post_migrate`而不是`db/migrate` . 请记住,后迁移是在生产中的部署后执行的. +* Check [timing guidelines for migrations](#timing-guidelines-for-migrations) +* 检查迁移是可逆的,并实现`#down`方法 +* 检查数据迁移: + * 建立在 GitLab.com 上执行的时间估计. + * 根据时间的不同,可以将数据迁移放在常规,部署后或后台迁移上. + * 数据迁移也应该是可逆的,或者在可能的情况下附带有关如何逆向的描述. 这适用于所有类型的迁移(常规,部署后,后台). +* 查询效果 + * 检查是否有任何明显复杂的查询,以及作者特别指出要进行审查的查询(如果有) + * 如果尚不存在,请要求作者提供 SQL 查询和查询计划(例如,通过使用[chatops](understanding_explain_plans.html#chatops)或直接数据库访问) + * 对于给定的查询,请查看有关数据分配的参数 + * [检查查询计划](understanding_explain_plans.html)并提出对查询的改进建议(更改查询,架构或添加索引等) + * 一般准则是查询执行时间少于 100 毫秒 + * 如果查询依赖于尚未在生产环境中进行的先前迁移(例如,索引,列),则可以使用[还原管道](https://ops.gitlab.net/gitlab-com/gl-infra/gitlab-restore/postgres-gprd)中[的一次性实例](https://ops.gitlab.net/gitlab-com/gl-infra/gitlab-restore/postgres-gprd)来建立适当的测试环境. 如果您无权访问此项目,请访问 Slack 上的#database 以获取有关如何进行的建议. + * 避免 N + 1 问题并最大程度地减少[查询数](merge_request_performance_guidelines.html#query-counts) . + +### Timing guidelines for migrations[](#timing-guidelines-for-migrations "Permalink") + +通常,对于单个部署,GitLab.com 的迁移时间不应超过 1 个小时. 以下准则不是硬性规定,据估计,这些准则可将迁移时间降到最低. + +**注意:**请记住,所有运行时均应根据 GitLab.com 进行测量. + +| 迁移类型 | 建议执行时间 | Notes | +| --- | --- | --- | +| 定期迁移`db/migrate` | `3 minutes` | 一个有效的例外是创建索引,因为这可能需要很长时间. | +| 在`db/post_migrate`上发布迁移 | `10 minutes` |   | +| 后台迁移 |  — | 由于它们适用于较大的表,因此无法设置精确的时序准则,但是,任何单个查询的冷缓存都必须保持在`1 second`以下的执行时间. | \ No newline at end of file diff --git a/docs/563.md b/docs/563.md new file mode 100644 index 0000000000000000000000000000000000000000..0fb587b4006c16998a56f4cec1f6e7de318d0796 --- /dev/null +++ b/docs/563.md @@ -0,0 +1,769 @@ +# Migration Style Guide + +> 原文:[https://docs.gitlab.com/ee/development/migration_style_guide.html](https://docs.gitlab.com/ee/development/migration_style_guide.html) + +* [Schema Changes](#schema-changes) +* [What Requires Downtime?](#what-requires-downtime) +* [Downtime Tagging](#downtime-tagging) +* [Reversibility](#reversibility) +* [Atomicity](#atomicity) +* [Heavy operations in a single transaction](#heavy-operations-in-a-single-transaction) +* [Retry mechanism when acquiring database locks](#retry-mechanism-when-acquiring-database-locks) + * [Examples](#examples) + * [When to use the helper method](#when-to-use-the-helper-method) + * [How the helper method works](#how-the-helper-method-works) +* [Multi-Threading](#multi-threading) +* [Removing indexes](#removing-indexes) +* [Adding indexes](#adding-indexes) +* [Adding foreign-key constraints](#adding-foreign-key-constraints) +* [`NOT NULL` constraints](#not-null-constraints) +* [Adding Columns With Default Values](#adding-columns-with-default-values) +* [Changing the column default](#changing-the-column-default) +* [Updating an existing column](#updating-an-existing-column) +* [Dropping a database table](#dropping-a-database-table) +* [Integer column type](#integer-column-type) +* [Strings and the Text data type](#strings-and-the-text-data-type) +* [Timestamp column type](#timestamp-column-type) +* [Storing JSON in database](#storing-json-in-database) +* [Testing](#testing) +* [Data migration](#data-migration) + * [Renaming reserved paths](#renaming-reserved-paths) + +# Migration Style Guide[](#migration-style-guide "Permalink") + +在为 GitLab 编写迁移时,必须考虑到这些迁移将由成千上万个各种规模的组织来运行,其中一些组织的数据库中包含多年的数据. + +此外,对于大多数组织来说,必须使服务器脱机以进行较小或较大的升级是一大负担. 因此,重要的是要仔细编写迁移文件,可以在线进行迁移,并遵守下面的样式指南. + +迁移**不准**要求 GitLab 设施采取离线,除非*绝对必要的* . + +如果需要停机,则必须通过以下方式批准迁移: + +1. 工程副总裁 +2. 后端维护者 +3. 数据库维护者 + +可以在[https://about.gitlab.com/company/team/中](https://about.gitlab.com/company/team/)找到持有这些头衔的人员的最新列表. + +When writing your migrations, also consider that databases might have stale data or inconsistencies and guard for that. Try to make as few assumptions as possible about the state of the database. + +请不要依赖特定于 GitLab 的代码,因为它可能会在将来的版本中更改. 如果需要,将 GitLab 代码复制粘贴到迁移中以使其向前兼容. + +对于 GitLab.com,请考虑到在[部署 Canary](https://about.gitlab.com/handbook/engineering/infrastructure/library/canary/#configuration-and-deployment)之前运行常规迁移(在`db/migrate` ),在完成生产部署后运行部署后的迁移( `db/post_migrate` ). + +## Schema Changes[](#schema-changes "Permalink") + +Changes to the schema should be committed to `db/structure.sql`. This file is automatically generated by Rails, so you normally should not edit this file by hand. If your migration is adding a column to a table, that column will be added at the bottom. Please do not reorder columns manually for existing tables as this will cause confusing to other people using `db/structure.sql` generated by Rails. + +当您的 GDK 中的本地数据库与`master`数据库中的模式不同时,可能很难将模式更改完全提交给 Git. 在这种情况下,您可以使用`scripts/regenerate-schema`脚本为要添加的迁移重新生成干净的`db/structure.sql` . 该脚本将应用在`db/migrate`或`db/post_migrate`找到的所有迁移,因此,如果您不想将任何迁移提交到架构,请重命名或删除它们. 如果您的分支不是以`master`为目标,则可以设置`TARGET`环境变量. + +``` +# Regenerate schema against `master` +scripts/regenerate-schema + +# Regenerate schema against `12-9-stable-ee` +TARGET=12-9-stable-ee scripts/regenerate-schema +``` + +## What Requires Downtime?[](#what-requires-downtime "Permalink") + +文档["什么需要停机?"](what_requires_downtime.html) 指定各种数据库操作,例如 + +* [dropping and renaming columns](what_requires_downtime.html#dropping-columns) +* [changing column constraints and types](what_requires_downtime.html#changing-column-constraints) +* [adding and dropping indexes, tables, and foreign keys](what_requires_downtime.html#adding-indexes) + +以及他们是否需要停机,以及如何尽可能地进行停机. + +## Downtime Tagging[](#downtime-tagging "Permalink") + +每个迁移都必须指定是否需要停机,并且如果需要停机,还必须指定原因. 这是即使在迁移的 99%,不需要停机,因为这使得它更容易地发现, *确实*需要停机迁移所需. + +要标记迁移,请在迁移类的主体中添加以下两个常量: + +* `DOWNTIME` :一个布尔值,当设置为`true`指示迁移需要停机时间. +* `DOWNTIME_REASON` :一个字符串,其中包含需要停机的迁移原因. 当`DOWNTIME`设置为`true`时, **必须**设置此常数. + +例如: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + DOWNTIME = true + DOWNTIME_REASON = 'This migration requires downtime because ...' + + def change + ... + end +end +``` + +如果迁移类中缺少`DOWNTIME`常量,则会出现错误(即 CI 将失败). + +## Reversibility[](#reversibility "Permalink") + +您的迁移**必须是**可逆的. 这非常重要,因为在出​​现漏洞或错误的情况下应该可以降级. + +在迁移中,添加一条注释,描述如何测试迁移的可逆性. + +某些迁移无法撤消. 例如,某些数据迁移无法撤消,因为在迁移之前,我们丢失了有关数据库状态的信息. 您仍然应该创建一个带注释的`down`方法,解释为什么不能撤消`up`方法执行的更改,以便即使撤消迁移期间执行的更改也可以撤消迁移本身: + +``` +def down + # no-op + + # comment explaining why changes performed by `up` cannot be reversed. +end +``` + +## Atomicity[](#atomicity "Permalink") + +默认情况下,迁移是单个事务. 即,在迁移开始时打开一个事务,并在处理完所有步骤后提交. + +在单个事务中运行迁移可确保如果其中一个步骤失败,则将不会执行任何步骤,从而使数据库保持有效状态. 因此,要么: + +* 将所有迁移都放在一个单事务迁移中. +* 如有必要,将大多数操作放入一个迁移中,并为无法在单个事务中完成的步骤创建一个单独的迁移. + +例如,如果创建一个空表并需要为其建立索引,则建议使用常规的单事务迁移和默认的 rails schema 语句: [`add_index`](https://api.rubyonrails.org/v5.2/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_index) . 这是一个阻塞操作,但不会引起问题,因为该表尚未使用,因此它还没有任何记录. + +## Heavy operations in a single transaction[](#heavy-operations-in-a-single-transaction "Permalink") + +使用单事务迁移时,事务将在迁移期间保持数据库连接,因此您必须确保迁移中的操作不会花费太多时间:通常,在迁移中执行的查询需要在 GitLab.com 上舒适地放置`15s` . + +如果您需要插入,更新或删除大量数据,请执行以下操作: + +* 必须使用`disable_ddl_transaction!`禁用单个事务`disable_ddl_transaction!` . +* 应该考虑在[后台迁移中](background_migrations.html)这样做. + +## Retry mechanism when acquiring database locks[](#retry-mechanism-when-acquiring-database-locks "Permalink") + +更改数据库架构时,我们使用辅助方法来调用 DDL(数据定义语言)语句. 在某些情况下,这些 DDL 语句需要特定的数据库锁. + +Example: + +``` +def change + remove_column :users, :full_name, :string +end +``` + +要执行此迁移,需要对`users`表进行排他锁定. 当表被其他进程同时访问和修改时,获取锁定可能需要一段时间. 锁定请求正在队列中等待,一旦进入队列,它也可能阻止`users`表上的其他查询. + +有关 PostgresSQL 锁的更多信息: [显式锁定](https://s0www0postgresql0org.icopy.site/docs/current/explicit-locking.html) + +出于稳定性考虑,GitLab.com 设置了特定的[`statement_timeout`](../user/gitlab_com/index.html#postgresql) . 调用迁移时,任何数据库查询都将有固定的执行时间. 在最坏的情况下,请求将坐在锁定队列中,在配置的语句超时时间内阻止其他查询,然后`canceling statement due to statement timeout`错误`canceling statement due to statement timeout`失败. + +此问题可能导致应用程序升级过程失败,甚至导致应用程序稳定性问题,因为该表可能会在短时间内无法访问. + +为了提高数据库迁移的可靠性和稳定性,GitLab 代码库提供了一种辅助方法,以使用不同的`lock_timeout`设置重试操作,并在两次尝试之间等待时间. 为了获得必要的锁定,进行了多次较小的尝试,从而使数据库可以处理其他语句. + +### Examples[](#examples "Permalink") + +**删除列:** + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + remove_column :users, :full_name + end +end + +def down + with_lock_retries do + add_column :users, :full_name, :string + end +end +``` + +**删除外键:** + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + remove_foreign_key :issues, :projects + end +end + +def down + with_lock_retries do + add_foreign_key :issues, :projects + end +end +``` + +**更改列的默认值:** + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + change_column_default :merge_requests, :lock_version, from: nil, to: 0 + end +end + +def down + with_lock_retries do + change_column_default :merge_requests, :lock_version, from: 0, to: nil + end +end +``` + +**用外键创建一个新表:** + +我们可以简单地用`with_lock_retries`包装`create_table`方法: + +``` +def up + with_lock_retries do + create_table :issues do |t| + t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade } + t.string :title, limit: 255 + end + end +end + +def down + drop_table :issues +end +``` + +**当我们有两个外键时创建一个新表:** + +为此,我们需要进行三个迁移: + +1. 创建不带外键(带有索引)的表. +2. 将外键添加到第一个表. +3. 将外键添加到第二个表. + +创建表: + +``` +def up + create_table :imports do |t| + t.bigint :project_id, null: false + t.bigint :user_id, null: false + t.string :jid, limit: 255 + end + + add_index :imports, :project_id + add_index :imports, :user_id +end + +def down + drop_table :imports +end +``` + +在`projects`添加外键: + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + add_foreign_key :imports, :projects, column: :project_id, on_delete: :cascade + end +end + +def down + with_lock_retries do + remove_foreign_key :imports, column: :project_id + end +end +``` + +向`users`添加外键: + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + add_foreign_key :imports, :users, column: :user_id, on_delete: :cascade + end +end + +def down + with_lock_retries do + remove_foreign_key :imports, column: :user_id + end +end +``` + +**与`disable_ddl_transaction!`配合使用`disable_ddl_transaction!`** + +通常, `with_lock_retries`帮助程序应与`disabled_ddl_transaction!` . 定制的 RuboCop 规则可确保只能将允许的方法放在锁重试块中. + +``` +disable_ddl_transaction! + +def up + with_lock_retries do + add_column :users, :name, :text + end + + add_text_limit :users, :name, 255 # Includes constraint validation (full table scan) +end +``` + +RuboCop 规则通常允许使用下面列出的标准 Rails 迁移方法. 此示例将导致 Rubocop 犯罪: + +``` +disabled_ddl_transaction! + +def up + with_lock_retries do + add_concurrent_index :users, :name + end +end +``` + +### When to use the helper method[](#when-to-use-the-helper-method "Permalink") + +通常使用标准的 Rails 迁移帮助器方法时,可以使用`with_lock_retries`帮助器方法. 如果在同一个表上执行多个迁移助手,则调用它们不是问题. + +当数据库迁移涉及高流量表之一时,建议使用`with_lock_retries`帮助程序方法: + +* `users` +* `projects` +* `namespaces` +* `issues` +* `merge_requests` +* `ci_pipelines` +* `ci_builds` +* `notes` + +更改示例: + +* `add_foreign_key` / `remove_foreign_key` +* `add_column` / `remove_column` +* `change_column_default` +* `create_table` / `drop_table` + +**注意:** `with_lock_retries`方法**不能**在`change`方法中使用,必须手动定义`up`和`down`方法以使迁移可逆. + +### How the helper method works[](#how-the-helper-method-works "Permalink") + +1. 重复 50 次. +2. 对于每次迭代,设置一个预配置的`lock_timeout` . +3. 尝试执行给定的块. ( `remove_column` ). +4. 如果出现`LockWaitTimeout`错误,请为预配置的`sleep_time`睡眠,然后重试该块. +5. 如果未引发错误,则当前迭代已成功执行该块. + +有关更多信息,请检查[`Gitlab::Database::WithLockRetries`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/with_lock_retries.rb)类. `with_lock_retries`帮助器方法在[`Gitlab::Database::MigrationHelpers`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/migration_helpers.rb)模块中实现. + +在最坏的情况下,该方法: + +* 在 40 分钟内最多执行 50 次该块. + * 大部分时间都花费在每次迭代后的预先配置的睡眠时段中. +* 第 50 次重试之后,将像标准迁移调用一样在没有`lock_timeout`情况下执行该块. +* 如果无法获取锁,则迁移将失败,并出现`statement timeout`错误. + +如果访问`users`表的事务运行时间很长(超过 40 分钟),则迁移可能会失败. + +## Multi-Threading[](#multi-threading "Permalink") + +有时,迁移可能需要使用多个 Ruby 线程来加快迁移速度. 为此,您的迁移需要包括模块`Gitlab::Database::MultiThreadedMigration` : + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + include Gitlab::Database::MultiThreadedMigration +end +``` + +然后可以使用`with_multiple_threads`方法在单独的线程中执行工作. 例如: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + include Gitlab::Database::MultiThreadedMigration + + def up + with_multiple_threads(4) do + disable_statement_timeout + + # ... + end + end +end +``` + +在这里,对`disable_statement_timeout`的调用将使用`with_multiple_threads`块本地的连接,而不是重新使用全局连接池. 这样可以确保每个线程都有自己的连接对象,并且在尝试获取一个连接对象时不会超时. + +**注意:** PostgreSQL 具有允许的最大连接数. 此限制因安装而异. 因此,建议您一次迁移不要使用超过 32 个线程. 通常,4-8 个线程应该绰绰有余. + +## Removing indexes[](#removing-indexes "Permalink") + +如果删除索引时表不为空,请确保使用方法`remove_concurrent_index`而不是常规的`remove_index`方法. `remove_concurrent_index`方法同时删除索引,因此不需要锁定,也无需停机. 要使用此方法,必须通过调用方法`disable_ddl_transaction!`禁用单交易模式`disable_ddl_transaction!` 在您的迁移类的主体中,如下所示: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + disable_ddl_transaction! + + def up + remove_concurrent_index :table_name, :column_name + end +end +``` + +请注意,在删除索引之前不必检查索引是否存在. + +对于较小的表(例如空表或少于`1,000`条记录的表),建议在单事务迁移中使用`remove_index` ,并将其与不需要`disable_ddl_transaction!`其他操作结合使用`disable_ddl_transaction!` . + +## Adding indexes[](#adding-indexes "Permalink") + +在添加索引之前,请考虑该索引是否必要. 在某些情况下可能不需要索引,例如: + +* 该表很小(少于`1,000`条记录),并且预计大小不会成倍增长. +* 任何现有索引都会过滤掉足够的行. +* 添加索引后查询时间的减少并不明显. + +另外,不需要宽索引来匹配查询的所有过滤条件,我们只需要覆盖足够多的列即可使索引查找具有足够小的选择性. 请查看我们的[添加数据库索引](adding_database_indexes.html)指南以获取更多详细信息. + +将索引添加到非空表时,请确保使用方法`add_concurrent_index`而不是常规的`add_index`方法. 使用 PostgreSQL 时, `add_concurrent_index`方法自动创建并发索引,从而消除了停机时间. + +要使用此方法,必须通过调用方法`disable_ddl_transaction!`禁用单交易模式`disable_ddl_transaction!` 在您的迁移类的主体中,如下所示: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :table, :column + end + + def down + remove_concurrent_index :table, :column + end +end +``` + +如果需要添加唯一索引,请记住,数据库中可能存在现有重复项. 这意味着在添加唯一索引之前,应始终*首先*添加一个删除所有重复项的迁移. + +对于小型表(例如空表或少于`1,000`条记录的表),建议在单事务迁移中使用`add_index` ,并将其与不需要`disable_ddl_transaction!`其他操作结合使用`disable_ddl_transaction!` . + +## Adding foreign-key constraints[](#adding-foreign-key-constraints "Permalink") + +向现有列或新列添加外键约束时,还请记住在该列上添加索引. + +这是所有外键所**必需**的,例如,为了支持有效的级联删除:当删除表中的许多行时,也需要删除引用的记录. 数据库必须在引用的表中查找相应的记录. 没有索引,这将导致对表进行顺序扫描,这可能需要很长时间. + +这是一个示例,其中我们添加了一个带有外键约束的新列. 请注意,它包括`index: true`为其创建索引. + +``` +class Migration < ActiveRecord::Migration[6.0] + + def change + add_reference :model, :other_model, index: true, foreign_key: { on_delete: :cascade } + end +end +``` + +当向非空表中的现有列添加外键约束时,我们必须使用`add_concurrent_foreign_key`和`add_concurrent_index`而不是`add_reference` . + +对于空表(例如新表),建议在单事务迁移中使用`add_reference` ,并将其与不需要`disable_ddl_transaction!`其他操作结合使用`disable_ddl_transaction!` . + +您可以阅读有关将[外键约束](database/add_foreign_key_to_existing_column.html)添加[到现有列的更多信息](database/add_foreign_key_to_existing_column.html) . + +## `NOT NULL` constraints[](#not-null-constraints "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38358) in GitLab 13.0. + +有关更多信息,请参见关于[`NOT NULL`约束](database/not_null_constraints.html)的样式指南. + +## Adding Columns With Default Values[](#adding-columns-with-default-values "Permalink") + +PostgreSQL 11 是自 GitLab 13.0 以来的最低版本,添加具有默认值的列变得更加容易,并且在所有情况下都应使用标准的`add_column`帮助器. + +在 PostgreSQL 11 之前,添加带有默认值的列是有问题的,因为这会导致全表重写. 相应的帮助程序`add_column_with_default`已被弃用,并将在以后的版本中删除. + +**注意:**如果%12.9 或更早版本需要向后端口添加具有默认值的列,则应使用`add_column_with_default`帮助器. 如果涉及[大表](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3) ,则禁止向后移植到%12.9. + +## Changing the column default[](#changing-the-column-default "Permalink") + +可能有人认为,使用`change_column_default`更改默认列对于较大的表来说是一项昂贵且破坏性的操作,但实际上并非如此. + +以以下迁移为例: + +``` +class DefaultRequestAccessGroups < ActiveRecord::Migration[5.2] + DOWNTIME = false + + def change + change_column_default(:namespaces, :request_access_enabled, from: false, to: true) + end +end +``` + +上面的迁移更改了我们最大的表之一的默认列值: `namespaces` . 可以将其翻译为: + +``` +ALTER TABLE namespaces +ALTER COLUMN request_access_enabled +DEFAULT false +``` + +在这种情况下,默认值存在,我们只是更改了`request_access_enabled`列的元数据,这并不意味着重写`namespaces`表中的所有现有记录. 仅当使用默认值创建新列时,所有记录才会被重写. + +**注意:** PostgresSQL 11.0 引入[了](https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/)更快的[ALTER TABLE ADD COLUMN(具有非空默认值](https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/) ),从而消除了在添加具有默认值的新列时重写表的需求. + +由于上述原因,在单事务迁移中使用`change_column_default`是安全的,而不需要`disable_ddl_transaction!` . + +## Updating an existing column[](#updating-an-existing-column "Permalink") + +要将现有列更新为特定值,可以使用`update_column_in_batches` . 这会将更新分为批次,因此我们不会在单个语句中更新太多行. + +这`some_column` `projects`表中的`foo`列更新为 10,其中`some_column`为`'hello'` : + +``` +update_column_in_batches(:projects, :foo, 10) do |table, query| + query.where(table[:some_column].eq('hello')) +end +``` + +如果需要计算的更新,则可以将值包装在`Arel.sql` ,因此 Arel 将其视为 SQL 文字. 这也是[Rails 6](https://gitlab.com/gitlab-org/gitlab/-/issues/28497)的必需弃用. + +下面的示例与上面的示例相同,但是该值设置为`bar`和`baz`列的乘积: + +``` +update_value = Arel.sql('bar * baz') + +update_column_in_batches(:projects, :foo, update_value) do |table, query| + query.where(table[:some_column].eq('hello')) +end +``` + +像`add_column_with_default`一样,有一个 RuboCop cop 可以检测大表上的用法. 在`update_column_in_batches`的情况下,可以在大表上运行,只要它仅更新表中行的一小部分,而在未在 GitLab.com 登台环境上进行验证的情况下不要忽略它-或事先请别人为您这样做. + +## Dropping a database table[](#dropping-a-database-table "Permalink") + +删除数据库表并不常见,Rails 提供的`drop_table`方法通常被认为是安全的. 删除表格之前,请考虑以下因素: + +如果您的表在高流量表上具有外键(如`projects` ),则`DROP TABLE`语句可能会失败,并出现**语句超时**错误. 确定哪些表是高流量可能很困难. 自我管理的实例可能会以不同的使用模式使用 GitLab 的不同功能,因此仅基于 GitLab.com 进行假设是不够的. + +表**没有记录** (功能从未使用过),也**没有外键** : + +* 只需在迁移中使用`drop_table`方法即可. + +``` +def change + drop_table :my_table +end +``` + +Table **有记录** but **没有外键**: + +* 第一版:删除与表相关的应用程序代码,例如模型,控制器和服务. +* 第二版:在迁移中使用`drop_table`方法. + +``` +def up + drop_table :my_table +end + +def down + # create_table ... +end +``` + +Table **有外键**: + +* 第一版:删除与表相关的应用程序代码,例如模型,控制器和服务. +* 第二版:使用`with_lock_retries`帮助器方法删除外键. 在另一个迁移文件中使用`drop_table` . + +**第二个版本的迁移:** + +删除`projects`表上的外键: + +``` +# first migration file + +def up + with_lock_retries do + remove_foreign_key :my_table, :projects + end +end + +def down + with_lock_retries do + add_foreign_key :my_table, :projects + end +end +``` + +放下桌子: + +``` +# second migration file + +def up + drop_table :my_table +end + +def down + # create_table ... +end +``` + +## Integer column type[](#integer-column-type "Permalink") + +默认情况下,整数列最多可容纳 4 个字节(32 位)的数字. 最大值为 2,147,483,647\. 创建一个以字节为单位保存文件大小的列时,请注意这一点. 如果以字节为单位跟踪文件大小,这会将最大文件大小限制为刚好超过 2GB. + +要允许整数列最多容纳 8 个字节(64 位)的数字,请将限制明确设置为 8 个字节. 这将使该列最多`9,223,372,036,854,775,807`个值. + +Rails 迁移示例: + +``` +add_column(:projects, :foo, :integer, default: 10, limit: 8) +``` + +## Strings and the Text data type[](#strings-and-the-text-data-type "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30453) . + +有关更多信息,请参见[文本数据类型](database/strings_and_the_text_data_type.html)样式指南. + +## Timestamp column type[](#timestamp-column-type "Permalink") + +默认情况下,Rails 使用`timestamp`数据类型来存储没有时区信息的时间戳数据. 通过调用`add_timestamps`或`timestamps`方法来使用`timestamp`数据类型. + +另外,Rails 将`:datetime`数据类型转换为`timestamp`一. + +Example: + +``` +# timestamps +create_table :users do |t| + t.timestamps +end + +# add_timestamps +def up + add_timestamps :users +end + +# :datetime +def up + add_column :users, :last_sign_in, :datetime +end +``` + +代替使用这些方法,应该使用以下方法来存储带有时区的时间戳: + +* `add_timestamps_with_timezone` +* `timestamps_with_timezone` +* `datetime_with_timezone` + +这样可以确保所有时间戳都有指定的时区. 反过来,这意味着当系统的时区更改时,现有时间戳不会突然使用其他时区. 这也使得非常清楚,首先使用了哪个时区. + +## Storing JSON in database[](#storing-json-in-database "Permalink") + +Rails 5 本机支持`JSONB` (二进制 JSON)列类型. 添加此列的示例迁移: + +``` +class AddOptionsToBuildMetadata < ActiveRecord::Migration[5.0] + DOWNTIME = false + + def change + add_column :ci_builds_metadata, :config_options, :jsonb + end +end +``` + +您必须使用序列化器来提供翻译层: + +``` +class BuildMetadata + serialize :config_options, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize +end +``` + +使用`JSONB`列时,请使用[JsonSchemaValidator](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/validators/json_schema_validator.rb)来控制随时间推移插入的数据. + +``` +class BuildMetadata + validates :config_options, json_schema: { filename: 'build_metadata_config_option' } +end +``` + +## Testing[](#testing "Permalink") + +请参阅" [测试 Rails 迁移](testing_guide/testing_migrations_guide.html)样式"指南. + +## Data migration[](#data-migration "Permalink") + +请比一般 ActiveRecord 语法更喜欢 Arel 和普通 SQL. 如果使用普通 SQL,则需要使用`quote_string` helper 手动引用所有输入. + +Arel 的示例: + +``` +users = Arel::Table.new(:users) +users.group(users[:user_id]).having(users[:id].count.gt(5)) + +#update other tables with these results +``` + +带有普通 SQL 和`quote_string`帮助器的示例: + +``` +select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(id) > 1").each do |tag| + tag_name = quote_string(tag["name"]) + duplicate_ids = select_all("SELECT id FROM tags WHERE name = '#{tag_name}'").map{|tag| tag["id"]} + origin_tag_id = duplicate_ids.first + duplicate_ids.delete origin_tag_id + + execute("UPDATE taggings SET tag_id = #{origin_tag_id} WHERE tag_id IN(#{duplicate_ids.join(",")})") + execute("DELETE FROM tags WHERE id IN(#{duplicate_ids.join(",")})") +end +``` + +如果需要更复杂的逻辑,则可以定义和使用迁移本地模型. 例如: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + class Project < ActiveRecord::Base + self.table_name = 'projects' + end + + def up + # Reset the column information of all the models that update the database + # to ensure the Active Record's knowledge of the table structure is current + Project.reset_column_information + + # ... ... + end +end +``` + +这样做时,请确保显式设置模型的表名,这样它就不会派生自类名或名称空间. + +最后,对于所有更新数据库的本地模型,请确保在迁移的`up`方法中运行`reset_column_information` . + +这样做的原因是所有迁移类都在开始时加载( `db:migrate`启动时),因此,如果另一个迁移更新了该模式,它们将与它们映射的表模式不同步. 这将导致在尝试插入基础表或对其进行更新时数据迁移失败,因为`ActiveRecord`将新列报告为`unknown attribute` . + +### Renaming reserved paths[](#renaming-reserved-paths "Permalink") + +引入新的项目路线时,它可能与任何现有记录冲突. 这些记录的路径应重命名,并且相关数据应在磁盘上移动. + +由于我们已经必须做几次,因此现在有一些帮助程序可以帮助您. + +要使用此功能,您可以在迁移中包括`Gitlab::Database::RenameReservedPathsMigration::V1` . 这将提供 3 种方法,您可以通过一种或多种需要拒绝的路径. + +**`rename_root_paths`** :这将使用给定名称重命名所有没有`parent_id`名称*空间*的路径. + +**`rename_child_paths`** :这将使用给定名称重命名所有具有`parent_id`名称*空间*的路径. + +**`rename_wildcard_paths`** :这将重命名所有*项目*的路径以及所有具有`project_id` *命名空间* . + +这些行的`path`列将重命名为其先前的值,后跟一个整数. 例如: `users`将变成`users0` \ No newline at end of file diff --git a/docs/564.md b/docs/564.md new file mode 100644 index 0000000000000000000000000000000000000000..8599965b910dbced1444b7316073dbfcd19370dc --- /dev/null +++ b/docs/564.md @@ -0,0 +1,357 @@ +# What requires downtime? + +> 原文:[https://docs.gitlab.com/ee/development/what_requires_downtime.html](https://docs.gitlab.com/ee/development/what_requires_downtime.html) + +* [Dropping Columns](#dropping-columns) + * [Step 1: Ignoring the column (release M)](#step-1-ignoring-the-column-release-m) + * [Step 2: Dropping the column (release M+1)](#step-2-dropping-the-column-release-m1) + * [Step 3: Removing the ignore rule (release M+2)](#step-3-removing-the-ignore-rule-release-m2) +* [Renaming Columns](#renaming-columns) + * [Step 1: Add The Regular Migration](#step-1-add-the-regular-migration) + * [Step 2: Add A Post-Deployment Migration](#step-2-add-a-post-deployment-migration) +* [Changing Column Constraints](#changing-column-constraints) +* [Changing Column Types](#changing-column-types) + * [Step 1: Create A Regular Migration](#step-1-create-a-regular-migration) + * [Step 2: Create A Post Deployment Migration](#step-2-create-a-post-deployment-migration) + * [Casting data to a new type](#casting-data-to-a-new-type) +* [Changing The Schema For Large Tables](#changing-the-schema-for-large-tables) +* [Adding Indexes](#adding-indexes) +* [Dropping Indexes](#dropping-indexes) +* [Adding Tables](#adding-tables) +* [Dropping Tables](#dropping-tables) +* [Renaming Tables](#renaming-tables) +* [Adding Foreign Keys](#adding-foreign-keys) +* [Removing Foreign Keys](#removing-foreign-keys) +* [Data Migrations](#data-migrations) + +# What requires downtime?[](#what-requires-downtime "Permalink") + +使用数据库时,可以在不使 GitLab 脱机的情况下执行某些操作,其他操作确实需要停机时间. 本指南介绍了各种操作,其影响以及如何在不停机的情况下执行这些操作. + +## Dropping Columns[](#dropping-columns "Permalink") + +删除列很棘手,因为正在运行的 GitLab 进程可能仍在使用这些列. 为了安全地解决此问题,您需要在三个版本中执行三个步骤: + +1. 忽略列(版本 M) +2. 删除列(版本 M + 1) +3. 删除忽略规则(版本 M + 2) + +之所以将其分布在三个发行版中,是因为删除列是一种破坏性操作,不易回滚. + +遵循此过程可帮助我们确保没有部署到 GitLab.com 并升级将这些步骤集中在一起的自我管理安装的过程. + +### Step 1: Ignoring the column (release M)[](#step-1-ignoring-the-column-release-m "Permalink") + +第一步是忽略应用程序代码中的列. 这是必要的,因为 Rails 缓存列并在各个地方重复使用此缓存. 这可以通过定义要忽略的列来完成. 例如,要忽略用户模型中的`updated_at` ,请使用以下命令: + +``` +class User < ApplicationRecord + include IgnorableColumns + ignore_column :updated_at, remove_with: '12.7', remove_after: '2019-12-22' +end +``` + +多列也可以忽略: + +``` +ignore_columns %i[updated_at created_at], remove_with: '12.7', remove_after: '2019-12-22' +``` + +我们要求通过以下方式指示何时可以安全地删除列忽略: + +* `remove_with` :设置为 GitLab 版本,通常在添加列忽略后两个版本(M + 2). +* `remove_after` :设置为一个日期,在该日期之后,我们认为通常可以在 M + 2 版本的开发周期内删除列忽略项. + +这些信息使我们能够更好地推理列忽略,并确保对于常规发行版和部署到 GitLab.com 而言,我们都不会过早删除列忽略. 例如,这避免了我们部署大量更改的情况,其中包括同时忽略列的更改和随后删除列忽略的更改(这将导致停机). + +在此示例中,忽略列的更改在 12.5 版中进行. + +### Step 2: Dropping the column (release M+1)[](#step-2-dropping-the-column-release-m1 "Permalink") + +继续我们的示例,删除该列将进入版本 12.6 中*的部署后*迁移: + +``` + remove_column :user, :updated_at +``` + +### Step 3: Removing the ignore rule (release M+2)[](#step-3-removing-the-ignore-rule-release-m2 "Permalink") + +在下一个版本中,在此示例 12.7 中,我们设置了另一个合并请求以删除忽略规则. 这将删除`ignore_column`行,并且如果不再需要,还将`IgnoreableColumns` . + +只有在`remove_after`日期过去之后,才应将其与`remove_with`指示的发行版合并. + +## Renaming Columns[](#renaming-columns "Permalink") + +重命名列通常需要停机,因为在数据库迁移期间/之后,应用程序可能会继续使用旧的列名称. 要在不停机的情况下重命名列,我们需要两个迁移:常规迁移和部署后迁移. 这些迁移都可以在同一版本中进行. + +### Step 1: Add The Regular Migration[](#step-1-add-the-regular-migration "Permalink") + +首先,我们需要创建常规迁移. 此迁移应当前使用`Gitlab::Database::MigrationHelpers#rename_column_concurrently`来执行重命名. 例如 + +``` +# A regular migration in db/migrate +class RenameUsersUpdatedAtToUpdatedAtTimestamp < ActiveRecord::Migration[4.2] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + def up + rename_column_concurrently :users, :updated_at, :updated_at_timestamp + end + + def down + undo_rename_column_concurrently :users, :updated_at, :updated_at_timestamp + end +end +``` + +这将负责重命名列,确保数据保持同步,通过索引和外键进行复制等. + +**注意:**如果一列包含 1 个或多个不包含原始列名称的索引,则上述过程将失败. 在这种情况下,您首先需要重命名这些索引. + +### Step 2: Add A Post-Deployment Migration[](#step-2-add-a-post-deployment-migration "Permalink") + +重命名过程需要在部署后迁移中进行一些清理. 我们可以使用`Gitlab::Database::MigrationHelpers#cleanup_concurrent_column_rename`来执行此清理: + +``` +# A post-deployment migration in db/post_migrate +class CleanupUsersUpdatedAtRename < ActiveRecord::Migration[4.2] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + def up + cleanup_concurrent_column_rename :users, :updated_at, :updated_at_timestamp + end + + def down + undo_cleanup_concurrent_column_rename :users, :updated_at, :updated_at_timestamp + end +end +``` + +**注意:**如果要重命名[大表](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3) ,请仔细考虑第一次迁移已运行但第二次清理迁移尚未运行的状态. 使用[Canary](https://about.gitlab.com/handbook/engineering/infrastructure/library/canary/) ,系统可能会在此状态下运行大量时间. + +## Changing Column Constraints[](#changing-column-constraints "Permalink") + +通常,无需停机即可添加或删除`NOT NULL`子句(或其他约束). 但是,这确实需要*首先*部署所有应用程序更改. 因此,在部署后的迁移中应该发生更改列约束的情况. + +避免使用`change_column`因为它会产生无效查询,因为它会重新定义整个列类型. + +您可以针对每个特定用例查看以下指南: + +* [Adding foreign-key constraints](migration_style_guide.html#adding-foreign-key-constraints) +* [Adding `NOT NULL` constraints](database/not_null_constraints.html) +* [Adding limits to text columns](database/strings_and_the_text_data_type.html) + +## Changing Column Types[](#changing-column-types "Permalink") + +可以使用`Gitlab::Database::MigrationHelpers#change_column_type_concurrently`来更改列的类型. 此方法的工作方式与`rename_column_concurrently`类似. 例如,假设我们要将`users.username`的类型从`string`更改为`text` . + +### Step 1: Create A Regular Migration[](#step-1-create-a-regular-migration "Permalink") + +常规迁移用于创建具有临时名称的新列,并设置一些触发器以使数据保持同步. 这样的迁移如下所示: + +``` +# A regular migration in db/migrate +class ChangeUsersUsernameStringToText < ActiveRecord::Migration[4.2] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + def up + change_column_type_concurrently :users, :username, :text + end + + def down + cleanup_concurrent_column_type_change :users, :username + end +end +``` + +### Step 2: Create A Post Deployment Migration[](#step-2-create-a-post-deployment-migration "Permalink") + +接下来,我们需要使用部署后迁移来清理更改: + +``` +# A post-deployment migration in db/post_migrate +class ChangeUsersUsernameStringToTextCleanup < ActiveRecord::Migration[4.2] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + def up + cleanup_concurrent_column_type_change :users, :username + end + + def down + change_column_type_concurrently :users, :username, :string + end +end +``` + +就是这样,我们完成了! + +### Casting data to a new type[](#casting-data-to-a-new-type "Permalink") + +某些类型更改需要将数据转换为新类型. 例如,从`text`更改为`jsonb` . 在这种情况下,请使用`type_cast_function`选项. 确保没有不良数据,并且投射将始终成功. 您还可以提供一个自定义函数来处理转换错误. + +迁移示例: + +``` + def up + change_column_type_concurrently :users, :settings, :jsonb, type_cast_function: 'jsonb' + end +``` + +## Changing The Schema For Large Tables[](#changing-the-schema-for-large-tables "Permalink") + +虽然`change_column_type_concurrently`和`rename_column_concurrently`可以用于在`rename_column_concurrently`机的情况下更改表的架构,但对于大型表来说,效果并不理想. 由于所有工作都是按顺序进行的,因此迁移可能需要很长时间才能完成,从而阻止了部署的进行. 由于数据库按顺序快速更新许多行,因此它们也可能给数据库带来很大压力. + +为减轻数据库压力,在迁移大表中的列时(例如`issues` ),应改用`change_column_type_using_background_migration`或`rename_column_using_background_migration` . 这些方法的工作方式与并发的类似,但是使用后台迁移将工作/负载分散在更长的时间段内,而不会减慢部署速度. + +例如,要使用后台迁移来更改列类型: + +``` +class ExampleMigration < ActiveRecord::Migration[4.2] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + class Issue < ActiveRecord::Base + self.table_name = 'issues' + + include EachBatch + + def self.to_migrate + where('closed_at IS NOT NULL') + end + end + + def up + change_column_type_using_background_migration( + Issue.to_migrate, + :closed_at, + :datetime_with_timezone + ) + end + + def down + change_column_type_using_background_migration( + Issue.to_migrate, + :closed_at, + :datetime + ) + end +end +``` + +这将将`issues.closed_at`的类型更改为`timestamp with time zone` . + +请记住,传递给`change_column_type_using_background_migration`的关系*必须*包含`EachBatch` ,否则将引发`TypeError` . + +然后,此迁移需要在单独的发行版( *而不是*补丁程序发行版)中进行清除迁移,该清除迁移应从队列中窃取并处理所有剩余的行. 例如: + +``` +class MigrateRemainingIssuesClosedAt < ActiveRecord::Migration[4.2] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + class Issue < ActiveRecord::Base + self.table_name = 'issues' + include EachBatch + end + + def up + Gitlab::BackgroundMigration.steal('CopyColumn') + Gitlab::BackgroundMigration.steal('CleanupConcurrentTypeChange') + + migrate_remaining_rows if migrate_column_type? + end + + def down + # Previous migrations already revert the changes made here. + end + + def migrate_remaining_rows + Issue.where('closed_at_for_type_change IS NULL AND closed_at IS NOT NULL').each_batch do |batch| + batch.update_all('closed_at_for_type_change = closed_at') + end + + cleanup_concurrent_column_type_change(:issues, :closed_at) + end + + def migrate_column_type? + # Some environments may have already executed the previous version of this + # migration, thus we don't need to migrate those environments again. + column_for('issues', 'closed_at').type == :datetime # rubocop:disable Migration/Datetime + end +end +``` + +这同样适用于`rename_column_using_background_migration` : + +1. 使用帮助程序创建迁移,该迁移将安排后台迁移以将写入分散在更长的时间范围内. +2. 在下一个每月发行版中,创建清理迁移以从 Sidekiq 队列中窃取,迁移所有丢失的行并清理重命名. 如果该列已被重命名,则此迁移应在从 Sidekiq 队列中窃取后跳过步骤. + +有关更多信息,请参阅[有关清理后台迁移的文档](background_migrations.html#cleaning-up) . + +## Adding Indexes[](#adding-indexes "Permalink") + +使用`add_concurrent_index`时,添加索引不需要停机. + +另请参阅《 [迁移样式指南》](migration_style_guide.html#adding-indexes) . + +## Dropping Indexes[](#dropping-indexes "Permalink") + +删除索引不需要停机. + +## Adding Tables[](#adding-tables "Permalink") + +此操作是安全的,因为还没有使用该表的代码. + +## Dropping Tables[](#dropping-tables "Permalink") + +使用部署后迁移可以安全地完成删除表的操作,但前提是应用程序不再使用该表. + +## Renaming Tables[](#renaming-tables "Permalink") + +重命名表需要停机,因为在数据库迁移期间/之后,应用程序可能会继续使用旧表名. + +## Adding Foreign Keys[](#adding-foreign-keys "Permalink") + +添加外键通常需要 3 个步骤: + +1. 开始交易 +2. 运行`ALTER TABLE`添加约束 +3. 检查所有现有数据 + +因为`ALTER TABLE`通常会在事务结束之前获取独占锁,所以这意味着该方法将需要停机. + +GitLab allows you to work around this by using `Gitlab::Database::MigrationHelpers#add_concurrent_foreign_key`. This method ensures that no downtime is needed. + +## Removing Foreign Keys[](#removing-foreign-keys "Permalink") + +此操作不需要停机. + +## Data Migrations[](#data-migrations "Permalink") + +数据迁移可能很棘手. 迁移数据的通常方法是采取 3 个步骤: + +1. 迁移初始数据 +2. 部署应用程序代码 +3. 迁移所有剩余数据 + +通常这有效,但并非总是如此. 例如,如果要将字段的格式从 JSON 更改为其他格式,我们会遇到一些问题. 如果我们在部署应用程序代码之前更改现有数据,则很可能会遇到错误. 另一方面,如果我们在部署应用程序代码后进行迁移,则可能会遇到相同的问题. + +如果您只需要更正一些无效数据,则部署后迁移通常就足够了. 如果您需要更改数据格式(例如,从 JSON 更改为其他格式),通常最好为新数据格式添加一个新列,然后让应用程序使用该列. 在这种情况下,程序将是: + +1. 以新格式添加新列 +2. 将现有数据复制到此新列 +3. 部署应用程序代码 +4. In a post-deployment migration, copy over any remaining data + +通常,没有一个万能的解决方案,因此最好在合并请求中讨论此类迁移,以确保以最佳方式实现它们. \ No newline at end of file diff --git a/docs/565.md b/docs/565.md new file mode 100644 index 0000000000000000000000000000000000000000..a01e6aa93ef787f3962a4ea9c6bdd9a75ea10b44 --- /dev/null +++ b/docs/565.md @@ -0,0 +1,647 @@ +# Understanding EXPLAIN plans + +> 原文:[https://docs.gitlab.com/ee/development/understanding_explain_plans.html](https://docs.gitlab.com/ee/development/understanding_explain_plans.html) + +* [Nodes](#nodes) +* [Node statistics](#node-statistics) +* [Node types](#node-types) + * [Seq Scan](#seq-scan) + * [Index Only Scan](#index-only-scan) + * [Index Scan](#index-scan) + * [Bitmap Index Scan and Bitmap Heap scan](#bitmap-index-scan-and-bitmap-heap-scan) + * [Limit](#limit) + * [Sort](#sort) + * [Nested Loop](#nested-loop) +* [Optimising queries](#optimising-queries) +* [Queries that can’t be optimised](#queries-that-cant-be-optimised) + * [Cardinality and selectivity](#cardinality-and-selectivity) +* [Rewriting queries](#rewriting-queries) +* [What makes a bad plan](#what-makes-a-bad-plan) +* [Producing query plans](#producing-query-plans) + * [Rails console](#rails-console) + * [ChatOps](#chatops) + * [`#database-lab`](#database-lab) + * [Tips & Tricks](#tips--tricks) +* [Further reading](#further-reading) + +# Understanding EXPLAIN plans[](#understanding-explain-plans "Permalink") + +PostgreSQL 允许您使用`EXPLAIN`命令获得查询计划. 尝试确定查询的执行方式时,此命令非常有用. 您可以在 SQL 查询中直接使用此命令,只要查询以它开头即可: + +``` +EXPLAIN +SELECT COUNT(*) +FROM projects +WHERE visibility_level IN (0, 20); +``` + +在 GitLab.com 上运行时,将显示以下输出: + +``` +Aggregate (cost=922411.76..922411.77 rows=1 width=8) + -> Seq Scan on projects (cost=0.00..908044.47 rows=5746914 width=0) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) +``` + +当*仅*使用`EXPLAIN` ,PostgreSQL 实际上不会执行我们的查询,而是会根据可用的统计信息生成一个*估计的*执行计划. 这意味着实际计划可能相差很大. 幸运的是,PostgreSQL 还为我们提供了执行查询的选项. 为此,我们需要使用`EXPLAIN ANALYZE`而不是`EXPLAIN` : + +``` +EXPLAIN ANALYZE +SELECT COUNT(*) +FROM projects +WHERE visibility_level IN (0, 20); +``` + +这将产生: + +``` +Aggregate (cost=922420.60..922420.61 rows=1 width=8) (actual time=3428.535..3428.535 rows=1 loops=1) + -> Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) + Rows Removed by Filter: 65677 +Planning time: 2.861 ms +Execution time: 3428.596 ms +``` + +如我们所见,该计划是完全不同的,并且包含许多数据. 让我们逐步讨论一下. + +由于`EXPLAIN ANALYZE`执行查询,因此在使用会写入数据或可能会超时的查询时应`EXPLAIN ANALYZE`小心. 如果查询修改了数据,请考虑将其包装在自动回滚的事务中,如下所示: + +``` +BEGIN; +EXPLAIN ANALYZE +DELETE FROM users WHERE id = 1; +ROLLBACK; +``` + +`EXPLAIN`命令还包含其他选项,例如`BUFFERS` : + +``` +EXPLAIN (ANALYZE, BUFFERS) +SELECT COUNT(*) +FROM projects +WHERE visibility_level IN (0, 20); +``` + +然后将产生: + +``` +Aggregate (cost=922420.60..922420.61 rows=1 width=8) (actual time=3428.535..3428.535 rows=1 loops=1) + Buffers: shared hit=208846 + -> Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) + Rows Removed by Filter: 65677 + Buffers: shared hit=208846 +Planning time: 2.861 ms +Execution time: 3428.596 ms +``` + +有关更多信息,请参阅官方的[`EXPLAIN`文档](https://s0www0postgresql0org.icopy.site/docs/current/sql-explain.html)并[使用`EXPLAIN`指南](https://s0www0postgresql0org.icopy.site/docs/current/using-explain.html) . + +## Nodes[](#nodes "Permalink") + +每个查询计划都由节点组成. 节点可以嵌套,并且可以由内而外执行. 这意味着最内部的节点在外部节点之前执行. 最好将其视为嵌套函数调用,并在展开时返回其结果. 例如,一个计划以`Aggregate`开头,然后是`Nested Loop` ,然后是`Index Only scan`可以认为是以下 Ruby 代码: + +``` +aggregate( + nested_loop( + index_only_scan() + index_only_scan() + ) +) +``` + +节点使用`->`表示,后跟所采用的节点类型. 例如: + +``` +Aggregate (cost=922411.76..922411.77 rows=1 width=8) + -> Seq Scan on projects (cost=0.00..908044.47 rows=5746914 width=0) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) +``` + +这里执行的第一个节点是`Seq scan on projects` . `Filter:`是应用于节点结果的附加过滤器. 过滤器与 Ruby 的`Array#select`非常相似:它接受输入行,应用过滤器,并生成新的行列表. 节点完成后,我们将在其上方执行`Aggregate` . + +嵌套节点将如下所示: + +``` +Aggregate (cost=176.97..176.98 rows=1 width=8) (actual time=0.252..0.252 rows=1 loops=1) + Buffers: shared hit=155 + -> Nested Loop (cost=0.86..176.75 rows=87 width=0) (actual time=0.035..0.249 rows=36 loops=1) + Buffers: shared hit=155 + -> Index Only Scan using users_pkey on users users_1 (cost=0.43..4.95 rows=87 width=4) (actual time=0.029..0.123 rows=36 loops=1) + Index Cond: (id < 100) + Heap Fetches: 0 + -> Index Only Scan using users_pkey on users (cost=0.43..1.96 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=36) + Index Cond: (id = users_1.id) + Heap Fetches: 0 +Planning time: 2.585 ms +Execution time: 0.310 ms +``` + +在这里,我们首先执行两次单独的"仅索引"扫描,然后对这两次扫描的结果执行"嵌套循环". + +## Node statistics[](#node-statistics "Permalink") + +计划中的每个节点都有一组关联的统计信息,例如成本,产生的行数,执行的循环数等等. 例如: + +``` +Seq Scan on projects (cost=0.00..908044.47 rows=5746914 width=0) +``` + +在这里,我们可以看到我们的成本范围为`0.00..908044.47` (稍后我们将对此进行介绍),并且我们估计(因为我们使用的是`EXPLAIN`而不是`EXPLAIN ANALYZE` ),因此此节点将产生总计 5,746,914 行. `width`统计信息描述了每行的估计宽度,以字节为单位. + +`costs`字段指定节点的价格. 成本以查询计划者的成本参数确定的任意单位衡量. 影响成本的因素取决于各种设置,例如`seq_page_cost` , `cpu_tuple_cost`和其他各种设置. 费用字段的格式如下: + +``` +STARTUP COST..TOTAL COST +``` + +The startup cost states how expensive it was to start the node, with the total cost describing how expensive the entire node was. In general: the greater the values, the more expensive the node. + +使用`EXPLAIN ANALYZE` ,这些统计信息还将包括实际花费的时间(以毫秒为单位)以及其他运行时统计信息(例如,产生的行的实际数量): + +``` +Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1) +``` + +在这里我们可以看到估计返回了 5,746,969 行,但实际上,我们返回了 5,746,940 行. 我们还可以看到, *仅*此顺序扫描就花费了 2.98 秒. + +使用`EXPLAIN (ANALYZE, BUFFERS)`还将为我们提供有关由过滤器删除的行数,使用的缓冲区数等信息. 例如: + +``` +Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) + Rows Removed by Filter: 65677 + Buffers: shared hit=208846 +``` + +在这里,我们可以看到我们的过滤器必须删除 65,677 行,并使用 208,846 个缓冲区. PostgreSQL 中的每个缓冲区都是 8 KB(8192 字节),这意味着我们上面的节点使用*1.6 GB 的缓冲区* . 好多啊! + +## Node types[](#node-types "Permalink") + +有很多不同类型的节点,因此我们在这里仅介绍一些较常见的节点. + +可以在[PostgreSQL 源文件`plannodes.h`](https://gitlab.com/postgres/postgres/blob/master/src/include/nodes/plannodes.h)找到所有可用节点及其描述的完整列表. + +### Seq Scan[](#seq-scan "Permalink") + +对数据库表(的一部分)进行顺序扫描. 这类似于使用`Array#each` ,但是在数据库表上. 检索大量行时,顺序扫描可能会非常慢,因此,对于大型表,最好避免使用这些扫描. + +### Index Only Scan[](#index-only-scan "Permalink") + +对不需要从表中获取任何内容的索引进行的扫描. 在某些情况下,仅索引扫描仍可能从表中获取数据,在这种情况下,节点将包含" `Heap Fetches:`统计信息. + +### Index Scan[](#index-scan "Permalink") + +对索引的扫描,该索引需要从表中检索一些数据. + +### Bitmap Index Scan and Bitmap Heap scan[](#bitmap-index-scan-and-bitmap-heap-scan "Permalink") + +位图扫描介于顺序扫描和索引扫描之间. 当我们从索引扫描中读取太多数据但执行顺序扫描时读取的数据太少时,通常会使用它们. 位图扫描使用所谓的[位图索引](https://en.wikipedia.org/wiki/Bitmap_index)来执行其工作. + +[PostgreSQL](https://gitlab.com/postgres/postgres/blob/REL_11_STABLE/src/include/nodes/plannodes.h#L441)的[源代码在位](https://gitlab.com/postgres/postgres/blob/REL_11_STABLE/src/include/nodes/plannodes.h#L441)图扫描中指出以下内容: + +> 位图索引扫描提供潜在元组位置的位图; 它不访问堆本身. 该位图可能由祖先位图堆扫描节点使用,可能是在经过中间位图和和/或位图或节点之后将其与其他位图索引扫描的结果组合在一起的. + +### Limit[](#limit "Permalink") + +在输入行上应用`LIMIT` . + +### Sort[](#sort "Permalink") + +使用`ORDER BY`语句对输入行进行排序. + +### Nested Loop[](#nested-loop "Permalink") + +嵌套循环将针对其前面的节点产生的每一行执行其子节点. 例如: + +``` +-> Nested Loop (cost=0.86..176.75 rows=87 width=0) (actual time=0.035..0.249 rows=36 loops=1) + Buffers: shared hit=155 + -> Index Only Scan using users_pkey on users users_1 (cost=0.43..4.95 rows=87 width=4) (actual time=0.029..0.123 rows=36 loops=1) + Index Cond: (id < 100) + Heap Fetches: 0 + -> Index Only Scan using users_pkey on users (cost=0.43..1.96 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=36) + Index Cond: (id = users_1.id) + Heap Fetches: 0 +``` + +在这里,第一个子节点( `Index Only Scan using users_pkey on users users_1` )产生 36 行,并执行一次( `rows=36 loops=1` ). 下一个节点产生 1 行( `rows=1` ),但重复 36 次( `loops=36` ). 这是因为前一个节点产生了 36 行. + +这意味着,如果各个子节点继续产生许多行,则嵌套循环会迅速降低查询速度. + +## Optimising queries[](#optimising-queries "Permalink") + +顺便说一句,让我们看看如何优化查询. 让我们以以下查询为例: + +``` +SELECT COUNT(*) +FROM users +WHERE twitter != ''; +``` + +该查询仅计算设置了 Twitter 个人资料的用户数. 让我们使用`EXPLAIN (ANALYZE, BUFFERS)`运行它: + +``` +EXPLAIN (ANALYZE, BUFFERS) +SELECT COUNT(*) +FROM users +WHERE twitter != ''; +``` + +这将产生以下计划: + +``` +Aggregate (cost=845110.21..845110.22 rows=1 width=8) (actual time=1271.157..1271.158 rows=1 loops=1) + Buffers: shared hit=202662 + -> Seq Scan on users (cost=0.00..844969.99 rows=56087 width=0) (actual time=0.019..1265.883 rows=51833 loops=1) + Filter: ((twitter)::text <> ''::text) + Rows Removed by Filter: 2487813 + Buffers: shared hit=202662 +Planning time: 0.390 ms +Execution time: 1271.180 ms +``` + +从该查询计划中,我们可以看到以下内容: + +1. 我们需要对`users`表执行顺序扫描. +2. 此顺序扫描使用`Filter`过滤掉 2,487,813 行. +3. 我们使用 202,622 个缓冲区,相当于 1.58 GB 的内存. +4. 完成所有这些操作需要 1.2 秒. + +考虑到我们只是在计算用户,这是相当昂贵的! + +在开始进行任何更改之前,让我们看一下`users`表上是否有可以使用的现有索引. 我们可以通过在`psql`控制台中运行`\d users` ,然后向下滚动至`Indexes:`部分来获取此信息: + +``` +Indexes: + "users_pkey" PRIMARY KEY, btree (id) + "index_users_on_confirmation_token" UNIQUE, btree (confirmation_token) + "index_users_on_email" UNIQUE, btree (email) + "index_users_on_reset_password_token" UNIQUE, btree (reset_password_token) + "index_users_on_static_object_token" UNIQUE, btree (static_object_token) + "index_users_on_unlock_token" UNIQUE, btree (unlock_token) + "index_on_users_name_lower" btree (lower(name::text)) + "index_users_on_accepted_term_id" btree (accepted_term_id) + "index_users_on_admin" btree (admin) + "index_users_on_created_at" btree (created_at) + "index_users_on_email_trigram" gin (email gin_trgm_ops) + "index_users_on_feed_token" btree (feed_token) + "index_users_on_group_view" btree (group_view) + "index_users_on_incoming_email_token" btree (incoming_email_token) + "index_users_on_managing_group_id" btree (managing_group_id) + "index_users_on_name" btree (name) + "index_users_on_name_trigram" gin (name gin_trgm_ops) + "index_users_on_public_email" btree (public_email) WHERE public_email::text <> ''::text + "index_users_on_state" btree (state) + "index_users_on_state_and_user_type" btree (state, user_type) + "index_users_on_unconfirmed_email" btree (unconfirmed_email) WHERE unconfirmed_email IS NOT NULL + "index_users_on_user_type" btree (user_type) + "index_users_on_username" btree (username) + "index_users_on_username_trigram" gin (username gin_trgm_ops) + "tmp_idx_on_user_id_where_bio_is_filled" btree (id) WHERE COALESCE(bio, ''::character varying)::text IS DISTINCT FROM ''::text +``` + +在这里,我们可以看到`twitter`列上没有索引,这意味着 PostgreSQL 在这种情况下必须执行顺序扫描. 让我们尝试通过添加以下索引来解决此问题: + +``` +CREATE INDEX CONCURRENTLY twitter_test ON users (twitter); +``` + +如果现在使用`EXPLAIN (ANALYZE, BUFFERS)`重新运行查询`EXPLAIN (ANALYZE, BUFFERS)`得到以下计划: + +``` +Aggregate (cost=61002.82..61002.83 rows=1 width=8) (actual time=297.311..297.312 rows=1 loops=1) + Buffers: shared hit=51854 dirtied=19 + -> Index Only Scan using twitter_test on users (cost=0.43..60873.13 rows=51877 width=0) (actual time=279.184..293.532 rows=51833 loops=1) + Filter: ((twitter)::text <> ''::text) + Rows Removed by Filter: 2487830 + Heap Fetches: 26037 + Buffers: shared hit=51854 dirtied=19 +Planning time: 0.191 ms +Execution time: 297.334 ms +``` + +现在获取数据只需不到 300 毫秒,而不是 1.2 秒. 但是,我们仍然使用 51,854 个缓冲区,这大约是 400 MB 的内存. 对于这种简单的查询,300 毫秒的速度也很慢. 要了解为什么此查询仍然昂贵,让我们看一下以下内容: + +``` +Index Only Scan using twitter_test on users (cost=0.43..60873.13 rows=51877 width=0) (actual time=279.184..293.532 rows=51833 loops=1) + Filter: ((twitter)::text <> ''::text) + Rows Removed by Filter: 2487830 +``` + +我们从仅对索引进行索引扫描开始,但是我们仍然以某种方式应用了`Filter` ,该过滤`Filter`可过滤掉 2,487,830 行. 这是为什么? 好,让我们看一下如何创建索引: + +``` +CREATE INDEX CONCURRENTLY twitter_test ON users (twitter); +``` + +我们只是简单地告诉 PostgreSQL 索引`twitter`列的所有可能值,甚至是空字符串. 我们的查询反过来使用`WHERE twitter != ''` . 这意味着索引确实可以改善事情,因为我们不需要进行顺序扫描,但是我们仍然可能会遇到空字符串. 这意味着 PostgreSQL *必须*对索引结果应用过滤器以摆脱这些值. + +幸运的是,我们可以使用"部分索引"来进一步改善它. 部分索引是在索引数据时具有`WHERE`条件的索引. 例如: + +``` +CREATE INDEX CONCURRENTLY some_index ON users (email) WHERE id < 100 +``` + +该索引仅索引与`WHERE id < 100`相匹配的行的`email`值. 我们可以使用部分索引将我们的 Twitter 索引更改为以下内容: + +``` +CREATE INDEX CONCURRENTLY twitter_test ON users (twitter) WHERE twitter != ''; +``` + +创建后,如果再次运行查询,将得到以下计划: + +``` +Aggregate (cost=1608.26..1608.27 rows=1 width=8) (actual time=19.821..19.821 rows=1 loops=1) + Buffers: shared hit=44036 + -> Index Only Scan using twitter_test on users (cost=0.41..1479.71 rows=51420 width=0) (actual time=0.023..15.514 rows=51833 loops=1) + Heap Fetches: 1208 + Buffers: shared hit=44036 +Planning time: 0.123 ms +Execution time: 19.848 ms +``` + +*好多了* ! 现在仅需要 20 毫秒即可获取数据,并且我们仅使用约 344 MB 的缓冲区(而不是原始的 1.58 GB). 之所以可行,是因为现在 PostgreSQL 不再需要应用`Filter` ,因为索引仅包含不为空的`twitter`值. + +请记住,每次您要优化查询时,不应该只添加部分索引. 每个索引都必须为每次写入更新,并且它们可能需要相当多的空间,具体取决于索引数据的数量. 结果,首先检查是否存在可以重用的现有索引. 如果没有,请检查是否可以略微更改现有查询以适合现有查询和新查询. 仅当现有索引无法以任何方式使用时,才添加新索引. + +## Queries that can’t be optimised[](#queries-that-cant-be-optimised "Permalink") + +既然我们已经了解了如何优化查询,让我们看一下可能无法优化的另一个查询: + +``` +EXPLAIN (ANALYZE, BUFFERS) +SELECT COUNT(*) +FROM projects +WHERE visibility_level IN (0, 20); +``` + +`EXPLAIN (ANALYZE, BUFFERS)`的输出如下: + +``` +Aggregate (cost=922420.60..922420.61 rows=1 width=8) (actual time=3428.535..3428.535 rows=1 loops=1) + Buffers: shared hit=208846 + -> Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) + Rows Removed by Filter: 65677 + Buffers: shared hit=208846 +Planning time: 2.861 ms +Execution time: 3428.596 ms +``` + +查看输出,我们看到以下过滤器: + +``` +Filter: (visibility_level = ANY ('{0,20}'::integer[])) +Rows Removed by Filter: 65677 +``` + +查看过滤器删除的行数,我们可能会想在`projects.visibility_level`上添加索引,以某种方式将此顺序扫描+过滤器转换为仅索引扫描. + +不幸的是,这样做不可能改善任何事情. 与某些人的看法相反,存在索引*并不能保证* PostgreSQL 会实际使用它. 例如,在执行`SELECT * FROM projects`时,仅扫描整个表而不是使用索引然后从表中获取数据要便宜得多. 在这种情况下,PostgreSQL 可能会决定不使用索引. + +其次,让我们考虑一下查询的作用:它使所有项目的可见性级别为 0 或 20.在上面的计划中,我们可以看到生成了很多行(5,745,940),但相对于总行数是多少? 通过运行以下查询来找出答案: + +``` +SELECT visibility_level, count(*) AS amount +FROM projects +GROUP BY visibility_level +ORDER BY visibility_level ASC; +``` + +对于 GitLab.com,这将产生: + +``` + visibility_level | amount +------------------+--------- + 0 | 5071325 + 10 | 65678 + 20 | 674801 +``` + +这里的项目总数为 5,811,804,其中 5,746,126 为 0 或 20 级.这是整个表的 98%! + +因此,无论我们做什么,此查询都将检索整个表的 98%. 由于大部分时间都花在做到这一点上,因此除了*完全不*运行查询之外,我们几乎没有其他方法可以改进此查询. + +这里重要的是,尽管有些人可能建议您在看到顺序扫描时立即直接添加索引,但*更重要的*是首先了解查询的功能,检索的数据量等等. 毕竟,您无法优化您不了解的内容. + +### Cardinality and selectivity[](#cardinality-and-selectivity "Permalink") + +早先我们看到查询必须检索表中 98%的行. 数据库通常使用两个术语:基数和选择性. 基数是指表中特定列中唯一值的数量. + +选择性是相对于总行数,操作(例如索引扫描或过滤器)产生的唯一值的数量. 选择性越高,PostgreSQL 使用索引的可能性就越大. + +In the above example, there are only 3 unique values: 0, 10, and 20\. This means the cardinality is 3\. The selectivity in turn is also very low: 0.0000003% (2 / 5,811,804), because our `Filter` only filters using two values (`0` and `20`). With such a low selectivity value it’s not surprising that PostgreSQL decides using an index is not worth it, because it would produce almost no unique rows. + +## Rewriting queries[](#rewriting-queries "Permalink") + +因此,上述查询无法真正按原样进行优化,或者至少没有太多优化. 但是,如果我们稍微改变它的目的怎么办? 如果不是检索`visibility_level` 0 或 20 的所有项目,而是检索用户与之交互的那些项目,该怎么办? + +幸运的是,GitLab 对此有一个答案,它是一个名为`user_interacted_projects`的表. 该表具有以下架构: + +``` +Table "public.user_interacted_projects" + Column | Type | Modifiers +------------+---------+----------- + user_id | integer | not null + project_id | integer | not null +Indexes: + "index_user_interacted_projects_on_project_id_and_user_id" UNIQUE, btree (project_id, user_id) + "index_user_interacted_projects_on_user_id" btree (user_id) +Foreign-key constraints: + "fk_rails_0894651f08" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE + "fk_rails_722ceba4f7" FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE +``` + +让我们重写查询以将该表加入到我们的项目中,并获取特定用户的项目: + +``` +EXPLAIN ANALYZE +SELECT COUNT(*) +FROM projects +INNER JOIN user_interacted_projects ON user_interacted_projects.project_id = projects.id +WHERE projects.visibility_level IN (0, 20) +AND user_interacted_projects.user_id = 1; +``` + +我们在这里做的是以下几点: + +1. 获得我们的项目. +2. INNER JOIN `user_interacted_projects` ,这意味着我们只剩下在`user_interacted_projects`中有对应行的`projects`中的行. +3. 将其限制为`visibility_level`为 0 或 20 的项目以及 ID 为 1 的用户与之交互的项目. + +如果运行此查询,则会得到以下计划: + +``` + Aggregate (cost=871.03..871.04 rows=1 width=8) (actual time=9.763..9.763 rows=1 loops=1) + -> Nested Loop (cost=0.86..870.52 rows=203 width=0) (actual time=1.072..9.748 rows=143 loops=1) + -> Index Scan using index_user_interacted_projects_on_user_id on user_interacted_projects (cost=0.43..160.71 rows=205 width=4) (actual time=0.939..2.508 rows=145 loops=1) + Index Cond: (user_id = 1) + -> Index Scan using projects_pkey on projects (cost=0.43..3.45 rows=1 width=4) (actual time=0.049..0.050 rows=1 loops=145) + Index Cond: (id = user_interacted_projects.project_id) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) + Rows Removed by Filter: 0 + Planning time: 2.614 ms + Execution time: 9.809 ms +``` + +在这里,仅花了不到 10 毫秒的时间即可获取数据. 我们还可以看到我们正在检索的项目要少得多: + +``` +Index Scan using projects_pkey on projects (cost=0.43..3.45 rows=1 width=4) (actual time=0.049..0.050 rows=1 loops=145) + Index Cond: (id = user_interacted_projects.project_id) + Filter: (visibility_level = ANY ('{0,20}'::integer[])) + Rows Removed by Filter: 0 +``` + +在这里,我们看到执行了 145 个循环( `loops=145` ),每个循环产生 1 行( `rows=1` ). 这比以前少了很多,我们的查询执行得更好! + +如果我们看一下计划,我们还会发现我们的成本非常低: + +``` +Index Scan using projects_pkey on projects (cost=0.43..3.45 rows=1 width=4) (actual time=0.049..0.050 rows=1 loops=145) +``` + +在这里,我们的成本仅为 3.45,而仅需 0.050 毫秒即可完成. 下一次索引扫描会贵一些: + +``` +Index Scan using index_user_interacted_projects_on_user_id on user_interacted_projects (cost=0.43..160.71 rows=205 width=4) (actual time=0.939..2.508 rows=145 loops=1) +``` + +此处的成本为 160.71( `cost=0.43..160.71` ),大约需要 2.5 毫秒(基于`actual time=....`的输出`actual time=....` ). + +这里最昂贵的部分是对这两个索引扫描的结果起作用的"嵌套循环": + +``` +Nested Loop (cost=0.86..870.52 rows=203 width=0) (actual time=1.072..9.748 rows=143 loops=1) +``` + +在这里,我们必须对 203 行(9.748 毫秒)执行 870.52 磁盘页读取,在单个循环中产生 143 行. + +这里的主要要点是,有时您必须重写(部分)查询以使其更好. 有时,这意味着必须稍微更改功能以适应更好的性能. + +## What makes a bad plan[](#what-makes-a-bad-plan "Permalink") + +这是一个很难回答的问题,因为"坏"的定义与您要解决的问题有关. 但是,在大多数情况下最好避免某些模式,例如: + +* 大表上的顺序扫描 +* 删除大量行的过滤器 +* 执行某个步骤(例如索引扫描)需要*很多*缓冲区(例如,GitLab.com 大于 512 MB). + +作为一般准则,请针对以下查询: + +1. 不超过 10 毫秒. 我们每个请求在 SQL 中花费的目标时间约为 100 毫秒,因此每个查询应尽可能快. +2. 相对于工作负载,不使用过多的缓冲区. 例如,检索十行应该不需要 1 GB 的缓冲区. +3. 不花费大量时间执行磁盘 IO 操作. 必须启用设置`track_io_timing` ,此数据才能包含在`EXPLAIN ANALYZE`的输出中. +4. 在检索行而不对其进行汇总时应用`LIMIT` ,例如`SELECT * FROM users` . +5. 不使用`Filter`过滤掉过多的行,尤其是在查询不使用`LIMIT`限制返回的行数的情况下. 通常可以通过添加(部分)索引来删除过滤器. + +这些是*准则* ,不是硬性要求,因为不同的需求可能需要不同的查询. 唯一的*规则*是,您*必须始终*使用`EXPLAIN (ANALYZE, BUFFERS)`和相关工具*来衡量*您的查询(最好使用类似生产的数据库): + +* [`explain.depesz.com`](https://explain.depesz.com/). +* [`explain.dalibo.com/`](https://explain.dalibo.com/). + +## Producing query plans[](#producing-query-plans "Permalink") + +有几种获取查询计划输出的方法. 当然,您可以直接在`psql`控制台中运行`EXPLAIN`查询,或者可以遵循以下其他选项之一. + +### Rails console[](#rails-console "Permalink") + +Using the [`activerecord-explain-analyze`](https://github.com/6/activerecord-explain-analyze) you can directly generate the query plan from the Rails console: + +``` +pry(main)> require 'activerecord-explain-analyze' +=> true +pry(main)> Project.where('build_timeout > ?', 3600).explain(analyze: true) + Project Load (1.9ms) SELECT "projects".* FROM "projects" WHERE (build_timeout > 3600) + ↳ (pry):12 +=> EXPLAIN for: SELECT "projects".* FROM "projects" WHERE (build_timeout > 3600) +Seq Scan on public.projects (cost=0.00..2.17 rows=1 width=742) (actual time=0.040..0.041 rows=0 loops=1) + Output: id, name, path, description, created_at, updated_at, creator_id, namespace_id, ... + Filter: (projects.build_timeout > 3600) + Rows Removed by Filter: 14 + Buffers: shared hit=2 +Planning time: 0.411 ms +Execution time: 0.113 ms +``` + +### ChatOps[](#chatops "Permalink") + +[GitLab 员工还可以使用`/chatops` slash 命令在 Slack 中使用我们的 ChatOps 解决方案](chatops_on_gitlabcom.html) . 您可以使用 ChatOps 通过运行以下命令来获取查询计划: + +``` +/chatops run explain SELECT COUNT(*) FROM projects WHERE visibility_level IN (0, 20) +``` + +还支持使用[https://explain.depesz.com/](https://explain.depesz.com/)可视化计划: + +``` +/chatops run explain --visual SELECT COUNT(*) FROM projects WHERE visibility_level IN (0, 20) +``` + +不需要查询. + +有关可用选项的更多信息,请运行: + +``` +/chatops run explain --help +``` + +### `#database-lab`[](#database-lab "Permalink") + +GitLab 员工可以使用的另一种工具是由[Joe](https://gitlab.com/postgres-ai/joe)支持的聊天机器人,该机器人使用[Database Lab](https://gitlab.com/postgres-ai/database-lab)立即为开发人员提供他们自己的生产数据库克隆. + +Joe 在 Slack 的[`#database-lab`](https://gitlab.slack.com/archives/CLJMDRD8C)频道中可用. + +与 ChatOps 不同,它为您提供了一种执行 DDL 语句(如创建索引和表)并获取查询计划的方法,该查询计划不仅适用于`SELECT`而且适用于`UPDATE`和`DELETE` . + +例如,为了测试新索引,您可以执行以下操作: + +创建索引: + +``` +exec CREATE INDEX index_projects_last_activity ON projects (last_activity_at) WHERE last_activity_at IS NOT NULL +``` + +分析表以更新其统计信息: + +``` +exec ANALYZE projects +``` + +获取查询计划: + +``` +explain SELECT * FROM projects WHERE last_activity_at < CURRENT_DATE +``` + +完成后,您可以回滚您的更改: + +``` +reset +``` + +有关可用选项的更多信息,请运行: + +``` +help +``` + +#### Tips & Tricks[](#tips--tricks "Permalink") + +现在,在整个会话期间都将维护数据库连接,因此您可以对任何会话变量(例如`enable_seqscan`或`work_mem` )使用`exec set ...` 这些设置将应用于所有后续命令,直到您重置它们. + +也可以使用事务. 当您处理修改数据的语句(例如 INSERT,UPDATE 和 DELETE)时,这可能很有用. `explain`命令将执行`EXPLAIN ANALYZE` ,该语句执行该语句. 为了从干净状态开始运行每个`explain` ,您可以将其包装在事务中,例如: + +``` +exec BEGIN + +explain UPDATE some_table SET some_column = TRUE + +exec ROLLBACK +``` + +## Further reading[](#further-reading "Permalink") + +在[Dalibo.org](https://www.dalibo.com/en/)的[演示中](https://public.dalibo.com/exports/conferences/_archives/_2012/201211_explain/understanding_explain.pdf)可以找到关于理解查询计划的更广泛的指南. \ No newline at end of file diff --git a/docs/566.md b/docs/566.md new file mode 100644 index 0000000000000000000000000000000000000000..d2b099c8e4dfd6f787238efc709cea606cb68868 --- /dev/null +++ b/docs/566.md @@ -0,0 +1,268 @@ +# Rake tasks for developers + +> 原文:[https://docs.gitlab.com/ee/development/rake_tasks.html](https://docs.gitlab.com/ee/development/rake_tasks.html) + +* [Set up database with developer seeds](#set-up-database-with-developer-seeds) + * [Environment variables](#environment-variables) + * [Seeding issues for all or a given project](#seeding-issues-for-all-or-a-given-project) + * [Seeding issues for Insights charts](#seeding-issues-for-insights-charts-ultimate) + * [Seeding groups with sub-groups](#seeding-groups-with-sub-groups) + * [Seeding custom metrics for the monitoring dashboard](#seeding-custom-metrics-for-the-monitoring-dashboard) + * [Automation](#automation) + * [Discard `stdout`](#discard-stdout) + * [Extra Project seed options](#extra-project-seed-options) +* [Run tests](#run-tests) + * [Speed up tests, Rake tasks, and migrations](#speed-up-tests-rake-tasks-and-migrations) +* [Compile Frontend Assets](#compile-frontend-assets) +* [Emoji tasks](#emoji-tasks) +* [Update project templates](#update-project-templates) +* [Generate route lists](#generate-route-lists) +* [Show obsolete `ignored_columns`](#show-obsolete-ignored_columns) +* [Update GraphQL documentation and schema definitions](#update-graphql-documentation-and-schema-definitions) + * [Update machine-readable schema files](#update-machine-readable-schema-files) + +# Rake tasks for developers[](#rake-tasks-for-developers "Permalink") + +Rake 任务适用于开发人员和为 GitLab 做出贡献的其他人员. + +## Set up database with developer seeds[](#set-up-database-with-developer-seeds "Permalink") + +请注意,如果您的数据库用户没有高级特权,则必须在运行此命令之前手动创建数据库. + +``` +bundle exec rake setup +``` + +`setup`任务是`gitlab:setup`的别名. 此任务调用`db:reset`创建数据库,并调用`db:seed_fu`播种数据库. 注意: `db:setup`调用`db:seed`但这没有任何作用. + +### Environment variables[](#environment-variables "Permalink") + +**MASS_INSERT** :创建数百万个用户(2m),项目(5m)及其关系. 强烈建议将种子与种子一起运行,以在开发过程中捕获缓慢的查询. 预计此过程最多可能需要 20 分钟. + +另请参见[批量插入 Rails 模型](mass_insert.html) . + +**LARGE_PROJECTS** :从一组预定义的 URL 创建大型项目(通过导入). + +### Seeding issues for all or a given project[](#seeding-issues-for-all-or-a-given-project "Permalink") + +您可以使用`gitlab:seed:issues`任务为所有项目或给定项目`gitlab:seed:issues` : + +``` +# All projects +bin/rake gitlab:seed:issues + +# A specific project +bin/rake "gitlab:seed:issues[group-path/project-path]" +``` + +默认情况下,每个项目的最近 5 周平均每周播种 2 个问题. + +#### Seeding issues for Insights charts[](#seeding-issues-for-insights-charts-ultimate "Permalink") + +您可以使用`gitlab:seed:insights:issues`任务为专门用于处理[Insights 图表](../user/group/insights/index.html)的`gitlab:seed:insights:issues` : + +``` +# All projects +bin/rake gitlab:seed:insights:issues + +# A specific project +bin/rake "gitlab:seed:insights:issues[group-path/project-path]" +``` + +默认情况下,每个项目在最近 52 周中平均每周播种 10 个问题. 所有问题还将随机标记团队,类型,严重性和优先级. + +#### Seeding groups with sub-groups[](#seeding-groups-with-sub-groups "Permalink") + +您可以使用`gitlab:seed:group_seed`任务为包含里程碑/项目/问题的子组播种组: + +``` +bin/rake "gitlab:seed:group_seed[subgroup_depth, username]" +``` + +如果 GitLab 实例具有可用的史诗功能,则该组还会另外添加史诗. + +#### Seeding custom metrics for the monitoring dashboard[](#seeding-custom-metrics-for-the-monitoring-dashboard "Permalink") + +监视仪表板中支持许多不同类型的指标. + +要导入这些指标,可以运行: + +``` +bundle exec rake 'gitlab:seed:development_metrics[your_project_id]' +``` + +### Automation[](#automation "Permalink") + +If you’re very sure that you want to **清除当前数据库** and refill seeds, you could: + +``` +echo 'yes' | bundle exec rake setup +``` + +使您免于手动回答`yes` . + +### Discard `stdout`[](#discard-stdout "Permalink") + +由于该脚本会打印很多信息,因此可能会减慢您的终端运行速度,并且如果您将其重定向到文件,则会生成 20G 以上的日志. 如果我们不在乎输出,则可以将其重定向到`/dev/null` : + +``` +echo 'yes' | bundle exec rake setup > /dev/null +``` + +请注意,由于您看不到`stdout`的问题,因此您可能只想`echo 'yes'`以使其运行. 它仍然会在`stderr`上打印错误,因此不必担心丢失错误. + +### Extra Project seed options[](#extra-project-seed-options "Permalink") + +您可以传递一些环境标志来更改项目的种子方式 + +* `SIZE` :默认为`8` ,最大为`32` . 要创建的项目数量. +* `LARGE_PROJECTS` :默认为 false. 如果设置,将克隆 6 个大型项目以帮助进行测试. +* `FORK` :默认为 false. 如果设置为`true`将分叉`torvalds/linux`五次. 也可以将其设置为现有项目 full_path,它将代替它. + +## Run tests[](#run-tests "Permalink") + +为了运行测试,您可以使用以下命令: + +* `bin/rake spec`运行 RSpec 套件 +* `bin/rake spec:unit`仅运行单元测试 +* `bin/rake spec:integration`仅运行集成测试 +* `bin/rake spec:system`仅运行系统测试 +* `bin/rake karma`运行 Karma 测试套件 + +`bin/rake spec`需要花费大量时间. 无需在本地运行完整的测试套件,而是可以通过运行与更改相关的单个测试或目录来节省大量时间. 提交合并请求后,CI 将为您运行完整的测试套件. 合并请求中的绿色 CI 状态表示已通过完整的测试套件. + +您不能运行`rspec .` 因为这将尝试运行它可以找到的所有`_spec.rb`文件,以及`/tmp` + +您可以将 RSpec 命令行选项传递给`spec:unit` , `spec:integration`和`spec:system`任务. 例如, `bin/rake "spec:unit[--tag ~geo --dry-run]"` . + +对于 RSpec 测试,要运行一个测试文件,可以运行: + +``` +bin/rspec spec/controllers/commit_controller_spec.rb +``` + +要在一个目录中运行多个测试: + +* 如果仅想测试 API,则对 RSpec 测试使用`bin/rspec spec/requests/api/` + +### Speed up tests, Rake tasks, and migrations[](#speed-up-tests-rake-tasks-and-migrations "Permalink") + +[Spring](https://github.com/rails/spring)是 Rails 应用程序的预加载器. 它通过使应用程序在后台运行来加快开发速度,因此您无需在每次运行测试,Rake 任务或迁移时都启动它. + +如果要使用它,则需要将`ENABLE_SPRING`环境变量导出为`1` : + +``` +export ENABLE_SPRING=1 +``` + +另外,您可以在每次运行规范时使用以下命令, + +``` +bundle exec spring rspec some_spec.rb +``` + +## Compile Frontend Assets[](#compile-frontend-assets "Permalink") + +您永远不需要在开发中手动编译前端资产,但是如果您需要测试在生产环境中如何编译资产,则可以使用以下命令进行: + +``` +RAILS_ENV=production NODE_ENV=production bundle exec rake gitlab:assets:compile +``` + +这将编译并缩小所有 JavaScript 和 CSS 资产,并将它们与所有其他前端资产(图像,字体等)一起复制到`/public/assets`中,以便于对其进行轻松检查. + +## Emoji tasks[](#emoji-tasks "Permalink") + +要更新表情符号别名文件(用于表情符号自动完成),请运行以下命令: + +``` +bundle exec rake gemojione:aliases +``` + +要更新表情符号摘要文件(用于表情符号自动完成),请运行以下命令: + +``` +bundle exec rake gemojione:digests +``` + +这将根据当前可用的表情`fixtures/emojis/digests.json`更新`fixtures/emojis/digests.json`文件. + +要生成包含所有表情符号的 Sprite 文件,请运行: + +``` +bundle exec rake gemojione:sprite +``` + +如果添加了新的表情符号,则子画面可能会更改大小. 为了补偿这种变化,请首先使用上述 Rake 任务生成`emoji.png` Sprite 表,然后检查新 Sprite 表的`SPRITESHEET_WIDTH`并`SPRITESHEET_HEIGHT`地更新`SPRITESHEET_WIDTH`和`SPRITESHEET_HEIGHT`常量. + +## Update project templates[](#update-project-templates "Permalink") + +从模板启动项目需要将该项目导出. 在最新的 master 分支上运行: + +``` +gdk start +bundle exec rake gitlab:update_project_templates +git checkout -b update-project-templates +git add vendor/project_templates +git commit +git push -u origin update-project-templates +``` + +现在创建一个合并请求并将其合并到主请求. + +## Generate route lists[](#generate-route-lists "Permalink") + +要查看 API 路由的完整列表,可以运行: + +``` +bundle exec rake grape:path_helpers +``` + +生成的列表包括 API 端点和功能性 RESTful API 动词的完整列表. + +对于 Rails 控制器,运行: + +``` +bundle exec rake routes +``` + +由于创建这些文件需要一些时间,因此将输出保存到文件以快速参考通常会很有帮助. + +## Show obsolete `ignored_columns`[](#show-obsolete-ignored_columns "Permalink") + +要查看所有已过时的`ignored_columns`的列表, `ignored_columns`运行: + +``` +bundle exec rake db:obsolete_ignored_columns +``` + +随时从自己的`ignored_columns`定义中删除其定义. + +## Update GraphQL documentation and schema definitions[](#update-graphql-documentation-and-schema-definitions "Permalink") + +要基于 GitLab 模式生成 GraphQL 文档,请运行: + +``` +bundle exec rake gitlab:graphql:compile_docs +``` + +在当前状态下,Rake 任务: + +* 生成 GraphQL 对象的输出. +* 将输出放置在`doc/api/graphql/reference/index.md` . + +这使用了来自`graphql-docs` gem 的一些功能,例如其模式解析器和帮助器方法. docs 生成器代码来自于我们,为我们提供了更大的灵活性,例如使用 Haml 模板和生成 Markdown 文件. + +要编辑使用的模板,请查看`lib/gitlab/graphql/docs/templates/default.md.haml` . 实际的渲染器位于`Gitlab::Graphql::Docs::Renderer` . + +`@parsed_schema`是`graphql-docs` gem 期望提供的实例变量. `Gitlab::Graphql::Docs::Helper`定义我们当前使用的`object`方法. 您还应该在这里为要显示的新类型实现任何新方法. + +### Update machine-readable schema files[](#update-machine-readable-schema-files "Permalink") + +要基于 GitLab 模式生成 GraphQL 模式文件,请运行: + +``` +bundle exec rake gitlab:graphql:schema:dump +``` + +它使用 GraphQL Ruby 的内置 Rake 任务来生成[IDL](https://www.prisma.io/blog/graphql-sdl-schema-definition-language-6755bcb9ce51)和 JSON 格式的文件. \ No newline at end of file diff --git a/docs/567.md b/docs/567.md new file mode 100644 index 0000000000000000000000000000000000000000..e5ffb19d79413a758f674deb3018b40c9a8a21e2 --- /dev/null +++ b/docs/567.md @@ -0,0 +1,14 @@ +# Mass inserting Rails models + +> 原文:[https://docs.gitlab.com/ee/development/mass_insert.html](https://docs.gitlab.com/ee/development/mass_insert.html) + +# Mass inserting Rails models[](#mass-inserting-rails-models "Permalink") + +在运行[`rake setup`](rake_tasks.html)时设置环境变量[`MASS_INSERT=1`](rake_tasks.html#environment-variables)将创建数百万条记录,但是默认情况下, `root`用户看不到这些记录. + +要使`root`用户可以看到任意数量的大容量插入项目,请在 rails 控制台中运行以下代码段. + +``` +u = User.find(1) +Project.last(100).each { |p| p.set_timestamps_for_create && p.add_maintainer(u, current_user: u) } # Change 100 to whatever number of projects you need access to +``` \ No newline at end of file diff --git a/docs/568.md b/docs/568.md new file mode 100644 index 0000000000000000000000000000000000000000..e81544b769212f2c6b395778456dc22c5d1a0035 --- /dev/null +++ b/docs/568.md @@ -0,0 +1,548 @@ +# GitLab Documentation guidelines + +> 原文:[https://docs.gitlab.com/ee/development/documentation/](https://docs.gitlab.com/ee/development/documentation/) + +* [Source files and rendered web locations](#source-files-and-rendered-web-locations) + * [Branch naming](#branch-naming) +* [Contributing to docs](#contributing-to-docs) +* [Markdown and styles](#markdown-and-styles) +* [Folder structure and files](#folder-structure-and-files) +* [Metadata](#metadata) + * [Stage and group metadata](#stage-and-group-metadata) + * [Page type metadata](#page-type-metadata) + * [Redirection metadata](#redirection-metadata) + * [Comments metadata](#comments-metadata) + * [Additional page metadata](#additional-page-metadata) +* [Changing document location](#changing-document-location) + * [Redirections for pages with Disqus comments](#redirections-for-pages-with-disqus-comments) +* [Merge requests for GitLab documentation](#merge-requests-for-gitlab-documentation) +* [GitLab `/help`](#gitlab-help) + * [Linking to `/help`](#linking-to-help) + * [GitLab `/help` tests](#gitlab-help-tests) +* [Docs site architecture](#docs-site-architecture) + * [Global navigation](#global-navigation) +* [Previewing the changes live](#previewing-the-changes-live) + * [Troubleshooting review apps](#troubleshooting-review-apps) + * [Technical aspects](#technical-aspects) +* [Testing](#testing) + * [Running tests](#running-tests) + * [Nanoc tests](#nanoc-tests) + * [Lint checks](#lint-checks) + * [Local linters](#local-linters) + * [markdownlint](#markdownlint) + * [Vale](#vale) + * [Install linters](#install-linters) + * [Configure editors](#configure-editors) + * [Disable Vale tests](#disable-vale-tests) +* [Danger Bot](#danger-bot) + +# GitLab Documentation guidelines[](#gitlab-documentation-guidelines "Permalink") + +GitLab 的文档[旨在作为唯一的真实来源(SSOT)](https://about.gitlab.com/handbook/documentation/) ,提供有关如何配置,使用 GitLab 以及对其进行故障排除的信息. 该文档包含按产品领域和主题组织的每个 GitLab 功能的用例和使用说明. 这包括跨多个 GitLab 功能的主题和工作流程,以及将 GitLab 与其他应用程序一起使用. + +除了此页面之外,以下资源还可以帮助您编写文档并做出贡献: + +* [样式指南](styleguide.html) -文档,语言指南,要遵循的 Markdown 标准,链接等内容. +* [结构和模板](structure.html) -了解文档页面的典型部分以及如何编写每一部分. +* [Documentation process](workflow.html). +* [Markdown 指南](../../user/markdown.html) -有关 GitLab 支持的所有 Markdown 语法的参考. +* [网站架构](site_architecture/index.html) -https [://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site)的构建方式. +* [功能标记的文档](feature_flags.html) -如何编写和更新部署在功能标记后面的 GitLab 功能的文档. + +## Source files and rendered web locations[](#source-files-and-rendered-web-locations "Permalink") + +有关 GitLab,GitLab Runner,Omnibus GitLab 和 Charts 的文档已发布到[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site) . GitLab 的文档也发布在 GitLab 实例域的`/help`内的应用程序中. 在`/help` ,仅包含当前版本和版本的帮助. 有关其他版本的帮助,请访问[https://docs.gitlab.com/archives/](https://docs.gitlab.com/archives/) . + +文档的源位于以下仓库位置的每个 GitLab 应用程序的代码库中: + +| Project | Path | +| --- | --- | +| [GitLab](https://gitlab.com/gitlab-org/gitlab/) | [`/doc`](https://gitlab.com/gitlab-org/gitlab/tree/master/doc) | +| [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/) | [`/docs`](https://gitlab.com/gitlab-org/gitlab-runner/tree/master/docs) | +| [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/) | [`/doc`](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc) | +| [Charts](https://gitlab.com/gitlab-org/charts/gitlab) | [`/doc`](https://gitlab.com/gitlab-org/charts/gitlab/tree/master/doc) | + +文档问题和合并请求是它们各自存储库的一部分,都带有标签`Documentation` . + +### Branch naming[](#branch-naming "Permalink") + +[GitLab 主项目](../pipelines.html)的[CI 管道](../pipelines.html)配置为仅自动运行与贡献类型匹配的作业. 如果您的贡献**仅**包含文档更改,那么将仅运行与文档相关的作业,并且管道的完成将比代码贡献更快. + +如果要向 Runner,Omnibus 或 Charts 提交仅文档更改,则不会自动确定快速管道. 相反,请使用以下指南为仅文档合并请求创建分支: + +| 分店名称 | 有效的例子 | +| --- | --- | +| 从`docs/`开始 | `docs/update-api-issues` | +| 从`docs-`开始 | `docs-update-api-issues` | +| 以`-docs` | `123-update-api-issues-docs` | + +## Contributing to docs[](#contributing-to-docs "Permalink") + +整个 GitLab 社区都欢迎[对 GitLab 文档做出贡献](workflow.html) . + +为确保 GitLab 文档是最新的,所有[功能更改](feature-change-workflow.html)都有特殊的流程和职责,即影响功能外观,使用或管理的开发工作. + +但是,任何人都可以贡献与功能更改无关的[文档改进](improvement-workflow.html) . 例如,添加有关如何完成用例的新文档,这可以通过 GitLab 或第三方工具和 GitLab 完成. + +## Markdown and styles[](#markdown-and-styles "Permalink") + +[GitLab 文档](https://gitlab.com/gitlab-org/gitlab-docs)使用[GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown)作为其 Markdown 渲染引擎. 有关完整的 Kramdown 参考,请参阅《 [GitLab Markdown 指南》](https://about.gitlab.com/handbook/markdown-guide/) . + +遵守[文档样式指南](styleguide.html) . 如果缺少样式标准,欢迎您通过合并请求提出建议. + +## Folder structure and files[](#folder-structure-and-files "Permalink") + +请参阅" [文档样式指南"](styleguide.html)的" [结构"](styleguide.html#structure)部分. + +## Metadata[](#metadata "Permalink") + +为了提供其他指令或有用的信息,我们将 YAML 格式的元数据添加到每个产品文档页面的开头(YAML 开头). 所有值均视为字符串,仅用于[docs 网站](site_architecture/index.html) . + +### Stage and group metadata[](#stage-and-group-metadata "Permalink") + +理想情况下,每个页面都应具有与其所属的阶段和组相关的元数据,以及如下所述的信息块: + +* `stage` :页面大部分内容所属的[Stage](https://about.gitlab.com/handbook/product/product-categories/#devops-stages) . +* `group` :页面大部分内容所属的[Group](https://about.gitlab.com/company/team/structure/#product-groups) . +* `info` :下一行,为与该页面的舞台和小组相关的技术作家联系提供指导,以帮助参与者: + + ``` + To determine the technical writer assigned to the Stage/Group + associated with this page, see + https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers + ``` + +例如,以下元数据将位于产品文档页面的开始,其内容主要与"审核事件"功能相关: + +``` +--- +stage: Monitor +group: APM +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- +``` + +### Page type metadata[](#page-type-metadata "Permalink") + +最初在[此史诗中](https://gitlab.com/groups/gitlab-org/-/epics/1280)讨论过,每个页面应该具有`type`元数据. 可以是以下一项或多项: + +* `index` :索引/概述页面. 它们充当其他页面的列表. 不一定意味着页面应命名为`index.md` . [示例页面](../../install/README.html) . +* `concepts` :使用产品之前需要了解的内容. 信息性的,非指导性的. 例如,抽象的想法,解释含义或收益,支持对任务的理解. 阅读它们以获取背景信息,例如"为什么 X 很重要". [示例页面](../../topics/autodevops/index.html) . +* `howto` :特定用例说明. [示例页面](../../ssh/README.html) . +* `tutorial` :边做边学过程/概念. [示例页面](../../gitlab-basics/start-using-git.html) . +* `reference` :介绍什么是/做什么. 诸如特定设置,没有太多解释的事实之类的东西可以阅读以获取详细信息. [示例页面](../../ci/yaml/README.html) . + +### Redirection metadata[](#redirection-metadata "Permalink") + +将页面移到另一个位置时,应添加以下元数据: + +* `redirect_to` :访问者应将移动页面重定向到的相对路径和文件名(扩展名为`.md` ). [了解更多](#changing-document-location) . +* `disqus_identifier` :Disqus 评论系统的标识符. 用于保留已被移至新 URL 的页面的注释. [了解更多](#redirections-for-pages-with-disqus-comments) . + +### Comments metadata[](#comments-metadata "Permalink") + +[docs 网站](site_architecture/index.html)上默认启用了注释(由 Disqus 提供). 如果要禁用它们(例如在索引页面中),请将其设置为`false` : + +``` +--- +comments: false +--- +``` + +### Additional page metadata[](#additional-page-metadata "Permalink") + +每个页面可以具有其他(可选)元数据(在[default.html](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/fc3577921343173d589dfa43d837b4307e4e620f/layouts/default.html#L30-52) Nanoc 布局中设置),如果定义,这些元数据将显示在页面顶部: + +* `author` :页面`author`的名称,通常是教程. 它需要`author_gitlab`才能显示. +* `author_gitlab` :GitLab.com 上作者的用户名. 它需要`author`才能显示. +* `date` :页面的创建日期,通常用于教程. +* `article_type` :文章的类型. 可以是`tutorial`或`user guide` . +* `level` :操作方法或教程的复杂程度. 可以是`beginner` , `advanced`或`intermediate` . +* `last_updated` :页面上次更新时的 ISO 格式日期. 例如`2020-02-14` . +* `reading_time` :如果要添加页面的大概阅读时间的指示,可以将`reading_time`设置为`true` . 这使用简单的[算法](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/lib/helpers/reading_time.rb)根据单词数计算阅读时间. + +## Changing document location[](#changing-document-location "Permalink") + +更改文档的位置需要特定的步骤,以确保用户可以无缝访问新的文档页面,无论他们是通过`/help`还是通过[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site)访问 GitLab 实例域上的内容. 如果您在此过程中有任何疑问(例如是否需要搬迁),请务必指派一名技术作家,并确保在合并之前技术作家会对此更改进行审查. + +如果确实需要更改文档的位置,请不要删除旧文档,而应将所有内容替换为以下内容: + +``` +--- +redirect_to: '../path/to/file/index.md' +--- + +This document was moved to [another location](../path/to/file/index.md). +``` + +其中`../path/to/file/index.md`通常是旧文档的相对路径. + +所述`redirect_to`变量同时支持完整或相对 URL,例如`https://docs.gitlab.com/ee/path/to/file.html` , `../path/to/file.html` , `path/to/file.md` . 它确保重定向将对[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site)起作用,并且任何`*.md`路径都将编译为`*.html` . 前部事项下方的新行通知用户文档已更改位置,对于从存储库浏览该文件的用户而言非常有用. + +例如,如果将`doc/workflow/lfs/index.md`移到`doc/administration/lfs.md` ,则步骤将是: + +1. Copy `doc/workflow/lfs/index.md` to `doc/administration/lfs.md` +2. 将`doc/workflow/lfs/index.md`的内容替换为: + + ``` + --- + redirect_to: '../../administration/lfs.md' + --- + + This document was moved to [another location](../../administration/lfs.md). + ``` + +3. 查找并用新位置替换所有出现的旧位置. 查找它们的快速方法是在将文件从以下位置更改的存储库中使用`git grep` : + + ``` + git grep -n "workflow/lfs/lfs_administration" + git grep -n "lfs/lfs_administration" + ``` + +**注意:**如果要移动的文档上有任何 Disqus 评论,则要执行的其他步骤[如下所示](#redirections-for-pages-with-disqus-comments) . + +注意事项: + +* 由于除了文档本身以外,我们还使用内联文档,因此该文档也可能在访问`/help`时将呈现的 GitLab( `app/` )视图中引用,有时甚至在测试套件( `spec/` )中也会引用. 您必须在这些路径中搜索对文档的引用并进行更新. +* 上面的`git grep`命令将在您在其中运行它的目录中以递归方式搜索`workflow/lfs/lfs_administration`和`lfs/lfs_administration` ,并将打印文件和提及该文件的行. 您可能会问为什么这两次抱怨. 由于[我们使用相对路径链接到文档](styleguide.html#links) ,因此有时更深入地搜索路径可能很有用. +* 当文档链接到 GitLab 的内置帮助页面时,不使用`*.md`扩展名,这就是为什么我们在`git grep`忽略它. +* 使用"更改文档位置" MR 描述模板上的清单. + +### Redirections for pages with Disqus comments[](#redirections-for-pages-with-disqus-comments "Permalink") + +如果要重定位的文档页面已经包含 Disqus 评论,则我们需要保留 Disqus 线程. + +Disqus 使用每页标识符,对于[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site) ,页面标识符被配置为页面 URL. 因此,当我们更改文档位置时,我们需要将旧的 URL 保留为相同的 Disqus 标识符. + +为此,将变量`disqus_identifier`添加到`disqus_identifier` ,使用旧的 URL 作为值. 例如,假设我们将`https://docs.gitlab.com/my-old-location/README.html`下可用的文档移到了新位置`https://docs.gitlab.com/my-new-location/index.html` . + +在**新文档的**开头部分,我们添加了以下内容: + +``` +--- +disqus_identifier: 'https://docs.gitlab.com/my-old-location/README.html' +--- +``` + +注:有必要在文件名中`disqus_identifier` URL,即使它`index.html`或`README.html` . + +## Merge requests for GitLab documentation[](#merge-requests-for-gitlab-documentation "Permalink") + +在开始之前,请确保您已阅读上面的" [为文档做贡献](#contributing-to-docs) "介绍性部分和[文档工作流程](workflow.html) . + +* 使用当前的[合并请求描述模板](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/merge_request_templates/Documentation.md) +* 标记 MR `Documentation` (只能由具有`developer`访问权限的`developer` (例如,GitLab 团队成员)完成) +* 在下面的每个注释中分配正确的里程碑(只能由具有`developer`访问权限的人(例如,GitLab 团队成员)完成) + +如果对现有内容进行了改进,文档将被合并,这代表了遵循模板和样式标准的真诚努力,并且被认为是准确的. + +对于进一步完善文档的进一步需求,应在后续的 MR 或问题中立即解决. + +**注意:**如果要添加文档的发行版已经冻结或发行,请使用标签`~"Pick into XY"`将其合并到正确的发行版中. 尽量避免选择过去的发行版,因为这样做会增加发行版管理器的工作量. + +## GitLab `/help`[](#gitlab-help "Permalink") + +每个 GitLab 实例都包含文档,该文档可从`/help` ( `https://gitlab.example.com/help` )获得. 例如, [https://gitlab.com/help](https://gitlab.com/help) . + +[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site)上在线提供的文档每隔四个小时从 GitLab,Omnibus 和 Runner 的`master`分支进行部署. 因此,合并请求合并后,它将在同一天在线可用. 但是,它将在分配给 MR 的里程碑内发货(并在`/help`上可用). + +例如,假设您的合并请求的里程碑设置为 11.3,该里程碑将于 2018-09-22 发布. 如果在 2018-09-15 合并,它将在 2018-09-15 联机提供,但是,随着功能冻结日期的过去,如果 MR 没有`~"Pick into 11.3"`标签,那么该里程碑必须更改为 11.4,并且仅在 2018-10-22 以及 GitLab 11.4 中将与所有 GitLab 软件包一起提供. 这意味着,它将仅在 GitLab 11.4 及更高版本的`/help`下提供,但在合并的同一天在[https://docs.gitlab.com/](https://docs.gitlab.com/)上提供. + +### Linking to `/help`[](#linking-to-help "Permalink") + +构建新功能时,可能需要从应用程序 GitLab 链接文档. 通常,这是通过`help_page_path` helper 方法在`app/views/`目录内的文件中完成的. + +以最简单的形式,用于生成到`/help`页面的链接的 HAML 代码为: + +``` += link_to 'Help page', help_page_path('user/permissions') +``` + +`help_page_path`使用以下约定包含要链接到的文档的路径: + +* 它相对于 GitLab 存储库中的`doc/`目录 +* `.md`扩展名必须省略 +* 它不能以斜杠( `/` )结尾 + +以下是根据情况应使用的一些特殊情况. 您可以结合以下一项或多项: + +1. **链接到锚链接.** 使用`anchor`作为`help_page_path`方法的一部分: + + ``` + = link_to 'Help page', help_page_path('user/permissions', anchor: 'anchor-link') + ``` + +2. **在新标签页中打开链接.** 这应该是默认行为: + + ``` + = link_to 'Help page', help_page_path('user/permissions'), target: '_blank' + ``` + +3. **链接到圆圈图标.** 通常用于无法使用长描述的设置,例如复选框旁边. 您基本上可以使用任何字体超赞的图标,但更喜欢使用`question-circle` : + + ``` + = link_to icon('question-circle'), help_page_path('user/permissions') + ``` + +4. **使用按钮链接.** 在文本与页面布局其余部分脱离上下文的地方很有用: + + ``` + = link_to 'Help page', help_page_path('user/permissions'), class: 'btn btn-info' + ``` + +5. **使用内联某些文本的链接.** + + ``` + Description to #{link_to 'Help page', help_page_path('user/permissions')}. + ``` + +6. **在句子末尾添加句点.** Useful when you don’t want the period to be part of the link: + + ``` + = succeed '.' do + Learn more in the + = link_to 'Help page', help_page_path('user/permissions') + ``` + +### GitLab `/help` tests[](#gitlab-help-tests "Permalink") + +运行了一些[RSpec 测试](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/features/help_pages_spec.rb)以确保 GitLab 文档能够呈现并正常工作. 特别是,该[主要文档的登录页面](../../README.html)将从`/help`正确运行. 例如, [GitLab.com 的`/help`](https://gitlab.com/help) . + +## Docs site architecture[](#docs-site-architecture "Permalink") + +请参阅" [文档"网站的体系结构](site_architecture/index.html)页面,以了解我们如何在[https://docs.gitlab.com 上](https://s0docs0gitlab0com.icopy.site)构建和部署该网站,并查看所有正在使用的资产和库. + +### Global navigation[](#global-navigation "Permalink") + +有关如何构建和更新左侧导航菜单的信息,请参阅[全局导航](site_architecture/global_nav.html)文档. + +## Previewing the changes live[](#previewing-the-changes-live "Permalink") + +**注意:**要在本地预览对文档的更改,请遵循本[开发指南](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/README.md#development-when-contributing-to-gitlab-documentation)或[GDK 的这些说明](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/gitlab_docs.md) . + +当前为以下项目启用了实时预览: + +* [`gitlab`](https://gitlab.com/gitlab-org/gitlab) +* [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner) + +如果您的合并请求中有 docs 更改,则可以使用手动`review-docs-deploy`作业为合并请求部署 docs review 应用. 您将至少需要维护者权限才能运行它. + +[![Manual trigger a docs build](img/4a007f26d24f09e03b3bb388bd94ae30.png)](img/manual_build_docs.png) + +**注意:**您将需要将分支推送到这些存储库,它不适用于 fork. + +`review-docs-deploy*`工作将: + +1. 在[`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs)项目中创建一个以该方案命名的新分支: `docs-preview-$DOCS_GITLAB_REPO_SUFFIX-$CI_MERGE_REQUEST_IID` ,其中`DOCS_GITLAB_REPO_SUFFIX`是每个产品的后缀,例如`ee`表示 EE, `omnibus`表示 Omnibus `CI_MERGE_REQUEST_IID` , `CI_MERGE_REQUEST_IID`等,相应合并请求的 ID. +2. 触发跨项目管道,并使用您的更改构建文档站点. + +如果评论应用程序 URL 返回 404,则意味着该站点尚未部署,或者远程管道出了点问题. 给它几分钟,它应该在线显示,否则,您可以从合并请求的作业输出中的链接检查远程管道的状态. 如果管道失败或阻塞,请在`#docs`聊天频道中添加一行. + +**提示:**对 GitLab 项目没有合并权限的人(想想贡献者的分支)不能运行手动作业. 在这种情况下,您可以请 GitLab 团队的某人授权为您执行此操作.**注意:**确保始终删除正在处理的合并请求的分支. 如果您不这样做,那么远程 docs 分支也不会被删除,并且承载 Review Apps 的服务器最终将没有磁盘空间. + +### Troubleshooting review apps[](#troubleshooting-review-apps "Permalink") + +如果评论应用程序 URL 返回 404,请按照以下步骤进行调试: + +1. **您是否遵循了合并请求小部件中的 URL?** 如果是,则检查链接是否与作业输出中的链接相同. +2. **您是否遵循作业输出中的 URL?** 如果是,则意味着该站点尚未部署或远程管道出了点问题. 给它几分钟,它应该在线显示,否则,您可以从作业输出中的链接检查远程管道的状态. 如果管道失败或阻塞,请在`#docs`聊天频道中添加一行. + +### Technical aspects[](#technical-aspects "Permalink") + +如果您想了解更深入的细节,这就是实际发生的事情: + +1. 您在合并请求中手动运行`review-docs-deploy`作业. +2. The job runs the [`scripts/trigger-build-docs`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/trigger-build-docs) script with the `deploy` flag, which in turn: + 1. 使用您的分支名称并应用以下内容: + * `docs-preview-`前缀已添加. + * 产品信息用于了解评论应用所源自的项目. + * 添加了合并请求的编号,以便您可以通过`gitlab-docs`分支名称知道其源自的合并请求. + 2. The remote branch is then created if it doesn’t exist (meaning you can re-run the manual job as many times as you want and this step will be skipped). + 3. 在 docs 项目中触发了新的跨项目管道. + 4. 预览 URL 显示在作业输出和合并请求小部件中. 您还将获得到远程管道的链接. +3. 在 docs 项目中,创建了管道,它[跳过了测试作业](https://gitlab.com/gitlab-org/gitlab-docs/blob/8d5d5c750c602a835614b02f9db42ead1c4b2f5e/.gitlab-ci.yml#L50-55)以减少构建时间. +4. 构建了 docs 网站之后,HTML 文件即作为工件上传. +5. 仅与 docs 项目相关联的特定 Runner,运行 Review App 作业,该作业下载工件,并使用`rsync`将文件传输到 NGINX 为它们提供文件的位置. + +The following GitLab features are used among others: + +* [Manual actions](../../ci/yaml/README.html#whenmanual) +* [Multi project pipelines](../../ci/multi_project_pipeline_graphs.html) +* [Review Apps](../../ci/review_apps/index.html) +* [Artifacts](../../ci/yaml/README.html#artifacts) +* [Specific Runner](../../ci/runners/README.html#prevent-a-specific-runner-from-being-enabled-for-other-projects) +* [Pipelines for merge requests](../../ci/merge_request_pipelines/index.html) + +## Testing[](#testing "Permalink") + +我们将文档视为代码,因此在 CI 管道中使用测试来维护文档的标准和质量. 提交带有新文档或更改文档的合并请求时,当前测试在 CI 作业中运行,它们是: + +* [`docs lint`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/docs.gitlab-ci.yml#L48) :对 docs 本身的内容运行一些测试: + * [`lint-doc.sh`脚本](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/lint-doc.sh)运行以下检查和操作: + * 所有 cURL 示例都使用长标记(例如:-- `--header` ,而不是`-H` ). + * `CHANGELOG.md`不包含重复的版本. + * `doc/`中没有文件是可执行文件. + * 没有添加新的`README.md` . + * [markdownlint](#markdownlint) . + * [谷](#vale) + * Nanoc 测试: + * [`internal_links`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/docs.gitlab-ci.yml#L67)检查所有内部链接(例如: `[link](../index.md)` )是否有效. + * [`internal_anchors`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/docs.gitlab-ci.yml#L69)检查所有内部锚点(例如: `[link](../index.md#internal_anchor)` )是否有效. + +### Running tests[](#running-tests "Permalink") + +除了在[本地预览更改](#previewing-the-changes-live)之外,您还可以[在本地](#previewing-the-changes-live)运行所有棉绒检查和 Nanoc 测试. + +#### Nanoc tests[](#nanoc-tests "Permalink") + +要在本地执行 Nanoc 测试: + +1. 导航到[`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs)目录. +2. Run: + + ``` + # Check for broken internal links + bundle exec nanoc check internal_links + + # Check for broken external links (might take a lot of time to complete). + # This test is set to be allowed to fail and is run only in the gitlab-docs project CI + bundle exec nanoc check internal_anchors + ``` + +#### Lint checks[](#lint-checks "Permalink") + +Lint 检查由[`lint-doc.sh`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/lint-doc.sh)脚本执行,可以按以下方式执行: + +1. 导航到`gitlab`目录. +2. Run: + + ``` + MD_DOC_PATH=path/to/my_doc.md scripts/lint-doc.sh + ``` + +`MD_DOC_PATH`指向您要运行 lint 检查的文件或目录的位置. 如果完全省略它,它将默认为`doc/`目录. 输出应类似于: + +``` +=> Linting documents at path /path/to/gitlab as ... +=> Checking for cURL short options... +=> Checking for CHANGELOG.md duplicate entries... +=> Checking /path/to/gitlab/doc for executable permissions... +=> Checking for new README.md files... +=> Linting markdown style... +=> Linting prose... +✔ 0 errors, 0 warnings and 0 suggestions in 1 file. +✔ Linting passed +``` + +请注意,这要求您要么在计算机上安装了必需的 lint 工具,要么在运行的 Docker 安装中,在这种情况下,将使用预安装了这些工具的映像. + +### Local linters[](#local-linters "Permalink") + +为了帮助您遵守[文档样式指南](styleguide.html) ,并改善添加到文档中的内容, [请安装文档短绒](#install-linters) , [并将其与代码编辑器集成](#configure-editors) . + +在 GitLab,我们主要使用: + +* [markdownlint](#markdownlint) +* [Vale](#vale) + +#### markdownlint[](#markdownlint "Permalink") + +[markdownlint](https://github.com/DavidAnson/markdownlint)检查 Markdown 语法是否遵循[某些规则](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#rules) ,并由[`docs-lint`测试使用](#testing) . + +我们的[文档样式指南](styleguide.html#markdown)和[Markdown 指南](https://about.gitlab.com/handbook/markdown-guide/)详细说明了为 GitLab 文档选择 Markdown 语法时必须进行哪些选择. 该工具有助于发现与这些准则的偏差. + +在以下项目中找到 markdownlint 配置: + +* [`gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/.markdownlint.json) +* [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/.markdownlint.json) +* [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/.markdownlint.json) +* [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/.markdownlint.json) +* [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/.markdownlint.json) + +在构建管道中也使用此配置. + +您可以使用 markdownlint: + +* [On the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--). +* [Within a code editor](#configure-editors). + +#### Vale[](#vale "Permalink") + +[淡水河谷](https://errata-ai.gitbook.io/vale/)是英语的语法,样式和单词用法惯用语. Vale 的配置存储在项目根目录下的[`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/blob/master/.vale.ini)文件中. + +Vale 支持创建可扩展多种检查类型的[自定义测试](https://errata-ai.github.io/vale/styles/) ,我们将这些检查存储在项目文档目录的`.linting/vale/styles/gitlab`目录中. + +在以下项目中找到 Vale 配置: + +* [`gitlab`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.vale/gitlab) +* [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/master/docs/.vale/gitlab) +* [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/tree/master/doc/.vale/gitlab) +* [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/tree/master/doc/.vale/gitlab) +* [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/master/doc/.vale/gitlab) + +在构建管道中也使用此配置. + +您可以使用 Vale: + +* [On the command line](https://errata-ai.gitbook.io/vale/getting-started/usage). +* [Within a code editor](#configure-editors). + +#### Install linters[](#install-linters "Permalink") + +至少要安装[markdownlint](#markdownlint)和[Vale](#vale)以匹配在构建管道中运行的检查: + +1. 使用以下任一方法安装`markdownlint-cli` : + + * `npm`: + + ``` + npm install -g markdownlint-cli + ``` + + * `yarn`: + + ``` + yarn global add markdownlint-cli + ``` + + 我们建议安装 linting [Docker image](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/dockerfiles/Dockerfile.gitlab-docs-lint#L38)文档中当前使用的`markdownlint-cli`版本. + +2. 安装[`vale`](https://github.com/errata-ai/vale/releases) . 例如,要使用`brew` for macOS 安装,请运行: + + ``` + brew install vale + ``` + + We recommend installing the version of Vale currently used in the documentation linting [Docker image](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/dockerfiles/Dockerfile.gitlab-docs-lint#L16). + +除了在命令行上使用 markdownlint 和 Vale 之外,这些工具还可以[与代码编辑器集成](#configure-editors) . + +#### Configure editors[](#configure-editors "Permalink") + +要在编辑器中配置 markdownlint,请根据需要安装以下之一: + +* [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint) +* [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint) +* [Atom](https://atom.io/packages/linter-node-markdownlint) + +要在编辑器中配置 Vale,请根据需要安装以下任一程序: + +* Sublime Text [`SublimeLinter-contrib-vale`插件](https://packagecontrol.io/packages/SublimeLinter-contrib-vale) +* Visual Studio Code [`testthedocs.vale`扩展](https://marketplace.visualstudio.com/items?itemName=testthedocs.vale) + +我们不使用[Vale Server](https://errata-ai.github.io/vale/#using-vale-with-a-text-editor-or-another-third-party-application) . + +#### Disable Vale tests[](#disable-vale-tests "Permalink") + +您可以为文档的任何部分禁用特定的 Vale 棉绒规则或所有 Vale 棉绒规则: + +* 要禁用特定规则,添加``文本之前标记和``后的文字标签,更换`rulename`与[GitLab 样式](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.linting/vale/styles/gitlab)目录中测试的文件名. +* 要禁用所有淡水河谷棉绒规则,请在文本前添加``淡水``标签,并在文本后添加``淡水``标签. + +只要有可能,仅排除有问题的规则和行. 在某些情况下,例如列表项,您可能需要禁用整个列表的绒毛,直到[Vale 问题#175](https://github.com/errata-ai/vale/issues/175)得到解决. + +有关更多信息,请参见[Vale 的文档](https://errata-ai.gitbook.io/vale/getting-started/markup#markup-based-configuration) . + +## Danger Bot[](#danger-bot "Permalink") + +GitLab 在代码审查中的某些元素上使用了[Danger](https://github.com/danger/danger) . 对于文档在合并请求中的更改,每当对`/doc`下的文件进行更改时,Danger Bot 都会在注释中留下有关文档处理的进一步说明. 这是在 GitLab 存储库中的`Dangerfile`中[/ danger / documentation /下配置的](https://gitlab.com/gitlab-org/gitlab/tree/master/danger/documentation) . \ No newline at end of file diff --git a/docs/569.md b/docs/569.md new file mode 100644 index 0000000000000000000000000000000000000000..74dc7e0628f9fe89009bb4fdb4b37aa847a6c696 --- /dev/null +++ b/docs/569.md @@ -0,0 +1,1547 @@ +# Documentation Style Guide + +> 原文:[https://docs.gitlab.com/ee/development/documentation/styleguide.html](https://docs.gitlab.com/ee/development/documentation/styleguide.html) + +* [Documentation is the single source of truth (SSOT)](#documentation-is-the-single-source-of-truth-ssot) + * [Why a single source of truth](#why-a-single-source-of-truth) + * [All information](#all-information) + * [All media types](#all-media-types) + * [No special types](#no-special-types) + * [Link instead of summarize](#link-instead-of-summarize) + * [Organize by topic, not by type](#organize-by-topic-not-by-type) + * [Docs-first methodology](#docs-first-methodology) +* [Markdown](#markdown) + * [HTML in Markdown](#html-in-markdown) + * [Markdown Rules](#markdown-rules) + * [Markdown rule `MD044/proper-names` (capitalization)](#markdown-rule-md044proper-names-capitalization) +* [Structure](#structure) + * [Folder structure overview](#folder-structure-overview) + * [Work with directories and files](#work-with-directories-and-files) + * [Avoid duplication](#avoid-duplication) + * [References across documents](#references-across-documents) + * [Structure within documents](#structure-within-documents) +* [Language](#language) + * [Point of view](#point-of-view) + * [Capitalization](#capitalization) + * [Language to avoid](#language-to-avoid) + * [Word usage clarifications](#word-usage-clarifications) + * [Contractions](#contractions) +* [Text](#text) + * [Emphasis](#emphasis) + * [Punctuation](#punctuation) + * [Placeholder text](#placeholder-text) +* [Lists](#lists) + * [Ordered vs. unordered lists](#ordered-vs-unordered-lists) + * [Markup](#markup) + * [Punctuation](#punctuation-1) + * [Nesting inside a list item](#nesting-inside-a-list-item) +* [Tables](#tables) + * [Creation guidelines](#creation-guidelines) + * [Feature tables](#feature-tables) +* [Quotes](#quotes) +* [Headings](#headings) + * [Heading titles](#heading-titles) + * [Anchor links](#anchor-links) +* [Links](#links) + * [Basic link criteria](#basic-link-criteria) + * [Links to internal documentation](#links-to-internal-documentation) + * [Links to external documentation](#links-to-external-documentation) + * [Links requiring permissions](#links-requiring-permissions) + * [Link to specific lines of code](#link-to-specific-lines-of-code) +* [Navigation](#navigation) +* [Images](#images) + * [Capture the image](#capture-the-image) + * [Save the image](#save-the-image) + * [Add the image link to content](#add-the-image-link-to-content) + * [Remove image shadow](#remove-image-shadow) + * [Compress images](#compress-images) +* [Videos](#videos) + * [Link to video](#link-to-video) + * [Embed videos](#embed-videos) +* [Code blocks](#code-blocks) +* [GitLab SVG icons](#gitlab-svg-icons) + * [Use GitLab SVGs to describe UI elements](#use-gitlab-svgs-to-describe-ui-elements) +* [Alert boxes](#alert-boxes) + * [Note](#note) + * [When to use](#when-to-use) + * [Tip](#tip) + * [Caution](#caution) + * [Danger](#danger) +* [Blockquotes](#blockquotes) +* [Terms](#terms) + * [Merge Requests (MRs)](#merge-requests-mrs) + * [Describe UI elements](#describe-ui-elements) + * [Verbs for UI elements](#verbs-for-ui-elements) + * [Other Verbs](#other-verbs) +* [GitLab versions and tiers](#gitlab-versions-and-tiers) + * [Text for documentation requiring version text](#text-for-documentation-requiring-version-text) + * [Versions in the past or future](#versions-in-the-past-or-future) + * [Importance of referencing GitLab versions and tiers](#importance-of-referencing-gitlab-versions-and-tiers) +* [Products and features](#products-and-features) + * [Avoid line breaks in names](#avoid-line-breaks-in-names) + * [Product badges](#product-badges) + * [How it works](#how-it-works) +* [Specific sections](#specific-sections) + * [GitLab restart](#gitlab-restart) + * [Installation guide](#installation-guide) + * [Configuration documentation for source and Omnibus installations](#configuration-documentation-for-source-and-omnibus-installations) + * [Troubleshooting](#troubleshooting) +* [Feature flags](#feature-flags) +* [API](#api) + * [API topic template](#api-topic-template) + * [Fake user information](#fake-user-information) + * [Fake URLs](#fake-urls) + * [Fake tokens](#fake-tokens) + * [Method description](#method-description) + * [cURL commands](#curl-commands) + * [cURL Examples](#curl-examples) + * [Simple cURL command](#simple-curl-command) + * [cURL example with parameters passed in the URL](#curl-example-with-parameters-passed-in-the-url) + * [Post data using cURL’s `--data`](#post-data-using-curls---data) + * [Post data using JSON content](#post-data-using-json-content) + * [Post data using form-data](#post-data-using-form-data) + * [Escape special characters](#escape-special-characters) + * [Pass arrays to API calls](#pass-arrays-to-api-calls) + +# Documentation Style Guide[](#documentation-style-guide "Permalink") + +本文档定义了 GitLab 文档内容和文件的标准. + +有关该文档的更多信息,请参见《 [文档指南》](index.html) . + +有关遵循该准则的编程帮助,请参阅" [测试"](index.html#testing) . + +请参阅 GitLab 手册,以获取适用于所有 GitLab 内容(不仅是文档)的进一步的[写作风格指南](https://about.gitlab.com/handbook/communication/#writing-style-guidelines) . + +## Documentation is the single source of truth (SSOT)[](#documentation-is-the-single-source-of-truth-ssot "Permalink") + +### Why a single source of truth[](#why-a-single-source-of-truth "Permalink") + +GitLab 产品和功能的文档是 SSOT,其中包含与实施,使用和故障排除有关的所有信息. 它与新产品和功能保持一致,并不断改进,以提高清晰度,准确性和完整性. + +该策略可以防止信息孤岛,从而更轻松地查找有关 GitLab 产品的信息. + +它还可以就我们包含在文档中的内容种类提供决策. + +### All information[](#all-information "Permalink") + +只要可以以充分详细的警告和警告的形式提供适当的上下文,就可以包括解决可能很少见或被认为是"危险"的解决问题的措施. 应该包括这类内容,因为它可能对其他人有帮助,并且在正确解释后,其好处大于风险. 如果您认为发现此规则有例外,请与技术写作团队联系. + +无论用户遇到何种情况,我们都会将所有故障排除信息添加到文档中. 对于" [疑难解答"部分](#troubleshooting) ,GitLab 支持人员可以自己合并添加项. + +### All media types[](#all-media-types "Permalink") + +如果内容与读者相关,则包括任何媒体类型/来源. 您可以自由地包含或链接演示文稿,图表,视频等; 不管它最初是为谁创作的,如果对我们的听众有帮助,我们都可以将其包括在内. + +* 如果使用的图像具有单独的源文件(例如,矢量或图表格式),则将该图像链接到源文件,以便任何人都可以重用或更新它. +* 除非从引用来源中引用有限的内容,否则请勿复制和粘贴其他来源的内容. 通常,最好用您自己的话语重述相关信息或链接到其他来源. + +### No special types[](#no-special-types "Permalink") + +在软件行业中,最佳实践是组织不同类型的文档. 例如, [Divio 建议](https://www.divio.com/blog/documentation/) : + +1. Tutorials +2. 入门指南 +3. Explanation +4. 参考(例如,词汇表) + +在 GitLab,我们的月度版本中有太多产品更改,以至于我们无法承受持续更新多种类型的信息的负担. 如果我们有多种类型,则信息将过时. 因此,我们只有一个文档[模板](structure.html) . + +我们目前不区分特定的文档类型,尽管一旦文档达到成熟度和质量的未来阶段,我们可以重新考虑此政策. 如果您正在阅读此书,那么尽管我们不断进行改进,但仍未达到这一点. + +### Link instead of summarize[](#link-instead-of-summarize "Permalink") + +有诱惑力将信息汇总在另一页上. 这将导致信息存在于两个地方. 相反,链接到 SSOT 并解释为什么使用信息很重要. + +### Organize by topic, not by type[](#organize-by-topic-not-by-type "Permalink") + +除了顶级受众类型的文件夹(例如, `administration` )之外,我们还按主题而不是按类型组织内容,因此可以在主题的单一来源(SSOT)部分中尽可能轻松地找到内容物. + +例如,不要创建相似媒体类型的分组. 例如: + +* Glossaries. +* FAQs. +* 所有文章或视频的集合. + +按类型对内容进行这种分组使得难以浏览所需信息,并且难以维护最新内容. 而是按主题组织内容(例如,与 CI 相关的所有内容都放在一起),并在任何相关内容之间进行交叉链接. + +### Docs-first methodology[](#docs-first-methodology "Permalink") + +我们采用**文档优先的方法,**以帮助确保文档保持完整且受信任的资源,并使有关 GitLab 使用的交流更加有效. + +* 如果文档中存在问题的答案,请共享文档链接,而不要改写信息. +* 当您遇到 GitLab 文档中没有的新信息时(例如,在处理支持案例或测试功能时),第一步应该是创建合并请求(MR),以将该信息添加到文档中. 然后,您可以共享 MR 以便传达此信息. + +如上所述,对将来的 GitLab 使用或故障排除有用的新信息不应直接写在论坛或其他消息系统中,而应添加到文档 MR 中,然后再进行引用. 请注意,除其他任何文档更改外,您还可以: + +* 如果不存在,请在文档中添加" [疑难解答"部分](#troubleshooting) . +* 取消注释并使用占位符疑难解答部分,该部分包含在我们的[文档模板中](structure.html#template-for-new-docs) (如果存在). + +我们向文档自如地添加有用信息的次数越多,文档就越会被用来(更成功)有效地完成任务和解决问题. + +如果您在考虑,创作或编辑文档时遇到问题,请提及适用于[DevOps 阶段](https://about.gitlab.com/handbook/product/product-categories/#devops-stages)的编写者,以`#docs`或 GitLab 中的 Slack 的技术写作团队提出. 否则,请尽力而为. 它并不一定是完美的. 团队很乐意审查和改进您的内容. 在开始您的第一个文档 MR 之前,请查阅[文档指南](index.html) . + +具有与文档不同的任何形式的知识库都将违反文档优先方法,因为其内容会与文档重叠. + +## Markdown[](#markdown "Permalink") + +所有的 GitLab 文档都是使用[Markdown](https://en.wikipedia.org/wiki/Markdown)编写的. + +[文档网站](https://s0docs0gitlab0com.icopy.site)使用 GitLab Kramdown 作为 Markdown 渲染引擎. 有关完整的 Kramdown 参考,请参阅《 [GitLab Markdown Kramdown 指南》](https://about.gitlab.com/handbook/markdown-guide/) . + +[`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown) Ruby gem 将来将支持所有[GFM 标记](../../user/markdown.html) . 也就是说,所有标记都支持在 GitLab 应用程序本身中显示. 目前,请按照链接的样式指南中的规则使用常规的 Markdown 标记. + +请注意,特定于 Kramdown 的标记(例如`{:.class}` )不会在[`/help`](index.html#gitlab-help)下的 GitLab 实例上正确呈现. + +### HTML in Markdown[](#html-in-markdown "Permalink") + +硬编码的 HTML 是有效的,尽管在使用`/help`时不建议使用. 只要允许 HTML,就可以: + +* Markdown 中没有等效的标记. +* 高级表是必需的. +* 需要特殊的样式. +* 由技术作家审查和批准. + +### Markdown Rules[](#markdown-rules "Permalink") + +GitLab 通过使用[markdownlint](index.html#markdownlint) [测试文档更改](index.html#testing)来确保所有文档中使用的 Markdown 是一致的,并且易于查看和维护. 当任何文档的 Markdown 格式存在问题时,此棉绒测试将失败,该问题可能导致页面在 GitLab 中无法正确呈现. 当文档使用非标准 Markdown(可以正确显示,但不是 GitLab 文档的当前标准)时,它也会失败. + +#### Markdown rule `MD044/proper-names` (capitalization)[](#markdown-rule-md044proper-names-capitalization "Permalink") + +可能引起混乱的规则是`MD044/proper-names` ,因为可能无法立即弄清是什么导致 markdownlint 失败或如何纠正失败. 此规则检查每个项目的`.markdownlint.json`文件中列出的已知单词的列表,以验证是否正确使用了大写字母和反引号. 反引号中的单词将被 markdownlint 忽略. + +通常,产品名称应紧跟产品,协议等正式名称的大写字母. 请参阅[`.markdownlint.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.markdownlint.json)以获取有关 GitLab 文档中经过适当大写测试的单词. + +如果使用不正确的大小写,则某些示例将失败: + +* MinIO(需要资本`IO` ) +* NGINX(需要所有资金) +* runit(需要小写`r` ) + +此外,反引号中必须包含命令,参数,值,文件名等. 例如: + +* "在您的`.gitlab.yml`更改`needs`关键字……" + * `needs`是一个参数,而`.gitlab.yml`是一个文件,因此两者都需要反引号. 此外, `.gitlab.yml`没有`.gitlab.yml` G 或 L,它将使 markdownlint 失败而没有反引号. +* “Run `git clone` to clone a Git repository…” + * `git clone`是命令,因此它必须是小写字母,而 Git 是乘积,因此它必须具有大写字母 G. + +## Structure[](#structure "Permalink") + +因为我们希望文档成为 SSOT,所以我们应该[按主题(而不是类型)进行组织](#organize-by-topic-not-by-type) . + +### Folder structure overview[](#folder-structure-overview "Permalink") + +该文档由顶级受众文件夹[`user`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/user) , [`administration`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/administration)和[`development`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/development) (贡献)文件夹分开. + +Beyond that, we primarily follow the structure of the GitLab user interface or API. + +我们的目标是要建立一个清晰的层次结构,并包含有意义的 URL,例如`docs.gitlab.com/user/project/merge_requests/` . 使用这种模式,您可以立即知道您正在导航到有关 Project 功能的用户相关文档; 特别是关于合并请求. 我们网站的路径与我们存储库的路径匹配,因此清晰的结构还使文档更易于更新. + +下表显示了什么样的文档. + +| Directory | 这里属于什么 | +| --- | --- | +| `doc/user/` | 与用户相关的文档. 可以在 GitLab UI 中完成的所有操作都在这里进行,包括使用`/admin`界面. | +| `doc/administration/` | 要求用户有权访问安装了 GitLab 的服务器的文档. 可以通过 GitLab 界面访问的管理设置位于`doc/user/admin_area/` . | +| `doc/api/` | API 相关文档. | +| `doc/development/` | 与 GitLab 开发相关的文档,无论是贡献代码还是文档. 相关的流程和样式指南应该在此处. | +| `doc/legal/` | 有关对 GitLab 进行贡献的法律文件. | +| `doc/install/` | 包含有关安装 GitLab 的说明. | +| `doc/update/` | 包含有关更新 GitLab 的说明. | +| `doc/topics/` | 每个主题的索引( `doc/topics/topic-name/index.md` ):该主题的所有资源. | + +### Work with directories and files[](#work-with-directories-and-files "Permalink") + +1. 创建新目录时,请始终以`index.md`文件开头. 不要使用其他文件名, **也不要**创建`README.md`文件. +2. **请勿**在文件名,目录名,分支名和任何会生成路径的文件中使用特殊字符和空格或大写字母. +3. 创建新文档时,如果名称中包含多个单词,请确保使用下划线而不是空格或破折号( `-` ). 例如,正确的命名应为`import_projects_from_github.md` . 相同的规则适用于图像. +4. 对于图像文件,请勿超过 100KB. +5. 不要将视频文件上传到产品存储库. [链接或嵌入视频](#videos) . +6. 有四个主要目录, `user` , `administration` , `api`和`development` . +7. `doc/user/`目录具有五个主要子目录: `project/` , `group/` , `profile/` , `dashboard/`和`admin_area/` . + 1. `doc/user/project/`应包含所有与项目相关的文档. + 2. `doc/user/group/`应包含所有与组有关的文档. + 3. `doc/user/profile/`应包含所有与个人资料相关的文档. 您在`/profile`下导航的每个页面都应该有其自己的文档,例如`account.md` , `applications.md`或`emails.md` . + 4. `doc/user/dashboard/`应包含所有与仪表板相关的文档. + 5. `doc/user/admin_area/`应该包含所有与管理员相关的文档,这些文档描述了通过访问 GitLab 的管理界面可以实现的目的( *不要与需要服务器访问权限的`doc/administration`混淆* ). + 1. `/admin/application_settings/`下的每个类别都应有自己的文档,位于`doc/user/admin_area/settings/` . 例如," **可见性和访问控制"**类别应具有位于`doc/user/admin_area/settings/visibility_and_access_controls.md` . +8. `doc/topics/`目录包含与主题相关的技术内容. 必要时创建`doc/topics/topic-name/subtopic-name/index.md` . 应放置与用户和管理员相关的常规文档. +9. 目录`/workflow/` , `/university/`和`/articles/`已被**弃用** ,并且大多数文档已通过较小的迭代移动到了正确的位置. + +如果您不确定文档或内容添加应该放在哪里,那么这不会阻止您创作和贡献. 您可以根据自己的最佳判断,然后要求 MR 的审阅者确认您的决定,和/或在此过程的任何阶段询问技术作家. 技术写作团队将审查所有文档更改,无论如何,并且如果有合适的位置,可以移动内容. + +### Avoid duplication[](#avoid-duplication "Permalink") + +不要在多个地方包含相同的信息. [链接到 SSOT.](#link-instead-of-summarize) + +### References across documents[](#references-across-documents "Permalink") + +* 给每个文件夹一个 index.md 页面,该页面介绍该主题,介绍其中的页面,并链接到其中的页面(包括任何下一级子路径的索引页面). +* 为确保可发现性,请确保每个新文档或重命名的文档都从其更高级别的索引页面和其他相关页面链接. +* 当引用其他 GitLab 产品和功能时,至少在第一次提及时,链接到它们各自的文档. +* 当引用第三方产品或技术时,请链接到其外部站点,文档和资源. + +### Structure within documents[](#structure-within-documents "Permalink") + +* 包括[结构和模板](structure.html)页面上所述的所有适用小节. +* Structure content in alphabetical order in tables, lists, and so on, unless there is a logical reason not to (for example, when mirroring the UI or an otherwise ordered sequence). + +## Language[](#language "Permalink") + +GitLab 文档应清晰易懂. + +* 清楚,简明并遵守文档的目标. +* 用美国英语和美国语法书写. (在[`British.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/British.yml)测试.) +* 使用包容性语言. + +### Point of view[](#point-of-view "Permalink") + +在大多数情况下,使用第二人称(您自己)的观点是适当的,因为它友好且易于理解. (在[`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml)测试.) + +### Capitalization[](#capitalization "Permalink") + +* 在 GitLab 中大写" G"和" L". +* 句子大小写用于: + * 标题. + * 标签. + * 菜单项. + * 纽扣. + * 标题. 除非标题中提及产品功能,否则请勿在标题中大写其他单词. 例如: + * 大写"问题"在`## What you can do with GitLab Issues` ,但在`## Closing multiple issues`不可接受. +* 引用时使用标题大小写: + * [GitLab 功能](https://about.gitlab.com/features/) . 例如,发行板,地缘和亚军. + * GitLab [产品层](https://about.gitlab.com/pricing/) . 例如,GitLab Core 和 GitLab Ultimate. (在[`BadgeCapitalization.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/BadgeCapitalization.yml)测试.) + * 第三方产品. 例如,Prometheus,Kubernetes 和 Git. + * 方法或方法论. 例如,持续集成,持续部署,Scrum 和敏捷. (在[`.markdownlint.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.markdownlint.json)测试.) + + **注意:**某些功能也是对象. 例如," GitLab 的合并请求支持 X"和"为 Z 创建新的合并请求". + +### Language to avoid[](#language-to-avoid "Permalink") + +创建文档时,请限制或避免使用以下动词时态,单词和短语: + +* 避免行话. +* 避免使用不常见的单词. +* 不要以第一人称单数形式书写. (在[`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml)测试.) + * 代替"我"或"我",而使用"我们","您","我们"或"一个". + * 在可能的情况下,通过写第二人称(" you"或命令式)来保持用户的注意力. +* 不要过度使用" that". 在许多情况下,您可以从句子中删除" that"并提高可读性. +* 避免使用将来时: + * 代替"在执行此命令后,GitLab 将显示结果",而应使用"在执行此命令后,GitLab 显示结果". + * 仅在将来某个时间实际发生动作或结果时,才使用将来时来表达. +* 不要使用斜杠将不同的单词组合在一起,也不要用"或"代替: + * 代替"和/或",可以考虑使用"或",或使用其他明智的结构. + * 其他示例包括"克隆/获取",作者/受让人和"命名空间/存储库名称". 以适当的方式拆分任何此类实例. + * 该规则的例外情况包括公认的技术术语,例如 CI / CD 和 TCP / IP. +* We discourage use of Latin abbreviations, such as “e.g.,” “i.e.,” or “etc.,” as even native users of English might misunderstand them. (Tested in [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml).) + + * 代替"即",使用"即". + * 代替"例如",使用"例如","例如","例如"或"喜欢". + * 代替"等",可以使用"依此类推",也可以考虑对其进行编辑,因为它可能含糊不清. +* 在谈论产品或其功能时,请避免*当前*使用该词. 该文档按原样描述了该产品,而不是将来的某个不确定点. +* 避免在增加 GitLab 为其他用户的性能时使用*可扩展性*一词. 在其他情况下,可以使用" *缩放"*或" *缩放"*一词,但对于其他用户而言,提高 GitLab 性能的参考应将读者引导至 GitLab [参考架构](../../administration/reference_architectures/index.html)页面. +* 避免使用所有形式的短语" *高可用性"*和" *HA"* ,而是将读者引导至 GitLab [参考体系结构,](../../administration/reference_architectures/index.html)以获取有关配置 GitLab 使其随着时间的推移具有更多用户所需的性能的信息. +* 不要使用亵渎或 ob 亵. 这样做可能会对其他用户和贡献者产生负面影响,这与 GitLab 的" [多样性","包容性"和"归属"](https://about.gitlab.com/handbook/values/#diversity-inclusion)的价值背道而驰. +* 避免使用对[种族不敏感的术语或短语](https://www.marketplace.org/2020/06/17/tech-companies-update-language-to-avoid-offensive-terms/) . 例如: + * 将*主*数据库和*辅助*数据库用于数据库和服务器关系. + * 使用*allowlist*和*denylist*来描述访问控制列表. + +### Word usage clarifications[](#word-usage-clarifications "Permalink") + +* 不要互换使用" may"和" might": + * 使用"可能"表示发生某事的可能性. "如果跳过此步骤,则导入过程可能会失败." + * 使用"可能"表示允许某人做某事,或者考虑使用"可以". "您可以在此屏幕上选择一个选项." 或者,"您可以在此屏幕上选择任一选项." + +### Contractions[](#contractions "Permalink") + +* Use common contractions when it helps create a friendly and informal tone, especially in tutorials, instructional documentation, and [UIs](https://design.gitlab.com/content/punctuation/#contractions). (Tested in [`Contractions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Contractions.yml).) + + | Do | Don’t | + | --- | --- | + | it’s | 它是 | + | can’t | cannot | + | wouldn’t | 不会 | + | you’re | 你是 | + | you’ve | 你有 | + | haven’t | 没有 | + | don’t | 不要 | + | we’re | 我们是 | + | that’s | 那是 | + | won’t | 将不会 | + +* 避免少见的宫缩: + + | Do | Don’t | + | --- | --- | + | 他会 | he’d | + | 它会 | it’ll | + | 应该有 | should’ve | + | 那里会 | there’d | + +* 不要使用带有专有名词和动词的缩略词. 例如: + + | Do | Don’t | + | --- | --- | + | GitLab 正在创建 X | manbetx 客户端打不开创建 X | + +* 当您需要强调负面情绪时,不要使用收缩. 例如: + + | Do | Don’t | + | --- | --- | + | **不要**为 Y 安装 X | **不要**将 X 与 Y 一起安装 | + +* 不要在参考文档中使用收缩. 例如: + + | Do | Don’t | + | --- | --- | + | **不要**设置限制大于 1000 | **请勿**将限制设置为大于 1000 | + | 对于`parameter1` ,默认值为 10 | 对于`parameter1` ,默认值为 10 | + +* 避免错误消息中出现收缩. 例子: + + | Do | Don’t | + | --- | --- | + | 不允许对本地主机的请求 | 不允许对本地主机的请求 | + | 指定的 URL 不能使用 | 指定的网址无法使用 | + +## Text[](#text "Permalink") + +* [Write in Markdown](#markdown). +* 分隔长行(最好最多 100 个字符)可以更轻松地提供有关小块文本的反馈. +* 在新段落中插入一个空行. +* 在不同的标记之间插入一个空行(例如,在每个段落,标题,列表等之后). 例: + + ``` + ## Header + + Paragraph. + - List item 1 + - List item 2 + ``` + +### Emphasis[](#emphasis "Permalink") + +* 使用双星号( `**` )将单词或文本标记为粗体( `**bold**` ). +* 下划线( `_` )用于斜体( `_italic_` )文本. +* 块引用使用大于( `>` ). + +### Punctuation[](#punctuation "Permalink") + +检查下表中 GitLab 文档的常规标点规则. 检查以下[列表的](#lists)特定标点规则. + +| Rule | Example | +| --- | --- | +| 总是以句号结束完整的句子. | *有关完整概述,请通读本文档.* | +| 在开始新句子时,请始终在句点之后添加空格. | *有关完整的概述,请查看此文档. 有关其他参考,请查阅本指南.* | +| 不要使用双空格. (在[`SentenceSpacing.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SentenceSpacing.yml)测试.) | — | +| 不要使用制表符进行缩进. 请改用空格. 您可以将代码编辑器配置为在按 Tab 键时输出空格而不是制表符. | — | +| 在列表中最后一个"和/或"之前使用连续逗号("牛津逗号"). (在[`OxfordComma.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/OxfordComma.yml)测试.) | *您可以创建新问题,合并请求和里程碑.* | +| 在句子中使用破折号之前和之后,请始终添加空格(例如,用于替换逗号). | *您应该尝试这样做-还是不可以.* | +| 总是在冒号后面使用小写字母. | *相关问题:一种在问题之间建立关系的方法.* | + +### Placeholder text[](#placeholder-text "Permalink") + +在示例中,编写者通常会提供除特定于阅读者的值之外完整的命令或配置. + +在这些情况下,使用[`<`和`>`](https://en.wikipedia.org/wiki/Usage_message#Pattern)指出读者必须用自己的值替换文本的位置. + +例如: + +``` +cp +``` + +## Lists[](#lists "Permalink") + +* 始终使用大写字母开头列表项,除非它们是反引号或类似的参数或命令. +* 始终在列表前后留空行. +* 以空格(不是制表符)开头的行表示[嵌套的子项](#nesting-inside-a-list-item) . + +### Ordered vs. unordered lists[](#ordered-vs-unordered-lists "Permalink") + +仅当其项目描述要遵循的步骤序列时,才使用有序列表. + +Do: + +``` +These are the steps to do something: + 1. First, do the first step. +1. Then, do the next step. +1. Finally, do the last step. +``` + +Don’t: + +``` +This is a list of available features: + 1. Feature 1 +1. Feature 2 +1. Feature 3 +``` + +### Markup[](#markup "Permalink") + +* 对于无序列表,请使用破折号( `-` )代替星号( `*` ). +* 在有序列表中的每个项目之前添加前缀`1.` .. 呈现后,列表项将自动以顺序编号显示. + +### Punctuation[](#punctuation-1 "Permalink") + +* 不要在列表项的末尾添加逗号( `,` )或分号( `;` ). +* 如果项目由完整的句子组成,则仅在项目的末尾添加句号. [完整句子](https://www2.le.ac.uk/offices/ld/all-resources/writing/grammar/grammar-guides/sentence)的[定义](https://www2.le.ac.uk/offices/ld/all-resources/writing/grammar/grammar-guides/sentence)是: *"完整句子总是包含一个动词,表达一个完整的构想,并且在单独存在时有意义"* . +* Be consistent throughout the list: if the majority of the items do not end in a period, do not end any of the items in a period, even if they consist of a complete sentence. The opposite is also valid: if the majority of the items end with a period, end all with a period. +* 从解释性文字分隔列表项用冒号( `:` ). 例如: + + ``` + The list is as follows: + - First item: this explains the first item. + - Second item: this explains the second item. + ``` + +**Examples:** + +Do: + +* 第一个清单项目 +* 第二个清单项目 +* 第三清单项目 + +Don’t: + +* 第一个清单项目 +* 第二个清单项目 +* 第三列表项. + +Do: + +* 假设这是一个完整的句子. +* 假设这也是一个完整的句子. +* 句子不完整. + +请勿(各种句号的使用;多数规则): + +* 假设这是一个完整的句子. +* 假设这也是一个完整的句子. +* 句子不完整 + +### Nesting inside a list item[](#nesting-inside-a-list-item "Permalink") + +可以将项目嵌套在列表项目下,以便它们呈现与列表项目相同的缩进. 这可以通过以下方式完成: + +* [Code blocks](#code-blocks) +* [Blockquotes](#blockquotes) +* [Alert boxes](#alert-boxes) +* [Images](#images) + +嵌套在列表中的项目应始终与列表项目的第一个字符对齐. 在无序列表(使用`-` )中,这表示每个缩进级别有两个空格: + +``` +- Unordered list item 1 + + A line nested using 2 spaces to align with the `U` above. + - Unordered list item 2 + > A quote block that will nest + > inside list item 2. + - Unordered list item 3 + + ```plaintext + a codeblock that will next inside list item 3 + ``` + - Unordered list item 4 + + ![an image that will nest inside list item 4](image.png) +``` + +对于有序列表,每个缩进级别使用三个空格: + +``` +1. Ordered list item 1 + + A line nested using 3 spaces to align with the `O` above. + 1. Ordered list item 2 + > A quote block that will nest + > inside list item 2. + 1. Ordered list item 3 + + ```plaintext + a codeblock that will next inside list item 3 + ``` + 1. Ordered list item 4 + + ![an image that will nest inside list item 4](image.png) +``` + +您可以使用与上述相同的规则将完整列表嵌套在其他列表中. 如果您希望混合类型,也可以,只要您不混合同一级别的项目即可: + +``` +1. Ordered list item one. +1. Ordered list item two. + - Nested unordered list item one. + - Nested unordered list item two. +1. Ordered list item three. + - Unordered list item one. +- Unordered list item two. + 1. Nested ordered list item one. + 1. Nested ordered list item two. +- Unordered list item three. +``` + +## Tables[](#tables "Permalink") + +应该使用表格以简单的方式描述复杂的信息. 请注意,在许多情况下,无序列表足以描述一个项目列表,而每个项目只有一个简单的描述. 但是,如果您拥有最能用矩阵描述的数据,则表是使用的最佳选择. + +### Creation guidelines[](#creation-guidelines "Permalink") + +由于可访问性和可扫描性要求,表中不应包含任何空白单元格. 如果某个单元格没有其他有意义的值,请考虑输入*N / A* ("不适用")或*不输入* . + +为了使表更易于维护,请考虑在列宽上添加额外的空格以使其一致. 例如: + +``` +| App name | Description | Requirements | +|:---------|:---------------------|:---------------| +| App 1 | Description text 1\. | Requirements 1 | +| App 2 | Description text 2\. | None | +``` + +考虑在编辑器中安装插件或扩展程序以格式化表格: + +* 用于 Visual Studio 代码的[Markdown 表修饰符](https://marketplace.visualstudio.com/items?itemName=darkriszty.markdown-table-prettify) +* 升华文字的[Markdown 表格式化](https://packagecontrol.io/packages/Markdown Table Formatter)程序 +* 用于 Atom 的[Markdown 表格式化](https://atom.io/packages/markdown-table-formatter)程序 + +### Feature tables[](#feature-tables "Permalink") + +创建功能列表时(例如," [权限"](../../user/permissions.html#project-members-permissions)页面上的某些角色是否可以使用功能),请使用以下短语(基于 SVG 图标): + +* *No*: No +* *Yes*: Yes + +## Quotes[](#quotes "Permalink") + +仅适用于 Markdown 内容,不适用于优先事项条目: + +* 标准引号:双引号( `"` ).例如:"这用双引号引起来". +* 用引号引起来:双引号( `"` )包裹单引号( `'` ).例如:"我正在用引号引起来". + +有关其他标点规则,请参考[GitLab UX 指南](https://design.gitlab.com/content/punctuation/) . + +## Headings[](#headings "Permalink") + +* 通过在每个文档的开头添加`#` (在使用 Markdown 时), **仅**在每个文档中添加**一个 H1** . `h1`将是文档`` . +* 从`h2` ( `##` )开始,并遵循`h2` > `h3` > `h4` > `h5` > `h6`的顺序. 切勿跳过层次结构级别,例如`h2` > `h4` +* 避免将数字放在标题中. 数字移动,因此文档锚链接也移动,最终导致死链接. 如果您认为在标题中添加数字非常有必要,请确保至少与"合并请求"中的某人进行讨论. +* [避免](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/84)在标题中[使用符号和特殊字符](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/84) . 只要有可能,它们应为纯文本和简短文本. +* 避免添加显示短暂状态的内容. 例如,如果某个功能被认为是 Beta 或试验性功能,请将此信息放在注释中而不是标题中. +* 引入新文档时,请注意标题在语法和语法上都是正确的. 提及[指定的技术作家(TW)](https://about.gitlab.com/handbook/product/product-categories/)以进行审查. 这是为了确保没有错误标题的文档将在未经审核的情况下生效,从而防止在纠正时出现无效链接和重定向问题. +* 在标题前后只留一个空白行. +* 不要在标题中使用链接. +* 根据功能所属的级别添加相应的[产品徽章](#product-badges) . +* 我们的 docs 网站搜索引擎会区分标题和副标题中使用的单词的优先级. 如[标题标题](#heading-titles)部分所示,使标题标题清晰,描述性且完整,以帮助用户找到正确的示例. +* 有关将标题[大写](#capitalization)的指南,请参见[大写](#capitalization) . + +### Heading titles[](#heading-titles "Permalink") + +保持标题清晰,直接. 使每个单词都重要. 为了适应搜索引擎优化(SEO),请尽可能使用命令. + +| Do | Don’t | +| --- | --- | +| Configure GDK | Configuring GDK | +| GitLab 发布和维护政策 | 本节介绍 GitLab 的发布和维护政策 | +| 向后移植到较旧的版本 | 向后移植到较旧的版本 | +| GitLab 页面示例 | Examples | + +有关大写标题的准则,请参见[大写](#capitalization)部分. + +**注意:**如果更改现有标题,请当心. 任何此类更改可能不仅影响页面内的[链接](#anchor-links) ,而且还可能影响来自 GitLab 本身的链接以及指向 GitLab 文档的外部链接. + +### Anchor links[](#anchor-links "Permalink") + +渲染时,标题会自动生成锚链接. `## This is an example`生成锚点`#this-is-an-example` . + +请记住,GitLab UI 链接到大量文档以及相应的锚链接,以将用户带到正确的位置. 因此,当您更改标题时,请在`doc/*` , `app/views/*`和`ee/app/views/*`搜索旧的锚点,以确保您不会破坏从其他文档或 GitLab UI 链接的锚点. 如果找到旧的锚,请确保将其替换为新的锚. + +Important: + +* 除非需要链接到文档的特定部分,否则请避免将文档交到标题. 如果方向改变,这将避免将来破坏锚. +* 如果可能,请避免更改标题,因为它们不仅是内部链接的. 互联网上有指向 GitLab 文档的各种链接,例如教程,演示文稿,StackOverflow 帖子和其他资源. +* 不要链接到`h1`标题. + +需要注意的是,与 Kramdown,也可以自定义 ID 添加到与降价的标记 HTML 元素,但他们**没有**在 GitLab 的工作`/help` . 因此,除非另行通知,否则不要使用此选项. + +## Links[](#links "Permalink") + +链接在 GitLab 文档中很重要. 它们使您可以[链接而不是进行汇总,](#link-instead-of-summarize)以帮助在 GitLab 文档中保留[SSoT](#why-a-single-source-of-truth) . + +我们提供以下类别的链接指南: + +* 如何设置标题的[锚链接](#anchor-links) . +* 如何设置[标准](#basic-link-criteria)配置的链接. +* [链接到`help`](../documentation/index.html#linking-to-help)页面时要设置的内容. +* 如何设置[指向内部文档的链接以](#links-to-internal-documentation)进行交叉引用. +* 如何建立[指向](#links-to-external-documentation)权威来源的[外部文档的链接](#links-to-external-documentation) . +* 何时使用[需要权限的链接](#links-requiring-permissions) . +* 如何设置[视频链接](#link-to-video) . +* 如何在[版本文本中包含链接](#text-for-documentation-requiring-version-text) . +* 如何[链接到特定的代码行](#link-to-specific-lines-of-code) + +### Basic link criteria[](#basic-link-criteria "Permalink") + +* 使用内联链接 Markdown 标记`[Text](https://example.com)` . 它更易于阅读,查看和维护. **不要**使用`[Text][identifier]` . + +* 使用[有意义的锚文本](https://www.futurehosting.com/blog/links-should-have-meaningful-anchor-text-heres-why/) . 例如, `Read more about GitLab Issue Boards [here](LINK)`编写类似" `Read more about GitLab Issue Boards [here](LINK)` ,而不是撰写`Read more about [GitLab Issue Boards](LINK)` . + +### Links to internal documentation[](#links-to-internal-documentation "Permalink") + +**注意:** *内部*是指同一项目中的文档. 链接到单独项目中的文档时(例如,从 GitLab 文档链接到 Omnibus 文档),必须使用绝对 URL. + +请勿使用`https://docs.gitlab.com/ee/index.html`类的绝对 URL 交叉链接到同一项目中的其他文档. 使用指向文件的相对链接,例如`../index.md` . (在呈现网站时将这些转换为 HTML.) + +相对链接使交叉链接可以正常工作: + +* 在 Review Apps,本地预览和`/help` . +* 在本地处理文档时,您可以在此过程中尽早验证它们是否有效. +* 浏览各自存储库中的文档文件时,可以在 GitLab UI 中使用. 例如,显示在`https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/README.md`的链接. + +链接到内部文档: + +* 使用相对链接指向同一存储库中的 Markdown 文件. +* 不要使用绝对 URL 或`docs.gitlab.com` URL. +* 使用`../`导航到更高级别的目录. +* 不要相对于根链接. 例如,/ `/ee/user/gitlab_com/index.md` . + + Don’t: + + * `https://docs.gitlab.com/ee/administration/geo/replication/troubleshooting.html` + * `/ee/administration/geo/replication/troubleshooting.md` + + Do: `../../geo/replication/troubleshooting.md` + +* 始终在链接末尾添加文件名`file.md` ,扩展名为`.md`而不是`.html` . + + Don’t: + + * `../../merge_requests/` + * `../../issues/tags.html` + * `../../issues/tags.html#stages` + + Do: + + * `../../merge_requests/index.md` + * `../../issues/tags.md` + * `../../issues/tags.md#stages` + +**注意:** GitLab 的[`/help`](index.html#gitlab-help)部分必须使用 Markdown 扩展名. + +### Links to external documentation[](#links-to-external-documentation "Permalink") + +描述与外部软件的交互时,包括指向外部文档的链接通常会很有帮助. 如果可能,请确保您链接到**权威**来源. 例如,如果您要描述 Microsoft Active Directory 中的功能,请包括指向 Microsoft 官方文档的链接. + +### Links requiring permissions[](#links-requiring-permissions "Permalink") + +不要直接链接到: + +* [Confidential issues](../../user/project/issues/confidential_issues.html). +* 需要[特殊权限](../../user/permissions.html)才能查看的项目功能. + +这些将因以下原因而失败: + +* 那些没有足够权限的人. +* 自动链接检查器. + +Instead: + +* 为了减少混乱,请在文本中提及以下信息之一: + * 包含在一个机密问题中. + * 需要项目的特殊权限才能查看. +* 在反勾号( ``` )中提供一个链接,以便那些有权访问该问题的人可以轻松导航到该问题. + +Example: + +``` +For more information, see the [confidential issue](../../user/project/issues/confidential_issues.md) `https://gitlab.com/gitlab-org/gitlab-foss/-/issues/<issue_number>`. +``` + +### Link to specific lines of code[](#link-to-specific-lines-of-code "Permalink") + +链接到文件中的特定行时,请链接到提交而不是分支. 代码行随时间变化,因此,使用 commit 链接链接到一行可确保用户落在您所指的行上. 在查看项目中的文件时,可以使用" **永久链接"**按钮,它可以轻松生成指向给定文件的最新提交的链接. + +* **Do:** `[link to line 3](https://gitlab.com/gitlab-org/gitlab/-/blob/11f17c56d8b7f0b752562d78a4298a3a95b5ce66/.gitlab/issue_templates/Feature%20proposal.md#L3)` +* **Don’t:** `[link to line 3](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal.md#L3).` + +如果由于进一步的提交,该链接的表达式不再在文件的该行中,则您仍然可以在文件中搜索该查询. 在这种情况下,请更新文档以确保其链接到文件的最新版本. + +## Navigation[](#navigation "Permalink") + +指示通过 UI 导航的步骤: + +* 使用界面中显示的确切字词,包括所有大写字母. +* 使用粗体文本显示导航项,并使用字符"大于"( `>` )作为分隔符(例如, `Navigate to your project's **Settings > CI/CD**` ). +* 如果有任何可展开的菜单,请确保提及用户需要展开选项卡以找到您要引用的设置(例如, `Navigate to your project's **Settings > CI/CD** and expand **General pipelines**` ). + +## Images[](#images "Permalink") + +图像(包括屏幕截图)可以帮助读者更好地理解概念. 但是,它们可能难以维护,应谨慎使用. + +在文档中包括图片之前,请确保它为读者提供了价值. + +### Capture the image[](#capture-the-image "Permalink") + +使用图像可以帮助读者了解它们在过程中的位置,或与应用程序进行交互的方式. + +截屏时: + +* *捕获页面中最相关的区域.* 不要包含不必要的空白或页面区域,以免说明您的观点. 另外,如果不需要,不要包括整个页面,而且还要确保图像包含足够的信息以允许用户确定事物的位置. +* *始终如一.* 找到适合您的浏览器窗口大小,该窗口大小还会显示产品的所有区域,包括左侧导航栏(通常> 1200 像素宽). 为了保持一致,请通过安装用于将窗口设置为特定大小的浏览器扩展程序(例如,用于 Google Chrome 的[Window Resizer](https://chrome.google.com/webstore/detail/window-resizer/kkelicaakdanhinjdeammmilcgefonfh/related?hl=en) ),将此浏览器窗口大小用于屏幕截图. + +### Save the image[](#save-the-image "Permalink") + +* 用一个小写的文件名保存该图像,该文件名描述了图像中的功能或概念. 如果该图像属于 GitLab 界面,则根据以下格式将 GitLab 版本附加到文件名: `image_name_vX_Y.png` . 例如,对于从 GitLab 11.1 的管道页面中截取的屏幕截图,有效名称为`pipelines_v11_1.png` . 如果要添加的插图不包含用户界面的各个部分,请添加与添加图像的版本相对应的版本号; 对于添加到 11.1 里程碑中的 MR,插图的有效名称是`devops_diagram_v11_1.png` . +* 将图像放置在名为`img/`的单独目录中,该目录与您正在使用的`.md`文档所在的目录相同. +* 考虑使用 PNG 图像而不是 JPEG. +* [Compress all PNG images](#compress-images). +* 使用[https://ezgif.com/optimize](https://ezgif.com/optimize)或类似工具压缩 gif. +* 应该使用图像(仅在必要时使用)来*说明*过程说明,而不是*替代*过程. +* 图片大小上限:100KB(含 Gif). +* 另请参阅如何链接和嵌入[视频](#videos)以说明文档. + +### Add the image link to content[](#add-the-image-link-to-content "Permalink") + +用于在文档中包含图像的 Markdown 代码为: `![Image description which will be the alt tag](img/document_image_title_vX_Y.png)` + +图像描述是 docs 网站上渲染图像的替代文本. 对于可访问性和 SEO,请使用以下[描述](https://webaim.org/techniques/alttext/) : + +* 准确,简洁且独特. +* 请勿使用*…的图像*或*…的* *图形*来描述图像. + +另外,如果标题紧随图像之后,请确保在图像和标题之间添加三个破折号( `---` ). + +### Remove image shadow[](#remove-image-shadow "Permalink") + +默认情况下,在[GitLab 文档站点](https://s0docs0gitlab0com.icopy.site)上显示的所有图像都有一个阴影框. 要删除框阴影,请使用直接应用于 HTML `img`标签的图像类`.image-noshadow` : + +``` +<img src="path/to/image.jpg" alt="Alt text (required)" class="image-noshadow"> +``` + +### Compress images[](#compress-images "Permalink") + +您应该始终压缩添加到文档中的任何新图像. 一种已知的工具是[`pngquant`](https://pngquant.org/) ,它是跨平台和开源的. 通过访问官方网站并按照您的操作系统说明进行安装. + +GitLab 有一个[Rake 任务](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/tasks/pngquant.rake) ,可用于自动执行该过程. 在本地`https://gitlab.com/gitlab-org/gitlab`副本的根目录中,在终端中运行: + +* 压缩之前,如果需要,请检查是否已压缩所有文档 PNG 图像: + + ``` + bundle exec rake pngquant:lint + ``` + +* 使用`pngquant`压缩所有文档 PNG 图像: + + ``` + bundle exec rake pngquant:compress + ``` + +唯一需要注意的是,该任务将在`doc/`下的所有图像上运行,而不仅仅是您可能包含在合并请求中的图像. 在这种情况下,您可以运行 compress 任务,仅提交与合并请求相关的图像. + +## Videos[](#videos "Permalink") + +强烈建议将 GitLab 的现有 YouTube 视频教程添加到文档中,除非该视频已过时. 视频不应取代文档,而应补充或说明文档. 如果视频中的内容是功能及其关键用例的基础,但是文档中没有对此进行充分介绍,请将此详细信息添加到文档文本中,或者创建问题以查看视频并这样做. + +不要将视频上传到产品存储库. [链接](#link-to-video)或[嵌入](#embed-videos)它们. + +### Link to video[](#link-to-video "Permalink") + +要链接到视频,请添加 YouTube 图标,以便读者在阅读之前可以快速轻松地扫描页面上的视频: + +``` +<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> +For an overview, see [Video Title](link-to-video). +``` + +您可以链接任何对 GitLab 用户有用的最新视频. + +### Embed videos[](#embed-videos "Permalink") + +在 GitLab 12.1 中[引入](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/472) . + +[GitLab Docs 网站](https://s0docs0gitlab0com.icopy.site)支持嵌入式视频. + +您只能嵌入来自[GitLab 的官方 YouTube 帐户的视频](https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg) . 对于其他来源的视频,请[链接](#link-to-video)它们. + +在大多数情况下,最好[链接到视频](#link-to-video) ,因为嵌入会占用页面上的大量空间,并且可能分散读者的注意力. + +要嵌入视频,请按照以下说明进行操作,并确保您的 MR 已得到技术作家的审查和批准. + +1. 复制下面的代码,并将其粘贴到 Markdown 文件中. 在其上方和下方保留空白行. 请勿编辑代码(请勿删除或添加任何空格). +2. 在 YouTube 上,访问要显示的视频 URL. 从您的浏览器复制常规 URL( `https://www.youtube.com/watch?v=VIDEO-ID` ),然后替换视频标题和`<div class="video-fallback">`行中的链接. +3. 在 YouTube 上,点击**共享** ,然后点击**嵌入** . +4. 仅复制`<iframe>`源( `src` ) **URL** ( `https://www.youtube.com/embed/VIDEO-ID` ),然后粘贴它,替换`iframe`标记中`src`字段的内容. + +``` +leave a blank line here +<div class="video-fallback"> + See the video: <a href="https://www.youtube.com/watch?v=MqL6BMOySIQ">Video title</a>. +</div> +<figure class="video-container"> + <iframe src="https://www.youtube.com/embed/MqL6BMOySIQ" frameborder="0" allowfullscreen="true"> </iframe> +</figure> +leave a blank line here +``` + +它是如何在 GitLab Docs 网站上呈现的: + +观看视频: [什么是 GitLab](https://www.youtube.com/watch?v=enMumwvLAug) . + +<figure class="video-container"><iframe src="https://www.youtube.com/embed/MqL6BMOySIQ" frameborder="0" allowfullscreen=""></iframe></figure> + +> Notes: +> +> * `figure`标记是语义 SEO 所必需的,而`video_container`类是必需的,以确保视频能够响应并在不同的移动设备上很好地显示. +> * `<div class="video-fallback">`是 GitLab 的`/help`必需的后备,因为 GitLab 的 Markdown 处理器不支持 iframe. 它隐藏在 docs 网站上,但将显示在 GitLab 的`/help` . + +## Code blocks[](#code-blocks "Permalink") + +* 始终将添加到句子的代码包装在内联代码块( ``` )中. 例如`.gitlab-ci.yml` , `git add .` , `CODEOWNERS`或`only: [master]` . 文件名,命令,条目以及任何涉及代码的内容都应添加到代码块中. 为了使用户更轻松,请始终为可复制和粘贴的内容添加完整的代码块,因为他们可以使用代码块上的按钮轻松进行操作. +* 在代码块的上方和下方添加一个空行. +* 提供 shell 命令及其输出时,请在 shell 命令前加上`$`前缀,并在命令和输出之间留空行. +* 提供无输出的命令时,请不要在 shell 命令前加上`$`前缀. +* 如果需要在代码块中包括三个反引号,则对代码块围栏使用四个反引号,而不是三个. +* 对于常规的受保护代码块,请始终使用与该语言对应的突出显示类,以提高可读性. 例子: + + ``` + ```ruby Ruby code + ``` + + ```javascript JavaScript code + ``` + + ```markdown [Markdown code example](example.md) + ``` + + ```plaintext Code or text for which no specific highlighting class is available. + ``` + ``` + +加到 GitLab 文档中的受防护代码块要求突出显示语法. 有关最常用的语言类别,请参考下表,或查看可用语言类别的[完整列表](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers) . + +| 首选语言标签 | 语言别名和注释 | +| --- | --- | +| `asciidoc` |   | +| `dockerfile` | Alias: `docker`. | +| `elixir` |   | +| `erb` |   | +| `golang` | Alias: `go`. | +| `graphql` |   | +| `haml` |   | +| `html` |   | +| `ini` | 对于一些非 TOML 格式的简单配置文件. | +| `javascript` | Alias `js`. | +| `json` |   | +| `markdown` | Alias: `md`. | +| `mermaid` |   | +| `nginx` |   | +| `perl` |   | +| `php` |   | +| `plaintext` | 没有定义语言的示例,例如 shell 命令或 API 调用的输出. 如果代码块没有语言,则默认为`plaintext` . 别名: `text` . | +| `prometheus` | Prometheus 配置示例. | +| `python` |   | +| `ruby` | Alias: `rb`. | +| `shell` | Aliases: `bash` or `sh`. | +| `sql` |   | +| `toml` | Runner 配置示例以及其他 TOML 格式的配置文件. | +| `typescript` | Alias: `ts`. | +| `xml` |   | +| `yaml` | Alias: `yml`. | + +有关代码块的完整参考,请参阅《 [Kramdown 指南》](https://about.gitlab.com/handbook/markdown-guide/#code-blocks) . + +## GitLab SVG icons[](#gitlab-svg-icons "Permalink") + +在 GitLab 12.7 中[引入](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/384) . + +您可以直接在文档中使用来自[GitLab SVG 库的](https://gitlab-org.gitlab.io/gitlab-svgs/)图标. + +This way, you can achieve a consistent look when writing about interacting with GitLab UI elements. + +用法示例: + +* 默认尺寸(16 像素)的`**{icon-name}**` : `**{icon-name}**` + + 示例: `**{tanuki}**`呈现为: . + +* 具有自定义尺寸的`**{icon-name, size}**` : `**{icon-name, size}**` + + 可用尺寸(以像素为单位):8、10、12、14、16、18、24、32、48 和 72 + + 示例: `**{tanuki, 24}**`呈现为: . + +* 具有自定义尺寸和类别的`**{icon-name, size, class-name}**` : `**{icon-name, size, class-name}**` . + + 您可以在 GitLab 文档 CSS 中访问此元素可用的任何类. + + 带有`float-right`示例, [Bootstrap 实用程序类](https://s0getbootstrap0com.icopy.site/docs/4.4/utilities/float/) : `**{tanuki, 32, float-right}**`呈现为: + +### Use GitLab SVGs to describe UI elements[](#use-gitlab-svgs-to-describe-ui-elements "Permalink") + +使用 GitLab SVG 描述屏幕元素时,还应包括该元素的名称或工具提示作为文本. + +例如,对于"管理区"的引用: + +* Correct: `**{admin}** **Admin Area > Settings**` ( **管理区域>设置**) +* Incorrect: `**{admin}** **> Settings**` ( **>设定**) + +这将确保源 Markdown 保持可读性,并应有助于辅助功能. + +以下是菜单项的源 Markdown 示例及其发布的输出: + +``` +1. Go to **{home}** **Project overview > Details** +1. Go to **{doc-text}** **Repository > Branches** +1. Go to **{issues}** **Issues > List** +1. Go to **{merge-request}** **Merge Requests** +1. Go to **{rocket}** **CI/CD > Pipelines** +1. Go to **{shield}** **Security & Compliance > Configuration** +1. Go to **{cloud-gear}** **Operations > Metrics** +1. Go to **{package}** **Packages > Container Registry** +1. Go to **{chart}** **Project Analytics > Code Review** +1. Go to **{book}** **Wiki** +1. Go to **{snippet}** **Snippets** +1. Go to **{users}** **Members** +1. Select the **More actions** **{ellipsis_v}** icon > **Hide stage** +``` + +1. 去 **项目概述>详细信息** +2. Go to **资料库>分支机构** +3. 去 **问题>清单** +4. 去 **合并请求** +5. 去 **CI / CD>管道** +6. 去 **安全与合规>配置** +7. 去 **操作>指标** +8. 去 **包>容器注册表** +9. 去 **项目分析>代码审查** +10. 去 **维基** +11. 去 **片段** +12. 去 **会员** +13. 选择**更多操作** 图标> **隐藏舞台** + +## Alert boxes[](#alert-boxes "Permalink") + +每当您需要特别注意特定句子时,请使用以下标记突出显示. + +请注意,警报框仅适用于一个段落. 多个段落,列表,标题等将无法正确呈现. 对于多行,请改用[blockquotes](#blockquotes) . + +警报框仅在 GitLab Docs 网站( [https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site) )上呈现. 在 GitLab 本身中,它们将显示为纯 Markdown 文本(如下面呈现的版本上方的示例). + +### Note[](#note "Permalink") + +注释引起了大多数读者的注意,因此应谨慎使用. 在大多数情况下,应考虑为便笺考虑的内容: + +* 仅作为上一段或最相关段落中的另一句话. +* 作为其自己的独立段落. +* 作为介绍该主题的新子标题下的内容,使它更明显/更容易找到. + +#### When to use[](#when-to-use "Permalink") + +当出于某种原因,大多数或所有浏览本节的读者都应看到内容时,请使用注释. 就是说,如果错过了它,可能会给少数用户造成重大麻烦,或者对大多数用户造成重大麻烦. + +权衡分散内容无关用户的成本与丢失内容(如果未表示为注释)的用户成本. + +``` +NOTE: **Note:** +This is something to note. +``` + +它如何在 GitLab Docs 网站上呈现: + +**注意:**这是要注意的事情. + +### Tip[](#tip "Permalink") + +``` +TIP: **Tip:** +This is a tip. +``` + +它如何在 GitLab Docs 网站上呈现: + +**提示:**这是一个提示. + +### Caution[](#caution "Permalink") + +``` +CAUTION: **Caution:** +This is something to be cautious about. +``` + +它如何在 GitLab Docs 网站上呈现: + +**注意:**这是要谨慎的事情. + +### Danger[](#danger "Permalink") + +``` +DANGER: **Danger:** +This is a breaking change, a bug, or something very important to note. +``` + +它如何在 GitLab Docs 网站上呈现: + +**危险:**这是一个重大更改,错误或要注意的重要事项. + +## Blockquotes[](#blockquotes "Permalink") + +要突出显示蓝色方框引号内的文本,请使用以下格式: + +``` +> This is a blockquote. +``` + +在[GitLab 文档网站上显示](https://s0docs0gitlab0com.icopy.site)为: + +> 这是一个大引用. + +如果文本跨多行,则可以拆分行. + +对于多个段落,请在每行之前使用符号`>` : + +``` +> This is the first paragraph. +> +> This is the second paragraph. +> +> - This is a list item +> - Second item in the list +``` + +导致: + +> 这是第一段. +> +> 这是第二段. +> +> * 这是一个清单项目 +> * 列表中的第二项 + +## Terms[](#terms "Permalink") + +为了通过 GitLab 文档保持一致性,以下内容将指导文档作者了解一致的样式和术语的用法. + +### Merge Requests (MRs)[](#merge-requests-mrs "Permalink") + +合并请求使您可以交换对源代码所做的更改,并与同一项目中的其他人进行协作. 您将看到此术语以下列方式使用: + +* 如果您要使用此功能,请使用**合并请求** . +* 在任何其他上下文中,请使用**merge request** . + +如我们公司的《 [写作风格指南》所述](https://about.gitlab.com/handbook/communication/#writing-style-guidelines) ,如果您使用**MR**首字母缩写词,请在每个文档页面上至少展开一次. 例如,第一次指定 MR 时,请指定*Merge Request(MR)*或*merge request(MR)* . + +Examples: + +* "我们更喜欢 GitLab 合并请求". +* "打开合并请求以修复断开的链接". +* "打开合并请求(MR)后,将您的 MR 提交以供审核和批准". + +### Describe UI elements[](#describe-ui-elements "Permalink") + +以下是在屏幕上描述 UI 元素时要遵循的样式: + +* 对于带有可见标签的元素,请使用带有匹配大小写的粗体标签. 例如, `the **Cancel** button` . +* 对于带有工具提示或悬停标签的元素,请使用带有匹配大小写的粗体标签. 例如, `the **Add status emoji** button` . + +### Verbs for UI elements[](#verbs-for-ui-elements "Permalink") + +以下是建议用于 UI 元素的特定动词: + +| Recommended | 用于 | Replaces | +| --- | --- | --- | +| *click* | 按钮,链接,菜单项 | "点击","按","选择" | +| *select* or *clear* | checkboxes | "启用","单击","按" | +| *select* | dropdowns | “pick” | +| *expand* | expandable sections | “open” | + +### Other Verbs[](#other-verbs "Permalink") + +| Recommended | 用于 | Replaces | +| --- | --- | --- | +| *去* | 使浏览器定位 | "导航至","打开" | + +## GitLab versions and tiers[](#gitlab-versions-and-tiers "Permalink") + +标记和发布版本的 GitLab 文档可用: + +* 在[文档档案中](https://docs.gitlab.com/archives/) . +* 在任何 GitLab 安装的`/help` URL 中. + +引入新功能的版本已添加到文档主题的顶部,以提供有关该功能开发方式的有用链接. + +### Text for documentation requiring version text[](#text-for-documentation-requiring-version-text "Permalink") + +* For features that need to declare the GitLab version that the feature was introduced. Text similar to the following should be added immediately below the heading as a blockquote: + * `> Introduced in GitLab 11.3.`. +* 只要有可能,版本文本都应具有指向已*完成的*发行,合并请求或引入了该功能的史诗的链接. 问题优先于合并请求,而合并请求优先于史诗. 例如: + * `> [Introduced](<link-to-issue>) in GitLab 11.3.` . +* 如果该功能仅在 GitLab 企业版中可用,请提及该功能在以下位置的[付费层](https://about.gitlab.com/handbook/marketing/product-marketing/#tiers) : + * `> [Introduced](<link-to-issue>) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.3.` . +* 如果随着功能的发展列出了多个版本的信息,请将该信息添加到带引号的项目符号列表中. 例如: + + ``` + > - [Introduced](<link-to-issue>) in GitLab 11.3. + > - Enabled by default in GitLab 11.4. + ``` + +* 如果功能已移至另一层: + + ``` + > - [Introduced](<link-to-issue>) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.5. + > - [Moved](<link-to-issue>) to [GitLab Starter](https://about.gitlab.com/pricing/) in 11.8. + > - [Moved](<link-to-issue>) to GitLab Core in 12.0. + ``` + +* 如果不推荐使用某个功能,请提供替换链接(如果有): + + ``` + > - [Deprecated](<link-to-issue>) in GitLab 11.3\. Replaced by [meaningful text](<link-to-appropriate-documentation>). + ``` + + 如果可以的话,也可以在周围的文字中描述替换内容. + + 如果现有文本中的弃用不明显,则可能需要添加警告,例如: + + ``` + CAUTION: **Warning:** + This feature was [deprecated](link-to-issue) in GitLab 12.3 + and replaced by [Feature name](link-to-feature-documentation). + ``` + +**注意:**版本文本必须在其单独的行上并由空白行包围才能正确呈现. + +### Versions in the past or future[](#versions-in-the-past-or-future "Permalink") + +描述过去或将来版本中可用的功能时,请使用: + +* **较早的** ,不**早** **于之前的** . +* **后来** ,并没有**新的**或**之后** . + +例如: + +* 在 GitLab 12.3 和更早版本中可用. +* 在 GitLab 12.4 和更高版本中可用. +* 如果使用 GitLab 11.4 或更早版本,… +* 如果使用 GitLab 10.6 或更高版本,… + +### Importance of referencing GitLab versions and tiers[](#importance-of-referencing-gitlab-versions-and-tiers "Permalink") + +提及 GitLab 版本和层对所有用户和贡献者来说很重要,以便他们能够快速访问引入变更的发行或合并请求以供参考. 此外,鉴于该注释包含一些关键信息,他们可以轻松了解其 GitLab 实例和版本中具有哪些功能. + +`[Introduced](link-to-issue) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7`链接到引入该功能的问题,说它属于哪个 GitLab 层,GitLab 说该版本可用的版本,并链接到定价页面,以防用户想要升级到付费层以使用该功能. + +例如,如果您是普通用户,并且正在查看以前从未使用过的功能的文档,则可以立即查看该功能是否可用. 另外,如果您长期使用某项功能并且以某种方式进行了更改,那么重要的是要能够发现更改的时间以及该功能的新增功能. + +这一点更为重要,因为我们没有一个完美的文档发布流程. 不幸的是,我们仍然看到没有文档的功能和没有功能的文档. 因此,就目前而言,我们不能 100%依赖 docs 网站版本. + +随着时间的推移,版本文本将引用 GitLab 的逐渐老版本. 如果版本文本引用了 GitLab 的四个或更多个主要版本,您可以考虑删除不相关或令人困惑的文本. + +例如,如果当前的主要版本是 12.x,则在需要更清晰或更干净的文档时,需要引用引用 GitLab 8.x 和更早版本的版本文本. + +## Products and features[](#products-and-features "Permalink") + +在 GitLab 产品文档中描述产品和功能时,请参考本节中的信息. + +### Avoid line breaks in names[](#avoid-line-breaks-in-names "Permalink") + +输入包含空格(例如 GitLab 社区版)或什至其他公司产品(例如 Amazon Web Services)的产品或功能名称时,请确保不要在插入了换行符的行之间拆分产品或功能名称. 跨行拆分产品或功能名称会使搜索这些项目更加困难,并且如果名称更改则可能导致问题. + +例如,以下 Markdown 内容的格式*不*正确: + +``` +When entering a product or feature name that includes a space (such as GitLab +Community Edition), don't split the product or feature name across lines. +``` + +而是,它应类似于以下内容: + +``` +When entering a product or feature name that includes a space (such as +GitLab Community Edition), don't split the product or feature name across lines. +``` + +### Product badges[](#product-badges "Permalink") + +当仅 EE 层中有功能可用时,请根据功能可用性添加相应的层: + +* 对于 GitLab Core 和 GitLab.com 免费: `**(CORE)**` . +* 对于 GitLab Starter 和 GitLab.com 铜牌: `**(STARTER)**` . +* 对于 GitLab Premium 和 GitLab.com 银牌: `**(PREMIUM)**` . +* 对于 GitLab Ultimate 和 GitLab.com Gold: `**(ULTIMATE)**` . + +要排除 GitLab.com 层(当该功能在 GitLab.com 中不可用时),请添加关键字" only": + +* 对于 GitLab Core: `**(CORE ONLY)**` . +* 对于 GitLab Starter: `**(STARTER ONLY)**`适用于`**(STARTER ONLY)**` . +* 对于 GitLab Premium: `**(PREMIUM ONLY)**` . +* 对于 GitLab Ultimate: `**(ULTIMATE ONLY)**` . + +对于 GitLab.com 仅适用于层(当该功能不适用于自我管理实例时): + +* 对于 GitLab 免费和更高级别: `**(FREE ONLY)**` . +* 对于 GitLab 青铜级和更高级别: `**(BRONZE ONLY)**`铜级`**(BRONZE ONLY)**` . +* 对于 GitLab Silver 和更高级别: `**(SILVER ONLY)**` . +* 对于 GitLab Gold: `**(GOLD ONLY)**` . + +理想情况下,应将该层添加到标题中,以便显示完整的徽标. 但是,也可以从段落,列表项和表格单元格中提及. 对于这些情况,层级提及将由橙色的信息图标**(信息)**表示,该图标将显示悬停时的层级. + +即使页面上存在较高级别的层,也应使用页面级别的最低层. 例如,您可能有一个页面标记为 Starter,而一个部分标记为 Premium. + +例如: + +* `**(STARTER)**`呈现为 +* `**(STARTER ONLY)**`呈现为 +* `**(SILVER ONLY)**`呈现为 + +没有提及层意味着该功能可在 GitLab Core,GitLab.com Free 和所有更高层使用. + +#### How it works[](#how-it-works "Permalink") + +由[!244](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/244)引入的特殊标记`**(STARTER)**`将生成一个`span`元素,以触发徽章和工具提示( `<span class="badge-trigger starter">` ). 添加关键字" only"时,将不会显示相应的 GitLab.com 徽章. + +## Specific sections[](#specific-sections "Permalink") + +某些样式应应用于特定部分. 下面概述了特定部分的样式. + +### GitLab restart[](#gitlab-restart "Permalink") + +在许多情况下,需要重新启动/重新配置 GitLab. 为避免重复,请链接到可以在[`doc/administration/restart_gitlab.md`](../../administration/restart_gitlab.html)找到的特殊文档. 通常,文本显示如下: + +``` +Save the file and [reconfigure GitLab](../../administration/restart_gitlab.md) +for the changes to take effect. +``` + +如果您正在编辑的文档位于 GitLab CE / EE `doc/`目录之外的其他位置,请使用完整路径,而不是相对链接: `https://docs.gitlab.com/ce/administration/restart_gitlab.html` : `https://docs.gitlab.com/ce/administration/restart_gitlab.html` . 在适当的地方,将`reconfigure`替换为`reconfigure` `restart` . + +### Installation guide[](#installation-guide "Permalink") + +**Ruby:**在[安装指南的第 2 步中](../../install/installation.html#2-ruby) ,我们从源代码安装 Ruby. 每当有新版本需要更新时,请记住在整个代码块中进行更改,并替换 sha256sum(可在 Ruby 网站的[下载页面](https://www.ruby-lang.org/en/downloads/)中找到). + +### Configuration documentation for source and Omnibus installations[](#configuration-documentation-for-source-and-omnibus-installations "Permalink") + +GitLab currently officially supports two installation methods: installations from source and Omnibus packages installations. + +只要有两种安装方法都可以配置的设置,就最好在 CE 文档中进行记录以避免重复. + +配置设置包括: + +1. 触及`config/`配置文件的设置. +2. NGINX 设置和`lib/support/`中的设置通常. + +如果有要执行的步骤列表,通常需要编辑配置文件并重新配置/重新启动 GitLab. 在这种情况下,请按照以下样式作为指导: + +``` +**For Omnibus installations** + 1. Edit `/etc/gitlab/gitlab.rb`: + + ```ruby + external_url "https://gitlab.example.com" + ``` + 1. Save the file and [reconfigure](path/to/administration/restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab for the changes to take effect. + --- +**For installations from source** + 1. Edit `config/gitlab.yml`: + + ```yaml + gitlab: + host: "gitlab.example.com" + ``` + 1. Save the file and [restart](path/to/administration/restart_gitlab.md#installations-from-source) GitLab for the changes to take effect. +``` + +在这种情况下: + +* 在每个步骤列表之前,安装方法以粗体声明. +* 三个破折号( `---` )用于创建水平线并将两种方法分开. +* 代码块在列表项下缩进一个或多个空格以正确呈现. +* 代码块中的每个配置使用不同的突出显示语言. +* [GitLab 重新启动](#gitlab-restart)部分用于说明 GitLab 所需的重新启动/重新配置. + +### Troubleshooting[](#troubleshooting "Permalink") + +对于疑难解答部分,您应该提供尽可能多的上下文,以便用户可以识别自己面临的问题并自行解决. 您可以通过确保故障排除内容解决以下问题来简化此操作: + +1. 用户需要解决的问题. +2. 用户如何确认他们有问题. +3. 用户可以采取的解决问题的步骤. + +如果可以将所有类别的内容汇总在一行中,并且不需要步骤列表,请考虑设置一个带有" *问题* |标题"的[表](#tables) . *原因* *解决方案* (或*解决方法(*如果此修复程序是临时的))或*错误消息* | *解决方法* . + +## Feature flags[](#feature-flags "Permalink") + +了解如何[记录标记后部署的功能](feature_flags.html) . 有关使用功能标记开发 GitLab 的指导,请参阅[GitLab 开发中的功能标记](../feature_flags/index.html) . + +## API[](#api "Permalink") + +这是必备物品清单. 按照本文档中出现的确切顺序使用它们. 下面给出进一步的解释. + +* Every method must have the REST API request. For example: + + ``` + GET /projects/:id/repository/branches + ``` + +* 每个方法都必须[对参数](#method-description)进行详细[说明](#method-description) . +* 每个方法都必须有一个 cURL 示例. +* 每个方法都必须具有响应主体(JSON 格式). + +### API topic template[](#api-topic-template "Permalink") + +以下内容可以用作入门模板: + +``` +## Descriptive title + +One or two sentence description of what endpoint does. + +```plaintext METHOD /endpoint +``` + +| Attribute | Type | Required | Description | +|:------------|:---------|:---------|:----------------------| +| `attribute` | datatype | yes/no | Detailed description. | +| `attribute` | datatype | yes/no | Detailed description. | + +Example request: + +```shell curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/endpoint?parameters' +``` + +Example response: + +```json [ { } ] +``` +``` + +### Fake user information[](#fake-user-information "Permalink") + +您可能需要演示包含用户名和电子邮件地址的 API 调用或 cURL 命令. 不要在 API 调用中使用真实的用户信息: + +* **电子邮件地址** :使用以`example.com`结尾的电子邮件地址. +* **名称** :使用`Example Username` **名之类的**字符串. 或者,使用具有常用姓氏的各种或非性别名称,例如`Sidney Jones` , `Zhang Wei` . 或`Maria Garcia` . + +### Fake URLs[](#fake-urls "Permalink") + +在文档中包含示例 URL 时,请使用: + +* 域名通用时为`example.com` . +* `gitlab.example.com`指 GitLab 的自我管理的实例时. + +### Fake tokens[](#fake-tokens "Permalink") + +有时可能需要令牌来证明使用 cURL 或 CI 中使用的变量进行 API 调用. 强烈建议不要在文档中使用真实令牌,即使令牌被利用的可能性很低. + +您可以使用以下伪造的令牌作为示例. + +| 代币类型 | 代币价值 | +| --- | --- | +| 私人用户令牌 | `<your_access_token>` | +| 个人访问令牌 | `n671WNGecHugsdEDPsyo` | +| 申请编号 | `2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6` | +| 应用机密 | `04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df` | +| 可变 CI / CD | `Li8j-mLUVA3eZYjPfd_H` | +| 特定跑步者令牌 | `yrnZW46BrtBFqM7xDzE7dddd` | +| 共享亚军令牌 | `6Vk7ZsosqQyfreAxXTZr` | +| 触发令牌 | `be20d8dcc028677c931e04f3871a9b` | +| Webhook 秘密令牌 | `6XhDroRcYPM5by_h-HLY` | +| 健康检查令牌 | `Tu7BgjR9qeZTEyRzGG2P` | +| 请求个人资料令牌 | `7VgpS4Ax5utVD2esNstz` | + +### Method description[](#method-description "Permalink") + +使用下表标题来描述方法. 属性应始终位于使用反引号( ``` )的代码块中. + +``` +| Attribute | Type | Required | Description | +|:----------|:-----|:---------|:------------| +``` + +渲染示例: + +| Attribute | Type | Required | Description | +| --- | --- | --- | --- | +| `user` | string | yes | GitLab 用户名 | + +### cURL commands[](#curl-commands "Permalink") + +* 使用`https://gitlab.example.com/api/v4/`作为端点. +* 在需要的地方使用此个人访问令牌: `<your_access_token>` . +* 始终将请求放在第一位. `GET`是默认设置,因此您不必包含它. +* 将该网址用双引号( `"` )引起来. +* 最好使用使用个人访问令牌的示例,并且不要传递用户名和密码的数据. + +| Methods | Description | +| --- | --- | +| `--header "PRIVATE-TOKEN: <your_access_token>"` | 每当需要身份验证时,请按原样使用此方法 | +| `--request POST` | 创建新对象时使用此方法 | +| `--request PUT` | 更新现有对象时使用此方法 | +| `--request DELETE` | 删除现有对象时使用此方法 | + +### cURL Examples[](#curl-examples "Permalink") + +以下是一组可以在 API 文档中使用的[cURL](https://curl.haxx.se)示例. + +#### Simple cURL command[](#simple-curl-command "Permalink") + +获取组的详细信息: + +``` +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/gitlab-org +``` + +#### cURL example with parameters passed in the URL[](#curl-example-with-parameters-passed-in-the-url "Permalink") + +在经过身份验证的用户的名称空间下创建一个新项目: + +``` +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects?name=foo" +``` + +#### Post data using cURL’s `--data`[](#post-data-using-curls---data "Permalink") + +您可以使用 cURL 的`--data`选项,而不是使用`--request POST`并将参数附加到 URI. 下面的示例将在经过身份验证的用户的名称空间下创建一个新项目`foo` . + +``` +curl --data "name=foo" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects" +``` + +#### Post data using JSON content[](#post-data-using-json-content "Permalink") + +> **注意:**在此示例中,我们创建一个新组. 仔细观察单引号和双引号. + +``` +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"path": "my-group", "name": "My group"}' https://gitlab.example.com/api/v4/groups +``` + +#### Post data using form-data[](#post-data-using-form-data "Permalink") + +除了使用 JSON 或 urlencode 外,您还可以使用 multipart / form-data 来正确处理数据编码: + +``` +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "title=ssh-key" --form "key=ssh-rsa AAAAB3NzaC1yc2EA..." https://gitlab.example.com/api/v4/users/25/keys +``` + +上面的示例由管理员运行,并将向用户帐户添加名为`ssh-key`的 SSH 公共密钥,其 ID 为 25. + +#### Escape special characters[](#escape-special-characters "Permalink") + +空格或斜杠( `/` )有时可能会导致错误,因此建议在可能的情况下转义它们. 在下面的示例中,我们创建了一个新问题,该问题的标题中包含空格. 观察如何使用 ASCII 代码对空格进行转义. + +``` +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/42/issues?title=Hello%20Dude" +``` + +将`/`用作斜杠( `/` ). + +#### Pass arrays to API calls[](#pass-arrays-to-api-calls "Permalink") + +GitLab API 有时会接受字符串或整数数组. 例如,要在请求项目用户列表时排除特定用户,您可以执行以下操作: + +``` +curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "skip_users[]=<user_id>" --data "skip_users[]=<user_id>" https://gitlab.example.com/api/v4/projects/<project_id>/users +``` \ No newline at end of file diff --git a/docs/570.md b/docs/570.md new file mode 100644 index 0000000000000000000000000000000000000000..66b58280a75b5c5bc9b609765b93872083297ab2 --- /dev/null +++ b/docs/570.md @@ -0,0 +1,147 @@ +# Documentation structure and template + +> 原文:[https://docs.gitlab.com/ee/development/documentation/structure.html](https://docs.gitlab.com/ee/development/documentation/structure.html) + +* [Components of a documentation page](#components-of-a-documentation-page) +* [Template for new docs](#template-for-new-docs) +* [Help and feedback section](#help-and-feedback-section) + * [Disqus](#disqus) + +# Documentation structure and template[](#documentation-structure-and-template "Permalink") + +本文档将帮助您确定如何在 GitLab 文档中构建页面以及包含哪些内容. 这些标准有助于确保整个文档的一致性和完整性,并使它们的贡献更加容易. + +在开始之前,请熟悉[GitLab 的文档指南](index.html)和[样式指南中](styleguide.html)有关内容的部分. + +## Components of a documentation page[](#components-of-a-documentation-page "Permalink") + +大多数页面将专用于 GitLab 的特定功能或涉及一个或多个功能的用例(可能与第三方工具结合使用). + +每个功能部件或用例文档应按以下顺序包括以下内容,以下内容和此页面中包含的模板中注明了例外和详细信息. + +* **标题** :具有功能名称或用例名称的顶级标题,该名称应以动词开头,例如" Configure"," Enable"等. +* **简介** :关于此主题以及在此页面上可以找到的内容的简短句子. 描述功能或主题是什么,它做什么,以及在什么情况下应使用它. 无需添加称为"简介"或"概述"的标题,因为人们很少搜索这些术语. 只需将这些信息放在标题之后即可. +* **用例** :描述该功能/配置的实际用例场景. +* **要求** :描述所需的软件,配置,帐户或知识. +* **说明** :遵循一套或多套详细说明. +* **故障排除**指南(推荐但不是必需的). + +有关每个[文档的](#template-for-new-docs)更多详细信息,请参见下面的[新文档模板](#template-for-new-docs) . + +请注意,您可以酌情包括其他小节,例如"工作原理","体系结构"以及其他逻辑划分,例如部署前和部署后步骤. + +## Template for new docs[](#template-for-new-docs "Permalink") + +要开始新文档,请遵守文件树和文件名准则以及样式准则. 使用以下模板: + +``` +<!--Follow the Style Guide when working on this document. https://docs.gitlab.com/ee/development/documentation/styleguide.html +When done, remove all of this commented-out text, except a commented-out Troubleshooting section, +which, if empty, can be left in place to encourage future use.--> +--- description: "Short document description." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here. +stage: "Add the stage name here, and remove the quotation marks" +group: "Add the group name here, and remove the quotation marks" +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- +# Feature Name or Use Case Name **[TIER]** (1) +<!--If writing about a use case, drop the tier, and start with a verb, e.g. "Configure", "Implement", + the goal/scenario--> + +<!--For pages on newly introduced features, add the following line. If only some aspects of the feature have been introduced, specify what parts of the feature.--> +> [Introduced](link_to_issue_or_mr) in GitLab (Tier) X.Y (2). + +An introduction -- without its own additional header -- goes here. +Offer a description of the feature or use case, and what to expect on this page. +(You can reuse this content, or part of it, for the front matter's `description` at the top of this file). + +The introduction should answer the following questions: + - What is this feature or use case? +- Who is it for? +- What is the context in which it is used and are there any prerequisites/requirements? +- What can the audience do with this? (Be sure to consider all applicable audiences, like GitLab admin and developer-user.) +- What are the benefits to using this over any alternatives? + +## Use cases + +Describe some use cases, typically in bulleted form. Include real-life examples for each. + +If the page itself is dedicated to a use case, this section can usually include more specific scenarios +for use (e.g. variations on the main use case), but if that's not applicable, the section can be omitted. + +Examples of use cases on feature pages: +- CE and EE: [Issues](../../user/project/issues/index.md#use-cases) +- CE and EE: [Merge Requests](../../user/project/merge_requests/index.md) +- EE-only: [Geo](../../administration/geo/replication/index.md) +- EE-only: [Jenkins integration](../../integration/jenkins.md) + +## Requirements + +State any requirements for using the feature and/or following along with the instructions. + +These can include both: +- technical requirements (e.g. an account on a third party service, an amount of storage space, prior configuration of another feature) +- prerequisite knowledge (e.g. familiarity with certain GitLab features, cloud technologies) + +Link each one to an appropriate place for more information. + +## Instructions + +"Instructions" is usually not the name of the heading. +This is the part of the document where you can include one or more sets of instructions, each to accomplish a specific task. +Headers should describe the task the reader will achieve by following the instructions within, typically starting with a verb. +Larger instruction sets may have subsections covering specific phases of the process. +Where appropriate, provide examples of code or configuration files to better clarify intended usage. + - Write a step-by-step guide, with no gaps between the steps. +- Include example code or configurations as part of the relevant step. Use appropriate Markdown to [wrap code blocks with syntax highlighting](../../user/markdown.md#colored-code-and-syntax-highlighting). +- Start with an h2 (`##`), break complex steps into small steps using +subheadings h3 > h4 > h5 > h6\. _Never skip a hierarchy level, such +as h2 > h4_, as it will break the TOC and may affect the breadcrumbs. +- Use short and descriptive headings (up to ~50 chars). You can use one +single heading like `## Configure X` for instructions when the feature +is simple and the document is short. + +<!-- ## Troubleshooting + +Include any troubleshooting steps that you can foresee. If you know beforehand what issues +one might have when setting this up, or when something is changed, or on upgrading, it's +important to describe those, too. Think of things that may go wrong and include them here. +This is important to minimize requests for support, and to avoid doc comments with +questions that you know someone might ask. + +Each scenario can be a third-level heading, e.g. `### Getting error message X`. +If you have none to add when creating a doc, leave this section in place +but commented out to help encourage others to add to it in the future. --> + --- +Notes: + - (1): Apply the [tier badges](styleguide.md#product-badges) accordingly +- (2): Apply the correct format for the [GitLab version introducing the feature](styleguide.md#gitlab-versions-and-tiers) +``` + +## Help and feedback section[](#help-and-feedback-section "Permalink") + +通过在文档的开头添加一个键,可以从文档中省略每个文档末尾显示的"帮助和反馈"部分(由[!319](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/319)引入): + +``` +--- +feedback: false +--- +``` + +默认为将其保留在此处. 如果要从文档中忽略它,则必须先咨询技术作家. + +### Disqus[](#disqus "Permalink") + +我们还将 docs 站点与 Disqus 集成在一起(由[!151](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/151)引入),使我们的用户可以发表评论. + +要仅忽略反馈部分中的评论,请在最前面使用以下键: + +``` +--- +comments: false +--- +``` + +We are only hiding comments in main index pages, such as [the main documentation index](../../README.html), since its content is too broad to comment on. Before omitting Disqus, you must check with a technical writer. + +请注意,一旦在前件中添加了" `feedback: false` ,它将自动省略 Disqus,因此,请勿将两个关​​键字都添加到同一文档中. + +Google 跟踪代码管理器会跟踪"反馈"部分中的点击事件. 通过导航至" **行为">"事件">"热门事件">" docs",**可以在 Google Analytics(分析)上查看转化. \ No newline at end of file diff --git a/docs/571.md b/docs/571.md new file mode 100644 index 0000000000000000000000000000000000000000..80f7a5f916aca40aad327e39072cf717e89bfeda --- /dev/null +++ b/docs/571.md @@ -0,0 +1,135 @@ +# Documentation process + +> 原文:[https://docs.gitlab.com/ee/development/documentation/workflow.html](https://docs.gitlab.com/ee/development/documentation/workflow.html) + +* [Who updates the docs?](#who-updates-the-docs) +* [Documentation labels](#documentation-labels) +* [How to update the docs](#how-to-update-the-docs) + * [Reviewing and merging](#reviewing-and-merging) +* [Other ways to help](#other-ways-to-help) +* [Post-merge reviews](#post-merge-reviews) + * [Before merging](#before-merging) + +# Documentation process[](#documentation-process "Permalink") + +创建和维护 GitLab 产品文档的过程允许任何人提交合并请求或为 GitLab 文档创建问题. + +**注意:**与新功能或功能增强相关的文档更新必须使用 GitLab 手册[中](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#for-a-product-change)描述的[功能工作流程](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#for-a-product-change) . + +## Who updates the docs?[](#who-updates-the-docs "Permalink") + +*任何人都*可以贡献力量! 您可以在以下情况下创建文档合并请求: + +* 您发现现有文档中存在错误或其他需要改进的地方. +* 您对全新文档有一个想法,可以帮助 GitLab 用户或管理员完成其与 GitLab 的工作. + +## Documentation labels[](#documentation-labels "Permalink") + +无论发布或合并请求的类型如何,添加或更新文档时都需要某些标签. 发行或合并请求作者添加了以下内容: + +* 适当的[类型标签](../contributing/issue_workflow.html#type-labels) . +* [阶段标签](../contributing/issue_workflow.html#stage-labels)和[组标签](../contributing/issue_workflow.html#group-labels) . 例如, `~devops::create`和`~devops::create` `~group::source code` . +* The `~documentation` [specialization label](../contributing/issue_workflow.html#specialization-labels). + +技术写作团队的成员还添加了以下内容: + +* 具有`docs::`前缀的文档[范围标签](../../user/project/labels.html#scoped-labels-premium) . 例如, `~docs::improvement` . +* The `~Technical Writing` [team label](../contributing/issue_workflow.html#team-labels). + +与新功能或更新功能的发布无关的文档更改不带有`~feature`标签,但仍需要`~documentation`标签. + +它们可能包括: + +* 创建或更新文档以提高准确性,完整性,易用性或[功能更改](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#for-a-product-change)以外的任何其他原因. +* 解决现有文档中的空白,或对现有文档进行改进. +* 处理与文档相关的特殊项目. + +## How to update the docs[](#how-to-update-the-docs "Permalink") + +要更新 GitLab 文档: + +1. Either: + * 单击[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site)上任何页面底部的" **编辑此页面"**链接. + * 导航到[GitLab 文档指南](index.html)页面上列出的存储库和文档路径之一. +2. 请遵循页面上列出的描述的标准和过程,包括: + * [结构和模板](structure.html)页面. + * [样式指南](styleguide.html) . + * [降价指南](https://about.gitlab.com/handbook/markdown-guide/) . +3. 遵循 GitLab 的[合并请求准则](../contributing/merge_request_workflow.html#merge-request-guidelines) . + +**提示:**如果您没有开发人员对 GitLab 项目的访问权限,请分叉工作. + +如果您满足以下条件,请寻求技术写作团队的帮助: + +* 需要帮助选择正确的文档位置. +* 想讨论文档想法或大纲. +* 想要请求其他帮助. + +要寻求帮助: + +1. 找到相关[DevOps 阶段组](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)的技术作家. +2. Either: + * 如果需要紧急帮助,请直接在问题或合并请求中分配技术作家. + * 如果需要非紧急帮助,请在问题或合并请求中 ping 技术作家. + +如果您是 GitLab Slack 工作区的成员,则可以在`#docs`请求帮助. + +### Reviewing and merging[](#reviewing-and-merging "Permalink") + +拥有维护者访问相关 GitLab 项目权限的任何人都可以合并文档更改. 维护者必须认真努力,以确保内容: + +* 清晰易懂,易于目标受众浏览和理解. +* 符合[文档指南](index.html)和[样式指南](styleguide.html) . + +如果作者或审稿人有任何疑问,他们可以提及被分配到相关[DevOps 阶段小组的作者](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments) . + +该过程涉及以下内容: + +* 主要审稿人. 由[代码审阅者](https://about.gitlab.com/handbook/engineering/projects/)或其他适当的同事进行[审阅](https://about.gitlab.com/handbook/engineering/projects/) ,以确认准确性,清晰度和完整性. 对于较小的修订,可以跳过,而无需实质性的内容更改. +* 技术作家(可选). 如果在合并之前未完成合并请求,则必须在合并后安排. 仅在需要紧急合并时才安排合并后审核. 要请求: + * 合并前审查,为适用的[DevOps 阶段组](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)分配列出的技术作家. + * 合并后审核,请参阅[合并后审核](#post-merge-reviews) . +* 维护者. 对于合并请求,维护者: + * 随时可以要求上述任何评论. + * 在技​​术作家审查之前或之后进行审查. + * 确保已设置给定的发布里程碑. + * 确保应用了适当的标签,包括将合并请求选择到版本中所需的标签. + * 确保(如果尚未完成或计划进行技术作家审查) [创建所需的问题](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Doc Review) ,将其分配给给定阶段组的技术作家,并将其与合并请求链接. + +该过程反映在" **文档** [合并请求"模板中](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/merge_request_templates/Documentation.md) . + +## Other ways to help[](#other-ways-to-help "Permalink") + +如果您有更多文档资源的想法,请使用"文档"模板[创建问题](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Documentation) . + +## Post-merge reviews[](#post-merge-reviews "Permalink") + +如果在合并之前未分配给技术作家进行审核,则开发人员或维护人员必须在合并后立即安排审核. 为此,请使用" [文档审阅"描述模板](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Doc Review)创建一个问题,并从引入了文档更改的合并合并请求中链接到该问题. + +可能会跳过常规的合并前技术作家审查的情况包括: + +* 里程碑发布还有很短的时间. 如果还有不到三天的时间,请寻求合并后的审查,并通过 Slack 对作者进行 ping 操作,以确保审查尽快完成. +* The size of the change is small and you have a high degree of confidence that early users of the feature (for example, GitLab.com users) can easily use the documentation as written. + +Remember: + +* 在 GitLab,我们将文档视为代码. 与代码一样,必须检查文档以确保质量. +* 文档是 GitLab [对 done 的定义的](../contributing/merge_request_workflow.html#definition-of-done)一部分. +* 当代码在里程碑发布之前完成得很好并且需要更大的文档更改时,这种合并前的 Technical Writer 审核应该是最常见的. +* 如果重要的是尽快使它附带的代码合并,那么可以要求对文档进行合并后技术审查. 在这种情况下,原始 MR 的作者将在后续 MR 中阐述技术作家提供的反馈. +* 技术作家还可以帮助您确定无需技术作家审查就可以合并文档,而审查将在合并后立即进行. + +### Before merging[](#before-merging "Permalink") + +如果跳过初步的技术作家审查,请确保以下各项: + +* 该[产品徽章](styleguide.html#product-badges)已应用. +* 包含引入该功能的 GitLab [版本](styleguide.html#text-for-documentation-requiring-version-text)已包括在内. +* 标题的更改不会影响应用内超链接. +* 记录了特定的[用户权限](../../user/permissions.html) . +* 为了发现,这些新文档从更高级别的索引链接在一起. +* 遵循样式指南: + * 用于[目录和文件](styleguide.html#work-with-directories-and-files) . + * 对于[图像](styleguide.html#images) . + +**注意:**更改文档位置的合并请求必须在合并之前始终由技术作家审查. \ No newline at end of file diff --git a/docs/572.md b/docs/572.md new file mode 100644 index 0000000000000000000000000000000000000000..22ccf34e74059a938e4836b90f6162e90defc1d8 --- /dev/null +++ b/docs/572.md @@ -0,0 +1,171 @@ +# Documentation site architecture + +> 原文:[https://docs.gitlab.com/ee/development/documentation/site_architecture/](https://docs.gitlab.com/ee/development/documentation/site_architecture/) + +* [Architecture](#architecture) +* [Assets](#assets) + * [Libraries](#libraries) + * [SEO](#seo) +* [Global navigation](#global-navigation) +* [Pipelines](#pipelines) + * [Rebuild the docs site Docker images](#rebuild-the-docs-site-docker-images) + * [Deploy the docs site](#deploy-the-docs-site) +* [Using YAML data files](#using-yaml-data-files) +* [Bumping versions of CSS and JavaScript](#bumping-versions-of-css-and-javascript) +* [Linking to source files](#linking-to-source-files) +* [Algolia search engine](#algolia-search-engine) +* [Monthly release process (versions)](#monthly-release-process-versions) +* [Review Apps for documentation merge requests](#review-apps-for-documentation-merge-requests) + +# Documentation site architecture[](#documentation-site-architecture "Permalink") + +[`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs)项目托管用于生成 GitLab 文档网站的资源库,该资源库已部署到[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site) . 它使用[Nanoc](https://nanoc.ws/)静态站点生成器. + +## Architecture[](#architecture "Permalink") + +文档内容的源存储在 GitLab 的各个产品存储库中,而用于*从该内容*构建文档站点的源位于[https://gitlab.com/gitlab-org/gitlab-docs](https://gitlab.com/gitlab-org/gitlab-docs) . + +下图说明了从中获取内容的存储库, `gitlab-docs`项目和已发布的输出之间的关系. + +图 LR A [gitlab / doc] B [gitlab-runner / docs] C [omnibus-gitlab / doc] D [charts / doc] E [gitlab-docs] A-> EB-> EC-> ED- -> EE-建立管道-> FF [docs.gitlab.com] G [/ ce /] H [/ ee /] I [/ runner /] J [/ omnibus /] K [/ charts /] F- -> HF-> IF-> JF-> KH-symlink-> G + +您不会在`gitlab-docs`存储库中找到任何 GitLab 文档内容. 所有文档文件都托管在每种产品各自的存储库中,并且全部拉在一起以生成 docs 网站: + +* [GitLab](https://gitlab.com/gitlab-org/gitlab/tree/master/doc) +* [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc) +* [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/tree/master/docs) +* [GitLab Chart](https://gitlab.com/charts/gitlab/tree/master/doc) + +**注意:**在 2019 年 9 月,我们[转向了一个单一的代码库](https://gitlab.com/gitlab-org/gitlab/-/issues/2952) ,因此 CE 和 EE 的文档现在完全相同. 出于历史原因,并且为了不破坏整个 Internet 上的任何现有链接,我们仍然维护 CE 文档( `https://docs.gitlab.com/ce/` ),尽管它已从网站中隐藏,现在已成为符号链接到 EE 文档. 如果[Pages 支持重定向](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/24) ,我们将能够彻底删除它. + +## Assets[](#assets "Permalink") + +为了提供优化的网站结构,设计和搜索引擎友好的网站以及可发现的文档,我们在 GitLab 文档网站中使用了一些资产. + +### Libraries[](#libraries "Permalink") + +* [Bootstrap 4.3.1 components](https://s0getbootstrap0com.icopy.site/docs/4.3/components/) +* [Bootstrap 4.3.1 JS](https://s0getbootstrap0com.icopy.site/docs/4.3/getting-started/javascript/) +* [jQuery](https://jquery.com/) 3.3.1 +* [Clipboard JS](https://clipboardjs.com/) +* [Font Awesome 4.7.0](https://fontawesome.com/v4.7.0/icons/) + +### SEO[](#seo "Permalink") + +* [Schema.org](https://schema.org/) +* [Google Analytics](https://marketingplatform.google.com/about/analytics/) +* [Google Tag Manager](https://developers.google.com/tag-manager/) + +## Global navigation[](#global-navigation "Permalink") + +通读[全局导航文档](global_nav.html)以了解: + +* 全局导航的构建方式. +* 如何添加新的导航项. + +## Pipelines[](#pipelines "Permalink") + +`gitlab-docs`项目中的管道: + +* 测试对 docs 站点代码的更改. +* 构建用于各种管道作业的 Docker 映像. +* 构建和部署文档站点本身. +* 触发`review-docs-deploy`作业时生成审阅应用程序. + +### Rebuild the docs site Docker images[](#rebuild-the-docs-site-docker-images "Permalink") + +星期一每周一次,运行预定的管道并重建用于各种管道作业(例如`docs-lint`的 Docker 映像. Docker 映像配置文件位于[Dockerfiles 目录中](https://gitlab.com/gitlab-org/gitlab-docs/-/tree/master/dockerfiles) . + +如果您需要立即重建 Docker 映像(必须具有维护者级别权限): + +**注意:**如果更改 dockerfile 配置并重建映像,则可以在`gitlab`主存储库以及`gitlab-docs`中`gitlab-docs` . 首先创建一个具有不同名称的映像,然后对其进行测试,以确保您不会中断管道. + +1. 在[`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs) ,转到 **CI / CD>管道** . +2. 单击**运行管道**按钮. +3. 看到新的管道正在运行. 构建图像的工作在第一阶段,即`build-images` . 您可以单击管道编号以查看较大的管道​​图,或单击迷你管道图中的第一( `build-images` )阶段以公开构建图像的作业. +4. 点击**播放** ( )按钮旁边的要重建的图像. + * 通常,您不需要重建`image:gitlab-docs-base`映像,因为它很少更改. 如果确实需要重建,请确保仅在重建完成后才运行`image:docs-lint` . + +### Deploy the docs site[](#deploy-the-docs-site "Permalink") + +计划的管道每隔四个小时就会构建和部署一个文档站点. 管道从主项目的 master 分支中获取当前文档,并使用 Nanoc 进行构建并将其部署到[https://docs.gitlab.com](https://s0docs0gitlab0com.icopy.site) . + +如果您需要立即构建和部署站点(必须具有维护者级别的权限): + +1. 在[`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs) ,转到 **CI / CD>时间表** . +2. For the `Build docs.gitlab.com every 4 hours` scheduled pipeline, click the **play** () button. + +## Using YAML data files[](#using-yaml-data-files "Permalink") + +在 Nanoc 中实现类似于[Jekyll 数据文件](https://jekyllrb.com/docs/datafiles/)的最简单方法是使用[`@items`](https://nanoc.ws/doc/reference/variables/#items-and-layouts)变量. + +数据文件必须放在`content/`目录中,然后可以在 ERB 模板中引用它. + +假设我们有具有`content/_data/versions.yaml`文件: + +``` +versions: + - 10.6 + - 10.5 + - 10.4 +``` + +然后,我们可以像下面这样遍历`versions`数组: + +``` +<% @items['/_data/versions.yaml'][:versions].each do | version | %> + +<h3><%= version %></h3> + +<% end &> +``` + +请注意,数据文件必须具有`yaml`扩展名(而不是`yml` ),并且我们使用符号( `:versions` )引用数组. + +## Bumping versions of CSS and JavaScript[](#bumping-versions-of-css-and-javascript "Permalink") + +每当`content/assets/`下的自定义 CSS 和 JavaScript 文件更改时,请确保在最前面更改其版本. 此方法通过清除先前文件的缓存来确保您的更改将生效. + +始终使用 Nanoc 包含这些文件的方式,不要在布局中对它们进行硬编码. 例如使用: + +``` +<script async type="application/javascript" src="<%= @items['/assets/javascripts/badges.*'].path %>"></script> + +<link rel="stylesheet" href="<%= @items['/assets/stylesheets/toc.*'].path %>"> +``` + +The links pointing to the files should be similar to: + +``` +<%= @items['/path/to/assets/file.*'].path %> +``` + +然后 Nanoc 将根据[`Rules`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/Rules)定义的内容正确构建和呈现这些链接. + +## Linking to source files[](#linking-to-source-files "Permalink") + +可以使用名为[`edit_on_gitlab`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/lib/helpers/edit_on_gitlab.rb)的助手来链接到页面的源文件. 我们可以链接到简单编辑器和 Web IDE. 这是在 Nanoc 布局中使用它的方法: + +* 默认编辑器: `<a href="<%= edit_on_gitlab(@item, editor: :simple) %>">Simple editor</a>` +* Web IDE: `<a href="<%= edit_on_gitlab(@item, editor: :webide) %>">Web IDE</a>` + +如果您未指定`editor:` :,则默认使用简单的一个. + +## Algolia search engine[](#algolia-search-engine "Permalink") + +docs 网站使用[Algolia DocSearch](https://community.algolia.com/docsearch/)进行搜索. 它是这样工作的: + +1. GitLab 是[DocSearch 程序](https://community.algolia.com/docsearch/#join-docsearch-program)的成员,该[程序](https://community.algolia.com/docsearch/#join-docsearch-program)是[Algolia](https://www.algolia.com/)的免费[版](https://www.algolia.com/) . +2. Algolia 为 GitLab docs 网站托管[DocSearch 配置](https://github.com/algolia/docsearch-configs/blob/master/configs/gitlab.json) ,我们已经共同努力对其进行完善. +3. 该[配置](https://community.algolia.com/docsearch/config-file.html)由[爬虫](https://community.algolia.com/docsearch/crawler-overview.html)每 24 小时进行一次解析,并将[DocSearch 索引](https://community.algolia.com/docsearch/how-do-we-build-an-index.html) [存储](https://community.algolia.com/docsearch/inside-the-engine.html)在[Algolia 的服务器上](https://community.algolia.com/docsearch/faq.html#where-is-my-data-hosted?) . +4. 在文档方面,我们使用了[DocSearch 布局](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/docsearch.html) ,除[https://docs.gitlab.com/search/](https://docs.gitlab.com/search/)使用其[自己的布局](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/instantsearch.html)之外,几乎所有页面上都存在该[布局](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/instantsearch.html) . 在这些布局中,有一个 JavaScript 代码段,该代码段使用 Algolia 显示结果所需的 API 密钥和索引名称( `gitlab` )来启动 DocSearch. + +**对于 GitLab 员工:**用于访问 Algolia 仪表板的凭据存储在 1Password 中. 如果要接收有关使用情况的每周报告,请搜索标题为`Email, Slack, and GitLab Groups and Aliases`的 Google 文档,搜索`docsearch` ,并在电子邮件中添加评论,以添加到获取每周报告的别名中. + +## Monthly release process (versions)[](#monthly-release-process-versions "Permalink") + +docs 网站支持版本,每个月我们都会将最新版本添加到列表中. 有关更多信息,请阅读有关[每月发布过程的信息](release_process.html) . + +## Review Apps for documentation merge requests[](#review-apps-for-documentation-merge-requests "Permalink") + +如果您为 GitLab 文档做出了贡献,请阅读如何[使用每个合并请求创建一个 Review App](../index.html#previewing-the-changes-live) . \ No newline at end of file diff --git a/docs/573.md b/docs/573.md new file mode 100644 index 0000000000000000000000000000000000000000..cb54d42c20489a1e47a2ed08809ccc7ee6679a0c --- /dev/null +++ b/docs/573.md @@ -0,0 +1,347 @@ +# Global navigation + +> 原文:[https://docs.gitlab.com/ee/development/documentation/site_architecture/global_nav.html](https://docs.gitlab.com/ee/development/documentation/site_architecture/global_nav.html) + +* [Quick start](#quick-start) +* [Adding new items](#adding-new-items) + * [Where to add](#where-to-add) + * [What to add](#what-to-add) +* [How it works](#how-it-works) +* [Composition](#composition) + * [Data file](#data-file) + * [Sections](#sections) + * [Categories](#categories) + * [Docs](#docs) + * [Syntax](#syntax) + * [Titles](#titles) + * [URLs](#urls) + * [Layout file (logic)](#layout-file-logic) + * [Path](#path) + * [Default URL](#default-url) + * [`ee-only` docs](#ee-only-docs) + * [CSS classes](#css-classes) + +# Global navigation[](#global-navigation "Permalink") + +版本历史 + +* 在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/362) . +* 在 GitLab 12.1 中[更新](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/482) . +* 在 GitLab 12.2 中添加了按[项目](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/498)导航. + +全局导航(三窗格文档中最左侧的窗格)提供: + +* 产品功能的高层分组视图. +* 通过浏览菜单结构发现新功能的能力. +* 一种让读者专注于产品领域的方法. +* 能够优化登录页面的功能,因此他们不必完成覆盖文档中包含的每个页面的所有工作. + +## Quick start[](#quick-start "Permalink") + +要将主题添加到全局导航,请转到包含[导航文件](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/)的目录,然后编辑产品区域的`yaml`文件. 您可以复制现有的导航条目并将其编辑以指向您的主题. + +这些文件是: + +| File | Document | Location | +| --- | --- | --- | +| `charts-nav.yaml` | GitLab 云原生头盔图 | `https://docs.gitlab.com/charts/` | +| `default-nav.yaml` | 亚搏体育 app 文件 | `https://docs.gitlab.com/ee/` | +| `omnibus-nav.yaml` | Omnibus GitLab Docs | `https://docs.gitlab.com/omnibus/` | +| `runner-nav.yaml` | 亚搏体育 app Runner Docs | `https://docs.gitlab.com/runner/` | + +## Adding new items[](#adding-new-items "Permalink") + +所有新页面都需要一个新的导航项. 如果没有导航,页面将变为"孤立". 那是: + +* 打开页面时,导航会关闭,并且阅读器会失去位置. +* 该页面与其他页面不属于同一组. + +这意味着创建新页面的决定就是创建新导航项的决定,反之亦然. + +### Where to add[](#where-to-add "Permalink") + +文档页面可以说属于以下几类: + +* GitLab 用户. 这是用于从 Reporter 到 Owner 拥有任何级别权限的用户日常使用 GitLab 的文档. +* GitLab 管理员. 这往往是自我管理实例的文档,这些实例需要访问托管 GitLab 的基础架构. +* 其他文档. 其中包括针对日常使用 GitLab 的客户以及贡献者的文档. 属于其他组的文档属于此处. + +考虑到这些组,以下是应在何处添加新项目的一般规则. + +* 用户文档: + * 组级别功能属于" **组"** . + * 项目级功能属于" **项目"** . + * 可以将组或项目级别(有时称为"实例级别")之外的功能放在顶层,但是必须注意不要淹没该顶层空间. 如果可能,可以以某种方式对这些功能进行分组. + * 除上述内容外,其他大多数其他用户文档都属于**User** . +* 管理文档属于**Administrator** . +* 其他文档属于顶层文档,但必须注意不要创建冗长的顶层导航,这会违背它的目的. + +**注意:**正在逐步推出使所有文档和导航项目都遵循这些原则的方法. + +### What to add[](#what-to-add "Permalink") + +确定了在哪里添加导航元素之后,下一步就是确定要添加的内容. 需要什么样的机制被[证明以下](#data-file) ,但在原则: + +* 导航项文本(读者看到的文本)应: + * 越短越好. + * 要根据具体情况. 很少需要重复父项中的文本. + * 避免使用行话或艺术术语,除非无处不在. 例如, **CI**是**持续集成**的可接受替代. +* 导航链接必须遵循[数据文件中](#data-file)记录的规则. +* EE 徽章受以下条件限制: + * 链接到仅 EE 的页面时必需. + * 链接到仅包含 CE 和 EE 内容的页面时,不需要. + * 当所有子项目均为 EE 专用时为必填项. 在这种情况下,没有子项目带有 EE 标志. + * 如果子项目是仅包含 CE 和 EE 的项目,则不需要. 在这种情况下,每个项目都将被适当标记. + +## How it works[](#how-it-works "Permalink") + +全局导航具有 3 个组成部分: + +* **Section** + * Category + * Doc + +下表描述了可用的部分: + +| Section | Description | +| --- | --- | +| User | GitLab 用户界面的文档. | +| Administrator | GitLab 管理区域的文档. | +| Contributor | 开发 GitLab 的文档. | + +根据用户界面添加了导航上可用的大多数链接. 匹配并不完美,因为某些 UI 导航项不适用于该文档,并且还有其他链接可帮助新用户发现文档. 为了清楚起见," **管理** "下的文档按字母顺序排列. + +要查看计划中的改进,请查看[全局导航史诗](https://gitlab.com/groups/gitlab-com/-/epics/21) . + +**注意:**未经技术作者之一的同意, **请勿** [将项目添加](#adding-new-items)到全局导航. + +## Composition[](#composition "Permalink") + +全局导航由两个文件构建: + +* [Data](#data-file) +* [Layout](#layout-file-logic) + +数据文件将布局与文档链接一起提供给布局. 该布局在[样式](#css-classes)正确[的](#css-classes)容器中的导航之间组织数据. + +### Data file[](#data-file "Permalink") + +数据文件描述了适用项目的导航结构. 所有数据文件都存储在[https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/中,](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/)并且包含三个组件: + +* Sections +* Categories +* Docs + +#### Sections[](#sections "Permalink") + +每个部分代表较高级别的导航项. 它由标题和 URL 组成: + +``` +sections: + - section_title: Text + section_url: 'link' +``` + +该部分可以单独使用,也可以包含其中的类别. + +#### Categories[](#categories "Permalink") + +部分中的每个类别都构成了导航的第二级. 它包括类别标题和链接. 它可以单独放置在导航栏中,也可以包含第三级子项目. + +具有一个独立类别的部分的示例: + +``` +- section_title: Section title + section_url: 'section-link' + section_categories: + - category_title: Category title + category_url: 'category-link' +``` + +具有两个独立类别的部分的示例: + +``` +- section_title: Section title + section_url: 'section-link' + section_categories: + - category_title: Category 1 title + category_url: 'category-1-link' + + - category_title: Category 2 title + category_url: 'category-2-link' +``` + +为了清楚起见,请**始终**在类别之间添加空白行. + +如果 CE 中没有类别 URL(这是仅 EE 的文档),请在类别链接下方添加属性`ee_only: true` . 例: + +``` +- category_title: Category title + category_url: 'category-link' + ee_only: true +``` + +如果类别链接到外部 URL,例如[GitLab Design System](https://design.gitlab.com) ,则在类别标题下添加属性`external_url: true` . 例: + +``` +- category_title: GitLab Design System + category_url: 'https://design.gitlab.com' + external_url: true +``` + +#### Docs[](#docs "Permalink") + +每个文档代表导航链接的第三级. 必须始终将它们添加到类别中. + +带有一个文档链接的示例: + +``` +- category_title: Category title + category_url: 'category-link' + docs: + - doc_title: Document title + doc_url: 'doc-link' +``` + +A category supports as many docs as necessary, but, for clarity, try to not overpopulate a category. + +多个文档的示例: + +``` +- category_title: Category title + category_url: 'category-link' + docs: + - doc_title: Document 1 title + doc_url: 'doc-1-link' + - doc_title: Document 2 title + doc_url: 'doc-2-link' +``` + +每当仅在 EE 中存在文档时,请在 doc 链接下添加属性`ee-only: true` . 例: + +``` +- doc_title: Document 2 title + doc_url: 'doc-2-link' + ee_only: true +``` + +如果您需要在外部 URL 中添加文档,请在 doc 链接下面添加属性`external_url` : + +``` +- doc_title: Document 2 title + doc_url: 'doc-2-link' + external_url: true +``` + +所有导航链接都是可单击的. 如果上级链接没有自己的链接,则它必须链接到它的第一个子项目链接,模仿 GitLab 的导航. 必须避免这种情况,以便我们不会同时有重复的链接或两个`.active`链接. + +Example: + +``` +- category_title: Operations + category_url: 'user/project/integrations/prometheus_library/' + # until we have a link to operations, the first doc link is + # repeated in the category link + docs: + - doc_title: Metrics + doc_url: 'user/project/integrations/prometheus_library/' +``` + +#### Syntax[](#syntax "Permalink") + +对于所有组件(节,类别和文档),请**遵循缩进**和以下语法规则. + +##### Titles[](#titles "Permalink") + +* 使用句子大小写,将特征名称大写. +* 除非其中有特殊字符,否则无需包装标题. 例如,在`GitLab CI/CD` ,存在`/` ,因此必须将其用引号引起来. 按照惯例,将标题用双引号引起来: `category_title: "GitLab CI/CD"` . + +##### URLs[](#urls "Permalink") + +* 按照惯例,始终将 URL 括在单引号`'url'` . +* 始终在 CE 和 EE 的所在地使用相对路径. 例子: + * 对于`https://docs.gitlab.com/ee/README.html` ,相对 URL 为`README.html` . + * 对于`https://docs.gitlab.com/ee/user/project/cycle_analytics.html` ,相对 URL 是`user/project/cycle_analytics.html` . +* 对于`README.html`文件,添加完整路径`path/to/README.html` . +* 对于`index.html`文件,请使用干净的(规范的)URL: `path/to/` . +* 对于仅限 EE 的文档,请使用相同的相对路径,但在`doc_url`或`category_url`下添加属性`ee_only: true` ,如上所述. 这将在导航上显示一个"信息"图标,以使用户知道该功能仅适用于 EE. + +**警告:**数据文件上存在的所有链接都必须以`.html`而不是`.md`结尾. 不要以斜杠`/`开头任何相对链接. + +Examples: + +``` +- category_title: Issues + category_url: 'user/project/issues/' + # note that the above URL does not start with a slash and + # does not include index.html at the end + + docs: + - doc_title: Service Desk + doc_url: 'user/project/service_desk.html' + ee_only: false + # note that the URL above ends in html and, as the + # document is EE-only, the attribute ee_only is set to true. +``` + +### Layout file (logic)[](#layout-file-logic "Permalink") + +[布局](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/global_nav.html)由[数据文件提供](#data-file) ,构建全局导航,并由[默认](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/default.html)布局呈现. + +为导航创建的逻辑主要考虑三个方面: + +* [路径](#path) : `docs.gitlab.com/`下的第一级目录: + * `https://docs.gitlab.com/ce/` + * `https://docs.gitlab.com/ee/` + * `https://docs.gitlab.com/omnibus/` + * `https://docs.gitlab.com/runner/` + * `https://docs.gitlab.com/debug/` + * `https://docs.gitlab.com/*` +* [仅限 EE](#ee-only-docs) :仅在`/ee/`可用的文档,在`/ce/`不可用,例如: + * `https://docs.gitlab.com/ee/user/group/epics/` + * `https://docs.gitlab.com/ee/user/project/security_dashboard.html` +* [默认 URL](#default-url) :CE 和 EE 文档之间的[默认 URL](#default-url) ,默认值为`ee` ,因此,除非在`/ce/`内部链接到`ce`否则所有文档都应链接到`/ee/` . + +#### Path[](#path "Permalink") + +要在数据文件中使用相对路径,我们从根的第一个子目录定义了变量`dir` ,该目录定义了构建指向其他页面的所有导航链接的路径: + +``` +<% dir = @item.identifier.to_s[%r{(?<=/)[^/]+}] %> +``` + +例如,对于`https://docs.gitlab.com/ce/user/index.html` , `dir` = = `ce` ,和`https://docs.gitlab.com/omnibus/README.html` , `dir` == `omnibus` . + +#### Default URL[](#default-url "Permalink") + +GitLab 文档的默认规范 URL 为`https://docs.gitlab.com/ee/` ,因此,文档站点中的所有链接都应链接至`/ee/`除非在`/ce/`文档本身之间进行链接. + +因此,如果用户正在查看`/ee/` , `/omnibus/` , `/runner/`或任何其他最高级别的目录,则导航栏应指向`/ee/` docs. + +另一方面,如果用户正在查看`/ce/` docs,则 CE 导航中的所有链接都应在内部链接到`/ce/`文件. + +``` +<% if dir != 'ce' %> + <a href="/ee/<%= sec[:section_url] %>">...</a> + <% else %> + <a href="/<%= dir %>/<%= sec[:section_url] %>">...</a> + <% end %> + ... +<% end %> +``` + +这也允许导航显示在其他最高级别的目录( `/omnibus/` , `/runner/`等)上,并将它们链接回`/ee/` . + +相同的逻辑应用于所有节( `sec[:section_url]` ),类别( `cat[:category_url]` )和 docs( `doc[:doc_url]` )URL. + +#### `ee-only` docs[](#ee-only-docs "Permalink") + +仅在 gitLab EE 中存在的功能文档在数据文件中被`ee-only`标记,并且在导航链接上显示一个图标,指示`ee-only`功能在 CE 中不可用. + +`ee-only`属性可用于`categories` ( `<% if cat[:ee_only] %>` )和`docs` ( `<% if doc[:ee_only] %>` ),但不能用于`sections` . + +### CSS classes[](#css-classes "Permalink") + +导航在常规`stylesheet.scss` . 要更改其样式,请将它们分组以在团队中更好地发展. + +URL 组件的独特样式由 CSS 类`.level-0` , `.level-1`和`.level-2` . 要调整链接的字体大小,填充,颜色等,请使用这些类. 这样,我们保证每个链接的规则都不会与样式表中的其他规则冲突. \ No newline at end of file diff --git a/docs/574.md b/docs/574.md new file mode 100644 index 0000000000000000000000000000000000000000..1f33fd4f0fb335bc294a3e5b1465dd7ad49f28b0 --- /dev/null +++ b/docs/574.md @@ -0,0 +1,187 @@ +# GitLab Docs monthly release process + +> 原文:[https://docs.gitlab.com/ee/development/documentation/site_architecture/release_process.html](https://docs.gitlab.com/ee/development/documentation/site_architecture/release_process.html) + +* [How to build the images](#how-to-build-the-images) +* [Monthly release process](#monthly-release-process) + * [1\. Add the chart version](#1-add-the-chart-version) + * [2\. Create an image for a single version](#2-create-an-image-for-a-single-version) + * [3\. Create the release merge request](#3-create-the-release-merge-request) + * [4\. Update the dropdown for all online versions](#4-update-the-dropdown-for-all-online-versions) + * [5\. Merge the release merge request](#5-merge-the-release-merge-request) +* [Update an old Docker image with new upstream docs content](#update-an-old-docker-image-with-new-upstream-docs-content) +* [Porting new website changes to old versions](#porting-new-website-changes-to-old-versions) +* [Troubleshooting](#troubleshooting) + * [`test_internal_links_and_anchors` failing on dropdown merge requests](#test_internal_links_and_anchors-failing-on-dropdown-merge-requests) + +# GitLab Docs monthly release process[](#gitlab-docs-monthly-release-process "Permalink") + +[`dockerfiles`目录](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/)包含构建和部署版本控制网站所需的所有 Dockerfile. 它在很大程度上受到了 Docker 的[Dockerfile 的](https://github.com/docker/docker.github.io/blob/06ed03db13895bfe867761b6fc2ad40acf6026dd/Dockerfile)启发. + +使用以下 Dockerfile. + +| Dockerfile | Docker 镜像 | Description | +| --- | --- | --- | +| [`Dockerfile.bootstrap`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.bootstrap) | `gitlab-docs:bootstrap` | 包含构建网站所需的所有依赖项. 如果宝石已更新且`Gemfile{,.lock}`更改,则必须重建映像. | +| [`Dockerfile.builder.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.builder.onbuild) | `gitlab-docs:builder-onbuild` | 用于建立 docs 网站的基本图片. 它使用`ONBUILD`执行所有步骤,并取决于`gitlab-docs:bootstrap` . | +| [`Dockerfile.nginx.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.nginx.onbuild) | `gitlab-docs:nginx-onbuild` | 用于构建文档档案的基本映像. 它使用`ONBUILD`执行所有必需的步骤来复制档案,并依赖于其父`Dockerfile.builder.onbuild` ,该父文件在构建单个文档档案时被调用(请参阅每个分支的`Dockerfile` . | +| [`Dockerfile.archives`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.archives) | `gitlab-docs:archives` | 在一个档案中包含网站的所有版本. 它从一个位置中的每个版本复制所有生成的 HTML 文件. | + +## How to build the images[](#how-to-build-the-images "Permalink") + +尽管构建映像是通过 GitLab CI / CD 自动构建的,但是您可以在本地构建和标记所有工具映像: + +1. 确保已[安装 Docker](https://s0docs0docker0com.icopy.site/install/) . +2. 确保您位于`gitlab-docs`存储库的`dockerfiles/`目录中. +3. 构建图像: + + ``` + docker build -t registry.gitlab.com/gitlab-org/gitlab-docs:bootstrap -f Dockerfile.bootstrap ../ + docker build -t registry.gitlab.com/gitlab-org/gitlab-docs:builder-onbuild -f Dockerfile.builder.onbuild ../ + docker build -t registry.gitlab.com/gitlab-org/gitlab-docs:nginx-onbuild -f Dockerfile.nginx.onbuild ../ + ``` + +对于每个图像, [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/.gitlab-ci.yml)的`images`阶段下都有一个手动作业,可以随意调用. + +## Monthly release process[](#monthly-release-process "Permalink") + +当 22 日发布新版本的 GitLab 时,我们需要创建相应的单个 Docker 映像,并更新一些文件,以使下拉列表正常工作. + +### 1\. Add the chart version[](#1-add-the-chart-version "Permalink") + +由于图表使用的版本号不同于所有其他 GitLab 产品,因此我们需要添加一个[版本映射](https://docs.gitlab.com/charts/installation/version_mappings.html) : + +1. 检查是否为新的图表版本[创建](https://gitlab.com/gitlab-org/charts/gitlab/-/branches)了[稳定的分支](https://gitlab.com/gitlab-org/charts/gitlab/-/branches) . 如果不确定或找不到,请在`#g_delivery`频道中添加一行. +2. 确保您位于`gitlab-docs`存储库的根路径中. +3. 打开`content/_data/chart_versions.yaml`并使用版本映射添加新的稳定分支版本. 请注意,仅需要`major.minor`版本. +4. 创建一个新的合并请求并将其合并. + +**提示:**创建将来的映射可能很方便,因为它们已广为人知. 在这种情况下,当发布新版本的 GitLab 时,您不必重复此第一步. + +### 2\. Create an image for a single version[](#2-create-an-image-for-a-single-version "Permalink") + +必须在发布合并请求之前创建单个 docs 版本,但这需要在为所有产品创建稳定分支之后发生. + +1. 确保您位于`gitlab-docs`存储库的根路径中. +2. 运行 Rake 任务以创建单个版本: + + ``` + ./bin/rake "release:single[12.0]" + ``` + + 应该已经创建了新的`Dockerfile.12.0`并且`.gitlab-ci.yml`应该将分支变量更新为新的分支. 他们将被自动提交. + +3. 推送新创建的分支,但**不要创建合并请求** . 推送后, `image:docker-singe`作业将创建一个新的 Docker 映像,该映像标记有您在第一步中创建的分支名称. 最后,该图像将被上载到[Container Registry 中](https://gitlab.com/gitlab-org/gitlab-docs/container_registry) ,并且将在位于`https://gitlab.com/gitlab-org/gitlab-docs/-/environments/folders/registry`的`registry`环境文件夹下列出.开发人员访问权限). + +(可选)您可以通过构建映像并运行它来进行本地测试: + +``` +docker build -t docs:12.0 -f Dockerfile.12.0 . +docker run -it --rm -p 4000:4000 docs:12.0 +``` + +访问`http://localhost:4000/12.0/`以查看一切是否正常. + +### 3\. Create the release merge request[](#3-create-the-release-merge-request "Permalink") + +**Note:** To be [automated](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/750). + +现在是时候创建每月发布合并请求,添加新版本并轮换旧版本了: + +1. 确保您位于`gitlab-docs`存储库的根路径中. +2. 创建一个分支`release-XY` : + + ``` + git checkout master + git checkout -b release-12-0 + ``` + +3. **轮换在线和离线版本:** + + 在任何给定时间,都有 4 个可浏览的在线版本:一个是从上游主分支(GitLab.com 的文档)中提取的,另一个是三个最新的稳定版本. + + 编辑`content/_data/versions.yaml`并旋转版本以反映新的更改: + + * `online` :3 个最新的稳定版本. + * `offline` :所有以前的版本都以脱机存档的形式提供. +4. **更新`:latest`和`:archives` Docker 映像:** + + 需要更新以下两个 Dockerfile: + + 1. `dockerfiles/Dockerfile.archives`在列表顶部添加最新版本. + 2. `Dockerfile.master`旋转版本(最旧的被删除,最新的被添加在列表的顶部). +5. 最后,应该总共更改了四个文件. 提交并使用"发布"模板推送以创建合并请求: + + ``` + git add content/ Dockerfile.master dockerfiles/Dockerfile.archives + git commit -m "Release 12.0" + git push origin release-12-0 + ``` + +### 4\. Update the dropdown for all online versions[](#4-update-the-dropdown-for-all-online-versions "Permalink") + +版本下拉列表采用"硬编码"方式. 在构建站点时,它将查看`content/_data/versions.yaml`的内容,并基于此内容填充下拉列表. 因此,较旧的分支将具有不同的内容,这意味着下拉列表将在后面列出一个或多个版本. 请记住,下拉菜单的新更改包含在未合并的`release-XY`分支中. + +The content of `content/_data/versions.yaml` needs to change for all online versions: + +1. 运行 Rake 任务,该任务将创建更新下拉列表所需的所有各个合并请求,并将其设置为在管道成功后自动合并. `release-XY`分支需要在本地存在,并且您需要切换到该分支,否则 Rake 任务将失败: + + ``` + ./bin/rake release:dropdowns + ``` + +2. [访问合并请求页面](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests?label_name[]=release)以检查其管道是否通过,并在所有管道合并后继续进行以下也是最后一步. + +**提示:**万一管道发生故障,请参阅[故障排除](#troubleshooting) . + +### 5\. Merge the release merge request[](#5-merge-the-release-merge-request "Permalink") + +下拉合并请求现在应该已经合并到各自的版本(稳定分支)中,这将触发另一个管道. 在这一点上,您只需要照看管道,并确保它们不会失败: + +1. 检查管道页面: `https://gitlab.com/gitlab-org/gitlab-docs/pipelines` : `https://gitlab.com/gitlab-org/gitlab-docs/pipelines`并确保所有稳定的分支都具有绿色管道. +2. 联机版本的所有管道成功后,请合并发布合并请求. +3. 最后,从`https://gitlab.com/gitlab-org/gitlab-docs/pipeline_schedules`运行`Build docker images weekly` Docker 映像管道,以构建`:latest`和`:archives` Docker 映像. + +一旦计划的管道成功,将在线部署所有新版本的 docs 网站. + +## Update an old Docker image with new upstream docs content[](#update-an-old-docker-image-with-new-upstream-docs-content "Permalink") + +如果对单个 Docker 映像中未包含的产品的任何稳定分支进行了任何更改,只需重新运行管道( `https://gitlab.com/gitlab-org/gitlab-docs/pipelines/new` )有问题的版本. + +## Porting new website changes to old versions[](#porting-new-website-changes-to-old-versions "Permalink") + +**警告:将**更改移植到较旧的分支机构可能会产生意想不到的影响,因为我们不断更改网站的后端. 仅在知道自己在做什么并确保在本地进行测试时使用. + +网站将不断变化和完善. 为了将这些更改合并到稳定分支中,我们需要不时选择某些更改. + +如果这不可能或有很多更改,请将 master 合并到其中: + +``` +git branch 12.0 +git fetch origin master +git merge origin/master +``` + +## Troubleshooting[](#troubleshooting "Permalink") + +发布新版本是一个漫长的过程,涉及许多活动部件. + +### `test_internal_links_and_anchors` failing on dropdown merge requests[](#test_internal_links_and_anchors-failing-on-dropdown-merge-requests "Permalink") + +**注意:**我们现在将版本`.gitlab-ci.yml`在相应分支的`.gitlab-ci.yml`中,因此不建议使用以下步骤. + +当[更新稳定版本的下拉列表时](#4-update-the-dropdown-for-all-online-versions) ,某些链接可能会失败. 创建下拉式 MR 的过程有一个警告,那就是通过拉动所有产品的主分支而不是相应的稳定分支来运行测试. + +在实际情况下,由于[`test_internal_links_and_anchors` test](https://gitlab.com/gitlab-org/gitlab-docs/-/jobs/328042431) [,导致与 12.4](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/604)合并请求[相匹配](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/604)的[Update 12.2 下拉列表](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/604)失败. + +发生这种情况是因为已经对产品进行了重命名( `gitlab-monitor`到`gitlab-exporter` ),而旧名称仍在 12.2 文档中引用. 如果使用了 12.2 的各个稳定分支,则不会失败,但是从[`compile_dev`作业中](https://gitlab.com/gitlab-org/gitlab-docs/-/jobs/328042427)可以看出, `master`分支已被拉出. + +要解决此问题, `https://gitlab.com/gitlab-org/gitlab-docs/pipelines/new`为`update-12-2-for-release-12-4`分支重新运行管道( `https://gitlab.com/gitlab-org/gitlab-docs/pipelines/new` ),以下环境变量: + +* `BRANCH_CE`设置为`12-2-stable` +* `BRANCH_EE`设置为`12-2-stable-ee` +* `BRANCH_OMNIBUS`设置为`12-2-stable` +* `BRANCH_RUNNER`设置为`12-2-stable` +* `BRANCH_CHARTS`设置为`2-2-stable` + +这应该使 MR 通过. \ No newline at end of file diff --git a/docs/575.md b/docs/575.md new file mode 100644 index 0000000000000000000000000000000000000000..fdd2ef2af340b9e1bd60817c25b2c27ba1b05812 --- /dev/null +++ b/docs/575.md @@ -0,0 +1,208 @@ +# Telemetry Guide + +> 原文:[https://docs.gitlab.com/ee/development/telemetry/](https://docs.gitlab.com/ee/development/telemetry/) + +* [Our tracking tools](#our-tracking-tools) + * [Snowplow JS (Frontend)](#snowplow-js-frontend) + * [Snowplow Ruby (Backend)](#snowplow-ruby-backend) + * [Usage Ping](#usage-ping) + * [Database import](#database-import) + * [Log system](#log-system) +* [What data can be tracked](#what-data-can-be-tracked) + * [Database counts](#database-counts) + * [Pageview events](#pageview-events) + * [UI Events](#ui-events) + * [CRUD or API events](#crud-or-api-events) + * [Event funnels](#event-funnels) + * [PostgreSQL data](#postgresql-data) + * [Logs](#logs) + * [External services](#external-services) +* [Telemetry systems overview](#telemetry-systems-overview) + * [GitLab Inc](#gitlab-inc) + * [Self-managed](#self-managed) + * [Differences between GitLab Inc and Self-managed](#differences-between-gitlab-inc-and-self-managed) +* [Snowflake data warehouse](#snowflake-data-warehouse) + * [Data sources](#data-sources) + +# Telemetry Guide[](#telemetry-guide "Permalink") + +在 GitLab,我们收集遥测信息,以帮助我们构建更好的 GitLab. 收集有关如何使用 GitLab 的数据,以更好地了解 GitLab 的哪些部分需要改进以及下一步要构建的功能. 遥测还可以帮助我们的团队更好地理解人们使用 GitLab 的原因,并且借助这一知识,我们能够做出更好的产品决策. + +我们还鼓励用户启用跟踪功能,并且我们的跟踪方法完全透明,因此可以轻松理解和信任它. 通过启用跟踪,用户可以: + +* 回馈更广泛的社区. +* 帮助 GitLab 改进产品. + +本文档包含三个指南,概述了 GitLab 的遥测. + +遥测指南: + +1. [Our tracking tools](#our-tracking-tools) +2. [What data can be tracked](#what-data-can-be-tracked) +3. [Telemetry systems overview](#telemetry-systems-overview) +4. [Snowflake data warehouse](#snowflake-data-warehouse) + +[Usage Ping Guide](usage_ping.html) + +1. [What is Usage Ping](usage_ping.html#what-is-usage-ping) +2. [Usage Ping payload](usage_ping.html#usage-ping-payload) +3. [Disable Usage Ping](usage_ping.html#disable-usage-ping) +4. [Usage Ping request flow](usage_ping.html#usage-ping-request-flow) +5. [How Usage Ping works](usage_ping.html#how-usage-ping-works) +6. [Implementing Usage Ping](usage_ping.html#implementing-usage-ping) +7. [Developing and testing Usage Ping](usage_ping.html#developing-and-testing-usage-ping) + +[Snowplow Guide](snowplow.html) + +1. [What is Snowplow](snowplow.html#what-is-snowplow) +2. [Snowplow schema](snowplow.html#snowplow-schema) +3. [Enabling Snowplow](snowplow.html#enabling-snowplow) +4. [Snowplow request flow](snowplow.html#snowplow-request-flow) +5. [Implementing Snowplow JS (Frontend) tracking](snowplow.html#implementing-snowplow-js-frontend-tracking) +6. [Implementing Snowplow Ruby (Backend) tracking](snowplow.html#implementing-snowplow-ruby-backend-tracking) +7. [Developing and testing Snowplow](snowplow.html#developing-and-testing-snowplow) + +更有用的链接: + +* [Telemetry Direction](https://about.gitlab.com/direction/telemetry/) +* [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/) +* [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/) +* [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) + +## Our tracking tools[](#our-tracking-tools "Permalink") + +我们使用几种不同的技术来收集产品使用数据. + +### Snowplow JS (Frontend)[](#snowplow-js-frontend "Permalink") + +Snowplow 是企业级营销和产品分析平台,可帮助跟踪用户与我们的网站和应用程序互动的方式. [Snowplow JS](https://github.com/snowplow/snowplow/wiki/javascript-tracker)是客户端事件的前端跟踪器. + +### Snowplow Ruby (Backend)[](#snowplow-ruby-backend "Permalink") + +Snowplow 是企业级营销和产品分析平台,可帮助跟踪用户与我们的网站和应用程序互动的方式. [Snowplow Ruby](https://github.com/snowplow/snowplow/wiki/ruby-tracker)是服务器端事件的后端跟踪器. + +### Usage Ping[](#usage-ping "Permalink") + +用法 Ping 是 GitLab Inc 收集 GitLab 实例上的用法数据的一种方法. 用法 Ping 主要由实例数据库中不同表的行数组成. 通过逐月比较这些计数(或逐周比较),我们可以大致了解实例如何使用产品中的不同功能. 这些高级数据用于帮助我们的产品,支持和销售团队. + +有关更多详细信息,请阅读《 [用法](usage_ping.html)说明》指南. + +### Database import[](#database-import "Permalink") + +数据库导入是将数据完全导入到 GitLab 的数据仓库中. 对于 GitLab.com,每 6 小时将 PostgreSQL 数据库加载到 Snowflake 数据仓库中. 有关更多详细信息,请参见[数据团队手册](https://about.gitlab.com/handbook/business-ops/data-team/platform/#extract-and-load) . + +### Log system[](#log-system "Permalink") + +系统日志是通过运行 GitLab Rails 应用程序生成的应用程序日志. 有关更多详细信息,请参阅[日志系统](../../administration/logs.html)和[日志记录基础结构](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#logging-infrastructure-overview) . + +## What data can be tracked[](#what-data-can-be-tracked "Permalink") + +我们不同的跟踪工具使我们能够跟踪不同类型的事件. 下面概述了事件类型和可以跟踪哪些数据的示例. + +| 事件类型 | 扫雪机 JS(前端) | 扫雪机 Ruby(后端) | 使用情况 | 数据库导入 | 日志系统 | +| --- | --- | --- | --- | --- | --- | +| 数据库计数 | | | | | | +| 浏览量事件 | | | | | | +| UI 事件 | | | | | | +| CRUD 和 API 事件 | | | | | | +| 活动渠道 | | | | | | +| PostgreSQL 数据 | | | | | | +| Logs | | | | | | +| 外部服务 | | | | | | + +### Database counts[](#database-counts "Permalink") + +* 唯一用户创建的项目数 +* Number of users logged in the past 28 day + +数据库计数是实例数据库中不同表的行计数. 这些是经过过滤,分组或聚合的 SQL 计数查询,可提供高级使用情况数据. 可用表的完整列表可以在[structure.sql 中](https://gitlab.com/gitlab-org/gitlab/-/blob/master/db/structure.sql)找到. + +### Pageview events[](#pageview-events "Permalink") + +* 访问/ dashboard / groups 页面的会话数 + +### UI Events[](#ui-events "Permalink") + +* 单击按钮或链接的会话数 +* 关闭模式的会话数 + +UI 事件是浏览器中任何界面驱动的动作,包括点击数据. + +### CRUD or API events[](#crud-or-api-events "Permalink") + +* Git 推送次数 +* GraphQL 查询数 +* 对 Rails 操作或控制器的请求数 + +这些是后端事件,包括记录的创建,读取,更新,删除以及其他可能从界面中可用层以外的层触发的事件. + +### Event funnels[](#event-funnels "Permalink") + +* 依次执行操作 A,B 和 C 的会话数 +* 从步骤 A 到步骤 B 的转化率 + +### PostgreSQL data[](#postgresql-data "Permalink") + +这些是原始数据库记录,可使用 Sisense 等商业智能工具进行浏览. 可用表的完整列表可以在[structure.sql 中](https://gitlab.com/gitlab-org/gitlab/-/blob/master/db/structure.sql)找到. + +### Logs[](#logs "Permalink") + +这些是原始日志,例如[生产日志](../../administration/logs.html#production_jsonlog) , [API 日志](../../administration/logs.html#api_jsonlog)或[Sidekiq 日志](../../administration/logs.html#sidekiqlog) . 有关更多详细信息,请参见[日志记录基础结构概述](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#logging-infrastructure-overview) . + +### External services[](#external-services "Permalink") + +这些是 GitLab 实例与之交互的外部服务,例如[外部存储提供程序](../../administration/static_objects_external_storage.html)或[外部容器注册表](../../administration/packages/container_registry.html#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint) . 这些服务必须能够将数据发送回 GitLab 实例,以便跟踪数据. + +## Telemetry systems overview[](#telemetry-systems-overview "Permalink") + +系统概述是一个简化的图,显示了 GitLab Inc 与自我管理实例之间的交互. + +[![Telemetry_Overview](img/1f5aad8fb69a4afb74547a2d31fcbc66.png)](../img/telemetry_system_overview.png) + +[Source file](https://app.diagrams.net/#G13DVpN-XnhWGz9tqReIj8pp1UE4ehk_EC) + +### GitLab Inc[](#gitlab-inc "Permalink") + +为了进行遥测,GitLab Inc 具有三个主要组件: + +1. [数据基础架构](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) :包含我们数据团队管理的所有内容,包括用于可视化的 Sisense 仪表板,用于数据仓库的 Snowflake,传入数据源(例如 PostgreSQL Pipeline 和 S3 Bucket)以及最后是数据收集器[GitLab.com 的 Snowplow Collector](https://about.gitlab.com/handbook/engineering/infrastructure/library/snowplow/)和 GitLab 的 Versions 应用程序. +2. GitLab.com:这是生产的 GitLab 应用程序,由客户端和服务器组成. 在客户端或浏览器端,使用 Snowplow JS 跟踪器(前端)来跟踪客户端事件. 在服务器或应用程序端,使用 Snowplow Ruby 跟踪器(后端)来跟踪服务器端事件. 该服务器还包含使用率 Ping,它利用 PostgreSQL 数据库和 Redis 内存数据存储来报告使用率数据. 最后,服务器还包含通过运行 GitLab 应用程序生成的系统日志. +3. [监视基础结构](https://about.gitlab.com/handbook/engineering/monitoring/) :这是用于确保 GitLab.com 正常运行的基础结构. 系统日志从 GitLab.com 发送到我们的监视基础结构,并由 FluentD 收集器收集. 从 FluentD,日志可以通过 Stackdriver 发送到长期的 Google Cloud Services 冷存储,或者通过 Cloud Pub / Sub 发送到我们的 Elastic Cluster,可以使用 Kibana 进行实时浏览. + +### Self-managed[](#self-managed "Permalink") + +出于遥测目的,自我管理实例具有两个主要组成部分: + +1. 数据基础结构:在自助式实例上,设置数据基础结构是可选的. 如果您想为自己管理的实例收集 Snowplow 跟踪事件,则可以设置自己的自我管理 Snowplow 收集器,并将 Snowplow 事件配置为指向自己的收集器. +2. GitLab:一个自我管理的 GitLab 实例包含与上述 GitLab.com 相同的所有组件. + +### Differences between GitLab Inc and Self-managed[](#differences-between-gitlab-inc-and-self-managed "Permalink") + +如橙色线所示,在 GitLab.com 上,Snowplow JS,Snowplow Ruby,Using Ping 和 PostgreSQL 数据库将所有流导入到 GitLab Inc 的数据基础结构中. 但是,在自我管理上,只有 Usage Ping 流入 GitLab Inc 的数据基础架构. + +如绿线所示,在 GitLab.com 上的系统日志流进入 GitLab Inc 的监视基础结构. 在自我管理下,没有日志发送到 GitLab Inc 的监视基础结构. + +GitLab.com 和自我管理之间的区别总结如下: + +| Environment | 扫雪机 JS(前端) | 扫雪机 Ruby(后端) | 使用情况 | 数据库导入 | 日志系统 | +| --- | --- | --- | --- | --- | --- | +| GitLab.com | | | | | | +| Self-Managed | (1) | (1) | | | | + +注意(1):Snowplow JS 和 Snowplow Ruby 在自我管理上可用,但是,Snowplow Collector 端点设置为 GitLab Inc 无法访问的自我管理 Snowplow Collector. + +## Snowflake data warehouse[](#snowflake-data-warehouse "Permalink") + +Snowflake 数据仓库是我们保存 GitLab Inc 所有数据的地方. + +### Data sources[](#data-sources "Permalink") + +Snowflake 和 Sisense 中有多个数据源可用,每个数据源代表沿转换管道的数据的不同视图. + +| Source | Description | Access | +| --- | --- | --- | +| raw | 这些表是原始数据源 | Access via Snowflake | +| analytics_staging | 这些表几乎没有经过任何数据转换,这意味着它们基本上是原始数据源的克隆. | 通过雪花或 Sisense 访问 | +| analytics | 这些表通常经历了更多的数据转换. 它们通常以`_xf`以表示它们已转换的事实 | 通过雪花或 Sisense 访问 | + +如果您是对原始数据感兴趣的产品经理,则可能会关注于`analytics`和`analytics_staging`源. 原始资源仅限于数据和基础架构团队. 有关更多信息,请参阅[产品经理数据:analytics_staging 和 analytics 之间有什么区别?](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/#whats-the-difference-between-analytics_staging-and-analytics) \ No newline at end of file diff --git a/docs/576.md b/docs/576.md new file mode 100644 index 0000000000000000000000000000000000000000..dbe4ed3fd0f0c044c9e50d6fd10f21c73cca4fb9 --- /dev/null +++ b/docs/576.md @@ -0,0 +1,723 @@ +# Usage Ping Guide + +> 原文:[https://docs.gitlab.com/ee/development/telemetry/usage_ping.html](https://docs.gitlab.com/ee/development/telemetry/usage_ping.html) + +* [What is Usage Ping?](#what-is-usage-ping) + * [Why should we enable Usage Ping?](#why-should-we-enable-usage-ping) + * [Limitations](#limitations) +* [Usage Ping payload](#usage-ping-payload) +* [Disable Usage Ping](#disable-usage-ping) +* [Usage Ping request flow](#usage-ping-request-flow) +* [How Usage Ping works](#how-usage-ping-works) +* [Implementing Usage Ping](#implementing-usage-ping) + * [Why batch counting](#why-batch-counting) + * [Ordinary Batch Counters](#ordinary-batch-counters) + * [Distinct Batch Counters](#distinct-batch-counters) + * [Redis Counters](#redis-counters) + * [Alternative Counters](#alternative-counters) + * [Prometheus Queries](#prometheus-queries) +* [Developing and testing Usage Ping](#developing-and-testing-usage-ping) + * [1\. Use your Rails console to manually test counters](#1-use-your-rails-console-to-manually-test-counters) + * [2\. Generate the SQL query](#2-generate-the-sql-query) + * [3\. Optimize queries with #database-lab](#3-optimize-queries-with-database-lab) + * [4\. Add the metric definition](#4-add-the-metric-definition) + * [5\. Add new metric to Versions Application](#5-add-new-metric-to-versions-application) + * [6\. Add the feature label](#6-add-the-feature-label) + * [7\. Add a changelog file](#7-add-a-changelog-file) + * [8\. Ask for a Telemetry Review](#8-ask-for-a-telemetry-review) + * [Optional: Test Prometheus based Usage Ping](#optional-test-prometheus-based-usage-ping) + * [Test with an Omnibus container](#test-with-an-omnibus-container) + * [Test with GitLab development toolkits](#test-with-gitlab-development-toolkits) +* [Usage Statistics definitions](#usage-statistics-definitions) +* [Example Usage Ping payload](#example-usage-ping-payload) + +# Usage Ping Guide[](#usage-ping-guide "Permalink") + +版本历史 + +* 在 GitLab 企业版 8.10 中引入. +* 在 GitLab 企业版 8.12 中添加了更多统计信息. +* 在 9.1 中移至 GitLab Core. +* 在 GitLab Ultimate 11.2 中添加了更多统计信息. + +本指南介绍了用法 Ping 的用途及其实现方式. + +有关遥测的更多信息,请参见: + +* [Telemetry Guide](index.html) +* [Snowplow Guide](snowplow.html) + +更有用的链接: + +* [Telemetry Direction](https://about.gitlab.com/direction/telemetry/) +* [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/) +* [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/) +* [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) + +## What is Usage Ping?[](#what-is-usage-ping "Permalink") + +* GitLab 每周将包含使用情况数据的有效负载发送到 GitLabInc.用法 Ping 提供高级数据来帮助我们的产品,支持和销售团队. 它不发送任何项目名称,用户名或任何其他特定数据. 使用 ping 中的信息不是匿名的,它链接到实例的主机名. 发送使用情况 ping 是可选的,任何实例都可以禁用分析. +* 使用情况数据主要由实例数据库中不同表的行计数组成. 通过逐月比较这些计数(或逐周比较),我们可以大致了解实例如何使用产品中的不同功能. 除计数外,还收集了其他有助于我们分类和了解 GitLab 安装的事实. +* 使用 ping 对 GitLab 很重要,因为我们使用它来计算阶段每月活跃用户(SMAU),这有助于我们衡量阶段和功能的成功程度. +* 启用使用情况 ping 后,GitLab 将从其他实例收集数据,并能够向用户显示您实例的使用情况统计信息. + +### Why should we enable Usage Ping?[](#why-should-we-enable-usage-ping "Permalink") + +* 使用 Ping 的主要目的是构建更好的 GitLab. 收集有关如何使用 GitLab 的数据,以更好地了解功能/阶段的采用和使用情况,这有助于我们了解 GitLab 如何增加价值,并帮助我们的团队更好地了解人们使用 GitLab 的原因,并且借助这些知识,我们可以做得更好产品决策. +* 作为激活使用 ping 的一项好处,GitLab 可让您分析 GitLab 安装过程中用户的活动. +* 作为激活使用 ping 的一项好处,GitLab 为您提供了 DevOps 得分,它为您提供了从计划到监视整个实例对并发 DevOps 的采用情况的概述. +* 您将获得更好,更主动的支持. (假设我们的 TAM 和支持组织使用这些数据来提供更多价值) +* 您将获得有关如何从 GitLab 的投资中获得最大价值的见识和建议. 您是否不想知道组织中未采用许多功能或价值? +* 您将获得一份报告,说明如何与其他类似组织(匿名)进行比较,并提供有关如何改进 DevOps 流程的具体建议和建议. +* 默认情况下启用用法 Ping. 要禁用它,请参阅[禁用用法 Ping](#disable-usage-ping) . + +### Limitations[](#limitations "Permalink") + +* Usage Ping does not track frontend events things like page views, link clicks, or user sessions, and only focuses on aggregated backend events. +* 由于这些限制,我们建议使用 Snowplow 来对您的产品进行检测,以在 GitLab.com 上进行更详细的分析,并使用 Usage Ping 跟踪自我管理中的汇总后端事件. + +## Usage Ping payload[](#usage-ping-payload "Permalink") + +您可以在管理面板中查看发送到 GitLab Inc.的确切 JSON 有效负载. 要查看有效负载: + +1. 导航到" **管理区域">"设置">"度量标准和性能分析"** . +2. 展开**使用情况统计信息**部分. +3. 单击**预览有效负载**按钮. + +有关有效负载的示例,请参阅[示例用法 Ping 有效负载](#example-usage-ping-payload) . + +## Disable Usage Ping[](#disable-usage-ping "Permalink") + +要在 GitLab UI 中禁用"使用情况 Ping",请转到管理面板的**"设置"**页面,然后取消选中" **使用情况 Ping"**复选框. + +要禁用用法 Ping 并防止日后通过管理面板对其进行配置,Omnibus 安装可以在[`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html)设置以下[`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html) : + +``` +gitlab_rails['usage_ping_enabled'] = false +``` + +源代码安装可以在`gitlab.yml`设置以下`gitlab.yml` : + +``` +production: &base + # ... + gitlab: + # ... + usage_ping_enabled: false +``` + +## Usage Ping request flow[](#usage-ping-request-flow "Permalink") + +The following example shows a basic request/response flow between a GitLab instance, the Versions Application, the License Application, Salesforce, GitLab’s S3 Bucket, GitLab’s Snowflake Data Warehouse, and Sisense: + +sequenceDiagram 参与者 GitLab 实例参与者版本应用程序参与者许可证应用程序参与者 Salesforce 参与者 S3 存储桶参与者 Snowflake DW 参与者 Sisense 仪表板 GitLab 实例->>版本应用程序:发送使用情况 ping 循环流程使用情况数据版本应用程序->>版本应用程序:解析使用情况数据版本应用程序- >>版本应用程序:写入数据库版本应用程序->>版本应用程序:更新许可证 ping 超时循环 Salesforce 版本的过程数据 Application-xLicenses 应用程序:请求 Zuora 订阅 ID 许可证 Application-xVersions 应用程序:Zuora 订阅 ID 版本 Application-xSalesforce:通过 Zuora 订阅 ID 请求 Zuora 帐户 ID Salesforce-xVersions 应用程序:Zuora 帐户 ID 版本 Application-xSalesforce:Zuora 帐户最终版本的使用数据 Application->> S3 存储桶:导出版本数据库 S3 存储桶->>雪花 DW:导入数据 Snowflake DW->>雪花 DW:Trans 使用 dbt Snowflake DW->> Sisense 仪表板的表单数据:可用于查询版本 Application->> GitLab 实例的数据:DevOps 得分(会话开发索引) + +## How Usage Ping works[](#how-usage-ping-works "Permalink") + +1. 在 Sidekiq 中将 Usage Ping [cron 作业](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/gitlab_usage_ping_worker.rb#L30)设置为每周运行. +2. 当 cron 作业运行时,它将调用[`GitLab::UsageData.to_json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L22) . +3. `GitLab::UsageData.to_json` [级联](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L22)到`GitLab::UsageData.to_json` +其他计数器方法调用. +4. 所有方法调用的响应都在`GitLab::UsageData.to_json`中[合并](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L14)为一个 JSON 负载. +5. 然后将 JSON 有效负载[发布到 Versions 应用程序](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L20) . + +## Implementing Usage Ping[](#implementing-usage-ping "Permalink") + +Usage Ping consists of two kinds of data, counters and observations. Counters track how often a certain event happened over time, such as how many CI pipelines have run. They are monotonic and always trend up. Observations are facts collected from one or more GitLab instances and can carry arbitrary data. There are no general guidelines around how to collect those, due to the individual nature of that data. + +在`usage_data.rb`中可以找到四种类型的计数器: + +* **普通批处理计数器:**给定 ActiveRecord_Relation 的简单计数 +* **不同的批次计数器:**给定列上给定 ActiveRecord_Relation 的不同计数 +* **备用计数器:**用于设置和配置 +* **Redis 计数器:**用于内存中计数. 由于数据不正确,此方法已被弃用,并将由持久性方法代替. + +**注意:**仅使用提供的计数器方法. 每个计数器方法都包含一个内置的故障保险柜,用于隔离每个计数器,以避免破坏整个使用情况 Ping. + +### Why batch counting[](#why-batch-counting "Permalink") + +对于大型表,由于 MVCC [(多版本并发控制)](https://en.wikipedia.org/wiki/Multiversion_concurrency_control) ,PostgreSQL 可能需要很长时间才能对行进行计数. 批计数是一种将单个大型查询分解为多个较小查询的计数方法. 例如,您可以执行 100 个每个 10,000 条记录的查询,而不是一个查询 1,000,000 条记录并进行批处理的查询. 批计数对于避免数据库超时很有用,因为每个批查询都比一个长期运行的查询短得多. + +对于 GitLab.com,有非常大的表具有 15 秒的查询超时,因此我们使用批计数来避免遇到超时. 以下是一些 GitLab.com 表的大小: + +| Table | 行数百万 | +| --- | --- | +| `merge_request_diff_commits` | 2280 | +| `ci_build_trace_sections` | 1764 | +| `merge_request_diff_files` | 1082 | +| `events` | 514 | + +提供了两种批处理计数方法:" `Ordinary Batch Counters`和" `Distinct Batch Counters` . 批计数需要列上的索引来计算最大值,最小值和范围查询. 在某些情况下,可能需要在计数器涉及的列上添加专门的索引. + +### Ordinary Batch Counters[](#ordinary-batch-counters "Permalink") + +Handles `ActiveRecord::StatementInvalid` error + +给定 ActiveRecord_Relation 的简单计数 + +Method: `count(relation, column = nil, batch: true, start: nil, finish: nil)` + +Arguments: + +* `relation` ActiveRecord_Relation 以执行计数 +* `column`要执行计数的列,默认情况下是主键 +* `batch` :默认为`true`以便使用批次计数 +* `start` :批处理计数的自定义开始,以避免复杂的最小值计算 +* `end` :批处理计数的自定义结束,以避免复杂的最小值计算 + +Examples: + +``` +count(User.active) +count(::Clusters::Cluster.aws_installed.enabled, :cluster_id) +count(::Clusters::Cluster.aws_installed.enabled, :cluster_id, start: ::Clusters::Cluster.minimum(:id), finish: ::Clusters::Cluster.maximum(:id)) +``` + +### Distinct Batch Counters[](#distinct-batch-counters "Permalink") + +Handles `ActiveRecord::StatementInvalid` error + +给定列上给定 ActiveRecord_Relation 的不重复计数 + +Method: `distinct_count(relation, column = nil, batch: true, start: nil, finish: nil)` + +Arguments: + +* `relation` ActiveRecord_Relation 以执行计数 +* `column`该列执行非重复计数,默认情况下是主键 +* `batch` :默认为`true`以便使用批次计数 +* `start` :批处理计数的自定义开始,以避免复杂的最小值计算 +* `end` :批处理计数的自定义结束,以避免复杂的最小值计算 + +Examples: + +``` +distinct_count(::Project, :creator_id) +distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id)) +distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id') +``` + +### Redis Counters[](#redis-counters "Permalink") + +当发送一个块时,句柄`::Redis::CommandError`和`Gitlab::UsageDataCounters::BaseCounter::UnknownEvent`返回-1,或者在向`counter(Gitlab::UsageDataCounters)`发送不同行为时由于所有 2 个不同而返回具有所有值-1 的哈希 Redis 计数器的实现 + +Method: `redis_usage_data(counter, &block)` + +Arguments: + +* `counter` :来自`Gitlab::UsageDataCounters`的计数器,该计数器已实现`fallback_totals`方法 +* 或`block` :被评估 + +用法示例: + +``` +redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter) +redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] } +``` + +请注意,Redis 计数器正在[被弃用](https://gitlab.com/gitlab-org/gitlab/-/issues/216330) ,您应该改为尝试使用 Snowplow 事件. 我们正在构建[自我管理的事件跟踪](https://gitlab.com/gitlab-org/telemetry/-/issues/373) ,一旦可用,我们会将所有 Redis 计数器转换为 Snowplow 事件. + +### Alternative Counters[](#alternative-counters "Permalink") + +以这种方式处理`StandardError`并将后备值处理为-1,如果遇到一个异常,并非所有度量都会失败. 主要用于设置和配置. + +Method: `alt_usage_data(value = nil, fallback: -1, &block)` + +Arguments: + +* `value` :一个简单的静态值,在这种情况下,仅返回该值. +* 或`block` :被评估 +* `fallback: -1` :用于失败的任何度量的通用值. + +用法示例: + +``` +alt_usage_data { Gitlab::VERSION } +alt_usage_data { Gitlab::CurrentSettings.uuid } +alt_usage_data(999) +``` + +### Prometheus Queries[](#prometheus-queries "Permalink") + +在那些操作指标应成为 Usage Ping 一部分的情况下,数据库或 Redis 查询不太可能提供有用的数据. 取而代之的是,Prometheus 可能更合适,因为大多数 GitLab 的体系结构组件都会向其发布指标,这些指标可以查询,汇总并作为使用数据包含在内. + +**注意:** Prometheus 作为 Usage Ping 的数据源目前仅适用于运行[捆绑的 Prometheus](../../administration/monitoring/prometheus/index.html)实例的单节点 Omnibus 安装. + +为了查询 Prometheus 的度量标准,可以使用一个助手方法,该方法将`yield`一个完整配置的`PrometheusClient` ,前提是可以按照上述说明使用它: + +``` +with_prometheus_client do |client| + response = client.query('<your query>') + ... +end +``` + +请参阅[`PrometheusClient`定义,](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/prometheus_client.rb)以了解如何使用其 API 查询数据. + +## Developing and testing Usage Ping[](#developing-and-testing-usage-ping "Permalink") + +### 1\. Use your Rails console to manually test counters[](#1-use-your-rails-console-to-manually-test-counters "Permalink") + +``` +# count +Gitlab::UsageData.count(User.active) +Gitlab::UsageData.count(::Clusters::Cluster.aws_installed.enabled, :cluster_id) + +# count distinct +Gitlab::UsageData.distinct_count(::Project, :creator_id) +Gitlab::UsageData.distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id)) +``` + +### 2\. Generate the SQL query[](#2-generate-the-sql-query "Permalink") + +您的 Rails 控制台将返回生成的 SQL 查询. + +Example: + +``` +pry(main)> Gitlab::UsageData.count(User.active) + (2.6ms) SELECT "features"."key" FROM "features" + (15.3ms) SELECT MIN("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) + (2.4ms) SELECT MAX("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) + (1.9ms) SELECT COUNT("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) AND "users"."id" BETWEEN 1 AND 100000 +``` + +### 3\. Optimize queries with #database-lab[](#3-optimize-queries-with-database-lab "Permalink") + +将 SQL 查询粘贴到`#database-lab`以查看查询的大规模执行情况. + +* `#database-lab` is a Slack channel which uses a production-sized environment to test your queries. +* GitLab.com 的生产数据库有 15 秒的超时. +* 任何单个查询的冷缓存都必须保持在 1 秒以下的执行时间. +* 在涉及的列上添加专门的索引,以减少执行时间. + +为了了解查询的执行情况,我们在 MR 描述中添加了以下信息: + +* 对于具有`time_period`测试的计数器,我们添加了两种情况的信息: + * 所有时间段的`time_period = {}` + * `time_period = { created_at: 28.days.ago..Time.current }`最近 28 天的时间段 +* 优化前后的执行计划和查询时间 +* 查询生成的索引和时间 +* 上下执行的迁移输出 + +我们还使用`#database-lab`和[explain.depesz.com](https://explain.depesz.com/) . 有关更多详细信息,请参见[数据库查看指南](../database_review.html#preparation-when-adding-or-modifying-queries) . + +查询优化工作的示例: + +* [Example 1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26445) +* [Example 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26871) + +### 4\. Add the metric definition[](#4-add-the-metric-definition "Permalink") + +添加,更改或更新指标时,请更新[使用情况统计信息定义表](#usage-statistics-definitions) . + +### 5\. Add new metric to Versions Application[](#5-add-new-metric-to-versions-application "Permalink") + +检查是否需要将新指标添加到"版本应用程序". 请参见`usage_data` [模式](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L147)和已[接受的](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/app/services/usage_ping.rb)用法数据[参数](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/app/services/usage_ping.rb) . 在`counts`键下添加的所有度量标准都保存在`counts`列中. + +有关更多详细信息,请参见[将其他工具添加到"用法" Ping 的过程](https://about.gitlab.com/handbook/product/product-processes/#process-to-add-additional-instrumentation-to-the-usage-ping) . + +### 6\. Add the feature label[](#6-add-the-feature-label "Permalink") + +将`feature`标签添加到"合并请求"以获取新的"用法 Ping"度量. 这些是面向用户的更改,并且是扩展"用法" Ping 功能的一部分. + +### 7\. Add a changelog file[](#7-add-a-changelog-file "Permalink") + +确保您遵守[Changelog 条目指南](../changelog.html) . + +### 8\. Ask for a Telemetry Review[](#8-ask-for-a-telemetry-review "Permalink") + +在 GitLab.com 上,我们具有 DangerBot 设置来监视遥测相关文件,并且 DangerBot 将建议进行遥测. 在您的 MR 中提及`@gitlab-org/growth/telemetry/engineers`以进行审核. + +### Optional: Test Prometheus based Usage Ping[](#optional-test-prometheus-based-usage-ping "Permalink") + +如果提交的数据包含您要检查和验证的[从 Prometheus 查询的](#prometheus-queries)指标,则需要确保 Prometheus 服务器在本地运行,并且相应的 GitLab 组件正在向其导出指标. 如果您不需要测试来自 Prometheus 的数据,则无需采取任何进一步的措施,因为在没有运行 Prometheus 服务器的情况下,Using Ping 应该会正常降低性能. + +当前,存在三种可以将数据导出到 Prometheus 的组件,这些组件包括在 Useing Ping 中: + +* [`node_exporter`](https://github.com/prometheus/node_exporter)从主机导出节点指标 +* [`gitlab-exporter`](https://gitlab.com/gitlab-org/gitlab-exporter)从各种 GitLab 组件导出过程指标 +* 各种 GitLab 服务(例如 Sidekiq 和 Rails 服务器)可导出自己的指标 + +#### Test with an Omnibus container[](#test-with-an-omnibus-container "Permalink") + +这是测试基于 Prometheus 的用法 Ping 的推荐方法. + +验证更改的最简单方法是通过 CI 从代码分支构建新的 Omnibus 映像,然后下载该映像并运行本地容器实例: + +1. 在合并请求中,单击`qa`阶段,然后触发`package-and-qa`作业. 这项工作将触发[`omnibus-gitlab-mirror`项目](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/-/pipelines)的[下游管道中的](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/-/pipelines) Omnibus 构建. +2. 在下游管道中,等待`gitlab-docker`作业完成. +3. 打开作业日志,然后找到完整的容器名称(包括版本). 它将采用以下形式: `registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>` . +4. 在本地计算机上,确保您已登录到 GitLab Docker 注册表. 您可以在[向 GitLab 容器注册表](../../user/packages/container_registry/index.html#authenticating-to-the-gitlab-container-registry)进行[身份验证中](../../user/packages/container_registry/index.html#authenticating-to-the-gitlab-container-registry)找到有关此操作的说明. +5. 登录后,通过`docker pull registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>`下载新映像`docker pull registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>` +6. 有关在 Docker 中使用和运行 Omnibus GitLab 容器的更多信息,请参阅 Omnibus 文档中的[GitLab Docker 映像](https://docs.gitlab.com/omnibus/docker/README.html) . + +#### Test with GitLab development toolkits[](#test-with-gitlab-development-toolkits "Permalink") + +这是不建议使用的方法,因为在模拟实际的 GitLab 部署时会遇到很多困难. + +当前未将[GDK](https://gitlab.com/gitlab-org/gitlab-development-kit)设置为与其他 GitLab 组件一起运行 Prometheus 服务器或`node_exporter` . 如果您愿意,可以[使用 Prometheus 监控 GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/prometheus/index.md#monitoring-the-gdk-with-prometheus) . + +[GCK](https://gitlab.com/gitlab-org/gitlab-compose-kit)对测试基于 Prometheus 的 Useing Ping 的支持有限. 默认情况下,它已经带有完整配置的 Prometheus 服务,该服务设置为可刮除许多组件,但具有以下限制: + +* 它当前未运行`gitlab-exporter`实例,因此可能缺少诸如 Gitaly 之类的服务中的多个`process_*`指标. +* 当它运行`node_exporter` , `node_exporter` `docker-compose`服务会模拟主机,这意味着它通常会报告自身不与正在运行的任何其他服务关联. 这不是在生产设置中报告节点度量的方式,在生产设置中, `node_exporter`始终作为进程与任何给定节点上的其他 GitLab 组件一起运行. 从用法 Ping 的角度来看,没有节点数据因此似乎与任何正在运行的服务相关联,因为它们似乎都在不同的主机上运行. 为了缓解此问题, `node_exporter` GCK 中的`node_exporter`任意"分配"给了`web`服务,这意味着仅针对该服务的`node_*`指标将出现在"用法" Ping 中. + +## Usage Statistics definitions[](#usage-statistics-definitions "Permalink") + +| Statistic | Section | Stage | Tier | Edition | Description | +| --- | --- | --- | --- | --- | --- | +| `uuid` |   |   |   |   |   | +| `hostname` |   |   |   |   |   | +| `version` |   |   |   |   |   | +| `installation_type` |   |   |   |   |   | +| `active_user_count` |   |   |   |   |   | +| `recorded_at` |   |   |   |   |   | +| `recording_ce_finished_at` |   |   |   | CE+EE | 计算核心特征时 | +| `recording_ee_finished_at` |   |   |   | EE | 计算 EE 特定功能时 | +| `edition` |   |   |   |   |   | +| `license_md5` |   |   |   |   |   | +| `license_id` |   |   |   |   |   | +| `historical_max_users` |   |   |   |   |   | +| `Name` | `licensee` |   |   |   |   | +| `Email` | `licensee` |   |   |   |   | +| `Company` | `licensee` |   |   |   |   | +| `license_user_count` |   |   |   |   |   | +| `license_starts_at` |   |   |   |   |   | +| `license_expires_at` |   |   |   |   |   | +| `license_plan` |   |   |   |   |   | +| `license_trial` |   |   |   |   |   | +| `assignee_lists` | `counts` |   |   |   |   | +| `boards` | `counts` |   |   |   |   | +| `ci_builds` | `counts` | `verify` |   |   | 项目中独特的构建 | +| `ci_internal_pipelines` | `counts` | `verify` |   |   | GitLab 存储库中的管道总数 | +| `ci_external_pipelines` | `counts` | `verify` |   |   | 外部存储库中的总管道 | +| `ci_pipeline_config_auto_devops` | `counts` | `verify` |   |   | Auto DevOps 模板中的管道总数 | +| `ci_pipeline_config_repository` | `counts` | `verify` |   |   | 来自存储库中模板的管道总数 | +| `ci_runners` | `counts` | `verify` |   |   | 项目中已配置的跑步者总数 | +| `ci_triggers` | `counts` | `verify` |   |   | 项目中已配置的触发器总数 | +| `ci_pipeline_schedules` | `counts` | `verify` |   |   | GitLab 中的管道时间表 | +| `auto_devops_enabled` | `counts` | `configure` |   |   | 启用了 Auto DevOps 模板的项目 | +| `auto_devops_disabled` | `counts` | `configure` |   |   | 禁用了 Auto DevOps 模板的项目 | +| `deploy_keys` | `counts` |   |   |   |   | +| `deployments` | `counts` | `release` |   |   | 总部署 | +| `deployments` | `counts_monthly` | `release` |   |   | 最近 28 天的部署总数 | +| `dast_jobs` | `counts` |   |   |   |   | +| `successful_deployments` | `counts` | `release` |   |   | 成功部署总数 | +| `successful_deployments` | `counts_monthly` | `release` |   |   | 最近 28 天成功部署的总数 | +| `failed_deployments` | `counts` | `release` |   |   | 失败的部署总数 | +| `failed_deployments` | `counts_monthly` | `release` |   |   | 最近 28 天失败的部署总数 | +| `environments` | `counts` | `release` |   |   | 可用和停止的环境总数 | +| `clusters` | `counts` | `configure` |   |   | 启用和禁用的 GitLab 托管群集总数 | +| `clusters_enabled` | `counts` | `configure` |   |   | 当前启用的 GitLab 托管群集总数 | +| `project_clusters_enabled` | `counts` | `configure` |   |   | 附加到项目的 GitLab 托管集群总数 | +| `group_clusters_enabled` | `counts` | `configure` |   |   | 附加到组的 GitLab 托管集群总数 | +| `instance_clusters_enabled` | `counts` | `configure` |   |   | 附加到实例的 GitLab 托管群集总数 | +| `clusters_disabled` | `counts` | `configure` |   |   | GitLab 托管的禁用集群总数 | +| `project_clusters_disabled` | `counts` | `configure` |   |   | 以前附加到项目的 GitLab 托管的禁用集群总数 | +| `group_clusters_disabled` | `counts` | `configure` |   |   | 以前附加到组的 GitLab 托管的禁用集群总数 | +| `instance_clusters_disabled` | `counts` | `configure` |   |   | 先前附加到实例的 GitLab 托管的禁用集群总数 | +| `clusters_platforms_eks` | `counts` | `configure` |   |   | 在 AWS EKS 上通过 GitLab 设置的 GitLab 托管群集总数 | +| `clusters_platforms_gke` | `counts` | `configure` |   |   | 在 GCE GKE 上通过 GitLab 设置的 GitLab 托管群集总数 | +| `clusters_platforms_user` | `counts` | `configure` |   |   | 用户配置的 GitLab 托管群集总数 | +| `clusters_applications_helm` | `counts` | `configure` |   |   | 启用 Helm 的 GitLab 托管群集总数 | +| `clusters_applications_ingress` | `counts` | `configure` |   |   | 启用了 Ingress 的 GitLab 托管群集总数 | +| `clusters_applications_cert_managers` | `counts` | `configure` |   |   | 启用了 Cert Manager 的 GitLab 托管群集总数 | +| `clusters_applications_crossplane` | `counts` | `configure` |   |   | 启用了 Crossplane 的 GitLab 托管群集总数 | +| `clusters_applications_prometheus` | `counts` | `configure` |   |   | 启用 Prometheus 的 GitLab 托管群集总数 | +| `clusters_applications_runner` | `counts` | `configure` |   |   | 启用 Runner 的 GitLab 托管群集总数 | +| `clusters_applications_knative` | `counts` | `configure` |   |   | 启用了 Knative 的 GitLab 托管群集总数 | +| `clusters_applications_elastic_stack` | `counts` | `configure` |   |   | 启用了 Elastic Stack 的 GitLab 托管集群总数 | +| `clusters_applications_cilium` | `counts` | `configure` |   |   | 启用 Cilium 的 GitLab 托管群集总数 | +| `clusters_management_project` | `counts` | `configure` |   |   | 定义了集群管理项目的 GitLab 托管集群总数 | +| `in_review_folder` | `counts` |   |   |   |   | +| `grafana_integrated_projects` | `counts` |   |   |   |   | +| `groups` | `counts` |   |   |   |   | +| `issues` | `counts` |   |   |   |   | +| `issues_created_from_gitlab_error_tracking_ui` | `counts` | `monitor` |   |   |   | +| `issues_with_associated_zoom_link` | `counts` | `monitor` |   |   |   | +| `issues_using_zoom_quick_actions` | `counts` | `monitor` |   |   |   | +| `issues_with_embedded_grafana_charts_approx` | `counts` | `monitor` |   |   |   | +| `issues_with_health_status` | `counts` |   |   |   |   | +| `keys` | `counts` |   |   |   |   | +| `label_lists` | `counts` |   |   |   |   | +| `lfs_objects` | `counts` |   |   |   |   | +| `milestone_lists` | `counts` |   |   |   |   | +| `milestones` | `counts` |   |   |   |   | +| `pages_domains` | `counts` | `release` |   |   | GitLab 页面总数 | +| `pool_repositories` | `counts` |   |   |   |   | +| `projects` | `counts` |   |   |   |   | +| `projects_imported_from_github` | `counts` |   |   |   |   | +| `projects_with_repositories_enabled` | `counts` |   |   |   |   | +| `projects_with_error_tracking_enabled` | `counts` | `monitor` |   |   |   | +| `protected_branches` | `counts` |   |   |   |   | +| `releases` | `counts` | `release` |   |   | 独特的发行标签 | +| `remote_mirrors` | `counts` |   |   |   |   | +| `requirements_created` | `counts` |   |   |   |   | +| `snippets` | `counts` | ‘create’ |   | CE+EE |   | +| `snippets` | `counts_monthly` | ‘create’ |   | CE+EE |   | +| `personal_snippets` | `counts` | ‘create’ |   | CE+EE |   | +| `personal_snippets` | `counts_monthly` | ‘create’ |   | CE+EE |   | +| `project_snippets` | `counts` | ‘create’ |   | CE+EE |   | +| `project_snippets` | `counts_monthly` | ‘create’ |   | CE+EE |   | +| `suggestions` | `counts` |   |   |   |   | +| `todos` | `counts` |   |   |   |   | +| `uploads` | `counts` |   |   |   |   | +| `web_hooks` | `counts` |   |   |   |   | +| `projects_alerts_active` | `counts` |   |   |   |   | +| `projects_asana_active` | `counts` |   |   |   |   | +| `projects_assembla_active` | `counts` |   |   |   |   | +| `projects_bamboo_active` | `counts` |   |   |   |   | +| `projects_bugzilla_active` | `counts` |   |   |   |   | +| `projects_buildkite_active` | `counts` |   |   |   |   | +| `projects_campfire_active` | `counts` |   |   |   |   | +| `projects_custom_issue_tracker_active` | `counts` |   |   |   |   | +| `projects_discord_active` | `counts` |   |   |   |   | +| `projects_drone_ci_active` | `counts` |   |   |   |   | +| `projects_emails_on_push_active` | `counts` |   |   |   |   | +| `projects_external_wiki_active` | `counts` |   |   |   |   | +| `projects_flowdock_active` | `counts` |   |   |   |   | +| `projects_github_active` | `counts` |   |   |   |   | +| `projects_hangouts_chat_active` | `counts` |   |   |   |   | +| `projects_hipchat_active` | `counts` |   |   |   |   | +| `projects_irker_active` | `counts` |   |   |   |   | +| `projects_jenkins_active` | `counts` |   |   |   |   | +| `projects_jira_active` | `counts` |   |   |   |   | +| `projects_mattermost_active` | `counts` |   |   |   |   | +| `projects_mattermost_slash_commands_active` | `counts` |   |   |   |   | +| `projects_microsoft_teams_active` | `counts` |   |   |   |   | +| `projects_packagist_active` | `counts` |   |   |   |   | +| `projects_pipelines_email_active` | `counts` |   |   |   |   | +| `projects_pivotaltracker_active` | `counts` |   |   |   |   | +| `projects_prometheus_active` | `counts` |   |   |   |   | +| `projects_pushover_active` | `counts` |   |   |   |   | +| `projects_redmine_active` | `counts` |   |   |   |   | +| `projects_slack_active` | `counts` |   |   |   |   | +| `projects_slack_slash_commands_active` | `counts` |   |   |   |   | +| `projects_teamcity_active` | `counts` |   |   |   |   | +| `projects_unify_circuit_active` | `counts` |   |   |   |   | +| `projects_webex_teams_active` | `counts` |   |   |   |   | +| `projects_youtrack_active` | `counts` |   |   |   |   | +| `projects_jira_server_active` | `counts` |   |   |   |   | +| `projects_jira_cloud_active` | `counts` |   |   |   |   | +| `projects_jira_dvcs_cloud_active` | `counts` |   |   |   |   | +| `projects_jira_dvcs_server_active` | `counts` |   |   |   |   | +| `projects_jira_issuelist_active` | `counts` | `create` |   | EE | 总的 Jira Issue 功能已启用 | +| `labels` | `counts` |   |   |   |   | +| `merge_requests` | `counts` |   |   |   |   | +| `merge_requests_users` | `counts` |   |   |   |   | +| `notes` | `counts` |   |   |   |   | +| `wiki_pages_create` | `counts` |   |   |   |   | +| `wiki_pages_update` | `counts` |   |   |   |   | +| `wiki_pages_delete` | `counts` |   |   |   |   | +| `web_ide_commits` | `counts` |   |   |   |   | +| `web_ide_views` | `counts` |   |   |   |   | +| `web_ide_merge_requests` | `counts` |   |   |   |   | +| `web_ide_previews` | `counts` |   |   |   |   | +| `snippet_comment` | `counts` |   |   |   |   | +| `commit_comment` | `counts` |   |   |   |   | +| `merge_request_comment` | `counts` |   |   |   |   | +| `snippet_create` | `counts` |   |   |   |   | +| `snippet_update` | `counts` |   |   |   |   | +| `navbar_searches` | `counts` |   |   |   |   | +| `cycle_analytics_views` | `counts` |   |   |   |   | +| `productivity_analytics_views` | `counts` |   |   |   |   | +| `source_code_pushes` | `counts` |   |   |   |   | +| `merge_request_create` | `counts` |   |   |   |   | +| `design_management_designs_create` | `counts` |   |   |   |   | +| `design_management_designs_update` | `counts` |   |   |   |   | +| `design_management_designs_delete` | `counts` |   |   |   |   | +| `licenses_list_views` | `counts` |   |   |   |   | +| `user_preferences_group_overview_details` | `counts` |   |   |   |   | +| `user_preferences_group_overview_security_dashboard` | `counts` |   |   |   |   | +| `ingress_modsecurity_logging` | `counts` |   |   |   |   | +| `ingress_modsecurity_blocking` | `counts` |   |   |   |   | +| `ingress_modsecurity_disabled` | `counts` |   |   |   |   | +| `ingress_modsecurity_not_installed` | `counts` |   |   |   |   | +| `dependency_list_usages_total` | `counts` |   |   |   |   | +| `epics` | `counts` |   |   |   |   | +| `feature_flags` | `counts` |   |   |   |   | +| `geo_nodes` | `counts` | `geo` |   |   | 地理部署中的站点数 | +| `geo_event_log_max_id` | `counts` | `geo` |   |   | Geo 主数据库上的复制事件数 | +| `incident_issues` | `counts` | `monitor` |   |   | 警报机器人产生的问题 | +| `alert_bot_incident_issues` | `counts` | `monitor` |   |   | 警报机器人产生的问题 | +| `incident_labeled_issues` | `counts` | `monitor` |   |   | 事件标签有问题 | +| `issues_created_gitlab_alerts` | `counts` | `monitor` |   |   | 非警报机器人用户根据警报创建的问题 | +| `issues_created_manually_from_alerts` | `counts` | `monitor` |   |   | 非警报机器人用户根据警报创建的问题 | +| `issues_created_from_alerts` | `counts` | `monitor` |   |   | 从 Prometheus 和警报管理警报创建的问题 | +| `ldap_group_links` | `counts` |   |   |   |   | +| `ldap_keys` | `counts` |   |   |   |   | +| `ldap_users` | `counts` |   |   |   |   | +| `pod_logs_usages_total` | `counts` |   |   |   |   | +| `projects_enforcing_code_owner_approval` | `counts` |   |   |   |   | +| `projects_mirrored_with_pipelines_enabled` | `counts` | `release` |   |   | 启用了存储库镜像的项目 | +| `projects_reporting_ci_cd_back_to_github` | `counts` | `verify` |   |   | 启用 GitHub 服务管道的项目 | +| `projects_with_packages` | `counts` | `package` |   |   | 配置了程序包注册表的项目 | +| `projects_with_prometheus_alerts` | `counts` | `monitor` |   |   | 启用 Prometheus 警报的项目 | +| `projects_with_tracing_enabled` | `counts` | `monitor` |   |   | 启用了跟踪的项目 | +| `projects_with_alerts_service_enabled` | `counts` | `monitor` |   |   | 启用了警报服务的项目 | +| `template_repositories` | `counts` |   |   |   |   | +| `container_scanning_jobs` | `counts` |   |   |   |   | +| `dependency_scanning_jobs` | `counts` |   |   |   |   | +| `license_management_jobs` | `counts` |   |   |   |   | +| `sast_jobs` | `counts` |   |   |   |   | +| `status_page_projects` | `counts` | `monitor` |   |   | 启用状态页的项目 | +| `status_page_issues` | `counts` | `monitor` |   |   | 发布到状态页面的问题 | +| `status_page_incident_publishes` | `counts` | `monitor` |   |   | 发布操作的使用累计次数 | +| `status_page_incident_unpublishes` | `counts` | `monitor` |   |   | 未发布操作的累计使用次数 | +| `epics_deepest_relationship_level` | `counts` |   |   |   |   | +| `operations_dashboard_default_dashboard` | `counts` | `monitor` |   |   | 启用了操作面板的活跃用户 | +| `operations_dashboard_users_with_projects_added` | `counts` | `monitor` |   |   | 在操作仪表板上具有项目的活跃用户 | +| `container_registry_enabled` |   |   |   |   |   | +| `dependency_proxy_enabled` |   |   |   |   |   | +| `gitlab_shared_runners_enabled` |   |   |   |   |   | +| `gravatar_enabled` |   |   |   |   |   | +| `ldap_enabled` |   |   |   |   |   | +| `mattermost_enabled` |   |   |   |   |   | +| `omniauth_enabled` |   |   |   |   |   | +| `prometheus_enabled` |   |   |   |   | 捆绑的 Prometheus 是否已启用 | +| `prometheus_metrics_enabled` |   |   |   |   |   | +| `reply_by_email_enabled` |   |   |   |   |   | +| `average` | `avg_cycle_analytics - code` |   |   |   |   | +| `sd` | `avg_cycle_analytics - code` |   |   |   |   | +| `missing` | `avg_cycle_analytics - code` |   |   |   |   | +| `average` | `avg_cycle_analytics - test` |   |   |   |   | +| `sd` | `avg_cycle_analytics - test` |   |   |   |   | +| `missing` | `avg_cycle_analytics - test` |   |   |   |   | +| `average` | `avg_cycle_analytics - review` |   |   |   |   | +| `sd` | `avg_cycle_analytics - review` |   |   |   |   | +| `missing` | `avg_cycle_analytics - review` |   |   |   |   | +| `average` | `avg_cycle_analytics - staging` |   |   |   |   | +| `sd` | `avg_cycle_analytics - staging` |   |   |   |   | +| `missing` | `avg_cycle_analytics - staging` |   |   |   |   | +| `average` | `avg_cycle_analytics - production` |   |   |   |   | +| `sd` | `avg_cycle_analytics - production` |   |   |   |   | +| `missing` | `avg_cycle_analytics - production` |   |   |   |   | +| `total` | `avg_cycle_analytics` |   |   |   |   | +| `g_analytics_contribution` | `analytics_unique_visits` | `manage` |   |   | 访问/ groups /:group /-/ contribution_analytics | +| `g_analytics_insights` | `analytics_unique_visits` | `manage` |   |   | 访问/ groups /:group /-/ insights | +| `g_analytics_issues` | `analytics_unique_visits` | `manage` |   |   | 访问/ groups /:group /-/ issues_analytics | +| `g_analytics_productivity` | `analytics_unique_visits` | `manage` |   |   | 访问/ groups /:group /-/ a​​nalytics / productivity_analytics | +| `g_analytics_valuestream` | `analytics_unique_visits` | `manage` |   |   | 访问/ groups /:group /-/ a​​nalytics / value_stream_analytics | +| `p_analytics_pipelines` | `analytics_unique_visits` | `manage` |   |   | 访问/:group /:project / pipelines / chart | +| `p_analytics_code_reviews` | `analytics_unique_visits` | `manage` |   |   | 访问/:group /:project /-/ a​​nalytics / code_reviews | +| `p_analytics_valuestream` | `analytics_unique_visits` | `manage` |   |   | 访问/:group /:project /-/ value_stream_analytics | +| `p_analytics_insights` | `analytics_unique_visits` | `manage` |   |   | 访问/:group /:project / insights | +| `p_analytics_issues` | `analytics_unique_visits` | `manage` |   |   | 访问/:group /:project /-/ a​​nalytics / issues_analytics | +| `p_analytics_repo` | `analytics_unique_visits` | `manage` |   |   | 访问/:group /:project /-/ graphs / master / charts | +| `u_analytics_todos` | `analytics_unique_visits` | `manage` |   |   | 访问/ dashboard / todos | +| `i_analytics_cohorts` | `analytics_unique_visits` | `manage` |   |   | 访问/-/ instance_statistics /群组 | +| `i_analytics_dev_ops_score` | `analytics_unique_visits` | `manage` |   |   | 访问/-/ instance_statistics / dev_ops_score | +| `analytics_unique_visits_for_any_target` | `analytics_unique_visits` | `manage` |   |   | 访问上面列出的任何页面 | +| `clusters_applications_cert_managers` | `usage_activity_by_stage` | `configure` |   | CE+EE | 启用了证书管理器的唯一集群 | +| `clusters_applications_helm` | `usage_activity_by_stage` | `configure` |   | CE+EE | 启用 Helm 的独特集群 | +| `clusters_applications_ingress` | `usage_activity_by_stage` | `configure` |   | CE+EE | 启用了 Ingress 的唯一集群 | +| `clusters_applications_knative` | `usage_activity_by_stage` | `configure` |   | CE+EE | 启用 Knative 的唯一集群 | +| `clusters_management_project` | `usage_activity_by_stage` | `configure` |   | CE+EE | 启用项目管理的独特集群 | +| `clusters_disabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 非" GitLab 托管群集"总数 | +| `clusters_enabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | GitLab 托管群集总数 | +| `clusters_platforms_gke` | `usage_activity_by_stage` | `configure` |   | CE+EE | 安装了 Google Cloud 的独特集群 | +| `clusters_platforms_eks` | `usage_activity_by_stage` | `configure` |   | CE+EE | 安装了 AWS 的唯一集群 | +| `clusters_platforms_user` | `usage_activity_by_stage` | `configure` |   | CE+EE | 用户提供的唯一集群 | +| `instance_clusters_disabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 实例上禁用了唯一集群 | +| `instance_clusters_enabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 在实例上启用了唯一集群 | +| `group_clusters_disabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 组上禁用了唯一集群 | +| `group_clusters_enabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 在组上启用了唯一集群 | +| `project_clusters_disabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 项目上禁用了唯一集群 | +| `project_clusters_enabled` | `usage_activity_by_stage` | `configure` |   | CE+EE | 在项目上启用了唯一集群 | +| `projects_slack_notifications_active` | `usage_activity_by_stage` | `configure` |   | EE | 启用了 Slack 服务的独特项目 | +| `projects_slack_slash_active` | `usage_activity_by_stage` | `configure` |   | EE | 启用了 Slack'/'命令的独特项目 | +| `projects_with_prometheus_alerts` | `usage_activity_by_stage` | `configure` |   | EE | 启用 Prometheus 且没有警报的项目 | +| `deploy_keys` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `keys` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `merge_requests` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `projects_with_disable_overriding_approvers_per_merge_request` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `projects_without_disable_overriding_approvers_per_merge_request` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `remote_mirrors` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `snippets` | `usage_activity_by_stage` | `create` |   | CE+EE |   | +| `merge_requests_users` | `usage_activity_by_stage_monthly` | `create` |   | CE+EE | 使用合并请求的唯一用户数 | +| `action_monthly_active_users_project_repo` | `usage_activity_by_stage_monthly` | `create` |   | CE+EE | 推送到项目存储库的唯一用户数 | +| `action_monthly_active_users_design_management` | `usage_activity_by_stage_monthly` | `create` |   | CE+EE | 与设计系统管理进行交互的唯一用户数 | +| `action_monthly_active_users_wiki_repo` | `usage_activity_by_stage_monthly` | `create` |   | CE+EE | 创建或更新 Wiki 存储库的用户的唯一数量 | +| `projects_enforcing_code_owner_approval` | `usage_activity_by_stage` | `create` |   | EE |   | +| `merge_requests_with_optional_codeowners` | `usage_activity_by_stage` | `create` |   | EE |   | +| `merge_requests_with_required_codeowners` | `usage_activity_by_stage` | `create` |   | EE |   | +| `projects_imported_from_github` | `usage_activity_by_stage` | `create` |   | EE |   | +| `projects_with_repositories_enabled` | `usage_activity_by_stage` | `create` |   | EE |   | +| `protected_branches` | `usage_activity_by_stage` | `create` |   | EE |   | +| `suggestions` | `usage_activity_by_stage` | `create` |   | EE |   | +| `approval_project_rules` | `usage_activity_by_stage` | `create` |   | EE | 项目批准规则数 | +| `approval_project_rules_with_target_branch` | `usage_activity_by_stage` | `create` |   | EE | 具有非默认目标分支的项目批准规则的数量 | +| `merge_requests_with_added_rules` | `usage_activity_by_stage` | `create` |   | EE | 合并带有附加规则的请求 | +| `clusters` | `usage_activity_by_stage` | `monitor` |   | CE+EE |   | +| `clusters_applications_prometheus` | `usage_activity_by_stage` | `monitor` |   | CE+EE |   | +| `operations_dashboard_default_dashboard` | `usage_activity_by_stage` | `monitor` |   | CE+EE |   | +| `operations_dashboard_users_with_projects_added` | `usage_activity_by_stage` | `monitor` |   | EE |   | +| `projects_prometheus_active` | `usage_activity_by_stage` | `monitor` |   | EE |   | +| `projects_with_error_tracking_enabled` | `usage_activity_by_stage` | `monitor` |   | EE |   | +| `projects_with_tracing_enabled` | `usage_activity_by_stage` | `monitor` |   | EE |   | +| `events` | `usage_activity_by_stage` | `manage` |   | CE+EE |   | +| `groups` | `usage_activity_by_stage` | `manage` |   | CE+EE |   | +| `users_created_at` | `usage_activity_by_stage` | `manage` |   | CE+EE |   | +| `omniauth_providers` | `usage_activity_by_stage` | `manage` |   | CE+EE |   | +| `ldap_keys` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `ldap_users` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `value_stream_management_customized_group_stages` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `projects_with_compliance_framework` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `ldap_servers` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `ldap_group_sync_enabled` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `ldap_admin_sync_enabled` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `group_saml_enabled` | `usage_activity_by_stage` | `manage` |   | EE |   | +| `issues` | `usage_activity_by_stage` | `plan` |   | CE+EE |   | +| `notes` | `usage_activity_by_stage` | `plan` |   | CE+EE |   | +| `projects` | `usage_activity_by_stage` | `plan` |   | CE+EE |   | +| `todos` | `usage_activity_by_stage` | `plan` |   | CE+EE |   | +| `assignee_lists` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `epics` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `label_lists` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `milestone_lists` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `projects_jira_active` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `projects_jira_dvcs_server_active` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `projects_jira_dvcs_server_active` | `usage_activity_by_stage` | `plan` |   | EE |   | +| `service_desk_enabled_projects` | `usage_activity_by_stage` | `plan` |   | CE+EE |   | +| `service_desk_issues` | `usage_activity_by_stage` | `plan` |   | CE+EE |   | +| `deployments` | `usage_activity_by_stage` | `release` |   | CE+EE | 总部署 | +| `failed_deployments` | `usage_activity_by_stage` | `release` |   | CE+EE | 失败的部署总数 | +| `projects_mirrored_with_pipelines_enabled` | `usage_activity_by_stage` | `release` |   | EE | 启用了存储库镜像的项目 | +| `releases` | `usage_activity_by_stage` | `release` |   | CE+EE | 项目中的唯一发行标签 | +| `successful_deployments` | `usage_activity_by_stage` | `release` |   | CE+EE | 成功部署总数 | +| `user_preferences_group_overview_security_dashboard` | `usage_activity_by_stage` | `secure` |   |   |   | +| `ci_builds` | `usage_activity_by_stage` | `verify` |   | CE+EE | 项目中独特的构建 | +| `ci_external_pipelines` | `usage_activity_by_stage` | `verify` |   | CE+EE | 外部存储库中的总管道 | +| `ci_internal_pipelines` | `usage_activity_by_stage` | `verify` |   | CE+EE | GitLab 存储库中的管道总数 | +| `ci_pipeline_config_auto_devops` | `usage_activity_by_stage` | `verify` |   | CE+EE | Auto DevOps 模板中的管道总数 | +| `ci_pipeline_config_repository` | `usage_activity_by_stage` | `verify` |   | CE+EE | 来自存储库中模板的管道 | +| `ci_pipeline_schedules` | `usage_activity_by_stage` | `verify` |   | CE+EE | GitLab 中的管道时间表 | +| `ci_pipelines` | `usage_activity_by_stage` | `verify` |   | CE+EE | 总管道 | +| `ci_triggers` | `usage_activity_by_stage` | `verify` |   | CE+EE | 触发已启用 | +| `clusters_applications_runner` | `usage_activity_by_stage` | `verify` |   | CE+EE | 启用 Runner 的独特集群 | +| `projects_reporting_ci_cd_back_to_github` | `usage_activity_by_stage` | `verify` |   | EE | 启用 GitHub 管道的独特项目 | +| `merge_requests_users` | `usage_activity_by_stage_monthly` | `create` |   |   | 使用合并请求的唯一用户数 | +| `duration_s` | `topology` | `enablement` |   |   | 收集拓扑数据所需的时间 | +| `application_requests_per_hour` | `topology` | `enablement` |   |   | 每小时对 Web 应用程序的请求数 | +| `failures` | `topology` | `enablement` |   |   | 包含有关失败查询的信息 | +| `nodes` | `topology` | `enablement` |   |   | 运行 GitLab 组件的服务器节点列表 | +| `node_memory_total_bytes` | `topology > nodes` | `enablement` |   |   | 该节点的总可用内存 | +| `node_cpus` | `topology > nodes` | `enablement` |   |   | 该节点的 CPU 核心数 | +| `node_uname_info` | `topology > nodes` | `enablement` |   |   | 有关此节点的基本硬件体系结构和 OS 发行信息 | +| `node_services` | `topology > nodes` | `enablement` |   |   | 在此节点上运行的 GitLab 服务列表 | +| `name` | `topology > nodes > node_services` | `enablement` |   |   | 在此节点上运行的 GitLab 服务的名称 | +| `process_count` | `topology > nodes > node_services` | `enablement` |   |   | 为此服务运行的进程数 | +| `process_memory_rss` | `topology > nodes > node_services` | `enablement` |   |   | 服务流程的平均居民集大小 | +| `process_memory_uss` | `topology > nodes > node_services` | `enablement` |   |   | 服务流程的平均唯一集大小 | +| `process_memory_pss` | `topology > nodes > node_services` | `enablement` |   |   | 服务流程的平均比例集大小 | +| `server` | `topology > nodes > node_services` | `enablement` |   |   | 使用的 Web 服务器类型(Unicorn 或 Puma) | +| `network_policy_forwards` | `counts` | `defend` |   | EE | 容器网络转发的数据包的累积计数 | +| `network_policy_drops` | `counts` | `defend` |   | EE | 容器网络丢弃的数据包的累积计数 | + +## Example Usage Ping payload[](#example-usage-ping-payload "Permalink") + +以下是用法 Ping 有效内容的示例内容. + +``` +{ "uuid": "0000000-0000-0000-0000-000000000000", "hostname": "example.com", "version": "12.10.0-pre", "installation_type": "omnibus-gitlab", "active_user_count": 999, "recorded_at": "2020-04-17T07:43:54.162+00:00", "edition": "EEU", "license_md5": "00000000000000000000000000000000", "license_id": null, "historical_max_users": 999, "licensee": { "Name": "ABC, Inc.", "Email": "email@example.com", "Company": "ABC, Inc." }, "license_user_count": 999, "license_starts_at": "2020-01-01", "license_expires_at": "2021-01-01", "license_plan": "ultimate", "license_add_ons": { }, "license_trial": false, "counts": { "assignee_lists": 999, "boards": 999, "ci_builds": 999, ... }, "container_registry_enabled": true, "dependency_proxy_enabled": false, "gitlab_shared_runners_enabled": true, "gravatar_enabled": true, "influxdb_metrics_enabled": true, "ldap_enabled": false, "mattermost_enabled": false, "omniauth_enabled": true, "prometheus_enabled": false, "prometheus_metrics_enabled": false, "reply_by_email_enabled": "incoming+%{key}@incoming.gitlab.com", "signup_enabled": true, "web_ide_clientside_preview_enabled": true, "ingress_modsecurity_enabled": true, "projects_with_expiration_policy_disabled": 999, "projects_with_expiration_policy_enabled": 999, ... "elasticsearch_enabled": true, "license_trial_ends_on": null, "geo_enabled": false, "git": { "version": { "major": 2, "minor": 26, "patch": 1 } }, "gitaly": { "version": "12.10.0-rc1-93-g40980d40", "servers": 56, "clusters": 14, "filesystems": [ "EXT_2_3_4" ] }, "gitlab_pages": { "enabled": true, "version": "1.17.0" }, "database": { "adapter": "postgresql", "version": "9.6.15" }, "app_server": { "type": "console" }, "avg_cycle_analytics": { "issue": { "average": 999, "sd": 999, "missing": 999 }, "plan": { "average": null, "sd": 999, "missing": 999 }, "code": { "average": null, "sd": 999, "missing": 999 }, "test": { "average": null, "sd": 999, "missing": 999 }, "review": { "average": null, "sd": 999, "missing": 999 }, "staging": { "average": null, "sd": 999, "missing": 999 }, "production": { "average": null, "sd": 999, "missing": 999 }, "total": 999 }, "analytics_unique_visits": { "g_analytics_contribution": 999, ... }, "usage_activity_by_stage": { "configure": { "project_clusters_enabled": 999, ... }, "create": { "merge_requests": 999, ... }, "manage": { "events": 999, ... }, "monitor": { "clusters": 999, ... }, "package": { "projects_with_packages": 999 }, "plan": { "issues": 999, ... }, "release": { "deployments": 999, ... }, "secure": { "user_container_scanning_jobs": 999, ... }, "verify": { "ci_builds": 999, ... } }, "usage_activity_by_stage_monthly": { "configure": { "project_clusters_enabled": 999, ... }, "create": { "merge_requests": 999, ... }, "manage": { "events": 999, ... }, "monitor": { "clusters": 999, ... }, "package": { "projects_with_packages": 999 }, "plan": { "issues": 999, ... }, "release": { "deployments": 999, ... }, "secure": { "user_container_scanning_jobs": 999, ... }, "verify": { "ci_builds": 999, ... } }, "topology": { "duration_s": 0.013836685999194742, "application_requests_per_hour": 4224, "failures": [], "nodes": [ { "node_memory_total_bytes": 33269903360, "node_cpus": 16, "node_uname_info": { "machine": "x86_64", "sysname": "Linux", "release": "4.19.76-linuxkit" }, "node_services": [ { "name": "web", "process_count": 16, "process_memory_pss": 233349888, "process_memory_rss": 788220927, "process_memory_uss": 195295487, "server": "puma" }, { "name": "sidekiq", "process_count": 1, "process_memory_pss": 734080000, "process_memory_rss": 750051328, "process_memory_uss": 731533312 }, ... ], ... }, ... ] } } +``` \ No newline at end of file diff --git a/docs/577.md b/docs/577.md new file mode 100644 index 0000000000000000000000000000000000000000..988544aff998db9dafc1b006d218bbacd5d24671 --- /dev/null +++ b/docs/577.md @@ -0,0 +1,396 @@ +# Snowplow Guide + +> 原文:[https://docs.gitlab.com/ee/development/telemetry/snowplow.html](https://docs.gitlab.com/ee/development/telemetry/snowplow.html) + +* [What is Snowplow](#what-is-snowplow) +* [Snowplow schema](#snowplow-schema) +* [Enabling Snowplow](#enabling-snowplow) +* [Snowplow request flow](#snowplow-request-flow) +* [Implementing Snowplow JS (Frontend) tracking](#implementing-snowplow-js-frontend-tracking) + * [Tracking in HAML (or Vue Templates)](#tracking-in-haml-or-vue-templates) + * [Tracking within Vue components](#tracking-within-vue-components) + * [Tracking in raw JavaScript](#tracking-in-raw-javascript) + * [Tests and test helpers](#tests-and-test-helpers) +* [Implementing Snowplow Ruby (Backend) tracking](#implementing-snowplow-ruby-backend-tracking) + * [Performance](#performance) +* [Developing and testing Snowplow](#developing-and-testing-snowplow) + * [Snowplow Analytics Debugger Chrome Extension](#snowplow-analytics-debugger-chrome-extension) + * [Snowplow Inspector Chrome Extension](#snowplow-inspector-chrome-extension) + * [Snowplow Micro](#snowplow-micro) + * [Snowplow Mini](#snowplow-mini) + +# Snowplow Guide[](#snowplow-guide "Permalink") + +本指南概述了 Snowplow 的工作原理以及实施细节. + +有关遥测的更多信息,请参见: + +* [Telemetry Guide](index.html) +* [Usage Ping Guide](usage_ping.html) + +更有用的链接: + +* [Telemetry Direction](https://about.gitlab.com/direction/telemetry/) +* [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/) +* [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/) +* [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) + +## What is Snowplow[](#what-is-snowplow "Permalink") + +Snowplow 是企业级营销和产品分析平台,可帮助跟踪用户与我们的网站和应用程序互动的方式. + +[扫雪机](https://github.com/snowplow/snowplow)由以下松耦合子系统组成: + +* **Trackers** fire Snowplow events. Snowplow has 12 trackers, covering web, mobile, desktop, server, and IoT. +* **收集器**从跟踪**器**接收 Snowplow 事件. 我们有三个不同的事件收集器,可将事件同步到 Amazon S3,Apache Kafka 或 Amazon Kinesis. +* **Enrich**清理原始的 Snowplow 事件,丰富它们并将其存储. 我们有一个基于 Hadoop 的扩充流程,以及一个基于 Kinesis 或基于 Kafka 的流程. +* 扫雪机事件所在的位置是**存储** . 我们将 Snowplow 事件存储在 S3 上的平面文件结构中以及 Redshift 和 PostgreSQL 数据库中. +* **数据建模**是将事件级别的数据与其他数据集合并在一起,并聚合为较小的数据集,然后应用业务逻辑. 这将产生一组干净的表,从而使对数据的分析更加容易. 我们有 Redshift 和 Looker 的数据模型. +* 在 Snowplow 事件或汇总表上执行**分析** . + +[![snowplow_flow](img/d366ea5b34fa89da8adbcbd7ec51bc2a.png)](../img/snowplow_flow.png) + +## Snowplow schema[](#snowplow-schema "Permalink") + +我们有 Snowplow 模式的许多定义. 我们有一个积极的问题要[对此模式](https://gitlab.com/gitlab-org/gitlab/-/issues/207930)进行[标准化,](https://gitlab.com/gitlab-org/gitlab/-/issues/207930)包括以下定义: + +* 前端和后端分类法如下所示 +* [Feature instrumentation taxonomy](https://about.gitlab.com/handbook/product/product-processes/#taxonomy) +* [Self describing events](https://github.com/snowplow/snowplow/wiki/Custom-events#self-describing-events) +* [Iglu schema](https://gitlab.com/gitlab-org/iglu/) +* [Snowplow authored events](https://github.com/snowplow/snowplow/wiki/Snowplow-authored-events) + +## Enabling Snowplow[](#enabling-snowplow "Permalink") + +可以在以下位置启用跟踪: + +* 实例级别,可以在前端层和后端层上进行跟踪. +* 用户级别,尽管可以按用户禁用用户跟踪. GitLab 跟踪遵循["不跟踪"](https://www.eff.org/issues/do-not-track)标准,因此不会在用户级别跟踪浏览器中启用了"不跟踪"选项的任何用户. + +我们将 Snowplow 用作大多数跟踪策略,并且已在 GitLab.com 上启用了它. 在自我管理的实例上,可以通过导航到以下地址来启用 Snowplow: + +* 用户界面中的**管理区域>设置>集成** . +* 浏览器中的`admin/application_settings/integrations` . + +需要以下配置: + +| Name | Value | +| --- | --- | +| Collector | `snowplow.trx.gitlab.net` | +| Site ID | `gitlab` | +| Cookie 域 | `.gitlab.com` | + +## Snowplow request flow[](#snowplow-request-flow "Permalink") + +下面的示例显示以下组件之间的基本请求/响应流: + +* GitLab.com 上的 Snowplow JS / Ruby Trackers +* [GitLab.com Snowplow Collector](https://gitlab.com/gitlab-com/gl-infra/readiness/-/blob/master/library/snowplow/index.md) +* 亚搏体育 app 的 S3 桶 +* GitLab 的 Snowflake 数据仓库 +* Sisense: + +sequenceDiagram 参与者 Snowplow JS(前端)参与者 Snowplow Ruby(后端)参与者 GitLab.com Snowplow Collector 参与者 S3 Bucket 参与者 Snowflake DW 参与者 Sisense Dashboards Snowplow JS(前端)->> GitLab.com Snowplow Collector:FE 跟踪事件 Snowplow Ruby(后端) ->> GitLab.com Snowplow 收集器:使用 Kinesis Stream 跟踪事件循环过程 GitLab.com Snowplow 收集器->> GitLab.com Snowplow 收集器:记录原始事件 GitLab.com Snowplow 收集器->> GitLab.com Snowplow 收集器:丰富事件 GitLab.com 扫雪机-> GitLab.com 扫雪机:写入磁盘端 GitLab.com 扫雪机->> S3 桶:K​​inesis Firehose S3 桶->>雪花 DW:导入数据 Snowflake DW->> Snowflake DW:转换 dbt Snowflake DW->> Sisense 仪表盘获取数据:可用于查询的数据 + +## Implementing Snowplow JS (Frontend) tracking[](#implementing-snowplow-js-frontend-tracking "Permalink") + +GitLab 提供了`Tracking` ,该接口包装了[Snowplow JavaScript Tracker](https://github.com/snowplow/snowplow/wiki/javascript-tracker)以跟踪自定义事件. 有几种利用跟踪的方法,但是每种方法通常至少需要一个`category`和一个`action` . 可以提供符合我们[功能仪表分类法的](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)其他数据. + +| field | type | 默认值 | description | +| --- | --- | --- | --- | +| `category` | string | document.body.dataset.page | 在其中捕获事件的页面或页面的子部分. | +| `action` | string | ‘generic’ | 用户正在采取的行动. 单击应该是`click` ,应该`activate` ,因此,例如,聚焦表单字段将是`activate_form_input` ,单击按钮将是`click_button` . | +| `data` | object | {} | 如[我们的功能仪表分类法中](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)所述的其他数据,例如`label` , `property` , `value`和`context` . | + +### Tracking in HAML (or Vue Templates)[](#tracking-in-haml-or-vue-templates "Permalink") + +在 HAML(或 Vue 模板)中工作时,我们可以向感兴趣的元素添加`data-track-*`属性. 具有`data-track-event`属性的所有元素都会自动对点击绑定事件跟踪. + +以下是分配给按钮的`data-track-*`属性的示例: + +``` +%button.btn{ data: { track: { event: "click_button", label: "template_preview", property: "my-template" } } } +``` + +``` +<button class="btn" + data-track-event="click_button" + data-track-label="template_preview" + data-track-property="my-template" +/> +``` + +事件侦听器在文档级别绑定,以处理具有这些数据属性的元素上或元素内的单击事件. 这样可以在重新渲染和更改 DOM 时正确处理它们. 请注意,由于绑定了这些事件的方式,不应阻止 click 事件传播 DOM 树. 如果出于某种原因阻止了点击事件的传播,则需要实现自己的侦听器,并按照[原始 JavaScript](#tracking-in-raw-javascript)中的[跟踪中](#tracking-in-raw-javascript)的说明进行操作. + +Below is a list of supported `data-track-*` attributes: + +| attribute | required | description | +| --- | --- | --- | +| `data-track-event` | true | 用户正在采取的行动. 点击次数必须预先考虑`click`并激活必须预先考虑`activate` . 例如,聚焦表单字段将是`activate_form_input` ,单击按钮将是`click_button` . | +| `data-track-label` | false | 如[我们的功能仪表分类中](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)所述的`label` . | +| `data-track-property` | false | 如[我们的功能仪表分类中](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)所述的`property` . | +| `data-track-value` | false | [我们的功能仪表分类法中](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)描述的`value` . 如果省略,则为元素的`value`属性或空字符串. 对于复选框,默认值为元素的选中属性,否则为`false` . | +| `data-track-context` | false | [我们的功能仪表分类法中](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)描述的`context` . | + +### Tracking within Vue components[](#tracking-within-vue-components "Permalink") + +如果需要更复杂的跟踪,可以在组件中使用跟踪 Vue mixin. 要使用它,请首先导入`Tracking`库并请求一个混合. + +``` +import Tracking from '~/tracking'; +const trackingMixin = Tracking.mixin({ label: 'right_sidebar' }); +``` + +您可以提供在组件中跟踪事件时都会传递的默认选项. 例如,如果应使用给定`label`跟踪组件中的所有事件,则此时可以提供一个. 可用的默认值是`category` , `label` , `property`和`value` . 如果未指定类别,则将`document.body.dataset.page`用作默认值. + +然后,您可以通过`mixin` Vue 声明在组件中正常使用 mixin. mixin 还提供了在`data`或`computed`指定跟踪选项的`data` . 这些将覆盖所有默认值,并允许这些值从 props 或基于状态是动态的. + +``` +export default { + mixins: [trackingMixin], + // ...[component implementation]... + data() { + return { + expanded: false, + tracking: { + label: 'left_sidebar' + } + }; + }, +} +``` + +mixin 提供了可以在模板中或从组件方法中调用的`track`方法. 整个实现的示例可能如下所示. + +``` +export default { + mixins: [Tracking.mixin({ label: 'right_sidebar' })], + data() { + return { + expanded: false, + }; + }, + methods: { + toggle() { + this.expanded = !this.expanded; + this.track('click_toggle', { value: this.expanded }) + } + } +}; +``` + +而且,如果需要模板中的内容,也可以直接使用`track`方法. + +``` +<template> + <div> + <a class="toggle" @click.prevent="toggle">Toggle</a> + <div v-if="expanded"> + <p>Hello world!</p> + <a @click.prevent="track('click_action')">Track an event</a> + </div> + </div> +</template> +``` + +### Tracking in raw JavaScript[](#tracking-in-raw-javascript "Permalink") + +可以通过直接调用`Tracking.event`静态函数来添加自定义事件跟踪和检测. 下面的示例演示如何通过手动调用`Tracking.event`按钮的单击. + +``` +import Tracking from '~/tracking'; + +const button = document.getElementById('create_from_template_button'); +button.addEventListener('click', () => { + Tracking.event('dashboard:projects:index', 'click_button', { + label: 'create_from_template', + property: 'template_preview', + value: 'rails', + }); +}) +``` + +### Tests and test helpers[](#tests-and-test-helpers "Permalink") + +在 Jest 中,尤其是在 Vue 测试中,可以使用以下命令: + +``` +import { mockTracking } from 'helpers/tracking_helper'; + +describe('MyTracking', () => { + let spy; + + beforeEach(() => { + spy = mockTracking('_category_', wrapper.element, jest.spyOn); + }); + + it('tracks an event when clicked on feedback', () => { + wrapper.find('.discover-feedback-icon').trigger('click'); + + expect(spy).toHaveBeenCalledWith('_category_', 'click_button', { + label: 'security-discover-feedback-cta', + property: '0', + }); + }); +}); +``` + +在过时的 Karma 测试中,其用法如下: + +``` +import { mockTracking, triggerEvent } from 'spec/helpers/tracking_helper'; + +describe('my component', () => { + let trackingSpy; + + beforeEach(() => { + trackingSpy = mockTracking('_category_', vm.$el, spyOn); + }); + + const triggerEvent = () => { + // action which should trigger a event + }; + + it('tracks an event when toggled', () => { + expect(trackingSpy).not.toHaveBeenCalled(); + + triggerEvent('a.toggle'); + + expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_edit_button', { + label: 'right_sidebar', + property: 'confidentiality', + }); + }); +}); +``` + +## Implementing Snowplow Ruby (Backend) tracking[](#implementing-snowplow-ruby-backend-tracking "Permalink") + +GitLab 提供`Gitlab::Tracking` ,该接口包装[Snowplow Ruby Tracker](https://github.com/snowplow/snowplow/wiki/ruby-tracker)以跟踪自定义事件. + +可以通过直接调用`GitLab::Tracking.event`类方法来添加自定义事件跟踪和检测,该方法接受以下参数: + +| argument | type | 默认值 | description | +| --- | --- | --- | --- | +| `category` | string | ‘application’ | 应用程序的区域或方面. 例如,这可以是`HealthCheckController`或`Lfs::FileTransformer` . | +| `action` | string | ‘generic’ | 正在执行的操作,可以是从控制器操作(如`create`到 Active Record 回调之类的任何内容. | +| `data` | object | {} | 如[我们的功能仪表分类法中](https://about.gitlab.com/handbook/product/feature-instrumentation/#taxonomy)所述的其他数据,例如`label` , `property` , `value`和`context` . 如果不提供,则将它们设置为空字符串. | + +跟踪既可以看作是跟踪用户的行为,也可以用于检测和监视代码区域或方面随时间变化的性能. + +例如: + +``` +class Projects::CreateService < BaseService + def execute + project = Project.create(params) + + Gitlab::Tracking.event('Projects::CreateService', 'create_project', + label: project.errors.full_messages.to_sentence, + value: project.valid? + ) + end +end +``` + +### Performance[](#performance "Permalink") + +跟踪事件时,我们使用[AsyncEmitter](https://github.com/snowplow/snowplow/wiki/Ruby-Tracker#52-the-asyncemitter-class) ,它允许在后台线程中运行检测调用. 这仍然是一个活跃的发展领域. + +## Developing and testing Snowplow[](#developing-and-testing-snowplow "Permalink") + +有几种工具可以开发和测试 Snowplow Event + +| 测试工具 | 前端追踪 | 后端追踪 | 当地发展环境 | 生产环境 | +| --- | --- | --- | --- | --- | +| Snowplow Analytics 调试器 Chrome 扩展 | | | | | +| Snowplow Inspector Chrome 扩展程序 | | | | | +| 扫雪机 | | | | | +| 扫雪机 Mini | | | | | + +### Snowplow Analytics Debugger Chrome Extension[](#snowplow-analytics-debugger-chrome-extension "Permalink") + +Snowplow Analytics Debugger 是用于测试前端事件的浏览器扩展. 这适用于生产,暂存和本地开发环境. + +1. 安装[Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome 浏览器扩展程序. +2. 将 Chrome DevTools 打开到 Snowplow Analytics 调试器选项卡. +3. 在[Igloo Analytics 上](https://www.iglooanalytics.com/blog/snowplow-analytics-debugger-chrome-extension.html)了解更多信息. + +### Snowplow Inspector Chrome Extension[](#snowplow-inspector-chrome-extension "Permalink") + +Snowplow Inspector Chrome 扩展程序是用于测试前端事件的浏览器扩展程序. 这适用于生产,暂存和本地开发环境. + +1. Install [Snowplow Inspector](https://chrome.google.com/webstore/detail/snowplow-inspector/maplkdomeamdlngconidoefjpogkmljm?hl=en). +2. 按下地址栏旁边的 Snowplow Inspector 图标,打开 Chrome 扩展程序. +3. 单击带有 Snowplow 的网页,您应该会在检查器窗口中看到触发 JavaScript 事件. + +### Snowplow Micro[](#snowplow-micro "Permalink") + +Snowplow Micro 是完整 Snowplow 数据收集管道的非常小版本:足够小,可以由测试套件启动. 就像完整的 Snowplow 管道一样,事件可以记录到 Snowplow Micro 中. Micro 然后公开了可以查询的 API. + +Snowplow Micro 是基于 Docker 的解决方案,用于在本地开发环境中测试前端和后端事件. 您需要按照以下说明修改 GDK 进行设置. + +* Read [Introducing Snowplow Micro](https://snowplowanalytics.com/blog/2019/07/17/introducing-snowplow-micro/) +* 查看[Snowplow Micro 存储库](https://github.com/snowplow-incubator/snowplow-micro) +* 观看我们的[安装指南记录](https://www.youtube.com/watch?v=OX46fo_A0Ag) + +1. Install [Snowplow Micro](https://github.com/snowplow-incubator/snowplow-micro): + + ``` + docker run --mount type=bind,source=$(pwd)/example,destination=/config -p 9090:9090 snowplow/snowplow-micro:latest --collector-config /config/micro.conf --iglu /config/iglu.json + ``` + +2. 通过克隆[此项目中](https://gitlab.com/a_akgun/snowplow-micro)的设置来安装 Snowplow micro: + + ``` + git clone git@gitlab.com:a_akgun/snowplow-micro.git + ./snowplow-micro.sh + ``` + +3. 在 SQL 中更新端口以设置`9090` : + + ``` + gdk psql -d gitlabhq_development + update application_settings set snowplow_collector_hostname='localhost:9090', snowplow_enabled=true, snowplow_cookie_domain='.gitlab.com'; + ``` + +4. Update `app/assets/javascripts/tracking.js` to [remove this line](https://gitlab.com/snippets/1918635): + + ``` + forceSecureTracker: true + ``` + +5. Update `lib/gitlab/tracking.rb` to [add these lines](https://gitlab.com/snippets/1918635): + + ``` + protocol: 'http', + port: 9090, + ``` + +6. Update `lib/gitlab/tracking.rb` to [change async emitter from https to http](https://gitlab.com/snippets/1918635): + + ``` + SnowplowTracker::AsyncEmitter.new(Gitlab::CurrentSettings.snowplow_collector_hostname, protocol: 'http'), + ``` + +7. 在管理区域 Settings :: Integrations :: Snowplow 中启用 Snowplow,以指向: `http://localhost:3000/admin/application_settings/integrations#js-snowplow-settings` . + +8. 重新启动 GDK: + + ``` + `gdk restart` + ``` + +9. 从 Rails 控制台发送测试 Snowplow 事件: + + ``` + Gitlab::Tracking.self_describing_event('iglu:com.gitlab/pageview_context/jsonschema/1-0-0', { page_type: ‘MY_TYPE' }, context: nil ) + ``` + +### Snowplow Mini[](#snowplow-mini "Permalink") + +[Snowplow Mini](https://github.com/snowplow/snowplow-mini)是[Snowplow](https://github.com/snowplow/snowplow-mini)的易于部署的单实例版本. + +Snowplow Mini 可用于在生产,暂存和本地开发环境上测试前端和后端事件. + +对于 GitLab.com,我们正在使用 Snowplow Mini 设置[质量检查和测试环境](https://gitlab.com/gitlab-org/telemetry/-/issues/266) . \ No newline at end of file diff --git a/docs/578.md b/docs/578.md new file mode 100644 index 0000000000000000000000000000000000000000..8bd7d89b8f073f8558a329b68b0d0c753010ea83 --- /dev/null +++ b/docs/578.md @@ -0,0 +1,73 @@ +# Experiment Guide + +> 原文:[https://docs.gitlab.com/ee/development/experiment_guide/](https://docs.gitlab.com/ee/development/experiment_guide/) + +* [Experiment tracking issue](#experiment-tracking-issue) +* [Code reviews](#code-reviews) +* [How to create an A/B test](#how-to-create-an-ab-test) + +# Experiment Guide[](#experiment-guide "Permalink") + +任何 GitLab 小组都可以进行实验,大多数情况下是来自[成长子部门的小组](https://about.gitlab.com/handbook/engineering/development/growth/) . 实验与发布无关,因为它们主要针对 GitLab.com. + +实验将作为 A / B 测试运行,并且位于功能标记后面以打开或关闭测试. 根据实验产生的数据,团队将决定实验是否产生了积极影响,并将其设置为新的默认值或回滚. + +## Experiment tracking issue[](#experiment-tracking-issue "Permalink") + +每个实验都应有一个[实验跟踪](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=✓&state=opened&label_name[]=growth experiment&search=)问题,以跟踪从推出到清除/删除的实验. 部署实验后,应立即设置问题的到期日期(这取决于实验,但最多可能需要几周的时间). 在截止日期之后,该问题需要解决,并且可以: + +* 成功,实验将成为新的默认设置. +* 它不成功,与实验相关的所有代码都将被删除. + +无论哪种情况,都应将实验结果与决策依据一起发布到问题上. + +## Code reviews[](#code-reviews "Permalink") + +由于实验代码在很长一段时间内都不会成为代码库的一部分,并且我们想快速迭代以检索数据,因此实验的代码质量有时可能无法满足我们的标准,但无论实验是否为 GitLab 都不会对其产生负面影响运行与否. 最初,实验仅会部署到一小部分用户,但我们仍希望为这些用户提供完美的体验. 因此,实验仍然需要测试. + +对于审阅者和维护者:如果您发现通常无法通过审阅但暂时可以接受的代码,请提及您的疑虑,但请注意,无需进行更改. 然后,作者在这段代码中添加注释,并添加指向该问题的链接以解决该实验. 如果实验成功并成为产品的一部分,则应解决这些后续问题. + +## How to create an A/B test[](#how-to-create-an-ab-test "Permalink") + +* 实验添加到`Gitlab::Experimentation::EXPERIMENTS`中的散列[`experimentation.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/experimentation.rb) : + + ``` + EXPERIMENTS = { + other_experiment: { + #... + }, + # Add your experiment here: + signup_flow: { + environment: ::Gitlab.dev_env_or_com?, # Target environment, defaults to enabled for development and GitLab.com + tracking_category: 'Growth::Acquisition::Experiment::SignUpFlow' # Used for providing the category when setting up tracking data + } + }.freeze + ``` + +* 在控制器中使用实验: + + ``` + class RegistrationController < ApplicationController + def show + # experiment_enabled?(:feature_name) is also available in views and helpers + if experiment_enabled?(:signup_flow) + # render the experiment + else + # render the original version + end + end + end + ``` + +* 跟踪必要的事件. 有关详细信息,请参见[遥测指南](../telemetry/index.html) . +* 合并请求合并后, [`chatops`](../../ci/chatops/README.html)在[适当的通道中](../feature_flags/controls.html#communicate-the-change)使用[`chatops`](../../ci/chatops/README.html)来为 10%的用户启动实验. 功能标记应带有附加了`_experiment_percentage`后缀的实验名称. 为了提高可视性,请在`#s_growth`通道中共享对生产运行的所有命令: + + ``` + /chatops run feature set signup_flow_experiment_percentage 10 + ``` + + 如果发现实验存在问题,则可以通过删除功能标记来禁用实验: + + ``` + /chatops run feature delete signup_flow_experiment_percentage + ``` \ No newline at end of file diff --git a/docs/579.md b/docs/579.md new file mode 100644 index 0000000000000000000000000000000000000000..f67a4c630424eeb73dbebcb8060cd9222083f422 --- /dev/null +++ b/docs/579.md @@ -0,0 +1,15 @@ +# Feature flags in development of GitLab + +> 原文:[https://docs.gitlab.com/ee/development/feature_flags/](https://docs.gitlab.com/ee/development/feature_flags/) + +# Feature flags in development of GitLab[](#feature-flags-in-development-of-gitlab "Permalink") + +[功能标记](../../operations/feature_flags.html)可用于逐步推出更改,无论是新功能还是性能改进. 通过使用功能标志,我们可以轻松地衡量更改的影响,同时仍然能够轻松禁用这些更改,而不必还原整个发行版. + +在使用功能标记进行 GitLab 开发之前,请通读以下内容: + +* [Process for using features flags](process.html). +* [Developing with feature flags](development.html). +* [Controlling feature flags](controls.html). +* [Documenting features deployed behind feature flags](../documentation/feature_flags.html). +* [How GitLab administrators can enable and disable features behind flags](../../administration/feature_flags.html). \ No newline at end of file diff --git a/docs/580.md b/docs/580.md new file mode 100644 index 0000000000000000000000000000000000000000..8a04285ff6f295459ed0430b7101fdfd05a70e67 --- /dev/null +++ b/docs/580.md @@ -0,0 +1,93 @@ +# Feature flags process + +> 原文:[https://docs.gitlab.com/ee/development/feature_flags/process.html](https://docs.gitlab.com/ee/development/feature_flags/process.html) + +* [Feature flags for user applications](#feature-flags-for-user-applications) +* [Feature flags in GitLab development](#feature-flags-in-gitlab-development) + * [When to use feature flags](#when-to-use-feature-flags) + * [Including a feature behind feature flag in the final release](#including-a-feature-behind-feature-flag-in-the-final-release) + * [The cost of feature flags](#the-cost-of-feature-flags) + +# Feature flags process[](#feature-flags-process "Permalink") + +## Feature flags for user applications[](#feature-flags-for-user-applications "Permalink") + +本文档仅涵盖在 GitLab 本身的开发中使用的功能标志. 可以在[功能标志功能文档中](../../user/project/operations/feature_flags.html)找到已部署的用户应用程序中的[功能标志](../../user/project/operations/feature_flags.html) . + +## Feature flags in GitLab development[](#feature-flags-in-gitlab-development "Permalink") + +在决定是否应利用功能标志时,应考虑以下重点: + +* 默认情况下,功能标志应为**off** . +* 功能标记应在代码库中保留尽可能短的时间,以减少对功能标记记帐的需求. +* 使用功能标记的人员负责与负责的利益相关者清楚地传达功能标记后面的功能状态. 应该使用功能标记名称以及明显需要功能标记的默认状态打开或关闭更新问题描述. +* 合并进行更改以隐藏在功能标记后的请求,或删除现有功能标记(因为认为功能稳定),必须分配〜" feature flag"标签. +* 当功能开发将分散在多个合并请求中时,可以使用以下工作流程: + + 1. 在第一个合并请求中引入默认情况下**关闭**的功能标志. + 2. 通过一个或多个合并请求提交增量更改,以确保只有在功能标记为**on 时**才能访问添加的任何新代码. 您可以在开发过程中在本地 GDK 上保持启用功能标志. + 3. When the feature is ready to be tested, enable the feature flag for a specific project and ensure that there are no issues with the implementation. + 4. 准备宣布该功能时,创建一个合并请求,以添加有关该功能的[文档](../documentation/feature_flags.html) ,包括[有关功能标志本身的文档](../documentation/feature_flags.html)以及一个 changelog 条目. 在同一合并请求中,要么将功能标记翻转为**默认状态,**要么将其完全删除以启用新行为. + +可能会想起功能标记将功能的发布延迟至少一个月(=一个发布). 不是这种情况. 功能标记不必在特定时间段内停留(例如,至少一个版本),而是应该一直停留到功能被认为稳定为止. 稳定意味着它可以在 GitLab.com 上运行,而不会引起任何问题,例如中断. + +另请阅读[功能标记](development.html)的[开发指南](development.html) . + +### When to use feature flags[](#when-to-use-feature-flags "Permalink") + +从 GitLab 11.4 开始,开发人员必须使用功能标志进行不重要的更改. 此类更改包括: + +* 新功能(例如,新的合并请求小部件,史诗等). +* 复杂的性能改进,可能需要在生产中进行其他测试,例如重写复杂的查询. +* 对用户界面的侵入性更改,例如新的导航栏或侧边栏的删除. +* 添加了对从第三方服务导入项目的支持. + +在所有情况下,进行更改的人员都可以最好地决定是否需要功能标记. 例如,更改按钮的颜色不需要功能标记,而更改导航栏则绝对需要一个功能标记. 如果您不确定是否需要功能部件标志,只需在合并请求中询问一下,那些查看更改的人员可能会为您提供答案. + +对 UI 元素使用功能标记时,请确保对基础后端代码*也*使用功能标记(如果有). 这样可以确保在启用该功能之前绝对无法使用该功能. + +### Including a feature behind feature flag in the final release[](#including-a-feature-behind-feature-flag-in-the-final-release "Permalink") + +为了构建最终版本并向自我管理的用户展示功能,功能标志至少应默认为**on** . 如果认为该功能稳定并且确信删除该功能标志是安全的,请考虑完全删除该功能标志. *强烈*建议在做出此决定之前**,至少在一天的** [**生产中** **全局**启用](./controls.html#enabling-a-feature-for-gitlabcom)功能标志. 在此期间,有时会发现意外的错误. + +从首次审查合并请求到将更改部署到 GitLab.com 的过程中,启用默认情况下禁用的功能的过程可能需要 5 到 6 天. 但是,建议将此活动留出 10 到 14 天的时间,以解决无法预料的问题. + +功能标记必须[根据其状态(启用/禁用)进行记录](../documentation/feature_flags.html) ,并且当状态更改时, **必须相应**地更新文档. + +**注意:**请注意,合并功能标记的更改后不久,此类操作可使功能在 GitLab.com 上可用. + +更改默认状态或删除功能标志必须在每月的 22 号之前*(至少在* 3-4 个工作日之前)进行,以便将更改包含在最终的自我管理版本中. + +除此之外,功能标志后面的功能应: + +* 在所有 GitLab.com 环境中运行足够长的时间. 该时间段取决于功能标志后面的功能,但是通常经验法则是 2-4 个工作日应该足以收集足够的反馈. +* 在上述时间段内,该功能应向 GitLab.com 计划内的所有用户公开. 将功能暴露给较小的百分比或仅将一组用户公开可能不会暴露出足够多的信息来帮助您确定功能稳定性. + +尽管很少使用,但即使使用了功能标志,发行经理也可能决定拒绝选择或还原稳定分支中的更改. 如果更改被认为是有问题的,过于侵入性的,或者只是没有足够的时间来正确衡量更改在 GitLab.com 上的行为,则可能有必要. + +### The cost of feature flags[](#the-cost-of-feature-flags "Permalink") + +阅读以上内容时,可能会想起此过程会增加很多工作. 幸运的是,事实并非如此,我们将说明原因. 在此示例中,我们将工作成本指定为一个数字,范围从 0 到无穷大. 数量越大,工作越昂贵. 成本并*没有*转化时间,这只是相对于另一个测量一个变化的复杂性的一种方式. + +假设我们正在构建一个新功能,并确定此功能的成本为 10.我们还确定,在不同位置添加功能标志检查的成本为 1.如果不使用功能标志,并且我们的功能按预期工作,我们的总费用为 10.这是最好的情况. 最佳情况下的优化肯定会导致麻烦,而最坏情况下的优化几乎总是更好. + +为了说明这一点,假设我们的功能导致停机,并且没有立即解决的方法. 这意味着我们必须采取以下步骤来解决停机问题: + +1. 还原发行版. +2. 根据所做的更改,执行可能需要的所有清理. +3. 恢复提交,确保" master"分支保持稳定. 如果解决问题可能需要几天甚至几周的时间,那么这尤其必要. +4. 选择还原提交到适当的稳定分支中,以确保在问题解决之前我们不会阻止任何将来的发行. + +如历史所示,这些步骤耗时,复杂,通常涉及许多开发人员,而且最糟糕的是:在解决问题之前,我们的用户使用 GitLab.com 的体验将很糟糕. + +现在,我们假设所有这些的关联成本为 10.这意味着在最坏的情况下(我们应该对其进行优化),我们的总成本现在为 20. + +如果我们使用了功能标记,情况将会大不相同. 我们不需要还原版本,并且由于默认情况下功能标记是禁用的,因此我们不需要还原并选择任何 Git 提交. 实际上,我们要做的就是禁用该功能,在最坏的情况下,执行清理. 假设这是 2 的成本.在这种情况下,我们的最佳案例成本是 11:构建功能部件的成本为 10:添加功能标志的成本为 1\. 现在最坏的情况是 13: + +* 10 构建功能. +* 1 添加功能标志. +* 2 禁用并清理. + +在这里,我们可以看到,在最佳情况下,与不使用功能标记相比,所需的工作仅多一点. 同时,还原变更的过程已大大便宜了. + +In other words, feature flags do not slow down the development process. Instead, they speed up the process as managing incidents now becomes *much* easier. Once continuous deployments are easier to perform, the time to iterate on a feature is reduced even further, as you no longer need to wait weeks before your changes are available on GitLab.com. \ No newline at end of file diff --git a/docs/581.md b/docs/581.md new file mode 100644 index 0000000000000000000000000000000000000000..27d4890b539081f8bcab0a88c0882fb3577bd2c0 --- /dev/null +++ b/docs/581.md @@ -0,0 +1,132 @@ +# Developing with feature flags + +> 原文:[https://docs.gitlab.com/ee/development/feature_flags/development.html](https://docs.gitlab.com/ee/development/feature_flags/development.html) + +* [Feature groups](#feature-groups) + * [Frontend](#frontend) + * [Specs](#specs) + * [`stub_feature_flags: true` (default and preferred)](#stub_feature_flags-true-default-and-preferred) + * [`stub_feature_flags: false`](#stub_feature_flags-false) + * [Enabling a feature flag (in development)](#enabling-a-feature-flag-in-development) + +# Developing with feature flags[](#developing-with-feature-flags "Permalink") + +通常,最好有一个基于组或基于用户的门,并且您应该比使用百分比门更好. 这将使调试更加容易,因为您也可以根据参与者过滤示例日志和错误. 此外,这允许首先启用`gitlab-org`或`gitlab-com`组,而其余用户则`gitlab-com` . + +``` +# Good +Feature.enabled?(:feature_flag, project) + +# Avoid, if possible +Feature.enabled?(:feature_flag) +``` + +要使用基于角色的特征门,模型需要响应`flipper_id` . 例如,要启用 Foo 模型: + +``` +class Foo < ActiveRecord::Base + include FeatureGate +end +``` + +只有`include FeatureGate`或公开的`flipper_id`方法的模型才能用作`Feature.enabled?` `flipper_id` `Feature.enabled?` . + +已开发并打算在功能标记后合并的功能不应包含变更日志条目. 该条目应添加到删除功能部件标记的合并请求中,或在功能部件标记的默认值设置为 true 的合并请求中添加. 如果功能包含任何数据库迁移,则该功能应包括数据库更改的更改日志条目. + +如果您需要功能标记自动打开,请在检查以下内容时使用`default_enabled: true` : + +``` +Feature.enabled?(:feature_flag, project, default_enabled: true) +``` + +[`Project#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/app/models/project_feature.rb#L63-68) , [`Namespace#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/ee/namespace.rb#L71-85) (EE)和[`License.feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/license.rb#L293-300) (EE)方法都隐式检查默认情况下启用的功能标志,该标志与提供的参数同名. + +例如,如果某个功能是许可门控的,则无需添加其他显式功能标志检查,因为该标志将作为`License.feature_available?`一部分进行检查`License.feature_available?` 呼叫. 同样,功能达到通用状态后,也无需"清理"功能标志. + +您是否仍想使用显式`Feature.enabled?` 检查您的新功能是否不受许可或计划的限制. + +**上面提到的隐式功能标志的一个重要副作用是,除非功能被明确禁用或限制为一定比例的用户,否则功能标志检查将默认为`true` .** + +当使用[几个较小的合并请求](https://about.gitlab.com/handbook/values/#make-small-merge-requests)开发功能时,或者当该功能被视为[alpha 或 beta 时](https://about.gitlab.com/handbook/product/#alpha-beta-ga) ,这是相关的,并且默认情况下不可用. + +例如,如果要交付功能的前端一半而没有后端,则希望完全禁用该功能,直到也可以交付后端一半. 要确保 GitLab.com 和自我管理实例均禁用此功能,应使用[`Namespace#alpha_feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/458749872f4a8f27abe8add930dbb958044cb926/ee/app/models/ee/namespace.rb#L113) 或[`Namespace#beta_feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/458749872f4a8f27abe8add930dbb958044cb926/ee/app/models/ee/namespace.rb#L100-112) 方法,根据我们的[定义](https://about.gitlab.com/handbook/product/#alpha-beta-ga) . 这样可以确保禁用功能,除非*明确*启用了功能标志. + +## Feature groups[](#feature-groups "Permalink") + +从 GitLab 9.4 开始,我们通过[Flipper 组](https://github.com/jnunemaker/flipper/blob/v0.10.2/docs/Gates.md#2-group)支持功能[组](https://github.com/jnunemaker/flipper/blob/v0.10.2/docs/Gates.md#2-group) . + +功能组必须在`lib/feature.rb` (在`.register_feature_groups`方法中)静态定义,但是它们的实现显然可以是动态的(查询数据库等). + +在`lib/feature.rb`定义后,您将能够通过[features API](../../api/features.html#set-or-create-a-feature)的[`feature_group`参数](../../api/features.html#set-or-create-a-feature)激活给定功能组[的功能](../../api/features.html#set-or-create-a-feature) + +### Frontend[](#frontend "Permalink") + +对于前端代码,可以使用方法`push_frontend_feature_flag` ,该方法适用于所有从`ApplicationController`继承的控制器. 使用此方法,可以按如下所示公开功能部件标志的状态: + +``` +before_action do + # Prefer to scope it per project or user e.g. + push_frontend_feature_flag(:vim_bindings, project) + + # Avoid, if possible + push_frontend_feature_flag(:vim_bindings) +end + +def index + # ... +end + +def edit + # ... +end +``` + +然后,您可以按照以下步骤检查 JavaScript 中功能部件标志的状态: + +``` +if ( gon.features.vimBindings ) { + // ... +} +``` + +JavaScript 中的功能标志的名称将始终为 camelCased,这意味着检查`gon.features.vim_bindings`将不起作用. + +有关如何访问 Vue 组件中的功能标志的详细信息,请参见[Vue 指南](../fe_guide/vue.html#accessing-feature-flags) . + +### Specs[](#specs "Permalink") + +我们在测试环境中的 Flipper 引擎以`Flipper::Adapters::Memory`的内存模式工作. `production`和`development`模式使用`Flipper::Adapters::ActiveRecord` . + +### `stub_feature_flags: true` (default and preferred)[](#stub_feature_flags-true-default-and-preferred "Permalink") + +在此模式下,将 Flipper 配置为使用`Flipper::Adapters::Memory`并将所有功能标志标记为默认状态,并在首次使用时保持不变. 这将覆盖`Feature.enabled?`的`default_enabled:` `Feature.enabled?` 和`Feature.disabled?` 除非功能标记持续存在,否则始终返回`true` . + +Make sure behavior under feature flag doesn’t go untested in some non-specific contexts. + +有关如何在测试中添加功能标志的信息和示例,请参见[测试指南](../testing_guide/best_practices.html#feature-flags-in-tests) . + +### `stub_feature_flags: false`[](#stub_feature_flags-false "Permalink") + +这将禁用存储在内存中的鳍状肢,并使用`Flipper::Adapters::ActiveRecord`一种`production`和`development`所使用的模式. + +仅当您确实想测试 Flipper 的各个方面及其与`ActiveRecord`交互方式时,才应使用此模式. + +### Enabling a feature flag (in development)[](#enabling-a-feature-flag-in-development "Permalink") + +在 rails 控制台( `rails c` )中,输入以下命令以启用功能部件标志 + +``` +Feature.enable(:feature_flag_name) +``` + +同样,以下命令将禁用功能部件标志: + +``` +Feature.disable(:feature_flag_name) +``` + +您也可以为给定的门启用功能标志: + +``` +Feature.enable(:feature_flag_name, Project.find_by_full_path("root/my-project")) +``` \ No newline at end of file diff --git a/docs/582.md b/docs/582.md new file mode 100644 index 0000000000000000000000000000000000000000..606a8fb1f609c84c178a0d98ef04b95e09ad4e2e --- /dev/null +++ b/docs/582.md @@ -0,0 +1,195 @@ +# Feature flag controls + +> 原文:[https://docs.gitlab.com/ee/development/feature_flags/controls.html](https://docs.gitlab.com/ee/development/feature_flags/controls.html) + +* [Access](#access) +* [Rolling out changes](#rolling-out-changes) + * [Enabling a feature for preproduction testing](#enabling-a-feature-for-preproduction-testing) + * [Enabling a feature for GitLab.com](#enabling-a-feature-for-gitlabcom) + * [Communicate the change](#communicate-the-change) + * [Process](#process) + * [Feature flag change logging](#feature-flag-change-logging) +* [Cleaning up](#cleaning-up) + +# Feature flag controls[](#feature-flag-controls "Permalink") + +## Access[](#access "Permalink") + +为了能够在 GitLab Inc.提供的任何环境(例如分期和生产)中打开/关闭功能标记后面的功能,您需要访问[Chatops](../chatops_on_gitlabcom.html)机器人. Chatops 机器人当前在 ops 实例上运行,该实例不同于[https://gitlab.com](https://gitlab.com)或[https://dev.gitlab.org](https://dev.gitlab.org) . + +按照 Chatops 文档[请求访问权限](../chatops_on_gitlabcom.html#requesting-access) . + +一旦您将访问权限传播到项目测试中,请运行: + +``` +/chatops run feature --help +``` + +## Rolling out changes[](#rolling-out-changes "Permalink") + +将更改部署到环境后,就该开始向我们的用户推出该功能了. 没有具体说明发布更改的确切过程,因为更改之间可能会有所不同. 但是,总的来说,我们建议逐步推出更改,而不是立即为所有人启用更改. 我们还建议您在部署代码*之前* *不要*启用功能. 这使您可以将部署的功能与部署分开,从而更容易分别衡量两者的影响. + +GitLab 的功能库(使用[Flipper](https://github.com/jnunemaker/flipper) ,并在[功能标志过程](process.html)指南中进行了介绍)支持向用户发布更改的时间百分比. 依次可以使用[GitLab Chatops](../../ci/chatops/README.html)进行控制. + +有关功能标志命令的最新列表,请参见[源代码](https://gitlab.com/gitlab-com/chatops/blob/master/lib/chatops/commands/feature.rb) . 请注意,该文件中的所有示例都必须在`/chatops run`之前. + +如果收到错误消息"糟糕! 不允许执行此操作. 该事件将得到报告." 这意味着您的 Slack 帐户不允许更改功能标志,或者您没有[访问权限](#access) . + +### Enabling a feature for preproduction testing[](#enabling-a-feature-for-preproduction-testing "Permalink") + +作为功​​能推出的第一步,您应该在[https://staging.gitlab.com](https://staging.gitlab.com)和[https://dev.gitlab.org](https://dev.gitlab.org)上启用功能. + +这两个环境具有不同的范围. `dev.gitlab.org`是具有内部 GitLab Inc.流量的生产 CE 环境,用于某些开发和其他相关工作. `staging.gitlab.com`有 GitLab.com 数据库和知识库的较小的子集,并没有正常的交通. 登台是 EE 实例,可以(非常)粗略估计您的功能在 GitLab.com 上的外观/行为. 这两个实例都已连接到 Sentry,因此请确保在启用功能标志后测试功能时,检查那里的项目是否存在异常. + +对于这些预生产环境,应在功能相关的阶段在 Slack 通道中运行命令. 例如,将`#s_monitor`通道用于 Monitor 阶段"运行状况"组开发的功能. + +To enable a feature for 25% of all users, run the following in Slack: + +``` +/chatops run feature set new_navigation_bar 25 --dev +/chatops run feature set new_navigation_bar 25 --staging +``` + +### Enabling a feature for GitLab.com[](#enabling-a-feature-for-gitlabcom "Permalink") + +在[预生产](#enabling-a-feature-for-preproduction-testing)环境中成功[启用功能](#enabling-a-feature-for-preproduction-testing)并验证其安全性和正常工作后,您可以将更改发布到 GitLab.com(生产). + +#### Communicate the change[](#communicate-the-change "Permalink") + +GitLab.com 上的某些功能标志更改应与公司部分进行沟通. 负责开发的人员需要确定这是否必要以及适当的通信级别. 这取决于功能及其可能产生的影响. + +作为指导: + +* 对于低风险且易于回滚的简单功能,只需继续[在`#production`启用该功能](#process) . +* 对于将影响用户体验的功能,请考虑事先通知`#support_gitlab-com` . +* 对于具有重大下游影响的功能(例如:打开/关闭 Elasticsearch 索引`#production` ),请考虑事先与`#production`协调. + +#### Process[](#process "Permalink") + +在切换任何功能标志之前,请检查 GitLab.com 上是否没有正在进行的重大事件. 您可以通过检查`#production`和`#incident-management` Slack 通道,或查找[未解决的事件问题](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/?scope=all&utf8=✓&state=opened&label_name[]=incident) (尽管检查日期和时间)来执行此操作. + +我们不想在事件发生时进行更改,因为它会使实现事件的诊断和解决变得更加困难,并且由于无法评估发布是否没有问题,因此在很大程度上会使发布过程无效. + +如有疑问,请在`#production`中`#production` . + +以下`/chatops`命令应在 Slack `#production`通道中执行. + +当您开始启用该功能时,请在您执行的第一个`/chatops`命令的 Slack 线程中链接到相关的功能标志发布问题,以便人们可以根据需要了解更改. + +要在 25%的时间内启用功能,请在 Slack 中运行以下命令: + +``` +/chatops run feature set new_navigation_bar 25 +``` + +这将根据以下公式将功能标记设置为`true` : + +``` +feature_flag_state = rand < (25 / 100.0) +``` + +这将为 GitLab.com 启用该功能,其中`new_navigation_bar`为该功能的名称. 此命令*不*启用用户总量的 25%的功能. 而是在`enabled?`该功能时进行检查`enabled?` ,它将在 25%的时间内返回`true` . + +要为 25%的参与者(例如用户,项目或组)启用功能,请在 Slack 中运行以下命令: + +``` +/chatops run feature set some_feature 25 --actors +``` + +这将根据以下公式将功能标记设置为`true` : + +``` +feature_flag_state = Zlib.crc32("some_feature<Actor>:#{actor.id}") % (100 * 1_000) < 25 * 1_000] +# where <Actor>: is a `User`, `Group`, `Project` and actor is an instance +``` + +在开发过程中,应根据功能的性质来选择演员. + +对于以用户为中心的功能: + +``` +Feature.enabled?(:feature_cool_avatars, current_user) +``` + +对于组或名称空间级别的功能: + +``` +Feature.enabled?(:feature_cooler_groups, group) +``` + +对于项目级别的功能: + +``` +Feature.enabled?(:feature_ice_cold_projects, project) +``` + +如果不确定要使用什么百分比,只需使用以下步骤: + +1. 25% +2. 50% +3. 75% +4. 100% + +在每个步骤之间,您都需要稍等片刻,并在[https://dashboards.gitlab.net](https://dashboards.gitlab.net)上监视适当的图形. 等待的确切时间可能有所不同. 对于某些功能,几分钟就足够了,而对于其他功能,您可能要等待几个小时甚至几天. 这完全取决于您,只要确保将其清楚地传达给您的团队和生产团队即可,如果您预计任何潜在的问题. + +功能门也可以基于`gitlab` ,例如,可以首先仅对`gitlab`项目启用功能. 通过提供`--project`标志来传递项目: + +``` +/chatops run feature set --project=gitlab-org/gitlab some_feature true +``` + +对于组, `--group`标志可用: + +``` +/chatops run feature set --group=gitlab-org some_feature true +``` + +请注意,基于角色的门适用于百分比. 例如,如果您运行以下两个命令,则将`group/project`视为`gitlab-org/gitlab`并将给定的示例功能视为`some_feature` : + +``` +/chatops run feature set --project=gitlab-org/gitlab some_feature true +/chatops run feature set some_feature 25 --actors +``` + +然后将为 25%的参与者同时启用`some_feature` ,并且始终在与`gitlab-org/gitlab`交互时`gitlab-org/gitlab` . 如果特征标记开发使用组参与者,这是一个好主意. + +``` +Feature.enabled?(:some_feature, group) +``` + +**注意:**如果要确保用户始终开启或关闭某项功能,则**时间百分比分布**不是一个好主意. 在这种情况下, **"参与者百分比"**展示是一种更好的方法. + +最后,要在尽可能多的情况下验证该功能被认为是稳定的,您应该通过运行以下命令**全局**启用该标志来全面推出该功能: + +``` +/chatops run feature set some_feature true +``` + +这会将功能标志状态更改为始终**启用** ,从而覆盖上述过程中现有的门(例如`--group=gitlab-org` ). + +### Feature flag change logging[](#feature-flag-change-logging "Permalink") + +任何影响 GitLab.com(生产)的功能标志更改都会自动记录在问题中. + +该问题是在[gl-infra / feature-flag-log](https://gitlab.com/gitlab-com/gl-infra/feature-flag-log/-/issues?scope=all&utf8=✓&state=closed)项目中创建的,它将至少记录启用功能标志的人员的 Slack 句柄,更改的时间和标志的名称. + +然后,该问题还将作为注释标记发布到 GitLab 的内部[Grafana 仪表板上](https://dashboards.gitlab.net/) ,以使更改更加明显. + +问题格式的更改可以在[Chatops 项目中](https://gitlab.com/gitlab-com/chatops)提交. + +## Cleaning up[](#cleaning-up "Permalink") + +更改被视为稳定后,请提交新的合并请求以删除功能标记. 这样可以确保所有用户和自我管理实例都可以使用该更改. 确保在此合并请求中添加〜" feature flag"标签,以便发行经理意识到更改隐藏在 feature 标志的后面. 如果必须将合并请求放入一个稳定的分支中,请确保还添加适当的`~"Pick into XY"`标签(例如`~"Pick into 13.0"` ). 有关更多详细信息,请参见[过程文档](process.html#including-a-feature-behind-feature-flag-in-the-final-release) . + +从代码库中删除功能门后,数据库中仍然存在该标志也已部署的功能记录. 将 MR 部署到每个环境后,可以删除该记录: + +``` +/chatops run feature delete some_feature --dev +/chatops run feature delete some_feature --staging +``` + +Then, you can delete it from production after the MR is deployed to prod: + +``` +/chatops run feature delete some_feature +``` \ No newline at end of file diff --git a/docs/583.md b/docs/583.md new file mode 100644 index 0000000000000000000000000000000000000000..3c839ad39e72801906fea1d8dc1e325264f4b208 --- /dev/null +++ b/docs/583.md @@ -0,0 +1,180 @@ +# Document features deployed behind feature flags + +> 原文:[https://docs.gitlab.com/ee/development/documentation/feature_flags.html](https://docs.gitlab.com/ee/development/documentation/feature_flags.html) + +* [Criteria](#criteria) + * [Features disabled by default](#features-disabled-by-default) + * [Features that became enabled by default](#features-that-became-enabled-by-default) + * [Features directly enabled by default](#features-directly-enabled-by-default) + * [Features with flag removed](#features-with-flag-removed) + +# Document features deployed behind feature flags[](#document-features-deployed-behind-feature-flags "Permalink") + +manbetx 客户端打不开使用[功能标志](../feature_flags/index.html)来战略性地推出自己的功能的部署. 我们在功能标记后面记录功能的方式取决于其状态(启用或禁用). 状态更改时,进行更改的开发人员**必须相应地更新文档** . + +## Criteria[](#criteria "Permalink") + +根据[部署功能标记后的 GitLab 功能](../feature_flags/process.html)的过程: + +> * *默认情况下,功能标志应处于关闭状态.* +> * *功能标记应尽可能短地保留在代码库中,以减少对功能标记记帐的需求.* +> * *为了构建最终版本并为自我管理的用户提供功能,功能标志至少应至少默认为 on.* + +根据标志的状态,请参阅下面的文档说明: + +* [Features disabled by default](#features-disabled-by-default). +* [Features that became enabled by default](#features-that-became-enabled-by-default). +* [Features directly enabled by default](#features-directly-enabled-by-default). +* [Features with the feature flag removed](#features-with-flag-removed). + +**注意:**功能级别的[`**(CORE ONLY)**`](styleguide.html#product-badges)徽标或等效标记应添加到以下行和标题中,即启用/禁用功能标志,因为这样做需要管理员访问权限,因此,它表示不能由 GitLab.com 的普通用户完成. + +### Features disabled by default[](#features-disabled-by-default "Permalink") + +对于默认情况下禁用的功能,如果由于缺乏完整性而无法使用它们,或者仍在内部评估中(例如,出于性能方面的考虑),请**不要对其进行文档化** :仅在以下情况下添加(或合并)文档:该功能是安全的,可供最终用户使用和测试. + +对于默认情况下禁用的功能标志,如果最终用户可以使用它们: + +* 说默认情况下它是禁用的. +* 说是否在 GitLab.com 上启用了它. +* 说说是否可以针对每个项目启用或禁用它. +* 说出是否建议将其用于生产. +* 记录如何启用和禁用它. + +例如,对于默认情况下禁用的功能,可以在每个项目上启用或禁用 GitLab.com 上禁用的功能,并且不准备用于生产环境: + +``` +# Feature Name + > - [Introduced](link-to-issue) in GitLab 12.0. +> - It's deployed behind a feature flag, disabled by default. +> - It's disabled on GitLab.com. +> - It's able to be enabled or disabled per-project +> - It's not recommended for production use. +> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#anchor-to-section). **(CORE ONLY)** + +(...) + +### Enable or disable <Feature Name> **(CORE ONLY)** + +<Feature Name> is under development and not ready for production use. It is +deployed behind a feature flag that is **disabled by default**. +[GitLab administrators with access to the GitLab Rails console](../path/to/administration/feature_flags.md) +can enable it for your instance. <Feature Name> can be enabled or disabled per-project + +To enable it: + +```ruby # Instance-wide +Feature.enable(:<feature flag>) +# or by project +Feature.enable(:<feature flag>, Project.find(<project id>)) +``` + +To disable it: + +```ruby # Instance-wide +Feature.disable(:<feature flag>) +# or by project +Feature.disable(:<feature flag>, Project.find(<project id>)) +``` +``` + +根据要记录的功能的状态来调整 Blur. + +### Features that became enabled by default[](#features-that-became-enabled-by-default "Permalink") + +对于默认启用的功能: + +* 假设默认情况下已启用它. +* 说是否在 GitLab.com 上启用了它. +* 说说是否可以针对每个项目启用或禁用它. +* 说出是否建议将其用于生产. +* 记录如何禁用和启用它. + +例如,对于最初部署时默认情况下禁用的功能,默认情况下已启用,在 GitLab.com 上启用了该功能,该功能无法按项目启用或禁用,并且可以用于生产环境: + +``` +# Feature Name + > - [Introduced](link-to-issue) in GitLab 12.0. +> - It was deployed behind a feature flag, disabled by default. +> - [Became enabled by default](link-to-issue) on GitLab 12.1. +> - It's enabled on GitLab.com. +> - It's not able to be enabled or disabled per-project +> - It's recommended for production use. +> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(CORE ONLY)** + +(...) + +### Enable or disable <Feature Name> **(CORE ONLY)** + +<Feature Name> is under development but ready for production use. +It is deployed behind a feature flag that is **enabled by default**. +[GitLab administrators with access to the GitLab Rails console](..path/to/administration/feature_flags.md) +can opt to disable it for your instance it cannot be enabled or disabled per-project. + +To disable it: + +```ruby Feature.disable(:<feature flag>) +``` + +To enable it: + +```ruby Feature.enable(:<feature flag>) +``` +``` + +根据要记录的功能的状态来调整 Blur. + +### Features directly enabled by default[](#features-directly-enabled-by-default "Permalink") + +对于默认启用的功能: + +* 说默认情况下已启用. +* 说是否在 GitLab.com 上启用了它. +* 说说是否可以针对每个项目启用或禁用它. +* 说出是否建议将其用于生产. +* 记录如何禁用和启用它. + +For example, for a feature enabled by default, enabled on GitLab.com, cannot be enabled or disabled per-project, and ready for production use: + +``` +# Feature Name + > - [Introduced](link-to-issue) in GitLab 12.0. +> - It's deployed behind a feature flag, enabled by default. +> - It's enabled on GitLab.com. +> - It's not able to be enabled or disabled per-project +> - It's recommended for production use. +> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(CORE ONLY)** + +(...) + +### Enable or disable <Feature Name> **(CORE ONLY)** + +<Feature Name> is under development but ready for production use. +It is deployed behind a feature flag that is **enabled by default**. +[GitLab administrators with access to the GitLab Rails console](..path/to/administration/feature_flags.md) +can opt to disable it for your instance. + +To disable it: + +```ruby Feature.disable(:<feature flag>) +``` + +To enable it: + +```ruby Feature.enable(:<feature flag>) +``` +``` + +根据要记录的功能的状态来调整 Blur. + +### Features with flag removed[](#features-with-flag-removed "Permalink") + +功能准备就绪并且标记已删除后,请清理文档. 删除功能标记的提及,只保留一个在版本历史记录注释中提及该标记的注释: + +``` +# Feature Name + > - [Introduced](link-to-issue) in GitLab 12.0. +> - [Feature flag removed](link-to-issue) in GitLab 12.2. + +(...) +``` \ No newline at end of file diff --git a/docs/584.md b/docs/584.md new file mode 100644 index 0000000000000000000000000000000000000000..e78ef7dc7103378837914bc0c11d4c52b317a5af --- /dev/null +++ b/docs/584.md @@ -0,0 +1,127 @@ +# Frontend Development Guidelines + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/](https://docs.gitlab.com/ee/development/fe_guide/) + +* [Overview](#overview) + * [Browser Support](#browser-support) +* [Initiatives](#initiatives) +* [Principles](#principles) +* [Development Process](#development-process) +* [Architecture](#architecture) +* [Testing](#testing) +* [Pajamas Design System](#pajamas-design-system) +* [Design Patterns](#design-patterns) +* [Vue.js Best Practices](#vuejs-best-practices) +* [Vuex](#vuex) +* [Axios](#axios) +* [GraphQL](#graphql) +* [Icons and Illustrations](#icons-and-illustrations) +* [Dependencies](#dependencies) +* [Frontend FAQ](#frontend-faq) +* [Style Guides](#style-guides) +* [Tooling](#tooling) +* [Performance](#performance) +* [Security](#security) +* [Accessibility](#accessibility) +* [Internationalization (i18n) and Translations](#internationalization-i18n-and-translations) + +# Frontend Development Guidelines[](#frontend-development-guidelines "Permalink") + +本文档介绍了各种指南,以确保整个 GitLab 前端团队的一致性和质量. + +## Overview[](#overview "Permalink") + +GitLab 使用[Haml](http://haml.info/)在[Ruby on Rails 的](https://rubyonrails.org)基础上构建,并且还基于[Vue.js](https://vuejs.org)基于 JavaScript 的 Frontend. 注意[使用 Hamlit 所](https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md#limitations)带来[的限制](https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md#limitations) . 我们还将[SCSS](https://sass-lang.com)和普通 JavaScript 与通过[Babel](https://babeljs.io/)支持的现代 ECMAScript 标准一起使用,并通过[webpack](https://webpack.js.org/)支持 ES 模块. + +使用我们的前端资产需要使用 Node(v10.13.0 或更高版本)和 Yarn(v1.10.0 或更高版本). 您可以在我们的[安装指南中](../../install/installation.html#4-node)找到有关如何安装它们的信息. + +### Browser Support[](#browser-support "Permalink") + +对于我们当前支持的浏览器,请参阅我们的[要求](../../install/requirements.html#supported-web-browsers) . + +使用[BrowserStack](https://www.browserstack.com/)来测试我们支持的浏览器. 使用保存在 GitLab [共享 1Password 帐户](https://about.gitlab.com/handbook/security/#1password-guide)的**Engineering**库中的凭据登录到 BrowserStack. + +## Initiatives[](#initiatives "Permalink") + +当前的高级前端目标列在" [前端史诗"中](https://gitlab.com/groups/gitlab-org/-/epics?label_name[]=frontend) . + +## Principles[](#principles "Permalink") + +对 GitLab 做出贡献[的高级指南](principles.html) . + +## Development Process[](#development-process "Permalink") + +我们如何[计划和执行](development_process.html)前端工作. + +## Architecture[](#architecture "Permalink") + +我们如何在 GitLab 的前端团队中[做出基本的设计决策](architecture.html) ,或者对我们的前端开发准则进行更改. + +## Testing[](#testing "Permalink") + +我们如何编写[前端测试](../testing_guide/frontend_testing.html) ,运行 GitLab 测试套件以及调试与测试相关的问题. + +## Pajamas Design System[](#pajamas-design-system "Permalink") + +在我们的[睡衣设计系统中](https://design.gitlab.com/)可以找到具有技术和使用指南的可重复使用组件. + +## Design Patterns[](#design-patterns "Permalink") + +GitLab 代码库中的常见 JavaScript [设计模式](design_patterns.html) . + +## Vue.js Best Practices[](#vuejs-best-practices "Permalink") + +明确具体的[设计模式和实践](vue.html) . + +## Vuex[](#vuex "Permalink") + +[Vuex](vuex.html)特定的设计模式和实践. + +## Axios[](#axios "Permalink") + +[Axios](axios.html)特定的实践和陷阱. + +## GraphQL[](#graphql "Permalink") + +如何使用[GraphQL](graphql.html) . + +## Icons and Illustrations[](#icons-and-illustrations "Permalink") + +我们如何将 SVG 用于我们的[图标和插图](icons.html) . + +## Dependencies[](#dependencies "Permalink") + +有关前端[依赖关系](dependencies.html)以及我们如何管理它们的常规信息. + +## Frontend FAQ[](#frontend-faq "Permalink") + +阅读[前端的常见问题](frontend_faq.html) ,以获取有用的常见小信息. + +## Style Guides[](#style-guides "Permalink") + +请参阅相关的样式指南以获取我们的准则以及有关棉绒的信息: + +* [JavaScript](style/javascript.html) . 我们的指南基于出色的[Airbnb](https://github.com/airbnb/javascript)样式指南,并做了一些小改动. +* [SCSS](style/scss.html) :我们的 SCSS 约定,通过[`scss-lint`](https://github.com/sds/scss-lint) . +* [HTML](style/html.html) . 与其余代码库一致的编写 HTML 代码的准则. +* [Vue](style/vue.html) . 有关 Vue 代码的准则和约定,请参见此处. + +## [Tooling](tooling.html)[](#tooling "Permalink") + +我们的代码会自动使用[Prettier](https://prettier.io)格式化,以遵循我们的准则. 阅读我们的[工具指南](tooling.html)以获取更多详细信息. + +## [Performance](performance.html)[](#performance "Permalink") + +监视和最大化前端性能的最佳实践. + +## [Security](security.html)[](#security "Permalink") + +前端安全实践. + +## [Accessibility](accessibility.html)[](#accessibility "Permalink") + +我们的无障碍标准和资源. + +## [Internationalization (i18n) and Translations](../i18n/externalization.html)[](#internationalization-i18n-and-translations "Permalink") + +[本文档](../i18n/)介绍了前端国际化支持. [指南](../i18n/externalization.html)的[外部化部分](../i18n/externalization.html)介绍了可用的帮助程序/方法. \ No newline at end of file diff --git a/docs/585.md b/docs/585.md new file mode 100644 index 0000000000000000000000000000000000000000..c06d4b613570e455f0d6668906cd0f12943e75ef --- /dev/null +++ b/docs/585.md @@ -0,0 +1,15 @@ +# Accessibility & Readability + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/accessibility.html](https://docs.gitlab.com/ee/development/fe_guide/accessibility.html) + +* [Resources](#resources) + +# Accessibility & Readability[](#accessibility--readability "Permalink") + +## Resources[](#resources "Permalink") + +[Chrome 可访问性开发人员工具](https://github.com/GoogleChrome/accessibility-developer-tools)对于在 GitLab 中测试潜在的可访问性问题很有用. + +[斧头](https://www.deque.com/axe/)浏览器扩展程序(适用于[Firefox](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/)和[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd) )也是一种便捷的工具,可用于运行审核并获取有关标记,CSS 甚至可能存在问题的颜色使用情况的反馈. + +可访问性最佳做法和更深入的信息可在 Chrome 可访问性开发人员工具[的"审核规则"页面上](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules)找到. " [超棒可访问性"](https://github.com/brunopulis/awesome-a11y)列表也是可访问性相关材料的有用汇编. \ No newline at end of file diff --git a/docs/586.md b/docs/586.md new file mode 100644 index 0000000000000000000000000000000000000000..8205dab976fbf8962b0e5544b4b26c02bd3c17ff --- /dev/null +++ b/docs/586.md @@ -0,0 +1,43 @@ +# Ajax + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/droplab/plugins/ajax.html](https://docs.gitlab.com/ee/development/fe_guide/droplab/plugins/ajax.html) + +* [Usage](#usage) + +# Ajax[](#ajax "Permalink") + +`Ajax`是一个 droplab 插件,允许从服务器检索和呈现列表数据. + +## Usage[](#usage "Permalink") + +将`Ajax`对象添加到`DropLab.prototype.init`或`DropLab.prototype.addHook`调用的 plugins 数组中. + +`Ajax`需要 2 个配置值, `endpoint`和`method` . + +* `endpoint`应该是请求端点的 URL. +* `method`应为`setData`或`addData` . +* `setData`将下拉列表完全替换为响应数据. +* `addData`将响应数据追加到当前下拉列表中. + +``` +<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a> +<ul id="list" data-dropdown><!-- ... --><ul> +``` + +``` +const droplab = new DropLab(); + +const trigger = document.getElementById('trigger'); +const list = document.getElementById('list'); + +droplab.addHook(trigger, list, [Ajax], { + Ajax: { + endpoint: '/some-endpoint', + method: 'setData', + }, +}); +``` + +(可选)您可以将`loadingTemplate`设置为 HTML 字符串. 请求待处理时,此 HTML 字符串将替换下拉列表. + +此外,您可以将`onError`设置为捕获任何 XHR 错误的函数. \ No newline at end of file diff --git a/docs/587.md b/docs/587.md new file mode 100644 index 0000000000000000000000000000000000000000..4996a0843761fb38bc0c38ba48114d5892d6e7d8 --- /dev/null +++ b/docs/587.md @@ -0,0 +1,19 @@ +# Architecture + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/architecture.html](https://docs.gitlab.com/ee/development/fe_guide/architecture.html) + +* [Examples](#examples) + +# Architecture[](#architecture "Permalink") + +在开发需要架构设计的新功能时,或者在更改现有功能的基本设计时,请确保与前端​​架构专家之一进行了讨论. + +前端架构师是一位专家,负责制定高层的前端设计决策并决定技术标准,包括编码标准和框架. + +每个人都应该可以了解体系结构决策,因此请在相关的"合并请求"讨论中记录它们,或者在适当时更新我们的文档. + +您可以在[团队页面](https://about.gitlab.com/company/team/)上找到 Frontend Architecture 专家. + +## Examples[](#examples "Permalink") + +您可以[在此处](vue.html)找到有关使用 Vue.js 构建的新功能所需架构的文档. \ No newline at end of file diff --git a/docs/588.md b/docs/588.md new file mode 100644 index 0000000000000000000000000000000000000000..2e3331b6a235c8d0a6a8b1fd582706564d571ebf --- /dev/null +++ b/docs/588.md @@ -0,0 +1,85 @@ +# Axios + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/axios.html](https://docs.gitlab.com/ee/development/fe_guide/axios.html) + +* [CSRF token](#csrf-token) +* [Usage](#usage) +* [Mock Axios response in tests](#mock-axios-response-in-tests) + * [Example](#example) + * [Mock poll requests in tests with Axios](#mock-poll-requests-in-tests-with-axios) + +# Axios[](#axios "Permalink") + +我们使用[Axios](https://github.com/axios/axios)在 Vue 应用程序和大多数新代码中与服务器进行通信. + +为了确保设置了所有默认值,您不应*直接使用 Axios* ,而应从`axios_utils`导入 Axios. + +## CSRF token[](#csrf-token "Permalink") + +我们所有的请求都需要 CSRF 令牌. 为了确保设置此令牌,我们将导入[Axios](https://github.com/axios/axios) ,设置令牌并导出`axios` . + +应该使用此导出模块,而不是直接使用 Axios 以确保已设置令牌. + +## Usage[](#usage "Permalink") + +``` + import axios from './lib/utils/axios_utils'; + + axios.get(url) + .then((response) => { + // `data` is the response that was provided by the server + const data = response.data; + + // `headers` the headers that the server responded with + // All header names are lower cased + const paginationData = response.headers; + }) + .catch(() => { + //handle the error + }); +``` + +## Mock Axios response in tests[](#mock-axios-response-in-tests "Permalink") + +为了帮助我们模拟响应,我们使用[axios-mock-adapter](https://github.com/ctimmerm/axios-mock-adapter) . + +比[`spyOn()`](https://jasmine.github.io/api/edge/global.html#spyOn)优势: + +* 无需创建响应对象 +* 不允许通话(我们要避免) +* 简单的 API 来测试错误情况 +* 提供`replyOnce()`以允许不同的响应 + +我们还决定不使用[Axios 拦截器,](https://github.com/axios/axios#interceptors)因为它们不适合模拟. + +### Example[](#example "Permalink") + +``` + import axios from '~/lib/utils/axios_utils'; + import MockAdapter from 'axios-mock-adapter'; + + let mock; + beforeEach(() => { + // This sets the mock adapter on the default instance + mock = new MockAdapter(axios); + // Mock any GET request to /users + // arguments for reply are (status, data, headers) + mock.onGet('/users').reply(200, { + users: [ + { id: 1, name: 'John Smith' } + ] + }); + }); + + afterEach(() => { + mock.restore(); + }); +``` + +### Mock poll requests in tests with Axios[](#mock-poll-requests-in-tests-with-axios "Permalink") + +因为轮询功能需要一个标头对象,所以我们需要始终包含一个对象作为第三个参数: + +``` + mock.onGet('/users').reply(200, { foo: 'bar' }, {}); +``` \ No newline at end of file diff --git a/docs/589.md b/docs/589.md new file mode 100644 index 0000000000000000000000000000000000000000..a96005fac39f4556d02d30c7461f42b0208f4088 --- /dev/null +++ b/docs/589.md @@ -0,0 +1,81 @@ +# Design Patterns + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/design_patterns.html](https://docs.gitlab.com/ee/development/fe_guide/design_patterns.html) + +* [Singletons](#singletons) +* [Manipulating the DOM in a JS Class](#manipulating-the-dom-in-a-js-class) + +# Design Patterns[](#design-patterns "Permalink") + +## Singletons[](#singletons "Permalink") + +当给定任务仅需要一个对象时,最好将其定义为`class`而不是对象文字. 除非灵活性很重要(例如,对于测试),否则也最好明确限制实例化. + +``` +// bad + +const MyThing = { + prop1: 'hello', + method1: () => {} +}; + +export default MyThing; + +// good + +class MyThing { + constructor() { + this.prop1 = 'hello'; + } + method1() {} +} + +export default new MyThing(); + +// best + +export default class MyThing { + constructor() { + if (!MyThing.prototype.singleton) { + this.init(); + MyThing.prototype.singleton = this; + } + return MyThing.prototype.singleton; + } + + init() { + this.prop1 = 'hello'; + } + + method1() {} +} +``` + +## Manipulating the DOM in a JS Class[](#manipulating-the-dom-in-a-js-class "Permalink") + +在编写需要处理 DOM 的类时,请确保提供了一个容器选项. 当我们需要在同一页面中多次实例化该类时,这很有用. + +Bad: + +``` +class Foo { + constructor() { + document.querySelector('.bar'); + } +} +new Foo(); +``` + +Good: + +``` +class Foo { + constructor(opts) { + document.querySelector(`${opts.container} .bar`); + } +} + +new Foo({ container: '.my-element' }); +``` + +您可以在这上面的例子[类](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/javascripts/mini_pipeline_graph_dropdown.js) ; \ No newline at end of file diff --git a/docs/590.md b/docs/590.md new file mode 100644 index 0000000000000000000000000000000000000000..adf7e20d3ac3a3e4383cff22eda647db47a73dc7 --- /dev/null +++ b/docs/590.md @@ -0,0 +1,98 @@ +# Frontend Development Process + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/development_process.html](https://docs.gitlab.com/ee/development/fe_guide/development_process.html) + +* [Development Checklist](#development-checklist) + * [Merge Request Review](#merge-request-review) + * [Share your work early](#share-your-work-early) + * [Vue features](#vue-features) + +# Frontend Development Process[](#frontend-development-process "Permalink") + +您可以在[手册中](https://about.gitlab.com/handbook/engineering/frontend/)找到有关前端团队组织的更多信息. + +## Development Checklist[](#development-checklist "Permalink") + +这个想法是在构建新功能或启动某些东西时提醒我们有关特定主题的信息. 这是其他行业(如飞行员)的常见做法,这些行业也使用标准化清单来尽早减少问题. + +将内容复制到您的问题或合并请求中,如果不适用,则将其从当前列表中删除. + +此清单旨在在开发更大的功能/重构时为我们提供帮助,而不是"始终使用它,并且每个点始终匹配"列表. + +请在使用时做出最好的判断,如果有想法请通过合并请求贡献新的积分. + +``` +### Frontend development + +#### Planning development + - [ ] Check the current set weight of the issue, does it fit your estimate? +- [ ] Are all [departments](https://about.gitlab.com/handbook/engineering/#engineering-teams) that are needed from your perspective already involved in the issue? (For example is UX missing?) +- [ ] Is the specification complete? Are you missing decisions? How about error handling/defaults/edge cases? Take your time to understand the needed implementation and go through its flow. +- [ ] Are all necessary UX specifications available that you will need in order to implement? Are there new UX components/patterns in the designs? Then contact the UI component team early on. How should error messages or validation be handled? +- [ ] **Library usage** Use Vuex as soon as you have even a medium state to manage, use Vue router if you need to have different views internally and want to link from the outside. Check what libraries we already have for which occasions. +- [ ] **Plan your implementation:** + - [ ] **Architecture plan:** Create a plan aligned with GitLab's architecture, how you are going to do the implementation, for example Vue application setup and its components (through [onion skinning](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35873#note_39994091)), Store structure and data flow, which existing Vue components can you reuse. It's a good idea to go through your plan with another engineer to refine it. + - [ ] **Backend:** The best way is to kickoff the implementation in a call and discuss with the assigned Backend engineer what you will need from the backend and also when. Can you reuse existing API's? How is the performance with the planned architecture? Maybe create together a JSON mock object to already start with development. + - [ ] **Communication:** It also makes sense to have for bigger features an own slack channel (normally called #f_{feature_name}) and even weekly demo calls with all people involved. + - [ ] **Dependency Plan:** Are there big dependencies in the plan between you and others, then maybe create an execution diagram to show what is blocking which part and the order of the different parts. + - [ ] **Task list:** Create a simple checklist of the subtasks that are needed for the implementation, also consider creating even sub issues. (for example show a comment, delete a comment, update a comment, etc.). This helps you and also everyone else following the implementation +- [ ] **Keep it small** To make it easier for you and also all reviewers try to keep merge requests small and merge into a feature branch if needed. To accomplish that you need to plan that from the start. Different methods are: + - [ ] **Skeleton based plan** Start with an MR that has the skeleton of the components with placeholder content. In following MRs you can fill the components with interactivity. This also makes it easier to spread out development on multiple people. + - [ ] **Cookie Mode** Think about hiding the feature behind a cookie flag if the implementation is on top of existing features + - [ ] **New route** Are you refactoring something big then you might consider adding a new route where you implement the new feature and when finished delete the current route and rename the new one. (for example 'merge_request' and 'new_merge_request') +- [ ] **Setup** Is there any specific setup needed for your implementation (for example a kubernetes cluster)? Then let everyone know if it is not already mentioned where they can find documentation (if it doesn't exist - create it) +- [ ] **Security** Are there any new security relevant implementations? Then please contact the security team for an app security review. If you are not sure ask our [domain expert](https://about.gitlab.com/handbook/engineering/frontend/#frontend-domain-experts) + +#### During development + - [ ] Check off tasks on your created task list to keep everyone updated on the progress +- [ ] [Share your work early with reviewers/maintainers](#share-your-work-early) +- [ ] Share your work with UXer and Product Manager with Screenshots and/or [GIF's](https://about.gitlab.com/handbook/product/making-gifs/). They are easy to create for you and keep them up to date. +- [ ] If you are blocked on something let everyone on the issue know through a comment. +- [ ] Are you unable to work on this issue for a longer period of time, also let everyone know. +- [ ] **Documentation** Update/add docs for the new feature, see `docs/`. Ping one of the documentation experts/reviewers + +#### Finishing development + Review + - [ ] **Keep it in the scope** Try to focus on the actual scope and avoid a scope creep during review and keep new things to new issues. +- [ ] **Performance** Have you checked performance? For example do the same thing with 500 comments instead of 1\. Document the tests and possible findings in the MR so a reviewer can directly see it. +- [ ] Have you tested with a variety of our [supported browsers](../../install/requirements.md#supported-web-browsers)? You can use [browserstack](https://www.browserstack.com/) to be able to access a wide variety of browsers and operating systems. +- [ ] Did you check the mobile view? +- [ ] Check the built webpack bundle (For the report run `WEBPACK_REPORT=true gdk run`, then open `webpack-report/index.html`) if we have unnecessary bloat due to wrong references, including libraries multiple times, etc.. If you need help contact the webpack [domain expert](https://about.gitlab.com/handbook/engineering/frontend/#frontend-domain-experts) +- [ ] **Tests** Not only greenfield tests - Test also all bad cases that come to your mind. +- [ ] If you have multiple MR's then also smoke test against the final merge. +- [ ] Are there any big changes on how and especially how frequently we use the API then let production know about it +- [ ] Smoke test of the RC on dev., staging., canary deployments and .com +- [ ] Follow up on issues that came out of the review. Create issues for discovered edge cases that should be covered in future iterations. +``` + +### Merge Request Review[](#merge-request-review "Permalink") + +为了[尊重他人的时间,](https://about.gitlab.com/handbook/values/#be-respectful-of-others-time)在进行审核[时,](https://about.gitlab.com/handbook/values/#be-respectful-of-others-time)请遵循以下准则: + +* 确保您的合并请求: + * 里程碑已设定 + * 至少设置了危险机器人建议的标签 + * 有清晰的描述 + * 如果 UI 发生更改,则包括屏幕截图之前/之后 + * 管道是绿色的 + * 包括测试 + * 包括变更日志条目(必要时) +* 在分配给维护者之前,请分配给审阅者. +* 如果您分配了合并请求或直接对某人执行 ping 操作,请耐心等待,因为我们在不同时区且异步工作. 除非紧急合并请求(例如修复损坏的主服务器),否则请不要 DM 或重新分配合并请求,然后再等待 24 小时窗口. +* 如果您对合并请求/问题有疑问,请在合并请求/问题中提出. 当我们彼此进行 DM 交流时,我们将不再拥有 SSOT,并且[其他人也无法做出贡献](https://about.gitlab.com/handbook/values/#public-by-default) . +* 如果您有一个包含许多更改的大型**Draft**合并请求,建议您在添加/删除重要代码之前开始审阅. 确保在发布截止日期之前就已对其进行了分配,因为审阅者/维护者将始终优先于**草稿中**优先审阅已完成的 MR. +* 确保在上一轮审核之前删除" `Draft:`标题. + +### Share your work early[](#share-your-work-early "Permalink") + +1. 在编写代码之前,请确保您对体系结构的了解与 GitLab 的体系结构保持一致. +2. Add a diagram to the issue and ask a frontend maintainer in the Slack channel `#frontend_maintainers` about it. + + [![Diagram of Issue Boards Architecture](img/11b32b9624ee5e827950dd6f126127d6.png)](img/boards_diagram.png) + +3. 从开始一项功能到与审阅者或维护者共享"合并请求"之间的时间不要超过一周. + +### Vue features[](#vue-features "Permalink") + +1. 请遵循[Vue.js 最佳做法中](vue.html)的步骤 +2. 遵循样式指南. +3. 仅有少数几个人可以合并 Vue 相关功能. 在此过程的早期,请一位 Vue 专家联系. \ No newline at end of file diff --git a/docs/591.md b/docs/591.md new file mode 100644 index 0000000000000000000000000000000000000000..e4ce82cba6f914a3595249841cdf1bc0ab6f74e5 --- /dev/null +++ b/docs/591.md @@ -0,0 +1,259 @@ +# DropLab + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/droplab/droplab.html](https://docs.gitlab.com/ee/development/fe_guide/droplab/droplab.html) + +* [Usage](#usage) + * [Static data](#static-data) + * [Explicit instantiation](#explicit-instantiation) + * [Dynamic data](#dynamic-data) +* [Internal selectors](#internal-selectors) +* [Internal events](#internal-events) +* [Plugins](#plugins) + * [Usage](#usage-1) + * [Documentation](#documentation) + * [Development](#development) + +# DropLab[](#droplab "Permalink") + +满足您所有自定义下拉菜单需求的通用下拉菜单. + +## Usage[](#usage "Permalink") + +只需添加`data-dropdown-trigger` HTML 属性即可使用 DropLab. 此属性使我们能够找到下拉菜单的"触发" *(切换)* ,无论是按钮,链接还是输入. + +`data-dropdown-trigger`应该是 DropLab 可以用来查找触发器的下拉列表的 CSS 选择器. + +您还应该添加`data-dropdown`属性以声明下拉列表. 该值无关紧要. + +DropLab 类没有副作用,因此在 DOM 准备就绪时,必须始终调用`.init` . `DropLab.prototype.init`的参数与`DropLab.prototype.addHook`相同. 如果不提供任何参数,它将全局查询并实例化所有与 droplab 兼容的下拉菜单. + +``` +<a href="#" data-dropdown-trigger="#list">Toggle</a> + +<ul id="list" data-dropdown> + <!-- ... --> +<ul> +``` + +``` +const droplab = new DropLab(); +droplab.init(); +``` + +As you can see, we have a “Toggle” link, that is declared as a trigger. It provides a selector to find the dropdown list it should control. + +### Static data[](#static-data "Permalink") + +您可以添加静态列表项. + +``` +<a href="#" data-dropdown-trigger="#list">Toggle</a> + +<ul id="list" data-dropdown> + <li>Static value 1</li> + <li>Static value 2</li> +<ul> +``` + +``` +const droplab = new DropLab(); +droplab.init(); +``` + +### Explicit instantiation[](#explicit-instantiation "Permalink") + +您可以使用`DropLab.prototype.init`方法将 trigger 和 list 元素作为构造函数参数传递,以返回 DropLab 的非全局实例. + +``` +<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a> + +<ul id="list" data-dropdown> + <!-- ... --> +<ul> +``` + +``` +const trigger = document.getElementById('trigger'); +const list = document.getElementById('list'); + +const droplab = new DropLab(); +droplab.init(trigger, list); +``` + +您还可以使用`DropLab.prototype.addHook`将挂钩添加到现有的 DropLab 实例. + +``` +<a href="#" data-dropdown-trigger="#auto-dropdown">Toggle</a> +<ul id="auto-dropdown" data-dropdown><!-- ... --><ul> + +<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a> +<ul id="list" data-dropdown><!-- ... --><ul> +``` + +``` +const droplab = new DropLab(); + +droplab.init(); + +const trigger = document.getElementById('trigger'); +const list = document.getElementById('list'); + +droplab.addHook(trigger, list); +``` + +### Dynamic data[](#dynamic-data "Permalink") + +将`data-dynamic`添加到下拉元素将启用动态列表呈现. + +您可以使用提供的数据对象的键对列表项进行模板化. 使用车把语法`{{ value }}`使 HTML 转义该值. 使用`<%= value %>`语法可以简单地插值. 使用`<%= value %>`语法评估该值. + +将对象数组传递给`DropLab.prototype.addData`将为该 DropLab 实例跟踪的所有`data-dynamic`下拉列表呈现该数据. + +``` +<a href="#" data-dropdown-trigger="#list">Toggle</a> + +<ul id="list" data-dropdown data-dynamic> + <li><a href="#" data-id="{{id}}">{{text}}</a></li> +</ul> +``` + +``` +const droplab = new DropLab(); + +droplab.init().addData([{ + id: 0, + text: 'Jacob', +}, { + id: 1, + text: 'Jeff', +}]); +``` + +或者,您可以指定一个特定的下拉菜单,以将数据添加到该数据,但将数据作为第二个参数传递,并将 trigger 元素的`id`作为第一个参数传递. + +``` +<a href="#" data-dropdown-trigger="#list" id="trigger">Toggle</a> + +<ul id="list" data-dropdown data-dynamic> + <li><a href="#" data-id="{{id}}">{{text}}</a></li> +</ul> +``` + +``` +const droplab = new DropLab(); + +droplab.init().addData('trigger', [{ + id: 0, + text: 'Jacob', +}, { + id: 1, + text: 'Jeff', +}]); +``` + +这使您可以轻松混合静态和动态内容,即使使用一个触发器也是如此. + +请注意,在有关`data-dropdown`属性的范围内使用范围来捕获两个下拉列表,其中之一是动态的. + +``` +<input id="trigger" data-dropdown-trigger="#list"> +<div id="list" data-dropdown> + <ul> + <li><a href="#">Static item 1</a></li> + <li><a href="#">Static item 2</a></li> + </ul> + <ul data-dynamic> + <li><a href="#" data-id="{{id}}">{{text}}</a></li> + </ul> +</div> +``` + +``` +const droplab = new DropLab(); + +droplab.init().addData('trigger', [{ + id: 0, + text: 'Jacob', +}, { + id: 1, + text: 'Jeff', +}]); +``` + +## Internal selectors[](#internal-selectors "Permalink") + +DropLab 添加了一些 CSS 类,以帮助降低集成的障碍. + +例如: + +* 将`droplab-item-selected` CSS 类添加到通过单击鼠标或 Enter 键选择的项目中. +* 将`droplab-item-active` CSS 类添加到使用箭头键导航选择的项目中. +* 您可以将`droplab-item-ignore` CSS 类添加到您不想选择的任何项目中. 例如,一个不应为交互式的`<li class="divider"></li>`列表分隔符元素. + +## Internal events[](#internal-events "Permalink") + +DropLab 使用一些自定义事件来帮助降低集成障碍. + +例如: + +* 单击`li`列表项时会触发`click.dl`事件. 当使用键盘选择了列表项时,也会触发该事件. 当它也烧`HookButton`按键(注册`button`标签或`a`标签触发). +* 所述`input.dl`当事件被触发`HookInput` (注册`input`标签触发)触发`input`事件. +* 该`mousedown.dl`当事件被触发`HookInput`触发`mousedown`事件. +* 该`keyup.dl`当事件被触发`HookInput`触发`keyup`事件. +* 该`keydown.dl`当事件被触发`HookInput`触发`keydown`事件. + +这些自定义事件将`detail`对象添加到提供一些潜在有用数据的原始`Event`对象. + +## Plugins[](#plugins "Permalink") + +插件是添加钩子后被注册为要执行的对象(实例化 droplab 触发器和下拉菜单时). + +如果未检测到模块 API,则该库将像使用`window.DropLab`那样回退,并添加`window.DropLab.plugins.PluginName` . + +### Usage[](#usage-1 "Permalink") + +要使用插件,您可以将它们作为`DropLab.prototype.init`或`DropLab.prototype.addHook`的第三个参数传递给数组. 一些插件需要配置值,可以将 config 对象作为第四个参数传递. + +``` +<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a> +<ul id="list" data-dropdown><!-- ... --><ul> +``` + +``` +const droplab = new DropLab(); + +const trigger = document.getElementById('trigger'); +const list = document.getElementById('list'); + +droplab.init(trigger, list, [droplabAjax], { + droplabAjax: { + endpoint: '/some-endpoint', + method: 'setData', + }, +}); +``` + +### Documentation[](#documentation "Permalink") + +* [Ajax plugin](plugins/ajax.html) +* [Filter plugin](plugins/filter.html) +* [InputSetter plugin](plugins/input_setter.html) + +### Development[](#development "Permalink") + +当为 droplab 触发器+下拉菜单初始化插件时,DropLab 将调用插件的`init`函数,因此必须在插件中实现. + +``` +class MyPlugin { + static init() { + this.someProp = 'someProp'; + this.someMethod(); + } + + static someMethod() { + this.otherProp = 'otherProp'; + } +} + +export default MyPlugin; +``` \ No newline at end of file diff --git a/docs/592.md b/docs/592.md new file mode 100644 index 0000000000000000000000000000000000000000..34771b9fee35acf1a38e7e061da9869b52c0e774 --- /dev/null +++ b/docs/592.md @@ -0,0 +1,25 @@ +# Emojis + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/emojis.html](https://docs.gitlab.com/ee/development/fe_guide/emojis.html) + +* [How to update Emojis](#how-to-update-emojis) + +# Emojis[](#emojis "Permalink") + +GitLab 支持本机 Unicode 表情符号,当您的平台不支持它时,它有选择地回退到基于图像的表情符号. + +## How to update Emojis[](#how-to-update-emojis "Permalink") + +1. 更新`gemojione`宝石 +2. 从[Gemojione](https://github.com/bonusly/gemojione/blob/master/config/index.json)更新`fixtures/emojis/index.json` [emojis](https://github.com/bonusly/gemojione/blob/master/config/index.json) `fixtures/emojis/index.json` . 将来,我们可以直接从 gem 获取文件. 我们可能应该对 Gemojione 项目进行 PR,以在解析后获得对所有表情符号的访问权,或者仅获取`json`文件本身的原始路径. +3. 确保[`emoji-unicode-version`](https://s0www0npmjs0com.icopy.site/package/emoji-unicode-version)是最新版本. +4. Run `bundle exec rake gemojione:aliases` +5. Run `bundle exec rake gemojione:digests` +6. Run `bundle exec rake gemojione:sprite` +7. 确保为 1x 和 2x 生成新的 Sprite 表 + * `app/assets/images/emoji.png` + * `app/assets/images/emoji@2x.png` +8. 确保您看到新的单个图像复制到`app/assets/images/emoji/` +9. 确保您可以在 GFM 自动完成功能中看到新的表情符号及其别名 +10. 确保您可以在奖励表情符号菜单中看到新的表情符号及其别名 +11. 您可能需要为不支持某些表情符号的平台添加新的表情符号 Unicode 支持检查和规则,我们需要回退到图像. 请参阅`app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js`和`app/assets/javascripts/emoji/support/unicode_support_map.js` \ No newline at end of file diff --git a/docs/593.md b/docs/593.md new file mode 100644 index 0000000000000000000000000000000000000000..a58e40f63e4b6843e2386f898df169a1333f71d5 --- /dev/null +++ b/docs/593.md @@ -0,0 +1,48 @@ +# Filter + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/droplab/plugins/filter.html](https://docs.gitlab.com/ee/development/fe_guide/droplab/plugins/filter.html) + +* [Usage](#usage) + +# Filter[](#filter "Permalink") + +`Filter`是一个插件,它允许使用简单的模糊字符串搜索输入值来过滤已添加到下拉列表中的数据. + +## Usage[](#usage "Permalink") + +将`Filter`对象添加到`DropLab.prototype.init`或`DropLab.prototype.addHook`调用的插件数组中. + +* `Filter`需要`template`的配置值. +* `template`应该是要与用户输入字符串进行比较以进行过滤的数据数组中对象的键. + +``` +<input href="#" id="trigger" data-dropdown-trigger="#list"> +<ul id="list" data-dropdown data-dynamic> + <li><a href="#" data-id="{{id}}">{{text}}</a></li> +<ul> +``` + +``` +const droplab = new DropLab(); + +const trigger = document.getElementById('trigger'); +const list = document.getElementById('list'); + +droplab.init(trigger, list, [Filter], { + Filter: { + template: 'text', + }, +}); + +droplab.addData('trigger', [{ + id: 0, + text: 'Jacob', +}, { + id: 1, + text: 'Jeff', +}]); +``` + +上面,输入字符串将与传递的数据对象的`test`键进行比较. + +您可以选择将`filterFunction`设置为一个函数. 将使用此函数代替`Filter`的内置字符串搜索. `filterFunction`传递了 2 个参数,第一个是数据对象之一,第二个是当前输入值. \ No newline at end of file diff --git a/docs/594.md b/docs/594.md new file mode 100644 index 0000000000000000000000000000000000000000..e67f4113a5a7ea80a61e3c76c0a776bf214fc9ce --- /dev/null +++ b/docs/594.md @@ -0,0 +1,146 @@ +# Frontend FAQ + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/frontend_faq.html](https://docs.gitlab.com/ee/development/fe_guide/frontend_faq.html) + +* [Rules of Frontend FAQ](#rules-of-frontend-faq) +* [FAQ](#faq) + * [1\. How do I find the Rails route for a page?](#1-how-do-i-find-the-rails-route-for-a-page) + * [Check the ‘page’ data attribute](#check-the-page-data-attribute) + * [Rails routes](#rails-routes) + * [2\. `modal_copy_button` vs `clipboard_button`](#2-modal_copy_button-vs-clipboard_button) + * [3\. A `gitlab-ui` component not conforming to Pajamas Design System](#3-a-gitlab-ui-component-not-conforming-to-pajamas-design-system) + * [4\. My submit form button becomes disabled after submitting](#4-my-submit-form-button-becomes-disabled-after-submitting) + * [5\. Should I use a full URL (i.e. `gon.gitlab_url`) or a full path (i.e. `gon.relative_url_root`) when referencing backend endpoints?](#5-should-i-use-a-full-url-ie-gongitlab_url-or-a-full-path-ie-gonrelative_url_root-when-referencing-backend-endpoints) + * [6\. How should the Frontend reference Backend paths?](#6-how-should-the-frontend-reference-backend-paths) + * [7\. How can I test the production build locally?](#7-how-can-i-test-the-production-build-locally) + +# Frontend FAQ[](#frontend-faq "Permalink") + +## Rules of Frontend FAQ[](#rules-of-frontend-faq "Permalink") + +1. **您谈论前端常见问题解答.** 请在适当的情况下共享指向它的链接,以便在内容过时时引起更多关注. +2. **保持简短和简单.** 只要答案需要两个以上的句子,它就不属于这里. +3. **尽可能提供背景.** 链接到相关的源代码,问题/史诗或其他文档有助于理解答案. +4. **如果您看到某些内容,请执行某些操作.** 看到后,请删除或更新任何过时的内容. + +## FAQ[](#faq "Permalink") + +### 1\. How do I find the Rails route for a page?[](#1-how-do-i-find-the-rails-route-for-a-page "Permalink") + +#### Check the ‘page’ data attribute[](#check-the-page-data-attribute "Permalink") + +最简单的方法是在相关页面上的浏览器中键入以下内容: + +``` +document.body.dataset.page +``` + +在此处找到[设置属性](https://gitlab.com/gitlab-org/gitlab/blob/cc5095edfce2b4d4083a4fb1cdc7c0a1898b9921/app/views/layouts/application.html.haml#L4)的[源代码](https://gitlab.com/gitlab-org/gitlab/blob/cc5095edfce2b4d4083a4fb1cdc7c0a1898b9921/app/views/layouts/application.html.haml#L4) . + +#### Rails routes[](#rails-routes "Permalink") + +The `rake routes` command can be used to list all the routes available in the application, piping the output into `grep`, we can perform a search through the list of available routes. The output includes the request types available, route parameters and the relevant controller. + +``` +bundle exec rake routes | grep "issues" +``` + +### 2\. `modal_copy_button` vs `clipboard_button`[](#2-modal_copy_button-vs-clipboard_button "Permalink") + +该`clipboard_button`使用`copy_to_clipboard.js`行为,这是在页面加载初始化,所以如果有不会在页面加载存在(如那些在基于 VUE 剪贴板按钮`GlModal` ),他们没有相关的点击处理程序与剪贴板包. + +添加了`modal_copy_button` ,用于管理特定于该组件实例的[`clipboard`插件](https://s0www0npmjs0com.icopy.site/package/clipboard)的实例,这意味着剪贴板事件在安装时绑定并在按钮按下时销毁,从而减轻了上述问题. 它还具有绑定到可用的特定容器或模式 ID 的功能,以与我们的 GlModal 创建的焦点陷阱一起使用. + +### 3\. A `gitlab-ui` component not conforming to [Pajamas Design System](https://design.gitlab.com/)[](#3-a-gitlab-ui-component-not-conforming-to-pajamas-design-system "Permalink") + +`gitlab-ui`实现的某些[睡衣设计系统](https://design.gitlab.com/)组件不符合设计系统规范,因为它们缺少某些计划的功能或样式尚未正确. 在睡衣网站上,组件示例顶部的标语指示: + +> 该组件尚未符合我们设计系统中定义的正确样式. 引用此组件的外观时,请参考 Design System 文档. + +例如,在撰写本文时,可以针对[所有表单组件](https://design.gitlab.com/components/forms/)观察到这种类型的警告. 但是,这并不意味着不应使用该组件. + +只要有合适的组件,GitLab 都会要求使用`<gl-*>`组件. 它使代码库变得统一,并且将来可以更轻松地进行维护/重构. + +确保[产品设计师](https://about.gitlab.com/company/team/?department=ux-department)在 MR 审查中审查不合格组件的使用. 提出后续问题,并将其附加到" [睡衣设计系统组件"](https://gitlab.com/groups/gitlab-org/-/epics/973)史诗中的组件实现[史诗中](https://gitlab.com/groups/gitlab-org/-/epics/973) . + +### 4\. My submit form button becomes disabled after submitting[](#4-my-submit-form-button-becomes-disabled-after-submitting "Permalink") + +如果在表单内使用提交按钮,并且在表单元素上附加了`onSubmit`事件侦听器,则[这段代码](https://gitlab.com/gitlab-org/gitlab/blob/794c247a910e2759ce9b401356432a38a4535d49/app/assets/javascripts/main.js#L225)将在提交表单时向提交按钮添加一个`disabled`类选择器. 为避免这种情况,请将`js-no-auto-disable`类添加到按钮. + +### 5\. Should I use a full URL (i.e. `gon.gitlab_url`) or a full path (i.e. `gon.relative_url_root`) when referencing backend endpoints?[](#5-should-i-use-a-full-url-ie-gongitlab_url-or-a-full-path-ie-gonrelative_url_root-when-referencing-backend-endpoints "Permalink") + +最好在**完整 URL**上使用**完整路径** ,因为 URL 将使用通过 GitLab 配置的主机名,该主机名可能与请求不匹配. 这将导致[像 Web IDE 这样的 CORS 问题](https://gitlab.com/gitlab-org/gitlab/-/issues/36810) . + +Example: + +``` +// bad :( +// If gitlab is configured with hostname `0.0.0.0` +// This will cause CORS issues if I request from `localhost` +axios.get(joinPaths(gon.gitlab_url, '-', 'foo')) + +// good :) +axios.get(joinPaths(gon.relative_url_root, '-', 'foo')) +``` + +另外,请尽量不要在前端中对路径进行硬编码,而应从后端接收它们(请参阅下一节). 引用后端导轨路径时,请避免使用`*_url` ,而应使用`*_path` . + +Example: + +``` +-# Bad :( #js-foo{ data: { foo_url: some_rails_foo_url } } + +-# Good :) #js-foo{ data: { foo_path: some_rails_foo_path } } +``` + +### 6\. How should the Frontend reference Backend paths?[](#6-how-should-the-frontend-reference-backend-paths "Permalink") + +我们不希望通过硬编码路径添加额外的耦合. 如果可能,请将这些路径作为数据属性添加到 JavaScript 中引用的 DOM 元素. + +Example: + +``` +// Bad :( +// Here's a Vuex action that hardcodes a path :( +export const fetchFoos = ({ state }) => { + return axios.get(joinPaths(gon.relative_url_root, '-', 'foo')); +}; + +// Good :) +function initFoo() { + const el = document.getElementById('js-foo'); + + // Path comes from our root element's data which is used to initialize the store :) + const store = createStore({ + fooPath: el.dataset.fooPath + }); + + Vue.extend({ + store, + el, + render(h) { + return h(Component); + }, + }); +} + +// Vuex action can now reference the path from its state :) +export const fetchFoos = ({ state }) => { + return axios.get(state.settings.fooPath); +}; +``` + +### 7\. How can I test the production build locally?[](#7-how-can-i-test-the-production-build-locally "Permalink") + +有时有必要在本地测试前端生产版本将产生什么,为此,步骤如下: + +1. 停止 webpack: `gdk stop webpack` . +2. 打开`gitlab.yaml`位于您`gitlab`安装文件夹,向下滚动到`webpack`部分和变化`dev_server`到`enabled: false` . +3. Run `yarn webpack-prod && gdk restart rails-web`. + +生产构建需要几分钟才能完成; 仅在再次执行上面的第 3 项后,此时才会显示任何代码更改. 要返回正常的开发模式: + +1. 打开`gitlab.yaml`位于您`gitlab`安装文件夹,向下滚动到`webpack`部分和变回`dev_server`到`enabled: true` . +2. `yarn clean`以除去生产资产并释放一些空间(可选). +3. 重新启动 webpack: `gdk start webpack` . +4. 重新启动 GDK: `gdk-restart rails-web` . \ No newline at end of file diff --git a/docs/595.md b/docs/595.md new file mode 100644 index 0000000000000000000000000000000000000000..97b88ecb4178108952ae67df1ce67e3a8005c30c --- /dev/null +++ b/docs/595.md @@ -0,0 +1,653 @@ +# GraphQL + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/graphql.html](https://docs.gitlab.com/ee/development/fe_guide/graphql.html) + +* [Getting Started](#getting-started) + * [Helpful Resources](#helpful-resources) + * [Libraries](#libraries) + * [Tooling](#tooling) + * [Apollo GraphQL VS Code extension](#apollo-graphql-vs-code-extension) + * [Exploring the GraphQL API](#exploring-the-graphql-api) +* [Apollo Client](#apollo-client) +* [GraphQL Queries](#graphql-queries) + * [Fragments](#fragments) +* [Usage in Vue](#usage-in-vue) + * [Local state with Apollo](#local-state-with-apollo) + * [Mocking API response with local Apollo cache](#mocking-api-response-with-local-apollo-cache) + * [Using with Vuex](#using-with-vuex) + * [Feature flags in queries](#feature-flags-in-queries) + * [Manually triggering queries](#manually-triggering-queries) + * [Working with pagination](#working-with-pagination) + * [Using `fetchMore` method in components](#using-fetchmore-method-in-components) + * [Testing](#testing) + * [Mocking response as component data](#mocking-response-as-component-data) + * [Testing loading state](#testing-loading-state) + * [Testing Apollo components](#testing-apollo-components) +* [Handling errors](#handling-errors) + * [Top-level errors](#top-level-errors) + * [Handling top-level errors](#handling-top-level-errors) + * [Errors-as-data](#errors-as-data) + * [Handling errors-as-data](#handling-errors-as-data) +* [Usage outside of Vue](#usage-outside-of-vue) + +# GraphQL[](#graphql "Permalink") + +## Getting Started[](#getting-started "Permalink") + +### Helpful Resources[](#helpful-resources "Permalink") + +**一般资源**: + +* [📚 Official Introduction to GraphQL](https://s0graphql0org.icopy.site/learn/) +* [📚 Official Introduction to Apollo](https://www.apollographql.com/docs/tutorial/introduction/) + +**GitLab 上的 GraphQL**: + +* [🎬 GitLab Unfiltered GraphQL playlist](https://www.youtube.com/watch?v=wHPKZBDMfxE&list=PL05JrBw4t0KpcjeHjaRMB7IGB2oDWyJzv) +* [GitLab 上的 GraphQL:深潜](../api_graphql_styleguide.html#deep-dive) (视频)作者 Nick Thomas + * GitLab 上 GraphQL 的历史概述(不是特定于前端的) +* [使用 GraphQL 和 Vue Apollo 进行 GitLab 功能演练](https://www.youtube.com/watch?v=6yYp2zB7FrM) (视频),作者 Natalia Tepluhina + * 使用 GraphQL 在 GitLab 中实现前端功能的真实示例 +* [GitLab 上的客户端 GraphQL 的历史](https://www.youtube.com/watch?v=mCKRJxvMnf0) (视频)Illya Klymov 和 Natalia Tepluhina +* Natalia Tepluhina [从 Vuex 到 Apollo](https://www.youtube.com/watch?v=9knwu87IfU8) (视频) + * 关于何时阿波罗可能比 Vuex 更好的选择以及如何进行过渡的有用概述 +* [🛠 Vuex -> Apollo Migration: a proof-of-concept project](https://gitlab.com/ntepluhina/vuex-to-apollo/blob/master/README.md) + * 一系列示例展示了使用 Vue + GraphQL +(Vuex 或 Apollo)应用进行状态管理的可能方法 + +### Libraries[](#libraries "Permalink") + +当使用 GraphQL 进行前端开发时,我们使用[Apollo](https://www.apollographql.com/) (特别是[Apollo Client](https://www.apollographql.com/docs/react/) )和[Vue Apollo](https://github.com/vuejs/vue-apollo) . + +如果在 Vue 应用程序中使用 GraphQL,则" Vue 中的[用法"](#usage-in-vue)部分可以帮助您学习如何集成 Vue Apollo. + +对于其他用例,请查看[Vue 外部](#usage-outside-of-vue)的[用法](#usage-outside-of-vue)部分. + +### Tooling[](#tooling "Permalink") + +* [Apollo Client Devtools](https://github.com/apollographql/apollo-client-devtools) + +#### [Apollo GraphQL VS Code extension](https://marketplace.visualstudio.com/items?itemName=apollographql.vscode-apollo)[](#apollo-graphql-vs-code-extension "Permalink") + +如果使用 VS Code,则 Apollo GraphQL 扩展名支持`.graphql`文件中的自动完成. 若要设置 GraphQL 扩展,请按照下列步骤操作: + +1. 将`apollo.config.js`文件添加到`gitlab`本地目录的根目录中. +2. 用以下内容填充文件: + + ``` + module.exports = { + client: { + includes: ['./app/assets/javascripts/**/*.graphql', './ee/app/assets/javascripts/**/*.graphql'], + service: { + name: 'GitLab', + localSchemaFile: './doc/api/graphql/reference/gitlab_schema.graphql', + }, + }, + }; + ``` + +3. 重新启动 VS Code. + +### Exploring the GraphQL API[](#exploring-the-graphql-api "Permalink") + +我们 GraphQL API 可以通过 GraphiQL 在您的实例的探索`/-/graphql-explorer`或[GitLab.com](https://gitlab.com/-/graphql-explorer) . 如有需要,请查阅《 [GitLab GraphQL API 参考》文档](../../api/graphql/reference) . + +您可以在 GraphiQL 的**文档浏览器**的右侧检查所有现有的查询和变异. 也可以直接在左选项卡上编写查询和变异,然后单击左上角的**执行查询**按钮来检查其执行情况: + +[![GraphiQL interface](img/40cd53294c496a4d049d735386c16649.png)](img/graphiql_explorer_v12_4.png) + +## Apollo Client[](#apollo-client "Permalink") + +为了保存在不同的应用程序中创建的重复客户端,我们使用[默认客户端](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/javascripts/lib/graphql.js) . 这将使用正确的 URL 设置 Apollo 客户端,并设置 CSRF 标头. + +默认客户端接受两个参数: `resolvers`和`config` . + +* 创建`resolvers`参数以接受用于[本地状态管理](#local-state-with-apollo)查询和突变的 resolvers 对象 +* `config`参数采用配置设置的对象: + * `cacheConfig`字段接受设置的可选对象以[自定义 Apollo 缓存](https://www.apollographql.com/docs/react/caching/cache-configuration/#configuring-the-cache) + * `baseUrl`允许我们传递与主端点不同的 GraphQL 端点的 URL(即`${gon.relative_url_root}/api/graphql` ) + * `assumeImmutableResults` (默认设置为`false` )-此设置为`true` ,将假定更新 Apollo Cache 时的每个操作都是不可变的. 它还将`freezeResults`设置为`true` ,因此任何尝试`freezeResults` Apollo Cache 的尝试都会在开发环境中引发控制台警告. 在将此选项设置为`true`之前,请确保在缓存更新操作中遵循不变性模式. + +## GraphQL Queries[](#graphql-queries "Permalink") + +为了在运行时保存查询编译,webpack 可以直接导入`.graphql`文件. 这使 webpack 可以在编译时对查询进行预处理,而不是由客户端进行查询的编译. + +为了将查询与突变和片段区分开来,建议使用以下命名约定: + +* `all_users.query.graphql`用于查询; +* `add_user.mutation.graphql`进行突变; +* 片段的`basic_user.fragment.graphql` . + +### Fragments[](#fragments "Permalink") + +[片段](https://s0graphql0org.icopy.site/learn/queries/)是使复杂的 GraphQL 查询更具可读性和可重用性的一种方式. 这是 GraphQL 片段的示例: + +``` +fragment DesignListItem on Design { + id + image + event + filename + notesCount +} +``` + +片段可以存储在单独的文件中,可以导入并用于查询,突变或其他片段. + +``` +#import "./design_list.fragment.graphql" +#import "./diff_refs.fragment.graphql" + +fragment DesignItem on Design { + ...DesignListItem + fullPath + diffRefs { + ...DesignDiffRefs + } +} +``` + +有关片段的更多信息: [GraphQL Docs](https://s0graphql0org.icopy.site/learn/queries/) + +## Usage in Vue[](#usage-in-vue "Permalink") + +要使用 Vue Apollo,请导入[Vue Apollo](https://github.com/vuejs/vue-apollo)插件以及默认客户端. 这应该在安装 Vue 应用程序的同一时间创建. + +``` +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; +Vue.use(VueApollo); + +const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient(), +}); + +new Vue({ + ..., + apolloProvider, + ... +}); +``` + +在[Vue Apollo 文档中](https://vue-apollo.netlify.app/guide/)阅读有关[Vue Apollo 的](https://github.com/vuejs/vue-apollo)更多信息. + +### Local state with Apollo[](#local-state-with-apollo "Permalink") + +创建默认客户端时,可以通过传入 resolvers 对象来使用 Apollo 管理应用程序状态. 设置默认客户端后,可以通过写入缓存来设置默认状态. + +``` +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; +Vue.use(VueApollo); + +const defaultClient = createDefaultClient({ + resolvers: {} +}); + +defaultClient.cache.writeData({ + data: { + user: { + name: 'John', + surname: 'Doe', + age: 30 + }, + }, +}); + +const apolloProvider = new VueApollo({ + defaultClient, +}); +``` + +我们可以使用`@client` Apollo 指令查询本地数据: + +``` +// user.query.graphql + +query User { + user @client { + name + surname + age + } +} +``` + +除了创建本地数据,我们还可以使用`@client`字段扩展现有的 GraphQL 类型. 当我们需要为尚未添加到 GraphQL API 中的字段模拟 API 响应时,这非常有用. + +#### Mocking API response with local Apollo cache[](#mocking-api-response-with-local-apollo-cache "Permalink") + +当我们需要在本地模拟某些 GraphQL API 响应,查询或变异时(例如,当它们仍未添加到我们的实际 API 中时),使用本地 Apollo 缓存非常方便. + +例如,我们在查询中使用了有关`DesignVersion`的[片段](#fragments) : + +``` +fragment VersionListItem on DesignVersion { + id + sha +} +``` + +我们还需要获取版本作者和'created at'属性,以在版本下拉列表中显示它们,但这些更改仍未在我们的 API 中实现. 我们可以更改现有片段,以针对这些新字段获得模拟的响应: + +``` +fragment VersionListItem on DesignVersion { + id + sha + author @client { + avatarUrl + name + } + createdAt @client +} +``` + +现在,Apollo 将尝试为每个标有`@client`指令的字段查找*解析器* . 让我们为`DesignVersion`类型创建一个解析器(为什么要使用`DesignVersion` ?,因为我们的片段是在这种类型上创建的). + +``` +// resolvers.js + +const resolvers = { + DesignVersion: { + author: () => ({ + avatarUrl: + 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon', + name: 'Administrator', + __typename: 'User', + }), + createdAt: () => '2019-11-13T16:08:11Z', + }, +}; + +export default resolvers; +``` + +我们需要将解析器对象传递给我们现有的 Apollo Client: + +``` +// graphql.js + +import createDefaultClient from '~/lib/graphql'; +import resolvers from './graphql/resolvers'; + +const defaultClient = createDefaultClient( + {}, + resolvers, +); +``` + +现在,每次尝试获取版本时,我们的客户端都会从远程 API 端点获取`id`和`sha` ,并将我们的硬编码值分配给`author`和`createdAt`版本属性. 有了这些数据,前端开发人员就可以在 UI 部件上工作,而不会被后端阻塞. 将实际响应添加到 API 后,可以快速删除自定义本地解析器,并且对查询/片段的唯一更改是`@client`指令删除. + +在[Vue Apollo 文档中](https://vue-apollo.netlify.app/guide/local-state.html#local-state)阅读有关使用 Apollo 进行本地状态管理的更多信息. + +### Using with Vuex[](#using-with-vuex "Permalink") + +When Apollo Client is used within Vuex and fetched data is stored in the Vuex store, there is no need in keeping Apollo Client cache enabled. Otherwise we would have data from the API stored in two places - Vuex store and Apollo Client cache. More to say, with Apollo’s default settings, a subsequent fetch from the GraphQL API could result in fetching data from Apollo cache (in the case where we have the same query and variables). To prevent this behavior, we need to disable Apollo Client cache passing a valid `fetchPolicy` option to its constructor: + +``` +import fetchPolicies from '~/graphql_shared/fetch_policy_constants'; + +export const gqClient = createGqClient( + {}, + { + fetchPolicy: fetchPolicies.NO_CACHE, + }, +); +``` + +### Feature flags in queries[](#feature-flags-in-queries "Permalink") + +有时在 GraphQL 查询中的功能标志后面放置一个实体可能会很有用. 例如,当处理后端已经合并但前端没有合并的功能时,您可能希望将 GraphQL 实体放在功能标记后面,以允许创建和合并较小的合并请求. + +为此, `if`语句通过,我们可以使用`@include`指令排除实体. + +``` +query getAuthorData($authorNameEnabled: Boolean = false) { username name @include(if: $authorNameEnabled) } +``` + +然后,在对查询的 Vue(或 JavaScript)调用中,我们可以传递功能标记. 此功能标志将需要已经正确设置. 有关正确方法,请参阅[功能部件标志文档](../feature_flags/development.html) . + +``` +export default { + apollo: { + user: { + query: QUERY_IMPORT, + variables() { + return { + authorNameEnabled: gon?.features?.authorNameEnabled, + }; + }, + } + }, +}; +``` + +### Manually triggering queries[](#manually-triggering-queries "Permalink") + +创建组件时,将自动对组件的`apollo`属性进行查询. 某些组件反而希望按需发出网络请求,例如,带有延迟加载项的下拉列表. + +有两种方法可以做到这一点: + +1. Use the `skip` property + +``` +export default { + apollo: { + user: { + query: QUERY_IMPORT, + skip() { + // only make the query when dropdown is open + return !this.isOpen; + }, + } + }, +}; +``` + +1. Using `addSmartQuery` + +您可以在您的方法中手动创建智能查询. + +``` +handleClick() { + this.$apollo.addSmartQuery('user', { + // this takes the same values as you'd have in the `apollo` section + query: QUERY_IMPORT, + }), +}; +``` + +### Working with pagination[](#working-with-pagination "Permalink") + +GitLab 的 GraphQL API 对连接类型使用[中继样式的游标分页](https://www.apollographql.com/docs/react/data/pagination/#cursor-based) . 这意味着使用"游标"来跟踪应从中提取下一项的数据集中的位置. [GraphQL Ruby Connection Concepts](https://graphql-ruby.org/pagination/connection_concepts.html)是对连接的良好概述和介绍. + +每个连接类型(例如`DesignConnection`和`DiscussionConnection` )都有一个字段`pageInfo` ,其中包含分页所需的信息: + +``` +pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor +} +``` + +Here: + +* `startCursor`和`endCursor`显示第一项和最后一项的光标. +* `hasPreviousPage`和`hasNextPage`允许我们检查当前页面之前或之后是否还有更多页面可用. + +当我们以连接类型获取数据时,我们可以`before`参数的`after`或`before`传递游标,以指示分页的起点或终点. 应该分别在它们的后跟`first`或`last`参数,以指示我们要在给定端点之后或之前获取*多少个*项目. + +例如,这里我们在光标之后获取 10 个设计: + +``` +query { + project(fullPath: "root/my-project") { + id + issue(iid: "42") { + designCollection { + designs(atVersion: null, after: "Ihwffmde0i", first: 10) { + edges { + node { + id + } + } + } + } + } + } +} +``` + +#### Using `fetchMore` method in components[](#using-fetchmore-method-in-components "Permalink") + +进行初始抓取时,我们通常希望从头开始进行分页. 在这种情况下,我们可以: + +* 跳过传递光标. +* 将`null`明确传递给`after` . + +提取数据后,我们应该保存一个`pageInfo`对象. 假设我们将其存储到 Vue 组件`data` : + +``` +data() { + return { + pageInfo: null, + } +}, +apollo: { + designs: { + query: projectQuery, + variables() { + return { + // rest of design variables + ... + first: 10, + }; + }, + result(res) { + this.pageInfo = res.data?.project?.issue?.designCollection?.designs?.pageInfo; + }, + }, +}, +``` + +当我们想移至下一页时,我们使用 Apollo `fetchMore`方法,在该方法中传递一个新的游标(以及可选的新变量). 在`updateQuery`挂钩中,我们必须在获取下一页之后返回要在 Apollo 缓存中看到的结果. + +``` +fetchNextPage() { + // as a first step, we're checking if we have more pages to move forward + if (this.pageInfo?.hasNextPage) { + this.$apollo.queries.designs.fetchMore({ + variables: { + // rest of design variables + ... + first: 10, + after: this.pageInfo?.endCursor, + }, + updateQuery(previousResult, { fetchMoreResult }) { + // here we can implement the logic of adding new designs to fetched one (for example, if we use infinite scroll) + // or replacing old result with the new one if we use numbered pages + + const newDesigns = fetchMoreResult.project.issue.designCollection.designs; + previousResult.project.issue.designCollection.designs.push(...newDesigns) + + return previousResult; + }, + }); + } +} +``` + +请注意,我们不必再保存`pageInfo`了; `fetchMore`触发查询`result`挂钩. + +### Testing[](#testing "Permalink") + +#### Mocking response as component data[](#mocking-response-as-component-data "Permalink") + +使用[Vue 测试工具](https://vue-test-utils.vuejs.org/) ,可以轻松快速地测试获取 GraphQL 查询的组件. 最简单的方法是使用`shallowMount` ,然后在组件上设置数据 + +``` +it('tests apollo component', () => { + const vm = shallowMount(App); + + vm.setData({ + ...mock data + }); +}); +``` + +#### Testing loading state[](#testing-loading-state "Permalink") + +如果需要测试当 GraphQL API 的结果仍在加载时组件的呈现方式,我们可以将加载状态模拟到相应的 Apollo 查询/突变中: + +``` + function createComponent({ + loading = false, + } = {}) { + const $apollo = { + queries: { + designs: { + loading, + }, + }; + + wrapper = shallowMount(Index, { + sync: false, + mocks: { $apollo } + }); + } + + it('renders loading icon', () => { + createComponent({ loading: true }); + + expect(wrapper.element).toMatchSnapshot(); +}) +``` + +#### Testing Apollo components[](#testing-apollo-components "Permalink") + +如果我们在组件中使用`ApolloQuery`或`ApolloMutation` ,为了测试其功能,我们需要先添加一个存根: + +``` +import { ApolloMutation } from 'vue-apollo'; + +function createComponent(props = {}) { + wrapper = shallowMount(MyComponent, { + sync: false, + propsData: { + ...props, + }, + stubs: { + ApolloMutation, + }, + }); +} +``` + +`ApolloMutation`组件通过作用域插槽公开了`mutate`方法. 如果要测试此方法,则需要将其添加到模拟中: + +``` +const mutate = jest.fn().mockResolvedValue(); +const $apollo = { + mutate, +}; + +function createComponent(props = {}) { + wrapper = shallowMount(MyComponent, { + sync: false, + propsData: { + ...props, + }, + stubs: { + ApolloMutation, + }, + mocks: { + $apollo: + } + }); +} +``` + +然后我们可以检查是否使用正确的变量调用了`mutate` : + +``` +const mutationVariables = { + mutation: createNoteMutation, + update: expect.anything(), + variables: { + input: { + noteableId: 'noteable-id', + body: 'test', + discussionId: '0', + }, + }, +}; + +it('calls mutation on submitting form ', () => { + createComponent() + findReplyForm().vm.$emit('submitForm'); + + expect(mutate).toHaveBeenCalledWith(mutationVariables); +}); +``` + +## Handling errors[](#handling-errors "Permalink") + +目前,GitLab 的 GraphQL 突变具有两种不同的错误模式: [顶级](#top-level-errors)和[数据错误](#errors-as-data) . + +利用 GraphQL 突变时,我们必须考虑处理**这两种错误模式,**以确保用户在发生错误时能够收到适当的反馈. + +### Top-level errors[](#top-level-errors "Permalink") + +这些错误位于 GraphQL 响应的"顶级". 这些是不可恢复的错误,包括参数错误和语法错误,因此不应直接呈现给用户. + +#### Handling top-level errors[](#handling-top-level-errors "Permalink") + +Apollo 意识到顶级错误,因此我们能够利用 Apollo 的各种错误处理机制来处理这些错误(例如,在调用[`mutate`](https://www.apollographql.com/docs/react/api/apollo-client/#ApolloClient.mutate)方法之后处理 Promise 拒绝,或处理从[`ApolloMutation`](https://apollo.vuejs.org/api/apollo-mutation.html#events)组件发出的`error`事件). + +由于这些错误不是针对用户的,因此应在客户端定义顶级错误的错误消息. + +### Errors-as-data[](#errors-as-data "Permalink") + +这些错误嵌套在 GraphQL 响应的`data`对象中. 这些是可恢复的错误,理想情况下,可以直接向用户显示. + +#### Handling errors-as-data[](#handling-errors-as-data "Permalink") + +首先,我们必须向我们的变异对象添加`errors` : + +``` +mutation createNoteMutation($input: String!) { + createNoteMutation(input: $input) { + note { + id ++ errors + } + } +``` + +现在,当我们提交此突变并发生错误时,响应中将包含`errors`供我们处理: + +``` +{ + data: { + mutationName: { + errors: ["Sorry, we were not able to update the note."] + } + } +} +``` + +处理数据错误时,请根据您的最佳判断来确定是将错误消息显示在响应中,还是将另一条客户端定义的消息显示给用户. + +## Usage outside of Vue[](#usage-outside-of-vue "Permalink") + +通过直接导入默认客户端并将其与查询一起使用,还可以在 Vue 之外使用 GraphQL. + +``` +import createDefaultClient from '~/lib/graphql'; +import query from './query.graphql'; + +const defaultClient = createDefaultClient(); + +defaultClient.query({ query }) + .then(result => console.log(result)); +``` + +[使用 Vuex 时](#Using-with-Vuex) ,在以下情况下禁用缓存: + +* 数据正在其他地方缓存 +* 如果数据正在其他地方缓存,或者对于给定的用例完全不需要,则用例不需要缓存. + +``` +import createDefaultClient from '~/lib/graphql'; +import fetchPolicies from '~/graphql_shared/fetch_policy_constants'; + +const defaultClient = createDefaultClient( + {}, + { + fetchPolicy: fetchPolicies.NO_CACHE, + }, +); +``` \ No newline at end of file diff --git a/docs/596.md b/docs/596.md new file mode 100644 index 0000000000000000000000000000000000000000..872580ecc12252fe728ac07a30c1ac1382dbeee5 --- /dev/null +++ b/docs/596.md @@ -0,0 +1,117 @@ +# Icons and SVG Illustrations + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/icons.html](https://docs.gitlab.com/ee/development/fe_guide/icons.html) + +* [Icons](#icons) + * [Usage in HAML/Rails](#usage-in-hamlrails) + * [Usage in Vue](#usage-in-vue) + * [Usage in HTML/JS](#usage-in-htmljs) +* [SVG Illustrations](#svg-illustrations) + * [Usage in HAML/Rails](#usage-in-hamlrails-1) + * [Usage in Vue](#usage-in-vue-1) + +# Icons and SVG Illustrations[](#icons-and-svg-illustrations "Permalink") + +我们在[`gitlab-svgs`](https://gitlab.com/gitlab-org/gitlab-svgs)存储库中管理自己的图标和插图库. 该存储库在[npm](https://s0www0npmjs0com.icopy.site/package/@gitlab/svgs)上发布,并通过 yarn 作为依赖项进行管理. 您可以[在此处](https://gitlab-org.gitlab.io/gitlab-svgs)浏览所有可用的图标和插图. 要升级到新版本,请运行`yarn upgrade @gitlab/svgs` . + +## Icons[](#icons "Permalink") + +我们正在 GitLab 中使用 SVG Sprite 使用 SVG 图标. 这意味着图标仅加载一次,并通过 ID 进行引用. 子画面 SVG 位于`/assets/icons.svg`下. + +我们的目标是一一替换所有内联 SVG 图标(如目前已膨胀的 HTML)以及所有 Font Awesome 图标. + +### Usage in HAML/Rails[](#usage-in-hamlrails "Permalink") + +要在 HAML 或 Rails 中使用精灵图标,我们使用特定的辅助函数: + +``` +sprite_icon(icon_name, size: nil, css_class: '') +``` + +* **icon_name**使用可以在 SVG Sprite 中找到的 icon_name( [此处提供概述](https://gitlab-org.gitlab.io/gitlab-svgs) ). +* **size(可选)**使用以下大小之一: `s16` (将被翻译成`s16`类) +* **css_class(可选)**如果要添加其他 CSS 类 + +**Example** + +``` += sprite_icon('issues', size: 72, css_class: 'icon-danger') +``` + +**上面示例的输出** + +``` +<svg class="s72 icon-danger"> + <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/assets/icons.svg#issues"></use> +</svg> +``` + +### Usage in Vue[](#usage-in-vue "Permalink") + +我们的组件库[GitLab UI](https://gitlab-org.gitlab.io/gitlab-ui/)提供了一个用于显示精灵图标的组件. + +样品用法: + +``` +<script> +import { GlIcon } from "@gitlab/ui"; + +export default { + components: { + GlIcon, + }, +}; +<script> + +<template> + <gl-icon + name="issues" + :size="24" + class="class-name" + /> +</template> +``` + +* **name** SVG Sprite 中图标的名称( [此处提供概述](https://gitlab-org.gitlab.io/gitlab-svgs) ). +* **size(可选)** ,然后将大小的数字值映射到特定的 CSS 类(可用大小: `sXX`映射到`sXX` CSS 类) +* **class(可选)**要添加到 SVG 标签的其他 CSS 类. + +### Usage in HTML/JS[](#usage-in-htmljs "Permalink") + +请在 JS 中使用以下函数来呈现图标: `gl.utils.spriteIcon(iconName)` + +## SVG Illustrations[](#svg-illustrations "Permalink") + +从现在开始,对于任何基于 SVG 的插图,请使用简单的`img`标签来显示插图,只需使用`image_tag`或`image_path`帮助器即可. 请使用周围的`svg-content`类,以确保呈现效果良好. + +### Usage in HAML/Rails[](#usage-in-hamlrails-1 "Permalink") + +**Example** + +``` +.svg-content + = image_tag 'illustrations/merge_requests.svg' +``` + +### Usage in Vue[](#usage-in-vue-1 "Permalink") + +要在模板中使用 SVG 插图,请将路径作为属性提供,并通过标准`img`标签显示它. + +Component: + +``` +<script> +export default { + props: { + svgIllustrationPath: { + type: String, + required: true, + }, + }, +}; +<script> + +<template> + <img :src="svgIllustrationPath" /> +</template> +``` \ No newline at end of file diff --git a/docs/597.md b/docs/597.md new file mode 100644 index 0000000000000000000000000000000000000000..4c175906c92f24118534d1e643cd26ff5cea2a40 --- /dev/null +++ b/docs/597.md @@ -0,0 +1,62 @@ +# InputSetter + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/droplab/plugins/input_setter.html](https://docs.gitlab.com/ee/development/fe_guide/droplab/plugins/input_setter.html) + +* [Usage](#usage) + +# InputSetter[](#inputsetter "Permalink") + +`InputSetter`是一个插件,当单击列表项时,该插件允许在 droplab 范围之外更新 DOM. + +## Usage[](#usage "Permalink") + +将`InputSetter`对象添加到`DropLab.prototype.init`或`DropLab.prototype.addHook`调用的插件数组中. + +* `InputSetter`需要`input`和`valueAttribute`的配置值. +* `input`应该是要操作的 DOM 元素. +* `valueAttribute`应该是一个字符串,它是列表项上属性的名称,用于获取用于更新`input`元素的值. + +您还可以将`InputSetter`配置设置为对象数组,这将允许您更新多个元素. + +``` +<input id="input" value=""> +<div id="div" data-selected-id=""></div> + +<input href="#" id="trigger" data-dropdown-trigger="#list"> +<ul id="list" data-dropdown data-dynamic> + <li><a href="#" data-id="{{id}}">{{text}}</a></li> +<ul> +``` + +``` +const droplab = new DropLab(); + +const trigger = document.getElementById('trigger'); +const list = document.getElementById('list'); + +const input = document.getElementById('input'); +const div = document.getElementById('div'); + +droplab.init(trigger, list, [InputSetter], { + InputSetter: [{ + input: input, + valueAttribute: 'data-id', + } { + input: div, + valueAttribute: 'data-id', + inputAttribute: 'data-selected-id', + }], +}); + +droplab.addData('trigger', [{ + id: 0, + text: 'Jacob', +}, { + id: 1, + text: 'Jeff', +}]); +``` + +上方,如果第二个列表项被单击,它将更新`#input`元素的`value` `1` ,还将更新`#div`元素的`data-selected-id`到`1` . + +(可选)您可以将`inputAttribute`设置为一个字符串,该字符串是您要更新的`input`元素上的属性的名称. 如果你不提供`inputAttribute` , `InputSetter`将更新`value`的的`input` ,如果它是一个元素`INPUT`元素,或者`textContent`的的`input`因素,如果它不是一个`INPUT`元素. \ No newline at end of file diff --git a/docs/598.md b/docs/598.md new file mode 100644 index 0000000000000000000000000000000000000000..f1e2cc8a8ac66464f650d175ecd3b1a983940f37 --- /dev/null +++ b/docs/598.md @@ -0,0 +1,120 @@ +# Performance + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/performance.html](https://docs.gitlab.com/ee/development/fe_guide/performance.html) + +* [Best Practices](#best-practices) + * [Realtime Components](#realtime-components) + * [Lazy Loading Images](#lazy-loading-images) + * [Animations](#animations) +* [Reducing Asset Footprint](#reducing-asset-footprint) + * [Universal code](#universal-code) + * [Page-specific JavaScript](#page-specific-javascript) + * [Important Considerations](#important-considerations) + * [Code Splitting](#code-splitting) + * [Minimizing page size](#minimizing-page-size) +* [Additional Resources](#additional-resources) + +# Performance[](#performance "Permalink") + +## Best Practices[](#best-practices "Permalink") + +### Realtime Components[](#realtime-components "Permalink") + +在为实时功能编写代码时,我们必须牢记以下几点: + +1. 不要使服务器超载请求. +2. 它应该是实时的. + +因此,我们必须在发送请求和实时感之间取得平衡. 创建实时解决方案时,请使用以下规则. + +1. 服务器将通过在标头中发送`Poll-Interval`来告诉您要轮询多少. 使用它作为轮询间隔. 这样[,系统管理员](../../administration/polling.html)就可以[轻松更改轮询速率](../../administration/polling.html) . `Poll-Interval: -1`表示您应禁用轮询,并且必须实施轮询. +2. HTTP 状态不同于 2XX 的响应也应禁用轮询. +3. 使用公共库进行轮询. +4. 仅对活动的选项卡进行轮询. 请使用" [可见性"](https://github.com/ai/visibilityjs) . +5. 使用常规的轮询间隔,不要使用退避轮询或抖动,因为间隔将由服务器控制. +6. 后端代码很可能将使用 etags. 您不会也不应检查状态`304 Not Modified` . 浏览器将为您进行转换. + +### Lazy Loading Images[](#lazy-loading-images "Permalink") + +为了缩短首次渲染的时间,我们对图像使用了延迟加载. 这是通过在`data-src`属性上设置实际图像源来实现的. 渲染 HTML 并加载 JavaScript 后,如果图像在当前视口中,则`data-src`的值将自动移至`src` . + +* 通过将`src`属性重命名为`data-src`并添加类`lazy`来准备 HTML 中的图像以进行延迟加载. +* 如果您使用的是 Rails `image_tag`帮助器,则默认情况下将延迟加载所有图像,除非提供了`lazy: false` . + +如果要异步添加包含惰性图像的内容,则需要调用函数`gl.lazyLoader.searchLazyImages()` ,它将搜索惰性图像并在需要时加载它们. 但通常应通过延迟加载功能中的`MutationObserver`自动处理它. + +### Animations[](#animations "Permalink") + +仅设置动画`opacity`和`transform`属性. 其他属性(例如`top` , `left` , `margin`和`padding` )都导致重新计算 Layout,这要昂贵得多. 有关详细信息,请参见《 [高性能动画](https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/) 》中的"影响布局的样式". + +如果*确实*需要更改布局(例如,将主要内容压入的侧边栏),则最好使用[FLIP](https://aerotwist.com/blog/flip-your-animations/)一次更改昂贵的属性,并使用转换处理实际动画. + +## Reducing Asset Footprint[](#reducing-asset-footprint "Permalink") + +### Universal code[](#universal-code "Permalink") + +`main.js`和`commons/index.js`中包含的代码将加载并在*所有*页面上运行. 除非*在任何地方*确实需要,否则**请勿**在这些文件中**添加**任何内容. 这些捆绑软件包括无处不在的库,例如`vue` , `axios`和`jQuery` ,以及用于主导航和侧边栏的代码. 我们应该尽可能地从这些捆绑软件中删除模块,以减少代码占用量. + +### Page-specific JavaScript[](#page-specific-javascript "Permalink") + +Webpack 已配置为根据`app/assets/javascripts/pages/*`的文件结构自动生成入口点捆绑包. `pages`目录中的目录对应于 Rails 控制器和操作. 这些自动生成的捆绑包将自动包含在相应的页面中. + +例如,如果要访问[https://gitlab.com/gitlab-org/gitlab/-/issues](https://gitlab.com/gitlab-org/gitlab/-/issues) ,则将使用`index`操作访问`app/controllers/projects/issues_controller.rb`控制器. 如果相应的文件位于`pages/projects/issues/index/index.js` ,它将被编译成一个 webpack 包并包含在页面中. + +**注意:**以前我们鼓励在 haml 文件中使用`content_for :page_specific_javascripts`以及手动生成的 webpack 捆绑包. 但是,在此新系统下,您永远不需要手动将入口点添加到`webpack.config.js`文件中.**提示:**如果不确定与给定页面对应的控制器和动作,可以通过在 GitLab 内任何页面上的浏览器开发人员控制台中检查`document.body.dataset.page`来找到. + +#### Important Considerations[](#important-considerations "Permalink") + +* **保持精简入口点:**页面专用的 JavaScript 入口点应尽可能精简. 这些文件免于单元测试,应主要用于实例化和依赖项,这些类和方法驻留在入口点脚本之外的模块中. 只需导入,读取 DOM,实例化,仅此而已. + +* **入口点可能是异步的:** *不要*假设运行入口点脚本时 DOM 已完全加载并且可用. 如果需要在 DOM 加载后运行某些代码,则应使用以下命令将事件处理程序附加到`DOMContentLoaded`事件: + + ``` + import initMyWidget from './my_widget'; + + document.addEventListener('DOMContentLoaded', () => { + initMyWidget(); + }); + ``` + +* **支持模块放置:** + * 如果类或模块*特定于特定路由* ,请尝试将其定位在将要使用的入口点附近. 例如,如果`my_widget.js`仅在`pages/widget/show/index.js`导入,则应将模块放在`pages/widget/show/my_widget.js` ,并使用相对路径`import initMyWidget from './my_widget';` (例如, `import initMyWidget from './my_widget';` ). + * 如果一个类或模块被*多个路由使用* ,请将其放置在最接近的公共父目录的共享目录中,以作为导入它的入口点. 例如,如果将`my_widget.js`导入到`pages/widget/show/index.js`和`pages/widget/run/index.js`两者中,则将模块放置在`pages/widget/shared/my_widget.js` ,并使用相对路径(例如`../shared/my_widget` ). +* **企业版警告:**对于 GitLab 企业版,特定于页面的入口点将覆盖具有相同名称的社区版对应点,因此,如果存在`ee/app/assets/javascripts/pages/foo/bar/index.js` ,它将具有优先权在`app/assets/javascripts/pages/foo/bar/index.js` . 如果要减少重复的代码,可以从另一个导入一个入口点. 不会自动完成此操作,以允许在覆盖功能方面具有灵活性. + +### Code Splitting[](#code-splitting "Permalink") + +对于不需要在页面加载后立即运行的任何代码(例如,模态,下拉列表和其他可以延迟加载的行为),您可以使用动态 import 语句将模块拆分为异步块. 这些导入返回一个 Promise,一旦脚本被加载,它将被解决: + +``` +import(/* webpackChunkName: 'emoji' */ '~/emoji') + .then(/* do something */) + .catch(/* report error */) +``` + +生成这些动态导入时,请尝试使用`webpackChunkName` ,因为它将为块提供确定性的文件名,然后可以将其缓存在 GitLab 版本中的浏览器中. + +更多信息,请参见[webpack 的代码拆分文档](https://webpack.js.org/guides/code-splitting/#dynamic-imports) . + +### Minimizing page size[](#minimizing-page-size "Permalink") + +较小的页面大小意味着页面加载速度更快(在移动连接和连接不良时尤其重要),浏览器可以更快地解析页面,并且数据流量上限的用户使用的数据更少. + +一般提示: + +* 不要添加新字体. +* Prefer font formats with better compression, e.g. WOFF2 is better than WOFF, which is better than TTF. +* 尽可能压缩和缩小资产(对于 CSS / JS,Sprockets 和 webpack 可以为我们完成此工作). +* 如果可以在不添加额外库的情况下合理地实现某些功能,请避免使用它们. +* 如上所述,使用特定于页面的 JavaScript 加载仅在某些页面上需要的库. +* 尽可能使用代码拆分动态导入来延迟加载最初不需要的代码. +* [High Performance Animations](https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/) + +* * * + +## Additional Resources[](#additional-resources "Permalink") + +* [WebPage Test,](https://www.webpagetest.org)用于测试网站的加载时间和大小. +* [Google PageSpeed Insights 对](https://developers.google.com/speed/pagespeed/insights/)网页进行评分,并提供反馈意见以改善网页. +* [Profiling with Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/) +* [Browser Diet](https://browserdiet.com/)是社区构建的指南,其中列出了一些实用技巧,以提高网页性能. \ No newline at end of file diff --git a/docs/599.md b/docs/599.md new file mode 100644 index 0000000000000000000000000000000000000000..49eaf1509ddf649c905ffe1b3b23f4ac7bacea47 --- /dev/null +++ b/docs/599.md @@ -0,0 +1,23 @@ +# Principles + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/principles.html](https://docs.gitlab.com/ee/development/fe_guide/principles.html) + +* [Discuss architecture before implementation](#discuss-architecture-before-implementation) +* [Be consistent](#be-consistent) +* [Improve code iteratively](#improve-code-iteratively) + +# Principles[](#principles "Permalink") + +这些原则将确保您的前端贡献从正确的方向开始. + +## Discuss architecture before implementation[](#discuss-architecture-before-implementation "Permalink") + +在编写代码之前,请先讨论您的体系结构设计问题. 这有助于减少审阅时间,也为编写和思考系统设计提供了良好的实践. + +## Be consistent[](#be-consistent "Permalink") + +有多种编写代码以实现相同结果的方法. 我们应该在代码库中编写代码的方式尽可能保持一致. 这将使我们更轻松地在整个 GitLab 中维护代码. + +## Improve code [iteratively](https://about.gitlab.com/handbook/values/#iteration)[](#improve-code-iteratively "Permalink") + +每当您看到不符合我们当前样式指南的现有代码时,请主动进行更新. 您不需要修复所有问题,但是每个合并请求都应迭代地改进我们的代码库,并在可能的情况下减少技术负担. \ No newline at end of file diff --git a/docs/600.md b/docs/600.md new file mode 100644 index 0000000000000000000000000000000000000000..fb2864fc07200f84d605829b7fa0d02391e59c84 --- /dev/null +++ b/docs/600.md @@ -0,0 +1,25 @@ +# Security + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/security.html](https://docs.gitlab.com/ee/development/fe_guide/security.html) + +* [Resources](#resources) +* [Including external resources](#including-external-resources) +* [Avoiding inline scripts and styles](#avoiding-inline-scripts-and-styles) + +# Security[](#security "Permalink") + +## Resources[](#resources "Permalink") + +[Mozilla 的 HTTP Observatory CLI](https://github.com/mozilla/http-observatory-cli)和[Qualys SSL Labs Server Test](https://www.ssllabs.com/ssltest/analyze.html)是发现潜在问题并确保遵守安全最佳实践的良好资源. + +## Including external resources[](#including-external-resources "Permalink") + +除 Google Analytics(分析)和 Piwik 外,切勿使用外部字体,CSS 和 JavaScript-仅在实例启用它时才可以使用. 资产应始终从 GitLab 实例本地托管和服务. 威盛嵌入式资源`iframes`不应该只是在某些情况下,如与验证码,不能没有使用使用`iframe` . + +## Avoiding inline scripts and styles[](#avoiding-inline-scripts-and-styles "Permalink") + +为了保护用户免受[XSS 漏洞的侵害](https://en.wikipedia.org/wiki/Cross-site_scripting) ,将来我们将使用内容安全策略禁用内联脚本. + +尽管内联脚本可能很有用,但它们也是安全问题. 如果无意中对用户提供的内容进行了未经消毒的处理,则恶意用户可以将脚本注入 Web 应用程序. + +几乎在所有情况下都应避免使用内联样式,只有在找不到替代方法时才应使用内联样式. 这允许样式的可重用性以及可读性. \ No newline at end of file diff --git a/docs/601.md b/docs/601.md new file mode 100644 index 0000000000000000000000000000000000000000..65facede54d4f7a7804f93ef85f80689b97c3a55 --- /dev/null +++ b/docs/601.md @@ -0,0 +1 @@ +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/testing.html](https://docs.gitlab.com/ee/development/fe_guide/testing.html) \ No newline at end of file diff --git a/docs/602.md b/docs/602.md new file mode 100644 index 0000000000000000000000000000000000000000..7498f0f00f06bf95a2ee392f564313b973e6e9b7 --- /dev/null +++ b/docs/602.md @@ -0,0 +1,210 @@ +# Tooling + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/tooling.html](https://docs.gitlab.com/ee/development/fe_guide/tooling.html) + +* [ESLint](#eslint) + * [Yarn Script](#yarn-script) + * [Disabling ESLint in new files](#disabling-eslint-in-new-files) + * [Disabling ESLint for a single violation](#disabling-eslint-for-a-single-violation) + * [The `no-undef` rule and declaring globals](#the-no-undef-rule-and-declaring-globals) +* [Formatting with Prettier](#formatting-with-prettier) + * [Editor](#editor) + * [Yarn Script](#yarn-script-1) + * [Scripts during Conversion period](#scripts-during-conversion-period) + * [VSCode Settings](#vscode-settings) + * [Select Prettier as default formatter](#select-prettier-as-default-formatter) + * [Format on Save](#format-on-save) + +# Tooling[](#tooling "Permalink") + +## ESLint[](#eslint "Permalink") + +我们使用 ESLint 封装和执行前端代码标准. 我们的配置可以在[`gitlab-eslint-config`](https://gitlab.com/gitlab-org/gitlab-eslint-config)项目中找到. + +### Yarn Script[](#yarn-script "Permalink") + +本节介绍可用于验证的脚本,并使用 ESLint 将自动修复应用于文件. + +要使用 ESLint 检查所有当前暂存的文件(基于`git diff` ),请运行以下脚本: + +``` +yarn eslint-staged +``` + +*找到的问题列表将记录到控制台.* + +要将自动 ESLint 修复应用于所有当前暂存的文件(基于`git diff` ),请运行以下脚本: + +``` +yarn eslint-staged-fix +``` + +*If manual changes are required, a list of changes will be sent to the console.* + +要使用 ESLint 检查存储库中的**所有**文件,请运行以下脚本: + +``` +yarn eslint +``` + +*找到的问题列表将记录到控制台.* + +要将自动 ESLint 修复应用于存储库中的**所有**文件,请运行以下脚本: + +``` +yarn eslint-fix +``` + +*如果需要手动更改,则会将更改列表发送到控制台.* + +**警告:**限制使用全局规则更新. 否则,更改可能导致巨大的合并请求. + +### Disabling ESLint in new files[](#disabling-eslint-in-new-files "Permalink") + +创建新文件时,请不要禁用 ESLint. 由于遗留兼容性的原因,现有文件可能已禁用现有规则,但是它们正在重构中. + +不要禁用特定的 ESLint 规则. 为避免引入技术债务,只有在调用/实例化现有代码模块时,才可以禁用以下规则. + +* [`no-new`](https://eslint.org/docs/rules/no-new) +* [`class-method-use-this`](https://eslint.org/docs/rules/class-methods-use-this) + +**注意:**逐行禁用这些规则. 这使得将来更容易重构. 例如,使用`eslint-disable-next-line`或`eslint-disable-line` . + +### Disabling ESLint for a single violation[](#disabling-eslint-for-a-single-violation "Permalink") + +如果确实需要为单个违规禁用规则,请以所需的最少代码量禁用它: + +``` +// bad +/* eslint-disable no-new */ + +import Foo from 'foo'; + +new Foo(); + +// better +import Foo from 'foo'; + +// eslint-disable-next-line no-new +new Foo(); +``` + +### The `no-undef` rule and declaring globals[](#the-no-undef-rule-and-declaring-globals "Permalink") + +**切勿**禁用`no-undef`规则. 用`/* global Foo */`代替声明 globals. + +声明多个全局变量时,请始终为每个变量使用一个`/* global [name] */`行. + +``` +// bad +/* globals Flash, Cookies, jQuery */ + +// good +/* global Flash */ +/* global Cookies */ +/* global jQuery */ +``` + +## Formatting with Prettier[](#formatting-with-prettier "Permalink") + +对 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/227280)的`.graphql`支持. + +我们的代码会自动使用[Prettier](https://prettier.io)格式化,以遵循我们的样式指南. 漂亮正在格式化的护理`.js` , `.vue` , `.graphql`和`.scss`基于标准的漂亮规则文件. 您可以在`.prettierrc`找到`.prettierrc`所有设置. + +### Editor[](#editor "Permalink") + +在工作流程中包括更漂亮的最简单方法是相应地设置您的首选编辑器(支持所有主要编辑器). 我们建议将漂亮的文件设置为在保存每个文件时自动运行. [在此处](https://prettier.io/docs/en/editors.html)找到[在](https://prettier.io/docs/en/editors.html)首选编辑器中进行设置的最佳方法. + +请小心,你只能让更漂亮的格式相同的文件类型,全球纱线脚本执行( `.js` , `.vue` , `.graphql`和`.scss` ). 以 VSCode 为例,您可以轻松地在设置文件中排除文件格式: + +``` + "prettier.disableLanguages": [ "json", "markdown" ] +``` + +### Yarn Script[](#yarn-script-1 "Permalink") + +以下纱线脚本可用于进行全局格式化: + +``` +yarn prettier-staged-save +``` + +使用 Prettier 更新所有当前暂存的文件(基于`git diff` )并保存所需的更改. + +``` +yarn prettier-staged +``` + +使用 Prettier 检查所有当前暂存的文件(基于`git diff` ),并记录哪些文件需要手动更新到控制台. + +``` +yarn prettier-all +``` + +使用 Prettier 检查所有文件,并记录哪些文件需要手动更新到控制台. + +``` +yarn prettier-all-save +``` + +使用 Prettier 格式化存储库中的所有文件. (这仅应用于测试全局规则更新,否则您将获得巨大的 MR). + +这些 Yarn 脚本的来源可以在`/scripts/frontend/prettier.js`找到. + +#### Scripts during Conversion period[](#scripts-during-conversion-period "Permalink") + +``` +node ./scripts/frontend/prettier.js check-all ./vendor/ +``` + +这将遍历特定文件夹中的所有文件并进行检查. + +``` +node ./scripts/frontend/prettier.js save-all ./vendor/ +``` + +这将遍历特定文件夹中的所有文件并将其保存. + +### VSCode Settings[](#vscode-settings "Permalink") + +#### Select Prettier as default formatter[](#select-prettier-as-default-formatter "Permalink") + +要将" Prettier"选择为格式器,请在"用户或工作区设置"中添加以下属性: + +``` +{ + "[html]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[vue]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[graphql]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } +} +``` + +#### Format on Save[](#format-on-save "Permalink") + +要使用 Prettier 自动设置文件格式,请在"用户或工作区设置"中添加以下属性: + +``` +{ + "[html]": { + "editor.formatOnSave": true + }, + "[javascript]": { + "editor.formatOnSave": true + }, + "[vue]": { + "editor.formatOnSave": true + }, + "[graphql]": { + "editor.formatOnSave": true + }, +} +``` \ No newline at end of file diff --git a/docs/603.md b/docs/603.md new file mode 100644 index 0000000000000000000000000000000000000000..2383058b5e6e8cf9e0dc3c980f9562c748eb48b2 --- /dev/null +++ b/docs/603.md @@ -0,0 +1,618 @@ +# Vuex + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/vuex.html](https://docs.gitlab.com/ee/development/fe_guide/vuex.html) + +* [Separation of concerns](#separation-of-concerns) +* [File structure](#file-structure) + * [`index.js`](#indexjs) + * [`state.js`](#statejs) + * [Access `state` properties](#access-state-properties) + * [`actions.js`](#actionsjs) + * [Dispatching actions](#dispatching-actions) + * [`mutations.js`](#mutationsjs) + * [Naming Pattern: `REQUEST` and `RECEIVE` namespaces](#naming-pattern-request-and-receive-namespaces) + * [Updating complex state](#updating-complex-state) + * [`getters.js`](#gettersjs) + * [`mutation_types.js`](#mutation_typesjs) + * [Initializing a store’s state](#initializing-a-stores-state) + * [Why not just …spread the initial state?](#why-not-just-spread-the-initial-state) + * [Communicating with the Store](#communicating-with-the-store) + * [Vuex Gotchas](#vuex-gotchas) + * [Testing Vuex](#testing-vuex) + * [Testing Vuex concerns](#testing-vuex-concerns) + * [Testing components that need a store](#testing-components-that-need-a-store) + * [Two way data binding](#two-way-data-binding) + +# Vuex[](#vuex "Permalink") + +如果将状态管理与组件分离有明显的好处(例如,由于状态复杂性),我们建议使用[Vuex 而](https://vuex.vuejs.org)不是其他任何 Flux 模式. 否则,请随时管理组件中的状态. + +在以下情况下,应强烈考虑 Vuex: + +* 您期望应用程序的多个部分对状态变化做出反应 +* 需要在多个组件之间共享数据 +* 与后端的交互非常复杂,例如多个 API 调用 +* 该应用程序涉及通过传统 REST API 和 GraphQL 与后端进行交互(尤其是将 REST API 移至 GraphQL 时,这是一项待处理的后端任务) + +*注意:以下*所有内容在[Vuex](https://vuex.vuejs.org)官方[文档](https://vuex.vuejs.org)中有更详细的[说明](https://vuex.vuejs.org) . + +## Separation of concerns[](#separation-of-concerns "Permalink") + +Vuex 由状态,获取器,变异,动作和模块组成. + +当用户点击一个动作时,我们需要`dispatch`它. 此操作将`commit`将更改状态的突变. *注意:*动作本身不会更新状态,只有突变可以更新状态. + +## File structure[](#file-structure "Permalink") + +在 GitLab 上使用 Vuex 时,请将这些问题分为不同的文件以提高可读性: + +``` +└── store + ├── index.js # where we assemble modules and export the store + ├── actions.js # actions + ├── mutations.js # mutations + ├── getters.js # getters + ├── state.js # state + └── mutation_types.js # mutation types +``` + +下例显示了一个列出用户并将其添加到状态的应用程序. (有关更复杂的示例实现,请查看[此处](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/app/assets/javascripts/vue_shared/security_reports/store)的安全应用程序商店) + +### `index.js`[](#indexjs "Permalink") + +这是我们商店的入口点. 您可以使用以下内容作为指导: + +``` +import Vuex from 'vuex'; +import * as actions from './actions'; +import * as getters from './getters'; +import mutations from './mutations'; +import state from './state'; + +export const createStore = () => + new Vuex.Store({ + actions, + getters, + mutations, + state, + }); +``` + +*注意:*在实施此[RFC](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/20)之前,以上内容将需要禁用`import/prefer-default-export` ESLint 规则. + +### `state.js`[](#statejs "Permalink") + +在编写任何代码之前,您应该做的第一件事就是设计状态. + +通常,我们需要将数据从 haml 提供给 Vue 应用程序. 让我们将其存储在状态中以便更好地访问. + +``` + export default () => ({ + endpoint: null, + + isLoading: false, + error: null, + + isAddingUser: false, + errorAddingUser: false, + + users: [], + }); +``` + +#### Access `state` properties[](#access-state-properties "Permalink") + +您可以使用`mapState`访问组件中的状态属性. + +### `actions.js`[](#actionsjs "Permalink") + +An action is a payload of information to send data from our application to our store. + +动作通常由`type`和`payload` ,它们描述发生了什么. 与[变种](#mutationsjs)不同,动作可以包含异步操作-这就是为什么我们始终需要在动作中处理异步逻辑. + +在此文件中,我们将编写将调用突变的操作以处理用户列表: + +``` + import * as types from './mutation_types'; + import axios from '~/lib/utils/axios_utils'; + import createFlash from '~/flash'; + + export const fetchUsers = ({ state, dispatch }) => { + commit(types.REQUEST_USERS); + + axios.get(state.endpoint) + .then(({ data }) => commit(types.RECEIVE_USERS_SUCCESS, data)) + .catch((error) => { + commit(types.RECEIVE_USERS_ERROR, error) + createFlash('There was an error') + }); + } + + export const addUser = ({ state, dispatch }, user) => { + commit(types.REQUEST_ADD_USER); + + axios.post(state.endpoint, user) + .then(({ data }) => commit(types.RECEIVE_ADD_USER_SUCCESS, data)) + .catch((error) => commit(types.REQUEST_ADD_USER_ERROR, error)); + } +``` + +#### Dispatching actions[](#dispatching-actions "Permalink") + +要从组件调度动作,请使用`mapActions`帮助器: + +``` +import { mapActions } from 'vuex'; + +{ + methods: { + ...mapActions([ + 'addUser', + ]), + onClickUser(user) { + this.addUser(user); + }, + }, +}; +``` + +### `mutations.js`[](#mutationsjs "Permalink") + +变异指定应用程序状态如何响应发送到商店的操作而改变. 更改 Vuex 存储中状态的唯一方法应该是通过提交突变. + +**在编写任何代码之前先考虑状态是一个好主意.** + +请记住,动作仅描述发生了某些事情,而没有描述应用程序状态如何变化. + +**切勿直接从组件提交突变** + +相反,您应该创建一个将导致突变的动作. + +``` + import * as types from './mutation_types'; + + export default { + [types.REQUEST_USERS](state) { + state.isLoading = true; + }, + [types.RECEIVE_USERS_SUCCESS](state, data) { + // Do any needed data transformation to the received payload here + state.users = data; + state.isLoading = false; + }, + [types.RECEIVE_USERS_ERROR](state, error) { + state.isLoading = false; + }, + [types.REQUEST_ADD_USER](state, user) { + state.isAddingUser = true; + }, + [types.RECEIVE_ADD_USER_SUCCESS](state, user) { + state.isAddingUser = false; + state.users.push(user); + }, + [types.REQUEST_ADD_USER_ERROR](state, error) { + state.isAddingUser = false; + state.errorAddingUser = error; + }, + }; +``` + +#### Naming Pattern: `REQUEST` and `RECEIVE` namespaces[](#naming-pattern-request-and-receive-namespaces "Permalink") + +发出请求时,我们通常希望向用户显示加载状态. + +与其创建一个突变来切换加载状态,不如: + +1. 类型为`REQUEST_SOMETHING`的突变,以切换加载状态 +2. 类型为`RECEIVE_SOMETHING_SUCCESS`的突变,用于处理成功回调 +3. 类型为`RECEIVE_SOMETHING_ERROR`的突变,用于处理错误回调 +4. 动作`fetchSomething`发出请求并在提到的情况下提交突变 + 1. 如果您的应用程序执行的不是`GET`请求,则可以使用以下示例: + * `POST` : `createSomething` + * `PUT` : `updateSomething` + * `DELETE` : `deleteSomething` + +结果,我们可以从该组件调度`fetchNamespace`操作,它将负责提交`REQUEST_NAMESPACE` , `RECEIVE_NAMESPACE_SUCCESS`和`RECEIVE_NAMESPACE_ERROR`突变. + +> 以前,我们是从`fetchNamespace`操作中调度操作,而不是提交突变,所以如果您在代码库的较早部分中找到了不同的模式,请不要感到困惑. 但是,无论何时您编写新的 Vuex 商店,我们都鼓励利用新模式 + +通过遵循这种模式,我们保证: + +1. 所有应用程序都遵循相同的模式,从而使任何人都更容易维护代码 +2. 应用程序中的所有数据都遵循相同的生命周期模式 +3. 单元测试更容易 + +#### Updating complex state[](#updating-complex-state "Permalink") + +有时,尤其是当状态复杂时,实际上很难遍历该状态以精确更新突变需要更新的内容. 理想情况下, `vuex`状态应尽可能标准化/解耦,但这并非总是如此. + +重要的是要记住,当在突变本身中选择`portion of the mutated state`并对其进行突变时,代码更易于阅读和维护. + +给定此状态: + +``` + export default () => ({ + items: [ + { + id: 1, + name: 'my_issue', + closed: false, + }, + { + id: 2, + name: 'another_issue', + closed: false, + } + ] +}); +``` + +像这样写一个突变可能很诱人: + +``` +// Bad +export default { + [types.MARK_AS_CLOSED](state, item) { + Object.assign(item, {closed: true}) + } +} +``` + +尽管此方法有效,但它具有以下依赖性: + +* 正确的选择`item`中的组件/动作. +* `item`属性已经在`closed`状态下声明. + * 新的`confidential`财产将不会产生反应. +* 他指出, `item`是通过引用`items` + +这样写的突变更难维护,更容易出错. 我们宁可这样写一个变异: + +``` +// Good +export default { + [types.MARK_AS_CLOSED](state, itemId) { + const item = state.items.find(i => i.id == itemId); + Vue.set(item, 'closed', true) + + state.items.splice(index, 1, item) + } +} +``` + +这种方法更好,因为: + +* 它选择并更新突变中的状态,这种状态更易于维护. +* 它没有外部依赖性,如果传递了正确的`itemId`则状态将正确更新. +* 它没有反应性警告,因为我们生成了一个新`item`以避免耦合到初始状态. + +这样写的变异更容易维护. 另外,我们避免了由于反应系统的限制而导致的错误. + +### `getters.js`[](#gettersjs "Permalink") + +有时我们可能需要根据存储状态获取派生状态,例如针对特定道具进行过滤. 使用 getter 还将由于依赖关系而缓存结果,这取决于[计算的 props 的工作方式.](https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods)这可以通过`getters`来完成: + +``` +// get all the users with pets +export const getUsersWithPets = (state, getters) => { + return state.users.filter(user => user.pet !== undefined); +}; +``` + +要从组件访问吸气剂,请使用`mapGetters`帮助器: + +``` +import { mapGetters } from 'vuex'; + +{ + computed: { + ...mapGetters([ + 'getUsersWithPets', + ]), + }, +}; +``` + +### `mutation_types.js`[](#mutation_typesjs "Permalink") + +来自[vuex 突变文档](https://vuex.vuejs.org/guide/mutations.html) :>在各种 Flux 实现中,将常数用于突变类型是一种常见的模式. 这使代码可以利用像 linters 这样的工具,并将所有常量放在一个文件中,使您的协作者可以快速了解整个应用程序中可能发生的变异. + +``` +export const ADD_USER = 'ADD_USER'; +``` + +### Initializing a store’s state[](#initializing-a-stores-state "Permalink") + +Vuex 存储通常需要一些初始状态才能使用其`action` . 通常,这些数据包括 API 端点,文档 URL 或 ID 之类的数据. + +要设置此初始状态,请在安装 Vue 组件时将其作为参数传递给商店的创建函数: + +``` +// in the Vue app's initialization script (e.g. mount_show.js) + +import Vue from 'vue'; +import Vuex from 'vuex'; +import { createStore } from './stores'; +import AwesomeVueApp from './components/awesome_vue_app.vue' + +Vue.use(Vuex); + +export default () => { + const el = document.getElementById('js-awesome-vue-app'); + + return new Vue({ + el, + store: createStore(el.dataset), + render: h => h(AwesomeVueApp) + }); +}; +``` + +然后,存储功能可以将此数据传递给州的创建功能: + +``` +// in store/index.js + +import * as actions from './actions'; +import mutations from './mutations'; +import createState from './state'; + +export default initialState => ({ + actions, + mutations, + state: createState(initialState), +}); +``` + +状态函数可以接受此初始数据作为参数并将其烘焙到返回的`state`对象中: + +``` +// in store/state.js + +export default ({ + projectId, + documentationPath, + anOptionalProperty = true +}) => ({ + projectId, + documentationPath, + anOptionalProperty, + + // other state properties here +}); +``` + +#### Why not just …spread the initial state?[](#why-not-just-spread-the-initial-state "Permalink") + +精明的读者将从上面的示例中看到切出几行代码的机会: + +``` +// Don't do this! + +export default initialState => ({ + ...initialState, + + // other state properties here +}); +``` + +我们已经做出有意识的决定,避免使用这种模式,以帮助我们的前端代码库实现可发现性和可搜索性. 在[此讨论中](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/56#note_302514865)描述了[这样做的原因](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/56#note_302514865) : + +> 考虑在存储状态中使用了`someStateKey` . 如果仅由`el.dataset`提供,则*可能*无法直接对其进行 grep. 相反,您必须 grep 以获得`some_state_key` ,因为它可能来自 rails 模板. 反之亦然:如果您正在查看 Rails 模板,您可能想知道是什么使用了`some_state_key` ,但是您*必须* grep 为`someStateKey` + +### Communicating with the Store[](#communicating-with-the-store "Permalink") + +``` +<script> +import { mapActions, mapState, mapGetters } from 'vuex'; + +export default { + computed: { + ...mapGetters([ + 'getUsersWithPets' + ]), + ...mapState([ + 'isLoading', + 'users', + 'error', + ]), + }, + methods: { + ...mapActions([ + 'fetchUsers', + 'addUser', + ]), + onClickAddUser(data) { + this.addUser(data); + } + }, + created() { + this.fetchUsers() + } +} +</script> <template> + <ul> + <li v-if="isLoading"> + Loading... + </li> + <li v-else-if="error"> + {{ error }} + </li> + <template v-else> + <li + v-for="user in users" + :key="user.id" + > + {{ user }} + </li> + </template> + </ul> </template> +``` + +### Vuex Gotchas[](#vuex-gotchas "Permalink") + +1. 不要直接调用突变. 始终使用动作进行突变. 这样做将在整个应用程序中保持一致性. 从 Vuex 文档: + + > Why don’t we just call store.commit(‘action’) directly? Well, remember that mutations must be synchronous? Actions aren’t. We can perform asynchronous operations inside an action. + + ``` + // component.vue + + // bad + created() { + this.$store.commit('mutation'); + } + + // good + created() { + this.$store.dispatch('action'); + } + ``` + +2. 使用变异类型而不是对字符串进行硬编码. 这将减少出错的可能性. +3. 在实例化商店的用途之后的所有组件中,都可以访问 State. + +### Testing Vuex[](#testing-vuex "Permalink") + +#### Testing Vuex concerns[](#testing-vuex-concerns "Permalink") + +有关测试操作,获取器和突变的信息,请参考[vuex 文档](https://vuex.vuejs.org/guide/testing.html) . + +#### Testing components that need a store[](#testing-components-that-need-a-store "Permalink") + +较小的组件可能会使用`store`属性来访问数据. 为了编写这些组件的单元测试,我们需要包括商店并提供正确的状态: + +``` +//component_spec.js +import Vue from 'vue'; +import Vuex from 'vuex'; +import { mount, createLocalVue } from '@vue/test-utils'; +import { createStore } from './store'; +import Component from './component.vue' + +const localVue = createLocalVue(); +localVue.use(Vuex); + +describe('component', () => { + let store; + let wrapper; + + const createComponent = () => { + store = createStore(); + + wrapper = mount(Component, { + localVue, + store, + }); + }; + + beforeEach(() => { + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('should show a user', async () => { + const user = { + name: 'Foo', + age: '30', + }; + + // populate the store + await store.dispatch('addUser', user); + + expect(wrapper.text()).toContain(user.name); + }); +}); +``` + +### Two way data binding[](#two-way-data-binding "Permalink") + +在 Vuex 中存储表单数据时,有时需要更新存储的值. 绝对不应直接更改存储,而应使用操作. 为了在我们的代码中仍然使用`v-model` ,我们需要以这种形式创建计算属性: + +``` +export default { + computed: { + someValue: { + get() { + return this.$store.state.someValue; + }, + set(value) { + this.$store.dispatch("setSomeValue", value); + } + } + } +}; +``` + +另一种方法是使用`mapState`和`mapActions` : + +``` +export default { + computed: { + ...mapState(['someValue']), + localSomeValue: { + get() { + return this.someValue; + }, + set(value) { + this.setSomeValue(value) + } + } + }, + methods: { + ...mapActions(['setSomeValue']) + } +}; +``` + +添加其中一些属性变得很麻烦,并使代码重复性更高,并需要编写更多的测试. 为了简化此操作, `~/vuex_shared/bindings.js`有一个帮助器. + +可以像这样使用助手: + +``` +// this store is non-functional and only used to give context to the example +export default { + state: { + baz: '', + bar: '', + foo: '' + }, + actions: { + updateBar() {...} + updateAll() {...} + }, + getters: { + getFoo() {...} + } +} +``` + +``` +import { mapComputed } from '~/vuex_shared/bindings' +export default { + computed: { + /** + * @param {(string[]|Object[])} list - list of string matching state keys or list objects + * @param {string} list[].key - the key matching the key present in the vuex state + * @param {string} list[].getter - the name of the getter, leave it empty to not use a getter + * @param {string} list[].updateFn - the name of the action, leave it empty to use the default action + * @param {string} defaultUpdateFn - the default function to dispatch + * @param {string} root - optional key of the state where to search fo they keys described in list + * @returns {Object} a dictionary with all the computed properties generated + */ + ...mapComputed( + [ + 'baz', + { key: 'bar', updateFn: 'updateBar' } + { key: 'foo', getter: 'getFoo' }, + ], + 'updateAll', + ), + } +} +``` + +然后, `mapComputed`将生成适当的计算属性,这些属性从存储中获取数据并在更新时调度正确的操作. \ No newline at end of file diff --git a/docs/604.md b/docs/604.md new file mode 100644 index 0000000000000000000000000000000000000000..5d71fd0bfbced603ef5bcb36a478113eb6bf1ce4 --- /dev/null +++ b/docs/604.md @@ -0,0 +1,372 @@ +# Vue + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/vue.html](https://docs.gitlab.com/ee/development/fe_guide/vue.html) + +* [Examples](#examples) +* [Vue architecture](#vue-architecture) + * [Components and Store](#components-and-store) + * [An `index.js` file](#an-indexjs-file) + * [Bootstrapping Gotchas](#bootstrapping-gotchas) + * [Providing data from HAML to JavaScript](#providing-data-from-haml-to-javascript) + * [Accessing the `gl` object](#accessing-the-gl-object) + * [Accessing feature flags](#accessing-feature-flags) + * [A folder for Components](#a-folder-for-components) + * [A folder for the Store](#a-folder-for-the-store) + * [Vuex](#vuex) + * [Mixing Vue and jQuery](#mixing-vue-and-jquery) +* [Style guide](#style-guide) +* [Testing Vue Components](#testing-vue-components) + * [Test the component’s output](#test-the-components-output) + * [Events](#events) +* [Vue.js Expert Role](#vuejs-expert-role) +* [Vue 2 -> Vue 3 Migration](#vue-2---vue-3-migration) +* [Appendix - Vue component subject under test](#appendix---vue-component-subject-under-test) + +# Vue[](#vue "Permalink") + +要开始使用 Vue,请通读[其文档](https://vuejs.org/v2/guide/) . + +## Examples[](#examples "Permalink") + +在以下示例中可以找到以下各节中描述的内容: + +* [Web IDE](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/ide/stores) +* [Security products](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/app/assets/javascripts/vue_shared/security_reports) +* [Registry](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/registry/stores) + +## Vue architecture[](#vue-architecture "Permalink") + +用 Vue.js 构建的所有新功能都必须遵循[Flux 架构](https://facebook.github.io/flux/) . 我们试图实现的主要目标是只有一个数据流和一个数据条目. 为了实现此目标,我们使用[vuex](#vuex) . + +您还可以在 Vue 文档中了解有关[状态管理](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch)和[数据流的一种方式的](https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow)此体系结构. + +### Components and Store[](#components-and-store "Permalink") + +在使用 Vue.js 实现的某些功能(例如[问题](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/boards)公告[板](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/boards)或[环境表)中,](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/environments)您可以找到明确的关注点分离: + +``` +new_feature +├── components +│ └── component.vue +│ └── ... +├── store +│ └── new_feature_store.js +├── index.js +``` + +*为了保持一致性,我们建议您采用相同的结构.* + +Let’s look into each of them: + +### An `index.js` file[](#an-indexjs-file "Permalink") + +这是新功能的索引文件. 这是新功能的根 Vue 实例所在的位置. + +应在此文件中导入和初始化商店和服务,并作为主要组件的道具提供. + +请务必阅读[特定](./performance.html#page-specific-javascript)于[页面的 JavaScript](./performance.html#page-specific-javascript) . + +### Bootstrapping Gotchas[](#bootstrapping-gotchas "Permalink") + +#### Providing data from HAML to JavaScript[](#providing-data-from-haml-to-javascript "Permalink") + +挂载 Vue 应用程序时,可能需要从 Rails 向 JavaScript 提供数据. 为此,您可以使用 HTML 元素中的`data`属性,并在安装应用程序时查询它们. + +*Note:* You should only do this while initializing the application, because the mounted element will be replaced with Vue-generated DOM. + +通过`render`函数中的`props`将数据从 DOM 提供给 Vue 实例而不是查询主 Vue 组件内部的 DOM 的好处是避免了在单元测试中创建固定装置或 HTML 元素的需要,因为它将进行测试更轻松. 请参见以下示例: + +``` +// haml +.js-vue-app{ data: { endpoint: 'foo' }} + +// index.js +document.addEventListener('DOMContentLoaded', () => new Vue({ + el: '.js-vue-app', + data() { + const dataset = this.$options.el.dataset; + return { + endpoint: dataset.endpoint, + }; + }, + render(createElement) { + return createElement('my-component', { + props: { + endpoint: this.endpoint, + }, + }); + }, +})); +``` + +#### Accessing the `gl` object[](#accessing-the-gl-object "Permalink") + +当我们需要查询`gl`对象以获取在应用程序生命周期内不会更改的数据时,我们应该在查询 DOM 的同一位置进行处理. 通过遵循这种做法,我们可以避免模拟`gl`对象的需求,这将使测试更加容易. 应该在初始化我们的 Vue 实例时完成,并且数据应作为主要组件的`props`提供: + +``` +document.addEventListener('DOMContentLoaded', () => new Vue({ + el: '.js-vue-app', + render(createElement) { + return createElement('my-component', { + props: { + username: gon.current_username, + }, + }); + }, +})); +``` + +#### Accessing feature flags[](#accessing-feature-flags "Permalink") + +使用 Vue 的[提供/注入](https://vuejs.org/v2/api/#provide-inject)机制使功能标志可用于 Vue 应用程序中的任何后代组件. `glFeatures`对象已经在`commons/vue.js` ,因此仅需要 mixin 即可使用这些标志: + +``` +// An arbitrary descendant component + +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; + +export default { + // ... + mixins: [glFeatureFlagsMixin()], + // ... + created() { + if (this.glFeatures.myFlag) { + // ... + } + }, +} +``` + +这种方法有一些好处: + +* 任意深度嵌套的组件都可以选择加入并访问该标志,而中间组件则不知道(例如,通过 prop 将标志向下传递). +* 良好的可测试性,因为可以从`vue-test-utils`将该标志提供给`mount` / `shallowMount` ,只是作为一个道具. + + ``` + import { shallowMount } from '@vue/test-utils'; + + shallowMount(component, { + provide: { + glFeatures: { myFlag: true }, + }, + }); + ``` + +* 除了在应用程序的[入口点](#accessing-the-gl-object)之外,无需访问全局变量. + +### A folder for Components[](#a-folder-for-components "Permalink") + +此文件夹包含此新功能特定的所有组件. 如果您需要使用或创建可能在其他地方使用的组件,请参考`vue_shared/components` . + +了解何时创建组件的一个很好的经验法则是考虑它是否可以在其他地方重用. + +例如,表在整个 GitLab 中被大量使用,表非常适合组件. 另一方面,仅在一个表中使用的表单元格不能很好地利用此模式. + +您可以在 Vue.js 网站[Component System 中](https://vuejs.org/v2/guide/#Composing-with-Components)阅读有关组件的更多信息. + +### A folder for the Store[](#a-folder-for-the-store "Permalink") + +#### Vuex[](#vuex "Permalink") + +检查此[页面](vuex.html)以获取更多详细信息. + +### Mixing Vue and jQuery[](#mixing-vue-and-jquery "Permalink") + +* 不建议将 Vue 和 jQuery 混合使用. +* 如果您需要在 Vue 中使用特定的 jQuery 插件,请[围绕它创建一个包装器](https://vuejs.org/v2/examples/select2.html) . +* Vue 使用 jQuery 事件侦听器侦听现有的 jQuery 事件是可以接受的. +* 不建议为 Vue 添加新的 jQuery 事件以与 jQuery 交互. + +## Style guide[](#style-guide "Permalink") + +在编写 Vue 组件和模板时,请参考我们的[样式指南](style/vue.html)的 Vue 部分以获取最佳实践. + +## Testing Vue Components[](#testing-vue-components "Permalink") + +每个 Vue 组件都有一个唯一的输出. 此输出始终存在于 render 函数中. + +尽管我们可以分别测试 Vue 组件的每种方法,但我们的目标必须是测试 render / template 函数的输出,该输出始终代表状态. + +这是[此 Vue 组件](#appendix---vue-component-subject-under-test)结构良好的单元测试的示例: + +``` +import { shallowMount } from '@vue/test-utils'; +import { GlLoadingIcon } from '@gitlab/ui'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; +import App from '~/todos/app.vue'; + +const TEST_TODOS = [ + { text: 'Lorem ipsum test text' }, + { text: 'Lorem ipsum 2' }, +]; +const TEST_NEW_TODO = 'New todo title'; +const TEST_TODO_PATH = '/todos'; + +describe('~/todos/app.vue', () => { + let wrapper; + let mock; + + beforeEach(() => { + // IMPORTANT: Use axios-mock-adapter for stubbing axios API requests + mock = new MockAdapter(axios); + mock.onGet(TEST_TODO_PATH).reply(200, TEST_TODOS); + mock.onPost(TEST_TODO_PATH).reply(200); + }); + + afterEach(() => { + // IMPORTANT: Clean up the component instance and axios mock adapter + wrapper.destroy(); + wrapper = null; + + mock.restore(); + }); + + // NOTE: It is very helpful to separate setting up the component from + // its collaborators (i.e. Vuex, axios, etc.) + const createWrapper = (props = {}) => { + wrapper = shallowMount(App, { + propsData: { + path: TEST_TODO_PATH, + ...props, + }, + }); + }; + // NOTE: Helper methods greatly help test maintainability and readability. + const findLoader = () => wrapper.find(GlLoadingIcon); + const findAddButton = () => wrapper.find('[data-testid="add-button"]'); + const findTextInput = () => wrapper.find('[data-testid="text-input"]'); + const findTodoData = () => wrapper.findAll('[data-testid="todo-item"]').wrappers.map(wrapper => ({ text: wrapper.text() })); + + describe('when mounted and loading', () => { + beforeEach(() => { + // Create request which will never resolve + mock.onGet(TEST_TODO_PATH).reply(() => new Promise(() => {})); + createWrapper(); + }); + + it('should render the loading state', () => { + expect(findLoader().exists()).toBe(true); + }); + }); + + describe('when todos are loaded', () => { + beforeEach(() => { + createWrapper(); + // IMPORTANT: This component fetches data asynchronously on mount, so let's wait for the Vue template to update + return wrapper.vm.$nextTick(); + }); + + it('should not show loading', () => { + expect(findLoader().exists()).toBe(false); + }); + + it('should render todos', () => { + expect(findTodoData()).toEqual(TEST_TODOS); + }); + + it('when todo is added, should post new todo', () => { + findTextInput().vm.$emit('update', TEST_NEW_TODO) + findAddButton().vm.$emit('click'); + + return wrapper.vm.$nextTick() + .then(() => { + expect(mock.history.post.map(x => JSON.parse(x.data))).toEqual([{ text: TEST_NEW_TODO }]); + }); + }); + }); +}); +``` + +### Test the component’s output[](#test-the-components-output "Permalink") + +Vue 组件的主要返回值是渲染的输出. 为了测试组件,我们需要测试渲染的输出. [Vue](https://vuejs.org/v2/guide/unit-testing.html)指南的单元测试向我们确切地表明: + +### Events[](#events "Permalink") + +我们应该测试响应组件中的操作而发出的事件,这对于验证是否使用正确的参数触发了正确的事件很有用. + +对于任何 DOM 事件,我们都应使用[`trigger`](https://vue-test-utils.vuejs.org/api/wrapper/#trigger)来触发事件. + +``` +// Assuming SomeButton renders: <button>Some button</button> +wrapper = mount(SomeButton); + +... +it('should fire the click event', () => { + const btn = wrapper.find('button') + + btn.trigger('click'); + ... +}) +``` + +当我们需要触发 Vue 事件时,我们应该使用[`emit`](https://vuejs.org/v2/guide/components-custom-events.html)事件来触发事件. + +``` +wrapper = shallowMount(DropdownItem); + +... + +it('should fire the itemClicked event', () => { + DropdownItem.vm.$emit('itemClicked'); + ... +}) +``` + +我们应该通过对[`emitted()`](https://vue-test-utils.vuejs.org/api/wrapper/#emitted)方法的结果进行断言来验证事件已被触发 + +## Vue.js Expert Role[](#vuejs-expert-role "Permalink") + +仅当您自己的合并请求并且您的评论显示时,您才应该申请成为 Vue.js 专家: + +* 对 Vue 和 Vuex 反应性的深入了解 +* Vue 和 Vuex 代码是根据官方规范和我们的准则构建的 +* 全面了解测试 Vue 和 Vuex 应用程序 +* Vuex 代码遵循[记录的模式](vuex.html#naming-pattern-request-and-receive-namespaces) +* 有关现有 Vue 和 Vuex 应用程序以及现有可重用组件的知识 + +## Vue 2 -> Vue 3 Migration[](#vue-2---vue-3-migration "Permalink") + +> 暂时添加此部分是为了支持将代码库从 Vue 2.x 迁移到 Vue 3.x 的工作. + +当前,我们建议尽量减少向代码库中添加某些功能,以防止增加最终迁移的技​​术负担: + +* filters; +* 活动巴士; +* 功能模板化 +* `slot` attributes + +您可以找到有关[迁移到 Vue 3 的](vue3_migration.html)更多详细信息 + +## Appendix - Vue component subject under test[](#appendix---vue-component-subject-under-test "Permalink") + +这是示例组件的模板,已在" [测试 Vue 组件"](#testing-vue-components)部分中进行了[测试](#testing-vue-components) : + +``` +<template> + <div class="content"> + <gl-loading-icon v-if="isLoading" /> + <template v-else> + <div + v-for="todo in todos" + :key="todo.id" + :class="{ 'gl-strike': todo.isDone }" + data-testid="todo-item" + >{{ toddo.text }}</div> + <footer class="gl-border-t-1 gl-mt-3 gl-pt-3"> + <gl-form-input + type="text" + v-model="todoText" + data-testid="text-input" + > + <gl-button + variant="success" + data-testid="add-button" + @click="addTodo" + >Add</gl-button> + </footer> + </template> + </div> +</template> +``` \ No newline at end of file diff --git a/docs/605.md b/docs/605.md new file mode 100644 index 0000000000000000000000000000000000000000..324bc30ba62337bd22cb76da5986e53caf4d98d7 --- /dev/null +++ b/docs/605.md @@ -0,0 +1,443 @@ +# Geo (development) + +> 原文:[https://docs.gitlab.com/ee/development/geo.html](https://docs.gitlab.com/ee/development/geo.html) + +* [Replication layer](#replication-layer) + * [Geo Log Cursor daemon](#geo-log-cursor-daemon) + * [Database replication](#database-replication) + * [Repository replication](#repository-replication) + * [Project Registry](#project-registry) + * [Repository Sync worker](#repository-sync-worker) + * [Uploads replication](#uploads-replication) + * [Upload Registry](#upload-registry) + * [File Download Dispatch worker](#file-download-dispatch-worker) +* [Authentication](#authentication) +* [Git Push to Geo secondary](#git-push-to-geo-secondary) +* [Using the Tracking Database](#using-the-tracking-database) + * [Configuration](#configuration) + * [Foreign Data Wrapper](#foreign-data-wrapper) + * [Refreshing the Foreign Tables](#refreshing-the-foreign-tables) + * [Accessing data from a Foreign Table](#accessing-data-from-a-foreign-table) +* [Finders](#finders) + * [Finders Performance](#finders-performance) +* [Redis](#redis) +* [Object Storage](#object-storage) +* [Verification](#verification) + * [Repository verification](#repository-verification) +* [Glossary](#glossary) + * [Primary node](#primary-node) + * [Secondary node](#secondary-node) + * [Streaming replication](#streaming-replication) + * [Tracking database](#tracking-database) + * [FDW](#fdw) +* [Geo Event Log](#geo-event-log) + * [Geo Log Cursor](#geo-log-cursor) +* [Code features](#code-features) + * [`Gitlab::Geo` utilities](#gitlabgeo-utilities) + * [Current node](#current-node) + * [Primary or secondary](#primary-or-secondary) + * [Geo Database configured?](#geo-database-configured) + * [Enablement](#enablement) + * [Read-only](#read-only) +* [Steps needed to replicate a new data type](#steps-needed-to-replicate-a-new-data-type) + * [Geo self-service framework (alpha)](#geo-self-service-framework-alpha) +* [History of communication channel](#history-of-communication-channel) + * [Custom code (GitLab 8.6 and earlier)](#custom-code-gitlab-86-and-earlier) + * [System hooks (GitLab 8.7 to 9.5)](#system-hooks-gitlab-87-to-95) + * [Geo Log Cursor (GitLab 10.0 and up)](#geo-log-cursor-gitlab-100-and-up) +* [Self-service framework](#self-service-framework) + +# Geo (development)[](#geo-development-premium-only "Permalink") + +Geo 将 GitLab 实例连接在一起. 一个 GitLab 实例被指定**为主**节点,并且可以与多个**辅助**节点一起运行. Geo 精心策划了很多组件,这些组件可以在下图中看到,并在本文档中进行了更详细的描述. + +[![Geo Architecture Diagram](img/5f13fe556b8940c2e698facdc219d16a.png)](../administration/geo/replication/img/geo_architecture.png) + +## Replication layer[](#replication-layer "Permalink") + +Geo 处理不同组件的复制: + +* [数据库](#database-replication) :包括整个应用程序,缓存和作业除外. +* [Git 存储库](#repository-replication) :包括项目和 Wiki. +* [上载的 Blob](#uploads-replication) :包括从问题附带的图像到 CI 的原始日志和资产的所有内容. + +除数据库复制外,在*辅助*节点上,所有内容均由[Geo Log Cursor](#geo-log-cursor)协调. + +### Geo Log Cursor daemon[](#geo-log-cursor-daemon "Permalink") + +[Geo Log Cursor 守护程序](#geo-log-cursor-daemon)是在每个**辅助**节点上运行的单独进程. 它监视[地理事件日志中](#geo-event-log)是否有新事件,并为每种特定事件类型创建后台作业. + +例如,当更新存储库时,Geo **主**节点会创建一个带有关联的存储库更新事件的 Geo 事件. Geo Log Cursor 守护程序接收事件并安排一个`Geo::ProjectSyncWorker`作业,该作业将使用`Geo::RepositorySyncService`和`Geo::WikiSyncService`类分别更新存储库和 Wiki. + +Geo Log Cursor 守护程序可以自动在高可用性模式下运行. 守护程序将不时尝试获取锁,一旦获得锁定,它将充当*活动*守护程序. + +在同一节点上的所有其他正在运行的守护程序都将处于待机模式,如果*活动*守护程序释放其锁定,则可以恢复工作. + +We use the [`ExclusiveLease`](https://www.rubydoc.info/github/gitlabhq/gitlabhq/Gitlab/ExclusiveLease) lock type with a small TTL, that is renewed at every pooling cycle. That allows us to implement this global lock with a timeout. + +在池化周期结束时,如果守护程序无法更新和/或重新获得锁定,它将切换到待机模式. + +### Database replication[](#database-replication "Permalink") + +Geo 使用[流复制](#streaming-replication)将数据库从**主**节点[复制](#streaming-replication)到**辅助**节点. 通过此复制, **辅助**节点可以访问数据库中保存的所有数据. 因此,用户可以登录**次级**和读取所有的问题,合并请求等**辅助**节点上. + +### Repository replication[](#repository-replication "Permalink") + +Geo 还复制存储库. 每个**辅助**节点都[跟踪跟踪数据库](#tracking-database)中每个存储库的状态. + +存在以下几种方式来复制存储库: + +* [Repository Sync worker](#repository-sync-worker). +* [Geo Log Cursor](#geo-log-cursor). + +#### Project Registry[](#project-registry "Permalink") + +`Geo::ProjectRegistry`类定义用于跟踪存储库复制状态的模型. 对于主数据库中的每个项目,在跟踪数据库中保留一个记录. + +它记录有关存储库的以下内容: + +* 他们上次同步的时间. +* 上一次成功同步它们. +* 是否需要重新同步. +* 重试的时间. +* 重试次数. +* 是否以及何时进行验证. + +它还将项目 Wiki 的这些属性存储在专用列中. + +#### Repository Sync worker[](#repository-sync-worker "Permalink") + +The `Geo::RepositorySyncWorker` class runs periodically in the background and it searches the `Geo::ProjectRegistry` model for projects that need updating. Those projects can be: + +* 未同步:从未在**辅助**节点上同步过的项目,因此尚不存在. +* 最近更新:项目的`last_repository_updated_at`时间戳比`Geo::ProjectRegistry`模型中的`last_repository_successful_sync_at`时间戳更新. +* 手动:管理员可以在[地理管理面板中](../user/admin_area/geo_nodes.html)手动标记存储库以重新同步. + +当我们在次要`RETRIES_BEFORE_REDOWNLOAD`时间内无法获取存储库时,Geo 会进行所谓的*重新下载* . 它将干净地克隆到存储根目录中的`@geo-temporary`目录中. 成功后,我们用新克隆的仓库替换主仓库. + +### Uploads replication[](#uploads-replication "Permalink") + +文件上传也被复制到**辅助**节点. 为了跟踪同步状态,使用了`Geo::UploadRegistry`模型. + +#### Upload Registry[](#upload-registry "Permalink") + +与[项目注册表](#project-registry)类似,有一个`Geo::UploadRegistry`模型可以跟踪同步的上传. + +CI Job Artifacts and LFS objects are synced in a similar way as uploads, but they are tracked by `Geo::JobArtifactRegistry`, and `Geo::LfsObjectRegistry` models respectively. + +#### File Download Dispatch worker[](#file-download-dispatch-worker "Permalink") + +还类似于[Repository Sync 工作器](#repository-sync-worker) ,有一个`Geo::FileDownloadDispatchWorker`类,该类定期运行以同步所有尚未同步到 Geo **辅助**节点的上载. + +通过 HTTP 复制文件,并通过`/api/v4/geo/transfers/:type/:id`端点(例如`/api/v4/geo/transfers/lfs/123` . + +## Authentication[](#authentication "Permalink") + +为了验证文件传输,每个`GeoNode`记录都有两个字段: + +* 公共访问密钥( `access_key`字段). +* 秘密访问密钥( `secret_access_key`字段). + +**次要**节点通过[JWT 请求进行](https://jwt.io/)身份验证. 当**辅助**节点希望下载文件时,它将发送带有`Authorization`标头的 HTTP 请求: + +``` +Authorization: GL-Geo <access_key>:<JWT payload> +``` + +**主**节点使用`access_key`字段查找相应的**辅助**节点并解密 JWT 有效负载,该负载包含用于标识文件请求的其他信息. 这样可以确保**辅助**节点为正确的数据库 ID 下载正确的文件. 例如,对于 LFS 对象,请求还必须包含文件的 SHA256 和. JWT 有效负载示例如下所示: + +``` +{ "data": { sha256: "31806bb23580caab78040f8c45d329f5016b0115" }, iat: "1234567890" } +``` + +如果请求的文件与请求的 SHA256 总和匹配,则 Geo **主**节点将通过[X-Sendfile](https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/)功能发送数据,这使 NGINX 可以处理文件传输而不会占用 Rails 或 Workhorse. + +**注意:** JWT 需要在所涉及的机器之间同步时钟,否则它可能会因加密错误而失败. + +## Git Push to Geo secondary[](#git-push-to-geo-secondary "Permalink") + +Git Push Proxy 作为`gitlab-shell`组件内置的功能存在. 它仅在**辅助**节点上处于活动状态. 它允许从辅助节点克隆存储库的用户推送到相同的 URL. + +定向到**次**节点的 Git `push`请求将发送到**主**节点,而`pull`请求将继续由**次**节点服务,以实现最大效率. + +HTTPS 和 SSH 请求的处理方式不同: + +* 使用 HTTPS,我们将为用户提供指向**主**节点上项目的`HTTP 302 Redirect` . Git 客户端足够聪明,可以理解该状态码并处理重定向. +* 使用 SSH,因为没有等效的方法来执行重定向,所以我们必须代理请求. 这是在[`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell)内部[`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell) ,方法是先将请求转换为 HTTP 协议,然后将其代理到**主**节点. + +[`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell)守护程序根据`/api/v4/allowed`的响应知道何时进行代理. 返回一个特殊的`HTTP 300`状态代码,我们执行在响应正文中指定的"自定义操作". 该响应包含允许代理`push`操作在**主**节点上发生的其他数据. + +## Using the Tracking Database[](#using-the-tracking-database "Permalink") + +除了要复制的主数据库外,Geo **辅助**节点还具有自己的单独的[跟踪数据库](#tracking-database) . + +跟踪数据库包含**辅助**节点的状态. + +任何需要在升级过程中运行的数据库迁移都需要应用于每个**辅助**节点上的跟踪数据库. + +### Configuration[](#configuration "Permalink") + +数据库配置在[`config/database_geo.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/config/database_geo.yml.postgresql)设置. [`ee/db/geo`](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/db/geo)目录包含此数据库的架构和迁移. + +要为数据库编写迁移,请使用`GeoMigrationGenerator` : + +``` +rails g geo_migration [args] [options] +``` + +要迁移跟踪数据库,请运行: + +``` +bundle exec rake geo:db:migrate +``` + +### Foreign Data Wrapper[](#foreign-data-wrapper "Permalink") + +在 GitLab 10.1 中引入. + +[地理日志游标](#geo-log-cursor)使用了外部数据包装器( [FDW](#fdw) ),并提高了许多同步操作的性能. + +FDW 是 PostgreSQL 扩展( [`postgres_fdw`](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html) ),已在 Geo Tracking 数据库中(在**辅助**节点上)启用,它允许它连接到只读数据库副本并执行查询和过滤来自两个实例的数据. + +该持久连接被配置为名为`gitlab_secondary`的 FDW 服务器. 此配置仅存在于数据库的用户上下文中. 要访问`gitlab_secondary` ,GitLab 需要使用先前配置的同一数据库用户. + +地理跟踪数据库以常规用户身份通过​​FDW 访问只读数据库副本,受其自身限制的限制. 凭据被配置为与先前映射的`SERVER` ( `gitlab_secondary` )相关联的`USER MAPPING` . + +FDW 配置和凭据定义由 Omnibus GitLab `gitlab-ctl reconfigure`命令自动管理. + +#### Refreshing the Foreign Tables[](#refreshing-the-foreign-tables "Permalink") + +每当在**主**节点上配置了新的地理节点或数据库架构更改时,都必须通过运行以下命令来刷新**辅助**节点上的外部表: + +``` +bundle exec rake geo:db:refresh_foreign_tables +``` + +否则,将阻止**辅助**节点正常运行. **辅助**节点将生成错误消息,如以下 PostgreSQL 错误所示: + +``` +ERROR: relation "gitlab_secondary.ci_job_artifacts" does not exist at character 323 +STATEMENT: SELECT a.attname, format_type(a.atttypid, a.atttypmod), + pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod + FROM pg_attribute a LEFT JOIN pg_attrdef d + ON a.attrelid = d.adrelid AND a.attnum = d.adnum + WHERE a.attrelid = '"gitlab_secondary"."ci_job_artifacts"'::regclass + AND a.attnum > 0 AND NOT a.attisdropped + ORDER BY a.attnum +``` + +#### Accessing data from a Foreign Table[](#accessing-data-from-a-foreign-table "Permalink") + +在 SQL 级别,您要做的就是从`gitlab_secondary.*` `SELECT`数据. + +这是一个如何从地理跟踪数据库的 FDW 访问所有项目的示例: + +``` +SELECT * FROM gitlab_secondary.projects; +``` + +作为一个更真实的示例,这是在"跟踪数据库"中过滤未归档项目的方式: + +``` +SELECT project_registry.* + FROM project_registry + JOIN gitlab_secondary.projects + ON (project_registry.project_id = gitlab_secondary.projects.id + AND gitlab_secondary.projects.archived IS FALSE) +``` + +在 ActiveRecord 级别,我们还有其他表示外部表的模型. 必须以稍微不同的方式映射它们,并且它们是只读的. + +检查`ee/app/models/geo/fdw`现有的 FDW 模型以供参考. + +从开发人员的角度来看,这与创建代表数据库视图的模型没有什么不同. + +通过上面的示例,您可以通过以下方式访问项目: + +``` +Geo::Fdw::Project.all +``` + +并通过未归档的项目访问`ProjectRegistry`过滤: + +``` +# We have to use Arel here: +project_registry_table = Geo::ProjectRegistry.arel_table +fdw_project_table = Geo::Fdw::Project.arel_table + +project_registry_table.join(fdw_project_table) + .on(project_registry_table[:project_id].eq(fdw_project_table[:id])) + .where((fdw_project_table[:archived]).eq(true)) # if you append `.to_sql` you can check generated query +``` + +## Finders[](#finders "Permalink") + +Geo 使用[Finders](https://gitlab.com/gitlab-org/gitlab/tree/master/app/finders) ,这是一些类,可以帮助您轻松查找项目/附件/等. 在跟踪数据库和主数据库中. + +### Finders Performance[](#finders-performance "Permalink") + +查找者需要将主数据库中的数据与跟踪数据库中的数据进行比较. 例如,计算已同步项目的数量通常涉及从一个数据库中检索项目 ID,并检查它们在另一个数据库中的状态. 这很慢并且需要大量内存. + +为了克服这个问题,查找器使用[FDW](#fdw)或外部数据包装器. 这允许在主数据库和跟踪数据库之间进行常规的`JOIN` . + +## Redis[](#redis "Permalink") + +Redis 的**辅助**节点上的工作方式相同的**主**节点上. 它用于缓存,存储会话和其他持久性数据. + +不使用**主**节点和**辅助**节点之间的 Redis 数据复制,因此会话等不在节点之间共享. + +## Object Storage[](#object-storage "Permalink") + +GitLab 可以选择使用对象存储来存储否则将存储在磁盘上的数据. 这些事情可以是: + +* LFS Objects +* CI 工作工件 +* Uploads + +Geo 不处理存储在对象存储中的对象. Geo 会忽略对象存储中的项目. 要么: + +* 对象存储层应注意其自身的地理复制. +* 所有辅助节点应使用相同的存储节点. + +## Verification[](#verification "Permalink") + +### Repository verification[](#repository-verification "Permalink") + +存储库将通过校验和进行验证. + +**主**节点在存储库上计算校验和. 它基本上将所有 Git 引用散列在一起,并将该散列存储在数据库的`project_repository_states`表中. + +**次**节点执行相同操作以计算其克隆的哈希,然后将哈希与**主**节点计算出的值进行比较. 如果存在不匹配,Geo 会将其标记为不匹配,管理员可以在[Geo 管理面板中](../user/admin_area/geo_nodes.html)看到此不匹配. + +## Glossary[](#glossary "Permalink") + +### Primary node[](#primary-node "Permalink") + +**主**节点是地理设置中具有读写功能的单个节点. 这是事实的唯一来源,Geo **次要**节点从那里复制数据. + +在地理位置设置中,只能有一个**主**节点. 所有**辅助**节点都连接到该**主**节点. + +### Secondary node[](#secondary-node "Permalink") + +**辅助**节点是在不同地理位置运行的**主要**节点的只读副本. + +### Streaming replication[](#streaming-replication "Permalink") + +Geo 取决于 PostgreSQL 的流复制功能. 它完全复制数据库数据和数据库模式. 数据库副本是只读副本. + +流复制取决于预写日志或 WAL. 这些日志将复制到副本并在此处重放. + +由于流复制还可以复制架构,因此数据库迁移不需要在辅助节点上运行. + +### Tracking database[](#tracking-database "Permalink") + +每个 Geo **辅助**节点上的数据库,该数据库保留其所在节点的状态. 在[使用跟踪数据库中](#using-the-tracking-database)阅读更多[信息](#using-the-tracking-database) . + +### FDW[](#fdw "Permalink") + +外部数据包装程序(FDW)是 PostgreSQL 内置的功能. 它允许从不同的数据源查询数据. 在 Geo 中,它用于查询来自不同 PostgreSQL 实例的数据. + +## Geo Event Log[](#geo-event-log "Permalink") + +Geo **主数据库**将事件存储在`geo_event_log`表中. 日志中的每个条目都包含特定类型的事件. 这些类型的事件包括: + +* 存储库已删除事件 +* 存储库重命名事件 +* 存储库更改事件 +* 存储库创建事件 +* 哈希存储迁移事件 +* Lfs 对象已删除事件 +* 哈希存储附件事件 +* Job Artifact Deleted 事件 +* 上载已删除的活动 + +### Geo Log Cursor[](#geo-log-cursor "Permalink") + +在寻找新的`Geo::EventLog`行的**辅助**节点上运行的进程. + +## Code features[](#code-features "Permalink") + +### `Gitlab::Geo` utilities[](#gitlabgeo-utilities "Permalink") + +与 Geo 相关的小型实用工具方法进入[`ee/lib/gitlab/geo.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/gitlab/geo.rb)文件. + +其中许多方法都使用`RequestStore`类进行缓存,以减少在整个代码库中使用这些方法对性能的影响. + +#### Current node[](#current-node "Permalink") + +类方法`.current_node`返回当前节点的`GeoNode`记录. + +我们使用`gitlab.yml`的`host` , `port`和`relative_url_root`值,并在数据库中搜索以标识我们所在的节点(请参见`GeoNode.current_node` ). + +#### Primary or secondary[](#primary-or-secondary "Permalink") + +要确定当前节点是**主**节点还是**辅助**节点,请使用`.primary?` 和`.secondary?` 类方法. + +当未启用节点时,这些方法都可能在节点上都返回`false` . 请参阅[启用](#enablement) . + +#### Geo Database configured?[](#geo-database-configured "Permalink") + +处理初始化期间发生的事情时,还有一个附加的陷阱. 在一些地方,我们使用`Gitlab::Geo.geo_database_configured?` 检查节点是否具有跟踪数据库的方法,该数据库仅存在于**辅助**节点上. 这克服了在引导新节点期间可能发生的竞争条件. + +#### Enablement[](#enablement "Permalink") + +当用户拥有包括功能的有效许可证,并且在"地理节点"屏幕上定义了至少一个节点时,我们认为地理功能已启用. + +See `Gitlab::Geo.enabled?` and `Gitlab::Geo.license_allows?` methods. + +#### Read-only[](#read-only "Permalink") + +所有地理**辅助**节点均为只读. + +[只读数据库](verifying_database_capabilities.html#read-only-database)的一般原则适用于所有 Geo **辅助**节点. 那么`Gitlab::Database.read_only?` 方法将始终在**辅助**节点上返回`true` . + +当由于节点是**辅助**节点而不允许某些写操作时,请考虑添加`Gitlab::Database.read_only?` 还是`Gitlab::Database.read_write?` 后卫,而不是`Gitlab::Geo.secondary?` . + +在复制的设置中,数据库本身已经是只读的,因此我们无需为此采取任何额外的步骤. + +## Steps needed to replicate a new data type[](#steps-needed-to-replicate-a-new-data-type "Permalink") + +随着 GitLab 的发展,我们不断需要向 Geo 复制系统添加新资源. 具体实现取决于资源的具体情况,但是需要注意以下几点: + +* 主站点上的事件生成. 每当更改/更新新资源时,我们都需要为 Log Cursor 创建一个任务. +* 事件处理. 日志游标需要为主站点生成的每种事件类型都有一个处理程序. +* 派遣工人(临时工). 确保回填条件良好. +* 同步工作者. +* 注册所有可能的状态. +* Verification. +* 清洁器. 更改辅助站点的同步设置后,需要清理一些资源. +* 地理节点状态. 我们需要在 GitLab 管理区域中提供 API 端点以及一些演示. +* 健康检查. 如果我们可以执行一些预检查并在出现问题时使节点不正常,则应该这样做. `rake gitlab:geo:check`命令也必须更新. + +### Geo self-service framework (alpha)[](#geo-self-service-framework-alpha "Permalink") + +我们开始开发新的[Geo 自助服务框架(alpha)](geo/framework.html) ,这使添加新数据类型变得容易得多. + +## History of communication channel[](#history-of-communication-channel "Permalink") + +自从第一次迭代以来,沟通渠道已经发生了变化,您可以在此处查看历史性决策以及我们为何迁移到新实现的原因. + +### Custom code (GitLab 8.6 and earlier)[](#custom-code-gitlab-86-and-earlier "Permalink") + +在 8.6 之前的 GitLab 版本中,自定义代码用于处理 HTTP 请求从**主**节点到**辅助**节点的通知. + +### System hooks (GitLab 8.7 to 9.5)[](#system-hooks-gitlab-87-to-95 "Permalink") + +后来,决定放弃自定义代码,开始使用系统挂钩. 使用它们的人越来越多,因此许多人将从对该通信层进行的改进中受益. + +我们的 API 代码(Grape)中有一个特定的**内部**端点,该端点接收来自此系统挂钩的所有请求: `/api/v4/geo/receive_events` . + +我们通过`event_name`字段切换和过滤每个事件. + +### Geo Log Cursor (GitLab 10.0 and up)[](#geo-log-cursor-gitlab-100-and-up "Permalink") + +从 GitLab 10.0 开始,不再使用[系统 Webhooks](#system-hooks-gitlab-87-to-95) , [而是](#system-hooks-gitlab-87-to-95)使用 Geo Log Cursor. 日志光标遍历`Geo::EventLog`行以查看自上次检查日志以来是否有更改,并将处理存储库更新,删除,更改和重命名. + +该表位于复制的数据库中. 与旧方法相比,它具有两个优点: + +* 复制是同步的,我们保留事件的顺序. +* 事件的复制与数据库中的更改同时发生. + +## Self-service framework[](#self-service-framework "Permalink") + +如果您想为正在处理的资源添加简单的地理复制,请查看我们的[自助服务框架](geo/framework.html) . \ No newline at end of file diff --git a/docs/606.md b/docs/606.md new file mode 100644 index 0000000000000000000000000000000000000000..d5d26fe00d62df05b5b16f0f789a12c2070d8dc7 --- /dev/null +++ b/docs/606.md @@ -0,0 +1,512 @@ +# Geo self-service framework (alpha) + +> 原文:[https://docs.gitlab.com/ee/development/geo/framework.html](https://docs.gitlab.com/ee/development/geo/framework.html) + +* [Nomenclature](#nomenclature) +* [Geo Domain-Specific Language](#geo-domain-specific-language) + * [The replicator](#the-replicator) + * [Linking to a model](#linking-to-a-model) + * [API](#api) + * [Library](#library) +* [Existing Replicator Strategies](#existing-replicator-strategies) + * [Blob Replicator Strategy](#blob-replicator-strategy) + * [Replication](#replication) + * [Verification](#verification) + * [Metrics](#metrics) + * [GraphQL API](#graphql-api) + * [Admin UI](#admin-ui) + +# Geo self-service framework (alpha)[](#geo-self-service-framework-alpha "Permalink") + +**注意:**本文档可能会随时更改. 这是我们正在研究的建议,一旦实施完成,此文档将得到更新. 跟随[史诗般的](https://gitlab.com/groups/gitlab-org/-/epics/2161)进度.**注意:** Geo 自助服务框架当前处于 Alpha 状态. 如果您需要复制新的数据类型,请与 Geo 小组联系以讨论选项. 您可以在 Slack 的`#g_geo`与他们联系,或在问题或合并请求中提及`@geo-team` . + +Geo 提供了一个 API,使跨 Geo 节点轻松复制数据类型成为可能. 该 API 以 Ruby 域特定语言(DSL)的形式呈现,旨在使创建数据类型的工程师只需花费很少的精力即可复制数据. + +## Nomenclature[](#nomenclature "Permalink") + +在深入研究 API 之前,开发人员需要了解一些特定于地理位置的命名约定. + +Model + +模型是活动模型,在整个 Rails 代码库中都是如此. 它通常与数据库表绑定. 从地理角度来看,模型可以具有一个或多个资源. + +Resource + +资源是属于模型的一条数据,由 GitLab 功能生成. 使用存储机制将其持久化. 默认情况下,资源不可复制. + +Data type + +Data type is how a resource is stored. Each resource should fit in one of the data types Geo supports: :- Git repository :- Blob :- Database + +有关更多详细信息,请参见[数据类型](../../administration/geo/replication/datatypes.html) . + +Geo Replicable + +可复制资源是 Geo 希望在 Geo 节点之间同步的资源. 受支持的可复制数据类型有限. 实现属于已知数据类型之一的资源的复制所需的工作量很小. + +Geo Replicator + +地理复制器是知道如何复制可复制对象的对象. 它负责::-触发事件(生产者):-消费事件(消费者) + +它与 Geo Replicable 数据类型相关. 所有复制器都有一个公共接口,可用于处理(即产生和使用)事件. 它负责主节点(产生事件的地方)和次节点(消耗事件的地方)之间的通信. 想要将 Geo 纳入其功能的工程师将使用复制器的 API 来实现这一目标. + +Geo Domain-Specific Language + +语法糖使工程师可以轻松指定应复制哪些资源以及如何复制. + +## Geo Domain-Specific Language[](#geo-domain-specific-language "Permalink") + +### The replicator[](#the-replicator "Permalink") + +首先,您需要编写一个复制器. 复制器位于[`ee/app/replicators/geo`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/app/replicators/geo) . 对于每个需要复制的资源,即使多个资源绑定到同一模型,也应指定一个单独的复制器. + +例如,以下复制器复制软件包文件: + +``` +module Geo + class PackageFileReplicator < Gitlab::Geo::Replicator + # Include one of the strategies your resource needs + include ::Geo::BlobReplicatorStrategy + + # Specify the CarrierWave uploader needed by the used strategy + def carrierwave_uploader + model_record.file + end + + # Specify the model this replicator belongs to + def self.model + ::Packages::PackageFile + end + end +end +``` + +类名应该是唯一的. 它还与注册表的表名紧密相关,因此在此示例中,注册表表将为`package_file_registry` . + +对于不同的数据类型,Geo 支持包括不同的策略. 选择一个适合您的需求. + +### Linking to a model[](#linking-to-a-model "Permalink") + +要将此复制器绑定到模型,需要在模型代码中添加以下内容: + +``` +class Packages::PackageFile < ApplicationRecord + include ::Gitlab::Geo::ReplicableModel + + with_replicator Geo::PackageFileReplicator +end +``` + +### API[](#api "Permalink") + +设置好后,可以通过模型轻松访问复制器: + +``` +package_file = Packages::PackageFile.find(4) # just a random id as example +replicator = package_file.replicator +``` + +或者从复制器取回模型: + +``` +replicator.model_record +=> <Packages::PackageFile id:4> +``` + +复制器可用于生成事件,例如在 ActiveRecord 挂钩中: + +``` + after_create_commit -> { replicator.publish_created_event } +``` + +#### Library[](#library "Permalink") + +所有这些背后的框架位于[`ee/lib/gitlab/geo/`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/lib/gitlab/geo) . + +## Existing Replicator Strategies[](#existing-replicator-strategies "Permalink") + +在编写一种新的复制器策略之前,请检查以下内容,以查看现有策略之一是否已经可以处理您的资源. 如果不确定,请咨询地理团队. + +### Blob Replicator Strategy[](#blob-replicator-strategy "Permalink") + +使用`Geo::BlobReplicatorStrategy`模块,Geo 可以轻松支持使用[CarrierWave 的](https://github.com/carrierwaveuploader/carrierwave) `Uploader::Base`模型. + +首先,每个文件应具有其自己的主要 ID 和模型. Geo 强烈建议将*每个文件都*视为头等公民,因为根据我们的经验,这大大简化了跟踪复制和验证状态. + +例如,要添加对具有`Widget` `widgets`表的`Widget`模型引用的文件的支持,您将执行以下步骤: + +#### Replication[](#replication "Permalink") + +1. 在`Widget`类中包含`Gitlab::Geo::ReplicableModel` ,并使用`with_replicator Geo::WidgetReplicator`指定 Replicator 类. + + 此时, `Widget`类应如下所示: + + ``` + # frozen_string_literal: true + + class Widget < ApplicationRecord + include ::Gitlab::Geo::ReplicableModel + + with_replicator Geo::WidgetReplicator + + mount_uploader :file, WidgetUploader + + def self.replicables_for_geo_node + # Should be implemented. The idea of the method is to restrict + # the set of synced items depending on synchronization settings + end + ... + end + ``` + +2. 创建`ee/app/replicators/geo/widget_replicator.rb` . 实现`#carrierwave_uploader`方法,该方法应返回`CarrierWave::Uploader` . 并实现类方法`.model`以返回`Widget`类. + + ``` + # frozen_string_literal: true + + module Geo + class WidgetReplicator < Gitlab::Geo::Replicator + include ::Geo::BlobReplicatorStrategy + + def self.model + ::Widget + end + + def carrierwave_uploader + model_record.file + end + end + end + ``` + +3. 创建`ee/spec/replicators/geo/widget_replicator_spec.rb`并执行必要的设置,以定义共享示例的`model_record`变量. + + ``` + # frozen_string_literal: true + + require 'spec_helper' + + RSpec.describe Geo::WidgetReplicator do + let(:model_record) { build(:widget) } + + it_behaves_like 'a blob replicator' + end + ``` + +4. 创建`widget_registry`表,以便 Geo 次要对象可以跟踪每个 Widget 文件的同步和验证状态: + + ``` + # frozen_string_literal: true + + class CreateWidgetRegistry < ActiveRecord::Migration[6.0] + DOWNTIME = false + + disable_ddl_transaction! + + def up + unless table_exists?(:widget_registry) + ActiveRecord::Base.transaction do + create_table :widget_registry, id: :bigserial, force: :cascade do |t| + t.integer :widget_id, null: false + t.integer :state, default: 0, null: false, limit: 2 + t.integer :retry_count, default: 0, limit: 2 + t.text :last_sync_failure + t.datetime_with_timezone :retry_at + t.datetime_with_timezone :last_synced_at + t.datetime_with_timezone :created_at, null: false + + t.index :widget_id + t.index :retry_at + t.index :state + end + end + end + + add_text_limit :widget_registry, :last_sync_failure, 255 + end + + def down + drop_table :widget_registry + end + end + ``` + +5. Create `ee/app/models/geo/widget_registry.rb`: + + ``` + # frozen_string_literal: true + + class Geo::WidgetRegistry < Geo::BaseRegistry + include Geo::ReplicableRegistry + + MODEL_CLASS = ::Widget + MODEL_FOREIGN_KEY = :widget_id + + belongs_to :widget, class_name: 'Widget' + end + ``` + + 方法`has_create_events?` 在大多数情况下应该返回`true` . 但是,如果您添加的实体没有创建事件,则根本不要添加该方法. + +6. Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`. + +7. Create `ee/spec/factories/geo/widget_registry.rb`: + + ``` + # frozen_string_literal: true + + FactoryBot.define do + factory :geo_widget_registry, class: 'Geo::WidgetRegistry' do + widget + state { Geo::WidgetRegistry.state_value(:pending) } + + trait :synced do + state { Geo::WidgetRegistry.state_value(:synced) } + last_synced_at { 5.days.ago } + end + + trait :failed do + state { Geo::WidgetRegistry.state_value(:failed) } + last_synced_at { 1.day.ago } + retry_count { 2 } + last_sync_failure { 'Random error' } + end + + trait :started do + state { Geo::WidgetRegistry.state_value(:started) } + last_synced_at { 1.day.ago } + retry_count { 0 } + end + end + end + ``` + +8. Create `ee/spec/models/geo/widget_registry_spec.rb`: + + ``` + # frozen_string_literal: true + + require 'spec_helper' + + RSpec.describe Geo::WidgetRegistry, :geo, type: :model do + let_it_be(:registry) { create(:geo_widget_registry) } + + specify 'factory is valid' do + expect(registry).to be_valid + end + + include_examples 'a Geo framework registry' + + describe '.find_registry_differences' do + ... # To be implemented + end + end + ``` + +小部件现在应该由 Geo 复制! + +#### Verification[](#verification "Permalink") + +1. 将验证状态字段添加到`widgets`表中,以便 Geo 主数据库可以跟踪验证状态: + + ``` + # frozen_string_literal: true + + class AddVerificationStateToWidgets < ActiveRecord::Migration[6.0] + DOWNTIME = false + + def change + add_column :widgets, :verification_retry_at, :datetime_with_timezone + add_column :widgets, :verified_at, :datetime_with_timezone + add_column :widgets, :verification_checksum, :binary, using: 'verification_checksum::bytea' + add_column :widgets, :verification_failure, :string + add_column :widgets, :verification_retry_count, :integer + end + end + ``` + +2. 在`verification_failure`和`verification_checksum`上添加部分索引,以确保可以高效执行重新验证: + + ``` + # frozen_string_literal: true + + class AddVerificationFailureIndexToWidgets < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :widgets, :verification_failure, where: "(verification_failure IS NOT NULL)", name: "widgets_verification_failure_partial" + add_concurrent_index :widgets, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: "widgets_verification_checksum_partial" + end + + def down + remove_concurrent_index :widgets, :verification_failure + remove_concurrent_index :widgets, :verification_checksum + end + end + ``` + +要做的事情:在二级服务器上添加验证. 这应作为以下内容的一部分完成[:Geo:自助服务框架-包文件验证的首次实现](https://gitlab.com/groups/gitlab-org/-/epics/1817) + +小部件现在应由 Geo 验证! + +#### Metrics[](#metrics "Permalink") + +指标由`Geo::MetricsUpdateWorker`收集,保存在`GeoNodeStatus`以显示在 UI 中,然后发送给 Prometheus. + +1. 将字段`widget_count` , `widget_checksummed_count` , `widget_checksum_failed_count` , `widget_synced_count` , `widget_failed_count`和`widget_registry_count`到`ee/app/models/geo_node_status.rb` `GeoNodeStatus#RESOURCE_STATUS_FIELDS`数组中. +2. 将相同的字段添加到`ee/app/models/geo_node_status.rb` `GeoNodeStatus#PROMETHEUS_METRICS`哈希中. +3. 将相同字段添加到`doc/administration/monitoring/prometheus/gitlab_metrics.md` `Sidekiq metrics`表中. +4. 将相同的字段添加到`doc/api/geo_nodes.md` `GET /geo_nodes/status`示例响应中. +5. 将相同的字段添加到`ee/spec/models/geo_node_status_spec.rb`和`ee/spec/factories/geo_node_statuses.rb` . +6. Set `widget_count` in `GeoNodeStatus#load_data_from_current_node`: + + ``` + self.widget_count = Geo::WidgetReplicator.primary_total_count + ``` + +7. 添加`GeoNodeStatus#load_widgets_data`来设置`widget_synced_count` , `widget_failed_count`和`widget_registry_count` : + + ``` + def load_widget_data + self.widget_synced_count = Geo::WidgetReplicator.synced_count + self.widget_failed_count = Geo::WidgetReplicator.failed_count + self.widget_registry_count = Geo::WidgetReplicator.registry_count + end + ``` + +8. Call `GeoNodeStatus#load_widgets_data` in `GeoNodeStatus#load_secondary_data`. + +9. Set `widget_checksummed_count` and `widget_checksum_failed_count` in `GeoNodeStatus#load_verification_data`: + + ``` + self.widget_checksummed_count = Geo::WidgetReplicator.checksummed_count self.widget_checksum_failed_count = Geo::WidgetReplicator.checksum_failed_count + ``` + +小部件复制和验证指标现在应该可以在 API,管理区域 UI 和 Prometheus 中使用! + +#### GraphQL API[](#graphql-api "Permalink") + +1. 在`ee/app/graphql/types/geo/geo_node_type.rb`向`GeoNodeType`添加一个新字段: + + ``` + field :widget_registries, ::Types::Geo::WidgetRegistryType.connection_type, + null: true, + resolver: ::Resolvers::Geo::WidgetRegistriesResolver, + description: 'Find widget registries on this Geo node', + feature_flag: :geo_self_service_framework + ``` + +2. 新添加`widget_registries`字段名的`expected_fields`在阵列`ee/spec/graphql/types/geo/geo_node_type_spec.rb` . + +3. Create `ee/app/graphql/resolvers/geo/widget_registries_resolver.rb`: + + ``` + # frozen_string_literal: true + + module Resolvers + module Geo + class WidgetRegistriesResolver < BaseResolver + include RegistriesResolver + end + end + end + ``` + +4. Create `ee/spec/graphql/resolvers/geo/widget_registries_resolver_spec.rb`: + + ``` + # frozen_string_literal: true + + require 'spec_helper' + + RSpec.describe Resolvers::Geo::WidgetRegistriesResolver do + it_behaves_like 'a Geo registries resolver', :geo_widget_registry + end + ``` + +5. Create `ee/app/finders/geo/widget_registry_finder.rb`: + + ``` + # frozen_string_literal: true + + module Geo + class WidgetRegistryFinder + include FrameworkRegistryFinder + end + end + ``` + +6. Create `ee/spec/finders/geo/widget_registry_finder_spec.rb`: + + ``` + # frozen_string_literal: true + + require 'spec_helper' + + RSpec.describe Geo::WidgetRegistryFinder do + it_behaves_like 'a framework registry finder', :geo_widget_registry + end + ``` + +7. Create `ee/app/graphql/types/geo/widget_registry_type.rb`: + + ``` + # frozen_string_literal: true + + module Types + module Geo + # rubocop:disable Graphql/AuthorizeTypes because it is included + class WidgetRegistryType < BaseObject + include ::Types::Geo::RegistryType + + graphql_name 'WidgetRegistry' + description 'Represents the sync and verification state of a widget' + + field :widget_id, GraphQL::ID_TYPE, null: false, description: 'ID of the Widget' + end + end + end + ``` + +8. Create `ee/spec/graphql/types/geo/widget_registry_type_spec.rb`: + + ``` + # frozen_string_literal: true + + require 'spec_helper' + + RSpec.describe GitlabSchema.types['WidgetRegistry'] do + it_behaves_like 'a Geo registry type' + + it 'has the expected fields (other than those included in RegistryType)' do + expected_fields = %i[widget_id] + + expect(described_class).to have_graphql_fields(*expected_fields).at_least + end + end + ``` + +9. Add integration tests for providing Widget registry data to the frontend via the GraphQL API, by duplicating and modifying the following shared examples in `ee/spec/requests/api/graphql/geo/registries_spec.rb`: + + ``` + it_behaves_like 'gets registries for', { + field_name: 'widgetRegistries', + registry_class_name: 'WidgetRegistry', + registry_factory: :geo_widget_registry, + registry_foreign_key_field_name: 'widgetId' + } + ``` + +现在应该可以通过 GraphQL API 获得各个小部件同步和验证数据! + +1. 注意复制"更新"事件. Geo Framework 目前不支持复制"更新"事件,因为此时添加到框架的所有实体都是不可变的. 如果您要添加的实体属于这种情况,请遵循[https://gitlab.com/gitlab-org/gitlab/-/issues/118743](https://gitlab.com/gitlab-org/gitlab/-/issues/118743)和[https://gitlab.com/gitlab-org/gitlab /// issues / 118745](https://gitlab.com/gitlab-org/gitlab/-/issues/118745)作为添加新事件类型的示例. 添加通知后,请同时删除它. + +#### Admin UI[](#admin-ui "Permalink") + +要做的事情:这应该作为《 [地理手册》的](https://gitlab.com/groups/gitlab-org/-/epics/2525)一部分完成[:实现自助服务框架可复制的前端](https://gitlab.com/groups/gitlab-org/-/epics/2525) + +窗口小部件同步和验证数据(总计和个人)现在应该在管理界面中可用! \ No newline at end of file diff --git a/docs/607.md b/docs/607.md new file mode 100644 index 0000000000000000000000000000000000000000..3c3a4441909167e62f561a2156875dda8af65245 --- /dev/null +++ b/docs/607.md @@ -0,0 +1,311 @@ +# Gitaly developers guide + +> 原文:[https://docs.gitlab.com/ee/development/gitaly.html](https://docs.gitlab.com/ee/development/gitaly.html) + +* [Deep Dive](#deep-dive) +* [Beginner’s guide](#beginners-guide) +* [Developing new Git features](#developing-new-git-features) + * [`gitaly-ruby`](#gitaly-ruby) +* [Gitaly-Related Test Failures](#gitaly-related-test-failures) +* [Legacy Rugged code](#legacy-rugged-code) +* [`TooManyInvocationsError` errors](#toomanyinvocationserror-errors) +* [Request counts](#request-counts) +* [Running tests with a locally modified version of Gitaly](#running-tests-with-a-locally-modified-version-of-gitaly) + * [Use a locally modified version of Gitaly RPC client](#use-a-locally-modified-version-of-gitaly-rpc-client) +* [Wrapping RPCs in Feature Flags](#wrapping-rpcs-in-feature-flags) + * [Gitaly](#gitaly) + * [GitLab Rails](#gitlab-rails) + * [Testing with GDK](#testing-with-gdk) + +# Gitaly developers guide[](#gitaly-developers-guide "Permalink") + +[Gitaly](https://gitlab.com/gitlab-org/gitaly)是 GitLab Rails,Workhorse 和 GitLab Shell 使用的高级 Git RPC 服务. + +## Deep Dive[](#deep-dive "Permalink") + +在 2019 年 5 月,Bob Van Landuyt 主持了有关 GitLab 的[Gitaly 项目](https://gitlab.com/gitlab-org/gitaly)以及如何以 Ruby 的形式进行的 Deep Dive(仅限 GitLab 团队成员: `https://gitlab.com/gitlab-org/create-stage/issues/1` : [//gitlab.com/gitlab-org/create-stage/issues/1](https://gitlab.com/gitlab-org/gitaly) )开发人员,以便与将来可能在代码库这一部分工作的任何人共享他的特定领域知识. + +您可以[在 YouTube 上](https://www.youtube.com/watch?v=BmlEWFS8ORo)找到[录音](https://www.youtube.com/watch?v=BmlEWFS8ORo) ,在[Google 幻灯片](https://docs.google.com/presentation/d/1VgRbiYih9ODhcPnL8dS0W98EwFYpJ7GXMPpX-1TM6YE/edit)和[PDF 中](https://gitlab.com/gitlab-org/create-stage/uploads/a4fdb1026278bda5c1c5bb574379cf80/Create_Deep_Dive__Gitaly_for_Create_Ruby_Devs.pdf)找到[幻灯片](https://docs.google.com/presentation/d/1VgRbiYih9ODhcPnL8dS0W98EwFYpJ7GXMPpX-1TM6YE/edit) . + +截至 GitLab 11.11 为止,本次深入介绍中涉及的所有内容都是准确的,尽管自那时以来特定细节可能有所更改,但它仍应作为一个很好的介绍. + +## Beginner’s guide[](#beginners-guide "Permalink") + +首先阅读 Gitaly 存储库的[Gitaly 贡献初学者指南](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/beginners_guide.md) . 它描述了如何设置 Gitaly,Gitaly 的各个组件以及它们的作用以及如何运行其测试套件. + +## Developing new Git features[](#developing-new-git-features "Permalink") + +要读取或写入 Git 数据,必须向 Gitaly 发出请求. 这意味着如果您要开发一项新功能,则需要`lib/gitlab/git`尚不可用的数据,则必须对 Gitaly 进行更改. + +> 这是一个尚未明确定义的新过程. 如果您想提供 Git 功能,但遇到困难,请与 Gitaly 团队或`@jacobvosmaer-gitlab` . + +"新功能"是指`lib/gitlab/git`中从`lib/gitlab/git`外部调用的任何方法或类. 有关从`lib/gitlab/git`内部调用的新方法,请参见下面的"修改现有 Git 功能". + +在`lib/gitlab/git`之外的任何地方,都不应有任何通过磁盘访问(例如 Rugged, `git` , `rm -rf` )接触 Git 存储库的新代码. + +添加新的 Gitaly 功能的过程是: + +* 探索/原型制作 +* 在[`gitaly-proto`](https://gitlab.com/gitlab-org/gitaly-proto)设计和创建新的 Gitaly RPC +* 发行新版本的`gitaly-proto` +* 用 Go 或 Ruby [在 Gitaly 中](https://gitlab.com/gitlab-org/gitaly)编写 RPC 的实现和测试 +* release a new version of Gitaly +* 在调用新 Gitaly RPC 的 GitLab CE / EE,GitLab Workhorse 或 GitLab Shell 中编写客户端代码 + +这些步骤经常重叠. 在测试和开发过程中,可以使用未发行的 Gitaly 和`gitaly-proto`版本. + +* 有关使用未发布的协议编写服务器端代码的说明,请参见[Gitaly 存储库](https://gitlab.com/gitlab-org/gitaly/blob/master/CONTRIBUTING.md#development-and-testing-with-a-custom-gitaly-proto) . +* 有关使用修改后的 Gitaly 版本运行 GitLab CE 测试的说明,请参见[下文](#running-tests-with-a-locally-modified-version-of-gitaly) . +* 在 GDK 中运行`gdk install`并重新启动`gdk run` (或`gdk run app` )以使用本地修改的 Gitaly 版本进行开发 + +### `gitaly-ruby`[](#gitaly-ruby "Permalink") + +可以在[`gitaly-ruby`](https://gitlab.com/gitlab-org/gitaly/tree/master/ruby)使用 Ruby 代码在[`gitaly-ruby`](https://gitlab.com/gitlab-org/gitaly/tree/master/ruby)实现和测试 RPC. 这应该使对不喜欢编写 Go 代码的开发人员的贡献更加容易. + +[Gitaly 存储库](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/ruby_endpoint.md)中提供[了](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/ruby_endpoint.md)有关此方法[的文档](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/ruby_endpoint.md) . + +## Gitaly-Related Test Failures[](#gitaly-related-test-failures "Permalink") + +如果您的测试套件因 Gitaly 问题而失败,请首先尝试运行: + +``` +rm -rf tmp/tests/gitaly +``` + +在 RSpec 测试期间,Gitaly 实例会将日志写入`gitlab/log/gitaly-test.log` . + +## Legacy Rugged code[](#legacy-rugged-code "Permalink") + +尽管 Gitaly 可以处理所有 Git 访问,但许多 GitLab 客户仍在 NFS 上运行 Gitaly. 由于 N + 1 个 Gitaly 调用和其他原因,用于 Git 调用的传统 Rugged 实现可能比 Gitaly RPC 更快. 有关更多详细信息,请参见[问题](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/57317) . + +在 GitLab 消除了大多数这些低效率问题或对 Git 数据停止使用 NFS 之前,可以通过功能标志启用某些最常用 RPC 的 Rugged 实现: + +* `rugged_find_commit` +* `rugged_get_tree_entries` +* `rugged_tree_entry` +* `rugged_commit_is_ancestor` +* `rugged_commit_tree_entry` +* `rugged_list_commits_by_oid` + +方便的 Rake 任务可用于一起启用或禁用这些标志. 启用: + +``` +bundle exec rake gitlab:features:enable_rugged +``` + +禁用: + +``` +bundle exec rake gitlab:features:disable_rugged +``` + +此代码大部分存在于`lib/gitlab/git/rugged_impl`目录中. + +**注意:**除非与[Gitaly Team](https://gitlab.com/groups/gl-gitaly/group_members)明确讨论,否则您无需添加或修改与 Rugged 相关的代码. 此代码不适用于 GitLab.com 或其他不使用 NFS 的 GitLab 实例. + +## `TooManyInvocationsError` errors[](#toomanyinvocationserror-errors "Permalink") + +在开发和测试过程中,您可能会遇到`Gitlab::GitalyClient::TooManyInvocationsError`故障. 该`GitalyClient`将试图通过时 Gitaly 被称为 30 倍以上在单个的 Rails 请求或 Sidekiq 执行提高此错误来阻止对潜在的 n + 1 点的问题. + +作为临时措施,导出`GITALY_DISABLE_REQUEST_LIMITS=1`以消除该错误. 这将在开发环境中禁用 n + 1 检测. + +请在 GitLab CE 或 EE 存储库中提出问题,以报告该问题. 包括标签〜Gitaly〜性能〜"技术债务". 请确保问题包含完整的堆栈跟踪和`TooManyInvocationsError`错误消息. 如果可能,还包括任何已知的失败测试. + +找出 n + 1 问题的根源. 通常,这将是一个循环,导致对数组中的每个元素调用 Gitaly. 如果您无法找出问题所在,请与[Gitaly 小组](https://gitlab.com/groups/gl-gitaly/group_members)成员联系以寻求帮助. + +找到源之后,将其包装在`allow_n_plus_1_calls`块中,如下所示: + +``` +# n+1: link to n+1 issue +Gitlab::GitalyClient.allow_n_plus_1_calls do + # original code + commits.each { |commit| ... } +end +``` + +一旦将代码包装在此块中,将从 n + 1 检测中排除此代码路径. + +## Request counts[](#request-counts "Permalink") + +提交和其他 Git 数据现在通过 Gitaly 获取. 可以像数据库一样批处理这些提取. 这样可以提高客户端以及 Gitaly 本身以及用户的性能. 为了保持性能稳定并防止性能下降,可以对 Gitaly 通话进行计数,并可以对通话计数进行测试. 这需要设置`:request_store`标志. + +``` +describe 'Gitaly Request count tests' do + context 'when the request store is activated', :request_store do + it 'correctly counts the gitaly requests made' do + expect { subject }.to change { Gitlab::GitalyClient.get_request_count }.by(10) + end + end +end +``` + +## Running tests with a locally modified version of Gitaly[](#running-tests-with-a-locally-modified-version-of-gitaly "Permalink") + +通常,GitLab CE / EE 测试在`tmp/tests/gitaly`使用 Gitaly 的本地克隆,固定在`GITALY_SERVER_VERSION`指定的版本上. `GITALY_SERVER_VERSION`文件还支持分支和 SHA,以在[https://gitlab.com/gitlab-org/gitaly 中](https://gitlab.com/gitlab-org/gitaly)使用自定义提交. + +**注:**通过引入自动部署 Gitaly 的,格式`GITALY_SERVER_VERSION`用总括的语法一致. 它不再支持`=revision` ,它将评估文件内容作为 Git 引用(分支或 SHA),仅当它与 semver 匹配时才在`v` . + +如果要针对修改后的 Gitaly 版本在本地运行测试,则可以用符号链接替换`tmp/tests/gitaly` . 这要快得多,因为这样可以避免每次运行`rspec`时都重新安装 Gitaly. + +``` +rm -rf tmp/tests/gitaly +ln -s /path/to/gitaly tmp/tests/gitaly +``` + +在运行测试之前,请确保在本地 Gitaly 目录中运行`make` . 否则,Gitaly 将无法启动. + +如果您在两次测试之间更改了本地 Gitaly,则需要再次手动运行`make` . + +请注意,CI 测试不会使用您本地修改的 Gitaly 版本. 要在 CI 中使用自定义 Gitaly 版本,您需要按照本段开头所述更新 GITALY_SERVER_VERSION. + +要使用其他 Gitaly 存储库(例如,如果您的更改出现在 fork 上),则可以在运行测试时指定`GITALY_REPO_URL`环境变量: + +``` +GITALY_REPO_URL=https://gitlab.com/nick.thomas/gitaly bundle exec rspec spec/lib/gitlab/git/repository_spec.rb +``` + +如果您的 Gitaly 分支是私有的,则可以生成一个[Deploy Token](../user/project/deploy_tokens/index.html)并在 URL 中指定它: + +``` +GITALY_REPO_URL=https://gitlab+deploy-token-1000:token-here@gitlab.com/nick.thomas/gitaly bundle exec rspec spec/lib/gitlab/git/repository_spec.rb +``` + +要在 CI 中使用自定义的 Gitaly 存储库,例如,如果您希望 GitLab 分支始终使用自己的 Gitaly 分支,请将`GITALY_REPO_URL`设置为[CI 环境变量](../ci/variables/README.html#gitlab-cicd-environment-variables) . + +### Use a locally modified version of Gitaly RPC client[](#use-a-locally-modified-version-of-gitaly-rpc-client "Permalink") + +如果要对 RPC 客户端进行更改,例如添加新端点或向现有端点添加新参数,请遵循[Gitaly proto](https://gitlab.com/gitlab-org/gitaly/blob/master/proto/README.md)指南. 在推送具有更改的分支(例如`new-feature-branch` )之后: + +1. 将 Rails 的`Gemfile`的`gitaly`行更改为: + + ``` + gem 'gitaly', git: 'https://gitlab.com/gitlab-org/gitaly.git', branch: 'new-feature-branch' + ``` + +2. 运行`bundle install`以使用修改后的 RPC 客户端. + +* * * + +[Return to Development documentation](README.html) + +## Wrapping RPCs in Feature Flags[](#wrapping-rpcs-in-feature-flags "Permalink") + +以下是在功能标记后在 Gitaly 中选通新功能的步骤. + +### Gitaly[](#gitaly "Permalink") + +1. 创建一个包范围的标志名: + + ``` + var findAllTagsFeatureFlag = "go-find-all-tags" + ``` + +2. 使用`featureflag`包在代码中创建一个开关: + + ``` + if featureflag.IsEnabled(ctx, findAllTagsFeatureFlag) { + // go implementation + } else { + // ruby implementation + } + ``` + +3. 创建 Prometheus 指标: + + ``` + var findAllTagsRequests = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "gitaly_find_all_tags_requests_total", + Help: "Counter of go vs ruby implementation of FindAllTags", + }, + []string{"implementation"}, + ) + + func init() { + prometheus.Register(findAllTagsRequests) + } + + if featureflag.IsEnabled(ctx, findAllTagsFeatureFlag) { + findAllTagsRequests.WithLabelValues("go").Inc() + // go implementation + } else { + findAllTagsRequests.WithLabelValues("ruby").Inc() + // ruby implementation + } + ``` + +4. Set headers in tests: + + ``` + import ( + "google.golang.org/grpc/metadata" + + "gitlab.com/gitlab-org/gitaly/internal/featureflag" + ) + + //... + + md := metadata.New(map[string]string{featureflag.HeaderKey(findAllTagsFeatureFlag): "true"}) + ctx = metadata.NewOutgoingContext(context.Background(), md) + + c, err = client.FindAllTags(ctx, rpcRequest) + require.NoError(t, err) + ``` + +### GitLab Rails[](#gitlab-rails "Permalink") + +1. 通过设置功能标记在 Rails 控制台中进行测试: + + **注意:请**注意标志的名称以及在 Rails 控制台中使用的标志的名称. 它们之间是有区别的(用下划线代替短划线,并且更改了名称前缀). 确保在所有标志`gitaly_`加上`gitaly_` . + + ``` + Feature.enable('gitaly_go_find_all_tags') + ``` + +### Testing with GDK[](#testing-with-gdk "Permalink") + +为确保正确设置该标志并将其放入 Gitaly 中,可以使用 GDK 检查集成: + +1. 标志的状态必须是可观察的. 要检查它,您需要通过获取 Prometheus 指标来启用它: + 1. 导航到 GDK 的根目录. + 2. 确保您已经为 Gitaly 签出了正确的分支. + 3. 使用`make gitaly-setup`重新编译它,并使用`gdk restart gitaly`重新启动服务. + 4. 确保您的设置正在运行: `gdk status | grep praefect` `gdk status | grep praefect` . + 5. 检查使用了什么配置文件: `cat ./services/praefect/run | grep praefect` `-config`标志的`cat ./services/praefect/run | grep praefect`值 + 6. 在配置文件中取消注释`prometheus_listen_addr`并运行`gdk restart gitaly` . +2. Make sure that the flag is not enabled yet: + 1. 执行触发更改所需的任何操作(项目创建,提交提交,观察历史记录等). + 2. 检查当前指标列表是否具有新的功能标记计数器: + + ``` + curl --silent http://localhost:9236/metrics | grep go_find_all_tags + ``` + +3. 一旦观察到新功能标志的度量标准并递增,就可以启用新功能: + 1. 导航到 GDK 的根目录. + 2. 启动一个 Rails 控制台: + + ``` + bundle install && bundle exec rails console + ``` + + 3. 检查功能标志列表: + + ``` + Feature :: Gitaly . server_feature_flags + ``` + + 应该禁用`"gitaly-feature-go-find-all-tags"=>"false"` . + + 4. 启用它: + + ``` + Feature . enable ( 'gitaly_go_find_all_tags' ) + ``` + + 5. 退出 Rails 控制台并执行触发更改所需的任何操作(项目创建,提交提交,观察历史记录等). + 6. 通过观察该功能的度量来确认该功能已启用: + + ``` + curl --silent http://localhost:9236/metrics | grep go_find_all_tags + ``` \ No newline at end of file diff --git a/docs/608.md b/docs/608.md new file mode 100644 index 0000000000000000000000000000000000000000..bae58bf95bcbb7ba748b298b9404cff2358df1cb --- /dev/null +++ b/docs/608.md @@ -0,0 +1 @@ +> 原文:[https://design.gitlab.com/](https://design.gitlab.com/) \ No newline at end of file diff --git a/docs/609.md b/docs/609.md new file mode 100644 index 0000000000000000000000000000000000000000..23efcd30f9d7a28e57cc8544fd5f3fc0aabd0759 --- /dev/null +++ b/docs/609.md @@ -0,0 +1,28 @@ +# GitLab development style guides + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/style/](https://docs.gitlab.com/ee/development/fe_guide/style/) + +* [JavaScript style guide](#javascript-style-guide) +* [SCSS style guide](#scss-style-guide) +* [HTML style guide](#html-style-guide) +* [Vue style guide](#vue-style-guide) + +# GitLab development style guides[](#gitlab-development-style-guides "Permalink") + +请参阅下面有关开发 GitLab 的相关样式指南,指南,棉绒和其他信息. + +## JavaScript style guide[](#javascript-style-guide "Permalink") + +我们使用`eslint`来实施我们的[JavaScript 样式指南](javascript.html) . 我们的指南基于出色的[AirBnB](https://github.com/airbnb/javascript)样式指南,并做了一些小改动. + +## SCSS style guide[](#scss-style-guide "Permalink") + +我们的[SCSS 约定](scss.html)通过[`scss-lint`](https://github.com/sds/scss-lint)强制执行. + +## HTML style guide[](#html-style-guide "Permalink") + +与其余代码库一致的编写[HTML 代码的](html.html)准则. + +## Vue style guide[](#vue-style-guide "Permalink") + +在[Vue 样式指南中](vue.html)可以找到有关 Vue 代码的准则和约定. \ No newline at end of file diff --git a/docs/610.md b/docs/610.md new file mode 100644 index 0000000000000000000000000000000000000000..3b538151a2165db464d5fa14a821eebec8fd0780 --- /dev/null +++ b/docs/610.md @@ -0,0 +1,244 @@ +# API style guide + +> 原文:[https://docs.gitlab.com/ee/development/api_styleguide.html](https://docs.gitlab.com/ee/development/api_styleguide.html) + +* [Instance variables](#instance-variables) +* [Entities](#entities) +* [Documentation](#documentation) +* [Methods and parameters description](#methods-and-parameters-description) +* [Declared parameters](#declared-parameters) + * [Exclude parameters from parent namespaces](#exclude-parameters-from-parent-namespaces) + * [When to use `declared(params)`](#when-to-use-declaredparams) +* [Array types](#array-types) + * [Automatic coercion of nil inputs](#automatic-coercion-of-nil-inputs) +* [Using HTTP status helpers](#using-http-status-helpers) +* [Using API path helpers in GitLab Rails codebase](#using-api-path-helpers-in-gitlab-rails-codebase) +* [Custom Validators](#custom-validators) + * [Using custom validators](#using-custom-validators) + * [Adding a new custom validator](#adding-a-new-custom-validator) +* [Internal API](#internal-api) +* [Avoiding N+1 problems](#avoiding-n1-problems) + * [Verifying with tests](#verifying-with-tests) +* [Testing](#testing) + +# API style guide[](#api-style-guide "Permalink") + +该样式指南建议 API 开发的最佳做法. + +## Instance variables[](#instance-variables "Permalink") + +请不要使用实例变量,不需要它们(我们不需要像在 Rails 视图中那样访问它们),可以使用局部变量. + +## Entities[](#entities "Permalink") + +始终使用[实体](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/entities)来呈现端点的有效负载. + +## Documentation[](#documentation "Permalink") + +API 端点必须随附[文档](documentation/styleguide.html#api) ,除非[文档](documentation/styleguide.html#api)在内部或在功能标志后面. 这些文档应位于同一合并请求中,或者在严格必要的情况下,应与原始合并请求具有相同的里程碑. + +## Methods and parameters description[](#methods-and-parameters-description "Permalink") + +每种方法都必须使用[Grape DSL](https://github.com/ruby-grape/grape#describing-methods)进行描述(有关示例,请参见[https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/environments.rb](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/environments.rb) ): + +* `desc`的方法的总结. 您应该将其传递给其他细节,例如: + * 添加端点时的 GitLab 版本. 如果它在功能标志后面,请提及: *该功能由:feature_flag_symbol 功能标志控制.* + * 如果不赞成使用端点,那么,何时删除它 +* `params`方法参数. 这充当[参数的](https://github.com/ruby-grape/grape#parameter-validation-and-coercion)描述, [验证和强制](https://github.com/ruby-grape/grape#parameter-validation-and-coercion) + +一个很好的例子如下: + +``` +desc 'Get all broadcast messages' do + detail 'This feature was introduced in GitLab 8.12.' + success Entities::BroadcastMessage +end +params do + optional :page, type: Integer, desc: 'Current page number' + optional :per_page, type: Integer, desc: 'Number of messages per page' +end +get do + messages = BroadcastMessage.all + + present paginate(messages), with: Entities::BroadcastMessage +end +``` + +## Declared parameters[](#declared-parameters "Permalink") + +> Grape 允许您仅访问由`params`块声明的`params` . 它过滤掉已传递但不允许的参数. + +– [https://github.com/ruby-grape/grape#declared](https://github.com/ruby-grape/grape#declared) + +### Exclude parameters from parent namespaces[](#exclude-parameters-from-parent-namespaces "Permalink") + +> 默认情况下, `declared(params)`包括在所有父名称空间中定义的参数. + +– [https://github.com/ruby-grape/grape#include-parent-namespaces](https://github.com/ruby-grape/grape#include-parent-namespaces) + +在大多数情况下,您将希望从父名称空间中排除参数: + +``` +declared(params, include_parent_namespaces: false) +``` + +### When to use `declared(params)`[](#when-to-use-declaredparams "Permalink") + +You should always use `declared(params)` when you pass the parameters hash as arguments to a method call. + +例如: + +``` +# bad +User.create(params) # imagine the user submitted `admin=1`... :) + +# good +User.create(declared(params, include_parent_namespaces: false).to_h) +``` + +> **注意:** `Hashie::Mash` `declared(params)`返回一个`Hashie::Mash`对象,您必须在其上调用`.to_h` . + +但是,当我们访问单个元素时,可以直接使用`params[key]` . + +例如: + +``` +# good +Model.create(foo: params[:foo]) +``` + +## Array types[](#array-types "Permalink") + +在 Grape v1.3 +中,必须使用`coerce_with`块定义数组类型,否则当从 API 请求传递字符串时,参数将无法验证. 有关更多详细信息,请参见[Grape 升级文档](https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#ensure-that-array-types-have-explicit-coercions) . + +### Automatic coercion of nil inputs[](#automatic-coercion-of-nil-inputs "Permalink") + +在 Grape v1.3.3 之前,具有`nil`值的 Array 参数将自动强制为空 Array. 但是,由于[v1.3.3 中的拉取请求,](https://github.com/ruby-grape/grape/pull/2040)情况不再如此. 例如,假设您定义一个具有可选参数的 PUT `/test`请求: + +``` +optional :user_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The user ids for this rule' +``` + +通常情况下,把一个请求`/test?user_ids`会导致葡萄传递`params`的`{ user_ids: nil }` . + +这可能会导致端点期望为空数组且无法正确处理`nil`输入的错误. 为了保留以前的行为,有一个辅助方法`coerce_nil_params_to_array!` 在所有 API 调用的`before`块中使用的代码: + +``` +before do + coerce_nil_params_to_array! +end +``` + +进行此更改后,对 PUT `/test?user_ids`的请求将使 Grape 传递的`params`为`{ user_ids: [] }` . + +[Grape Tracker 中](https://github.com/ruby-grape/grape/issues/2068)存在[一个未解决的问题,](https://github.com/ruby-grape/grape/issues/2068)可以使此操作更容易. + +## Using HTTP status helpers[](#using-http-status-helpers "Permalink") + +对于非 200 HTTP 响应,请使用`lib/api/helpers.rb`提供的帮助`lib/api/helpers.rb`以确保行为正确( `not_found!` , `no_content!`等). 这些将`throw` Grape 并中止端点的执行. + +对于`DELETE`请求,通常还应该`destroy_conditionally!`地使用`destroy_conditionally!` 默认情况下,helper 会在成功时返回`204 No Content`响应,或者在给定的`If-Unmodified-Since`标头超出范围时返回`412 Precondition Failed` . 该助手在传递的资源上调用`#destroy` ,但是您也可以通过传递一个块来实现自定义删除方法. + +## Using API path helpers in GitLab Rails codebase[](#using-api-path-helpers-in-gitlab-rails-codebase "Permalink") + +因为我们支持[在相对 URL 下安装 GitLab](../install/relative_url.html) ,所以在使用 Grape 生成的 API 路径帮助程序时必须考虑到这一点. 任何此类 API 路径帮助程序用法都必须包装在`expose_path`帮助程序调用中. + +例如: + +``` +- endpoint = expose_path(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid)) +``` + +## Custom Validators[](#custom-validators "Permalink") + +为了验证 API 请求中的某些参数,我们先验证它们,然后再进一步发送它们(例如 Gitaly). 以下是[自定义验证器](https://GitLab.com/gitlab-org/gitlab/-/tree/master/lib/api/validations/validators) ,到目前为止,我们已经添加了它们以及如何使用它们. 我们还编写了有关如何添加新的自定义验证器的指南. + +### Using custom validators[](#using-custom-validators "Permalink") + +* `FilePath`: + + GitLab 支持我们需要遍历文件路径的各种功能. [`FilePath`验证器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators/file_path.rb)针对不同情况验证参数值. 主要是,它使用`File::Separator`检查路径是否是相对路径,是否包含`../../`相对遍历,以及路径是否是绝对路径,例如`/etc/passwd/` . + +* `Git SHA`: + + [`Git SHA`验证器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators/git_sha.rb)检查 Git SHA 参数是否为有效的 SHA. 它通过使用[`commit.rb`](https://gitlab.com/gitlab-org/gitlab/-/commit/b9857d8b662a2dbbf54f46ecdcecb44702affe55#d1c10892daedb4d4dd3d4b12b6d071091eea83df_30_30)文件中提到的正则表达式进行检查. + +* `Absence`: + + [`Absence`验证器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators/absence.rb)检查给定参数哈希中是否缺少特定参数. + +* `IntegerNoneAny`: + + [`IntegerNoneAny`验证器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators/integer_none_any.rb)检查给定参数的值是`Integer` , `None`还是`Any` . 它仅允许上述任何一个值在请求中前进. + +* `ArrayNoneAny`: + + [`ArrayNoneAny`验证器](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators/array_none_any.rb)检查给定参数的值是`Array` , `None`还是`Any` . 它仅允许上述任何一个值在请求中前进. + +### Adding a new custom validator[](#adding-a-new-custom-validator "Permalink") + +自定义验证器是在将参数发送到平台进行进一步处理之前对其进行验证的好方法. 如果我们在一开始就识别出无效的参数,它将在服务器和平台之间来回保存一些时间. + +如果您需要添加自定义验证器,它将被添加到[`validators`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/validations/validators)目录中自己的文件中. 由于我们使用[Grape](https://github.com/ruby-grape/grape)添加 API,因此我们继承了`Grape::Validations::Base`类中的`Grape::Validations::Base`类. 现在,您要做的就是定义`validate_param!` 该方法具有两个参数: `params`哈希和要验证的`param`名称. + +该方法的主体进行了验证参数值的艰苦工作,并将适当的错误消息返回给调用方方法. + +最后,我们使用以下行注册验证器: + +``` +Grape::Validations.register_validator(<validator name as symbol>, ::API::Helpers::CustomValidators::<YourCustomValidatorClassName>) +``` + +添加验证器后,请确保将其`rspec`添加到其在[`validators`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/lib/api/validations/validators)目录中的自己的文件中. + +## Internal API[](#internal-api "Permalink") + +[内部 API](./internal_api.html)已记录供内部使用. 请保持最新状态,以便我们了解不同组件正在使用哪些端点. + +## Avoiding N+1 problems[](#avoiding-n1-problems "Permalink") + +为了避免在 API 端点中返回记录集合时常见的 N + 1 问题,我们应该使用预先加载. + +在 API 中执行此操作的标准方法是让模型实现一个名为`with_api_entity_associations`的范围,该范围将预加载 API 中返回的关联和数据. 在[`Issue`模型中](https://gitlab.com/gitlab-org/gitlab/blob/2fedc47b97837ea08c3016cf2fb773a0300a4a25/app/models/issue.rb#L62)可以看到此范围的示例. + +在同一个模型的 API 中有多个实体的情况下(例如`UserBasic` , `User`和`UserPublic` ),您应谨慎使用此范围. 可能是您针对最基本的实体进行了优化,并在该范围上建立了连续的实体. + +当在 Todos API 中返回时, `with_api_entity_associations`范围还将[自动](https://gitlab.com/gitlab-org/gitlab/blob/19f74903240e209736c7668132e6a5a735954e7c/app/models/todo.rb#L34)为`Todo` *目标* [预先加载数据](https://gitlab.com/gitlab-org/gitlab/blob/19f74903240e209736c7668132e6a5a735954e7c/app/models/todo.rb#L34) . + +有关预加载的更多上下文和讨论,请参阅[此合并请求](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25711) , [该合并请求](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25711)引入了作用域. + +### Verifying with tests[](#verifying-with-tests "Permalink") + +当 API 端点返回集合时,无论现在还是将来,始终添加一个测试以验证 API 端点没有 N + 1 问题. 我们可以使用[`ActiveRecord::QueryRecorder`](query_recorder.html)做到这一点. + +Example: + +``` +def make_api_request + get api('/foo', personal_access_token: pat) +end + +it 'avoids N+1 queries', :request_store do + # Firstly, record how many PostgreSQL queries the endpoint will make + # when it returns a single record + create_record + + control = ActiveRecord::QueryRecorder.new { make_api_request } + + # Now create a second record and ensure that the API does not execute + # any more queries than before + create_record + + expect { make_api_request }.not_to exceed_query_limit(control) +end +``` + +## Testing[](#testing "Permalink") + +在编写新的 API 端点的测试,可以考虑使用模式[夹具](./testing_guide/best_practices.html#fixtures)位于`/spec/fixtures/api/schemas` . 您可以`expect`响应匹配给定的架构: + +``` +expect(response).to match_response_schema('merge_requests') +``` + +另请参阅在测试中[验证 N + 1 性能](#verifying-with-tests) . \ No newline at end of file diff --git a/docs/611.md b/docs/611.md new file mode 100644 index 0000000000000000000000000000000000000000..5f8ad5f11f232aede3f7fb101f609daf7c34a15e --- /dev/null +++ b/docs/611.md @@ -0,0 +1,353 @@ +# Go standards and style guidelines + +> 原文:[https://docs.gitlab.com/ee/development/go_guide/](https://docs.gitlab.com/ee/development/go_guide/) + +* [Overview](#overview) +* [Dependency Management](#dependency-management) +* [Code Review](#code-review) + * [Security](#security) + * [Finding a reviewer](#finding-a-reviewer) +* [Code style and format](#code-style-and-format) + * [Automatic linting](#automatic-linting) +* [Dependencies](#dependencies) + * [Modules](#modules) + * [ORM](#orm) + * [Migrations](#migrations) +* [Testing](#testing) + * [Testing frameworks](#testing-frameworks) + * [Subtests](#subtests) + * [Better output in tests](#better-output-in-tests) + * [Table-Driven Tests](#table-driven-tests) + * [Defining test cases](#defining-test-cases) + * [Contents of the test case](#contents-of-the-test-case) + * [Variable names](#variable-names) + * [Benchmarks](#benchmarks) +* [Error handling](#error-handling) + * [Adding context](#adding-context) + * [Naming](#naming) + * [Checking Error types](#checking-error-types) + * [References for working with errors](#references-for-working-with-errors) +* [CLIs](#clis) +* [Daemons](#daemons) + * [Logging](#logging) + * [Structured (JSON) logging](#structured-json-logging) + * [How to use Logrus](#how-to-use-logrus) + * [Tracing and Correlation](#tracing-and-correlation) + * [Context](#context) +* [Dockerfiles](#dockerfiles) +* [Distributing Go binaries](#distributing-go-binaries) + * [Updating Go version](#updating-go-version) + * [Supporting multiple Go versions](#supporting-multiple-go-versions) +* [Secure Team standards and style guidelines](#secure-team-standards-and-style-guidelines) + * [Code style and format](#code-style-and-format-1) + +# Go standards and style guidelines[](#go-standards-and-style-guidelines "Permalink") + +本文档介绍了使用[Go 语言的](https://s0golang0org.icopy.site) GitLab 项目的各种指南和最佳实践. + +## Overview[](#overview "Permalink") + +GitLab 构建在[Ruby on Rails](https://rubyonrails.org/)之上,但我们还在有意义的项目中使用 Go. Go 是一种非常强大的语言,具有许多优点,最适合具有大量 IO(磁盘/网络访问),HTTP 请求,并行处理等的项目.由于我们在 git 上都有 Ruby on Rails 和 Go,因此我们应该仔细评估两者中哪一个最适合工作. + +该页面旨在根据我们的各种经验来定义和组织我们的 Go 准则. 几个项目是从不同的标准开始的,但仍然可以有一些具体说明. 它们将在各自的`README.md`或`PROCESS.md`文件中进行描述. + +## Dependency Management[](#dependency-management "Permalink") + +Go 使用基于源的策略进行依赖性管理. 依赖项从其源存储库中下载为源. 这不同于更常见的基于工件的策略,在后者中,依赖项是从与依赖项源存储库分开的程序包存储库中作为工件下载的. + +Go 在 1.11 之前没有对版本管理的一流支持. 该版本引入了 Go 模块和语义版本控制的使用. Go 1.12 引入了模块代理,它们可以用作客户端和源版本控制系统之间的中介,以及校验和数据库,可以用于验证依赖项下载的完整性. + +有关更多详细信息,请参见[Go 中的依赖管理](dependencies.html) . + +## Code Review[](#code-review "Permalink") + +我们遵循[Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)的通用原则. + +审阅者和维护者应注意: + +* `defer`功能:在需要时以及在`err`检查之后确保存在. +* 注入依赖项作为参数. +* 封送至 JSON 时,其 Void 结构(生成`null`而不是`[]` ). + +### Security[](#security "Permalink") + +安全是我们在 GitLab 的首要任务. 在代码审查期间,我们必须注意代码中可能存在的安全漏洞: + +* 使用文字/模板时的 XSS +* 使用大猩猩的 CSRF 保护 +* 使用没有已知漏洞的 Go 版本 +* 不要泄漏秘密令牌 +* SQL 注入 + +记住要运行[SAST](../../user/application_security/sast/index.html)和[依赖项扫描](../../user/application_security/dependency_scanning/index.html) 在您的项目(或至少是[gosec 分析器](https://gitlab.com/gitlab-org/security-products/analyzers/gosec) )上,并遵守我们的[安全要求](../code_review.html#security-requirements) . + +Web 服务器可以利用[Secure](https://github.com/unrolled/secure)等中间件的优势. + +### Finding a reviewer[](#finding-a-reviewer "Permalink") + +我们的许多项目规模太小,无法拥有专职维护人员. 这就是为什么我们在 GitLab 有一个共享的 Go 评论者池. 要查找审阅者,请使用手册"工程项目"页面上" GitLab"项目的["执行"部分](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_go) . + +要将您自己添加到此列表中,请将以下内容添加到[team.yml](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/team.yml)文件中的个人资料中,并请您的经理进行审核和合并. + +``` +projects: + gitlab: reviewer go +``` + +## Code style and format[](#code-style-and-format "Permalink") + +* 避免全局变量,即使在软件包中也是如此. 这样,如果多次包含该软件包,您将产生副作用. +* 在提交之前使用`goimports` . [goimports](https://s0godoc0org.icopy.site/golang.org/x/tools/cmd/goimports)是一个工具,除了格式化导入行,添加缺少的行和删除未引用的行之外, [它还可以](https://s0golang0org.icopy.site/cmd/gofmt/)使用[Gofmt](https://s0golang0org.icopy.site/cmd/gofmt/)自动格式化 Go 源代码. + + 大多数编辑器/ IDE 允许您在保存文件之前/之后运行命令,您可以将其设置为运行`goimports`以便在保存时将其应用于每个文件. + +* 将私有方法放在源文件中第一个调用方方法的下面. + +### Automatic linting[](#automatic-linting "Permalink") + +所有 Go 项目均应包括以下 GitLab CI / CD 作业: + +``` +lint: + image: registry.gitlab.com/gitlab-org/gitlab-build-images:golangci-lint-alpine + stage: test + script: + # Use default .golangci.yml file from the image if one is not present in the project root. + - '[ -e .golangci.yml ] || cp /golangci/.golangci.yml .' + # Write the code coverage report to gl-code-quality-report.json + # and print linting issues to stdout in the format: path/to/file:line description + - golangci-lint run --out-format code-climate | tee gl-code-quality-report.json | jq -r '.[] | "\(.location.path):\(.location.lines.begin) \(.description)"' + artifacts: + reports: + codequality: gl-code-quality-report.json + paths: + - gl-code-quality-report.json + allow_failure: true +``` + +在项目的根目录中包含`.golangci.yml`可以配置`golangci-lint` . 此[示例](https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml)中列出了`golangci-lint`所有选项. + +[递归包含](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/56836)可用后,您就可以共享作业模板,例如此[分析器](https://gitlab.com/gitlab-org/security-products/ci-templates/raw/master/includes-dev/analyzer.yml) . + +## Dependencies[](#dependencies "Permalink") + +依赖性应保持最小. 根据我们的[批准指南](../code_review.html#approval-guidelines) ,应在合并请求中对引入新的依赖项进行争论. 两种[许可证管理](../../user/compliance/license_compliance/index.html) 和[依赖项扫描](../../user/application_security/dependency_scanning/index.html) 应该在所有项目上激活,以确保新的依赖项安全状态和许可证兼容性. + +### Modules[](#modules "Permalink") + +从 Go 1.11 开始,名称[Go 的模块](https://github.com/golang/go/wiki/Modules)后面提供了一个标准的依赖系统. 它提供了一种方法来定义和锁定可复制构建的依赖关系. 应尽可能使用它. + +当使用 Go Modules 时,不应有`vendor/`目录. 相反,Go 会在需要构建项目时自动下载依赖项. 这与 Ruby 项目中 Bundler 处理依赖关系的方式一致,并使合并请求更易于查看. + +在某些情况下,例如构建一个 Go 项目以充当另一个项目的 CI 运行的依赖项,删除`vendor/`目录意味着必须重复下载代码,这可能由于速率限制或网络而导致间歇性问题.失败. 在这种情况下,您应该[在之间缓存下载的代码](../../ci/caching/index.html#caching-go-dependencies) . + +Go <v1.11.4 中的[模块校验和](https://github.com/golang/go/issues/29278)存在一个[错误](https://github.com/golang/go/issues/29278) ,因此请确保至少使用此版本,以避免`checksum mismatch`错误. + +### ORM[](#orm "Permalink") + +我们不在 GitLab 上使用对象关系映射库(ORM)(Ruby on Rails 中的[ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html)除外). 可以使用服务来结构化项目以避免它们. [PQ](https://github.com/lib/pq)应该足以与 PostgreSQL 数据库进行交互. + +### Migrations[](#migrations "Permalink") + +在极少数情况下,如果管理托管数据库,则必须使用 ActiveRecord 提供的迁移系统. 像[Journey](https://github.com/db-journey/journey)这样的简单库,可以在`postgres`容器中使用,可以部署为长期运行的 pod. 新版本将部署新的 Pod,并自动迁移数据. + +## Testing[](#testing "Permalink") + +### Testing frameworks[](#testing-frameworks "Permalink") + +我们不应该使用任何特定的库或框架来进行测试,因为[标准库](https://s0golang0org.icopy.site/pkg/)已经提供了入门所需的一切. 如果需要更复杂的测试工具,则在我们决定使用特定的库或框架时,以下外部依赖项可能值得考虑: + +* [Testify](https://github.com/stretchr/testify) +* [httpexpect](https://github.com/gavv/httpexpect) + +### Subtests[](#subtests "Permalink") + +尽可能使用[子测试,](https://blog.golang.org/subtests)以提高代码的可读性和测试输出. + +### Better output in tests[](#better-output-in-tests "Permalink") + +When comparing expected and actual values in tests, use [`testify/require.Equal`](https://s0godoc0org.icopy.site/github.com/stretchr/testify/require), [`testify/require.EqualError`](https://s0godoc0org.icopy.site/github.com/stretchr/testify/require), [`testify/require.EqualValues`](https://s0godoc0org.icopy.site/github.com/stretchr/testify/require), and others to improve readability when comparing structs, errors, large portions of text, or JSON documents: + +``` +type TestData struct { + // ... +} + +func FuncUnderTest() TestData { + // ... +} + +func Test(t *testing.T) { + t.Run("FuncUnderTest", func(t *testing.T) { + want := TestData{} + got := FuncUnderTest() + + require.Equal(t, want, got) // note that expected value comes first, then comes the actual one ("diff" semantics) + }) +} +``` + +### Table-Driven Tests[](#table-driven-tests "Permalink") + +当您为同一功能输入/输出有多个条目时,使用[表驱动测试](https://github.com/golang/go/wiki/TableDrivenTests)通常是一个好习惯. 以下是编写表驱动测试时可以遵循的一些准则. 这些准则主要是从 Go 标准库源代码中提取的. 请记住,在合理的时候不要遵循这些准则. + +#### Defining test cases[](#defining-test-cases "Permalink") + +每个表条目都是一个完整的测试用例,其中包含输入和预期结果,有时还包含其他信息(例如测试名称),以使测试输出易于阅读. + +* 在测试内部[定义一片匿名结构](https://github.com/golang/go/blob/50bd1c4d4eb4fac8ddeb5f063c099daccfb71b26/src/encoding/csv/reader_test.go#L16) . +* 在测试之外[定义一片匿名结构](https://github.com/golang/go/blob/55d31e16c12c38d36811bdee65ac1f7772148250/src/cmd/go/internal/module/module_test.go#L9-L66) . +* 用于代码重用的[命名结构](https://github.com/golang/go/blob/2e0cd2aef5924e48e1ceb74e3d52e76c56dd34cc/src/cmd/go/internal/modfetch/coderepo_test.go#L54-L69) . +* [Using `map[string]struct{}`](https://github.com/golang/go/blob/6d5caf38e37bf9aeba3291f1f0b0081f934b1187/src/cmd/trace/annotations_test.go#L180-L235). + +#### Contents of the test case[](#contents-of-the-test-case "Permalink") + +* 理想情况下,每个测试用例都应具有一个带有唯一标识符的字段,以用于命名子测试. 在 Go 标准库中,这通常是`name string`字段. +* 当您在测试用例中指定将用于断言的内容时,请使用`want` / `expect` / `actual` . + +#### Variable names[](#variable-names "Permalink") + +* 每个表驱动的测试映射/结构片段都可以命名为`tests` . +* 遍历`tests` ,匿名结构可以称为`tt`或`tc` . +* 测试的描述可以称为`name` / `testName` / `tn` . + +### Benchmarks[](#benchmarks "Permalink") + +处理大量 IO 或复杂操作的程序应始终包含[基准测试](https://s0golang0org.icopy.site/pkg/testing/) ,以确保随时间推移的性能一致性. + +## Error handling[](#error-handling "Permalink") + +### Adding context[](#adding-context "Permalink") + +在返回错误之前添加上下文可能会有所帮助,而不仅仅是返回错误. 这使开发人员可以了解程序进入错误状态时试图做什么,从而使调试更加容易. + +例如: + +``` +// Wrap the error +return nil, fmt.Errorf("get cache %s: %w", f.Name, err) + +// Just add context +return nil, fmt.Errorf("saving cache %s: %v", f.Name, err) +``` + +A few things to keep in mind when adding context: + +* 确定是否要向调用者公开潜在的错误. 如果是这样,请使用`%w` ,否则请使用`%v` . +* 不要使用`failed` , `error` , `didn't` . 因为这是一个错误,所以用户已经知道某件事失败了,这可能导致出现诸如`failed xx failed xx failed xx`类的字符串. 解释*什么* ,而不是失败. +* 错误字符串不应大写或以标点符号或换行符结尾. 您可以使用`golint`进行检查. + +### Naming[](#naming "Permalink") + +* 使用哨兵错误时,应始终将它们命名为`ErrXxx` . +* 创建新的错误类型时,应始终将其命名为`XxxError` . + +### Checking Error types[](#checking-error-types "Permalink") + +* 要检查错误是否相等,请不要使用`==` . 使用[`errors.Is`](https://pkg.go.dev/errors?tab=doc#Is)代替(对于围棋版本> = 1.13). +* 要检查错误是否属于某种类型,请不要使用类型断言,而应使用[`errors.As`](https://pkg.go.dev/errors?tab=doc#As) (对于 Go 版本> = 1.13). + +### References for working with errors[](#references-for-working-with-errors "Permalink") + +* [Go 1.13 errors](https://blog.golang.org/go1.13-errors). +* [Programing with errors](https://peter.bourgon.org/blog/2019/09/11/programming-with-errors.html). +* [Don’t just check errors, handle them gracefully](https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully). + +## CLIs[](#clis "Permalink") + +每个 Go 程序都是从命令行启动的. [cli](https://github.com/urfave/cli)是用于创建命令行应用程序的便捷软件包. 无论项目是守护程序还是简单的 cli 工具,都应使用它. 可以将标志直接映射到[环境变量](https://github.com/urfave/cli#values-from-the-environment) ,这些[变量](https://github.com/urfave/cli#values-from-the-environment)同时记录和集中与程序的所有可能的命令行交互. 不要使用`os.GetEnv` ,它会将变量隐藏在代码深处. + +## Daemons[](#daemons "Permalink") + +### Logging[](#logging "Permalink") + +强烈建议为守护程序使用日志记录库. 即使标准库中有一个`log`包,我们通常也使用[Logrus](https://github.com/sirupsen/logrus) . 它的插件("挂钩")系统使其成为功能强大的日志记录库,并能够直接在记录器级别添加通知程序和格式化程序. + +#### Structured (JSON) logging[](#structured-json-logging "Permalink") + +理想情况下,每个二进制文件都必须具有结构化(JSON)日志记录,因为它有助于搜索和过滤日志. 在 GitLab,我们使用 JSON 格式的结构化日志记录,因为我们所有的基础架构都假定这样做. 使用[Logrus 时](https://github.com/sirupsen/logrus) ,只需使用[JSON 格式化程序中](https://github.com/sirupsen/logrus#formatters)的构建即可打开结构化日志记录. 这遵循我们在[Ruby 应用程序中](../logging.html#use-structured-json-logging)使用的相同日志记录类型. + +#### How to use Logrus[](#how-to-use-logrus "Permalink") + +使用[Logrus](https://github.com/sirupsen/logrus)软件包时,应遵循一些准则: + +* 打印错误时,请使用[WithError](https://s0godoc0org.icopy.site/github.com/sirupsen/logrus) . 例如, `logrus.WithError(err).Error("Failed to do something")` . +* 由于我们使用[结构化日志记录](#structured-json-logging) ,因此可以在该代码路径的上下文中记录字段,例如使用[`WithField`](https://s0godoc0org.icopy.site/github.com/sirupsen/logrus)或[`WithFields`](https://s0godoc0org.icopy.site/github.com/sirupsen/logrus)的请求的 URI. 例如, `logrus.WithField("file", "/app/go").Info("Opening dir")` . 如果必须记录多个键,请始终使用`WithFields`而不是多次调用`WithField` . + +### Tracing and Correlation[](#tracing-and-correlation "Permalink") + +[LabKit](https://gitlab.com/gitlab-org/labkit)是为 Go 服务保留通用库的地方. 目前,它已销售到两个项目:Workhorse 和 Gitaly,并且导出了两个主要(但相关)功能: + +* [`gitlab.com/gitlab-org/labkit/correlation`](https://gitlab.com/gitlab-org/labkit/tree/master/correlation) :用于传播和提取服务之间的相关 ID. +* [`gitlab.com/gitlab-org/labkit/tracing`](https://gitlab.com/gitlab-org/labkit/tree/master/tracing): for instrumenting Go libraries for distributed tracing. + +这为我们提供了对底层实现的精简抽象,该抽象实现在 Workhorse,Gitaly 以及将来的其他 Go 服务器之间保持一致. 例如,对于`gitlab.com/gitlab-org/labkit/tracing`我们可以从直接使用`gitlab.com/gitlab-org/labkit/tracing`切换为使用 Zipkin 或 Gokit 自己的跟踪包装器,而无需更改应用程序代码,同时仍保持相同的一致配置机制(即`GITLAB_TRACING`环境变量). + +### Context[](#context "Permalink") + +由于守护程序是长期运行的应用程序,因此它们应具有管理取消的机制,并避免不必要的资源消耗(这可能导致 DDOS 漏洞). [Go Context](https://github.com/golang/go/wiki/CodeReviewComments#contexts)应该在可以阻塞并作为第一个参数传递的函数中使用. + +## Dockerfiles[](#dockerfiles "Permalink") + +每个项目都应在其存储库的根目录中具有一个`Dockerfile` ,以构建和运行该项目. 由于 Go 程序是静态二进制文件,因此它们不需要任何外部依赖关系,并且最终映像中的 shell 无用. 我们鼓励进行[多阶段构建](https://s0docs0docker0com.icopy.site/develop/develop-images/multistage-build/) : + +* 他们使用户可以使用正确的 Go 版本和依赖项来构建项目. +* 它们生成一个小的,自包含的图像,该图像取自`Scratch` . + +生成的 Docker 映像应在其`Entrypoint`处具有程序以创建可移植命令. 这样,任何人都可以运行该映像,并且没有参数就可以显示其帮助消息(如果已使用`cli` ). + +## Distributing Go binaries[](#distributing-go-binaries "Permalink") + +除了发布自己的二进制文件的[GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner)之外,我们的 Go 二进制文件都是由" [分发"组](https://about.gitlab.com/handbook/product/product-categories/#distribution-group)管理的项目创建的. + +[Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab)项目创建一个包含所有二进制文件的单一的操作系统软件包,而[Cloud-Native GitLab(CNG)](https://gitlab.com/gitlab-org/build/CNG)项目发布一组 Docker 映像和 Helm 图表以将它们粘合在一起. + +两种方法对所有项目都使用相同版本的 Go,因此确保我们所有使用 Go 的项目在其测试矩阵中至少具有一个相同的 Go 版本非常重要. 您可以检查[Omnibus](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/blob/master/docker/Dockerfile_debian_10#L59)当前正在使用的 Go 版本以及[CNG](https://gitlab.com/gitlab-org/build/cng/blob/master/ci_files/variables.yml#L12)正在使用的版本. + +### Updating Go version[](#updating-go-version "Permalink") + +我们应该始终使用[受支持](https://s0golang0org.icopy.site/doc/devel/release.html)的 Go [版本](https://s0golang0org.icopy.site/doc/devel/release.html) ,即三个最新的次要版本之一,并且应该始终使用该版本的最新补丁程序级别,因为它可能包含安全修复程序. + +更改版本会影响正在编译的每个项目,因此在更改程序包构建器以使用它之前,请确保已更新所有项目以针对新的 Go 版本进行测试非常重要. 尽管[Go 保证了兼容性](https://s0golang0org.icopy.site/doc/go1compat) ,但次要版本之间的更改可能会暴露错误或在我们的项目中引起问题. + +选择要使用的新 Go 版本之后,更新 Omnibus 和 CNG 的步骤如下: + +* [创建于 CNG 项目的合并请求](https://gitlab.com/gitlab-org/build/CNG/edit/master/ci_files/variables.yml?branch_name=update-go-version) ,更新`GO_VERSION`在`ci_files/variables.yml` . +* 在[`gitlab-omnibus-builder`项目中](https://gitlab.com/gitlab-org/gitlab-omnibus-builder)创建合并请求,更新`GO_VERSION` `docker/`目录中的每个文件,以便`GO_VERSION`设置`GO_VERSION` . [这是一个例子](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/125/diffs) . +* 标记包含更改的`gitlab-omnibus-builder`的新版本. +* [在`omnibus-gitlab`项目中创建合并请求](https://gitlab.com/gitlab-org/omnibus-gitlab/edit/master/.gitlab-ci.yml?branch_name=update-gitlab-omnibus-builder-version) ,更新`BUILDER_IMAGE_REVISION`以匹配新创建的标记. + +为了减少两种分发方法之间不必要的差异,Omnibus 和 CNG **应该始终使用相同的 Go 版本** . + +### Supporting multiple Go versions[](#supporting-multiple-go-versions "Permalink") + +出于以下原因,各个 Golang 项目需要支持多个 Go 版本: + +1. 当新的 Go 版本发布时,我们应该开始将其集成到 CI 管道中,以验证与新编译器的兼容性. +2. 我们必须支持[Omnibus 官方的 Go 版本](#updating-go-version) ,该[版本](#updating-go-version)可能在最新的次要版本之后. +3. 当 Omnibus 切换为 Go 版本时,我们仍可能需要支持旧版本进行安全反向移植. + +保持对 Go 的 3 个最新次要版本的支持,可以轻松满足这 3 个要求. + +可以放弃对最旧的 Go 版本的支持,并且仅支持 2 个最新版本,如果这足以支持向后 3 个 GitLab 次要版本的反向移植. + +Example: + +如果我们要丢弃的支持`go 1.11`在 GitLab `12.10` ,我们需要验证我们使用哪去版本`12.9` , `12.8`和`12.7` . + +我们将不考虑活动的里程碑`12.10` ,因为在关键安全发布的情况下将需要`12.7`的反向端口. + +1. 如果从 GitLab `12.7`开始[Omnibus 和 CNG](#updating-go-version)都在使用 Go `1.12` ,那么我们可以放心地放弃对`1.11`支持. +2. 如果 Omnibus 或 CNG 在 GitLab `12.7`中使用`1.11` ,那么我们仍然需要保持对 Go `1.11`支持,以便更轻松地向后移植安全修复程序. + +## Secure Team standards and style guidelines[](#secure-team-standards-and-style-guidelines "Permalink") + +以下是一些特定于安全团队的样式准则. + +### Code style and format[](#code-style-and-format-1 "Permalink") + +在提交之前,请使用`goimports -local gitlab.com/gitlab-org` . [goimports](https://s0godoc0org.icopy.site/golang.org/x/tools/cmd/goimports)是一个工具,除了格式化导入行,添加缺少的行和删除未引用的行之外, [它还可以](https://s0golang0org.icopy.site/cmd/gofmt/)使用[Gofmt](https://s0golang0org.icopy.site/cmd/gofmt/)自动格式化 Go 源代码. 通过使用`-local gitlab.com/gitlab-org`选项, `goimports`会将本地引用的软件包与外部软件包分开分组. 有关更多详细信息,请参见 Go Wiki 上"代码审查注释"页面[的导入部分](https://github.com/golang/go/wiki/CodeReviewComments#imports) . 大多数编辑器/ IDE 允许您在保存文件之前/之后运行命令,您可以将其设置为运行`goimports -local gitlab.com/gitlab-org`以便在保存时将其应用于每个文件. + +* * * + +[Return to Development documentation](../README.html). \ No newline at end of file diff --git a/docs/612.md b/docs/612.md new file mode 100644 index 0000000000000000000000000000000000000000..038c94410e90284cf62cc4b2ce4398ba33055247 --- /dev/null +++ b/docs/612.md @@ -0,0 +1,937 @@ +# GraphQL API style guide + +> 原文:[https://docs.gitlab.com/ee/development/api_graphql_styleguide.html](https://docs.gitlab.com/ee/development/api_graphql_styleguide.html) + +* [How GitLab implements GraphQL](#how-gitlab-implements-graphql) +* [Deep Dive](#deep-dive) +* [GraphiQL](#graphiql) +* [Authentication](#authentication) +* [Types](#types) + * [Nullable fields](#nullable-fields) + * [Exposing Global IDs](#exposing-global-ids) + * [Connection Types](#connection-types) + * [Shortcut fields](#shortcut-fields) + * [Exposing permissions for a type](#exposing-permissions-for-a-type) +* [Feature flags](#feature-flags) + * [`feature_flag` property](#feature_flag-property) + * [Toggle the value of a field](#toggle-the-value-of-a-field) +* [Deprecating fields](#deprecating-fields) + * [Deprecation reason style guide](#deprecation-reason-style-guide) +* [Enums](#enums) +* [Descriptions](#descriptions) + * [Description style guide](#description-style-guide) + * [`copy_field_description` helper](#copy_field_description-helper) +* [Authorization](#authorization) + * [Type authorization](#type-authorization) + * [Field authorization](#field-authorization) + * [Type and Field authorizations together](#type-and-field-authorizations-together) +* [Resolvers](#resolvers) + * [Correct use of `Resolver#ready?`](#correct-use-of-resolverready) + * [Look-Ahead](#look-ahead) +* [Mutations](#mutations) + * [Building Mutations](#building-mutations) + * [Naming conventions](#naming-conventions) + * [Arguments](#arguments) + * [Fields](#fields) + * [The `resolve` method](#the-resolve-method) + * [Mounting the mutation](#mounting-the-mutation) + * [Authorizing resources](#authorizing-resources) + * [Errors in mutations](#errors-in-mutations) + * [Success](#success) + * [Failure (relevant to the user)](#failure-relevant-to-the-user) + * [Failure (irrelevant to the user)](#failure-irrelevant-to-the-user) + * [Categorizing errors](#categorizing-errors) + * [Aliasing and deprecating mutations](#aliasing-and-deprecating-mutations) +* [Validating arguments](#validating-arguments) +* [GitLab’s custom scalars](#gitlabs-custom-scalars) + * [`Types::TimeType`](#typestimetype) +* [Testing](#testing) +* [Notes about Query flow and GraphQL infrastructure](#notes-about-query-flow-and-graphql-infrastructure) + * [Query limits](#query-limits) +* [Documentation and Schema](#documentation-and-schema) + +# GraphQL API style guide[](#graphql-api-style-guide "Permalink") + +本文档概述了 GitLab 的[GraphQL API](../api/graphql/index.html)的样式指南. + +## How GitLab implements GraphQL[](#how-gitlab-implements-graphql "Permalink") + +我们使用[Robert Mosolgo](https://github.com/rmosolgo/)编写的[GraphQL Ruby 宝石](https://graphql-ruby.org/) . + +所有 GraphQL 查询都定向到单个端点( [`app/controllers/graphql_controller.rb#execute`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/controllers/graphql_controller.rb) ),该端点在`/api/graphql`处作为 API 端点`/api/graphql` . + +## Deep Dive[](#deep-dive "Permalink") + +在 2019 年 3 月,尼克·托马斯(Nick Thomas)在 GitLab 的[GraphQL API 上](../api/graphql/index.html)进行了一次深潜(仅限 GitLab 团队成员: `https://gitlab.com/gitlab-org/create-stage/issues/1` : [//gitlab.com/gitlab-org/create-stage/issues/1](../api/graphql/index.html) ),以与可能将来会在代码库的这一部分中工作. 您可以[在 YouTube 上](https://www.youtube.com/watch?v=-9L_1MWrjkg)找到[录音](https://www.youtube.com/watch?v=-9L_1MWrjkg) ,在[Google 幻灯片](https://docs.google.com/presentation/d/1qOTxpkTdHIp1CRjuTvO-aXg0_rUtzE3ETfLUdnBB5uQ/edit)和[PDF 中](https://gitlab.com/gitlab-org/create-stage/uploads/8e78ea7f326b2ef649e7d7d569c26d56/GraphQL_Deep_Dive__Create_.pdf)找到[幻灯片](https://docs.google.com/presentation/d/1qOTxpkTdHIp1CRjuTvO-aXg0_rUtzE3ETfLUdnBB5uQ/edit) . 自 GitLab 11.9 起,本次深入学习中涉及的所有内容都是准确的,尽管自那时以来特定细节可能有所更改,但它仍应作为一个很好的介绍. + +## GraphiQL[](#graphiql "Permalink") + +GraphiQL 是一个交互式 GraphQL API 资源管理器,您可以在其中使用现有查询. 您可以在`https://<your-gitlab-site.com>/-/graphql-explorer`任何 GitLab 环境中访问它. 例如,用于[GitLab.com 的那个](https://gitlab.com/-/graphql-explorer) . + +## Authentication[](#authentication "Permalink") + +认证通过`GraphqlController` ,现在,它使用与 Rails 应用程序相同的认证. 因此可以共享会话. + +也可以将`private_token`添加到查询字符串,或添加`HTTP_PRIVATE_TOKEN`标头. + +## Types[](#types "Permalink") + +我们使用代码优先模式,并声明 Ruby 中所有内容的类型. + +例如, `app/graphql/types/issue_type.rb` : + +``` +graphql_name 'Issue' + +field :iid, GraphQL::ID_TYPE, null: true +field :title, GraphQL::STRING_TYPE, null: true + +# we also have a method here that we've defined, that extends `field` +markdown_field :title_html, null: true +field :description, GraphQL::STRING_TYPE, null: true +markdown_field :description_html, null: true +``` + +We give each type a name (in this case `Issue`). + +`iid` , `title`和`description`是*标量* GraphQL 类型. `iid`是`GraphQL::ID_TYPE` ,这是一种特殊的字符串类型,表示唯一的 ID. `title`和`description`是常规的`GraphQL::STRING_TYPE`类型. + +When exposing a model through the GraphQL API, we do so by creating a new type in `app/graphql/types`. You can also declare custom GraphQL data types for scalar data types (e.g. `TimeType`). + +公开类型中的属性时,请确保将定义内的逻辑保持尽可能小. 相反,请考虑将任何逻辑转移到演示者中: + +``` +class Types::MergeRequestType < BaseObject + present_using MergeRequestPresenter + + name 'MergeRequest' +end +``` + +可以使用现有的演示者,但是也可以专门为 GraphQL 创建一个新的演示者. + +使用由字段解析的对象和上下文初始化演示者. + +### Nullable fields[](#nullable-fields "Permalink") + +GraphQL 允许字段为"可为空"或"不可为空". 前者意味着可以返回`null`而不是指定类型的值. **通常** ,出于以下原因,您应该首选使用可空字段而不是不可空字段: + +* 数据从必需切换到不需要,然后再次返回是很常见的 +* 即使没有可能成为可选字段的前景,在查询时它也可能不可**用** + * 例如,可能需要从 Gitaly 查找 blob 的`content` + * 如果`content`可为空,我们可以返回**部分**响应,而不是使整个查询失败 +* 对于无版本模式,很难从不可为空的字段更改为可为空的字段 + +非空字段仅应在需要字段时使用,将来不太可能成为可选字段,并且非常容易计算. 一个示例是`id`字段. + +进一步阅读: + +* [GraphQL Best Practices Guide](https://s0graphql0org.icopy.site/learn/best-practices/) +* [Using nullability in GraphQL](https://www.apollographql.com/blog/using-nullability-in-graphql-2254f84c4ed7) + +### Exposing Global IDs[](#exposing-global-ids "Permalink") + +在类型上公开`ID`字段时,默认情况下,我们将通过在要渲染的资源上调用`to_global_id`来公开全局 ID. + +要覆盖此行为,可以在要公开其 ID 的类型上实现`id`方法. 请确保在使用自定义方法公开`GraphQL::ID_TYPE` ,它是全局唯一的. + +被曝光的记录`full_path`作为`ID_TYPE`是这些例外之一. 由于完整路径是`Project`或`Namespace`的唯一标识符. + +### Connection Types[](#connection-types "Permalink") + +GraphQL 使用[基于光标的分页](https://s0graphql0org.icopy.site/learn/pagination/)来公开项目的集合. 这为客户提供了很大的灵活性,同时还允许后端使用不同的分页模型. + +为了公开资源的集合,我们可以使用连接类型. 这将使用默认的分页字段包装数组. 例如,对项目管道的查询可能如下所示: + +``` +query($project_path: ID!) { project(fullPath: $project_path) { pipelines(first: 2) { pageInfo { hasNextPage hasPreviousPage } edges { cursor node { id status } } } } } +``` + +这将返回项目的前两个管道和相关的分页信息,按降序 ID 排序. 返回的数据如下所示: + +``` +{ "data": { "project": { "pipelines": { "pageInfo": { "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "cursor": "Nzc=", "node": { "id": "gid://gitlab/Pipeline/77", "status": "FAILED" } }, { "cursor": "Njc=", "node": { "id": "gid://gitlab/Pipeline/67", "status": "FAILED" } } ] } } } } +``` + +要获取下一页,可以传递最后一个已知元素的光标: + +``` +query($project_path: ID!) { project(fullPath: $project_path) { pipelines(first: 2, after: "Njc=") { pageInfo { hasNextPage hasPreviousPage } edges { cursor node { id status } } } } } +``` + +为了确保获得一致的顺序,我们将在主键上按降序附加顺序. 这通常是`id` ,因此基本上我们将在关系的末尾添加`order(id: :desc)` . 基础表上*必须*有主键. + +#### Shortcut fields[](#shortcut-fields "Permalink") + +有时似乎很容易实现"快捷字段",如果没有传递任何参数,则让解析程序返回集合的第一个. 不鼓励使用这些"快捷字段",因为它们会增加维护开销. 它们需要与规范字段保持同步,并且如果规范字段发生更改,则不建议使用或修改它们. 除非有充分的理由,否则请使用框架提供的功能. + +例如,不要使用`latest_pipeline` ,而应使用`pipelines(last: 1)` . + +### Exposing permissions for a type[](#exposing-permissions-for-a-type "Permalink") + +若要公开当前用户对资源的权限,可以调用以单独的类型传递的`expose_permissions` ,该类型表示资源的权限. + +例如: + +``` +module Types + class MergeRequestType < BaseObject + expose_permissions Types::MergeRequestPermissionsType + end +end +``` + +权限类型继承自`BasePermissionType` ,其中包括一些帮助程序方法,这些方法允许将权限公开为不可为 null 的布尔值: + +``` +class MergeRequestPermissionsType < BasePermissionType + present_using MergeRequestPresenter + + graphql_name 'MergeRequestPermissions' + + abilities :admin_merge_request, :update_merge_request, :create_note + + ability_field :resolve_note, + description: 'Indicates the user can resolve discussions on the merge request' + permission_field :push_to_source_branch, method: :can_push_to_source_branch? +end +``` + +* **`permission_field`** :其作用与`graphql-ruby`的`field`方法相同,但设置默认描述和类型,并使它们不可为空. 通过将它们添加为参数,仍然可以覆盖这些选项. +* **`ability_field`** :公开我们政策中定义的能力. 此行为与`permission_field`相同,并且可以覆盖相同的参数. +* **`abilities`** :允许一次暴露我们政策中定义的几种能力. 这些字段都将是带有默认说明的非空布尔值. + +## Feature flags[](#feature-flags "Permalink") + +开发人员可以通过以下方式将[功能标志](../development/feature_flags/index.html)添加到 GraphQL 字段: + +* 将`feature_flag`属性添加到字段. 当禁用该标志时,这将允许从 GraphQL 模式中*隐藏*该字段. +* 解析字段时切换返回值. + +您可以参考以下准则来决定使用哪种方法: + +* 如果您的字段是实验性的,并且其名称或类型可能会发生变化,请使用`feature_flag`属性. +* 如果您的字段是稳定的,并且即使删除了标志,其定义也不会更改,请改为切换字段的返回值. 请注意, [所有字段](#nullable-fields)无论如何[都应该为空](#nullable-fields) . + +### `feature_flag` property[](#feature_flag-property "Permalink") + +`feature_flag`属性允许您在 GraphQL 模式中切换字段的[可见性](https://graphql-ruby.org/authorization/visibility.html) . 禁用该标志后,将从架构中删除该字段. + +字段后[附有](https://gitlab.com/gitlab-org/gitlab/-/blob/497b556/app/graphql/types/base_field.rb#L44-53)说明,表示该说明位于功能标志的后面. + +**警告:**如果在禁用功能标志时客户端查询该字段,则查询将失败. 在生产中打开或关闭功能的可见性时,请考虑此问题. + +`feature_flag`属性不允许使用[基于 actor](../development/feature_flags/development.html)的[特征门](../development/feature_flags/development.html) . 这意味着功能标记不能仅针对特定的项目,组或用户进行切换,而只能针对所有人进行全局切换. + +Example: + +``` +field :test_field, type: GraphQL::STRING_TYPE, + null: true, + description: 'Some test field', + feature_flag: :my_feature_flag +``` + +### Toggle the value of a field[](#toggle-the-value-of-a-field "Permalink") + +对字段使用特征标记的这种方法是切换字段的返回值. 这可以在解析器中,在类型中甚至在模型方法中完成,具体取决于您的偏好和情况. + +当应用功能标记来切换字段的值时,该字段的`description`必须: + +* 说明该字段的值可以通过功能标记切换. +* 命名功能标志. +* 说明禁用(或启用,如果更合适的话)功能标志时字段将返回的内容. + +Example: + +``` +field :foo, GraphQL::STRING_TYPE, + null: true, + description: 'Some test field. Will always return `null`' \ + 'if `my_feature_flag` feature flag is disabled' + +def foo + object.foo unless Feature.enabled?(:my_feature_flag, object) +end +``` + +## Deprecating fields[](#deprecating-fields "Permalink") + +GitLab 的 GraphQL API 是无版本的,这意味着我们会与 API 的旧版本保持向下兼容性. 除了删除字段,我们还需要*弃用*该字段. 将来,GitLab [可能会删除不推荐使用的字段](https://gitlab.com/gitlab-org/gitlab/-/issues/32292) . + +使用`deprecated`推荐使用的属性不推荐使用字段. 该属性的值是以下各项的`Hash`值: + +* `reason` -弃用的原因. +* `milestone` -已弃用该字段的里程碑. + +Example: + +``` +field :token, GraphQL::STRING_TYPE, null: true, + deprecated: { reason: 'Login via token has been removed', milestone: '10.0' }, + description: 'Token for login' +``` + +最初的`description:`现场应保持,并且*不*应该更新提折旧. + +### Deprecation reason style guide[](#deprecation-reason-style-guide "Permalink") + +如果弃用的原因是该字段被另一个字段替换,则`reason`必须是: + +``` +Use `otherFieldName` +``` + +Example: + +``` +field :designs, ::Types::DesignManagement::DesignCollectionType, null: true, + deprecated: { reason: 'Use `designCollection`', milestone: '10.0' }, + description: 'The designs associated with this issue', +``` + +如果该字段没有被另一个字段替换,则应给出描述性的弃用`reason` . + +## Enums[](#enums "Permalink") + +GitLab GraphQL enums are defined in `app/graphql/types`. When defining new enums, the following rules apply: + +* 值必须为大写. +* 类名必须以字符串`Enum`结尾. +* `graphql_name`不得包含字符串`Enum` . + +例如: + +``` +module Types + class TrafficLightStateEnum < BaseEnum + graphql_name 'TrafficLightState' + description 'State of a traffic light' + + value 'RED', description: 'Drivers must stop' + value 'YELLOW', description: 'Drivers must stop when it is safe to' + value 'GREEN', description: 'Drivers can start or keep driving' + end +end +``` + +If the enum will be used for a class property in Ruby that is not an uppercase string, you can provide a `value:` option that will adapt the uppercase value. + +在以下示例中: + +* GraphQL inputs of `OPENED` will be converted to `'opened'`. +* Ruby 的`'opened'`值将在 GraphQL 响应中转换为`"OPENED"` . + +``` +module Types + class EpicStateEnum < BaseEnum + graphql_name 'EpicState' + description 'State of a GitLab epic' + + value 'OPENED', value: 'opened', description: 'An open Epic' + value 'CLOSED', value: 'closed', description: 'An closed Epic' + end +end +``` + +## Descriptions[](#descriptions "Permalink") + +所有字段和参数都[必须具有描述](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16438) . + +使用`description:`关键字给出字段或自变量的`description:` . 例如: + +``` +field :id, GraphQL::ID_TYPE, description: 'ID of the resource' +``` + +用户可以通过以下方式查看字段和参数的描述: + +* The [GraphiQL explorer](#graphiql). +* The [static GraphQL API reference](../api/graphql/#reference). + +### Description style guide[](#description-style-guide "Permalink") + +为确保一致性,每次添加或更新描述时都应遵循以下规定: + +* 在描述中提及资源的名称. 示例: `'Labels of the issue'` (问题就是资源). +* 尽可能`"{x} of the {y}"` . 示例: `'Title of the issue'` . 不要下手描述`The` . +* `GraphQL::BOOLEAN_TYPE`字段的描述应回答以下问题:"此字段的作用是什么?". 示例: `'Indicates project has a Git repository'` . +* 描述类型为`Types::TimeType`的参数或字段时,请始终包含单词`"timestamp"` . 这使读者知道该属性的格式将是`Time` ,而不仅仅是`Date` . +* 没有`.` 在字符串末尾. + +Example: + +``` +field :id, GraphQL::ID_TYPE, description: 'ID of the Issue' +field :confidential, GraphQL::BOOLEAN_TYPE, description: 'Indicates the issue is confidential' +field :closed_at, Types::TimeType, description: 'Timestamp of when the issue was closed' +``` + +### `copy_field_description` helper[](#copy_field_description-helper "Permalink") + +有时我们希望确保两个描述始终相同. 例如,当两个类型字段描述都表示相同的属性时,它们要与突变参数保持相同. + +除了提供描述之外,我们还可以使用`copy_field_description`帮助器,将其类型和字段名称传递给它,以复制其描述. + +Example: + +``` +argument :title, GraphQL::STRING_TYPE, + required: false, + description: copy_field_description(Types::MergeRequestType, :title) +``` + +## Authorization[](#authorization "Permalink") + +可以使用与 Rails 应用程序中相同的功能将授权应用于类型和字段. + +如果: + +* 当前经过身份验证的用户未通过授权,授权资源将返回`null` . +* 资源是集合的一部分,该集合将被过滤以排除用户授权检查失败的对象. + +另请参见[在变异中授权资源](#authorizing-resources) . + +**提示:**尝试仅先加载允许当前已认证用户使用我们现有的查找器查看的内容,而不依赖于授权来过滤记录. 这样可以最大程度地减少数据库查询和对已加载记录的不必要的授权检查. + +### Type authorization[](#type-authorization "Permalink") + +通过将能力传递给`authorize`方法来`authorize`类型. 通过检查当前经过身份验证的用户是否具有所需的能力,将对所有具有相同类型的字段进行授权. + +例如,以下授权可确保当前经过身份验证的用户只能看到其具有`read_project`能力的项目(只要在使用`Types::ProjectType`的字段中返回该`Types::ProjectType` ): + +``` +module Types + class ProjectType < BaseObject + authorize :read_project + end +end +``` + +您还可以授权多个能力,在这种情况下,所有能力检查都必须通过. + +例如,以下授权可确保当前经过身份验证的用户必须具有`read_project`和`another_ability`能力才能查看项目: + +``` +module Types + class ProjectType < BaseObject + authorize [:read_project, :another_ability] + end +end +``` + +### Field authorization[](#field-authorization "Permalink") + +可以使用`authorize`选项对字段进行授权. + +例如,以下授权可确保当前经过身份验证的用户必须具有`owner_access`功能才能查看项目: + +``` +module Types + class MyType < BaseObject + field :project, Types::ProjectType, null: true, resolver: Resolvers::ProjectResolver, authorize: :owner_access + end +end +``` + +还可以针对多个能力授权字段,在这种情况下,所有能力检查都必须通过. **注意:**这需要显式地将一个块传递给`field` : + +``` +module Types + class MyType < BaseObject + field :project, Types::ProjectType, null: true, resolver: Resolvers::ProjectResolver do + authorize [:owner_access, :another_ability] + end + end +end +``` + +**注意:**如果字段的类型已经[具有特定的授权,](#type-authorization)则无需将该相同的授权添加到字段中. + +### Type and Field authorizations together[](#type-and-field-authorizations-together "Permalink") + +授权是累积性的,因此,在一个字段以及该字段的类型上定义了授权的情况下,当前经过身份验证的用户将需要通过所有能力检查. + +在下面的简化示例中,当前经过身份验证的用户将需要`first_permission`和`second_permission`能力,才能看到问题的作者. + +``` +class UserType + authorize :first_permission +end +``` + +``` +class IssueType + field :author, UserType, authorize: :second_permission +end +``` + +## Resolvers[](#resolvers "Permalink") + +我们使用存储在`app/graphql/resolvers`目录中的*解析器*定义应用程序如何响应. 解析器提供了用于检索相关对象的实际实现逻辑. + +要查找要显示在字段中的对象,我们可以将解析器添加到`app/graphql/resolvers` . + +可以在解析程序中定义参数,这些参数将通过解析程序提供给字段. 公开具有内部 ID( `iid` )的模型时,最好将其与名称空间路径结合使用,作为解析器中的参数,而不是数据库 ID. 否则,请使用[全局唯一 ID](#exposing-global-ids) . + +我们已经有一个`FullPathLoader` ,可以将其包含在其他解析器中,以快速查找将有很多依赖对象的项目和命名空间. + +为了限制执行的查询数量,我们可以使用`BatchLoader` . + +### Correct use of `Resolver#ready?`[](#correct-use-of-resolverready "Permalink") + +解析器有两个公共 API 方法作为框架的一部分: `#ready?(**args)`和`#resolve(**args)` . 我们可以使用`#ready?` 无需调用`#resolve`即可执行设置,验证或提前退货. + +有充分理由使用`#ready?` 包括: + +* 验证互斥参数(请参阅[验证参数](#validating-arguments) ) +* 如果事先知道没有结果,则返回`Relation.none` +* 执行诸如初始化实例变量的设置(尽管为此考虑了延迟初始化的方法) + +[`Resolver#ready?(**args)`](https://graphql-ruby.org/api-doc/1.10.9/GraphQL/Schema/Resolver#ready?-instance_method)应返回`(Boolean, early_return_data)` ,如下所示: + +``` +def ready?(**args) + [false, 'have this instead'] +end +``` + +因此,无论何时调用解析器(主要是在测试中-作为框架抽象,不应将解析器视为可重用的,最好使用查找器),还记得调用`ready?` 方法,并在调用`resolve`之前检查布尔值标志! 在我们的[`GraphQLHelpers`](https://gitlab.com/gitlab-org/gitlab/-/blob/2d395f32d2efbb713f7bc861f96147a2a67e92f2/spec/support/helpers/graphql_helpers.rb#L20-27)可以看到一个示例. + +### Look-Ahead[](#look-ahead "Permalink") + +完整查询是在执行期间预先知道的,这意味着我们可以利用[超前](https://graphql-ruby.org/queries/lookahead.html)查询来优化查询,并知道我们将需要的批处理负载关联. 考虑在解析器中添加前瞻性支持,以避免`N+1`性能问题. + +为了支持常见的前瞻用例(在请求子字段时预加载关联),可以包含[`LooksAhead`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/resolvers/concerns/looks_ahead.rb) . 例如: + +``` +# Assuming a model `MyThing` with attributes `[child_attribute, other_attribute, nested]`, +# where nested has an attribute named `included_attribute`. +class MyThingResolver < BaseResolver + include LooksAhead + + # Rather than defining `resolve(**args)`, we implement: `resolve_with_lookahead(**args)` + def resolve_with_lookahead(**args) + apply_lookahead(MyThingFinder.new(current_user).execute) + end + + # We list things that should always be preloaded: + # For example, if child_attribute is always needed (during authorization + # perhaps), then we can include it here. + def unconditional_includes + [:child_attribute] + end + + # We list things that should be included if a certain field is selected: + def preloads + { + field_one: [:other_attribute], + field_two: [{ nested: [:included_attribute] }] + } + end +end +``` + +需要做的最后一件事是,使用此解析器的每个字段都需要公告提前查询的需求: + +``` + # in ParentType + field :my_things, MyThingType.connection_type, null: true, + extras: [:lookahead], # Necessary + resolver: MyThingResolver, + description: 'My things' +``` + +有关实际使用的示例,请参见[`ResolvesMergeRequests`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/resolvers/concerns/resolves_merge_requests.rb) . + +## Mutations[](#mutations "Permalink") + +变异用于更改任何存储的值或触发动作. 与 GET 请求不应修改数据的方式相同,我们无法在常规 GraphQL 查询中修改数据. 但是我们可以突变. + +要查找突变的对象,需要指定参数. 与[解析程序一样](#resolvers) ,最好使用内部 ID 或全局 ID(而不是数据库 ID)(如果需要). + +### Building Mutations[](#building-mutations "Permalink") + +突变存在于`app/graphql/mutations`理想情况下,突变是根据它们正在突变的资源进行分组的,类似于我们的服务. 他们应该继承`Mutations::BaseMutation` . 突变的结果将返回在突变上定义的字段. + +### Naming conventions[](#naming-conventions "Permalink") + +每个突变都必须定义一个`graphql_name` ,这是 GraphQL 模式中的突变名称. + +Example: + +``` +class UserUpdateMutation < BaseMutation + graphql_name 'UserUpdate' +end +``` + +我们的 GraphQL 突变名称在历史上是不一致的,但是新的突变名称应遵循约定`'{Resource}{Action}'`或`'{Resource}{Action}{Attribute}'` . + +**创建**新资源的变异应使用动词`Create` . + +Example: + +* `CommitCreate` + +**更新**数据的突变应使用: + +* 动词`Update` . +* 特定于域的动词,例如`Set` , `Add`或`Toggle`如果更合适). + +Examples: + +* `EpicTreeReorder` +* `IssueSetWeight` +* `IssueUpdate` +* `TodoMarkDone` + +**删除**数据的突变应使用: + +* 动词`Delete`而不是`Destroy` . +* 特定于域的动词,例如" `Remove`如果更合适). + +Examples: + +* `AwardEmojiRemove` +* `NoteDelete` + +如果您需要有关突变命名的建议,请查看 Slack `#graphql`渠道以获取反馈. + +### Arguments[](#arguments "Permalink") + +突变所需的参数可以定义为字段所需的参数. 这些将被包装为突变的输入类型. 例如,带有 GraphQL 名称`MergeRequestSetWip`的`Mutations::MergeRequests::SetWip` `MergeRequestSetWip`定义了以下参数: + +``` +argument :project_path, GraphQL::ID_TYPE, + required: true, + description: "The project the merge request to mutate is in" + +argument :iid, GraphQL::STRING_TYPE, + required: true, + description: "The iid of the merge request to mutate" + +argument :wip, + GraphQL::BOOLEAN_TYPE, + required: false, + description: <<~DESC Whether or not to set the merge request as a WIP. + If not passed, the value will be toggled. DESC +``` + +这将自动生成一个名为`MergeRequestSetWipInput`的输入类型, `MergeRequestSetWipInput`包含我们指定的 3 个参数和`clientMutationId` . + +然后将这些参数作为关键字参数传递给突变的`resolve`方法. + +### Fields[](#fields "Permalink") + +在最常见的情况下,变异会返回 2 个字段: + +* 正在修改的资源 +* 错误列表,说明无法执行该操作的原因. 如果突变成功,此列表将为空. + +通过从`Mutations::BaseMutation`继承任何新的突变, `errors`字段将自动添加. 还添加了一个`clientMutationId`字段,当在单个请求中执行多个变异时,客户端可以使用它来标识单个变异的结果. + +### The `resolve` method[](#the-resolve-method "Permalink") + +`resolve`方法接收变异的参数作为关键字参数. 从这里,我们可以调用将修改资源的服务. + +然后, `resolve`方法应返回一个哈希,该哈希具有与在突变上定义的字段名称相同的字段名称,包括`errors`数组. 例如, `Mutations::MergeRequests::SetWip`定义了`merge_request`字段: + +``` +field :merge_request, + Types::MergeRequestType, + null: true, + description: "The merge request after mutation" +``` + +这意味着在此突变中从`resolve`返回的哈希应如下所示: + +``` +{ + # The merge request modified, this will be wrapped in the type + # defined on the field + merge_request: merge_request, + # An array of strings if the mutation failed after authorization. + # The `errors_on_object` helper collects `errors.full_messages` + errors: errors_on_object(merge_request) +} +``` + +### Mounting the mutation[](#mounting-the-mutation "Permalink") + +为了使变异可用,必须在存在于`graphql/types/mutation_types`的变异类型上进行定义. `mount_mutation`帮助器方法将基于突变的 GraphQL 名称定义一个字段: + +``` +module Types + class MutationType < BaseObject + include Gitlab::Graphql::MountMutation + + graphql_name "Mutation" + + mount_mutation Mutations::MergeRequests::SetWip + end +end +``` + +将生成一个名为`mergeRequestSetWip`的字段, `Mutations::MergeRequests::SetWip`字段将要解决的`Mutations::MergeRequests::SetWip` . + +### Authorizing resources[](#authorizing-resources "Permalink") + +要授权某个变异内的资源,我们首先要提供所需的变异能力,如下所示: + +``` +module Mutations + module MergeRequests + class SetWip < Base + graphql_name 'MergeRequestSetWip' + + authorize :update_merge_request + end + end +end +``` + +然后,我们可以致电`authorize!` 在`resolve`方法中,传入我们要验证其功能的资源. + +或者,我们可以添加一个`find_object`方法,该方法将在突变上加载对象. 这将允许您使用`authorized_find!` 辅助方法. + +当不允许用户执行该操作或找不到对象时,我们应该引发`Gitlab::Graphql::Errors::ResourceNotAvailable`错误. 哪些将正确呈现给客户端. + +### Errors in mutations[](#errors-in-mutations "Permalink") + +我们鼓励遵循[错误](https://graphql-ruby.org/mutations/mutation_errors)的做法,将其[作为](https://graphql-ruby.org/mutations/mutation_errors)突变的[数据](https://graphql-ruby.org/mutations/mutation_errors) ,从而根据错误的相关者,定义的错误处理者来区分错误. + +关键点: + +* 所有突变响应都有一个`errors`字段. 如果失败,则应填充此文件;如果成功,则应填充该文件. +* 考虑谁需要看到错误: **用户**还是**开发人员** . +* 客户在执行突变时应始终请求`errors`字段. +* 错误可能会以`$root.errors` (顶级错误)或`$root.data.mutationName.errors` (变异错误)的形式报告给用户. 位置取决于这是什么类型的错误以及它所包含的信息. + +考虑一个示例变体`doTheThing` ,该变`doTheThing`返回带有两个字段的响应: `errors: [String]`和`thing: ThingType` . 由于我们正在考虑错误,因此`thing`本身的特定性质与这些示例无关. + +突变响应可以处于三种状态: + +* [Success](#success) +* [Failure (relevant to the user)](#failure-relevant-to-the-user) +* [Failure (irrelevant to the user)](#failure-irrelevant-to-the-user) + +#### Success[](#success "Permalink") + +在快乐的道路上, *可能*会返回错误以及预期的有效负载,但是如果一切成功,则`errors`应该是一个空数组,因为没有任何问题需要通知用户. + +``` +{ + data: { + doTheThing: { + errors: [] // if successful, this array will generally be empty. + thing: { .. } + } + } +} +``` + +#### Failure (relevant to the user)[](#failure-relevant-to-the-user "Permalink") + +发生了影响**用户**的错误. 我们将这些称为*突变错误* . 在这种情况下通常没有`thing`来回报: + +``` +{ + data: { + doTheThing: { + errors: ["you cannot touch the thing"], + thing: null + } + } +} +``` + +例如: + +* Model validation errors: the user may need to change the inputs. +* 权限错误:用户需要知道他们不能执行此操作,他们可能需要请求权限或登录. +* 应用程序状态问题阻止了用户的操作,例如:合并冲突,资源被锁定等等. + +理想情况下,我们应该防止用户走得太远,但是如果这样做了,则需要告诉他们出了什么问题,以便他们了解失败的原因以及可以实现其意图的方法,即使那很简单重试请求. + +可以与变异数据一起返回*可恢复的*错误. 例如,如果用户上载 10 个文件,而其中 3 个失败,其余文件成功,则可以将失败的错误以及有关成功的信息与用户一起使用. + +#### Failure (irrelevant to the user)[](#failure-irrelevant-to-the-user "Permalink") + +可以在*顶层*返回一个或多个*不可恢复的*错误. 这些是**用户**几乎无法控制的事情,主要应该是**开发人员**需要了解的系统或编程问题. 在这种情况下,没有`data` : + +``` +{ + errors: [ + {"message": "argument error: expected an integer, got null"}, + ] +} +``` + +这是在突变过程中引发错误的结果. 在我们的实现中,参数错误和验证错误的消息将返回给客户端,所有其他`StandardError`实例将被捕获,记录并呈现给客户端,并将消息设置为`"Internal server error"` . 有关详细信息,请参见[`GraphqlController`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/controllers/graphql_controller.rb) . + +这些代表编程错误,例如: + +* A GraphQL syntax error, where an `Int` was passed instead of a `String`, or a required argument was not present. +* 我们架构中的错误,例如无法为不可为空的字段提供值. +* 系统错误:例如,Git 存储异常或数据库不可用. + +用户在常规使用中不应导致此类错误. 此类错误应视为内部错误,并且不向用户详细显示. + +我们需要在突变失败时通知用户,但是我们不必告诉他们原因,因为他们不可能造成突变,尽管我们可以提供重试突变的方法,但他们无能为力. + +#### Categorizing errors[](#categorizing-errors "Permalink") + +当我们编写突变时,我们需要意识到错误状态属于这两个类别中的哪一个(并与前端开发人员进行沟通以验证我们的假设). 这意味着将*用户*的需求与*客户*的需求区分开. + +> *除非用户需要了解错误,否则切勿捕获错误.* + +如果用户确实需要了解它,请与前端开发人员进行交流,以确保我们传回的错误信息有用. + +另请参见[前端 GraphQL 指南](../development/fe_guide/graphql.html#handling-errors) . + +### Aliasing and deprecating mutations[](#aliasing-and-deprecating-mutations "Permalink") + +`#mount_aliased_mutation`帮助器允许我们将突变别名作为`MutationType`另一个名称. + +例如,将名为`FooMutation`的突变别名为`BarMutation` : + +``` +mount_aliased_mutation 'BarMutation', Mutations::FooMutation +``` + +结合[`deprecated`](#deprecating-fields)参数,这使我们可以重命名突变并继续支持旧名称. + +Example: + +``` +mount_aliased_mutation 'UpdateFoo', + Mutations::Foo::Update, + deprecated: { reason: 'Use fooUpdate', milestone: '13.2' } +``` + +不赞成使用的突变应添加到`Types::DeprecatedMutations`并在`Types::MutationType`的单元测试中进行测试. 合并请求[!34798](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34798)可以称为此示例,包括测试已弃用的别名突变的方法. + +## Validating arguments[](#validating-arguments "Permalink") + +要验证单个参数,请照常使用[`prepare`选项](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/fields/arguments.md) . + +有时,变异或解析器可以接受许多可选参数,但是我们仍然要验证是否至少提供了一个可选参数. 在这种情况下,请考虑使用`#ready?` 突变或解析器中提供验证的方法. `#ready?` 在`#resolve`方法中完成任何工作之前,将调用方法. + +Example: + +``` +def ready?(**args) + if args.values_at(:body, :position).compact.blank? + raise Gitlab::Graphql::Errors::ArgumentError, + 'body or position arguments are required' + end + + # Always remember to call `#super` + super +end +``` + +如果将来将此[RFC](https://github.com/graphql/graphql-spec/blob/master/rfcs/InputUnion.md)合并,则可以使用`InputUnions`完成. + +## GitLab’s custom scalars[](#gitlabs-custom-scalars "Permalink") + +### `Types::TimeType`[](#typestimetype "Permalink") + +[`Types::TimeType`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/graphql/types/time_type.rb)必须用作处理 Ruby `Time`和`DateTime`对象的所有字段和参数的类型. + +该类型是[一个自定义标量](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/scalars.md#custom-scalars) : + +* 当用作 GraphQL 字段的类型时,将 Ruby 的`Time`和`DateTime`对象转换为标准化的 ISO-8601 格式的字符串. +* 当用作 GraphQL 参数的类型时,将 ISO-8601 格式的时间字符串转换为 Ruby `Time`对象. + +这使我们的 GraphQL API 具有标准化的方式来表示时间并处理时间输入. + +Example: + +``` +field :created_at, Types::TimeType, null: true, description: 'Timestamp of when the issue was created' +``` + +## Testing[](#testing "Permalink") + +在`spec/requests/api/graphql`实时进行针对 graphql 查询或突变的*全栈*测试. + +添加查询时,可以使用`a working graphql query`共享示例来测试该查询是否呈现有效结果. + +使用`GraphqlHelpers#all_graphql_fields_for` -helper,可以构造一个包含所有可用字段的查询. 这使得添加测试渲染所有可能的查询字段变得容易. + +为了测试 GraphQL 突变请求, `GraphqlHelpers`提供了 2 个助手: `graphql_mutation` ,它使用突变的名称;以及带有该突变输入的哈希. 这将返回带有变异查询和预备变量的结构. + +然后可以将此结构传递给`post_graphql_mutation`帮助器,该帮助器将使用正确的参数发布请求,就像 GraphQL 客户端所做的那样. + +要访问突变的响应,可以使用`graphql_mutation_response`帮助器. + +使用这些帮助器,我们可以建立如下规格: + +``` +let(:mutation) do + graphql_mutation( + :merge_request_set_wip, + project_path: 'gitlab-org/gitlab-foss', + iid: '1', + wip: true + ) +end + +it 'returns a successful response' do + post_graphql_mutation(mutation, current_user: user) + + expect(response).to have_gitlab_http_status(:success) + expect(graphql_mutation_response(:merge_request_set_wip)['errors']).to be_empty +end +``` + +## Notes about Query flow and GraphQL infrastructure[](#notes-about-query-flow-and-graphql-infrastructure "Permalink") + +可以在`lib/gitlab/graphql`找到 GitLab 的 GraphQL 基础架构. + +[检测](https://graphql-ruby.org/queries/instrumentation.html)是环绕正在执行的查询的功能. 它被实现为使用`Instrumentation`类的模块. + +Example: `Present` + +``` +module Gitlab + module Graphql + module Present + #... some code above... + + def self.use(schema_definition) + schema_definition.instrument(:field, ::Gitlab::Graphql::Present::Instrumentation.new) + end + end + end +end +``` + +[查询分析器](https://graphql-ruby.org/queries/ast_analysis.html#analyzer-api)包含一系列回调,以在执行查询之前对其进行验证. 每个字段都可以通过分析仪,最终值也可供您使用. + +[多重查询](https://graphql-ruby.org/queries/multiplex.html)使多个查询可以在单个请求中发送. 这减少了发送到服务器的请求数量. (GraphQL Ruby 提供了自定义的 Multiplex 查询分析器和 Multiplex 工具). + +### Query limits[](#query-limits "Permalink") + +查询和变异受到深度,复杂性和递归的限制,以保护服务器资源免受过度野心或恶意查询的侵害. 这些值可以设置为默认值,并根据需要在特定查询中覆盖. 也可以为每个对象设置复杂度值,并根据返回的对象数来评估最终查询的复杂度. 这对于昂贵的对象(例如需要 Gitaly 调用)很有用. + +例如,解析器中的条件复杂度方法: + +``` +def self.resolver_complexity(args, child_complexity:) + complexity = super + complexity += 2 if args[:labelName] + + complexity +end +``` + +有关复杂性的更多信息: [GraphQL Ruby 文档](https://graphql-ruby.org/queries/complexity_and_depth.html) . + +## Documentation and Schema[](#documentation-and-schema "Permalink") + +我们的模式位于`app/graphql/gitlab_schema.rb` . 有关详细信息,请参见[架构参考](../api/graphql/reference/index.html) . + +模式更改时,需要更新此生成的 GraphQL 文档. 有关生成 GraphQL 文档和架构文件的信息,请参阅[更新架构文档](rake_tasks.html#update-graphql-documentation-and-schema-definitions) . \ No newline at end of file diff --git a/docs/613.md b/docs/613.md new file mode 100644 index 0000000000000000000000000000000000000000..00e7d9ea5f6285734d118939a08625035824e3f0 --- /dev/null +++ b/docs/613.md @@ -0,0 +1,223 @@ +# Guidelines for shell commands in the GitLab codebase + +> 原文:[https://docs.gitlab.com/ee/development/shell_commands.html](https://docs.gitlab.com/ee/development/shell_commands.html) + +* [References](#references) +* [Use File and FileUtils instead of shell commands](#use-file-and-fileutils-instead-of-shell-commands) +* [Always use the configurable Git binary path for Git commands](#always-use-the-configurable-git-binary-path-for-git-commands) +* [Bypass the shell by splitting commands into separate tokens](#bypass-the-shell-by-splitting-commands-into-separate-tokens) +* [Separate options from arguments with –](#separate-options-from-arguments-with---) +* [Do not use the backticks](#do-not-use-the-backticks) +* [Avoid user input at the start of path strings](#avoid-user-input-at-the-start-of-path-strings) +* [Guard against path traversal](#guard-against-path-traversal) +* [Properly anchor regular expressions to the start and end of strings](#properly-anchor-regular-expressions-to-the-start-and-end-of-strings) + +# Guidelines for shell commands in the GitLab codebase[](#guidelines-for-shell-commands-in-the-gitlab-codebase "Permalink") + +本文档包含使用 GitLab 代码库中的进程和文件的准则. 这些准则旨在使您的代码更加可靠*和*安全. + +## References[](#references "Permalink") + +* [Google Ruby Security Reviewer’s Guide](https://code.google.com/archive/p/ruby-security/wikis/Guide.wiki) +* [OWASP Command Injection](https://wiki.owasp.org/index.php/Command_Injection) +* [Ruby on Rails Security Guide Command Line Injection](https://guides.rubyonrails.org/security.html#command-line-injection) + +## Use File and FileUtils instead of shell commands[](#use-file-and-fileutils-instead-of-shell-commands "Permalink") + +有时,当还有 Ruby API 可以通过外壳调用基本的 Unix 命令时. 使用 Ruby API(如果存在). [http://www.ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html#module-FileUtils-label-Module+Functions](http://www.ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html#module-FileUtils-label-Module+Functions) + +``` +# Wrong +system "mkdir -p tmp/special/directory" +# Better (separate tokens) +system *%W(mkdir -p tmp/special/directory) +# Best (do not use a shell command) +FileUtils.mkdir_p "tmp/special/directory" + +# Wrong +contents = `cat #{filename}` +# Correct +contents = File.read(filename) + +# Sometimes a shell command is just the best solution. The example below has no +# user input, and is hard to implement correctly in Ruby: delete all files and +# directories older than 120 minutes under /some/path, but not /some/path +# itself. +Gitlab::Popen.popen(%W(find /some/path -not -path /some/path -mmin +120 -delete)) +``` + +这种编码风格可能阻止了 CVE-2013-4490. + +## Always use the configurable Git binary path for Git commands[](#always-use-the-configurable-git-binary-path-for-git-commands "Permalink") + +``` +# Wrong +system(*%W(git branch -d -- #{branch_name})) + +# Correct +system(*%W(#{Gitlab.config.git.bin_path} branch -d -- #{branch_name})) +``` + +## Bypass the shell by splitting commands into separate tokens[](#bypass-the-shell-by-splitting-commands-into-separate-tokens "Permalink") + +当我们将 shell 命令作为单个字符串传递给 Ruby 时,Ruby 将让`/bin/sh`评估整个字符串. 本质上,我们要求外壳程序评估单行脚本. 这会造成外壳注入攻击的风险. 最好自己将 shell 命令拆分为令牌. 有时,我们使用外壳程序的脚本功能来更改工作目录或设置环境变量. 所有这些都可以直接从 Ruby 安全地实现 + +``` +# Wrong +system "cd /home/git/gitlab && bundle exec rake db:#{something} RAILS_ENV=production" +# Correct +system({'RAILS_ENV' => 'production'}, *%W(bundle exec rake db:#{something}), chdir: '/home/git/gitlab') + +# Wrong +system "touch #{myfile}" +# Better +system "touch", myfile +# Best (do not run a shell command at all) +FileUtils.touch myfile +``` + +这种编码风格可能阻止了 CVE-2013-4546. + +## Separate options from arguments with –[](#separate-options-from-arguments-with--- "Permalink") + +使用`--`使系统命令的参数解析器可以清楚了解选项和参数之间的区别. 许多但并非所有 Unix 命令都支持此功能. + +要了解什么`--`不,请考虑以下问题. + +``` +# Example +$ echo hello > -l +$ cat -l + +cat: illegal option -- l +usage: cat [-benstuv] [file ...] +``` + +在上面的示例中, `cat`的参数解析器假定`-l`是一个选项. 在上面的例子中的解决方案是明确告诉`cat`那`-l`实在是一个论点,不是一种选择. 许多 Unix 命令行工具都遵循用`--`分隔选项和参数的约定. + +``` +# Example (continued) +$ cat -- -l + +hello +``` + +在 GitLab 代码库中,我们*总是*通过对支持它的命令使用`--`来避免选项/参数的歧义. + +``` +# Wrong +system(*%W(#{Gitlab.config.git.bin_path} branch -d #{branch_name})) +# Correct +system(*%W(#{Gitlab.config.git.bin_path} branch -d -- #{branch_name})) +``` + +这种编码风格可能阻止了 CVE-2013-4582. + +## Do not use the backticks[](#do-not-use-the-backticks "Permalink") + +用反引号捕获 shell 命令的输出很不错,但是您不得不将命令作为一个字符串传递给 shell. 上面我们解释了这是不安全的. 在主要的 GitLab 代码库中,解决方案是改用`Gitlab::Popen.popen` . + +``` +# Wrong +logs = `cd #{repo_dir} && #{Gitlab.config.git.bin_path} log` +# Correct +logs, exit_status = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} log), repo_dir) + +# Wrong +user = `whoami` +# Correct +user, exit_status = Gitlab::Popen.popen(%W(whoami)) +``` + +在其他存储库(如 GitLab Shell)中,您也可以使用`IO.popen` . + +``` +# Safe IO.popen example +logs = IO.popen(%W(#{Gitlab.config.git.bin_path} log), chdir: repo_dir) { |p| p.read } +``` + +请注意,与`Gitlab::Popen.popen`不同, `IO.popen`不会捕获标准错误. + +## Avoid user input at the start of path strings[](#avoid-user-input-at-the-start-of-path-strings "Permalink") + +可以使用各种在 Ruby 中打开和读取文件的方法来读取进程的标准输出而不是文件. 以下两个命令大致相同: + +``` +`touch /tmp/pawned-by-backticks` +File.read('|touch /tmp/pawned-by-file-read') +``` + +关键是打开一个以" `|` "开头的"文件" `|` . 受影响的方法包括 Kernel#open,File :: read,File :: open,IO :: open 和 IO :: read. + +您可以通过确保攻击者无法控制要打开的文件名字符串的开头来防止"打开"和"读取"这种行为. 例如,下面的内容足以防止意外地使用`|`启动 shell 命令`|` : + +``` +# we assume repo_path is not controlled by the attacker (user) +path = File.join(repo_path, user_input) +# path cannot start with '|' now. +File.read(path) +``` + +如果必须使用用户输入的相对路径,请在路径前添加`./` . + +前缀用户提供的路径还提供了针对以`-`开头的路径的额外保护(请参阅上面有关使用`--`的讨论). + +## Guard against path traversal[](#guard-against-path-traversal "Permalink") + +路径遍历是一种安全措施,程序(GitLab)试图限制用户对磁盘上某个目录的访问,但用户设法利用`../`路径符号来打开该目录之外的文件. + +``` +# Suppose the user gave us a path and they are trying to trick us +user_input = '../other-repo.git/other-file' + +# We look up the repo path somewhere +repo_path = 'repositories/user-repo.git' + +# The intention of the code below is to open a file under repo_path, but +# because the user used '..' they can 'break out' into +# 'repositories/other-repo.git' +full_path = File.join(repo_path, user_input) +File.open(full_path) do # Oops! +``` + +防止这种情况发生的好方法是根据 Ruby 的`File.absolute_path`将完整路径与其"绝对路径"进行`File.absolute_path` . + +``` +full_path = File.join(repo_path, user_input) +if full_path != File.absolute_path(full_path) + raise "Invalid path: #{full_path.inspect}" +end + +File.open(full_path) do # Etc. +``` + +这样的检查可以避免 CVE-2013-4583. + +## Properly anchor regular expressions to the start and end of strings[](#properly-anchor-regular-expressions-to-the-start-and-end-of-strings "Permalink") + +当使用正则表达式来验证作为参数传递给 shell 命令的用户输入时,请确保使用`\A`和`\z`定位符来指定字符串的开头和结尾,而不是`^`和`$` ,或者不要使用定位符所有. + +如果您不这样做,攻击者可能会使用它来执行具有潜在有害影响的命令. + +例如,当如下所示验证项目的`import_url`时,用户可以诱使 GitLab 从本地文件系统上的 Git 存储`import_url` . + +``` +validates :import_url, format: { with: URI.regexp(%w(ssh git http https)) } +# URI.regexp(%w(ssh git http https)) roughly evaluates to /(ssh|git|http|https):(something_that_looks_like_a_url)/ +``` + +假设用户提交以下内容作为其导入 URL: + +``` +file://git:/tmp/lol +``` + +由于使用的正则表达式中没有锚,因此值中的`git:/tmp/lol`将匹配,并且验证将通过. + +导入时,GitLab 将执行以下命令,将`import_url`作为参数传递: + +``` +git clone file://git:/tmp/lol +``` + +Git 只会忽略`git:`部分,将路径解释为`file:///tmp/lol` ,然后将存储库导入到新项目中. 此操作可能使攻击者可以访问系统中的任何存储库(无论是否私有). \ No newline at end of file diff --git a/docs/614.md b/docs/614.md new file mode 100644 index 0000000000000000000000000000000000000000..b98b72d86fe38bdc1f523f2e2478cb89c6570bf7 --- /dev/null +++ b/docs/614.md @@ -0,0 +1,64 @@ +# HTML style guide + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/style/html.html](https://docs.gitlab.com/ee/development/fe_guide/style/html.html) + +* [Buttons](#buttons) + * [Button type](#button-type) + * [Button role](#button-role) +* [Links](#links) + * [Blank target](#blank-target) + * [Fake links](#fake-links) + +# HTML style guide[](#html-style-guide "Permalink") + +## Buttons[](#buttons "Permalink") + +### Button type[](#button-type "Permalink") + +按钮标记需要根据[W3C HTML 规范](https://www.w3.org/TR/2011/WD-html5-20110525/the-button-element.html#dom-button-type)的`type`属性. + +``` +// bad +<button></button> + +// good +<button type="button"></button> +``` + +### Button role[](#button-role "Permalink") + +如果 HTML 元素具有`onClick`处理程序但不是按钮,则应具有`role="button"` . 这[更容易访问](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/Accessibility/ARIA/Roles/button_role) . + +``` +// bad +<div onClick="doSomething"></div> + +// good +<div role="button" onClick="doSomething"></div> +``` + +## Links[](#links "Permalink") + +### Blank target[](#blank-target "Permalink") + +每当您的链接在新窗口中打开时,即使用`target="_blank"` ,请使用`rel="noopener noreferrer"` `target="_blank"` . 这可以防止[JitBit 记录](https://www.jitbit.com/alexblog/256-targetblank---the-most-underestimated-vulnerability-ever/)的安全漏洞. + +``` +// bad +<a href="url" target="_blank"></a> + +// good +<a href="url" target="_blank" rel="noopener noreferrer"></a> +``` + +### Fake links[](#fake-links "Permalink") + +**不要使用虚假链接.** 如果链接仅调用 JavaScript click 事件处理程序,则使用按钮标签,这更具语义. + +``` +// bad +<a class="js-do-something" href="#"></a> + +// good +<button class="js-do-something" type="button"></button> +``` \ No newline at end of file diff --git a/docs/615.md b/docs/615.md new file mode 100644 index 0000000000000000000000000000000000000000..a84609801d0771b586df38c800df280e058b950f --- /dev/null +++ b/docs/615.md @@ -0,0 +1,294 @@ +# JavaScript style guide + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/style/javascript.html](https://docs.gitlab.com/ee/development/fe_guide/style/javascript.html) + +* [Avoid forEach](#avoid-foreach) +* [Limit number of parameters](#limit-number-of-parameters) +* [Avoid classes to handle DOM events](#avoid-classes-to-handle-dom-events) +* [Pass element container to constructor](#pass-element-container-to-constructor) +* [Use ParseInt](#use-parseint) +* [CSS Selectors - Use `js-` prefix](#css-selectors---use-js--prefix) +* [ES Module Syntax](#es-module-syntax) +* [Absolute vs relative paths for modules](#absolute-vs-relative-paths-for-modules) +* [Do not use `DOMContentLoaded` in non-page modules](#do-not-use-domcontentloaded-in-non-page-modules) +* [Avoid XSS](#avoid-xss) +* [Avoid single-line conditional statements](#avoid-single-line-conditional-statements) +* [ESLint](#eslint) +* [IIFEs](#iifes) +* [Global namespace](#global-namespace) +* [Side effects](#side-effects) + * [Top-level side effects](#top-level-side-effects) + * [Avoid side effects in constructors](#avoid-side-effects-in-constructors) +* [Pure Functions and Data Mutation](#pure-functions-and-data-mutation) + +# JavaScript style guide[](#javascript-style-guide "Permalink") + +我们使用[Airbnb 的 JavaScript 样式指南](https://github.com/airbnb/javascript)及其附带的 linter 来管理我们的大多数 JavaScript 样式指南. + +除了由 Airbnb 设置的样式准则之外,我们还列出了以下一些特定规则. + +> **提示:**您可以通过运行`yarn eslint`在本地运行`yarn eslint` + +## Avoid forEach[](#avoid-foreach "Permalink") + +变异数据时避免 forEach. 更改数据时,请使用`map` , `reduce`或`filter`而不是`forEach` . 这样可以最大程度地减少功能上的变化,从而与[Airbnb 的风格指南](https://github.com/airbnb/javascript#testing--for-real)保持一致. + +``` +// bad +users.forEach((user, index) => { + user.id = index; +}); + +// good +const usersWithId = users.map((user, index) => { + return Object.assign({}, user, { id: index }); +}); +``` + +## Limit number of parameters[](#limit-number-of-parameters "Permalink") + +如果您的函数或方法具有三个以上的参数,请改为使用对象作为参数. + +``` +// bad +function a(p1, p2, p3) { + // ... +}; + +// good +function a(p) { + // ... +}; +``` + +## Avoid classes to handle DOM events[](#avoid-classes-to-handle-dom-events "Permalink") + +如果该类的唯一目的是绑定 DOM 事件并处理回调,则最好使用函数. + +``` +// bad +class myClass { + constructor(config) { + this.config = config; + } + + init() { + document.addEventListener('click', () => {}); + } +} + +// good + +const myFunction = () => { + document.addEventListener('click', () => { + // handle callback here + }); +} +``` + +## Pass element container to constructor[](#pass-element-container-to-constructor "Permalink") + +当您的类操作 DOM 时,将元素容器作为参数接收. 这样更易于维护和执行. + +``` +// bad +class a { + constructor() { + document.querySelector('.b'); + } +} + +// good +class a { + constructor(options) { + options.container.querySelector('.b'); + } +} +``` + +## Use ParseInt[](#use-parseint "Permalink") + +将数字字符串转换为数字时,请使用`ParseInt` . + +``` +// bad +Number('10') + +// good +parseInt('10', 10); +``` + +## CSS Selectors - Use `js-` prefix[](#css-selectors---use-js--prefix "Permalink") + +如果仅在 JavaScript 中使用 CSS 类作为对元素的引用,则使用`js-`作为类名的前缀. + +``` +// bad +<button class="add-user"></button> + +// good +<button class="js-add-user"></button> +``` + +## ES Module Syntax[](#es-module-syntax "Permalink") + +使用 ES 模块语法导入模块: + +``` +// bad +const SomeClass = require('some_class'); + +// good +import SomeClass from 'some_class'; + +// bad +module.exports = SomeClass; + +// good +export default SomeClass; +``` + +*注意:*我们仍然在`scripts/`和`config/`文件中使用`require` . + +## Absolute vs relative paths for modules[](#absolute-vs-relative-paths-for-modules "Permalink") + +如果要导入的模块少于两个级别,请使用相对路径. + +``` +// bad +import GitLabStyleGuide from '~/guides/GitLabStyleGuide'; + +// good +import GitLabStyleGuide from '../GitLabStyleGuide'; +``` + +如果要导入的模块为两个或两个以上级别,请改用绝对路径: + +``` +// bad +import GitLabStyleGuide from '../../../guides/GitLabStyleGuide'; + +// good +import GitLabStyleGuide from '~/GitLabStyleGuide'; +``` + +Additionally, **不添加到全局名称空间**. + +## Do not use `DOMContentLoaded` in non-page modules[](#do-not-use-domcontentloaded-in-non-page-modules "Permalink") + +导入的模块每次加载时都应发挥相同的作用. `DOMContentLoaded`事件仅允许在`/pages/*`目录中加载的模块上使用,因为这些事件是通过 webpack 动态加载的. + +## Avoid XSS[](#avoid-xss "Permalink") + +不要使用`innerHTML` , `append()`或`html()`设置内容. 它打开了太多的漏洞. + +## Avoid single-line conditional statements[](#avoid-single-line-conditional-statements "Permalink") + +缩进在扫描代码时很重要,因为它可以快速指示分支,循环和返回点的存在. 这可以帮助快速了解控制流程. + +``` +// bad +if (isThingNull) return ''; + +if (isThingNull) + return ''; + +// good +if (isThingNull) { + return ''; +} +``` + +## ESLint[](#eslint "Permalink") + +ESLint 行为可以在我们的[工具指南中](../tooling.html)找到. + +## IIFEs[](#iifes "Permalink") + +避免使用 IIFE(立即调用函数表达式). 尽管我们有很多将其内容包装在 IIFE 中的文件示例,但是从 Sprockets 过渡到 Webpack 之后,这不再是必需的. 重构遗留代码时,请不要再使用它们,并随时将其删除. + +## Global namespace[](#global-namespace "Permalink") + +避免添加到全局名称空间. + +``` +// bad +window.MyClass = class { /* ... */ }; + +// good +export default class MyClass { /* ... */ } +``` + +## Side effects[](#side-effects "Permalink") + +### Top-level side effects[](#top-level-side-effects "Permalink") + +在任何包含`export`脚本中都禁止顶级副作用: + +``` +// bad +export default class MyClass { /* ... */ } + +document.addEventListener("DOMContentLoaded", function(event) { + new MyClass(); +} +``` + +### Avoid side effects in constructors[](#avoid-side-effects-in-constructors "Permalink") + +避免在`constructor`进行异步调用,API 请求或 DOM 操作. 而是将它们移动到单独的函数中. 这将使测试更易于编写,并且避免违反[单一职责原则](https://en.wikipedia.org/wiki/Single_responsibility_principle) . + +``` +// bad +class myClass { + constructor(config) { + this.config = config; + axios.get(this.config.endpoint) + } +} + +// good +class myClass { + constructor(config) { + this.config = config; + } + + makeRequest() { + axios.get(this.config.endpoint) + } +} +const instance = new myClass(); +instance.makeRequest(); +``` + +## Pure Functions and Data Mutation[](#pure-functions-and-data-mutation "Permalink") + +努力编写许多小的纯函数,并尽量减少发生突变的地方 + +``` + // bad + const values = {foo: 1}; + + function impureFunction(items) { + const bar = 1; + + items.foo = items.a * bar + 2; + + return items.a; + } + + const c = impureFunction(values); + + // good + var values = {foo: 1}; + + function pureFunction (foo) { + var bar = 1; + + foo = foo * bar + 2; + + return foo; + } + + var c = pureFunction(values.foo); +``` \ No newline at end of file diff --git a/docs/616.md b/docs/616.md new file mode 100644 index 0000000000000000000000000000000000000000..0fb587b4006c16998a56f4cec1f6e7de318d0796 --- /dev/null +++ b/docs/616.md @@ -0,0 +1,769 @@ +# Migration Style Guide + +> 原文:[https://docs.gitlab.com/ee/development/migration_style_guide.html](https://docs.gitlab.com/ee/development/migration_style_guide.html) + +* [Schema Changes](#schema-changes) +* [What Requires Downtime?](#what-requires-downtime) +* [Downtime Tagging](#downtime-tagging) +* [Reversibility](#reversibility) +* [Atomicity](#atomicity) +* [Heavy operations in a single transaction](#heavy-operations-in-a-single-transaction) +* [Retry mechanism when acquiring database locks](#retry-mechanism-when-acquiring-database-locks) + * [Examples](#examples) + * [When to use the helper method](#when-to-use-the-helper-method) + * [How the helper method works](#how-the-helper-method-works) +* [Multi-Threading](#multi-threading) +* [Removing indexes](#removing-indexes) +* [Adding indexes](#adding-indexes) +* [Adding foreign-key constraints](#adding-foreign-key-constraints) +* [`NOT NULL` constraints](#not-null-constraints) +* [Adding Columns With Default Values](#adding-columns-with-default-values) +* [Changing the column default](#changing-the-column-default) +* [Updating an existing column](#updating-an-existing-column) +* [Dropping a database table](#dropping-a-database-table) +* [Integer column type](#integer-column-type) +* [Strings and the Text data type](#strings-and-the-text-data-type) +* [Timestamp column type](#timestamp-column-type) +* [Storing JSON in database](#storing-json-in-database) +* [Testing](#testing) +* [Data migration](#data-migration) + * [Renaming reserved paths](#renaming-reserved-paths) + +# Migration Style Guide[](#migration-style-guide "Permalink") + +在为 GitLab 编写迁移时,必须考虑到这些迁移将由成千上万个各种规模的组织来运行,其中一些组织的数据库中包含多年的数据. + +此外,对于大多数组织来说,必须使服务器脱机以进行较小或较大的升级是一大负担. 因此,重要的是要仔细编写迁移文件,可以在线进行迁移,并遵守下面的样式指南. + +迁移**不准**要求 GitLab 设施采取离线,除非*绝对必要的* . + +如果需要停机,则必须通过以下方式批准迁移: + +1. 工程副总裁 +2. 后端维护者 +3. 数据库维护者 + +可以在[https://about.gitlab.com/company/team/中](https://about.gitlab.com/company/team/)找到持有这些头衔的人员的最新列表. + +When writing your migrations, also consider that databases might have stale data or inconsistencies and guard for that. Try to make as few assumptions as possible about the state of the database. + +请不要依赖特定于 GitLab 的代码,因为它可能会在将来的版本中更改. 如果需要,将 GitLab 代码复制粘贴到迁移中以使其向前兼容. + +对于 GitLab.com,请考虑到在[部署 Canary](https://about.gitlab.com/handbook/engineering/infrastructure/library/canary/#configuration-and-deployment)之前运行常规迁移(在`db/migrate` ),在完成生产部署后运行部署后的迁移( `db/post_migrate` ). + +## Schema Changes[](#schema-changes "Permalink") + +Changes to the schema should be committed to `db/structure.sql`. This file is automatically generated by Rails, so you normally should not edit this file by hand. If your migration is adding a column to a table, that column will be added at the bottom. Please do not reorder columns manually for existing tables as this will cause confusing to other people using `db/structure.sql` generated by Rails. + +当您的 GDK 中的本地数据库与`master`数据库中的模式不同时,可能很难将模式更改完全提交给 Git. 在这种情况下,您可以使用`scripts/regenerate-schema`脚本为要添加的迁移重新生成干净的`db/structure.sql` . 该脚本将应用在`db/migrate`或`db/post_migrate`找到的所有迁移,因此,如果您不想将任何迁移提交到架构,请重命名或删除它们. 如果您的分支不是以`master`为目标,则可以设置`TARGET`环境变量. + +``` +# Regenerate schema against `master` +scripts/regenerate-schema + +# Regenerate schema against `12-9-stable-ee` +TARGET=12-9-stable-ee scripts/regenerate-schema +``` + +## What Requires Downtime?[](#what-requires-downtime "Permalink") + +文档["什么需要停机?"](what_requires_downtime.html) 指定各种数据库操作,例如 + +* [dropping and renaming columns](what_requires_downtime.html#dropping-columns) +* [changing column constraints and types](what_requires_downtime.html#changing-column-constraints) +* [adding and dropping indexes, tables, and foreign keys](what_requires_downtime.html#adding-indexes) + +以及他们是否需要停机,以及如何尽可能地进行停机. + +## Downtime Tagging[](#downtime-tagging "Permalink") + +每个迁移都必须指定是否需要停机,并且如果需要停机,还必须指定原因. 这是即使在迁移的 99%,不需要停机,因为这使得它更容易地发现, *确实*需要停机迁移所需. + +要标记迁移,请在迁移类的主体中添加以下两个常量: + +* `DOWNTIME` :一个布尔值,当设置为`true`指示迁移需要停机时间. +* `DOWNTIME_REASON` :一个字符串,其中包含需要停机的迁移原因. 当`DOWNTIME`设置为`true`时, **必须**设置此常数. + +例如: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + DOWNTIME = true + DOWNTIME_REASON = 'This migration requires downtime because ...' + + def change + ... + end +end +``` + +如果迁移类中缺少`DOWNTIME`常量,则会出现错误(即 CI 将失败). + +## Reversibility[](#reversibility "Permalink") + +您的迁移**必须是**可逆的. 这非常重要,因为在出​​现漏洞或错误的情况下应该可以降级. + +在迁移中,添加一条注释,描述如何测试迁移的可逆性. + +某些迁移无法撤消. 例如,某些数据迁移无法撤消,因为在迁移之前,我们丢失了有关数据库状态的信息. 您仍然应该创建一个带注释的`down`方法,解释为什么不能撤消`up`方法执行的更改,以便即使撤消迁移期间执行的更改也可以撤消迁移本身: + +``` +def down + # no-op + + # comment explaining why changes performed by `up` cannot be reversed. +end +``` + +## Atomicity[](#atomicity "Permalink") + +默认情况下,迁移是单个事务. 即,在迁移开始时打开一个事务,并在处理完所有步骤后提交. + +在单个事务中运行迁移可确保如果其中一个步骤失败,则将不会执行任何步骤,从而使数据库保持有效状态. 因此,要么: + +* 将所有迁移都放在一个单事务迁移中. +* 如有必要,将大多数操作放入一个迁移中,并为无法在单个事务中完成的步骤创建一个单独的迁移. + +例如,如果创建一个空表并需要为其建立索引,则建议使用常规的单事务迁移和默认的 rails schema 语句: [`add_index`](https://api.rubyonrails.org/v5.2/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_index) . 这是一个阻塞操作,但不会引起问题,因为该表尚未使用,因此它还没有任何记录. + +## Heavy operations in a single transaction[](#heavy-operations-in-a-single-transaction "Permalink") + +使用单事务迁移时,事务将在迁移期间保持数据库连接,因此您必须确保迁移中的操作不会花费太多时间:通常,在迁移中执行的查询需要在 GitLab.com 上舒适地放置`15s` . + +如果您需要插入,更新或删除大量数据,请执行以下操作: + +* 必须使用`disable_ddl_transaction!`禁用单个事务`disable_ddl_transaction!` . +* 应该考虑在[后台迁移中](background_migrations.html)这样做. + +## Retry mechanism when acquiring database locks[](#retry-mechanism-when-acquiring-database-locks "Permalink") + +更改数据库架构时,我们使用辅助方法来调用 DDL(数据定义语言)语句. 在某些情况下,这些 DDL 语句需要特定的数据库锁. + +Example: + +``` +def change + remove_column :users, :full_name, :string +end +``` + +要执行此迁移,需要对`users`表进行排他锁定. 当表被其他进程同时访问和修改时,获取锁定可能需要一段时间. 锁定请求正在队列中等待,一旦进入队列,它也可能阻止`users`表上的其他查询. + +有关 PostgresSQL 锁的更多信息: [显式锁定](https://s0www0postgresql0org.icopy.site/docs/current/explicit-locking.html) + +出于稳定性考虑,GitLab.com 设置了特定的[`statement_timeout`](../user/gitlab_com/index.html#postgresql) . 调用迁移时,任何数据库查询都将有固定的执行时间. 在最坏的情况下,请求将坐在锁定队列中,在配置的语句超时时间内阻止其他查询,然后`canceling statement due to statement timeout`错误`canceling statement due to statement timeout`失败. + +此问题可能导致应用程序升级过程失败,甚至导致应用程序稳定性问题,因为该表可能会在短时间内无法访问. + +为了提高数据库迁移的可靠性和稳定性,GitLab 代码库提供了一种辅助方法,以使用不同的`lock_timeout`设置重试操作,并在两次尝试之间等待时间. 为了获得必要的锁定,进行了多次较小的尝试,从而使数据库可以处理其他语句. + +### Examples[](#examples "Permalink") + +**删除列:** + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + remove_column :users, :full_name + end +end + +def down + with_lock_retries do + add_column :users, :full_name, :string + end +end +``` + +**删除外键:** + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + remove_foreign_key :issues, :projects + end +end + +def down + with_lock_retries do + add_foreign_key :issues, :projects + end +end +``` + +**更改列的默认值:** + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + change_column_default :merge_requests, :lock_version, from: nil, to: 0 + end +end + +def down + with_lock_retries do + change_column_default :merge_requests, :lock_version, from: 0, to: nil + end +end +``` + +**用外键创建一个新表:** + +我们可以简单地用`with_lock_retries`包装`create_table`方法: + +``` +def up + with_lock_retries do + create_table :issues do |t| + t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade } + t.string :title, limit: 255 + end + end +end + +def down + drop_table :issues +end +``` + +**当我们有两个外键时创建一个新表:** + +为此,我们需要进行三个迁移: + +1. 创建不带外键(带有索引)的表. +2. 将外键添加到第一个表. +3. 将外键添加到第二个表. + +创建表: + +``` +def up + create_table :imports do |t| + t.bigint :project_id, null: false + t.bigint :user_id, null: false + t.string :jid, limit: 255 + end + + add_index :imports, :project_id + add_index :imports, :user_id +end + +def down + drop_table :imports +end +``` + +在`projects`添加外键: + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + add_foreign_key :imports, :projects, column: :project_id, on_delete: :cascade + end +end + +def down + with_lock_retries do + remove_foreign_key :imports, column: :project_id + end +end +``` + +向`users`添加外键: + +``` +include Gitlab::Database::MigrationHelpers + +def up + with_lock_retries do + add_foreign_key :imports, :users, column: :user_id, on_delete: :cascade + end +end + +def down + with_lock_retries do + remove_foreign_key :imports, column: :user_id + end +end +``` + +**与`disable_ddl_transaction!`配合使用`disable_ddl_transaction!`** + +通常, `with_lock_retries`帮助程序应与`disabled_ddl_transaction!` . 定制的 RuboCop 规则可确保只能将允许的方法放在锁重试块中. + +``` +disable_ddl_transaction! + +def up + with_lock_retries do + add_column :users, :name, :text + end + + add_text_limit :users, :name, 255 # Includes constraint validation (full table scan) +end +``` + +RuboCop 规则通常允许使用下面列出的标准 Rails 迁移方法. 此示例将导致 Rubocop 犯罪: + +``` +disabled_ddl_transaction! + +def up + with_lock_retries do + add_concurrent_index :users, :name + end +end +``` + +### When to use the helper method[](#when-to-use-the-helper-method "Permalink") + +通常使用标准的 Rails 迁移帮助器方法时,可以使用`with_lock_retries`帮助器方法. 如果在同一个表上执行多个迁移助手,则调用它们不是问题. + +当数据库迁移涉及高流量表之一时,建议使用`with_lock_retries`帮助程序方法: + +* `users` +* `projects` +* `namespaces` +* `issues` +* `merge_requests` +* `ci_pipelines` +* `ci_builds` +* `notes` + +更改示例: + +* `add_foreign_key` / `remove_foreign_key` +* `add_column` / `remove_column` +* `change_column_default` +* `create_table` / `drop_table` + +**注意:** `with_lock_retries`方法**不能**在`change`方法中使用,必须手动定义`up`和`down`方法以使迁移可逆. + +### How the helper method works[](#how-the-helper-method-works "Permalink") + +1. 重复 50 次. +2. 对于每次迭代,设置一个预配置的`lock_timeout` . +3. 尝试执行给定的块. ( `remove_column` ). +4. 如果出现`LockWaitTimeout`错误,请为预配置的`sleep_time`睡眠,然后重试该块. +5. 如果未引发错误,则当前迭代已成功执行该块. + +有关更多信息,请检查[`Gitlab::Database::WithLockRetries`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/with_lock_retries.rb)类. `with_lock_retries`帮助器方法在[`Gitlab::Database::MigrationHelpers`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/migration_helpers.rb)模块中实现. + +在最坏的情况下,该方法: + +* 在 40 分钟内最多执行 50 次该块. + * 大部分时间都花费在每次迭代后的预先配置的睡眠时段中. +* 第 50 次重试之后,将像标准迁移调用一样在没有`lock_timeout`情况下执行该块. +* 如果无法获取锁,则迁移将失败,并出现`statement timeout`错误. + +如果访问`users`表的事务运行时间很长(超过 40 分钟),则迁移可能会失败. + +## Multi-Threading[](#multi-threading "Permalink") + +有时,迁移可能需要使用多个 Ruby 线程来加快迁移速度. 为此,您的迁移需要包括模块`Gitlab::Database::MultiThreadedMigration` : + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + include Gitlab::Database::MultiThreadedMigration +end +``` + +然后可以使用`with_multiple_threads`方法在单独的线程中执行工作. 例如: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + include Gitlab::Database::MultiThreadedMigration + + def up + with_multiple_threads(4) do + disable_statement_timeout + + # ... + end + end +end +``` + +在这里,对`disable_statement_timeout`的调用将使用`with_multiple_threads`块本地的连接,而不是重新使用全局连接池. 这样可以确保每个线程都有自己的连接对象,并且在尝试获取一个连接对象时不会超时. + +**注意:** PostgreSQL 具有允许的最大连接数. 此限制因安装而异. 因此,建议您一次迁移不要使用超过 32 个线程. 通常,4-8 个线程应该绰绰有余. + +## Removing indexes[](#removing-indexes "Permalink") + +如果删除索引时表不为空,请确保使用方法`remove_concurrent_index`而不是常规的`remove_index`方法. `remove_concurrent_index`方法同时删除索引,因此不需要锁定,也无需停机. 要使用此方法,必须通过调用方法`disable_ddl_transaction!`禁用单交易模式`disable_ddl_transaction!` 在您的迁移类的主体中,如下所示: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + disable_ddl_transaction! + + def up + remove_concurrent_index :table_name, :column_name + end +end +``` + +请注意,在删除索引之前不必检查索引是否存在. + +对于较小的表(例如空表或少于`1,000`条记录的表),建议在单事务迁移中使用`remove_index` ,并将其与不需要`disable_ddl_transaction!`其他操作结合使用`disable_ddl_transaction!` . + +## Adding indexes[](#adding-indexes "Permalink") + +在添加索引之前,请考虑该索引是否必要. 在某些情况下可能不需要索引,例如: + +* 该表很小(少于`1,000`条记录),并且预计大小不会成倍增长. +* 任何现有索引都会过滤掉足够的行. +* 添加索引后查询时间的减少并不明显. + +另外,不需要宽索引来匹配查询的所有过滤条件,我们只需要覆盖足够多的列即可使索引查找具有足够小的选择性. 请查看我们的[添加数据库索引](adding_database_indexes.html)指南以获取更多详细信息. + +将索引添加到非空表时,请确保使用方法`add_concurrent_index`而不是常规的`add_index`方法. 使用 PostgreSQL 时, `add_concurrent_index`方法自动创建并发索引,从而消除了停机时间. + +要使用此方法,必须通过调用方法`disable_ddl_transaction!`禁用单交易模式`disable_ddl_transaction!` 在您的迁移类的主体中,如下所示: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :table, :column + end + + def down + remove_concurrent_index :table, :column + end +end +``` + +如果需要添加唯一索引,请记住,数据库中可能存在现有重复项. 这意味着在添加唯一索引之前,应始终*首先*添加一个删除所有重复项的迁移. + +对于小型表(例如空表或少于`1,000`条记录的表),建议在单事务迁移中使用`add_index` ,并将其与不需要`disable_ddl_transaction!`其他操作结合使用`disable_ddl_transaction!` . + +## Adding foreign-key constraints[](#adding-foreign-key-constraints "Permalink") + +向现有列或新列添加外键约束时,还请记住在该列上添加索引. + +这是所有外键所**必需**的,例如,为了支持有效的级联删除:当删除表中的许多行时,也需要删除引用的记录. 数据库必须在引用的表中查找相应的记录. 没有索引,这将导致对表进行顺序扫描,这可能需要很长时间. + +这是一个示例,其中我们添加了一个带有外键约束的新列. 请注意,它包括`index: true`为其创建索引. + +``` +class Migration < ActiveRecord::Migration[6.0] + + def change + add_reference :model, :other_model, index: true, foreign_key: { on_delete: :cascade } + end +end +``` + +当向非空表中的现有列添加外键约束时,我们必须使用`add_concurrent_foreign_key`和`add_concurrent_index`而不是`add_reference` . + +对于空表(例如新表),建议在单事务迁移中使用`add_reference` ,并将其与不需要`disable_ddl_transaction!`其他操作结合使用`disable_ddl_transaction!` . + +您可以阅读有关将[外键约束](database/add_foreign_key_to_existing_column.html)添加[到现有列的更多信息](database/add_foreign_key_to_existing_column.html) . + +## `NOT NULL` constraints[](#not-null-constraints "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38358) in GitLab 13.0. + +有关更多信息,请参见关于[`NOT NULL`约束](database/not_null_constraints.html)的样式指南. + +## Adding Columns With Default Values[](#adding-columns-with-default-values "Permalink") + +PostgreSQL 11 是自 GitLab 13.0 以来的最低版本,添加具有默认值的列变得更加容易,并且在所有情况下都应使用标准的`add_column`帮助器. + +在 PostgreSQL 11 之前,添加带有默认值的列是有问题的,因为这会导致全表重写. 相应的帮助程序`add_column_with_default`已被弃用,并将在以后的版本中删除. + +**注意:**如果%12.9 或更早版本需要向后端口添加具有默认值的列,则应使用`add_column_with_default`帮助器. 如果涉及[大表](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3) ,则禁止向后移植到%12.9. + +## Changing the column default[](#changing-the-column-default "Permalink") + +可能有人认为,使用`change_column_default`更改默认列对于较大的表来说是一项昂贵且破坏性的操作,但实际上并非如此. + +以以下迁移为例: + +``` +class DefaultRequestAccessGroups < ActiveRecord::Migration[5.2] + DOWNTIME = false + + def change + change_column_default(:namespaces, :request_access_enabled, from: false, to: true) + end +end +``` + +上面的迁移更改了我们最大的表之一的默认列值: `namespaces` . 可以将其翻译为: + +``` +ALTER TABLE namespaces +ALTER COLUMN request_access_enabled +DEFAULT false +``` + +在这种情况下,默认值存在,我们只是更改了`request_access_enabled`列的元数据,这并不意味着重写`namespaces`表中的所有现有记录. 仅当使用默认值创建新列时,所有记录才会被重写. + +**注意:** PostgresSQL 11.0 引入[了](https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/)更快的[ALTER TABLE ADD COLUMN(具有非空默认值](https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/) ),从而消除了在添加具有默认值的新列时重写表的需求. + +由于上述原因,在单事务迁移中使用`change_column_default`是安全的,而不需要`disable_ddl_transaction!` . + +## Updating an existing column[](#updating-an-existing-column "Permalink") + +要将现有列更新为特定值,可以使用`update_column_in_batches` . 这会将更新分为批次,因此我们不会在单个语句中更新太多行. + +这`some_column` `projects`表中的`foo`列更新为 10,其中`some_column`为`'hello'` : + +``` +update_column_in_batches(:projects, :foo, 10) do |table, query| + query.where(table[:some_column].eq('hello')) +end +``` + +如果需要计算的更新,则可以将值包装在`Arel.sql` ,因此 Arel 将其视为 SQL 文字. 这也是[Rails 6](https://gitlab.com/gitlab-org/gitlab/-/issues/28497)的必需弃用. + +下面的示例与上面的示例相同,但是该值设置为`bar`和`baz`列的乘积: + +``` +update_value = Arel.sql('bar * baz') + +update_column_in_batches(:projects, :foo, update_value) do |table, query| + query.where(table[:some_column].eq('hello')) +end +``` + +像`add_column_with_default`一样,有一个 RuboCop cop 可以检测大表上的用法. 在`update_column_in_batches`的情况下,可以在大表上运行,只要它仅更新表中行的一小部分,而在未在 GitLab.com 登台环境上进行验证的情况下不要忽略它-或事先请别人为您这样做. + +## Dropping a database table[](#dropping-a-database-table "Permalink") + +删除数据库表并不常见,Rails 提供的`drop_table`方法通常被认为是安全的. 删除表格之前,请考虑以下因素: + +如果您的表在高流量表上具有外键(如`projects` ),则`DROP TABLE`语句可能会失败,并出现**语句超时**错误. 确定哪些表是高流量可能很困难. 自我管理的实例可能会以不同的使用模式使用 GitLab 的不同功能,因此仅基于 GitLab.com 进行假设是不够的. + +表**没有记录** (功能从未使用过),也**没有外键** : + +* 只需在迁移中使用`drop_table`方法即可. + +``` +def change + drop_table :my_table +end +``` + +Table **有记录** but **没有外键**: + +* 第一版:删除与表相关的应用程序代码,例如模型,控制器和服务. +* 第二版:在迁移中使用`drop_table`方法. + +``` +def up + drop_table :my_table +end + +def down + # create_table ... +end +``` + +Table **有外键**: + +* 第一版:删除与表相关的应用程序代码,例如模型,控制器和服务. +* 第二版:使用`with_lock_retries`帮助器方法删除外键. 在另一个迁移文件中使用`drop_table` . + +**第二个版本的迁移:** + +删除`projects`表上的外键: + +``` +# first migration file + +def up + with_lock_retries do + remove_foreign_key :my_table, :projects + end +end + +def down + with_lock_retries do + add_foreign_key :my_table, :projects + end +end +``` + +放下桌子: + +``` +# second migration file + +def up + drop_table :my_table +end + +def down + # create_table ... +end +``` + +## Integer column type[](#integer-column-type "Permalink") + +默认情况下,整数列最多可容纳 4 个字节(32 位)的数字. 最大值为 2,147,483,647\. 创建一个以字节为单位保存文件大小的列时,请注意这一点. 如果以字节为单位跟踪文件大小,这会将最大文件大小限制为刚好超过 2GB. + +要允许整数列最多容纳 8 个字节(64 位)的数字,请将限制明确设置为 8 个字节. 这将使该列最多`9,223,372,036,854,775,807`个值. + +Rails 迁移示例: + +``` +add_column(:projects, :foo, :integer, default: 10, limit: 8) +``` + +## Strings and the Text data type[](#strings-and-the-text-data-type "Permalink") + +在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30453) . + +有关更多信息,请参见[文本数据类型](database/strings_and_the_text_data_type.html)样式指南. + +## Timestamp column type[](#timestamp-column-type "Permalink") + +默认情况下,Rails 使用`timestamp`数据类型来存储没有时区信息的时间戳数据. 通过调用`add_timestamps`或`timestamps`方法来使用`timestamp`数据类型. + +另外,Rails 将`:datetime`数据类型转换为`timestamp`一. + +Example: + +``` +# timestamps +create_table :users do |t| + t.timestamps +end + +# add_timestamps +def up + add_timestamps :users +end + +# :datetime +def up + add_column :users, :last_sign_in, :datetime +end +``` + +代替使用这些方法,应该使用以下方法来存储带有时区的时间戳: + +* `add_timestamps_with_timezone` +* `timestamps_with_timezone` +* `datetime_with_timezone` + +这样可以确保所有时间戳都有指定的时区. 反过来,这意味着当系统的时区更改时,现有时间戳不会突然使用其他时区. 这也使得非常清楚,首先使用了哪个时区. + +## Storing JSON in database[](#storing-json-in-database "Permalink") + +Rails 5 本机支持`JSONB` (二进制 JSON)列类型. 添加此列的示例迁移: + +``` +class AddOptionsToBuildMetadata < ActiveRecord::Migration[5.0] + DOWNTIME = false + + def change + add_column :ci_builds_metadata, :config_options, :jsonb + end +end +``` + +您必须使用序列化器来提供翻译层: + +``` +class BuildMetadata + serialize :config_options, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize +end +``` + +使用`JSONB`列时,请使用[JsonSchemaValidator](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/validators/json_schema_validator.rb)来控制随时间推移插入的数据. + +``` +class BuildMetadata + validates :config_options, json_schema: { filename: 'build_metadata_config_option' } +end +``` + +## Testing[](#testing "Permalink") + +请参阅" [测试 Rails 迁移](testing_guide/testing_migrations_guide.html)样式"指南. + +## Data migration[](#data-migration "Permalink") + +请比一般 ActiveRecord 语法更喜欢 Arel 和普通 SQL. 如果使用普通 SQL,则需要使用`quote_string` helper 手动引用所有输入. + +Arel 的示例: + +``` +users = Arel::Table.new(:users) +users.group(users[:user_id]).having(users[:id].count.gt(5)) + +#update other tables with these results +``` + +带有普通 SQL 和`quote_string`帮助器的示例: + +``` +select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(id) > 1").each do |tag| + tag_name = quote_string(tag["name"]) + duplicate_ids = select_all("SELECT id FROM tags WHERE name = '#{tag_name}'").map{|tag| tag["id"]} + origin_tag_id = duplicate_ids.first + duplicate_ids.delete origin_tag_id + + execute("UPDATE taggings SET tag_id = #{origin_tag_id} WHERE tag_id IN(#{duplicate_ids.join(",")})") + execute("DELETE FROM tags WHERE id IN(#{duplicate_ids.join(",")})") +end +``` + +如果需要更复杂的逻辑,则可以定义和使用迁移本地模型. 例如: + +``` +class MyMigration < ActiveRecord::Migration[6.0] + class Project < ActiveRecord::Base + self.table_name = 'projects' + end + + def up + # Reset the column information of all the models that update the database + # to ensure the Active Record's knowledge of the table structure is current + Project.reset_column_information + + # ... ... + end +end +``` + +这样做时,请确保显式设置模型的表名,这样它就不会派生自类名或名称空间. + +最后,对于所有更新数据库的本地模型,请确保在迁移的`up`方法中运行`reset_column_information` . + +这样做的原因是所有迁移类都在开始时加载( `db:migrate`启动时),因此,如果另一个迁移更新了该模式,它们将与它们映射的表模式不同步. 这将导致在尝试插入基础表或对其进行更新时数据迁移失败,因为`ActiveRecord`将新列报告为`unknown attribute` . + +### Renaming reserved paths[](#renaming-reserved-paths "Permalink") + +引入新的项目路线时,它可能与任何现有记录冲突. 这些记录的路径应重命名,并且相关数据应在磁盘上移动. + +由于我们已经必须做几次,因此现在有一些帮助程序可以帮助您. + +要使用此功能,您可以在迁移中包括`Gitlab::Database::RenameReservedPathsMigration::V1` . 这将提供 3 种方法,您可以通过一种或多种需要拒绝的路径. + +**`rename_root_paths`** :这将使用给定名称重命名所有没有`parent_id`名称*空间*的路径. + +**`rename_child_paths`** :这将使用给定名称重命名所有具有`parent_id`名称*空间*的路径. + +**`rename_wildcard_paths`** :这将重命名所有*项目*的路径以及所有具有`project_id` *命名空间* . + +这些行的`path`列将重命名为其先前的值,后跟一个整数. 例如: `users`将变成`users0` \ No newline at end of file diff --git a/docs/617.md b/docs/617.md new file mode 100644 index 0000000000000000000000000000000000000000..9410954bb21c0199c71c7aeff1d429252b46e68d --- /dev/null +++ b/docs/617.md @@ -0,0 +1,112 @@ +# Newlines style guide + +> 原文:[https://docs.gitlab.com/ee/development/newlines_styleguide.html](https://docs.gitlab.com/ee/development/newlines_styleguide.html) + +* [Rule: separate code with newlines only to group together related logic](#rule-separate-code-with-newlines-only-to-group-together-related-logic) +* [Rule: separate code and block with newlines](#rule-separate-code-and-block-with-newlines) + * [Newline before block](#newline-before-block) +* [Newline after block](#newline-after-block) + * [Exception: no need for newline when code block starts or ends right inside another code block](#exception-no-need-for-newline-when-code-block-starts-or-ends-right-inside-another-code-block) + +# Newlines style guide[](#newlines-style-guide "Permalink") + +该样式指南为 Ruby 代码中的换行符推荐了最佳做法. + +## Rule: separate code with newlines only to group together related logic[](#rule-separate-code-with-newlines-only-to-group-together-related-logic "Permalink") + +``` +# bad +def method + issue = Issue.new + + issue.save + + render json: issue +end +``` + +``` +# good +def method + issue = Issue.new + issue.save + + render json: issue +end +``` + +## Rule: separate code and block with newlines[](#rule-separate-code-and-block-with-newlines "Permalink") + +### Newline before block[](#newline-before-block "Permalink") + +``` +# bad +def method + issue = Issue.new + if issue.save + render json: issue + end +end +``` + +``` +# good +def method + issue = Issue.new + + if issue.save + render json: issue + end +end +``` + +## Newline after block[](#newline-after-block "Permalink") + +``` +# bad +def method + if issue.save + issue.send_email + end + render json: issue +end +``` + +``` +# good +def method + if issue.save + issue.send_email + end + + render json: issue +end +``` + +### Exception: no need for newline when code block starts or ends right inside another code block[](#exception-no-need-for-newline-when-code-block-starts-or-ends-right-inside-another-code-block "Permalink") + +``` +# bad +def method + + if issue + + if issue.valid? + issue.save + end + + end + +end +``` + +``` +# good +def method + if issue + if issue.valid? + issue.save + end + end +end +``` \ No newline at end of file diff --git a/docs/618.md b/docs/618.md new file mode 100644 index 0000000000000000000000000000000000000000..41162259b3186fa6f2ef172bc87b8ebcec67ddd1 --- /dev/null +++ b/docs/618.md @@ -0,0 +1,80 @@ +# Python Development Guidelines + +> 原文:[https://docs.gitlab.com/ee/development/python_guide/](https://docs.gitlab.com/ee/development/python_guide/) + +* [Installation](#installation) + * [macOS](#macos) + * [Linux](#linux) + * [Shell integration](#shell-integration) +* [Dependency management](#dependency-management) +* [Use instructions](#use-instructions) + +# Python Development Guidelines[](#python-development-guidelines "Permalink") + +GitLab requires Python as a dependency for [reStructuredText](https://docutils.sourceforge.io/rst.html) markup rendering. + +从 GitLab 11.10 开始,我们需要 Python 3. + +## Installation[](#installation "Permalink") + +有几种方法可以在系统上安装 Python. 为了能够使用生产中使用的相同版本,建议您使用[pyenv](https://github.com/pyenv/pyenv) . 它的工作方式和行为与 Ruby 世界中的[同类产品 rbenv 相似](https://github.com/rbenv/rbenv) . + +### macOS[](#macos "Permalink") + +要在 macOS 上安装`pyenv` ,可以将[Homebrew](https://brew.sh/)与以下软件配合使用: + +``` +brew install pyenv +``` + +### Linux[](#linux "Permalink") + +要在 Linux 上安装`pyenv` ,您可以运行以下命令: + +``` +curl https://pyenv.run | bash +``` + +另外,您可以通过发行版软件包管理器找到`pyenv`作为系统软件包. + +您可以在以下[网址](https://github.com/pyenv/pyenv-installer#prerequisites)了解更多信息: [https](https://github.com/pyenv/pyenv-installer#prerequisites) : [//github.com/pyenv/pyenv-installer#prerequisites](https://github.com/pyenv/pyenv-installer#prerequisites) . + +### Shell integration[](#shell-integration "Permalink") + +Pyenv 安装会将必需的更改添加到 Bash. 如果使用其他外壳,请检查是否需要其他步骤. + +对于 Fish,您可以为[Fisher](https://github.com/jorgebucaran/fisher)安装插件: + +``` +fisher add fisherman/pyenv +``` + +还是为了[我的鱼](https://github.com/oh-my-fish/oh-my-fish) : + +``` +omf install pyenv +``` + +## Dependency management[](#dependency-management "Permalink") + +尽管 GitLab 不直接包含任何 Python 脚本,但是由于我们依赖 Python 来呈现[reStructuredText](https://docutils.sourceforge.io/rst.html)标记,因此我们需要在主项目级别上跟踪依赖项,以便可以在开发机器上运行它. + +最近,Python 引入了与`Gemfile`和[Bundler](https://bundler.io/)项目等效的项目: `Pipfile`和[Pipenv](https://pipenv.readthedocs.io/en/latest/) . + +现在,您将在根文件夹中找到具有相关性的`Pipfile` . 要安装它们,请运行: + +``` +pipenv install +``` + +运行此命令将安装所需的 Python 版本以及所需的 pip 依赖项. + +## Use instructions[](#use-instructions "Permalink") + +要在 Pipenv 环境下运行任何 Python 代码,您需要首先根据应用程序的依赖关系启动`virtualenv` . 使用 Pipenv,运行起来很简单: + +``` +pipenv shell +``` + +运行该命令后,您可以在同一外壳上运行 GitLab,它将使用从`pipenv install`命令安装的 Python 和依赖项. \ No newline at end of file diff --git a/docs/619.md b/docs/619.md new file mode 100644 index 0000000000000000000000000000000000000000..ce8cd8a70b009bffb8e0f6dd03f15fa567642723 --- /dev/null +++ b/docs/619.md @@ -0,0 +1,285 @@ +# SCSS style guide + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/style/scss.html](https://docs.gitlab.com/ee/development/fe_guide/style/scss.html) + +* [Rules](#rules) + * [Utility Classes](#utility-classes) + * [Where are utility classes defined?](#where-are-utility-classes-defined) + * [Where should I put new utility classes?](#where-should-i-put-new-utility-classes) + * [When should I create component classes?](#when-should-i-create-component-classes) + * [Naming](#naming) + * [Formatting](#formatting) + * [Colors](#colors) + * [Indentation](#indentation) + * [Semicolons](#semicolons) + * [Shorthand](#shorthand) + * [Zero Units](#zero-units) + * [Selectors with a `js-` Prefix](#selectors-with-a-js--prefix) + * [IDs](#ids) + * [Variables](#variables) +* [Linting](#linting) + * [Fixing issues](#fixing-issues) + * [Ignoring issues](#ignoring-issues) + +# SCSS style guide[](#scss-style-guide "Permalink") + +本样式指南为 SCSS 推荐了最佳做法,以使样式易于阅读,易于维护并为最终用户提供高性能. + +## Rules[](#rules "Permalink") + +我们的 CSS 是现有方法和旧方法的结合. 这意味着有时可能难以按照本指南进行操作. 这意味着您肯定会遇到例外,在这种情况下,如果不付出巨大的努力,很难甚至不可能遵循该指南. 在这种情况下,您可以与审核者和维护者一起确定不符合这些规则的方法. 请努力限制这些情况. + +### Utility Classes[](#utility-classes "Permalink") + +为了减少随着站点的增加而产生更多 CSS 的可能性,与添加新 CSS 相比,更喜欢使用实用程序类. 在复杂的情况下,可以通过添加组件类来解决 CSS. + +#### Where are utility classes defined?[](#where-are-utility-classes-defined "Permalink") + +优先使用[在 GitLab UI 中定义](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/doc/css.md#utilities)的[实用程序类](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/doc/css.md#utilities) . [在 Unpkg 上](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss)也可以[看到](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss)一个简单的类列表. + +在类[`utilities.scss`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/stylesheets/utilities.scss)和[`common.scss`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/stylesheets/framework/common.scss)被弃用. 应该避免使用[`common.scss`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/stylesheets/framework/common.scss)中的非设计系统值的类,而采用一致的值. + +Avoid [Bootstrap’s Utility Classes](https://s0getbootstrap0com.icopy.site/docs/4.3/utilities/). + +#### Where should I put new utility classes?[](#where-should-i-put-new-utility-classes "Permalink") + +如果尚未将所需的类添加到 GitLab UI,则可以添加它! 请遵循[实用程序文件中](https://gitlab.com/gitlab-org/gitlab-ui/-/tree/master/src/scss/utility-mixins)记录的命名模式,并参阅[GitLab UI 的 CSS 文档](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/doc/contributing/adding_css.md#adding-utility-mixins)以获取更多详细信息,尤其是有关添加响应式和有状态规则的信息. + +如果它是不可能等待 GitLab UI 更新(通常一天),将该类添加到[`utilities.scss`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/stylesheets/utilities.scss)按照 GitLab UI 文件相同的命名约定. 应该解决将类反向移植到 GitLab UI 并将其从 GitLab 中删除的后续问题. + +#### When should I create component classes?[](#when-should-i-create-component-classes "Permalink") + +我们建议采用"效用至上"的方法. + +1. 从实用程序类开始. +2. 如果将实用程序类组合到组件类中可以消除代码重复并封装明确的职责,请执行此操作. + +这鼓励了组件类的有机增长,并防止创建一次性不可重用的类. 而且,从"效用优先"产生的类的种类倾向于以设计为中心(例如`.button` , `.alert` , `.card` )而不是以领域为中心(例如`.security-report-widget` , `.commit-header-icon` ). + +使用"效用优先"创建的组件类的示例包括: + +* [`.circle-icon-container`](https://gitlab.com/gitlab-org/gitlab/blob/579fa8b8ec7eb38d40c96521f517c9dab8c3b97a/app/assets/stylesheets/framework/icons.scss#L85) +* [`.d-flex-center`](https://gitlab.com/gitlab-org/gitlab/blob/900083d89cd6af391d26ab7922b3f64fa2839bef/app/assets/stylesheets/framework/common.scss#L425) + +Inspiration: + +* [https://tailwindcss.com/docs/utility-first/](https://tailwindcss.com/docs/utility-first/) +* [https://tailwindcss.com/docs/extracting-components/](https://tailwindcss.com/docs/extracting-components/) + +### Naming[](#naming "Permalink") + +文件名应使用`snake_case` . + +CSS 类应使用`lowercase-hyphenated`格式,而不是`snake_case`或`camelCase` . + +``` +// Bad +.class_name { + color: #fff; +} + +// Bad +.className { + color: #fff; +} + +// Good +.class-name { + color: #fff; +} +``` + +应该使用类名代替标记名选择器. 在 CSS 中不建议使用标记名称选择器,因为它们会影响层次结构中的意外元素. 另外,由于它们不是有意义的名称,因此不会在代码中添加含义. + +``` +// Bad +ul { + color: #fff; +} + +// Good +.class-name { + color: #fff; +} +``` + +### Formatting[](#formatting "Permalink") + +大括号前应始终使用空格,大括号应位于同一行上,每个属性都应具有自己的行,并且属性与其值之间应有一个空格. + +``` +// Bad +.container-item { + width: 100px; height: 100px; + margin-top: 0; +} + +// Bad +.container-item +{ + width: 100px; + height: 100px; + margin-top: 0; +} + +// Bad +.container-item{ + width:100px; + height:100px; + margin-top:0; +} + +// Good +.container-item { + width: 100px; + height: 100px; + margin-top: 0; +} +``` + +请注意,单行规则集是一个例外,尽管通常不建议使用这些规则集. + +``` +p { margin: 0; padding: 0; } +``` + +### Colors[](#colors "Permalink") + +十六进制(十六进制)颜色应尽可能使用简写形式,并应使用小写字母区分字母和数字,例如`#E3E3E3`与`#e3e3e3` . + +``` +// Bad +p { + color: #ffffff; +} + +// Bad +p { + color: #FFFFFF; +} + +// Good +p { + color: #fff; +} +``` + +### Indentation[](#indentation "Permalink") + +缩进应始终为每个缩进级别使用两个空格. + +``` +// Bad, four spaces +p { + color: #f00; +} + +// Good +p { + color: #f00; +} +``` + +### Semicolons[](#semicolons "Permalink") + +在每个属性后面都应始终包含分号. 缩小样式表后,分号将自动删除. + +``` +// Bad +.container-item { + width: 100px; + height: 100px +} + +// Good +.container-item { + width: 100px; + height: 100px; +} +``` + +### Shorthand[](#shorthand "Permalink") + +简写形式应用于支持它的属性. + +``` +// Bad +margin: 10px 15px 10px 15px; +padding: 10px 10px 10px 10px; + +// Good +margin: 10px 15px; +padding: 10px; +``` + +### Zero Units[](#zero-units "Permalink") + +省略长度单位为零的值,这是不必要的,不包括长度单位的性能更高. + +``` +// Bad +.item-with-padding { + padding: 0px; +} + +// Good +.item-with-padding { + padding: 0; +} +``` + +### Selectors with a `js-` Prefix[](#selectors-with-a-js--prefix "Permalink") + +不要将任何以`js-`选择器用于样式目的. 这些选择器仅可与 JavaScript 一起使用,以便在不破坏样式的情况下进行删除或重命名. + +### IDs[](#ids "Permalink") + +不要在 CSS 中使用 ID 选择器. + +``` +// Bad +#my-element { + padding: 0; +} + +// Good +.my-element { + padding: 0; +} +``` + +### Variables[](#variables "Permalink") + +在为颜色或尺寸添加新变量之前,请确保: + +* 还没有一个 +* 我们没有类似的替代方法. + +## Linting[](#linting "Permalink") + +我们使用[SCSS Lint](https://github.com/sds/scss-lint)检查样式指南的一致性. 它使用`.scss-lint.yml`的规则集,该规则集位于项目的主目录中. + +要检查您的更改是否会产生任何警告,您可以在 GitLab 目录中运行`rake scss_lint` . SCSS Lint 也将在 GitLab CI / CD 中运行以捕获任何警告. + +如果 Rake 任务发出了您不了解的警告,SCSS Lint 的文档将包含[其](https://github.com/sds/scss-lint/blob/master/lib/scss_lint/linter/README.md)短毛绒的[完整列表](https://github.com/sds/scss-lint/blob/master/lib/scss_lint/linter/README.md) . + +### Fixing issues[](#fixing-issues "Permalink") + +如果要自动更改大部分代码库以符合 SCSS 样式指南,则可以使用[CSSComb](https://github.com/csscomb/csscomb.js) . 首先安装[Node](https://github.com/nodejs/node)和[NPM](https://s0www0npmjs0com.icopy.site/) ,然后运行`npm install csscomb -g`全局(系统范围)安装 CSSComb. 使用`csscomb app/assets/stylesheets`在 GitLab 目录中运行它,以自动修复 CSS / SCSS 问题. + +请注意,这并不能解决所有问题,但应该可以解决大多数问题. + +### Ignoring issues[](#ignoring-issues "Permalink") + +如果您希望`// scss-lint:disable RuleName`忽略一条线或一组线,则可以使用`// scss-lint:disable RuleName` ( [更多信息](https://github.com/sds/scss-lint#disabling-linters-via-source) ): + +``` +// This lint rule is disabled because it is supported only in Chrome/Safari +// scss-lint:disable PropertySpelling +body { + text-decoration-skip: ink; +} +// scss-lint:enable PropertySpelling +``` + +确保在`disable`规则上方的行上添加了注释,否则短绒棉绒将抛出警告. 已启用`DisableLinterReason`以确保不忽略样式指南,并与其他人交流为什么在这种情况下忽略样式指南. \ No newline at end of file diff --git a/docs/620.md b/docs/620.md new file mode 100644 index 0000000000000000000000000000000000000000..52d76d2da10d0be516e4248f9c391e5de98c6430 --- /dev/null +++ b/docs/620.md @@ -0,0 +1,105 @@ +# Shell scripting standards and style guidelines + +> 原文:[https://docs.gitlab.com/ee/development/shell_scripting_guide/](https://docs.gitlab.com/ee/development/shell_scripting_guide/) + +* [Overview](#overview) + * [Avoid using shell scripts](#avoid-using-shell-scripts) +* [Scope of this guide](#scope-of-this-guide) +* [Shell language choice](#shell-language-choice) +* [Code style and format](#code-style-and-format) + * [Linting](#linting) + * [Formatting](#formatting) +* [Testing](#testing) +* [Code Review](#code-review) + +# Shell scripting standards and style guidelines[](#shell-scripting-standards-and-style-guidelines "Permalink") + +## Overview[](#overview "Permalink") + +GitLab 由许多不同的服务和子项目组成. 他们的大多数后端代码都是用[Ruby](https://www.ruby-lang.org)和[Go](https://s0golang0org.icopy.site)编写的. 但是,其中一些使用 shell 脚本来自动化日常系统管理任务,例如部署,安装等.之所以这样做是出于历史原因,或者是为了最大程度地减少对 Docker 映像的依赖性. + +该页面旨在根据我们的各种经验来定义和组织我们的 Shell 脚本编写准则. GitLab 项目中的所有 Shell 脚本最终都应与本指南保持一致. 如果每个项目与本指南存在差异,则应在此类项目的`README.md`或`PROCESS.md`文件中进行说明. + +### Avoid using shell scripts[](#avoid-using-shell-scripts "Permalink") + +**注意:**这是必读部分. + +综上所述,我们建议尽可能远离 Shell 脚本. 像 Ruby 或 Python 这样的语言(如果需要与我们利用的代码库保持一致),几乎总是一个更好的选择. 高级解释语言具有更易读的语法,为单元测试,整理和错误报告提供了更成熟的功能. + +仅在对项目的依赖项大小有严格限制或在特定情况下更重要的任何其他要求时,才使用 Shell 脚本. + +## Scope of this guide[](#scope-of-this-guide "Permalink") + +根据[GitLab 安装要求](../../install/requirements.html) ,本指南仅涵盖受[支持的 Linux 发行版](../../install/requirements.html#supported-linux-distributions)使用的那些 shell,即: + +* [POSIX Shell](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html) +* [Bash](https://www.gnu.org/software/bash/) + +## Shell language choice[](#shell-language-choice "Permalink") + +* 当您需要减少依赖关系列表时,请使用环境提供的内容. 例如,对于泊坞图片是`sh`从`alpine`这是基本的图像对于大多数我们的工具的图像. +* 如果可能,请在其他任何地方使用`bash` . 它比`sh`更强大,但仍然是广泛使用的 shell. + +## Code style and format[](#code-style-and-format "Permalink") + +本节描述了包含外壳程序脚本的工具,这些工具应成为项目 CI 管道的必需部分. 这些工具可自动执行 Shell 代码格式化,检查错误或漏洞等. + +### Linting[](#linting "Permalink") + +我们在默认配置中使用[ShellCheck](https://www.shellcheck.net/)实用程序来[整理](https://www.shellcheck.net/)我们的 Shell 脚本. + +所有带有 shell 脚本的项目都应使用此 GitLab CI / CD 作业: + +``` +shell check: + image: koalaman/shellcheck-alpine:stable + stage: test + before_script: + - shellcheck --version + script: + - shellcheck scripts/**/*.sh # path to your shell scripts +``` + +**提示:**默认情况下,ShellCheck 将使用[外壳检测](https://github.com/koalaman/shellcheck/wiki/SC2148#rationale)来确定使用中的外壳方言. 如果 shell 文件不在您的控制范围内,并且 ShellCheck 无法检测到方言,请使用`-s`标志指定它: `-s sh`或`-s bash` . + +### Formatting[](#formatting "Permalink") + +建议使用[shfmt](https://github.com/mvdan/sh#shfmt)工具来保持一致的格式. 我们根据《 [Google Shell 样式指南》设置](https://google.github.io/styleguide/shell.xml)外壳脚本的格式,因此以下`shfmt`调用应应用于项目的脚本文件: + +``` +shfmt -i 2 -ci -w scripts/**/*.sh +``` + +除了[Linting](#linting) GitLab CI / CD 作业外,所有带有 shell 脚本的项目也应使用此作业: + +``` +shfmt: + image: mvdan/shfmt:v3.1.0-alpine + stage: test + before_script: + - shfmt -version + script: + - shfmt -i 2 -ci -d scripts # path to your shell scripts +``` + +**提示:**默认情况下,shfmt 将使用类似于 ShellCheck 之一的[shell 检测](https://github.com/mvdan/sh#shfmt) ,并忽略以句点开头的文件. 要覆盖它,请使用`-ln`标志来指定 shell 方言: `-ln posix`或`-ln bash` . + +## Testing[](#testing "Permalink") + +**注意:**这是一项正在进行的工作. + +评估各种工具以自动测试 Shell 脚本(例如[BATS](https://github.com/bats-core/bats-core) )是一项[持续的工作](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64016) . + +## Code Review[](#code-review "Permalink") + +代码审查应根据以下条件执行: + +* [ShellCheck Checks list](https://github.com/koalaman/shellcheck/wiki/Checks) +* [Google Shell Style Guide](https://google.github.io/styleguide/shell.xml) +* [Shfmt formatting caveats](https://github.com/mvdan/sh#caveats) + +但是,建议采取的措施是使用上述工具并处理报告的违法行为. 这应该消除对代码审查的需要. + +* * * + +[Return to Development documentation](../README.html). \ No newline at end of file diff --git a/docs/621.md b/docs/621.md new file mode 100644 index 0000000000000000000000000000000000000000..f77b9e9c4bec190f0cdbe7756cfa8d45be8c7155 --- /dev/null +++ b/docs/621.md @@ -0,0 +1,11 @@ +# Sidekiq debugging + +> 原文:[https://docs.gitlab.com/ee/development/sidekiq_debugging.html](https://docs.gitlab.com/ee/development/sidekiq_debugging.html) + +* [Log arguments to Sidekiq jobs](#log-arguments-to-sidekiq-jobs) + +# Sidekiq debugging[](#sidekiq-debugging "Permalink") + +## Log arguments to Sidekiq jobs[](#log-arguments-to-sidekiq-jobs "Permalink") + +此内容已移至[故障排除 Sidekiq 文档](../administration/troubleshooting/sidekiq.html) . \ No newline at end of file diff --git a/docs/622.md b/docs/622.md new file mode 100644 index 0000000000000000000000000000000000000000..05db0d7e7b118bb9db4271d62d022a870e867d48 --- /dev/null +++ b/docs/622.md @@ -0,0 +1,509 @@ +# Sidekiq Style Guide + +> 原文:[https://docs.gitlab.com/ee/development/sidekiq_style_guide.html](https://docs.gitlab.com/ee/development/sidekiq_style_guide.html) + +* [ApplicationWorker](#applicationworker) +* [Dedicated Queues](#dedicated-queues) +* [Queue Namespaces](#queue-namespaces) +* [Idempotent Jobs](#idempotent-jobs) + * [Ensuring a worker is idempotent](#ensuring-a-worker-is-idempotent) + * [Declaring a worker as idempotent](#declaring-a-worker-as-idempotent) + * [Deduplication](#deduplication) +* [Job urgency](#job-urgency) + * [Latency sensitive jobs](#latency-sensitive-jobs) + * [Changing a queue’s urgency](#changing-a-queues-urgency) +* [Jobs with External Dependencies](#jobs-with-external-dependencies) +* [CPU-bound and Memory-bound Workers](#cpu-bound-and-memory-bound-workers) +* [Declaring a Job as CPU-bound](#declaring-a-job-as-cpu-bound) +* [Determining whether a worker is CPU-bound](#determining-whether-a-worker-is-cpu-bound) +* [Feature category](#feature-category) +* [Job weights](#job-weights) +* [Worker context](#worker-context) + * [Cron workers](#cron-workers) + * [Jobs scheduled in bulk](#jobs-scheduled-in-bulk) +* [Arguments logging](#arguments-logging) +* [Tests](#tests) +* [Sidekiq Compatibility across Updates](#sidekiq-compatibility-across-updates) + * [Changing the arguments for a worker](#changing-the-arguments-for-a-worker) + * [Remove an argument](#remove-an-argument) + * [Add an argument](#add-an-argument) + * [Multi-step deployment](#multi-step-deployment) + * [Parameter hash](#parameter-hash) + * [Removing workers](#removing-workers) + * [Renaming queues](#renaming-queues) + +# Sidekiq Style Guide[](#sidekiq-style-guide "Permalink") + +本文档概述了添加或修改 Sidekiq 工作程序时应遵循的各种准则. + +## ApplicationWorker[](#applicationworker "Permalink") + +All workers should include `ApplicationWorker` instead of `Sidekiq::Worker`, which adds some convenience methods and automatically sets the queue based on the worker’s name. + +## Dedicated Queues[](#dedicated-queues "Permalink") + +所有工作程序都应使用自己的队列,该队列将根据工作程序类名称自动设置. 对于名为`ProcessSomethingWorker`的工作程序,队列名称将为`process_something` . 如果不确定工人使用什么队列,可以使用`SomeWorker.queue`找到它. 几乎没有理由使用`sidekiq_options queue: :some_queue`手动覆盖队列名称. + +添加新队列后,运行`bin/rake gitlab:sidekiq:all_queues_yml:generate`来重新生成`app/workers/all_queues.yml`或`ee/app/workers/all_queues.yml`以便可以由[`sidekiq-cluster`](../administration/operations/extra_sidekiq_processes.html)拾取. + +## Queue Namespaces[](#queue-namespaces "Permalink") + +虽然不同的工作人员无法共享队列,但是他们可以共享队列名称空间. + +为工作程序定义队列名称空间可以启动 Sidekiq 进程,该进程自动为该工作空间中的所有工作程序处理作业,而无需显式列出其所有队列名称. 例如,如果由`sidekiq-cron`管理的所有工作人员都使用`cronjob`队列名称空间,那么我们可以专门针对此类计划的作业启动 Sidekiq 进程. 如果稍后添加使用`cronjob`命名空间的新工作程序,则 Sidekiq 进程也将自动为该工作程序选择作业(重新启动后),而无需更改任何配置. + +可以使用`queue_namespace` DSL 类方法设置队列名称空间: + +``` +class SomeScheduledTaskWorker + include ApplicationWorker + + queue_namespace :cronjob + + # ... +end +``` + +在后台,这会将`SomeScheduledTaskWorker.queue`设置为`cronjob:some_scheduled_task` . 常用的名称空间将具有自己的关注模块,可以轻松地将其包含在 worker 类中,并且可以设置队列名称空间以外的其他 Sidekiq 选项. 例如, `CronjobQueue`设置名称空间,但也禁用重试. + +`bundle exec sidekiq`是可感知名称空间的,当提供名称空间而不是`--queue` ( `-q` )选项中的简单队列名称时,它将自动侦听名称空间中的所有队列(技术上:所有以名称空间名称为前缀的队列) ,或`config/sidekiq_queues.yml`中的`:queues:`部分. + +请注意,应谨慎执行将工作程序添加到现有命名空间的操作,因为如果没有适当调整可用于处理命名空间的 Sidekiq 进程可用的资源,则额外的作业将占用已经存在的工作程序的资源. + +## Idempotent Jobs[](#idempotent-jobs "Permalink") + +众所周知,一项作业可能由于多种原因而失败. 例如,网络中断或错误. 为了解决此问题,Sidekiq 具有内置的重试机制,GitLab 中的大多数工作人员默认使用该机制. + +期望作业在失败后可以再次运行,而不会给应用程序或用户带来重大副作用,这就是 Sidekiq 鼓励作业具有[幂等性和事务性的原因](https://github.com/mperham/sidekiq/wiki/Best-Practices#2-make-your-job-idempotent-and-transactional) . + +通常,在以下情况下,可以将工人视为等幂的: + +* 它可以使用相同的参数安全地运行多次. +* 预期应用程序副作用仅发生一次(或第二次运行的副作用无效). + +一个很好的例子是缓存过期工作器. + +**注意:**如果队列中已经存在具有相同参数的未启动作业,则为等幂工作器调度的作业将自动进行[重复数据删除](#deduplication) . + +### Ensuring a worker is idempotent[](#ensuring-a-worker-is-idempotent "Permalink") + +确保使用以下共享示例通过工作程序测试: + +``` +include_examples 'an idempotent worker' do + it 'marks the MR as merged' do + # Using subject inside this block will process the job multiple times + subject + + expect(merge_request.state).to eq('merged') + end +end +``` + +直接使用`perform_multiple`方法而不是`job.perform` (此辅助方法将自动包含在 worker 中). + +### Declaring a worker as idempotent[](#declaring-a-worker-as-idempotent "Permalink") + +``` +class IdempotentWorker + include ApplicationWorker + + # Declares a worker is idempotent and can + # safely run multiple times. + idempotent! + + # ... +end +``` + +鼓励只具有`idempotent!` 即使在另一个类或模块中定义了`perform`方法,也要在最顶层的 worker 类中调用. + +**注意:**如果工人阶级没有被标记为幂等,那么警察将失败. 如果您不确定自己的工作可以安全地多次运行,请考虑跳过警察. + +### Deduplication[](#deduplication "Permalink") + +当队列中有另一个幂函数的作业入队而另一个未启动的作业时,GitLab 会删除第二个作业. 之所以跳过该工作,是因为首先安排的工作将完成相同的工作; 到第二个作业执行时,第一个作业什么也做不了. + +例如, `AuthorizedProjectsWorker`需要一个用户 ID. 当工作程序运行时,它将重新计算用户的授权. 每当操作有可能更改用户的授权时,GitLab 都会计划此作业. 如果将同一用户同时添加到两个项目,则如果第一个作业尚未开始,则可以跳过第二个作业,因为当第一个作业运行时,它将为两个项目创建授权. + +GitLab 不会跳过将来计划的作业,因为我们假设在计划执行作业时状态将已更改. + +[已经提出了](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/195)更多的[重复数据删除策略](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/195) . 如果您正在部署的员工可能会从其他策略中受益,请在问题中发表评论. + +如果自动重复数据删除会导致某些队列出现问题. 可以通过启用名为`disable_<queue name>_deduplication`的功能标志来暂时禁用此功能. 例如,要禁用`AuthorizedProjectsWorker`重复数据删除,我们将启用功能标记`disable_authorized_projects_deduplication` . + +从 ChatOps: + +``` +/chatops run feature set disable_authorized_projects_deduplication true +``` + +从 rails 控制台: + +``` +Feature.enable!(:disable_authorized_projects_deduplication) +``` + +## Job urgency[](#job-urgency "Permalink") + +作业可以设置一个`urgency`属性,可以是`:high` , `:low`或`:throttled` . 这些目标如下: + +| **Urgency** | **队列调度目标** | **执行延迟要求** | +| --- | --- | --- | +| `:high` | 10 秒 | 1 秒的 p50、10 秒的 p99 | +| `:low` | 1 分钟 | 最长运行时间为 5 分钟 | +| `:throttled` | None | 最长运行时间为 5 分钟 | + +要设置作业的紧急程度,请使用`urgency`类方法: + +``` +class HighUrgencyWorker + include ApplicationWorker + + urgency :high + + # ... +end +``` + +### Latency sensitive jobs[](#latency-sensitive-jobs "Permalink") + +如果立即安排大量后台作业,则在作业等待辅助节点可用时,可能会出现作业排队. 这是正常现象,它可以通过系统地处理流量高峰来赋予系统弹性. 但是,某些作业比其他作业对延迟更敏感. 这些工作的示例包括: + +1. 在推送到分支之后更新合并请求的作业. +2. 在推送到分支之后,该任务会使项目的已知分支的缓存无效. +3. 更改权限后,用户可以看到重新计算组和项目的作业. +4. 在状态更改为管道中的作业之后更新 CI 管道状态的作业. + +当这些作业被延迟时,用户可能会将延迟视为错误:例如,他们可以推送分支,然后尝试为该分支创建合并请求,但在 UI 中被告知该分支不存在. 我们认为这些工作很`urgency :high` + +做出额外的努力以确保这些作业在计划后的很短时间内启动. 但是,为了确保吞吐量,这些作业还具有非常严格的执行持续时间要求: + +1. 中位作业执行时间应少于 1 秒. +2. 99%的工作应在 10 秒内完成. + +如果一个工作人员不能满足这些期望,那么就不能将其视为`urgency :high`工作人员:考虑重新设计该工作人员,或在两个不同的工作人员之间拆分工作,其中一个工作`urgency :high`执行快速的`urgency :high`代码,另一个工作`urgency :low` ,它没有执行延迟要求(但也有较低的调度目标). + +### Changing a queue’s urgency[](#changing-a-queues-urgency "Permalink") + +在 GitLab.com,我们几个跑 Sidekiq [碎片](https://dashboards.gitlab.net/d/sidekiq-shard-detail/sidekiq-shard-detail) ,其中每一个代表一个特定类型的工作负载. + +更改队列的紧急性或添加新队列时,我们需要考虑新分片上的预期工作量. 请注意,如果我们要更改现有队列,那么也会对旧分片产生影响,但这始终会减少工作量. + +为此,我们要计算新分片的总执行时间和 RPS(吞吐量)的预期增长. 我们可以从以下获得这些值: + +* " [队列详细信息"仪表板](https://dashboards.gitlab.net/d/sidekiq-queue-detail/sidekiq-queue-detail)具有队列本身的值. 对于新队列,我们​​可以查找具有类似模式或在类似情况下安排的队列. +* [碎片详细信息仪表板](https://dashboards.gitlab.net/d/sidekiq-shard-detail/sidekiq-shard-detail)具有总执行时间和吞吐量(RPS). "分片利用率"面板将显示该分片当前是否有多余的容量. + +然后,我们可以计算我们要更改的队列的 RPS *平均运行时间(针对新作业的估算值),以查看新分片期望的 RPS 和执行时间的相对增加: + +``` +new_queue_consumption = queue_rps * queue_duration_avg +shard_consumption = shard_rps * shard_duration_avg + +(new_queue_consumption / shard_consumption) * 100 +``` + +如果我们预期增加**幅度小于 5%** ,则无需采取进一步措施. + +否则,请对合并请求 ping `@gitlab-org/scalability`并要求进行审查. + +## Jobs with External Dependencies[](#jobs-with-external-dependencies "Permalink") + +GitLab 应用程序中的大多数后台作业都与其他 GitLab 服务进行通信. 例如,PostgreSQL,Redis,Gitaly 和对象存储. 这些被视为作业的"内部"依赖性. + +但是,某些作业将依赖于外部服务才能成功完成. 一些示例包括: + +1. 调用用户配置的 Web 钩子的作业. +2. 将应用程序部署到用户配置的 k8s 集群的作业. + +这些作业具有"外部依赖性". 这对于后台处理群集的运行有多种重要的作用: + +1. 大多数外部依赖项(例如 Web 钩子)都不提供 SLO,因此我们不能保证这些作业的执行延迟. 由于我们无法保证执行延迟,因此无法确保吞吐量,因此,在高流量环境中,我们需要确保将具有外部依赖关系的作业与高紧急性作业分开,以确保这些队列上的吞吐量. +2. Errors in jobs with external dependencies have higher alerting thresholds as there is a likelihood that the cause of the error is external. + +``` +class ExternalDependencyWorker + include ApplicationWorker + + # Declares that this worker depends on + # third-party, external services in order + # to complete successfully + worker_has_external_dependencies! + + # ... +end +``` + +**注意:**请注意,一项工作既不能具有很高的紧迫性,又不能具有外部依赖性. + +## CPU-bound and Memory-bound Workers[](#cpu-bound-and-memory-bound-workers "Permalink") + +受 CPU 或内存资源限制约束的工作程序应使用`worker_resource_boundary`方法进行注释. + +大多数工作人员倾向于将大部分时间都花在阻止时间上,等待来自 Redis,PostgreSQL 和 Gitaly 等其他服务的网络响应. 由于 Sidekiq 是多线程环境,因此可以高并发地调度这些作业. + +但是,有些工人在 Ruby 中花费大量时间*在 CPU*运行逻辑上. Ruby MRI 不支持真正的多线程-它依赖[GIL](https://thoughtbot.com/blog/untangling-ruby-threads#the-global-interpreter-lock)来极大简化应用程序开发,无论托管该进程的计算机有多少核,一次仅允许一个进程中的一部分 Ruby 代码运行一次. 对于受 IO 约束的工作人员,这不是问题,因为大多数线程在基础库(位于 GIL 之外)中被阻止. + +如果许多线程试图同时运行 Ruby 代码,则将导致 GIL 争用,这将减慢所有进程的速度. + +在高流量的环境中,知道一个工作人员受 CPU 限制,可以使我们在具有较低并发性的其他队列中运行它. 这样可以确保最佳性能. + +同样,如果工作人员使用大量内存,则可以在定制的低并发,高内存队列上运行这些内存. + +请注意,受内存限制的工作程序会创建大量的 GC 工作负载,暂停时间为 10-50ms. 这将对工作人员的延迟要求产生影响. 因此, `memory`限制, `urgency :high`作业是不允许的,并且将使 CI 失败. 通常,不鼓励受`memory`限制的工作人员,应考虑处理工作的替代方法. + +如果工作程序需要大量的内存和 CPU 时间,则由于上述对高紧急性的内存绑定工作程序的限制,应将其标记为内存绑定. + +## Declaring a Job as CPU-bound[](#declaring-a-job-as-cpu-bound "Permalink") + +本示例说明如何将作业声明为受 CPU 约束. + +``` +class CPUIntensiveWorker + include ApplicationWorker + + # Declares that this worker will perform a lot of + # calculations on-CPU. + worker_resource_boundary :cpu + + # ... +end +``` + +## Determining whether a worker is CPU-bound[](#determining-whether-a-worker-is-cpu-bound "Permalink") + +我们使用以下方法来确定工作程序是否受 CPU 限制: + +* 在 Sidekiq 结构化 JSON 日志中,汇总工作`duration`和`cpu_s`字段. +* `duration` refers to the total job execution duration, in seconds +* `cpu_s`是从[`Process::CLOCK_THREAD_CPUTIME_ID`](https://www.rubydoc.info/stdlib/core/Process:clock_gettime)计数器派生的,它是作业在 CPU 上花费的时间的度量. +* 将`cpu_s`除以`duration`即可得到在 CPU 上花费的`duration`百分比. +* 如果该比例超过 33%,则认为该工作线程受 CPU 限制,因此应进行注释. +* 请注意,这些值不应用于较小的样本量,而应用于相当大的汇总. + +## Feature category[](#feature-category "Permalink") + +所有 Sidekiq 工作人员都必须定义一个已知的[特征类别](feature_categorization/index.html#sidekiq-workers) . + +## Job weights[](#job-weights "Permalink") + +某些作业的重量已声明. 仅在默认执行模式下运行 Sidekiq 时才使用此选项-使用[`sidekiq-cluster`](../administration/operations/extra_sidekiq_processes.html)不能计算权重. + +随着我们[朝在 Core 中使用`sidekiq-cluster`迈进](https://gitlab.com/gitlab-org/gitlab/-/issues/34396) ,新增加的工作人员无需指定权重. 他们可以简单地使用默认权重 1. + +## Worker context[](#worker-context "Permalink") + +版本历史 + +* 在 GitLab 12.8 中[引入](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/9) . + +为了在日志中获得有关工作程序的更多信息,我们[以`ApplicationContext`的形式向工作](logging.html#logging-context-metadata-through-rails-or-grape-requests)添加[元数据](logging.html#logging-context-metadata-through-rails-or-grape-requests) . 在大多数情况下,从请求计划作业时,该上下文已经从请求中扣除并添加到计划的作业中. + +运行作业时,将还原计划时处于活动状态的上下文. 这会使上下文传播到正在运行的作业中计划的任何作业. + +所有这些意味着在大多数情况下,要将上下文添加到作业中,我们无需执行任何操作. + +但是,在某些情况下,计划作业时将不存在任何上下文,或者存在的上下文很可能不正确. 对于这些实例,我们添加了 Rubocop 规则以引起注意并避免日志中的元数据不正确. + +与大多数警察一样,有完全正当的理由禁用它们. 在这种情况下,可能来自请求的上下文是正确的. 或者,您可能已经以警察无法接受的方式指定了上下文. 无论如何,请在禁用警察时留下指向将使用哪个上下文的代码注释. + +当确实为上下文提供对象时,请确保已预先加载名称空间和项目的路由. 这可以通过使用来完成`.with_route`上所有定义范围`Routable`秒. + +### Cron workers[](#cron-workers "Permalink") + +对于 Cronjob 队列( `include CronjobQueue` )中的工作人员,将自动清除上下文,即使从请求中安排工作人员时也是如此. 我们这样做是为了避免从 cron worker 安排其他作业时出现不正确的元数据. + +Cron 工作人员自己在实例范围内运行,因此它们的作用域不限于应添加到上下文中的用户,名称空间,项目或其他资源. + +然而,他们往往安排*确实*需要方面的其他工作. + +这就是为什么需要在工作人员中某处显示上下文的原因. 可以通过在工作器内的某些位置使用以下方法之一来完成此操作: + +1. 在`with_context`帮助器中包装用于调度作业的代码: + + ``` + def perform + deletion_cutoff = Gitlab::CurrentSettings + .deletion_adjourned_period.days.ago.to_date + projects = Project.with_route.with_namespace + .aimed_for_deletion(deletion_cutoff) + + projects.find_each(batch_size: 100).with_index do |project, index| + delay = index * INTERVAL + + with_context(project: project) do + AdjournedProjectDeletionWorker.perform_in(delay, project.id) + end + end + end + ``` + +2. 使用提供上下文的批处理调度方法: + + ``` + def schedule_projects_in_batch(projects) + ProjectImportScheduleWorker.bulk_perform_async_with_contexts( + projects, + arguments_proc: -> (project) { project.id }, + context_proc: -> (project) { { project: project } } + ) + end + ``` + + 或者,在延迟调度时: + + ``` + diffs.each_batch(of: BATCH_SIZE) do |diffs, index| + DeleteDiffFilesWorker + .bulk_perform_in_with_contexts(index * 5.minutes, + diffs, + arguments_proc: -> (diff) { diff.id }, + context_proc: -> (diff) { { project: diff.merge_request.target_project } }) + end + ``` + +### Jobs scheduled in bulk[](#jobs-scheduled-in-bulk "Permalink") + +通常,在批量调度作业时,这些作业应具有单独的上下文而不是总体上下文. + +如果是这样的话, `bulk_perform_async`可以通过更换`bulk_perform_async_with_context`帮手,而不是`bulk_perform_in`使用`bulk_perform_in_with_context` . + +例如: + +``` + ProjectImportScheduleWorker.bulk_perform_async_with_contexts( + projects, + arguments_proc: -> (project) { project.id }, + context_proc: -> (project) { { project: project } } + ) +``` + +第一个参数中可枚举的每个对象分为两个块: + +* `arguments_proc` ,它需要返回作业需要调度的参数列表. + +* 需要返回带有作业上下文信息的哈希值的`context_proc` . + +## Arguments logging[](#arguments-logging "Permalink") + +当[`SIDEKIQ_LOG_ARGUMENTS`](../administration/troubleshooting/sidekiq.html#log-arguments-to-sidekiq-jobs)启用,Sidekiq 作业参数将被记录. + +默认情况下,记录的唯一参数是数字参数,因为其他类型的参数可能包含敏感信息. 要覆盖此参数,请在工作程序内部使用`loggable_arguments`并记录要记录的参数的索引. (此处不需要指定数字参数.) + +例如: + +``` +class MyWorker + include ApplicationWorker + + loggable_arguments 1, 3 + + # object_id will be logged as it's numeric + # string_a will be logged due to the loggable_arguments call + # string_b will be filtered from logs + # string_c will be logged due to the loggable_arguments call + def perform(object_id, string_a, string_b, string_c) + end +end +``` + +## Tests[](#tests "Permalink") + +与其他任何类一样,每个 Sidekiq 工作者都必须使用 RSpec 进行测试. 这些测试应放在`spec/workers` . + +## Sidekiq Compatibility across Updates[](#sidekiq-compatibility-across-updates "Permalink") + +请记住,Sidekiq 作业的参数在计划执行时存储在队列中. 在线更新期间,这可能会导致几种可能的情况: + +1. 该应用程序的较旧版本发布作业,该作业由升级的 Sidekiq 节点执行. +2. 作业在升级之前排队,但在升级之后执行. +3. 作业由运行较新版本应用程序的节点排队,但在运行较旧版本应用程序的节点上执行. + +### Changing the arguments for a worker[](#changing-the-arguments-for-a-worker "Permalink") + +作业需要在应用程序的连续版本之间向后和向前兼容. 在所有 Rails 和 Sidekiq 节点都具有更新的代码之前,添加或删除参数可能会在部署期间引起问题. + +#### Remove an argument[](#remove-an-argument "Permalink") + +**不要从`perform`函数中删除参数.** . 而是,使用以下方法: + +1. 提供默认值(通常为`nil` )并使用注释将参数标记为已弃用 +2. 停止在`perform_async`使用该参数. +3. 忽略 worker 类中的值,但是直到下一个主要版本才将其删除. + +在以下示例中,如果要删除`arg2` ,请首先设置`nil`默认值,然后更新调用`ExampleWorker.perform_async`位置. + +``` +class ExampleWorker + def perform(object_id, arg1, arg2 = nil) + # ... + end +end +``` + +#### Add an argument[](#add-an-argument "Permalink") + +有两种方法可以安全地向 Sidekiq 工作者添加新参数: + +1. Set up a [multi-step deployment](#multi-step-deployment) in which the new argument is first added to the worker +2. 将[参数哈希](#parameter-hash)用于其他参数. 这也许是最灵活的选择. + +##### Multi-step deployment[](#multi-step-deployment "Permalink") + +这种方法需要多个合并请求,并且在合并其他更改之前,要合并和部署第一个合并请求. + +1. 在初始合并请求中,使用默认值将参数添加到 worker 中: + + ``` + class ExampleWorker + def perform(object_id, new_arg = nil) + # ... + end + end + ``` + +2. 使用新参数合并和部署工作程序. +3. 在另一个合并请求中,更新`ExampleWorker.perform_async`调用以使用新参数. + +##### Parameter hash[](#parameter-hash "Permalink") + +如果现有工作人员已经利用参数哈希,则此方法将不需要多次部署. + +1. 在 worker 中使用参数散列以实现将来的灵活性: + + ``` + class ExampleWorker + def perform(object_id, params = {}) + # ... + end + end + ``` + +### Removing workers[](#removing-workers "Permalink") + +尽量避免在次要版本和修补程序版本中删除工作人员及其队列. + +在联机更新期间,实例可能有待处理的作业,而删除队列可能导致这些作业永远卡住. 如果您无法为这些 Sidekiq 作业编写迁移,请考虑仅在主要版本中删除该工作程序. + +### Renaming queues[](#renaming-queues "Permalink") + +出于同样的原因,遣散工人也很危险,因此在重命名队列时应格外小心. + +重命名队列时,请使用`sidekiq_queue_migrate`帮助程序迁移方法,如本示例所示: + +``` +class MigrateTheRenamedSidekiqQueue < ActiveRecord::Migration[5.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + sidekiq_queue_migrate 'old_queue_name', to: 'new_queue_name' + end + + def down + sidekiq_queue_migrate 'new_queue_name', to: 'old_queue_name' + end +end +``` \ No newline at end of file diff --git a/docs/623.md b/docs/623.md new file mode 100644 index 0000000000000000000000000000000000000000..d44367c4a82ef7d0c2d421048501fe7628c2e5f4 --- /dev/null +++ b/docs/623.md @@ -0,0 +1,317 @@ +# SQL Query Guidelines + +> 原文:[https://docs.gitlab.com/ee/development/sql.html](https://docs.gitlab.com/ee/development/sql.html) + +* [Using LIKE Statements](#using-like-statements) +* [LIKE & Indexes](#like--indexes) +* [Reliably referencing database columns](#reliably-referencing-database-columns) + * [Good (prefer)](#good-prefer) + * [Bad (avoid)](#bad-avoid) +* [Plucking IDs](#plucking-ids) +* [Inherit from ApplicationRecord](#inherit-from-applicationrecord) +* [Use UNIONs](#use-unions) +* [Ordering by Creation Date](#ordering-by-creation-date) +* [Use WHERE EXISTS instead of WHERE IN](#use-where-exists-instead-of-where-in) +* [`.find_or_create_by` is not atomic](#find_or_create_by-is-not-atomic) + +# SQL Query Guidelines[](#sql-query-guidelines "Permalink") + +本文档介绍了使用 ActiveRecord / Arel 或原始 SQL 查询编写 SQL 查询时要遵循的各种准则. + +## Using LIKE Statements[](#using-like-statements "Permalink") + +搜索数据的最常见方法是使用`LIKE`语句. 例如,要获取标题以" WIP:"开头的所有问题,您可以编写以下查询: + +``` +SELECT * +FROM issues +WHERE title LIKE 'WIP:%'; +``` + +在 PostgreSQL 上, `LIKE`语句区分大小写. 要执行不区分大小写的`LIKE` ,必须改为使用`ILIKE` . + +要自动处理此问题,您应该使用 Arel 而不是原始 SQL 片段使用`LIKE`查询,因为 Arel 在 PostgreSQL 上自动使用`ILIKE` . + +``` +Issue.where('title LIKE ?', 'WIP:%') +``` + +您可以这样写: + +``` +Issue.where(Issue.arel_table[:title].matches('WIP:%')) +``` + +根据所使用的数据库,此处的`matches`生成正确的`LIKE` / `ILIKE`语句. + +如果您需要链接多个`OR`条件,也可以使用 Arel 进行此操作: + +``` +table = Issue.arel_table + +Issue.where(table[:title].matches('WIP:%').or(table[:foo].matches('WIP:%'))) +``` + +在 PostgreSQL 上,这将产生: + +``` +SELECT * +FROM issues +WHERE (title ILIKE 'WIP:%' OR foo ILIKE 'WIP:%') +``` + +## LIKE & Indexes[](#like--indexes "Permalink") + +在一开始使用带有通配符的`LIKE` / `ILIKE`时,PostgreSQL 将不使用任何索引. 例如,这将不使用任何索引: + +``` +SELECT * +FROM issues +WHERE title ILIKE '%WIP:%'; +``` + +因为`ILIKE`的值以通配符开头,所以数据库无法使用索引,因为它不知道从何处开始扫描索引. + +幸运的是,PostgreSQL *确实*提供了一种解决方案:trigram GIN 索引. 可以如下创建这些索引: + +``` +CREATE INDEX [CONCURRENTLY] index_name_here +ON table_name +USING GIN(column_name gin_trgm_ops); +``` + +这里的关键是`GIN(column_name gin_trgm_ops)`部分. 这将创建一个[GIN 索引](https://s0www0postgresql0org.icopy.site/docs/current/gin.html) ,并将操作符类设置为`gin_trgm_ops` . 这些索引*可*通过使用`ILIKE` / `LIKE` ,并可能导致大大改进的性能. 这些索引的缺点之一是它们很容易变大(取决于索引的数据量). + +为了使这些索引的命名保持一致,请使用以下命名模式: + +``` +index_TABLE_on_COLUMN_trigram +``` + +例如,一个`issues.title`的 GIN / `issues.title`索引将称为`index_issues_on_title_trigram` . + +Due to these indexes taking quite some time to be built they should be built concurrently. This can be done by using `CREATE INDEX CONCURRENTLY` instead of just `CREATE INDEX`. Concurrent indexes can *not* be created inside a transaction. Transactions for migrations can be disabled using the following pattern: + +``` +class MigrationName < ActiveRecord::Migration[4.2] + disable_ddl_transaction! +end +``` + +例如: + +``` +class AddUsersLowerUsernameEmailIndexes < ActiveRecord::Migration[4.2] + disable_ddl_transaction! + + def up + execute 'CREATE INDEX CONCURRENTLY index_on_users_lower_username ON users (LOWER(username));' + execute 'CREATE INDEX CONCURRENTLY index_on_users_lower_email ON users (LOWER(email));' + end + + def down + remove_index :users, :index_on_users_lower_username + remove_index :users, :index_on_users_lower_email + end +end +``` + +## Reliably referencing database columns[](#reliably-referencing-database-columns "Permalink") + +默认情况下,ActiveRecord 返回查询的数据库表中的所有列. 在某些情况下,可能需要自定义返回的行,例如: + +* 仅指定几列以减少从数据库返回的数据量. +* 包括`JOIN`关系中的列. +* 执行计算( `SUM` , `COUNT` ). + +在此示例中,我们指定列,但不指定其表: + +* `projects`表的`path` +* `merge_requests`表中的`user_id` + +查询: + +``` +# bad, avoid +Project.select("path, user_id").joins(:merge_requests) # SELECT path, user_id FROM "projects" ... +``` + +稍后,一项新功能将一个额外的列添加到`projects`表: `user_id` . 在部署期间,可能会在很短的时间范围内执行数据库迁移,但是尚未部署新版本的应用程序代码. 当上述查询在此期间执行时,查询将失败,并显示以下错误消息: `PG::AmbiguousColumn: ERROR: column reference "user_id" is ambiguous` + +问题是由从数据库中选择属性的方式引起的. 的`user_id`列存在于两个`users`和`merge_requests`表. 查询计划者无法确定在查找`user_id`列时要使用哪个表. + +在编写自定义的`SELECT`语句时,最好**使用表名明确指定列** . + +### Good (prefer)[](#good-prefer "Permalink") + +``` +Project.select(:path, 'merge_requests.user_id').joins(:merge_requests) + +# SELECT "projects"."path", merge_requests.user_id as user_id FROM "projects" ... +``` + +``` +Project.select(:path, :'merge_requests.user_id').joins(:merge_requests) + +# SELECT "projects"."path", "merge_requests"."id" as user_id FROM "projects" ... +``` + +使用 Arel( `arel_table` )的示例: + +``` +Project.select(:path, MergeRequest.arel_table[:user_id]).joins(:merge_requests) + +# SELECT "projects"."path", "merge_requests"."user_id" FROM "projects" ... +``` + +编写原始 SQL 查询时: + +``` +SELECT projects.path, merge_requests.user_id FROM "projects"... +``` + +When the raw SQL query is parameterized (needs escaping): + +``` +include ActiveRecord::ConnectionAdapters::Quoting + +""" +SELECT #{quote_table_name('projects')}.#{quote_column_name('path')}, #{quote_table_name('merge_requests')}.#{quote_column_name('user_id')} FROM ... +""" +``` + +### Bad (avoid)[](#bad-avoid "Permalink") + +``` +Project.select('id, path, user_id').joins(:merge_requests).to_sql + +# SELECT id, path, user_id FROM "projects" ... +``` + +``` +Project.select("path", "user_id").joins(:merge_requests) +# SELECT "projects"."path", "user_id" FROM "projects" ... + +# or + +Project.select(:path, :user_id).joins(:merge_requests) +# SELECT "projects"."path", "user_id" FROM "projects" ... +``` + +给定列列表后,ActiveRecord 尝试将参数与`projects`表中定义的列进行匹配,并自动在表名前添加前缀. 在这种情况下, `id`列不会有问题,但是`user_id`列可能返回意外数据: + +``` +Project.select(:id, :user_id).joins(:merge_requests) + +# Before deployment (user_id is taken from the merge_requests table): +# SELECT "projects"."id", "user_id" FROM "projects" ... + +# After deployment (user_id is taken from the projects table): +# SELECT "projects"."id", "projects"."user_id" FROM "projects" ... +``` + +## Plucking IDs[](#plucking-ids "Permalink") + +这还不够强调: **永远不要**使用 ActiveRecord 的`pluck`将一组值插入内存中,而只是将它们用作另一个查询的参数. 例如,这将使数据库**非常**悲伤: + +``` +projects = Project.all.pluck(:id) + +MergeRequest.where(source_project_id: projects) +``` + +相反,您可以只使用性能更好的子查询: + +``` +MergeRequest.where(source_project_id: Project.all.select(:id)) +``` + +*唯一*应该使用`pluck`时间是您实际上需要对 Ruby 本身中的值进行操作(例如,将它们写入文件中)时. 在几乎所有其他情况下,您都应该问自己"我不仅可以使用子查询吗?". + +根据我们的`CodeReuse/ActiveRecord`缔约方会议,您应仅在模型代码中使用诸如`pluck(:id)`或`pluck(:user_id)`之类的形式. 在前一种情况下,可以改用`ApplicationRecord` `.pluck_primary_key`帮助器方法. 在后者中,您应该在相关模型中添加一个小的辅助方法. + +## Inherit from ApplicationRecord[](#inherit-from-applicationrecord "Permalink") + +GitLab 代码库中的大多数模型应继承自`ApplicationRecord` ,而不是`ActiveRecord::Base` . 这样可以轻松添加辅助方法. + +在数据库迁移中创建的模型存在此规则的例外. 由于这些应与应用程序代码隔离,因此它们应继续从`ActiveRecord::Base`继承子类. + +## Use UNIONs[](#use-unions "Permalink") + +UNION 在大多数 Rails 应用程序中并不是很常用,但是它们非常强大且有用. 在大多数应用程序中,查询倾向于使用大量 JOIN 来获取相关数据或基于特定条件的数据,但是 JOIN 性能会随着所涉及数据的增长而迅速恶化. + +例如,如果要获取名称包含值*或*名称空间名称包含值的项目列表,大多数人会编写以下查询: + +``` +SELECT * +FROM projects +JOIN namespaces ON namespaces.id = projects.namespace_id +WHERE projects.name ILIKE '%gitlab%' +OR namespaces.name ILIKE '%gitlab%'; +``` + +使用大型数据库,此查询可能很容易花费大约 800 毫秒来运行. 使用 UNION,我们改为编写以下内容: + +``` +SELECT projects.* +FROM projects +WHERE projects.name ILIKE '%gitlab%' + +UNION + +SELECT projects.* +FROM projects +JOIN namespaces ON namespaces.id = projects.namespace_id +WHERE namespaces.name ILIKE '%gitlab%'; +``` + +反过来,此查询只需要 15 毫秒即可完成,同时返回完全相同的记录. + +这并不意味着您应该在所有地方开始使用 UNION,但是在查询中使用大量 JOIN 并根据联接的数据过滤掉记录时要牢记这一点. + +GitLab 带有一个`Gitlab::SQL::Union`类,可用于构建多个`ActiveRecord::Relation`对象的 UNION. 您可以按如下方式使用此类: + +``` +union = Gitlab::SQL::Union.new([projects, more_projects, ...]) + +Project.from("(#{union.to_sql}) projects") +``` + +## Ordering by Creation Date[](#ordering-by-creation-date "Permalink") + +根据记录的创建时间对记录进行排序时,只需按`id`列进行排序即可,而不必按`created_at`进行排序. 因为 ID 始终是唯一的,并且按照创建行的顺序递增,所以这将产生完全相同的结果. 这也意味着,由于默认情况下已经对`id`进行了索引,因此无需在`created_at`上添加索引以确保一致的性能. + +## Use WHERE EXISTS instead of WHERE IN[](#use-where-exists-instead-of-where-in "Permalink") + +虽然可以使用`WHERE IN`和`WHERE EXISTS`来生成相同的数据,但建议尽可能使用`WHERE EXISTS` . 尽管在许多情况下 PostgreSQL 可以很好地优化`WHERE IN`但在许多情况下`WHERE EXISTS`会好得多. + +在 Rails 中,您必须通过创建 SQL 片段来使用它: + +``` +Project.where('EXISTS (?)', User.select(1).where('projects.creator_id = users.id AND users.foo = X')) +``` + +然后,将按照以下内容生成查询: + +``` +SELECT * +FROM projects +WHERE EXISTS ( + SELECT 1 + FROM users + WHERE projects.creator_id = users.id + AND users.foo = X +) +``` + +## `.find_or_create_by` is not atomic[](#find_or_create_by-is-not-atomic "Permalink") + +`.find_or_create_by`和`.first_or_create`等方法的固有模式是它们不是原子的. 这意味着,它首先运行`SELECT` ,如果没有结果,则执行`INSERT` . 考虑到并发过程,因此存在竞争条件,这可能导致尝试插入两个相似的记录. 例如,这可能是不希望的,或者可能由于约束冲突而导致查询之一失败. + +使用事务不能解决此问题. + +为了解决这个问题,我们添加了`ApplicationRecord.safe_find_or_create_by` . + +可以像平常的`find_or_create_by`一样使用此方法,但是它将调用包装在*新*事务中,如果由于`ActiveRecord::RecordNotUnique`错误而失败,则将重试. + +为了能够使用此方法,请确保要在其上使用的模型继承自`ApplicationRecord` . \ No newline at end of file diff --git a/docs/624.md b/docs/624.md new file mode 100644 index 0000000000000000000000000000000000000000..fd065b1d6fd0c826a8634cc2013b0e14264b7e64 --- /dev/null +++ b/docs/624.md @@ -0,0 +1,431 @@ +# Vue.js style guide + +> 原文:[https://docs.gitlab.com/ee/development/fe_guide/style/vue.html](https://docs.gitlab.com/ee/development/fe_guide/style/vue.html) + +* [Linting](#linting) +* [Basic Rules](#basic-rules) +* [Naming](#naming) +* [Alignment](#alignment) +* [Quotes](#quotes) +* [Props](#props) +* [Data](#data) +* [Directives](#directives) +* [Closing tags](#closing-tags) +* [Component usage within templates](#component-usage-within-templates) +* [Ordering](#ordering) +* [`:key`](#key) +* [Vue and Bootstrap](#vue-and-bootstrap) +* [The JavaScript/Vue Accord](#the-javascriptvue-accord) + +# Vue.js style guide[](#vuejs-style-guide "Permalink") + +## Linting[](#linting "Permalink") + +我们默认为[eslint-vue-plugin](https://github.com/vuejs/eslint-plugin-vue) ,其`plugin:vue/recommended` . 请检查此[规则](https://github.com/vuejs/eslint-plugin-vue#bulb-rules)以获取更多文档. + +## Basic Rules[](#basic-rules "Permalink") + +1. 该服务具有自己的文件 +2. 商店有自己的文件 +3. 使用捆绑文件中的函数实例化 Vue 组件: + + ``` + // bad + class { + init() { + new Component({}) + } + } + + // good + document.addEventListener('DOMContentLoaded', () => new Vue({ + el: '#element', + components: { + componentName + }, + render: createElement => createElement('component-name'), + })); + ``` + +4. 不要将单例用于服务或商店 + + ``` + // bad + class Store { + constructor() { + if (!this.prototype.singleton) { + // do something + } + } + } + + // good + class Store { + constructor() { + // do something + } + } + ``` + +5. 将`.vue`用于 Vue 模板. 不要在 HAML 中使用`%template` . + +## Naming[](#naming "Permalink") + +1. **扩展名** :对 Vue 组件使用`.vue`扩展名. 不要将`.js`用作文件扩展名( [#34371](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34371) ). +2. **参考命名** :将 PascalCase 用于其实例: + + ``` + // bad + import cardBoard from 'cardBoard.vue' + + components: { + cardBoard, + }; + + // good + import CardBoard from 'cardBoard.vue' + + components: { + CardBoard, + }; + ``` + +3. **道具命名:**避免使用 DOM 组件道具名称. +4. **道具命名:**使用 kebab-case 代替 camelCase 在模板中提供道具. + + ``` + // bad + <component class="btn"> + + // good + <component css-class="btn"> + + // bad + <component myProp="prop" /> + + // good + <component my-prop="prop" /> + ``` + +## Alignment[](#alignment "Permalink") + +1. 对于模板方法,请遵循以下对齐方式: + + 1. 具有多个属性,所有属性都应换行: + + ``` + // bad + <component v-if="bar" + param="baz" /> + + <button class="btn">Click me</button> + + // good + <component + v-if="bar" + param="baz" + /> + + <button class="btn"> + Click me + </button> + ``` + + 2. 如果只有一个属性,则标签可以是内联的: + + ``` + // good + <component bar="bar" /> + + // good + <component + bar="bar" + /> + + // bad + <component + bar="bar" /> + ``` + +## Quotes[](#quotes "Permalink") + +1. 对于所有其他 JS,请始终在模板内使用双引号`"`在模板内使用单引号`'` . + + ``` + // bad + template: ` + <button :class='style'>Button</button> + ` + + // good + template: ` + <button :class="style">Button</button> + ` + ``` + +## Props[](#props "Permalink") + +1. 道具应声明为对象 + + ``` + // bad + props: ['foo'] + + // good + props: { + foo: { + type: String, + required: false, + default: 'bar' + } + } + ``` + +2. 声明道具时应始终提供必需的钥匙 + + ``` + // bad + props: { + foo: { + type: String, + } + } + + // good + props: { + foo: { + type: String, + required: false, + default: 'bar' + } + } + ``` + +3. 如果不需要道具,则应提供默认密钥. *注意:*在某些情况下,我们需要检查属性的存在. 在这些上,不应提供默认密钥. + + ``` + // good + props: { + foo: { + type: String, + required: false, + } + } + + // good + props: { + foo: { + type: String, + required: false, + default: 'bar' + } + } + + // good + props: { + foo: { + type: String, + required: true + } + } + ``` + +## Data[](#data "Permalink") + +1. `data`方法应始终是一个函数 + + ``` + // bad + data: { + foo: 'foo' + } + + // good + data() { + return { + foo: 'foo' + }; + } + ``` + +## Directives[](#directives "Permalink") + +1. 速记`@`优先于`v-on` + + ``` + // bad + <component v-on:click="eventHandler"/> + + // good + <component @click="eventHandler"/> + ``` + +2. 速记`:`优于`v-bind` + + ``` + // bad + <component v-bind:class="btn"/> + + // good + <component :class="btn"/> + ``` + +3. Shorthand `#` is preferable over `v-slot` + + ``` + // bad + <template v-slot:header></template> + + // good + <template #header></template> + ``` + +## Closing tags[](#closing-tags "Permalink") + +1. 首选自闭合组件标签 + + ``` + // bad + <component></component> + + // good + <component /> + ``` + +## Component usage within templates[](#component-usage-within-templates "Permalink") + +1. 在模板中使用组件时,将组件的 kebab 命名的名称优先于其他样式 + + ``` + // bad + <MyComponent /> + + // good + <my-component /> + ``` + +## Ordering[](#ordering "Permalink") + +1. `.vue`文件中的标记顺序 + + ``` + <script> + // ... + </script> + + <template> + // ... + </template> + + // We don't use scoped styles but there are few instances of this + <style> + // ... + </style> + ``` + +2. Vue 组件中[的属性](https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/order-in-components.md) :检查[组件 rule 中的属性顺序](https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/order-in-components.md) . + +## `:key`[](#key "Permalink") + +使用`v-for`您需要为每个项目提供*唯一的* `:key`属性. + +1. 如果要迭代的数组元素具有唯一的`id` ,则建议使用它: + + ``` + <div + v-for="item in items" + :key="item.id" + > + <!-- content --> + </div> + ``` + +2. 当要迭代的元素没有唯一 ID 时,可以将数组索引用作`:key`属性 + + ``` + <div + v-for="(item, index) in items" + :key="index" + > + <!-- content --> + </div> + ``` + +3. 当将`v-for`与`template`并且有多个子元素时, `:key`值必须唯一. 建议使用`kebab-case`名称空间. + + ``` + <template v-for="(item, index) in items"> + <span :key="`span-${index}`"></span> + <button :key="`button-${index}`"></button> + </template> + ``` + +4. 处理嵌套`v-for`使用与上述相同的准则. + + ``` + <div + v-for="item in items" + :key="item.id" + > + <span + v-for="element in array" + :key="element.id" + > + <!-- content --> + </span> + </div> + ``` + +有用的链接: + +1. [`key`](https://vuejs.org/v2/guide/list.html#key) +2. [Vue Style Guide: Keyed v-for](https://vuejs.org/v2/style-guide/#Keyed-v-for-essential) + +## Vue and Bootstrap[](#vue-and-bootstrap "Permalink") + +1. 工具提示:请勿依赖 Vue 组件的`has-tooltip`类名称 + + ``` + // bad + <span + class="has-tooltip" + title="Some tooltip text"> + Text + </span> + + // good + <span + v-tooltip + title="Some tooltip text"> + Text + </span> + ``` + +2. 工具提示:使用工具提示时,请包含工具提示指令`./app/assets/javascripts/vue_shared/directives/tooltip.js` + +3. 不要更改`data-original-title` . + + ``` + // bad + <span data-original-title="tooltip text">Foo</span> + + // good + <span title="tooltip text">Foo</span> + + $('span').tooltip('_fixTitle'); + ``` + +## The JavaScript/Vue Accord[](#the-javascriptvue-accord "Permalink") + +该协议的目的是确保我们都在同一页面上. + +1. 编写 Vue 时,您可能无法在应用程序中使用 jQuery. + 1. 如果您需要从 DOM 抓取数据,则可以在引导应用程序以使用`dataset`抓取数据属性时查询 DOM 1 次. 您可以在没有 jQuery 的情况下执行此操作. + 2. 您可以[按照 docs 中的此示例](https://vuejs.org/v2/examples/select2.html)在 Vue.js 中使用 jQuery 依赖关系. + 3. 如果需要在 Vue 应用程序内部侦听外部 jQuery 事件,则可以使用 jQuery 事件侦听器. + 4. 我们将避免在不需要时添加新的 jQuery 事件. 与其添加新的 jQuery 事件,不如看看[执行相同任务的不同方法](https://vuejs.org/v2/api/#vm-emit) . +2. 您可以一次引导`window`对象,同时引导您的应用程序以获取应用程序特定的数据(例如, `scrollTo`可以随时访问). 在应用程序引导期间执行此访问. +3. 您可能会临时需要立即但不符合我们标准的代码来编写技术债,以备以后重构. 维护人员首先要对技术债务保持满意. 应该为该技术债务创建一个问题,以便对其进行进一步评估和讨论. 在接下来的几个月中,您应该解决该技术债务,其优先级由维护者确定. +4. 在产生技术债务时,您必须事先为该代码编写测试,并且这些测试可能不会被重写. 例如,将 jQuery 测试重写为 Vue 测试. +5. 您可以选择将 VueX 用作集中式状态管理. 如果选择不使用 VueX,则必须使用可以在[Vue.js 文档中](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch)找到的*存储模式* . +6. 选择集中式状态管理解决方案后,必须将其用于整个应用程序. 即不要混淆并匹配您的状态管理解决方案. \ No newline at end of file diff --git a/docs/625.md b/docs/625.md new file mode 100644 index 0000000000000000000000000000000000000000..68e84e913b731dad9bb98ef0e0304cd36cb5228a --- /dev/null +++ b/docs/625.md @@ -0,0 +1,141 @@ +# Instrumenting Ruby code + +> 原文:[https://docs.gitlab.com/ee/development/instrumentation.html](https://docs.gitlab.com/ee/development/instrumentation.html) + +* [Instrumenting Methods](#instrumenting-methods) + * [Examples](#examples) + * [Checking Instrumented Methods](#checking-instrumented-methods) +* [Instrumenting Ruby Blocks](#instrumenting-ruby-blocks) +* [Tracking Custom Events](#tracking-custom-events) + +# Instrumenting Ruby code[](#instrumenting-ruby-code "Permalink") + +[GitLab Performance Monitoring](../administration/monitoring/performance/index.html)可以检测 Ruby 代码的方法和自定义块. 方法检测是基于块的检测的主要检测形式,仅当我们想深入到方法中特定代码区域时才使用. + +如果要跟踪产品使用模式,请参考[遥测](telemetry/index.html) . + +## Instrumenting Methods[](#instrumenting-methods "Permalink") + +使用`Gitlab::Metrics::Instrumentation`模块可以完成检测方法. 该模块提供了几种可用于检测代码的方法: + +* `instrument_method` :检测单个类方法. +* `instrument_instance_method` :检测单个实例方法. +* `instrument_class_hierarchy` :给定一个 Class,此方法将递归地检测所有子类(类方法和实例方法). +* `instrument_methods` :检测模块的所有公共和私有类方法. +* `instrument_instance_methods` :检测模块的所有公共和私有实例方法. + +为了消除键入完整的`Gitlab::Metrics::Instrumentation`命名空间的需要,您可以使用`configure`类方法. 通过传递`Gitlab::Metrics::Instrumentation`作为其参数时,此方法仅产生提供的块. 一个例子: + +``` +Gitlab::Metrics::Instrumentation.configure do |conf| + conf.instrument_method(Foo, :bar) + conf.instrument_method(Foo, :baz) +end +``` + +通常,使用此方法优于直接调用各种检测方法. + +方法检测应添加到初始化程序`config/initializers/zz_metrics.rb` . + +### Examples[](#examples "Permalink") + +检测单个方法: + +``` +Gitlab::Metrics::Instrumentation.configure do |conf| + conf.instrument_method(User, :find_by) +end +``` + +检测整个类的层次结构: + +``` +Gitlab::Metrics::Instrumentation.configure do |conf| + conf.instrument_class_hierarchy(ActiveRecord::Base) +end +``` + +检测所有公共类方法: + +``` +Gitlab::Metrics::Instrumentation.configure do |conf| + conf.instrument_methods(User) +end +``` + +### Checking Instrumented Methods[](#checking-instrumented-methods "Permalink") + +检查一种方法是否已被检测的最简单方法是检查其源位置. 例如: + +``` +method = Banzai::Renderer.method(:render) + +method.source_location +``` + +如果源位置指向`lib/gitlab/metrics/instrumentation.rb` ,则说明该方法已经过检测. + +如果使用的是 Pry,则可以使用`$`命令显示方法的源代码(及其源位置),这比运行上面的 Ruby 代码容易. 如果是上述片段,请运行以下代码: + +* `$ Banzai::Renderer.render` + +这将打印出以下内容: + +``` +From: /path/to/your/gitlab/lib/gitlab/metrics/instrumentation.rb @ line 148: +Owner: #<Module:0x0055f0865c6d50> +Visibility: public +Number of lines: 21 + +def #{name}(#{args_signature}) + if trans = Gitlab::Metrics::Instrumentation.transaction + trans.measure_method(#{label.inspect}) { super } + else + super + end +end +``` + +## Instrumenting Ruby Blocks[](#instrumenting-ruby-blocks "Permalink") + +通过调用`Gitlab::Metrics.measure`并将其传递给块来完成对 Ruby 代码块的测量. 例如: + +``` +Gitlab::Metrics.measure(:foo) do + ... +end +``` + +执行该块并将执行时间存储为当前运行的事务中的一组字段. 如果不存在事务,则不进行任何测量就产生该块. + +测量一个块的三个值: + +* 经过的实时时间,存储在`NAME_real_time` . +* The CPU time elapsed, stored in `NAME_cpu_time`. +* 通话次数,存储在`NAME_call_count` . + +实时和 CPU 计时均以毫秒为单位. + +多次调用同一块将导致最终值是所有单个值的总和. 以下面的代码为例: + +``` +3.times do + Gitlab::Metrics.measure(:sleep) do + sleep 1 + end +end +``` + +在这里, `sleep_real_time`的最终值为`3` , *而不是* `1` . + +## Tracking Custom Events[](#tracking-custom-events "Permalink") + +除了检测代码,GitLab Performance Monitoring 还支持跟踪自定义事件. 这主要用于跟踪业务指标,例如 Git 推送数,存储库导入等. + +要跟踪自定义事件,只需调用`Gitlab::Metrics.add_event`传递事件名称和一组自定义(可选)标签. 例如: + +``` +Gitlab::Metrics.add_event(:user_login, email: current_user.email) +``` + +事件名称应为动词,例如`push_repository`和`remove_branch` . \ No newline at end of file diff --git a/docs/626.md b/docs/626.md new file mode 100644 index 0000000000000000000000000000000000000000..2102163cbf7bf16eb747524235ab39e7a3270be7 --- /dev/null +++ b/docs/626.md @@ -0,0 +1,67 @@ +# Testing standards and style guidelines + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/](https://docs.gitlab.com/ee/development/testing_guide/) + +* [Overview](#overview) +* [Testing levels](#testing-levels) +* [Testing best practices](#testing-best-practices) +* [Frontend testing standards and style guidelines](#frontend-testing-standards-and-style-guidelines) +* [Flaky tests](#flaky-tests) +* [GitLab tests in the Continuous Integration (CI) context](#gitlab-tests-in-the-continuous-integration-ci-context) +* [Review apps](#review-apps) +* [Testing Rake tasks](#testing-rake-tasks) +* [End-to-end tests](#end-to-end-tests) +* [Migrations tests](#migrations-tests) + +# Testing standards and style guidelines[](#testing-standards-and-style-guidelines "Permalink") + +本文档介绍了自动测试 GitLab 项目的各种指南和最佳实践. + +它是对[Thoughtbot 测试风格指南](https://github.com/thoughtbot/guides/tree/master/style/testing)的*扩展* . 如果本指南定义的规则与 Thoughtbot 指南相抵触,则以本指南为准. 可能会逐字重复某些准则以强调其重要性. + +## Overview[](#overview "Permalink") + +GitLab 建立在[Ruby on Rails](https://rubyonrails.org/)之上,并且我们将[RSpec](https://github.com/rspec/rspec-rails#feature-specs)用于所有后端测试,而[Capybara](https://github.com/teamcapybara/capybara)用于端到端集成测试. 在前端,我们将[Jest](https://jestjs.io/)和[Karma](http://karma-runner.github.io/) / [Jasmine](https://jasmine.github.io/)用于 JavaScript 单元和集成测试. + +以下是两篇很棒的文章,每个人都应该阅读它们,以了解自动化测试的含义以及其原理是什么: + +* [五因素测试](https://madeintandem.com/blog/five-factor-testing/) :为什么我们需要测试? +* [自动化测试的原则:测试](https://www.lihaoyi.com/post/PrinciplesofAutomatedTesting.html)级别. 确定测试的优先级. 测试费用. + +## [Testing levels](testing_levels.html)[](#testing-levels "Permalink") + +Learn about the different testing levels, and how to decide at what level your changes should be tested. + +## [Testing best practices](best_practices.html)[](#testing-best-practices "Permalink") + +关于编写良好测试的所有知识,包括:测试设计,RSpec,FactoryBot,系统测试,参数化测试等. + +## [Frontend testing standards and style guidelines](frontend_testing.html)[](#frontend-testing-standards-and-style-guidelines "Permalink") + +您应该知道的有关如何编写良好的前端测试的所有知识:业力,测试承诺,存根等. + +## [Flaky tests](flaky_tests.html)[](#flaky-tests "Permalink") + +什么是片状测试,我们遇到的不同类型的片状测试,以及我们如何处理它们. + +## [GitLab tests in the Continuous Integration (CI) context](ci.html)[](#gitlab-tests-in-the-continuous-integration-ci-context "Permalink") + +GitLab 测试套件如何在 CI 上下文中运行:设置,缓存,工件,并行化,监视. + +## [Review apps](review_apps.html)[](#review-apps "Permalink") + +如何为 GitLab CE / EE 设置评论应用程序以及如何使用它们. + +## [Testing Rake tasks](testing_rake_tasks.html)[](#testing-rake-tasks "Permalink") + +您应该了解的有关如何测试 Rake 任务的所有知识. + +## [End-to-end tests](end_to_end/index.html)[](#end-to-end-tests "Permalink") + +您应该了解有关如何使用[GitLab QA](https://gitlab.com/gitlab-org/gitlab-qa)测试框架进行端到端测试的所有知识. + +## [Migrations tests](testing_migrations_guide.html)[](#migrations-tests "Permalink") + +您应该了解的有关如何测试迁移的一切. + +[Return to Development documentation](../README.html) \ No newline at end of file diff --git a/docs/627.md b/docs/627.md new file mode 100644 index 0000000000000000000000000000000000000000..cda06bf92e420dc71d74fdd4d315c939bfe39b1f --- /dev/null +++ b/docs/627.md @@ -0,0 +1,120 @@ +# Flaky tests + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/flaky_tests.html](https://docs.gitlab.com/ee/development/testing_guide/flaky_tests.html) + +* [What’s a flaky test?](#whats-a-flaky-test) +* [Quarantined tests](#quarantined-tests) + * [Quarantine tests on the CI](#quarantine-tests-on-the-ci) +* [Automatic retries and flaky tests detection](#automatic-retries-and-flaky-tests-detection) +* [Problems we had in the past at GitLab](#problems-we-had-in-the-past-at-gitlab) + * [Time-sensitive flaky tests](#time-sensitive-flaky-tests) + * [Array order expectation](#array-order-expectation) + * [Feature tests](#feature-tests) + * [Capybara viewport size related issues](#capybara-viewport-size-related-issues) + * [Capybara JS driver related issues](#capybara-js-driver-related-issues) + * [PhantomJS / WebKit related issues](#phantomjs--webkit-related-issues) + * [Capybara expectation times out](#capybara-expectation-times-out) +* [Resources](#resources) + +# Flaky tests[](#flaky-tests "Permalink") + +## What’s a flaky test?[](#whats-a-flaky-test "Permalink") + +这个测试有时会失败,但是如果您重试了多次,它最终会通过. + +## Quarantined tests[](#quarantined-tests "Permalink") + +当`master`的测试频繁失败时,应创建[〜" master:broken"问题](https://about.gitlab.com/handbook/engineering/workflow/#broken-master) . 如果无法及时修复测试,则会影响所有开发人员的工作效率,因此应通过分配`:quarantine`元数据将其放入隔离`:quarantine` . + +这意味着除非使用`--tag quarantine`运行,否则它将被跳过: + +``` +bin/rspec --tag quarantine +``` + +**在对隔离进行测试之前,应确保存在〜" master:broken"问题,这样它才不会永远留在隔离区.** + +Once a test is in quarantine, there are 3 choices: + +* 测试应该固定(即摆脱其脆弱性)吗? +* 是否应将测试移至较低级别的测试? +* 是否应该完全删除该测试(例如,因为已经有一个较低级别的测试,或者它正在复制另一个相同级别的测试,或者它测试的太多等等)? + +### Quarantine tests on the CI[](#quarantine-tests-on-the-ci "Permalink") + +隔离测试在允许失败的专用作业中在 CI 上运行: + +* `rspec-pg-quarantine` (CE 和 EE) +* `rspec-pg-quarantine-ee` (仅适用于 EE) + +## Automatic retries and flaky tests detection[](#automatic-retries-and-flaky-tests-detection "Permalink") + +在 CI 上,我们使用[RSpec :: Retry](https://github.com/NoRedInk/rspec-retry)自动重试失败的示例几次(有关准确的重试次数,请参阅[`spec/spec_helper.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/spec_helper.rb) ). + +我们还使用自制的`RspecFlaky::Listener`侦听`RspecFlaky::Listener` ,该`RspecFlaky::Listener`将`RspecFlaky::Listener`示例记录在`master`上的 JSON 报告文件中( `retrieve-tests-metadata`和`update-tests-metadata`作业). + +这最初是在以下[网址中](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13021)实现的: [https](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13021) : [//gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13021](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13021) . + +如果要在本地启用重试,则可以使用`RETRIES`环境变量. 例如`RETRIES=1 bin/rspec ...`将重试失败的示例一次. + +## Problems we had in the past at GitLab[](#problems-we-had-in-the-past-at-gitlab "Permalink") + +* [`rspec-retry` is biting us when some API specs fail](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29242): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9825](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9825) +* [Sporadic RSpec failures due to `PG::UniqueViolation`](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28307#note_24958837): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9846](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9846) + * Follow-up: [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10688](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10688) + * [Capybara.reset_session! should be called before requests are blocked](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33779): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12224](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12224) +* FFaker 生成测试尚未准备就绪的时髦数据(测试应该是可预测的,所以很糟糕!): + * [使`spec/mailers/notify_spec.rb`更加健壮](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20121) : [https](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10015) : [`spec/mailers/notify_spec.rb`](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20121) + * [`spec/requests/api/commits_spec.rb`暂时失败](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/27988#note_25342521) : [https](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9944) : [`spec/requests/api/commits_spec.rb`](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/27988#note_25342521) + * [用序列替换 FFaker 工厂数据](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29643) : [https](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10184) : [//gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10184](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29643) + * [spec / finders / issues_finder_spec.rb 中的暂时失败](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30211#note_26707685) : [https](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10404) : [//gitlab.com/gitlab-org/gitlab-foss/-//merge_requests/10404](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30211#note_26707685) + +### Time-sensitive flaky tests[](#time-sensitive-flaky-tests "Permalink") + +* [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10046](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10046) +* [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10306](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10306) + +### Array order expectation[](#array-order-expectation "Permalink") + +* [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10148](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10148) + +### Feature tests[](#feature-tests "Permalink") + +* [Be sure to create all the data the test need before starting exercise](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/32622#note_31128195): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12059](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12059) +* [Bis](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34609#note_34048715): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12604](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12604) +* [Bis](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34698#note_34276286): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12664](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12664) +* [Assert against the underlying database state instead of against a page’s content](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/31437): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10934](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10934) +* 在 JS 测试中,当元素在 Capybara 发送点击的确切时间移动时,移动元素会导致 Capybara 误点击 + * [由于窗口大小和滚动位置,下拉菜单向上或向下渲染](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17660) + * [延迟加载的图像可能导致水豚误点击](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18713) +* [Triggering JS events before the event handlers are set up](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18742) +* [Wait for the image to be lazy-loaded when asserting on a Markdown image’s `src` attribute](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25408) + +#### Capybara viewport size related issues[](#capybara-viewport-size-related-issues "Permalink") + +* [Transient failure of spec/features/issues/filtered_search/filter_issues_spec.rb](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29241#note_26743936): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10411](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10411) + +#### Capybara JS driver related issues[](#capybara-js-driver-related-issues "Permalink") + +* [Don’t wait for AJAX when no AJAX request is fired](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30461): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10454](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10454) +* [Bis](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34647): [https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12626](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12626) + +#### PhantomJS / WebKit related issues[](#phantomjs--webkit-related-issues "Permalink") + +* 记忆在屋顶! (TL; DR:加载图像但阻止图像请求!): [https](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12003) : [//gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12003](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12003) + +#### Capybara expectation times out[](#capybara-expectation-times-out "Permalink") + +* [Test imports a project (via Sidekiq) that is growing over time, leading to timeouts when the import takes longer than 60 seconds](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22599) + +## Resources[](#resources "Permalink") + +* [Flaky Tests: Are You Sure You Want to Rerun Them?](https://semaphoreci.com/blog/2017/04/20/flaky-tests.html) +* [How to Deal With and Eliminate Flaky Tests](https://semaphoreci.com/community/tutorials/how-to-deal-with-and-eliminate-flaky-tests) +* [Tips on Treating Flakiness in your Rails Test Suite](https://semaphoreci.com/blog/2017/08/03/tips-on-treating-flakiness-in-your-test-suite.html) +* [‘Flaky’ tests: a short story](https://www.ombulabs.com/blog/rspec/continuous-integration/how-to-track-down-a-flaky-test.html) +* [Using Insights to Discover Flaky, Slow, and Failed Tests](https://s0circleci0com.icopy.site/blog/using-insights-to-discover-flaky-slow-and-failed-tests/) + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/docs/628.md b/docs/628.md new file mode 100644 index 0000000000000000000000000000000000000000..a2976829b0350daa727a26cde2ad7c96eddea853 --- /dev/null +++ b/docs/628.md @@ -0,0 +1,940 @@ +# Frontend testing standards and style guidelines + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/frontend_testing.html](https://docs.gitlab.com/ee/development/testing_guide/frontend_testing.html) + +* [Vue.js testing](#vuejs-testing) +* [Jest](#jest) +* [Karma test suite](#karma-test-suite) + * [When should I use Jest over Karma?](#when-should-i-use-jest-over-karma) + * [Differences to Karma](#differences-to-karma) + * [Limitations of jsdom](#limitations-of-jsdom) + * [Debugging Jest tests](#debugging-jest-tests) + * [Timeout error](#timeout-error) +* [What and how to test](#what-and-how-to-test) + * [Don’t test the library](#dont-test-the-library) + * [Don’t test your mock](#dont-test-your-mock) + * [Follow the user](#follow-the-user) +* [Common practices](#common-practices) + * [How to query DOM elements](#how-to-query-dom-elements) + * [Naming unit tests](#naming-unit-tests) + * [Testing promises](#testing-promises) + * [Manipulating Time](#manipulating-time) + * [`setTimeout()` / `setInterval()` in application](#settimeout--setinterval-in-application) + * [Waiting in tests](#waiting-in-tests) + * [Promises and Ajax calls](#promises-and-ajax-calls) + * [Vue rendering](#vue-rendering) + * [Events](#events) + * [Ensuring that tests are isolated](#ensuring-that-tests-are-isolated) + * [Jest best practices](#jest-best-practices) + * [Prefer `toBe` over `toEqual` when comparing primitive values](#prefer-tobe-over-toequal-when-comparing-primitive-values) + * [Prefer more befitting matchers](#prefer-more-befitting-matchers) + * [Avoid using `toBeTruthy` or `toBeFalsy`](#avoid-using-tobetruthy-or-tobefalsy) + * [Tricky `toBeDefined` matcher](#tricky-tobedefined-matcher) + * [Avoid using `setImmediate`](#avoid-using-setimmediate) +* [Factories](#factories) +* [Mocking Strategies with Jest](#mocking-strategies-with-jest) + * [Stubbing and Mocking](#stubbing-and-mocking) + * [Manual module mocks](#manual-module-mocks) + * [Where should I put manual mocks?](#where-should-i-put-manual-mocks) + * [Manual mock examples](#manual-mock-examples) + * [Keep mocks light](#keep-mocks-light) + * [Additional mocking techniques](#additional-mocking-techniques) +* [Running Frontend Tests](#running-frontend-tests) + * [Live testing and focused testing – Jest](#live-testing-and-focused-testing----jest) + * [Live testing and focused testing – Karma](#live-testing-and-focused-testing----karma) +* [Frontend test fixtures](#frontend-test-fixtures) +* [Data-driven tests](#data-driven-tests) +* [Gotchas](#gotchas) + * [RSpec errors due to JavaScript](#rspec-errors-due-to-javascript) +* [Overview of Frontend Testing Levels](#overview-of-frontend-testing-levels) +* [Test helpers](#test-helpers) + * [Vuex Helper: `testAction`](#vuex-helper-testaction) + * [Wait until Axios requests finish](#wait-until-axios-requests-finish) +* [Testing with older browsers](#testing-with-older-browsers) + * [BrowserStack](#browserstack) + * [Firefox](#firefox) + * [macOS](#macos) + +# Frontend testing standards and style guidelines[](#frontend-testing-standards-and-style-guidelines "Permalink") + +在 GitLab 上开发前端代码时,会遇到两种测试套件. 我们将 Karma 与 Jasmine 和 Jest 一起用于 JavaScript 单元和集成测试,将 RSpec 功能测试与 Capybara 一起用于 e2e(端对端)集成测试. + +需要为所有新功能编写单元和功能测试. 大多数时候,您应该使用[RSpec](https://github.com/rspec/rspec-rails#feature-specs)进行功能测试. + +应该编写回归测试来修复错误,以防止将来再次发生. + +See the [Testing Standards and Style Guidelines](index.html) page for more information on general testing practices at GitLab. + +## Vue.js testing[](#vuejs-testing "Permalink") + +如果您正在寻找有关 Vue 组件测试的指南,则可以立即跳至本[部分](../fe_guide/vue.html#testing-vue-components) . + +## Jest[](#jest "Permalink") + +我们已经开始将前端测试迁移到[Jest](https://jestjs.io)测试框架(另请参见相应的[epic](https://gitlab.com/groups/gitlab-org/-/epics/895) ). + +开玩笑的测试可以在 EE 的`/spec/frontend`和`/ee/spec/frontend`中找到. + +> **Note:** +> +> 大多数示例都有 Jest 和 Karma 示例. 如果您在发现过程中偶然发现了一些用例,请仅参阅 Karma 示例以解释代码中发生的事情. 开玩笑的例子是您应该遵循的例子. + +## Karma test suite[](#karma-test-suite "Permalink") + +当 GitLab 切换到[Jest 时,](https://jestjs.io)您仍然会在我们的应用程序中找到 Karma 测试. [Karma](http://karma-runner.github.io/)是使用[Jasmine](https://jasmine.github.io/)作为测试框架的测试运行程序. Jest 还使用 Jasmine 作为基础,这就是为什么它看起来非常相似的原因. + +业力测试存在于`/ee/spec/javascripts`中的`spec/javascripts/`和`/ee/spec/javascripts`中. + +`app/assets/javascripts/behaviors/autosize.js`可能具有相应的`spec/javascripts/behaviors/autosize_spec.js`文件. + +请记住,在 CI 环境中,这些测试是在无头浏览器中运行的,您将无权访问某些必须进行存根的 API,例如[`Notification`](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/API/notification) . + +### When should I use Jest over Karma?[](#when-should-i-use-jest-over-karma "Permalink") + +如果您需要更新现有的 Karma 测试文件(可在`spec/javascripts`找到),则无需将整个规范迁移到 Jest. 只需更新 Karma 规范以测试您的更改就可以了. 在单独的合并请求中迁移到 Jest 可能更合适. + +如果创建新的测试文件,则需要在 Jest 中创建它. 这将有助于支持我们的迁移,我们认为您会喜欢使用 Jest. + +与往常一样,请谨慎使用. Jest 解决了我们在 Karma 中遇到的许多问题,并提供了更好的开发人员体验,但是可能会出现潜在的意外问题(尤其是针对浏览器特定功能进行测试). + +### Differences to Karma[](#differences-to-karma "Permalink") + +* Jest 在 Node.js 环境中运行,而不是在浏览器中. 运行在浏览器中测试玩笑支持[计划](https://gitlab.com/gitlab-org/gitlab/-/issues/26982) . +* 由于 Jest 在 Node.js 环境中运行,因此默认情况下它使用[jsdom](https://github.com/jsdom/jsdom) . 另请参见下面的[限制](#limitations-of-jsdom) . +* Jest 无权访问 Webpack 加载程序或别名. Jest 使用的别名是在其[自己的配置](https://gitlab.com/gitlab-org/gitlab/blob/master/jest.config.js)中定义的. +* 对`setTimeout`和`setInterval`所有调用都被模拟掉了. 另请参阅[Jest Timer Mocks](https://jestjs.io/docs/en/timer-mocks) . +* `rewire`不需要因为玩笑支撑嘲笑模块. 另请参见" [手动模拟"](https://jestjs.io/docs/en/manual-mocks) . +* 没有[上下文对象](https://jasmine.github.io/tutorials/your_first_suite#section-The_<code>this</code>_keyword)传递给 Jest 中的测试. 这意味着`this.something`在`beforeEach()`和`it()`之间共享`this.something`不起作用. 相反,您应该在需要共享变量的上下文中声明它们(通过`const` / `let` ). +* 以下将导致测试在 Jest 中失败: + * 未模拟的请求. + * 未处理的承诺拒绝. + * 调用`console.warn` ,包括来自 Vue 之类的库的警告. + +### Limitations of jsdom[](#limitations-of-jsdom "Permalink") + +[如上所述](#differences-to-karma) ,Jest 使用 jsdom 而不是浏览器来运行测试. 这有很多限制,即: + +* [No scrolling support](https://github.com/jsdom/jsdom/blob/15.1.1/lib/jsdom/browser/Window.js#L623-L625) +* [No element sizes or positions](https://github.com/jsdom/jsdom/blob/15.1.1/lib/jsdom/living/nodes/Element-impl.js#L334-L371) +* 一般[没有版面设计引擎](https://github.com/jsdom/jsdom/issues/1322) + +另请参阅有关[在浏览器中运行 Jest 测试的支持](https://gitlab.com/gitlab-org/gitlab/-/issues/26982)问题. + +### Debugging Jest tests[](#debugging-jest-tests "Permalink") + +运行`yarn jest-debug`将在调试模式下运行 Jest,从而允许您按照[Jest docs](https://jestjs.io/docs/en/troubleshooting#tests-are-failing-and-you-don-t-know-why)中的说明进行调试/检查. + +### Timeout error[](#timeout-error "Permalink") + +Jest 的默认超时是在[`/spec/frontend/test_setup.js`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/test_setup.js)设置的. + +如果您的测试超过该时间,它将失败. + +如果无法提高测试性能,则可以使用[`setTestTimeout`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/helpers/timeout.js)来增加特定测试的超时时间. + +``` +import { setTestTimeout } from 'helpers/timeout'; + +describe('Component', () => { + it('does something amazing', () => { + setTestTimeout(500); + // ... + }); +}); +``` + +请记住,每个测试的性能取决于环境. + +## What and how to test[](#what-and-how-to-test "Permalink") + +在深入了解有关 Jest 特定工作流程(如模拟和间谍)的更具体细节之前,我们应该简要介绍一下使用 Jest 测试的内容. + +### Don’t test the library[](#dont-test-the-library "Permalink") + +库是任何 JavaScript 开发人员生活中不可或缺的一部分. 一般建议是不要测试库的内部,但是希望库知道它应该做什么并且自己进行测试覆盖. 一个一般的例子可能是这样的 + +``` +import { convertToFahrenheit } from 'temperatureLibrary' + +function getFahrenheit(celsius) { + return convertToFahrenheit(celsius) +} +``` + +测试我们的`getFahrenheit`函数没有任何意义,因为在其下面除了调用库函数外,什么都没有做,而且我们可以预期它正在按预期工作. (简化,我知道) + +让我们看一下 Vue 领域. Vue 是 GitLab JavaScript 代码库的关键部分. 在编写 Vue 组件规范时,通常的陷阱是最终测试 Vue 提供的功能,因为这似乎是最容易测试的事情. 这是取自我们代码库的示例. + +``` +// Component +{ + computed: { + hasMetricTypes() { + return this.metricTypes.length; + }, +} +``` + +这是相应的规格 + +``` + describe('computed', () => { + describe('hasMetricTypes', () => { + it('returns true if metricTypes exist', () => { + factory({ metricTypes }); + expect(wrapper.vm.hasMetricTypes).toBe(2); + }); + + it('returns true if no metricTypes exist', () => { + factory(); + expect(wrapper.vm.hasMetricTypes).toBe(0); + }); + }); +}); +``` + +测试`hasMetricTypes`计算的道具似乎是给定的,但是要测试所计算的属性是否返回`metricTypes`的长度, `metricTypes`测试 Vue 库本身. 除了将其添加到测试套件之外,这没有任何价值. 最好以用户与之交互的方式对其进行测试. 大概通过模板. + +请注意这些测试,因为它们只会使更新逻辑变得比所需的更加脆弱和乏味. 其他库也是如此. + +在[前端单元测试部分中](testing_levels.html#frontend-unit-tests)可以找到更多示例. + +### Don’t test your mock[](#dont-test-your-mock "Permalink") + +另一个常见的陷阱是规范最终验证了该模拟程序是否正常运行. 如果使用模拟,则模拟应支持测试,但不应成为测试的目标. + +**Bad:** + +``` +const spy = jest.spyOn(idGenerator, 'create') +spy.mockImplementation = () = '1234' + +expect(idGenerator.create()).toBe('1234') +``` + +**Good:** + +``` +const spy = jest.spyOn(idGenerator, 'create') +spy.mockImplementation = () = '1234' + +// Actually focusing on the logic of your component and just leverage the controllable mocks output +expect(wrapper.find('div').html()).toBe('<div id="1234">...</div>') +``` + +### Follow the user[](#follow-the-user "Permalink") + +在繁重的组件环境中,单元测试和集成测试之间的界限可能非常模糊. 最重要的准则如下: + +* 编写干净的单元测试,以孤立的方式测试复杂的逻辑部分是否具有实际价值,以防止将来被破坏 +* 否则,请尝试将规格写得尽可能接近用户的需求 + +例如,与手动调用方法并验证数据结构或计算的属性相比,使用生成的标记来触发按钮单击并验证相应更改的标记更好. 在测试通过并提供错误的安全感的同时,总是有偶然破坏用户流的机会. + +## Common practices[](#common-practices "Permalink") + +接下来,您会发现一些通用的常规做法,它们将作为我们测试套件的一部分. 如果您发现不遵循本指南的内容,最好立即进行修复. + +### How to query DOM elements[](#how-to-query-dom-elements "Permalink") + +当涉及到测试中的 DOM 元素查询时,最好以唯一且语义上为目标的元素. 有时这无法切实可行. 在这些情况下,添加测试属性以简化选择器可能是最佳选择. + +优选地,在使用`@vue/test-utils`进行组件测试时,您应该使用组件本身来查询子组件. 这有助于强制执行该组件的各个单元测试可以涵盖的特定行为. 否则,请尝试使用: + +* 语义属性(例如`name` (还验证`name`是否正确设置) +* 一个`data-testid`属性( [由`@vue/test-utils`维护者推荐](https://github.com/vuejs/vue-test-utils/issues/1498#issuecomment-610133465) ) +* Vue `ref` (如果使用`@vue/test-utils` ) + +Examples: + +``` +it('exists', () => { + // Good + wrapper.find(FooComponent); + wrapper.find('input[name=foo]'); + wrapper.find('[data-testid="foo"]'); + wrapper.find({ ref: 'foo'}); + + // Bad + wrapper.find('.js-foo'); + wrapper.find('.btn-primary'); + wrapper.find('.qa-foo-component'); + wrapper.find('[data-qa-selector="foo"]'); +}); +``` + +不建议您仅添加`.js-*`类用于测试目的. 仅当没有其他可行的选择时才这样做. + +除 QA 端到端测试外,请勿将`.qa-*`类或`data-qa-selector`属性用于任何测试. + +### Naming unit tests[](#naming-unit-tests "Permalink") + +在编写描述测试块以测试特定功能/方法时,请使用方法名称作为描述块名称. + +``` +// Good +describe('methodName', () => { + it('passes', () => { + expect(true).toEqual(true); + }); +}); + +// Bad +describe('#methodName', () => { + it('passes', () => { + expect(true).toEqual(true); + }); +}); + +// Bad +describe('.methodName', () => { + it('passes', () => { + expect(true).toEqual(true); + }); +}); +``` + +### Testing promises[](#testing-promises "Permalink") + +在测试 Promises 时,应始终确保测试是异步的并且拒绝被处理. 现在可以在测试套件中使用`async/await`语法: + +``` +it('tests a promise', async () => { + const users = await fetchUsers() + expect(users.length).toBe(42) +}); + +it('tests a promise rejection', async () => { + expect.assertions(1); + try { + await user.getUserName(1); + } catch (e) { + expect(e).toEqual({ + error: 'User with 1 not found.', + }); + } +}); +``` + +您也可以使用 Promise 链. 在这种情况下,您可以利用`done`回调和`done.fail`发生错误. 以下是一些示例: + +``` +// Good +it('tests a promise', done => { + promise + .then(data => { + expect(data).toBe(asExpected); + }) + .then(done) + .catch(done.fail); +}); + +// Good +it('tests a promise rejection', done => { + promise + .then(done.fail) + .catch(error => { + expect(error).toBe(expectedError); + }) + .then(done) + .catch(done.fail); +}); + +// Bad (missing done callback) +it('tests a promise', () => { + promise.then(data => { + expect(data).toBe(asExpected); + }); +}); + +// Bad (missing catch) +it('tests a promise', done => { + promise + .then(data => { + expect(data).toBe(asExpected); + }) + .then(done); +}); + +// Bad (use done.fail in asynchronous tests) +it('tests a promise', done => { + promise + .then(data => { + expect(data).toBe(asExpected); + }) + .then(done) + .catch(fail); +}); + +// Bad (missing catch) +it('tests a promise rejection', done => { + promise + .catch(error => { + expect(error).toBe(expectedError); + }) + .then(done); +}); +``` + +### Manipulating Time[](#manipulating-time "Permalink") + +有时我们必须测试时间敏感的代码. 例如,每隔 X 秒或类似的时间运行一次重复发生的事件. 在这里,您将找到一些应对策略: + +#### `setTimeout()` / `setInterval()` in application[](#settimeout--setinterval-in-application "Permalink") + +如果应用程序本身正在等待一段时间,请模拟等待. 在 Jest 中[,默认情况下](https://gitlab.com/gitlab-org/gitlab/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47)已[完成](https://gitlab.com/gitlab-org/gitlab/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47)此[操作](https://gitlab.com/gitlab-org/gitlab/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47) (另请参见[Jest Timer Mocks](https://jestjs.io/docs/en/timer-mocks) ). 在 Karma 中,您可以使用[Jasmine 模拟时钟](https://jasmine.github.io/api/2.9/Clock.html) . + +``` +const doSomethingLater = () => { + setTimeout(() => { + // do something + }, 4000); +}; +``` + +**在:** + +``` +it('does something', () => { + doSomethingLater(); + jest.runAllTimers(); + + expect(something).toBe('done'); +}); +``` + +**在业力中:** + +``` +it('does something', () => { + jasmine.clock().install(); + + doSomethingLater(); + jasmine.clock().tick(4000); + + expect(something).toBe('done'); + jasmine.clock().uninstall(); +}); +``` + +### Waiting in tests[](#waiting-in-tests "Permalink") + +有时,测试需要等待应用程序中的某些事情发生后才能继续. 避免使用[`setTimeout`](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)因为它会使等待的原因不清楚,如果在 Karma 中使用的时间大于零,则会减慢我们的测试套件的速度. 而是使用以下方法之一. + +#### Promises and Ajax calls[](#promises-and-ajax-calls "Permalink") + +注册处理程序函数以等待`Promise`被解决. + +``` +const askTheServer = () => { + return axios + .get('/endpoint') + .then(response => { + // do something + }) + .catch(error => { + // do something else + }); +}; +``` + +**在:** + +``` +it('waits for an Ajax call', async () => { + await askTheServer() + expect(something).toBe('done'); +}); +``` + +**在业力中:** + +``` +it('waits for an Ajax call', done => { + askTheServer() + .then(() => { + expect(something).toBe('done'); + }) + .then(done) + .catch(done.fail); +}); +``` + +如果您无法将处理程序注册到`Promise` ,例如因为它是在同步 Vue 生命周期挂钩中执行的,请查看[waitFor](#wait-until-axios-requests-finish)帮助器,或者您可以刷新所有待处理的`Promise` : + +**在:** + +``` +it('waits for an Ajax call', () => { + synchronousFunction(); + jest.runAllTicks(); + + expect(something).toBe('done'); +}); +``` + +#### Vue rendering[](#vue-rendering "Permalink") + +要等到重新渲染 Vue 组件后,请使用等效的[`Vue.nextTick()`](https://vuejs.org/v2/api/#Vue-nextTick)或`vm.$nextTick()` . + +**在:** + +``` +it('renders something', () => { + wrapper.setProps({ value: 'new value' }); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.text()).toBe('new value'); + }); +}); +``` + +**in Karma:** + +``` +it('renders something', done => { + wrapper.setProps({ value: 'new value' }); + + wrapper.vm + .$nextTick() + .then(() => { + expect(wrapper.text()).toBe('new value'); + }) + .then(done) + .catch(done.fail); +}); +``` + +#### Events[](#events "Permalink") + +如果应用程序触发了您需要在测试中等待的事件,请注册一个包含断言的事件处理程序: + +``` +it('waits for an event', done => { + eventHub.$once('someEvent', eventHandler); + + someFunction(); + + function eventHandler() { + expect(something).toBe('done'); + done(); + } +}); +``` + +在 Jest 中,您还可以使用`Promise` : + +``` +it('waits for an event', () => { + const eventTriggered = new Promise(resolve => eventHub.$once('someEvent', resolve)); + + someFunction(); + + return eventTriggered.then(() => { + expect(something).toBe('done'); + }); +}); +``` + +### Ensuring that tests are isolated[](#ensuring-that-tests-are-isolated "Permalink") + +测试通常以一种模式进行架构,该模式要求重复设置并破坏被测组件. 这是通过使用`beforeEach`和`afterEach`挂钩完成的. + +Example + +``` + let wrapper; + + beforeEach(() => { + wrapper = mount(Component); + }); + + afterEach(() => { + wrapper.destroy(); + }); +``` + +最初查看此内容时,您会怀疑该组件是在每次测试之前设置的,然后在以后进行了细分,从而在测试之间提供了隔离. + +但是,这并不是完全正确的,因为`destroy`方法不会删除`wrapper`对象上所有已突变的东西. 对于功能组件,destroy 仅从文档中删除呈现的 DOM 元素. + +In order to ensure that a clean wrapper object and DOM are being used in each test, the breakdown of the component should rather be performed as follows: + +``` + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); +``` + +另请参见[有关`destroy`](https://vue-test-utils.vuejs.org/api/wrapper/#destroy)的[Vue Test Utils 文档](https://vue-test-utils.vuejs.org/api/wrapper/#destroy) . + +### Jest best practices[](#jest-best-practices "Permalink") + +在 GitLab 13.2 中[引入](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34209) . + +#### Prefer `toBe` over `toEqual` when comparing primitive values[](#prefer-tobe-over-toequal-when-comparing-primitive-values "Permalink") + +[`toBe`](https://jestjs.io/docs/en/expect#tobevalue) [`toEqual`](https://jestjs.io/docs/en/expect#toequalvalue)匹配者. 由于[`toBe`](https://jestjs.io/docs/en/expect#tobevalue)使用[`Object.is`](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)比较值,因此(默认情况下)比使用`toEqual` . 尽管后者最终将回退以利用[`Object.is`](https://github.com/facebook/jest/blob/master/packages/expect/src/jasmineUtils.ts#L91)获得原始值,但仅应在需要比较复杂对象的情况下使用它. + +Examples: + +``` +const foo = 1; + +// good +expect(foo).toBe(1); + +// bad +expect(foo).toEqual(1); +``` + +#### Prefer more befitting matchers[](#prefer-more-befitting-matchers "Permalink") + +Jest 提供了有用的匹配器,例如`toHaveLength`或`toBeUndefined`以使您的测试更具可读性并产生更易理解的错误消息. 查看他们的文档以获取[匹配器](https://jestjs.io/docs/en/expect#methods)的[完整列表](https://jestjs.io/docs/en/expect#methods) . + +Examples: + +``` +const arr = [1, 2]; + +// prints: +// Expected length: 1 +// Received length: 2 +expect(arr).toHaveLength(1); + +// prints: +// Expected: 1 +// Received: 2 +expect(arr.length).toBe(1); + +// prints: +// expect(received).toBe(expected) // Object.is equality +// Expected: undefined +// Received: "bar" +const foo = 'bar'; +expect(foo).toBe(undefined); + +// prints: +// expect(received).toBeUndefined() +// Received: "bar" +const foo = 'bar'; +expect(foo).toBeUndefined(); +``` + +#### Avoid using `toBeTruthy` or `toBeFalsy`[](#avoid-using-tobetruthy-or-tobefalsy "Permalink") + +Jest 还提供以下匹配器: `toBeTruthy`和`toBeFalsy` . 我们不应该使用它们,因为它们会使测试变弱并产生假阳性结果. + +例如,当`someBoolean === null`以及`someBoolean === false`时,会通过`expect(someBoolean).toBeFalsy()` . + +#### Tricky `toBeDefined` matcher[](#tricky-tobedefined-matcher "Permalink") + +Jest 有一个棘手的`toBeDefined`匹配器,它可能会产生假阳性测试. 因为它仅[验证](https://github.com/facebook/jest/blob/master/packages/expect/src/matchers.ts#L204) `undefined`的给定值. + +``` +// good +expect(wrapper.find('foo').exists()).toBe(true); + +// bad +// if finder returns null, the test will pass +expect(wrapper.find('foo')).toBeDefined(); +``` + +#### Avoid using `setImmediate`[](#avoid-using-setimmediate "Permalink") + +尝试避免使用`setImmediate` . `setImmediate`是一个临时解决方案,可在 I / O 完成后运行您的回调. 而且它不是 Web API 的一部分,因此,我们在单元测试中以 NodeJS 环境为目标. + +代替`setImmediate` ,使用`jest.runAllTimers`或`jest.runOnlyPendingTimers`来运行暂挂计时器. 当代码中有`setInterval`时,后者很有用. **请记住:**我们的 Jest 配置使用假计时器. + +## Factories[](#factories "Permalink") + +TBU + +## Mocking Strategies with Jest[](#mocking-strategies-with-jest "Permalink") + +### Stubbing and Mocking[](#stubbing-and-mocking "Permalink") + +Jasmine 提供存根和模拟功能. 在 Karma 和 Jest 中,如何使用它有一些细微的差异. + +存根或间谍通常是同义词. 在 Jest 中,使用`.spyOn`方法非常容易. [官方文档](https://jestjs.io/docs/en/jest-object#jestspyonobject-methodname)更具挑战性的部分是模拟,可用于功能甚至依赖项. + +### Manual module mocks[](#manual-module-mocks "Permalink") + +手动模拟用于模拟整个 Jest 环境中的模块. 这是一个功能非常强大的测试工具,它通过模拟出在我们的测试环境中不容易使用的模块来帮助简化单元测试. + +> **警告:**如果不应在每个规范中始终采用模拟,则不要使用手动模拟(即,仅少数规范需要使用). 而是考虑在相关规范文件中使用[`jest.mock(..)`](https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options) (或类似的[`jest.mock(..)`](https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options)功能). + +#### Where should I put manual mocks?[](#where-should-i-put-manual-mocks "Permalink") + +Jest 通过将模拟放置在源模块旁边的`__mocks__/`目录(例如`app/assets/javascripts/ide/__mocks__` )中来支持[手动模块](https://jestjs.io/docs/en/manual-mocks)模拟. **不要这样** 我们希望将所有与测试相关的代码保存在一个地方( `spec/`文件夹). + +如果`node_modules`软件包需要手动模拟,请使用`spec/frontend/__mocks__`文件夹. 这是[`monaco-editor`软件包](https://gitlab.com/gitlab-org/gitlab/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js#L1)的[Jest 模拟](https://gitlab.com/gitlab-org/gitlab/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js#L1)示例. + +如果 CE 模块需要手动模拟,请将其放在`spec/frontend/mocks/ce` . + +* `spec/frontend/mocks/ce`文件将从`app/assets/javascripts`模拟相应的 CE 模块,从而镜像源模块的路径. + * 示例: `spec/frontend/mocks/ce/lib/utils/axios_utils`将模拟模块`~/lib/utils/axios_utils` . +* 我们尚不支持模拟 EE 模块. +* 如果找到了不存在源模块的模拟,则测试套件将失败. 目前尚不支持"虚拟"模拟或与源模块没有 1 对 1 关联的模拟. + +#### Manual mock examples[](#manual-mock-examples "Permalink") + +* 模拟[`mocks/axios_utils`](https://gitlab.com/gitlab-org/gitlab/blob/bd20aeb64c4eed117831556c54b40ff4aee9bfd1/spec/frontend/mocks/ce/lib/utils/axios_utils.js#L1)此模拟很有用,因为我们不希望任何未经模拟的请求通过任何测试. 另外,我们能够注入一些测试助手,例如`axios.waitForAll` . +* [`__mocks__/mousetrap/index.js`](https://gitlab.com/gitlab-org/gitlab/blob/cd4c086d894226445be9d18294a060ba46572435/spec/frontend/__mocks__/mousetrap/index.js#L1)此模拟很有用,因为该模块本身使用 webpack 可以理解的 AMD 格式,但与玩笑的环境不兼容. 该模拟不会删除任何行为,仅提供与 es6 兼容的包装器. +* [`__mocks__/monaco-editor/index.js`](https://gitlab.com/gitlab-org/gitlab/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js) - This mock is helpful because the Monaco package is completely incompatible in a Jest environment. In fact, webpack requires a special loader to make it work. This mock simply makes this package consumable by Jest. + +### Keep mocks light[](#keep-mocks-light "Permalink") + +全局模拟会引入魔术,并且从技术上讲可以减少测试的覆盖范围. 当嘲笑被视为有利可图时: + +* 保持模拟简短而集中. +* 请在模拟中留下为什么有必要的顶级评论. + +### Additional mocking techniques[](#additional-mocking-techniques "Permalink") + +请查阅[官方的 Jest 文档](https://jestjs.io/docs/en/jest-object#mock-modules) ,以获取有关可用模拟功能的完整概述. + +## Running Frontend Tests[](#running-frontend-tests "Permalink") + +要运行前端测试,您需要以下命令: + +* `rake frontend:fixtures` (re-)generates [fixtures](#frontend-test-fixtures). +* `yarn test`执行测试. +* `yarn jest`执行 Jest 测试. + +只要固定装置不变, `yarn test`就足够了(并节省了一些时间). + +### Live testing and focused testing – Jest[](#live-testing-and-focused-testing----jest "Permalink") + +在测试套件上工作时,您可能希望以监视模式运行这些规范,因此它们会在每次保存时自动重新运行. + +``` +# Watch and rerun all specs matching the name icon +yarn jest --watch icon + +# Watch and rerun one specifc file +yarn jest --watch path/to/spec/file.spec.js +``` + +您也可以在不使用`--watch`标志的情况下运行一些重点测试 + +``` +# Run specific jest file +yarn jest ./path/to/local_spec.js +# Run specific jest folder +yarn jest ./path/to/folder/ +# Run all jest files which path contain term +yarn jest term +``` + +### Live testing and focused testing – Karma[](#live-testing-and-focused-testing----karma "Permalink") + +业力允许类似的东西,但是成本更高. + +用`yarn run karma-start`运行 Karma 将编译 JavaScript 资产并在`http://localhost:9876/`上运行服务器,在该服务器上它将自动在连接到它的任何浏览器上运行测试. 您可以一次在多个浏览器上输入该 URL,以使其在每个浏览器上并行运行测试. + +当 Karma 运行时,您所做的任何更改都会立即触发**整个测试套件**的重新编译和重新**测试** ,因此您可以立即查看是否使用所做的更改破坏了测试. 您可以使用[针对 Jasmine 的](https://jasmine.github.io/2.5/focused_specs.html)测试或排除测试(使用`fdescribe`或`xdescribe` )来使 Karma 仅在您使用特定功能时运行所需的测试,但是请确保在提交代码时删除这些指令. + +通过使用参数`--filter-spec`或 short `-f`过滤运行测试,也可以仅在特定的文件夹或文件上运行 Karma: + +``` +# Run all files +yarn karma-start +# Run specific spec files +yarn karma-start --filter-spec profile/account/components/update_username_spec.js +# Run specific spec folder +yarn karma-start --filter-spec profile/account/components/ +# Run all specs which path contain vue_shared or vie +yarn karma-start -f vue_shared -f vue_mr_widget +``` + +您还可以使用 glob 语法来匹配文件. 请记住在引号周围加上引号,否则您的 shell 可能会将其拆分为多个参数: + +``` +# Run all specs named `file_spec` within the IDE subdirectory +yarn karma -f 'spec/javascripts/ide/**/file_spec.js' +``` + +## Frontend test fixtures[](#frontend-test-fixtures "Permalink") + +添加到 HAML 模板(在`app/views/` )或向后端发出 Ajax 请求的代码具有要求后端提供 HTML 或 JSON 的测试. 这些测试的夹具位于: + +* `spec/frontend/fixtures/` ,用于在 CE 中运行测试. +* `ee/spec/frontend/fixtures/` ,用于在 EE 中运行测试. + +灯具文件位于: + +* Karma 测试套件由[jasmine-jquery 提供](https://github.com/velesin/jasmine-jquery) . +* 开玩笑地使用`spec/frontend/helpers/fixtures.js` . + +以下是适用于 Karma 和 Jest 的测试示例: + +``` +it('makes a request', () => { + const responseBody = getJSONFixture('some/fixture.json'); // loads spec/frontend/fixtures/some/fixture.json + axiosMock.onGet(endpoint).reply(200, responseBody); + + myButton.click(); + + // ... +}); + +it('uses some HTML element', () => { + loadFixtures('some/page.html'); // loads spec/frontend/fixtures/some/page.html and adds it to the DOM + + const element = document.getElementById('#my-id'); + + // ... +}); +``` + +HTML 和 JSON 固定装置是使用 RSpec 从后端视图和控制器生成的(请参阅`spec/frontend/fixtures/*.rb` ). + +对于每个灯具, `response`变量的内容存储在输出文件中. 如果测试标记为`type: :request`或`type: :controller`则此变量将自动设置. 可以使用`bin/rake frontend:fixtures`命令来重新生成`bin/rake frontend:fixtures`但是您也可以单独生成它们,例如`bin/rspec spec/frontend/fixtures/merge_requests.rb` . 创建新的固定装置时,通常有必要在`(ee/)spec/controllers/`或`(ee/)spec/requests/`查看端点的相应测试. + +## Data-driven tests[](#data-driven-tests "Permalink") + +与[RSpec 的参数化测试](best_practices.html#table-based--parameterized-tests)类似,Jest 支持以下数据驱动的测试: + +* 使用[`test.each`](https://jestjs.io/docs/en/api#testeachtable-name-fn-timeout)单独测试(别名为`it.each` ). +* 使用[`describe.each`](https://jestjs.io/docs/en/api#describeeachtable-name-fn-timeout)的测试组. + +这些对于减少测试中的重复很有用. 每个选项都可以采用数据值数组或带标签的模板文字. + +例如: + +``` +// function to test +const icon = status => status ? 'pipeline-passed' : 'pipeline-failed' +const message = status => status ? 'pipeline-passed' : 'pipeline-failed' + +// test with array block +it.each([ + [false, 'pipeline-failed'], + [true, 'pipeline-passed'] +])('icon with %s will return %s', + (status, icon) => { + expect(renderPipeline(status)).toEqual(icon) + } +); +``` + +``` +// test suite with tagged template literal block +describe.each` + status | icon | message ${false} | ${'pipeline-failed'} | ${'Pipeline failed - boo-urns'} ${true} | ${'pipeline-passed'} | ${'Pipeline succeeded - win!'} `('pipeline component', ({ status, icon, message }) => { + it(`returns icon ${icon} with status ${status}`, () => { + expect(icon(status)).toEqual(message) + }) + + it(`returns message ${message} with status ${status}`, () => { + expect(message(status)).toEqual(message) + }) +}); +``` + +## Gotchas[](#gotchas "Permalink") + +### RSpec errors due to JavaScript[](#rspec-errors-due-to-javascript "Permalink") + +默认情况下,RSpec 单元测试不会在无头浏览器中运行 JavaScript,而仅依赖于检查 rails 生成的 HTML. + +如果集成测试依赖 JavaScript 才能正确运行,则需要确保将规范配置为在运行测试时启用 JavaScript. 如果不这样做,您会看到规范运行器发出的模糊错误消息. + +To enable a JavaScript driver in an `rspec` test, add `:js` to the individual spec or the context block containing multiple specs that need JavaScript enabled: + +``` +# For one spec +it 'presents information about abuse report', :js do + # assertions... +end + +describe "Admin::AbuseReports", :js do + it 'presents information about abuse report' do + # assertions... + end + it 'shows buttons for adding to abuse report' do + # assertions... + end +end +``` + +## Overview of Frontend Testing Levels[](#overview-of-frontend-testing-levels "Permalink") + +有关前端测试级别的主要信息,请参见" [测试级别"页面](testing_levels.html) . + +与前端开发相关的测试可以在以下位置找到: + +* `spec/javascripts/` ,用于业力测试 +* `spec/frontend/` ,用于 Is 测试 +* `spec/features/` ,用于 RSpec 测试 + +RSpec 运行完整的[功能测试](testing_levels.html#frontend-feature-tests) ,而 Jest 和 Karma 目录包含[前端单元测试](testing_levels.html#frontend-unit-tests) , [前端组件测试](testing_levels.html#frontend-component-tests)和[前端集成测试](testing_levels.html#frontend-integration-tests) . + +`spec/javascripts/`所有测试最终都将迁移到`spec/frontend/` (另请参见[#52483](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52483) ). + +在 2018 年 5 月之前, `features/`还包含 Spinach 运行的功能测试. 这些测试已于 2018 年 5 月从代码库中删除( [#23036](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/23036) ). + +另请参阅[有关测试 Vue 组件的说明](../fe_guide/vue.html#testing-vue-components) . + +## Test helpers[](#test-helpers "Permalink") + +### Vuex Helper: `testAction`[](#vuex-helper-testaction "Permalink") + +根据[官方文档](https://vuex.vuejs.org/guide/testing.html) ,我们提供了一个帮助程序,可以简化测试操作: + +``` +testAction( + actions.actionName, // action + { }, // params to be passed to action + state, // state + [ + { type: types.MUTATION}, + { type: types.MUTATION_1, payload: {}}, + ], // mutations committed + [ + { type: 'actionName', payload: {}}, + { type: 'actionName1', payload: {}}, + ] // actions dispatched + done, +); +``` + +在[`spec/javascripts/ide/stores/actions_spec.jsspec/javascripts/ide/stores/actions_spec.js`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/javascripts/ide/stores/actions_spec.js) . + +### Wait until Axios requests finish[](#wait-until-axios-requests-finish "Permalink") + +The Axios Utils mock module located in `spec/frontend/mocks/ce/lib/utils/axios_utils.js` contains two helper methods for Jest tests that spawn HTTP requests. These are very useful if you don’t have a handle to the request’s Promise, for example when a Vue component does a request as part of its life cycle. + +* `waitFor(url, callback)` :对`url`的请求完成后(成功或失败)运行`callback` . +* `waitForAll(callback)` :所有未完成的请求完成后,运行`callback` . 如果没有待处理的请求,则在下一个刻度上运行`callback` . + +这两个函数运行`callback` (使用请求结束后的下一个滴答`setImmediate()`以允许任何`.then()`或`.catch()`处理程序来运行. + +## Testing with older browsers[](#testing-with-older-browsers "Permalink") + +某些回归仅影响特定的浏览器版本. 我们可以按照以下步骤使用 Firefox 或 BrowserStack 在特定的浏览器中安装和测试: + +### BrowserStack[](#browserstack "Permalink") + +[BrowserStack](https://www.browserstack.com/)可以测试 1200 多种移动设备和浏览器. 您可以直接通过[实时应用程序](https://www.browserstack.com/live)使用它,也可以安装[chrome 扩展程序](https://chrome.google.com/webstore/detail/browserstack/nkihdmlheodkdfojglpcjjmioefjahjb)以便于访问. 使用保存在 GitLab [共享 1Password 帐户](https://about.gitlab.com/handbook/security/#1password-guide)的**Engineering**库中的凭据登录到 BrowserStack. + +### Firefox[](#firefox "Permalink") + +#### macOS[](#macos "Permalink") + +您可以从发布的 FTP 服务器[https://ftp.mozilla.org/pub/firefox/releases/](https://ftp.mozilla.org/pub/firefox/releases/)下载任何较旧版本的 Firefox: + +1. 从网站上选择一个版本,在本例中为`50.0.1` . +2. 转到 mac 文件夹. +3. 选择您喜欢的语言,您将在其中找到 DMG 软件包并下载. +4. 将应用程序拖放到"应用`Applications`文件夹以外的任何其他文件夹中. +5. 将应用程序重命名为`Firefox_Old` . +6. 将应用程序移至"应用`Applications`文件夹. +7. 打开终端,然后运行`/Applications/Firefox_Old.app/Contents/MacOS/firefox-bin -profilemanager`以创建特定于该 Firefox 版本的新配置文件. +8. 创建配置文件后,请退出应用程序,然后像平常一样再次运行它. 现在,您可以使用较旧的 Firefox 版本. + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/docs/629.md b/docs/629.md new file mode 100644 index 0000000000000000000000000000000000000000..15161cce7e05d5229b89748174e8c46db609398c --- /dev/null +++ b/docs/629.md @@ -0,0 +1,37 @@ +# GitLab tests in the Continuous Integration (CI) context + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/ci.html](https://docs.gitlab.com/ee/development/testing_guide/ci.html) + +* [Test suite parallelization on the CI](#test-suite-parallelization-on-the-ci) +* [Monitoring](#monitoring) +* [CI setup](#ci-setup) + +# GitLab tests in the Continuous Integration (CI) context[](#gitlab-tests-in-the-continuous-integration-ci-context "Permalink") + +## Test suite parallelization on the CI[](#test-suite-parallelization-on-the-ci "Permalink") + +我们当前的 CI 并行化设置如下: + +1. 在`prepare`阶段的`retrieve-tests-metadata`作业可确保我们有一个`knapsack/report-master.json`文件: + * 从 S3 提取`knapsack/report-master.json`文件,如果不在此处,则使用`{}`初始化文件. +2. 每个`[rspec|rspec-ee] [unit|integration|system|geo] nm`作业均使用`knapsack rspec`运行,并且应具有均匀分布的测试份额: + * 之所以起作用,是因为"默认情况下传递了所有先前阶段的工件"以来,作业可以访问`knapsack/report-master.json` . + * 作业将自己的报告路径设置为`"knapsack/${TEST_TOOL}_${TEST_LEVEL}_${DATABASE}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json"` . + * 如果背包正在执行任务,则运行的测试文件应列在`Report specs` ,而不是" `Leftover specs` . +3. `update-tests-metadata`作业(仅[在规范项目的](https://gitlab.com/gitlab-org/gitlab)预定管道上运行)将所有`knapsack/rspec*_pg_*.json`文件合并在一起,然后将它们全部合并为一个`knapsack/report-master.json`文件,然后将其上传到 S3. + +之后,下一个管道将使用最新的`knapsack/report-master.json`文件. + +## Monitoring[](#monitoring "Permalink") + +[监视](../performance.html#rspec-profiling) GitLab 测试套件的`master`分支以及名称中包含`rspec-profile`任何分支. + +[公共仪表板](https://redash.gitlab.com/public/dashboards/l1WhHXaxrCWM5Ai9D7YDqHKehq6OU3bx5gssaiWe?org_slug=default)可供所有人查看. 随意查看最慢的测试文件并尝试对其进行改进. + +## CI setup[](#ci-setup "Permalink") + +* [由于性能原因](https://jtway.co/speed-up-your-rails-test-suite-by-6-in-1-line-13fedb869ec4) ,CI 中默认情况下禁用 Rails 日志到`log/test.log` . 要覆盖此设置,请提供`RAILS_ENABLE_TEST_LOG`环境变量. + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/docs/630.md b/docs/630.md new file mode 100644 index 0000000000000000000000000000000000000000..02f0c01438ba4fbf65ef377e75d1efcb6e55b91b --- /dev/null +++ b/docs/630.md @@ -0,0 +1,337 @@ +# Review Apps + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/review_apps.html](https://docs.gitlab.com/ee/development/testing_guide/review_apps.html) + +* [How does it work?](#how-does-it-work) + * [CI/CD architecture diagram](#cicd-architecture-diagram) + * [Detailed explanation](#detailed-explanation) + * [Auto-stopping of Review Apps](#auto-stopping-of-review-apps) +* [QA runs](#qa-runs) +* [Performance Metrics](#performance-metrics) +* [Cluster configuration](#cluster-configuration) + * [Node pools](#node-pools) + * [Helm](#helm) +* [How to](#how-to) + * [Get access to the GCP Review Apps cluster](#get-access-to-the-gcp-review-apps-cluster) + * [Log into my Review App](#log-into-my-review-app) + * [Enable a feature flag for my Review App](#enable-a-feature-flag-for-my-review-app) + * [Find my Review App slug](#find-my-review-app-slug) + * [Run a Rails console](#run-a-rails-console) + * [Dig into a Pod’s logs](#dig-into-a-pods-logs) +* [Diagnosing unhealthy Review App releases](#diagnosing-unhealthy-review-app-releases) + * [Release failed with `ImagePullBackOff`](#release-failed-with-imagepullbackoff) + * [Node count is always increasing (i.e. never stabilizing or decreasing)](#node-count-is-always-increasing-ie-never-stabilizing-or-decreasing) + * [p99 CPU utilization is at 100% for most of the nodes and/or many components](#p99-cpu-utilization-is-at-100-for-most-of-the-nodes-andor-many-components) + * [The `logging/user/events/FailedMount` chart is going up](#the-loggingusereventsfailedmount-chart-is-going-up) + * [Using K9s](#using-k9s) + * [Troubleshoot a pending `dns-gitlab-review-app-external-dns` Deployment](#troubleshoot-a-pending-dns-gitlab-review-app-external-dns-deployment) + * [Finding the problem](#finding-the-problem) + * [Solving the problem](#solving-the-problem) + * [Mitigation steps taken to avoid this problem in the future](#mitigation-steps-taken-to-avoid-this-problem-in-the-future) +* [Frequently Asked Questions](#frequently-asked-questions) +* [Other resources](#other-resources) + * [Helpful command line tools](#helpful-command-line-tools) + +# Review Apps[](#review-apps "Permalink") + +Review Apps 由[管道](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6665)自动部署. + +## How does it work?[](#how-does-it-work "Permalink") + +### CI/CD architecture diagram[](#cicd-architecture-diagram "Permalink") + +图 TD A [" build-qa-image,编译生产资产 +(仅适用于规范的默认参考)"]; B [review-build-cng]; C [review-deploy]; D [CNG-mirror]; E [review-qa-smoke]; A-> |一旦准备`阶段已完成| BB -.-> |触发 CNG 镜像管道并等待其完成| DD -.-> |轮询直到完成| BB-> |一旦完成`view-build-cng`工作完成| CC-> |完成"审查-部署"工作| E 子图" 1\. gitlab`prepare` stage"结束子图" 2\. gitlab`review-prepare`阶段" B 结束子图" 3\. gitlab`review` stage" C [" review-deploy + +Helm 使用云部署 Review App +由 CNG 镜像管道构建的本机映像. + +Cloud Native 映像已部署到" review-apps" +Kubernetes(GKE)集群,位于 GCP`gitlab-review-apps`项目中."]结束子图" 4\. gitlab`qa` stage" E [review-qa-smoke + +gitlab-qa 对 Review App 运行冒烟套件.]结束子图" CNG 镜像管道" D>构建了 Cloud Native 图像]; 结束 + +### Detailed explanation[](#detailed-explanation "Permalink") + +1. 在`prepare`阶段的每个[管道](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730)上,都会自动启动[`compile-production-assets`](https://gitlab.com/gitlab-org/gitlab/-/jobs/641770154)作业. + * 完成后, [`review-build-cng`](https://gitlab.com/gitlab-org/gitlab/-/jobs/467724808)作业开始,因为在后续步骤中触发的[`CNG-mirror`](https://gitlab.com/gitlab-org/build/CNG-mirror)管道依赖[`review-build-cng`](https://gitlab.com/gitlab-org/gitlab/-/jobs/467724808) . +2. 完成`compile-production-assets`后, [`review-build-cng`](https://gitlab.com/gitlab-org/gitlab/-/jobs/467724808)作业[将触发](https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/44364657) [`CNG-mirror`](https://gitlab.com/gitlab-org/build/CNG-mirror)项目中[的管道](https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/44364657) . + * 仅当您的 MR 包括[CI 或前端更改时](../pipelines.html#changes-patterns) , `review-build-cng`作业才会自动开始. 在其他情况下,该工作是手动的. + * [`CNG-mirror`](https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/44364657)管道基于[GitLab 管道](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730)的提交创建每个组件(例如`gitlab-rails-ee` , `gitlab-shell` , `gitaly`等)的 Docker 映像,并将它们存储在其[注册表中](https://gitlab.com/gitlab-org/build/CNG-mirror/container_registry) . + * 我们使用[`CNG-mirror`](https://gitlab.com/gitlab-org/build/CNG-mirror)项目,以便`CNG` (Cloud Native GitLab)项目的注册表不会因大量临时 Docker 映像而过载. + * 请注意,官方的 CNG 图像是由`cloud-native-image`作业构建的,该作业仅针对标签运行,并自身触发[`CNG`](https://gitlab.com/gitlab-org/build/CNG)管道. +3. 完成`review-build-cng`后, [`review-deploy`](https://gitlab.com/gitlab-org/gitlab/-/jobs/467724810)作业使用[官方的 GitLab Helm 图表](https://gitlab.com/gitlab-org/charts/gitlab/)将 Review App 部署到 GCP 上的[`review-apps`](https://console.cloud.google.com/kubernetes/clusters/details/us-central1-b/review-apps?project=gitlab-review-apps) Kubernetes 集群. + * 可以在[`scripts/review_apps/review-apps.sh`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/review_apps/review-apps.sh)找到用于部署 Review App 的实际脚本. + * 这些脚本基本上是[我们的官方 Auto DevOps 脚本](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml) ,其中默认的 CNG 映像会被构建并存储在[`CNG-mirror`项目注册表中](https://gitlab.com/gitlab-org/build/CNG-mirror/container_registry)的映像覆盖. + * 由于我们使用的[是官方的 GitLab Helm 图表](https://gitlab.com/gitlab-org/charts/gitlab/) ,这意味着您将为分支机构获得一个专用的环境,该环境非常接近生产环境. +4. 一旦[`review-deploy`](https://gitlab.com/gitlab-org/gitlab/-/jobs/467724810)作业成功,您应该可以使用您的 Review App,这要归功于 MR 小部件与它的直接链接. 要登录 Review App,请参阅"登录我的 Review App?". 下面. + +**补充笔记:** + +* 如果`review-deploy`工作持续失败(请注意,我们已经试了两次),请在发布消息`#g_qe_engineering_productivity`通道和/或创建`~"Engineering Productivity"` `~"ep::review apps"` `~bug`的问题有链接到您的合并请求. 请注意,部署失败可能会揭示合并请求中引入的实际问题(即,这不一定是暂时性失败)! +* 如果`review-qa-smoke`作业仍然失败(请注意,我们已经重试了两次),请检查该作业的日志:您可能会发现合并请求中引入的实际问题. 您也可以下载工件,以查看发生故障时页面的屏幕截图. 如果您找不到失败的原因,或者看起来与更改无关,请在`#quality`频道中发布一条消息和/或创建`#quality`问题,并带有指向合并请求的链接. +* 手动`review-stop`可用于手动停止复查应用,一旦合并请求的分支在合并后被删除,GitLab 也将启动手动`review-stop` . +* 使用[GitLab 的 Kubernetes 集成](../../user/project/clusters/index.html)将 Kubernetes 集群连接到`gitlab`项目. 这基本上允许直接从合并请求窗口小部件链接到 Review App. + +### Auto-stopping of Review Apps[](#auto-stopping-of-review-apps "Permalink") + +借助[环境自动停止](../../ci/environments/index.html#environments-auto-stop)功能,Review Apps 在上次部署后 2 天会自动停止. + +If you need your Review App to stay up for a longer time, you can [pin its environment](../../ci/environments/index.html#auto-stop-example) or retry the `review-deploy` job to update the “latest deployed at” time. + +The `review-cleanup` job that automatically runs in scheduled pipelines (and is manual in merge request) stops stale Review Apps after 5 days, deletes their environment after 6 days, and cleans up any dangling Helm releases and Kubernetes resources after 7 days. + +自动在计划的管道中运行的`review-gcp-cleanup`作业(在合并请求中手动执行)将删除所有未与 Kubernetes 资源一起删除的悬空 GCP 网络资源. + +## QA runs[](#qa-runs "Permalink") + +在`qa`阶段(在`review`阶段之后)的每个[管道](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730)上, `review-qa-smoke`作业都会自动启动,并运行 QA 烟雾套件. + +您也可以手动启动`review-qa-all` :它运行完整的质量检查套件. + +## Performance Metrics[](#performance-metrics "Permalink") + +在每一个[管道](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730)在`qa`阶段, `review-performance`作业自动启动:这项工作确实使用基本的浏览器性能测试[Sitespeed.io 集装箱](../../user/project/merge_requests/browser_performance_testing.html) . + +## Cluster configuration[](#cluster-configuration "Permalink") + +### Node pools[](#node-pools "Permalink") + +目前, `review-apps`集群使用以下节点池进行设置: + +* 具有自动`e2-highcpu-16` (16 vCPU,16 GB 内存)可抢占节点 + +### Helm[](#helm "Permalink") + +使用的 Helm 版本在[`registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-helm3-kubectl1.14`映像中](https://gitlab.com/gitlab-org/gitlab-build-images/-/blob/master/Dockerfile.gitlab-helm3-kubectl1.14#L7)定义,由`review-deploy`和`review-stop`作业使用. + +## How to[](#how-to "Permalink") + +### Get access to the GCP Review Apps cluster[](#get-access-to-the-gcp-review-apps-cluster "Permalink") + +您需要[打开](https://gitlab.com/gitlab-com/access-requests/-/issues/new) `gcp-review-apps-sg` GCP 组[的访问请求(内部链接)](https://gitlab.com/gitlab-com/access-requests/-/issues/new) . 为了加入群组,您必须在访问请求中指定所需的 GCP 角色. 该角色将授予您特定的权限,以便与 Review App 容器进行交互. + +Here are some permissions you may want to have, and the roles that grant them: + +* `container.pods.getLogs` [检索 pod 日志所](#dig-into-a-pods-logs)必需. 由[查看者( `roles/viewer` )](https://cloud.google.com/iam/docs/understanding-roles#kubernetes-engine-roles)授予. +* `container.pods.exec` [运行 Rails 控制台](#run-a-rails-console)所需. 由[Kubernetes Engine 开发人员( `roles/container.developer` )](https://cloud.google.com/iam/docs/understanding-roles#kubernetes-engine-roles)授予. + +### Log into my Review App[](#log-into-my-review-app "Permalink") + +默认用户名是`root` ,其密码可以在名为`gitlab-{ce,ee} Review App's root password`的 1Password 安全注释中找到. + +### Enable a feature flag for my Review App[](#enable-a-feature-flag-for-my-review-app "Permalink") + +1. 打开您的 Review App 并按照上述说明登录. +2. 创建一个个人访问令牌. +3. 使用[Feature 标志 API](../../api/features.html)启用[功能标志](../../api/features.html) . + +### Find my Review App slug[](#find-my-review-app-slug "Permalink") + +1. 打开`review-deploy`作业. +2. 查找" `Checking for previous deployment of review-*` . +3. 例如,对于`Checking for previous deployment of review-qa-raise-e-12chm0`在这种情况下,您的 Review App `Checking for previous deployment of review-qa-raise-e-12chm0`将为`review-qa-raise-e-12chm0` . + +### Run a Rails console[](#run-a-rails-console "Permalink") + +1. 确保首先[具有访问群集](#get-access-to-the-gcp-review-apps-cluster)和`container.pods.exec`权限的权限. +2. [根据您的 Review App](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps) `review-qa-raise-e-12chm0` [过滤工作量](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps) ,例如`review-qa-raise-e-12chm0` . +3. 查找并打开`task-runner`部署,例如`review-qa-raise-e-12chm0-task-runner` . +4. 单击"托管窗格"部分中的 Pod,例如`review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz` . +5. 点击`KUBECTL`下拉菜单,然后`Exec` - > `task-runner` . +6. 从默认命令`-it -- gitlab-rails console` `-c task-runner -- ls`替换为`-it -- gitlab-rails console` ,或者 + * 运行`kubectl exec --namespace review-apps review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz -it -- gitlab-rails console`和 + * 用您的 Pod 名称替换`review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz` . + +### Dig into a Pod’s logs[](#dig-into-a-pods-logs "Permalink") + +1. 确保首先[有权访问集群](#get-access-to-the-gcp-review-apps-cluster)和`container.pods.getLogs`权限. +2. [根据您的 Review App](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps) `review-qa-raise-e-12chm0` [过滤工作量](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps) ,例如`review-qa-raise-e-12chm0` . +3. 查找并打开`migrations`部署,例如`review-qa-raise-e-12chm0-migrations.1` . +4. 单击"托管窗格"部分中的 Pod,例如`review-qa-raise-e-12chm0-migrations.1-nqwtx` . +5. 单击`Container logs`链接. + +## Diagnosing unhealthy Review App releases[](#diagnosing-unhealthy-review-app-releases "Permalink") + +如果[Review App Stability](https://app.periscopedata.com/app/gitlab/496118/Engineering-Productivity-Sandbox?widget=6690556&udv=785399)下降,则可能表明[Review](https://app.periscopedata.com/app/gitlab/496118/Engineering-Productivity-Sandbox?widget=6690556&udv=785399) `review-apps-ce/ee`集群不健康. 领先的指标可能是导致重新启动的运行状况检查失败或 Review App 部署的多数失败. + +[Review Apps Overview 仪表板可](https://console.cloud.google.com/monitoring/classic/dashboards/6798952013815386466?project=gitlab-review-apps&timeDomain=1d)帮助确定群集上的负载峰值,以及节点是否有问题或整个群集是否趋于不正常. + +### Release failed with `ImagePullBackOff`[](#release-failed-with-imagepullbackoff "Permalink") + +**潜在原因:** + +如果看到`ImagePullBackoff`状态,请检查缺少的 Docker 映像. + +**在哪里寻找进一步的调试:** + +要检查是否已创建 Docker 映像,请运行以下 Docker 命令: + +``` +`DOCKER_CLI_EXPERIMENTAL=enabled docker manifest repository:tag` +``` + +此命令的输出指示 Docker 映像是否存在. 例如: + +``` +DOCKER_CLI_EXPERIMENTAL=enabled docker manifest inspect registry.gitlab.com/gitlab-org/build/cng-mirror/gitlab-rails-ee:39467-allow-a-release-s-associated-milestones-to-be-edited-thro +``` + +如果 Docker 映像不存在: + +* 验证`helm upgrade --install`命令中的`image.repository`和`image.tag`选项是否与 CNG-mirror 管道使用的存储库名称匹配. +* 在`review-build-cng`作业中进一步查看相应的下游 CNG 镜像管道. + +### Node count is always increasing (i.e. never stabilizing or decreasing)[](#node-count-is-always-increasing-ie-never-stabilizing-or-decreasing "Permalink") + +**潜在原因:** + +这可能表明`review-cleanup`作业未能清除过时的审查应用和 Kubernetes 资源. + +**在哪里寻找进一步的调试:** + +查看最新的`review-cleanup`作业日志,并确定是否存在任何意外故障. + +### p99 CPU utilization is at 100% for most of the nodes and/or many components[](#p99-cpu-utilization-is-at-100-for-most-of-the-nodes-andor-many-components "Permalink") + +**潜在原因:** + +这可能表明 Helm 无法部署 Review Apps. 当 Helm 有很多`FAILED`版本发布时,CPU 利用率似乎正在增加,这可能是由于 Helm 或 Kubernetes 试图重新创建组件所致. + +**在哪里寻找进一步的调试:** + +查看最近的`review-deploy`作业日志. + +**有用的命令:** + +``` +# Identify if node spikes are common or load on specific nodes which may get rebalanced by the Kubernetes scheduler +kubectl top nodes | sort --key 3 --numeric + +# Identify pods under heavy CPU load +kubectl top pods | sort --key 2 --numeric +``` + +### The `logging/user/events/FailedMount` chart is going up[](#the-loggingusereventsfailedmount-chart-is-going-up "Permalink") + +**潜在原因:** + +这可能表明存在太多过时的机密和/或配置图. + +**在哪里寻找进一步的调试:** + +查看[配置列表](https://console.cloud.google.com/kubernetes/config?project=gitlab-review-apps)或`kubectl get secret,cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-'` `kubectl get secret,cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-'` . + +怀疑任何超过 5 天的机密或配置图,应将其删除. + +**有用的命令:** + +``` +# List secrets and config maps ordered by created date +kubectl get secret,cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-' + +# Delete all secrets that are 5 to 9 days old +kubectl get secret --sort-by='{.metadata.creationTimestamp}' | grep '^review-' | grep '[5-9]d$' | cut -d' ' -f1 | xargs kubectl delete secret + +# Delete all secrets that are 10 to 99 days old +kubectl get secret --sort-by='{.metadata.creationTimestamp}' | grep '^review-' | grep '[1-9][0-9]d$' | cut -d' ' -f1 | xargs kubectl delete secret + +# Delete all config maps that are 5 to 9 days old +kubectl get cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-' | grep -v 'dns-gitlab-review-app' | grep '[5-9]d$' | cut -d' ' -f1 | xargs kubectl delete cm + +# Delete all config maps that are 10 to 99 days old +kubectl get cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-' | grep -v 'dns-gitlab-review-app' | grep '[1-9][0-9]d$' | cut -d' ' -f1 | xargs kubectl delete cm +``` + +### Using K9s[](#using-k9s "Permalink") + +[K9s](https://github.com/derailed/k9s)是功能强大的命令行仪表板,可让您按标签过滤. 这可以帮助确定趋势超过[审阅应用程序资源请求的应用程序](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/review_apps/base-config.yaml) . Kubernetes 将根据资源请求将 Pod 调度到节点,并允许 CPU 使用量达到上限. + +* 在 K9s 中,您可以通过输入`/`字符来排序或添加过滤器 + * `-lrelease=<review-app-slug>` -过滤所有发布的 Pod. 这有助于确定单个部署中存在的问题 + * `-lapp=<app>` -筛选特定应用程序的所有 pod. 这有助于确定应用程序的资源使用情况. +* 您可以滚动到 Kubernetes 资源并按`d` (描述), `s` (shell), `l` (日志)进行更深入的检查 + +[![K9s](img/281606a988de9b8e23469c0de4e22062.png)](img/k9s.png) + +### Troubleshoot a pending `dns-gitlab-review-app-external-dns` Deployment[](#troubleshoot-a-pending-dns-gitlab-review-app-external-dns-deployment "Permalink") + +#### Finding the problem[](#finding-the-problem "Permalink") + +[过去](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62834) ,发生了`dns-gitlab-review-app-external-dns`部署处于挂起状态的情况,有效地阻止了所有 Review App 分配 DNS 记录,从而使它们无法通过域名访问. + +反过来,这阻止了 Review App 的其他组件正常启动(例如`gitlab-runner` ). + +经过一番挖掘后,我们发现在使用`systemd-mount`瞬时作用域(例如 pod)执行新安装时,新安装失败: + +``` +MountVolume.SetUp failed for volume "dns-gitlab-review-app-external-dns-token-sj5jm" : mount failed: exit status 1 +Mounting command: systemd-run +Mounting arguments: --description=Kubernetes transient mount for /var/lib/kubelet/pods/06add1c3-87b4-11e9-80a9-42010a800107/volumes/kubernetes.io~secret/dns-gitlab-review-app-external-dns-token-sj5jm --scope -- mount -t tmpfs tmpfs /var/lib/kubelet/pods/06add1c3-87b4-11e9-80a9-42010a800107/volumes/kubernetes.io~secret/dns-gitlab-review-app-external-dns-token-sj5jm +Output: Failed to start transient scope unit: Connection timed out +``` + +这可能是因为 GitLab 图表创建了 67 个资源,导致在基础 GCP 节点上创建了许多安装点. + +在[根本的问题似乎是一个`systemd`错误](https://github.com/kubernetes/kubernetes/issues/57345#issuecomment-359068048)是固定在`systemd` `v237` . 不幸的是,我们的 GCP 节点当前正在使用`v232` . + +记录下来,找出此问题的调试步骤是: + +1. 将 kubectl 上下文切换到 review-apps-ce(我们建议使用[kubectx](https://github.com/ahmetb/kubectx/) ) +2. `kubectl get pods | grep dns` +3. `kubectl describe pod <pod name>`并确认确切的错误消息 +4. 在兔子洞中找到[相关的 Kubernetes 错误报告后](https://github.com/kubernetes/kubernetes/issues/57345) ,在网上搜索确切的错误消息 +5. 通过 GCP 控制台通过 SSH 访问节点( **计算机引擎> VM 实例,**然后单击`dns-gitlab-review-app-external-dns` pod 运行的节点的" SSH"按钮) +6. In the node: `systemctl --version` => `systemd 232` +7. 收集更多信息: + * `mount | grep kube | wc -l` `mount | grep kube | wc -l` =>例如 290 + * `systemctl list-units --all | grep -i var-lib-kube | wc -l` `systemctl list-units --all | grep -i var-lib-kube | wc -l` =>例如 142 +8. 检查多少个 Pod 处于不良状态: + * 获取运行给定节点的所有 Pod: `kubectl get pods --field-selector=spec.nodeName=NODE_NAME` + * 获取给定节点上的所有`Running` pods: `kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep Running` `kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep Running` + * 在给定节点上获取所有处于不良状态的 Pod: `kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep -v 'Running' | grep -v 'Completed'` `kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep -v 'Running' | grep -v 'Completed'` + +#### Solving the problem[](#solving-the-problem "Permalink") + +为了解决该问题,我们需要(强制)耗尽一些节点: + +1. 在运行`dns-gitlab-review-app-external-dns` pod 的节点上尝试正常排水,以使 Kubernetes 自动将其移动到另一个节点: `kubectl drain NODE_NAME` +2. 如果那不起作用,您还可以通过删除所有吊舱来强制"排水"节点: `kubectl delete pods --field-selector=spec.nodeName=NODE_NAME` +3. 在节点中: + * 执行`systemctl daemon-reload`以删除无效/无效的单元 + * 如果那不能解决问题,请执行硬重启: `sudo systemctl reboot` +4. 取消封锁所有封锁的节点: `kubectl uncordon NODE_NAME`封锁`kubectl uncordon NODE_NAME` + +同时,由于大多数 Review App 处于损坏状态,因此我们将其删除以清理非`Running` Pod 列表. 以下是一个命令,用于根据其上次部署日期(当前日期为当时的 6 月 6 日)删除 Review Apps, + +``` +helm ls -d | grep "Jun 4" | cut -f1 | xargs helm delete --purge +``` + +#### Mitigation steps taken to avoid this problem in the future[](#mitigation-steps-taken-to-avoid-this-problem-in-the-future "Permalink") + +我们用较小的计算机创建了一个新的节点池,这样一来,将来计算机就不太可能遇到"装载点过多"的问题. + +## Frequently Asked Questions[](#frequently-asked-questions "Permalink") + +**在每次测试运行时触发 CNG 映像生成是否过多? 这将创建数千个未使用的 Docker 映像.** + +> 我们必须从某个地方开始,以后再改进. 另外,我们正在使用 CNG-mirror 项目来存储这些 Docker 映像,以便我们可以在某个时候清除注册表,并使用一个新的,空的注册表. + +**我们如何确保它免受滥用? 应用程序向世界开放,因此我们需要找到一种方法将其限制为仅限我们自己.** + +> This isn’t enabled for forks. + +## Other resources[](#other-resources "Permalink") + +* [Review Apps integration for CE/EE (presentation)](https://docs.google.com/presentation/d/1QPLr6FO4LduROU8pQIPkX1yfGvD13GEJIBOenqoKxR8/edit?usp=sharing) +* [Stability issues](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/212) + +### Helpful command line tools[](#helpful-command-line-tools "Permalink") + +* [K9s-](https://github.com/derailed/k9s)启用跨 Pod 的 CLI 仪表板并启用按标签过滤 +* [船尾](https://github.com/wercker/stern) -基于标签/字段选择器启用跨 Pod 日志拖尾 + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/docs/631.md b/docs/631.md new file mode 100644 index 0000000000000000000000000000000000000000..ad7d6df2cdba98cdcba5fa417e322dd23b1b48dd --- /dev/null +++ b/docs/631.md @@ -0,0 +1,26 @@ +# Smoke Tests + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/smoke.html](https://docs.gitlab.com/ee/development/testing_guide/smoke.html) + +# Smoke Tests[](#smoke-tests "Permalink") + +在任何测试套件中,必须有烟雾测试. 简而言之,冒烟测试将运行来自 GitLab QA 的快速端到端功能测试,旨在针对指定环境运行以确保基本功能正常运行. + +当前,我们的套件包括以下基本功能: + +* 用户标准认证 +* SSH 密钥创建和添加到用户 +* 项目简单创建 +* 启用 Auto-DevOps 的项目创建 +* 问题创建 +* 问题用户提及 +* 合并请求创建 +* 片段创建 + +冒烟测试具有`:smoke` RSpec 元数据. + +有关[端到端测试](end_to_end/index.html)的更多详细信息,请参见[端到端](end_to_end/index.html)测试. + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/docs/632.md b/docs/632.md new file mode 100644 index 0000000000000000000000000000000000000000..0a6a912c7a058549923ef70f90257d64ab1920e9 --- /dev/null +++ b/docs/632.md @@ -0,0 +1,665 @@ +# Testing best practices + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/best_practices.html](https://docs.gitlab.com/ee/development/testing_guide/best_practices.html) + +* [Test Design](#test-design) +* [Test speed](#test-speed) +* [RSpec](#rspec) + * [General guidelines](#general-guidelines) + * [Coverage](#coverage) + * [System / Feature tests](#system--feature-tests) + * [Debugging Capybara](#debugging-capybara) + * [Live debug](#live-debug) + * [Run `:js` spec in a visible browser](#run-js-spec-in-a-visible-browser) + * [Screenshots](#screenshots) + * [Fast unit tests](#fast-unit-tests) + * [`let` variables](#let-variables) + * [Common test setup](#common-test-setup) + * [Time-sensitive tests](#time-sensitive-tests) + * [Feature flags in tests](#feature-flags-in-tests) + * [`stub_feature_flags` vs `Feature.enable*`](#stub_feature_flags-vs-featureenable) + * [Stubbing gate](#stubbing-gate) + * [Pristine test environments](#pristine-test-environments) + * [SQL database](#sql-database) + * [Redis](#redis) + * [Background jobs / Sidekiq](#background-jobs--sidekiq) + * [DNS](#dns) + * [Filesystem](#filesystem) + * [Persistent in-memory application state](#persistent-in-memory-application-state) + * [Table-based / Parameterized tests](#table-based--parameterized-tests) + * [Prometheus tests](#prometheus-tests) + * [Matchers](#matchers) + * [`be_like_time`](#be_like_time) + * [`have_gitlab_http_status`](#have_gitlab_http_status) + * [Testing query performance](#testing-query-performance) + * [QueryRecorder](#queryrecorder) + * [GitalyClient](#gitalyclient) + * [Shared contexts](#shared-contexts) + * [Shared examples](#shared-examples) + * [Helpers](#helpers) + * [Factories](#factories) + * [Fixtures](#fixtures) + * [Repositories](#repositories) + * [Configuration](#configuration) + * [Test environment logging](#test-environment-logging) + +# Testing best practices[](#testing-best-practices "Permalink") + +## Test Design[](#test-design "Permalink") + +在 manbetx 客户端打不开的测试是头等公民,而不是事后的想法. 在设计功能时,必须考虑测试的设计,这一点很重要. + +在实现功能时,我们考虑以正确的方式开发正确的功能,这有助于我们将范围缩小到可管理的水平. 在对功能进行测试时,我们必须考虑开发正确的测试,然后涵盖测试可能失败的*所有*重要方式,这可能很快将我们的范围扩大到难以管理的水平. + +测试启发法可以帮助解决此问题. 它们简明地解决了错误在我们的代码中表现出来的许多常见方式. 在设计测试时,请花一些时间来回顾已知的测试启发法,以告知我们的测试设计. 我们可以在" [测试工程"](https://about.gitlab.com/handbook/engineering/quality/test-engineering/#test-heuristics)部分的"手册"中找到一些有用的启发式方法. + +## Test speed[](#test-speed "Permalink") + +GitLab has a massive test suite that, without [parallelization](ci.html#test-suite-parallelization-on-the-ci), can take hours to run. It’s important that we make an effort to write tests that are accurate and effective *以及* fast. + +关于测试性能,需要牢记以下几点: + +* `instance_double`和`spy`比`FactoryBot.build(...)`快 +* `FactoryBot.build(...)`和`.build_stubbed`比`.create`更快. +* 当`build` , `build_stubbed` , `attributes_for` , `spy`或`instance_double`可以使用时,不要`create`对象. 数据库持久性很慢! +* 除非*实际*需要测试有效,否则不要将功能标记为需要 JavaScript(通过 RSpec 中的`:js` ). 无头浏览器测试很慢! + +## RSpec[](#rspec "Permalink") + +要运行 RSpec 测试: + +``` +# run test for a file +bin/rspec spec/models/project_spec.rb + +# run test for the example on line 10 on that file +bin/rspec spec/models/project_spec.rb:10 + +# run tests matching the example name has that string +bin/rspec spec/models/project_spec.rb -e associations + +# run all tests, will take hours for GitLab codebase! +bin/rspec +``` + +使用[Guard](https://github.com/guard/guard)连续监视更改,并仅运行匹配的测试: + +``` +bundle exec guard +``` + +一起使用 spring 和 guard 时,请改用`SPRING=1 bundle exec guard`来使用 spring. + +使用[Factory Doctor](https://test-prof.evilmartians.io/#/factory_doctor.md)查找不必要的数据库操作案例,这可能会导致测试缓慢. + +``` +# run test for path +FDOC=1 bin/rspec spec/[path]/[to]/[spec].rb +``` + +### General guidelines[](#general-guidelines "Permalink") + +* 使用单个顶级`RSpec.describe ClassName`块. +* 使用`.method`来描述类方法,并使用`#method`来描述实例方法. +* 使用`context`测试分支逻辑. +* 尝试使测试的顺序与类中的顺序匹配. +* 尝试遵循[四阶段测试](https://thoughtbot.com/blog/four-phase-test)模式,使用换行符分隔各个阶段. +* 使用`Gitlab.config.gitlab.host`而不是硬编码`'localhost'` +* 不要断言序列生成的属性的绝对值(请参见[Gotchas](../gotchas.html#do-not-assert-against-the-absolute-value-of-a-sequence-generated-attribute) ). +* 避免使用`expect_any_instance_of`或`allow_any_instance_of` (见[陷阱](../gotchas.html#do-not-assert-against-the-absolute-value-of-a-sequence-generated-attribute) ). +* 不要将`:each`参数提供给钩子,因为它是默认值. +* 在钩子`before`和`after` ,最好将它的作用域设置为`:context`不是`:all` +* 当使用作用在给定元素上的`execute_script` `evaluate_script("$('.js-foo').testSomething()")` (或`execute_script` )时,请事先使用 Capybara 匹配器(例如`find('.js-foo')` )以确保该元素实际存在. +* 使用`focus: true`可以隔离要运行的部分规范. +* 如果测试中有多个期望,请使用[`:aggregate_failures`](https://relishapp.com/rspec/rspec-core/docs/expectation-framework-integration/aggregating-failures) . +* 对于[空的测试描述块](https://github.com/rubocop-hq/rspec-style-guide#it-and-specify) ,如果测试是不言自明的,请使用`specify`而不是`it do` . +* 当您需要一个实际上不存在的 ID / IID /访问级别时,请使用`non_existing_record_id` / `non_existing_record_iid` / `non_existing_record_access_level` . 使用 123、1234 甚至 999 都很容易,因为在 CI 运行的情况下,这些 ID 实际上可能存在于数据库中. + +### Coverage[](#coverage "Permalink") + +[`simplecov`](https://github.com/colszowka/simplecov)用于生成代码测试覆盖率报告. 它们是在 CI 上自动生成的,但在本地运行测试时不会自动生成. 要在计算机上运行规格文件时生成部分报告,请设置`SIMPLECOV`环境变量: + +``` +SIMPLECOV=1 bundle exec rspec spec/models/repository_spec.rb +``` + +覆盖率报告会生成到应用程序根目录下的`coverage`文件夹中,您可以在浏览器中打开这些报告,例如: + +``` +firefox coverage/index.html +``` + +使用覆盖率报告来确保您的测试覆盖 100%的代码. + +### System / Feature tests[](#system--feature-tests "Permalink") + +**注意:**在编写新的系统测试之前, [请考虑**不要**编写一个](testing_levels.html#consider-not-writing-a-system-test) ! + +* Feature specs should be named `ROLE_ACTION_spec.rb`, such as `user_changes_password_spec.rb`. +* 使用描述成功和失败路径的方案标题. +* 避免方案标题未添加任何信息,例如"成功". +* 避免场景标题重复功能标题. +* Create only the necessary records in the database +* 测试一条幸福的道路和一条不太幸福的道路,仅此而已 +* 所有其他可能的路径均应通过单元测试或集成测试进行测试 +* 测试页面上显示的内容,而不是 ActiveRecord 模型的内部. 例如,如果您要验证是否已创建记录,请添加期望其记录显示在页面上的期望,而不是`Model.count`增加一. +* 可以查找 DOM 元素,但不要滥用它,因为它会使测试更加脆弱 + +#### Debugging Capybara[](#debugging-capybara "Permalink") + +有时您可能需要通过观察浏览器行为来调试 Capybara 测试. + +#### Live debug[](#live-debug "Permalink") + +您可以使用规范中的`live_debug`方法暂停 Capybara 并在浏览器中查看网站. 当前页面将在默认浏览器中自动打开. 您可能需要先登录(当前用户的凭据显示在终端中). + +要恢复测试运行,请按任意键. + +例如: + +``` +$ bin/rspec spec/features/auto_deploy_spec.rb:34 +Running via Spring preloader in process 8999 +Run options: include {:locations=>{"./spec/features/auto_deploy_spec.rb"=>[34]}} + +Current example is paused for live debugging +The current user credentials are: user2 / 12345678 +Press any key to resume the execution of the example! +Back to the example! +. + +Finished in 34.51 seconds (files took 0.76702 seconds to load) +1 example, 0 failures +``` + +注意: `live_debug`仅在启用 JavaScript 的规范上起作用. + +#### Run `:js` spec in a visible browser[](#run-js-spec-in-a-visible-browser "Permalink") + +使用`CHROME_HEADLESS=0`运行规范,例如: + +``` +CHROME_HEADLESS=0 bin/rspec some_spec.rb +``` + +测试将很快进行,但这将使您对正在发生的事情有所了解. 对`CHROME_HEADLESS=0`使用`live_debug`暂停打开的浏览器,并且不会再次打开该页面. 这可用于调试和检查元素. + +您还可以添加`byebug`或`binding.pry`暂停执行,并[步通过](../pry_debugging.html#stepping)测试. + +#### Screenshots[](#screenshots "Permalink") + +我们使用`capybara-screenshot` gem 在失败时自动截屏. 在 CI 中,您可以下载这些文件作为作业工件. + +另外,您可以通过添加以下方法在测试中的任何时候手动获取屏幕截图. 请确保在不再需要它们时将其删除! 有关更多信息,请参见[https://github.com/mattheworiordan/capybara-screenshot#manual-screenshots](https://github.com/mattheworiordan/capybara-screenshot#manual-screenshots) . + +在`:js`规范中添加`screenshot_and_save_page`以截图 Capybara 看到的内容,并保存页面源代码. + +在`:js`规范中添加`screenshot_and_open_image`以截图 Capybara 看到的内容,并自动打开图像. + +由此创建的 HTML 转储缺少 CSS. 这导致它们看起来与实际应用程序截然不同. 有一个添加 CSS 的[小技巧](https://gitlab.com/gitlab-org/gitlab-foss/snippets/1718469) ,可简化调试过程. + +### Fast unit tests[](#fast-unit-tests "Permalink") + +某些类与 Rails 完全隔离,您应该能够测试它们,而不会因 Rails 环境和 Bundler 的`:default`组的 gem 加载而增加开销. 在这些情况下,您可以在测试文件中`require 'fast_spec_helper'`而不是`require 'spec_helper'` ,并且由于以下原因,测试应该运行得非常快: + +* 宝石加载被跳过 +* Rails 应用启动被跳过 +* 跳过了 GitLab Shell 和 Gitaly 设置 +* 测试存储库设置被跳过 + +`fast_spec_helper`还支持`lib/`目录中的自动加载类. 这意味着只要您的类/模块仅使用`lib/`目录中的代码,就无需显式加载任何依赖项. `fast_spec_helper`还将加载所有 ActiveSupport 扩展,包括 Rails 环境中常用的核心扩展. + +请注意,在某些情况下,当代码使用 gems 或`lib/`没有依赖项时,您可能仍必须使用`require_dependency`加载某些依赖项. + +例如,如果要测试调用`Gitlab::UntrustedRegexp`类的代码,该类在`Gitlab::UntrustedRegexp`使用`re2`库,则应将`require_dependency 're2'`添加到需要`re2` gem 的库文件中,以达到此要求明确,也可以将其添加到规范本身中,但最好使用前者. + +加载使用`fast_spec_helper`测试大约需要一秒钟,而不是常规`spec_helper`的 30+秒. + +### `let` variables[](#let-variables "Permalink") + +GitLab 的 RSpec 套件广泛使用`let` (以及严格的非延迟版本`let!` )变量来减少重复. 但是,有时这有时要以[清楚为代价](https://thoughtbot.com/blog/lets-not) ,因此我们需要为以后的使用设置一些准则: + +* `let!` 变量优于实例变量. `let`变量比`let!`可取`let!` 变量. 局部变量比`let`变量更可取. +* 使用`let`可以减少整个规格文件中的重复项. +* 不要使用`let`定义单个测试使用的变量; 在测试的`it`块中将它们定义为局部变量. +* 不要在顶层`describe`块中定义只用于更深层嵌套`context`或`describe`块的`let`变量. 使定义尽可能靠近使用位置. +* 尽量避免将一个`let`变量的定义覆盖另一个. +* 不要定义只供另一个定义使用的`let`变量. 请改用辅助方法. +* `let!` 变量应该只在需要与定义为了严格评估的情况下使用,否则`let`就足够了. 请记住, `let`是惰性的,在被引用之前不会被评估. + +### Common test setup[](#common-test-setup "Permalink") + +在某些情况下,无需为每个示例再次创建相同的对象以进行测试. 例如,需要一个项目和该项目的访客来测试同一项目上的问题,一个项目和一个用户将对整个文件进行测试. + +尽可能不要使用`before(:all)`或`before(:context)`实现此目的. 如果这样做,您将需要手动清理数据,因为这些挂钩在数据库事务外部运行. + +相反,这可以通过使用来实现[`let_it_be`](https://test-prof.evilmartians.io/#/let_it_be)变量和[`before_all`](https://test-prof.evilmartians.io/#/before_all)钩从[`test-prof`的宝石](https://rubygems.org/gems/test-prof) . + +``` +let_it_be(:project) { create(:project) } +let_it_be(:user) { create(:user) } + +before_all do + project.add_guest(user) +end +``` + +这将仅为此上下文创建一个`Project` , `User`和`ProjectMember` . + +`let_it_be`和`before_all`在嵌套上下文中也可用. 使用事务回滚自动处理上下文后进行清理. + +Note that if you modify an object defined inside a `let_it_be` block, then you will need to reload the object as needed, or specify the `reload` option to reload for every example. + +``` +let_it_be(:project, reload: true) { create(:project) } +``` + +您还可以指定`refind`选项以完全加载新对象. + +``` +let_it_be(:project, refind: true) { create(:project) } +``` + +### Time-sensitive tests[](#time-sensitive-tests "Permalink") + +在基于 Ruby 的测试中可以使用[Timecop](https://github.com/travisjeffery/timecop)来验证对时间敏感的事物. 任何锻炼或验证时间敏感的测试都应使用 Timecop 来防止瞬态测试失败. + +Example: + +``` +it 'is overdue' do + issue = build(:issue, due_date: Date.tomorrow) + + Timecop.freeze(3.days.from_now) do + expect(issue).to be_overdue + end +end +``` + +### Feature flags in tests[](#feature-flags-in-tests "Permalink") + +在基于 Ruby 的测试中,默认情况下所有功能标志都已启用. + +要在测试中禁用功能标记,请使用`stub_feature_flags`帮助器. 例如,要在测试中全局禁用`ci_live_trace`功能标志: + +``` +stub_feature_flags(ci_live_trace: false) + +Feature.enabled?(:ci_live_trace) # => false +``` + +如果您希望设置一个仅对某些角色而不对其他角色启用功能标志的测试,则可以在传递给助手的选项中指定此功能. 例如,要为特定项目启用`ci_live_trace`功能标记: + +``` +project1, project2 = build_list(:project, 2) + +# Feature will only be enabled for project1 +stub_feature_flags(ci_live_trace: project1) + +Feature.enabled?(:ci_live_trace) # => false +Feature.enabled?(:ci_live_trace, project1) # => true +Feature.enabled?(:ci_live_trace, project2) # => false +``` + +这代表了 FlipperGate 的实际行为: + +1. 您可以启用要启用的指定角色的替代 +2. 您可以禁用(删除)指定角色的替代,并还原为默认状态 +3. 无法建模您明确禁用指定的参与者 + +``` +Feature.enable(:my_feature) +Feature.disable(:my_feature, project1) +Feature.enabled?(:my_feature) # => true +Feature.enabled?(:my_feature, project1) # => true +``` + +``` +Feature.disable(:my_feature2) +Feature.enable(:my_feature2, project1) +Feature.enabled?(:my_feature2) # => false +Feature.enabled?(:my_feature2, project1) # => true +``` + +#### `stub_feature_flags` vs `Feature.enable*`[](#stub_feature_flags-vs-featureenable "Permalink") + +最好使用`stub_feature_flags`在测试环境中启用功能标志. 该方法为简单的用例提供了一个简单且描述良好的界面. + +但是,在某些情况下,需要测试更复杂的行为,例如功能标志百分比展示. 这可以使用`.enable_percentage_of_time`和`.enable_percentage_of_actors`来实现 + +``` +# Good: feature needs to be explicitly disabled, as it is enabled by default if not defined +stub_feature_flags(my_feature: false) +stub_feature_flags(my_feature: true) +stub_feature_flags(my_feature: project) +stub_feature_flags(my_feature: [project, project2]) + +# Bad +Feature.enable(:my_feature_2) + +# Good: enable my_feature for 50% of time +Feature.enable_percentage_of_time(:my_feature_3, 50) + +# Good: enable my_feature for 50% of actors/gates/things +Feature.enable_percentage_of_actors(:my_feature_4, 50) +``` + +具有定义状态的每个功能标志将在测试执行时间内保留: + +``` +Feature.persisted_names.include?('my_feature') => true +Feature.persisted_names.include?('my_feature_2') => true +Feature.persisted_names.include?('my_feature_3') => true +Feature.persisted_names.include?('my_feature_4') => true +``` + +#### Stubbing gate[](#stubbing-gate "Permalink") + +要求将作为参数传递给`Feature.enabled?` 和`Feature.disabled?` 是包含`FeatureGate`的对象. + +在规范中,您可以使用`stub_feature_flag_gate`方法,该方法可让您快速使用自定义门: + +``` +gate = stub_feature_flag_gate('CustomActor') + +stub_feature_flags(ci_live_trace: gate) + +Feature.enabled?(:ci_live_trace) # => false +Feature.enabled?(:ci_live_trace, gate) # => true +``` + +### Pristine test environments[](#pristine-test-environments "Permalink") + +单个 GitLab 测试执行的代码可以访问和修改许多数据项. 无需在测试运行之前进行仔细的准备,然后再进行清理,则测试可以更改数据,从而影响后续测试的行为. 应不惜一切代价避免这种情况! 幸运的是,现有的测试框架已经可以处理大多数情况. + +当测试环境确实受到污染时,常见的结果就是[不稳定的测试](flaky_tests.html) . 污染通常表现为顺序依赖性:运行规格 A,然后运行规格 B 会可靠地失败,但是运行规格 B,然后运行规格 A 将可靠地成功. 在这些情况下,可以使用`rspec --bisect` (或规格文件的手动成对二`rspec --bisect` )来确定哪个规格有问题. 要解决此问题,需要对测试套件如何确保原始环境有一些了解. 继续阅读以发现有关每个数据存储的更多信息! + +#### SQL database[](#sql-database "Permalink") + +这是由`database_cleaner` gem 为我们管理的. 每个规范都包含在一个事务中,一旦测试完成,该事务将回滚. 某些规范将在完成后针对每个表发出`DELETE FROM`查询; 这样可以从多个数据库连接中查看创建的行,这对于在浏览器中运行的规范或迁移规范等非常重要. + +使用这些策略而不是众所周知的`TRUNCATE TABLES`方法的结果是,主键和其他序列**不会**在整个规范中重置. 因此,如果您在规范 A 中创建一个项目,然后在规范 B 中创建一个项目,则第一个将具有`id=1` ,而第二个将具有`id=2` . + +这意味着规范**永远**不应依赖 ID 或任何其他序列生成的列的值. 为避免意外冲突,规范还应避免手动指定此类列中的任何值. 而是将它们保留为未指定状态,并在创建行后查找值. + +#### Redis[](#redis "Permalink") + +GitLab 在 Redis 中存储了两个主要的数据类别:缓存项和 Sidekiq 作业. + +在大多数规范中,Rails 缓存实际上是一个内存存储. 规格之间已替换了该代码,因此对`Rails.cache.read`和`Rails.cache.write`调用是安全的. 但是,如果某个规范直接进行 Redis 调用,则应适当地使用`:clean_gitlab_redis_cache` , `:clean_gitlab_redis_shared_state`或`:clean_gitlab_redis_queues`特征对其进行标记. + +#### Background jobs / Sidekiq[](#background-jobs--sidekiq "Permalink") + +默认情况下,Sidekiq 作业会排队到作业数组中,并且不会进行处理. 如果测试将 Sidekiq 作业排入队列并需要对其进行处理,则可以使用`:sidekiq_inline`特性. + +The `:sidekiq_might_not_need_inline` trait was added when [Sidekiq inline mode was changed to fake mode](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15479) to all the tests that needed Sidekiq to actually process jobs. Tests with this trait should be either fixed to not rely on Sidekiq processing jobs, or their `:sidekiq_might_not_need_inline` trait should be updated to `:sidekiq_inline` if the processing of background jobs is needed/expected. + +**注意:** `perform_enqueued_jobs`的用法仅对测试延迟的邮件传递有用,因为我们的 Sidekiq 工作者不是从`ApplicationJob` / `ActiveJob::Base`继承. + +#### DNS[](#dns "Permalink") + +DNS 请求在测试套件中普遍存在(截至[!22368](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22368) ),因为 DNS 可能会导致问题,具体取决于开发人员的本地网络. 在`spec/support/dns.rb`有可用的 RSpec 标签,如果您需要绕过 DNS 存根,则可以将其应用于测试,例如: + +``` +it "really connects to Prometheus", :permit_dns do +``` + +而且,如果需要更具体的控制,则可以在`spec/support/helpers/dns_helpers.rb`实现 DNS 阻止,并且可以在其他地方调用这些方法. + +#### Filesystem[](#filesystem "Permalink") + +文件系统数据可以大致分为"存储库"和"其他所有内容". 存储库存储在`tmp/tests/repositories` . 在测试运行开始之前和测试运行结束之后,将清空此目录. 在规格之间不清空它,因此在过程的整个生命周期中,创建的存储库都在此目录中累积. 删除它们很昂贵,但是除非精心管理,否则可能会导致污染. + +为避免这种情况,在测试套件中启用了[哈希存储](../../administration/repository_storage_types.html) . 这意味着将为存储库提供一个唯一的路径,该路径取决于其项目的 ID. 由于在规范之间未重置项目 ID,因此可以确保每个规范在磁盘上获得自己的存储库,并防止在规范之间可见更改. + +如果规范手动指定了项目 ID,或直接检查`tmp/tests/repositories/`目录的状态,则它应该在运行之前和之后清理该目录. 通常,应完全避免这些模式. + +链接到数据库对象的其他文件类别(例如上载)通常以相同的方式进行管理. 在规范中启用了散列存储后,它们将在 ID 确定的位置写入磁盘,因此不会发生冲突. + +一些规范通过将`:legacy_storage`特征传递给`projects`工厂来禁用哈希存储. 执行此操作的规范绝**不能**覆盖项目或其任何组的`path` . 默认路径包含项目 ID,因此不会发生冲突. 但是,如果两个规范创建具有相同路径的`:legacy_storage`项目,则它们将使用磁盘上的相同存储库并导致测试环境污染. + +其他文件必须由规范手动管理. 例如,如果运行创建`tmp/test-file.csv`文件的代码,则规范必须确保在清理过程中删除了该文件. + +#### Persistent in-memory application state[](#persistent-in-memory-application-state "Permalink") + +给定`rspec`运行中的所有规范共享相同的 Ruby 进程,这意味着它们可以通过修改规范之间可访问的 Ruby 对象相互影响. 实际上,这意味着全局变量和常量(包括 Ruby 类,模块等). + +全局变量通常不应修改. 如果绝对必要,则可以使用如下所示的块来确保更改被回滚: + +``` +around(:each) do |example| + old_value = $0 + + begin + $0 = "new-value" + example.run + ensure + $0 = old_value + end +end +``` + +如果规范需要修改常量,则应使用`stub_const`帮助器以确保更改被回滚. + +如果需要修改`ENV`常量的内容,则可以改用`stub_env`帮助器方法. + +虽然大多数 Ruby **实例**不在规范之间共享,但**类**和**模块**通常是共享的. 类和模块实例变量,访问器,类变量和其他有状态习语应与全局变量一样对待-除非必须修改,否则请勿对其进行修改! 特别是,最好使用期望值或依赖项注入以及存根,以避免进行修改. 如果没有其他选择,可以使用类似于上面的全局变量示例的`around`块,但应尽可能避免这种情况. + +### Table-based / Parameterized tests[](#table-based--parameterized-tests "Permalink") + +这种测试风格用于执行一段具有广泛输入范围的代码. 通过一次指定测试用例,并在每个输入和预期输出表的旁边,可以使您的测试更易于阅读和紧凑. + +我们使用[RSpec :: Parameterized](https://github.com/tomykaira/rspec-parameterized) gem. 一个简短的示例,使用表语法并检查 Ruby 相等性是否为一系列输入,可能看起来像这样: + +``` +describe "#==" do + using RSpec::Parameterized::TableSyntax + + where(:a, :b, :result) do + 1 | 1 | true + 1 | 2 | false + true | true | true + true | false | false + end + + with_them do + it { expect(a == b).to eq(result) } + + it 'is isomorphic' do + expect(b == a).to eq(result) + end + end +end +``` + +**注意:**仅将简单值用作`where`块中的输入. 使用 proc,有状态对象,FactoryBot 创建的对象等可能导致[意外结果](https://github.com/tomykaira/rspec-parameterized/issues/8) . + +### Prometheus tests[](#prometheus-tests "Permalink") + +可以将 Prometheus 度量从一次测试运行保存到另一次测试. 为了确保在每个示例之前重置指标,请在 RSpec 测试中添加`:prometheus`标记. + +### Matchers[](#matchers "Permalink") + +应该创建自定义匹配器以阐明意图和/或隐藏 RSpec 期望的复杂性. 它们应放在`spec/support/matchers/` . 如果匹配器仅适用于某种类型的规范(例如功能,请求等),则可以放在子文件夹中,但如果它们适用于多种类型的规范,则不应该放在子文件夹中. + +#### `be_like_time`[](#be_like_time "Permalink") + +从数据库返回的时间的精度可能与 Ruby 中的时间对象不同,因此在规格比较时我们需要灵活的容差. 我们可以使用`be_like_time`来比较时间在彼此之间一秒之内. + +Example: + +``` +expect(metrics.merged_at).to be_like_time(time) +``` + +#### `have_gitlab_http_status`[](#have_gitlab_http_status "Permalink") + +`have_gitlab_http_status`使用`have_http_status`而不是`have_http_status`和`have_http_status` `expect(response.status).to` `have_http_status` ,因为只要状态不匹配,前者还可以显示响应主体. 每当某些测试开始中断时,这将非常有用,我们很想知道为什么不编辑源代码并重新运行测试. + +每当它显示 500 内部服务器错误时,此功能特别有用. + +在数字表示形式`206` `:no_content`命名为 HTTP 的状态,如`:no_content` . 请参阅[支持的状态代码](https://github.com/rack/rack/blob/f2d2df4016a906beec755b63b4edfcc07b58ee05/lib/rack/utils.rb#L490)列表. + +Example: + +``` +expect(response).to have_gitlab_http_status(:ok) +``` + +### Testing query performance[](#testing-query-performance "Permalink") + +测试查询性能使我们能够: + +* 断言代码块中不存在 N + 1 个问题. +* 确保代码块中的查询数量不会被忽略. + +#### QueryRecorder[](#queryrecorder "Permalink") + +`QueryRecorder`允许分析和测试在给定代码块中执行的数据库查询的数量. + +有关更多详细信息,请参见[`QueryRecorder`](../query_recorder.html)部分. + +#### GitalyClient[](#gitalyclient "Permalink") + +`Gitlab::GitalyClient.get_request_count` allows tests of the number of Gitaly queries made by a given block of code: + +有关更多详细信息,请参见[`Gitaly Request Counts`](../gitaly.html#request-counts)部分. + +### Shared contexts[](#shared-contexts "Permalink") + +可以内联声明仅在一个规范文件中使用的共享上下文. 一个以上规范文件使用的任何共享上下文: + +* 应该放在`spec/support/shared_contexts/` . +* 如果它们仅适用于某种类型的规范(例如功能,请求等),则可以放在子文件夹中,但如果它们适用于多种类型的规范,则不应放在子文件夹中. + +每个文件应仅包含一个上下文并具有描述性名称,例如`spec/support/shared_contexts/controllers/githubish_import_controller_shared_context.rb` . + +### Shared examples[](#shared-examples "Permalink") + +可以内联声明仅在一个规范文件中使用的共享示例. 多个规范文件使用的任何共享示例: + +* 应该放在`spec/support/shared_examples/` . +* 如果它们仅适用于某种类型的规范(例如功能,请求等),则可以放在子文件夹中,但如果它们适用于多种类型的规范,则不应放在子文件夹中. + +每个文件应仅包含一个上下文并具有描述性名称,例如`spec/support/shared_examples/controllers/githubish_import_controller_shared_example.rb` . + +### Helpers[](#helpers "Permalink") + +帮助程序通常是提供一些隐藏特定 RSpec 示例复杂性的方法的模块. 如果不希望与其他规范共享,则可以在 RSpec 文件中定义帮助程序. 否则,应将它们放在`spec/support/helpers/` . 如果助手仅适用于某种类型的规范(例如功能,请求等),则可以放在子文件夹中,但如果它们适用于多种类型的规范,则不应放在子文件夹中. + +助手应遵循 Rails 的命名/命名空间约定. 例如`spec/support/helpers/cycle_analytics_helpers.rb`应该定义: + +``` +module Spec + module Support + module Helpers + module CycleAnalyticsHelpers + def create_commit_referencing_issue(issue, branch_name: random_git_name) + project.repository.add_branch(user, branch_name, 'master') + create_commit("Commit for ##{issue.iid}", issue.project, user, branch_name) + end + end + end + end +end +``` + +助手不应更改 RSpec 配置. 例如,上述帮助器模块不应包括: + +``` +RSpec.configure do |config| + config.include Spec::Support::Helpers::CycleAnalyticsHelpers +end +``` + +### Factories[](#factories "Permalink") + +GitLab 使用[factory_bot](https://github.com/thoughtbot/factory_bot)替代测试夹具. + +* 工厂定义存在于`spec/factories/` ,使用其对应模型的复数形式命名( `User`工厂在`users.rb`中定义). +* 每个文件应该只有一个顶级工厂定义. +* FactoryBot 方法混入了所有 RSpec 组. 这意味着您可以(并且应该)调用`create(...)`而不是`FactoryBot.create(...)` . +* 利用[特征](https://www.rubydoc.info/gems/factory_bot/file/GETTING_STARTED.md#traits)来清理定义和用法. +* 定义工厂时,请勿定义结果记录通过验证不需要的属性. +* 从工厂实例化时,不要提供测试不需要的属性. +* 工厂不必仅限于`ActiveRecord`对象. [参见示例](https://gitlab.com/gitlab-org/gitlab-foss/commit/0b8cefd3b2385a21cfed779bd659978c0402766d) . + +### Fixtures[](#fixtures "Permalink") + +所有固定装置应放置在`spec/fixtures/` . + +### Repositories[](#repositories "Permalink") + +测试某些功能(例如,合并合并请求)需要在测试环境中具有某种状态的 Git 存储库. GitLab 在某些常见情况下会维护[`gitlab-test`](https://gitlab.com/gitlab-org/gitlab-test)存储库-您可以确保该存储库的副本与`:repository`特性一起用于项目工厂: + +``` +let(:project) { create(:project, :repository) } +``` + +可以的话,请考虑使用`:custom_repo`特性而不是`:repository` . 这使您可以精确地指定哪些文件将出现在项目存储库的`master`分支中. 例如: + +``` +let(:project) do + create( + :project, :custom_repo, + files: { + 'README.md' => 'Content here', + 'foo/bar/baz.txt' => 'More content here' + } + ) +end +``` + +这将创建一个包含两个文件的存储库,这两个文件具有默认权限和指定的内容. + +### Configuration[](#configuration "Permalink") + +RSpec 配置文件是更改 RSpec 配置的文件(即`RSpec.configure do |config|`块). 它们应放在`spec/support/` . + +每个文件都应与特定域相关,例如`spec/support/capybara.rb` , `spec/support/carrierwave.rb`等. + +如果 helpers 模块仅适用于某种规格,则应在`config.include`调用中添加修饰符. 例如,如果`spec/support/helpers/cycle_analytics_helpers.rb`仅适用于`:lib`和`type: :model` specs,则应编写以下内容: + +``` +RSpec.configure do |config| + config.include Spec::Support::Helpers::CycleAnalyticsHelpers, :lib + config.include Spec::Support::Helpers::CycleAnalyticsHelpers, type: :model +end +``` + +If a configuration file only consists of `config.include`, you can add these `config.include` directly in `spec/spec_helper.rb`. + +对于非常通用的帮助程序,请考虑将它们包括在`spec/support/rspec.rb`文件使用的`spec/fast_spec_helper.rb`文件中. 有关`spec/fast_spec_helper.rb`文件的更多详细信息,请参见[快速单元测试](#fast-unit-tests) . + +### Test environment logging[](#test-environment-logging "Permalink") + +在运行测试时,会自动配置并启动用于测试环境的服务,包括 Gitaly,Workhorse,Elasticsearch 和 Capybara. 在 CI 中运行时,或者如果需要安装服务,则测试环境将记录有关设置时间的信息,并产生如下日志消息: + +``` +==> Setting up Gitaly... + Gitaly set up in 31.459649 seconds... + +==> Setting up GitLab Workhorse... + GitLab Workhorse set up in 29.695619 seconds... +fatal: update refs/heads/diff-files-symlink-to-image: invalid <newvalue>: 8cfca84 +From https://gitlab.com/gitlab-org/gitlab-test + * [new branch] diff-files-image-to-symlink -> origin/diff-files-image-to-symlink + * [new branch] diff-files-symlink-to-image -> origin/diff-files-symlink-to-image + * [new branch] diff-files-symlink-to-text -> origin/diff-files-symlink-to-text + * [new branch] diff-files-text-to-symlink -> origin/diff-files-text-to-symlink + b80faa8..40232f7 snippet/multiple-files -> origin/snippet/multiple-files + * [new branch] testing/branch-with-#-hash -> origin/testing/branch-with-#-hash + +==> Setting up GitLab Elasticsearch Indexer... + GitLab Elasticsearch Indexer set up in 26.514623 seconds... +``` + +当在本地运行并且不需要执行任何操作时,将忽略此信息. 如果您始终希望看到这些消息,请设置以下环境变量: + +``` +GITLAB_TESTING_LOG_LEVEL=debug +``` + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/docs/633.md b/docs/633.md new file mode 100644 index 0000000000000000000000000000000000000000..24dcb4a14533192b21f5a10cba738d1302ec46d4 --- /dev/null +++ b/docs/633.md @@ -0,0 +1,342 @@ +# Testing levels + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/testing_levels.html](https://docs.gitlab.com/ee/development/testing_guide/testing_levels.html) + +* [Unit tests](#unit-tests) + * [Frontend unit tests](#frontend-unit-tests) + * [When to use unit tests](#when-to-use-unit-tests) + * [When *not* to use unit tests](#when-not-to-use-unit-tests) + * [What to mock in unit tests](#what-to-mock-in-unit-tests) + * [What *not* to mock in unit tests](#what-not-to-mock-in-unit-tests) + * [Frontend component tests](#frontend-component-tests) + * [When to use component tests](#when-to-use-component-tests) + * [When *not* to use component tests](#when-not-to-use-component-tests) + * [What to mock in component tests](#what-to-mock-in-component-tests) + * [What *not* to mock in component tests](#what-not-to-mock-in-component-tests) +* [Integration tests](#integration-tests) + * [Frontend integration tests](#frontend-integration-tests) + * [When to use integration tests](#when-to-use-integration-tests) + * [What to mock in integration tests](#what-to-mock-in-integration-tests) + * [What *not* to mock in integration tests](#what-not-to-mock-in-integration-tests) + * [About controller tests](#about-controller-tests) + * [About Karma](#about-karma) +* [White-box tests at the system level (formerly known as System / Feature tests)](#white-box-tests-at-the-system-level-formerly-known-as-system--feature-tests) + * [Frontend feature tests](#frontend-feature-tests) + * [When to use feature tests](#when-to-use-feature-tests) + * [Relevant notes](#relevant-notes) + * [Consider **not** writing a system test](#consider-not-writing-a-system-test) +* [Black-box tests at the system level, aka end-to-end tests](#black-box-tests-at-the-system-level-aka-end-to-end-tests) + * [Smoke tests](#smoke-tests) + * [GitLab QA orchestrator](#gitlab-qa-orchestrator) +* [EE-specific tests](#ee-specific-tests) +* [How to test at the correct level?](#how-to-test-at-the-correct-level) + * [Frontend-related tests](#frontend-related-tests) + +# Testing levels[](#testing-levels "Permalink") + +[![Testing priority triangle](img/35460a8c847cde5f9e477c80231d7f8b.png)](img/testing_triangle.png) + +*此图说明了我们使用的每种测试类型的相对优先级. `e2e`代表端到端.* + +截至 2019-05-01,我们每个级别的测试分布如下: + +| 测试等级 | 社区版 | 企业版 | 社区+企业版 | +| --- | --- | --- | --- | +| 系统级别的黑盒测试(也称为端到端或 QA 测试) | 68 (0.14%) | 31 (0.2%) | 99 (0.17%) | +| 系统级别的白盒测试(也称为系统或功能测试) | 5,471 (11.9%) | 969 (7.4%) | 6440 (10.9%) | +| 整合测试 | 8,333 (18.2%) | 2,244 (17.2%) | 10,577 (17.9%) | +| 单元测试 | 32,031 (69.7%) | 9,778 (75.1%) | 41,809 (71%) | + +## Unit tests[](#unit-tests "Permalink") + +正式定义: [https](https://en.wikipedia.org/wiki/Unit_testing) : [//en.wikipedia.org/wiki/Unit_testing](https://en.wikipedia.org/wiki/Unit_testing) + +这类测试可确保单个代码单元(一种方法)按预期工作(给定输入,它具有可预测的输出). 这些测试应尽可能隔离. 例如,对数据库不做任何事情的模型方法不需要数据库记录. 不需要数据库记录的类应尽可能使用存根/双精度数. + +| 代码路径 | 测试路径 | 测试引擎 | Notes | +| --- | --- | --- | --- | +| `app/assets/javascripts/` | `spec/javascripts/`, `spec/frontend/` | 因果 | " [前端测试指南"](frontend_testing.html)部分中的更多详细信息. | +| `app/finders/` | `spec/finders/` | RSpec |   | +| `app/graphql/` | `spec/graphql/` | RSpec |   | +| `app/helpers/` | `spec/helpers/` | RSpec |   | +| `app/models/` | `spec/models/` | RSpec |   | +| `app/policies/` | `spec/policies/` | RSpec |   | +| `app/presenters/` | `spec/presenters/` | RSpec |   | +| `app/serializers/` | `spec/serializers/` | RSpec |   | +| `app/services/` | `spec/services/` | RSpec |   | +| `app/uploaders/` | `spec/uploaders/` | RSpec |   | +| `app/validators/` | `spec/validators/` | RSpec |   | +| `app/views/` | `spec/views/` | RSpec |   | +| `app/workers/` | `spec/workers/` | RSpec |   | +| `bin/` | `spec/bin/` | RSpec |   | +| `config/` | `spec/config/` | RSpec |   | +| `config/initializers/` | `spec/initializers/` | RSpec |   | +| `config/routes.rb`, `config/routes/` | `spec/routing/` | RSpec |   | +| `config/puma.example.development.rb`, `config/unicorn.rb.example` | `spec/rack_servers/` | RSpec |   | +| `db/` | `spec/db/` | RSpec |   | +| `db/{post_,}migrate/` | `spec/migrations/` | RSpec | 更多信息,请参见《 [Testing Rails 迁移指南》](testing_migrations_guide.html) . | +| `Gemfile` | `spec/dependencies/`, `spec/sidekiq/` | RSpec |   | +| `lib/` | `spec/lib/` | RSpec |   | +| `lib/tasks/` | `spec/tasks/` | RSpec |   | +| `rubocop/` | `spec/rubocop/` | RSpec |   | +| `spec/factories` | `spec/factories_spec.rb` | RSpec |   | + +### Frontend unit tests[](#frontend-unit-tests "Permalink") + +Unit tests are on the lowest abstraction level and typically test functionality that is not directly perceivable by a user. + +图 RL plain [普通 JavaScript]; Vue [Vue 组件]; feature-flags [功能标志]; 许可证检查[许可证检查]; 普通--Vuex; 普通--GraphQL; Vue--简单 Vue --- Vuex; Vue--GraphQL; 浏览器-普通 浏览器--- Vue; 普通-后端; Vuex-后端; GraphQL--后端; Vue-后端; 后端-数据库 后端-功能标记; 后端-许可证检查; 普通测试 经过 Vuex 类测试; classDef 节点颜色:#909090,填充:#f0f0f0,笔划宽度:2px,笔划:#909090 classDef 标签 stroke-width:0; classDef 测试的颜色:#000000,填充:#a0c0ff,笔划:#6666ff,笔划宽度:2px,笔划数组:5、5; 经过测试的子图; 嘲笑 等级测试 结束 + +#### When to use unit tests[](#when-to-use-unit-tests "Permalink") + +* **导出的函数和类** :导出的所有内容都可以以您无法控制的方式在各个地方重复使用. 您应该用测试记录公共接口的预期行为. +* **Vuex 操作** :任何 Vuex 操作都必须以一致的方式工作,而不依赖于触发它的组件. +* **Vuex 突变** :对于复杂的 Vuex 突变,您应该将测试与 Vuex 存储的其他部分分开,以简化问题解决的过程. + +#### When *not* to use unit tests[](#when-not-to-use-unit-tests "Permalink") + +* **非导出的函数或类** :任何未从模块导出的东西都可以视为私有或实现细节,不需要进行测试. +* **常量** :测试**常量**的值意味着将其复制,从而导致额外的工作,而又没有信心确保该值正确. +* **Vue 组件** :计算出的属性,方法和生命周期挂钩可被视为组件的实现细节,它们被组件测试隐式涵盖,并且不需要进行测试. 有关更多信息,请参见[官方 Vue 指南](https://vue-test-utils.vuejs.org/guides/#getting-started) . + +#### What to mock in unit tests[](#what-to-mock-in-unit-tests "Permalink") + +* **被测类**的状态:直接修改**被测类**的状态而不是使用类的方法可以避免测试设置中的副作用. +* **其他导出的类** :必须隔离测试每个类,以防止测试方案成倍增长. +* **如果将单个 DOM 元素作为参数传递** :对于仅在单个 DOM 元素而不是整个页面上运行的测试,创建这些元素比加载整个 HTML 固定工具便宜. +* **所有服务器请求** :在运行前端单元测试时,后端可能无法访问,因此需要模拟所有传出的请求. +* **异步后台操作** :后台操作无法停止或等待,因此它们将在以下测试中继续运行并产生副作用. + +#### What *not* to mock in unit tests[](#what-not-to-mock-in-unit-tests "Permalink") + +* **非导出的函数或类** :可以将未导出的所有内容视为该模块的私有内容,并将通过导出的类和函数进行隐式测试. +* **被测类的方法** :通过模拟**被测类的**方法,将对模拟进行测试,而不是对实际方法进行测试. +* **实用程序功能(纯功能或仅修改参数**的功能**)** :如果某个功能由于没有状态而没有副作用,则可以在测试中不对其进行模拟. +* **完整的 HTML 页面** :避免在单元测试中加载整个页面的 HTML,因为这会减慢测试速度. + +### Frontend component tests[](#frontend-component-tests "Permalink") + +组件测试涵盖了用户可以根据外部信号(例如用户输入,从其他组件触发的事件或应用程序状态)感知到的单个组件的状态. + +图 RL plain [普通 JavaScript]; Vue [Vue 组件]; feature-flags [功能标志]; 许可证检查[许可证检查]; 普通--Vuex; 普通--GraphQL; Vue--简单 Vue --- Vuex; Vue--GraphQL; 浏览器-普通 浏览器--- Vue; 普通-后端; Vuex-后端; GraphQL--后端; Vue-后端; 后端-数据库 后端-功能标记; 后端-许可证检查; 经过 Vue 测试; classDef 节点颜色:#909090,填充:#f0f0f0,笔划宽度:2px,笔划:#909090 classDef 标签 stroke-width:0; classDef 测试的颜色:#000000,填充:#a0c0ff,笔划:#6666ff,笔划宽度:2px,笔划数组:5、5; 经过测试的子图; 嘲笑 等级测试 结束 + +#### When to use component tests[](#when-to-use-component-tests "Permalink") + +* **组件视图** + +#### When *not* to use component tests[](#when-not-to-use-component-tests "Permalink") + +* **Vue 应用程序** :Vue 应用程序可能包含许多组件. 在组件级别测试它们需要太多的工作. 因此,它们在前端集成级别进行了测试. +* **HAML 模板** :HAML 模板仅包含标记,不包含前端逻辑. 因此,它们不是完整的组件. + +#### What to mock in component tests[](#what-to-mock-in-component-tests "Permalink") + +* **DOM** :在真实 DOM 上操作要比在虚拟 DOM 上慢得多. +* **被测组件的属性和状态** :与测试类类似,直接修改属性(而不是依赖组件的方法)可以避免副作用. +* **Vuex 存储库** :为了避免副作用并简化组件测试,Vuex 存储库被模拟代替. +* **所有服务器请求** :与单元测试类似,在运行组件测试时,后端可能无法访问,因此需要模拟所有传出的请求. +* **异步后台操作** :与单元测试类似,后台操作无法停止或等待. 这意味着它们将在以下测试中继续运行并产生副作用. +* **子组件** :每个组件都经过单独测试,因此要模拟子组件. 另请参见[`shallowMount()`](https://vue-test-utils.vuejs.org/api/#shallowmount) + +#### What *not* to mock in component tests[](#what-not-to-mock-in-component-tests "Permalink") + +* **被测组件的方法或计算属性** :通过模拟**被测组件的**一部分,将对模拟进行测试,而不是实际组件. +* **独立于 Vue 的函数和类** :单元测试已经涵盖了所有普通的 JavaScript 代码,无需在组件测试中进行模拟. + +## Integration tests[](#integration-tests "Permalink") + +正式定义: [https](https://en.wikipedia.org/wiki/Integration_testing) : [//en.wikipedia.org/wiki/Integration_testing](https://en.wikipedia.org/wiki/Integration_testing) + +这些测试可确保应用程序的各个部分可以很好地协同工作,而不会造成实际应用程序环境(即浏览器)的开销. 这些测试应在请求/响应级别进行声明:状态码,标头,正文. 它们对于测试权限,重定向,呈现的视图等很有用. + +| Code path | 测试路径 | 测试引擎 | Notes | +| --- | --- | --- | --- | +| `app/controllers/` | `spec/controllers/` | RSpec | 对于 N + 1 测试,请使用[请求规范](../query_recorder.html#use-request-specs-instead-of-controller-specs) | +| `app/mailers/` | `spec/mailers/` | RSpec |   | +| `lib/api/` | `spec/requests/api/` | RSpec |   | +| `app/assets/javascripts/` | `spec/javascripts/`, `spec/frontend/` | 因果 | [More details below](#frontend-integration-tests) | + +### Frontend integration tests[](#frontend-integration-tests "Permalink") + +集成测试涵盖单个页面上所有组件之间的交互. 它们的抽象级别可与用户与 UI 交互的方式进行比较. + +图 RL plain [普通 JavaScript]; Vue [Vue 组件]; feature-flags [功能标志]; 许可证检查[许可证检查]; 普通--Vuex; 普通--GraphQL; Vue--简单 Vue --- Vuex; Vue--GraphQL; 浏览器-普通 浏览器--- Vue; 普通-后端; Vuex-后端; GraphQL--后端; Vue-后端; 后端-数据库 后端-功能标记; 后端-许可证检查; 普通测试 经过 Vue 测试; 经过 Vuex 类测试; 经过 GraphQL 类测试; 经过类浏览器测试; linkStyle 0、1、2、3、4、5、6 笔画:#6666ff,笔画宽度:2px,笔划数组:5、5; classDef 节点颜色:#909090,填充:#f0f0f0,笔划宽度:2px,笔划:#909090 classDef 标签 stroke-width:0; classDef 测试的颜色:#000000,填充:#a0c0ff,笔划:#6666ff,笔划宽度:2px,笔划数组:5、5; 经过测试的子图; 嘲笑 等级测试 结束 + +#### When to use integration tests[](#when-to-use-integration-tests "Permalink") + +* **页面捆绑包( `app/assets/javascripts/pages/` `index.js`文件)** :测试页面捆绑包可确保相应的前端组件很好地集成. +* **页面捆绑之外的 Vue 应用程序** :对 Vue 应用程序进行整体测试可确保相应的前端组件很好地集成. + +#### What to mock in integration tests[](#what-to-mock-in-integration-tests "Permalink") + +* **HAML 视图(改为使用夹具)** :渲染 HAML 视图需要一个 Rails 环境,其中包括一个正在运行的数据库,您不能在前端测试中依赖它. +* **所有服务器请求** :类似于单元测试和组件测试,在运行组件测试时,后端可能无法访问,因此必须模拟所有传出的请求. +* **页面上无法感知的异步后台操作** :影响页面的后台操作必须在此级别上进行测试. 所有其他后台操作都无法停止或等待,因此它们将在以下测试中继续运行并产生副作用. + +#### What *not* to mock in integration tests[](#what-not-to-mock-in-integration-tests "Permalink") + +* **DOM** :在真实的 DOM 上进行测试可确保您的组件在预期的环境中工作. DOM 测试的一部分委托给[跨浏览器测试](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/45) . +* **组件的属性或状态** :在此级别上,所有测试只能执行用户将要执行的操作. 例如:要更改组件的状态,将触发 click 事件. +* **Vuex 存储** :整体上测试页面的前端代码时,还将涵盖 Vue 组件与 Vuex 存储之间的交互. + +### About controller tests[](#about-controller-tests "Permalink") + +在理想的世界中,控制器应该很薄. 但是,如果不是这种情况,则可以编写不使用 JavaScript 而不是控制器测试的系统或功能测试. 测试胖控制器通常涉及很多桩工作,例如: + +``` +controller.instance_variable_set(:@user, user) +``` + +并使用 Rails 5( [#23768](https://gitlab.com/gitlab-org/gitlab/-/issues/16260) )中不推荐使用的方法. + +### About Karma[](#about-karma "Permalink") + +业力同时在单元测试和集成测试类别中. 业力提供了运行 JavaScript 测试的环境,因此您可以运行单元测试(例如,测试单个 JavaScript 方法)或集成测试(例如,测试由多个组件组成的组件). + +## White-box tests at the system level (formerly known as System / Feature tests)[](#white-box-tests-at-the-system-level-formerly-known-as-system--feature-tests "Permalink") + +正式定义: + +* [https://en.wikipedia.org/wiki/System_testing](https://en.wikipedia.org/wiki/System_testing) +* [https://en.wikipedia.org/wiki/White-box_testing](https://en.wikipedia.org/wiki/White-box_testing) + +这些测试可确保 GitLab *Rails*应用程序(例如`gitlab-foss` / `gitlab` )从*浏览器的*角度正常工作. + +注意: + +* 仍需要了解应用程序内部的知识 +* 测试所需的数据通常是使用 RSpec 工厂直接创建的 +* 期望通常在数据库或对象状态上设置 + +这些测试仅在以下情况下使用: + +* 被测试的功能/组件很小 +* 对象/数据库的内部状态*需要*测试 +* 它不能在较低的水平上进行测试 + +例如,要测试给定页面上的面包屑,编写系统测试很有意义,因为它是一个很小的组件,无法在单元或控制器级别进行测试. + +仅测试幸福的道路,但要确保为使用更好的测试无法在较低级别上捕获到的任何回归添加测试用例(例如,如果找到了回归,则应在可能的最低级别上添加回归测试). + +| 测试路径 | 测试引擎 | Notes | +| --- | --- | --- | +| `spec/features/` | [Capybara](https://github.com/teamcapybara/capybara) + [RSpec](https://github.com/rspec/rspec-rails#feature-specs) | If your test has the `:js` metadata, the browser driver will be [Poltergeist](https://github.com/teamcapybara/capybara#poltergeist), otherwise it’s using [RackTest](https://github.com/teamcapybara/capybara#racktest). | + +### Frontend feature tests[](#frontend-feature-tests "Permalink") + +与[前端集成测试](#frontend-integration-tests)相反,功能测试针对真正的后端而不是使用固定装置发出请求. 这也意味着将执行数据库查询,这将大大降低该类别的速度. + +也可以看看: + +* The [RSpec testing guidelines](../testing_guide/best_practices.html#rspec). +* [测试最佳实践](best_practices.html#system--feature-tests)中的系统/功能测试. +* [第 26159 期](https://gitlab.com/gitlab-org/gitlab/-/issues/26159) ,旨在将这些准则与本页面结合在一起. + +图 RL plain [普通 JavaScript]; Vue [Vue 组件]; feature-flags [功能标志]; 许可证检查[许可证检查]; 普通--Vuex; 普通--GraphQL; Vue--简单 Vue --- Vuex; Vue--GraphQL; 浏览器-普通 浏览器--- Vue; 普通-后端; Vuex-后端; GraphQL--后端; Vue-后端; 后端-数据库 后端-功能标记; 后端-许可证检查; 经过类后端测试; 普通测试 经过 Vue 测试; 经过 Vuex 类测试; 经过 GraphQL 类测试; 经过类浏览器测试; linkStyle 0、1、2、3、4、5、6、7、8、9、10 笔画:#6666ff,笔划宽度:2px,笔划数组:5、5; classDef 节点颜色:#909090,填充:#f0f0f0,笔划宽度:2px,笔划:#909090 classDef 标签 stroke-width:0; classDef 测试的颜色:#000000,填充:#a0c0ff,笔划:#6666ff,笔划宽度:2px,笔划数组:5、5; 经过测试的子图; 嘲笑 等级测试 结束 + +#### When to use feature tests[](#when-to-use-feature-tests "Permalink") + +* 需要后端并且无法使用固定装置进行测试的用例. +* 行为不是页面捆绑的一部分,而是全局定义的. + +#### Relevant notes[](#relevant-notes "Permalink") + +`:js`标志已添加到测试中,以确保已加载完整环境: + +``` +scenario 'successfully', :js do + sign_in(create(:admin)) +end +``` + +每个测试的步骤都是使用( [水豚法](https://www.rubydoc.info/gems/capybara) )编写的. + +XHR(XMLHttpRequest)调用可能要求您在步骤之间使用`wait_for_requests` ,例如: + +``` +find('.form-control').native.send_keys(:enter) + +wait_for_requests + +expect(page).not_to have_selector('.card') +``` + +### Consider **not** writing a system test[](#consider-not-writing-a-system-test "Permalink") + +如果我们有信心低级组件可以正常工作(如果我们有足够的单元和集成测试,那就应该如此),我们就不需要在系统测试级别重复它们的全面测试. + +添加测试非常容易,但是删除或改进测试却要困难得多,因此应该注意不要引入太多(缓慢和重复的)测试. + +我们遵循这些最佳做法的原因如下: + +* 系统测试运行缓慢,因为它们会在无头浏览器中启动整个应用程序堆栈,而在集成 JS 驱动程序时甚至会更慢 +* 当系统测试使用 JavaScript 驱动程序运行时,测试将在与应用程序不同的线程中运行. 这意味着它不共享数据库连接,并且您的测试将必须提交事务才能使正在运行的应用程序看到数据(反之亦然). 在那种情况下,我们需要在每个规范之后截断数据库,而不是简单地回滚事务(用于其他类型测试的更快策略). 但是,这比事务处理要慢,因此我们只想在必要时使用截断. + +## Black-box tests at the system level, aka end-to-end tests[](#black-box-tests-at-the-system-level-aka-end-to-end-tests "Permalink") + +正式定义: + +* [https://en.wikipedia.org/wiki/System_testing](https://en.wikipedia.org/wiki/System_testing) +* [https://en.wikipedia.org/wiki/Black-box_testing](https://en.wikipedia.org/wiki/Black-box_testing) + +GitLab 由[多个组件](../architecture.html#components)组成,例如[GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell) , [GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) , [Gitaly](https://gitlab.com/gitlab-org/gitaly) , [GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages) , [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner)和 GitLab Rails. 所有这些部件均由[Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab)进行配置和包装. + +QA 框架和实例级场景是[GitLab Rails 的一部分,](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa)因此它们始终与代码库(尤其是视图)保持同步. + +注意: + +* 不需要了解应用程序内部 +* 测试所需的数据只能使用 GUI 或 API 创建 +* 只能针对浏览器页面和 API 响应做出期望 + +每个新功能都应附带[测试计划](https://gitlab.com/gitlab-org/gitlab/tree/master/.gitlab/issue_templates/Test plan.md) . + +| 测试路径 | 测试引擎 | Notes | +| --- | --- | --- | +| `qa/qa/specs/features/` | [Capybara](https://github.com/teamcapybara/capybara) + [RSpec](https://github.com/rspec/rspec-rails#feature-specs) +自定义质量检查框架 | 测试应放在相应的[产品类别下](https://about.gitlab.com/handbook/product/product-categories/) | + +> 有关更多信息,请参见[端对端测试](end_to_end/index.html) . + +请注意, `qa/spec`包含 QA 框架本身的[单元测试](#unit-tests) ,请勿与应用程序的[单元测试](#unit-tests)或[端到端](#black-box-tests-at-the-system-level-aka-end-to-end-tests) [测试](#unit-tests)相混淆. + +### Smoke tests[](#smoke-tests "Permalink") + +冒烟测试是可以随时运行的快速测试(尤其是在部署前迁移之后). + +这些测试针对 UI 运行,并确保基本功能正常运行. + +> 有关更多信息,请参见[烟雾测试](smoke.html) . + +### GitLab QA orchestrator[](#gitlab-qa-orchestrator "Permalink") + +[GitLab QA 协调器](https://gitlab.com/gitlab-org/gitlab-qa)是一种工具,可以通过为给定版本的 GitLab Rails 构建 Docker 映像并对其进行端到端测试(即使用 Capybara)来测试所有这些部分是否集成良好. + +在[GitLab 质量检查协调器自述文件中](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md)了解更多信息. + +## EE-specific tests[](#ee-specific-tests "Permalink") + +特定于 EE 的测试遵循相同的组织,但位于`ee/spec`文件夹下. + +## How to test at the correct level?[](#how-to-test-at-the-correct-level "Permalink") + +与生活中的许多事情一样,决定在每个测试级别上测试什么是一个权衡: + +* 单元测试通常很便宜,您应该将它们视为房子的地下室:您需要它们来确保您的代码行为正确. 但是,如果仅运行单元测试而不进行集成/系统测试,则可能会[错过](https://twitter.com/ThePracticalDev/status/850748070698651649) [大局](https://twitter.com/timbray/status/822470746773409794) / [大局](https://twitter.com/withzombies/status/829716565834752000) ! +* 集成测试要贵一些,但是请不要滥用它们. 系统测试通常比集成测试要好得多. +* 系统测试非常昂贵(与单元测试相比),如果它们需要 JavaScript 驱动程序,则价格甚至更高. 确保遵循" [速度"](best_practices.html#test-speed)部分中的准则. + +另一种看待它的方式是考虑"测试成本",本文对此进行了很好的解释[,](https://medium.com/table-xi/high-cost-tests-and-high-value-tests-a86e27a54df#.2ulyh3a4e)基本思想是测试成本包括: + +* 编写测试所需的时间 +* 套件每次运行都需要运行测试的时间 +* 了解测试所需的时间 +* 如果测试失败并且基础代码正常,则修复测试所花费的时间 +* 也许,更改代码以使其可测试所需的时间. + +### Frontend-related tests[](#frontend-related-tests "Permalink") + +在某些情况下,要测试的行为不值得花时间运行整个应用程序,例如,如果要测试样式,动画,边缘情况或不涉及后端的小动作,则应编写集成测试使用茉莉花. + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/docs/634.md b/docs/634.md new file mode 100644 index 0000000000000000000000000000000000000000..3b4263899d26f9838e102beddfd6e67db9e5b6cb --- /dev/null +++ b/docs/634.md @@ -0,0 +1,198 @@ +# Testing Rails migrations at GitLab + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/testing_migrations_guide.html](https://docs.gitlab.com/ee/development/testing_guide/testing_migrations_guide.html) + +* [When to write a migration test](#when-to-write-a-migration-test) +* [How does it work?](#how-does-it-work) +* [Testing an `ActiveRecord::Migration` class](#testing-an-activerecordmigration-class) + * [Test helpers](#test-helpers) + * [`table`](#table) + * [`migrate!`](#migrate) + * [`reversible_migration`](#reversible_migration) + * [Example database migration test](#example-database-migration-test) +* [Testing a non-`ActiveRecord::Migration` class](#testing-a-non-activerecordmigration-class) + * [Example background migration test](#example-background-migration-test) + +# Testing Rails migrations at GitLab[](#testing-rails-migrations-at-gitlab "Permalink") + +为了可靠地检查 Rails 迁移,我们需要针对数据库架构对其进行测试. + +## When to write a migration test[](#when-to-write-a-migration-test "Permalink") + +* 后期迁移( `/db/post_migrate` )和后台迁移( `lib/gitlab/background_migration` ) **必须**执行迁移测试. +* 如果您的迁移是数据迁移,那么它**必须**具有迁移测试. +* 如有必要,其他迁移可能会进行迁移测试. + +## How does it work?[](#how-does-it-work "Permalink") + +在测试签名中添加`:migration`标记,可以在[`spec/support/migration.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/f81fa6ab1dd788b70ef44b85aaba1f31ffafae7d/spec/support/migration.rb)挂钩`before`和`after`运行一些自定义 RSpec. + +`before`钩子会将所有迁移还原到尚未迁移被测试的迁移点. + +换句话说,我们的自定义 RSpec 挂钩将找到以前的迁移,并将数据库**向下**迁移到以前的迁移版本. + +使用这种方法,您可以针对数据库架构测试迁移. + +一个`after`钩子将数据库迁移**并** reinstitute 最新的架构版本,因此该方法不会影响后续的规格,并确保适当的隔离. + +## Testing an `ActiveRecord::Migration` class[](#testing-an-activerecordmigration-class "Permalink") + +要测试`ActiveRecord::Migration`类(即常规迁移`db/migrate`或迁移后`db/post_migrate` ),您将需要手动`require`迁移文件,因为它不会随 Rails 自动加载. 例: + +``` +require Rails.root.join('db', 'post_migrate', '20170526185842_migrate_pipeline_stages.rb') +``` + +### Test helpers[](#test-helpers "Permalink") + +#### `table`[](#table "Permalink") + +使用`table`助手为`table`创建一个临时的`ActiveRecord::Base`派生模型. [FactoryBot](best_practices.html#factories) **不**应用于为迁移规范创建数据. 例如,要在`projects`表中创建一条记录: + +``` +project = table(:projects).create!(id: 1, name: 'gitlab1', path: 'gitlab1') +``` + +#### `migrate!`[](#migrate "Permalink") + +使用`migrate!` 帮助程序来运行正在测试的迁移. 它不仅将运行迁移,还将在`schema_migrations`表中增加模式版本. 这是必要的,因为在`after`钩中,我们会触发其余的迁移,并且我们需要知道从哪里开始. 例: + +``` +it 'migrates successfully' do + # ... pre-migration expectations + + migrate! + + # ... post-migration expectations +end +``` + +#### `reversible_migration`[](#reversible_migration "Permalink") + +Use the `reversible_migration` helper to test migrations with either a `change` or both `up` and `down` hooks. This will test that the state of the application and its data after the migration becomes reversed is the same as it was before the migration ran in the first place. The helper: + +1. 在**向上**迁移之前运行`before`期望. +2. Migrates **up**. +3. 运行`after`期望. +4. Migrates **down**. +5. `before`运行`before`期望. + +Example: + +``` +reversible_migration do |migration| + migration.before -> { + # ... pre-migration expectations + } + + migration.after -> { + # ... post-migration expectations + } +end +``` + +### Example database migration test[](#example-database-migration-test "Permalink") + +该规范测试了[`db/post_migrate/20170526185842_migrate_pipeline_stages.rb`](https://gitlab.com/gitlab-org/gitlab-foss/blob/v11.6.5/db/post_migrate/20170526185842_migrate_pipeline_stages.rb)迁移. 您可以在[`spec/migrations/migrate_pipeline_stages_spec.rb`](https://gitlab.com/gitlab-org/gitlab-foss/blob/v11.6.5/spec/migrations/migrate_pipeline_stages_spec.rb)找到完整的规范. + +``` +require 'spec_helper' +require Rails.root.join('db', 'post_migrate', '20170526185842_migrate_pipeline_stages.rb') + +RSpec.describe MigratePipelineStages do + # Create test data - pipeline and CI/CD jobs. + let(:jobs) { table(:ci_builds) } + let(:stages) { table(:ci_stages) } + let(:pipelines) { table(:ci_pipelines) } + let(:projects) { table(:projects) } + + before do + projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1') + pipelines.create!(id: 1, project_id: 123, ref: 'master', sha: 'adf43c3a') + jobs.create!(id: 1, commit_id: 1, project_id: 123, stage_idx: 2, stage: 'build') + jobs.create!(id: 2, commit_id: 1, project_id: 123, stage_idx: 1, stage: 'test') + end + + # Test just the up migration. + it 'correctly migrates pipeline stages' do + expect(stages.count).to be_zero + + migrate! + + expect(stages.count).to eq 2 + expect(stages.all.pluck(:name)).to match_array %w[test build] + end + + # Test a reversible migration. + it 'correctly migrates up and down pipeline stages' do + reversible_migration do |migration| + # Expectations will run before the up migration, + # and then again after the down migration + migration.before -> { + expect(stages.count).to be_zero + } + + # Expectations will run after the up migration. + migration.after -> { + expect(stages.count).to eq 2 + expect(stages.all.pluck(:name)).to match_array %w[test build] + } + end +end +``` + +## Testing a non-`ActiveRecord::Migration` class[](#testing-a-non-activerecordmigration-class "Permalink") + +要测试非`ActiveRecord::Migration`测试(后台迁移),您将需要手动提供所需的架构版本. 请向要在其中切换数据库架构的上下文中添加`schema`标签. + +如果未设置,则`schema`默认为`:latest` . + +Example: + +``` +describe SomeClass, schema: 20170608152748 do + # ... +end +``` + +### Example background migration test[](#example-background-migration-test "Permalink") + +该规范测试了[`lib/gitlab/background_migration/archive_legacy_traces.rb`](https://gitlab.com/gitlab-org/gitlab-foss/blob/v11.6.5/lib/gitlab/background_migration/archive_legacy_traces.rb)背景迁移. 您可以在[`spec/lib/gitlab/background_migration/archive_legacy_traces_spec.rb`](https://gitlab.com/gitlab-org/gitlab-foss/blob/v11.6.5/spec/lib/gitlab/background_migration/archive_legacy_traces_spec.rb)找到完整的规范 + +``` +require 'spec_helper' + +describe Gitlab::BackgroundMigration::ArchiveLegacyTraces, schema: 20180529152628 do + include TraceHelpers + + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:builds) { table(:ci_builds) } + let(:job_artifacts) { table(:ci_job_artifacts) } + + before do + namespaces.create!(id: 123, name: 'gitlab1', path: 'gitlab1') + projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1', namespace_id: 123) + @build = builds.create!(id: 1, project_id: 123, status: 'success', type: 'Ci::Build') + end + + context 'when trace file exists at the right place' do + before do + create_legacy_trace(@build, 'trace in file') + end + + it 'correctly archive legacy traces' do + expect(job_artifacts.count).to eq(0) + expect(File.exist?(legacy_trace_path(@build))).to be_truthy + + described_class.new.perform(1, 1) + + expect(job_artifacts.count).to eq(1) + expect(File.exist?(legacy_trace_path(@build))).to be_falsy + expect(File.read(archived_trace_path(job_artifacts.first))).to eq('trace in file') + end + end +end +``` + +**注意:**由于我们使用删除数据库清除策略,因此这些测试不在数据库事务中运行. 不要依赖存在的事务. \ No newline at end of file diff --git a/docs/635.md b/docs/635.md new file mode 100644 index 0000000000000000000000000000000000000000..c3d5210c1902c8d19f32e5694539acdd34268203 --- /dev/null +++ b/docs/635.md @@ -0,0 +1,37 @@ +# Testing Rake tasks + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/testing_rake_tasks.html](https://docs.gitlab.com/ee/development/testing_guide/testing_rake_tasks.html) + +# Testing Rake tasks[](#testing-rake-tasks "Permalink") + +为了使测试 Rake 任务更容易一些,可以使用一个辅助程序来代替标准 Spec 辅助程序. 代替`require 'spec_helper'` ,使用`require 'rake_helper'` . 该帮助程序包括为您提供的`spec_helper` ,并配置了一些其他内容以使测试 Rake 任务更加容易. + +至少需要 Rake 帮助程序重定向`stdout` ,包括运行时任务帮助程序,并包括`RakeHelpers` Spec 支持模块. + +`RakeHelpers`模块公开了`run_rake_task(<task>)`方法以简化执行任务. 有关所有可用方法,请参见`spec/support/helpers/rake_helpers.rb` . + +Example: + +``` +require 'rake_helper' + +describe 'gitlab:shell rake tasks' do + before do + Rake.application.rake_require 'tasks/gitlab/shell' + + stub_warn_user_is_not_gitlab + end + + describe 'install task' do + it 'invokes create_hooks task' do + expect(Rake::Task['gitlab:shell:create_hooks']).to receive(:invoke) + + run_rake_task('gitlab:shell:install') + end + end +end +``` + +* * * + +[Return to Testing documentation](index.html) \ No newline at end of file diff --git a/docs/636.md b/docs/636.md new file mode 100644 index 0000000000000000000000000000000000000000..69261b63437eb7ae1adbf6273f83d80bce03aea4 --- /dev/null +++ b/docs/636.md @@ -0,0 +1,133 @@ +# End-to-end Testing + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/) + +* [What is end-to-end testing?](#what-is-end-to-end-testing) +* [How do we test GitLab?](#how-do-we-test-gitlab) + * [Testing nightly builds](#testing-nightly-builds) + * [Testing staging](#testing-staging) + * [Testing code in merge requests](#testing-code-in-merge-requests) + * [Using the `package-and-qa` job](#using-the-package-and-qa-job) + * [How does it work?](#how-does-it-work) + * [With Pipeline for Merged Results](#with-pipeline-for-merged-results) + * [Running custom tests](#running-custom-tests) + * [Using the `review-qa-all` jobs](#using-the-review-qa-all-jobs) +* [How do I run the tests?](#how-do-i-run-the-tests) + * [Running tests that require special setup](#running-tests-that-require-special-setup) +* [How do I write tests?](#how-do-i-write-tests) +* [Where can I ask for help?](#where-can-i-ask-for-help) + +# End-to-end Testing[](#end-to-end-testing "Permalink") + +## What is end-to-end testing?[](#what-is-end-to-end-testing "Permalink") + +端到端测试是一种策略,用于检查您的应用程序在整个软件堆栈和体系结构中是否按预期工作,包括应该协同工作的所有微服务和组件的集成. + +## How do we test GitLab?[](#how-do-we-test-gitlab "Permalink") + +我们使用[Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab)构建 GitLab 程序包,然后使用[GitLab QA 协调器](https://gitlab.com/gitlab-org/gitlab-qa)工具测试这些程序包,该工具是 API 和 UI 的黑盒测试框架. + +### Testing nightly builds[](#testing-nightly-builds "Permalink") + +我们每天晚上运行预定的管道,以测试 Omnibus 创建的每晚构建. 您可以在`https://gitlab.com/gitlab-org/quality/nightly/pipelines` (需要开发人员访问权限)中找到这些夜间管道. 结果在`#qa-nightly` Slack 频道中报告. + +### Testing staging[](#testing-staging "Permalink") + +我们每天晚上运行预定的管道以测试阶段. 您可以在`https://gitlab.com/gitlab-org/quality/staging/pipelines` (需要开发人员访问权限)中找到这些夜间管道. 结果在`#qa-staging` Slack 频道中报告. + +### Testing code in merge requests[](#testing-code-in-merge-requests "Permalink") + +#### Using the `package-and-qa` job[](#using-the-package-and-qa-job "Permalink") + +通过在`test`阶段触发`package-and-qa`手动操作,可以对合并请求运行端到端测试,最终在[`gitlab-qa-mirror`](https://gitlab.com/gitlab-org/gitlab-qa-mirror/)项目的管道中运行(不适用于 fork) ). + +**这将针对根据合并请求的更改构建的自定义 CE 和 EE(具有终极许可证)Omnibus 程序包进行端到端测试.** + +[Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab)中的合并请求中也提供了启动端到端测试的手动操作. + +您可以在下面阅读有关如何使用它以及如何工作的更多信息. + +#### How does it work?[](#how-does-it-work "Permalink") + +当前,我们正在使用类似*多项目管道*的方法来运行质量检查管道. + +图 LR A1 -.-> | 1\. 触发 omnibus-gitlab-mirror 管道并等待它完成| A2 B2 [`Trigger-qa`阶段 +`Trigger:qa-test`工作] -.-> | 2\. 触发 gitlab-qa-mirror 管道并等待它完成| A3 子图" gitlab-foss / gitlab 管道" A1 [`test`阶段 +"打包和质量检查"工作]结束子图" omnibus-gitlab 管道" A2 [`Trigger-docker`阶段 +`Trigger:gitlab-docker`作业]-> |一旦完成| B2 结束子图" gitlab-qa-镜像管道" A3> QA 作业运行] -.-> | 3\. 将管道结果报告给"打包和质量检查"作业 +并将结果发布到经过测试的原始提交| A1 端 + +1. 开发人员触发手动操作,可以在 GitLab 合并请求中找到该操作. 这将启动多个项目中的一系列管道. + +2. 正在执行的脚本触发[Omnibus GitLab Mirror 中](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror)的管道,并等待结果状态. 我们将此称为*状态归因* . + +3. 在[Omnibus GitLab Mirror](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror)管道中正在构建 GitLab 软件包. 然后将程序包推送到其容器注册表. + +4. 当软件包准备就绪并在注册表中可用时, [Omnibus GitLab Mirror](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror)管道的最后一步将触发新的 GitLab QA 管道(具有访问权限的人可以在`https://gitlab.com/gitlab-org/gitlab-qa-mirror/pipelines`查看它们) `https://gitlab.com/gitlab-org/gitlab-qa-mirror/pipelines` ). 它还等待结果状态. + +5. GitLab QA 从注册表中提取图像,旋转容器,并针对刚刚由`gitlab-qa`工具精心策划的测试环境运行测试. + +6. GitLab QA 管道的结果正在通过 Omnibus 上游传播回 GitLab 合并请求. + +请注意,我们计划[添加](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/156)有关`gitlab-qa-mirror`中运行的每个作业/场景中包含的测试的[更多特定信息](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/156) . + +#### With Pipeline for Merged Results[](#with-pipeline-for-merged-results "Permalink") + +在"合并结果的管道"中,管道在包含源分支和目标分支的合并结果的新引用上运行. 但是,此参考不适用于`gitlab-qa-mirror`管道. + +因此,在"合并结果"管道上的端到端测试将使用合并请求源分支的头部. + +graph LR A["a1b1c1 - branch HEAD (CI_MERGE_REQUEST_SOURCE_BRANCH_SHA)"] B["x1y1z1 - master HEAD"] C["d1e1f1 - merged results (CI_COMMIT_SHA)"] A --> C B --> C A --> E["E2E tests"] C --> D["Pipeline for merged results"] + +##### Running custom tests[](#running-custom-tests "Permalink") + +在下游`gitlab-qa-mirror`管道中运行的[现有场景](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md)包括许多测试,但是有时您可能想要运行一个测试或一组与任何现有场景中的组不同的测试. + +例如,当我们[对](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#dequarantining-tests)一个薄片状测试进行[隔离](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#dequarantining-tests)时,我们首先要确保它不再是薄片状的. 我们可以使用`ce:custom-parallel`和`ee:custom-parallel`作业来做到这一点. 两者都是手动作业,您可以使用自定义变量进行配置. 单击并行作业之一的名称(而不是播放图标)时,系统将提示您输入变量. 您可以使用[`gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables)可以使用的任何[变量](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables)以及这些[变量](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables) : + +| Variable | Description | +| --- | --- | +| `QA_SCENARIO` | 要运行的方案(默认`Test::Instance::Image` ) | +| `QA_TESTS` | 要运行的测试(没有默认设置,这意味着运行方案中的所有测试). 通过 RSpec 运行测试时,请使用文件路径,例如, `qa/specs/features/ee/browser_ui`将包括所有`EE` UI 测试. | +| `QA_RSPEC_TAGS` | 要添加的 RSpec 标记(无默认值) | + +现在, [具有自定义变量的手动作业在重试时将不会使用相同的变量](https://gitlab.com/gitlab-org/gitlab/-/issues/31367) ,因此,如果要多次运行相同的测试,请在每个`custom-parallel`作业中指定相同的变量(最多可使用 10 个变量)您要运行的作业). + +#### Using the `review-qa-all` jobs[](#using-the-review-qa-all-jobs "Permalink") + +在`test`阶段的每个管道上,都会自动启动`review-qa-smoke`作业:它将针对[Review App](../review_apps.html)运行 QA 烟雾套件. + +您还可以手动启动`review-qa-all` :它针对[Review App](../review_apps.html)运行完整的质量检查套件. + +**This runs end-to-end tests against a Review App based on [the official GitLab Helm chart](https://gitlab.com/gitlab-org/charts/gitlab/), itself deployed with custom [Cloud Native components](https://gitlab.com/gitlab-org/build/CNG) built from your merge request’s changes.** + +有关[审阅应用程序](../review_apps.html)的更多详细信息,请参见[审阅应用](../review_apps.html)程序. + +## How do I run the tests?[](#how-do-i-run-the-tests "Permalink") + +如果您不是[在合并请求中测试代码](#testing-code-in-merge-requests) ,则有两个主要选项可用于运行测试. 如果您只想对一个实时的 GitLab 实例或一个预先构建的 Docker 映像运行现有测试,则可以使用[GitLab QA 协调器](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md) . 另请参见[可以通过 Orchestrator 运行的测试方案示例](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#examples) . + +另一方面,如果您想在本地开发的 GitLab 环境中运行,则可以使用[GitLab 开发工具包(GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/) . 请参考[质量检查自述文件](https://gitlab.com/gitlab-org/gitlab/tree/master/qa/README.md#how-can-i-use-it)和以下部分中的说明. + +### Running tests that require special setup[](#running-tests-that-require-special-setup "Permalink") + +了解如何执行[需要特殊设置或考虑才能在本地环境上运行的测试](running_tests_that_require_special_setup.html) . + +## How do I write tests?[](#how-do-i-write-tests "Permalink") + +为了编写新的测试,您首先需要了解有关 GitLab QA 体系结构的更多信息. 请参阅有关[文档](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/architecture.md) . + +一旦决定了将[测试环境业务流程场景](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/lib/gitlab/qa/scenario)和[实例级场景](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features)放置在何处,请查看[GitLab QA 自述文件](https://gitlab.com/gitlab-org/gitlab/tree/master/qa/README.md) , [GitLab QA Orchestrator 自述文件](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md)和[已经存在的实例级场景](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features) . + +继续阅读: + +* [Beginner’s Guide](beginners_guide.html) +* [Style Guide](style_guide.html) +* [Best Practices](best_practices.html) +* [Testing with feature flags](feature_flags.html) +* [Flows](flows.html) +* [RSpec metadata/tags](rspec_metadata_tests.html) + +## Where can I ask for help?[](#where-can-i-ask-for-help "Permalink") + +您可以在 Slack 上的`#quality`频道(GitLab 内部)上[`gitlab`](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name[]=QA&label_name[]=test) ,或者[在`gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/-/issues?label_name[]=new+scenario) [问题跟踪器](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name[]=QA&label_name[]=test)或[`gitlab-qa`问题跟踪器中](https://gitlab.com/gitlab-org/gitlab-qa/-/issues?label_name[]=new+scenario)找到您要[`gitlab-qa`问题](https://gitlab.com/gitlab-org/gitlab-qa/-/issues?label_name[]=new+scenario) . \ No newline at end of file diff --git a/docs/637.md b/docs/637.md new file mode 100644 index 0000000000000000000000000000000000000000..9c78d707286ab1b598aab67a5b2a80383e040407 --- /dev/null +++ b/docs/637.md @@ -0,0 +1,314 @@ +# Beginner's guide to writing end-to-end tests + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/beginners_guide.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/beginners_guide.html) + +* [Before you write a test](#before-you-write-a-test) +* [Determine if end-to-end tests are needed](#determine-if-end-to-end-tests-are-needed) +* [Identify the DevOps stage](#identify-the-devops-stage) +* [Create a skeleton test](#create-a-skeleton-test) + * [The outer `context` block](#the-outer-context-block) + * [The outer `RSpec.describe` block](#the-outer-rspecdescribe-block) + * [The `describe` block](#the-describe-block) + * [The `it` blocks (examples)](#the-it-blocks-examples) +* [Write the test](#write-the-test) +* [De-duplicate your code](#de-duplicate-your-code) +* [Test setup using resources and page objects](#test-setup-using-resources-and-page-objects) +* [Write the page object](#write-the-page-object) +* [Run the spec](#run-the-spec) + +# Beginner’s guide to writing end-to-end tests[](#beginners-guide-to-writing-end-to-end-tests "Permalink") + +在本教程中,您将学习如何为[GitLab 社区版](https://about.gitlab.com/install/?version=ce)和[GitLab 企业版](https://about.gitlab.com/install/)创建端到端( *e2e* )测试. + +在本教程结束时,您将能够: + +* 确定是否需要端到端测试. +* Understand the directory structure within `qa/`. +* 编写一个基本的端到端测试,以验证登录功能. +* 开发任何缺少的[页面对象](page_objects.html)库. + +## Before you write a test[](#before-you-write-a-test "Permalink") + +在编写测试之前,必须将您的[GitLab 开发套件(GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit)配置为运行规范. 端到端测试: + +* 包含在`qa/`目录中. +* 应该是独立和[幂等的](https://en.wikipedia.org/wiki/Idempotence#Computer_science_meaning) . +* 临时创建[资源](resources.html) (例如项目,问题,用户). +* Test the UI and API interfaces, and use the API to efficiently set up the UI tests. + +**提示:**有关更多信息,请参阅[端到端测试最佳实践](best_practices.html) . + +## Determine if end-to-end tests are needed[](#determine-if-end-to-end-tests-are-needed "Permalink") + +在编写端到端测试之前,请为[GitLab 社区版](https://gitlab-org.gitlab.io/gitlab-foss/coverage-ruby/#_AllFiles)和[GitLab 企业版](https://gitlab-org.gitlab.io/gitlab/coverage-ruby/#_AllFiles)项目检查特定功能的代码覆盖率. 在单元,功能或集成级别上是否存在足够的测试范围? 如果回答*是肯定的* ,那么你*就*需要一个终端到终端的测试. + +有关 GitLab 中每个级别的测试分布的信息,请参见[测试级别](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/testing_guide/testing_levels.md) . + +* 请参阅[如何以正确的级别进行测试?](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/testing_guide/testing_levels.md#how-to-test-at-the-correct-level) " [测试级别"](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/testing_guide/testing_levels.md)文档的"部分". +* 查看功能更改的频率. 如果较低级别的测试中已经包含了稳定的特性,那么这些特性不会经常更改,那么端到端测试可能就不值得考虑. +* 最后,与参与实现功能和较低级别测试的开发人员讨论建议的测试. + +**注意:**检查[GitLab 社区版](https://gitlab-org.gitlab.io/gitlab-foss/coverage-ruby/#_AllFiles)和[GitLab 企业版](https://gitlab-org.gitlab.io/gitlab/coverage-ruby/#_AllFiles)覆盖率项目,以检查是否为此功能编写了以前的测试. 为了分析代码覆盖率,您必须了解哪些应用程序文件实现了特定功能.**注意:**在本教程中,我们将编写一个登录端到端测试,即使它已经被较低级别的测试所覆盖,因为这是大多数端到端流的第一步,并且最容易理解. + +## Identify the DevOps stage[](#identify-the-devops-stage "Permalink") + +GitLab QA 端到端测试是由[DevOps 生命周期](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features/browser_ui)的不同[阶段](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features/browser_ui)组织的. 确定应按[阶段](https://about.gitlab.com/handbook/product/product-categories/#devops-stages)放置测试的位置,确定该测试属于哪个功能,然后将其放置在该阶段下的子目录中. + +[![DevOps lifecycle by stages](img/31396caea61831939862213abb8dd10c.png)](img/gl-devops-lifecycle-by-stage-numbers_V12_10.png) + +**注意:**如果该测试仅是企业版,则将在`features/ee`目录中创建该测试,但遵循相同的 DevOps 生命周期格式. + +## Create a skeleton test[](#create-a-skeleton-test "Permalink") + +在本教程的第一部分中,我们将测试由 Manage 阶段拥有的登录名. 在`qa/specs/features/browser_ui/1_manage/login` ,创建文件`basic_login_spec.rb` . + +### The outer `context` block[](#the-outer-context-block "Permalink") + +参见[`RSpec.describe`外部块](#the-outer-rspecdescribe-block) + +**弃用声明:**遵循 RSpec 4.0 规范在`13.2`中[弃用](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/550)了外部`context` . 请改用`RSpec.describe` . + +### The outer `RSpec.describe` block[](#the-outer-rspecdescribe-block "Permalink") + +规格具有外部`RSpec.describe`指示 DevOps 阶段. + +``` +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + + end +end +``` + +### The `describe` block[](#the-describe-block "Permalink") + +在我们的外部`RSpec.describe`内部,描述要测试的功能. 在这种情况下,请`Login` . + +``` +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + describe 'Login' do + + end + end +end +``` + +### The `it` blocks (examples)[](#the-it-blocks-examples "Permalink") + +每个测试套件包含至少一个`it`阻断(实施例). 一个好方法,开始写终端到终端的测试是编写测试用例描述为`it`块: + +``` +module QA + RSpec.describe 'Manage' do + describe 'Login' do + it 'can login' do + + end + + it 'can logout' do + + end + end + end +end +``` + +## Write the test[](#write-the-test "Permalink") + +一个重要的问题是"我们要测试什么?" 更重要的是,"我们如何测试?" + +首先登录. + +``` +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + describe 'Login' do + it 'can login' do + Flow::Login.sign_in + + end + + it 'can logout' do + Flow::Login.sign_in + + end + end + end +end +``` + +[运行规范后](#run-the-spec) ,我们的测试应登录并结束; 那么我们应该回答"我们要测试什么?"这个问题. + +``` +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + describe 'Login' do + it 'can login' do + Flow::Login.sign_in + + Page::Main::Menu.perform do |menu| + expect(menu).to be_signed_in + end + end + + it 'can logout' do + Flow::Login.sign_in + + Page::Main::Menu.perform do |menu| + menu.sign_out + + expect(menu).not_to be_signed_in + end + end + end + end +end +``` + +**我们要测试什么?** + +1. 我们可以登录吗? +2. 我们可以注销吗? + +**我们如何测试?** + +1. 检查用户头像是否出现在顶部导航中. +2. 检查用户头像*是否未*出现在顶部导航中. + +**注意:**在幕后, `be_signed_in`是一个[谓词匹配器](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/built-in-matchers/predicate-matchers) ,可[实现对用户头像的检查](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/page/main/menu.rb#L74) . + +## De-duplicate your code[](#de-duplicate-your-code "Permalink") + +将测试重构为使用`before`块进行测试设置,因为它复制了对`sign_in`的调用. + +``` +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + describe 'Login' do + before do + Flow::Login.sign_in + end + + it 'can login' do + Page::Main::Menu.perform do |menu| + expect(menu).to be_signed_in + end + end + + it 'can logout' do + Page::Main::Menu.perform do |menu| + menu.sign_out + + expect(menu).not_to be_signed_in + end + end + end + end +end +``` + +`before`块本质上是一个`before(:each)`并且在每个示例之前运行,确保我们现在在每个测试的开始处登录. + +## Test setup using resources and page objects[](#test-setup-using-resources-and-page-objects "Permalink") + +接下来,让我们测试登录以外的其他功能. 让我们测试"计划"阶段拥有的"问题",因此在`qa/specs/features/browser_ui/3_create/issues` [创建一个](#identify-the-devops-stage)名为`issues_spec.rb` . + +``` +# frozen_string_literal: true + +module QA + RSpec.describe 'Plan' do + describe 'Issues' do + let(:issue) do + Resource::Issue.fabricate_via_api! do |issue| + issue.title = 'My issue' + issue.description = 'This is an issue specific to this test' + end + end + + before do + Flow::Login.sign_in + issue.visit! + end + + it 'can close an issue' do + Page::Project::Issue::Show.perform do |show| + show.click_close_issue_button + + expect(show).to be_closed + end + end + end + end +end +``` + +请注意以下要点: + +* 在我们的示例开始时,我们将在`page/issue/show.rb` [页面](page_objects.html) . +* 我们的测试仅在需要时制造需要的东西. +* 该问题是通过 API 伪造的,以节省时间. +* GitLab 更喜欢`let()`不是实例变量. 查看[最佳做法](../best_practices.html#let-variables) . +* `be_closed`尚未在`page/project/issue/show.rb`中实现,但将在下一步中实现. + +该问题被伪装成[Resource](resources.html) ,它是您可以通过 UI 或 API 创建的 GitLab 实体. 其他示例包括: + +* A [Merge Request](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/resource/merge_request.rb). +* A [User](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/resource/user.rb). +* A [Project](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/resource/project.rb). +* A [Group](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/resource/group.rb). + +## Write the page object[](#write-the-page-object "Permalink") + +[Page Object](page_objects.html)是我们套件中的一个类,代表 GitLab 中的一个页面. **登录**页面就是一个例子. 由于我们的" **问题显示"**页面的页面对象已经存在,请添加`closed?` 方法. + +``` +module Page::Project::Issue + class Show + view 'app/views/projects/issues/show.html.haml' do + element :closed_status_box + end + + def closed? + has_element?(:closed_status_box) + end + end +end +``` + +接下来,在视图中定义元素`closed_status_box` ,以便页面对象可以看到它. + +``` +-#=> app/views/projects/issues/show.html.haml .issuable-status-box.status-box.status-box-issue-closed{ ..., data: { qa_selector: 'closed_status_box' } } +``` + +## Run the spec[](#run-the-spec "Permalink") + +在运行规范之前,请确认: + +* GDK 已安装. +* GDK 在本地 3000 端口上运行. +* 尚未应用其他[RSpec 元数据标签](rspec_metadata_tests.html) . +* 您的工作目录是 GDK GitLab 安装中的`qa/` . + +要运行该规范,请运行以下命令: + +``` +bundle exec bin/qa Test::Instance::All http://localhost:3000 -- <test_file> +``` + +Where `<test_file>` is: + +* 运行"登录"示例时,请输入`qa/specs/features/browser_ui/1_manage/login/login_spec.rb` . +* 运行"问题"示例时,请执行`qa/specs/features/browser_ui/2_plan/issues/issue_spec.rb` . \ No newline at end of file diff --git a/docs/638.md b/docs/638.md new file mode 100644 index 0000000000000000000000000000000000000000..aed4287200aa5384830e525a8f6fe3c240077d68 --- /dev/null +++ b/docs/638.md @@ -0,0 +1,144 @@ +# End-to-end testing Best Practices + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html) + +* [Prefer API over UI](#prefer-api-over-ui) +* [Avoid superfluous expectations](#avoid-superfluous-expectations) +* [Prefer to split tests across multiple files](#prefer-to-split-tests-across-multiple-files) +* [Limit the use of the UI in `before(:context)` and `after` hooks](#limit-the-use-of-the-ui-in-beforecontext-and-after-hooks) +* [Ensure tests do not leave the browser logged in](#ensure-tests-do-not-leave-the-browser-logged-in) +* [Tag tests that require Administrator access](#tag-tests-that-require-administrator-access) +* [Prefer `Commit` resource over `ProjectPush`](#prefer-commit-resource-over-projectpush) + +# End-to-end testing Best Practices[](#end-to-end-testing-best-practices "Permalink") + +**注意:**这是[测试指南中](../best_practices.html)最佳实践的量身定制的扩展. + +## Prefer API over UI[](#prefer-api-over-ui "Permalink") + +端到端测试框架能够根据具体情况来构造其资源. 应尽可能通过 API 来构造资源. + +通过 API 构造测试所需的资源,我们可以节省时间和金钱. + +[Learn more](resources.html) about resources. + +## Avoid superfluous expectations[](#avoid-superfluous-expectations "Permalink") + +为了使测试保持精简,重要的是我们仅测试需要测试的内容. + +确保不添加任何与需要测试的内容无关的`expect()`语句. + +例如: + +``` +#=> Good +Flow::Login.sign_in +Page::Main::Menu.perform do |menu| + expect(menu).to be_signed_in +end + +#=> Bad +Flow::Login.sign_in(as: user) +Page::Main::Menu.perform do |menu| + expect(menu).to be_signed_in + expect(page).to have_content(user.name) #=> we already validated being signed in. redundant. + expect(menu).to have_element(:nav_bar) #=> likely unnecessary. already validated in lower-level. test doesn't call for validating this. +end + +#=> Good +issue = Resource::Issue.fabricate_via_api! do |issue| + issue.name = 'issue-name' +end + +Project::Issues::Index.perform do |index| + expect(index).to have_issue(issue) +end + +#=> Bad +issue = Resource::Issue.fabricate_via_api! do |issue| + issue.name = 'issue-name' +end + +Project::Issues::Index.perform do |index| + expect(index).to have_issue(issue) + expect(page).to have_content(issue.name) #=> page content check is redundant as the issue was already validated in the line above. +end +``` + +## Prefer to split tests across multiple files[](#prefer-to-split-tests-across-multiple-files "Permalink") + +我们的框架包括几个并行化机制,这些机制通过并行执行 spec 文件来工作. + +但是,由于测试是通过 spec *文件*而不是通过 test / example 并行化的,因此如果将新测试添加到现有文件中,我们将无法实现更大的并行化. + +尽管如此,可能还有其他原因要向现有文件添加新测试. + +例如,如果测试共享状态的设置成本很高,则即使执行一次使用该设置的测试无法并行化,执行一次设置可能会更有效. + +综上所述: + +* **可以** :将测试拆分到单独的文件中,除非测试共享昂贵的设置. +* **不要** :在不考虑对并行化的影响的情况下,将新测试放在现有文件中. + +## Limit the use of the UI in `before(:context)` and `after` hooks[](#limit-the-use-of-the-ui-in-beforecontext-and-after-hooks "Permalink") + +限制使用`before(:context)`挂钩仅通过 API 调用,非 UI 操作或基本 UI 操作(例如登录`before(:context)`来执行设置任务. + +我们使用[`capybara-screenshot`](https://github.com/mattheworiordan/capybara-screenshot)库自动保存失败时的屏幕截图. + +`capybara-screenshot` [将屏幕](https://github.com/mattheworiordan/capybara-screenshot/blob/master/lib/capybara-screenshot/rspec.rb#L97) `capybara-screenshot` [保存在 RSpec 的`after` hook 中](https://github.com/mattheworiordan/capybara-screenshot/blob/master/lib/capybara-screenshot/rspec.rb#L97) . [如果`before(:context)`失败,则不会调用`after`挂钩](https://github.com/rspec/rspec-core/pull/2652/files#diff-5e04af96d5156e787f28d519a8c99615R148) ,因此不会保存屏幕截图. + +鉴于这一事实,我们应该将`before(:context)`使用仅限于不需要屏幕快照的那些操作. + +同样, `after`钩子仅应用于非 UI 操作. 测试文件中`after` hook 中的任何 UI 操作都将在获取屏幕快照的`after` hook 之前执行. 这将导致 UI 状态从故障点移开,因此无法在正确的时刻捕获屏幕截图. + +## Ensure tests do not leave the browser logged in[](#ensure-tests-do-not-leave-the-browser-logged-in "Permalink") + +所有测试都希望能够在测试开始时登录. + +有关示例,请参见: [https](https://gitlab.com/gitlab-org/gitlab/-/issues/34736) : [//gitlab.com/gitlab-org/gitlab/-/issues/34736](https://gitlab.com/gitlab-org/gitlab/-/issues/34736) + +理想情况下,在`after(:context)` (或[`before(:context)`](#limit-the-use-of-the-ui-in-beforecontext-and-after-hooks) )块中执行的任何动作都可以通过 API 执行. 但是,如果有必要通过 UI 进行操作(例如,如果不存在 API 功能),请确保在该块的末尾注销. + +``` +after(:all) do + login unless Page::Main::Menu.perform(&:signed_in?) + + # Do something while logged in + + Page::Main::Menu.perform(&:sign_out) +end +``` + +## Tag tests that require Administrator access[](#tag-tests-that-require-administrator-access "Permalink") + +我们不会运行需要管理员对生产环境进行访问的测试. + +当您添加需要管理员访问权限的新测试时,请应用 RSpec 元数据`:requires_admin`以使该测试不会包含在针对生产环境和我们不想在其上运行这些测试的其他环境执行的测试套件中. + +注意:在本地运行测试或配置管道时,可以将环境变量`QA_CAN_TEST_ADMIN_FEATURES`设置为`false`以跳过带有`:requires_admin`标记的测试. + +## Prefer `Commit` resource over `ProjectPush`[](#prefer-commit-resource-over-projectpush "Permalink") + +与[使用 API​​一致](#prefer-api-over-ui) ,请尽可能使用`Commit`资源. + +`ProjectPush`通过 Git 命令行界面(CLI)使用原始 Shell 命令,而`Commit`资源则发出 HTTP 请求. + +``` +# Using a commit resource +Resource::Commit.fabricate_via_api! do |commit| + commit.commit_message = 'Initial commit' + commit.add_files([ + {file_path: 'README.md', content: 'Hello, GitLab'} + ]) +end + +# Using a ProjectPush +Resource::Repository::ProjectPush.fabricate! do |push| + push.commit_message = 'Initial commit' + push.file_name = 'README.md' + push.file_content = 'Hello, GitLab' +end +``` + +**注意:**当您的测试要求测试 SSH 集成或使用 Git CLI 时,使用`ProjectPush`会出现一些例外. \ No newline at end of file diff --git a/docs/639.md b/docs/639.md new file mode 100644 index 0000000000000000000000000000000000000000..6f7fe72bb00981e7cf7619eecd83d9cb27df8548 --- /dev/null +++ b/docs/639.md @@ -0,0 +1,122 @@ +# Dynamic Element Validation + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/dynamic_element_validation.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/dynamic_element_validation.html) + +* [How it works](#how-it-works) + * [Navigation](#navigation) + * [Clicks](#clicks) + * [Required Elements](#required-elements) + * [Definition](#definition) + * [Application](#application) +* [Examples](#examples) + * [Navigating](#navigating) + * [Clicking](#clicking) + +# Dynamic Element Validation[](#dynamic-element-validation "Permalink") + +我们设计了一种解决方案来解决常见的测试自动化问题,例如可怕的`NoSuchElementException` . + +动态元素验证解决的其他问题是… + +* 当我们用鼠标执行操作时,我们期望会发生一些事情. +* 当我们的测试导航到页面(或从页面导航)时,我们确保在继续测试之前我们位于期望的页面上. + +## How it works[](#how-it-works "Permalink") + +我们将页面上的用户操作解释为具有某种效果. 这些动作是 + +* [Navigation](#navigation) +* [Clicks](#clicks) + +### Navigation[](#navigation "Permalink") + +导航到页面时,有些元素将始终无条件地出现在页面上. + +使用时进行动态元素验证 + +``` +Runtime::Browser.visit(:gitlab, Some::Page) +``` + +### Clicks[](#clicks "Permalink") + +当我们在测试中执行单击时,我们期望会发生一些事情. 那可能是现在要出现在网页上的组件,或者是完全离开该页面的测试. + +使用时进行动态元素验证 + +``` +click_element :my_element, Some::Page +``` + +### Required Elements[](#required-elements "Permalink") + +#### Definition[](#definition "Permalink") + +First it is important to define what a “required element” is. + +简而言之,必填元素是可见的 HTML 元素,它无需任何用户输入即可出现在 UI 组件上. + +"可见"可以定义为 + +* 没有任何 CSS 阻止其显示. 例如: `display: none`或`width: 0px; height: 0px;` `width: 0px; height: 0px;` +* 能够与用户互动 + +" UI 组件"可以定义为 + +* 用户看到的任何内容 +* 一个按钮,一个文本字段 +* 位于页面上方的图层 + +#### Application[](#application "Permalink") + +要求元素非常容易. 通过将`required: true`作为`element`的参数添加,您现在已经要求该元素在导航时显示在页面上. + +## Examples[](#examples "Permalink") + +鉴于... + +``` +class MyPage < Page::Base + view 'app/views/view.html.haml' do + element :my_element, required: true + element :another_element, required: true + element :conditional_element + end + + def open_layer + click_element :my_element, Layer::MyLayer + end +end + +class Layer < Page::Component + view 'app/views/mylayer/layer.html.haml' do + element :message_content, required: true + end +end +``` + +### Navigating[](#navigating "Permalink") + +给定[来源](#examples) ... + +``` +Runtime::Browser.visit(:gitlab, Page::MyPage) + +execute_stuff +``` + +在继续`execute_stuff`之前,将调用 GitLab 质量检查人员在`MyPage`上扫描`my_element`和`another_element`在页面上 + +### Clicking[](#clicking "Permalink") + +给定[来源](#examples) ... + +``` +def open_layer + click_element :my_element, Layer::MyLayer +end +``` + +将在单击`my_element`时调用 GitLab 质量检查以确保`message_content`出现在 Layer 上. + +这意味着在继续测试之前确实已渲染了 Layer. \ No newline at end of file diff --git a/docs/640.md b/docs/640.md new file mode 100644 index 0000000000000000000000000000000000000000..7576d82ec3e15a644ded328fbd2a66731e670744 --- /dev/null +++ b/docs/640.md @@ -0,0 +1,57 @@ +# Flows in GitLab QA + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/flows.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/flows.html) + +# Flows in GitLab QA[](#flows-in-gitlab-qa "Permalink") + +流是经常使用的动作序列. 它们是比页面对象更高的抽象级别. 流可以包含多个页面对象或任何其他相关代码. + +例如,登录流封装了每个浏览器 UI 测试中包含的两个步骤. + +``` +# QA::Flow::Login + +def sign_in(as: nil) + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.perform { |login| login.sign_in_using_credentials(user: as) } +end + +# When used in a test + +it 'performs a test after signing in as the default user' do + Flow::Login.sign_in + + # Perform the test +end +``` + +`QA::Flow::Login`提供了更有用的流程,使测试可以轻松切换用户. + +``` +# QA::Flow::Login + +def while_signed_in(as: nil) + Page::Main::Menu.perform(&:sign_out_if_signed_in) + + sign_in(as: as) + + yield + + Page::Main::Menu.perform(&:sign_out) +end + +# When used in a test + +it 'performs a test as one user and verifies as another' do + user1 = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) + user2 = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_2, Runtime::Env.gitlab_qa_password_2) + + Flow::Login.while_signed_in(as: user1) do + # Perform some setup as user1 + end + + Flow::Login.sign_in(as: user2) + + # Perform the rest of the test as user2 +end +``` \ No newline at end of file diff --git a/docs/641.md b/docs/641.md new file mode 100644 index 0000000000000000000000000000000000000000..950e22231d225d7f3730bd4fbe81d732104680c2 --- /dev/null +++ b/docs/641.md @@ -0,0 +1,275 @@ +# Page objects in GitLab QA + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/page_objects.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/page_objects.html) + +* [Why do we need that?](#why-do-we-need-that) +* [What problems did we have in the past?](#what-problems-did-we-have-in-the-past) +* [How did we solve fragile tests problem?](#how-did-we-solve-fragile-tests-problem) +* [How to properly implement a page object?](#how-to-properly-implement-a-page-object) + * [Defining Elements](#defining-elements) + * [Adding Elements to a View](#adding-elements-to-a-view) + * [`data-qa-selector` vs `.qa-selector`](#data-qa-selector-vs-qa-selector) + * [Dynamic element selection](#dynamic-element-selection) + * [Examples](#examples) + * [Exceptions](#exceptions) + * [Define Page concerns](#define-page-concerns) +* [Running the test locally](#running-the-test-locally) +* [Where to ask for help?](#where-to-ask-for-help) + +# Page objects in GitLab QA[](#page-objects-in-gitlab-qa "Permalink") + +在 GitLab 质量检查中,我们使用一种称为*Page Objects*的已知模式. + +这意味着我们已经为用于驱动 GitLab 质量检查方案的 GitLab 中的所有页面建立了抽象. 每当我们在页面上执行某项操作(例如填写表单或单击按钮)时,我们仅通过与该 GitLab 区域相关联的页面对象来执行此操作. + +例如,当 GitLab QA 测试工具登录到 GitLab 时,它需要填写用户登录名和用户密码. 为此,我们有一个名为`Page::Main::Login`和`sign_in_using_credentials`方法的类,这是代码中仅有的一部分,它具有有关`user_login`和`user_password`字段的知识. + +## Why do we need that?[](#why-do-we-need-that "Permalink") + +我们需要页面对象,因为只要有人在 GitLab 的源代码中更改某些选择器,我们就需要减少重复并避免出现问题. + +想象一下,我们在 GitLab 质量检查中有 100 个规格,并且在每次声明之前我们都需要登录 GitLab. 如果没有页面对象,则需要依靠易失性助手或直接调用 Capybara 方法. 想象一下在每个`*_spec.rb`文件/测试示例中调用`fill_in :user_login` . + +以后有人在与此页面关联的视图`t.text_field :login`更改为`t.text_field :username` ,它将生成一个不同的字段标识符,这将有效地破坏所有测试. + +因为我们到处都在使用`Page::Main::Login.perform(&:sign_in_using_credentials)` ,所以当我们要登录到 GitLab 时,页面对象是唯一的事实来源,我们需要将`fill_in :user_login`更新为`fill_in :user_username`只能放在一个位置. + +## What problems did we have in the past?[](#what-problems-did-we-have-in-the-past "Permalink") + +由于性能原因以及构建软件包和测试所有内容所花费的时间,我们不会针对每次提交都运行 QA 测试. + +这就是为什么当有人在*新的会话*视图中将`t.text_field :login`更改为`t.text_field :username` ,直到我们的 GitLab QA 夜间管道失败或有人触发了他们的`package-and-qa`操作,我们才知道这一更改.合并请求. + +显然,这样的更改将破坏所有测试. 我们称这个问题为*脆弱的测试问题* . + +为了使 GitLab QA 更加可靠和健壮,我们必须通过在 GitLab CE / EE 视图与 GitLab QA 之间引入耦合来解决此问题. + +## How did we solve fragile tests problem?[](#how-did-we-solve-fragile-tests-problem "Permalink") + +当前,当您添加新的`Page::Base`派生类时,还需要定义页面对象所依赖的所有选择器. + +Whenever you push your code to CE / EE repository, `qa:selectors` sanity test job is going to be run as a part of a CI pipeline. + +此测试将验证我们在`qa/page`目录中实现的所有页面对象. 失败时,将通知您有关丢失的或无效的视图/选择器定义的信息. + +## How to properly implement a page object?[](#how-to-properly-implement-a-page-object "Permalink") + +我们建立了一个 DSL 来定义页面对象和它实际实现的 GitLab 视图之间的耦合. 请参阅下面的示例. + +``` +module Page + module Main + class Login < Page::Base + view 'app/views/devise/passwords/edit.html.haml' do + element :password_field + element :password_confirmation + element :change_password_button + end + + view 'app/views/devise/sessions/_new_base.html.haml' do + element :login_field + element :password_field + element :sign_in_button + end + + # ... + end + end +end +``` + +### Defining Elements[](#defining-elements "Permalink") + +`view` DSL 方法将对应于渲染元素的 rails View,partial 或 Vue 组件. + +`element` DSL 方法依次声明一个元素,需要将其相应的`data-qa-selector=element_name_snaked`数据属性添加到视图文件中. + +您还可以定义一个值(字符串或正则表达式)以匹配实际的视图代码,但是出于两个原因, **不**建议使用上述方法,建议使用该值: + +* 一致性:只有一种定义元素的方法 +* 关注点分离:QA 使用专用的`data-qa-*`属性,而不是重用其他组件使用的代码或类(例如`js-*`类等) + +``` +view 'app/views/my/view.html.haml' do + + ### Good ### + + # Implicitly require the CSS selector `[data-qa-selector="logout_button"]` to be present in the view + element :logout_button + + ### Bad ### + + ## This is deprecated and forbidden by the `QA/ElementWithPattern` RuboCop cop. + # Require `f.submit "Sign in"` to be present in `my/view.html.haml + element :my_button, 'f.submit "Sign in"' # rubocop:disable QA/ElementWithPattern + + ## This is deprecated and forbidden by the `QA/ElementWithPattern` RuboCop cop. + # Match every line in `my/view.html.haml` against + # `/link_to .* "My Profile"/` regexp. + element :profile_link, /link_to .* "My Profile"/ # rubocop:disable QA/ElementWithPattern +end +``` + +### Adding Elements to a View[](#adding-elements-to-a-view "Permalink") + +鉴于以下要素... + +``` +view 'app/views/my/view.html.haml' do + element :login_field + element :password_field + element :sign_in_button +end +``` + +要将这些元素添加到视图,必须通过为定义的每个元素添加`data-qa-selector`属性来更改 rails View,Partial 或 Vue 组件. + +在我们的示例中, `data-qa-selector="login_field"` , `data-qa-selector="password_field"`和`data-qa-selector="sign_in_button"` + +**app/views/my/view.html.haml** + +``` += f.text_field :login, class: "form-control top", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off", required: true, title: "This field is required.", data: { qa_selector: 'login_field' } += f.password_field :password, class: "form-control bottom", required: true, title: "This field is required.", data: { qa_selector: 'password_field' } += f.submit "Sign in", class: "btn btn-success", data: { qa_selector: 'sign_in_button' } +``` + +注意事项: + +* 元素的名称和`qa_selector`必须匹配并使用 snake_cased +* 如果该元素无条件显示在页面上,请向该元素添加`required: true` . 请参阅[动态元素验证](dynamic_element_validation.html) +* 您可能会在现有的页面对象中看到`.qa-selector`类. 我们应该使用[`data-qa-selector`](#data-qa-selector-vs-qa-selector)定义方法,而不是`.qa-selector` CSS 类. + +### `data-qa-selector` vs `.qa-selector`[](#data-qa-selector-vs-qa-selector "Permalink") + +在 GitLab 12.1 中引入 + +在视图中定义元素有两种支持的方法. + +1. `data-qa-selector` attribute +2. `.qa-selector` class + +任何现有的`.qa-selector`类都应视为已弃用,我们应该更喜欢`data-qa-selector`定义方法. + +### Dynamic element selection[](#dynamic-element-selection "Permalink") + +在 GitLab 12.5 中引入 + +自动化测试中常见的一种情况是选择一个"多对多"元素. 在几个项目的列表中,如何区分选择的内容? 最常见的解决方法是通过文本匹配. 相反,更好的做法是通过唯一标识符而不是文本来匹配该特定元素. + +我们通过添加`data-qa-*`可扩展选择机制来解决此问题. + +#### Examples[](#examples "Permalink") + +**例子 1** + +给出以下 Rails 视图(以 GitLab Issues 为例): + +``` +%ul.issues-list + - @issues.each do |issue| + %li.issue{data: { qa_selector: 'issue', qa_issue_title: issue.title } }= link_to issue +``` + +我们可以通过在 Rails 模型上进行匹配来选择特定的问题. + +``` +class Page::Project::Issues::Index < Page::Base + def has_issue?(issue) + has_element? :issue, issue_title: issue + end +end +``` + +在我们的测试中,我们可以验证此特定问题的存在. + +``` +describe 'Issue' do + it 'has an issue titled "hello"' do + Page::Project::Issues::Index.perform do |index| + expect(index).to have_issue('hello') + end + end +end +``` + +**例子 2** + +*通过索引…* + +``` +%ol + - @some_model.each_with_index do |model, idx| + %li.model{ data: { qa_selector: 'model', qa_index: idx } } +``` + +``` +expect(the_page).to have_element(:model, index: 1) #=> select on the first model that appears in the list +``` + +### Exceptions[](#exceptions "Permalink") + +在某些情况下,可能无法或不值得添加选择器. + +一些 UI 组件使用外部库,包括一些第三方维护的库. 即使 GitLab 维护了一个库,选择器的健全性测试也只能在 GitLab 项目中的代码上运行,因此无法为库中的代码指定视图的路径. + +在这种罕见的情况下,在页面对象方法中使用 CSS 选择器是合理的,并带有注释说明为什么不能添加`element`原因. + +### Define Page concerns[](#define-page-concerns "Permalink") + +某些页面具有共同的行为,并且/或者在特定于 EE 的模块之前添加了特定于 EE 的方法. + +These modules must: + +1. 从`QA::Page::PageConcern`模块`extend QA::Page::PageConcern` ,并`extend QA::Page::PageConcern` . +2. 重写`self.prepended`方法,如果他们需要`include` / `prepend`其他模块本身,和/或定义`view`或`elements` . +3. 将`super`称为`self.prepended`的第一件事. +4. 包含/添加其他模块,并在`base.class_eval`块中定义其`view` / `elements` ,以确保在添加模块的类中定义了它们. + +这些步骤确保健全性选择器检查将正确检测到问题. + +例如, `qa/qa/ee/page/merge_request/show.rb`将 EE 特定方法添加到`qa/qa/page/merge_request/show.rb` (带有`QA::Page::MergeRequest::Show.prepend_if_ee('QA::EE::Page::MergeRequest::Show')` ),其实现方式如下(仅显示相关部分,并使用内嵌注释引用上述 4 个步骤): + +``` +module QA + module EE + module Page + module MergeRequest + module Show + extend QA::Page::PageConcern # 1. + + def self.prepended(base) # 2. + super # 3. + + base.class_eval do # 4. + prepend Page::Component::LicenseManagement + + view 'app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue' do + element :head_mismatch, "The source branch HEAD has recently changed." + end + + [...] + end + end + end + end + end + end +end +``` + +## Running the test locally[](#running-the-test-locally "Permalink") + +在开发过程中,您可以运行以下命令来运行`qa:selectors`测试 + +``` +bin/qa Test::Sanity::Selectors +``` + +从`qa`目录中. + +## Where to ask for help?[](#where-to-ask-for-help "Permalink") + +如果您需要更多信息,请在 Slack 上的`#quality`频道(仅限内部,GitLab 团队)上寻求帮助. + +如果你不是一个团队成员,你仍然需要帮助的贡献,请打开 GitLab CE 问题追踪的一个问题`~QA`标签. \ No newline at end of file diff --git a/docs/642.md b/docs/642.md new file mode 100644 index 0000000000000000000000000000000000000000..a492e6c0a4f71ba7da5bf7ead0731d17b0af9cb6 --- /dev/null +++ b/docs/642.md @@ -0,0 +1,362 @@ +# Resource class in GitLab QA + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/resources.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/resources.html) + +* [How to properly implement a resource class?](#how-to-properly-implement-a-resource-class) + * [Define API implementation](#define-api-implementation) + * [Resource attributes](#resource-attributes) + * [Product data attributes](#product-data-attributes) + * [Define an attribute based on an API response](#define-an-attribute-based-on-an-api-response) +* [Creating resources in your tests](#creating-resources-in-your-tests) +* [Where to ask for help?](#where-to-ask-for-help) + +# Resource class in GitLab QA[](#resource-class-in-gitlab-qa "Permalink") + +资源主要是使用浏览器 UI 步骤创建的,但也可以通过 API 或 CLI 创建的. + +## How to properly implement a resource class?[](#how-to-properly-implement-a-resource-class "Permalink") + +所有资源类都应继承自`Resource::Base` . + +只有一种强制性方法可以实现以定义资源类. 这是`#fabricate!` 方法,用于通过浏览器 UI 构建资源. 请注意,在此方法中,您仅应使用[Page 对象](page_objects.html)与网页进行交互. + +这是一个假想的例子: + +``` +module QA + module Resource + class Shirt < Base + attr_accessor :name + + def fabricate! + Page::Dashboard::Index.perform do |dashboard_index| + dashboard_index.go_to_new_shirt + end + + Page::Shirt::New.perform do |shirt_new| + shirt_new.set_name(name) + shirt_new.create_shirt! + end + end + end + end +end +``` + +### Define API implementation[](#define-api-implementation "Permalink") + +资源类还可以实现以下三种方法,以便能够通过公共 GitLab API 创建资源: + +* `#api_get_path` :获取现有资源的`GET`路径. +* `#api_post_path` :用于创建新资源的`POST`路径. +* `#api_post_body` :用于创建新资源的`POST`正文(作为 Ruby 哈希). + +> 请注意,许多 API 资源都是[分页的](../../../api/README.html#pagination) . 如果找不到期望的结果,请检查是否有超过一页的结果. + +让我们使用`Shirt`资源类,并添加以下三个 API 方法: + +``` +module QA + module Resource + class Shirt < Base + attr_accessor :name + + def fabricate! + # ... same as before + end + + def api_get_path + "/shirt/#{name}" + end + + def api_post_path + "/shirts" + end + + def api_post_body + { + name: name + } + end + end + end +end +``` + +`Project`资源是浏览器 UI 和 API 实现的一个很好的真实示例. + +#### Resource attributes[](#resource-attributes "Permalink") + +一个资源可能首先需要另一个资源. 例如,一个项目需要在其中创建一个组. + +要定义资源属性,可以将`attribute`方法与使用其他资源类的块一起使用以构造资源. + +这将允许从资源对象的方法访问其他资源. 您通常会在`#fabricate!`使用它`#fabricate!` , `#api_get_path` , `#api_post_path` , `#api_post_body` . + +让我们使用`Shirt`资源类,并向其添加一个`project`属性: + +``` +module QA + module Resource + class Shirt < Base + attr_accessor :name + + attribute :project do + Project.fabricate! do |resource| + resource.name = 'project-to-create-a-shirt' + end + end + + def fabricate! + project.visit! + + Page::Project::Show.perform do |project_show| + project_show.go_to_new_shirt + end + + Page::Shirt::New.perform do |shirt_new| + shirt_new.set_name(name) + shirt_new.create_shirt! + end + end + + def api_get_path + "/project/#{project.path}/shirt/#{name}" + end + + def api_post_path + "/project/#{project.path}/shirts" + end + + def api_post_body + { + name: name + } + end + end + end +end +``` + +**请注意,所有属性都是延迟构造的. 这意味着,如果您要首先构造特定的属性,则即使不使用它,也需要首先调用 attribute 方法.** + +#### Product data attributes[](#product-data-attributes "Permalink") + +创建后,您可能希望使用可在网页或 API 响应中找到的属性填充资源. 例如,创建项目后,您可能希望将其存储库 SSH URL 存储为属性. + +同样,我们可以将`attribute`方法与块一起使用,使用页面对象来检索页面上的数据. + +让我们以`Shirt`资源类`Shirt` ,并定义一个`:brand`属性: + +``` +module QA + module Resource + class Shirt < Base + attr_accessor :name + + attribute :project do + Project.fabricate! do |resource| + resource.name = 'project-to-create-a-shirt' + end + end + + # Attribute populated from the Browser UI (using the block) + attribute :brand do + Page::Shirt::Show.perform do |shirt_show| + shirt_show.fetch_brand_from_page + end + end + + # ... same as before + end + end +end +``` + +**再次注意,所有属性都是延迟构造的. 这意味着,如果您`shirt.brand`另一页面后再调用`shirt.brand` ,则由于我们不在预期的页面上,因此将无法正确检索数据.** + +考虑一下: + +``` +shirt = + QA::Resource::Shirt.fabricate! do |resource| + resource.name = "GitLab QA" + end + +shirt.project.visit! + +shirt.brand # => FAIL! +``` + +上面的示例将失败,因为现在我们在项目页面上,试图从衬衫页面构造品牌数据,但是我们已经移至项目页面. 有两种解决方法,一种是我们可以在再次访问该项目之前尝试检索该品牌: + +``` +shirt = + QA::Resource::Shirt.fabricate! do |resource| + resource.name = "GitLab QA" + end + +shirt.brand # => OK! + +shirt.project.visit! + +shirt.brand # => OK! +``` + +The attribute will be stored in the instance therefore all the following calls will be fine, using the data previously constructed. If we think that this might be too brittle, we could eagerly construct the data right before ending fabrication: + +``` +module QA + module Resource + class Shirt < Base + # ... same as before + + def fabricate! + project.visit! + + Page::Project::Show.perform do |project_show| + project_show.go_to_new_shirt + end + + Page::Shirt::New.perform do |shirt_new| + shirt_new.set_name(name) + shirt_new.create_shirt! + end + + populate(:brand) # Eagerly construct the data + end + end + end +end +``` + +`populate`方法将遍历其参数并分别调用每个属性. 这里`populate(:brand)`有像刚才一样的效果`brand` . 使用填充方法使意图更清晰. + +这样,将确保我们在创建衬衫后立即构造数据. 缺点是,即使我们不需要使用数据,也总是在构造资源时构造数据. + +另外,我们可以在构建品牌数据之前确保在正确的页面上: + +``` +module QA + module Resource + class Shirt < Base + attr_accessor :name + + attribute :project do + Project.fabricate! do |resource| + resource.name = 'project-to-create-a-shirt' + end + end + + # Attribute populated from the Browser UI (using the block) + attribute :brand do + back_url = current_url + visit! + + Page::Shirt::Show.perform do |shirt_show| + shirt_show.fetch_brand_from_page + end + + visit(back_url) + end + + # ... same as before + end + end +end +``` + +这将确保在构建品牌之前,它在衬衫页面上,并返回到上一页以避免破坏状态. + +#### Define an attribute based on an API response[](#define-an-attribute-based-on-an-api-response "Permalink") + +有时,您想基于来自其`GET`或`POST`请求的 API 响应来定义资源属性. 例如,如果通过 API 创建衬衫的返回 + +``` +{ + brand: 'a-brand-new-brand', + style: 't-shirt', + materials: [[:cotton, 80], [:polyamide, 20]] +} +``` + +您可能希望将`style` `main_fabric`在资源中,并在`main_fabric`属性中获取第一个`materials`项的第一个值. + +让我们以`Shirt`资源类`:main_fabric` ,并定义一个`:style`和`:main_fabric`属性: + +``` +module QA + module Resource + class Shirt < Base + # ... same as before + + # @style from the instance if present, + # or fetched from the API response if present, + # or a QA::Resource::Base::NoValueError is raised otherwise + attribute :style + + # If @main_fabric is not present, + # and if the API does not contain this field, this block will be + # used to construct the value based on the API response, and + # store the result in @main_fabric + attribute :main_fabric do + api_response.&dig(:materials, 0, 0) + end + + # ... same as before + end + end +end +``` + +**有关属性优先级的说明:** + +* 资源实例变量具有最高优先级 +* API 响应中的属性优先于块中的属性(通常是来自浏览器用户界面) +* 没有值的属性将引发`QA::Resource::Base::NoValueError`错误 + +## Creating resources in your tests[](#creating-resources-in-your-tests "Permalink") + +要在测试中创建资源,可以调用`.fabricate!` 资源类上的方法. 请注意,如果资源类支持 API 构造,则默认情况下将使用该构造. + +这是一个示例,由于`Shirt`资源类支持该方法,因此将在后台使用 API​​构造方法: + +``` +my_shirt = Resource::Shirt.fabricate! do |shirt| + shirt.name = 'my-shirt' +end + +expect(page).to have_text(my_shirt.name) # => "my-shirt" from the resource's instance variable +expect(page).to have_text(my_shirt.brand) # => "a-brand-new-brand" from the API response +expect(page).to have_text(my_shirt.style) # => "t-shirt" from the API response +expect(page).to have_text(my_shirt.main_fabric) # => "cotton" from the API response via the block +``` + +如果您明确希望使用浏览器 UI 的制作方法,则可以调用`.fabricate_via_browser_ui!` 方法: + +``` +my_shirt = Resource::Shirt.fabricate_via_browser_ui! do |shirt| + shirt.name = 'my-shirt' +end + +expect(page).to have_text(my_shirt.name) # => "my-shirt" from the resource's instance variable +expect(page).to have_text(my_shirt.brand) # => the brand name fetched from the `Page::Shirt::Show` page via the block +expect(page).to have_text(my_shirt.style) # => QA::Resource::Base::NoValueError will be raised because no API response nor a block is provided +expect(page).to have_text(my_shirt.main_fabric) # => QA::Resource::Base::NoValueError will be raised because no API response and the block didn't provide a value (because it's also based on the API response) +``` + +您还可以通过调用`.fabricate_via_api!`来显式使用 API `.fabricate_via_api!` 方法: + +``` +my_shirt = Resource::Shirt.fabricate_via_api! do |shirt| + shirt.name = 'my-shirt' +end +``` + +在这种情况下,结果将类似于调用`Resource::Shirt.fabricate!` . + +## Where to ask for help?[](#where-to-ask-for-help "Permalink") + +如果您需要更多信息,请在 Slack 上的`#quality`频道(仅限内部,GitLab 团队)上寻求帮助. + +如果你不是一个团队成员,你仍然需要帮助的贡献,请打开 GitLab CE 问题追踪的一个问题`~QA`标签. \ No newline at end of file diff --git a/docs/643.md b/docs/643.md new file mode 100644 index 0000000000000000000000000000000000000000..4efaaa9ce24a19ee3121fa67f037d4e678da236d --- /dev/null +++ b/docs/643.md @@ -0,0 +1,167 @@ +# Style guide for writing end-to-end tests + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/style_guide.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/style_guide.html) + +* [`click_` versus `go_to_`](#click_-versus-go_to_) + * [When to use `click_`?](#when-to-use-click_) + * [When to use `go_to_`?](#when-to-use-go_to_) +* [Element naming convention](#element-naming-convention) + * [Examples](#examples) +* [Block argument naming](#block-argument-naming) + * [Examples](#examples-1) + +# Style guide for writing end-to-end tests[](#style-guide-for-writing-end-to-end-tests "Permalink") + +本文档介绍了在 GitLab 上使用 GitLab QA 项目编写端到端(E2E)测试所使用的约定. + +## `click_` versus `go_to_`[](#click_-versus-go_to_ "Permalink") + +### When to use `click_`?[](#when-to-use-click_ "Permalink") + +单击单个链接进行导航时,请使用`click_` . + +E.g.: + +``` +def click_ci_cd_pipelines + within_sidebar do + click_element :link_pipelines + end +end +``` + +从测试的角度来看,如果我们要检查单击链接或按钮(单个交互)是否按预期工作,我们希望测试的内容为: + +* 点击某个元素 +* 验证操作是否发生 + +### When to use `go_to_`?[](#when-to-use-go_to_ "Permalink") + +与多个元素进行交互以转到页面时,请使用`go_to_` . + +E.g.: + +``` +def go_to_operations_environments + hover_operations do + within_submenu do + click_element(:operations_environments_link) + end + end +end +``` + +`go_to_`适合与多个元素进行交互的定义,因为它更多的是包含多个交互的元导航操作. + +请注意,在上面的示例中,在单击`:operations_environments_link`之前,将鼠标悬停在另一个元素上. + +> 我们可以创建这些方法作为抽象多步导航的助手. + +## Element naming convention[](#element-naming-convention "Permalink") + +在页面上添加新元素时,重要的是要有统一的元素命名约定. + +我们遵循一个基于匈牙利表示法的简单公式. + +*Formula*: `element :<descriptor>_<type>` + +* `descriptor` :元素是什么的自然语言描述. 在登录页面上,可以是`username`或`password` . +* `type` :用户可以在页面上看到的通用控件. + * `_button` + * `_checkbox` + * `_container` :包含其他元素但本身不显示可见内容的元素. 例如,其中具有第三方编辑器的元素,但它本身不是编辑器,因此不包含编辑器的内容. + * `_content` :包含文本,图像或显示给用户的任何其他内容的任何元素. + * `_dropdown` + * `_field` :文本输入元素. + * `_link` + * `_modal` :弹出的模式对话框,例如确认提示. + * `_placeholder` :加载内容时出现的临时元素. 例如,在获取讨论时显示的元素而不是讨论. + * `_radio` + * `_tab` + * `_menu_item` + +*注意:如果列出的类型都不适合,请打开合并请求以将适当的类型添加到列表中.* + +### Examples[](#examples "Permalink") + +**Good** + +``` +view '...' do + element :edit_button + element :notes_tab + element :squash_checkbox + element :username_field + element :issue_title_content +end +``` + +**Bad** + +``` +view '...' do + # `_confirmation` should be `_field`. what sort of confirmation? a checkbox confirmation? no real way to disambiguate. + # an appropriate replacement would be `element :password_confirmation_field` + element :password_confirmation + + # `clone_options` is too vague. If it's a dropdown menu, it should be `clone_dropdown`. + # If it's a checkbox, it should be `clone_checkbox` + element :clone_options + + # how is this url being displayed? is it a textbox? a simple span? + # If it is content on the page, it should be `ssh_clone_url_content` + element :ssh_clone_url +end +``` + +## Block argument naming[](#block-argument-naming "Permalink") + +为了对使用`.perform`方法时调用的页面和资源有一个标准,我们在`.perform`使用页面对象的[名称](https://en.wikipedia.org/wiki/Snake_case) (全部小写,单词之间用下划线分隔). 请参阅下面的好与坏示例. + +尽管在大多数情况下我们倾向于遵循该标准,但是只要名称不明确,也可以使用常见缩写(例如`mr` )或其他替代方式. 如果有助于避免混淆或使代码更具可读性,则可以包括附加`_page` . 例如,如果一个页面对象被命名为`New` ,也可能是混淆命名块论点`new` ,因为这是用来实例化对象,所以`new_page`是可以接受的. + +我们选择不只是使用`page`因为这会遮盖 Capybara DSL,从而可能导致混乱和错误. + +### Examples[](#examples-1 "Permalink") + +**Good** + +``` +Page::Project::Members.perform do |members| + members.do_something +end +``` + +``` +Resource::MergeRequest.fabricate! do |merge_request| + merge_request.do_something_else +end +``` + +``` +Resource::MergeRequest.fabricate! do |mr| + mr.do_something_else +end +``` + +``` +Page::Project::New.peform do |new_page| + new_page.do_something +end +``` + +**Bad** + +``` +Page::Project::Members.perform do |project_settings_members_page| + project_settings_members_page.do_something +end +``` + +``` +Page::Project::New.peform do |page| + page.do_something +end +``` + +> 除了采用标准的优点之外,通过遵循该标准,我们还编写了较短的代码行. \ No newline at end of file diff --git a/docs/644.md b/docs/644.md new file mode 100644 index 0000000000000000000000000000000000000000..dbe7c0ab11660946162fccaa1a7760bb91ef2210 --- /dev/null +++ b/docs/644.md @@ -0,0 +1,35 @@ +# Testing with feature flags + +> 原文:[https://docs.gitlab.com/ee/development/testing_guide/end_to_end/feature_flags.html](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/feature_flags.html) + +* [Running a scenario with a feature flag enabled](#running-a-scenario-with-a-feature-flag-enabled) + +# Testing with feature flags[](#testing-with-feature-flags "Permalink") + +要在启用了功能标志的情况下运行特定的测试,可以使用`QA::Runtime::Feature`类来启用和禁用功能标志( [通过 API](../../../api/features.html) ). + +请注意,更改功能标志需要管理员授权. 只要您通过`GITLAB_QA_ADMIN_ACCESS_TOKEN` (推荐)提供适当的访问令牌,或者提供`GITLAB_ADMIN_USERNAME`和`GITLAB_ADMIN_PASSWORD` , `QA::Runtime::Feature`将自动以管理员身份进行身份验证. + +请确保包含标签`:requires_admin`以便在没有管理员权限的环境中可以跳过测试. + +``` +RSpec.describe "with feature flag enabled", :requires_admin do + before do + Runtime::Feature.enable('feature_flag_name') + end + + it "feature flag test" do + # Execute a test with a feature flag enabled + end + + after do + Runtime::Feature.disable('feature_flag_name') + end +end +``` + +## Running a scenario with a feature flag enabled[](#running-a-scenario-with-a-feature-flag-enabled "Permalink") + +也可以在启用功能标记的情况下运行整个方案,而无需编辑现有测试或编写新测试. + +有关详细信息,请参见[质量检查自述文件](https://gitlab.com/gitlab-org/gitlab/tree/master/qa#running-tests-with-a-feature-flag-enabled) . \ No newline at end of file diff --git a/docs/645.md b/docs/645.md new file mode 100644 index 0000000000000000000000000000000000000000..ce7e7285f182f439bc458d6bc154138a507535a6 --- /dev/null +++ b/docs/645.md @@ -0,0 +1,47 @@ +# Translate GitLab to your language + +> 原文:[https://docs.gitlab.com/ee/development/i18n/](https://docs.gitlab.com/ee/development/i18n/) + +* [How to contribute](#how-to-contribute) + * [Externalize strings](#externalize-strings) + * [Translate strings](#translate-strings) + * [Proof reading](#proof-reading) +* [Release](#release) + +# Translate GitLab to your language[](#translate-gitlab-to-your-language "Permalink") + +默认情况下,GitLab 用户界面中的文本为美式英语. 每个字符串都可以翻译成其他语言. 在翻译每个字符串时,会将其添加到语言翻译文件中,并将在以后的 GitLab 版本中提供. + +始终需要为翻译做出贡献. 许多字符串尚未转换,因为它们尚未被外部化. 帮助外部化字符串有益于所有语言. 某些翻译不完整或不一致. 翻译字符串将有助于完成和改进每种语言. + +## How to contribute[](#how-to-contribute "Permalink") + +您可以通过多种方式来翻译 GitLab. + +### Externalize strings[](#externalize-strings "Permalink") + +在翻译字符串之前,必须将其外部化. 在此过程中,GitLab 源代码中的英文字符串被包装到一个函数中,该函数检索用户语言的翻译后的字符串. + +随着新功能的添加和现有功能的更新,周围的字符串也被外部化,但是,GitLab 的许多部分仍需要更多的工作来外部化所有字符串. + +See [Externalization for GitLab](externalization.html). + +### Translate strings[](#translate-strings "Permalink") + +使用[CrowdIn](https://crowdin.com/)在[https://translate.gitlab.com](https://translate.gitlab.com)上管理翻译过程. 您需要先创建一个帐户,然后才能提交翻译. 登录后,选择您想要贡献翻译的语言. + +对翻译进行投票也很有价值,有助于确认良好的翻译并标记不正确的翻译. + +See [Translation guidelines](translation.html). + +### Proof reading[](#proof-reading "Permalink") + +校对有助于确保翻译的准确性和一致性. 在接受所有翻译之前,请先进行校对. 如果翻译需要更改,则会通过注释告知您原因. + +有关谁可以校对的更多信息以及您自己成为校对者的说明,请参见[校对译文](proofreader.html) . + +## Release[](#release "Permalink") + +翻译通常包含在下一个主要或次要版本中. + +See [Merging translations from CrowdIn](merging_translations.html). \ No newline at end of file diff --git a/docs/646.md b/docs/646.md new file mode 100644 index 0000000000000000000000000000000000000000..cfec390610ba6aa58b3c827f4ba1fe5c1345a354 --- /dev/null +++ b/docs/646.md @@ -0,0 +1,584 @@ +# Internationalization for GitLab + +> 原文:[https://docs.gitlab.com/ee/development/i18n/externalization.html](https://docs.gitlab.com/ee/development/i18n/externalization.html) + +* [Setting up GitLab Development Kit (GDK)](#setting-up-gitlab-development-kit-gdk) +* [Tools](#tools) +* [Preparing a page for translation](#preparing-a-page-for-translation) + * [Ruby files](#ruby-files) + * [HAML files](#haml-files) + * [ERB files](#erb-files) + * [JavaScript files](#javascript-files) + * [Dynamic translations](#dynamic-translations) +* [Working with special content](#working-with-special-content) + * [Interpolation](#interpolation) + * [Plurals](#plurals) + * [Namespaces](#namespaces) + * [Dates / times](#dates--times) +* [Best practices](#best-practices) + * [Keep translations dynamic](#keep-translations-dynamic) + * [Splitting sentences](#splitting-sentences) + * [Avoid splitting sentences when adding links](#avoid-splitting-sentences-when-adding-links) + * [Vue components interpolation](#vue-components-interpolation) +* [Updating the PO files with the new content](#updating-the-po-files-with-the-new-content) + * [Validating PO files](#validating-po-files) +* [Adding a new language](#adding-a-new-language) + +# Internationalization for GitLab[](#internationalization-for-gitlab "Permalink") + +在 GitLab 9.2 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10669) . + +为了使用国际化(i18n),使用了[GNU gettext](https://www.gnu.org/software/gettext/) ,因为它是该任务最常用的工具,并且有许多应用程序可以帮助我们使用它. + +## Setting up GitLab Development Kit (GDK)[](#setting-up-gitlab-development-kit-gdk "Permalink") + +为了能够在[GitLab 社区版](https://gitlab.com/gitlab-org/gitlab-foss)项目上工作,您必须通过[GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/set-up-gdk.md)下载并配置它. + +准备好 GitLab 项目后,就可以开始进行翻译了. + +## Tools[](#tools "Permalink") + +使用以下工具: + +1. [`gettext_i18n_rails`](https://github.com/grosser/gettext_i18n_rails) :这个 gem 使我们可以转换模型,视图和控制器中的内容. 此外,它还使我们可以访问以下 Rake 任务: + * `rake gettext:find` :解析 Rails 应用程序中的几乎所有文件,以查找已标记为要翻译的内容. 最后,它将使用找到的新内容更新 PO 文件. + * `rake gettext:pack` :处理 PO 文件并生成二进制的 MO 文件,最终由应用程序使用. +2. [`gettext_i18n_rails_js`](https://github.com/webhippie/gettext_i18n_rails_js) :此 gem 对于使翻译在 JavaScript 中可用非常有用. 它提供以下 Rake 任务: + * `rake gettext:po_to_json` :从 PO 文件中读取内容,并生成包含所有可用翻译的 JSON 文件. +3. PO 编辑器:有多个应用程序可以帮助我们处理 PO 文件, [Poedit](https://poedit.net/download)是一个不错的选择,可用于 macOS,GNU / Linux 和 Windows. + +## Preparing a page for translation[](#preparing-a-page-for-translation "Permalink") + +我们基本上有 4 种类型的文件: + +1. Ruby 文件:基本上是模型和控制器. +2. HAML 文件:这些是视图文件. +3. ERB 文件:用于电子邮件模板. +4. JavaScript 文件:我们主要需要使用 Vue 模板. + +### Ruby files[](#ruby-files "Permalink") + +例如,如果存在使用原始字符串的方法或变量,则: + +``` +def hello + "Hello world!" +end +``` + +Or: + +``` +hello = "Hello world!" +``` + +您可以轻松地将该内容标记为要翻译的内容: + +``` +def hello + _("Hello world!") +end +``` + +Or: + +``` +hello = _("Hello world!") +``` + +在类或模块级别转换字符串时要小心,因为在类加载时它们只会被评估一次. + +例如: + +``` +validates :group_id, uniqueness: { scope: [:project_id], message: _("already shared with this group") } +``` + +当加载该类时,这将被翻译,并导致错误消息始终位于默认语言环境中. + +Active Record’s `:message` option accepts a `Proc`, so we can do this instead: + +``` +validates :group_id, uniqueness: { scope: [:project_id], message: -> (object, data) { _("already shared with this group") } } +``` + +**注意:** API( `lib/api/`或`app/graphql` )中的消息无需外部化. + +### HAML files[](#haml-files "Permalink") + +考虑到 HAML 中的以下内容: + +``` +%h1 Hello world! +``` + +您可以使用以下方式将该内容标记为要翻译的内容: + +``` +%h1= _("Hello world!") +``` + +### ERB files[](#erb-files "Permalink") + +考虑到 ERB 中的以下内容: + +``` +<h1>Hello world!</h1> +``` + +您可以使用以下方式将该内容标记为要翻译的内容: + +``` +<h1><%= _("Hello world!") %></h1> +``` + +### JavaScript files[](#javascript-files "Permalink") + +在 JavaScript 中,我们添加了`__()` (双下划线括号)函数,您可以从`~/locale`文件中导入该函数. 例如: + +``` +import { __ } from '~/locale'; +const label = __('Subscribe'); +``` + +为了测试 JavaScript 翻译,您必须将 GitLab 本地化更改为英语以外的其他语言,并且必须使用`bin/rake gettext:po_to_json`或`bin/rake gettext:compile`生成 JSON 文件. + +### Dynamic translations[](#dynamic-translations "Permalink") + +有时,运行`bin/rake gettext:find`时,解析器无法找到一些动态转换. 对于这些情况,可以使用[`N_`方法](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#unfound-translations-with-rake-gettextfind) . + +还有另一种方法可以[转换来自验证错误的消息](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#option-a) . + +## Working with special content[](#working-with-special-content "Permalink") + +### Interpolation[](#interpolation "Permalink") + +翻译后的文字中的占位符应与相应源文件的代码样式匹配. 例如使用`%{created_at}`在 Ruby,但`%{createdAt}`在 JavaScript. [添加链接时,](#avoid-splitting-sentences-when-adding-links)请确保[避免拆分句子](#avoid-splitting-sentences-when-adding-links) . + +* 在 Ruby / HAML 中: + + ``` + _("Hello %{name}") % { name: 'Joe' } => 'Hello Joe' + ``` + +* 在 Vue 中: + + 请参见有关[Vue 分量插值](#vue-components-interpolation)的部分. + +* 在 JavaScript 中(无法使用 Vue 时): + + ``` + import { __, sprintf } from '~/locale'; + + sprintf(__('Hello %{username}'), { username: 'Joe' }); // => 'Hello Joe' + ``` + + 如果要在翻译中使用标记并且正在使用 Vue,则**必须**使用[`gl-sprintf`](#vue-components-interpolation)组件. 如果由于某种原因您不能使用 Vue,请使用`sprintf`并通过将`false`用作第三个参数来阻止其转义占位符值. 您**必须**使用自己逃避任何插值动态值,例如`escape`从`lodash` . + + ``` + import { escape } from 'lodash'; + import { __, sprintf } from '~/locale'; + + let someDynamicValue = '<script>alert("evil")</script>'; + + // Dangerous: + sprintf(__('This is %{value}'), { value: `<strong>${someDynamicValue}</strong>`, false); + // => 'This is <strong><script>alert('evil')</script></strong>' + + // Incorrect: + sprintf(__('This is %{value}'), { value: `<strong>${someDynamicValue}</strong>` }); + // => 'This is <strong><script>alert('evil')</script></strong>' + + // OK: + sprintf(__('This is %{value}'), { value: `<strong>${escape(someDynamicValue)}</strong>`, false); + // => 'This is <strong><script>alert('evil')</script></strong>' + ``` + +### Plurals[](#plurals "Permalink") + +* 在 Ruby / HAML 中: + + ``` + n_('Apple', 'Apples', 3) + # => 'Apples' + ``` + + 使用插值: + + ``` + n_("There is a mouse.", "There are %d mice.", size) % size + # => When size == 1: 'There is a mouse.' + # => When size == 2: 'There are 2 mice.' + ``` + + 避免在单个字符串中使用`%d`或计数变量. 这样可以更自然地翻译某些语言. + +* 在 JavaScript 中: + + ``` + n__('Apple', 'Apples', 3) + // => 'Apples' + ``` + + 使用插值: + + ``` + n__('Last day', 'Last %d days', x) + // => When x == 1: 'Last day' + // => When x == 2: 'Last 2 days' + ``` + +`n_`方法仅应用于获取同一字符串的多个转换,而不能控制针对不同数量显示不同字符串的逻辑. 某些语言具有不同数量的目标复数形式-例如,中文(简体)在我们的翻译工具中仅具有一种目标复数形式. 这意味着翻译者将不得不选择只翻译一个字符串,而翻译在另一种情况下的表现将不符合预期. + +例如,更喜欢使用: + +``` +if selected_projects.one? + selected_projects.first.name +else + n__("Project selected", "%d projects selected", selected_projects.count) +end +``` + +而不是: + +``` +# incorrect usage example +n_("%{project_name}", "%d projects selected", count) % { project_name: 'GitLab' } +``` + +### Namespaces[](#namespaces "Permalink") + +命名空间是一种将属于在一起的翻译进行分组的方法. 它们通过在前缀后面加上条形符号( `|` )为我们的翻译人员提供上下文. 例如: + +``` +'Namespace|Translated string' +``` + +命名空间具有以下优点: + +* 它解决了词义上的歧义,例如: `Promotions|Promote` vs `Epic|Promote` +* 它使翻译人员可以专注于翻译属于相同产品区域而不是任意产品区域的外部化字符串. +* 它提供了语言环境以帮助翻译. + +在某些情况下,例如,对于无处不在的 UI 单词和短语(如"取消")或短语(如"保存更改")而言,名称空间可能会适得其反. + +命名空间应为 PascalCase. + +* 在 Ruby / HAML 中: + + ``` + s_('OpenedNDaysAgo|Opened') + ``` + + 如果找不到翻译,它将返回`Opened` . + +* 在 JavaScript 中: + + ``` + s__('OpenedNDaysAgo|Opened') + ``` + +注意:应从转换中删除名称空间. 有关[更多详细信息,](translation.html#namespaced-strings)请参见[翻译指南](translation.html#namespaced-strings) . + +### Dates / times[](#dates--times "Permalink") + +* 在 JavaScript 中: + +``` +import { createDateTimeFormat } from '~/locale'; + +const dateFormat = createDateTimeFormat({ year: 'numeric', month: 'long', day: 'numeric' }); +console.log(dateFormat.format(new Date('2063-04-05'))) // April 5, 2063 +``` + +这利用了[`Intl.DateTimeFormat`](https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat) . + +* 在 Ruby / HAML 中,我们有两种向日期和时间添加格式的方法: + + 1. **通过`l`帮助器** ,即`l(active_session.created_at, format: :short)` . 我们有一些预定义的[日期](https://gitlab.com/gitlab-org/gitlab/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/config/locales/en.yml#L54)和[时间](https://gitlab.com/gitlab-org/gitlab/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/config/locales/en.yml#L262)格式. 如果您需要添加新格式,因为代码的其他部分可能会从中受益,则需要将其添加到[en.yml](https://gitlab.com/gitlab-org/gitlab/blob/master/config/locales/en.yml)文件中. + 2. **通过`strftime`** ,即`milestone.start_date.strftime('%b %-d')` . 如果在[en.yml 上](https://gitlab.com/gitlab-org/gitlab/blob/master/config/locales/en.yml)定义的格式[均不](https://gitlab.com/gitlab-org/gitlab/blob/master/config/locales/en.yml)符合我们所需的日期/时间规范,并且由于非常特殊而无需将其添加为新格式的情况(例如,仅在单个视图中使用),则我们将使用`strftime` . . + +## Best practices[](#best-practices "Permalink") + +### Keep translations dynamic[](#keep-translations-dynamic "Permalink") + +在某些情况下,将翻译内容保持在数组或哈希中是有意义的. + +Examples: + +* 下拉列表的映射 +* 错误讯息 + +要存储此类数据,使用常数似乎是最佳选择,但这不适用于翻译. + +不好,请避免: + +``` +class MyPresenter + MY_LIST = { + key_1: _('item 1'), + key_2: _('item 2'), + key_3: _('item 3') + } +end +``` + +首次加载该类时,将调用翻译方法( `_` ),并将文本翻译为默认语言环境. 无论用户的语言环境是什么,这些值都不会再次转换. + +将类方法与备注一起使用时,也会发生类似的情况. + +不好,请避免: + +``` +class MyModel + def self.list + @list ||= { + key_1: _('item 1'), + key_2: _('item 2'), + key_3: _('item 3') + } + end +end +``` + +此方法将使用用户的语言环境来记住翻译,该用户首先"调用"此方法. + +为避免这些问题,请保持翻译动态. + +Good: + +``` +class MyPresenter + def self.my_list + { + key_1: _('item 1'), + key_2: _('item 2'), + key_3: _('item 3') + }.freeze + end +end +``` + +### Splitting sentences[](#splitting-sentences "Permalink") + +请不要拆分句子,因为这会假定句子的语法和结构在所有语言中都是相同的. + +例如,以下内容: + +``` +{{ s__("mrWidget|Set by") }} +{{ author.name }} +{{ s__("mrWidget|to be merged automatically when the pipeline succeeds") }} +``` + +应该外部化如下: + +``` +{{ sprintf(s__("mrWidget|Set by %{author} to be merged automatically when the pipeline succeeds"), { author: author.name }) }} +``` + +#### Avoid splitting sentences when adding links[](#avoid-splitting-sentences-when-adding-links "Permalink") + +当在翻译的句子之间使用链接时,这也适用,否则这些文本在某些语言中不可翻译. + +* 在 Ruby / HAML 中,而不是: + + ``` + - zones_link = link_to(s_('ClusterIntegration|zones'), 'https://cloud.google.com/compute/docs/regions-zones/regions-zones', target: '_blank', rel: 'noopener noreferrer') + = s_('ClusterIntegration|Learn more about %{zones_link}').html_safe % { zones_link: zones_link } + ``` + + 将链接的开始和结束 HTML 片段设置为变量,如下所示: + + ``` + - zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones' + - zones_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: zones_link_url } + = s_('ClusterIntegration|Learn more about %{zones_link_start}zones%{zones_link_end}').html_safe % { zones_link_start: zones_link_start, zones_link_end: '</a>'.html_safe } + ``` + +* 在 Vue 中,而不是: + + ``` + <template> + <div> + <gl-sprintf :message="s__('ClusterIntegration|Learn more about %{link}')"> + <template #link> + <gl-link + href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" + target="_blank" + >zones</gl-link> + </template> + </gl-sprintf> + </div> + </template> + ``` + + 将链接的开始和结束 HTML 片段设置为占位符,如下所示: + + ``` + <template> + <div> + <gl-sprintf :message="s__('ClusterIntegration|Learn more about %{linkStart}zones%{linkEnd}')"> + <template #link="{ content }"> + <gl-link + href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" + target="_blank" + >{{ content }}</gl-link> + </template> + </gl-sprintf> + </div> + </template> + ``` + +* 在 JavaScript 中(无法使用 Vue 时),而不是: + + ``` + {{ + sprintf(s__("ClusterIntegration|Learn more about %{link}"), { + link: '<a href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" target="_blank" rel="noopener noreferrer">zones</a>' + }) + }} + ``` + + 将链接的开始和结束 HTML 片段设置为占位符,如下所示: + + ``` + {{ + sprintf(s__("ClusterIntegration|Learn more about %{linkStart}zones%{linkEnd}"), { + linkStart: '<a href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" target="_blank" rel="noopener noreferrer">', + linkEnd: '</a>', + }) + }} + ``` + +其背后的原因是,在某些语言中,单词会根据上下文而变化. 例如,日语将は添加到句子的主语中,将を添加到宾语的主语中. 如果我们从句子中提取单个单词,则无法正确翻译. + +如有疑问,请尝试遵循此[Mozilla Developer 文档中](https://s0developer0mozilla0org.icopy.site/en-US/docs/Mozilla/Localization/Localization_content_best_practices)描述的最佳做法. + +##### Vue components interpolation[](#vue-components-interpolation "Permalink") + +在 Vue 组件中翻译 UI 文本时,您可能希望在转换字符串中包括子组件. 您不能使用仅 JavaScript 的解决方案来呈现翻译,因为 Vue 不会意识到子组件并将其呈现为纯文本. + +对于此用例,应使用在**GitLab UI 中**维护的`gl-sprintf`组件. + +`gl-sprintf`组件接受`message`属性,该属性是可翻译的字符串,并且为字符串中的每个占位符公开一个命名的插槽,这使您可以轻松地包含 Vue 组件. + +假设您要打印`Pipeline %{pipelineId} triggered %{timeago} by %{author}`的可翻译字符串`Pipeline %{pipelineId} triggered %{timeago} by %{author}` . 要将`%{timeago}`和`%{author}`占位符替换为 Vue 组件,以下是使用`gl-sprintf` : + +``` +<template> + <div> + <gl-sprintf :message="__('Pipeline %{pipelineId} triggered %{timeago} by %{author}')"> + <template #pipelineId>{{ pipeline.id }}</template> + <template #timeago> + <timeago :time="pipeline.triggerTime" /> + </template> + <template #author> + <gl-avatar-labeled + :src="pipeline.triggeredBy.avatarPath" + :label="pipeline.triggeredBy.name" + /> + </template> + </gl-sprintf> + </div> +</template> +``` + +有关更多信息,请参见[`gl-sprintf`](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-sprintf--default)文档. + +## Updating the PO files with the new content[](#updating-the-po-files-with-the-new-content "Permalink") + +现在,新内容已标记为要翻译,我们需要使用以下命令更新`locale/gitlab.pot`文件: + +``` +bin/rake gettext:regenerate +``` + +该命令将使用新外部化的字符串更新`locale/gitlab.pot`文件,并删除不再使用的任何字符串. 您应该检入此文件.一旦将更改保存在主文件中,它们将由[CrowdIn 提取](https://translate.gitlab.com)并显示以进行翻译. + +我们不需要签入对`locale/[language]/gitlab.po`文件的任何更改. 当[来自 CrowdIn 的翻译合并](merging_translations.html)时,它们会自动更新. + +如果`gitlab.pot`文件中存在合并冲突,则可以删除该文件并使用同一命令重新生成它. + +### Validating PO files[](#validating-po-files "Permalink") + +为了确保我们的翻译文件保持最新, `static-analysis`工作中有一个运行在 CI 上的 lint. + +要在本地`rake gettext:lint` PO 文件中的调整,可以运行`rake gettext:lint` . + +短绒将考虑以下因素: + +* 有效的 PO 文件语法 +* 可变用法 + * 仅一个未命名( `%d` )变量,因为变量的顺序可能会以不同的语言更改 + * 消息 ID 中使用的所有变量都在转换中使用 + * 转换中不应使用消息 ID 中没有的变量 +* 翻译时出错. + +错误按文件和消息 ID 分组: + +``` +Errors in `locale/zh_HK/gitlab.po`: + PO-syntax errors + SimplePoParser::ParserErrorSyntax error in lines + Syntax error in msgctxt + Syntax error in msgid + Syntax error in msgstr + Syntax error in message_line + There should be only whitespace until the end of line after the double quote character of a message text. + Parsing result before error: '{:msgid=>["", "You are going to remove %{project_name_with_namespace}.\\n", "Removed project CANNOT be restored!\\n", "Are you ABSOLUTELY sure?"]}' + SimplePoParser filtered backtrace: SimplePoParser::ParserError +Errors in `locale/zh_TW/gitlab.po`: + 1 pipeline + <%d 條流水線> is using unknown variables: [%d] + Failure translating to zh_TW with []: too few arguments +``` + +在此输出中, `locale/zh_HK/gitlab.po`具有语法错误. `locale/zh_TW/gitlab.po`具有转换中使用的变量,这些变量不在 ID `1 pipeline`的消息中. + +## Adding a new language[](#adding-a-new-language "Permalink") + +假设您想添加一种新语言的翻译,例如法语. + +1. 第一步是在`lib/gitlab/i18n.rb`注册新语言: + + ``` + ... + AVAILABLE_LANGUAGES = { + ..., + 'fr' => 'Français' + }.freeze + ... + ``` + +2. 接下来,您需要添加语言: + + ``` + bin/rake gettext:add_language[fr] + ``` + + 如果要为特定区域添加新语言,则命令类似,您只需要用下划线( `_` )分隔区域即可. 例如: + + ``` + bin/rake gettext:add_language[en_GB] + ``` + + 请注意,您需要在大写字母中指定地区部分. + +3. 现在已经添加了该语言,已经在以下路径下创建了一个新目录: `locale/fr/` . 现在,您可以开始使用 PO 编辑器来编辑位于`locale/fr/gitlab.edit.po`的 PO 文件. + +4. 更新完翻译后,您需要处理 PO 文件以生成二进制 MO 文件,最后更新包含翻译的 JSON 文件: + + ``` + bin/rake gettext:compile + ``` + +5. 为了查看翻译后的内容,我们需要更改首选语言,该语言可以在用户的**设置** ( `/profile` )下找到. + +6. 在确认更改没问题之后,您可以继续提交新文件. 例如: + + ``` + git add locale/fr/ app/assets/javascripts/locale/fr/ + git commit -m "Add French translations for Value Stream Analytics page" + ``` \ No newline at end of file diff --git a/docs/647.md b/docs/647.md new file mode 100644 index 0000000000000000000000000000000000000000..008820abe88e6856175c670009df84c50bd1702f --- /dev/null +++ b/docs/647.md @@ -0,0 +1,91 @@ +# Translating GitLab + +> 原文:[https://docs.gitlab.com/ee/development/i18n/translation.html](https://docs.gitlab.com/ee/development/i18n/translation.html) + +* [Using CrowdIn](#using-crowdin) + * [Sign In](#sign-in) + * [Language Selections](#language-selections) + * [Translation Editor](#translation-editor) +* [General Translation Guidelines](#general-translation-guidelines) + * [Namespaced strings](#namespaced-strings) + * [Technical terms](#technical-terms) + * [Formality](#formality) + * [Inclusive language](#inclusive-language) + * [Updating the glossary](#updating-the-glossary) +* [French Translation Guidelines](#french-translation-guidelines) + * [Inclusive language in French](#inclusive-language-in-french) + +# Translating GitLab[](#translating-gitlab "Permalink") + +为了管理翻译过程,我们使用[CrowdIn](https://crowdin.com) . + +## Using CrowdIn[](#using-crowdin "Permalink") + +第一步是熟悉 CrowdIn. + +### Sign In[](#sign-in "Permalink") + +要在[https://translate.gitlab.com 上](https://translate.gitlab.com)提供翻译,您必须创建一个 CrowdIn 帐户. 您可以创建一个新帐户或使用其任何受支持的登录服务. + +### Language Selections[](#language-selections "Permalink") + +manbetx 客户端打不开被翻译成多种语言. + +1. 通过单击标志来选择您想要贡献翻译的语言 +2. 您将看到文件和文件夹的列表. 单击`gitlab.pot`打开翻译编辑器. + +### Translation Editor[](#translation-editor "Permalink") + +The online translation editor is the easiest way to contribute translations. + +[![CrowdIn Editor](img/6314765d395236bbba1552cc65c1228c.png)](img/crowdin-editor.png) + +1. 用于翻译的字符串列在左侧面板中 +2. 翻译输入到中央面板中. 包含复数的字符串将需要多次翻译. 上面显示了要翻译的字符串,并突出显示了词汇表术语. 如果要翻译的字符串不清楚,则可以"请求上下文" + +单击右侧的术语,可以在右侧面板中找到常用术语的词汇表. 可以添加评论以与社区讨论翻译. + +记住要**保存**每个翻译. + +## General Translation Guidelines[](#general-translation-guidelines "Permalink") + +转换任何字符串之前,请务必检查以下准则. + +### Namespaced strings[](#namespaced-strings "Permalink") + +当外部字符串带有名称空间(例如`s_('OpenedNDaysAgo|Opened')` ,应从最终转换中删除该名称空间. 例如,用法语`OpenedNDaysAgo|Opened`将被翻译为`Ouvert•e` ,而不是`OpenedNDaysAgo|Ouvert•e` . + +### Technical terms[](#technical-terms "Permalink") + +某些技术术语应像专有名词一样对待,不要翻译. + +使用[https://translate.gitlab.com](https://translate.gitlab.com)时,在词汇表中会注明应始终为英语的技术术语. + +这有助于维护工具(例如`git`客户端)和 GitLab 之间的逻辑连接和一致性. + +### Formality[](#formality "Permalink") + +软件中使用的形式级别因语言而异: + +| Language | Formality | Example | +| --- | --- | --- | +| French | formal | `vous` for `you` | +| German | informal | `du` for `you` | + +您可以参考词汇表中其他翻译的字符串和注释,以帮助确定适当的形式水平. + +### Inclusive language[](#inclusive-language "Permalink") + +[多样性](https://about.gitlab.com/handbook/values/#diversity)是 GitLab 的价值之一. 我们要求您避免翻译将性别或族裔排除在外的人. 在区分男女形式的语言中,请同时使用或选择中性的表述. + +例如,德语中的"用户"一词可以翻译成" Benutzer"(男性)或" Benutzerin"(女性). 因此,"创建新用户"将翻译为" Benutzer(in)anlegen". + +### Updating the glossary[](#updating-the-glossary "Permalink") + +要提出对词汇表的补充,请[打开一期](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=✓&state=all&label_name[]=Category:Internationalization) . + +## French Translation Guidelines[](#french-translation-guidelines "Permalink") + +### Inclusive language in French[](#inclusive-language-in-french "Permalink") + +在法语中,"包容所有法律"已结束(请参见[Legifrance](https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000036068906&categorieLien=id) ). 因此,要包括两个性别,请写上" Utilisateurs et utilisatrices",而不是" Utilisateur·rice·s". 如果缺少空间,则应单独使用男性. \ No newline at end of file diff --git a/docs/648.md b/docs/648.md new file mode 100644 index 0000000000000000000000000000000000000000..41a694a211754e8b3e68706865045420203d2207 --- /dev/null +++ b/docs/648.md @@ -0,0 +1,138 @@ +# Proofread Translations + +> 原文:[https://docs.gitlab.com/ee/development/i18n/proofreader.html](https://docs.gitlab.com/ee/development/i18n/proofreader.html) + +* [Proofreaders](#proofreaders) +* [Become a proofreader](#become-a-proofreader) + +# Proofread Translations[](#proofread-translations "Permalink") + +大多数翻译是由社区贡献,审查和接受的. 我们非常感谢翻译人员和校对人员所做的工作! + +## Proofreaders[](#proofreaders "Permalink") + +* Albanian + * 需要校对者. +* Amharic + * Tsegaselassie Tadesse - [GitLab](https://gitlab.com/tsega), [CrowdIn](https://crowdin.com/profile/tsegaselassi/activity) +* Arabic + * 需要校对者. +* Bosnian + * 需要校对者. +* Bulgarian + * Lyubomir Vasilev- [CrowdIn](https://crowdin.com/profile/lyubomirv) +* Catalan + * 大卫 Planella - [GitLab](https://gitlab.com/dplanella) , [CrowdIn](https://crowdin.com/profile/dplanella) +* 简体中文简体中文 + * 黄涛- [GitLab](https://gitlab.com/htve) , [CrowdIn](https://crowdin.com/profile/htve) + * 维克多武- [GitLab](https://gitlab.com/victorwuky) , [CrowdIn](https://crowdin.com/profile/victorwu) + * 小刚文- [GitLab](https://gitlab.com/xiaogang_gitlab) , [CrowdIn](https://crowdin.com/profile/xiaogang_gitlab) +* Chinese Traditional 繁体中文 + * Weizhe Ding - [GitLab](https://gitlab.com/d.weizhe) , [CrowdIn](https://crowdin.com/profile/d.weizhe) + * Yi-Jyun Pan - [GitLab](https://gitlab.com/pan93412) , [CrowdIn](https://crowdin.com/profile/pan93412) + * Victor Wu - [GitLab](https://gitlab.com/victorwuky) , [CrowdIn](https://crowdin.com/profile/victorwu) +* Chinese Traditional, Hong Kong 繁体中文(香港) + * Victor Wu - [GitLab](https://gitlab.com/victorwuky) , [CrowdIn](https://crowdin.com/profile/victorwu) + * Ivan Ip - [GitLab](https://gitlab.com/lifehome) , [CrowdIn](https://crowdin.com/profile/lifehome) +* Croatian + * 需要校对者. +* Czech + * 一月 Urbanec - [GitLab](https://gitlab.com/TatranskyMedved) , [CrowdIn](https://crowdin.com/profile/Tatranskymedved) +* Danish + * Saederup92- [GitLab](https://gitlab.com/Saederup92) , [人群进入](https://crowdin.com/profile/Saederup92) +* Dutch + * 艾米丽 Hendle - [GitLab](https://gitlab.com/pundachan) , [CrowdIn](https://crowdin.com/profile/pandachan) +* Esperanto + * Lyubomir Vasilev- [CrowdIn](https://crowdin.com/profile/lyubomirv) +* Estonian + * 需要校对者. +* Filipino + * Andrei Jiroh Halili- [GitLab](https://gitlab.com/AJHalili2006DevPH) , [克劳丁](https://crowdin.com/profile/AndreiJirohHaliliDev2006) +* French + * Davy Defaud- [GitLab](https://gitlab.com/DevDef) , [人群](https://crowdin.com/profile/DevDef) +* Galician + * AntónMéixome- [群众](https://crowdin.com/profile/meixome) + * 佩德罗·加西亚- [GitLab](https://gitlab.com/pedgarrod) , [CrowdIn](https://crowdin.com/profile/breaking_pitt) +* German + * 迈克尔 Hahnle - [GitLab](https://gitlab.com/mhah) , [CrowdIn](https://crowdin.com/profile/mhah) + * 卡特琳 Leinweber - [GitLab](https://gitlab.com/katrinleinweber/) , [CrowdIn](https://crowdin.com/profile/katrinleinweber) +* Greek + * 需要校对者. +* Hebrew + * Yaron Shahrabani- [GitLab](https://gitlab.com/yarons) , [人群](https://crowdin.com/profile/YaronSh) +* Hindi + * 需要校对者. +* Hungarian + * 需要校对者. +* Indonesian + * 阿迪 Ferdian - [GitLab](https://gitlab.com/adiferd) , [CrowdIn](https://crowdin.com/profile/adiferd) + * Ahmad Naufal Mukhtar- [GitLab](https://gitlab.com/anaufalm) , [CrowdIn](https://crowdin.com/profile/anaufalm) +* Italian + * Massimiliano Cuttini- [GitLab](https://gitlab.com/maxcuttins) , [人群](https://crowdin.com/profile/maxcuttins) + * 保罗 Falomo - [GitLab](https://gitlab.com/paolofalomo) , [CrowdIn](https://crowdin.com/profile/paolo.falomo) +* Japanese + * 佐藤博之- [GitLab](https://gitlab.com/hiroponz) , [CrowdIn](https://crowdin.com/profile/hiroponz) + * Tomo Dote- [GitLab](https://gitlab.com/fu7mu4) , [人群](https://crowdin.com/profile/fu7mu4) + * 博美 Nozawa- [GitLab](https://gitlab.com/hir0mi) , [CrowdIn](https://crowdin.com/profile/hir0mi) + * 木村拓哉 Noguchi- [GitLab](https://gitlab.com/tnir) , [CrowdIn](https://crowdin.com/profile/tnir) +* Korean + * Chang-Ho Cha- [GitLab](https://gitlab.com/changho-cha) , [人群](https://crowdin.com/profile/zzazang) + * Ji Hun Oh- [GitLab](https://gitlab.com/Baw-Appie) , [CrowdIn](https://crowdin.com/profile/BawAppie) + * Jeongwhan 彩- [GitLab](https://gitlab.com/jeongwhanchoi) , [CrowdIn](https://crowdin.com/profile/jeongwhanchoi) +* Mongolian + * 需要校对者. +* 挪威博克马尔 + * 需要校对者. +* Polish + * 菲利普机甲- [GitLab](https://gitlab.com/mehenz) , [CrowdIn](https://crowdin.com/profile/mehenz) + * Maksymilian 罗马- [GitLab](https://gitlab.com/villaincandle) , [CrowdIn](https://crowdin.com/profile/villaincandle) +* Portuguese + * Diogo Trindade- [GitLab](https://gitlab.com/luisdiogo2071317) , [人群](https://crowdin.com/profile/ldiogotrindade) +* 葡萄牙语,巴西语 + * 保罗乔治·戈麦斯贝泽拉- [GitLab](https://gitlab.com/paulobezerra) , [CrowdIn](https://crowdin.com/profile/paulogomes.rep) + * [AndréGama](https://crowdin.com/profile/ToeOficial) - [GitLab](https://gitlab.com/andregamma) , [众筹](https://crowdin.com/profile/ToeOficial) +* Romanian + * 需要校对者. +* Russian + * 尼基塔 Grylov - [GitLab](https://gitlab.com/nixel2007) , [Crowdin](https://crowdin.com/profile/nixel2007) + * 阿列克西 Lustin - [GitLab](https://gitlab.com/allustin) , [Crowdin](https://crowdin.com/profile/lustin) + * 马克 Minakou - [GitLab](https://gitlab.com/sandzhaj) , [Crowdin](https://crowdin.com/profile/sandzhaj) + * 尼克·沃伦金- [克劳丁](https://crowdin.com/profile/NickVolynkin) + * 安德烈·科马洛夫- [GitLab](https://gitlab.com/elkamarado) , [Crowdin](https://crowdin.com/profile/kamarado) + * Iaroslav Postovalov- [GitLab](https://gitlab.com/CMDR_Tvis) , [克劳丁](https://crowdin.com/profile/CMDR_Tvis) +* 塞尔维亚文(拉丁文和西里尔文) + * 需要校对者. +* Slovak + * 需要校对者. +* Spanish + * 佩德罗·加西亚- [GitLab](https://gitlab.com/pedgarrod) , [CrowdIn](https://crowdin.com/profile/breaking_pitt) +* Swedish + * 需要校对者. +* Turkish + * AliDemirtaş- [GitLab](https://gitlab.com/alidemirtas) , [CrowdIn](https://crowdin.com/profile/alidemirtas) + * 瑞法特Ünalmış(瑞法特 Unalmis) - [GitLab](https://gitlab.com/runalmis) , [CrowdIn](https://crowdin.com/profile/runalmis) +* Ukrainian + * Volodymyr Sobotovych- [GitLab](https://gitlab.com/wheleph) , [人群](https://crowdin.com/profile/wheleph) + * Andrew Vityuk- [GitLab](https://gitlab.com/3_1_3_u) , [人群](https://crowdin.com/profile/andruwa13) +* Welsh + * Delyth 价格- [GitLab](https://gitlab.com/Delyth) , [CrowdIn](https://crowdin.com/profile/DelythPrys) + +## Become a proofreader[](#become-a-proofreader "Permalink") + +> **注意:**在 CrowdIn 中请求校对者权限之前,请确保您具有向 GitLab 项目提供翻译的历史. + +1. 向 GitLab 提供翻译. 请参阅有关[翻译 GitLab 的说明](translation.html) . + + 转换 GitLab 是一项社区工作,需要团队合作并注重细节. 校对人员在帮助新撰稿人,确保翻译的一致性和质量方面发挥着重要作用. 您作为翻译的行为和贡献应在要求成为校对之前反映出这一点. + +2. 通过打开将自己添加到校对者列表的合并请求来请求校对者权限. + + 打开[proofreader.md 源文件](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/i18n/proofreader.md) ,然后单击" **编辑"** . + + 按字母顺序添加您的语言,并将您自己添加到列表中,包括:-名称-链接到 GitLab 配置文件-链接到 CrowdIn 配置文件 + + 在合并请求说明中,请包含指向您之前翻译过的所有项目的链接. + +3. 熟练使用该语言的[GitLab 团队成员](https://about.gitlab.com/company/team/)或[核心团队成员](https://about.gitlab.com/community/core-team/)或当前的校对者,将考虑您以前作为校对者的要求. + + * 当要求使用某种语言的第一校对者时,并且没有使用该语言的[GitLab 团队成员](https://about.gitlab.com/company/team/)或[Core 团队成员](https://about.gitlab.com/community/core-team/) ,我们将请求指向其他社区或项目中先前翻译工作的链接. \ No newline at end of file diff --git a/docs/649.md b/docs/649.md new file mode 100644 index 0000000000000000000000000000000000000000..3a80a5c7de28ea716ce295062b370aea7699fea2 --- /dev/null +++ b/docs/649.md @@ -0,0 +1,49 @@ +# Merging translations from CrowdIn + +> 原文:[https://docs.gitlab.com/ee/development/i18n/merging_translations.html](https://docs.gitlab.com/ee/development/i18n/merging_translations.html) + +* [Validation](#validation) +* [Merging translations](#merging-translations) +* [Recreate the merge request](#recreate-the-merge-request) +* [Recreate the GitLab integration in CrowdIn](#recreate-the-gitlab-integration-in-crowdin) + +# Merging translations from CrowdIn[](#merging-translations-from-crowdin "Permalink") + +CrowdIn 自动将`gitlab.pot`文件与 CrowdIn 服务同步,将新添加的外部化字符串呈现给翻译者社区. + +[GitLab CrowdIn Bot](https://gitlab.com/gitlab-crowdin-bot)还会创建合并请求,以接受新批准的翻译提交并将其合并到`locale/<language>/gitlab.po`文件中. 检查[`gitlab-crowdin-bot`创建](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&utf8=✓&state=opened&author_username=gitlab-crowdin-bot)的[合并请求,](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&utf8=✓&state=opened&author_username=gitlab-crowdin-bot)以查看新的和合并的合并请求. + +## Validation[](#validation "Permalink") + +默认情况下,CrowdIn 使用提交消息中的`[skip ci]`提交翻译. 这样做是为了避免运行一堆管道. 在合并翻译之前,请确保触发管道以验证翻译,我们进行了静态分析,以验证 CrowdIn 不执行的操作. 为`master-i18n`分支在`https://gitlab.com/gitlab-org/gitlab/pipelines/new` (需要开发人员访问权限)处创建一个新管道. + +如果存在验证错误,最简单的解决方案是拒绝 CrowdIn 中有问题的字符串,并在注释中注明解决该问题所需的内容. 有一个[问题](https://gitlab.com/gitlab-org/gitlab/-/issues/23256)提示自动完成这一过程. 拒登将排除无效翻译,合并请求将在几分钟内更新. + +将 CrowdIn 端的集成暂停一会可能很方便,因此翻译不会持续进行. 这可以通过在[CrowdIn 集成设置页面](https://translate.gitlab.com/project/gitlab-ee/settings#integration)上单击" `Pause sync`来完成. + +解决所有故障后,需要再次检查翻译,如[机密问题](../../user/project/issues/confidential_issues.html) `https://gitlab.com/gitlab-org/gitlab/-/issues/19485` . + +## Merging translations[](#merging-translations "Permalink") + +当发现所有翻译都很好并且流水线通过时,这些翻译可以合并到 master 分支中. 合并翻译时,请确保选中" **删除源分支"**复选框,以便 CrowdIn 在合并新翻译后从 master 重新创建`master-i18n` . + +我们正在讨论使[整个过程自动化](https://gitlab.com/gitlab-org/gitlab/-/issues/19896) . + +## Recreate the merge request[](#recreate-the-merge-request "Permalink") + +一旦关闭或合并旧的 CrowdIn,它就会创建一个新的合并请求. 但是它不会每次都重新创建`master-i18n`分支. 要强制 CrowdIn 重新创建分支,请关闭所有[打开的合并请求](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&utf8=✓&state=opened&author_username=gitlab-crowdin-bot)并删除[`master-18n`](https://gitlab.com/gitlab-org/gitlab/-/branches/all?utf8=✓&search=master-i18n) . + +当合并请求包含已在主服务器上修复的故障时,可能需要这样做. + +## Recreate the GitLab integration in CrowdIn[](#recreate-the-gitlab-integration-in-crowdin "Permalink") + +***注意:**这些说明仅适用于 GitLab 团队成员. + +If for some reason the GitLab integration in CrowdIn does not exist, it can be recreated by the following steps: + +1. 以`gitlab-crowdin-bot`身份登录到 GitLab(如果您是 GitLab 团队成员,请在 GitLab 共享的[1Password 帐户中](https://about.gitlab.com/handbook/security/#1password-for-teams)找到凭据 +2. 使用 GitLab 集成登录 Crowdin +3. 导航到设置>集成> GitLab>设置集成 +4. Select `gitlab-org/gitlab` repository +5. 在" `Select Branches for Translation` ,选择" `master` +6. 确保`Service Branch Name`为`master-i18n` \ No newline at end of file diff --git a/docs/650.md b/docs/650.md new file mode 100644 index 0000000000000000000000000000000000000000..dbeaf92e5723e4baf6800a043f8c85d79c652e43 --- /dev/null +++ b/docs/650.md @@ -0,0 +1,186 @@ +# Value Stream Analytics development guide + +> 原文:[https://docs.gitlab.com/ee/development/value_stream_analytics.html](https://docs.gitlab.com/ee/development/value_stream_analytics.html) + +* [Stage](#stage) + * [Events](#events) + * [Implementing an `Event` class](#implementing-an-event-class) + * [Validating start and end events](#validating-start-and-end-events) + * [Parent](#parent) + * [How parent relationship it work](#how-parent-relationship-it-work) + * [Default stages](#default-stages) +* [Data Collector](#data-collector) +* [Database query](#database-query) +* [High-level overview](#high-level-overview) +* [Testing](#testing) + +# Value Stream Analytics development guide[](#value-stream-analytics-development-guide "Permalink") + +值流分析计算域对象上记录的两个任意事件之间的时间,并提供有关持续时间的汇总统计信息. + +有关如何在 GitLab 中配置 Value Stream Analytics 的信息,请参阅我们的[分析文档](../user/analytics/value_stream_analytics.html) . + +## Stage[](#stage "Permalink") + +在开发过程中,会发生一些事件,这些事件会移动问题并在不同的进展阶段合并请求,直到认为它们完成为止. 这些阶段可以用`Stage`模型表示. + +示例阶段: + +* Name: Development +* 开始事件:问题已创建 +* 结束事件:在提交中首先提到的问题 +* Parent: `Group: gitlab-org` + +### Events[](#events "Permalink") + +事件是价值流分析功能的最小构建块. 一个阶段包括两个事件: + +* Start +* End + +这些事件在持续时间计算中起关键作用. + +Formula: `duration = end_event_time - start_event_time` + +为了使持续时间计算更加灵活,每个`Event`都实现为一个单独的类. 他们负责定义将在计算查询中使用的时间戳表达式. + +#### Implementing an `Event` class[](#implementing-an-event-class "Permalink") + +有一些方法需要实现, `StageEvent`基类非常详细地描述了它们. 最重要的是: + +* `object_type` +* `timestamp_projection` + +`object_type`方法定义将查询哪个域对象以进行计算. 当前允许两种模型: + +* `Issue` +* `MergeRequest` + +对于持续时间计算,将使用`timestamp_projection`方法. + +``` +def timestamp_projection + # your timestamp expression comes here +end + +# event will use the issue creation time in the duration calculation +def timestamp_projection + Issue.arel_table[:created_at] +end +``` + +**注意:**也可以使用更复杂的表达式(例如,使用`COALESCE` ). 查看现有事件类作为示例. + +在某些情况下,仅定义`timestamp_projection`方法是不够的. 计算查询应该知道哪个表包含时间戳表达式. 每个`Event`类负责修改计算查询,以使`timestamp_projection`起作用. 这通常意味着加入一个附加表. + +连接`issue_metrics`表并使用`first_mentioned_in_commit_at`列作为时间戳表达式的`first_mentioned_in_commit_at` : + +``` +def object_type + Issue +end + +def timestamp_projection + IssueMetrics.arel_table[:first_mentioned_in_commit_at] +end + +def apply_query_customization(query) + # in this case the query attribute will be based on the Issue model: `Issue.where(...)` + query.joins(:metrics) +end +``` + +### Validating start and end events[](#validating-start-and-end-events "Permalink") + +某些开始/结束事件对彼此不"兼容". 例如: + +* 从"已创建问题"到"已合并请求":事件类在不同的域模型上定义, `object_type`方法不同. +* "问题已关闭"到"问题已创建":必须先创建问题,然后才能将其关闭. +* 从"问题已关闭"到"问题已关闭":持续时间始终为 0. + +`StageEvents`模块描述了允许的`start_event`和`end_event`配对( `PAIRING_RULES`常数). 如果添加了新事件,则需要在该模块中注册它. 要添加新事件: + +1. 在`ENUM_MAPPING`添加一个具有唯一编号的条目,该条目将在`Stage`模型中用作`enum` . +2. 在`PAIRING_RULES`哈希中定义哪些事件与该事件兼容. + +支持的开始/结束事件配对: + +图 LR; IssueCreated-> IssueClosed; IssueCreated-> IssueFirstAddedToBoard; IssueCreated-> IssueFirstAssociatedWithMilestone; IssueCreated-> IssueFirstMentionedInCommit; IssueCreated-> IssueLastEdited; IssueCreated-> IssueLabelAdded; IssueCreated-> IssueLabelRemoved; MergeRequestCreated-> MergeRequestMerged; MergeRequestCreated-> MergeRequestClosed; MergeRequestCreated-> MergeRequestFirstDeployedToProduction; MergeRequestCreated-> MergeRequestLastBuildStarted; MergeRequestCreated-> MergeRequestLastBuildFinished; MergeRequestCreated-> MergeRequestLastEdited; MergeRequestCreated-> MergeRequestLabelAdded; MergeRequestCreated-> MergeRequestLabelRemoved; MergeRequestLastBuildStarted-> MergeRequestLastBuildFinished; MergeRequestLastBuildStarted-> MergeRequestClosed; MergeRequestLastBuildStarted-> MergeRequestFirstDeployedToProduction; MergeRequestLastBuildStarted-> MergeRequestLastEdited; MergeRequestLastBuildStarted-> MergeRequestMerged; MergeRequestLastBuildStarted-> MergeRequestLabelAdded; MergeRequestLastBuildStarted-> MergeRequestLabelRemoved; MergeRequestMerged-> MergeRequestFirstDeployedToProduction; MergeRequestMerged-> MergeRequestClosed; MergeRequestMerged-> MergeRequestFirstDeployedToProduction; MergeRequestMerged-> MergeRequestLastEdited; MergeRequestMerged-> MergeRequestLabelAdded; MergeRequestMerged-> MergeRequestLabelRemoved; IssueLabelAdded-> IssueLabelAdded; IssueLabelAdded-> IssueLabelRemoved; IssueLabelAdded-> IssueClosed; IssueLabelRemoved-> IssueClosed; IssueFirstAddedToBoard-> IssueClosed; IssueFirstAddedToBoard-> IssueFirstAssociatedWithMilestone; IssueFirstAddedToBoard-> IssueFirstMentionedInCommit; IssueFirstAddedToBoard-> IssueLastEdited; IssueFirstAddedToBoard-> IssueLabelAdded; IssueFirstAddedToBoard-> IssueLabelRemoved; IssueFirstAssociatedWithMilestone-> IssueClosed; IssueFirstAssociatedWithMilestone-> IssueFirstAddedToBoard; IssueFirstAssociatedWithMilestone-> IssueFirstMentionedInCommit; IssueFirstAssociatedWithMilestone-> IssueLastEdited; IssueFirstAssociatedWithMilestone-> IssueLabelAdded; IssueFirstAssociatedWithMilestone-> IssueLabelRemoved; IssueFirstMentionedInCommit-> IssueClosed; IssueFirstMentionedInCommit-> IssueFirstAssociatedWithMilestone; IssueFirstMentionedInCommit-> IssueFirstAddedToBoard; IssueFirstMentionedInCommit-> IssueLastEdited; IssueFirstMentionedInCommit-> IssueLabelAdded; IssueFirstMentionedInCommit->已删除 IssueLabel; IssueClosed-> IssueLastEdited; IssueClosed-> IssueLabelAdded; IssueClosed-> IssueLabelRemoved; MergeRequestClosed-> MergeRequestFirstDeployedToProduction; MergeRequestClosed-> MergeRequestLastEdited; MergeRequestClosed-> MergeRequestLabelAdded; MergeRequestClosed-> MergeRequestLabelRemoved; MergeRequestFirstDeployedToProduction-> MergeRequestLastEdited; MergeRequestFirstDeployedToProduction-> MergeRequestLabelAdded; MergeRequestFirstDeployedToProduction-> MergeRequestLabelRemoved; MergeRequestLastBuildFinished-> MergeRequestClosed; MergeRequestLastBuildFinished-> MergeRequestFirstDeployedToProduction; MergeRequestLastBuildFinished-> MergeRequestLastEdited; MergeRequestLastBuildFinished-> MergeRequestMerged; MergeRequestLastBuildFinished-> MergeRequestLabelAdded; MergeRequestLastBuildFinished-> MergeRequestLabelRemoved; MergeRequestLabelAdded-> MergeRequestLabelAdded; MergeRequestLabelAdded-> MergeRequestLabelRemoved; MergeRequestLabelRemoved-> MergeRequestLabelAdded; MergeRequestLabelRemoved-> MergeRequestLabelRemoved; + +### Parent[](#parent "Permalink") + +团队和组织可能会定义自己的软件构建方式,因此阶段可能完全不同. 对于每个阶段,都需要定义一个父对象. + +目前支持的父母: + +* `Project` +* `Group` + +#### How parent relationship it work[](#how-parent-relationship-it-work "Permalink") + +1. 用户导航到价值流分析页面. +2. 用户选择一个组. +3. 后端将加载选定组的已定义阶段. +4. 对阶段的添加和修改将仅保留在所选组中. + +### Default stages[](#default-stages "Permalink") + +价值流分析的[原始实施](https://gitlab.com/gitlab-org/gitlab/-/issues/847)定义了 7 个阶段. 每个父母都可以使用这些阶段,但是无法更改这些阶段. 为了提高效率并减少创建的记录数,默认阶段被表示为内存中对象(不持久). 当用户首次创建自定义阶段时,所有阶段都将保留. 此行为在价值流分析服务对象中实现. 这样做的原因是我们希望稍后添加隐藏和订购阶段的功能. + +## Data Collector[](#data-collector "Permalink") + +`DataCollector`是从数据库查询数据的中心点. 该类始终在单个阶段上运行,并且由以下组件组成: + +* `BaseQueryBuilder`: + * 负责编写初始查询. + * 处理特定于`Stage`配置:事件及其查询自定义. + * 来自用户界面的参数:日期范围. +* `Median` :使用`BaseQueryBuilder`的查询计算一个阶段的中位数持续时间. +* `RecordsFetcher` :使用来自`BaseQueryBuilder`的查询和特定的`Finder`类加载阶段的相关记录,以应用可见性规则. +* `DataForDurationChart` :加载散点图的带有完成时间(结束事件时间戳)的计算的持续时间. + +对于新的计算或查询,可将其实现为`DataCollector`类中的新方法调用. + +## Database query[](#database-query "Permalink") + +数据库查询的结构: + +``` +SELECT (customized by: Median or RecordsFetcher or DataForDurationChart) +FROM OBJECT_TYPE (Issue or MergeRequest) +INNER JOIN (several JOIN statements, depending on the events) +WHERE + (Filter by the PARENT model, example: filter Issues from Project A) + (Date range filter based on the OBJECT_TYPE.created_at) + (Check if the START_EVENT is earlier than END_EVENT, preventing negative duration) +``` + +`Median`的`SELECT`语句的结构: + +``` +SELECT (calculate median from START_EVENT_TIME-END_EVENT_TIME) +``` + +用于`DataForDurationChart`的`SELECT`语句的`DataForDurationChart` : + +``` +SELECT (START_EVENT_TIME-END_EVENT_TIME) as duration, END_EVENT.timestamp +``` + +## High-level overview[](#high-level-overview "Permalink") + +* Rails 控制器( `Analytics::CycleAnalytics`模块):值流分析通过 JSON 端点公开其数据,该端点在`analytics`工作区中实现. 配置阶段还实现 JSON 端点(CRUD). +* 服务( `Analytics::CycleAnalytics`模块):所有与`Stage`相关的操作都将委派给相应的服务对象. +* 模型( `Analytics::CycleAnalytics`模块):模型用于持久化`Stage`对象`ProjectStage`和`GroupStage` . +* 要素类( `Gitlab::Analytics::CycleAnalytics`模块): + * 负责撰写查询并定义特定于功能的业务逻辑. + * `DataCollector` , `Event` , `StageEvents`等. + +## Testing[](#testing "Permalink") + +由于我们有很多事件和可能的配对,因此无法测试每个配对. 规则是至少要有一个使用`Event`类的测试用例. + +使用新`Event`为阶段编写测试用例可能会遇到挑战,因为必须为两个事件都创建数据. 为了使此过程更简单,必须在`data_collector_spec.rb`中实现每个测试用例,在该`data_collector_spec.rb`中,通过`DataCollector`对该阶段进行测试. 每个测试用例都将变成多个测试,涵盖以下情况: + +* 不同的父母: `Group`或`Project` +* 不同的计算方式: `Median` , `RecordsFetcher`或`DataForDurationChart` \ No newline at end of file diff --git a/docs/651.md b/docs/651.md new file mode 100644 index 0000000000000000000000000000000000000000..26849b9f9964611b7fd2290d6bef1465a8523898 --- /dev/null +++ b/docs/651.md @@ -0,0 +1,542 @@ +# GitLab subscription + +> 原文:[https://docs.gitlab.com/ee/subscriptions/](https://docs.gitlab.com/ee/subscriptions/) + +* [Choosing a GitLab subscription](#choosing-a-gitlab-subscription) + * [Choosing a GitLab tier](#choosing-a-gitlab-tier) + * [Choosing between GitLab.com or self-managed](#choosing-between-gitlabcom-or-self-managed) + * [Choosing a GitLab.com group or personal subscription](#choosing-a-gitlabcom-group-or-personal-subscription) + * [Choosing the number of users](#choosing-the-number-of-users) + * [GitLab.com](#gitlabcom) + * [Self-managed](#self-managed) + * [Users statistics](#users-statistics) +* [Obtain a GitLab subscription](#obtain-a-gitlab-subscription) + * [Subscribe to GitLab.com](#subscribe-to-gitlabcom) + * [Subscribe through GitLab self-managed](#subscribe-through-gitlab-self-managed) +* [Manage your GitLab account](#manage-your-gitlab-account) + * [Change billing information](#change-billing-information) + * [Change payment method](#change-payment-method) + * [Change the linked account](#change-the-linked-account) + * [Change the associated namespace](#change-the-associated-namespace) + * [Change customer portal account password](#change-customer-portal-account-password) +* [View your subscription](#view-your-subscription) + * [View your GitLab.com subscription](#view-your-gitlabcom-subscription) + * [View your self-managed subscription](#view-your-self-managed-subscription) +* [Renew your subscription](#renew-your-subscription) + * [Prepare for renewal by reviewing your account](#prepare-for-renewal-by-reviewing-your-account) + * [Users over License](#users-over-license) + * [Purchase additional seats for GitLab.com](#purchase-additional-seats-for-gitlabcom) + * [Purchase additional users for self-managed](#purchase-additional-users-for-self-managed) + * [Seat Link](#seat-link) + * [Disable Seat Link](#disable-seat-link) + * [Renew or change a GitLab.com subscription](#renew-or-change-a-gitlabcom-subscription) + * [Automatic renewal](#automatic-renewal) + * [Renew a self-managed subscription](#renew-a-self-managed-subscription) +* [Upgrade your subscription tier](#upgrade-your-subscription-tier) + * [Upgrade your GitLab.com subscription tier](#upgrade-your-gitlabcom-subscription-tier) + * [Upgrade your self-managed subscription tier](#upgrade-your-self-managed-subscription-tier) +* [Subscription expiry](#subscription-expiry) + * [Self-managed GitLab data](#self-managed-gitlab-data) +* [CI pipeline minutes](#ci-pipeline-minutes) + * [Purchasing additional CI minutes](#purchasing-additional-ci-minutes) +* [Contact Support](#contact-support) +* [GitLab for Education subscriptions](#gitlab-for-education-subscriptions) +* [GitLab for Open Source subscriptions](#gitlab-for-open-source-subscriptions) + +# GitLab subscription[](#gitlab-subscription "Permalink") + +GitLab 提供了多层功能. 您的订阅决定了您有权访问的层. 订阅有效期为 12 个月. + +GitLab 为[GitLab 教育计划](https://about.gitlab.com/solutions/education/)和[GitLab 开源计划的](https://about.gitlab.com/solutions/open-source/)参与者提供特殊订阅. 有关获取和续订这些订阅的详细信息,请参阅: + +* [GitLab for Education subscriptions](#gitlab-for-education-subscriptions) +* [GitLab for Open Source subscriptions](#gitlab-for-open-source-subscriptions) + +## Choosing a GitLab subscription[](#choosing-a-gitlab-subscription "Permalink") + +选择订阅时,请考虑以下因素: + +* [GitLab tier](#choosing-a-gitlab-tier) +* [GitLab.com or self-managed](#choosing-between-gitlabcom-or-self-managed) +* [Group or personal subscription (GitLab.com only)](#choosing-a-gitlabcom-group-or-personal-subscription) +* [Number of users](#choosing-the-number-of-users) + +### Choosing a GitLab tier[](#choosing-a-gitlab-tier "Permalink") + +定价[基于层级](https://about.gitlab.com/pricing/) ,使您可以选择适合预算的功能. 请参阅[GitLab.com 功能比较](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/)和[自我管理功能比较,](https://about.gitlab.com/pricing/self-managed/feature-comparison/)以获取有关每种产品在每个层上可用的[功能](https://about.gitlab.com/pricing/self-managed/feature-comparison/)的信息. + +### Choosing between GitLab.com or self-managed[](#choosing-between-gitlabcom-or-self-managed "Permalink") + +订阅的应用方式有所不同,具体取决于您使用的是 GitLab.com 还是自我管理的实例. + +* [GitLab.com:GitLab](#gitlabcom)的软件即服务产品. 您无需安装任何程序即可使用 GitLab.com,只需[注册](https://gitlab.com/users/sign_up)并立即开始使用 GitLab. +* [GitLab 自我管理](#self-managed) :安装,管理和维护自己的 GitLab 实例. + +在自我管理的实例上,GitLab 订阅为所有用户提供了相同的功能集. 在 GitLab.com 上,您可以将订阅应用于组或个人名称空间. + +**注意:**订阅不能在 GitLab.com 和 GitLab 自我管理之间转移. 必须购买新订阅并根据需要应用. + +### Choosing a GitLab.com group or personal subscription[](#choosing-a-gitlabcom-group-or-personal-subscription "Permalink") + +在 GitLab.com 上,您可以将订阅应用于组或个人名称空间. + +适用于: + +* GitLab.com 上的**组** ,组,所有子组以及所选组下的所有项目将具有关联层的功能. GitLab 建议在管理组织的项目和用户时选择一个小组计划. +* 作为**个人用户空间** ,所有项目都将具有应用了订阅的功能,但是由于它不是一个组,因此将无法使用组功能. + +### Choosing the number of users[](#choosing-the-number-of-users "Permalink") + +订阅中的计数对象之间有一些不同,具体取决于您使用的是 GitLab.com 还是自我管理的实例. + +#### GitLab.com[](#gitlabcom "Permalink") + +GitLab.com 订阅使用并发( *座位* )模型. 您需要根据一次启用的最大用户数来支付订阅费用. 您可以在订阅期间添加和删除用户,只要在任何给定时间的总用户数都在订阅数之内即可. + +预订中将计算每个已占用的席位,无论是按人员,职位还是漫游器,但以下情况除外: + +* 具有金牌订阅的访客权限的成员. + +**提示:**为了支持开源社区并鼓励开发开源项目,GitLab 授予所有 GitLab.com **公共**项目访问**金牌**功能的权限,无论其订阅如何. + +#### Self-managed[](#self-managed "Permalink") + +自我管理的订阅使用混合模型. 您需要根据订阅期内启用的最大用户数来支付订阅费用. 对于非脱机或封闭网络上的实例,每季度使用[Seat Link](#seat-link)检查一次自我管理安装中的最大同时用户数. + +预订中将计算每个已占用的席位,无论是按人员,工作还是漫游方式,但以下情况除外: + +* 在订阅续订之前受到限制的[停用](../user/admin_area/activating_deactivating_users.html#deactivating-a-user)和[阻止的](../user/admin_area/blocking_unblocking_users.html)用户不会被视为续订订阅的活动用户. 在最初添加他们的订阅期内,他们可以算作活动用户. +* 具有 Ultimate 订阅的 Guest 权限的成员. +* GitLab 创建的服务帐户: `Ghost User`和`Support Bot` . + +##### Users statistics[](#users-statistics "Permalink") + +要查看实例中用户的细分,包括活动,计费和已阻止,请转至**管理区域>概述>仪表板,**然后在" **用户"**部分中选择" **用户统计信息** ". 有关更多详细信息,请参阅[用户统计信息](../user/admin_area/index.html#users-statistics) . + +**注意:**如果启用了 LDAP 集成,则配置域中的任何人都可以注册一个 GitLab 帐户. 续订时可能会导致意外的账单. 考虑[禁用新注册](../user/admin_area/settings/sign_up_restrictions.html)并改为手动管理新用户. + +## Obtain a GitLab subscription[](#obtain-a-gitlab-subscription "Permalink") + +### Subscribe to GitLab.com[](#subscribe-to-gitlabcom "Permalink") + +订阅 GitLab.com: + +1. 使用我们的[注册页面](https://gitlab.com/users/sign_in#register-pane)为您自己创建一个用户帐户. +2. 创建一个[组](../user/group/index.html) . GitLab 组帮助将相关项目组合在一起,使您可以一次授予成员访问多个项目的权限. 如果您计划在个人名称空间中包含项目,则不需要组. +3. 创建其他用户并将其[添加到组中](../user/group/index.html#add-users-to-a-group) . +4. 通过[客户门户](https://customers.gitlab.com/)选择**青铜** , **银**或**金** GitLab.com 计划. +5. 将您的 GitLab.com 帐户与客户门户帐户关联. 选择计划后,如果尚未链接您的帐户,系统将提示您使用" **登录到 GitLab.com"**按钮来链接您的帐户. +6. 从下拉列表中选择名称空间以关联预订. +7. 进行结算. + +**提示:**您也可以转到" [**我的帐户"**](https://customers.gitlab.com/customers/edit)页面来添加或更改 GitLab.com 帐户链接. + +### Subscribe through GitLab self-managed[](#subscribe-through-gitlab-self-managed "Permalink") + +要通过自我管理安装订阅 GitLab: + +1. 转到[客户门户](https://customers.gitlab.com/)并购买**Starter** , **Premium**或**Ultimate**自我管理计划. +2. 购买后,许可证文件将发送到与客户门户帐户关联的电子邮件地址,该电子邮件地址必须[上传到您的 GitLab 实例](../user/admin_area/license.html#uploading-your-license) . + +**提示:**如果您要购买现有**Core**自管实例的订阅,请确保购买的席位足以[覆盖您的用户](../user/admin_area/index.html#administering-users) . + +## Manage your GitLab account[](#manage-your-gitlab-account "Permalink") + +使用[客户门户,](https://customers.gitlab.com/)您可以: + +* [Change billing and company information](#change-billing-information) +* [Change the payment method](#change-payment-method) +* [Change the linked account](#change-the-linked-account) +* [Change the associated namespace](#change-the-associated-namespace) +* [Change customers portal account password](#change-customer-portal-account-password) + +### Change billing information[](#change-billing-information "Permalink") + +要更改帐单信息: + +1. 登录到[客户门户](https://customers.gitlab.com/customers/sign_in) . +2. 选择**我的帐户**下拉菜单,然后点击**付款方式** . +3. 对" **帐户详细**信息"进行必要的更改. +4. Click **保存更改**. + +**注意:**将来的购买将使用此部分中的信息. 本节中列出的电子邮件用于客户门户登录以及与许可证相关的电子邮件通信. + +### Change payment method[](#change-payment-method "Permalink") + +要更改付款方式或更新信用卡信息: + +1. 登录到[客户门户](https://customers.gitlab.com/customers/sign_in) . +2. 选择**我的帐户**下拉菜单,然后点击**付款方式** . +3. **编辑**现有的付款方式信息或**添加新的付款方式** . +4. 保存更改. + +### Change the linked account[](#change-the-linked-account "Permalink") + +要更改与您的客户门户帐户关联的 GitLab.com 帐户: + +1. 登录到[客户门户](https://customers.gitlab.com/customers/sign_in) . +2. 在单独的浏览器选项卡中,转到[GitLab.com,](https://gitlab.com)并确保您尚未登录. +3. 在"客户门户"页面上,单击**我的帐户>帐户详细信息** . +4. 在**您的 GitLab.com 帐户下** ,单击" **更改关联的帐户"** . +5. 登录到要链接到"客户门户"帐户的[GitLab.com](https://gitlab.com)帐户. + +### Change the associated namespace[](#change-the-associated-namespace "Permalink") + +使用关联的 GitLab.com 帐户: + +1. 登录到[客户门户](https://customers.gitlab.com/customers/sign_in) . +2. 导航到" **管理购买"**页面. +3. Click **更改链接的名称空间**. +4. 从" **此订阅用于"**下拉列表中选择所需的组. +5. Click **进行结算**. + +订阅费用是根据一个组中的用户总数(包括其子组和嵌套项目)来计算的. 如果用户总数超过了订阅中的席位数,则将向您收取额外的用户费用. + +### Change customer portal account password[](#change-customer-portal-account-password "Permalink") + +要更改此客户门户帐户的密码: + +1. 登录到[客户门户](https://customers.gitlab.com/customers/sign_in) . +2. 选择**我的帐户**下拉菜单,然后点击**帐户详细信息** . +3. 对**您的密码**部分进行必要的更改. +4. Click **保存更改**. + +## View your subscription[](#view-your-subscription "Permalink") + +### View your GitLab.com subscription[](#view-your-gitlabcom-subscription "Permalink") + +要查看您的 GitLab.com 订阅状态,请登录 GitLab.com 并转到相关名称空间的**Billing**部分: + +* 对于个人: + 1. 转到**用户头像>设置** . + 2. 点击**结算** . +* 对于团体: + 1. 在群组页面( *而不是*群组中的项目)中,转到**设置>结算** . + +下表描述了您的组订阅详细信息: + +| Field | Description | +| --- | --- | +| 订阅席 | 如果这是付费计划,则表示您已支付支持该组座位的数量. | +| 当前使用的座椅 | 当前正在使用的活动座位数. | +| 最多使用的座位 | 您使用过的最高座位数. 如果这超出了订阅的席位,则您可能欠其他用户额外的费用. | +| 欠座位 | 如果您使用的最大席位超出了订阅中的席位,您将为已添加的用户欠额外的费用. | +| 订阅开始日期 | 订阅开始的日期. 如果这是免费计划,则是您从组的付费计划过渡的日期. | +| 订阅结束日期 | 当前订阅的终止日期. 不适用于免费计划. | + +### View your self-managed subscription[](#view-your-self-managed-subscription "Permalink") + +要查看您的自我管理订阅的状态,请登录到自我管理实例,然后转到" **许可证"**页面. + +1. 去 **管理区** . +2. 从左侧菜单中选择**许可证** . + +## Renew your subscription[](#renew-your-subscription "Permalink") + +要续订您的订阅,请[通过查看您的帐户来准备续订](#prepare-for-renewal-by-reviewing-your-account) ,然后执行以下一项操作: + +* [Renew a GitLab.com subscription](#renew-or-change-a-gitlabcom-subscription). +* [Renew a self-managed subscription](#renew-a-self-managed-subscription). + +### Prepare for renewal by reviewing your account[](#prepare-for-renewal-by-reviewing-your-account "Permalink") + +[客户门户](https://customers.gitlab.com/customers/sign_in)是您续订和修改订阅的工具. 在进行续订之前,请登录并验证或更新: + +* **帐户详细信息**页面上的发票联系方式. +* 在" **付款方式"**页面上存档的信用卡. + +**提示:**如果您需要访问客户门户的帮助或需要更改管理您的订阅的联系人,请与我们的[支持团队](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293)联系. + +定期检查您的用户帐户很重要,因为: + +* GitLab 订阅基于用户数量. 如果为太多的用户续订,则您将支付比应支付的更多的费用,而如果您尝试为太少的用户续订订阅,则续订将失败. +* 过时的用户帐户可能会带来安全风险. 定期检查有助于降低这种风险. + +#### Users over License[](#users-over-license "Permalink") + +GitLab 订阅对特定数量的用户有效. 有关详细信息,请参阅[选择用户数](#choosing-the-number-of-users) . 如果活动用户数超过了订阅中包含的数量,即*超过许可证*的*用户*数,则必须在续订之前或续订时为超出的用户数付费. 这也称为*真正的升级*过程. + +##### Purchase additional seats for GitLab.com[](#purchase-additional-seats-for-gitlabcom "Permalink") + +没有自助服务选项可以购买额外的座位. 您必须从 GitLab 销售处索取报价. 为此,请通过我们的[支持表格](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293)联系 GitLab. + +每个座位收取的费用是通过以下方法之一计算的: + +* 如果在续订前付费,则每个座位的数量将按比例计算. 例如,如果在订阅期结束前 3 个月添加了用户,则应付款额的计算方式为:(3/12)x 年费. +* 如果在续签时支付,则每个席位的金额为标准年费. + +##### Purchase additional users for self-managed[](#purchase-additional-users-for-self-managed "Permalink") + +自我管理实例可以在订阅期间的任何时间将用户添加到订阅中. 订阅期内添加的其他用户的成本是从购买之日起到订阅期结束之间按比例分配的. + +要将用户添加到订阅中: + +1. 登录到[客户门户](https://customers.gitlab.com/) . +2. 导航到" **管理购买"**页面. +3. 选择相关订阅卡上的**添加更多席位** . +4. 输入其他用户数. +5. Select **进行结算**. +6. 查看**订阅升级详细信息** . 系统会列出系统上所有用户的总价,以及您已支付的款项的信用额. 您只需要支付零钱. +7. Select **确认升级**. + +以下内容将通过电子邮件发送给您: + +* 付款收据. 您也可以在客户门户的" [**查看发票"**](https://customers.gitlab.com/receipts)下访问此信息. +* A new license. [Upload this license](../user/admin_area/license.html#uploading-your-license) to your instance to use it. + +### Seat Link[](#seat-link "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208832) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.9. + +利用 Seat Link,我们可以使用季度对帐流程为自助客户提供按比例分配的费用,用于全年增加用户. + +Seat Link 每天将连接的自我管理实例中的所有用户计数发送到 GitLab. 该信息用于自动按比例分配对帐. 数据通过加密的 HTTPS 连接安全地发送. + +Seat Link **仅**向 GitLab 提供以下信息: + +* Date +* License key +* 历史最大用户数 +* 活动用户数 + +对于离线或封闭网络客户,将使用现有[的调整模型](#users-over-license) . 如果没有用户计数数据,则无法按比例收取费用. + +<details><summary title="Click here to view example content of a Seat Link POST request.">单击此处查看 Seat Link POST 请求的示例内容.</summary> + +``` + { + date: '2020-01-29', + license_key: 'ZXlKa1lYUmhJam9pWm5WNmVsTjVZekZ2YTJoV2NucDBh +RXRxTTA5amQxcG1VMVZqDQpXR3RwZEc5SGIyMVhibmxuZDJ0NWFrNXJTVzVH +UzFCT1hHNVRiVFIyT0ZaUFlVSm1OV1ZGV0VObE1uVk4NCk4xY3ZkM1F4Y2to +MFFuVklXSFJvUWpSM01VdE9SVE5rYkVjclZrdDJORkpOTlhka01qaE5aalpj +YmxSMg0KWVd3MFNFTldTRmRtV1ZGSGRDOUhPR05oUVZvNUsxVnRXRUZIZFU1 +U1VqUm5aVFZGZUdwTWIxbDFZV1EyDQphV1JTY1V4c1ZYSjNPVGhrYVZ4dVlu +TkpWMHRJZUU5dmF6ZEJRVVkxTlVWdFUwMTNSMGRHWm5SNlJFcFYNClQyVkJl +VXc0UzA0NWFFb3ZlSFJrZW0xbVRqUlZabkZ4U1hWcWNXRnZYRzVaTm5GSmVW +UnJVR1JQYTJKdA0KU0ZZclRHTmFPRTVhZEVKMUt6UjRkSE15WkRCT1UyNWlS +MGRJZDFCdmRFWk5Za2h4Tm5sT1VsSktlVlYyDQpXRmhjYmxSeU4wRnRNMU5q +THpCVWFGTmpTMnh3UWpOWVkyc3pkbXBST1dnelZHY3hUV3hxVDIwdlZYRlQN +Ck9EWTJSVWx4WlVOT01EQXhVRlZ3ZGs1Rk0xeHVSVEJTTDFkMWJUQTVhV1ZK +WjBORFdWUktaRXNyVnpsTw0KTldkWWQwWTNZa05VWlZBMmRUVk9kVUpxT1hV +Mk5VdDFTUzk0TUU5V05XbFJhWGh0WEc1cVkyWnhaeTlXDQpTMEpyZWt0cmVY +bzBOVGhFVG1oU1oxSm5WRFprY0Uwck0wZEdhVUpEV1d4a1RXZFRjVU5tYTB0 +a2RteEQNCmNWTlFSbFpuWlZWY2JpdFVVbXhIV0d4MFRuUnRWbkJKTkhwSFJt +TnRaMGsyV0U1MFFUUXJWMUJVTWtOSA0KTVhKUWVGTkxPVTkzV1VsMlVUUldk +R3hNTWswNU1USlNjRnh1U1UxTGJTdHRRM1l5YTFWaWJtSlBTMkUxDQplRkpL +SzJSckszaG1hVXB1ZVRWT1UwdHZXV0ZOVG1WamMyVjRPV0pSUlZkUU9UUnpU +VWh2Wlc5cFhHNUgNClNtRkdVMDUyY1RGMWNGTnhVbU5JUkZkeGVWcHVRMnBh +VTBSUGR6VnRNVGhvWTFBM00zVkZlVzFOU0djMA0KY1ZFM1FWSlplSFZ5UzFS +aGIxTmNia3BSUFQxY2JpSXNJbxRsZVNJNkltZFhiVzFGVkRZNWNFWndiV2Rt +DQpNWEIyY21SbFFrdFNZamxaYURCdVVHcHhiRlV3Tm1WQ2JGSlFaSFJ3Y0Rs +cFMybGhSMnRPTkZOMWNVNU0NClVGeHVTa3N6TUUxcldVOTVWREl6WVVWdk5U +ZGhWM1ZvVjJkSFRtZFBZVXRJTkVGcE55dE1NRE5dWnpWeQ0KWlV0aWJsVk9T +RmRzVVROUGRHVXdWR3hEWEc1MWjWaEtRMGQ2YTAxWFpUZHJURTVET0doV00w +ODRWM0V2DQphV2M1YWs5cWFFWk9aR3BYTm1aVmJXNUNaazlXVUVRMWRrMXpj +bTFDV0V4dldtRmNibFpTTWpWU05VeFMNClEwTjRNMWxWCUtSVGEzTTJaV2xE +V0hKTFRGQmpURXRsZFVaQlNtRnJTbkpPZGtKdlUyUmlNVWxNWWpKaQ0KT0dw +c05YbE1kVnh1YzFWbk5VZDFhbU56ZUM5Tk16TXZUakZOVW05cVpsVTNObEo0 +TjJ4eVlVUkdkWEJtDQpkSHByYWpreVJrcG9UVlo0Y0hKSU9URndiV2RzVFdO +VlhHNXRhVmszTkV0SVEzcEpNMWRyZEVoRU4ydHINCmRIRnFRVTlCVUVVM1pV +SlRORE4xUjFaYVJGb3JlWGM5UFZ4dUlpd2lhWFlpt2lKV00yRnNVbk5RTjJk +Sg0KU1hNMGExaE9SVGR2V2pKQlBUMWNiaUo5DQo=', + max_historical_user_count: 10, + active_users: 6 +} +```</details> + +您可以在管理面板中查看确切的 JSON 有效负载. 要查看有效负载: + +1. 导航到" **管理区域">"设置">"度量和分析",**然后展开" **Seat Link"** . +2. Click **预览有效载荷**. + +#### Disable Seat Link[](#disable-seat-link "Permalink") + +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212375) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.10. + +默认情况下,Seat Link 已启用. + +要禁用此功能,请转到 **在管理区域>设置>指标和配置文件中** ,取消选中" **启用座椅链接"**复选框>" **保存更改"** . + +要在 Omnibus GitLab 安装中禁用 Seat Link,并防止日后通过管理面板对其进行配置,请在[`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html)设置以下[`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html) : + +``` +gitlab_rails['seat_link_enabled'] = false +``` + +要在 GitLab 源代码安装中禁用 Seat Link,并防止日后通过管理面板对其进行配置,请在`gitlab.yml`进行以下设置: + +``` +production: &base + # ... + gitlab: + # ... + seat_link_enabled: false +``` + +### Renew or change a GitLab.com subscription[](#renew-or-change-a-gitlabcom-subscription "Permalink") + +要更新为更多的用户比你们 GitLab.com 系统目前正在积极,请联系我们通过销售团队`renewals@gitlab.com`寻求帮助,因为这不能在客户门户网站来完成. + +For details on upgrading your subscription tier, see [Upgrade your GitLab.com subscription tier](#upgrade-your-gitlabcom-subscription-tier). + +#### Automatic renewal[](#automatic-renewal "Permalink") + +要查看或更改自动订阅续订(与上一周期位于同一层),请登录到[客户门户](https://customers.gitlab.com/customers/sign_in) ,然后: + +* 如果您看到" **恢复订阅"**按钮,则您的订阅先前已被取消. 单击它可以恢复自动续订. +* 如果看到" **取消订阅"** ,则您的订阅将设置为在订阅期结束时自动续订. 单击它可以取消自动续订. + +启用自动续订后,订阅将在到期日期自动续订,并且可用服务之间不会有任何差距. 将会生成一张用于续订的发票,并且可以在" [查看发票"](https://customers.gitlab.com/receipts)页面中查看或下载. 如果您在续订过程中遇到困难,请联系我们的[支持团队](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293)以寻求帮助. + +### Renew a self-managed subscription[](#renew-a-self-managed-subscription "Permalink") + +从订阅到期前 30 天开始,GitLab 会在 GitLab 用户界面中用标语通知管理员到期日期. + +我们建议您在续订期间执行以下步骤: + +1. 通过[阻止](../user/admin_area/blocking_unblocking_users.html#blocking-a-user)任何不活跃或不需要的用户来修剪[它们](../user/admin_area/blocking_unblocking_users.html#blocking-a-user) . +2. 确定在即将到来的订阅中是否需要增加用户. +3. 登录到[客户门户,](https://customers.gitlab.com/customers/sign_in)然后选择现有订阅下的" **续订"**按钮. + + **提示:**如果您需要更改您的[GitLab 层](https://about.gitlab.com/pricing/) ,请通过`renewals@gitlab.com`与我们的销售团队联系以寻求帮助,因为这不能在客户门户中完成. +4. 在第一个框中,输入来年需要的用户许可总数. 确保此数目至少**等于或大于**执行更新时系统中的活动用户数. +5. 在第二个框中,输入上一个订购期限内发生的用户超额[使用的许可证超用户](#users-over-license)数. + + **提示:**您可以*通过以下方式*在实例的**管理**控制台中找到获得*许可*的*用户* **:** (顶部)中的( **管理区域** ),或转到`/admin` . + + 下表介绍了管理控制台和续订条款的详细信息: + + | Field | Description | + | --- | --- | + | 许可中的用户 | 您在系统上加载的当前许可证中已付费的用户数. 这不包括您在续订期间`Users over license`向`Users over license`支付的金额. | + | 活跃用户 | 系统上当前的活动用户数. | + | 最大用户 | 在已加载许可证有效期内,系统上活动用户数最多. 如果此数字在任何时候都超出了许可数量的用户,则会使用户蒙受许可数量的困扰. | + | 超过许可的用户 | 在当前许可期限内,超出`Users in License`用户数量的用户数量. 此数量的用户将在下次续订时付费. | + +6. 查看您的续订详细信息并完成付款过程. +7. 可以在相关订阅卡上的" [管理购买"](https://customers.gitlab.com/subscriptions)页面上下载续订期限的许可证. 选择**将许可证复制到剪贴板**或选择**下载许可证**以获取副本. +8. 将新许可证[上载到](../user/admin_area/license.html#uploading-your-license)您的实例. + +将会生成一张用于续订的发票,并且可以在" [查看发票"](https://customers.gitlab.com/receipts)页面上查看或下载. 如果您在续订过程中遇到困难,请联系我们的[支持团队](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293)以寻求帮助. + +## Upgrade your subscription tier[](#upgrade-your-subscription-tier "Permalink") + +升级过程因您是 GitLab.com 还是自我管理的客户而异. + +### Upgrade your GitLab.com subscription tier[](#upgrade-your-gitlabcom-subscription-tier "Permalink") + +要升级您的[GitLab 层](https://about.gitlab.com/pricing/) : + +1. 登录到[客户门户](https://customers.gitlab.com/customers/sign_in) . +2. 在" [管理购买"](https://customers.gitlab.com/subscriptions)页面上,选择相关订阅卡上的" **升级"**按钮. +3. 选择所需的升级. +4. 确认有效的付款方式,或添加新的付款方式. +5. 选中**我接受隐私政策和服务条款**复选框. +6. Select **确认购买**. + +处理完购买后,您将收到新订阅等级的确认. + +### Upgrade your self-managed subscription tier[](#upgrade-your-self-managed-subscription-tier "Permalink") + +要升级您的[GitLab 层](https://about.gitlab.com/pricing/) ,请联系我们的销售团队,因为这不能在客户门户中完成. 您可以发送电子邮件至`renewals@gitlab.com`或填写" [**联系销售"**](https://about.gitlab.com/sales/)表单. 在消息中包括要升级的订阅的详细信息以及所需的层. + +After messaging the sales team, the workflow is as follows: + +1. 收到销售团队的答复,要求确认升级. +2. 回复销售团队,确认升级细节. +3. 收到销售团队的报价. +4. 签名并返回报价. +5. 收到新许可证. +6. 上载新许可证. 有关详细信息,请参阅上[载许可证](../user/admin_area/license.html#uploading-your-license) . + +上载许可证文件后,新的订阅层将处于活动状态. + +## Subscription expiry[](#subscription-expiry "Permalink") + +当您的订阅或试用版到期时,GitLab 不会删除您的数据,但是根据到期时的层级,它可能变得不可访问. 如果您没有准备好到期,则某些功能可能无法达到预期的效果. 例如, [未传递特定](https://gitlab.com/gitlab-org/gitlab/-/issues/24759)于[环境的变量](https://gitlab.com/gitlab-org/gitlab/-/issues/24759) . + +如果您续订或升级,您的数据将再次可访问. + +### Self-managed GitLab data[](#self-managed-gitlab-data "Permalink") + +对于自我管理的客户,有 14 天的宽限期,您的功能将继续按原样运行,此后整个实例将变为只读状态. + +但是,如果删除许可证,您将立即恢复为核心功能,并且实例将再次被读取/写入. + +## CI pipeline minutes[](#ci-pipeline-minutes "Permalink") + +CI 管道分钟数是您在 GitLab 共享运行程序上的[管道](../ci/pipelines/index.html)的执行时间. 每个[GitLab.com 层均](https://about.gitlab.com/pricing/)包含 CI 管道分钟的每月配额: + +* 免费:2,000 分钟 +* 青铜:2,000 分钟 +* Silver: 10,000 minutes +* 金牌:50,000 分钟 + +配额适用于: + +* 组,其中在组的所有成员,其子组和嵌套项目之间共享分钟. 要查看该组的使用情况,请导航至该组,然后 **设置** > **使用配额** . +* 您的个人帐户,其中可用于您的个人项目的纪要. 要查看和购买个人会议记录,请点击您的头像,然后 **设置** > **[使用配额](https://gitlab.com/profile/usage_quotas#pipelines-quota-tab)** . + +只有 GitLab 共享运行程序的管道时间受到限制. 如果您为项目设置了特定的运行器,则在 GitLab.com 上的构建时间没有限制. + +可用配额在每个日历月的第一个 UTC 午夜重置. + +CI 分钟数用完后,会自动发送一封电子邮件以通知名称空间的所有者. 您可以[购买其他 CI 分钟](#purchasing-additional-ci-minutes) ,或者将帐户升级为[Silver 或 Gold](https://about.gitlab.com/pricing/) . 即使您达到极限,仍然可以使用您自己的跑步者. + +### Purchasing additional CI minutes[](#purchasing-additional-ci-minutes "Permalink") + +如果您使用的是 GitLab.com,则可以购买额外的 CI 分钟,这样在使用完您的主要配额中的所有 CI 分钟后,管道不会被阻塞. 您可以在[GitLab 客户门户中](https://customers.gitlab.com/plans)找到其他 CI / CD 分钟的价格. 其他分钟: + +* 仅在订阅中包含的共享配额用完后才使用. +* 逐月滚动. + +要在 GitLab.com 上为您的小组购买更多时间: + +1. 在您的小组中,转到 **设置>使用配额** . +2. 选择**购买其他分钟** ,您将被带到客户门户. +3. 在 GitLab.com 上找到与您的小组链接的订阅卡,单击" **购买更多 CI 分钟"** ,然后完成有关交易的详细信息. +4. 处理完您的付款后,多余的 CI 分钟将同步到您的组名称空间. +5. 要确认可用的 CI 分钟,请转到您的小组,然后 **设置>使用配额** . + + The **额外的分钟** displayed now includes the purchased additional CI minutes, plus any minutes rolled over from last month. + +要为您的个人命名空间购买更多分钟,请执行以下操作: + +1. 单击您的头像,然后转到**设置>使用配额** . +2. 选择**购买其他分钟** ,您将被带到客户门户. +3. 在 GitLab.com 上找到链接到您的个人命名空间的订阅卡,单击" **购买更多 CI 分钟"** ,然后完成有关交易的详细信息. 我们处理完您的付款后,多余的 CI 分钟将同步到您的个人名称空间. +4. 要确认您的个人项目可用的 CI 分钟,请单击您的头像,然后转到**设置>使用配额** . + + 现在显示的" **其他分钟"**包括已购买的其他配置项分钟,以及上个月结转的所有分钟. + +意识到: + +* 如果您在购买付费计划之前购买了额外的 CI 分钟数,我们将为您的付费计划按比例计算费用. 这意味着您可能需要不到一年的费用,因为您之前是使用额外的 CI 分钟创建订阅的. +* 一旦将额外的 CI 分钟分配给一个组,就无法将其转移到另一个组. +* 如果您使用的分钟数超出了默认配额,则这些分钟数将在您购买额外的分钟数后立即从"其他分钟数"配额中扣除. + +## Contact Support[](#contact-support "Permalink") + +我们还鼓励所有用户在项目跟踪器中搜索[GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/)项目中的已知问题和现有功能要求. + +这些问题是获取特定产品计划的更新以及直接与相关 GitLab 团队成员进行沟通的最佳途径. + +学习更多关于: + +* [GitLab 支持](https://about.gitlab.com/support/)的层次. +* [Submit a request via the Support Portal](https://support.gitlab.com/hc/en-us/requests/new). + +## GitLab for Education subscriptions[](#gitlab-for-education-subscriptions "Permalink") + +要续订[GitLab for Education](https://about.gitlab.com/solutions/education/)订阅,请发送电子邮件至`education@gitlab.com`其中包含以下信息: + +1. 续订的座位数. 您可以根据需要添加座位. +2. 许可证的用例. 具体来说,我们需要验证其使用是否符合《 [最终用户许可协议》](https://about.gitlab.com/terms/#edu-oss)的条件. 请注意,大学的基础设施运营和信息技术运营不在教育计划的规定范围之内. 有关详细信息,请参见" [教育常见问题解答"](https://about.gitlab.com/solutions/education/#FAQ) . +3. 要签署续订报价的主要联系人的全名,电子邮件地址和电话号码. 只有代表大学的具有适当签署权的教职员工签署才能被接受. + +收到上述信息后,我们将处理请求并返回续签以供签名. 请至少等待 2 个工作日才能退货. 如有任何问题,请发送电子邮件至`education@gitlab.com` . + +## GitLab for Open Source subscriptions[](#gitlab-for-open-source-subscriptions "Permalink") + +所有的[GitLab for Open Source](https://about.gitlab.com/solutions/open-source/program/)请求(包括订阅续订)都必须通过应用程序进行. 如有任何疑问,请发送电子邮件至`opensource@gitlab.com`寻求帮助. \ No newline at end of file diff --git a/docs/652.md b/docs/652.md new file mode 100644 index 0000000000000000000000000000000000000000..f8ffc762fbdb32f0cdb0908fbb58326cb1648dcc --- /dev/null +++ b/docs/652.md @@ -0,0 +1,94 @@ +# Activate GitLab EE with a license + +> 原文:[https://docs.gitlab.com/ee/user/admin_area/license.html](https://docs.gitlab.com/ee/user/admin_area/license.html) + +* [Uploading your license](#uploading-your-license) +* [Add your license at install time](#add-your-license-at-install-time) +* [Notification before the license expires](#notification-before-the-license-expires) +* [What happens when your license expires](#what-happens-when-your-license-expires) +* [License history](#license-history) +* [Troubleshooting](#troubleshooting) + * [There is no License tab in the Admin Area](#there-is-no-license-tab-in-the-admin-area) + * [Users exceed license limit upon renewal](#users-exceed-license-limit-upon-renewal) + +# Activate GitLab EE with a license[](#activate-gitlab-ee-with-a-license-starter-only "Permalink") + +要激活所有 GitLab 企业版(EE)功能,您需要上传许可证. 从 GitLab Inc.获得许可证后,您可以通过**以管理员身份登录到 GitLab 实例**或在安装时添加许可证来上载许可证. + +许可证的形式为 base64 编码的 ASCII 文本,扩展名为`.gitlab-license` ,可以在[购买](https://about.gitlab.com/pricing/) `.gitlab-license`或注册[免费试用时获得](https://about.gitlab.com/free-trial/) . + +**注意:**从 GitLab Enterprise Edition 9.4.0 开始,没有上载许可证的新安装实例将仅具有核心功能. 试用许可证将激活所有 Ultimate 功能,但是[试用期满后](#what-happens-when-your-license-expires) ,某些功能将被锁定. + +## Uploading your license[](#uploading-your-license "Permalink") + +首次访问以 admin 身份登录的 GitLab EE 安装时,您会看到一条注释,敦促您上传许可证,并带有一个链接,该链接可直接转到**Admin Area> License** . + +否则,您可以: + +1. 通过单击菜单栏中的扳手图标,手动导航到**管理区域** . + + [![Admin Area icon](img/53056397d59c4378696296d359f20adc.png)](img/admin_wrench.png) + +2. 然后转到" **许可证"**选项卡,然后单击"上**载新许可证"** . + + [![License Admin Area](img/b132b9b00d4641da41d2cb7dca5ea55c.png)](img/license_admin_area.png) + +3. 如果您收到`.gitlab-license`文件,则应该已经将其下载到本地计算机中. 然后,您可以通过选择许可证文件并单击"上**载许可证"**按钮直接上载它. 在下图中,您可以看到所选的许可证文件名为`GitLab.gitlab-license` . + + [![Upload license](img/5016b6014148674f85d6fdba7bc5bb5e.png)](img/license_upload.png) + + 如果您以纯文本格式收到许可证,则需要选择"输入许可证密钥"选项,复制许可证,将其粘贴到"许可证密钥"字段中,然后点击**上传许可证** . + +## Add your license at install time[](#add-your-license-at-install-time "Permalink") + +通过将名为`Gitlab.gitlab-license`的文件放置在`/etc/gitlab/`对于 Omnibus)或`config/`对于源代码安装,可以在安装时自动导入`Gitlab.gitlab-license` . + +还可以为许可证指定自定义位置和文件名. + +源代码安装应使用有效的 GitLab Enterprise Edition 许可证的路径设置`GITLAB_LICENSE_FILE`环境变量. + +``` +export GITLAB_LICENSE_FILE="/path/to/license/file" +``` + +Omnibus 安装应将此条目添加到`gitlab.rb` : + +``` +gitlab_rails['initial_license_file'] = "/path/to/license/file" +``` + +**警告:**这些方法只会在安装时添加许可证. 使用 Web 用户界面中的"管理区域"来续订或升级许可证. + +* * * + +许可证上载后,所有 GitLab 企业版功能都将处于激活状态,直到许可证期结束. 该时间段结束后,该实例将[恢复](#what-happens-when-your-license-expires)为仅 Core 功能. + +您可以随时在"管理区域"的"许可证"部分中查看许可证详细信息. + +[![License details](img/181ef05617eae83f93df5db5884cb3f2.png)](img/license_details.png) + +## Notification before the license expires[](#notification-before-the-license-expires "Permalink") + +许可证到期前一个月,GitLab 管理员将开始看到一条消息,通知到期时间. 确保您更新了许可证,否则,如果许可证过期,您将错过所有付费功能. + +## What happens when your license expires[](#what-happens-when-your-license-expires "Permalink") + +万一您的许可证过期,GitLab 将锁定某些功能,如 Git 推送,问题创建等,并且将向所有管理员显示一条消息,告知已过期的许可证. + +为了恢复所有以前的功能,必须上载新的许可证. 要退回到仅激活核心功能,您需要删除过期的许可证. + +## License history[](#license-history "Permalink") + +可以上传和查看多个许可证,但是只有最新的许可证将用作活动许可证. + +## Troubleshooting[](#troubleshooting "Permalink") + +### There is no License tab in the Admin Area[](#there-is-no-license-tab-in-the-admin-area "Permalink") + +如果您最初安装的是 Community Edition,而不是 Enterprise Edition,则需要在[升级](../../update/README.html#community-to-enterprise-edition)许可证之前[升级到 Enterprise Edition](../../update/README.html#community-to-enterprise-edition) . + +GitLab.com 用户无法上传和使用自我管理的许可证. 如果您希望在 GitLab.com 上使用付费功能,则可以[购买](../../subscriptions/index.html#subscribe-to-gitlabcom)单独的订阅. + +### Users exceed license limit upon renewal[](#users-exceed-license-limit-upon-renewal "Permalink") + +如果您在续订之前将新用户添加到您的 GitLab 实例中,则可能需要购买额外的席位来覆盖这些用户. 如果是这种情况,并且上传了没有足够用户的许可证,则会显示一条消息,提示您购买其他用户. 有关如何确定所需用户数以及如何增加其他席位的更多信息,请参见[许可常见问题解答](https://about.gitlab.com/pricing/licensing-faq/) . \ No newline at end of file diff --git a/docs/img/000b14e609fee563642c55e238caca88.png b/docs/img/000b14e609fee563642c55e238caca88.png new file mode 100644 index 0000000000000000000000000000000000000000..eb0619b840ef4c96a97694d61aab9a24a6c66b94 Binary files /dev/null and b/docs/img/000b14e609fee563642c55e238caca88.png differ diff --git a/docs/img/0050abd936ad2e13e4ad057a58611cc9.png b/docs/img/0050abd936ad2e13e4ad057a58611cc9.png new file mode 100644 index 0000000000000000000000000000000000000000..8aa3192eb970101327c88261485c7e0ab500cfa4 Binary files /dev/null and b/docs/img/0050abd936ad2e13e4ad057a58611cc9.png differ diff --git a/docs/img/00cb101eb824b3ede4fa4a3914f95c09.png b/docs/img/00cb101eb824b3ede4fa4a3914f95c09.png new file mode 100644 index 0000000000000000000000000000000000000000..3b615b594ea3c5989cdc8c2549307c7ff0b2f0c4 Binary files /dev/null and b/docs/img/00cb101eb824b3ede4fa4a3914f95c09.png differ diff --git a/docs/img/00fd9bca0c7bdc64f74a24b691e0adac.png b/docs/img/00fd9bca0c7bdc64f74a24b691e0adac.png new file mode 100644 index 0000000000000000000000000000000000000000..671fd2253d279d0066dd200e796d978e12d48404 Binary files /dev/null and b/docs/img/00fd9bca0c7bdc64f74a24b691e0adac.png differ diff --git a/docs/img/0124687ca256ab68d34dd0918f1e1a8d.png b/docs/img/0124687ca256ab68d34dd0918f1e1a8d.png new file mode 100644 index 0000000000000000000000000000000000000000..a2b9e2e90e75255644735b39b53d64e9b9832b78 Binary files /dev/null and b/docs/img/0124687ca256ab68d34dd0918f1e1a8d.png differ diff --git a/docs/img/01df5698e4465e052dcb7bf0ed6a55ae.png b/docs/img/01df5698e4465e052dcb7bf0ed6a55ae.png new file mode 100644 index 0000000000000000000000000000000000000000..4c0b8147f57afc20a71af50a744be26a5cb2a3f1 Binary files /dev/null and b/docs/img/01df5698e4465e052dcb7bf0ed6a55ae.png differ diff --git a/docs/img/0290c1013dba1b07f226f1548c8b6fd2.png b/docs/img/0290c1013dba1b07f226f1548c8b6fd2.png new file mode 100644 index 0000000000000000000000000000000000000000..cf225c91f8dadecabf811f0a08899d8538f7a2fb Binary files /dev/null and b/docs/img/0290c1013dba1b07f226f1548c8b6fd2.png differ diff --git a/docs/img/02f288cad0ff70d293c035d6dc434f34.png b/docs/img/02f288cad0ff70d293c035d6dc434f34.png new file mode 100644 index 0000000000000000000000000000000000000000..1ff3bd975bbebd5cabbd076a3734244e6e1b34dc Binary files /dev/null and b/docs/img/02f288cad0ff70d293c035d6dc434f34.png differ diff --git a/docs/img/033c41dc1122d52872dcb67228037524.png b/docs/img/033c41dc1122d52872dcb67228037524.png new file mode 100644 index 0000000000000000000000000000000000000000..f9ea1c7fd1d0d29bd493a4ef0dd1ef5e036834d0 Binary files /dev/null and b/docs/img/033c41dc1122d52872dcb67228037524.png differ diff --git a/docs/img/0370f6d6a289b9e8237fcad4c7672e78.png b/docs/img/0370f6d6a289b9e8237fcad4c7672e78.png new file mode 100644 index 0000000000000000000000000000000000000000..eb6ec77e1f8ec80a6939577ebd7d29b7826c46ef Binary files /dev/null and b/docs/img/0370f6d6a289b9e8237fcad4c7672e78.png differ diff --git a/docs/img/0387751ed4b8717777ebac2706c2d637.png b/docs/img/0387751ed4b8717777ebac2706c2d637.png new file mode 100644 index 0000000000000000000000000000000000000000..387b5ccd7cb45a388c9c6007fe72d3e2cbc62b9b Binary files /dev/null and b/docs/img/0387751ed4b8717777ebac2706c2d637.png differ diff --git a/docs/img/03d3f984ea7608322b1fd6a7feba47c0.png b/docs/img/03d3f984ea7608322b1fd6a7feba47c0.png new file mode 100644 index 0000000000000000000000000000000000000000..d8e269f86f9fe046ac92b0b8fa19344cd6657a14 Binary files /dev/null and b/docs/img/03d3f984ea7608322b1fd6a7feba47c0.png differ diff --git a/docs/img/04b61606f38fddf21d194ee3e13abaa3.png b/docs/img/04b61606f38fddf21d194ee3e13abaa3.png new file mode 100644 index 0000000000000000000000000000000000000000..40d57044d43a2d03d10436bd382f7d3c60458011 Binary files /dev/null and b/docs/img/04b61606f38fddf21d194ee3e13abaa3.png differ diff --git a/docs/img/0574a3e535157d8b9c5744214f19f7c7.png b/docs/img/0574a3e535157d8b9c5744214f19f7c7.png new file mode 100644 index 0000000000000000000000000000000000000000..3076cd6edff029ff05a588c6307fcf7dccf32ef6 Binary files /dev/null and b/docs/img/0574a3e535157d8b9c5744214f19f7c7.png differ diff --git a/docs/img/05a0790512923394006a9c3face18d58.png b/docs/img/05a0790512923394006a9c3face18d58.png new file mode 100644 index 0000000000000000000000000000000000000000..6f78ff359e0b87c9e40227a27802d5297b130f17 Binary files /dev/null and b/docs/img/05a0790512923394006a9c3face18d58.png differ diff --git a/docs/img/05dd8439c1da77198297616b4c4f8458.png b/docs/img/05dd8439c1da77198297616b4c4f8458.png new file mode 100644 index 0000000000000000000000000000000000000000..5f482eecab97853a4776bef0e22dc1e83bc15109 Binary files /dev/null and b/docs/img/05dd8439c1da77198297616b4c4f8458.png differ diff --git a/docs/img/061d5d0d60fdf019ad696860942563af.png b/docs/img/061d5d0d60fdf019ad696860942563af.png new file mode 100644 index 0000000000000000000000000000000000000000..57004dd4f549a1f9c9cc0eabf182fc2d6f9b680b Binary files /dev/null and b/docs/img/061d5d0d60fdf019ad696860942563af.png differ diff --git a/docs/img/0748208b938145b0cf688cc0a3cb7b09.png b/docs/img/0748208b938145b0cf688cc0a3cb7b09.png new file mode 100644 index 0000000000000000000000000000000000000000..951f7374352baa81221ae6948bb3113c5b35deb8 Binary files /dev/null and b/docs/img/0748208b938145b0cf688cc0a3cb7b09.png differ diff --git a/docs/img/074834195e0c24213cffeef5ef08a9e1.png b/docs/img/074834195e0c24213cffeef5ef08a9e1.png new file mode 100644 index 0000000000000000000000000000000000000000..bdea937f04cc498136bc286848955e9187262bc1 Binary files /dev/null and b/docs/img/074834195e0c24213cffeef5ef08a9e1.png differ diff --git a/docs/img/079efbfe641967c936be8ed9b033bca6.png b/docs/img/079efbfe641967c936be8ed9b033bca6.png new file mode 100644 index 0000000000000000000000000000000000000000..14355dca0e7cf644f0ae8856b02b5ce380406030 Binary files /dev/null and b/docs/img/079efbfe641967c936be8ed9b033bca6.png differ diff --git a/docs/img/07c2c84efb64460dfa2373f1f75645ab.png b/docs/img/07c2c84efb64460dfa2373f1f75645ab.png new file mode 100644 index 0000000000000000000000000000000000000000..4669fb5e6d55b8e73ae251ade310fd97b38680ac Binary files /dev/null and b/docs/img/07c2c84efb64460dfa2373f1f75645ab.png differ diff --git a/docs/img/07e4663db45be7313a205a17ec342edb.png b/docs/img/07e4663db45be7313a205a17ec342edb.png new file mode 100644 index 0000000000000000000000000000000000000000..7eacb23acc712246070a63ebe84855b3dc50518d Binary files /dev/null and b/docs/img/07e4663db45be7313a205a17ec342edb.png differ diff --git a/docs/img/083580c1827d40263d500a21f072249f.png b/docs/img/083580c1827d40263d500a21f072249f.png new file mode 100644 index 0000000000000000000000000000000000000000..7b3732beafa2e2ccc2b37268ed85347281522b12 Binary files /dev/null and b/docs/img/083580c1827d40263d500a21f072249f.png differ diff --git a/docs/img/097706015c4d2abaaf34d0782cfac635.png b/docs/img/097706015c4d2abaaf34d0782cfac635.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba581a1e2e99449a88cb74ff0932f7960b50f71 Binary files /dev/null and b/docs/img/097706015c4d2abaaf34d0782cfac635.png differ diff --git a/docs/img/09870a42c6e3e94e7553f338a65c0b6d.png b/docs/img/09870a42c6e3e94e7553f338a65c0b6d.png new file mode 100644 index 0000000000000000000000000000000000000000..c07d64ddf91c0b2a4974b7eebc6c81094da588e9 Binary files /dev/null and b/docs/img/09870a42c6e3e94e7553f338a65c0b6d.png differ diff --git a/docs/img/098a5864447e44da06b72051af59b294.png b/docs/img/098a5864447e44da06b72051af59b294.png new file mode 100644 index 0000000000000000000000000000000000000000..54b8c2fbf34179cf4833f51420025d9eaad9db3e Binary files /dev/null and b/docs/img/098a5864447e44da06b72051af59b294.png differ diff --git a/docs/img/0991c603daeaefcd2df14e098fa66ea4.png b/docs/img/0991c603daeaefcd2df14e098fa66ea4.png new file mode 100644 index 0000000000000000000000000000000000000000..d63ddfb2a4f382e6b171102fb15ac08d057119fb Binary files /dev/null and b/docs/img/0991c603daeaefcd2df14e098fa66ea4.png differ diff --git a/docs/img/09a583a4343d2359d87040afc14139dd.png b/docs/img/09a583a4343d2359d87040afc14139dd.png new file mode 100644 index 0000000000000000000000000000000000000000..315f78237a13916fa31b655b49513bb1652928cd Binary files /dev/null and b/docs/img/09a583a4343d2359d87040afc14139dd.png differ diff --git a/docs/img/09b8263a3534de004ff180005a876b4a.png b/docs/img/09b8263a3534de004ff180005a876b4a.png new file mode 100644 index 0000000000000000000000000000000000000000..fe128cda6f868901ead87a8a4c6378c4ed02ea06 Binary files /dev/null and b/docs/img/09b8263a3534de004ff180005a876b4a.png differ diff --git a/docs/img/09e1824644c088dfbd0f2f9710fc7d77.png b/docs/img/09e1824644c088dfbd0f2f9710fc7d77.png new file mode 100644 index 0000000000000000000000000000000000000000..dab477be4618b18f64f7cd791ec8b267a1bf96cc Binary files /dev/null and b/docs/img/09e1824644c088dfbd0f2f9710fc7d77.png differ diff --git a/docs/img/0a61445809db70ca6bf85d986bf52223.png b/docs/img/0a61445809db70ca6bf85d986bf52223.png new file mode 100644 index 0000000000000000000000000000000000000000..9c9b3825ab9504a24f45f455efc109d3b7040c82 Binary files /dev/null and b/docs/img/0a61445809db70ca6bf85d986bf52223.png differ diff --git a/docs/img/0a64287e1feef55413a5a906d02ec8ea.png b/docs/img/0a64287e1feef55413a5a906d02ec8ea.png new file mode 100644 index 0000000000000000000000000000000000000000..da392c83a18d9ba87bc57bd594f8eed28d043fe8 Binary files /dev/null and b/docs/img/0a64287e1feef55413a5a906d02ec8ea.png differ diff --git a/docs/img/0a8b584e09781bad1c374f8badc0a12c.png b/docs/img/0a8b584e09781bad1c374f8badc0a12c.png new file mode 100644 index 0000000000000000000000000000000000000000..0d1e5c1379a16ee4d352551d25231bd565b8474b Binary files /dev/null and b/docs/img/0a8b584e09781bad1c374f8badc0a12c.png differ diff --git a/docs/img/0a8c15f1fa2c2e0a210d9baae9fff372.png b/docs/img/0a8c15f1fa2c2e0a210d9baae9fff372.png new file mode 100644 index 0000000000000000000000000000000000000000..7defe270352f2e05eac7f1ae56844d1716ce96f5 Binary files /dev/null and b/docs/img/0a8c15f1fa2c2e0a210d9baae9fff372.png differ diff --git a/docs/img/0b5158f524983df0ee4e4aa152abcc86.png b/docs/img/0b5158f524983df0ee4e4aa152abcc86.png new file mode 100644 index 0000000000000000000000000000000000000000..f69d7eef345c58ef9c0b5adf861080804e8b80b4 Binary files /dev/null and b/docs/img/0b5158f524983df0ee4e4aa152abcc86.png differ diff --git a/docs/img/0b804819bf30ce8e657ad538d376ecc5.png b/docs/img/0b804819bf30ce8e657ad538d376ecc5.png new file mode 100644 index 0000000000000000000000000000000000000000..0f622411d6edba03c140ad4f44b5e77bc191882b Binary files /dev/null and b/docs/img/0b804819bf30ce8e657ad538d376ecc5.png differ diff --git a/docs/img/0bc8de7b7d20af897fb8b38bb48663e8.png b/docs/img/0bc8de7b7d20af897fb8b38bb48663e8.png new file mode 100644 index 0000000000000000000000000000000000000000..771a355ce45e2afd0e659d0bd3f5bbaa997d55dd Binary files /dev/null and b/docs/img/0bc8de7b7d20af897fb8b38bb48663e8.png differ diff --git a/docs/img/0bef311ef1713ebb246577aeaaa012c3.png b/docs/img/0bef311ef1713ebb246577aeaaa012c3.png new file mode 100644 index 0000000000000000000000000000000000000000..60e4557e72fd3f7ddb0a84a7b75a06bf75c632c1 Binary files /dev/null and b/docs/img/0bef311ef1713ebb246577aeaaa012c3.png differ diff --git a/docs/img/0c549416181d6e18eb1dd34825b00425.png b/docs/img/0c549416181d6e18eb1dd34825b00425.png new file mode 100644 index 0000000000000000000000000000000000000000..ec29faa14b25ca9c5ebd23999f5cacc12a6d6703 Binary files /dev/null and b/docs/img/0c549416181d6e18eb1dd34825b00425.png differ diff --git a/docs/img/0d0a16295f0edf554f921ffda49ff421.png b/docs/img/0d0a16295f0edf554f921ffda49ff421.png new file mode 100644 index 0000000000000000000000000000000000000000..7ba901418e8d6ff36c4fe312233bc5456273102f Binary files /dev/null and b/docs/img/0d0a16295f0edf554f921ffda49ff421.png differ diff --git a/docs/img/0d1089161431c5f21751458027d84535.png b/docs/img/0d1089161431c5f21751458027d84535.png new file mode 100644 index 0000000000000000000000000000000000000000..456bb0c7e1080206bbda3246ea932a4d2bcd01f3 Binary files /dev/null and b/docs/img/0d1089161431c5f21751458027d84535.png differ diff --git a/docs/img/0d1c10a8d14f11dd831b96878fc521e5.png b/docs/img/0d1c10a8d14f11dd831b96878fc521e5.png new file mode 100644 index 0000000000000000000000000000000000000000..0a1fa8576c8ebb34d2efeeabaed01b28dc739bf8 Binary files /dev/null and b/docs/img/0d1c10a8d14f11dd831b96878fc521e5.png differ diff --git a/docs/img/0d2f752f5d8c7352da5333f4f0d27835.png b/docs/img/0d2f752f5d8c7352da5333f4f0d27835.png new file mode 100644 index 0000000000000000000000000000000000000000..b19f2962d169588765b9c2b174d17af169b7c1ee Binary files /dev/null and b/docs/img/0d2f752f5d8c7352da5333f4f0d27835.png differ diff --git a/docs/img/0d3f7491de96f0f5d1d30a594ec42739.png b/docs/img/0d3f7491de96f0f5d1d30a594ec42739.png new file mode 100644 index 0000000000000000000000000000000000000000..abdd6188d46eb88edcdadb72f9695b76065f2a32 Binary files /dev/null and b/docs/img/0d3f7491de96f0f5d1d30a594ec42739.png differ diff --git a/docs/img/0d59f9135c1fed79a51921909516ef69.png b/docs/img/0d59f9135c1fed79a51921909516ef69.png new file mode 100644 index 0000000000000000000000000000000000000000..554a2ae40ee928088d8fe9cfd667e8c21bac4a72 Binary files /dev/null and b/docs/img/0d59f9135c1fed79a51921909516ef69.png differ diff --git a/docs/img/0d6a90afbcbb1f9414d4a9a8437e49f8.png b/docs/img/0d6a90afbcbb1f9414d4a9a8437e49f8.png new file mode 100644 index 0000000000000000000000000000000000000000..e16ee6df04e8ae24448064a2f13ac89ed47d02c4 Binary files /dev/null and b/docs/img/0d6a90afbcbb1f9414d4a9a8437e49f8.png differ diff --git a/docs/img/0dad61d266449688c931d1703509bca3.png b/docs/img/0dad61d266449688c931d1703509bca3.png new file mode 100644 index 0000000000000000000000000000000000000000..77d82ea2c7943559205ba81e1a28d0a124f380cb Binary files /dev/null and b/docs/img/0dad61d266449688c931d1703509bca3.png differ diff --git a/docs/img/0dd0fc53dcaa34b76a16be18538c1a35.png b/docs/img/0dd0fc53dcaa34b76a16be18538c1a35.png new file mode 100644 index 0000000000000000000000000000000000000000..3b2814f9e4194b563fdaa16d067ded004233fb75 Binary files /dev/null and b/docs/img/0dd0fc53dcaa34b76a16be18538c1a35.png differ diff --git a/docs/img/0df7602f630bb279bdd6d7dc6a5dcf2f.png b/docs/img/0df7602f630bb279bdd6d7dc6a5dcf2f.png new file mode 100644 index 0000000000000000000000000000000000000000..e80f95a8e94e5238c913045395e3a7c446b15647 Binary files /dev/null and b/docs/img/0df7602f630bb279bdd6d7dc6a5dcf2f.png differ diff --git a/docs/img/0e0e78d03e98ec2ac04952defaba83ff.png b/docs/img/0e0e78d03e98ec2ac04952defaba83ff.png new file mode 100644 index 0000000000000000000000000000000000000000..c6096f09c507c8142839e6e88fdc4ed389cf1e5e Binary files /dev/null and b/docs/img/0e0e78d03e98ec2ac04952defaba83ff.png differ diff --git a/docs/img/0e2287fb4b32bf9dff45f3255ddd45fe.png b/docs/img/0e2287fb4b32bf9dff45f3255ddd45fe.png new file mode 100644 index 0000000000000000000000000000000000000000..2a5e67660bfc56dfa483977d52c0e5b3ea530bf5 Binary files /dev/null and b/docs/img/0e2287fb4b32bf9dff45f3255ddd45fe.png differ diff --git a/docs/img/0e27f7f7b1dd7b6748365d5ea985238a.png b/docs/img/0e27f7f7b1dd7b6748365d5ea985238a.png new file mode 100644 index 0000000000000000000000000000000000000000..49f920b8917ff9a1a5010ea439c08a51fb16d196 Binary files /dev/null and b/docs/img/0e27f7f7b1dd7b6748365d5ea985238a.png differ diff --git a/docs/img/0f7aab3f307e6b54ebe4d00d94f1da0a.png b/docs/img/0f7aab3f307e6b54ebe4d00d94f1da0a.png new file mode 100644 index 0000000000000000000000000000000000000000..649c3d6d78d028b55a71bd3e82e65b9f1f304f31 Binary files /dev/null and b/docs/img/0f7aab3f307e6b54ebe4d00d94f1da0a.png differ diff --git a/docs/img/0f88b0e1a49600472f2922218cec1ed7.png b/docs/img/0f88b0e1a49600472f2922218cec1ed7.png new file mode 100644 index 0000000000000000000000000000000000000000..370ec4c0354bb499e3dc6f086dcff1e7abe8650a Binary files /dev/null and b/docs/img/0f88b0e1a49600472f2922218cec1ed7.png differ diff --git a/docs/img/0fdd144a1493e4d21226f1b04a5d336a.png b/docs/img/0fdd144a1493e4d21226f1b04a5d336a.png new file mode 100644 index 0000000000000000000000000000000000000000..52c337db9bc37a03146f6c14904396c821d09f16 Binary files /dev/null and b/docs/img/0fdd144a1493e4d21226f1b04a5d336a.png differ diff --git a/docs/img/0ff1ac0799b3b8867f4ebefa4e22d786.png b/docs/img/0ff1ac0799b3b8867f4ebefa4e22d786.png new file mode 100644 index 0000000000000000000000000000000000000000..630bf35e4ebc4cca62c744f81b5f9f527b33956d Binary files /dev/null and b/docs/img/0ff1ac0799b3b8867f4ebefa4e22d786.png differ diff --git a/docs/img/104374dd85800b346ef75734f6fd0b38.png b/docs/img/104374dd85800b346ef75734f6fd0b38.png new file mode 100644 index 0000000000000000000000000000000000000000..3228c8a50912d8368e8c269356dd06117a77382b Binary files /dev/null and b/docs/img/104374dd85800b346ef75734f6fd0b38.png differ diff --git a/docs/img/10fd27d874d8e6ace6b74801909782ae.png b/docs/img/10fd27d874d8e6ace6b74801909782ae.png new file mode 100644 index 0000000000000000000000000000000000000000..df0130d12ac56af8ca71baf1921fdc9cc09a5c11 Binary files /dev/null and b/docs/img/10fd27d874d8e6ace6b74801909782ae.png differ diff --git a/docs/img/114dc1abb6412aca14f3c3b6ad3048dc.png b/docs/img/114dc1abb6412aca14f3c3b6ad3048dc.png new file mode 100644 index 0000000000000000000000000000000000000000..5612a9ed9c893ba3b7a80285b7afdb901d627231 Binary files /dev/null and b/docs/img/114dc1abb6412aca14f3c3b6ad3048dc.png differ diff --git a/docs/img/1162f64da937aa1ef37877c6b8930e1e.png b/docs/img/1162f64da937aa1ef37877c6b8930e1e.png new file mode 100644 index 0000000000000000000000000000000000000000..77c6ee8fd4cc19d228796742829df100e0543bfc Binary files /dev/null and b/docs/img/1162f64da937aa1ef37877c6b8930e1e.png differ diff --git a/docs/img/1165fee2238c55848aeb09d59c76cf7b.png b/docs/img/1165fee2238c55848aeb09d59c76cf7b.png new file mode 100644 index 0000000000000000000000000000000000000000..e7318320a0f006d210dc153c4ef0e82d51cb42d1 Binary files /dev/null and b/docs/img/1165fee2238c55848aeb09d59c76cf7b.png differ diff --git a/docs/img/11728974fe5385112311ab02ea56783e.png b/docs/img/11728974fe5385112311ab02ea56783e.png new file mode 100644 index 0000000000000000000000000000000000000000..7bf908e2f2417218092d1a1ac1228b33519f322f Binary files /dev/null and b/docs/img/11728974fe5385112311ab02ea56783e.png differ diff --git a/docs/img/11b32b9624ee5e827950dd6f126127d6.png b/docs/img/11b32b9624ee5e827950dd6f126127d6.png new file mode 100644 index 0000000000000000000000000000000000000000..dbb95e771a08491ed9db5bb83ea7f57b52d41173 Binary files /dev/null and b/docs/img/11b32b9624ee5e827950dd6f126127d6.png differ diff --git a/docs/img/11f64bd49fd604a4644dd54ed7e423e8.png b/docs/img/11f64bd49fd604a4644dd54ed7e423e8.png new file mode 100644 index 0000000000000000000000000000000000000000..3ffbcf14cb4847af46206b64d592ce24bfdd6ebe Binary files /dev/null and b/docs/img/11f64bd49fd604a4644dd54ed7e423e8.png differ diff --git a/docs/img/12208c7d040cd738d51605b7fcb55237.png b/docs/img/12208c7d040cd738d51605b7fcb55237.png new file mode 100644 index 0000000000000000000000000000000000000000..82c975df531ce7d3610ea1201da300ca97c67e80 Binary files /dev/null and b/docs/img/12208c7d040cd738d51605b7fcb55237.png differ diff --git a/docs/img/12e557e74666b1c90827cdd5bfe4d87a.png b/docs/img/12e557e74666b1c90827cdd5bfe4d87a.png new file mode 100644 index 0000000000000000000000000000000000000000..ec02aad32ce5e8c29f6b7e64b660c56f62179e27 Binary files /dev/null and b/docs/img/12e557e74666b1c90827cdd5bfe4d87a.png differ diff --git a/docs/img/136df5416c67f2d80606b4849658e289.png b/docs/img/136df5416c67f2d80606b4849658e289.png new file mode 100644 index 0000000000000000000000000000000000000000..d7a71c08b2474fa25c46f8f771dc4677289a736b Binary files /dev/null and b/docs/img/136df5416c67f2d80606b4849658e289.png differ diff --git a/docs/img/137ac74ffc45b0c50cf354baa972ca89.png b/docs/img/137ac74ffc45b0c50cf354baa972ca89.png new file mode 100644 index 0000000000000000000000000000000000000000..051d660e8bbc5f93dd909fa6e984aa262754fe46 Binary files /dev/null and b/docs/img/137ac74ffc45b0c50cf354baa972ca89.png differ diff --git a/docs/img/13b2b9b44dbf46de0243edc068ecab42.png b/docs/img/13b2b9b44dbf46de0243edc068ecab42.png new file mode 100644 index 0000000000000000000000000000000000000000..825cac669030588a0138f4f0bf7caea63d1dfc4e Binary files /dev/null and b/docs/img/13b2b9b44dbf46de0243edc068ecab42.png differ diff --git a/docs/img/13c910771ce7fad76e82ba7b8bdd440b.png b/docs/img/13c910771ce7fad76e82ba7b8bdd440b.png new file mode 100644 index 0000000000000000000000000000000000000000..11e2c98a84eae322af0f8d4894099f5e1cba3030 Binary files /dev/null and b/docs/img/13c910771ce7fad76e82ba7b8bdd440b.png differ diff --git a/docs/img/14110c067c5c98646bcad82dbd3be10b.png b/docs/img/14110c067c5c98646bcad82dbd3be10b.png new file mode 100644 index 0000000000000000000000000000000000000000..b3be73a5c864aee43bc02c775ab06a1bf3e1ca24 Binary files /dev/null and b/docs/img/14110c067c5c98646bcad82dbd3be10b.png differ diff --git a/docs/img/1427a32ce32914c8100f7563817e3d64.png b/docs/img/1427a32ce32914c8100f7563817e3d64.png new file mode 100644 index 0000000000000000000000000000000000000000..edadad37cba80ff392e8a8fff946ed09fbb958d1 Binary files /dev/null and b/docs/img/1427a32ce32914c8100f7563817e3d64.png differ diff --git a/docs/img/149fa515778bea7ce86903f0c8d9b31f.png b/docs/img/149fa515778bea7ce86903f0c8d9b31f.png new file mode 100644 index 0000000000000000000000000000000000000000..02612e925812ed64abd2caf364cf4cc65446d326 Binary files /dev/null and b/docs/img/149fa515778bea7ce86903f0c8d9b31f.png differ diff --git a/docs/img/14b1dcd13ed2d776e5cab726504e2df9.png b/docs/img/14b1dcd13ed2d776e5cab726504e2df9.png new file mode 100644 index 0000000000000000000000000000000000000000..f9b1685bb48a623c105bca7885aeac338041b7e8 Binary files /dev/null and b/docs/img/14b1dcd13ed2d776e5cab726504e2df9.png differ diff --git a/docs/img/15b455cffa86c3a9234ad8c30082a4df.png b/docs/img/15b455cffa86c3a9234ad8c30082a4df.png new file mode 100644 index 0000000000000000000000000000000000000000..d81e29bb512d7a941545236f9f9c4f211b64bf9d Binary files /dev/null and b/docs/img/15b455cffa86c3a9234ad8c30082a4df.png differ diff --git a/docs/img/161780e2fab1ff78247b22985553ba96.png b/docs/img/161780e2fab1ff78247b22985553ba96.png new file mode 100644 index 0000000000000000000000000000000000000000..3337df4bf2a4b0864a18405d0bdfe909211c52be Binary files /dev/null and b/docs/img/161780e2fab1ff78247b22985553ba96.png differ diff --git a/docs/img/169af1eb67d287048e2bd4de1d3a178a.png b/docs/img/169af1eb67d287048e2bd4de1d3a178a.png new file mode 100644 index 0000000000000000000000000000000000000000..60ae66c23391666d2d703b479df229e971a969fc Binary files /dev/null and b/docs/img/169af1eb67d287048e2bd4de1d3a178a.png differ diff --git a/docs/img/16db6a809ddf03cf101fdbec905d41a2.png b/docs/img/16db6a809ddf03cf101fdbec905d41a2.png new file mode 100644 index 0000000000000000000000000000000000000000..cb58d4a31b41b0191fa874c6752f3e3af78df94b Binary files /dev/null and b/docs/img/16db6a809ddf03cf101fdbec905d41a2.png differ diff --git a/docs/img/16f0d7c3d19700b0e30aa6c1528acb91.png b/docs/img/16f0d7c3d19700b0e30aa6c1528acb91.png new file mode 100644 index 0000000000000000000000000000000000000000..48a212b6dad87af6630565d1e293f4bfc6d216fb Binary files /dev/null and b/docs/img/16f0d7c3d19700b0e30aa6c1528acb91.png differ diff --git a/docs/img/1780684b75826fc70c4f9d6a00cd9984.png b/docs/img/1780684b75826fc70c4f9d6a00cd9984.png new file mode 100644 index 0000000000000000000000000000000000000000..ab566831623543117b9eb9ab8bac0fabfab2cef2 Binary files /dev/null and b/docs/img/1780684b75826fc70c4f9d6a00cd9984.png differ diff --git a/docs/img/17abb300a15db5073a41bf8a13e53bc7.png b/docs/img/17abb300a15db5073a41bf8a13e53bc7.png new file mode 100644 index 0000000000000000000000000000000000000000..0cf3afd441fafb718eff65d3fe2596a1d8dfbce4 Binary files /dev/null and b/docs/img/17abb300a15db5073a41bf8a13e53bc7.png differ diff --git a/docs/img/17d0ef7b105be8069a4258a758bd25bb.png b/docs/img/17d0ef7b105be8069a4258a758bd25bb.png new file mode 100644 index 0000000000000000000000000000000000000000..12ed0d74698ea73d38cbe870dd140c2279b59a67 Binary files /dev/null and b/docs/img/17d0ef7b105be8069a4258a758bd25bb.png differ diff --git a/docs/img/17e23e08ff33b405e039adae1f73cb83.png b/docs/img/17e23e08ff33b405e039adae1f73cb83.png new file mode 100644 index 0000000000000000000000000000000000000000..fdada3feff124e2326de96a65588840b0b9a0c34 Binary files /dev/null and b/docs/img/17e23e08ff33b405e039adae1f73cb83.png differ diff --git a/docs/img/181ef05617eae83f93df5db5884cb3f2.png b/docs/img/181ef05617eae83f93df5db5884cb3f2.png new file mode 100644 index 0000000000000000000000000000000000000000..889effdbd786e226a99411b46530470d41a46037 Binary files /dev/null and b/docs/img/181ef05617eae83f93df5db5884cb3f2.png differ diff --git a/docs/img/182928c540d17ccf275438850fc7592d.png b/docs/img/182928c540d17ccf275438850fc7592d.png new file mode 100644 index 0000000000000000000000000000000000000000..3b7f74cc6bfa885370bcefccd5e31138700414f2 Binary files /dev/null and b/docs/img/182928c540d17ccf275438850fc7592d.png differ diff --git a/docs/img/184e7323733c8aa9331e3fbef102e17c.png b/docs/img/184e7323733c8aa9331e3fbef102e17c.png new file mode 100644 index 0000000000000000000000000000000000000000..84658aa5104a439ed312b9545e623aef3c8c74e1 Binary files /dev/null and b/docs/img/184e7323733c8aa9331e3fbef102e17c.png differ diff --git a/docs/img/185cfb126a59b17e7d802717876f8725.png b/docs/img/185cfb126a59b17e7d802717876f8725.png new file mode 100644 index 0000000000000000000000000000000000000000..03c43e8fcc67fcf8bfe292b059d777dd36d83ea6 Binary files /dev/null and b/docs/img/185cfb126a59b17e7d802717876f8725.png differ diff --git a/docs/img/1864a1996bbb1636d65648dd8b0857df.png b/docs/img/1864a1996bbb1636d65648dd8b0857df.png new file mode 100644 index 0000000000000000000000000000000000000000..d29a1aefbc14f5c0850be3a6a4ec07ff8f022002 Binary files /dev/null and b/docs/img/1864a1996bbb1636d65648dd8b0857df.png differ diff --git a/docs/img/18f2b22b7daf0beab9074c6695c99960.png b/docs/img/18f2b22b7daf0beab9074c6695c99960.png new file mode 100644 index 0000000000000000000000000000000000000000..6ce5a3c3a60bb8e62e7912c5dadec92bfceaed05 Binary files /dev/null and b/docs/img/18f2b22b7daf0beab9074c6695c99960.png differ diff --git a/docs/img/191e4984d9e1aa615a86fec2b6d42dcd.png b/docs/img/191e4984d9e1aa615a86fec2b6d42dcd.png new file mode 100644 index 0000000000000000000000000000000000000000..d22d76eaedb0dd4aff443c363cf42c66d72bcad6 Binary files /dev/null and b/docs/img/191e4984d9e1aa615a86fec2b6d42dcd.png differ diff --git a/docs/img/1a097c142decf7d516165322a0f7b880.png b/docs/img/1a097c142decf7d516165322a0f7b880.png new file mode 100644 index 0000000000000000000000000000000000000000..d9a5db4e0a98789e0eb04f942b30cbfc4d59b166 Binary files /dev/null and b/docs/img/1a097c142decf7d516165322a0f7b880.png differ diff --git a/docs/img/1a1b871d7e874d4f8e2ab4905d000509.png b/docs/img/1a1b871d7e874d4f8e2ab4905d000509.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c7565370b115c2edc39e54cf84203885039ca1 Binary files /dev/null and b/docs/img/1a1b871d7e874d4f8e2ab4905d000509.png differ diff --git a/docs/img/1a3371a11e14e221f5c8e0e75e327d08.png b/docs/img/1a3371a11e14e221f5c8e0e75e327d08.png new file mode 100644 index 0000000000000000000000000000000000000000..f48d0bfb9d6e02717098f07cbe3552cf9c073699 Binary files /dev/null and b/docs/img/1a3371a11e14e221f5c8e0e75e327d08.png differ diff --git a/docs/img/1a3f578f317c266ca4b5d61eb91d025b.png b/docs/img/1a3f578f317c266ca4b5d61eb91d025b.png new file mode 100644 index 0000000000000000000000000000000000000000..c3c88c4aa8ee8ecb3d1e761f15346dba8a5d4392 Binary files /dev/null and b/docs/img/1a3f578f317c266ca4b5d61eb91d025b.png differ diff --git a/docs/img/1a5840885de676ed33d7cdb688b26a12.png b/docs/img/1a5840885de676ed33d7cdb688b26a12.png new file mode 100644 index 0000000000000000000000000000000000000000..80c0478b58a67bc355f348e312330be62b8fbe53 Binary files /dev/null and b/docs/img/1a5840885de676ed33d7cdb688b26a12.png differ diff --git a/docs/img/1ab2181cd0be5aa7d8e96f16a1348ef9.png b/docs/img/1ab2181cd0be5aa7d8e96f16a1348ef9.png new file mode 100644 index 0000000000000000000000000000000000000000..6ea70960e7b1c9b7a8d04cf568f4b8cf4b875c78 Binary files /dev/null and b/docs/img/1ab2181cd0be5aa7d8e96f16a1348ef9.png differ diff --git a/docs/img/1b109b486c41c14a03eea4127cec2351.png b/docs/img/1b109b486c41c14a03eea4127cec2351.png new file mode 100644 index 0000000000000000000000000000000000000000..1c6baf9d648ae1f62832322ef63477a77407ced2 Binary files /dev/null and b/docs/img/1b109b486c41c14a03eea4127cec2351.png differ diff --git a/docs/img/1b69e9fcb692fa835e9b7e06fa856aee.png b/docs/img/1b69e9fcb692fa835e9b7e06fa856aee.png new file mode 100644 index 0000000000000000000000000000000000000000..e8bde94d7c795639f8d3b3e1f3194a3f89542fac Binary files /dev/null and b/docs/img/1b69e9fcb692fa835e9b7e06fa856aee.png differ diff --git a/docs/img/1b984d904256e7a325a4cc30bcf71ee1.png b/docs/img/1b984d904256e7a325a4cc30bcf71ee1.png new file mode 100644 index 0000000000000000000000000000000000000000..130d5ccc03b294324770c0e691d159a6d51c88ac Binary files /dev/null and b/docs/img/1b984d904256e7a325a4cc30bcf71ee1.png differ diff --git a/docs/img/1bb73cd8d699dd8fa617c328abafb76b.png b/docs/img/1bb73cd8d699dd8fa617c328abafb76b.png new file mode 100644 index 0000000000000000000000000000000000000000..9cd62c8e9f94f0d7102102b93c5b8fb1d693e3d3 Binary files /dev/null and b/docs/img/1bb73cd8d699dd8fa617c328abafb76b.png differ diff --git a/docs/img/1bc92f79d9645e6ae51aff10100e5c0d.png b/docs/img/1bc92f79d9645e6ae51aff10100e5c0d.png new file mode 100644 index 0000000000000000000000000000000000000000..1a1bb82c612670151a8b18cf04e92e6fcdf94eb5 Binary files /dev/null and b/docs/img/1bc92f79d9645e6ae51aff10100e5c0d.png differ diff --git a/docs/img/1bce7244cd585ee6d059a7aa1903f194.png b/docs/img/1bce7244cd585ee6d059a7aa1903f194.png new file mode 100644 index 0000000000000000000000000000000000000000..e7d2b80c8c63adf2d1c61962d3ddafe8e169f412 Binary files /dev/null and b/docs/img/1bce7244cd585ee6d059a7aa1903f194.png differ diff --git a/docs/img/1be5fea51b824b103e9b5bac12136a90.png b/docs/img/1be5fea51b824b103e9b5bac12136a90.png new file mode 100644 index 0000000000000000000000000000000000000000..1cdc02a389bfc8999b512f6efb121491f4dc7541 Binary files /dev/null and b/docs/img/1be5fea51b824b103e9b5bac12136a90.png differ diff --git a/docs/img/1c1c9ba40bbb3c1ab789e70a4c4d42e6.png b/docs/img/1c1c9ba40bbb3c1ab789e70a4c4d42e6.png new file mode 100644 index 0000000000000000000000000000000000000000..0f35a62ff3b4e0f9099adbb8abc6a0db8180240f Binary files /dev/null and b/docs/img/1c1c9ba40bbb3c1ab789e70a4c4d42e6.png differ diff --git a/docs/img/1c4eef7cdb82fd840a9facad4ee93d6b.png b/docs/img/1c4eef7cdb82fd840a9facad4ee93d6b.png new file mode 100644 index 0000000000000000000000000000000000000000..9ebe002a85d4cbc40e8e3af64259d27c4675f802 Binary files /dev/null and b/docs/img/1c4eef7cdb82fd840a9facad4ee93d6b.png differ diff --git a/docs/img/1c78b1078232f166ee3d03d64f2b3907.png b/docs/img/1c78b1078232f166ee3d03d64f2b3907.png new file mode 100644 index 0000000000000000000000000000000000000000..a8cfd35269a967f53a15b66e4332484e60382473 Binary files /dev/null and b/docs/img/1c78b1078232f166ee3d03d64f2b3907.png differ diff --git a/docs/img/1c96e8d94988240b7dc68ae02dbea405.png b/docs/img/1c96e8d94988240b7dc68ae02dbea405.png new file mode 100644 index 0000000000000000000000000000000000000000..06faad869874f493d9eaef75e6658595c146ddc1 Binary files /dev/null and b/docs/img/1c96e8d94988240b7dc68ae02dbea405.png differ diff --git a/docs/img/1d54aa31264e3f3b98ebf2049669f910.png b/docs/img/1d54aa31264e3f3b98ebf2049669f910.png new file mode 100644 index 0000000000000000000000000000000000000000..d3f5631fa1b1838abee9ba2069c8fc4be6e22c15 Binary files /dev/null and b/docs/img/1d54aa31264e3f3b98ebf2049669f910.png differ diff --git a/docs/img/1d8faac0ce4cf1206b5c2745df725ca6.png b/docs/img/1d8faac0ce4cf1206b5c2745df725ca6.png new file mode 100644 index 0000000000000000000000000000000000000000..434fb1b25e655802df3c79feb6f71fc80fa29f95 Binary files /dev/null and b/docs/img/1d8faac0ce4cf1206b5c2745df725ca6.png differ diff --git a/docs/img/1d9bd6ef20c22f103a6d120b8c673b06.png b/docs/img/1d9bd6ef20c22f103a6d120b8c673b06.png new file mode 100644 index 0000000000000000000000000000000000000000..c9c932108db67f46c961ee6dce72eeb19a46e091 Binary files /dev/null and b/docs/img/1d9bd6ef20c22f103a6d120b8c673b06.png differ diff --git a/docs/img/1dcfd40d9306c4cfb80013c0cebdcac0.png b/docs/img/1dcfd40d9306c4cfb80013c0cebdcac0.png new file mode 100644 index 0000000000000000000000000000000000000000..221115c8dfcacc97a7c825f948bb8adce8736911 Binary files /dev/null and b/docs/img/1dcfd40d9306c4cfb80013c0cebdcac0.png differ diff --git a/docs/img/1e0213e85ced3ac9dcc079f0e1831068.png b/docs/img/1e0213e85ced3ac9dcc079f0e1831068.png new file mode 100644 index 0000000000000000000000000000000000000000..fcf79604e283ab7f24d4d68e310a03b6cde81b28 Binary files /dev/null and b/docs/img/1e0213e85ced3ac9dcc079f0e1831068.png differ diff --git a/docs/img/1e1a93a55568355165c7529b5326427b.png b/docs/img/1e1a93a55568355165c7529b5326427b.png new file mode 100644 index 0000000000000000000000000000000000000000..1dacb5dc1abfe4b0a7b46af9ffd0748c5f10df0f Binary files /dev/null and b/docs/img/1e1a93a55568355165c7529b5326427b.png differ diff --git a/docs/img/1f5aad8fb69a4afb74547a2d31fcbc66.png b/docs/img/1f5aad8fb69a4afb74547a2d31fcbc66.png new file mode 100644 index 0000000000000000000000000000000000000000..63e4c57fb16ba58aabfb259048f48b282b116075 Binary files /dev/null and b/docs/img/1f5aad8fb69a4afb74547a2d31fcbc66.png differ diff --git a/docs/img/1fa927abbc0d78f64822dcc6c7295cd4.png b/docs/img/1fa927abbc0d78f64822dcc6c7295cd4.png new file mode 100644 index 0000000000000000000000000000000000000000..24e40e88cf63bf2152f36909290c10f60ae11a63 Binary files /dev/null and b/docs/img/1fa927abbc0d78f64822dcc6c7295cd4.png differ diff --git a/docs/img/1fdfdef058a3092e25352089de97fee6.png b/docs/img/1fdfdef058a3092e25352089de97fee6.png new file mode 100644 index 0000000000000000000000000000000000000000..e563a48ba8807d6a3b872b60b833431c4a69183e Binary files /dev/null and b/docs/img/1fdfdef058a3092e25352089de97fee6.png differ diff --git a/docs/img/1ff79a3af1496b3e864efbcf5f93307f.png b/docs/img/1ff79a3af1496b3e864efbcf5f93307f.png new file mode 100644 index 0000000000000000000000000000000000000000..1a3328be136ea9a5efa06ec40b5b9f7487670f6c Binary files /dev/null and b/docs/img/1ff79a3af1496b3e864efbcf5f93307f.png differ diff --git a/docs/img/2066156f84e498acec96cdfb63d2d2a4.png b/docs/img/2066156f84e498acec96cdfb63d2d2a4.png new file mode 100644 index 0000000000000000000000000000000000000000..b0d6880f84cfc93dbc3f20ccca3cff9bc5d4dfee Binary files /dev/null and b/docs/img/2066156f84e498acec96cdfb63d2d2a4.png differ diff --git a/docs/img/206da14c2b9fd76390be58e7103b69c7.png b/docs/img/206da14c2b9fd76390be58e7103b69c7.png new file mode 100644 index 0000000000000000000000000000000000000000..e30751e1271dc1d5034b2e3616cf9d01d6dc9e2c Binary files /dev/null and b/docs/img/206da14c2b9fd76390be58e7103b69c7.png differ diff --git a/docs/img/20bba5f798131b98df30aaa9202ccfd5.png b/docs/img/20bba5f798131b98df30aaa9202ccfd5.png new file mode 100644 index 0000000000000000000000000000000000000000..301a5727e4a0e90cff67804c3529a083600661cd Binary files /dev/null and b/docs/img/20bba5f798131b98df30aaa9202ccfd5.png differ diff --git a/docs/img/210e34a4dbdbe21aba5083c6f7dac9cb.png b/docs/img/210e34a4dbdbe21aba5083c6f7dac9cb.png new file mode 100644 index 0000000000000000000000000000000000000000..fb70dec5262560a26b923cd4a597ed6ffe73c1af Binary files /dev/null and b/docs/img/210e34a4dbdbe21aba5083c6f7dac9cb.png differ diff --git a/docs/img/212946086e16f591c716728308d49ca3.png b/docs/img/212946086e16f591c716728308d49ca3.png new file mode 100644 index 0000000000000000000000000000000000000000..3d9c01aae9304f43a297e682bd6bf5149c176934 Binary files /dev/null and b/docs/img/212946086e16f591c716728308d49ca3.png differ diff --git a/docs/img/21967843cf3a12bcfa5e39a39b1b3f69.png b/docs/img/21967843cf3a12bcfa5e39a39b1b3f69.png new file mode 100644 index 0000000000000000000000000000000000000000..54324df41ddf7dd53a4b58eb43e941804a943ada Binary files /dev/null and b/docs/img/21967843cf3a12bcfa5e39a39b1b3f69.png differ diff --git a/docs/img/222aa4a1e09c2312446d0aa324c6f193.png b/docs/img/222aa4a1e09c2312446d0aa324c6f193.png new file mode 100644 index 0000000000000000000000000000000000000000..d40e041cc8429378eb5f8d5d9ef508e414b7f5e5 Binary files /dev/null and b/docs/img/222aa4a1e09c2312446d0aa324c6f193.png differ diff --git a/docs/img/2257f7989872604ba6ce6506ba811b15.png b/docs/img/2257f7989872604ba6ce6506ba811b15.png new file mode 100644 index 0000000000000000000000000000000000000000..a1859df48955c6f64c49232695b47ad29e032e87 Binary files /dev/null and b/docs/img/2257f7989872604ba6ce6506ba811b15.png differ diff --git a/docs/img/2279c6b38c41208a2726d04b0df15c37.png b/docs/img/2279c6b38c41208a2726d04b0df15c37.png new file mode 100644 index 0000000000000000000000000000000000000000..9ff313fb6c07f4a6fd588692ce649e5be8223037 Binary files /dev/null and b/docs/img/2279c6b38c41208a2726d04b0df15c37.png differ diff --git a/docs/img/2310ec0a03905adc0774d21079604b57.png b/docs/img/2310ec0a03905adc0774d21079604b57.png new file mode 100644 index 0000000000000000000000000000000000000000..aa37927b8236b1a74140f7037c6574224acb5c07 Binary files /dev/null and b/docs/img/2310ec0a03905adc0774d21079604b57.png differ diff --git a/docs/img/235fdd047e32990019bc08c92ced8299.png b/docs/img/235fdd047e32990019bc08c92ced8299.png new file mode 100644 index 0000000000000000000000000000000000000000..1145bf0b207e41a5c6269cb58e6a99dd79e12f6c Binary files /dev/null and b/docs/img/235fdd047e32990019bc08c92ced8299.png differ diff --git a/docs/img/23b032de89e1f1056b75bd7ad55823ea.png b/docs/img/23b032de89e1f1056b75bd7ad55823ea.png new file mode 100644 index 0000000000000000000000000000000000000000..847166f384ab4d5366640d4043fb5207ceeca4b0 Binary files /dev/null and b/docs/img/23b032de89e1f1056b75bd7ad55823ea.png differ diff --git a/docs/img/243c1a9fc7dab75d6576c27470e73bf0.png b/docs/img/243c1a9fc7dab75d6576c27470e73bf0.png new file mode 100644 index 0000000000000000000000000000000000000000..0fe2b87e8d30a1b49b9277ba085dc05fb082174d Binary files /dev/null and b/docs/img/243c1a9fc7dab75d6576c27470e73bf0.png differ diff --git a/docs/img/24ea9a3635dc27668b899d6785917b1b.png b/docs/img/24ea9a3635dc27668b899d6785917b1b.png new file mode 100644 index 0000000000000000000000000000000000000000..b8af583951ed282d3928d8fd5d2b8cc2934b894b Binary files /dev/null and b/docs/img/24ea9a3635dc27668b899d6785917b1b.png differ diff --git a/docs/img/252e40c4dc029a21eb939cb40f715d34.png b/docs/img/252e40c4dc029a21eb939cb40f715d34.png new file mode 100644 index 0000000000000000000000000000000000000000..c6d35b60762697ec954ea318486567c7ed4987f8 Binary files /dev/null and b/docs/img/252e40c4dc029a21eb939cb40f715d34.png differ diff --git a/docs/img/25892ec4aa99429a91c30ac3395379e0.png b/docs/img/25892ec4aa99429a91c30ac3395379e0.png new file mode 100644 index 0000000000000000000000000000000000000000..20bbe25e8762d21320cd0a5d11dd6a5b6f02c983 Binary files /dev/null and b/docs/img/25892ec4aa99429a91c30ac3395379e0.png differ diff --git a/docs/img/261e6c6422bccbb978c24c0728f3a593.png b/docs/img/261e6c6422bccbb978c24c0728f3a593.png new file mode 100644 index 0000000000000000000000000000000000000000..577dc4812829880cab0a98d34d27a184c909aad6 Binary files /dev/null and b/docs/img/261e6c6422bccbb978c24c0728f3a593.png differ diff --git a/docs/img/2629e4ef9252e4970d626ca424e88dd2.png b/docs/img/2629e4ef9252e4970d626ca424e88dd2.png new file mode 100644 index 0000000000000000000000000000000000000000..0642c1caa2964d84818ec0b483349c4f8e53161d Binary files /dev/null and b/docs/img/2629e4ef9252e4970d626ca424e88dd2.png differ diff --git a/docs/img/262e648fe4e99ca02b386ebade539097.png b/docs/img/262e648fe4e99ca02b386ebade539097.png new file mode 100644 index 0000000000000000000000000000000000000000..15570c619a8e5f2f2026f864e4a451f2db726726 Binary files /dev/null and b/docs/img/262e648fe4e99ca02b386ebade539097.png differ diff --git a/docs/img/264ee345c8d001f9b7cabf52e10f47bf.png b/docs/img/264ee345c8d001f9b7cabf52e10f47bf.png new file mode 100644 index 0000000000000000000000000000000000000000..1042fd3dc067b765017e4e36edf8b6b941cd6075 Binary files /dev/null and b/docs/img/264ee345c8d001f9b7cabf52e10f47bf.png differ diff --git a/docs/img/265f035427185c0998b05886114d104b.png b/docs/img/265f035427185c0998b05886114d104b.png new file mode 100644 index 0000000000000000000000000000000000000000..7bc218af356d10f3bfed49e7eed5c6f774599bbf Binary files /dev/null and b/docs/img/265f035427185c0998b05886114d104b.png differ diff --git a/docs/img/26b5d3ef6b515c199d6c860ac62a4671.png b/docs/img/26b5d3ef6b515c199d6c860ac62a4671.png new file mode 100644 index 0000000000000000000000000000000000000000..68143805c0a8fdb5b3fb527e4bedf8468bde8953 Binary files /dev/null and b/docs/img/26b5d3ef6b515c199d6c860ac62a4671.png differ diff --git a/docs/img/276614fbc4ef7b7b9f7a445dffbc5691.png b/docs/img/276614fbc4ef7b7b9f7a445dffbc5691.png new file mode 100644 index 0000000000000000000000000000000000000000..2c64b681dfba44b42de4b4df30520548ac160a32 Binary files /dev/null and b/docs/img/276614fbc4ef7b7b9f7a445dffbc5691.png differ diff --git a/docs/img/27858125d0f3461e373b06413f40e616.png b/docs/img/27858125d0f3461e373b06413f40e616.png new file mode 100644 index 0000000000000000000000000000000000000000..861bba650361792d1ae6851dd732ea558701000a Binary files /dev/null and b/docs/img/27858125d0f3461e373b06413f40e616.png differ diff --git a/docs/img/279650b9e9c3ec26a7d6f0493bd5af7c.png b/docs/img/279650b9e9c3ec26a7d6f0493bd5af7c.png new file mode 100644 index 0000000000000000000000000000000000000000..fed4b3030aed026538b04b588b260a9d2dec566d Binary files /dev/null and b/docs/img/279650b9e9c3ec26a7d6f0493bd5af7c.png differ diff --git a/docs/img/27b77c1cf5861234d7e06b742e7cbf58.png b/docs/img/27b77c1cf5861234d7e06b742e7cbf58.png new file mode 100644 index 0000000000000000000000000000000000000000..0e394d63a1b4496f0e359e712a78952f9b38af90 Binary files /dev/null and b/docs/img/27b77c1cf5861234d7e06b742e7cbf58.png differ diff --git a/docs/img/27d6bf9eb64fd8e4298e7a2a8ae64983.png b/docs/img/27d6bf9eb64fd8e4298e7a2a8ae64983.png new file mode 100644 index 0000000000000000000000000000000000000000..35d4828dd55dd0dc6ba840ddd651a27b0afa7d9c Binary files /dev/null and b/docs/img/27d6bf9eb64fd8e4298e7a2a8ae64983.png differ diff --git a/docs/img/27f5db1ffe5c715ccd311bccf93665f2.png b/docs/img/27f5db1ffe5c715ccd311bccf93665f2.png new file mode 100644 index 0000000000000000000000000000000000000000..209bec6356901650c16cbc5b7d6fee2e29190eb4 Binary files /dev/null and b/docs/img/27f5db1ffe5c715ccd311bccf93665f2.png differ diff --git a/docs/img/281606a988de9b8e23469c0de4e22062.png b/docs/img/281606a988de9b8e23469c0de4e22062.png new file mode 100644 index 0000000000000000000000000000000000000000..912d3266426e8197c1f51acf6b56a4f7cb3801bc Binary files /dev/null and b/docs/img/281606a988de9b8e23469c0de4e22062.png differ diff --git a/docs/img/2823aaef9502e47fb72734606099a98a.png b/docs/img/2823aaef9502e47fb72734606099a98a.png new file mode 100644 index 0000000000000000000000000000000000000000..3bb926c684a522502c6b5c697566c18341751ebc Binary files /dev/null and b/docs/img/2823aaef9502e47fb72734606099a98a.png differ diff --git a/docs/img/28300ad671ab6b5aec8525cb2a7af157.png b/docs/img/28300ad671ab6b5aec8525cb2a7af157.png new file mode 100644 index 0000000000000000000000000000000000000000..1b6f902e9958e5d30456ed541bc28d77c776e91b Binary files /dev/null and b/docs/img/28300ad671ab6b5aec8525cb2a7af157.png differ diff --git a/docs/img/283011f90b0969b60cd202dd293525ca.png b/docs/img/283011f90b0969b60cd202dd293525ca.png new file mode 100644 index 0000000000000000000000000000000000000000..fedf36e1476f1e66320da0748c74e1051c337744 Binary files /dev/null and b/docs/img/283011f90b0969b60cd202dd293525ca.png differ diff --git a/docs/img/284b72b1bfc8d5679fdaa384932b3b8c.png b/docs/img/284b72b1bfc8d5679fdaa384932b3b8c.png new file mode 100644 index 0000000000000000000000000000000000000000..343cc5a3116249723f50407a042f28d8d376550a Binary files /dev/null and b/docs/img/284b72b1bfc8d5679fdaa384932b3b8c.png differ diff --git a/docs/img/28ba73ced40f830058c21c46c8291bfe.png b/docs/img/28ba73ced40f830058c21c46c8291bfe.png new file mode 100644 index 0000000000000000000000000000000000000000..686c4191307a49437f2366eadcda31bef5fdb976 Binary files /dev/null and b/docs/img/28ba73ced40f830058c21c46c8291bfe.png differ diff --git a/docs/img/28e0f270ca5b3b728207d80c19a82d71.png b/docs/img/28e0f270ca5b3b728207d80c19a82d71.png new file mode 100644 index 0000000000000000000000000000000000000000..b3ac97b273bdfcfb82f881bc4e42e6ca27d02132 Binary files /dev/null and b/docs/img/28e0f270ca5b3b728207d80c19a82d71.png differ diff --git a/docs/img/28ec7a2f016b77873dfadd5ab59c447b.png b/docs/img/28ec7a2f016b77873dfadd5ab59c447b.png new file mode 100644 index 0000000000000000000000000000000000000000..167832ad29e19f46cefe1e3c91b43e44c9b5f4fc Binary files /dev/null and b/docs/img/28ec7a2f016b77873dfadd5ab59c447b.png differ diff --git a/docs/img/2927b047cacec2945671ab2484aafe9d.png b/docs/img/2927b047cacec2945671ab2484aafe9d.png new file mode 100644 index 0000000000000000000000000000000000000000..9228e2464ed72bb1c22266945646cf98419aa7bc Binary files /dev/null and b/docs/img/2927b047cacec2945671ab2484aafe9d.png differ diff --git a/docs/img/2a301148b56e04c50113445dc7280c15.png b/docs/img/2a301148b56e04c50113445dc7280c15.png new file mode 100644 index 0000000000000000000000000000000000000000..461fe295303c46f92a4225ae7e8bd7bf07871c67 Binary files /dev/null and b/docs/img/2a301148b56e04c50113445dc7280c15.png differ diff --git a/docs/img/2a62cf1a17a5306e4d6cd91c30149941.png b/docs/img/2a62cf1a17a5306e4d6cd91c30149941.png new file mode 100644 index 0000000000000000000000000000000000000000..3adf7276ed6bb0ca4b10311a56445fb0f73fc15d Binary files /dev/null and b/docs/img/2a62cf1a17a5306e4d6cd91c30149941.png differ diff --git a/docs/img/2ae8145aa44498bcadafa3451ee343b1.png b/docs/img/2ae8145aa44498bcadafa3451ee343b1.png new file mode 100644 index 0000000000000000000000000000000000000000..91f93becd33ee240eb25985db21e387b08722d8b Binary files /dev/null and b/docs/img/2ae8145aa44498bcadafa3451ee343b1.png differ diff --git a/docs/img/2b38faa6a2c817e4d1b8b32f803db372.png b/docs/img/2b38faa6a2c817e4d1b8b32f803db372.png new file mode 100644 index 0000000000000000000000000000000000000000..60f091a0e5e1f99ab04e78ca9638626efa5d3a7c Binary files /dev/null and b/docs/img/2b38faa6a2c817e4d1b8b32f803db372.png differ diff --git a/docs/img/2b49f82a2ff96781b55685367813e6c9.png b/docs/img/2b49f82a2ff96781b55685367813e6c9.png new file mode 100644 index 0000000000000000000000000000000000000000..ea847a5cdd9e884665188b106209ec91569ace81 Binary files /dev/null and b/docs/img/2b49f82a2ff96781b55685367813e6c9.png differ diff --git a/docs/img/2b66844a710706131349b467b399b449.png b/docs/img/2b66844a710706131349b467b399b449.png new file mode 100644 index 0000000000000000000000000000000000000000..b3a5029444ef8e294ba9f7fe833510e528ba19e7 Binary files /dev/null and b/docs/img/2b66844a710706131349b467b399b449.png differ diff --git a/docs/img/2bb7640bbe66bec0d43070f6f4053758.png b/docs/img/2bb7640bbe66bec0d43070f6f4053758.png new file mode 100644 index 0000000000000000000000000000000000000000..70ebf6e70d7692bd6fda9ee93d9a722c5e6ef935 Binary files /dev/null and b/docs/img/2bb7640bbe66bec0d43070f6f4053758.png differ diff --git a/docs/img/2c7964b63403cf1f03ea9bdbfeee96cf.png b/docs/img/2c7964b63403cf1f03ea9bdbfeee96cf.png new file mode 100644 index 0000000000000000000000000000000000000000..ac35818c8568e55bc7aa923bcfd261cc17576b70 Binary files /dev/null and b/docs/img/2c7964b63403cf1f03ea9bdbfeee96cf.png differ diff --git a/docs/img/2c8994d4c86769ec5151192ff555b261.png b/docs/img/2c8994d4c86769ec5151192ff555b261.png new file mode 100644 index 0000000000000000000000000000000000000000..81e5f6f7fa28d8030a99c82a59a3d0817513a52c Binary files /dev/null and b/docs/img/2c8994d4c86769ec5151192ff555b261.png differ diff --git a/docs/img/2d13f3059b88ccaf448646ed61f70d47.png b/docs/img/2d13f3059b88ccaf448646ed61f70d47.png new file mode 100644 index 0000000000000000000000000000000000000000..b5b4391905f23e6f03988e025c013c1b21d125c3 Binary files /dev/null and b/docs/img/2d13f3059b88ccaf448646ed61f70d47.png differ diff --git a/docs/img/2d1845503f8ff90d4dc71459313e4e62.png b/docs/img/2d1845503f8ff90d4dc71459313e4e62.png new file mode 100644 index 0000000000000000000000000000000000000000..b32f3d1d04aaef7a24ac0739b427bca423a20f04 Binary files /dev/null and b/docs/img/2d1845503f8ff90d4dc71459313e4e62.png differ diff --git a/docs/img/2dde5152cc249727c2d1016051d52131.png b/docs/img/2dde5152cc249727c2d1016051d52131.png new file mode 100644 index 0000000000000000000000000000000000000000..2e88cc041a0ccbf9c3eaeba86f6572a9825664ee Binary files /dev/null and b/docs/img/2dde5152cc249727c2d1016051d52131.png differ diff --git a/docs/img/2e1001a11cd343049b87ebf60a315e9f.png b/docs/img/2e1001a11cd343049b87ebf60a315e9f.png new file mode 100644 index 0000000000000000000000000000000000000000..c4e3bfe3e9432a12fffd6211cb5dc9930ff0f916 Binary files /dev/null and b/docs/img/2e1001a11cd343049b87ebf60a315e9f.png differ diff --git a/docs/img/2e2c36f66667fc52b3fb3681533dcef7.png b/docs/img/2e2c36f66667fc52b3fb3681533dcef7.png new file mode 100644 index 0000000000000000000000000000000000000000..10fbe41d6f6f476a4c057bfd8a27baf152632165 Binary files /dev/null and b/docs/img/2e2c36f66667fc52b3fb3681533dcef7.png differ diff --git a/docs/img/2ed1719eefb651778ccd248f0bbe577c.png b/docs/img/2ed1719eefb651778ccd248f0bbe577c.png new file mode 100644 index 0000000000000000000000000000000000000000..dc7f37b2b774abed028a6b84ac6f857fc0db22db Binary files /dev/null and b/docs/img/2ed1719eefb651778ccd248f0bbe577c.png differ diff --git a/docs/img/2f78c411d32ee05e95a1984ef90b2356.png b/docs/img/2f78c411d32ee05e95a1984ef90b2356.png new file mode 100644 index 0000000000000000000000000000000000000000..1b85f599493c2d074b2e3c0152df3b830f87a02d Binary files /dev/null and b/docs/img/2f78c411d32ee05e95a1984ef90b2356.png differ diff --git a/docs/img/2f8e418a69825e31935272d55cceae7f.png b/docs/img/2f8e418a69825e31935272d55cceae7f.png new file mode 100644 index 0000000000000000000000000000000000000000..cf2b436579426581f0b2e281cc57a7265dda59b6 Binary files /dev/null and b/docs/img/2f8e418a69825e31935272d55cceae7f.png differ diff --git a/docs/img/2fdc2024eee83764328fb015ffd4e392.png b/docs/img/2fdc2024eee83764328fb015ffd4e392.png new file mode 100644 index 0000000000000000000000000000000000000000..9bb64605cbe9d6289d57bfa6d80a07f2c011003c Binary files /dev/null and b/docs/img/2fdc2024eee83764328fb015ffd4e392.png differ diff --git a/docs/img/2fe480e26b1b89b82607729986e5b13a.png b/docs/img/2fe480e26b1b89b82607729986e5b13a.png new file mode 100644 index 0000000000000000000000000000000000000000..8db70c71febaf3523981c7aaabe911a9658bf3d9 Binary files /dev/null and b/docs/img/2fe480e26b1b89b82607729986e5b13a.png differ diff --git a/docs/img/2fed535a429569e1ae792fb3960bcdd5.png b/docs/img/2fed535a429569e1ae792fb3960bcdd5.png new file mode 100644 index 0000000000000000000000000000000000000000..cc8f7fba523501c283eb081f563837c2592d1383 Binary files /dev/null and b/docs/img/2fed535a429569e1ae792fb3960bcdd5.png differ diff --git a/docs/img/3001efd4ffb849af0c15eb8dda4d4050.png b/docs/img/3001efd4ffb849af0c15eb8dda4d4050.png new file mode 100644 index 0000000000000000000000000000000000000000..abe345be14581776cf0baa2408b85ae44ae3c012 Binary files /dev/null and b/docs/img/3001efd4ffb849af0c15eb8dda4d4050.png differ diff --git a/docs/img/30152366655be1543f687603c8d34d96.png b/docs/img/30152366655be1543f687603c8d34d96.png new file mode 100644 index 0000000000000000000000000000000000000000..02427f1ef6ed1fe01f9bdcf696254a8ddaa563b2 Binary files /dev/null and b/docs/img/30152366655be1543f687603c8d34d96.png differ diff --git a/docs/img/30460bec4b16c49e4f5d5ccc7ac92601.png b/docs/img/30460bec4b16c49e4f5d5ccc7ac92601.png new file mode 100644 index 0000000000000000000000000000000000000000..7608284e7e2aa2e26066fc20a06bfc80afa65179 Binary files /dev/null and b/docs/img/30460bec4b16c49e4f5d5ccc7ac92601.png differ diff --git a/docs/img/31396caea61831939862213abb8dd10c.png b/docs/img/31396caea61831939862213abb8dd10c.png new file mode 100644 index 0000000000000000000000000000000000000000..e317ebb6336ba513a948d2d009f0cc79230daab0 Binary files /dev/null and b/docs/img/31396caea61831939862213abb8dd10c.png differ diff --git a/docs/img/317167b85f9604b741e71e57b1702b6c.png b/docs/img/317167b85f9604b741e71e57b1702b6c.png new file mode 100644 index 0000000000000000000000000000000000000000..a7344eae866b9d622aa48039e131270bba6fe841 Binary files /dev/null and b/docs/img/317167b85f9604b741e71e57b1702b6c.png differ diff --git a/docs/img/31c7821d41281d527a8ee4f058bafaca.png b/docs/img/31c7821d41281d527a8ee4f058bafaca.png new file mode 100644 index 0000000000000000000000000000000000000000..5fc353914478992c82178061d8f978f44df9774b Binary files /dev/null and b/docs/img/31c7821d41281d527a8ee4f058bafaca.png differ diff --git a/docs/img/31d242e54217fe005ee1481fbb81c786.png b/docs/img/31d242e54217fe005ee1481fbb81c786.png new file mode 100644 index 0000000000000000000000000000000000000000..fec656ce3902ff7576d9002fb1582238b13bebac Binary files /dev/null and b/docs/img/31d242e54217fe005ee1481fbb81c786.png differ diff --git a/docs/img/31f0a42465a379e152ef6c0c7a6395e9.png b/docs/img/31f0a42465a379e152ef6c0c7a6395e9.png new file mode 100644 index 0000000000000000000000000000000000000000..fdd7985491e9f294d07b54b515adeee0420480d6 Binary files /dev/null and b/docs/img/31f0a42465a379e152ef6c0c7a6395e9.png differ diff --git a/docs/img/31f8f986b27020e646540b9595d026cd.png b/docs/img/31f8f986b27020e646540b9595d026cd.png new file mode 100644 index 0000000000000000000000000000000000000000..72846c2b4f3425a60fc73ed27711a7708ce102cb Binary files /dev/null and b/docs/img/31f8f986b27020e646540b9595d026cd.png differ diff --git a/docs/img/3252759837ced64a222db48c62becdd3.png b/docs/img/3252759837ced64a222db48c62becdd3.png new file mode 100644 index 0000000000000000000000000000000000000000..29ddb119aca16e16f255380dc90085a31a3155f1 Binary files /dev/null and b/docs/img/3252759837ced64a222db48c62becdd3.png differ diff --git a/docs/img/3281ef5fea53e2f0a57bb3c648aa7fa4.png b/docs/img/3281ef5fea53e2f0a57bb3c648aa7fa4.png new file mode 100644 index 0000000000000000000000000000000000000000..f8ffa92a76062874828f06b0939d7f87d4e49439 Binary files /dev/null and b/docs/img/3281ef5fea53e2f0a57bb3c648aa7fa4.png differ diff --git a/docs/img/337891c1885c756f35968127a8050c21.png b/docs/img/337891c1885c756f35968127a8050c21.png new file mode 100644 index 0000000000000000000000000000000000000000..0f01bf03dd7b5e242e5fc3a37c7b3ea13df7e754 Binary files /dev/null and b/docs/img/337891c1885c756f35968127a8050c21.png differ diff --git a/docs/img/33ae5f16a8ad7c683e894a2a3032cfa9.png b/docs/img/33ae5f16a8ad7c683e894a2a3032cfa9.png new file mode 100644 index 0000000000000000000000000000000000000000..2d797aff8cf1008d769a672891031a16c322535b Binary files /dev/null and b/docs/img/33ae5f16a8ad7c683e894a2a3032cfa9.png differ diff --git a/docs/img/33c514aefa1ff87fe18907b27d473e03.png b/docs/img/33c514aefa1ff87fe18907b27d473e03.png new file mode 100644 index 0000000000000000000000000000000000000000..85c4ba8513104d3bf9b949129c7d1a767f12fb8a Binary files /dev/null and b/docs/img/33c514aefa1ff87fe18907b27d473e03.png differ diff --git a/docs/img/33cc6d96a283a4f1b3cc5b27da9fd1c4.png b/docs/img/33cc6d96a283a4f1b3cc5b27da9fd1c4.png new file mode 100644 index 0000000000000000000000000000000000000000..3536265100983f7e67620b6b594a8bbfede6aa49 Binary files /dev/null and b/docs/img/33cc6d96a283a4f1b3cc5b27da9fd1c4.png differ diff --git a/docs/img/33da6433c882c8bcc4c699a4e0008b7c.png b/docs/img/33da6433c882c8bcc4c699a4e0008b7c.png new file mode 100644 index 0000000000000000000000000000000000000000..8c0e15ee0bb2b9c03c36d6236417f087d75eb198 Binary files /dev/null and b/docs/img/33da6433c882c8bcc4c699a4e0008b7c.png differ diff --git a/docs/img/3444bd33319e0b2d996233cf9e1103c5.png b/docs/img/3444bd33319e0b2d996233cf9e1103c5.png new file mode 100644 index 0000000000000000000000000000000000000000..b6bfd6d3e94d81f3ebbd3f19b577f223ec662906 Binary files /dev/null and b/docs/img/3444bd33319e0b2d996233cf9e1103c5.png differ diff --git a/docs/img/3478cae6da4e529f7c9cf2f4e71dd462.png b/docs/img/3478cae6da4e529f7c9cf2f4e71dd462.png new file mode 100644 index 0000000000000000000000000000000000000000..602803119a6c765864114a59fb95d29023f47911 Binary files /dev/null and b/docs/img/3478cae6da4e529f7c9cf2f4e71dd462.png differ diff --git a/docs/img/35460a8c847cde5f9e477c80231d7f8b.png b/docs/img/35460a8c847cde5f9e477c80231d7f8b.png new file mode 100644 index 0000000000000000000000000000000000000000..54b0bd865dd8918bdb03ac476deb83ee743d9570 Binary files /dev/null and b/docs/img/35460a8c847cde5f9e477c80231d7f8b.png differ diff --git a/docs/img/35b66299a79c8b3212bf8fbb00e9c903.png b/docs/img/35b66299a79c8b3212bf8fbb00e9c903.png new file mode 100644 index 0000000000000000000000000000000000000000..f1bec233632ff00b4c31c4e9170faa6f8f83375e Binary files /dev/null and b/docs/img/35b66299a79c8b3212bf8fbb00e9c903.png differ diff --git a/docs/img/35e89eba4dfc37f409cb295b0c8b13d1.png b/docs/img/35e89eba4dfc37f409cb295b0c8b13d1.png new file mode 100644 index 0000000000000000000000000000000000000000..80a8f648b670473108d214a41a9a08d9b3f06945 Binary files /dev/null and b/docs/img/35e89eba4dfc37f409cb295b0c8b13d1.png differ diff --git a/docs/img/35fbd0a23d3b20913cb4490a3957d8b3.png b/docs/img/35fbd0a23d3b20913cb4490a3957d8b3.png new file mode 100644 index 0000000000000000000000000000000000000000..861eb0aba619820884a63dfd9b738979bb53ef23 Binary files /dev/null and b/docs/img/35fbd0a23d3b20913cb4490a3957d8b3.png differ diff --git a/docs/img/3601605e24186a1976e7aff09112bb7e.png b/docs/img/3601605e24186a1976e7aff09112bb7e.png new file mode 100644 index 0000000000000000000000000000000000000000..b5cecadbb2ed5ebc45645b6393add18f8c4ee4b6 Binary files /dev/null and b/docs/img/3601605e24186a1976e7aff09112bb7e.png differ diff --git a/docs/img/3636c78ef6cb3ccc1462dd451c7f3efc.png b/docs/img/3636c78ef6cb3ccc1462dd451c7f3efc.png new file mode 100644 index 0000000000000000000000000000000000000000..26d4426a1161887c53b1b26b40594808b00d89bf Binary files /dev/null and b/docs/img/3636c78ef6cb3ccc1462dd451c7f3efc.png differ diff --git a/docs/img/3667bc1901823963df25df8a2458047a.png b/docs/img/3667bc1901823963df25df8a2458047a.png new file mode 100644 index 0000000000000000000000000000000000000000..a17bb4d89ce073a4152a36f1a873a9a129fa5f34 Binary files /dev/null and b/docs/img/3667bc1901823963df25df8a2458047a.png differ diff --git a/docs/img/366832d79f753b4e66470fa923fa7acf.png b/docs/img/366832d79f753b4e66470fa923fa7acf.png new file mode 100644 index 0000000000000000000000000000000000000000..fa0f797b00a516c61d43897a6741669f18a03b07 Binary files /dev/null and b/docs/img/366832d79f753b4e66470fa923fa7acf.png differ diff --git a/docs/img/3694fc45636610ba5fb4e24d7a9eb3b9.png b/docs/img/3694fc45636610ba5fb4e24d7a9eb3b9.png new file mode 100644 index 0000000000000000000000000000000000000000..95ae04db34819d72a1a1b64656a9c21a3a786db1 Binary files /dev/null and b/docs/img/3694fc45636610ba5fb4e24d7a9eb3b9.png differ diff --git a/docs/img/36aa502eb297ed552d82e3b015053e9e.png b/docs/img/36aa502eb297ed552d82e3b015053e9e.png new file mode 100644 index 0000000000000000000000000000000000000000..bf02d33a3c0ce06423a84f3afdcd378c18506648 Binary files /dev/null and b/docs/img/36aa502eb297ed552d82e3b015053e9e.png differ diff --git a/docs/img/36abd47af07b3b82f814e74be4619b4d.png b/docs/img/36abd47af07b3b82f814e74be4619b4d.png new file mode 100644 index 0000000000000000000000000000000000000000..7c4e7b98375de43b34b0d63ea3932920d4c3adeb Binary files /dev/null and b/docs/img/36abd47af07b3b82f814e74be4619b4d.png differ diff --git a/docs/img/36d97eaa1e64c3f6d5b78d205d1ce881.png b/docs/img/36d97eaa1e64c3f6d5b78d205d1ce881.png new file mode 100644 index 0000000000000000000000000000000000000000..19678b9eca43b4d7074728385a3b95a950aa384b Binary files /dev/null and b/docs/img/36d97eaa1e64c3f6d5b78d205d1ce881.png differ diff --git a/docs/img/370ac43323901b08b905644b04f6a802.png b/docs/img/370ac43323901b08b905644b04f6a802.png new file mode 100644 index 0000000000000000000000000000000000000000..42004b0e4af4744918033f65463b78c9d884afee Binary files /dev/null and b/docs/img/370ac43323901b08b905644b04f6a802.png differ diff --git a/docs/img/371d1ca1640afbd824acc19b18bc40c9.png b/docs/img/371d1ca1640afbd824acc19b18bc40c9.png new file mode 100644 index 0000000000000000000000000000000000000000..73560de7cc40d1134ff72d7263ed25528e1264b4 Binary files /dev/null and b/docs/img/371d1ca1640afbd824acc19b18bc40c9.png differ diff --git a/docs/img/37238acd557de0d61f0c3be198c56e00.png b/docs/img/37238acd557de0d61f0c3be198c56e00.png new file mode 100644 index 0000000000000000000000000000000000000000..e341b0f77e04b0957b65db19ea8d067f8286f73b Binary files /dev/null and b/docs/img/37238acd557de0d61f0c3be198c56e00.png differ diff --git a/docs/img/3794ce06aeeb9528fa1a66915cc69072.png b/docs/img/3794ce06aeeb9528fa1a66915cc69072.png new file mode 100644 index 0000000000000000000000000000000000000000..9aaa5b706eb91613c1106a375f042f5c878f01d5 Binary files /dev/null and b/docs/img/3794ce06aeeb9528fa1a66915cc69072.png differ diff --git a/docs/img/379bd77b46dd7f0617bc273a203c9a29.png b/docs/img/379bd77b46dd7f0617bc273a203c9a29.png new file mode 100644 index 0000000000000000000000000000000000000000..6450710ce821284eee7e3c9afe6575179543bf5e Binary files /dev/null and b/docs/img/379bd77b46dd7f0617bc273a203c9a29.png differ diff --git a/docs/img/37cb6e38ded4ec606f9bc7776f765e70.png b/docs/img/37cb6e38ded4ec606f9bc7776f765e70.png new file mode 100644 index 0000000000000000000000000000000000000000..fd65a3239b0d2115daf1a864d37fdc22a4d2e0ae Binary files /dev/null and b/docs/img/37cb6e38ded4ec606f9bc7776f765e70.png differ diff --git a/docs/img/381000c5f5c6ad01300dfcc889f7fb0f.png b/docs/img/381000c5f5c6ad01300dfcc889f7fb0f.png new file mode 100644 index 0000000000000000000000000000000000000000..a181912af9fe3aa360e512a8d8ce0a383c5f26c8 Binary files /dev/null and b/docs/img/381000c5f5c6ad01300dfcc889f7fb0f.png differ diff --git a/docs/img/381cb6fd4ceed7b2a8b3642926cb8cf2.png b/docs/img/381cb6fd4ceed7b2a8b3642926cb8cf2.png new file mode 100644 index 0000000000000000000000000000000000000000..9ca4ae0df687f40a0a4f8fa91c23c38ad38cfb57 Binary files /dev/null and b/docs/img/381cb6fd4ceed7b2a8b3642926cb8cf2.png differ diff --git a/docs/img/3863add8513c90ad786112f7a200a568.png b/docs/img/3863add8513c90ad786112f7a200a568.png new file mode 100644 index 0000000000000000000000000000000000000000..5bbf935b3eaf0253399bd26f34128b8b1f432634 Binary files /dev/null and b/docs/img/3863add8513c90ad786112f7a200a568.png differ diff --git a/docs/img/3887423740965d20eecf9471bc1b3061.png b/docs/img/3887423740965d20eecf9471bc1b3061.png new file mode 100644 index 0000000000000000000000000000000000000000..dd8f69b624f4627101f9e0be00d1388c0c0153e4 Binary files /dev/null and b/docs/img/3887423740965d20eecf9471bc1b3061.png differ diff --git a/docs/img/38c073cc1c78dc88bf317e878e9995cc.png b/docs/img/38c073cc1c78dc88bf317e878e9995cc.png new file mode 100644 index 0000000000000000000000000000000000000000..05982c8a4b0b660c92556a918425973ea5a9f03e Binary files /dev/null and b/docs/img/38c073cc1c78dc88bf317e878e9995cc.png differ diff --git a/docs/img/38d4db85b589523cbab105da53e5fb09.png b/docs/img/38d4db85b589523cbab105da53e5fb09.png new file mode 100644 index 0000000000000000000000000000000000000000..b8ca0aa9b4ca631fc3904a5e3abc1b0612c6f9b7 Binary files /dev/null and b/docs/img/38d4db85b589523cbab105da53e5fb09.png differ diff --git a/docs/img/38ef5bf427869fe9b1050db6eacd2972.png b/docs/img/38ef5bf427869fe9b1050db6eacd2972.png new file mode 100644 index 0000000000000000000000000000000000000000..29b0ff1e55a0bda29f8d3b49ad76330f000e3ed1 Binary files /dev/null and b/docs/img/38ef5bf427869fe9b1050db6eacd2972.png differ diff --git a/docs/img/393dab24a6c8be1031a4cf469f3039e9.png b/docs/img/393dab24a6c8be1031a4cf469f3039e9.png new file mode 100644 index 0000000000000000000000000000000000000000..96fd20332578bac20636ab8d15343d1d4886d687 Binary files /dev/null and b/docs/img/393dab24a6c8be1031a4cf469f3039e9.png differ diff --git a/docs/img/39b4809628ba97edb93621d6eefa5135.png b/docs/img/39b4809628ba97edb93621d6eefa5135.png new file mode 100644 index 0000000000000000000000000000000000000000..472fbc63083eacaa443a70364615140d1f8c5103 Binary files /dev/null and b/docs/img/39b4809628ba97edb93621d6eefa5135.png differ diff --git a/docs/img/3a328cbf9c83e567fa5921d3580a84cb.png b/docs/img/3a328cbf9c83e567fa5921d3580a84cb.png new file mode 100644 index 0000000000000000000000000000000000000000..da7c9c006208efed4f144b511871a9b43e074f59 Binary files /dev/null and b/docs/img/3a328cbf9c83e567fa5921d3580a84cb.png differ diff --git a/docs/img/3b13f587681dd3391c82eb9b650ff6cf.png b/docs/img/3b13f587681dd3391c82eb9b650ff6cf.png new file mode 100644 index 0000000000000000000000000000000000000000..2c9f40ec7d093cde98a5c833c4055c8ff21a8951 Binary files /dev/null and b/docs/img/3b13f587681dd3391c82eb9b650ff6cf.png differ diff --git a/docs/img/3b33bfa40900241891ce4c916e441a22.png b/docs/img/3b33bfa40900241891ce4c916e441a22.png new file mode 100644 index 0000000000000000000000000000000000000000..9e5c8a8406049ae9c89ddb2f9cb8ca19ed99f698 Binary files /dev/null and b/docs/img/3b33bfa40900241891ce4c916e441a22.png differ diff --git a/docs/img/3b3e644f832753a09f245236299e74b2.png b/docs/img/3b3e644f832753a09f245236299e74b2.png new file mode 100644 index 0000000000000000000000000000000000000000..35a42ddd164a41c56172c244d9b0c13b8b8bc121 Binary files /dev/null and b/docs/img/3b3e644f832753a09f245236299e74b2.png differ diff --git a/docs/img/3b8b0bcac599d7207d90ed8194bed83e.png b/docs/img/3b8b0bcac599d7207d90ed8194bed83e.png new file mode 100644 index 0000000000000000000000000000000000000000..c804c7e4253f9de349dfe0d79e0e98fc854a81fd Binary files /dev/null and b/docs/img/3b8b0bcac599d7207d90ed8194bed83e.png differ diff --git a/docs/img/3c9cb466046f19c70255f0de753a307c.png b/docs/img/3c9cb466046f19c70255f0de753a307c.png new file mode 100644 index 0000000000000000000000000000000000000000..6e40db206ad9095cfeda5278d6fde39cea477703 Binary files /dev/null and b/docs/img/3c9cb466046f19c70255f0de753a307c.png differ diff --git a/docs/img/3ca3bc9234ff248b19d9555bb5f1cff4.png b/docs/img/3ca3bc9234ff248b19d9555bb5f1cff4.png new file mode 100644 index 0000000000000000000000000000000000000000..6ce63e5e1a18b1e472b251e02385a650cc07b13d Binary files /dev/null and b/docs/img/3ca3bc9234ff248b19d9555bb5f1cff4.png differ diff --git a/docs/img/3d8b21038a5aa14baa75dc65de55d728.png b/docs/img/3d8b21038a5aa14baa75dc65de55d728.png new file mode 100644 index 0000000000000000000000000000000000000000..468a61588e6a0435ee5bcb0f0114f937845c0cc6 Binary files /dev/null and b/docs/img/3d8b21038a5aa14baa75dc65de55d728.png differ diff --git a/docs/img/3da5d65194b00f9dc3ffde2ac5f8473b.png b/docs/img/3da5d65194b00f9dc3ffde2ac5f8473b.png new file mode 100644 index 0000000000000000000000000000000000000000..590e7e732848ca92d436cd5c329e9235b9f29179 Binary files /dev/null and b/docs/img/3da5d65194b00f9dc3ffde2ac5f8473b.png differ diff --git a/docs/img/3e0f74f35030a15b593a12090d5c0daf.png b/docs/img/3e0f74f35030a15b593a12090d5c0daf.png new file mode 100644 index 0000000000000000000000000000000000000000..9994bb1c1e21c2bbf2c899bec94bb14ada590b84 Binary files /dev/null and b/docs/img/3e0f74f35030a15b593a12090d5c0daf.png differ diff --git a/docs/img/3e903eab58c2b1ac777ef30adf3bd44e.png b/docs/img/3e903eab58c2b1ac777ef30adf3bd44e.png new file mode 100644 index 0000000000000000000000000000000000000000..afb7c9dc6fdb021afdccf979a97a4c905902f3ff Binary files /dev/null and b/docs/img/3e903eab58c2b1ac777ef30adf3bd44e.png differ diff --git a/docs/img/3ed7ccf7499687536cf254fc6f47d5e7.png b/docs/img/3ed7ccf7499687536cf254fc6f47d5e7.png new file mode 100644 index 0000000000000000000000000000000000000000..2ff325ce930d69b20cd5b5b3f1c5da797574aeef Binary files /dev/null and b/docs/img/3ed7ccf7499687536cf254fc6f47d5e7.png differ diff --git a/docs/img/3f64ac42c5324a759f292fa0f7e4d991.png b/docs/img/3f64ac42c5324a759f292fa0f7e4d991.png new file mode 100644 index 0000000000000000000000000000000000000000..e7eb30292573aa947599ceb45944e0a7e24e9af9 Binary files /dev/null and b/docs/img/3f64ac42c5324a759f292fa0f7e4d991.png differ diff --git a/docs/img/40834a63780a362f429e1902450a4a7a.png b/docs/img/40834a63780a362f429e1902450a4a7a.png new file mode 100644 index 0000000000000000000000000000000000000000..048ae91c8aa8a292e7a378b792d735f4ac3c134c Binary files /dev/null and b/docs/img/40834a63780a362f429e1902450a4a7a.png differ diff --git a/docs/img/40cd53294c496a4d049d735386c16649.png b/docs/img/40cd53294c496a4d049d735386c16649.png new file mode 100644 index 0000000000000000000000000000000000000000..ff399e26e73ff2e7cc8dcdac352c10426b6cfda6 Binary files /dev/null and b/docs/img/40cd53294c496a4d049d735386c16649.png differ diff --git a/docs/img/40dbd9d2f1f965f42a1c417a258da575.png b/docs/img/40dbd9d2f1f965f42a1c417a258da575.png new file mode 100644 index 0000000000000000000000000000000000000000..b812d331538353d6214a60a297145b1792b6d012 Binary files /dev/null and b/docs/img/40dbd9d2f1f965f42a1c417a258da575.png differ diff --git a/docs/img/41371f9efeaf03eb888ba8e19a486185.png b/docs/img/41371f9efeaf03eb888ba8e19a486185.png new file mode 100644 index 0000000000000000000000000000000000000000..65629737050a6e8ee31ceecc50337ea97bc59526 Binary files /dev/null and b/docs/img/41371f9efeaf03eb888ba8e19a486185.png differ diff --git a/docs/img/41571e3a155c671e6ff9f259f20fdeed.png b/docs/img/41571e3a155c671e6ff9f259f20fdeed.png new file mode 100644 index 0000000000000000000000000000000000000000..701e46d8e30c0fa2b6888286394bbb4758393008 Binary files /dev/null and b/docs/img/41571e3a155c671e6ff9f259f20fdeed.png differ diff --git a/docs/img/423e566cce1da11ef163c69219f870aa.png b/docs/img/423e566cce1da11ef163c69219f870aa.png new file mode 100644 index 0000000000000000000000000000000000000000..0733c5a6f159860628dbf3ce8a15faf82213fff1 Binary files /dev/null and b/docs/img/423e566cce1da11ef163c69219f870aa.png differ diff --git a/docs/img/423fb353db83bd90502f2f029c398e43.png b/docs/img/423fb353db83bd90502f2f029c398e43.png new file mode 100644 index 0000000000000000000000000000000000000000..4c1d25258fc6ed99ee8144d92b6f460f64160776 Binary files /dev/null and b/docs/img/423fb353db83bd90502f2f029c398e43.png differ diff --git a/docs/img/429e9751a8b0336bb8b7e3faab15a373.png b/docs/img/429e9751a8b0336bb8b7e3faab15a373.png new file mode 100644 index 0000000000000000000000000000000000000000..7947c534408383f8452c4be4a86bffa0a7b480a2 Binary files /dev/null and b/docs/img/429e9751a8b0336bb8b7e3faab15a373.png differ diff --git a/docs/img/439a9c21f68de25b8a16d0d0a28d19be.png b/docs/img/439a9c21f68de25b8a16d0d0a28d19be.png new file mode 100644 index 0000000000000000000000000000000000000000..46830b65782e2e0aaf4ad03b583ad2cb77a161ad Binary files /dev/null and b/docs/img/439a9c21f68de25b8a16d0d0a28d19be.png differ diff --git a/docs/img/43a1d5a081bb166e1d43d6e671f250e1.png b/docs/img/43a1d5a081bb166e1d43d6e671f250e1.png new file mode 100644 index 0000000000000000000000000000000000000000..8ce373b96c3272728188b87087c562b1fb284913 Binary files /dev/null and b/docs/img/43a1d5a081bb166e1d43d6e671f250e1.png differ diff --git a/docs/img/43c1d4f646051452c436962222af114b.png b/docs/img/43c1d4f646051452c436962222af114b.png new file mode 100644 index 0000000000000000000000000000000000000000..1501a74a429981334cc1b2a99842a5c5ee95d724 Binary files /dev/null and b/docs/img/43c1d4f646051452c436962222af114b.png differ diff --git a/docs/img/4401376aa4e3f3764851b2dbb25f6f2e.png b/docs/img/4401376aa4e3f3764851b2dbb25f6f2e.png new file mode 100644 index 0000000000000000000000000000000000000000..704264fc13925dcf1a4d4c9c58d4f23ba8025fda Binary files /dev/null and b/docs/img/4401376aa4e3f3764851b2dbb25f6f2e.png differ diff --git a/docs/img/441419241245b159818b469c6508f227.png b/docs/img/441419241245b159818b469c6508f227.png new file mode 100644 index 0000000000000000000000000000000000000000..f41e0b9750581f49a5763839fc859852b8ac1ec1 Binary files /dev/null and b/docs/img/441419241245b159818b469c6508f227.png differ diff --git a/docs/img/44be1cce97f886ea1f1c93950d764041.png b/docs/img/44be1cce97f886ea1f1c93950d764041.png new file mode 100644 index 0000000000000000000000000000000000000000..f332b2c6c3887b2ba033ed93093739d941a43870 Binary files /dev/null and b/docs/img/44be1cce97f886ea1f1c93950d764041.png differ diff --git a/docs/img/44cad341f814ae94da18480c3dc1d2be.png b/docs/img/44cad341f814ae94da18480c3dc1d2be.png new file mode 100644 index 0000000000000000000000000000000000000000..952cdda943097316d7a7964916aec1f1f75cd70b Binary files /dev/null and b/docs/img/44cad341f814ae94da18480c3dc1d2be.png differ diff --git a/docs/img/44dfa1e85103f88c82598a4ef9f8d0ae.png b/docs/img/44dfa1e85103f88c82598a4ef9f8d0ae.png new file mode 100644 index 0000000000000000000000000000000000000000..fc9d98adc4d60019d16a879e1cf217e6da4933cb Binary files /dev/null and b/docs/img/44dfa1e85103f88c82598a4ef9f8d0ae.png differ diff --git a/docs/img/45586bacf83042f9bfcdb01d5576fe3c.png b/docs/img/45586bacf83042f9bfcdb01d5576fe3c.png new file mode 100644 index 0000000000000000000000000000000000000000..244beddcaf634bf7ca68eed4c3a008e4449a9c9e --- /dev/null +++ b/docs/img/45586bacf83042f9bfcdb01d5576fe3c.png @@ -0,0 +1 @@ +<svg width="1170" height="638" viewBox="0 0 1170 638" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>review-apps-CD-outlinedCreated with Sketch. \ No newline at end of file diff --git a/docs/img/45974f94466502ace734ecc3473a0d58.png b/docs/img/45974f94466502ace734ecc3473a0d58.png new file mode 100644 index 0000000000000000000000000000000000000000..355e140c0307c46f05c33c67f84d77d417a11a00 Binary files /dev/null and b/docs/img/45974f94466502ace734ecc3473a0d58.png differ diff --git a/docs/img/45c66aeb387e650cfe717047d1b78263.png b/docs/img/45c66aeb387e650cfe717047d1b78263.png new file mode 100644 index 0000000000000000000000000000000000000000..0d7a1886fa7152c80e1e9fbc6f95278cb61f23a4 Binary files /dev/null and b/docs/img/45c66aeb387e650cfe717047d1b78263.png differ diff --git a/docs/img/45cb073d466ec4a6fcb5a09d7f5f204c.png b/docs/img/45cb073d466ec4a6fcb5a09d7f5f204c.png new file mode 100644 index 0000000000000000000000000000000000000000..97d39d07c116ad04a150e39935d5d115f9c6ae75 Binary files /dev/null and b/docs/img/45cb073d466ec4a6fcb5a09d7f5f204c.png differ diff --git a/docs/img/45cc34490ebcb0a656d7c57d3dcbbb00.png b/docs/img/45cc34490ebcb0a656d7c57d3dcbbb00.png new file mode 100644 index 0000000000000000000000000000000000000000..c0728e037be73c3faa1bb3987d15dd51efa8d22b Binary files /dev/null and b/docs/img/45cc34490ebcb0a656d7c57d3dcbbb00.png differ diff --git a/docs/img/46322215ec68c4896b6b622f9f1ad11e.png b/docs/img/46322215ec68c4896b6b622f9f1ad11e.png new file mode 100644 index 0000000000000000000000000000000000000000..7b1eff620521af7c6d85ad1b905439c55643c4f6 Binary files /dev/null and b/docs/img/46322215ec68c4896b6b622f9f1ad11e.png differ diff --git a/docs/img/4635aba96009dfb3ab93ab6f4b92ee4c.png b/docs/img/4635aba96009dfb3ab93ab6f4b92ee4c.png new file mode 100644 index 0000000000000000000000000000000000000000..cc70962d2301ec8b4ed97d2ba23c47b84c0d9ed2 Binary files /dev/null and b/docs/img/4635aba96009dfb3ab93ab6f4b92ee4c.png differ diff --git a/docs/img/468eb44e935f615292705e2fc013ddb7.png b/docs/img/468eb44e935f615292705e2fc013ddb7.png new file mode 100644 index 0000000000000000000000000000000000000000..107dbef7e22b9ce82db416213e610f12904845a9 Binary files /dev/null and b/docs/img/468eb44e935f615292705e2fc013ddb7.png differ diff --git a/docs/img/471bcfe6a44b22703662997289b517c9.png b/docs/img/471bcfe6a44b22703662997289b517c9.png new file mode 100644 index 0000000000000000000000000000000000000000..81dbe1345cab372bc3a6c7181c8524cec2e5fbb0 Binary files /dev/null and b/docs/img/471bcfe6a44b22703662997289b517c9.png differ diff --git a/docs/img/47c6e09feffe93d1d9f758d50837b31b.png b/docs/img/47c6e09feffe93d1d9f758d50837b31b.png new file mode 100644 index 0000000000000000000000000000000000000000..f4654eb8202f15128d6d66dc031f99661764fe0d Binary files /dev/null and b/docs/img/47c6e09feffe93d1d9f758d50837b31b.png differ diff --git a/docs/img/481f18ff2e4575d1c38d4c93631bd23c.png b/docs/img/481f18ff2e4575d1c38d4c93631bd23c.png new file mode 100644 index 0000000000000000000000000000000000000000..c589ba482f4b7bbc80005484480113fdb87e3083 Binary files /dev/null and b/docs/img/481f18ff2e4575d1c38d4c93631bd23c.png differ diff --git a/docs/img/482b8e23d226428516ae20fae41ca7cf.png b/docs/img/482b8e23d226428516ae20fae41ca7cf.png new file mode 100644 index 0000000000000000000000000000000000000000..48ac0114732df1fb528c383dc4307c07a16f82fe Binary files /dev/null and b/docs/img/482b8e23d226428516ae20fae41ca7cf.png differ diff --git a/docs/img/48482b1410caf250f0257d772e55c544.png b/docs/img/48482b1410caf250f0257d772e55c544.png new file mode 100644 index 0000000000000000000000000000000000000000..82049a741f5916c0653096cbc352cf8dae67f19e Binary files /dev/null and b/docs/img/48482b1410caf250f0257d772e55c544.png differ diff --git a/docs/img/486761bb835c9408dac03956a04b3a53.png b/docs/img/486761bb835c9408dac03956a04b3a53.png new file mode 100644 index 0000000000000000000000000000000000000000..1e5363eb1cd6e9b96c40cc2a2e576ad4bf773956 Binary files /dev/null and b/docs/img/486761bb835c9408dac03956a04b3a53.png differ diff --git a/docs/img/49588b733704d134418744f910f7809b.png b/docs/img/49588b733704d134418744f910f7809b.png new file mode 100644 index 0000000000000000000000000000000000000000..296afe63b76a03890a657532232f3fc4476626dd Binary files /dev/null and b/docs/img/49588b733704d134418744f910f7809b.png differ diff --git a/docs/img/49d46d08d1ca6c3cd3d0b0ef98472512.png b/docs/img/49d46d08d1ca6c3cd3d0b0ef98472512.png new file mode 100644 index 0000000000000000000000000000000000000000..274cff5c80ad087f8f53c56f678e2d9035039d3f Binary files /dev/null and b/docs/img/49d46d08d1ca6c3cd3d0b0ef98472512.png differ diff --git a/docs/img/4a007f26d24f09e03b3bb388bd94ae30.png b/docs/img/4a007f26d24f09e03b3bb388bd94ae30.png new file mode 100644 index 0000000000000000000000000000000000000000..5d51855da45212cc1f43d79af3c4207ed3e89c93 Binary files /dev/null and b/docs/img/4a007f26d24f09e03b3bb388bd94ae30.png differ diff --git a/docs/img/4a3c28657f884da12667bc861ea60e0c.png b/docs/img/4a3c28657f884da12667bc861ea60e0c.png new file mode 100644 index 0000000000000000000000000000000000000000..83942b4fe6b308a85d2fbc8aad4c6d7ce240d65c Binary files /dev/null and b/docs/img/4a3c28657f884da12667bc861ea60e0c.png differ diff --git a/docs/img/4a7c845c8d7b28d90af5923b08fb1e1d.png b/docs/img/4a7c845c8d7b28d90af5923b08fb1e1d.png new file mode 100644 index 0000000000000000000000000000000000000000..3f407a5288dab5d4dbc71f6c34386c649d2650ff Binary files /dev/null and b/docs/img/4a7c845c8d7b28d90af5923b08fb1e1d.png differ diff --git a/docs/img/4ab2d185d65e76a0d58ad6564dff777a.png b/docs/img/4ab2d185d65e76a0d58ad6564dff777a.png new file mode 100644 index 0000000000000000000000000000000000000000..d25041658866379d42f100f6cd9272a20b662139 Binary files /dev/null and b/docs/img/4ab2d185d65e76a0d58ad6564dff777a.png differ diff --git a/docs/img/4b690260474eb340f7b3f6d25b0568d2.png b/docs/img/4b690260474eb340f7b3f6d25b0568d2.png new file mode 100644 index 0000000000000000000000000000000000000000..34b07412474b4022a3220baf450e977d2b516df3 Binary files /dev/null and b/docs/img/4b690260474eb340f7b3f6d25b0568d2.png differ diff --git a/docs/img/4b803fd891a7ec7f422522d2ff185864.png b/docs/img/4b803fd891a7ec7f422522d2ff185864.png new file mode 100644 index 0000000000000000000000000000000000000000..edadad37cba80ff392e8a8fff946ed09fbb958d1 Binary files /dev/null and b/docs/img/4b803fd891a7ec7f422522d2ff185864.png differ diff --git a/docs/img/4c0cef07da8190af4f517bd8d336cb5b.png b/docs/img/4c0cef07da8190af4f517bd8d336cb5b.png new file mode 100644 index 0000000000000000000000000000000000000000..2810ad6f3029211062c3a0452bf58c6321c33396 Binary files /dev/null and b/docs/img/4c0cef07da8190af4f517bd8d336cb5b.png differ diff --git a/docs/img/4c34240e5c09caa62a018e3d109c1ba3.png b/docs/img/4c34240e5c09caa62a018e3d109c1ba3.png new file mode 100644 index 0000000000000000000000000000000000000000..e735937348aa610e2e468166b28d449ab15776b0 Binary files /dev/null and b/docs/img/4c34240e5c09caa62a018e3d109c1ba3.png differ diff --git a/docs/img/4c6172d095020a91bcf8d48c85ee4d1d.png b/docs/img/4c6172d095020a91bcf8d48c85ee4d1d.png new file mode 100644 index 0000000000000000000000000000000000000000..f4c9d21982672113dcbdef752c1bccd7cb177ac6 Binary files /dev/null and b/docs/img/4c6172d095020a91bcf8d48c85ee4d1d.png differ diff --git a/docs/img/4ceccc7ae590a56e8b135fa8baaafabe.png b/docs/img/4ceccc7ae590a56e8b135fa8baaafabe.png new file mode 100644 index 0000000000000000000000000000000000000000..e9b8c9588ed05cffe8fc79b3424f47eced97575c Binary files /dev/null and b/docs/img/4ceccc7ae590a56e8b135fa8baaafabe.png differ diff --git a/docs/img/4d2f841f1dee2bdbbdcd14bd5518c000.png b/docs/img/4d2f841f1dee2bdbbdcd14bd5518c000.png new file mode 100644 index 0000000000000000000000000000000000000000..82d6e46bd52b599d4d86982552edfd65f38b3594 Binary files /dev/null and b/docs/img/4d2f841f1dee2bdbbdcd14bd5518c000.png differ diff --git a/docs/img/4d5fab6dd3f65351ba798d87517db0bd.png b/docs/img/4d5fab6dd3f65351ba798d87517db0bd.png new file mode 100644 index 0000000000000000000000000000000000000000..3dea589160bdb4ba364fb7a6e0c15066932c754d Binary files /dev/null and b/docs/img/4d5fab6dd3f65351ba798d87517db0bd.png differ diff --git a/docs/img/4d9fbb6b23cf91f72dd201cf3a52f475.png b/docs/img/4d9fbb6b23cf91f72dd201cf3a52f475.png new file mode 100644 index 0000000000000000000000000000000000000000..4ce6be22a002fa19c8f7d0cf01c1cecfacbdfb82 Binary files /dev/null and b/docs/img/4d9fbb6b23cf91f72dd201cf3a52f475.png differ diff --git a/docs/img/4e0797b4100df465293bf0c8f24a097b.png b/docs/img/4e0797b4100df465293bf0c8f24a097b.png new file mode 100644 index 0000000000000000000000000000000000000000..b0c1400ee28b3d6da29c1ecdba61669d11eb65d4 Binary files /dev/null and b/docs/img/4e0797b4100df465293bf0c8f24a097b.png differ diff --git a/docs/img/4e480a29eb679b62ed97f748fc9acdd7.png b/docs/img/4e480a29eb679b62ed97f748fc9acdd7.png new file mode 100644 index 0000000000000000000000000000000000000000..d1b1e575663a37a18dcfad7e076abac6846ad844 Binary files /dev/null and b/docs/img/4e480a29eb679b62ed97f748fc9acdd7.png differ diff --git a/docs/img/4e86bb665dcf8b8997d807441dbd60cd.png b/docs/img/4e86bb665dcf8b8997d807441dbd60cd.png new file mode 100644 index 0000000000000000000000000000000000000000..32fe50d985b88ae8b237ec36ce64529d5b7fbf1a Binary files /dev/null and b/docs/img/4e86bb665dcf8b8997d807441dbd60cd.png differ diff --git a/docs/img/4e980984ef171e4c624f56ebeb3277c7.png b/docs/img/4e980984ef171e4c624f56ebeb3277c7.png new file mode 100644 index 0000000000000000000000000000000000000000..3ec7cba088d0fd1b79e713221dadbfa55deeab65 Binary files /dev/null and b/docs/img/4e980984ef171e4c624f56ebeb3277c7.png differ diff --git a/docs/img/4f0a47acf91c1135738d76e1c06eec3a.png b/docs/img/4f0a47acf91c1135738d76e1c06eec3a.png new file mode 100644 index 0000000000000000000000000000000000000000..024ca50a098db419eead35d0ea679ec7098cadb3 Binary files /dev/null and b/docs/img/4f0a47acf91c1135738d76e1c06eec3a.png differ diff --git a/docs/img/4f9a7d54cb4f539c606eaef8fd65b8ed.png b/docs/img/4f9a7d54cb4f539c606eaef8fd65b8ed.png new file mode 100644 index 0000000000000000000000000000000000000000..9ecad83db4b5184b6c94598b3d41b783e6a838f0 Binary files /dev/null and b/docs/img/4f9a7d54cb4f539c606eaef8fd65b8ed.png differ diff --git a/docs/img/4feb8b1885ea3a6c0945d7d32d15e8ff.png b/docs/img/4feb8b1885ea3a6c0945d7d32d15e8ff.png new file mode 100644 index 0000000000000000000000000000000000000000..bd7a68351d5c4c07accfd056e98f41d66afba514 Binary files /dev/null and b/docs/img/4feb8b1885ea3a6c0945d7d32d15e8ff.png differ diff --git a/docs/img/4ffe26c8f949643669a5c295958616cf.png b/docs/img/4ffe26c8f949643669a5c295958616cf.png new file mode 100644 index 0000000000000000000000000000000000000000..09c92c333a0c3656b89df03208ca75104dfb7a30 Binary files /dev/null and b/docs/img/4ffe26c8f949643669a5c295958616cf.png differ diff --git a/docs/img/5016b6014148674f85d6fdba7bc5bb5e.png b/docs/img/5016b6014148674f85d6fdba7bc5bb5e.png new file mode 100644 index 0000000000000000000000000000000000000000..9d2c0e45da15f3a5c47fcda3aef00f385be6a2ef Binary files /dev/null and b/docs/img/5016b6014148674f85d6fdba7bc5bb5e.png differ diff --git a/docs/img/50ab118d473b61d3d08773d6ea65a8ac.png b/docs/img/50ab118d473b61d3d08773d6ea65a8ac.png new file mode 100644 index 0000000000000000000000000000000000000000..384dbd88dd2267200b26dc81bb0136135a2a432e Binary files /dev/null and b/docs/img/50ab118d473b61d3d08773d6ea65a8ac.png differ diff --git a/docs/img/50ffc4ae0babeef44a73e82cfe49bb30.png b/docs/img/50ffc4ae0babeef44a73e82cfe49bb30.png new file mode 100644 index 0000000000000000000000000000000000000000..1504f0712c917e8ebd97d2cab6a0c15694dc71b6 Binary files /dev/null and b/docs/img/50ffc4ae0babeef44a73e82cfe49bb30.png differ diff --git a/docs/img/510cd4b11aa5f23be76d594a9ad782d6.png b/docs/img/510cd4b11aa5f23be76d594a9ad782d6.png new file mode 100644 index 0000000000000000000000000000000000000000..c907e65f59f78319c7416f289bd3a394aab8a814 Binary files /dev/null and b/docs/img/510cd4b11aa5f23be76d594a9ad782d6.png differ diff --git a/docs/img/5113c12752dd029f29a28c6f0660cde1.png b/docs/img/5113c12752dd029f29a28c6f0660cde1.png new file mode 100644 index 0000000000000000000000000000000000000000..8db5d2e0416895c68b358b927531ef5a658b9ccc Binary files /dev/null and b/docs/img/5113c12752dd029f29a28c6f0660cde1.png differ diff --git a/docs/img/51192310b3785dec5f60b6d59717a7a6.png b/docs/img/51192310b3785dec5f60b6d59717a7a6.png new file mode 100644 index 0000000000000000000000000000000000000000..300be9cce286c5e12bb493edced4251b091d7b58 Binary files /dev/null and b/docs/img/51192310b3785dec5f60b6d59717a7a6.png differ diff --git a/docs/img/517f5b10646cf257d0fd0413cb54c3e9.png b/docs/img/517f5b10646cf257d0fd0413cb54c3e9.png new file mode 100644 index 0000000000000000000000000000000000000000..52fc966bb33432537ecf368144464e5353a0c2bb Binary files /dev/null and b/docs/img/517f5b10646cf257d0fd0413cb54c3e9.png differ diff --git a/docs/img/51902d01ed097ad499a4e6eb984d3e86.png b/docs/img/51902d01ed097ad499a4e6eb984d3e86.png new file mode 100644 index 0000000000000000000000000000000000000000..21ddda0d370302bcad2646b1866aa2b7b09e0d6a Binary files /dev/null and b/docs/img/51902d01ed097ad499a4e6eb984d3e86.png differ diff --git a/docs/img/51e7561422b1e74237ea14e916cffc78.png b/docs/img/51e7561422b1e74237ea14e916cffc78.png new file mode 100644 index 0000000000000000000000000000000000000000..216fe176c405480562a31c5cec62dbb76daa6d85 Binary files /dev/null and b/docs/img/51e7561422b1e74237ea14e916cffc78.png differ diff --git a/docs/img/5262199c26e59a11bfa467901c29122a.png b/docs/img/5262199c26e59a11bfa467901c29122a.png new file mode 100644 index 0000000000000000000000000000000000000000..fad3ae5c6cc674e951d298491e05aa8b1bd2b55e Binary files /dev/null and b/docs/img/5262199c26e59a11bfa467901c29122a.png differ diff --git a/docs/img/529405d6cc5cbeb813be69b57b0e45b1.png b/docs/img/529405d6cc5cbeb813be69b57b0e45b1.png new file mode 100644 index 0000000000000000000000000000000000000000..e2737b77dcf26f671567e6cdccd963ecf195b188 Binary files /dev/null and b/docs/img/529405d6cc5cbeb813be69b57b0e45b1.png differ diff --git a/docs/img/52c8f25cfabbe64b4ed7e579d9a27e4a.png b/docs/img/52c8f25cfabbe64b4ed7e579d9a27e4a.png new file mode 100644 index 0000000000000000000000000000000000000000..184e714a14109a58d490b016e295250500f431ae Binary files /dev/null and b/docs/img/52c8f25cfabbe64b4ed7e579d9a27e4a.png differ diff --git a/docs/img/52f1314a06269a0dc317f758c8e8cdab.png b/docs/img/52f1314a06269a0dc317f758c8e8cdab.png new file mode 100644 index 0000000000000000000000000000000000000000..eedc20587bc138b551ceefdb14822bebd727c5af Binary files /dev/null and b/docs/img/52f1314a06269a0dc317f758c8e8cdab.png differ diff --git a/docs/img/52fecb33c2f168630e9a8f7c95aaf517.png b/docs/img/52fecb33c2f168630e9a8f7c95aaf517.png new file mode 100644 index 0000000000000000000000000000000000000000..ce88b751e9430c5e24b545ed6c063fbe7c96c13a Binary files /dev/null and b/docs/img/52fecb33c2f168630e9a8f7c95aaf517.png differ diff --git a/docs/img/53056397d59c4378696296d359f20adc.png b/docs/img/53056397d59c4378696296d359f20adc.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec0d2cefea8de2add9c215c5d2714914bfc55a7 Binary files /dev/null and b/docs/img/53056397d59c4378696296d359f20adc.png differ diff --git a/docs/img/53bcd8c2d2c69aceb7db6677802be6b1.png b/docs/img/53bcd8c2d2c69aceb7db6677802be6b1.png new file mode 100644 index 0000000000000000000000000000000000000000..f6b1c1561b0dd9e540a700e2865ed690f4fee79e Binary files /dev/null and b/docs/img/53bcd8c2d2c69aceb7db6677802be6b1.png differ diff --git a/docs/img/53dc09446080b42329a76d4ecbb64aa3.png b/docs/img/53dc09446080b42329a76d4ecbb64aa3.png new file mode 100644 index 0000000000000000000000000000000000000000..bd94dc363d18b78f1b103cfcf9cc147bb653c7b6 Binary files /dev/null and b/docs/img/53dc09446080b42329a76d4ecbb64aa3.png differ diff --git a/docs/img/544adf1331ba8dc0c6391bf07ba6df8c.png b/docs/img/544adf1331ba8dc0c6391bf07ba6df8c.png new file mode 100644 index 0000000000000000000000000000000000000000..e23cb1aa931eb91e5e392fd63a7fc46c2da35efb Binary files /dev/null and b/docs/img/544adf1331ba8dc0c6391bf07ba6df8c.png differ diff --git a/docs/img/5460742929164e737a1b4c1990b75fc3.png b/docs/img/5460742929164e737a1b4c1990b75fc3.png new file mode 100644 index 0000000000000000000000000000000000000000..a32f4814387e77cc2bf1d7aa0da55f87ab08cc35 Binary files /dev/null and b/docs/img/5460742929164e737a1b4c1990b75fc3.png differ diff --git a/docs/img/5574e9e4660196e59606fe9d673097b7.png b/docs/img/5574e9e4660196e59606fe9d673097b7.png new file mode 100644 index 0000000000000000000000000000000000000000..777a4bfa595d6b668ab6d6d4874f93a1f629a940 Binary files /dev/null and b/docs/img/5574e9e4660196e59606fe9d673097b7.png differ diff --git a/docs/img/557f2cc00416c6f64286e93532f50121.png b/docs/img/557f2cc00416c6f64286e93532f50121.png new file mode 100644 index 0000000000000000000000000000000000000000..78e7a8f2bb4744453596d956c153982b7e16bb2b Binary files /dev/null and b/docs/img/557f2cc00416c6f64286e93532f50121.png differ diff --git a/docs/img/55c6a94e74c9a00da3a400ae60e3bf41.png b/docs/img/55c6a94e74c9a00da3a400ae60e3bf41.png new file mode 100644 index 0000000000000000000000000000000000000000..f436c146d54075101c2695e08c96c4eaf92982dc Binary files /dev/null and b/docs/img/55c6a94e74c9a00da3a400ae60e3bf41.png differ diff --git a/docs/img/56321b27a391110651e26fae3d93064e.png b/docs/img/56321b27a391110651e26fae3d93064e.png new file mode 100644 index 0000000000000000000000000000000000000000..b1fd1c77db1ac18a03b5e0e1aadc7387048923f7 Binary files /dev/null and b/docs/img/56321b27a391110651e26fae3d93064e.png differ diff --git a/docs/img/5653420f4acd0e8a49be80d5d413bd10.png b/docs/img/5653420f4acd0e8a49be80d5d413bd10.png new file mode 100644 index 0000000000000000000000000000000000000000..9007d265bc82dc2bf2b3ecf0ae7e66eb4b1dad10 Binary files /dev/null and b/docs/img/5653420f4acd0e8a49be80d5d413bd10.png differ diff --git a/docs/img/5665233091dd783791b6dd32107e61ec.png b/docs/img/5665233091dd783791b6dd32107e61ec.png new file mode 100644 index 0000000000000000000000000000000000000000..c3c7d2b6ede6ca3c3ce4d696b9533656c0b4379f Binary files /dev/null and b/docs/img/5665233091dd783791b6dd32107e61ec.png differ diff --git a/docs/img/56b25600afa13ee05e76062ab09ee470.png b/docs/img/56b25600afa13ee05e76062ab09ee470.png new file mode 100644 index 0000000000000000000000000000000000000000..3909146b7226874ff3466fa025bf192547312523 Binary files /dev/null and b/docs/img/56b25600afa13ee05e76062ab09ee470.png differ diff --git a/docs/img/56c21932bdeb67b5407d18238e8ec7f3.png b/docs/img/56c21932bdeb67b5407d18238e8ec7f3.png new file mode 100644 index 0000000000000000000000000000000000000000..8cd20c069ff5e9a4348039f39420b3b925e8a501 Binary files /dev/null and b/docs/img/56c21932bdeb67b5407d18238e8ec7f3.png differ diff --git a/docs/img/56d89ff1e02ecf30404a57092adae96d.png b/docs/img/56d89ff1e02ecf30404a57092adae96d.png new file mode 100644 index 0000000000000000000000000000000000000000..853725b7522656243060f7f4141e36ef050ef5f9 Binary files /dev/null and b/docs/img/56d89ff1e02ecf30404a57092adae96d.png differ diff --git a/docs/img/56eeecad0f9627fae21bc6b196391ba7.png b/docs/img/56eeecad0f9627fae21bc6b196391ba7.png new file mode 100644 index 0000000000000000000000000000000000000000..a1f055abdc8bf32a46915a76cfda1b10f15b8f89 Binary files /dev/null and b/docs/img/56eeecad0f9627fae21bc6b196391ba7.png differ diff --git a/docs/img/572645049ee5ab43733f62fc45312843.png b/docs/img/572645049ee5ab43733f62fc45312843.png new file mode 100644 index 0000000000000000000000000000000000000000..65e8914b0d2274876fe310149ab772e87fcb0c55 Binary files /dev/null and b/docs/img/572645049ee5ab43733f62fc45312843.png differ diff --git a/docs/img/57b0d20488fb6cdd9ed2e8f573fcb7bb.png b/docs/img/57b0d20488fb6cdd9ed2e8f573fcb7bb.png new file mode 100644 index 0000000000000000000000000000000000000000..f756f0edb44aa18a3695a7025c2649c63cc60260 Binary files /dev/null and b/docs/img/57b0d20488fb6cdd9ed2e8f573fcb7bb.png differ diff --git a/docs/img/5844f1567aec337f6ba990bc855c348a.png b/docs/img/5844f1567aec337f6ba990bc855c348a.png new file mode 100644 index 0000000000000000000000000000000000000000..95c06ec89ce7732a3fe29a587163cec6c97d99c3 Binary files /dev/null and b/docs/img/5844f1567aec337f6ba990bc855c348a.png differ diff --git a/docs/img/5881da97228cb042e5934f836edfd06c.png b/docs/img/5881da97228cb042e5934f836edfd06c.png new file mode 100644 index 0000000000000000000000000000000000000000..22fe637226a6fcdfe2a20e29d282dd006d60ca03 Binary files /dev/null and b/docs/img/5881da97228cb042e5934f836edfd06c.png differ diff --git a/docs/img/590715bab1c8704d5a4c16437c011ed5.png b/docs/img/590715bab1c8704d5a4c16437c011ed5.png new file mode 100644 index 0000000000000000000000000000000000000000..4533bdff99c22a6561f4d9f308d8ab41a5e1547b Binary files /dev/null and b/docs/img/590715bab1c8704d5a4c16437c011ed5.png differ diff --git a/docs/img/596a395127f6b3d5c9d1deac3f676680.png b/docs/img/596a395127f6b3d5c9d1deac3f676680.png new file mode 100644 index 0000000000000000000000000000000000000000..4511f6b40eba46aff565602a2844037398a04354 Binary files /dev/null and b/docs/img/596a395127f6b3d5c9d1deac3f676680.png differ diff --git a/docs/img/599297cd25b4f282b1340e8e61e2e087.png b/docs/img/599297cd25b4f282b1340e8e61e2e087.png new file mode 100644 index 0000000000000000000000000000000000000000..f9eb98ccafdc16148d173de2d210253bc160d516 Binary files /dev/null and b/docs/img/599297cd25b4f282b1340e8e61e2e087.png differ diff --git a/docs/img/5a2430ba8091036f8e9e3308aa845de8.png b/docs/img/5a2430ba8091036f8e9e3308aa845de8.png new file mode 100644 index 0000000000000000000000000000000000000000..a1514ea19581a767ef92d6410d294398d9b2655c Binary files /dev/null and b/docs/img/5a2430ba8091036f8e9e3308aa845de8.png differ diff --git a/docs/img/5a26f77375b52645c2387aec1f77a777.png b/docs/img/5a26f77375b52645c2387aec1f77a777.png new file mode 100644 index 0000000000000000000000000000000000000000..8cdcac6a7e94460b1d7b30a1febb757dfa132f94 Binary files /dev/null and b/docs/img/5a26f77375b52645c2387aec1f77a777.png differ diff --git a/docs/img/5b2694c5d35f9fdb42b43bb1f38ec29c.png b/docs/img/5b2694c5d35f9fdb42b43bb1f38ec29c.png new file mode 100644 index 0000000000000000000000000000000000000000..8f6f3ee0a609e1ec88da611d0cbeaf7690eb6dc0 Binary files /dev/null and b/docs/img/5b2694c5d35f9fdb42b43bb1f38ec29c.png differ diff --git a/docs/img/5b8558c08a5996468dcd0d1a119ac76b.png b/docs/img/5b8558c08a5996468dcd0d1a119ac76b.png new file mode 100644 index 0000000000000000000000000000000000000000..155c6bfb32bb8648407aa11b9b0a4cd8b1f840a8 Binary files /dev/null and b/docs/img/5b8558c08a5996468dcd0d1a119ac76b.png differ diff --git a/docs/img/5bf127e31dfc7f61e3134780f75114ff.png b/docs/img/5bf127e31dfc7f61e3134780f75114ff.png new file mode 100644 index 0000000000000000000000000000000000000000..b30961f5942a87114e0a38d0f57029c175e023f4 Binary files /dev/null and b/docs/img/5bf127e31dfc7f61e3134780f75114ff.png differ diff --git a/docs/img/5c0acf7979c7bc1e89dc413017b70870.png b/docs/img/5c0acf7979c7bc1e89dc413017b70870.png new file mode 100644 index 0000000000000000000000000000000000000000..933e257f56ae490974a683d131d64dd1cf97df35 Binary files /dev/null and b/docs/img/5c0acf7979c7bc1e89dc413017b70870.png differ diff --git a/docs/img/5d1d35707b32fd37e1e218e8b1df1771.png b/docs/img/5d1d35707b32fd37e1e218e8b1df1771.png new file mode 100644 index 0000000000000000000000000000000000000000..95e465d3c591c6bdd352c8595d397692a3883b27 Binary files /dev/null and b/docs/img/5d1d35707b32fd37e1e218e8b1df1771.png differ diff --git a/docs/img/5d200a6bcc883fcfa57dac51301bc2e3.png b/docs/img/5d200a6bcc883fcfa57dac51301bc2e3.png new file mode 100644 index 0000000000000000000000000000000000000000..dd7d6a22a17b7d5a67a259e86f0be3d48ddad78a Binary files /dev/null and b/docs/img/5d200a6bcc883fcfa57dac51301bc2e3.png differ diff --git a/docs/img/5d98850d2ad30c43029645c8c0486059.png b/docs/img/5d98850d2ad30c43029645c8c0486059.png new file mode 100644 index 0000000000000000000000000000000000000000..979006b7dd1a5ee1f93fe742364d23d70df834dc Binary files /dev/null and b/docs/img/5d98850d2ad30c43029645c8c0486059.png differ diff --git a/docs/img/5dd66b504685d06e7b88c8f8a71d39ba.png b/docs/img/5dd66b504685d06e7b88c8f8a71d39ba.png new file mode 100644 index 0000000000000000000000000000000000000000..9737d2f48a39de0664e045c283cbc2775c8edb5c Binary files /dev/null and b/docs/img/5dd66b504685d06e7b88c8f8a71d39ba.png differ diff --git a/docs/img/5e2e81b44d67af322056491cf32bb8da.png b/docs/img/5e2e81b44d67af322056491cf32bb8da.png new file mode 100644 index 0000000000000000000000000000000000000000..c2a1f0fcef890a437165dd919e608c5f4bde23d0 Binary files /dev/null and b/docs/img/5e2e81b44d67af322056491cf32bb8da.png differ diff --git a/docs/img/5e3cf2019e5c2c58b6dd5868fffb9e81.png b/docs/img/5e3cf2019e5c2c58b6dd5868fffb9e81.png new file mode 100644 index 0000000000000000000000000000000000000000..9ccb37f11b6773dd0fc7eb4ec65d325d4914820f Binary files /dev/null and b/docs/img/5e3cf2019e5c2c58b6dd5868fffb9e81.png differ diff --git a/docs/img/5e63fee9a28bb3e02eb772646de82b5c.png b/docs/img/5e63fee9a28bb3e02eb772646de82b5c.png new file mode 100644 index 0000000000000000000000000000000000000000..c38e5f1950cbfe8ddcf8b523fe3c41657d0da3f4 Binary files /dev/null and b/docs/img/5e63fee9a28bb3e02eb772646de82b5c.png differ diff --git a/docs/img/5e9b34b344fc5f08d74d5156c419f471.png b/docs/img/5e9b34b344fc5f08d74d5156c419f471.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec839c13c52c0c0a5c460e66efd50b048c9496b Binary files /dev/null and b/docs/img/5e9b34b344fc5f08d74d5156c419f471.png differ diff --git a/docs/img/5ec08a62b534de16956701e85c41e6b5.png b/docs/img/5ec08a62b534de16956701e85c41e6b5.png new file mode 100644 index 0000000000000000000000000000000000000000..d0be4ecb1b9c92f960933e60b3f2a99f618e4e4a Binary files /dev/null and b/docs/img/5ec08a62b534de16956701e85c41e6b5.png differ diff --git a/docs/img/5f13fe556b8940c2e698facdc219d16a.png b/docs/img/5f13fe556b8940c2e698facdc219d16a.png new file mode 100644 index 0000000000000000000000000000000000000000..4661f5a84e989e03ee216770401c0383dd1e3048 Binary files /dev/null and b/docs/img/5f13fe556b8940c2e698facdc219d16a.png differ diff --git a/docs/img/5f3552f35a06cac8dfa02c21fd48c852.png b/docs/img/5f3552f35a06cac8dfa02c21fd48c852.png new file mode 100644 index 0000000000000000000000000000000000000000..3782a5ffd5bdda57d50db155982a968735c515ef Binary files /dev/null and b/docs/img/5f3552f35a06cac8dfa02c21fd48c852.png differ diff --git a/docs/img/5f6c85f0240f3ec56519dde74a715dba.png b/docs/img/5f6c85f0240f3ec56519dde74a715dba.png new file mode 100644 index 0000000000000000000000000000000000000000..e00b3cb05344e5263e57568d47f6fa66b892ef6d Binary files /dev/null and b/docs/img/5f6c85f0240f3ec56519dde74a715dba.png differ diff --git a/docs/img/5f87ce250e2ea1a803a3aeda446eca15.png b/docs/img/5f87ce250e2ea1a803a3aeda446eca15.png new file mode 100644 index 0000000000000000000000000000000000000000..83bff45db9ddd03752b5b735aa3df33effb7b4f9 Binary files /dev/null and b/docs/img/5f87ce250e2ea1a803a3aeda446eca15.png differ diff --git a/docs/img/604dc2f6326d049dca30995958a84ad2.png b/docs/img/604dc2f6326d049dca30995958a84ad2.png new file mode 100644 index 0000000000000000000000000000000000000000..47454e3695f1af043fb50dee1118d04e827f1a1f Binary files /dev/null and b/docs/img/604dc2f6326d049dca30995958a84ad2.png differ diff --git a/docs/img/60958029f56e4c49c6a21082ea151191.png b/docs/img/60958029f56e4c49c6a21082ea151191.png new file mode 100644 index 0000000000000000000000000000000000000000..8e7f4510bf8f7ed3cc0f99abaf8a0fe50351d3cd Binary files /dev/null and b/docs/img/60958029f56e4c49c6a21082ea151191.png differ diff --git a/docs/img/611650a65dd2baf63b32d99fbe8e4a8a.png b/docs/img/611650a65dd2baf63b32d99fbe8e4a8a.png new file mode 100644 index 0000000000000000000000000000000000000000..61ef9ab09b97d26a37a69da3e30a2257a46f3718 Binary files /dev/null and b/docs/img/611650a65dd2baf63b32d99fbe8e4a8a.png differ diff --git a/docs/img/618ce3d47266d9b45262489065b68cf7.png b/docs/img/618ce3d47266d9b45262489065b68cf7.png new file mode 100644 index 0000000000000000000000000000000000000000..b0eebf0c7c53be5c41169de74f0943739fc0e232 Binary files /dev/null and b/docs/img/618ce3d47266d9b45262489065b68cf7.png differ diff --git a/docs/img/618f6f4ba2a434609a1a9de7a9725e49.png b/docs/img/618f6f4ba2a434609a1a9de7a9725e49.png new file mode 100644 index 0000000000000000000000000000000000000000..4cb5166817f387be4b8ef18366c8b94ae0128c69 Binary files /dev/null and b/docs/img/618f6f4ba2a434609a1a9de7a9725e49.png differ diff --git a/docs/img/61dd95f1efb048c48f6ab843e79120d0.png b/docs/img/61dd95f1efb048c48f6ab843e79120d0.png new file mode 100644 index 0000000000000000000000000000000000000000..49bfa2816ff514a9dcc89b1e4e9665f0f050aec9 Binary files /dev/null and b/docs/img/61dd95f1efb048c48f6ab843e79120d0.png differ diff --git a/docs/img/62073039b38c0dfa370251cfe07ca5e5.png b/docs/img/62073039b38c0dfa370251cfe07ca5e5.png new file mode 100644 index 0000000000000000000000000000000000000000..74c886fa7ed07a2796ec2dbfccb5c8a5077c0838 Binary files /dev/null and b/docs/img/62073039b38c0dfa370251cfe07ca5e5.png differ diff --git a/docs/img/6224c1a367d53cc7bb5c5536af96ec6e.png b/docs/img/6224c1a367d53cc7bb5c5536af96ec6e.png new file mode 100644 index 0000000000000000000000000000000000000000..4df75ad33585ee9658cc9268247e79ef5d1d8365 Binary files /dev/null and b/docs/img/6224c1a367d53cc7bb5c5536af96ec6e.png differ diff --git a/docs/img/62313a9f27e05c60c700ec9625e27d02.png b/docs/img/62313a9f27e05c60c700ec9625e27d02.png new file mode 100644 index 0000000000000000000000000000000000000000..421a559c4e24013962003d99381b1f04f49b078b Binary files /dev/null and b/docs/img/62313a9f27e05c60c700ec9625e27d02.png differ diff --git a/docs/img/6261dd255633edf09ab3d7245ccaf2c1.png b/docs/img/6261dd255633edf09ab3d7245ccaf2c1.png new file mode 100644 index 0000000000000000000000000000000000000000..9e8edb4f24c7e1eb6723910fb2c6db15f9801eb7 Binary files /dev/null and b/docs/img/6261dd255633edf09ab3d7245ccaf2c1.png differ diff --git a/docs/img/62b879dea0345cb8767d9cd4fb041f97.png b/docs/img/62b879dea0345cb8767d9cd4fb041f97.png new file mode 100644 index 0000000000000000000000000000000000000000..7890d458e72945391941e5bc1026ba6b7b5f272f Binary files /dev/null and b/docs/img/62b879dea0345cb8767d9cd4fb041f97.png differ diff --git a/docs/img/62d2b5c8435d31dff0a7fc689c288e8c.png b/docs/img/62d2b5c8435d31dff0a7fc689c288e8c.png new file mode 100644 index 0000000000000000000000000000000000000000..9e39ca3f861dcbf9cdb4afaea81e07fa3fdc8f35 Binary files /dev/null and b/docs/img/62d2b5c8435d31dff0a7fc689c288e8c.png differ diff --git a/docs/img/6314765d395236bbba1552cc65c1228c.png b/docs/img/6314765d395236bbba1552cc65c1228c.png new file mode 100644 index 0000000000000000000000000000000000000000..4eeff1aea23f26404fd95ba20033584e667f686a Binary files /dev/null and b/docs/img/6314765d395236bbba1552cc65c1228c.png differ diff --git a/docs/img/631b8ad9816cfdd87ba106377c86c7a4.png b/docs/img/631b8ad9816cfdd87ba106377c86c7a4.png new file mode 100644 index 0000000000000000000000000000000000000000..077e15c35b2cf863915b7c80cfddb09857669bf0 Binary files /dev/null and b/docs/img/631b8ad9816cfdd87ba106377c86c7a4.png differ diff --git a/docs/img/640bc8c28d8cd3035fbe0c4c1018d2d1.png b/docs/img/640bc8c28d8cd3035fbe0c4c1018d2d1.png new file mode 100644 index 0000000000000000000000000000000000000000..f175ffe7bc58f30409e0d75f6a888bdb56e0a0ed Binary files /dev/null and b/docs/img/640bc8c28d8cd3035fbe0c4c1018d2d1.png differ diff --git a/docs/img/6427e1b107996a8eb9c401e1aa76bf87.png b/docs/img/6427e1b107996a8eb9c401e1aa76bf87.png new file mode 100644 index 0000000000000000000000000000000000000000..6046611953ce4e17ec8469d53750db6def7a1f2a Binary files /dev/null and b/docs/img/6427e1b107996a8eb9c401e1aa76bf87.png differ diff --git a/docs/img/645965e7ebb61697ff42cc06214ca5af.png b/docs/img/645965e7ebb61697ff42cc06214ca5af.png new file mode 100644 index 0000000000000000000000000000000000000000..eb598083963b6a1281bec0d527e0a1b677b1f3b6 Binary files /dev/null and b/docs/img/645965e7ebb61697ff42cc06214ca5af.png differ diff --git a/docs/img/64d10619e1633359be63480f18d60b90.png b/docs/img/64d10619e1633359be63480f18d60b90.png new file mode 100644 index 0000000000000000000000000000000000000000..a548f5acbfad2aa44736a54713a7b7f4bd59a900 Binary files /dev/null and b/docs/img/64d10619e1633359be63480f18d60b90.png differ diff --git a/docs/img/655bbae75a3608d2016397c70682f7d4.png b/docs/img/655bbae75a3608d2016397c70682f7d4.png new file mode 100644 index 0000000000000000000000000000000000000000..47a618ea3628fff8720de9cd7d5fa42fd77cce05 Binary files /dev/null and b/docs/img/655bbae75a3608d2016397c70682f7d4.png differ diff --git a/docs/img/6564cc179b8bafb5577b9762c905010c.png b/docs/img/6564cc179b8bafb5577b9762c905010c.png new file mode 100644 index 0000000000000000000000000000000000000000..19560bffef2d905302c148c4fcedfdd6bf2d1f08 Binary files /dev/null and b/docs/img/6564cc179b8bafb5577b9762c905010c.png differ diff --git a/docs/img/65770b50cd2119e84c6a852b44cf403d.png b/docs/img/65770b50cd2119e84c6a852b44cf403d.png new file mode 100644 index 0000000000000000000000000000000000000000..50fab030a41c7b2206e86563c4f1f6d2fe75009a Binary files /dev/null and b/docs/img/65770b50cd2119e84c6a852b44cf403d.png differ diff --git a/docs/img/659964d0e0d080d80881d6eb74aaaf7e.png b/docs/img/659964d0e0d080d80881d6eb74aaaf7e.png new file mode 100644 index 0000000000000000000000000000000000000000..378e38fc6da9d1cd5e3cf1865fe331eeb0ed6229 Binary files /dev/null and b/docs/img/659964d0e0d080d80881d6eb74aaaf7e.png differ diff --git a/docs/img/662e9b0c090a4f28c82eb779aabdc9c8.png b/docs/img/662e9b0c090a4f28c82eb779aabdc9c8.png new file mode 100644 index 0000000000000000000000000000000000000000..afd2f2700a3073f4be36d6ceb9544fed49b72c86 Binary files /dev/null and b/docs/img/662e9b0c090a4f28c82eb779aabdc9c8.png differ diff --git a/docs/img/669c2de32e70a30ad93c28d4afd41491.png b/docs/img/669c2de32e70a30ad93c28d4afd41491.png new file mode 100644 index 0000000000000000000000000000000000000000..6a234607e27ec22c11a7b63f117ff8a8c73db1b1 Binary files /dev/null and b/docs/img/669c2de32e70a30ad93c28d4afd41491.png differ diff --git a/docs/img/66a70133eaa2327dce4cd61c485afcdb.png b/docs/img/66a70133eaa2327dce4cd61c485afcdb.png new file mode 100644 index 0000000000000000000000000000000000000000..6fd449abfb80b6cbae5422d8e9e85e890eceb6b4 Binary files /dev/null and b/docs/img/66a70133eaa2327dce4cd61c485afcdb.png differ diff --git a/docs/img/66e7cbbe98ed69a6154c1adcd7ec4f6e.png b/docs/img/66e7cbbe98ed69a6154c1adcd7ec4f6e.png new file mode 100644 index 0000000000000000000000000000000000000000..307c3304b44671f0e51c85dba1bde03137b0539a Binary files /dev/null and b/docs/img/66e7cbbe98ed69a6154c1adcd7ec4f6e.png differ diff --git a/docs/img/671787cdf6cd1dde3e748fae72d46779.png b/docs/img/671787cdf6cd1dde3e748fae72d46779.png new file mode 100644 index 0000000000000000000000000000000000000000..cb898e5ad549a742a8e8a0f9245dc8edb47f3193 Binary files /dev/null and b/docs/img/671787cdf6cd1dde3e748fae72d46779.png differ diff --git a/docs/img/674c1579957cca4a644bc90fb8fbb2f3.png b/docs/img/674c1579957cca4a644bc90fb8fbb2f3.png new file mode 100644 index 0000000000000000000000000000000000000000..567263c8fad8701b9b727ce30e27d1ddfe6bfb6e Binary files /dev/null and b/docs/img/674c1579957cca4a644bc90fb8fbb2f3.png differ diff --git a/docs/img/676537e7ead1101c5c0668a2adbc08d5.png b/docs/img/676537e7ead1101c5c0668a2adbc08d5.png new file mode 100644 index 0000000000000000000000000000000000000000..29759b5112f7c9da924b0757842cbca2c0e83585 Binary files /dev/null and b/docs/img/676537e7ead1101c5c0668a2adbc08d5.png differ diff --git a/docs/img/677d8f883392679f3fba97024a259665.png b/docs/img/677d8f883392679f3fba97024a259665.png new file mode 100644 index 0000000000000000000000000000000000000000..737ab0b6ccff5beaa0b3659ea112448738e45423 Binary files /dev/null and b/docs/img/677d8f883392679f3fba97024a259665.png differ diff --git a/docs/img/67f7d8117f3d6bf60fe4d5e03bca7b6e.png b/docs/img/67f7d8117f3d6bf60fe4d5e03bca7b6e.png new file mode 100644 index 0000000000000000000000000000000000000000..898351f9e270d79492780f875146de366d5766cb Binary files /dev/null and b/docs/img/67f7d8117f3d6bf60fe4d5e03bca7b6e.png differ diff --git a/docs/img/6809ef73be513357f41ebe6d325265d5.png b/docs/img/6809ef73be513357f41ebe6d325265d5.png new file mode 100644 index 0000000000000000000000000000000000000000..a69613768f83098ed5b5ae78dff4118f1203a2e0 Binary files /dev/null and b/docs/img/6809ef73be513357f41ebe6d325265d5.png differ diff --git a/docs/img/6867e53bf251ef0cb0e190c2e702d188.png b/docs/img/6867e53bf251ef0cb0e190c2e702d188.png new file mode 100644 index 0000000000000000000000000000000000000000..10d6c281fcd3cc38caf79aca9be8430c55053619 Binary files /dev/null and b/docs/img/6867e53bf251ef0cb0e190c2e702d188.png differ diff --git a/docs/img/69a8b09a09599e563d1796eac13f945e.png b/docs/img/69a8b09a09599e563d1796eac13f945e.png new file mode 100644 index 0000000000000000000000000000000000000000..0ea21fd0d76ae9541d07b74504752d1b86ad9039 --- /dev/null +++ b/docs/img/69a8b09a09599e563d1796eac13f945e.png @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + coverage + + + coverage + + + unknown + + + unknown + + + + diff --git a/docs/img/6a23362ee367dd144c2c8ea315b8dde0.png b/docs/img/6a23362ee367dd144c2c8ea315b8dde0.png new file mode 100644 index 0000000000000000000000000000000000000000..34bd845f0a543cdda300e7a5a44de971bf5be5ec Binary files /dev/null and b/docs/img/6a23362ee367dd144c2c8ea315b8dde0.png differ diff --git a/docs/img/6a2d24148988c584ff47ac7c526b48ff.png b/docs/img/6a2d24148988c584ff47ac7c526b48ff.png new file mode 100644 index 0000000000000000000000000000000000000000..42772878fe5a7d38cec0d5d6d87aaa0e6b3e16e4 Binary files /dev/null and b/docs/img/6a2d24148988c584ff47ac7c526b48ff.png differ diff --git a/docs/img/6a33d33154553990ed15338a6f9c7b35.png b/docs/img/6a33d33154553990ed15338a6f9c7b35.png new file mode 100644 index 0000000000000000000000000000000000000000..f70b0a6843a83528020eabae3692c6982f54d2aa Binary files /dev/null and b/docs/img/6a33d33154553990ed15338a6f9c7b35.png differ diff --git a/docs/img/6ad15d363481e18f443e6709fc8d1368.png b/docs/img/6ad15d363481e18f443e6709fc8d1368.png new file mode 100644 index 0000000000000000000000000000000000000000..641f917a572ffe5aa55e4990e5d11db8ae740cc1 Binary files /dev/null and b/docs/img/6ad15d363481e18f443e6709fc8d1368.png differ diff --git a/docs/img/6b48060a3ef4c055e75a74e6a396ebb9.png b/docs/img/6b48060a3ef4c055e75a74e6a396ebb9.png new file mode 100644 index 0000000000000000000000000000000000000000..fa7a2ab7e86cc484b37d9ca17b53fae3b0c9d7ac Binary files /dev/null and b/docs/img/6b48060a3ef4c055e75a74e6a396ebb9.png differ diff --git a/docs/img/6b5837eb8878551d4881e94247d957e9.png b/docs/img/6b5837eb8878551d4881e94247d957e9.png new file mode 100644 index 0000000000000000000000000000000000000000..d526409f76b434e35698d3e60c62749e5cf8f80b Binary files /dev/null and b/docs/img/6b5837eb8878551d4881e94247d957e9.png differ diff --git a/docs/img/6c431eb1e4bc729eceb4a6a36f0ea6b0.png b/docs/img/6c431eb1e4bc729eceb4a6a36f0ea6b0.png new file mode 100644 index 0000000000000000000000000000000000000000..1cd97355cf04b1448e82f94e3b272c7ab3fefb47 Binary files /dev/null and b/docs/img/6c431eb1e4bc729eceb4a6a36f0ea6b0.png differ diff --git a/docs/img/6cad1c326921f33ce6d53e7f2ebd1158.png b/docs/img/6cad1c326921f33ce6d53e7f2ebd1158.png new file mode 100644 index 0000000000000000000000000000000000000000..949158b9c0e1776e4a2d1abd36bd239d5f5f926c Binary files /dev/null and b/docs/img/6cad1c326921f33ce6d53e7f2ebd1158.png differ diff --git a/docs/img/6d49650d7eab0173612011fa6d81dc4e.png b/docs/img/6d49650d7eab0173612011fa6d81dc4e.png new file mode 100644 index 0000000000000000000000000000000000000000..9a0c4f909e8613a36c3ac665dc5cb79429aae619 Binary files /dev/null and b/docs/img/6d49650d7eab0173612011fa6d81dc4e.png differ diff --git a/docs/img/6de450be845a1f48a3feae9ce8e7be6e.png b/docs/img/6de450be845a1f48a3feae9ce8e7be6e.png new file mode 100644 index 0000000000000000000000000000000000000000..a22b6c72475d81bad072105fc71f33a64cf34c4d Binary files /dev/null and b/docs/img/6de450be845a1f48a3feae9ce8e7be6e.png differ diff --git a/docs/img/6deba2d9890a294d17564cce39fcbaef.png b/docs/img/6deba2d9890a294d17564cce39fcbaef.png new file mode 100644 index 0000000000000000000000000000000000000000..3883afb5f01ccd5ef6fcb4b57623d8b3eee19e46 Binary files /dev/null and b/docs/img/6deba2d9890a294d17564cce39fcbaef.png differ diff --git a/docs/img/6dffd31bb67148d85ebfccbfc20abfd8.png b/docs/img/6dffd31bb67148d85ebfccbfc20abfd8.png new file mode 100644 index 0000000000000000000000000000000000000000..042d04070db5675f69d789eb1f03bddfcaec59ee Binary files /dev/null and b/docs/img/6dffd31bb67148d85ebfccbfc20abfd8.png differ diff --git a/docs/img/6e17896087b8446f53400a1c8d39c0d6.png b/docs/img/6e17896087b8446f53400a1c8d39c0d6.png new file mode 100644 index 0000000000000000000000000000000000000000..1b3cf1d11da71c7189791be52bbc5d7656cf5c31 Binary files /dev/null and b/docs/img/6e17896087b8446f53400a1c8d39c0d6.png differ diff --git a/docs/img/6e3e1e9c7013cd330bcb6380ef19ddf9.png b/docs/img/6e3e1e9c7013cd330bcb6380ef19ddf9.png new file mode 100644 index 0000000000000000000000000000000000000000..e257602577047de608c6641be7b9f5fe470ed110 Binary files /dev/null and b/docs/img/6e3e1e9c7013cd330bcb6380ef19ddf9.png differ diff --git a/docs/img/6ea99225391da160a92dd9fd1fb01cd7.png b/docs/img/6ea99225391da160a92dd9fd1fb01cd7.png new file mode 100644 index 0000000000000000000000000000000000000000..9abdfc0338b15ff7e60f7a25214a712fca5257dc Binary files /dev/null and b/docs/img/6ea99225391da160a92dd9fd1fb01cd7.png differ diff --git a/docs/img/6f52527c138db466f7fba27994ad67f8.png b/docs/img/6f52527c138db466f7fba27994ad67f8.png new file mode 100644 index 0000000000000000000000000000000000000000..f187f24f7b5fc7ca8a66605ec0cacafb1a65148e Binary files /dev/null and b/docs/img/6f52527c138db466f7fba27994ad67f8.png differ diff --git a/docs/img/70117ebf119dd375e0def463921cc363.png b/docs/img/70117ebf119dd375e0def463921cc363.png new file mode 100644 index 0000000000000000000000000000000000000000..4dc6e1779c04d609881e5f8888aeb30903fe188b Binary files /dev/null and b/docs/img/70117ebf119dd375e0def463921cc363.png differ diff --git a/docs/img/7042e9f430cefb3a9c62194cec839692.png b/docs/img/7042e9f430cefb3a9c62194cec839692.png new file mode 100644 index 0000000000000000000000000000000000000000..fd3d092e3745753acf8c77830dbc33bdcb684f7c Binary files /dev/null and b/docs/img/7042e9f430cefb3a9c62194cec839692.png differ diff --git a/docs/img/705d87c5c620f8ade251682fceb074e3.png b/docs/img/705d87c5c620f8ade251682fceb074e3.png new file mode 100644 index 0000000000000000000000000000000000000000..da9f825c19a55cee612c44695adbe9c096ba08e3 Binary files /dev/null and b/docs/img/705d87c5c620f8ade251682fceb074e3.png differ diff --git a/docs/img/70c613da170fdfd7665282f16becad56.png b/docs/img/70c613da170fdfd7665282f16becad56.png new file mode 100644 index 0000000000000000000000000000000000000000..b4d3f764a20d02ce029c5e89c166246b9c84e6ef Binary files /dev/null and b/docs/img/70c613da170fdfd7665282f16becad56.png differ diff --git a/docs/img/7151cdf5255313b82b775852ed2aef73.png b/docs/img/7151cdf5255313b82b775852ed2aef73.png new file mode 100644 index 0000000000000000000000000000000000000000..04b10453c6a97c78e154bf4e4097bbc9581f0bc6 Binary files /dev/null and b/docs/img/7151cdf5255313b82b775852ed2aef73.png differ diff --git a/docs/img/71c2f22b2aef83c58870637723d6f7ef.png b/docs/img/71c2f22b2aef83c58870637723d6f7ef.png new file mode 100644 index 0000000000000000000000000000000000000000..10c3d9914a3c0a8255773ec6aab2c59b4a3721ce Binary files /dev/null and b/docs/img/71c2f22b2aef83c58870637723d6f7ef.png differ diff --git a/docs/img/72431eb6b6fe2dd27e2f6f9be7d91672.png b/docs/img/72431eb6b6fe2dd27e2f6f9be7d91672.png new file mode 100644 index 0000000000000000000000000000000000000000..4b9e42d5a3cf9885ca0280d79339b92f35eb189b Binary files /dev/null and b/docs/img/72431eb6b6fe2dd27e2f6f9be7d91672.png differ diff --git a/docs/img/729f4c6815c7118c098b6925f2375918.png b/docs/img/729f4c6815c7118c098b6925f2375918.png new file mode 100644 index 0000000000000000000000000000000000000000..75ed57e8a55b1260b2dd27361da3563a9c4f0a33 Binary files /dev/null and b/docs/img/729f4c6815c7118c098b6925f2375918.png differ diff --git a/docs/img/72a8c3cb5bafa1e02d93f68a624b6094.png b/docs/img/72a8c3cb5bafa1e02d93f68a624b6094.png new file mode 100644 index 0000000000000000000000000000000000000000..f26025fe7a4353b0df3f272b4edf86761a9796d1 Binary files /dev/null and b/docs/img/72a8c3cb5bafa1e02d93f68a624b6094.png differ diff --git a/docs/img/72befe6a3da1a58465dbf55200aefd26.png b/docs/img/72befe6a3da1a58465dbf55200aefd26.png new file mode 100644 index 0000000000000000000000000000000000000000..2f7aa2224f4566a487243dc501e79cec3c67d154 Binary files /dev/null and b/docs/img/72befe6a3da1a58465dbf55200aefd26.png differ diff --git a/docs/img/731943edb4428a3eb27c86d8d454d0e0.png b/docs/img/731943edb4428a3eb27c86d8d454d0e0.png new file mode 100644 index 0000000000000000000000000000000000000000..bf17b1f97cc1f9d9cf3d3f65f2f105ea365c3cd8 Binary files /dev/null and b/docs/img/731943edb4428a3eb27c86d8d454d0e0.png differ diff --git a/docs/img/7355fc1627be101cc5ed59387d36b6a3.png b/docs/img/7355fc1627be101cc5ed59387d36b6a3.png new file mode 100644 index 0000000000000000000000000000000000000000..a82c41818fa783280260e8388561166b851affc6 Binary files /dev/null and b/docs/img/7355fc1627be101cc5ed59387d36b6a3.png differ diff --git a/docs/img/7356a350b6fac674fc341d110380f723.png b/docs/img/7356a350b6fac674fc341d110380f723.png new file mode 100644 index 0000000000000000000000000000000000000000..8a597b86c2deec58890ec7514236fee9a0c63e89 Binary files /dev/null and b/docs/img/7356a350b6fac674fc341d110380f723.png differ diff --git a/docs/img/738413ec37e13f47706eeda5de3b9dfb.png b/docs/img/738413ec37e13f47706eeda5de3b9dfb.png new file mode 100644 index 0000000000000000000000000000000000000000..07e35638b48d0c0cb1843679764d2829e10625f6 Binary files /dev/null and b/docs/img/738413ec37e13f47706eeda5de3b9dfb.png differ diff --git a/docs/img/74017afb9b6459aed36b4c4a53df62e9.png b/docs/img/74017afb9b6459aed36b4c4a53df62e9.png new file mode 100644 index 0000000000000000000000000000000000000000..9dba1c76f08e1463a4cb1b40560a67c24f7ff106 Binary files /dev/null and b/docs/img/74017afb9b6459aed36b4c4a53df62e9.png differ diff --git a/docs/img/743ce9a40d40e900e957589a9024f116.png b/docs/img/743ce9a40d40e900e957589a9024f116.png new file mode 100644 index 0000000000000000000000000000000000000000..8181be88a0de350d6301e11a69fb3bde14449d64 Binary files /dev/null and b/docs/img/743ce9a40d40e900e957589a9024f116.png differ diff --git a/docs/img/74f87e79779a102e82a644227e50a2e4.png b/docs/img/74f87e79779a102e82a644227e50a2e4.png new file mode 100644 index 0000000000000000000000000000000000000000..e42050d3e42fa18c97aa46e38d19dabc16fa6bc4 Binary files /dev/null and b/docs/img/74f87e79779a102e82a644227e50a2e4.png differ diff --git a/docs/img/75ca9285f50e058d4d85796b4d0b8e69.png b/docs/img/75ca9285f50e058d4d85796b4d0b8e69.png new file mode 100644 index 0000000000000000000000000000000000000000..8f43c40df6bc86fe0b1bb5c31264db633745b776 Binary files /dev/null and b/docs/img/75ca9285f50e058d4d85796b4d0b8e69.png differ diff --git a/docs/img/75ff7ad133721fa954b7960ba4edc025.png b/docs/img/75ff7ad133721fa954b7960ba4edc025.png new file mode 100644 index 0000000000000000000000000000000000000000..3c7c1d06b47d1e3c50cf52b713d78c480a274b81 Binary files /dev/null and b/docs/img/75ff7ad133721fa954b7960ba4edc025.png differ diff --git a/docs/img/75ffde23ab0100e58532632d19b84db0.png b/docs/img/75ffde23ab0100e58532632d19b84db0.png new file mode 100644 index 0000000000000000000000000000000000000000..7da1ffe8ffa78c377faef665ec41870fdce05543 Binary files /dev/null and b/docs/img/75ffde23ab0100e58532632d19b84db0.png differ diff --git a/docs/img/768ab05f8c35931c200b6da1f8d92352.png b/docs/img/768ab05f8c35931c200b6da1f8d92352.png new file mode 100644 index 0000000000000000000000000000000000000000..b2a4c178383072e963d80a050a0db0d1bae7e6ed Binary files /dev/null and b/docs/img/768ab05f8c35931c200b6da1f8d92352.png differ diff --git a/docs/img/7710cb575c3aefd0769c3f6aadb6e879.png b/docs/img/7710cb575c3aefd0769c3f6aadb6e879.png new file mode 100644 index 0000000000000000000000000000000000000000..9d3dcd5d4a2b1ae555141c2fb6323289ce765558 Binary files /dev/null and b/docs/img/7710cb575c3aefd0769c3f6aadb6e879.png differ diff --git a/docs/img/771e5d2c3cbeba5811f78938b976dfdf.png b/docs/img/771e5d2c3cbeba5811f78938b976dfdf.png new file mode 100644 index 0000000000000000000000000000000000000000..46c3dc28b7953248ea1ac7a5ba6cac5317afa488 Binary files /dev/null and b/docs/img/771e5d2c3cbeba5811f78938b976dfdf.png differ diff --git a/docs/img/7727ed12caef6b761b73e4bd379c7839.png b/docs/img/7727ed12caef6b761b73e4bd379c7839.png new file mode 100644 index 0000000000000000000000000000000000000000..6b4e0d28fb042f9f36948d6c6e8e7f32fb3becc6 Binary files /dev/null and b/docs/img/7727ed12caef6b761b73e4bd379c7839.png differ diff --git a/docs/img/773702223af81c9872bccd88d63ad3a5.png b/docs/img/773702223af81c9872bccd88d63ad3a5.png new file mode 100644 index 0000000000000000000000000000000000000000..85298df4ab63cac86741ee974b511fbc35080bcd Binary files /dev/null and b/docs/img/773702223af81c9872bccd88d63ad3a5.png differ diff --git a/docs/img/77707dedee5c3b669fd992a327698362.png b/docs/img/77707dedee5c3b669fd992a327698362.png new file mode 100644 index 0000000000000000000000000000000000000000..6efbc5679aee95e0e342cd9e40c722e27715f620 Binary files /dev/null and b/docs/img/77707dedee5c3b669fd992a327698362.png differ diff --git a/docs/img/7775f0c2ba5f85e61aae351b9939cdf2.png b/docs/img/7775f0c2ba5f85e61aae351b9939cdf2.png new file mode 100644 index 0000000000000000000000000000000000000000..ff026e2d27dca8750fc9345e4548f45336409a57 Binary files /dev/null and b/docs/img/7775f0c2ba5f85e61aae351b9939cdf2.png differ diff --git a/docs/img/77a2b247e60ad05b022cfd3f3a62c069.png b/docs/img/77a2b247e60ad05b022cfd3f3a62c069.png new file mode 100644 index 0000000000000000000000000000000000000000..ebcc5fede484137e217b4a5203bab885be1b85dd Binary files /dev/null and b/docs/img/77a2b247e60ad05b022cfd3f3a62c069.png differ diff --git a/docs/img/78801b2f265bdecdb7a5ff7e8be47802.png b/docs/img/78801b2f265bdecdb7a5ff7e8be47802.png new file mode 100644 index 0000000000000000000000000000000000000000..04f6e927221d49f8bc6a9a7248712285d2f6cc3f Binary files /dev/null and b/docs/img/78801b2f265bdecdb7a5ff7e8be47802.png differ diff --git a/docs/img/7887f58c141f9c2e749a75158e430ac6.png b/docs/img/7887f58c141f9c2e749a75158e430ac6.png new file mode 100644 index 0000000000000000000000000000000000000000..0dc625cfd932148615c5e47ce40d799d6d575b8d Binary files /dev/null and b/docs/img/7887f58c141f9c2e749a75158e430ac6.png differ diff --git a/docs/img/788efc08015bf62f608d47f16b49b4d7.png b/docs/img/788efc08015bf62f608d47f16b49b4d7.png new file mode 100644 index 0000000000000000000000000000000000000000..a6e922147f5fe2a4368c5a1e5ee1fb30377e02ba Binary files /dev/null and b/docs/img/788efc08015bf62f608d47f16b49b4d7.png differ diff --git a/docs/img/7896b9b275d92d4b9cb2001cc464e509.png b/docs/img/7896b9b275d92d4b9cb2001cc464e509.png new file mode 100644 index 0000000000000000000000000000000000000000..5da697fa240cec7723dfab832037bbe5ff40fd15 Binary files /dev/null and b/docs/img/7896b9b275d92d4b9cb2001cc464e509.png differ diff --git a/docs/img/78dac22706dcca5ce3855d23987289ea.png b/docs/img/78dac22706dcca5ce3855d23987289ea.png new file mode 100644 index 0000000000000000000000000000000000000000..1896c579211f0827a07a7a4fed5419ad2f7534ed Binary files /dev/null and b/docs/img/78dac22706dcca5ce3855d23987289ea.png differ diff --git a/docs/img/793399d61e9710ebd809bd4c52901d68.png b/docs/img/793399d61e9710ebd809bd4c52901d68.png new file mode 100644 index 0000000000000000000000000000000000000000..de5ae27dbb06619017349063c7082e86f207ad76 Binary files /dev/null and b/docs/img/793399d61e9710ebd809bd4c52901d68.png differ diff --git a/docs/img/7a0180479e056fe1c4aa11c3e8684906.png b/docs/img/7a0180479e056fe1c4aa11c3e8684906.png new file mode 100644 index 0000000000000000000000000000000000000000..81655fb37468ae117113b49189baaf351e6173b6 Binary files /dev/null and b/docs/img/7a0180479e056fe1c4aa11c3e8684906.png differ diff --git a/docs/img/7a0b5b2ee322d8676753d89561c1d3cb.png b/docs/img/7a0b5b2ee322d8676753d89561c1d3cb.png new file mode 100644 index 0000000000000000000000000000000000000000..37bc9e1790baee991fdafe0a07adc67744dba4f9 Binary files /dev/null and b/docs/img/7a0b5b2ee322d8676753d89561c1d3cb.png differ diff --git a/docs/img/7a1046341466c144b96bc573f0a16114.png b/docs/img/7a1046341466c144b96bc573f0a16114.png new file mode 100644 index 0000000000000000000000000000000000000000..5d0dc7e63f8d5a82ce67c7c7fa9de170b2727d87 Binary files /dev/null and b/docs/img/7a1046341466c144b96bc573f0a16114.png differ diff --git a/docs/img/7a4195dce33a791e39b721499e4137ad.png b/docs/img/7a4195dce33a791e39b721499e4137ad.png new file mode 100644 index 0000000000000000000000000000000000000000..0c9a22f54c81f91272ce3adea42b9d0e6e4acb1f Binary files /dev/null and b/docs/img/7a4195dce33a791e39b721499e4137ad.png differ diff --git a/docs/img/7a5996be0f8e75beb29e443470d79ee6.png b/docs/img/7a5996be0f8e75beb29e443470d79ee6.png new file mode 100644 index 0000000000000000000000000000000000000000..408f8223bbbb87d53f1a5364a830c1976740609f Binary files /dev/null and b/docs/img/7a5996be0f8e75beb29e443470d79ee6.png differ diff --git a/docs/img/7a5c28bfcfa2942d75aaace7ccb281ce.png b/docs/img/7a5c28bfcfa2942d75aaace7ccb281ce.png new file mode 100644 index 0000000000000000000000000000000000000000..6370442a82dd45a585528075165975179bfa6fa6 Binary files /dev/null and b/docs/img/7a5c28bfcfa2942d75aaace7ccb281ce.png differ diff --git a/docs/img/7a612dcc3c18a6e6433eb5a57a99368d.png b/docs/img/7a612dcc3c18a6e6433eb5a57a99368d.png new file mode 100644 index 0000000000000000000000000000000000000000..95b2b45c5874f73343ddc026fd03e80ba7e7adda Binary files /dev/null and b/docs/img/7a612dcc3c18a6e6433eb5a57a99368d.png differ diff --git a/docs/img/7a9e6a406ba2eb40638f2b43024b368b.png b/docs/img/7a9e6a406ba2eb40638f2b43024b368b.png new file mode 100644 index 0000000000000000000000000000000000000000..fb14288704080745e74d3aad4ffa7a034d799da6 Binary files /dev/null and b/docs/img/7a9e6a406ba2eb40638f2b43024b368b.png differ diff --git a/docs/img/7ac2e224cec000f3932b1186bc1d643f.png b/docs/img/7ac2e224cec000f3932b1186bc1d643f.png new file mode 100644 index 0000000000000000000000000000000000000000..eb046ca1ad21d4739465aea83e4b11b60a0a74f9 Binary files /dev/null and b/docs/img/7ac2e224cec000f3932b1186bc1d643f.png differ diff --git a/docs/img/7b1af71091089deb54dbd357d9679d9c.png b/docs/img/7b1af71091089deb54dbd357d9679d9c.png new file mode 100644 index 0000000000000000000000000000000000000000..f95331a810c22b650f6fbd7d31610d840a9be9c3 Binary files /dev/null and b/docs/img/7b1af71091089deb54dbd357d9679d9c.png differ diff --git a/docs/img/7b7c08f411e1307c05a834071bccb610.png b/docs/img/7b7c08f411e1307c05a834071bccb610.png new file mode 100644 index 0000000000000000000000000000000000000000..0c6996e3d0b488dcd0a44bef48878a5b78863c37 Binary files /dev/null and b/docs/img/7b7c08f411e1307c05a834071bccb610.png differ diff --git a/docs/img/7bcf8d15daa1fb25935d7638acd8eb43.png b/docs/img/7bcf8d15daa1fb25935d7638acd8eb43.png new file mode 100644 index 0000000000000000000000000000000000000000..4da3204aebf77b43c5907889474c0ab738fa4f95 Binary files /dev/null and b/docs/img/7bcf8d15daa1fb25935d7638acd8eb43.png differ diff --git a/docs/img/7cc97c84798f08bc78608f1afa423aa2.png b/docs/img/7cc97c84798f08bc78608f1afa423aa2.png new file mode 100644 index 0000000000000000000000000000000000000000..94b6dcb1b63121005177303ca5511501c2eb380f Binary files /dev/null and b/docs/img/7cc97c84798f08bc78608f1afa423aa2.png differ diff --git a/docs/img/7cfe14b5f606095866af7260c844d4e2.png b/docs/img/7cfe14b5f606095866af7260c844d4e2.png new file mode 100644 index 0000000000000000000000000000000000000000..d04101bd97f7e02446c49cd4a20210061c5b23c6 Binary files /dev/null and b/docs/img/7cfe14b5f606095866af7260c844d4e2.png differ diff --git a/docs/img/7d05273dffbd24f67285426b02a19ddc.png b/docs/img/7d05273dffbd24f67285426b02a19ddc.png new file mode 100644 index 0000000000000000000000000000000000000000..51e640b648f7cdb533d7cf34501faee86e3d1b39 Binary files /dev/null and b/docs/img/7d05273dffbd24f67285426b02a19ddc.png differ diff --git a/docs/img/7d08a10bdee492162fdb554fb3033f0d.png b/docs/img/7d08a10bdee492162fdb554fb3033f0d.png new file mode 100644 index 0000000000000000000000000000000000000000..4ea903691677c21c655db89811a29824dd11b910 Binary files /dev/null and b/docs/img/7d08a10bdee492162fdb554fb3033f0d.png differ diff --git a/docs/img/7dc58177067caac48605788b7932d846.png b/docs/img/7dc58177067caac48605788b7932d846.png new file mode 100644 index 0000000000000000000000000000000000000000..2698626f5592fc6e4713787751a1e3b2350c4bff Binary files /dev/null and b/docs/img/7dc58177067caac48605788b7932d846.png differ diff --git a/docs/img/7ddc19b18c20bfa78acb7fe9dd2ede4b.png b/docs/img/7ddc19b18c20bfa78acb7fe9dd2ede4b.png new file mode 100644 index 0000000000000000000000000000000000000000..f927104262dbefc02e3120e321720d2d20b53ba7 Binary files /dev/null and b/docs/img/7ddc19b18c20bfa78acb7fe9dd2ede4b.png differ diff --git a/docs/img/7e5039b0d8fb74c5ea813e354f23493e.png b/docs/img/7e5039b0d8fb74c5ea813e354f23493e.png new file mode 100644 index 0000000000000000000000000000000000000000..a138ba1e4abc9585981cec4cf4429450bf416c18 Binary files /dev/null and b/docs/img/7e5039b0d8fb74c5ea813e354f23493e.png differ diff --git a/docs/img/7ebc386f852ada24782fd3b7e5dd226e.png b/docs/img/7ebc386f852ada24782fd3b7e5dd226e.png new file mode 100644 index 0000000000000000000000000000000000000000..8e97f831404b3282077e93cbc1d2e2b7840fd9ec Binary files /dev/null and b/docs/img/7ebc386f852ada24782fd3b7e5dd226e.png differ diff --git a/docs/img/7efae901a0febb2a8e969415dced271a.png b/docs/img/7efae901a0febb2a8e969415dced271a.png new file mode 100644 index 0000000000000000000000000000000000000000..7761319c37991d0fb9b69da2b02902c196a5aec3 Binary files /dev/null and b/docs/img/7efae901a0febb2a8e969415dced271a.png differ diff --git a/docs/img/7f1a1847005ab07ba8259a9e67005213.png b/docs/img/7f1a1847005ab07ba8259a9e67005213.png new file mode 100644 index 0000000000000000000000000000000000000000..8f5f63bf83b84e6ae0703d92c6d05300964db8fd Binary files /dev/null and b/docs/img/7f1a1847005ab07ba8259a9e67005213.png differ diff --git a/docs/img/7f8f5e942a32629817a87b08e33d9071.png b/docs/img/7f8f5e942a32629817a87b08e33d9071.png new file mode 100644 index 0000000000000000000000000000000000000000..aabf65e1ae346142d35e056ea3eb5cc9a7cc071e Binary files /dev/null and b/docs/img/7f8f5e942a32629817a87b08e33d9071.png differ diff --git a/docs/img/7fb24fed9f39dcdabb530523bcb8dc08.png b/docs/img/7fb24fed9f39dcdabb530523bcb8dc08.png new file mode 100644 index 0000000000000000000000000000000000000000..ae578d8d0a16bf657fc7cd9cf2c118d127275f93 Binary files /dev/null and b/docs/img/7fb24fed9f39dcdabb530523bcb8dc08.png differ diff --git a/docs/img/7ff67c276870da733a9bc04b2aa9d969.png b/docs/img/7ff67c276870da733a9bc04b2aa9d969.png new file mode 100644 index 0000000000000000000000000000000000000000..c3ed48957331c3e6dce00ea5eb900024bdc9e415 Binary files /dev/null and b/docs/img/7ff67c276870da733a9bc04b2aa9d969.png differ diff --git a/docs/img/8013884e699eb543397343ba53b7f107.png b/docs/img/8013884e699eb543397343ba53b7f107.png new file mode 100644 index 0000000000000000000000000000000000000000..f33004d590c5522c31fad2450fed92d0e3940426 Binary files /dev/null and b/docs/img/8013884e699eb543397343ba53b7f107.png differ diff --git a/docs/img/801adc20d157f18e08adbd379180f3c7.png b/docs/img/801adc20d157f18e08adbd379180f3c7.png new file mode 100644 index 0000000000000000000000000000000000000000..4a051e5aabcfd8d57b6a91013e7e5fa9372de4c0 Binary files /dev/null and b/docs/img/801adc20d157f18e08adbd379180f3c7.png differ diff --git a/docs/img/8069500bf085102224933129529dfa12.png b/docs/img/8069500bf085102224933129529dfa12.png new file mode 100644 index 0000000000000000000000000000000000000000..216ec28c67be58b73ae7518f4c8a537f10e74b71 Binary files /dev/null and b/docs/img/8069500bf085102224933129529dfa12.png differ diff --git a/docs/img/806d03909b4b194f095b4c69e175868d.png b/docs/img/806d03909b4b194f095b4c69e175868d.png new file mode 100644 index 0000000000000000000000000000000000000000..789128b4aafb4d9d60f22b0060e6c8d3b88789e5 Binary files /dev/null and b/docs/img/806d03909b4b194f095b4c69e175868d.png differ diff --git a/docs/img/8095440bd29d634de897ae56f76a4969.png b/docs/img/8095440bd29d634de897ae56f76a4969.png new file mode 100644 index 0000000000000000000000000000000000000000..8946c3b3b1008c97b9282955d8985e0ab2a54371 Binary files /dev/null and b/docs/img/8095440bd29d634de897ae56f76a4969.png differ diff --git a/docs/img/80a62bce7846a67c7743ef7324a58757.png b/docs/img/80a62bce7846a67c7743ef7324a58757.png new file mode 100644 index 0000000000000000000000000000000000000000..b3e227ab5fe30abf735d9d9652b8c2ad5b98e115 Binary files /dev/null and b/docs/img/80a62bce7846a67c7743ef7324a58757.png differ diff --git a/docs/img/80a9fe0374f84134fa2b40172431604d.png b/docs/img/80a9fe0374f84134fa2b40172431604d.png new file mode 100644 index 0000000000000000000000000000000000000000..a9c76bc158d6151125bc33d09d6a0f6ca92679f0 Binary files /dev/null and b/docs/img/80a9fe0374f84134fa2b40172431604d.png differ diff --git a/docs/img/813cda0881e353d15eed9ca9417104f1.png b/docs/img/813cda0881e353d15eed9ca9417104f1.png new file mode 100644 index 0000000000000000000000000000000000000000..fd6d3b3fb492718b56baf074ac3013b36001b1fc Binary files /dev/null and b/docs/img/813cda0881e353d15eed9ca9417104f1.png differ diff --git a/docs/img/813e077e7aa22bb747b5f237984f1b22.png b/docs/img/813e077e7aa22bb747b5f237984f1b22.png new file mode 100644 index 0000000000000000000000000000000000000000..d2237fa602977d0d24cf0a640db07e09ba58588c Binary files /dev/null and b/docs/img/813e077e7aa22bb747b5f237984f1b22.png differ diff --git a/docs/img/81b83780f68abcbb32edb1eb48002a4d.png b/docs/img/81b83780f68abcbb32edb1eb48002a4d.png new file mode 100644 index 0000000000000000000000000000000000000000..1538700b7db8ced089bbf6249b047778125713d3 Binary files /dev/null and b/docs/img/81b83780f68abcbb32edb1eb48002a4d.png differ diff --git a/docs/img/81c888ba61ab652f9505d5b51406ed22.png b/docs/img/81c888ba61ab652f9505d5b51406ed22.png new file mode 100644 index 0000000000000000000000000000000000000000..0d55b392a20b7e3084d0644dfe5f931358ea12b2 Binary files /dev/null and b/docs/img/81c888ba61ab652f9505d5b51406ed22.png differ diff --git a/docs/img/81cb03504811f2ae5f008de13366a1db.png b/docs/img/81cb03504811f2ae5f008de13366a1db.png new file mode 100644 index 0000000000000000000000000000000000000000..4bf124d8732da09fb77711f5ea8cc1bf8cf6735e Binary files /dev/null and b/docs/img/81cb03504811f2ae5f008de13366a1db.png differ diff --git a/docs/img/81fe297de1dccaedd3340735454273bc.png b/docs/img/81fe297de1dccaedd3340735454273bc.png new file mode 100644 index 0000000000000000000000000000000000000000..eeb97c26b674f4945b2fad3e5e08f541b69e4f38 Binary files /dev/null and b/docs/img/81fe297de1dccaedd3340735454273bc.png differ diff --git a/docs/img/8201105b83669750c4d60036b41f6c6d.png b/docs/img/8201105b83669750c4d60036b41f6c6d.png new file mode 100644 index 0000000000000000000000000000000000000000..9e15c82ffaaab2fb64c69c766ad51ad99a0eeba3 Binary files /dev/null and b/docs/img/8201105b83669750c4d60036b41f6c6d.png differ diff --git a/docs/img/8215c374294289cd2bd24399439403fd.png b/docs/img/8215c374294289cd2bd24399439403fd.png new file mode 100644 index 0000000000000000000000000000000000000000..3dea589160bdb4ba364fb7a6e0c15066932c754d Binary files /dev/null and b/docs/img/8215c374294289cd2bd24399439403fd.png differ diff --git a/docs/img/82c2caa32c2aff60b744c3ede8725ac9.png b/docs/img/82c2caa32c2aff60b744c3ede8725ac9.png new file mode 100644 index 0000000000000000000000000000000000000000..a625f142341369f39c0397b7c16c6f322b868bbb Binary files /dev/null and b/docs/img/82c2caa32c2aff60b744c3ede8725ac9.png differ diff --git a/docs/img/8308fbab7a41e24cad0bf6c358863ae3.png b/docs/img/8308fbab7a41e24cad0bf6c358863ae3.png new file mode 100644 index 0000000000000000000000000000000000000000..a538e55ad6b0edc2ab1a983939536e301797fe5d Binary files /dev/null and b/docs/img/8308fbab7a41e24cad0bf6c358863ae3.png differ diff --git a/docs/img/8375b8805ee35febb22389954e463cb3.png b/docs/img/8375b8805ee35febb22389954e463cb3.png new file mode 100644 index 0000000000000000000000000000000000000000..c8fad0ac9430a9c10884371d30600252415a788f Binary files /dev/null and b/docs/img/8375b8805ee35febb22389954e463cb3.png differ diff --git a/docs/img/838245c530d1afaf54929d9edd3f6a24.png b/docs/img/838245c530d1afaf54929d9edd3f6a24.png new file mode 100644 index 0000000000000000000000000000000000000000..ea36b83c43dd5dd2d707be92dc367778a151f56e Binary files /dev/null and b/docs/img/838245c530d1afaf54929d9edd3f6a24.png differ diff --git a/docs/img/83a4859fc1c1d9fc2ea68819a53eaea8.png b/docs/img/83a4859fc1c1d9fc2ea68819a53eaea8.png new file mode 100644 index 0000000000000000000000000000000000000000..33877d9fa94579eca3c7d6b71d0eee32f678bd25 Binary files /dev/null and b/docs/img/83a4859fc1c1d9fc2ea68819a53eaea8.png differ diff --git a/docs/img/83da8fe833233875ee4fe28fa21eb1dd.png b/docs/img/83da8fe833233875ee4fe28fa21eb1dd.png new file mode 100644 index 0000000000000000000000000000000000000000..1374e3093d2331527b9cec14a4b4c2fda50b83a8 Binary files /dev/null and b/docs/img/83da8fe833233875ee4fe28fa21eb1dd.png differ diff --git a/docs/img/8465cc4b8bf68fad2a64c9fc838c7939.png b/docs/img/8465cc4b8bf68fad2a64c9fc838c7939.png new file mode 100644 index 0000000000000000000000000000000000000000..2c24a5a46a000296c648380d5e9ae67024b35d58 Binary files /dev/null and b/docs/img/8465cc4b8bf68fad2a64c9fc838c7939.png differ diff --git a/docs/img/8489a6c45ad75964ea7b4b54b9d9fcaa.png b/docs/img/8489a6c45ad75964ea7b4b54b9d9fcaa.png new file mode 100644 index 0000000000000000000000000000000000000000..4eebb382b28bae807c42399c538e03f5a38dcee5 Binary files /dev/null and b/docs/img/8489a6c45ad75964ea7b4b54b9d9fcaa.png differ diff --git a/docs/img/85055487485aff8bd5dc0cf97f711d52.png b/docs/img/85055487485aff8bd5dc0cf97f711d52.png new file mode 100644 index 0000000000000000000000000000000000000000..a3de5a934f534c9ef127f3801b45299e50c8dc8a Binary files /dev/null and b/docs/img/85055487485aff8bd5dc0cf97f711d52.png differ diff --git a/docs/img/854d722d9976d5b36956ddbe41ceae48.png b/docs/img/854d722d9976d5b36956ddbe41ceae48.png new file mode 100644 index 0000000000000000000000000000000000000000..08cb1c640c74ec821fde93cbcaad62f00c6d7ddd Binary files /dev/null and b/docs/img/854d722d9976d5b36956ddbe41ceae48.png differ diff --git a/docs/img/85b07bb9804f9dd3c4e3edfc1e562f31.png b/docs/img/85b07bb9804f9dd3c4e3edfc1e562f31.png new file mode 100644 index 0000000000000000000000000000000000000000..240c9b6f3b6d2243c1827bfbace2775372244ab6 Binary files /dev/null and b/docs/img/85b07bb9804f9dd3c4e3edfc1e562f31.png differ diff --git a/docs/img/865329b4b113d6de44cf382bd77178fa.png b/docs/img/865329b4b113d6de44cf382bd77178fa.png new file mode 100644 index 0000000000000000000000000000000000000000..7dab3d5a83ff7a1a7d48f36cd23cefe982f767cb Binary files /dev/null and b/docs/img/865329b4b113d6de44cf382bd77178fa.png differ diff --git a/docs/img/865915f0e39a0035ffc91de736f5a047.png b/docs/img/865915f0e39a0035ffc91de736f5a047.png new file mode 100644 index 0000000000000000000000000000000000000000..344f4191752d2fa0f885b93c50b04ffcb9b62026 Binary files /dev/null and b/docs/img/865915f0e39a0035ffc91de736f5a047.png differ diff --git a/docs/img/86614ecfb76f8a91344d98d3effa7d2a.png b/docs/img/86614ecfb76f8a91344d98d3effa7d2a.png new file mode 100644 index 0000000000000000000000000000000000000000..f962cc4a4687aa3e76d2c010d4c11e62492c11f1 Binary files /dev/null and b/docs/img/86614ecfb76f8a91344d98d3effa7d2a.png differ diff --git a/docs/img/86738432aa05c0c68fffb68c00788fa4.png b/docs/img/86738432aa05c0c68fffb68c00788fa4.png new file mode 100644 index 0000000000000000000000000000000000000000..8c88a72d600a9bb0d9060e1f876594269cf0f63c Binary files /dev/null and b/docs/img/86738432aa05c0c68fffb68c00788fa4.png differ diff --git a/docs/img/86b62f200c6aa129ed945d20ec0fbfa2.png b/docs/img/86b62f200c6aa129ed945d20ec0fbfa2.png new file mode 100644 index 0000000000000000000000000000000000000000..20b7c7e40776fe0dd817fb440dc37c89bbaa77b2 Binary files /dev/null and b/docs/img/86b62f200c6aa129ed945d20ec0fbfa2.png differ diff --git a/docs/img/86c94810add9e77037bd8a135ef2b972.png b/docs/img/86c94810add9e77037bd8a135ef2b972.png new file mode 100644 index 0000000000000000000000000000000000000000..5dad2a06ad21f85d0adc19652c797868125fdf82 Binary files /dev/null and b/docs/img/86c94810add9e77037bd8a135ef2b972.png differ diff --git a/docs/img/874270632cfad28b99af65b5d0275fee.png b/docs/img/874270632cfad28b99af65b5d0275fee.png new file mode 100644 index 0000000000000000000000000000000000000000..8531365e51bcba091818ee069efc473f5db33c32 Binary files /dev/null and b/docs/img/874270632cfad28b99af65b5d0275fee.png differ diff --git a/docs/img/878c3488cf7403499b80fcd402198e32.png b/docs/img/878c3488cf7403499b80fcd402198e32.png new file mode 100644 index 0000000000000000000000000000000000000000..2b05b8e67814ed8315cfb85cbb5e01536e68a8c6 Binary files /dev/null and b/docs/img/878c3488cf7403499b80fcd402198e32.png differ diff --git a/docs/img/87be547831d2207399009a0f9dd4b91a.png b/docs/img/87be547831d2207399009a0f9dd4b91a.png new file mode 100644 index 0000000000000000000000000000000000000000..03025f156ea587e9898c17f2b63ba61df98521be Binary files /dev/null and b/docs/img/87be547831d2207399009a0f9dd4b91a.png differ diff --git a/docs/img/8855ae33dbb80420649c523afdf3fe8b.png b/docs/img/8855ae33dbb80420649c523afdf3fe8b.png new file mode 100644 index 0000000000000000000000000000000000000000..2d42314141e23968e906e9cbaaa19453f8c11f76 Binary files /dev/null and b/docs/img/8855ae33dbb80420649c523afdf3fe8b.png differ diff --git a/docs/img/89c2a0a388333182ff39563629933a87.png b/docs/img/89c2a0a388333182ff39563629933a87.png new file mode 100644 index 0000000000000000000000000000000000000000..fb63d1db918d9719f4190010b9a7874adc2a0965 Binary files /dev/null and b/docs/img/89c2a0a388333182ff39563629933a87.png differ diff --git a/docs/img/8a05f3552d23f56607411f613a5ceb05.png b/docs/img/8a05f3552d23f56607411f613a5ceb05.png new file mode 100644 index 0000000000000000000000000000000000000000..b7727e9ad8a669a0f6e74820feae975d474aa3cb Binary files /dev/null and b/docs/img/8a05f3552d23f56607411f613a5ceb05.png differ diff --git a/docs/img/8a2c3991978374372fe0370f27f4fad4.png b/docs/img/8a2c3991978374372fe0370f27f4fad4.png new file mode 100644 index 0000000000000000000000000000000000000000..a7181b9e5ba19d76d4cbf0ce57f2081344fb3bef Binary files /dev/null and b/docs/img/8a2c3991978374372fe0370f27f4fad4.png differ diff --git a/docs/img/8a4af39c416005af074623092e32d782.png b/docs/img/8a4af39c416005af074623092e32d782.png new file mode 100644 index 0000000000000000000000000000000000000000..e69dd08f4a08bb1584fb0b74c046b94b50106253 Binary files /dev/null and b/docs/img/8a4af39c416005af074623092e32d782.png differ diff --git a/docs/img/8a56e678752a9bd9def98422dee92f3e.png b/docs/img/8a56e678752a9bd9def98422dee92f3e.png new file mode 100644 index 0000000000000000000000000000000000000000..1e7aebb8fad7c6a2a63e3c00e9104f0eee00571f Binary files /dev/null and b/docs/img/8a56e678752a9bd9def98422dee92f3e.png differ diff --git a/docs/img/8a6c0fc733a099005b7f7f9bcfbfe2ff.png b/docs/img/8a6c0fc733a099005b7f7f9bcfbfe2ff.png new file mode 100644 index 0000000000000000000000000000000000000000..cf8112c09bde702d1541703fc8aabefa924efc0e Binary files /dev/null and b/docs/img/8a6c0fc733a099005b7f7f9bcfbfe2ff.png differ diff --git a/docs/img/8ab62c2dee9f26abae9b7f794b4f5fae.png b/docs/img/8ab62c2dee9f26abae9b7f794b4f5fae.png new file mode 100644 index 0000000000000000000000000000000000000000..f04d77f4ee2d216f6f2dfddf9bb71900ffdeadb5 Binary files /dev/null and b/docs/img/8ab62c2dee9f26abae9b7f794b4f5fae.png differ diff --git a/docs/img/8c47dc71d95554edf7da34adb5acc575.png b/docs/img/8c47dc71d95554edf7da34adb5acc575.png new file mode 100644 index 0000000000000000000000000000000000000000..4dd276abe23f7ad29021e6a703c9da160cd70bf4 Binary files /dev/null and b/docs/img/8c47dc71d95554edf7da34adb5acc575.png differ diff --git a/docs/img/8c80632a58ede646cb8f2046924a504a.png b/docs/img/8c80632a58ede646cb8f2046924a504a.png new file mode 100644 index 0000000000000000000000000000000000000000..6e373e67fa6eb0d9f3bd27b4e2d48ec970361b06 Binary files /dev/null and b/docs/img/8c80632a58ede646cb8f2046924a504a.png differ diff --git a/docs/img/8cebf5d928a8666adcfc25eccfeec89e.png b/docs/img/8cebf5d928a8666adcfc25eccfeec89e.png new file mode 100644 index 0000000000000000000000000000000000000000..01825cc8fd9bf50c4a00eb08e87c8d834dcfdb90 Binary files /dev/null and b/docs/img/8cebf5d928a8666adcfc25eccfeec89e.png differ diff --git a/docs/img/8d249dc6a1ff208c520bfc8cad423a4a.png b/docs/img/8d249dc6a1ff208c520bfc8cad423a4a.png new file mode 100644 index 0000000000000000000000000000000000000000..63c807d19973afe9f79cef67350a298b8999df2a Binary files /dev/null and b/docs/img/8d249dc6a1ff208c520bfc8cad423a4a.png differ diff --git a/docs/img/8d66587fae4dab1dca05f85389caa499.png b/docs/img/8d66587fae4dab1dca05f85389caa499.png new file mode 100644 index 0000000000000000000000000000000000000000..25be05639dda8ee12eb4798217d8e8ac7f63a110 Binary files /dev/null and b/docs/img/8d66587fae4dab1dca05f85389caa499.png differ diff --git a/docs/img/8db9ef3ba0d1153ab46b990e98372677.png b/docs/img/8db9ef3ba0d1153ab46b990e98372677.png new file mode 100644 index 0000000000000000000000000000000000000000..e3a36133a623653e6e9dae7dc58bb72199b1e0be Binary files /dev/null and b/docs/img/8db9ef3ba0d1153ab46b990e98372677.png differ diff --git a/docs/img/8e301ace1928e93f6138075596994c18.png b/docs/img/8e301ace1928e93f6138075596994c18.png new file mode 100644 index 0000000000000000000000000000000000000000..fe03578d4a09f64c7412ed345a139a4c5fb995fc Binary files /dev/null and b/docs/img/8e301ace1928e93f6138075596994c18.png differ diff --git a/docs/img/8e5585152d153d9f1f4073f0cddba269.png b/docs/img/8e5585152d153d9f1f4073f0cddba269.png new file mode 100644 index 0000000000000000000000000000000000000000..0258d8c68f88937ef59d0dda6fe406842d1c0601 --- /dev/null +++ b/docs/img/8e5585152d153d9f1f4073f0cddba269.png @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + Frontend Coverage + + + Frontend Coverage + + + 39.78% + + + 39.78% + + + + diff --git a/docs/img/8ec36cbe2f746b6b6cc0d28e1620899a.png b/docs/img/8ec36cbe2f746b6b6cc0d28e1620899a.png new file mode 100644 index 0000000000000000000000000000000000000000..2a3024c398a7a108ae3b277ba9877d29dd7b3373 Binary files /dev/null and b/docs/img/8ec36cbe2f746b6b6cc0d28e1620899a.png differ diff --git a/docs/img/8edd1cbf476ddc76f3df25fdeff8b55c.png b/docs/img/8edd1cbf476ddc76f3df25fdeff8b55c.png new file mode 100644 index 0000000000000000000000000000000000000000..c21ebbbc3f4294a95a5cbccda44338866756a5d7 Binary files /dev/null and b/docs/img/8edd1cbf476ddc76f3df25fdeff8b55c.png differ diff --git a/docs/img/8f07bae8fce74cd6b8276b7dd9e59c2e.png b/docs/img/8f07bae8fce74cd6b8276b7dd9e59c2e.png new file mode 100644 index 0000000000000000000000000000000000000000..5136f5d0477e49d0e7c28e98d5b80f7a8d3f95c9 Binary files /dev/null and b/docs/img/8f07bae8fce74cd6b8276b7dd9e59c2e.png differ diff --git a/docs/img/8f8d204a16e9c896b01a62220529b921.png b/docs/img/8f8d204a16e9c896b01a62220529b921.png new file mode 100644 index 0000000000000000000000000000000000000000..e24457030045f6c98c87927e15826ed25b436b53 Binary files /dev/null and b/docs/img/8f8d204a16e9c896b01a62220529b921.png differ diff --git a/docs/img/8fc9989164e038f62ee1015c2f477d84.png b/docs/img/8fc9989164e038f62ee1015c2f477d84.png new file mode 100644 index 0000000000000000000000000000000000000000..f2beb6c1c0a71a2fde2c3e43400d31ecb9559b5e Binary files /dev/null and b/docs/img/8fc9989164e038f62ee1015c2f477d84.png differ diff --git a/docs/img/906ca69aaf7c7a7f53479eb595f83ec0.png b/docs/img/906ca69aaf7c7a7f53479eb595f83ec0.png new file mode 100644 index 0000000000000000000000000000000000000000..e54bc3434bd62c36316fb17abc8e91456147fe58 Binary files /dev/null and b/docs/img/906ca69aaf7c7a7f53479eb595f83ec0.png differ diff --git a/docs/img/9079254cc7f9fbc13ee5005765608b59.png b/docs/img/9079254cc7f9fbc13ee5005765608b59.png new file mode 100644 index 0000000000000000000000000000000000000000..d8173eaea89d94238ae0409347ad5f471361fd38 Binary files /dev/null and b/docs/img/9079254cc7f9fbc13ee5005765608b59.png differ diff --git a/docs/img/909d20c0dd57155c8ac404a81c2a30cb.png b/docs/img/909d20c0dd57155c8ac404a81c2a30cb.png new file mode 100644 index 0000000000000000000000000000000000000000..e8351a2db33d28abc8f35656d333a4e7cd93c55f Binary files /dev/null and b/docs/img/909d20c0dd57155c8ac404a81c2a30cb.png differ diff --git a/docs/img/90bcd1f29936328bfb5d344868b8bb81.png b/docs/img/90bcd1f29936328bfb5d344868b8bb81.png new file mode 100644 index 0000000000000000000000000000000000000000..3bc06c49ba50b8a3a77ce8ea5e3decafbc5df4b3 Binary files /dev/null and b/docs/img/90bcd1f29936328bfb5d344868b8bb81.png differ diff --git a/docs/img/9101937463fa0be989f93d09d9f54d7a.png b/docs/img/9101937463fa0be989f93d09d9f54d7a.png new file mode 100644 index 0000000000000000000000000000000000000000..5e908eaed5ecbd76209cb21147d7a79cbe609faa Binary files /dev/null and b/docs/img/9101937463fa0be989f93d09d9f54d7a.png differ diff --git a/docs/img/911c6aa51b9202fc3dc3bdc143b30f82.png b/docs/img/911c6aa51b9202fc3dc3bdc143b30f82.png new file mode 100644 index 0000000000000000000000000000000000000000..b7da623ddc6e29a978c75fa45e4138ec6b9dc442 Binary files /dev/null and b/docs/img/911c6aa51b9202fc3dc3bdc143b30f82.png differ diff --git a/docs/img/9121e1772146daa5a3259be82cde8902.png b/docs/img/9121e1772146daa5a3259be82cde8902.png new file mode 100644 index 0000000000000000000000000000000000000000..fc7f7e9c14c210c966b36e7fdf6a41898b7f6252 Binary files /dev/null and b/docs/img/9121e1772146daa5a3259be82cde8902.png differ diff --git a/docs/img/9149638f26311ced385bcc879401a8fd.png b/docs/img/9149638f26311ced385bcc879401a8fd.png new file mode 100644 index 0000000000000000000000000000000000000000..55d23448f888adfbc61526f133fbd8a3ce6f23a7 Binary files /dev/null and b/docs/img/9149638f26311ced385bcc879401a8fd.png differ diff --git a/docs/img/91abd5be225ec3a5c131075cce857fb8.png b/docs/img/91abd5be225ec3a5c131075cce857fb8.png new file mode 100644 index 0000000000000000000000000000000000000000..9c0dc541896b9cac603731e533b25a7bca362553 Binary files /dev/null and b/docs/img/91abd5be225ec3a5c131075cce857fb8.png differ diff --git a/docs/img/9246e597493024c10e4f678f7de7318e.png b/docs/img/9246e597493024c10e4f678f7de7318e.png new file mode 100644 index 0000000000000000000000000000000000000000..9ffbecd33110288647379e33f28978acd0598997 Binary files /dev/null and b/docs/img/9246e597493024c10e4f678f7de7318e.png differ diff --git a/docs/img/9255a795b62eb0bbe1c91eab2f85c149.png b/docs/img/9255a795b62eb0bbe1c91eab2f85c149.png new file mode 100644 index 0000000000000000000000000000000000000000..8a69bdcc41c02e6144776ee0e179c16fc8a74175 Binary files /dev/null and b/docs/img/9255a795b62eb0bbe1c91eab2f85c149.png differ diff --git a/docs/img/92601175945fcac1aee644fd449e9adf.png b/docs/img/92601175945fcac1aee644fd449e9adf.png new file mode 100644 index 0000000000000000000000000000000000000000..a4975605d2f0a9f474155858205ea6cc153b9532 Binary files /dev/null and b/docs/img/92601175945fcac1aee644fd449e9adf.png differ diff --git a/docs/img/9443fbb9f077bc7be6beb1486c392c96.png b/docs/img/9443fbb9f077bc7be6beb1486c392c96.png new file mode 100644 index 0000000000000000000000000000000000000000..69d05e3b572b5bc63fa38658f6fb3f0bdc4fd106 Binary files /dev/null and b/docs/img/9443fbb9f077bc7be6beb1486c392c96.png differ diff --git a/docs/img/94675a32947787d4e216a44e3047d0b5.png b/docs/img/94675a32947787d4e216a44e3047d0b5.png new file mode 100644 index 0000000000000000000000000000000000000000..163d36cd86ecbe6249ba4d32cb67a9e3f34ff8da Binary files /dev/null and b/docs/img/94675a32947787d4e216a44e3047d0b5.png differ diff --git a/docs/img/94b9b90ebfb15979835f3e48d710cb45.png b/docs/img/94b9b90ebfb15979835f3e48d710cb45.png new file mode 100644 index 0000000000000000000000000000000000000000..1d1a99ad8bd54cc19a618010e9dc459ad69cb117 Binary files /dev/null and b/docs/img/94b9b90ebfb15979835f3e48d710cb45.png differ diff --git a/docs/img/94be136c7407855701b88eaded7db929.png b/docs/img/94be136c7407855701b88eaded7db929.png new file mode 100644 index 0000000000000000000000000000000000000000..aeb7a87a4070d681a9dfc05ffd3e2d969e7bcef7 Binary files /dev/null and b/docs/img/94be136c7407855701b88eaded7db929.png differ diff --git a/docs/img/9570df3750a76ee8a88eddb48512daa3.png b/docs/img/9570df3750a76ee8a88eddb48512daa3.png new file mode 100644 index 0000000000000000000000000000000000000000..05a49bb224b445f40d8200d5853fd6f923734201 Binary files /dev/null and b/docs/img/9570df3750a76ee8a88eddb48512daa3.png differ diff --git a/docs/img/95882a4976be6b95971ad0011fcd7617.png b/docs/img/95882a4976be6b95971ad0011fcd7617.png new file mode 100644 index 0000000000000000000000000000000000000000..d86bfecc748598ea82f127244f3db2c55784cd8a Binary files /dev/null and b/docs/img/95882a4976be6b95971ad0011fcd7617.png differ diff --git a/docs/img/95c0b87af108caee2a239482aec61675.png b/docs/img/95c0b87af108caee2a239482aec61675.png new file mode 100644 index 0000000000000000000000000000000000000000..3308fc37f525e50502b6360c3ee49936be24d44a Binary files /dev/null and b/docs/img/95c0b87af108caee2a239482aec61675.png differ diff --git a/docs/img/95cf4cb85bf824cf0817d4d93d93934d.png b/docs/img/95cf4cb85bf824cf0817d4d93d93934d.png new file mode 100644 index 0000000000000000000000000000000000000000..93abd4cb804cf5aa4381a08a2bf45a9e68a9448d Binary files /dev/null and b/docs/img/95cf4cb85bf824cf0817d4d93d93934d.png differ diff --git a/docs/img/96aa3b50d60a091349e8d39c74877a5d.png b/docs/img/96aa3b50d60a091349e8d39c74877a5d.png new file mode 100644 index 0000000000000000000000000000000000000000..9f7455e9c8205ec266497f1908977494040ea197 Binary files /dev/null and b/docs/img/96aa3b50d60a091349e8d39c74877a5d.png differ diff --git a/docs/img/96c6ce839dca0e2ef2d69b8fbc0cff56.png b/docs/img/96c6ce839dca0e2ef2d69b8fbc0cff56.png new file mode 100644 index 0000000000000000000000000000000000000000..fd98a4987a1e925254e93145bff236e2b09bf119 Binary files /dev/null and b/docs/img/96c6ce839dca0e2ef2d69b8fbc0cff56.png differ diff --git a/docs/img/97acbf99c97921ca9e5837c4c70cfa4c.png b/docs/img/97acbf99c97921ca9e5837c4c70cfa4c.png new file mode 100644 index 0000000000000000000000000000000000000000..b76e70d3c315b259b90b6befa0d930764191fb49 Binary files /dev/null and b/docs/img/97acbf99c97921ca9e5837c4c70cfa4c.png differ diff --git a/docs/img/97c7baeb5e993264f4619e443bdacebc.png b/docs/img/97c7baeb5e993264f4619e443bdacebc.png new file mode 100644 index 0000000000000000000000000000000000000000..d172c780e2a02c2b0a802594830676034508bc9b Binary files /dev/null and b/docs/img/97c7baeb5e993264f4619e443bdacebc.png differ diff --git a/docs/img/9807a6b10b783af2ed7c8703958f017a.png b/docs/img/9807a6b10b783af2ed7c8703958f017a.png new file mode 100644 index 0000000000000000000000000000000000000000..57388926ce1e215c08cf20f4e44d5b52eb18a80b Binary files /dev/null and b/docs/img/9807a6b10b783af2ed7c8703958f017a.png differ diff --git a/docs/img/987208c515a3f2627904cc38b355dc15.png b/docs/img/987208c515a3f2627904cc38b355dc15.png new file mode 100644 index 0000000000000000000000000000000000000000..b7bcaa672b06431d210394760c1ac9e6436fb66f Binary files /dev/null and b/docs/img/987208c515a3f2627904cc38b355dc15.png differ diff --git a/docs/img/98f7e80b6f738f9886082aeec3955fd5.png b/docs/img/98f7e80b6f738f9886082aeec3955fd5.png new file mode 100644 index 0000000000000000000000000000000000000000..b99da0fd3d3a0f2eadfa5c98b95a339af78e9117 Binary files /dev/null and b/docs/img/98f7e80b6f738f9886082aeec3955fd5.png differ diff --git a/docs/img/993315f2d7b2aa15b2f3faa03d14705c.png b/docs/img/993315f2d7b2aa15b2f3faa03d14705c.png new file mode 100644 index 0000000000000000000000000000000000000000..a9383d232435068292a52336e20a44635a9fb36a Binary files /dev/null and b/docs/img/993315f2d7b2aa15b2f3faa03d14705c.png differ diff --git a/docs/img/9950340e3b641e3f63d70fb29b2b05bb.png b/docs/img/9950340e3b641e3f63d70fb29b2b05bb.png new file mode 100644 index 0000000000000000000000000000000000000000..a242da8cdd8d731a26e4078cdee3c49a6cf8e1ea Binary files /dev/null and b/docs/img/9950340e3b641e3f63d70fb29b2b05bb.png differ diff --git a/docs/img/996ea860188e6458fe761cf86b2b72b1.png b/docs/img/996ea860188e6458fe761cf86b2b72b1.png new file mode 100644 index 0000000000000000000000000000000000000000..ffe75604b231a134ee06dd3207ec4788cd5af7c0 Binary files /dev/null and b/docs/img/996ea860188e6458fe761cf86b2b72b1.png differ diff --git a/docs/img/9a002df90c6ed1d01c8ae3a9817242df.png b/docs/img/9a002df90c6ed1d01c8ae3a9817242df.png new file mode 100644 index 0000000000000000000000000000000000000000..bcc242173bbe34c756865912a58de6f7a63eabc6 Binary files /dev/null and b/docs/img/9a002df90c6ed1d01c8ae3a9817242df.png differ diff --git a/docs/img/9a996b513114d1fe39fa67c75e54df46.png b/docs/img/9a996b513114d1fe39fa67c75e54df46.png new file mode 100644 index 0000000000000000000000000000000000000000..7a9424eb0de9acd872081424b6b38570122b80f9 Binary files /dev/null and b/docs/img/9a996b513114d1fe39fa67c75e54df46.png differ diff --git a/docs/img/9aa51957855aec8590e352694fe75d5d.png b/docs/img/9aa51957855aec8590e352694fe75d5d.png new file mode 100644 index 0000000000000000000000000000000000000000..7c5531c1603c3a41cdd98ad2e13705a69d666a88 Binary files /dev/null and b/docs/img/9aa51957855aec8590e352694fe75d5d.png differ diff --git a/docs/img/9abb23a34d42854b307382ef64d9a013.png b/docs/img/9abb23a34d42854b307382ef64d9a013.png new file mode 100644 index 0000000000000000000000000000000000000000..aa63c6ea67a6fe50443d5e6883e7db70e5200031 Binary files /dev/null and b/docs/img/9abb23a34d42854b307382ef64d9a013.png differ diff --git a/docs/img/9b6a8d0d96113fcaadd766cecfbecdbc.png b/docs/img/9b6a8d0d96113fcaadd766cecfbecdbc.png new file mode 100644 index 0000000000000000000000000000000000000000..2964219482bbdfb75b51116d8ba5fe8598805eaa Binary files /dev/null and b/docs/img/9b6a8d0d96113fcaadd766cecfbecdbc.png differ diff --git a/docs/img/9bc04e4a71e5ed3917efabdca45725c7.png b/docs/img/9bc04e4a71e5ed3917efabdca45725c7.png new file mode 100644 index 0000000000000000000000000000000000000000..e4661bd012ddb2b790f319a9be2f9bfab3380674 Binary files /dev/null and b/docs/img/9bc04e4a71e5ed3917efabdca45725c7.png differ diff --git a/docs/img/9bf0c7423d5735ccdfbdfe250f9a5452.png b/docs/img/9bf0c7423d5735ccdfbdfe250f9a5452.png new file mode 100644 index 0000000000000000000000000000000000000000..548879d32967becfd210d487f3f6434d9fefa085 Binary files /dev/null and b/docs/img/9bf0c7423d5735ccdfbdfe250f9a5452.png differ diff --git a/docs/img/9cb5bb737c82aad68bc28e2a7357e05c.png b/docs/img/9cb5bb737c82aad68bc28e2a7357e05c.png new file mode 100644 index 0000000000000000000000000000000000000000..8358c7bcd00c4778a1bd79231f053e9c587e48c9 Binary files /dev/null and b/docs/img/9cb5bb737c82aad68bc28e2a7357e05c.png differ diff --git a/docs/img/9cc2ca9eb5afc113cacfbc529374fe3b.png b/docs/img/9cc2ca9eb5afc113cacfbc529374fe3b.png new file mode 100644 index 0000000000000000000000000000000000000000..9511a76fa2634875ef75f017d819701b5c9bb72e Binary files /dev/null and b/docs/img/9cc2ca9eb5afc113cacfbc529374fe3b.png differ diff --git a/docs/img/9d0b2e21b9be06d263674db132420176.png b/docs/img/9d0b2e21b9be06d263674db132420176.png new file mode 100644 index 0000000000000000000000000000000000000000..d5daff1a91098657c12ad2fb5d7240c16936fd36 Binary files /dev/null and b/docs/img/9d0b2e21b9be06d263674db132420176.png differ diff --git a/docs/img/9d8d2ee20801484a30509d79022ce53c.png b/docs/img/9d8d2ee20801484a30509d79022ce53c.png new file mode 100644 index 0000000000000000000000000000000000000000..4a0ab0fbf79d54dd777748431ac6ea9dbfc83059 Binary files /dev/null and b/docs/img/9d8d2ee20801484a30509d79022ce53c.png differ diff --git a/docs/img/9d9a196fe723b5afc79e2d7b29fd0f4d.png b/docs/img/9d9a196fe723b5afc79e2d7b29fd0f4d.png new file mode 100644 index 0000000000000000000000000000000000000000..05f8d96ad6d69f037eec88ac4c6450b7fa61d4a2 Binary files /dev/null and b/docs/img/9d9a196fe723b5afc79e2d7b29fd0f4d.png differ diff --git a/docs/img/9e7b70cdf92b88509713225035e8e964.png b/docs/img/9e7b70cdf92b88509713225035e8e964.png new file mode 100644 index 0000000000000000000000000000000000000000..905a7568ed31e0efb1496b3fe20d279eda62fc63 Binary files /dev/null and b/docs/img/9e7b70cdf92b88509713225035e8e964.png differ diff --git a/docs/img/9e837ca8522bced4f7b219416c893fe4.png b/docs/img/9e837ca8522bced4f7b219416c893fe4.png new file mode 100644 index 0000000000000000000000000000000000000000..e022c55547856040b709786fa9f126e1c52563f2 Binary files /dev/null and b/docs/img/9e837ca8522bced4f7b219416c893fe4.png differ diff --git a/docs/img/9e8d2b5134e62de656bff96c60c04e10.png b/docs/img/9e8d2b5134e62de656bff96c60c04e10.png new file mode 100644 index 0000000000000000000000000000000000000000..f9fd91e8b82900a5ad34708e355f640236f2ae29 Binary files /dev/null and b/docs/img/9e8d2b5134e62de656bff96c60c04e10.png differ diff --git a/docs/img/9f29552692cfb04d323dc62cc4bc1d1e.png b/docs/img/9f29552692cfb04d323dc62cc4bc1d1e.png new file mode 100644 index 0000000000000000000000000000000000000000..d4165b2f6678d7bfae094c300f0f68601ee3a4d1 Binary files /dev/null and b/docs/img/9f29552692cfb04d323dc62cc4bc1d1e.png differ diff --git a/docs/img/9f4a21c247f193621ddd2f709c4536d7.png b/docs/img/9f4a21c247f193621ddd2f709c4536d7.png new file mode 100644 index 0000000000000000000000000000000000000000..514065291c757a1b88c6c102d6cc78601103bb54 Binary files /dev/null and b/docs/img/9f4a21c247f193621ddd2f709c4536d7.png differ diff --git a/docs/img/9f6da2599274d0db274d6aa19a27fcfc.png b/docs/img/9f6da2599274d0db274d6aa19a27fcfc.png new file mode 100644 index 0000000000000000000000000000000000000000..7bea75c9a31653211eead96517c199877a1fcde7 Binary files /dev/null and b/docs/img/9f6da2599274d0db274d6aa19a27fcfc.png differ diff --git a/docs/img/9f6f0b27f8e7df6c95a3262de502b39f.png b/docs/img/9f6f0b27f8e7df6c95a3262de502b39f.png new file mode 100644 index 0000000000000000000000000000000000000000..cbed54dda354028313af2f40b91154a9c00ff1ea Binary files /dev/null and b/docs/img/9f6f0b27f8e7df6c95a3262de502b39f.png differ diff --git a/docs/img/9fa8173be554c09a1397ae7e064f24e5.png b/docs/img/9fa8173be554c09a1397ae7e064f24e5.png new file mode 100644 index 0000000000000000000000000000000000000000..1358a4e7db05da3d8ca14a59515a0951a25b171f Binary files /dev/null and b/docs/img/9fa8173be554c09a1397ae7e064f24e5.png differ diff --git a/docs/img/9fa9d16dd2302ab20167b7ff1ca62575.png b/docs/img/9fa9d16dd2302ab20167b7ff1ca62575.png new file mode 100644 index 0000000000000000000000000000000000000000..499fabf3ece8eeaf949f1ab703d10ec5546aeebb Binary files /dev/null and b/docs/img/9fa9d16dd2302ab20167b7ff1ca62575.png differ diff --git a/docs/img/9fd7b49e564d04c79644e7fb8c7d7d5d.png b/docs/img/9fd7b49e564d04c79644e7fb8c7d7d5d.png new file mode 100644 index 0000000000000000000000000000000000000000..97c585ca676bc84aed2de286d010310a22e6c747 Binary files /dev/null and b/docs/img/9fd7b49e564d04c79644e7fb8c7d7d5d.png differ diff --git a/docs/img/a0ea9fb503066a9bed377bc4dadb0d59.png b/docs/img/a0ea9fb503066a9bed377bc4dadb0d59.png new file mode 100644 index 0000000000000000000000000000000000000000..4c7e36efef6f487783919fa6e420cf98d2b3ca16 Binary files /dev/null and b/docs/img/a0ea9fb503066a9bed377bc4dadb0d59.png differ diff --git a/docs/img/a102a1abbf4c760dba4b8b3daef8fe26.png b/docs/img/a102a1abbf4c760dba4b8b3daef8fe26.png new file mode 100644 index 0000000000000000000000000000000000000000..2912a66ec6b9e12316cd7c740a0b861f0dd29b04 Binary files /dev/null and b/docs/img/a102a1abbf4c760dba4b8b3daef8fe26.png differ diff --git a/docs/img/a14ce4f4a816ce9ceea3133c64b5f328.png b/docs/img/a14ce4f4a816ce9ceea3133c64b5f328.png new file mode 100644 index 0000000000000000000000000000000000000000..7f33003d7013323e620cafaefab138a55ab2975d Binary files /dev/null and b/docs/img/a14ce4f4a816ce9ceea3133c64b5f328.png differ diff --git a/docs/img/a15f0b2964d7094b019c5c33425ba75b.png b/docs/img/a15f0b2964d7094b019c5c33425ba75b.png new file mode 100644 index 0000000000000000000000000000000000000000..759ab0f27882f1c545cbf7a645330dc880c9fea5 Binary files /dev/null and b/docs/img/a15f0b2964d7094b019c5c33425ba75b.png differ diff --git a/docs/img/a198157b454aaa7b52001592ed46dc03.png b/docs/img/a198157b454aaa7b52001592ed46dc03.png new file mode 100644 index 0000000000000000000000000000000000000000..d428c51824415a41242811c472927b5eda5e79ef Binary files /dev/null and b/docs/img/a198157b454aaa7b52001592ed46dc03.png differ diff --git a/docs/img/a19f68ae0d29248e1f28009bfb10a89a.png b/docs/img/a19f68ae0d29248e1f28009bfb10a89a.png new file mode 100644 index 0000000000000000000000000000000000000000..b64866a24e7b211721fd0010bccb6718c82ff4a7 Binary files /dev/null and b/docs/img/a19f68ae0d29248e1f28009bfb10a89a.png differ diff --git a/docs/img/a1efb7c23a97e2901852465c9168914f.png b/docs/img/a1efb7c23a97e2901852465c9168914f.png new file mode 100644 index 0000000000000000000000000000000000000000..0c246896d06e7c8b3104660b4f906b8f65a43ec2 Binary files /dev/null and b/docs/img/a1efb7c23a97e2901852465c9168914f.png differ diff --git a/docs/img/a1f2874d536bbec36fba8132d424e066.png b/docs/img/a1f2874d536bbec36fba8132d424e066.png new file mode 100644 index 0000000000000000000000000000000000000000..3b27fc95801a148a6fdae396d975ec2bd7571d28 Binary files /dev/null and b/docs/img/a1f2874d536bbec36fba8132d424e066.png differ diff --git a/docs/img/a223e320ef570ec303a4e7346a899af7.png b/docs/img/a223e320ef570ec303a4e7346a899af7.png new file mode 100644 index 0000000000000000000000000000000000000000..ee4680727425b30fdde14e9909939fb14d0d5b89 Binary files /dev/null and b/docs/img/a223e320ef570ec303a4e7346a899af7.png differ diff --git a/docs/img/a272933779dc7642aed4eb4acde12df9.png b/docs/img/a272933779dc7642aed4eb4acde12df9.png new file mode 100644 index 0000000000000000000000000000000000000000..706472f77ae85b7c4a5233bcea51f7031e4bacdf Binary files /dev/null and b/docs/img/a272933779dc7642aed4eb4acde12df9.png differ diff --git a/docs/img/a283d966822ac6a760d1a650273fbb3b.png b/docs/img/a283d966822ac6a760d1a650273fbb3b.png new file mode 100644 index 0000000000000000000000000000000000000000..d73bec47477cbf5d0d791e26eabcee94893ee030 Binary files /dev/null and b/docs/img/a283d966822ac6a760d1a650273fbb3b.png differ diff --git a/docs/img/a33f8dce89b50020e90de33ed9a1e78e.png b/docs/img/a33f8dce89b50020e90de33ed9a1e78e.png new file mode 100644 index 0000000000000000000000000000000000000000..cadfa7e6bb6bdf38cc5fcf85ed849b02d4294817 Binary files /dev/null and b/docs/img/a33f8dce89b50020e90de33ed9a1e78e.png differ diff --git a/docs/img/a3626522e1409168b7c977ecebbaee6e.png b/docs/img/a3626522e1409168b7c977ecebbaee6e.png new file mode 100644 index 0000000000000000000000000000000000000000..aead2fe2a47ac9fd9d0f128774384805926e0297 Binary files /dev/null and b/docs/img/a3626522e1409168b7c977ecebbaee6e.png differ diff --git a/docs/img/a3802569c81d8f8dd179fd218322a4ca.png b/docs/img/a3802569c81d8f8dd179fd218322a4ca.png new file mode 100644 index 0000000000000000000000000000000000000000..cf7268c3bb4f054b5e12efd877ab3d8d7caa34ce Binary files /dev/null and b/docs/img/a3802569c81d8f8dd179fd218322a4ca.png differ diff --git a/docs/img/a3964b6d91003c90a72b5ca689b9e0c5.png b/docs/img/a3964b6d91003c90a72b5ca689b9e0c5.png new file mode 100644 index 0000000000000000000000000000000000000000..add03bde76b04b552cc9763ee30cb0df654fe30b Binary files /dev/null and b/docs/img/a3964b6d91003c90a72b5ca689b9e0c5.png differ diff --git a/docs/img/a3acce71246e984986cedc7a1cece8f9.png b/docs/img/a3acce71246e984986cedc7a1cece8f9.png new file mode 100644 index 0000000000000000000000000000000000000000..5a81bf46aa36bddead1a442feea6aa7c4b8c6421 Binary files /dev/null and b/docs/img/a3acce71246e984986cedc7a1cece8f9.png differ diff --git a/docs/img/a3b1935e9fe6f6222ef3200715c2f595.png b/docs/img/a3b1935e9fe6f6222ef3200715c2f595.png new file mode 100644 index 0000000000000000000000000000000000000000..b54e7392d4a1dd891c8d3ff939fabd0c6f884fdd Binary files /dev/null and b/docs/img/a3b1935e9fe6f6222ef3200715c2f595.png differ diff --git a/docs/img/a48fc7b7ef95b54bd7ec66c17cad7dbb.png b/docs/img/a48fc7b7ef95b54bd7ec66c17cad7dbb.png new file mode 100644 index 0000000000000000000000000000000000000000..4cac0ff109c1a31804e34dfab1ecda401c683126 Binary files /dev/null and b/docs/img/a48fc7b7ef95b54bd7ec66c17cad7dbb.png differ diff --git a/docs/img/a4e7c4f55411323814dd3b9cb30ab9f8.png b/docs/img/a4e7c4f55411323814dd3b9cb30ab9f8.png new file mode 100644 index 0000000000000000000000000000000000000000..8929b8646dc33d5dd7eb56fc71b98c818d001c8f Binary files /dev/null and b/docs/img/a4e7c4f55411323814dd3b9cb30ab9f8.png differ diff --git a/docs/img/a5023ba03c96276e989dc4dbff1ca8dd.png b/docs/img/a5023ba03c96276e989dc4dbff1ca8dd.png new file mode 100644 index 0000000000000000000000000000000000000000..bafa95e6d870332a2b86c3e72782e798e03cc312 Binary files /dev/null and b/docs/img/a5023ba03c96276e989dc4dbff1ca8dd.png differ diff --git a/docs/img/a51fbcc597a6bc32e35c13c31799e36c.png b/docs/img/a51fbcc597a6bc32e35c13c31799e36c.png new file mode 100644 index 0000000000000000000000000000000000000000..153c048fd06d301b753d40d1ac5b682d1fd0dc1d Binary files /dev/null and b/docs/img/a51fbcc597a6bc32e35c13c31799e36c.png differ diff --git a/docs/img/a68a3a59d914e3b3ef4b3cd56a67c1e1.png b/docs/img/a68a3a59d914e3b3ef4b3cd56a67c1e1.png new file mode 100644 index 0000000000000000000000000000000000000000..6c5db33e288ecb85b4e510d2ae0606b9e75347d5 Binary files /dev/null and b/docs/img/a68a3a59d914e3b3ef4b3cd56a67c1e1.png differ diff --git a/docs/img/a6d06d0c4a54ff34856e0fbc07a50a60.png b/docs/img/a6d06d0c4a54ff34856e0fbc07a50a60.png new file mode 100644 index 0000000000000000000000000000000000000000..27d3f048c5edff6612537aab3134c5c4f3210447 Binary files /dev/null and b/docs/img/a6d06d0c4a54ff34856e0fbc07a50a60.png differ diff --git a/docs/img/a6d5e94df0d5d50038a0909603d69933.png b/docs/img/a6d5e94df0d5d50038a0909603d69933.png new file mode 100644 index 0000000000000000000000000000000000000000..8ab3f6dfe7d19a238a1be80c99d9fc73711c365d Binary files /dev/null and b/docs/img/a6d5e94df0d5d50038a0909603d69933.png differ diff --git a/docs/img/a6e9b62f94c53cd2f37f7300362137a9.png b/docs/img/a6e9b62f94c53cd2f37f7300362137a9.png new file mode 100644 index 0000000000000000000000000000000000000000..f56472eec79547058fc1f23efeb79bc880b8f21d Binary files /dev/null and b/docs/img/a6e9b62f94c53cd2f37f7300362137a9.png differ diff --git a/docs/img/a792de1a5441a31253d7a939dfd2de54.png b/docs/img/a792de1a5441a31253d7a939dfd2de54.png new file mode 100644 index 0000000000000000000000000000000000000000..0f03bf3b29aea6fa73d656e784562d259d99523d Binary files /dev/null and b/docs/img/a792de1a5441a31253d7a939dfd2de54.png differ diff --git a/docs/img/a7a0c433c6f01281a584ba08db57d159.png b/docs/img/a7a0c433c6f01281a584ba08db57d159.png new file mode 100644 index 0000000000000000000000000000000000000000..49af76d8360c35fee63e3b43595830ab3c2a5956 Binary files /dev/null and b/docs/img/a7a0c433c6f01281a584ba08db57d159.png differ diff --git a/docs/img/a87cd8265a25e22c9a715c6372ff047a.png b/docs/img/a87cd8265a25e22c9a715c6372ff047a.png new file mode 100644 index 0000000000000000000000000000000000000000..839e8222965d0056b017424eb1f825537d0f255b Binary files /dev/null and b/docs/img/a87cd8265a25e22c9a715c6372ff047a.png differ diff --git a/docs/img/a88692f85b1b05ca94199204a3cc1f00.png b/docs/img/a88692f85b1b05ca94199204a3cc1f00.png new file mode 100644 index 0000000000000000000000000000000000000000..559b39dae063895069501d66efa0a6579ed4d2ad Binary files /dev/null and b/docs/img/a88692f85b1b05ca94199204a3cc1f00.png differ diff --git a/docs/img/a8ac57717b491533848b3ebca40aae86.png b/docs/img/a8ac57717b491533848b3ebca40aae86.png new file mode 100644 index 0000000000000000000000000000000000000000..c1c3908f093e9dc9b3639724abde30970939b9fe Binary files /dev/null and b/docs/img/a8ac57717b491533848b3ebca40aae86.png differ diff --git a/docs/img/a9325984eddfbb907563c5bf5003f704.png b/docs/img/a9325984eddfbb907563c5bf5003f704.png new file mode 100644 index 0000000000000000000000000000000000000000..20118b018f4792fd03c4658a5474e34c59e688e5 Binary files /dev/null and b/docs/img/a9325984eddfbb907563c5bf5003f704.png differ diff --git a/docs/img/a93d26d68bbc1f4954a7038e601ba3b6.png b/docs/img/a93d26d68bbc1f4954a7038e601ba3b6.png new file mode 100644 index 0000000000000000000000000000000000000000..1b5a619c08ce1a96a736428e0eb6659e5615f73b Binary files /dev/null and b/docs/img/a93d26d68bbc1f4954a7038e601ba3b6.png differ diff --git a/docs/img/a94b1f6b20cc665168a8d8359d195f78.png b/docs/img/a94b1f6b20cc665168a8d8359d195f78.png new file mode 100644 index 0000000000000000000000000000000000000000..ab33e2a01f50e017e200581857b516f1c6b18077 Binary files /dev/null and b/docs/img/a94b1f6b20cc665168a8d8359d195f78.png differ diff --git a/docs/img/a9880855e171e225a4b6c73ae1790538.png b/docs/img/a9880855e171e225a4b6c73ae1790538.png new file mode 100644 index 0000000000000000000000000000000000000000..42d708786e75e1658b88c83e9050cbef796ce2e3 Binary files /dev/null and b/docs/img/a9880855e171e225a4b6c73ae1790538.png differ diff --git a/docs/img/a9b252d8a3c25b1c5166799c2233c569.png b/docs/img/a9b252d8a3c25b1c5166799c2233c569.png new file mode 100644 index 0000000000000000000000000000000000000000..27c3fb776aca5fe460ed1a3e37717e79909fd742 Binary files /dev/null and b/docs/img/a9b252d8a3c25b1c5166799c2233c569.png differ diff --git a/docs/img/aa2dd1694d7e1573bbd49200ed1ccb04.png b/docs/img/aa2dd1694d7e1573bbd49200ed1ccb04.png new file mode 100644 index 0000000000000000000000000000000000000000..218b8281245915eb85f73b72529c02550d647bef Binary files /dev/null and b/docs/img/aa2dd1694d7e1573bbd49200ed1ccb04.png differ diff --git a/docs/img/aabf40f234d995e031a5a1a0f66b5905.png b/docs/img/aabf40f234d995e031a5a1a0f66b5905.png new file mode 100644 index 0000000000000000000000000000000000000000..2fd16f55526288e45a5e64645766da642f36214c Binary files /dev/null and b/docs/img/aabf40f234d995e031a5a1a0f66b5905.png differ diff --git a/docs/img/aafa273009fd04415444f040f8b4c6cc.png b/docs/img/aafa273009fd04415444f040f8b4c6cc.png new file mode 100644 index 0000000000000000000000000000000000000000..ae744c8c43926be42dff1491c2625f8eb658625d Binary files /dev/null and b/docs/img/aafa273009fd04415444f040f8b4c6cc.png differ diff --git a/docs/img/ab48b86f7a0dfe92d4358f705bf938a8.png b/docs/img/ab48b86f7a0dfe92d4358f705bf938a8.png new file mode 100644 index 0000000000000000000000000000000000000000..6ce494e995e32ef5567d85229f66714f62535f9a Binary files /dev/null and b/docs/img/ab48b86f7a0dfe92d4358f705bf938a8.png differ diff --git a/docs/img/abdf7941c6dc575d115b24d74a80a68b.png b/docs/img/abdf7941c6dc575d115b24d74a80a68b.png new file mode 100644 index 0000000000000000000000000000000000000000..48cb84b22a9346656e56f5da3def9a562df29c16 Binary files /dev/null and b/docs/img/abdf7941c6dc575d115b24d74a80a68b.png differ diff --git a/docs/img/ac3623994213ad815a95e7826a3cfc3e.png b/docs/img/ac3623994213ad815a95e7826a3cfc3e.png new file mode 100644 index 0000000000000000000000000000000000000000..ee00cc9bd62c174e9b5a4ce6ef75f1597369c532 Binary files /dev/null and b/docs/img/ac3623994213ad815a95e7826a3cfc3e.png differ diff --git a/docs/img/ad2cdacdd36348cddf7d5c19d8940d5b.png b/docs/img/ad2cdacdd36348cddf7d5c19d8940d5b.png new file mode 100644 index 0000000000000000000000000000000000000000..ccf6173f96cd807cbca78dc21d59015149db0226 Binary files /dev/null and b/docs/img/ad2cdacdd36348cddf7d5c19d8940d5b.png differ diff --git a/docs/img/ad33446e7ba7897d31835424ce5e1feb.png b/docs/img/ad33446e7ba7897d31835424ce5e1feb.png new file mode 100644 index 0000000000000000000000000000000000000000..8ba6922f114936b8948fdd03ed9169f748eded99 Binary files /dev/null and b/docs/img/ad33446e7ba7897d31835424ce5e1feb.png differ diff --git a/docs/img/ad8ac82c77beb415e901040df8d93b17.png b/docs/img/ad8ac82c77beb415e901040df8d93b17.png new file mode 100644 index 0000000000000000000000000000000000000000..8de97ab4d0dcce89063c576be8448e2fa0ddfa1b Binary files /dev/null and b/docs/img/ad8ac82c77beb415e901040df8d93b17.png differ diff --git a/docs/img/adc0d64a6c4c1979d43d8bf1d8d485e8.png b/docs/img/adc0d64a6c4c1979d43d8bf1d8d485e8.png new file mode 100644 index 0000000000000000000000000000000000000000..a62fd57f2b02ab604bcf3885794cb598a0975870 Binary files /dev/null and b/docs/img/adc0d64a6c4c1979d43d8bf1d8d485e8.png differ diff --git a/docs/img/adf6de6d0c4125be4e7a25119c0193e1.png b/docs/img/adf6de6d0c4125be4e7a25119c0193e1.png new file mode 100644 index 0000000000000000000000000000000000000000..81227650adac335954dfcc2a47c3b00885061f12 Binary files /dev/null and b/docs/img/adf6de6d0c4125be4e7a25119c0193e1.png differ diff --git a/docs/img/ae307552914d8ff018365bbde4d23479.png b/docs/img/ae307552914d8ff018365bbde4d23479.png new file mode 100644 index 0000000000000000000000000000000000000000..0bdf664946b86acac6c9e0c3482ae00c07bbb43d Binary files /dev/null and b/docs/img/ae307552914d8ff018365bbde4d23479.png differ diff --git a/docs/img/ae54430a80c08d51c51659ac1a4dd8b9.png b/docs/img/ae54430a80c08d51c51659ac1a4dd8b9.png new file mode 100644 index 0000000000000000000000000000000000000000..ba72fe3f41ea641985f5c1e7a81bda728517f4ae Binary files /dev/null and b/docs/img/ae54430a80c08d51c51659ac1a4dd8b9.png differ diff --git a/docs/img/ae5a500e2333874603b33328b017eb35.png b/docs/img/ae5a500e2333874603b33328b017eb35.png new file mode 100644 index 0000000000000000000000000000000000000000..c63975ff5de98c7fc068928043358c1cb172c984 Binary files /dev/null and b/docs/img/ae5a500e2333874603b33328b017eb35.png differ diff --git a/docs/img/ae9e67c8841e45007cf186891963198f.png b/docs/img/ae9e67c8841e45007cf186891963198f.png new file mode 100644 index 0000000000000000000000000000000000000000..c8e2e9fb3800b7c01fccc35205797f2b9f71e7ef Binary files /dev/null and b/docs/img/ae9e67c8841e45007cf186891963198f.png differ diff --git a/docs/img/aec2abca2644938484258f63a3df71d2.png b/docs/img/aec2abca2644938484258f63a3df71d2.png new file mode 100644 index 0000000000000000000000000000000000000000..d99590be8c25f872c5ea4476bac5110964fb2337 Binary files /dev/null and b/docs/img/aec2abca2644938484258f63a3df71d2.png differ diff --git a/docs/img/aeccb5cc55fc430d8645e67086388300.png b/docs/img/aeccb5cc55fc430d8645e67086388300.png new file mode 100644 index 0000000000000000000000000000000000000000..c7d457e58c0be01a3ce30a95db6f2a6900dd0115 Binary files /dev/null and b/docs/img/aeccb5cc55fc430d8645e67086388300.png differ diff --git a/docs/img/afdb4890858bdb916f8a393b22b8ef96.png b/docs/img/afdb4890858bdb916f8a393b22b8ef96.png new file mode 100644 index 0000000000000000000000000000000000000000..57995b05db7764d197488dfc2005a24d77d45156 Binary files /dev/null and b/docs/img/afdb4890858bdb916f8a393b22b8ef96.png differ diff --git a/docs/img/afe1906c0ba8e9c44277342a20a48db6.png b/docs/img/afe1906c0ba8e9c44277342a20a48db6.png new file mode 100644 index 0000000000000000000000000000000000000000..a19fad9620c93b9bbec2e479dfa920c8a71b3280 Binary files /dev/null and b/docs/img/afe1906c0ba8e9c44277342a20a48db6.png differ diff --git a/docs/img/afec6ffec0973dba40a3e3bc2c244bad.png b/docs/img/afec6ffec0973dba40a3e3bc2c244bad.png new file mode 100644 index 0000000000000000000000000000000000000000..d3773361ffde392ecc8a538723eef55d28954f23 Binary files /dev/null and b/docs/img/afec6ffec0973dba40a3e3bc2c244bad.png differ diff --git a/docs/img/b061980557a1e04fe2a2f3836b8dd9c1.png b/docs/img/b061980557a1e04fe2a2f3836b8dd9c1.png new file mode 100644 index 0000000000000000000000000000000000000000..3b14141416953d983010bb4cc566c2f489f80ff6 Binary files /dev/null and b/docs/img/b061980557a1e04fe2a2f3836b8dd9c1.png differ diff --git a/docs/img/b12f4326b7cccf6e82c375163842f58e.png b/docs/img/b12f4326b7cccf6e82c375163842f58e.png new file mode 100644 index 0000000000000000000000000000000000000000..2bec00864fe3a8619b1f45ffac1dc89888579b23 Binary files /dev/null and b/docs/img/b12f4326b7cccf6e82c375163842f58e.png differ diff --git a/docs/img/b132b9b00d4641da41d2cb7dca5ea55c.png b/docs/img/b132b9b00d4641da41d2cb7dca5ea55c.png new file mode 100644 index 0000000000000000000000000000000000000000..eb0a0ff49b0ef41332144934896544eca741f962 Binary files /dev/null and b/docs/img/b132b9b00d4641da41d2cb7dca5ea55c.png differ diff --git a/docs/img/b15b2918f982a43ce2379b4f2ec765a9.png b/docs/img/b15b2918f982a43ce2379b4f2ec765a9.png new file mode 100644 index 0000000000000000000000000000000000000000..2b7be1136039bec35bc804b50460ed833fb13bed Binary files /dev/null and b/docs/img/b15b2918f982a43ce2379b4f2ec765a9.png differ diff --git a/docs/img/b1b6eda7a121cb284375e6c83317263d.png b/docs/img/b1b6eda7a121cb284375e6c83317263d.png new file mode 100644 index 0000000000000000000000000000000000000000..12b6f2ac2fc41bb659138ba40651fca4a5ed681d Binary files /dev/null and b/docs/img/b1b6eda7a121cb284375e6c83317263d.png differ diff --git a/docs/img/b1edf28a1aa5c59ffa779a574c4fc548.png b/docs/img/b1edf28a1aa5c59ffa779a574c4fc548.png new file mode 100644 index 0000000000000000000000000000000000000000..5db30e2c20eba2a1e58370521e1f323b289ae504 Binary files /dev/null and b/docs/img/b1edf28a1aa5c59ffa779a574c4fc548.png differ diff --git a/docs/img/b203ae7a973815c03ea680032d1e75eb.png b/docs/img/b203ae7a973815c03ea680032d1e75eb.png new file mode 100644 index 0000000000000000000000000000000000000000..6e5f6ffe9d2489a4a09e422e298f78fc8d7433ad Binary files /dev/null and b/docs/img/b203ae7a973815c03ea680032d1e75eb.png differ diff --git a/docs/img/b22d9654d7ad1868d2368d7e3f82e9a3.png b/docs/img/b22d9654d7ad1868d2368d7e3f82e9a3.png new file mode 100644 index 0000000000000000000000000000000000000000..765ec4a2616c83809f9d0ff034aa3a07e60211b9 Binary files /dev/null and b/docs/img/b22d9654d7ad1868d2368d7e3f82e9a3.png differ diff --git a/docs/img/b2499f834ff0e8252829dd96bad93d97.png b/docs/img/b2499f834ff0e8252829dd96bad93d97.png new file mode 100644 index 0000000000000000000000000000000000000000..bee411f26e8aba678638c5bfc4fda1e2bcbef840 Binary files /dev/null and b/docs/img/b2499f834ff0e8252829dd96bad93d97.png differ diff --git a/docs/img/b24c623173b50fdf9cd2676f1f311580.png b/docs/img/b24c623173b50fdf9cd2676f1f311580.png new file mode 100644 index 0000000000000000000000000000000000000000..352e6ddaad0646f748a2148d22641a1be6a4607d Binary files /dev/null and b/docs/img/b24c623173b50fdf9cd2676f1f311580.png differ diff --git a/docs/img/b36e59e0da065f17e34891efef2ee0a1.png b/docs/img/b36e59e0da065f17e34891efef2ee0a1.png new file mode 100644 index 0000000000000000000000000000000000000000..f117a230e175adcc0dc9f4b3df03d53877979b98 Binary files /dev/null and b/docs/img/b36e59e0da065f17e34891efef2ee0a1.png differ diff --git a/docs/img/b379b1821f4b3d10ab0be61a59bcd491.png b/docs/img/b379b1821f4b3d10ab0be61a59bcd491.png new file mode 100644 index 0000000000000000000000000000000000000000..7780e3331837ee25ce8be65be61c290ab5ec4fd7 Binary files /dev/null and b/docs/img/b379b1821f4b3d10ab0be61a59bcd491.png differ diff --git a/docs/img/b44c56313892b2d78da86b3f64519a98.png b/docs/img/b44c56313892b2d78da86b3f64519a98.png new file mode 100644 index 0000000000000000000000000000000000000000..56551e85e5723ce3b3c8304928ac48aa272747c9 Binary files /dev/null and b/docs/img/b44c56313892b2d78da86b3f64519a98.png differ diff --git a/docs/img/b452a194fd7fbbdd22f73a1dda9b236a.png b/docs/img/b452a194fd7fbbdd22f73a1dda9b236a.png new file mode 100644 index 0000000000000000000000000000000000000000..ff22790dfd9b6698add0b33b2c058fc020ec5204 Binary files /dev/null and b/docs/img/b452a194fd7fbbdd22f73a1dda9b236a.png differ diff --git a/docs/img/b46359f55df1f2affc4fe493965ebd0a.png b/docs/img/b46359f55df1f2affc4fe493965ebd0a.png new file mode 100644 index 0000000000000000000000000000000000000000..8a48deca8b626134e3c2e72d4d55c08b8586bdb9 Binary files /dev/null and b/docs/img/b46359f55df1f2affc4fe493965ebd0a.png differ diff --git a/docs/img/b4a1ffd094e753d655825c1385561991.png b/docs/img/b4a1ffd094e753d655825c1385561991.png new file mode 100644 index 0000000000000000000000000000000000000000..97c2da4bd72008263abdd0c62f59a6108b4b1d13 Binary files /dev/null and b/docs/img/b4a1ffd094e753d655825c1385561991.png differ diff --git a/docs/img/b4e4d114d9b2244a7848961617e05a95.png b/docs/img/b4e4d114d9b2244a7848961617e05a95.png new file mode 100644 index 0000000000000000000000000000000000000000..79c081880e15e905b18b2ebcda140671c92c6d2b Binary files /dev/null and b/docs/img/b4e4d114d9b2244a7848961617e05a95.png differ diff --git a/docs/img/b4e821b8b83e29e837f01f4620e557b7.png b/docs/img/b4e821b8b83e29e837f01f4620e557b7.png new file mode 100644 index 0000000000000000000000000000000000000000..dc724aa6e8ecbf235608905f92197255ef127fa0 Binary files /dev/null and b/docs/img/b4e821b8b83e29e837f01f4620e557b7.png differ diff --git a/docs/img/b51efc1bf28d2363ac0b4e95c4318fbe.png b/docs/img/b51efc1bf28d2363ac0b4e95c4318fbe.png new file mode 100644 index 0000000000000000000000000000000000000000..04697a910ebd1ccf1038bc587b3e63a506d86bd2 Binary files /dev/null and b/docs/img/b51efc1bf28d2363ac0b4e95c4318fbe.png differ diff --git a/docs/img/b6069220bf06467d1d434d3652c5d82a.png b/docs/img/b6069220bf06467d1d434d3652c5d82a.png new file mode 100644 index 0000000000000000000000000000000000000000..638bf431f8f46a8635e7952de82adeffec2e8a2a Binary files /dev/null and b/docs/img/b6069220bf06467d1d434d3652c5d82a.png differ diff --git a/docs/img/b62968cd49816ab794ddd37a7dcfb7a2.png b/docs/img/b62968cd49816ab794ddd37a7dcfb7a2.png new file mode 100644 index 0000000000000000000000000000000000000000..da7ab5eb5a02f846e4272b7345cfb47ae952c873 Binary files /dev/null and b/docs/img/b62968cd49816ab794ddd37a7dcfb7a2.png differ diff --git a/docs/img/b64907bafa7c740c069ec7395a5c5471.png b/docs/img/b64907bafa7c740c069ec7395a5c5471.png new file mode 100644 index 0000000000000000000000000000000000000000..a3f6631dab9c8138337c29475d5d0cedbb5357ae Binary files /dev/null and b/docs/img/b64907bafa7c740c069ec7395a5c5471.png differ diff --git a/docs/img/b6662e0dd306cb7949bbfd70db9b384c.png b/docs/img/b6662e0dd306cb7949bbfd70db9b384c.png new file mode 100644 index 0000000000000000000000000000000000000000..6b306ecea8bb478c70f2254a7a7218105bf7b6f6 Binary files /dev/null and b/docs/img/b6662e0dd306cb7949bbfd70db9b384c.png differ diff --git a/docs/img/b6696ad0d59c74a9a3974493085915f9.png b/docs/img/b6696ad0d59c74a9a3974493085915f9.png new file mode 100644 index 0000000000000000000000000000000000000000..68e6c595f7a4b968634f76486218e08519d0e7a8 Binary files /dev/null and b/docs/img/b6696ad0d59c74a9a3974493085915f9.png differ diff --git a/docs/img/b66dc4137ac73e81c66e408cf9fcf391.png b/docs/img/b66dc4137ac73e81c66e408cf9fcf391.png new file mode 100644 index 0000000000000000000000000000000000000000..ad84c63c80e96567f87f0476041e5fd97e2fc0b6 Binary files /dev/null and b/docs/img/b66dc4137ac73e81c66e408cf9fcf391.png differ diff --git a/docs/img/b6a9c5aa2e348263baf61cb961ac802f.png b/docs/img/b6a9c5aa2e348263baf61cb961ac802f.png new file mode 100644 index 0000000000000000000000000000000000000000..06d66c59ce12017613e2289da62547b6ec646096 Binary files /dev/null and b/docs/img/b6a9c5aa2e348263baf61cb961ac802f.png differ diff --git a/docs/img/b6c59d6785a7941658315a7e8e148751.png b/docs/img/b6c59d6785a7941658315a7e8e148751.png new file mode 100644 index 0000000000000000000000000000000000000000..71c083d6f3540e311c898a801f8ab14740757627 Binary files /dev/null and b/docs/img/b6c59d6785a7941658315a7e8e148751.png differ diff --git a/docs/img/b6d33f6e98bcf842659df9a637bbaeb9.png b/docs/img/b6d33f6e98bcf842659df9a637bbaeb9.png new file mode 100644 index 0000000000000000000000000000000000000000..d6146377fa6715d7ef1521d75766912cce7ad839 Binary files /dev/null and b/docs/img/b6d33f6e98bcf842659df9a637bbaeb9.png differ diff --git a/docs/img/b6f3d1302a444a29689905582d97eb84.png b/docs/img/b6f3d1302a444a29689905582d97eb84.png new file mode 100644 index 0000000000000000000000000000000000000000..2b406ae27c830fbe0439db2073fa1c8f537dc6f8 Binary files /dev/null and b/docs/img/b6f3d1302a444a29689905582d97eb84.png differ diff --git a/docs/img/b7658a174f8b110251a289f5276dc822.png b/docs/img/b7658a174f8b110251a289f5276dc822.png new file mode 100644 index 0000000000000000000000000000000000000000..2d0432673698fdb20b2c967df8550e96f0d01e24 Binary files /dev/null and b/docs/img/b7658a174f8b110251a289f5276dc822.png differ diff --git a/docs/img/b786322ea49fe7840203db128b72a5e0.png b/docs/img/b786322ea49fe7840203db128b72a5e0.png new file mode 100644 index 0000000000000000000000000000000000000000..b5ae858a0c5b72ed3ca8b3b722cc7587a5f8fa2e Binary files /dev/null and b/docs/img/b786322ea49fe7840203db128b72a5e0.png differ diff --git a/docs/img/b820c73810583190a0b1697c813fdda8.png b/docs/img/b820c73810583190a0b1697c813fdda8.png new file mode 100644 index 0000000000000000000000000000000000000000..78ad0a1ea62cc56b72736f9c143bd696faa0dac2 Binary files /dev/null and b/docs/img/b820c73810583190a0b1697c813fdda8.png differ diff --git a/docs/img/b962444c71ad27ba05dfc6bfc69269f4.png b/docs/img/b962444c71ad27ba05dfc6bfc69269f4.png new file mode 100644 index 0000000000000000000000000000000000000000..71c3d8d44d05ae13d88c4213dc7b6a1030452761 Binary files /dev/null and b/docs/img/b962444c71ad27ba05dfc6bfc69269f4.png differ diff --git a/docs/img/b96e754d4dd8ba06065aac231327e160.png b/docs/img/b96e754d4dd8ba06065aac231327e160.png new file mode 100644 index 0000000000000000000000000000000000000000..3861d687ef7a1147353ec0003bfabfd106bea6d8 Binary files /dev/null and b/docs/img/b96e754d4dd8ba06065aac231327e160.png differ diff --git a/docs/img/b98f1bb6205ce5c692946b81e8c78003.png b/docs/img/b98f1bb6205ce5c692946b81e8c78003.png new file mode 100644 index 0000000000000000000000000000000000000000..949143c71358790f643d49429ab174de9587de5b Binary files /dev/null and b/docs/img/b98f1bb6205ce5c692946b81e8c78003.png differ diff --git a/docs/img/ba294e1cb39daadf43b81f113e5ef506.png b/docs/img/ba294e1cb39daadf43b81f113e5ef506.png new file mode 100644 index 0000000000000000000000000000000000000000..d4351aeaec93607a65b4ff10278f979df06db625 Binary files /dev/null and b/docs/img/ba294e1cb39daadf43b81f113e5ef506.png differ diff --git a/docs/img/ba685b05a8bb7c09fe3b58048ac4884e.png b/docs/img/ba685b05a8bb7c09fe3b58048ac4884e.png new file mode 100644 index 0000000000000000000000000000000000000000..b756d55ed873b184dd6c8d07f510b155d9cd92c0 Binary files /dev/null and b/docs/img/ba685b05a8bb7c09fe3b58048ac4884e.png differ diff --git a/docs/img/baa29e50412ef4acd25e287681ad9e9e.png b/docs/img/baa29e50412ef4acd25e287681ad9e9e.png new file mode 100644 index 0000000000000000000000000000000000000000..e6e6f139e50c84ab3537b12ec95bf6eff8f59801 Binary files /dev/null and b/docs/img/baa29e50412ef4acd25e287681ad9e9e.png differ diff --git a/docs/img/bab81ba0a915cec8b039166d2defc074.png b/docs/img/bab81ba0a915cec8b039166d2defc074.png new file mode 100644 index 0000000000000000000000000000000000000000..d1bf838bfaddb841804bd45fb6225b6046f57290 Binary files /dev/null and b/docs/img/bab81ba0a915cec8b039166d2defc074.png differ diff --git a/docs/img/bab86c57be5bd24c1329a7de56df456a.png b/docs/img/bab86c57be5bd24c1329a7de56df456a.png new file mode 100644 index 0000000000000000000000000000000000000000..c32f7cbd24c265d2b2b3cc959371327626915af5 Binary files /dev/null and b/docs/img/bab86c57be5bd24c1329a7de56df456a.png differ diff --git a/docs/img/bad584bc95c83e26be6c67a2b54b26ae.png b/docs/img/bad584bc95c83e26be6c67a2b54b26ae.png new file mode 100644 index 0000000000000000000000000000000000000000..8547e102032b27d7c600fe30c99736db9ba7f258 Binary files /dev/null and b/docs/img/bad584bc95c83e26be6c67a2b54b26ae.png differ diff --git a/docs/img/bad7cd1d32a4bbf53fc1d27dcb3dd211.png b/docs/img/bad7cd1d32a4bbf53fc1d27dcb3dd211.png new file mode 100644 index 0000000000000000000000000000000000000000..0a6d821bc02b81d60ed9dabc96cb53653d3ee81c --- /dev/null +++ b/docs/img/bad7cd1d32a4bbf53fc1d27dcb3dd211.png @@ -0,0 +1,265 @@ + + + +Page Not Found | GitLab Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + +
      +
      +
      +
      +
      +404 +
      +
      +
      +
      +
      + + + + + + + +
      +
      +
      + +
      +
      +
      +
      + +
      +
      + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/img/bb46a964436bb5fa1becb0900b9b0fc3.png b/docs/img/bb46a964436bb5fa1becb0900b9b0fc3.png new file mode 100644 index 0000000000000000000000000000000000000000..c7c4fa75cf5879731178e811d84d407866f4b3b6 Binary files /dev/null and b/docs/img/bb46a964436bb5fa1becb0900b9b0fc3.png differ diff --git a/docs/img/bb7ff3b17ad66e05a64ee12def63524b.png b/docs/img/bb7ff3b17ad66e05a64ee12def63524b.png new file mode 100644 index 0000000000000000000000000000000000000000..144019279484cfda29567a8e3dc12f0f25d0df57 Binary files /dev/null and b/docs/img/bb7ff3b17ad66e05a64ee12def63524b.png differ diff --git a/docs/img/bba7007707d548d73c9b6f0efad3c50b.png b/docs/img/bba7007707d548d73c9b6f0efad3c50b.png new file mode 100644 index 0000000000000000000000000000000000000000..a2350c299094af4a2b2ed8a615371206c788ebc1 Binary files /dev/null and b/docs/img/bba7007707d548d73c9b6f0efad3c50b.png differ diff --git a/docs/img/bc03121106ba9696b67a617d6aeb3878.png b/docs/img/bc03121106ba9696b67a617d6aeb3878.png new file mode 100644 index 0000000000000000000000000000000000000000..93855662ceb2f3243cba6716bfb099ed897e4440 Binary files /dev/null and b/docs/img/bc03121106ba9696b67a617d6aeb3878.png differ diff --git a/docs/img/bcbedbd56c50879eb35c2fc2f534d693.png b/docs/img/bcbedbd56c50879eb35c2fc2f534d693.png new file mode 100644 index 0000000000000000000000000000000000000000..f0786ad45f344649df274f6653c5cea86ab49a0e Binary files /dev/null and b/docs/img/bcbedbd56c50879eb35c2fc2f534d693.png differ diff --git a/docs/img/bccfe6e36a18f67a038a8d90f2a6499f.png b/docs/img/bccfe6e36a18f67a038a8d90f2a6499f.png new file mode 100644 index 0000000000000000000000000000000000000000..3952c9ca5360d3a5d913ddd55b33450a1edd7d45 Binary files /dev/null and b/docs/img/bccfe6e36a18f67a038a8d90f2a6499f.png differ diff --git a/docs/img/bd8c2bfd77b1834503e87e4dc5b58420.png b/docs/img/bd8c2bfd77b1834503e87e4dc5b58420.png new file mode 100644 index 0000000000000000000000000000000000000000..28e9b47ef10a70699090cc282e0153bcbeb12ea8 Binary files /dev/null and b/docs/img/bd8c2bfd77b1834503e87e4dc5b58420.png differ diff --git a/docs/img/bde796b0c195045db9849eef2842bd0e.png b/docs/img/bde796b0c195045db9849eef2842bd0e.png new file mode 100644 index 0000000000000000000000000000000000000000..a8f2687dc03ee89ed21953b28475780562623a28 Binary files /dev/null and b/docs/img/bde796b0c195045db9849eef2842bd0e.png differ diff --git a/docs/img/be1eaf723e0603b081c01aa4310c304c.png b/docs/img/be1eaf723e0603b081c01aa4310c304c.png new file mode 100644 index 0000000000000000000000000000000000000000..9ec46ca556f97be9741defc28442a5b4085ccb2b Binary files /dev/null and b/docs/img/be1eaf723e0603b081c01aa4310c304c.png differ diff --git a/docs/img/be7e963d6561756bb87f6fea0cd245fa.png b/docs/img/be7e963d6561756bb87f6fea0cd245fa.png new file mode 100644 index 0000000000000000000000000000000000000000..5a102a9587a6bc1f8be4c279b2c95d13fe4e54c9 Binary files /dev/null and b/docs/img/be7e963d6561756bb87f6fea0cd245fa.png differ diff --git a/docs/img/bec396562e8fe025cb7009de091ff2aa.png b/docs/img/bec396562e8fe025cb7009de091ff2aa.png new file mode 100644 index 0000000000000000000000000000000000000000..7443c06c52bf4b774d9b008b8fc7e5946a5d68a6 Binary files /dev/null and b/docs/img/bec396562e8fe025cb7009de091ff2aa.png differ diff --git a/docs/img/bed33522d3ca08c8f5c920ba11fa05d4.png b/docs/img/bed33522d3ca08c8f5c920ba11fa05d4.png new file mode 100644 index 0000000000000000000000000000000000000000..670586a92df42b954c99e85b642a819f3a600193 Binary files /dev/null and b/docs/img/bed33522d3ca08c8f5c920ba11fa05d4.png differ diff --git a/docs/img/bf46825f18b4b1998d719dffeab0c45c.png b/docs/img/bf46825f18b4b1998d719dffeab0c45c.png new file mode 100644 index 0000000000000000000000000000000000000000..b113bb56cb986f6506c765e82645fae3f0fff5e8 Binary files /dev/null and b/docs/img/bf46825f18b4b1998d719dffeab0c45c.png differ diff --git a/docs/img/bf99e217a01388f7c11df39626ab9e22.png b/docs/img/bf99e217a01388f7c11df39626ab9e22.png new file mode 100644 index 0000000000000000000000000000000000000000..1fc478842f51e7519866f474a02ad605235bc6a6 Binary files /dev/null and b/docs/img/bf99e217a01388f7c11df39626ab9e22.png differ diff --git a/docs/img/c01efbb34a741e385a7089a6799e9b59.png b/docs/img/c01efbb34a741e385a7089a6799e9b59.png new file mode 100644 index 0000000000000000000000000000000000000000..6f40bf22159402d7515e1d32af40f22b0febae8b Binary files /dev/null and b/docs/img/c01efbb34a741e385a7089a6799e9b59.png differ diff --git a/docs/img/c07889c4060a55eccd0e5dde9cb54f74.png b/docs/img/c07889c4060a55eccd0e5dde9cb54f74.png new file mode 100644 index 0000000000000000000000000000000000000000..b055f8e7a8595e8830394ebbd4a11a128c9dedf1 Binary files /dev/null and b/docs/img/c07889c4060a55eccd0e5dde9cb54f74.png differ diff --git a/docs/img/c0fd76908cea66a75fbd88aeb1ccec31.png b/docs/img/c0fd76908cea66a75fbd88aeb1ccec31.png new file mode 100644 index 0000000000000000000000000000000000000000..144eac7b1ed984878167ba36a617204ba35a21c4 Binary files /dev/null and b/docs/img/c0fd76908cea66a75fbd88aeb1ccec31.png differ diff --git a/docs/img/c10c0f19a1d0076044db1057cfb19875.png b/docs/img/c10c0f19a1d0076044db1057cfb19875.png new file mode 100644 index 0000000000000000000000000000000000000000..f95fbc9027c108809d096a174b3ca2a921ae1e30 Binary files /dev/null and b/docs/img/c10c0f19a1d0076044db1057cfb19875.png differ diff --git a/docs/img/c154238c63e38411889c5647b2cdf20e.png b/docs/img/c154238c63e38411889c5647b2cdf20e.png new file mode 100644 index 0000000000000000000000000000000000000000..74c93a6238c574dc4a5b330b4bae07f3925e2cca Binary files /dev/null and b/docs/img/c154238c63e38411889c5647b2cdf20e.png differ diff --git a/docs/img/c17db26d06341055b4834c8be77c604b.png b/docs/img/c17db26d06341055b4834c8be77c604b.png new file mode 100644 index 0000000000000000000000000000000000000000..7005fb039ae313bd7198f9092b82348d675576d4 Binary files /dev/null and b/docs/img/c17db26d06341055b4834c8be77c604b.png differ diff --git a/docs/img/c187176d6b8d40e19db360c4c68ffb46.png b/docs/img/c187176d6b8d40e19db360c4c68ffb46.png new file mode 100644 index 0000000000000000000000000000000000000000..bda4bb03e089ddef0aad1e71eb4a04c51034a2f2 Binary files /dev/null and b/docs/img/c187176d6b8d40e19db360c4c68ffb46.png differ diff --git a/docs/img/c187de65e481b5598b110fee5310776c.png b/docs/img/c187de65e481b5598b110fee5310776c.png new file mode 100644 index 0000000000000000000000000000000000000000..5b38f138428421b90790b095d0487e0535acf222 Binary files /dev/null and b/docs/img/c187de65e481b5598b110fee5310776c.png differ diff --git a/docs/img/c1e086b58ff99dd5c5684a4571e568e3.png b/docs/img/c1e086b58ff99dd5c5684a4571e568e3.png new file mode 100644 index 0000000000000000000000000000000000000000..1ee416d3ce9993cd5973e8b47c79d3fe89470eed Binary files /dev/null and b/docs/img/c1e086b58ff99dd5c5684a4571e568e3.png differ diff --git a/docs/img/c1ff864dc0ff6749087bc64b4781d767.png b/docs/img/c1ff864dc0ff6749087bc64b4781d767.png new file mode 100644 index 0000000000000000000000000000000000000000..604b2e31f05d8c99cd3228a474bc87a9c52e2bc0 Binary files /dev/null and b/docs/img/c1ff864dc0ff6749087bc64b4781d767.png differ diff --git a/docs/img/c29b503c10922622f8ec612bd5168b10.png b/docs/img/c29b503c10922622f8ec612bd5168b10.png new file mode 100644 index 0000000000000000000000000000000000000000..e4be6e19addd9076d1d4910fe3e925c898cd85e5 Binary files /dev/null and b/docs/img/c29b503c10922622f8ec612bd5168b10.png differ diff --git a/docs/img/c2b9039967ef1a229c8db9d7542591fb.png b/docs/img/c2b9039967ef1a229c8db9d7542591fb.png new file mode 100644 index 0000000000000000000000000000000000000000..bf723ef20c5cb99e7af02f417733a1db2e2428a6 Binary files /dev/null and b/docs/img/c2b9039967ef1a229c8db9d7542591fb.png differ diff --git a/docs/img/c2f9cb2f2c88244b3dbf094572214a02.png b/docs/img/c2f9cb2f2c88244b3dbf094572214a02.png new file mode 100644 index 0000000000000000000000000000000000000000..6c73667aebb2282e9fb0b128dba843ae2e21a628 Binary files /dev/null and b/docs/img/c2f9cb2f2c88244b3dbf094572214a02.png differ diff --git a/docs/img/c3174e54aed82ba15686b58fc97068f1.png b/docs/img/c3174e54aed82ba15686b58fc97068f1.png new file mode 100644 index 0000000000000000000000000000000000000000..51fecf27daaa0ed6c6c677a5c1b54c61be3f58d1 Binary files /dev/null and b/docs/img/c3174e54aed82ba15686b58fc97068f1.png differ diff --git a/docs/img/c380b8ddd78f1d3281d0eeea7f19971c.png b/docs/img/c380b8ddd78f1d3281d0eeea7f19971c.png new file mode 100644 index 0000000000000000000000000000000000000000..40a432914f6e888aaf41dbba4ab1ef112188a1fc Binary files /dev/null and b/docs/img/c380b8ddd78f1d3281d0eeea7f19971c.png differ diff --git a/docs/img/c3948ae724d699cf1ec0da64ab3e6a14.png b/docs/img/c3948ae724d699cf1ec0da64ab3e6a14.png new file mode 100644 index 0000000000000000000000000000000000000000..804a4451b69fb83c81c8fd3664240d454cacf75a Binary files /dev/null and b/docs/img/c3948ae724d699cf1ec0da64ab3e6a14.png differ diff --git a/docs/img/c39dc466882289b42ad827dbbc05b39f.png b/docs/img/c39dc466882289b42ad827dbbc05b39f.png new file mode 100644 index 0000000000000000000000000000000000000000..ededdd5a6319fdab381fc439824301a4cc9be4b0 Binary files /dev/null and b/docs/img/c39dc466882289b42ad827dbbc05b39f.png differ diff --git a/docs/img/c3c27ff673c33bcd50004c2adb617d5f.png b/docs/img/c3c27ff673c33bcd50004c2adb617d5f.png new file mode 100644 index 0000000000000000000000000000000000000000..1345a00e3f4473a179e72695883500777da76687 Binary files /dev/null and b/docs/img/c3c27ff673c33bcd50004c2adb617d5f.png differ diff --git a/docs/img/c3c7ade0ae9c901a64dedf780f4efdaf.png b/docs/img/c3c7ade0ae9c901a64dedf780f4efdaf.png new file mode 100644 index 0000000000000000000000000000000000000000..6f15f32e6ac15e3e0da9fb25efa1e5c28296e123 Binary files /dev/null and b/docs/img/c3c7ade0ae9c901a64dedf780f4efdaf.png differ diff --git a/docs/img/c3f7298c5f6d1b4dbd0a120ce98b9d06.png b/docs/img/c3f7298c5f6d1b4dbd0a120ce98b9d06.png new file mode 100644 index 0000000000000000000000000000000000000000..85387b2d3cd4e74a67e5f92787b1c5bc834dee99 Binary files /dev/null and b/docs/img/c3f7298c5f6d1b4dbd0a120ce98b9d06.png differ diff --git a/docs/img/c42e6852cdd2c45b0a814f7a659ee5d2.png b/docs/img/c42e6852cdd2c45b0a814f7a659ee5d2.png new file mode 100644 index 0000000000000000000000000000000000000000..902267b2db7076a2ce4cf164690d98d811bf40ee Binary files /dev/null and b/docs/img/c42e6852cdd2c45b0a814f7a659ee5d2.png differ diff --git a/docs/img/c43432893b48081561609f3667b7d497.png b/docs/img/c43432893b48081561609f3667b7d497.png new file mode 100644 index 0000000000000000000000000000000000000000..485db733cec7ccc099dddfcc76cb6e4696ba90b3 Binary files /dev/null and b/docs/img/c43432893b48081561609f3667b7d497.png differ diff --git a/docs/img/c4c2d27f307636160d5773556cb14345.png b/docs/img/c4c2d27f307636160d5773556cb14345.png new file mode 100644 index 0000000000000000000000000000000000000000..67c6ced6f27ec8b435d2af2d216e4e2c7e306135 Binary files /dev/null and b/docs/img/c4c2d27f307636160d5773556cb14345.png differ diff --git a/docs/img/c5c16791538bd6838d6196a0b4ec5bb7.png b/docs/img/c5c16791538bd6838d6196a0b4ec5bb7.png new file mode 100644 index 0000000000000000000000000000000000000000..db9ed6b8eeca6cbb71fbda6b75fba0f2a9c5530e Binary files /dev/null and b/docs/img/c5c16791538bd6838d6196a0b4ec5bb7.png differ diff --git a/docs/img/c5d0cec2b61194796c06f7c2c5294294.png b/docs/img/c5d0cec2b61194796c06f7c2c5294294.png new file mode 100644 index 0000000000000000000000000000000000000000..80eec768f81c65e85ebf8b165a3eb0d8bcde6e31 Binary files /dev/null and b/docs/img/c5d0cec2b61194796c06f7c2c5294294.png differ diff --git a/docs/img/c5fbd1d44b70c599ae2cc8751ccfca14.png b/docs/img/c5fbd1d44b70c599ae2cc8751ccfca14.png new file mode 100644 index 0000000000000000000000000000000000000000..40239d6874a1b61b338620a1ed557c2e87701f62 Binary files /dev/null and b/docs/img/c5fbd1d44b70c599ae2cc8751ccfca14.png differ diff --git a/docs/img/c61ac95a0fe55d92ab3c711ea814a8c8.png b/docs/img/c61ac95a0fe55d92ab3c711ea814a8c8.png new file mode 100644 index 0000000000000000000000000000000000000000..2554c975d7171d2cff1a76004deb6be9f1377f63 Binary files /dev/null and b/docs/img/c61ac95a0fe55d92ab3c711ea814a8c8.png differ diff --git a/docs/img/c6273de0eb8e4c8e7750113a7a66e7d6.png b/docs/img/c6273de0eb8e4c8e7750113a7a66e7d6.png new file mode 100644 index 0000000000000000000000000000000000000000..e088f4c632e90b83039f3ee3f4bbbb8164bb4f74 Binary files /dev/null and b/docs/img/c6273de0eb8e4c8e7750113a7a66e7d6.png differ diff --git a/docs/img/c65afb6da67de7dea9950e2b151cca40.png b/docs/img/c65afb6da67de7dea9950e2b151cca40.png new file mode 100644 index 0000000000000000000000000000000000000000..62436ca7d1b75e859c922e8f17643c4d9fa81c8c Binary files /dev/null and b/docs/img/c65afb6da67de7dea9950e2b151cca40.png differ diff --git a/docs/img/c67bf60334fcbd1f63dc0a6515d02eca.png b/docs/img/c67bf60334fcbd1f63dc0a6515d02eca.png new file mode 100644 index 0000000000000000000000000000000000000000..d70adcb6d432776b17191acc3c7d1e77529a819d Binary files /dev/null and b/docs/img/c67bf60334fcbd1f63dc0a6515d02eca.png differ diff --git a/docs/img/c67faf1fb34407861ed68b426e46da72.png b/docs/img/c67faf1fb34407861ed68b426e46da72.png new file mode 100644 index 0000000000000000000000000000000000000000..0d12a66a8eb71d6275ca7dfcfb1d8d926afcb5be Binary files /dev/null and b/docs/img/c67faf1fb34407861ed68b426e46da72.png differ diff --git a/docs/img/c6a214b87abe3ccc6a5287ea1d256834.png b/docs/img/c6a214b87abe3ccc6a5287ea1d256834.png new file mode 100644 index 0000000000000000000000000000000000000000..9c964b08bb75bc6a5872349f0d06fc0ffe49de8d Binary files /dev/null and b/docs/img/c6a214b87abe3ccc6a5287ea1d256834.png differ diff --git a/docs/img/c6c38f70c273cc4412f6d3bd29af3829.png b/docs/img/c6c38f70c273cc4412f6d3bd29af3829.png new file mode 100644 index 0000000000000000000000000000000000000000..35d7389883b60a8b8a46e9f2e5b0b08e78b12eb2 Binary files /dev/null and b/docs/img/c6c38f70c273cc4412f6d3bd29af3829.png differ diff --git a/docs/img/c6daa1e81d653cfd0b476144f1f71874.png b/docs/img/c6daa1e81d653cfd0b476144f1f71874.png new file mode 100644 index 0000000000000000000000000000000000000000..5c9da6b107b8b77f66af491f065215d313f6519d Binary files /dev/null and b/docs/img/c6daa1e81d653cfd0b476144f1f71874.png differ diff --git a/docs/img/c7126ad3e897b95ff53bc9300bce4d43.png b/docs/img/c7126ad3e897b95ff53bc9300bce4d43.png new file mode 100644 index 0000000000000000000000000000000000000000..d00c640be9395a755ff2408254324d84c7dc91fc Binary files /dev/null and b/docs/img/c7126ad3e897b95ff53bc9300bce4d43.png differ diff --git a/docs/img/c73475715fce01bf6b51edda84064d67.png b/docs/img/c73475715fce01bf6b51edda84064d67.png new file mode 100644 index 0000000000000000000000000000000000000000..76e824ea96bb82332eadba9dbaf976c2e39e6727 Binary files /dev/null and b/docs/img/c73475715fce01bf6b51edda84064d67.png differ diff --git a/docs/img/c736ba09ab7186102250ad9e624d79c1.png b/docs/img/c736ba09ab7186102250ad9e624d79c1.png new file mode 100644 index 0000000000000000000000000000000000000000..83206cf6717b38e76aea9475527c656f89f3394e Binary files /dev/null and b/docs/img/c736ba09ab7186102250ad9e624d79c1.png differ diff --git a/docs/img/c7562ae46b8ec150661af0c88f1a5aad.png b/docs/img/c7562ae46b8ec150661af0c88f1a5aad.png new file mode 100644 index 0000000000000000000000000000000000000000..0416097fc40994a531b478b6e1af8c7c9dc0f2a2 Binary files /dev/null and b/docs/img/c7562ae46b8ec150661af0c88f1a5aad.png differ diff --git a/docs/img/c77b45147112088b7940cb4ebcc5f4a6.png b/docs/img/c77b45147112088b7940cb4ebcc5f4a6.png new file mode 100644 index 0000000000000000000000000000000000000000..ef438fb7739ae10c814ca9aeb33a2655977f2628 Binary files /dev/null and b/docs/img/c77b45147112088b7940cb4ebcc5f4a6.png differ diff --git a/docs/img/c7918abdac813cb6d0b57bb682269b93.png b/docs/img/c7918abdac813cb6d0b57bb682269b93.png new file mode 100644 index 0000000000000000000000000000000000000000..1c019afac8efd17513b817cb843a3c7057d2020a --- /dev/null +++ b/docs/img/c7918abdac813cb6d0b57bb682269b93.png @@ -0,0 +1,17 @@ + + + + + + + + + + coverage + + + unknown + + + + diff --git a/docs/img/c79ebe6e2611f151d42f879eaee753fe.png b/docs/img/c79ebe6e2611f151d42f879eaee753fe.png new file mode 100644 index 0000000000000000000000000000000000000000..6d0f4975db730818b46aba75f3fa41e29db0b39f Binary files /dev/null and b/docs/img/c79ebe6e2611f151d42f879eaee753fe.png differ diff --git a/docs/img/c7a5bc700a43a5880572c7f8cc0acdc7.png b/docs/img/c7a5bc700a43a5880572c7f8cc0acdc7.png new file mode 100644 index 0000000000000000000000000000000000000000..b10e672983ebb917b445af587552cb808af97d2e Binary files /dev/null and b/docs/img/c7a5bc700a43a5880572c7f8cc0acdc7.png differ diff --git a/docs/img/c7b2f6ed12531da21a4512becdf843af.png b/docs/img/c7b2f6ed12531da21a4512becdf843af.png new file mode 100644 index 0000000000000000000000000000000000000000..34860464b0379fcdf6a23e1a3fb3837a42dea9fc Binary files /dev/null and b/docs/img/c7b2f6ed12531da21a4512becdf843af.png differ diff --git a/docs/img/c7ee3e55c50a5f7d0e3faceda16e2dc2.png b/docs/img/c7ee3e55c50a5f7d0e3faceda16e2dc2.png new file mode 100644 index 0000000000000000000000000000000000000000..6b75dc997971100556327e66290a17c59d3dbc9d Binary files /dev/null and b/docs/img/c7ee3e55c50a5f7d0e3faceda16e2dc2.png differ diff --git a/docs/img/c89e56a24555efe89bb446cf31b5f764.png b/docs/img/c89e56a24555efe89bb446cf31b5f764.png new file mode 100644 index 0000000000000000000000000000000000000000..d3249d5d715897d94ca290ee4ee2c71666cf14c4 Binary files /dev/null and b/docs/img/c89e56a24555efe89bb446cf31b5f764.png differ diff --git a/docs/img/c932281f198053757ebfaf5a9b99b335.png b/docs/img/c932281f198053757ebfaf5a9b99b335.png new file mode 100644 index 0000000000000000000000000000000000000000..ac208fa2170ce32e8da1a2523301bb7a85bff9f7 Binary files /dev/null and b/docs/img/c932281f198053757ebfaf5a9b99b335.png differ diff --git a/docs/img/c9d2a45b5906d81d1118b63a832bbcd4.png b/docs/img/c9d2a45b5906d81d1118b63a832bbcd4.png new file mode 100644 index 0000000000000000000000000000000000000000..4abb872a8d6c2af6c3b2f55707d6fe5a584d681d Binary files /dev/null and b/docs/img/c9d2a45b5906d81d1118b63a832bbcd4.png differ diff --git a/docs/img/c9fb44f57074dc166ca07353bd7d31c7.png b/docs/img/c9fb44f57074dc166ca07353bd7d31c7.png new file mode 100644 index 0000000000000000000000000000000000000000..01b99d21fdd36c6530f7d24c317da6bbc6a31b96 Binary files /dev/null and b/docs/img/c9fb44f57074dc166ca07353bd7d31c7.png differ diff --git a/docs/img/ca33b4a75b3a1bc207dd2eddae8c3949.png b/docs/img/ca33b4a75b3a1bc207dd2eddae8c3949.png new file mode 100644 index 0000000000000000000000000000000000000000..bb16bdd21550985520157fa718ea10c29e75f684 Binary files /dev/null and b/docs/img/ca33b4a75b3a1bc207dd2eddae8c3949.png differ diff --git a/docs/img/ca66569a1f77e8f2d208a42e0fee1794.png b/docs/img/ca66569a1f77e8f2d208a42e0fee1794.png new file mode 100644 index 0000000000000000000000000000000000000000..a22c91ae13602e4764d0bdfd9d1039371bc4c91c Binary files /dev/null and b/docs/img/ca66569a1f77e8f2d208a42e0fee1794.png differ diff --git a/docs/img/cb3829e4d0ca25082e0f52f135a9d1de.png b/docs/img/cb3829e4d0ca25082e0f52f135a9d1de.png new file mode 100644 index 0000000000000000000000000000000000000000..7e9ddbee645a834e0423f1ef52a02dac6c48b529 Binary files /dev/null and b/docs/img/cb3829e4d0ca25082e0f52f135a9d1de.png differ diff --git a/docs/img/cb4ff59b46134d4c61caedcf5a66a74f.png b/docs/img/cb4ff59b46134d4c61caedcf5a66a74f.png new file mode 100644 index 0000000000000000000000000000000000000000..549a155702d95a8105b0851c5765e0d8a31f2a69 Binary files /dev/null and b/docs/img/cb4ff59b46134d4c61caedcf5a66a74f.png differ diff --git a/docs/img/cbd0470f26aadc25ca385447ade97392.png b/docs/img/cbd0470f26aadc25ca385447ade97392.png new file mode 100644 index 0000000000000000000000000000000000000000..a5b193d4d0d4f26e78d1a7b8bee342fdce5ff250 Binary files /dev/null and b/docs/img/cbd0470f26aadc25ca385447ade97392.png differ diff --git a/docs/img/cbf589a2c41bb518f8f2da56b76a59dc.png b/docs/img/cbf589a2c41bb518f8f2da56b76a59dc.png new file mode 100644 index 0000000000000000000000000000000000000000..f414c89d2626fac041ee325b7f7c95ac4a3fc90c Binary files /dev/null and b/docs/img/cbf589a2c41bb518f8f2da56b76a59dc.png differ diff --git a/docs/img/cc52a99e48b72695add0c3e8efab158f.png b/docs/img/cc52a99e48b72695add0c3e8efab158f.png new file mode 100644 index 0000000000000000000000000000000000000000..43fe705c45abb72ae7d5993613446d69bd0f0d04 Binary files /dev/null and b/docs/img/cc52a99e48b72695add0c3e8efab158f.png differ diff --git a/docs/img/cc6935399d2235840119ad00eb778fc9.png b/docs/img/cc6935399d2235840119ad00eb778fc9.png new file mode 100644 index 0000000000000000000000000000000000000000..a2b2514fd445c8748f25cb18273645fd767af981 Binary files /dev/null and b/docs/img/cc6935399d2235840119ad00eb778fc9.png differ diff --git a/docs/img/cca5497f42d0f0512126392deb81fa3e.png b/docs/img/cca5497f42d0f0512126392deb81fa3e.png new file mode 100644 index 0000000000000000000000000000000000000000..bcbd2cdf29cd2b54dc2d56291f5938328db870f6 Binary files /dev/null and b/docs/img/cca5497f42d0f0512126392deb81fa3e.png differ diff --git a/docs/img/cd210f00f72fcb8f7b00750457b0ab2c.png b/docs/img/cd210f00f72fcb8f7b00750457b0ab2c.png new file mode 100644 index 0000000000000000000000000000000000000000..f336cb8363894ea78568a85ac24d837b47d1f93c Binary files /dev/null and b/docs/img/cd210f00f72fcb8f7b00750457b0ab2c.png differ diff --git a/docs/img/cdce9b0515678bb30cdd0e1173a30749.png b/docs/img/cdce9b0515678bb30cdd0e1173a30749.png new file mode 100644 index 0000000000000000000000000000000000000000..26251ed46947e35835fe6c784668c398f9595aa2 Binary files /dev/null and b/docs/img/cdce9b0515678bb30cdd0e1173a30749.png differ diff --git a/docs/img/ce119917ec56b195b909d4371bb994aa.png b/docs/img/ce119917ec56b195b909d4371bb994aa.png new file mode 100644 index 0000000000000000000000000000000000000000..b90d9882a3979bd5cbf4e49fdf4f6ed7bf1f5583 Binary files /dev/null and b/docs/img/ce119917ec56b195b909d4371bb994aa.png differ diff --git a/docs/img/ce2f28e687df2b322895dbfb6c48d389.png b/docs/img/ce2f28e687df2b322895dbfb6c48d389.png new file mode 100644 index 0000000000000000000000000000000000000000..294ced1c3e7f9fd9b38d02360fae80e51071f113 Binary files /dev/null and b/docs/img/ce2f28e687df2b322895dbfb6c48d389.png differ diff --git a/docs/img/ce6315abe3d0bf8a315febe4ab497312.png b/docs/img/ce6315abe3d0bf8a315febe4ab497312.png new file mode 100644 index 0000000000000000000000000000000000000000..6ff5131b916de5631880e97a8495ebcbfa3d9dd6 Binary files /dev/null and b/docs/img/ce6315abe3d0bf8a315febe4ab497312.png differ diff --git a/docs/img/ce7d1dd63f95f0330b281fd577aaa8d4.png b/docs/img/ce7d1dd63f95f0330b281fd577aaa8d4.png new file mode 100644 index 0000000000000000000000000000000000000000..e18067cebbbe318474b3056546aa3033b7aa9888 Binary files /dev/null and b/docs/img/ce7d1dd63f95f0330b281fd577aaa8d4.png differ diff --git a/docs/img/ce9e5e0a216a3a51d412bcb3cb11f420.png b/docs/img/ce9e5e0a216a3a51d412bcb3cb11f420.png new file mode 100644 index 0000000000000000000000000000000000000000..22d66c364fd80ae232f669917a48dc57361f9e7b Binary files /dev/null and b/docs/img/ce9e5e0a216a3a51d412bcb3cb11f420.png differ diff --git a/docs/img/ceb135d0071e5591ba58f5d2820e8f4b.png b/docs/img/ceb135d0071e5591ba58f5d2820e8f4b.png new file mode 100644 index 0000000000000000000000000000000000000000..fd267c4d3113a8ce434c3b902e5f3ef63ca5b6ee Binary files /dev/null and b/docs/img/ceb135d0071e5591ba58f5d2820e8f4b.png differ diff --git a/docs/img/ced764ccc10657c7f37a1ffe8a7e338a.png b/docs/img/ced764ccc10657c7f37a1ffe8a7e338a.png new file mode 100644 index 0000000000000000000000000000000000000000..83e5711132c244261cef10e27c8aeb0ac9469131 Binary files /dev/null and b/docs/img/ced764ccc10657c7f37a1ffe8a7e338a.png differ diff --git a/docs/img/cee9b8bcba36170c0ae5df4747bb8c44.png b/docs/img/cee9b8bcba36170c0ae5df4747bb8c44.png new file mode 100644 index 0000000000000000000000000000000000000000..96ec83f3fa814414587590f0332182f17627f0b1 Binary files /dev/null and b/docs/img/cee9b8bcba36170c0ae5df4747bb8c44.png differ diff --git a/docs/img/cf0c5e15a3b44eb89d7513b961d6a274.png b/docs/img/cf0c5e15a3b44eb89d7513b961d6a274.png new file mode 100644 index 0000000000000000000000000000000000000000..29bd7b2a529a6e5b7f3cad09ee18e0928b4a3ccc Binary files /dev/null and b/docs/img/cf0c5e15a3b44eb89d7513b961d6a274.png differ diff --git a/docs/img/cff0e046ac8eca2d9fde8f13a3365d66.png b/docs/img/cff0e046ac8eca2d9fde8f13a3365d66.png new file mode 100644 index 0000000000000000000000000000000000000000..17439ac5747a89ed6b9265e88893824981b12dad Binary files /dev/null and b/docs/img/cff0e046ac8eca2d9fde8f13a3365d66.png differ diff --git a/docs/img/d0143a44aad793332527a786d79524f7.png b/docs/img/d0143a44aad793332527a786d79524f7.png new file mode 100644 index 0000000000000000000000000000000000000000..45e480a602fce8e8e554497c09937d2c6591dd6e Binary files /dev/null and b/docs/img/d0143a44aad793332527a786d79524f7.png differ diff --git a/docs/img/d04d999de9102632af46c867821c47c3.png b/docs/img/d04d999de9102632af46c867821c47c3.png new file mode 100644 index 0000000000000000000000000000000000000000..aab7332269e368cc2f9448140471925fc6fd5c65 Binary files /dev/null and b/docs/img/d04d999de9102632af46c867821c47c3.png differ diff --git a/docs/img/d0707d7a1f822105efb120e442c32246.png b/docs/img/d0707d7a1f822105efb120e442c32246.png new file mode 100644 index 0000000000000000000000000000000000000000..1fa24fddf6396df121cc80b2f34b56e517dde987 Binary files /dev/null and b/docs/img/d0707d7a1f822105efb120e442c32246.png differ diff --git a/docs/img/d0b0b1ad83988d76ef9c42281782f961.png b/docs/img/d0b0b1ad83988d76ef9c42281782f961.png new file mode 100644 index 0000000000000000000000000000000000000000..e05cb22930e6ca851e81d60bf5d3638f9a893dc0 Binary files /dev/null and b/docs/img/d0b0b1ad83988d76ef9c42281782f961.png differ diff --git a/docs/img/d0b9fcc8669d772a04d7d72ccb5a82cc.png b/docs/img/d0b9fcc8669d772a04d7d72ccb5a82cc.png new file mode 100644 index 0000000000000000000000000000000000000000..5df268318c8373dad7b4dd98a0c497601cde6482 Binary files /dev/null and b/docs/img/d0b9fcc8669d772a04d7d72ccb5a82cc.png differ diff --git a/docs/img/d0e9aaf43b9e19912342dddfb4b6be13.png b/docs/img/d0e9aaf43b9e19912342dddfb4b6be13.png new file mode 100644 index 0000000000000000000000000000000000000000..95e728219bd597a8e5c114c9540015a4aed54956 Binary files /dev/null and b/docs/img/d0e9aaf43b9e19912342dddfb4b6be13.png differ diff --git a/docs/img/d15d948fc7d1b6e5c8dabacbe7c2fcc9.png b/docs/img/d15d948fc7d1b6e5c8dabacbe7c2fcc9.png new file mode 100644 index 0000000000000000000000000000000000000000..d24d808fd73673f06c9330dbfcefff3494fa42c4 Binary files /dev/null and b/docs/img/d15d948fc7d1b6e5c8dabacbe7c2fcc9.png differ diff --git a/docs/img/d198d958fcf8be60727c232ff69b9713.png b/docs/img/d198d958fcf8be60727c232ff69b9713.png new file mode 100644 index 0000000000000000000000000000000000000000..ef6d2879e416deddd26026de55e9c232c5a36090 Binary files /dev/null and b/docs/img/d198d958fcf8be60727c232ff69b9713.png differ diff --git a/docs/img/d19e6203a8567c2d6be7d878dd653654.png b/docs/img/d19e6203a8567c2d6be7d878dd653654.png new file mode 100644 index 0000000000000000000000000000000000000000..ea83b183e391de849c1440d52f129f7481a651e6 Binary files /dev/null and b/docs/img/d19e6203a8567c2d6be7d878dd653654.png differ diff --git a/docs/img/d1c47110b6092ce9cec04ff22addfaa4.png b/docs/img/d1c47110b6092ce9cec04ff22addfaa4.png new file mode 100644 index 0000000000000000000000000000000000000000..a80fefb492a7cf047e168d61a9933441509dbeca Binary files /dev/null and b/docs/img/d1c47110b6092ce9cec04ff22addfaa4.png differ diff --git a/docs/img/d1e835585272f821d777f384eed6a832.png b/docs/img/d1e835585272f821d777f384eed6a832.png new file mode 100644 index 0000000000000000000000000000000000000000..4c4119dfd715a5ec06480c297f45862513667a80 Binary files /dev/null and b/docs/img/d1e835585272f821d777f384eed6a832.png differ diff --git a/docs/img/d241e2868510cfa5755170c1f02c78f3.png b/docs/img/d241e2868510cfa5755170c1f02c78f3.png new file mode 100644 index 0000000000000000000000000000000000000000..0182a8226bbfc7b964f13533b8c0fe08d830ad10 Binary files /dev/null and b/docs/img/d241e2868510cfa5755170c1f02c78f3.png differ diff --git a/docs/img/d25fe780083ad8adbc24cf5fcc4feaf8.png b/docs/img/d25fe780083ad8adbc24cf5fcc4feaf8.png new file mode 100644 index 0000000000000000000000000000000000000000..8b00820dd3728a2522c35bf74c950d1f0f7c3edf Binary files /dev/null and b/docs/img/d25fe780083ad8adbc24cf5fcc4feaf8.png differ diff --git a/docs/img/d277485e75207494ed3529dfcc7a6395.png b/docs/img/d277485e75207494ed3529dfcc7a6395.png new file mode 100644 index 0000000000000000000000000000000000000000..29edb7f70b076cfdf199fa60b7c938c472a487da Binary files /dev/null and b/docs/img/d277485e75207494ed3529dfcc7a6395.png differ diff --git a/docs/img/d2f0725099f8a66ed235d537ea6592a4.png b/docs/img/d2f0725099f8a66ed235d537ea6592a4.png new file mode 100644 index 0000000000000000000000000000000000000000..25992feca9f3534c7567986fc58841e19623681e Binary files /dev/null and b/docs/img/d2f0725099f8a66ed235d537ea6592a4.png differ diff --git a/docs/img/d32d8400522e9b5c9dd295fba00e1255.png b/docs/img/d32d8400522e9b5c9dd295fba00e1255.png new file mode 100644 index 0000000000000000000000000000000000000000..840a0d91ae943999d3d24836fcd556eee3e3d8b4 Binary files /dev/null and b/docs/img/d32d8400522e9b5c9dd295fba00e1255.png differ diff --git a/docs/img/d345ea7938f401127d9471442b27eb27.png b/docs/img/d345ea7938f401127d9471442b27eb27.png new file mode 100644 index 0000000000000000000000000000000000000000..2735c7a8d2af437c2d51424cac9100293428bd05 Binary files /dev/null and b/docs/img/d345ea7938f401127d9471442b27eb27.png differ diff --git a/docs/img/d366ea5b34fa89da8adbcbd7ec51bc2a.png b/docs/img/d366ea5b34fa89da8adbcbd7ec51bc2a.png new file mode 100644 index 0000000000000000000000000000000000000000..79dd5a4c6135aecee7c08b6dbda8d28624b12122 Binary files /dev/null and b/docs/img/d366ea5b34fa89da8adbcbd7ec51bc2a.png differ diff --git a/docs/img/d3cc00bf5599be56b0b3154ca2751cbc.png b/docs/img/d3cc00bf5599be56b0b3154ca2751cbc.png new file mode 100644 index 0000000000000000000000000000000000000000..c7e1530d8e2cb8dd6b5288b53ab5d45f34e4198a Binary files /dev/null and b/docs/img/d3cc00bf5599be56b0b3154ca2751cbc.png differ diff --git a/docs/img/d4a6279fcd73fa0a1dc68761261f4854.png b/docs/img/d4a6279fcd73fa0a1dc68761261f4854.png new file mode 100644 index 0000000000000000000000000000000000000000..d1ee6980b4623caa6b550996a8489c136a77743e Binary files /dev/null and b/docs/img/d4a6279fcd73fa0a1dc68761261f4854.png differ diff --git a/docs/img/d4fcdfd2497a9936b17469dbafbd320e.png b/docs/img/d4fcdfd2497a9936b17469dbafbd320e.png new file mode 100644 index 0000000000000000000000000000000000000000..66a2fcb999e76eeb1faed14cdddac5a225fdd9d9 Binary files /dev/null and b/docs/img/d4fcdfd2497a9936b17469dbafbd320e.png differ diff --git a/docs/img/d5171d012a8ff616032035f890d8dbd5.png b/docs/img/d5171d012a8ff616032035f890d8dbd5.png new file mode 100644 index 0000000000000000000000000000000000000000..96eaa1d5d1f5f154d0ee29bd4f12064edab6c78d Binary files /dev/null and b/docs/img/d5171d012a8ff616032035f890d8dbd5.png differ diff --git a/docs/img/d5a5a91fe5e2b490b9388b43801b6a39.png b/docs/img/d5a5a91fe5e2b490b9388b43801b6a39.png new file mode 100644 index 0000000000000000000000000000000000000000..74e75a7c4c6c16c06be7e372bca9a4cbc3749f07 Binary files /dev/null and b/docs/img/d5a5a91fe5e2b490b9388b43801b6a39.png differ diff --git a/docs/img/d5df9e77d389b58908ef235600ccc61c.png b/docs/img/d5df9e77d389b58908ef235600ccc61c.png new file mode 100644 index 0000000000000000000000000000000000000000..bbaa4c66717f6fc7eed9970a033f2dcbd46a5dd2 Binary files /dev/null and b/docs/img/d5df9e77d389b58908ef235600ccc61c.png differ diff --git a/docs/img/d677bbf1d2f77fd7394cddab976e6f67.png b/docs/img/d677bbf1d2f77fd7394cddab976e6f67.png new file mode 100644 index 0000000000000000000000000000000000000000..314447565d123168f7edd738fd215eedf41698c1 Binary files /dev/null and b/docs/img/d677bbf1d2f77fd7394cddab976e6f67.png differ diff --git a/docs/img/d67d5681f30c4769c6d92232eada26e4.png b/docs/img/d67d5681f30c4769c6d92232eada26e4.png new file mode 100644 index 0000000000000000000000000000000000000000..35b07bb5172cc2383eff92b4f2b802ca525179a8 Binary files /dev/null and b/docs/img/d67d5681f30c4769c6d92232eada26e4.png differ diff --git a/docs/img/d69ab181c07176aa054b0ceac08b702c.png b/docs/img/d69ab181c07176aa054b0ceac08b702c.png new file mode 100644 index 0000000000000000000000000000000000000000..68ed53c896b80706a60191d9878076d4f85534ac Binary files /dev/null and b/docs/img/d69ab181c07176aa054b0ceac08b702c.png differ diff --git a/docs/img/d79207e6e4f140448c9dd5e6ebe5e380.png b/docs/img/d79207e6e4f140448c9dd5e6ebe5e380.png new file mode 100644 index 0000000000000000000000000000000000000000..c0de3c431a8709f0c3acb5f5d930eab16be54b19 Binary files /dev/null and b/docs/img/d79207e6e4f140448c9dd5e6ebe5e380.png differ diff --git a/docs/img/d7b0c4003d725d7125fdfb9c24aae17e.png b/docs/img/d7b0c4003d725d7125fdfb9c24aae17e.png new file mode 100644 index 0000000000000000000000000000000000000000..ab3c1b02cb1620da020432cb9853aac5c7db37ed Binary files /dev/null and b/docs/img/d7b0c4003d725d7125fdfb9c24aae17e.png differ diff --git a/docs/img/d7b5490ec5cb26ce71f19d5c56f003f3.png b/docs/img/d7b5490ec5cb26ce71f19d5c56f003f3.png new file mode 100644 index 0000000000000000000000000000000000000000..53ae48aa0cfdf1b96cd73ea2bf42a2e8ce361e2e Binary files /dev/null and b/docs/img/d7b5490ec5cb26ce71f19d5c56f003f3.png differ diff --git a/docs/img/d7cb226977bb46d9aaa1c1d7e195025a.png b/docs/img/d7cb226977bb46d9aaa1c1d7e195025a.png new file mode 100644 index 0000000000000000000000000000000000000000..7bb9204fb06100c40294b64d1506875caee263f0 Binary files /dev/null and b/docs/img/d7cb226977bb46d9aaa1c1d7e195025a.png differ diff --git a/docs/img/d8baae909b3683bffff327402580132f.png b/docs/img/d8baae909b3683bffff327402580132f.png new file mode 100644 index 0000000000000000000000000000000000000000..378507a6b9c96c7ca8a84e7834ab1cff19589e43 Binary files /dev/null and b/docs/img/d8baae909b3683bffff327402580132f.png differ diff --git a/docs/img/da13575f699b92fa864c2d3fae1fae9e.png b/docs/img/da13575f699b92fa864c2d3fae1fae9e.png new file mode 100644 index 0000000000000000000000000000000000000000..9458cd2e77eb86475e3781a5097df791c18ab4ea Binary files /dev/null and b/docs/img/da13575f699b92fa864c2d3fae1fae9e.png differ diff --git a/docs/img/da1fdf492cc3f883353bb1997795a4a5.png b/docs/img/da1fdf492cc3f883353bb1997795a4a5.png new file mode 100644 index 0000000000000000000000000000000000000000..45a919b8ed676f03b0904ace40707206269be2e2 Binary files /dev/null and b/docs/img/da1fdf492cc3f883353bb1997795a4a5.png differ diff --git a/docs/img/da60a36cf66e162640faa1f6cddaacdc.png b/docs/img/da60a36cf66e162640faa1f6cddaacdc.png new file mode 100644 index 0000000000000000000000000000000000000000..af7c554f1c848073498090281b4373338dabd9f1 Binary files /dev/null and b/docs/img/da60a36cf66e162640faa1f6cddaacdc.png differ diff --git a/docs/img/da827bb1926cf748cff537fec6ecc954.png b/docs/img/da827bb1926cf748cff537fec6ecc954.png new file mode 100644 index 0000000000000000000000000000000000000000..c69fece9597f9fd43a0eef25e2a7a847a036113b Binary files /dev/null and b/docs/img/da827bb1926cf748cff537fec6ecc954.png differ diff --git a/docs/img/daa9468beb587bb748cbb9ec37bbb43f.png b/docs/img/daa9468beb587bb748cbb9ec37bbb43f.png new file mode 100644 index 0000000000000000000000000000000000000000..63c0ce25e4a323123a1bdd5e686fbdbb3e01f91a Binary files /dev/null and b/docs/img/daa9468beb587bb748cbb9ec37bbb43f.png differ diff --git a/docs/img/db0182b2e43670178e35b1a3485ca25e.png b/docs/img/db0182b2e43670178e35b1a3485ca25e.png new file mode 100644 index 0000000000000000000000000000000000000000..51115559e51e74689c04291f6359eecf97626043 Binary files /dev/null and b/docs/img/db0182b2e43670178e35b1a3485ca25e.png differ diff --git a/docs/img/db0b9c2164464a7b2e1772c54232681a.png b/docs/img/db0b9c2164464a7b2e1772c54232681a.png new file mode 100644 index 0000000000000000000000000000000000000000..d63cd87915f77371bbcbdb6167db653690f57000 Binary files /dev/null and b/docs/img/db0b9c2164464a7b2e1772c54232681a.png differ diff --git a/docs/img/db92110fba2588fed57b9af6bb2a381c.png b/docs/img/db92110fba2588fed57b9af6bb2a381c.png new file mode 100644 index 0000000000000000000000000000000000000000..249e669385a6b64ccf349797161b3dc7267d2e2e Binary files /dev/null and b/docs/img/db92110fba2588fed57b9af6bb2a381c.png differ diff --git a/docs/img/dbae11f07630ae759b8156031d0c496d.png b/docs/img/dbae11f07630ae759b8156031d0c496d.png new file mode 100644 index 0000000000000000000000000000000000000000..8a259a3b0f868c5be0993440850d883334389476 Binary files /dev/null and b/docs/img/dbae11f07630ae759b8156031d0c496d.png differ diff --git a/docs/img/dbb80511727781129d638c6d3413a45f.png b/docs/img/dbb80511727781129d638c6d3413a45f.png new file mode 100644 index 0000000000000000000000000000000000000000..0c76dc680fe798f9ce48a5fe2c809d7cf9c01560 Binary files /dev/null and b/docs/img/dbb80511727781129d638c6d3413a45f.png differ diff --git a/docs/img/dbb89cfb3c7539310a17d809c65c34a5.png b/docs/img/dbb89cfb3c7539310a17d809c65c34a5.png new file mode 100644 index 0000000000000000000000000000000000000000..36817ede83d124e1e7731f6ab13e2815ac304ff4 Binary files /dev/null and b/docs/img/dbb89cfb3c7539310a17d809c65c34a5.png differ diff --git a/docs/img/dc12d72310a7e06d2981fd6774b0903d.png b/docs/img/dc12d72310a7e06d2981fd6774b0903d.png new file mode 100644 index 0000000000000000000000000000000000000000..f2710d29ec3730d1be6a70f96152c37fd6d8108a Binary files /dev/null and b/docs/img/dc12d72310a7e06d2981fd6774b0903d.png differ diff --git a/docs/img/dc47374cec4da1de3e6476346ecf738e.png b/docs/img/dc47374cec4da1de3e6476346ecf738e.png new file mode 100644 index 0000000000000000000000000000000000000000..98ff87785f5baf08dcecf6b6faa3be1aef034538 Binary files /dev/null and b/docs/img/dc47374cec4da1de3e6476346ecf738e.png differ diff --git a/docs/img/dc5fe88e82dc925a618598e1ac284f39.png b/docs/img/dc5fe88e82dc925a618598e1ac284f39.png new file mode 100644 index 0000000000000000000000000000000000000000..0148e4db367791fb63a2a53162666f75fde16413 Binary files /dev/null and b/docs/img/dc5fe88e82dc925a618598e1ac284f39.png differ diff --git a/docs/img/dc75662feab34ea9fa5cb187a2d77739.png b/docs/img/dc75662feab34ea9fa5cb187a2d77739.png new file mode 100644 index 0000000000000000000000000000000000000000..d0dd28b0fa7c51ec03c8f67bf8203a40b493794e Binary files /dev/null and b/docs/img/dc75662feab34ea9fa5cb187a2d77739.png differ diff --git a/docs/img/dce9a8c36e06896553bd80f313c3a756.png b/docs/img/dce9a8c36e06896553bd80f313c3a756.png new file mode 100644 index 0000000000000000000000000000000000000000..babcddd5801415e42889f30938b3e4913326c332 Binary files /dev/null and b/docs/img/dce9a8c36e06896553bd80f313c3a756.png differ diff --git a/docs/img/dd6b38427a8d14832104464d1603afed.png b/docs/img/dd6b38427a8d14832104464d1603afed.png new file mode 100644 index 0000000000000000000000000000000000000000..7c94c05483405d479a4b07e1b84afd1fb0e5cd9d Binary files /dev/null and b/docs/img/dd6b38427a8d14832104464d1603afed.png differ diff --git a/docs/img/ddc1b7f5f622e5c8f6581738b42964cb.png b/docs/img/ddc1b7f5f622e5c8f6581738b42964cb.png new file mode 100644 index 0000000000000000000000000000000000000000..f29cc24db3c65e3b8db1aeb8eb2162fd6842081a Binary files /dev/null and b/docs/img/ddc1b7f5f622e5c8f6581738b42964cb.png differ diff --git a/docs/img/de408a3a079dceb2e72d044abac21ac3.png b/docs/img/de408a3a079dceb2e72d044abac21ac3.png new file mode 100644 index 0000000000000000000000000000000000000000..45922a9917742bf0d57fd5d2c25c459bd25b6263 Binary files /dev/null and b/docs/img/de408a3a079dceb2e72d044abac21ac3.png differ diff --git a/docs/img/de608fa9aefa963f38d0d95043413679.png b/docs/img/de608fa9aefa963f38d0d95043413679.png new file mode 100644 index 0000000000000000000000000000000000000000..dcb6a5a0bfd3d79cc8924acd12de7981860f2df9 Binary files /dev/null and b/docs/img/de608fa9aefa963f38d0d95043413679.png differ diff --git a/docs/img/def845e9e4d65228469b73dbc625c6cd.png b/docs/img/def845e9e4d65228469b73dbc625c6cd.png new file mode 100644 index 0000000000000000000000000000000000000000..286d7b7716c00064548a55a09018ab38795a22d3 Binary files /dev/null and b/docs/img/def845e9e4d65228469b73dbc625c6cd.png differ diff --git a/docs/img/defc257dc0219b95ed3f3065afcaff94.png b/docs/img/defc257dc0219b95ed3f3065afcaff94.png new file mode 100644 index 0000000000000000000000000000000000000000..a6badbe62325e02174c3ab2a73a7bab1a741ea9f Binary files /dev/null and b/docs/img/defc257dc0219b95ed3f3065afcaff94.png differ diff --git a/docs/img/e006fccde54b694d8c0f506a675942e0.png b/docs/img/e006fccde54b694d8c0f506a675942e0.png new file mode 100644 index 0000000000000000000000000000000000000000..13582e55eeac1038bfa9640eb6217e338359cc0b Binary files /dev/null and b/docs/img/e006fccde54b694d8c0f506a675942e0.png differ diff --git a/docs/img/e0fb1b28f653637edd64e072798f2385.png b/docs/img/e0fb1b28f653637edd64e072798f2385.png new file mode 100644 index 0000000000000000000000000000000000000000..90542ee2ed009eb97ed1f65582a3c223c255f707 Binary files /dev/null and b/docs/img/e0fb1b28f653637edd64e072798f2385.png differ diff --git a/docs/img/e14dc9ee9528f343daf09a4dd5340b99.png b/docs/img/e14dc9ee9528f343daf09a4dd5340b99.png new file mode 100644 index 0000000000000000000000000000000000000000..e6a73f291f965c7eaefcd3bcd7cbe5517c303401 Binary files /dev/null and b/docs/img/e14dc9ee9528f343daf09a4dd5340b99.png differ diff --git a/docs/img/e18ff80d06980688066f9ec9404bd2da.png b/docs/img/e18ff80d06980688066f9ec9404bd2da.png new file mode 100644 index 0000000000000000000000000000000000000000..5c85169a13a32b2a2879bc7d7cb0653b5face16a Binary files /dev/null and b/docs/img/e18ff80d06980688066f9ec9404bd2da.png differ diff --git a/docs/img/e1f4f357a93d9362f282810a575d73e3.png b/docs/img/e1f4f357a93d9362f282810a575d73e3.png new file mode 100644 index 0000000000000000000000000000000000000000..abeb6db9733a89e4ded2d53253e05e3ca9f35ed4 Binary files /dev/null and b/docs/img/e1f4f357a93d9362f282810a575d73e3.png differ diff --git a/docs/img/e20aec7ab33bbd61bae4825e6c9e35f1.png b/docs/img/e20aec7ab33bbd61bae4825e6c9e35f1.png new file mode 100644 index 0000000000000000000000000000000000000000..efc69387d86d3d1b255d17afc9260c0847849ee9 Binary files /dev/null and b/docs/img/e20aec7ab33bbd61bae4825e6c9e35f1.png differ diff --git a/docs/img/e255c03f63cd814a974b54b2a9eb6b02.png b/docs/img/e255c03f63cd814a974b54b2a9eb6b02.png new file mode 100644 index 0000000000000000000000000000000000000000..fbd66cc158395f1c3a17d1cf264e0cf76ef83710 Binary files /dev/null and b/docs/img/e255c03f63cd814a974b54b2a9eb6b02.png differ diff --git a/docs/img/e28a59687a00b33f8174f2bcba18ac5d.png b/docs/img/e28a59687a00b33f8174f2bcba18ac5d.png new file mode 100644 index 0000000000000000000000000000000000000000..6f5382d70fa3ba641cb8b2999fe81948049dc58e Binary files /dev/null and b/docs/img/e28a59687a00b33f8174f2bcba18ac5d.png differ diff --git a/docs/img/e28a69b4996ee400ca3df4431df0ab13.png b/docs/img/e28a69b4996ee400ca3df4431df0ab13.png new file mode 100644 index 0000000000000000000000000000000000000000..13e6edef7ed3a0cf89b7064ba797b6dcb6300ad9 Binary files /dev/null and b/docs/img/e28a69b4996ee400ca3df4431df0ab13.png differ diff --git a/docs/img/e2a52ca7a089fcbd9b17f94875cba0ca.png b/docs/img/e2a52ca7a089fcbd9b17f94875cba0ca.png new file mode 100644 index 0000000000000000000000000000000000000000..aa3210cc3eff162cb34698fba2f1641a8c10626e Binary files /dev/null and b/docs/img/e2a52ca7a089fcbd9b17f94875cba0ca.png differ diff --git a/docs/img/e2e1d44121ea24d32b388b9b84bd7ea5.png b/docs/img/e2e1d44121ea24d32b388b9b84bd7ea5.png new file mode 100644 index 0000000000000000000000000000000000000000..c9b9caf1cfefaf44b1c9134e0130e4307f1d0a76 Binary files /dev/null and b/docs/img/e2e1d44121ea24d32b388b9b84bd7ea5.png differ diff --git a/docs/img/e2e835cd5cd1be1afaa876fde2475fe5.png b/docs/img/e2e835cd5cd1be1afaa876fde2475fe5.png new file mode 100644 index 0000000000000000000000000000000000000000..031dd8a4b2a0f7dd51d32055ad18901ee1e44228 Binary files /dev/null and b/docs/img/e2e835cd5cd1be1afaa876fde2475fe5.png differ diff --git a/docs/img/e336833accfac93c8ed18718b667dab5.png b/docs/img/e336833accfac93c8ed18718b667dab5.png new file mode 100644 index 0000000000000000000000000000000000000000..907b6bf93629f4716c951a9cc8872aa5a7d6b0e5 Binary files /dev/null and b/docs/img/e336833accfac93c8ed18718b667dab5.png differ diff --git a/docs/img/e3439aafb873fb6b7cdb3a5c6d51c3b9.png b/docs/img/e3439aafb873fb6b7cdb3a5c6d51c3b9.png new file mode 100644 index 0000000000000000000000000000000000000000..39685c685b24e5e41364b5f0aaac6d6f5cbda3ba Binary files /dev/null and b/docs/img/e3439aafb873fb6b7cdb3a5c6d51c3b9.png differ diff --git a/docs/img/e3489f723615b369a1abec41ebe9dea2.png b/docs/img/e3489f723615b369a1abec41ebe9dea2.png new file mode 100644 index 0000000000000000000000000000000000000000..1df0b6da8c6919a67c294a7dba74fdd1a313dd36 Binary files /dev/null and b/docs/img/e3489f723615b369a1abec41ebe9dea2.png differ diff --git a/docs/img/e392f78e991a2b0865f4a2fe825fd7fc.png b/docs/img/e392f78e991a2b0865f4a2fe825fd7fc.png new file mode 100644 index 0000000000000000000000000000000000000000..ffc389881374d0c5ef08b42035e9255fc14d00b9 Binary files /dev/null and b/docs/img/e392f78e991a2b0865f4a2fe825fd7fc.png differ diff --git a/docs/img/e3e09b090e6c8612f71f6dbd7244cbb2.png b/docs/img/e3e09b090e6c8612f71f6dbd7244cbb2.png new file mode 100644 index 0000000000000000000000000000000000000000..5d2d0a9f7c0636f9b0ea58ed45dcff9029ac7a65 Binary files /dev/null and b/docs/img/e3e09b090e6c8612f71f6dbd7244cbb2.png differ diff --git a/docs/img/e3eeb697453d582cf0ec4a746f30ed31.png b/docs/img/e3eeb697453d582cf0ec4a746f30ed31.png new file mode 100644 index 0000000000000000000000000000000000000000..52872dc1ea5d10d8385161e1319bad476f589ef2 Binary files /dev/null and b/docs/img/e3eeb697453d582cf0ec4a746f30ed31.png differ diff --git a/docs/img/e3feca46add6d42b1afc92fcf120dbfb.png b/docs/img/e3feca46add6d42b1afc92fcf120dbfb.png new file mode 100644 index 0000000000000000000000000000000000000000..a2eeb07a2ff1f006f246f39466992b83787ce272 Binary files /dev/null and b/docs/img/e3feca46add6d42b1afc92fcf120dbfb.png differ diff --git a/docs/img/e41f9ac1eea140d12bc83ea9312e71d0.png b/docs/img/e41f9ac1eea140d12bc83ea9312e71d0.png new file mode 100644 index 0000000000000000000000000000000000000000..9ce1ae8ad80c403b2ec1f2f445a05fe752850a3e Binary files /dev/null and b/docs/img/e41f9ac1eea140d12bc83ea9312e71d0.png differ diff --git a/docs/img/e4581843d51522e972a6bb6716aa4b05.png b/docs/img/e4581843d51522e972a6bb6716aa4b05.png new file mode 100644 index 0000000000000000000000000000000000000000..c280c236f15aa3ddd8258d70f65b1a68af07d980 Binary files /dev/null and b/docs/img/e4581843d51522e972a6bb6716aa4b05.png differ diff --git a/docs/img/e470cb0eb6198f35d2db011704471fce.png b/docs/img/e470cb0eb6198f35d2db011704471fce.png new file mode 100644 index 0000000000000000000000000000000000000000..6acf3049416812ef941804e5a2bbaa045b52bd5a Binary files /dev/null and b/docs/img/e470cb0eb6198f35d2db011704471fce.png differ diff --git a/docs/img/e4b88f4d9d317b9a38522ce9c63f84bc.png b/docs/img/e4b88f4d9d317b9a38522ce9c63f84bc.png new file mode 100644 index 0000000000000000000000000000000000000000..de7dfaf2e6dc24fadb32ec1eae306a2130e8abf1 Binary files /dev/null and b/docs/img/e4b88f4d9d317b9a38522ce9c63f84bc.png differ diff --git a/docs/img/e4fa52f4d522392d049bf73b1bb065a5.png b/docs/img/e4fa52f4d522392d049bf73b1bb065a5.png new file mode 100644 index 0000000000000000000000000000000000000000..d6c330e4a7727c2746bab0c5827dd855e05f69df Binary files /dev/null and b/docs/img/e4fa52f4d522392d049bf73b1bb065a5.png differ diff --git a/docs/img/e545dd77cf453f5a97873da4f0083ebb.png b/docs/img/e545dd77cf453f5a97873da4f0083ebb.png new file mode 100644 index 0000000000000000000000000000000000000000..5b6a59705cef1d62479d996c2587f647303ee071 Binary files /dev/null and b/docs/img/e545dd77cf453f5a97873da4f0083ebb.png differ diff --git a/docs/img/e57526dd100a1b0a33bdae55e3bf32c7.png b/docs/img/e57526dd100a1b0a33bdae55e3bf32c7.png new file mode 100644 index 0000000000000000000000000000000000000000..5f16fdb3ab3a38f99d68e5d63a81a9e202966dd6 Binary files /dev/null and b/docs/img/e57526dd100a1b0a33bdae55e3bf32c7.png differ diff --git a/docs/img/e5d9c1be329fa86c36614dea613f69a3.png b/docs/img/e5d9c1be329fa86c36614dea613f69a3.png new file mode 100644 index 0000000000000000000000000000000000000000..3dd9c677935280cf2e5f4a158c0098d38472c04a Binary files /dev/null and b/docs/img/e5d9c1be329fa86c36614dea613f69a3.png differ diff --git a/docs/img/e5f179b25c2db023892b0a5f559b67d5.png b/docs/img/e5f179b25c2db023892b0a5f559b67d5.png new file mode 100644 index 0000000000000000000000000000000000000000..4627bf02954da67ab4584b89c6fc7354b08f78c9 Binary files /dev/null and b/docs/img/e5f179b25c2db023892b0a5f559b67d5.png differ diff --git a/docs/img/e6522f2cefe000bb17275b2a0451bf82.png b/docs/img/e6522f2cefe000bb17275b2a0451bf82.png new file mode 100644 index 0000000000000000000000000000000000000000..d3a2d825ff25f9275867df791957a511675079d6 Binary files /dev/null and b/docs/img/e6522f2cefe000bb17275b2a0451bf82.png differ diff --git a/docs/img/e661a6c6931c39f12f5b6833566b8947.png b/docs/img/e661a6c6931c39f12f5b6833566b8947.png new file mode 100644 index 0000000000000000000000000000000000000000..77b48b7189acb0f8e5997371c8e516697bdf924e Binary files /dev/null and b/docs/img/e661a6c6931c39f12f5b6833566b8947.png differ diff --git a/docs/img/e6ef8c883764c13967c9c9fcc5617980.png b/docs/img/e6ef8c883764c13967c9c9fcc5617980.png new file mode 100644 index 0000000000000000000000000000000000000000..961112c995525ae8fc32503c5c2e1d525656173e Binary files /dev/null and b/docs/img/e6ef8c883764c13967c9c9fcc5617980.png differ diff --git a/docs/img/e71e8b254fc758ab1a18ac4373e14344.png b/docs/img/e71e8b254fc758ab1a18ac4373e14344.png new file mode 100644 index 0000000000000000000000000000000000000000..0872d3ae2295d7538e5a7fe9ec25f70250a9ee8a Binary files /dev/null and b/docs/img/e71e8b254fc758ab1a18ac4373e14344.png differ diff --git a/docs/img/e75b1239d806589f91c4a40aba7fdc05.png b/docs/img/e75b1239d806589f91c4a40aba7fdc05.png new file mode 100644 index 0000000000000000000000000000000000000000..aa1e7807b1e70e9a85f20e1d1924405325ecf341 Binary files /dev/null and b/docs/img/e75b1239d806589f91c4a40aba7fdc05.png differ diff --git a/docs/img/e7acd74bc1dc7f0103e1b107aac74f84.png b/docs/img/e7acd74bc1dc7f0103e1b107aac74f84.png new file mode 100644 index 0000000000000000000000000000000000000000..797b65ae063bee8bc4c79dda233b0c647dcf6db0 Binary files /dev/null and b/docs/img/e7acd74bc1dc7f0103e1b107aac74f84.png differ diff --git a/docs/img/e7d35854d0a726fbc4756cca4de4bf77.png b/docs/img/e7d35854d0a726fbc4756cca4de4bf77.png new file mode 100644 index 0000000000000000000000000000000000000000..7e4084d7ec102bf29697e23bd00d09281b3a7a21 Binary files /dev/null and b/docs/img/e7d35854d0a726fbc4756cca4de4bf77.png differ diff --git a/docs/img/e7d7b1c5ccf121da6fcfbbc1eb78bbcd.png b/docs/img/e7d7b1c5ccf121da6fcfbbc1eb78bbcd.png new file mode 100644 index 0000000000000000000000000000000000000000..a98a73348524e1b65f066fbf891d0dbbba18700d Binary files /dev/null and b/docs/img/e7d7b1c5ccf121da6fcfbbc1eb78bbcd.png differ diff --git a/docs/img/e80fdda43c295fbc39611b3d918d4b75.png b/docs/img/e80fdda43c295fbc39611b3d918d4b75.png new file mode 100644 index 0000000000000000000000000000000000000000..8a55677a56ff1131a47a521caefdf7f9c3455ebb Binary files /dev/null and b/docs/img/e80fdda43c295fbc39611b3d918d4b75.png differ diff --git a/docs/img/e81fe926a5b379f37dfc5af80b8f83f3.png b/docs/img/e81fe926a5b379f37dfc5af80b8f83f3.png new file mode 100644 index 0000000000000000000000000000000000000000..d0e6d7adfcec88b97acef5a242011ba54d5a0a92 Binary files /dev/null and b/docs/img/e81fe926a5b379f37dfc5af80b8f83f3.png differ diff --git a/docs/img/e8c78799e0967a32ee1efeaea30f6213.png b/docs/img/e8c78799e0967a32ee1efeaea30f6213.png new file mode 100644 index 0000000000000000000000000000000000000000..65a377568d3f9f48307cd5109ab39c53f58df384 Binary files /dev/null and b/docs/img/e8c78799e0967a32ee1efeaea30f6213.png differ diff --git a/docs/img/e9dbc908a405f57008dbb80d1b8a9a70.png b/docs/img/e9dbc908a405f57008dbb80d1b8a9a70.png new file mode 100644 index 0000000000000000000000000000000000000000..213c5ed75450eca18c707010cc75ee2fa1bdf218 Binary files /dev/null and b/docs/img/e9dbc908a405f57008dbb80d1b8a9a70.png differ diff --git a/docs/img/e9fe43924bd4226e7b819104bcc8b8c1.png b/docs/img/e9fe43924bd4226e7b819104bcc8b8c1.png new file mode 100644 index 0000000000000000000000000000000000000000..450cc70b9ba13a79de4eec6fafc8f8e3e58a72fa Binary files /dev/null and b/docs/img/e9fe43924bd4226e7b819104bcc8b8c1.png differ diff --git a/docs/img/ea01744c06eb8853392bfd840dc1517d.png b/docs/img/ea01744c06eb8853392bfd840dc1517d.png new file mode 100644 index 0000000000000000000000000000000000000000..6ef1ed0f1b27d1195c8fa05d728ff0d2a619f1eb Binary files /dev/null and b/docs/img/ea01744c06eb8853392bfd840dc1517d.png differ diff --git a/docs/img/ea0e34b1e4e7a7a6379bc52995143bf9.png b/docs/img/ea0e34b1e4e7a7a6379bc52995143bf9.png new file mode 100644 index 0000000000000000000000000000000000000000..36b7c732de9a5712fdc61707148276183e88022a Binary files /dev/null and b/docs/img/ea0e34b1e4e7a7a6379bc52995143bf9.png differ diff --git a/docs/img/ea665ae1d507d66f5a44d05ff9e32613.png b/docs/img/ea665ae1d507d66f5a44d05ff9e32613.png new file mode 100644 index 0000000000000000000000000000000000000000..034187445c6f0005520031e03e598210f15f7a75 Binary files /dev/null and b/docs/img/ea665ae1d507d66f5a44d05ff9e32613.png differ diff --git a/docs/img/ea804dce7429c547bcf0703446150f59.png b/docs/img/ea804dce7429c547bcf0703446150f59.png new file mode 100644 index 0000000000000000000000000000000000000000..7a40b049f6500eabe8431cfc045517d823ae439d Binary files /dev/null and b/docs/img/ea804dce7429c547bcf0703446150f59.png differ diff --git a/docs/img/eaa74cb66b0dd1b45f9b312af76c23fb.png b/docs/img/eaa74cb66b0dd1b45f9b312af76c23fb.png new file mode 100644 index 0000000000000000000000000000000000000000..733b4168f28dbdc9a1341fc32005775e82b1bfc7 Binary files /dev/null and b/docs/img/eaa74cb66b0dd1b45f9b312af76c23fb.png differ diff --git a/docs/img/eac2240244a4d3fb9f3d16c19760ea53.png b/docs/img/eac2240244a4d3fb9f3d16c19760ea53.png new file mode 100644 index 0000000000000000000000000000000000000000..48ba055cf80259c93d7128bfb7812f4ec4bbc9e9 Binary files /dev/null and b/docs/img/eac2240244a4d3fb9f3d16c19760ea53.png differ diff --git a/docs/img/ead8d62e426d9309f25a82da77770f59.png b/docs/img/ead8d62e426d9309f25a82da77770f59.png new file mode 100644 index 0000000000000000000000000000000000000000..27857a4bda81d2507fce27e61ea8809d67d04973 Binary files /dev/null and b/docs/img/ead8d62e426d9309f25a82da77770f59.png differ diff --git a/docs/img/eb191fa059117d5fb30958d7f6241704.png b/docs/img/eb191fa059117d5fb30958d7f6241704.png new file mode 100644 index 0000000000000000000000000000000000000000..e4161dbc6e3a961f810b7b998b833ff418ec98a6 Binary files /dev/null and b/docs/img/eb191fa059117d5fb30958d7f6241704.png differ diff --git a/docs/img/eb36e4acf26c49641689d1a05dd8fa8a.png b/docs/img/eb36e4acf26c49641689d1a05dd8fa8a.png new file mode 100644 index 0000000000000000000000000000000000000000..c6f69f98baaf962055e356ced11f840d33d4e0d8 Binary files /dev/null and b/docs/img/eb36e4acf26c49641689d1a05dd8fa8a.png differ diff --git a/docs/img/eb851fa4a367081c86d0a2eac3bdca65.png b/docs/img/eb851fa4a367081c86d0a2eac3bdca65.png new file mode 100644 index 0000000000000000000000000000000000000000..790f55fb2aef96782ca90cbeab03f8a527d502be Binary files /dev/null and b/docs/img/eb851fa4a367081c86d0a2eac3bdca65.png differ diff --git a/docs/img/eb93aca89ce7486ca89aa5a9f4357617.png b/docs/img/eb93aca89ce7486ca89aa5a9f4357617.png new file mode 100644 index 0000000000000000000000000000000000000000..fda2b72c510589901869abd205191fd7d36af913 Binary files /dev/null and b/docs/img/eb93aca89ce7486ca89aa5a9f4357617.png differ diff --git a/docs/img/ebaf329b1a5a45f2d451e4574f3d7857.png b/docs/img/ebaf329b1a5a45f2d451e4574f3d7857.png new file mode 100644 index 0000000000000000000000000000000000000000..0a6d821bc02b81d60ed9dabc96cb53653d3ee81c --- /dev/null +++ b/docs/img/ebaf329b1a5a45f2d451e4574f3d7857.png @@ -0,0 +1,265 @@ + + + +Page Not Found | GitLab Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + +
      +
      +
      +
      +
      +404 +
      +
      +
      +
      +
      + + + + + + + +
      +
      +
      + +
      +
      +
      +
      + +
      +
      + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/img/ebc54b5fdcb529ff40d6d097098188ae.png b/docs/img/ebc54b5fdcb529ff40d6d097098188ae.png new file mode 100644 index 0000000000000000000000000000000000000000..bd9c2ae9f71fa119e6137d486e97ba60fb207304 Binary files /dev/null and b/docs/img/ebc54b5fdcb529ff40d6d097098188ae.png differ diff --git a/docs/img/ec9eebd0b49b9f0b94eb6d12fadd7cf5.png b/docs/img/ec9eebd0b49b9f0b94eb6d12fadd7cf5.png new file mode 100644 index 0000000000000000000000000000000000000000..b03c585bd3f70bb3e27a231148709605884bfac9 Binary files /dev/null and b/docs/img/ec9eebd0b49b9f0b94eb6d12fadd7cf5.png differ diff --git a/docs/img/eca0c9ec85c6dfc8dbde06c368a9d94d.png b/docs/img/eca0c9ec85c6dfc8dbde06c368a9d94d.png new file mode 100644 index 0000000000000000000000000000000000000000..a9e3343b396499fbcce2b625ebaadf0f01732a8f Binary files /dev/null and b/docs/img/eca0c9ec85c6dfc8dbde06c368a9d94d.png differ diff --git a/docs/img/ecb561241f5fcf0f0695ee4e29069b11.png b/docs/img/ecb561241f5fcf0f0695ee4e29069b11.png new file mode 100644 index 0000000000000000000000000000000000000000..14c84825b19c1a7b143239a8e79f65f4d273d276 Binary files /dev/null and b/docs/img/ecb561241f5fcf0f0695ee4e29069b11.png differ diff --git a/docs/img/ecb68ae545435c5eb9229937635a5aee.png b/docs/img/ecb68ae545435c5eb9229937635a5aee.png new file mode 100644 index 0000000000000000000000000000000000000000..891b21f4f766ea3fc3a1c4be62e1ee4c92f311b7 Binary files /dev/null and b/docs/img/ecb68ae545435c5eb9229937635a5aee.png differ diff --git a/docs/img/ece990045e1a7ae1237b5f2912a2df3e.png b/docs/img/ece990045e1a7ae1237b5f2912a2df3e.png new file mode 100644 index 0000000000000000000000000000000000000000..8091f290afe453c3629255f49590db7ab6297410 Binary files /dev/null and b/docs/img/ece990045e1a7ae1237b5f2912a2df3e.png differ diff --git a/docs/img/ed5a96971ab453e6d33b3ad9079bd47c.png b/docs/img/ed5a96971ab453e6d33b3ad9079bd47c.png new file mode 100644 index 0000000000000000000000000000000000000000..1d9bae148566b23a5d2d27f54994c25ba8a6e216 Binary files /dev/null and b/docs/img/ed5a96971ab453e6d33b3ad9079bd47c.png differ diff --git a/docs/img/ed70f998a438f30a2762829a3cc5b5b6.png b/docs/img/ed70f998a438f30a2762829a3cc5b5b6.png new file mode 100644 index 0000000000000000000000000000000000000000..7d4f4a24cf80652c03b0bcfd3f347f26e943069f Binary files /dev/null and b/docs/img/ed70f998a438f30a2762829a3cc5b5b6.png differ diff --git a/docs/img/ed7d654fa8271709dfa6c567b48c5de6.png b/docs/img/ed7d654fa8271709dfa6c567b48c5de6.png new file mode 100644 index 0000000000000000000000000000000000000000..71f773b4a6b07125ab6a2466d00e59248ad33b71 Binary files /dev/null and b/docs/img/ed7d654fa8271709dfa6c567b48c5de6.png differ diff --git a/docs/img/ed8bdb5d349320bc1d470f096578dfe7.png b/docs/img/ed8bdb5d349320bc1d470f096578dfe7.png new file mode 100644 index 0000000000000000000000000000000000000000..1a70c4041fc648ec5105af96bef67ffcdbb63417 Binary files /dev/null and b/docs/img/ed8bdb5d349320bc1d470f096578dfe7.png differ diff --git a/docs/img/ed8e7e034537074afe857aa208bd315c.png b/docs/img/ed8e7e034537074afe857aa208bd315c.png new file mode 100644 index 0000000000000000000000000000000000000000..d7193d25bec814e1e8e719630f1e5e44217b7ce0 Binary files /dev/null and b/docs/img/ed8e7e034537074afe857aa208bd315c.png differ diff --git a/docs/img/ee0396a1cb32367d7ba7c6f4a7262c7f.png b/docs/img/ee0396a1cb32367d7ba7c6f4a7262c7f.png new file mode 100644 index 0000000000000000000000000000000000000000..b120099391faca900fb1de5575ea4d30c91514ae Binary files /dev/null and b/docs/img/ee0396a1cb32367d7ba7c6f4a7262c7f.png differ diff --git a/docs/img/ee04e8247fff074d8b122d6b5ec848f4.png b/docs/img/ee04e8247fff074d8b122d6b5ec848f4.png new file mode 100644 index 0000000000000000000000000000000000000000..3a495fe407b76e6fbe497026a05273d1268faef5 Binary files /dev/null and b/docs/img/ee04e8247fff074d8b122d6b5ec848f4.png differ diff --git a/docs/img/ee8ead7652026dd03a75e2551122350f.png b/docs/img/ee8ead7652026dd03a75e2551122350f.png new file mode 100644 index 0000000000000000000000000000000000000000..2e1abf75bf7939db4bab30835801d4b3ea55bc37 Binary files /dev/null and b/docs/img/ee8ead7652026dd03a75e2551122350f.png differ diff --git a/docs/img/eeadc0bb054ceec8f09d2c44982f4103.png b/docs/img/eeadc0bb054ceec8f09d2c44982f4103.png new file mode 100644 index 0000000000000000000000000000000000000000..26a8b91c3ef65551938fb6d836e18198006ef262 Binary files /dev/null and b/docs/img/eeadc0bb054ceec8f09d2c44982f4103.png differ diff --git a/docs/img/eec4d73b57835f2caa3ad88d45260b49.png b/docs/img/eec4d73b57835f2caa3ad88d45260b49.png new file mode 100644 index 0000000000000000000000000000000000000000..d88e9037a388e78039c1fbb955536a6526f8b392 Binary files /dev/null and b/docs/img/eec4d73b57835f2caa3ad88d45260b49.png differ diff --git a/docs/img/ef26fe9cbbfc0c1f060c6e7c578bd450.png b/docs/img/ef26fe9cbbfc0c1f060c6e7c578bd450.png new file mode 100644 index 0000000000000000000000000000000000000000..eefa7f43469943ae576021ef12aabd9f1bd7e29c Binary files /dev/null and b/docs/img/ef26fe9cbbfc0c1f060c6e7c578bd450.png differ diff --git a/docs/img/ef67d77909a856277f9f2821fa0c18ea.png b/docs/img/ef67d77909a856277f9f2821fa0c18ea.png new file mode 100644 index 0000000000000000000000000000000000000000..2d723d21d28f8e5f3fbaee7055858496d3f6dc1b Binary files /dev/null and b/docs/img/ef67d77909a856277f9f2821fa0c18ea.png differ diff --git a/docs/img/ef8ff296b4a28ddcd52a6c4fd3ded454.png b/docs/img/ef8ff296b4a28ddcd52a6c4fd3ded454.png new file mode 100644 index 0000000000000000000000000000000000000000..018ad66f4807d701751f05c15047f1ce123d738f Binary files /dev/null and b/docs/img/ef8ff296b4a28ddcd52a6c4fd3ded454.png differ diff --git a/docs/img/f08e838598cbf1f61321a510bb24c6a1.png b/docs/img/f08e838598cbf1f61321a510bb24c6a1.png new file mode 100644 index 0000000000000000000000000000000000000000..47744d767cafc78b60ef755e7341ea3ac422e9f3 Binary files /dev/null and b/docs/img/f08e838598cbf1f61321a510bb24c6a1.png differ diff --git a/docs/img/f0a8b71ac0a74f03724937e45e8782b9.png b/docs/img/f0a8b71ac0a74f03724937e45e8782b9.png new file mode 100644 index 0000000000000000000000000000000000000000..5528a9bb4d9d05edefd2ab94f40a6578cf72a6fb Binary files /dev/null and b/docs/img/f0a8b71ac0a74f03724937e45e8782b9.png differ diff --git a/docs/img/f0d4bcbd75dfae1dbbc867343090a4ca.png b/docs/img/f0d4bcbd75dfae1dbbc867343090a4ca.png new file mode 100644 index 0000000000000000000000000000000000000000..48820f5a3d390fe6cb4f3c0a23ad078bc127e80e Binary files /dev/null and b/docs/img/f0d4bcbd75dfae1dbbc867343090a4ca.png differ diff --git a/docs/img/f0d8585fb8235b36b1464ed1d142a4c0.png b/docs/img/f0d8585fb8235b36b1464ed1d142a4c0.png new file mode 100644 index 0000000000000000000000000000000000000000..c20e5cd70231df16da0eb2f0123677dc30a33617 Binary files /dev/null and b/docs/img/f0d8585fb8235b36b1464ed1d142a4c0.png differ diff --git a/docs/img/f12701028e6548c505318ef2d4e378db.png b/docs/img/f12701028e6548c505318ef2d4e378db.png new file mode 100644 index 0000000000000000000000000000000000000000..7422a121841e499a6cd6e79b827505310b8cbcf2 Binary files /dev/null and b/docs/img/f12701028e6548c505318ef2d4e378db.png differ diff --git a/docs/img/f1e26381a4d60fa929a9285e04721656.png b/docs/img/f1e26381a4d60fa929a9285e04721656.png new file mode 100644 index 0000000000000000000000000000000000000000..a86dd6e374963a4c468b41a7e0fd22d8f6ede71b Binary files /dev/null and b/docs/img/f1e26381a4d60fa929a9285e04721656.png differ diff --git a/docs/img/f293e9e73b2cf8c4ef278104fbd068d5.png b/docs/img/f293e9e73b2cf8c4ef278104fbd068d5.png new file mode 100644 index 0000000000000000000000000000000000000000..0a7bc01310f435ee28a891b62c26a2d3c0c2721e Binary files /dev/null and b/docs/img/f293e9e73b2cf8c4ef278104fbd068d5.png differ diff --git a/docs/img/f2d420adddd87cc8087fea62246e7b67.png b/docs/img/f2d420adddd87cc8087fea62246e7b67.png new file mode 100644 index 0000000000000000000000000000000000000000..9749a791e030bf72a76724aa0840911e9ed10b16 Binary files /dev/null and b/docs/img/f2d420adddd87cc8087fea62246e7b67.png differ diff --git a/docs/img/f313f74b73573e7a2449aa6d00ae7934.png b/docs/img/f313f74b73573e7a2449aa6d00ae7934.png new file mode 100644 index 0000000000000000000000000000000000000000..78b810e200e4dde279be2a1114527746519d600c Binary files /dev/null and b/docs/img/f313f74b73573e7a2449aa6d00ae7934.png differ diff --git a/docs/img/f3550bb5a4a6074ef46ae27848adc308.png b/docs/img/f3550bb5a4a6074ef46ae27848adc308.png new file mode 100644 index 0000000000000000000000000000000000000000..608959f8d821d26713da96d45c7181635c15303b Binary files /dev/null and b/docs/img/f3550bb5a4a6074ef46ae27848adc308.png differ diff --git a/docs/img/f36631c8d1fd9cb42fb7c58a495c24be.png b/docs/img/f36631c8d1fd9cb42fb7c58a495c24be.png new file mode 100644 index 0000000000000000000000000000000000000000..4231c353c59c997dac90b9f3c3e15b0b65610af6 Binary files /dev/null and b/docs/img/f36631c8d1fd9cb42fb7c58a495c24be.png differ diff --git a/docs/img/f380fbb3646558d8becf561df5894c38.png b/docs/img/f380fbb3646558d8becf561df5894c38.png new file mode 100644 index 0000000000000000000000000000000000000000..c69ef2499032d756ccdd89dce84b84d14358159f Binary files /dev/null and b/docs/img/f380fbb3646558d8becf561df5894c38.png differ diff --git a/docs/img/f406b88682259abab36d343539b1664c.png b/docs/img/f406b88682259abab36d343539b1664c.png new file mode 100644 index 0000000000000000000000000000000000000000..5129573a3c1ba13628eb0e4a701364afe8565501 Binary files /dev/null and b/docs/img/f406b88682259abab36d343539b1664c.png differ diff --git a/docs/img/f44886a0dc98ed48e0854c7d2ac6a220.png b/docs/img/f44886a0dc98ed48e0854c7d2ac6a220.png new file mode 100644 index 0000000000000000000000000000000000000000..6368c6e82b0be5479f35b72bf2f96f89ea943c0a Binary files /dev/null and b/docs/img/f44886a0dc98ed48e0854c7d2ac6a220.png differ diff --git a/docs/img/f4a6d7020c73bd402fc6428d02a4e550.png b/docs/img/f4a6d7020c73bd402fc6428d02a4e550.png new file mode 100644 index 0000000000000000000000000000000000000000..f7242dd5c50539546cd8b1825ef24b8df80afd22 Binary files /dev/null and b/docs/img/f4a6d7020c73bd402fc6428d02a4e550.png differ diff --git a/docs/img/f52fe1b4788045a510a1783bfb546b6f.png b/docs/img/f52fe1b4788045a510a1783bfb546b6f.png new file mode 100644 index 0000000000000000000000000000000000000000..88f25e9fe236b30a9309b6ea69754520cdb8c0ba Binary files /dev/null and b/docs/img/f52fe1b4788045a510a1783bfb546b6f.png differ diff --git a/docs/img/f5739c1b278ddd91c915c534514b4235.png b/docs/img/f5739c1b278ddd91c915c534514b4235.png new file mode 100644 index 0000000000000000000000000000000000000000..a1d7bc2878d3f66a38350315857b794fff497f7b Binary files /dev/null and b/docs/img/f5739c1b278ddd91c915c534514b4235.png differ diff --git a/docs/img/f5f57e5e3d074f574a5b26d23eb0b721.png b/docs/img/f5f57e5e3d074f574a5b26d23eb0b721.png new file mode 100644 index 0000000000000000000000000000000000000000..374de715ab46f139a6c35a2c456ae63d221e14b5 Binary files /dev/null and b/docs/img/f5f57e5e3d074f574a5b26d23eb0b721.png differ diff --git a/docs/img/f60803ec89d6ae84310e181507eb2ad8.png b/docs/img/f60803ec89d6ae84310e181507eb2ad8.png new file mode 100644 index 0000000000000000000000000000000000000000..c1aa44669a873fc61b55e3cf4f635240cd04b0f1 Binary files /dev/null and b/docs/img/f60803ec89d6ae84310e181507eb2ad8.png differ diff --git a/docs/img/f652f5dac5bec0bb81edc08cbfd7a01b.png b/docs/img/f652f5dac5bec0bb81edc08cbfd7a01b.png new file mode 100644 index 0000000000000000000000000000000000000000..48a88fedc8d9d38f2340e5015e4cf78394e01de6 Binary files /dev/null and b/docs/img/f652f5dac5bec0bb81edc08cbfd7a01b.png differ diff --git a/docs/img/f6b1fbcae610d7e8b04ec117e32573f3.png b/docs/img/f6b1fbcae610d7e8b04ec117e32573f3.png new file mode 100644 index 0000000000000000000000000000000000000000..ca9882d2902fc80f4abe3addad66db2b851cadc0 Binary files /dev/null and b/docs/img/f6b1fbcae610d7e8b04ec117e32573f3.png differ diff --git a/docs/img/f6e26efd0e5206a2e9d1bf43865b9f4a.png b/docs/img/f6e26efd0e5206a2e9d1bf43865b9f4a.png new file mode 100644 index 0000000000000000000000000000000000000000..c4f392553bba74d680656aed3c65c990767b12e5 Binary files /dev/null and b/docs/img/f6e26efd0e5206a2e9d1bf43865b9f4a.png differ diff --git a/docs/img/f7050ce0aa3559c639befc2fe3d7aacb.png b/docs/img/f7050ce0aa3559c639befc2fe3d7aacb.png new file mode 100644 index 0000000000000000000000000000000000000000..fe057773f62136fd59232126e0377b48f15c61b8 Binary files /dev/null and b/docs/img/f7050ce0aa3559c639befc2fe3d7aacb.png differ diff --git a/docs/img/f7ae6b6be5d2dd02010825234555fee6.png b/docs/img/f7ae6b6be5d2dd02010825234555fee6.png new file mode 100644 index 0000000000000000000000000000000000000000..df7e89862834fc0227453945ec11743ff4abbb62 Binary files /dev/null and b/docs/img/f7ae6b6be5d2dd02010825234555fee6.png differ diff --git a/docs/img/f7bf9b7c134eb4ee2629082be8992d5a.png b/docs/img/f7bf9b7c134eb4ee2629082be8992d5a.png new file mode 100644 index 0000000000000000000000000000000000000000..c3cb7f7cceae1f71ac0c81004c7879235c6b7015 Binary files /dev/null and b/docs/img/f7bf9b7c134eb4ee2629082be8992d5a.png differ diff --git a/docs/img/f81ccf2ef168880473496ad46b2d991f.png b/docs/img/f81ccf2ef168880473496ad46b2d991f.png new file mode 100644 index 0000000000000000000000000000000000000000..5d1e2fe43eb3a716a8a9b5512213e852a25733b1 Binary files /dev/null and b/docs/img/f81ccf2ef168880473496ad46b2d991f.png differ diff --git a/docs/img/f8c3e75c59db0de2544d73c590e98696.png b/docs/img/f8c3e75c59db0de2544d73c590e98696.png new file mode 100644 index 0000000000000000000000000000000000000000..313c88a666529f01c31983845aef1cac6b5bba88 Binary files /dev/null and b/docs/img/f8c3e75c59db0de2544d73c590e98696.png differ diff --git a/docs/img/f8c421bf7dd271d1aeee39c15aab183d.png b/docs/img/f8c421bf7dd271d1aeee39c15aab183d.png new file mode 100644 index 0000000000000000000000000000000000000000..91afff16ba50d9af08bb4492a94a8e3f0065a99f Binary files /dev/null and b/docs/img/f8c421bf7dd271d1aeee39c15aab183d.png differ diff --git a/docs/img/f8cfebdbd362ba809375c8d9c38416ba.png b/docs/img/f8cfebdbd362ba809375c8d9c38416ba.png new file mode 100644 index 0000000000000000000000000000000000000000..a84f0c4b86983ed2fa99b8a8fd809f330dad44c8 Binary files /dev/null and b/docs/img/f8cfebdbd362ba809375c8d9c38416ba.png differ diff --git a/docs/img/f9144e03cf945bcf549c131e2816298f.png b/docs/img/f9144e03cf945bcf549c131e2816298f.png new file mode 100644 index 0000000000000000000000000000000000000000..8b1a7e6890a9352e38f526e56dd6932538abf498 Binary files /dev/null and b/docs/img/f9144e03cf945bcf549c131e2816298f.png differ diff --git a/docs/img/f94efd219528f7641e29dbca3bc215ad.png b/docs/img/f94efd219528f7641e29dbca3bc215ad.png new file mode 100644 index 0000000000000000000000000000000000000000..a92a3362eee67d783b140b9d558afe378a51912a Binary files /dev/null and b/docs/img/f94efd219528f7641e29dbca3bc215ad.png differ diff --git a/docs/img/f9a1ce8fe1042543bc2355950f642a05.png b/docs/img/f9a1ce8fe1042543bc2355950f642a05.png new file mode 100644 index 0000000000000000000000000000000000000000..aa030517803ea8c5ced744019967a1960647a4fe Binary files /dev/null and b/docs/img/f9a1ce8fe1042543bc2355950f642a05.png differ diff --git a/docs/img/f9be0028bdcfdf495f7fd0f148de5214.png b/docs/img/f9be0028bdcfdf495f7fd0f148de5214.png new file mode 100644 index 0000000000000000000000000000000000000000..944bd3045109705afbe8d6381a95b566596ff945 Binary files /dev/null and b/docs/img/f9be0028bdcfdf495f7fd0f148de5214.png differ diff --git a/docs/img/fa591f90dc1e8840fe7fd692f24dcffe.png b/docs/img/fa591f90dc1e8840fe7fd692f24dcffe.png new file mode 100644 index 0000000000000000000000000000000000000000..acb0ed243428adf45d0627b21df26767451d6f14 Binary files /dev/null and b/docs/img/fa591f90dc1e8840fe7fd692f24dcffe.png differ diff --git a/docs/img/fad2df1fa4371b39b3ea1032a8ad236c.png b/docs/img/fad2df1fa4371b39b3ea1032a8ad236c.png new file mode 100644 index 0000000000000000000000000000000000000000..58bdb855fb7418196421f1ee32af03a91b763599 Binary files /dev/null and b/docs/img/fad2df1fa4371b39b3ea1032a8ad236c.png differ diff --git a/docs/img/fb0d67715160a5a049ca0b8e7d7af698.png b/docs/img/fb0d67715160a5a049ca0b8e7d7af698.png new file mode 100644 index 0000000000000000000000000000000000000000..827e16a712fe77d9996dcf100cc345171bebcdd2 Binary files /dev/null and b/docs/img/fb0d67715160a5a049ca0b8e7d7af698.png differ diff --git a/docs/img/fb8ded1bb07112b49dc42dff02fe01f7.png b/docs/img/fb8ded1bb07112b49dc42dff02fe01f7.png new file mode 100644 index 0000000000000000000000000000000000000000..42685867e0e965c1c9a5f7862ac06bc47561174f Binary files /dev/null and b/docs/img/fb8ded1bb07112b49dc42dff02fe01f7.png differ diff --git a/docs/img/fc09af9303f629aff49a9a4dc5327e65.png b/docs/img/fc09af9303f629aff49a9a4dc5327e65.png new file mode 100644 index 0000000000000000000000000000000000000000..117797d615a8eae14d26245a0c3d617d3be60540 Binary files /dev/null and b/docs/img/fc09af9303f629aff49a9a4dc5327e65.png differ diff --git a/docs/img/fc692dde7a0c9ce30f0036b1a05b2768.png b/docs/img/fc692dde7a0c9ce30f0036b1a05b2768.png new file mode 100644 index 0000000000000000000000000000000000000000..b37c819bbcaf382b3b38b76f192650936d2a7425 Binary files /dev/null and b/docs/img/fc692dde7a0c9ce30f0036b1a05b2768.png differ diff --git a/docs/img/fc80ee243381890526471d6fc360f7cf.png b/docs/img/fc80ee243381890526471d6fc360f7cf.png new file mode 100644 index 0000000000000000000000000000000000000000..4af65360d1df88921ee7e5d8caa3fb675ece0055 Binary files /dev/null and b/docs/img/fc80ee243381890526471d6fc360f7cf.png differ diff --git a/docs/img/fd0991d7941fed77c4d82bd219ec713b.png b/docs/img/fd0991d7941fed77c4d82bd219ec713b.png new file mode 100644 index 0000000000000000000000000000000000000000..832d0c0709e83125df05fae0015cf0bd792f4915 Binary files /dev/null and b/docs/img/fd0991d7941fed77c4d82bd219ec713b.png differ diff --git a/docs/img/fd15df8f9a5a46582845610e8b5881bb.png b/docs/img/fd15df8f9a5a46582845610e8b5881bb.png new file mode 100644 index 0000000000000000000000000000000000000000..ce37bda0b23aa910c951f86dbc4db8e0b3f27dc8 Binary files /dev/null and b/docs/img/fd15df8f9a5a46582845610e8b5881bb.png differ diff --git a/docs/img/fd1e35952a7538923376d54325798b24.png b/docs/img/fd1e35952a7538923376d54325798b24.png new file mode 100644 index 0000000000000000000000000000000000000000..d5a3143fdd44b781b907a99e64a353f8ac30d906 Binary files /dev/null and b/docs/img/fd1e35952a7538923376d54325798b24.png differ diff --git a/docs/img/fd24d5842b589870b2063edaca149511.png b/docs/img/fd24d5842b589870b2063edaca149511.png new file mode 100644 index 0000000000000000000000000000000000000000..d09aa966f780acc2e3bc40e504acd63725f72f7a Binary files /dev/null and b/docs/img/fd24d5842b589870b2063edaca149511.png differ diff --git a/docs/img/fd54213f0e98a4b2f6482ab98d497410.png b/docs/img/fd54213f0e98a4b2f6482ab98d497410.png new file mode 100644 index 0000000000000000000000000000000000000000..6bcd55962d4ecd643fd84be907bbc06b2e643093 Binary files /dev/null and b/docs/img/fd54213f0e98a4b2f6482ab98d497410.png differ diff --git a/docs/img/fd7124974fcca5463d2ce7385bfb700e.png b/docs/img/fd7124974fcca5463d2ce7385bfb700e.png new file mode 100644 index 0000000000000000000000000000000000000000..dc7be55b6c2bab3b3674273a7f42cb2bf9b4246f Binary files /dev/null and b/docs/img/fd7124974fcca5463d2ce7385bfb700e.png differ diff --git a/docs/img/fd79e7dae86040d6e1249793ae0b1502.png b/docs/img/fd79e7dae86040d6e1249793ae0b1502.png new file mode 100644 index 0000000000000000000000000000000000000000..6737bf27193ea50ef94f2a302eef7d48f133e605 Binary files /dev/null and b/docs/img/fd79e7dae86040d6e1249793ae0b1502.png differ diff --git a/docs/img/fe213f080418c1bd6d92faa7e49770d3.png b/docs/img/fe213f080418c1bd6d92faa7e49770d3.png new file mode 100644 index 0000000000000000000000000000000000000000..e55e664b31065692a4d0fd6be07f6c48c6250ce9 Binary files /dev/null and b/docs/img/fe213f080418c1bd6d92faa7e49770d3.png differ diff --git a/docs/img/fe601ff47f99f0fd5220742f61007450.png b/docs/img/fe601ff47f99f0fd5220742f61007450.png new file mode 100644 index 0000000000000000000000000000000000000000..53c10121e84c072e964d94702c83d4f9d9972fdb Binary files /dev/null and b/docs/img/fe601ff47f99f0fd5220742f61007450.png differ diff --git a/docs/img/fe7d77556848be98a93c7b6516b0e6f8.png b/docs/img/fe7d77556848be98a93c7b6516b0e6f8.png new file mode 100644 index 0000000000000000000000000000000000000000..ae8248f93e09655a412c3d77b2fa17b8d5e9cc2f Binary files /dev/null and b/docs/img/fe7d77556848be98a93c7b6516b0e6f8.png differ diff --git a/docs/img/fe827d4bc97b90c3a250af05fd988fc4.png b/docs/img/fe827d4bc97b90c3a250af05fd988fc4.png new file mode 100644 index 0000000000000000000000000000000000000000..9a378656b68d126a84c5e58a4583d92e0e9ea48a Binary files /dev/null and b/docs/img/fe827d4bc97b90c3a250af05fd988fc4.png differ diff --git a/docs/img/fee3cc5116f884089066af3908605cbe.png b/docs/img/fee3cc5116f884089066af3908605cbe.png new file mode 100644 index 0000000000000000000000000000000000000000..d8224ec40ea73af042268142723ee62fc76c4dbe Binary files /dev/null and b/docs/img/fee3cc5116f884089066af3908605cbe.png differ diff --git a/docs/img/fef11068ab5cc264b208a4bd3addb7fa.png b/docs/img/fef11068ab5cc264b208a4bd3addb7fa.png new file mode 100644 index 0000000000000000000000000000000000000000..7c260a6d968ee31bb616ca8bb04ee29f2d17dbb9 Binary files /dev/null and b/docs/img/fef11068ab5cc264b208a4bd3addb7fa.png differ diff --git a/docs/img/ff2558c68f4e646052a0c39a7d3f8710.png b/docs/img/ff2558c68f4e646052a0c39a7d3f8710.png new file mode 100644 index 0000000000000000000000000000000000000000..664d095bdbfecbb28746f7574b9df916a90631dc Binary files /dev/null and b/docs/img/ff2558c68f4e646052a0c39a7d3f8710.png differ diff --git a/docs/img/ff949c9ca6d0d99318f68a1784db7950.png b/docs/img/ff949c9ca6d0d99318f68a1784db7950.png new file mode 100644 index 0000000000000000000000000000000000000000..12bbe6fcfe2657ee19663fe324f344d622123c87 Binary files /dev/null and b/docs/img/ff949c9ca6d0d99318f68a1784db7950.png differ diff --git a/docs/img/logo-s.png b/docs/img/logo-s.png new file mode 100644 index 0000000000000000000000000000000000000000..0fcb701b78f7c3e8d3963c7f1d80aab429347f60 Binary files /dev/null and b/docs/img/logo-s.png differ diff --git a/docs/img/logo.png b/docs/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8ef04aca0f633c9a1c7075681ef1db4b8e03c7f9 Binary files /dev/null and b/docs/img/logo.png differ diff --git a/node_modules/.bin/cake b/node_modules/.bin/cake new file mode 120000 index 0000000000000000000000000000000000000000..d95f32af48adc98f911bba3e83f3724566fd35c9 --- /dev/null +++ b/node_modules/.bin/cake @@ -0,0 +1 @@ +../coffee-script/bin/cake \ No newline at end of file diff --git a/node_modules/.bin/coffee b/node_modules/.bin/coffee new file mode 120000 index 0000000000000000000000000000000000000000..b57f275d7de58767bfe8245846ac09dbc80a9173 --- /dev/null +++ b/node_modules/.bin/coffee @@ -0,0 +1 @@ +../coffee-script/bin/coffee \ No newline at end of file diff --git a/node_modules/.bin/esparse b/node_modules/.bin/esparse new file mode 120000 index 0000000000000000000000000000000000000000..7423b18b24efb09ee2916ad6db079b83ef0eb132 --- /dev/null +++ b/node_modules/.bin/esparse @@ -0,0 +1 @@ +../esprima/bin/esparse.js \ No newline at end of file diff --git a/node_modules/.bin/esvalidate b/node_modules/.bin/esvalidate new file mode 120000 index 0000000000000000000000000000000000000000..16069effbc99a3dfc83b6a7b8f04a2c18fb9861f --- /dev/null +++ b/node_modules/.bin/esvalidate @@ -0,0 +1 @@ +../esprima/bin/esvalidate.js \ No newline at end of file diff --git a/node_modules/.bin/js-yaml b/node_modules/.bin/js-yaml new file mode 120000 index 0000000000000000000000000000000000000000..9dbd010d470368b942148cb9ec3acf02d7aac993 --- /dev/null +++ b/node_modules/.bin/js-yaml @@ -0,0 +1 @@ +../js-yaml/bin/js-yaml.js \ No newline at end of file diff --git a/node_modules/.bin/markdown-toc b/node_modules/.bin/markdown-toc new file mode 120000 index 0000000000000000000000000000000000000000..d18b9c774e36bf8b1f17b7784d06d018f930ee53 --- /dev/null +++ b/node_modules/.bin/markdown-toc @@ -0,0 +1 @@ +../markdown-toc/cli.js \ No newline at end of file diff --git a/node_modules/.bin/remarkable b/node_modules/.bin/remarkable new file mode 120000 index 0000000000000000000000000000000000000000..29c2d736a85a68acd911b4c564ccf7f35f6b3365 --- /dev/null +++ b/node_modules/.bin/remarkable @@ -0,0 +1 @@ +../remarkable/bin/remarkable.js \ No newline at end of file diff --git a/node_modules/ansi-red/LICENSE b/node_modules/ansi-red/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..41283c9f71f85ee1686a2721160fde87677044f5 --- /dev/null +++ b/node_modules/ansi-red/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) <%= year() %>, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/ansi-red/index.js b/node_modules/ansi-red/index.js new file mode 100644 index 0000000000000000000000000000000000000000..00ea30283a8d04d3f3d0f51e031add4e975ea58b --- /dev/null +++ b/node_modules/ansi-red/index.js @@ -0,0 +1,14 @@ +/*! + * ansi-red + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +var wrap = require('ansi-wrap'); + +module.exports = function red(message) { + return wrap(31, 39, message); +}; diff --git a/node_modules/ansi-red/package.json b/node_modules/ansi-red/package.json new file mode 100644 index 0000000000000000000000000000000000000000..11d085a4be2ad4b59d9f0c66c871645ba59e936e --- /dev/null +++ b/node_modules/ansi-red/package.json @@ -0,0 +1,115 @@ +{ + "_args": [ + [ + { + "name": "ansi-red", + "raw": "ansi-red@^0.1.1", + "rawSpec": "^0.1.1", + "scope": null, + "spec": ">=0.1.1 <0.2.0", + "type": "range" + }, + "/Users/xxm/Documents/gitlab/codechina-docs/node_modules/gray-matter" + ] + ], + "_from": "ansi-red@>=0.1.1 <0.2.0", + "_id": "ansi-red@0.1.1", + "_inCache": true, + "_installable": true, + "_location": "/ansi-red", + "_nodeVersion": "0.12.0", + "_npmUser": { + "email": "github@sellside.com", + "name": "jonschlinkert" + }, + "_npmVersion": "2.10.0", + "_phantomChildren": {}, + "_requested": { + "name": "ansi-red", + "raw": "ansi-red@^0.1.1", + "rawSpec": "^0.1.1", + "scope": null, + "spec": ">=0.1.1 <0.2.0", + "type": "range" + }, + "_requiredBy": [ + "/gray-matter" + ], + "_resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "_shasum": "8c638f9d1080800a353c9c28c8a81ca4705d946c", + "_shrinkwrap": null, + "_spec": "ansi-red@^0.1.1", + "_where": "/Users/xxm/Documents/gitlab/codechina-docs/node_modules/gray-matter", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/ansi-red/issues" + }, + "dependencies": { + "ansi-wrap": "0.1.0" + }, + "description": "The color red, in ansi.", + "devDependencies": { + "mocha": "*" + }, + "directories": {}, + "dist": { + "shasum": "8c638f9d1080800a353c9c28c8a81ca4705d946c", + "tarball": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/ansi-red", + "keywords": [ + "red", + "256", + "ansi", + "cli", + "color", + "colors", + "colour", + "command", + "command-line", + "console", + "format", + "formatting", + "iterm", + "log", + "logging", + "rgb", + "shell", + "string", + "style", + "styles", + "styling", + "terminal", + "text", + "tty", + "xterm" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "email": "github@sellside.com", + "name": "jonschlinkert" + } + ], + "name": "ansi-red", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/ansi-red.git" + }, + "scripts": { + "test": "mocha" + }, + "version": "0.1.1" +} diff --git a/node_modules/ansi-red/readme.md b/node_modules/ansi-red/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..e09e77b3ec2fb5cd3deeb4590e788ad28639e236 --- /dev/null +++ b/node_modules/ansi-red/readme.md @@ -0,0 +1,74 @@ +# ansi-red [![NPM version](https://badge.fury.io/js/ansi-red.svg)](http://badge.fury.io/js/ansi-red) + +> The color red, in ansi. + +## Install + +Install with [npm](https://www.npmjs.com/) + +```sh +$ npm i ansi-red --save +``` + +## Usage + +```js +var red = require('ansi-red'); +``` + +## Related projects + +* [ansi-reset](https://github.com/jonschlinkert/ansi-reset) +* [ansi-bold](https://github.com/jonschlinkert/ansi-bold) +* [ansi-dim](https://github.com/jonschlinkert/ansi-dim) +* [ansi-italic](https://github.com/jonschlinkert/ansi-italic) +* [ansi-underline](https://github.com/jonschlinkert/ansi-underline) +* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse) +* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden) +* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough) +* [ansi-black](https://github.com/jonschlinkert/ansi-black) +* [ansi-red](https://github.com/jonschlinkert/ansi-red) +* [ansi-green](https://github.com/jonschlinkert/ansi-green) +* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow) +* [ansi-blue](https://github.com/jonschlinkert/ansi-blue) +* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta) +* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan) +* [ansi-white](https://github.com/jonschlinkert/ansi-white) +* [ansi-gray](https://github.com/jonschlinkert/ansi-gray) +* [ansi-grey](https://github.com/jonschlinkert/ansi-grey) +* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack) +* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred) +* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen) +* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow) +* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue) +* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta) +* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan) +* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite) + +## Running tests + +Install dev dependencies: + +```sh +$ npm i -d && npm test +``` + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-red/issues/new) + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2015 Jon Schlinkert +Released under the MIT license. + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._ \ No newline at end of file diff --git a/node_modules/ansi-wrap/LICENSE b/node_modules/ansi-wrap/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..65f90aca8c2fff1b890f31f571aa41ddfc8d9a10 --- /dev/null +++ b/node_modules/ansi-wrap/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/ansi-wrap/README.md b/node_modules/ansi-wrap/README.md new file mode 100644 index 0000000000000000000000000000000000000000..032c1e6b2e3dc9cd69564ac09daccf0970b929da --- /dev/null +++ b/node_modules/ansi-wrap/README.md @@ -0,0 +1,89 @@ +# ansi-wrap [![NPM version](https://badge.fury.io/js/ansi-wrap.svg)](http://badge.fury.io/js/ansi-wrap) + +> Create ansi colors by passing the open and close codes. + +## Install + +Install with [npm](https://www.npmjs.com/) + +```sh +$ npm i ansi-wrap --save +``` + +## Usage + +```js +var wrap = require('ansi-wrap'); +``` + +**Example** + +Pass codes for [ansi magenta background](https://github.com/jonschlinkert/ansi-bgmagenta): + +```js +console.log(wrap(45, 49, 'This is a message...')); +//=> '\u001b[45mfoo\u001b[49m' +``` + +Which prints out... + +[![screen shot 2015-05-21 at 8 28 32 pm](https://cloud.githubusercontent.com/assets/383994/7761769/12488afa-fff8-11e4-9cc1-71a8a6ec14a4.png)](https://www.npmjs.com/) + +## Related projects + +This is used in these projects: + +* [ansi-reset](https://github.com/jonschlinkert/ansi-reset) +* [ansi-bold](https://github.com/jonschlinkert/ansi-bold) +* [ansi-dim](https://github.com/jonschlinkert/ansi-dim) +* [ansi-italic](https://github.com/jonschlinkert/ansi-italic) +* [ansi-underline](https://github.com/jonschlinkert/ansi-underline) +* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse) +* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden) +* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough) +* [ansi-black](https://github.com/jonschlinkert/ansi-black) +* [ansi-red](https://github.com/jonschlinkert/ansi-red) +* [ansi-green](https://github.com/jonschlinkert/ansi-green) +* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow) +* [ansi-blue](https://github.com/jonschlinkert/ansi-blue) +* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta) +* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan) +* [ansi-white](https://github.com/jonschlinkert/ansi-white) +* [ansi-gray](https://github.com/jonschlinkert/ansi-gray) +* [ansi-grey](https://github.com/jonschlinkert/ansi-grey) +* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack) +* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred) +* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen) +* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow) +* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue) +* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta) +* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan) +* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite) + +## Running tests + +Install dev dependencies: + +```sh +$ npm i -d && npm test +``` + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-wrap/issues/new) + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2015 Jon Schlinkert +Released under the MIT license. + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._ \ No newline at end of file diff --git a/node_modules/ansi-wrap/index.js b/node_modules/ansi-wrap/index.js new file mode 100644 index 0000000000000000000000000000000000000000..ffc52d75cc2d41695520f51ce6c99b6906f1da67 --- /dev/null +++ b/node_modules/ansi-wrap/index.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function(a, b, msg) { + return '\u001b['+ a + 'm' + msg + '\u001b[' + b + 'm'; +}; diff --git a/node_modules/ansi-wrap/package.json b/node_modules/ansi-wrap/package.json new file mode 100644 index 0000000000000000000000000000000000000000..31adc316cc77b21f834efa59c4e06349b4b6d0cd --- /dev/null +++ b/node_modules/ansi-wrap/package.json @@ -0,0 +1,88 @@ +{ + "_args": [ + [ + { + "name": "ansi-wrap", + "raw": "ansi-wrap@0.1.0", + "rawSpec": "0.1.0", + "scope": null, + "spec": "0.1.0", + "type": "version" + }, + "/Users/xxm/Documents/gitlab/codechina-docs/node_modules/ansi-red" + ] + ], + "_from": "ansi-wrap@0.1.0", + "_id": "ansi-wrap@0.1.0", + "_inCache": true, + "_installable": true, + "_location": "/ansi-wrap", + "_nodeVersion": "0.12.0", + "_npmUser": { + "email": "github@sellside.com", + "name": "jonschlinkert" + }, + "_npmVersion": "2.5.1", + "_phantomChildren": {}, + "_requested": { + "name": "ansi-wrap", + "raw": "ansi-wrap@0.1.0", + "rawSpec": "0.1.0", + "scope": null, + "spec": "0.1.0", + "type": "version" + }, + "_requiredBy": [ + "/ansi-red" + ], + "_resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "_shasum": "a82250ddb0015e9a27ca82e82ea603bbfa45efaf", + "_shrinkwrap": null, + "_spec": "ansi-wrap@0.1.0", + "_where": "/Users/xxm/Documents/gitlab/codechina-docs/node_modules/ansi-red", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/ansi-wrap/issues" + }, + "dependencies": {}, + "description": "Create ansi colors by passing the open and close codes.", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "a82250ddb0015e9a27ca82e82ea603bbfa45efaf", + "tarball": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/ansi-wrap", + "keywords": [], + "license": { + "type": "MIT", + "url": "https://github.com/jonschlinkert/ansi-wrap/blob/master/LICENSE" + }, + "main": "index.js", + "maintainers": [ + { + "email": "github@sellside.com", + "name": "jonschlinkert" + } + ], + "name": "ansi-wrap", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/ansi-wrap.git" + }, + "scripts": { + "test": "mocha" + }, + "version": "0.1.0" +} diff --git a/node_modules/argparse/CHANGELOG.md b/node_modules/argparse/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..a43c628ccc2ecf2d41b29b14704f2caff4b7f91d --- /dev/null +++ b/node_modules/argparse/CHANGELOG.md @@ -0,0 +1,185 @@ +1.0.10 / 2018-02-15 +------------------ + +- Use .concat instead of + for arrays, #122. + + +1.0.9 / 2016-09-29 +------------------ + +- Rerelease after 1.0.8 - deps cleanup. + + +1.0.8 / 2016-09-29 +------------------ + +- Maintenance (deps bump, fix node 6.5+ tests, coverage report). + + +1.0.7 / 2016-03-17 +------------------ + +- Teach `addArgument` to accept string arg names. #97, @tomxtobin. + + +1.0.6 / 2016-02-06 +------------------ + +- Maintenance: moved to eslint & updated CS. + + +1.0.5 / 2016-02-05 +------------------ + +- Removed lodash dependency to significantly reduce install size. + Thanks to @mourner. + + +1.0.4 / 2016-01-17 +------------------ + +- Maintenance: lodash update to 4.0.0. + + +1.0.3 / 2015-10-27 +------------------ + +- Fix parse `=` in args: `--examplepath="C:\myfolder\env=x64"`. #84, @CatWithApple. + + +1.0.2 / 2015-03-22 +------------------ + +- Relaxed lodash version dependency. + + +1.0.1 / 2015-02-20 +------------------ + +- Changed dependencies to be compatible with ancient nodejs. + + +1.0.0 / 2015-02-19 +------------------ + +- Maintenance release. +- Replaced `underscore` with `lodash`. +- Bumped version to 1.0.0 to better reflect semver meaning. +- HISTORY.md -> CHANGELOG.md + + +0.1.16 / 2013-12-01 +------------------- + +- Maintenance release. Updated dependencies and docs. + + +0.1.15 / 2013-05-13 +------------------- + +- Fixed #55, @trebor89 + + +0.1.14 / 2013-05-12 +------------------- + +- Fixed #62, @maxtaco + + +0.1.13 / 2013-04-08 +------------------- + +- Added `.npmignore` to reduce package size + + +0.1.12 / 2013-02-10 +------------------- + +- Fixed conflictHandler (#46), @hpaulj + + +0.1.11 / 2013-02-07 +------------------- + +- Multiple bugfixes, @hpaulj +- Added 70+ tests (ported from python), @hpaulj +- Added conflictHandler, @applepicke +- Added fromfilePrefixChar, @hpaulj + + +0.1.10 / 2012-12-30 +------------------- + +- Added [mutual exclusion](http://docs.python.org/dev/library/argparse.html#mutual-exclusion) + support, thanks to @hpaulj +- Fixed options check for `storeConst` & `appendConst` actions, thanks to @hpaulj + + +0.1.9 / 2012-12-27 +------------------ + +- Fixed option dest interferens with other options (issue #23), thanks to @hpaulj +- Fixed default value behavior with `*` positionals, thanks to @hpaulj +- Improve `getDefault()` behavior, thanks to @hpaulj +- Imrove negative argument parsing, thanks to @hpaulj + + +0.1.8 / 2012-12-01 +------------------ + +- Fixed parser parents (issue #19), thanks to @hpaulj +- Fixed negative argument parse (issue #20), thanks to @hpaulj + + +0.1.7 / 2012-10-14 +------------------ + +- Fixed 'choices' argument parse (issue #16) +- Fixed stderr output (issue #15) + + +0.1.6 / 2012-09-09 +------------------ + +- Fixed check for conflict of options (thanks to @tomxtobin) + + +0.1.5 / 2012-09-03 +------------------ + +- Fix parser #setDefaults method (thanks to @tomxtobin) + + +0.1.4 / 2012-07-30 +------------------ + +- Fixed pseudo-argument support (thanks to @CGamesPlay) +- Fixed addHelp default (should be true), if not set (thanks to @benblank) + + +0.1.3 / 2012-06-27 +------------------ + +- Fixed formatter api name: Formatter -> HelpFormatter + + +0.1.2 / 2012-05-29 +------------------ + +- Added basic tests +- Removed excess whitespace in help +- Fixed error reporting, when parcer with subcommands + called with empty arguments + + +0.1.1 / 2012-05-23 +------------------ + +- Fixed line wrapping in help formatter +- Added better error reporting on invalid arguments + + +0.1.0 / 2012-05-16 +------------------ + +- First release. diff --git a/node_modules/argparse/LICENSE b/node_modules/argparse/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..1afdae5584056a7a33e9ebf747979baf6cac762a --- /dev/null +++ b/node_modules/argparse/LICENSE @@ -0,0 +1,21 @@ +(The MIT License) + +Copyright (C) 2012 by Vitaly Puzrin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/argparse/README.md b/node_modules/argparse/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7fa6c40503e56ad3afed1a26c2e8ee0b74f0eeef --- /dev/null +++ b/node_modules/argparse/README.md @@ -0,0 +1,257 @@ +argparse +======== + +[![Build Status](https://secure.travis-ci.org/nodeca/argparse.svg?branch=master)](http://travis-ci.org/nodeca/argparse) +[![NPM version](https://img.shields.io/npm/v/argparse.svg)](https://www.npmjs.org/package/argparse) + +CLI arguments parser for node.js. Javascript port of python's +[argparse](http://docs.python.org/dev/library/argparse.html) module +(original version 3.2). That's a full port, except some very rare options, +recorded in issue tracker. + +**NB. Difference with original.** + +- Method names changed to camelCase. See [generated docs](http://nodeca.github.com/argparse/). +- Use `defaultValue` instead of `default`. +- Use `argparse.Const.REMAINDER` instead of `argparse.REMAINDER`, and + similarly for constant values `OPTIONAL`, `ZERO_OR_MORE`, and `ONE_OR_MORE` + (aliases for `nargs` values `'?'`, `'*'`, `'+'`, respectively), and + `SUPPRESS`. + + +Example +======= + +test.js file: + +```javascript +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp:true, + description: 'Argparse example' +}); +parser.addArgument( + [ '-f', '--foo' ], + { + help: 'foo bar' + } +); +parser.addArgument( + [ '-b', '--bar' ], + { + help: 'bar foo' + } +); +parser.addArgument( + '--baz', + { + help: 'baz bar' + } +); +var args = parser.parseArgs(); +console.dir(args); +``` + +Display help: + +``` +$ ./test.js -h +usage: example.js [-h] [-v] [-f FOO] [-b BAR] [--baz BAZ] + +Argparse example + +Optional arguments: + -h, --help Show this help message and exit. + -v, --version Show program's version number and exit. + -f FOO, --foo FOO foo bar + -b BAR, --bar BAR bar foo + --baz BAZ baz bar +``` + +Parse arguments: + +``` +$ ./test.js -f=3 --bar=4 --baz 5 +{ foo: '3', bar: '4', baz: '5' } +``` + +More [examples](https://github.com/nodeca/argparse/tree/master/examples). + + +ArgumentParser objects +====================== + +``` +new ArgumentParser({parameters hash}); +``` + +Creates a new ArgumentParser object. + +**Supported params:** + +- ```description``` - Text to display before the argument help. +- ```epilog``` - Text to display after the argument help. +- ```addHelp``` - Add a -h/–help option to the parser. (default: true) +- ```argumentDefault``` - Set the global default value for arguments. (default: null) +- ```parents``` - A list of ArgumentParser objects whose arguments should also be included. +- ```prefixChars``` - The set of characters that prefix optional arguments. (default: ‘-‘) +- ```formatterClass``` - A class for customizing the help output. +- ```prog``` - The name of the program (default: `path.basename(process.argv[1])`) +- ```usage``` - The string describing the program usage (default: generated) +- ```conflictHandler``` - Usually unnecessary, defines strategy for resolving conflicting optionals. + +**Not supported yet** + +- ```fromfilePrefixChars``` - The set of characters that prefix files from which additional arguments should be read. + + +Details in [original ArgumentParser guide](http://docs.python.org/dev/library/argparse.html#argumentparser-objects) + + +addArgument() method +==================== + +``` +ArgumentParser.addArgument(name or flag or [name] or [flags...], {options}) +``` + +Defines how a single command-line argument should be parsed. + +- ```name or flag or [name] or [flags...]``` - Either a positional name + (e.g., `'foo'`), a single option (e.g., `'-f'` or `'--foo'`), an array + of a single positional name (e.g., `['foo']`), or an array of options + (e.g., `['-f', '--foo']`). + +Options: + +- ```action``` - The basic type of action to be taken when this argument is encountered at the command line. +- ```nargs```- The number of command-line arguments that should be consumed. +- ```constant``` - A constant value required by some action and nargs selections. +- ```defaultValue``` - The value produced if the argument is absent from the command line. +- ```type``` - The type to which the command-line argument should be converted. +- ```choices``` - A container of the allowable values for the argument. +- ```required``` - Whether or not the command-line option may be omitted (optionals only). +- ```help``` - A brief description of what the argument does. +- ```metavar``` - A name for the argument in usage messages. +- ```dest``` - The name of the attribute to be added to the object returned by parseArgs(). + +Details in [original add_argument guide](http://docs.python.org/dev/library/argparse.html#the-add-argument-method) + + +Action (some details) +================ + +ArgumentParser objects associate command-line arguments with actions. +These actions can do just about anything with the command-line arguments associated +with them, though most actions simply add an attribute to the object returned by +parseArgs(). The action keyword argument specifies how the command-line arguments +should be handled. The supported actions are: + +- ```store``` - Just stores the argument’s value. This is the default action. +- ```storeConst``` - Stores value, specified by the const keyword argument. + (Note that the const keyword argument defaults to the rather unhelpful None.) + The 'storeConst' action is most commonly used with optional arguments, that + specify some sort of flag. +- ```storeTrue``` and ```storeFalse``` - Stores values True and False + respectively. These are special cases of 'storeConst'. +- ```append``` - Stores a list, and appends each argument value to the list. + This is useful to allow an option to be specified multiple times. +- ```appendConst``` - Stores a list, and appends value, specified by the + const keyword argument to the list. (Note, that the const keyword argument defaults + is None.) The 'appendConst' action is typically used when multiple arguments need + to store constants to the same list. +- ```count``` - Counts the number of times a keyword argument occurs. For example, + used for increasing verbosity levels. +- ```help``` - Prints a complete help message for all the options in the current + parser and then exits. By default a help action is automatically added to the parser. + See ArgumentParser for details of how the output is created. +- ```version``` - Prints version information and exit. Expects a `version=` + keyword argument in the addArgument() call. + +Details in [original action guide](http://docs.python.org/dev/library/argparse.html#action) + + +Sub-commands +============ + +ArgumentParser.addSubparsers() + +Many programs split their functionality into a number of sub-commands, for +example, the svn program can invoke sub-commands like `svn checkout`, `svn update`, +and `svn commit`. Splitting up functionality this way can be a particularly good +idea when a program performs several different functions which require different +kinds of command-line arguments. `ArgumentParser` supports creation of such +sub-commands with `addSubparsers()` method. The `addSubparsers()` method is +normally called with no arguments and returns an special action object. +This object has a single method `addParser()`, which takes a command name and +any `ArgumentParser` constructor arguments, and returns an `ArgumentParser` object +that can be modified as usual. + +Example: + +sub_commands.js +```javascript +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp:true, + description: 'Argparse examples: sub-commands', +}); + +var subparsers = parser.addSubparsers({ + title:'subcommands', + dest:"subcommand_name" +}); + +var bar = subparsers.addParser('c1', {addHelp:true}); +bar.addArgument( + [ '-f', '--foo' ], + { + action: 'store', + help: 'foo3 bar3' + } +); +var bar = subparsers.addParser( + 'c2', + {aliases:['co'], addHelp:true} +); +bar.addArgument( + [ '-b', '--bar' ], + { + action: 'store', + type: 'int', + help: 'foo3 bar3' + } +); + +var args = parser.parseArgs(); +console.dir(args); + +``` + +Details in [original sub-commands guide](http://docs.python.org/dev/library/argparse.html#sub-commands) + + +Contributors +============ + +- [Eugene Shkuropat](https://github.com/shkuropat) +- [Paul Jacobson](https://github.com/hpaulj) + +[others](https://github.com/nodeca/argparse/graphs/contributors) + +License +======= + +Copyright (c) 2012 [Vitaly Puzrin](https://github.com/puzrin). +Released under the MIT license. See +[LICENSE](https://github.com/nodeca/argparse/blob/master/LICENSE) for details. + + diff --git a/node_modules/argparse/index.js b/node_modules/argparse/index.js new file mode 100644 index 0000000000000000000000000000000000000000..3bbc143200483c06ce8cdc5b8fef406bdabf2268 --- /dev/null +++ b/node_modules/argparse/index.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('./lib/argparse'); diff --git a/node_modules/argparse/lib/action.js b/node_modules/argparse/lib/action.js new file mode 100644 index 0000000000000000000000000000000000000000..1483c79ffa53d6537fbae068987e39a50e2cfa08 --- /dev/null +++ b/node_modules/argparse/lib/action.js @@ -0,0 +1,146 @@ +/** + * class Action + * + * Base class for all actions + * Do not call in your code, use this class only for inherits your own action + * + * Information about how to convert command line strings to Javascript objects. + * Action objects are used by an ArgumentParser to represent the information + * needed to parse a single argument from one or more strings from the command + * line. The keyword arguments to the Action constructor are also all attributes + * of Action instances. + * + * ##### Allowed keywords: + * + * - `store` + * - `storeConstant` + * - `storeTrue` + * - `storeFalse` + * - `append` + * - `appendConstant` + * - `count` + * - `help` + * - `version` + * + * Information about action options see [[Action.new]] + * + * See also [original guide](http://docs.python.org/dev/library/argparse.html#action) + * + **/ + +'use strict'; + + +// Constants +var c = require('./const'); + + +/** + * new Action(options) + * + * Base class for all actions. Used only for inherits + * + * + * ##### Options: + * + * - `optionStrings` A list of command-line option strings for the action. + * - `dest` Attribute to hold the created object(s) + * - `nargs` The number of command-line arguments that should be consumed. + * By default, one argument will be consumed and a single value will be + * produced. + * - `constant` Default value for an action with no value. + * - `defaultValue` The value to be produced if the option is not specified. + * - `type` Cast to 'string'|'int'|'float'|'complex'|function (string). If + * None, 'string'. + * - `choices` The choices available. + * - `required` True if the action must always be specified at the command + * line. + * - `help` The help describing the argument. + * - `metavar` The name to be used for the option's argument with the help + * string. If None, the 'dest' value will be used as the name. + * + * ##### nargs supported values: + * + * - `N` (an integer) consumes N arguments (and produces a list) + * - `?` consumes zero or one arguments + * - `*` consumes zero or more arguments (and produces a list) + * - `+` consumes one or more arguments (and produces a list) + * + * Note: that the difference between the default and nargs=1 is that with the + * default, a single value will be produced, while with nargs=1, a list + * containing a single value will be produced. + **/ +var Action = module.exports = function Action(options) { + options = options || {}; + this.optionStrings = options.optionStrings || []; + this.dest = options.dest; + this.nargs = typeof options.nargs !== 'undefined' ? options.nargs : null; + this.constant = typeof options.constant !== 'undefined' ? options.constant : null; + this.defaultValue = options.defaultValue; + this.type = typeof options.type !== 'undefined' ? options.type : null; + this.choices = typeof options.choices !== 'undefined' ? options.choices : null; + this.required = typeof options.required !== 'undefined' ? options.required : false; + this.help = typeof options.help !== 'undefined' ? options.help : null; + this.metavar = typeof options.metavar !== 'undefined' ? options.metavar : null; + + if (!(this.optionStrings instanceof Array)) { + throw new Error('optionStrings should be an array'); + } + if (typeof this.required !== 'undefined' && typeof this.required !== 'boolean') { + throw new Error('required should be a boolean'); + } +}; + +/** + * Action#getName -> String + * + * Tells action name + **/ +Action.prototype.getName = function () { + if (this.optionStrings.length > 0) { + return this.optionStrings.join('/'); + } else if (this.metavar !== null && this.metavar !== c.SUPPRESS) { + return this.metavar; + } else if (typeof this.dest !== 'undefined' && this.dest !== c.SUPPRESS) { + return this.dest; + } + return null; +}; + +/** + * Action#isOptional -> Boolean + * + * Return true if optional + **/ +Action.prototype.isOptional = function () { + return !this.isPositional(); +}; + +/** + * Action#isPositional -> Boolean + * + * Return true if positional + **/ +Action.prototype.isPositional = function () { + return (this.optionStrings.length === 0); +}; + +/** + * Action#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Should be implemented in inherited classes + * + * ##### Example + * + * ActionCount.prototype.call = function (parser, namespace, values, optionString) { + * namespace.set(this.dest, (namespace[this.dest] || 0) + 1); + * }; + * + **/ +Action.prototype.call = function () { + throw new Error('.call() not defined');// Not Implemented error +}; diff --git a/node_modules/argparse/lib/action/append.js b/node_modules/argparse/lib/action/append.js new file mode 100644 index 0000000000000000000000000000000000000000..b5da0de2327504e69266b713f07fd4cc3c83ecaa --- /dev/null +++ b/node_modules/argparse/lib/action/append.js @@ -0,0 +1,53 @@ +/*:nodoc:* + * class ActionAppend + * + * This action stores a list, and appends each argument value to the list. + * This is useful to allow an option to be specified multiple times. + * This class inherided from [[Action]] + * + **/ + +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +// Constants +var c = require('../const'); + +/*:nodoc:* + * new ActionAppend(options) + * - options (object): options hash see [[Action.new]] + * + * Note: options.nargs should be optional for constants + * and more then zero for other + **/ +var ActionAppend = module.exports = function ActionAppend(options) { + options = options || {}; + if (this.nargs <= 0) { + throw new Error('nargs for append actions must be > 0; if arg ' + + 'strings are not supplying the value to append, ' + + 'the append const action may be more appropriate'); + } + if (!!this.constant && this.nargs !== c.OPTIONAL) { + throw new Error('nargs must be OPTIONAL to supply const'); + } + Action.call(this, options); +}; +util.inherits(ActionAppend, Action); + +/*:nodoc:* + * ActionAppend#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionAppend.prototype.call = function (parser, namespace, values) { + var items = (namespace[this.dest] || []).slice(); + items.push(values); + namespace.set(this.dest, items); +}; diff --git a/node_modules/argparse/lib/action/append/constant.js b/node_modules/argparse/lib/action/append/constant.js new file mode 100644 index 0000000000000000000000000000000000000000..313f5d2efcb03fa8d62b5f9d79d0577bed0b6ea4 --- /dev/null +++ b/node_modules/argparse/lib/action/append/constant.js @@ -0,0 +1,47 @@ +/*:nodoc:* + * class ActionAppendConstant + * + * This stores a list, and appends the value specified by + * the const keyword argument to the list. + * (Note that the const keyword argument defaults to null.) + * The 'appendConst' action is typically useful when multiple + * arguments need to store constants to the same list. + * + * This class inherited from [[Action]] + **/ + +'use strict'; + +var util = require('util'); + +var Action = require('../../action'); + +/*:nodoc:* + * new ActionAppendConstant(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionAppendConstant = module.exports = function ActionAppendConstant(options) { + options = options || {}; + options.nargs = 0; + if (typeof options.constant === 'undefined') { + throw new Error('constant option is required for appendAction'); + } + Action.call(this, options); +}; +util.inherits(ActionAppendConstant, Action); + +/*:nodoc:* + * ActionAppendConstant#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionAppendConstant.prototype.call = function (parser, namespace) { + var items = [].concat(namespace[this.dest] || []); + items.push(this.constant); + namespace.set(this.dest, items); +}; diff --git a/node_modules/argparse/lib/action/count.js b/node_modules/argparse/lib/action/count.js new file mode 100644 index 0000000000000000000000000000000000000000..d6a5899d07ef2405d31777a2616bed14a0485d74 --- /dev/null +++ b/node_modules/argparse/lib/action/count.js @@ -0,0 +1,40 @@ +/*:nodoc:* + * class ActionCount + * + * This counts the number of times a keyword argument occurs. + * For example, this is useful for increasing verbosity levels + * + * This class inherided from [[Action]] + * + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +/*:nodoc:* + * new ActionCount(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionCount = module.exports = function ActionCount(options) { + options = options || {}; + options.nargs = 0; + + Action.call(this, options); +}; +util.inherits(ActionCount, Action); + +/*:nodoc:* + * ActionCount#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionCount.prototype.call = function (parser, namespace) { + namespace.set(this.dest, (namespace[this.dest] || 0) + 1); +}; diff --git a/node_modules/argparse/lib/action/help.js b/node_modules/argparse/lib/action/help.js new file mode 100644 index 0000000000000000000000000000000000000000..b40e05a6f0b3eb2382b7d7c78b67653a5be18ce5 --- /dev/null +++ b/node_modules/argparse/lib/action/help.js @@ -0,0 +1,47 @@ +/*:nodoc:* + * class ActionHelp + * + * Support action for printing help + * This class inherided from [[Action]] + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +// Constants +var c = require('../const'); + +/*:nodoc:* + * new ActionHelp(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionHelp = module.exports = function ActionHelp(options) { + options = options || {}; + if (options.defaultValue !== null) { + options.defaultValue = options.defaultValue; + } else { + options.defaultValue = c.SUPPRESS; + } + options.dest = (options.dest !== null ? options.dest : c.SUPPRESS); + options.nargs = 0; + Action.call(this, options); + +}; +util.inherits(ActionHelp, Action); + +/*:nodoc:* + * ActionHelp#call(parser, namespace, values, optionString) + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Print help and exit + **/ +ActionHelp.prototype.call = function (parser) { + parser.printHelp(); + parser.exit(); +}; diff --git a/node_modules/argparse/lib/action/store.js b/node_modules/argparse/lib/action/store.js new file mode 100644 index 0000000000000000000000000000000000000000..283b8609217561910aca7d0eb725a37b4966d314 --- /dev/null +++ b/node_modules/argparse/lib/action/store.js @@ -0,0 +1,50 @@ +/*:nodoc:* + * class ActionStore + * + * This action just stores the argument’s value. This is the default action. + * + * This class inherited from [[Action]] + * + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +// Constants +var c = require('../const'); + + +/*:nodoc:* + * new ActionStore(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionStore = module.exports = function ActionStore(options) { + options = options || {}; + if (this.nargs <= 0) { + throw new Error('nargs for store actions must be > 0; if you ' + + 'have nothing to store, actions such as store ' + + 'true or store const may be more appropriate'); + + } + if (typeof this.constant !== 'undefined' && this.nargs !== c.OPTIONAL) { + throw new Error('nargs must be OPTIONAL to supply const'); + } + Action.call(this, options); +}; +util.inherits(ActionStore, Action); + +/*:nodoc:* + * ActionStore#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionStore.prototype.call = function (parser, namespace, values) { + namespace.set(this.dest, values); +}; diff --git a/node_modules/argparse/lib/action/store/constant.js b/node_modules/argparse/lib/action/store/constant.js new file mode 100644 index 0000000000000000000000000000000000000000..23caa897b375d47cf8e07a6b2e80b92f867fc1c7 --- /dev/null +++ b/node_modules/argparse/lib/action/store/constant.js @@ -0,0 +1,43 @@ +/*:nodoc:* + * class ActionStoreConstant + * + * This action stores the value specified by the const keyword argument. + * (Note that the const keyword argument defaults to the rather unhelpful null.) + * The 'store_const' action is most commonly used with optional + * arguments that specify some sort of flag. + * + * This class inherited from [[Action]] + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../../action'); + +/*:nodoc:* + * new ActionStoreConstant(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionStoreConstant = module.exports = function ActionStoreConstant(options) { + options = options || {}; + options.nargs = 0; + if (typeof options.constant === 'undefined') { + throw new Error('constant option is required for storeAction'); + } + Action.call(this, options); +}; +util.inherits(ActionStoreConstant, Action); + +/*:nodoc:* + * ActionStoreConstant#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionStoreConstant.prototype.call = function (parser, namespace) { + namespace.set(this.dest, this.constant); +}; diff --git a/node_modules/argparse/lib/action/store/false.js b/node_modules/argparse/lib/action/store/false.js new file mode 100644 index 0000000000000000000000000000000000000000..9924f461dadfe687903a93825a59f819b01eb989 --- /dev/null +++ b/node_modules/argparse/lib/action/store/false.js @@ -0,0 +1,27 @@ +/*:nodoc:* + * class ActionStoreFalse + * + * This action store the values False respectively. + * This is special cases of 'storeConst' + * + * This class inherited from [[Action]] + **/ + +'use strict'; + +var util = require('util'); + +var ActionStoreConstant = require('./constant'); + +/*:nodoc:* + * new ActionStoreFalse(options) + * - options (object): hash of options see [[Action.new]] + * + **/ +var ActionStoreFalse = module.exports = function ActionStoreFalse(options) { + options = options || {}; + options.constant = false; + options.defaultValue = options.defaultValue !== null ? options.defaultValue : true; + ActionStoreConstant.call(this, options); +}; +util.inherits(ActionStoreFalse, ActionStoreConstant); diff --git a/node_modules/argparse/lib/action/store/true.js b/node_modules/argparse/lib/action/store/true.js new file mode 100644 index 0000000000000000000000000000000000000000..9e22f7d4419eeafd4c4ce2136aa492d781de2818 --- /dev/null +++ b/node_modules/argparse/lib/action/store/true.js @@ -0,0 +1,26 @@ +/*:nodoc:* + * class ActionStoreTrue + * + * This action store the values True respectively. + * This isspecial cases of 'storeConst' + * + * This class inherited from [[Action]] + **/ +'use strict'; + +var util = require('util'); + +var ActionStoreConstant = require('./constant'); + +/*:nodoc:* + * new ActionStoreTrue(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionStoreTrue = module.exports = function ActionStoreTrue(options) { + options = options || {}; + options.constant = true; + options.defaultValue = options.defaultValue !== null ? options.defaultValue : false; + ActionStoreConstant.call(this, options); +}; +util.inherits(ActionStoreTrue, ActionStoreConstant); diff --git a/node_modules/argparse/lib/action/subparsers.js b/node_modules/argparse/lib/action/subparsers.js new file mode 100644 index 0000000000000000000000000000000000000000..99dfedd0f1aa02e7a55cc9b75512e31f40f382d4 --- /dev/null +++ b/node_modules/argparse/lib/action/subparsers.js @@ -0,0 +1,149 @@ +/** internal + * class ActionSubparsers + * + * Support the creation of such sub-commands with the addSubparsers() + * + * This class inherited from [[Action]] + **/ +'use strict'; + +var util = require('util'); +var format = require('util').format; + + +var Action = require('../action'); + +// Constants +var c = require('../const'); + +// Errors +var argumentErrorHelper = require('../argument/error'); + + +/*:nodoc:* + * new ChoicesPseudoAction(name, help) + * + * Create pseudo action for correct help text + * + **/ +function ChoicesPseudoAction(name, help) { + var options = { + optionStrings: [], + dest: name, + help: help + }; + + Action.call(this, options); +} + +util.inherits(ChoicesPseudoAction, Action); + +/** + * new ActionSubparsers(options) + * - options (object): options hash see [[Action.new]] + * + **/ +function ActionSubparsers(options) { + options = options || {}; + options.dest = options.dest || c.SUPPRESS; + options.nargs = c.PARSER; + + this.debug = (options.debug === true); + + this._progPrefix = options.prog; + this._parserClass = options.parserClass; + this._nameParserMap = {}; + this._choicesActions = []; + + options.choices = this._nameParserMap; + Action.call(this, options); +} + +util.inherits(ActionSubparsers, Action); + +/*:nodoc:* + * ActionSubparsers#addParser(name, options) -> ArgumentParser + * - name (string): sub-command name + * - options (object): see [[ArgumentParser.new]] + * + * Note: + * addParser supports an additional aliases option, + * which allows multiple strings to refer to the same subparser. + * This example, like svn, aliases co as a shorthand for checkout + * + **/ +ActionSubparsers.prototype.addParser = function (name, options) { + var parser; + + var self = this; + + options = options || {}; + + options.debug = (this.debug === true); + + // set program from the existing prefix + if (!options.prog) { + options.prog = this._progPrefix + ' ' + name; + } + + var aliases = options.aliases || []; + + // create a pseudo-action to hold the choice help + if (!!options.help || typeof options.help === 'string') { + var help = options.help; + delete options.help; + + var choiceAction = new ChoicesPseudoAction(name, help); + this._choicesActions.push(choiceAction); + } + + // create the parser and add it to the map + parser = new this._parserClass(options); + this._nameParserMap[name] = parser; + + // make parser available under aliases also + aliases.forEach(function (alias) { + self._nameParserMap[alias] = parser; + }); + + return parser; +}; + +ActionSubparsers.prototype._getSubactions = function () { + return this._choicesActions; +}; + +/*:nodoc:* + * ActionSubparsers#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Parse input aguments + **/ +ActionSubparsers.prototype.call = function (parser, namespace, values) { + var parserName = values[0]; + var argStrings = values.slice(1); + + // set the parser name if requested + if (this.dest !== c.SUPPRESS) { + namespace[this.dest] = parserName; + } + + // select the parser + if (this._nameParserMap[parserName]) { + parser = this._nameParserMap[parserName]; + } else { + throw argumentErrorHelper(format( + 'Unknown parser "%s" (choices: [%s]).', + parserName, + Object.keys(this._nameParserMap).join(', ') + )); + } + + // parse all the remaining options into the namespace + parser.parseArgs(argStrings, namespace); +}; + +module.exports = ActionSubparsers; diff --git a/node_modules/argparse/lib/action/version.js b/node_modules/argparse/lib/action/version.js new file mode 100644 index 0000000000000000000000000000000000000000..8053328cdef44694a00f2cc31d72818d967ce4dc --- /dev/null +++ b/node_modules/argparse/lib/action/version.js @@ -0,0 +1,47 @@ +/*:nodoc:* + * class ActionVersion + * + * Support action for printing program version + * This class inherited from [[Action]] + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +// +// Constants +// +var c = require('../const'); + +/*:nodoc:* + * new ActionVersion(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionVersion = module.exports = function ActionVersion(options) { + options = options || {}; + options.defaultValue = (options.defaultValue ? options.defaultValue : c.SUPPRESS); + options.dest = (options.dest || c.SUPPRESS); + options.nargs = 0; + this.version = options.version; + Action.call(this, options); +}; +util.inherits(ActionVersion, Action); + +/*:nodoc:* + * ActionVersion#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Print version and exit + **/ +ActionVersion.prototype.call = function (parser) { + var version = this.version || parser.version; + var formatter = parser._getFormatter(); + formatter.addText(version); + parser.exit(0, formatter.formatHelp()); +}; diff --git a/node_modules/argparse/lib/action_container.js b/node_modules/argparse/lib/action_container.js new file mode 100644 index 0000000000000000000000000000000000000000..6f1237bea23d59b8cb1bb0d8778bcd1e0c1a2c39 --- /dev/null +++ b/node_modules/argparse/lib/action_container.js @@ -0,0 +1,482 @@ +/** internal + * class ActionContainer + * + * Action container. Parent for [[ArgumentParser]] and [[ArgumentGroup]] + **/ + +'use strict'; + +var format = require('util').format; + +// Constants +var c = require('./const'); + +var $$ = require('./utils'); + +//Actions +var ActionHelp = require('./action/help'); +var ActionAppend = require('./action/append'); +var ActionAppendConstant = require('./action/append/constant'); +var ActionCount = require('./action/count'); +var ActionStore = require('./action/store'); +var ActionStoreConstant = require('./action/store/constant'); +var ActionStoreTrue = require('./action/store/true'); +var ActionStoreFalse = require('./action/store/false'); +var ActionVersion = require('./action/version'); +var ActionSubparsers = require('./action/subparsers'); + +// Errors +var argumentErrorHelper = require('./argument/error'); + +/** + * new ActionContainer(options) + * + * Action container. Parent for [[ArgumentParser]] and [[ArgumentGroup]] + * + * ##### Options: + * + * - `description` -- A description of what the program does + * - `prefixChars` -- Characters that prefix optional arguments + * - `argumentDefault` -- The default value for all arguments + * - `conflictHandler` -- The conflict handler to use for duplicate arguments + **/ +var ActionContainer = module.exports = function ActionContainer(options) { + options = options || {}; + + this.description = options.description; + this.argumentDefault = options.argumentDefault; + this.prefixChars = options.prefixChars || ''; + this.conflictHandler = options.conflictHandler; + + // set up registries + this._registries = {}; + + // register actions + this.register('action', null, ActionStore); + this.register('action', 'store', ActionStore); + this.register('action', 'storeConst', ActionStoreConstant); + this.register('action', 'storeTrue', ActionStoreTrue); + this.register('action', 'storeFalse', ActionStoreFalse); + this.register('action', 'append', ActionAppend); + this.register('action', 'appendConst', ActionAppendConstant); + this.register('action', 'count', ActionCount); + this.register('action', 'help', ActionHelp); + this.register('action', 'version', ActionVersion); + this.register('action', 'parsers', ActionSubparsers); + + // raise an exception if the conflict handler is invalid + this._getHandler(); + + // action storage + this._actions = []; + this._optionStringActions = {}; + + // groups + this._actionGroups = []; + this._mutuallyExclusiveGroups = []; + + // defaults storage + this._defaults = {}; + + // determines whether an "option" looks like a negative number + // -1, -1.5 -5e+4 + this._regexpNegativeNumber = new RegExp('^[-]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$'); + + // whether or not there are any optionals that look like negative + // numbers -- uses a list so it can be shared and edited + this._hasNegativeNumberOptionals = []; +}; + +// Groups must be required, then ActionContainer already defined +var ArgumentGroup = require('./argument/group'); +var MutuallyExclusiveGroup = require('./argument/exclusive'); + +// +// Registration methods +// + +/** + * ActionContainer#register(registryName, value, object) -> Void + * - registryName (String) : object type action|type + * - value (string) : keyword + * - object (Object|Function) : handler + * + * Register handlers + **/ +ActionContainer.prototype.register = function (registryName, value, object) { + this._registries[registryName] = this._registries[registryName] || {}; + this._registries[registryName][value] = object; +}; + +ActionContainer.prototype._registryGet = function (registryName, value, defaultValue) { + if (arguments.length < 3) { + defaultValue = null; + } + return this._registries[registryName][value] || defaultValue; +}; + +// +// Namespace default accessor methods +// + +/** + * ActionContainer#setDefaults(options) -> Void + * - options (object):hash of options see [[Action.new]] + * + * Set defaults + **/ +ActionContainer.prototype.setDefaults = function (options) { + options = options || {}; + for (var property in options) { + if ($$.has(options, property)) { + this._defaults[property] = options[property]; + } + } + + // if these defaults match any existing arguments, replace the previous + // default on the object with the new one + this._actions.forEach(function (action) { + if ($$.has(options, action.dest)) { + action.defaultValue = options[action.dest]; + } + }); +}; + +/** + * ActionContainer#getDefault(dest) -> Mixed + * - dest (string): action destination + * + * Return action default value + **/ +ActionContainer.prototype.getDefault = function (dest) { + var result = $$.has(this._defaults, dest) ? this._defaults[dest] : null; + + this._actions.forEach(function (action) { + if (action.dest === dest && $$.has(action, 'defaultValue')) { + result = action.defaultValue; + } + }); + + return result; +}; +// +// Adding argument actions +// + +/** + * ActionContainer#addArgument(args, options) -> Object + * - args (String|Array): argument key, or array of argument keys + * - options (Object): action objects see [[Action.new]] + * + * #### Examples + * - addArgument([ '-f', '--foo' ], { action: 'store', defaultValue: 1, ... }) + * - addArgument([ 'bar' ], { action: 'store', nargs: 1, ... }) + * - addArgument('--baz', { action: 'store', nargs: 1, ... }) + **/ +ActionContainer.prototype.addArgument = function (args, options) { + args = args; + options = options || {}; + + if (typeof args === 'string') { + args = [ args ]; + } + if (!Array.isArray(args)) { + throw new TypeError('addArgument first argument should be a string or an array'); + } + if (typeof options !== 'object' || Array.isArray(options)) { + throw new TypeError('addArgument second argument should be a hash'); + } + + // if no positional args are supplied or only one is supplied and + // it doesn't look like an option string, parse a positional argument + if (!args || args.length === 1 && this.prefixChars.indexOf(args[0][0]) < 0) { + if (args && !!options.dest) { + throw new Error('dest supplied twice for positional argument'); + } + options = this._getPositional(args, options); + + // otherwise, we're adding an optional argument + } else { + options = this._getOptional(args, options); + } + + // if no default was supplied, use the parser-level default + if (typeof options.defaultValue === 'undefined') { + var dest = options.dest; + if ($$.has(this._defaults, dest)) { + options.defaultValue = this._defaults[dest]; + } else if (typeof this.argumentDefault !== 'undefined') { + options.defaultValue = this.argumentDefault; + } + } + + // create the action object, and add it to the parser + var ActionClass = this._popActionClass(options); + if (typeof ActionClass !== 'function') { + throw new Error(format('Unknown action "%s".', ActionClass)); + } + var action = new ActionClass(options); + + // throw an error if the action type is not callable + var typeFunction = this._registryGet('type', action.type, action.type); + if (typeof typeFunction !== 'function') { + throw new Error(format('"%s" is not callable', typeFunction)); + } + + return this._addAction(action); +}; + +/** + * ActionContainer#addArgumentGroup(options) -> ArgumentGroup + * - options (Object): hash of options see [[ArgumentGroup.new]] + * + * Create new arguments groups + **/ +ActionContainer.prototype.addArgumentGroup = function (options) { + var group = new ArgumentGroup(this, options); + this._actionGroups.push(group); + return group; +}; + +/** + * ActionContainer#addMutuallyExclusiveGroup(options) -> ArgumentGroup + * - options (Object): {required: false} + * + * Create new mutual exclusive groups + **/ +ActionContainer.prototype.addMutuallyExclusiveGroup = function (options) { + var group = new MutuallyExclusiveGroup(this, options); + this._mutuallyExclusiveGroups.push(group); + return group; +}; + +ActionContainer.prototype._addAction = function (action) { + var self = this; + + // resolve any conflicts + this._checkConflict(action); + + // add to actions list + this._actions.push(action); + action.container = this; + + // index the action by any option strings it has + action.optionStrings.forEach(function (optionString) { + self._optionStringActions[optionString] = action; + }); + + // set the flag if any option strings look like negative numbers + action.optionStrings.forEach(function (optionString) { + if (optionString.match(self._regexpNegativeNumber)) { + if (!self._hasNegativeNumberOptionals.some(Boolean)) { + self._hasNegativeNumberOptionals.push(true); + } + } + }); + + // return the created action + return action; +}; + +ActionContainer.prototype._removeAction = function (action) { + var actionIndex = this._actions.indexOf(action); + if (actionIndex >= 0) { + this._actions.splice(actionIndex, 1); + } +}; + +ActionContainer.prototype._addContainerActions = function (container) { + // collect groups by titles + var titleGroupMap = {}; + this._actionGroups.forEach(function (group) { + if (titleGroupMap[group.title]) { + throw new Error(format('Cannot merge actions - two groups are named "%s".', group.title)); + } + titleGroupMap[group.title] = group; + }); + + // map each action to its group + var groupMap = {}; + function actionHash(action) { + // unique (hopefully?) string suitable as dictionary key + return action.getName(); + } + container._actionGroups.forEach(function (group) { + // if a group with the title exists, use that, otherwise + // create a new group matching the container's group + if (!titleGroupMap[group.title]) { + titleGroupMap[group.title] = this.addArgumentGroup({ + title: group.title, + description: group.description + }); + } + + // map the actions to their new group + group._groupActions.forEach(function (action) { + groupMap[actionHash(action)] = titleGroupMap[group.title]; + }); + }, this); + + // add container's mutually exclusive groups + // NOTE: if add_mutually_exclusive_group ever gains title= and + // description= then this code will need to be expanded as above + var mutexGroup; + container._mutuallyExclusiveGroups.forEach(function (group) { + mutexGroup = this.addMutuallyExclusiveGroup({ + required: group.required + }); + // map the actions to their new mutex group + group._groupActions.forEach(function (action) { + groupMap[actionHash(action)] = mutexGroup; + }); + }, this); // forEach takes a 'this' argument + + // add all actions to this container or their group + container._actions.forEach(function (action) { + var key = actionHash(action); + if (groupMap[key]) { + groupMap[key]._addAction(action); + } else { + this._addAction(action); + } + }); +}; + +ActionContainer.prototype._getPositional = function (dest, options) { + if (Array.isArray(dest)) { + dest = dest[0]; + } + // make sure required is not specified + if (options.required) { + throw new Error('"required" is an invalid argument for positionals.'); + } + + // mark positional arguments as required if at least one is + // always required + if (options.nargs !== c.OPTIONAL && options.nargs !== c.ZERO_OR_MORE) { + options.required = true; + } + if (options.nargs === c.ZERO_OR_MORE && typeof options.defaultValue === 'undefined') { + options.required = true; + } + + // return the keyword arguments with no option strings + options.dest = dest; + options.optionStrings = []; + return options; +}; + +ActionContainer.prototype._getOptional = function (args, options) { + var prefixChars = this.prefixChars; + var optionStrings = []; + var optionStringsLong = []; + + // determine short and long option strings + args.forEach(function (optionString) { + // error on strings that don't start with an appropriate prefix + if (prefixChars.indexOf(optionString[0]) < 0) { + throw new Error(format('Invalid option string "%s": must start with a "%s".', + optionString, + prefixChars + )); + } + + // strings starting with two prefix characters are long options + optionStrings.push(optionString); + if (optionString.length > 1 && prefixChars.indexOf(optionString[1]) >= 0) { + optionStringsLong.push(optionString); + } + }); + + // infer dest, '--foo-bar' -> 'foo_bar' and '-x' -> 'x' + var dest = options.dest || null; + delete options.dest; + + if (!dest) { + var optionStringDest = optionStringsLong.length ? optionStringsLong[0] : optionStrings[0]; + dest = $$.trimChars(optionStringDest, this.prefixChars); + + if (dest.length === 0) { + throw new Error( + format('dest= is required for options like "%s"', optionStrings.join(', ')) + ); + } + dest = dest.replace(/-/g, '_'); + } + + // return the updated keyword arguments + options.dest = dest; + options.optionStrings = optionStrings; + + return options; +}; + +ActionContainer.prototype._popActionClass = function (options, defaultValue) { + defaultValue = defaultValue || null; + + var action = (options.action || defaultValue); + delete options.action; + + var actionClass = this._registryGet('action', action, action); + return actionClass; +}; + +ActionContainer.prototype._getHandler = function () { + var handlerString = this.conflictHandler; + var handlerFuncName = '_handleConflict' + $$.capitalize(handlerString); + var func = this[handlerFuncName]; + if (typeof func === 'undefined') { + var msg = 'invalid conflict resolution value: ' + handlerString; + throw new Error(msg); + } else { + return func; + } +}; + +ActionContainer.prototype._checkConflict = function (action) { + var optionStringActions = this._optionStringActions; + var conflictOptionals = []; + + // find all options that conflict with this option + // collect pairs, the string, and an existing action that it conflicts with + action.optionStrings.forEach(function (optionString) { + var conflOptional = optionStringActions[optionString]; + if (typeof conflOptional !== 'undefined') { + conflictOptionals.push([ optionString, conflOptional ]); + } + }); + + if (conflictOptionals.length > 0) { + var conflictHandler = this._getHandler(); + conflictHandler.call(this, action, conflictOptionals); + } +}; + +ActionContainer.prototype._handleConflictError = function (action, conflOptionals) { + var conflicts = conflOptionals.map(function (pair) { return pair[0]; }); + conflicts = conflicts.join(', '); + throw argumentErrorHelper( + action, + format('Conflicting option string(s): %s', conflicts) + ); +}; + +ActionContainer.prototype._handleConflictResolve = function (action, conflOptionals) { + // remove all conflicting options + var self = this; + conflOptionals.forEach(function (pair) { + var optionString = pair[0]; + var conflictingAction = pair[1]; + // remove the conflicting option string + var i = conflictingAction.optionStrings.indexOf(optionString); + if (i >= 0) { + conflictingAction.optionStrings.splice(i, 1); + } + delete self._optionStringActions[optionString]; + // if the option now has no option string, remove it from the + // container holding it + if (conflictingAction.optionStrings.length === 0) { + conflictingAction.container._removeAction(conflictingAction); + } + }); +}; diff --git a/node_modules/argparse/lib/argparse.js b/node_modules/argparse/lib/argparse.js new file mode 100644 index 0000000000000000000000000000000000000000..f2a2c51d9a8917bc2089cf662b84a1032ecd6ddd --- /dev/null +++ b/node_modules/argparse/lib/argparse.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports.ArgumentParser = require('./argument_parser.js'); +module.exports.Namespace = require('./namespace'); +module.exports.Action = require('./action'); +module.exports.HelpFormatter = require('./help/formatter.js'); +module.exports.Const = require('./const.js'); + +module.exports.ArgumentDefaultsHelpFormatter = + require('./help/added_formatters.js').ArgumentDefaultsHelpFormatter; +module.exports.RawDescriptionHelpFormatter = + require('./help/added_formatters.js').RawDescriptionHelpFormatter; +module.exports.RawTextHelpFormatter = + require('./help/added_formatters.js').RawTextHelpFormatter; diff --git a/node_modules/argparse/lib/argument/error.js b/node_modules/argparse/lib/argument/error.js new file mode 100644 index 0000000000000000000000000000000000000000..c8a02a08b8fbafb1c4f609f1f7195a84042e619a --- /dev/null +++ b/node_modules/argparse/lib/argument/error.js @@ -0,0 +1,50 @@ +'use strict'; + + +var format = require('util').format; + + +var ERR_CODE = 'ARGError'; + +/*:nodoc:* + * argumentError(argument, message) -> TypeError + * - argument (Object): action with broken argument + * - message (String): error message + * + * Error format helper. An error from creating or using an argument + * (optional or positional). The string value of this exception + * is the message, augmented with information + * about the argument that caused it. + * + * #####Example + * + * var argumentErrorHelper = require('./argument/error'); + * if (conflictOptionals.length > 0) { + * throw argumentErrorHelper( + * action, + * format('Conflicting option string(s): %s', conflictOptionals.join(', ')) + * ); + * } + * + **/ +module.exports = function (argument, message) { + var argumentName = null; + var errMessage; + var err; + + if (argument.getName) { + argumentName = argument.getName(); + } else { + argumentName = '' + argument; + } + + if (!argumentName) { + errMessage = message; + } else { + errMessage = format('argument "%s": %s', argumentName, message); + } + + err = new TypeError(errMessage); + err.code = ERR_CODE; + return err; +}; diff --git a/node_modules/argparse/lib/argument/exclusive.js b/node_modules/argparse/lib/argument/exclusive.js new file mode 100644 index 0000000000000000000000000000000000000000..8287e00d0464f37c2f5ab02e3750d56c3dc56ff3 --- /dev/null +++ b/node_modules/argparse/lib/argument/exclusive.js @@ -0,0 +1,54 @@ +/** internal + * class MutuallyExclusiveGroup + * + * Group arguments. + * By default, ArgumentParser groups command-line arguments + * into “positional arguments” and “optional arguments” + * when displaying help messages. When there is a better + * conceptual grouping of arguments than this default one, + * appropriate groups can be created using the addArgumentGroup() method + * + * This class inherited from [[ArgumentContainer]] + **/ +'use strict'; + +var util = require('util'); + +var ArgumentGroup = require('./group'); + +/** + * new MutuallyExclusiveGroup(container, options) + * - container (object): main container + * - options (object): options.required -> true/false + * + * `required` could be an argument itself, but making it a property of + * the options argument is more consistent with the JS adaptation of the Python) + **/ +var MutuallyExclusiveGroup = module.exports = function MutuallyExclusiveGroup(container, options) { + var required; + options = options || {}; + required = options.required || false; + ArgumentGroup.call(this, container); + this.required = required; + +}; +util.inherits(MutuallyExclusiveGroup, ArgumentGroup); + + +MutuallyExclusiveGroup.prototype._addAction = function (action) { + var msg; + if (action.required) { + msg = 'mutually exclusive arguments must be optional'; + throw new Error(msg); + } + action = this._container._addAction(action); + this._groupActions.push(action); + return action; +}; + + +MutuallyExclusiveGroup.prototype._removeAction = function (action) { + this._container._removeAction(action); + this._groupActions.remove(action); +}; + diff --git a/node_modules/argparse/lib/argument/group.js b/node_modules/argparse/lib/argument/group.js new file mode 100644 index 0000000000000000000000000000000000000000..58b271f2fec8d005065c9001c2fb65b960185fd0 --- /dev/null +++ b/node_modules/argparse/lib/argument/group.js @@ -0,0 +1,75 @@ +/** internal + * class ArgumentGroup + * + * Group arguments. + * By default, ArgumentParser groups command-line arguments + * into “positional arguments” and “optional arguments” + * when displaying help messages. When there is a better + * conceptual grouping of arguments than this default one, + * appropriate groups can be created using the addArgumentGroup() method + * + * This class inherited from [[ArgumentContainer]] + **/ +'use strict'; + +var util = require('util'); + +var ActionContainer = require('../action_container'); + + +/** + * new ArgumentGroup(container, options) + * - container (object): main container + * - options (object): hash of group options + * + * #### options + * - **prefixChars** group name prefix + * - **argumentDefault** default argument value + * - **title** group title + * - **description** group description + * + **/ +var ArgumentGroup = module.exports = function ArgumentGroup(container, options) { + + options = options || {}; + + // add any missing keyword arguments by checking the container + options.conflictHandler = (options.conflictHandler || container.conflictHandler); + options.prefixChars = (options.prefixChars || container.prefixChars); + options.argumentDefault = (options.argumentDefault || container.argumentDefault); + + ActionContainer.call(this, options); + + // group attributes + this.title = options.title; + this._groupActions = []; + + // share most attributes with the container + this._container = container; + this._registries = container._registries; + this._actions = container._actions; + this._optionStringActions = container._optionStringActions; + this._defaults = container._defaults; + this._hasNegativeNumberOptionals = container._hasNegativeNumberOptionals; + this._mutuallyExclusiveGroups = container._mutuallyExclusiveGroups; +}; +util.inherits(ArgumentGroup, ActionContainer); + + +ArgumentGroup.prototype._addAction = function (action) { + // Parent add action + action = ActionContainer.prototype._addAction.call(this, action); + this._groupActions.push(action); + return action; +}; + + +ArgumentGroup.prototype._removeAction = function (action) { + // Parent remove action + ActionContainer.prototype._removeAction.call(this, action); + var actionIndex = this._groupActions.indexOf(action); + if (actionIndex >= 0) { + this._groupActions.splice(actionIndex, 1); + } +}; + diff --git a/node_modules/argparse/lib/argument_parser.js b/node_modules/argparse/lib/argument_parser.js new file mode 100644 index 0000000000000000000000000000000000000000..bd9a59a453c946f47032be60f4b26ca0430fbe0f --- /dev/null +++ b/node_modules/argparse/lib/argument_parser.js @@ -0,0 +1,1161 @@ +/** + * class ArgumentParser + * + * Object for parsing command line strings into js objects. + * + * Inherited from [[ActionContainer]] + **/ +'use strict'; + +var util = require('util'); +var format = require('util').format; +var Path = require('path'); +var sprintf = require('sprintf-js').sprintf; + +// Constants +var c = require('./const'); + +var $$ = require('./utils'); + +var ActionContainer = require('./action_container'); + +// Errors +var argumentErrorHelper = require('./argument/error'); + +var HelpFormatter = require('./help/formatter'); + +var Namespace = require('./namespace'); + + +/** + * new ArgumentParser(options) + * + * Create a new ArgumentParser object. + * + * ##### Options: + * - `prog` The name of the program (default: Path.basename(process.argv[1])) + * - `usage` A usage message (default: auto-generated from arguments) + * - `description` A description of what the program does + * - `epilog` Text following the argument descriptions + * - `parents` Parsers whose arguments should be copied into this one + * - `formatterClass` HelpFormatter class for printing help messages + * - `prefixChars` Characters that prefix optional arguments + * - `fromfilePrefixChars` Characters that prefix files containing additional arguments + * - `argumentDefault` The default value for all arguments + * - `addHelp` Add a -h/-help option + * - `conflictHandler` Specifies how to handle conflicting argument names + * - `debug` Enable debug mode. Argument errors throw exception in + * debug mode and process.exit in normal. Used for development and + * testing (default: false) + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#argumentparser-objects + **/ +function ArgumentParser(options) { + if (!(this instanceof ArgumentParser)) { + return new ArgumentParser(options); + } + var self = this; + options = options || {}; + + options.description = (options.description || null); + options.argumentDefault = (options.argumentDefault || null); + options.prefixChars = (options.prefixChars || '-'); + options.conflictHandler = (options.conflictHandler || 'error'); + ActionContainer.call(this, options); + + options.addHelp = typeof options.addHelp === 'undefined' || !!options.addHelp; + options.parents = options.parents || []; + // default program name + options.prog = (options.prog || Path.basename(process.argv[1])); + this.prog = options.prog; + this.usage = options.usage; + this.epilog = options.epilog; + this.version = options.version; + + this.debug = (options.debug === true); + + this.formatterClass = (options.formatterClass || HelpFormatter); + this.fromfilePrefixChars = options.fromfilePrefixChars || null; + this._positionals = this.addArgumentGroup({ title: 'Positional arguments' }); + this._optionals = this.addArgumentGroup({ title: 'Optional arguments' }); + this._subparsers = null; + + // register types + function FUNCTION_IDENTITY(o) { + return o; + } + this.register('type', 'auto', FUNCTION_IDENTITY); + this.register('type', null, FUNCTION_IDENTITY); + this.register('type', 'int', function (x) { + var result = parseInt(x, 10); + if (isNaN(result)) { + throw new Error(x + ' is not a valid integer.'); + } + return result; + }); + this.register('type', 'float', function (x) { + var result = parseFloat(x); + if (isNaN(result)) { + throw new Error(x + ' is not a valid float.'); + } + return result; + }); + this.register('type', 'string', function (x) { + return '' + x; + }); + + // add help and version arguments if necessary + var defaultPrefix = (this.prefixChars.indexOf('-') > -1) ? '-' : this.prefixChars[0]; + if (options.addHelp) { + this.addArgument( + [ defaultPrefix + 'h', defaultPrefix + defaultPrefix + 'help' ], + { + action: 'help', + defaultValue: c.SUPPRESS, + help: 'Show this help message and exit.' + } + ); + } + if (typeof this.version !== 'undefined') { + this.addArgument( + [ defaultPrefix + 'v', defaultPrefix + defaultPrefix + 'version' ], + { + action: 'version', + version: this.version, + defaultValue: c.SUPPRESS, + help: "Show program's version number and exit." + } + ); + } + + // add parent arguments and defaults + options.parents.forEach(function (parent) { + self._addContainerActions(parent); + if (typeof parent._defaults !== 'undefined') { + for (var defaultKey in parent._defaults) { + if (parent._defaults.hasOwnProperty(defaultKey)) { + self._defaults[defaultKey] = parent._defaults[defaultKey]; + } + } + } + }); +} + +util.inherits(ArgumentParser, ActionContainer); + +/** + * ArgumentParser#addSubparsers(options) -> [[ActionSubparsers]] + * - options (object): hash of options see [[ActionSubparsers.new]] + * + * See also [subcommands][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#sub-commands + **/ +ArgumentParser.prototype.addSubparsers = function (options) { + if (this._subparsers) { + this.error('Cannot have multiple subparser arguments.'); + } + + options = options || {}; + options.debug = (this.debug === true); + options.optionStrings = []; + options.parserClass = (options.parserClass || ArgumentParser); + + + if (!!options.title || !!options.description) { + + this._subparsers = this.addArgumentGroup({ + title: (options.title || 'subcommands'), + description: options.description + }); + delete options.title; + delete options.description; + + } else { + this._subparsers = this._positionals; + } + + // prog defaults to the usage message of this parser, skipping + // optional arguments and with no "usage:" prefix + if (!options.prog) { + var formatter = this._getFormatter(); + var positionals = this._getPositionalActions(); + var groups = this._mutuallyExclusiveGroups; + formatter.addUsage(this.usage, positionals, groups, ''); + options.prog = formatter.formatHelp().trim(); + } + + // create the parsers action and add it to the positionals list + var ParsersClass = this._popActionClass(options, 'parsers'); + var action = new ParsersClass(options); + this._subparsers._addAction(action); + + // return the created parsers action + return action; +}; + +ArgumentParser.prototype._addAction = function (action) { + if (action.isOptional()) { + this._optionals._addAction(action); + } else { + this._positionals._addAction(action); + } + return action; +}; + +ArgumentParser.prototype._getOptionalActions = function () { + return this._actions.filter(function (action) { + return action.isOptional(); + }); +}; + +ArgumentParser.prototype._getPositionalActions = function () { + return this._actions.filter(function (action) { + return action.isPositional(); + }); +}; + + +/** + * ArgumentParser#parseArgs(args, namespace) -> Namespace|Object + * - args (array): input elements + * - namespace (Namespace|Object): result object + * + * Parsed args and throws error if some arguments are not recognized + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#the-parse-args-method + **/ +ArgumentParser.prototype.parseArgs = function (args, namespace) { + var argv; + var result = this.parseKnownArgs(args, namespace); + + args = result[0]; + argv = result[1]; + if (argv && argv.length > 0) { + this.error( + format('Unrecognized arguments: %s.', argv.join(' ')) + ); + } + return args; +}; + +/** + * ArgumentParser#parseKnownArgs(args, namespace) -> array + * - args (array): input options + * - namespace (Namespace|Object): result object + * + * Parse known arguments and return tuple of result object + * and unknown args + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#partial-parsing + **/ +ArgumentParser.prototype.parseKnownArgs = function (args, namespace) { + var self = this; + + // args default to the system args + args = args || process.argv.slice(2); + + // default Namespace built from parser defaults + namespace = namespace || new Namespace(); + + self._actions.forEach(function (action) { + if (action.dest !== c.SUPPRESS) { + if (!$$.has(namespace, action.dest)) { + if (action.defaultValue !== c.SUPPRESS) { + var defaultValue = action.defaultValue; + if (typeof action.defaultValue === 'string') { + defaultValue = self._getValue(action, defaultValue); + } + namespace[action.dest] = defaultValue; + } + } + } + }); + + Object.keys(self._defaults).forEach(function (dest) { + namespace[dest] = self._defaults[dest]; + }); + + // parse the arguments and exit if there are any errors + try { + var res = this._parseKnownArgs(args, namespace); + + namespace = res[0]; + args = res[1]; + if ($$.has(namespace, c._UNRECOGNIZED_ARGS_ATTR)) { + args = $$.arrayUnion(args, namespace[c._UNRECOGNIZED_ARGS_ATTR]); + delete namespace[c._UNRECOGNIZED_ARGS_ATTR]; + } + return [ namespace, args ]; + } catch (e) { + this.error(e); + } +}; + +ArgumentParser.prototype._parseKnownArgs = function (argStrings, namespace) { + var self = this; + + var extras = []; + + // replace arg strings that are file references + if (this.fromfilePrefixChars !== null) { + argStrings = this._readArgsFromFiles(argStrings); + } + // map all mutually exclusive arguments to the other arguments + // they can't occur with + // Python has 'conflicts = action_conflicts.setdefault(mutex_action, [])' + // though I can't conceive of a way in which an action could be a member + // of two different mutually exclusive groups. + + function actionHash(action) { + // some sort of hashable key for this action + // action itself cannot be a key in actionConflicts + // I think getName() (join of optionStrings) is unique enough + return action.getName(); + } + + var conflicts, key; + var actionConflicts = {}; + + this._mutuallyExclusiveGroups.forEach(function (mutexGroup) { + mutexGroup._groupActions.forEach(function (mutexAction, i, groupActions) { + key = actionHash(mutexAction); + if (!$$.has(actionConflicts, key)) { + actionConflicts[key] = []; + } + conflicts = actionConflicts[key]; + conflicts.push.apply(conflicts, groupActions.slice(0, i)); + conflicts.push.apply(conflicts, groupActions.slice(i + 1)); + }); + }); + + // find all option indices, and determine the arg_string_pattern + // which has an 'O' if there is an option at an index, + // an 'A' if there is an argument, or a '-' if there is a '--' + var optionStringIndices = {}; + + var argStringPatternParts = []; + + argStrings.forEach(function (argString, argStringIndex) { + if (argString === '--') { + argStringPatternParts.push('-'); + while (argStringIndex < argStrings.length) { + argStringPatternParts.push('A'); + argStringIndex++; + } + } else { + // otherwise, add the arg to the arg strings + // and note the index if it was an option + var pattern; + var optionTuple = self._parseOptional(argString); + if (!optionTuple) { + pattern = 'A'; + } else { + optionStringIndices[argStringIndex] = optionTuple; + pattern = 'O'; + } + argStringPatternParts.push(pattern); + } + }); + var argStringsPattern = argStringPatternParts.join(''); + + var seenActions = []; + var seenNonDefaultActions = []; + + + function takeAction(action, argumentStrings, optionString) { + seenActions.push(action); + var argumentValues = self._getValues(action, argumentStrings); + + // error if this argument is not allowed with other previously + // seen arguments, assuming that actions that use the default + // value don't really count as "present" + if (argumentValues !== action.defaultValue) { + seenNonDefaultActions.push(action); + if (actionConflicts[actionHash(action)]) { + actionConflicts[actionHash(action)].forEach(function (actionConflict) { + if (seenNonDefaultActions.indexOf(actionConflict) >= 0) { + throw argumentErrorHelper( + action, + format('Not allowed with argument "%s".', actionConflict.getName()) + ); + } + }); + } + } + + if (argumentValues !== c.SUPPRESS) { + action.call(self, namespace, argumentValues, optionString); + } + } + + function consumeOptional(startIndex) { + // get the optional identified at this index + var optionTuple = optionStringIndices[startIndex]; + var action = optionTuple[0]; + var optionString = optionTuple[1]; + var explicitArg = optionTuple[2]; + + // identify additional optionals in the same arg string + // (e.g. -xyz is the same as -x -y -z if no args are required) + var actionTuples = []; + + var args, argCount, start, stop; + + for (;;) { + if (!action) { + extras.push(argStrings[startIndex]); + return startIndex + 1; + } + if (explicitArg) { + argCount = self._matchArgument(action, 'A'); + + // if the action is a single-dash option and takes no + // arguments, try to parse more single-dash options out + // of the tail of the option string + var chars = self.prefixChars; + if (argCount === 0 && chars.indexOf(optionString[1]) < 0) { + actionTuples.push([ action, [], optionString ]); + optionString = optionString[0] + explicitArg[0]; + var newExplicitArg = explicitArg.slice(1) || null; + var optionalsMap = self._optionStringActions; + + if (Object.keys(optionalsMap).indexOf(optionString) >= 0) { + action = optionalsMap[optionString]; + explicitArg = newExplicitArg; + } else { + throw argumentErrorHelper(action, sprintf('ignored explicit argument %r', explicitArg)); + } + } else if (argCount === 1) { + // if the action expect exactly one argument, we've + // successfully matched the option; exit the loop + stop = startIndex + 1; + args = [ explicitArg ]; + actionTuples.push([ action, args, optionString ]); + break; + } else { + // error if a double-dash option did not use the + // explicit argument + throw argumentErrorHelper(action, sprintf('ignored explicit argument %r', explicitArg)); + } + } else { + // if there is no explicit argument, try to match the + // optional's string arguments with the following strings + // if successful, exit the loop + + start = startIndex + 1; + var selectedPatterns = argStringsPattern.substr(start); + + argCount = self._matchArgument(action, selectedPatterns); + stop = start + argCount; + + + args = argStrings.slice(start, stop); + + actionTuples.push([ action, args, optionString ]); + break; + } + + } + + // add the Optional to the list and return the index at which + // the Optional's string args stopped + if (actionTuples.length < 1) { + throw new Error('length should be > 0'); + } + for (var i = 0; i < actionTuples.length; i++) { + takeAction.apply(self, actionTuples[i]); + } + return stop; + } + + // the list of Positionals left to be parsed; this is modified + // by consume_positionals() + var positionals = self._getPositionalActions(); + + function consumePositionals(startIndex) { + // match as many Positionals as possible + var selectedPattern = argStringsPattern.substr(startIndex); + var argCounts = self._matchArgumentsPartial(positionals, selectedPattern); + + // slice off the appropriate arg strings for each Positional + // and add the Positional and its args to the list + for (var i = 0; i < positionals.length; i++) { + var action = positionals[i]; + var argCount = argCounts[i]; + if (typeof argCount === 'undefined') { + continue; + } + var args = argStrings.slice(startIndex, startIndex + argCount); + + startIndex += argCount; + takeAction(action, args); + } + + // slice off the Positionals that we just parsed and return the + // index at which the Positionals' string args stopped + positionals = positionals.slice(argCounts.length); + return startIndex; + } + + // consume Positionals and Optionals alternately, until we have + // passed the last option string + var startIndex = 0; + var position; + + var maxOptionStringIndex = -1; + + Object.keys(optionStringIndices).forEach(function (position) { + maxOptionStringIndex = Math.max(maxOptionStringIndex, parseInt(position, 10)); + }); + + var positionalsEndIndex, nextOptionStringIndex; + + while (startIndex <= maxOptionStringIndex) { + // consume any Positionals preceding the next option + nextOptionStringIndex = null; + for (position in optionStringIndices) { + if (!optionStringIndices.hasOwnProperty(position)) { continue; } + + position = parseInt(position, 10); + if (position >= startIndex) { + if (nextOptionStringIndex !== null) { + nextOptionStringIndex = Math.min(nextOptionStringIndex, position); + } else { + nextOptionStringIndex = position; + } + } + } + + if (startIndex !== nextOptionStringIndex) { + positionalsEndIndex = consumePositionals(startIndex); + // only try to parse the next optional if we didn't consume + // the option string during the positionals parsing + if (positionalsEndIndex > startIndex) { + startIndex = positionalsEndIndex; + continue; + } else { + startIndex = positionalsEndIndex; + } + } + + // if we consumed all the positionals we could and we're not + // at the index of an option string, there were extra arguments + if (!optionStringIndices[startIndex]) { + var strings = argStrings.slice(startIndex, nextOptionStringIndex); + extras = extras.concat(strings); + startIndex = nextOptionStringIndex; + } + // consume the next optional and any arguments for it + startIndex = consumeOptional(startIndex); + } + + // consume any positionals following the last Optional + var stopIndex = consumePositionals(startIndex); + + // if we didn't consume all the argument strings, there were extras + extras = extras.concat(argStrings.slice(stopIndex)); + + // if we didn't use all the Positional objects, there were too few + // arg strings supplied. + if (positionals.length > 0) { + self.error('too few arguments'); + } + + // make sure all required actions were present + self._actions.forEach(function (action) { + if (action.required) { + if (seenActions.indexOf(action) < 0) { + self.error(format('Argument "%s" is required', action.getName())); + } + } + }); + + // make sure all required groups have one option present + var actionUsed = false; + self._mutuallyExclusiveGroups.forEach(function (group) { + if (group.required) { + actionUsed = group._groupActions.some(function (action) { + return seenNonDefaultActions.indexOf(action) !== -1; + }); + + // if no actions were used, report the error + if (!actionUsed) { + var names = []; + group._groupActions.forEach(function (action) { + if (action.help !== c.SUPPRESS) { + names.push(action.getName()); + } + }); + names = names.join(' '); + var msg = 'one of the arguments ' + names + ' is required'; + self.error(msg); + } + } + }); + + // return the updated namespace and the extra arguments + return [ namespace, extras ]; +}; + +ArgumentParser.prototype._readArgsFromFiles = function (argStrings) { + // expand arguments referencing files + var self = this; + var fs = require('fs'); + var newArgStrings = []; + argStrings.forEach(function (argString) { + if (self.fromfilePrefixChars.indexOf(argString[0]) < 0) { + // for regular arguments, just add them back into the list + newArgStrings.push(argString); + } else { + // replace arguments referencing files with the file content + try { + var argstrs = []; + var filename = argString.slice(1); + var content = fs.readFileSync(filename, 'utf8'); + content = content.trim().split('\n'); + content.forEach(function (argLine) { + self.convertArgLineToArgs(argLine).forEach(function (arg) { + argstrs.push(arg); + }); + argstrs = self._readArgsFromFiles(argstrs); + }); + newArgStrings.push.apply(newArgStrings, argstrs); + } catch (error) { + return self.error(error.message); + } + } + }); + return newArgStrings; +}; + +ArgumentParser.prototype.convertArgLineToArgs = function (argLine) { + return [ argLine ]; +}; + +ArgumentParser.prototype._matchArgument = function (action, regexpArgStrings) { + + // match the pattern for this action to the arg strings + var regexpNargs = new RegExp('^' + this._getNargsPattern(action)); + var matches = regexpArgStrings.match(regexpNargs); + var message; + + // throw an exception if we weren't able to find a match + if (!matches) { + switch (action.nargs) { + /*eslint-disable no-undefined*/ + case undefined: + case null: + message = 'Expected one argument.'; + break; + case c.OPTIONAL: + message = 'Expected at most one argument.'; + break; + case c.ONE_OR_MORE: + message = 'Expected at least one argument.'; + break; + default: + message = 'Expected %s argument(s)'; + } + + throw argumentErrorHelper( + action, + format(message, action.nargs) + ); + } + // return the number of arguments matched + return matches[1].length; +}; + +ArgumentParser.prototype._matchArgumentsPartial = function (actions, regexpArgStrings) { + // progressively shorten the actions list by slicing off the + // final actions until we find a match + var self = this; + var result = []; + var actionSlice, pattern, matches; + var i, j; + + function getLength(string) { + return string.length; + } + + for (i = actions.length; i > 0; i--) { + pattern = ''; + actionSlice = actions.slice(0, i); + for (j = 0; j < actionSlice.length; j++) { + pattern += self._getNargsPattern(actionSlice[j]); + } + + pattern = new RegExp('^' + pattern); + matches = regexpArgStrings.match(pattern); + + if (matches && matches.length > 0) { + // need only groups + matches = matches.splice(1); + result = result.concat(matches.map(getLength)); + break; + } + } + + // return the list of arg string counts + return result; +}; + +ArgumentParser.prototype._parseOptional = function (argString) { + var action, optionString, argExplicit, optionTuples; + + // if it's an empty string, it was meant to be a positional + if (!argString) { + return null; + } + + // if it doesn't start with a prefix, it was meant to be positional + if (this.prefixChars.indexOf(argString[0]) < 0) { + return null; + } + + // if the option string is present in the parser, return the action + if (this._optionStringActions[argString]) { + return [ this._optionStringActions[argString], argString, null ]; + } + + // if it's just a single character, it was meant to be positional + if (argString.length === 1) { + return null; + } + + // if the option string before the "=" is present, return the action + if (argString.indexOf('=') >= 0) { + optionString = argString.split('=', 1)[0]; + argExplicit = argString.slice(optionString.length + 1); + + if (this._optionStringActions[optionString]) { + action = this._optionStringActions[optionString]; + return [ action, optionString, argExplicit ]; + } + } + + // search through all possible prefixes of the option string + // and all actions in the parser for possible interpretations + optionTuples = this._getOptionTuples(argString); + + // if multiple actions match, the option string was ambiguous + if (optionTuples.length > 1) { + var optionStrings = optionTuples.map(function (optionTuple) { + return optionTuple[1]; + }); + this.error(format( + 'Ambiguous option: "%s" could match %s.', + argString, optionStrings.join(', ') + )); + // if exactly one action matched, this segmentation is good, + // so return the parsed action + } else if (optionTuples.length === 1) { + return optionTuples[0]; + } + + // if it was not found as an option, but it looks like a negative + // number, it was meant to be positional + // unless there are negative-number-like options + if (argString.match(this._regexpNegativeNumber)) { + if (!this._hasNegativeNumberOptionals.some(Boolean)) { + return null; + } + } + // if it contains a space, it was meant to be a positional + if (argString.search(' ') >= 0) { + return null; + } + + // it was meant to be an optional but there is no such option + // in this parser (though it might be a valid option in a subparser) + return [ null, argString, null ]; +}; + +ArgumentParser.prototype._getOptionTuples = function (optionString) { + var result = []; + var chars = this.prefixChars; + var optionPrefix; + var argExplicit; + var action; + var actionOptionString; + + // option strings starting with two prefix characters are only split at + // the '=' + if (chars.indexOf(optionString[0]) >= 0 && chars.indexOf(optionString[1]) >= 0) { + if (optionString.indexOf('=') >= 0) { + var optionStringSplit = optionString.split('=', 1); + + optionPrefix = optionStringSplit[0]; + argExplicit = optionStringSplit[1]; + } else { + optionPrefix = optionString; + argExplicit = null; + } + + for (actionOptionString in this._optionStringActions) { + if (actionOptionString.substr(0, optionPrefix.length) === optionPrefix) { + action = this._optionStringActions[actionOptionString]; + result.push([ action, actionOptionString, argExplicit ]); + } + } + + // single character options can be concatenated with their arguments + // but multiple character options always have to have their argument + // separate + } else if (chars.indexOf(optionString[0]) >= 0 && chars.indexOf(optionString[1]) < 0) { + optionPrefix = optionString; + argExplicit = null; + var optionPrefixShort = optionString.substr(0, 2); + var argExplicitShort = optionString.substr(2); + + for (actionOptionString in this._optionStringActions) { + if (!$$.has(this._optionStringActions, actionOptionString)) continue; + + action = this._optionStringActions[actionOptionString]; + if (actionOptionString === optionPrefixShort) { + result.push([ action, actionOptionString, argExplicitShort ]); + } else if (actionOptionString.substr(0, optionPrefix.length) === optionPrefix) { + result.push([ action, actionOptionString, argExplicit ]); + } + } + + // shouldn't ever get here + } else { + throw new Error(format('Unexpected option string: %s.', optionString)); + } + // return the collected option tuples + return result; +}; + +ArgumentParser.prototype._getNargsPattern = function (action) { + // in all examples below, we have to allow for '--' args + // which are represented as '-' in the pattern + var regexpNargs; + + switch (action.nargs) { + // the default (null) is assumed to be a single argument + case undefined: + case null: + regexpNargs = '(-*A-*)'; + break; + // allow zero or more arguments + case c.OPTIONAL: + regexpNargs = '(-*A?-*)'; + break; + // allow zero or more arguments + case c.ZERO_OR_MORE: + regexpNargs = '(-*[A-]*)'; + break; + // allow one or more arguments + case c.ONE_OR_MORE: + regexpNargs = '(-*A[A-]*)'; + break; + // allow any number of options or arguments + case c.REMAINDER: + regexpNargs = '([-AO]*)'; + break; + // allow one argument followed by any number of options or arguments + case c.PARSER: + regexpNargs = '(-*A[-AO]*)'; + break; + // all others should be integers + default: + regexpNargs = '(-*' + $$.repeat('-*A', action.nargs) + '-*)'; + } + + // if this is an optional action, -- is not allowed + if (action.isOptional()) { + regexpNargs = regexpNargs.replace(/-\*/g, ''); + regexpNargs = regexpNargs.replace(/-/g, ''); + } + + // return the pattern + return regexpNargs; +}; + +// +// Value conversion methods +// + +ArgumentParser.prototype._getValues = function (action, argStrings) { + var self = this; + + // for everything but PARSER args, strip out '--' + if (action.nargs !== c.PARSER && action.nargs !== c.REMAINDER) { + argStrings = argStrings.filter(function (arrayElement) { + return arrayElement !== '--'; + }); + } + + var value, argString; + + // optional argument produces a default when not present + if (argStrings.length === 0 && action.nargs === c.OPTIONAL) { + + value = (action.isOptional()) ? action.constant : action.defaultValue; + + if (typeof (value) === 'string') { + value = this._getValue(action, value); + this._checkValue(action, value); + } + + // when nargs='*' on a positional, if there were no command-line + // args, use the default if it is anything other than None + } else if (argStrings.length === 0 && action.nargs === c.ZERO_OR_MORE && + action.optionStrings.length === 0) { + + value = (action.defaultValue || argStrings); + this._checkValue(action, value); + + // single argument or optional argument produces a single value + } else if (argStrings.length === 1 && + (!action.nargs || action.nargs === c.OPTIONAL)) { + + argString = argStrings[0]; + value = this._getValue(action, argString); + this._checkValue(action, value); + + // REMAINDER arguments convert all values, checking none + } else if (action.nargs === c.REMAINDER) { + value = argStrings.map(function (v) { + return self._getValue(action, v); + }); + + // PARSER arguments convert all values, but check only the first + } else if (action.nargs === c.PARSER) { + value = argStrings.map(function (v) { + return self._getValue(action, v); + }); + this._checkValue(action, value[0]); + + // all other types of nargs produce a list + } else { + value = argStrings.map(function (v) { + return self._getValue(action, v); + }); + value.forEach(function (v) { + self._checkValue(action, v); + }); + } + + // return the converted value + return value; +}; + +ArgumentParser.prototype._getValue = function (action, argString) { + var result; + + var typeFunction = this._registryGet('type', action.type, action.type); + if (typeof typeFunction !== 'function') { + var message = format('%s is not callable', typeFunction); + throw argumentErrorHelper(action, message); + } + + // convert the value to the appropriate type + try { + result = typeFunction(argString); + + // ArgumentTypeErrors indicate errors + // If action.type is not a registered string, it is a function + // Try to deduce its name for inclusion in the error message + // Failing that, include the error message it raised. + } catch (e) { + var name = null; + if (typeof action.type === 'string') { + name = action.type; + } else { + name = action.type.name || action.type.displayName || ''; + } + var msg = format('Invalid %s value: %s', name, argString); + if (name === '') { msg += '\n' + e.message; } + throw argumentErrorHelper(action, msg); + } + // return the converted value + return result; +}; + +ArgumentParser.prototype._checkValue = function (action, value) { + // converted value must be one of the choices (if specified) + var choices = action.choices; + if (choices) { + // choise for argument can by array or string + if ((typeof choices === 'string' || Array.isArray(choices)) && + choices.indexOf(value) !== -1) { + return; + } + // choise for subparsers can by only hash + if (typeof choices === 'object' && !Array.isArray(choices) && choices[value]) { + return; + } + + if (typeof choices === 'string') { + choices = choices.split('').join(', '); + } else if (Array.isArray(choices)) { + choices = choices.join(', '); + } else { + choices = Object.keys(choices).join(', '); + } + var message = format('Invalid choice: %s (choose from [%s])', value, choices); + throw argumentErrorHelper(action, message); + } +}; + +// +// Help formatting methods +// + +/** + * ArgumentParser#formatUsage -> string + * + * Return usage string + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#printing-help + **/ +ArgumentParser.prototype.formatUsage = function () { + var formatter = this._getFormatter(); + formatter.addUsage(this.usage, this._actions, this._mutuallyExclusiveGroups); + return formatter.formatHelp(); +}; + +/** + * ArgumentParser#formatHelp -> string + * + * Return help + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#printing-help + **/ +ArgumentParser.prototype.formatHelp = function () { + var formatter = this._getFormatter(); + + // usage + formatter.addUsage(this.usage, this._actions, this._mutuallyExclusiveGroups); + + // description + formatter.addText(this.description); + + // positionals, optionals and user-defined groups + this._actionGroups.forEach(function (actionGroup) { + formatter.startSection(actionGroup.title); + formatter.addText(actionGroup.description); + formatter.addArguments(actionGroup._groupActions); + formatter.endSection(); + }); + + // epilog + formatter.addText(this.epilog); + + // determine help from format above + return formatter.formatHelp(); +}; + +ArgumentParser.prototype._getFormatter = function () { + var FormatterClass = this.formatterClass; + var formatter = new FormatterClass({ prog: this.prog }); + return formatter; +}; + +// +// Print functions +// + +/** + * ArgumentParser#printUsage() -> Void + * + * Print usage + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#printing-help + **/ +ArgumentParser.prototype.printUsage = function () { + this._printMessage(this.formatUsage()); +}; + +/** + * ArgumentParser#printHelp() -> Void + * + * Print help + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#printing-help + **/ +ArgumentParser.prototype.printHelp = function () { + this._printMessage(this.formatHelp()); +}; + +ArgumentParser.prototype._printMessage = function (message, stream) { + if (!stream) { + stream = process.stdout; + } + if (message) { + stream.write('' + message); + } +}; + +// +// Exit functions +// + +/** + * ArgumentParser#exit(status=0, message) -> Void + * - status (int): exit status + * - message (string): message + * + * Print message in stderr/stdout and exit program + **/ +ArgumentParser.prototype.exit = function (status, message) { + if (message) { + if (status === 0) { + this._printMessage(message); + } else { + this._printMessage(message, process.stderr); + } + } + + process.exit(status); +}; + +/** + * ArgumentParser#error(message) -> Void + * - err (Error|string): message + * + * Error method Prints a usage message incorporating the message to stderr and + * exits. If you override this in a subclass, + * it should not return -- it should + * either exit or throw an exception. + * + **/ +ArgumentParser.prototype.error = function (err) { + var message; + if (err instanceof Error) { + if (this.debug === true) { + throw err; + } + message = err.message; + } else { + message = err; + } + var msg = format('%s: error: %s', this.prog, message) + c.EOL; + + if (this.debug === true) { + throw new Error(msg); + } + + this.printUsage(process.stderr); + + return this.exit(2, msg); +}; + +module.exports = ArgumentParser; diff --git a/node_modules/argparse/lib/const.js b/node_modules/argparse/lib/const.js new file mode 100644 index 0000000000000000000000000000000000000000..b1fd4ced4e888b0aa67dd7cde76c6f41f582c3d6 --- /dev/null +++ b/node_modules/argparse/lib/const.js @@ -0,0 +1,21 @@ +// +// Constants +// + +'use strict'; + +module.exports.EOL = '\n'; + +module.exports.SUPPRESS = '==SUPPRESS=='; + +module.exports.OPTIONAL = '?'; + +module.exports.ZERO_OR_MORE = '*'; + +module.exports.ONE_OR_MORE = '+'; + +module.exports.PARSER = 'A...'; + +module.exports.REMAINDER = '...'; + +module.exports._UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'; diff --git a/node_modules/argparse/lib/help/added_formatters.js b/node_modules/argparse/lib/help/added_formatters.js new file mode 100644 index 0000000000000000000000000000000000000000..f8e42998e9bf5871f3c0e42ce8a00ae048178c90 --- /dev/null +++ b/node_modules/argparse/lib/help/added_formatters.js @@ -0,0 +1,87 @@ +'use strict'; + +var util = require('util'); + +// Constants +var c = require('../const'); + +var $$ = require('../utils'); +var HelpFormatter = require('./formatter.js'); + +/** + * new RawDescriptionHelpFormatter(options) + * new ArgumentParser({formatterClass: argparse.RawDescriptionHelpFormatter, ...}) + * + * Help message formatter which adds default values to argument help. + * + * Only the name of this class is considered a public API. All the methods + * provided by the class are considered an implementation detail. + **/ + +function ArgumentDefaultsHelpFormatter(options) { + HelpFormatter.call(this, options); +} + +util.inherits(ArgumentDefaultsHelpFormatter, HelpFormatter); + +ArgumentDefaultsHelpFormatter.prototype._getHelpString = function (action) { + var help = action.help; + if (action.help.indexOf('%(defaultValue)s') === -1) { + if (action.defaultValue !== c.SUPPRESS) { + var defaulting_nargs = [ c.OPTIONAL, c.ZERO_OR_MORE ]; + if (action.isOptional() || (defaulting_nargs.indexOf(action.nargs) >= 0)) { + help += ' (default: %(defaultValue)s)'; + } + } + } + return help; +}; + +module.exports.ArgumentDefaultsHelpFormatter = ArgumentDefaultsHelpFormatter; + +/** + * new RawDescriptionHelpFormatter(options) + * new ArgumentParser({formatterClass: argparse.RawDescriptionHelpFormatter, ...}) + * + * Help message formatter which retains any formatting in descriptions. + * + * Only the name of this class is considered a public API. All the methods + * provided by the class are considered an implementation detail. + **/ + +function RawDescriptionHelpFormatter(options) { + HelpFormatter.call(this, options); +} + +util.inherits(RawDescriptionHelpFormatter, HelpFormatter); + +RawDescriptionHelpFormatter.prototype._fillText = function (text, width, indent) { + var lines = text.split('\n'); + lines = lines.map(function (line) { + return $$.trimEnd(indent + line); + }); + return lines.join('\n'); +}; +module.exports.RawDescriptionHelpFormatter = RawDescriptionHelpFormatter; + +/** + * new RawTextHelpFormatter(options) + * new ArgumentParser({formatterClass: argparse.RawTextHelpFormatter, ...}) + * + * Help message formatter which retains formatting of all help text. + * + * Only the name of this class is considered a public API. All the methods + * provided by the class are considered an implementation detail. + **/ + +function RawTextHelpFormatter(options) { + RawDescriptionHelpFormatter.call(this, options); +} + +util.inherits(RawTextHelpFormatter, RawDescriptionHelpFormatter); + +RawTextHelpFormatter.prototype._splitLines = function (text) { + return text.split('\n'); +}; + +module.exports.RawTextHelpFormatter = RawTextHelpFormatter; diff --git a/node_modules/argparse/lib/help/formatter.js b/node_modules/argparse/lib/help/formatter.js new file mode 100644 index 0000000000000000000000000000000000000000..29036c14b2e156e4287e8136a545ec0be17fc5b4 --- /dev/null +++ b/node_modules/argparse/lib/help/formatter.js @@ -0,0 +1,795 @@ +/** + * class HelpFormatter + * + * Formatter for generating usage messages and argument help strings. Only the + * name of this class is considered a public API. All the methods provided by + * the class are considered an implementation detail. + * + * Do not call in your code, use this class only for inherits your own forvatter + * + * ToDo add [additonal formatters][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#formatter-class + **/ +'use strict'; + +var sprintf = require('sprintf-js').sprintf; + +// Constants +var c = require('../const'); + +var $$ = require('../utils'); + + +/*:nodoc:* internal + * new Support(parent, heding) + * - parent (object): parent section + * - heading (string): header string + * + **/ +function Section(parent, heading) { + this._parent = parent; + this._heading = heading; + this._items = []; +} + +/*:nodoc:* internal + * Section#addItem(callback) -> Void + * - callback (array): tuple with function and args + * + * Add function for single element + **/ +Section.prototype.addItem = function (callback) { + this._items.push(callback); +}; + +/*:nodoc:* internal + * Section#formatHelp(formatter) -> string + * - formatter (HelpFormatter): current formatter + * + * Form help section string + * + **/ +Section.prototype.formatHelp = function (formatter) { + var itemHelp, heading; + + // format the indented section + if (this._parent) { + formatter._indent(); + } + + itemHelp = this._items.map(function (item) { + var obj, func, args; + + obj = formatter; + func = item[0]; + args = item[1]; + return func.apply(obj, args); + }); + itemHelp = formatter._joinParts(itemHelp); + + if (this._parent) { + formatter._dedent(); + } + + // return nothing if the section was empty + if (!itemHelp) { + return ''; + } + + // add the heading if the section was non-empty + heading = ''; + if (this._heading && this._heading !== c.SUPPRESS) { + var currentIndent = formatter.currentIndent; + heading = $$.repeat(' ', currentIndent) + this._heading + ':' + c.EOL; + } + + // join the section-initialize newline, the heading and the help + return formatter._joinParts([ c.EOL, heading, itemHelp, c.EOL ]); +}; + +/** + * new HelpFormatter(options) + * + * #### Options: + * - `prog`: program name + * - `indentIncriment`: indent step, default value 2 + * - `maxHelpPosition`: max help position, default value = 24 + * - `width`: line width + * + **/ +var HelpFormatter = module.exports = function HelpFormatter(options) { + options = options || {}; + + this._prog = options.prog; + + this._maxHelpPosition = options.maxHelpPosition || 24; + this._width = (options.width || ((process.env.COLUMNS || 80) - 2)); + + this._currentIndent = 0; + this._indentIncriment = options.indentIncriment || 2; + this._level = 0; + this._actionMaxLength = 0; + + this._rootSection = new Section(null); + this._currentSection = this._rootSection; + + this._whitespaceMatcher = new RegExp('\\s+', 'g'); + this._longBreakMatcher = new RegExp(c.EOL + c.EOL + c.EOL + '+', 'g'); +}; + +HelpFormatter.prototype._indent = function () { + this._currentIndent += this._indentIncriment; + this._level += 1; +}; + +HelpFormatter.prototype._dedent = function () { + this._currentIndent -= this._indentIncriment; + this._level -= 1; + if (this._currentIndent < 0) { + throw new Error('Indent decreased below 0.'); + } +}; + +HelpFormatter.prototype._addItem = function (func, args) { + this._currentSection.addItem([ func, args ]); +}; + +// +// Message building methods +// + +/** + * HelpFormatter#startSection(heading) -> Void + * - heading (string): header string + * + * Start new help section + * + * See alse [code example][1] + * + * ##### Example + * + * formatter.startSection(actionGroup.title); + * formatter.addText(actionGroup.description); + * formatter.addArguments(actionGroup._groupActions); + * formatter.endSection(); + * + **/ +HelpFormatter.prototype.startSection = function (heading) { + this._indent(); + var section = new Section(this._currentSection, heading); + var func = section.formatHelp.bind(section); + this._addItem(func, [ this ]); + this._currentSection = section; +}; + +/** + * HelpFormatter#endSection -> Void + * + * End help section + * + * ##### Example + * + * formatter.startSection(actionGroup.title); + * formatter.addText(actionGroup.description); + * formatter.addArguments(actionGroup._groupActions); + * formatter.endSection(); + **/ +HelpFormatter.prototype.endSection = function () { + this._currentSection = this._currentSection._parent; + this._dedent(); +}; + +/** + * HelpFormatter#addText(text) -> Void + * - text (string): plain text + * + * Add plain text into current section + * + * ##### Example + * + * formatter.startSection(actionGroup.title); + * formatter.addText(actionGroup.description); + * formatter.addArguments(actionGroup._groupActions); + * formatter.endSection(); + * + **/ +HelpFormatter.prototype.addText = function (text) { + if (text && text !== c.SUPPRESS) { + this._addItem(this._formatText, [ text ]); + } +}; + +/** + * HelpFormatter#addUsage(usage, actions, groups, prefix) -> Void + * - usage (string): usage text + * - actions (array): actions list + * - groups (array): groups list + * - prefix (string): usage prefix + * + * Add usage data into current section + * + * ##### Example + * + * formatter.addUsage(this.usage, this._actions, []); + * return formatter.formatHelp(); + * + **/ +HelpFormatter.prototype.addUsage = function (usage, actions, groups, prefix) { + if (usage !== c.SUPPRESS) { + this._addItem(this._formatUsage, [ usage, actions, groups, prefix ]); + } +}; + +/** + * HelpFormatter#addArgument(action) -> Void + * - action (object): action + * + * Add argument into current section + * + * Single variant of [[HelpFormatter#addArguments]] + **/ +HelpFormatter.prototype.addArgument = function (action) { + if (action.help !== c.SUPPRESS) { + var self = this; + + // find all invocations + var invocations = [ this._formatActionInvocation(action) ]; + var invocationLength = invocations[0].length; + + var actionLength; + + if (action._getSubactions) { + this._indent(); + action._getSubactions().forEach(function (subaction) { + + var invocationNew = self._formatActionInvocation(subaction); + invocations.push(invocationNew); + invocationLength = Math.max(invocationLength, invocationNew.length); + + }); + this._dedent(); + } + + // update the maximum item length + actionLength = invocationLength + this._currentIndent; + this._actionMaxLength = Math.max(this._actionMaxLength, actionLength); + + // add the item to the list + this._addItem(this._formatAction, [ action ]); + } +}; + +/** + * HelpFormatter#addArguments(actions) -> Void + * - actions (array): actions list + * + * Mass add arguments into current section + * + * ##### Example + * + * formatter.startSection(actionGroup.title); + * formatter.addText(actionGroup.description); + * formatter.addArguments(actionGroup._groupActions); + * formatter.endSection(); + * + **/ +HelpFormatter.prototype.addArguments = function (actions) { + var self = this; + actions.forEach(function (action) { + self.addArgument(action); + }); +}; + +// +// Help-formatting methods +// + +/** + * HelpFormatter#formatHelp -> string + * + * Format help + * + * ##### Example + * + * formatter.addText(this.epilog); + * return formatter.formatHelp(); + * + **/ +HelpFormatter.prototype.formatHelp = function () { + var help = this._rootSection.formatHelp(this); + if (help) { + help = help.replace(this._longBreakMatcher, c.EOL + c.EOL); + help = $$.trimChars(help, c.EOL) + c.EOL; + } + return help; +}; + +HelpFormatter.prototype._joinParts = function (partStrings) { + return partStrings.filter(function (part) { + return (part && part !== c.SUPPRESS); + }).join(''); +}; + +HelpFormatter.prototype._formatUsage = function (usage, actions, groups, prefix) { + if (!prefix && typeof prefix !== 'string') { + prefix = 'usage: '; + } + + actions = actions || []; + groups = groups || []; + + + // if usage is specified, use that + if (usage) { + usage = sprintf(usage, { prog: this._prog }); + + // if no optionals or positionals are available, usage is just prog + } else if (!usage && actions.length === 0) { + usage = this._prog; + + // if optionals and positionals are available, calculate usage + } else if (!usage) { + var prog = this._prog; + var optionals = []; + var positionals = []; + var actionUsage; + var textWidth; + + // split optionals from positionals + actions.forEach(function (action) { + if (action.isOptional()) { + optionals.push(action); + } else { + positionals.push(action); + } + }); + + // build full usage string + actionUsage = this._formatActionsUsage([].concat(optionals, positionals), groups); + usage = [ prog, actionUsage ].join(' '); + + // wrap the usage parts if it's too long + textWidth = this._width - this._currentIndent; + if ((prefix.length + usage.length) > textWidth) { + + // break usage into wrappable parts + var regexpPart = new RegExp('\\(.*?\\)+|\\[.*?\\]+|\\S+', 'g'); + var optionalUsage = this._formatActionsUsage(optionals, groups); + var positionalUsage = this._formatActionsUsage(positionals, groups); + + + var optionalParts = optionalUsage.match(regexpPart); + var positionalParts = positionalUsage.match(regexpPart) || []; + + if (optionalParts.join(' ') !== optionalUsage) { + throw new Error('assert "optionalParts.join(\' \') === optionalUsage"'); + } + if (positionalParts.join(' ') !== positionalUsage) { + throw new Error('assert "positionalParts.join(\' \') === positionalUsage"'); + } + + // helper for wrapping lines + /*eslint-disable func-style*/ // node 0.10 compat + var _getLines = function (parts, indent, prefix) { + var lines = []; + var line = []; + + var lineLength = prefix ? prefix.length - 1 : indent.length - 1; + + parts.forEach(function (part) { + if (lineLength + 1 + part.length > textWidth) { + lines.push(indent + line.join(' ')); + line = []; + lineLength = indent.length - 1; + } + line.push(part); + lineLength += part.length + 1; + }); + + if (line) { + lines.push(indent + line.join(' ')); + } + if (prefix) { + lines[0] = lines[0].substr(indent.length); + } + return lines; + }; + + var lines, indent, parts; + // if prog is short, follow it with optionals or positionals + if (prefix.length + prog.length <= 0.75 * textWidth) { + indent = $$.repeat(' ', (prefix.length + prog.length + 1)); + if (optionalParts) { + lines = [].concat( + _getLines([ prog ].concat(optionalParts), indent, prefix), + _getLines(positionalParts, indent) + ); + } else if (positionalParts) { + lines = _getLines([ prog ].concat(positionalParts), indent, prefix); + } else { + lines = [ prog ]; + } + + // if prog is long, put it on its own line + } else { + indent = $$.repeat(' ', prefix.length); + parts = optionalParts.concat(positionalParts); + lines = _getLines(parts, indent); + if (lines.length > 1) { + lines = [].concat( + _getLines(optionalParts, indent), + _getLines(positionalParts, indent) + ); + } + lines = [ prog ].concat(lines); + } + // join lines into usage + usage = lines.join(c.EOL); + } + } + + // prefix with 'usage:' + return prefix + usage + c.EOL + c.EOL; +}; + +HelpFormatter.prototype._formatActionsUsage = function (actions, groups) { + // find group indices and identify actions in groups + var groupActions = []; + var inserts = []; + var self = this; + + groups.forEach(function (group) { + var end; + var i; + + var start = actions.indexOf(group._groupActions[0]); + if (start >= 0) { + end = start + group._groupActions.length; + + //if (actions.slice(start, end) === group._groupActions) { + if ($$.arrayEqual(actions.slice(start, end), group._groupActions)) { + group._groupActions.forEach(function (action) { + groupActions.push(action); + }); + + if (!group.required) { + if (inserts[start]) { + inserts[start] += ' ['; + } else { + inserts[start] = '['; + } + inserts[end] = ']'; + } else { + if (inserts[start]) { + inserts[start] += ' ('; + } else { + inserts[start] = '('; + } + inserts[end] = ')'; + } + for (i = start + 1; i < end; i += 1) { + inserts[i] = '|'; + } + } + } + }); + + // collect all actions format strings + var parts = []; + + actions.forEach(function (action, actionIndex) { + var part; + var optionString; + var argsDefault; + var argsString; + + // suppressed arguments are marked with None + // remove | separators for suppressed arguments + if (action.help === c.SUPPRESS) { + parts.push(null); + if (inserts[actionIndex] === '|') { + inserts.splice(actionIndex, actionIndex); + } else if (inserts[actionIndex + 1] === '|') { + inserts.splice(actionIndex + 1, actionIndex + 1); + } + + // produce all arg strings + } else if (!action.isOptional()) { + part = self._formatArgs(action, action.dest); + + // if it's in a group, strip the outer [] + if (groupActions.indexOf(action) >= 0) { + if (part[0] === '[' && part[part.length - 1] === ']') { + part = part.slice(1, -1); + } + } + // add the action string to the list + parts.push(part); + + // produce the first way to invoke the option in brackets + } else { + optionString = action.optionStrings[0]; + + // if the Optional doesn't take a value, format is: -s or --long + if (action.nargs === 0) { + part = '' + optionString; + + // if the Optional takes a value, format is: -s ARGS or --long ARGS + } else { + argsDefault = action.dest.toUpperCase(); + argsString = self._formatArgs(action, argsDefault); + part = optionString + ' ' + argsString; + } + // make it look optional if it's not required or in a group + if (!action.required && groupActions.indexOf(action) < 0) { + part = '[' + part + ']'; + } + // add the action string to the list + parts.push(part); + } + }); + + // insert things at the necessary indices + for (var i = inserts.length - 1; i >= 0; --i) { + if (inserts[i] !== null) { + parts.splice(i, 0, inserts[i]); + } + } + + // join all the action items with spaces + var text = parts.filter(function (part) { + return !!part; + }).join(' '); + + // clean up separators for mutually exclusive groups + text = text.replace(/([\[(]) /g, '$1'); // remove spaces + text = text.replace(/ ([\])])/g, '$1'); + text = text.replace(/\[ *\]/g, ''); // remove empty groups + text = text.replace(/\( *\)/g, ''); + text = text.replace(/\(([^|]*)\)/g, '$1'); // remove () from single action groups + + text = text.trim(); + + // return the text + return text; +}; + +HelpFormatter.prototype._formatText = function (text) { + text = sprintf(text, { prog: this._prog }); + var textWidth = this._width - this._currentIndent; + var indentIncriment = $$.repeat(' ', this._currentIndent); + return this._fillText(text, textWidth, indentIncriment) + c.EOL + c.EOL; +}; + +HelpFormatter.prototype._formatAction = function (action) { + var self = this; + + var helpText; + var helpLines; + var parts; + var indentFirst; + + // determine the required width and the entry label + var helpPosition = Math.min(this._actionMaxLength + 2, this._maxHelpPosition); + var helpWidth = this._width - helpPosition; + var actionWidth = helpPosition - this._currentIndent - 2; + var actionHeader = this._formatActionInvocation(action); + + // no help; start on same line and add a final newline + if (!action.help) { + actionHeader = $$.repeat(' ', this._currentIndent) + actionHeader + c.EOL; + + // short action name; start on the same line and pad two spaces + } else if (actionHeader.length <= actionWidth) { + actionHeader = $$.repeat(' ', this._currentIndent) + + actionHeader + + ' ' + + $$.repeat(' ', actionWidth - actionHeader.length); + indentFirst = 0; + + // long action name; start on the next line + } else { + actionHeader = $$.repeat(' ', this._currentIndent) + actionHeader + c.EOL; + indentFirst = helpPosition; + } + + // collect the pieces of the action help + parts = [ actionHeader ]; + + // if there was help for the action, add lines of help text + if (action.help) { + helpText = this._expandHelp(action); + helpLines = this._splitLines(helpText, helpWidth); + parts.push($$.repeat(' ', indentFirst) + helpLines[0] + c.EOL); + helpLines.slice(1).forEach(function (line) { + parts.push($$.repeat(' ', helpPosition) + line + c.EOL); + }); + + // or add a newline if the description doesn't end with one + } else if (actionHeader.charAt(actionHeader.length - 1) !== c.EOL) { + parts.push(c.EOL); + } + // if there are any sub-actions, add their help as well + if (action._getSubactions) { + this._indent(); + action._getSubactions().forEach(function (subaction) { + parts.push(self._formatAction(subaction)); + }); + this._dedent(); + } + // return a single string + return this._joinParts(parts); +}; + +HelpFormatter.prototype._formatActionInvocation = function (action) { + if (!action.isOptional()) { + var format_func = this._metavarFormatter(action, action.dest); + var metavars = format_func(1); + return metavars[0]; + } + + var parts = []; + var argsDefault; + var argsString; + + // if the Optional doesn't take a value, format is: -s, --long + if (action.nargs === 0) { + parts = parts.concat(action.optionStrings); + + // if the Optional takes a value, format is: -s ARGS, --long ARGS + } else { + argsDefault = action.dest.toUpperCase(); + argsString = this._formatArgs(action, argsDefault); + action.optionStrings.forEach(function (optionString) { + parts.push(optionString + ' ' + argsString); + }); + } + return parts.join(', '); +}; + +HelpFormatter.prototype._metavarFormatter = function (action, metavarDefault) { + var result; + + if (action.metavar || action.metavar === '') { + result = action.metavar; + } else if (action.choices) { + var choices = action.choices; + + if (typeof choices === 'string') { + choices = choices.split('').join(', '); + } else if (Array.isArray(choices)) { + choices = choices.join(','); + } else { + choices = Object.keys(choices).join(','); + } + result = '{' + choices + '}'; + } else { + result = metavarDefault; + } + + return function (size) { + if (Array.isArray(result)) { + return result; + } + + var metavars = []; + for (var i = 0; i < size; i += 1) { + metavars.push(result); + } + return metavars; + }; +}; + +HelpFormatter.prototype._formatArgs = function (action, metavarDefault) { + var result; + var metavars; + + var buildMetavar = this._metavarFormatter(action, metavarDefault); + + switch (action.nargs) { + /*eslint-disable no-undefined*/ + case undefined: + case null: + metavars = buildMetavar(1); + result = '' + metavars[0]; + break; + case c.OPTIONAL: + metavars = buildMetavar(1); + result = '[' + metavars[0] + ']'; + break; + case c.ZERO_OR_MORE: + metavars = buildMetavar(2); + result = '[' + metavars[0] + ' [' + metavars[1] + ' ...]]'; + break; + case c.ONE_OR_MORE: + metavars = buildMetavar(2); + result = '' + metavars[0] + ' [' + metavars[1] + ' ...]'; + break; + case c.REMAINDER: + result = '...'; + break; + case c.PARSER: + metavars = buildMetavar(1); + result = metavars[0] + ' ...'; + break; + default: + metavars = buildMetavar(action.nargs); + result = metavars.join(' '); + } + return result; +}; + +HelpFormatter.prototype._expandHelp = function (action) { + var params = { prog: this._prog }; + + Object.keys(action).forEach(function (actionProperty) { + var actionValue = action[actionProperty]; + + if (actionValue !== c.SUPPRESS) { + params[actionProperty] = actionValue; + } + }); + + if (params.choices) { + if (typeof params.choices === 'string') { + params.choices = params.choices.split('').join(', '); + } else if (Array.isArray(params.choices)) { + params.choices = params.choices.join(', '); + } else { + params.choices = Object.keys(params.choices).join(', '); + } + } + + return sprintf(this._getHelpString(action), params); +}; + +HelpFormatter.prototype._splitLines = function (text, width) { + var lines = []; + var delimiters = [ ' ', '.', ',', '!', '?' ]; + var re = new RegExp('[' + delimiters.join('') + '][^' + delimiters.join('') + ']*$'); + + text = text.replace(/[\n\|\t]/g, ' '); + + text = text.trim(); + text = text.replace(this._whitespaceMatcher, ' '); + + // Wraps the single paragraph in text (a string) so every line + // is at most width characters long. + text.split(c.EOL).forEach(function (line) { + if (width >= line.length) { + lines.push(line); + return; + } + + var wrapStart = 0; + var wrapEnd = width; + var delimiterIndex = 0; + while (wrapEnd <= line.length) { + if (wrapEnd !== line.length && delimiters.indexOf(line[wrapEnd] < -1)) { + delimiterIndex = (re.exec(line.substring(wrapStart, wrapEnd)) || {}).index; + wrapEnd = wrapStart + delimiterIndex + 1; + } + lines.push(line.substring(wrapStart, wrapEnd)); + wrapStart = wrapEnd; + wrapEnd += width; + } + if (wrapStart < line.length) { + lines.push(line.substring(wrapStart, wrapEnd)); + } + }); + + return lines; +}; + +HelpFormatter.prototype._fillText = function (text, width, indent) { + var lines = this._splitLines(text, width); + lines = lines.map(function (line) { + return indent + line; + }); + return lines.join(c.EOL); +}; + +HelpFormatter.prototype._getHelpString = function (action) { + return action.help; +}; diff --git a/node_modules/argparse/lib/namespace.js b/node_modules/argparse/lib/namespace.js new file mode 100644 index 0000000000000000000000000000000000000000..a860de9ecc48ddc61ef65fab4794406005f67a48 --- /dev/null +++ b/node_modules/argparse/lib/namespace.js @@ -0,0 +1,76 @@ +/** + * class Namespace + * + * Simple object for storing attributes. Implements equality by attribute names + * and values, and provides a simple string representation. + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#the-namespace-object + **/ +'use strict'; + +var $$ = require('./utils'); + +/** + * new Namespace(options) + * - options(object): predefined propertis for result object + * + **/ +var Namespace = module.exports = function Namespace(options) { + $$.extend(this, options); +}; + +/** + * Namespace#isset(key) -> Boolean + * - key (string|number): property name + * + * Tells whenever `namespace` contains given `key` or not. + **/ +Namespace.prototype.isset = function (key) { + return $$.has(this, key); +}; + +/** + * Namespace#set(key, value) -> self + * -key (string|number|object): propery name + * -value (mixed): new property value + * + * Set the property named key with value. + * If key object then set all key properties to namespace object + **/ +Namespace.prototype.set = function (key, value) { + if (typeof (key) === 'object') { + $$.extend(this, key); + } else { + this[key] = value; + } + return this; +}; + +/** + * Namespace#get(key, defaultValue) -> mixed + * - key (string|number): property name + * - defaultValue (mixed): default value + * + * Return the property key or defaulValue if not set + **/ +Namespace.prototype.get = function (key, defaultValue) { + return !this[key] ? defaultValue : this[key]; +}; + +/** + * Namespace#unset(key, defaultValue) -> mixed + * - key (string|number): property name + * - defaultValue (mixed): default value + * + * Return data[key](and delete it) or defaultValue + **/ +Namespace.prototype.unset = function (key, defaultValue) { + var value = this[key]; + if (value !== null) { + delete this[key]; + return value; + } + return defaultValue; +}; diff --git a/node_modules/argparse/lib/utils.js b/node_modules/argparse/lib/utils.js new file mode 100644 index 0000000000000000000000000000000000000000..4a9cf3edb615ce9a5f572836c66711e0814cec9c --- /dev/null +++ b/node_modules/argparse/lib/utils.js @@ -0,0 +1,57 @@ +'use strict'; + +exports.repeat = function (str, num) { + var result = ''; + for (var i = 0; i < num; i++) { result += str; } + return result; +}; + +exports.arrayEqual = function (a, b) { + if (a.length !== b.length) { return false; } + for (var i = 0; i < a.length; i++) { + if (a[i] !== b[i]) { return false; } + } + return true; +}; + +exports.trimChars = function (str, chars) { + var start = 0; + var end = str.length - 1; + while (chars.indexOf(str.charAt(start)) >= 0) { start++; } + while (chars.indexOf(str.charAt(end)) >= 0) { end--; } + return str.slice(start, end + 1); +}; + +exports.capitalize = function (str) { + return str.charAt(0).toUpperCase() + str.slice(1); +}; + +exports.arrayUnion = function () { + var result = []; + for (var i = 0, values = {}; i < arguments.length; i++) { + var arr = arguments[i]; + for (var j = 0; j < arr.length; j++) { + if (!values[arr[j]]) { + values[arr[j]] = true; + result.push(arr[j]); + } + } + } + return result; +}; + +function has(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} + +exports.has = has; + +exports.extend = function (dest, src) { + for (var i in src) { + if (has(src, i)) { dest[i] = src[i]; } + } +}; + +exports.trimEnd = function (str) { + return str.replace(/\s+$/g, ''); +}; diff --git a/node_modules/argparse/package.json b/node_modules/argparse/package.json new file mode 100644 index 0000000000000000000000000000000000000000..3080ced3e533c46bf3bda85738437270fe8cd7d0 --- /dev/null +++ b/node_modules/argparse/package.json @@ -0,0 +1,109 @@ +{ + "_args": [ + [ + { + "name": "argparse", + "raw": "argparse@^1.0.7", + "rawSpec": "^1.0.7", + "scope": null, + "spec": ">=1.0.7 <2.0.0", + "type": "range" + }, + "/Users/xxm/Documents/gitlab/codechina-docs/node_modules/js-yaml" + ] + ], + "_from": "argparse@>=1.0.7 <2.0.0", + "_hasShrinkwrap": false, + "_id": "argparse@1.0.10", + "_inCache": true, + "_installable": true, + "_location": "/argparse", + "_nodeVersion": "8.9.1", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/argparse_1.0.10_1518704641025_0.2567322588736727" + }, + "_npmUser": { + "email": "vitaly@rcdesign.ru", + "name": "vitaly" + }, + "_npmVersion": "5.5.1", + "_phantomChildren": {}, + "_requested": { + "name": "argparse", + "raw": "argparse@^1.0.7", + "rawSpec": "^1.0.7", + "scope": null, + "spec": ">=1.0.7 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/js-yaml", + "/remarkable" + ], + "_resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "_shasum": "bcd6791ea5ae09725e17e5ad988134cd40b3d911", + "_shrinkwrap": null, + "_spec": "argparse@^1.0.7", + "_where": "/Users/xxm/Documents/gitlab/codechina-docs/node_modules/js-yaml", + "bugs": { + "url": "https://github.com/nodeca/argparse/issues" + }, + "contributors": [ + { + "name": "Eugene Shkuropat" + }, + { + "name": "Paul Jacobson" + } + ], + "dependencies": { + "sprintf-js": "~1.0.2" + }, + "description": "Very powerful CLI arguments parser. Native port of argparse - python's options parsing library", + "devDependencies": { + "eslint": "^2.13.1", + "istanbul": "^0.4.5", + "mocha": "^3.1.0", + "ndoc": "^5.0.1" + }, + "directories": {}, + "dist": { + "fileCount": 27, + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "shasum": "bcd6791ea5ae09725e17e5ad988134cd40b3d911", + "tarball": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "unpackedSize": 116446 + }, + "files": [ + "index.js", + "lib/" + ], + "gitHead": "ea45e14bad13b9e4a10af28f11fb7e731079ab72", + "homepage": "https://github.com/nodeca/argparse#readme", + "keywords": [ + "cli", + "parser", + "argparse", + "option", + "args" + ], + "license": "MIT", + "maintainers": [ + { + "email": "vitaly@rcdesign.ru", + "name": "vitaly" + } + ], + "name": "argparse", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/nodeca/argparse.git" + }, + "scripts": { + "test": "make test" + }, + "version": "1.0.10" +} diff --git a/node_modules/autolinker/LICENSE b/node_modules/autolinker/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..3ff145b9fa33846bf8ff36b6c6eca9c6705591a3 --- /dev/null +++ b/node_modules/autolinker/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014 Gregory Jacobs (http://greg-jacobs.com) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/autolinker/README.md b/node_modules/autolinker/README.md new file mode 100644 index 0000000000000000000000000000000000000000..78cc38973072192d1e1598d70e849c8c335cb6e1 --- /dev/null +++ b/node_modules/autolinker/README.md @@ -0,0 +1,340 @@ +# Autolinker.js + +Because I had so much trouble finding a good auto-linking implementation out in +the wild, I decided to roll my own. It seemed that everything I found out there +was either an implementation that didn't cover every case, or was just limited +in one way or another. + +So, this utility attempts to handle everything. It: + +- Autolinks URLs, whether or not they start with the protocol (i.e. 'http://'). + In other words, it will automatically link the text "google.com", as well as + "http://google.com". +- Will properly handle URLs with special characters +- Will properly handle URLs with query parameters or a named anchor (i.e. hash) +- Will autolink email addresses. +- Will autolink phone numbers. +- Will autolink Twitter handles. +- Will autolink hashtags. +- Will properly handle HTML input. The utility will not change the `href` + attribute inside anchor (<a>) tags (or any other tag/attribute for that + matter), and will not accidentally wrap the inner text of an anchor tag with a + new one (which would cause doubly-nested anchor tags). + +Hope that this utility helps you as well! + +Full API Docs: [http://gregjacobs.github.io/Autolinker.js/docs/](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker)
      +Live Example: [http://gregjacobs.github.io/Autolinker.js/examples/live-example/](http://gregjacobs.github.io/Autolinker.js/examples/live-example/) + + +## Installation + +#### Download + +Simply clone or download the zip of the project, and link to either +`dist/Autolinker.js` or `dist/Autolinker.min.js` with a script tag: + +```html + +``` + +#### Using with the [Bower](http://bower.io) package manager: + +Command line: + +```shell +bower install Autolinker.js --save +``` + +#### Using with [Node.js](http://nodejs.org) via [npm](https://www.npmjs.org/): + +Command Line: + +```shell +npm install autolinker --save +``` + +JavaScript: + +```javascript +var Autolinker = require( 'autolinker' ); +// note: npm wants an all-lowercase package name, but the utility is a class and +// should be aliased with a capital letter +``` + + +## Usage + +Using the static [link()](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-static-method-link) +method: + +```javascript +var linkedText = Autolinker.link( textToAutolink[, options] ); +``` + +Using as a class: + +```javascript +var autolinker = new Autolinker( [ options ] ); + +var linkedText = autolinker.link( textToAutoLink ); +``` + +Note: if using the same options to autolink multiple pieces of html/text, it is +slightly more efficient to create a single Autolinker instance, and run the +[link()](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-method-link) +method repeatedly (i.e. use the "class" form above). + + +#### Example: + +```javascript +var linkedText = Autolinker.link( "Check out google.com", { className: "myLink" } ); +// Produces: "Check out google.com" +``` + +## Options + +These are the options which may be specified for linking. These are specified by +providing an Object as the second parameter to [Autolinker.link()](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-static-method-link). These include: + +- [newWindow](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-newWindow) : Boolean
      + `true` to have the links should open in a new window when clicked, `false` + otherwise. Defaults to `true`.

      +- [stripPrefix](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-stripPrefix) : Boolean
      + `true` to have the 'http://' or 'https://' and/or the 'www.' stripped from the + beginning of links, `false` otherwise. Defaults to `true`.

      +- [truncate](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-truncate) : Number/Object
      + A number for how many characters long URLs/emails/Twitter handles/Twitter + hashtags should be truncated to inside the text of a link. If the match is + over the number of characters, it will be truncated to this length by + replacing the end of the string with a two period ellipsis ('..').

      + + Example: a url like 'http://www.yahoo.com/some/long/path/to/a/file' truncated + to 25 characters may look like this: 'yahoo.com/some/long/pat..'

      + + In the object form, both `length` and `location` may be specified to perform + truncation. Available options for `location` are: 'end' (default), 'middle', + or 'smart'. Example usage: + + ```javascript + truncate: { length: 32, location: 'middle' } + ``` + + The 'smart' truncation option is for URLs where the algorithm attempts to + strip out unnecessary parts of the URL (such as the 'www.', then URL scheme, + hash, etc.) before trying to find a good point to insert the ellipsis if it is + still too long. For details, see source code of: + [TruncateSmart](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker.truncate.TruncateSmart) +- [className](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-className) : String
      + A CSS class name to add to the generated anchor tags. This class will be added + to all links, as well as this class plus "url"/"email"/"phone"/"twitter"/"hashtag" + suffixes for styling url/email/phone/twitter/hashtag links differently. + + For example, if this config is provided as "myLink", then: + + 1) URL links will have the CSS classes: "myLink myLink-url"
      + 2) Email links will have the CSS classes: "myLink myLink-email"
      + 3) Phone links will have the CSS classes: "myLink myLink-phone"
      + 4) Twitter links will have the CSS classes: "myLink myLink-twitter"
      + 5) Hashtag links will have the CSS classes: "myLink myLink-hashtag"
      + +- [urls](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-urls) : Boolean/Object
      + `true` to have URLs auto-linked, `false` to skip auto-linking of URLs. + Defaults to `true`.
      + + This option also accepts an Object form with 3 properties, to allow for more + customization of what exactly gets linked. All default to `true`: + + - schemeMatches (Boolean): `true` to match URLs found prefixed with a scheme, + i.e. `http://google.com`, or `other+scheme://google.com`, `false` to + prevent these types of matches. + - wwwMatches (Boolean): `true` to match urls found prefixed with `'www.'`, + i.e. `www.google.com`. `false` to prevent these types of matches. Note + that if the URL had a prefixed scheme, and `schemeMatches` is true, it + will still be linked. + - tldMatches: `true` to match URLs with known top level domains (.com, .net, + etc.) that are not prefixed with a scheme or `'www.'`. Ex: `google.com`, + `asdf.org/?page=1`, etc. `false` to prevent these types of matches. +
      + + Example usage: `urls: { schemeMatches: true, wwwMatches: true, tldMatches: false }` + +- [email](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-email) : Boolean
      + `true` to have email addresses auto-linked, `false` to skip auto-linking of + email addresses. Defaults to `true`.

      +- [phone](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-phone) : Boolean
      + `true` to have phone numbers auto-linked, `false` to skip auto-linking of + phone numbers. Defaults to `true`.

      +- [twitter](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-twitter) : Boolean
      + `true` to have Twitter handles auto-linked, `false` to skip auto-linking of + Twitter handles. Defaults to `true`.

      +- [hashtag](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-hashtag) : Boolean/String
      + A string for the service name to have hashtags auto-linked to. Supported + values at this time are 'twitter', 'facebook' and 'instagram'. Pass `false` to skip + auto-linking of hashtags. Defaults to `false`.

      +- [replaceFn](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-replaceFn) : Function
      + A function to use to programmatically make replacements of matches in the + input string, one at a time. See the section + Custom Replacement Function for + more details. + + +For example, if you wanted to disable links from opening in [new windows](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-newWindow), you could do: + +```javascript +var linkedText = Autolinker.link( "Check out google.com", { newWindow: false } ); +// Produces: "Check out google.com" +``` + +And if you wanted to truncate the length of URLs (while also not opening in a new window), you could do: + +```javascript +var linkedText = Autolinker.link( "http://www.yahoo.com/some/long/path/to/a/file", { truncate: 25, newWindow: false } ); +// Produces: "yahoo.com/some/long/pat.." +``` + +## More Examples +One could update an entire DOM element that has unlinked text to auto-link them +as such: + +```javascript +var myTextEl = document.getElementById( 'text' ); +myTextEl.innerHTML = Autolinker.link( myTextEl.innerHTML ); +``` + +Using the same pre-configured [Autolinker](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker) +instance in multiple locations of a codebase (usually by dependency injection): + +```javascript +var autolinker = new Autolinker( { newWindow: false, truncate: 25 } ); + +//... + +autolinker.link( "Check out http://www.yahoo.com/some/long/path/to/a/file" ); +// Produces: "Check out yahoo.com/some/long/pat.." + +//... + +autolinker.link( "Go to www.google.com" ); +// Produces: "Go to google.com" + +``` + + +## Custom Replacement Function + +A custom replacement function ([replaceFn](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker-cfg-replaceFn)) +may be provided to replace url/email/phone/Twitter handle/hashtag matches on an +individual basis, based on the return from this function. + +#### Full example, for purposes of documenting the API: + +```javascript +var input = "..."; // string with URLs, Email Addresses, Twitter Handles, and Hashtags + +var linkedText = Autolinker.link( input, { + replaceFn : function( autolinker, match ) { + console.log( "href = ", match.getAnchorHref() ); + console.log( "text = ", match.getAnchorText() ); + + switch( match.getType() ) { + case 'url' : + console.log( "url: ", match.getUrl() ); + + return true; // let Autolinker perform its normal anchor tag replacement + + case 'email' : + var email = match.getEmail(); + console.log( "email: ", email ); + + if( email === "my@own.address" ) { + return false; // don't auto-link this particular email address; leave as-is + } else { + return; // no return value will have Autolinker perform its normal anchor tag replacement (same as returning `true`) + } + + case 'phone' : + console.log( "Phone Number: ", match.getNumber() ); + + return '' + match.getNumber() + ''; + + case 'twitter' : + console.log( "Twitter Handle: ", match.getTwitterHandle() ); + + return '' + match.getTwitterHandle() + ''; + + case 'hashtag' : + console.log( "Hashtag: ", match.getHashtag() ); + + return '' + match.getHashtag() + ''; + } + } +} ); +``` + +#### Modifying the default generated anchor tag + +```javascript +var input = "..."; // string with URLs, Email Addresses, Twitter Handles, and Hashtags + +var linkedText = Autolinker.link( input, { + replaceFn : function( autolinker, match ) { + console.log( "href = ", match.getAnchorHref() ); + console.log( "text = ", match.getAnchorText() ); + + var tag = match.buildTag(); // returns an `Autolinker.HtmlTag` instance for an tag + tag.setAttr( 'rel', 'nofollow' ); // adds a 'rel' attribute + tag.addClass( 'external-link' ); // adds a CSS class + tag.setInnerHtml( 'Click here!' ); // sets the inner html for the anchor tag + + return tag; + } +} ); +``` + + +The `replaceFn` is provided two arguments: + +1. The [Autolinker](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker) instance that is performing replacements. +2. An [Autolinker.match.Match](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker.match.Match) + object which details the match that is to be replaced. + + +A replacement of the match is made based on the return value of the function. +The following return values may be provided: + +1. No return value (`undefined`), or `true` (Boolean): Delegate back to + Autolinker to replace the match as it normally would. +2. `false` (Boolean): Do not replace the current match at all - leave as-is. +3. Any String: If a string is returned from the function, the string will be used + directly as the replacement HTML for the match. +4. An [Autolinker.HtmlTag](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker.HtmlTag) + instance, which can be used to build/modify an HTML tag before writing out its + HTML text. + + +## Full API Docs + +The full API docs for Autolinker may be referenced at: +[http://gregjacobs.github.io/Autolinker.js/docs/](http://gregjacobs.github.io/Autolinker.js/docs/#!/api/Autolinker) + +## Live Example + +[http://gregjacobs.github.io/Autolinker.js/examples/live-example/](http://gregjacobs.github.io/Autolinker.js/examples/live-example/) + + + +## Contributing + +Pull requests definitely welcome. + +- Make sure to add tests to cover your new functionality/bugfix. +- Run the `gulp` command to build/test (or alternatively, open the `tests/index.html` file to run the tests). +- When committing, please omit checking in the files in the `dist/` folder after building/testing. These are only committed to the repository for users downloading Autolinker via Bower. I will build these files and assign them a version number when merging your PR. +- Please use tabs for indents! Tabs are better for everybody (individuals can set their editors to different tab sizes based on their visual preferences). + + +## Changelog + +See [Releases](https://github.com/gregjacobs/Autolinker.js/releases) diff --git a/node_modules/autolinker/dist/Autolinker.js b/node_modules/autolinker/dist/Autolinker.js new file mode 100644 index 0000000000000000000000000000000000000000..36b655315ea0747597753dacf6cf4bbd049f76ae --- /dev/null +++ b/node_modules/autolinker/dist/Autolinker.js @@ -0,0 +1,3770 @@ +/*! + * Autolinker.js + * 0.28.1 + * + * Copyright(c) 2016 Gregory Jacobs + * MIT License + * + * https://github.com/gregjacobs/Autolinker.js + */ +;(function(root, factory) { + if (typeof define === 'function' && define.amd) { + define([], factory); + } else if (typeof exports === 'object') { + module.exports = factory(); + } else { + root.Autolinker = factory(); + } +}(this, function() { +/** + * @class Autolinker + * @extends Object + * + * Utility class used to process a given string of text, and wrap the matches in + * the appropriate anchor (<a>) tags to turn them into links. + * + * Any of the configuration options may be provided in an Object (map) provided + * to the Autolinker constructor, which will configure how the {@link #link link()} + * method will process the links. + * + * For example: + * + * var autolinker = new Autolinker( { + * newWindow : false, + * truncate : 30 + * } ); + * + * var html = autolinker.link( "Joe went to www.yahoo.com" ); + * // produces: 'Joe went to yahoo.com' + * + * + * The {@link #static-link static link()} method may also be used to inline + * options into a single call, which may be more convenient for one-off uses. + * For example: + * + * var html = Autolinker.link( "Joe went to www.yahoo.com", { + * newWindow : false, + * truncate : 30 + * } ); + * // produces: 'Joe went to yahoo.com' + * + * + * ## Custom Replacements of Links + * + * If the configuration options do not provide enough flexibility, a {@link #replaceFn} + * may be provided to fully customize the output of Autolinker. This function is + * called once for each URL/Email/Phone#/Twitter Handle/Hashtag match that is + * encountered. + * + * For example: + * + * var input = "..."; // string with URLs, Email Addresses, Phone #s, Twitter Handles, and Hashtags + * + * var linkedText = Autolinker.link( input, { + * replaceFn : function( autolinker, match ) { + * console.log( "href = ", match.getAnchorHref() ); + * console.log( "text = ", match.getAnchorText() ); + * + * switch( match.getType() ) { + * case 'url' : + * console.log( "url: ", match.getUrl() ); + * + * if( match.getUrl().indexOf( 'mysite.com' ) === -1 ) { + * var tag = autolinker.getTagBuilder().build( match ); // returns an `Autolinker.HtmlTag` instance, which provides mutator methods for easy changes + * tag.setAttr( 'rel', 'nofollow' ); + * tag.addClass( 'external-link' ); + * + * return tag; + * + * } else { + * return true; // let Autolinker perform its normal anchor tag replacement + * } + * + * case 'email' : + * var email = match.getEmail(); + * console.log( "email: ", email ); + * + * if( email === "my@own.address" ) { + * return false; // don't auto-link this particular email address; leave as-is + * } else { + * return; // no return value will have Autolinker perform its normal anchor tag replacement (same as returning `true`) + * } + * + * case 'phone' : + * var phoneNumber = match.getPhoneNumber(); + * console.log( phoneNumber ); + * + * return '' + phoneNumber + ''; + * + * case 'twitter' : + * var twitterHandle = match.getTwitterHandle(); + * console.log( twitterHandle ); + * + * return '' + twitterHandle + ''; + * + * case 'hashtag' : + * var hashtag = match.getHashtag(); + * console.log( hashtag ); + * + * return '' + hashtag + ''; + * } + * } + * } ); + * + * + * The function may return the following values: + * + * - `true` (Boolean): Allow Autolinker to replace the match as it normally + * would. + * - `false` (Boolean): Do not replace the current match at all - leave as-is. + * - Any String: If a string is returned from the function, the string will be + * used directly as the replacement HTML for the match. + * - An {@link Autolinker.HtmlTag} instance, which can be used to build/modify + * an HTML tag before writing out its HTML text. + * + * @constructor + * @param {Object} [cfg] The configuration options for the Autolinker instance, + * specified in an Object (map). + */ +var Autolinker = function( cfg ) { + cfg = cfg || {}; + + this.version = Autolinker.version; + + this.urls = this.normalizeUrlsCfg( cfg.urls ); + this.email = typeof cfg.email === 'boolean' ? cfg.email : true; + this.twitter = typeof cfg.twitter === 'boolean' ? cfg.twitter : true; + this.phone = typeof cfg.phone === 'boolean' ? cfg.phone : true; + this.hashtag = cfg.hashtag || false; + this.newWindow = typeof cfg.newWindow === 'boolean' ? cfg.newWindow : true; + this.stripPrefix = typeof cfg.stripPrefix === 'boolean' ? cfg.stripPrefix : true; + + // Validate the value of the `hashtag` cfg. + var hashtag = this.hashtag; + if( hashtag !== false && hashtag !== 'twitter' && hashtag !== 'facebook' && hashtag !== 'instagram' ) { + throw new Error( "invalid `hashtag` cfg - see docs" ); + } + + this.truncate = this.normalizeTruncateCfg( cfg.truncate ); + this.className = cfg.className || ''; + this.replaceFn = cfg.replaceFn || null; + + this.htmlParser = null; + this.matchers = null; + this.tagBuilder = null; +}; + + + +/** + * Automatically links URLs, Email addresses, Phone Numbers, Twitter handles, + * and Hashtags found in the given chunk of HTML. Does not link URLs found + * within HTML tags. + * + * For instance, if given the text: `You should go to http://www.yahoo.com`, + * then the result will be `You should go to <a href="http://www.yahoo.com">http://www.yahoo.com</a>` + * + * Example: + * + * var linkedText = Autolinker.link( "Go to google.com", { newWindow: false } ); + * // Produces: "Go to google.com" + * + * @static + * @param {String} textOrHtml The HTML or text to find matches within (depending + * on if the {@link #urls}, {@link #email}, {@link #phone}, {@link #twitter}, + * and {@link #hashtag} options are enabled). + * @param {Object} [options] Any of the configuration options for the Autolinker + * class, specified in an Object (map). See the class description for an + * example call. + * @return {String} The HTML text, with matches automatically linked. + */ +Autolinker.link = function( textOrHtml, options ) { + var autolinker = new Autolinker( options ); + return autolinker.link( textOrHtml ); +}; + + +/** + * @static + * @property {String} version (readonly) + * + * The Autolinker version number in the form major.minor.patch + * + * Ex: 0.25.1 + */ +Autolinker.version = '0.28.1'; + + +Autolinker.prototype = { + constructor : Autolinker, // fix constructor property + + /** + * @cfg {Boolean/Object} [urls=true] + * + * `true` if URLs should be automatically linked, `false` if they should not + * be. + * + * This option also accepts an Object form with 3 properties, to allow for + * more customization of what exactly gets linked. All default to `true`: + * + * @param {Boolean} schemeMatches `true` to match URLs found prefixed with a + * scheme, i.e. `http://google.com`, or `other+scheme://google.com`, + * `false` to prevent these types of matches. + * @param {Boolean} wwwMatches `true` to match urls found prefixed with + * `'www.'`, i.e. `www.google.com`. `false` to prevent these types of + * matches. Note that if the URL had a prefixed scheme, and + * `schemeMatches` is true, it will still be linked. + * @param {Boolean} tldMatches `true` to match URLs with known top level + * domains (.com, .net, etc.) that are not prefixed with a scheme or + * `'www.'`. This option attempts to match anything that looks like a URL + * in the given text. Ex: `google.com`, `asdf.org/?page=1`, etc. `false` + * to prevent these types of matches. + */ + + /** + * @cfg {Boolean} [email=true] + * + * `true` if email addresses should be automatically linked, `false` if they + * should not be. + */ + + /** + * @cfg {Boolean} [twitter=true] + * + * `true` if Twitter handles ("@example") should be automatically linked, + * `false` if they should not be. + */ + + /** + * @cfg {Boolean} [phone=true] + * + * `true` if Phone numbers ("(555)555-5555") should be automatically linked, + * `false` if they should not be. + */ + + /** + * @cfg {Boolean/String} [hashtag=false] + * + * A string for the service name to have hashtags (ex: "#myHashtag") + * auto-linked to. The currently-supported values are: + * + * - 'twitter' + * - 'facebook' + * - 'instagram' + * + * Pass `false` to skip auto-linking of hashtags. + */ + + /** + * @cfg {Boolean} [newWindow=true] + * + * `true` if the links should open in a new window, `false` otherwise. + */ + + /** + * @cfg {Boolean} [stripPrefix=true] + * + * `true` if 'http://' or 'https://' and/or the 'www.' should be stripped + * from the beginning of URL links' text, `false` otherwise. + */ + + /** + * @cfg {Number/Object} [truncate=0] + * + * ## Number Form + * + * A number for how many characters matched text should be truncated to + * inside the text of a link. If the matched text is over this number of + * characters, it will be truncated to this length by adding a two period + * ellipsis ('..') to the end of the string. + * + * For example: A url like 'http://www.yahoo.com/some/long/path/to/a/file' + * truncated to 25 characters might look something like this: + * 'yahoo.com/some/long/pat..' + * + * Example Usage: + * + * truncate: 25 + * + * + * Defaults to `0` for "no truncation." + * + * + * ## Object Form + * + * An Object may also be provided with two properties: `length` (Number) and + * `location` (String). `location` may be one of the following: 'end' + * (default), 'middle', or 'smart'. + * + * Example Usage: + * + * truncate: { length: 25, location: 'middle' } + * + * @cfg {Number} [truncate.length=0] How many characters to allow before + * truncation will occur. Defaults to `0` for "no truncation." + * @cfg {"end"/"middle"/"smart"} [truncate.location="end"] + * + * - 'end' (default): will truncate up to the number of characters, and then + * add an ellipsis at the end. Ex: 'yahoo.com/some/long/pat..' + * - 'middle': will truncate and add the ellipsis in the middle. Ex: + * 'yahoo.com/s..th/to/a/file' + * - 'smart': for URLs where the algorithm attempts to strip out unnecessary + * parts first (such as the 'www.', then URL scheme, hash, etc.), + * attempting to make the URL human-readable before looking for a good + * point to insert the ellipsis if it is still too long. Ex: + * 'yahoo.com/some..to/a/file'. For more details, see + * {@link Autolinker.truncate.TruncateSmart}. + */ + + /** + * @cfg {String} className + * + * A CSS class name to add to the generated links. This class will be added + * to all links, as well as this class plus match suffixes for styling + * url/email/phone/twitter/hashtag links differently. + * + * For example, if this config is provided as "myLink", then: + * + * - URL links will have the CSS classes: "myLink myLink-url" + * - Email links will have the CSS classes: "myLink myLink-email", and + * - Twitter links will have the CSS classes: "myLink myLink-twitter" + * - Phone links will have the CSS classes: "myLink myLink-phone" + * - Hashtag links will have the CSS classes: "myLink myLink-hashtag" + */ + + /** + * @cfg {Function} replaceFn + * + * A function to individually process each match found in the input string. + * + * See the class's description for usage. + * + * This function is called with the following parameters: + * + * @cfg {Autolinker} replaceFn.autolinker The Autolinker instance, which may + * be used to retrieve child objects from (such as the instance's + * {@link #getTagBuilder tag builder}). + * @cfg {Autolinker.match.Match} replaceFn.match The Match instance which + * can be used to retrieve information about the match that the `replaceFn` + * is currently processing. See {@link Autolinker.match.Match} subclasses + * for details. + */ + + + /** + * @property {String} version (readonly) + * + * The Autolinker version number in the form major.minor.patch + * + * Ex: 0.25.1 + */ + + /** + * @private + * @property {Autolinker.htmlParser.HtmlParser} htmlParser + * + * The HtmlParser instance used to skip over HTML tags, while finding text + * nodes to process. This is lazily instantiated in the {@link #getHtmlParser} + * method. + */ + + /** + * @private + * @property {Autolinker.matcher.Matcher[]} matchers + * + * The {@link Autolinker.matcher.Matcher} instances for this Autolinker + * instance. + * + * This is lazily created in {@link #getMatchers}. + */ + + /** + * @private + * @property {Autolinker.AnchorTagBuilder} tagBuilder + * + * The AnchorTagBuilder instance used to build match replacement anchor tags. + * Note: this is lazily instantiated in the {@link #getTagBuilder} method. + */ + + + /** + * Normalizes the {@link #urls} config into an Object with 3 properties: + * `schemeMatches`, `wwwMatches`, and `tldMatches`, all Booleans. + * + * See {@link #urls} config for details. + * + * @private + * @param {Boolean/Object} urls + * @return {Object} + */ + normalizeUrlsCfg : function( urls ) { + if( urls == null ) urls = true; // default to `true` + + if( typeof urls === 'boolean' ) { + return { schemeMatches: urls, wwwMatches: urls, tldMatches: urls }; + + } else { // object form + return { + schemeMatches : typeof urls.schemeMatches === 'boolean' ? urls.schemeMatches : true, + wwwMatches : typeof urls.wwwMatches === 'boolean' ? urls.wwwMatches : true, + tldMatches : typeof urls.tldMatches === 'boolean' ? urls.tldMatches : true + }; + } + }, + + + /** + * Normalizes the {@link #truncate} config into an Object with 2 properties: + * `length` (Number), and `location` (String). + * + * See {@link #truncate} config for details. + * + * @private + * @param {Number/Object} truncate + * @return {Object} + */ + normalizeTruncateCfg : function( truncate ) { + if( typeof truncate === 'number' ) { + return { length: truncate, location: 'end' }; + + } else { // object, or undefined/null + return Autolinker.Util.defaults( truncate || {}, { + length : Number.POSITIVE_INFINITY, + location : 'end' + } ); + } + }, + + + /** + * Parses the input `textOrHtml` looking for URLs, email addresses, phone + * numbers, username handles, and hashtags (depending on the configuration + * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match} + * objects describing those matches. + * + * This method is used by the {@link #link} method, but can also be used to + * simply do parsing of the input in order to discover what kinds of links + * there are and how many. + * + * @param {String} textOrHtml The HTML or text to find matches within + * (depending on if the {@link #urls}, {@link #email}, {@link #phone}, + * {@link #twitter}, and {@link #hashtag} options are enabled). + * @return {Autolinker.match.Match[]} The array of Matches found in the + * given input `textOrHtml`. + */ + parse : function( textOrHtml ) { + var htmlParser = this.getHtmlParser(), + htmlNodes = htmlParser.parse( textOrHtml ), + anchorTagStackCount = 0, // used to only process text around anchor tags, and any inner text/html they may have; + matches = []; + + // Find all matches within the `textOrHtml` (but not matches that are + // already nested within tags) + for( var i = 0, len = htmlNodes.length; i < len; i++ ) { + var node = htmlNodes[ i ], + nodeType = node.getType(); + + if( nodeType === 'element' && node.getTagName() === 'a' ) { // Process HTML anchor element nodes in the input `textOrHtml` to find out when we're within an tag + if( !node.isClosing() ) { // it's the start tag + anchorTagStackCount++; + } else { // it's the end tag + anchorTagStackCount = Math.max( anchorTagStackCount - 1, 0 ); // attempt to handle extraneous tags by making sure the stack count never goes below 0 + } + + } else if( nodeType === 'text' && anchorTagStackCount === 0 ) { // Process text nodes that are not within an tag + var textNodeMatches = this.parseText( node.getText(), node.getOffset() ); + + matches.push.apply( matches, textNodeMatches ); + } + } + + + // After we have found all matches, remove subsequent matches that + // overlap with a previous match. This can happen for instance with URLs, + // where the url 'google.com/#link' would match '#link' as a hashtag. + matches = this.compactMatches( matches ); + + // And finally, remove matches for match types that have been turned + // off. We needed to have all match types turned on initially so that + // things like hashtags could be filtered out if they were really just + // part of a URL match (for instance, as a named anchor). + matches = this.removeUnwantedMatches( matches ); + + return matches; + }, + + + /** + * After we have found all matches, we need to remove subsequent matches + * that overlap with a previous match. This can happen for instance with + * URLs, where the url 'google.com/#link' would match '#link' as a hashtag. + * + * @private + * @param {Autolinker.match.Match[]} matches + * @return {Autolinker.match.Match[]} + */ + compactMatches : function( matches ) { + // First, the matches need to be sorted in order of offset + matches.sort( function( a, b ) { return a.getOffset() - b.getOffset(); } ); + + for( var i = 0; i < matches.length - 1; i++ ) { + var match = matches[ i ], + endIdx = match.getOffset() + match.getMatchedText().length; + + // Remove subsequent matches that overlap with the current match + while( i + 1 < matches.length && matches[ i + 1 ].getOffset() <= endIdx ) { + matches.splice( i + 1, 1 ); + } + } + + return matches; + }, + + + /** + * Removes matches for matchers that were turned off in the options. For + * example, if {@link #hashtag hashtags} were not to be matched, we'll + * remove them from the `matches` array here. + * + * @private + * @param {Autolinker.match.Match[]} matches The array of matches to remove + * the unwanted matches from. Note: this array is mutated for the + * removals. + * @return {Autolinker.match.Match[]} The mutated input `matches` array. + */ + removeUnwantedMatches : function( matches ) { + var remove = Autolinker.Util.remove; + + if( !this.hashtag ) remove( matches, function( match ) { return match.getType() === 'hashtag'; } ); + if( !this.email ) remove( matches, function( match ) { return match.getType() === 'email'; } ); + if( !this.phone ) remove( matches, function( match ) { return match.getType() === 'phone'; } ); + if( !this.twitter ) remove( matches, function( match ) { return match.getType() === 'twitter'; } ); + if( !this.urls.schemeMatches ) { + remove( matches, function( m ) { return m.getType() === 'url' && m.getUrlMatchType() === 'scheme'; } ); + } + if( !this.urls.wwwMatches ) { + remove( matches, function( m ) { return m.getType() === 'url' && m.getUrlMatchType() === 'www'; } ); + } + if( !this.urls.tldMatches ) { + remove( matches, function( m ) { return m.getType() === 'url' && m.getUrlMatchType() === 'tld'; } ); + } + + return matches; + }, + + + /** + * Parses the input `text` looking for URLs, email addresses, phone + * numbers, username handles, and hashtags (depending on the configuration + * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match} + * objects describing those matches. + * + * This method processes a **non-HTML string**, and is used to parse and + * match within the text nodes of an HTML string. This method is used + * internally by {@link #parse}. + * + * @private + * @param {String} text The text to find matches within (depending on if the + * {@link #urls}, {@link #email}, {@link #phone}, {@link #twitter}, and + * {@link #hashtag} options are enabled). This must be a non-HTML string. + * @param {Number} [offset=0] The offset of the text node within the + * original string. This is used when parsing with the {@link #parse} + * method to generate correct offsets within the {@link Autolinker.match.Match} + * instances, but may be omitted if calling this method publicly. + * @return {Autolinker.match.Match[]} The array of Matches found in the + * given input `text`. + */ + parseText : function( text, offset ) { + offset = offset || 0; + var matchers = this.getMatchers(), + matches = []; + + for( var i = 0, numMatchers = matchers.length; i < numMatchers; i++ ) { + var textMatches = matchers[ i ].parseMatches( text ); + + // Correct the offset of each of the matches. They are originally + // the offset of the match within the provided text node, but we + // need to correct them to be relative to the original HTML input + // string (i.e. the one provided to #parse). + for( var j = 0, numTextMatches = textMatches.length; j < numTextMatches; j++ ) { + textMatches[ j ].setOffset( offset + textMatches[ j ].getOffset() ); + } + + matches.push.apply( matches, textMatches ); + } + return matches; + }, + + + /** + * Automatically links URLs, Email addresses, Phone numbers, Twitter + * handles, and Hashtags found in the given chunk of HTML. Does not link + * URLs found within HTML tags. + * + * For instance, if given the text: `You should go to http://www.yahoo.com`, + * then the result will be `You should go to + * <a href="http://www.yahoo.com">http://www.yahoo.com</a>` + * + * This method finds the text around any HTML elements in the input + * `textOrHtml`, which will be the text that is processed. Any original HTML + * elements will be left as-is, as well as the text that is already wrapped + * in anchor (<a>) tags. + * + * @param {String} textOrHtml The HTML or text to autolink matches within + * (depending on if the {@link #urls}, {@link #email}, {@link #phone}, + * {@link #twitter}, and {@link #hashtag} options are enabled). + * @return {String} The HTML, with matches automatically linked. + */ + link : function( textOrHtml ) { + if( !textOrHtml ) { return ""; } // handle `null` and `undefined` + + var matches = this.parse( textOrHtml ), + newHtml = [], + lastIndex = 0; + + for( var i = 0, len = matches.length; i < len; i++ ) { + var match = matches[ i ]; + + newHtml.push( textOrHtml.substring( lastIndex, match.getOffset() ) ); + newHtml.push( this.createMatchReturnVal( match ) ); + + lastIndex = match.getOffset() + match.getMatchedText().length; + } + newHtml.push( textOrHtml.substring( lastIndex ) ); // handle the text after the last match + + return newHtml.join( '' ); + }, + + + /** + * Creates the return string value for a given match in the input string. + * + * This method handles the {@link #replaceFn}, if one was provided. + * + * @private + * @param {Autolinker.match.Match} match The Match object that represents + * the match. + * @return {String} The string that the `match` should be replaced with. + * This is usually the anchor tag string, but may be the `matchStr` itself + * if the match is not to be replaced. + */ + createMatchReturnVal : function( match ) { + // Handle a custom `replaceFn` being provided + var replaceFnResult; + if( this.replaceFn ) { + replaceFnResult = this.replaceFn.call( this, this, match ); // Autolinker instance is the context, and the first arg + } + + if( typeof replaceFnResult === 'string' ) { + return replaceFnResult; // `replaceFn` returned a string, use that + + } else if( replaceFnResult === false ) { + return match.getMatchedText(); // no replacement for the match + + } else if( replaceFnResult instanceof Autolinker.HtmlTag ) { + return replaceFnResult.toAnchorString(); + + } else { // replaceFnResult === true, or no/unknown return value from function + // Perform Autolinker's default anchor tag generation + var anchorTag = match.buildTag(); // returns an Autolinker.HtmlTag instance + + return anchorTag.toAnchorString(); + } + }, + + + /** + * Lazily instantiates and returns the {@link #htmlParser} instance for this + * Autolinker instance. + * + * @protected + * @return {Autolinker.htmlParser.HtmlParser} + */ + getHtmlParser : function() { + var htmlParser = this.htmlParser; + + if( !htmlParser ) { + htmlParser = this.htmlParser = new Autolinker.htmlParser.HtmlParser(); + } + + return htmlParser; + }, + + + /** + * Lazily instantiates and returns the {@link Autolinker.matcher.Matcher} + * instances for this Autolinker instance. + * + * @protected + * @return {Autolinker.matcher.Matcher[]} + */ + getMatchers : function() { + if( !this.matchers ) { + var matchersNs = Autolinker.matcher, + tagBuilder = this.getTagBuilder(); + + var matchers = [ + new matchersNs.Hashtag( { tagBuilder: tagBuilder, serviceName: this.hashtag } ), + new matchersNs.Email( { tagBuilder: tagBuilder } ), + new matchersNs.Phone( { tagBuilder: tagBuilder } ), + new matchersNs.Twitter( { tagBuilder: tagBuilder } ), + new matchersNs.Url( { tagBuilder: tagBuilder, stripPrefix: this.stripPrefix } ) + ]; + + return ( this.matchers = matchers ); + + } else { + return this.matchers; + } + }, + + + /** + * Returns the {@link #tagBuilder} instance for this Autolinker instance, lazily instantiating it + * if it does not yet exist. + * + * This method may be used in a {@link #replaceFn} to generate the {@link Autolinker.HtmlTag HtmlTag} instance that + * Autolinker would normally generate, and then allow for modifications before returning it. For example: + * + * var html = Autolinker.link( "Test google.com", { + * replaceFn : function( autolinker, match ) { + * var tag = autolinker.getTagBuilder().build( match ); // returns an {@link Autolinker.HtmlTag} instance + * tag.setAttr( 'rel', 'nofollow' ); + * + * return tag; + * } + * } ); + * + * // generated html: + * // Test google.com + * + * @return {Autolinker.AnchorTagBuilder} + */ + getTagBuilder : function() { + var tagBuilder = this.tagBuilder; + + if( !tagBuilder ) { + tagBuilder = this.tagBuilder = new Autolinker.AnchorTagBuilder( { + newWindow : this.newWindow, + truncate : this.truncate, + className : this.className + } ); + } + + return tagBuilder; + } + +}; + + +// Autolinker Namespaces + +Autolinker.match = {}; +Autolinker.matcher = {}; +Autolinker.htmlParser = {}; +Autolinker.truncate = {}; + +/*global Autolinker */ +/*jshint eqnull:true, boss:true */ +/** + * @class Autolinker.Util + * @singleton + * + * A few utility methods for Autolinker. + */ +Autolinker.Util = { + + /** + * @property {Function} abstractMethod + * + * A function object which represents an abstract method. + */ + abstractMethod : function() { throw "abstract"; }, + + + /** + * @private + * @property {RegExp} trimRegex + * + * The regular expression used to trim the leading and trailing whitespace + * from a string. + */ + trimRegex : /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + + /** + * Assigns (shallow copies) the properties of `src` onto `dest`. + * + * @param {Object} dest The destination object. + * @param {Object} src The source object. + * @return {Object} The destination object (`dest`) + */ + assign : function( dest, src ) { + for( var prop in src ) { + if( src.hasOwnProperty( prop ) ) { + dest[ prop ] = src[ prop ]; + } + } + + return dest; + }, + + + /** + * Assigns (shallow copies) the properties of `src` onto `dest`, if the + * corresponding property on `dest` === `undefined`. + * + * @param {Object} dest The destination object. + * @param {Object} src The source object. + * @return {Object} The destination object (`dest`) + */ + defaults : function( dest, src ) { + for( var prop in src ) { + if( src.hasOwnProperty( prop ) && dest[ prop ] === undefined ) { + dest[ prop ] = src[ prop ]; + } + } + + return dest; + }, + + + /** + * Extends `superclass` to create a new subclass, adding the `protoProps` to the new subclass's prototype. + * + * @param {Function} superclass The constructor function for the superclass. + * @param {Object} protoProps The methods/properties to add to the subclass's prototype. This may contain the + * special property `constructor`, which will be used as the new subclass's constructor function. + * @return {Function} The new subclass function. + */ + extend : function( superclass, protoProps ) { + var superclassProto = superclass.prototype; + + var F = function() {}; + F.prototype = superclassProto; + + var subclass; + if( protoProps.hasOwnProperty( 'constructor' ) ) { + subclass = protoProps.constructor; + } else { + subclass = function() { superclassProto.constructor.apply( this, arguments ); }; + } + + var subclassProto = subclass.prototype = new F(); // set up prototype chain + subclassProto.constructor = subclass; // fix constructor property + subclassProto.superclass = superclassProto; + + delete protoProps.constructor; // don't re-assign constructor property to the prototype, since a new function may have been created (`subclass`), which is now already there + Autolinker.Util.assign( subclassProto, protoProps ); + + return subclass; + }, + + + /** + * Truncates the `str` at `len - ellipsisChars.length`, and adds the `ellipsisChars` to the + * end of the string (by default, two periods: '..'). If the `str` length does not exceed + * `len`, the string will be returned unchanged. + * + * @param {String} str The string to truncate and add an ellipsis to. + * @param {Number} truncateLen The length to truncate the string at. + * @param {String} [ellipsisChars=..] The ellipsis character(s) to add to the end of `str` + * when truncated. Defaults to '..' + */ + ellipsis : function( str, truncateLen, ellipsisChars ) { + if( str.length > truncateLen ) { + ellipsisChars = ( ellipsisChars == null ) ? '..' : ellipsisChars; + str = str.substring( 0, truncateLen - ellipsisChars.length ) + ellipsisChars; + } + return str; + }, + + + /** + * Supports `Array.prototype.indexOf()` functionality for old IE (IE8 and below). + * + * @param {Array} arr The array to find an element of. + * @param {*} element The element to find in the array, and return the index of. + * @return {Number} The index of the `element`, or -1 if it was not found. + */ + indexOf : function( arr, element ) { + if( Array.prototype.indexOf ) { + return arr.indexOf( element ); + + } else { + for( var i = 0, len = arr.length; i < len; i++ ) { + if( arr[ i ] === element ) return i; + } + return -1; + } + }, + + + /** + * Removes array elements based on a filtering function. Mutates the input + * array. + * + * Using this instead of the ES5 Array.prototype.filter() function, to allow + * Autolinker compatibility with IE8, and also to prevent creating many new + * arrays in memory for filtering. + * + * @param {Array} arr The array to remove elements from. This array is + * mutated. + * @param {Function} fn A function which should return `true` to + * remove an element. + * @return {Array} The mutated input `arr`. + */ + remove : function( arr, fn ) { + for( var i = arr.length - 1; i >= 0; i-- ) { + if( fn( arr[ i ] ) === true ) { + arr.splice( i, 1 ); + } + } + }, + + + /** + * Performs the functionality of what modern browsers do when `String.prototype.split()` is called + * with a regular expression that contains capturing parenthesis. + * + * For example: + * + * // Modern browsers: + * "a,b,c".split( /(,)/ ); // --> [ 'a', ',', 'b', ',', 'c' ] + * + * // Old IE (including IE8): + * "a,b,c".split( /(,)/ ); // --> [ 'a', 'b', 'c' ] + * + * This method emulates the functionality of modern browsers for the old IE case. + * + * @param {String} str The string to split. + * @param {RegExp} splitRegex The regular expression to split the input `str` on. The splitting + * character(s) will be spliced into the array, as in the "modern browsers" example in the + * description of this method. + * Note #1: the supplied regular expression **must** have the 'g' flag specified. + * Note #2: for simplicity's sake, the regular expression does not need + * to contain capturing parenthesis - it will be assumed that any match has them. + * @return {String[]} The split array of strings, with the splitting character(s) included. + */ + splitAndCapture : function( str, splitRegex ) { + if( !splitRegex.global ) throw new Error( "`splitRegex` must have the 'g' flag set" ); + + var result = [], + lastIdx = 0, + match; + + while( match = splitRegex.exec( str ) ) { + result.push( str.substring( lastIdx, match.index ) ); + result.push( match[ 0 ] ); // push the splitting char(s) + + lastIdx = match.index + match[ 0 ].length; + } + result.push( str.substring( lastIdx ) ); + + return result; + }, + + + /** + * Trims the leading and trailing whitespace from a string. + * + * @param {String} str The string to trim. + * @return {String} + */ + trim : function( str ) { + return str.replace( this.trimRegex, '' ); + } + +}; +/*global Autolinker */ +/*jshint boss:true */ +/** + * @class Autolinker.HtmlTag + * @extends Object + * + * Represents an HTML tag, which can be used to easily build/modify HTML tags programmatically. + * + * Autolinker uses this abstraction to create HTML tags, and then write them out as strings. You may also use + * this class in your code, especially within a {@link Autolinker#replaceFn replaceFn}. + * + * ## Examples + * + * Example instantiation: + * + * var tag = new Autolinker.HtmlTag( { + * tagName : 'a', + * attrs : { 'href': 'http://google.com', 'class': 'external-link' }, + * innerHtml : 'Google' + * } ); + * + * tag.toAnchorString(); // Google + * + * // Individual accessor methods + * tag.getTagName(); // 'a' + * tag.getAttr( 'href' ); // 'http://google.com' + * tag.hasClass( 'external-link' ); // true + * + * + * Using mutator methods (which may be used in combination with instantiation config properties): + * + * var tag = new Autolinker.HtmlTag(); + * tag.setTagName( 'a' ); + * tag.setAttr( 'href', 'http://google.com' ); + * tag.addClass( 'external-link' ); + * tag.setInnerHtml( 'Google' ); + * + * tag.getTagName(); // 'a' + * tag.getAttr( 'href' ); // 'http://google.com' + * tag.hasClass( 'external-link' ); // true + * + * tag.toAnchorString(); // Google + * + * + * ## Example use within a {@link Autolinker#replaceFn replaceFn} + * + * var html = Autolinker.link( "Test google.com", { + * replaceFn : function( autolinker, match ) { + * var tag = match.buildTag(); // returns an {@link Autolinker.HtmlTag} instance, configured with the Match's href and anchor text + * tag.setAttr( 'rel', 'nofollow' ); + * + * return tag; + * } + * } ); + * + * // generated html: + * // Test google.com + * + * + * ## Example use with a new tag for the replacement + * + * var html = Autolinker.link( "Test google.com", { + * replaceFn : function( autolinker, match ) { + * var tag = new Autolinker.HtmlTag( { + * tagName : 'button', + * attrs : { 'title': 'Load URL: ' + match.getAnchorHref() }, + * innerHtml : 'Load URL: ' + match.getAnchorText() + * } ); + * + * return tag; + * } + * } ); + * + * // generated html: + * // Test + */ +Autolinker.HtmlTag = Autolinker.Util.extend( Object, { + + /** + * @cfg {String} tagName + * + * The tag name. Ex: 'a', 'button', etc. + * + * Not required at instantiation time, but should be set using {@link #setTagName} before {@link #toAnchorString} + * is executed. + */ + + /** + * @cfg {Object.} attrs + * + * An key/value Object (map) of attributes to create the tag with. The keys are the attribute names, and the + * values are the attribute values. + */ + + /** + * @cfg {String} innerHtml + * + * The inner HTML for the tag. + * + * Note the camel case name on `innerHtml`. Acronyms are camelCased in this utility (such as not to run into the acronym + * naming inconsistency that the DOM developers created with `XMLHttpRequest`). You may alternatively use {@link #innerHTML} + * if you prefer, but this one is recommended. + */ + + /** + * @cfg {String} innerHTML + * + * Alias of {@link #innerHtml}, accepted for consistency with the browser DOM api, but prefer the camelCased version + * for acronym names. + */ + + + /** + * @protected + * @property {RegExp} whitespaceRegex + * + * Regular expression used to match whitespace in a string of CSS classes. + */ + whitespaceRegex : /\s+/, + + + /** + * @constructor + * @param {Object} [cfg] The configuration properties for this class, in an Object (map) + */ + constructor : function( cfg ) { + Autolinker.Util.assign( this, cfg ); + + this.innerHtml = this.innerHtml || this.innerHTML; // accept either the camelCased form or the fully capitalized acronym + }, + + + /** + * Sets the tag name that will be used to generate the tag with. + * + * @param {String} tagName + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + setTagName : function( tagName ) { + this.tagName = tagName; + return this; + }, + + + /** + * Retrieves the tag name. + * + * @return {String} + */ + getTagName : function() { + return this.tagName || ""; + }, + + + /** + * Sets an attribute on the HtmlTag. + * + * @param {String} attrName The attribute name to set. + * @param {String} attrValue The attribute value to set. + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + setAttr : function( attrName, attrValue ) { + var tagAttrs = this.getAttrs(); + tagAttrs[ attrName ] = attrValue; + + return this; + }, + + + /** + * Retrieves an attribute from the HtmlTag. If the attribute does not exist, returns `undefined`. + * + * @param {String} attrName The attribute name to retrieve. + * @return {String} The attribute's value, or `undefined` if it does not exist on the HtmlTag. + */ + getAttr : function( attrName ) { + return this.getAttrs()[ attrName ]; + }, + + + /** + * Sets one or more attributes on the HtmlTag. + * + * @param {Object.} attrs A key/value Object (map) of the attributes to set. + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + setAttrs : function( attrs ) { + var tagAttrs = this.getAttrs(); + Autolinker.Util.assign( tagAttrs, attrs ); + + return this; + }, + + + /** + * Retrieves the attributes Object (map) for the HtmlTag. + * + * @return {Object.} A key/value object of the attributes for the HtmlTag. + */ + getAttrs : function() { + return this.attrs || ( this.attrs = {} ); + }, + + + /** + * Sets the provided `cssClass`, overwriting any current CSS classes on the HtmlTag. + * + * @param {String} cssClass One or more space-separated CSS classes to set (overwrite). + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + setClass : function( cssClass ) { + return this.setAttr( 'class', cssClass ); + }, + + + /** + * Convenience method to add one or more CSS classes to the HtmlTag. Will not add duplicate CSS classes. + * + * @param {String} cssClass One or more space-separated CSS classes to add. + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + addClass : function( cssClass ) { + var classAttr = this.getClass(), + whitespaceRegex = this.whitespaceRegex, + indexOf = Autolinker.Util.indexOf, // to support IE8 and below + classes = ( !classAttr ) ? [] : classAttr.split( whitespaceRegex ), + newClasses = cssClass.split( whitespaceRegex ), + newClass; + + while( newClass = newClasses.shift() ) { + if( indexOf( classes, newClass ) === -1 ) { + classes.push( newClass ); + } + } + + this.getAttrs()[ 'class' ] = classes.join( " " ); + return this; + }, + + + /** + * Convenience method to remove one or more CSS classes from the HtmlTag. + * + * @param {String} cssClass One or more space-separated CSS classes to remove. + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + removeClass : function( cssClass ) { + var classAttr = this.getClass(), + whitespaceRegex = this.whitespaceRegex, + indexOf = Autolinker.Util.indexOf, // to support IE8 and below + classes = ( !classAttr ) ? [] : classAttr.split( whitespaceRegex ), + removeClasses = cssClass.split( whitespaceRegex ), + removeClass; + + while( classes.length && ( removeClass = removeClasses.shift() ) ) { + var idx = indexOf( classes, removeClass ); + if( idx !== -1 ) { + classes.splice( idx, 1 ); + } + } + + this.getAttrs()[ 'class' ] = classes.join( " " ); + return this; + }, + + + /** + * Convenience method to retrieve the CSS class(es) for the HtmlTag, which will each be separated by spaces when + * there are multiple. + * + * @return {String} + */ + getClass : function() { + return this.getAttrs()[ 'class' ] || ""; + }, + + + /** + * Convenience method to check if the tag has a CSS class or not. + * + * @param {String} cssClass The CSS class to check for. + * @return {Boolean} `true` if the HtmlTag has the CSS class, `false` otherwise. + */ + hasClass : function( cssClass ) { + return ( ' ' + this.getClass() + ' ' ).indexOf( ' ' + cssClass + ' ' ) !== -1; + }, + + + /** + * Sets the inner HTML for the tag. + * + * @param {String} html The inner HTML to set. + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + setInnerHtml : function( html ) { + this.innerHtml = html; + + return this; + }, + + + /** + * Retrieves the inner HTML for the tag. + * + * @return {String} + */ + getInnerHtml : function() { + return this.innerHtml || ""; + }, + + + /** + * Override of superclass method used to generate the HTML string for the tag. + * + * @return {String} + */ + toAnchorString : function() { + var tagName = this.getTagName(), + attrsStr = this.buildAttrsStr(); + + attrsStr = ( attrsStr ) ? ' ' + attrsStr : ''; // prepend a space if there are actually attributes + + return [ '<', tagName, attrsStr, '>', this.getInnerHtml(), '' ].join( "" ); + }, + + + /** + * Support method for {@link #toAnchorString}, returns the string space-separated key="value" pairs, used to populate + * the stringified HtmlTag. + * + * @protected + * @return {String} Example return: `attr1="value1" attr2="value2"` + */ + buildAttrsStr : function() { + if( !this.attrs ) return ""; // no `attrs` Object (map) has been set, return empty string + + var attrs = this.getAttrs(), + attrsArr = []; + + for( var prop in attrs ) { + if( attrs.hasOwnProperty( prop ) ) { + attrsArr.push( prop + '="' + attrs[ prop ] + '"' ); + } + } + return attrsArr.join( " " ); + } + +} ); + +/*global Autolinker */ +/** + * @class Autolinker.RegexLib + * @singleton + * + * Builds and stores a library of the common regular expressions used by the + * Autolinker utility. + * + * Other regular expressions may exist ad-hoc, but these are generally the + * regular expressions that are shared between source files. + */ +Autolinker.RegexLib = (function() { + + /** + * The string form of a regular expression that would match all of the + * alphabetic ("letter") chars in the unicode character set when placed in a + * RegExp character class (`[]`). This includes all international alphabetic + * characters. + * + * These would be the characters matched by unicode regex engines `\p{L}` + * escape ("all letters"). + * + * Taken from the XRegExp library: http://xregexp.com/ + * Specifically: http://xregexp.com/v/3.0.0/unicode-categories.js + * + * @private + * @type {String} + */ + var alphaCharsStr = 'A-Za-z\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC'; + + /** + * The string form of a regular expression that would match all of the + * decimal number chars in the unicode character set when placed in a RegExp + * character class (`[]`). + * + * These would be the characters matched by unicode regex engines `\p{Nd}` + * escape ("all decimal numbers") + * + * Taken from the XRegExp library: http://xregexp.com/ + * Specifically: http://xregexp.com/v/3.0.0/unicode-categories.js + * + * @private + * @type {String} + */ + var decimalNumbersStr = '0-9\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0DE6-\u0DEF\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uA9F0-\uA9F9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19'; + + + // See documentation below + var alphaNumericCharsStr = alphaCharsStr + decimalNumbersStr; + + + // See documentation below + var domainNameRegex = new RegExp( '[' + alphaNumericCharsStr + '.\\-]*[' + alphaNumericCharsStr + '\\-]' ); + + + // See documentation below + var tldRegex = /(?:travelersinsurance|sandvikcoromant|kerryproperties|cancerresearch|weatherchannel|kerrylogistics|spreadbetting|international|wolterskluwer|lifeinsurance|construction|pamperedchef|scholarships|versicherung|bridgestone|creditunion|kerryhotels|investments|productions|blackfriday|enterprises|lamborghini|photography|motorcycles|williamhill|playstation|contractors|barclaycard|accountants|redumbrella|engineering|management|telefonica|protection|consulting|tatamotors|creditcard|vlaanderen|schaeffler|associates|properties|foundation|republican|bnpparibas|boehringer|eurovision|extraspace|industries|immobilien|university|technology|volkswagen|healthcare|restaurant|cuisinella|vistaprint|apartments|accountant|travelers|homedepot|institute|vacations|furniture|fresenius|insurance|christmas|bloomberg|solutions|barcelona|firestone|financial|kuokgroup|fairwinds|community|passagens|goldpoint|equipment|lifestyle|yodobashi|aquarelle|marketing|analytics|education|amsterdam|statefarm|melbourne|allfinanz|directory|microsoft|stockholm|montblanc|accenture|lancaster|landrover|everbank|istanbul|graphics|grainger|ipiranga|softbank|attorney|pharmacy|saarland|catering|airforce|yokohama|mortgage|frontier|mutuelle|stcgroup|memorial|pictures|football|symantec|cipriani|ventures|telecity|cityeats|verisign|flsmidth|boutique|cleaning|firmdale|clinique|clothing|redstone|infiniti|deloitte|feedback|services|broadway|plumbing|commbank|training|barclays|exchange|computer|brussels|software|delivery|barefoot|builders|business|bargains|engineer|holdings|download|security|helsinki|lighting|movistar|discount|hdfcbank|supplies|marriott|property|diamonds|capetown|partners|democrat|jpmorgan|bradesco|budapest|rexroth|zuerich|shriram|academy|science|support|youtube|singles|surgery|alibaba|statoil|dentist|schwarz|android|cruises|cricket|digital|markets|starhub|systems|courses|coupons|netbank|country|domains|corsica|network|neustar|realtor|lincoln|limited|schmidt|yamaxun|cooking|contact|auction|spiegel|liaison|leclerc|latrobe|lasalle|abogado|compare|lanxess|exposed|express|company|cologne|college|avianca|lacaixa|fashion|recipes|ferrero|komatsu|storage|wanggou|clubmed|sandvik|fishing|fitness|bauhaus|kitchen|flights|florist|flowers|watches|weather|temasek|samsung|bentley|forsale|channel|theater|frogans|theatre|okinawa|website|tickets|jewelry|gallery|tiffany|iselect|shiksha|brother|organic|wedding|genting|toshiba|origins|philips|hyundai|hotmail|hoteles|hosting|rentals|windows|cartier|bugatti|holiday|careers|whoswho|hitachi|panerai|caravan|reviews|guitars|capital|trading|hamburg|hangout|finance|stream|family|abbott|health|review|travel|report|hermes|hiphop|gratis|career|toyota|hockey|dating|repair|google|social|soccer|reisen|global|otsuka|giving|unicom|casino|photos|center|broker|rocher|orange|bostik|garden|insure|ryukyu|bharti|safety|physio|sakura|oracle|online|jaguar|gallup|piaget|tienda|futbol|pictet|joburg|webcam|berlin|office|juegos|kaufen|chanel|chrome|xihuan|church|tennis|circle|kinder|flickr|bayern|claims|clinic|viajes|nowruz|xperia|norton|yachts|studio|coffee|camera|sanofi|nissan|author|expert|events|comsec|lawyer|tattoo|viking|estate|villas|condos|realty|yandex|energy|emerck|virgin|vision|durban|living|school|coupon|london|taobao|natura|taipei|nagoya|luxury|walter|aramco|sydney|madrid|credit|maison|makeup|schule|market|anquan|direct|design|swatch|suzuki|alsace|vuelos|dental|alipay|voyage|shouji|voting|airtel|mutual|degree|supply|agency|museum|mobily|dealer|monash|select|mormon|active|moscow|racing|datsun|quebec|nissay|rodeo|email|gifts|works|photo|chloe|edeka|cheap|earth|vista|tushu|koeln|glass|shoes|globo|tunes|gmail|nokia|space|kyoto|black|ricoh|seven|lamer|sener|epson|cisco|praxi|trust|citic|crown|shell|lease|green|legal|lexus|ninja|tatar|gripe|nikon|group|video|wales|autos|gucci|party|nexus|guide|linde|adult|parts|amica|lixil|boats|azure|loans|locus|cymru|lotte|lotto|stada|click|poker|quest|dabur|lupin|nadex|paris|faith|dance|canon|place|gives|trade|skype|rocks|mango|cloud|boots|smile|final|swiss|homes|honda|media|horse|cards|deals|watch|bosch|house|pizza|miami|osaka|tours|total|xerox|coach|sucks|style|delta|toray|iinet|tools|money|codes|beats|tokyo|salon|archi|movie|baidu|study|actor|yahoo|store|apple|world|forex|today|bible|tmall|tirol|irish|tires|forum|reise|vegas|vodka|sharp|omega|weber|jetzt|audio|promo|build|bingo|chase|gallo|drive|dubai|rehab|press|solar|sale|beer|bbva|bank|band|auto|sapo|sarl|saxo|audi|asia|arte|arpa|army|yoga|ally|zara|scor|scot|sexy|seat|zero|seek|aero|adac|zone|aarp|maif|meet|meme|menu|surf|mini|mobi|mtpc|porn|desi|star|ltda|name|talk|navy|love|loan|live|link|news|limo|like|spot|life|nico|lidl|lgbt|land|taxi|team|tech|kred|kpmg|sony|song|kiwi|kddi|jprs|jobs|sohu|java|itau|tips|info|immo|icbc|hsbc|town|host|page|toys|here|help|pars|haus|guru|guge|tube|goog|golf|gold|sncf|gmbh|gift|ggee|gent|gbiz|game|vana|pics|fund|ford|ping|pink|fish|film|fast|farm|play|fans|fail|plus|skin|pohl|fage|moda|post|erni|dvag|prod|doha|prof|docs|viva|diet|luxe|site|dell|sina|dclk|show|qpon|date|vote|cyou|voto|read|coop|cool|wang|club|city|chat|cern|cash|reit|rent|casa|cars|care|camp|rest|call|cafe|weir|wien|rich|wiki|buzz|wine|book|bond|room|work|rsvp|shia|ruhr|blue|bing|shaw|bike|safe|xbox|best|pwc|mtn|lds|aig|boo|fyi|nra|nrw|ntt|car|gal|obi|zip|aeg|vin|how|one|ong|onl|dad|ooo|bet|esq|org|htc|bar|uol|ibm|ovh|gdn|ice|icu|uno|gea|ifm|bot|top|wtf|lol|day|pet|eus|wtc|ubs|tvs|aco|ing|ltd|ink|tab|abb|afl|cat|int|pid|pin|bid|cba|gle|com|cbn|ads|man|wed|ceb|gmo|sky|ist|gmx|tui|mba|fan|ski|iwc|app|pro|med|ceo|jcb|jcp|goo|dev|men|aaa|meo|pub|jlc|bom|jll|gop|jmp|mil|got|gov|win|jot|mma|joy|trv|red|cfa|cfd|bio|moe|moi|mom|ren|biz|aws|xin|bbc|dnp|buy|kfh|mov|thd|xyz|fit|kia|rio|rip|kim|dog|vet|nyc|bcg|mtr|bcn|bms|bmw|run|bzh|rwe|tel|stc|axa|kpn|fly|krd|cab|bnl|foo|crs|eat|tci|sap|srl|nec|sas|net|cal|sbs|sfr|sca|scb|csc|edu|new|xxx|hiv|fox|wme|ngo|nhk|vip|sex|frl|lat|yun|law|you|tax|soy|sew|om|ac|hu|se|sc|sg|sh|sb|sa|rw|ru|rs|ro|re|qa|py|si|pw|pt|ps|sj|sk|pr|pn|pm|pl|sl|sm|pk|sn|ph|so|pg|pf|pe|pa|zw|nz|nu|nr|np|no|nl|ni|ng|nf|sr|ne|st|nc|na|mz|my|mx|mw|mv|mu|mt|ms|mr|mq|mp|mo|su|mn|mm|ml|mk|mh|mg|me|sv|md|mc|sx|sy|ma|ly|lv|sz|lu|lt|ls|lr|lk|li|lc|lb|la|tc|kz|td|ky|kw|kr|kp|kn|km|ki|kh|tf|tg|th|kg|ke|jp|jo|jm|je|it|is|ir|tj|tk|tl|tm|iq|tn|to|io|in|im|il|ie|ad|sd|ht|hr|hn|hm|tr|hk|gy|gw|gu|gt|gs|gr|gq|tt|gp|gn|gm|gl|tv|gi|tw|tz|ua|gh|ug|uk|gg|gf|ge|gd|us|uy|uz|va|gb|ga|vc|ve|fr|fo|fm|fk|fj|vg|vi|fi|eu|et|es|er|eg|ee|ec|dz|do|dm|dk|vn|dj|de|cz|cy|cx|cw|vu|cv|cu|cr|co|cn|cm|cl|ck|ci|ch|cg|cf|cd|cc|ca|wf|bz|by|bw|bv|bt|bs|br|bo|bn|bm|bj|bi|ws|bh|bg|bf|be|bd|bb|ba|az|ax|aw|au|at|as|ye|ar|aq|ao|am|al|yt|ai|za|ag|af|ae|zm|id)\b/; + + + return { + + /** + * The string form of a regular expression that would match all of the + * letters and decimal number chars in the unicode character set when placed + * in a RegExp character class (`[]`). + * + * These would be the characters matched by unicode regex engines `[\p{L}\p{Nd}]` + * escape ("all letters and decimal numbers") + * + * @property {String} alphaNumericCharsStr + */ + alphaNumericCharsStr : alphaNumericCharsStr, + + /** + * A regular expression to match domain names of a URL or email address. + * Ex: 'google', 'yahoo', 'some-other-company', etc. + * + * @property {RegExp} domainNameRegex + */ + domainNameRegex : domainNameRegex, + + /** + * A regular expression to match top level domains (TLDs) for a URL or + * email address. Ex: 'com', 'org', 'net', etc. + * + * @property {RegExp} tldRegex + */ + tldRegex : tldRegex + + }; + + +}() ); +/*global Autolinker */ +/*jshint sub:true */ +/** + * @protected + * @class Autolinker.AnchorTagBuilder + * @extends Object + * + * Builds anchor (<a>) tags for the Autolinker utility when a match is + * found. + * + * Normally this class is instantiated, configured, and used internally by an + * {@link Autolinker} instance, but may actually be retrieved in a {@link Autolinker#replaceFn replaceFn} + * to create {@link Autolinker.HtmlTag HtmlTag} instances which may be modified + * before returning from the {@link Autolinker#replaceFn replaceFn}. For + * example: + * + * var html = Autolinker.link( "Test google.com", { + * replaceFn : function( autolinker, match ) { + * var tag = autolinker.getTagBuilder().build( match ); // returns an {@link Autolinker.HtmlTag} instance + * tag.setAttr( 'rel', 'nofollow' ); + * + * return tag; + * } + * } ); + * + * // generated html: + * // Test google.com + */ +Autolinker.AnchorTagBuilder = Autolinker.Util.extend( Object, { + + /** + * @cfg {Boolean} newWindow + * @inheritdoc Autolinker#newWindow + */ + + /** + * @cfg {Object} truncate + * @inheritdoc Autolinker#truncate + */ + + /** + * @cfg {String} className + * @inheritdoc Autolinker#className + */ + + + /** + * @constructor + * @param {Object} [cfg] The configuration options for the AnchorTagBuilder instance, specified in an Object (map). + */ + constructor : function( cfg ) { + Autolinker.Util.assign( this, cfg ); + }, + + + /** + * Generates the actual anchor (<a>) tag to use in place of the + * matched text, via its `match` object. + * + * @param {Autolinker.match.Match} match The Match instance to generate an + * anchor tag from. + * @return {Autolinker.HtmlTag} The HtmlTag instance for the anchor tag. + */ + build : function( match ) { + return new Autolinker.HtmlTag( { + tagName : 'a', + attrs : this.createAttrs( match.getType(), match.getAnchorHref() ), + innerHtml : this.processAnchorText( match.getAnchorText() ) + } ); + }, + + + /** + * Creates the Object (map) of the HTML attributes for the anchor (<a>) + * tag being generated. + * + * @protected + * @param {"url"/"email"/"phone"/"twitter"/"hashtag"} matchType The type of + * match that an anchor tag is being generated for. + * @param {String} anchorHref The href for the anchor tag. + * @return {Object} A key/value Object (map) of the anchor tag's attributes. + */ + createAttrs : function( matchType, anchorHref ) { + var attrs = { + 'href' : anchorHref // we'll always have the `href` attribute + }; + + var cssClass = this.createCssClass( matchType ); + if( cssClass ) { + attrs[ 'class' ] = cssClass; + } + if( this.newWindow ) { + attrs[ 'target' ] = "_blank"; + attrs[ 'rel' ] = "noopener noreferrer"; + } + + return attrs; + }, + + + /** + * Creates the CSS class that will be used for a given anchor tag, based on + * the `matchType` and the {@link #className} config. + * + * @private + * @param {"url"/"email"/"phone"/"twitter"/"hashtag"} matchType The type of + * match that an anchor tag is being generated for. + * @return {String} The CSS class string for the link. Example return: + * "myLink myLink-url". If no {@link #className} was configured, returns + * an empty string. + */ + createCssClass : function( matchType ) { + var className = this.className; + + if( !className ) + return ""; + else + return className + " " + className + "-" + matchType; // ex: "myLink myLink-url", "myLink myLink-email", "myLink myLink-phone", "myLink myLink-twitter", or "myLink myLink-hashtag" + }, + + + /** + * Processes the `anchorText` by truncating the text according to the + * {@link #truncate} config. + * + * @private + * @param {String} anchorText The anchor tag's text (i.e. what will be + * displayed). + * @return {String} The processed `anchorText`. + */ + processAnchorText : function( anchorText ) { + anchorText = this.doTruncate( anchorText ); + + return anchorText; + }, + + + /** + * Performs the truncation of the `anchorText` based on the {@link #truncate} + * option. If the `anchorText` is longer than the length specified by the + * {@link #truncate} option, the truncation is performed based on the + * `location` property. See {@link #truncate} for details. + * + * @private + * @param {String} anchorText The anchor tag's text (i.e. what will be + * displayed). + * @return {String} The truncated anchor text. + */ + doTruncate : function( anchorText ) { + var truncate = this.truncate; + if( !truncate || !truncate.length ) return anchorText; + + var truncateLength = truncate.length, + truncateLocation = truncate.location; + + if( truncateLocation === 'smart' ) { + return Autolinker.truncate.TruncateSmart( anchorText, truncateLength, '..' ); + + } else if( truncateLocation === 'middle' ) { + return Autolinker.truncate.TruncateMiddle( anchorText, truncateLength, '..' ); + + } else { + return Autolinker.truncate.TruncateEnd( anchorText, truncateLength, '..' ); + } + } + +} ); + +/*global Autolinker */ +/** + * @class Autolinker.htmlParser.HtmlParser + * @extends Object + * + * An HTML parser implementation which simply walks an HTML string and returns an array of + * {@link Autolinker.htmlParser.HtmlNode HtmlNodes} that represent the basic HTML structure of the input string. + * + * Autolinker uses this to only link URLs/emails/Twitter handles within text nodes, effectively ignoring / "walking + * around" HTML tags. + */ +Autolinker.htmlParser.HtmlParser = Autolinker.Util.extend( Object, { + + /** + * @private + * @property {RegExp} htmlRegex + * + * The regular expression used to pull out HTML tags from a string. Handles namespaced HTML tags and + * attribute names, as specified by http://www.w3.org/TR/html-markup/syntax.html. + * + * Capturing groups: + * + * 1. The "!DOCTYPE" tag name, if a tag is a <!DOCTYPE> tag. + * 2. If it is an end tag, this group will have the '/'. + * 3. If it is a comment tag, this group will hold the comment text (i.e. + * the text inside the `<!--` and `-->`. + * 4. The tag name for all tags (other than the <!DOCTYPE> tag) + */ + htmlRegex : (function() { + var commentTagRegex = /!--([\s\S]+?)--/, + tagNameRegex = /[0-9a-zA-Z][0-9a-zA-Z:]*/, + attrNameRegex = /[^\s"'>\/=\x00-\x1F\x7F]+/, // the unicode range accounts for excluding control chars, and the delete char + attrValueRegex = /(?:"[^"]*?"|'[^']*?'|[^'"=<>`\s]+)/, // double quoted, single quoted, or unquoted attribute values + nameEqualsValueRegex = attrNameRegex.source + '(?:\\s*=\\s*' + attrValueRegex.source + ')?'; // optional '=[value]' + + return new RegExp( [ + // for tag. Ex: ) + '(?:', + '<(!DOCTYPE)', // *** Capturing Group 1 - If it's a doctype tag + + // Zero or more attributes following the tag name + '(?:', + '\\s+', // one or more whitespace chars before an attribute + + // Either: + // A. attr="value", or + // B. "value" alone (To cover example doctype tag: ) + '(?:', nameEqualsValueRegex, '|', attrValueRegex.source + ')', + ')*', + '>', + ')', + + '|', + + // All other HTML tags (i.e. tags that are not ) + '(?:', + '<(/)?', // Beginning of a tag or comment. Either '<' for a start tag, or '' + + ')', + ')', + '>', + ')' + ].join( "" ), 'gi' ); + } )(), + + /** + * @private + * @property {RegExp} htmlCharacterEntitiesRegex + * + * The regular expression that matches common HTML character entities. + * + * Ignoring & as it could be part of a query string -- handling it separately. + */ + htmlCharacterEntitiesRegex: /( | |<|<|>|>|"|"|')/gi, + + + /** + * Parses an HTML string and returns a simple array of {@link Autolinker.htmlParser.HtmlNode HtmlNodes} + * to represent the HTML structure of the input string. + * + * @param {String} html The HTML to parse. + * @return {Autolinker.htmlParser.HtmlNode[]} + */ + parse : function( html ) { + var htmlRegex = this.htmlRegex, + currentResult, + lastIndex = 0, + textAndEntityNodes, + nodes = []; // will be the result of the method + + while( ( currentResult = htmlRegex.exec( html ) ) !== null ) { + var tagText = currentResult[ 0 ], + commentText = currentResult[ 3 ], // if we've matched a comment + tagName = currentResult[ 1 ] || currentResult[ 4 ], // The tag (ex: "!DOCTYPE"), or another tag (ex: "a" or "img") + isClosingTag = !!currentResult[ 2 ], + offset = currentResult.index, + inBetweenTagsText = html.substring( lastIndex, offset ); + + // Push TextNodes and EntityNodes for any text found between tags + if( inBetweenTagsText ) { + textAndEntityNodes = this.parseTextAndEntityNodes( lastIndex, inBetweenTagsText ); + nodes.push.apply( nodes, textAndEntityNodes ); + } + + // Push the CommentNode or ElementNode + if( commentText ) { + nodes.push( this.createCommentNode( offset, tagText, commentText ) ); + } else { + nodes.push( this.createElementNode( offset, tagText, tagName, isClosingTag ) ); + } + + lastIndex = offset + tagText.length; + } + + // Process any remaining text after the last HTML element. Will process all of the text if there were no HTML elements. + if( lastIndex < html.length ) { + var text = html.substring( lastIndex ); + + // Push TextNodes and EntityNodes for any text found between tags + if( text ) { + textAndEntityNodes = this.parseTextAndEntityNodes( lastIndex, text ); + nodes.push.apply( nodes, textAndEntityNodes ); + } + } + + return nodes; + }, + + + /** + * Parses text and HTML entity nodes from a given string. The input string + * should not have any HTML tags (elements) within it. + * + * @private + * @param {Number} offset The offset of the text node match within the + * original HTML string. + * @param {String} text The string of text to parse. This is from an HTML + * text node. + * @return {Autolinker.htmlParser.HtmlNode[]} An array of HtmlNodes to + * represent the {@link Autolinker.htmlParser.TextNode TextNodes} and + * {@link Autolinker.htmlParser.EntityNode EntityNodes} found. + */ + parseTextAndEntityNodes : function( offset, text ) { + var nodes = [], + textAndEntityTokens = Autolinker.Util.splitAndCapture( text, this.htmlCharacterEntitiesRegex ); // split at HTML entities, but include the HTML entities in the results array + + // Every even numbered token is a TextNode, and every odd numbered token is an EntityNode + // For example: an input `text` of "Test "this" today" would turn into the + // `textAndEntityTokens`: [ 'Test ', '"', 'this', '"', ' today' ] + for( var i = 0, len = textAndEntityTokens.length; i < len; i += 2 ) { + var textToken = textAndEntityTokens[ i ], + entityToken = textAndEntityTokens[ i + 1 ]; + + if( textToken ) { + nodes.push( this.createTextNode( offset, textToken ) ); + offset += textToken.length; + } + if( entityToken ) { + nodes.push( this.createEntityNode( offset, entityToken ) ); + offset += entityToken.length; + } + } + return nodes; + }, + + + /** + * Factory method to create an {@link Autolinker.htmlParser.CommentNode CommentNode}. + * + * @private + * @param {Number} offset The offset of the match within the original HTML + * string. + * @param {String} tagText The full text of the tag (comment) that was + * matched, including its <!-- and -->. + * @param {String} commentText The full text of the comment that was matched. + */ + createCommentNode : function( offset, tagText, commentText ) { + return new Autolinker.htmlParser.CommentNode( { + offset : offset, + text : tagText, + comment: Autolinker.Util.trim( commentText ) + } ); + }, + + + /** + * Factory method to create an {@link Autolinker.htmlParser.ElementNode ElementNode}. + * + * @private + * @param {Number} offset The offset of the match within the original HTML + * string. + * @param {String} tagText The full text of the tag (element) that was + * matched, including its attributes. + * @param {String} tagName The name of the tag. Ex: An <img> tag would + * be passed to this method as "img". + * @param {Boolean} isClosingTag `true` if it's a closing tag, false + * otherwise. + * @return {Autolinker.htmlParser.ElementNode} + */ + createElementNode : function( offset, tagText, tagName, isClosingTag ) { + return new Autolinker.htmlParser.ElementNode( { + offset : offset, + text : tagText, + tagName : tagName.toLowerCase(), + closing : isClosingTag + } ); + }, + + + /** + * Factory method to create a {@link Autolinker.htmlParser.EntityNode EntityNode}. + * + * @private + * @param {Number} offset The offset of the match within the original HTML + * string. + * @param {String} text The text that was matched for the HTML entity (such + * as '&nbsp;'). + * @return {Autolinker.htmlParser.EntityNode} + */ + createEntityNode : function( offset, text ) { + return new Autolinker.htmlParser.EntityNode( { offset: offset, text: text } ); + }, + + + /** + * Factory method to create a {@link Autolinker.htmlParser.TextNode TextNode}. + * + * @private + * @param {Number} offset The offset of the match within the original HTML + * string. + * @param {String} text The text that was matched. + * @return {Autolinker.htmlParser.TextNode} + */ + createTextNode : function( offset, text ) { + return new Autolinker.htmlParser.TextNode( { offset: offset, text: text } ); + } + +} ); +/*global Autolinker */ +/** + * @abstract + * @class Autolinker.htmlParser.HtmlNode + * + * Represents an HTML node found in an input string. An HTML node is one of the + * following: + * + * 1. An {@link Autolinker.htmlParser.ElementNode ElementNode}, which represents + * HTML tags. + * 2. A {@link Autolinker.htmlParser.CommentNode CommentNode}, which represents + * HTML comments. + * 3. A {@link Autolinker.htmlParser.TextNode TextNode}, which represents text + * outside or within HTML tags. + * 4. A {@link Autolinker.htmlParser.EntityNode EntityNode}, which represents + * one of the known HTML entities that Autolinker looks for. This includes + * common ones such as &quot; and &nbsp; + */ +Autolinker.htmlParser.HtmlNode = Autolinker.Util.extend( Object, { + + /** + * @cfg {Number} offset (required) + * + * The offset of the HTML node in the original text that was parsed. + */ + offset : undefined, + + /** + * @cfg {String} text (required) + * + * The text that was matched for the HtmlNode. + * + * - In the case of an {@link Autolinker.htmlParser.ElementNode ElementNode}, + * this will be the tag's text. + * - In the case of an {@link Autolinker.htmlParser.CommentNode CommentNode}, + * this will be the comment's text. + * - In the case of a {@link Autolinker.htmlParser.TextNode TextNode}, this + * will be the text itself. + * - In the case of a {@link Autolinker.htmlParser.EntityNode EntityNode}, + * this will be the text of the HTML entity. + */ + text : undefined, + + + /** + * @constructor + * @param {Object} cfg The configuration properties for the Match instance, + * specified in an Object (map). + */ + constructor : function( cfg ) { + Autolinker.Util.assign( this, cfg ); + + if( this.offset == null ) throw new Error( '`offset` cfg required' ); + if( this.text == null ) throw new Error( '`text` cfg required' ); + }, + + + /** + * Returns a string name for the type of node that this class represents. + * + * @abstract + * @return {String} + */ + getType : Autolinker.Util.abstractMethod, + + + /** + * Retrieves the {@link #offset} of the HtmlNode. This is the offset of the + * HTML node in the original string that was parsed. + * + * @return {Number} + */ + getOffset : function() { + return this.offset; + }, + + + /** + * Retrieves the {@link #text} for the HtmlNode. + * + * @return {String} + */ + getText : function() { + return this.text; + } + +} ); +/*global Autolinker */ +/** + * @class Autolinker.htmlParser.CommentNode + * @extends Autolinker.htmlParser.HtmlNode + * + * Represents an HTML comment node that has been parsed by the + * {@link Autolinker.htmlParser.HtmlParser}. + * + * See this class's superclass ({@link Autolinker.htmlParser.HtmlNode}) for more + * details. + */ +Autolinker.htmlParser.CommentNode = Autolinker.Util.extend( Autolinker.htmlParser.HtmlNode, { + + /** + * @cfg {String} comment (required) + * + * The text inside the comment tag. This text is stripped of any leading or + * trailing whitespace. + */ + comment : '', + + + /** + * Returns a string name for the type of node that this class represents. + * + * @return {String} + */ + getType : function() { + return 'comment'; + }, + + + /** + * Returns the comment inside the comment tag. + * + * @return {String} + */ + getComment : function() { + return this.comment; + } + +} ); +/*global Autolinker */ +/** + * @class Autolinker.htmlParser.ElementNode + * @extends Autolinker.htmlParser.HtmlNode + * + * Represents an HTML element node that has been parsed by the {@link Autolinker.htmlParser.HtmlParser}. + * + * See this class's superclass ({@link Autolinker.htmlParser.HtmlNode}) for more + * details. + */ +Autolinker.htmlParser.ElementNode = Autolinker.Util.extend( Autolinker.htmlParser.HtmlNode, { + + /** + * @cfg {String} tagName (required) + * + * The name of the tag that was matched. + */ + tagName : '', + + /** + * @cfg {Boolean} closing (required) + * + * `true` if the element (tag) is a closing tag, `false` if its an opening + * tag. + */ + closing : false, + + + /** + * Returns a string name for the type of node that this class represents. + * + * @return {String} + */ + getType : function() { + return 'element'; + }, + + + /** + * Returns the HTML element's (tag's) name. Ex: for an <img> tag, + * returns "img". + * + * @return {String} + */ + getTagName : function() { + return this.tagName; + }, + + + /** + * Determines if the HTML element (tag) is a closing tag. Ex: <div> + * returns `false`, while </div> returns `true`. + * + * @return {Boolean} + */ + isClosing : function() { + return this.closing; + } + +} ); +/*global Autolinker */ +/** + * @class Autolinker.htmlParser.EntityNode + * @extends Autolinker.htmlParser.HtmlNode + * + * Represents a known HTML entity node that has been parsed by the {@link Autolinker.htmlParser.HtmlParser}. + * Ex: '&nbsp;', or '&#160;' (which will be retrievable from the {@link #getText} + * method. + * + * Note that this class will only be returned from the HtmlParser for the set of + * checked HTML entity nodes defined by the {@link Autolinker.htmlParser.HtmlParser#htmlCharacterEntitiesRegex}. + * + * See this class's superclass ({@link Autolinker.htmlParser.HtmlNode}) for more + * details. + */ +Autolinker.htmlParser.EntityNode = Autolinker.Util.extend( Autolinker.htmlParser.HtmlNode, { + + /** + * Returns a string name for the type of node that this class represents. + * + * @return {String} + */ + getType : function() { + return 'entity'; + } + +} ); +/*global Autolinker */ +/** + * @class Autolinker.htmlParser.TextNode + * @extends Autolinker.htmlParser.HtmlNode + * + * Represents a text node that has been parsed by the {@link Autolinker.htmlParser.HtmlParser}. + * + * See this class's superclass ({@link Autolinker.htmlParser.HtmlNode}) for more + * details. + */ +Autolinker.htmlParser.TextNode = Autolinker.Util.extend( Autolinker.htmlParser.HtmlNode, { + + /** + * Returns a string name for the type of node that this class represents. + * + * @return {String} + */ + getType : function() { + return 'text'; + } + +} ); +/*global Autolinker */ +/** + * @abstract + * @class Autolinker.match.Match + * + * Represents a match found in an input string which should be Autolinked. A Match object is what is provided in a + * {@link Autolinker#replaceFn replaceFn}, and may be used to query for details about the match. + * + * For example: + * + * var input = "..."; // string with URLs, Email Addresses, and Twitter Handles + * + * var linkedText = Autolinker.link( input, { + * replaceFn : function( autolinker, match ) { + * console.log( "href = ", match.getAnchorHref() ); + * console.log( "text = ", match.getAnchorText() ); + * + * switch( match.getType() ) { + * case 'url' : + * console.log( "url: ", match.getUrl() ); + * + * case 'email' : + * console.log( "email: ", match.getEmail() ); + * + * case 'twitter' : + * console.log( "twitter: ", match.getTwitterHandle() ); + * } + * } + * } ); + * + * See the {@link Autolinker} class for more details on using the {@link Autolinker#replaceFn replaceFn}. + */ +Autolinker.match.Match = Autolinker.Util.extend( Object, { + + /** + * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required) + * + * Reference to the AnchorTagBuilder instance to use to generate an anchor + * tag for the Match. + */ + + /** + * @cfg {String} matchedText (required) + * + * The original text that was matched by the {@link Autolinker.matcher.Matcher}. + */ + + /** + * @cfg {Number} offset (required) + * + * The offset of where the match was made in the input string. + */ + + + /** + * @constructor + * @param {Object} cfg The configuration properties for the Match + * instance, specified in an Object (map). + */ + constructor : function( cfg ) { + if( cfg.tagBuilder == null ) throw new Error( '`tagBuilder` cfg required' ); + if( cfg.matchedText == null ) throw new Error( '`matchedText` cfg required' ); + if( cfg.offset == null ) throw new Error( '`offset` cfg required' ); + + this.tagBuilder = cfg.tagBuilder; + this.matchedText = cfg.matchedText; + this.offset = cfg.offset; + }, + + + /** + * Returns a string name for the type of match that this class represents. + * + * @abstract + * @return {String} + */ + getType : Autolinker.Util.abstractMethod, + + + /** + * Returns the original text that was matched. + * + * @return {String} + */ + getMatchedText : function() { + return this.matchedText; + }, + + + /** + * Sets the {@link #offset} of where the match was made in the input string. + * + * A {@link Autolinker.matcher.Matcher} will be fed only HTML text nodes, + * and will therefore set an original offset that is relative to the HTML + * text node itself. However, we want this offset to be relative to the full + * HTML input string, and thus if using {@link Autolinker#parse} (rather + * than calling a {@link Autolinker.matcher.Matcher} directly), then this + * offset is corrected after the Matcher itself has done its job. + * + * @param {Number} offset + */ + setOffset : function( offset ) { + this.offset = offset; + }, + + + /** + * Returns the offset of where the match was made in the input string. This + * is the 0-based index of the match. + * + * @return {Number} + */ + getOffset : function() { + return this.offset; + }, + + + /** + * Returns the anchor href that should be generated for the match. + * + * @abstract + * @return {String} + */ + getAnchorHref : Autolinker.Util.abstractMethod, + + + /** + * Returns the anchor text that should be generated for the match. + * + * @abstract + * @return {String} + */ + getAnchorText : Autolinker.Util.abstractMethod, + + + /** + * Builds and returns an {@link Autolinker.HtmlTag} instance based on the + * Match. + * + * This can be used to easily generate anchor tags from matches, and either + * return their HTML string, or modify them before doing so. + * + * Example Usage: + * + * var tag = match.buildTag(); + * tag.addClass( 'cordova-link' ); + * tag.setAttr( 'target', '_system' ); + * + * tag.toAnchorString(); // Google + */ + buildTag : function() { + return this.tagBuilder.build( this ); + } + +} ); +/*global Autolinker */ +/** + * @class Autolinker.match.Email + * @extends Autolinker.match.Match + * + * Represents a Email match found in an input string which should be Autolinked. + * + * See this class's superclass ({@link Autolinker.match.Match}) for more details. + */ +Autolinker.match.Email = Autolinker.Util.extend( Autolinker.match.Match, { + + /** + * @cfg {String} email (required) + * + * The email address that was matched. + */ + + + /** + * @constructor + * @param {Object} cfg The configuration properties for the Match + * instance, specified in an Object (map). + */ + constructor : function( cfg ) { + Autolinker.match.Match.prototype.constructor.call( this, cfg ); + + if( !cfg.email ) throw new Error( '`email` cfg required' ); + + this.email = cfg.email; + }, + + + /** + * Returns a string name for the type of match that this class represents. + * + * @return {String} + */ + getType : function() { + return 'email'; + }, + + + /** + * Returns the email address that was matched. + * + * @return {String} + */ + getEmail : function() { + return this.email; + }, + + + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + getAnchorHref : function() { + return 'mailto:' + this.email; + }, + + + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + getAnchorText : function() { + return this.email; + } + +} ); +/*global Autolinker */ +/** + * @class Autolinker.match.Hashtag + * @extends Autolinker.match.Match + * + * Represents a Hashtag match found in an input string which should be + * Autolinked. + * + * See this class's superclass ({@link Autolinker.match.Match}) for more + * details. + */ +Autolinker.match.Hashtag = Autolinker.Util.extend( Autolinker.match.Match, { + + /** + * @cfg {String} serviceName + * + * The service to point hashtag matches to. See {@link Autolinker#hashtag} + * for available values. + */ + + /** + * @cfg {String} hashtag (required) + * + * The Hashtag that was matched, without the '#'. + */ + + + /** + * @constructor + * @param {Object} cfg The configuration properties for the Match + * instance, specified in an Object (map). + */ + constructor : function( cfg ) { + Autolinker.match.Match.prototype.constructor.call( this, cfg ); + + // TODO: if( !serviceName ) throw new Error( '`serviceName` cfg required' ); + if( !cfg.hashtag ) throw new Error( '`hashtag` cfg required' ); + + this.serviceName = cfg.serviceName; + this.hashtag = cfg.hashtag; + }, + + + /** + * Returns the type of match that this class represents. + * + * @return {String} + */ + getType : function() { + return 'hashtag'; + }, + + + /** + * Returns the configured {@link #serviceName} to point the Hashtag to. + * Ex: 'facebook', 'twitter'. + * + * @return {String} + */ + getServiceName : function() { + return this.serviceName; + }, + + + /** + * Returns the matched hashtag, without the '#' character. + * + * @return {String} + */ + getHashtag : function() { + return this.hashtag; + }, + + + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + getAnchorHref : function() { + var serviceName = this.serviceName, + hashtag = this.hashtag; + + switch( serviceName ) { + case 'twitter' : + return 'https://twitter.com/hashtag/' + hashtag; + case 'facebook' : + return 'https://www.facebook.com/hashtag/' + hashtag; + case 'instagram' : + return 'https://instagram.com/explore/tags/' + hashtag; + + default : // Shouldn't happen because Autolinker's constructor should block any invalid values, but just in case. + throw new Error( 'Unknown service name to point hashtag to: ', serviceName ); + } + }, + + + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + getAnchorText : function() { + return '#' + this.hashtag; + } + +} ); + +/*global Autolinker */ +/** + * @class Autolinker.match.Phone + * @extends Autolinker.match.Match + * + * Represents a Phone number match found in an input string which should be + * Autolinked. + * + * See this class's superclass ({@link Autolinker.match.Match}) for more + * details. + */ +Autolinker.match.Phone = Autolinker.Util.extend( Autolinker.match.Match, { + + /** + * @protected + * @property {String} number (required) + * + * The phone number that was matched, without any delimiter characters. + * + * Note: This is a string to allow for prefixed 0's. + */ + + /** + * @protected + * @property {Boolean} plusSign (required) + * + * `true` if the matched phone number started with a '+' sign. We'll include + * it in the `tel:` URL if so, as this is needed for international numbers. + * + * Ex: '+1 (123) 456 7879' + */ + + + /** + * @constructor + * @param {Object} cfg The configuration properties for the Match + * instance, specified in an Object (map). + */ + constructor : function( cfg ) { + Autolinker.match.Match.prototype.constructor.call( this, cfg ); + + if( !cfg.number ) throw new Error( '`number` cfg required' ); + if( cfg.plusSign == null ) throw new Error( '`plusSign` cfg required' ); + + this.number = cfg.number; + this.plusSign = cfg.plusSign; + }, + + + /** + * Returns a string name for the type of match that this class represents. + * + * @return {String} + */ + getType : function() { + return 'phone'; + }, + + + /** + * Returns the phone number that was matched as a string, without any + * delimiter characters. + * + * Note: This is a string to allow for prefixed 0's. + * + * @return {String} + */ + getNumber: function() { + return this.number; + }, + + + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + getAnchorHref : function() { + return 'tel:' + ( this.plusSign ? '+' : '' ) + this.number; + }, + + + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + getAnchorText : function() { + return this.matchedText; + } + +} ); + +/*global Autolinker */ +/** + * @class Autolinker.match.Twitter + * @extends Autolinker.match.Match + * + * Represents a Twitter match found in an input string which should be Autolinked. + * + * See this class's superclass ({@link Autolinker.match.Match}) for more details. + */ +Autolinker.match.Twitter = Autolinker.Util.extend( Autolinker.match.Match, { + + /** + * @cfg {String} twitterHandle (required) + * + * The Twitter handle that was matched, without the '@' character. + */ + + + /** + * @constructor + * @param {Object} cfg The configuration properties for the Match + * instance, specified in an Object (map). + */ + constructor : function( cfg) { + Autolinker.match.Match.prototype.constructor.call( this, cfg ); + + if( !cfg.twitterHandle ) throw new Error( '`twitterHandle` cfg required' ); + + this.twitterHandle = cfg.twitterHandle; + }, + + + /** + * Returns the type of match that this class represents. + * + * @return {String} + */ + getType : function() { + return 'twitter'; + }, + + + /** + * Returns the twitter handle, without the '@' character. + * + * @return {String} + */ + getTwitterHandle : function() { + return this.twitterHandle; + }, + + + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + getAnchorHref : function() { + return 'https://twitter.com/' + this.twitterHandle; + }, + + + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + getAnchorText : function() { + return '@' + this.twitterHandle; + } + +} ); +/*global Autolinker */ +/** + * @class Autolinker.match.Url + * @extends Autolinker.match.Match + * + * Represents a Url match found in an input string which should be Autolinked. + * + * See this class's superclass ({@link Autolinker.match.Match}) for more details. + */ +Autolinker.match.Url = Autolinker.Util.extend( Autolinker.match.Match, { + + /** + * @cfg {String} url (required) + * + * The url that was matched. + */ + + /** + * @cfg {"scheme"/"www"/"tld"} urlMatchType (required) + * + * The type of URL match that this class represents. This helps to determine + * if the match was made in the original text with a prefixed scheme (ex: + * 'http://www.google.com'), a prefixed 'www' (ex: 'www.google.com'), or + * was matched by a known top-level domain (ex: 'google.com'). + */ + + /** + * @cfg {Boolean} protocolUrlMatch (required) + * + * `true` if the URL is a match which already has a protocol (i.e. + * 'http://'), `false` if the match was from a 'www' or known TLD match. + */ + + /** + * @cfg {Boolean} protocolRelativeMatch (required) + * + * `true` if the URL is a protocol-relative match. A protocol-relative match + * is a URL that starts with '//', and will be either http:// or https:// + * based on the protocol that the site is loaded under. + */ + + /** + * @cfg {Boolean} stripPrefix (required) + * @inheritdoc Autolinker#cfg-stripPrefix + */ + + + /** + * @constructor + * @param {Object} cfg The configuration properties for the Match + * instance, specified in an Object (map). + */ + constructor : function( cfg ) { + Autolinker.match.Match.prototype.constructor.call( this, cfg ); + + if( cfg.urlMatchType !== 'scheme' && cfg.urlMatchType !== 'www' && cfg.urlMatchType !== 'tld' ) throw new Error( '`urlMatchType` cfg must be one of: "scheme", "www", or "tld"' ); + if( !cfg.url ) throw new Error( '`url` cfg required' ); + if( cfg.protocolUrlMatch == null ) throw new Error( '`protocolUrlMatch` cfg required' ); + if( cfg.protocolRelativeMatch == null ) throw new Error( '`protocolRelativeMatch` cfg required' ); + if( cfg.stripPrefix == null ) throw new Error( '`stripPrefix` cfg required' ); + + this.urlMatchType = cfg.urlMatchType; + this.url = cfg.url; + this.protocolUrlMatch = cfg.protocolUrlMatch; + this.protocolRelativeMatch = cfg.protocolRelativeMatch; + this.stripPrefix = cfg.stripPrefix; + }, + + + /** + * @private + * @property {RegExp} urlPrefixRegex + * + * A regular expression used to remove the 'http://' or 'https://' and/or the 'www.' from URLs. + */ + urlPrefixRegex: /^(https?:\/\/)?(www\.)?/i, + + /** + * @private + * @property {RegExp} protocolRelativeRegex + * + * The regular expression used to remove the protocol-relative '//' from the {@link #url} string, for purposes + * of {@link #getAnchorText}. A protocol-relative URL is, for example, "//yahoo.com" + */ + protocolRelativeRegex : /^\/\//, + + /** + * @private + * @property {Boolean} protocolPrepended + * + * Will be set to `true` if the 'http://' protocol has been prepended to the {@link #url} (because the + * {@link #url} did not have a protocol) + */ + protocolPrepended : false, + + + /** + * Returns a string name for the type of match that this class represents. + * + * @return {String} + */ + getType : function() { + return 'url'; + }, + + + /** + * Returns a string name for the type of URL match that this class + * represents. + * + * This helps to determine if the match was made in the original text with a + * prefixed scheme (ex: 'http://www.google.com'), a prefixed 'www' (ex: + * 'www.google.com'), or was matched by a known top-level domain (ex: + * 'google.com'). + * + * @return {"scheme"/"www"/"tld"} + */ + getUrlMatchType : function() { + return this.urlMatchType; + }, + + + /** + * Returns the url that was matched, assuming the protocol to be 'http://' if the original + * match was missing a protocol. + * + * @return {String} + */ + getUrl : function() { + var url = this.url; + + // if the url string doesn't begin with a protocol, assume 'http://' + if( !this.protocolRelativeMatch && !this.protocolUrlMatch && !this.protocolPrepended ) { + url = this.url = 'http://' + url; + + this.protocolPrepended = true; + } + + return url; + }, + + + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + getAnchorHref : function() { + var url = this.getUrl(); + + return url.replace( /&/g, '&' ); // any &'s in the URL should be converted back to '&' if they were displayed as & in the source html + }, + + + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + getAnchorText : function() { + var anchorText = this.getMatchedText(); + + if( this.protocolRelativeMatch ) { + // Strip off any protocol-relative '//' from the anchor text + anchorText = this.stripProtocolRelativePrefix( anchorText ); + } + if( this.stripPrefix ) { + anchorText = this.stripUrlPrefix( anchorText ); + } + anchorText = this.removeTrailingSlash( anchorText ); // remove trailing slash, if there is one + + return anchorText; + }, + + + // --------------------------------------- + + // Utility Functionality + + /** + * Strips the URL prefix (such as "http://" or "https://") from the given text. + * + * @private + * @param {String} text The text of the anchor that is being generated, for which to strip off the + * url prefix (such as stripping off "http://") + * @return {String} The `anchorText`, with the prefix stripped. + */ + stripUrlPrefix : function( text ) { + return text.replace( this.urlPrefixRegex, '' ); + }, + + + /** + * Strips any protocol-relative '//' from the anchor text. + * + * @private + * @param {String} text The text of the anchor that is being generated, for which to strip off the + * protocol-relative prefix (such as stripping off "//") + * @return {String} The `anchorText`, with the protocol-relative prefix stripped. + */ + stripProtocolRelativePrefix : function( text ) { + return text.replace( this.protocolRelativeRegex, '' ); + }, + + + /** + * Removes any trailing slash from the given `anchorText`, in preparation for the text to be displayed. + * + * @private + * @param {String} anchorText The text of the anchor that is being generated, for which to remove any trailing + * slash ('/') that may exist. + * @return {String} The `anchorText`, with the trailing slash removed. + */ + removeTrailingSlash : function( anchorText ) { + if( anchorText.charAt( anchorText.length - 1 ) === '/' ) { + anchorText = anchorText.slice( 0, -1 ); + } + return anchorText; + } + +} ); +/*global Autolinker */ +/** + * @abstract + * @class Autolinker.matcher.Matcher + * + * An abstract class and interface for individual matchers to find matches in + * an input string with linkified versions of them. + * + * Note that Matchers do not take HTML into account - they must be fed the text + * nodes of any HTML string, which is handled by {@link Autolinker#parse}. + */ +Autolinker.matcher.Matcher = Autolinker.Util.extend( Object, { + + /** + * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required) + * + * Reference to the AnchorTagBuilder instance to use to generate HTML tags + * for {@link Autolinker.match.Match Matches}. + */ + + + /** + * @constructor + * @param {Object} cfg The configuration properties for the Matcher + * instance, specified in an Object (map). + */ + constructor : function( cfg ) { + if( !cfg.tagBuilder ) throw new Error( '`tagBuilder` cfg required' ); + + this.tagBuilder = cfg.tagBuilder; + }, + + + /** + * Parses the input `text` and returns the array of {@link Autolinker.match.Match Matches} + * for the matcher. + * + * @abstract + * @param {String} text The text to scan and replace matches in. + * @return {Autolinker.match.Match[]} + */ + parseMatches : Autolinker.Util.abstractMethod + +} ); +/*global Autolinker */ +/** + * @class Autolinker.matcher.Email + * @extends Autolinker.matcher.Matcher + * + * Matcher to find email matches in an input string. + * + * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more details. + */ +Autolinker.matcher.Email = Autolinker.Util.extend( Autolinker.matcher.Matcher, { + + /** + * The regular expression to match email addresses. Example match: + * + * person@place.com + * + * @private + * @property {RegExp} matcherRegex + */ + matcherRegex : (function() { + var alphaNumericChars = Autolinker.RegexLib.alphaNumericCharsStr, + emailRegex = new RegExp( '[' + alphaNumericChars + '\\-_\';:&=+$.,]+@' ), // something@ for email addresses (a.k.a. local-part) + domainNameRegex = Autolinker.RegexLib.domainNameRegex, + tldRegex = Autolinker.RegexLib.tldRegex; // match our known top level domains (TLDs) + + return new RegExp( [ + emailRegex.source, + domainNameRegex.source, + '\\.', tldRegex.source // '.com', '.net', etc + ].join( "" ), 'gi' ); + } )(), + + + /** + * @inheritdoc + */ + parseMatches : function( text ) { + var matcherRegex = this.matcherRegex, + tagBuilder = this.tagBuilder, + matches = [], + match; + + while( ( match = matcherRegex.exec( text ) ) !== null ) { + var matchedText = match[ 0 ]; + + matches.push( new Autolinker.match.Email( { + tagBuilder : tagBuilder, + matchedText : matchedText, + offset : match.index, + email : matchedText + } ) ); + } + + return matches; + } + +} ); +/*global Autolinker */ +/** + * @class Autolinker.matcher.Hashtag + * @extends Autolinker.matcher.Matcher + * + * Matcher to find Hashtag matches in an input string. + */ +Autolinker.matcher.Hashtag = Autolinker.Util.extend( Autolinker.matcher.Matcher, { + + /** + * @cfg {String} serviceName + * + * The service to point hashtag matches to. See {@link Autolinker#hashtag} + * for available values. + */ + + + /** + * The regular expression to match Hashtags. Example match: + * + * #asdf + * + * @private + * @property {RegExp} matcherRegex + */ + matcherRegex : new RegExp( '#[_' + Autolinker.RegexLib.alphaNumericCharsStr + ']{1,139}', 'g' ), + + /** + * The regular expression to use to check the character before a username match to + * make sure we didn't accidentally match an email address. + * + * For example, the string "asdf@asdf.com" should not match "@asdf" as a username. + * + * @private + * @property {RegExp} nonWordCharRegex + */ + nonWordCharRegex : new RegExp( '[^' + Autolinker.RegexLib.alphaNumericCharsStr + ']' ), + + + /** + * @constructor + * @param {Object} cfg The configuration properties for the Match instance, + * specified in an Object (map). + */ + constructor : function( cfg ) { + Autolinker.matcher.Matcher.prototype.constructor.call( this, cfg ); + + this.serviceName = cfg.serviceName; + }, + + + /** + * @inheritdoc + */ + parseMatches : function( text ) { + var matcherRegex = this.matcherRegex, + nonWordCharRegex = this.nonWordCharRegex, + serviceName = this.serviceName, + tagBuilder = this.tagBuilder, + matches = [], + match; + + while( ( match = matcherRegex.exec( text ) ) !== null ) { + var offset = match.index, + prevChar = text.charAt( offset - 1 ); + + // If we found the match at the beginning of the string, or we found the match + // and there is a whitespace char in front of it (meaning it is not a '#' char + // in the middle of a word), then it is a hashtag match. + if( offset === 0 || nonWordCharRegex.test( prevChar ) ) { + var matchedText = match[ 0 ], + hashtag = match[ 0 ].slice( 1 ); // strip off the '#' character at the beginning + + matches.push( new Autolinker.match.Hashtag( { + tagBuilder : tagBuilder, + matchedText : matchedText, + offset : offset, + serviceName : serviceName, + hashtag : hashtag + } ) ); + } + } + + return matches; + } + +} ); +/*global Autolinker */ +/** + * @class Autolinker.matcher.Phone + * @extends Autolinker.matcher.Matcher + * + * Matcher to find Phone number matches in an input string. + * + * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more + * details. + */ +Autolinker.matcher.Phone = Autolinker.Util.extend( Autolinker.matcher.Matcher, { + + /** + * The regular expression to match Phone numbers. Example match: + * + * (123) 456-7890 + * + * This regular expression has the following capturing groups: + * + * 1. The prefixed '+' sign, if there is one. + * + * @private + * @property {RegExp} matcherRegex + */ + matcherRegex : /(?:(\+)?\d{1,3}[-\040.])?\(?\d{3}\)?[-\040.]?\d{3}[-\040.]\d{4}/g, // ex: (123) 456-7890, 123 456 7890, 123-456-7890, etc. + + /** + * @inheritdoc + */ + parseMatches : function( text ) { + var matcherRegex = this.matcherRegex, + tagBuilder = this.tagBuilder, + matches = [], + match; + + while( ( match = matcherRegex.exec( text ) ) !== null ) { + // Remove non-numeric values from phone number string + var matchedText = match[ 0 ], + cleanNumber = matchedText.replace( /\D/g, '' ), // strip out non-digit characters + plusSign = !!match[ 1 ]; // match[ 1 ] is the prefixed plus sign, if there is one + + matches.push( new Autolinker.match.Phone( { + tagBuilder : tagBuilder, + matchedText : matchedText, + offset : match.index, + number : cleanNumber, + plusSign : plusSign + } ) ); + } + + return matches; + } + +} ); +/*global Autolinker */ +/** + * @class Autolinker.matcher.Twitter + * @extends Autolinker.matcher.Matcher + * + * Matcher to find/replace username matches in an input string. + */ +Autolinker.matcher.Twitter = Autolinker.Util.extend( Autolinker.matcher.Matcher, { + + /** + * The regular expression to match username handles. Example match: + * + * @asdf + * + * @private + * @property {RegExp} matcherRegex + */ + matcherRegex : new RegExp( '@[_' + Autolinker.RegexLib.alphaNumericCharsStr + ']{1,20}', 'g' ), + + /** + * The regular expression to use to check the character before a username match to + * make sure we didn't accidentally match an email address. + * + * For example, the string "asdf@asdf.com" should not match "@asdf" as a username. + * + * @private + * @property {RegExp} nonWordCharRegex + */ + nonWordCharRegex : new RegExp( '[^' + Autolinker.RegexLib.alphaNumericCharsStr + ']' ), + + + /** + * @inheritdoc + */ + parseMatches : function( text ) { + var matcherRegex = this.matcherRegex, + nonWordCharRegex = this.nonWordCharRegex, + tagBuilder = this.tagBuilder, + matches = [], + match; + + while( ( match = matcherRegex.exec( text ) ) !== null ) { + var offset = match.index, + prevChar = text.charAt( offset - 1 ); + + // If we found the match at the beginning of the string, or we found the match + // and there is a whitespace char in front of it (meaning it is not an email + // address), then it is a username match. + if( offset === 0 || nonWordCharRegex.test( prevChar ) ) { + var matchedText = match[ 0 ], + twitterHandle = match[ 0 ].slice( 1 ); // strip off the '@' character at the beginning + + matches.push( new Autolinker.match.Twitter( { + tagBuilder : tagBuilder, + matchedText : matchedText, + offset : offset, + twitterHandle : twitterHandle + } ) ); + } + } + + return matches; + } + +} ); +/*global Autolinker */ +/** + * @class Autolinker.matcher.Url + * @extends Autolinker.matcher.Matcher + * + * Matcher to find URL matches in an input string. + * + * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more details. + */ +Autolinker.matcher.Url = Autolinker.Util.extend( Autolinker.matcher.Matcher, { + + /** + * @cfg {Boolean} stripPrefix (required) + * @inheritdoc Autolinker#stripPrefix + */ + + + /** + * @private + * @property {RegExp} matcherRegex + * + * The regular expression to match URLs with an optional scheme, port + * number, path, query string, and hash anchor. + * + * Example matches: + * + * http://google.com + * www.google.com + * google.com/path/to/file?q1=1&q2=2#myAnchor + * + * + * This regular expression will have the following capturing groups: + * + * 1. Group that matches a scheme-prefixed URL (i.e. 'http://google.com'). + * This is used to match scheme URLs with just a single word, such as + * 'http://localhost', where we won't double check that the domain name + * has at least one dot ('.') in it. + * 2. Group that matches a 'www.' prefixed URL. This is only matched if the + * 'www.' text was not prefixed by a scheme (i.e.: not prefixed by + * 'http://', 'ftp:', etc.) + * 3. A protocol-relative ('//') match for the case of a 'www.' prefixed + * URL. Will be an empty string if it is not a protocol-relative match. + * We need to know the character before the '//' in order to determine + * if it is a valid match or the // was in a string we don't want to + * auto-link. + * 4. Group that matches a known TLD (top level domain), when a scheme + * or 'www.'-prefixed domain is not matched. + * 5. A protocol-relative ('//') match for the case of a known TLD prefixed + * URL. Will be an empty string if it is not a protocol-relative match. + * See #3 for more info. + */ + matcherRegex : (function() { + var schemeRegex = /(?:[A-Za-z][-.+A-Za-z0-9]*:(?![A-Za-z][-.+A-Za-z0-9]*:\/\/)(?!\d+\/?)(?:\/\/)?)/, // match protocol, allow in format "http://" or "mailto:". However, do not match the first part of something like 'link:http://www.google.com' (i.e. don't match "link:"). Also, make sure we don't interpret 'google.com:8000' as if 'google.com' was a protocol here (i.e. ignore a trailing port number in this regex) + wwwRegex = /(?:www\.)/, // starting with 'www.' + domainNameRegex = Autolinker.RegexLib.domainNameRegex, + tldRegex = Autolinker.RegexLib.tldRegex, // match our known top level domains (TLDs) + alphaNumericCharsStr = Autolinker.RegexLib.alphaNumericCharsStr, + + // Allow optional path, query string, and hash anchor, not ending in the following characters: "?!:,.;" + // http://blog.codinghorror.com/the-problem-with-urls/ + urlSuffixRegex = new RegExp( '[' + alphaNumericCharsStr + '\\-+&@#/%=~_()|\'$*\\[\\]?!:,.;]*[' + alphaNumericCharsStr + '\\-+&@#/%=~_()|\'$*\\[\\]]' ); + + return new RegExp( [ + '(?:', // parens to cover match for scheme (optional), and domain + '(', // *** Capturing group $1, for a scheme-prefixed url (ex: http://google.com) + schemeRegex.source, + domainNameRegex.source, + ')', + + '|', + + '(', // *** Capturing group $2, for a 'www.' prefixed url (ex: www.google.com) + '(//)?', // *** Capturing group $3 for an optional protocol-relative URL. Must be at the beginning of the string or start with a non-word character (handled later) + wwwRegex.source, + domainNameRegex.source, + ')', + + '|', + + '(', // *** Capturing group $4, for known a TLD url (ex: google.com) + '(//)?', // *** Capturing group $5 for an optional protocol-relative URL. Must be at the beginning of the string or start with a non-word character (handled later) + domainNameRegex.source + '\\.', + tldRegex.source, + ')', + ')', + + '(?:' + urlSuffixRegex.source + ')?' // match for path, query string, and/or hash anchor - optional + ].join( "" ), 'gi' ); + } )(), + + + /** + * A regular expression to use to check the character before a protocol-relative + * URL match. We don't want to match a protocol-relative URL if it is part + * of another word. + * + * For example, we want to match something like "Go to: //google.com", + * but we don't want to match something like "abc//google.com" + * + * This regular expression is used to test the character before the '//'. + * + * @private + * @type {RegExp} wordCharRegExp + */ + wordCharRegExp : /\w/, + + + /** + * The regular expression to match opening parenthesis in a URL match. + * + * This is to determine if we have unbalanced parenthesis in the URL, and to + * drop the final parenthesis that was matched if so. + * + * Ex: The text "(check out: wikipedia.com/something_(disambiguation))" + * should only autolink the inner "wikipedia.com/something_(disambiguation)" + * part, so if we find that we have unbalanced parenthesis, we will drop the + * last one for the match. + * + * @private + * @property {RegExp} + */ + openParensRe : /\(/g, + + /** + * The regular expression to match closing parenthesis in a URL match. See + * {@link #openParensRe} for more information. + * + * @private + * @property {RegExp} + */ + closeParensRe : /\)/g, + + + /** + * @constructor + * @param {Object} cfg The configuration properties for the Match instance, + * specified in an Object (map). + */ + constructor : function( cfg ) { + Autolinker.matcher.Matcher.prototype.constructor.call( this, cfg ); + + this.stripPrefix = cfg.stripPrefix; + + if( this.stripPrefix == null ) throw new Error( '`stripPrefix` cfg required' ); + }, + + + /** + * @inheritdoc + */ + parseMatches : function( text ) { + var matcherRegex = this.matcherRegex, + stripPrefix = this.stripPrefix, + tagBuilder = this.tagBuilder, + matches = [], + match; + + while( ( match = matcherRegex.exec( text ) ) !== null ) { + var matchStr = match[ 0 ], + schemeUrlMatch = match[ 1 ], + wwwUrlMatch = match[ 2 ], + wwwProtocolRelativeMatch = match[ 3 ], + //tldUrlMatch = match[ 4 ], -- not needed at the moment + tldProtocolRelativeMatch = match[ 5 ], + offset = match.index, + protocolRelativeMatch = wwwProtocolRelativeMatch || tldProtocolRelativeMatch, + prevChar = text.charAt( offset - 1 ); + + if( !Autolinker.matcher.UrlMatchValidator.isValid( matchStr, schemeUrlMatch ) ) { + continue; + } + + // If the match is preceded by an '@' character, then it is either + // an email address or a username. Skip these types of matches. + if( offset > 0 && prevChar === '@' ) { + continue; + } + + // If it's a protocol-relative '//' match, but the character before the '//' + // was a word character (i.e. a letter/number), then we found the '//' in the + // middle of another word (such as "asdf//asdf.com"). In this case, skip the + // match. + if( offset > 0 && protocolRelativeMatch && this.wordCharRegExp.test( prevChar ) ) { + continue; + } + + // Handle a closing parenthesis at the end of the match, and exclude + // it if there is not a matching open parenthesis in the match + // itself. + if( this.matchHasUnbalancedClosingParen( matchStr ) ) { + matchStr = matchStr.substr( 0, matchStr.length - 1 ); // remove the trailing ")" + } else { + // Handle an invalid character after the TLD + var pos = this.matchHasInvalidCharAfterTld( matchStr, schemeUrlMatch ); + if( pos > -1 ) { + matchStr = matchStr.substr( 0, pos ); // remove the trailing invalid chars + } + } + + var urlMatchType = schemeUrlMatch ? 'scheme' : ( wwwUrlMatch ? 'www' : 'tld' ), + protocolUrlMatch = !!schemeUrlMatch; + + matches.push( new Autolinker.match.Url( { + tagBuilder : tagBuilder, + matchedText : matchStr, + offset : offset, + urlMatchType : urlMatchType, + url : matchStr, + protocolUrlMatch : protocolUrlMatch, + protocolRelativeMatch : !!protocolRelativeMatch, + stripPrefix : stripPrefix + } ) ); + } + + return matches; + }, + + + /** + * Determines if a match found has an unmatched closing parenthesis. If so, + * this parenthesis will be removed from the match itself, and appended + * after the generated anchor tag. + * + * A match may have an extra closing parenthesis at the end of the match + * because the regular expression must include parenthesis for URLs such as + * "wikipedia.com/something_(disambiguation)", which should be auto-linked. + * + * However, an extra parenthesis *will* be included when the URL itself is + * wrapped in parenthesis, such as in the case of "(wikipedia.com/something_(disambiguation))". + * In this case, the last closing parenthesis should *not* be part of the + * URL itself, and this method will return `true`. + * + * @private + * @param {String} matchStr The full match string from the {@link #matcherRegex}. + * @return {Boolean} `true` if there is an unbalanced closing parenthesis at + * the end of the `matchStr`, `false` otherwise. + */ + matchHasUnbalancedClosingParen : function( matchStr ) { + var lastChar = matchStr.charAt( matchStr.length - 1 ); + + if( lastChar === ')' ) { + var openParensMatch = matchStr.match( this.openParensRe ), + closeParensMatch = matchStr.match( this.closeParensRe ), + numOpenParens = ( openParensMatch && openParensMatch.length ) || 0, + numCloseParens = ( closeParensMatch && closeParensMatch.length ) || 0; + + if( numOpenParens < numCloseParens ) { + return true; + } + } + + return false; + }, + + + /** + * Determine if there's an invalid character after the TLD in a URL. Valid + * characters after TLD are ':/?#'. Exclude scheme matched URLs from this + * check. + * + * @private + * @param {String} urlMatch The matched URL, if there was one. Will be an + * empty string if the match is not a URL match. + * @param {String} schemeUrlMatch The match URL string for a scheme + * match. Ex: 'http://yahoo.com'. This is used to match something like + * 'http://localhost', where we won't double check that the domain name + * has at least one '.' in it. + * @return {Number} the position where the invalid character was found. If + * no such character was found, returns -1 + */ + matchHasInvalidCharAfterTld : function( urlMatch, schemeUrlMatch ) { + if( !urlMatch ) { + return -1; + } + + var offset = 0; + if ( schemeUrlMatch ) { + offset = urlMatch.indexOf(':'); + urlMatch = urlMatch.slice(offset); + } + + var re = /^((.?\/\/)?[A-Za-z0-9\u00C0-\u017F\.\-]*[A-Za-z0-9\u00C0-\u017F\-]\.[A-Za-z]+)/; + var res = re.exec( urlMatch ); + if ( res === null ) { + return -1; + } + + offset += res[1].length; + urlMatch = urlMatch.slice(res[1].length); + if (/^[^.A-Za-z:\/?#]/.test(urlMatch)) { + return offset; + } + + return -1; + } + +} ); +/*global Autolinker */ +/*jshint scripturl:true */ +/** + * @private + * @class Autolinker.matcher.UrlMatchValidator + * @singleton + * + * Used by Autolinker to filter out false URL positives from the + * {@link Autolinker.matcher.Url UrlMatcher}. + * + * Due to the limitations of regular expressions (including the missing feature + * of look-behinds in JS regular expressions), we cannot always determine the + * validity of a given match. This class applies a bit of additional logic to + * filter out any false positives that have been matched by the + * {@link Autolinker.matcher.Url UrlMatcher}. + */ +Autolinker.matcher.UrlMatchValidator = { + + /** + * Regex to test for a full protocol, with the two trailing slashes. Ex: 'http://' + * + * @private + * @property {RegExp} hasFullProtocolRegex + */ + hasFullProtocolRegex : /^[A-Za-z][-.+A-Za-z0-9]*:\/\//, + + /** + * Regex to find the URI scheme, such as 'mailto:'. + * + * This is used to filter out 'javascript:' and 'vbscript:' schemes. + * + * @private + * @property {RegExp} uriSchemeRegex + */ + uriSchemeRegex : /^[A-Za-z][-.+A-Za-z0-9]*:/, + + /** + * Regex to determine if at least one word char exists after the protocol (i.e. after the ':') + * + * @private + * @property {RegExp} hasWordCharAfterProtocolRegex + */ + hasWordCharAfterProtocolRegex : /:[^\s]*?[A-Za-z\u00C0-\u017F]/, + + /** + * Regex to determine if the string is a valid IP address + * + * @private + * @property {RegExp} ipRegex + */ + ipRegex: /[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?(:[0-9]*)?\/?$/, + + /** + * Determines if a given URL match found by the {@link Autolinker.matcher.Url UrlMatcher} + * is valid. Will return `false` for: + * + * 1) URL matches which do not have at least have one period ('.') in the + * domain name (effectively skipping over matches like "abc:def"). + * However, URL matches with a protocol will be allowed (ex: 'http://localhost') + * 2) URL matches which do not have at least one word character in the + * domain name (effectively skipping over matches like "git:1.0"). + * 3) A protocol-relative url match (a URL beginning with '//') whose + * previous character is a word character (effectively skipping over + * strings like "abc//google.com") + * + * Otherwise, returns `true`. + * + * @param {String} urlMatch The matched URL, if there was one. Will be an + * empty string if the match is not a URL match. + * @param {String} protocolUrlMatch The match URL string for a protocol + * match. Ex: 'http://yahoo.com'. This is used to match something like + * 'http://localhost', where we won't double check that the domain name + * has at least one '.' in it. + * @return {Boolean} `true` if the match given is valid and should be + * processed, or `false` if the match is invalid and/or should just not be + * processed. + */ + isValid : function( urlMatch, protocolUrlMatch ) { + if( + ( protocolUrlMatch && !this.isValidUriScheme( protocolUrlMatch ) ) || + this.urlMatchDoesNotHaveProtocolOrDot( urlMatch, protocolUrlMatch ) || // At least one period ('.') must exist in the URL match for us to consider it an actual URL, *unless* it was a full protocol match (like 'http://localhost') + (this.urlMatchDoesNotHaveAtLeastOneWordChar( urlMatch, protocolUrlMatch ) && // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0" + !this.isValidIpAddress( urlMatch ) // Except if it's an IP address + ) + ) { + return false; + } + + return true; + }, + + + isValidIpAddress : function ( uriSchemeMatch ) { + var newRegex = new RegExp(this.hasFullProtocolRegex.source + this.ipRegex.source); + var uriScheme = uriSchemeMatch.match( newRegex ); + + return uriScheme !== null; + }, + + /** + * Determines if the URI scheme is a valid scheme to be autolinked. Returns + * `false` if the scheme is 'javascript:' or 'vbscript:' + * + * @private + * @param {String} uriSchemeMatch The match URL string for a full URI scheme + * match. Ex: 'http://yahoo.com' or 'mailto:a@a.com'. + * @return {Boolean} `true` if the scheme is a valid one, `false` otherwise. + */ + isValidUriScheme : function( uriSchemeMatch ) { + var uriScheme = uriSchemeMatch.match( this.uriSchemeRegex )[ 0 ].toLowerCase(); + + return ( uriScheme !== 'javascript:' && uriScheme !== 'vbscript:' ); + }, + + + /** + * Determines if a URL match does not have either: + * + * a) a full protocol (i.e. 'http://'), or + * b) at least one dot ('.') in the domain name (for a non-full-protocol + * match). + * + * Either situation is considered an invalid URL (ex: 'git:d' does not have + * either the '://' part, or at least one dot in the domain name. If the + * match was 'git:abc.com', we would consider this valid.) + * + * @private + * @param {String} urlMatch The matched URL, if there was one. Will be an + * empty string if the match is not a URL match. + * @param {String} protocolUrlMatch The match URL string for a protocol + * match. Ex: 'http://yahoo.com'. This is used to match something like + * 'http://localhost', where we won't double check that the domain name + * has at least one '.' in it. + * @return {Boolean} `true` if the URL match does not have a full protocol, + * or at least one dot ('.') in a non-full-protocol match. + */ + urlMatchDoesNotHaveProtocolOrDot : function( urlMatch, protocolUrlMatch ) { + return ( !!urlMatch && ( !protocolUrlMatch || !this.hasFullProtocolRegex.test( protocolUrlMatch ) ) && urlMatch.indexOf( '.' ) === -1 ); + }, + + + /** + * Determines if a URL match does not have at least one word character after + * the protocol (i.e. in the domain name). + * + * At least one letter character must exist in the domain name after a + * protocol match. Ex: skip over something like "git:1.0" + * + * @private + * @param {String} urlMatch The matched URL, if there was one. Will be an + * empty string if the match is not a URL match. + * @param {String} protocolUrlMatch The match URL string for a protocol + * match. Ex: 'http://yahoo.com'. This is used to know whether or not we + * have a protocol in the URL string, in order to check for a word + * character after the protocol separator (':'). + * @return {Boolean} `true` if the URL match does not have at least one word + * character in it after the protocol, `false` otherwise. + */ + urlMatchDoesNotHaveAtLeastOneWordChar : function( urlMatch, protocolUrlMatch ) { + if( urlMatch && protocolUrlMatch ) { + return !this.hasWordCharAfterProtocolRegex.test( urlMatch ); + } else { + return false; + } + } + +}; +/*global Autolinker */ +/** + * A truncation feature where the ellipsis will be placed at the end of the URL. + * + * @param {String} anchorText + * @param {Number} truncateLen The maximum length of the truncated output URL string. + * @param {String} ellipsisChars The characters to place within the url, e.g. "..". + * @return {String} The truncated URL. + */ +Autolinker.truncate.TruncateEnd = function(anchorText, truncateLen, ellipsisChars){ + return Autolinker.Util.ellipsis( anchorText, truncateLen, ellipsisChars ); +}; + +/*global Autolinker */ +/** + * Date: 2015-10-05 + * Author: Kasper Søfren (https://github.com/kafoso) + * + * A truncation feature, where the ellipsis will be placed in the dead-center of the URL. + * + * @param {String} url A URL. + * @param {Number} truncateLen The maximum length of the truncated output URL string. + * @param {String} ellipsisChars The characters to place within the url, e.g. "..". + * @return {String} The truncated URL. + */ +Autolinker.truncate.TruncateMiddle = function(url, truncateLen, ellipsisChars){ + if (url.length <= truncateLen) { + return url; + } + var availableLength = truncateLen - ellipsisChars.length; + var end = ""; + if (availableLength > 0) { + end = url.substr((-1)*Math.floor(availableLength/2)); + } + return (url.substr(0, Math.ceil(availableLength/2)) + ellipsisChars + end).substr(0, truncateLen); +}; + +/*global Autolinker */ +/** + * Date: 2015-10-05 + * Author: Kasper Søfren (https://github.com/kafoso) + * + * A truncation feature, where the ellipsis will be placed at a section within + * the URL making it still somewhat human readable. + * + * @param {String} url A URL. + * @param {Number} truncateLen The maximum length of the truncated output URL string. + * @param {String} ellipsisChars The characters to place within the url, e.g. "..". + * @return {String} The truncated URL. + */ +Autolinker.truncate.TruncateSmart = function(url, truncateLen, ellipsisChars){ + var parse_url = function(url){ // Functionality inspired by PHP function of same name + var urlObj = {}; + var urlSub = url; + var match = urlSub.match(/^([a-z]+):\/\//i); + if (match) { + urlObj.scheme = match[1]; + urlSub = urlSub.substr(match[0].length); + } + match = urlSub.match(/^(.*?)(?=(\?|#|\/|$))/i); + if (match) { + urlObj.host = match[1]; + urlSub = urlSub.substr(match[0].length); + } + match = urlSub.match(/^\/(.*?)(?=(\?|#|$))/i); + if (match) { + urlObj.path = match[1]; + urlSub = urlSub.substr(match[0].length); + } + match = urlSub.match(/^\?(.*?)(?=(#|$))/i); + if (match) { + urlObj.query = match[1]; + urlSub = urlSub.substr(match[0].length); + } + match = urlSub.match(/^#(.*?)$/i); + if (match) { + urlObj.fragment = match[1]; + //urlSub = urlSub.substr(match[0].length); -- not used. Uncomment if adding another block. + } + return urlObj; + }; + + var buildUrl = function(urlObj){ + var url = ""; + if (urlObj.scheme && urlObj.host) { + url += urlObj.scheme + "://"; + } + if (urlObj.host) { + url += urlObj.host; + } + if (urlObj.path) { + url += "/" + urlObj.path; + } + if (urlObj.query) { + url += "?" + urlObj.query; + } + if (urlObj.fragment) { + url += "#" + urlObj.fragment; + } + return url; + }; + + var buildSegment = function(segment, remainingAvailableLength){ + var remainingAvailableLengthHalf = remainingAvailableLength/ 2, + startOffset = Math.ceil(remainingAvailableLengthHalf), + endOffset = (-1)*Math.floor(remainingAvailableLengthHalf), + end = ""; + if (endOffset < 0) { + end = segment.substr(endOffset); + } + return segment.substr(0, startOffset) + ellipsisChars + end; + }; + if (url.length <= truncateLen) { + return url; + } + var availableLength = truncateLen - ellipsisChars.length; + var urlObj = parse_url(url); + // Clean up the URL + if (urlObj.query) { + var matchQuery = urlObj.query.match(/^(.*?)(?=(\?|\#))(.*?)$/i); + if (matchQuery) { + // Malformed URL; two or more "?". Removed any content behind the 2nd. + urlObj.query = urlObj.query.substr(0, matchQuery[1].length); + url = buildUrl(urlObj); + } + } + if (url.length <= truncateLen) { + return url; + } + if (urlObj.host) { + urlObj.host = urlObj.host.replace(/^www\./, ""); + url = buildUrl(urlObj); + } + if (url.length <= truncateLen) { + return url; + } + // Process and build the URL + var str = ""; + if (urlObj.host) { + str += urlObj.host; + } + if (str.length >= availableLength) { + if (urlObj.host.length == truncateLen) { + return (urlObj.host.substr(0, (truncateLen - ellipsisChars.length)) + ellipsisChars).substr(0, truncateLen); + } + return buildSegment(str, availableLength).substr(0, truncateLen); + } + var pathAndQuery = ""; + if (urlObj.path) { + pathAndQuery += "/" + urlObj.path; + } + if (urlObj.query) { + pathAndQuery += "?" + urlObj.query; + } + if (pathAndQuery) { + if ((str+pathAndQuery).length >= availableLength) { + if ((str+pathAndQuery).length == truncateLen) { + return (str + pathAndQuery).substr(0, truncateLen); + } + var remainingAvailableLength = availableLength - str.length; + return (str + buildSegment(pathAndQuery, remainingAvailableLength)).substr(0, truncateLen); + } else { + str += pathAndQuery; + } + } + if (urlObj.fragment) { + var fragment = "#"+urlObj.fragment; + if ((str+fragment).length >= availableLength) { + if ((str+fragment).length == truncateLen) { + return (str + fragment).substr(0, truncateLen); + } + var remainingAvailableLength2 = availableLength - str.length; + return (str + buildSegment(fragment, remainingAvailableLength2)).substr(0, truncateLen); + } else { + str += fragment; + } + } + if (urlObj.scheme && urlObj.host) { + var scheme = urlObj.scheme + "://"; + if ((str+scheme).length < availableLength) { + return (scheme + str).substr(0, truncateLen); + } + } + if (str.length <= truncateLen) { + return str; + } + var end = ""; + if (availableLength > 0) { + end = str.substr((-1)*Math.floor(availableLength/2)); + } + return (str.substr(0, Math.ceil(availableLength/2)) + ellipsisChars + end).substr(0, truncateLen); +}; + +return Autolinker; +})); diff --git a/node_modules/autolinker/dist/Autolinker.min.js b/node_modules/autolinker/dist/Autolinker.min.js new file mode 100644 index 0000000000000000000000000000000000000000..fb80ada47017537022aed6e19c712e96ea787404 --- /dev/null +++ b/node_modules/autolinker/dist/Autolinker.min.js @@ -0,0 +1,10 @@ +/*! + * Autolinker.js + * 0.28.1 + * + * Copyright(c) 2016 Gregory Jacobs + * MIT License + * + * https://github.com/gregjacobs/Autolinker.js + */ +!function(t,e){"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?module.exports=e():t.Autolinker=e()}(this,function(){var t=function(e){e=e||{},this.version=t.version,this.urls=this.normalizeUrlsCfg(e.urls),this.email="boolean"!=typeof e.email||e.email,this.twitter="boolean"!=typeof e.twitter||e.twitter,this.phone="boolean"!=typeof e.phone||e.phone,this.hashtag=e.hashtag||!1,this.newWindow="boolean"!=typeof e.newWindow||e.newWindow,this.stripPrefix="boolean"!=typeof e.stripPrefix||e.stripPrefix;var r=this.hashtag;if(r!==!1&&"twitter"!==r&&"facebook"!==r&&"instagram"!==r)throw new Error("invalid `hashtag` cfg - see docs");this.truncate=this.normalizeTruncateCfg(e.truncate),this.className=e.className||"",this.replaceFn=e.replaceFn||null,this.htmlParser=null,this.matchers=null,this.tagBuilder=null};return t.link=function(e,r){var a=new t(r);return a.link(e)},t.version="0.28.1",t.prototype={constructor:t,normalizeUrlsCfg:function(t){return null==t&&(t=!0),"boolean"==typeof t?{schemeMatches:t,wwwMatches:t,tldMatches:t}:{schemeMatches:"boolean"!=typeof t.schemeMatches||t.schemeMatches,wwwMatches:"boolean"!=typeof t.wwwMatches||t.wwwMatches,tldMatches:"boolean"!=typeof t.tldMatches||t.tldMatches}},normalizeTruncateCfg:function(e){return"number"==typeof e?{length:e,location:"end"}:t.Util.defaults(e||{},{length:Number.POSITIVE_INFINITY,location:"end"})},parse:function(t){for(var e=this.getHtmlParser(),r=e.parse(t),a=0,n=[],i=0,s=r.length;ie&&(r=null==r?"..":r,t=t.substring(0,e-r.length)+r),t},indexOf:function(t,e){if(Array.prototype.indexOf)return t.indexOf(e);for(var r=0,a=t.length;r=0;r--)e(t[r])===!0&&t.splice(r,1)},splitAndCapture:function(t,e){for(var r,a=[],n=0;r=e.exec(t);)a.push(t.substring(n,r.index)),a.push(r[0]),n=r.index+r[0].length;return a.push(t.substring(n)),a},trim:function(t){return t.replace(this.trimRegex,"")}},t.HtmlTag=t.Util.extend(Object,{whitespaceRegex:/\s+/,constructor:function(e){t.Util.assign(this,e),this.innerHtml=this.innerHtml||this.innerHTML},setTagName:function(t){return this.tagName=t,this},getTagName:function(){return this.tagName||""},setAttr:function(t,e){var r=this.getAttrs();return r[t]=e,this},getAttr:function(t){return this.getAttrs()[t]},setAttrs:function(e){var r=this.getAttrs();return t.Util.assign(r,e),this},getAttrs:function(){return this.attrs||(this.attrs={})},setClass:function(t){return this.setAttr("class",t)},addClass:function(e){for(var r,a=this.getClass(),n=this.whitespaceRegex,i=t.Util.indexOf,s=a?a.split(n):[],o=e.split(n);r=o.shift();)i(s,r)===-1&&s.push(r);return this.getAttrs()["class"]=s.join(" "),this},removeClass:function(e){for(var r,a=this.getClass(),n=this.whitespaceRegex,i=t.Util.indexOf,s=a?a.split(n):[],o=e.split(n);s.length&&(r=o.shift());){var c=i(s,r);c!==-1&&s.splice(c,1)}return this.getAttrs()["class"]=s.join(" "),this},getClass:function(){return this.getAttrs()["class"]||""},hasClass:function(t){return(" "+this.getClass()+" ").indexOf(" "+t+" ")!==-1},setInnerHtml:function(t){return this.innerHtml=t,this},getInnerHtml:function(){return this.innerHtml||""},toAnchorString:function(){var t=this.getTagName(),e=this.buildAttrsStr();return e=e?" "+e:"",["<",t,e,">",this.getInnerHtml(),""].join("")},buildAttrsStr:function(){if(!this.attrs)return"";var t=this.getAttrs(),e=[];for(var r in t)t.hasOwnProperty(r)&&e.push(r+'="'+t[r]+'"');return e.join(" ")}}),t.RegexLib=function(){var t="A-Za-z\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽͿΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙա-ևא-תװ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠ-ࢴऄ-हऽॐक़-ॡॱ-ঀঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡૹଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-హఽౘ-ౚౠౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഅ-ഌഎ-ഐഒ-ഺഽൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎↃↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ々〆〱-〵〻〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꩾ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ",e="0-9٠-٩۰-۹߀-߉०-९০-৯੦-੯૦-૯୦-୯௦-௯౦-౯೦-೯൦-൯෦-෯๐-๙໐-໙༠-༩၀-၉႐-႙០-៩᠐-᠙᥆-᥏᧐-᧙᪀-᪉᪐-᪙᭐-᭙᮰-᮹᱀-᱉᱐-᱙꘠-꘩꣐-꣙꤀-꤉꧐-꧙꧰-꧹꩐-꩙꯰-꯹0-9",r=t+e,a=new RegExp("["+r+".\\-]*["+r+"\\-]"),n=/(?:travelersinsurance|sandvikcoromant|kerryproperties|cancerresearch|weatherchannel|kerrylogistics|spreadbetting|international|wolterskluwer|lifeinsurance|construction|pamperedchef|scholarships|versicherung|bridgestone|creditunion|kerryhotels|investments|productions|blackfriday|enterprises|lamborghini|photography|motorcycles|williamhill|playstation|contractors|barclaycard|accountants|redumbrella|engineering|management|telefonica|protection|consulting|tatamotors|creditcard|vlaanderen|schaeffler|associates|properties|foundation|republican|bnpparibas|boehringer|eurovision|extraspace|industries|immobilien|university|technology|volkswagen|healthcare|restaurant|cuisinella|vistaprint|apartments|accountant|travelers|homedepot|institute|vacations|furniture|fresenius|insurance|christmas|bloomberg|solutions|barcelona|firestone|financial|kuokgroup|fairwinds|community|passagens|goldpoint|equipment|lifestyle|yodobashi|aquarelle|marketing|analytics|education|amsterdam|statefarm|melbourne|allfinanz|directory|microsoft|stockholm|montblanc|accenture|lancaster|landrover|everbank|istanbul|graphics|grainger|ipiranga|softbank|attorney|pharmacy|saarland|catering|airforce|yokohama|mortgage|frontier|mutuelle|stcgroup|memorial|pictures|football|symantec|cipriani|ventures|telecity|cityeats|verisign|flsmidth|boutique|cleaning|firmdale|clinique|clothing|redstone|infiniti|deloitte|feedback|services|broadway|plumbing|commbank|training|barclays|exchange|computer|brussels|software|delivery|barefoot|builders|business|bargains|engineer|holdings|download|security|helsinki|lighting|movistar|discount|hdfcbank|supplies|marriott|property|diamonds|capetown|partners|democrat|jpmorgan|bradesco|budapest|rexroth|zuerich|shriram|academy|science|support|youtube|singles|surgery|alibaba|statoil|dentist|schwarz|android|cruises|cricket|digital|markets|starhub|systems|courses|coupons|netbank|country|domains|corsica|network|neustar|realtor|lincoln|limited|schmidt|yamaxun|cooking|contact|auction|spiegel|liaison|leclerc|latrobe|lasalle|abogado|compare|lanxess|exposed|express|company|cologne|college|avianca|lacaixa|fashion|recipes|ferrero|komatsu|storage|wanggou|clubmed|sandvik|fishing|fitness|bauhaus|kitchen|flights|florist|flowers|watches|weather|temasek|samsung|bentley|forsale|channel|theater|frogans|theatre|okinawa|website|tickets|jewelry|gallery|tiffany|iselect|shiksha|brother|organic|wedding|genting|toshiba|origins|philips|hyundai|hotmail|hoteles|hosting|rentals|windows|cartier|bugatti|holiday|careers|whoswho|hitachi|panerai|caravan|reviews|guitars|capital|trading|hamburg|hangout|finance|stream|family|abbott|health|review|travel|report|hermes|hiphop|gratis|career|toyota|hockey|dating|repair|google|social|soccer|reisen|global|otsuka|giving|unicom|casino|photos|center|broker|rocher|orange|bostik|garden|insure|ryukyu|bharti|safety|physio|sakura|oracle|online|jaguar|gallup|piaget|tienda|futbol|pictet|joburg|webcam|berlin|office|juegos|kaufen|chanel|chrome|xihuan|church|tennis|circle|kinder|flickr|bayern|claims|clinic|viajes|nowruz|xperia|norton|yachts|studio|coffee|camera|sanofi|nissan|author|expert|events|comsec|lawyer|tattoo|viking|estate|villas|condos|realty|yandex|energy|emerck|virgin|vision|durban|living|school|coupon|london|taobao|natura|taipei|nagoya|luxury|walter|aramco|sydney|madrid|credit|maison|makeup|schule|market|anquan|direct|design|swatch|suzuki|alsace|vuelos|dental|alipay|voyage|shouji|voting|airtel|mutual|degree|supply|agency|museum|mobily|dealer|monash|select|mormon|active|moscow|racing|datsun|quebec|nissay|rodeo|email|gifts|works|photo|chloe|edeka|cheap|earth|vista|tushu|koeln|glass|shoes|globo|tunes|gmail|nokia|space|kyoto|black|ricoh|seven|lamer|sener|epson|cisco|praxi|trust|citic|crown|shell|lease|green|legal|lexus|ninja|tatar|gripe|nikon|group|video|wales|autos|gucci|party|nexus|guide|linde|adult|parts|amica|lixil|boats|azure|loans|locus|cymru|lotte|lotto|stada|click|poker|quest|dabur|lupin|nadex|paris|faith|dance|canon|place|gives|trade|skype|rocks|mango|cloud|boots|smile|final|swiss|homes|honda|media|horse|cards|deals|watch|bosch|house|pizza|miami|osaka|tours|total|xerox|coach|sucks|style|delta|toray|iinet|tools|money|codes|beats|tokyo|salon|archi|movie|baidu|study|actor|yahoo|store|apple|world|forex|today|bible|tmall|tirol|irish|tires|forum|reise|vegas|vodka|sharp|omega|weber|jetzt|audio|promo|build|bingo|chase|gallo|drive|dubai|rehab|press|solar|sale|beer|bbva|bank|band|auto|sapo|sarl|saxo|audi|asia|arte|arpa|army|yoga|ally|zara|scor|scot|sexy|seat|zero|seek|aero|adac|zone|aarp|maif|meet|meme|menu|surf|mini|mobi|mtpc|porn|desi|star|ltda|name|talk|navy|love|loan|live|link|news|limo|like|spot|life|nico|lidl|lgbt|land|taxi|team|tech|kred|kpmg|sony|song|kiwi|kddi|jprs|jobs|sohu|java|itau|tips|info|immo|icbc|hsbc|town|host|page|toys|here|help|pars|haus|guru|guge|tube|goog|golf|gold|sncf|gmbh|gift|ggee|gent|gbiz|game|vana|pics|fund|ford|ping|pink|fish|film|fast|farm|play|fans|fail|plus|skin|pohl|fage|moda|post|erni|dvag|prod|doha|prof|docs|viva|diet|luxe|site|dell|sina|dclk|show|qpon|date|vote|cyou|voto|read|coop|cool|wang|club|city|chat|cern|cash|reit|rent|casa|cars|care|camp|rest|call|cafe|weir|wien|rich|wiki|buzz|wine|book|bond|room|work|rsvp|shia|ruhr|blue|bing|shaw|bike|safe|xbox|best|pwc|mtn|lds|aig|boo|fyi|nra|nrw|ntt|car|gal|obi|zip|aeg|vin|how|one|ong|onl|dad|ooo|bet|esq|org|htc|bar|uol|ibm|ovh|gdn|ice|icu|uno|gea|ifm|bot|top|wtf|lol|day|pet|eus|wtc|ubs|tvs|aco|ing|ltd|ink|tab|abb|afl|cat|int|pid|pin|bid|cba|gle|com|cbn|ads|man|wed|ceb|gmo|sky|ist|gmx|tui|mba|fan|ski|iwc|app|pro|med|ceo|jcb|jcp|goo|dev|men|aaa|meo|pub|jlc|bom|jll|gop|jmp|mil|got|gov|win|jot|mma|joy|trv|red|cfa|cfd|bio|moe|moi|mom|ren|biz|aws|xin|bbc|dnp|buy|kfh|mov|thd|xyz|fit|kia|rio|rip|kim|dog|vet|nyc|bcg|mtr|bcn|bms|bmw|run|bzh|rwe|tel|stc|axa|kpn|fly|krd|cab|bnl|foo|crs|eat|tci|sap|srl|nec|sas|net|cal|sbs|sfr|sca|scb|csc|edu|new|xxx|hiv|fox|wme|ngo|nhk|vip|sex|frl|lat|yun|law|you|tax|soy|sew|om|ac|hu|se|sc|sg|sh|sb|sa|rw|ru|rs|ro|re|qa|py|si|pw|pt|ps|sj|sk|pr|pn|pm|pl|sl|sm|pk|sn|ph|so|pg|pf|pe|pa|zw|nz|nu|nr|np|no|nl|ni|ng|nf|sr|ne|st|nc|na|mz|my|mx|mw|mv|mu|mt|ms|mr|mq|mp|mo|su|mn|mm|ml|mk|mh|mg|me|sv|md|mc|sx|sy|ma|ly|lv|sz|lu|lt|ls|lr|lk|li|lc|lb|la|tc|kz|td|ky|kw|kr|kp|kn|km|ki|kh|tf|tg|th|kg|ke|jp|jo|jm|je|it|is|ir|tj|tk|tl|tm|iq|tn|to|io|in|im|il|ie|ad|sd|ht|hr|hn|hm|tr|hk|gy|gw|gu|gt|gs|gr|gq|tt|gp|gn|gm|gl|tv|gi|tw|tz|ua|gh|ug|uk|gg|gf|ge|gd|us|uy|uz|va|gb|ga|vc|ve|fr|fo|fm|fk|fj|vg|vi|fi|eu|et|es|er|eg|ee|ec|dz|do|dm|dk|vn|dj|de|cz|cy|cx|cw|vu|cv|cu|cr|co|cn|cm|cl|ck|ci|ch|cg|cf|cd|cc|ca|wf|bz|by|bw|bv|bt|bs|br|bo|bn|bm|bj|bi|ws|bh|bg|bf|be|bd|bb|ba|az|ax|aw|au|at|as|ye|ar|aq|ao|am|al|yt|ai|za|ag|af|ae|zm|id)\b/;return{alphaNumericCharsStr:r,domainNameRegex:a,tldRegex:n}}(),t.AnchorTagBuilder=t.Util.extend(Object,{constructor:function(e){t.Util.assign(this,e)},build:function(e){return new t.HtmlTag({tagName:"a",attrs:this.createAttrs(e.getType(),e.getAnchorHref()),innerHtml:this.processAnchorText(e.getAnchorText())})},createAttrs:function(t,e){var r={href:e},a=this.createCssClass(t);return a&&(r["class"]=a),this.newWindow&&(r.target="_blank",r.rel="noopener noreferrer"),r},createCssClass:function(t){var e=this.className;return e?e+" "+e+"-"+t:""},processAnchorText:function(t){return t=this.doTruncate(t)},doTruncate:function(e){var r=this.truncate;if(!r||!r.length)return e;var a=r.length,n=r.location;return"smart"===n?t.truncate.TruncateSmart(e,a,".."):"middle"===n?t.truncate.TruncateMiddle(e,a,".."):t.truncate.TruncateEnd(e,a,"..")}}),t.htmlParser.HtmlParser=t.Util.extend(Object,{htmlRegex:function(){var t=/!--([\s\S]+?)--/,e=/[0-9a-zA-Z][0-9a-zA-Z:]*/,r=/[^\s"'>\/=\x00-\x1F\x7F]+/,a=/(?:"[^"]*?"|'[^']*?'|[^'"=<>`\s]+)/,n=r.source+"(?:\\s*=\\s*"+a.source+")?";return new RegExp(["(?:","<(!DOCTYPE)","(?:","\\s+","(?:",n,"|",a.source+")",")*",">",")","|","(?:","<(/)?","(?:",t.source,"|","(?:","("+e.source+")","(?:","(?:\\s+|\\b)",n,")*","\\s*/?",")",")",">",")"].join(""),"gi")}(),htmlCharacterEntitiesRegex:/( | |<|<|>|>|"|"|')/gi,parse:function(t){for(var e,r,a=this.htmlRegex,n=0,i=[];null!==(e=a.exec(t));){var s=e[0],o=e[3],c=e[1]||e[4],h=!!e[2],l=e.index,u=t.substring(n,l);u&&(r=this.parseTextAndEntityNodes(n,u),i.push.apply(i,r)),o?i.push(this.createCommentNode(l,s,o)):i.push(this.createElementNode(l,s,c,h)),n=l+s.length}if(n0&&"@"===f||g>0&&m&&this.wordCharRegExp.test(f))){if(this.matchHasUnbalancedClosingParen(o))o=o.substr(0,o.length-1);else{var p=this.matchHasInvalidCharAfterTld(o,c);p>-1&&(o=o.substr(0,p))}var d=c?"scheme":h?"www":"tld",b=!!c;s.push(new t.match.Url({tagBuilder:i,matchedText:o,offset:g,urlMatchType:d,url:o,protocolUrlMatch:b,protocolRelativeMatch:!!m,stripPrefix:n}))}}return s},matchHasUnbalancedClosingParen:function(t){var e=t.charAt(t.length-1);if(")"===e){var r=t.match(this.openParensRe),a=t.match(this.closeParensRe),n=r&&r.length||0,i=a&&a.length||0;if(n0&&(n=t.substr(-1*Math.floor(a/2))),(t.substr(0,Math.ceil(a/2))+r+n).substr(0,e)},t.truncate.TruncateSmart=function(t,e,r){var a=function(t){var e={},r=t,a=r.match(/^([a-z]+):\/\//i);return a&&(e.scheme=a[1],r=r.substr(a[0].length)),a=r.match(/^(.*?)(?=(\?|#|\/|$))/i),a&&(e.host=a[1],r=r.substr(a[0].length)),a=r.match(/^\/(.*?)(?=(\?|#|$))/i),a&&(e.path=a[1],r=r.substr(a[0].length)),a=r.match(/^\?(.*?)(?=(#|$))/i),a&&(e.query=a[1],r=r.substr(a[0].length)),a=r.match(/^#(.*?)$/i),a&&(e.fragment=a[1]),e},n=function(t){var e="";return t.scheme&&t.host&&(e+=t.scheme+"://"),t.host&&(e+=t.host),t.path&&(e+="/"+t.path),t.query&&(e+="?"+t.query),t.fragment&&(e+="#"+t.fragment),e},i=function(t,e){var a=e/2,n=Math.ceil(a),i=-1*Math.floor(a),s="";return i<0&&(s=t.substr(i)),t.substr(0,n)+r+s};if(t.length<=e)return t;var s=e-r.length,o=a(t);if(o.query){var c=o.query.match(/^(.*?)(?=(\?|\#))(.*?)$/i);c&&(o.query=o.query.substr(0,c[1].length),t=n(o))}if(t.length<=e)return t;if(o.host&&(o.host=o.host.replace(/^www\./,""),t=n(o)),t.length<=e)return t;var h="";if(o.host&&(h+=o.host),h.length>=s)return o.host.length==e?(o.host.substr(0,e-r.length)+r).substr(0,e):i(h,s).substr(0,e);var l="";if(o.path&&(l+="/"+o.path),o.query&&(l+="?"+o.query),l){if((h+l).length>=s){if((h+l).length==e)return(h+l).substr(0,e);var u=s-h.length;return(h+i(l,u)).substr(0,e)}h+=l}if(o.fragment){var g="#"+o.fragment;if((h+g).length>=s){if((h+g).length==e)return(h+g).substr(0,e);var m=s-h.length;return(h+i(g,m)).substr(0,e)}h+=g}if(o.scheme&&o.host){var f=o.scheme+"://";if((h+f).length0&&(p=h.substr(-1*Math.floor(s/2))),(h.substr(0,Math.ceil(s/2))+r+p).substr(0,e)},t}); \ No newline at end of file diff --git a/node_modules/autolinker/package.json b/node_modules/autolinker/package.json new file mode 100644 index 0000000000000000000000000000000000000000..d577922bfb5c9f7c52c86340bcc1a9b08869c94f --- /dev/null +++ b/node_modules/autolinker/package.json @@ -0,0 +1,123 @@ +{ + "_args": [ + [ + { + "name": "autolinker", + "raw": "autolinker@~0.28.0", + "rawSpec": "~0.28.0", + "scope": null, + "spec": ">=0.28.0 <0.29.0", + "type": "range" + }, + "/Users/xxm/Documents/gitlab/codechina-docs/node_modules/remarkable" + ] + ], + "_from": "autolinker@>=0.28.0 <0.29.0", + "_id": "autolinker@0.28.1", + "_inCache": true, + "_installable": true, + "_location": "/autolinker", + "_nodeVersion": "5.10.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/autolinker-0.28.1.tgz_1473119637218_0.16458595311269164" + }, + "_npmUser": { + "email": "greg@greg-jacobs.com", + "name": "gregjacobs" + }, + "_npmVersion": "3.8.3", + "_phantomChildren": {}, + "_requested": { + "name": "autolinker", + "raw": "autolinker@~0.28.0", + "rawSpec": "~0.28.0", + "scope": null, + "spec": ">=0.28.0 <0.29.0", + "type": "range" + }, + "_requiredBy": [ + "/remarkable" + ], + "_resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.28.1.tgz", + "_shasum": "0652b491881879f0775dace0cdca3233942a4e47", + "_shrinkwrap": null, + "_spec": "autolinker@~0.28.0", + "_where": "/Users/xxm/Documents/gitlab/codechina-docs/node_modules/remarkable", + "author": { + "email": "greg@greg-jacobs.com", + "name": "Gregory Jacobs" + }, + "bugs": { + "url": "https://github.com/gregjacobs/Autolinker.js/issues" + }, + "dependencies": { + "gulp-header": "^1.7.1" + }, + "description": "Utility to automatically link the URLs, email addresses, and Twitter handles in a given block of text/HTML", + "devDependencies": { + "gulp": "^3.9.1", + "gulp-clone": "^1.0.0", + "gulp-concat": "^2.6.0", + "gulp-connect": "^3.0.0", + "gulp-jasmine": "^2.3.0", + "gulp-jsduck": "^0.3.0", + "gulp-jshint": "^2.0.0", + "gulp-preprocess": "^2.0.0", + "gulp-rename": "^1.2.2", + "gulp-typescript": "^2.13.0", + "gulp-uglify": "^1.5.3", + "gulp-umd": "^0.2.0", + "jasmine-core": "^2.4.1", + "jshint": "^2.9.1", + "jshint-stylish": "^2.1.0", + "karma": "^0.13.21", + "karma-jasmine": "^0.3.7", + "karma-phantomjs-launcher": "^1.0.0", + "karma-spec-reporter": "0.0.24", + "lodash": "^4.3.0", + "merge-stream": "^1.0.0", + "phantomjs-prebuilt": "^2.1.4", + "requirejs": "^2.1.11", + "through2": "^2.0.1" + }, + "directories": { + "test": "tests" + }, + "dist": { + "shasum": "0652b491881879f0775dace0cdca3233942a4e47", + "tarball": "https://registry.npmjs.org/autolinker/-/autolinker-0.28.1.tgz" + }, + "files": [ + "dist" + ], + "gitHead": "e6634b3736d462b60df5ee10d9e8c3c21a45f8e6", + "homepage": "https://github.com/gregjacobs/Autolinker.js", + "keywords": [ + "auto", + "link", + "autolink", + "url", + "urls", + "anchor" + ], + "license": "MIT", + "main": "dist/Autolinker.js", + "maintainers": [ + { + "email": "greg@greg-jacobs.com", + "name": "gregjacobs" + } + ], + "name": "autolinker", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/gregjacobs/Autolinker.js.git" + }, + "scripts": { + "test": "gulp" + }, + "version": "0.28.1" +} diff --git a/node_modules/boolbase/README.md b/node_modules/boolbase/README.md new file mode 100644 index 0000000000000000000000000000000000000000..85eefa5e5048913b08ec4eb37d0a78473f88505d --- /dev/null +++ b/node_modules/boolbase/README.md @@ -0,0 +1,10 @@ +#boolbase +This very simple module provides two basic functions, one that always returns true (`trueFunc`) and one that always returns false (`falseFunc`). + +###WTF? + +By having only a single instance of these functions around, it's possible to do some nice optimizations. Eg. [`CSSselect`](https://github.com/fb55/CSSselect) uses these functions to determine whether a selector won't match any elements. If that's the case, the DOM doesn't even have to be touched. + +###And why is this a separate module? + +I'm trying to modularize `CSSselect` and most modules depend on these functions. IMHO, having a separate module is the easiest solution to this problem. \ No newline at end of file diff --git a/node_modules/boolbase/index.js b/node_modules/boolbase/index.js new file mode 100644 index 0000000000000000000000000000000000000000..8799fd95dbe31a85c48b956eb19f3625da9f8fb1 --- /dev/null +++ b/node_modules/boolbase/index.js @@ -0,0 +1,8 @@ +module.exports = { + trueFunc: function trueFunc(){ + return true; + }, + falseFunc: function falseFunc(){ + return false; + } +}; \ No newline at end of file diff --git a/node_modules/boolbase/package.json b/node_modules/boolbase/package.json new file mode 100644 index 0000000000000000000000000000000000000000..03ea9db2868421dd24320b72d7e0990bb472ff59 --- /dev/null +++ b/node_modules/boolbase/package.json @@ -0,0 +1,82 @@ +{ + "_args": [ + [ + { + "name": "boolbase", + "raw": "boolbase@~1.0.0", + "rawSpec": "~1.0.0", + "scope": null, + "spec": ">=1.0.0 <1.1.0", + "type": "range" + }, + "/Users/xxm/Documents/gitlab/codechina-docs/node_modules/css-select" + ] + ], + "_from": "boolbase@>=1.0.0 <1.1.0", + "_id": "boolbase@1.0.0", + "_inCache": true, + "_installable": true, + "_location": "/boolbase", + "_npmUser": { + "email": "me@feedic.com", + "name": "feedic" + }, + "_npmVersion": "1.4.2", + "_phantomChildren": {}, + "_requested": { + "name": "boolbase", + "raw": "boolbase@~1.0.0", + "rawSpec": "~1.0.0", + "scope": null, + "spec": ">=1.0.0 <1.1.0", + "type": "range" + }, + "_requiredBy": [ + "/css-select", + "/nth-check" + ], + "_resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "_shasum": "68dff5fbe60c51eb37725ea9e3ed310dcc1e776e", + "_shrinkwrap": null, + "_spec": "boolbase@~1.0.0", + "_where": "/Users/xxm/Documents/gitlab/codechina-docs/node_modules/css-select", + "author": { + "email": "me@feedic.com", + "name": "Felix Boehm" + }, + "bugs": { + "url": "https://github.com/fb55/boolbase/issues" + }, + "dependencies": {}, + "description": "two functions: One that returns true, one that returns false", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "68dff5fbe60c51eb37725ea9e3ed310dcc1e776e", + "tarball": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" + }, + "homepage": "https://github.com/fb55/boolbase", + "keywords": [ + "boolean", + "function" + ], + "license": "ISC", + "main": "index.js", + "maintainers": [ + { + "email": "me@feedic.com", + "name": "feedic" + } + ], + "name": "boolbase", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/fb55/boolbase.git" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "version": "1.0.0" +} diff --git a/node_modules/buffer-from/LICENSE b/node_modules/buffer-from/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..e4bf1d69b1bb0df5acf1278e583264acdc1eefc5 --- /dev/null +++ b/node_modules/buffer-from/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016, 2018 Linus Unnebäck + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/buffer-from/index.js b/node_modules/buffer-from/index.js new file mode 100644 index 0000000000000000000000000000000000000000..d92a83d01fd8b5ce1fcbdf92e72e234672d09d15 --- /dev/null +++ b/node_modules/buffer-from/index.js @@ -0,0 +1,69 @@ +var toString = Object.prototype.toString + +var isModern = ( + typeof Buffer.alloc === 'function' && + typeof Buffer.allocUnsafe === 'function' && + typeof Buffer.from === 'function' +) + +function isArrayBuffer (input) { + return toString.call(input).slice(8, -1) === 'ArrayBuffer' +} + +function fromArrayBuffer (obj, byteOffset, length) { + byteOffset >>>= 0 + + var maxLength = obj.byteLength - byteOffset + + if (maxLength < 0) { + throw new RangeError("'offset' is out of bounds") + } + + if (length === undefined) { + length = maxLength + } else { + length >>>= 0 + + if (length > maxLength) { + throw new RangeError("'length' is out of bounds") + } + } + + return isModern + ? Buffer.from(obj.slice(byteOffset, byteOffset + length)) + : new Buffer(new Uint8Array(obj.slice(byteOffset, byteOffset + length))) +} + +function fromString (string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('"encoding" must be a valid string encoding') + } + + return isModern + ? Buffer.from(string, encoding) + : new Buffer(string, encoding) +} + +function bufferFrom (value, encodingOrOffset, length) { + if (typeof value === 'number') { + throw new TypeError('"value" argument must not be a number') + } + + if (isArrayBuffer(value)) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof value === 'string') { + return fromString(value, encodingOrOffset) + } + + return isModern + ? Buffer.from(value) + : new Buffer(value) +} + +module.exports = bufferFrom diff --git a/node_modules/buffer-from/package.json b/node_modules/buffer-from/package.json new file mode 100644 index 0000000000000000000000000000000000000000..1168d85bd9cded90f27c8a7fc6b656892a3d8ed7 --- /dev/null +++ b/node_modules/buffer-from/package.json @@ -0,0 +1,91 @@ +{ + "_args": [ + [ + { + "name": "buffer-from", + "raw": "buffer-from@^1.0.0", + "rawSpec": "^1.0.0", + "scope": null, + "spec": ">=1.0.0 <2.0.0", + "type": "range" + }, + "/Users/xxm/Documents/gitlab/codechina-docs/node_modules/concat-stream" + ] + ], + "_from": "buffer-from@>=1.0.0 <2.0.0", + "_id": "buffer-from@1.1.1", + "_inCache": true, + "_installable": true, + "_location": "/buffer-from", + "_nodeVersion": "10.5.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/buffer-from_1.1.1_1533048083841_0.2458068233892754" + }, + "_npmUser": { + "email": "linus@folkdatorn.se", + "name": "linusu" + }, + "_npmVersion": "6.1.0", + "_phantomChildren": {}, + "_requested": { + "name": "buffer-from", + "raw": "buffer-from@^1.0.0", + "rawSpec": "^1.0.0", + "scope": null, + "spec": ">=1.0.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/concat-stream" + ], + "_resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "_shasum": "32713bc028f75c02fdb710d7c7bcec1f2c6070ef", + "_shrinkwrap": null, + "_spec": "buffer-from@^1.0.0", + "_where": "/Users/xxm/Documents/gitlab/codechina-docs/node_modules/concat-stream", + "bugs": { + "url": "https://github.com/LinusU/buffer-from/issues" + }, + "dependencies": {}, + "description": "A [ponyfill](https://ponyfill.com) for `Buffer.from`, uses native implementation if available.", + "devDependencies": { + "standard": "^7.1.2" + }, + "directories": {}, + "dist": { + "fileCount": 4, + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbYHUTCRA9TVsSAnZWagAAgoQP/1LXApc57d1uAc/0mnLq\nCI87dq7EtKS4lG7EjFY3yzxIZxlq1++vH0/sWe0V8je9sHhrm/AkSxlcplEV\nWELPjRwIY4h3LP6U5ppG7XAVGmbipkIAGhiRaJtqGfI/TgPRiB3QcrqanlRG\nBf4oDubBJ2vK8dh5Gd0AhAkkTOsIcf4b5uC64A5GUtMoPOrko+zyRYM8IrRo\n7kDspGfsk3YYxyB/L0APD4AIC8vYz2Gin2ca+zJBZH6cvfThhFWbSnCFfVuW\nxXcheune4boTojusOn5dm4LxzFyMgbeibDZTaq+Yod3RuuUVaSCXWNITcT6g\nIlP7wdbBFGx7Ik5hKEtAGtsCdWshzg9YxHR7g7CPe+0xIeb0zNeKBlxFF2jT\niPeiI+JGlMZuH2Qu+284T9WWom/j0NcbZuWmrV5E1GUimVJqtgqD3S3ivc4y\n6fS6OTIemRUmWwmS7farPxzTs34QkUp0vH/dhuvNeZKockTjLvlveHlOtC4m\nhGp5UdiwrsV7Xqqy/RHlACxPjexkDfhwi0FSeY799VkzbgrPm7Npwn8HwMDI\nv6qpaxPbruRJx65zp1J4DqWlhYENreSFOaXGY/t34GIQ1yNHXGg4Z2ltshPi\nb3lJuLEolQYK5GAcryVnAGusAisYQDfygT1BPxYsVT2ZWYmicpHs7UD+70ya\nfbJa\r\n=YgJu\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "32713bc028f75c02fdb710d7c7bcec1f2c6070ef", + "tarball": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "unpackedSize": 4966 + }, + "files": [ + "index.js" + ], + "gitHead": "53f464194ae30e806f6faef635202b4dfd404ed5", + "homepage": "https://github.com/LinusU/buffer-from#readme", + "keywords": [ + "buffer", + "buffer from" + ], + "license": "MIT", + "maintainers": [ + { + "email": "linus@folkdatorn.se", + "name": "linusu" + } + ], + "name": "buffer-from", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/LinusU/buffer-from.git" + }, + "scripts": { + "test": "standard && node test" + }, + "version": "1.1.1" +} diff --git a/node_modules/buffer-from/readme.md b/node_modules/buffer-from/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..9880a558a7c91fefb0e6908318fbd991b6b93dcf --- /dev/null +++ b/node_modules/buffer-from/readme.md @@ -0,0 +1,69 @@ +# Buffer From + +A [ponyfill](https://ponyfill.com) for `Buffer.from`, uses native implementation if available. + +## Installation + +```sh +npm install --save buffer-from +``` + +## Usage + +```js +const bufferFrom = require('buffer-from') + +console.log(bufferFrom([1, 2, 3, 4])) +//=> + +const arr = new Uint8Array([1, 2, 3, 4]) +console.log(bufferFrom(arr.buffer, 1, 2)) +//=> + +console.log(bufferFrom('test', 'utf8')) +//=> + +const buf = bufferFrom('test') +console.log(bufferFrom(buf)) +//=> +``` + +## API + +### bufferFrom(array) + +- `array` <Array> + +Allocates a new `Buffer` using an `array` of octets. + +### bufferFrom(arrayBuffer[, byteOffset[, length]]) + +- `arrayBuffer` <ArrayBuffer> The `.buffer` property of a TypedArray or ArrayBuffer +- `byteOffset` <Integer> Where to start copying from `arrayBuffer`. **Default:** `0` +- `length` <Integer> How many bytes to copy from `arrayBuffer`. **Default:** `arrayBuffer.length - byteOffset` + +When passed a reference to the `.buffer` property of a TypedArray instance, the +newly created `Buffer` will share the same allocated memory as the TypedArray. + +The optional `byteOffset` and `length` arguments specify a memory range within +the `arrayBuffer` that will be shared by the `Buffer`. + +### bufferFrom(buffer) + +- `buffer` <Buffer> An existing `Buffer` to copy data from + +Copies the passed `buffer` data onto a new `Buffer` instance. + +### bufferFrom(string[, encoding]) + +- `string` <String> A string to encode. +- `encoding` <String> The encoding of `string`. **Default:** `'utf8'` + +Creates a new `Buffer` containing the given JavaScript string `string`. If +provided, the `encoding` parameter identifies the character encoding of +`string`. + +## See also + +- [buffer-alloc](https://github.com/LinusU/buffer-alloc) A ponyfill for `Buffer.alloc` +- [buffer-alloc-unsafe](https://github.com/LinusU/buffer-alloc-unsafe) A ponyfill for `Buffer.allocUnsafe` diff --git a/node_modules/cheerio/History.md b/node_modules/cheerio/History.md new file mode 100644 index 0000000000000000000000000000000000000000..c7e38e66a76870ecc8741b553590d8792b697731 --- /dev/null +++ b/node_modules/cheerio/History.md @@ -0,0 +1,576 @@ + +0.22.0 / 2016-08-23 +================== + + * Return undefined in .prop if given an invalid element or tag (#880) + * Merge pull request #884 from cheeriojs/readme-cleanup + * readme updates + * Merge pull request #881 from piamancini/patch-1 + * Added backers and sponsors from OpenCollective + * Use jQuery from the jquery module in benchmarks (#871) + * Document, test, and extend static `$.text` method (#855) + * Fix typo on calling _.extend (#861) + * Update versions (#870) + * Use individual lodash functions (#864) + * Added `.serialize()` support. Fixes #69 (#827) + * Update Readme.md (#857) + * add extension for JSON require call + * remove gittask badge + * Merge pull request #672 from underdogio/dev/checkbox.radio.values.sqwished + * Added default value for checkboxes/radios + +0.20.0 / 2016-02-01 +================== + + * Add coveralls badge, remove link to old report (Felix Böhm) + * Update lodash dependeny to 4.1.0 (leif.hanack) + * Fix PR #726 adding 'appendTo()' and 'prependTo()' (Delgan) + * Added appendTo and prependTo with tests #641 (digihaven) + * Fix #780 by changing options context in '.find()' (Felix Böhm) + * Add an unit test checking the query of child (Delgan) + * fix #667: attr({foo: null}) removes attribute foo, like attr('foo', null) (Ray Waldin) + * Include reference to dedicated "Loading" section (Mike Pennisi) + * Added load method to $ (alanev) + * update css-select to 1.2.0 (Felix Böhm) + * Fixing Grammatical Error (Dan Corman) + * Test against node v0.12 --> v4.2 (Jason Kurian) + * Correct output in example (Felix Böhm) + * Fix npm files filter (Bogdan Chadkin) + * Enable setting data on all elements in selection (Mike Pennisi) + * Reinstate `$.fn.toArray` (Mike Pennisi) + * update css-select to 1.1.0 (Thomas Shafer) + * Complete implementation of `wrap` (Mike Pennisi) + * Correct name of unit test (Mike Pennisi) + * Correct grammar in test titles (Mike Pennisi) + * Normalize whitespace (Mike Pennisi) + * Insert omitted assertion (Mike Pennisi) + * Update invocation of `children` (Mike Pennisi) + * Begin implementation of `wrap` method (Dandlezzz) + * Update Readme.md (Sven Slootweg) + * fix document's mistake in Readme.md (exoticknight) + * Add tests for setting text and html as non-strings (Ryc O'Chet) + * Fix for passing non-string values to .html or .text (Ryc O'Chet) + * use a selector to filter form elements (fb55) + * fix README.md typo (Yutian Li) + * README: fix spelling (Chris Rebert) + * Added support for options without a `value` attribute. Fixes #633 (Todd Wolfson) + * responding to pull request feedback - remove item() method and related tests (Ray Waldin) + * add length property and item method to object returned by prop('style'), plus tests (Ray Waldin) + * Added .prop method to readme (Artem Burtsev) + * Added .prop method (Artem Burtsev) + * Added Gitter badge (The Gitter Badger) + +0.19.0 / 2015-03-21 +================== + + * fixed allignment (fb55) + * added test case for malformed json in data attributes (fb55) + * fix: handle some extreme cases like `data-custom="{{templatevar}}"`. There is possibility error while parsing json . (Harish.K) + * Add missing optional selector doc for {prev,next}{All,Until} (Jérémie Astori) + * update to dom-serializer@0.1.0 (Felix Böhm) + * Document `Cheerio#serialzeArray` (Mike Pennisi) + * Fixed up `serializeArray()` and added multiple support (Todd Wolfson) + * Implement serializeArray() (Jarno Leppänen) + * recognize options in $.xml() (fb55) + * lib/static.js: text(): rm errant space before ++ (Chris Rebert) + * Do not expose internal `children` array (Mike Pennisi) + * Change lodash dependencies to ^3.1.0 (Samy Pessé) + * Update lodash@3.1.0 (Samy Pessé) + * Updates Readme.md: .not(function (index, elem)) (Patrick Ward) + * update to css-select@1.0.0 (fb55) + * Allow failures in Node.js v0.11 (Mike Pennisi) + * Added: Gittask badge (Matthew Mueller) + * Isolate prototypes of functions created via `load` (Mike Pennisi) + * Updates Readme.md: adds JS syntax highlighting (frankcash) + * #608 -- Add support for insertBefore/insertAfter syntax. Supports target types of: $, [$], selector (both single and multiple results) (Ben Cochran) + * Clone input nodes when inserting over a set (Mike Pennisi) + * Move unit test files (Mike Pennisi) + * remove unnecessarily tricky code (David Chambers) + * pass options to $.html in toString (fb55) + * add license info to package.json (Chris Rebert) + * xyz@~0.5.0 (David Chambers) + * Remove unofficial signature of `children` (Mike Pennisi) + * Fix bug in `css` method (Mike Pennisi) + * Correct bug in implementation of `Cheerio#val` (Mike Pennisi) + +0.18.0 / 2014-11-06 +================== + + * bump htmlparser2 dependency to ~3.8.1 (Chris Rebert) + * Correct unit test titles (Mike Pennisi) + * Correct behavior of `after` and `before` (Mike Pennisi) + * implement jQuery's .has() (Chris Rebert) + * Update repository url (haqii) + * attr() should return undefined or name for booleans (Raoul Millais) + * Update Readme.md (Ryan Breen) + * Implement `Cheerio#not` (Mike Pennisi) + * Clone nodes according to original parsing options (Mike Pennisi) + * fix lint error (David Chambers) + * Add explicit tests for DOM level 1 API (Mike Pennisi) + * Expose DOM level 1 API for Node-like objects (Mike Pennisi) + * Correct error in documentation (Mike Pennisi) + * Return a fully-qualified Function from `$.load` (Mike Pennisi) + * Update tests to avoid duck typing (Mike Pennisi) + * Alter "loaded" functions to produce true instances (Mike Pennisi) + * Organize tests for `cheerio.load` (Mike Pennisi) + * Complete `$.prototype.find` (Mike Pennisi) + * Use JSHint's `extends` option (Mike Pennisi) + * Remove aliases for exported methods (Mike Pennisi) + * Disallow unused variables (Mike Pennisi) + * Remove unused internal variables (Mike Pennisi) + * Remove unused variables from unit tests (Mike Pennisi) + * Remove unused API method references (Mike Pennisi) + * Move tests for `contains` method (Mike Pennisi) + * xyz@0.4.0 (David Chambers) + * Created a wiki for companies using cheerio in production (Matthew Mueller) + * Implement `$.prototype.index` (Mike Pennisi) + * Implement `$.prototype.addBack` (Mike Pennisi) + * Added double quotes to radio attribute name to account for characters such as brackets (akant10) + * Update History.md (Gabriel Falkenberg) + * add 0.17.0 changelog (David Chambers) + * exit prepublish script if tag not found (David Chambers) + * alphabetize devDependencies (fb55) + * ignore coverage dir (fb55) + * submit coverage to coveralls (fb55) + * replace jscoverage with istanbul (fb55) + +0.17.0 / 2014-06-10 +================== + + * Fix bug in internal `uniqueSplice` function (Mike Pennisi) + * accept buffer argument to cheerio.load (David Chambers) + * Respect options on the element level (Alex Indigo) + * Change state definition to more readable (Artem Burtsev) + * added test (0xBADC0FFEE) + * add class only if doesn't exist (Artem Burtsev) + * Made it less insane. (Alex Indigo) + * Implement `Cheerio#add` (Mike Pennisi) + * Use "loaded" instance of Cheerio in unit tests (Mike Pennisi) + * Be more strict with object check. (Alex Indigo) + * Added options argument to .html() static method. (Alex Indigo) + * Fixed encoding mishaps. Adjusted tests. (Alex Indigo) + * use dom-serializer module (fb55) + * don't test on 0.8, don't ignore 0.11 (Felix Böhm) + * parse: rm unused variables (coderaiser) + * cheerio: rm unused variable (coderaiser) + * Fixed test (Avi Kohn) + * Added test (Avi Kohn) + * Changed == to === (Avi Kohn) + * Fixed a bug in removing type="hidden" attr (Avi Kohn) + * sorted (Alexey Raspopov) + * add `muted` attr to booleanAttributes (Alexey Raspopov) + * fixed context of `this` in .html (Felix Böhm) + * append new elements for each element in selection (fb55) + +0.16.0 / 2014-05-08 +================== + + * fix `make bench` (David Chambers) + * makefile: add release-* targets (David Chambers) + * alphabetize dependencies (David Chambers) + * Rewrite `data` internals with caching behavior (Mike Pennisi) + * Fence .val example as js (Kevin Sawicki) + * Fixed typos. Deleted trailing whitespace from test/render.js (Nattaphoom Ch) + * Fix manipulation APIs with removed elements (kpdecker) + * Perform manual string parsing for hasClass (kpdecker) + * Fix existing element removal (kpdecker) + * update render tests (Felix Böhm) + * fixed cheerio path (Felix Böhm) + * use `entities.escape` for attribute values (Felix Böhm) + * bump entities version (Felix Böhm) + * remove lowerCaseTags option from readme (Felix Böhm) + * added test case for .html in xmlMode (fb55) + * render xml in `html()` when `xmlMode: true` (fb55) + * use a map for booleanAttributes (fb55) + * update singleTags, use utils.isTag (fb55) + * update travis badge URL (Felix Böhm) + * use typeof instead of _.isString and _.isNumber (fb55) + * use Array.isArray instead of _.isArray (fb55) + * replace _.isFunction with typeof (fb55) + * removed unnecessary error message (fb55) + * decode entities in htmlparser2 (fb55) + * pass options object to CSSselect (fb55) + +0.15.0 / 2014-04-08 +================== + + * Update callbacks to pass element per docs (@kpdecker) + * preserve options (@fb55) + * Use SVG travis badge (@t3chnoboy) + * only use static requires (@fb55) + * Optimize manipulation methods (@kpdecker) + * Optimize add and remove class cases (@kpdecker) + * accept dom of DomHandler to cheerio.load (@nleush) + * added parentsUntil method (@finspin) + * Add performance optimization and bug fix `empty` method (@kpdecker) + +0.14.0 / 2014-04-01 +================== + + * call encodeXML and directly expose decodeHTML (@fb55) + * use latest htmlparser2 and entities versions (@fb55) + * Deprecate `$.fn.toArray` (@jugglinmike) + * Implement `$.fn.get` (@jugglinmike) + * .replaceWith now replaces all selected elements. (@xavi-) + * Correct arguments for 'replaceWith' callback (@jugglinmike) + * switch to lodash (@fb55) + * update to entities@0.5.0 (@fb55) + * Fix attr when $ collection contains text modules (@kpdecker) + * Update to latest version of expect.js (@jugglinmike) + * Remove nodes from their previous structures (@jugglinmike) + * Update render.js (@stevenvachon) + * CDATA test (@stevenvachon) + * only ever one child index for cdata (@stevenvachon) + * don't loop through cdata children array (@stevenvachon) + * proper rendering of CDATA (@stevenvachon) + * Add cheerio-only bench option (@kpdecker) + * Avoid delete operations (@kpdecker) + * Add independent html benchmark (@kpdecker) + * Cache tag check in render (@kpdecker) + * Simplify attribute rendering step (@kpdecker) + * Add html rendering bench case (@kpdecker) + * Remove unnecessary check from removeAttr (@kpdecker) + * Remove unnecessary encoding step for attrs (@kpdecker) + * Add test for removeAttr+attr on boolean attributes (@kpdecker) + * Add single element benchmark case (@kpdecker) + * Optimize filter with selector (@kpdecker) + * Fix passing context as dom node (@alfred-nsh) + * Fix bug in `nextUntil` (@jugglinmike) + * Fix bug in `nextAll` (@jugglinmike) + * Implement `selector` argument of `next` method (@jugglinmike) + * Fix bug in `prevUntil` (@jugglinmike) + * Implement `selector` argument of `prev` method (@jugglinmike) + * Fix bug in `prevAll` (@jugglinmike) + * Fix bug in `siblings` (@jugglinmike) + * Avoid unnecessary indexOf from toggleClass (@kpdecker) + * Use strict equality rather than falsy check in eq (@kpdecker) + * Add benchmark coverage for all $ APIs (@kpdecker) + * Optimize filter Cheerio intermediate creation (@kpdecker) + * Optimize siblings cheerio instance creation (@kpdecker) + * Optimize identity cases for first/last/eq (@kpdecker) + * Use domEach for traversal (@kpdecker) + * Inline children lookup in find (@kpdecker) + * Use domEach in data accessor (@kpdecker) + * Avoid cheerio creation in add/remove/toggleClass (@kpdecker) + * Implement getAttr local helper (@kpdecker) + +0.13.1 / 2014-01-07 +================== + + * Fix select with context in Cheerio function (@jugglinmike) + * Remove unecessary DOM maintenance logic (@jugglinmike) + * Deprecate support for node 0.6 + +0.13.0 / 2013-12-30 +================== + + * Remove "root" node (@jugglinmike) + * Fix bug in `prevAll`, `prev`, `nextAll`, `next`, `prevUntil`, `nextUntil` (@jugglinmike) + * Fix `replaceWith` method (@jugglinmike) + * added nextUntil() and prevUntil() (@finspin) + * Remove internal `connect` function (@jugglinmike) + * Rename `Cheerio#make` to document private status (@jugginmike) + * Remove extraneous call to `_.uniq` (@jugglinmike) + * Use CSSselect library directly (@jugglinmike) + * Run CI against Node v0.11 as an allowed failure (@jugginmike) + * Correct bug in `Cheerio#parents` (@jugglinmike) + * Implement `$.fn.end` (@jugginmike) + * Ignore colons inside of url(.*) when parsing css (@Meekohi) + * Introduce rudimentary benchmark suite (@jugglinmike) + * Update HtmlParser2 version (@jugglinmike) + * Correct inconsistency in `$.fn.map` (@jugglinmike) + * fixed traversing tests (@finspin) + * Simplify `make` method (@jugglinmike) + * Avoid shadowing instance methods from arrays (@jugglinmike) + +0.12.4 / 2013-11-12 +================== + + * Coerce JSON values returned by `data` (@jugglinmike) + * issue #284: when rendering HTML, use original data attributes (@Trott) + * Introduce JSHint for automated code linting (@jugglinmike) + * Prevent `find` from returning duplicate elements (@jugglinmike) + * Implement function signature of `replaceWith` (@jugglinmike) + * Implement function signature of `before` (@jugglinmike) + * Implement function signature of `after` (@jugglinmike) + * Implement function signature of `append`/`prepend` (@jugglinmike) + * Extend iteration methods to accept nodes (@jugglinmike) + * Improve `removeClass` (@jugglinmike) + * Complete function signature of `addClass` (@jugglinmike) + * Fix bug in `removeClass` (@jugglinmike) + * Improve contributing.md (@jugglinmike) + * Fix and document .css() (@jugglinmike) + +0.12.3 / 2013-10-04 +=================== + + * Add .toggleClass() function (@cyberthom) + * Add contributing guidelines (@jugglinmike) + * Fix bug in `siblings` (@jugglinmike) + * Correct the implementation `filter` and `is` (@jugglinmike) + * add .data() function (@andi-neck) + * add .css() (@yields) + * Implements contents() (@jlep) + +0.12.2 / 2013-09-04 +================== + + * Correct implementation of `$.fn.text` (@jugglinmike) + * Refactor Cheerio array creation (@jugglinmike) + * Extend manipulation methods to accept Arrays (@jugglinmike) + * support .attr(attributeName, function(index, attr)) (@xiaohwan) + +0.12.1 / 2013-07-30 +================== + + * Correct behavior of `Cheerio#parents` (@jugglinmike) + * Double quotes inside attributes kills HTML (@khoomeister) + * Making next({}) and prev({}) return empty object (@absentTelegraph) + * Implement $.parseHTML (@jugglinmike) + * Correct bug in jQuery.fn.closest (@jugglinmike) + * Correct behavior of $.fn.val on 'option' elements (@jugglinmike) + +0.12.0 / 2013-06-09 +=================== + + * Breaking Change: Changed context from parent to the actual passed one (@swissmanu) + * Fixed: jquery checkbox val behavior (@jhubble) + * Added: output xml with $.xml() (@Maciek416) + * Bumped: htmlparser2 to 3.1.1 + * Fixed: bug in attr(key, val) on empty objects (@farhadi) + * Added: prevAll, nextAll (@lessmind) + * Fixed: Safety check in parents and closest (@zero21xxx) + * Added: .is(sel) (@zero21xxx) + +0.11.0 / 2013-04-22 +================== + +* Added: .closest() (@jeremy-dentel) +* Added: .parents() (@zero21xxx) +* Added: .val() (@rschmukler & @leahciMic) +* Added: Travis support for node 0.10.0 (@jeremy-dentel) +* Fixed: .find() if no selector (@davidchambers) +* Fixed: Propagate syntax errors caused by invalid selectors (@davidchambers) + +0.10.8 / 2013-03-11 +================== + +* Add slice method (SBoudrias) + +0.10.7 / 2013-02-10 +================== + +* Code & doc cleanup (davidchambers) +* Fixed bug in filter (jugglinmike) + +0.10.6 / 2013-01-29 +================== + +* Added `$.contains(...)` (jugglinmike) +* formatting cleanup (davidchambers) +* Bug fix for `.children()` (jugglinmike & davidchambers) +* Remove global `render` bug (wvl) + +0.10.5 / 2012-12-18 +=================== + +* Fixed botched publish from 0.10.4 - changes should now be present + +0.10.4 / 2012-12-16 +================== + +* $.find should query descendants only (@jugglinmike) +* Tighter underscore dependency + +0.10.3 / 2012-11-18 +=================== + +* fixed outer html bug +* Updated documentation for $(...).html() and $.html() + +0.10.2 / 2012-11-17 +=================== + +* Added a toString() method (@bensheldon) +* use `_.each` and `_.map` to simplify cheerio namesakes (@davidchambers) +* Added filter() with tests and updated readme (@bensheldon & @davidchambers) +* Added spaces between attributes rewritten by removeClass (@jos3000) +* updated docs to remove reference to size method (@ironchefpython) +* removed HTML tidy/pretty print from cheerio + +0.10.1 / 2012-10-04 +=================== + +* Fixed regression, filtering with a context (#106) + +0.10.0 / 2012-09-24 +=================== + +* Greatly simplified and reorganized the library, reducing the loc by 30% +* Now supports mocha's test-coverage +* Deprecated self-closing tags (HTML5 doesn't require them) +* Fixed error thrown in removeClass(...) @robashton + +0.9.2 / 2012-08-10 +================== + +* added $(...).map(fn) +* manipulation: refactor `makeCheerioArray` +* make .removeClass() remove *all* occurrences (#64) + +0.9.1 / 2012-08-03 +================== + +* fixed bug causing options not to make it to the parser + +0.9.0 / 2012-07-24 +================== + +* Added node 8.x support +* Removed node 4.x support +* Add html(dom) support (@wvl) +* fixed xss vulnerabilities on .attr(), .text(), & .html() (@benatkin, @FB55) +* Rewrote tests into javascript, removing coffeescript dependency (@davidchambers) +* Tons of cleanup (@davidchambers) + +0.8.3 / 2012-06-12 +================== + +* Fixed minor package regression (closes #60) + +0.8.2 / 2012-06-11 +================== + +* Now fails gracefully in cases that involve special chars, which is inline with jQuery (closes #59) +* text() now decode special entities (closes #52) +* updated travis.yml to test node 4.x + +0.8.1 / 2012-06-02 +================== + +* fixed regression where if you created an element, it would update the root +* compatible with node 4.x (again) + +0.8.0 / 2012-05-27 +================== + +* Updated CSS parser to use FB55/CSSselect. Cheerio now supports most CSS3 psuedo selectors thanks to @FB55. +* ignoreWhitespace now on by default again. See #55 for context. +* Changed $(':root') to $.root(), cleaned up $.clone() +* Support for .eq(i) thanks to @alexbardas +* Removed support for node 0.4.x +* Fixed memory leak where package.json was continually loaded +* Tons more tests + +0.7.0 / 2012-04-08 +================== + +* Now testing with node v0.7.7 +* Added travis-ci integration +* Replaced should.js with expect.js. Browser testing to come +* Fixed spacing between attributes and their values +* Added HTML tidy/pretty print +* Exposed node-htmlparser2 parsing options +* Revert .replaceWith(...) to be consistent with jQuery + +0.6.2 / 2012-02-12 +================== + +* Fixed .replaceWith(...) regression + +0.6.1 / 2012-02-12 +================== + +* Added .first(), .last(), and .clone() commands. +* Option to parse using whitespace added to `.load`. +* Many bug fixes to make cheerio more aligned with jQuery. +* Added $(':root') to select the highest level element. + +Many thanks to the contributors that made this release happen: @ironchefpython and @siddMahen + +0.6.0 / 2012-02-07 +================== + +* *Important:* `$(...).html()` now returns inner HTML, which is in line with the jQuery spec +* `$.html()` returns the full HTML string. `$.html([cheerioObject])` will return the outer(selected element's tag) and inner HTML of that object +* Fixed bug that prevented HTML strings with depth (eg. `append('
      ')`) from getting `parent`, `next`, `prev` attributes. +* Halted [htmlparser2](https://github.com/FB55/node-htmlparser) at v2.2.2 until single attributes bug gets fixed. + +0.5.1 / 2012-02-05 +================== + +* Fixed minor regression: $(...).text(fn) would fail + +0.5.1 / 2012-02-05 +================== + +* Fixed regression: HTML pages with comments would fail + +0.5.0 / 2012-02-04 +================== + +* Transitioned from Coffeescript back to Javascript +* Parser now ignores whitespace +* Fixed issue with double slashes on self-enclosing tags +* Added boolean attributes to html rendering + +0.4.2 / 2012-01-16 +================== + +* Multiple selectors support: $('.apple, .orange'). Thanks @siddMahen! +* Update package.json to always use latest cheerio-soupselect +* Fix memory leak in index.js + +0.4.1 / 2011-12-19 +================== +* Minor packaging changes to allow `make test` to work from npm installation + +0.4.0 / 2011-12-19 +================== + +* Rewrote all unit tests as cheerio transitioned from vows -> mocha +* Internally, renderer.render -> render(...), parser.parse -> parse(...) +* Append, prepend, html, before, after all work with only text (no tags) +* Bugfix: Attributes can now be removed from script and style tags +* Added yield as a single tag +* Cheerio now compatible with node >=0.4.7 + +0.3.2 / 2011-12-1 +================= + +* Fixed $(...).text(...) to work with "root" element + +0.3.1 / 2011-11-25 +================== + +* Now relying on cheerio-soupselect instead of node-soupselect +* Removed all lingering htmlparser dependencies +* parser now returns parent "root" element. Root now never needs to be updated when there is multiple roots. This fixes ongoing issues with before(...), after(...) and other manipulation functions +* Added jQuery's $(...).replaceWith(...) + +0.3.0 / 2011-11-19 +================== + +* Now using htmlparser2 for parsing (2x speed increase, cleaner, actively developed) +* Added benchmark directory for future speed tests +* $('...').dom() was funky, so it was removed in favor of $('...').get(). $.dom() still works the same. +* $.root now correctly static across all instances of $ +* Added a screencast + +0.2.2 / 2011-11-9 +================= + +* Traversing will select `", + "expected": [ + { + "type": "tag", + "name": "head", + "attribs": {}, + "children": [ + { + "type": "script", + "name": "script", + "attribs": { + "language": "Javascript" + }, + "children": [ + { + "data": "var foo = \"\"; alert(2 > foo); var baz = 10 << 2; var zip = 10 >> 1; var yap = \"<<>>>><<\";", + "type": "text" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/node_modules/domhandler/test/cases/05-tags_in_comment.json b/node_modules/domhandler/test/cases/05-tags_in_comment.json new file mode 100644 index 0000000000000000000000000000000000000000..2d22d9e1d8f6f49019c280246346346ae6821a11 --- /dev/null +++ b/node_modules/domhandler/test/cases/05-tags_in_comment.json @@ -0,0 +1,18 @@ +{ + "name": "Special char in comment", + "options": {}, + "html": "", + "expected": [ + { + "type": "tag", + "name": "head", + "attribs": {}, + "children": [ + { + "data": " commented out tags Test", + "type": "comment" + } + ] + } + ] +} \ No newline at end of file diff --git a/node_modules/domhandler/test/cases/06-comment_in_script.json b/node_modules/domhandler/test/cases/06-comment_in_script.json new file mode 100644 index 0000000000000000000000000000000000000000..9a21cdabf8b262829273ab0f326a53c6d76d1d92 --- /dev/null +++ b/node_modules/domhandler/test/cases/06-comment_in_script.json @@ -0,0 +1,18 @@ +{ + "name": "Script source in comment", + "options": {}, + "html": "", + "expected": [ + { + "type": "script", + "name": "script", + "attribs": {}, + "children": [ + { + "data": "", + "type": "text" + } + ] + } + ] +} \ No newline at end of file diff --git a/node_modules/domhandler/test/cases/07-unescaped_in_style.json b/node_modules/domhandler/test/cases/07-unescaped_in_style.json new file mode 100644 index 0000000000000000000000000000000000000000..77438fdc1d5b1d2db0e1279f6adc67467426cadc --- /dev/null +++ b/node_modules/domhandler/test/cases/07-unescaped_in_style.json @@ -0,0 +1,20 @@ +{ + "name": "Unescaped chars in style", + "options": {}, + "html": "", + "expected": [ + { + "type": "style", + "name": "style", + "attribs": { + "type": "text/css" + }, + "children": [ + { + "data": "\n body > p\n\t{ font-weight: bold; }", + "type": "text" + } + ] + } + ] +} \ No newline at end of file diff --git a/node_modules/domhandler/test/cases/08-extra_spaces_in_tag.json b/node_modules/domhandler/test/cases/08-extra_spaces_in_tag.json new file mode 100644 index 0000000000000000000000000000000000000000..5c2492e222f138b2aa28237f74555beb0a34a03d --- /dev/null +++ b/node_modules/domhandler/test/cases/08-extra_spaces_in_tag.json @@ -0,0 +1,20 @@ +{ + "name": "Extra spaces in tag", + "options": {}, + "html": "the text", + "expected": [ + { + "type": "tag", + "name": "font", + "attribs": { + "size": "14" + }, + "children": [ + { + "data": "the text", + "type": "text" + } + ] + } + ] +} \ No newline at end of file diff --git a/node_modules/domhandler/test/cases/09-unquoted_attrib.json b/node_modules/domhandler/test/cases/09-unquoted_attrib.json new file mode 100644 index 0000000000000000000000000000000000000000..543cceeed7b5cff975d62399d8dc279d409209f0 --- /dev/null +++ b/node_modules/domhandler/test/cases/09-unquoted_attrib.json @@ -0,0 +1,20 @@ +{ + "name": "Unquoted attributes", + "options": {}, + "html": "the text", + "expected": [ + { + "type": "tag", + "name": "font", + "attribs": { + "size": "14" + }, + "children": [ + { + "data": "the text", + "type": "text" + } + ] + } + ] +} \ No newline at end of file diff --git a/node_modules/domhandler/test/cases/10-singular_attribute.json b/node_modules/domhandler/test/cases/10-singular_attribute.json new file mode 100644 index 0000000000000000000000000000000000000000..544636e49eb7f6213d2f56cdbcfcd6d083178911 --- /dev/null +++ b/node_modules/domhandler/test/cases/10-singular_attribute.json @@ -0,0 +1,15 @@ +{ + "name": "Singular attribute", + "options": {}, + "html": "